From: Yun Xu xuyun@ramaxel.com
Ramaxel inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4ZR0O CVE: NA
------------------------------------
There are some issues of the driver that cannot be fixed now. The driver is not good enough for the LTS quality requirements of openEuler,so remove it.
Signed-off-by: Yun Xu xuyun@ramaxel.com Signed-off-by: Yanling Song songyl@ramaxel.com Reviewed-by: Yun Xu xuyun@ramaxel.com Acked-by: Xie Xiuqi xiexiuqi@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- arch/arm64/configs/openeuler_defconfig | 1 - arch/x86/configs/openeuler_defconfig | 1 - drivers/scsi/Kconfig | 1 - drivers/scsi/Makefile | 1 - drivers/scsi/spfc/Kconfig | 16 - drivers/scsi/spfc/Makefile | 47 - drivers/scsi/spfc/common/unf_common.h | 1753 ------- drivers/scsi/spfc/common/unf_disc.c | 1276 ----- drivers/scsi/spfc/common/unf_disc.h | 51 - drivers/scsi/spfc/common/unf_event.c | 517 -- drivers/scsi/spfc/common/unf_event.h | 83 - drivers/scsi/spfc/common/unf_exchg.c | 2317 --------- drivers/scsi/spfc/common/unf_exchg.h | 436 -- drivers/scsi/spfc/common/unf_exchg_abort.c | 825 --- drivers/scsi/spfc/common/unf_exchg_abort.h | 23 - drivers/scsi/spfc/common/unf_fcstruct.h | 459 -- drivers/scsi/spfc/common/unf_gs.c | 2521 --------- drivers/scsi/spfc/common/unf_gs.h | 58 - drivers/scsi/spfc/common/unf_init.c | 353 -- drivers/scsi/spfc/common/unf_io.c | 1219 ----- drivers/scsi/spfc/common/unf_io.h | 96 - drivers/scsi/spfc/common/unf_io_abnormal.c | 986 ---- drivers/scsi/spfc/common/unf_io_abnormal.h | 19 - drivers/scsi/spfc/common/unf_log.h | 178 - drivers/scsi/spfc/common/unf_lport.c | 1008 ---- drivers/scsi/spfc/common/unf_lport.h | 519 -- drivers/scsi/spfc/common/unf_ls.c | 4883 ------------------ drivers/scsi/spfc/common/unf_ls.h | 61 - drivers/scsi/spfc/common/unf_npiv.c | 1005 ---- drivers/scsi/spfc/common/unf_npiv.h | 47 - drivers/scsi/spfc/common/unf_npiv_portman.c | 360 -- drivers/scsi/spfc/common/unf_npiv_portman.h | 17 - drivers/scsi/spfc/common/unf_portman.c | 2431 --------- drivers/scsi/spfc/common/unf_portman.h | 96 - drivers/scsi/spfc/common/unf_rport.c | 2286 -------- drivers/scsi/spfc/common/unf_rport.h | 301 -- drivers/scsi/spfc/common/unf_scsi.c | 1462 ------ drivers/scsi/spfc/common/unf_scsi_common.h | 570 -- drivers/scsi/spfc/common/unf_service.c | 1430 ----- drivers/scsi/spfc/common/unf_service.h | 66 - drivers/scsi/spfc/common/unf_type.h | 216 - drivers/scsi/spfc/hw/spfc_chipitf.c | 1105 ---- drivers/scsi/spfc/hw/spfc_chipitf.h | 797 --- drivers/scsi/spfc/hw/spfc_cqm_bat_cla.c | 1611 ------ drivers/scsi/spfc/hw/spfc_cqm_bat_cla.h | 215 - drivers/scsi/spfc/hw/spfc_cqm_bitmap_table.c | 885 ---- drivers/scsi/spfc/hw/spfc_cqm_bitmap_table.h | 65 - drivers/scsi/spfc/hw/spfc_cqm_main.c | 987 ---- drivers/scsi/spfc/hw/spfc_cqm_main.h | 411 -- drivers/scsi/spfc/hw/spfc_cqm_object.c | 937 ---- drivers/scsi/spfc/hw/spfc_cqm_object.h | 279 - drivers/scsi/spfc/hw/spfc_hba.c | 1751 ------- drivers/scsi/spfc/hw/spfc_hba.h | 341 -- drivers/scsi/spfc/hw/spfc_hw_wqe.h | 1645 ------ drivers/scsi/spfc/hw/spfc_io.c | 1193 ----- drivers/scsi/spfc/hw/spfc_io.h | 138 - drivers/scsi/spfc/hw/spfc_lld.c | 997 ---- drivers/scsi/spfc/hw/spfc_lld.h | 76 - drivers/scsi/spfc/hw/spfc_module.h | 297 -- drivers/scsi/spfc/hw/spfc_parent_context.h | 269 - drivers/scsi/spfc/hw/spfc_queue.c | 4852 ----------------- drivers/scsi/spfc/hw/spfc_queue.h | 711 --- drivers/scsi/spfc/hw/spfc_service.c | 2170 -------- drivers/scsi/spfc/hw/spfc_service.h | 282 - drivers/scsi/spfc/hw/spfc_utils.c | 102 - drivers/scsi/spfc/hw/spfc_utils.h | 202 - drivers/scsi/spfc/hw/spfc_wqe.c | 646 --- drivers/scsi/spfc/hw/spfc_wqe.h | 239 - drivers/scsi/spfc/sphw_api_cmd.c | 1 - drivers/scsi/spfc/sphw_cmdq.c | 1 - drivers/scsi/spfc/sphw_common.c | 1 - drivers/scsi/spfc/sphw_eqs.c | 1 - drivers/scsi/spfc/sphw_hw_cfg.c | 1 - drivers/scsi/spfc/sphw_hw_comm.c | 1 - drivers/scsi/spfc/sphw_hwdev.c | 1 - drivers/scsi/spfc/sphw_hwif.c | 1 - drivers/scsi/spfc/sphw_mbox.c | 1 - drivers/scsi/spfc/sphw_mgmt.c | 1 - drivers/scsi/spfc/sphw_prof_adap.c | 1 - drivers/scsi/spfc/sphw_wq.c | 1 - 80 files changed, 53210 deletions(-) delete mode 100644 drivers/scsi/spfc/Kconfig delete mode 100644 drivers/scsi/spfc/Makefile delete mode 100644 drivers/scsi/spfc/common/unf_common.h delete mode 100644 drivers/scsi/spfc/common/unf_disc.c delete mode 100644 drivers/scsi/spfc/common/unf_disc.h delete mode 100644 drivers/scsi/spfc/common/unf_event.c delete mode 100644 drivers/scsi/spfc/common/unf_event.h delete mode 100644 drivers/scsi/spfc/common/unf_exchg.c delete mode 100644 drivers/scsi/spfc/common/unf_exchg.h delete mode 100644 drivers/scsi/spfc/common/unf_exchg_abort.c delete mode 100644 drivers/scsi/spfc/common/unf_exchg_abort.h delete mode 100644 drivers/scsi/spfc/common/unf_fcstruct.h delete mode 100644 drivers/scsi/spfc/common/unf_gs.c delete mode 100644 drivers/scsi/spfc/common/unf_gs.h delete mode 100644 drivers/scsi/spfc/common/unf_init.c delete mode 100644 drivers/scsi/spfc/common/unf_io.c delete mode 100644 drivers/scsi/spfc/common/unf_io.h delete mode 100644 drivers/scsi/spfc/common/unf_io_abnormal.c delete mode 100644 drivers/scsi/spfc/common/unf_io_abnormal.h delete mode 100644 drivers/scsi/spfc/common/unf_log.h delete mode 100644 drivers/scsi/spfc/common/unf_lport.c delete mode 100644 drivers/scsi/spfc/common/unf_lport.h delete mode 100644 drivers/scsi/spfc/common/unf_ls.c delete mode 100644 drivers/scsi/spfc/common/unf_ls.h delete mode 100644 drivers/scsi/spfc/common/unf_npiv.c delete mode 100644 drivers/scsi/spfc/common/unf_npiv.h delete mode 100644 drivers/scsi/spfc/common/unf_npiv_portman.c delete mode 100644 drivers/scsi/spfc/common/unf_npiv_portman.h delete mode 100644 drivers/scsi/spfc/common/unf_portman.c delete mode 100644 drivers/scsi/spfc/common/unf_portman.h delete mode 100644 drivers/scsi/spfc/common/unf_rport.c delete mode 100644 drivers/scsi/spfc/common/unf_rport.h delete mode 100644 drivers/scsi/spfc/common/unf_scsi.c delete mode 100644 drivers/scsi/spfc/common/unf_scsi_common.h delete mode 100644 drivers/scsi/spfc/common/unf_service.c delete mode 100644 drivers/scsi/spfc/common/unf_service.h delete mode 100644 drivers/scsi/spfc/common/unf_type.h delete mode 100644 drivers/scsi/spfc/hw/spfc_chipitf.c delete mode 100644 drivers/scsi/spfc/hw/spfc_chipitf.h delete mode 100644 drivers/scsi/spfc/hw/spfc_cqm_bat_cla.c delete mode 100644 drivers/scsi/spfc/hw/spfc_cqm_bat_cla.h delete mode 100644 drivers/scsi/spfc/hw/spfc_cqm_bitmap_table.c delete mode 100644 drivers/scsi/spfc/hw/spfc_cqm_bitmap_table.h delete mode 100644 drivers/scsi/spfc/hw/spfc_cqm_main.c delete mode 100644 drivers/scsi/spfc/hw/spfc_cqm_main.h delete mode 100644 drivers/scsi/spfc/hw/spfc_cqm_object.c delete mode 100644 drivers/scsi/spfc/hw/spfc_cqm_object.h delete mode 100644 drivers/scsi/spfc/hw/spfc_hba.c delete mode 100644 drivers/scsi/spfc/hw/spfc_hba.h delete mode 100644 drivers/scsi/spfc/hw/spfc_hw_wqe.h delete mode 100644 drivers/scsi/spfc/hw/spfc_io.c delete mode 100644 drivers/scsi/spfc/hw/spfc_io.h delete mode 100644 drivers/scsi/spfc/hw/spfc_lld.c delete mode 100644 drivers/scsi/spfc/hw/spfc_lld.h delete mode 100644 drivers/scsi/spfc/hw/spfc_module.h delete mode 100644 drivers/scsi/spfc/hw/spfc_parent_context.h delete mode 100644 drivers/scsi/spfc/hw/spfc_queue.c delete mode 100644 drivers/scsi/spfc/hw/spfc_queue.h delete mode 100644 drivers/scsi/spfc/hw/spfc_service.c delete mode 100644 drivers/scsi/spfc/hw/spfc_service.h delete mode 100644 drivers/scsi/spfc/hw/spfc_utils.c delete mode 100644 drivers/scsi/spfc/hw/spfc_utils.h delete mode 100644 drivers/scsi/spfc/hw/spfc_wqe.c delete mode 100644 drivers/scsi/spfc/hw/spfc_wqe.h delete mode 120000 drivers/scsi/spfc/sphw_api_cmd.c delete mode 120000 drivers/scsi/spfc/sphw_cmdq.c delete mode 120000 drivers/scsi/spfc/sphw_common.c delete mode 120000 drivers/scsi/spfc/sphw_eqs.c delete mode 120000 drivers/scsi/spfc/sphw_hw_cfg.c delete mode 120000 drivers/scsi/spfc/sphw_hw_comm.c delete mode 120000 drivers/scsi/spfc/sphw_hwdev.c delete mode 120000 drivers/scsi/spfc/sphw_hwif.c delete mode 120000 drivers/scsi/spfc/sphw_mbox.c delete mode 120000 drivers/scsi/spfc/sphw_mgmt.c delete mode 120000 drivers/scsi/spfc/sphw_prof_adap.c delete mode 120000 drivers/scsi/spfc/sphw_wq.c
diff --git a/arch/arm64/configs/openeuler_defconfig b/arch/arm64/configs/openeuler_defconfig index 401ab0f99631..1fd250cc103c 100644 --- a/arch/arm64/configs/openeuler_defconfig +++ b/arch/arm64/configs/openeuler_defconfig @@ -2403,7 +2403,6 @@ CONFIG_SCSI_QLA_FC=m CONFIG_SCSI_QLA_ISCSI=m CONFIG_QEDI=m CONFIG_QEDF=m -CONFIG_SPFC=m CONFIG_SCSI_HUAWEI_FC=m CONFIG_SCSI_FC_HIFC=m CONFIG_SCSI_LPFC=m diff --git a/arch/x86/configs/openeuler_defconfig b/arch/x86/configs/openeuler_defconfig index 64afe7021c45..cd9aaba18fa4 100644 --- a/arch/x86/configs/openeuler_defconfig +++ b/arch/x86/configs/openeuler_defconfig @@ -2367,7 +2367,6 @@ CONFIG_SCSI_QLA_FC=m CONFIG_SCSI_QLA_ISCSI=m CONFIG_QEDI=m CONFIG_QEDF=m -CONFIG_SPFC=m CONFIG_SCSI_HUAWEI_FC=m CONFIG_SCSI_FC_HIFC=m CONFIG_SCSI_LPFC=m diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 170d59df48d1..0fbe4edeccd0 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -1151,7 +1151,6 @@ source "drivers/scsi/qla2xxx/Kconfig" source "drivers/scsi/qla4xxx/Kconfig" source "drivers/scsi/qedi/Kconfig" source "drivers/scsi/qedf/Kconfig" -source "drivers/scsi/spfc/Kconfig" source "drivers/scsi/huawei/Kconfig"
config SCSI_LPFC diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 299d3318fac8..78a3c832394c 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -85,7 +85,6 @@ obj-$(CONFIG_PCMCIA_QLOGIC) += qlogicfas408.o obj-$(CONFIG_SCSI_QLOGIC_1280) += qla1280.o obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx/ obj-$(CONFIG_SCSI_QLA_ISCSI) += libiscsi.o qla4xxx/ -obj-$(CONFIG_SPFC) += spfc/ obj-$(CONFIG_SCSI_LPFC) += lpfc/ obj-$(CONFIG_SCSI_HUAWEI_FC) += huawei/ obj-$(CONFIG_SCSI_BFA_FC) += bfa/ diff --git a/drivers/scsi/spfc/Kconfig b/drivers/scsi/spfc/Kconfig deleted file mode 100644 index 9d4566d90809..000000000000 --- a/drivers/scsi/spfc/Kconfig +++ /dev/null @@ -1,16 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -# -# Ramaxel SPFC driver configuration -# - -config SPFC - tristate "Ramaxel Fabric Channel Host Adapter Support" - default m - depends on PCI && SCSI - depends on SCSI_FC_ATTRS - depends on ARM64 || X86_64 - help - This driver supports Ramaxel Fabric Channel PCIe host adapter. - To compile this driver as part of the kernel, choose Y here. - If unsure, choose N. - The default is M. diff --git a/drivers/scsi/spfc/Makefile b/drivers/scsi/spfc/Makefile deleted file mode 100644 index 849b730ac733..000000000000 --- a/drivers/scsi/spfc/Makefile +++ /dev/null @@ -1,47 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -obj-$(CONFIG_SPFC) += spfc.o - -subdir-ccflags-y += -I$(srctree)/$(src)/../../net/ethernet/ramaxel/spnic/hw -subdir-ccflags-y += -I$(srctree)/$(src)/hw -subdir-ccflags-y += -I$(srctree)/$(src)/common - -spfc-objs := common/unf_init.o \ - common/unf_event.o \ - common/unf_exchg.o \ - common/unf_exchg_abort.o \ - common/unf_io.o \ - common/unf_io_abnormal.o \ - common/unf_lport.o \ - common/unf_npiv.o \ - common/unf_npiv_portman.o \ - common/unf_disc.o \ - common/unf_rport.o \ - common/unf_service.o \ - common/unf_ls.o \ - common/unf_gs.o \ - common/unf_portman.o \ - common/unf_scsi.o \ - hw/spfc_utils.o \ - hw/spfc_lld.o \ - hw/spfc_io.o \ - hw/spfc_wqe.o \ - hw/spfc_service.o \ - hw/spfc_chipitf.o \ - hw/spfc_queue.o \ - hw/spfc_hba.o \ - hw/spfc_cqm_bat_cla.o \ - hw/spfc_cqm_bitmap_table.o \ - hw/spfc_cqm_main.o \ - hw/spfc_cqm_object.o \ - sphw_hwdev.o \ - sphw_hw_cfg.o \ - sphw_hw_comm.o \ - sphw_prof_adap.o \ - sphw_common.o \ - sphw_hwif.o \ - sphw_wq.o \ - sphw_cmdq.o \ - sphw_eqs.o \ - sphw_mbox.o \ - sphw_mgmt.o \ - sphw_api_cmd.o diff --git a/drivers/scsi/spfc/common/unf_common.h b/drivers/scsi/spfc/common/unf_common.h deleted file mode 100644 index 9613649308bf..000000000000 --- a/drivers/scsi/spfc/common/unf_common.h +++ /dev/null @@ -1,1753 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef UNF_COMMON_H -#define UNF_COMMON_H - -#include "unf_type.h" -#include "unf_fcstruct.h" - -/* version num */ -#define SPFC_DRV_VERSION "B101" -#define SPFC_DRV_DESC "Ramaxel Memory Technology Fibre Channel Driver" - -#define UNF_MAX_SECTORS 0xffff -#define UNF_PKG_FREE_OXID 0x0 -#define UNF_PKG_FREE_RXID 0x1 - -#define UNF_SPFC_MAXRPORT_NUM (2048) -#define SPFC_DEFAULT_RPORT_INDEX (UNF_SPFC_MAXRPORT_NUM - 1) - -/* session use sq num */ -#define UNF_SQ_NUM_PER_SESSION 3 - -extern atomic_t fc_mem_ref; -extern u32 unf_dgb_level; -extern u32 spfc_dif_type; -extern u32 spfc_dif_enable; -extern u8 spfc_guard; -extern int link_lose_tmo; - -/* 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) - -#define UNF_BITS_PER_BYTE 8 - -#define UNF_NOTIFY_UP_CLEAN_FLASH 2 - -/* Echo macro define */ -#define ECHO_MG_VERSION_LOCAL 1 -#define ECHO_MG_VERSION_REMOTE 2 - -#define SPFC_WIN_NPIV_NUM 32 - -#define UNF_GET_NAME_HIGH_WORD(name) (((name) >> 32) & 0xffffffff) -#define UNF_GET_NAME_LOW_WORD(name) ((name) & 0xffffffff) - -#define UNF_FIRST_LPORT_ID_MASK 0xffffff00 -#define UNF_PORT_ID_MASK 0x000000ff -#define UNF_FIRST_LPORT_ID 0x00000000 -#define UNF_SECOND_LPORT_ID 0x00000001 -#define UNF_EIGHTH_LPORT_ID 0x00000007 -#define SPFC_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 UNF_GET_SLOT_ID_BY_PORTID(port_id) (((port_id) & 0x001f00) >> 8) -#define UNF_GET_FUNC_ID_BY_PORTID(port_id) ((port_id) & 0x0000ff) -#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 - -enum unf_rport_qos_level { - UNF_QOS_LEVEL_DEFAULT = 0, - UNF_QOS_LEVEL_MIDDLE, - UNF_QOS_LEVEL_HIGH, - UNF_QOS_LEVEL_BUTT -}; - -struct buff_list { - u8 *vaddr; - dma_addr_t paddr; -}; - -struct buf_describe { - struct buff_list *buflist; - u32 buf_size; - u32 buf_num; -}; - -#define IO_STATICS -struct unf_port_info { - u32 local_nport_id; - u32 nport_id; - u32 rport_index; - u64 port_name; - enum unf_rport_qos_level qos_level; - u8 cs_ctrl; - u8 rsvd0[3]; - u32 sqn_base; -}; - -struct unf_cfg_item { - char *puc_name; - u32 min_value; - u32 default_value; - u32 max_value; -}; - -struct unf_port_param { - u32 ra_tov; - u32 ed_tov; -}; - -/* get wwpn adn wwnn */ -struct unf_get_chip_info_argout { - u8 board_type; - u64 wwpn; - u64 wwnn; - u64 sys_mac; -}; - -/* get sfp info: present and speed */ -struct unf_get_port_info_argout { - u8 sfp_speed; - u8 present; - u8 rsvd[2]; -}; - -/* SFF-8436(QSFP+) Rev 4.7 */ -struct unf_sfp_plus_field_a0 { - u8 identifier; - /* offset 1~2 */ - struct { - u8 reserved; - u8 status; - } status_indicator; - /* offset 3~21 */ - struct { - u8 rx_tx_los; - u8 tx_fault; - u8 all_resv; - - u8 ini_complete : 1; - u8 bit_resv : 3; - u8 temp_low_warn : 1; - u8 temp_high_warn : 1; - u8 temp_low_alarm : 1; - u8 temp_high_alarm : 1; - - u8 resv : 4; - u8 vcc_low_warn : 1; - u8 vcc_high_warn : 1; - u8 vcc_low_alarm : 1; - u8 vcc_high_alarm : 1; - - u8 resv8; - u8 rx_pow[2]; - u8 tx_bias[2]; - u8 reserved[6]; - u8 vendor_specifics[3]; - } interrupt_flag; - /* offset 22~33 */ - struct { - u8 temp[2]; - u8 reserved[2]; - u8 supply_vol[2]; - u8 reserveds[2]; - u8 vendor_specific[4]; - } module_monitors; - /* offset 34~81 */ - struct { - u8 rx_pow[8]; - u8 tx_bias[8]; - u8 reserved[16]; - u8 vendor_specific[16]; - } channel_monitor_val; - - /* offset 82~85 */ - u8 reserved[4]; - - /* offset 86~97 */ - struct { - /* 86~88 */ - u8 tx_disable; - u8 rx_rate_select; - u8 tx_rate_select; - - /* 89~92 */ - u8 rx4_app_select; - u8 rx3_app_select; - u8 rx2_app_select; - u8 rx1_app_select; - /* 93 */ - u8 power_override : 1; - u8 power_set : 1; - u8 reserved : 6; - - /* 94~97 */ - u8 tx4_app_select; - u8 tx3_app_select; - u8 tx2_app_select; - u8 tx1_app_select; - /* 98~99 */ - u8 reserved2[2]; - } control; - /* 100~106 */ - struct { - /* 100 */ - u8 m_rx1_los : 1; - u8 m_rx2_los : 1; - u8 m_rx3_los : 1; - u8 m_rx4_los : 1; - u8 m_tx1_los : 1; - u8 m_tx2_los : 1; - u8 m_tx3_los : 1; - u8 m_tx4_los : 1; - /* 101 */ - u8 m_tx1_fault : 1; - u8 m_tx2_fault : 1; - u8 m_tx3_fault : 1; - u8 m_tx4_fault : 1; - u8 reserved : 4; - /* 102 */ - u8 reserved1; - /* 103 */ - u8 mini_cmp_flag : 1; - u8 rsv : 3; - u8 m_temp_low_warn : 1; - u8 m_temp_high_warn : 1; - u8 m_temp_low_alarm : 1; - u8 m_temp_high_alarm : 1; - /* 104 */ - u8 rsv1 : 4; - u8 m_vcc_low_warn : 1; - u8 m_vcc_high_warn : 1; - u8 m_vcc_low_alarm : 1; - u8 m_vcc_high_alarm : 1; - /* 105~106 */ - u8 vendor_specific[2]; - } module_channel_mask_bit; - /* 107~118 */ - u8 resv[12]; - /* 119~126 */ - u8 password_reserved[8]; - /* 127 */ - u8 page_select; -}; - -/* page 00 */ -struct unf_sfp_plus_field_00 { - /* 128~191 */ - struct { - u8 id; - u8 id_ext; - u8 connector; - u8 speci_com[6]; - u8 mode; - u8 speed; - u8 encoding; - u8 br_nominal; - u8 ext_rate_select_com; - u8 length_smf; - u8 length_om3; - u8 length_om2; - u8 length_om1; - u8 length_copper; - u8 device_tech; - u8 vendor_name[16]; - u8 ex_module; - u8 vendor_oui[3]; - u8 vendor_pn[16]; - u8 vendor_rev[2]; - /* Wave length or Copper cable Attenuation*/ - u8 wave_or_copper_attenuation[2]; - u8 wave_length_toler[2]; /* Wavelength tolerance */ - u8 max_temp; - u8 cc_base; - } base_id_fields; - /* 192~223 */ - struct { - u8 options[4]; - u8 vendor_sn[16]; - u8 date_code[8]; - u8 diagn_monit_type; - u8 enhance_opt; - u8 reserved; - u8 ccext; - } ext_id_fields; - /* 224~255 */ - u8 vendor_spec_eeprom[32]; -}; - -/* page 01 */ -struct unf_sfp_plus_field_01 { - u8 optional01[128]; -}; - -/* page 02 */ -struct unf_sfp_plus_field_02 { - u8 optional02[128]; -}; - -/* page 03 */ -struct unf_sfp_plus_field_03 { - u8 temp_high_alarm[2]; - u8 temp_low_alarm[2]; - u8 temp_high_warn[2]; - u8 temp_low_warn[2]; - - u8 reserved1[8]; - - u8 vcc_high_alarm[2]; - u8 vcc_low_alarm[2]; - u8 vcc_high_warn[2]; - u8 vcc_low_warn[2]; - - u8 reserved2[8]; - u8 vendor_specific1[16]; - - u8 pow_high_alarm[2]; - u8 pow_low_alarm[2]; - u8 pow_high_warn[2]; - u8 pow_low_warn[2]; - - u8 bias_high_alarm[2]; - u8 bias_low_alarm[2]; - u8 bias_high_warn[2]; - u8 bias_low_warn[2]; - - u8 tx_power_high_alarm[2]; - u8 tx_power_low_alarm[2]; - u8 reserved3[4]; - - u8 reserved4[8]; - - u8 vendor_specific2[16]; - u8 reserved5[2]; - u8 vendor_specific3[12]; - u8 rx_ampl[2]; - u8 rx_tx_sq_disable; - u8 rx_output_disable; - u8 chan_monit_mask[12]; - u8 reserved6[2]; -}; - -struct unf_sfp_plus_info { - struct unf_sfp_plus_field_a0 sfp_plus_info_a0; - struct unf_sfp_plus_field_00 sfp_plus_info_00; - struct unf_sfp_plus_field_01 sfp_plus_info_01; - struct unf_sfp_plus_field_02 sfp_plus_info_02; - struct unf_sfp_plus_field_03 sfp_plus_info_03; -}; - -struct unf_sfp_data_field_a0 { - /* Offset 0~63 */ - struct { - u8 id; - u8 id_ext; - u8 connector; - u8 transceiver[8]; - u8 encoding; - u8 br_nominal; /* Nominal signalling rate, units of 100MBd. */ - u8 rate_identifier; /* Type of rate select functionality */ - /* Link length supported for single mode fiber, units of km */ - u8 length_smk_km; - /* Link length supported for single mode fiber, - *units of 100 m - */ - u8 length_smf; - /* Link length supported for 50 um OM2 fiber,units of 10 m */ - u8 length_smf_om2; - /* Link length supported for 62.5 um OM1 fiber, units of 10 m */ - u8 length_smf_om1; - /*Link length supported for copper/direct attach cable, - *units of m - */ - u8 length_cable; - /* Link length supported for 50 um OM3 fiber, units of 10m */ - u8 length_om3; - u8 vendor_name[16]; /* ASCII */ - /* Code for electronic or optical compatibility*/ - u8 transceiver2; - u8 vendor_oui[3]; /* SFP vendor IEEE company ID */ - u8 vendor_pn[16]; /* Part number provided by SFP vendor (ASCII) - */ - /* Revision level for part number provided by vendor (ASCII) */ - u8 vendor_rev[4]; - /* Laser wavelength (Passive/Active Cable - *Specification Compliance) - */ - u8 wave_length[2]; - u8 unallocated; - /* Check code for Base ID Fields (addresses 0 to 62)*/ - u8 cc_base; - } base_id_fields; - - /* Offset 64~95 */ - struct { - u8 options[2]; - u8 br_max; - u8 br_min; - u8 vendor_sn[16]; - u8 date_code[8]; - u8 diag_monitoring_type; - u8 enhanced_options; - u8 sff8472_compliance; - u8 cc_ext; - } ext_id_fields; - - /* Offset 96~255 */ - struct { - u8 vendor_spec_eeprom[32]; - u8 rsvd[128]; - } vendor_spec_id_fields; -}; - -struct unf_sfp_data_field_a2 { - /* Offset 0~119 */ - struct { - /* 0~39 */ - struct { - u8 temp_alarm_high[2]; - u8 temp_alarm_low[2]; - u8 temp_warning_high[2]; - u8 temp_warning_low[2]; - - u8 vcc_alarm_high[2]; - u8 vcc_alarm_low[2]; - u8 vcc_warning_high[2]; - u8 vcc_warning_low[2]; - - u8 bias_alarm_high[2]; - u8 bias_alarm_low[2]; - u8 bias_warning_high[2]; - u8 bias_warning_low[2]; - - u8 tx_alarm_high[2]; - u8 tx_alarm_low[2]; - u8 tx_warning_high[2]; - u8 tx_warning_low[2]; - - u8 rx_alarm_high[2]; - u8 rx_alarm_low[2]; - u8 rx_warning_high[2]; - u8 rx_warning_low[2]; - } alarm_warn_th; - - u8 unallocated0[16]; - u8 ext_cal_constants[36]; - u8 unallocated1[3]; - u8 cc_dmi; - - /* 96~105 */ - struct { - u8 temp[2]; - u8 vcc[2]; - u8 tx_bias[2]; - u8 tx_power[2]; - u8 rx_power[2]; - } diag; - - u8 unallocated2[4]; - - struct { - u8 data_rdy_bar_state : 1; - u8 rx_los : 1; - u8 tx_fault_state : 1; - u8 soft_rate_select_state : 1; - u8 rate_select_state : 1; - u8 rs_state : 1; - u8 soft_tx_disable_select : 1; - u8 tx_disable_state : 1; - } status_ctrl; - u8 rsvd; - - /* 112~113 */ - struct { - /* 112 */ - u8 tx_alarm_low : 1; - u8 tx_alarm_high : 1; - u8 tx_bias_alarm_low : 1; - u8 tx_bias_alarm_high : 1; - u8 vcc_alarm_low : 1; - u8 vcc_alarm_high : 1; - u8 temp_alarm_low : 1; - u8 temp_alarm_high : 1; - - /* 113 */ - u8 rsvd : 6; - u8 rx_alarm_low : 1; - u8 rx_alarm_high : 1; - } alarm; - - u8 unallocated3[2]; - - /* 116~117 */ - struct { - /* 116 */ - u8 tx_warn_lo : 1; - u8 tx_warn_hi : 1; - u8 bias_warn_lo : 1; - u8 bias_warn_hi : 1; - u8 vcc_warn_lo : 1; - u8 vcc_warn_hi : 1; - u8 temp_warn_lo : 1; - u8 temp_warn_hi : 1; - - /* 117 */ - u8 rsvd : 6; - u8 rx_warn_lo : 1; - u8 rx_warn_hi : 1; - } warning; - - u8 ext_status_and_ctrl[2]; - } diag; - - /* Offset 120~255 */ - struct { - u8 vendor_spec[8]; - u8 user_eeprom[120]; - u8 vendor_ctrl[8]; - } general_use_fields; -}; - -struct unf_sfp_info { - struct unf_sfp_data_field_a0 sfp_info_a0; - struct unf_sfp_data_field_a2 sfp_info_a2; -}; - -struct unf_sfp_err_rome_info { - struct unf_sfp_info sfp_info; - struct unf_sfp_plus_info sfp_plus_info; -}; - -struct unf_err_code { - u32 loss_of_signal_count; - u32 bad_rx_char_count; - u32 loss_of_sync_count; - u32 link_fail_count; - u32 rx_eof_a_count; - u32 dis_frame_count; - u32 bad_crc_count; - u32 proto_error_count; -}; - -/* config file */ -enum unf_port_mode { - UNF_PORT_MODE_UNKNOWN = 0x00, - UNF_PORT_MODE_TGT = 0x10, - UNF_PORT_MODE_INI = 0x20, - UNF_PORT_MODE_BOTH = 0x30 -}; - -enum unf_port_upgrade { - 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(u8 *buffer, u32 size) -{ - u32 *buf = NULL; - u32 word_sum = 0; - u32 index = 0; - - if (!buffer) - return; - - buf = (u32 *)buffer; - - /* byte to word */ - if (size % UNF_BYTES_OF_DWORD == 0) - word_sum = size / UNF_BYTES_OF_DWORD; - else - return; - - /* word to byte */ - while (index < word_sum) { - *buf = be32_to_cpu(*buf); - buf++; - index++; - } -} - -static inline void __attribute__((unused)) unf_cpu_to_big_end(void *buffer, u32 size) -{ -#define DWORD_BIT 32 -#define BYTE_BIT 8 - u32 *buf = NULL; - u32 word_sum = 0; - u32 index = 0; - u32 tmp = 0; - - if (!buffer) - return; - - buf = (u32 *)buffer; - - /* byte to dword */ - word_sum = size / UNF_BYTES_OF_DWORD; - - /* dword to byte */ - while (index < word_sum) { - *buf = cpu_to_be32(*buf); - buf++; - index++; - } - - if (size % UNF_BYTES_OF_DWORD) { - tmp = cpu_to_be32(*buf); - tmp = - tmp >> (DWORD_BIT - (size % UNF_BYTES_OF_DWORD) * BYTE_BIT); - memcpy(buf, &tmp, (size % UNF_BYTES_OF_DWORD)); - } -} - -#define UNF_TOP_AUTO_MASK 0x0f -#define UNF_TOP_UNKNOWN 0xff -#define SPFC_TOP_AUTO 0x0 - -#define UNF_NORMAL_MODE 0 -#define UNF_SET_NOMAL_MODE(mode) ((mode) = UNF_NORMAL_MODE) - -/* - * * SCSI status - */ -#define SCSI_GOOD 0x00 -#define SCSI_CHECK_CONDITION 0x02 -#define SCSI_CONDITION_MET 0x04 -#define SCSI_BUSY 0x08 -#define SCSI_INTERMEDIATE 0x10 -#define SCSI_INTERMEDIATE_COND_MET 0x14 -#define SCSI_RESERVATION_CONFLICT 0x18 -#define SCSI_TASK_SET_FULL 0x28 -#define SCSI_ACA_ACTIVE 0x30 -#define SCSI_TASK_ABORTED 0x40 - -enum unf_act_topo { - 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_INVALID_LOOP_ADDR 0xff - -#define UNF_LOOP_ROLE_MASTER_OR_SLAVE 0x0 -#define UNF_LOOP_ROLE_ONLY_SLAVE 0x1 - -#define UNF_TOU16_CHECK(dest, src, over_action) \ - do { \ - if (unlikely(0xFFFF < (src))) { \ - FC_DRV_PRINT(UNF_LOG_REG_ATT, \ - UNF_ERR, "ToU16 error, src 0x%x ", \ - (src)); \ - over_action; \ - } \ - ((dest) = (u16)(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_OP_DEBUG_DUMP 0x0001 -#define UNF_OP_FCPORT_INFO 0x0002 -#define UNF_OP_FCPORT_LINK_CMD_TEST 0x0003 -#define UNF_OP_TEST_MBX 0x0004 - -/* 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_RRQ_MIN_TIMEOUT_INTERVAL 30000 -#define UNF_LOGO_TIMEOUT_INTERVAL 3000 -#define UNF_SFS_MIN_TIMEOUT_INTERVAL 15000 -#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_MAX_ABTS_WAIT_INTERVAL ((UNF_WAIT_SEM_TIMEOUT - 500) / 1000) - -#define UNF_TGT_RRQ_REDUNDANT_TIME 2000 -#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 -#define UNF_LGN_INFRAMESIZE 2048 - -/* 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_0_MASK \ - (UNF_FC4_FRAME_PARM_0_FCP | UNF_FC4_FRAME_PARM_0_I_PAIR | \ - UNF_FC4_FRAME_PARM_0_GOOD_RSP_CODE) -#define UNF_FC4_FRAME_PARM_3_INI 0x00000020 -#define UNF_FC4_FRAME_PARM_3_TGT 0x00000010 -#define UNF_FC4_FRAME_PARM_3_BOTH \ - (UNF_FC4_FRAME_PARM_3_INI | UNF_FC4_FRAME_PARM_3_TGT) -#define UNF_FC4_FRAME_PARM_3_R_XFER_DIS 0x00000002 -#define UNF_FC4_FRAME_PARM_3_W_XFER_DIS 0x00000001 -#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_FC4_FRAME_PARM_3_MASK \ - (UNF_FC4_FRAME_PARM_3_INI | UNF_FC4_FRAME_PARM_3_TGT | \ - UNF_FC4_FRAME_PARM_3_R_XFER_DIS) - -#define UNF_FC4_TYPE_SHIFT 24 -#define UNF_FC4_TYPE_MASK 0xff -/* FC4 feature we support */ -#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 */ - -#define UNF_FC_PROTOCOL_CLASS_3 0x0 -#define UNF_FC_PROTOCOL_CLASS_2 0x1 -#define UNF_FC_PROTOCOL_CLASS_1 0x2 -#define UNF_FC_PROTOCOL_CLASS_F 0x3 -#define UNF_FC_PROTOCOL_CLASS_OTHER 0x4 - -#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(cmnd) ((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_LOGOUT 0x0009 -#define UNF_PORT_CLEAR_VLINK 0x000a -#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 - -/* - * 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 IS_VERIFY_COMMAND(opcode) \ - ((opcode) == SCSIOPC_VERIFY_10 || (opcode) == SCSIOPC_VERIFY_12 || \ - (opcode) == SCSIOPC_VERIFY_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(ret, port_id, work, work_symb) \ - do { \ - if (!cancel_delayed_work_sync(work)) { \ - FC_DRV_PRINT(UNF_LOG_REG_ATT, \ - UNF_INFO, \ - "[info]LPort or RPort(0x%x) %s worker " \ - "can't destroy, or no " \ - "worker", \ - port_id, work_symb); \ - ret = UNF_RETURN_ERROR; \ - } else { \ - ret = RETURN_OK; \ - } \ - } while (0) - -#define UNF_GET_SFS_ENTRY(pkg) ((union unf_sfs_u *)(void *)(((struct unf_frame_pkg *)(pkg)) \ - ->unf_cmnd_pload_bl.buffer_ptr)) -/* FLOGI */ -#define UNF_GET_FLOGI_PAYLOAD(pkg) \ - (&(((union unf_sfs_u *)(UNF_GET_SFS_ENTRY(pkg)))->flogi.flogi_payload)) -#define UNF_FLOGI_PAYLOAD_LEN sizeof(struct unf_flogi_fdisc_payload) - -/* FLOGI ACC */ -#define UNF_GET_FLOGI_ACC_PAYLOAD(pkg) \ - (&(((union unf_sfs_u *)(UNF_GET_SFS_ENTRY(pkg))) \ - ->flogi_acc.flogi_payload)) -#define UNF_FLOGI_ACC_PAYLOAD_LEN sizeof(struct unf_flogi_fdisc_payload) - -/* 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(pkg) \ - (&(((union unf_sfs_u *)(UNF_GET_SFS_ENTRY(pkg)))->plogi.payload)) -#define UNF_PLOGI_PAYLOAD_LEN sizeof(struct unf_plogi_payload) - -/* PLOGI ACC */ -#define UNF_GET_PLOGI_ACC_PAYLOAD(pkg) \ - (&(((union unf_sfs_u *)(UNF_GET_SFS_ENTRY(pkg)))->plogi_acc.payload)) -#define UNF_PLOGI_ACC_PAYLOAD_LEN sizeof(struct unf_plogi_payload) - -/* LOGO */ -#define UNF_GET_LOGO_PAYLOAD(pkg) \ - (&(((union unf_sfs_u *)(UNF_GET_SFS_ENTRY(pkg)))->logo.payload)) -#define UNF_LOGO_PAYLOAD_LEN sizeof(struct unf_logo_payload) - -/* ECHO */ -#define UNF_GET_ECHO_PAYLOAD(pkg) \ - (((union unf_sfs_u *)(UNF_GET_SFS_ENTRY(pkg)))->echo.echo_pld) - -/* ECHO PHYADDR */ -#define UNF_GET_ECHO_PAYLOAD_PHYADDR(pkg) \ - (((union unf_sfs_u *)(UNF_GET_SFS_ENTRY(pkg)))->echo.phy_echo_addr) - -#define UNF_ECHO_PAYLOAD_LEN sizeof(struct unf_echo_payload) - -/* REC */ -#define UNF_GET_REC_PAYLOAD(pkg) \ - (&(((union unf_sfs_u *)(UNF_GET_SFS_ENTRY(pkg)))->rec.rec_pld)) - -#define UNF_REC_PAYLOAD_LEN sizeof(struct unf_rec_pld) - -/* ECHO ACC */ -#define UNF_GET_ECHO_ACC_PAYLOAD(pkg) \ - (((union unf_sfs_u *)(UNF_GET_SFS_ENTRY(pkg)))->echo_acc.echo_pld) -#define UNF_ECHO_ACC_PAYLOAD_LEN sizeof(struct unf_echo_payload) - -/* RRQ */ -#define UNF_GET_RRQ_PAYLOAD(pkg) \ - (&(((union unf_sfs_u *)(UNF_GET_SFS_ENTRY(pkg)))->rrq.cmnd)) -#define UNF_RRQ_PAYLOAD_LEN \ - (sizeof(struct unf_rrq) - sizeof(struct unf_fc_head)) - -/* PRLI */ -#define UNF_GET_PRLI_PAYLOAD(pkg) \ - (&(((union unf_sfs_u *)(UNF_GET_SFS_ENTRY(pkg)))->prli.payload)) -#define UNF_PRLI_PAYLOAD_LEN sizeof(struct unf_prli_payload) - -/* PRLI ACC */ -#define UNF_GET_PRLI_ACC_PAYLOAD(pkg) \ - (&(((union unf_sfs_u *)(UNF_GET_SFS_ENTRY(pkg)))->prli_acc.payload)) -#define UNF_PRLI_ACC_PAYLOAD_LEN sizeof(struct unf_prli_payload) - -/* PRLO */ -#define UNF_GET_PRLO_PAYLOAD(pkg) \ - (&(((union unf_sfs_u *)(UNF_GET_SFS_ENTRY(pkg)))->prlo.payload)) -#define UNF_PRLO_PAYLOAD_LEN sizeof(struct unf_prli_payload) - -#define UNF_GET_PRLO_ACC_PAYLOAD(pkg) \ - (&(((union unf_sfs_u *)(UNF_GET_SFS_ENTRY(pkg)))->prlo_acc.payload)) -#define UNF_PRLO_ACC_PAYLOAD_LEN sizeof(struct unf_prli_payload) - -/* PDISC */ -#define UNF_GET_PDISC_PAYLOAD(pkg) \ - (&(((union unf_sfs_u *)(UNF_GET_SFS_ENTRY(pkg)))->pdisc.payload)) -#define UNF_PDISC_PAYLOAD_LEN sizeof(struct unf_plogi_payload) - -/* PDISC ACC */ -#define UNF_GET_PDISC_ACC_PAYLOAD(pkg) \ - (&(((union unf_sfs_u *)(UNF_GET_SFS_ENTRY(pkg)))->pdisc_acc.payload)) -#define UNF_PDISC_ACC_PAYLOAD_LEN sizeof(struct unf_plogi_payload) - -/* ADISC */ -#define UNF_GET_ADISC_PAYLOAD(pkg) \ - (&(((union unf_sfs_u *)(UNF_GET_SFS_ENTRY(pkg)))->adisc.adisc_payl)) -#define UNF_ADISC_PAYLOAD_LEN sizeof(struct unf_adisc_payload) - -/* ADISC ACC */ -#define UNF_GET_ADISC_ACC_PAYLOAD(pkg) \ - (&(((union unf_sfs_u *)(UNF_GET_SFS_ENTRY(pkg)))->adisc_acc.adisc_payl)) -#define UNF_ADISC_ACC_PAYLOAD_LEN sizeof(struct unf_adisc_payload) - -/* RSCN ACC */ -#define UNF_GET_RSCN_ACC_PAYLOAD(pkg) \ - (&(((union unf_sfs_u *)(UNF_GET_SFS_ENTRY(pkg)))->els_acc.cmnd)) -#define UNF_RSCN_ACC_PAYLOAD_LEN \ - (sizeof(struct unf_els_acc) - sizeof(struct unf_fc_head)) - -/* LOGO ACC */ -#define UNF_GET_LOGO_ACC_PAYLOAD(pkg) \ - (&(((union unf_sfs_u *)(UNF_GET_SFS_ENTRY(pkg)))->els_acc.cmnd)) -#define UNF_LOGO_ACC_PAYLOAD_LEN \ - (sizeof(struct unf_els_acc) - sizeof(struct unf_fc_head)) - -/* RRQ ACC */ -#define UNF_GET_RRQ_ACC_PAYLOAD(pkg) \ - (&(((union unf_sfs_u *)(UNF_GET_SFS_ENTRY(pkg)))->els_acc.cmnd)) -#define UNF_RRQ_ACC_PAYLOAD_LEN \ - (sizeof(struct unf_els_acc) - sizeof(struct unf_fc_head)) - -/* REC ACC */ -#define UNF_GET_REC_ACC_PAYLOAD(pkg) \ - (&(((union unf_sfs_u *)(UNF_GET_SFS_ENTRY(pkg)))->els_acc.cmnd)) -#define UNF_REC_ACC_PAYLOAD_LEN \ - (sizeof(struct unf_els_acc) - sizeof(struct unf_fc_head)) - -/* GPN_ID */ -#define UNF_GET_GPNID_PAYLOAD(pkg) \ - (&(((union unf_sfs_u *)UNF_GET_SFS_ENTRY(pkg))->gpn_id.ctiu_pream)) -#define UNF_GPNID_PAYLOAD_LEN \ - (sizeof(struct unf_gpnid) - sizeof(struct unf_fc_head)) - -#define UNF_GET_GPNID_RSP_PAYLOAD(pkg) \ - (&(((union unf_sfs_u *)UNF_GET_SFS_ENTRY(pkg))->gpn_id_rsp.ctiu_pream)) -#define UNF_GPNID_RSP_PAYLOAD_LEN \ - (sizeof(struct unf_gpnid_rsp) - sizeof(struct unf_fc_head)) - -/* GNN_ID */ -#define UNF_GET_GNNID_PAYLOAD(pkg) \ - (&(((union unf_sfs_u *)UNF_GET_SFS_ENTRY(pkg))->gnn_id.ctiu_pream)) -#define UNF_GNNID_PAYLOAD_LEN \ - (sizeof(struct unf_gnnid) - sizeof(struct unf_fc_head)) - -#define UNF_GET_GNNID_RSP_PAYLOAD(pkg) \ - (&(((union unf_sfs_u *)UNF_GET_SFS_ENTRY(pkg))->gnn_id_rsp.ctiu_pream)) -#define UNF_GNNID_RSP_PAYLOAD_LEN \ - (sizeof(struct unf_gnnid_rsp) - sizeof(struct unf_fc_head)) - -/* GFF_ID */ -#define UNF_GET_GFFID_PAYLOAD(pkg) \ - (&(((union unf_sfs_u *)UNF_GET_SFS_ENTRY(pkg))->gff_id.ctiu_pream)) -#define UNF_GFFID_PAYLOAD_LEN \ - (sizeof(struct unf_gffid) - sizeof(struct unf_fc_head)) - -#define UNF_GET_GFFID_RSP_PAYLOAD(pkg) \ - (&(((union unf_sfs_u *)UNF_GET_SFS_ENTRY(pkg))->gff_id_rsp.ctiu_pream)) -#define UNF_GFFID_RSP_PAYLOAD_LEN \ - (sizeof(struct unf_gffid_rsp) - sizeof(struct unf_fc_head)) - -/* GID_FT/GID_PT */ -#define UNF_GET_GID_PAYLOAD(pkg) \ - (&(((union unf_sfs_u *)UNF_GET_SFS_ENTRY(pkg)) \ - ->get_id.gid_req.ctiu_pream)) - -#define UNF_GID_PAYLOAD_LEN (sizeof(struct unf_ctiu_prem) + sizeof(u32)) -#define UNF_GET_GID_ACC_PAYLOAD(pkg) \ - (((union unf_sfs_u *)UNF_GET_SFS_ENTRY(pkg)) \ - ->get_id.gid_rsp.gid_acc_pld) -#define UNF_GID_ACC_PAYLOAD_LEN sizeof(struct unf_gid_acc_pld) - -/* RFT_ID */ -#define UNF_GET_RFTID_PAYLOAD(pkg) \ - (&(((union unf_sfs_u *)UNF_GET_SFS_ENTRY(pkg))->rft_id.ctiu_pream)) -#define UNF_RFTID_PAYLOAD_LEN \ - (sizeof(struct unf_rftid) - sizeof(struct unf_fc_head)) - -#define UNF_GET_RFTID_RSP_PAYLOAD(pkg) \ - (&(((union unf_sfs_u *)UNF_GET_SFS_ENTRY(pkg))->rft_id_rsp.ctiu_pream)) -#define UNF_RFTID_RSP_PAYLOAD_LEN sizeof(struct unf_ctiu_prem) - -/* RFF_ID */ -#define UNF_GET_RFFID_PAYLOAD(pkg) \ - (&(((union unf_sfs_u *)UNF_GET_SFS_ENTRY(pkg))->rff_id.ctiu_pream)) -#define UNF_RFFID_PAYLOAD_LEN \ - (sizeof(struct unf_rffid) - sizeof(struct unf_fc_head)) - -#define UNF_GET_RFFID_RSP_PAYLOAD(pkg) \ - (&(((union unf_sfs_u *)UNF_GET_SFS_ENTRY(pkg))->rff_id_rsp.ctiu_pream)) -#define UNF_RFFID_RSP_PAYLOAD_LEN sizeof(struct unf_ctiu_prem) - -/* ACC&RJT */ -#define UNF_GET_ELS_ACC_RJT_PAYLOAD(pkg) \ - (&(((union unf_sfs_u *)UNF_GET_SFS_ENTRY(pkg))->els_rjt.cmnd)) -#define UNF_ELS_ACC_RJT_LEN \ - (sizeof(struct unf_els_rjt) - sizeof(struct unf_fc_head)) - -/* SCR */ -#define UNF_SCR_PAYLOAD(pkg) \ - (((union unf_sfs_u *)UNF_GET_SFS_ENTRY(pkg))->scr.payload) -#define UNF_SCR_PAYLOAD_LEN \ - (sizeof(struct unf_scr) - sizeof(struct unf_fc_head)) - -#define UNF_SCR_RSP_PAYLOAD(pkg) \ - (&(((union unf_sfs_u *)UNF_GET_SFS_ENTRY(pkg))->els_acc.cmnd)) -#define UNF_SCR_RSP_PAYLOAD_LEN \ - (sizeof(struct unf_els_acc) - sizeof(struct unf_fc_head)) - -#define UNF_GS_RSP_PAYLOAD_LEN \ - (sizeof(union unf_sfs_u) - sizeof(struct unf_fc_head)) - -#define UNF_GET_XCHG_TAG(pkg) \ - (((struct unf_frame_pkg *)(pkg)) \ - ->private_data[PKG_PRIVATE_XCHG_HOT_POOL_INDEX]) -#define UNF_GET_ABTS_XCHG_TAG(pkg) \ - ((u16)(((pkg)->private_data[PKG_PRIVATE_XCHG_HOT_POOL_INDEX]) >> 16)) -#define UNF_GET_IO_XCHG_TAG(pkg) \ - ((u16)((pkg)->private_data[PKG_PRIVATE_XCHG_HOT_POOL_INDEX])) - -#define UNF_GET_HOTPOOL_TAG(pkg) \ - (((struct unf_frame_pkg *)(pkg)) \ - ->private_data[PKG_PRIVATE_XCHG_HOT_POOL_INDEX]) -#define UNF_GET_SID(pkg) \ - (((struct unf_frame_pkg *)(pkg))->frame_head.csctl_sid & \ - UNF_NPORTID_MASK) -#define UNF_GET_DID(pkg) \ - (((struct unf_frame_pkg *)(pkg))->frame_head.rctl_did & \ - UNF_NPORTID_MASK) -#define UNF_GET_OXID(pkg) \ - (((struct unf_frame_pkg *)(pkg))->frame_head.oxid_rxid >> 16) -#define UNF_GET_RXID(pkg) \ - ((u16)((struct unf_frame_pkg *)(pkg))->frame_head.oxid_rxid) -#define UNF_GET_XID_RELEASE_TIMER(pkg) \ - (((struct unf_frame_pkg *)(pkg))->release_task_id_timer) -#define UNF_GETXCHGALLOCTIME(pkg) \ - (((struct unf_frame_pkg *)(pkg)) \ - ->private_data[PKG_PRIVATE_XCHG_ALLOC_TIME]) - -#define UNF_SET_XCHG_ALLOC_TIME(pkg, xchg) \ - (((struct unf_frame_pkg *)(pkg)) \ - ->private_data[PKG_PRIVATE_XCHG_ALLOC_TIME] = \ - (((struct unf_xchg *)(xchg)) \ - ->private_data[PKG_PRIVATE_XCHG_ALLOC_TIME])) -#define UNF_SET_ABORT_INFO_IOTYPE(pkg, xchg) \ - (((struct unf_frame_pkg *)(pkg)) \ - ->private_data[PKG_PRIVATE_XCHG_ABORT_INFO] |= \ - (((u8)(((struct unf_xchg *)(xchg))->data_direction & 0x7)) \ - << 2)) - -#define UNF_CHECK_NPORT_FPORT_BIT(els_payload) \ - (((struct unf_flogi_fdisc_payload *)(els_payload)) \ - ->fabric_parms.co_parms.nport) - -#define UNF_GET_RSP_BUF(pkg) \ - ((void *)(((struct unf_frame_pkg *)(pkg))->unf_rsp_pload_bl.buffer_ptr)) -#define UNF_GET_RSP_LEN(pkg) \ - (((struct unf_frame_pkg *)(pkg))->unf_rsp_pload_bl.length) - -#define UNF_N_PORT 0 -#define UNF_F_PORT 1 - -#define UNF_GET_RA_TOV_FROM_PARAMS(pfcparams) \ - (((struct unf_fabric_parm *)(pfcparams))->co_parms.r_a_tov) -#define UNF_GET_RT_TOV_FROM_PARAMS(pfcparams) \ - (((struct unf_fabric_parm *)(pfcparams))->co_parms.r_t_tov) -#define UNF_GET_E_D_TOV_FROM_PARAMS(pfcparams) \ - (((struct unf_fabric_parm *)(pfcparams))->co_parms.e_d_tov) -#define UNF_GET_E_D_TOV_RESOLUTION_FROM_PARAMS(pfcparams) \ - (((struct unf_fabric_parm *)(pfcparams))->co_parms.e_d_tov_resolution) -#define UNF_GET_BB_SC_N_FROM_PARAMS(pfcparams) \ - (((struct unf_fabric_parm *)(pfcparams))->co_parms.bbscn) -#define UNF_GET_BB_CREDIT_FROM_PARAMS(pfcparams) \ - (((struct unf_fabric_parm *)(pfcparams))->co_parms.bb_credit) - -enum unf_pcie_error_code { - 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_BLS_REPLY 0x0102 -#define UNF_PKG_BLS_REPLY_DONE 0x0103 - -#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_TGT_XFER 0x0400 -#define UNF_PKG_TGT_RSP 0x0401 -#define UNF_PKG_TGT_RSP_NOSGL 0x0402 -#define UNF_PKG_TGT_RSP_STATUS 0x0403 - -#define UNF_PKG_INI_IO 0x0500 -#define UNF_PKG_INI_RCV_TGT_RSP 0x0507 - -/* external sgl struct start */ -struct unf_esgl_page { - u64 page_address; - dma_addr_t esgl_phy_addr; - u32 page_size; -}; - -/* external sgl struct end */ -struct unf_esgl { - struct list_head entry_esgl; - struct unf_esgl_page page; -}; - -#define UNF_RESPONE_DATA_LEN 8 -struct unf_frame_payld { - u8 *buffer_ptr; - dma_addr_t buf_dma_addr; - u32 length; -}; - -enum pkg_private_index { - 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_XCHG_SSQ_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 u32 dix_flag; -extern u32 dif_sgl_mode; -extern u32 dif_app_esc_check; -extern u32 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_DIF_CRC_ERR 0x1001 -#define UNF_DIF_APP_ERR 0x1002 -#define UNF_DIF_LBA_ERR 0x1003 - -#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_512_BLOCK_CNT(data_len) ((data_len) >> 9) -#define UNF_CAL_BLOCK_CNT(data_len, sector_size) ((data_len) / (sector_size)) -#define UNF_CAL_CRC_BLK_CNT(crc_data_len, sector_size) \ - ((crc_data_len) / ((sector_size) + 8)) - -#define UNF_DIF_DOUBLE_SGL (1 << 1) -#define UNF_DIF_SECTSIZE_4KB (1 << 2) -#define UNF_DIF_SECTSIZE_512 (0 << 2) -#define UNF_DIF_LBA_NONE_INCREASE (1 << 3) -#define UNF_DIF_TYPE3 (1 << 4) - -#define SECTOR_SIZE_512 512 -#define SECTOR_SIZE_4096 4096 -#define SPFC_DIF_APP_REF_ESC_NOT_CHECK 1 -#define SPFC_DIF_APP_REF_ESC_CHECK 0 - -struct unf_dif { - u16 crc; - u16 app_tag; - u32 lba; -}; - -enum unf_io_state { 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 - -struct unf_frame_pkg { - /* pkt type:BLS/ELS/FC4LS/CMND/XFER/RSP */ - u32 type; - u32 last_pkg_flag; - u32 fcp_conf_flag; - -#define UNF_FCP_RESPONSE_VALID 0x01 -#define UNF_FCP_SENSE_VALID 0x02 - u32 response_and_sense_valid_flag; /* resp and sense vailed flag */ - u32 cmnd; - struct unf_fc_head frame_head; - u32 entry_count; - void *xchg_contex; - u32 transfer_len; - u32 residus_len; - u32 status; - u32 status_sub_code; - enum unf_io_state io_state; - u32 qos_level; - u32 private_data[PKG_MAX_PRIVATE_DATA_SIZE]; - struct unf_fcp_cmnd *fcp_cmnd; - struct unf_dif_control_info dif_control; - struct unf_frame_payld unf_cmnd_pload_bl; - struct unf_frame_payld unf_rsp_pload_bl; - struct unf_frame_payld unf_sense_pload_bl; - void *upper_cmd; - u32 abts_maker_status; - u32 release_task_id_timer; - u8 byte_orders; - u8 rx_or_ox_id; - u8 class_mode; - u8 rsvd; - u8 *peresp; - u32 rcvrsp_len; - ulong timeout; - u32 origin_hottag; - u32 origin_magicnum; -}; - -#define UNF_MAX_SFS_XCHG 2048 -#define UNF_RESERVE_SFS_XCHG 128 /* times on exchange mgr num */ - -struct unf_lport_cfg_item { - u32 port_id; - u32 port_mode; /* INI(0x20), TGT(0x10), BOTH(0x30) */ - u32 port_topology; /* 0x3:loop , 0xc:p2p ,0xf:auto */ - u32 max_queue_depth; - u32 max_io; /* Recommended Value 512-4096 */ - u32 max_login; - u32 max_sfs_xchg; - u32 port_speed; /* 0:auto 1:1Gbps 2:2Gbps 4:4Gbps 8:8Gbps 16:16Gbps */ - u32 tape_support; /* ape support */ - u32 fcp_conf; /* fcp confirm support */ - u32 bbscn; -}; - -struct unf_port_dynamic_info { - u32 sfp_posion; - u32 sfp_valid; - u32 phy_link; - u32 firmware_state; - u32 cur_speed; - u32 mailbox_timeout_cnt; -}; - -struct unf_port_intr_coalsec { - u32 delay_timer; - u32 depth; -}; - -struct unf_port_topo { - u32 topo_cfg; - enum unf_act_topo topo_act; -}; - -struct unf_port_transfer_para { - u32 type; - u32 value; -}; - -struct unf_buf { - u8 *buf; - u32 buf_len; -}; - -/* get ucode & up ver */ -#define SPFC_VER_LEN (16) -#define SPFC_COMPILE_TIME_LEN (20) -struct unf_fw_version { - u32 message_type; - u8 fw_version[SPFC_VER_LEN]; -}; - -struct unf_port_wwn { - u64 sys_port_wwn; - u64 sys_node_name; -}; - -enum unf_port_config_set_op { - UNF_PORT_CFG_SET_SPEED, - UNF_PORT_CFG_SET_PORT_SWITCH, - UNF_PORT_CFG_SET_POWER_STATE, - UNF_PORT_CFG_SET_PORT_STATE, - UNF_PORT_CFG_UPDATE_WWN, - UNF_PORT_CFG_TEST_FLASH, - UNF_PORT_CFG_UPDATE_FABRIC_PARAM, - UNF_PORT_CFG_UPDATE_PLOGI_PARAM, - UNF_PORT_CFG_SET_BUTT -}; - -enum unf_port_cfg_get_op { - UNF_PORT_CFG_GET_TOPO_ACT, - UNF_PORT_CFG_GET_LOOP_MAP, - UNF_PORT_CFG_GET_SFP_PRESENT, - UNF_PORT_CFG_GET_FW_VER, - UNF_PORT_CFG_GET_HW_VER, - 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_MAC_ADDR, - UNF_PORT_CFG_GET_SFP_VER, - UNF_PORT_CFG_GET_SFP_SUPPORT_UPDATE, - UNF_PORT_CFG_GET_SFP_LOG, - UNF_PORT_CFG_GET_PCIE_LINK_STATE, - UNF_PORT_CFG_GET_FLASH_DATA_INFO, - UNF_PORT_CFG_GET_BUTT, -}; - -enum unf_port_config_state { - 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 -}; - -enum unf_port_config_update { - UNF_PORT_CONFIG_UPDATE_FW_MINIMUM, - UNF_PORT_CONFIG_UPDATE_FW_ALL, - UNF_PORT_CONFIG_UPDATE_BUTT -}; - -enum unf_disable_vp_mode { - UNF_DISABLE_VP_MODE_ONLY = 0x8, - UNF_DISABLE_VP_MODE_REINIT_LINK = 0x9, - UNF_DISABLE_VP_MODE_NOFAB_LOGO = 0xA, - UNF_DISABLE_VP_MODE_LOGO_ALL = 0xB -}; - -struct unf_vport_info { - u16 vp_index; - u64 node_name; - u64 port_name; - u32 port_mode; /* INI, TGT or both */ - enum unf_disable_vp_mode disable_mode; - u32 nport_id; /* maybe acquired by lowlevel and update to common */ - void *vport; -}; - -struct unf_port_login_parms { - enum unf_act_topo act_topo; - - u32 rport_index; - u32 seq_cnt : 1; - u32 ed_tov : 1; - u32 reserved : 14; - u32 tx_mfs : 16; - u32 ed_tov_timer_val; - - u8 remote_rttov_tag; - u8 remote_edtov_tag; - u16 remote_bb_credit; - u16 compared_bbscn; - u32 compared_edtov_val; - u32 compared_ratov_val; - u32 els_cmnd_code; -}; - -struct unf_mbox_head_info { - /* mbox header */ - u8 cmnd_type; - u8 length; - u8 port_id; - u8 pad0; - - /* operation */ - u32 opcode : 4; - u32 pad1 : 28; -}; - -struct unf_mbox_head_sts { - /* mbox header */ - u8 cmnd_type; - u8 length; - u8 port_id; - u8 pad0; - - /* operation */ - u16 pad1; - u8 pad2; - u8 status; -}; - -struct unf_low_level_service_op { - u32 (*unf_ls_gs_send)(void *hba, struct unf_frame_pkg *pkg); - u32 (*unf_bls_send)(void *hba, struct unf_frame_pkg *pkg); - u32 (*unf_cmnd_send)(void *hba, struct unf_frame_pkg *pkg); - u32 (*unf_rsp_send)(void *handle, struct unf_frame_pkg *pkg); - u32 (*unf_release_rport_res)(void *handle, struct unf_port_info *rport_info); - u32 (*unf_flush_ini_resp_que)(void *handle); - u32 (*unf_alloc_rport_res)(void *handle, struct unf_port_info *rport_info); - u32 (*ll_release_xid)(void *handle, struct unf_frame_pkg *pkg); - u32 (*unf_xfer_send)(void *handle, struct unf_frame_pkg *pkg); -}; - -struct unf_low_level_port_mgr_op { - /* fcport/opcode/input parameter */ - u32 (*ll_port_config_set)(void *fc_port, enum unf_port_config_set_op opcode, void *para_in); - - /* fcport/opcode/output parameter */ - u32 (*ll_port_config_get)(void *fc_port, enum unf_port_cfg_get_op opcode, void *para_out); -}; - -struct unf_chip_info { - u8 chip_type; - u8 chip_work_mode; - u8 disable_err_flag; -}; - -struct unf_low_level_functioon_op { - struct unf_chip_info chip_info; - /* low level type */ - u32 low_level_type; - const char *name; - struct pci_dev *dev; - u64 sys_node_name; - u64 sys_port_name; - struct unf_lport_cfg_item lport_cfg_items; -#define UNF_LOW_LEVEL_MGR_TYPE_ACTIVE 0 -#define UNF_LOW_LEVEL_MGR_TYPE_PASSTIVE 1 - const u32 xchg_mgr_type; - -#define UNF_NO_EXTRA_ABTS_XCHG 0x0 -#define UNF_LL_IOC_ABTS_XCHG 0x1 - const u32 abts_xchg; - -#define UNF_CM_RPORT_SET_QUALIFIER 0x0 -#define UNF_CM_RPORT_SET_QUALIFIER_REUSE 0x1 -#define UNF_CM_RPORT_SET_QUALIFIER_SPFC 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 - u32 passthrough_flag; - - /* low level parameter */ - u32 support_max_npiv_num; - u32 support_max_ssq_num; - u32 support_max_speed; - u32 support_min_speed; - u32 fc_ser_max_speed; - - u32 support_max_rport; - - u32 support_max_hot_tag_range; - u32 sfp_type; - u32 update_fw_reset_active; - u32 support_upgrade_report; - u32 multi_conf_support; - u32 port_type; -#define UNF_LOW_LEVEL_RELEASE_RPORT_SYNC 0x0 -#define UNF_LOW_LEVEL_RELEASE_RPORT_ASYNC 0x1 - u8 rport_release_type; -#define UNF_LOW_LEVEL_SIRT_PAGE_MODE_FIXED 0x0 -#define UNF_LOW_LEVEL_SIRT_PAGE_MODE_XCHG 0x1 - u8 sirt_page_mode; - u8 sfp_speed; - - /* IO reference */ - struct unf_low_level_service_op service_op; - - /* Port Mgr reference */ - struct unf_low_level_port_mgr_op port_mgr_op; - - u8 chip_id; -}; - -struct unf_cm_handle_op { - /* return:L_Port */ - void *(*unf_alloc_local_port)(void *private_data, - struct unf_low_level_functioon_op *low_level_op); - - /* input para:L_Port */ - u32 (*unf_release_local_port)(void *lport); - - /* input para:L_Port, FRAME_PKG_S */ - u32 (*unf_receive_ls_gs_pkg)(void *lport, struct unf_frame_pkg *pkg); - - /* input para:L_Port, FRAME_PKG_S */ - u32 (*unf_receive_bls_pkg)(void *lport, struct unf_frame_pkg *pkg); - /* input para:L_Port, FRAME_PKG_S */ - u32 (*unf_send_els_done)(void *lport, struct unf_frame_pkg *pkg); - - /* input para:L_Port, FRAME_PKG_S */ - u32 (*unf_receive_marker_status)(void *lport, struct unf_frame_pkg *pkg); - u32 (*unf_receive_abts_marker_status)(void *lport, struct unf_frame_pkg *pkg); - /* input para:L_Port, FRAME_PKG_S */ - u32 (*unf_receive_ini_response)(void *lport, struct unf_frame_pkg *pkg); - - int (*unf_get_cfg_parms)(char *section_name, - struct unf_cfg_item *cfg_parm, u32 *cfg_value, - u32 item_num); - - /* TGT IO interface */ - u32 (*unf_process_fcp_cmnd)(void *lport, struct unf_frame_pkg *pkg); - - /* TGT IO Done */ - u32 (*unf_tgt_cmnd_xfer_or_rsp_echo)(void *lport, struct unf_frame_pkg *pkg); - - u32 (*unf_cm_get_sgl_entry)(void *pkg, char **buf, u32 *buf_len); - u32 (*unf_cm_get_dif_sgl_entry)(void *pkg, char **buf, u32 *buf_len); - - struct unf_esgl_page *(*unf_get_one_free_esgl_page)(void *lport, struct unf_frame_pkg *pkg); - - /* input para:L_Port, EVENT */ - u32 (*unf_fc_port_event)(void *lport, u32 events, void *input); - - int (*unf_drv_start_work)(void *lport); - - void (*unf_card_rport_chip_err)(struct pci_dev const *pci_dev); -}; - -u32 unf_get_cm_handle_ops(struct unf_cm_handle_op *cm_handle); -int unf_common_init(void); -void unf_common_exit(void); - -#endif diff --git a/drivers/scsi/spfc/common/unf_disc.c b/drivers/scsi/spfc/common/unf_disc.c deleted file mode 100644 index c48d0ba670d4..000000000000 --- a/drivers/scsi/spfc/common/unf_disc.c +++ /dev/null @@ -1,1276 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#include "unf_disc.h" -#include "unf_log.h" -#include "unf_common.h" -#include "unf_event.h" -#include "unf_lport.h" -#include "unf_rport.h" -#include "unf_exchg.h" -#include "unf_ls.h" -#include "unf_gs.h" -#include "unf_portman.h" - -#define UNF_LIST_RSCN_PAGE_CNT 2560 -#define UNF_MAX_PORTS_PRI_LOOP 2 -#define UNF_MAX_GS_SEND_NUM 8 -#define UNF_OS_REMOVE_CARD_TIMEOUT (60 * 1000) - -static void unf_set_disc_state(struct unf_disc *disc, - enum unf_disc_state states) -{ - FC_CHECK_RETURN_VOID(disc); - - if (states != disc->states) { - /* Reset disc retry count */ - disc->retry_count = 0; - } - - disc->states = states; -} - -static inline u32 unf_get_loop_map(struct unf_lport *lport, u8 loop_map[], u32 loop_map_size) -{ - struct unf_buf buf = {0}; - u32 ret = UNF_RETURN_ERROR; - - FC_CHECK_RETURN_VALUE(lport->low_level_func.port_mgr_op.ll_port_config_get, - UNF_RETURN_ERROR); - - buf.buf = loop_map; - buf.buf_len = loop_map_size; - - ret = lport->low_level_func.port_mgr_op.ll_port_config_get(lport->fc_port, - UNF_PORT_CFG_GET_LOOP_MAP, - (void *)&buf); - return ret; -} - -static void unf_login_with_loop_node(struct unf_lport *lport, u32 alpa) -{ - /* Only used for Private Loop LOGIN */ - struct unf_rport *unf_rport = NULL; - ulong rport_flag = 0; - u32 port_feature = 0; - u32 ret; - - /* Check AL_PA validity */ - if (lport->nport_id == alpa) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "[info]Port(0x%x) is the same as RPort with AL_PA(0x%x), do nothing", - lport->port_id, alpa); - return; - } - - if (alpa == 0) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) RPort(0x%x) is fabric, do nothing", - lport->port_id, alpa); - return; - } - - /* Get & set R_Port: reuse only */ - unf_rport = unf_get_rport_by_nport_id(lport, alpa); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: Port(0x%x_0x%x) RPort(0x%x_0x%p) login with private loop", - lport->port_id, lport->nport_id, alpa, unf_rport); - - unf_rport = unf_get_safe_rport(lport, unf_rport, UNF_RPORT_REUSE_ONLY, alpa); - if (!unf_rport) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x_0x%x) allocate new RPort(0x%x) failed", - lport->port_id, lport->nport_id, alpa); - return; - } - - /* Update R_Port state & N_Port_ID */ - spin_lock_irqsave(&unf_rport->rport_state_lock, rport_flag); - unf_rport->nport_id = alpa; - unf_rport_state_ma(unf_rport, UNF_EVENT_RPORT_ENTER_PLOGI); - spin_unlock_irqrestore(&unf_rport->rport_state_lock, rport_flag); - - /* Private Loop: check whether need delay to send PLOGI or not */ - port_feature = unf_rport->options; - - /* check Rport and Lport feature */ - if (port_feature == UNF_PORT_MODE_UNKNOWN && - lport->options == UNF_PORT_MODE_INI) { - /* Start to send PLOGI */ - ret = unf_send_plogi(lport, unf_rport); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]LOGIN: Port(0x%x_0x%x) send PLOGI to RPort(0x%x) failed", - lport->port_id, lport->nport_id, unf_rport->nport_id); - - unf_rport_error_recovery(unf_rport); - } - } else { - unf_check_rport_need_delay_plogi(lport, unf_rport, port_feature); - } -} - -static int unf_discover_private_loop(void *arg_in, void *arg_out) -{ - struct unf_lport *unf_lport = (struct unf_lport *)arg_in; - u32 ret = UNF_RETURN_ERROR; - u32 i = 0; - u8 loop_id = 0; - u32 alpa_index = 0; - u8 loop_map[UNF_LOOPMAP_COUNT]; - - FC_CHECK_RETURN_VALUE(unf_lport, UNF_RETURN_ERROR); - memset(loop_map, 0x0, UNF_LOOPMAP_COUNT); - - /* Get Port Loop Map */ - ret = unf_get_loop_map(unf_lport, loop_map, UNF_LOOPMAP_COUNT); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) get loop map failed", unf_lport->port_id); - - return UNF_RETURN_ERROR; - } - - /* Check Loop Map Ports Count */ - if (loop_map[ARRAY_INDEX_0] > UNF_MAX_PORTS_PRI_LOOP) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) has more than %d ports(%u) in private loop", - unf_lport->port_id, UNF_MAX_PORTS_PRI_LOOP, loop_map[ARRAY_INDEX_0]); - - return UNF_RETURN_ERROR; - } - - /* AL_PA = 0 means Public Loop */ - if (loop_map[ARRAY_INDEX_1] == UNF_FL_PORT_LOOP_ADDR || - loop_map[ARRAY_INDEX_2] == UNF_FL_PORT_LOOP_ADDR) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) one or more AL_PA is 0x00, indicate it's FL_Port", - unf_lport->port_id); - - return UNF_RETURN_ERROR; - } - - /* Discovery Private Loop Ports */ - for (i = 0; i < loop_map[ARRAY_INDEX_0]; i++) { - alpa_index = i + 1; - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "[info]Port(0x%x) start to disc(0x%x) with count(0x%x)", - unf_lport->port_id, loop_map[alpa_index], i); - - /* Check whether need delay to send PLOGI or not */ - loop_id = loop_map[alpa_index]; - unf_login_with_loop_node(unf_lport, (u32)loop_id); - } - - return RETURN_OK; -} - -u32 unf_disc_start(void *lport) -{ - /* - * Call by: - * 1. Enter Private Loop Login - * 2. Analysis RSCN payload - * 3. SCR callback - * * - * Doing: - * Fabric/Public Loop: Send GID_PT - * Private Loop: (delay to) send PLOGI or send LOGO immediately - * P2P: do nothing - */ - struct unf_lport *unf_lport = (struct unf_lport *)lport; - struct unf_rport *unf_rport = NULL; - struct unf_disc *disc = NULL; - struct unf_cm_event_report *event = NULL; - u32 ret = RETURN_OK; - ulong flag = 0; - enum unf_act_topo act_topo = UNF_ACT_TOP_UNKNOWN; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - act_topo = unf_lport->act_topo; - disc = &unf_lport->disc; - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "[info]LOGIN: Port(0x%x) with topo(0x%x) begin to discovery", - unf_lport->port_id, act_topo); - - if (act_topo == UNF_ACT_TOP_P2P_FABRIC || - act_topo == UNF_ACT_TOP_PUBLIC_LOOP) { - /* 1. Fabric or Public Loop Topology: for directory server */ - unf_rport = unf_get_rport_by_nport_id(unf_lport, - UNF_FC_FID_DIR_SERV); /* 0xfffffc */ - if (!unf_rport) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) unable to get SNS RPort(0xfffffc)", - unf_lport->port_id); - - unf_rport = unf_rport_get_free_and_init(unf_lport, UNF_PORT_TYPE_FC, - UNF_FC_FID_DIR_SERV); - if (!unf_rport) - return UNF_RETURN_ERROR; - - unf_rport->nport_id = UNF_FC_FID_DIR_SERV; - } - - spin_lock_irqsave(&disc->rport_busy_pool_lock, flag); - unf_set_disc_state(disc, UNF_DISC_ST_START); /* disc start */ - unf_disc_state_ma(unf_lport, UNF_EVENT_DISC_NORMAL_ENTER); - spin_unlock_irqrestore(&disc->rport_busy_pool_lock, flag); - - /* - * NOTE: Send GID_PT - * The Name Server shall, when it receives a GID_PT request, - * return all Port Identifiers having registered support for the - * specified Port Type. One or more Port Identifiers, having - * registered as the specified Port Type, are returned. - */ - ret = unf_send_gid_pt(unf_lport, unf_rport); - if (ret != RETURN_OK) - unf_disc_error_recovery(unf_lport); - } else if (act_topo == UNF_ACT_TOP_PRIVATE_LOOP) { - /* Private Loop: to thread process */ - event = unf_get_one_event_node(unf_lport); - FC_CHECK_RETURN_VALUE(event, UNF_RETURN_ERROR); - - event->lport = unf_lport; - event->event_asy_flag = UNF_EVENT_ASYN; - event->unf_event_task = unf_discover_private_loop; - event->para_in = (void *)unf_lport; - - unf_post_one_event_node(unf_lport, event); - } else { - /* P2P toplogy mode: Do nothing */ - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x) with topo(0x%x) need do nothing", - unf_lport->port_id, act_topo); - } - - return ret; -} - -static u32 unf_disc_stop(void *lport) -{ - /* Call by GID_ACC processer */ - struct unf_lport *unf_lport = NULL; - struct unf_lport *root_lport = NULL; - struct unf_rport *sns_port = NULL; - struct unf_disc_rport *disc_rport = NULL; - struct unf_disc *disc = NULL; - struct unf_disc *root_disc = NULL; - struct list_head *node = NULL; - ulong flag = 0; - u32 ret = RETURN_OK; - u32 nport_id = 0; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - - unf_lport = (struct unf_lport *)lport; - disc = &unf_lport->disc; - root_lport = (struct unf_lport *)unf_lport->root_lport; - root_disc = &root_lport->disc; - - /* Get R_Port for Directory server */ - sns_port = unf_get_rport_by_nport_id(unf_lport, UNF_FC_FID_DIR_SERV); - if (!sns_port) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) find fabric RPort(0xfffffc) failed", - unf_lport->port_id); - - return UNF_RETURN_ERROR; - } - - /* for R_Port from disc pool busy list */ - spin_lock_irqsave(&disc->rport_busy_pool_lock, flag); - if (list_empty(&disc->disc_rport_mgr.list_disc_rports_busy)) { - spin_unlock_irqrestore(&disc->rport_busy_pool_lock, flag); - return RETURN_OK; - } - - node = UNF_OS_LIST_NEXT(&disc->disc_rport_mgr.list_disc_rports_busy); - do { - /* Delete from Disc busy list */ - disc_rport = list_entry(node, struct unf_disc_rport, entry_rport); - nport_id = disc_rport->nport_id; - list_del_init(node); - spin_unlock_irqrestore(&disc->rport_busy_pool_lock, flag); - - /* Add back to (free) Disc R_Port pool (list) */ - spin_lock_irqsave(&root_disc->rport_busy_pool_lock, flag); - list_add_tail(node, &root_disc->disc_rport_mgr.list_disc_rports_pool); - spin_unlock_irqrestore(&root_disc->rport_busy_pool_lock, flag); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "Port(0x%x_0x%x) remove nportid:0x%x from rportbusy list", - unf_lport->port_id, unf_lport->nport_id, disc_rport->nport_id); - /* Send GNN_ID to Name Server */ - ret = unf_get_and_post_disc_event(unf_lport, sns_port, nport_id, - UNF_DISC_GET_NODE_NAME); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) add discovery event(0x%x) failed Rport(0x%x)", - unf_lport->nport_id, UNF_DISC_GET_NODE_NAME, nport_id); - - /* NOTE: go to next stage */ - unf_rcv_gnn_id_rsp_unknown(unf_lport, sns_port, nport_id); - } - - spin_lock_irqsave(&disc->rport_busy_pool_lock, flag); - node = UNF_OS_LIST_NEXT(&disc->disc_rport_mgr.list_disc_rports_busy); - } while (node != &disc->disc_rport_mgr.list_disc_rports_busy); - spin_unlock_irqrestore(&disc->rport_busy_pool_lock, flag); - - return ret; -} - -static u32 unf_init_rport_pool(struct unf_lport *lport) -{ - struct unf_rport_pool *rport_pool = NULL; - struct unf_rport *unf_rport = NULL; - u32 ret = RETURN_OK; - u32 i = 0; - u32 bitmap_cnt = 0; - ulong flag = 0; - u32 max_login = 0; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - - /* Init RPort Pool info */ - rport_pool = &lport->rport_pool; - max_login = lport->low_level_func.lport_cfg_items.max_login; - rport_pool->rport_pool_completion = NULL; - rport_pool->rport_pool_count = max_login; - spin_lock_init(&rport_pool->rport_free_pool_lock); - INIT_LIST_HEAD(&rport_pool->list_rports_pool); /* free RPort pool */ - - /* 1. Alloc RPort Pool buffer/resource (memory) */ - rport_pool->rport_pool_add = vmalloc((size_t)(max_login * sizeof(struct unf_rport))); - if (!rport_pool->rport_pool_add) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) allocate RPort(s) resource failed", lport->port_id); - - return UNF_RETURN_ERROR; - } - memset(rport_pool->rport_pool_add, 0, (max_login * sizeof(struct unf_rport))); - - /* 2. Alloc R_Port Pool bitmap */ - bitmap_cnt = (lport->low_level_func.support_max_rport) / BITS_PER_LONG + 1; - rport_pool->rpi_bitmap = vmalloc((size_t)(bitmap_cnt * sizeof(ulong))); - if (!rport_pool->rpi_bitmap) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) allocate RPort Bitmap failed", lport->port_id); - - vfree(rport_pool->rport_pool_add); - rport_pool->rport_pool_add = NULL; - return UNF_RETURN_ERROR; - } - memset(rport_pool->rpi_bitmap, 0, (bitmap_cnt * sizeof(ulong))); - - /* 3. Rport resource Management: Add Rports (buffer) to Rport Pool List - */ - unf_rport = (struct unf_rport *)(rport_pool->rport_pool_add); - spin_lock_irqsave(&rport_pool->rport_free_pool_lock, flag); - for (i = 0; i < rport_pool->rport_pool_count; i++) { - spin_lock_init(&unf_rport->rport_state_lock); - list_add_tail(&unf_rport->entry_rport, &rport_pool->list_rports_pool); - sema_init(&unf_rport->task_sema, 0); - unf_rport++; - } - spin_unlock_irqrestore(&rport_pool->rport_free_pool_lock, flag); - - return ret; -} - -static void unf_free_rport_pool(struct unf_lport *lport) -{ - struct unf_rport_pool *rport_pool = NULL; - bool wait = false; - ulong flag = 0; - u32 remain = 0; - u64 timeout = 0; - u32 max_login = 0; - u32 i; - struct unf_rport *unf_rport = NULL; - struct completion rport_pool_completion; - - init_completion(&rport_pool_completion); - FC_CHECK_RETURN_VOID(lport); - - rport_pool = &lport->rport_pool; - max_login = lport->low_level_func.lport_cfg_items.max_login; - - spin_lock_irqsave(&rport_pool->rport_free_pool_lock, flag); - if (rport_pool->rport_pool_count != max_login) { - rport_pool->rport_pool_completion = &rport_pool_completion; - remain = max_login - rport_pool->rport_pool_count; - wait = true; - } - spin_unlock_irqrestore(&rport_pool->rport_free_pool_lock, flag); - - if (wait) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]Port(0x%x) begin to wait for RPort pool completion, remain(0x%x)", - lport->port_id, remain); - - unf_show_all_rport(lport); - - timeout = wait_for_completion_timeout(rport_pool->rport_pool_completion, - msecs_to_jiffies(UNF_OS_REMOVE_CARD_TIMEOUT)); - if (timeout == 0) - unf_cm_mark_dirty_mem(lport, UNF_LPORT_DIRTY_FLAG_RPORT_POOL_DIRTY); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]Port(0x%x) wait for RPort pool completion end", - lport->port_id); - - spin_lock_irqsave(&rport_pool->rport_free_pool_lock, flag); - rport_pool->rport_pool_completion = NULL; - spin_unlock_irqrestore(&rport_pool->rport_free_pool_lock, flag); - } - - unf_rport = (struct unf_rport *)(rport_pool->rport_pool_add); - for (i = 0; i < rport_pool->rport_pool_count; i++) { - if (!unf_rport) - break; - unf_rport++; - } - - if ((lport->dirty_flag & UNF_LPORT_DIRTY_FLAG_RPORT_POOL_DIRTY) == 0) { - vfree(rport_pool->rport_pool_add); - rport_pool->rport_pool_add = NULL; - vfree(rport_pool->rpi_bitmap); - rport_pool->rpi_bitmap = NULL; - } -} - -static void unf_init_rscn_node(struct unf_port_id_page *port_id_page) -{ - FC_CHECK_RETURN_VOID(port_id_page); - - port_id_page->addr_format = 0; - port_id_page->event_qualifier = 0; - port_id_page->reserved = 0; - port_id_page->port_id_area = 0; - port_id_page->port_id_domain = 0; - port_id_page->port_id_port = 0; -} - -struct unf_port_id_page *unf_get_free_rscn_node(void *rscn_mg) -{ - /* Call by Save RSCN Port_ID */ - struct unf_rscn_mgr *rscn_mgr = NULL; - struct unf_port_id_page *port_id_node = NULL; - struct list_head *list_node = NULL; - ulong flag = 0; - - FC_CHECK_RETURN_VALUE(rscn_mg, NULL); - rscn_mgr = (struct unf_rscn_mgr *)rscn_mg; - - spin_lock_irqsave(&rscn_mgr->rscn_id_list_lock, flag); - if (list_empty(&rscn_mgr->list_free_rscn_page)) { - FC_DRV_PRINT(UNF_LOG_EQUIP_ATT, UNF_WARN, - "[warn]No RSCN node anymore"); - - spin_unlock_irqrestore(&rscn_mgr->rscn_id_list_lock, flag); - return NULL; - } - - /* Get from list_free_RSCN_page */ - list_node = UNF_OS_LIST_NEXT(&rscn_mgr->list_free_rscn_page); - list_del(list_node); - rscn_mgr->free_rscn_count--; - port_id_node = list_entry(list_node, struct unf_port_id_page, list_node_rscn); - unf_init_rscn_node(port_id_node); - spin_unlock_irqrestore(&rscn_mgr->rscn_id_list_lock, flag); - - return port_id_node; -} - -static void unf_release_rscn_node(void *rscn_mg, void *port_id_node) -{ - /* Call by RSCN GID_ACC */ - struct unf_rscn_mgr *rscn_mgr = NULL; - struct unf_port_id_page *port_id_page = NULL; - ulong flag = 0; - - FC_CHECK_RETURN_VOID(rscn_mg); - FC_CHECK_RETURN_VOID(port_id_node); - rscn_mgr = (struct unf_rscn_mgr *)rscn_mg; - port_id_page = (struct unf_port_id_page *)port_id_node; - - /* Back to list_free_RSCN_page */ - spin_lock_irqsave(&rscn_mgr->rscn_id_list_lock, flag); - rscn_mgr->free_rscn_count++; - unf_init_rscn_node(port_id_page); - list_add_tail(&port_id_page->list_node_rscn, &rscn_mgr->list_free_rscn_page); - spin_unlock_irqrestore(&rscn_mgr->rscn_id_list_lock, flag); -} - -static u32 unf_init_rscn_pool(struct unf_lport *lport) -{ - struct unf_rscn_mgr *rscn_mgr = NULL; - struct unf_port_id_page *port_id_page = NULL; - u32 ret = RETURN_OK; - u32 i = 0; - ulong flag = 0; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - rscn_mgr = &lport->disc.rscn_mgr; - - /* Get RSCN Pool buffer */ - rscn_mgr->rscn_pool_add = vmalloc(UNF_LIST_RSCN_PAGE_CNT * sizeof(struct unf_port_id_page)); - if (!rscn_mgr->rscn_pool_add) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[warn]Port(0x%x) allocate RSCN pool failed", lport->port_id); - - return UNF_RETURN_ERROR; - } - memset(rscn_mgr->rscn_pool_add, 0, - UNF_LIST_RSCN_PAGE_CNT * sizeof(struct unf_port_id_page)); - - spin_lock_irqsave(&rscn_mgr->rscn_id_list_lock, flag); - port_id_page = (struct unf_port_id_page *)(rscn_mgr->rscn_pool_add); - for (i = 0; i < UNF_LIST_RSCN_PAGE_CNT; i++) { - /* Add tail to list_free_RSCN_page */ - list_add_tail(&port_id_page->list_node_rscn, &rscn_mgr->list_free_rscn_page); - - rscn_mgr->free_rscn_count++; - port_id_page++; - } - spin_unlock_irqrestore(&rscn_mgr->rscn_id_list_lock, flag); - - return ret; -} - -static void unf_freerscn_pool(struct unf_lport *lport) -{ - struct unf_disc *disc = NULL; - - FC_CHECK_RETURN_VOID(lport); - - disc = &lport->disc; - if (disc->rscn_mgr.rscn_pool_add) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, - UNF_INFO, "[info]Port(0x%x) free RSCN pool", lport->nport_id); - - vfree(disc->rscn_mgr.rscn_pool_add); - disc->rscn_mgr.rscn_pool_add = NULL; - } -} - -static u32 unf_init_rscn_mgr(struct unf_lport *lport) -{ - struct unf_rscn_mgr *rscn_mgr = NULL; - u32 ret = RETURN_OK; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - rscn_mgr = &lport->disc.rscn_mgr; - - INIT_LIST_HEAD(&rscn_mgr->list_free_rscn_page); /* free RSCN page list */ - INIT_LIST_HEAD(&rscn_mgr->list_using_rscn_page); /* busy RSCN page list */ - spin_lock_init(&rscn_mgr->rscn_id_list_lock); - rscn_mgr->free_rscn_count = 0; - rscn_mgr->unf_get_free_rscn_node = unf_get_free_rscn_node; - rscn_mgr->unf_release_rscn_node = unf_release_rscn_node; - - ret = unf_init_rscn_pool(lport); - return ret; -} - -static void unf_destroy_rscn_mngr(struct unf_lport *lport) -{ - struct unf_rscn_mgr *rscn_mgr = NULL; - - FC_CHECK_RETURN_VOID(lport); - rscn_mgr = &lport->disc.rscn_mgr; - - rscn_mgr->free_rscn_count = 0; - rscn_mgr->unf_get_free_rscn_node = NULL; - rscn_mgr->unf_release_rscn_node = NULL; - - unf_freerscn_pool(lport); -} - -static u32 unf_init_disc_rport_pool(struct unf_lport *lport) -{ - struct unf_disc_rport_mg *disc_mgr = NULL; - struct unf_disc_rport *disc_rport = NULL; - u32 i = 0; - u32 max_log_in = 0; - ulong flag = 0; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - max_log_in = lport->low_level_func.lport_cfg_items.max_login; - disc_mgr = &lport->disc.disc_rport_mgr; - - /* Alloc R_Port Disc Pool buffer */ - disc_mgr->disc_pool_add = - vmalloc(max_log_in * sizeof(struct unf_disc_rport)); - if (!disc_mgr->disc_pool_add) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[warn]Port(0x%x) allocate disc RPort pool failed", lport->port_id); - - return UNF_RETURN_ERROR; - } - memset(disc_mgr->disc_pool_add, 0, (max_log_in * sizeof(struct unf_disc_rport))); - - /* Add R_Port to (free) DISC R_Port Pool */ - spin_lock_irqsave(&lport->disc.rport_busy_pool_lock, flag); - disc_rport = (struct unf_disc_rport *)(disc_mgr->disc_pool_add); - for (i = 0; i < max_log_in; i++) { - /* Add tail to list_disc_Rport_pool */ - list_add_tail(&disc_rport->entry_rport, &disc_mgr->list_disc_rports_pool); - - disc_rport++; - } - spin_unlock_irqrestore(&lport->disc.rport_busy_pool_lock, flag); - - return RETURN_OK; -} - -static void unf_free_disc_rport_pool(struct unf_lport *lport) -{ - struct unf_disc *disc = NULL; - - FC_CHECK_RETURN_VOID(lport); - - disc = &lport->disc; - if (disc->disc_rport_mgr.disc_pool_add) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, - UNF_INFO, "[info]Port(0x%x) free disc RPort pool", lport->port_id); - - vfree(disc->disc_rport_mgr.disc_pool_add); - disc->disc_rport_mgr.disc_pool_add = NULL; - } -} - -int unf_discover_port_info(void *arg_in) -{ - struct unf_disc_gs_event_info *disc_gs_info = NULL; - u32 ret = UNF_RETURN_ERROR; - struct unf_lport *unf_lport = NULL; - struct unf_rport *unf_rport = NULL; - - FC_CHECK_RETURN_VALUE(arg_in, UNF_RETURN_ERROR); - - disc_gs_info = (struct unf_disc_gs_event_info *)arg_in; - unf_lport = (struct unf_lport *)disc_gs_info->lport; - unf_rport = (struct unf_rport *)disc_gs_info->rport; - - switch (disc_gs_info->type) { - case UNF_DISC_GET_PORT_NAME: - ret = unf_send_gpn_id(unf_lport, unf_rport, disc_gs_info->rport_id); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) send GPN_ID failed RPort(0x%x)", - unf_lport->nport_id, disc_gs_info->rport_id); - unf_rcv_gpn_id_rsp_unknown(unf_lport, disc_gs_info->rport_id); - } - break; - case UNF_DISC_GET_FEATURE: - ret = unf_send_gff_id(unf_lport, unf_rport, disc_gs_info->rport_id); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) send GFF_ID failed to get RPort(0x%x)'s feature", - unf_lport->port_id, disc_gs_info->rport_id); - - unf_rcv_gff_id_rsp_unknown(unf_lport, disc_gs_info->rport_id); - } - break; - case UNF_DISC_GET_NODE_NAME: - ret = unf_send_gnn_id(unf_lport, unf_rport, disc_gs_info->rport_id); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) GNN_ID send failed with NPort ID(0x%x)", - unf_lport->port_id, disc_gs_info->rport_id); - - /* NOTE: Continue to next stage */ - unf_rcv_gnn_id_rsp_unknown(unf_lport, unf_rport, disc_gs_info->rport_id); - } - break; - default: - FC_DRV_PRINT(UNF_LOG_NORMAL, UNF_ERR, - "[err]Send GS packet type(0x%x) is unknown", disc_gs_info->type); - } - - kfree(disc_gs_info); - - return (int)ret; -} - -u32 unf_get_and_post_disc_event(void *lport, void *sns_port, u32 nport_id, - enum unf_disc_type type) -{ - struct unf_disc_gs_event_info *disc_gs_info = NULL; - ulong flag = 0; - struct unf_lport *root_lport = NULL; - struct unf_lport *unf_lport = NULL; - struct unf_disc_manage_info *disc_info = NULL; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(sns_port, UNF_RETURN_ERROR); - - unf_lport = (struct unf_lport *)lport; - - if (unf_lport->link_up == UNF_PORT_LINK_DOWN) - return RETURN_OK; - - root_lport = unf_lport->root_lport; - disc_info = &root_lport->disc.disc_thread_info; - - if (disc_info->thread_exit) - return RETURN_OK; - - disc_gs_info = kmalloc(sizeof(struct unf_disc_gs_event_info), GFP_ATOMIC); - if (!disc_gs_info) - return UNF_RETURN_ERROR; - - disc_gs_info->type = type; - disc_gs_info->lport = unf_lport; - disc_gs_info->rport = sns_port; - disc_gs_info->rport_id = nport_id; - - INIT_LIST_HEAD(&disc_gs_info->list_entry); - - spin_lock_irqsave(&disc_info->disc_event_list_lock, flag); - list_add_tail(&disc_gs_info->list_entry, &disc_info->list_head); - spin_unlock_irqrestore(&disc_info->disc_event_list_lock, flag); - wake_up_process(disc_info->thread); - return RETURN_OK; -} - -static int unf_disc_event_process(void *arg) -{ - struct list_head *node = NULL; - struct unf_disc_gs_event_info *disc_gs_info = NULL; - ulong flags = 0; - struct unf_disc *disc = (struct unf_disc *)arg; - struct unf_disc_manage_info *disc_info = &disc->disc_thread_info; - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_INFO, - "Port(0x%x) enter discovery thread.", disc->lport->port_id); - - while (!kthread_should_stop()) { - if (disc_info->thread_exit) - break; - - spin_lock_irqsave(&disc_info->disc_event_list_lock, flags); - if ((list_empty(&disc_info->list_head)) || - (atomic_read(&disc_info->disc_contrl_size) == 0)) { - spin_unlock_irqrestore(&disc_info->disc_event_list_lock, flags); - - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout((long)msecs_to_jiffies(UNF_S_TO_MS)); - } else { - node = UNF_OS_LIST_NEXT(&disc_info->list_head); - list_del_init(node); - disc_gs_info = list_entry(node, struct unf_disc_gs_event_info, list_entry); - spin_unlock_irqrestore(&disc_info->disc_event_list_lock, flags); - unf_discover_port_info(disc_gs_info); - } - } - FC_DRV_PRINT(UNF_LOG_EVENT, UNF_MAJOR, - "Port(0x%x) discovery thread over.", disc->lport->port_id); - - return RETURN_OK; -} - -void unf_flush_disc_event(void *disc, void *vport) -{ - struct unf_disc *unf_disc = (struct unf_disc *)disc; - struct unf_disc_manage_info *disc_info = NULL; - struct list_head *list = NULL; - struct list_head *list_tmp = NULL; - struct unf_disc_gs_event_info *disc_gs_info = NULL; - ulong flag = 0; - - FC_CHECK_RETURN_VOID(disc); - - disc_info = &unf_disc->disc_thread_info; - - spin_lock_irqsave(&disc_info->disc_event_list_lock, flag); - list_for_each_safe(list, list_tmp, &disc_info->list_head) { - disc_gs_info = list_entry(list, struct unf_disc_gs_event_info, list_entry); - - if (!vport || disc_gs_info->lport == vport) { - list_del_init(&disc_gs_info->list_entry); - kfree(disc_gs_info); - } - } - - if (!vport) - atomic_set(&disc_info->disc_contrl_size, UNF_MAX_GS_SEND_NUM); - spin_unlock_irqrestore(&disc_info->disc_event_list_lock, flag); -} - -void unf_disc_ctrl_size_inc(void *lport, u32 cmnd) -{ - struct unf_lport *unf_lport = NULL; - - FC_CHECK_RETURN_VOID(lport); - - unf_lport = (struct unf_lport *)lport; - unf_lport = unf_lport->root_lport; - FC_CHECK_RETURN_VOID(unf_lport); - - if (atomic_read(&unf_lport->disc.disc_thread_info.disc_contrl_size) == - UNF_MAX_GS_SEND_NUM) - return; - - if (cmnd == NS_GPN_ID || cmnd == NS_GNN_ID || cmnd == NS_GFF_ID) - atomic_inc(&unf_lport->disc.disc_thread_info.disc_contrl_size); -} - -void unf_destroy_disc_thread(void *disc) -{ - struct unf_disc_manage_info *disc_info = NULL; - struct unf_disc *unf_disc = (struct unf_disc *)disc; - - FC_CHECK_RETURN_VOID(unf_disc); - - disc_info = &unf_disc->disc_thread_info; - - disc_info->thread_exit = true; - unf_flush_disc_event(unf_disc, NULL); - - wake_up_process(disc_info->thread); - kthread_stop(disc_info->thread); - disc_info->thread = NULL; - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "Port(0x%x) destroy discovery thread succeed.", - unf_disc->lport->port_id); -} - -u32 unf_crerate_disc_thread(void *disc) -{ - struct unf_disc_manage_info *disc_info = NULL; - struct unf_disc *unf_disc = (struct unf_disc *)disc; - - FC_CHECK_RETURN_VALUE(unf_disc, UNF_RETURN_ERROR); - - /* If the thread cannot be found, apply for a new thread. */ - disc_info = &unf_disc->disc_thread_info; - - memset(disc_info, 0, sizeof(struct unf_disc_manage_info)); - - INIT_LIST_HEAD(&disc_info->list_head); - spin_lock_init(&disc_info->disc_event_list_lock); - atomic_set(&disc_info->disc_contrl_size, UNF_MAX_GS_SEND_NUM); - - disc_info->thread_exit = false; - disc_info->thread = kthread_create(unf_disc_event_process, unf_disc, "%x_DiscT", - unf_disc->lport->port_id); - - if (IS_ERR(disc_info->thread) || !disc_info->thread) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "Port(0x%x) creat discovery thread(0x%p) unsuccessful.", - unf_disc->lport->port_id, disc_info->thread); - - return UNF_RETURN_ERROR; - } - - wake_up_process(disc_info->thread); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_INFO, - "Port(0x%x) creat discovery thread succeed.", unf_disc->lport->port_id); - - return RETURN_OK; -} - -void unf_disc_ref_cnt_dec(struct unf_disc *disc) -{ - ulong flag = 0; - - FC_CHECK_RETURN_VOID(disc); - - spin_lock_irqsave(&disc->rport_busy_pool_lock, flag); - if (atomic_dec_and_test(&disc->disc_ref_cnt)) { - if (disc->disc_completion) - complete(disc->disc_completion); - } - spin_unlock_irqrestore(&disc->rport_busy_pool_lock, flag); -} - -void unf_wait_disc_complete(struct unf_lport *lport) -{ - struct unf_disc *disc = NULL; - bool wait = false; - ulong flag = 0; - u32 ret = UNF_RETURN_ERROR; - u64 time_out = 0; - - struct completion disc_completion; - - init_completion(&disc_completion); - disc = &lport->disc; - - UNF_DELAYED_WORK_SYNC(ret, (lport->port_id), (&disc->disc_work), - "Disc_work"); - if (ret == RETURN_OK) - unf_disc_ref_cnt_dec(disc); - - spin_lock_irqsave(&disc->rport_busy_pool_lock, flag); - if (atomic_read(&disc->disc_ref_cnt) != 0) { - disc->disc_completion = &disc_completion; - wait = true; - } - spin_unlock_irqrestore(&disc->rport_busy_pool_lock, flag); - - if (wait) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]Port(0x%x) begin to wait for discover completion", - lport->port_id); - - time_out = - wait_for_completion_timeout(disc->disc_completion, - msecs_to_jiffies(UNF_OS_REMOVE_CARD_TIMEOUT)); - if (time_out == 0) - unf_cm_mark_dirty_mem(lport, UNF_LPORT_DIRTY_FLAG_DISC_DIRTY); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]Port(0x%x) wait for discover completion end", lport->port_id); - - spin_lock_irqsave(&disc->rport_busy_pool_lock, flag); - disc->disc_completion = NULL; - spin_unlock_irqrestore(&disc->rport_busy_pool_lock, flag); - } -} - -void unf_disc_mgr_destroy(void *lport) -{ - struct unf_disc *disc = NULL; - struct unf_lport *unf_lport = NULL; - - FC_CHECK_RETURN_VOID(lport); - unf_lport = (struct unf_lport *)lport; - - disc = &unf_lport->disc; - disc->retry_count = 0; - disc->disc_temp.unf_disc_start = NULL; - disc->disc_temp.unf_disc_stop = NULL; - disc->disc_temp.unf_disc_callback = NULL; - - unf_free_disc_rport_pool(unf_lport); - unf_destroy_rscn_mngr(unf_lport); - unf_wait_disc_complete(unf_lport); - - if (unf_lport->root_lport != unf_lport) - return; - - unf_destroy_disc_thread(disc); - unf_free_rport_pool(unf_lport); - unf_lport->destroy_step = UNF_LPORT_DESTROY_STEP_6_DESTROY_DISC_MGR; -} - -void unf_disc_error_recovery(void *lport) -{ - struct unf_rport *unf_rport = NULL; - struct unf_disc *disc = NULL; - ulong delay = 0; - ulong flag = 0; - u32 ret = UNF_RETURN_ERROR; - struct unf_lport *unf_lport = NULL; - - FC_CHECK_RETURN_VOID(lport); - - unf_lport = (struct unf_lport *)lport; - disc = &unf_lport->disc; - - unf_rport = unf_get_rport_by_nport_id(unf_lport, UNF_FC_FID_DIR_SERV); - if (!unf_rport) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, - UNF_WARN, "[warn]Port(0x%x) find RPort failed", unf_lport->port_id); - return; - } - - spin_lock_irqsave(&disc->rport_busy_pool_lock, flag); - - /* Delay work is pending */ - if (delayed_work_pending(&disc->disc_work)) { - spin_unlock_irqrestore(&disc->rport_busy_pool_lock, flag); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x) disc_work is running and do nothing", - unf_lport->port_id); - return; - } - - /* Continue to retry */ - if (disc->retry_count < disc->max_retry_count) { - disc->retry_count++; - delay = (ulong)unf_lport->ed_tov; - if (queue_delayed_work(unf_wq, &disc->disc_work, - (ulong)msecs_to_jiffies((u32)delay))) - atomic_inc(&disc->disc_ref_cnt); - spin_unlock_irqrestore(&disc->rport_busy_pool_lock, flag); - } else { - /* Go to next stage */ - if (disc->states == UNF_DISC_ST_GIDPT_WAIT) { - /* GID_PT_WAIT --->>> Send GID_FT */ - unf_disc_state_ma(unf_lport, UNF_EVENT_DISC_RETRY_TIMEOUT); - spin_unlock_irqrestore(&disc->rport_busy_pool_lock, flag); - - while ((ret != RETURN_OK) && - (disc->retry_count < disc->max_retry_count)) { - ret = unf_send_gid_ft(unf_lport, unf_rport); - disc->retry_count++; - } - } else if (disc->states == UNF_DISC_ST_GIDFT_WAIT) { - /* GID_FT_WAIT --->>> Send LOGO */ - unf_disc_state_ma(unf_lport, UNF_EVENT_DISC_RETRY_TIMEOUT); - spin_unlock_irqrestore(&disc->rport_busy_pool_lock, flag); - } else { - spin_unlock_irqrestore(&disc->rport_busy_pool_lock, flag); - } - } -} - -enum unf_disc_state unf_disc_stat_start(enum unf_disc_state old_state, - enum unf_disc_event event) -{ - enum unf_disc_state next_state = UNF_DISC_ST_END; - - if (event == UNF_EVENT_DISC_NORMAL_ENTER) - next_state = UNF_DISC_ST_GIDPT_WAIT; - else - next_state = old_state; - - return next_state; -} - -enum unf_disc_state unf_disc_stat_gid_pt_wait(enum unf_disc_state old_state, - enum unf_disc_event event) -{ - enum unf_disc_state next_state = UNF_DISC_ST_END; - - switch (event) { - case UNF_EVENT_DISC_FAILED: - next_state = UNF_DISC_ST_GIDPT_WAIT; - break; - - case UNF_EVENT_DISC_RETRY_TIMEOUT: - next_state = UNF_DISC_ST_GIDFT_WAIT; - break; - - case UNF_EVENT_DISC_SUCCESS: - next_state = UNF_DISC_ST_END; - break; - - case UNF_EVENT_DISC_LINKDOWN: - next_state = UNF_DISC_ST_START; - break; - - default: - next_state = old_state; - break; - } - - return next_state; -} - -enum unf_disc_state unf_disc_stat_gid_ft_wait(enum unf_disc_state old_state, - enum unf_disc_event event) -{ - enum unf_disc_state next_state = UNF_DISC_ST_END; - - switch (event) { - case UNF_EVENT_DISC_FAILED: - next_state = UNF_DISC_ST_GIDFT_WAIT; - break; - - case UNF_EVENT_DISC_RETRY_TIMEOUT: - next_state = UNF_DISC_ST_END; - break; - - case UNF_EVENT_DISC_LINKDOWN: - next_state = UNF_DISC_ST_START; - break; - - case UNF_EVENT_DISC_SUCCESS: - next_state = UNF_DISC_ST_END; - break; - - default: - next_state = old_state; - break; - } - - return next_state; -} - -enum unf_disc_state unf_disc_stat_end(enum unf_disc_state old_state, enum unf_disc_event event) -{ - enum unf_disc_state next_state = UNF_DISC_ST_END; - - if (event == UNF_EVENT_DISC_LINKDOWN) - next_state = UNF_DISC_ST_START; - else - next_state = old_state; - - return next_state; -} - -void unf_disc_state_ma(struct unf_lport *lport, enum unf_disc_event event) -{ - struct unf_disc *disc = NULL; - enum unf_disc_state old_state = UNF_DISC_ST_START; - enum unf_disc_state next_state = UNF_DISC_ST_START; - - FC_CHECK_RETURN_VOID(lport); - - disc = &lport->disc; - old_state = disc->states; - - switch (disc->states) { - case UNF_DISC_ST_START: - next_state = unf_disc_stat_start(old_state, event); - break; - - case UNF_DISC_ST_GIDPT_WAIT: - next_state = unf_disc_stat_gid_pt_wait(old_state, event); - break; - - case UNF_DISC_ST_GIDFT_WAIT: - next_state = unf_disc_stat_gid_ft_wait(old_state, event); - break; - - case UNF_DISC_ST_END: - next_state = unf_disc_stat_end(old_state, event); - break; - - default: - next_state = old_state; - break; - } - - unf_set_disc_state(disc, next_state); -} - -static void unf_lport_disc_timeout(struct work_struct *work) -{ - struct unf_lport *unf_lport = NULL; - struct unf_rport *unf_rport = NULL; - struct unf_disc *disc = NULL; - enum unf_disc_state state = UNF_DISC_ST_END; - ulong flag = 0; - - FC_CHECK_RETURN_VOID(work); - - disc = container_of(work, struct unf_disc, disc_work.work); - if (!disc) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, - UNF_WARN, "[warn]Get discover pointer failed"); - - return; - } - - unf_lport = disc->lport; - if (!unf_lport) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Find Port by discovery work failed"); - - unf_disc_ref_cnt_dec(disc); - return; - } - - spin_lock_irqsave(&disc->rport_busy_pool_lock, flag); - state = disc->states; - spin_unlock_irqrestore(&disc->rport_busy_pool_lock, flag); - - unf_rport = unf_get_rport_by_nport_id(unf_lport, UNF_FC_FID_DIR_SERV); /* 0xfffffc */ - if (!unf_rport) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) find fabric RPort failed", unf_lport->port_id); - - unf_disc_ref_cnt_dec(disc); - return; - } - - switch (state) { - case UNF_DISC_ST_START: - break; - - case UNF_DISC_ST_GIDPT_WAIT: - (void)unf_send_gid_pt(unf_lport, unf_rport); - break; - - case UNF_DISC_ST_GIDFT_WAIT: - (void)unf_send_gid_ft(unf_lport, unf_rport); - break; - - case UNF_DISC_ST_END: - break; - - default: - break; - } - - unf_disc_ref_cnt_dec(disc); -} - -u32 unf_init_disc_mgr(struct unf_lport *lport) -{ - struct unf_disc *disc = NULL; - u32 ret = RETURN_OK; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - - disc = &lport->disc; - disc->max_retry_count = UNF_DISC_RETRY_TIMES; - disc->retry_count = 0; - disc->disc_flag = UNF_DISC_NONE; - INIT_LIST_HEAD(&disc->list_busy_rports); - INIT_LIST_HEAD(&disc->list_delete_rports); - INIT_LIST_HEAD(&disc->list_destroy_rports); - spin_lock_init(&disc->rport_busy_pool_lock); - - disc->disc_rport_mgr.disc_pool_add = NULL; - INIT_LIST_HEAD(&disc->disc_rport_mgr.list_disc_rports_pool); - INIT_LIST_HEAD(&disc->disc_rport_mgr.list_disc_rports_busy); - - disc->disc_completion = NULL; - disc->lport = lport; - INIT_DELAYED_WORK(&disc->disc_work, unf_lport_disc_timeout); - disc->disc_temp.unf_disc_start = unf_disc_start; - disc->disc_temp.unf_disc_stop = unf_disc_stop; - disc->disc_temp.unf_disc_callback = NULL; - atomic_set(&disc->disc_ref_cnt, 0); - - /* Init RSCN Manager */ - ret = unf_init_rscn_mgr(lport); - if (ret != RETURN_OK) - return UNF_RETURN_ERROR; - - if (lport->root_lport != lport) - return ret; - - ret = unf_crerate_disc_thread(disc); - if (ret != RETURN_OK) { - unf_destroy_rscn_mngr(lport); - - return UNF_RETURN_ERROR; - } - - /* Init R_Port free Pool */ - ret = unf_init_rport_pool(lport); - if (ret != RETURN_OK) { - unf_destroy_disc_thread(disc); - unf_destroy_rscn_mngr(lport); - - return UNF_RETURN_ERROR; - } - - /* Init R_Port free disc Pool */ - ret = unf_init_disc_rport_pool(lport); - if (ret != RETURN_OK) { - unf_destroy_disc_thread(disc); - unf_free_rport_pool(lport); - unf_destroy_rscn_mngr(lport); - - return UNF_RETURN_ERROR; - } - - return ret; -} diff --git a/drivers/scsi/spfc/common/unf_disc.h b/drivers/scsi/spfc/common/unf_disc.h deleted file mode 100644 index 7ecad3eec424..000000000000 --- a/drivers/scsi/spfc/common/unf_disc.h +++ /dev/null @@ -1,51 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef UNF_DISC_H -#define UNF_DISC_H - -#include "unf_type.h" - -#define UNF_DISC_RETRY_TIMES 3 -#define UNF_DISC_NONE 0 -#define UNF_DISC_FABRIC 1 -#define UNF_DISC_LOOP 2 - -enum unf_disc_state { - UNF_DISC_ST_START = 0x3000, - UNF_DISC_ST_GIDPT_WAIT, - UNF_DISC_ST_GIDFT_WAIT, - UNF_DISC_ST_END -}; - -enum unf_disc_event { - UNF_EVENT_DISC_NORMAL_ENTER = 0x8000, - UNF_EVENT_DISC_FAILED = 0x8001, - UNF_EVENT_DISC_SUCCESS = 0x8002, - UNF_EVENT_DISC_RETRY_TIMEOUT = 0x8003, - UNF_EVENT_DISC_LINKDOWN = 0x8004 -}; - -enum unf_disc_type { - UNF_DISC_GET_PORT_NAME = 0, - UNF_DISC_GET_NODE_NAME, - UNF_DISC_GET_FEATURE -}; - -struct unf_disc_gs_event_info { - void *lport; - void *rport; - u32 rport_id; - enum unf_disc_type type; - struct list_head list_entry; -}; - -u32 unf_get_and_post_disc_event(void *lport, void *sns_port, u32 nport_id, - enum unf_disc_type type); - -void unf_flush_disc_event(void *disc, void *vport); -void unf_disc_ctrl_size_inc(void *lport, u32 cmnd); -void unf_disc_error_recovery(void *lport); -void unf_disc_mgr_destroy(void *lport); - -#endif diff --git a/drivers/scsi/spfc/common/unf_event.c b/drivers/scsi/spfc/common/unf_event.c deleted file mode 100644 index cf51c31ca4a3..000000000000 --- a/drivers/scsi/spfc/common/unf_event.c +++ /dev/null @@ -1,517 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#include "unf_event.h" -#include "unf_log.h" -#include "unf_common.h" -#include "unf_lport.h" - -struct unf_event_list fc_event_list; -struct unf_global_event_queue global_event_queue; - -/* Max global event node */ -#define UNF_MAX_GLOBAL_ENENT_NODE 24 - -u32 unf_init_event_msg(struct unf_lport *lport) -{ - struct unf_event_mgr *event_mgr = NULL; - struct unf_cm_event_report *event_node = NULL; - u32 ret = RETURN_OK; - u32 index = 0; - ulong flag = 0; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - event_mgr = &lport->event_mgr; - - /* Get and Initial Event Node resource */ - event_mgr->mem_add = vmalloc((size_t)event_mgr->free_event_count * - sizeof(struct unf_cm_event_report)); - if (!event_mgr->mem_add) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[warn]Port(0x%x) allocate event manager failed", - lport->port_id); - - return UNF_RETURN_ERROR; - } - memset(event_mgr->mem_add, 0, - ((size_t)event_mgr->free_event_count * sizeof(struct unf_cm_event_report))); - - event_node = (struct unf_cm_event_report *)(event_mgr->mem_add); - - spin_lock_irqsave(&event_mgr->port_event_lock, flag); - for (index = 0; index < event_mgr->free_event_count; index++) { - INIT_LIST_HEAD(&event_node->list_entry); - list_add_tail(&event_node->list_entry, &event_mgr->list_free_event); - event_node++; - } - spin_unlock_irqrestore(&event_mgr->port_event_lock, flag); - - return ret; -} - -static void unf_del_event_center_fun_op(struct unf_lport *lport) -{ - struct unf_event_mgr *event_mgr = NULL; - - FC_CHECK_RETURN_VOID(lport); - - event_mgr = &lport->event_mgr; - event_mgr->unf_get_free_event_func = NULL; - event_mgr->unf_release_event = NULL; - event_mgr->unf_post_event_func = NULL; -} - -void unf_init_event_node(struct unf_cm_event_report *event_node) -{ - FC_CHECK_RETURN_VOID(event_node); - - event_node->event = UNF_EVENT_TYPE_REQUIRE; - event_node->event_asy_flag = UNF_EVENT_ASYN; - event_node->delay_times = 0; - event_node->para_in = NULL; - event_node->para_out = NULL; - event_node->result = 0; - event_node->lport = NULL; - event_node->unf_event_task = NULL; -} - -struct unf_cm_event_report *unf_get_free_event_node(void *lport) -{ - struct unf_event_mgr *event_mgr = NULL; - struct unf_cm_event_report *event_node = NULL; - struct list_head *list_node = NULL; - struct unf_lport *unf_lport = NULL; - ulong flags = 0; - - FC_CHECK_RETURN_VALUE(lport, NULL); - unf_lport = (struct unf_lport *)lport; - unf_lport = unf_lport->root_lport; - - if (unlikely(atomic_read(&unf_lport->lport_no_operate_flag) == UNF_LPORT_NOP)) - return NULL; - - event_mgr = &unf_lport->event_mgr; - - spin_lock_irqsave(&event_mgr->port_event_lock, flags); - if (list_empty(&event_mgr->list_free_event)) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[warn]Port(0x%x) have no event node anymore", - unf_lport->port_id); - - spin_unlock_irqrestore(&event_mgr->port_event_lock, flags); - return NULL; - } - - list_node = UNF_OS_LIST_NEXT(&event_mgr->list_free_event); - list_del(list_node); - event_mgr->free_event_count--; - event_node = list_entry(list_node, struct unf_cm_event_report, list_entry); - - unf_init_event_node(event_node); - spin_unlock_irqrestore(&event_mgr->port_event_lock, flags); - - return event_node; -} - -void unf_post_event(void *lport, void *event_node) -{ - struct unf_cm_event_report *cm_event_node = NULL; - struct unf_chip_manage_info *card_thread_info = NULL; - struct unf_lport *unf_lport = NULL; - ulong flags = 0; - - FC_CHECK_RETURN_VOID(event_node); - cm_event_node = (struct unf_cm_event_report *)event_node; - - /* If null, post to global event center */ - if (!lport) { - spin_lock_irqsave(&fc_event_list.fc_event_list_lock, flags); - fc_event_list.list_num++; - list_add_tail(&cm_event_node->list_entry, &fc_event_list.list_head); - spin_unlock_irqrestore(&fc_event_list.fc_event_list_lock, flags); - - wake_up_process(event_task_thread); - } else { - unf_lport = (struct unf_lport *)lport; - unf_lport = unf_lport->root_lport; - card_thread_info = unf_lport->chip_info; - - /* Post to global event center */ - if (!card_thread_info) { - FC_DRV_PRINT(UNF_LOG_EVENT, UNF_WARN, - "[warn]Port(0x%x) has strange event with type(0x%x)", - unf_lport->nport_id, cm_event_node->event); - - spin_lock_irqsave(&fc_event_list.fc_event_list_lock, flags); - fc_event_list.list_num++; - list_add_tail(&cm_event_node->list_entry, &fc_event_list.list_head); - spin_unlock_irqrestore(&fc_event_list.fc_event_list_lock, flags); - - wake_up_process(event_task_thread); - } else { - spin_lock_irqsave(&card_thread_info->chip_event_list_lock, flags); - card_thread_info->list_num++; - list_add_tail(&cm_event_node->list_entry, &card_thread_info->list_head); - spin_unlock_irqrestore(&card_thread_info->chip_event_list_lock, flags); - - wake_up_process(card_thread_info->thread); - } - } -} - -void unf_check_event_mgr_status(struct unf_event_mgr *event_mgr) -{ - ulong flag = 0; - - FC_CHECK_RETURN_VOID(event_mgr); - - spin_lock_irqsave(&event_mgr->port_event_lock, flag); - if (event_mgr->emg_completion && event_mgr->free_event_count == UNF_MAX_EVENT_NODE) - complete(event_mgr->emg_completion); - - spin_unlock_irqrestore(&event_mgr->port_event_lock, flag); -} - -void unf_release_event(void *lport, void *event_node) -{ - struct unf_event_mgr *event_mgr = NULL; - struct unf_lport *unf_lport = NULL; - struct unf_cm_event_report *cm_event_node = NULL; - ulong flags = 0; - - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(event_node); - - cm_event_node = (struct unf_cm_event_report *)event_node; - unf_lport = (struct unf_lport *)lport; - unf_lport = unf_lport->root_lport; - event_mgr = &unf_lport->event_mgr; - - spin_lock_irqsave(&event_mgr->port_event_lock, flags); - event_mgr->free_event_count++; - unf_init_event_node(cm_event_node); - list_add_tail(&cm_event_node->list_entry, &event_mgr->list_free_event); - spin_unlock_irqrestore(&event_mgr->port_event_lock, flags); - - unf_check_event_mgr_status(event_mgr); -} - -void unf_release_global_event(void *event_node) -{ - ulong flag = 0; - struct unf_cm_event_report *cm_event_node = NULL; - - FC_CHECK_RETURN_VOID(event_node); - cm_event_node = (struct unf_cm_event_report *)event_node; - - unf_init_event_node(cm_event_node); - - spin_lock_irqsave(&global_event_queue.global_event_list_lock, flag); - global_event_queue.list_number++; - list_add_tail(&cm_event_node->list_entry, &global_event_queue.global_event_list); - spin_unlock_irqrestore(&global_event_queue.global_event_list_lock, flag); -} - -u32 unf_init_event_center(void *lport) -{ - struct unf_event_mgr *event_mgr = NULL; - u32 ret = RETURN_OK; - struct unf_lport *unf_lport = NULL; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - unf_lport = (struct unf_lport *)lport; - - /* Initial Disc manager */ - event_mgr = &unf_lport->event_mgr; - event_mgr->free_event_count = UNF_MAX_EVENT_NODE; - event_mgr->unf_get_free_event_func = unf_get_free_event_node; - event_mgr->unf_release_event = unf_release_event; - event_mgr->unf_post_event_func = unf_post_event; - - INIT_LIST_HEAD(&event_mgr->list_free_event); - spin_lock_init(&event_mgr->port_event_lock); - event_mgr->emg_completion = NULL; - - ret = unf_init_event_msg(unf_lport); - - return ret; -} - -void unf_wait_event_mgr_complete(struct unf_event_mgr *event_mgr) -{ - struct unf_event_mgr *event_mgr_temp = NULL; - bool wait = false; - ulong mg_flag = 0; - - struct completion fc_event_completion; - - init_completion(&fc_event_completion); - FC_CHECK_RETURN_VOID(event_mgr); - event_mgr_temp = event_mgr; - - spin_lock_irqsave(&event_mgr_temp->port_event_lock, mg_flag); - if (event_mgr_temp->free_event_count != UNF_MAX_EVENT_NODE) { - event_mgr_temp->emg_completion = &fc_event_completion; - wait = true; - } - spin_unlock_irqrestore(&event_mgr_temp->port_event_lock, mg_flag); - - if (wait) - wait_for_completion(event_mgr_temp->emg_completion); - - spin_lock_irqsave(&event_mgr_temp->port_event_lock, mg_flag); - event_mgr_temp->emg_completion = NULL; - spin_unlock_irqrestore(&event_mgr_temp->port_event_lock, mg_flag); -} - -u32 unf_event_center_destroy(void *lport) -{ - struct unf_event_mgr *event_mgr = NULL; - struct list_head *list = NULL; - struct list_head *list_tmp = NULL; - struct unf_cm_event_report *event_node = NULL; - u32 ret = RETURN_OK; - ulong flag = 0; - ulong list_lock_flag = 0; - struct unf_lport *unf_lport = NULL; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - unf_lport = (struct unf_lport *)lport; - event_mgr = &unf_lport->event_mgr; - - spin_lock_irqsave(&fc_event_list.fc_event_list_lock, list_lock_flag); - if (!list_empty(&fc_event_list.list_head)) { - list_for_each_safe(list, list_tmp, &fc_event_list.list_head) { - event_node = list_entry(list, struct unf_cm_event_report, list_entry); - - if (event_node->lport == unf_lport) { - list_del_init(&event_node->list_entry); - if (event_node->event_asy_flag == UNF_EVENT_SYN) { - event_node->result = UNF_RETURN_ERROR; - complete(&event_node->event_comp); - } - - spin_lock_irqsave(&event_mgr->port_event_lock, flag); - event_mgr->free_event_count++; - list_add_tail(&event_node->list_entry, - &event_mgr->list_free_event); - spin_unlock_irqrestore(&event_mgr->port_event_lock, flag); - } - } - } - spin_unlock_irqrestore(&fc_event_list.fc_event_list_lock, list_lock_flag); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]Port(0x%x) begin to wait event", - unf_lport->port_id); - - unf_wait_event_mgr_complete(event_mgr); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]Port(0x%x) wait event process end", - unf_lport->port_id); - - unf_del_event_center_fun_op(unf_lport); - - vfree(event_mgr->mem_add); - event_mgr->mem_add = NULL; - unf_lport->destroy_step = UNF_LPORT_DESTROY_STEP_3_DESTROY_EVENT_CENTER; - - return ret; -} - -static void unf_procee_asyn_event(struct unf_cm_event_report *event_node) -{ - struct unf_lport *lport = NULL; - u32 ret = UNF_RETURN_ERROR; - - lport = (struct unf_lport *)event_node->lport; - - FC_CHECK_RETURN_VOID(lport); - if (event_node->unf_event_task) { - ret = (u32)event_node->unf_event_task(event_node->para_in, - event_node->para_out); - } - - if (lport->event_mgr.unf_release_event) - lport->event_mgr.unf_release_event(lport, event_node); - - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_EVENT, UNF_WARN, - "[warn]Port(0x%x) handle event(0x%x) failed", - lport->port_id, event_node->event); - } -} - -void unf_handle_event(struct unf_cm_event_report *event_node) -{ - u32 ret = UNF_RETURN_ERROR; - u32 event = 0; - u32 event_asy_flag = UNF_EVENT_ASYN; - - FC_CHECK_RETURN_VOID(event_node); - - event = event_node->event; - event_asy_flag = event_node->event_asy_flag; - - switch (event_asy_flag) { - case UNF_EVENT_SYN: /* synchronous event node */ - case UNF_GLOBAL_EVENT_SYN: - if (event_node->unf_event_task) - ret = (u32)event_node->unf_event_task(event_node->para_in, - event_node->para_out); - - event_node->result = ret; - complete(&event_node->event_comp); - break; - - case UNF_EVENT_ASYN: /* asynchronous event node */ - unf_procee_asyn_event(event_node); - break; - - case UNF_GLOBAL_EVENT_ASYN: - if (event_node->unf_event_task) { - ret = (u32)event_node->unf_event_task(event_node->para_in, - event_node->para_out); - } - - unf_release_global_event(event_node); - - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_EVENT, UNF_WARN, - "[warn]handle global event(0x%x) failed", event); - } - break; - - default: - FC_DRV_PRINT(UNF_LOG_EVENT, UNF_WARN, - "[warn]Unknown event(0x%x)", event); - break; - } -} - -u32 unf_init_global_event_msg(void) -{ - struct unf_cm_event_report *event_node = NULL; - u32 ret = RETURN_OK; - u32 index = 0; - ulong flag = 0; - - INIT_LIST_HEAD(&global_event_queue.global_event_list); - spin_lock_init(&global_event_queue.global_event_list_lock); - global_event_queue.list_number = 0; - - global_event_queue.global_event_add = vmalloc(UNF_MAX_GLOBAL_ENENT_NODE * - sizeof(struct unf_cm_event_report)); - if (!global_event_queue.global_event_add) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Can't allocate global event queue"); - - return UNF_RETURN_ERROR; - } - memset(global_event_queue.global_event_add, 0, - (UNF_MAX_GLOBAL_ENENT_NODE * sizeof(struct unf_cm_event_report))); - - event_node = (struct unf_cm_event_report *)(global_event_queue.global_event_add); - - spin_lock_irqsave(&global_event_queue.global_event_list_lock, flag); - for (index = 0; index < UNF_MAX_GLOBAL_ENENT_NODE; index++) { - INIT_LIST_HEAD(&event_node->list_entry); - list_add_tail(&event_node->list_entry, &global_event_queue.global_event_list); - - global_event_queue.list_number++; - event_node++; - } - spin_unlock_irqrestore(&global_event_queue.global_event_list_lock, flag); - - return ret; -} - -void unf_destroy_global_event_msg(void) -{ - if (global_event_queue.list_number != UNF_MAX_GLOBAL_ENENT_NODE) { - FC_DRV_PRINT(UNF_LOG_EVENT, UNF_CRITICAL, - "[warn]Global event release not complete with remain nodes(0x%x)", - global_event_queue.list_number); - } - - vfree(global_event_queue.global_event_add); -} - -u32 unf_schedule_global_event(void *para_in, u32 event_asy_flag, - int (*unf_event_task)(void *arg_in, void *arg_out)) -{ - struct list_head *list_node = NULL; - struct unf_cm_event_report *event_node = NULL; - ulong flag = 0; - u32 ret = UNF_RETURN_ERROR; - spinlock_t *event_list_lock = NULL; - - FC_CHECK_RETURN_VALUE(unf_event_task, UNF_RETURN_ERROR); - - if (event_asy_flag != UNF_GLOBAL_EVENT_ASYN && event_asy_flag != UNF_GLOBAL_EVENT_SYN) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[warn]Event async flag(0x%x) abnormity", - event_asy_flag); - - return UNF_RETURN_ERROR; - } - - event_list_lock = &global_event_queue.global_event_list_lock; - spin_lock_irqsave(event_list_lock, flag); - if (list_empty(&global_event_queue.global_event_list)) { - spin_unlock_irqrestore(event_list_lock, flag); - - return UNF_RETURN_ERROR; - } - - list_node = UNF_OS_LIST_NEXT(&global_event_queue.global_event_list); - list_del_init(list_node); - global_event_queue.list_number--; - event_node = list_entry(list_node, struct unf_cm_event_report, list_entry); - spin_unlock_irqrestore(event_list_lock, flag); - - /* Initial global event */ - unf_init_event_node(event_node); - init_completion(&event_node->event_comp); - event_node->event_asy_flag = event_asy_flag; - event_node->unf_event_task = unf_event_task; - event_node->para_in = (void *)para_in; - event_node->para_out = NULL; - - unf_post_event(NULL, event_node); - - if (event_asy_flag == UNF_GLOBAL_EVENT_SYN) { - /* must wait for complete */ - wait_for_completion(&event_node->event_comp); - ret = event_node->result; - unf_release_global_event(event_node); - } else { - ret = RETURN_OK; - } - - return ret; -} - -struct unf_cm_event_report *unf_get_one_event_node(void *lport) -{ - struct unf_lport *unf_lport = (struct unf_lport *)lport; - - FC_CHECK_RETURN_VALUE(lport, NULL); - FC_CHECK_RETURN_VALUE(unf_lport->event_mgr.unf_get_free_event_func, NULL); - - return unf_lport->event_mgr.unf_get_free_event_func((void *)unf_lport); -} - -void unf_post_one_event_node(void *lport, struct unf_cm_event_report *event) -{ - struct unf_lport *unf_lport = (struct unf_lport *)lport; - - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(event); - - FC_CHECK_RETURN_VOID(unf_lport->event_mgr.unf_post_event_func); - FC_CHECK_RETURN_VOID(event); - - unf_lport->event_mgr.unf_post_event_func((void *)unf_lport, event); -} diff --git a/drivers/scsi/spfc/common/unf_event.h b/drivers/scsi/spfc/common/unf_event.h deleted file mode 100644 index 3fbd72bff8d7..000000000000 --- a/drivers/scsi/spfc/common/unf_event.h +++ /dev/null @@ -1,83 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef UNF_EVENT_H -#define UNF_EVENT_H - -#include "unf_type.h" - -#define UNF_MAX_EVENT_NODE 256 - -enum unf_event_type { - UNF_EVENT_TYPE_ALARM = 0, /* Alarm */ - UNF_EVENT_TYPE_REQUIRE, /* Require */ - UNF_EVENT_TYPE_RECOVERY, /* Recovery */ - UNF_EVENT_TYPE_BUTT -}; - -struct unf_cm_event_report { - /* event type */ - u32 event; - - /* ASY flag */ - u32 event_asy_flag; - - /* Delay times,must be async event */ - u32 delay_times; - - struct list_head list_entry; - - void *lport; - - /* parameter */ - void *para_in; - void *para_out; - u32 result; - - /* recovery strategy */ - int (*unf_event_task)(void *arg_in, void *arg_out); - - struct completion event_comp; -}; - -struct unf_event_mgr { - spinlock_t port_event_lock; - u32 free_event_count; - - struct list_head list_free_event; - - struct completion *emg_completion; - - void *mem_add; - struct unf_cm_event_report *(*unf_get_free_event_func)(void *lport); - void (*unf_release_event)(void *lport, void *event_node); - void (*unf_post_event_func)(void *lport, void *event_node); -}; - -struct unf_global_event_queue { - void *global_event_add; - u32 list_number; - struct list_head global_event_list; - spinlock_t global_event_list_lock; -}; - -struct unf_event_list { - struct list_head list_head; - spinlock_t fc_event_list_lock; - u32 list_num; /* list node number */ -}; - -void unf_handle_event(struct unf_cm_event_report *event_node); -u32 unf_init_global_event_msg(void); -void unf_destroy_global_event_msg(void); -u32 unf_schedule_global_event(void *para_in, u32 event_asy_flag, - int (*unf_event_task)(void *arg_in, void *arg_out)); -struct unf_cm_event_report *unf_get_one_event_node(void *lport); -void unf_post_one_event_node(void *lport, struct unf_cm_event_report *event); -u32 unf_event_center_destroy(void *lport); -u32 unf_init_event_center(void *lport); - -extern struct task_struct *event_task_thread; -extern struct unf_global_event_queue global_event_queue; -extern struct unf_event_list fc_event_list; -#endif diff --git a/drivers/scsi/spfc/common/unf_exchg.c b/drivers/scsi/spfc/common/unf_exchg.c deleted file mode 100644 index ab35cc318b6f..000000000000 --- a/drivers/scsi/spfc/common/unf_exchg.c +++ /dev/null @@ -1,2317 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#include "unf_exchg.h" -#include "unf_log.h" -#include "unf_common.h" -#include "unf_rport.h" -#include "unf_service.h" -#include "unf_io.h" -#include "unf_exchg_abort.h" - -#define SPFC_XCHG_TYPE_MASK 0xFFFF -#define UNF_DEL_XCHG_TIMER_SAFE(xchg) \ - do { \ - if (cancel_delayed_work(&((xchg)->timeout_work))) { \ - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_MAJOR, \ - "Exchange(0x%p) is free, but timer is pending.", \ - xchg); \ - } else { \ - FC_DRV_PRINT(UNF_LOG_IO_ATT, \ - UNF_CRITICAL, \ - "Exchange(0x%p) is free, but timer is running.", \ - xchg); \ - } \ - } while (0) - -static struct unf_io_flow_id io_stage_table[] = { - {"XCHG_ALLOC"}, {"TGT_RECEIVE_ABTS"}, - {"TGT_ABTS_DONE"}, {"TGT_IO_SRR"}, - {"SFS_RESPONSE"}, {"SFS_TIMEOUT"}, - {"INI_SEND_CMND"}, {"INI_RESPONSE_DONE"}, - {"INI_EH_ABORT"}, {"INI_EH_DEVICE_RESET"}, - {"INI_EH_BLS_DONE"}, {"INI_IO_TIMEOUT"}, - {"INI_REQ_TIMEOUT"}, {"XCHG_CANCEL_TIMER"}, - {"XCHG_FREE_XCHG"}, {"SEND_ELS"}, - {"IO_XCHG_WAIT"}, -}; - -static void unf_init_xchg_attribute(struct unf_xchg *xchg); -static void unf_delay_work_del_syn(struct unf_xchg *xchg); -static void unf_free_lport_sfs_xchg(struct unf_xchg_mgr *xchg_mgr, - bool done_ini_flag); -static void unf_free_lport_destroy_xchg(struct unf_xchg_mgr *xchg_mgr); - -void unf_wake_up_scsi_task_cmnd(struct unf_lport *lport) -{ - struct list_head *node = NULL; - struct list_head *next_node = NULL; - struct unf_xchg *xchg = NULL; - ulong hot_pool_lock_flags = 0; - ulong xchg_flag = 0; - struct unf_xchg_mgr *xchg_mgrs = NULL; - u32 i; - - FC_CHECK_RETURN_VOID(lport); - - for (i = 0; i < UNF_EXCHG_MGR_NUM; i++) { - xchg_mgrs = unf_get_xchg_mgr_by_lport(lport, i); - - if (!xchg_mgrs) { - FC_DRV_PRINT(UNF_LOG_EVENT, UNF_MINOR, - "Can't find LPort(0x%x) MgrIdx %u exchange manager.", - lport->port_id, i); - continue; - } - - spin_lock_irqsave(&xchg_mgrs->hot_pool->xchg_hotpool_lock, hot_pool_lock_flags); - list_for_each_safe(node, next_node, - (&xchg_mgrs->hot_pool->ini_busylist)) { - xchg = list_entry(node, struct unf_xchg, list_xchg_entry); - - spin_lock_irqsave(&xchg->xchg_state_lock, xchg_flag); - if (INI_IO_STATE_UPTASK & xchg->io_state && - (atomic_read(&xchg->ref_cnt) > 0)) { - UNF_SET_SCSI_CMND_RESULT(xchg, UNF_IO_SUCCESS); - up(&xchg->task_sema); - FC_DRV_PRINT(UNF_LOG_EVENT, UNF_MINOR, - "Wake up task command exchange(0x%p), Hot Pool Tag(0x%x).", - xchg, xchg->hotpooltag); - } - spin_unlock_irqrestore(&xchg->xchg_state_lock, xchg_flag); - } - - spin_unlock_irqrestore(&xchg_mgrs->hot_pool->xchg_hotpool_lock, - hot_pool_lock_flags); - } -} - -void *unf_cm_get_free_xchg(void *lport, u32 xchg_type) -{ - struct unf_lport *unf_lport = NULL; - struct unf_cm_xchg_mgr_template *xchg_mgr_temp = NULL; - - FC_CHECK_RETURN_VALUE(unlikely(lport), NULL); - - unf_lport = (struct unf_lport *)lport; - xchg_mgr_temp = &unf_lport->xchg_mgr_temp; - - /* Find the corresponding Lport Xchg management template. */ - FC_CHECK_RETURN_VALUE(unlikely(xchg_mgr_temp->unf_xchg_get_free_and_init), NULL); - - return xchg_mgr_temp->unf_xchg_get_free_and_init(unf_lport, xchg_type); -} - -void unf_cm_free_xchg(void *lport, void *xchg) -{ - struct unf_lport *unf_lport = NULL; - struct unf_cm_xchg_mgr_template *xchg_mgr_temp = NULL; - - FC_CHECK_RETURN_VOID(unlikely(lport)); - FC_CHECK_RETURN_VOID(unlikely(xchg)); - - unf_lport = (struct unf_lport *)lport; - xchg_mgr_temp = &unf_lport->xchg_mgr_temp; - FC_CHECK_RETURN_VOID(unlikely(xchg_mgr_temp->unf_xchg_release)); - - /* - * unf_cm_free_xchg --->>> unf_free_xchg - * --->>> unf_xchg_ref_dec --->>> unf_free_fcp_xchg --->>> - * unf_done_ini_xchg - */ - xchg_mgr_temp->unf_xchg_release(lport, xchg); -} - -void *unf_cm_lookup_xchg_by_tag(void *lport, u16 hot_pool_tag) -{ - struct unf_lport *unf_lport = NULL; - struct unf_cm_xchg_mgr_template *xchg_mgr_temp = NULL; - - FC_CHECK_RETURN_VALUE(unlikely(lport), NULL); - - /* Find the corresponding Lport Xchg management template */ - unf_lport = (struct unf_lport *)lport; - xchg_mgr_temp = &unf_lport->xchg_mgr_temp; - - FC_CHECK_RETURN_VALUE(unlikely(xchg_mgr_temp->unf_look_up_xchg_by_tag), NULL); - - return xchg_mgr_temp->unf_look_up_xchg_by_tag(lport, hot_pool_tag); -} - -void *unf_cm_lookup_xchg_by_id(void *lport, u16 ox_id, u32 oid) -{ - struct unf_lport *unf_lport = NULL; - struct unf_cm_xchg_mgr_template *xchg_mgr_temp = NULL; - - FC_CHECK_RETURN_VALUE(unlikely(lport), NULL); - - unf_lport = (struct unf_lport *)lport; - xchg_mgr_temp = &unf_lport->xchg_mgr_temp; - - /* Find the corresponding Lport Xchg management template */ - FC_CHECK_RETURN_VALUE(unlikely(xchg_mgr_temp->unf_look_up_xchg_by_id), NULL); - - return xchg_mgr_temp->unf_look_up_xchg_by_id(lport, ox_id, oid); -} - -struct unf_xchg *unf_cm_lookup_xchg_by_cmnd_sn(void *lport, u64 command_sn, - u32 world_id, void *pinitiator) -{ - struct unf_lport *unf_lport = NULL; - struct unf_cm_xchg_mgr_template *xchg_mgr_temp = NULL; - struct unf_xchg *xchg = NULL; - - FC_CHECK_RETURN_VALUE(unlikely(lport), NULL); - - unf_lport = (struct unf_lport *)lport; - xchg_mgr_temp = &unf_lport->xchg_mgr_temp; - - FC_CHECK_RETURN_VALUE(unlikely(xchg_mgr_temp->unf_look_up_xchg_by_cmnd_sn), NULL); - - xchg = (struct unf_xchg *)xchg_mgr_temp->unf_look_up_xchg_by_cmnd_sn(unf_lport, - command_sn, - world_id, - pinitiator); - - return xchg; -} - -static u32 unf_init_xchg(struct unf_lport *lport, struct unf_xchg_mgr *xchg_mgr, - u32 xchg_sum, u32 sfs_sum) -{ - struct unf_xchg *xchg_mem = NULL; - union unf_sfs_u *sfs_mm_start = NULL; - dma_addr_t sfs_dma_addr; - struct unf_xchg *xchg = NULL; - struct unf_xchg_free_pool *free_pool = NULL; - ulong flags = 0; - u32 i = 0; - - FC_CHECK_RETURN_VALUE((sfs_sum <= xchg_sum), UNF_RETURN_ERROR); - - free_pool = &xchg_mgr->free_pool; - xchg_mem = xchg_mgr->fcp_mm_start; - xchg = xchg_mem; - - sfs_mm_start = (union unf_sfs_u *)xchg_mgr->sfs_mm_start; - sfs_dma_addr = xchg_mgr->sfs_phy_addr; - /* 1. Allocate the SFS UNION memory to each SFS XCHG - * and mount the SFS XCHG to the corresponding FREE linked list - */ - free_pool->total_sfs_xchg = 0; - free_pool->sfs_xchg_sum = sfs_sum; - for (i = 0; i < sfs_sum; i++) { - INIT_LIST_HEAD(&xchg->list_xchg_entry); - INIT_LIST_HEAD(&xchg->list_esgls); - spin_lock_init(&xchg->xchg_state_lock); - sema_init(&xchg->task_sema, 0); - sema_init(&xchg->echo_info.echo_sync_sema, 0); - - spin_lock_irqsave(&free_pool->xchg_freepool_lock, flags); - xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr = sfs_mm_start; - xchg->fcp_sfs_union.sfs_entry.sfs_buff_phy_addr = sfs_dma_addr; - xchg->fcp_sfs_union.sfs_entry.sfs_buff_len = sizeof(*sfs_mm_start); - list_add_tail(&xchg->list_xchg_entry, &free_pool->list_sfs_xchg_list); - free_pool->total_sfs_xchg++; - spin_unlock_irqrestore(&free_pool->xchg_freepool_lock, flags); - - sfs_mm_start++; - sfs_dma_addr = sfs_dma_addr + sizeof(union unf_sfs_u); - xchg++; - } - - free_pool->total_fcp_xchg = 0; - - for (i = 0; (i < xchg_sum - sfs_sum); i++) { - INIT_LIST_HEAD(&xchg->list_xchg_entry); - - INIT_LIST_HEAD(&xchg->list_esgls); - spin_lock_init(&xchg->xchg_state_lock); - sema_init(&xchg->task_sema, 0); - sema_init(&xchg->echo_info.echo_sync_sema, 0); - - /* alloc dma buffer for fcp_rsp_iu */ - spin_lock_irqsave(&free_pool->xchg_freepool_lock, flags); - list_add_tail(&xchg->list_xchg_entry, &free_pool->list_free_xchg_list); - free_pool->total_fcp_xchg++; - spin_unlock_irqrestore(&free_pool->xchg_freepool_lock, flags); - - xchg++; - } - - free_pool->fcp_xchg_sum = free_pool->total_fcp_xchg; - - return RETURN_OK; -} - -static u32 unf_get_xchg_config_sum(struct unf_lport *lport, u32 *xchg_sum) -{ - struct unf_lport_cfg_item *lport_cfg_items = NULL; - - lport_cfg_items = &lport->low_level_func.lport_cfg_items; - - /* It has been checked at the bottom layer. Don't need to check it - * again. - */ - *xchg_sum = lport_cfg_items->max_sfs_xchg + lport_cfg_items->max_io; - if ((*xchg_sum / UNF_EXCHG_MGR_NUM) == 0 || - lport_cfg_items->max_sfs_xchg / UNF_EXCHG_MGR_NUM == 0) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Port(0x%x) Xchgsum(%u) or SfsXchg(%u) is less than ExchangeMgrNum(%u).", - lport->port_id, *xchg_sum, lport_cfg_items->max_sfs_xchg, - UNF_EXCHG_MGR_NUM); - return UNF_RETURN_ERROR; - } - - if (*xchg_sum > (INVALID_VALUE16 - 1)) { - /* If the format of ox_id/rx_id is exceeded, this function is - * not supported - */ - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "Port(0x%x) Exchange num(0x%x) is Too Big.", - lport->port_id, *xchg_sum); - - return UNF_RETURN_ERROR; - } - - return RETURN_OK; -} - -static void unf_xchg_cancel_timer(void *xchg) -{ - struct unf_xchg *tmp_xchg = NULL; - bool need_dec_xchg_ref = false; - ulong flag = 0; - - FC_CHECK_RETURN_VOID(xchg); - tmp_xchg = (struct unf_xchg *)xchg; - - spin_lock_irqsave(&tmp_xchg->xchg_state_lock, flag); - if (cancel_delayed_work(&tmp_xchg->timeout_work)) - need_dec_xchg_ref = true; - - spin_unlock_irqrestore(&tmp_xchg->xchg_state_lock, flag); - - if (need_dec_xchg_ref) - unf_xchg_ref_dec(xchg, XCHG_CANCEL_TIMER); -} - -void unf_show_all_xchg(struct unf_lport *lport, struct unf_xchg_mgr *xchg_mgr) -{ - struct unf_lport *unf_lport = NULL; - struct unf_xchg *xchg = NULL; - struct list_head *xchg_node = NULL; - struct list_head *next_xchg_node = NULL; - ulong flags = 0; - - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(xchg_mgr); - - unf_lport = lport; - - /* hot Xchg */ - spin_lock_irqsave(&xchg_mgr->hot_pool->xchg_hotpool_lock, flags); - - FC_DRV_PRINT(UNF_LOG_NORMAL, UNF_WARN, "INI busy :"); - list_for_each_safe(xchg_node, next_xchg_node, &xchg_mgr->hot_pool->ini_busylist) { - xchg = list_entry(xchg_node, struct unf_xchg, list_xchg_entry); - FC_DRV_PRINT(UNF_LOG_NORMAL, UNF_MAJOR, - "0x%p---0x%x----0x%x----0x%x----0x%x----0x%x----0x%x----0x%x----0x%x----%llu.", - xchg, (u32)xchg->hotpooltag, (u32)xchg->xchg_type, - (u32)xchg->oxid, (u32)xchg->rxid, (u32)xchg->sid, (u32)xchg->did, - atomic_read(&xchg->ref_cnt), (u32)xchg->io_state, xchg->alloc_jif); - } - - FC_DRV_PRINT(UNF_LOG_NORMAL, UNF_WARN, "SFS :"); - list_for_each_safe(xchg_node, next_xchg_node, &xchg_mgr->hot_pool->sfs_busylist) { - xchg = list_entry(xchg_node, struct unf_xchg, list_xchg_entry); - FC_DRV_PRINT(UNF_LOG_NORMAL, UNF_WARN, - "0x%p---0x%x---0x%x----0x%x----0x%x----0x%x----0x%x----0x%x----0x%x----0x%x----%llu.", - xchg, xchg->cmnd_code, (u32)xchg->hotpooltag, - (u32)xchg->xchg_type, (u32)xchg->oxid, (u32)xchg->rxid, (u32)xchg->sid, - (u32)xchg->did, atomic_read(&xchg->ref_cnt), - (u32)xchg->io_state, xchg->alloc_jif); - } - - FC_DRV_PRINT(UNF_LOG_NORMAL, UNF_WARN, "Destroy list."); - list_for_each_safe(xchg_node, next_xchg_node, &xchg_mgr->hot_pool->list_destroy_xchg) { - xchg = list_entry(xchg_node, struct unf_xchg, list_xchg_entry); - FC_DRV_PRINT(UNF_LOG_NORMAL, UNF_WARN, - "0x%p---0x%x----0x%x----0x%x----0x%x----0x%x----0x%x----0x%x----0x%x----%llu.", - xchg, (u32)xchg->hotpooltag, (u32)xchg->xchg_type, - (u32)xchg->oxid, (u32)xchg->rxid, (u32)xchg->sid, (u32)xchg->did, - atomic_read(&xchg->ref_cnt), (u32)xchg->io_state, xchg->alloc_jif); - } - spin_unlock_irqrestore(&xchg_mgr->hot_pool->xchg_hotpool_lock, flags); -} - -static u32 unf_free_lport_xchg(struct unf_lport *lport, struct unf_xchg_mgr *xchg_mgr) -{ -#define UNF_OS_WAITIO_TIMEOUT (10 * 1000) - - ulong free_pool_lock_flags = 0; - bool wait = false; - u32 total_xchg = 0; - u32 total_xchg_sum = 0; - u32 ret = RETURN_OK; - u64 time_out = 0; - struct completion xchg_mgr_completion; - - init_completion(&xchg_mgr_completion); - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(xchg_mgr, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(xchg_mgr->hot_pool, UNF_RETURN_ERROR); - - unf_free_lport_sfs_xchg(xchg_mgr, false); - - /* free INI Mode exchanges belong to L_Port */ - unf_free_lport_ini_xchg(xchg_mgr, false); - - spin_lock_irqsave(&xchg_mgr->free_pool.xchg_freepool_lock, free_pool_lock_flags); - total_xchg = xchg_mgr->free_pool.total_fcp_xchg + xchg_mgr->free_pool.total_sfs_xchg; - total_xchg_sum = xchg_mgr->free_pool.fcp_xchg_sum + xchg_mgr->free_pool.sfs_xchg_sum; - if (total_xchg != total_xchg_sum) { - xchg_mgr->free_pool.xchg_mgr_completion = &xchg_mgr_completion; - wait = true; - } - spin_unlock_irqrestore(&xchg_mgr->free_pool.xchg_freepool_lock, free_pool_lock_flags); - - if (wait) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]Port(0x%x) begin to wait for exchange manager completion (0x%x:0x%x)", - lport->port_id, total_xchg, total_xchg_sum); - - unf_show_all_xchg(lport, xchg_mgr); - - time_out = wait_for_completion_timeout(xchg_mgr->free_pool.xchg_mgr_completion, - msecs_to_jiffies(UNF_OS_WAITIO_TIMEOUT)); - if (time_out == 0) - unf_free_lport_destroy_xchg(xchg_mgr); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]Port(0x%x) wait for exchange manager completion end", - lport->port_id); - - spin_lock_irqsave(&xchg_mgr->free_pool.xchg_freepool_lock, free_pool_lock_flags); - xchg_mgr->free_pool.xchg_mgr_completion = NULL; - spin_unlock_irqrestore(&xchg_mgr->free_pool.xchg_freepool_lock, - free_pool_lock_flags); - } - - return ret; -} - -void unf_free_lport_all_xchg(struct unf_lport *lport) -{ - struct unf_xchg_mgr *xchg_mgr = NULL; - u32 i; - - FC_CHECK_RETURN_VOID(lport); - - for (i = 0; i < UNF_EXCHG_MGR_NUM; i++) { - xchg_mgr = unf_get_xchg_mgr_by_lport(lport, i); - ; - if (unlikely(!xchg_mgr)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[err]Port(0x%x) hot pool is NULL", - lport->port_id); - - continue; - } - unf_free_lport_sfs_xchg(xchg_mgr, false); - - /* free INI Mode exchanges belong to L_Port */ - unf_free_lport_ini_xchg(xchg_mgr, false); - - unf_free_lport_destroy_xchg(xchg_mgr); - } -} - -static void unf_delay_work_del_syn(struct unf_xchg *xchg) -{ - FC_CHECK_RETURN_VOID(xchg); - - /* synchronous release timer */ - if (!cancel_delayed_work_sync(&xchg->timeout_work)) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "Exchange(0x%p), State(0x%x) can't delete work timer, timer is running or no timer.", - xchg, xchg->io_state); - } else { - /* The reference count cannot be directly subtracted. - * This prevents the XCHG from being moved to the Free linked - * list when the card is unloaded. - */ - unf_cm_free_xchg(xchg->lport, xchg); - } -} - -static void unf_free_lport_sfs_xchg(struct unf_xchg_mgr *xchg_mgr, bool done_ini_flag) -{ - struct list_head *list = NULL; - struct unf_xchg *xchg = NULL; - ulong hot_pool_lock_flags = 0; - - FC_CHECK_RETURN_VOID(xchg_mgr); - FC_CHECK_RETURN_VOID(xchg_mgr->hot_pool); - - spin_lock_irqsave(&xchg_mgr->hot_pool->xchg_hotpool_lock, hot_pool_lock_flags); - while (!list_empty(&xchg_mgr->hot_pool->sfs_busylist)) { - list = UNF_OS_LIST_NEXT(&xchg_mgr->hot_pool->sfs_busylist); - list_del_init(list); - - /* Prevent the xchg of the sfs from being accessed repeatedly. - * The xchg is first mounted to the destroy linked list. - */ - list_add_tail(list, &xchg_mgr->hot_pool->list_destroy_xchg); - - xchg = list_entry(list, struct unf_xchg, list_xchg_entry); - spin_unlock_irqrestore(&xchg_mgr->hot_pool->xchg_hotpool_lock, hot_pool_lock_flags); - unf_delay_work_del_syn(xchg); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "Free SFS Exchange(0x%p), State(0x%x), Reference count(%d), Start time(%llu).", - xchg, xchg->io_state, atomic_read(&xchg->ref_cnt), xchg->alloc_jif); - - unf_cm_free_xchg(xchg->lport, xchg); - - spin_lock_irqsave(&xchg_mgr->hot_pool->xchg_hotpool_lock, hot_pool_lock_flags); - } - spin_unlock_irqrestore(&xchg_mgr->hot_pool->xchg_hotpool_lock, hot_pool_lock_flags); -} - -void unf_free_lport_ini_xchg(struct unf_xchg_mgr *xchg_mgr, bool done_ini_flag) -{ - struct list_head *list = NULL; - struct unf_xchg *xchg = NULL; - ulong hot_pool_lock_flags = 0; - u32 up_status = 0; - - FC_CHECK_RETURN_VOID(xchg_mgr); - FC_CHECK_RETURN_VOID(xchg_mgr->hot_pool); - - spin_lock_irqsave(&xchg_mgr->hot_pool->xchg_hotpool_lock, hot_pool_lock_flags); - while (!list_empty(&xchg_mgr->hot_pool->ini_busylist)) { - /* for each INI busy_list (exchange) node */ - list = UNF_OS_LIST_NEXT(&xchg_mgr->hot_pool->ini_busylist); - - /* Put exchange node to destroy_list, prevent done repeatly */ - list_del_init(list); - list_add_tail(list, &xchg_mgr->hot_pool->list_destroy_xchg); - xchg = list_entry(list, struct unf_xchg, list_xchg_entry); - if (atomic_read(&xchg->ref_cnt) <= 0) - continue; - - spin_unlock_irqrestore(&xchg_mgr->hot_pool->xchg_hotpool_lock, - hot_pool_lock_flags); - unf_delay_work_del_syn(xchg); - - /* In the case of INI done, the command should be set to fail to - * prevent data inconsistency caused by the return of OK - */ - up_status = unf_get_up_level_cmnd_errcode(xchg->scsi_cmnd_info.err_code_table, - xchg->scsi_cmnd_info.err_code_table_cout, - UNF_IO_PORT_LOGOUT); - - if (INI_IO_STATE_UPABORT & xchg->io_state) { - /* - * About L_Port destroy: - * UP_ABORT ---to--->>> ABORT_Port_Removing - */ - up_status = UNF_IO_ABORT_PORT_REMOVING; - } - - xchg->scsi_cmnd_info.result = up_status; - up(&xchg->task_sema); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]Free INI exchange(0x%p) state(0x%x) reference count(%d) start time(%llu)", - xchg, xchg->io_state, atomic_read(&xchg->ref_cnt), xchg->alloc_jif); - - unf_cm_free_xchg(xchg->lport, xchg); - - /* go to next INI busy_list (exchange) node */ - spin_lock_irqsave(&xchg_mgr->hot_pool->xchg_hotpool_lock, hot_pool_lock_flags); - } - spin_unlock_irqrestore(&xchg_mgr->hot_pool->xchg_hotpool_lock, hot_pool_lock_flags); -} - -static void unf_free_lport_destroy_xchg(struct unf_xchg_mgr *xchg_mgr) -{ -#define UNF_WAIT_DESTROY_EMPTY_STEP_MS 1000 -#define UNF_WAIT_IO_STATE_TGT_FRONT_MS (10 * 1000) - - struct unf_xchg *xchg = NULL; - struct list_head *next_xchg_node = NULL; - ulong hot_pool_lock_flags = 0; - ulong xchg_flag = 0; - - FC_CHECK_RETURN_VOID(xchg_mgr); - FC_CHECK_RETURN_VOID(xchg_mgr->hot_pool); - - /* In this case, the timer on the destroy linked list is deleted. - * You only need to check whether the timer is released at the end of - * the tgt. - */ - spin_lock_irqsave(&xchg_mgr->hot_pool->xchg_hotpool_lock, hot_pool_lock_flags); - while (!list_empty(&xchg_mgr->hot_pool->list_destroy_xchg)) { - next_xchg_node = UNF_OS_LIST_NEXT(&xchg_mgr->hot_pool->list_destroy_xchg); - xchg = list_entry(next_xchg_node, struct unf_xchg, list_xchg_entry); - - spin_lock_irqsave(&xchg->xchg_state_lock, xchg_flag); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "Free Exchange(0x%p), Type(0x%x), State(0x%x), Reference count(%d), Start time(%llu)", - xchg, xchg->xchg_type, xchg->io_state, - atomic_read(&xchg->ref_cnt), xchg->alloc_jif); - - spin_unlock_irqrestore(&xchg->xchg_state_lock, xchg_flag); - spin_unlock_irqrestore(&xchg_mgr->hot_pool->xchg_hotpool_lock, hot_pool_lock_flags); - - /* This interface can be invoked to ensure that the timer is - * successfully canceled or wait until the timer execution is - * complete - */ - unf_delay_work_del_syn(xchg); - - /* - * If the timer is canceled successfully, delete Xchg - * If the timer has burst, the Xchg may have been released,In - * this case, deleting the Xchg will be failed - */ - unf_cm_free_xchg(xchg->lport, xchg); - - spin_lock_irqsave(&xchg_mgr->hot_pool->xchg_hotpool_lock, hot_pool_lock_flags); - }; - - spin_unlock_irqrestore(&xchg_mgr->hot_pool->xchg_hotpool_lock, hot_pool_lock_flags); -} - -static void unf_free_all_big_sfs(struct unf_xchg_mgr *xchg_mgr) -{ - struct unf_big_sfs *big_sfs = NULL; - struct list_head *node = NULL; - struct list_head *next_node = NULL; - ulong flag = 0; - u32 i; - - FC_CHECK_RETURN_VOID(xchg_mgr); - - /* Release the free resources in the busy state */ - spin_lock_irqsave(&xchg_mgr->big_sfs_pool.big_sfs_pool_lock, flag); - list_for_each_safe(node, next_node, &xchg_mgr->big_sfs_pool.list_busypool) { - list_del(node); - list_add_tail(node, &xchg_mgr->big_sfs_pool.list_freepool); - } - - list_for_each_safe(node, next_node, &xchg_mgr->big_sfs_pool.list_freepool) { - list_del(node); - big_sfs = list_entry(node, struct unf_big_sfs, entry_bigsfs); - if (big_sfs->addr) - big_sfs->addr = NULL; - } - spin_unlock_irqrestore(&xchg_mgr->big_sfs_pool.big_sfs_pool_lock, flag); - - if (xchg_mgr->big_sfs_buf_list.buflist) { - for (i = 0; i < xchg_mgr->big_sfs_buf_list.buf_num; i++) { - kfree(xchg_mgr->big_sfs_buf_list.buflist[i].vaddr); - xchg_mgr->big_sfs_buf_list.buflist[i].vaddr = NULL; - } - - kfree(xchg_mgr->big_sfs_buf_list.buflist); - xchg_mgr->big_sfs_buf_list.buflist = NULL; - } -} - -static void unf_free_big_sfs_pool(struct unf_xchg_mgr *xchg_mgr) -{ - FC_CHECK_RETURN_VOID(xchg_mgr); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_INFO, - "Free Big SFS Pool, Count(0x%x).", - xchg_mgr->big_sfs_pool.free_count); - - unf_free_all_big_sfs(xchg_mgr); - xchg_mgr->big_sfs_pool.free_count = 0; - - if (xchg_mgr->big_sfs_pool.big_sfs_pool) { - vfree(xchg_mgr->big_sfs_pool.big_sfs_pool); - xchg_mgr->big_sfs_pool.big_sfs_pool = NULL; - } -} - -static void unf_free_xchg_mgr_mem(struct unf_lport *lport, struct unf_xchg_mgr *xchg_mgr) -{ - struct unf_xchg *xchg = NULL; - u32 i = 0; - u32 xchg_sum = 0; - struct unf_xchg_free_pool *free_pool = NULL; - - FC_CHECK_RETURN_VOID(xchg_mgr); - - unf_free_big_sfs_pool(xchg_mgr); - - /* The sfs is released first, and the XchgMgr is allocated by the get - * free page. Therefore, the XchgMgr is compared with the '0' - */ - if (xchg_mgr->sfs_mm_start != 0) { - dma_free_coherent(&lport->low_level_func.dev->dev, xchg_mgr->sfs_mem_size, - xchg_mgr->sfs_mm_start, xchg_mgr->sfs_phy_addr); - xchg_mgr->sfs_mm_start = 0; - } - - /* Release Xchg first */ - if (xchg_mgr->fcp_mm_start) { - unf_get_xchg_config_sum(lport, &xchg_sum); - xchg_sum = xchg_sum / UNF_EXCHG_MGR_NUM; - - xchg = xchg_mgr->fcp_mm_start; - for (i = 0; i < xchg_sum; i++) { - if (!xchg) - break; - xchg++; - } - - vfree(xchg_mgr->fcp_mm_start); - xchg_mgr->fcp_mm_start = NULL; - } - - /* release the hot pool */ - if (xchg_mgr->hot_pool) { - vfree(xchg_mgr->hot_pool); - xchg_mgr->hot_pool = NULL; - } - - free_pool = &xchg_mgr->free_pool; - - vfree(xchg_mgr); -} - -static void unf_free_xchg_mgr(struct unf_lport *lport, struct unf_xchg_mgr *xchg_mgr) -{ - ulong flags = 0; - u32 ret = UNF_RETURN_ERROR; - - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(xchg_mgr); - - /* 1. At first, free exchanges for this Exch_Mgr */ - ret = unf_free_lport_xchg(lport, xchg_mgr); - - /* 2. Delete this Exch_Mgr entry */ - spin_lock_irqsave(&lport->xchg_mgr_lock, flags); - list_del_init(&xchg_mgr->xchg_mgr_entry); - spin_unlock_irqrestore(&lport->xchg_mgr_lock, flags); - - /* 3. free Exch_Mgr memory if necessary */ - if (ret == RETURN_OK) { - /* free memory directly */ - unf_free_xchg_mgr_mem(lport, xchg_mgr); - } else { - /* Add it to Dirty list */ - spin_lock_irqsave(&lport->xchg_mgr_lock, flags); - list_add_tail(&xchg_mgr->xchg_mgr_entry, &lport->list_drty_xchg_mgr_head); - spin_unlock_irqrestore(&lport->xchg_mgr_lock, flags); - - /* Mark dirty flag */ - unf_cm_mark_dirty_mem(lport, UNF_LPORT_DIRTY_FLAG_XCHGMGR_DIRTY); - } -} - -void unf_free_all_xchg_mgr(struct unf_lport *lport) -{ - struct unf_xchg_mgr *xchg_mgr = NULL; - ulong flags = 0; - u32 i = 0; - - FC_CHECK_RETURN_VOID(lport); - - /* for each L_Port->Exch_Mgr_List */ - spin_lock_irqsave(&lport->xchg_mgr_lock, flags); - while (!list_empty(&lport->list_xchg_mgr_head)) { - spin_unlock_irqrestore(&lport->xchg_mgr_lock, flags); - - xchg_mgr = unf_get_xchg_mgr_by_lport(lport, i); - unf_free_xchg_mgr(lport, xchg_mgr); - if (i < UNF_EXCHG_MGR_NUM) - lport->xchg_mgr[i] = NULL; - - i++; - - /* go to next */ - spin_lock_irqsave(&lport->xchg_mgr_lock, flags); - } - spin_unlock_irqrestore(&lport->xchg_mgr_lock, flags); - - lport->destroy_step = UNF_LPORT_DESTROY_STEP_4_DESTROY_EXCH_MGR; -} - -static u32 unf_init_xchg_mgr(struct unf_xchg_mgr *xchg_mgr) -{ - FC_CHECK_RETURN_VALUE(xchg_mgr, UNF_RETURN_ERROR); - - memset(xchg_mgr, 0, sizeof(struct unf_xchg_mgr)); - - INIT_LIST_HEAD(&xchg_mgr->xchg_mgr_entry); - xchg_mgr->fcp_mm_start = NULL; - xchg_mgr->mem_szie = sizeof(struct unf_xchg_mgr); - - return RETURN_OK; -} - -static u32 unf_init_xchg_mgr_free_pool(struct unf_xchg_mgr *xchg_mgr) -{ - struct unf_xchg_free_pool *free_pool = NULL; - - FC_CHECK_RETURN_VALUE(xchg_mgr, UNF_RETURN_ERROR); - - free_pool = &xchg_mgr->free_pool; - INIT_LIST_HEAD(&free_pool->list_free_xchg_list); - INIT_LIST_HEAD(&free_pool->list_sfs_xchg_list); - spin_lock_init(&free_pool->xchg_freepool_lock); - free_pool->fcp_xchg_sum = 0; - free_pool->xchg_mgr_completion = NULL; - - return RETURN_OK; -} - -static u32 unf_init_xchg_hot_pool(struct unf_lport *lport, struct unf_xchg_hot_pool *hot_pool, - u32 xchg_sum) -{ - FC_CHECK_RETURN_VALUE(hot_pool, UNF_RETURN_ERROR); - - INIT_LIST_HEAD(&hot_pool->sfs_busylist); - INIT_LIST_HEAD(&hot_pool->ini_busylist); - spin_lock_init(&hot_pool->xchg_hotpool_lock); - INIT_LIST_HEAD(&hot_pool->list_destroy_xchg); - hot_pool->total_xchges = 0; - hot_pool->wait_state = false; - hot_pool->lport = lport; - - /* Slab Pool Index */ - hot_pool->slab_next_index = 0; - UNF_TOU16_CHECK(hot_pool->slab_total_sum, xchg_sum, return UNF_RETURN_ERROR); - - return RETURN_OK; -} - -static u32 unf_alloc_and_init_big_sfs_pool(struct unf_lport *lport, struct unf_xchg_mgr *xchg_mgr) -{ -#define UNF_MAX_RESOURCE_RESERVED_FOR_RSCN 20 -#define UNF_BIG_SFS_POOL_TYPES 6 - u32 i = 0; - u32 size = 0; - u32 align_size = 0; - u32 npiv_cnt = 0; - struct unf_big_sfs_pool *big_sfs_pool = NULL; - struct unf_big_sfs *big_sfs_buff = NULL; - u32 buf_total_size; - u32 buf_num; - u32 buf_cnt_per_huge_buf; - u32 alloc_idx; - u32 cur_buf_idx = 0; - u32 cur_buf_offset = 0; - - FC_CHECK_RETURN_VALUE(xchg_mgr, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - big_sfs_pool = &xchg_mgr->big_sfs_pool; - - INIT_LIST_HEAD(&big_sfs_pool->list_freepool); - INIT_LIST_HEAD(&big_sfs_pool->list_busypool); - spin_lock_init(&big_sfs_pool->big_sfs_pool_lock); - npiv_cnt = lport->low_level_func.support_max_npiv_num; - - /* - * The value*6 indicates GID_PT/GID_FT, RSCN, and ECHO - * Another command is received when a command is being responded - * A maximum of 20 resources are reserved for the RSCN. During the test, - * multiple rscn are found. As a result, the resources are insufficient - * and the disc fails. - */ - big_sfs_pool->free_count = (npiv_cnt + 1) * UNF_BIG_SFS_POOL_TYPES + - UNF_MAX_RESOURCE_RESERVED_FOR_RSCN; - big_sfs_buff = - (struct unf_big_sfs *)vmalloc(big_sfs_pool->free_count * sizeof(struct unf_big_sfs)); - if (!big_sfs_buff) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "Allocate Big SFS buf fail."); - - return UNF_RETURN_ERROR; - } - memset(big_sfs_buff, 0, big_sfs_pool->free_count * sizeof(struct unf_big_sfs)); - xchg_mgr->mem_szie += (u32)(big_sfs_pool->free_count * sizeof(struct unf_big_sfs)); - big_sfs_pool->big_sfs_pool = (void *)big_sfs_buff; - - /* - * Use the larger value of sizeof (struct unf_gid_acc_pld) and sizeof - * (struct unf_rscn_pld) to avoid the icp error.Therefore, the value is - * directly assigned instead of being compared. - */ - size = sizeof(struct unf_gid_acc_pld); - align_size = ALIGN(size, PAGE_SIZE); - - buf_total_size = align_size * big_sfs_pool->free_count; - xchg_mgr->big_sfs_buf_list.buf_size = - buf_total_size > BUF_LIST_PAGE_SIZE ? BUF_LIST_PAGE_SIZE - : buf_total_size; - - buf_cnt_per_huge_buf = xchg_mgr->big_sfs_buf_list.buf_size / align_size; - buf_num = big_sfs_pool->free_count % buf_cnt_per_huge_buf - ? big_sfs_pool->free_count / buf_cnt_per_huge_buf + 1 - : big_sfs_pool->free_count / buf_cnt_per_huge_buf; - - xchg_mgr->big_sfs_buf_list.buflist = (struct buff_list *)kmalloc(buf_num * - sizeof(struct buff_list), GFP_KERNEL); - xchg_mgr->big_sfs_buf_list.buf_num = buf_num; - - if (!xchg_mgr->big_sfs_buf_list.buflist) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[err]Allocate BigSfs pool buf list failed out of memory"); - goto free_buff; - } - memset(xchg_mgr->big_sfs_buf_list.buflist, 0, buf_num * sizeof(struct buff_list)); - for (alloc_idx = 0; alloc_idx < buf_num; alloc_idx++) { - xchg_mgr->big_sfs_buf_list.buflist[alloc_idx].vaddr = - kmalloc(xchg_mgr->big_sfs_buf_list.buf_size, GFP_ATOMIC); - if (xchg_mgr->big_sfs_buf_list.buflist[alloc_idx].vaddr == - NULL) { - goto free_buff; - } - memset(xchg_mgr->big_sfs_buf_list.buflist[alloc_idx].vaddr, 0, - xchg_mgr->big_sfs_buf_list.buf_size); - } - - for (i = 0; i < big_sfs_pool->free_count; i++) { - if (i != 0 && !(i % buf_cnt_per_huge_buf)) - cur_buf_idx++; - - cur_buf_offset = align_size * (i % buf_cnt_per_huge_buf); - big_sfs_buff->addr = xchg_mgr->big_sfs_buf_list.buflist[cur_buf_idx].vaddr + - cur_buf_offset; - big_sfs_buff->size = size; - xchg_mgr->mem_szie += size; - list_add_tail(&big_sfs_buff->entry_bigsfs, &big_sfs_pool->list_freepool); - big_sfs_buff++; - } - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[EVENT]Allocate BigSfs pool size:%d,align_size:%d,buf_num:%u,buf_size:%u", - size, align_size, xchg_mgr->big_sfs_buf_list.buf_num, - xchg_mgr->big_sfs_buf_list.buf_size); - return RETURN_OK; -free_buff: - unf_free_all_big_sfs(xchg_mgr); - vfree(big_sfs_buff); - big_sfs_pool->big_sfs_pool = NULL; - return UNF_RETURN_ERROR; -} - -static void unf_free_one_big_sfs(struct unf_xchg *xchg) -{ - ulong flag = 0; - struct unf_xchg_mgr *xchg_mgr = NULL; - - FC_CHECK_RETURN_VOID(xchg); - xchg_mgr = xchg->xchg_mgr; - FC_CHECK_RETURN_VOID(xchg_mgr); - if (!xchg->big_sfs_buf) - return; - - if (xchg->cmnd_code != NS_GID_PT && xchg->cmnd_code != NS_GID_FT && - xchg->cmnd_code != ELS_ECHO && - xchg->cmnd_code != (UNF_SET_ELS_ACC_TYPE(ELS_ECHO)) && xchg->cmnd_code != ELS_RSCN && - xchg->cmnd_code != (UNF_SET_ELS_ACC_TYPE(ELS_RSCN))) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "Exchange(0x%p), Command(0x%x) big SFS buf is not NULL.", - xchg, xchg->cmnd_code); - } - - spin_lock_irqsave(&xchg_mgr->big_sfs_pool.big_sfs_pool_lock, flag); - list_del(&xchg->big_sfs_buf->entry_bigsfs); - list_add_tail(&xchg->big_sfs_buf->entry_bigsfs, - &xchg_mgr->big_sfs_pool.list_freepool); - xchg_mgr->big_sfs_pool.free_count++; - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "Free one big SFS buf(0x%p), Count(0x%x), Exchange(0x%p), Command(0x%x).", - xchg->big_sfs_buf->addr, xchg_mgr->big_sfs_pool.free_count, - xchg, xchg->cmnd_code); - spin_unlock_irqrestore(&xchg_mgr->big_sfs_pool.big_sfs_pool_lock, flag); -} - -static void unf_free_exchg_mgr_info(struct unf_lport *lport) -{ - u32 i; - struct list_head *node = NULL; - struct list_head *next_node = NULL; - ulong flags = 0; - struct unf_xchg_mgr *xchg_mgr = NULL; - - spin_lock_irqsave(&lport->xchg_mgr_lock, flags); - list_for_each_safe(node, next_node, &lport->list_xchg_mgr_head) { - list_del(node); - xchg_mgr = list_entry(node, struct unf_xchg_mgr, xchg_mgr_entry); - } - spin_unlock_irqrestore(&lport->xchg_mgr_lock, flags); - - for (i = 0; i < UNF_EXCHG_MGR_NUM; i++) { - xchg_mgr = lport->xchg_mgr[i]; - - if (xchg_mgr) { - unf_free_big_sfs_pool(xchg_mgr); - - if (xchg_mgr->sfs_mm_start) { - dma_free_coherent(&lport->low_level_func.dev->dev, - xchg_mgr->sfs_mem_size, xchg_mgr->sfs_mm_start, - xchg_mgr->sfs_phy_addr); - xchg_mgr->sfs_mm_start = 0; - } - - if (xchg_mgr->fcp_mm_start) { - vfree(xchg_mgr->fcp_mm_start); - xchg_mgr->fcp_mm_start = NULL; - } - - if (xchg_mgr->hot_pool) { - vfree(xchg_mgr->hot_pool); - xchg_mgr->hot_pool = NULL; - } - - vfree(xchg_mgr); - lport->xchg_mgr[i] = NULL; - } - } -} - -static u32 unf_alloc_and_init_xchg_mgr(struct unf_lport *lport) -{ - struct unf_xchg_mgr *xchg_mgr = NULL; - struct unf_xchg_hot_pool *hot_pool = NULL; - struct unf_xchg *xchg_mem = NULL; - void *sfs_mm_start = 0; - dma_addr_t sfs_phy_addr = 0; - u32 xchg_sum = 0; - u32 sfs_xchg_sum = 0; - ulong flags = 0; - u32 ret = UNF_RETURN_ERROR; - u32 slab_num = 0; - u32 i = 0; - - ret = unf_get_xchg_config_sum(lport, &xchg_sum); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "Port(0x%x) can't get Exchange.", lport->port_id); - - return UNF_RETURN_ERROR; - } - - /* SFS Exchange Sum */ - sfs_xchg_sum = lport->low_level_func.lport_cfg_items.max_sfs_xchg / - UNF_EXCHG_MGR_NUM; - xchg_sum = xchg_sum / UNF_EXCHG_MGR_NUM; - slab_num = lport->low_level_func.support_max_hot_tag_range / UNF_EXCHG_MGR_NUM; - for (i = 0; i < UNF_EXCHG_MGR_NUM; i++) { - /* Alloc Exchange Manager */ - xchg_mgr = (struct unf_xchg_mgr *)vmalloc(sizeof(struct unf_xchg_mgr)); - if (!xchg_mgr) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "Port(0x%x) allocate Exchange Manager Memory Fail.", - lport->port_id); - goto exit; - } - - /* Init Exchange Manager */ - ret = unf_init_xchg_mgr(xchg_mgr); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "Port(0x%x) initialization Exchange Manager unsuccessful.", - lport->port_id); - goto free_xchg_mgr; - } - - /* Initialize the Exchange Free Pool resource */ - ret = unf_init_xchg_mgr_free_pool(xchg_mgr); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "Port(0x%x) initialization Exchange Manager Free Pool unsuccessful.", - lport->port_id); - goto free_xchg_mgr; - } - - /* Allocate memory for Hot Pool and Xchg slab */ - hot_pool = vmalloc(sizeof(struct unf_xchg_hot_pool) + - sizeof(struct unf_xchg *) * slab_num); - if (!hot_pool) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "Port(0x%x) allocate Hot Pool Memory Fail.", - lport->port_id); - goto free_xchg_mgr; - } - memset(hot_pool, 0, - sizeof(struct unf_xchg_hot_pool) + sizeof(struct unf_xchg *) * slab_num); - - xchg_mgr->mem_szie += (u32)(sizeof(struct unf_xchg_hot_pool) + - sizeof(struct unf_xchg *) * slab_num); - /* Initialize the Exchange Hot Pool resource */ - ret = unf_init_xchg_hot_pool(lport, hot_pool, slab_num); - if (ret != RETURN_OK) - goto free_hot_pool; - - hot_pool->base += (u16)(i * slab_num); - /* Allocate the memory of all Xchg (IO/SFS) */ - xchg_mem = vmalloc(sizeof(struct unf_xchg) * xchg_sum); - if (!xchg_mem) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "Port(0x%x) allocate Exchange Memory Fail.", - lport->port_id); - goto free_hot_pool; - } - memset(xchg_mem, 0, sizeof(struct unf_xchg) * xchg_sum); - - xchg_mgr->mem_szie += (u32)(sizeof(struct unf_xchg) * xchg_sum); - xchg_mgr->hot_pool = hot_pool; - xchg_mgr->fcp_mm_start = xchg_mem; - /* Allocate the memory used by the SFS Xchg to carry the - * ELS/BLS/GS command and response - */ - xchg_mgr->sfs_mem_size = (u32)(sizeof(union unf_sfs_u) * sfs_xchg_sum); - - /* Apply for the DMA space for sending sfs frames. - * If the value of DMA32 is less than 4 GB, cross-4G problems - * will not occur - */ - sfs_mm_start = dma_alloc_coherent(&lport->low_level_func.dev->dev, - xchg_mgr->sfs_mem_size, - &sfs_phy_addr, GFP_KERNEL); - if (!sfs_mm_start) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "Port(0x%x) Get Free Pagers Fail .", - lport->port_id); - goto free_xchg_mem; - } - memset(sfs_mm_start, 0, sizeof(union unf_sfs_u) * sfs_xchg_sum); - - xchg_mgr->mem_szie += xchg_mgr->sfs_mem_size; - xchg_mgr->sfs_mm_start = sfs_mm_start; - xchg_mgr->sfs_phy_addr = sfs_phy_addr; - /* The Xchg is initialized and mounted to the Free Pool */ - ret = unf_init_xchg(lport, xchg_mgr, xchg_sum, sfs_xchg_sum); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "Port(0x%x) initialization Exchange unsuccessful, Exchange Number(%d), SFS Exchange number(%d).", - lport->port_id, xchg_sum, sfs_xchg_sum); - dma_free_coherent(&lport->low_level_func.dev->dev, xchg_mgr->sfs_mem_size, - xchg_mgr->sfs_mm_start, xchg_mgr->sfs_phy_addr); - xchg_mgr->sfs_mm_start = 0; - goto free_xchg_mem; - } - - /* Apply for the memory used by GID_PT, GID_FT, and RSCN */ - ret = unf_alloc_and_init_big_sfs_pool(lport, xchg_mgr); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "Port(0x%x) allocate big SFS fail", lport->port_id); - dma_free_coherent(&lport->low_level_func.dev->dev, xchg_mgr->sfs_mem_size, - xchg_mgr->sfs_mm_start, xchg_mgr->sfs_phy_addr); - xchg_mgr->sfs_mm_start = 0; - goto free_xchg_mem; - } - - spin_lock_irqsave(&lport->xchg_mgr_lock, flags); - lport->xchg_mgr[i] = (void *)xchg_mgr; - list_add_tail(&xchg_mgr->xchg_mgr_entry, &lport->list_xchg_mgr_head); - spin_unlock_irqrestore(&lport->xchg_mgr_lock, flags); - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]Port(0x%x) ExchangeMgr:(0x%p),Base:(0x%x).", - lport->port_id, lport->xchg_mgr[i], hot_pool->base); - } - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_INFO, - "Port(0x%x) allocate Exchange Manager size(0x%x).", - lport->port_id, xchg_mgr->mem_szie); - return RETURN_OK; -free_xchg_mem: - vfree(xchg_mem); -free_hot_pool: - vfree(hot_pool); -free_xchg_mgr: - vfree(xchg_mgr); -exit: - unf_free_exchg_mgr_info(lport); - return UNF_RETURN_ERROR; -} - -void unf_xchg_mgr_destroy(struct unf_lport *lport) -{ - FC_CHECK_RETURN_VOID(lport); - - unf_free_all_xchg_mgr(lport); -} - -u32 unf_alloc_xchg_resource(struct unf_lport *lport) -{ - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - - INIT_LIST_HEAD(&lport->list_drty_xchg_mgr_head); - INIT_LIST_HEAD(&lport->list_xchg_mgr_head); - spin_lock_init(&lport->xchg_mgr_lock); - - /* LPort Xchg Management Unit Alloc */ - if (unf_alloc_and_init_xchg_mgr(lport) != RETURN_OK) - return UNF_RETURN_ERROR; - - return RETURN_OK; -} - -void unf_destroy_dirty_xchg(struct unf_lport *lport, bool show_only) -{ - u32 dirty_xchg = 0; - struct unf_xchg_mgr *xchg_mgr = NULL; - ulong flags = 0; - struct list_head *node = NULL; - struct list_head *next_node = NULL; - - FC_CHECK_RETURN_VOID(lport); - - if (lport->dirty_flag & UNF_LPORT_DIRTY_FLAG_XCHGMGR_DIRTY) { - spin_lock_irqsave(&lport->xchg_mgr_lock, flags); - list_for_each_safe(node, next_node, &lport->list_drty_xchg_mgr_head) { - xchg_mgr = list_entry(node, struct unf_xchg_mgr, xchg_mgr_entry); - spin_unlock_irqrestore(&lport->xchg_mgr_lock, flags); - if (xchg_mgr) { - dirty_xchg = (xchg_mgr->free_pool.total_fcp_xchg + - xchg_mgr->free_pool.total_sfs_xchg); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]Port(0x%x) has %u dirty exchange(s)", - lport->port_id, dirty_xchg); - - unf_show_all_xchg(lport, xchg_mgr); - - if (!show_only) { - /* Delete Dirty Exchange Mgr entry */ - spin_lock_irqsave(&lport->xchg_mgr_lock, flags); - list_del_init(&xchg_mgr->xchg_mgr_entry); - spin_unlock_irqrestore(&lport->xchg_mgr_lock, flags); - - /* Free Dirty Exchange Mgr memory */ - unf_free_xchg_mgr_mem(lport, xchg_mgr); - } - } - spin_lock_irqsave(&lport->xchg_mgr_lock, flags); - } - spin_unlock_irqrestore(&lport->xchg_mgr_lock, flags); - } -} - -struct unf_xchg_mgr *unf_get_xchg_mgr_by_lport(struct unf_lport *lport, u32 idx) -{ - struct unf_xchg_mgr *xchg_mgr = NULL; - ulong flags = 0; - - FC_CHECK_RETURN_VALUE(lport, NULL); - FC_CHECK_RETURN_VALUE((idx < UNF_EXCHG_MGR_NUM), NULL); - - spin_lock_irqsave(&lport->xchg_mgr_lock, flags); - xchg_mgr = lport->xchg_mgr[idx]; - spin_unlock_irqrestore(&lport->xchg_mgr_lock, flags); - - return xchg_mgr; -} - -struct unf_xchg_hot_pool *unf_get_hot_pool_by_lport(struct unf_lport *lport, - u32 mgr_idx) -{ - struct unf_xchg_mgr *xchg_mgr = NULL; - struct unf_lport *unf_lport = NULL; - - FC_CHECK_RETURN_VALUE(lport, NULL); - - unf_lport = (struct unf_lport *)(lport->root_lport); - - FC_CHECK_RETURN_VALUE(unf_lport, NULL); - - /* Get Xchg Manager */ - xchg_mgr = unf_get_xchg_mgr_by_lport(unf_lport, mgr_idx); - if (!xchg_mgr) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_MAJOR, - "Port(0x%x) Exchange Manager is NULL.", - unf_lport->port_id); - - return NULL; - } - - /* Get Xchg Manager Hot Pool */ - return xchg_mgr->hot_pool; -} - -static inline void unf_hot_pool_slab_set(struct unf_xchg_hot_pool *hot_pool, - u16 slab_index, struct unf_xchg *xchg) -{ - FC_CHECK_RETURN_VOID(hot_pool); - - hot_pool->xchg_slab[slab_index] = xchg; -} - -static inline struct unf_xchg *unf_get_xchg_by_xchg_tag(struct unf_xchg_hot_pool *hot_pool, - u16 slab_index) -{ - FC_CHECK_RETURN_VALUE(hot_pool, NULL); - - return hot_pool->xchg_slab[slab_index]; -} - -static void *unf_look_up_xchg_by_tag(void *lport, u16 hot_pool_tag) -{ - struct unf_lport *unf_lport = NULL; - struct unf_xchg_hot_pool *hot_pool = NULL; - struct unf_xchg *xchg = NULL; - ulong flags = 0; - u32 exchg_mgr_idx = 0; - struct unf_xchg_mgr *xchg_mgr = NULL; - - FC_CHECK_RETURN_VALUE(lport, NULL); - - /* In the case of NPIV, lport is the Vport pointer, - * the share uses the ExchMgr of RootLport - */ - unf_lport = ((struct unf_lport *)lport)->root_lport; - FC_CHECK_RETURN_VALUE(unf_lport, NULL); - - exchg_mgr_idx = (hot_pool_tag * UNF_EXCHG_MGR_NUM) / - unf_lport->low_level_func.support_max_hot_tag_range; - if (unlikely(exchg_mgr_idx >= UNF_EXCHG_MGR_NUM)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[err]Port(0x%x) Get ExchgMgr %u err", - unf_lport->port_id, exchg_mgr_idx); - - return NULL; - } - - xchg_mgr = unf_lport->xchg_mgr[exchg_mgr_idx]; - - if (unlikely(!xchg_mgr)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[err]Port(0x%x) ExchgMgr %u is null", - unf_lport->port_id, exchg_mgr_idx); - - return NULL; - } - - hot_pool = xchg_mgr->hot_pool; - - if (unlikely(!hot_pool)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_MAJOR, - "Port(0x%x) Hot Pool is NULL.", - unf_lport->port_id); - - return NULL; - } - - if (unlikely(hot_pool_tag >= (hot_pool->slab_total_sum + hot_pool->base))) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[err]LPort(0x%x) can't Input Tag(0x%x), Max(0x%x).", - unf_lport->port_id, hot_pool_tag, - (hot_pool->slab_total_sum + hot_pool->base)); - - return NULL; - } - - spin_lock_irqsave(&hot_pool->xchg_hotpool_lock, flags); - xchg = unf_get_xchg_by_xchg_tag(hot_pool, hot_pool_tag - hot_pool->base); - spin_unlock_irqrestore(&hot_pool->xchg_hotpool_lock, flags); - - return (void *)xchg; -} - -static void *unf_find_xchg_by_ox_id(void *lport, u16 ox_id, u32 oid) -{ - struct unf_xchg_hot_pool *hot_pool = NULL; - struct unf_xchg *xchg = NULL; - struct list_head *node = NULL; - struct list_head *next_node = NULL; - struct unf_lport *unf_lport = NULL; - ulong flags = 0; - ulong xchg_flags = 0; - u32 i = 0; - - FC_CHECK_RETURN_VALUE(lport, NULL); - - /* In the case of NPIV, the lport is the Vport pointer, - * and the share uses the ExchMgr of the RootLport - */ - unf_lport = ((struct unf_lport *)lport)->root_lport; - FC_CHECK_RETURN_VALUE(unf_lport, NULL); - - for (i = 0; i < UNF_EXCHG_MGR_NUM; i++) { - hot_pool = unf_get_hot_pool_by_lport(unf_lport, i); - if (unlikely(!hot_pool)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_MAJOR, - "Port(0x%x) MgrIdex %u Hot Pool is NULL.", - unf_lport->port_id, i); - continue; - } - - spin_lock_irqsave(&hot_pool->xchg_hotpool_lock, flags); - - /* 1. Traverse sfs_busy list */ - list_for_each_safe(node, next_node, &hot_pool->sfs_busylist) { - xchg = list_entry(node, struct unf_xchg, list_xchg_entry); - spin_lock_irqsave(&xchg->xchg_state_lock, xchg_flags); - if (unf_check_oxid_matched(ox_id, oid, xchg)) { - atomic_inc(&xchg->ref_cnt); - spin_unlock_irqrestore(&xchg->xchg_state_lock, xchg_flags); - spin_unlock_irqrestore(&hot_pool->xchg_hotpool_lock, flags); - return xchg; - } - spin_unlock_irqrestore(&xchg->xchg_state_lock, xchg_flags); - } - - /* 2. Traverse INI_Busy List */ - list_for_each_safe(node, next_node, &hot_pool->ini_busylist) { - xchg = list_entry(node, struct unf_xchg, list_xchg_entry); - spin_lock_irqsave(&xchg->xchg_state_lock, xchg_flags); - if (unf_check_oxid_matched(ox_id, oid, xchg)) { - atomic_inc(&xchg->ref_cnt); - spin_unlock_irqrestore(&xchg->xchg_state_lock, xchg_flags); - spin_unlock_irqrestore(&hot_pool->xchg_hotpool_lock, flags); - return xchg; - } - spin_unlock_irqrestore(&xchg->xchg_state_lock, - xchg_flags); - } - - spin_unlock_irqrestore(&hot_pool->xchg_hotpool_lock, flags); - } - - return NULL; -} - -static inline bool unf_check_xchg_matched(struct unf_xchg *xchg, u64 command_sn, - u32 world_id, void *pinitiator) -{ - bool matched = false; - - matched = (command_sn == xchg->cmnd_sn); - if (matched && (atomic_read(&xchg->ref_cnt) > 0)) - return true; - else - return false; -} - -static void *unf_look_up_xchg_by_cmnd_sn(void *lport, u64 command_sn, - u32 world_id, void *pinitiator) -{ - struct unf_lport *unf_lport = NULL; - struct unf_xchg_hot_pool *hot_pool = NULL; - struct list_head *node = NULL; - struct list_head *next_node = NULL; - struct unf_xchg *xchg = NULL; - ulong flags = 0; - u32 i; - - FC_CHECK_RETURN_VALUE(lport, NULL); - - /* In NPIV, lport is a Vport pointer, and idle resources are shared by - * ExchMgr of RootLport. However, busy resources are mounted on each - * vport. Therefore, vport needs to be used. - */ - unf_lport = (struct unf_lport *)lport; - FC_CHECK_RETURN_VALUE(unf_lport, NULL); - - for (i = 0; i < UNF_EXCHG_MGR_NUM; i++) { - hot_pool = unf_get_hot_pool_by_lport(unf_lport, i); - if (unlikely(!hot_pool)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[err]Port(0x%x) hot pool is NULL", - unf_lport->port_id); - - continue; - } - - /* from busy_list */ - spin_lock_irqsave(&hot_pool->xchg_hotpool_lock, flags); - list_for_each_safe(node, next_node, &hot_pool->ini_busylist) { - xchg = list_entry(node, struct unf_xchg, list_xchg_entry); - if (unf_check_xchg_matched(xchg, command_sn, world_id, pinitiator)) { - spin_unlock_irqrestore(&hot_pool->xchg_hotpool_lock, flags); - - return xchg; - } - } - - /* vport: from destroy_list */ - if (unf_lport != unf_lport->root_lport) { - list_for_each_safe(node, next_node, &hot_pool->list_destroy_xchg) { - xchg = list_entry(node, struct unf_xchg, list_xchg_entry); - if (unf_check_xchg_matched(xchg, command_sn, world_id, - pinitiator)) { - spin_unlock_irqrestore(&hot_pool->xchg_hotpool_lock, flags); - - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_MAJOR, - "[info]Port(0x%x) lookup exchange from destroy list", - unf_lport->port_id); - - return xchg; - } - } - } - - spin_unlock_irqrestore(&hot_pool->xchg_hotpool_lock, flags); - } - - return NULL; -} - -static inline u32 unf_alloc_hot_pool_slab(struct unf_xchg_hot_pool *hot_pool, struct unf_xchg *xchg) -{ - u16 slab_index = 0; - - FC_CHECK_RETURN_VALUE(hot_pool, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(xchg, UNF_RETURN_ERROR); - - /* Check whether the hotpool tag is in the specified range sirt. - * If yes, set up the management relationship. If no, handle the problem - * according to the normal IO. If the sirt digitmap is used but the tag - * is occupied, it indicates that the I/O is discarded. - */ - - hot_pool->slab_next_index = (u16)hot_pool->slab_next_index; - slab_index = hot_pool->slab_next_index; - while (unf_get_xchg_by_xchg_tag(hot_pool, slab_index)) { - slab_index++; - slab_index = slab_index % hot_pool->slab_total_sum; - - /* Rewind occurs */ - if (slab_index == hot_pool->slab_next_index) { - FC_DRV_PRINT(UNF_LOG_EQUIP_ATT, UNF_MAJOR, - "There is No Slab At Hot Pool(0x%p) for xchg(0x%p).", - hot_pool, xchg); - - return UNF_RETURN_ERROR; - } - } - - unf_hot_pool_slab_set(hot_pool, slab_index, xchg); - xchg->hotpooltag = slab_index + hot_pool->base; - slab_index++; - hot_pool->slab_next_index = slab_index % hot_pool->slab_total_sum; - - return RETURN_OK; -} - -struct unf_esgl_page * -unf_get_and_add_one_free_esgl_page(struct unf_lport *lport, struct unf_xchg *xchg) -{ - struct unf_esgl *esgl = NULL; - struct list_head *list_head = NULL; - ulong flag = 0; - - FC_CHECK_RETURN_VALUE(lport, NULL); - FC_CHECK_RETURN_VALUE(xchg, NULL); - - /* Obtain a new Esgl from the EsglPool and add it to the list_esgls of - * the Xchg - */ - spin_lock_irqsave(&lport->esgl_pool.esgl_pool_lock, flag); - if (!list_empty(&lport->esgl_pool.list_esgl_pool)) { - list_head = UNF_OS_LIST_NEXT(&lport->esgl_pool.list_esgl_pool); - list_del(list_head); - lport->esgl_pool.esgl_pool_count--; - list_add_tail(list_head, &xchg->list_esgls); - - esgl = list_entry(list_head, struct unf_esgl, entry_esgl); - atomic_inc(&xchg->esgl_cnt); - spin_unlock_irqrestore(&lport->esgl_pool.esgl_pool_lock, flag); - } else { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x) esgl pool is empty", - lport->nport_id); - - spin_unlock_irqrestore(&lport->esgl_pool.esgl_pool_lock, flag); - return NULL; - } - - return &esgl->page; -} - -void unf_release_esgls(struct unf_xchg *xchg) -{ - struct unf_lport *unf_lport = NULL; - struct list_head *list = NULL; - struct list_head *list_tmp = NULL; - ulong flag = 0; - - FC_CHECK_RETURN_VOID(xchg); - FC_CHECK_RETURN_VOID(xchg->lport); - - if (atomic_read(&xchg->esgl_cnt) <= 0) - return; - - /* In the case of NPIV, the Vport pointer is saved in v_pstExch, - * and the EsglPool of RootLport is shared. - */ - unf_lport = (xchg->lport)->root_lport; - FC_CHECK_RETURN_VOID(unf_lport); - - spin_lock_irqsave(&unf_lport->esgl_pool.esgl_pool_lock, flag); - if (!list_empty(&xchg->list_esgls)) { - list_for_each_safe(list, list_tmp, &xchg->list_esgls) { - list_del(list); - list_add_tail(list, &unf_lport->esgl_pool.list_esgl_pool); - unf_lport->esgl_pool.esgl_pool_count++; - atomic_dec(&xchg->esgl_cnt); - } - } - spin_unlock_irqrestore(&unf_lport->esgl_pool.esgl_pool_lock, flag); -} - -static void unf_add_back_to_fcp_list(struct unf_xchg_free_pool *free_pool, struct unf_xchg *xchg) -{ - ulong flags = 0; - - FC_CHECK_RETURN_VOID(free_pool); - FC_CHECK_RETURN_VOID(xchg); - - unf_init_xchg_attribute(xchg); - - /* The released I/O resources are added to the queue tail to facilitate - * fault locating - */ - spin_lock_irqsave(&free_pool->xchg_freepool_lock, flags); - list_add_tail(&xchg->list_xchg_entry, &free_pool->list_free_xchg_list); - free_pool->total_fcp_xchg++; - spin_unlock_irqrestore(&free_pool->xchg_freepool_lock, flags); -} - -static void unf_check_xchg_mgr_status(struct unf_xchg_mgr *xchg_mgr) -{ - ulong flags = 0; - u32 total_xchg = 0; - u32 total_xchg_sum = 0; - - FC_CHECK_RETURN_VOID(xchg_mgr); - - spin_lock_irqsave(&xchg_mgr->free_pool.xchg_freepool_lock, flags); - - total_xchg = xchg_mgr->free_pool.total_fcp_xchg + xchg_mgr->free_pool.total_sfs_xchg; - total_xchg_sum = xchg_mgr->free_pool.fcp_xchg_sum + xchg_mgr->free_pool.sfs_xchg_sum; - - if (xchg_mgr->free_pool.xchg_mgr_completion && total_xchg == total_xchg_sum) - complete(xchg_mgr->free_pool.xchg_mgr_completion); - - spin_unlock_irqrestore(&xchg_mgr->free_pool.xchg_freepool_lock, flags); -} - -static void unf_free_fcp_xchg(struct unf_xchg *xchg) -{ - struct unf_xchg_free_pool *free_pool = NULL; - struct unf_xchg_mgr *xchg_mgr = NULL; - struct unf_lport *unf_lport = NULL; - struct unf_rport *unf_rport = NULL; - - FC_CHECK_RETURN_VOID(xchg); - - /* Releasing a Specified INI I/O and Invoking the scsi_done Process */ - unf_done_ini_xchg(xchg); - free_pool = xchg->free_pool; - xchg_mgr = xchg->xchg_mgr; - unf_lport = xchg->lport; - unf_rport = xchg->rport; - - atomic_dec(&unf_rport->pending_io_cnt); - /* Release the Esgls in the Xchg structure and return it to the EsglPool - * of the Lport - */ - unf_release_esgls(xchg); - - if (unlikely(xchg->fcp_sfs_union.fcp_rsp_entry.fcp_rsp_iu)) { - kfree(xchg->fcp_sfs_union.fcp_rsp_entry.fcp_rsp_iu); - xchg->fcp_sfs_union.fcp_rsp_entry.fcp_rsp_iu = NULL; - } - - /* Mount I/O resources to the FCP Free linked list */ - unf_add_back_to_fcp_list(free_pool, xchg); - - /* The Xchg is released synchronously and then forcibly released to - * prevent the Xchg from accessing the Xchg in the normal I/O process - */ - if (unlikely(unf_lport->port_removing)) - unf_check_xchg_mgr_status(xchg_mgr); -} - -static void unf_init_io_xchg_param(struct unf_xchg *xchg, struct unf_lport *lport, - struct unf_xchg_mgr *xchg_mgr) -{ - static atomic64_t exhd_id; - - xchg->start_jif = atomic64_inc_return(&exhd_id); - xchg->xchg_mgr = xchg_mgr; - xchg->free_pool = &xchg_mgr->free_pool; - xchg->hot_pool = xchg_mgr->hot_pool; - xchg->lport = lport; - xchg->xchg_type = UNF_XCHG_TYPE_INI; - xchg->free_xchg = unf_free_fcp_xchg; - xchg->scsi_or_tgt_cmnd_func = NULL; - xchg->io_state = UNF_IO_STATE_NEW; - xchg->io_send_stage = TGT_IO_SEND_STAGE_NONE; - xchg->io_send_result = TGT_IO_SEND_RESULT_INVALID; - xchg->io_send_abort = false; - xchg->io_abort_result = false; - xchg->oxid = INVALID_VALUE16; - xchg->abort_oxid = INVALID_VALUE16; - xchg->rxid = INVALID_VALUE16; - xchg->sid = INVALID_VALUE32; - xchg->did = INVALID_VALUE32; - xchg->oid = INVALID_VALUE32; - xchg->seq_id = INVALID_VALUE8; - xchg->cmnd_code = INVALID_VALUE32; - xchg->data_len = 0; - xchg->resid_len = 0; - xchg->data_direction = DMA_NONE; - xchg->may_consume_res_cnt = 0; - xchg->fast_consume_res_cnt = 0; - xchg->io_front_jif = 0; - xchg->tmf_state = 0; - xchg->ucode_abts_state = INVALID_VALUE32; - xchg->abts_state = 0; - xchg->rport_bind_jifs = INVALID_VALUE64; - xchg->scsi_id = INVALID_VALUE32; - xchg->qos_level = 0; - xchg->world_id = INVALID_VALUE32; - - memset(&xchg->dif_control, 0, sizeof(struct unf_dif_control_info)); - memset(&xchg->req_sgl_info, 0, sizeof(struct unf_req_sgl_info)); - memset(&xchg->dif_sgl_info, 0, sizeof(struct unf_req_sgl_info)); - xchg->scsi_cmnd_info.result = 0; - - xchg->private_data[PKG_PRIVATE_XCHG_ALLOC_TIME] = - (u32)atomic64_inc_return(&((struct unf_lport *)lport->root_lport)->exchg_index); - - if (xchg->private_data[PKG_PRIVATE_XCHG_ALLOC_TIME] == INVALID_VALUE32) { - xchg->private_data[PKG_PRIVATE_XCHG_ALLOC_TIME] = - (u32)atomic64_inc_return(&((struct unf_lport *)lport->root_lport)->exchg_index); - } - - if (xchg->private_data[PKG_PRIVATE_XCHG_ALLOC_TIME] == 0) { - xchg->private_data[PKG_PRIVATE_XCHG_ALLOC_TIME] = - (u32)atomic64_inc_return(&((struct unf_lport *)lport->root_lport)->exchg_index); - } - - atomic_set(&xchg->ref_cnt, 0); - atomic_set(&xchg->delay_flag, 0); - - if (delayed_work_pending(&xchg->timeout_work)) - UNF_DEL_XCHG_TIMER_SAFE(xchg); - - INIT_DELAYED_WORK(&xchg->timeout_work, unf_fc_ini_io_xchg_time_out); -} - -static struct unf_xchg *unf_alloc_io_xchg(struct unf_lport *lport, - struct unf_xchg_mgr *xchg_mgr) -{ - struct unf_xchg *xchg = NULL; - struct list_head *list_node = NULL; - struct unf_xchg_free_pool *free_pool = NULL; - struct unf_xchg_hot_pool *hot_pool = NULL; - ulong flags = 0; - - FC_CHECK_RETURN_VALUE(xchg_mgr, NULL); - FC_CHECK_RETURN_VALUE(lport, NULL); - - free_pool = &xchg_mgr->free_pool; - hot_pool = xchg_mgr->hot_pool; - FC_CHECK_RETURN_VALUE(free_pool, NULL); - FC_CHECK_RETURN_VALUE(hot_pool, NULL); - - /* 1. Free Pool */ - spin_lock_irqsave(&free_pool->xchg_freepool_lock, flags); - if (unlikely(list_empty(&free_pool->list_free_xchg_list))) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_INFO, - "Port(0x%x) have no Exchange anymore.", - lport->port_id); - spin_unlock_irqrestore(&free_pool->xchg_freepool_lock, flags); - return NULL; - } - - /* Select an idle node from free pool */ - list_node = UNF_OS_LIST_NEXT(&free_pool->list_free_xchg_list); - list_del(list_node); - free_pool->total_fcp_xchg--; - spin_unlock_irqrestore(&free_pool->xchg_freepool_lock, flags); - - xchg = list_entry(list_node, struct unf_xchg, list_xchg_entry); - /* - * Hot Pool: - * When xchg is mounted to Hot Pool, the mount mode and release mode - * of Xchg must be specified and stored in the sfs linked list. - */ - flags = 0; - spin_lock_irqsave(&hot_pool->xchg_hotpool_lock, flags); - if (unf_alloc_hot_pool_slab(hot_pool, xchg) != RETURN_OK) { - spin_unlock_irqrestore(&hot_pool->xchg_hotpool_lock, flags); - unf_add_back_to_fcp_list(free_pool, xchg); - if (unlikely(lport->port_removing)) - unf_check_xchg_mgr_status(xchg_mgr); - - return NULL; - } - list_add_tail(&xchg->list_xchg_entry, &hot_pool->ini_busylist); - spin_unlock_irqrestore(&hot_pool->xchg_hotpool_lock, flags); - - /* 3. Exchange State */ - spin_lock_irqsave(&xchg->xchg_state_lock, flags); - unf_init_io_xchg_param(xchg, lport, xchg_mgr); - spin_unlock_irqrestore(&xchg->xchg_state_lock, flags); - - return xchg; -} - -static void unf_add_back_to_sfs_list(struct unf_xchg_free_pool *free_pool, - struct unf_xchg *xchg) -{ - ulong flags = 0; - - FC_CHECK_RETURN_VOID(free_pool); - FC_CHECK_RETURN_VOID(xchg); - - unf_init_xchg_attribute(xchg); - - spin_lock_irqsave(&free_pool->xchg_freepool_lock, flags); - - list_add_tail(&xchg->list_xchg_entry, &free_pool->list_sfs_xchg_list); - free_pool->total_sfs_xchg++; - spin_unlock_irqrestore(&free_pool->xchg_freepool_lock, flags); -} - -static void unf_free_sfs_xchg(struct unf_xchg *xchg) -{ - struct unf_xchg_free_pool *free_pool = NULL; - struct unf_xchg_mgr *xchg_mgr = NULL; - struct unf_lport *unf_lport = NULL; - - FC_CHECK_RETURN_VOID(xchg); - - free_pool = xchg->free_pool; - unf_lport = xchg->lport; - xchg_mgr = xchg->xchg_mgr; - - /* The memory is applied for when the GID_PT/GID_FT is sent. - * If no response is received, the GID_PT/GID_FT needs to be forcibly - * released. - */ - - unf_free_one_big_sfs(xchg); - - unf_add_back_to_sfs_list(free_pool, xchg); - - if (unlikely(unf_lport->port_removing)) - unf_check_xchg_mgr_status(xchg_mgr); -} - -static void unf_fc_xchg_add_timer(void *xchg, ulong time_ms, - enum unf_timer_type time_type) -{ - ulong flag = 0; - struct unf_xchg *unf_xchg = NULL; - ulong times_ms = time_ms; - struct unf_lport *unf_lport = NULL; - - FC_CHECK_RETURN_VOID(xchg); - unf_xchg = (struct unf_xchg *)xchg; - unf_lport = unf_xchg->lport; - FC_CHECK_RETURN_VOID(unf_lport); - - /* update timeout */ - switch (time_type) { - /* The processing of TGT RRQ timeout is the same as that of TGT IO - * timeout. The timeout period is different. - */ - case UNF_TIMER_TYPE_TGT_RRQ: - times_ms = times_ms + UNF_TGT_RRQ_REDUNDANT_TIME; - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_INFO, - "TGT RRQ Timer set."); - break; - - case UNF_TIMER_TYPE_INI_RRQ: - times_ms = times_ms - UNF_INI_RRQ_REDUNDANT_TIME; - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_INFO, - "INI RRQ Timer set."); - break; - - case UNF_TIMER_TYPE_SFS: - times_ms = times_ms + UNF_INI_ELS_REDUNDANT_TIME; - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_INFO, - "INI ELS Timer set."); - break; - default: - break; - } - - /* The xchg of the timer must be valid. If the reference count of xchg - * is 0, the timer must not be added - */ - if (atomic_read(&unf_xchg->ref_cnt) <= 0) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_KEVENT, - "[warn]Abnormal Exchange(0x%p), Reference count(0x%x), Can't add timer.", - unf_xchg, atomic_read(&unf_xchg->ref_cnt)); - return; - } - - /* Delay Work: Hold for timer */ - spin_lock_irqsave(&unf_xchg->xchg_state_lock, flag); - if (queue_delayed_work(unf_lport->xchg_wq, &unf_xchg->timeout_work, - (ulong)msecs_to_jiffies((u32)times_ms))) { - /* hold for timer */ - atomic_inc(&unf_xchg->ref_cnt); - } - spin_unlock_irqrestore(&unf_xchg->xchg_state_lock, flag); -} - -static void unf_init_sfs_xchg_param(struct unf_xchg *xchg, - struct unf_lport *lport, - struct unf_xchg_mgr *xchg_mgr) -{ - xchg->free_pool = &xchg_mgr->free_pool; - xchg->hot_pool = xchg_mgr->hot_pool; - xchg->lport = lport; - xchg->xchg_mgr = xchg_mgr; - xchg->free_xchg = unf_free_sfs_xchg; - xchg->xchg_type = UNF_XCHG_TYPE_SFS; - xchg->io_state = UNF_IO_STATE_NEW; - xchg->scsi_cmnd_info.result = 0; - xchg->ob_callback_sts = UNF_IO_SUCCESS; - - xchg->private_data[PKG_PRIVATE_XCHG_ALLOC_TIME] = - (u32)atomic64_inc_return(&((struct unf_lport *)lport->root_lport)->exchg_index); - - if (xchg->private_data[PKG_PRIVATE_XCHG_ALLOC_TIME] == - INVALID_VALUE32) { - xchg->private_data[PKG_PRIVATE_XCHG_ALLOC_TIME] = - (u32)atomic64_inc_return(&((struct unf_lport *)lport->root_lport)->exchg_index); - } - - if (xchg->private_data[PKG_PRIVATE_XCHG_ALLOC_TIME] == 0) { - xchg->private_data[PKG_PRIVATE_XCHG_ALLOC_TIME] = - (u32)atomic64_inc_return(&((struct unf_lport *)lport->root_lport)->exchg_index); - } - - if (delayed_work_pending(&xchg->timeout_work)) - UNF_DEL_XCHG_TIMER_SAFE(xchg); - - INIT_DELAYED_WORK(&xchg->timeout_work, unf_sfs_xchg_time_out); -} - -static struct unf_xchg *unf_alloc_sfs_xchg(struct unf_lport *lport, - struct unf_xchg_mgr *xchg_mgr) -{ - struct unf_xchg *xchg = NULL; - struct list_head *list_node = NULL; - struct unf_xchg_free_pool *free_pool = NULL; - struct unf_xchg_hot_pool *hot_pool = NULL; - ulong flags = 0; - - FC_CHECK_RETURN_VALUE(lport, NULL); - FC_CHECK_RETURN_VALUE(xchg_mgr, NULL); - free_pool = &xchg_mgr->free_pool; - hot_pool = xchg_mgr->hot_pool; - FC_CHECK_RETURN_VALUE(free_pool, NULL); - FC_CHECK_RETURN_VALUE(hot_pool, NULL); - - /* Select an idle node from free pool */ - spin_lock_irqsave(&free_pool->xchg_freepool_lock, flags); - if (list_empty(&free_pool->list_sfs_xchg_list)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_MAJOR, - "Port(0x%x) have no Exchange anymore.", - lport->port_id); - spin_unlock_irqrestore(&free_pool->xchg_freepool_lock, flags); - return NULL; - } - - list_node = UNF_OS_LIST_NEXT(&free_pool->list_sfs_xchg_list); - list_del(list_node); - free_pool->total_sfs_xchg--; - spin_unlock_irqrestore(&free_pool->xchg_freepool_lock, flags); - - xchg = list_entry(list_node, struct unf_xchg, list_xchg_entry); - /* - * The xchg is mounted to the Hot Pool. - * The mount mode and release mode of the xchg must be specified - * and stored in the sfs linked list. - */ - flags = 0; - spin_lock_irqsave(&hot_pool->xchg_hotpool_lock, flags); - if (unf_alloc_hot_pool_slab(hot_pool, xchg) != RETURN_OK) { - spin_unlock_irqrestore(&hot_pool->xchg_hotpool_lock, flags); - unf_add_back_to_sfs_list(free_pool, xchg); - if (unlikely(lport->port_removing)) - unf_check_xchg_mgr_status(xchg_mgr); - - return NULL; - } - - list_add_tail(&xchg->list_xchg_entry, &hot_pool->sfs_busylist); - hot_pool->total_xchges++; - spin_unlock_irqrestore(&hot_pool->xchg_hotpool_lock, flags); - - spin_lock_irqsave(&xchg->xchg_state_lock, flags); - unf_init_sfs_xchg_param(xchg, lport, xchg_mgr); - spin_unlock_irqrestore(&xchg->xchg_state_lock, flags); - - return xchg; -} - -static void *unf_get_new_xchg(void *lport, u32 xchg_type) -{ - struct unf_lport *unf_lport = NULL; - struct unf_xchg_mgr *xchg_mgr = NULL; - struct unf_xchg *xchg = NULL; - u32 exchg_type = 0; - u16 xchg_mgr_type; - u32 rtry_cnt = 0; - u32 last_exchg_mgr_idx; - - xchg_mgr_type = (xchg_type >> UNF_SHIFT_16); - exchg_type = xchg_type & SPFC_XCHG_TYPE_MASK; - FC_CHECK_RETURN_VALUE(lport, NULL); - - /* In the case of NPIV, the lport is the Vport pointer, - * and the share uses the ExchMgr of the RootLport. - */ - unf_lport = ((struct unf_lport *)lport)->root_lport; - FC_CHECK_RETURN_VALUE(unf_lport, NULL); - - if (unlikely((atomic_read(&unf_lport->lport_no_operate_flag) == UNF_LPORT_NOP) || - (atomic_read(&((struct unf_lport *)lport)->lport_no_operate_flag) == - UNF_LPORT_NOP))) { - return NULL; - } - - last_exchg_mgr_idx = (u32)atomic64_inc_return(&unf_lport->last_exchg_mgr_idx); -try_next_mgr: - rtry_cnt++; - if (unlikely(rtry_cnt > UNF_EXCHG_MGR_NUM)) - return NULL; - - /* If Fixed mode,only use XchgMgr 0 */ - if (unlikely(xchg_mgr_type == UNF_XCHG_MGR_TYPE_FIXED)) { - xchg_mgr = (struct unf_xchg_mgr *)unf_lport->xchg_mgr[ARRAY_INDEX_0]; - } else { - xchg_mgr = (struct unf_xchg_mgr *)unf_lport - ->xchg_mgr[last_exchg_mgr_idx % UNF_EXCHG_MGR_NUM]; - } - if (unlikely(!xchg_mgr)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[err]Port(0x%x) get exchangemgr %u is null.", - unf_lport->port_id, last_exchg_mgr_idx % UNF_EXCHG_MGR_NUM); - return NULL; - } - last_exchg_mgr_idx++; - - /* Allocate entries based on the Exchange type */ - switch (exchg_type) { - case UNF_XCHG_TYPE_SFS: - xchg = unf_alloc_sfs_xchg(lport, xchg_mgr); - break; - case UNF_XCHG_TYPE_INI: - xchg = unf_alloc_io_xchg(lport, xchg_mgr); - break; - - default: - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_MAJOR, - "Port(0x%x) unwonted, Exchange type(0x%x).", - unf_lport->port_id, exchg_type); - break; - } - - if (likely(xchg)) { - xchg->oxid = INVALID_VALUE16; - xchg->abort_oxid = INVALID_VALUE16; - xchg->rxid = INVALID_VALUE16; - xchg->debug_hook = false; - xchg->alloc_jif = jiffies; - - atomic_set(&xchg->ref_cnt, 1); - atomic_set(&xchg->esgl_cnt, 0); - } else { - goto try_next_mgr; - } - - return xchg; -} - -static void unf_free_xchg(void *lport, void *xchg) -{ - struct unf_xchg *unf_xchg = NULL; - - FC_CHECK_RETURN_VOID(xchg); - - unf_xchg = (struct unf_xchg *)xchg; - unf_xchg_ref_dec(unf_xchg, XCHG_FREE_XCHG); -} - -u32 unf_init_xchg_mgr_temp(struct unf_lport *lport) -{ - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - - lport->xchg_mgr_temp.unf_xchg_get_free_and_init = unf_get_new_xchg; - lport->xchg_mgr_temp.unf_xchg_release = unf_free_xchg; - lport->xchg_mgr_temp.unf_look_up_xchg_by_tag = unf_look_up_xchg_by_tag; - lport->xchg_mgr_temp.unf_look_up_xchg_by_id = unf_find_xchg_by_ox_id; - lport->xchg_mgr_temp.unf_xchg_add_timer = unf_fc_xchg_add_timer; - lport->xchg_mgr_temp.unf_xchg_cancel_timer = unf_xchg_cancel_timer; - lport->xchg_mgr_temp.unf_xchg_abort_all_io = unf_xchg_abort_all_xchg; - lport->xchg_mgr_temp.unf_look_up_xchg_by_cmnd_sn = unf_look_up_xchg_by_cmnd_sn; - lport->xchg_mgr_temp.unf_xchg_abort_by_lun = unf_xchg_abort_by_lun; - lport->xchg_mgr_temp.unf_xchg_abort_by_session = unf_xchg_abort_by_session; - lport->xchg_mgr_temp.unf_xchg_mgr_io_xchg_abort = unf_xchg_mgr_io_xchg_abort; - lport->xchg_mgr_temp.unf_xchg_mgr_sfs_xchg_abort = unf_xchg_mgr_sfs_xchg_abort; - - return RETURN_OK; -} - -void unf_release_xchg_mgr_temp(struct unf_lport *lport) -{ - FC_CHECK_RETURN_VOID(lport); - - if (lport->dirty_flag & UNF_LPORT_DIRTY_FLAG_XCHGMGR_DIRTY) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "Port(0x%x) has dirty exchange, Don't release exchange manager template.", - lport->port_id); - - return; - } - - memset(&lport->xchg_mgr_temp, 0, sizeof(struct unf_cm_xchg_mgr_template)); - - lport->destroy_step = UNF_LPORT_DESTROY_STEP_7_DESTROY_XCHG_MGR_TMP; -} - -void unf_set_hot_pool_wait_state(struct unf_lport *lport, bool wait_state) -{ - struct unf_xchg_hot_pool *hot_pool = NULL; - ulong pool_lock_flags = 0; - u32 i = 0; - - FC_CHECK_RETURN_VOID(lport); - - for (i = 0; i < UNF_EXCHG_MGR_NUM; i++) { - hot_pool = unf_get_hot_pool_by_lport(lport, i); - if (unlikely(!hot_pool)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x) hot pool is NULL", - lport->port_id); - continue; - } - - spin_lock_irqsave(&hot_pool->xchg_hotpool_lock, pool_lock_flags); - hot_pool->wait_state = wait_state; - spin_unlock_irqrestore(&hot_pool->xchg_hotpool_lock, pool_lock_flags); - } -} - -u32 unf_xchg_ref_inc(struct unf_xchg *xchg, enum unf_ioflow_id io_stage) -{ - struct unf_xchg_hot_pool *hot_pool = NULL; - ulong flags = 0; - u32 ret = UNF_RETURN_ERROR; - - FC_CHECK_RETURN_VALUE(xchg, UNF_RETURN_ERROR); - - if (unlikely(xchg->debug_hook)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_MAJOR, - "[info]Xchg(0x%p) State(0x%x) SID_DID(0x%x_0x%x) OX_ID_RX_ID(0x%x_0x%x) AllocJiff(%llu) Refcnt(%d) Stage(%s)", - xchg, xchg->io_state, xchg->sid, xchg->did, - xchg->oxid, xchg->rxid, xchg->alloc_jif, - atomic_read(&xchg->ref_cnt), - io_stage_table[io_stage].stage); - } - - hot_pool = xchg->hot_pool; - FC_CHECK_RETURN_VALUE(hot_pool, UNF_RETURN_ERROR); - - /* Exchange -> Hot Pool Tag check */ - if (unlikely((xchg->hotpooltag >= (hot_pool->slab_total_sum + hot_pool->base)) || - xchg->hotpooltag < hot_pool->base)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[err]Xchg(0x%p) S_ID(%xh) D_ID(0x%x) hot_pool_tag(0x%x) is bigger than slab total num(0x%x) base(0x%x)", - xchg, xchg->sid, xchg->did, xchg->hotpooltag, - hot_pool->slab_total_sum + hot_pool->base, hot_pool->base); - - return UNF_RETURN_ERROR; - } - - /* atomic read & inc */ - spin_lock_irqsave(&xchg->xchg_state_lock, flags); - if (unlikely(atomic_read(&xchg->ref_cnt) <= 0)) { - ret = UNF_RETURN_ERROR; - } else { - if (unf_get_xchg_by_xchg_tag(hot_pool, xchg->hotpooltag - hot_pool->base) == xchg) { - atomic_inc(&xchg->ref_cnt); - ret = RETURN_OK; - } else { - ret = UNF_RETURN_ERROR; - } - } - spin_unlock_irqrestore(&xchg->xchg_state_lock, flags); - - return ret; -} - -void unf_xchg_ref_dec(struct unf_xchg *xchg, enum unf_ioflow_id io_stage) -{ - /* Atomic dec ref_cnt & test, free exchange if necessary (ref_cnt==0) */ - struct unf_xchg_hot_pool *hot_pool = NULL; - void (*free_xchg)(struct unf_xchg *) = NULL; - ulong flags = 0; - ulong xchg_lock_falgs = 0; - - FC_CHECK_RETURN_VOID(xchg); - - if (xchg->debug_hook) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_MAJOR, - "[info]Xchg(0x%p) State(0x%x) SID_DID(0x%x_0x%x) OXID_RXID(0x%x_0x%x) AllocJiff(%llu) Refcnt(%d) Statge %s", - xchg, xchg->io_state, xchg->sid, xchg->did, xchg->oxid, - xchg->rxid, xchg->alloc_jif, - atomic_read(&xchg->ref_cnt), - io_stage_table[io_stage].stage); - } - - hot_pool = xchg->hot_pool; - FC_CHECK_RETURN_VOID(hot_pool); - FC_CHECK_RETURN_VOID((xchg->hotpooltag >= hot_pool->base)); - - /* - * 1. Atomic dec & test - * 2. Free exchange if necessary (ref_cnt == 0) - */ - spin_lock_irqsave(&xchg->xchg_state_lock, xchg_lock_falgs); - if (atomic_dec_and_test(&xchg->ref_cnt)) { - free_xchg = xchg->free_xchg; - spin_unlock_irqrestore(&xchg->xchg_state_lock, xchg_lock_falgs); - spin_lock_irqsave(&hot_pool->xchg_hotpool_lock, flags); - unf_hot_pool_slab_set(hot_pool, - xchg->hotpooltag - hot_pool->base, NULL); - /* Delete exchange list entry */ - list_del_init(&xchg->list_xchg_entry); - hot_pool->total_xchges--; - spin_unlock_irqrestore(&hot_pool->xchg_hotpool_lock, flags); - - /* unf_free_fcp_xchg --->>> unf_done_ini_xchg */ - if (free_xchg) - free_xchg(xchg); - } else { - spin_unlock_irqrestore(&xchg->xchg_state_lock, xchg_lock_falgs); - } -} - -static void unf_init_xchg_attribute(struct unf_xchg *xchg) -{ - ulong flags = 0; - - FC_CHECK_RETURN_VOID(xchg); - - spin_lock_irqsave(&xchg->xchg_state_lock, flags); - xchg->xchg_mgr = NULL; - xchg->free_pool = NULL; - xchg->hot_pool = NULL; - xchg->lport = NULL; - xchg->rport = NULL; - xchg->disc_rport = NULL; - xchg->io_state = UNF_IO_STATE_NEW; - xchg->io_send_stage = TGT_IO_SEND_STAGE_NONE; - xchg->io_send_result = TGT_IO_SEND_RESULT_INVALID; - xchg->io_send_abort = false; - xchg->io_abort_result = false; - xchg->abts_state = 0; - xchg->oxid = INVALID_VALUE16; - xchg->abort_oxid = INVALID_VALUE16; - xchg->rxid = INVALID_VALUE16; - xchg->sid = INVALID_VALUE32; - xchg->did = INVALID_VALUE32; - xchg->oid = INVALID_VALUE32; - xchg->disc_portid = INVALID_VALUE32; - xchg->seq_id = INVALID_VALUE8; - xchg->cmnd_code = INVALID_VALUE32; - xchg->cmnd_sn = INVALID_VALUE64; - xchg->data_len = 0; - xchg->resid_len = 0; - xchg->data_direction = DMA_NONE; - xchg->hotpooltag = INVALID_VALUE16; - xchg->big_sfs_buf = NULL; - xchg->may_consume_res_cnt = 0; - xchg->fast_consume_res_cnt = 0; - xchg->io_front_jif = INVALID_VALUE64; - xchg->ob_callback_sts = UNF_IO_SUCCESS; - xchg->start_jif = 0; - xchg->rport_bind_jifs = INVALID_VALUE64; - xchg->scsi_id = INVALID_VALUE32; - xchg->qos_level = 0; - xchg->world_id = INVALID_VALUE32; - - memset(&xchg->seq, 0, sizeof(struct unf_seq)); - memset(&xchg->fcp_cmnd, 0, sizeof(struct unf_fcp_cmnd)); - memset(&xchg->scsi_cmnd_info, 0, sizeof(struct unf_scsi_cmd_info)); - memset(&xchg->dif_info, 0, sizeof(struct dif_info)); - memset(xchg->private_data, 0, (PKG_MAX_PRIVATE_DATA_SIZE * sizeof(u32))); - xchg->echo_info.echo_result = UNF_ELS_ECHO_RESULT_OK; - xchg->echo_info.response_time = 0; - - if (xchg->xchg_type == UNF_XCHG_TYPE_SFS) { - if (xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr) { - memset(xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr, 0, - sizeof(union unf_sfs_u)); - xchg->fcp_sfs_union.sfs_entry.cur_offset = 0; - } - } else if (xchg->xchg_type != UNF_XCHG_TYPE_INI) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_MAJOR, - "Exchange Type(0x%x) SFS Union uninited.", - xchg->xchg_type); - } - xchg->xchg_type = UNF_XCHG_TYPE_INVALID; - xchg->xfer_or_rsp_echo = NULL; - xchg->scsi_or_tgt_cmnd_func = NULL; - xchg->ob_callback = NULL; - xchg->callback = NULL; - xchg->free_xchg = NULL; - - atomic_set(&xchg->ref_cnt, 0); - atomic_set(&xchg->esgl_cnt, 0); - atomic_set(&xchg->delay_flag, 0); - - if (delayed_work_pending(&xchg->timeout_work)) - UNF_DEL_XCHG_TIMER_SAFE(xchg); - - spin_unlock_irqrestore(&xchg->xchg_state_lock, flags); -} - -bool unf_busy_io_completed(struct unf_lport *lport) -{ - struct unf_xchg_mgr *xchg_mgr = NULL; - ulong pool_lock_flags = 0; - u32 i; - - FC_CHECK_RETURN_VALUE(lport, true); - - for (i = 0; i < UNF_EXCHG_MGR_NUM; i++) { - xchg_mgr = unf_get_xchg_mgr_by_lport(lport, i); - if (unlikely(!xchg_mgr)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x) Exchange Manager is NULL", - lport->port_id); - continue; - } - - spin_lock_irqsave(&xchg_mgr->hot_pool->xchg_hotpool_lock, - pool_lock_flags); - if (!list_empty(&xchg_mgr->hot_pool->ini_busylist)) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_INFO, - "[info]Port(0x%x) ini busylist is not empty.", - lport->port_id); - spin_unlock_irqrestore(&xchg_mgr->hot_pool->xchg_hotpool_lock, - pool_lock_flags); - return false; - } - spin_unlock_irqrestore(&xchg_mgr->hot_pool->xchg_hotpool_lock, - pool_lock_flags); - } - return true; -} diff --git a/drivers/scsi/spfc/common/unf_exchg.h b/drivers/scsi/spfc/common/unf_exchg.h deleted file mode 100644 index 0a48be31b971..000000000000 --- a/drivers/scsi/spfc/common/unf_exchg.h +++ /dev/null @@ -1,436 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef UNF_EXCHG_H -#define UNF_EXCHG_H - -#include "unf_type.h" -#include "unf_fcstruct.h" -#include "unf_lport.h" -#include "unf_scsi_common.h" - -enum unf_ioflow_id { - XCHG_ALLOC = 0, - TGT_RECEIVE_ABTS, - TGT_ABTS_DONE, - TGT_IO_SRR, - SFS_RESPONSE, - SFS_TIMEOUT, - INI_SEND_CMND, - INI_RESPONSE_DONE, - INI_EH_ABORT, - INI_EH_DEVICE_RESET, - INI_EH_BLS_DONE, - INI_IO_TIMEOUT, - INI_REQ_TIMEOUT, - XCHG_CANCEL_TIMER, - XCHG_FREE_XCHG, - SEND_ELS, - IO_XCHG_WAIT, - XCHG_BUTT -}; - -enum unf_xchg_type { - UNF_XCHG_TYPE_INI = 0, /* INI IO */ - UNF_XCHG_TYPE_SFS = 1, - UNF_XCHG_TYPE_INVALID -}; - -enum unf_xchg_mgr_type { - UNF_XCHG_MGR_TYPE_RANDOM = 0, - UNF_XCHG_MGR_TYPE_FIXED = 1, - UNF_XCHG_MGR_TYPE_INVALID -}; - -enum tgt_io_send_stage { - TGT_IO_SEND_STAGE_NONE = 0, - TGT_IO_SEND_STAGE_DOING = 1, /* xfer/rsp into queue */ - TGT_IO_SEND_STAGE_DONE = 2, /* xfer/rsp into queue complete */ - TGT_IO_SEND_STAGE_ECHO = 3, /* driver handled TSTS */ - TGT_IO_SEND_STAGE_INVALID -}; - -enum tgt_io_send_result { - TGT_IO_SEND_RESULT_OK = 0, /* xfer/rsp enqueue succeed */ - TGT_IO_SEND_RESULT_FAIL = 1, /* xfer/rsp enqueue fail */ - TGT_IO_SEND_RESULT_INVALID -}; - -struct unf_io_flow_id { - char *stage; -}; - -#define unf_check_oxid_matched(ox_id, oid, xchg) \ - (((ox_id) == (xchg)->oxid) && ((oid) == (xchg)->oid) && \ - (atomic_read(&(xchg)->ref_cnt) > 0)) - -#define UNF_CHECK_ALLOCTIME_VALID(lport, xchg_tag, exchg, pkg_alloc_time, \ - xchg_alloc_time) \ - do { \ - if (unlikely(((pkg_alloc_time) != 0) && \ - ((pkg_alloc_time) != (xchg_alloc_time)))) { \ - FC_DRV_PRINT(UNF_LOG_NORMAL, UNF_ERR, \ - "Lport(0x%x_0x%x_0x%x_0x%p) AllocTime is not " \ - "equal,PKG " \ - "AllocTime:0x%x,Exhg AllocTime:0x%x", \ - (lport)->port_id, (lport)->nport_id, xchg_tag, \ - exchg, pkg_alloc_time, xchg_alloc_time); \ - return UNF_RETURN_ERROR; \ - }; \ - if (unlikely((pkg_alloc_time) == 0)) { \ - FC_DRV_PRINT(UNF_LOG_NORMAL, UNF_MAJOR, \ - "Lport(0x%x_0x%x_0x%x_0x%p) pkgtime err,PKG " \ - "AllocTime:0x%x,Exhg AllocTime:0x%x", \ - (lport)->port_id, (lport)->nport_id, xchg_tag, \ - exchg, pkg_alloc_time, xchg_alloc_time); \ - }; \ - } while (0) - -#define UNF_SET_SCSI_CMND_RESULT(xchg, cmnd_result) \ - ((xchg)->scsi_cmnd_info.result = (cmnd_result)) - -#define UNF_GET_GS_SFS_XCHG_TIMER(lport) (3 * (ulong)(lport)->ra_tov) - -#define UNF_GET_BLS_SFS_XCHG_TIMER(lport) (2 * (ulong)(lport)->ra_tov) - -#define UNF_GET_ELS_SFS_XCHG_TIMER(lport) (2 * (ulong)(lport)->ra_tov) - -#define UNF_ELS_ECHO_RESULT_OK 0 -#define UNF_ELS_ECHO_RESULT_FAIL 1 - -struct unf_xchg; -/* Xchg hot pool, busy IO lookup Xchg */ -struct unf_xchg_hot_pool { - /* Xchg sum, in hot pool */ - u16 total_xchges; - bool wait_state; - - /* pool lock */ - spinlock_t xchg_hotpool_lock; - - /* Xchg posiontion list */ - struct list_head sfs_busylist; - struct list_head ini_busylist; - struct list_head list_destroy_xchg; - - /* Next free hot point */ - u16 slab_next_index; - u16 slab_total_sum; - u16 base; - - struct unf_lport *lport; - - struct unf_xchg *xchg_slab[ARRAY_INDEX_0]; -}; - -/* Xchg's FREE POOL */ -struct unf_xchg_free_pool { - spinlock_t xchg_freepool_lock; - - u32 fcp_xchg_sum; - - /* IO used Xchg */ - struct list_head list_free_xchg_list; - u32 total_fcp_xchg; - - /* SFS used Xchg */ - struct list_head list_sfs_xchg_list; - u32 total_sfs_xchg; - u32 sfs_xchg_sum; - - struct completion *xchg_mgr_completion; -}; - -struct unf_big_sfs { - struct list_head entry_bigsfs; - void *addr; - u32 size; -}; - -struct unf_big_sfs_pool { - void *big_sfs_pool; - u32 free_count; - struct list_head list_freepool; - struct list_head list_busypool; - spinlock_t big_sfs_pool_lock; -}; - -/* Xchg Manager for vport Xchg */ -struct unf_xchg_mgr { - /* MG type */ - u32 mgr_type; - - /* MG entry */ - struct list_head xchg_mgr_entry; - - /* MG attribution */ - u32 mem_szie; - - /* MG alloced resource */ - void *fcp_mm_start; - - u32 sfs_mem_size; - void *sfs_mm_start; - dma_addr_t sfs_phy_addr; - - struct unf_xchg_free_pool free_pool; - struct unf_xchg_hot_pool *hot_pool; - - struct unf_big_sfs_pool big_sfs_pool; - - struct buf_describe big_sfs_buf_list; -}; - -struct unf_seq { - /* Seq ID */ - u8 seq_id; - - /* Seq Cnt */ - u16 seq_cnt; - - /* Seq state and len,maybe used for fcoe */ - u16 seq_stat; - u32 rec_data_len; -}; - -union unf_xchg_fcp_sfs { - struct unf_sfs_entry sfs_entry; - struct unf_fcp_rsp_iu_entry fcp_rsp_entry; -}; - -#define UNF_IO_STATE_NEW 0 -#define TGT_IO_STATE_SEND_XFERRDY (1 << 2) /* succeed to send XFer rdy */ -#define TGT_IO_STATE_RSP (1 << 5) /* chip send rsp */ -#define TGT_IO_STATE_ABORT (1 << 7) - -#define INI_IO_STATE_UPTASK \ - (1 << 15) /* INI Upper-layer Task Management Commands */ -#define INI_IO_STATE_UPABORT \ - (1 << 16) /* INI Upper-layer timeout Abort flag \ - */ -#define INI_IO_STATE_DRABORT (1 << 17) /* INI driver Abort flag */ -#define INI_IO_STATE_DONE (1 << 18) /* INI complete flag */ -#define INI_IO_STATE_WAIT_RRQ (1 << 19) /* INI wait send rrq */ -#define INI_IO_STATE_UPSEND_ERR (1 << 20) /* INI send fail flag */ -/* INI only clear firmware resource flag */ -#define INI_IO_STATE_ABORT_RESOURCE (1 << 21) -/* ioc abort:INI send ABTS ,5S timeout Semaphore,than set 1 */ -#define INI_IO_STATE_ABORT_TIMEOUT (1 << 22) -#define INI_IO_STATE_RRQSEND_ERR (1 << 23) /* INI send RRQ fail flag */ -#define INI_IO_STATE_LOGO (1 << 24) /* INI busy IO session logo status */ -#define INI_IO_STATE_TMF_ABORT (1 << 25) /* INI TMF ABORT IO flag */ -#define INI_IO_STATE_REC_TIMEOUT_WAIT (1 << 26) /* INI REC TIMEOUT WAIT */ -#define INI_IO_STATE_REC_TIMEOUT (1 << 27) /* INI REC TIMEOUT */ - -#define TMF_RESPONSE_RECEIVED (1 << 0) -#define MARKER_STS_RECEIVED (1 << 1) -#define ABTS_RESPONSE_RECEIVED (1 << 2) - -struct unf_scsi_cmd_info { - ulong time_out; - ulong abort_time_out; - void *scsi_cmnd; - void (*done)(struct unf_scsi_cmnd *scsi_cmd); - ini_get_sgl_entry_buf unf_get_sgl_entry_buf; - struct unf_ini_error_code *err_code_table; /* error code table */ - char *sense_buf; - u32 err_code_table_cout; /* Size of the error code table */ - u32 buf_len; - u32 entry_cnt; - u32 result; /* Stores command execution results */ - u32 port_id; -/* Re-search for rport based on scsiid during retry. Otherwise, - *data inconsistency will occur - */ - u32 scsi_id; - void *sgl; - uplevel_cmd_done uplevel_done; -}; - -struct unf_req_sgl_info { - void *sgl; - void *sgl_start; - u32 req_index; - u32 entry_index; -}; - -struct unf_els_echo_info { - u64 response_time; - struct semaphore echo_sync_sema; - u32 echo_result; -}; - -struct unf_xchg { - /* Mg resource relative */ - /* list delete from HotPool */ - struct unf_xchg_hot_pool *hot_pool; - - /* attach to FreePool */ - struct unf_xchg_free_pool *free_pool; - struct unf_xchg_mgr *xchg_mgr; - struct unf_lport *lport; /* Local LPort/VLPort */ - struct unf_rport *rport; /* Rmote Port */ - struct unf_rport *disc_rport; /* Discover Rmote Port */ - struct list_head list_xchg_entry; - struct list_head list_abort_xchg_entry; - spinlock_t xchg_state_lock; - - /* Xchg reference */ - atomic_t ref_cnt; - atomic_t esgl_cnt; - bool debug_hook; - /* Xchg attribution */ - u16 hotpooltag; - u16 abort_oxid; - u32 xchg_type; /* LS,TGT CMND ,REQ,or SCSI Cmnd */ - u16 oxid; - u16 rxid; - u32 sid; - u32 did; - u32 oid; /* ID of the exchange initiator */ - u32 disc_portid; /* Send GNN_ID/GFF_ID NPortId */ - u8 seq_id; - u8 byte_orders; /* Byte order */ - struct unf_seq seq; - - u32 cmnd_code; - u32 world_id; - /* Dif control */ - struct unf_dif_control_info dif_control; - struct dif_info dif_info; - /* IO status Abort,timer out */ - u32 io_state; /* TGT_IO_STATE_E */ - u32 tmf_state; /* TMF STATE */ - u32 ucode_abts_state; - u32 abts_state; - - /* IO Enqueuing */ - enum tgt_io_send_stage io_send_stage; /* tgt_io_send_stage */ - /* IO Enqueuing result, success or failure */ - enum tgt_io_send_result io_send_result; /* tgt_io_send_result */ - - u8 io_send_abort; /* is or not send io abort */ - /*result of io abort cmd(succ:true; fail:false)*/ - u8 io_abort_result; - /* for INI,Indicates the length of the data transmitted over the PCI - * link - */ - u32 data_len; - /* ResidLen,greater than 0 UnderFlow or Less than Overflow */ - int resid_len; - /* +++++++++++++++++IO Special++++++++++++++++++++ */ - /* point to tgt cmnd/req/scsi cmnd */ - /* Fcp cmnd */ - struct unf_fcp_cmnd fcp_cmnd; - - struct unf_scsi_cmd_info scsi_cmnd_info; - - struct unf_req_sgl_info req_sgl_info; - - struct unf_req_sgl_info dif_sgl_info; - - u64 cmnd_sn; - void *pinitiator; - - /* timestamp */ - u64 start_jif; - u64 alloc_jif; - - u64 io_front_jif; - - u32 may_consume_res_cnt; - u32 fast_consume_res_cnt; - - /* scsi req info */ - u32 data_direction; - - struct unf_big_sfs *big_sfs_buf; - - /* scsi cmnd sense_buffer pointer */ - union unf_xchg_fcp_sfs fcp_sfs_union; - - /* One exchange may use several External Sgls */ - struct list_head list_esgls; - struct unf_els_echo_info echo_info; - struct semaphore task_sema; - - /* for RRQ ,IO Xchg add to SFS Xchg */ - void *io_xchg; - - /* Xchg delay work */ - struct delayed_work timeout_work; - - void (*xfer_or_rsp_echo)(struct unf_xchg *xchg, u32 status); - - /* wait list XCHG send function */ - int (*scsi_or_tgt_cmnd_func)(struct unf_xchg *xchg); - - /* send result callback */ - void (*ob_callback)(struct unf_xchg *xchg); - - /* Response IO callback */ - void (*callback)(void *lport, void *rport, void *xchg); - - /* Xchg release function */ - void (*free_xchg)(struct unf_xchg *xchg); - - /* +++++++++++++++++low level Special++++++++++++++++++++ */ - /* private data,provide for low level */ - u32 private_data[PKG_MAX_PRIVATE_DATA_SIZE]; - - u64 rport_bind_jifs; - - /* sfs exchg ob callback status */ - u32 ob_callback_sts; - u32 scsi_id; - u32 qos_level; - void *ls_rsp_addr; - void *ls_req; - u32 status; - atomic_t delay_flag; - void *upper_ct; -}; - -struct unf_esgl_page * -unf_get_and_add_one_free_esgl_page(struct unf_lport *lport, - struct unf_xchg *xchg); -void unf_release_xchg_mgr_temp(struct unf_lport *lport); -u32 unf_init_xchg_mgr_temp(struct unf_lport *lport); -u32 unf_alloc_xchg_resource(struct unf_lport *lport); -void unf_free_all_xchg_mgr(struct unf_lport *lport); -void unf_xchg_mgr_destroy(struct unf_lport *lport); -u32 unf_xchg_ref_inc(struct unf_xchg *xchg, enum unf_ioflow_id io_stage); -void unf_xchg_ref_dec(struct unf_xchg *xchg, enum unf_ioflow_id io_stage); -struct unf_xchg_mgr *unf_get_xchg_mgr_by_lport(struct unf_lport *lport, - u32 mgr_idx); -struct unf_xchg_hot_pool *unf_get_hot_pool_by_lport(struct unf_lport *lport, - u32 mgr_idx); -void unf_free_lport_ini_xchg(struct unf_xchg_mgr *xchg_mgr, bool done_ini_flag); -struct unf_xchg *unf_cm_lookup_xchg_by_cmnd_sn(void *lport, u64 command_sn, - u32 world_id, void *pinitiator); -void *unf_cm_lookup_xchg_by_id(void *lport, u16 ox_id, u32 oid); -void unf_cm_xchg_abort_by_lun(struct unf_lport *lport, struct unf_rport *rport, - u64 lun_id, void *tm_xchg, - bool abort_all_lun_flag); -void unf_cm_xchg_abort_by_session(struct unf_lport *lport, - struct unf_rport *rport); - -void unf_cm_xchg_mgr_abort_io_by_id(struct unf_lport *lport, - struct unf_rport *rport, u32 sid, u32 did, - u32 extra_io_stat); -void unf_cm_xchg_mgr_abort_sfs_by_id(struct unf_lport *lport, - struct unf_rport *rport, u32 sid, u32 did); -void unf_cm_free_xchg(void *lport, void *xchg); -void *unf_cm_get_free_xchg(void *lport, u32 xchg_type); -void *unf_cm_lookup_xchg_by_tag(void *lport, u16 hot_pool_tag); -void unf_release_esgls(struct unf_xchg *xchg); -void unf_show_all_xchg(struct unf_lport *lport, struct unf_xchg_mgr *xchg_mgr); -void unf_destroy_dirty_xchg(struct unf_lport *lport, bool show_only); -void unf_wake_up_scsi_task_cmnd(struct unf_lport *lport); -void unf_set_hot_pool_wait_state(struct unf_lport *lport, bool wait_state); -void unf_free_lport_all_xchg(struct unf_lport *lport); -extern u32 unf_get_up_level_cmnd_errcode(struct unf_ini_error_code *err_table, - u32 err_table_count, u32 drv_err_code); -bool unf_busy_io_completed(struct unf_lport *lport); - -#endif diff --git a/drivers/scsi/spfc/common/unf_exchg_abort.c b/drivers/scsi/spfc/common/unf_exchg_abort.c deleted file mode 100644 index 68f751be04aa..000000000000 --- a/drivers/scsi/spfc/common/unf_exchg_abort.c +++ /dev/null @@ -1,825 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#include "unf_exchg_abort.h" -#include "unf_log.h" -#include "unf_common.h" -#include "unf_rport.h" -#include "unf_service.h" -#include "unf_ls.h" -#include "unf_io.h" - -void unf_cm_xchg_mgr_abort_io_by_id(struct unf_lport *lport, struct unf_rport *rport, u32 sid, - u32 did, u32 extra_io_state) -{ - /* - * for target session: set ABORT - * 1. R_Port remove - * 2. Send PLOGI_ACC callback - * 3. RCVD PLOGI - * 4. RCVD LOGO - */ - FC_CHECK_RETURN_VOID(lport); - - if (lport->xchg_mgr_temp.unf_xchg_mgr_io_xchg_abort) { - /* The SID/DID of the Xchg is in reverse direction in different - * phases. Therefore, the reverse direction needs to be - * considered - */ - lport->xchg_mgr_temp.unf_xchg_mgr_io_xchg_abort(lport, rport, sid, did, - extra_io_state); - lport->xchg_mgr_temp.unf_xchg_mgr_io_xchg_abort(lport, rport, did, sid, - extra_io_state); - } -} - -void unf_cm_xchg_mgr_abort_sfs_by_id(struct unf_lport *lport, - struct unf_rport *rport, u32 sid, u32 did) -{ - FC_CHECK_RETURN_VOID(lport); - - if (lport->xchg_mgr_temp.unf_xchg_mgr_sfs_xchg_abort) { - /* The SID/DID of the Xchg is in reverse direction in different - * phases, therefore, the reverse direction needs to be - * considered - */ - lport->xchg_mgr_temp.unf_xchg_mgr_sfs_xchg_abort(lport, rport, sid, did); - lport->xchg_mgr_temp.unf_xchg_mgr_sfs_xchg_abort(lport, rport, did, sid); - } -} - -void unf_cm_xchg_abort_by_lun(struct unf_lport *lport, struct unf_rport *rport, - u64 lun_id, void *xchg, bool abort_all_lun_flag) -{ - /* - * LUN Reset: set UP_ABORT tag, with: - * INI_Busy_list, IO_Wait_list, - * IO_Delay_list, IO_Delay_transfer_list - */ - void (*unf_xchg_abort_by_lun)(void *, void *, u64, void *, bool) = NULL; - - FC_CHECK_RETURN_VOID(lport); - - unf_xchg_abort_by_lun = lport->xchg_mgr_temp.unf_xchg_abort_by_lun; - if (unf_xchg_abort_by_lun) - unf_xchg_abort_by_lun((void *)lport, (void *)rport, lun_id, - xchg, abort_all_lun_flag); -} - -void unf_cm_xchg_abort_by_session(struct unf_lport *lport, struct unf_rport *rport) -{ - void (*unf_xchg_abort_by_session)(void *, void *) = NULL; - - FC_CHECK_RETURN_VOID(lport); - - unf_xchg_abort_by_session = lport->xchg_mgr_temp.unf_xchg_abort_by_session; - if (unf_xchg_abort_by_session) - unf_xchg_abort_by_session((void *)lport, (void *)rport); -} - -static void unf_xchg_abort_all_sfs_xchg(struct unf_lport *lport, bool clean) -{ - struct unf_xchg_hot_pool *hot_pool = NULL; - struct list_head *xchg_node = NULL; - struct list_head *next_xchg_node = NULL; - struct unf_xchg *xchg = NULL; - ulong pool_lock_falgs = 0; - ulong xchg_lock_flags = 0; - u32 i = 0; - - FC_CHECK_RETURN_VOID(lport); - for (i = 0; i < UNF_EXCHG_MGR_NUM; i++) { - hot_pool = unf_get_hot_pool_by_lport(lport, i); - if (unlikely(!hot_pool)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, - UNF_MAJOR, "Port(0x%x) Hot Pool is NULL.", lport->port_id); - - continue; - } - - if (!clean) { - spin_lock_irqsave(&hot_pool->xchg_hotpool_lock, pool_lock_falgs); - - /* Clearing the SFS_Busy_list Exchange Resource */ - list_for_each_safe(xchg_node, next_xchg_node, &hot_pool->sfs_busylist) { - xchg = list_entry(xchg_node, struct unf_xchg, list_xchg_entry); - spin_lock_irqsave(&xchg->xchg_state_lock, xchg_lock_flags); - if (atomic_read(&xchg->ref_cnt) > 0) - xchg->io_state |= TGT_IO_STATE_ABORT; - - spin_unlock_irqrestore(&xchg->xchg_state_lock, xchg_lock_flags); - } - - spin_unlock_irqrestore(&hot_pool->xchg_hotpool_lock, pool_lock_falgs); - } else { - continue; - } - } -} - -static void unf_xchg_abort_ini_io_xchg(struct unf_lport *lport, bool clean) -{ - /* Clean L_Port/V_Port Link Down I/O: Abort */ - struct unf_xchg_hot_pool *hot_pool = NULL; - struct list_head *xchg_node = NULL; - struct list_head *next_xchg_node = NULL; - struct unf_xchg *xchg = NULL; - ulong pool_lock_falgs = 0; - ulong xchg_lock_flags = 0; - u32 io_state = 0; - u32 i = 0; - - FC_CHECK_RETURN_VOID(lport); - - for (i = 0; i < UNF_EXCHG_MGR_NUM; i++) { - hot_pool = unf_get_hot_pool_by_lport(lport, i); - if (unlikely(!hot_pool)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x) hot pool is NULL", - lport->port_id); - - continue; - } - - if (!clean) { - spin_lock_irqsave(&hot_pool->xchg_hotpool_lock, pool_lock_falgs); - - /* 1. Abort INI_Busy_List IO */ - list_for_each_safe(xchg_node, next_xchg_node, &hot_pool->ini_busylist) { - xchg = list_entry(xchg_node, struct unf_xchg, list_xchg_entry); - spin_lock_irqsave(&xchg->xchg_state_lock, xchg_lock_flags); - if (atomic_read(&xchg->ref_cnt) > 0) - xchg->io_state |= INI_IO_STATE_DRABORT | io_state; - spin_unlock_irqrestore(&xchg->xchg_state_lock, xchg_lock_flags); - } - - spin_unlock_irqrestore(&hot_pool->xchg_hotpool_lock, pool_lock_falgs); - } else { - /* Do nothing, just return */ - continue; - } - } -} - -void unf_xchg_abort_all_xchg(void *lport, u32 xchg_type, bool clean) -{ - struct unf_lport *unf_lport = NULL; - - FC_CHECK_RETURN_VOID(lport); - unf_lport = (struct unf_lport *)lport; - - switch (xchg_type) { - case UNF_XCHG_TYPE_SFS: - unf_xchg_abort_all_sfs_xchg(unf_lport, clean); - break; - /* Clean L_Port/V_Port Link Down I/O: Abort */ - case UNF_XCHG_TYPE_INI: - unf_xchg_abort_ini_io_xchg(unf_lport, clean); - break; - default: - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x) unknown exch type(0x%x)", - unf_lport->port_id, xchg_type); - break; - } -} - -static void unf_xchg_abort_ini_send_tm_cmd(void *lport, void *rport, u64 lun_id) -{ - /* - * LUN Reset: set UP_ABORT tag, with: - * INI_Busy_list, IO_Wait_list, - * IO_Delay_list, IO_Delay_transfer_list - */ - struct unf_lport *unf_lport = NULL; - struct unf_rport *unf_rport = NULL; - struct unf_xchg_hot_pool *hot_pool = NULL; - struct list_head *node = NULL; - struct list_head *next_node = NULL; - struct unf_xchg *xchg = NULL; - ulong flags = 0; - ulong xchg_flag = 0; - u32 i = 0; - u64 raw_lun_id = 0; - - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(rport); - - unf_lport = ((struct unf_lport *)lport)->root_lport; - FC_CHECK_RETURN_VOID(unf_lport); - unf_rport = (struct unf_rport *)rport; - - for (i = 0; i < UNF_EXCHG_MGR_NUM; i++) { - hot_pool = unf_get_hot_pool_by_lport(unf_lport, i); - if (unlikely(!hot_pool)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[err]Port(0x%x) hot pool is NULL", - unf_lport->port_id); - continue; - } - - spin_lock_irqsave(&hot_pool->xchg_hotpool_lock, flags); - - /* 1. for each exchange from busy list */ - list_for_each_safe(node, next_node, &hot_pool->ini_busylist) { - xchg = list_entry(node, struct unf_xchg, list_xchg_entry); - - raw_lun_id = *(u64 *)(xchg->fcp_cmnd.lun) >> UNF_SHIFT_16 & - UNF_RAW_LUN_ID_MASK; - if (lun_id == raw_lun_id && unf_rport == xchg->rport) { - spin_lock_irqsave(&xchg->xchg_state_lock, xchg_flag); - xchg->io_state |= INI_IO_STATE_TMF_ABORT; - spin_unlock_irqrestore(&xchg->xchg_state_lock, xchg_flag); - - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_MAJOR, - "[info]Exchange(%p) state(0x%x) S_ID(0x%x) D_ID(0x%x) tag(0x%x) abort by TMF CMD", - xchg, xchg->io_state, - ((struct unf_lport *)lport)->nport_id, - unf_rport->nport_id, xchg->hotpooltag); - } - } - - spin_unlock_irqrestore(&hot_pool->xchg_hotpool_lock, flags); - } -} - -static void unf_xchg_abort_ini_tmf_target_reset(void *lport, void *rport) -{ - /* - * LUN Reset: set UP_ABORT tag, with: - * INI_Busy_list, IO_Wait_list, - * IO_Delay_list, IO_Delay_transfer_list - */ - struct unf_lport *unf_lport = NULL; - struct unf_rport *unf_rport = NULL; - struct unf_xchg_hot_pool *hot_pool = NULL; - struct list_head *node = NULL; - struct list_head *next_node = NULL; - struct unf_xchg *xchg = NULL; - ulong flags = 0; - ulong xchg_flag = 0; - u32 i = 0; - - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(rport); - - unf_lport = ((struct unf_lport *)lport)->root_lport; - FC_CHECK_RETURN_VOID(unf_lport); - unf_rport = (struct unf_rport *)rport; - - for (i = 0; i < UNF_EXCHG_MGR_NUM; i++) { - hot_pool = unf_get_hot_pool_by_lport(unf_lport, i); - if (unlikely(!hot_pool)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[err]Port(0x%x) hot pool is NULL", - unf_lport->port_id); - continue; - } - - spin_lock_irqsave(&hot_pool->xchg_hotpool_lock, flags); - - /* 1. for each exchange from busy_list */ - list_for_each_safe(node, next_node, &hot_pool->ini_busylist) { - xchg = list_entry(node, struct unf_xchg, list_xchg_entry); - if (unf_rport == xchg->rport) { - spin_lock_irqsave(&xchg->xchg_state_lock, xchg_flag); - xchg->io_state |= INI_IO_STATE_TMF_ABORT; - spin_unlock_irqrestore(&xchg->xchg_state_lock, xchg_flag); - - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_MAJOR, - "[info]Exchange(%p) state(0x%x) S_ID(0x%x) D_ID(0x%x) tag(0x%x) abort by TMF CMD", - xchg, xchg->io_state, unf_lport->nport_id, - unf_rport->nport_id, xchg->hotpooltag); - } - } - - spin_unlock_irqrestore(&hot_pool->xchg_hotpool_lock, flags); - } -} - -void unf_xchg_abort_by_lun(void *lport, void *rport, u64 lun_id, void *xchg, - bool abort_all_lun_flag) -{ - /* ABORT: set UP_ABORT tag for target LUN I/O */ - struct unf_xchg *tm_xchg = (struct unf_xchg *)xchg; - - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_MAJOR, - "[event]Port(0x%x) LUN_ID(0x%llx) TM_EXCH(0x%p) flag(%d)", - ((struct unf_lport *)lport)->port_id, lun_id, xchg, - abort_all_lun_flag); - - /* for INI Mode */ - if (!tm_xchg) { - /* - * LUN Reset: set UP_ABORT tag, with: - * INI_Busy_list, IO_Wait_list, - * IO_Delay_list, IO_Delay_transfer_list - */ - unf_xchg_abort_ini_send_tm_cmd(lport, rport, lun_id); - - return; - } -} - -void unf_xchg_abort_by_session(void *lport, void *rport) -{ - /* - * LUN Reset: set UP_ABORT tag, with: - * INI_Busy_list, IO_Wait_list, - * IO_Delay_list, IO_Delay_transfer_list - */ - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_MAJOR, - "[event]Port(0x%x) Rport(0x%x) start session reset with TMF", - ((struct unf_lport *)lport)->port_id, ((struct unf_rport *)rport)->nport_id); - - unf_xchg_abort_ini_tmf_target_reset(lport, rport); -} - -void unf_xchg_up_abort_io_by_scsi_id(void *lport, u32 scsi_id) -{ - struct unf_lport *unf_lport = NULL; - struct unf_xchg_hot_pool *hot_pool = NULL; - struct list_head *node = NULL; - struct list_head *next_node = NULL; - struct unf_xchg *xchg = NULL; - ulong flags = 0; - ulong xchg_flag = 0; - u32 i; - u32 io_abort_flag = INI_IO_STATE_UPABORT | INI_IO_STATE_UPSEND_ERR | - INI_IO_STATE_TMF_ABORT; - - FC_CHECK_RETURN_VOID(lport); - - unf_lport = ((struct unf_lport *)lport)->root_lport; - FC_CHECK_RETURN_VOID(unf_lport); - - for (i = 0; i < UNF_EXCHG_MGR_NUM; i++) { - hot_pool = unf_get_hot_pool_by_lport(unf_lport, i); - if (unlikely(!hot_pool)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[err]Port(0x%x) hot pool is NULL", - unf_lport->port_id); - continue; - } - - spin_lock_irqsave(&hot_pool->xchg_hotpool_lock, flags); - - /* 1. for each exchange from busy_list */ - list_for_each_safe(node, next_node, &hot_pool->ini_busylist) { - xchg = list_entry(node, struct unf_xchg, list_xchg_entry); - spin_lock_irqsave(&xchg->xchg_state_lock, xchg_flag); - if (lport == xchg->lport && scsi_id == xchg->scsi_id && - !(xchg->io_state & io_abort_flag)) { - xchg->io_state |= INI_IO_STATE_UPABORT; - spin_unlock_irqrestore(&xchg->xchg_state_lock, xchg_flag); - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_MAJOR, - "[info]Exchange(%p) scsi_cmd(0x%p) state(0x%x) scsi_id(0x%x) tag(0x%x) upabort by scsi id", - xchg, xchg->scsi_cmnd_info.scsi_cmnd, - xchg->io_state, scsi_id, xchg->hotpooltag); - } else { - spin_unlock_irqrestore(&xchg->xchg_state_lock, xchg_flag); - } - } - spin_unlock_irqrestore(&hot_pool->xchg_hotpool_lock, flags); - } -} - -static void unf_ini_busy_io_xchg_abort(void *xchg_hot_pool, void *rport, - u32 sid, u32 did, u32 extra_io_state) -{ - /* - * for target session: Set (DRV) ABORT - * 1. R_Port remove - * 2. Send PLOGI_ACC callback - * 3. RCVD PLOGI - * 4. RCVD LOGO - */ - struct unf_xchg_hot_pool *hot_pool = NULL; - struct unf_xchg *xchg = NULL; - struct list_head *xchg_node = NULL; - struct list_head *next_xchg_node = NULL; - struct unf_rport *unf_rport = NULL; - ulong xchg_lock_flags = 0; - - unf_rport = (struct unf_rport *)rport; - hot_pool = (struct unf_xchg_hot_pool *)xchg_hot_pool; - - /* ABORT INI IO: INI_BUSY_LIST */ - list_for_each_safe(xchg_node, next_xchg_node, &hot_pool->ini_busylist) { - xchg = list_entry(xchg_node, struct unf_xchg, list_xchg_entry); - - spin_lock_irqsave(&xchg->xchg_state_lock, xchg_lock_flags); - if (did == xchg->did && sid == xchg->sid && - unf_rport == xchg->rport && - (atomic_read(&xchg->ref_cnt) > 0)) { - xchg->scsi_cmnd_info.result = UNF_SCSI_HOST(DID_IMM_RETRY); - xchg->io_state |= INI_IO_STATE_DRABORT; - xchg->io_state |= extra_io_state; - - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_MAJOR, - "[info]Abort INI:0x%p---0x%x----0x%x----0x%x----0x%x----0x%x----0x%x----0x%x----0x%x----%llu.", - xchg, (u32)xchg->hotpooltag, (u32)xchg->xchg_type, - (u32)xchg->oxid, (u32)xchg->rxid, - (u32)xchg->sid, (u32)xchg->did, (u32)xchg->io_state, - atomic_read(&xchg->ref_cnt), xchg->alloc_jif); - } - spin_unlock_irqrestore(&xchg->xchg_state_lock, xchg_lock_flags); - } -} - -void unf_xchg_mgr_io_xchg_abort(void *lport, void *rport, u32 sid, u32 did, u32 extra_io_state) -{ - /* - * for target session: set ABORT - * 1. R_Port remove - * 2. Send PLOGI_ACC callback - * 3. RCVD PLOGI - * 4. RCVD LOGO - */ - struct unf_xchg_hot_pool *hot_pool = NULL; - struct unf_lport *unf_lport = NULL; - ulong pool_lock_falgs = 0; - u32 i = 0; - - FC_CHECK_RETURN_VOID(lport); - unf_lport = ((struct unf_lport *)lport)->root_lport; - FC_CHECK_RETURN_VOID(unf_lport); - - for (i = 0; i < UNF_EXCHG_MGR_NUM; i++) { - hot_pool = unf_get_hot_pool_by_lport(unf_lport, i); - if (unlikely(!hot_pool)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x) hot pool is NULL", - unf_lport->port_id); - - continue; - } - - spin_lock_irqsave(&hot_pool->xchg_hotpool_lock, pool_lock_falgs); - - /* 1. Clear INI (session) IO: INI Mode */ - unf_ini_busy_io_xchg_abort(hot_pool, rport, sid, did, extra_io_state); - - spin_unlock_irqrestore(&hot_pool->xchg_hotpool_lock, pool_lock_falgs); - } -} - -void unf_xchg_mgr_sfs_xchg_abort(void *lport, void *rport, u32 sid, u32 did) -{ - struct unf_xchg_hot_pool *hot_pool = NULL; - struct list_head *xchg_node = NULL; - struct list_head *next_xchg_node = NULL; - struct unf_xchg *xchg = NULL; - struct unf_lport *unf_lport = NULL; - struct unf_rport *unf_rport = NULL; - ulong pool_lock_falgs = 0; - ulong xchg_lock_flags = 0; - u32 i = 0; - - FC_CHECK_RETURN_VOID(lport); - - unf_lport = ((struct unf_lport *)lport)->root_lport; - FC_CHECK_RETURN_VOID(unf_lport); - - for (i = 0; i < UNF_EXCHG_MGR_NUM; i++) { - hot_pool = unf_get_hot_pool_by_lport(unf_lport, i); - if (!hot_pool) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, - UNF_MAJOR, "Port(0x%x) Hot Pool is NULL.", - unf_lport->port_id); - - continue; - } - - unf_rport = (struct unf_rport *)rport; - - spin_lock_irqsave(&hot_pool->xchg_hotpool_lock, pool_lock_falgs); - - /* Clear the SFS exchange of the corresponding connection */ - list_for_each_safe(xchg_node, next_xchg_node, &hot_pool->sfs_busylist) { - xchg = list_entry(xchg_node, struct unf_xchg, list_xchg_entry); - - spin_lock_irqsave(&xchg->xchg_state_lock, xchg_lock_flags); - if (did == xchg->did && sid == xchg->sid && - unf_rport == xchg->rport && (atomic_read(&xchg->ref_cnt) > 0)) { - xchg->io_state |= TGT_IO_STATE_ABORT; - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_MAJOR, - "Abort SFS:0x%p---0x%x----0x%x----0x%x----0x%x----0x%x----0x%x----0x%x----0x%x----%llu.", - xchg, (u32)xchg->hotpooltag, (u32)xchg->xchg_type, - (u32)xchg->oxid, (u32)xchg->rxid, (u32)xchg->sid, - (u32)xchg->did, (u32)xchg->io_state, - atomic_read(&xchg->ref_cnt), xchg->alloc_jif); - } - spin_unlock_irqrestore(&xchg->xchg_state_lock, xchg_lock_flags); - } - - spin_unlock_irqrestore(&hot_pool->xchg_hotpool_lock, pool_lock_falgs); - } -} - -static void unf_fc_wait_abts_complete(struct unf_lport *lport, struct unf_xchg *xchg) -{ - struct unf_lport *unf_lport = lport; - struct unf_scsi_cmnd scsi_cmnd = {0}; - ulong flag = 0; - u32 time_out_value = 2000; - struct unf_rport_scsi_id_image *scsi_image_table = NULL; - u32 io_result; - - scsi_cmnd.scsi_id = xchg->scsi_cmnd_info.scsi_id; - scsi_cmnd.upper_cmnd = xchg->scsi_cmnd_info.scsi_cmnd; - scsi_cmnd.done = xchg->scsi_cmnd_info.done; - scsi_image_table = &unf_lport->rport_scsi_table; - - if (down_timeout(&xchg->task_sema, (s64)msecs_to_jiffies(time_out_value))) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x) recv abts marker timeout,Exch(0x%p) OX_ID(0x%x) RX_ID(0x%x)", - unf_lport->port_id, xchg, xchg->oxid, xchg->rxid); - goto ABTS_FIAILED; - } - - spin_lock_irqsave(&xchg->xchg_state_lock, flag); - if (xchg->ucode_abts_state == UNF_IO_SUCCESS || - xchg->scsi_cmnd_info.result == UNF_IO_ABORT_PORT_REMOVING) { - spin_unlock_irqrestore(&xchg->xchg_state_lock, flag); - - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_MAJOR, - "[info]Port(0x%x) Send ABTS succeed and recv marker Exch(0x%p) OX_ID(0x%x) RX_ID(0x%x) marker status(0x%x)", - unf_lport->port_id, xchg, xchg->oxid, xchg->rxid, - xchg->ucode_abts_state); - io_result = DID_BUS_BUSY; - UNF_IO_RESULT_CNT(scsi_image_table, scsi_cmnd.scsi_id, io_result); - unf_complete_cmnd(&scsi_cmnd, io_result << UNF_SHIFT_16); - return; - } - spin_unlock_irqrestore(&xchg->xchg_state_lock, flag); - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[warn]Port(0x%x) send ABTS failed. Exch(0x%p) hot_tag(0x%x) ret(0x%x) xchg->io_state (0x%x)", - unf_lport->port_id, xchg, xchg->hotpooltag, - xchg->scsi_cmnd_info.result, xchg->io_state); - goto ABTS_FIAILED; - -ABTS_FIAILED: - unf_lport->xchg_mgr_temp.unf_xchg_cancel_timer((void *)xchg); - spin_lock_irqsave(&xchg->xchg_state_lock, flag); - xchg->io_state &= ~INI_IO_STATE_UPABORT; - spin_unlock_irqrestore(&xchg->xchg_state_lock, flag); -} - -void unf_fc_abort_time_out_cmnd(struct unf_lport *lport, struct unf_xchg *xchg) -{ - struct unf_lport *unf_lport = lport; - ulong flag = 0; - - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(xchg); - - spin_lock_irqsave(&xchg->xchg_state_lock, flag); - if (xchg->io_state & INI_IO_STATE_UPABORT) { - spin_unlock_irqrestore(&xchg->xchg_state_lock, flag); - - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_MAJOR, - "LPort(0x%x) xchange(0x%p) OX_ID(0x%x), RX_ID(0x%x) Cmdsn(0x%lx) has been aborted.", - unf_lport->port_id, xchg, xchg->oxid, - xchg->rxid, (ulong)xchg->cmnd_sn); - return; - } - xchg->io_state |= INI_IO_STATE_UPABORT; - spin_unlock_irqrestore(&xchg->xchg_state_lock, flag); - - FC_DRV_PRINT(UNF_LOG_NORMAL, UNF_KEVENT, - "LPort(0x%x) exchg(0x%p) OX_ID(0x%x) RX_ID(0x%x) Cmdsn(0x%lx) timeout abort it", - unf_lport->port_id, xchg, xchg->oxid, xchg->rxid, (ulong)xchg->cmnd_sn); - - unf_lport->xchg_mgr_temp.unf_xchg_add_timer((void *)xchg, - (ulong)UNF_WAIT_ABTS_RSP_TIMEOUT, UNF_TIMER_TYPE_INI_ABTS); - - sema_init(&xchg->task_sema, 0); - - if (unf_send_abts(unf_lport, xchg) != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_MAJOR, - "LPort(0x%x) send ABTS, Send ABTS unsuccessful. Exchange OX_ID(0x%x), RX_ID(0x%x).", - unf_lport->port_id, xchg->oxid, xchg->rxid); - unf_lport->xchg_mgr_temp.unf_xchg_cancel_timer((void *)xchg); - spin_lock_irqsave(&xchg->xchg_state_lock, flag); - xchg->io_state &= ~INI_IO_STATE_UPABORT; - spin_unlock_irqrestore(&xchg->xchg_state_lock, flag); - return; - } - unf_fc_wait_abts_complete(unf_lport, xchg); -} - -static void unf_fc_ini_io_rec_wait_time_out(struct unf_lport *lport, struct unf_rport *rport, - struct unf_xchg *xchg) -{ - ulong time_out = 0; - - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x) RPort(0x%x) Exch(0x%p) Rec timeout exchange OX_ID(0x%x) RX_ID(0x%x) state(0x%x)", - lport->port_id, rport->nport_id, xchg, xchg->oxid, - xchg->rxid, xchg->io_state); - - if (xchg->rport_bind_jifs == rport->rport_alloc_jifs) { - unf_send_rec(lport, rport, xchg); - - if (xchg->scsi_cmnd_info.abort_time_out > 0) { - time_out = (xchg->scsi_cmnd_info.abort_time_out > UNF_REC_TOV) ? - (xchg->scsi_cmnd_info.abort_time_out - UNF_REC_TOV) : 0; - if (time_out > 0) { - lport->xchg_mgr_temp.unf_xchg_add_timer((void *)xchg, time_out, - UNF_TIMER_TYPE_REQ_IO); - } else { - unf_fc_abort_time_out_cmnd(lport, xchg); - } - } - } -} - -static void unf_fc_ini_send_abts_time_out(struct unf_lport *lport, struct unf_rport *rport, - struct unf_xchg *xchg) -{ - if (xchg->rport_bind_jifs == rport->rport_alloc_jifs && - xchg->rport_bind_jifs != INVALID_VALUE64) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x) RPort(0x%x) Exch(0x%p) first time to send abts timeout, retry again OX_ID(0x%x) RX_ID(0x%x) HotTag(0x%x) state(0x%x)", - lport->port_id, rport->nport_id, xchg, xchg->oxid, - xchg->rxid, xchg->hotpooltag, xchg->io_state); - - lport->xchg_mgr_temp.unf_xchg_add_timer((void *)xchg, - (ulong)UNF_WAIT_ABTS_RSP_TIMEOUT, UNF_TIMER_TYPE_INI_ABTS); - - if (unf_send_abts(lport, xchg) != RETURN_OK) { - lport->xchg_mgr_temp.unf_xchg_cancel_timer((void *)xchg); - - unf_abts_timeout_recovery_default(rport, xchg); - - unf_cm_free_xchg(lport, xchg); - } - } else { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x) RPort(0x%x) Exch(0x%p) rport is invalid, exchg rport jiff(0x%llx 0x%llx), free exchange OX_ID(0x%x) RX_ID(0x%x) state(0x%x)", - lport->port_id, rport->nport_id, xchg, - xchg->rport_bind_jifs, rport->rport_alloc_jifs, - xchg->oxid, xchg->rxid, xchg->io_state); - - unf_cm_free_xchg(lport, xchg); - } -} - -void unf_fc_ini_io_xchg_time_out(struct work_struct *work) -{ - struct unf_xchg *xchg = NULL; - struct unf_lport *unf_lport = NULL; - struct unf_rport *unf_rport = NULL; - ulong flags = 0; - u32 ret = UNF_RETURN_ERROR; - u32 port_valid_flag = 0; - - xchg = container_of(work, struct unf_xchg, timeout_work.work); - FC_CHECK_RETURN_VOID(xchg); - - ret = unf_xchg_ref_inc(xchg, INI_IO_TIMEOUT); - FC_CHECK_RETURN_VOID(ret == RETURN_OK); - - unf_lport = xchg->lport; - unf_rport = xchg->rport; - - port_valid_flag = (!unf_lport) || (!unf_rport); - if (port_valid_flag) { - unf_xchg_ref_dec(xchg, INI_IO_TIMEOUT); - unf_xchg_ref_dec(xchg, INI_IO_TIMEOUT); - return; - } - - spin_lock_irqsave(&xchg->xchg_state_lock, flags); - /* 1. for Send RRQ failed Timer timeout */ - if (INI_IO_STATE_RRQSEND_ERR & xchg->io_state) { - spin_unlock_irqrestore(&xchg->xchg_state_lock, flags); - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[info]LPort(0x%x) RPort(0x%x) Exch(0x%p) had wait enough time for RRQ send failed OX_ID(0x%x) RX_ID(0x%x) state(0x%x)", - unf_lport->port_id, unf_rport->nport_id, xchg, - xchg->oxid, xchg->rxid, xchg->io_state); - unf_notify_chip_free_xid(xchg); - unf_cm_free_xchg(unf_lport, xchg); - } - /* Second ABTS timeout and enter LOGO process */ - else if ((INI_IO_STATE_ABORT_TIMEOUT & xchg->io_state) && - (!(ABTS_RESPONSE_RECEIVED & xchg->abts_state))) { - spin_unlock_irqrestore(&xchg->xchg_state_lock, flags); - - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x) RPort(0x%x) Exch(0x%p) had wait enough time for second abts send OX_ID(0x%x) RX_ID(0x%x) state(0x%x)", - unf_lport->port_id, unf_rport->nport_id, xchg, - xchg->oxid, xchg->rxid, xchg->io_state); - unf_abts_timeout_recovery_default(unf_rport, xchg); - unf_cm_free_xchg(unf_lport, xchg); - } - /* First time to send ABTS, timeout and retry to send ABTS again */ - else if ((INI_IO_STATE_UPABORT & xchg->io_state) && - (!(ABTS_RESPONSE_RECEIVED & xchg->abts_state))) { - xchg->io_state |= INI_IO_STATE_ABORT_TIMEOUT; - spin_unlock_irqrestore(&xchg->xchg_state_lock, flags); - unf_fc_ini_send_abts_time_out(unf_lport, unf_rport, xchg); - } - /* 3. IO_DONE */ - else if ((INI_IO_STATE_DONE & xchg->io_state) && - (ABTS_RESPONSE_RECEIVED & xchg->abts_state)) { - /* - * for IO_DONE: - * 1. INI ABTS first timer time out - * 2. INI RCVD ABTS Response - * 3. Normal case for I/O Done - */ - /* Send ABTS & RCVD RSP & no timeout */ - spin_unlock_irqrestore(&xchg->xchg_state_lock, flags); - if (unf_send_rrq(unf_lport, unf_rport, xchg) == RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_MAJOR, - "[info]LPort(0x%x) send RRQ succeed to RPort(0x%x) Exch(0x%p) OX_ID(0x%x) RX_ID(0x%x) state(0x%x)", - unf_lport->port_id, unf_rport->nport_id, xchg, - xchg->oxid, xchg->rxid, xchg->io_state); - } else { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]LPort(0x%x) can't send RRQ to RPort(0x%x) Exch(0x%p) OX_ID(0x%x) RX_ID(0x%x) state(0x%x)", - unf_lport->port_id, unf_rport->nport_id, xchg, - xchg->oxid, xchg->rxid, xchg->io_state); - - spin_lock_irqsave(&xchg->xchg_state_lock, flags); - xchg->io_state |= INI_IO_STATE_RRQSEND_ERR; - spin_unlock_irqrestore(&xchg->xchg_state_lock, flags); - unf_lport->xchg_mgr_temp.unf_xchg_add_timer((void *)xchg, - (ulong)UNF_WRITE_RRQ_SENDERR_INTERVAL, UNF_TIMER_TYPE_INI_IO); - } - } else if (INI_IO_STATE_REC_TIMEOUT_WAIT & xchg->io_state) { - xchg->io_state &= ~INI_IO_STATE_REC_TIMEOUT_WAIT; - spin_unlock_irqrestore(&xchg->xchg_state_lock, flags); - unf_fc_ini_io_rec_wait_time_out(unf_lport, unf_rport, xchg); - } else { - spin_unlock_irqrestore(&xchg->xchg_state_lock, flags); - unf_fc_abort_time_out_cmnd(unf_lport, xchg); - } - - unf_xchg_ref_dec(xchg, INI_IO_TIMEOUT); - unf_xchg_ref_dec(xchg, INI_IO_TIMEOUT); -} - -void unf_sfs_xchg_time_out(struct work_struct *work) -{ - struct unf_xchg *xchg = NULL; - u32 ret = UNF_RETURN_ERROR; - struct unf_lport *unf_lport = NULL; - struct unf_rport *unf_rport = NULL; - ulong flags = 0; - - FC_CHECK_RETURN_VOID(work); - xchg = container_of(work, struct unf_xchg, timeout_work.work); - FC_CHECK_RETURN_VOID(xchg); - - ret = unf_xchg_ref_inc(xchg, SFS_TIMEOUT); - FC_CHECK_RETURN_VOID(ret == RETURN_OK); - - spin_lock_irqsave(&xchg->xchg_state_lock, flags); - unf_lport = xchg->lport; - unf_rport = xchg->rport; - spin_unlock_irqrestore(&xchg->xchg_state_lock, flags); - - unf_xchg_ref_dec(xchg, SFS_TIMEOUT); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]SFS Exch(%p) Cmnd(0x%x) IO Exch(0x%p) Sid_Did(0x%x:0x%x) HotTag(0x%x) State(0x%x) Timeout.", - xchg, xchg->cmnd_code, xchg->io_xchg, xchg->sid, xchg->did, - xchg->hotpooltag, xchg->io_state); - - spin_lock_irqsave(&xchg->xchg_state_lock, flags); - if ((xchg->io_state & TGT_IO_STATE_ABORT) && - xchg->cmnd_code != ELS_RRQ && xchg->cmnd_code != ELS_LOGO) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "SFS Exch(0x%p) Cmnd(0x%x) Hot Pool Tag(0x%x) timeout, but aborted, no need to handle.", - xchg, xchg->cmnd_code, xchg->hotpooltag); - spin_unlock_irqrestore(&xchg->xchg_state_lock, flags); - - unf_xchg_ref_dec(xchg, SFS_TIMEOUT); - unf_xchg_ref_dec(xchg, SFS_TIMEOUT); - - return; - } - spin_unlock_irqrestore(&xchg->xchg_state_lock, flags); - - /* The sfs times out. If the sfs is ELS reply, - * go to UNF_RPortErrorRecovery/unf_lport_error_recovery. - * Otherwise, go to the corresponding obCallback. - */ - if (UNF_XCHG_IS_ELS_REPLY(xchg) && unf_rport) { - if (unf_rport->nport_id >= UNF_FC_FID_DOM_MGR) - unf_lport_error_recovery(unf_lport); - else - unf_rport_error_recovery(unf_rport); - - } else if (xchg->ob_callback) { - xchg->ob_callback(xchg); - } else { - /* Do nothing */ - } - unf_notify_chip_free_xid(xchg); - unf_xchg_ref_dec(xchg, SFS_TIMEOUT); - unf_xchg_ref_dec(xchg, SFS_TIMEOUT); -} diff --git a/drivers/scsi/spfc/common/unf_exchg_abort.h b/drivers/scsi/spfc/common/unf_exchg_abort.h deleted file mode 100644 index 75b5a1bab733..000000000000 --- a/drivers/scsi/spfc/common/unf_exchg_abort.h +++ /dev/null @@ -1,23 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef UNF_EXCHG_ABORT_H -#define UNF_EXCHG_ABORT_H - -#include "unf_type.h" -#include "unf_exchg.h" - -#define UNF_RAW_LUN_ID_MASK 0x000000000000ffff - -void unf_xchg_abort_by_lun(void *lport, void *rport, u64 lun_id, void *tm_xchg, - bool abort_all_lun_flag); -void unf_xchg_abort_by_session(void *lport, void *rport); -void unf_xchg_mgr_io_xchg_abort(void *lport, void *rport, u32 sid, u32 did, - u32 extra_io_state); -void unf_xchg_mgr_sfs_xchg_abort(void *lport, void *rport, u32 sid, u32 did); -void unf_xchg_abort_all_xchg(void *lport, u32 xchg_type, bool clean); -void unf_fc_abort_time_out_cmnd(struct unf_lport *lport, struct unf_xchg *xchg); -void unf_fc_ini_io_xchg_time_out(struct work_struct *work); -void unf_sfs_xchg_time_out(struct work_struct *work); -void unf_xchg_up_abort_io_by_scsi_id(void *lport, u32 scsi_id); -#endif diff --git a/drivers/scsi/spfc/common/unf_fcstruct.h b/drivers/scsi/spfc/common/unf_fcstruct.h deleted file mode 100644 index d6eb8592994b..000000000000 --- a/drivers/scsi/spfc/common/unf_fcstruct.h +++ /dev/null @@ -1,459 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef UNF_FCSTRUCT_H -#define UNF_FCSTRUCT_H - -#include "unf_type.h" -#include "unf_scsi_common.h" - -#define FC_RCTL_BLS 0x80000000 - -/* - * * R_CTL Basic Link Data defines - */ - -#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_RJT_LOGICAL_ERROR 0x00030000 - -/* - * * BA_RJT code explanation - */ - -#define FCXLS_LS_RJT_INVALID_OXID_RXID 0x00001700 - -/* - * * ELS ACC - */ -struct unf_els_acc { - struct unf_fc_head frame_hdr; - u32 cmnd; -}; - -/* - * * ELS RJT - */ -struct unf_els_rjt { - struct unf_fc_head frame_hdr; - u32 cmnd; - u32 reason_code; -}; - -/* - * * FLOGI payload, - * * FC-LS-2 FLOGI, PLOGI, FDISC or LS_ACC Payload - */ -struct unf_flogi_fdisc_payload { - u32 cmnd; - struct unf_fabric_parm fabric_parms; -}; - -/* - * * Flogi and Flogi accept frames. They are the same structure - */ -struct unf_flogi_fdisc_acc { - struct unf_fc_head frame_hdr; - struct unf_flogi_fdisc_payload flogi_payload; -}; - -/* - * * Fdisc and Fdisc accept frames. They are the same structure - */ - -struct unf_fdisc_acc { - struct unf_fc_head frame_hdr; - struct unf_flogi_fdisc_payload fdisc_payload; -}; - -/* - * * PLOGI payload - */ -struct unf_plogi_payload { - u32 cmnd; - struct unf_lgn_parm stparms; -}; - -/* - *Plogi, Plogi accept, Pdisc and Pdisc accept frames. They are all the same - *structure. - */ -struct unf_plogi_pdisc { - struct unf_fc_head frame_hdr; - struct unf_plogi_payload payload; -}; - -/* - * * LOGO logout link service requests invalidation of service parameters and - * * port name. - * * see FC-PH 4.3 Section 21.4.8 - */ -struct unf_logo_payload { - u32 cmnd; - u32 nport_id; - u32 high_port_name; - u32 low_port_name; -}; - -/* - * * payload to hold LOGO command - */ -struct unf_logo { - struct unf_fc_head frame_hdr; - struct unf_logo_payload payload; -}; - -/* - * * payload for ECHO command, refer to FC-LS-2 4.2.4 - */ -struct unf_echo_payload { - u32 cmnd; -#define UNF_FC_ECHO_PAYLOAD_LENGTH 255 /* Length in words */ - u32 data[UNF_FC_ECHO_PAYLOAD_LENGTH]; -}; - -struct unf_echo { - struct unf_fc_head frame_hdr; - struct unf_echo_payload *echo_pld; - dma_addr_t phy_echo_addr; -}; - -#define UNF_PRLI_SIRT_EXTRA_SIZE 12 - -/* - * * payload for PRLI and PRLO - */ -struct unf_prli_payload { - u32 cmnd; -#define UNF_FC_PRLI_PAYLOAD_LENGTH 7 /* Length in words */ - u32 parms[UNF_FC_PRLI_PAYLOAD_LENGTH]; -}; - -/* - * * FCHS structure with payload - */ -struct unf_prli_prlo { - struct unf_fc_head frame_hdr; - struct unf_prli_payload payload; -}; - -struct unf_adisc_payload { - u32 cmnd; - u32 hard_address; - u32 high_port_name; - u32 low_port_name; - u32 high_node_name; - u32 low_node_name; - u32 nport_id; -}; - -/* - * * FCHS structure with payload - */ -struct unf_adisc { - struct unf_fc_head frame_hdr; /* FCHS structure */ - struct unf_adisc_payload - adisc_payl; /* Payload data containing ADISC info - */ -}; - -/* - * * RLS payload - */ -struct unf_rls_payload { - u32 cmnd; - u32 nport_id; /* in litle endian format */ -}; - -/* - * * RLS - */ -struct unf_rls { - struct unf_fc_head frame_hdr; /* FCHS structure */ - struct unf_rls_payload rls; /* payload data containing the RLS info */ -}; - -/* - * * RLS accept payload - */ -struct unf_rls_acc_payload { - u32 cmnd; - u32 link_failure_count; - u32 loss_of_sync_count; - u32 loss_of_signal_count; - u32 primitive_seq_count; - u32 invalid_trans_word_count; - u32 invalid_crc_count; -}; - -/* - * * RLS accept - */ -struct unf_rls_acc { - struct unf_fc_head frame_hdr; /* FCHS structure */ - struct unf_rls_acc_payload - rls; /* payload data containing the RLS ACC info - */ -}; - -/* - * * FCHS structure with payload - */ -struct unf_rrq { - struct unf_fc_head frame_hdr; - u32 cmnd; - u32 sid; - u32 oxid_rxid; -}; - -#define UNF_SCR_PAYLOAD_CNT 2 -struct unf_scr { - struct unf_fc_head frame_hdr; - u32 payload[UNF_SCR_PAYLOAD_CNT]; -}; - -struct unf_ctiu_prem { - u32 rev_inid; - u32 gstype_gssub_options; - u32 cmnd_rsp_size; - u32 frag_reason_exp_vend; -}; - -#define UNF_FC4TYPE_CNT 8 -struct unf_rftid { - struct unf_fc_head frame_hdr; - struct unf_ctiu_prem ctiu_pream; - u32 nport_id; - u32 fc4_types[UNF_FC4TYPE_CNT]; -}; - -struct unf_rffid { - struct unf_fc_head frame_hdr; - struct unf_ctiu_prem ctiu_pream; - u32 nport_id; - u32 fc4_feature; -}; - -struct unf_rffid_rsp { - struct unf_fc_head frame_hdr; - struct unf_ctiu_prem ctiu_pream; -}; - -struct unf_gffid { - struct unf_fc_head frame_hdr; - struct unf_ctiu_prem ctiu_pream; - u32 nport_id; -}; - -struct unf_gffid_rsp { - struct unf_fc_head frame_hdr; - struct unf_ctiu_prem ctiu_pream; - u32 fc4_feature[32]; -}; - -struct unf_gnnid { - struct unf_fc_head frame_hdr; - struct unf_ctiu_prem ctiu_pream; - u32 nport_id; -}; - -struct unf_gnnid_rsp { - struct unf_fc_head frame_hdr; - struct unf_ctiu_prem ctiu_pream; - u32 node_name[2]; -}; - -struct unf_gpnid { - struct unf_fc_head frame_hdr; - struct unf_ctiu_prem ctiu_pream; - u32 nport_id; -}; - -struct unf_gpnid_rsp { - struct unf_fc_head frame_hdr; - struct unf_ctiu_prem ctiu_pream; - u32 port_name[2]; -}; - -struct unf_rft_rsp { - struct unf_fc_head frame_hdr; - struct unf_ctiu_prem ctiu_pream; -}; - -struct unf_ls_rjt_pld { - u32 srr_op; /* 01000000h */ - u8 vandor; - u8 reason_exp; - u8 reason; - u8 reserved; -}; - -struct unf_ls_rjt { - struct unf_fc_head frame_hdr; - struct unf_ls_rjt_pld pld; -}; - -struct unf_rec_pld { - u32 rec_cmnd; - u32 xchg_org_sid; /* bit0-bit23 */ - u16 rx_id; - u16 ox_id; -}; - -struct unf_rec { - struct unf_fc_head frame_hdr; - struct unf_rec_pld rec_pld; -}; - -struct unf_rec_acc_pld { - u32 cmnd; - u16 rx_id; - u16 ox_id; - u32 org_addr_id; /* bit0-bit23 */ - u32 rsp_addr_id; /* bit0-bit23 */ -}; - -struct unf_rec_acc { - struct unf_fc_head frame_hdr; - struct unf_rec_acc_pld payload; -}; - -struct unf_gid { - struct unf_ctiu_prem ctiu_pream; - u32 scope_type; -}; - -struct unf_gid_acc { - struct unf_fc_head frame_hdr; - struct unf_ctiu_prem ctiu_pream; -}; - -#define UNF_LOOPMAP_COUNT 128 -struct unf_loop_init { - struct unf_fc_head frame_hdr; - u32 cmnd; -#define UNF_FC_ALPA_BIT_MAP_SIZE 4 - u32 alpha_bit_map[UNF_FC_ALPA_BIT_MAP_SIZE]; -}; - -struct unf_loop_map { - struct unf_fc_head frame_hdr; - u32 cmnd; - u32 loop_map[32]; -}; - -struct unf_ctiu_rjt { - struct unf_fc_head frame_hdr; - struct unf_ctiu_prem ctiu_pream; -}; - -struct unf_gid_acc_pld { - struct unf_ctiu_prem ctiu_pream; - - u32 gid_port_id[UNF_GID_PORT_CNT]; -}; - -struct unf_gid_rsp { - struct unf_gid_acc_pld *gid_acc_pld; -}; - -struct unf_gid_req_rsp { - struct unf_fc_head frame_hdr; - struct unf_gid gid_req; - struct unf_gid_rsp gid_rsp; -}; - -/* FC-LS-2 Table 31 RSCN Payload */ -struct unf_rscn_port_id_page { - u8 port_id_port; - u8 port_id_area; - u8 port_id_domain; - - u8 addr_format : 2; - u8 event_qualifier : 4; - u8 reserved : 2; -}; - -struct unf_rscn_pld { - u32 cmnd; - struct unf_rscn_port_id_page port_id_page[UNF_RSCN_PAGE_SUM]; -}; - -struct unf_rscn { - struct unf_fc_head frame_hdr; - struct unf_rscn_pld *rscn_pld; -}; - -union unf_sfs_u { - struct { - struct unf_fc_head frame_head; - u8 data[0]; - } sfs_common; - struct unf_els_acc els_acc; - struct unf_els_rjt els_rjt; - struct unf_plogi_pdisc plogi; - struct unf_logo logo; - struct unf_echo echo; - struct unf_echo echo_acc; - struct unf_prli_prlo prli; - struct unf_prli_prlo prlo; - struct unf_rls rls; - struct unf_rls_acc rls_acc; - struct unf_plogi_pdisc pdisc; - struct unf_adisc adisc; - struct unf_rrq rrq; - struct unf_flogi_fdisc_acc flogi; - struct unf_fdisc_acc fdisc; - struct unf_scr scr; - struct unf_rec rec; - struct unf_rec_acc rec_acc; - struct unf_ls_rjt ls_rjt; - struct unf_rscn rscn; - struct unf_gid_req_rsp get_id; - struct unf_rftid rft_id; - struct unf_rft_rsp rft_id_rsp; - struct unf_rffid rff_id; - struct unf_rffid_rsp rff_id_rsp; - struct unf_gffid gff_id; - struct unf_gffid_rsp gff_id_rsp; - struct unf_gnnid gnn_id; - struct unf_gnnid_rsp gnn_id_rsp; - struct unf_gpnid gpn_id; - struct unf_gpnid_rsp gpn_id_rsp; - struct unf_plogi_pdisc plogi_acc; - struct unf_plogi_pdisc pdisc_acc; - struct unf_adisc adisc_acc; - struct unf_prli_prlo prli_acc; - struct unf_prli_prlo prlo_acc; - struct unf_flogi_fdisc_acc flogi_acc; - struct unf_fdisc_acc fdisc_acc; - struct unf_loop_init lpi; - struct unf_loop_map loop_map; - struct unf_ctiu_rjt ctiu_rjt; -}; - -struct unf_sfs_entry { - union unf_sfs_u *fc_sfs_entry_ptr; /* Virtual addr of SFS buffer */ - u64 sfs_buff_phy_addr; /* Physical addr of SFS buffer */ - u32 sfs_buff_len; /* Length of bytes in SFS buffer */ - u32 cur_offset; -}; - -struct unf_fcp_rsp_iu_entry { - u8 *fcp_rsp_iu; - u32 fcp_sense_len; -}; - -struct unf_rjt_info { - u32 els_cmnd_code; - u32 reason_code; - u32 reason_explanation; - u8 class_mode; - u8 ucrsvd[3]; -}; - -#endif diff --git a/drivers/scsi/spfc/common/unf_gs.c b/drivers/scsi/spfc/common/unf_gs.c deleted file mode 100644 index cb5fc1a5d246..000000000000 --- a/drivers/scsi/spfc/common/unf_gs.c +++ /dev/null @@ -1,2521 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#include "unf_gs.h" -#include "unf_log.h" -#include "unf_exchg.h" -#include "unf_rport.h" -#include "unf_service.h" -#include "unf_portman.h" -#include "unf_ls.h" - -static void unf_gpn_id_callback(void *lport, void *sns_port, void *xchg); -static void unf_gpn_id_ob_callback(struct unf_xchg *xchg); -static void unf_gnn_id_ob_callback(struct unf_xchg *xchg); -static void unf_scr_callback(void *lport, void *rport, void *xchg); -static void unf_scr_ob_callback(struct unf_xchg *xchg); -static void unf_gff_id_ob_callback(struct unf_xchg *xchg); -static void unf_gff_id_callback(void *lport, void *sns_port, void *xchg); -static void unf_gnn_id_callback(void *lport, void *sns_port, void *xchg); -static void unf_gid_ft_ob_callback(struct unf_xchg *xchg); -static void unf_gid_ft_callback(void *lport, void *rport, void *xchg); -static void unf_gid_pt_ob_callback(struct unf_xchg *xchg); -static void unf_gid_pt_callback(void *lport, void *rport, void *xchg); -static void unf_rft_id_ob_callback(struct unf_xchg *xchg); -static void unf_rft_id_callback(void *lport, void *rport, void *xchg); -static void unf_rff_id_callback(void *lport, void *rport, void *xchg); -static void unf_rff_id_ob_callback(struct unf_xchg *xchg); - -#define UNF_GET_DOMAIN_ID(x) (((x) & 0xFF0000) >> 16) -#define UNF_GET_AREA_ID(x) (((x) & 0x00FF00) >> 8) - -#define UNF_GID_LAST_PORT_ID 0x80 -#define UNF_GID_CONTROL(nport_id) ((nport_id) >> 24) -#define UNF_GET_PORT_OPTIONS(fc_4feature) ((fc_4feature) >> 20) - -#define UNF_SERVICE_GET_NPORTID_FORM_GID_PAGE(port_id_page) \ - (((u32)(port_id_page)->port_id_domain << 16) | \ - ((u32)(port_id_page)->port_id_area << 8) | \ - ((u32)(port_id_page)->port_id_port)) - -#define UNF_GNN_GFF_ID_RJT_REASON(rjt_reason) \ - ((UNF_CTIU_RJT_UNABLE_PERFORM == \ - ((rjt_reason) & UNF_CTIU_RJT_MASK)) && \ - ((UNF_CTIU_RJT_EXP_PORTID_NO_REG == \ - ((rjt_reason) & UNF_CTIU_RJT_EXP_MASK)) || \ - (UNF_CTIU_RJT_EXP_PORTNAME_NO_REG == \ - ((rjt_reason) & UNF_CTIU_RJT_EXP_MASK)) || \ - (UNF_CTIU_RJT_EXP_NODENAME_NO_REG == \ - ((rjt_reason) & UNF_CTIU_RJT_EXP_MASK)))) - -u32 unf_send_scr(struct unf_lport *lport, struct unf_rport *rport) -{ - /* after RCVD RFF_ID ACC */ - struct unf_scr *scr = NULL; - union unf_sfs_u *fc_entry = NULL; - struct unf_xchg *xchg = NULL; - u32 ret = UNF_RETURN_ERROR; - struct unf_frame_pkg pkg = {0}; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(rport, UNF_RETURN_ERROR); - - xchg = unf_get_sfs_free_xchg_and_init(lport, rport->nport_id, NULL, &fc_entry); - if (!xchg) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) exchange can't be NULL for SCR", - lport->port_id); - - return ret; - } - - xchg->cmnd_code = ELS_SCR; - - xchg->callback = unf_scr_callback; - xchg->ob_callback = unf_scr_ob_callback; - - unf_fill_package(&pkg, xchg, rport); - pkg.type = UNF_PKG_ELS_REQ; - - scr = &fc_entry->scr; - memset(scr, 0, sizeof(struct unf_scr)); - scr->payload[ARRAY_INDEX_0] = (UNF_GS_CMND_SCR); /* SCR is 0x62 */ - scr->payload[ARRAY_INDEX_1] = (UNF_FABRIC_FULL_REG); /* Full registration */ - ret = unf_ls_gs_cmnd_send(lport, &pkg, xchg); - if (ret != RETURN_OK) - unf_cm_free_xchg((void *)lport, (void *)xchg); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: SCR send %s. Port(0x%x_0x%x)--->RPort(0x%x) with hottag(0x%x)", - (ret != RETURN_OK) ? "failed" : "succeed", lport->port_id, - lport->nport_id, rport->nport_id, xchg->hotpooltag); - - return ret; -} - -static void unf_fill_gff_id_pld(struct unf_gffid *gff_id, u32 nport_id) -{ - FC_CHECK_RETURN_VOID(gff_id); - - gff_id->ctiu_pream.rev_inid = (UNF_REV_NPORTID_INIT); - gff_id->ctiu_pream.gstype_gssub_options = (UNF_FSTYPE_OPT_INIT); - gff_id->ctiu_pream.cmnd_rsp_size = (UNF_FSTYPE_GFF_ID); - gff_id->ctiu_pream.frag_reason_exp_vend = UNF_FRAG_REASON_VENDOR; - gff_id->nport_id = nport_id; -} - -static void unf_ctpass_thru_callback(void *lport, void *rport, void *xchg) -{ - struct unf_lport *unf_lport = NULL; - struct unf_gid_acc_pld *gid_acc_pld = NULL; - struct unf_xchg *unf_xchg = NULL; - union unf_sfs_u *sfs = NULL; - u32 cmnd_rsp_size = 0; - - struct send_com_trans_out *out_send = NULL; - - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(rport); - FC_CHECK_RETURN_VOID(xchg); - - unf_lport = (struct unf_lport *)lport; - unf_xchg = (struct unf_xchg *)xchg; - sfs = unf_xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr; - - gid_acc_pld = sfs->get_id.gid_rsp.gid_acc_pld; - if (!gid_acc_pld) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]LOGIN: Port(0x%x) CT PassThru response payload is NULL", - unf_lport->port_id); - - return; - } - - out_send = (struct send_com_trans_out *)unf_xchg->upper_ct; - - cmnd_rsp_size = (gid_acc_pld->ctiu_pream.cmnd_rsp_size); - if (UNF_CT_IU_ACCEPT == (cmnd_rsp_size & UNF_CT_IU_RSP_MASK)) { - out_send->hba_status = 0; /* HBA_STATUS_OK 0 */ - out_send->total_resp_buffer_cnt = unf_xchg->fcp_sfs_union.sfs_entry.cur_offset; - out_send->actual_resp_buffer_cnt = unf_xchg->fcp_sfs_union.sfs_entry.cur_offset; - unf_cpu_to_big_end(out_send->resp_buffer, (u32)out_send->total_resp_buffer_cnt); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: Port(0x%x_0x%x) CT PassThru was receive len is(0x%0x)", - unf_lport->port_id, unf_lport->nport_id, - out_send->total_resp_buffer_cnt); - } else if (UNF_CT_IU_REJECT == (cmnd_rsp_size & UNF_CT_IU_RSP_MASK)) { - out_send->hba_status = 13; /* HBA_STATUS_ERROR_ELS_REJECT 13 */ - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]LOGIN: Port(0x%x_0x%x) CT PassThru was rejected", - unf_lport->port_id, unf_lport->nport_id); - } else { - out_send->hba_status = 1; /* HBA_STATUS_ERROR 1 */ - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]LOGIN: Port(0x%x_0x%x) CT PassThru was UNKNOWN", - unf_lport->port_id, unf_lport->nport_id); - } - - up(&unf_lport->wmi_task_sema); -} - -u32 unf_send_ctpass_thru(struct unf_lport *lport, void *buffer, u32 bufflen) -{ - union unf_sfs_u *fc_entry = NULL; - struct unf_xchg *xchg = NULL; - u32 ret = UNF_RETURN_ERROR; - struct unf_rport *sns_port = NULL; - struct send_com_trans_in *in_send = (struct send_com_trans_in *)buffer; - struct send_com_trans_out *out_send = - (struct send_com_trans_out *)buffer; - struct unf_ctiu_prem *ctiu_pream = NULL; - struct unf_gid *gs_pld = NULL; - struct unf_frame_pkg pkg = {0}; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(buffer, UNF_RETURN_ERROR); - - ctiu_pream = (struct unf_ctiu_prem *)in_send->req_buffer; - unf_cpu_to_big_end(ctiu_pream, sizeof(struct unf_gid)); - - if (ctiu_pream->cmnd_rsp_size >> UNF_SHIFT_16 == NS_GIEL) { - sns_port = unf_get_rport_by_nport_id(lport, UNF_FC_FID_MGMT_SERV); - if (!sns_port) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) can't find SNS port", - lport->port_id); - - return UNF_RETURN_ERROR; - } - } else if (ctiu_pream->cmnd_rsp_size >> UNF_SHIFT_16 == NS_GA_NXT) { - sns_port = unf_get_rport_by_nport_id(lport, UNF_FC_FID_DIR_SERV); - if (!sns_port) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) can't find SNS port", - lport->port_id); - - return UNF_RETURN_ERROR; - } - } else { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[info]%s cmnd(0x%x) is error:", __func__, - ctiu_pream->cmnd_rsp_size >> UNF_SHIFT_16); - - return UNF_RETURN_ERROR; - } - - xchg = unf_get_sfs_free_xchg_and_init(lport, sns_port->nport_id, sns_port, &fc_entry); - if (!xchg) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) exchange can't be NULL for GFF_ID", - lport->port_id); - - return UNF_RETURN_ERROR; - } - - xchg->cmnd_code = ctiu_pream->cmnd_rsp_size >> UNF_SHIFT_16; - xchg->upper_ct = buffer; - xchg->ob_callback = NULL; - xchg->callback = unf_ctpass_thru_callback; - xchg->oxid = xchg->hotpooltag; - unf_fill_package(&pkg, xchg, sns_port); - pkg.type = UNF_PKG_GS_REQ; - xchg->fcp_sfs_union.sfs_entry.sfs_buff_len = bufflen; - gs_pld = &fc_entry->get_id.gid_req; /* GID req payload */ - memset(gs_pld, 0, sizeof(struct unf_gid)); - memcpy(gs_pld, (struct unf_gid *)in_send->req_buffer, sizeof(struct unf_gid)); - fc_entry->get_id.gid_rsp.gid_acc_pld = (struct unf_gid_acc_pld *)out_send->resp_buffer; - - ret = unf_ls_gs_cmnd_send(lport, &pkg, xchg); - - return ret; -} - -u32 unf_send_gff_id(struct unf_lport *lport, struct unf_rport *sns_port, - u32 nport_id) -{ - struct unf_gffid *gff_id = NULL; - union unf_sfs_u *fc_entry = NULL; - struct unf_xchg *xchg = NULL; - u32 ret = UNF_RETURN_ERROR; - - struct unf_frame_pkg pkg; - struct unf_lport *unf_lport = NULL; - - FC_CHECK_RETURN_VALUE(sns_port, UNF_RETURN_ERROR); - - if (unf_is_lport_valid(lport) != RETURN_OK) - /* Lport is invalid, no retry or handle required, return ok */ - return RETURN_OK; - - unf_lport = (struct unf_lport *)lport->root_lport; - - memset(&pkg, 0, sizeof(struct unf_frame_pkg)); - - xchg = unf_get_sfs_free_xchg_and_init(lport, sns_port->nport_id, sns_port, &fc_entry); - if (!xchg) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) exchange can't be NULL for GFF_ID", - lport->port_id); - - return unf_get_and_post_disc_event(lport, sns_port, nport_id, UNF_DISC_GET_FEATURE); - } - - xchg->cmnd_code = NS_GFF_ID; - xchg->disc_portid = nport_id; - - xchg->ob_callback = unf_gff_id_ob_callback; - xchg->callback = unf_gff_id_callback; - - unf_fill_package(&pkg, xchg, sns_port); - pkg.type = UNF_PKG_GS_REQ; - - gff_id = &fc_entry->gff_id; - memset(gff_id, 0, sizeof(struct unf_gffid)); - unf_fill_gff_id_pld(gff_id, nport_id); - - ret = unf_ls_gs_cmnd_send(lport, &pkg, xchg); - if (ret != RETURN_OK) - unf_cm_free_xchg((void *)lport, (void *)xchg); - else - atomic_dec(&unf_lport->disc.disc_thread_info.disc_contrl_size); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: GFF_ID send %s. Port(0x%x)--->RPort(0x%x). Inquire RPort(0x%x)", - (ret != RETURN_OK) ? "failed" : "succeed", lport->port_id, - sns_port->nport_id, nport_id); - - return ret; -} - -static void unf_fill_gnnid_pld(struct unf_gnnid *gnnid_pld, u32 nport_id) -{ - /* Inquiry R_Port node name from SW */ - FC_CHECK_RETURN_VOID(gnnid_pld); - - gnnid_pld->ctiu_pream.rev_inid = (UNF_REV_NPORTID_INIT); - gnnid_pld->ctiu_pream.gstype_gssub_options = (UNF_FSTYPE_OPT_INIT); - gnnid_pld->ctiu_pream.cmnd_rsp_size = (UNF_FSTYPE_GNN_ID); - gnnid_pld->ctiu_pream.frag_reason_exp_vend = UNF_FRAG_REASON_VENDOR; - - gnnid_pld->nport_id = nport_id; -} - -u32 unf_send_gnn_id(struct unf_lport *lport, struct unf_rport *sns_port, - u32 nport_id) -{ - /* from DISC stop/re-login */ - struct unf_gnnid *unf_gnnid = NULL; - union unf_sfs_u *fc_entry = NULL; - struct unf_xchg *xchg = NULL; - u32 ret = UNF_RETURN_ERROR; - struct unf_frame_pkg pkg; - struct unf_lport *unf_lport = NULL; - - FC_CHECK_RETURN_VALUE(sns_port, UNF_RETURN_ERROR); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "Port(0x%x_0x%x) send gnnid to 0x%x.", lport->port_id, - lport->nport_id, nport_id); - - if (unf_is_lport_valid(lport) != RETURN_OK) - /* Lport is invalid, no retry or handle required, return ok */ - return RETURN_OK; - - unf_lport = (struct unf_lport *)lport->root_lport; - - memset(&pkg, 0, sizeof(struct unf_frame_pkg)); - - xchg = unf_get_sfs_free_xchg_and_init(lport, sns_port->nport_id, - sns_port, &fc_entry); - if (!xchg) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) exchange can't be NULL for GNN_ID", - lport->port_id); - - return unf_get_and_post_disc_event(lport, sns_port, nport_id, - UNF_DISC_GET_NODE_NAME); - } - - xchg->cmnd_code = NS_GNN_ID; - xchg->disc_portid = nport_id; - - xchg->ob_callback = unf_gnn_id_ob_callback; - xchg->callback = unf_gnn_id_callback; - - unf_fill_package(&pkg, xchg, sns_port); - pkg.type = UNF_PKG_GS_REQ; - - unf_gnnid = &fc_entry->gnn_id; /* GNNID payload */ - memset(unf_gnnid, 0, sizeof(struct unf_gnnid)); - unf_fill_gnnid_pld(unf_gnnid, nport_id); - - ret = unf_ls_gs_cmnd_send(lport, &pkg, xchg); - if (ret != RETURN_OK) - unf_cm_free_xchg((void *)lport, (void *)xchg); - else - atomic_dec(&unf_lport->disc.disc_thread_info.disc_contrl_size); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: GNN_ID send %s. Port(0x%x_0x%x)--->RPort(0x%x) inquire Nportid(0x%x)", - (ret != RETURN_OK) ? "failed" : "succeed", lport->port_id, - lport->nport_id, sns_port->nport_id, nport_id); - - return ret; -} - -static void unf_fill_gpnid_pld(struct unf_gpnid *gpnid_pld, u32 nport_id) -{ - FC_CHECK_RETURN_VOID(gpnid_pld); - - gpnid_pld->ctiu_pream.rev_inid = (UNF_REV_NPORTID_INIT); - gpnid_pld->ctiu_pream.gstype_gssub_options = (UNF_FSTYPE_OPT_INIT); - gpnid_pld->ctiu_pream.cmnd_rsp_size = (UNF_FSTYPE_GPN_ID); - gpnid_pld->ctiu_pream.frag_reason_exp_vend = UNF_FRAG_REASON_VENDOR; - - /* Inquiry WWN from SW */ - gpnid_pld->nport_id = nport_id; -} - -u32 unf_send_gpn_id(struct unf_lport *lport, struct unf_rport *sns_port, - u32 nport_id) -{ - struct unf_gpnid *gpnid_pld = NULL; - union unf_sfs_u *fc_entry = NULL; - struct unf_xchg *xchg = NULL; - u32 ret = UNF_RETURN_ERROR; - struct unf_frame_pkg pkg; - struct unf_lport *unf_lport = NULL; - - FC_CHECK_RETURN_VALUE(sns_port, UNF_RETURN_ERROR); - - if (unf_is_lport_valid(lport) != RETURN_OK) - /* Lport is invalid, no retry or handle required, return ok */ - return RETURN_OK; - - unf_lport = (struct unf_lport *)lport->root_lport; - - memset(&pkg, 0, sizeof(struct unf_frame_pkg)); - - xchg = unf_get_sfs_free_xchg_and_init(lport, sns_port->nport_id, - sns_port, &fc_entry); - if (!xchg) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) exchange can't be NULL for GPN_ID", - lport->port_id); - - return unf_get_and_post_disc_event(lport, sns_port, nport_id, - UNF_DISC_GET_PORT_NAME); - } - - xchg->cmnd_code = NS_GPN_ID; - xchg->disc_portid = nport_id; - - xchg->callback = unf_gpn_id_callback; - xchg->ob_callback = unf_gpn_id_ob_callback; - - unf_fill_package(&pkg, xchg, sns_port); - pkg.type = UNF_PKG_GS_REQ; - - gpnid_pld = &fc_entry->gpn_id; - memset(gpnid_pld, 0, sizeof(struct unf_gpnid)); - unf_fill_gpnid_pld(gpnid_pld, nport_id); - - ret = unf_ls_gs_cmnd_send(lport, &pkg, xchg); - if (ret != RETURN_OK) - unf_cm_free_xchg((void *)lport, (void *)xchg); - else - atomic_dec(&unf_lport->disc.disc_thread_info.disc_contrl_size); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: GPN_ID send %s. Port(0x%x)--->RPort(0x%x). Inquire RPort(0x%x)", - (ret != RETURN_OK) ? "failed" : "succeed", lport->port_id, - sns_port->nport_id, nport_id); - - return ret; -} - -static void unf_fill_gid_ft_pld(struct unf_gid *gid_pld) -{ - FC_CHECK_RETURN_VOID(gid_pld); - - gid_pld->ctiu_pream.rev_inid = (UNF_REV_NPORTID_INIT); - gid_pld->ctiu_pream.gstype_gssub_options = (UNF_FSTYPE_OPT_INIT); - gid_pld->ctiu_pream.cmnd_rsp_size = (UNF_FSTYPE_GID_FT); - gid_pld->ctiu_pream.frag_reason_exp_vend = UNF_FRAG_REASON_VENDOR; - - gid_pld->scope_type = (UNF_GID_FT_TYPE); -} - -u32 unf_send_gid_ft(struct unf_lport *lport, struct unf_rport *rport) -{ - struct unf_gid *gid_pld = NULL; - struct unf_gid_rsp *gid_rsp = NULL; - struct unf_gid_acc_pld *gid_acc_pld = NULL; - union unf_sfs_u *fc_entry = NULL; - struct unf_xchg *xchg = NULL; - u32 ret = UNF_RETURN_ERROR; - struct unf_frame_pkg pkg = {0}; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(rport, UNF_RETURN_ERROR); - - xchg = unf_get_sfs_free_xchg_and_init(lport, rport->nport_id, - rport, &fc_entry); - if (!xchg) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) exchange can't be NULL for GID_FT", - lport->port_id); - - return ret; - } - - xchg->cmnd_code = NS_GID_FT; - - xchg->ob_callback = unf_gid_ft_ob_callback; - xchg->callback = unf_gid_ft_callback; - - unf_fill_package(&pkg, xchg, rport); - pkg.type = UNF_PKG_GS_REQ; - - gid_pld = &fc_entry->get_id.gid_req; /* GID req payload */ - unf_fill_gid_ft_pld(gid_pld); - gid_rsp = &fc_entry->get_id.gid_rsp; /* GID rsp payload */ - - gid_acc_pld = (struct unf_gid_acc_pld *)unf_get_one_big_sfs_buf(xchg); - if (!gid_acc_pld) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) allocate GID_FT response buffer failed", - lport->port_id); - - unf_cm_free_xchg(lport, xchg); - return UNF_RETURN_ERROR; - } - memset(gid_acc_pld, 0, sizeof(struct unf_gid_acc_pld)); - gid_rsp->gid_acc_pld = gid_acc_pld; - - ret = unf_ls_gs_cmnd_send(lport, &pkg, xchg); - if (ret != RETURN_OK) - unf_cm_free_xchg((void *)lport, (void *)xchg); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: GID_FT send %s. Port(0x%x)--->RPort(0x%x)", - (ret != RETURN_OK) ? "failed" : "succeed", lport->port_id, - rport->nport_id); - - return ret; -} - -static void unf_fill_gid_pt_pld(struct unf_gid *gid_pld, - struct unf_lport *lport) -{ - FC_CHECK_RETURN_VOID(gid_pld); - FC_CHECK_RETURN_VOID(lport); - - gid_pld->ctiu_pream.rev_inid = (UNF_REV_NPORTID_INIT); - gid_pld->ctiu_pream.gstype_gssub_options = (UNF_FSTYPE_OPT_INIT); - gid_pld->ctiu_pream.cmnd_rsp_size = (UNF_FSTYPE_GID_PT); - gid_pld->ctiu_pream.frag_reason_exp_vend = UNF_FRAG_REASON_VENDOR; - - /* 0x7F000000 means NX_Port */ - gid_pld->scope_type = (UNF_GID_PT_TYPE); - UNF_PRINT_SFS_LIMIT(UNF_INFO, lport->port_id, gid_pld, - sizeof(struct unf_gid)); -} - -u32 unf_send_gid_pt(struct unf_lport *lport, struct unf_rport *rport) -{ - /* from DISC start */ - struct unf_gid *gid_pld = NULL; - struct unf_gid_rsp *gid_rsp = NULL; - struct unf_gid_acc_pld *gid_acc_pld = NULL; - union unf_sfs_u *fc_entry = NULL; - struct unf_xchg *xchg = NULL; - u32 ret = UNF_RETURN_ERROR; - struct unf_frame_pkg pkg = {0}; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(rport, UNF_RETURN_ERROR); - - xchg = unf_get_sfs_free_xchg_and_init(lport, rport->nport_id, - rport, &fc_entry); - if (!xchg) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) exchange can't be NULL for GID_PT", - lport->port_id); - - return ret; - } - - xchg->cmnd_code = NS_GID_PT; - - xchg->ob_callback = unf_gid_pt_ob_callback; - xchg->callback = unf_gid_pt_callback; - - unf_fill_package(&pkg, xchg, rport); - pkg.type = UNF_PKG_GS_REQ; - - gid_pld = &fc_entry->get_id.gid_req; /* GID req payload */ - unf_fill_gid_pt_pld(gid_pld, lport); - gid_rsp = &fc_entry->get_id.gid_rsp; /* GID rsp payload */ - - gid_acc_pld = (struct unf_gid_acc_pld *)unf_get_one_big_sfs_buf(xchg); - if (!gid_acc_pld) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%0x) Allocate GID_PT response buffer failed", - lport->port_id); - - unf_cm_free_xchg(lport, xchg); - return UNF_RETURN_ERROR; - } - memset(gid_acc_pld, 0, sizeof(struct unf_gid_acc_pld)); - gid_rsp->gid_acc_pld = gid_acc_pld; - - ret = unf_ls_gs_cmnd_send(lport, &pkg, xchg); - if (ret != RETURN_OK) - unf_cm_free_xchg((void *)lport, (void *)xchg); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: GID_PT send %s. Port(0x%x_0x%x)--->RPort(0x%x)", - (ret != RETURN_OK) ? "failed" : "succeed", lport->port_id, - lport->nport_id, rport->nport_id); - - return ret; -} - -static void unf_fill_rft_id_pld(struct unf_rftid *rftid_pld, - struct unf_lport *lport) -{ - u32 index = 1; - - FC_CHECK_RETURN_VOID(rftid_pld); - FC_CHECK_RETURN_VOID(lport); - - rftid_pld->ctiu_pream.rev_inid = (UNF_REV_NPORTID_INIT); - rftid_pld->ctiu_pream.gstype_gssub_options = (UNF_FSTYPE_OPT_INIT); - rftid_pld->ctiu_pream.cmnd_rsp_size = (UNF_FSTYPE_RFT_ID); - rftid_pld->ctiu_pream.frag_reason_exp_vend = UNF_FRAG_REASON_VENDOR; - rftid_pld->nport_id = (lport->nport_id); - rftid_pld->fc4_types[ARRAY_INDEX_0] = (UNF_FC4_SCSI_BIT8); - - for (index = ARRAY_INDEX_2; index < UNF_FC4TYPE_CNT; index++) - rftid_pld->fc4_types[index] = 0; -} - -u32 unf_send_rft_id(struct unf_lport *lport, struct unf_rport *rport) -{ - /* After PLOGI process */ - struct unf_rftid *rft_id = NULL; - union unf_sfs_u *fc_entry = NULL; - struct unf_xchg *xchg = NULL; - u32 ret = UNF_RETURN_ERROR; - struct unf_frame_pkg pkg; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(rport, UNF_RETURN_ERROR); - - memset(&pkg, 0, sizeof(struct unf_frame_pkg)); - - xchg = unf_get_sfs_free_xchg_and_init(lport, rport->nport_id, - rport, &fc_entry); - if (!xchg) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) exchange can't be NULL for RFT_ID", - lport->port_id); - - return ret; - } - - xchg->cmnd_code = NS_RFT_ID; - - xchg->callback = unf_rft_id_callback; - xchg->ob_callback = unf_rft_id_ob_callback; - - unf_fill_package(&pkg, xchg, rport); - pkg.type = UNF_PKG_GS_REQ; - - rft_id = &fc_entry->rft_id; - memset(rft_id, 0, sizeof(struct unf_rftid)); - unf_fill_rft_id_pld(rft_id, lport); - ret = unf_ls_gs_cmnd_send(lport, &pkg, xchg); - if (ret != RETURN_OK) - unf_cm_free_xchg((void *)lport, (void *)xchg); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: RFT_ID send %s. Port(0x%x_0x%x)--->RPort(0x%x). rport(0x%p) wwpn(0x%llx) ", - (ret != RETURN_OK) ? "failed" : "succeed", lport->port_id, - lport->nport_id, rport->nport_id, rport, rport->port_name); - - return ret; -} - -static void unf_fill_rff_id_pld(struct unf_rffid *rffid_pld, - struct unf_lport *lport, u32 fc4_type) -{ - FC_CHECK_RETURN_VOID(rffid_pld); - FC_CHECK_RETURN_VOID(lport); - - rffid_pld->ctiu_pream.rev_inid = (UNF_REV_NPORTID_INIT); - rffid_pld->ctiu_pream.gstype_gssub_options = (UNF_FSTYPE_OPT_INIT); - rffid_pld->ctiu_pream.cmnd_rsp_size = (UNF_FSTYPE_RFF_ID); - rffid_pld->ctiu_pream.frag_reason_exp_vend = UNF_FRAG_REASON_VENDOR; - rffid_pld->nport_id = (lport->nport_id); - rffid_pld->fc4_feature = (fc4_type | (lport->options << UNF_SHIFT_4)); -} - -u32 unf_send_rff_id(struct unf_lport *lport, struct unf_rport *rport, - u32 fc4_type) -{ - /* from RFT_ID, then Send SCR */ - struct unf_rffid *rff_id = NULL; - union unf_sfs_u *fc_entry = NULL; - struct unf_xchg *xchg = NULL; - u32 ret = UNF_RETURN_ERROR; - struct unf_frame_pkg pkg = {0}; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(rport, UNF_RETURN_ERROR); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, - UNF_INFO, "%s Enter", __func__); - - xchg = unf_get_sfs_free_xchg_and_init(lport, rport->nport_id, - rport, &fc_entry); - if (!xchg) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) exchange can't be NULL for RFF_ID", - lport->port_id); - - return ret; - } - - xchg->cmnd_code = NS_RFF_ID; - - xchg->callback = unf_rff_id_callback; - xchg->ob_callback = unf_rff_id_ob_callback; - - unf_fill_package(&pkg, xchg, rport); - pkg.type = UNF_PKG_GS_REQ; - - rff_id = &fc_entry->rff_id; - memset(rff_id, 0, sizeof(struct unf_rffid)); - unf_fill_rff_id_pld(rff_id, lport, fc4_type); - - ret = unf_ls_gs_cmnd_send(lport, &pkg, xchg); - if (ret != RETURN_OK) - unf_cm_free_xchg((void *)lport, (void *)xchg); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: RFF_ID feature 0x%x(10:TGT,20:INI,30:COM) send %s. Port(0x%x_0x%x)--->RPortid(0x%x) rport(0x%p)", - lport->options, (ret != RETURN_OK) ? "failed" : "succeed", - lport->port_id, lport->nport_id, rport->nport_id, rport); - - return ret; -} - -void unf_handle_init_gid_acc(struct unf_gid_acc_pld *gid_acc_pld, - struct unf_lport *lport) -{ - /* - * from SCR ACC callback - * NOTE: inquiry disc R_Port used for NPIV - */ - struct unf_disc_rport *disc_rport = NULL; - struct unf_disc *disc = NULL; - u32 ret = UNF_RETURN_ERROR; - u32 gid_port_id = 0; - u32 nport_id = 0; - u32 index = 0; - u8 control = 0; - - FC_CHECK_RETURN_VOID(gid_acc_pld); - FC_CHECK_RETURN_VOID(lport); - - /* - * 1. Find & Check & Get (new) R_Port from list_disc_rports_pool - * then, Add to R_Port Disc_busy_list - */ - while (index < UNF_GID_PORT_CNT) { - gid_port_id = (gid_acc_pld->gid_port_id[index]); - nport_id = UNF_NPORTID_MASK & gid_port_id; - control = UNF_GID_CONTROL(gid_port_id); - - /* for each N_Port_ID from GID_ACC payload */ - if (lport->nport_id != nport_id && nport_id != 0 && - (!unf_lookup_lport_by_nportid(lport, nport_id))) { - /* for New Port, not L_Port */ - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x_0x%x) get nportid(0x%x) from GID_ACC", - lport->port_id, lport->nport_id, nport_id); - - /* Get R_Port from list of RPort Disc Pool */ - disc_rport = unf_rport_get_free_and_init(lport, - UNF_PORT_TYPE_DISC, nport_id); - if (!disc_rport) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x_0x%x) can't allocate new rport(0x%x) from disc pool", - lport->port_id, lport->nport_id, - nport_id); - - index++; - continue; - } - } - - if (UNF_GID_LAST_PORT_ID == (UNF_GID_LAST_PORT_ID & control)) - break; - - index++; - } - - /* - * 2. Do port disc stop operation: - * NOTE: Do DISC & release R_Port from busy_list back to - * list_disc_rports_pool - */ - disc = &lport->disc; - if (!disc->disc_temp.unf_disc_stop) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x_0x%x) disc stop function is NULL", - lport->port_id, lport->nport_id); - - return; - } - - ret = disc->disc_temp.unf_disc_stop(lport); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x_0x%x) do disc stop failed", - lport->port_id, lport->nport_id); - } -} - -u32 unf_rport_relogin(struct unf_lport *lport, u32 nport_id) -{ - /* Send GNN_ID */ - struct unf_rport *sns_port = NULL; - u32 ret = RETURN_OK; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - - /* Get SNS R_Port */ - sns_port = unf_get_rport_by_nport_id(lport, UNF_FC_FID_DIR_SERV); - if (!sns_port) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) can't find fabric Port", lport->nport_id); - - return UNF_RETURN_ERROR; - } - - /* Send GNN_ID now to SW */ - ret = unf_get_and_post_disc_event(lport, sns_port, nport_id, - UNF_DISC_GET_NODE_NAME); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) add discovery event(0x%x) failed Rport(0x%x)", - lport->nport_id, UNF_DISC_GET_NODE_NAME, nport_id); - - /* NOTE: Continue to next stage */ - unf_rcv_gnn_id_rsp_unknown(lport, sns_port, nport_id); - } - - return ret; -} - -u32 unf_rport_check_wwn(struct unf_lport *lport, struct unf_rport *rport) -{ - /* Send GPN_ID */ - struct unf_rport *sns_port = NULL; - u32 ret = RETURN_OK; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(rport, UNF_RETURN_ERROR); - - /* Get SNS R_Port */ - sns_port = unf_get_rport_by_nport_id(lport, UNF_FC_FID_DIR_SERV); - if (!sns_port) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) can't find fabric Port", lport->nport_id); - - return UNF_RETURN_ERROR; - } - - /* Send GPN_ID to SW */ - ret = unf_get_and_post_disc_event(lport, sns_port, rport->nport_id, - UNF_DISC_GET_PORT_NAME); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) add discovery event(0x%x) failed Rport(0x%x)", - lport->nport_id, UNF_DISC_GET_PORT_NAME, - rport->nport_id); - - unf_rcv_gpn_id_rsp_unknown(lport, rport->nport_id); - } - - return ret; -} - -u32 unf_handle_rscn_port_not_indisc(struct unf_lport *lport, u32 rscn_nport_id) -{ - /* RSCN Port_ID not in GID_ACC payload table: Link Down */ - struct unf_rport *unf_rport = NULL; - u32 ret = RETURN_OK; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - - /* from R_Port busy list by N_Port_ID */ - unf_rport = unf_get_rport_by_nport_id(lport, rscn_nport_id); - if (unf_rport) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_KEVENT, - "[info]Port(0x%x) RPort(0x%x) wwpn(0x%llx) has been removed and link down it", - lport->port_id, rscn_nport_id, unf_rport->port_name); - - unf_rport_linkdown(lport, unf_rport); - } else { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "[info]Port(0x%x) has no RPort(0x%x) and do nothing", - lport->nport_id, rscn_nport_id); - } - - return ret; -} - -u32 unf_handle_rscn_port_indisc(struct unf_lport *lport, u32 rscn_nport_id) -{ - /* Send GPN_ID or re-login(GNN_ID) */ - struct unf_rport *unf_rport = NULL; - u32 ret = RETURN_OK; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - - /* from R_Port busy list by N_Port_ID */ - unf_rport = unf_get_rport_by_nport_id(lport, rscn_nport_id); - if (unf_rport) { - /* R_Port exist: send GPN_ID */ - ret = unf_rport_check_wwn(lport, unf_rport); - } else { - if (UNF_PORT_MODE_INI == (lport->options & UNF_PORT_MODE_INI)) - /* Re-LOGIN with INI mode: Send GNN_ID */ - ret = unf_rport_relogin(lport, rscn_nport_id); - else - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x) with no INI feature. Do nothing", - lport->nport_id); - } - - return ret; -} - -static u32 unf_handle_rscn_port_addr(struct unf_port_id_page *portid_page, - struct unf_gid_acc_pld *gid_acc_pld, - struct unf_lport *lport) -{ - /* - * Input parameters: - * 1. Port_ID_page: saved from RSCN payload - * 2. GID_ACC_payload: back from GID_ACC (GID_PT or GID_FT) - * * - * Do work: check whether RSCN Port_ID within GID_ACC payload or not - * then, re-login or link down rport - */ - u32 rscn_nport_id = 0; - u32 gid_port_id = 0; - u32 nport_id = 0; - u32 index = 0; - u8 control = 0; - u32 ret = RETURN_OK; - bool have_same_id = false; - - FC_CHECK_RETURN_VALUE(portid_page, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(gid_acc_pld, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - - /* 1. get RSCN_NPort_ID from (L_Port->Disc->RSCN_Mgr)->RSCN_Port_ID_Page - */ - rscn_nport_id = UNF_SERVICE_GET_NPORTID_FORM_GID_PAGE(portid_page); - - /* - * 2. for RSCN_NPort_ID - * check whether RSCN_NPort_ID within GID_ACC_Payload or not - */ - while (index < UNF_GID_PORT_CNT) { - gid_port_id = (gid_acc_pld->gid_port_id[index]); - nport_id = UNF_NPORTID_MASK & gid_port_id; - control = UNF_GID_CONTROL(gid_port_id); - - if (lport->nport_id != nport_id && nport_id != 0) { - /* is not L_Port */ - if (nport_id == rscn_nport_id) { - /* RSCN Port_ID within GID_ACC payload */ - have_same_id = true; - break; - } - } - - if (UNF_GID_LAST_PORT_ID == (UNF_GID_LAST_PORT_ID & control)) - break; - - index++; - } - - /* 3. RSCN_Port_ID not within GID_ACC payload table */ - if (!have_same_id) { - /* rport has been removed */ - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "[warn]Port(0x%x_0x%x) find RSCN N_Port_ID(0x%x) in GID_ACC table failed", - lport->port_id, lport->nport_id, rscn_nport_id); - - /* Link down rport */ - ret = unf_handle_rscn_port_not_indisc(lport, rscn_nport_id); - - } else { /* 4. RSCN_Port_ID within GID_ACC payload table */ - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "[info]Port(0x%x_0x%x) find RSCN N_Port_ID(0x%x) in GID_ACC table succeed", - lport->port_id, lport->nport_id, rscn_nport_id); - - /* Re-login with INI mode */ - ret = unf_handle_rscn_port_indisc(lport, rscn_nport_id); - } - - return ret; -} - -void unf_check_rport_rscn_process(struct unf_rport *rport, - struct unf_port_id_page *portid_page) -{ - struct unf_rport *unf_rport = rport; - struct unf_port_id_page *unf_portid_page = portid_page; - u8 addr_format = unf_portid_page->addr_format; - - switch (addr_format) { - /* domain+area */ - case UNF_RSCN_AREA_ADDR_GROUP: - if (UNF_GET_DOMAIN_ID(unf_rport->nport_id) == unf_portid_page->port_id_domain && - UNF_GET_AREA_ID(unf_rport->nport_id) == unf_portid_page->port_id_area) - unf_rport->rscn_position = UNF_RPORT_NEED_PROCESS; - - break; - /* domain */ - case UNF_RSCN_DOMAIN_ADDR_GROUP: - if (UNF_GET_DOMAIN_ID(unf_rport->nport_id) == unf_portid_page->port_id_domain) - unf_rport->rscn_position = UNF_RPORT_NEED_PROCESS; - - break; - /* all */ - case UNF_RSCN_FABRIC_ADDR_GROUP: - unf_rport->rscn_position = UNF_RPORT_NEED_PROCESS; - break; - default: - break; - } -} - -static void unf_set_rport_rscn_position(struct unf_lport *lport, - struct unf_port_id_page *portid_page) -{ - struct unf_rport *unf_rport = NULL; - struct list_head *list_node = NULL; - struct list_head *list_nextnode = NULL; - struct unf_disc *disc = NULL; - ulong disc_flag = 0; - ulong rport_flag = 0; - - FC_CHECK_RETURN_VOID(lport); - disc = &lport->disc; - - spin_lock_irqsave(&disc->rport_busy_pool_lock, disc_flag); - list_for_each_safe(list_node, list_nextnode, &disc->list_busy_rports) { - unf_rport = list_entry(list_node, struct unf_rport, entry_rport); - spin_lock_irqsave(&unf_rport->rport_state_lock, rport_flag); - - if (unf_rport->nport_id < UNF_FC_FID_DOM_MGR) { - if (unf_rport->rscn_position == UNF_RPORT_NOT_NEED_PROCESS) - unf_check_rport_rscn_process(unf_rport, portid_page); - } else { - unf_rport->rscn_position = UNF_RPORT_NOT_NEED_PROCESS; - } - - spin_unlock_irqrestore(&unf_rport->rport_state_lock, rport_flag); - } - spin_unlock_irqrestore(&disc->rport_busy_pool_lock, disc_flag); -} - -static void unf_set_rport_rscn_position_local(struct unf_lport *lport) -{ - struct unf_rport *unf_rport = NULL; - struct list_head *list_node = NULL; - struct list_head *list_nextnode = NULL; - struct unf_disc *disc = NULL; - ulong disc_flag = 0; - ulong rport_flag = 0; - - FC_CHECK_RETURN_VOID(lport); - disc = &lport->disc; - - spin_lock_irqsave(&disc->rport_busy_pool_lock, disc_flag); - list_for_each_safe(list_node, list_nextnode, &disc->list_busy_rports) { - unf_rport = list_entry(list_node, struct unf_rport, entry_rport); - spin_lock_irqsave(&unf_rport->rport_state_lock, rport_flag); - - if (unf_rport->nport_id < UNF_FC_FID_DOM_MGR) { - if (unf_rport->rscn_position == UNF_RPORT_NEED_PROCESS) - unf_rport->rscn_position = UNF_RPORT_ONLY_IN_LOCAL_PROCESS; - } else { - unf_rport->rscn_position = UNF_RPORT_NOT_NEED_PROCESS; - } - - spin_unlock_irqrestore(&unf_rport->rport_state_lock, rport_flag); - } - spin_unlock_irqrestore(&disc->rport_busy_pool_lock, disc_flag); -} - -static void unf_reset_rport_rscn_setting(struct unf_lport *lport) -{ - struct unf_rport *rport = NULL; - struct list_head *list_node = NULL; - struct list_head *list_nextnode = NULL; - struct unf_disc *disc = NULL; - ulong rport_flag = 0; - - FC_CHECK_RETURN_VOID(lport); - disc = &lport->disc; - - list_for_each_safe(list_node, list_nextnode, &disc->list_busy_rports) { - rport = list_entry(list_node, struct unf_rport, entry_rport); - spin_lock_irqsave(&rport->rport_state_lock, rport_flag); - rport->rscn_position = UNF_RPORT_NOT_NEED_PROCESS; - spin_unlock_irqrestore(&rport->rport_state_lock, rport_flag); - } -} - -void unf_compare_nport_id_with_rport_list(struct unf_lport *lport, u32 nport_id, - struct unf_port_id_page *portid_page) -{ - struct unf_rport *rport = NULL; - ulong rport_flag = 0; - u8 addr_format = portid_page->addr_format; - - FC_CHECK_RETURN_VOID(lport); - - switch (addr_format) { - /* domain+area */ - case UNF_RSCN_AREA_ADDR_GROUP: - if ((UNF_GET_DOMAIN_ID(nport_id) != portid_page->port_id_domain) || - (UNF_GET_AREA_ID(nport_id) != portid_page->port_id_area)) - return; - - break; - /* domain */ - case UNF_RSCN_DOMAIN_ADDR_GROUP: - if (UNF_GET_DOMAIN_ID(nport_id) != portid_page->port_id_domain) - return; - - break; - /* all */ - case UNF_RSCN_FABRIC_ADDR_GROUP: - break; - /* can't enter this branch guarantee by outer */ - default: - break; - } - - rport = unf_get_rport_by_nport_id(lport, nport_id); - - if (!rport) { - if (UNF_PORT_MODE_INI == (lport->options & UNF_PORT_MODE_INI)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_KEVENT, - "[event]Port(0x%x) Find Rport(0x%x) by RSCN", - lport->nport_id, nport_id); - unf_rport_relogin(lport, nport_id); - } - } else { - spin_lock_irqsave(&rport->rport_state_lock, rport_flag); - if (rport->rscn_position == UNF_RPORT_NEED_PROCESS) - rport->rscn_position = UNF_RPORT_IN_DISC_AND_LOCAL_PROCESS; - - spin_unlock_irqrestore(&rport->rport_state_lock, rport_flag); - } -} - -static void unf_compare_disc_with_local_rport(struct unf_lport *lport, - struct unf_gid_acc_pld *pld, - struct unf_port_id_page *page) -{ - u32 gid_port_id = 0; - u32 nport_id = 0; - u32 index = 0; - u8 control = 0; - - FC_CHECK_RETURN_VOID(pld); - FC_CHECK_RETURN_VOID(lport); - - while (index < UNF_GID_PORT_CNT) { - gid_port_id = (pld->gid_port_id[index]); - nport_id = UNF_NPORTID_MASK & gid_port_id; - control = UNF_GID_CONTROL(gid_port_id); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, - UNF_INFO, "[info]Port(0x%x) DISC N_Port_ID(0x%x)", - lport->nport_id, nport_id); - - if (nport_id != 0 && - (!unf_lookup_lport_by_nportid(lport, nport_id))) - unf_compare_nport_id_with_rport_list(lport, nport_id, page); - - if (UNF_GID_LAST_PORT_ID == (UNF_GID_LAST_PORT_ID & control)) - break; - - index++; - } - - unf_set_rport_rscn_position_local(lport); -} - -static u32 unf_process_each_rport_after_rscn(struct unf_lport *lport, - struct unf_rport *sns_port, - struct unf_rport *rport) -{ - ulong rport_flag = 0; - u32 ret = RETURN_OK; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(sns_port, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(sns_port, UNF_RETURN_ERROR); - - spin_lock_irqsave(&rport->rport_state_lock, rport_flag); - - if (rport->rscn_position == UNF_RPORT_IN_DISC_AND_LOCAL_PROCESS) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_KEVENT, - "[info]Port(0x%x_0x%x) RPort(0x%x) rescan position(0x%x), check wwpn", - lport->port_id, lport->nport_id, rport->nport_id, - rport->rscn_position); - rport->rscn_position = UNF_RPORT_NOT_NEED_PROCESS; - spin_unlock_irqrestore(&rport->rport_state_lock, rport_flag); - ret = unf_rport_check_wwn(lport, rport); - } else if (rport->rscn_position == UNF_RPORT_ONLY_IN_LOCAL_PROCESS) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_KEVENT, - "[event]Port(0x%x_0x%x) RPort(0x%x) rescan position(0x%x), linkdown it", - lport->port_id, lport->nport_id, rport->nport_id, - rport->rscn_position); - rport->rscn_position = UNF_RPORT_NOT_NEED_PROCESS; - spin_unlock_irqrestore(&rport->rport_state_lock, rport_flag); - unf_rport_linkdown(lport, rport); - } else { - spin_unlock_irqrestore(&rport->rport_state_lock, rport_flag); - } - - return ret; -} - -static u32 unf_process_local_rport_after_rscn(struct unf_lport *lport, - struct unf_rport *sns_port) -{ - struct unf_rport *unf_rport = NULL; - struct list_head *list_node = NULL; - struct unf_disc *disc = NULL; - ulong disc_flag = 0; - u32 ret = RETURN_OK; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(sns_port, UNF_RETURN_ERROR); - disc = &lport->disc; - - spin_lock_irqsave(&disc->rport_busy_pool_lock, disc_flag); - if (list_empty(&disc->list_busy_rports)) { - spin_unlock_irqrestore(&disc->rport_busy_pool_lock, disc_flag); - - return UNF_RETURN_ERROR; - } - - list_node = UNF_OS_LIST_NEXT(&disc->list_busy_rports); - - do { - unf_rport = list_entry(list_node, struct unf_rport, entry_rport); - - if (unf_rport->rscn_position == UNF_RPORT_NOT_NEED_PROCESS) { - list_node = UNF_OS_LIST_NEXT(list_node); - continue; - } else { - spin_unlock_irqrestore(&disc->rport_busy_pool_lock, disc_flag); - ret = unf_process_each_rport_after_rscn(lport, sns_port, unf_rport); - spin_lock_irqsave(&disc->rport_busy_pool_lock, disc_flag); - list_node = UNF_OS_LIST_NEXT(&disc->list_busy_rports); - } - } while (list_node != &disc->list_busy_rports); - - unf_reset_rport_rscn_setting(lport); - spin_unlock_irqrestore(&disc->rport_busy_pool_lock, disc_flag); - - return ret; -} - -static u32 unf_handle_rscn_group_addr(struct unf_port_id_page *portid_page, - struct unf_gid_acc_pld *gid_acc_pld, - struct unf_lport *lport) -{ - struct unf_rport *sns_port = NULL; - u32 ret = RETURN_OK; - - FC_CHECK_RETURN_VALUE(portid_page, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(gid_acc_pld, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - - sns_port = unf_get_rport_by_nport_id(lport, UNF_FC_FID_DIR_SERV); - if (!sns_port) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) find fabric port failed", lport->port_id); - - return UNF_RETURN_ERROR; - } - - unf_set_rport_rscn_position(lport, portid_page); - unf_compare_disc_with_local_rport(lport, gid_acc_pld, portid_page); - - ret = unf_process_local_rport_after_rscn(lport, sns_port); - - return ret; -} - -static void unf_handle_rscn_gid_acc(struct unf_gid_acc_pld *gid_acc_pid, - struct unf_lport *lport) -{ - /* for N_Port_ID table return from RSCN */ - struct unf_port_id_page *port_id_page = NULL; - struct unf_rscn_mgr *rscn_mgr = NULL; - struct list_head *list_node = NULL; - ulong flag = 0; - - FC_CHECK_RETURN_VOID(gid_acc_pid); - FC_CHECK_RETURN_VOID(lport); - rscn_mgr = &lport->disc.rscn_mgr; - - spin_lock_irqsave(&rscn_mgr->rscn_id_list_lock, flag); - while (!list_empty(&rscn_mgr->list_using_rscn_page)) { - /* - * for each RSCN_Using_Page(NPortID) - * for each - * L_Port->Disc->RSCN_Mgr->RSCN_Using_Page(Port_ID_Page) - * * NOTE: - * check using_page_port_id whether within GID_ACC payload or - * not - */ - list_node = UNF_OS_LIST_NEXT(&rscn_mgr->list_using_rscn_page); - port_id_page = list_entry(list_node, struct unf_port_id_page, list_node_rscn); - list_del(list_node); /* NOTE: here delete node (from RSCN using Page) */ - spin_unlock_irqrestore(&rscn_mgr->rscn_id_list_lock, flag); - - switch (port_id_page->addr_format) { - /* each page of RSNC corresponding one of N_Port_ID */ - case UNF_RSCN_PORT_ADDR: - (void)unf_handle_rscn_port_addr(port_id_page, gid_acc_pid, lport); - break; - - /* each page of RSNC corresponding address group */ - case UNF_RSCN_AREA_ADDR_GROUP: - case UNF_RSCN_DOMAIN_ADDR_GROUP: - case UNF_RSCN_FABRIC_ADDR_GROUP: - (void)unf_handle_rscn_group_addr(port_id_page, gid_acc_pid, lport); - break; - - default: - break; - } - - /* NOTE: release this RSCN_Node */ - rscn_mgr->unf_release_rscn_node(rscn_mgr, port_id_page); - - /* go to next */ - spin_lock_irqsave(&rscn_mgr->rscn_id_list_lock, flag); - } - - spin_unlock_irqrestore(&rscn_mgr->rscn_id_list_lock, flag); -} - -static void unf_gid_acc_handle(struct unf_gid_acc_pld *gid_acc_pid, - struct unf_lport *lport) -{ -#define UNF_NONE_DISC 0X0 /* before enter DISC */ - struct unf_disc *disc = NULL; - ulong flag = 0; - - FC_CHECK_RETURN_VOID(gid_acc_pid); - FC_CHECK_RETURN_VOID(lport); - disc = &lport->disc; - - spin_lock_irqsave(&disc->rport_busy_pool_lock, flag); - switch (disc->disc_option) { - case UNF_INIT_DISC: /* from SCR callback with INI mode */ - disc->disc_option = UNF_NONE_DISC; - spin_unlock_irqrestore(&disc->rport_busy_pool_lock, flag); - - unf_handle_init_gid_acc(gid_acc_pid, lport); /* R_Port from Disc_list */ - break; - - case UNF_RSCN_DISC: /* from RSCN payload parse(analysis) */ - disc->disc_option = UNF_NONE_DISC; - spin_unlock_irqrestore(&disc->rport_busy_pool_lock, flag); - - unf_handle_rscn_gid_acc(gid_acc_pid, lport); /* R_Port from busy_list */ - break; - - default: - spin_unlock_irqrestore(&disc->rport_busy_pool_lock, flag); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x_0x%x)'s disc option(0x%x) is abnormal", - lport->port_id, lport->nport_id, disc->disc_option); - break; - } -} - -static void unf_gid_ft_ob_callback(struct unf_xchg *xchg) -{ - /* Do recovery */ - struct unf_lport *lport = NULL; - union unf_sfs_u *sfs_ptr = NULL; - struct unf_disc *disc = NULL; - ulong flag = 0; - - FC_CHECK_RETURN_VOID(xchg); - - sfs_ptr = xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr; - if (!sfs_ptr) - return; - - spin_lock_irqsave(&xchg->xchg_state_lock, flag); - lport = xchg->lport; - spin_unlock_irqrestore(&xchg->xchg_state_lock, flag); - if (!lport) - return; - - disc = &lport->disc; - spin_lock_irqsave(&disc->rport_busy_pool_lock, flag); - unf_disc_state_ma(lport, UNF_EVENT_DISC_FAILED); - spin_unlock_irqrestore(&disc->rport_busy_pool_lock, flag); - - /* Do DISC recovery operation */ - unf_disc_error_recovery(lport); -} - -static void unf_gid_ft_callback(void *lport, void *rport, void *xchg) -{ - struct unf_lport *unf_lport = NULL; - struct unf_disc *disc = NULL; - struct unf_gid_acc_pld *gid_acc_pld = NULL; - struct unf_xchg *unf_xchg = NULL; - union unf_sfs_u *sfs_ptr = NULL; - u32 cmnd_rsp_size = 0; - u32 rjt_reason = 0; - ulong flag = 0; - - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(rport); - FC_CHECK_RETURN_VOID(xchg); - - unf_lport = (struct unf_lport *)lport; - unf_xchg = (struct unf_xchg *)xchg; - disc = &unf_lport->disc; - - sfs_ptr = unf_xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr; - gid_acc_pld = sfs_ptr->get_id.gid_rsp.gid_acc_pld; - if (!gid_acc_pld) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]LOGIN: Port(0x%x) GID_FT response payload is NULL", - unf_lport->port_id); - - return; - } - - cmnd_rsp_size = gid_acc_pld->ctiu_pream.cmnd_rsp_size; - if (UNF_CT_IU_ACCEPT == (cmnd_rsp_size & UNF_CT_IU_RSP_MASK)) { - spin_lock_irqsave(&disc->rport_busy_pool_lock, flag); - unf_disc_state_ma(unf_lport, UNF_EVENT_DISC_SUCCESS); - spin_unlock_irqrestore(&disc->rport_busy_pool_lock, flag); - - /* Process GID_FT ACC */ - unf_gid_acc_handle(gid_acc_pld, unf_lport); - } else if (UNF_CT_IU_REJECT == (cmnd_rsp_size & UNF_CT_IU_RSP_MASK)) { - rjt_reason = (gid_acc_pld->ctiu_pream.frag_reason_exp_vend); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]LOGIN: Port(0x%x) GID_FT was rejected with reason code(0x%x)", - unf_lport->port_id, rjt_reason); - - if (UNF_CTIU_RJT_EXP_FC4TYPE_NO_REG == - (rjt_reason & UNF_CTIU_RJT_EXP_MASK)) { - spin_lock_irqsave(&disc->rport_busy_pool_lock, flag); - unf_disc_state_ma(unf_lport, UNF_EVENT_DISC_SUCCESS); - spin_unlock_irqrestore(&disc->rport_busy_pool_lock, flag); - - unf_gid_acc_handle(gid_acc_pld, unf_lport); - } else { - spin_lock_irqsave(&disc->rport_busy_pool_lock, flag); - unf_disc_state_ma(unf_lport, UNF_EVENT_DISC_SUCCESS); - spin_unlock_irqrestore(&disc->rport_busy_pool_lock, flag); - } - } else { - spin_lock_irqsave(&disc->rport_busy_pool_lock, flag); - unf_disc_state_ma(unf_lport, UNF_EVENT_DISC_FAILED); - spin_unlock_irqrestore(&disc->rport_busy_pool_lock, flag); - - /* Do DISC recovery operation */ - unf_disc_error_recovery(unf_lport); - } -} - -static void unf_gid_pt_ob_callback(struct unf_xchg *xchg) -{ - /* Do recovery */ - struct unf_lport *lport = NULL; - union unf_sfs_u *sfs_ptr = NULL; - struct unf_disc *disc = NULL; - ulong flag = 0; - - FC_CHECK_RETURN_VOID(xchg); - - sfs_ptr = xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr; - if (!sfs_ptr) - return; - - spin_lock_irqsave(&xchg->xchg_state_lock, flag); - lport = xchg->lport; - spin_unlock_irqrestore(&xchg->xchg_state_lock, flag); - if (!lport) - return; - - disc = &lport->disc; - spin_lock_irqsave(&disc->rport_busy_pool_lock, flag); - unf_disc_state_ma(lport, UNF_EVENT_DISC_FAILED); - spin_unlock_irqrestore(&disc->rport_busy_pool_lock, flag); - - /* Do DISC recovery operation */ - unf_disc_error_recovery(lport); -} - -static void unf_gid_pt_callback(void *lport, void *rport, void *xchg) -{ - struct unf_lport *unf_lport = NULL; - struct unf_rport *unf_rport = NULL; - struct unf_disc *disc = NULL; - struct unf_gid_acc_pld *gid_acc_pld = NULL; - struct unf_xchg *unf_xchg = NULL; - union unf_sfs_u *sfs_ptr = NULL; - u32 cmnd_rsp_size = 0; - u32 rjt_reason = 0; - ulong flag = 0; - u32 ret = UNF_RETURN_ERROR; - - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(rport); - FC_CHECK_RETURN_VOID(xchg); - - unf_lport = (struct unf_lport *)lport; - unf_rport = (struct unf_rport *)rport; - disc = &unf_lport->disc; - unf_xchg = (struct unf_xchg *)xchg; - sfs_ptr = unf_xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr; - - gid_acc_pld = sfs_ptr->get_id.gid_rsp.gid_acc_pld; - if (!gid_acc_pld) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]LOGIN: Port(0x%x) GID_PT response payload is NULL", - unf_lport->port_id); - return; - } - - cmnd_rsp_size = (gid_acc_pld->ctiu_pream.cmnd_rsp_size); - if ((cmnd_rsp_size & UNF_CT_IU_RSP_MASK) == UNF_CT_IU_ACCEPT) { - spin_lock_irqsave(&disc->rport_busy_pool_lock, flag); - unf_disc_state_ma(unf_lport, UNF_EVENT_DISC_SUCCESS); - spin_unlock_irqrestore(&disc->rport_busy_pool_lock, flag); - - unf_gid_acc_handle(gid_acc_pld, unf_lport); - } else if ((cmnd_rsp_size & UNF_CT_IU_RSP_MASK) == UNF_CT_IU_REJECT) { - rjt_reason = (gid_acc_pld->ctiu_pream.frag_reason_exp_vend); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]LOGIN: Port(0x%x_0x%x) GID_PT was rejected with reason code(0x%x)", - unf_lport->port_id, unf_lport->nport_id, rjt_reason); - - if ((rjt_reason & UNF_CTIU_RJT_EXP_MASK) == - UNF_CTIU_RJT_EXP_PORTTYPE_NO_REG) { - spin_lock_irqsave(&disc->rport_busy_pool_lock, flag); - unf_disc_state_ma(unf_lport, UNF_EVENT_DISC_SUCCESS); - spin_unlock_irqrestore(&disc->rport_busy_pool_lock, flag); - - unf_gid_acc_handle(gid_acc_pld, unf_lport); - } else { - ret = unf_send_gid_ft(unf_lport, unf_rport); - if (ret != RETURN_OK) - goto SEND_GID_PT_FT_FAILED; - } - } else { - goto SEND_GID_PT_FT_FAILED; - } - - return; -SEND_GID_PT_FT_FAILED: - spin_lock_irqsave(&disc->rport_busy_pool_lock, flag); - unf_disc_state_ma(unf_lport, UNF_EVENT_DISC_FAILED); - spin_unlock_irqrestore(&disc->rport_busy_pool_lock, flag); - unf_disc_error_recovery(unf_lport); -} - -static void unf_gnn_id_ob_callback(struct unf_xchg *xchg) -{ - /* Send GFF_ID */ - struct unf_lport *lport = NULL; - struct unf_rport *sns_port = NULL; - u32 ret = UNF_RETURN_ERROR; - u32 nport_id = 0; - struct unf_lport *root_lport = NULL; - - FC_CHECK_RETURN_VOID(xchg); - lport = xchg->lport; - FC_CHECK_RETURN_VOID(lport); - sns_port = xchg->rport; - FC_CHECK_RETURN_VOID(sns_port); - nport_id = xchg->disc_portid; - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]LOGIN: Port(0x%x) send GNN_ID failed to inquire RPort(0x%x)", - lport->port_id, nport_id); - - root_lport = (struct unf_lport *)lport->root_lport; - atomic_inc(&root_lport->disc.disc_thread_info.disc_contrl_size); - wake_up_process(root_lport->disc.disc_thread_info.thread); - - /* NOTE: continue next stage */ - ret = unf_get_and_post_disc_event(lport, sns_port, nport_id, UNF_DISC_GET_FEATURE); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) add discovery event(0x%x) failed Rport(0x%x)", - lport->port_id, UNF_DISC_GET_FEATURE, nport_id); - - unf_rcv_gff_id_rsp_unknown(lport, nport_id); - } -} - -static void unf_rcv_gnn_id_acc(struct unf_lport *lport, - struct unf_rport *sns_port, - struct unf_gnnid_rsp *gnnid_rsp_pld, - u32 nport_id) -{ - /* Send GFF_ID or Link down immediately */ - struct unf_lport *unf_lport = lport; - struct unf_rport *unf_sns_port = sns_port; - struct unf_gnnid_rsp *unf_gnnid_rsp_pld = gnnid_rsp_pld; - struct unf_rport *rport = NULL; - u64 node_name = 0; - u32 ret = UNF_RETURN_ERROR; - - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(sns_port); - FC_CHECK_RETURN_VOID(gnnid_rsp_pld); - - node_name = ((u64)(unf_gnnid_rsp_pld->node_name[ARRAY_INDEX_0]) << UNF_SHIFT_32) | - ((u64)(unf_gnnid_rsp_pld->node_name[ARRAY_INDEX_1])); - - if (unf_lport->node_name == node_name) { - /* R_Port & L_Port with same Node Name */ - rport = unf_get_rport_by_nport_id(unf_lport, nport_id); - if (rport) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_KEVENT, - "[info]Port(0x%x) has the same node name(0x%llx) with RPort(0x%x), linkdown it", - unf_lport->port_id, node_name, nport_id); - - /* Destroy immediately */ - unf_rport_immediate_link_down(unf_lport, rport); - } - } else { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: Port(0x%x) got RPort(0x%x) with node name(0x%llx) by GNN_ID", - unf_lport->port_id, nport_id, node_name); - - /* Start to Send GFF_ID */ - ret = unf_get_and_post_disc_event(unf_lport, unf_sns_port, - nport_id, UNF_DISC_GET_FEATURE); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) add discovery event(0x%x) failed Rport(0x%x)", - unf_lport->port_id, UNF_DISC_GET_FEATURE, nport_id); - - unf_rcv_gff_id_rsp_unknown(unf_lport, nport_id); - } - } -} - -static void unf_rcv_gnn_id_rjt(struct unf_lport *lport, - struct unf_rport *sns_port, - struct unf_gnnid_rsp *gnnid_rsp_pld, - u32 nport_id) -{ - /* Send GFF_ID */ - struct unf_lport *unf_lport = lport; - struct unf_rport *unf_sns_port = sns_port; - struct unf_gnnid_rsp *unf_gnnid_rsp_pld = gnnid_rsp_pld; - u32 rjt_reason = 0; - u32 ret = UNF_RETURN_ERROR; - - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(sns_port); - FC_CHECK_RETURN_VOID(gnnid_rsp_pld); - - rjt_reason = (unf_gnnid_rsp_pld->ctiu_pream.frag_reason_exp_vend); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]LOGIN: Port(0x%x_0x%x) GNN_ID was rejected with reason code(0x%x)", - unf_lport->port_id, unf_lport->nport_id, rjt_reason); - - if (!UNF_GNN_GFF_ID_RJT_REASON(rjt_reason)) { - /* Node existence: Continue next stage */ - ret = unf_get_and_post_disc_event(unf_lport, unf_sns_port, - nport_id, UNF_DISC_GET_FEATURE); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) add discovery event(0x%x) failed Rport(0x%x)", - unf_lport->port_id, UNF_DISC_GET_FEATURE, nport_id); - - unf_rcv_gff_id_rsp_unknown(unf_lport, nport_id); - } - } -} - -void unf_rcv_gnn_id_rsp_unknown(struct unf_lport *lport, - struct unf_rport *sns_port, u32 nport_id) -{ - /* Send GFF_ID */ - struct unf_lport *unf_lport = lport; - struct unf_rport *unf_sns_port = sns_port; - u32 ret = UNF_RETURN_ERROR; - - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(sns_port); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]LOGIN: Port(0x%x_0x%x) Rportid(0x%x) GNN_ID response is unknown. Sending GFF_ID", - unf_lport->port_id, unf_lport->nport_id, nport_id); - - ret = unf_get_and_post_disc_event(unf_lport, unf_sns_port, nport_id, UNF_DISC_GET_FEATURE); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) add discovery event(0x%x) failed Rport(0x%x)", - unf_lport->port_id, UNF_DISC_GET_FEATURE, - nport_id); - - /* NOTE: go to next stage */ - unf_rcv_gff_id_rsp_unknown(unf_lport, nport_id); - } -} - -static void unf_gnn_id_callback(void *lport, void *sns_port, void *xchg) -{ - struct unf_lport *unf_lport = (struct unf_lport *)lport; - struct unf_rport *unf_sns_port = (struct unf_rport *)sns_port; - struct unf_xchg *unf_xchg = (struct unf_xchg *)xchg; - struct unf_gnnid_rsp *gnnid_rsp_pld = NULL; - u32 cmnd_rsp_size = 0; - u32 nport_id = 0; - struct unf_lport *root_lport = NULL; - - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(sns_port); - FC_CHECK_RETURN_VOID(xchg); - - nport_id = unf_xchg->disc_portid; - gnnid_rsp_pld = &unf_xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr->gnn_id_rsp; - cmnd_rsp_size = gnnid_rsp_pld->ctiu_pream.cmnd_rsp_size; - - root_lport = (struct unf_lport *)unf_lport->root_lport; - atomic_inc(&root_lport->disc.disc_thread_info.disc_contrl_size); - wake_up_process(root_lport->disc.disc_thread_info.thread); - - if ((cmnd_rsp_size & UNF_CT_IU_RSP_MASK) == UNF_CT_IU_ACCEPT) { - /* Case ACC: send GFF_ID or Link down immediately */ - unf_rcv_gnn_id_acc(unf_lport, unf_sns_port, gnnid_rsp_pld, nport_id); - } else if ((cmnd_rsp_size & UNF_CT_IU_RSP_MASK) == UNF_CT_IU_REJECT) { - /* Case RJT: send GFF_ID */ - unf_rcv_gnn_id_rjt(unf_lport, unf_sns_port, gnnid_rsp_pld, nport_id); - } else { /* NOTE: continue next stage */ - /* Case unknown: send GFF_ID */ - unf_rcv_gnn_id_rsp_unknown(unf_lport, unf_sns_port, nport_id); - } -} - -static void unf_gff_id_ob_callback(struct unf_xchg *xchg) -{ - /* Send PLOGI */ - struct unf_lport *lport = NULL; - struct unf_lport *root_lport = NULL; - struct unf_rport *rport = NULL; - ulong flag = 0; - u32 ret = UNF_RETURN_ERROR; - u32 nport_id = 0; - - FC_CHECK_RETURN_VOID(xchg); - - spin_lock_irqsave(&xchg->xchg_state_lock, flag); - lport = xchg->lport; - nport_id = xchg->disc_portid; - spin_unlock_irqrestore(&xchg->xchg_state_lock, flag); - - FC_CHECK_RETURN_VOID(lport); - - root_lport = (struct unf_lport *)lport->root_lport; - atomic_inc(&root_lport->disc.disc_thread_info.disc_contrl_size); - wake_up_process(root_lport->disc.disc_thread_info.thread); - - /* Get (safe) R_Port */ - rport = unf_get_rport_by_nport_id(lport, nport_id); - rport = unf_get_safe_rport(lport, rport, UNF_RPORT_REUSE_ONLY, nport_id); - if (!rport) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) can't allocate new RPort(0x%x)", - lport->port_id, nport_id); - return; - } - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x_0x%x) send GFF_ID(0x%x_0x%x) to RPort(0x%x_0x%x) abnormal", - lport->port_id, lport->nport_id, xchg->oxid, xchg->rxid, - rport->rport_index, rport->nport_id); - - /* Update R_Port state: PLOGI_WAIT */ - spin_lock_irqsave(&rport->rport_state_lock, flag); - rport->nport_id = nport_id; - unf_rport_state_ma(rport, UNF_EVENT_RPORT_ENTER_PLOGI); - spin_unlock_irqrestore(&rport->rport_state_lock, flag); - - /* NOTE: Start to send PLOGI */ - ret = unf_send_plogi(lport, rport); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) send PLOGI failed, enter recovry", - lport->port_id); - - /* Do R_Port recovery */ - unf_rport_error_recovery(rport); - } -} - -void unf_rcv_gff_id_acc(struct unf_lport *lport, - struct unf_gffid_rsp *gffid_rsp_pld, u32 nport_id) -{ - /* Delay to LOGIN */ - struct unf_lport *unf_lport = lport; - struct unf_rport *rport = NULL; - struct unf_gffid_rsp *unf_gffid_rsp_pld = gffid_rsp_pld; - u32 fc_4feacture = 0; - ulong flag = 0; - - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(gffid_rsp_pld); - - fc_4feacture = unf_gffid_rsp_pld->fc4_feature[ARRAY_INDEX_1]; - if ((UNF_GFF_ACC_MASK & fc_4feacture) == 0) - fc_4feacture = be32_to_cpu(unf_gffid_rsp_pld->fc4_feature[ARRAY_INDEX_1]); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: Port(0x%x_0x%x) RPort(0x%x) received GFF_ID ACC. FC4 feature is 0x%x(1:TGT,2:INI,3:COM)", - unf_lport->port_id, unf_lport->nport_id, nport_id, fc_4feacture); - - /* Check (& Get new) R_Port */ - rport = unf_get_rport_by_nport_id(unf_lport, nport_id); - if (rport) - rport = unf_find_rport(unf_lport, nport_id, rport->port_name); - - if (rport || (UNF_GET_PORT_OPTIONS(fc_4feacture) != UNF_PORT_MODE_INI)) { - rport = unf_get_safe_rport(unf_lport, rport, UNF_RPORT_REUSE_ONLY, nport_id); - FC_CHECK_RETURN_VOID(rport); - } else { - return; - } - - if ((fc_4feacture & UNF_GFF_ACC_MASK) != 0) { - spin_lock_irqsave(&rport->rport_state_lock, flag); - rport->options = UNF_GET_PORT_OPTIONS(fc_4feacture); - spin_unlock_irqrestore(&rport->rport_state_lock, flag); - } else if (rport->port_name != INVALID_WWPN) { - spin_lock_irqsave(&rport->rport_state_lock, flag); - rport->options = unf_get_port_feature(rport->port_name); - spin_unlock_irqrestore(&rport->rport_state_lock, flag); - } - - /* NOTE: Send PLOGI if necessary */ - unf_check_rport_need_delay_plogi(unf_lport, rport, rport->options); -} - -void unf_rcv_gff_id_rjt(struct unf_lport *lport, - struct unf_gffid_rsp *gffid_rsp_pld, u32 nport_id) -{ - /* Delay LOGIN or LOGO */ - struct unf_lport *unf_lport = lport; - struct unf_rport *rport = NULL; - struct unf_gffid_rsp *unf_gffid_rsp_pld = gffid_rsp_pld; - u32 rjt_reason = 0; - ulong flag = 0; - - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(gffid_rsp_pld); - - /* Check (& Get new) R_Port */ - rport = unf_get_rport_by_nport_id(unf_lport, nport_id); - if (rport) - rport = unf_find_rport(unf_lport, nport_id, rport->port_name); - - if (!rport) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x) get RPort by N_Port_ID(0x%x) failed and alloc new", - unf_lport->port_id, nport_id); - - rport = unf_rport_get_free_and_init(unf_lport, UNF_PORT_TYPE_FC, nport_id); - FC_CHECK_RETURN_VOID(rport); - - spin_lock_irqsave(&rport->rport_state_lock, flag); - rport->nport_id = nport_id; - spin_unlock_irqrestore(&rport->rport_state_lock, flag); - } - - rjt_reason = unf_gffid_rsp_pld->ctiu_pream.frag_reason_exp_vend; - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]LOGIN: Port(0x%x) send GFF_ID for RPort(0x%x) but was rejected. Reason code(0x%x)", - unf_lport->port_id, nport_id, rjt_reason); - - if (!UNF_GNN_GFF_ID_RJT_REASON(rjt_reason)) { - rport = unf_get_safe_rport(lport, rport, UNF_RPORT_REUSE_ONLY, nport_id); - FC_CHECK_RETURN_VOID(rport); - - /* Update R_Port state: PLOGI_WAIT */ - spin_lock_irqsave(&rport->rport_state_lock, flag); - rport->nport_id = nport_id; - unf_rport_state_ma(rport, UNF_EVENT_RPORT_ENTER_PLOGI); - spin_unlock_irqrestore(&rport->rport_state_lock, flag); - - /* Delay to send PLOGI */ - unf_rport_delay_login(rport); - } else { - spin_lock_irqsave(&rport->rport_state_lock, flag); - if (rport->rp_state == UNF_RPORT_ST_INIT) { - spin_unlock_irqrestore(&rport->rport_state_lock, flag); - - /* Enter closing state */ - unf_rport_enter_logo(unf_lport, rport); - } else { - spin_unlock_irqrestore(&rport->rport_state_lock, flag); - } - } -} - -void unf_rcv_gff_id_rsp_unknown(struct unf_lport *lport, u32 nport_id) -{ - /* Send PLOGI */ - struct unf_lport *unf_lport = lport; - struct unf_rport *rport = NULL; - ulong flag = 0; - u32 ret = RETURN_OK; - - FC_CHECK_RETURN_VOID(lport); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]LOGIN: Port(0x%x) send GFF_ID for RPort(0x%x) but response is unknown", - unf_lport->port_id, nport_id); - - /* Get (Safe) R_Port & Set State */ - rport = unf_get_rport_by_nport_id(unf_lport, nport_id); - if (rport) - rport = unf_find_rport(unf_lport, nport_id, rport->port_name); - - if (!rport) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x_0x%x) can't get RPort by NPort ID(0x%x), allocate new RPort", - unf_lport->port_id, unf_lport->nport_id, nport_id); - - rport = unf_rport_get_free_and_init(unf_lport, UNF_PORT_TYPE_FC, nport_id); - FC_CHECK_RETURN_VOID(rport); - - spin_lock_irqsave(&rport->rport_state_lock, flag); - rport->nport_id = nport_id; - spin_unlock_irqrestore(&rport->rport_state_lock, flag); - } - - rport = unf_get_safe_rport(unf_lport, rport, UNF_RPORT_REUSE_ONLY, nport_id); - FC_CHECK_RETURN_VOID(rport); - - /* Update R_Port state: PLOGI_WAIT */ - spin_lock_irqsave(&rport->rport_state_lock, flag); - rport->nport_id = nport_id; - unf_rport_state_ma(rport, UNF_EVENT_RPORT_ENTER_PLOGI); - spin_unlock_irqrestore(&rport->rport_state_lock, flag); - - /* Start to send PLOGI */ - ret = unf_send_plogi(unf_lport, rport); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]LOGIN: Port(0x%x) can not send PLOGI for RPort(0x%x), enter recovery", - unf_lport->port_id, nport_id); - - unf_rport_error_recovery(rport); - } -} - -static void unf_gff_id_callback(void *lport, void *sns_port, void *xchg) -{ - struct unf_lport *unf_lport = (struct unf_lport *)lport; - struct unf_lport *root_lport = NULL; - struct unf_xchg *unf_xchg = (struct unf_xchg *)xchg; - struct unf_gffid_rsp *gffid_rsp_pld = NULL; - u32 cmnd_rsp_size = 0; - u32 nport_id = 0; - - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(sns_port); - FC_CHECK_RETURN_VOID(xchg); - - nport_id = unf_xchg->disc_portid; - - gffid_rsp_pld = &unf_xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr->gff_id_rsp; - cmnd_rsp_size = (gffid_rsp_pld->ctiu_pream.cmnd_rsp_size); - - root_lport = (struct unf_lport *)unf_lport->root_lport; - atomic_inc(&root_lport->disc.disc_thread_info.disc_contrl_size); - wake_up_process(root_lport->disc.disc_thread_info.thread); - - if ((cmnd_rsp_size & UNF_CT_IU_RSP_MASK) == UNF_CT_IU_ACCEPT) { - /* Case for GFF_ID ACC: (Delay)PLOGI */ - unf_rcv_gff_id_acc(unf_lport, gffid_rsp_pld, nport_id); - } else if ((cmnd_rsp_size & UNF_CT_IU_RSP_MASK) == UNF_CT_IU_REJECT) { - /* Case for GFF_ID RJT: Delay PLOGI or LOGO directly */ - unf_rcv_gff_id_rjt(unf_lport, gffid_rsp_pld, nport_id); - } else { - /* Send PLOGI */ - unf_rcv_gff_id_rsp_unknown(unf_lport, nport_id); - } -} - -static void unf_rcv_gpn_id_acc(struct unf_lport *lport, - u32 nport_id, u64 port_name) -{ - /* then PLOGI or re-login */ - struct unf_lport *unf_lport = lport; - struct unf_rport *rport = NULL; - ulong flag = 0; - u32 ret = UNF_RETURN_ERROR; - - rport = unf_find_valid_rport(unf_lport, port_name, nport_id); - if (rport) { - /* R_Port with TGT mode & L_Port with INI mode: - * send PLOGI with INIT state - */ - if ((rport->options & UNF_PORT_MODE_TGT) == UNF_PORT_MODE_TGT) { - rport = unf_get_safe_rport(lport, rport, UNF_RPORT_REUSE_INIT, nport_id); - FC_CHECK_RETURN_VOID(rport); - - /* Update R_Port state: PLOGI_WAIT */ - spin_lock_irqsave(&rport->rport_state_lock, flag); - rport->nport_id = nport_id; - unf_rport_state_ma(rport, UNF_EVENT_RPORT_ENTER_PLOGI); - spin_unlock_irqrestore(&rport->rport_state_lock, flag); - - /* Start to send PLOGI */ - ret = unf_send_plogi(unf_lport, rport); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]LOGIN: Port(0x%x_0x%x) send PLOGI failed for 0x%x, enter recovry", - unf_lport->port_id, unf_lport->nport_id, nport_id); - - unf_rport_error_recovery(rport); - } - } else { - spin_lock_irqsave(&rport->rport_state_lock, flag); - if (rport->rp_state != UNF_RPORT_ST_PLOGI_WAIT && - rport->rp_state != UNF_RPORT_ST_PRLI_WAIT && - rport->rp_state != UNF_RPORT_ST_READY) { - unf_rport_state_ma(rport, UNF_EVENT_RPORT_LOGO); - spin_unlock_irqrestore(&rport->rport_state_lock, flag); - - /* Do LOGO operation */ - unf_rport_enter_logo(unf_lport, rport); - } else { - spin_unlock_irqrestore(&rport->rport_state_lock, flag); - } - } - } else { - /* Send GNN_ID */ - (void)unf_rport_relogin(unf_lport, nport_id); - } -} - -static void unf_rcv_gpn_id_rjt(struct unf_lport *lport, u32 nport_id) -{ - struct unf_lport *unf_lport = lport; - struct unf_rport *rport = NULL; - - FC_CHECK_RETURN_VOID(lport); - - rport = unf_get_rport_by_nport_id(unf_lport, nport_id); - if (rport) - /* Do R_Port Link down */ - unf_rport_linkdown(unf_lport, rport); -} - -void unf_rcv_gpn_id_rsp_unknown(struct unf_lport *lport, u32 nport_id) -{ - struct unf_lport *unf_lport = lport; - - FC_CHECK_RETURN_VOID(lport); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]LOGIN: Port(0x%x) wrong response of GPN_ID with RPort(0x%x)", - unf_lport->port_id, nport_id); - - /* NOTE: go to next stage */ - (void)unf_rport_relogin(unf_lport, nport_id); -} - -static void unf_gpn_id_ob_callback(struct unf_xchg *xchg) -{ - struct unf_lport *lport = NULL; - u32 nport_id = 0; - struct unf_lport *root_lport = NULL; - - FC_CHECK_RETURN_VOID(xchg); - - lport = xchg->lport; - nport_id = xchg->disc_portid; - FC_CHECK_RETURN_VOID(lport); - - root_lport = (struct unf_lport *)lport->root_lport; - atomic_inc(&root_lport->disc.disc_thread_info.disc_contrl_size); - wake_up_process(root_lport->disc.disc_thread_info.thread); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]LOGIN: Port(0x%x) send GPN_ID failed to inquire RPort(0x%x)", - lport->port_id, nport_id); - - /* NOTE: go to next stage */ - (void)unf_rport_relogin(lport, nport_id); -} - -static void unf_gpn_id_callback(void *lport, void *sns_port, void *xchg) -{ - struct unf_lport *unf_lport = NULL; - struct unf_xchg *unf_xchg = NULL; - struct unf_gpnid_rsp *gpnid_rsp_pld = NULL; - u64 port_name = 0; - u32 cmnd_rsp_size = 0; - u32 nport_id = 0; - struct unf_lport *root_lport = NULL; - - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(sns_port); - FC_CHECK_RETURN_VOID(xchg); - - unf_lport = (struct unf_lport *)lport; - unf_xchg = (struct unf_xchg *)xchg; - nport_id = unf_xchg->disc_portid; - - root_lport = (struct unf_lport *)unf_lport->root_lport; - atomic_inc(&root_lport->disc.disc_thread_info.disc_contrl_size); - wake_up_process(root_lport->disc.disc_thread_info.thread); - - gpnid_rsp_pld = &unf_xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr->gpn_id_rsp; - cmnd_rsp_size = gpnid_rsp_pld->ctiu_pream.cmnd_rsp_size; - if (UNF_CT_IU_ACCEPT == (cmnd_rsp_size & UNF_CT_IU_RSP_MASK)) { - /* GPN_ID ACC */ - port_name = ((u64)(gpnid_rsp_pld->port_name[ARRAY_INDEX_0]) - << UNF_SHIFT_32) | - ((u64)(gpnid_rsp_pld->port_name[ARRAY_INDEX_1])); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: Port(0x%x) GPN_ID ACC with WWN(0x%llx) RPort NPort ID(0x%x)", - unf_lport->port_id, port_name, nport_id); - - /* Send PLOGI or LOGO or GNN_ID */ - unf_rcv_gpn_id_acc(unf_lport, nport_id, port_name); - } else if (UNF_CT_IU_REJECT == (cmnd_rsp_size & UNF_CT_IU_RSP_MASK)) { - /* GPN_ID RJT: Link Down */ - unf_rcv_gpn_id_rjt(unf_lport, nport_id); - } else { - /* GPN_ID response type unknown: Send GNN_ID */ - unf_rcv_gpn_id_rsp_unknown(unf_lport, nport_id); - } -} - -static void unf_rff_id_ob_callback(struct unf_xchg *xchg) -{ - /* Do recovery */ - struct unf_lport *lport = NULL; - ulong flag = 0; - - FC_CHECK_RETURN_VOID(xchg); - - spin_lock_irqsave(&xchg->xchg_state_lock, flag); - lport = xchg->lport; - spin_unlock_irqrestore(&xchg->xchg_state_lock, flag); - - FC_CHECK_RETURN_VOID(lport); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]LOGIN: Port(0x%x_0x%x) send RFF_ID failed", - lport->port_id, lport->nport_id); - - unf_lport_error_recovery(lport); -} - -static void unf_rff_id_callback(void *lport, void *rport, void *xchg) -{ - struct unf_lport *unf_lport = NULL; - struct unf_rport *unf_rport = NULL; - struct unf_xchg *unf_xchg = NULL; - struct unf_ctiu_prem *ctiu_prem = NULL; - u32 ret = UNF_RETURN_ERROR; - u32 cmnd_rsp_size = 0; - ulong flag = 0; - - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(rport); - FC_CHECK_RETURN_VOID(xchg); - - unf_lport = (struct unf_lport *)lport; - unf_xchg = (struct unf_xchg *)xchg; - if (unlikely(!unf_xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr)) - return; - - unf_rport = unf_get_rport_by_nport_id(unf_lport, UNF_FC_FID_FCTRL); - unf_rport = unf_get_safe_rport(unf_lport, unf_rport, - UNF_RPORT_REUSE_ONLY, UNF_FC_FID_FCTRL); - if (unlikely(!unf_rport)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) can't allocate RPort(0x%x)", - unf_lport->port_id, UNF_FC_FID_FCTRL); - return; - } - - unf_rport->nport_id = UNF_FC_FID_FCTRL; - ctiu_prem = &unf_xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr->rff_id_rsp.ctiu_pream; - cmnd_rsp_size = ctiu_prem->cmnd_rsp_size; - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "[info]LOGIN: Port(0x%x_0x%x) RFF_ID rsp is (0x%x)", - unf_lport->port_id, unf_lport->nport_id, - (cmnd_rsp_size & UNF_CT_IU_RSP_MASK)); - - /* RSP Type check: some SW not support RFF_ID, go to next stage also */ - if ((cmnd_rsp_size & UNF_CT_IU_RSP_MASK) == UNF_CT_IU_ACCEPT) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: Port(0x%x_0x%x) receive RFF ACC(0x%x) in state(0x%x)", - unf_lport->port_id, unf_lport->nport_id, - (cmnd_rsp_size & UNF_CT_IU_RSP_MASK), unf_lport->states); - } else { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]LOGIN: Port(0x%x_0x%x) receive RFF RJT(0x%x) in state(0x%x) with RJT reason code(0x%x) explanation(0x%x)", - unf_lport->port_id, unf_lport->nport_id, - (cmnd_rsp_size & UNF_CT_IU_RSP_MASK), unf_lport->states, - (ctiu_prem->frag_reason_exp_vend) & UNF_CT_IU_REASON_MASK, - (ctiu_prem->frag_reason_exp_vend) & UNF_CT_IU_EXPLAN_MASK); - } - - /* L_Port state check */ - spin_lock_irqsave(&unf_lport->lport_state_lock, flag); - if (unf_lport->states != UNF_LPORT_ST_RFF_ID_WAIT) { - spin_unlock_irqrestore(&unf_lport->lport_state_lock, flag); - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]LOGIN: Port(0x%x_0x%x) receive RFF reply in state(0x%x)", - unf_lport->port_id, unf_lport->nport_id, unf_lport->states); - - return; - } - /* LPort: RFF_ID_WAIT --> SCR_WAIT */ - unf_lport_state_ma(unf_lport, UNF_EVENT_LPORT_REMOTE_ACC); - spin_unlock_irqrestore(&unf_lport->lport_state_lock, flag); - - ret = unf_send_scr(unf_lport, unf_rport); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]LOGIN: Port(0x%x_0x%x) send SCR failed", - unf_lport->port_id, unf_lport->nport_id); - unf_lport_error_recovery(unf_lport); - } -} - -static void unf_rft_id_ob_callback(struct unf_xchg *xchg) -{ - struct unf_lport *lport = NULL; - ulong flag = 0; - - FC_CHECK_RETURN_VOID(xchg); - spin_lock_irqsave(&xchg->xchg_state_lock, flag); - lport = xchg->lport; - spin_unlock_irqrestore(&xchg->xchg_state_lock, flag); - FC_CHECK_RETURN_VOID(lport); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]LOGIN: Port(0x%x_0x%x) send RFT_ID failed", - lport->port_id, lport->nport_id); - unf_lport_error_recovery(lport); -} - -static void unf_rft_id_callback(void *lport, void *rport, void *xchg) -{ - /* RFT_ID --->>> RFF_ID */ - struct unf_lport *unf_lport = NULL; - struct unf_rport *unf_rport = NULL; - struct unf_xchg *unf_xchg = NULL; - struct unf_ctiu_prem *ctiu_prem = NULL; - u32 ret = UNF_RETURN_ERROR; - u32 cmnd_rsp_size = 0; - ulong flag = 0; - - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(rport); - FC_CHECK_RETURN_VOID(xchg); - - unf_lport = (struct unf_lport *)lport; - unf_rport = (struct unf_rport *)rport; - unf_xchg = (struct unf_xchg *)xchg; - - if (!unf_xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) SFS entry is NULL with state(0x%x)", - unf_lport->port_id, unf_lport->states); - return; - } - - ctiu_prem = &unf_xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr - ->rft_id_rsp.ctiu_pream; - cmnd_rsp_size = (ctiu_prem->cmnd_rsp_size); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: Port(0x%x_0x%x) RFT_ID response is (0x%x)", - (cmnd_rsp_size & UNF_CT_IU_RSP_MASK), unf_lport->port_id, - unf_lport->nport_id); - - if (UNF_CT_IU_ACCEPT == (cmnd_rsp_size & UNF_CT_IU_RSP_MASK)) { - /* Case for RFT_ID ACC: send RFF_ID */ - spin_lock_irqsave(&unf_lport->lport_state_lock, flag); - if (unf_lport->states != UNF_LPORT_ST_RFT_ID_WAIT) { - spin_unlock_irqrestore(&unf_lport->lport_state_lock, flag); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x_0x%x) receive RFT_ID ACC in state(0x%x)", - unf_lport->port_id, unf_lport->nport_id, - unf_lport->states); - - return; - } - - /* LPort: RFT_ID_WAIT --> RFF_ID_WAIT */ - unf_lport_state_ma(unf_lport, UNF_EVENT_LPORT_REMOTE_ACC); - spin_unlock_irqrestore(&unf_lport->lport_state_lock, flag); - - /* Start to send RFF_ID GS command */ - ret = unf_send_rff_id(unf_lport, unf_rport, UNF_FC4_FCP_TYPE); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]LOGIN: Port(0x%x_0x%x) send RFF_ID failed", - unf_lport->port_id, unf_lport->nport_id); - unf_lport_error_recovery(unf_lport); - } - } else { - /* Case for RFT_ID RJT: do recovery */ - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]LOGIN: Port(0x%x_0x%x) receive RFT_ID RJT with reason_code(0x%x) explanation(0x%x)", - unf_lport->port_id, unf_lport->nport_id, - (ctiu_prem->frag_reason_exp_vend) & UNF_CT_IU_REASON_MASK, - (ctiu_prem->frag_reason_exp_vend) & UNF_CT_IU_EXPLAN_MASK); - - /* Do L_Port recovery */ - unf_lport_error_recovery(unf_lport); - } -} - -static void unf_scr_ob_callback(struct unf_xchg *xchg) -{ - /* Callback fucnion for exception: Do L_Port error recovery */ - struct unf_lport *lport = NULL; - ulong flag = 0; - - FC_CHECK_RETURN_VOID(xchg); - - spin_lock_irqsave(&xchg->xchg_state_lock, flag); - lport = xchg->lport; - spin_unlock_irqrestore(&xchg->xchg_state_lock, flag); - - FC_CHECK_RETURN_VOID(lport); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) send SCR failed and do port recovery", - lport->port_id); - - unf_lport_error_recovery(lport); -} - -static void unf_scr_callback(void *lport, void *rport, void *xchg) -{ - /* Callback function for SCR response: Send GID_PT with INI mode */ - struct unf_lport *unf_lport = NULL; - struct unf_disc *disc = NULL; - struct unf_xchg *unf_xchg = NULL; - struct unf_els_acc *els_acc = NULL; - u32 ret = UNF_RETURN_ERROR; - ulong port_flag = 0; - ulong disc_flag = 0; - u32 cmnd = 0; - - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(xchg); - - unf_lport = (struct unf_lport *)lport; - unf_xchg = (struct unf_xchg *)xchg; - disc = &unf_lport->disc; - - if (!unf_xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr) - return; - - els_acc = &unf_xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr->els_acc; - if (unf_xchg->byte_orders & UNF_BIT_2) - cmnd = be32_to_cpu(els_acc->cmnd); - else - cmnd = (els_acc->cmnd); - - if ((cmnd & UNF_ELS_CMND_HIGH_MASK) == UNF_ELS_CMND_ACC) { - spin_lock_irqsave(&unf_lport->lport_state_lock, port_flag); - if (unf_lport->states != UNF_LPORT_ST_SCR_WAIT) { - spin_unlock_irqrestore(&unf_lport->lport_state_lock, - port_flag); - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x_0x%x) receive SCR ACC with error state(0x%x)", - unf_lport->port_id, unf_lport->nport_id, - unf_lport->states); - return; - } - - /* LPort: SCR_WAIT --> READY */ - unf_lport_state_ma(unf_lport, UNF_EVENT_LPORT_REMOTE_ACC); - if (unf_lport->states == UNF_LPORT_ST_READY) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: Port(0x%x_0x%x) enter READY state when received SCR response", - unf_lport->port_id, unf_lport->nport_id); - } - - /* Start to Discovery with INI mode: GID_PT */ - if ((unf_lport->options & UNF_PORT_MODE_INI) == - UNF_PORT_MODE_INI) { - spin_unlock_irqrestore(&unf_lport->lport_state_lock, - port_flag); - - if (unf_lport->disc.disc_temp.unf_disc_start) { - spin_lock_irqsave(&disc->rport_busy_pool_lock, - disc_flag); - unf_lport->disc.disc_option = UNF_INIT_DISC; - disc->last_disc_jiff = jiffies; - spin_unlock_irqrestore(&disc->rport_busy_pool_lock, disc_flag); - - ret = unf_lport->disc.disc_temp.unf_disc_start(unf_lport); - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "[info]LOGIN: Port(0x%x) DISC %s with INI mode", - unf_lport->port_id, - (ret != RETURN_OK) ? "failed" : "succeed"); - } - return; - } - - spin_unlock_irqrestore(&unf_lport->lport_state_lock, port_flag); - /* NOTE: set state with UNF_DISC_ST_END used for - * RSCN process - */ - spin_lock_irqsave(&disc->rport_busy_pool_lock, disc_flag); - unf_lport->disc.states = UNF_DISC_ST_END; - spin_unlock_irqrestore(&disc->rport_busy_pool_lock, disc_flag); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "[info]Port(0x%x) is TGT mode, no need to discovery", - unf_lport->port_id); - - return; - } - unf_lport_error_recovery(unf_lport); -} - -void unf_check_rport_need_delay_plogi(struct unf_lport *lport, - struct unf_rport *rport, u32 port_feature) -{ - /* - * Called by: - * 1. Private loop - * 2. RCVD GFF_ID ACC - */ - struct unf_lport *unf_lport = lport; - struct unf_rport *unf_rport = rport; - ulong flag = 0; - u32 nport_id = 0; - u32 ret = UNF_RETURN_ERROR; - - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(rport); - nport_id = unf_rport->nport_id; - - /* - * Send GFF_ID means L_Port has INI attribute - * * - * When to send PLOGI: - * 1. R_Port has TGT mode (COM or TGT), send PLOGI immediately - * 2. R_Port only with INI, send LOGO immediately - * 3. R_Port with unknown attribute, delay to send PLOGI - */ - if ((UNF_PORT_MODE_TGT & port_feature) || - (UNF_LPORT_ENHANCED_FEATURE_ENHANCED_GFF & - unf_lport->enhanced_features)) { - /* R_Port has TGT mode: send PLOGI immediately */ - unf_rport = unf_get_safe_rport(lport, unf_rport, UNF_RPORT_REUSE_ONLY, nport_id); - FC_CHECK_RETURN_VOID(unf_rport); - - /* Update R_Port state: PLOGI_WAIT */ - spin_lock_irqsave(&unf_rport->rport_state_lock, flag); - unf_rport->nport_id = nport_id; - unf_rport_state_ma(unf_rport, UNF_EVENT_RPORT_ENTER_PLOGI); - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flag); - - /* Start to send PLOGI */ - ret = unf_send_plogi(unf_lport, unf_rport); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]LOGIN: Port(0x%x_0x%x) send PLOGI to RPort(0x%x) failed", - unf_lport->port_id, unf_lport->nport_id, - nport_id); - - unf_rport_error_recovery(unf_rport); - } - } else if (port_feature == UNF_PORT_MODE_INI) { - /* R_Port only with INI mode: can't send PLOGI - * --->>> LOGO/nothing - */ - spin_lock_irqsave(&unf_rport->rport_state_lock, flag); - if (unf_rport->rp_state == UNF_RPORT_ST_INIT) { - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flag); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]LOGIN: Port(0x%x_0x%x) send LOGO to RPort(0x%x) which only with INI mode", - unf_lport->port_id, unf_lport->nport_id, nport_id); - - /* Enter Closing state */ - unf_rport_enter_logo(unf_lport, unf_rport); - } else { - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flag); - } - } else { - /* Unknown R_Port attribute: Delay to send PLOGI */ - unf_rport = unf_get_safe_rport(lport, unf_rport, UNF_RPORT_REUSE_ONLY, nport_id); - FC_CHECK_RETURN_VOID(unf_rport); - - /* Update R_Port state: PLOGI_WAIT */ - spin_lock_irqsave(&unf_rport->rport_state_lock, flag); - unf_rport->nport_id = nport_id; - unf_rport_state_ma(unf_rport, UNF_EVENT_RPORT_ENTER_PLOGI); - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flag); - - unf_rport_delay_login(unf_rport); - } -} diff --git a/drivers/scsi/spfc/common/unf_gs.h b/drivers/scsi/spfc/common/unf_gs.h deleted file mode 100644 index d9856133b3cd..000000000000 --- a/drivers/scsi/spfc/common/unf_gs.h +++ /dev/null @@ -1,58 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef UNF_GS_H -#define UNF_GS_H - -#include "unf_type.h" -#include "unf_lport.h" - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -u32 unf_send_scr(struct unf_lport *lport, - struct unf_rport *rport); -u32 unf_send_ctpass_thru(struct unf_lport *lport, - void *buffer, u32 bufflen); - -u32 unf_send_gid_ft(struct unf_lport *lport, - struct unf_rport *rport); -u32 unf_send_gid_pt(struct unf_lport *lport, - struct unf_rport *rport); -u32 unf_send_gpn_id(struct unf_lport *lport, - struct unf_rport *sns_port, u32 nport_id); -u32 unf_send_gnn_id(struct unf_lport *lport, - struct unf_rport *sns_port, u32 nport_id); -u32 unf_send_gff_id(struct unf_lport *lport, - struct unf_rport *sns_port, u32 nport_id); - -u32 unf_send_rff_id(struct unf_lport *lport, - struct unf_rport *rport, u32 fc4_type); -u32 unf_send_rft_id(struct unf_lport *lport, - struct unf_rport *rport); -void unf_rcv_gnn_id_rsp_unknown(struct unf_lport *lport, - struct unf_rport *sns_port, u32 nport_id); -void unf_rcv_gpn_id_rsp_unknown(struct unf_lport *lport, u32 nport_id); -void unf_rcv_gff_id_rsp_unknown(struct unf_lport *lport, u32 nport_id); -void unf_check_rport_need_delay_plogi(struct unf_lport *lport, - struct unf_rport *rport, u32 port_feature); - -struct send_com_trans_in { - unsigned char port_wwn[8]; - u32 req_buffer_count; - unsigned char req_buffer[ARRAY_INDEX_1]; -}; - -struct send_com_trans_out { - u32 hba_status; - u32 total_resp_buffer_cnt; - u32 actual_resp_buffer_cnt; - unsigned char resp_buffer[ARRAY_INDEX_1]; -}; - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif diff --git a/drivers/scsi/spfc/common/unf_init.c b/drivers/scsi/spfc/common/unf_init.c deleted file mode 100644 index 7e6f98d16977..000000000000 --- a/drivers/scsi/spfc/common/unf_init.c +++ /dev/null @@ -1,353 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#include "unf_type.h" -#include "unf_log.h" -#include "unf_scsi_common.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" -#include "unf_io_abnormal.h" - -#define UNF_PID 12 -#define MY_PID UNF_PID - -#define RPORT_FEATURE_POOL_SIZE 4096 -struct task_struct *event_task_thread; -struct workqueue_struct *unf_wq; - -atomic_t fc_mem_ref; - -struct unf_global_card_thread card_thread_mgr; -u32 unf_dgb_level = UNF_MAJOR; -u32 log_print_level = UNF_INFO; -u32 log_limited_times = UNF_LOGIN_ATT_PRINT_TIMES; - -static struct unf_esgl_page *unf_get_one_free_esgl_page - (void *lport, struct unf_frame_pkg *pkg) -{ - struct unf_lport *unf_lport = NULL; - struct unf_xchg *unf_xchg = NULL; - - FC_CHECK_RETURN_VALUE(lport, NULL); - FC_CHECK_RETURN_VALUE(pkg, NULL); - - unf_lport = (struct unf_lport *)lport; - unf_xchg = (struct unf_xchg *)pkg->xchg_contex; - - return unf_get_and_add_one_free_esgl_page(unf_lport, unf_xchg); -} - -static int unf_get_cfg_parms(char *section_name, struct unf_cfg_item *cfg_itm, - u32 *cfg_value, u32 itemnum) -{ - /* Maximum length of a configuration item value, including the end - * character - */ -#define UNF_MAX_ITEM_VALUE_LEN (256) - - u32 *unf_cfg_value = NULL; - struct unf_cfg_item *unf_cfg_itm = NULL; - u32 i = 0; - - unf_cfg_itm = cfg_itm; - unf_cfg_value = cfg_value; - - for (i = 0; i < itemnum; i++) { - if (!unf_cfg_itm || !unf_cfg_value) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, - UNF_ERR, - "[err]Config name or value is NULL"); - - return UNF_RETURN_ERROR; - } - - if (strcmp("End", unf_cfg_itm->puc_name) == 0x0) - break; - - if (strcmp("fw_path", unf_cfg_itm->puc_name) == 0x0) { - unf_cfg_itm++; - unf_cfg_value += UNF_MAX_ITEM_VALUE_LEN / sizeof(u32); - continue; - } - - *unf_cfg_value = unf_cfg_itm->default_value; - unf_cfg_itm++; - unf_cfg_value++; - } - - return RETURN_OK; -} - -struct unf_cm_handle_op unf_cm_handle_ops = { - .unf_alloc_local_port = unf_lport_create_and_init, - .unf_release_local_port = unf_release_local_port, - .unf_receive_ls_gs_pkg = unf_receive_ls_gs_pkg, - .unf_receive_bls_pkg = unf_receive_bls_pkg, - .unf_send_els_done = unf_send_els_done, - .unf_receive_ini_response = unf_ini_scsi_completed, - .unf_get_cfg_parms = unf_get_cfg_parms, - .unf_receive_marker_status = unf_recv_tmf_marker_status, - .unf_receive_abts_marker_status = unf_recv_abts_marker_status, - - .unf_process_fcp_cmnd = NULL, - .unf_tgt_cmnd_xfer_or_rsp_echo = NULL, - .unf_cm_get_sgl_entry = unf_ini_get_sgl_entry, - .unf_cm_get_dif_sgl_entry = unf_ini_get_dif_sgl_entry, - .unf_get_one_free_esgl_page = unf_get_one_free_esgl_page, - .unf_fc_port_event = unf_fc_port_link_event, -}; - -u32 unf_get_cm_handle_ops(struct unf_cm_handle_op *cm_handle) -{ - FC_CHECK_RETURN_VALUE(cm_handle, UNF_RETURN_ERROR); - - memcpy(cm_handle, &unf_cm_handle_ops, sizeof(struct unf_cm_handle_op)); - - return RETURN_OK; -} - -static void unf_deinit_cm_handle_ops(void) -{ - memset(&unf_cm_handle_ops, 0, sizeof(struct unf_cm_handle_op)); -} - -int unf_event_process(void *worker_ptr) -{ - struct list_head *event_list = NULL; - struct unf_cm_event_report *event_node = NULL; - struct completion *create_done = (struct completion *)worker_ptr; - ulong flags = 0; - - set_user_nice(current, UNF_OS_THRD_PRI_LOW); - recalc_sigpending(); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_INFO, - "[event]Enter event thread"); - - if (create_done) - complete(create_done); - - do { - spin_lock_irqsave(&fc_event_list.fc_event_list_lock, flags); - if (list_empty(&fc_event_list.list_head)) { - spin_unlock_irqrestore(&fc_event_list.fc_event_list_lock, flags); - - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout((long)msecs_to_jiffies(UNF_S_TO_MS)); - } else { - event_list = UNF_OS_LIST_NEXT(&fc_event_list.list_head); - list_del_init(event_list); - fc_event_list.list_num--; - event_node = list_entry(event_list, - struct unf_cm_event_report, - list_entry); - spin_unlock_irqrestore(&fc_event_list.fc_event_list_lock, flags); - - /* Process event node */ - unf_handle_event(event_node); - } - } while (!kthread_should_stop()); - - FC_DRV_PRINT(UNF_LOG_EVENT, UNF_MAJOR, - "[event]Event thread exit"); - - return RETURN_OK; -} - -static int unf_creat_event_center(void) -{ - struct completion create_done; - - init_completion(&create_done); - INIT_LIST_HEAD(&fc_event_list.list_head); - fc_event_list.list_num = 0; - spin_lock_init(&fc_event_list.fc_event_list_lock); - - event_task_thread = kthread_run(unf_event_process, &create_done, "spfc_event"); - if (IS_ERR(event_task_thread)) { - complete_and_exit(&create_done, 0); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Create event thread failed(0x%p)", - event_task_thread); - - return UNF_RETURN_ERROR; - } - wait_for_completion(&create_done); - return RETURN_OK; -} - -static void unf_cm_event_thread_exit(void) -{ - if (event_task_thread) - kthread_stop(event_task_thread); -} - -static void unf_init_card_mgr_list(void) -{ - /* So far, do not care */ - INIT_LIST_HEAD(&card_thread_mgr.card_list_head); - - spin_lock_init(&card_thread_mgr.global_card_list_lock); - - card_thread_mgr.card_num = 0; -} - -int unf_port_feature_pool_init(void) -{ - u32 index = 0; - u32 rport_feature_pool_size = 0; - struct unf_rport_feature_recard *rport_feature = NULL; - unsigned long flags = 0; - - rport_feature_pool_size = sizeof(struct unf_rport_feature_pool); - port_feature_pool = vmalloc(rport_feature_pool_size); - if (!port_feature_pool) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]cannot allocate rport feature pool"); - - return UNF_RETURN_ERROR; - } - memset(port_feature_pool, 0, rport_feature_pool_size); - spin_lock_init(&port_feature_pool->port_fea_pool_lock); - INIT_LIST_HEAD(&port_feature_pool->list_busy_head); - INIT_LIST_HEAD(&port_feature_pool->list_free_head); - - port_feature_pool->port_feature_pool_addr = - vmalloc((size_t)(RPORT_FEATURE_POOL_SIZE * sizeof(struct unf_rport_feature_recard))); - if (!port_feature_pool->port_feature_pool_addr) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]cannot allocate rport feature pool address"); - - vfree(port_feature_pool); - port_feature_pool = NULL; - - return UNF_RETURN_ERROR; - } - - memset(port_feature_pool->port_feature_pool_addr, 0, - RPORT_FEATURE_POOL_SIZE * sizeof(struct unf_rport_feature_recard)); - rport_feature = (struct unf_rport_feature_recard *) - port_feature_pool->port_feature_pool_addr; - - spin_lock_irqsave(&port_feature_pool->port_fea_pool_lock, flags); - for (index = 0; index < RPORT_FEATURE_POOL_SIZE; index++) { - list_add_tail(&rport_feature->entry_feature, &port_feature_pool->list_free_head); - rport_feature++; - } - spin_unlock_irqrestore(&port_feature_pool->port_fea_pool_lock, flags); - - return RETURN_OK; -} - -void unf_free_port_feature_pool(void) -{ - if (port_feature_pool->port_feature_pool_addr) { - vfree(port_feature_pool->port_feature_pool_addr); - port_feature_pool->port_feature_pool_addr = NULL; - } - - vfree(port_feature_pool); - port_feature_pool = NULL; -} - -int unf_common_init(void) -{ - int ret = RETURN_OK; - - unf_dgb_level = UNF_MAJOR; - log_print_level = UNF_KEVENT; - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_KEVENT, - "UNF Driver Version:%s.", SPFC_DRV_VERSION); - - atomic_set(&fc_mem_ref, 0); - ret = unf_port_feature_pool_init(); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Port Feature Pool init failed"); - return ret; - } - - ret = (int)unf_register_ini_transport(); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]INI interface init failed"); - goto REG_INITRANSPORT_FAIL; - } - - unf_port_mgmt_init(); - unf_init_card_mgr_list(); - ret = (int)unf_init_global_event_msg(); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Create global event center failed"); - goto CREAT_GLBEVENTMSG_FAIL; - } - - ret = (int)unf_creat_event_center(); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Create event center (thread) failed"); - goto CREAT_EVENTCENTER_FAIL; - } - - unf_wq = create_workqueue("unf_wq"); - if (!unf_wq) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Create work queue failed"); - goto CREAT_WORKQUEUE_FAIL; - } - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]Init common layer succeed"); - return ret; -CREAT_WORKQUEUE_FAIL: - unf_cm_event_thread_exit(); -CREAT_EVENTCENTER_FAIL: - unf_destroy_global_event_msg(); -CREAT_GLBEVENTMSG_FAIL: - unf_unregister_ini_transport(); -REG_INITRANSPORT_FAIL: - unf_free_port_feature_pool(); - return UNF_RETURN_ERROR; -} - -static void unf_destroy_dirty_port(void) -{ - u32 ditry_port_num = 0; - - unf_show_dirty_port(false, &ditry_port_num); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]Sys has %u dirty L_Port(s)", ditry_port_num); -} - -void unf_common_exit(void) -{ - unf_free_port_feature_pool(); - - unf_destroy_dirty_port(); - - flush_workqueue(unf_wq); - destroy_workqueue(unf_wq); - unf_wq = NULL; - - unf_cm_event_thread_exit(); - - unf_destroy_global_event_msg(); - - unf_deinit_cm_handle_ops(); - - unf_port_mgmt_deinit(); - - unf_unregister_ini_transport(); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_KEVENT, - "[info]SPFC module remove succeed, memory reference count is %d", - atomic_read(&fc_mem_ref)); -} diff --git a/drivers/scsi/spfc/common/unf_io.c b/drivers/scsi/spfc/common/unf_io.c deleted file mode 100644 index 5de69f8ddc6d..000000000000 --- a/drivers/scsi/spfc/common/unf_io.c +++ /dev/null @@ -1,1219 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#include "unf_io.h" -#include "unf_log.h" -#include "unf_portman.h" -#include "unf_service.h" -#include "unf_io_abnormal.h" - -u32 sector_size_flag; - -#define UNF_GET_FCP_CTL(pkg) ((((pkg)->status) >> UNF_SHIFT_8) & 0xFF) -#define UNF_GET_SCSI_STATUS(pkg) (((pkg)->status) & 0xFF) - -static u32 unf_io_success_handler(struct unf_xchg *xchg, - struct unf_frame_pkg *pkg, u32 up_status); -static u32 unf_ini_error_default_handler(struct unf_xchg *xchg, - struct unf_frame_pkg *pkg, - u32 up_status); -static u32 unf_io_underflow_handler(struct unf_xchg *xchg, - struct unf_frame_pkg *pkg, u32 up_status); -static u32 unf_ini_dif_error_handler(struct unf_xchg *xchg, - struct unf_frame_pkg *pkg, u32 up_status); - -struct unf_ini_error_handler_s { - u32 ini_error_code; - u32 (*unf_ini_error_handler)(struct unf_xchg *xchg, - struct unf_frame_pkg *pkg, u32 up_status); -}; - -struct unf_ini_error_handler_s ini_error_handler_table[] = { - {UNF_IO_SUCCESS, unf_io_success_handler}, - {UNF_IO_ABORTED, unf_ini_error_default_handler}, - {UNF_IO_FAILED, unf_ini_error_default_handler}, - {UNF_IO_ABORT_ABTS, unf_ini_error_default_handler}, - {UNF_IO_ABORT_LOGIN, unf_ini_error_default_handler}, - {UNF_IO_ABORT_REET, unf_ini_error_default_handler}, - {UNF_IO_ABORT_FAILED, unf_ini_error_default_handler}, - {UNF_IO_OUTOF_ORDER, unf_ini_error_default_handler}, - {UNF_IO_FTO, unf_ini_error_default_handler}, - {UNF_IO_LINK_FAILURE, unf_ini_error_default_handler}, - {UNF_IO_OVER_FLOW, unf_ini_error_default_handler}, - {UNF_IO_RSP_OVER, unf_ini_error_default_handler}, - {UNF_IO_LOST_FRAME, unf_ini_error_default_handler}, - {UNF_IO_UNDER_FLOW, unf_io_underflow_handler}, - {UNF_IO_HOST_PROG_ERROR, unf_ini_error_default_handler}, - {UNF_IO_SEST_PROG_ERROR, unf_ini_error_default_handler}, - {UNF_IO_INVALID_ENTRY, unf_ini_error_default_handler}, - {UNF_IO_ABORT_SEQ_NOT, unf_ini_error_default_handler}, - {UNF_IO_REJECT, unf_ini_error_default_handler}, - {UNF_IO_EDC_IN_ERROR, unf_ini_error_default_handler}, - {UNF_IO_EDC_OUT_ERROR, unf_ini_error_default_handler}, - {UNF_IO_UNINIT_KEK_ERR, unf_ini_error_default_handler}, - {UNF_IO_DEK_OUTOF_RANGE, unf_ini_error_default_handler}, - {UNF_IO_KEY_UNWRAP_ERR, unf_ini_error_default_handler}, - {UNF_IO_KEY_TAG_ERR, unf_ini_error_default_handler}, - {UNF_IO_KEY_ECC_ERR, unf_ini_error_default_handler}, - {UNF_IO_BLOCK_SIZE_ERROR, unf_ini_error_default_handler}, - {UNF_IO_ILLEGAL_CIPHER_MODE, unf_ini_error_default_handler}, - {UNF_IO_CLEAN_UP, unf_ini_error_default_handler}, - {UNF_IO_ABORTED_BY_TARGET, unf_ini_error_default_handler}, - {UNF_IO_TRANSPORT_ERROR, unf_ini_error_default_handler}, - {UNF_IO_LINK_FLASH, unf_ini_error_default_handler}, - {UNF_IO_TIMEOUT, unf_ini_error_default_handler}, - {UNF_IO_DMA_ERROR, unf_ini_error_default_handler}, - {UNF_IO_DIF_ERROR, unf_ini_dif_error_handler}, - {UNF_IO_INCOMPLETE, unf_ini_error_default_handler}, - {UNF_IO_DIF_REF_ERROR, unf_ini_dif_error_handler}, - {UNF_IO_DIF_GEN_ERROR, unf_ini_dif_error_handler}, - {UNF_IO_NO_XCHG, unf_ini_error_default_handler} - }; - -void unf_done_ini_xchg(struct unf_xchg *xchg) -{ - /* - * About I/O Done - * 1. normal case - * 2. Send ABTS & RCVD RSP - * 3. Send ABTS & timer timeout - */ - struct unf_scsi_cmnd scsi_cmd = {0}; - ulong flags = 0; - struct unf_scsi_cmd_info *scsi_cmnd_info = NULL; - struct unf_rport_scsi_id_image *scsi_image_table = NULL; - u32 scsi_id = 0; - - FC_CHECK_RETURN_VOID(xchg); - - if (unlikely(!xchg->scsi_cmnd_info.scsi_cmnd)) - return; - - /* 1. Free RX_ID for INI SIRT: Do not care */ - - /* - * 2. set & check exchange state - * * - * for Set UP_ABORT Tag: - * 1) L_Port destroy - * 2) LUN reset - * 3) Target/Session reset - * 4) SCSI send Abort(ABTS) - */ - spin_lock_irqsave(&xchg->xchg_state_lock, flags); - xchg->io_state |= INI_IO_STATE_DONE; - if (unlikely(xchg->io_state & - (INI_IO_STATE_UPABORT | INI_IO_STATE_UPSEND_ERR | INI_IO_STATE_TMF_ABORT))) { - /* - * a. UPABORT: scsi have send ABTS - * --->>> do not call SCSI_Done, return directly - * b. UPSEND_ERR: error happened duiring LLDD send SCSI_CMD - * --->>> do not call SCSI_Done, scsi need retry - */ - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_KEVENT, - "[event]Exchange(0x%p) Cmdsn:0x%lx upCmd:%p hottag(0x%x) with state(0x%x) has been aborted or send error", - xchg, (ulong)xchg->cmnd_sn, xchg->scsi_cmnd_info.scsi_cmnd, - xchg->hotpooltag, xchg->io_state); - - spin_unlock_irqrestore(&xchg->xchg_state_lock, flags); - return; - } - spin_unlock_irqrestore(&xchg->xchg_state_lock, flags); - - scsi_cmnd_info = &xchg->scsi_cmnd_info; - - /* - * 3. Set: - * scsi_cmnd; - * cmnd_done_func; - * cmnd up_level_done; - * sense_buff_addr; - * resid_length; - * cmnd_result; - * dif_info - * ** - * UNF_SCSI_CMND <<-- UNF_SCSI_CMND_INFO - */ - UNF_SET_HOST_CMND((&scsi_cmd), scsi_cmnd_info->scsi_cmnd); - UNF_SER_CMND_DONE_FUNC((&scsi_cmd), scsi_cmnd_info->done); - UNF_SET_UP_LEVEL_CMND_DONE_FUNC(&scsi_cmd, scsi_cmnd_info->uplevel_done); - scsi_cmd.drv_private = xchg->lport; - if (unlikely((UNF_SCSI_STATUS(xchg->scsi_cmnd_info.result)) & FCP_SNS_LEN_VALID_MASK)) { - unf_save_sense_data(scsi_cmd.upper_cmnd, - (char *)xchg->fcp_sfs_union.fcp_rsp_entry.fcp_rsp_iu, - (int)xchg->fcp_sfs_union.fcp_rsp_entry.fcp_sense_len); - } - UNF_SET_RESID((&scsi_cmd), (u32)xchg->resid_len); - UNF_SET_CMND_RESULT((&scsi_cmd), scsi_cmnd_info->result); - memcpy(&scsi_cmd.dif_info, &xchg->dif_info, sizeof(struct dif_info)); - - scsi_id = scsi_cmnd_info->scsi_id; - - UNF_DONE_SCSI_CMND((&scsi_cmd)); - - /* 4. Update IO result CNT */ - if (likely(xchg->lport)) { - scsi_image_table = &xchg->lport->rport_scsi_table; - UNF_IO_RESULT_CNT(scsi_image_table, scsi_id, - (scsi_cmnd_info->result >> UNF_SHIFT_16)); - } -} - -static inline u32 unf_ini_get_sgl_entry_buf(ini_get_sgl_entry_buf ini_get_sgl, - void *cmnd, void *driver_sgl, - void **upper_sgl, u32 *req_index, - u32 *index, char **buf, - u32 *buf_len) -{ - if (unlikely(!ini_get_sgl)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_MAJOR, - "Command(0x%p) Get sgl Entry func Null.", cmnd); - - return UNF_RETURN_ERROR; - } - - return ini_get_sgl(cmnd, driver_sgl, upper_sgl, req_index, index, buf, buf_len); -} - -u32 unf_ini_get_sgl_entry(void *pkg, char **buf, u32 *buf_len) -{ - struct unf_frame_pkg *unf_pkg = (struct unf_frame_pkg *)pkg; - struct unf_xchg *unf_xchg = NULL; - u32 ret = RETURN_OK; - - FC_CHECK_RETURN_VALUE(pkg, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(buf, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(buf_len, UNF_RETURN_ERROR); - - unf_xchg = (struct unf_xchg *)unf_pkg->xchg_contex; - FC_CHECK_RETURN_VALUE(unf_xchg, UNF_RETURN_ERROR); - - /* Get SGL Entry buffer for INI Mode */ - ret = unf_ini_get_sgl_entry_buf(unf_xchg->scsi_cmnd_info.unf_get_sgl_entry_buf, - unf_xchg->scsi_cmnd_info.scsi_cmnd, NULL, - &unf_xchg->req_sgl_info.sgl, - &unf_xchg->scsi_cmnd_info.port_id, - &((unf_xchg->req_sgl_info).entry_index), buf, buf_len); - - return ret; -} - -u32 unf_ini_get_dif_sgl_entry(void *pkg, char **buf, u32 *buf_len) -{ - struct unf_frame_pkg *unf_pkg = (struct unf_frame_pkg *)pkg; - struct unf_xchg *unf_xchg = NULL; - u32 ret = RETURN_OK; - - FC_CHECK_RETURN_VALUE(pkg, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(buf, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(buf_len, UNF_RETURN_ERROR); - - unf_xchg = (struct unf_xchg *)unf_pkg->xchg_contex; - FC_CHECK_RETURN_VALUE(unf_xchg, UNF_RETURN_ERROR); - - /* Get SGL Entry buffer for INI Mode */ - ret = unf_ini_get_sgl_entry_buf(unf_xchg->scsi_cmnd_info.unf_get_sgl_entry_buf, - unf_xchg->scsi_cmnd_info.scsi_cmnd, NULL, - &unf_xchg->dif_sgl_info.sgl, - &unf_xchg->scsi_cmnd_info.port_id, - &((unf_xchg->dif_sgl_info).entry_index), buf, buf_len); - return ret; -} - -u32 unf_get_up_level_cmnd_errcode(struct unf_ini_error_code *err_table, - u32 err_table_count, u32 drv_err_code) -{ - u32 loop = 0; - - /* fail return UNF_RETURN_ERROR,adjust by up level */ - if (unlikely(!err_table)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_MAJOR, - "Error Code Table is Null, Error Code(0x%x).", drv_err_code); - - return (u32)UNF_SCSI_HOST(DID_ERROR); - } - - for (loop = 0; loop < err_table_count; loop++) { - if (err_table[loop].drv_errcode == drv_err_code) - return err_table[loop].ap_errcode; - } - - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Unsupported Ap Error code by Error Code(0x%x).", drv_err_code); - - return (u32)UNF_SCSI_HOST(DID_ERROR); -} - -static u32 unf_ini_status_handle(struct unf_xchg *xchg, - struct unf_frame_pkg *pkg) -{ - u32 loop = 0; - u32 ret = UNF_RETURN_ERROR; - u32 up_status = 0; - - for (loop = 0; loop < sizeof(ini_error_handler_table) / - sizeof(struct unf_ini_error_handler_s); loop++) { - if (UNF_GET_LL_ERR(pkg) == ini_error_handler_table[loop].ini_error_code) { - up_status = - unf_get_up_level_cmnd_errcode(xchg->scsi_cmnd_info.err_code_table, - xchg->scsi_cmnd_info.err_code_table_cout, - UNF_GET_LL_ERR(pkg)); - - if (ini_error_handler_table[loop].unf_ini_error_handler) { - ret = ini_error_handler_table[loop] - .unf_ini_error_handler(xchg, pkg, up_status); - } else { - /* set exchange->result ---to--->>>scsi_result */ - ret = unf_ini_error_default_handler(xchg, pkg, up_status); - } - - return ret; - } - } - - up_status = unf_get_up_level_cmnd_errcode(xchg->scsi_cmnd_info.err_code_table, - xchg->scsi_cmnd_info.err_code_table_cout, - UNF_IO_SOFT_ERR); - - ret = unf_ini_error_default_handler(xchg, pkg, up_status); - - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[err]Can not find com status, SID(0x%x) exchange(0x%p) com_status(0x%x) DID(0x%x) hot_pool_tag(0x%x)", - xchg->sid, xchg, pkg->status, xchg->did, xchg->hotpooltag); - - return ret; -} - -static void unf_analysis_response_info(struct unf_xchg *xchg, - struct unf_frame_pkg *pkg, - u32 *up_status) -{ - u8 *resp_buf = NULL; - - /* LL_Driver use Little End, and copy RSP_INFO to COM_Driver */ - if (unlikely(pkg->unf_rsp_pload_bl.length > UNF_RESPONE_DATA_LEN)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Receive FCP response resp buffer len is invalid 0x%x", - pkg->unf_rsp_pload_bl.length); - return; - } - - resp_buf = (u8 *)pkg->unf_rsp_pload_bl.buffer_ptr; - if (resp_buf) { - /* If chip use Little End, then change it to Big End */ - if ((pkg->byte_orders & UNF_BIT_3) == 0) - unf_cpu_to_big_end(resp_buf, pkg->unf_rsp_pload_bl.length); - - /* Chip DAM data with Big End */ - if (resp_buf[ARRAY_INDEX_3] != UNF_FCP_TM_RSP_COMPLETE) { - *up_status = UNF_SCSI_HOST(DID_BUS_BUSY); - - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%p) DID bus busy, scsi_status(0x%x)", - xchg->lport, UNF_GET_SCSI_STATUS(pkg)); - } - } else { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Receive FCP response, resp buffer is NULL resp buffer len is 0x%x", - pkg->unf_rsp_pload_bl.length); - } -} - -static void unf_analysis_sense_info(struct unf_xchg *xchg, - struct unf_frame_pkg *pkg, u32 *up_status) -{ - u32 length = 0; - - /* 4 bytes Align */ - length = MIN(SCSI_SENSE_DATA_LEN, pkg->unf_sense_pload_bl.length); - - if (unlikely(pkg->unf_sense_pload_bl.length > SCSI_SENSE_DATA_LEN)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[info]Receive FCP response resp buffer len is 0x%x", - pkg->unf_sense_pload_bl.length); - } - /* - * If have sense info then copy directly - * else, the chip has been dma the data to sense buffer - */ - - if (length != 0 && pkg->unf_rsp_pload_bl.buffer_ptr) { - /* has been dma to exchange buffer */ - if (unlikely(pkg->unf_rsp_pload_bl.length > UNF_RESPONE_DATA_LEN)) { - *up_status = UNF_SCSI_HOST(DID_ERROR); - - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Receive FCP response resp buffer len is invalid 0x%x", - pkg->unf_rsp_pload_bl.length); - - return; - } - - xchg->fcp_sfs_union.fcp_rsp_entry.fcp_rsp_iu = (u8 *)kmalloc(length, GFP_ATOMIC); - if (!xchg->fcp_sfs_union.fcp_rsp_entry.fcp_rsp_iu) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[err]Alloc FCP sense buffer failed"); - return; - } - - memcpy(xchg->fcp_sfs_union.fcp_rsp_entry.fcp_rsp_iu, - ((u8 *)(pkg->unf_rsp_pload_bl.buffer_ptr)) + - pkg->unf_rsp_pload_bl.length, length); - - xchg->fcp_sfs_union.fcp_rsp_entry.fcp_sense_len = length; - } else { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Receive FCP response, sense buffer is NULL sense buffer len is 0x%x", - length); - } -} - -static u32 unf_io_success_handler(struct unf_xchg *xchg, - struct unf_frame_pkg *pkg, u32 up_status) -{ - u8 scsi_status = 0; - u8 control = 0; - u32 status = up_status; - - FC_CHECK_RETURN_VALUE(xchg, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(pkg, UNF_RETURN_ERROR); - - control = UNF_GET_FCP_CTL(pkg); - scsi_status = UNF_GET_SCSI_STATUS(pkg); - - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_INFO, - "[info]Port(0x%p), Exchange(0x%p) Completed, Control(0x%x), Scsi Status(0x%x)", - xchg->lport, xchg, control, scsi_status); - - if (control & FCP_SNS_LEN_VALID_MASK) { - /* has sense info */ - if (scsi_status == FCP_SCSI_STATUS_GOOD) - scsi_status = SCSI_CHECK_CONDITION; - - unf_analysis_sense_info(xchg, pkg, &status); - } else { - /* - * When the FCP_RSP_LEN_VALID bit is set to one, - * the content of the SCSI STATUS CODE field is not reliable - * and shall be ignored by the application client. - */ - if (control & FCP_RSP_LEN_VALID_MASK) - unf_analysis_response_info(xchg, pkg, &status); - } - - xchg->scsi_cmnd_info.result = status | UNF_SCSI_STATUS(scsi_status); - - return RETURN_OK; -} - -static u32 unf_ini_error_default_handler(struct unf_xchg *xchg, - struct unf_frame_pkg *pkg, - u32 up_status) -{ - /* set exchange->result ---to--->>> scsi_cmnd->result */ - FC_CHECK_RETURN_VALUE(xchg, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(pkg, UNF_RETURN_ERROR); - - FC_DRV_PRINT(UNF_LOG_ABNORMAL, UNF_WARN, - "[warn]SID(0x%x) exchange(0x%p) com_status(0x%x) up_status(0x%x) DID(0x%x) hot_pool_tag(0x%x) response_len(0x%x)", - xchg->sid, xchg, pkg->status, up_status, xchg->did, - xchg->hotpooltag, pkg->residus_len); - - xchg->scsi_cmnd_info.result = - up_status | UNF_SCSI_STATUS(UNF_GET_SCSI_STATUS(pkg)); - - return RETURN_OK; -} - -static u32 unf_ini_dif_error_handler(struct unf_xchg *xchg, - struct unf_frame_pkg *pkg, u32 up_status) -{ - u8 *sense_data = NULL; - u16 sense_code = 0; - - FC_CHECK_RETURN_VALUE(xchg, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(pkg, UNF_RETURN_ERROR); - - /* - * According to DIF scheme - * drive set check condition(0x2) when dif error occurs, - * and returns the values base on the upper-layer verification resule - * Check sequence: crc,Lba,App, - * if CRC error is found, the subsequent check is not performed - */ - xchg->scsi_cmnd_info.result = UNF_SCSI_STATUS(SCSI_CHECK_CONDITION); - - sense_code = (u16)pkg->status_sub_code; - sense_data = (u8 *)kmalloc(SCSI_SENSE_DATA_LEN, GFP_ATOMIC); - if (!sense_data) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[err]Alloc FCP sense buffer failed"); - - return UNF_RETURN_ERROR; - } - memset(sense_data, 0, SCSI_SENSE_DATA_LEN); - sense_data[ARRAY_INDEX_0] = SENSE_DATA_RESPONSE_CODE; /* response code:0x70 */ - sense_data[ARRAY_INDEX_2] = ILLEGAL_REQUEST; /* sense key:0x05; */ - sense_data[ARRAY_INDEX_7] = ADDITINONAL_SENSE_LEN; /* additional sense length:0x7 */ - sense_data[ARRAY_INDEX_12] = (u8)(sense_code >> UNF_SHIFT_8); - sense_data[ARRAY_INDEX_13] = (u8)sense_code; - - xchg->fcp_sfs_union.fcp_rsp_entry.fcp_rsp_iu = sense_data; - xchg->fcp_sfs_union.fcp_rsp_entry.fcp_sense_len = SCSI_SENSE_DATA_LEN; - - /* valid sense data length snscode[13] */ - return RETURN_OK; -} - -static u32 unf_io_underflow_handler(struct unf_xchg *xchg, - struct unf_frame_pkg *pkg, u32 up_status) -{ - /* under flow: residlen > 0 */ - FC_CHECK_RETURN_VALUE(xchg, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(pkg, UNF_RETURN_ERROR); - - if (xchg->fcp_cmnd.cdb[ARRAY_INDEX_0] != SCSIOPC_REPORT_LUN && - xchg->fcp_cmnd.cdb[ARRAY_INDEX_0] != SCSIOPC_INQUIRY) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_INFO, - "[info]IO under flow: SID(0x%x) exchange(0x%p) com status(0x%x) up_status(0x%x) DID(0x%x) hot_pool_tag(0x%x) response SID(0x%x)", - xchg->sid, xchg, pkg->status, up_status, - xchg->did, xchg->hotpooltag, pkg->residus_len); - } - - xchg->resid_len = (int)pkg->residus_len; - (void)unf_io_success_handler(xchg, pkg, up_status); - - return RETURN_OK; -} - -void unf_complete_cmnd(struct unf_scsi_cmnd *scsi_cmnd, u32 result_size) -{ - /* - * Exception during process Que_CMND - * 1. L_Port == NULL; - * 2. L_Port == removing; - * 3. R_Port == NULL; - * 4. Xchg == NULL. - */ - FC_CHECK_RETURN_VOID((UNF_GET_CMND_DONE_FUNC(scsi_cmnd))); - - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_INFO, - "[info]Command(0x%p), Result(0x%x).", scsi_cmnd, result_size); - - UNF_SET_CMND_RESULT(scsi_cmnd, result_size); - - UNF_DONE_SCSI_CMND(scsi_cmnd); -} - -static inline void unf_bind_xchg_scsi_cmd(struct unf_xchg *xchg, - struct unf_scsi_cmnd *scsi_cmnd) -{ - struct unf_scsi_cmd_info *scsi_cmnd_info = NULL; - - scsi_cmnd_info = &xchg->scsi_cmnd_info; - - /* UNF_SCSI_CMND_INFO <<-- UNF_SCSI_CMND */ - scsi_cmnd_info->err_code_table = UNF_GET_ERR_CODE_TABLE(scsi_cmnd); - scsi_cmnd_info->err_code_table_cout = UNF_GET_ERR_CODE_TABLE_COUNT(scsi_cmnd); - scsi_cmnd_info->done = UNF_GET_CMND_DONE_FUNC(scsi_cmnd); - scsi_cmnd_info->scsi_cmnd = UNF_GET_HOST_CMND(scsi_cmnd); - scsi_cmnd_info->sense_buf = (char *)UNF_GET_SENSE_BUF_ADDR(scsi_cmnd); - scsi_cmnd_info->uplevel_done = UNF_GET_UP_LEVEL_CMND_DONE(scsi_cmnd); - scsi_cmnd_info->unf_get_sgl_entry_buf = UNF_GET_SGL_ENTRY_BUF_FUNC(scsi_cmnd); - scsi_cmnd_info->sgl = UNF_GET_CMND_SGL(scsi_cmnd); - scsi_cmnd_info->time_out = scsi_cmnd->time_out; - scsi_cmnd_info->entry_cnt = scsi_cmnd->entry_count; - scsi_cmnd_info->port_id = (u32)scsi_cmnd->port_id; - scsi_cmnd_info->scsi_id = UNF_GET_SCSI_ID_BY_CMND(scsi_cmnd); -} - -u32 unf_ini_scsi_completed(void *lport, struct unf_frame_pkg *pkg) -{ - struct unf_lport *unf_lport = NULL; - struct unf_xchg *unf_xchg = NULL; - struct unf_fcp_cmnd *fcp_cmnd = NULL; - u32 control = 0; - u16 xchg_tag = 0x0ffff; - u32 ret = UNF_RETURN_ERROR; - ulong xchg_flag = 0; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(pkg, UNF_RETURN_ERROR); - - unf_lport = (struct unf_lport *)lport; - xchg_tag = (u16)pkg->private_data[PKG_PRIVATE_XCHG_HOT_POOL_INDEX]; - - /* 1. Find Exchange Context */ - unf_xchg = unf_cm_lookup_xchg_by_tag(lport, (u16)xchg_tag); - if (unlikely(!unf_xchg)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x_0x%x) can not find exchange by tag(0x%x)", - unf_lport->port_id, unf_lport->nport_id, xchg_tag); - - /* NOTE: return directly */ - return UNF_RETURN_ERROR; - } - - /* 2. Consistency check */ - UNF_CHECK_ALLOCTIME_VALID(unf_lport, xchg_tag, unf_xchg, - pkg->private_data[PKG_PRIVATE_XCHG_ALLOC_TIME], - unf_xchg->private_data[PKG_PRIVATE_XCHG_ALLOC_TIME]); - - /* 3. Increase ref_cnt for exchange protecting */ - ret = unf_xchg_ref_inc(unf_xchg, INI_RESPONSE_DONE); /* hold */ - FC_CHECK_RETURN_VALUE((ret == RETURN_OK), UNF_RETURN_ERROR); - - fcp_cmnd = &unf_xchg->fcp_cmnd; - control = fcp_cmnd->control; - control = UNF_GET_TASK_MGMT_FLAGS(control); - - /* 4. Cancel timer if necessary */ - if (unf_xchg->scsi_cmnd_info.time_out != 0) - unf_lport->xchg_mgr_temp.unf_xchg_cancel_timer(unf_xchg); - - /* 5. process scsi TMF if necessary */ - if (control != 0) { - unf_process_scsi_mgmt_result(pkg, unf_xchg); - unf_xchg_ref_dec(unf_xchg, INI_RESPONSE_DONE); /* cancel hold */ - - /* NOTE: return directly */ - return RETURN_OK; - } - - /* 6. Xchg Abort state check */ - spin_lock_irqsave(&unf_xchg->xchg_state_lock, xchg_flag); - unf_xchg->oxid = UNF_GET_OXID(pkg); - unf_xchg->rxid = UNF_GET_RXID(pkg); - if (INI_IO_STATE_UPABORT & unf_xchg->io_state) { - spin_unlock_irqrestore(&unf_xchg->xchg_state_lock, xchg_flag); - - FC_DRV_PRINT(UNF_LOG_NORMAL, UNF_WARN, - "[warn]Port(0x%x) find exchange(%p) state(0x%x) has been aborted", - unf_lport->port_id, unf_xchg, unf_xchg->io_state); - - /* NOTE: release exchange during SCSI ABORT(ABTS) */ - unf_xchg_ref_dec(unf_xchg, INI_RESPONSE_DONE); /* cancel hold */ - - return ret; - } - spin_unlock_irqrestore(&unf_xchg->xchg_state_lock, xchg_flag); - - /* - * 7. INI SCSI CMND Status process - * set exchange->result ---to--->>> scsi_result - */ - ret = unf_ini_status_handle(unf_xchg, pkg); - - /* 8. release exchangenecessary */ - unf_cm_free_xchg(unf_lport, unf_xchg); - - /* 9. dec exch ref_cnt */ - unf_xchg_ref_dec(unf_xchg, INI_RESPONSE_DONE); /* cancel hold: release resource now */ - - return ret; -} - -u32 unf_hardware_start_io(struct unf_lport *lport, struct unf_frame_pkg *pkg) -{ - if (unlikely(!lport->low_level_func.service_op.unf_cmnd_send)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[err]Port(0x%x) low level send scsi function is NULL", - lport->port_id); - - return UNF_RETURN_ERROR; - } - - return lport->low_level_func.service_op.unf_cmnd_send(lport->fc_port, pkg); -} - -struct unf_rport *unf_find_rport_by_scsi_id(struct unf_lport *lport, - struct unf_ini_error_code *err_code_table, - u32 err_code_table_cout, u32 scsi_id, u32 *scsi_result) -{ - struct unf_rport_scsi_id_image *scsi_image_table = NULL; - struct unf_wwpn_rport_info *wwpn_rport_info = NULL; - struct unf_rport *unf_rport = NULL; - ulong flags = 0; - - /* scsi_table -> session_table ->image_table */ - scsi_image_table = &lport->rport_scsi_table; - - /* 1. Scsi_Id validity check */ - if (unlikely(scsi_id >= scsi_image_table->max_scsi_id)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[err]Input scsi_id(0x%x) bigger than max_scsi_id(0x%x).", - scsi_id, scsi_image_table->max_scsi_id); - - *scsi_result = unf_get_up_level_cmnd_errcode(err_code_table, err_code_table_cout, - UNF_IO_SOFT_ERR); /* did_soft_error */ - - return NULL; - } - - /* 2. GetR_Port_Info/R_Port: use Scsi_Id find from L_Port's - * Rport_Scsi_Table (image table) - */ - spin_lock_irqsave(&scsi_image_table->scsi_image_table_lock, flags); - wwpn_rport_info = &scsi_image_table->wwn_rport_info_table[scsi_id]; - unf_rport = wwpn_rport_info->rport; - spin_unlock_irqrestore(&scsi_image_table->scsi_image_table_lock, flags); - - if (unlikely(!unf_rport)) { - *scsi_result = unf_get_up_level_cmnd_errcode(err_code_table, - err_code_table_cout, - UNF_IO_PORT_LOGOUT); - - return NULL; - } - - return unf_rport; -} - -static u32 unf_build_xchg_fcpcmnd(struct unf_fcp_cmnd *fcp_cmnd, - struct unf_scsi_cmnd *scsi_cmnd) -{ - memcpy(fcp_cmnd->cdb, &UNF_GET_FCP_CMND(scsi_cmnd), scsi_cmnd->cmnd_len); - - if ((fcp_cmnd->control == UNF_FCP_WR_DATA && - (IS_READ_COMMAND(fcp_cmnd->cdb[ARRAY_INDEX_0]))) || - (fcp_cmnd->control == UNF_FCP_RD_DATA && - (IS_WRITE_COMMAND(fcp_cmnd->cdb[ARRAY_INDEX_0])))) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_MINOR, - "Scsi command direction inconsistent, CDB[ARRAY_INDEX_0](0x%x), direction(0x%x).", - fcp_cmnd->cdb[ARRAY_INDEX_0], fcp_cmnd->control); - - return UNF_RETURN_ERROR; - } - - memcpy(fcp_cmnd->lun, scsi_cmnd->lun_id, sizeof(fcp_cmnd->lun)); - - unf_big_end_to_cpu((void *)fcp_cmnd->cdb, sizeof(fcp_cmnd->cdb)); - fcp_cmnd->data_length = UNF_GET_DATA_LEN(scsi_cmnd); - - return RETURN_OK; -} - -static void unf_adjust_xchg_len(struct unf_xchg *xchg, u32 scsi_cmnd) -{ - switch (scsi_cmnd) { - case SCSIOPC_REQUEST_SENSE: /* requires different buffer */ - xchg->data_len = UNF_SCSI_SENSE_BUFFERSIZE; - - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_MINOR, "Request Sense new."); - break; - - case SCSIOPC_TEST_UNIT_READY: - case SCSIOPC_RESERVE: - case SCSIOPC_RELEASE: - case SCSIOPC_START_STOP_UNIT: - xchg->data_len = 0; - break; - - default: - break; - } -} - -static void unf_copy_dif_control(struct unf_dif_control_info *dif_control, - struct unf_scsi_cmnd *scsi_cmnd) -{ - dif_control->fcp_dl = scsi_cmnd->dif_control.fcp_dl; - dif_control->protect_opcode = scsi_cmnd->dif_control.protect_opcode; - dif_control->start_lba = scsi_cmnd->dif_control.start_lba; - dif_control->app_tag = scsi_cmnd->dif_control.app_tag; - - dif_control->flags = scsi_cmnd->dif_control.flags; - dif_control->dif_sge_count = scsi_cmnd->dif_control.dif_sge_count; - dif_control->dif_sgl = scsi_cmnd->dif_control.dif_sgl; -} - -static void unf_adjust_dif_pci_transfer_len(struct unf_xchg *xchg, u32 direction) -{ - struct unf_dif_control_info *dif_control = NULL; - u32 sector_size = 0; - - dif_control = &xchg->dif_control; - - if (dif_control->protect_opcode == UNF_DIF_ACTION_NONE) - return; - if ((dif_control->flags & UNF_DIF_SECTSIZE_4KB) == 0) - sector_size = SECTOR_SIZE_512; - else - sector_size = SECTOR_SIZE_4096; - switch (dif_control->protect_opcode & UNF_DIF_ACTION_MASK) { - case UNF_DIF_ACTION_INSERT: - if (direction == DMA_TO_DEVICE) { - /* write IO,insert,Indicates that data with DIF is - * transmitted over the link. - */ - dif_control->fcp_dl = xchg->data_len + - UNF_CAL_BLOCK_CNT(xchg->data_len, sector_size) * UNF_DIF_AREA_SIZE; - } else { - /* read IO,insert,Indicates that the internal DIf is - * carried, and the link does not carry the DIf. - */ - dif_control->fcp_dl = xchg->data_len; - } - break; - - case UNF_DIF_ACTION_VERIFY_AND_DELETE: - if (direction == DMA_TO_DEVICE) { - /* write IO,Delete,Indicates that the internal DIf is - * carried, and the link does not carry the DIf. - */ - dif_control->fcp_dl = xchg->data_len; - } else { - /* read IO,Delete,Indicates that data with DIF is - * carried on the link and does not contain DIF on - * internal. - */ - dif_control->fcp_dl = xchg->data_len + - UNF_CAL_BLOCK_CNT(xchg->data_len, sector_size) * UNF_DIF_AREA_SIZE; - } - break; - - case UNF_DIF_ACTION_VERIFY_AND_FORWARD: - dif_control->fcp_dl = xchg->data_len + - UNF_CAL_BLOCK_CNT(xchg->data_len, sector_size) * UNF_DIF_AREA_SIZE; - break; - - default: - dif_control->fcp_dl = xchg->data_len; - break; - } - - xchg->fcp_cmnd.data_length = dif_control->fcp_dl; -} - -static void unf_get_dma_direction(struct unf_fcp_cmnd *fcp_cmnd, - struct unf_scsi_cmnd *scsi_cmnd) -{ - if (UNF_GET_DATA_DIRECTION(scsi_cmnd) == DMA_TO_DEVICE) { - fcp_cmnd->control = UNF_FCP_WR_DATA; - } else if (UNF_GET_DATA_DIRECTION(scsi_cmnd) == DMA_FROM_DEVICE) { - fcp_cmnd->control = UNF_FCP_RD_DATA; - } else { - /* DMA Direction None */ - fcp_cmnd->control = 0; - } -} - -static int unf_save_scsi_cmnd_to_xchg(struct unf_lport *lport, - struct unf_rport *rport, - struct unf_xchg *xchg, - struct unf_scsi_cmnd *scsi_cmnd) -{ - struct unf_lport *unf_lport = lport; - struct unf_rport *unf_rport = rport; - struct unf_xchg *unf_xchg = xchg; - u32 result_size = 0; - - scsi_cmnd->driver_scribble = (void *)unf_xchg->start_jif; - unf_xchg->rport = unf_rport; - unf_xchg->rport_bind_jifs = unf_rport->rport_alloc_jifs; - - /* Build Xchg SCSI_CMND info */ - unf_bind_xchg_scsi_cmd(unf_xchg, scsi_cmnd); - - unf_xchg->data_len = UNF_GET_DATA_LEN(scsi_cmnd); - unf_xchg->data_direction = UNF_GET_DATA_DIRECTION(scsi_cmnd); - unf_xchg->sid = unf_lport->nport_id; - unf_xchg->did = unf_rport->nport_id; - unf_xchg->private_data[PKG_PRIVATE_XCHG_RPORT_INDEX] = unf_rport->rport_index; - unf_xchg->world_id = scsi_cmnd->world_id; - unf_xchg->cmnd_sn = scsi_cmnd->cmnd_sn; - unf_xchg->pinitiator = scsi_cmnd->pinitiator; - unf_xchg->scsi_id = scsi_cmnd->scsi_id; - if (scsi_cmnd->qos_level == UNF_QOS_LEVEL_DEFAULT) - unf_xchg->qos_level = unf_rport->qos_level; - else - unf_xchg->qos_level = scsi_cmnd->qos_level; - - unf_get_dma_direction(&unf_xchg->fcp_cmnd, scsi_cmnd); - result_size = unf_build_xchg_fcpcmnd(&unf_xchg->fcp_cmnd, scsi_cmnd); - if (unlikely(result_size != RETURN_OK)) - return UNF_RETURN_ERROR; - - unf_adjust_xchg_len(unf_xchg, UNF_GET_FCP_CMND(scsi_cmnd)); - - unf_adjust_xchg_len(unf_xchg, UNF_GET_FCP_CMND(scsi_cmnd)); - - /* Dif (control) info */ - unf_copy_dif_control(&unf_xchg->dif_control, scsi_cmnd); - memcpy(&unf_xchg->dif_info, &scsi_cmnd->dif_info, sizeof(struct dif_info)); - unf_adjust_dif_pci_transfer_len(unf_xchg, UNF_GET_DATA_DIRECTION(scsi_cmnd)); - - /* single sgl info */ - if (unf_xchg->data_direction != DMA_NONE && UNF_GET_CMND_SGL(scsi_cmnd)) { - unf_xchg->req_sgl_info.sgl = UNF_GET_CMND_SGL(scsi_cmnd); - unf_xchg->req_sgl_info.sgl_start = unf_xchg->req_sgl_info.sgl; - /* Save the sgl header for easy - * location and printing. - */ - unf_xchg->req_sgl_info.req_index = 0; - unf_xchg->req_sgl_info.entry_index = 0; - } - - if (scsi_cmnd->dif_control.dif_sgl) { - unf_xchg->dif_sgl_info.sgl = UNF_INI_GET_DIF_SGL(scsi_cmnd); - unf_xchg->dif_sgl_info.entry_index = 0; - unf_xchg->dif_sgl_info.req_index = 0; - unf_xchg->dif_sgl_info.sgl_start = unf_xchg->dif_sgl_info.sgl; - } - - return RETURN_OK; -} - -static int unf_send_fcpcmnd(struct unf_lport *lport, struct unf_rport *rport, - struct unf_xchg *xchg) -{ -#define UNF_MAX_PENDING_IO_CNT 3 - struct unf_scsi_cmd_info *scsi_cmnd_info = NULL; - struct unf_lport *unf_lport = lport; - struct unf_rport *unf_rport = rport; - struct unf_xchg *unf_xchg = xchg; - struct unf_frame_pkg pkg = {0}; - u32 result_size = 0; - ulong flags = 0; - - memcpy(&pkg.dif_control, &unf_xchg->dif_control, sizeof(struct unf_dif_control_info)); - pkg.dif_control.fcp_dl = unf_xchg->dif_control.fcp_dl; - pkg.transfer_len = unf_xchg->data_len; /* Pcie data transfer length */ - pkg.xchg_contex = unf_xchg; - pkg.qos_level = unf_xchg->qos_level; - scsi_cmnd_info = &xchg->scsi_cmnd_info; - pkg.entry_count = unf_xchg->scsi_cmnd_info.entry_cnt; - if (unf_xchg->data_direction == DMA_NONE || !scsi_cmnd_info->sgl) - pkg.entry_count = 0; - - pkg.private_data[PKG_PRIVATE_XCHG_ALLOC_TIME] = - unf_xchg->private_data[PKG_PRIVATE_XCHG_ALLOC_TIME]; - pkg.private_data[PKG_PRIVATE_XCHG_VP_INDEX] = unf_lport->vp_index; - pkg.private_data[PKG_PRIVATE_XCHG_RPORT_INDEX] = unf_rport->rport_index; - pkg.private_data[PKG_PRIVATE_XCHG_HOT_POOL_INDEX] = unf_xchg->hotpooltag; - - unf_select_sq(unf_xchg, &pkg); - pkg.fcp_cmnd = &unf_xchg->fcp_cmnd; - pkg.frame_head.csctl_sid = unf_lport->nport_id; - pkg.frame_head.rctl_did = unf_rport->nport_id; - pkg.upper_cmd = unf_xchg->scsi_cmnd_info.scsi_cmnd; - - /* exch->fcp_rsp_id --->>> pkg->buffer_ptr */ - pkg.frame_head.oxid_rxid = ((u32)unf_xchg->oxid << (u32)UNF_SHIFT_16 | unf_xchg->rxid); - - FC_DRV_PRINT(UNF_LOG_EQUIP_ATT, UNF_INFO, - "[info]LPort (0x%p), Nport ID(0x%x) RPort ID(0x%x) direction(0x%x) magic number(0x%x) IO to entry count(0x%x) hottag(0x%x)", - unf_lport, unf_lport->nport_id, unf_rport->nport_id, - xchg->data_direction, pkg.private_data[PKG_PRIVATE_XCHG_ALLOC_TIME], - pkg.entry_count, unf_xchg->hotpooltag); - - atomic_inc(&unf_rport->pending_io_cnt); - if (unf_rport->tape_support_needed && - (atomic_read(&unf_rport->pending_io_cnt) <= UNF_MAX_PENDING_IO_CNT)) { - spin_lock_irqsave(&xchg->xchg_state_lock, flags); - unf_xchg->io_state |= INI_IO_STATE_REC_TIMEOUT_WAIT; - spin_unlock_irqrestore(&xchg->xchg_state_lock, flags); - scsi_cmnd_info->abort_time_out = scsi_cmnd_info->time_out; - scsi_cmnd_info->time_out = UNF_REC_TOV; - } - /* 3. add INI I/O timer if necessary */ - if (scsi_cmnd_info->time_out != 0) { - /* I/O inner timer, do not used at this time */ - unf_lport->xchg_mgr_temp.unf_xchg_add_timer(unf_xchg, - scsi_cmnd_info->time_out, UNF_TIMER_TYPE_REQ_IO); - } - - /* 4. R_Port state check */ - if (unlikely(unf_rport->lport_ini_state != UNF_PORT_STATE_LINKUP || - unf_rport->rp_state > UNF_RPORT_ST_READY)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[info]Port(0x%x) RPort(0x%p) NPortId(0x%x) inistate(0x%x): RPort state(0x%x) pUpperCmd(0x%p) is not ready", - unf_lport->port_id, unf_rport, unf_rport->nport_id, - unf_rport->lport_ini_state, unf_rport->rp_state, pkg.upper_cmd); - - result_size = unf_get_up_level_cmnd_errcode(scsi_cmnd_info->err_code_table, - scsi_cmnd_info->err_code_table_cout, - UNF_IO_INCOMPLETE); - scsi_cmnd_info->result = result_size; - - if (scsi_cmnd_info->time_out != 0) - unf_lport->xchg_mgr_temp.unf_xchg_cancel_timer(unf_xchg); - - unf_cm_free_xchg(unf_lport, unf_xchg); - - /* DID_IMM_RETRY */ - return RETURN_OK; - } else if (unf_rport->rp_state < UNF_RPORT_ST_READY) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[info]Port(0x%x) RPort(0x%p) NPortId(0x%x) inistate(0x%x): RPort state(0x%x) pUpperCmd(0x%p) is not ready", - unf_lport->port_id, unf_rport, unf_rport->nport_id, - unf_rport->lport_ini_state, unf_rport->rp_state, pkg.upper_cmd); - - spin_lock_irqsave(&xchg->xchg_state_lock, flags); - unf_xchg->io_state |= INI_IO_STATE_UPSEND_ERR; /* need retry */ - spin_unlock_irqrestore(&xchg->xchg_state_lock, flags); - - if (unlikely(scsi_cmnd_info->time_out != 0)) - unf_lport->xchg_mgr_temp.unf_xchg_cancel_timer((void *)unf_xchg); - - /* Host busy & need scsi retry */ - return UNF_RETURN_ERROR; - } - - /* 5. send scsi_cmnd to FC_LL Driver */ - if (unf_hardware_start_io(unf_lport, &pkg) != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port (0x%x) pUpperCmd(0x%p) Hardware Send IO failed.", - unf_lport->port_id, pkg.upper_cmd); - - unf_release_esgls(unf_xchg); - - result_size = unf_get_up_level_cmnd_errcode(scsi_cmnd_info->err_code_table, - scsi_cmnd_info->err_code_table_cout, - UNF_IO_INCOMPLETE); - scsi_cmnd_info->result = result_size; - - if (scsi_cmnd_info->time_out != 0) - unf_lport->xchg_mgr_temp.unf_xchg_cancel_timer(unf_xchg); - - unf_cm_free_xchg(unf_lport, unf_xchg); - - /* SCSI_DONE */ - return RETURN_OK; - } - - return RETURN_OK; -} - -int unf_prefer_to_send_scsi_cmnd(struct unf_xchg *xchg) -{ - /* - * About INI_IO_STATE_DRABORT: - * 1. Set ABORT tag: Clean L_Port/V_Port Link Down I/O - * with: INI_busy_list, delay_list, delay_transfer_list, wait_list - * * - * 2. Set ABORT tag: for target session: - * with: INI_busy_list, delay_list, delay_transfer_list, wait_list - * a. R_Port remove - * b. Send PLOGI_ACC callback - * c. RCVD PLOGI - * d. RCVD LOGO - * * - * 3. if set ABORT: prevent send scsi_cmnd to target - */ - struct unf_lport *unf_lport = NULL; - struct unf_rport *unf_rport = NULL; - int ret = RETURN_OK; - ulong flags = 0; - - unf_lport = xchg->lport; - - unf_rport = xchg->rport; - if (unlikely(!unf_lport || !unf_rport)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[err]Port(0x%p) or RPort(0x%p) is NULL", unf_lport, unf_rport); - - /* if happened (never happen): need retry */ - return UNF_RETURN_ERROR; - } - - /* 1. inc ref_cnt to protect exchange */ - ret = (int)unf_xchg_ref_inc(xchg, INI_SEND_CMND); - if (unlikely(ret != RETURN_OK)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x) exhg(%p) exception ref(%d) ", unf_lport->port_id, - xchg, atomic_read(&xchg->ref_cnt)); - /* exchange exception, need retry */ - spin_lock_irqsave(&xchg->xchg_state_lock, flags); - xchg->io_state |= INI_IO_STATE_UPSEND_ERR; - spin_unlock_irqrestore(&xchg->xchg_state_lock, flags); - - /* INI_IO_STATE_UPSEND_ERR: Host busy --->>> need retry */ - return UNF_RETURN_ERROR; - } - - /* 2. Xchg Abort state check: Free EXCH if necessary */ - spin_lock_irqsave(&xchg->xchg_state_lock, flags); - if (unlikely((xchg->io_state & INI_IO_STATE_UPABORT) || - (xchg->io_state & INI_IO_STATE_DRABORT))) { - /* Prevent to send: UP_ABORT/DRV_ABORT */ - spin_unlock_irqrestore(&xchg->xchg_state_lock, flags); - xchg->scsi_cmnd_info.result = UNF_SCSI_HOST(DID_IMM_RETRY); - ret = RETURN_OK; - - unf_xchg_ref_dec(xchg, INI_SEND_CMND); - unf_cm_free_xchg(unf_lport, xchg); - - /* - * Release exchange & return directly: - * 1. FC LLDD rcvd ABTS before scsi_cmnd: do nothing - * 2. INI_IO_STATE_UPABORT/INI_IO_STATE_DRABORT: discard this - * cmnd directly - */ - return ret; - } - spin_unlock_irqrestore(&xchg->xchg_state_lock, flags); - - /* 3. Send FCP_CMND to FC_LL Driver */ - ret = unf_send_fcpcmnd(unf_lport, unf_rport, xchg); - if (unlikely(ret != RETURN_OK)) { - /* exchange exception, need retry */ - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x) send exhg(%p) hottag(0x%x) to Rport(%p) NPortID(0x%x) state(0x%x) scsi_id(0x%x) failed", - unf_lport->port_id, xchg, xchg->hotpooltag, unf_rport, - unf_rport->nport_id, unf_rport->rp_state, unf_rport->scsi_id); - - spin_lock_irqsave(&xchg->xchg_state_lock, flags); - - xchg->io_state |= INI_IO_STATE_UPSEND_ERR; - /* need retry */ - spin_unlock_irqrestore(&xchg->xchg_state_lock, flags); - /* INI_IO_STATE_UPSEND_ERR: Host busy --->>> need retry */ - unf_cm_free_xchg(unf_lport, xchg); - } - - /* 4. dec ref_cnt */ - unf_xchg_ref_dec(xchg, INI_SEND_CMND); - - return ret; -} - -struct unf_lport *unf_find_lport_by_scsi_cmd(struct unf_scsi_cmnd *scsi_cmnd) -{ - struct unf_lport *unf_lport = NULL; - - /* cmd -->> L_Port */ - unf_lport = (struct unf_lport *)UNF_GET_HOST_PORT_BY_CMND(scsi_cmnd); - if (unlikely(!unf_lport)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Find Port by scsi_cmnd(0x%p) failed", scsi_cmnd); - - /* cmnd -->> scsi_host_id -->> L_Port */ - unf_lport = unf_find_lport_by_scsi_hostid(UNF_GET_SCSI_HOST_ID_BY_CMND(scsi_cmnd)); - } - - return unf_lport; -} - -int unf_cm_queue_command(struct unf_scsi_cmnd *scsi_cmnd) -{ - /* SCSI Command --->>> FC FCP Command */ - struct unf_lport *unf_lport = NULL; - struct unf_xchg *unf_xchg = NULL; - struct unf_rport *unf_rport = NULL; - struct unf_rport_scsi_id_image *scsi_image_table = NULL; - u32 cmnd_result = 0; - int ret = RETURN_OK; - ulong flags = 0; - u32 scsi_id = 0; - u32 exhg_mgr_type = UNF_XCHG_MGR_TYPE_RANDOM; - - /* 1. Get L_Port */ - unf_lport = unf_find_lport_by_scsi_cmd(scsi_cmnd); - - /* - * corresponds to the insertion or removal scenario or the remove card - * scenario. This method is used to search for LPort information based - * on SCSI_HOST_ID. The Slave alloc is not invoked when LUNs are not - * scanned. Therefore, the Lport cannot be obtained. You need to obtain - * the Lport from the Lport linked list. - * * - * FC After Link Up, the first SCSI command is inquiry. - * Before inquiry, SCSI delivers slave_alloc. - */ - if (!unf_lport) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[err]Find Port by scsi cmd(0x%p) failed", scsi_cmnd); - - /* find from ini_error_code_table1 */ - cmnd_result = unf_get_up_level_cmnd_errcode(scsi_cmnd->err_code_table, - scsi_cmnd->err_code_table_cout, - UNF_IO_NO_LPORT); - - /* DID_NOT_CONNECT & SCSI_DONE & RETURN_OK(0) & I/O error */ - unf_complete_cmnd(scsi_cmnd, cmnd_result); - return RETURN_OK; - } - - /* Get Local SCSI_Image_table & SCSI_ID */ - scsi_image_table = &unf_lport->rport_scsi_table; - scsi_id = scsi_cmnd->scsi_id; - - /* 2. L_Port State check */ - if (unlikely(unf_lport->port_removing || unf_lport->pcie_link_down)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x) is removing(%d) or pcielinkdown(%d) and return with scsi_id(0x%x)", - unf_lport->port_id, unf_lport->port_removing, - unf_lport->pcie_link_down, UNF_GET_SCSI_ID_BY_CMND(scsi_cmnd)); - - cmnd_result = unf_get_up_level_cmnd_errcode(scsi_cmnd->err_code_table, - scsi_cmnd->err_code_table_cout, - UNF_IO_NO_LPORT); - - UNF_IO_RESULT_CNT(scsi_image_table, scsi_id, (cmnd_result >> UNF_SHIFT_16)); - - /* DID_NOT_CONNECT & SCSI_DONE & RETURN_OK(0) & I/O error */ - unf_complete_cmnd(scsi_cmnd, cmnd_result); - return RETURN_OK; - } - - /* 3. Get R_Port */ - unf_rport = unf_find_rport_by_scsi_id(unf_lport, scsi_cmnd->err_code_table, - scsi_cmnd->err_code_table_cout, - UNF_GET_SCSI_ID_BY_CMND(scsi_cmnd), &cmnd_result); - if (unlikely(!unf_rport)) { - /* never happen: do not care */ - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) find RPort by scsi_id(0x%x) failed", - unf_lport->port_id, UNF_GET_SCSI_ID_BY_CMND(scsi_cmnd)); - - UNF_IO_RESULT_CNT(scsi_image_table, scsi_id, (cmnd_result >> UNF_SHIFT_16)); - - /* DID_NOT_CONNECT/DID_SOFT_ERROR & SCSI_DONE & RETURN_OK(0) & - * I/O error - */ - unf_complete_cmnd(scsi_cmnd, cmnd_result); - return RETURN_OK; - } - - /* 4. Can't get exchange & return host busy, retry by uplevel */ - unf_xchg = (struct unf_xchg *)unf_cm_get_free_xchg(unf_lport, - exhg_mgr_type << UNF_SHIFT_16 | UNF_XCHG_TYPE_INI); - if (unlikely(!unf_xchg)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[err]Port(0x%x) get free exchange for INI IO(0x%x) failed", - unf_lport->port_id, UNF_GET_SCSI_ID_BY_CMND(scsi_cmnd)); - - /* NOTE: need scsi retry */ - return UNF_RETURN_ERROR; - } - - unf_xchg->scsi_cmnd_info.result = UNF_SCSI_HOST(DID_ERROR); - - /* 5. Save the SCSI CMND information in advance. */ - ret = unf_save_scsi_cmnd_to_xchg(unf_lport, unf_rport, unf_xchg, scsi_cmnd); - if (unlikely(ret != RETURN_OK)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[err]Port(0x%x) save scsi_cmnd info(0x%x) to exchange failed", - unf_lport->port_id, UNF_GET_SCSI_ID_BY_CMND(scsi_cmnd)); - - spin_lock_irqsave(&unf_xchg->xchg_state_lock, flags); - unf_xchg->io_state |= INI_IO_STATE_UPSEND_ERR; - spin_unlock_irqrestore(&unf_xchg->xchg_state_lock, flags); - - /* INI_IO_STATE_UPSEND_ERR: Don't Do SCSI_DONE, need retry I/O */ - unf_cm_free_xchg(unf_lport, unf_xchg); - - /* NOTE: need scsi retry */ - return UNF_RETURN_ERROR; - } - - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_INFO, - "[info]Get exchange(0x%p) hottag(0x%x) for Pcmd:%p,Cmdsn:0x%lx,WorldId:%d", - unf_xchg, unf_xchg->hotpooltag, scsi_cmnd->upper_cmnd, - (ulong)scsi_cmnd->cmnd_sn, scsi_cmnd->world_id); - /* 6. Send SCSI CMND */ - ret = unf_prefer_to_send_scsi_cmnd(unf_xchg); - - return ret; -} diff --git a/drivers/scsi/spfc/common/unf_io.h b/drivers/scsi/spfc/common/unf_io.h deleted file mode 100644 index d8e50eb8035e..000000000000 --- a/drivers/scsi/spfc/common/unf_io.h +++ /dev/null @@ -1,96 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef UNF_IO_H -#define UNF_IO_H - -#include "unf_type.h" -#include "unf_scsi_common.h" -#include "unf_exchg.h" -#include "unf_rport.h" - -#define UNF_MAX_TARGET_NUMBER 2048 -#define UNF_DEFAULT_MAX_LUN 0xFFFF -#define UNF_MAX_DMA_SEGS 0x400 -#define UNF_MAX_SCSI_CMND_LEN 16 -#define UNF_MAX_BUS_CHANNEL 0 -#define UNF_DMA_BOUNDARY 0xffffffffffffffff -#define UNF_MAX_CMND_PER_LUN 64 /* LUN max command */ -#define UNF_CHECK_LUN_ID_MATCH(lun_id, raw_lun_id, scsi_id, xchg) \ - (((lun_id) == (raw_lun_id) || (lun_id) == INVALID_VALUE64) && \ - ((scsi_id) == (xchg)->scsi_id)) - -#define NO_SENSE 0x00 -#define RECOVERED_ERROR 0x01 -#define NOT_READY 0x02 -#define MEDIUM_ERROR 0x03 -#define HARDWARE_ERROR 0x04 -#define ILLEGAL_REQUEST 0x05 -#define UNIT_ATTENTION 0x06 -#define DATA_PROTECT 0x07 -#define BLANK_CHECK 0x08 -#define COPY_ABORTED 0x0a -#define ABORTED_COMMAND 0x0b -#define VOLUME_OVERFLOW 0x0d -#define MISCOMPARE 0x0e - -#define SENSE_DATA_RESPONSE_CODE 0x70 -#define ADDITINONAL_SENSE_LEN 0x7 - -extern u32 sector_size_flag; - -#define UNF_GET_SCSI_HOST_ID_BY_CMND(cmd) ((cmd)->scsi_host_id) -#define UNF_GET_SCSI_ID_BY_CMND(cmd) ((cmd)->scsi_id) -#define UNF_GET_HOST_PORT_BY_CMND(cmd) ((cmd)->drv_private) -#define UNF_GET_FCP_CMND(cmd) ((cmd)->pcmnd[ARRAY_INDEX_0]) -#define UNF_GET_DATA_LEN(cmd) ((cmd)->transfer_len) -#define UNF_GET_DATA_DIRECTION(cmd) ((cmd)->data_direction) - -#define UNF_GET_HOST_CMND(cmd) ((cmd)->upper_cmnd) -#define UNF_GET_CMND_DONE_FUNC(cmd) ((cmd)->done) -#define UNF_GET_UP_LEVEL_CMND_DONE(cmd) ((cmd)->uplevel_done) -#define UNF_GET_SGL_ENTRY_BUF_FUNC(cmd) ((cmd)->unf_ini_get_sgl_entry) -#define UNF_GET_SENSE_BUF_ADDR(cmd) ((cmd)->sense_buf) -#define UNF_GET_ERR_CODE_TABLE(cmd) ((cmd)->err_code_table) -#define UNF_GET_ERR_CODE_TABLE_COUNT(cmd) ((cmd)->err_code_table_cout) - -#define UNF_SET_HOST_CMND(cmd, host_cmd) ((cmd)->upper_cmnd = (host_cmd)) -#define UNF_SER_CMND_DONE_FUNC(cmd, pfn) ((cmd)->done = (pfn)) -#define UNF_SET_UP_LEVEL_CMND_DONE_FUNC(cmd, pfn) ((cmd)->uplevel_done = (pfn)) - -#define UNF_SET_RESID(cmd, uiresid) ((cmd)->resid = (uiresid)) -#define UNF_SET_CMND_RESULT(cmd, uiresult) ((cmd)->result = ((int)(uiresult))) - -#define UNF_DONE_SCSI_CMND(cmd) ((cmd)->done(cmd)) - -#define UNF_GET_CMND_SGL(cmd) ((cmd)->sgl) -#define UNF_INI_GET_DIF_SGL(cmd) ((cmd)->dif_control.dif_sgl) - -u32 unf_ini_scsi_completed(void *lport, struct unf_frame_pkg *pkg); -u32 unf_ini_get_sgl_entry(void *pkg, char **buf, u32 *buf_len); -u32 unf_ini_get_dif_sgl_entry(void *pkg, char **buf, u32 *buf_len); -void unf_complete_cmnd(struct unf_scsi_cmnd *scsi_cmnd, u32 result_size); -void unf_done_ini_xchg(struct unf_xchg *xchg); -u32 unf_tmf_timeout_recovery_special(void *rport, void *xchg); -u32 unf_tmf_timeout_recovery_default(void *rport, void *xchg); -void unf_abts_timeout_recovery_default(void *rport, void *xchg); -int unf_cm_queue_command(struct unf_scsi_cmnd *scsi_cmnd); -int unf_cm_eh_abort_handler(struct unf_scsi_cmnd *scsi_cmnd); -int unf_cm_eh_device_reset_handler(struct unf_scsi_cmnd *scsi_cmnd); -int unf_cm_target_reset_handler(struct unf_scsi_cmnd *scsi_cmnd); -int unf_cm_bus_reset_handler(struct unf_scsi_cmnd *scsi_cmnd); -int unf_cm_virtual_reset_handler(struct unf_scsi_cmnd *scsi_cmnd); -struct unf_rport *unf_find_rport_by_scsi_id(struct unf_lport *lport, - struct unf_ini_error_code *errcode_table, - u32 errcode_table_count, - u32 scsi_id, u32 *scsi_result); -u32 UNF_IOExchgDelayProcess(struct unf_lport *lport, struct unf_xchg *xchg); -struct unf_lport *unf_find_lport_by_scsi_cmd(struct unf_scsi_cmnd *scsi_cmnd); -int unf_send_scsi_mgmt_cmnd(struct unf_xchg *xchg, struct unf_lport *lport, - struct unf_rport *rport, - struct unf_scsi_cmnd *scsi_cmnd, - enum unf_task_mgmt_cmd task_mgnt_cmd_type); -void unf_tmf_abnormal_recovery(struct unf_lport *lport, struct unf_rport *rport, - struct unf_xchg *xchg); - -#endif diff --git a/drivers/scsi/spfc/common/unf_io_abnormal.c b/drivers/scsi/spfc/common/unf_io_abnormal.c deleted file mode 100644 index 4e268ac026ca..000000000000 --- a/drivers/scsi/spfc/common/unf_io_abnormal.c +++ /dev/null @@ -1,986 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#include "unf_io_abnormal.h" -#include "unf_log.h" -#include "unf_scsi_common.h" -#include "unf_rport.h" -#include "unf_io.h" -#include "unf_portman.h" -#include "unf_service.h" - -static int unf_send_abts_success(struct unf_lport *lport, struct unf_xchg *xchg, - struct unf_scsi_cmnd *scsi_cmnd, - u32 time_out_value) -{ - bool need_wait_marker = true; - struct unf_rport_scsi_id_image *scsi_image_table = NULL; - u32 scsi_id = 0; - u32 return_value = 0; - ulong xchg_flag = 0; - - spin_lock_irqsave(&xchg->xchg_state_lock, xchg_flag); - need_wait_marker = (xchg->abts_state & MARKER_STS_RECEIVED) ? false : true; - spin_unlock_irqrestore(&xchg->xchg_state_lock, xchg_flag); - - if (need_wait_marker) { - if (down_timeout(&xchg->task_sema, (s64)msecs_to_jiffies(time_out_value))) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x) recv abts marker timeout,Exch(0x%p) OX_ID(0x%x 0x%x) RX_ID(0x%x)", - lport->port_id, xchg, xchg->oxid, - xchg->hotpooltag, xchg->rxid); - - /* Cancel abts rsp timer when sema timeout */ - lport->xchg_mgr_temp.unf_xchg_cancel_timer((void *)xchg); - - /* Cnacel the flag of INI_IO_STATE_UPABORT and process - * the io in TMF - */ - spin_lock_irqsave(&xchg->xchg_state_lock, xchg_flag); - xchg->io_state &= ~INI_IO_STATE_UPABORT; - xchg->io_state |= INI_IO_STATE_TMF_ABORT; - spin_unlock_irqrestore(&xchg->xchg_state_lock, xchg_flag); - - return UNF_SCSI_ABORT_FAIL; - } - } else { - xchg->ucode_abts_state = UNF_IO_SUCCESS; - } - - scsi_image_table = &lport->rport_scsi_table; - scsi_id = scsi_cmnd->scsi_id; - - spin_lock_irqsave(&xchg->xchg_state_lock, xchg_flag); - if (xchg->ucode_abts_state == UNF_IO_SUCCESS || - xchg->scsi_cmnd_info.result == UNF_IO_ABORT_PORT_REMOVING) { - spin_unlock_irqrestore(&xchg->xchg_state_lock, xchg_flag); - - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_MAJOR, - "[info]Port(0x%x) Send ABTS succeed and recv marker Exch(0x%p) OX_ID(0x%x) RX_ID(0x%x) marker status(0x%x)", - lport->port_id, xchg, xchg->oxid, xchg->rxid, xchg->ucode_abts_state); - return_value = DID_RESET; - UNF_IO_RESULT_CNT(scsi_image_table, scsi_id, return_value); - unf_complete_cmnd(scsi_cmnd, DID_RESET << UNF_SHIFT_16); - return UNF_SCSI_ABORT_SUCCESS; - } - - xchg->io_state &= ~INI_IO_STATE_UPABORT; - xchg->io_state |= INI_IO_STATE_TMF_ABORT; - - spin_unlock_irqrestore(&xchg->xchg_state_lock, xchg_flag); - - /* Cancel abts rsp timer when sema timeout */ - lport->xchg_mgr_temp.unf_xchg_cancel_timer((void *)xchg); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[warn]Port(0x%x) send ABTS failed. Exch(0x%p) oxid(0x%x) hot_tag(0x%x) ret(0x%x) xchg->io_state (0x%x)", - lport->port_id, xchg, xchg->oxid, xchg->hotpooltag, - xchg->scsi_cmnd_info.result, xchg->io_state); - - /* return fail and then enter TMF */ - return UNF_SCSI_ABORT_FAIL; -} - -static int unf_ini_abort_cmnd(struct unf_lport *lport, struct unf_xchg *xchg, - struct unf_scsi_cmnd *scsi_cmnd) -{ - /* - * About INI_IO_STATE_UPABORT: - * * - * 1. Check: L_Port destroy - * 2. Check: I/O XCHG timeout - * 3. Set ABORT: send ABTS - * 4. Set ABORT: LUN reset - * 5. Set ABORT: Target reset - * 6. Check: Prevent to send I/O to target - * (unf_prefer_to_send_scsi_cmnd) - * 7. Check: Done INI XCHG --->>> do not call scsi_done, return directly - * 8. Check: INI SCSI Complete --->>> do not call scsi_done, return - * directly - */ -#define UNF_RPORT_NOTREADY_WAIT_SEM_TIMEOUT (2000) - - struct unf_lport *unf_lport = NULL; - struct unf_rport *unf_rport = NULL; - ulong rport_flag = 0; - ulong xchg_flag = 0; - struct unf_rport_scsi_id_image *scsi_image_table = NULL; - u32 scsi_id = 0; - u32 time_out_value = (u32)UNF_WAIT_SEM_TIMEOUT; - u32 return_value = 0; - - FC_CHECK_RETURN_VALUE(lport, UNF_SCSI_ABORT_FAIL); - unf_lport = lport; - - /* 1. Xchg State Set: INI_IO_STATE_UPABORT */ - spin_lock_irqsave(&xchg->xchg_state_lock, xchg_flag); - xchg->io_state |= INI_IO_STATE_UPABORT; - unf_rport = xchg->rport; - spin_unlock_irqrestore(&xchg->xchg_state_lock, xchg_flag); - - /* 2. R_Port check */ - if (unlikely(!unf_rport)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x) send ABTS but no RPort, OX_ID(0x%x) RX_ID(0x%x)", - unf_lport->port_id, xchg->oxid, xchg->rxid); - - return UNF_SCSI_ABORT_SUCCESS; - } - - spin_lock_irqsave(&unf_rport->rport_state_lock, rport_flag); - if (unlikely(unf_rport->rp_state != UNF_RPORT_ST_READY)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x) find RPort's state(0x%x) is not ready but send ABTS also, exchange(0x%p) tag(0x%x)", - unf_lport->port_id, unf_rport->rp_state, xchg, xchg->hotpooltag); - - /* - * Important: Send ABTS also & update timer - * Purpose: only used for release chip (uCode) resource, - * continue - */ - time_out_value = UNF_RPORT_NOTREADY_WAIT_SEM_TIMEOUT; - } - spin_unlock_irqrestore(&unf_rport->rport_state_lock, rport_flag); - - /* 3. L_Port State check */ - if (unlikely(unf_lport->port_removing)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x) is removing", unf_lport->port_id); - - xchg->io_state &= ~INI_IO_STATE_UPABORT; - - return UNF_SCSI_ABORT_FAIL; - } - - scsi_image_table = &unf_lport->rport_scsi_table; - scsi_id = scsi_cmnd->scsi_id; - - /* If pcie linkdown, complete this io and flush all io */ - if (unlikely(unf_lport->pcie_link_down)) { - return_value = DID_RESET; - UNF_IO_RESULT_CNT(scsi_image_table, scsi_id, return_value); - unf_complete_cmnd(scsi_cmnd, DID_RESET << UNF_SHIFT_16); - unf_free_lport_all_xchg(lport); - return UNF_SCSI_ABORT_SUCCESS; - } - - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_KEVENT, - "[abort]Port(0x%x) Exchg(0x%p) delay(%llu) SID(0x%x) DID(0x%x) wwpn(0x%llx) hottag(0x%x) scsi_id(0x%x) lun_id(0x%x) cmdsn(0x%llx) Ini:%p", - unf_lport->port_id, xchg, - (u64)jiffies_to_msecs(jiffies) - (u64)jiffies_to_msecs(xchg->alloc_jif), - xchg->sid, xchg->did, unf_rport->port_name, xchg->hotpooltag, - scsi_cmnd->scsi_id, (u32)scsi_cmnd->raw_lun_id, scsi_cmnd->cmnd_sn, - scsi_cmnd->pinitiator); - - /* Init abts marker semaphore */ - sema_init(&xchg->task_sema, 0); - - if (xchg->scsi_cmnd_info.time_out != 0) - unf_lport->xchg_mgr_temp.unf_xchg_cancel_timer(xchg); - - lport->xchg_mgr_temp.unf_xchg_add_timer((void *)xchg, (ulong)UNF_WAIT_ABTS_RSP_TIMEOUT, - UNF_TIMER_TYPE_INI_ABTS); - - /* 4. Send INI ABTS CMND */ - if (unf_send_abts(unf_lport, xchg) != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x) Send ABTS failed. Exch(0x%p) hottag(0x%x)", - unf_lport->port_id, xchg, xchg->hotpooltag); - - lport->xchg_mgr_temp.unf_xchg_cancel_timer((void *)xchg); - - spin_lock_irqsave(&xchg->xchg_state_lock, xchg_flag); - xchg->io_state &= ~INI_IO_STATE_UPABORT; - xchg->io_state |= INI_IO_STATE_TMF_ABORT; - - spin_unlock_irqrestore(&xchg->xchg_state_lock, xchg_flag); - - return UNF_SCSI_ABORT_FAIL; - } - - return unf_send_abts_success(unf_lport, xchg, scsi_cmnd, time_out_value); -} - -static void unf_flush_ini_resp_que(struct unf_lport *lport) -{ - FC_CHECK_RETURN_VOID(lport); - - if (lport->low_level_func.service_op.unf_flush_ini_resp_que) - (void)lport->low_level_func.service_op.unf_flush_ini_resp_que(lport->fc_port); -} - -int unf_cm_eh_abort_handler(struct unf_scsi_cmnd *scsi_cmnd) -{ - /* - * SCSI ABORT Command --->>> FC ABTS Command - * If return ABORT_FAIL, then enter TMF process - */ - struct unf_lport *unf_lport = NULL; - struct unf_xchg *unf_xchg = NULL; - struct unf_rport *unf_rport = NULL; - struct unf_lport *xchg_lport = NULL; - int ret = UNF_SCSI_ABORT_SUCCESS; - ulong flag = 0; - - /* 1. Get L_Port: Point to Scsi_host */ - unf_lport = unf_find_lport_by_scsi_cmd(scsi_cmnd); - if (!unf_lport) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Can't find port by scsi host id(0x%x)", - UNF_GET_SCSI_HOST_ID_BY_CMND(scsi_cmnd)); - return UNF_SCSI_ABORT_FAIL; - } - - /* 2. find target Xchg for INI Abort CMND */ - unf_xchg = unf_cm_lookup_xchg_by_cmnd_sn(unf_lport, scsi_cmnd->cmnd_sn, - scsi_cmnd->world_id, - scsi_cmnd->pinitiator); - if (unlikely(!unf_xchg)) { - FC_DRV_PRINT(UNF_LOG_ABNORMAL, UNF_WARN, - "[warn]Port(0x%x) can't find exchange by Cmdsn(0x%lx),Ini:%p", - unf_lport->port_id, (ulong)scsi_cmnd->cmnd_sn, - scsi_cmnd->pinitiator); - - unf_flush_ini_resp_que(unf_lport); - - return UNF_SCSI_ABORT_SUCCESS; - } - - /* 3. increase ref_cnt to protect exchange */ - ret = (int)unf_xchg_ref_inc(unf_xchg, INI_EH_ABORT); - if (unlikely(ret != RETURN_OK)) { - unf_flush_ini_resp_que(unf_lport); - - return UNF_SCSI_ABORT_SUCCESS; - } - - scsi_cmnd->upper_cmnd = unf_xchg->scsi_cmnd_info.scsi_cmnd; - unf_xchg->debug_hook = true; - - /* 4. Exchang L_Port/R_Port Get & check */ - spin_lock_irqsave(&unf_xchg->xchg_state_lock, flag); - xchg_lport = unf_xchg->lport; - unf_rport = unf_xchg->rport; - spin_unlock_irqrestore(&unf_xchg->xchg_state_lock, flag); - - if (unlikely(!xchg_lport || !unf_rport)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Exchange(0x%p)'s L_Port or R_Port is NULL, state(0x%x)", - unf_xchg, unf_xchg->io_state); - - unf_xchg_ref_dec(unf_xchg, INI_EH_ABORT); - - if (!xchg_lport) - /* for L_Port */ - return UNF_SCSI_ABORT_FAIL; - /* for R_Port */ - return UNF_SCSI_ABORT_SUCCESS; - } - - /* 5. Send INI Abort Cmnd */ - ret = unf_ini_abort_cmnd(xchg_lport, unf_xchg, scsi_cmnd); - - /* 6. decrease exchange ref_cnt */ - unf_xchg_ref_dec(unf_xchg, INI_EH_ABORT); - - return ret; -} - -u32 unf_tmf_timeout_recovery_default(void *rport, void *xchg) -{ - struct unf_lport *unf_lport = NULL; - ulong flag = 0; - struct unf_xchg *unf_xchg = (struct unf_xchg *)xchg; - struct unf_rport *unf_rport = (struct unf_rport *)rport; - - unf_lport = unf_xchg->lport; - FC_CHECK_RETURN_VALUE(unf_lport, UNF_RETURN_ERROR); - - spin_lock_irqsave(&unf_rport->rport_state_lock, flag); - unf_rport_state_ma(unf_rport, UNF_EVENT_RPORT_LOGO); - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flag); - - unf_rport_enter_logo(unf_lport, unf_rport); - - return RETURN_OK; -} - -void unf_abts_timeout_recovery_default(void *rport, void *xchg) -{ - struct unf_lport *unf_lport = NULL; - ulong flag = 0; - ulong flags = 0; - struct unf_xchg *unf_xchg = (struct unf_xchg *)xchg; - struct unf_rport *unf_rport = (struct unf_rport *)rport; - - unf_lport = unf_xchg->lport; - FC_CHECK_RETURN_VOID(unf_lport); - - spin_lock_irqsave(&unf_xchg->xchg_state_lock, flags); - if (INI_IO_STATE_DONE & unf_xchg->io_state) { - spin_unlock_irqrestore(&unf_xchg->xchg_state_lock, flags); - - return; - } - spin_unlock_irqrestore(&unf_xchg->xchg_state_lock, flags); - - if (unf_xchg->rport_bind_jifs != unf_rport->rport_alloc_jifs) - return; - - spin_lock_irqsave(&unf_rport->rport_state_lock, flag); - unf_rport_state_ma(unf_rport, UNF_EVENT_RPORT_LOGO); - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flag); - - unf_rport_enter_logo(unf_lport, unf_rport); -} - -u32 unf_tmf_timeout_recovery_special(void *rport, void *xchg) -{ - /* Do port reset or R_Port LOGO */ - int ret = UNF_RETURN_ERROR; - struct unf_lport *unf_lport = NULL; - struct unf_xchg *unf_xchg = (struct unf_xchg *)xchg; - struct unf_rport *unf_rport = (struct unf_rport *)rport; - - FC_CHECK_RETURN_VALUE(rport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(xchg, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(unf_xchg->lport, UNF_RETURN_ERROR); - - unf_lport = unf_xchg->lport->root_lport; - FC_CHECK_RETURN_VALUE(unf_lport, UNF_RETURN_ERROR); - - /* 1. TMF response timeout & Marker STS timeout */ - if (!(unf_xchg->tmf_state & - (MARKER_STS_RECEIVED | TMF_RESPONSE_RECEIVED))) { - /* TMF timeout & marker timeout */ - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) receive marker status timeout and do recovery", - unf_lport->port_id); - - /* Do port reset */ - ret = unf_cm_reset_port(unf_lport->port_id); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) do reset failed", - unf_lport->port_id); - - return UNF_RETURN_ERROR; - } - - return RETURN_OK; - } - - /* 2. default case: Do LOGO process */ - unf_tmf_timeout_recovery_default(unf_rport, unf_xchg); - - return RETURN_OK; -} - -void unf_tmf_abnormal_recovery(struct unf_lport *lport, struct unf_rport *rport, - struct unf_xchg *xchg) -{ - /* - * for device(lun)/target(session) reset: - * Do port reset or R_Port LOGO - */ - if (lport->unf_tmf_abnormal_recovery) - lport->unf_tmf_abnormal_recovery((void *)rport, (void *)xchg); -} - -int unf_cm_eh_device_reset_handler(struct unf_scsi_cmnd *scsi_cmnd) -{ - /* SCSI Device/LUN Reset Command --->>> FC LUN/Device Reset Command */ - struct unf_lport *unf_lport = NULL; - struct unf_rport *unf_rport = NULL; - struct unf_xchg *unf_xchg = NULL; - u32 cmnd_result = 0; - int ret = SUCCESS; - - FC_CHECK_RETURN_VALUE(scsi_cmnd, FAILED); - FC_CHECK_RETURN_VALUE(scsi_cmnd->lun_id, FAILED); - - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_MAJOR, - "[event]Enter device/LUN reset handler"); - - /* 1. Get L_Port */ - unf_lport = unf_find_lport_by_scsi_cmd(scsi_cmnd); - if (!unf_lport) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Can't find port by scsi_host_id(0x%x)", - UNF_GET_SCSI_HOST_ID_BY_CMND(scsi_cmnd)); - - return FAILED; - } - - /* 2. L_Port State checking */ - if (unlikely(unf_lport->port_removing)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%p) is removing", unf_lport); - - return FAILED; - } - - /* - * 3. Get R_Port: no rport is found or rport is not ready,return ok - * from: L_Port -->> rport_scsi_table (image table) -->> - * rport_info_table - */ - unf_rport = unf_find_rport_by_scsi_id(unf_lport, scsi_cmnd->err_code_table, - scsi_cmnd->err_code_table_cout, - UNF_GET_SCSI_ID_BY_CMND(scsi_cmnd), &cmnd_result); - if (unlikely(!unf_rport)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x) Can't find rport by scsi_id(0x%x)", - unf_lport->port_id, UNF_GET_SCSI_ID_BY_CMND(scsi_cmnd)); - - return SUCCESS; - } - - /* - * 4. Set the I/O of the corresponding LUN to abort. - * * - * LUN Reset: set UP_ABORT tag, with: - * INI_Busy_list, IO_Wait_list, - * IO_Delay_list, IO_Delay_transfer_list - */ - unf_cm_xchg_abort_by_lun(unf_lport, unf_rport, *((u64 *)scsi_cmnd->lun_id), NULL, false); - - /* 5. R_Port state check */ - if (unlikely(unf_rport->rp_state != UNF_RPORT_ST_READY)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x) RPort(0x%x) state(0x%x) SCSI Command(0x%p), rport is not ready", - unf_lport->port_id, unf_rport->nport_id, - unf_rport->rp_state, scsi_cmnd); - - return SUCCESS; - } - - /* 6. Get & inc ref_cnt free Xchg for Device reset */ - unf_xchg = (struct unf_xchg *)unf_cm_get_free_xchg(unf_lport, UNF_XCHG_TYPE_INI); - if (unlikely(!unf_xchg)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%p) can't get free exchange", unf_lport); - - return FAILED; - } - - /* increase ref_cnt for protecting exchange */ - ret = (int)unf_xchg_ref_inc(unf_xchg, INI_EH_DEVICE_RESET); - FC_CHECK_RETURN_VALUE((ret == RETURN_OK), FAILED); - - /* 7. Send Device/LUN Reset to Low level */ - ret = unf_send_scsi_mgmt_cmnd(unf_xchg, unf_lport, unf_rport, scsi_cmnd, - UNF_FCP_TM_LOGICAL_UNIT_RESET); - if (unlikely(ret == FAILED)) { - /* - * Do port reset or R_Port LOGO: - * 1. FAILED: send failed - * 2. FAILED: semaphore timeout - * 3. SUCCESS: rcvd rsp & semaphore has been waken up - */ - unf_tmf_abnormal_recovery(unf_lport, unf_rport, unf_xchg); - } - - /* - * 8. Release resource immediately if necessary - * NOTE: here, semaphore timeout or rcvd rsp(semaphore has been waken - * up) - */ - if (likely(!unf_lport->port_removing || unf_lport->root_lport != unf_lport)) - unf_cm_free_xchg(unf_xchg->lport, unf_xchg); - - /* decrease ref_cnt */ - unf_xchg_ref_dec(unf_xchg, INI_EH_DEVICE_RESET); - - return SUCCESS; -} - -int unf_cm_target_reset_handler(struct unf_scsi_cmnd *scsi_cmnd) -{ - /* SCSI Target Reset Command --->>> FC Session Reset/Delete Command */ - struct unf_lport *unf_lport = NULL; - struct unf_rport *unf_rport = NULL; - struct unf_xchg *unf_xchg = NULL; - u32 cmnd_result = 0; - int ret = SUCCESS; - - FC_CHECK_RETURN_VALUE(scsi_cmnd, FAILED); - FC_CHECK_RETURN_VALUE(scsi_cmnd->lun_id, FAILED); - - /* 1. Get L_Port */ - unf_lport = unf_find_lport_by_scsi_cmd(scsi_cmnd); - if (!unf_lport) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Can't find port by scsi_host_id(0x%x)", - UNF_GET_SCSI_HOST_ID_BY_CMND(scsi_cmnd)); - - return FAILED; - } - - /* 2. L_Port State check */ - if (unlikely(unf_lport->port_removing)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%p) is removing", unf_lport); - - return FAILED; - } - - /* - * 3. Get R_Port: no rport is found or rport is not ready,return ok - * from: L_Port -->> rport_scsi_table (image table) -->> - * rport_info_table - */ - unf_rport = unf_find_rport_by_scsi_id(unf_lport, scsi_cmnd->err_code_table, - scsi_cmnd->err_code_table_cout, - UNF_GET_SCSI_ID_BY_CMND(scsi_cmnd), &cmnd_result); - if (unlikely(!unf_rport)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Can't find rport by scsi_id(0x%x)", - UNF_GET_SCSI_ID_BY_CMND(scsi_cmnd)); - - return SUCCESS; - } - - /* - * 4. set UP_ABORT on Target IO and Session IO - * * - * LUN Reset: set UP_ABORT tag, with: - * INI_Busy_list, IO_Wait_list, - * IO_Delay_list, IO_Delay_transfer_list - */ - unf_cm_xchg_abort_by_session(unf_lport, unf_rport); - - /* 5. R_Port state check */ - if (unlikely(unf_rport->rp_state != UNF_RPORT_ST_READY)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x) RPort(0x%x) state(0x%x) is not ready, SCSI Command(0x%p)", - unf_lport->port_id, unf_rport->nport_id, - unf_rport->rp_state, scsi_cmnd); - - return SUCCESS; - } - - /* 6. Get free Xchg for Target Reset CMND */ - unf_xchg = (struct unf_xchg *)unf_cm_get_free_xchg(unf_lport, UNF_XCHG_TYPE_INI); - if (unlikely(!unf_xchg)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%p) can't get free exchange", unf_lport); - - return FAILED; - } - - /* increase ref_cnt to protect exchange */ - ret = (int)unf_xchg_ref_inc(unf_xchg, INI_EH_DEVICE_RESET); - FC_CHECK_RETURN_VALUE((ret == RETURN_OK), FAILED); - - /* 7. Send Target Reset Cmnd to low-level */ - ret = unf_send_scsi_mgmt_cmnd(unf_xchg, unf_lport, unf_rport, scsi_cmnd, - UNF_FCP_TM_TARGET_RESET); - if (unlikely(ret == FAILED)) { - /* - * Do port reset or R_Port LOGO: - * 1. FAILED: send failed - * 2. FAILED: semaphore timeout - * 3. SUCCESS: rcvd rsp & semaphore has been waken up - */ - unf_tmf_abnormal_recovery(unf_lport, unf_rport, unf_xchg); - } - - /* - * 8. Release resource immediately if necessary - * NOTE: here, semaphore timeout or rcvd rsp(semaphore has been waken - * up) - */ - if (likely(!unf_lport->port_removing || unf_lport->root_lport != unf_lport)) - unf_cm_free_xchg(unf_xchg->lport, unf_xchg); - - /* decrease exchange ref_cnt */ - unf_xchg_ref_dec(unf_xchg, INI_EH_DEVICE_RESET); - - return SUCCESS; -} - -int unf_cm_bus_reset_handler(struct unf_scsi_cmnd *scsi_cmnd) -{ - /* SCSI BUS Reset Command --->>> FC Port Reset Command */ - struct unf_lport *unf_lport = NULL; - int cmnd_result = 0; - - /* 1. Get L_Port */ - unf_lport = unf_find_lport_by_scsi_cmd(scsi_cmnd); - if (!unf_lport) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Can't find port by scsi_host_id(0x%x)", - UNF_GET_SCSI_HOST_ID_BY_CMND(scsi_cmnd)); - - return FAILED; - } - - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_KEVENT, - "[event]Do port reset with scsi_bus_reset"); - - cmnd_result = unf_cm_reset_port(unf_lport->port_id); - if (unlikely(cmnd_result == UNF_RETURN_ERROR)) - return FAILED; - else - return SUCCESS; -} - -void unf_process_scsi_mgmt_result(struct unf_frame_pkg *pkg, - struct unf_xchg *xchg) -{ - u8 *rsp_info = NULL; - u8 rsp_code = 0; - u32 code_index = 0; - - /* - * LLT found that:RSP_CODE is the third byte of - * FCP_RSP_INFO, on Little endian should be byte 0, For - * detail FCP_4 Table 26 FCP_RSP_INFO field format - * * - * 1. state setting - * 2. wake up semaphore - */ - FC_CHECK_RETURN_VOID(pkg); - FC_CHECK_RETURN_VOID(xchg); - - xchg->tmf_state |= TMF_RESPONSE_RECEIVED; - - if (UNF_GET_LL_ERR(pkg) != UNF_IO_SUCCESS || - pkg->unf_rsp_pload_bl.length > UNF_RESPONE_DATA_LEN) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Send scsi manage command failed with error code(0x%x) resp len(0x%x)", - UNF_GET_LL_ERR(pkg), pkg->unf_rsp_pload_bl.length); - - xchg->scsi_cmnd_info.result = UNF_IO_FAILED; - - /* wakeup semaphore & return */ - up(&xchg->task_sema); - - return; - } - - rsp_info = pkg->unf_rsp_pload_bl.buffer_ptr; - if (rsp_info && pkg->unf_rsp_pload_bl.length != 0) { - /* change to little end if necessary */ - if (pkg->byte_orders & UNF_BIT_3) - unf_big_end_to_cpu(rsp_info, pkg->unf_rsp_pload_bl.length); - } - - if (!rsp_info) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_MAJOR, - "[info]FCP response data pointer is NULL with Xchg TAG(0x%x)", - xchg->hotpooltag); - - xchg->scsi_cmnd_info.result = UNF_IO_SUCCESS; - - /* wakeup semaphore & return */ - up(&xchg->task_sema); - - return; - } - - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_MAJOR, - "[info]FCP response data length(0x%x), RSP_CODE(0x%x:%x:%x:%x:%x:%x:%x:%x)", - pkg->unf_rsp_pload_bl.length, rsp_info[ARRAY_INDEX_0], - rsp_info[ARRAY_INDEX_1], rsp_info[ARRAY_INDEX_2], - rsp_info[ARRAY_INDEX_3], rsp_info[ARRAY_INDEX_4], - rsp_info[ARRAY_INDEX_5], rsp_info[ARRAY_INDEX_6], - rsp_info[ARRAY_INDEX_7]); - - rsp_code = rsp_info[code_index]; - if (rsp_code == UNF_FCP_TM_RSP_COMPLETE || rsp_code == UNF_FCP_TM_RSP_SUCCEED) - xchg->scsi_cmnd_info.result = UNF_IO_SUCCESS; - else - xchg->scsi_cmnd_info.result = UNF_IO_FAILED; - - /* wakeup semaphore & return */ - up(&xchg->task_sema); -} - -static void unf_build_task_mgmt_fcp_cmnd(struct unf_fcp_cmnd *fcp_cmnd, - struct unf_scsi_cmnd *scsi_cmnd, - enum unf_task_mgmt_cmd task_mgmt) -{ - FC_CHECK_RETURN_VOID(fcp_cmnd); - FC_CHECK_RETURN_VOID(scsi_cmnd); - - unf_big_end_to_cpu((void *)scsi_cmnd->lun_id, UNF_FCP_LUNID_LEN_8); - (*(u64 *)(scsi_cmnd->lun_id)) >>= UNF_SHIFT_8; - memcpy(fcp_cmnd->lun, scsi_cmnd->lun_id, sizeof(fcp_cmnd->lun)); - - /* - * If the TASK MANAGEMENT FLAGS field is set to a nonzero value, - * the FCP_CDB field, the FCP_DL field, the TASK ATTRIBUTE field, - * the RDDATA bit, and the WRDATA bit shall be ignored and the - * FCP_BIDIRECTIONAL_READ_DL field shall not be included in the FCP_CMND - * IU payload - */ - fcp_cmnd->control = UNF_SET_TASK_MGMT_FLAGS((u32)(task_mgmt)); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "SCSI cmnd(0x%x) is task mgmt cmnd. ntrl Flag(LITTLE END) is 0x%x.", - task_mgmt, fcp_cmnd->control); -} - -int unf_send_scsi_mgmt_cmnd(struct unf_xchg *xchg, struct unf_lport *lport, - struct unf_rport *rport, - struct unf_scsi_cmnd *scsi_cmnd, - enum unf_task_mgmt_cmd task_mgnt_cmd_type) -{ - /* - * 1. Device/LUN reset - * 2. Target/Session reset - */ - struct unf_xchg *unf_xchg = NULL; - int ret = SUCCESS; - struct unf_frame_pkg pkg = {0}; - ulong xchg_flag = 0; - ulong flag = 0; - - FC_CHECK_RETURN_VALUE(lport, FAILED); - FC_CHECK_RETURN_VALUE(rport, FAILED); - FC_CHECK_RETURN_VALUE(xchg, FAILED); - FC_CHECK_RETURN_VALUE(scsi_cmnd, FAILED); - FC_CHECK_RETURN_VALUE(task_mgnt_cmd_type <= UNF_FCP_TM_TERMINATE_TASK && - task_mgnt_cmd_type >= UNF_FCP_TM_QUERY_TASK_SET, FAILED); - - unf_xchg = xchg; - unf_xchg->lport = lport; - unf_xchg->rport = rport; - - /* 1. State: Up_Task */ - spin_lock_irqsave(&unf_xchg->xchg_state_lock, xchg_flag); - unf_xchg->io_state |= INI_IO_STATE_UPTASK; - spin_unlock_irqrestore(&unf_xchg->xchg_state_lock, xchg_flag); - pkg.frame_head.oxid_rxid = ((u32)unf_xchg->oxid << (u32)UNF_SHIFT_16) | unf_xchg->rxid; - - /* 2. Set TASK MANAGEMENT FLAGS of FCP_CMND to the corresponding task - * management command - */ - unf_build_task_mgmt_fcp_cmnd(&unf_xchg->fcp_cmnd, scsi_cmnd, task_mgnt_cmd_type); - - pkg.xchg_contex = unf_xchg; - pkg.private_data[PKG_PRIVATE_XCHG_RPORT_INDEX] = rport->rport_index; - pkg.fcp_cmnd = &unf_xchg->fcp_cmnd; - pkg.private_data[PKG_PRIVATE_XCHG_HOT_POOL_INDEX] = unf_xchg->hotpooltag; - pkg.frame_head.csctl_sid = lport->nport_id; - pkg.frame_head.rctl_did = rport->nport_id; - - pkg.private_data[PKG_PRIVATE_XCHG_ALLOC_TIME] = - xchg->private_data[PKG_PRIVATE_XCHG_ALLOC_TIME]; - - if (unlikely(lport->pcie_link_down)) { - unf_free_lport_all_xchg(lport); - return SUCCESS; - } - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_KEVENT, - "[event]Port(0x%x) send task_cmnd(0x%x) to RPort(0x%x) Hottag(0x%x) lunid(0x%llx)", - lport->port_id, task_mgnt_cmd_type, rport->nport_id, - unf_xchg->hotpooltag, *((u64 *)scsi_cmnd->lun_id)); - - /* 3. Init exchange task semaphore */ - sema_init(&unf_xchg->task_sema, 0); - - /* 4. Send Mgmt Task to low-level */ - if (unf_hardware_start_io(lport, &pkg) != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x) send task_cmnd(0x%x) to RPort(0x%x) failed", - lport->port_id, task_mgnt_cmd_type, rport->nport_id); - - return FAILED; - } - - /* - * semaphore timeout - ** - * Code review: The second input parameter needs to be converted to - jiffies. - * set semaphore after the message is sent successfully.The semaphore is - returned when the semaphore times out or is woken up. - ** - * 5. The semaphore is cleared and counted when the Mgmt Task message is - sent, and is Wake Up when the RSP message is received. - * If the semaphore is not Wake Up, the semaphore is triggered after - timeout. That is, no RSP message is received within the timeout period. - */ - if (down_timeout(&unf_xchg->task_sema, (s64)msecs_to_jiffies((u32)UNF_WAIT_SEM_TIMEOUT))) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x) send task_cmnd(0x%x) to RPort(0x%x) timeout scsi id(0x%x) lun id(0x%x)", - lport->nport_id, task_mgnt_cmd_type, - rport->nport_id, scsi_cmnd->scsi_id, - (u32)scsi_cmnd->raw_lun_id); - unf_notify_chip_free_xid(unf_xchg); - /* semaphore timeout */ - ret = FAILED; - spin_lock_irqsave(&lport->lport_state_lock, flag); - if (lport->states == UNF_LPORT_ST_RESET) - ret = SUCCESS; - spin_unlock_irqrestore(&lport->lport_state_lock, flag); - - return ret; - } - - /* - * 6. NOTE: no timeout (has been waken up) - * Do Scsi_Cmnd(Mgmt Task) result checking - * * - * FAILED: with error code or RSP is error - * SUCCESS: others - */ - if (unf_xchg->scsi_cmnd_info.result == UNF_IO_SUCCESS) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_MAJOR, - "[info]Port(0x%x) send task_cmnd(0x%x) to RPort(0x%x) and receive rsp succeed", - lport->nport_id, task_mgnt_cmd_type, rport->nport_id); - - ret = SUCCESS; - } else { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x) send task_cmnd(0x%x) to RPort(0x%x) and receive rsp failed scsi id(0x%x) lun id(0x%x)", - lport->nport_id, task_mgnt_cmd_type, rport->nport_id, - scsi_cmnd->scsi_id, (u32)scsi_cmnd->raw_lun_id); - - ret = FAILED; - } - - return ret; -} - -u32 unf_recv_tmf_marker_status(void *lport, struct unf_frame_pkg *pkg) -{ - struct unf_lport *unf_lport = NULL; - u32 uret = RETURN_OK; - struct unf_xchg *unf_xchg = NULL; - u16 hot_pool_tag = 0; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(pkg, UNF_RETURN_ERROR); - unf_lport = (struct unf_lport *)lport; - - /* Find exchange which point to marker sts */ - if (!unf_lport->xchg_mgr_temp.unf_look_up_xchg_by_tag) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) tag function is NULL", unf_lport->port_id); - - return UNF_RETURN_ERROR; - } - - hot_pool_tag = - (u16)(pkg->private_data[PKG_PRIVATE_XCHG_HOT_POOL_INDEX]); - - unf_xchg = - (struct unf_xchg *)(unf_lport->xchg_mgr_temp - .unf_look_up_xchg_by_tag((void *)unf_lport, hot_pool_tag)); - if (!unf_xchg) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x_0x%x) find exchange by tag(0x%x) failed", - unf_lport->port_id, unf_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 - */ - unf_xchg->tmf_state |= MARKER_STS_RECEIVED; - - FC_DRV_PRINT(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)", - pkg->frame_head.rctl_did & UNF_NPORTID_MASK, - pkg->frame_head.csctl_sid & UNF_NPORTID_MASK, - (u16)(pkg->frame_head.oxid_rxid >> UNF_SHIFT_16), - (u16)(pkg->frame_head.oxid_rxid), unf_xchg->did, unf_xchg->sid, - unf_xchg->oxid, unf_xchg->rxid); - - return uret; -} - -u32 unf_recv_abts_marker_status(void *lport, struct unf_frame_pkg *pkg) -{ - struct unf_lport *unf_lport = NULL; - struct unf_xchg *unf_xchg = NULL; - u16 hot_pool_tag = 0; - ulong flags = 0; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(pkg, UNF_RETURN_ERROR); - unf_lport = (struct unf_lport *)lport; - - /* Find exchange by tag */ - if (!unf_lport->xchg_mgr_temp.unf_look_up_xchg_by_tag) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) tag function is NULL", unf_lport->port_id); - - return UNF_RETURN_ERROR; - } - - hot_pool_tag = (u16)(pkg->private_data[PKG_PRIVATE_XCHG_HOT_POOL_INDEX]); - - unf_xchg = - (struct unf_xchg *)(unf_lport->xchg_mgr_temp.unf_look_up_xchg_by_tag((void *)unf_lport, - hot_pool_tag)); - if (!unf_xchg) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x_0x%x) find exchange by tag(0x%x) failed", - unf_lport->port_id, unf_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(&unf_xchg->xchg_state_lock, flags); - unf_xchg->ucode_abts_state = pkg->status; - unf_xchg->abts_state |= MARKER_STS_RECEIVED; - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_KEVENT, - "[info]Port(0x%x) wake up SEMA for Abts marker exchange(0x%p) oxid(0x%x 0x%x) hottag(0x%x) status(0x%x)", - unf_lport->port_id, unf_xchg, unf_xchg->oxid, unf_xchg->rxid, - unf_xchg->hotpooltag, pkg->abts_maker_status); - - /* - * NOTE: Second time for ABTS marker received, or - * ABTS response have been received, no need to wake up sema - */ - if ((INI_IO_STATE_ABORT_TIMEOUT & unf_xchg->io_state) || - (ABTS_RESPONSE_RECEIVED & unf_xchg->abts_state)) { - spin_unlock_irqrestore(&unf_xchg->xchg_state_lock, flags); - - FC_DRV_PRINT(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)", - unf_lport->port_id, unf_xchg->abts_state, unf_xchg->io_state); - - return RETURN_OK; - } - - if (unf_xchg->io_state & INI_IO_STATE_TMF_ABORT) { - spin_unlock_irqrestore(&unf_xchg->xchg_state_lock, flags); - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_KEVENT, - "[info]Port(0x%x) receive Abts marker, exchange(%p) state(0x%x) free it", - unf_lport->port_id, unf_xchg, unf_xchg->io_state); - - unf_cm_free_xchg(unf_lport, unf_xchg); - } else { - spin_unlock_irqrestore(&unf_xchg->xchg_state_lock, flags); - up(&unf_xchg->task_sema); - } - - return RETURN_OK; -} diff --git a/drivers/scsi/spfc/common/unf_io_abnormal.h b/drivers/scsi/spfc/common/unf_io_abnormal.h deleted file mode 100644 index 31cc8e30e51a..000000000000 --- a/drivers/scsi/spfc/common/unf_io_abnormal.h +++ /dev/null @@ -1,19 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef UNF_IO_ABNORMAL_H -#define UNF_IO_ABNORMAL_H - -#include "unf_type.h" -#include "unf_lport.h" -#include "unf_exchg.h" - -#define UNF_GET_LL_ERR(pkg) (((pkg)->status) >> 16) - -void unf_process_scsi_mgmt_result(struct unf_frame_pkg *pkg, - struct unf_xchg *xchg); -u32 unf_hardware_start_io(struct unf_lport *lport, struct unf_frame_pkg *pkg); -u32 unf_recv_abts_marker_status(void *lport, struct unf_frame_pkg *pkg); -u32 unf_recv_tmf_marker_status(void *lport, struct unf_frame_pkg *pkg); - -#endif diff --git a/drivers/scsi/spfc/common/unf_log.h b/drivers/scsi/spfc/common/unf_log.h deleted file mode 100644 index 801e23ac0829..000000000000 --- a/drivers/scsi/spfc/common/unf_log.h +++ /dev/null @@ -1,178 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef UNF_LOG_H -#define UNF_LOG_H -#include "unf_type.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 { - UNF_DEBUG_TYPE_MML = 0, - UNF_DEBUG_TYPE_DIAGNOSE = 1, - UNF_DEBUG_TYPE_MESSAGE = 2, - UNF_DEBUG_TYPE_BUTT -}; - -enum unf_log_attr { - 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 { - 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 u32 unf_dgb_level; -extern u32 log_print_level; -extern u32 log_limited_times; - -#define DRV_LOG_LIMIT(module_id, log_level, 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_limited_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 FC_CHECK_RETURN_VALUE(condition, ret) \ - do { \ - if (unlikely(!(condition))) { \ - FC_DRV_PRINT(UNF_LOG_REG_ATT, \ - UNF_ERR, "Para check(%s) invalid", \ - #condition); \ - return ret; \ - } \ - } while (0) - -#define FC_CHECK_RETURN_VOID(condition) \ - do { \ - if (unlikely(!(condition))) { \ - FC_DRV_PRINT(UNF_LOG_REG_ATT, \ - UNF_ERR, "Para check(%s) invalid", \ - #condition); \ - return; \ - } \ - } while (0) - -#define FC_DRV_PRINT(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_att, format, ##__VA_ARGS__); \ - } else if (log_level == UNF_WARN) { \ - DRV_LOG_LIMIT(UNF_PID, KERN_WARNING, \ - log_att, format, ##__VA_ARGS__); \ - } else if (log_level == UNF_ERR) { \ - DRV_LOG_LIMIT(UNF_PID, KERN_ERR, \ - 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_att, format, ##__VA_ARGS__); \ - } else if (log_level == UNF_INFO || \ - log_level == UNF_DATA) { \ - DRV_LOG_LIMIT(UNF_PID, KERN_INFO, \ - log_att, format, ##__VA_ARGS__); \ - } \ - } \ - } while (0) - -#define UNF_PRINT_SFS(dbg_level, portid, data, size) \ - do { \ - if ((dbg_level) <= log_print_level) { \ - u32 cnt = 0; \ - printk(KERN_INFO "[INFO]Port(0x%x) sfs:0x", (portid)); \ - for (cnt = 0; cnt < (size) / 4; cnt++) { \ - printk(KERN_INFO "%08x ", \ - ((u32 *)(data))[cnt]); \ - } \ - printk(KERN_INFO "[FC_UNF][%s]\n", __func__); \ - } \ - } while (0) - -#define UNF_PRINT_SFS_LIMIT(dbg_level, portid, data, size) \ - do { \ - if ((dbg_level) <= log_print_level) { \ - static ulong pre; \ - static int should_print = UNF_LOGIN_ATT_PRINT_TIMES; \ - if (time_after_eq( \ - jiffies, pre + UNF_IO_ATT_PRINT_LIMIT)) { \ - should_print = log_limited_times; \ - } \ - if (should_print < 0) { \ - pre = jiffies; \ - break; \ - } \ - if (should_print-- > 0) { \ - UNF_PRINT_SFS(dbg_level, portid, data, size); \ - } \ - if (should_print == 0) { \ - printk( \ - KERN_INFO \ - "[FC_UNF]sfs log is limited[%s][%-5d]\n", \ - __func__, __LINE__); \ - } \ - pre = jiffies; \ - } \ - } while (0) - -#endif diff --git a/drivers/scsi/spfc/common/unf_lport.c b/drivers/scsi/spfc/common/unf_lport.c deleted file mode 100644 index 66d3ac14d676..000000000000 --- a/drivers/scsi/spfc/common/unf_lport.c +++ /dev/null @@ -1,1008 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#include "unf_lport.h" -#include "unf_log.h" -#include "unf_rport.h" -#include "unf_exchg.h" -#include "unf_service.h" -#include "unf_ls.h" -#include "unf_gs.h" -#include "unf_portman.h" - -static void unf_lport_config(struct unf_lport *lport); -void unf_cm_mark_dirty_mem(struct unf_lport *lport, enum unf_lport_dirty_flag type) -{ - FC_CHECK_RETURN_VOID((lport)); - - lport->dirty_flag |= (u32)type; -} - -u32 unf_init_lport_route(struct unf_lport *lport) -{ - u32 ret = RETURN_OK; - int ret_val = 0; - - FC_CHECK_RETURN_VALUE((lport), UNF_RETURN_ERROR); - - /* Init L_Port route work */ - INIT_DELAYED_WORK(&lport->route_timer_work, unf_lport_route_work); - - /* Delay route work */ - ret_val = queue_delayed_work(unf_wq, &lport->route_timer_work, - (ulong)msecs_to_jiffies(UNF_LPORT_POLL_TIMER)); - if (unlikely((!(bool)(ret_val)))) { - FC_DRV_PRINT(UNF_LOG_EQUIP_ATT, UNF_WARN, - "[warn]Port(0x%x) schedule route work failed", - lport->port_id); - - return UNF_RETURN_ERROR; - } - - ret = unf_lport_ref_inc(lport); - return ret; -} - -void unf_destroy_lport_route(struct unf_lport *lport) -{ - u32 ret = UNF_RETURN_ERROR; - - FC_CHECK_RETURN_VOID(lport); - - /* Cancel (route timer) delay work */ - UNF_DELAYED_WORK_SYNC(ret, (lport->port_id), (&lport->route_timer_work), - "Route Timer work"); - if (ret == RETURN_OK) - /* Corresponding to ADD operation */ - unf_lport_ref_dec(lport); - - lport->destroy_step = UNF_LPORT_DESTROY_STEP_2_CLOSE_ROUTE; -} - -void unf_init_port_parms(struct unf_lport *lport) -{ - INIT_LIST_HEAD(&lport->list_vports_head); - INIT_LIST_HEAD(&lport->list_intergrad_vports); - INIT_LIST_HEAD(&lport->list_destroy_vports); - INIT_LIST_HEAD(&lport->entry_lport); - INIT_LIST_HEAD(&lport->list_qos_head); - - spin_lock_init(&lport->qos_mgr_lock); - spin_lock_init(&lport->lport_state_lock); - - lport->max_frame_size = max_frame_size; - lport->ed_tov = UNF_DEFAULT_EDTOV; - lport->ra_tov = UNF_DEFAULT_RATOV; - lport->fabric_node_name = 0; - lport->qos_level = UNF_QOS_LEVEL_DEFAULT; - lport->qos_cs_ctrl = false; - lport->priority = (bool)UNF_PRIORITY_DISABLE; - lport->port_dirt_exchange = false; - - unf_lport_config(lport); - - unf_set_lport_state(lport, UNF_LPORT_ST_ONLINE); - - lport->link_up = UNF_PORT_LINK_DOWN; - lport->port_removing = false; - lport->lport_free_completion = NULL; - lport->last_tx_fault_jif = 0; - lport->enhanced_features = 0; - lport->destroy_step = INVALID_VALUE32; - lport->dirty_flag = 0; - lport->switch_state = false; - lport->bbscn_support = false; - lport->loop_back_test_mode = false; - lport->start_work_state = UNF_START_WORK_STOP; - lport->sfp_power_fault_count = 0; - lport->sfp_9545_fault_count = 0; - - atomic_set(&lport->lport_no_operate_flag, UNF_LPORT_NORMAL); - atomic_set(&lport->port_ref_cnt, 0); - atomic_set(&lport->scsi_session_add_success, 0); - atomic_set(&lport->scsi_session_add_failed, 0); - atomic_set(&lport->scsi_session_del_success, 0); - atomic_set(&lport->scsi_session_del_failed, 0); - atomic_set(&lport->add_start_work_failed, 0); - atomic_set(&lport->add_closing_work_failed, 0); - atomic_set(&lport->alloc_scsi_id, 0); - atomic_set(&lport->resume_scsi_id, 0); - atomic_set(&lport->reuse_scsi_id, 0); - atomic_set(&lport->device_alloc, 0); - atomic_set(&lport->device_destroy, 0); - atomic_set(&lport->session_loss_tmo, 0); - atomic_set(&lport->host_no, 0); - atomic64_set(&lport->exchg_index, 0x1000); - atomic_inc(&lport->port_ref_cnt); - - memset(&lport->port_dynamic_info, 0, sizeof(struct unf_port_dynamic_info)); - memset(&lport->link_service_info, 0, sizeof(struct unf_link_service_collect)); - memset(&lport->err_code_sum, 0, sizeof(struct unf_err_code)); -} - -void unf_reset_lport_params(struct unf_lport *lport) -{ - struct unf_lport *unf_lport = lport; - - FC_CHECK_RETURN_VOID(lport); - - unf_lport->link_up = UNF_PORT_LINK_DOWN; - unf_lport->nport_id = 0; - unf_lport->max_frame_size = max_frame_size; - unf_lport->ed_tov = UNF_DEFAULT_EDTOV; - unf_lport->ra_tov = UNF_DEFAULT_RATOV; - unf_lport->fabric_node_name = 0; -} - -static enum unf_lport_login_state -unf_lport_state_online(enum unf_lport_login_state old_state, - enum unf_lport_event lport_event) -{ - enum unf_lport_login_state next_state = UNF_LPORT_ST_ONLINE; - - switch (lport_event) { - case UNF_EVENT_LPORT_LINK_UP: - next_state = UNF_LPORT_ST_LINK_UP; - break; - - case UNF_EVENT_LPORT_NORMAL_ENTER: - next_state = UNF_LPORT_ST_INITIAL; - break; - - default: - next_state = old_state; - break; - } - - return next_state; -} - -static enum unf_lport_login_state unf_lport_state_initial(enum unf_lport_login_state old_state, - enum unf_lport_event lport_event) -{ - enum unf_lport_login_state next_state = UNF_LPORT_ST_ONLINE; - - switch (lport_event) { - case UNF_EVENT_LPORT_LINK_UP: - next_state = UNF_LPORT_ST_LINK_UP; - break; - - default: - next_state = old_state; - break; - } - - return next_state; -} - -static enum unf_lport_login_state unf_lport_state_linkup(enum unf_lport_login_state old_state, - enum unf_lport_event lport_event) -{ - enum unf_lport_login_state next_state = UNF_LPORT_ST_ONLINE; - - switch (lport_event) { - case UNF_EVENT_LPORT_NORMAL_ENTER: - next_state = UNF_LPORT_ST_FLOGI_WAIT; - break; - - case UNF_EVENT_LPORT_READY: - next_state = UNF_LPORT_ST_READY; - break; - - case UNF_EVENT_LPORT_LINK_DOWN: - next_state = UNF_LPORT_ST_INITIAL; - break; - - default: - next_state = old_state; - break; - } - - return next_state; -} - -static enum unf_lport_login_state unf_lport_state_flogi_wait(enum unf_lport_login_state old_state, - enum unf_lport_event lport_event) -{ - enum unf_lport_login_state next_state = UNF_LPORT_ST_ONLINE; - - switch (lport_event) { - case UNF_EVENT_LPORT_REMOTE_ACC: - next_state = UNF_LPORT_ST_PLOGI_WAIT; - break; - - case UNF_EVENT_LPORT_READY: - next_state = UNF_LPORT_ST_READY; - break; - - case UNF_EVENT_LPORT_REMOTE_TIMEOUT: - next_state = UNF_LPORT_ST_LOGO; - break; - - case UNF_EVENT_LPORT_LINK_DOWN: - next_state = UNF_LPORT_ST_INITIAL; - break; - - default: - next_state = old_state; - break; - } - - return next_state; -} - -static enum unf_lport_login_state unf_lport_state_plogi_wait(enum unf_lport_login_state old_state, - enum unf_lport_event lport_event) -{ - enum unf_lport_login_state next_state = UNF_LPORT_ST_ONLINE; - - switch (lport_event) { - case UNF_EVENT_LPORT_REMOTE_ACC: - next_state = UNF_LPORT_ST_RFT_ID_WAIT; - break; - - case UNF_EVENT_LPORT_REMOTE_TIMEOUT: - next_state = UNF_LPORT_ST_LOGO; - break; - - case UNF_EVENT_LPORT_LINK_DOWN: - next_state = UNF_LPORT_ST_INITIAL; - break; - - default: - next_state = old_state; - break; - } - - return next_state; -} - -static enum unf_lport_login_state -unf_lport_state_rftid_wait(enum unf_lport_login_state old_state, - enum unf_lport_event lport_event) -{ - enum unf_lport_login_state next_state = UNF_LPORT_ST_ONLINE; - - switch (lport_event) { - case UNF_EVENT_LPORT_REMOTE_ACC: - next_state = UNF_LPORT_ST_RFF_ID_WAIT; - break; - - case UNF_EVENT_LPORT_REMOTE_TIMEOUT: - next_state = UNF_LPORT_ST_LOGO; - break; - - case UNF_EVENT_LPORT_LINK_DOWN: - next_state = UNF_LPORT_ST_INITIAL; - break; - - default: - next_state = old_state; - break; - } - - return next_state; -} - -static enum unf_lport_login_state unf_lport_state_rffid_wait(enum unf_lport_login_state old_state, - enum unf_lport_event lport_event) -{ - enum unf_lport_login_state next_state = UNF_LPORT_ST_ONLINE; - - switch (lport_event) { - case UNF_EVENT_LPORT_REMOTE_ACC: - next_state = UNF_LPORT_ST_SCR_WAIT; - break; - - case UNF_EVENT_LPORT_REMOTE_TIMEOUT: - next_state = UNF_LPORT_ST_LOGO; - break; - - case UNF_EVENT_LPORT_LINK_DOWN: - next_state = UNF_LPORT_ST_INITIAL; - break; - - default: - next_state = old_state; - break; - } - - return next_state; -} - -static enum unf_lport_login_state unf_lport_state_scr_wait(enum unf_lport_login_state old_state, - enum unf_lport_event lport_event) -{ - enum unf_lport_login_state next_state = UNF_LPORT_ST_ONLINE; - - switch (lport_event) { - case UNF_EVENT_LPORT_REMOTE_ACC: - next_state = UNF_LPORT_ST_READY; - break; - - case UNF_EVENT_LPORT_REMOTE_TIMEOUT: - next_state = UNF_LPORT_ST_LOGO; - break; - - case UNF_EVENT_LPORT_LINK_DOWN: - next_state = UNF_LPORT_ST_INITIAL; - break; - - default: - next_state = old_state; - break; - } - - return next_state; -} - -static enum unf_lport_login_state -unf_lport_state_logo(enum unf_lport_login_state old_state, - enum unf_lport_event lport_event) -{ - enum unf_lport_login_state next_state = UNF_LPORT_ST_ONLINE; - - switch (lport_event) { - case UNF_EVENT_LPORT_NORMAL_ENTER: - next_state = UNF_LPORT_ST_OFFLINE; - break; - - case UNF_EVENT_LPORT_LINK_DOWN: - next_state = UNF_LPORT_ST_INITIAL; - break; - - default: - next_state = old_state; - break; - } - - return next_state; -} - -static enum unf_lport_login_state unf_lport_state_offline(enum unf_lport_login_state old_state, - enum unf_lport_event lport_event) -{ - enum unf_lport_login_state next_state = UNF_LPORT_ST_ONLINE; - - switch (lport_event) { - case UNF_EVENT_LPORT_ONLINE: - next_state = UNF_LPORT_ST_ONLINE; - break; - - case UNF_EVENT_LPORT_RESET: - next_state = UNF_LPORT_ST_RESET; - break; - - case UNF_EVENT_LPORT_LINK_DOWN: - next_state = UNF_LPORT_ST_INITIAL; - break; - - default: - next_state = old_state; - break; - } - - return next_state; -} - -static enum unf_lport_login_state unf_lport_state_reset(enum unf_lport_login_state old_state, - enum unf_lport_event lport_event) -{ - enum unf_lport_login_state next_state = UNF_LPORT_ST_ONLINE; - - switch (lport_event) { - case UNF_EVENT_LPORT_NORMAL_ENTER: - next_state = UNF_LPORT_ST_INITIAL; - break; - - default: - next_state = old_state; - break; - } - - return next_state; -} - -static enum unf_lport_login_state unf_lport_state_ready(enum unf_lport_login_state old_state, - enum unf_lport_event lport_event) -{ - enum unf_lport_login_state next_state = UNF_LPORT_ST_ONLINE; - - switch (lport_event) { - case UNF_EVENT_LPORT_LINK_DOWN: - next_state = UNF_LPORT_ST_INITIAL; - break; - - case UNF_EVENT_LPORT_RESET: - next_state = UNF_LPORT_ST_RESET; - break; - - case UNF_EVENT_LPORT_OFFLINE: - next_state = UNF_LPORT_ST_LOGO; - break; - - default: - next_state = old_state; - break; - } - - return next_state; -} - -static struct unf_lport_state_ma lport_state[] = { - {UNF_LPORT_ST_ONLINE, unf_lport_state_online}, - {UNF_LPORT_ST_INITIAL, unf_lport_state_initial}, - {UNF_LPORT_ST_LINK_UP, unf_lport_state_linkup}, - {UNF_LPORT_ST_FLOGI_WAIT, unf_lport_state_flogi_wait}, - {UNF_LPORT_ST_PLOGI_WAIT, unf_lport_state_plogi_wait}, - {UNF_LPORT_ST_RFT_ID_WAIT, unf_lport_state_rftid_wait}, - {UNF_LPORT_ST_RFF_ID_WAIT, unf_lport_state_rffid_wait}, - {UNF_LPORT_ST_SCR_WAIT, unf_lport_state_scr_wait}, - {UNF_LPORT_ST_LOGO, unf_lport_state_logo}, - {UNF_LPORT_ST_OFFLINE, unf_lport_state_offline}, - {UNF_LPORT_ST_RESET, unf_lport_state_reset}, - {UNF_LPORT_ST_READY, unf_lport_state_ready}, -}; - -void unf_lport_state_ma(struct unf_lport *lport, - enum unf_lport_event lport_event) -{ - enum unf_lport_login_state old_state = UNF_LPORT_ST_ONLINE; - enum unf_lport_login_state next_state = UNF_LPORT_ST_ONLINE; - u32 index = 0; - - FC_CHECK_RETURN_VOID(lport); - - old_state = lport->states; - - while (index < (sizeof(lport_state) / sizeof(struct unf_lport_state_ma))) { - if (lport->states == lport_state[index].lport_state) { - next_state = lport_state[index].lport_state_ma(old_state, lport_event); - break; - } - index++; - } - - if (index >= (sizeof(lport_state) / sizeof(struct unf_lport_state_ma))) { - next_state = old_state; - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, - UNF_MAJOR, "[info]Port(0x%x) hold state(0x%x)", - lport->port_id, lport->states); - } - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "[info]Port(0x%x) with old state(0x%x) event(0x%x) next state(0x%x)", - lport->port_id, old_state, lport_event, next_state); - - unf_set_lport_state(lport, next_state); -} - -u32 unf_lport_retry_flogi(struct unf_lport *lport) -{ - struct unf_rport *unf_rport = NULL; - u32 ret = UNF_RETURN_ERROR; - ulong flag = 0; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - - /* Get (new) R_Port */ - unf_rport = unf_get_rport_by_nport_id(lport, UNF_FC_FID_FLOGI); - unf_rport = unf_get_safe_rport(lport, unf_rport, UNF_RPORT_REUSE_ONLY, UNF_FC_FID_FLOGI); - if (unlikely(!unf_rport)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, - UNF_WARN, "[warn]Port(0x%x) allocate RPort failed", - lport->port_id); - - return UNF_RETURN_ERROR; - } - - /* Check L_Port state */ - spin_lock_irqsave(&lport->lport_state_lock, flag); - if (lport->states != UNF_LPORT_ST_FLOGI_WAIT) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) no need to retry FLOGI with state(0x%x)", - lport->port_id, lport->states); - - spin_unlock_irqrestore(&lport->lport_state_lock, flag); - return RETURN_OK; - } - spin_unlock_irqrestore(&lport->lport_state_lock, flag); - - spin_lock_irqsave(&unf_rport->rport_state_lock, flag); - unf_rport->nport_id = UNF_FC_FID_FLOGI; - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flag); - - /* Send FLOGI or FDISC */ - if (lport->root_lport != lport) { - ret = unf_send_fdisc(lport, unf_rport); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]LOGIN: Port(0x%x) send FDISC failed", lport->port_id); - - /* Do L_Port recovery */ - unf_lport_error_recovery(lport); - } - } else { - ret = unf_send_flogi(lport, unf_rport); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]LOGIN: Port(0x%x) send FLOGI failed\n", lport->port_id); - - /* Do L_Port recovery */ - unf_lport_error_recovery(lport); - } - } - - return ret; -} - -u32 unf_lport_name_server_register(struct unf_lport *lport, - enum unf_lport_login_state state) -{ - struct unf_rport *unf_rport = NULL; - ulong flag = 0; - u32 ret = UNF_RETURN_ERROR; - u32 fabric_id = UNF_FC_FID_DIR_SERV; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - - if (state == UNF_LPORT_ST_SCR_WAIT) - fabric_id = UNF_FC_FID_FCTRL; - - /* Get (safe) R_Port */ - unf_rport = - unf_get_rport_by_nport_id(lport, fabric_id); - unf_rport = unf_get_safe_rport(lport, unf_rport, UNF_RPORT_REUSE_ONLY, - fabric_id); - if (!unf_rport) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, - UNF_WARN, "[warn]Port(0x%x) allocate RPort failed", - lport->port_id); - - return UNF_RETURN_ERROR; - } - - /* Update R_Port & L_Port state */ - spin_lock_irqsave(&unf_rport->rport_state_lock, flag); - unf_rport->nport_id = fabric_id; - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flag); - - spin_lock_irqsave(&lport->lport_state_lock, flag); - unf_lport_state_ma(lport, UNF_EVENT_LPORT_NORMAL_ENTER); - spin_unlock_irqrestore(&lport->lport_state_lock, flag); - - switch (state) { - /* RFT_ID */ - case UNF_LPORT_ST_RFT_ID_WAIT: - ret = unf_send_rft_id(lport, unf_rport); - break; - /* RFF_ID */ - case UNF_LPORT_ST_RFF_ID_WAIT: - ret = unf_send_rff_id(lport, unf_rport, UNF_FC4_FCP_TYPE); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]LOGIN: Port(0x%x) register SCSI FC4Type to fabric(0xfffffc) failed", - lport->nport_id); - unf_lport_error_recovery(lport); - } - break; - - /* SCR */ - case UNF_LPORT_ST_SCR_WAIT: - ret = unf_send_scr(lport, unf_rport); - break; - - /* PLOGI */ - case UNF_LPORT_ST_PLOGI_WAIT: - default: - spin_lock_irqsave(&unf_rport->rport_state_lock, flag); - unf_rport_state_ma(unf_rport, UNF_EVENT_RPORT_ENTER_PLOGI); - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flag); - - ret = unf_send_plogi(lport, unf_rport); - break; - } - - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]LOGIN: Port(0x%x) register fabric(0xfffffc) failed", - lport->nport_id); - - /* Do L_Port recovery */ - unf_lport_error_recovery(lport); - } - - return ret; -} - -u32 unf_lport_enter_sns_logo(struct unf_lport *lport, struct unf_rport *rport) -{ - struct unf_rport *unf_rport = NULL; - ulong flag = 0; - u32 ret = UNF_RETURN_ERROR; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - - if (!rport) - unf_rport = unf_get_rport_by_nport_id(lport, UNF_FC_FID_DIR_SERV); - else - unf_rport = rport; - - if (!unf_rport) { - spin_lock_irqsave(&lport->lport_state_lock, flag); - unf_lport_state_ma(lport, UNF_EVENT_LPORT_NORMAL_ENTER); - spin_unlock_irqrestore(&lport->lport_state_lock, flag); - - return RETURN_OK; - } - - /* Update L_Port & R_Port state */ - spin_lock_irqsave(&lport->lport_state_lock, flag); - unf_lport_state_ma(lport, UNF_EVENT_LPORT_NORMAL_ENTER); - spin_unlock_irqrestore(&lport->lport_state_lock, flag); - - spin_lock_irqsave(&unf_rport->rport_state_lock, flag); - unf_rport_state_ma(unf_rport, UNF_EVENT_RPORT_LOGO); - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flag); - - /* Do R_Port LOGO state */ - unf_rport_enter_logo(lport, unf_rport); - - return ret; -} - -void unf_lport_enter_sns_plogi(struct unf_lport *lport) -{ - /* Fabric or Public Loop Mode: Login with Name server */ - struct unf_lport *unf_lport = lport; - struct unf_rport *unf_rport = NULL; - ulong flag = 0; - u32 ret = UNF_RETURN_ERROR; - - FC_CHECK_RETURN_VOID(lport); - - /* Get (safe) R_Port */ - unf_rport = unf_get_rport_by_nport_id(unf_lport, UNF_FC_FID_DIR_SERV); - if (unf_rport) { - /* for port swap: Delete old R_Port if necessary */ - if (unf_rport->local_nport_id != lport->nport_id) { - unf_rport_immediate_link_down(lport, unf_rport); - unf_rport = NULL; - } - } - - unf_rport = unf_get_safe_rport(lport, unf_rport, UNF_RPORT_REUSE_ONLY, - UNF_FC_FID_DIR_SERV); - if (!unf_rport) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, - UNF_WARN, "[warn]Port(0x%x) allocate RPort failed", - lport->port_id); - - unf_lport_error_recovery(unf_lport); - return; - } - - spin_lock_irqsave(&unf_rport->rport_state_lock, flag); - unf_rport->nport_id = UNF_FC_FID_DIR_SERV; - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flag); - - /* Send PLOGI to Fabric(0xfffffc) */ - ret = unf_send_plogi(unf_lport, unf_rport); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]LOGIN: Port(0x%x) send PLOGI to name server failed", - lport->port_id); - - unf_lport_error_recovery(unf_lport); - } -} - -int unf_get_port_params(void *arg_in, void *arg_out) -{ - struct unf_lport *unf_lport = (struct unf_lport *)arg_in; - struct unf_low_level_port_mgr_op *port_mgr = NULL; - struct unf_port_param port_params = {0}; - - FC_CHECK_RETURN_VALUE(arg_in, UNF_RETURN_ERROR); - - port_mgr = &unf_lport->low_level_func.port_mgr_op; - if (!port_mgr->ll_port_config_get) { - FC_DRV_PRINT(UNF_LOG_EQUIP_ATT, UNF_WARN, - "[warn]Port(0x%x) low level port_config_get function is NULL", - unf_lport->port_id); - - return UNF_RETURN_ERROR; - } - - FC_DRV_PRINT(UNF_LOG_EQUIP_ATT, UNF_INFO, - "[warn]Port(0x%x) get parameters with default:R_A_TOV(%d) E_D_TOV(%d)", - unf_lport->port_id, UNF_DEFAULT_FABRIC_RATOV, - UNF_DEFAULT_EDTOV); - - port_params.ra_tov = UNF_DEFAULT_FABRIC_RATOV; - port_params.ed_tov = UNF_DEFAULT_EDTOV; - - /* Update parameters with Fabric mode */ - if (unf_lport->act_topo == UNF_ACT_TOP_PUBLIC_LOOP || - unf_lport->act_topo == UNF_ACT_TOP_P2P_FABRIC) { - unf_lport->ra_tov = port_params.ra_tov; - unf_lport->ed_tov = port_params.ed_tov; - } - - return RETURN_OK; -} - -u32 unf_lport_enter_flogi(struct unf_lport *lport) -{ - struct unf_rport *unf_rport = NULL; - struct unf_cm_event_report *event = NULL; - ulong flag = 0; - u32 ret = UNF_RETURN_ERROR; - u32 nport_id = 0; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - - /* Get (safe) R_Port */ - nport_id = UNF_FC_FID_FLOGI; - unf_rport = unf_get_rport_by_nport_id(lport, UNF_FC_FID_FLOGI); - - unf_rport = unf_get_safe_rport(lport, unf_rport, UNF_RPORT_REUSE_ONLY, nport_id); - if (!unf_rport) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) allocate RPort failed", - lport->port_id); - - return UNF_RETURN_ERROR; - } - - /* Updtae L_Port state */ - spin_lock_irqsave(&lport->lport_state_lock, flag); - unf_lport_state_ma(lport, UNF_EVENT_LPORT_NORMAL_ENTER); - spin_unlock_irqrestore(&lport->lport_state_lock, flag); - - /* Update R_Port N_Port_ID */ - spin_lock_irqsave(&unf_rport->rport_state_lock, flag); - unf_rport->nport_id = UNF_FC_FID_FLOGI; - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flag); - - event = unf_get_one_event_node(lport); - if (event) { - event->lport = lport; - event->event_asy_flag = UNF_EVENT_ASYN; - event->unf_event_task = unf_get_port_params; - event->para_in = (void *)lport; - unf_post_one_event_node(lport, event); - } - - if (lport->root_lport != lport) { - /* for NPIV */ - ret = unf_send_fdisc(lport, unf_rport); - if (ret != RETURN_OK) - unf_lport_error_recovery(lport); - } else { - /* for Physical Port */ - ret = unf_send_flogi(lport, unf_rport); - if (ret != RETURN_OK) - unf_lport_error_recovery(lport); - } - - return ret; -} - -void unf_set_lport_state(struct unf_lport *lport, enum unf_lport_login_state state) -{ - FC_CHECK_RETURN_VOID(lport); - if (lport->states != state) - lport->retries = 0; - - lport->states = state; -} - -static void unf_lport_timeout(struct work_struct *work) -{ - struct unf_lport *unf_lport = NULL; - enum unf_lport_login_state state = UNF_LPORT_ST_READY; - ulong flag = 0; - - FC_CHECK_RETURN_VOID(work); - unf_lport = container_of(work, struct unf_lport, retry_work.work); - spin_lock_irqsave(&unf_lport->lport_state_lock, flag); - state = unf_lport->states; - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) is timeout with state(0x%x)", - unf_lport->port_id, state); - spin_unlock_irqrestore(&unf_lport->lport_state_lock, flag); - - switch (state) { - /* FLOGI retry */ - case UNF_LPORT_ST_FLOGI_WAIT: - (void)unf_lport_retry_flogi(unf_lport); - break; - - case UNF_LPORT_ST_PLOGI_WAIT: - case UNF_LPORT_ST_RFT_ID_WAIT: - case UNF_LPORT_ST_RFF_ID_WAIT: - case UNF_LPORT_ST_SCR_WAIT: - (void)unf_lport_name_server_register(unf_lport, state); - break; - - /* Send LOGO External */ - case UNF_LPORT_ST_LOGO: - break; - - /* Do nothing */ - case UNF_LPORT_ST_OFFLINE: - case UNF_LPORT_ST_READY: - case UNF_LPORT_ST_RESET: - case UNF_LPORT_ST_ONLINE: - case UNF_LPORT_ST_INITIAL: - case UNF_LPORT_ST_LINK_UP: - - unf_lport->retries = 0; - break; - default: - break; - } - - unf_lport_ref_dec_to_destroy(unf_lport); -} - -static void unf_lport_config(struct unf_lport *lport) -{ - FC_CHECK_RETURN_VOID(lport); - - INIT_DELAYED_WORK(&lport->retry_work, unf_lport_timeout); - - lport->max_retry_count = UNF_MAX_RETRY_COUNT; - lport->retries = 0; -} - -void unf_lport_error_recovery(struct unf_lport *lport) -{ - ulong delay = 0; - ulong flag = 0; - int ret_val = 0; - u32 ret = UNF_RETURN_ERROR; - - FC_CHECK_RETURN_VOID(lport); - - ret = unf_lport_ref_inc(lport); - if (unlikely(ret != RETURN_OK)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) is removing and no need process", - lport->port_id); - return; - } - - spin_lock_irqsave(&lport->lport_state_lock, flag); - - /* Port State: removing */ - if (lport->port_removing) { - spin_unlock_irqrestore(&lport->lport_state_lock, flag); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) is removing and no need process", - lport->port_id); - - unf_lport_ref_dec_to_destroy(lport); - return; - } - - /* Port State: offline */ - if (lport->states == UNF_LPORT_ST_OFFLINE) { - spin_unlock_irqrestore(&lport->lport_state_lock, flag); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) is offline and no need process", - lport->port_id); - - unf_lport_ref_dec_to_destroy(lport); - return; - } - - /* Queue work state check */ - if (delayed_work_pending(&lport->retry_work)) { - spin_unlock_irqrestore(&lport->lport_state_lock, flag); - - unf_lport_ref_dec_to_destroy(lport); - return; - } - - /* Do retry operation */ - if (lport->retries < lport->max_retry_count) { - lport->retries++; - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x_0x%x) enter recovery and retry %u times", - lport->port_id, lport->nport_id, lport->retries); - - delay = (ulong)lport->ed_tov; - ret_val = queue_delayed_work(unf_wq, &lport->retry_work, - (ulong)msecs_to_jiffies((u32)delay)); - if (ret_val != 0) { - atomic_inc(&lport->port_ref_cnt); - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x) queue work success and reference count is %d", - lport->port_id, - atomic_read(&lport->port_ref_cnt)); - } - spin_unlock_irqrestore(&lport->lport_state_lock, flag); - } else { - unf_lport_state_ma(lport, UNF_EVENT_LPORT_REMOTE_TIMEOUT); - spin_unlock_irqrestore(&lport->lport_state_lock, flag); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) register operation timeout and do LOGO", - lport->port_id); - - (void)unf_lport_enter_sns_logo(lport, NULL); - } - - unf_lport_ref_dec_to_destroy(lport); -} - -struct unf_lport *unf_cm_lookup_vport_by_vp_index(struct unf_lport *lport, u16 vp_index) -{ - FC_CHECK_RETURN_VALUE(lport, NULL); - - if (vp_index == 0) - return lport; - - if (!lport->lport_mgr_temp.unf_look_up_vport_by_index) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Port(0x%x) function do look up vport by index is NULL", - lport->port_id); - - return NULL; - } - - return lport->lport_mgr_temp.unf_look_up_vport_by_index(lport, vp_index); -} - -struct unf_lport *unf_cm_lookup_vport_by_did(struct unf_lport *lport, u32 did) -{ - FC_CHECK_RETURN_VALUE(lport, NULL); - - if (!lport->lport_mgr_temp.unf_look_up_vport_by_did) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Port(0x%x) function do look up vport by D_ID is NULL", - lport->port_id); - - return NULL; - } - - return lport->lport_mgr_temp.unf_look_up_vport_by_did(lport, did); -} - -struct unf_lport *unf_cm_lookup_vport_by_wwpn(struct unf_lport *lport, u64 wwpn) -{ - FC_CHECK_RETURN_VALUE(lport, NULL); - - if (!lport->lport_mgr_temp.unf_look_up_vport_by_wwpn) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Port(0x%x) function do look up vport by WWPN is NULL", - lport->port_id); - - return NULL; - } - - return lport->lport_mgr_temp.unf_look_up_vport_by_wwpn(lport, wwpn); -} - -void unf_cm_vport_remove(struct unf_lport *vport) -{ - struct unf_lport *unf_lport = NULL; - - FC_CHECK_RETURN_VOID(vport); - unf_lport = vport->root_lport; - FC_CHECK_RETURN_VOID(unf_lport); - - if (!unf_lport->lport_mgr_temp.unf_vport_remove) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Port(0x%x) function do vport remove is NULL", - unf_lport->port_id); - return; - } - - unf_lport->lport_mgr_temp.unf_vport_remove(vport); -} diff --git a/drivers/scsi/spfc/common/unf_lport.h b/drivers/scsi/spfc/common/unf_lport.h deleted file mode 100644 index dbd531f15b13..000000000000 --- a/drivers/scsi/spfc/common/unf_lport.h +++ /dev/null @@ -1,519 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef UNF_LPORT_H -#define UNF_LPORT_H - -#include "unf_type.h" -#include "unf_disc.h" -#include "unf_event.h" -#include "unf_common.h" - -#define UNF_PORT_TYPE_FC 0 -#define UNF_PORT_TYPE_DISC 1 -#define UNF_FW_UPDATE_PATH_LEN_MAX 255 -#define UNF_EXCHG_MGR_NUM (4) -#define UNF_ERR_CODE_PRINT_TIME 10 /* error code print times */ -#define UNF_MAX_IO_TYPE_STAT_NUM 48 /* IO abnormal max counter */ -#define UNF_MAX_IO_RETURN_VALUE 0x12 -#define UNF_MAX_SCSI_CMD 0xFF -#define UNF_MAX_LPRT_SCSI_ID_MAP 2048 - -enum unf_scsi_error_handle_type { - UNF_SCSI_ABORT_IO_TYPE = 0, - UNF_SCSI_DEVICE_RESET_TYPE, - UNF_SCSI_TARGET_RESET_TYPE, - UNF_SCSI_BUS_RESET_TYPE, - UNF_SCSI_HOST_RESET_TYPE, - UNF_SCSI_VIRTUAL_RESET_TYPE, - UNF_SCSI_ERROR_HANDLE_BUTT -}; - -enum unf_lport_destroy_step { - UNF_LPORT_DESTROY_STEP_0_SET_REMOVING = 0, - UNF_LPORT_DESTROY_STEP_1_REPORT_PORT_OUT, - UNF_LPORT_DESTROY_STEP_2_CLOSE_ROUTE, - UNF_LPORT_DESTROY_STEP_3_DESTROY_EVENT_CENTER, - UNF_LPORT_DESTROY_STEP_4_DESTROY_EXCH_MGR, - UNF_LPORT_DESTROY_STEP_5_DESTROY_ESGL_POOL, - UNF_LPORT_DESTROY_STEP_6_DESTROY_DISC_MGR, - UNF_LPORT_DESTROY_STEP_7_DESTROY_XCHG_MGR_TMP, - UNF_LPORT_DESTROY_STEP_8_DESTROY_RPORT_MG_TMP, - UNF_LPORT_DESTROY_STEP_9_DESTROY_LPORT_MG_TMP, - UNF_LPORT_DESTROY_STEP_10_DESTROY_SCSI_TABLE, - UNF_LPORT_DESTROY_STEP_11_UNREG_TGT_HOST, - UNF_LPORT_DESTROY_STEP_12_UNREG_SCSI_HOST, - UNF_LPORT_DESTROY_STEP_13_DESTROY_LW_INTERFACE, - UNF_LPORT_DESTROY_STEP_BUTT -}; - -enum unf_lport_enhanced_feature { - /* Enhance GFF feature connect even if fail to get GFF feature */ - UNF_LPORT_ENHANCED_FEATURE_ENHANCED_GFF = 0x0001, - UNF_LPORT_ENHANCED_FEATURE_IO_TRANSFERLIST = 0x0002, /* Enhance IO balance */ - UNF_LPORT_ENHANCED_FEATURE_IO_CHECKPOINT = 0x0004, /* Enhance IO check */ - UNF_LPORT_ENHANCED_FEATURE_CLOSE_FW_ROUTE = 0x0008, /* Close FW ROUTE */ - /* lowest frequency read SFP information */ - UNF_LPORT_ENHANCED_FEATURE_READ_SFP_ONCE = 0x0010, - UNF_LPORT_ENHANCED_FEATURE_BUTT -}; - -enum unf_lport_login_state { - UNF_LPORT_ST_ONLINE = 0x2000, /* uninitialized */ - UNF_LPORT_ST_INITIAL, /* initialized and LinkDown */ - UNF_LPORT_ST_LINK_UP, /* initialized and Link UP */ - UNF_LPORT_ST_FLOGI_WAIT, /* waiting for FLOGI completion */ - UNF_LPORT_ST_PLOGI_WAIT, /* waiting for PLOGI completion */ - UNF_LPORT_ST_RNN_ID_WAIT, /* waiting for RNN_ID completion */ - UNF_LPORT_ST_RSNN_NN_WAIT, /* waiting for RSNN_NN completion */ - UNF_LPORT_ST_RSPN_ID_WAIT, /* waiting for RSPN_ID completion */ - UNF_LPORT_ST_RPN_ID_WAIT, /* waiting for RPN_ID completion */ - UNF_LPORT_ST_RFT_ID_WAIT, /* waiting for RFT_ID completion */ - UNF_LPORT_ST_RFF_ID_WAIT, /* waiting for RFF_ID completion */ - UNF_LPORT_ST_SCR_WAIT, /* waiting for SCR completion */ - UNF_LPORT_ST_READY, /* ready for use */ - UNF_LPORT_ST_LOGO, /* waiting for LOGO completion */ - UNF_LPORT_ST_RESET, /* being reset and will restart */ - UNF_LPORT_ST_OFFLINE, /* offline */ - UNF_LPORT_ST_BUTT -}; - -enum unf_lport_event { - UNF_EVENT_LPORT_NORMAL_ENTER = 0x8000, /* next state enter */ - UNF_EVENT_LPORT_ONLINE = 0x8001, /* LPort link up */ - UNF_EVENT_LPORT_LINK_UP = 0x8002, /* LPort link up */ - UNF_EVENT_LPORT_LINK_DOWN = 0x8003, /* LPort link down */ - UNF_EVENT_LPORT_OFFLINE = 0x8004, /* lPort bing stopped */ - UNF_EVENT_LPORT_RESET = 0x8005, - UNF_EVENT_LPORT_REMOTE_ACC = 0x8006, /* next state enter */ - UNF_EVENT_LPORT_REMOTE_RJT = 0x8007, /* rport reject */ - UNF_EVENT_LPORT_REMOTE_TIMEOUT = 0x8008, /* rport time out */ - UNF_EVENT_LPORT_READY = 0x8009, - UNF_EVENT_LPORT_REMOTE_BUTT -}; - -struct unf_cm_disc_mg_template { - /* start input:L_Port,return:ok/fail */ - u32 (*unf_disc_start)(void *lport); - /* stop input: L_Port,return:ok/fail */ - u32 (*unf_disc_stop)(void *lport); - - /* Callback after disc complete[with event:ok/fail]. */ - void (*unf_disc_callback)(void *lport, u32 result); -}; - -struct unf_chip_manage_info { - struct list_head list_chip_thread_entry; - struct list_head list_head; - spinlock_t chip_event_list_lock; - struct task_struct *thread; - u32 list_num; - u32 slot_id; - u8 chip_id; - u8 rsv; - u8 sfp_9545_fault; - u8 sfp_power_fault; - atomic_t ref_cnt; - u32 thread_exit; - struct unf_chip_info chip_info; - atomic_t card_loop_test_flag; - spinlock_t card_loop_back_state_lock; - char update_path[UNF_FW_UPDATE_PATH_LEN_MAX]; -}; - -enum unf_timer_type { - UNF_TIMER_TYPE_TGT_IO, - UNF_TIMER_TYPE_INI_IO, - UNF_TIMER_TYPE_REQ_IO, - UNF_TIMER_TYPE_TGT_RRQ, - UNF_TIMER_TYPE_INI_RRQ, - UNF_TIMER_TYPE_SFS, - UNF_TIMER_TYPE_INI_ABTS -}; - -struct unf_cm_xchg_mgr_template { - void *(*unf_xchg_get_free_and_init)(void *lport, u32 xchg_type); - void *(*unf_look_up_xchg_by_id)(void *lport, u16 ox_id, u32 oid); - void *(*unf_look_up_xchg_by_tag)(void *lport, u16 hot_pool_tag); - void (*unf_xchg_release)(void *lport, void *xchg); - void (*unf_xchg_mgr_io_xchg_abort)(void *lport, void *rport, u32 sid, u32 did, - u32 extra_io_state); - void (*unf_xchg_mgr_sfs_xchg_abort)(void *lport, void *rport, u32 sid, u32 did); - void (*unf_xchg_add_timer)(void *xchg, ulong time_ms, enum unf_timer_type time_type); - void (*unf_xchg_cancel_timer)(void *xchg); - void (*unf_xchg_abort_all_io)(void *lport, u32 xchg_type, bool clean); - void *(*unf_look_up_xchg_by_cmnd_sn)(void *lport, u64 command_sn, - u32 world_id, void *pinitiator); - void (*unf_xchg_abort_by_lun)(void *lport, void *rport, u64 lun_id, void *xchg, - bool abort_all_lun_flag); - - void (*unf_xchg_abort_by_session)(void *lport, void *rport); -}; - -struct unf_cm_lport_template { - void *(*unf_look_up_vport_by_index)(void *lport, u16 vp_index); - void *(*unf_look_up_vport_by_port_id)(void *lport, u32 port_id); - void *(*unf_look_up_vport_by_wwpn)(void *lport, u64 wwpn); - void *(*unf_look_up_vport_by_did)(void *lport, u32 did); - void (*unf_vport_remove)(void *vport); -}; - -struct unf_lport_state_ma { - enum unf_lport_login_state lport_state; - enum unf_lport_login_state (*lport_state_ma)(enum unf_lport_login_state old_state, - enum unf_lport_event event); -}; - -struct unf_rport_pool { - u32 rport_pool_count; - void *rport_pool_add; - struct list_head list_rports_pool; - spinlock_t rport_free_pool_lock; - /* for synchronous reuse RPort POOL completion */ - struct completion *rport_pool_completion; - ulong *rpi_bitmap; -}; - -struct unf_vport_pool { - u16 vport_pool_count; - void *vport_pool_addr; - struct list_head list_vport_pool; - spinlock_t vport_pool_lock; - struct completion *vport_pool_completion; - u16 slab_next_index; /* Next free vport */ - u16 slab_total_sum; /* Total Vport num */ - struct unf_lport *vport_slab[ARRAY_INDEX_0]; -}; - -struct unf_esgl_pool { - u32 esgl_pool_count; - void *esgl_pool_addr; - struct list_head list_esgl_pool; - spinlock_t esgl_pool_lock; - struct buf_describe esgl_buff_list; -}; - -/* little endium */ -struct unf_port_id_page { - struct list_head list_node_rscn; - u8 port_id_port; - u8 port_id_area; - u8 port_id_domain; - u8 addr_format : 2; - u8 event_qualifier : 4; - u8 reserved : 2; -}; - -struct unf_rscn_mgr { - spinlock_t rscn_id_list_lock; - u32 free_rscn_count; - struct list_head list_free_rscn_page; - struct list_head list_using_rscn_page; - void *rscn_pool_add; - struct unf_port_id_page *(*unf_get_free_rscn_node)(void *rscn_mg); - void (*unf_release_rscn_node)(void *rscn_mg, void *rscn_node); -}; - -struct unf_disc_rport_mg { - void *disc_pool_add; - struct list_head list_disc_rports_pool; - struct list_head list_disc_rports_busy; -}; - -struct unf_disc_manage_info { - struct list_head list_head; - spinlock_t disc_event_list_lock; - atomic_t disc_contrl_size; - - u32 thread_exit; - struct task_struct *thread; -}; - -struct unf_disc { - u32 retry_count; - u32 max_retry_count; - u32 disc_flag; - - struct completion *disc_completion; - atomic_t disc_ref_cnt; - - struct list_head list_busy_rports; - struct list_head list_delete_rports; - struct list_head list_destroy_rports; - - spinlock_t rport_busy_pool_lock; - - struct unf_lport *lport; - enum unf_disc_state states; - struct delayed_work disc_work; - - /* Disc operation template */ - struct unf_cm_disc_mg_template disc_temp; - - /* UNF_INIT_DISC/UNF_RSCN_DISC */ - u32 disc_option; - - /* RSCN list */ - struct unf_rscn_mgr rscn_mgr; - struct unf_disc_rport_mg disc_rport_mgr; - struct unf_disc_manage_info disc_thread_info; - - u64 last_disc_jiff; -}; - -enum unf_service_item { - UNF_SERVICE_ITEM_FLOGI = 0, - UNF_SERVICE_ITEM_PLOGI, - UNF_SERVICE_ITEM_PRLI, - UNF_SERVICE_ITEM_RSCN, - UNF_SERVICE_ITEM_ABTS, - UNF_SERVICE_ITEM_PDISC, - UNF_SERVICE_ITEM_ADISC, - UNF_SERVICE_ITEM_LOGO, - UNF_SERVICE_ITEM_SRR, - UNF_SERVICE_ITEM_RRQ, - UNF_SERVICE_ITEM_ECHO, - UNF_SERVICE_BUTT -}; - -/* Link service counter */ -struct unf_link_service_collect { - u64 service_cnt[UNF_SERVICE_BUTT]; -}; - -struct unf_pcie_error_count { - u32 pcie_error_count[UNF_PCIE_BUTT]; -}; - -#define INVALID_WWPN 0 - -enum unf_device_scsi_state { - UNF_SCSI_ST_INIT = 0, - UNF_SCSI_ST_OFFLINE, - UNF_SCSI_ST_ONLINE, - UNF_SCSI_ST_DEAD, - UNF_SCSI_ST_BUTT -}; - -struct unf_wwpn_dfx_counter_info { - atomic64_t io_done_cnt[UNF_MAX_IO_RETURN_VALUE]; - atomic64_t scsi_cmd_cnt[UNF_MAX_SCSI_CMD]; - atomic64_t target_busy; - atomic64_t host_busy; - atomic_t error_handle[UNF_SCSI_ERROR_HANDLE_BUTT]; - atomic_t error_handle_result[UNF_SCSI_ERROR_HANDLE_BUTT]; - atomic_t device_alloc; - atomic_t device_destroy; -}; - -#define UNF_MAX_LUN_PER_TARGET 256 -struct unf_wwpn_rport_info { - u64 wwpn; - struct unf_rport *rport; /* Rport which linkup */ - void *lport; /* Lport */ - u32 target_id; /* target_id distribute by scsi */ - u32 las_ten_scsi_state; - atomic_t scsi_state; - struct unf_wwpn_dfx_counter_info *dfx_counter; - struct delayed_work loss_tmo_work; - bool need_scan; - struct list_head fc_lun_list; - u8 *lun_qos_level; -}; - -struct unf_rport_scsi_id_image { - spinlock_t scsi_image_table_lock; - struct unf_wwpn_rport_info - *wwn_rport_info_table; - u32 max_scsi_id; -}; - -enum unf_lport_dirty_flag { - UNF_LPORT_DIRTY_FLAG_NONE = 0, - UNF_LPORT_DIRTY_FLAG_XCHGMGR_DIRTY = 0x100, - UNF_LPORT_DIRTY_FLAG_RPORT_POOL_DIRTY = 0x200, - UNF_LPORT_DIRTY_FLAG_DISC_DIRTY = 0x400, - UNF_LPORT_DIRTY_FLAG_BUTT -}; - -typedef struct unf_rport *(*unf_rport_set_qualifier)(struct unf_lport *lport, - struct unf_rport *rport_by_nport_id, - struct unf_rport *rport_by_wwpn, - u64 wwpn, u32 sid); - -typedef u32 (*unf_tmf_status_recovery)(void *rport, void *xchg); - -enum unf_start_work_state { - UNF_START_WORK_STOP, - UNF_START_WORK_BEGIN, - UNF_START_WORK_COMPLETE -}; - -struct unf_qos_info { - u64 wwpn; - u32 nport_id; - enum unf_rport_qos_level qos_level; - struct list_head entry_qos_info; -}; - -struct unf_ini_private_info { - u32 driver_type; /* Driver Type */ - void *lower; /* driver private pointer */ -}; - -struct unf_product_host_info { - void *tgt_host; - struct Scsi_Host *host; - struct unf_ini_private_info drv_private_info; - struct Scsi_Host scsihost; -}; - -struct unf_lport { - u32 port_type; /* Port Type, fc or fcoe */ - atomic_t port_ref_cnt; /* LPort reference counter */ - void *fc_port; /* hard adapter hba pointer */ - void *rport, *drport; /* Used for SCSI interface */ - void *vport; - ulong system_io_bus_num; - - struct unf_product_host_info host_info; /* scsi host mg */ - struct unf_rport_scsi_id_image rport_scsi_table; - bool port_removing; - bool io_allowed; - bool port_dirt_exchange; - - spinlock_t xchg_mgr_lock; - struct list_head list_xchg_mgr_head; - struct list_head list_drty_xchg_mgr_head; - void *xchg_mgr[UNF_EXCHG_MGR_NUM]; - bool qos_cs_ctrl; - bool priority; - enum unf_rport_qos_level qos_level; - spinlock_t qos_mgr_lock; - struct list_head list_qos_head; - struct list_head list_vports_head; /* Vport Mg */ - struct list_head list_intergrad_vports; /* Vport intergrad list */ - struct list_head list_destroy_vports; /* Vport destroy list */ - - struct list_head entry_vport; /* VPort entry, hook in list_vports_head */ - - struct list_head entry_lport; /* LPort entry */ - spinlock_t lport_state_lock; /* UL Port Lock */ - struct unf_disc disc; /* Disc and rport Mg */ - struct unf_rport_pool rport_pool; /* rport pool,Vport share Lport pool */ - struct unf_esgl_pool esgl_pool; /* external sgl pool */ - u32 port_id; /* Port Management ,0x11000 etc. */ - enum unf_lport_login_state states; - u32 link_up; - u32 speed; - - u64 node_name; - u64 port_name; - u64 fabric_node_name; - u32 nport_id; - u32 max_frame_size; - u32 ed_tov; - u32 ra_tov; - u32 class_of_service; - u32 options; /* ini or tgt */ - u32 retries; - u32 max_retry_count; - enum unf_act_topo act_topo; - bool switch_state; /* TRUE---->ON,false---->OFF */ - bool last_switch_state; /* TRUE---->ON,false---->OFF */ - bool bbscn_support; /* TRUE---->ON,false---->OFF */ - - enum unf_start_work_state start_work_state; - struct unf_cm_xchg_mgr_template xchg_mgr_temp; /* Xchg Mg operation template */ - struct unf_cm_lport_template lport_mgr_temp; /* Xchg LPort operation template */ - struct unf_low_level_functioon_op low_level_func; - struct unf_event_mgr event_mgr; /* Disc and rport Mg */ - struct delayed_work retry_work; /* poll work or delay work */ - - struct workqueue_struct *link_event_wq; - struct workqueue_struct *xchg_wq; - atomic64_t io_stat[UNF_MAX_IO_TYPE_STAT_NUM]; - struct unf_err_code err_code_sum; /* Error code counter */ - struct unf_port_dynamic_info port_dynamic_info; - struct unf_link_service_collect link_service_info; - struct unf_pcie_error_count pcie_error_cnt; - unf_rport_set_qualifier unf_qualify_rport; /* Qualify Rport */ - - unf_tmf_status_recovery unf_tmf_abnormal_recovery; /* tmf marker recovery */ - - struct delayed_work route_timer_work; /* L_Port timer route */ - - u16 vp_index; /* Vport Index, Lport:0 */ - u16 path_id; - struct unf_vport_pool *vport_pool; /* Only for Lport */ - void *lport_mgr[UNF_MAX_LPRT_SCSI_ID_MAP]; - bool vport_remove_flags; - - void *root_lport; /* Point to physic Lport */ - - struct completion *lport_free_completion; /* Free LPort Completion */ - -#define UNF_LPORT_NOP 1 -#define UNF_LPORT_NORMAL 0 - - atomic_t lport_no_operate_flag; - - bool loop_back_test_mode; - bool switch_state_before_test_mode; /* TRUE---->ON,false---->OFF */ - u32 enhanced_features; /* Enhanced Features */ - - u32 destroy_step; - u32 dirty_flag; - struct unf_chip_manage_info *chip_info; - - u8 unique_position; - u8 sfp_power_fault_count; - u8 sfp_9545_fault_count; - u64 last_tx_fault_jif; /* SFP last tx fault jiffies */ - u32 target_cnt; - /* Server card: UNF_FC_SERVER_BOARD_32_G(6) for 32G mode, - * UNF_FC_SERVER_BOARD_16_G(7) for 16G mode - */ - u32 card_type; - atomic_t scsi_session_add_success; - atomic_t scsi_session_add_failed; - atomic_t scsi_session_del_success; - atomic_t scsi_session_del_failed; - atomic_t add_start_work_failed; - atomic_t add_closing_work_failed; - atomic_t device_alloc; - atomic_t device_destroy; - atomic_t session_loss_tmo; - atomic_t alloc_scsi_id; - atomic_t resume_scsi_id; - atomic_t reuse_scsi_id; - atomic64_t last_exchg_mgr_idx; - atomic_t host_no; - atomic64_t exchg_index; - int scan_world_id; - struct semaphore wmi_task_sema; - bool ready_to_remove; - u32 pcie_link_down_cnt; - bool pcie_link_down; - u8 fw_version[SPFC_VER_LEN]; - atomic_t link_lose_tmo; - u32 max_ssq_num; -}; - -void unf_lport_state_ma(struct unf_lport *lport, enum unf_lport_event lport_event); -void unf_lport_error_recovery(struct unf_lport *lport); -void unf_set_lport_state(struct unf_lport *lport, enum unf_lport_login_state state); -void unf_init_port_parms(struct unf_lport *lport); -u32 unf_lport_enter_flogi(struct unf_lport *lport); -void unf_lport_enter_sns_plogi(struct unf_lport *lport); -u32 unf_init_disc_mgr(struct unf_lport *lport); -u32 unf_init_lport_route(struct unf_lport *lport); -void unf_destroy_lport_route(struct unf_lport *lport); -void unf_reset_lport_params(struct unf_lport *lport); -void unf_cm_mark_dirty_mem(struct unf_lport *lport, enum unf_lport_dirty_flag type); -struct unf_lport *unf_cm_lookup_vport_by_vp_index(struct unf_lport *lport, u16 vp_index); -struct unf_lport *unf_cm_lookup_vport_by_did(struct unf_lport *lport, u32 did); -struct unf_lport *unf_cm_lookup_vport_by_wwpn(struct unf_lport *lport, u64 wwpn); -void unf_cm_vport_remove(struct unf_lport *vport); - -#endif diff --git a/drivers/scsi/spfc/common/unf_ls.c b/drivers/scsi/spfc/common/unf_ls.c deleted file mode 100644 index 6a2e1fd1872f..000000000000 --- a/drivers/scsi/spfc/common/unf_ls.c +++ /dev/null @@ -1,4883 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#include "unf_ls.h" -#include "unf_log.h" -#include "unf_service.h" -#include "unf_portman.h" -#include "unf_gs.h" -#include "unf_npiv.h" - -static void unf_flogi_acc_ob_callback(struct unf_xchg *xchg); -static void unf_plogi_acc_ob_callback(struct unf_xchg *xchg); -static void unf_prli_acc_ob_callback(struct unf_xchg *xchg); -static void unf_rscn_acc_ob_callback(struct unf_xchg *xchg); -static void unf_pdisc_acc_ob_callback(struct unf_xchg *xchg); -static void unf_adisc_acc_ob_callback(struct unf_xchg *xchg); -static void unf_logo_acc_ob_callback(struct unf_xchg *xchg); -static void unf_logo_ob_callback(struct unf_xchg *xchg); -static void unf_logo_callback(void *lport, void *rport, void *xchg); -static void unf_rrq_callback(void *lport, void *rport, void *xchg); -static void unf_rrq_ob_callback(struct unf_xchg *xchg); -static void unf_lport_update_nport_id(struct unf_lport *lport, u32 nport_id); -static void -unf_lport_update_time_params(struct unf_lport *lport, - struct unf_flogi_fdisc_payload *flogi_payload); - -static void unf_login_with_rport_in_n2n(struct unf_lport *lport, - u64 remote_port_name, - u64 remote_node_name); -#define UNF_LOWLEVEL_BBCREDIT 0x6 -#define UNF_DEFAULT_BB_SC_N 0 - -#define UNF_ECHO_REQ_SIZE 0 -#define UNF_ECHO_WAIT_SEM_TIMEOUT(lport) (2 * (ulong)(lport)->ra_tov) - -#define UNF_SERVICE_COLLECT(service_collect, item) \ - do { \ - if ((item) < UNF_SERVICE_BUTT) { \ - (service_collect).service_cnt[(item)]++; \ - } \ - } while (0) - -static void unf_check_rport_need_delay_prli(struct unf_lport *lport, - struct unf_rport *rport, - u32 port_feature) -{ - u32 ret = UNF_RETURN_ERROR; - - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(rport); - - port_feature &= UNF_PORT_MODE_BOTH; - - /* Used for: L_Port has INI mode & R_Port is not SW */ - if (rport->nport_id < UNF_FC_FID_DOM_MGR) { - /* - * 1. immediately: R_Port only with TGT, or - * L_Port only with INI & R_Port has TGT mode, send PRLI - * immediately - */ - if ((port_feature == UNF_PORT_MODE_TGT || - lport->act_topo == UNF_ACT_TOP_P2P_DIRECT) || - (UNF_PORT_MODE_TGT == (port_feature & UNF_PORT_MODE_TGT))) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, - UNF_MAJOR, - "[info]LOGIN: Port(0x%x_0x%x) Rport(0x%x) with feature(0x%x) send PRLI", - lport->port_id, lport->nport_id, - rport->nport_id, port_feature); - ret = unf_send_prli(lport, rport, ELS_PRLI); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]LOGIN: Port(0x%x_0x%x) Rport(0x%x) with feature(0x%x) send PRLI failed", - lport->port_id, lport->nport_id, - rport->nport_id, port_feature); - - unf_rport_error_recovery(rport); - } - } - /* 2. R_Port has BOTH mode or unknown, Delay to send PRLI */ - else if (port_feature != UNF_PORT_MODE_INI) { - /* Prevent: PRLI done before PLOGI */ - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: Port(0x%x_0x%x) Rport(0x%x) with feature(0x%x) delay to send PRLI", - lport->port_id, lport->nport_id, - rport->nport_id, port_feature); - - /* Delay to send PRLI to R_Port */ - unf_rport_delay_login(rport); - } else { - /* 3. R_Port only with INI mode: wait for R_Port's PRLI: - * Do not care - */ - /* Cancel recovery(timer) work */ - if (delayed_work_pending(&rport->recovery_work)) { - if (cancel_delayed_work(&rport->recovery_work)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "[info]LOGIN: Port(0x%x_0x%x) Rport(0x%x) with feature(0x%x) is pure INI", - lport->port_id, - lport->nport_id, - rport->nport_id, - port_feature); - - unf_rport_ref_dec(rport); - } - } - - /* Server: R_Port only support INI, do not care this - * case - */ - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: Port(0x%x_0x%x) Rport(0x%x) with feature(0x%x) wait for PRLI", - lport->port_id, lport->nport_id, - rport->nport_id, port_feature); - } - } -} - -static u32 unf_low_level_bb_credit(struct unf_lport *lport) -{ - struct unf_lport *unf_lport = NULL; - u32 ret = UNF_RETURN_ERROR; - u32 bb_credit = UNF_LOWLEVEL_BBCREDIT; - - if (unlikely(!lport)) - return bb_credit; - - unf_lport = lport; - - if (unlikely(!unf_lport->low_level_func.port_mgr_op.ll_port_config_get)) - return bb_credit; - - ret = unf_lport->low_level_func.port_mgr_op.ll_port_config_get((void *)unf_lport->fc_port, - UNF_PORT_CFG_GET_WORKBALE_BBCREDIT, - (void *)&bb_credit); - if (unlikely(ret != RETURN_OK)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "[warn]Port(0x%x) get BB_Credit failed, use default value(%d)", - unf_lport->port_id, UNF_LOWLEVEL_BBCREDIT); - - bb_credit = UNF_LOWLEVEL_BBCREDIT; - } - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "[info]Port(0x%x) with BB_Credit(%u)", unf_lport->port_id, - bb_credit); - - return bb_credit; -} - -u32 unf_low_level_bb_scn(struct unf_lport *lport) -{ - struct unf_lport *unf_lport = NULL; - struct unf_low_level_port_mgr_op *port_mgr = NULL; - u32 ret = UNF_RETURN_ERROR; - u32 bb_scn = UNF_DEFAULT_BB_SC_N; - - if (unlikely(!lport)) - return bb_scn; - - unf_lport = lport; - port_mgr = &unf_lport->low_level_func.port_mgr_op; - - if (unlikely(!port_mgr->ll_port_config_get)) - return bb_scn; - - ret = port_mgr->ll_port_config_get((void *)unf_lport->fc_port, - UNF_PORT_CFG_GET_WORKBALE_BBSCN, - (void *)&bb_scn); - if (unlikely(ret != RETURN_OK)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "[warn]Port(0x%x) get bbscn failed, use default value(%d)", - unf_lport->port_id, UNF_DEFAULT_BB_SC_N); - - bb_scn = UNF_DEFAULT_BB_SC_N; - } - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "[info]Port(0x%x)'s bbscn(%d)", unf_lport->port_id, bb_scn); - - return bb_scn; -} - -static void unf_fill_rec_pld(struct unf_rec_pld *rec_pld, u32 sid) -{ - FC_CHECK_RETURN_VOID(rec_pld); - - rec_pld->rec_cmnd = (UNF_ELS_CMND_REC); - rec_pld->xchg_org_sid = sid; - rec_pld->ox_id = INVALID_VALUE16; - rec_pld->rx_id = INVALID_VALUE16; -} - -u32 unf_send_rec(struct unf_lport *lport, struct unf_rport *rport, - struct unf_xchg *io_xchg) -{ - struct unf_rec_pld *rec_pld = NULL; - union unf_sfs_u *fc_entry = NULL; - struct unf_xchg *xchg = NULL; - u32 ret = UNF_RETURN_ERROR; - struct unf_frame_pkg pkg; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(rport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(io_xchg, UNF_RETURN_ERROR); - - memset(&pkg, 0, sizeof(struct unf_frame_pkg)); - - xchg = unf_get_sfs_free_xchg_and_init(lport, rport->nport_id, rport, &fc_entry); - if (!xchg) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) exchange can't be NULL for PLOGI", - lport->port_id); - - return ret; - } - - xchg->cmnd_code = ELS_REC; - - unf_fill_package(&pkg, xchg, rport); - pkg.type = UNF_PKG_ELS_REQ; - pkg.origin_hottag = io_xchg->hotpooltag; - pkg.origin_magicnum = io_xchg->private_data[PKG_PRIVATE_XCHG_ALLOC_TIME]; - rec_pld = &fc_entry->rec.rec_pld; - memset(rec_pld, 0, sizeof(struct unf_rec_pld)); - - unf_fill_rec_pld(rec_pld, lport->nport_id); - - ret = unf_ls_gs_cmnd_send(lport, &pkg, xchg); - if (ret != RETURN_OK) - unf_cm_free_xchg((void *)lport, (void *)xchg); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_KEVENT, - "[info]LOGIN: Send REC %s. Port(0x%x_0x%x_0x%llx)--->RPort(0x%x_0x%llx) with hottag(0x%x)", - (ret != RETURN_OK) ? "failed" : "succeed", lport->port_id, - lport->nport_id, lport->port_name, rport->nport_id, - rport->port_name, xchg->hotpooltag); - - return ret; -} - -static void unf_fill_flogi_pld(struct unf_flogi_fdisc_payload *flogi_pld, - struct unf_lport *lport) -{ - struct unf_fabric_parm *fabric_parms = NULL; - - FC_CHECK_RETURN_VOID(flogi_pld); - FC_CHECK_RETURN_VOID(lport); - - fabric_parms = &flogi_pld->fabric_parms; - if (lport->act_topo == UNF_ACT_TOP_P2P_FABRIC || - lport->act_topo == UNF_ACT_TOP_P2P_DIRECT || - lport->act_topo == UNF_TOP_P2P_MASK) { - /* Fabric or P2P or FCoE VN2VN topology */ - fabric_parms->co_parms.bb_credit = unf_low_level_bb_credit(lport); - fabric_parms->co_parms.lowest_version = UNF_PLOGI_VERSION_LOWER; - fabric_parms->co_parms.highest_version = UNF_PLOGI_VERSION_UPPER; - fabric_parms->co_parms.bb_receive_data_field_size = (lport->max_frame_size); - fabric_parms->co_parms.bbscn = unf_low_level_bb_scn(lport); - } else { - /* Loop topology here */ - fabric_parms->co_parms.clean_address = UNF_CLEAN_ADDRESS_DEFAULT; - fabric_parms->co_parms.bb_credit = UNF_BBCREDIT_LPORT; - fabric_parms->co_parms.lowest_version = UNF_PLOGI_VERSION_LOWER; - fabric_parms->co_parms.highest_version = UNF_PLOGI_VERSION_UPPER; - fabric_parms->co_parms.alternate_bb_credit_mgmt = UNF_BBCREDIT_MANAGE_LPORT; - fabric_parms->co_parms.bb_receive_data_field_size = (lport->max_frame_size); - } - - if (lport->low_level_func.support_max_npiv_num != 0) - /* support NPIV */ - fabric_parms->co_parms.clean_address = 1; - - fabric_parms->cl_parms[ARRAY_INDEX_2].valid = UNF_CLASS_VALID; - - /* according the user value to set the priority */ - if (lport->qos_cs_ctrl) - fabric_parms->cl_parms[ARRAY_INDEX_2].priority = UNF_PRIORITY_ENABLE; - else - fabric_parms->cl_parms[ARRAY_INDEX_2].priority = UNF_PRIORITY_DISABLE; - - fabric_parms->cl_parms[ARRAY_INDEX_2].sequential_delivery = UNF_SEQUEN_DELIVERY_REQ; - fabric_parms->cl_parms[ARRAY_INDEX_2].received_data_field_size = (lport->max_frame_size); - - fabric_parms->high_node_name = UNF_GET_NAME_HIGH_WORD(lport->node_name); - fabric_parms->low_node_name = UNF_GET_NAME_LOW_WORD(lport->node_name); - fabric_parms->high_port_name = UNF_GET_NAME_HIGH_WORD(lport->port_name); - fabric_parms->low_port_name = UNF_GET_NAME_LOW_WORD(lport->port_name); -} - -u32 unf_send_flogi(struct unf_lport *lport, struct unf_rport *rport) -{ - struct unf_xchg *xchg = NULL; - struct unf_flogi_fdisc_payload *flogi_pld = NULL; - union unf_sfs_u *fc_entry = NULL; - u32 ret = UNF_RETURN_ERROR; - struct unf_frame_pkg pkg = {0}; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(rport, UNF_RETURN_ERROR); - - xchg = unf_get_sfs_free_xchg_and_init(lport, rport->nport_id, rport, &fc_entry); - if (!xchg) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) exchange can't be NULL for FLOGI", - lport->port_id); - - return ret; - } - - /* FLOGI */ - xchg->cmnd_code = ELS_FLOGI; - - /* for rcvd flogi acc/rjt processer */ - xchg->callback = unf_flogi_callback; - /* for send flogi failed processer */ - xchg->ob_callback = unf_flogi_ob_callback; - - unf_fill_package(&pkg, xchg, rport); - pkg.type = UNF_PKG_ELS_REQ; - - flogi_pld = &fc_entry->flogi.flogi_payload; - memset(flogi_pld, 0, sizeof(struct unf_flogi_fdisc_payload)); - unf_fill_flogi_pld(flogi_pld, lport); - flogi_pld->cmnd = (UNF_ELS_CMND_FLOGI); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: Begin to send FLOGI. Port(0x%x)--->RPort(0x%x) with hottag(0x%x)", - lport->port_id, rport->nport_id, xchg->hotpooltag); - - UNF_PRINT_SFS_LIMIT(UNF_INFO, lport->port_id, flogi_pld, - sizeof(struct unf_flogi_fdisc_payload)); - ret = unf_ls_gs_cmnd_send(lport, &pkg, xchg); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[warn]LOGIN: Send FLOGI failed. Port(0x%x)--->RPort(0x%x)", - lport->port_id, rport->nport_id); - - unf_cm_free_xchg((void *)lport, (void *)xchg); - } - - return ret; -} - -u32 unf_send_fdisc(struct unf_lport *lport, struct unf_rport *rport) -{ - struct unf_xchg *exch = NULL; - struct unf_flogi_fdisc_payload *fdisc_pld = NULL; - union unf_sfs_u *fc_entry = NULL; - u32 ret = UNF_RETURN_ERROR; - struct unf_frame_pkg pkg = {0}; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(rport, UNF_RETURN_ERROR); - - exch = unf_get_sfs_free_xchg_and_init(lport, rport->nport_id, rport, &fc_entry); - if (!exch) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) exchange can't be NULL for FDISC", - lport->port_id); - - return ret; - } - - exch->cmnd_code = ELS_FDISC; - - exch->callback = unf_fdisc_callback; - exch->ob_callback = unf_fdisc_ob_callback; - - unf_fill_package(&pkg, exch, rport); - pkg.type = UNF_PKG_ELS_REQ; - - fdisc_pld = &fc_entry->fdisc.fdisc_payload; - memset(fdisc_pld, 0, sizeof(struct unf_flogi_fdisc_payload)); - unf_fill_flogi_pld(fdisc_pld, lport); - fdisc_pld->cmnd = UNF_ELS_CMND_FDISC; - - ret = unf_ls_gs_cmnd_send(lport, &pkg, exch); - - if (ret != RETURN_OK) - unf_cm_free_xchg((void *)lport, (void *)exch); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: FDISC send %s. Port(0x%x)--->RPort(0x%x) with hottag(0x%x)", - (ret != RETURN_OK) ? "failed" : "succeed", lport->port_id, - rport->nport_id, exch->hotpooltag); - - return ret; -} - -static void unf_fill_plogi_pld(struct unf_plogi_payload *plogi_pld, - struct unf_lport *lport) -{ - struct unf_lgn_parm *login_parms = NULL; - struct unf_lport *unf_lport = NULL; - - FC_CHECK_RETURN_VOID(plogi_pld); - FC_CHECK_RETURN_VOID(lport); - - unf_lport = lport->root_lport; - plogi_pld->cmnd = (UNF_ELS_CMND_PLOGI); - login_parms = &plogi_pld->stparms; - - if (lport->act_topo == UNF_ACT_TOP_P2P_FABRIC || - lport->act_topo == UNF_ACT_TOP_P2P_DIRECT) { - /* P2P or Fabric mode or FCoE VN2VN */ - login_parms->co_parms.bb_credit = (unf_low_level_bb_credit(lport)); - login_parms->co_parms.alternate_bb_credit_mgmt = UNF_BBCREDIT_MANAGE_NFPORT; - login_parms->co_parms.bbscn = - (lport->act_topo == UNF_ACT_TOP_P2P_FABRIC) - ? 0 - : unf_low_level_bb_scn(lport); - } else { - /* Public loop & Private loop mode */ - login_parms->co_parms.bb_credit = UNF_BBCREDIT_LPORT; - login_parms->co_parms.alternate_bb_credit_mgmt = UNF_BBCREDIT_MANAGE_LPORT; - } - - login_parms->co_parms.lowest_version = UNF_PLOGI_VERSION_LOWER; - login_parms->co_parms.highest_version = UNF_PLOGI_VERSION_UPPER; - login_parms->co_parms.continuously_increasing = UNF_CONTIN_INCREASE_SUPPORT; - login_parms->co_parms.bb_receive_data_field_size = (lport->max_frame_size); - login_parms->co_parms.nport_total_concurrent_sequences = (UNF_PLOGI_CONCURRENT_SEQ); - login_parms->co_parms.relative_offset = (UNF_PLOGI_RO_CATEGORY); - login_parms->co_parms.e_d_tov = UNF_DEFAULT_EDTOV; - if (unf_lport->priority == UNF_PRIORITY_ENABLE) { - login_parms->cl_parms[ARRAY_INDEX_2].priority = - UNF_PRIORITY_ENABLE; - } else { - login_parms->cl_parms[ARRAY_INDEX_2].priority = - UNF_PRIORITY_DISABLE; - } - - /* for class_3 */ - login_parms->cl_parms[ARRAY_INDEX_2].valid = UNF_CLASS_VALID; - login_parms->cl_parms[ARRAY_INDEX_2].received_data_field_size = (lport->max_frame_size); - login_parms->cl_parms[ARRAY_INDEX_2].concurrent_sequences = (UNF_PLOGI_CONCURRENT_SEQ); - login_parms->cl_parms[ARRAY_INDEX_2].open_sequence_per_exchange = (UNF_PLOGI_SEQ_PER_XCHG); - - login_parms->high_node_name = UNF_GET_NAME_HIGH_WORD(lport->node_name); - login_parms->low_node_name = UNF_GET_NAME_LOW_WORD(lport->node_name); - login_parms->high_port_name = UNF_GET_NAME_HIGH_WORD(lport->port_name); - login_parms->low_port_name = UNF_GET_NAME_LOW_WORD(lport->port_name); - - UNF_PRINT_SFS_LIMIT(UNF_INFO, lport->port_id, plogi_pld, sizeof(struct unf_plogi_payload)); -} - -u32 unf_send_plogi(struct unf_lport *lport, struct unf_rport *rport) -{ - struct unf_plogi_payload *plogi_pld = NULL; - union unf_sfs_u *fc_entry = NULL; - struct unf_xchg *xchg = NULL; - u32 ret = UNF_RETURN_ERROR; - struct unf_frame_pkg pkg; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(rport, UNF_RETURN_ERROR); - - memset(&pkg, 0, sizeof(struct unf_frame_pkg)); - - xchg = unf_get_sfs_free_xchg_and_init(lport, rport->nport_id, rport, &fc_entry); - if (!xchg) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) exchange can't be NULL for PLOGI", - lport->port_id); - - return ret; - } - - xchg->cmnd_code = ELS_PLOGI; - - xchg->callback = unf_plogi_callback; - xchg->ob_callback = unf_plogi_ob_callback; - - unf_fill_package(&pkg, xchg, rport); - pkg.type = UNF_PKG_ELS_REQ; - unf_cm_xchg_mgr_abort_io_by_id(lport, rport, xchg->sid, xchg->did, 0); - - plogi_pld = &fc_entry->plogi.payload; - memset(plogi_pld, 0, sizeof(struct unf_plogi_payload)); - unf_fill_plogi_pld(plogi_pld, lport); - - ret = unf_ls_gs_cmnd_send(lport, &pkg, xchg); - if (ret != RETURN_OK) - unf_cm_free_xchg((void *)lport, (void *)xchg); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: Send PLOGI %s. Port(0x%x_0x%x_0x%llx)--->RPort(0x%x_0x%llx) with hottag(0x%x)", - (ret != RETURN_OK) ? "failed" : "succeed", lport->port_id, - lport->nport_id, lport->port_name, rport->nport_id, - rport->port_name, xchg->hotpooltag); - - return ret; -} - -static void unf_fill_logo_pld(struct unf_logo_payload *logo_pld, - struct unf_lport *lport) -{ - FC_CHECK_RETURN_VOID(logo_pld); - FC_CHECK_RETURN_VOID(lport); - - logo_pld->cmnd = (UNF_ELS_CMND_LOGO); - logo_pld->nport_id = (lport->nport_id); - logo_pld->high_port_name = UNF_GET_NAME_HIGH_WORD(lport->port_name); - logo_pld->low_port_name = UNF_GET_NAME_LOW_WORD(lport->port_name); - - UNF_PRINT_SFS_LIMIT(UNF_INFO, lport->port_id, logo_pld, sizeof(struct unf_logo_payload)); -} - -u32 unf_send_logo(struct unf_lport *lport, struct unf_rport *rport) -{ - struct unf_logo_payload *logo_pld = NULL; - union unf_sfs_u *fc_entry = NULL; - struct unf_xchg *xchg = NULL; - struct unf_frame_pkg pkg = {0}; - u32 ret = UNF_RETURN_ERROR; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - - xchg = unf_get_sfs_free_xchg_and_init(lport, rport->nport_id, rport, &fc_entry); - if (!xchg) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) exchange can't be NULL for LOGO", - lport->port_id); - - return ret; - } - - xchg->cmnd_code = ELS_LOGO; - /* retry or link down immediately */ - xchg->callback = unf_logo_callback; - /* do nothing */ - xchg->ob_callback = unf_logo_ob_callback; - - unf_fill_package(&pkg, xchg, rport); - pkg.type = UNF_PKG_ELS_REQ; - - logo_pld = &fc_entry->logo.payload; - memset(logo_pld, 0, sizeof(struct unf_logo_payload)); - unf_fill_logo_pld(logo_pld, lport); - - ret = unf_ls_gs_cmnd_send(lport, &pkg, xchg); - if (ret != RETURN_OK) - unf_cm_free_xchg((void *)lport, (void *)xchg); - - rport->logo_retries++; - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_KEVENT, - "[info]LOGIN: LOGO send %s. Port(0x%x)--->RPort(0x%x) hottag(0x%x) Retries(%d)", - (ret != RETURN_OK) ? "failed" : "succeed", lport->port_id, - rport->nport_id, xchg->hotpooltag, rport->logo_retries); - - return ret; -} - -u32 unf_send_logo_by_did(struct unf_lport *lport, u32 did) -{ - struct unf_logo_payload *logo_pld = NULL; - union unf_sfs_u *fc_entry = NULL; - struct unf_xchg *xchg = NULL; - struct unf_frame_pkg pkg = {0}; - u32 ret = UNF_RETURN_ERROR; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - - xchg = unf_get_sfs_free_xchg_and_init(lport, did, NULL, &fc_entry); - if (!xchg) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) exchange can't be NULL for LOGO", - lport->port_id); - - return ret; - } - - xchg->cmnd_code = ELS_LOGO; - - unf_fill_package(&pkg, xchg, NULL); - pkg.type = UNF_PKG_ELS_REQ; - - logo_pld = &fc_entry->logo.payload; - memset(logo_pld, 0, sizeof(struct unf_logo_payload)); - unf_fill_logo_pld(logo_pld, lport); - - ret = unf_ls_gs_cmnd_send(lport, &pkg, xchg); - if (ret != RETURN_OK) - unf_cm_free_xchg((void *)lport, (void *)xchg); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: LOGO send %s. Port(0x%x)--->RPort(0x%x) with hottag(0x%x)", - (ret != RETURN_OK) ? "failed" : "succeed", lport->port_id, - did, xchg->hotpooltag); - - return ret; -} - -static void unf_echo_callback(void *lport, void *rport, void *xchg) -{ - struct unf_lport *unf_lport = (struct unf_lport *)lport; - struct unf_rport *unf_rport = (struct unf_rport *)rport; - struct unf_xchg *unf_xchg = NULL; - struct unf_echo_payload *echo_rsp_pld = NULL; - u32 cmnd = 0; - u32 mag_ver_local = 0; - u32 mag_ver_remote = 0; - - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(rport); - FC_CHECK_RETURN_VOID(xchg); - - unf_xchg = (struct unf_xchg *)xchg; - if (!unf_xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr) - return; - - echo_rsp_pld = unf_xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr->echo_acc.echo_pld; - FC_CHECK_RETURN_VOID(echo_rsp_pld); - - if (unf_xchg->byte_orders & UNF_BIT_2) { - unf_big_end_to_cpu((u8 *)echo_rsp_pld, sizeof(struct unf_echo_payload)); - cmnd = echo_rsp_pld->cmnd; - } else { - cmnd = echo_rsp_pld->cmnd; - } - - mag_ver_local = echo_rsp_pld->data[ARRAY_INDEX_0]; - mag_ver_remote = echo_rsp_pld->data[ARRAY_INDEX_1]; - - if (UNF_ELS_CMND_ACC == (cmnd & UNF_ELS_CMND_HIGH_MASK)) { - if (mag_ver_local == ECHO_MG_VERSION_LOCAL && - mag_ver_remote == ECHO_MG_VERSION_REMOTE) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "LPort(0x%x) send ECHO to RPort(0x%x), received ACC. local snd echo:(0x%x), remote rcv echo:(0x%x), remote snd echo acc:(0x%x), local rcv echo acc:(0x%x)", - unf_lport->port_id, unf_rport->nport_id, - unf_xchg->private_data[PKG_PRIVATE_ECHO_CMD_SND_TIME], - unf_xchg->private_data[PKG_PRIVATE_ECHO_CMD_RCV_TIME], - unf_xchg->private_data[PKG_PRIVATE_ECHO_RSP_SND_TIME], - unf_xchg->private_data[PKG_PRIVATE_ECHO_ACC_RCV_TIME]); - } else if ((mag_ver_local == ECHO_MG_VERSION_LOCAL) && - (mag_ver_remote != ECHO_MG_VERSION_REMOTE)) { - /* the peer don't supprt smartping, only local snd and - * rcv rsp time stamp - */ - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "LPort(0x%x) send ECHO to RPort(0x%x), received ACC. local snd echo:(0x%x), local rcv echo acc:(0x%x)", - unf_lport->port_id, unf_rport->nport_id, - unf_xchg->private_data[PKG_PRIVATE_ECHO_CMD_SND_TIME], - unf_xchg->private_data[PKG_PRIVATE_ECHO_ACC_RCV_TIME]); - } else if ((mag_ver_local != ECHO_MG_VERSION_LOCAL) && - (mag_ver_remote != ECHO_MG_VERSION_REMOTE)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, - UNF_MAJOR, - "LPort(0x%x) send ECHO to RPort(0x%x), received ACC. local and remote is not FC HBA", - unf_lport->port_id, unf_rport->nport_id); - } - } else { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) send ECHO to RPort(0x%x) and received RJT", - unf_lport->port_id, unf_rport->nport_id); - } - - unf_xchg->echo_info.echo_result = UNF_ELS_ECHO_RESULT_OK; - unf_xchg->echo_info.response_time = jiffies - unf_xchg->echo_info.response_time; - - /* wake up semaphore */ - up(&unf_xchg->echo_info.echo_sync_sema); -} - -static void unf_echo_ob_callback(struct unf_xchg *xchg) -{ - struct unf_lport *unf_lport = NULL; - struct unf_rport *unf_rport = NULL; - - FC_CHECK_RETURN_VOID(xchg); - unf_lport = xchg->lport; - FC_CHECK_RETURN_VOID(unf_lport); - unf_rport = xchg->rport; - FC_CHECK_RETURN_VOID(unf_rport); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) send ECHO to RPort(0x%x) but timeout", - unf_lport->port_id, unf_rport->nport_id); - - xchg->echo_info.echo_result = UNF_ELS_ECHO_RESULT_FAIL; - - /* wake up semaphore */ - up(&xchg->echo_info.echo_sync_sema); -} - -u32 unf_send_echo(struct unf_lport *lport, struct unf_rport *rport, u32 *time) -{ - struct unf_echo_payload *echo_pld = NULL; - union unf_sfs_u *fc_entry = NULL; - struct unf_xchg *xchg = NULL; - struct unf_frame_pkg pkg = {0}; - u32 ret = UNF_RETURN_ERROR; - ulong delay = 0; - dma_addr_t phy_echo_addr; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(rport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(time, UNF_RETURN_ERROR); - - delay = UNF_ECHO_WAIT_SEM_TIMEOUT(lport); - xchg = unf_get_sfs_free_xchg_and_init(lport, rport->nport_id, rport, &fc_entry); - if (!xchg) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) exchange can't be NULL for ECHO", - lport->port_id); - - return ret; - } - - /* ECHO */ - xchg->cmnd_code = ELS_ECHO; - xchg->fcp_sfs_union.sfs_entry.cur_offset = UNF_ECHO_REQ_SIZE; - - /* Set callback function, wake up semaphore */ - xchg->callback = unf_echo_callback; - /* wake up semaphore */ - xchg->ob_callback = unf_echo_ob_callback; - - unf_fill_package(&pkg, xchg, rport); - pkg.type = UNF_PKG_ELS_REQ; - - echo_pld = (struct unf_echo_payload *)unf_get_one_big_sfs_buf(xchg); - if (!echo_pld) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) can't allocate buffer for ECHO", - lport->port_id); - - unf_cm_free_xchg(lport, xchg); - return UNF_RETURN_ERROR; - } - - fc_entry->echo.echo_pld = echo_pld; - phy_echo_addr = pci_map_single(lport->low_level_func.dev, echo_pld, - UNF_ECHO_PAYLOAD_LEN, - DMA_BIDIRECTIONAL); - if (pci_dma_mapping_error(lport->low_level_func.dev, phy_echo_addr)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, - UNF_WARN, "[warn]Port(0x%x) pci map err", lport->port_id); - unf_cm_free_xchg(lport, xchg); - return UNF_RETURN_ERROR; - } - fc_entry->echo.phy_echo_addr = phy_echo_addr; - memset(echo_pld, 0, sizeof(struct unf_echo_payload)); - echo_pld->cmnd = (UNF_ELS_CMND_ECHO); - echo_pld->data[ARRAY_INDEX_0] = ECHO_MG_VERSION_LOCAL; - - ret = unf_xchg_ref_inc(xchg, SEND_ELS); - FC_CHECK_RETURN_VALUE((ret == RETURN_OK), UNF_RETURN_ERROR); - - xchg->echo_info.response_time = jiffies; - ret = unf_ls_gs_cmnd_send(lport, &pkg, xchg); - if (ret != RETURN_OK) { - unf_cm_free_xchg((void *)lport, (void *)xchg); - } else { - if (down_timeout(&xchg->echo_info.echo_sync_sema, - (long)msecs_to_jiffies((u32)delay))) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]ECHO send %s. Port(0x%x)--->RPort(0x%x) but response timeout ", - (ret != RETURN_OK) ? "failed" : "succeed", - lport->port_id, rport->nport_id); - - xchg->echo_info.echo_result = UNF_ELS_ECHO_RESULT_FAIL; - } - - if (xchg->echo_info.echo_result == UNF_ELS_ECHO_RESULT_FAIL) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, - UNF_MAJOR, "Echo send fail or timeout"); - - ret = UNF_RETURN_ERROR; - } else { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "echo acc rsp,echo_cmd_snd(0x%xus)-->echo_cmd_rcv(0x%xus)-->echo_acc_ snd(0x%xus)-->echo_acc_rcv(0x%xus).", - xchg->private_data[PKG_PRIVATE_ECHO_CMD_SND_TIME], - xchg->private_data[PKG_PRIVATE_ECHO_CMD_RCV_TIME], - xchg->private_data[PKG_PRIVATE_ECHO_RSP_SND_TIME], - xchg->private_data[PKG_PRIVATE_ECHO_ACC_RCV_TIME]); - - *time = - (xchg->private_data[PKG_PRIVATE_ECHO_ACC_RCV_TIME] - - xchg->private_data[PKG_PRIVATE_ECHO_CMD_SND_TIME]) - - (xchg->private_data[PKG_PRIVATE_ECHO_RSP_SND_TIME] - - xchg->private_data[PKG_PRIVATE_ECHO_CMD_RCV_TIME]); - } - } - - pci_unmap_single(lport->low_level_func.dev, phy_echo_addr, - UNF_ECHO_PAYLOAD_LEN, DMA_BIDIRECTIONAL); - fc_entry->echo.phy_echo_addr = 0; - unf_xchg_ref_dec(xchg, SEND_ELS); - - return ret; -} - -static void unf_fill_prli_pld(struct unf_prli_payload *prli_pld, - struct unf_lport *lport) -{ - u32 pld_len = 0; - - FC_CHECK_RETURN_VOID(prli_pld); - FC_CHECK_RETURN_VOID(lport); - - pld_len = sizeof(struct unf_prli_payload) - UNF_PRLI_SIRT_EXTRA_SIZE; - prli_pld->cmnd = - (UNF_ELS_CMND_PRLI | - ((u32)UNF_FC4_FRAME_PAGE_SIZE << UNF_FC4_FRAME_PAGE_SIZE_SHIFT) | - ((u32)pld_len)); - - prli_pld->parms[ARRAY_INDEX_0] = (UNF_FC4_FRAME_PARM_0_FCP | UNF_FC4_FRAME_PARM_0_I_PAIR); - prli_pld->parms[ARRAY_INDEX_1] = UNF_NOT_MEANINGFUL; - prli_pld->parms[ARRAY_INDEX_2] = UNF_NOT_MEANINGFUL; - - /* About Read Xfer_rdy disable */ - prli_pld->parms[ARRAY_INDEX_3] = (UNF_FC4_FRAME_PARM_3_R_XFER_DIS | lport->options); - - /* About FCP confirm */ - if (lport->low_level_func.lport_cfg_items.fcp_conf) - prli_pld->parms[ARRAY_INDEX_3] |= UNF_FC4_FRAME_PARM_3_CONF_ALLOW; - - /* About Tape support */ - if (lport->low_level_func.lport_cfg_items.tape_support) - prli_pld->parms[ARRAY_INDEX_3] |= - (UNF_FC4_FRAME_PARM_3_REC_SUPPORT | - UNF_FC4_FRAME_PARM_3_RETRY_SUPPORT | - UNF_FC4_FRAME_PARM_3_TASK_RETRY_ID_SUPPORT | - UNF_FC4_FRAME_PARM_3_CONF_ALLOW); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x)'s PRLI payload: options(0x%x) parameter-3(0x%x)", - lport->port_id, lport->options, - prli_pld->parms[ARRAY_INDEX_3]); - - UNF_PRINT_SFS_LIMIT(UNF_INFO, lport->port_id, prli_pld, sizeof(struct unf_prli_payload)); -} - -u32 unf_send_prli(struct unf_lport *lport, struct unf_rport *rport, - u32 cmnd_code) -{ - struct unf_prli_payload *prli_pal = NULL; - union unf_sfs_u *fc_entry = NULL; - struct unf_xchg *xchg = NULL; - u32 ret = UNF_RETURN_ERROR; - struct unf_frame_pkg pkg = {0}; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(rport, UNF_RETURN_ERROR); - - xchg = unf_get_sfs_free_xchg_and_init(lport, rport->nport_id, rport, &fc_entry); - if (!xchg) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) exchange can't be NULL for PRLI", - lport->port_id); - - return ret; - } - - xchg->cmnd_code = cmnd_code; - - /* for rcvd prli acc/rjt processer */ - xchg->callback = unf_prli_callback; - /* for send prli failed processer */ - xchg->ob_callback = unf_prli_ob_callback; - - unf_fill_package(&pkg, xchg, rport); - pkg.type = UNF_PKG_ELS_REQ; - - prli_pal = &fc_entry->prli.payload; - memset(prli_pal, 0, sizeof(struct unf_prli_payload)); - unf_fill_prli_pld(prli_pal, lport); - - ret = unf_ls_gs_cmnd_send(lport, &pkg, xchg); - if (ret != RETURN_OK) - unf_cm_free_xchg((void *)lport, (void *)xchg); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: PRLI send %s. Port(0x%x)--->RPort(0x%x)", - (ret != RETURN_OK) ? "failed" : "succeed", lport->port_id, - rport->nport_id); - - return ret; -} - -static void unf_fill_prlo_pld(struct unf_prli_payload *prlo_pld, - struct unf_lport *lport) -{ - FC_CHECK_RETURN_VOID(prlo_pld); - FC_CHECK_RETURN_VOID(lport); - - prlo_pld->cmnd = (UNF_ELS_CMND_PRLO); - prlo_pld->parms[ARRAY_INDEX_0] = (UNF_FC4_FRAME_PARM_0_FCP); - prlo_pld->parms[ARRAY_INDEX_1] = UNF_NOT_MEANINGFUL; - prlo_pld->parms[ARRAY_INDEX_2] = UNF_NOT_MEANINGFUL; - prlo_pld->parms[ARRAY_INDEX_3] = UNF_NO_SERVICE_PARAMS; - - UNF_PRINT_SFS_LIMIT(UNF_INFO, lport->port_id, prlo_pld, sizeof(struct unf_prli_payload)); -} - -u32 unf_send_prlo(struct unf_lport *lport, struct unf_rport *rport) -{ - struct unf_prli_payload *prlo_pld = NULL; - union unf_sfs_u *fc_entry = NULL; - struct unf_xchg *xchg = NULL; - u32 ret = UNF_RETURN_ERROR; - struct unf_frame_pkg pkg; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(rport, UNF_RETURN_ERROR); - - memset(&pkg, 0, sizeof(struct unf_frame_pkg)); - - xchg = unf_get_sfs_free_xchg_and_init(lport, rport->nport_id, rport, &fc_entry); - if (!xchg) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) exchange can't be NULL for PRLO", lport->port_id); - - return ret; - } - - xchg->cmnd_code = ELS_PRLO; - - unf_fill_package(&pkg, xchg, rport); - pkg.type = UNF_PKG_ELS_REQ; - - prlo_pld = &fc_entry->prlo.payload; - memset(prlo_pld, 0, sizeof(struct unf_prli_payload)); - unf_fill_prlo_pld(prlo_pld, lport); - - ret = unf_ls_gs_cmnd_send(lport, &pkg, xchg); - if (ret != RETURN_OK) - unf_cm_free_xchg((void *)lport, (void *)xchg); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: PRLO send %s. Port(0x%x)--->RPort(0x%x)", - (ret != RETURN_OK) ? "failed" : "succeed", lport->port_id, - rport->nport_id); - - return ret; -} - -static void unf_fill_pdisc_pld(struct unf_plogi_payload *pdisc_pld, - struct unf_lport *lport) -{ - struct unf_lgn_parm *login_parms = NULL; - - FC_CHECK_RETURN_VOID(pdisc_pld); - FC_CHECK_RETURN_VOID(lport); - - pdisc_pld->cmnd = (UNF_ELS_CMND_PDISC); - login_parms = &pdisc_pld->stparms; - - if (lport->act_topo == UNF_ACT_TOP_P2P_FABRIC || - lport->act_topo == UNF_ACT_TOP_P2P_DIRECT) { - /* P2P & Fabric */ - login_parms->co_parms.bb_credit = (unf_low_level_bb_credit(lport)); - login_parms->co_parms.alternate_bb_credit_mgmt = UNF_BBCREDIT_MANAGE_NFPORT; - login_parms->co_parms.bbscn = - (lport->act_topo == UNF_ACT_TOP_P2P_FABRIC) - ? 0 - : unf_low_level_bb_scn(lport); - } else { - /* Public loop & Private loop */ - login_parms->co_parms.bb_credit = UNF_BBCREDIT_LPORT; - /* :1 */ - login_parms->co_parms.alternate_bb_credit_mgmt = UNF_BBCREDIT_MANAGE_LPORT; - } - - login_parms->co_parms.lowest_version = UNF_PLOGI_VERSION_LOWER; - login_parms->co_parms.highest_version = UNF_PLOGI_VERSION_UPPER; - login_parms->co_parms.continuously_increasing = UNF_CONTIN_INCREASE_SUPPORT; - login_parms->co_parms.bb_receive_data_field_size = (lport->max_frame_size); - login_parms->co_parms.nport_total_concurrent_sequences = (UNF_PLOGI_CONCURRENT_SEQ); - login_parms->co_parms.relative_offset = (UNF_PLOGI_RO_CATEGORY); - login_parms->co_parms.e_d_tov = (lport->ed_tov); - - login_parms->high_node_name = UNF_GET_NAME_HIGH_WORD(lport->node_name); - login_parms->low_node_name = UNF_GET_NAME_LOW_WORD(lport->node_name); - login_parms->high_port_name = UNF_GET_NAME_HIGH_WORD(lport->port_name); - login_parms->low_port_name = UNF_GET_NAME_LOW_WORD(lport->port_name); - - /* class-3 */ - login_parms->cl_parms[ARRAY_INDEX_2].valid = UNF_CLASS_VALID; - login_parms->cl_parms[ARRAY_INDEX_2].received_data_field_size = (lport->max_frame_size); - login_parms->cl_parms[ARRAY_INDEX_2].concurrent_sequences = (UNF_PLOGI_CONCURRENT_SEQ); - login_parms->cl_parms[ARRAY_INDEX_2].open_sequence_per_exchange = (UNF_PLOGI_SEQ_PER_XCHG); - - UNF_PRINT_SFS_LIMIT(UNF_INFO, lport->port_id, pdisc_pld, sizeof(struct unf_plogi_payload)); -} - -u32 unf_send_pdisc(struct unf_lport *lport, struct unf_rport *rport) -{ - /* PLOGI/PDISC with same payload */ - struct unf_plogi_payload *pdisc_pld = NULL; - union unf_sfs_u *fc_entry = NULL; - struct unf_xchg *xchg = NULL; - u32 ret = UNF_RETURN_ERROR; - struct unf_frame_pkg pkg = {0}; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(rport, UNF_RETURN_ERROR); - - xchg = unf_get_sfs_free_xchg_and_init(lport, rport->nport_id, rport, &fc_entry); - if (!xchg) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) exchange can't be NULL for PDISC", - lport->port_id); - - return ret; - } - - xchg->cmnd_code = ELS_PDISC; - xchg->callback = NULL; - xchg->ob_callback = NULL; - - unf_fill_package(&pkg, xchg, rport); - pkg.type = UNF_PKG_ELS_REQ; - - pdisc_pld = &fc_entry->pdisc.payload; - memset(pdisc_pld, 0, sizeof(struct unf_plogi_payload)); - unf_fill_pdisc_pld(pdisc_pld, lport); - - ret = unf_ls_gs_cmnd_send(lport, &pkg, xchg); - if (ret != RETURN_OK) - unf_cm_free_xchg((void *)lport, (void *)xchg); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: PDISC send %s. Port(0x%x)--->RPort(0x%x)", - (ret != RETURN_OK) ? "failed" : "succeed", lport->port_id, rport->nport_id); - - return ret; -} - -static void unf_fill_adisc_pld(struct unf_adisc_payload *adisc_pld, - struct unf_lport *lport) -{ - FC_CHECK_RETURN_VOID(adisc_pld); - FC_CHECK_RETURN_VOID(lport); - - adisc_pld->cmnd = (UNF_ELS_CMND_ADISC); - adisc_pld->high_node_name = UNF_GET_NAME_HIGH_WORD(lport->node_name); - adisc_pld->low_node_name = UNF_GET_NAME_LOW_WORD(lport->node_name); - adisc_pld->high_port_name = UNF_GET_NAME_HIGH_WORD(lport->port_name); - adisc_pld->low_port_name = UNF_GET_NAME_LOW_WORD(lport->port_name); - - UNF_PRINT_SFS_LIMIT(UNF_INFO, lport->port_id, adisc_pld, sizeof(struct unf_adisc_payload)); -} - -u32 unf_send_adisc(struct unf_lport *lport, struct unf_rport *rport) -{ - struct unf_adisc_payload *adisc_pal = NULL; - union unf_sfs_u *fc_entry = NULL; - struct unf_xchg *xchg = NULL; - u32 ret = UNF_RETURN_ERROR; - struct unf_frame_pkg pkg = {0}; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(rport, UNF_RETURN_ERROR); - - xchg = unf_get_sfs_free_xchg_and_init(lport, rport->nport_id, rport, &fc_entry); - if (!xchg) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) exchange can't be NULL for ADISC", lport->port_id); - - return ret; - } - - xchg->cmnd_code = ELS_ADISC; - - xchg->callback = NULL; - xchg->ob_callback = NULL; - - unf_fill_package(&pkg, xchg, rport); - pkg.type = UNF_PKG_ELS_REQ; - - adisc_pal = &fc_entry->adisc.adisc_payl; - memset(adisc_pal, 0, sizeof(struct unf_adisc_payload)); - unf_fill_adisc_pld(adisc_pal, lport); - - ret = unf_ls_gs_cmnd_send(lport, &pkg, xchg); - if (ret != RETURN_OK) - unf_cm_free_xchg((void *)lport, (void *)xchg); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: ADISC send %s. Port(0x%x)--->RPort(0x%x)", - (ret != RETURN_OK) ? "failed" : "succeed", lport->port_id, - rport->nport_id); - - return ret; -} - -static void unf_fill_rrq_pld(struct unf_rrq *rrq_pld, struct unf_xchg *xchg) -{ - FC_CHECK_RETURN_VOID(rrq_pld); - FC_CHECK_RETURN_VOID(xchg); - - rrq_pld->cmnd = UNF_ELS_CMND_RRQ; - rrq_pld->sid = xchg->sid; - rrq_pld->oxid_rxid = ((u32)xchg->oxid << UNF_SHIFT_16 | xchg->rxid); -} - -u32 unf_send_rrq(struct unf_lport *lport, struct unf_rport *rport, - struct unf_xchg *xchg) -{ - /* after ABTS Done */ - struct unf_rrq *rrq_pld = NULL; - union unf_sfs_u *fc_entry = NULL; - struct unf_xchg *unf_xchg = NULL; - struct unf_frame_pkg pkg = {0}; - u32 ret = UNF_RETURN_ERROR; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(rport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(xchg, UNF_RETURN_ERROR); - - unf_xchg = unf_get_sfs_free_xchg_and_init(lport, rport->nport_id, rport, &fc_entry); - if (!unf_xchg) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) exchange can't be NULL for RRQ", - lport->port_id); - - return ret; - } - - unf_xchg->cmnd_code = ELS_RRQ; /* RRQ */ - - unf_xchg->callback = unf_rrq_callback; /* release I/O exchange context */ - unf_xchg->ob_callback = unf_rrq_ob_callback; /* release I/O exchange context */ - unf_xchg->io_xchg = xchg; /* pointer to IO XCHG */ - - unf_fill_package(&pkg, unf_xchg, rport); - pkg.type = UNF_PKG_ELS_REQ; - rrq_pld = &fc_entry->rrq; - memset(rrq_pld, 0, sizeof(struct unf_rrq)); - unf_fill_rrq_pld(rrq_pld, xchg); - - ret = unf_ls_gs_cmnd_send(lport, &pkg, unf_xchg); - if (ret != RETURN_OK) - unf_cm_free_xchg((void *)lport, (void *)unf_xchg); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]RRQ send %s. Port(0x%x)--->RPort(0x%x) free old exchange(0x%x)", - (ret != RETURN_OK) ? "failed" : "succeed", lport->port_id, - rport->nport_id, xchg->hotpooltag); - - return ret; -} - -u32 unf_send_flogi_acc(struct unf_lport *lport, struct unf_rport *rport, - struct unf_xchg *xchg) -{ - struct unf_flogi_fdisc_payload *flogi_acc_pld = NULL; - union unf_sfs_u *fc_entry = NULL; - u32 ret = UNF_RETURN_ERROR; - struct unf_frame_pkg pkg = {0}; - u16 ox_id = 0; - u16 rx_id = 0; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(rport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(xchg, UNF_RETURN_ERROR); - - xchg->cmnd_code = UNF_SET_ELS_ACC_TYPE(ELS_FLOGI); - - xchg->did = 0; /* D_ID must be 0 */ - xchg->sid = UNF_FC_FID_FLOGI; /* S_ID must be 0xfffffe */ - xchg->oid = xchg->sid; - xchg->callback = NULL; - xchg->lport = lport; - xchg->rport = rport; - xchg->ob_callback = unf_flogi_acc_ob_callback; /* call back for sending - * FLOGI response - */ - - fc_entry = xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr; - if (!fc_entry) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[warn]Port(0x%x) entry can't be NULL with tag(0x%x)", - lport->port_id, xchg->hotpooltag); - - unf_cm_free_xchg(lport, xchg); - return UNF_RETURN_ERROR; - } - - unf_fill_package(&pkg, xchg, rport); - pkg.type = UNF_PKG_ELS_REPLY; - - memset(fc_entry, 0, sizeof(union unf_sfs_u)); - flogi_acc_pld = &fc_entry->flogi_acc.flogi_payload; - flogi_acc_pld->cmnd = (UNF_ELS_CMND_ACC); - unf_fill_flogi_pld(flogi_acc_pld, lport); - ox_id = xchg->oxid; - rx_id = xchg->rxid; - - ret = unf_ls_gs_cmnd_send(lport, &pkg, xchg); - if (ret != RETURN_OK) - unf_cm_free_xchg((void *)lport, (void *)xchg); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]LOGIN: FLOGI ACC send %s. Port(0x%x)--->RPort(0x%x) with OX_ID(0x%x) RX_ID(0x%x)", - (ret != RETURN_OK) ? "failed" : "succeed", lport->port_id, - rport->nport_id, ox_id, rx_id); - return ret; -} - -static void unf_fill_plogi_acc_pld(struct unf_plogi_payload *plogi_acc_pld, - struct unf_lport *lport) -{ - struct unf_lgn_parm *login_parms = NULL; - - FC_CHECK_RETURN_VOID(plogi_acc_pld); - FC_CHECK_RETURN_VOID(lport); - - plogi_acc_pld->cmnd = (UNF_ELS_CMND_ACC); - login_parms = &plogi_acc_pld->stparms; - - if (lport->act_topo == UNF_ACT_TOP_P2P_FABRIC || - lport->act_topo == UNF_ACT_TOP_P2P_DIRECT) { - login_parms->co_parms.bb_credit = (unf_low_level_bb_credit(lport)); - login_parms->co_parms.alternate_bb_credit_mgmt = UNF_BBCREDIT_MANAGE_NFPORT; /* 0 */ - login_parms->co_parms.bbscn = - (lport->act_topo == UNF_ACT_TOP_P2P_FABRIC) - ? 0 - : unf_low_level_bb_scn(lport); - } else { - login_parms->co_parms.bb_credit = UNF_BBCREDIT_LPORT; - login_parms->co_parms.alternate_bb_credit_mgmt = UNF_BBCREDIT_MANAGE_LPORT; /* 1 */ - } - - login_parms->co_parms.lowest_version = UNF_PLOGI_VERSION_LOWER; - login_parms->co_parms.highest_version = UNF_PLOGI_VERSION_UPPER; - login_parms->co_parms.continuously_increasing = UNF_CONTIN_INCREASE_SUPPORT; - login_parms->co_parms.bb_receive_data_field_size = (lport->max_frame_size); - login_parms->co_parms.nport_total_concurrent_sequences = (UNF_PLOGI_CONCURRENT_SEQ); - login_parms->co_parms.relative_offset = (UNF_PLOGI_RO_CATEGORY); - login_parms->co_parms.e_d_tov = (lport->ed_tov); - login_parms->cl_parms[ARRAY_INDEX_2].valid = UNF_CLASS_VALID; /* class-3 */ - login_parms->cl_parms[ARRAY_INDEX_2].received_data_field_size = (lport->max_frame_size); - login_parms->cl_parms[ARRAY_INDEX_2].concurrent_sequences = (UNF_PLOGI_CONCURRENT_SEQ); - login_parms->cl_parms[ARRAY_INDEX_2].open_sequence_per_exchange = (UNF_PLOGI_SEQ_PER_XCHG); - login_parms->high_node_name = UNF_GET_NAME_HIGH_WORD(lport->node_name); - login_parms->low_node_name = UNF_GET_NAME_LOW_WORD(lport->node_name); - login_parms->high_port_name = UNF_GET_NAME_HIGH_WORD(lport->port_name); - login_parms->low_port_name = UNF_GET_NAME_LOW_WORD(lport->port_name); - - UNF_PRINT_SFS_LIMIT(UNF_INFO, lport->port_id, plogi_acc_pld, - sizeof(struct unf_plogi_payload)); -} - -u32 unf_send_plogi_acc(struct unf_lport *lport, struct unf_rport *rport, - struct unf_xchg *xchg) -{ - struct unf_plogi_payload *plogi_acc_pld = NULL; - union unf_sfs_u *fc_entry = NULL; - u32 ret = UNF_RETURN_ERROR; - struct unf_frame_pkg pkg = {0}; - u16 ox_id = 0; - u16 rx_id = 0; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(rport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(xchg, UNF_RETURN_ERROR); - - xchg->cmnd_code = UNF_SET_ELS_ACC_TYPE(ELS_PLOGI); - - xchg->did = rport->nport_id; - xchg->sid = lport->nport_id; - xchg->oid = xchg->sid; - xchg->callback = NULL; - xchg->lport = lport; - xchg->rport = rport; - - xchg->ob_callback = unf_plogi_acc_ob_callback; /* call back for sending PLOGI ACC */ - - unf_fill_package(&pkg, xchg, rport); - pkg.type = UNF_PKG_ELS_REPLY; - fc_entry = xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr; - if (!fc_entry) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) entry can't be NULL with tag(0x%x)", - lport->port_id, xchg->hotpooltag); - - unf_cm_free_xchg(lport, xchg); - return UNF_RETURN_ERROR; - } - - memset(fc_entry, 0, sizeof(union unf_sfs_u)); - plogi_acc_pld = &fc_entry->plogi_acc.payload; - unf_fill_plogi_acc_pld(plogi_acc_pld, lport); - ox_id = xchg->oxid; - rx_id = xchg->rxid; - - ret = unf_ls_gs_cmnd_send(lport, &pkg, xchg); - if (ret != RETURN_OK) - unf_cm_free_xchg((void *)lport, (void *)xchg); - - if (rport->nport_id < UNF_FC_FID_DOM_MGR || - lport->act_topo == UNF_ACT_TOP_P2P_DIRECT) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: PLOGI ACC send %s. Port(0x%x_0x%x_0x%llx)--->RPort(0x%x_0x%llx) with OX_ID(0x%x) RX_ID(0x%x)", - (ret != RETURN_OK) ? "failed" : "succeed", - lport->port_id, lport->nport_id, lport->port_name, - rport->nport_id, rport->port_name, ox_id, rx_id); - } - - return ret; -} - -static void unf_fill_prli_acc_pld(struct unf_prli_payload *prli_acc_pld, - struct unf_lport *lport, - struct unf_rport *rport) -{ - u32 port_mode = UNF_FC4_FRAME_PARM_3_TGT; - - FC_CHECK_RETURN_VOID(prli_acc_pld); - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(rport); - - prli_acc_pld->cmnd = - (UNF_ELS_CMND_ACC | - ((u32)UNF_FC4_FRAME_PAGE_SIZE << UNF_FC4_FRAME_PAGE_SIZE_SHIFT) | - ((u32)(sizeof(struct unf_prli_payload) - UNF_PRLI_SIRT_EXTRA_SIZE))); - - prli_acc_pld->parms[ARRAY_INDEX_0] = - (UNF_FC4_FRAME_PARM_0_FCP | UNF_FC4_FRAME_PARM_0_I_PAIR | - UNF_FC4_FRAME_PARM_0_GOOD_RSP_CODE); - prli_acc_pld->parms[ARRAY_INDEX_1] = UNF_NOT_MEANINGFUL; - prli_acc_pld->parms[ARRAY_INDEX_2] = UNF_NOT_MEANINGFUL; - - /* About INI/TGT mode */ - if (rport->nport_id < UNF_FC_FID_DOM_MGR) { - /* return INI (0x20): R_Port has TGT mode, L_Port has INI mode - */ - port_mode = UNF_FC4_FRAME_PARM_3_INI; - } else { - port_mode = lport->options; - } - - /* About Read xfer_rdy disable */ - prli_acc_pld->parms[ARRAY_INDEX_3] = - (UNF_FC4_FRAME_PARM_3_R_XFER_DIS | port_mode); /* 0x2 */ - - /* About Tape support */ - if (rport->tape_support_needed) { - prli_acc_pld->parms[ARRAY_INDEX_3] |= - (UNF_FC4_FRAME_PARM_3_REC_SUPPORT | - UNF_FC4_FRAME_PARM_3_RETRY_SUPPORT | - UNF_FC4_FRAME_PARM_3_TASK_RETRY_ID_SUPPORT | - UNF_FC4_FRAME_PARM_3_CONF_ALLOW); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "PRLI ACC tape support"); - } - - /* About confirm */ - if (lport->low_level_func.lport_cfg_items.fcp_conf) - prli_acc_pld->parms[ARRAY_INDEX_3] |= - UNF_FC4_FRAME_PARM_3_CONF_ALLOW; /* 0x80 */ - - UNF_PRINT_SFS_LIMIT(UNF_INFO, lport->port_id, prli_acc_pld, - sizeof(struct unf_prli_payload)); -} - -u32 unf_send_prli_acc(struct unf_lport *lport, struct unf_rport *rport, - struct unf_xchg *xchg) -{ - struct unf_prli_payload *prli_acc_pld = NULL; - union unf_sfs_u *fc_entry = NULL; - u32 ret = UNF_RETURN_ERROR; - struct unf_frame_pkg pkg = {0}; - u16 ox_id = 0; - u16 rx_id = 0; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(rport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(xchg, UNF_RETURN_ERROR); - - xchg->cmnd_code = UNF_SET_ELS_ACC_TYPE(ELS_PRLI); - xchg->did = rport->nport_id; - xchg->sid = lport->nport_id; - xchg->oid = xchg->sid; - xchg->lport = lport; - xchg->rport = rport; - - xchg->callback = NULL; - xchg->ob_callback = - unf_prli_acc_ob_callback; /* callback when send succeed */ - - unf_fill_package(&pkg, xchg, rport); - - pkg.type = UNF_PKG_ELS_REPLY; - fc_entry = xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr; - if (!fc_entry) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) entry can't be NULL with tag(0x%x)", - lport->port_id, xchg->hotpooltag); - - unf_cm_free_xchg(lport, xchg); - return UNF_RETURN_ERROR; - } - - memset(fc_entry, 0, sizeof(union unf_sfs_u)); - prli_acc_pld = &fc_entry->prli_acc.payload; - unf_fill_prli_acc_pld(prli_acc_pld, lport, rport); - ox_id = xchg->oxid; - rx_id = xchg->rxid; - - ret = unf_ls_gs_cmnd_send(lport, &pkg, xchg); - if (ret != RETURN_OK) - unf_cm_free_xchg((void *)lport, (void *)xchg); - - if (rport->nport_id < UNF_FC_FID_DOM_MGR || - lport->act_topo == UNF_ACT_TOP_P2P_DIRECT) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: PRLI ACC send %s. Port(0x%x)--->RPort(0x%x) with OX_ID(0x%x) RX_ID(0x%x)", - (ret != RETURN_OK) ? "failed" : "succeed", - lport->port_id, rport->nport_id, ox_id, rx_id); - } - - return ret; -} - -u32 unf_send_rec_acc(struct unf_lport *lport, struct unf_rport *rport, - struct unf_xchg *xchg) -{ - /* Reserved */ - unf_cm_free_xchg((void *)lport, (void *)xchg); - - return RETURN_OK; -} - -static void unf_rrq_acc_ob_callback(struct unf_xchg *xchg) -{ - FC_CHECK_RETURN_VOID(xchg); - - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_MAJOR, - "[info]RRQ ACC Xchg(0x%p) tag(0x%x)", xchg, - xchg->hotpooltag); -} - -static void unf_fill_els_acc_pld(struct unf_els_acc *els_acc_pld) -{ - FC_CHECK_RETURN_VOID(els_acc_pld); - - els_acc_pld->cmnd = (UNF_ELS_CMND_ACC); -} - -u32 unf_send_rscn_acc(struct unf_lport *lport, struct unf_rport *rport, - struct unf_xchg *xchg) -{ - struct unf_els_acc *rscn_acc = NULL; - union unf_sfs_u *fc_entry = NULL; - u32 ret = UNF_RETURN_ERROR; - u16 ox_id = 0; - u16 rx_id = 0; - struct unf_frame_pkg pkg; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(rport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(xchg, UNF_RETURN_ERROR); - - memset(&pkg, 0, sizeof(struct unf_frame_pkg)); - xchg->cmnd_code = UNF_SET_ELS_ACC_TYPE(ELS_RSCN); - xchg->did = rport->nport_id; - xchg->sid = lport->nport_id; - xchg->oid = xchg->sid; - xchg->lport = lport; - xchg->rport = rport; - - xchg->callback = NULL; - xchg->ob_callback = unf_rscn_acc_ob_callback; - - unf_fill_package(&pkg, xchg, rport); - pkg.type = UNF_PKG_ELS_REPLY; - fc_entry = xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr; - if (!fc_entry) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) entry can't be NULL with tag(0x%x)", - lport->port_id, xchg->hotpooltag); - - unf_cm_free_xchg(lport, xchg); - return UNF_RETURN_ERROR; - } - - memset(fc_entry, 0, sizeof(union unf_sfs_u)); - rscn_acc = &fc_entry->els_acc; - unf_fill_els_acc_pld(rscn_acc); - ox_id = xchg->oxid; - rx_id = xchg->rxid; - - ret = unf_ls_gs_cmnd_send(lport, &pkg, xchg); - if (ret != RETURN_OK) - unf_cm_free_xchg((void *)lport, (void *)xchg); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: RSCN ACC send %s. Port(0x%x)--->RPort(0x%x) with OXID(0x%x) RXID(0x%x)", - (ret != RETURN_OK) ? "failed" : "succeed", lport->port_id, - rport->nport_id, ox_id, rx_id); - - return ret; -} - -u32 unf_send_logo_acc(struct unf_lport *lport, struct unf_rport *rport, - struct unf_xchg *xchg) -{ - struct unf_els_acc *logo_acc = NULL; - union unf_sfs_u *fc_entry = NULL; - u32 ret = UNF_RETURN_ERROR; - u16 ox_id = 0; - u16 rx_id = 0; - struct unf_frame_pkg pkg; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(rport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(xchg, UNF_RETURN_ERROR); - - memset(&pkg, 0, sizeof(struct unf_frame_pkg)); - - xchg->cmnd_code = UNF_SET_ELS_ACC_TYPE(ELS_LOGO); - xchg->did = rport->nport_id; - xchg->sid = lport->nport_id; - xchg->oid = xchg->sid; - xchg->lport = lport; - xchg->rport = rport; - xchg->callback = NULL; - xchg->ob_callback = unf_logo_acc_ob_callback; - - unf_fill_package(&pkg, xchg, rport); - pkg.type = UNF_PKG_ELS_REPLY; - fc_entry = xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr; - if (!fc_entry) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) entry can't be NULL with tag(0x%x)", - lport->port_id, xchg->hotpooltag); - - unf_cm_free_xchg(lport, xchg); - return UNF_RETURN_ERROR; - } - - memset(fc_entry, 0, sizeof(union unf_sfs_u)); - logo_acc = &fc_entry->els_acc; - unf_fill_els_acc_pld(logo_acc); - ox_id = xchg->oxid; - rx_id = xchg->rxid; - - ret = unf_ls_gs_cmnd_send(lport, &pkg, xchg); - if (ret != RETURN_OK) - unf_cm_free_xchg((void *)lport, (void *)xchg); - - if (rport->nport_id < UNF_FC_FID_DOM_MGR) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: LOGO ACC send %s. Port(0x%x)--->RPort(0x%x) with OX_ID(0x%x) RX_ID(0x%x)", - (ret != RETURN_OK) ? "failed" : "succeed", - lport->port_id, rport->nport_id, ox_id, rx_id); - } - - return ret; -} - -static u32 unf_send_rrq_acc(struct unf_lport *lport, struct unf_rport *rport, - struct unf_xchg *xchg) -{ - struct unf_els_acc *rrq_acc = NULL; - union unf_sfs_u *fc_entry = NULL; - u32 ret = UNF_RETURN_ERROR; - u16 ox_id = 0; - u16 rx_id = 0; - struct unf_frame_pkg pkg = {0}; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(rport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(xchg, UNF_RETURN_ERROR); - - xchg->did = rport->nport_id; - xchg->sid = lport->nport_id; - xchg->oid = xchg->sid; - xchg->lport = lport; - xchg->rport = rport; - xchg->callback = NULL; /* do noting */ - - fc_entry = xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr; - if (!fc_entry) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) entry can't be NULL with tag(0x%x)", - lport->port_id, xchg->hotpooltag); - - return UNF_RETURN_ERROR; - } - - memset(fc_entry, 0, sizeof(union unf_sfs_u)); - rrq_acc = &fc_entry->els_acc; - xchg->cmnd_code = UNF_SET_ELS_ACC_TYPE(ELS_RRQ); - xchg->ob_callback = unf_rrq_acc_ob_callback; /* do noting */ - unf_fill_els_acc_pld(rrq_acc); - ox_id = xchg->oxid; - rx_id = xchg->rxid; - - unf_fill_package(&pkg, xchg, rport); - pkg.type = UNF_PKG_ELS_REPLY; - ret = unf_ls_gs_cmnd_send(lport, &pkg, xchg); - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]RRQ ACC send %s. Port(0x%x)--->RPort(0x%x) with Xchg(0x%p) OX_ID(0x%x) RX_ID(0x%x)", - (ret != RETURN_OK) ? "failed" : "succeed", lport->port_id, - rport->nport_id, xchg, ox_id, rx_id); - - return ret; -} - -static void unf_fill_pdisc_acc_pld(struct unf_plogi_payload *pdisc_acc_pld, - struct unf_lport *lport) -{ - struct unf_lgn_parm *login_parms = NULL; - - FC_CHECK_RETURN_VOID(pdisc_acc_pld); - FC_CHECK_RETURN_VOID(lport); - - pdisc_acc_pld->cmnd = (UNF_ELS_CMND_ACC); - login_parms = &pdisc_acc_pld->stparms; - - if (lport->act_topo == UNF_ACT_TOP_P2P_FABRIC || - lport->act_topo == UNF_ACT_TOP_P2P_DIRECT) { - login_parms->co_parms.bb_credit = (unf_low_level_bb_credit(lport)); - login_parms->co_parms.alternate_bb_credit_mgmt = UNF_BBCREDIT_MANAGE_NFPORT; - login_parms->co_parms.bbscn = - (lport->act_topo == UNF_ACT_TOP_P2P_FABRIC) - ? 0 - : unf_low_level_bb_scn(lport); - } else { - login_parms->co_parms.bb_credit = UNF_BBCREDIT_LPORT; - login_parms->co_parms.alternate_bb_credit_mgmt = UNF_BBCREDIT_MANAGE_LPORT; - } - - login_parms->co_parms.lowest_version = UNF_PLOGI_VERSION_LOWER; - login_parms->co_parms.highest_version = UNF_PLOGI_VERSION_UPPER; - login_parms->co_parms.continuously_increasing = UNF_CONTIN_INCREASE_SUPPORT; - login_parms->co_parms.bb_receive_data_field_size = (lport->max_frame_size); - login_parms->co_parms.nport_total_concurrent_sequences = (UNF_PLOGI_CONCURRENT_SEQ); - login_parms->co_parms.relative_offset = (UNF_PLOGI_RO_CATEGORY); - login_parms->co_parms.e_d_tov = (lport->ed_tov); - - login_parms->cl_parms[ARRAY_INDEX_2].valid = UNF_CLASS_VALID; /* class-3 */ - login_parms->cl_parms[ARRAY_INDEX_2].received_data_field_size = (lport->max_frame_size); - login_parms->cl_parms[ARRAY_INDEX_2].concurrent_sequences = (UNF_PLOGI_CONCURRENT_SEQ); - login_parms->cl_parms[ARRAY_INDEX_2].open_sequence_per_exchange = (UNF_PLOGI_SEQ_PER_XCHG); - - login_parms->high_node_name = UNF_GET_NAME_HIGH_WORD(lport->node_name); - login_parms->low_node_name = UNF_GET_NAME_LOW_WORD(lport->node_name); - login_parms->high_port_name = UNF_GET_NAME_HIGH_WORD(lport->port_name); - login_parms->low_port_name = UNF_GET_NAME_LOW_WORD(lport->port_name); - - UNF_PRINT_SFS_LIMIT(UNF_INFO, lport->port_id, pdisc_acc_pld, - sizeof(struct unf_plogi_payload)); -} - -u32 unf_send_pdisc_acc(struct unf_lport *lport, struct unf_rport *rport, - struct unf_xchg *xchg) -{ - struct unf_plogi_payload *pdisc_acc_pld = NULL; - union unf_sfs_u *fc_entry = NULL; - u32 ret = UNF_RETURN_ERROR; - u16 ox_id = 0; - u16 rx_id = 0; - struct unf_frame_pkg pkg; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(rport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(xchg, UNF_RETURN_ERROR); - - memset(&pkg, 0, sizeof(struct unf_frame_pkg)); - - xchg->cmnd_code = UNF_SET_ELS_ACC_TYPE(ELS_PDISC); - xchg->did = rport->nport_id; - xchg->sid = lport->nport_id; - xchg->oid = xchg->sid; - xchg->lport = lport; - xchg->rport = rport; - - xchg->callback = NULL; - xchg->ob_callback = unf_pdisc_acc_ob_callback; - - unf_fill_package(&pkg, xchg, rport); - pkg.type = UNF_PKG_ELS_REPLY; - fc_entry = xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr; - if (!fc_entry) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) entry can't be NULL with tag(0x%x)", - lport->port_id, xchg->hotpooltag); - - unf_cm_free_xchg(lport, xchg); - return UNF_RETURN_ERROR; - } - - memset(fc_entry, 0, sizeof(union unf_sfs_u)); - pdisc_acc_pld = &fc_entry->pdisc_acc.payload; - unf_fill_pdisc_acc_pld(pdisc_acc_pld, lport); - ox_id = xchg->oxid; - rx_id = xchg->rxid; - - ret = unf_ls_gs_cmnd_send(lport, &pkg, xchg); - if (ret != RETURN_OK) - unf_cm_free_xchg((void *)lport, (void *)xchg); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: Send PDISC ACC %s. Port(0x%x)--->RPort(0x%x) with OX_ID(0x%x) RX_ID(0x%x)", - (ret != RETURN_OK) ? "failed" : "succeed", lport->port_id, - rport->nport_id, ox_id, rx_id); - - return ret; -} - -static void unf_fill_adisc_acc_pld(struct unf_adisc_payload *adisc_acc_pld, - struct unf_lport *lport) -{ - FC_CHECK_RETURN_VOID(adisc_acc_pld); - FC_CHECK_RETURN_VOID(lport); - - adisc_acc_pld->cmnd = (UNF_ELS_CMND_ACC); - - adisc_acc_pld->hard_address = (lport->nport_id & UNF_ALPA_MASK); - adisc_acc_pld->high_node_name = UNF_GET_NAME_HIGH_WORD(lport->node_name); - adisc_acc_pld->low_node_name = UNF_GET_NAME_LOW_WORD(lport->node_name); - adisc_acc_pld->high_port_name = UNF_GET_NAME_HIGH_WORD(lport->port_name); - adisc_acc_pld->low_port_name = UNF_GET_NAME_LOW_WORD(lport->port_name); - adisc_acc_pld->nport_id = lport->nport_id; - - UNF_PRINT_SFS_LIMIT(UNF_INFO, lport->port_id, adisc_acc_pld, - sizeof(struct unf_adisc_payload)); -} - -u32 unf_send_adisc_acc(struct unf_lport *lport, struct unf_rport *rport, - struct unf_xchg *xchg) -{ - struct unf_adisc_payload *adisc_acc_pld = NULL; - union unf_sfs_u *fc_entry = NULL; - u32 ret = UNF_RETURN_ERROR; - struct unf_frame_pkg pkg = {0}; - u16 ox_id = 0; - u16 rx_id = 0; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(rport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(xchg, UNF_RETURN_ERROR); - - xchg->cmnd_code = UNF_SET_ELS_ACC_TYPE(ELS_ADISC); - xchg->did = rport->nport_id; - xchg->sid = lport->nport_id; - xchg->oid = xchg->sid; - xchg->lport = lport; - xchg->rport = rport; - - xchg->callback = NULL; - xchg->ob_callback = unf_adisc_acc_ob_callback; - unf_fill_package(&pkg, xchg, rport); - pkg.type = UNF_PKG_ELS_REPLY; - fc_entry = xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr; - if (!fc_entry) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) entry can't be NULL with tag(0x%x)", - lport->port_id, xchg->hotpooltag); - - unf_cm_free_xchg(lport, xchg); - return UNF_RETURN_ERROR; - } - - memset(fc_entry, 0, sizeof(union unf_sfs_u)); - adisc_acc_pld = &fc_entry->adisc_acc.adisc_payl; - unf_fill_adisc_acc_pld(adisc_acc_pld, lport); - ox_id = xchg->oxid; - rx_id = xchg->rxid; - - ret = unf_ls_gs_cmnd_send(lport, &pkg, xchg); - if (ret != RETURN_OK) - unf_cm_free_xchg((void *)lport, (void *)xchg); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: Send ADISC ACC %s. Port(0x%x)--->RPort(0x%x) with OX_ID(0x%x) RX_ID(0x%x)", - (ret != RETURN_OK) ? "failed" : "succeed", lport->port_id, - rport->nport_id, ox_id, rx_id); - - return ret; -} - -static void unf_fill_prlo_acc_pld(struct unf_prli_prlo *prlo_acc, - struct unf_lport *lport) -{ - struct unf_prli_payload *prlo_acc_pld = NULL; - - FC_CHECK_RETURN_VOID(prlo_acc); - - prlo_acc_pld = &prlo_acc->payload; - prlo_acc_pld->cmnd = - (UNF_ELS_CMND_ACC | - ((u32)UNF_FC4_FRAME_PAGE_SIZE << UNF_FC4_FRAME_PAGE_SIZE_SHIFT) | - ((u32)sizeof(struct unf_prli_payload))); - prlo_acc_pld->parms[ARRAY_INDEX_0] = - (UNF_FC4_FRAME_PARM_0_FCP | UNF_FC4_FRAME_PARM_0_GOOD_RSP_CODE); - prlo_acc_pld->parms[ARRAY_INDEX_1] = 0; - prlo_acc_pld->parms[ARRAY_INDEX_2] = 0; - prlo_acc_pld->parms[ARRAY_INDEX_3] = 0; - - UNF_PRINT_SFS_LIMIT(UNF_INFO, lport->port_id, prlo_acc_pld, - sizeof(struct unf_prli_payload)); -} - -u32 unf_send_prlo_acc(struct unf_lport *lport, struct unf_rport *rport, - struct unf_xchg *xchg) -{ - struct unf_prli_prlo *prlo_acc = NULL; - union unf_sfs_u *fc_entry = NULL; - u32 ret = UNF_RETURN_ERROR; - u16 ox_id = 0; - u16 rx_id = 0; - struct unf_frame_pkg pkg; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(rport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(xchg, UNF_RETURN_ERROR); - - memset(&pkg, 0, sizeof(struct unf_frame_pkg)); - - xchg->cmnd_code = UNF_SET_ELS_ACC_TYPE(ELS_PRLO); - xchg->did = rport->nport_id; - xchg->sid = lport->nport_id; - xchg->oid = xchg->sid; - xchg->lport = lport; - xchg->rport = rport; - - xchg->callback = NULL; - xchg->ob_callback = NULL; - - unf_fill_package(&pkg, xchg, rport); - pkg.type = UNF_PKG_ELS_REPLY; - fc_entry = xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr; - if (!fc_entry) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) entry can't be NULL with tag(0x%x)", - lport->port_id, xchg->hotpooltag); - - unf_cm_free_xchg(lport, xchg); - return UNF_RETURN_ERROR; - } - - memset(fc_entry, 0, sizeof(union unf_sfs_u)); - prlo_acc = &fc_entry->prlo_acc; - unf_fill_prlo_acc_pld(prlo_acc, lport); - ox_id = xchg->oxid; - rx_id = xchg->rxid; - - ret = unf_ls_gs_cmnd_send(lport, &pkg, xchg); - if (ret != RETURN_OK) - unf_cm_free_xchg((void *)lport, (void *)xchg); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: Send PRLO ACC %s. Port(0x%x)--->RPort(0x%x) with OX_ID(0x%x) RX_ID(0x%x)", - (ret != RETURN_OK) ? "failed" : "succeed", lport->port_id, - rport->nport_id, ox_id, rx_id); - - return ret; -} - -static void unf_prli_acc_ob_callback(struct unf_xchg *xchg) -{ - /* Report R_Port scsi Link Up */ - struct unf_lport *unf_lport = NULL; - struct unf_rport *unf_rport = NULL; - ulong flags = 0; - enum unf_rport_login_state rport_state = UNF_RPORT_ST_INIT; - - FC_CHECK_RETURN_VOID(xchg); - unf_lport = xchg->lport; - unf_rport = xchg->rport; - FC_CHECK_RETURN_VOID(unf_lport); - FC_CHECK_RETURN_VOID(unf_rport); - - /* Update & Report Link Up */ - spin_lock_irqsave(&unf_rport->rport_state_lock, flags); - unf_rport_state_ma(unf_rport, UNF_EVENT_RPORT_READY); - rport_state = unf_rport->rp_state; - if (unf_rport->nport_id < UNF_FC_FID_DOM_MGR) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_KEVENT, - "[event]LOGIN: Port(0x%x) RPort(0x%x) state(0x%x) WWN(0x%llx) prliacc", - unf_lport->port_id, unf_rport->nport_id, - unf_rport->rp_state, unf_rport->port_name); - } - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flags); - - if (rport_state == UNF_RPORT_ST_READY) { - unf_rport->logo_retries = 0; - unf_update_lport_state_by_linkup_event(unf_lport, unf_rport, - unf_rport->options); - } -} - -static void unf_schedule_open_work(struct unf_lport *lport, - struct unf_rport *rport) -{ - /* Used for L_Port port only with TGT, or R_Port only with INI */ - struct unf_lport *unf_lport = lport; - struct unf_rport *unf_rport = rport; - ulong delay = 0; - ulong flag = 0; - u32 ret = 0; - u32 port_feature = INVALID_VALUE32; - - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(rport); - - delay = (ulong)unf_lport->ed_tov; - port_feature = unf_rport->options & UNF_PORT_MODE_BOTH; - - if (unf_lport->options == UNF_PORT_MODE_TGT || - port_feature == UNF_PORT_MODE_INI) { - spin_lock_irqsave(&unf_rport->rport_state_lock, flag); - - ret = unf_rport_ref_inc(unf_rport); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x_0x%x) RPort(0x%x) abnormal, no need open", - unf_lport->port_id, unf_lport->nport_id, unf_rport->nport_id); - - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flag); - return; - } - - /* Delay work pending check */ - if (delayed_work_pending(&unf_rport->open_work)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x_0x%x) RPort(0x%x) open work is running, no need re-open", - unf_lport->port_id, unf_lport->nport_id, - unf_rport->nport_id); - - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flag); - unf_rport_ref_dec(unf_rport); - return; - } - - /* start open work */ - if (queue_delayed_work(unf_wq, &unf_rport->open_work, - (ulong)msecs_to_jiffies((u32)delay))) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x_0x%x) RPort(0x%x) start open work", - unf_lport->port_id, unf_lport->nport_id, unf_rport->nport_id); - - (void)unf_rport_ref_inc(unf_rport); - } - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flag); - - unf_rport_ref_dec(unf_rport); - } -} - -static void unf_plogi_acc_ob_callback(struct unf_xchg *xchg) -{ - struct unf_lport *unf_lport = NULL; - struct unf_rport *unf_rport = NULL; - ulong flags = 0; - - FC_CHECK_RETURN_VOID(xchg); - - spin_lock_irqsave(&xchg->xchg_state_lock, flags); - unf_lport = xchg->lport; - unf_rport = xchg->rport; - spin_unlock_irqrestore(&xchg->xchg_state_lock, flags); - - FC_CHECK_RETURN_VOID(unf_lport); - FC_CHECK_RETURN_VOID(unf_rport); - - /* - * 1. According to FC-LS 4.2.7.1: - * after RCVD PLOGI or sending PLOGI ACC, need to termitate open EXCH - */ - unf_cm_xchg_mgr_abort_io_by_id(unf_lport, unf_rport, - unf_rport->nport_id, unf_lport->nport_id, 0); - - /* 2. Send PLOGI ACC fail */ - if (xchg->ob_callback_sts != UNF_IO_SUCCESS) { - /* Do R_Port recovery */ - unf_rport_error_recovery(unf_rport); - - /* Do not care: Just used for L_Port only is TGT mode or R_Port - * only is INI mode - */ - unf_schedule_open_work(unf_lport, unf_rport); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]LOGIN: Port(0x%x_0x%x_0x%x) send PLOGI ACC failed(0x%x) with RPort(0x%x) feature(0x%x)", - unf_lport->port_id, unf_lport->nport_id, - unf_lport->options, xchg->ob_callback_sts, - unf_rport->nport_id, unf_rport->options); - - return; - } - - /* 3. Private Loop: check whether or not need to send PRLI */ - spin_lock_irqsave(&unf_rport->rport_state_lock, flags); - if (unf_lport->act_topo == UNF_ACT_TOP_PRIVATE_LOOP && - (unf_rport->rp_state == UNF_RPORT_ST_PRLI_WAIT || - unf_rport->rp_state == UNF_RPORT_ST_READY)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x_0x%x) RPort(0x%x) with State(0x%x) return directly", - unf_lport->port_id, unf_lport->nport_id, - unf_rport->nport_id, unf_rport->rp_state); - - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flags); - return; - } - unf_rport_state_ma(unf_rport, UNF_EVENT_RPORT_ENTER_PRLI); - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flags); - - /* 4. Set Port Feature with BOTH: cancel */ - if (unf_rport->options == UNF_PORT_MODE_UNKNOWN && unf_rport->port_name != INVALID_WWPN) - unf_rport->options = unf_get_port_feature(unf_rport->port_name); - - /* - * 5. Check whether need to send PRLI delay - * Call by: RCVD PLOGI ACC or callback for sending PLOGI ACC succeed - */ - unf_check_rport_need_delay_prli(unf_lport, unf_rport, unf_rport->options); - - /* 6. Do not care: Just used for L_Port only is TGT mode or R_Port only - * is INI mode - */ - unf_schedule_open_work(unf_lport, unf_rport); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: Port(0x%x_0x%x_0x%x) send PLOGI ACC succeed with RPort(0x%x) feature(0x%x)", - unf_lport->port_id, unf_lport->nport_id, unf_lport->options, - unf_rport->nport_id, unf_rport->options); -} - -static void unf_flogi_acc_ob_callback(struct unf_xchg *xchg) -{ - /* Callback for Sending FLOGI ACC succeed */ - struct unf_lport *unf_lport = NULL; - struct unf_rport *unf_rport = NULL; - ulong flags = 0; - u64 rport_port_name = 0; - u64 rport_node_name = 0; - - FC_CHECK_RETURN_VOID(xchg); - FC_CHECK_RETURN_VOID(xchg->lport); - FC_CHECK_RETURN_VOID(xchg->rport); - - spin_lock_irqsave(&xchg->xchg_state_lock, flags); - unf_lport = xchg->lport; - unf_rport = xchg->rport; - spin_unlock_irqrestore(&xchg->xchg_state_lock, flags); - - spin_lock_irqsave(&unf_rport->rport_state_lock, flags); - if (unf_rport->port_name == 0 && unf_rport->node_name == 0) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: Port(0x%x_0x%x_0x%x) already send Plogi with RPort(0x%x) feature(0x%x).", - unf_lport->port_id, unf_lport->nport_id, unf_lport->options, - unf_rport->nport_id, unf_rport->options); - - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flags); - return; - } - - rport_port_name = unf_rport->port_name; - rport_node_name = unf_rport->node_name; - - /* Swap case: Set WWPN & WWNN with zero */ - unf_rport->port_name = 0; - unf_rport->node_name = 0; - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flags); - - /* Enter PLOGI stage: after send FLOGI ACC succeed */ - unf_login_with_rport_in_n2n(unf_lport, rport_port_name, rport_node_name); -} - -static void unf_rscn_acc_ob_callback(struct unf_xchg *xchg) -{ -} - -static void unf_logo_acc_ob_callback(struct unf_xchg *xchg) -{ -} - -static void unf_adisc_acc_ob_callback(struct unf_xchg *xchg) -{ -} - -static void unf_pdisc_acc_ob_callback(struct unf_xchg *xchg) -{ -} - -static inline u8 unf_determin_bbscn(u8 local_bbscn, u8 remote_bbscn) -{ - if (remote_bbscn == 0 || local_bbscn == 0) - local_bbscn = 0; - else - local_bbscn = local_bbscn > remote_bbscn ? local_bbscn : remote_bbscn; - - return local_bbscn; -} - -static void unf_cfg_lowlevel_fabric_params(struct unf_lport *lport, - struct unf_rport *rport, - struct unf_fabric_parm *login_parms) -{ - struct unf_port_login_parms login_co_parms = {0}; - u32 remote_edtov = 0; - u32 ret = 0; - u8 remote_edtov_resolution = 0; /* 0:ms; 1:ns */ - - if (!lport->low_level_func.port_mgr_op.ll_port_config_set) - return; - - login_co_parms.remote_rttov_tag = (u8)UNF_GET_RT_TOV_FROM_PARAMS(login_parms); - login_co_parms.remote_edtov_tag = 0; - login_co_parms.remote_bb_credit = (u16)UNF_GET_BB_CREDIT_FROM_PARAMS(login_parms); - login_co_parms.compared_bbscn = - (u32)unf_determin_bbscn((u8)lport->low_level_func.lport_cfg_items.bbscn, - (u8)UNF_GET_BB_SC_N_FROM_PARAMS(login_parms)); - - remote_edtov_resolution = (u8)UNF_GET_E_D_TOV_RESOLUTION_FROM_PARAMS(login_parms); - remote_edtov = UNF_GET_E_D_TOV_FROM_PARAMS(login_parms); - login_co_parms.compared_edtov_val = - remote_edtov_resolution ? (remote_edtov / UNF_OS_MS_TO_NS) - : remote_edtov; - - login_co_parms.compared_ratov_val = UNF_GET_RA_TOV_FROM_PARAMS(login_parms); - login_co_parms.els_cmnd_code = ELS_FLOGI; - - if (UNF_TOP_P2P_MASK & (u32)lport->act_topo) { - login_co_parms.act_topo = (login_parms->co_parms.nport == UNF_F_PORT) - ? UNF_ACT_TOP_P2P_FABRIC - : UNF_ACT_TOP_P2P_DIRECT; - } else { - login_co_parms.act_topo = lport->act_topo; - } - - ret = lport->low_level_func.port_mgr_op.ll_port_config_set((void *)lport->fc_port, - UNF_PORT_CFG_UPDATE_FABRIC_PARAM, (void *)&login_co_parms); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Lowlevel unsupport fabric config"); - } -} - -u32 unf_check_flogi_params(struct unf_lport *lport, struct unf_rport *rport, - struct unf_fabric_parm *fabric_parms) -{ - u32 ret = RETURN_OK; - u32 high_port_name; - u32 low_port_name; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(rport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(fabric_parms, UNF_RETURN_ERROR); - - if (fabric_parms->cl_parms[ARRAY_INDEX_2].valid == UNF_CLASS_INVALID) { - /* Discard directly */ - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) NPort_ID(0x%x) FLOGI not support class3", - lport->port_id, rport->nport_id); - - return UNF_RETURN_ERROR; - } - - high_port_name = UNF_GET_NAME_HIGH_WORD(lport->port_name); - low_port_name = UNF_GET_NAME_LOW_WORD(lport->port_name); - if (fabric_parms->high_port_name == high_port_name && - fabric_parms->low_port_name == low_port_name) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]The wwpn(0x%x%x) of lport(0x%x) is same as the wwpn of rport(0x%x)", - high_port_name, low_port_name, lport->port_id, rport->nport_id); - return UNF_RETURN_ERROR; - } - - return ret; -} - -static void unf_save_fabric_params(struct unf_lport *lport, - struct unf_rport *rport, - struct unf_fabric_parm *fabric_parms) -{ - u64 fabric_node_name = 0; - - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(rport); - FC_CHECK_RETURN_VOID(fabric_parms); - - fabric_node_name = (u64)(((u64)(fabric_parms->high_node_name) << UNF_SHIFT_32) | - ((u64)(fabric_parms->low_node_name))); - - /* R_Port for 0xfffffe is used for FLOGI, not need to save WWN */ - if (fabric_parms->co_parms.bb_receive_data_field_size > UNF_MAX_FRAME_SIZE) - rport->max_frame_size = UNF_MAX_FRAME_SIZE; /* 2112 */ - else - rport->max_frame_size = fabric_parms->co_parms.bb_receive_data_field_size; - - /* with Fabric attribute */ - if (fabric_parms->co_parms.nport == UNF_F_PORT) { - rport->ed_tov = fabric_parms->co_parms.e_d_tov; - rport->ra_tov = fabric_parms->co_parms.r_a_tov; - lport->ed_tov = fabric_parms->co_parms.e_d_tov; - lport->ra_tov = fabric_parms->co_parms.r_a_tov; - lport->fabric_node_name = fabric_node_name; - } - - /* Configure info from FLOGI to chip */ - unf_cfg_lowlevel_fabric_params(lport, rport, fabric_parms); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "[info]Port(0x%x) Rport(0x%x) login parameter: E_D_TOV = %u. LPort E_D_TOV = %u. fabric nodename: 0x%x%x", - lport->port_id, rport->nport_id, (fabric_parms->co_parms.e_d_tov), - lport->ed_tov, fabric_parms->high_node_name, fabric_parms->low_node_name); -} - -u32 unf_flogi_handler(struct unf_lport *lport, u32 sid, struct unf_xchg *xchg) -{ - struct unf_rport *unf_rport = NULL; - struct unf_flogi_fdisc_acc *flogi_frame = NULL; - struct unf_fabric_parm *fabric_login_parms = NULL; - u32 ret = UNF_RETURN_ERROR; - ulong flag = 0; - u64 wwpn = 0; - u64 wwnn = 0; - enum unf_act_topo unf_active_topo; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(xchg, UNF_RETURN_ERROR); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]LOGIN: Port(0x%x)<---RPort(0x%x) Receive FLOGI with OX_ID(0x%x)", - lport->port_id, sid, xchg->oxid); - - UNF_SERVICE_COLLECT(lport->link_service_info, UNF_SERVICE_ITEM_FLOGI); - - /* Check L_Port state: Offline */ - if (lport->states >= UNF_LPORT_ST_OFFLINE) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) with state(0x%x) not need to handle FLOGI", - lport->port_id, lport->states); - - unf_cm_free_xchg(lport, xchg); - return ret; - } - - flogi_frame = &xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr->flogi; - fabric_login_parms = &flogi_frame->flogi_payload.fabric_parms; - UNF_PRINT_SFS_LIMIT(UNF_INFO, lport->port_id, &flogi_frame->flogi_payload, - sizeof(struct unf_flogi_fdisc_payload)); - wwpn = (u64)(((u64)(fabric_login_parms->high_port_name) << UNF_SHIFT_32) | - ((u64)fabric_login_parms->low_port_name)); - wwnn = (u64)(((u64)(fabric_login_parms->high_node_name) << UNF_SHIFT_32) | - ((u64)fabric_login_parms->low_node_name)); - - /* Get (new) R_Port: reuse only */ - unf_rport = unf_get_rport_by_nport_id(lport, UNF_FC_FID_FLOGI); - unf_rport = unf_get_safe_rport(lport, unf_rport, UNF_RPORT_REUSE_ONLY, UNF_FC_FID_FLOGI); - if (unlikely(!unf_rport)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) has no RPort. do nothing", lport->port_id); - - unf_cm_free_xchg(lport, xchg); - return UNF_RETURN_ERROR; - } - - /* Update R_Port info */ - spin_lock_irqsave(&unf_rport->rport_state_lock, flag); - unf_rport->port_name = wwpn; - unf_rport->node_name = wwnn; - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flag); - - /* Check RCVD FLOGI parameters: only for class-3 */ - ret = unf_check_flogi_params(lport, unf_rport, fabric_login_parms); - if (ret != RETURN_OK) { - /* Discard directly */ - unf_cm_free_xchg(lport, xchg); - return UNF_RETURN_ERROR; - } - - /* Save fabric parameters */ - unf_save_fabric_params(lport, unf_rport, fabric_login_parms); - - if ((u32)lport->act_topo & UNF_TOP_P2P_MASK) { - unf_active_topo = - (fabric_login_parms->co_parms.nport == UNF_F_PORT) - ? UNF_ACT_TOP_P2P_FABRIC - : UNF_ACT_TOP_P2P_DIRECT; - unf_lport_update_topo(lport, unf_active_topo); - } - /* Send ACC for FLOGI */ - ret = unf_send_flogi_acc(lport, unf_rport, xchg); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]LOGIN: Port(0x%x) send FLOGI ACC failed and do recover", - lport->port_id); - - /* Do L_Port recovery */ - unf_lport_error_recovery(lport); - } - - return ret; -} - -static void unf_cfg_lowlevel_port_params(struct unf_lport *lport, - struct unf_rport *rport, - struct unf_lgn_parm *login_parms, - u32 cmd_type) -{ - struct unf_port_login_parms login_co_parms = {0}; - u32 ret = 0; - - if (!lport->low_level_func.port_mgr_op.ll_port_config_set) - return; - - login_co_parms.rport_index = rport->rport_index; - login_co_parms.seq_cnt = 0; - login_co_parms.ed_tov = 0; /* ms */ - login_co_parms.ed_tov_timer_val = lport->ed_tov; - login_co_parms.tx_mfs = rport->max_frame_size; - - login_co_parms.remote_rttov_tag = (u8)UNF_GET_RT_TOV_FROM_PARAMS(login_parms); - login_co_parms.remote_edtov_tag = 0; - login_co_parms.remote_bb_credit = (u16)UNF_GET_BB_CREDIT_FROM_PARAMS(login_parms); - login_co_parms.els_cmnd_code = cmd_type; - - if (lport->act_topo == UNF_ACT_TOP_PRIVATE_LOOP) { - login_co_parms.compared_bbscn = 0; - } else { - login_co_parms.compared_bbscn = - (u32)unf_determin_bbscn((u8)lport->low_level_func.lport_cfg_items.bbscn, - (u8)UNF_GET_BB_SC_N_FROM_PARAMS(login_parms)); - } - - login_co_parms.compared_edtov_val = lport->ed_tov; - login_co_parms.compared_ratov_val = lport->ra_tov; - - ret = lport->low_level_func.port_mgr_op.ll_port_config_set((void *)lport->fc_port, - UNF_PORT_CFG_UPDATE_PLOGI_PARAM, (void *)&login_co_parms); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) Lowlevel unsupport port config", lport->port_id); - } -} - -u32 unf_check_plogi_params(struct unf_lport *lport, struct unf_rport *rport, - struct unf_lgn_parm *login_parms) -{ - u32 ret = RETURN_OK; - ulong flag = 0; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(rport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(login_parms, UNF_RETURN_ERROR); - - /* Parameters check: Class-type */ - if (login_parms->cl_parms[ARRAY_INDEX_2].valid == UNF_CLASS_INVALID || - login_parms->co_parms.bb_receive_data_field_size == 0) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) RPort N_Port_ID(0x%x) with PLOGI parameters invalid: class3(%u), BBReceiveDataFieldSize(0x%x), send LOGO", - lport->port_id, rport->nport_id, - login_parms->cl_parms[ARRAY_INDEX_2].valid, - login_parms->co_parms.bb_receive_data_field_size); - - spin_lock_irqsave(&rport->rport_state_lock, flag); - unf_rport_state_ma(rport, UNF_EVENT_RPORT_LOGO); /* --->>> LOGO */ - spin_unlock_irqrestore(&rport->rport_state_lock, flag); - - /* Enter LOGO stage */ - unf_rport_enter_logo(lport, rport); - return UNF_RETURN_ERROR; - } - - /* 16G FC Brocade SW, Domain Controller's PLOGI both support CLASS-1 & - * CLASS-2 - */ - if (login_parms->cl_parms[ARRAY_INDEX_0].valid == UNF_CLASS_VALID || - login_parms->cl_parms[ARRAY_INDEX_1].valid == UNF_CLASS_VALID) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "[info]Port(0x%x) get PLOGI class1(%u) class2(%u) from N_Port_ID(0x%x)", - lport->port_id, login_parms->cl_parms[ARRAY_INDEX_0].valid, - login_parms->cl_parms[ARRAY_INDEX_1].valid, rport->nport_id); - } - - return ret; -} - -static void unf_save_plogi_params(struct unf_lport *lport, - struct unf_rport *rport, - struct unf_lgn_parm *login_parms, - u32 cmd_code) -{ -#define UNF_DELAY_TIME 100 /* WWPN smaller delay to send PRLI with COM mode */ - - u64 wwpn = INVALID_VALUE64; - u64 wwnn = INVALID_VALUE64; - u32 ed_tov = 0; - u32 remote_edtov = 0; - - if (login_parms->co_parms.bb_receive_data_field_size > UNF_MAX_FRAME_SIZE) - rport->max_frame_size = UNF_MAX_FRAME_SIZE; /* 2112 */ - else - rport->max_frame_size = login_parms->co_parms.bb_receive_data_field_size; - - wwnn = (u64)(((u64)(login_parms->high_node_name) << UNF_SHIFT_32) | - ((u64)login_parms->low_node_name)); - wwpn = (u64)(((u64)(login_parms->high_port_name) << UNF_SHIFT_32) | - ((u64)login_parms->low_port_name)); - - remote_edtov = login_parms->co_parms.e_d_tov; - ed_tov = login_parms->co_parms.e_d_tov_resolution - ? (remote_edtov / UNF_OS_MS_TO_NS) - : remote_edtov; - - rport->port_name = wwpn; - rport->node_name = wwnn; - rport->local_nport_id = lport->nport_id; - - if (lport->act_topo == UNF_ACT_TOP_P2P_DIRECT || - lport->act_topo == UNF_ACT_TOP_PRIVATE_LOOP) { - /* P2P or Private Loop or FCoE VN2VN */ - lport->ed_tov = (lport->ed_tov > ed_tov) ? lport->ed_tov : ed_tov; - lport->ra_tov = 2 * lport->ed_tov; /* 2 * E_D_TOV */ - - if (ed_tov != 0) - rport->ed_tov = ed_tov; - else - rport->ed_tov = UNF_DEFAULT_EDTOV; - } else { - /* SAN: E_D_TOV updated by FLOGI */ - rport->ed_tov = lport->ed_tov; - } - - /* WWPN smaller: delay to send PRLI */ - if (rport->port_name > lport->port_name) - rport->ed_tov += UNF_DELAY_TIME; /* 100ms */ - - /* Configure port parameters to low level (chip) */ - unf_cfg_lowlevel_port_params(lport, rport, login_parms, cmd_code); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "[info]Port(0x%x) RPort(0x%x) with WWPN(0x%llx) WWNN(0x%llx) login: ED_TOV(%u) Port: ED_TOV(%u)", - lport->port_id, rport->nport_id, rport->port_name, rport->node_name, - ed_tov, lport->ed_tov); -} - -static bool unf_check_bbscn_is_enabled(u8 local_bbscn, u8 remote_bbscn) -{ - return unf_determin_bbscn(local_bbscn, remote_bbscn) ? true : false; -} - -static u32 unf_irq_process_switch2thread(void *lport, struct unf_xchg *xchg, - unf_event_task evt_task) -{ - struct unf_cm_event_report *event = NULL; - struct unf_xchg *unf_xchg = NULL; - u32 ret = 0; - struct unf_lport *unf_lport = NULL; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(xchg, UNF_RETURN_ERROR); - unf_lport = lport; - unf_xchg = xchg; - - if (unlikely(!unf_lport->event_mgr.unf_get_free_event_func || - !unf_lport->event_mgr.unf_post_event_func || - !unf_lport->event_mgr.unf_release_event)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) event function is NULL", - unf_lport->port_id); - - return UNF_RETURN_ERROR; - } - - ret = unf_xchg_ref_inc(unf_xchg, SFS_RESPONSE); - FC_CHECK_RETURN_VALUE((ret == RETURN_OK), UNF_RETURN_ERROR); - - event = unf_lport->event_mgr.unf_get_free_event_func((void *)lport); - FC_CHECK_RETURN_VALUE(event, UNF_RETURN_ERROR); - - event->lport = unf_lport; - event->event_asy_flag = UNF_EVENT_ASYN; - event->unf_event_task = evt_task; - event->para_in = xchg; - unf_lport->event_mgr.unf_post_event_func(unf_lport, event); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x) start to switch thread process now", - unf_lport->port_id); - - return ret; -} - -u32 unf_plogi_handler_com_process(struct unf_xchg *xchg) -{ - struct unf_xchg *unf_xchg = xchg; - struct unf_lport *unf_lport = NULL; - struct unf_rport *unf_rport = NULL; - struct unf_plogi_pdisc *plogi_frame = NULL; - struct unf_lgn_parm *login_parms = NULL; - u32 ret = UNF_RETURN_ERROR; - ulong flag = 0; - - FC_CHECK_RETURN_VALUE(unf_xchg, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(unf_xchg->lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(unf_xchg->rport, UNF_RETURN_ERROR); - - unf_lport = unf_xchg->lport; - unf_rport = unf_xchg->rport; - plogi_frame = &unf_xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr->plogi; - login_parms = &plogi_frame->payload.stparms; - - unf_save_plogi_params(unf_lport, unf_rport, login_parms, ELS_PLOGI); - - /* Update state: PLOGI_WAIT */ - spin_lock_irqsave(&unf_rport->rport_state_lock, flag); - unf_rport->nport_id = unf_xchg->sid; - unf_rport_state_ma(unf_rport, UNF_EVENT_RPORT_ENTER_PLOGI); - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flag); - - /* Send PLOGI ACC to remote port */ - ret = unf_send_plogi_acc(unf_lport, unf_rport, unf_xchg); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]LOGIN: Port(0x%x) send PLOGI ACC failed", - unf_lport->port_id); - - /* NOTE: exchange has been freed inner(before) */ - unf_rport_error_recovery(unf_rport); - return ret; - } - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "[info]LOGIN: Port(0x%x) send PLOGI ACC to Port(0x%x) succeed", - unf_lport->port_id, unf_rport->nport_id); - - return ret; -} - -int unf_plogi_async_handle(void *argc_in, void *argc_out) -{ - struct unf_xchg *xchg = (struct unf_xchg *)argc_in; - u32 ret = RETURN_OK; - - FC_CHECK_RETURN_VALUE(xchg, UNF_RETURN_ERROR); - - ret = unf_plogi_handler_com_process(xchg); - - unf_xchg_ref_dec(xchg, SFS_RESPONSE); - - return (int)ret; -} - -u32 unf_plogi_handler(struct unf_lport *lport, u32 sid, struct unf_xchg *xchg) -{ - struct unf_xchg *unf_xchg = xchg; - struct unf_lport *unf_lport = lport; - struct unf_rport *unf_rport = NULL; - struct unf_plogi_pdisc *plogi_frame = NULL; - struct unf_lgn_parm *login_parms = NULL; - struct unf_rjt_info rjt_info = {0}; - u64 wwpn = INVALID_VALUE64; - u32 ret = UNF_RETURN_ERROR; - bool bbscn_enabled = false; - bool switch2thread = false; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(xchg, UNF_RETURN_ERROR); - - /* 1. Maybe: PLOGI is sent by Name server */ - if (sid < UNF_FC_FID_DOM_MGR || - lport->act_topo == UNF_ACT_TOP_P2P_DIRECT) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: Receive PLOGI. Port(0x%x_0x%x)<---RPort(0x%x) with OX_ID(0x%x)", - lport->port_id, lport->nport_id, sid, xchg->oxid); - } - - UNF_SERVICE_COLLECT(lport->link_service_info, UNF_SERVICE_ITEM_PLOGI); - - /* 2. State check: Offline */ - if (unf_lport->states >= UNF_LPORT_ST_OFFLINE) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x_0x%x) received PLOGI with state(0x%x)", - unf_lport->port_id, unf_lport->nport_id, unf_lport->states); - - unf_cm_free_xchg(unf_lport, unf_xchg); - return UNF_RETURN_ERROR; - } - - /* Get R_Port by WWpn */ - plogi_frame = &unf_xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr->plogi; - login_parms = &plogi_frame->payload.stparms; - - UNF_PRINT_SFS_LIMIT(UNF_INFO, unf_lport->port_id, &plogi_frame->payload, - sizeof(struct unf_plogi_payload)); - - wwpn = (u64)(((u64)(login_parms->high_port_name) << UNF_SHIFT_32) | - ((u64)login_parms->low_port_name)); - - /* 3. Get (new) R_Port (by wwpn) */ - unf_rport = unf_find_rport(unf_lport, sid, wwpn); - unf_rport = unf_get_safe_rport(unf_lport, unf_rport, UNF_RPORT_REUSE_ONLY, sid); - if (!unf_rport) { - memset(&rjt_info, 0, sizeof(struct unf_rjt_info)); - rjt_info.els_cmnd_code = ELS_PLOGI; - rjt_info.reason_code = UNF_LS_RJT_BUSY; - rjt_info.reason_explanation = UNF_LS_RJT_INSUFFICIENT_RESOURCES; - - /* R_Port is NULL: Send ELS RJT for PLOGI */ - (void)unf_send_els_rjt_by_did(unf_lport, unf_xchg, sid, &rjt_info); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) has no RPort and send PLOGI reject", - unf_lport->port_id); - return RETURN_OK; - } - - /* - * 4. According to FC-LS 4.2.7.1: - * After RCVD PLogi or send Plogi ACC, need to termitate open EXCH - */ - unf_cm_xchg_mgr_abort_io_by_id(unf_lport, unf_rport, sid, unf_lport->nport_id, 0); - - /* 5. Cancel recovery timer work after RCVD PLOGI */ - if (cancel_delayed_work(&unf_rport->recovery_work)) - atomic_dec(&unf_rport->rport_ref_cnt); - - /* - * 6. Plogi parameters check - * Call by: (RCVD) PLOGI handler & callback function for RCVD PLOGI_ACC - */ - ret = unf_check_plogi_params(unf_lport, unf_rport, login_parms); - if (ret != RETURN_OK) { - unf_cm_free_xchg(unf_lport, unf_xchg); - return UNF_RETURN_ERROR; - } - - unf_xchg->lport = lport; - unf_xchg->rport = unf_rport; - unf_xchg->sid = sid; - - /* 7. About bbscn for context change */ - bbscn_enabled = - unf_check_bbscn_is_enabled((u8)unf_lport->low_level_func.lport_cfg_items.bbscn, - (u8)UNF_GET_BB_SC_N_FROM_PARAMS(login_parms)); - if (unf_lport->act_topo == UNF_ACT_TOP_P2P_DIRECT && bbscn_enabled) { - switch2thread = true; - unf_lport->bbscn_support = true; - } - - /* 8. Process PLOGI Frame: switch to thread if necessary */ - if (switch2thread && unf_lport->root_lport == unf_lport) { - /* Wait for LR complete sync */ - ret = unf_irq_process_switch2thread(unf_lport, unf_xchg, unf_plogi_async_handle); - } else { - ret = unf_plogi_handler_com_process(unf_xchg); - } - - return ret; -} - -static void unf_obtain_tape_capacity(struct unf_lport *lport, - struct unf_rport *rport, u32 tape_parm) -{ - u32 rec_support = 0; - u32 task_retry_support = 0; - u32 retry_support = 0; - - rec_support = tape_parm & UNF_FC4_FRAME_PARM_3_REC_SUPPORT; - task_retry_support = - tape_parm & UNF_FC4_FRAME_PARM_3_TASK_RETRY_ID_SUPPORT; - retry_support = tape_parm & UNF_FC4_FRAME_PARM_3_RETRY_SUPPORT; - - if (lport->low_level_func.lport_cfg_items.tape_support && - rec_support && task_retry_support && retry_support) { - rport->tape_support_needed = true; - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x_0x%x) FC_tape is needed for RPort(0x%x)", - lport->port_id, lport->nport_id, rport->nport_id); - } - - if ((tape_parm & UNF_FC4_FRAME_PARM_3_CONF_ALLOW) && - lport->low_level_func.lport_cfg_items.fcp_conf) { - rport->fcp_conf_needed = true; - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x_0x%x) FCP confirm is needed for RPort(0x%x)", - lport->port_id, lport->nport_id, rport->nport_id); - } -} - -static u32 unf_prli_handler_com_process(struct unf_xchg *xchg) -{ - struct unf_prli_prlo *prli = NULL; - u32 ret = UNF_RETURN_ERROR; - ulong flags = 0; - u32 sid = 0; - struct unf_lport *unf_lport = NULL; - struct unf_rport *unf_rport = NULL; - struct unf_xchg *unf_xchg = NULL; - - unf_xchg = xchg; - FC_CHECK_RETURN_VALUE(unf_xchg->lport, UNF_RETURN_ERROR); - unf_lport = unf_xchg->lport; - sid = xchg->sid; - - UNF_SERVICE_COLLECT(unf_lport->link_service_info, UNF_SERVICE_ITEM_PRLI); - - /* 1. Get R_Port: for each R_Port from rport_busy_list */ - unf_rport = unf_get_rport_by_nport_id(unf_lport, sid); - if (!unf_rport) { - /* non session (R_Port) existence */ - (void)unf_send_logo_by_did(unf_lport, sid); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x_0x%x) received PRLI but no RPort SID(0x%x) OX_ID(0x%x)", - unf_lport->port_id, unf_lport->nport_id, sid, xchg->oxid); - - unf_cm_free_xchg(unf_lport, xchg); - return ret; - } - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "[info]LOGIN: Receive PRLI. Port(0x%x)<---RPort(0x%x) with S_ID(0x%x)", - unf_lport->port_id, unf_rport->nport_id, sid); - - /* 2. Get PRLI info */ - prli = &xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr->prli; - if (sid < UNF_FC_FID_DOM_MGR || unf_lport->act_topo == UNF_ACT_TOP_P2P_DIRECT) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: Receive PRLI. Port(0x%x_0x%x)<---RPort(0x%x) parameter-3(0x%x) OX_ID(0x%x)", - unf_lport->port_id, unf_lport->nport_id, sid, - prli->payload.parms[ARRAY_INDEX_3], xchg->oxid); - } - - UNF_PRINT_SFS_LIMIT(UNF_INFO, unf_lport->port_id, &prli->payload, - sizeof(struct unf_prli_payload)); - - spin_lock_irqsave(&unf_rport->rport_state_lock, flags); - - /* 3. Increase R_Port ref_cnt */ - ret = unf_rport_ref_inc(unf_rport); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) RPort(0x%x_0x%p) is removing and do nothing", - unf_lport->port_id, unf_rport->nport_id, unf_rport); - - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flags); - - unf_cm_free_xchg(unf_lport, xchg); - return RETURN_ERROR; - } - - /* 4. Cancel R_Port Open work */ - if (cancel_delayed_work(&unf_rport->open_work)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x_0x%x) RPort(0x%x) cancel open work succeed", - unf_lport->port_id, unf_lport->nport_id, unf_rport->nport_id); - - /* This is not the last counter */ - atomic_dec(&unf_rport->rport_ref_cnt); - } - - /* 5. Check R_Port state */ - if (unf_rport->rp_state != UNF_RPORT_ST_PRLI_WAIT && - unf_rport->rp_state != UNF_RPORT_ST_READY) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x_0x%x) RPort(0x%x) with state(0x%x) when received PRLI, send LOGO", - unf_lport->port_id, unf_lport->nport_id, - unf_rport->nport_id, unf_rport->rp_state); - - unf_rport_state_ma(unf_rport, UNF_EVENT_RPORT_LOGO); - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flags); - - /* NOTE: Start to send LOGO */ - unf_rport_enter_logo(unf_lport, unf_rport); - - unf_cm_free_xchg(unf_lport, xchg); - unf_rport_ref_dec(unf_rport); - - return RETURN_ERROR; - } - - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flags); - - /* 6. Update R_Port options(INI/TGT/BOTH) */ - unf_rport->options = - prli->payload.parms[ARRAY_INDEX_3] & - (UNF_FC4_FRAME_PARM_3_TGT | UNF_FC4_FRAME_PARM_3_INI); - - unf_update_port_feature(unf_rport->port_name, unf_rport->options); - - /* for Confirm */ - unf_rport->fcp_conf_needed = false; - - unf_obtain_tape_capacity(unf_lport, unf_rport, prli->payload.parms[ARRAY_INDEX_3]); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "[info]Port(0x%x_0x%x) RPort(0x%x) parameter-3(0x%x) options(0x%x)", - unf_lport->port_id, unf_lport->nport_id, unf_rport->nport_id, - prli->payload.parms[ARRAY_INDEX_3], unf_rport->options); - - /* 7. Send PRLI ACC */ - ret = unf_send_prli_acc(unf_lport, unf_rport, xchg); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]LOGIN: Port(0x%x_0x%x) RPort(0x%x) send PRLI ACC failed", - unf_lport->port_id, unf_lport->nport_id, unf_rport->nport_id); - - /* NOTE: exchange has been freed inner(before) */ - unf_rport_error_recovery(unf_rport); - } - - /* 8. Decrease R_Port ref_cnt */ - unf_rport_ref_dec(unf_rport); - - return ret; -} - -int unf_prli_async_handle(void *argc_in, void *argc_out) -{ - struct unf_xchg *xchg = (struct unf_xchg *)argc_in; - u32 ret = RETURN_OK; - - FC_CHECK_RETURN_VALUE(xchg, UNF_RETURN_ERROR); - - ret = unf_prli_handler_com_process(xchg); - - unf_xchg_ref_dec(xchg, SFS_RESPONSE); - - return (int)ret; -} - -u32 unf_prli_handler(struct unf_lport *lport, u32 sid, struct unf_xchg *xchg) -{ - u32 ret = UNF_RETURN_ERROR; - bool switch2thread = false; - struct unf_lport *unf_lport = NULL; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(xchg, UNF_RETURN_ERROR); - - xchg->sid = sid; - xchg->lport = lport; - unf_lport = lport; - - if (lport->bbscn_support && - lport->act_topo == UNF_ACT_TOP_P2P_DIRECT) - switch2thread = true; - - if (switch2thread && unf_lport->root_lport == unf_lport) { - /* Wait for LR done sync */ - ret = unf_irq_process_switch2thread(lport, xchg, unf_prli_async_handle); - } else { - ret = unf_prli_handler_com_process(xchg); - } - - return ret; -} - -static void unf_save_rscn_port_id(struct unf_rscn_mgr *rscn_mg, - struct unf_rscn_port_id_page *rscn_port_id) -{ - struct unf_port_id_page *exit_port_id_page = NULL; - struct unf_port_id_page *new_port_id_page = NULL; - struct list_head *node = NULL; - struct list_head *next_node = NULL; - ulong flag = 0; - bool is_repeat = false; - - FC_CHECK_RETURN_VOID(rscn_mg); - FC_CHECK_RETURN_VOID(rscn_port_id); - - /* 1. check new RSCN Port_ID (RSNC_Page) whether within RSCN_Mgr or not - */ - spin_lock_irqsave(&rscn_mg->rscn_id_list_lock, flag); - if (list_empty(&rscn_mg->list_using_rscn_page)) { - is_repeat = false; - } else { - /* Check repeat: for each exist RSCN page form RSCN_Mgr Page - * list - */ - list_for_each_safe(node, next_node, &rscn_mg->list_using_rscn_page) { - exit_port_id_page = list_entry(node, struct unf_port_id_page, - list_node_rscn); - if (exit_port_id_page->port_id_port == rscn_port_id->port_id_port && - exit_port_id_page->port_id_area == rscn_port_id->port_id_area && - exit_port_id_page->port_id_domain == rscn_port_id->port_id_domain) { - is_repeat = true; - break; - } - } - } - spin_unlock_irqrestore(&rscn_mg->rscn_id_list_lock, flag); - - FC_CHECK_RETURN_VOID(rscn_mg->unf_get_free_rscn_node); - - /* 2. Get & add free RSNC Node --->>> RSCN_Mgr */ - if (!is_repeat) { - new_port_id_page = rscn_mg->unf_get_free_rscn_node(rscn_mg); - if (!new_port_id_page) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, - UNF_ERR, "[err]Get free RSCN node failed"); - - return; - } - - new_port_id_page->addr_format = rscn_port_id->addr_format; - new_port_id_page->event_qualifier = rscn_port_id->event_qualifier; - new_port_id_page->reserved = rscn_port_id->reserved; - new_port_id_page->port_id_domain = rscn_port_id->port_id_domain; - new_port_id_page->port_id_area = rscn_port_id->port_id_area; - new_port_id_page->port_id_port = rscn_port_id->port_id_port; - - /* Add entry to list: using_rscn_page */ - spin_lock_irqsave(&rscn_mg->rscn_id_list_lock, flag); - list_add_tail(&new_port_id_page->list_node_rscn, &rscn_mg->list_using_rscn_page); - spin_unlock_irqrestore(&rscn_mg->rscn_id_list_lock, flag); - } else { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x) has repeat RSCN node with domain(0x%x) area(0x%x)", - rscn_port_id->port_id_domain, rscn_port_id->port_id_area, - rscn_port_id->port_id_port); - } -} - -static u32 unf_analysis_rscn_payload(struct unf_lport *lport, - struct unf_rscn_pld *rscn_pld) -{ -#define UNF_OS_DISC_REDISC_TIME 10000 - - struct unf_rscn_port_id_page *rscn_port_id = NULL; - struct unf_disc *disc = NULL; - struct unf_rscn_mgr *rscn_mgr = NULL; - u32 index = 0; - u32 pld_len = 0; - u32 port_id_page_cnt = 0; - u32 ret = RETURN_OK; - ulong flag = 0; - bool eb_need_disc_flag = false; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(rscn_pld, UNF_RETURN_ERROR); - - /* This field is the length in bytes of the entire Payload, inclusive of - * the word 0 - */ - pld_len = UNF_GET_RSCN_PLD_LEN(rscn_pld->cmnd); - pld_len -= sizeof(rscn_pld->cmnd); - port_id_page_cnt = pld_len / UNF_RSCN_PAGE_LEN; - - /* Pages within payload is nor more than 255 */ - if (port_id_page_cnt > UNF_RSCN_PAGE_SUM) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x_0x%x) page num(0x%x) exceed 255 in RSCN", - lport->port_id, lport->nport_id, port_id_page_cnt); - - return UNF_RETURN_ERROR; - } - - /* L_Port-->Disc-->Rscn_Mgr */ - disc = &lport->disc; - rscn_mgr = &disc->rscn_mgr; - - /* for each ID from RSCN_Page: check whether need to Disc or not */ - while (index < port_id_page_cnt) { - rscn_port_id = &rscn_pld->port_id_page[index]; - if (unf_lookup_lport_by_nportid(lport, *(u32 *)rscn_port_id)) { - /* Prevent to create session with L_Port which have the - * same N_Port_ID - */ - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "[info]Port(0x%x) find local N_Port_ID(0x%x) within RSCN payload", - ((struct unf_lport *)(lport->root_lport))->nport_id, - *(u32 *)rscn_port_id); - } else { - /* New RSCN_Page ID find, save it to RSCN_Mgr */ - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "[info]Port(0x%x_0x%x) save RSCN N_Port_ID(0x%x)", - lport->port_id, lport->nport_id, - *(u32 *)rscn_port_id); - - /* 1. new RSCN_Page ID find, save it to RSCN_Mgr */ - unf_save_rscn_port_id(rscn_mgr, rscn_port_id); - eb_need_disc_flag = true; - } - index++; - } - - if (!eb_need_disc_flag) { - FC_DRV_PRINT(UNF_LOG_NORMAL, UNF_MAJOR, - "[info]Port(0x%x) find all N_Port_ID and do not need to disc", - ((struct unf_lport *)(lport->root_lport))->nport_id); - - return RETURN_OK; - } - - /* 2. Do/Start Disc: Check & do Disc (GID_PT) process */ - if (!disc->disc_temp.unf_disc_start) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x_0x%x) DISC start function is NULL", - lport->nport_id, lport->nport_id); - - return UNF_RETURN_ERROR; - } - - spin_lock_irqsave(&disc->rport_busy_pool_lock, flag); - if (disc->states == UNF_DISC_ST_END || - ((jiffies - disc->last_disc_jiff) > msecs_to_jiffies(UNF_OS_DISC_REDISC_TIME))) { - disc->disc_option = UNF_RSCN_DISC; - disc->last_disc_jiff = jiffies; - spin_unlock_irqrestore(&disc->rport_busy_pool_lock, flag); - - ret = disc->disc_temp.unf_disc_start(lport); - } else { - FC_DRV_PRINT(UNF_LOG_ABNORMAL, UNF_INFO, - "[info]Port(0x%x_0x%x) DISC state(0x%x) with last time(%llu) and don't do DISC", - lport->port_id, lport->nport_id, disc->states, - disc->last_disc_jiff); - - spin_unlock_irqrestore(&disc->rport_busy_pool_lock, flag); - } - - return ret; -} - -u32 unf_rscn_handler(struct unf_lport *lport, u32 sid, struct unf_xchg *xchg) -{ - /* - * A RSCN ELS shall be sent to registered Nx_Ports - * when an event occurs that may have affected the state of - * one or more Nx_Ports, or the ULP state within the Nx_Port. - * * - * The Payload of a RSCN Request includes a list - * containing the addresses of the affected Nx_Ports. - * * - * Each affected Port_ID page contains the ID of the Nx_Port, - * Fabric Controller, E_Port, domain, or area for which the event was - * detected. - */ - struct unf_rscn_pld *rscn_pld = NULL; - struct unf_rport *unf_rport = NULL; - u32 ret = UNF_RETURN_ERROR; - u32 pld_len = 0; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(xchg, UNF_RETURN_ERROR); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Receive RSCN Port(0x%x_0x%x)<---RPort(0x%x) OX_ID(0x%x)", - lport->port_id, lport->nport_id, sid, xchg->oxid); - - UNF_SERVICE_COLLECT(lport->link_service_info, UNF_SERVICE_ITEM_RSCN); - - /* 1. Get R_Port by S_ID */ - unf_rport = unf_get_rport_by_nport_id(lport, sid); /* rport busy_list */ - if (!unf_rport) { - unf_rport = unf_rport_get_free_and_init(lport, UNF_PORT_TYPE_FC, sid); - if (!unf_rport) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x_0x%x) received RSCN but has no RPort(0x%x) with OX_ID(0x%x)", - lport->port_id, lport->nport_id, sid, xchg->oxid); - - unf_cm_free_xchg(lport, xchg); - return UNF_RETURN_ERROR; - } - - unf_rport->nport_id = sid; - } - - rscn_pld = xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr->rscn.rscn_pld; - FC_CHECK_RETURN_VALUE(rscn_pld, UNF_RETURN_ERROR); - pld_len = UNF_GET_RSCN_PLD_LEN(rscn_pld->cmnd); - UNF_PRINT_SFS_LIMIT(UNF_INFO, lport->port_id, rscn_pld, pld_len); - - /* 2. NOTE: Analysis RSCN payload(save & disc if necessary) */ - ret = unf_analysis_rscn_payload(lport, rscn_pld); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x_0x%x) analysis RSCN failed", - lport->port_id, lport->nport_id); - } - - /* 3. send rscn_acc after analysis payload */ - ret = unf_send_rscn_acc(lport, unf_rport, xchg); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x_0x%x) send RSCN response failed", - lport->port_id, lport->nport_id); - } - - return ret; -} - -static void unf_analysis_pdisc_pld(struct unf_lport *lport, - struct unf_rport *rport, - struct unf_plogi_pdisc *pdisc) -{ - struct unf_lgn_parm *pdisc_params = NULL; - u64 wwpn = INVALID_VALUE64; - u64 wwnn = INVALID_VALUE64; - - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(rport); - FC_CHECK_RETURN_VOID(pdisc); - - pdisc_params = &pdisc->payload.stparms; - if (pdisc_params->co_parms.bb_receive_data_field_size > UNF_MAX_FRAME_SIZE) - rport->max_frame_size = UNF_MAX_FRAME_SIZE; - else - rport->max_frame_size = pdisc_params->co_parms.bb_receive_data_field_size; - - wwnn = (u64)(((u64)(pdisc_params->high_node_name) << UNF_SHIFT_32) | - ((u64)pdisc_params->low_node_name)); - wwpn = (u64)(((u64)(pdisc_params->high_port_name) << UNF_SHIFT_32) | - ((u64)pdisc_params->low_port_name)); - - rport->port_name = wwpn; - rport->node_name = wwnn; - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x) save PDISC parameters to Rport(0x%x) WWPN(0x%llx) WWNN(0x%llx)", - lport->port_id, rport->nport_id, rport->port_name, - rport->node_name); -} - -u32 unf_send_pdisc_rjt(struct unf_lport *lport, struct unf_rport *rport, struct unf_xchg *xchg) -{ - u32 ret = UNF_RETURN_ERROR; - struct unf_rjt_info rjt_info; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(rport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(xchg, UNF_RETURN_ERROR); - - memset(&rjt_info, 0, sizeof(struct unf_rjt_info)); - rjt_info.els_cmnd_code = ELS_PDISC; - rjt_info.reason_code = UNF_LS_RJT_LOGICAL_ERROR; - rjt_info.reason_explanation = UNF_LS_RJT_NO_ADDITIONAL_INFO; - - ret = unf_send_els_rjt_by_rport(lport, xchg, rport, &rjt_info); - - return ret; -} - -u32 unf_pdisc_handler(struct unf_lport *lport, u32 sid, struct unf_xchg *xchg) -{ - struct unf_plogi_pdisc *pdisc = NULL; - struct unf_rport *unf_rport = NULL; - ulong flags = 0; - u32 ret = RETURN_OK; - u64 wwpn = 0; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(xchg, UNF_RETURN_ERROR); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: Receive PDISC. Port(0x%x)<---RPort(0x%x) with OX_ID(0x%x)", - lport->port_id, sid, xchg->oxid); - - UNF_SERVICE_COLLECT(lport->link_service_info, UNF_SERVICE_ITEM_PDISC); - pdisc = &xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr->pdisc; - UNF_PRINT_SFS_LIMIT(UNF_INFO, lport->port_id, &pdisc->payload, - sizeof(struct unf_plogi_payload)); - wwpn = (u64)(((u64)(pdisc->payload.stparms.high_port_name) << UNF_SHIFT_32) | - ((u64)pdisc->payload.stparms.low_port_name)); - - unf_rport = unf_find_rport(lport, sid, wwpn); - if (!unf_rport) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) can't find RPort by NPort ID(0x%x). Free exchange and send LOGO", - lport->port_id, sid); - - unf_cm_free_xchg(lport, xchg); - (void)unf_send_logo_by_did(lport, sid); - } else { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MINOR, - "[info]Port(0x%x) get exist RPort(0x%x) when receive PDISC with S_Id(0x%x)", - lport->port_id, unf_rport->nport_id, sid); - - if (sid >= UNF_FC_FID_DOM_MGR) - return unf_send_pdisc_rjt(lport, unf_rport, xchg); - - unf_analysis_pdisc_pld(lport, unf_rport, pdisc); - - /* State: READY */ - spin_lock_irqsave(&unf_rport->rport_state_lock, flags); - if (unf_rport->rp_state == UNF_RPORT_ST_READY) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x) find RPort(0x%x) state is READY when receiving PDISC", - lport->port_id, sid); - - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flags); - - ret = unf_send_pdisc_acc(lport, unf_rport, xchg); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) handle PDISC failed", - lport->port_id); - - return ret; - } - - /* Report Down/Up event to scsi */ - unf_update_lport_state_by_linkup_event(lport, - unf_rport, unf_rport->options); - } else if ((unf_rport->rp_state == UNF_RPORT_ST_CLOSING) && - (unf_rport->session)) { - /* State: Closing */ - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) find RPort(0x%x) state is 0x%x when receiving PDISC", - lport->port_id, sid, unf_rport->rp_state); - - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flags); - - unf_cm_free_xchg(lport, xchg); - (void)unf_send_logo_by_did(lport, sid); - } else if (unf_rport->rp_state == UNF_RPORT_ST_PRLI_WAIT) { - /* State: PRLI_WAIT */ - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x) find RPort(0x%x) state is 0x%x when receiving PDISC", - lport->port_id, sid, unf_rport->rp_state); - - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flags); - - ret = unf_send_pdisc_acc(lport, unf_rport, xchg); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) handle PDISC failed", - lport->port_id); - - return ret; - } - } else { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) find RPort(0x%x) state is 0x%x when receiving PDISC, send LOGO", - lport->port_id, sid, unf_rport->rp_state); - - unf_rport_state_ma(unf_rport, UNF_EVENT_RPORT_LOGO); - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flags); - - unf_rport_enter_logo(lport, unf_rport); - unf_cm_free_xchg(lport, xchg); - } - } - - return ret; -} - -static void unf_analysis_adisc_pld(struct unf_lport *lport, - struct unf_rport *rport, - struct unf_adisc_payload *adisc_pld) -{ - u64 wwpn = INVALID_VALUE64; - u64 wwnn = INVALID_VALUE64; - - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(rport); - FC_CHECK_RETURN_VOID(adisc_pld); - - wwnn = (u64)(((u64)(adisc_pld->high_node_name) << UNF_SHIFT_32) | - ((u64)adisc_pld->low_node_name)); - wwpn = (u64)(((u64)(adisc_pld->high_port_name) << UNF_SHIFT_32) | - ((u64)adisc_pld->low_port_name)); - - rport->port_name = wwpn; - rport->node_name = wwnn; - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x) save ADISC parameters to RPort(0x%x), WWPN(0x%llx) WWNN(0x%llx) NPort ID(0x%x)", - lport->port_id, rport->nport_id, rport->port_name, - rport->node_name, adisc_pld->nport_id); -} - -u32 unf_adisc_handler(struct unf_lport *lport, u32 sid, struct unf_xchg *xchg) -{ - struct unf_rport *unf_rport = NULL; - struct unf_adisc_payload *adisc_pld = NULL; - ulong flags = 0; - u64 wwpn = 0; - u32 ret = RETURN_ERROR; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(xchg, UNF_RETURN_ERROR); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: Receive ADISC. Port(0x%x)<---RPort(0x%x) with OX_ID(0x%x)", - lport->port_id, sid, xchg->oxid); - - UNF_SERVICE_COLLECT(lport->link_service_info, UNF_SERVICE_ITEM_ADISC); - adisc_pld = &xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr->adisc.adisc_payl; - UNF_PRINT_SFS_LIMIT(UNF_INFO, lport->port_id, adisc_pld, sizeof(struct unf_adisc_payload)); - wwpn = (u64)(((u64)(adisc_pld->high_port_name) << UNF_SHIFT_32) | - ((u64)adisc_pld->low_port_name)); - - unf_rport = unf_find_rport(lport, sid, wwpn); - if (!unf_rport) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) can't find RPort by NPort ID(0x%x). Free exchange and send LOGO", - lport->port_id, sid); - - unf_cm_free_xchg(lport, xchg); - (void)unf_send_logo_by_did(lport, sid); - - return ret; - } - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MINOR, - "[info]Port(0x%x) get exist RPort(0x%x) when receive ADISC with S_ID(0x%x)", - lport->port_id, unf_rport->nport_id, sid); - - unf_analysis_adisc_pld(lport, unf_rport, adisc_pld); - - /* State: READY */ - spin_lock_irqsave(&unf_rport->rport_state_lock, flags); - if (unf_rport->rp_state == UNF_RPORT_ST_READY) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x) find RPort(0x%x) state is READY when receiving ADISC", - lport->port_id, sid); - - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flags); - - /* Return ACC directly */ - ret = unf_send_adisc_acc(lport, unf_rport, xchg); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) send ADISC ACC failed", lport->port_id); - - return ret; - } - - /* Report Down/Up event to SCSI */ - unf_update_lport_state_by_linkup_event(lport, unf_rport, unf_rport->options); - } - /* State: Closing */ - else if ((unf_rport->rp_state == UNF_RPORT_ST_CLOSING) && - (unf_rport->session)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) find RPort(0x%x) state is 0x%x when receiving ADISC", - lport->port_id, sid, unf_rport->rp_state); - - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flags); - - unf_rport = unf_get_safe_rport(lport, unf_rport, - UNF_RPORT_REUSE_RECOVER, - unf_rport->nport_id); - if (unf_rport) { - spin_lock_irqsave(&unf_rport->rport_state_lock, flags); - unf_rport->nport_id = sid; - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flags); - - ret = unf_send_adisc_acc(lport, unf_rport, xchg); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) send ADISC ACC failed", - lport->port_id); - - return ret; - } - - unf_update_lport_state_by_linkup_event(lport, - unf_rport, unf_rport->options); - } else { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) can't find RPort by NPort_ID(0x%x). Free exchange and send LOGO", - lport->port_id, sid); - - unf_cm_free_xchg(lport, xchg); - (void)unf_send_logo_by_did(lport, sid); - } - } else if (unf_rport->rp_state == UNF_RPORT_ST_PRLI_WAIT) { - /* State: PRLI_WAIT */ - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x) find RPort(0x%x) state is 0x%x when receiving ADISC", - lport->port_id, sid, unf_rport->rp_state); - - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flags); - - ret = unf_send_adisc_acc(lport, unf_rport, xchg); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) send ADISC ACC failed", lport->port_id); - - return ret; - } - } else { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) find RPort(0x%x) state is 0x%x when receiving ADISC, send LOGO", - lport->port_id, sid, unf_rport->rp_state); - - unf_rport_state_ma(unf_rport, UNF_EVENT_RPORT_LOGO); - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flags); - - unf_rport_enter_logo(lport, unf_rport); - unf_cm_free_xchg(lport, xchg); - } - - return ret; -} - -u32 unf_rec_handler(struct unf_lport *lport, u32 sid, struct unf_xchg *xchg) -{ - struct unf_rport *unf_rport = NULL; - u32 ret = UNF_RETURN_ERROR; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(xchg, UNF_RETURN_ERROR); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: Port(0x%x) receive REC", lport->port_id); - - /* Send rec acc */ - ret = unf_send_rec_acc(lport, unf_rport, xchg); /* discard directly */ - - return ret; -} - -u32 unf_rrq_handler(struct unf_lport *lport, u32 sid, struct unf_xchg *xchg) -{ - struct unf_rport *unf_rport = NULL; - struct unf_rrq *rrq = NULL; - struct unf_xchg *xchg_reused = NULL; - u32 ret = UNF_RETURN_ERROR; - u16 ox_id = 0; - u16 rx_id = 0; - u32 unf_sid = 0; - ulong flags = 0; - struct unf_rjt_info rjt_info = {0}; - struct unf_xchg_hot_pool *hot_pool = NULL; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(xchg, UNF_RETURN_ERROR); - - UNF_SERVICE_COLLECT(lport->link_service_info, UNF_SERVICE_ITEM_RRQ); - rrq = &xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr->rrq; - ox_id = (u16)(rrq->oxid_rxid >> UNF_SHIFT_16); - rx_id = (u16)(rrq->oxid_rxid); - unf_sid = rrq->sid & UNF_NPORTID_MASK; - - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_KEVENT, - "[warn]Receive RRQ. Port(0x%x)<---RPort(0x%x) sfsXchg(0x%p) OX_ID(0x%x,0x%x) RX_ID(0x%x)", - lport->port_id, sid, xchg, ox_id, xchg->oxid, rx_id); - - /* Get R_Port */ - unf_rport = unf_get_rport_by_nport_id(lport, sid); - if (!unf_rport) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x) receive RRQ but has no RPort(0x%x)", - lport->port_id, sid); - - /* NOTE: send LOGO */ - unf_send_logo_by_did(lport, unf_sid); - - unf_cm_free_xchg(lport, xchg); - return ret; - } - - /* Get Target (Abort I/O) exchange context */ - xchg_reused = unf_cm_lookup_xchg_by_id(lport, ox_id, unf_sid); /* unf_find_xchg_by_ox_id */ - if (!xchg_reused) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x) cannot find exchange with OX_ID(0x%x) RX_ID(0x%x) S_ID(0x%x)", - lport->port_id, ox_id, rx_id, unf_sid); - - rjt_info.els_cmnd_code = ELS_RRQ; - rjt_info.reason_code = FCXLS_BA_RJT_LOGICAL_ERROR | FCXLS_LS_RJT_INVALID_OXID_RXID; - - /* NOTE: send ELS RJT */ - if (unf_send_els_rjt_by_rport(lport, xchg, unf_rport, &rjt_info) != RETURN_OK) { - unf_cm_free_xchg(lport, xchg); - return UNF_RETURN_ERROR; - } - - return RETURN_OK; - } - - hot_pool = xchg_reused->hot_pool; - if (unlikely(!hot_pool)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_MAJOR, - "Port(0x%x) OxId(0x%x) Rxid(0x%x) Sid(0x%x) Hot Pool is NULL.", - lport->port_id, ox_id, rx_id, unf_sid); - - return ret; - } - - spin_lock_irqsave(&hot_pool->xchg_hotpool_lock, flags); - xchg_reused->oxid = INVALID_VALUE16; - xchg_reused->rxid = INVALID_VALUE16; - spin_unlock_irqrestore(&hot_pool->xchg_hotpool_lock, flags); - - /* NOTE: release I/O exchange context */ - unf_xchg_ref_dec(xchg_reused, SFS_RESPONSE); - - /* Send RRQ ACC */ - ret = unf_send_rrq_acc(lport, unf_rport, xchg); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x) can not send RRQ rsp. Xchg(0x%p) Ioxchg(0x%p) OX_RX_ID(0x%x 0x%x) S_ID(0x%x)", - lport->port_id, xchg, xchg_reused, ox_id, rx_id, unf_sid); - - unf_cm_free_xchg(lport, xchg); - } - - return ret; -} - -u32 unf_logo_handler(struct unf_lport *lport, u32 sid, struct unf_xchg *xchg) -{ - struct unf_rport *unf_rport = NULL; - struct unf_rport *logo_rport = NULL; - struct unf_logo *logo = NULL; - u32 ret = UNF_RETURN_ERROR; - u32 nport_id = 0; - struct unf_rjt_info rjt_info = {0}; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(xchg, UNF_RETURN_ERROR); - - UNF_SERVICE_COLLECT(lport->link_service_info, UNF_SERVICE_ITEM_LOGO); - logo = &xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr->logo; - nport_id = logo->payload.nport_id & UNF_NPORTID_MASK; - - if (sid < UNF_FC_FID_DOM_MGR) { - /* R_Port is not fabric port */ - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_KEVENT, - "[info]LOGIN: Receive LOGO. Port(0x%x)<---RPort(0x%x) NPort_ID(0x%x) OXID(0x%x)", - lport->port_id, sid, nport_id, xchg->oxid); - } - - UNF_PRINT_SFS_LIMIT(UNF_INFO, lport->port_id, &logo->payload, - sizeof(struct unf_logo_payload)); - - /* - * 1. S_ID unequal to NPort_ID: - * link down Rport find by NPort_ID immediately - */ - if (sid != nport_id) { - logo_rport = unf_get_rport_by_nport_id(lport, nport_id); - if (logo_rport) - unf_rport_immediate_link_down(lport, logo_rport); - } - - /* 2. Get R_Port by S_ID (frame header) */ - unf_rport = unf_get_rport_by_nport_id(lport, sid); - unf_rport = unf_get_safe_rport(lport, unf_rport, UNF_RPORT_REUSE_INIT, sid); /* INIT */ - if (!unf_rport) { - memset(&rjt_info, 0, sizeof(struct unf_rjt_info)); - rjt_info.els_cmnd_code = ELS_LOGO; - rjt_info.reason_code = UNF_LS_RJT_LOGICAL_ERROR; - rjt_info.reason_explanation = UNF_LS_RJT_NO_ADDITIONAL_INFO; - ret = unf_send_els_rjt_by_did(lport, xchg, sid, &rjt_info); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) receive LOGO but has no RPort(0x%x)", - lport->port_id, sid); - - return ret; - } - - /* - * 3. I/O resource release: set ABORT tag - * * - * Call by: R_Port remove; RCVD LOGO; RCVD PLOGI; send PLOGI ACC - */ - unf_cm_xchg_mgr_abort_io_by_id(lport, unf_rport, sid, lport->nport_id, INI_IO_STATE_LOGO); - - /* 4. Send LOGO ACC */ - ret = unf_send_logo_acc(lport, unf_rport, xchg); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, - UNF_WARN, "[warn]Port(0x%x) send LOGO failed", lport->port_id); - } - /* - * 5. Do same operations with RCVD LOGO/PRLO & Send LOGO: - * retry (LOGIN or LOGO) or link down immediately - */ - unf_process_rport_after_logo(lport, unf_rport); - - return ret; -} - -u32 unf_prlo_handler(struct unf_lport *lport, u32 sid, struct unf_xchg *xchg) -{ - struct unf_rport *unf_rport = NULL; - struct unf_prli_prlo *prlo = NULL; - u32 ret = UNF_RETURN_ERROR; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(xchg, UNF_RETURN_ERROR); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: Receive PRLO. Port(0x%x)<---RPort(0x%x) with OX_ID(0x%x)", - lport->port_id, sid, xchg->oxid); - - UNF_SERVICE_COLLECT(lport->link_service_info, UNF_SERVICE_ITEM_LOGO); - - /* Get (new) R_Port */ - unf_rport = unf_get_rport_by_nport_id(lport, sid); - unf_rport = unf_get_safe_rport(lport, unf_rport, UNF_RPORT_REUSE_INIT, sid); /* INIT */ - if (!unf_rport) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) receive PRLO but has no RPort", - lport->port_id); - - /* Discard directly */ - unf_cm_free_xchg(lport, xchg); - return ret; - } - - prlo = &xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr->prlo; - UNF_PRINT_SFS_LIMIT(UNF_INFO, lport->port_id, &prlo->payload, - sizeof(struct unf_prli_payload)); - - /* Send PRLO ACC to remote */ - ret = unf_send_prlo_acc(lport, unf_rport, xchg); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) send PRLO ACC failed", lport->port_id); - } - - /* Enter Enhanced action after LOGO (retry LOGIN or LOGO) */ - unf_process_rport_after_logo(lport, unf_rport); - - return ret; -} - -static void unf_fill_echo_acc_pld(struct unf_echo *echo_acc) -{ - struct unf_echo_payload *echo_acc_pld = NULL; - - FC_CHECK_RETURN_VOID(echo_acc); - - echo_acc_pld = echo_acc->echo_pld; - FC_CHECK_RETURN_VOID(echo_acc_pld); - - echo_acc_pld->cmnd = UNF_ELS_CMND_ACC; -} - -static void unf_echo_acc_callback(struct unf_xchg *xchg) -{ - struct unf_lport *unf_lport = NULL; - - FC_CHECK_RETURN_VOID(xchg); - - unf_lport = xchg->lport; - - FC_CHECK_RETURN_VOID(unf_lport); - if (xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr->echo_acc.phy_echo_addr) { - pci_unmap_single(unf_lport->low_level_func.dev, - xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr->echo_acc - .phy_echo_addr, - UNF_ECHO_PAYLOAD_LEN, DMA_BIDIRECTIONAL); - xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr->echo_acc.phy_echo_addr = 0; - } -} - -static u32 unf_send_echo_acc(struct unf_lport *lport, u32 did, - struct unf_xchg *xchg) -{ - struct unf_echo *echo_acc = NULL; - union unf_sfs_u *fc_entry = NULL; - u32 ret = UNF_RETURN_ERROR; - u16 ox_id = 0; - u16 rx_id = 0; - struct unf_frame_pkg pkg; - dma_addr_t phy_echo_acc_addr; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(xchg, UNF_RETURN_ERROR); - - memset(&pkg, 0, sizeof(struct unf_frame_pkg)); - xchg->cmnd_code = UNF_SET_ELS_ACC_TYPE(ELS_ECHO); - xchg->did = did; - xchg->sid = lport->nport_id; - xchg->oid = xchg->sid; - xchg->lport = lport; - - xchg->callback = NULL; - xchg->ob_callback = unf_echo_acc_callback; - - unf_fill_package(&pkg, xchg, xchg->rport); - pkg.type = UNF_PKG_ELS_REPLY; - fc_entry = xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr; - if (!fc_entry) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) entry can't be NULL with tag(0x%x)", - lport->port_id, xchg->hotpooltag); - - unf_cm_free_xchg(lport, xchg); - return UNF_RETURN_ERROR; - } - - echo_acc = &fc_entry->echo_acc; - unf_fill_echo_acc_pld(echo_acc); - ox_id = xchg->oxid; - rx_id = xchg->rxid; - phy_echo_acc_addr = pci_map_single(lport->low_level_func.dev, - echo_acc->echo_pld, - UNF_ECHO_PAYLOAD_LEN, - DMA_BIDIRECTIONAL); - if (pci_dma_mapping_error(lport->low_level_func.dev, phy_echo_acc_addr)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, - UNF_WARN, "[warn]Port(0x%x) pci map err", - lport->port_id); - unf_cm_free_xchg(lport, xchg); - return UNF_RETURN_ERROR; - } - echo_acc->phy_echo_addr = phy_echo_acc_addr; - - ret = unf_ls_gs_cmnd_send(lport, &pkg, xchg); - if (ret != RETURN_OK) { - unf_cm_free_xchg((void *)lport, (void *)xchg); - pci_unmap_single(lport->low_level_func.dev, - phy_echo_acc_addr, UNF_ECHO_PAYLOAD_LEN, - DMA_BIDIRECTIONAL); - echo_acc->phy_echo_addr = 0; - } - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]ECHO ACC send %s. Port(0x%x)--->RPort(0x%x) with OX_ID(0x%x) RX_ID(0x%x)", - (ret != RETURN_OK) ? "failed" : "succeed", lport->port_id, - did, ox_id, rx_id); - - return ret; -} - -u32 unf_echo_handler(struct unf_lport *lport, u32 sid, struct unf_xchg *xchg) -{ - struct unf_echo_payload *echo_pld = NULL; - struct unf_rport *unf_rport = NULL; - u32 ret = UNF_RETURN_ERROR; - u32 data_len = 0; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(xchg, UNF_RETURN_ERROR); - - data_len = xchg->fcp_sfs_union.sfs_entry.cur_offset; - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Receive ECHO. Port(0x%x)<---RPort(0x%x) with OX_ID(0x%x))", - lport->port_id, sid, xchg->oxid); - - UNF_SERVICE_COLLECT(lport->link_service_info, UNF_SERVICE_ITEM_ECHO); - echo_pld = xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr->echo.echo_pld; - UNF_PRINT_SFS_LIMIT(UNF_INFO, lport->port_id, echo_pld, data_len); - unf_rport = unf_get_rport_by_nport_id(lport, sid); - xchg->rport = unf_rport; - - ret = unf_send_echo_acc(lport, sid, xchg); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, - UNF_WARN, "[warn]Port(0x%x) send ECHO ACC failed", lport->port_id); - } - - return ret; -} - -static void unf_login_with_rport_in_n2n(struct unf_lport *lport, - u64 remote_port_name, - u64 remote_node_name) -{ - /* - * Call by (P2P): - * 1. RCVD FLOGI ACC - * 2. Send FLOGI ACC succeed - * * - * Compare WWN, larger is master, then send PLOGI - */ - struct unf_lport *unf_lport = lport; - struct unf_rport *unf_rport = NULL; - ulong lport_flag = 0; - ulong rport_flag = 0; - u64 port_name = 0; - u64 node_name = 0; - u32 ret = RETURN_OK; - - FC_CHECK_RETURN_VOID(lport); - - spin_lock_irqsave(&unf_lport->lport_state_lock, lport_flag); - unf_lport_state_ma(unf_lport, UNF_EVENT_LPORT_READY); /* LPort: FLOGI_WAIT --> READY */ - spin_unlock_irqrestore(&unf_lport->lport_state_lock, lport_flag); - - port_name = remote_port_name; - node_name = remote_node_name; - - if (unf_lport->port_name > port_name) { - /* Master case: send PLOGI */ - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x)'s WWN(0x%llx) is larger than rport(0x%llx), should be master", - unf_lport->port_id, unf_lport->port_name, port_name); - - /* Update N_Port_ID now: 0xEF */ - unf_lport->nport_id = UNF_P2P_LOCAL_NPORT_ID; - - unf_rport = unf_find_valid_rport(lport, port_name, UNF_P2P_REMOTE_NPORT_ID); - unf_rport = unf_get_safe_rport(lport, unf_rport, UNF_RPORT_REUSE_ONLY, - UNF_P2P_REMOTE_NPORT_ID); - if (unf_rport) { - unf_rport->node_name = node_name; - unf_rport->port_name = port_name; - unf_rport->nport_id = UNF_P2P_REMOTE_NPORT_ID; /* 0xD6 */ - unf_rport->local_nport_id = UNF_P2P_LOCAL_NPORT_ID; /* 0xEF */ - - spin_lock_irqsave(&unf_rport->rport_state_lock, rport_flag); - if (unf_rport->rp_state == UNF_RPORT_ST_PLOGI_WAIT || - unf_rport->rp_state == UNF_RPORT_ST_PRLI_WAIT || - unf_rport->rp_state == UNF_RPORT_ST_READY) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: Port(0x%x) Rport(0x%x) have sent PLOGI or PRLI with state(0x%x)", - unf_lport->port_id, - unf_rport->nport_id, - unf_rport->rp_state); - - spin_unlock_irqrestore(&unf_rport->rport_state_lock, - rport_flag); - return; - } - /* Update L_Port State: PLOGI_WAIT */ - unf_rport_state_ma(unf_rport, UNF_EVENT_RPORT_ENTER_PLOGI); - spin_unlock_irqrestore(&unf_rport->rport_state_lock, rport_flag); - - /* P2P with master: Start to Send PLOGI */ - ret = unf_send_plogi(unf_lport, unf_rport); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]LOGIN: Port(0x%x) with WWN(0x%llx) send PLOGI to(0x%llx) failed", - unf_lport->port_id, - unf_lport->port_name, port_name); - - unf_rport_error_recovery(unf_rport); - } - } else { - /* Get/Alloc R_Port failed */ - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) with WWN(0x%llx) allocate RPort(ID:0x%x,WWPN:0x%llx) failed", - unf_lport->port_id, unf_lport->port_name, - UNF_P2P_REMOTE_NPORT_ID, port_name); - } - } else { - /* Slave case: L_Port's Port Name is smaller than R_Port */ - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x) with WWN(0x%llx) is smaller than rport(0x%llx), do nothing", - unf_lport->port_id, unf_lport->port_name, port_name); - } -} - -void unf_lport_enter_mns_plogi(struct unf_lport *lport) -{ - /* Fabric or Public Loop Mode: Login with Name server */ - struct unf_lport *unf_lport = lport; - struct unf_rport *unf_rport = NULL; - ulong flag = 0; - u32 ret = UNF_RETURN_ERROR; - struct unf_plogi_payload *plogi_pld = NULL; - union unf_sfs_u *fc_entry = NULL; - struct unf_xchg *xchg = NULL; - struct unf_frame_pkg pkg; - - FC_CHECK_RETURN_VOID(lport); - - /* Get (safe) R_Port */ - unf_rport = unf_rport_get_free_and_init(lport, UNF_PORT_TYPE_FC, UNF_FC_FID_MGMT_SERV); - if (!unf_rport) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) allocate RPort failed", lport->port_id); - return; - } - - spin_lock_irqsave(&unf_rport->rport_state_lock, flag); - unf_rport->nport_id = UNF_FC_FID_MGMT_SERV; /* 0xfffffa */ - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flag); - - memset(&pkg, 0, sizeof(struct unf_frame_pkg)); - - /* Get & Set new free exchange */ - xchg = unf_cm_get_free_xchg(lport, UNF_XCHG_TYPE_SFS); - if (!xchg) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) exchange can't be NULL for PLOGI", lport->port_id); - - return; - } - - xchg->cmnd_code = ELS_PLOGI; /* PLOGI */ - xchg->did = unf_rport->nport_id; - xchg->sid = lport->nport_id; - xchg->oid = xchg->sid; - xchg->lport = unf_lport; - xchg->rport = unf_rport; - - /* Set callback function */ - xchg->callback = NULL; /* for rcvd plogi acc/rjt processer */ - xchg->ob_callback = NULL; /* for send plogi failed processer */ - - unf_fill_package(&pkg, xchg, unf_rport); - pkg.type = UNF_PKG_ELS_REQ; - /* Fill PLOGI payload */ - fc_entry = xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr; - if (!fc_entry) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) entry can't be NULL with tag(0x%x)", - lport->port_id, xchg->hotpooltag); - - unf_cm_free_xchg(lport, xchg); - return; - } - - plogi_pld = &fc_entry->plogi.payload; - memset(plogi_pld, 0, sizeof(struct unf_plogi_payload)); - unf_fill_plogi_pld(plogi_pld, lport); - - /* Start to Send PLOGI command */ - ret = unf_ls_gs_cmnd_send(lport, &pkg, xchg); - if (ret != RETURN_OK) - unf_cm_free_xchg((void *)lport, (void *)xchg); -} - -static void unf_register_to_switch(struct unf_lport *lport) -{ - /* Register to Fabric, used for: FABRIC & PUBLI LOOP */ - ulong flag = 0; - - FC_CHECK_RETURN_VOID(lport); - - spin_lock_irqsave(&lport->lport_state_lock, flag); - unf_lport_state_ma(lport, UNF_EVENT_LPORT_REMOTE_ACC); - spin_unlock_irqrestore(&lport->lport_state_lock, flag); - - /* Login with Name server: PLOGI */ - unf_lport_enter_sns_plogi(lport); - - unf_lport_enter_mns_plogi(lport); - - /* Physical Port */ - if (lport->root_lport == lport && - lport->act_topo == UNF_ACT_TOP_P2P_FABRIC) { - unf_linkup_all_vports(lport); - } -} - -void unf_fdisc_ob_callback(struct unf_xchg *xchg) -{ - /* Do recovery */ - struct unf_lport *unf_lport = NULL; - ulong flag = 0; - - FC_CHECK_RETURN_VOID(xchg); - - spin_lock_irqsave(&xchg->xchg_state_lock, flag); - unf_lport = xchg->lport; - spin_unlock_irqrestore(&xchg->xchg_state_lock, flag); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]LOGIN: FDISC send failed"); - - FC_CHECK_RETURN_VOID(unf_lport); - - /* Do L_Port error recovery */ - unf_lport_error_recovery(unf_lport); -} - -void unf_fdisc_callback(void *lport, void *rport, void *exch) -{ - /* Register to Name Server or Do recovery */ - struct unf_lport *unf_lport = NULL; - struct unf_rport *unf_rport = NULL; - struct unf_xchg *xchg = NULL; - struct unf_flogi_fdisc_payload *fdisc_pld = NULL; - ulong flag = 0; - u32 cmd = 0; - - unf_lport = (struct unf_lport *)lport; - unf_rport = (struct unf_rport *)rport; - xchg = (struct unf_xchg *)exch; - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(rport); - FC_CHECK_RETURN_VOID(exch); - FC_CHECK_RETURN_VOID(xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr); - fdisc_pld = &xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr->fdisc_acc.fdisc_payload; - if (xchg->byte_orders & UNF_BIT_2) - unf_big_end_to_cpu((u8 *)fdisc_pld, sizeof(struct unf_flogi_fdisc_payload)); - - cmd = fdisc_pld->cmnd; - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: FDISC response is (0x%x). Port(0x%x)<---RPort(0x%x) with OX_ID(0x%x)", - cmd, unf_lport->port_id, unf_rport->nport_id, xchg->oxid); - unf_rport = unf_get_rport_by_nport_id(unf_lport, UNF_FC_FID_FLOGI); - unf_rport = unf_get_safe_rport(unf_lport, unf_rport, - UNF_RPORT_REUSE_ONLY, UNF_FC_FID_FLOGI); - if (!unf_rport) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) has no Rport", unf_lport->port_id); - return; - } - - spin_lock_irqsave(&unf_rport->rport_state_lock, flag); - unf_rport->nport_id = UNF_FC_FID_FLOGI; - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flag); - - if ((cmd & UNF_ELS_CMND_HIGH_MASK) == UNF_ELS_CMND_ACC) { - /* Case for ACC */ - spin_lock_irqsave(&unf_lport->lport_state_lock, flag); - if (unf_lport->states != UNF_LPORT_ST_FLOGI_WAIT) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x_0x%x) receive Flogi/Fdisc ACC in state(0x%x)", - unf_lport->port_id, unf_lport->nport_id, unf_lport->states); - - spin_unlock_irqrestore(&unf_lport->lport_state_lock, flag); - return; - } - spin_unlock_irqrestore(&unf_lport->lport_state_lock, flag); - - unf_lport_update_nport_id(unf_lport, xchg->sid); - unf_lport_update_time_params(unf_lport, fdisc_pld); - unf_register_to_switch(unf_lport); - } else { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]LOGIN: FDISC response is (0x%x). Port(0x%x)<---RPort(0x%x) with OX_ID(0x%x)", - cmd, unf_lport->port_id, unf_rport->nport_id, xchg->oxid); - - /* Case for RJT: Do L_Port recovery */ - unf_lport_error_recovery(unf_lport); - } -} - -void unf_flogi_ob_callback(struct unf_xchg *xchg) -{ - /* Send FLOGI failed & Do L_Port recovery */ - struct unf_lport *unf_lport = NULL; - ulong flag = 0; - - FC_CHECK_RETURN_VOID(xchg); - - /* Get L_port from exchange context */ - spin_lock_irqsave(&xchg->xchg_state_lock, flag); - unf_lport = xchg->lport; - spin_unlock_irqrestore(&xchg->xchg_state_lock, flag); - FC_CHECK_RETURN_VOID(unf_lport); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]LOGIN: Port(0x%x) send FLOGI failed", - unf_lport->port_id); - - /* Check L_Port state */ - spin_lock_irqsave(&unf_lport->lport_state_lock, flag); - if (unf_lport->states != UNF_LPORT_ST_FLOGI_WAIT) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]LOGIN: Port(0x%x_0x%x) send FLOGI failed with state(0x%x)", - unf_lport->port_id, unf_lport->nport_id, unf_lport->states); - - spin_unlock_irqrestore(&unf_lport->lport_state_lock, flag); - return; - } - spin_unlock_irqrestore(&unf_lport->lport_state_lock, flag); - - /* Do L_Port error recovery */ - unf_lport_error_recovery(unf_lport); -} - -static void unf_lport_update_nport_id(struct unf_lport *lport, u32 nport_id) -{ - ulong flag = 0; - - FC_CHECK_RETURN_VOID(lport); - - spin_lock_irqsave(&lport->lport_state_lock, flag); - lport->nport_id = nport_id; - spin_unlock_irqrestore(&lport->lport_state_lock, flag); -} - -static void -unf_lport_update_time_params(struct unf_lport *lport, - struct unf_flogi_fdisc_payload *flogi_payload) -{ - ulong flag = 0; - u32 ed_tov = 0; - u32 ra_tov = 0; - - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(flogi_payload); - - ed_tov = flogi_payload->fabric_parms.co_parms.e_d_tov; - ra_tov = flogi_payload->fabric_parms.co_parms.r_a_tov; - - spin_lock_irqsave(&lport->lport_state_lock, flag); - - /* FC-FS-3: 21.3.4, 21.3.5 */ - if (lport->act_topo == UNF_ACT_TOP_P2P_FABRIC || - lport->act_topo == UNF_ACT_TOP_PUBLIC_LOOP) { - lport->ed_tov = ed_tov; - lport->ra_tov = ra_tov; - } else { - FC_DRV_PRINT(UNF_LOG_EQUIP_ATT, UNF_MAJOR, - "[info]Port(0x%x_0x%x) with topo(0x%x) no need to save time parameters", - lport->port_id, lport->nport_id, lport->act_topo); - } - - spin_unlock_irqrestore(&lport->lport_state_lock, flag); -} - -static void unf_rcv_flogi_acc(struct unf_lport *lport, struct unf_rport *rport, - struct unf_flogi_fdisc_payload *flogi_pld, - u32 nport_id, struct unf_xchg *xchg) -{ - /* PLOGI to Name server or remote port */ - struct unf_lport *unf_lport = lport; - struct unf_rport *unf_rport = rport; - struct unf_flogi_fdisc_payload *unf_flogi_pld = flogi_pld; - struct unf_fabric_parm *fabric_params = NULL; - u64 port_name = 0; - u64 node_name = 0; - ulong flag = 0; - - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(rport); - FC_CHECK_RETURN_VOID(flogi_pld); - - /* Check L_Port state: FLOGI_WAIT */ - spin_lock_irqsave(&unf_lport->lport_state_lock, flag); - if (unf_lport->states != UNF_LPORT_ST_FLOGI_WAIT) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[info]Port(0x%x_0x%x) receive FLOGI ACC with state(0x%x)", - unf_lport->port_id, unf_lport->nport_id, unf_lport->states); - - spin_unlock_irqrestore(&unf_lport->lport_state_lock, flag); - return; - } - spin_unlock_irqrestore(&unf_lport->lport_state_lock, flag); - - fabric_params = &unf_flogi_pld->fabric_parms; - node_name = - (u64)(((u64)(fabric_params->high_node_name) << UNF_SHIFT_32) | - ((u64)(fabric_params->low_node_name))); - port_name = - (u64)(((u64)(fabric_params->high_port_name) << UNF_SHIFT_32) | - ((u64)(fabric_params->low_port_name))); - - /* flogi acc pyload class 3 service priority value */ - if (unf_lport->root_lport == unf_lport && unf_lport->qos_cs_ctrl && - fabric_params->cl_parms[ARRAY_INDEX_2].priority == UNF_PRIORITY_ENABLE) - unf_lport->priority = (bool)UNF_PRIORITY_ENABLE; - else - unf_lport->priority = (bool)UNF_PRIORITY_DISABLE; - - /* Save Flogi parameters */ - unf_save_fabric_params(unf_lport, unf_rport, fabric_params); - - if (UNF_CHECK_NPORT_FPORT_BIT(unf_flogi_pld) == UNF_N_PORT) { - /* P2P Mode */ - unf_lport_update_topo(unf_lport, UNF_ACT_TOP_P2P_DIRECT); - unf_login_with_rport_in_n2n(unf_lport, port_name, node_name); - } else { - /* for: - * UNF_ACT_TOP_PUBLIC_LOOP/UNF_ACT_TOP_P2P_FABRIC - * /UNF_TOP_P2P_MASK - */ - if (unf_lport->act_topo != UNF_ACT_TOP_PUBLIC_LOOP) - unf_lport_update_topo(unf_lport, UNF_ACT_TOP_P2P_FABRIC); - - unf_lport_update_nport_id(unf_lport, nport_id); - unf_lport_update_time_params(unf_lport, unf_flogi_pld); - - /* Save process both for Public loop & Fabric */ - unf_register_to_switch(unf_lport); - } -} - -static void unf_flogi_acc_com_process(struct unf_xchg *xchg) -{ - /* Maybe within interrupt or thread context */ - struct unf_lport *unf_lport = NULL; - struct unf_rport *unf_rport = NULL; - struct unf_flogi_fdisc_payload *flogi_pld = NULL; - u32 nport_id = 0; - u32 cmnd = 0; - ulong flags = 0; - struct unf_xchg *unf_xchg = xchg; - - FC_CHECK_RETURN_VOID(unf_xchg); - FC_CHECK_RETURN_VOID(unf_xchg->lport); - - unf_lport = unf_xchg->lport; - unf_rport = unf_xchg->rport; - flogi_pld = &unf_xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr->flogi_acc.flogi_payload; - cmnd = flogi_pld->cmnd; - - /* Get N_Port_ID & R_Port */ - /* Others: 0xFFFFFE */ - unf_rport = unf_get_rport_by_nport_id(unf_lport, UNF_FC_FID_FLOGI); - nport_id = UNF_FC_FID_FLOGI; - - /* Get Safe R_Port: reuse only */ - unf_rport = unf_get_safe_rport(unf_lport, unf_rport, UNF_RPORT_REUSE_ONLY, nport_id); - if (!unf_rport) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) can not allocate new Rport", unf_lport->port_id); - - return; - } - - spin_lock_irqsave(&unf_rport->rport_state_lock, flags); - unf_rport->nport_id = UNF_FC_FID_FLOGI; - - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flags); - - /* Process FLOGI ACC or RJT */ - if ((cmnd & UNF_ELS_CMND_HIGH_MASK) == UNF_ELS_CMND_ACC) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: FLOGI response is(0x%x). Port(0x%x)<---RPort(0x%x) with OX_ID(0x%x)", - cmnd, unf_lport->port_id, unf_rport->nport_id, unf_xchg->oxid); - - /* Case for ACC */ - unf_rcv_flogi_acc(unf_lport, unf_rport, flogi_pld, unf_xchg->sid, unf_xchg); - } else { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]LOGIN: FLOGI response is(0x%x). Port(0x%x)<---RPort(0x%x) with OX_ID(0x%x)", - cmnd, unf_lport->port_id, unf_rport->nport_id, - unf_xchg->oxid); - - /* Case for RJT: do L_Port error recovery */ - unf_lport_error_recovery(unf_lport); - } -} - -static int unf_rcv_flogi_acc_async_callback(void *argc_in, void *argc_out) -{ - struct unf_xchg *xchg = (struct unf_xchg *)argc_in; - - FC_CHECK_RETURN_VALUE(xchg, UNF_RETURN_ERROR); - - unf_flogi_acc_com_process(xchg); - - unf_xchg_ref_dec(xchg, SFS_RESPONSE); - - return RETURN_OK; -} - -void unf_flogi_callback(void *lport, void *rport, void *xchg) -{ - /* Callback function for FLOGI ACC or RJT */ - struct unf_lport *unf_lport = (struct unf_lport *)lport; - struct unf_xchg *unf_xchg = (struct unf_xchg *)xchg; - struct unf_flogi_fdisc_payload *flogi_pld = NULL; - bool bbscn_enabled = false; - enum unf_act_topo act_topo = UNF_ACT_TOP_UNKNOWN; - bool switch2thread = false; - - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(rport); - FC_CHECK_RETURN_VOID(xchg); - FC_CHECK_RETURN_VOID(unf_xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr); - - unf_xchg->lport = lport; - flogi_pld = &unf_xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr->flogi_acc.flogi_payload; - - if (unf_xchg->byte_orders & UNF_BIT_2) - unf_big_end_to_cpu((u8 *)flogi_pld, sizeof(struct unf_flogi_fdisc_payload)); - - if (unf_lport->act_topo != UNF_ACT_TOP_PUBLIC_LOOP && - (UNF_CHECK_NPORT_FPORT_BIT(flogi_pld) == UNF_F_PORT)) - /* Get Top Mode (P2P_F) --->>> used for BBSCN */ - act_topo = UNF_ACT_TOP_P2P_FABRIC; - - bbscn_enabled = - unf_check_bbscn_is_enabled((u8)unf_lport->low_level_func.lport_cfg_items.bbscn, - (u8)UNF_GET_BB_SC_N_FROM_PARAMS(&flogi_pld->fabric_parms)); - if (act_topo == UNF_ACT_TOP_P2P_FABRIC && bbscn_enabled) { - /* BBSCN Enable or not --->>> used for Context change */ - unf_lport->bbscn_support = true; - switch2thread = true; - } - - if (switch2thread && unf_lport->root_lport == unf_lport) { - /* Wait for LR done sync: for Root Port */ - (void)unf_irq_process_switch2thread(unf_lport, unf_xchg, - unf_rcv_flogi_acc_async_callback); - } else { - /* Process FLOGI response directly */ - unf_flogi_acc_com_process(unf_xchg); - } - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ALL, - "[info]Port(0x%x) process FLOGI response: switch(%d) to thread done", - unf_lport->port_id, switch2thread); -} - -void unf_plogi_ob_callback(struct unf_xchg *xchg) -{ - /* Do L_Port or R_Port recovery */ - struct unf_lport *unf_lport = NULL; - struct unf_rport *unf_rport = NULL; - ulong flag = 0; - - FC_CHECK_RETURN_VOID(xchg); - - spin_lock_irqsave(&xchg->xchg_state_lock, flag); - unf_lport = xchg->lport; - unf_rport = xchg->rport; - spin_unlock_irqrestore(&xchg->xchg_state_lock, flag); - - FC_CHECK_RETURN_VOID(unf_lport); - FC_CHECK_RETURN_VOID(unf_rport); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]LOGIN: Port(0x%x_0x%x) send PLOGI(0x%x_0x%x) to RPort(%p:0x%x_0x%x) failed", - unf_lport->port_id, unf_lport->nport_id, xchg->oxid, - xchg->rxid, unf_rport, unf_rport->rport_index, - unf_rport->nport_id); - - /* Start to recovery */ - if (unf_rport->nport_id > UNF_FC_FID_DOM_MGR) { - /* with Name server: R_Port is fabric --->>> L_Port error - * recovery - */ - unf_lport_error_recovery(unf_lport); - } else { - /* R_Port is not fabric --->>> R_Port error recovery */ - unf_rport_error_recovery(unf_rport); - } -} - -void unf_rcv_plogi_acc(struct unf_lport *lport, struct unf_rport *rport, - struct unf_lgn_parm *login_parms) -{ - /* PLOGI ACC: PRLI(non fabric) or RFT_ID(fabric) */ - struct unf_lport *unf_lport = lport; - struct unf_rport *unf_rport = rport; - struct unf_lgn_parm *unf_login_parms = login_parms; - u64 node_name = 0; - u64 port_name = 0; - ulong flag = 0; - u32 ret = RETURN_OK; - - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(rport); - FC_CHECK_RETURN_VOID(login_parms); - - node_name = (u64)(((u64)(unf_login_parms->high_node_name) << UNF_SHIFT_32) | - ((u64)(unf_login_parms->low_node_name))); - port_name = (u64)(((u64)(unf_login_parms->high_port_name) << UNF_SHIFT_32) | - ((u64)(unf_login_parms->low_port_name))); - - /* ACC & Case for: R_Port is fabric (RFT_ID) */ - if (unf_rport->nport_id >= UNF_FC_FID_DOM_MGR) { - /* Check L_Port state */ - spin_lock_irqsave(&unf_lport->lport_state_lock, flag); - if (unf_lport->states != UNF_LPORT_ST_PLOGI_WAIT) { - spin_unlock_irqrestore(&unf_lport->lport_state_lock, flag); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) receive PLOGI ACC with error state(0x%x)", - lport->port_id, unf_lport->states); - - return; - } - unf_lport_state_ma(unf_lport, UNF_EVENT_LPORT_REMOTE_ACC); - spin_unlock_irqrestore(&unf_lport->lport_state_lock, flag); - - /* PLOGI parameters save */ - unf_save_plogi_params(unf_lport, unf_rport, unf_login_parms, ELS_ACC); - - /* Update R_Port WWPN & WWNN */ - spin_lock_irqsave(&unf_rport->rport_state_lock, flag); - unf_rport->node_name = node_name; - unf_rport->port_name = port_name; - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flag); - - /* Start to Send RFT_ID */ - ret = unf_send_rft_id(unf_lport, unf_rport); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]LOGIN: Port(0x%x) send RFT_ID failed", - lport->port_id); - - unf_lport_error_recovery(unf_lport); - } - } else { - /* ACC & Case for: R_Port is not fabric */ - if (unf_rport->options == UNF_PORT_MODE_UNKNOWN && - unf_rport->port_name != INVALID_WWPN) - unf_rport->options = unf_get_port_feature(port_name); - - /* Set Port Feature with BOTH: cancel */ - spin_lock_irqsave(&unf_rport->rport_state_lock, flag); - unf_rport->node_name = node_name; - unf_rport->port_name = port_name; - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "[info]LOGIN: Port(0x%x)<---LS_ACC(DID:0x%x SID:0x%x) for PLOGI ACC with RPort state(0x%x) NodeName(0x%llx) E_D_TOV(%u)", - unf_lport->port_id, unf_lport->nport_id, - unf_rport->nport_id, unf_rport->rp_state, - unf_rport->node_name, unf_rport->ed_tov); - - if (unf_lport->act_topo == UNF_ACT_TOP_PRIVATE_LOOP && - (unf_rport->rp_state == UNF_RPORT_ST_PRLI_WAIT || - unf_rport->rp_state == UNF_RPORT_ST_READY)) { - /* Do nothing, return directly */ - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flag); - return; - } - - unf_rport_state_ma(unf_rport, UNF_EVENT_RPORT_ENTER_PRLI); - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flag); - - /* PLOGI parameters save */ - unf_save_plogi_params(unf_lport, unf_rport, unf_login_parms, ELS_ACC); - - /* - * Need Delay to Send PRLI or not - * Used for: L_Port with INI mode & R_Port is not Fabric - */ - unf_check_rport_need_delay_prli(unf_lport, unf_rport, unf_rport->options); - - /* Do not care: Just used for L_Port only is TGT mode or R_Port - * only is INI mode - */ - unf_schedule_open_work(unf_lport, unf_rport); - } -} - -void unf_plogi_acc_com_process(struct unf_xchg *xchg) -{ - struct unf_lport *unf_lport = NULL; - struct unf_rport *unf_rport = NULL; - struct unf_xchg *unf_xchg = (struct unf_xchg *)xchg; - struct unf_plogi_payload *plogi_pld = NULL; - struct unf_lgn_parm *login_parms = NULL; - ulong flag = 0; - u64 port_name = 0; - u32 rport_nport_id = 0; - u32 cmnd = 0; - u32 ret = UNF_RETURN_ERROR; - - FC_CHECK_RETURN_VOID(unf_xchg); - FC_CHECK_RETURN_VOID(unf_xchg->lport); - FC_CHECK_RETURN_VOID(unf_xchg->rport); - - unf_lport = unf_xchg->lport; - unf_rport = unf_xchg->rport; - rport_nport_id = unf_rport->nport_id; - plogi_pld = &unf_xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr->plogi_acc.payload; - login_parms = &plogi_pld->stparms; - cmnd = (plogi_pld->cmnd); - - if (UNF_ELS_CMND_ACC == (cmnd & UNF_ELS_CMND_HIGH_MASK)) { - /* Case for PLOGI ACC: Go to next stage */ - port_name = - (u64)(((u64)(login_parms->high_port_name) << UNF_SHIFT_32) | - ((u64)(login_parms->low_port_name))); - - /* Get (new) R_Port: 0xfffffc has same WWN with 0xfffcxx */ - unf_rport = unf_find_rport(unf_lport, rport_nport_id, port_name); - unf_rport = unf_get_safe_rport(unf_lport, unf_rport, - UNF_RPORT_REUSE_ONLY, rport_nport_id); - if (unlikely(!unf_rport)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x_0x%x) alloc new RPort with wwpn(0x%llx) failed", - unf_lport->port_id, unf_lport->nport_id, port_name); - return; - } - - /* PLOGI parameters check */ - ret = unf_check_plogi_params(unf_lport, unf_rport, login_parms); - if (ret != RETURN_OK) - return; - - /* Update R_Port state */ - spin_lock_irqsave(&unf_rport->rport_state_lock, flag); - unf_rport->nport_id = rport_nport_id; - unf_rport_state_ma(unf_rport, UNF_EVENT_RPORT_ENTER_PLOGI); - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flag); - - /* Start to process PLOGI ACC */ - unf_rcv_plogi_acc(unf_lport, unf_rport, login_parms); - } else { - /* Case for PLOGI RJT: L_Port or R_Port recovery */ - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]LOGIN: Port(0x%x)<---RPort(0x%p) with LS_RJT(DID:0x%x SID:0x%x) for PLOGI", - unf_lport->port_id, unf_rport, unf_lport->nport_id, - unf_rport->nport_id); - - if (unf_rport->nport_id >= UNF_FC_FID_DOM_MGR) - unf_lport_error_recovery(unf_lport); - else - unf_rport_error_recovery(unf_rport); - } - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: PLOGI response(0x%x). Port(0x%x_0x%x)<---RPort(0x%x_0x%p) wwpn(0x%llx) OX_ID(0x%x)", - cmnd, unf_lport->port_id, unf_lport->nport_id, unf_rport->nport_id, - unf_rport, port_name, unf_xchg->oxid); -} - -static int unf_rcv_plogi_acc_async_callback(void *argc_in, void *argc_out) -{ - struct unf_xchg *xchg = (struct unf_xchg *)argc_in; - - FC_CHECK_RETURN_VALUE(xchg, UNF_RETURN_ERROR); - - unf_plogi_acc_com_process(xchg); - - unf_xchg_ref_dec(xchg, SFS_RESPONSE); - - return RETURN_OK; -} - -void unf_plogi_callback(void *lport, void *rport, void *xchg) -{ - struct unf_lport *unf_lport = (struct unf_lport *)lport; - struct unf_xchg *unf_xchg = (struct unf_xchg *)xchg; - struct unf_plogi_payload *plogi_pld = NULL; - struct unf_lgn_parm *login_parms = NULL; - bool bbscn_enabled = false; - bool switch2thread = false; - - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(rport); - FC_CHECK_RETURN_VOID(xchg); - FC_CHECK_RETURN_VOID(unf_xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr); - - plogi_pld = &unf_xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr->plogi_acc.payload; - login_parms = &plogi_pld->stparms; - unf_xchg->lport = lport; - - if (unf_xchg->byte_orders & UNF_BIT_2) - unf_big_end_to_cpu((u8 *)plogi_pld, sizeof(struct unf_plogi_payload)); - - bbscn_enabled = - unf_check_bbscn_is_enabled((u8)unf_lport->low_level_func.lport_cfg_items.bbscn, - (u8)UNF_GET_BB_SC_N_FROM_PARAMS(login_parms)); - if ((bbscn_enabled) && - unf_lport->act_topo == UNF_ACT_TOP_P2P_DIRECT) { - switch2thread = true; - unf_lport->bbscn_support = true; - } - - if (switch2thread && unf_lport->root_lport == unf_lport) { - /* Wait for LR done sync: just for ROOT Port */ - (void)unf_irq_process_switch2thread(unf_lport, unf_xchg, - unf_rcv_plogi_acc_async_callback); - } else { - unf_plogi_acc_com_process(unf_xchg); - } -} - -static void unf_logo_ob_callback(struct unf_xchg *xchg) -{ - struct unf_lport *lport = NULL; - struct unf_rport *rport = NULL; - struct unf_rport *old_rport = NULL; - struct unf_xchg *unf_xchg = NULL; - u32 nport_id = 0; - u32 logo_retry = 0; - u32 max_frame_size = 0; - u64 port_name = 0; - - FC_CHECK_RETURN_VOID(xchg); - unf_xchg = xchg; - old_rport = unf_xchg->rport; - logo_retry = old_rport->logo_retries; - max_frame_size = old_rport->max_frame_size; - port_name = old_rport->port_name; - unf_rport_enter_closing(old_rport); - - lport = unf_xchg->lport; - if (unf_is_lport_valid(lport) != RETURN_OK) - return; - - /* Get R_Port by exchange info: Init state */ - nport_id = unf_xchg->did; - rport = unf_get_rport_by_nport_id(lport, nport_id); - rport = unf_get_safe_rport(lport, rport, UNF_RPORT_REUSE_INIT, nport_id); - if (!rport) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) cannot allocate RPort", lport->port_id); - return; - } - - rport->logo_retries = logo_retry; - rport->max_frame_size = max_frame_size; - rport->port_name = port_name; - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[info]LOGIN: Port(0x%x) received LOGO RSP timeout topo(0x%x) retries(%u)", - lport->port_id, lport->act_topo, rport->logo_retries); - - /* RCVD LOGO/PRLO & SEND LOGO: the same process */ - if (rport->logo_retries < UNF_MAX_RETRY_COUNT) { - /* <: retry (LOGIN or LOGO) if necessary */ - unf_process_rport_after_logo(lport, rport); - } else { - /* >=: Link down */ - unf_rport_immediate_link_down(lport, rport); - } -} - -static void unf_logo_callback(void *lport, void *rport, void *xchg) -{ - /* RCVD LOGO ACC/RJT: retry(LOGIN/LOGO) or link down immediately */ - struct unf_lport *unf_lport = (struct unf_lport *)lport; - struct unf_rport *unf_rport = NULL; - struct unf_rport *old_rport = NULL; - struct unf_xchg *unf_xchg = NULL; - struct unf_els_rjt *els_acc_rjt = NULL; - u32 cmnd = 0; - u32 nport_id = 0; - u32 logo_retry = 0; - u32 max_frame_size = 0; - u64 port_name = 0; - - FC_CHECK_RETURN_VOID(xchg); - - unf_xchg = (struct unf_xchg *)xchg; - old_rport = unf_xchg->rport; - - logo_retry = old_rport->logo_retries; - max_frame_size = old_rport->max_frame_size; - port_name = old_rport->port_name; - unf_rport_enter_closing(old_rport); - - if (unf_is_lport_valid(lport) != RETURN_OK) - return; - - if (!unf_xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr) - return; - - /* Get R_Port by exchange info: Init state */ - els_acc_rjt = &unf_xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr->els_rjt; - nport_id = unf_xchg->did; - unf_rport = unf_get_rport_by_nport_id(unf_lport, nport_id); - unf_rport = unf_get_safe_rport(unf_lport, unf_rport, UNF_RPORT_REUSE_INIT, nport_id); - - if (!unf_rport) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, - UNF_WARN, "[warn]Port(0x%x) cannot allocate RPort", - unf_lport->port_id); - return; - } - - unf_rport->logo_retries = logo_retry; - unf_rport->max_frame_size = max_frame_size; - unf_rport->port_name = port_name; - cmnd = be32_to_cpu(els_acc_rjt->cmnd); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: Port(0x%x) received LOGO RSP(0x%x),topo(0x%x) Port options(0x%x) RPort options(0x%x) retries(%u)", - unf_lport->port_id, (cmnd & UNF_ELS_CMND_HIGH_MASK), - unf_lport->act_topo, unf_lport->options, unf_rport->options, - unf_rport->logo_retries); - - /* RCVD LOGO/PRLO & SEND LOGO: the same process */ - if (unf_rport->logo_retries < UNF_MAX_RETRY_COUNT) { - /* <: retry (LOGIN or LOGO) if necessary */ - unf_process_rport_after_logo(unf_lport, unf_rport); - } else { - /* >=: Link down */ - unf_rport_immediate_link_down(unf_lport, unf_rport); - } -} - -void unf_prli_ob_callback(struct unf_xchg *xchg) -{ - /* Do R_Port recovery */ - struct unf_lport *lport = NULL; - struct unf_rport *rport = NULL; - ulong flag = 0; - - FC_CHECK_RETURN_VOID(xchg); - - spin_lock_irqsave(&xchg->xchg_state_lock, flag); - lport = xchg->lport; - rport = xchg->rport; - spin_unlock_irqrestore(&xchg->xchg_state_lock, flag); - - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(rport); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]LOGIN: Port(0x%x_0x%x) RPort(0x%x) send PRLI failed and do recovery", - lport->port_id, lport->nport_id, rport->nport_id); - - /* Start to do R_Port error recovery */ - unf_rport_error_recovery(rport); -} - -void unf_prli_callback(void *lport, void *rport, void *xchg) -{ - /* RCVD PRLI RSP: ACC or RJT --->>> SCSI Link Up */ - struct unf_lport *unf_lport = NULL; - struct unf_rport *unf_rport = NULL; - struct unf_xchg *unf_xchg = NULL; - struct unf_prli_payload *prli_acc_pld = NULL; - ulong flag = 0; - u32 cmnd = 0; - u32 options = 0; - u32 fcp_conf = 0; - u32 rec_support = 0; - u32 task_retry_support = 0; - u32 retry_support = 0; - u32 tape_support = 0; - u32 fc4_type = 0; - enum unf_rport_login_state rport_state = UNF_RPORT_ST_INIT; - - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(rport); - FC_CHECK_RETURN_VOID(xchg); - unf_lport = (struct unf_lport *)lport; - unf_rport = (struct unf_rport *)rport; - unf_xchg = (struct unf_xchg *)xchg; - - if (!unf_xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) exchange(%p) entry is NULL", - unf_lport->port_id, unf_xchg); - return; - } - - /* Get PRLI ACC payload */ - prli_acc_pld = &unf_xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr->prli_acc.payload; - if (unf_xchg->byte_orders & UNF_BIT_2) { - /* Change to little End, About INI/TGT mode & confirm info */ - options = be32_to_cpu(prli_acc_pld->parms[ARRAY_INDEX_3]) & - (UNF_FC4_FRAME_PARM_3_TGT | UNF_FC4_FRAME_PARM_3_INI); - - cmnd = be32_to_cpu(prli_acc_pld->cmnd); - fcp_conf = be32_to_cpu(prli_acc_pld->parms[ARRAY_INDEX_3]) & - UNF_FC4_FRAME_PARM_3_CONF_ALLOW; - rec_support = be32_to_cpu(prli_acc_pld->parms[ARRAY_INDEX_3]) & - UNF_FC4_FRAME_PARM_3_REC_SUPPORT; - task_retry_support = be32_to_cpu(prli_acc_pld->parms[ARRAY_INDEX_3]) & - UNF_FC4_FRAME_PARM_3_TASK_RETRY_ID_SUPPORT; - retry_support = be32_to_cpu(prli_acc_pld->parms[ARRAY_INDEX_3]) & - UNF_FC4_FRAME_PARM_3_RETRY_SUPPORT; - fc4_type = be32_to_cpu(prli_acc_pld->parms[ARRAY_INDEX_0]) >> - UNF_FC4_TYPE_SHIFT & UNF_FC4_TYPE_MASK; - } else { - options = (prli_acc_pld->parms[ARRAY_INDEX_3]) & - (UNF_FC4_FRAME_PARM_3_TGT | UNF_FC4_FRAME_PARM_3_INI); - - cmnd = (prli_acc_pld->cmnd); - fcp_conf = prli_acc_pld->parms[ARRAY_INDEX_3] & UNF_FC4_FRAME_PARM_3_CONF_ALLOW; - rec_support = prli_acc_pld->parms[ARRAY_INDEX_3] & UNF_FC4_FRAME_PARM_3_REC_SUPPORT; - task_retry_support = prli_acc_pld->parms[ARRAY_INDEX_3] & - UNF_FC4_FRAME_PARM_3_TASK_RETRY_ID_SUPPORT; - retry_support = prli_acc_pld->parms[ARRAY_INDEX_3] & - UNF_FC4_FRAME_PARM_3_RETRY_SUPPORT; - fc4_type = prli_acc_pld->parms[ARRAY_INDEX_0] >> UNF_FC4_TYPE_SHIFT; - } - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: PRLI RSP: RPort(0x%x) parameter-3(0x%x) option(0x%x) cmd(0x%x) uiRecSupport:%u", - unf_rport->nport_id, prli_acc_pld->parms[ARRAY_INDEX_3], - options, cmnd, rec_support); - - /* PRLI ACC: R_Port READY & Report R_Port Link Up */ - if (UNF_ELS_CMND_ACC == (cmnd & UNF_ELS_CMND_HIGH_MASK)) { - /* Update R_Port options(INI/TGT/BOTH) */ - unf_rport->options = options; - - unf_update_port_feature(unf_rport->port_name, unf_rport->options); - - /* NOTE: R_Port only with INI mode, send LOGO */ - if (unf_rport->options == UNF_PORT_MODE_INI) { - /* Update R_Port state: LOGO */ - spin_lock_irqsave(&unf_rport->rport_state_lock, flag); - unf_rport_state_ma(unf_rport, UNF_EVENT_RPORT_LOGO); - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flag); - - /* NOTE: Start to Send LOGO */ - unf_rport_enter_logo(unf_lport, unf_rport); - return; - } - - /* About confirm */ - if (fcp_conf && unf_lport->low_level_func.lport_cfg_items.fcp_conf) { - unf_rport->fcp_conf_needed = true; - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x_0x%x) FCP config is need for RPort(0x%x)", - unf_lport->port_id, unf_lport->nport_id, - unf_rport->nport_id); - } - - tape_support = (rec_support && task_retry_support && retry_support); - if (tape_support && unf_lport->low_level_func.lport_cfg_items.tape_support) { - unf_rport->tape_support_needed = true; - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_KEVENT, - "[info]Port(0x%x_0x%x) Rec is enabled for RPort(0x%x)", - unf_lport->port_id, unf_lport->nport_id, - unf_rport->nport_id); - } - - /* Update R_Port state: READY */ - spin_lock_irqsave(&unf_rport->rport_state_lock, flag); - unf_rport_state_ma(unf_rport, UNF_EVENT_RPORT_READY); - rport_state = unf_rport->rp_state; - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flag); - - /* Report R_Port online (Link Up) event to SCSI */ - if (rport_state == UNF_RPORT_ST_READY) { - unf_rport->logo_retries = 0; - unf_update_lport_state_by_linkup_event(unf_lport, unf_rport, - unf_rport->options); - } - } else { - /* PRLI RJT: Do R_Port error recovery */ - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: Port(0x%x)<---LS_RJT(DID:0x%x SID:0x%x) for PRLI. RPort(0x%p) OX_ID(0x%x)", - unf_lport->port_id, unf_lport->nport_id, - unf_rport->nport_id, unf_rport, unf_xchg->oxid); - - unf_rport_error_recovery(unf_rport); - } -} - -static void unf_rrq_callback(void *lport, void *rport, void *xchg) -{ - /* Release I/O */ - struct unf_lport *unf_lport = NULL; - struct unf_xchg *unf_xchg = NULL; - struct unf_xchg *io_xchg = NULL; - - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(rport); - FC_CHECK_RETURN_VOID(xchg); - - unf_lport = (struct unf_lport *)lport; - unf_xchg = (struct unf_xchg *)xchg; - - if (!unf_xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x) exchange(0x%p) SfsEntryPtr is NULL", - unf_lport->port_id, unf_xchg); - return; - } - - io_xchg = (struct unf_xchg *)unf_xchg->io_xchg; - if (!io_xchg) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x) IO exchange is NULL. RRQ cb sfs xchg(0x%p) tag(0x%x)", - unf_lport->port_id, unf_xchg, unf_xchg->hotpooltag); - return; - } - - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_MAJOR, - "[info]Port(0x%x) release IO exch(0x%p) tag(0x%x). RRQ cb sfs xchg(0x%p) tag(0x%x)", - unf_lport->port_id, unf_xchg->io_xchg, io_xchg->hotpooltag, - unf_xchg, unf_xchg->hotpooltag); - - /* After RRQ Success, Free xid */ - unf_notify_chip_free_xid(io_xchg); - - /* NOTE: release I/O exchange resource */ - unf_xchg_ref_dec(io_xchg, XCHG_ALLOC); -} - -static void unf_rrq_ob_callback(struct unf_xchg *xchg) -{ - /* Release I/O */ - struct unf_xchg *unf_xchg = NULL; - struct unf_xchg *io_xchg = NULL; - - unf_xchg = (struct unf_xchg *)xchg; - if (!unf_xchg) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, - UNF_WARN, "[warn]Exchange can't be NULL"); - return; - } - - io_xchg = (struct unf_xchg *)unf_xchg->io_xchg; - if (!io_xchg) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]IO exchange can't be NULL with Sfs exch(0x%p) tag(0x%x)", - unf_xchg, unf_xchg->hotpooltag); - return; - } - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_KEVENT, - "[info]send RRQ failed: SFS exch(0x%p) tag(0x%x) exch(0x%p) tag(0x%x) OXID_RXID(0x%x_0x%x) SID_DID(0x%x_0x%x)", - unf_xchg, unf_xchg->hotpooltag, io_xchg, io_xchg->hotpooltag, - io_xchg->oxid, io_xchg->rxid, io_xchg->sid, io_xchg->did); - - /* If RRQ failure or timepout, Free xid. */ - unf_notify_chip_free_xid(io_xchg); - - /* NOTE: Free I/O exchange resource */ - unf_xchg_ref_dec(io_xchg, XCHG_ALLOC); -} diff --git a/drivers/scsi/spfc/common/unf_ls.h b/drivers/scsi/spfc/common/unf_ls.h deleted file mode 100644 index 5fdd9e1a258d..000000000000 --- a/drivers/scsi/spfc/common/unf_ls.h +++ /dev/null @@ -1,61 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef UNF_LS_H -#define UNF_LS_H - -#include "unf_type.h" -#include "unf_exchg.h" -#include "unf_rport.h" - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -u32 unf_send_adisc(struct unf_lport *lport, struct unf_rport *rport); -u32 unf_send_pdisc(struct unf_lport *lport, struct unf_rport *rport); -u32 unf_send_flogi(struct unf_lport *lport, struct unf_rport *rport); -u32 unf_send_fdisc(struct unf_lport *lport, struct unf_rport *rport); -u32 unf_send_plogi(struct unf_lport *lport, struct unf_rport *rport); -u32 unf_send_prli(struct unf_lport *lport, struct unf_rport *rport, - u32 cmnd_code); -u32 unf_send_prlo(struct unf_lport *lport, struct unf_rport *rport); -u32 unf_send_logo(struct unf_lport *lport, struct unf_rport *rport); -u32 unf_send_logo_by_did(struct unf_lport *lport, u32 did); -u32 unf_send_echo(struct unf_lport *lport, struct unf_rport *rport, u32 *time); -u32 unf_send_plogi_rjt_by_did(struct unf_lport *lport, u32 did); -u32 unf_send_rrq(struct unf_lport *lport, struct unf_rport *rport, - struct unf_xchg *xchg); -void unf_flogi_ob_callback(struct unf_xchg *xchg); -void unf_flogi_callback(void *lport, void *rport, void *xchg); -void unf_fdisc_ob_callback(struct unf_xchg *xchg); -void unf_fdisc_callback(void *lport, void *rport, void *xchg); - -void unf_plogi_ob_callback(struct unf_xchg *xchg); -void unf_plogi_callback(void *lport, void *rport, void *xchg); -void unf_prli_ob_callback(struct unf_xchg *xchg); -void unf_prli_callback(void *lport, void *rport, void *xchg); -u32 unf_flogi_handler(struct unf_lport *lport, u32 sid, struct unf_xchg *xchg); -u32 unf_plogi_handler(struct unf_lport *lport, u32 sid, struct unf_xchg *xchg); -u32 unf_rec_handler(struct unf_lport *lport, u32 sid, struct unf_xchg *xchg); -u32 unf_prli_handler(struct unf_lport *lport, u32 sid, struct unf_xchg *xchg); -u32 unf_prlo_handler(struct unf_lport *lport, u32 sid, struct unf_xchg *xchg); -u32 unf_rscn_handler(struct unf_lport *lport, u32 sid, struct unf_xchg *xchg); -u32 unf_logo_handler(struct unf_lport *lport, u32 sid, struct unf_xchg *xchg); -u32 unf_echo_handler(struct unf_lport *lport, u32 sid, struct unf_xchg *xchg); -u32 unf_pdisc_handler(struct unf_lport *lport, u32 sid, struct unf_xchg *xchg); -u32 unf_send_pdisc_rjt(struct unf_lport *lport, struct unf_rport *rport, - struct unf_xchg *xchg); -u32 unf_adisc_handler(struct unf_lport *lport, u32 sid, struct unf_xchg *xchg); -u32 unf_rrq_handler(struct unf_lport *lport, u32 sid, struct unf_xchg *xchg); -u32 unf_send_rec(struct unf_lport *lport, struct unf_rport *rport, - struct unf_xchg *io_xchg); - -u32 unf_low_level_bb_scn(struct unf_lport *lport); -typedef int (*unf_event_task)(void *arg_in, void *arg_out); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __UNF_SERVICE_H__ */ diff --git a/drivers/scsi/spfc/common/unf_npiv.c b/drivers/scsi/spfc/common/unf_npiv.c deleted file mode 100644 index 0d441f1c9e06..000000000000 --- a/drivers/scsi/spfc/common/unf_npiv.c +++ /dev/null @@ -1,1005 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#include "unf_npiv.h" -#include "unf_log.h" -#include "unf_rport.h" -#include "unf_exchg.h" -#include "unf_portman.h" -#include "unf_npiv_portman.h" - -#define UNF_DELETE_VPORT_MAX_WAIT_TIME_MS 60000 - -u32 unf_init_vport_pool(struct unf_lport *lport) -{ - u32 ret = RETURN_OK; - u32 i; - u16 vport_cnt = 0; - struct unf_lport *vport = NULL; - struct unf_vport_pool *vport_pool = NULL; - u32 vport_pool_size; - ulong flags = 0; - - FC_CHECK_RETURN_VALUE(lport, RETURN_ERROR); - - UNF_TOU16_CHECK(vport_cnt, lport->low_level_func.support_max_npiv_num, - return RETURN_ERROR); - if (vport_cnt == 0) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[warn]Port(0x%x) do not support NPIV", - lport->port_id); - - return RETURN_OK; - } - - vport_pool_size = sizeof(struct unf_vport_pool) + sizeof(struct unf_lport *) * vport_cnt; - lport->vport_pool = vmalloc(vport_pool_size); - if (!lport->vport_pool) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Port(0x%x) cannot allocate vport pool", - lport->port_id); - - return RETURN_ERROR; - } - memset(lport->vport_pool, 0, vport_pool_size); - vport_pool = lport->vport_pool; - vport_pool->vport_pool_count = vport_cnt; - vport_pool->vport_pool_completion = NULL; - spin_lock_init(&vport_pool->vport_pool_lock); - INIT_LIST_HEAD(&vport_pool->list_vport_pool); - - vport_pool->vport_pool_addr = - vmalloc((size_t)(vport_cnt * sizeof(struct unf_lport))); - if (!vport_pool->vport_pool_addr) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Port(0x%x) cannot allocate vport pool address", - lport->port_id); - vfree(lport->vport_pool); - lport->vport_pool = NULL; - - return RETURN_ERROR; - } - - memset(vport_pool->vport_pool_addr, 0, - vport_cnt * sizeof(struct unf_lport)); - vport = (struct unf_lport *)vport_pool->vport_pool_addr; - - spin_lock_irqsave(&vport_pool->vport_pool_lock, flags); - for (i = 0; i < vport_cnt; i++) { - list_add_tail(&vport->entry_vport, &vport_pool->list_vport_pool); - vport++; - } - - vport_pool->slab_next_index = 0; - vport_pool->slab_total_sum = vport_cnt; - spin_unlock_irqrestore(&vport_pool->vport_pool_lock, flags); - - return ret; -} - -void unf_free_vport_pool(struct unf_lport *lport) -{ - struct unf_vport_pool *vport_pool = NULL; - bool wait = false; - ulong flag = 0; - u32 remain = 0; - struct completion vport_pool_completion; - - init_completion(&vport_pool_completion); - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(lport->vport_pool); - vport_pool = lport->vport_pool; - - spin_lock_irqsave(&vport_pool->vport_pool_lock, flag); - - if (vport_pool->slab_total_sum != vport_pool->vport_pool_count) { - vport_pool->vport_pool_completion = &vport_pool_completion; - remain = vport_pool->slab_total_sum - vport_pool->vport_pool_count; - wait = true; - } - spin_unlock_irqrestore(&vport_pool->vport_pool_lock, flag); - - if (wait) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]Port(0x%x) begin to wait for vport pool completion remain(0x%x)", - lport->port_id, remain); - - wait_for_completion(vport_pool->vport_pool_completion); - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]Port(0x%x) wait for vport pool completion end", - lport->port_id); - spin_lock_irqsave(&vport_pool->vport_pool_lock, flag); - vport_pool->vport_pool_completion = NULL; - spin_unlock_irqrestore(&vport_pool->vport_pool_lock, flag); - } - - if (lport->vport_pool->vport_pool_addr) { - vfree(lport->vport_pool->vport_pool_addr); - lport->vport_pool->vport_pool_addr = NULL; - } - - vfree(lport->vport_pool); - lport->vport_pool = NULL; -} - -struct unf_lport *unf_get_vport_by_slab_index(struct unf_vport_pool *vport_pool, - u16 slab_index) -{ - FC_CHECK_RETURN_VALUE(vport_pool, NULL); - - return vport_pool->vport_slab[slab_index]; -} - -static inline void unf_vport_pool_slab_set(struct unf_vport_pool *vport_pool, - u16 slab_index, - struct unf_lport *vport) -{ - FC_CHECK_RETURN_VOID(vport_pool); - - vport_pool->vport_slab[slab_index] = vport; -} - -u32 unf_alloc_vp_index(struct unf_vport_pool *vport_pool, - struct unf_lport *vport, u16 vpid) -{ - u16 slab_index; - ulong flags = 0; - - FC_CHECK_RETURN_VALUE(vport_pool, RETURN_ERROR); - FC_CHECK_RETURN_VALUE(vport, RETURN_ERROR); - - spin_lock_irqsave(&vport_pool->vport_pool_lock, flags); - if (vpid == 0) { - slab_index = vport_pool->slab_next_index; - while (unf_get_vport_by_slab_index(vport_pool, slab_index)) { - slab_index = (slab_index + 1) % vport_pool->slab_total_sum; - - if (vport_pool->slab_next_index == slab_index) { - spin_unlock_irqrestore(&vport_pool->vport_pool_lock, flags); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[warn]VPort pool has no slab "); - - return RETURN_ERROR; - } - } - } else { - slab_index = vpid - 1; - if (unf_get_vport_by_slab_index(vport_pool, slab_index)) { - spin_unlock_irqrestore(&vport_pool->vport_pool_lock, flags); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, - UNF_WARN, - "[warn]VPort Index(0x%x) is occupy", vpid); - - return RETURN_ERROR; - } - } - - unf_vport_pool_slab_set(vport_pool, slab_index, vport); - - vport_pool->slab_next_index = (slab_index + 1) % vport_pool->slab_total_sum; - - spin_unlock_irqrestore(&vport_pool->vport_pool_lock, flags); - - spin_lock_irqsave(&vport->lport_state_lock, flags); - vport->vp_index = slab_index + 1; - spin_unlock_irqrestore(&vport->lport_state_lock, flags); - - return RETURN_OK; -} - -void unf_free_vp_index(struct unf_vport_pool *vport_pool, - struct unf_lport *vport) -{ - ulong flags = 0; - - FC_CHECK_RETURN_VOID(vport_pool); - FC_CHECK_RETURN_VOID(vport); - - if (vport->vp_index == 0 || - vport->vp_index > vport_pool->slab_total_sum) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_MAJOR, - "Input vpoot index(0x%x) is beyond the normal range, min(0x1), max(0x%x).", - vport->vp_index, vport_pool->slab_total_sum); - return; - } - - spin_lock_irqsave(&vport_pool->vport_pool_lock, flags); - unf_vport_pool_slab_set(vport_pool, vport->vp_index - 1, - NULL); /* SlabIndex=VpIndex-1 */ - spin_unlock_irqrestore(&vport_pool->vport_pool_lock, flags); - - spin_lock_irqsave(&vport->lport_state_lock, flags); - vport->vp_index = INVALID_VALUE16; - spin_unlock_irqrestore(&vport->lport_state_lock, flags); -} - -struct unf_lport *unf_get_free_vport(struct unf_lport *lport) -{ - struct unf_lport *vport = NULL; - struct list_head *list_head = NULL; - struct unf_vport_pool *vport_pool = NULL; - ulong flag = 0; - - FC_CHECK_RETURN_VALUE(lport, NULL); - FC_CHECK_RETURN_VALUE(lport->vport_pool, NULL); - - vport_pool = lport->vport_pool; - - spin_lock_irqsave(&vport_pool->vport_pool_lock, flag); - if (!list_empty(&vport_pool->list_vport_pool)) { - list_head = UNF_OS_LIST_NEXT(&vport_pool->list_vport_pool); - list_del(list_head); - vport_pool->vport_pool_count--; - list_add_tail(list_head, &lport->list_vports_head); - vport = list_entry(list_head, struct unf_lport, entry_vport); - } else { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]LPort(0x%x)'s vport pool is empty", lport->port_id); - spin_unlock_irqrestore(&vport_pool->vport_pool_lock, flag); - - return NULL; - } - spin_unlock_irqrestore(&vport_pool->vport_pool_lock, flag); - - return vport; -} - -void unf_vport_back_to_pool(void *vport) -{ - struct unf_lport *unf_lport = NULL; - struct unf_lport *unf_vport = NULL; - struct list_head *list = NULL; - ulong flag = 0; - - FC_CHECK_RETURN_VOID(vport); - unf_vport = vport; - unf_lport = (struct unf_lport *)(unf_vport->root_lport); - FC_CHECK_RETURN_VOID(unf_lport); - FC_CHECK_RETURN_VOID(unf_lport->vport_pool); - - unf_free_vp_index(unf_lport->vport_pool, unf_vport); - - spin_lock_irqsave(&unf_lport->vport_pool->vport_pool_lock, flag); - - list = &unf_vport->entry_vport; - list_del(list); - list_add_tail(list, &unf_lport->vport_pool->list_vport_pool); - unf_lport->vport_pool->vport_pool_count++; - - spin_unlock_irqrestore(&unf_lport->vport_pool->vport_pool_lock, flag); -} - -void unf_init_vport_from_lport(struct unf_lport *vport, struct unf_lport *lport) -{ - FC_CHECK_RETURN_VOID(vport); - FC_CHECK_RETURN_VOID(lport); - - vport->port_type = lport->port_type; - vport->fc_port = lport->fc_port; - vport->act_topo = lport->act_topo; - vport->root_lport = lport; - vport->unf_qualify_rport = lport->unf_qualify_rport; - vport->link_event_wq = lport->link_event_wq; - vport->xchg_wq = lport->xchg_wq; - - memcpy(&vport->xchg_mgr_temp, &lport->xchg_mgr_temp, - sizeof(struct unf_cm_xchg_mgr_template)); - - memcpy(&vport->event_mgr, &lport->event_mgr, sizeof(struct unf_event_mgr)); - - memset(&vport->lport_mgr_temp, 0, sizeof(struct unf_cm_lport_template)); - - memcpy(&vport->low_level_func, &lport->low_level_func, - sizeof(struct unf_low_level_functioon_op)); -} - -void unf_check_vport_pool_status(struct unf_lport *lport) -{ - struct unf_vport_pool *vport_pool = NULL; - ulong flags = 0; - - FC_CHECK_RETURN_VOID(lport); - vport_pool = lport->vport_pool; - FC_CHECK_RETURN_VOID(vport_pool); - - spin_lock_irqsave(&vport_pool->vport_pool_lock, flags); - - if (vport_pool->vport_pool_completion && - vport_pool->slab_total_sum == vport_pool->vport_pool_count) { - complete(vport_pool->vport_pool_completion); - } - spin_unlock_irqrestore(&vport_pool->vport_pool_lock, flags); -} - -void unf_vport_fabric_logo(struct unf_lport *vport) -{ - struct unf_rport *unf_rport = NULL; - ulong flag = 0; - - unf_rport = unf_get_rport_by_nport_id(vport, UNF_FC_FID_FLOGI); - FC_CHECK_RETURN_VOID(unf_rport); - spin_lock_irqsave(&unf_rport->rport_state_lock, flag); - unf_rport_state_ma(unf_rport, UNF_EVENT_RPORT_LOGO); - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flag); - - unf_rport_enter_logo(vport, unf_rport); -} - -void unf_vport_deinit(void *vport) -{ - struct unf_lport *unf_vport = NULL; - - FC_CHECK_RETURN_VOID(vport); - unf_vport = (struct unf_lport *)vport; - - unf_unregister_scsi_host(unf_vport); - - unf_disc_mgr_destroy(unf_vport); - - unf_release_xchg_mgr_temp(unf_vport); - - unf_release_vport_mgr_temp(unf_vport); - - unf_destroy_scsi_id_table(unf_vport); - - unf_lport_release_lw_funop(unf_vport); - unf_vport->fc_port = NULL; - unf_vport->vport = NULL; - - if (unf_vport->lport_free_completion) { - complete(unf_vport->lport_free_completion); - } else { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]VPort(0x%x) point(0x%p) completion free function is NULL", - unf_vport->port_id, unf_vport); - dump_stack(); - } -} - -void unf_vport_ref_dec(struct unf_lport *vport) -{ - FC_CHECK_RETURN_VOID(vport); - - if (atomic_dec_and_test(&vport->port_ref_cnt)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]VPort(0x%x) point(0x%p) reference count is 0 and freevport", - vport->port_id, vport); - - unf_vport_deinit(vport); - } -} - -u32 unf_vport_init(void *vport) -{ - struct unf_lport *unf_vport = NULL; - - FC_CHECK_RETURN_VALUE(vport, RETURN_ERROR); - unf_vport = (struct unf_lport *)vport; - - unf_vport->options = UNF_PORT_MODE_INI; - unf_vport->nport_id = 0; - - if (unf_init_scsi_id_table(unf_vport) != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Vport(0x%x) can not initialize SCSI ID table", - unf_vport->port_id); - - return RETURN_ERROR; - } - - if (unf_init_disc_mgr(unf_vport) != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Vport(0x%x) can not initialize discover manager", - unf_vport->port_id); - unf_destroy_scsi_id_table(unf_vport); - - return RETURN_ERROR; - } - - if (unf_register_scsi_host(unf_vport) != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Vport(0x%x) vport can not register SCSI host", - unf_vport->port_id); - unf_disc_mgr_destroy(unf_vport); - unf_destroy_scsi_id_table(unf_vport); - - return RETURN_ERROR; - } - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_KEVENT, - "[event]Vport(0x%x) Create succeed with wwpn(0x%llx)", - unf_vport->port_id, unf_vport->port_name); - - return RETURN_OK; -} - -void unf_vport_remove(void *vport) -{ - struct unf_lport *unf_vport = NULL; - struct unf_lport *unf_lport = NULL; - struct completion port_free_completion; - - init_completion(&port_free_completion); - FC_CHECK_RETURN_VOID(vport); - unf_vport = (struct unf_lport *)vport; - unf_lport = (struct unf_lport *)(unf_vport->root_lport); - unf_vport->lport_free_completion = &port_free_completion; - - unf_set_lport_removing(unf_vport); - - unf_vport_ref_dec(unf_vport); - - wait_for_completion(unf_vport->lport_free_completion); - unf_vport_back_to_pool(unf_vport); - - unf_check_vport_pool_status(unf_lport); -} - -u32 unf_npiv_conf(u32 port_id, u64 wwpn, enum unf_rport_qos_level qos_level) -{ -#define VPORT_WWN_MASK 0xff00ffffffffffff -#define VPORT_WWN_SHIFT 48 - - struct fc_vport_identifiers vid = {0}; - struct Scsi_Host *host = NULL; - struct unf_lport *unf_lport = NULL; - struct unf_lport *unf_vport = NULL; - u16 vport_id = 0; - - unf_lport = unf_find_lport_by_port_id(port_id); - if (!unf_lport) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Cannot find LPort by (0x%x).", port_id); - - return RETURN_ERROR; - } - - unf_vport = unf_cm_lookup_vport_by_wwpn(unf_lport, wwpn); - if (unf_vport) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[err]Port(0x%x) has find vport with wwpn(0x%llx), can't create again", - unf_lport->port_id, wwpn); - - return RETURN_ERROR; - } - - unf_vport = unf_get_free_vport(unf_lport); - if (!unf_vport) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[warn]Can not get free vport from pool"); - - return RETURN_ERROR; - } - - unf_init_port_parms(unf_vport); - unf_init_vport_from_lport(unf_vport, unf_lport); - - if ((unf_lport->port_name & VPORT_WWN_MASK) == (wwpn & VPORT_WWN_MASK)) { - vport_id = (wwpn & ~VPORT_WWN_MASK) >> VPORT_WWN_SHIFT; - if (vport_id == 0) - vport_id = (unf_lport->port_name & ~VPORT_WWN_MASK) >> VPORT_WWN_SHIFT; - } - - if (unf_alloc_vp_index(unf_lport->vport_pool, unf_vport, vport_id) != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[warn]Vport can not allocate vport index"); - unf_vport_back_to_pool(unf_vport); - - return RETURN_ERROR; - } - unf_vport->port_id = (((u32)unf_vport->vp_index) << PORTID_VPINDEX_SHIT) | - unf_lport->port_id; - - vid.roles = FC_PORT_ROLE_FCP_INITIATOR; - vid.vport_type = FC_PORTTYPE_NPIV; - vid.disable = false; - vid.node_name = unf_lport->node_name; - - if (wwpn) { - vid.port_name = wwpn; - } else { - if ((unf_lport->port_name & ~VPORT_WWN_MASK) >> VPORT_WWN_SHIFT != - unf_vport->vp_index) { - vid.port_name = (unf_lport->port_name & VPORT_WWN_MASK) | - (((u64)unf_vport->vp_index) << VPORT_WWN_SHIFT); - } else { - vid.port_name = (unf_lport->port_name & VPORT_WWN_MASK); - } - } - - unf_vport->port_name = vid.port_name; - - host = unf_lport->host_info.host; - - if (!fc_vport_create(host, 0, &vid)) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Port(0x%x) Cannot Failed to create vport wwpn=%llx", - unf_lport->port_id, vid.port_name); - - unf_vport_back_to_pool(unf_vport); - - return RETURN_ERROR; - } - - unf_vport->qos_level = qos_level; - return RETURN_OK; -} - -struct unf_lport *unf_creat_vport(struct unf_lport *lport, - struct vport_config *vport_config) -{ - u32 ret = RETURN_OK; - struct unf_lport *unf_lport = NULL; - struct unf_lport *vport = NULL; - enum unf_act_topo lport_topo; - enum unf_lport_login_state lport_state; - ulong flag = 0; - - FC_CHECK_RETURN_VALUE(lport, NULL); - FC_CHECK_RETURN_VALUE(vport_config, NULL); - - if (vport_config->port_mode != FC_PORT_ROLE_FCP_INITIATOR) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Only support INITIATOR port mode(0x%x)", - vport_config->port_mode); - - return NULL; - } - unf_lport = lport; - - if (unf_lport->root_lport != unf_lport) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Port(0x%x) not root port return", - unf_lport->port_id); - - return NULL; - } - - vport = unf_cm_lookup_vport_by_wwpn(unf_lport, vport_config->port_name); - if (!vport) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[err]Port(0x%x) can not find vport with wwpn(0x%llx)", - unf_lport->port_id, vport_config->port_name); - - return NULL; - } - - ret = unf_vport_init(vport); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[warn]VPort(0x%x) can not initialize vport", - vport->port_id); - - return NULL; - } - - spin_lock_irqsave(&unf_lport->lport_state_lock, flag); - lport_topo = unf_lport->act_topo; - lport_state = unf_lport->states; - - vport_config->node_name = unf_lport->node_name; - spin_unlock_irqrestore(&unf_lport->lport_state_lock, flag); - - vport->port_name = vport_config->port_name; - vport->node_name = vport_config->node_name; - - if (lport_topo == UNF_ACT_TOP_P2P_FABRIC && - lport_state >= UNF_LPORT_ST_PLOGI_WAIT && - lport_state <= UNF_LPORT_ST_READY) { - vport->link_up = unf_lport->link_up; - (void)unf_lport_login(vport, lport_topo); - } - - return vport; -} - -u32 unf_drop_vport(struct unf_lport *vport) -{ - u32 ret = RETURN_ERROR; - struct fc_vport *unf_vport = NULL; - - FC_CHECK_RETURN_VALUE(vport, RETURN_ERROR); - - unf_vport = vport->vport; - if (!unf_vport) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]VPort(0x%x) find vport in scsi is NULL", - vport->port_id); - - return ret; - } - - ret = fc_vport_terminate(unf_vport); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]VPort(0x%x) terminate vport(%p) in scsi failed", - vport->port_id, unf_vport); - - return ret; - } - return ret; -} - -u32 unf_delete_vport(u32 port_id, u32 vp_index) -{ - struct unf_lport *unf_lport = NULL; - u16 unf_vp_index = 0; - struct unf_lport *vport = NULL; - - unf_lport = unf_find_lport_by_port_id(port_id); - if (!unf_lport) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Port(0x%x) can not be found by portid", port_id); - - return RETURN_ERROR; - } - - if (atomic_read(&unf_lport->lport_no_operate_flag) == UNF_LPORT_NOP) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]Port(0x%x) is in NOP, destroy all vports function will be called", - unf_lport->port_id); - - return RETURN_OK; - } - - UNF_TOU16_CHECK(unf_vp_index, vp_index, return RETURN_ERROR); - vport = unf_cm_lookup_vport_by_vp_index(unf_lport, unf_vp_index); - if (!vport) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[warn]Can not lookup VPort by VPort index(0x%x)", - unf_vp_index); - - return RETURN_ERROR; - } - - return unf_drop_vport(vport); -} - -void unf_vport_abort_all_sfs_exch(struct unf_lport *vport) -{ - struct unf_xchg_hot_pool *hot_pool = NULL; - struct list_head *xchg_node = NULL; - struct list_head *next_xchg_node = NULL; - struct unf_xchg *exch = NULL; - ulong pool_lock_flags = 0; - ulong exch_lock_flags = 0; - u32 i; - - FC_CHECK_RETURN_VOID(vport); - for (i = 0; i < UNF_EXCHG_MGR_NUM; i++) { - hot_pool = unf_get_hot_pool_by_lport((struct unf_lport *)(vport->root_lport), i); - if (unlikely(!hot_pool)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x) hot pool is NULL", - ((struct unf_lport *)(vport->root_lport))->port_id); - continue; - } - - spin_lock_irqsave(&hot_pool->xchg_hotpool_lock, pool_lock_flags); - list_for_each_safe(xchg_node, next_xchg_node, &hot_pool->sfs_busylist) { - exch = list_entry(xchg_node, struct unf_xchg, list_xchg_entry); - spin_lock_irqsave(&exch->xchg_state_lock, exch_lock_flags); - if (vport == exch->lport && (atomic_read(&exch->ref_cnt) > 0)) { - exch->io_state |= TGT_IO_STATE_ABORT; - spin_unlock_irqrestore(&exch->xchg_state_lock, exch_lock_flags); - unf_disc_ctrl_size_inc(vport, exch->cmnd_code); - /* Transfer exch to destroy chain */ - list_del(xchg_node); - list_add_tail(xchg_node, &hot_pool->list_destroy_xchg); - } else { - spin_unlock_irqrestore(&exch->xchg_state_lock, exch_lock_flags); - } - } - spin_unlock_irqrestore(&hot_pool->xchg_hotpool_lock, pool_lock_flags); - } -} - -void unf_vport_abort_ini_io_exch(struct unf_lport *vport) -{ - struct unf_xchg_hot_pool *hot_pool = NULL; - struct list_head *xchg_node = NULL; - struct list_head *next_xchg_node = NULL; - struct unf_xchg *exch = NULL; - ulong pool_lock_flags = 0; - ulong exch_lock_flags = 0; - u32 i; - - FC_CHECK_RETURN_VOID(vport); - for (i = 0; i < UNF_EXCHG_MGR_NUM; i++) { - hot_pool = unf_get_hot_pool_by_lport((struct unf_lport *)(vport->root_lport), i); - if (unlikely(!hot_pool)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x) MgrIdex %u hot pool is NULL", - ((struct unf_lport *)(vport->root_lport))->port_id, i); - continue; - } - - spin_lock_irqsave(&hot_pool->xchg_hotpool_lock, pool_lock_flags); - list_for_each_safe(xchg_node, next_xchg_node, &hot_pool->ini_busylist) { - exch = list_entry(xchg_node, struct unf_xchg, list_xchg_entry); - - if (vport == exch->lport && atomic_read(&exch->ref_cnt) > 0) { - /* Transfer exch to destroy chain */ - list_del(xchg_node); - list_add_tail(xchg_node, &hot_pool->list_destroy_xchg); - - spin_lock_irqsave(&exch->xchg_state_lock, exch_lock_flags); - exch->io_state |= INI_IO_STATE_DRABORT; - spin_unlock_irqrestore(&exch->xchg_state_lock, exch_lock_flags); - } - } - - spin_unlock_irqrestore(&hot_pool->xchg_hotpool_lock, pool_lock_flags); - } -} - -void unf_vport_abort_exch(struct unf_lport *vport) -{ - FC_CHECK_RETURN_VOID(vport); - - unf_vport_abort_all_sfs_exch(vport); - - unf_vport_abort_ini_io_exch(vport); -} - -u32 unf_vport_wait_all_exch_removed(struct unf_lport *vport) -{ -#define UNF_WAIT_EXCH_REMOVE_ONE_TIME_MS 1000 - struct unf_xchg_hot_pool *hot_pool = NULL; - struct list_head *xchg_node = NULL; - struct list_head *next_xchg_node = NULL; - struct unf_xchg *exch = NULL; - u32 vport_uses = 0; - ulong flags = 0; - u32 wait_timeout = 0; - u32 i = 0; - - FC_CHECK_RETURN_VALUE(vport, RETURN_ERROR); - - while (1) { - vport_uses = 0; - - for (i = 0; i < UNF_EXCHG_MGR_NUM; i++) { - hot_pool = - unf_get_hot_pool_by_lport((struct unf_lport *)(vport->root_lport), i); - if (unlikely(!hot_pool)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x) hot Pool is NULL", - ((struct unf_lport *)(vport->root_lport))->port_id); - - continue; - } - - spin_lock_irqsave(&hot_pool->xchg_hotpool_lock, flags); - list_for_each_safe(xchg_node, next_xchg_node, - &hot_pool->list_destroy_xchg) { - exch = list_entry(xchg_node, struct unf_xchg, list_xchg_entry); - - if (exch->lport != vport) - continue; - vport_uses++; - if (wait_timeout >= - UNF_DELETE_VPORT_MAX_WAIT_TIME_MS) { - FC_DRV_PRINT(UNF_LOG_NORMAL, UNF_ERR, - "[error]VPort(0x%x) Abort Exch(0x%p) Type(0x%x) OxRxid(0x%x 0x%x),sid did(0x%x 0x%x) SeqId(0x%x) IOState(0x%x) Ref(0x%x)", - vport->port_id, exch, - (u32)exch->xchg_type, - (u32)exch->oxid, - (u32)exch->rxid, (u32)exch->sid, - (u32)exch->did, (u32)exch->seq_id, - (u32)exch->io_state, - atomic_read(&exch->ref_cnt)); - } - } - spin_unlock_irqrestore(&hot_pool->xchg_hotpool_lock, flags); - } - - if (vport_uses == 0) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_MAJOR, - "[info]VPort(0x%x) has removed all exchanges it used", - vport->port_id); - break; - } - - if (wait_timeout >= UNF_DELETE_VPORT_MAX_WAIT_TIME_MS) - return RETURN_ERROR; - - msleep(UNF_WAIT_EXCH_REMOVE_ONE_TIME_MS); - wait_timeout += UNF_WAIT_EXCH_REMOVE_ONE_TIME_MS; - } - - return RETURN_OK; -} - -u32 unf_vport_wait_rports_removed(struct unf_lport *vport) -{ -#define UNF_WAIT_RPORT_REMOVE_ONE_TIME_MS 5000 - - struct unf_disc *disc = NULL; - struct list_head *node = NULL; - struct list_head *next_node = NULL; - u32 vport_uses = 0; - ulong flags = 0; - u32 wait_timeout = 0; - struct unf_rport *unf_rport = NULL; - - FC_CHECK_RETURN_VALUE(vport, RETURN_ERROR); - disc = &vport->disc; - - while (1) { - vport_uses = 0; - spin_lock_irqsave(&disc->rport_busy_pool_lock, flags); - list_for_each_safe(node, next_node, &disc->list_delete_rports) { - unf_rport = list_entry(node, struct unf_rport, entry_rport); - FC_DRV_PRINT(UNF_LOG_NORMAL, UNF_MAJOR, - "[info]Vport(0x%x) Rport(0x%x) point(%p) is in Delete", - vport->port_id, unf_rport->nport_id, unf_rport); - vport_uses++; - } - - list_for_each_safe(node, next_node, &disc->list_destroy_rports) { - unf_rport = list_entry(node, struct unf_rport, entry_rport); - FC_DRV_PRINT(UNF_LOG_NORMAL, UNF_MAJOR, - "[info]Vport(0x%x) Rport(0x%x) point(%p) is in Destroy", - vport->port_id, unf_rport->nport_id, unf_rport); - vport_uses++; - } - spin_unlock_irqrestore(&disc->rport_busy_pool_lock, flags); - - if (vport_uses == 0) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_MAJOR, - "[info]VPort(0x%x) has removed all RPorts it used", - vport->port_id); - break; - } - - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Vport(0x%x) has %u RPorts not removed wait timeout(%u ms)", - vport->port_id, vport_uses, wait_timeout); - - if (wait_timeout >= UNF_DELETE_VPORT_MAX_WAIT_TIME_MS) - return RETURN_ERROR; - - msleep(UNF_WAIT_RPORT_REMOVE_ONE_TIME_MS); - wait_timeout += UNF_WAIT_RPORT_REMOVE_ONE_TIME_MS; - } - - return RETURN_OK; -} - -u32 unf_destroy_one_vport(struct unf_lport *vport) -{ - u32 ret; - struct unf_lport *root_port = NULL; - - FC_CHECK_RETURN_VALUE(vport, RETURN_ERROR); - - root_port = (struct unf_lport *)vport->root_lport; - - unf_vport_fabric_logo(vport); - - /* 1 set NOP */ - atomic_set(&vport->lport_no_operate_flag, UNF_LPORT_NOP); - vport->port_removing = true; - - /* 2 report linkdown to scsi and delele rpot */ - unf_linkdown_one_vport(vport); - - /* 3 set abort for exchange */ - unf_vport_abort_exch(vport); - - /* 4 wait exch return freepool */ - if (!root_port->port_dirt_exchange) { - ret = unf_vport_wait_all_exch_removed(vport); - if (ret != RETURN_OK) { - if (!root_port->port_removing) { - vport->port_removing = false; - FC_DRV_PRINT(UNF_LOG_NORMAL, UNF_ERR, - "[err]VPort(0x%x) can not wait Exchange return freepool", - vport->port_id); - - return RETURN_ERROR; - } - - FC_DRV_PRINT(UNF_LOG_NORMAL, UNF_WARN, - "[warn]Port(0x%x) is removing, there is dirty exchange, continue", - root_port->port_id); - - root_port->port_dirt_exchange = true; - } - } - - /* wait rport return rportpool */ - ret = unf_vport_wait_rports_removed(vport); - if (ret != RETURN_OK) { - vport->port_removing = false; - FC_DRV_PRINT(UNF_LOG_NORMAL, UNF_ERR, - "[err]VPort(0x%x) can not wait Rport return freepool", - vport->port_id); - - return RETURN_ERROR; - } - - unf_cm_vport_remove(vport); - - return RETURN_OK; -} - -void unf_destroy_all_vports(struct unf_lport *lport) -{ - struct unf_vport_pool *vport_pool = NULL; - struct unf_lport *unf_lport = NULL; - struct unf_lport *vport = NULL; - struct list_head *node = NULL; - struct list_head *next_node = NULL; - ulong flags = 0; - - unf_lport = lport; - FC_CHECK_RETURN_VOID(unf_lport); - - vport_pool = unf_lport->vport_pool; - if (unlikely(!vport_pool)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[err]Lport(0x%x) VPort pool is NULL", unf_lport->port_id); - - return; - } - - /* Transfer to the transition chain */ - spin_lock_irqsave(&vport_pool->vport_pool_lock, flags); - list_for_each_safe(node, next_node, &unf_lport->list_vports_head) { - vport = list_entry(node, struct unf_lport, entry_vport); - list_del_init(&vport->entry_vport); - list_add_tail(&vport->entry_vport, &unf_lport->list_destroy_vports); - } - - list_for_each_safe(node, next_node, &unf_lport->list_intergrad_vports) { - vport = list_entry(node, struct unf_lport, entry_vport); - list_del_init(&vport->entry_vport); - list_add_tail(&vport->entry_vport, &unf_lport->list_destroy_vports); - atomic_dec(&vport->port_ref_cnt); - } - spin_unlock_irqrestore(&vport_pool->vport_pool_lock, flags); - - spin_lock_irqsave(&vport_pool->vport_pool_lock, flags); - while (!list_empty(&unf_lport->list_destroy_vports)) { - node = UNF_OS_LIST_NEXT(&unf_lport->list_destroy_vports); - vport = list_entry(node, struct unf_lport, entry_vport); - - list_del_init(&vport->entry_vport); - list_add_tail(&vport->entry_vport, &unf_lport->list_vports_head); - spin_unlock_irqrestore(&vport_pool->vport_pool_lock, flags); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]VPort(0x%x) Destroy begin", vport->port_id); - unf_drop_vport(vport); - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_KEVENT, - "[info]VPort(0x%x) Destroy end", vport->port_id); - - spin_lock_irqsave(&vport_pool->vport_pool_lock, flags); - } - spin_unlock_irqrestore(&vport_pool->vport_pool_lock, flags); -} - -u32 unf_init_vport_mgr_temp(struct unf_lport *lport) -{ - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - lport->lport_mgr_temp.unf_look_up_vport_by_index = unf_lookup_vport_by_index; - lport->lport_mgr_temp.unf_look_up_vport_by_port_id = unf_lookup_vport_by_portid; - lport->lport_mgr_temp.unf_look_up_vport_by_did = unf_lookup_vport_by_did; - lport->lport_mgr_temp.unf_look_up_vport_by_wwpn = unf_lookup_vport_by_wwpn; - lport->lport_mgr_temp.unf_vport_remove = unf_vport_remove; - - return RETURN_OK; -} - -void unf_release_vport_mgr_temp(struct unf_lport *lport) -{ - FC_CHECK_RETURN_VOID(lport); - - memset(&lport->lport_mgr_temp, 0, sizeof(struct unf_cm_lport_template)); - - lport->destroy_step = UNF_LPORT_DESTROY_STEP_9_DESTROY_LPORT_MG_TMP; -} diff --git a/drivers/scsi/spfc/common/unf_npiv.h b/drivers/scsi/spfc/common/unf_npiv.h deleted file mode 100644 index 6f522470f47a..000000000000 --- a/drivers/scsi/spfc/common/unf_npiv.h +++ /dev/null @@ -1,47 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef UNF_NPIV_H -#define UNF_NPIV_H - -#include "unf_type.h" -#include "unf_common.h" -#include "unf_lport.h" - -/* product VPORT configure */ -struct vport_config { - u64 node_name; - u64 port_name; - u32 port_mode; /* INI, TGT or both */ -}; - -/* product Vport function */ -#define PORTID_VPINDEX_MASK 0xff000000 -#define PORTID_VPINDEX_SHIT 24 -u32 unf_npiv_conf(u32 port_id, u64 wwpn, enum unf_rport_qos_level qos_level); -struct unf_lport *unf_creat_vport(struct unf_lport *lport, - struct vport_config *vport_config); -u32 unf_delete_vport(u32 port_id, u32 vp_index); - -/* Vport pool creat and release function */ -u32 unf_init_vport_pool(struct unf_lport *lport); -void unf_free_vport_pool(struct unf_lport *lport); - -/* Lport resigster stLPortMgTemp function */ -void unf_vport_remove(void *vport); -void unf_vport_ref_dec(struct unf_lport *vport); - -/* linkdown all Vport after receive linkdown event */ -void unf_linkdown_all_vports(void *lport); -/* Lport receive Flogi Acc linkup all Vport */ -void unf_linkup_all_vports(struct unf_lport *lport); -/* Lport remove delete all Vport */ -void unf_destroy_all_vports(struct unf_lport *lport); -void unf_vport_fabric_logo(struct unf_lport *vport); -u32 unf_destroy_one_vport(struct unf_lport *vport); -u32 unf_drop_vport(struct unf_lport *vport); -u32 unf_init_vport_mgr_temp(struct unf_lport *lport); -void unf_release_vport_mgr_temp(struct unf_lport *lport); -struct unf_lport *unf_get_vport_by_slab_index(struct unf_vport_pool *vport_pool, - u16 slab_index); -#endif diff --git a/drivers/scsi/spfc/common/unf_npiv_portman.c b/drivers/scsi/spfc/common/unf_npiv_portman.c deleted file mode 100644 index b4f393f2e732..000000000000 --- a/drivers/scsi/spfc/common/unf_npiv_portman.c +++ /dev/null @@ -1,360 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#include "unf_npiv_portman.h" -#include "unf_log.h" -#include "unf_common.h" -#include "unf_rport.h" -#include "unf_npiv.h" -#include "unf_portman.h" - -void *unf_lookup_vport_by_index(void *lport, u16 vp_index) -{ - struct unf_lport *unf_lport = NULL; - struct unf_vport_pool *vport_pool = NULL; - struct unf_lport *unf_vport = NULL; - ulong flags = 0; - - FC_CHECK_RETURN_VALUE(lport, NULL); - - unf_lport = (struct unf_lport *)lport; - - vport_pool = unf_lport->vport_pool; - if (unlikely(!vport_pool)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x) vport pool is NULL", unf_lport->port_id); - - return NULL; - } - - if (vp_index == 0 || vp_index > vport_pool->slab_total_sum) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[err]Port(0x%x) input vport index(0x%x) is beyond the normal range(0x1~0x%x)", - unf_lport->port_id, vp_index, vport_pool->slab_total_sum); - - return NULL; - } - - spin_lock_irqsave(&vport_pool->vport_pool_lock, flags); - unf_vport = unf_get_vport_by_slab_index(vport_pool, vp_index - 1); - spin_unlock_irqrestore(&vport_pool->vport_pool_lock, flags); - - return (void *)unf_vport; -} - -void *unf_lookup_vport_by_portid(void *lport, u32 port_id) -{ - struct unf_lport *unf_lport = NULL; - struct unf_vport_pool *vport_pool = NULL; - struct unf_lport *unf_vport = NULL; - struct list_head *node = NULL; - struct list_head *next_node = NULL; - ulong flag = 0; - - FC_CHECK_RETURN_VALUE(lport, NULL); - - unf_lport = (struct unf_lport *)lport; - vport_pool = unf_lport->vport_pool; - if (unlikely(!vport_pool)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x) vport pool is NULL", unf_lport->port_id); - - return NULL; - } - - spin_lock_irqsave(&vport_pool->vport_pool_lock, flag); - list_for_each_safe(node, next_node, &unf_lport->list_vports_head) { - unf_vport = list_entry(node, struct unf_lport, entry_vport); - if (unf_vport->port_id == port_id) { - spin_unlock_irqrestore(&vport_pool->vport_pool_lock, flag); - return unf_vport; - } - } - - list_for_each_safe(node, next_node, &unf_lport->list_intergrad_vports) { - unf_vport = list_entry(node, struct unf_lport, entry_vport); - if (unf_vport->port_id == port_id) { - spin_unlock_irqrestore(&vport_pool->vport_pool_lock, flag); - return unf_vport; - } - } - spin_unlock_irqrestore(&vport_pool->vport_pool_lock, flag); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) has no vport ID(0x%x).", - unf_lport->port_id, port_id); - return NULL; -} - -void *unf_lookup_vport_by_did(void *lport, u32 did) -{ - struct unf_lport *unf_lport = NULL; - struct unf_vport_pool *vport_pool = NULL; - struct unf_lport *unf_vport = NULL; - struct list_head *node = NULL; - struct list_head *next_node = NULL; - ulong flag = 0; - - FC_CHECK_RETURN_VALUE(lport, NULL); - - unf_lport = (struct unf_lport *)lport; - vport_pool = unf_lport->vport_pool; - if (unlikely(!vport_pool)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x) vport pool is NULL", unf_lport->port_id); - - return NULL; - } - - spin_lock_irqsave(&vport_pool->vport_pool_lock, flag); - list_for_each_safe(node, next_node, &unf_lport->list_vports_head) { - unf_vport = list_entry(node, struct unf_lport, entry_vport); - if (unf_vport->nport_id == did) { - spin_unlock_irqrestore(&vport_pool->vport_pool_lock, flag); - - return unf_vport; - } - } - - list_for_each_safe(node, next_node, &unf_lport->list_intergrad_vports) { - unf_vport = list_entry(node, struct unf_lport, entry_vport); - if (unf_vport->nport_id == did) { - spin_unlock_irqrestore(&vport_pool->vport_pool_lock, flag); - return unf_vport; - } - } - spin_unlock_irqrestore(&vport_pool->vport_pool_lock, flag); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) has no vport Nport ID(0x%x)", unf_lport->port_id, did); - return NULL; -} - -void *unf_lookup_vport_by_wwpn(void *lport, u64 wwpn) -{ - struct unf_lport *unf_lport = NULL; - struct unf_vport_pool *vport_pool = NULL; - struct unf_lport *unf_vport = NULL; - struct list_head *node = NULL; - struct list_head *next_node = NULL; - ulong flag = 0; - - FC_CHECK_RETURN_VALUE(lport, NULL); - - unf_lport = (struct unf_lport *)lport; - vport_pool = unf_lport->vport_pool; - if (unlikely(!vport_pool)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x) vport pool is NULL", unf_lport->port_id); - - return NULL; - } - - spin_lock_irqsave(&vport_pool->vport_pool_lock, flag); - list_for_each_safe(node, next_node, &unf_lport->list_vports_head) { - unf_vport = list_entry(node, struct unf_lport, entry_vport); - if (unf_vport->port_name == wwpn) { - spin_unlock_irqrestore(&vport_pool->vport_pool_lock, flag); - - return unf_vport; - } - } - - list_for_each_safe(node, next_node, &unf_lport->list_intergrad_vports) { - unf_vport = list_entry(node, struct unf_lport, entry_vport); - if (unf_vport->port_name == wwpn) { - spin_unlock_irqrestore(&vport_pool->vport_pool_lock, flag); - return unf_vport; - } - } - spin_unlock_irqrestore(&vport_pool->vport_pool_lock, flag); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x) has no vport WWPN(0x%llx)", - unf_lport->port_id, wwpn); - - return NULL; -} - -void unf_linkdown_one_vport(struct unf_lport *vport) -{ - ulong flag = 0; - struct unf_lport *root_lport = NULL; - - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_KEVENT, - "[info]VPort(0x%x) linkdown", vport->port_id); - - spin_lock_irqsave(&vport->lport_state_lock, flag); - vport->link_up = UNF_PORT_LINK_DOWN; - vport->nport_id = 0; /* set nportid 0 before send fdisc again */ - unf_lport_state_ma(vport, UNF_EVENT_LPORT_LINK_DOWN); - spin_unlock_irqrestore(&vport->lport_state_lock, flag); - - root_lport = (struct unf_lport *)vport->root_lport; - - unf_flush_disc_event(&root_lport->disc, vport); - - unf_clean_linkdown_rport(vport); -} - -void unf_linkdown_all_vports(void *lport) -{ - struct unf_lport *unf_lport = NULL; - struct unf_vport_pool *vport_pool = NULL; - struct unf_lport *unf_vport = NULL; - struct list_head *node = NULL; - struct list_head *next_node = NULL; - ulong flags = 0; - - FC_CHECK_RETURN_VOID(lport); - - unf_lport = (struct unf_lport *)lport; - vport_pool = unf_lport->vport_pool; - if (unlikely(!vport_pool)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[err]Port(0x%x) VPort pool is NULL", unf_lport->port_id); - - return; - } - - /* Transfer to the transition chain */ - spin_lock_irqsave(&vport_pool->vport_pool_lock, flags); - list_for_each_safe(node, next_node, &unf_lport->list_vports_head) { - unf_vport = list_entry(node, struct unf_lport, entry_vport); - list_del_init(&unf_vport->entry_vport); - list_add_tail(&unf_vport->entry_vport, &unf_lport->list_intergrad_vports); - (void)unf_lport_ref_inc(unf_vport); - } - spin_unlock_irqrestore(&vport_pool->vport_pool_lock, flags); - - spin_lock_irqsave(&vport_pool->vport_pool_lock, flags); - while (!list_empty(&unf_lport->list_intergrad_vports)) { - node = UNF_OS_LIST_NEXT(&unf_lport->list_intergrad_vports); - unf_vport = list_entry(node, struct unf_lport, entry_vport); - - list_del_init(&unf_vport->entry_vport); - list_add_tail(&unf_vport->entry_vport, &unf_lport->list_vports_head); - spin_unlock_irqrestore(&vport_pool->vport_pool_lock, flags); - - unf_linkdown_one_vport(unf_vport); - - unf_vport_ref_dec(unf_vport); - - spin_lock_irqsave(&vport_pool->vport_pool_lock, flags); - } - spin_unlock_irqrestore(&vport_pool->vport_pool_lock, flags); -} - -int unf_process_vports_linkup(void *arg_in, void *arg_out) -{ -#define UNF_WAIT_VPORT_LOGIN_ONE_TIME_MS 100 - struct unf_vport_pool *vport_pool = NULL; - struct unf_lport *unf_lport = NULL; - struct unf_lport *unf_vport = NULL; - struct list_head *node = NULL; - struct list_head *next_node = NULL; - ulong flags = 0; - int ret = RETURN_OK; - - FC_CHECK_RETURN_VALUE(arg_in, RETURN_ERROR); - - unf_lport = (struct unf_lport *)arg_in; - - if (atomic_read(&unf_lport->lport_no_operate_flag) == UNF_LPORT_NOP) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) is NOP don't continue", unf_lport->port_id); - - return RETURN_OK; - } - - if (unf_lport->link_up != UNF_PORT_LINK_UP) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) is not linkup don't continue.", - unf_lport->port_id); - - return RETURN_OK; - } - - vport_pool = unf_lport->vport_pool; - if (unlikely(!vport_pool)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[err]Port(0x%x) VPort pool is NULL.", unf_lport->port_id); - - return RETURN_OK; - } - - /* Transfer to the transition chain */ - spin_lock_irqsave(&vport_pool->vport_pool_lock, flags); - list_for_each_safe(node, next_node, &unf_lport->list_vports_head) { - unf_vport = list_entry(node, struct unf_lport, entry_vport); - list_del_init(&unf_vport->entry_vport); - list_add_tail(&unf_vport->entry_vport, &unf_lport->list_intergrad_vports); - (void)unf_lport_ref_inc(unf_vport); - } - spin_unlock_irqrestore(&vport_pool->vport_pool_lock, flags); - - spin_lock_irqsave(&vport_pool->vport_pool_lock, flags); - while (!list_empty(&unf_lport->list_intergrad_vports)) { - node = UNF_OS_LIST_NEXT(&unf_lport->list_intergrad_vports); - unf_vport = list_entry(node, struct unf_lport, entry_vport); - - list_del_init(&unf_vport->entry_vport); - list_add_tail(&unf_vport->entry_vport, &unf_lport->list_vports_head); - spin_unlock_irqrestore(&vport_pool->vport_pool_lock, flags); - - if (atomic_read(&unf_vport->lport_no_operate_flag) == UNF_LPORT_NOP) { - unf_vport_ref_dec(unf_vport); - spin_lock_irqsave(&vport_pool->vport_pool_lock, flags); - continue; - } - - if (unf_lport->link_up == UNF_PORT_LINK_UP && - unf_lport->act_topo == UNF_ACT_TOP_P2P_FABRIC) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_MAJOR, - "[info]Vport(0x%x) begin login", unf_vport->port_id); - - unf_vport->link_up = UNF_PORT_LINK_UP; - (void)unf_lport_login(unf_vport, unf_lport->act_topo); - - msleep(UNF_WAIT_VPORT_LOGIN_ONE_TIME_MS); - } else { - unf_linkdown_one_vport(unf_vport); - - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Vport(0x%x) login failed because root port linkdown", - unf_vport->port_id); - } - - unf_vport_ref_dec(unf_vport); - spin_lock_irqsave(&vport_pool->vport_pool_lock, flags); - } - spin_unlock_irqrestore(&vport_pool->vport_pool_lock, flags); - - return ret; -} - -void unf_linkup_all_vports(struct unf_lport *lport) -{ - struct unf_cm_event_report *event = NULL; - - FC_CHECK_RETURN_VOID(lport); - - if (unlikely(!lport->event_mgr.unf_get_free_event_func || - !lport->event_mgr.unf_post_event_func || - !lport->event_mgr.unf_release_event)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) Event fun is NULL", - lport->port_id); - return; - } - - event = lport->event_mgr.unf_get_free_event_func((void *)lport); - FC_CHECK_RETURN_VOID(event); - - event->lport = lport; - event->event_asy_flag = UNF_EVENT_ASYN; - event->unf_event_task = unf_process_vports_linkup; - event->para_in = (void *)lport; - - lport->event_mgr.unf_post_event_func(lport, event); -} diff --git a/drivers/scsi/spfc/common/unf_npiv_portman.h b/drivers/scsi/spfc/common/unf_npiv_portman.h deleted file mode 100644 index 284c23c9abe4..000000000000 --- a/drivers/scsi/spfc/common/unf_npiv_portman.h +++ /dev/null @@ -1,17 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef UNF_NPIV_PORTMAN_H -#define UNF_NPIV_PORTMAN_H - -#include "unf_type.h" -#include "unf_lport.h" - -/* Lport resigster stLPortMgTemp function */ -void *unf_lookup_vport_by_index(void *lport, u16 vp_index); -void *unf_lookup_vport_by_portid(void *lport, u32 port_id); -void *unf_lookup_vport_by_did(void *lport, u32 did); -void *unf_lookup_vport_by_wwpn(void *lport, u64 wwpn); -void unf_linkdown_one_vport(struct unf_lport *vport); - -#endif diff --git a/drivers/scsi/spfc/common/unf_portman.c b/drivers/scsi/spfc/common/unf_portman.c deleted file mode 100644 index ef8f90eb3777..000000000000 --- a/drivers/scsi/spfc/common/unf_portman.c +++ /dev/null @@ -1,2431 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#include "unf_portman.h" -#include "unf_log.h" -#include "unf_exchg.h" -#include "unf_rport.h" -#include "unf_io.h" -#include "unf_npiv.h" -#include "unf_scsi_common.h" - -#define UNF_LPORT_CHIP_ERROR(unf_lport) \ - ((unf_lport)->pcie_error_cnt.pcie_error_count[UNF_PCIE_FATALERRORDETECTED]) - -struct unf_global_lport global_lport_mgr; - -static int unf_port_switch(struct unf_lport *lport, bool switch_flag); -static u32 unf_build_lport_wwn(struct unf_lport *lport); -static int unf_lport_destroy(void *lport, void *arg_out); -static u32 unf_port_linkup(struct unf_lport *lport, void *input); -static u32 unf_port_linkdown(struct unf_lport *lport, void *input); -static u32 unf_port_abnormal_reset(struct unf_lport *lport, void *input); -static u32 unf_port_reset_start(struct unf_lport *lport, void *input); -static u32 unf_port_reset_end(struct unf_lport *lport, void *input); -static u32 unf_port_nop(struct unf_lport *lport, void *input); -static void unf_destroy_card_thread(struct unf_lport *lport); -static u32 unf_creat_card_thread(struct unf_lport *lport); -static u32 unf_find_card_thread(struct unf_lport *lport); -static u32 unf_port_begin_remove(struct unf_lport *lport, void *input); - -static struct unf_port_action g_lport_action[] = { - {UNF_PORT_LINK_UP, unf_port_linkup}, - {UNF_PORT_LINK_DOWN, unf_port_linkdown}, - {UNF_PORT_RESET_START, unf_port_reset_start}, - {UNF_PORT_RESET_END, unf_port_reset_end}, - {UNF_PORT_NOP, unf_port_nop}, - {UNF_PORT_BEGIN_REMOVE, unf_port_begin_remove}, - {UNF_PORT_RELEASE_RPORT_INDEX, unf_port_release_rport_index}, - {UNF_PORT_ABNORMAL_RESET, unf_port_abnormal_reset}, -}; - -static void unf_destroy_dirty_rport(struct unf_lport *lport, bool show_only) -{ - u32 dirty_rport = 0; - - /* for whole L_Port */ - if (lport->dirty_flag & UNF_LPORT_DIRTY_FLAG_RPORT_POOL_DIRTY) { - dirty_rport = lport->rport_pool.rport_pool_count; - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]Port(0x%x) has %d dirty RPort(s)", - lport->port_id, dirty_rport); - - /* Show L_Port's R_Port(s) from busy_list & destroy_list */ - unf_show_all_rport(lport); - - /* free R_Port pool memory & bitmap */ - if (!show_only) { - vfree(lport->rport_pool.rport_pool_add); - lport->rport_pool.rport_pool_add = NULL; - vfree(lport->rport_pool.rpi_bitmap); - lport->rport_pool.rpi_bitmap = NULL; - } - } -} - -void unf_show_dirty_port(bool show_only, u32 *dirty_port_num) -{ - struct list_head *node = NULL; - struct list_head *node_next = NULL; - struct unf_lport *unf_lport = NULL; - ulong flags = 0; - u32 port_num = 0; - - FC_CHECK_RETURN_VOID(dirty_port_num); - - /* for each dirty L_Port from global L_Port list */ - spin_lock_irqsave(&global_lport_mgr.global_lport_list_lock, flags); - list_for_each_safe(node, node_next, &global_lport_mgr.dirty_list_head) { - unf_lport = list_entry(node, struct unf_lport, entry_lport); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]Port(0x%x) has dirty data(0x%x)", - unf_lport->port_id, unf_lport->dirty_flag); - - /* Destroy dirty L_Port's exchange(s) & R_Port(s) */ - unf_destroy_dirty_xchg(unf_lport, show_only); - unf_destroy_dirty_rport(unf_lport, show_only); - - /* Delete (dirty L_Port) list entry if necessary */ - if (!show_only) { - list_del_init(node); - vfree(unf_lport); - } - - port_num++; - } - spin_unlock_irqrestore(&global_lport_mgr.global_lport_list_lock, flags); - - *dirty_port_num = port_num; -} - -void unf_show_all_rport(struct unf_lport *lport) -{ - struct unf_lport *unf_lport = NULL; - struct unf_rport *unf_rport = NULL; - struct unf_disc *disc = NULL; - struct list_head *node = NULL; - struct list_head *next_node = NULL; - ulong flag = 0; - u32 rport_cnt = 0; - u32 target_cnt = 0; - - FC_CHECK_RETURN_VOID(lport); - - unf_lport = lport; - disc = &unf_lport->disc; - - spin_lock_irqsave(&disc->rport_busy_pool_lock, flag); - - FC_DRV_PRINT(UNF_LOG_NORMAL, UNF_MAJOR, - "[info]Port(0x%x) disc state(0x%x)", unf_lport->port_id, disc->states); - - /* for each R_Port from busy_list */ - list_for_each_safe(node, next_node, &disc->list_busy_rports) { - unf_rport = list_entry(node, struct unf_rport, entry_rport); - rport_cnt++; - - FC_DRV_PRINT(UNF_LOG_NORMAL, UNF_MAJOR, - "[info]Port(0x%x) busy RPorts(%u_%p) WWPN(0x%016llx) scsi_id(0x%x) local N_Port_ID(0x%x) N_Port_ID(0x%06x). State(0x%04x) options(0x%04x) index(0x%04x) ref(%d) pend:%d", - unf_lport->port_id, rport_cnt, unf_rport, - unf_rport->port_name, unf_rport->scsi_id, - unf_rport->local_nport_id, unf_rport->nport_id, - unf_rport->rp_state, unf_rport->options, - unf_rport->rport_index, - atomic_read(&unf_rport->rport_ref_cnt), - atomic_read(&unf_rport->pending_io_cnt)); - - if (unf_rport->nport_id < UNF_FC_FID_DOM_MGR) - target_cnt++; - } - - unf_lport->target_cnt = target_cnt; - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]Port(0x%x) targetnum=(%u)", unf_lport->port_id, - unf_lport->target_cnt); - - /* for each R_Port from destroy_list */ - list_for_each_safe(node, next_node, &disc->list_destroy_rports) { - unf_rport = list_entry(node, struct unf_rport, entry_rport); - rport_cnt++; - - FC_DRV_PRINT(UNF_LOG_NORMAL, UNF_MAJOR, - "[info]Port(0x%x) destroy RPorts(%u) WWPN(0x%016llx) N_Port_ID(0x%06x) State(0x%04x) options(0x%04x) index(0x%04x) ref(%d)", - unf_lport->port_id, rport_cnt, unf_rport->port_name, - unf_rport->nport_id, unf_rport->rp_state, - unf_rport->options, unf_rport->rport_index, - atomic_read(&unf_rport->rport_ref_cnt)); - } - - spin_unlock_irqrestore(&disc->rport_busy_pool_lock, flag); -} - -u32 unf_lport_ref_inc(struct unf_lport *lport) -{ - ulong lport_flags = 0; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - - spin_lock_irqsave(&lport->lport_state_lock, lport_flags); - if (atomic_read(&lport->port_ref_cnt) <= 0) { - spin_unlock_irqrestore(&lport->lport_state_lock, lport_flags); - - return UNF_RETURN_ERROR; - } - - atomic_inc(&lport->port_ref_cnt); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "[info]Port(0x%p) port_id(0x%x) reference count is %d", - lport, lport->port_id, atomic_read(&lport->port_ref_cnt)); - - spin_unlock_irqrestore(&lport->lport_state_lock, lport_flags); - - return RETURN_OK; -} - -void unf_lport_ref_dec(struct unf_lport *lport) -{ - ulong flags = 0; - ulong lport_flags = 0; - - FC_CHECK_RETURN_VOID(lport); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "LPort(0x%p), port ID(0x%x), reference count is %d.", - lport, lport->port_id, atomic_read(&lport->port_ref_cnt)); - - spin_lock_irqsave(&global_lport_mgr.global_lport_list_lock, flags); - spin_lock_irqsave(&lport->lport_state_lock, lport_flags); - if (atomic_dec_and_test(&lport->port_ref_cnt)) { - spin_unlock_irqrestore(&lport->lport_state_lock, lport_flags); - list_del(&lport->entry_lport); - global_lport_mgr.lport_sum--; - - /* attaches the lport to the destroy linked list for dfx */ - list_add_tail(&lport->entry_lport, &global_lport_mgr.destroy_list_head); - spin_unlock_irqrestore(&global_lport_mgr.global_lport_list_lock, flags); - - (void)unf_lport_destroy(lport, NULL); - } else { - spin_unlock_irqrestore(&lport->lport_state_lock, lport_flags); - spin_unlock_irqrestore(&global_lport_mgr.global_lport_list_lock, flags); - } -} - -void unf_lport_update_topo(struct unf_lport *lport, - enum unf_act_topo active_topo) -{ - ulong flag = 0; - - FC_CHECK_RETURN_VOID(lport); - - if (active_topo > UNF_ACT_TOP_UNKNOWN || active_topo < UNF_ACT_TOP_PUBLIC_LOOP) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) set invalid topology(0x%x) with current value(0x%x)", - lport->nport_id, active_topo, lport->act_topo); - - return; - } - - spin_lock_irqsave(&lport->lport_state_lock, flag); - lport->act_topo = active_topo; - spin_unlock_irqrestore(&lport->lport_state_lock, flag); -} - -void unf_set_lport_removing(struct unf_lport *lport) -{ - FC_CHECK_RETURN_VOID(lport); - - lport->fc_port = NULL; - lport->port_removing = true; - lport->destroy_step = UNF_LPORT_DESTROY_STEP_0_SET_REMOVING; -} - -u32 unf_release_local_port(void *lport) -{ - struct unf_lport *unf_lport = lport; - struct completion lport_free_completion; - - init_completion(&lport_free_completion); - FC_CHECK_RETURN_VALUE(unf_lport, UNF_RETURN_ERROR); - - unf_lport->lport_free_completion = &lport_free_completion; - unf_set_lport_removing(unf_lport); - unf_lport_ref_dec(unf_lport); - wait_for_completion(unf_lport->lport_free_completion); - /* for dirty case */ - if (unf_lport->dirty_flag == 0) - vfree(unf_lport); - - return RETURN_OK; -} - -static void unf_free_all_esgl_pages(struct unf_lport *lport) -{ - struct list_head *node = NULL; - struct list_head *next_node = NULL; - ulong flag = 0; - u32 i; - - FC_CHECK_RETURN_VOID(lport); - spin_lock_irqsave(&lport->esgl_pool.esgl_pool_lock, flag); - list_for_each_safe(node, next_node, &lport->esgl_pool.list_esgl_pool) { - list_del(node); - } - - spin_unlock_irqrestore(&lport->esgl_pool.esgl_pool_lock, flag); - if (lport->esgl_pool.esgl_buff_list.buflist) { - for (i = 0; i < lport->esgl_pool.esgl_buff_list.buf_num; i++) { - if (lport->esgl_pool.esgl_buff_list.buflist[i].vaddr) { - dma_free_coherent(&lport->low_level_func.dev->dev, - lport->esgl_pool.esgl_buff_list.buf_size, - lport->esgl_pool.esgl_buff_list.buflist[i].vaddr, - lport->esgl_pool.esgl_buff_list.buflist[i].paddr); - lport->esgl_pool.esgl_buff_list.buflist[i].vaddr = NULL; - } - } - kfree(lport->esgl_pool.esgl_buff_list.buflist); - lport->esgl_pool.esgl_buff_list.buflist = NULL; - } -} - -static u32 unf_init_esgl_pool(struct unf_lport *lport) -{ - struct unf_esgl *esgl = NULL; - u32 ret = RETURN_OK; - u32 index = 0; - u32 buf_total_size; - u32 buf_num; - u32 alloc_idx; - u32 curbuf_idx = 0; - u32 curbuf_offset = 0; - u32 buf_cnt_perhugebuf; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - - lport->esgl_pool.esgl_pool_count = lport->low_level_func.lport_cfg_items.max_io; - spin_lock_init(&lport->esgl_pool.esgl_pool_lock); - INIT_LIST_HEAD(&lport->esgl_pool.list_esgl_pool); - - lport->esgl_pool.esgl_pool_addr = - vmalloc((size_t)((lport->esgl_pool.esgl_pool_count) * sizeof(struct unf_esgl))); - if (!lport->esgl_pool.esgl_pool_addr) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "LPort(0x%x) cannot allocate ESGL Pool.", lport->port_id); - - return UNF_RETURN_ERROR; - } - esgl = (struct unf_esgl *)lport->esgl_pool.esgl_pool_addr; - memset(esgl, 0, ((lport->esgl_pool.esgl_pool_count) * sizeof(struct unf_esgl))); - - buf_total_size = (u32)(PAGE_SIZE * lport->esgl_pool.esgl_pool_count); - - lport->esgl_pool.esgl_buff_list.buf_size = - buf_total_size > BUF_LIST_PAGE_SIZE ? BUF_LIST_PAGE_SIZE : buf_total_size; - buf_cnt_perhugebuf = lport->esgl_pool.esgl_buff_list.buf_size / PAGE_SIZE; - buf_num = lport->esgl_pool.esgl_pool_count % buf_cnt_perhugebuf - ? lport->esgl_pool.esgl_pool_count / buf_cnt_perhugebuf + 1 - : lport->esgl_pool.esgl_pool_count / buf_cnt_perhugebuf; - lport->esgl_pool.esgl_buff_list.buflist = - (struct buff_list *)kmalloc(buf_num * sizeof(struct buff_list), GFP_KERNEL); - lport->esgl_pool.esgl_buff_list.buf_num = buf_num; - - if (!lport->esgl_pool.esgl_buff_list.buflist) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[err]Allocate Esgl pool buf list failed out of memory"); - goto free_buff; - } - memset(lport->esgl_pool.esgl_buff_list.buflist, 0, buf_num * sizeof(struct buff_list)); - - for (alloc_idx = 0; alloc_idx < buf_num; alloc_idx++) { - lport->esgl_pool.esgl_buff_list.buflist[alloc_idx] - .vaddr = dma_alloc_coherent(&lport->low_level_func.dev->dev, - lport->esgl_pool.esgl_buff_list.buf_size, - &lport->esgl_pool.esgl_buff_list.buflist[alloc_idx].paddr, GFP_KERNEL); - if (!lport->esgl_pool.esgl_buff_list.buflist[alloc_idx].vaddr) - goto free_buff; - memset(lport->esgl_pool.esgl_buff_list.buflist[alloc_idx].vaddr, 0, - lport->esgl_pool.esgl_buff_list.buf_size); - } - - /* allocates the Esgl page, and the DMA uses the */ - for (index = 0; index < lport->esgl_pool.esgl_pool_count; index++) { - if (index != 0 && !(index % buf_cnt_perhugebuf)) - curbuf_idx++; - curbuf_offset = (u32)(PAGE_SIZE * (index % buf_cnt_perhugebuf)); - esgl->page.page_address = - (u64)lport->esgl_pool.esgl_buff_list.buflist[curbuf_idx].vaddr + curbuf_offset; - esgl->page.page_size = PAGE_SIZE; - esgl->page.esgl_phy_addr = - lport->esgl_pool.esgl_buff_list.buflist[curbuf_idx].paddr + curbuf_offset; - list_add_tail(&esgl->entry_esgl, &lport->esgl_pool.list_esgl_pool); - esgl++; - } - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_INFO, - "[EVENT]Allocate bufnum:%u,buf_total_size:%u", buf_num, buf_total_size); - - return ret; -free_buff: - unf_free_all_esgl_pages(lport); - vfree(lport->esgl_pool.esgl_pool_addr); - - return UNF_RETURN_ERROR; -} - -static void unf_free_esgl_pool(struct unf_lport *lport) -{ - FC_CHECK_RETURN_VOID(lport); - - unf_free_all_esgl_pages(lport); - lport->esgl_pool.esgl_pool_count = 0; - - if (lport->esgl_pool.esgl_pool_addr) { - vfree(lport->esgl_pool.esgl_pool_addr); - lport->esgl_pool.esgl_pool_addr = NULL; - } - - lport->destroy_step = UNF_LPORT_DESTROY_STEP_5_DESTROY_ESGL_POOL; -} - -struct unf_lport *unf_find_lport_by_port_id(u32 port_id) -{ - struct unf_lport *unf_lport = NULL; - struct list_head *node = NULL; - struct list_head *next_node = NULL; - ulong flags = 0; - u32 portid = port_id & (~PORTID_VPINDEX_MASK); - u16 vport_index; - spinlock_t *lport_list_lock = NULL; - - lport_list_lock = &global_lport_mgr.global_lport_list_lock; - vport_index = (port_id & PORTID_VPINDEX_MASK) >> PORTID_VPINDEX_SHIT; - spin_lock_irqsave(lport_list_lock, flags); - - list_for_each_safe(node, next_node, &global_lport_mgr.lport_list_head) { - unf_lport = list_entry(node, struct unf_lport, entry_lport); - if (unf_lport->port_id == portid && !unf_lport->port_removing) { - spin_unlock_irqrestore(lport_list_lock, flags); - - return unf_cm_lookup_vport_by_vp_index(unf_lport, vport_index); - } - } - - list_for_each_safe(node, next_node, &global_lport_mgr.intergrad_head) { - unf_lport = list_entry(node, struct unf_lport, entry_lport); - if (unf_lport->port_id == portid && !unf_lport->port_removing) { - spin_unlock_irqrestore(lport_list_lock, flags); - - return unf_cm_lookup_vport_by_vp_index(unf_lport, vport_index); - } - } - - spin_unlock_irqrestore(lport_list_lock, flags); - - return NULL; -} - -u32 unf_is_vport_valid(struct unf_lport *lport, struct unf_lport *vport) -{ - struct unf_lport *unf_lport = NULL; - struct unf_vport_pool *vport_pool = NULL; - struct unf_lport *unf_vport = NULL; - struct list_head *node = NULL; - struct list_head *next_node = NULL; - ulong flag = 0; - spinlock_t *vport_pool_lock = NULL; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(vport, UNF_RETURN_ERROR); - - unf_lport = lport; - vport_pool = unf_lport->vport_pool; - if (unlikely(!vport_pool)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[err]Port(0x%x) vport pool is NULL", unf_lport->port_id); - - return UNF_RETURN_ERROR; - } - - vport_pool_lock = &vport_pool->vport_pool_lock; - spin_lock_irqsave(vport_pool_lock, flag); - list_for_each_safe(node, next_node, &unf_lport->list_vports_head) { - unf_vport = list_entry(node, struct unf_lport, entry_vport); - - if (unf_vport == vport && !unf_vport->port_removing) { - spin_unlock_irqrestore(vport_pool_lock, flag); - - return RETURN_OK; - } - } - - list_for_each_safe(node, next_node, &unf_lport->list_intergrad_vports) { - unf_vport = list_entry(node, struct unf_lport, entry_vport); - - if (unf_vport == vport && !unf_vport->port_removing) { - spin_unlock_irqrestore(vport_pool_lock, flag); - - return RETURN_OK; - } - } - spin_unlock_irqrestore(vport_pool_lock, flag); - - return UNF_RETURN_ERROR; -} - -u32 unf_is_lport_valid(struct unf_lport *lport) -{ - struct unf_lport *unf_lport = NULL; - struct list_head *node = NULL; - struct list_head *next_node = NULL; - ulong flags = 0; - spinlock_t *lport_list_lock = NULL; - - lport_list_lock = &global_lport_mgr.global_lport_list_lock; - spin_lock_irqsave(lport_list_lock, flags); - - list_for_each_safe(node, next_node, &global_lport_mgr.lport_list_head) { - unf_lport = list_entry(node, struct unf_lport, entry_lport); - - if (unf_lport == lport && !unf_lport->port_removing) { - spin_unlock_irqrestore(lport_list_lock, flags); - - return RETURN_OK; - } - - if (unf_is_vport_valid(unf_lport, lport) == RETURN_OK) { - spin_unlock_irqrestore(lport_list_lock, flags); - - return RETURN_OK; - } - } - - list_for_each_safe(node, next_node, &global_lport_mgr.intergrad_head) { - unf_lport = list_entry(node, struct unf_lport, entry_lport); - - if (unf_lport == lport && !unf_lport->port_removing) { - spin_unlock_irqrestore(lport_list_lock, flags); - - return RETURN_OK; - } - - if (unf_is_vport_valid(unf_lport, lport) == RETURN_OK) { - spin_unlock_irqrestore(lport_list_lock, flags); - - return RETURN_OK; - } - } - - list_for_each_safe(node, next_node, &global_lport_mgr.destroy_list_head) { - unf_lport = list_entry(node, struct unf_lport, entry_lport); - - if (unf_lport == lport && !unf_lport->port_removing) { - spin_unlock_irqrestore(lport_list_lock, flags); - - return RETURN_OK; - } - - if (unf_is_vport_valid(unf_lport, lport) == RETURN_OK) { - spin_unlock_irqrestore(lport_list_lock, flags); - - return RETURN_OK; - } - } - - spin_unlock_irqrestore(lport_list_lock, flags); - - return UNF_RETURN_ERROR; -} - -static void unf_clean_linkdown_io(struct unf_lport *lport, bool clean_flag) -{ - /* Clean L_Port/V_Port Link Down I/O: Set Abort Tag */ - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(lport->xchg_mgr_temp.unf_xchg_abort_all_io); - - lport->xchg_mgr_temp.unf_xchg_abort_all_io(lport, UNF_XCHG_TYPE_INI, clean_flag); - lport->xchg_mgr_temp.unf_xchg_abort_all_io(lport, UNF_XCHG_TYPE_SFS, clean_flag); -} - -u32 unf_fc_port_link_event(void *lport, u32 events, void *input) -{ - struct unf_lport *unf_lport = NULL; - u32 ret = UNF_RETURN_ERROR; - u32 index = 0; - - if (unlikely(!lport)) - return UNF_RETURN_ERROR; - unf_lport = (struct unf_lport *)lport; - - ret = unf_lport_ref_inc(unf_lport); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x) is removing and do nothing", - unf_lport->port_id); - - return RETURN_OK; - } - - /* process port event */ - while (index < (sizeof(g_lport_action) / sizeof(struct unf_port_action))) { - if (g_lport_action[index].action == events) { - ret = g_lport_action[index].unf_action(unf_lport, input); - - unf_lport_ref_dec_to_destroy(unf_lport); - - return ret; - } - index++; - } - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) receive unknown event(0x%x)", - unf_lport->port_id, events); - - unf_lport_ref_dec_to_destroy(unf_lport); - - return ret; -} - -void unf_port_mgmt_init(void) -{ - memset(&global_lport_mgr, 0, sizeof(struct unf_global_lport)); - - INIT_LIST_HEAD(&global_lport_mgr.lport_list_head); - - INIT_LIST_HEAD(&global_lport_mgr.intergrad_head); - - INIT_LIST_HEAD(&global_lport_mgr.destroy_list_head); - - INIT_LIST_HEAD(&global_lport_mgr.dirty_list_head); - - spin_lock_init(&global_lport_mgr.global_lport_list_lock); - - UNF_SET_NOMAL_MODE(global_lport_mgr.dft_mode); - - global_lport_mgr.start_work = true; -} - -void unf_port_mgmt_deinit(void) -{ - if (global_lport_mgr.lport_sum != 0) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[warn]There are %u port pool memory giveaway", - global_lport_mgr.lport_sum); - } - - memset(&global_lport_mgr, 0, sizeof(struct unf_global_lport)); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]Common port manager exit succeed"); -} - -static void unf_port_register(struct unf_lport *lport) -{ - ulong flags = 0; - - FC_CHECK_RETURN_VOID(lport); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_INFO, - "Register LPort(0x%p), port ID(0x%x).", lport, lport->port_id); - - /* Add to the global management linked list header */ - spin_lock_irqsave(&global_lport_mgr.global_lport_list_lock, flags); - list_add_tail(&lport->entry_lport, &global_lport_mgr.lport_list_head); - global_lport_mgr.lport_sum++; - spin_unlock_irqrestore(&global_lport_mgr.global_lport_list_lock, flags); -} - -static void unf_port_unregister(struct unf_lport *lport) -{ - ulong flags = 0; - - FC_CHECK_RETURN_VOID(lport); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_INFO, - "Unregister LPort(0x%p), port ID(0x%x).", lport, lport->port_id); - - /* Remove from the global management linked list header */ - spin_lock_irqsave(&global_lport_mgr.global_lport_list_lock, flags); - list_del(&lport->entry_lport); - global_lport_mgr.lport_sum--; - spin_unlock_irqrestore(&global_lport_mgr.global_lport_list_lock, flags); -} - -int unf_port_start_work(struct unf_lport *lport) -{ - ulong flag = 0; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - - spin_lock_irqsave(&lport->lport_state_lock, flag); - if (lport->start_work_state != UNF_START_WORK_STOP) { - spin_unlock_irqrestore(&lport->lport_state_lock, flag); - - return RETURN_OK; - } - lport->start_work_state = UNF_START_WORK_COMPLETE; - spin_unlock_irqrestore(&lport->lport_state_lock, flag); - - /* switch sfp to start work */ - (void)unf_port_switch(lport, true); - - return RETURN_OK; -} - -static u32 -unf_lport_init_lw_funop(struct unf_lport *lport, - struct unf_low_level_functioon_op *low_level_op) -{ - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(low_level_op, UNF_RETURN_ERROR); - - lport->port_id = low_level_op->lport_cfg_items.port_id; - lport->port_name = low_level_op->sys_port_name; - lport->node_name = low_level_op->sys_node_name; - lport->options = low_level_op->lport_cfg_items.port_mode; - lport->act_topo = UNF_ACT_TOP_UNKNOWN; - lport->max_ssq_num = low_level_op->support_max_ssq_num; - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_INFO, - "Port(0x%x) .", lport->port_id); - - memcpy(&lport->low_level_func, low_level_op, sizeof(struct unf_low_level_functioon_op)); - - return RETURN_OK; -} - -void unf_lport_release_lw_funop(struct unf_lport *lport) -{ - FC_CHECK_RETURN_VOID(lport); - - memset(&lport->low_level_func, 0, sizeof(struct unf_low_level_functioon_op)); - - lport->destroy_step = UNF_LPORT_DESTROY_STEP_13_DESTROY_LW_INTERFACE; -} - -struct unf_lport *unf_find_lport_by_scsi_hostid(u32 scsi_host_id) -{ - struct list_head *node = NULL, *next_node = NULL; - struct list_head *vp_node = NULL, *next_vp_node = NULL; - struct unf_lport *unf_lport = NULL; - struct unf_lport *unf_vport = NULL; - ulong flags = 0; - ulong pool_flags = 0; - spinlock_t *vp_pool_lock = NULL; - spinlock_t *lport_list_lock = &global_lport_mgr.global_lport_list_lock; - - spin_lock_irqsave(lport_list_lock, flags); - list_for_each_safe(node, next_node, &global_lport_mgr.lport_list_head) { - unf_lport = list_entry(node, struct unf_lport, entry_lport); - vp_pool_lock = &unf_lport->vport_pool->vport_pool_lock; - if (scsi_host_id == UNF_GET_SCSI_HOST_ID(unf_lport->host_info.host)) { - spin_unlock_irqrestore(lport_list_lock, flags); - - return unf_lport; - } - - /* support NPIV */ - if (unf_lport->vport_pool) { - spin_lock_irqsave(vp_pool_lock, pool_flags); - list_for_each_safe(vp_node, next_vp_node, &unf_lport->list_vports_head) { - unf_vport = list_entry(vp_node, struct unf_lport, entry_vport); - - if (scsi_host_id == - UNF_GET_SCSI_HOST_ID(unf_vport->host_info.host)) { - spin_unlock_irqrestore(vp_pool_lock, pool_flags); - spin_unlock_irqrestore(lport_list_lock, flags); - - return unf_vport; - } - } - spin_unlock_irqrestore(vp_pool_lock, pool_flags); - } - } - - list_for_each_safe(node, next_node, &global_lport_mgr.intergrad_head) { - unf_lport = list_entry(node, struct unf_lport, entry_lport); - vp_pool_lock = &unf_lport->vport_pool->vport_pool_lock; - if (scsi_host_id == - UNF_GET_SCSI_HOST_ID(unf_lport->host_info.host)) { - spin_unlock_irqrestore(lport_list_lock, flags); - - return unf_lport; - } - - /* support NPIV */ - if (unf_lport->vport_pool) { - spin_lock_irqsave(vp_pool_lock, pool_flags); - list_for_each_safe(vp_node, next_vp_node, &unf_lport->list_vports_head) { - unf_vport = list_entry(vp_node, struct unf_lport, entry_vport); - - if (scsi_host_id == - UNF_GET_SCSI_HOST_ID(unf_vport->host_info.host)) { - spin_unlock_irqrestore(vp_pool_lock, pool_flags); - spin_unlock_irqrestore(lport_list_lock, flags); - - return unf_vport; - } - } - spin_unlock_irqrestore(vp_pool_lock, pool_flags); - } - } - spin_unlock_irqrestore(lport_list_lock, flags); - - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Can not find port by scsi_host_id(0x%x), may be removing", - scsi_host_id); - - return NULL; -} - -u32 unf_init_scsi_id_table(struct unf_lport *lport) -{ - struct unf_rport_scsi_id_image *rport_scsi_id_image = NULL; - struct unf_wwpn_rport_info *wwpn_port_info = NULL; - u32 idx; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - - rport_scsi_id_image = &lport->rport_scsi_table; - rport_scsi_id_image->max_scsi_id = UNF_MAX_SCSI_ID; - - /* If the number of remote connections supported by the L_Port is 0, an - * exception occurs - */ - if (rport_scsi_id_image->max_scsi_id == 0) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Port(0x%x), supported maximum login is zero.", lport->port_id); - - return UNF_RETURN_ERROR; - } - - rport_scsi_id_image->wwn_rport_info_table = - vmalloc(rport_scsi_id_image->max_scsi_id * sizeof(struct unf_wwpn_rport_info)); - if (!rport_scsi_id_image->wwn_rport_info_table) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Port(0x%x) can't allocate SCSI ID Table(0x%x).", - lport->port_id, rport_scsi_id_image->max_scsi_id); - - return UNF_RETURN_ERROR; - } - memset(rport_scsi_id_image->wwn_rport_info_table, 0, - rport_scsi_id_image->max_scsi_id * sizeof(struct unf_wwpn_rport_info)); - - wwpn_port_info = rport_scsi_id_image->wwn_rport_info_table; - - for (idx = 0; idx < rport_scsi_id_image->max_scsi_id; idx++) { - INIT_DELAYED_WORK(&wwpn_port_info->loss_tmo_work, unf_sesion_loss_timeout); - INIT_LIST_HEAD(&wwpn_port_info->fc_lun_list); - wwpn_port_info->lport = lport; - wwpn_port_info->target_id = INVALID_VALUE32; - wwpn_port_info++; - } - - spin_lock_init(&rport_scsi_id_image->scsi_image_table_lock); - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_INFO, - "[info]Port(0x%x) supported maximum login is %u.", - lport->port_id, rport_scsi_id_image->max_scsi_id); - - return RETURN_OK; -} - -void unf_destroy_scsi_id_table(struct unf_lport *lport) -{ - struct unf_rport_scsi_id_image *rport_scsi_id_image = NULL; - struct unf_wwpn_rport_info *wwn_rport_info = NULL; - u32 i = 0; - u32 ret = UNF_RETURN_ERROR; - - FC_CHECK_RETURN_VOID(lport); - - rport_scsi_id_image = &lport->rport_scsi_table; - if (rport_scsi_id_image->wwn_rport_info_table) { - for (i = 0; i < UNF_MAX_SCSI_ID; i++) { - wwn_rport_info = &rport_scsi_id_image->wwn_rport_info_table[i]; - UNF_DELAYED_WORK_SYNC(ret, (lport->port_id), - (&wwn_rport_info->loss_tmo_work), - "loss tmo Timer work"); - if (wwn_rport_info->lun_qos_level) { - vfree(wwn_rport_info->lun_qos_level); - wwn_rport_info->lun_qos_level = NULL; - } - } - - if (ret) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "Port(0x%x) cancel loss tmo work success", lport->port_id); - } - vfree(rport_scsi_id_image->wwn_rport_info_table); - rport_scsi_id_image->wwn_rport_info_table = NULL; - } - - rport_scsi_id_image->max_scsi_id = 0; - lport->destroy_step = UNF_LPORT_DESTROY_STEP_10_DESTROY_SCSI_TABLE; -} - -static u32 unf_lport_init(struct unf_lport *lport, void *private_data, - struct unf_low_level_functioon_op *low_level_op) -{ - u32 ret = RETURN_OK; - char work_queue_name[13]; - - unf_init_port_parms(lport); - - /* Associating LPort with FCPort */ - lport->fc_port = private_data; - - /* VpIndx=0 is reserved for Lport, and rootLport points to its own */ - lport->vp_index = 0; - lport->root_lport = lport; - lport->chip_info = NULL; - - /* Initialize the units related to L_Port and lw func */ - ret = unf_lport_init_lw_funop(lport, low_level_op); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "LPort(0x%x) initialize lowlevel function unsuccessful.", - lport->port_id); - - return ret; - } - - /* Init Linkevent workqueue */ - snprintf(work_queue_name, sizeof(work_queue_name), "%x_lkq", lport->port_id); - - lport->link_event_wq = create_singlethread_workqueue(work_queue_name); - if (!lport->link_event_wq) { - FC_DRV_PRINT(UNF_LOG_NORMAL, UNF_ERR, - "[err]Port(0x%x) creat link event work queue failed", lport->port_id); - - return UNF_RETURN_ERROR; - } - snprintf(work_queue_name, sizeof(work_queue_name), "%x_xchgwq", lport->port_id); - lport->xchg_wq = create_workqueue(work_queue_name); - if (!lport->xchg_wq) { - FC_DRV_PRINT(UNF_LOG_NORMAL, UNF_ERR, - "[err]Port(0x%x) creat Exchg work queue failed", - lport->port_id); - flush_workqueue(lport->link_event_wq); - destroy_workqueue(lport->link_event_wq); - lport->link_event_wq = NULL; - return UNF_RETURN_ERROR; - } - /* scsi table (R_Port) required for initializing INI - * Initialize the scsi id Table table to manage the mapping between SCSI - * ID, WWN, and Rport. - */ - - ret = unf_init_scsi_id_table(lport); - if (ret != RETURN_OK) { - flush_workqueue(lport->link_event_wq); - destroy_workqueue(lport->link_event_wq); - lport->link_event_wq = NULL; - - flush_workqueue(lport->xchg_wq); - destroy_workqueue(lport->xchg_wq); - lport->xchg_wq = NULL; - return ret; - } - - /* Initialize the EXCH resource */ - ret = unf_alloc_xchg_resource(lport); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "LPort(0x%x) can't allocate exchange resource.", lport->port_id); - - flush_workqueue(lport->link_event_wq); - destroy_workqueue(lport->link_event_wq); - lport->link_event_wq = NULL; - - flush_workqueue(lport->xchg_wq); - destroy_workqueue(lport->xchg_wq); - lport->xchg_wq = NULL; - unf_destroy_scsi_id_table(lport); - - return ret; - } - - /* Initialize the ESGL resource pool used by Lport */ - ret = unf_init_esgl_pool(lport); - if (ret != RETURN_OK) { - flush_workqueue(lport->link_event_wq); - destroy_workqueue(lport->link_event_wq); - lport->link_event_wq = NULL; - - flush_workqueue(lport->xchg_wq); - destroy_workqueue(lport->xchg_wq); - lport->xchg_wq = NULL; - unf_free_all_xchg_mgr(lport); - unf_destroy_scsi_id_table(lport); - - return ret; - } - /* Initialize the disc manager under Lport */ - ret = unf_init_disc_mgr(lport); - if (ret != RETURN_OK) { - flush_workqueue(lport->link_event_wq); - destroy_workqueue(lport->link_event_wq); - lport->link_event_wq = NULL; - - flush_workqueue(lport->xchg_wq); - destroy_workqueue(lport->xchg_wq); - lport->xchg_wq = NULL; - unf_free_esgl_pool(lport); - unf_free_all_xchg_mgr(lport); - unf_destroy_scsi_id_table(lport); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "LPort(0x%x) initialize discover manager unsuccessful.", - lport->port_id); - - return ret; - } - - /* Initialize the LPort manager */ - ret = unf_init_vport_mgr_temp(lport); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "LPort(0x%x) initialize RPort manager unsuccessful.", lport->port_id); - - goto RELEASE_LPORT; - } - - /* Initialize the EXCH manager */ - ret = unf_init_xchg_mgr_temp(lport); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "LPort(0x%x) initialize exchange manager unsuccessful.", - lport->port_id); - goto RELEASE_LPORT; - } - /* Initialize the resources required by the event processing center */ - ret = unf_init_event_center(lport); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "LPort(0x%x) initialize event center unsuccessful.", lport->port_id); - goto RELEASE_LPORT; - } - /* Initialize the initialization status of Lport */ - unf_set_lport_state(lport, UNF_LPORT_ST_INITIAL); - - /* Initialize the Lport route test case */ - ret = unf_init_lport_route(lport); - if (ret != RETURN_OK) { - flush_workqueue(lport->link_event_wq); - destroy_workqueue(lport->link_event_wq); - lport->link_event_wq = NULL; - - flush_workqueue(lport->xchg_wq); - destroy_workqueue(lport->xchg_wq); - lport->xchg_wq = NULL; - (void)unf_event_center_destroy(lport); - unf_disc_mgr_destroy(lport); - unf_free_esgl_pool(lport); - unf_free_all_xchg_mgr(lport); - unf_destroy_scsi_id_table(lport); - - return ret; - } - /* Thesupports the initialization stepof the NPIV */ - ret = unf_init_vport_pool(lport); - if (ret != RETURN_OK) { - flush_workqueue(lport->link_event_wq); - destroy_workqueue(lport->link_event_wq); - lport->link_event_wq = NULL; - - flush_workqueue(lport->xchg_wq); - destroy_workqueue(lport->xchg_wq); - lport->xchg_wq = NULL; - - unf_destroy_lport_route(lport); - (void)unf_event_center_destroy(lport); - unf_disc_mgr_destroy(lport); - unf_free_esgl_pool(lport); - unf_free_all_xchg_mgr(lport); - unf_destroy_scsi_id_table(lport); - - return ret; - } - - /* qualifier rport callback */ - lport->unf_qualify_rport = unf_rport_set_qualifier_key_reuse; - lport->unf_tmf_abnormal_recovery = unf_tmf_timeout_recovery_special; - return RETURN_OK; -RELEASE_LPORT: - flush_workqueue(lport->link_event_wq); - destroy_workqueue(lport->link_event_wq); - lport->link_event_wq = NULL; - - flush_workqueue(lport->xchg_wq); - destroy_workqueue(lport->xchg_wq); - lport->xchg_wq = NULL; - - unf_disc_mgr_destroy(lport); - unf_free_esgl_pool(lport); - unf_free_all_xchg_mgr(lport); - unf_destroy_scsi_id_table(lport); - - return ret; -} - -void unf_free_qos_info(struct unf_lport *lport) -{ - struct list_head *node = NULL; - struct list_head *next_node = NULL; - struct unf_qos_info *qos_info = NULL; - ulong flag = 0; - - FC_CHECK_RETURN_VOID(lport); - - spin_lock_irqsave(&lport->qos_mgr_lock, flag); - list_for_each_safe(node, next_node, &lport->list_qos_head) { - qos_info = (struct unf_qos_info *)list_entry(node, - struct unf_qos_info, entry_qos_info); - list_del_init(&qos_info->entry_qos_info); - kfree(qos_info); - } - - spin_unlock_irqrestore(&lport->qos_mgr_lock, flag); -} - -u32 unf_lport_deinit(struct unf_lport *lport) -{ - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - - unf_free_qos_info(lport); - - unf_unregister_scsi_host(lport); - - /* If the card is unloaded normally, the thread is stopped once. The - * problem does not occur if you stop the thread again. - */ - unf_destroy_lport_route(lport); - - /* minus the reference count of the card event; the last port deletes - * the card thread - */ - unf_destroy_card_thread(lport); - flush_workqueue(lport->link_event_wq); - destroy_workqueue(lport->link_event_wq); - lport->link_event_wq = NULL; - - (void)unf_event_center_destroy(lport); - unf_free_vport_pool(lport); - unf_xchg_mgr_destroy(lport); - - unf_free_esgl_pool(lport); - - /* reliability review :Disc should release after Xchg. Destroy the disc - * manager - */ - unf_disc_mgr_destroy(lport); - - unf_release_xchg_mgr_temp(lport); - - unf_release_vport_mgr_temp(lport); - - unf_destroy_scsi_id_table(lport); - - flush_workqueue(lport->xchg_wq); - destroy_workqueue(lport->xchg_wq); - lport->xchg_wq = NULL; - - /* Releasing the lw Interface Template */ - unf_lport_release_lw_funop(lport); - lport->fc_port = NULL; - - return RETURN_OK; -} - -static int unf_card_event_process(void *arg) -{ - struct list_head *node = NULL; - struct unf_cm_event_report *event_node = NULL; - ulong flags = 0; - struct unf_chip_manage_info *chip_info = (struct unf_chip_manage_info *)arg; - - set_user_nice(current, UNF_OS_THRD_PRI_LOW); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_INFO, - "Slot(%u) chip(0x%x) enter event thread.", - chip_info->slot_id, chip_info->chip_id); - - while (!kthread_should_stop()) { - if (chip_info->thread_exit) - break; - - spin_lock_irqsave(&chip_info->chip_event_list_lock, flags); - if (list_empty(&chip_info->list_head)) { - spin_unlock_irqrestore(&chip_info->chip_event_list_lock, flags); - - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout((long)msecs_to_jiffies(UNF_S_TO_MS)); - } else { - node = UNF_OS_LIST_NEXT(&chip_info->list_head); - list_del_init(node); - chip_info->list_num--; - event_node = list_entry(node, struct unf_cm_event_report, list_entry); - spin_unlock_irqrestore(&chip_info->chip_event_list_lock, flags); - unf_handle_event(event_node); - } - } - FC_DRV_PRINT(UNF_LOG_EVENT, UNF_MAJOR, - "Slot(%u) chip(0x%x) exit event thread.", - chip_info->slot_id, chip_info->chip_id); - - return RETURN_OK; -} - -static void unf_destroy_card_thread(struct unf_lport *lport) -{ - struct unf_event_mgr *event_mgr = NULL; - struct unf_chip_manage_info *chip_info = NULL; - struct list_head *list = NULL; - struct list_head *list_tmp = NULL; - struct unf_cm_event_report *event_node = NULL; - ulong event_lock_flag = 0; - ulong flag = 0; - - FC_CHECK_RETURN_VOID(lport); - - /* If the thread cannot be found, apply for a new thread. */ - chip_info = lport->chip_info; - if (!chip_info) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "Port(0x%x) has no event thread.", lport->port_id); - return; - } - event_mgr = &lport->event_mgr; - - spin_lock_irqsave(&chip_info->chip_event_list_lock, flag); - if (!list_empty(&chip_info->list_head)) { - list_for_each_safe(list, list_tmp, &chip_info->list_head) { - event_node = list_entry(list, struct unf_cm_event_report, list_entry); - - /* The LPort under the global event node is null. */ - if (event_node->lport == lport) { - list_del_init(&event_node->list_entry); - if (event_node->event_asy_flag == UNF_EVENT_SYN) { - event_node->result = UNF_RETURN_ERROR; - complete(&event_node->event_comp); - } - - spin_lock_irqsave(&event_mgr->port_event_lock, event_lock_flag); - event_mgr->free_event_count++; - list_add_tail(&event_node->list_entry, &event_mgr->list_free_event); - spin_unlock_irqrestore(&event_mgr->port_event_lock, - event_lock_flag); - } - } - } - spin_unlock_irqrestore(&chip_info->chip_event_list_lock, flag); - - /* If the number of events introduced by the event thread is 0, - * it indicates that no interface is used. In this case, thread - * resources need to be consumed - */ - if (atomic_dec_and_test(&chip_info->ref_cnt)) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "Port(0x%x) destroy slot(%u) chip(0x%x) event thread succeed.", - lport->port_id, chip_info->slot_id, chip_info->chip_id); - chip_info->thread_exit = true; - wake_up_process(chip_info->thread); - kthread_stop(chip_info->thread); - chip_info->thread = NULL; - - spin_lock_irqsave(&card_thread_mgr.global_card_list_lock, flag); - list_del_init(&chip_info->list_chip_thread_entry); - card_thread_mgr.card_num--; - spin_unlock_irqrestore(&card_thread_mgr.global_card_list_lock, flag); - - vfree(chip_info); - } - - lport->chip_info = NULL; -} - -static u32 unf_creat_card_thread(struct unf_lport *lport) -{ - ulong flag = 0; - struct unf_chip_manage_info *chip_manage_info = NULL; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - - /* If the thread cannot be found, apply for a new thread. */ - chip_manage_info = (struct unf_chip_manage_info *) - vmalloc(sizeof(struct unf_chip_manage_info)); - if (!chip_manage_info) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "Port(0x%x) cannot allocate thread memory.", lport->port_id); - - return UNF_RETURN_ERROR; - } - memset(chip_manage_info, 0, sizeof(struct unf_chip_manage_info)); - - memcpy(&chip_manage_info->chip_info, &lport->low_level_func.chip_info, - sizeof(struct unf_chip_info)); - chip_manage_info->slot_id = UNF_GET_BOARD_TYPE_AND_SLOT_ID_BY_PORTID(lport->port_id); - chip_manage_info->chip_id = lport->low_level_func.chip_id; - chip_manage_info->list_num = 0; - chip_manage_info->sfp_9545_fault = false; - chip_manage_info->sfp_power_fault = false; - atomic_set(&chip_manage_info->ref_cnt, 1); - atomic_set(&chip_manage_info->card_loop_test_flag, false); - spin_lock_init(&chip_manage_info->card_loop_back_state_lock); - INIT_LIST_HEAD(&chip_manage_info->list_head); - spin_lock_init(&chip_manage_info->chip_event_list_lock); - - chip_manage_info->thread_exit = false; - chip_manage_info->thread = kthread_create(unf_card_event_process, - chip_manage_info, "%x_et", lport->port_id); - - if (IS_ERR(chip_manage_info->thread) || !chip_manage_info->thread) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "Port(0x%x) creat event thread(0x%p) unsuccessful.", - lport->port_id, chip_manage_info->thread); - - vfree(chip_manage_info); - - return UNF_RETURN_ERROR; - } - - lport->chip_info = chip_manage_info; - wake_up_process(chip_manage_info->thread); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_INFO, - "Port(0x%x) creat slot(%u) chip(0x%x) event thread succeed.", - lport->port_id, chip_manage_info->slot_id, - chip_manage_info->chip_id); - - spin_lock_irqsave(&card_thread_mgr.global_card_list_lock, flag); - list_add_tail(&chip_manage_info->list_chip_thread_entry, &card_thread_mgr.card_list_head); - card_thread_mgr.card_num++; - spin_unlock_irqrestore(&card_thread_mgr.global_card_list_lock, flag); - - return RETURN_OK; -} - -static u32 unf_find_card_thread(struct unf_lport *lport) -{ - ulong flag = 0; - struct list_head *node = NULL; - struct list_head *next_node = NULL; - struct unf_chip_manage_info *chip_info = NULL; - u32 ret = UNF_RETURN_ERROR; - - spin_lock_irqsave(&card_thread_mgr.global_card_list_lock, flag); - list_for_each_safe(node, next_node, &card_thread_mgr.card_list_head) { - chip_info = list_entry(node, struct unf_chip_manage_info, list_chip_thread_entry); - - if (chip_info->chip_id == lport->low_level_func.chip_id && - chip_info->slot_id == - UNF_GET_BOARD_TYPE_AND_SLOT_ID_BY_PORTID(lport->port_id)) { - atomic_inc(&chip_info->ref_cnt); - lport->chip_info = chip_info; - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "Port(0x%x) find card(%u) chip(0x%x) event thread succeed.", - lport->port_id, chip_info->slot_id, chip_info->chip_id); - - spin_unlock_irqrestore(&card_thread_mgr.global_card_list_lock, flag); - - return RETURN_OK; - } - } - spin_unlock_irqrestore(&card_thread_mgr.global_card_list_lock, flag); - - ret = unf_creat_card_thread(lport); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "LPort(0x%x) creat event thread unsuccessful. Destroy LPort.", - lport->port_id); - - return UNF_RETURN_ERROR; - } else { - return RETURN_OK; - } -} - -void *unf_lport_create_and_init(void *private_data, struct unf_low_level_functioon_op *low_level_op) -{ - struct unf_lport *unf_lport = NULL; - u32 ret = UNF_RETURN_ERROR; - - if (!private_data) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "Private Data is NULL"); - - return NULL; - } - if (!low_level_op) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "LowLevel port(0x%p) function is NULL", private_data); - - return NULL; - } - - /* 1. vmalloc & Memset L_Port */ - unf_lport = vmalloc(sizeof(struct unf_lport)); - if (!unf_lport) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "Alloc LPort memory failed."); - - return NULL; - } - memset(unf_lport, 0, sizeof(struct unf_lport)); - - /* 2. L_Port Init */ - if (unf_lport_init(unf_lport, private_data, low_level_op) != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "LPort initialize unsuccessful."); - - vfree(unf_lport); - - return NULL; - } - - /* 4. Get or Create Chip Thread - * Chip_ID & Slot_ID - */ - ret = unf_find_card_thread(unf_lport); - if (ret != RETURN_OK) { - (void)unf_lport_deinit(unf_lport); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "LPort(0x%x) Find Chip thread unsuccessful. Destroy LPort.", - unf_lport->port_id); - - vfree(unf_lport); - return NULL; - } - - /* 5. Registers with in the port management global linked list */ - unf_port_register(unf_lport); - /* update WWN */ - if (unf_build_lport_wwn(unf_lport) != RETURN_OK) { - unf_port_unregister(unf_lport); - (void)unf_lport_deinit(unf_lport); - vfree(unf_lport); - return NULL; - } - - // unf_init_link_lose_tmo(unf_lport);//TO DO - - /* initialize Scsi Host */ - if (unf_register_scsi_host(unf_lport) != RETURN_OK) { - unf_port_unregister(unf_lport); - (void)unf_lport_deinit(unf_lport); - vfree(unf_lport); - return NULL; - } - /* 7. Here, start work now */ - if (global_lport_mgr.start_work) { - if (unf_port_start_work(unf_lport) != RETURN_OK) { - unf_port_unregister(unf_lport); - - (void)unf_lport_deinit(unf_lport); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[warn]Port(0x%x) start work failed", unf_lport->port_id); - vfree(unf_lport); - return NULL; - } - } - - return unf_lport; -} - -static int unf_lport_destroy(void *lport, void *arg_out) -{ - struct unf_lport *unf_lport = NULL; - ulong flags = 0; - - if (!lport) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, "LPort is NULL."); - - return UNF_RETURN_ERROR; - } - - unf_lport = (struct unf_lport *)lport; - - FC_DRV_PRINT(UNF_LOG_NORMAL, UNF_MAJOR, - "Destroy LPort(0x%p), ID(0x%x).", unf_lport, unf_lport->port_id); - /* NPIV Ensure that all Vport are deleted */ - unf_destroy_all_vports(unf_lport); - unf_lport->destroy_step = UNF_LPORT_DESTROY_STEP_1_REPORT_PORT_OUT; - - (void)unf_lport_deinit(lport); - - /* The port is removed from the destroy linked list. The next step is to - * release the memory - */ - spin_lock_irqsave(&global_lport_mgr.global_lport_list_lock, flags); - list_del(&unf_lport->entry_lport); - - /* If the port has dirty memory, the port is mounted to the linked list - * of dirty ports - */ - if (unf_lport->dirty_flag) - list_add_tail(&unf_lport->entry_lport, &global_lport_mgr.dirty_list_head); - spin_unlock_irqrestore(&global_lport_mgr.global_lport_list_lock, flags); - - if (unf_lport->lport_free_completion) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "Complete LPort(0x%p), port ID(0x%x)'s Free Completion.", - unf_lport, unf_lport->port_id); - complete(unf_lport->lport_free_completion); - } else { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "LPort(0x%p), port ID(0x%x)'s Free Completion is NULL.", - unf_lport, unf_lport->port_id); - dump_stack(); - } - - return RETURN_OK; -} - -static int unf_port_switch(struct unf_lport *lport, bool switch_flag) -{ - struct unf_lport *unf_lport = lport; - int ret = UNF_RETURN_ERROR; - bool flag = false; - - FC_CHECK_RETURN_VALUE(unf_lport, UNF_RETURN_ERROR); - - if (!unf_lport->low_level_func.port_mgr_op.ll_port_config_set) { - FC_DRV_PRINT(UNF_LOG_EQUIP_ATT, UNF_WARN, - "[warn]Port(0x%x)'s config(switch) function is NULL", - unf_lport->port_id); - - return UNF_RETURN_ERROR; - } - - flag = switch_flag ? true : false; - - ret = (int)unf_lport->low_level_func.port_mgr_op.ll_port_config_set(unf_lport->fc_port, - UNF_PORT_CFG_SET_PORT_SWITCH, (void *)&flag); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_EQUIP_ATT, - UNF_WARN, "[warn]Port(0x%x) switch %s failed", - unf_lport->port_id, switch_flag ? "On" : "Off"); - - return UNF_RETURN_ERROR; - } - - unf_lport->switch_state = (bool)flag; - - return RETURN_OK; -} - -static int unf_send_event(u32 port_id, u32 syn_flag, void *argc_in, void *argc_out, - int (*func)(void *argc_in, void *argc_out)) -{ - struct unf_lport *lport = NULL; - struct unf_cm_event_report *event = NULL; - int ret = 0; - - lport = unf_find_lport_by_port_id(port_id); - if (!lport) { - FC_DRV_PRINT(UNF_LOG_EQUIP_ATT, - UNF_INFO, "Cannot find LPort(0x%x).", port_id); - - return UNF_RETURN_ERROR; - } - - if (unf_lport_ref_inc(lport) != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "LPort(0x%x) is removing, no need process.", - lport->port_id); - - return UNF_RETURN_ERROR; - } - if (unlikely(!lport->event_mgr.unf_get_free_event_func || - !lport->event_mgr.unf_post_event_func || - !lport->event_mgr.unf_release_event)) { - FC_DRV_PRINT(UNF_LOG_EQUIP_ATT, - UNF_MAJOR, "Event function is NULL."); - - unf_lport_ref_dec_to_destroy(lport); - - return UNF_RETURN_ERROR; - } - - if (lport->port_removing) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "LPort(0x%x) is removing, no need process.", - lport->port_id); - - unf_lport_ref_dec_to_destroy(lport); - - return UNF_RETURN_ERROR; - } - - event = lport->event_mgr.unf_get_free_event_func((void *)lport); - if (!event) { - unf_lport_ref_dec_to_destroy(lport); - - return UNF_RETURN_ERROR; - } - - init_completion(&event->event_comp); - event->lport = lport; - event->event_asy_flag = syn_flag; - event->unf_event_task = func; - event->para_in = argc_in; - event->para_out = argc_out; - lport->event_mgr.unf_post_event_func(lport, event); - - if (event->event_asy_flag) { - /* You must wait for the other party to return. Otherwise, the - * linked list may be in disorder. - */ - wait_for_completion(&event->event_comp); - ret = (int)event->result; - lport->event_mgr.unf_release_event(lport, event); - } else { - ret = RETURN_OK; - } - - unf_lport_ref_dec_to_destroy(lport); - return ret; -} - -static int unf_reset_port(void *arg_in, void *arg_out) -{ - struct unf_reset_port_argin *input = (struct unf_reset_port_argin *)arg_in; - struct unf_lport *lport = NULL; - u32 ret = UNF_RETURN_ERROR; - enum unf_port_config_state port_state = UNF_PORT_CONFIG_STATE_RESET; - - FC_CHECK_RETURN_VALUE(input, UNF_RETURN_ERROR); - - lport = unf_find_lport_by_port_id(input->port_id); - if (!lport) { - FC_DRV_PRINT(UNF_LOG_EQUIP_ATT, - UNF_MAJOR, "Not find LPort(0x%x).", - input->port_id); - - return UNF_RETURN_ERROR; - } - - /* reset port */ - if (!lport->low_level_func.port_mgr_op.ll_port_config_set) { - FC_DRV_PRINT(UNF_LOG_EQUIP_ATT, UNF_MAJOR, - "Port(0x%x)'s corresponding function is NULL.", lport->port_id); - - return UNF_RETURN_ERROR; - } - - lport->act_topo = UNF_ACT_TOP_UNKNOWN; - lport->speed = UNF_PORT_SPEED_UNKNOWN; - lport->fabric_node_name = 0; - - ret = lport->low_level_func.port_mgr_op.ll_port_config_set(lport->fc_port, - UNF_PORT_CFG_SET_PORT_STATE, - (void *)&port_state); - - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_EQUIP_ATT, - UNF_MAJOR, "Reset port(0x%x) unsuccessful.", - lport->port_id); - - return UNF_RETURN_ERROR; - } - - return RETURN_OK; -} - -int unf_cm_reset_port(u32 port_id) -{ - int ret = UNF_RETURN_ERROR; - - ret = unf_send_event(port_id, UNF_EVENT_SYN, (void *)&port_id, - (void *)NULL, unf_reset_port); - return ret; -} - -int unf_lport_reset_port(struct unf_lport *lport, u32 flag) -{ - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - - return unf_send_event(lport->port_id, flag, (void *)&lport->port_id, - (void *)NULL, unf_reset_port); -} - -static inline u32 unf_get_loop_alpa(struct unf_lport *lport, void *loop_alpa) -{ - u32 ret = UNF_RETURN_ERROR; - - FC_CHECK_RETURN_VALUE(lport->low_level_func.port_mgr_op.ll_port_config_get, - UNF_RETURN_ERROR); - - ret = lport->low_level_func.port_mgr_op.ll_port_config_get(lport->fc_port, - UNF_PORT_CFG_GET_LOOP_ALPA, loop_alpa); - - return ret; -} - -static u32 unf_lport_enter_private_loop_login(struct unf_lport *lport) -{ - struct unf_lport *unf_lport = lport; - ulong flag = 0; - u32 ret = UNF_RETURN_ERROR; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - - spin_lock_irqsave(&unf_lport->lport_state_lock, flag); - unf_lport_state_ma(unf_lport, UNF_EVENT_LPORT_READY); /* LPort: LINK_UP --> READY */ - spin_unlock_irqrestore(&unf_lport->lport_state_lock, flag); - - unf_lport_update_topo(unf_lport, UNF_ACT_TOP_PRIVATE_LOOP); - - /* NOP: check L_Port state */ - if (atomic_read(&unf_lport->lport_no_operate_flag) == UNF_LPORT_NOP) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, - UNF_MAJOR, "[info]Port(0x%x) is NOP, do nothing", - unf_lport->port_id); - - return RETURN_OK; - } - - /* INI: check L_Port mode */ - if (UNF_PORT_MODE_INI != (unf_lport->options & UNF_PORT_MODE_INI)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x) has no INI feature(0x%x), do nothing", - unf_lport->port_id, unf_lport->options); - - return RETURN_OK; - } - - if (unf_lport->disc.disc_temp.unf_disc_start) { - ret = unf_lport->disc.disc_temp.unf_disc_start(unf_lport); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) with nportid(0x%x) start discovery failed", - unf_lport->port_id, unf_lport->nport_id); - } - } - - return ret; -} - -u32 unf_lport_login(struct unf_lport *lport, enum unf_act_topo act_topo) -{ - u32 loop_alpa = 0; - u32 ret = RETURN_OK; - ulong flag = 0; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - - /* 1. Update (set) L_Port topo which get from low level */ - unf_lport_update_topo(lport, act_topo); - - spin_lock_irqsave(&lport->lport_state_lock, flag); - - /* 2. Link state check */ - if (lport->link_up != UNF_PORT_LINK_UP) { - spin_unlock_irqrestore(&lport->lport_state_lock, flag); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) with link_state(0x%x) port_state(0x%x) when login", - lport->port_id, lport->link_up, lport->states); - - return UNF_RETURN_ERROR; - } - - /* 3. Update L_Port state */ - unf_lport_state_ma(lport, UNF_EVENT_LPORT_LINK_UP); /* LPort: INITIAL --> LINK UP */ - spin_unlock_irqrestore(&lport->lport_state_lock, flag); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "[info]LOGIN: Port(0x%x) start to login with topology(0x%x)", - lport->port_id, lport->act_topo); - - /* 4. Start logoin */ - if (act_topo == UNF_TOP_P2P_MASK || - act_topo == UNF_ACT_TOP_P2P_FABRIC || - act_topo == UNF_ACT_TOP_P2P_DIRECT) { - /* P2P or Fabric mode */ - ret = unf_lport_enter_flogi(lport); - } else if (act_topo == UNF_ACT_TOP_PUBLIC_LOOP) { - /* Public loop */ - (void)unf_get_loop_alpa(lport, &loop_alpa); - - /* Before FLOGI ALPA just low 8 bit, after FLOGI ACC, switch - * will assign complete addresses - */ - spin_lock_irqsave(&lport->lport_state_lock, flag); - lport->nport_id = loop_alpa; - spin_unlock_irqrestore(&lport->lport_state_lock, flag); - - ret = unf_lport_enter_flogi(lport); - } else if (act_topo == UNF_ACT_TOP_PRIVATE_LOOP) { - /* Private loop */ - (void)unf_get_loop_alpa(lport, &loop_alpa); - - spin_lock_irqsave(&lport->lport_state_lock, flag); - lport->nport_id = loop_alpa; - spin_unlock_irqrestore(&lport->lport_state_lock, flag); - - ret = unf_lport_enter_private_loop_login(lport); - } else { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]LOGIN: Port(0x%x) login with unknown topology(0x%x)", - lport->port_id, lport->act_topo); - } - - return ret; -} - -static u32 unf_port_linkup(struct unf_lport *lport, void *input) -{ - struct unf_lport *unf_lport = lport; - u32 ret = RETURN_OK; - enum unf_act_topo act_topo = UNF_ACT_TOP_UNKNOWN; - ulong flag = 0; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - - /* If NOP state, stop */ - if (atomic_read(&unf_lport->lport_no_operate_flag) == UNF_LPORT_NOP) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[warn]Port(0x%x) is NOP and do nothing", unf_lport->port_id); - - return RETURN_OK; - } - - /* Update port state */ - spin_lock_irqsave(&unf_lport->lport_state_lock, flag); - unf_lport->link_up = UNF_PORT_LINK_UP; - unf_lport->speed = *((u32 *)input); - unf_set_lport_state(lport, UNF_LPORT_ST_INITIAL); /* INITIAL state */ - spin_unlock_irqrestore(&unf_lport->lport_state_lock, flag); - - /* set hot pool wait state: so far, do not care */ - unf_set_hot_pool_wait_state(unf_lport, true); - - unf_lport->enhanced_features |= UNF_LPORT_ENHANCED_FEATURE_READ_SFP_ONCE; - - /* Get port active topopolgy (from low level) */ - if (!unf_lport->low_level_func.port_mgr_op.ll_port_config_get) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[warn]Port(0x%x) get topo function is NULL", unf_lport->port_id); - - return UNF_RETURN_ERROR; - } - ret = unf_lport->low_level_func.port_mgr_op.ll_port_config_get(unf_lport->fc_port, - UNF_PORT_CFG_GET_TOPO_ACT, (void *)&act_topo); - - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[warn]Port(0x%x) get topo from low level failed", - unf_lport->port_id); - - return UNF_RETURN_ERROR; - } - - /* Start Login process */ - ret = unf_lport_login(unf_lport, act_topo); - - return ret; -} - -static u32 unf_port_linkdown(struct unf_lport *lport, void *input) -{ - ulong flag = 0; - struct unf_lport *unf_lport = NULL; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - - unf_lport = lport; - - /* To prevent repeated reporting linkdown */ - spin_lock_irqsave(&unf_lport->lport_state_lock, flag); - unf_lport->speed = UNF_PORT_SPEED_UNKNOWN; - unf_lport->act_topo = UNF_ACT_TOP_UNKNOWN; - if (unf_lport->link_up == UNF_PORT_LINK_DOWN) { - spin_unlock_irqrestore(&unf_lport->lport_state_lock, flag); - - return RETURN_OK; - } - unf_lport_state_ma(unf_lport, UNF_EVENT_LPORT_LINK_DOWN); - unf_reset_lport_params(unf_lport); - spin_unlock_irqrestore(&unf_lport->lport_state_lock, flag); - - unf_set_hot_pool_wait_state(unf_lport, false); - - /* - * clear I/O: - * 1. INI do ABORT only, - * 2. TGT need do source clear with Wait_IO - * * - * for INI: busy/delay/delay_transfer/wait - * Clean L_Port/V_Port Link Down I/O: only set ABORT tag - */ - unf_flush_disc_event(&unf_lport->disc, NULL); - - unf_clean_linkdown_io(unf_lport, false); - - /* for L_Port's R_Ports */ - unf_clean_linkdown_rport(unf_lport); - /* for L_Port's all Vports */ - unf_linkdown_all_vports(lport); - return RETURN_OK; -} - -static u32 unf_port_abnormal_reset(struct unf_lport *lport, void *input) -{ - u32 ret = UNF_RETURN_ERROR; - struct unf_lport *unf_lport = NULL; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - - unf_lport = lport; - - ret = (u32)unf_lport_reset_port(unf_lport, UNF_EVENT_ASYN); - - return ret; -} - -static u32 unf_port_reset_start(struct unf_lport *lport, void *input) -{ - u32 ret = RETURN_OK; - ulong flag = 0; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - - spin_lock_irqsave(&lport->lport_state_lock, flag); - unf_set_lport_state(lport, UNF_LPORT_ST_RESET); - spin_unlock_irqrestore(&lport->lport_state_lock, flag); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "Port(0x%x) begin to reset.", lport->port_id); - - return ret; -} - -static u32 unf_port_reset_end(struct unf_lport *lport, void *input) -{ - ulong flag = 0; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "Port(0x%x) reset end.", lport->port_id); - - /* Task management command returns success and avoid repair measures - * case offline device - */ - unf_wake_up_scsi_task_cmnd(lport); - - spin_lock_irqsave(&lport->lport_state_lock, flag); - unf_set_lport_state(lport, UNF_LPORT_ST_INITIAL); - spin_unlock_irqrestore(&lport->lport_state_lock, flag); - - return RETURN_OK; -} - -static u32 unf_port_nop(struct unf_lport *lport, void *input) -{ - struct unf_lport *unf_lport = NULL; - ulong flag = 0; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - - unf_lport = lport; - - atomic_set(&unf_lport->lport_no_operate_flag, UNF_LPORT_NOP); - - spin_lock_irqsave(&unf_lport->lport_state_lock, flag); - unf_lport_state_ma(unf_lport, UNF_EVENT_LPORT_LINK_DOWN); - unf_reset_lport_params(unf_lport); - spin_unlock_irqrestore(&unf_lport->lport_state_lock, flag); - - /* Set Tag prevent pending I/O to wait_list when close sfp failed */ - unf_set_hot_pool_wait_state(unf_lport, false); - - unf_flush_disc_event(&unf_lport->disc, NULL); - - /* L_Port/V_Port's I/O(s): Clean Link Down I/O: Set Abort Tag */ - unf_clean_linkdown_io(unf_lport, false); - - /* L_Port/V_Port's R_Port(s): report link down event to scsi & clear - * resource - */ - unf_clean_linkdown_rport(unf_lport); - unf_linkdown_all_vports(unf_lport); - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x) report NOP event done", unf_lport->nport_id); - - return RETURN_OK; -} - -static u32 unf_port_begin_remove(struct unf_lport *lport, void *input) -{ - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - /* Cancel route timer delay work */ - unf_destroy_lport_route(lport); - - return RETURN_OK; -} - -static u32 unf_get_pcie_link_state(struct unf_lport *lport) -{ - struct unf_lport *unf_lport = lport; - bool linkstate = true; - u32 ret = UNF_RETURN_ERROR; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(unf_lport->low_level_func.port_mgr_op.ll_port_config_get, - UNF_RETURN_ERROR); - - ret = unf_lport->low_level_func.port_mgr_op.ll_port_config_get(unf_lport->fc_port, - UNF_PORT_CFG_GET_PCIE_LINK_STATE, (void *)&linkstate); - if (ret != RETURN_OK || linkstate != true) { - FC_DRV_PRINT(UNF_LOG_EQUIP_ATT, - UNF_KEVENT, "[err]Can't Get Pcie Link State"); - - return UNF_RETURN_ERROR; - } - - return RETURN_OK; -} - -void unf_root_lport_ref_dec(struct unf_lport *lport) -{ - ulong flags = 0; - ulong lport_flags = 0; - u32 ret = UNF_RETURN_ERROR; - - FC_CHECK_RETURN_VOID(lport); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "[info]Port(0x%p) port_id(0x%x) reference count is %d", - lport, lport->port_id, atomic_read(&lport->port_ref_cnt)); - - spin_lock_irqsave(&global_lport_mgr.global_lport_list_lock, flags); - spin_lock_irqsave(&lport->lport_state_lock, lport_flags); - if (atomic_dec_and_test(&lport->port_ref_cnt)) { - spin_unlock_irqrestore(&lport->lport_state_lock, lport_flags); - - list_del(&lport->entry_lport); - global_lport_mgr.lport_sum--; - - /* Put L_Port to destroy list for debuging */ - list_add_tail(&lport->entry_lport, &global_lport_mgr.destroy_list_head); - spin_unlock_irqrestore(&global_lport_mgr.global_lport_list_lock, flags); - - ret = unf_schedule_global_event((void *)lport, UNF_GLOBAL_EVENT_ASYN, - unf_lport_destroy); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_EVENT, UNF_CRITICAL, - "[warn]Schedule global event faile. remain nodes(0x%x)", - global_event_queue.list_number); - } - } else { - spin_unlock_irqrestore(&lport->lport_state_lock, lport_flags); - spin_unlock_irqrestore(&global_lport_mgr.global_lport_list_lock, flags); - } -} - -void unf_lport_ref_dec_to_destroy(struct unf_lport *lport) -{ - if (lport->root_lport != lport) - unf_vport_ref_dec(lport); - else - unf_root_lport_ref_dec(lport); -} - -void unf_lport_route_work(struct work_struct *work) -{ -#define UNF_MAX_PCIE_LINK_DOWN_TIMES 3 - struct unf_lport *unf_lport = NULL; - int ret = 0; - - FC_CHECK_RETURN_VOID(work); - - unf_lport = container_of(work, struct unf_lport, route_timer_work.work); - if (unlikely(!unf_lport)) { - FC_DRV_PRINT(UNF_LOG_EQUIP_ATT, - UNF_KEVENT, "[err]LPort is NULL"); - - return; - } - - if (unlikely(unf_lport->port_removing)) { - FC_DRV_PRINT(UNF_LOG_EQUIP_ATT, UNF_KEVENT, - "[warn]LPort(0x%x) route work is closing.", unf_lport->port_id); - - unf_lport_ref_dec_to_destroy(unf_lport); - - return; - } - - if (unlikely(unf_get_pcie_link_state(unf_lport))) - unf_lport->pcie_link_down_cnt++; - else - unf_lport->pcie_link_down_cnt = 0; - - if (unf_lport->pcie_link_down_cnt >= UNF_MAX_PCIE_LINK_DOWN_TIMES) { - FC_DRV_PRINT(UNF_LOG_EQUIP_ATT, UNF_KEVENT, - "[warn]LPort(0x%x) detected pcie linkdown, closing route work", - unf_lport->port_id); - unf_lport->pcie_link_down = true; - unf_free_lport_all_xchg(unf_lport); - unf_lport_ref_dec_to_destroy(unf_lport); - return; - } - - if (unlikely(UNF_LPORT_CHIP_ERROR(unf_lport))) { - FC_DRV_PRINT(UNF_LOG_EQUIP_ATT, UNF_KEVENT, - "[warn]LPort(0x%x) reported chip error, closing route work. ", - unf_lport->port_id); - - unf_lport_ref_dec_to_destroy(unf_lport); - - return; - } - - if (unf_lport->enhanced_features & - UNF_LPORT_ENHANCED_FEATURE_CLOSE_FW_ROUTE) { - FC_DRV_PRINT(UNF_LOG_EQUIP_ATT, UNF_KEVENT, - "[warn]User close LPort(0x%x) route work. ", unf_lport->port_id); - - unf_lport_ref_dec_to_destroy(unf_lport); - - return; - } - - /* Scheduling 1 second */ - ret = queue_delayed_work(unf_wq, &unf_lport->route_timer_work, - (ulong)msecs_to_jiffies(UNF_LPORT_POLL_TIMER)); - if (ret == 0) { - FC_DRV_PRINT(UNF_LOG_EQUIP_ATT, UNF_KEVENT, - "[warn]LPort(0x%x) schedule work unsuccessful.", unf_lport->port_id); - - unf_lport_ref_dec_to_destroy(unf_lport); - } -} - -static int unf_cm_get_mac_adr(void *argc_in, void *argc_out) -{ - struct unf_lport *unf_lport = NULL; - struct unf_get_chip_info_argout *chip_info = NULL; - - FC_CHECK_RETURN_VALUE(argc_in, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(argc_out, UNF_RETURN_ERROR); - - unf_lport = (struct unf_lport *)argc_in; - chip_info = (struct unf_get_chip_info_argout *)argc_out; - - if (!unf_lport) { - FC_DRV_PRINT(UNF_LOG_EQUIP_ATT, - UNF_MAJOR, " LPort is null."); - - return UNF_RETURN_ERROR; - } - - if (!unf_lport->low_level_func.port_mgr_op.ll_port_config_get) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "Port(0x%x)'s corresponding function is NULL.", unf_lport->port_id); - - return UNF_RETURN_ERROR; - } - - if (unf_lport->low_level_func.port_mgr_op.ll_port_config_get(unf_lport->fc_port, - UNF_PORT_CFG_GET_MAC_ADDR, - chip_info) != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "Port(0x%x) get .", unf_lport->port_id); - - return UNF_RETURN_ERROR; - } - - return RETURN_OK; -} - -int unf_build_sys_wwn(u32 port_id, u64 *sys_port_name, u64 *sys_node_name) -{ - struct unf_get_chip_info_argout wwn = {0}; - u32 ret = UNF_RETURN_ERROR; - struct unf_lport *unf_lport = NULL; - - FC_CHECK_RETURN_VALUE((sys_port_name), UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE((sys_node_name), UNF_RETURN_ERROR); - - unf_lport = unf_find_lport_by_port_id(port_id); - if (!unf_lport) - return UNF_RETURN_ERROR; - - ret = (u32)unf_send_event(unf_lport->port_id, UNF_EVENT_SYN, - (void *)unf_lport, (void *)&wwn, unf_cm_get_mac_adr); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "send event(port get mac adr) fail."); - return UNF_RETURN_ERROR; - } - - /* save card mode: UNF_FC_SERVER_BOARD_32_G(6):32G; - * UNF_FC_SERVER_BOARD_16_G(7):16G MODE - */ - unf_lport->card_type = wwn.board_type; - - /* update port max speed */ - if (wwn.board_type == UNF_FC_SERVER_BOARD_32_G) - unf_lport->low_level_func.fc_ser_max_speed = UNF_PORT_SPEED_32_G; - else if (wwn.board_type == UNF_FC_SERVER_BOARD_16_G) - unf_lport->low_level_func.fc_ser_max_speed = UNF_PORT_SPEED_16_G; - else if (wwn.board_type == UNF_FC_SERVER_BOARD_8_G) - unf_lport->low_level_func.fc_ser_max_speed = UNF_PORT_SPEED_8_G; - else - unf_lport->low_level_func.fc_ser_max_speed = UNF_PORT_SPEED_32_G; - - *sys_port_name = wwn.wwpn; - *sys_node_name = wwn.wwnn; - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_INFO, - "Port(0x%x) Port Name(0x%llx), Node Name(0x%llx.)", - port_id, *sys_port_name, *sys_node_name); - - return RETURN_OK; -} - -static u32 unf_update_port_wwn(struct unf_lport *lport, - struct unf_port_wwn *port_wwn) -{ - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(port_wwn, UNF_RETURN_ERROR); - - /* Now notice lowlevel to update */ - if (!lport->low_level_func.port_mgr_op.ll_port_config_set) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "Port(0x%x)'s corresponding function is NULL.", - lport->port_id); - - return UNF_RETURN_ERROR; - } - - if (lport->low_level_func.port_mgr_op.ll_port_config_set(lport->fc_port, - UNF_PORT_CFG_UPDATE_WWN, - port_wwn) != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "Port(0x%x) update WWN unsuccessful.", - lport->port_id); - - return UNF_RETURN_ERROR; - } - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "Port(0x%x) update WWN: previous(0x%llx, 0x%llx), now(0x%llx, 0x%llx).", - lport->port_id, lport->port_name, lport->node_name, - port_wwn->sys_port_wwn, port_wwn->sys_node_name); - - lport->port_name = port_wwn->sys_port_wwn; - lport->node_name = port_wwn->sys_node_name; - - return RETURN_OK; -} - -static u32 unf_build_lport_wwn(struct unf_lport *lport) -{ - struct unf_port_wwn port_wwn = {0}; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - - if (unf_build_sys_wwn(lport->port_id, &port_wwn.sys_port_wwn, - &port_wwn.sys_node_name) != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "Port(0x%x) build WWN unsuccessful.", lport->port_id); - - return UNF_RETURN_ERROR; - } - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]Port(0x%x) build WWN succeed", lport->port_id); - - if (unf_update_port_wwn(lport, &port_wwn) != RETURN_OK) - return UNF_RETURN_ERROR; - - return RETURN_OK; -} - -u32 unf_port_release_rport_index(struct unf_lport *lport, void *input) -{ - u32 rport_index = INVALID_VALUE32; - ulong flag = 0; - struct unf_rport_pool *rport_pool = NULL; - struct unf_lport *unf_lport = NULL; - spinlock_t *rport_pool_lock = NULL; - - unf_lport = (struct unf_lport *)lport->root_lport; - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - - if (input) { - rport_index = *(u32 *)input; - if (rport_index < lport->low_level_func.support_max_rport) { - rport_pool = &unf_lport->rport_pool; - rport_pool_lock = &rport_pool->rport_free_pool_lock; - spin_lock_irqsave(rport_pool_lock, flag); - if (test_bit((int)rport_index, rport_pool->rpi_bitmap)) { - clear_bit((int)rport_index, rport_pool->rpi_bitmap); - } else { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) try to release a free rport index(0x%x)", - lport->port_id, rport_index); - } - spin_unlock_irqrestore(rport_pool_lock, flag); - } else { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) try to release a not exist rport index(0x%x)", - lport->port_id, rport_index); - } - } - - return RETURN_OK; -} - -void *unf_lookup_lport_by_nportid(void *lport, u32 nport_id) -{ - struct unf_lport *unf_lport = NULL; - struct unf_vport_pool *vport_pool = NULL; - struct unf_lport *unf_vport = NULL; - struct list_head *node = NULL; - struct list_head *next_node = NULL; - ulong flag = 0; - - FC_CHECK_RETURN_VALUE(lport, NULL); - - unf_lport = (struct unf_lport *)lport; - unf_lport = unf_lport->root_lport; - vport_pool = unf_lport->vport_pool; - - if (unf_lport->nport_id == nport_id) - return unf_lport; - - if (unlikely(!vport_pool)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x) vport pool is NULL", unf_lport->port_id); - - return NULL; - } - - spin_lock_irqsave(&vport_pool->vport_pool_lock, flag); - list_for_each_safe(node, next_node, &unf_lport->list_vports_head) { - unf_vport = list_entry(node, struct unf_lport, entry_vport); - if (unf_vport->nport_id == nport_id) { - spin_unlock_irqrestore(&vport_pool->vport_pool_lock, flag); - return unf_vport; - } - } - - list_for_each_safe(node, next_node, &unf_lport->list_intergrad_vports) { - unf_vport = list_entry(node, struct unf_lport, entry_vport); - if (unf_vport->nport_id == nport_id) { - spin_unlock_irqrestore(&vport_pool->vport_pool_lock, flag); - return unf_vport; - } - } - spin_unlock_irqrestore(&vport_pool->vport_pool_lock, flag); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "Port(0x%x) has no vport Nport ID(0x%x)", - unf_lport->port_id, nport_id); - - return NULL; -} - -int unf_get_link_lose_tmo(struct unf_lport *lport) -{ - u32 tmo_value = 0; - - if (!lport) - return UNF_LOSE_TMO; - - tmo_value = atomic_read(&lport->link_lose_tmo); - - if (!tmo_value) - tmo_value = UNF_LOSE_TMO; - - return (int)tmo_value; -} - -u32 unf_register_scsi_host(struct unf_lport *lport) -{ - struct unf_host_param host_param = {0}; - - struct Scsi_Host **scsi_host = NULL; - struct unf_lport_cfg_item *lport_cfg_items = NULL; - - FC_CHECK_RETURN_VALUE((lport), UNF_RETURN_ERROR); - - /* Point to -->> L_port->Scsi_host */ - scsi_host = &lport->host_info.host; - - lport_cfg_items = &lport->low_level_func.lport_cfg_items; - host_param.can_queue = (int)lport_cfg_items->max_queue_depth; - - /* Performance optimization */ - host_param.cmnd_per_lun = UNF_MAX_CMND_PER_LUN; - - host_param.sg_table_size = UNF_MAX_DMA_SEGS; - host_param.max_id = UNF_MAX_TARGET_NUMBER; - host_param.max_lun = UNF_DEFAULT_MAX_LUN; - host_param.max_channel = UNF_MAX_BUS_CHANNEL; - host_param.max_cmnd_len = UNF_MAX_SCSI_CMND_LEN; /* CDB-16 */ - host_param.dma_boundary = UNF_DMA_BOUNDARY; - host_param.max_sectors = UNF_MAX_SECTORS; - host_param.port_id = lport->port_id; - host_param.lport = lport; - host_param.pdev = &lport->low_level_func.dev->dev; - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_INFO, - "[info]Port(0x%x) allocate scsi host: can queue(%u), command performance LUN(%u), max lun(%u)", - lport->port_id, host_param.can_queue, host_param.cmnd_per_lun, - host_param.max_lun); - - if (unf_alloc_scsi_host(scsi_host, &host_param) != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Port(0x%x) allocate scsi host failed", lport->port_id); - - return UNF_RETURN_ERROR; - } - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_KEVENT, - "[event]Port(0x%x) allocate scsi host(0x%x) succeed", - lport->port_id, UNF_GET_SCSI_HOST_ID(*scsi_host)); - - return RETURN_OK; -} - -void unf_unregister_scsi_host(struct unf_lport *lport) -{ - struct Scsi_Host *scsi_host = NULL; - u32 host_no = 0; - - FC_CHECK_RETURN_VOID(lport); - - scsi_host = lport->host_info.host; - - if (scsi_host) { - host_no = UNF_GET_SCSI_HOST_ID(scsi_host); - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[event]Port(0x%x) starting unregister scsi host(0x%x)", - lport->port_id, host_no); - unf_free_scsi_host(scsi_host); - /* can`t set scsi_host for NULL, since it does`t alloc by itself */ - } else { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_KEVENT, - "[warn]Port(0x%x) unregister scsi host, invalid scsi_host ", - lport->port_id); - } - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[event]Port(0x%x) unregister scsi host(0x%x) succeed", - lport->port_id, host_no); - - lport->destroy_step = UNF_LPORT_DESTROY_STEP_12_UNREG_SCSI_HOST; -} diff --git a/drivers/scsi/spfc/common/unf_portman.h b/drivers/scsi/spfc/common/unf_portman.h deleted file mode 100644 index 4ad93d32bcaa..000000000000 --- a/drivers/scsi/spfc/common/unf_portman.h +++ /dev/null @@ -1,96 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef UNF_PORTMAN_H -#define UNF_PORTMAN_H - -#include "unf_type.h" -#include "unf_lport.h" - -#define UNF_LPORT_POLL_TIMER ((u32)(1 * 1000)) -#define UNF_TX_CREDIT_REG_32_G 0x2289420 -#define UNF_RX_CREDIT_REG_32_G 0x228950c -#define UNF_CREDIT_REG_16_G 0x2283418 -#define UNF_PORT_OFFSET_BASE 0x10000 -#define UNF_CREDIT_EMU_VALUE 0x20 -#define UNF_CREDIT_VALUE_32_G 0x8 -#define UNF_CREDIT_VALUE_16_G 0x8000000080008 - -struct unf_nportid_map { - u32 sid; - u32 did; - void *rport[1024]; - void *lport; -}; - -struct unf_global_card_thread { - struct list_head card_list_head; - spinlock_t global_card_list_lock; - u32 card_num; -}; - -/* Global L_Port MG,manage all L_Port */ -struct unf_global_lport { - struct list_head lport_list_head; - - /* Temporary list,used in hold list traverse */ - struct list_head intergrad_head; - - /* destroy list,used in card remove */ - struct list_head destroy_list_head; - - /* Dirty list,abnormal port */ - struct list_head dirty_list_head; - spinlock_t global_lport_list_lock; - u32 lport_sum; - u8 dft_mode; - bool start_work; -}; - -struct unf_port_action { - u32 action; - u32 (*unf_action)(struct unf_lport *lport, void *input); -}; - -struct unf_reset_port_argin { - u32 port_id; -}; - -extern struct unf_global_lport global_lport_mgr; -extern struct unf_global_card_thread card_thread_mgr; -extern struct workqueue_struct *unf_wq; - -struct unf_lport *unf_find_lport_by_port_id(u32 port_id); -struct unf_lport *unf_find_lport_by_scsi_hostid(u32 scsi_host_id); -void * -unf_lport_create_and_init(void *private_data, - struct unf_low_level_functioon_op *low_level_op); -u32 unf_fc_port_link_event(void *lport, u32 events, void *input); -u32 unf_release_local_port(void *lport); -void unf_lport_route_work(struct work_struct *work); -void unf_lport_update_topo(struct unf_lport *lport, - enum unf_act_topo active_topo); -void unf_lport_ref_dec(struct unf_lport *lport); -u32 unf_lport_ref_inc(struct unf_lport *lport); -void unf_lport_ref_dec_to_destroy(struct unf_lport *lport); -void unf_port_mgmt_deinit(void); -void unf_port_mgmt_init(void); -void unf_show_dirty_port(bool show_only, u32 *dirty_port_num); -void *unf_lookup_lport_by_nportid(void *lport, u32 nport_id); -u32 unf_is_lport_valid(struct unf_lport *lport); -int unf_lport_reset_port(struct unf_lport *lport, u32 flag); -int unf_cm_ops_handle(u32 type, void **arg_in); -u32 unf_register_scsi_host(struct unf_lport *lport); -void unf_unregister_scsi_host(struct unf_lport *lport); -void unf_destroy_scsi_id_table(struct unf_lport *lport); -u32 unf_lport_login(struct unf_lport *lport, enum unf_act_topo act_topo); -u32 unf_init_scsi_id_table(struct unf_lport *lport); -void unf_set_lport_removing(struct unf_lport *lport); -void unf_lport_release_lw_funop(struct unf_lport *lport); -void unf_show_all_rport(struct unf_lport *lport); -void unf_disc_state_ma(struct unf_lport *lport, enum unf_disc_event evnet); -int unf_get_link_lose_tmo(struct unf_lport *lport); -u32 unf_port_release_rport_index(struct unf_lport *lport, void *input); -int unf_cm_reset_port(u32 port_id); - -#endif diff --git a/drivers/scsi/spfc/common/unf_rport.c b/drivers/scsi/spfc/common/unf_rport.c deleted file mode 100644 index 9b06df884524..000000000000 --- a/drivers/scsi/spfc/common/unf_rport.c +++ /dev/null @@ -1,2286 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#include "unf_rport.h" -#include "unf_log.h" -#include "unf_exchg.h" -#include "unf_ls.h" -#include "unf_service.h" -#include "unf_portman.h" - -/* rport state:ready --->>> link_down --->>> closing --->>> timeout --->>> delete */ -struct unf_rport_feature_pool *port_feature_pool; - -void unf_sesion_loss_timeout(struct work_struct *work) -{ - struct unf_wwpn_rport_info *wwpn_rport_info = NULL; - - FC_CHECK_RETURN_VOID(work); - - wwpn_rport_info = container_of(work, struct unf_wwpn_rport_info, loss_tmo_work.work); - if (unlikely(!wwpn_rport_info)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]wwpn_rport_info is NULL"); - return; - } - - atomic_set(&wwpn_rport_info->scsi_state, UNF_SCSI_ST_DEAD); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_KEVENT, - "[info]Port(0x%x) wwpn(0x%llx) set target(0x%x) scsi state to dead", - ((struct unf_lport *)(wwpn_rport_info->lport))->port_id, - wwpn_rport_info->wwpn, wwpn_rport_info->target_id); -} - -u32 unf_alloc_scsi_id(struct unf_lport *lport, struct unf_rport *rport) -{ - struct unf_rport_scsi_id_image *rport_scsi_table = NULL; - struct unf_wwpn_rport_info *wwn_rport_info = NULL; - ulong flags = 0; - u32 index = 0; - u32 ret = UNF_RETURN_ERROR; - spinlock_t *rport_scsi_tb_lock = NULL; - - rport_scsi_table = &lport->rport_scsi_table; - rport_scsi_tb_lock = &rport_scsi_table->scsi_image_table_lock; - spin_lock_irqsave(rport_scsi_tb_lock, flags); - - /* 1. At first, existence check */ - for (index = 0; index < rport_scsi_table->max_scsi_id; index++) { - wwn_rport_info = &rport_scsi_table->wwn_rport_info_table[index]; - if (rport->port_name == wwn_rport_info->wwpn) { - spin_unlock_irqrestore(rport_scsi_tb_lock, flags); - UNF_DELAYED_WORK_SYNC(ret, (lport->port_id), - (&wwn_rport_info->loss_tmo_work), - "loss tmo Timer work"); - - /* Plug case: reuse again */ - spin_lock_irqsave(rport_scsi_tb_lock, flags); - wwn_rport_info->rport = rport; - wwn_rport_info->las_ten_scsi_state = - atomic_read(&wwn_rport_info->scsi_state); - atomic_set(&wwn_rport_info->scsi_state, UNF_SCSI_ST_ONLINE); - spin_unlock_irqrestore(rport_scsi_tb_lock, flags); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x) find the same scsi_id(0x%x) by wwpn(0x%llx) RPort(%p) N_Port_ID(0x%x)", - lport->port_id, index, wwn_rport_info->wwpn, rport, - rport->nport_id); - - atomic_inc(&lport->resume_scsi_id); - goto find; - } - } - - /* 2. Alloc new SCSI ID */ - for (index = 0; index < rport_scsi_table->max_scsi_id; index++) { - wwn_rport_info = &rport_scsi_table->wwn_rport_info_table[index]; - if (wwn_rport_info->wwpn == INVALID_WWPN) { - spin_unlock_irqrestore(rport_scsi_tb_lock, flags); - UNF_DELAYED_WORK_SYNC(ret, (lport->port_id), - (&wwn_rport_info->loss_tmo_work), - "loss tmo Timer work"); - /* Use the free space */ - spin_lock_irqsave(rport_scsi_tb_lock, flags); - wwn_rport_info->rport = rport; - wwn_rport_info->wwpn = rport->port_name; - wwn_rport_info->las_ten_scsi_state = - atomic_read(&wwn_rport_info->scsi_state); - atomic_set(&wwn_rport_info->scsi_state, UNF_SCSI_ST_ONLINE); - spin_unlock_irqrestore(rport_scsi_tb_lock, flags); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x) allco new scsi_id(0x%x) by wwpn(0x%llx) RPort(%p) N_Port_ID(0x%x)", - lport->port_id, index, wwn_rport_info->wwpn, rport, - rport->nport_id); - - atomic_inc(&lport->alloc_scsi_id); - goto find; - } - } - - /* 3. Reuse space has been used */ - for (index = 0; index < rport_scsi_table->max_scsi_id; index++) { - wwn_rport_info = &rport_scsi_table->wwn_rport_info_table[index]; - if (atomic_read(&wwn_rport_info->scsi_state) == UNF_SCSI_ST_DEAD) { - spin_unlock_irqrestore(rport_scsi_tb_lock, flags); - UNF_DELAYED_WORK_SYNC(ret, (lport->port_id), - (&wwn_rport_info->loss_tmo_work), - "loss tmo Timer work"); - - spin_lock_irqsave(rport_scsi_tb_lock, flags); - if (wwn_rport_info->dfx_counter) { - memset(wwn_rport_info->dfx_counter, 0, - sizeof(struct unf_wwpn_dfx_counter_info)); - } - if (wwn_rport_info->lun_qos_level) { - memset(wwn_rport_info->lun_qos_level, 0, - sizeof(u8) * UNF_MAX_LUN_PER_TARGET); - } - wwn_rport_info->rport = rport; - wwn_rport_info->wwpn = rport->port_name; - wwn_rport_info->las_ten_scsi_state = - atomic_read(&wwn_rport_info->scsi_state); - atomic_set(&wwn_rport_info->scsi_state, UNF_SCSI_ST_ONLINE); - spin_unlock_irqrestore(rport_scsi_tb_lock, flags); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[info]Port(0x%x) reuse a dead scsi_id(0x%x) by wwpn(0x%llx) RPort(%p) N_Port_ID(0x%x)", - lport->port_id, index, wwn_rport_info->wwpn, rport, - rport->nport_id); - - atomic_inc(&lport->reuse_scsi_id); - goto find; - } - } - - spin_unlock_irqrestore(rport_scsi_tb_lock, flags); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) there is not enough scsi_id with max_value(0x%x)", - lport->port_id, index); - - return INVALID_VALUE32; - -find: - if (!wwn_rport_info->dfx_counter) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_INFO, - "[info]Port(0x%x) allocate Rport(0x%x) DFX buffer", - lport->port_id, wwn_rport_info->rport->nport_id); - wwn_rport_info->dfx_counter = vmalloc(sizeof(struct unf_wwpn_dfx_counter_info)); - if (!wwn_rport_info->dfx_counter) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Port(0x%x) allocate DFX buffer fail", - lport->port_id); - - return INVALID_VALUE32; - } - - memset(wwn_rport_info->dfx_counter, 0, sizeof(struct unf_wwpn_dfx_counter_info)); - } - - return index; -} - -u32 unf_get_scsi_id_by_wwpn(struct unf_lport *lport, u64 wwpn) -{ - struct unf_rport_scsi_id_image *rport_scsi_table = NULL; - struct unf_wwpn_rport_info *wwn_rport_info = NULL; - ulong flags = 0; - u32 index = 0; - spinlock_t *rport_scsi_tb_lock = NULL; - - FC_CHECK_RETURN_VALUE(lport, INVALID_VALUE32); - rport_scsi_table = &lport->rport_scsi_table; - rport_scsi_tb_lock = &rport_scsi_table->scsi_image_table_lock; - - if (wwpn == 0) - return INVALID_VALUE32; - - spin_lock_irqsave(rport_scsi_tb_lock, flags); - - for (index = 0; index < rport_scsi_table->max_scsi_id; index++) { - wwn_rport_info = &rport_scsi_table->wwn_rport_info_table[index]; - if (wwn_rport_info->wwpn == wwpn) { - spin_unlock_irqrestore(rport_scsi_tb_lock, flags); - return index; - } - } - - spin_unlock_irqrestore(rport_scsi_tb_lock, flags); - - return INVALID_VALUE32; -} - -void unf_set_device_state(struct unf_lport *lport, u32 scsi_id, int scsi_state) -{ - struct unf_rport_scsi_id_image *scsi_image_table = NULL; - struct unf_wwpn_rport_info *wwpn_rport_info = NULL; - - if (unlikely(scsi_id >= UNF_MAX_SCSI_ID)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) RPort scsi_id(0x%x) is max than 0x%x", - lport->port_id, scsi_id, UNF_MAX_SCSI_ID); - return; - } - - scsi_image_table = &lport->rport_scsi_table; - wwpn_rport_info = &scsi_image_table->wwn_rport_info_table[scsi_id]; - atomic_set(&wwpn_rport_info->scsi_state, scsi_state); -} - -void unf_rport_linkdown(struct unf_lport *lport, struct unf_rport *rport) -{ - /* - * 1. port_logout - * 2. rcvd_rscn_port_not_in_disc - * 3. each_rport_after_rscn - * 4. rcvd_gpnid_rjt - * 5. rport_after_logout(rport is fabric port) - */ - ulong flag = 0; - - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(rport); - - /* 1. Update R_Port state: Link Down Event --->>> closing state */ - spin_lock_irqsave(&rport->rport_state_lock, flag); - unf_rport_state_ma(rport, UNF_EVENT_RPORT_LINK_DOWN); - spin_unlock_irqrestore(&rport->rport_state_lock, flag); - - /* 3. Port enter closing (then enter to Delete) process */ - unf_rport_enter_closing(rport); -} - -static struct unf_rport *unf_rport_is_changed(struct unf_lport *lport, - struct unf_rport *rport, u32 sid) -{ - if (rport) { - /* S_ID or D_ID has been changed */ - if (rport->nport_id != sid || rport->local_nport_id != lport->nport_id) { - /* 1. Swap case: (SID or DID changed): Report link down - * & delete immediately - */ - unf_rport_immediate_link_down(lport, rport); - return NULL; - } - } - - return rport; -} - -struct unf_rport *unf_rport_set_qualifier_key_reuse(struct unf_lport *lport, - struct unf_rport *rport_by_nport_id, - struct unf_rport *rport_by_wwpn, - u64 wwpn, u32 sid) -{ - /* Used for SPFC Chip */ - struct unf_rport *rport = NULL; - struct unf_rport *rporta = NULL; - struct unf_rport *rportb = NULL; - bool wwpn_flag = false; - - FC_CHECK_RETURN_VALUE(lport, NULL); - - /* About R_Port by N_Port_ID */ - rporta = unf_rport_is_changed(lport, rport_by_nport_id, sid); - - /* About R_Port by WWpn */ - rportb = unf_rport_is_changed(lport, rport_by_wwpn, sid); - - if (!rporta && !rportb) { - return NULL; - } else if (!rporta && rportb) { - /* 3. Plug case: reuse again */ - rport = rportb; - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x) RPort(0x%p) WWPN(0x%llx) S_ID(0x%x) D_ID(0x%x) reused by wwpn", - lport->port_id, rport, rport->port_name, - rport->nport_id, rport->local_nport_id); - - return rport; - } else if (rporta && !rportb) { - wwpn_flag = (rporta->port_name != wwpn && rporta->port_name != 0 && - rporta->port_name != INVALID_VALUE64); - if (wwpn_flag) { - /* 4. WWPN changed: Report link down & delete - * immediately - */ - unf_rport_immediate_link_down(lport, rporta); - return NULL; - } - - /* Updtae WWPN */ - rporta->port_name = wwpn; - rport = rporta; - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x) RPort(0x%p) WWPN(0x%llx) S_ID(0x%x) D_ID(0x%x) reused by N_Port_ID", - lport->port_id, rport, rport->port_name, - rport->nport_id, rport->local_nport_id); - - return rport; - } - - /* 5. Case for A == B && A != NULL && B != NULL */ - if (rportb == rporta) { - rport = rporta; - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x) find the same RPort(0x%p) WWPN(0x%llx) S_ID(0x%x) D_ID(0x%x)", - lport->port_id, rport, rport->port_name, rport->nport_id, - rport->local_nport_id); - - return rport; - } - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) find two duplicate login. RPort(A:0x%p, WWPN:0x%llx, S_ID:0x%x, D_ID:0x%x) RPort(B:0x%p, WWPN:0x%llx, S_ID:0x%x, D_ID:0x%x)", - lport->port_id, rporta, rporta->port_name, rporta->nport_id, - rporta->local_nport_id, rportb, rportb->port_name, rportb->nport_id, - rportb->local_nport_id); - - /* 6. Case for A != B && A != NULL && B != NULL: Immediate - * Report && Deletion - */ - unf_rport_immediate_link_down(lport, rporta); - unf_rport_immediate_link_down(lport, rportb); - - return NULL; -} - -struct unf_rport *unf_find_valid_rport(struct unf_lport *lport, u64 wwpn, u32 sid) -{ - struct unf_rport *rport = NULL; - struct unf_rport *rport_by_nport_id = NULL; - struct unf_rport *rport_by_wwpn = NULL; - ulong flags = 0; - spinlock_t *rport_state_lock = NULL; - - FC_CHECK_RETURN_VALUE(lport, NULL); - FC_CHECK_RETURN_VALUE(lport->unf_qualify_rport, NULL); - - /* Get R_Port by WWN & N_Port_ID */ - rport_by_nport_id = unf_get_rport_by_nport_id(lport, sid); - rport_by_wwpn = unf_get_rport_by_wwn(lport, wwpn); - rport_state_lock = &rport_by_wwpn->rport_state_lock; - - /* R_Port check: by WWPN */ - if (rport_by_wwpn) { - spin_lock_irqsave(rport_state_lock, flags); - if (rport_by_wwpn->nport_id == UNF_FC_FID_FLOGI) { - spin_unlock_irqrestore(rport_state_lock, flags); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "[info]Port(0x%x) RPort(0x%p) find by WWPN(0x%llx) is invalid", - lport->port_id, rport_by_wwpn, wwpn); - - rport_by_wwpn = NULL; - } else { - spin_unlock_irqrestore(rport_state_lock, flags); - } - } - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x_0x%x) RPort(0x%p) find by N_Port_ID(0x%x) and RPort(0x%p) by WWPN(0x%llx)", - lport->port_id, lport->nport_id, rport_by_nport_id, sid, rport_by_wwpn, wwpn); - - /* R_Port validity check: get by WWPN & N_Port_ID */ - rport = lport->unf_qualify_rport(lport, rport_by_nport_id, - rport_by_wwpn, wwpn, sid); - - return rport; -} - -void unf_rport_delay_login(struct unf_rport *rport) -{ - FC_CHECK_RETURN_VOID(rport); - - /* Do R_Port recovery: PLOGI or PRLI or LOGO */ - unf_rport_error_recovery(rport); -} - -void unf_rport_enter_logo(struct unf_lport *lport, struct unf_rport *rport) -{ - /* - * 1. TMF/ABTS timeout recovery :Y - * 2. L_Port error recovery --->>> larger than retry_count :Y - * 3. R_Port error recovery --->>> larger than retry_count :Y - * 4. Check PLOGI parameter --->>> parameter is error :Y - * 5. PRLI handler --->>> R_Port state is error :Y - * 6. PDISC handler --->>> R_Port state is not PRLI_WAIT :Y - * 7. ADISC handler --->>> R_Port state is not PRLI_WAIT :Y - * 8. PLOGI wait timeout with R_PORT is INI mode :Y - * 9. RCVD GFFID_RJT --->>> R_Port state is INIT :Y - * 10. RCVD GPNID_ACC --->>> R_Port state is error :Y - * 11. Private Loop mode with LOGO case :Y - * 12. P2P mode with LOGO case :Y - * 13. Fabric mode with LOGO case :Y - * 14. RCVD PRLI_ACC with R_Port is INI :Y - * 15. TGT RCVD BLS_REQ with session is error :Y - */ - ulong flags = 0; - - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(rport); - - spin_lock_irqsave(&rport->rport_state_lock, flags); - - if (rport->rp_state == UNF_RPORT_ST_CLOSING || - rport->rp_state == UNF_RPORT_ST_DELETE) { - /* 1. Already within Closing or Delete: Do nothing */ - spin_unlock_irqrestore(&rport->rport_state_lock, flags); - - return; - } else if (rport->rp_state == UNF_RPORT_ST_LOGO) { - /* 2. Update R_Port state: Normal Enter Event --->>> closing - * state - */ - unf_rport_state_ma(rport, UNF_EVENT_RPORT_NORMAL_ENTER); - spin_unlock_irqrestore(&rport->rport_state_lock, flags); - - /* Send Logo if necessary */ - if (unf_send_logo(lport, rport) != RETURN_OK) - unf_rport_enter_closing(rport); - } else { - /* 3. Update R_Port state: Link Down Event --->>> closing state - */ - unf_rport_state_ma(rport, UNF_EVENT_RPORT_LINK_DOWN); - spin_unlock_irqrestore(&rport->rport_state_lock, flags); - - unf_rport_enter_closing(rport); - } -} - -u32 unf_free_scsi_id(struct unf_lport *lport, u32 scsi_id) -{ - ulong flags = 0; - struct unf_rport_scsi_id_image *rport_scsi_table = NULL; - struct unf_wwpn_rport_info *wwn_rport_info = NULL; - spinlock_t *rport_scsi_tb_lock = NULL; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - - if (unlikely(lport->port_removing)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x_0x%x) is removing and do nothing", - lport->port_id, lport->nport_id); - - return UNF_RETURN_ERROR; - } - - if (unlikely(scsi_id >= UNF_MAX_SCSI_ID)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x_0x%x) scsi_id(0x%x) is bigger than %d", - lport->port_id, lport->nport_id, scsi_id, UNF_MAX_SCSI_ID); - - return UNF_RETURN_ERROR; - } - - rport_scsi_table = &lport->rport_scsi_table; - rport_scsi_tb_lock = &rport_scsi_table->scsi_image_table_lock; - if (rport_scsi_table->wwn_rport_info_table) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "[warn]Port(0x%x_0x%x) RPort(0x%p) free scsi_id(0x%x) wwpn(0x%llx) target_id(0x%x) succeed", - lport->port_id, lport->nport_id, - rport_scsi_table->wwn_rport_info_table[scsi_id].rport, - scsi_id, rport_scsi_table->wwn_rport_info_table[scsi_id].wwpn, - rport_scsi_table->wwn_rport_info_table[scsi_id].target_id); - - spin_lock_irqsave(rport_scsi_tb_lock, flags); - wwn_rport_info = &rport_scsi_table->wwn_rport_info_table[scsi_id]; - if (wwn_rport_info->rport) { - wwn_rport_info->rport->rport = NULL; - wwn_rport_info->rport = NULL; - } - wwn_rport_info->target_id = INVALID_VALUE32; - atomic_set(&wwn_rport_info->scsi_state, UNF_SCSI_ST_DEAD); - - /* NOTE: remain WWPN/Port_Name unchanged(un-cleared) */ - spin_unlock_irqrestore(rport_scsi_tb_lock, flags); - - return RETURN_OK; - } - - return UNF_RETURN_ERROR; -} - -static void unf_report_ini_linkwown_event(struct unf_lport *lport, struct unf_rport *rport) -{ - u32 scsi_id = 0; - struct fc_rport *unf_rport = NULL; - ulong flag = 0; - - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(rport); - - /* - * 1. set local device(rport/rport_info_table) state - * -------------------------------------------------OFF_LINE - * * - * about rport->scsi_id - * valid during rport link up to link down - */ - - spin_lock_irqsave(&rport->rport_state_lock, flag); - scsi_id = rport->scsi_id; - unf_set_device_state(lport, scsi_id, UNF_SCSI_ST_OFFLINE); - - /* 2. delete scsi's rport */ - unf_rport = (struct fc_rport *)rport->rport; - spin_unlock_irqrestore(&rport->rport_state_lock, flag); - if (unf_rport) { - fc_remote_port_delete(unf_rport); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_KEVENT, - "[event]Port(0x%x_0x%x) delete RPort(0x%x) wwpn(0x%llx) scsi_id(0x%x) succeed", - lport->port_id, lport->nport_id, rport->nport_id, - rport->port_name, scsi_id); - - atomic_inc(&lport->scsi_session_del_success); - } else { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_KEVENT, - "[warn]Port(0x%x_0x%x) delete RPort(0x%x_0x%p) failed", - lport->port_id, lport->nport_id, rport->nport_id, rport); - } -} - -static void unf_report_ini_linkup_event(struct unf_lport *lport, struct unf_rport *rport) -{ - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(rport); - - FC_DRV_PRINT(UNF_LOG_NORMAL, UNF_MAJOR, - "[event]Port(0x%x) RPort(0x%x_0x%p) put INI link up work(%p) to work_queue", - lport->port_id, rport->nport_id, rport, &rport->start_work); - - if (unlikely(!queue_work(lport->link_event_wq, &rport->start_work))) { - atomic_inc(&lport->add_start_work_failed); - - FC_DRV_PRINT(UNF_LOG_NORMAL, UNF_ERR, - "[err]Port(0x%x) RPort(0x%x_0x%p) put INI link up to work_queue failed", - lport->port_id, rport->nport_id, rport); - } -} - -void unf_update_lport_state_by_linkup_event(struct unf_lport *lport, - struct unf_rport *rport, - u32 rport_att) -{ - /* Report R_Port Link Up/Down Event */ - ulong flag = 0; - enum unf_port_state lport_state = 0; - - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(rport); - - spin_lock_irqsave(&rport->rport_state_lock, flag); - - /* 1. R_Port does not has TGT mode any more */ - if (((rport_att & UNF_FC4_FRAME_PARM_3_TGT) == 0) && - rport->lport_ini_state == UNF_PORT_STATE_LINKUP) { - rport->last_lport_ini_state = rport->lport_ini_state; - rport->lport_ini_state = UNF_PORT_STATE_LINKDOWN; - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) RPort(0x%x) does not have TGT attribute(0x%x) any more", - lport->port_id, rport->nport_id, rport_att); - } - - /* 2. R_Port with TGT mode, L_Port with INI mode */ - if ((rport_att & UNF_FC4_FRAME_PARM_3_TGT) && - (lport->options & UNF_FC4_FRAME_PARM_3_INI)) { - rport->last_lport_ini_state = rport->lport_ini_state; - rport->lport_ini_state = UNF_PORT_STATE_LINKUP; - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "[warn]Port(0x%x) update INI state with last(0x%x) and now(0x%x)", - lport->port_id, rport->last_lport_ini_state, - rport->lport_ini_state); - } - - /* 3. Report L_Port INI/TGT Down/Up event to SCSI */ - if (rport->last_lport_ini_state == rport->lport_ini_state) { - if (rport->nport_id < UNF_FC_FID_DOM_MGR) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) RPort(0x%x %p) INI state(0x%x) has not been changed", - lport->port_id, rport->nport_id, rport, - rport->lport_ini_state); - } - - spin_unlock_irqrestore(&rport->rport_state_lock, flag); - - return; - } - - lport_state = rport->lport_ini_state; - - spin_unlock_irqrestore(&rport->rport_state_lock, flag); - - switch (lport_state) { - case UNF_PORT_STATE_LINKDOWN: - unf_report_ini_linkwown_event(lport, rport); - break; - case UNF_PORT_STATE_LINKUP: - unf_report_ini_linkup_event(lport, rport); - break; - default: - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) with unknown link status(0x%x)", - lport->port_id, rport->lport_ini_state); - break; - } -} - -static void unf_rport_callback(void *rport, void *lport, u32 result) -{ - struct unf_rport *unf_rport = NULL; - struct unf_lport *unf_lport = NULL; - ulong flag = 0; - - FC_CHECK_RETURN_VOID(rport); - FC_CHECK_RETURN_VOID(lport); - unf_rport = (struct unf_rport *)rport; - unf_lport = (struct unf_lport *)lport; - - spin_lock_irqsave(&unf_rport->rport_state_lock, flag); - unf_rport->last_lport_ini_state = unf_rport->lport_ini_state; - unf_rport->lport_ini_state = UNF_PORT_STATE_LINKDOWN; - unf_rport->last_lport_tgt_state = unf_rport->lport_tgt_state; - unf_rport->lport_tgt_state = UNF_PORT_STATE_LINKDOWN; - - /* Report R_Port Link Down Event to scsi */ - if (unf_rport->last_lport_ini_state == unf_rport->lport_ini_state) { - if (unf_rport->nport_id < UNF_FC_FID_DOM_MGR) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) RPort(0x%x %p) INI state(0x%x) has not been changed", - unf_lport->port_id, unf_rport->nport_id, - unf_rport, unf_rport->lport_ini_state); - } - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flag); - - return; - } - - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flag); - - unf_report_ini_linkwown_event(unf_lport, unf_rport); -} - -static void unf_rport_recovery_timeout(struct work_struct *work) -{ - struct unf_lport *lport = NULL; - struct unf_rport *rport = NULL; - u32 ret = RETURN_OK; - ulong flag = 0; - enum unf_rport_login_state rp_state = UNF_RPORT_ST_INIT; - - FC_CHECK_RETURN_VOID(work); - - rport = container_of(work, struct unf_rport, recovery_work.work); - if (unlikely(!rport)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]RPort is NULL"); - - return; - } - - lport = rport->lport; - if (unlikely(!lport)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]RPort(0x%x) Port is NULL", rport->nport_id); - - /* for timer */ - unf_rport_ref_dec(rport); - return; - } - - spin_lock_irqsave(&rport->rport_state_lock, flag); - rp_state = rport->rp_state; - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x_0x%x) RPort(0x%x) state(0x%x) recovery timer timeout", - lport->port_id, lport->nport_id, rport->nport_id, rp_state); - spin_unlock_irqrestore(&rport->rport_state_lock, flag); - - switch (rp_state) { - case UNF_RPORT_ST_PLOGI_WAIT: - if ((lport->act_topo == UNF_ACT_TOP_P2P_DIRECT && - lport->port_name > rport->port_name) || - lport->act_topo != UNF_ACT_TOP_P2P_DIRECT) { - /* P2P: Name is master with P2P_D - * or has INI Mode - */ - ret = unf_send_plogi(rport->lport, rport); - } - break; - case UNF_RPORT_ST_PRLI_WAIT: - ret = unf_send_prli(rport->lport, rport, ELS_PRLI); - if (ret != RETURN_OK) - unf_rport_error_recovery(rport); - fallthrough; - default: - break; - } - - if (ret != RETURN_OK) - unf_rport_error_recovery(rport); - - /* company with timer */ - unf_rport_ref_dec(rport); -} - -void unf_schedule_closing_work(struct unf_lport *lport, struct unf_rport *rport) -{ - ulong flags = 0; - struct unf_rport_scsi_id_image *rport_scsi_table = NULL; - struct unf_wwpn_rport_info *wwn_rport_info = NULL; - u32 scsi_id = 0; - u32 ret = 0; - u32 delay = 0; - - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(rport); - - delay = (u32)(unf_get_link_lose_tmo(lport) * 1000); - - rport_scsi_table = &lport->rport_scsi_table; - scsi_id = rport->scsi_id; - spin_lock_irqsave(&rport->rport_state_lock, flags); - - /* 1. Cancel recovery_work */ - if (cancel_delayed_work(&rport->recovery_work)) { - atomic_dec(&rport->rport_ref_cnt); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x_0x%x) RPort(0x%x_0x%p) cancel recovery work succeed", - lport->port_id, lport->nport_id, rport->nport_id, rport); - } - - /* 2. Cancel Open_work */ - if (cancel_delayed_work(&rport->open_work)) { - atomic_dec(&rport->rport_ref_cnt); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x_0x%x) RPort(0x%x_0x%p) cancel open work succeed", - lport->port_id, lport->nport_id, rport->nport_id, rport); - } - - spin_unlock_irqrestore(&rport->rport_state_lock, flags); - - /* 3. Work in-queue (switch to thread context) */ - if (!queue_work(lport->link_event_wq, &rport->closing_work)) { - FC_DRV_PRINT(UNF_LOG_NORMAL, UNF_ERR, - "[warn]Port(0x%x) RPort(0x%x_0x%p) add link down to work queue failed", - lport->port_id, rport->nport_id, rport); - - atomic_inc(&lport->add_closing_work_failed); - } else { - spin_lock_irqsave(&rport->rport_state_lock, flags); - (void)unf_rport_ref_inc(rport); - spin_unlock_irqrestore(&rport->rport_state_lock, flags); - - FC_DRV_PRINT(UNF_LOG_NORMAL, UNF_MAJOR, - "[info]Port(0x%x) RPort(0x%x_0x%p) add link down to work(%p) queue succeed", - lport->port_id, rport->nport_id, rport, - &rport->closing_work); - } - - if (rport->nport_id > UNF_FC_FID_DOM_MGR) - return; - - if (scsi_id >= UNF_MAX_SCSI_ID) { - scsi_id = unf_get_scsi_id_by_wwpn(lport, rport->port_name); - if (scsi_id >= UNF_MAX_SCSI_ID) { - FC_DRV_PRINT(UNF_LOG_NORMAL, UNF_WARN, - "[warn]Port(0x%x) RPort(0x%p) NPortId(0x%x) wwpn(0x%llx) option(0x%x) scsi_id(0x%x) is max than(0x%x)", - lport->port_id, rport, rport->nport_id, - rport->port_name, rport->options, scsi_id, - UNF_MAX_SCSI_ID); - - return; - } - } - - wwn_rport_info = &rport_scsi_table->wwn_rport_info_table[scsi_id]; - ret = queue_delayed_work(unf_wq, &wwn_rport_info->loss_tmo_work, - (ulong)msecs_to_jiffies((u32)delay)); - if (!ret) { - FC_DRV_PRINT(UNF_LOG_NORMAL, UNF_MAJOR, - "[info] Port(0x%x) add RPort(0x%p) NPortId(0x%x) scsi_id(0x%x) wwpn(0x%llx) loss timeout work failed", - lport->port_id, rport, rport->nport_id, scsi_id, - rport->port_name); - } -} - -static void unf_rport_closing_timeout(struct work_struct *work) -{ - /* closing --->>>(timeout)--->>> delete */ - struct unf_rport *rport = NULL; - struct unf_lport *lport = NULL; - struct unf_disc *disc = NULL; - ulong rport_flag = 0; - ulong disc_flag = 0; - void (*unf_rport_callback)(void *, void *, u32) = NULL; - enum unf_rport_login_state old_state; - - FC_CHECK_RETURN_VOID(work); - - /* Get R_Port & L_Port & Disc */ - rport = container_of(work, struct unf_rport, closing_work); - if (unlikely(!rport)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]RPort is NULL"); - return; - } - - lport = rport->lport; - if (unlikely(!lport)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]RPort(0x%x_0x%p) Port is NULL", - rport->nport_id, rport); - - /* Release directly (for timer) */ - unf_rport_ref_dec(rport); - return; - } - disc = &lport->disc; - - spin_lock_irqsave(&rport->rport_state_lock, rport_flag); - - old_state = rport->rp_state; - /* 1. Update R_Port state: event_timeout --->>> state_delete */ - unf_rport_state_ma(rport, UNF_EVENT_RPORT_CLS_TIMEOUT); - - /* Check R_Port state */ - if (rport->rp_state != UNF_RPORT_ST_DELETE) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x_0x%x) RPort(0x%x_0x%p) closing timeout with error state(0x%x->0x%x)", - lport->port_id, lport->nport_id, rport->nport_id, - rport, old_state, rport->rp_state); - - spin_unlock_irqrestore(&rport->rport_state_lock, rport_flag); - - /* Dec ref_cnt for timer */ - unf_rport_ref_dec(rport); - return; - } - - unf_rport_callback = rport->unf_rport_callback; - spin_unlock_irqrestore(&rport->rport_state_lock, rport_flag); - - /* 2. Put R_Port to delete list */ - spin_lock_irqsave(&disc->rport_busy_pool_lock, disc_flag); - list_del_init(&rport->entry_rport); - list_add_tail(&rport->entry_rport, &disc->list_delete_rports); - spin_unlock_irqrestore(&disc->rport_busy_pool_lock, disc_flag); - - /* 3. Report rport link down event to scsi */ - if (unf_rport_callback) { - unf_rport_callback((void *)rport, (void *)rport->lport, RETURN_OK); - } else { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]RPort(0x%x) callback is NULL", - rport->nport_id); - } - - /* 4. Remove/delete R_Port */ - unf_rport_ref_dec(rport); - unf_rport_ref_dec(rport); -} - -static void unf_rport_linkup_to_scsi(struct work_struct *work) -{ - struct fc_rport_identifiers rport_ids; - struct fc_rport *rport = NULL; - ulong flags = RETURN_OK; - struct unf_wwpn_rport_info *wwn_rport_info = NULL; - struct unf_rport_scsi_id_image *rport_scsi_table = NULL; - u32 scsi_id = 0; - - struct unf_lport *lport = NULL; - struct unf_rport *unf_rport = NULL; - - FC_CHECK_RETURN_VOID(work); - - unf_rport = container_of(work, struct unf_rport, start_work); - if (unlikely(!unf_rport)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]RPort is NULL for work(%p)", work); - return; - } - - lport = unf_rport->lport; - if (unlikely(!lport)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]RPort(0x%x_0x%p) Port is NULL", - unf_rport->nport_id, unf_rport); - return; - } - - /* 1. Alloc R_Port SCSI_ID (image table) */ - unf_rport->scsi_id = unf_alloc_scsi_id(lport, unf_rport); - if (unlikely(unf_rport->scsi_id == INVALID_VALUE32)) { - atomic_inc(&lport->scsi_session_add_failed); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[err]Port(0x%x_0x%x) RPort(0x%x_0x%p) wwpn(0x%llx) scsi_id(0x%x) is invalid", - lport->port_id, lport->nport_id, - unf_rport->nport_id, unf_rport, - unf_rport->port_name, unf_rport->scsi_id); - - /* NOTE: return */ - return; - } - - /* 2. Add rport to scsi */ - scsi_id = unf_rport->scsi_id; - rport_ids.node_name = unf_rport->node_name; - rport_ids.port_name = unf_rport->port_name; - rport_ids.port_id = unf_rport->nport_id; - rport_ids.roles = FC_RPORT_ROLE_UNKNOWN; - rport = fc_remote_port_add(lport->host_info.host, 0, &rport_ids); - if (unlikely(!rport)) { - atomic_inc(&lport->scsi_session_add_failed); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x_0x%x) RPort(0x%x_0x%p) wwpn(0x%llx) report link up to scsi failed", - lport->port_id, lport->nport_id, unf_rport->nport_id, unf_rport, - unf_rport->port_name); - - unf_free_scsi_id(lport, scsi_id); - return; - } - - /* 3. Change rport role */ - *((u32 *)rport->dd_data) = scsi_id; /* save local SCSI_ID to scsi rport */ - rport->supported_classes = FC_COS_CLASS3; - rport_ids.roles |= FC_PORT_ROLE_FCP_TARGET; - rport->dev_loss_tmo = (u32)unf_get_link_lose_tmo(lport); /* default 30s */ - fc_remote_port_rolechg(rport, rport_ids.roles); - - /* 4. Save scsi rport info to local R_Port */ - spin_lock_irqsave(&unf_rport->rport_state_lock, flags); - unf_rport->rport = rport; - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flags); - - rport_scsi_table = &lport->rport_scsi_table; - spin_lock_irqsave(&rport_scsi_table->scsi_image_table_lock, flags); - wwn_rport_info = &rport_scsi_table->wwn_rport_info_table[scsi_id]; - wwn_rport_info->target_id = rport->scsi_target_id; - wwn_rport_info->rport = unf_rport; - atomic_set(&wwn_rport_info->scsi_state, UNF_SCSI_ST_ONLINE); - spin_unlock_irqrestore(&rport_scsi_table->scsi_image_table_lock, flags); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_KEVENT, - "[event]Port(0x%x_0x%x) RPort(0x%x) wwpn(0x%llx) scsi_id(0x%x) link up to scsi succeed", - lport->port_id, lport->nport_id, unf_rport->nport_id, - unf_rport->port_name, scsi_id); - - atomic_inc(&lport->scsi_session_add_success); -} - -static void unf_rport_open_timeout(struct work_struct *work) -{ - struct unf_rport *rport = NULL; - struct unf_lport *lport = NULL; - ulong flags = 0; - - FC_CHECK_RETURN_VOID(work); - - rport = container_of(work, struct unf_rport, open_work.work); - if (!rport) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, - UNF_WARN, "[warn]RPort is NULL"); - - return; - } - - spin_lock_irqsave(&rport->rport_state_lock, flags); - lport = rport->lport; - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x_0x%x) RPort(0x%x) open work timeout with state(0x%x)", - lport->port_id, lport->nport_id, rport->nport_id, - rport->rp_state); - - /* NOTE: R_Port state check */ - if (rport->rp_state != UNF_RPORT_ST_PRLI_WAIT) { - spin_unlock_irqrestore(&rport->rport_state_lock, flags); - - /* Dec ref_cnt for timer case */ - unf_rport_ref_dec(rport); - return; - } - - /* Report R_Port Link Down event */ - unf_rport_state_ma(rport, UNF_EVENT_RPORT_LINK_DOWN); - spin_unlock_irqrestore(&rport->rport_state_lock, flags); - - unf_rport_enter_closing(rport); - /* Dec ref_cnt for timer case */ - unf_rport_ref_dec(rport); -} - -static u32 unf_alloc_index_for_rport(struct unf_lport *lport, struct unf_rport *rport) -{ - ulong rport_flag = 0; - ulong pool_flag = 0; - u32 alloc_indx = 0; - u32 max_rport = 0; - struct unf_rport_pool *rport_pool = NULL; - spinlock_t *rport_scsi_tb_lock = NULL; - - rport_pool = &lport->rport_pool; - rport_scsi_tb_lock = &rport_pool->rport_free_pool_lock; - max_rport = lport->low_level_func.lport_cfg_items.max_login; - - max_rport = max_rport > SPFC_DEFAULT_RPORT_INDEX ? SPFC_DEFAULT_RPORT_INDEX : max_rport; - - spin_lock_irqsave(rport_scsi_tb_lock, pool_flag); - while (alloc_indx < max_rport) { - if (!test_bit((int)alloc_indx, rport_pool->rpi_bitmap)) { - /* Case for SPFC */ - if (unlikely(atomic_read(&lport->lport_no_operate_flag) == UNF_LPORT_NOP)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) is within NOP", lport->port_id); - - spin_unlock_irqrestore(rport_scsi_tb_lock, pool_flag); - return UNF_RETURN_ERROR; - } - - spin_lock_irqsave(&rport->rport_state_lock, rport_flag); - rport->rport_index = alloc_indx; - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "[info]Port(0x%x) RPort(0x%x) alloc index(0x%x) succeed", - lport->port_id, alloc_indx, rport->nport_id); - - spin_unlock_irqrestore(&rport->rport_state_lock, rport_flag); - - /* Set (index) bit */ - set_bit((int)alloc_indx, rport_pool->rpi_bitmap); - - /* Break here */ - break; - } - alloc_indx++; - } - spin_unlock_irqrestore(rport_scsi_tb_lock, pool_flag); - - if (max_rport == alloc_indx) - return UNF_RETURN_ERROR; - return RETURN_OK; -} - -static void unf_check_rport_pool_status(struct unf_lport *lport) -{ - struct unf_lport *unf_lport = lport; - struct unf_rport_pool *rport_pool = NULL; - ulong flags = 0; - u32 max_rport = 0; - - FC_CHECK_RETURN_VOID(lport); - rport_pool = &unf_lport->rport_pool; - - spin_lock_irqsave(&rport_pool->rport_free_pool_lock, flags); - max_rport = unf_lport->low_level_func.lport_cfg_items.max_login; - if (rport_pool->rport_pool_completion && - rport_pool->rport_pool_count == max_rport) { - complete(rport_pool->rport_pool_completion); - } - - spin_unlock_irqrestore(&rport_pool->rport_free_pool_lock, flags); -} - -static void unf_init_rport_sq_num(struct unf_rport *rport, struct unf_lport *lport) -{ - u32 session_order; - u32 ssq_average_session_num; - - ssq_average_session_num = (lport->max_ssq_num - 1) / UNF_SQ_NUM_PER_SESSION; - session_order = (rport->rport_index) % ssq_average_session_num; - rport->sqn_base = (session_order * UNF_SQ_NUM_PER_SESSION); -} - -void unf_init_rport_params(struct unf_rport *rport, struct unf_lport *lport) -{ - struct unf_rport *unf_rport = rport; - ulong flag = 0; - - FC_CHECK_RETURN_VOID(unf_rport); - FC_CHECK_RETURN_VOID(lport); - - spin_lock_irqsave(&unf_rport->rport_state_lock, flag); - unf_set_rport_state(unf_rport, UNF_RPORT_ST_INIT); - unf_rport->unf_rport_callback = unf_rport_callback; - unf_rport->lport = lport; - unf_rport->fcp_conf_needed = false; - unf_rport->tape_support_needed = false; - unf_rport->max_retries = UNF_MAX_RETRY_COUNT; - unf_rport->logo_retries = 0; - unf_rport->retries = 0; - unf_rport->rscn_position = UNF_RPORT_NOT_NEED_PROCESS; - unf_rport->last_lport_ini_state = UNF_PORT_STATE_LINKDOWN; - unf_rport->lport_ini_state = UNF_PORT_STATE_LINKDOWN; - unf_rport->last_lport_tgt_state = UNF_PORT_STATE_LINKDOWN; - unf_rport->lport_tgt_state = UNF_PORT_STATE_LINKDOWN; - unf_rport->node_name = 0; - unf_rport->port_name = INVALID_WWPN; - unf_rport->disc_done = 0; - unf_rport->scsi_id = INVALID_VALUE32; - unf_rport->data_thread = NULL; - sema_init(&unf_rport->task_sema, 0); - atomic_set(&unf_rport->rport_ref_cnt, 0); - atomic_set(&unf_rport->pending_io_cnt, 0); - unf_rport->rport_alloc_jifs = jiffies; - - unf_rport->ed_tov = UNF_DEFAULT_EDTOV + 500; - unf_rport->ra_tov = UNF_DEFAULT_RATOV; - - INIT_WORK(&unf_rport->closing_work, unf_rport_closing_timeout); - INIT_WORK(&unf_rport->start_work, unf_rport_linkup_to_scsi); - INIT_DELAYED_WORK(&unf_rport->recovery_work, unf_rport_recovery_timeout); - INIT_DELAYED_WORK(&unf_rport->open_work, unf_rport_open_timeout); - - atomic_inc(&unf_rport->rport_ref_cnt); - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flag); -} - -static u32 unf_alloc_ll_rport_resource(struct unf_lport *lport, - struct unf_rport *rport, u32 nport_id) -{ - u32 ret = RETURN_OK; - struct unf_port_info rport_info = {0}; - struct list_head *node = NULL; - struct list_head *next_node = NULL; - struct unf_qos_info *qos_info = NULL; - struct unf_lport *unf_lport = NULL; - ulong flag = 0; - - unf_lport = lport->root_lport; - - if (unf_lport->low_level_func.service_op.unf_alloc_rport_res) { - spin_lock_irqsave(&lport->qos_mgr_lock, flag); - rport_info.qos_level = lport->qos_level; - list_for_each_safe(node, next_node, &lport->list_qos_head) { - qos_info = (struct unf_qos_info *)list_entry(node, struct unf_qos_info, - entry_qos_info); - - if (qos_info && qos_info->nport_id == nport_id) { - rport_info.qos_level = qos_info->qos_level; - break; - } - } - - spin_unlock_irqrestore(&lport->qos_mgr_lock, flag); - - unf_init_rport_sq_num(rport, unf_lport); - - rport->qos_level = rport_info.qos_level; - rport_info.nport_id = nport_id; - rport_info.rport_index = rport->rport_index; - rport_info.local_nport_id = lport->nport_id; - rport_info.port_name = 0; - rport_info.cs_ctrl = UNF_CSCTRL_INVALID; - rport_info.sqn_base = rport->sqn_base; - - if (unf_lport->priority == UNF_PRIORITY_ENABLE) { - if (rport_info.qos_level == UNF_QOS_LEVEL_DEFAULT) - rport_info.cs_ctrl = UNF_CSCTRL_LOW; - else if (rport_info.qos_level == UNF_QOS_LEVEL_MIDDLE) - rport_info.cs_ctrl = UNF_CSCTRL_MIDDLE; - else if (rport_info.qos_level == UNF_QOS_LEVEL_HIGH) - rport_info.cs_ctrl = UNF_CSCTRL_HIGH; - } - - ret = unf_lport->low_level_func.service_op.unf_alloc_rport_res(unf_lport->fc_port, - &rport_info); - } else { - ret = RETURN_OK; - } - - return ret; -} - -static void *unf_add_rport_to_busy_list(struct unf_lport *lport, - struct unf_rport *new_rport, - u32 nport_id) -{ - struct unf_rport_pool *rport_pool = NULL; - struct unf_lport *unf_lport = NULL; - struct unf_disc *disc = NULL; - struct unf_rport *unf_new_rport = new_rport; - struct unf_rport *old_rport = NULL; - struct list_head *node = NULL; - struct list_head *next_node = NULL; - ulong flag = 0; - spinlock_t *rport_free_lock = NULL; - spinlock_t *rport_busy_lock = NULL; - - FC_CHECK_RETURN_VALUE(lport, NULL); - FC_CHECK_RETURN_VALUE(new_rport, NULL); - - unf_lport = lport->root_lport; - disc = &lport->disc; - FC_CHECK_RETURN_VALUE(unf_lport, NULL); - rport_pool = &unf_lport->rport_pool; - rport_free_lock = &rport_pool->rport_free_pool_lock; - rport_busy_lock = &disc->rport_busy_pool_lock; - - spin_lock_irqsave(rport_busy_lock, flag); - list_for_each_safe(node, next_node, &disc->list_busy_rports) { - /* According to N_Port_ID */ - old_rport = list_entry(node, struct unf_rport, entry_rport); - if (old_rport->nport_id == nport_id) - break; - old_rport = NULL; - } - - if (old_rport) { - spin_unlock_irqrestore(rport_busy_lock, flag); - - /* Use old R_Port & Add new R_Port back to R_Port Pool */ - spin_lock_irqsave(rport_free_lock, flag); - clear_bit((int)unf_new_rport->rport_index, rport_pool->rpi_bitmap); - list_add_tail(&unf_new_rport->entry_rport, &rport_pool->list_rports_pool); - rport_pool->rport_pool_count++; - spin_unlock_irqrestore(rport_free_lock, flag); - - unf_check_rport_pool_status(unf_lport); - return (void *)old_rport; - } - spin_unlock_irqrestore(rport_busy_lock, flag); - if (nport_id != UNF_FC_FID_FLOGI) { - if (unf_alloc_ll_rport_resource(lport, unf_new_rport, nport_id) != RETURN_OK) { - /* Add new R_Port back to R_Port Pool */ - spin_lock_irqsave(rport_free_lock, flag); - clear_bit((int)unf_new_rport->rport_index, rport_pool->rpi_bitmap); - list_add_tail(&unf_new_rport->entry_rport, &rport_pool->list_rports_pool); - rport_pool->rport_pool_count++; - spin_unlock_irqrestore(rport_free_lock, flag); - unf_check_rport_pool_status(unf_lport); - - return NULL; - } - } - - spin_lock_irqsave(rport_busy_lock, flag); - /* Add new R_Port to busy list */ - list_add_tail(&unf_new_rport->entry_rport, &disc->list_busy_rports); - unf_new_rport->nport_id = nport_id; - unf_new_rport->local_nport_id = lport->nport_id; - spin_unlock_irqrestore(rport_busy_lock, flag); - unf_init_rport_params(unf_new_rport, lport); - - return (void *)unf_new_rport; -} - -void *unf_rport_get_free_and_init(void *lport, u32 port_type, u32 nport_id) -{ - struct unf_lport *unf_lport = NULL; - struct unf_rport_pool *rport_pool = NULL; - struct unf_disc *disc = NULL; - struct unf_disc *vport_disc = NULL; - struct unf_rport *rport = NULL; - struct list_head *list_head = NULL; - ulong flag = 0; - struct unf_disc_rport *disc_rport = NULL; - - FC_CHECK_RETURN_VALUE(lport, NULL); - unf_lport = ((struct unf_lport *)lport)->root_lport; - FC_CHECK_RETURN_VALUE(unf_lport, NULL); - - /* Check L_Port state: NOP */ - if (unlikely(atomic_read(&unf_lport->lport_no_operate_flag) == UNF_LPORT_NOP)) - return NULL; - - rport_pool = &unf_lport->rport_pool; - disc = &unf_lport->disc; - - /* 1. UNF_PORT_TYPE_DISC: Get from disc_rport_pool */ - if (port_type == UNF_PORT_TYPE_DISC) { - vport_disc = &((struct unf_lport *)lport)->disc; - /* NOTE: list_disc_rports_pool used with list_disc_rports_busy */ - spin_lock_irqsave(&disc->rport_busy_pool_lock, flag); - if (!list_empty(&disc->disc_rport_mgr.list_disc_rports_pool)) { - /* Get & delete from Disc R_Port Pool & Add it to Busy list */ - list_head = UNF_OS_LIST_NEXT(&disc->disc_rport_mgr.list_disc_rports_pool); - list_del_init(list_head); - disc_rport = list_entry(list_head, struct unf_disc_rport, entry_rport); - disc_rport->nport_id = nport_id; - spin_unlock_irqrestore(&disc->rport_busy_pool_lock, flag); - - /* Add to list_disc_rports_busy */ - spin_lock_irqsave(&vport_disc->rport_busy_pool_lock, flag); - list_add_tail(list_head, &vport_disc->disc_rport_mgr.list_disc_rports_busy); - spin_unlock_irqrestore(&vport_disc->rport_busy_pool_lock, flag); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "Port(0x%x_0x%x) add nportid:0x%x to rportbusy list", - unf_lport->port_id, unf_lport->nport_id, - disc_rport->nport_id); - } else { - disc_rport = NULL; - spin_unlock_irqrestore(&disc->rport_busy_pool_lock, flag); - } - - /* NOTE: return */ - return disc_rport; - } - - /* 2. UNF_PORT_TYPE_FC (rport_pool): Get from list_rports_pool */ - spin_lock_irqsave(&rport_pool->rport_free_pool_lock, flag); - if (!list_empty(&rport_pool->list_rports_pool)) { - /* Get & delete from R_Port free Pool */ - list_head = UNF_OS_LIST_NEXT(&rport_pool->list_rports_pool); - list_del_init(list_head); - rport_pool->rport_pool_count--; - rport = list_entry(list_head, struct unf_rport, entry_rport); - } else { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x_0x%x) RPort pool is empty", - unf_lport->port_id, unf_lport->nport_id); - - spin_unlock_irqrestore(&rport_pool->rport_free_pool_lock, flag); - - return NULL; - } - spin_unlock_irqrestore(&rport_pool->rport_free_pool_lock, flag); - - /* 3. Alloc (& set bit) R_Port index */ - if (unf_alloc_index_for_rport(unf_lport, rport) != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) allocate index for new RPort failed", - unf_lport->nport_id); - - /* Alloc failed: Add R_Port back to R_Port Pool */ - spin_lock_irqsave(&rport_pool->rport_free_pool_lock, flag); - list_add_tail(&rport->entry_rport, &rport_pool->list_rports_pool); - rport_pool->rport_pool_count++; - spin_unlock_irqrestore(&rport_pool->rport_free_pool_lock, flag); - unf_check_rport_pool_status(unf_lport); - return NULL; - } - - /* 4. Add R_Port to busy list */ - rport = unf_add_rport_to_busy_list(lport, rport, nport_id); - - return (void *)rport; -} - -u32 unf_release_rport_res(struct unf_lport *lport, struct unf_rport *rport) -{ - u32 ret = UNF_RETURN_ERROR; - struct unf_port_info rport_info; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(rport, UNF_RETURN_ERROR); - - memset(&rport_info, 0, sizeof(struct unf_port_info)); - - rport_info.rport_index = rport->rport_index; - rport_info.nport_id = rport->nport_id; - rport_info.port_name = rport->port_name; - rport_info.sqn_base = rport->sqn_base; - - /* 2. release R_Port(parent context/Session) resource */ - if (!lport->low_level_func.service_op.unf_release_rport_res) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) release rport resource function can't be NULL", - lport->port_id); - - return ret; - } - - ret = lport->low_level_func.service_op.unf_release_rport_res(lport->fc_port, &rport_info); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) rport_index(0x%x, %p) send release session CMND failed", - lport->port_id, rport_info.rport_index, rport); - } - - return ret; -} - -static void unf_reset_rport_attribute(struct unf_rport *rport) -{ - ulong flag = 0; - - FC_CHECK_RETURN_VOID(rport); - - spin_lock_irqsave(&rport->rport_state_lock, flag); - rport->unf_rport_callback = NULL; - rport->lport = NULL; - rport->node_name = INVALID_VALUE64; - rport->port_name = INVALID_WWPN; - rport->nport_id = INVALID_VALUE32; - rport->local_nport_id = INVALID_VALUE32; - rport->max_frame_size = UNF_MAX_FRAME_SIZE; - rport->ed_tov = UNF_DEFAULT_EDTOV; - rport->ra_tov = UNF_DEFAULT_RATOV; - rport->rport_index = INVALID_VALUE32; - rport->scsi_id = INVALID_VALUE32; - rport->rport_alloc_jifs = INVALID_VALUE64; - - /* ini or tgt */ - rport->options = 0; - - /* fcp conf */ - rport->fcp_conf_needed = false; - - /* special req retry times */ - rport->retries = 0; - rport->logo_retries = 0; - - /* special req retry times */ - rport->max_retries = UNF_MAX_RETRY_COUNT; - - /* for target mode */ - rport->session = NULL; - rport->last_lport_ini_state = UNF_PORT_STATE_LINKDOWN; - rport->lport_ini_state = UNF_PORT_STATE_LINKDOWN; - rport->rp_state = UNF_RPORT_ST_INIT; - rport->last_lport_tgt_state = UNF_PORT_STATE_LINKDOWN; - rport->lport_tgt_state = UNF_PORT_STATE_LINKDOWN; - rport->rscn_position = UNF_RPORT_NOT_NEED_PROCESS; - rport->disc_done = 0; - rport->sqn_base = 0; - - /* for scsi */ - rport->data_thread = NULL; - spin_unlock_irqrestore(&rport->rport_state_lock, flag); -} - -u32 unf_rport_remove(void *rport) -{ - struct unf_lport *lport = NULL; - struct unf_rport *unf_rport = NULL; - struct unf_rport_pool *rport_pool = NULL; - ulong flag = 0; - u32 rport_index = 0; - u32 nport_id = 0; - - FC_CHECK_RETURN_VALUE(rport, UNF_RETURN_ERROR); - - unf_rport = (struct unf_rport *)rport; - lport = unf_rport->lport; - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - rport_pool = &((struct unf_lport *)lport->root_lport)->rport_pool; - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "[info]Remove RPort(0x%p) with remote_nport_id(0x%x) local_nport_id(0x%x)", - unf_rport, unf_rport->nport_id, unf_rport->local_nport_id); - - /* 1. Terminate open exchange before rport remove: set ABORT tag */ - unf_cm_xchg_mgr_abort_io_by_id(lport, unf_rport, unf_rport->nport_id, lport->nport_id, 0); - - /* 2. Abort sfp exchange before rport remove */ - unf_cm_xchg_mgr_abort_sfs_by_id(lport, unf_rport, unf_rport->nport_id, lport->nport_id); - - /* 3. Release R_Port resource: session reset/delete */ - if (likely(unf_rport->nport_id != UNF_FC_FID_FLOGI)) - (void)unf_release_rport_res(lport, unf_rport); - - nport_id = unf_rport->nport_id; - - /* 4.1 Delete R_Port from disc destroy/delete list */ - spin_lock_irqsave(&lport->disc.rport_busy_pool_lock, flag); - list_del_init(&unf_rport->entry_rport); - spin_unlock_irqrestore(&lport->disc.rport_busy_pool_lock, flag); - - rport_index = unf_rport->rport_index; - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_KEVENT, - "[event]Port(0x%x) release RPort(0x%x_%p) with index(0x%x)", - lport->port_id, unf_rport->nport_id, unf_rport, - unf_rport->rport_index); - - unf_reset_rport_attribute(unf_rport); - - /* 4.2 Add rport to --->>> rport_pool (free pool) & clear bitmap */ - spin_lock_irqsave(&rport_pool->rport_free_pool_lock, flag); - if (unlikely(nport_id == UNF_FC_FID_FLOGI)) { - if (test_bit((int)rport_index, rport_pool->rpi_bitmap)) - clear_bit((int)rport_index, rport_pool->rpi_bitmap); - } - - list_add_tail(&unf_rport->entry_rport, &rport_pool->list_rports_pool); - rport_pool->rport_pool_count++; - spin_unlock_irqrestore(&rport_pool->rport_free_pool_lock, flag); - - unf_check_rport_pool_status((struct unf_lport *)lport->root_lport); - up(&unf_rport->task_sema); - - return RETURN_OK; -} - -u32 unf_rport_ref_inc(struct unf_rport *rport) -{ - FC_CHECK_RETURN_VALUE(rport, UNF_RETURN_ERROR); - - if (atomic_read(&rport->rport_ref_cnt) <= 0) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Rport(0x%x) reference count is wrong %d", - rport->nport_id, - atomic_read(&rport->rport_ref_cnt)); - return UNF_RETURN_ERROR; - } - - atomic_inc(&rport->rport_ref_cnt); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "[info]Rport(0x%x) reference count is %d", rport->nport_id, - atomic_read(&rport->rport_ref_cnt)); - - return RETURN_OK; -} - -void unf_rport_ref_dec(struct unf_rport *rport) -{ - ulong flag = 0; - - FC_CHECK_RETURN_VOID(rport); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "[info]Rport(0x%x) reference count is %d", rport->nport_id, - atomic_read(&rport->rport_ref_cnt)); - - spin_lock_irqsave(&rport->rport_state_lock, flag); - if (atomic_dec_and_test(&rport->rport_ref_cnt)) { - spin_unlock_irqrestore(&rport->rport_state_lock, flag); - (void)unf_rport_remove(rport); - } else { - spin_unlock_irqrestore(&rport->rport_state_lock, flag); - } -} - -void unf_set_rport_state(struct unf_rport *rport, - enum unf_rport_login_state states) -{ - FC_CHECK_RETURN_VOID(rport); - - if (rport->rp_state != states) { - /* Reset R_Port retry count */ - rport->retries = 0; - } - - rport->rp_state = states; -} - -static enum unf_rport_login_state -unf_rport_stat_init(enum unf_rport_login_state old_state, - enum unf_rport_event event) -{ - enum unf_rport_login_state next_state = UNF_RPORT_ST_INIT; - - switch (event) { - case UNF_EVENT_RPORT_LOGO: - next_state = UNF_RPORT_ST_LOGO; - break; - - case UNF_EVENT_RPORT_ENTER_PLOGI: - next_state = UNF_RPORT_ST_PLOGI_WAIT; - break; - - case UNF_EVENT_RPORT_LINK_DOWN: - next_state = UNF_RPORT_ST_CLOSING; - break; - - default: - next_state = old_state; - break; - } - - return next_state; -} - -static enum unf_rport_login_state unf_rport_stat_plogi_wait(enum unf_rport_login_state old_state, - enum unf_rport_event event) -{ - enum unf_rport_login_state next_state = UNF_RPORT_ST_INIT; - - switch (event) { - case UNF_EVENT_RPORT_ENTER_PRLI: - next_state = UNF_RPORT_ST_PRLI_WAIT; - break; - - case UNF_EVENT_RPORT_LINK_DOWN: - next_state = UNF_RPORT_ST_CLOSING; - break; - - case UNF_EVENT_RPORT_LOGO: - next_state = UNF_RPORT_ST_LOGO; - break; - - case UNF_EVENT_RPORT_RECOVERY: - next_state = UNF_RPORT_ST_READY; - break; - - default: - next_state = old_state; - break; - } - - return next_state; -} - -static enum unf_rport_login_state unf_rport_stat_prli_wait(enum unf_rport_login_state old_state, - enum unf_rport_event event) -{ - enum unf_rport_login_state next_state = UNF_RPORT_ST_INIT; - - switch (event) { - case UNF_EVENT_RPORT_READY: - next_state = UNF_RPORT_ST_READY; - break; - - case UNF_EVENT_RPORT_LOGO: - next_state = UNF_RPORT_ST_LOGO; - break; - - case UNF_EVENT_RPORT_LINK_DOWN: - next_state = UNF_RPORT_ST_CLOSING; - break; - - case UNF_EVENT_RPORT_RECOVERY: - next_state = UNF_RPORT_ST_READY; - break; - - default: - next_state = old_state; - break; - } - - return next_state; -} - -static enum unf_rport_login_state unf_rport_stat_ready(enum unf_rport_login_state old_state, - enum unf_rport_event event) -{ - enum unf_rport_login_state next_state = UNF_RPORT_ST_INIT; - - switch (event) { - case UNF_EVENT_RPORT_LOGO: - next_state = UNF_RPORT_ST_LOGO; - break; - - case UNF_EVENT_RPORT_LINK_DOWN: - next_state = UNF_RPORT_ST_CLOSING; - break; - - case UNF_EVENT_RPORT_ENTER_PLOGI: - next_state = UNF_RPORT_ST_PLOGI_WAIT; - break; - - default: - next_state = old_state; - break; - } - - return next_state; -} - -static enum unf_rport_login_state unf_rport_stat_closing(enum unf_rport_login_state old_state, - enum unf_rport_event event) -{ - enum unf_rport_login_state next_state = UNF_RPORT_ST_INIT; - - switch (event) { - case UNF_EVENT_RPORT_CLS_TIMEOUT: - next_state = UNF_RPORT_ST_DELETE; - break; - - case UNF_EVENT_RPORT_RELOGIN: - next_state = UNF_RPORT_ST_INIT; - break; - - case UNF_EVENT_RPORT_RECOVERY: - next_state = UNF_RPORT_ST_READY; - break; - - default: - next_state = old_state; - break; - } - - return next_state; -} - -static enum unf_rport_login_state unf_rport_stat_logo(enum unf_rport_login_state old_state, - enum unf_rport_event event) -{ - enum unf_rport_login_state next_state = UNF_RPORT_ST_INIT; - - switch (event) { - case UNF_EVENT_RPORT_NORMAL_ENTER: - next_state = UNF_RPORT_ST_CLOSING; - break; - - case UNF_EVENT_RPORT_RECOVERY: - next_state = UNF_RPORT_ST_READY; - break; - - default: - next_state = old_state; - break; - } - - return next_state; -} - -void unf_rport_state_ma(struct unf_rport *rport, enum unf_rport_event event) -{ - enum unf_rport_login_state old_state = UNF_RPORT_ST_INIT; - enum unf_rport_login_state next_state = UNF_RPORT_ST_INIT; - - FC_CHECK_RETURN_VOID(rport); - - old_state = rport->rp_state; - - switch (rport->rp_state) { - case UNF_RPORT_ST_INIT: - next_state = unf_rport_stat_init(old_state, event); - break; - case UNF_RPORT_ST_PLOGI_WAIT: - next_state = unf_rport_stat_plogi_wait(old_state, event); - break; - case UNF_RPORT_ST_PRLI_WAIT: - next_state = unf_rport_stat_prli_wait(old_state, event); - break; - case UNF_RPORT_ST_LOGO: - next_state = unf_rport_stat_logo(old_state, event); - break; - case UNF_RPORT_ST_CLOSING: - next_state = unf_rport_stat_closing(old_state, event); - break; - case UNF_RPORT_ST_READY: - next_state = unf_rport_stat_ready(old_state, event); - break; - case UNF_RPORT_ST_DELETE: - default: - next_state = UNF_RPORT_ST_INIT; - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, - UNF_MAJOR, "[info]RPort(0x%x) hold state(0x%x)", - rport->nport_id, rport->rp_state); - break; - } - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MINOR, - "[info]RPort(0x%x) with oldstate(0x%x) event(0x%x) nextstate(0x%x)", - rport->nport_id, old_state, event, next_state); - - unf_set_rport_state(rport, next_state); -} - -void unf_clean_linkdown_rport(struct unf_lport *lport) -{ - /* for L_Port's R_Port(s) */ - struct unf_disc *disc = NULL; - struct list_head *node = NULL; - struct list_head *next_node = NULL; - struct unf_rport *rport = NULL; - struct unf_lport *unf_lport = NULL; - ulong disc_lock_flag = 0; - ulong rport_lock_flag = 0; - - FC_CHECK_RETURN_VOID(lport); - disc = &lport->disc; - - /* for each busy R_Port */ - spin_lock_irqsave(&disc->rport_busy_pool_lock, disc_lock_flag); - list_for_each_safe(node, next_node, &disc->list_busy_rports) { - rport = list_entry(node, struct unf_rport, entry_rport); - - /* 1. Prevent process Repeatly: Closing */ - spin_lock_irqsave(&rport->rport_state_lock, rport_lock_flag); - if (rport->rp_state == UNF_RPORT_ST_CLOSING) { - spin_unlock_irqrestore(&rport->rport_state_lock, rport_lock_flag); - continue; - } - - /* 2. Increase ref_cnt to protect R_Port */ - if (unf_rport_ref_inc(rport) != RETURN_OK) { - spin_unlock_irqrestore(&rport->rport_state_lock, rport_lock_flag); - continue; - } - - /* 3. Update R_Port state: Link Down Event --->>> closing state - */ - unf_rport_state_ma(rport, UNF_EVENT_RPORT_LINK_DOWN); - - /* 4. Put R_Port from busy to destroy list */ - list_del_init(&rport->entry_rport); - list_add_tail(&rport->entry_rport, &disc->list_destroy_rports); - - unf_lport = rport->lport; - spin_unlock_irqrestore(&rport->rport_state_lock, rport_lock_flag); - - /* 5. Schedule Closing work (Enqueuing workqueue) */ - unf_schedule_closing_work(unf_lport, rport); - - /* 6. decrease R_Port ref_cnt (company with 2) */ - unf_rport_ref_dec(rport); - } - spin_unlock_irqrestore(&disc->rport_busy_pool_lock, disc_lock_flag); -} - -void unf_rport_enter_closing(struct unf_rport *rport) -{ - /* - * call by - * 1. with RSCN processer - * 2. with LOGOUT processer - * * - * from - * 1. R_Port Link Down - * 2. R_Port enter LOGO - */ - ulong rport_lock_flag = 0; - u32 ret = UNF_RETURN_ERROR; - struct unf_lport *lport = NULL; - struct unf_disc *disc = NULL; - - FC_CHECK_RETURN_VOID(rport); - - /* 1. Increase ref_cnt to protect R_Port */ - spin_lock_irqsave(&rport->rport_state_lock, rport_lock_flag); - ret = unf_rport_ref_inc(rport); - if (ret != RETURN_OK) { - spin_unlock_irqrestore(&rport->rport_state_lock, rport_lock_flag); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]RPort(0x%x_0x%p) is removing and no need process", - rport->nport_id, rport); - - return; - } - - /* NOTE: R_Port state has been set(with closing) */ - - lport = rport->lport; - spin_unlock_irqrestore(&rport->rport_state_lock, rport_lock_flag); - - /* 2. Put R_Port from busy to destroy list */ - disc = &lport->disc; - spin_lock_irqsave(&disc->rport_busy_pool_lock, rport_lock_flag); - list_del_init(&rport->entry_rport); - list_add_tail(&rport->entry_rport, &disc->list_destroy_rports); - spin_unlock_irqrestore(&disc->rport_busy_pool_lock, rport_lock_flag); - - /* 3. Schedule Closing work (Enqueuing workqueue) */ - unf_schedule_closing_work(lport, rport); - - /* 4. dec R_Port ref_cnt */ - unf_rport_ref_dec(rport); -} - -void unf_rport_error_recovery(struct unf_rport *rport) -{ - ulong delay = 0; - ulong flag = 0; - u32 ret = UNF_RETURN_ERROR; - - FC_CHECK_RETURN_VOID(rport); - - spin_lock_irqsave(&rport->rport_state_lock, flag); - - ret = unf_rport_ref_inc(rport); - if (ret != RETURN_OK) { - spin_unlock_irqrestore(&rport->rport_state_lock, flag); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]RPort(0x%x_0x%p) is removing and no need process", - rport->nport_id, rport); - return; - } - - /* Check R_Port state */ - if (rport->rp_state == UNF_RPORT_ST_CLOSING || - rport->rp_state == UNF_RPORT_ST_DELETE) { - spin_unlock_irqrestore(&rport->rport_state_lock, flag); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]RPort(0x%x_0x%p) offline and no need process", - rport->nport_id, rport); - - unf_rport_ref_dec(rport); - return; - } - - /* Check repeatability with recovery work */ - if (delayed_work_pending(&rport->recovery_work)) { - spin_unlock_irqrestore(&rport->rport_state_lock, flag); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]RPort(0x%x_0x%p) recovery work is running and no need process", - rport->nport_id, rport); - - unf_rport_ref_dec(rport); - return; - } - - /* NOTE: Re-login or Logout directly (recovery work) */ - if (rport->retries < rport->max_retries) { - rport->retries++; - delay = UNF_DEFAULT_EDTOV / 4; - - if (queue_delayed_work(unf_wq, &rport->recovery_work, - (ulong)msecs_to_jiffies((u32)delay))) { - /* Inc ref_cnt: corresponding to this work timer */ - (void)unf_rport_ref_inc(rport); - } - spin_unlock_irqrestore(&rport->rport_state_lock, flag); - } else { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]RPort(0x%x_0x%p) state(0x%x) retry login failed", - rport->nport_id, rport, rport->rp_state); - - /* Update R_Port state: LOGO event --->>> ST_LOGO */ - unf_rport_state_ma(rport, UNF_EVENT_RPORT_LOGO); - spin_unlock_irqrestore(&rport->rport_state_lock, flag); - - unf_rport_enter_logo(rport->lport, rport); - } - - unf_rport_ref_dec(rport); -} - -static u32 unf_rport_reuse_only(struct unf_rport *rport) -{ - ulong flag = 0; - u32 ret = UNF_RETURN_ERROR; - - FC_CHECK_RETURN_VALUE(rport, UNF_RETURN_ERROR); - - spin_lock_irqsave(&rport->rport_state_lock, flag); - ret = unf_rport_ref_inc(rport); - if (ret != RETURN_OK) { - spin_unlock_irqrestore(&rport->rport_state_lock, flag); - - /* R_Port with delete state */ - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]RPort(0x%x_0x%p) is removing and no need process", - rport->nport_id, rport); - - return UNF_RETURN_ERROR; - } - - /* R_Port State check: delete */ - if (rport->rp_state == UNF_RPORT_ST_DELETE || - rport->rp_state == UNF_RPORT_ST_CLOSING) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]RPort(0x%x_0x%p) state(0x%x) is delete or closing no need process", - rport->nport_id, rport, rport->rp_state); - - ret = UNF_RETURN_ERROR; - } - spin_unlock_irqrestore(&rport->rport_state_lock, flag); - - unf_rport_ref_dec(rport); - - return ret; -} - -static u32 unf_rport_reuse_recover(struct unf_rport *rport) -{ - ulong flags = 0; - u32 ret = UNF_RETURN_ERROR; - - FC_CHECK_RETURN_VALUE(rport, UNF_RETURN_ERROR); - - spin_lock_irqsave(&rport->rport_state_lock, flags); - ret = unf_rport_ref_inc(rport); - if (ret != RETURN_OK) { - spin_unlock_irqrestore(&rport->rport_state_lock, flags); - - /* R_Port with delete state */ - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]RPort(0x%x_0x%p) is removing and no need process", - rport->nport_id, rport); - - return UNF_RETURN_ERROR; - } - - /* R_Port state check: delete */ - if (rport->rp_state == UNF_RPORT_ST_DELETE || - rport->rp_state == UNF_RPORT_ST_CLOSING) { - ret = UNF_RETURN_ERROR; - } - - /* Update R_Port state: recovery --->>> ready */ - unf_rport_state_ma(rport, UNF_EVENT_RPORT_RECOVERY); - spin_unlock_irqrestore(&rport->rport_state_lock, flags); - - unf_rport_ref_dec(rport); - - return ret; -} - -static u32 unf_rport_reuse_init(struct unf_rport *rport) -{ - ulong flag = 0; - u32 ret = UNF_RETURN_ERROR; - - FC_CHECK_RETURN_VALUE(rport, UNF_RETURN_ERROR); - - spin_lock_irqsave(&rport->rport_state_lock, flag); - ret = unf_rport_ref_inc(rport); - if (ret != RETURN_OK) { - spin_unlock_irqrestore(&rport->rport_state_lock, flag); - - /* R_Port with delete state */ - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]RPort(0x%x_0x%p) is removing and no need process", - rport->nport_id, rport); - - return UNF_RETURN_ERROR; - } - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "[info]RPort(0x%x)'s state is 0x%x with use_init flag", - rport->nport_id, rport->rp_state); - - /* R_Port State check: delete */ - if (rport->rp_state == UNF_RPORT_ST_DELETE || - rport->rp_state == UNF_RPORT_ST_CLOSING) { - ret = UNF_RETURN_ERROR; - } else { - /* Update R_Port state: re-enter Init state */ - unf_set_rport_state(rport, UNF_RPORT_ST_INIT); - } - spin_unlock_irqrestore(&rport->rport_state_lock, flag); - - unf_rport_ref_dec(rport); - - return ret; -} - -struct unf_rport *unf_get_rport_by_nport_id(struct unf_lport *lport, - u32 nport_id) -{ - struct unf_lport *unf_lport = NULL; - struct unf_disc *disc = NULL; - struct unf_rport *rport = NULL; - struct list_head *node = NULL; - struct list_head *next_node = NULL; - ulong flag = 0; - struct unf_rport *find_rport = NULL; - - FC_CHECK_RETURN_VALUE(lport, NULL); - unf_lport = (struct unf_lport *)lport; - disc = &unf_lport->disc; - - /* for each r_port from rport_busy_list: compare N_Port_ID */ - spin_lock_irqsave(&disc->rport_busy_pool_lock, flag); - list_for_each_safe(node, next_node, &disc->list_busy_rports) { - rport = list_entry(node, struct unf_rport, entry_rport); - if (rport && rport->nport_id == nport_id) { - find_rport = rport; - break; - } - } - spin_unlock_irqrestore(&disc->rport_busy_pool_lock, flag); - - return find_rport; -} - -struct unf_rport *unf_get_rport_by_wwn(struct unf_lport *lport, u64 wwpn) -{ - struct unf_lport *unf_lport = NULL; - struct unf_disc *disc = NULL; - struct unf_rport *rport = NULL; - struct list_head *node = NULL; - struct list_head *next_node = NULL; - ulong flag = 0; - struct unf_rport *find_rport = NULL; - - FC_CHECK_RETURN_VALUE(lport, NULL); - unf_lport = (struct unf_lport *)lport; - disc = &unf_lport->disc; - - /* for each r_port from busy_list: compare wwpn(port name) */ - spin_lock_irqsave(&disc->rport_busy_pool_lock, flag); - list_for_each_safe(node, next_node, &disc->list_busy_rports) { - rport = list_entry(node, struct unf_rport, entry_rport); - if (rport && rport->port_name == wwpn) { - find_rport = rport; - break; - } - } - spin_unlock_irqrestore(&disc->rport_busy_pool_lock, flag); - - return find_rport; -} - -struct unf_rport *unf_get_safe_rport(struct unf_lport *lport, - struct unf_rport *rport, - enum unf_rport_reuse_flag reuse_flag, - u32 nport_id) -{ - /* - * New add or plug - * * - * retry_flogi --->>> reuse_only - * name_server_register --->>> reuse_only - * SNS_plogi --->>> reuse_only - * enter_flogi --->>> reuse_only - * logout --->>> reuse_only - * flogi_handler --->>> reuse_only - * plogi_handler --->>> reuse_only - * adisc_handler --->>> reuse_recovery - * logout_handler --->>> reuse_init - * prlo_handler --->>> reuse_init - * login_with_loop --->>> reuse_only - * gffid_callback --->>> reuse_only - * delay_plogi --->>> reuse_only - * gffid_rjt --->>> reuse_only - * gffid_rsp_unknown --->>> reuse_only - * gpnid_acc --->>> reuse_init - * fdisc_callback --->>> reuse_only - * flogi_acc --->>> reuse_only - * plogi_acc --->>> reuse_only - * logo_callback --->>> reuse_init - * rffid_callback --->>> reuse_only - */ -#define UNF_AVOID_LINK_FLASH_TIME 3000 - - struct unf_rport *unf_rport = rport; - u32 ret = UNF_RETURN_ERROR; - - FC_CHECK_RETURN_VALUE(lport, NULL); - - /* 1. Alloc New R_Port or Update R_Port Property */ - if (!unf_rport) { - /* If NULL, get/Alloc new node (R_Port from R_Port pool) - * directly - */ - unf_rport = unf_rport_get_free_and_init(lport, UNF_PORT_TYPE_FC, nport_id); - } else { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, - UNF_INFO, - "[info]Port(0x%x) get exist RPort(0x%x) with state(0x%x) and reuse_flag(0x%x)", - lport->port_id, unf_rport->nport_id, - unf_rport->rp_state, reuse_flag); - - switch (reuse_flag) { - case UNF_RPORT_REUSE_ONLY: - ret = unf_rport_reuse_only(unf_rport); - if (ret != RETURN_OK) { - /* R_Port within delete list: need get new */ - unf_rport = unf_rport_get_free_and_init(lport, UNF_PORT_TYPE_FC, - nport_id); - } - break; - - case UNF_RPORT_REUSE_INIT: - ret = unf_rport_reuse_init(unf_rport); - if (ret != RETURN_OK) { - /* R_Port within delete list: need get new */ - unf_rport = unf_rport_get_free_and_init(lport, UNF_PORT_TYPE_FC, - nport_id); - } - break; - - case UNF_RPORT_REUSE_RECOVER: - ret = unf_rport_reuse_recover(unf_rport); - if (ret != RETURN_OK) { - /* R_Port within delete list, - * NOTE: do nothing - */ - unf_rport = NULL; - } - break; - - default: - break; - } - } // end else: R_Port != NULL - - return unf_rport; -} - -u32 unf_get_port_feature(u64 wwpn) -{ - struct unf_rport_feature_recard *port_fea = NULL; - struct list_head *node = NULL; - struct list_head *next_node = NULL; - ulong flags = 0; - struct list_head list_temp_node; - struct list_head *list_busy_head = NULL; - struct list_head *list_free_head = NULL; - spinlock_t *feature_lock = NULL; - - list_busy_head = &port_feature_pool->list_busy_head; - list_free_head = &port_feature_pool->list_free_head; - feature_lock = &port_feature_pool->port_fea_pool_lock; - spin_lock_irqsave(feature_lock, flags); - list_for_each_safe(node, next_node, list_busy_head) { - port_fea = list_entry(node, struct unf_rport_feature_recard, entry_feature); - - if (port_fea->wwpn == wwpn) { - list_del(&port_fea->entry_feature); - list_add(&port_fea->entry_feature, list_busy_head); - spin_unlock_irqrestore(feature_lock, flags); - - return port_fea->port_feature; - } - } - - list_for_each_safe(node, next_node, list_free_head) { - port_fea = list_entry(node, struct unf_rport_feature_recard, entry_feature); - - if (port_fea->wwpn == wwpn) { - list_del(&port_fea->entry_feature); - list_add(&port_fea->entry_feature, list_busy_head); - spin_unlock_irqrestore(feature_lock, flags); - - return port_fea->port_feature; - } - } - - /* can't find wwpn */ - if (list_empty(list_free_head)) { - /* free is empty, transport busy to free */ - list_temp_node = port_feature_pool->list_free_head; - port_feature_pool->list_free_head = port_feature_pool->list_busy_head; - port_feature_pool->list_busy_head = list_temp_node; - } - - port_fea = list_entry(UNF_OS_LIST_PREV(list_free_head), - struct unf_rport_feature_recard, - entry_feature); - list_del(&port_fea->entry_feature); - list_add(&port_fea->entry_feature, list_busy_head); - - port_fea->wwpn = wwpn; - port_fea->port_feature = UNF_PORT_MODE_UNKNOWN; - - spin_unlock_irqrestore(feature_lock, flags); - return UNF_PORT_MODE_UNKNOWN; -} - -void unf_update_port_feature(u64 wwpn, u32 port_feature) -{ - struct unf_rport_feature_recard *port_fea = NULL; - struct list_head *node = NULL; - struct list_head *next_node = NULL; - struct list_head *busy_head = NULL; - struct list_head *free_head = NULL; - ulong flags = 0; - spinlock_t *feature_lock = NULL; - - feature_lock = &port_feature_pool->port_fea_pool_lock; - busy_head = &port_feature_pool->list_busy_head; - free_head = &port_feature_pool->list_free_head; - - spin_lock_irqsave(feature_lock, flags); - list_for_each_safe(node, next_node, busy_head) { - port_fea = list_entry(node, struct unf_rport_feature_recard, entry_feature); - - if (port_fea->wwpn == wwpn) { - port_fea->port_feature = port_feature; - list_del(&port_fea->entry_feature); - list_add(&port_fea->entry_feature, busy_head); - spin_unlock_irqrestore(feature_lock, flags); - - return; - } - } - - list_for_each_safe(node, next_node, free_head) { - port_fea = list_entry(node, struct unf_rport_feature_recard, entry_feature); - - if (port_fea->wwpn == wwpn) { - port_fea->port_feature = port_feature; - list_del(&port_fea->entry_feature); - list_add(&port_fea->entry_feature, busy_head); - - spin_unlock_irqrestore(feature_lock, flags); - - return; - } - } - - spin_unlock_irqrestore(feature_lock, flags); -} diff --git a/drivers/scsi/spfc/common/unf_rport.h b/drivers/scsi/spfc/common/unf_rport.h deleted file mode 100644 index a9d58cb29b8a..000000000000 --- a/drivers/scsi/spfc/common/unf_rport.h +++ /dev/null @@ -1,301 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef UNF_RPORT_H -#define UNF_RPORT_H - -#include "unf_type.h" -#include "unf_common.h" -#include "unf_lport.h" - -extern struct unf_rport_feature_pool *port_feature_pool; - -#define UNF_MAX_SCSI_ID 2048 -#define UNF_LOSE_TMO 30 -#define UNF_RPORT_INVALID_INDEX 0xffff - -/* RSCN compare DISC list with local RPort macro */ -#define UNF_RPORT_NEED_PROCESS 0x1 -#define UNF_RPORT_ONLY_IN_DISC_PROCESS 0x2 -#define UNF_RPORT_ONLY_IN_LOCAL_PROCESS 0x3 -#define UNF_RPORT_IN_DISC_AND_LOCAL_PROCESS 0x4 -#define UNF_RPORT_NOT_NEED_PROCESS 0x5 - -#define UNF_ECHO_SEND_MAX_TIMES 1 - -/* csctrl level value */ -#define UNF_CSCTRL_LOW 0x81 -#define UNF_CSCTRL_MIDDLE 0x82 -#define UNF_CSCTRL_HIGH 0x83 -#define UNF_CSCTRL_INVALID 0x0 - -enum unf_rport_login_state { - UNF_RPORT_ST_INIT = 0x1000, /* initialized */ - UNF_RPORT_ST_PLOGI_WAIT, /* waiting for PLOGI completion */ - UNF_RPORT_ST_PRLI_WAIT, /* waiting for PRLI completion */ - UNF_RPORT_ST_READY, /* ready for use */ - UNF_RPORT_ST_LOGO, /* port logout sent */ - UNF_RPORT_ST_CLOSING, /* being closed */ - UNF_RPORT_ST_DELETE, /* port being deleted */ - UNF_RPORT_ST_BUTT -}; - -enum unf_rport_event { - UNF_EVENT_RPORT_NORMAL_ENTER = 0x9000, - UNF_EVENT_RPORT_ENTER_PLOGI = 0x9001, - UNF_EVENT_RPORT_ENTER_PRLI = 0x9002, - UNF_EVENT_RPORT_READY = 0x9003, - UNF_EVENT_RPORT_LOGO = 0x9004, - UNF_EVENT_RPORT_CLS_TIMEOUT = 0x9005, - UNF_EVENT_RPORT_RECOVERY = 0x9006, - UNF_EVENT_RPORT_RELOGIN = 0x9007, - UNF_EVENT_RPORT_LINK_DOWN = 0x9008, - UNF_EVENT_RPORT_BUTT -}; - -/* RPort local link state */ -enum unf_port_state { - UNF_PORT_STATE_LINKUP = 0x1001, - UNF_PORT_STATE_LINKDOWN = 0x1002 -}; - -enum unf_rport_reuse_flag { - UNF_RPORT_REUSE_ONLY = 0x1001, - UNF_RPORT_REUSE_INIT = 0x1002, - UNF_RPORT_REUSE_RECOVER = 0x1003 -}; - -struct unf_disc_rport { - /* RPort entry */ - struct list_head entry_rport; - - u32 nport_id; /* Remote port NPortID */ - u32 disc_done; /* 1:Disc done */ -}; - -struct unf_rport_feature_pool { - struct list_head list_busy_head; - struct list_head list_free_head; - void *port_feature_pool_addr; - spinlock_t port_fea_pool_lock; -}; - -struct unf_rport_feature_recard { - struct list_head entry_feature; - u64 wwpn; - u32 port_feature; - u32 reserved; -}; - -struct unf_os_thread_private_data { - struct list_head list; - spinlock_t spin_lock; - struct task_struct *thread; - unsigned int in_process; - unsigned int cpu_id; - atomic_t user_count; -}; - -/* Remote Port struct */ -struct unf_rport { - u32 max_frame_size; - u32 supported_classes; - - /* Dynamic Attributes */ - /* Remote Port loss timeout in seconds. */ - u32 dev_loss_tmo; - - u64 node_name; - u64 port_name; - u32 nport_id; /* Remote port NPortID */ - u32 local_nport_id; - - u32 roles; - - /* Remote port local INI state */ - enum unf_port_state lport_ini_state; - enum unf_port_state last_lport_ini_state; - - /* Remote port local TGT state */ - enum unf_port_state lport_tgt_state; - enum unf_port_state last_lport_tgt_state; - - /* Port Type,fc or fcoe */ - u32 port_type; - - /* RPort reference counter */ - atomic_t rport_ref_cnt; - - /* Pending IO count */ - atomic_t pending_io_cnt; - - /* RPort entry */ - struct list_head entry_rport; - - /* Port State,delay reclaim when uiRpState == complete. */ - enum unf_rport_login_state rp_state; - u32 disc_done; /* 1:Disc done */ - - struct unf_lport *lport; - void *rport; - spinlock_t rport_state_lock; - - /* Port attribution */ - u32 ed_tov; - u32 ra_tov; - u32 options; /* ini or tgt */ - u32 last_report_link_up_options; - u32 fcp_conf_needed; /* INI Rport send FCP CONF flag */ - u32 tape_support_needed; /* INI tape support flag */ - u32 retries; /* special req retry times */ - u32 logo_retries; /* logo error recovery retry times */ - u32 max_retries; /* special req retry times */ - u64 rport_alloc_jifs; /* Rport alloc jiffies */ - - void *session; - - /* binding with SCSI */ - u32 scsi_id; - - /* disc list compare flag */ - u32 rscn_position; - - u32 rport_index; - - u32 sqn_base; - enum unf_rport_qos_level qos_level; - - /* RPort timer,closing status */ - struct work_struct closing_work; - - /* RPort timer,rport linkup */ - struct work_struct start_work; - - /* RPort timer,recovery */ - struct delayed_work recovery_work; - - /* RPort timer,TGT mode,PRLI waiting */ - struct delayed_work open_work; - - struct semaphore task_sema; - /* Callback after rport Ready/delete.[with state:ok/fail].Creat/free TGT session here */ - /* input : L_Port,R_Port,state:ready --creat session/delete--free session */ - void (*unf_rport_callback)(void *rport, void *lport, u32 result); - - struct unf_os_thread_private_data *data_thread; -}; - -#define UNF_IO_RESULT_CNT(scsi_table, scsi_id, io_result) \ - do { \ - if (likely(((io_result) < UNF_MAX_IO_RETURN_VALUE) && \ - ((scsi_id) < UNF_MAX_SCSI_ID) && \ - ((scsi_table)->wwn_rport_info_table) && \ - (((scsi_table)->wwn_rport_info_table[scsi_id].dfx_counter)))) {\ - atomic64_inc(&((scsi_table)->wwn_rport_info_table[scsi_id] \ - .dfx_counter->io_done_cnt[(io_result)])); \ - } else { \ - FC_DRV_PRINT(UNF_LOG_EQUIP_ATT, \ - UNF_ERR, \ - "[err] io return value(0x%x) or " \ - "scsi id(0x%x) is invalid", \ - io_result, scsi_id); \ - } \ - } while (0) - -#define UNF_SCSI_CMD_CNT(scsi_table, scsi_id, io_type) \ - do { \ - if (likely(((io_type) < UNF_MAX_SCSI_CMD) && \ - ((scsi_id) < UNF_MAX_SCSI_ID) && \ - ((scsi_table)->wwn_rport_info_table) && \ - (((scsi_table)->wwn_rport_info_table[scsi_id].dfx_counter)))) { \ - atomic64_inc(&(((scsi_table)->wwn_rport_info_table[scsi_id]) \ - .dfx_counter->scsi_cmd_cnt[io_type])); \ - } else { \ - FC_DRV_PRINT(UNF_LOG_EQUIP_ATT, \ - UNF_ERR, \ - "[err] scsi_cmd(0x%x) or scsi id(0x%x) " \ - "is invalid", \ - io_type, scsi_id); \ - } \ - } while (0) - -#define UNF_SCSI_ERROR_HANDLE_CNT(scsi_table, scsi_id, io_type) \ - do { \ - if (likely(((io_type) < UNF_SCSI_ERROR_HANDLE_BUTT) && \ - ((scsi_id) < UNF_MAX_SCSI_ID) && \ - ((scsi_table)->wwn_rport_info_table) && \ - (((scsi_table)->wwn_rport_info_table[scsi_id] \ - .dfx_counter)))) { \ - atomic_inc(&((scsi_table)->wwn_rport_info_table[scsi_id] \ - .dfx_counter->error_handle[io_type])); \ - } else { \ - FC_DRV_PRINT(UNF_LOG_EQUIP_ATT, \ - UNF_ERR, \ - "[err] scsi_cmd(0x%x) or scsi id(0x%x) " \ - "is invalid", \ - (io_type), (scsi_id)); \ - } \ - } while (0) - -#define UNF_SCSI_ERROR_HANDLE_RESULT_CNT(scsi_table, scsi_id, io_type) \ - do { \ - if (likely(((io_type) < UNF_SCSI_ERROR_HANDLE_BUTT) && \ - ((scsi_id) < UNF_MAX_SCSI_ID) && \ - ((scsi_table)->wwn_rport_info_table) &&\ - (((scsi_table)-> \ - wwn_rport_info_table[scsi_id].dfx_counter)))) { \ - atomic_inc(&( \ - (scsi_table) \ - ->wwn_rport_info_table[scsi_id] \ - .dfx_counter->error_handle_result[io_type])); \ - } else { \ - FC_DRV_PRINT(UNF_LOG_EQUIP_ATT, \ - UNF_ERR, \ - "[err] scsi_cmd(0x%x) or scsi id(0x%x) " \ - "is invalid", \ - io_type, scsi_id); \ - } \ - } while (0) - -void unf_rport_state_ma(struct unf_rport *rport, enum unf_rport_event event); -void unf_update_lport_state_by_linkup_event(struct unf_lport *lport, - struct unf_rport *rport, - u32 rport_att); - -void unf_set_rport_state(struct unf_rport *rport, enum unf_rport_login_state states); -void unf_rport_enter_closing(struct unf_rport *rport); -u32 unf_release_rport_res(struct unf_lport *lport, struct unf_rport *rport); -u32 unf_initrport_mgr_temp(struct unf_lport *lport); -void unf_clean_linkdown_rport(struct unf_lport *lport); -void unf_rport_error_recovery(struct unf_rport *rport); -struct unf_rport *unf_get_rport_by_nport_id(struct unf_lport *lport, u32 nport_id); -struct unf_rport *unf_get_rport_by_wwn(struct unf_lport *lport, u64 wwpn); -void unf_rport_enter_logo(struct unf_lport *lport, struct unf_rport *rport); -u32 unf_rport_ref_inc(struct unf_rport *rport); -void unf_rport_ref_dec(struct unf_rport *rport); - -struct unf_rport *unf_rport_set_qualifier_key_reuse(struct unf_lport *lport, - struct unf_rport *rport_by_nport_id, - struct unf_rport *rport_by_wwpn, - u64 wwpn, u32 sid); -void unf_rport_delay_login(struct unf_rport *rport); -struct unf_rport *unf_find_valid_rport(struct unf_lport *lport, u64 wwpn, - u32 sid); -void unf_rport_linkdown(struct unf_lport *lport, struct unf_rport *rport); -void unf_apply_for_session(struct unf_lport *lport, struct unf_rport *rport); -struct unf_rport *unf_get_safe_rport(struct unf_lport *lport, - struct unf_rport *rport, - enum unf_rport_reuse_flag reuse_flag, - u32 nport_id); -void *unf_rport_get_free_and_init(void *lport, u32 port_type, u32 nport_id); - -void unf_set_device_state(struct unf_lport *lport, u32 scsi_id, int scsi_state); -u32 unf_get_scsi_id_by_wwpn(struct unf_lport *lport, u64 wwpn); -u32 unf_get_device_state(struct unf_lport *lport, u32 scsi_id); -u32 unf_free_scsi_id(struct unf_lport *lport, u32 scsi_id); -void unf_schedule_closing_work(struct unf_lport *lport, struct unf_rport *rport); -void unf_sesion_loss_timeout(struct work_struct *work); -u32 unf_get_port_feature(u64 wwpn); -void unf_update_port_feature(u64 wwpn, u32 port_feature); - -#endif diff --git a/drivers/scsi/spfc/common/unf_scsi.c b/drivers/scsi/spfc/common/unf_scsi.c deleted file mode 100644 index 3615d95c77e9..000000000000 --- a/drivers/scsi/spfc/common/unf_scsi.c +++ /dev/null @@ -1,1462 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#include "unf_type.h" -#include "unf_log.h" -#include "unf_scsi_common.h" -#include "unf_lport.h" -#include "unf_rport.h" -#include "unf_portman.h" -#include "unf_exchg.h" -#include "unf_exchg_abort.h" -#include "unf_npiv.h" -#include "unf_io.h" - -#define UNF_LUN_ID_MASK 0x00000000ffff0000 -#define UNF_CMD_PER_LUN 3 - -static int unf_scsi_queue_cmd(struct Scsi_Host *phost, struct scsi_cmnd *pcmd); -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 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))} -}; - -u32 ini_err_code_table_cnt1 = sizeof(ini_error_code_table1) / sizeof(struct unf_ini_error_code); - -static void unf_set_rport_loss_tmo(struct fc_rport *rport, u32 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 *unf_lport = NULL; - - unf_lport = (struct unf_lport *)shost->hostdata[0]; - if (unlikely(!unf_lport)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, "[err]Port is null"); - return; - } - - fc_host_port_id(shost) = unf_lport->port_id; -} - -static void unf_get_host_speed(struct Scsi_Host *shost) -{ - struct unf_lport *unf_lport = NULL; - u32 speed = FC_PORTSPEED_UNKNOWN; - - unf_lport = (struct unf_lport *)shost->hostdata[0]; - if (unlikely(!unf_lport)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, "[err]Port is null"); - return; - } - - switch (unf_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: - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) with unknown speed(0x%x) for FC mode", - unf_lport->port_id, unf_lport->speed); - break; - } - - fc_host_speed(shost) = speed; -} - -static void unf_get_host_port_type(struct Scsi_Host *shost) -{ - struct unf_lport *unf_lport = NULL; - u32 port_type = FC_PORTTYPE_UNKNOWN; - - unf_lport = (struct unf_lport *)shost->hostdata[0]; - if (unlikely(!unf_lport)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, "[err]Port is null"); - return; - } - - switch (unf_lport->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: - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) with unknown topo type(0x%x) for FC mode", - unf_lport->port_id, unf_lport->act_topo); - break; - } - - fc_host_port_type(shost) = port_type; -} - -static void unf_get_symbolic_name(struct Scsi_Host *shost) -{ - u8 *name = NULL; - struct unf_lport *unf_lport = NULL; - - unf_lport = (struct unf_lport *)(uintptr_t)shost->hostdata[0]; - if (unlikely(!unf_lport)) { - FC_DRV_PRINT(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, "SPFC_FW_RELEASE:%s SPFC_DRV_RELEASE:%s", - unf_lport->fw_version, SPFC_DRV_VERSION); -} - -static void unf_get_host_fabric_name(struct Scsi_Host *shost) -{ - struct unf_lport *unf_lport = NULL; - - unf_lport = (struct unf_lport *)shost->hostdata[0]; - - if (unlikely(!unf_lport)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, "[err]Port is null"); - return; - } - fc_host_fabric_name(shost) = unf_lport->fabric_node_name; -} - -static void unf_get_host_port_state(struct Scsi_Host *shost) -{ - struct unf_lport *unf_lport = NULL; - enum fc_port_state port_state; - - unf_lport = (struct unf_lport *)shost->hostdata[0]; - if (unlikely(!unf_lport)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, "[err]Port is null"); - return; - } - - switch (unf_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 *unf_lport = NULL; - u32 scsi_id = 0; - - if (unlikely(!rport)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, "[err]SCSI rport is null"); - return; - } - - host = rport_to_shost(rport); - if (unlikely(!host)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, "[err]Host is null"); - return; - } - - scsi_id = *(u32 *)(rport->dd_data); /* according to Local SCSI_ID */ - if (unlikely(scsi_id >= UNF_MAX_SCSI_ID)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]rport(0x%p) scsi_id(0x%x) is max than(0x%x)", - rport, scsi_id, UNF_MAX_SCSI_ID); - return; - } - - unf_lport = (struct unf_lport *)host->hostdata[0]; - if (unf_is_lport_valid(unf_lport) == RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "[event]Port(0x%x_0x%x) rport(0x%p) scsi_id(0x%x) target_id(0x%x) loss timeout", - unf_lport->port_id, unf_lport->nport_id, rport, - scsi_id, rport->scsi_target_id); - - atomic_inc(&unf_lport->session_loss_tmo); - - /* Free SCSI ID & set table state with DEAD */ - (void)unf_free_scsi_id(unf_lport, scsi_id); - unf_xchg_up_abort_io_by_scsi_id(unf_lport, scsi_id); - } else { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(%p) is invalid", unf_lport); - } - - *((u32 *)rport->dd_data) = INVALID_VALUE32; -} - -int unf_scsi_create_vport(struct fc_vport *fc_port, bool disabled) -{ - struct unf_lport *vport = NULL; - struct unf_lport *unf_lport = NULL; - struct Scsi_Host *shost = NULL; - struct vport_config vport_config = {0}; - - shost = vport_to_shost(fc_port); - - unf_lport = (struct unf_lport *)shost->hostdata[0]; - if (unf_is_lport_valid(unf_lport) != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(%p) is invalid", unf_lport); - - return RETURN_ERROR; - } - - vport_config.port_name = fc_port->port_name; - - vport_config.port_mode = fc_port->roles; - - vport = unf_creat_vport(unf_lport, &vport_config); - if (!vport) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) Create Vport failed on lldrive", - unf_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 *vport = NULL; - - vport = (struct unf_lport *)fc_port->dd_data; - if (unf_is_lport_valid(vport) != RETURN_OK) { - FC_DRV_PRINT(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) { - FC_DRV_PRINT(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 = 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 = NULL, - .vport_disable = NULL, - .vport_delete = NULL, - .bsg_request = NULL, - .bsg_timeout = NULL, -}; - -struct scsi_host_template scsi_host_template = { - .module = THIS_MODULE, - .name = "SPFC", - - .queuecommand = unf_scsi_queue_cmd, - .eh_timed_out = fc_eh_timed_out, - .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, /* this_id: -1 */ - .cmd_per_lun = UNF_CMD_PER_LUN, - .shost_attrs = NULL, - .sg_tablesize = SG_ALL, - .max_sectors = UNF_MAX_SECTORS, - .supported_mode = MODE_INITIATOR, -}; - -void unf_unmap_prot_sgl(struct scsi_cmnd *cmnd) -{ - struct device *dev = NULL; - - if ((scsi_get_prot_op(cmnd) != SCSI_PROT_NORMAL) && spfc_dif_enable && - (scsi_prot_sg_count(cmnd))) { - dev = cmnd->device->host->dma_dev; - dma_unmap_sg(dev, scsi_prot_sglist(cmnd), - (int)scsi_prot_sg_count(cmnd), - cmnd->sc_data_direction); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_INFO, - "scsi done cmd:%p op:%u, difsglcount:%u", cmnd, - scsi_get_prot_op(cmnd), scsi_prot_sg_count(cmnd)); - } -} - -void unf_scsi_done(struct unf_scsi_cmnd *scsi_cmd) -{ - struct scsi_cmnd *cmd = NULL; - - cmd = (struct scsi_cmnd *)scsi_cmd->upper_cmnd; - FC_CHECK_RETURN_VOID(scsi_cmd); - FC_CHECK_RETURN_VOID(cmd); - FC_CHECK_RETURN_VOID(cmd->scsi_done); - scsi_set_resid(cmd, (int)scsi_cmd->resid); - - cmd->result = scsi_cmd->result; - scsi_dma_unmap(cmd); - unf_unmap_prot_sgl(cmd); - return cmd->scsi_done(cmd); -} - -static void unf_get_protect_op(struct scsi_cmnd *cmd, - struct unf_dif_control_info *dif_control_info) -{ - 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; - } -} - -int unf_get_protect_mode(struct unf_lport *lport, struct scsi_cmnd *scsi_cmd, - struct unf_scsi_cmnd *unf_scsi_cmd) -{ - struct scsi_cmnd *cmd = NULL; - int dif_seg_cnt = 0; - struct unf_dif_control_info *dif_control_info = NULL; - - cmd = scsi_cmd; - dif_control_info = &unf_scsi_cmd->dif_control; - - unf_get_protect_op(cmd, dif_control_info); - - if (dif_sgl_mode) - dif_control_info->flags |= UNF_DIF_DOUBLE_SGL; - dif_control_info->flags |= ((cmd->device->sector_size) == SECTOR_SIZE_4096) - ? UNF_DIF_SECTSIZE_4KB : UNF_DIF_SECTSIZE_512; - 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 (cmd->device->sector_size == SECTOR_SIZE_4096) - dif_control_info->start_lba = dif_control_info->start_lba >> UNF_SHIFT_3; - - if (scsi_prot_sg_count(cmd)) { - dif_seg_cnt = 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(!dif_seg_cnt)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) cmd:%p map dif sgl err", - lport->port_id, cmd); - return UNF_RETURN_ERROR; - } - } - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_INFO, - "build scsi cmd:%p op:%u,difsglcount:%u,difsegcnt:%u", cmd, - scsi_get_prot_op(cmd), scsi_prot_sg_count(cmd), - dif_seg_cnt); - return RETURN_OK; -} - -static u32 unf_get_rport_qos_level(struct scsi_cmnd *cmd, u32 scsi_id, - struct unf_rport_scsi_id_image *scsi_image_table) -{ - enum unf_rport_qos_level level = 0; - - if (!scsi_image_table->wwn_rport_info_table[scsi_id].lun_qos_level || - cmd->device->lun >= UNF_MAX_LUN_PER_TARGET) { - level = 0; - } else { - level = (scsi_image_table->wwn_rport_info_table[scsi_id] - .lun_qos_level[cmd->device->lun]); - } - return level; -} - -u32 unf_get_frame_entry_buf(void *up_cmnd, void *driver_sgl, void **upper_sgl, - u32 *port_id, u32 *index, char **buf, u32 *buf_len) -{ -#define SPFC_MAX_DMA_LENGTH (0x20000 - 1) - struct scatterlist *scsi_sgl = *upper_sgl; - - if (unlikely(!scsi_sgl)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[err]Command(0x%p) can not get SGL.", up_cmnd); - return RETURN_ERROR; - } - *buf = (char *)sg_dma_address(scsi_sgl); - *buf_len = sg_dma_len(scsi_sgl); - *upper_sgl = (void *)sg_next(scsi_sgl); - if (unlikely((*buf_len > SPFC_MAX_DMA_LENGTH) || (*buf_len == 0))) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[err]Command(0x%p) dmalen:0x%x is not support.", - up_cmnd, *buf_len); - return RETURN_ERROR; - } - - return RETURN_OK; -} - -static void unf_init_scsi_cmnd(struct Scsi_Host *host, struct scsi_cmnd *cmd, - struct unf_scsi_cmnd *scsi_cmnd, - struct unf_rport_scsi_id_image *scsi_image_table, - int datasegcnt) -{ - static atomic64_t count; - enum unf_rport_qos_level level = 0; - u32 scsi_id = 0; - - scsi_id = (u32)((u64)cmd->device->hostdata); - level = unf_get_rport_qos_level(cmd, scsi_id, scsi_image_table); - scsi_cmnd->scsi_host_id = host->host_no; /* save host_no to scsi_cmnd->scsi_host_id */ - scsi_cmnd->scsi_id = scsi_id; - scsi_cmnd->raw_lun_id = ((u64)cmd->device->lun << 16) & UNF_LUN_ID_MASK; - scsi_cmnd->data_direction = cmd->sc_data_direction; - scsi_cmnd->under_flow = 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_buflen = UNF_SCSI_SENSE_BUFFERSIZE; - scsi_cmnd->sense_buf = cmd->sense_buffer; - scsi_cmnd->time_out = 0; - scsi_cmnd->upper_cmnd = cmd; - scsi_cmnd->drv_private = (void *)(*(u64 *)shost_priv(host)); - scsi_cmnd->entry_count = datasegcnt; - scsi_cmnd->sgl = scsi_sglist(cmd); - scsi_cmnd->unf_ini_get_sgl_entry = unf_get_frame_entry_buf; - scsi_cmnd->done = unf_scsi_done; - scsi_cmnd->lun_id = (u8 *)&scsi_cmnd->raw_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 = INVALID_WORLD_ID; - scsi_cmnd->cmnd_sn = atomic64_inc_return(&count); - scsi_cmnd->qos_level = level; - if (unlikely(scsi_cmnd->cmnd_sn == 0)) - scsi_cmnd->cmnd_sn = atomic64_inc_return(&count); -} - -static void unf_io_error_done(struct scsi_cmnd *cmd, - struct unf_rport_scsi_id_image *scsi_image_table, - u32 scsi_id, u32 result) -{ - cmd->result = (int)(result << UNF_SHIFT_16); - cmd->scsi_done(cmd); - if (scsi_image_table) - UNF_IO_RESULT_CNT(scsi_image_table, scsi_id, result); -} - -static bool unf_scan_device_cmd(struct scsi_cmnd *cmd) -{ - return ((cmd->cmnd[0] == INQUIRY) || (cmd->cmnd[0] == REPORT_LUNS)); -} - -static int unf_scsi_queue_cmd(struct Scsi_Host *phost, struct scsi_cmnd *pcmd) -{ - struct Scsi_Host *host = NULL; - struct scsi_cmnd *cmd = NULL; - struct unf_scsi_cmnd scsi_cmd = {0}; - u32 scsi_id = 0; - u32 scsi_state = 0; - int ret = SCSI_MLQUEUE_HOST_BUSY; - struct unf_lport *unf_lport = NULL; - struct fc_rport *rport = NULL; - struct unf_rport_scsi_id_image *scsi_image_table = NULL; - struct unf_rport *unf_rport = NULL; - u32 cmnd_result = 0; - u32 rport_state_err = 0; - bool scan_device_cmd = false; - int datasegcnt = 0; - - host = phost; - cmd = pcmd; - FC_CHECK_RETURN_VALUE(host, RETURN_ERROR); - FC_CHECK_RETURN_VALUE(cmd, RETURN_ERROR); - - /* Get L_Port from scsi_cmd */ - unf_lport = (struct unf_lport *)host->hostdata[0]; - if (unlikely(!unf_lport)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Check l_port failed, cmd(%p)", cmd); - unf_io_error_done(cmd, scsi_image_table, scsi_id, DID_NO_CONNECT); - return 0; - } - - /* Check device/session local state by device_id */ - scsi_id = (u32)((u64)cmd->device->hostdata); - if (unlikely(scsi_id >= UNF_MAX_SCSI_ID)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) scsi_id(0x%x) is max than %d", - unf_lport->port_id, scsi_id, UNF_MAX_SCSI_ID); - unf_io_error_done(cmd, scsi_image_table, scsi_id, DID_NO_CONNECT); - return 0; - } - - scsi_image_table = &unf_lport->rport_scsi_table; - UNF_SCSI_CMD_CNT(scsi_image_table, scsi_id, cmd->cmnd[0]); - - /* Get scsi r_port */ - rport = starget_to_rport(scsi_target(cmd->device)); - if (unlikely(!rport)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) cmd(%p) to get scsi rport failed", - unf_lport->port_id, cmd); - unf_io_error_done(cmd, scsi_image_table, scsi_id, DID_NO_CONNECT); - return 0; - } - - if (unlikely(!scsi_image_table->wwn_rport_info_table)) { - FC_DRV_PRINT(UNF_LOG_ABNORMAL, UNF_WARN, - "[warn]LPort porid(0x%x) WwnRportInfoTable NULL", - unf_lport->port_id); - unf_io_error_done(cmd, scsi_image_table, scsi_id, DID_NO_CONNECT); - return 0; - } - - if (unlikely(unf_lport->port_removing)) { - FC_DRV_PRINT(UNF_LOG_ABNORMAL, UNF_WARN, - "[warn]Port(0x%x) scsi_id(0x%x) rport(0x%p) target_id(0x%x) cmd(0x%p) unf_lport removing", - unf_lport->port_id, scsi_id, rport, rport->scsi_target_id, cmd); - unf_io_error_done(cmd, scsi_image_table, scsi_id, DID_NO_CONNECT); - return 0; - } - - scsi_state = atomic_read(&scsi_image_table->wwn_rport_info_table[scsi_id].scsi_state); - if (unlikely(scsi_state != UNF_SCSI_ST_ONLINE)) { - if (scsi_state == UNF_SCSI_ST_OFFLINE) { - FC_DRV_PRINT(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", - unf_lport->port_id, scsi_state, scsi_id, rport, - rport->scsi_target_id, cmd); - - scan_device_cmd = unf_scan_device_cmd(cmd); - /* 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) { - FC_DRV_PRINT(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", - unf_lport->port_id, host->host_no, scsi_id, - (u64)cmd->device->lun, cmd->cmnd[0]); - unf_io_error_done(cmd, scsi_image_table, scsi_id, DID_NO_CONNECT); - 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 */ - FC_DRV_PRINT(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", - unf_lport->port_id, scsi_id, rport, - rport->scsi_target_id, cmd); - unf_io_error_done(cmd, scsi_image_table, scsi_id, DID_NO_CONNECT); - return 0; - } - - if (scsi_sg_count(cmd)) { - datasegcnt = dma_map_sg(&unf_lport->low_level_func.dev->dev, scsi_sglist(cmd), - (int)scsi_sg_count(cmd), cmd->sc_data_direction); - if (unlikely(!datasegcnt)) { - FC_DRV_PRINT(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", - unf_lport->port_id, scsi_id, rport, - rport->scsi_target_id, cmd); - unf_io_error_done(cmd, scsi_image_table, scsi_id, DID_BUS_BUSY); - return SCSI_MLQUEUE_HOST_BUSY; - } - } - - /* Construct local SCSI CMND info */ - unf_init_scsi_cmnd(host, cmd, &scsi_cmd, scsi_image_table, datasegcnt); - - if ((scsi_get_prot_op(cmd) != SCSI_PROT_NORMAL) && spfc_dif_enable) { - ret = unf_get_protect_mode(unf_lport, cmd, &scsi_cmd); - if (ret != RETURN_OK) { - unf_io_error_done(cmd, scsi_image_table, scsi_id, DID_BUS_BUSY); - scsi_dma_unmap(cmd); - return SCSI_MLQUEUE_HOST_BUSY; - } - } - - FC_DRV_PRINT(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) protect_opcode is (0x%x) dif_sgl_mode is %d, sector size(%d)", - unf_lport->port_id, host->host_no, scsi_id, (u64)cmd->device->lun, - scsi_cmd.transfer_len, scsi_cmd.cmnd_len, cmd->sc_data_direction, - scsi_cmd.pcmnd[0], scsi_cmd.under_flow, - scsi_cmd.dif_control.protect_opcode, dif_sgl_mode, - (cmd->device->sector_size)); - - /* Bind the Exchange address corresponding to scsi_cmd to - * scsi_cmd->host_scribble - */ - cmd->host_scribble = (unsigned char *)scsi_cmd.cmnd_sn; - ret = unf_cm_queue_command(&scsi_cmd); - if (ret != RETURN_OK) { - unf_rport = unf_find_rport_by_scsi_id(unf_lport, ini_error_code_table1, - ini_err_code_table_cnt1, - scsi_id, &cmnd_result); - rport_state_err = (!unf_rport) || - (unf_rport->lport_ini_state != UNF_PORT_STATE_LINKUP) || - (unf_rport->rp_state == UNF_RPORT_ST_CLOSING); - scan_device_cmd = unf_scan_device_cmd(cmd); - - /* 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) { - FC_DRV_PRINT(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", - unf_lport->port_id, host->host_no, scsi_id, - (u64)cmd->device->lun, cmd->cmnd[0], - cmnd_result); - unf_io_error_done(cmd, scsi_image_table, scsi_id, DID_NO_CONNECT); - 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); - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) return(0x%x) to process INI IO falid", - unf_lport->port_id, ret); - } - return ret; -} - -static void unf_init_abts_tmf_scsi_cmd(struct scsi_cmnd *cmnd, - struct unf_scsi_cmnd *scsi_cmd, - bool abort_cmd) -{ - struct Scsi_Host *scsi_host = NULL; - - scsi_host = cmnd->device->host; - scsi_cmd->scsi_host_id = scsi_host->host_no; - scsi_cmd->scsi_id = (u32)((u64)cmnd->device->hostdata); - scsi_cmd->raw_lun_id = (u64)cmnd->device->lun; - scsi_cmd->upper_cmnd = cmnd; - scsi_cmd->drv_private = (void *)(*(u64 *)shost_priv(scsi_host)); - scsi_cmd->cmnd_sn = (u64)(cmnd->host_scribble); - scsi_cmd->lun_id = (u8 *)&scsi_cmd->raw_lun_id; - if (abort_cmd) { - scsi_cmd->done = unf_scsi_done; - scsi_cmd->world_id = INVALID_WORLD_ID; - } -} - -int unf_scsi_abort_scsi_cmnd(struct scsi_cmnd *cmnd) -{ - /* SCSI ABORT Command --->>> FC ABTS */ - struct unf_scsi_cmnd scsi_cmd = {0}; - int ret = FAILED; - struct unf_rport_scsi_id_image *scsi_image_table = NULL; - struct unf_lport *unf_lport = NULL; - u32 scsi_id = 0; - u32 err_handle = 0; - - FC_CHECK_RETURN_VALUE(cmnd, FAILED); - - unf_lport = (struct unf_lport *)cmnd->device->host->hostdata[0]; - scsi_id = (u32)((u64)cmnd->device->hostdata); - - if (unf_is_lport_valid(unf_lport) == RETURN_OK) { - scsi_image_table = &unf_lport->rport_scsi_table; - err_handle = UNF_SCSI_ABORT_IO_TYPE; - UNF_SCSI_ERROR_HANDLE_CNT(scsi_image_table, scsi_id, err_handle); - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[abort]Port(0x%x) scsi_id(0x%x) lun_id(0x%x) cmnd_type(0x%x)", - unf_lport->port_id, scsi_id, - (u32)cmnd->device->lun, cmnd->cmnd[0]); - } else { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Lport(%p) is moving or null", unf_lport); - return UNF_SCSI_ABORT_FAIL; - } - - /* Check local SCSI_ID validity */ - if (unlikely(scsi_id >= UNF_MAX_SCSI_ID)) { - FC_DRV_PRINT(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(cmnd); - if (unlikely(ret != 0)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Block scsi eh failed(0x%x)", ret); - return ret; - } - - unf_init_abts_tmf_scsi_cmd(cmnd, &scsi_cmd, true); - /* Process scsi Abort cmnd */ - ret = unf_cm_eh_abort_handler(&scsi_cmd); - if (ret == UNF_SCSI_ABORT_SUCCESS) { - if (unf_is_lport_valid(unf_lport) == RETURN_OK) { - scsi_image_table = &unf_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; -} - -int unf_scsi_device_reset_handler(struct scsi_cmnd *cmnd) -{ - /* LUN reset */ - struct unf_scsi_cmnd scsi_cmd = {0}; - struct unf_rport_scsi_id_image *scsi_image_table = NULL; - int ret = FAILED; - struct unf_lport *unf_lport = NULL; - u32 scsi_id = 0; - u32 err_handle = 0; - - FC_CHECK_RETURN_VALUE(cmnd, FAILED); - - unf_lport = (struct unf_lport *)cmnd->device->host->hostdata[0]; - if (unf_is_lport_valid(unf_lport) == RETURN_OK) { - scsi_image_table = &unf_lport->rport_scsi_table; - err_handle = UNF_SCSI_DEVICE_RESET_TYPE; - UNF_SCSI_ERROR_HANDLE_CNT(scsi_image_table, scsi_id, err_handle); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_KEVENT, - "[device_reset]Port(0x%x) scsi_id(0x%x) lun_id(0x%x) cmnd_type(0x%x)", - unf_lport->port_id, scsi_id, (u32)cmnd->device->lun, cmnd->cmnd[0]); - } else { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, "[err]Port is invalid"); - - return FAILED; - } - - /* Check local SCSI_ID validity */ - scsi_id = (u32)((u64)cmnd->device->hostdata); - if (unlikely(scsi_id >= UNF_MAX_SCSI_ID)) { - FC_DRV_PRINT(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(cmnd); - if (unlikely(ret != 0)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Block scsi eh failed(0x%x)", ret); - - return ret; - } - - unf_init_abts_tmf_scsi_cmd(cmnd, &scsi_cmd, false); - /* Process scsi device/LUN reset cmnd */ - ret = unf_cm_eh_device_reset_handler(&scsi_cmd); - if (ret == UNF_SCSI_ABORT_SUCCESS) { - if (unf_is_lport_valid(unf_lport) == RETURN_OK) { - scsi_image_table = &unf_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; -} - -int unf_scsi_bus_reset_handler(struct scsi_cmnd *cmnd) -{ - /* BUS Reset */ - struct unf_scsi_cmnd scsi_cmd = {0}; - struct unf_lport *unf_lport = NULL; - struct unf_rport_scsi_id_image *scsi_image_table = NULL; - int ret = FAILED; - u32 scsi_id = 0; - u32 err_handle = 0; - - FC_CHECK_RETURN_VALUE(cmnd, FAILED); - - unf_lport = (struct unf_lport *)cmnd->device->host->hostdata[0]; - if (unlikely(!unf_lport)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port is null"); - - return FAILED; - } - - /* Check local SCSI_ID validity */ - scsi_id = (u32)((u64)cmnd->device->hostdata); - if (unlikely(scsi_id >= UNF_MAX_SCSI_ID)) { - FC_DRV_PRINT(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(unf_lport) == RETURN_OK) { - scsi_image_table = &unf_lport->rport_scsi_table; - err_handle = UNF_SCSI_BUS_RESET_TYPE; - UNF_SCSI_ERROR_HANDLE_CNT(scsi_image_table, scsi_id, err_handle); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info][bus_reset]Port(0x%x) scsi_id(0x%x) lun_id(0x%x) cmnd_type(0x%x)", - unf_lport->port_id, scsi_id, (u32)cmnd->device->lun, - cmnd->cmnd[0]); - } - - /* Block scsi (check rport state -> whether offline or not) */ - ret = fc_block_scsi_eh(cmnd); - if (unlikely(ret != 0)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Block scsi eh failed(0x%x)", ret); - - return ret; - } - - unf_init_abts_tmf_scsi_cmd(cmnd, &scsi_cmd, false); - /* Process scsi BUS Reset cmnd */ - ret = unf_cm_bus_reset_handler(&scsi_cmd); - if (ret == UNF_SCSI_ABORT_SUCCESS) { - if (unf_is_lport_valid(unf_lport) == RETURN_OK) { - scsi_image_table = &unf_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; -} - -int unf_scsi_target_reset_handler(struct scsi_cmnd *cmnd) -{ - /* Session reset/delete */ - struct unf_scsi_cmnd scsi_cmd = {0}; - struct unf_rport_scsi_id_image *scsi_image_table = NULL; - int ret = FAILED; - struct unf_lport *unf_lport = NULL; - u32 scsi_id = 0; - u32 err_handle = 0; - - FC_CHECK_RETURN_VALUE(cmnd, RETURN_ERROR); - - unf_lport = (struct unf_lport *)cmnd->device->host->hostdata[0]; - if (unlikely(!unf_lport)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port is null"); - - return FAILED; - } - - /* Check local SCSI_ID validity */ - scsi_id = (u32)((u64)cmnd->device->hostdata); - if (unlikely(scsi_id >= UNF_MAX_SCSI_ID)) { - FC_DRV_PRINT(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(unf_lport) == RETURN_OK) { - scsi_image_table = &unf_lport->rport_scsi_table; - err_handle = UNF_SCSI_TARGET_RESET_TYPE; - UNF_SCSI_ERROR_HANDLE_CNT(scsi_image_table, scsi_id, err_handle); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_KEVENT, - "[target_reset]Port(0x%x) scsi_id(0x%x) lun_id(0x%x) cmnd_type(0x%x)", - unf_lport->port_id, scsi_id, (u32)cmnd->device->lun, cmnd->cmnd[0]); - } - - /* Block scsi (check rport state -> whether offline or not) */ - ret = fc_block_scsi_eh(cmnd); - if (unlikely(ret != 0)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Block scsi eh failed(0x%x)", ret); - - return ret; - } - - unf_init_abts_tmf_scsi_cmd(cmnd, &scsi_cmd, false); - /* Process scsi Target/Session reset/delete cmnd */ - ret = unf_cm_target_reset_handler(&scsi_cmd); - if (ret == UNF_SCSI_ABORT_SUCCESS) { - if (unf_is_lport_valid(unf_lport) == RETURN_OK) { - scsi_image_table = &unf_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) -{ - struct fc_rport *rport = NULL; - u32 scsi_id = 0; - struct unf_lport *unf_lport = NULL; - struct Scsi_Host *host = NULL; - struct unf_rport_scsi_id_image *scsi_image_table = NULL; - - /* About device */ - if (unlikely(!sdev)) { - FC_DRV_PRINT(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))) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, "[err]SCSI rport is null"); - - if (rport) { - FC_DRV_PRINT(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)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, "[err]Host is null"); - - return -ENXIO; - } - - /* About Local Port */ - unf_lport = (struct unf_lport *)host->hostdata[0]; - if (unf_is_lport_valid(unf_lport) != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, "[err]Port is invalid"); - - return -ENXIO; - } - - /* About Local SCSI_ID */ - scsi_id = - *(u32 *)rport->dd_data; - if (unlikely(scsi_id >= UNF_MAX_SCSI_ID)) { - FC_DRV_PRINT(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 = &unf_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(&unf_lport->device_alloc); - sdev->hostdata = (void *)(u64)scsi_id; - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_KEVENT, - "[event]Port(0x%x) use scsi_id(%u) to alloc device[%u:%u:%u:%u]", - unf_lport->port_id, scsi_id, host->host_no, sdev->channel, sdev->id, - (u32)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 - */ - struct fc_rport *rport = NULL; - u32 scsi_id = 0; - struct unf_lport *unf_lport = NULL; - struct Scsi_Host *host = NULL; - struct unf_rport_scsi_id_image *scsi_image_table = NULL; - - /* About scsi device */ - if (unlikely(!sdev)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]SDev is null"); - - return; - } - - /* About scsi rport */ - rport = starget_to_rport(scsi_target(sdev)); - if (unlikely(!rport)) { - FC_DRV_PRINT(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)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, "[err]Host is null"); - - return; - } - - /* About L_Port */ - unf_lport = (struct unf_lport *)host->hostdata[0]; - if (unf_is_lport_valid(unf_lport) == RETURN_OK) { - scsi_image_table = &unf_lport->rport_scsi_table; - atomic_inc(&unf_lport->device_destroy); - - scsi_id = (u32)((u64)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); - } - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_KEVENT, - "[event]Port(0x%x) with scsi_id(%u) to destroy slave device[%u:%u:%u:%u]", - unf_lport->port_id, scsi_id, host->host_no, - sdev->channel, sdev->id, (u32)sdev->lun); - } else { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[err]Port(0x%x) scsi_id(%u) is invalid and destroy device[%u:%u:%u:%u]", - unf_lport->port_id, scsi_id, host->host_no, - sdev->channel, sdev->id, (u32)sdev->lun); - } - } else { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(%p) is invalid", unf_lport); - } - - sdev->hostdata = NULL; -} - -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); - - FC_DRV_PRINT(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) -{ - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[event]Scan finished"); - - return 1; -} - -static void unf_scsi_scan_start(struct Scsi_Host *shost) -{ - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[event]Start scsi scan..."); -} - -void unf_host_init_attr_setting(struct Scsi_Host *scsi_host) -{ - struct unf_lport *unf_lport = NULL; - u32 speed = FC_PORTSPEED_UNKNOWN; - - unf_lport = (struct unf_lport *)scsi_host->hostdata[0]; - fc_host_supported_classes(scsi_host) = FC_COS_CLASS3; - fc_host_dev_loss_tmo(scsi_host) = (u32)unf_get_link_lose_tmo(unf_lport); - fc_host_node_name(scsi_host) = unf_lport->node_name; - fc_host_port_name(scsi_host) = unf_lport->port_name; - - fc_host_max_npiv_vports(scsi_host) = (u16)((unf_lport == unf_lport->root_lport) ? - unf_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 (unf_lport->low_level_func.fc_ser_max_speed == UNF_PORT_SPEED_32_G && - unf_lport->card_type == UNF_FC_SERVER_BOARD_32_G) { - speed = FC_PORTSPEED_32GBIT | FC_PORTSPEED_16GBIT | FC_PORTSPEED_8GBIT; - } else if (unf_lport->low_level_func.fc_ser_max_speed == UNF_PORT_SPEED_16_G && - unf_lport->card_type == UNF_FC_SERVER_BOARD_16_G) { - speed = FC_PORTSPEED_16GBIT | FC_PORTSPEED_8GBIT | FC_PORTSPEED_4GBIT; - } else if (unf_lport->low_level_func.fc_ser_max_speed == UNF_PORT_SPEED_8_G && - unf_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(struct Scsi_Host **unf_scsi_host, - struct unf_host_param *host_param) -{ - int ret = RETURN_ERROR; - struct Scsi_Host *scsi_host = NULL; - struct unf_lport *unf_lport = NULL; - - FC_CHECK_RETURN_VALUE(unf_scsi_host, RETURN_ERROR); - FC_CHECK_RETURN_VALUE(host_param, RETURN_ERROR); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, "[event]Alloc scsi host..."); - - /* Check L_Port validity */ - unf_lport = (struct unf_lport *)(host_param->lport); - if (unlikely(!unf_lport)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port is NULL and return directly"); - - return RETURN_ERROR; - } - - scsi_host_template.can_queue = host_param->can_queue; - scsi_host_template.cmd_per_lun = host_param->cmnd_per_lun; - scsi_host_template.sg_tablesize = host_param->sg_table_size; - scsi_host_template.max_sectors = host_param->max_sectors; - - /* Alloc scsi host */ - scsi_host = scsi_host_alloc(&scsi_host_template, sizeof(u64)); - if (unlikely(!scsi_host)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, "[err]Register scsi host failed"); - - return RETURN_ERROR; - } - - scsi_host->max_channel = host_param->max_channel; - scsi_host->max_lun = host_param->max_lun; - scsi_host->max_cmd_len = host_param->max_cmnd_len; - scsi_host->unchecked_isa_dma = 0; - scsi_host->hostdata[0] = (unsigned long)(uintptr_t)unf_lport; /* save lport to scsi */ - scsi_host->unique_id = scsi_host->host_no; - scsi_host->max_id = host_param->max_id; - scsi_host->transportt = (unf_lport == unf_lport->root_lport) - ? scsi_transport_template - : scsi_transport_template_v; - - /* register DIF/DIX protection */ - if (spfc_dif_enable) { - /* Enable DIF and DIX function */ - scsi_host_set_prot(scsi_host, spfc_dif_type); - - spfc_guard = SHOST_DIX_GUARD_CRC; - /* Enable IP checksum algorithm in DIX */ - if (dix_flag) - spfc_guard |= SHOST_DIX_GUARD_IP; - scsi_host_set_guard(scsi_host, spfc_guard); - } - - /* Add scsi host */ - ret = scsi_add_host(scsi_host, host_param->pdev); - if (unlikely(ret)) { - FC_DRV_PRINT(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); - *unf_scsi_host = scsi_host; - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[event]Alloc and add scsi host(0x%llx) succeed", - (u64)scsi_host); - - return RETURN_OK; -} - -void unf_free_scsi_host(struct Scsi_Host *unf_scsi_host) -{ - struct Scsi_Host *scsi_host = NULL; - - scsi_host = unf_scsi_host; - fc_remove_host(scsi_host); - scsi_remove_host(scsi_host); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[event]Remove scsi host(%u) succeed", scsi_host->host_no); - - scsi_host_put(scsi_host); -} - -u32 unf_register_ini_transport(void) -{ - /* Register INI Transport */ - scsi_transport_template = fc_attach_transport(&function_template); - - if (!scsi_transport_template) { - FC_DRV_PRINT(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) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Register FC vport transport to scsi failed"); - - fc_release_transport(scsi_transport_template); - - return RETURN_ERROR; - } - - FC_DRV_PRINT(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); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[event]Unregister FC transport succeed"); -} - -void unf_save_sense_data(void *scsi_cmd, const char *sense, int sens_len) -{ - struct scsi_cmnd *cmd = NULL; - - FC_CHECK_RETURN_VOID(scsi_cmd); - FC_CHECK_RETURN_VOID(sense); - - cmd = (struct scsi_cmnd *)scsi_cmd; - memcpy(cmd->sense_buffer, sense, sens_len); -} diff --git a/drivers/scsi/spfc/common/unf_scsi_common.h b/drivers/scsi/spfc/common/unf_scsi_common.h deleted file mode 100644 index f20cdd7f0479..000000000000 --- a/drivers/scsi/spfc/common/unf_scsi_common.h +++ /dev/null @@ -1,570 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef UNF_SCSI_COMMON_H -#define UNF_SCSI_COMMON_H - -#include "unf_type.h" - -#define SCSI_SENSE_DATA_LEN 96 -#define DRV_SCSI_CDB_LEN 16 -#define DRV_SCSI_LUN_LEN 8 - -#define DRV_ENTRY_PER_SGL 64 /* Size of an entry array in a hash table */ - -#define UNF_DIF_AREA_SIZE (8) - -struct unf_dif_control_info { - u16 app_tag; - u16 flags; - u32 protect_opcode; - u32 fcp_dl; - u32 start_lba; - u8 actual_dif[UNF_DIF_AREA_SIZE]; - u8 expected_dif[UNF_DIF_AREA_SIZE]; - u32 dif_sge_count; - void *dif_sgl; -}; - -struct dif_result_info { - unsigned char actual_idf[UNF_DIF_AREA_SIZE]; - unsigned char expect_dif[UNF_DIF_AREA_SIZE]; -}; - -struct drv_sge { - char *buf; - void *page_ctrl; - u32 Length; - u32 offset; -}; - -struct drv_scsi_cmd_result { - u32 Status; - u16 sense_data_length; /* sense data length */ - u8 sense_data[SCSI_SENSE_DATA_LEN]; /* fail sense info */ -}; - -enum drv_io_direction { - DRV_IO_BIDIRECTIONAL = 0, - DRV_IO_DIRECTION_WRITE = 1, - DRV_IO_DIRECTION_READ = 2, - DRV_IO_DIRECTION_NONE = 3, -}; - -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; - u32 flag; - u64 serial_num; - struct drv_sge sge[DRV_ENTRY_PER_SGL]; - struct list_head node; - u32 cpu_id; -}; - -struct dif_info { -/* Indicates the result returned when the data protection - *information is inconsistent,add by pangea - */ - struct dif_result_info 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 - */ - u32 protect_opcode; - unsigned short apptag; - u64 start_lba; /* IO start LBA */ - struct drv_sgl *protection_sgl; -}; - -struct drv_device_address { - u16 initiator_id; /* ini id */ - u16 bus_id; /* device bus id */ - u16 target_id; /* device target id,for PCIe SSD,device id */ - u16 function_id; /* function id */ -}; - -struct drv_ini_cmd { - struct drv_scsi_cmd_result result; - void *upper; /* product private pointer */ - void *lower; /* driver private pointer */ - u8 cdb[DRV_SCSI_CDB_LEN]; /* CDB edit by product */ - u8 lun[DRV_SCSI_LUN_LEN]; - u16 cmd_len; - u16 tag; /* SCSI cmd add by driver */ - enum drv_io_direction io_direciton; - u32 data_length; - u32 underflow; - u32 overflow; - u32 resid; - u64 port_id; - u64 cmd_sn; - struct drv_device_address addr; - struct drv_sgl *sgl; - void *device; - void (*done)(struct drv_ini_cmd *cmd); /* callback pointer */ - struct dif_info dif_info; -}; - -typedef void (*uplevel_cmd_done)(struct drv_ini_cmd *scsi_cmnd); - -#ifndef SUCCESS -#define SUCCESS 0x2002 -#endif -#ifndef FAILED -#define FAILED 0x2003 -#endif - -#ifndef DRIVER_OK -#define DRIVER_OK 0x00 /* Driver status */ -#endif - -#ifndef PCI_FUNC -#define PCI_FUNC(devfn) ((devfn) & 0x07) -#endif - -#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_ini_error_code { - u32 drv_errcode; /* driver error code */ - u32 ap_errcode; /* up level error code */ -}; - -typedef u32 (*ini_get_sgl_entry_buf)(void *upper_cmnd, void *driver_sgl, - void **upper_sgl, u32 *req_index, - u32 *index, char **buf, - u32 *buf_len); - -#define UNF_SCSI_SENSE_BUFFERSIZE 96 -struct unf_scsi_cmnd { - u32 scsi_host_id; - u32 scsi_id; /* cmd->dev->id */ - u64 raw_lun_id; - u64 port_id; - u32 under_flow; /* Underflow */ - u32 transfer_len; /* Transfer Length */ - u32 resid; /* Resid */ - u32 sense_buflen; - int result; - u32 entry_count; /* IO Buffer counter */ - u32 abort; - u32 err_code_table_cout; /* error code size */ - u64 cmnd_sn; - ulong time_out; /* EPL driver add timer */ - u16 cmnd_len; /* Cdb length */ - u8 data_direction; /* data direction */ - u8 *pcmnd; /* SCSI CDB */ - u8 *sense_buf; - void *drv_private; /* driver host pionter */ - void *driver_scribble; /* Xchg pionter */ - void *upper_cmnd; /* UpperCmnd pointer by driver */ - u8 *lun_id; /* new lunid */ - u32 world_id; - struct unf_dif_control_info dif_control; /* DIF control */ - struct unf_ini_error_code *err_code_table; /* error code table */ - void *sgl; /* Sgl pointer */ - ini_get_sgl_entry_buf unf_ini_get_sgl_entry; - void (*done)(struct unf_scsi_cmnd *cmd); - uplevel_cmd_done uplevel_done; - struct dif_info dif_info; - u32 qos_level; - void *pinitiator; -}; - -#ifndef FC_PORTSPEED_32GBIT -#define FC_PORTSPEED_32GBIT 0x40 -#endif - -#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 - -struct unf_fc_head { - u32 rctl_did; /* Routing control and Destination address of the seq */ - u32 csctl_sid; /* Class control and Source address of the sequence */ - u32 type_fctl; /* Data type and Initial frame control value of the seq - */ - u32 seqid_dfctl_seqcnt; /* Seq ID, Data Field and Initial seq count */ - u32 oxid_rxid; /* Originator & Responder exchange IDs for the sequence - */ - u32 parameter; /* Relative offset of the first frame of the sequence */ -}; - -#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) -#define UNF_FCP_CONF_REQ (1 << 4) - -/* T10: FCP2r.07 9.4.1 Overview and format of FCP_RSP IU */ -struct unf_fcprsp_iu { - u32 reserved[2]; - u8 reserved2[2]; - u8 control; - u8 fcp_status; - u32 fcp_residual; - u32 fcp_sense_len; /* Length of sense info field */ - u32 fcp_response_len; /* Length of response info field in bytes 0,4 or 8 - */ - u8 fcp_resp_info[UNF_MAX_RSP_INFO_LEN]; /* Buffer for response info */ - u8 fcp_sense_info[SCSI_SENSE_DATA_LEN]; /* Buffer for sense info */ -} __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(fcp_tm_code) ((fcp_tm_code) << 8) -#define UNF_GET_TASK_MGMT_FLAGS(control) (((control) & UNF_TASK_MGMT_MASK) >> 8) - -enum unf_task_mgmt_cmd { - 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 { - u8 lun[UNF_FCP_LUNID_LEN_8]; /* Logical unit number */ - u32 control; - u8 cdb[UNF_FCP_CDB_LEN_16]; /* Payload data containing cdb info */ - u32 data_length; /* Number of bytes expected to be transferred */ -} __attribute__((packed)); - -struct unf_fcp_cmd_hdr { - struct unf_fc_head frame_hdr; /* FCHS structure */ - struct unf_fcp_cmnd fcp_cmnd; /* Fcp Cmnd struct */ -}; - -/* FC-LS-2 Common Service Parameter applicability */ -struct unf_fabric_coparm { -#if defined(UNF_CPU_ENDIAN) - u32 bb_credit : 16; /* 0 [0-15] */ - u32 lowest_version : 8; /* 0 [16-23] */ - u32 highest_version : 8; /* 0 [24-31] */ -#else - u32 highest_version : 8; /* 0 [24-31] */ - u32 lowest_version : 8; /* 0 [16-23] */ - u32 bb_credit : 16; /* 0 [0-15] */ -#endif - -#if defined(UNF_CPU_ENDIAN) - u32 bb_receive_data_field_size : 12; /* 1 [0-11] */ - u32 bbscn : 4; /* 1 [12-15] */ - u32 payload_length : 1; /* 1 [16] */ - u32 seq_cnt : 1; /* 1 [17] */ - u32 dynamic_half_duplex : 1; /* 1 [18] */ - u32 r_t_tov : 1; /* 1 [19] */ - u32 reserved_co2 : 6; /* 1 [20-25] */ - u32 e_d_tov_resolution : 1; /* 1 [26] */ - u32 alternate_bb_credit_mgmt : 1; /* 1 [27] */ - u32 nport : 1; /* 1 [28] */ - u32 mnid_assignment : 1; /* 1 [29] */ - u32 random_relative_offset : 1; /* 1 [30] */ - u32 clean_address : 1; /* 1 [31] */ -#else - u32 reserved_co2 : 2; /* 1 [24-25] */ - u32 e_d_tov_resolution : 1; /* 1 [26] */ - u32 alternate_bb_credit_mgmt : 1; /* 1 [27] */ - u32 nport : 1; /* 1 [28] */ - u32 mnid_assignment : 1; /* 1 [29] */ - u32 random_relative_offset : 1; /* 1 [30] */ - u32 clean_address : 1; /* 1 [31] */ - - u32 payload_length : 1; /* 1 [16] */ - u32 seq_cnt : 1; /* 1 [17] */ - u32 dynamic_half_duplex : 1; /* 1 [18] */ - u32 r_t_tov : 1; /* 1 [19] */ - u32 reserved_co5 : 4; /* 1 [20-23] */ - - u32 bb_receive_data_field_size : 12; /* 1 [0-11] */ - u32 bbscn : 4; /* 1 [12-15] */ -#endif - u32 r_a_tov; /* 2 [0-31] */ - u32 e_d_tov; /* 3 [0-31] */ -}; - -/* FC-LS-2 Common Service Parameter applicability */ -/*Common Service Parameters - PLOGI and PLOGI LS_ACC */ -struct lgn_port_coparm { -#if defined(UNF_CPU_ENDIAN) - u32 bb_credit : 16; /* 0 [0-15] */ - u32 lowest_version : 8; /* 0 [16-23] */ - u32 highest_version : 8; /* 0 [24-31] */ -#else - u32 highest_version : 8; /* 0 [24-31] */ - u32 lowest_version : 8; /* 0 [16-23] */ - u32 bb_credit : 16; /* 0 [0-15] */ -#endif - -#if defined(UNF_CPU_ENDIAN) - u32 bb_receive_data_field_size : 12; /* 1 [0-11] */ - u32 bbscn : 4; /* 1 [12-15] */ - u32 payload_length : 1; /* 1 [16] */ - u32 seq_cnt : 1; /* 1 [17] */ - u32 dynamic_half_duplex : 1; /* 1 [18] */ - u32 reserved_co2 : 7; /* 1 [19-25] */ - u32 e_d_tov_resolution : 1; /* 1 [26] */ - u32 alternate_bb_credit_mgmt : 1; /* 1 [27] */ - u32 nport : 1; /* 1 [28] */ - u32 vendor_version_level : 1; /* 1 [29] */ - u32 random_relative_offset : 1; /* 1 [30] */ - u32 continuously_increasing : 1; /* 1 [31] */ -#else - u32 reserved_co2 : 2; /* 1 [24-25] */ - u32 e_d_tov_resolution : 1; /* 1 [26] */ - u32 alternate_bb_credit_mgmt : 1; /* 1 [27] */ - u32 nport : 1; /* 1 [28] */ - u32 vendor_version_level : 1; /* 1 [29] */ - u32 random_relative_offset : 1; /* 1 [30] */ - u32 continuously_increasing : 1; /* 1 [31] */ - - u32 payload_length : 1; /* 1 [16] */ - u32 seq_cnt : 1; /* 1 [17] */ - u32 dynamic_half_duplex : 1; /* 1 [18] */ - u32 reserved_co5 : 5; /* 1 [19-23] */ - - u32 bb_receive_data_field_size : 12; /* 1 [0-11] */ - u32 reserved_co1 : 4; /* 1 [12-15] */ -#endif - -#if defined(UNF_CPU_ENDIAN) - u32 relative_offset : 16; /* 2 [0-15] */ - u32 nport_total_concurrent_sequences : 16; /* 2 [16-31] */ -#else - u32 nport_total_concurrent_sequences : 16; /* 2 [16-31] */ - u32 relative_offset : 16; /* 2 [0-15] */ -#endif - - u32 e_d_tov; -}; - -/* FC-LS-2 Class Service Parameters Applicability */ -struct unf_lgn_port_clparm { -#if defined(UNF_CPU_ENDIAN) - u32 reserved_cl1 : 6; /* 0 [0-5] */ - u32 ic_data_compression_history_buffer_size : 2; /* 0 [6-7] */ - u32 ic_data_compression_capable : 1; /* 0 [8] */ - - u32 ic_ack_generation_assistance : 1; /* 0 [9] */ - u32 ic_ack_n_capable : 1; /* 0 [10] */ - u32 ic_ack_o_capable : 1; /* 0 [11] */ - u32 ic_initial_responder_processes_accociator : 2; /* 0 [12-13] */ - u32 ic_x_id_reassignment : 2; /* 0 [14-15] */ - - u32 reserved_cl2 : 7; /* 0 [16-22] */ - u32 priority : 1; /* 0 [23] */ - u32 buffered_class : 1; /* 0 [24] */ - u32 camp_on : 1; /* 0 [25] */ - u32 dedicated_simplex : 1; /* 0 [26] */ - u32 sequential_delivery : 1; /* 0 [27] */ - u32 stacked_connect_request : 2; /* 0 [28-29] */ - u32 intermix_mode : 1; /* 0 [30] */ - u32 valid : 1; /* 0 [31] */ -#else - u32 buffered_class : 1; /* 0 [24] */ - u32 camp_on : 1; /* 0 [25] */ - u32 dedicated_simplex : 1; /* 0 [26] */ - u32 sequential_delivery : 1; /* 0 [27] */ - u32 stacked_connect_request : 2; /* 0 [28-29] */ - u32 intermix_mode : 1; /* 0 [30] */ - u32 valid : 1; /* 0 [31] */ - u32 reserved_cl2 : 7; /* 0 [16-22] */ - u32 priority : 1; /* 0 [23] */ - u32 ic_data_compression_capable : 1; /* 0 [8] */ - u32 ic_ack_generation_assistance : 1; /* 0 [9] */ - u32 ic_ack_n_capable : 1; /* 0 [10] */ - u32 ic_ack_o_capable : 1; /* 0 [11] */ - u32 ic_initial_responder_processes_accociator : 2; /* 0 [12-13] */ - u32 ic_x_id_reassignment : 2; /* 0 [14-15] */ - - u32 reserved_cl1 : 6; /* 0 [0-5] */ - u32 ic_data_compression_history_buffer_size : 2; /* 0 [6-7] */ -#endif - -#if defined(UNF_CPU_ENDIAN) - u32 received_data_field_size : 16; /* 1 [0-15] */ - - u32 reserved_cl3 : 5; /* 1 [16-20] */ - u32 rc_data_compression_history_buffer_size : 2; /* 1 [21-22] */ - u32 rc_data_compression_capable : 1; /* 1 [23] */ - - u32 rc_data_categories_per_sequence : 2; /* 1 [24-25] */ - u32 reserved_cl4 : 1; /* 1 [26] */ - u32 rc_error_policy_supported : 2; /* 1 [27-28] */ - u32 rc_x_id_interlock : 1; /* 1 [29] */ - u32 rc_ack_n_capable : 1; /* 1 [30] */ - u32 rc_ack_o_capable : 1; /* 1 [31] */ -#else - u32 rc_data_categories_per_sequence : 2; /* 1 [24-25] */ - u32 reserved_cl4 : 1; /* 1 [26] */ - u32 rc_error_policy_supported : 2; /* 1 [27-28] */ - u32 rc_x_id_interlock : 1; /* 1 [29] */ - u32 rc_ack_n_capable : 1; /* 1 [30] */ - u32 rc_ack_o_capable : 1; /* 1 [31] */ - - u32 reserved_cl3 : 5; /* 1 [16-20] */ - u32 rc_data_compression_history_buffer_size : 2; /* 1 [21-22] */ - u32 rc_data_compression_capable : 1; /* 1 [23] */ - - u32 received_data_field_size : 16; /* 1 [0-15] */ -#endif - -#if defined(UNF_CPU_ENDIAN) - u32 nport_end_to_end_credit : 15; /* 2 [0-14] */ - u32 reserved_cl5 : 1; /* 2 [15] */ - - u32 concurrent_sequences : 16; /* 2 [16-31] */ -#else - u32 concurrent_sequences : 16; /* 2 [16-31] */ - - u32 nport_end_to_end_credit : 15; /* 2 [0-14] */ - u32 reserved_cl5 : 1; /* 2 [15] */ -#endif - -#if defined(UNF_CPU_ENDIAN) - u32 reserved_cl6 : 16; /* 3 [0-15] */ - u32 open_sequence_per_exchange : 16; /* 3 [16-31] */ -#else - u32 open_sequence_per_exchange : 16; /* 3 [16-31] */ - u32 reserved_cl6 : 16; /* 3 [0-15] */ -#endif -}; - -struct unf_fabric_parm { - struct unf_fabric_coparm co_parms; - u32 high_port_name; - u32 low_port_name; - u32 high_node_name; - u32 low_node_name; - struct unf_lgn_port_clparm cl_parms[3]; - u32 reserved_1[4]; - u32 vendor_version_level[4]; -}; - -struct unf_lgn_parm { - struct lgn_port_coparm co_parms; - u32 high_port_name; - u32 low_port_name; - u32 high_node_name; - u32 low_node_name; - struct unf_lgn_port_clparm cl_parms[3]; - u32 reserved_1[4]; - u32 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_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 INVALID_WORLD_ID 0xfffffffc - -struct unf_host_param { - int can_queue; - u16 sg_table_size; - short cmnd_per_lun; - u32 max_id; - u32 max_lun; - u32 max_channel; - u16 max_cmnd_len; - u16 max_sectors; - u64 dma_boundary; - u32 port_id; - void *lport; - struct device *pdev; -}; - -int unf_alloc_scsi_host(struct Scsi_Host **unf_scsi_host, struct unf_host_param *host_param); -void unf_free_scsi_host(struct Scsi_Host *unf_scsi_host); -u32 unf_register_ini_transport(void); -void unf_unregister_ini_transport(void); -void unf_save_sense_data(void *scsi_cmd, const char *sense, int sens_len); - -#endif diff --git a/drivers/scsi/spfc/common/unf_service.c b/drivers/scsi/spfc/common/unf_service.c deleted file mode 100644 index 9c86c99374c8..000000000000 --- a/drivers/scsi/spfc/common/unf_service.c +++ /dev/null @@ -1,1430 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#include "unf_service.h" -#include "unf_log.h" -#include "unf_rport.h" -#include "unf_ls.h" -#include "unf_gs.h" - -struct unf_els_handle_table els_handle_table[] = { - {ELS_PLOGI, unf_plogi_handler}, {ELS_FLOGI, unf_flogi_handler}, - {ELS_LOGO, unf_logo_handler}, {ELS_ECHO, unf_echo_handler}, - {ELS_RRQ, unf_rrq_handler}, {ELS_REC, unf_rec_handler}, - {ELS_PRLI, unf_prli_handler}, {ELS_PRLO, unf_prlo_handler}, - {ELS_PDISC, unf_pdisc_handler}, {ELS_ADISC, unf_adisc_handler}, - {ELS_RSCN, unf_rscn_handler} }; - -u32 max_frame_size = UNF_DEFAULT_FRAME_SIZE; - -#define UNF_NEED_BIG_RESPONSE_BUFF(cmnd_code) \ - (((cmnd_code) == ELS_ECHO) || ((cmnd_code) == NS_GID_PT) || \ - ((cmnd_code) == NS_GID_FT)) - -#define NEED_REFRESH_NPORTID(pkg) \ - ((((pkg)->cmnd == ELS_PLOGI) || ((pkg)->cmnd == ELS_PDISC) || \ - ((pkg)->cmnd == ELS_ADISC))) - -void unf_select_sq(struct unf_xchg *xchg, struct unf_frame_pkg *pkg) -{ - u32 ssq_index = 0; - struct unf_rport *unf_rport = NULL; - - if (likely(xchg)) { - unf_rport = xchg->rport; - - if (unf_rport) { - ssq_index = (xchg->hotpooltag % UNF_SQ_NUM_PER_SESSION) + - unf_rport->sqn_base; - } - } - - pkg->private_data[PKG_PRIVATE_XCHG_SSQ_INDEX] = ssq_index; -} - -u32 unf_ls_gs_cmnd_send(struct unf_lport *lport, struct unf_frame_pkg *pkg, - struct unf_xchg *xchg) -{ - u32 ret = UNF_RETURN_ERROR; - ulong time_out = 0; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(pkg, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(xchg, UNF_RETURN_ERROR); - - if (unlikely(!lport->low_level_func.service_op.unf_ls_gs_send)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) LS/GS send function is NULL", - lport->port_id); - - return ret; - } - - if (pkg->type == UNF_PKG_GS_REQ) - time_out = UNF_GET_GS_SFS_XCHG_TIMER(lport); - else - time_out = UNF_GET_ELS_SFS_XCHG_TIMER(lport); - - if (xchg->cmnd_code == ELS_RRQ) { - time_out = ((ulong)UNF_GET_ELS_SFS_XCHG_TIMER(lport) > UNF_RRQ_MIN_TIMEOUT_INTERVAL) - ? (ulong)UNF_GET_ELS_SFS_XCHG_TIMER(lport) - : UNF_RRQ_MIN_TIMEOUT_INTERVAL; - } else if (xchg->cmnd_code == ELS_LOGO) { - time_out = UNF_LOGO_TIMEOUT_INTERVAL; - } - - pkg->private_data[PKG_PRIVATE_XCHG_TIMEER] = (u32)time_out; - lport->xchg_mgr_temp.unf_xchg_add_timer((void *)xchg, time_out, UNF_TIMER_TYPE_SFS); - - unf_select_sq(xchg, pkg); - - ret = lport->low_level_func.service_op.unf_ls_gs_send(lport->fc_port, pkg); - if (unlikely(ret != RETURN_OK)) - lport->xchg_mgr_temp.unf_xchg_cancel_timer((void *)xchg); - - return ret; -} - -static u32 unf_bls_cmnd_send(struct unf_lport *lport, struct unf_frame_pkg *pkg, - struct unf_xchg *xchg) -{ - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(pkg, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(xchg, UNF_RETURN_ERROR); - - pkg->private_data[PKG_PRIVATE_XCHG_TIMEER] = (u32)UNF_GET_BLS_SFS_XCHG_TIMER(lport); - pkg->private_data[PKG_PRIVATE_XCHG_ALLOC_TIME] = - xchg->private_data[PKG_PRIVATE_XCHG_ALLOC_TIME]; - - unf_select_sq(xchg, pkg); - - return lport->low_level_func.service_op.unf_bls_send(lport->fc_port, pkg); -} - -void unf_fill_package(struct unf_frame_pkg *pkg, struct unf_xchg *xchg, - struct unf_rport *rport) -{ - /* v_pstRport maybe NULL */ - FC_CHECK_RETURN_VOID(pkg); - FC_CHECK_RETURN_VOID(xchg); - - pkg->cmnd = xchg->cmnd_code; - pkg->fcp_cmnd = &xchg->fcp_cmnd; - pkg->frame_head.csctl_sid = xchg->sid; - pkg->frame_head.rctl_did = xchg->did; - pkg->frame_head.oxid_rxid = ((u32)xchg->oxid << UNF_SHIFT_16 | xchg->rxid); - pkg->xchg_contex = xchg; - - FC_CHECK_RETURN_VOID(xchg->lport); - pkg->private_data[PKG_PRIVATE_XCHG_VP_INDEX] = xchg->lport->vp_index; - - if (!rport) { - pkg->private_data[PKG_PRIVATE_XCHG_RPORT_INDEX] = UNF_RPORT_INVALID_INDEX; - pkg->private_data[PKG_PRIVATE_RPORT_RX_SIZE] = INVALID_VALUE32; - } else { - if (likely(rport->nport_id != UNF_FC_FID_FLOGI)) - pkg->private_data[PKG_PRIVATE_XCHG_RPORT_INDEX] = rport->rport_index; - else - pkg->private_data[PKG_PRIVATE_XCHG_RPORT_INDEX] = SPFC_DEFAULT_RPORT_INDEX; - - pkg->private_data[PKG_PRIVATE_RPORT_RX_SIZE] = rport->max_frame_size; - } - - pkg->private_data[PKG_PRIVATE_XCHG_HOT_POOL_INDEX] = xchg->hotpooltag; - pkg->private_data[PKG_PRIVATE_XCHG_ALLOC_TIME] = - xchg->private_data[PKG_PRIVATE_XCHG_ALLOC_TIME]; - pkg->private_data[PKG_PRIVATE_LOWLEVEL_XCHG_ADD] = - xchg->private_data[PKG_PRIVATE_LOWLEVEL_XCHG_ADD]; - pkg->unf_cmnd_pload_bl.buffer_ptr = - (u8 *)xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr; - pkg->unf_cmnd_pload_bl.buf_dma_addr = - xchg->fcp_sfs_union.sfs_entry.sfs_buff_phy_addr; - - /* Low level need to know payload length if send ECHO response */ - pkg->unf_cmnd_pload_bl.length = xchg->fcp_sfs_union.sfs_entry.cur_offset; -} - -struct unf_xchg *unf_get_sfs_free_xchg_and_init(struct unf_lport *lport, u32 did, - struct unf_rport *rport, - union unf_sfs_u **fc_entry) -{ - struct unf_xchg *xchg = NULL; - union unf_sfs_u *sfs_fc_entry = NULL; - - xchg = unf_cm_get_free_xchg(lport, UNF_XCHG_TYPE_SFS); - if (!xchg) - return NULL; - - xchg->did = did; - xchg->sid = lport->nport_id; - xchg->oid = xchg->sid; - xchg->lport = lport; - xchg->rport = rport; - xchg->disc_rport = NULL; - xchg->callback = NULL; - xchg->ob_callback = NULL; - - sfs_fc_entry = xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr; - if (!sfs_fc_entry) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) entry can't be NULL with tag(0x%x)", - lport->port_id, xchg->hotpooltag); - - unf_cm_free_xchg(lport, xchg); - return NULL; - } - - *fc_entry = sfs_fc_entry; - - return xchg; -} - -void *unf_get_one_big_sfs_buf(struct unf_xchg *xchg) -{ - struct unf_big_sfs *big_sfs = NULL; - struct list_head *list_head = NULL; - struct unf_xchg_mgr *xchg_mgr = NULL; - ulong flag = 0; - spinlock_t *big_sfs_pool_lock = NULL; - - FC_CHECK_RETURN_VALUE(xchg, NULL); - xchg_mgr = xchg->xchg_mgr; - FC_CHECK_RETURN_VALUE(xchg_mgr, NULL); - big_sfs_pool_lock = &xchg_mgr->big_sfs_pool.big_sfs_pool_lock; - - spin_lock_irqsave(big_sfs_pool_lock, flag); - if (!list_empty(&xchg_mgr->big_sfs_pool.list_freepool)) { - /* from free to busy */ - list_head = UNF_OS_LIST_NEXT(&xchg_mgr->big_sfs_pool.list_freepool); - list_del(list_head); - xchg_mgr->big_sfs_pool.free_count--; - list_add_tail(list_head, &xchg_mgr->big_sfs_pool.list_busypool); - big_sfs = list_entry(list_head, struct unf_big_sfs, entry_bigsfs); - } else { - spin_unlock_irqrestore(big_sfs_pool_lock, flag); - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Allocate big sfs buf failed, count(0x%x) exchange(0x%p) command(0x%x)", - xchg_mgr->big_sfs_pool.free_count, xchg, xchg->cmnd_code); - - return NULL; - } - spin_unlock_irqrestore(big_sfs_pool_lock, flag); - - xchg->big_sfs_buf = big_sfs; - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "[info]Allocate one big sfs buffer(0x%p), remaining count(0x%x) exchange(0x%p) command(0x%x)", - big_sfs->addr, xchg_mgr->big_sfs_pool.free_count, xchg, - xchg->cmnd_code); - - return big_sfs->addr; -} - -static void unf_fill_rjt_pld(struct unf_els_rjt *els_rjt, u32 reason_code, - u32 reason_explanation) -{ - FC_CHECK_RETURN_VOID(els_rjt); - - els_rjt->cmnd = UNF_ELS_CMND_RJT; - els_rjt->reason_code = (reason_code | reason_explanation); -} - -u32 unf_send_abts(struct unf_lport *lport, struct unf_xchg *xchg) -{ - struct unf_rport *unf_rport = NULL; - u32 ret = UNF_RETURN_ERROR; - struct unf_frame_pkg pkg; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(xchg, UNF_RETURN_ERROR); - unf_rport = xchg->rport; - FC_CHECK_RETURN_VALUE(unf_rport, UNF_RETURN_ERROR); - - /* set pkg info */ - memset(&pkg, 0, sizeof(struct unf_frame_pkg)); - pkg.type = UNF_PKG_BLS_REQ; - pkg.frame_head.csctl_sid = xchg->sid; - pkg.frame_head.rctl_did = xchg->did; - pkg.frame_head.oxid_rxid = ((u32)xchg->oxid << UNF_SHIFT_16 | xchg->rxid); - pkg.xchg_contex = xchg; - pkg.unf_cmnd_pload_bl.buffer_ptr = (u8 *)xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr; - - pkg.unf_cmnd_pload_bl.buf_dma_addr = xchg->fcp_sfs_union.sfs_entry.sfs_buff_phy_addr; - pkg.private_data[PKG_PRIVATE_XCHG_HOT_POOL_INDEX] = xchg->hotpooltag; - - UNF_SET_XCHG_ALLOC_TIME(&pkg, xchg); - UNF_SET_ABORT_INFO_IOTYPE(&pkg, xchg); - - pkg.private_data[PKG_PRIVATE_XCHG_RPORT_INDEX] = - xchg->private_data[PKG_PRIVATE_XCHG_RPORT_INDEX]; - - /* Send ABTS frame to target */ - ret = unf_bls_cmnd_send(lport, &pkg, xchg); - - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_MAJOR, - "[info]Port(0x%x_0x%x) send ABTS %s. Abort exch(0x%p) Cmdsn:0x%lx, tag(0x%x) iotype(0x%x)", - lport->port_id, lport->nport_id, - (ret == UNF_RETURN_ERROR) ? "failed" : "succeed", xchg, - (ulong)xchg->cmnd_sn, xchg->hotpooltag, xchg->data_direction); - - return ret; -} - -u32 unf_send_els_rjt_by_rport(struct unf_lport *lport, struct unf_xchg *xchg, - struct unf_rport *rport, struct unf_rjt_info *rjt_info) -{ - struct unf_els_rjt *els_rjt = NULL; - union unf_sfs_u *fc_entry = NULL; - struct unf_frame_pkg pkg = {0}; - u32 ret = UNF_RETURN_ERROR; - u16 ox_id = 0; - u16 rx_id = 0; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(xchg, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(rport, UNF_RETURN_ERROR); - - xchg->cmnd_code = UNF_SET_ELS_RJT_TYPE(rjt_info->els_cmnd_code); - xchg->did = rport->nport_id; - xchg->sid = lport->nport_id; - xchg->oid = xchg->sid; - xchg->lport = lport; - xchg->rport = rport; - xchg->disc_rport = NULL; - - xchg->callback = NULL; - xchg->ob_callback = NULL; - - unf_fill_package(&pkg, xchg, rport); - pkg.class_mode = UNF_FC_PROTOCOL_CLASS_3; - pkg.type = UNF_PKG_ELS_REPLY; - - fc_entry = xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr; - if (!fc_entry) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) entry can't be NULL with tag(0x%x)", - lport->port_id, xchg->hotpooltag); - - unf_cm_free_xchg(lport, xchg); - return UNF_RETURN_ERROR; - } - - els_rjt = &fc_entry->els_rjt; - memset(els_rjt, 0, sizeof(struct unf_els_rjt)); - unf_fill_rjt_pld(els_rjt, rjt_info->reason_code, rjt_info->reason_explanation); - ox_id = xchg->oxid; - rx_id = xchg->rxid; - - ret = unf_ls_gs_cmnd_send(lport, &pkg, xchg); - if (ret != RETURN_OK) - unf_cm_free_xchg((void *)lport, (void *)xchg); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: Send LS_RJT for 0x%x %s. Port(0x%x)--->RPort(0x%x) with OX_ID(0x%x) RX_ID(0x%x)", - rjt_info->els_cmnd_code, - (ret != RETURN_OK) ? "failed" : "succeed", lport->port_id, - rport->nport_id, ox_id, rx_id); - - return ret; -} - -u32 unf_send_els_rjt_by_did(struct unf_lport *lport, struct unf_xchg *xchg, - u32 did, struct unf_rjt_info *rjt_info) -{ - struct unf_els_rjt *els_rjt = NULL; - union unf_sfs_u *fc_entry = NULL; - struct unf_frame_pkg pkg = {0}; - u32 ret = UNF_RETURN_ERROR; - u16 ox_id = 0; - u16 rx_id = 0; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(xchg, UNF_RETURN_ERROR); - - xchg->cmnd_code = UNF_SET_ELS_RJT_TYPE(rjt_info->els_cmnd_code); - xchg->did = did; - xchg->sid = lport->nport_id; - xchg->oid = xchg->sid; - xchg->lport = lport; - xchg->rport = NULL; - xchg->disc_rport = NULL; - - xchg->callback = NULL; - xchg->ob_callback = NULL; - - unf_fill_package(&pkg, xchg, NULL); - pkg.class_mode = UNF_FC_PROTOCOL_CLASS_3; - pkg.type = UNF_PKG_ELS_REPLY; - - if (rjt_info->reason_code == UNF_LS_RJT_CLASS_ERROR && - rjt_info->class_mode != UNF_FC_PROTOCOL_CLASS_3) { - pkg.class_mode = rjt_info->class_mode; - } - - fc_entry = xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr; - if (!fc_entry) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) entry can't be NULL with tag(0x%x)", - lport->port_id, xchg->hotpooltag); - - unf_cm_free_xchg(lport, xchg); - return UNF_RETURN_ERROR; - } - - els_rjt = &fc_entry->els_rjt; - memset(els_rjt, 0, sizeof(struct unf_els_rjt)); - unf_fill_rjt_pld(els_rjt, rjt_info->reason_code, rjt_info->reason_explanation); - ox_id = xchg->oxid; - rx_id = xchg->rxid; - - ret = unf_ls_gs_cmnd_send(lport, &pkg, xchg); - if (ret != RETURN_OK) - unf_cm_free_xchg((void *)lport, (void *)xchg); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]LOGIN: Send LS_RJT %s. Port(0x%x)--->RPort(0x%x) with OX_ID(0x%x) RX_ID(0x%x)", - (ret != RETURN_OK) ? "failed" : "succeed", lport->port_id, did, ox_id, rx_id); - - return ret; -} - -static u32 unf_els_cmnd_default_handler(struct unf_lport *lport, struct unf_xchg *xchg, u32 sid, - u32 els_cmnd_code) -{ - struct unf_rport *unf_rport = NULL; - struct unf_rjt_info rjt_info = {0}; - u32 ret = UNF_RETURN_ERROR; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(xchg, UNF_RETURN_ERROR); - - FC_DRV_PRINT(UNF_LOG_ABNORMAL, UNF_KEVENT, - "[info]Receive Unknown ELS command(0x%x). Port(0x%x)<---RPort(0x%x) with OX_ID(0x%x)", - els_cmnd_code, lport->port_id, sid, xchg->oxid); - - memset(&rjt_info, 0, sizeof(struct unf_rjt_info)); - rjt_info.els_cmnd_code = els_cmnd_code; - rjt_info.reason_code = UNF_LS_RJT_NOT_SUPPORTED; - - unf_rport = unf_get_rport_by_nport_id(lport, sid); - if (unf_rport) - ret = unf_send_els_rjt_by_rport(lport, xchg, unf_rport, &rjt_info); - else - ret = unf_send_els_rjt_by_did(lport, xchg, sid, &rjt_info); - - return ret; -} - -static struct unf_xchg *unf_alloc_xchg_for_rcv_cmnd(struct unf_lport *lport, - struct unf_frame_pkg *pkg) -{ - struct unf_xchg *xchg = NULL; - ulong flags = 0; - u32 i = 0; - u32 offset = 0; - u8 *cmnd_pld = NULL; - u32 first_dword = 0; - u32 alloc_time = 0; - - FC_CHECK_RETURN_VALUE(lport, NULL); - FC_CHECK_RETURN_VALUE(pkg, NULL); - - if (!pkg->xchg_contex) { - xchg = unf_cm_get_free_xchg(lport, UNF_XCHG_TYPE_SFS); - if (!xchg) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[warn]Port(0x%x) get new exchange failed", - lport->port_id); - - return NULL; - } - - offset = (xchg->fcp_sfs_union.sfs_entry.cur_offset); - cmnd_pld = (u8 *)xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr->rscn.rscn_pld; - first_dword = xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr - ->sfs_common.frame_head.rctl_did; - - if (cmnd_pld || first_dword != 0 || offset != 0) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) exchange(0x%p) abnormal, maybe data overrun, start(%llu) command(0x%x)", - lport->port_id, xchg, xchg->alloc_jif, pkg->cmnd); - - UNF_PRINT_SFS(UNF_INFO, lport->port_id, - xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr, - sizeof(union unf_sfs_u)); - } - - memset(xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr, 0, sizeof(union unf_sfs_u)); - - pkg->xchg_contex = (void *)xchg; - - spin_lock_irqsave(&xchg->xchg_state_lock, flags); - xchg->fcp_sfs_union.sfs_entry.cur_offset = 0; - alloc_time = xchg->private_data[PKG_PRIVATE_XCHG_ALLOC_TIME]; - for (i = 0; i < PKG_MAX_PRIVATE_DATA_SIZE; i++) - xchg->private_data[i] = pkg->private_data[i]; - - xchg->private_data[PKG_PRIVATE_XCHG_ALLOC_TIME] = alloc_time; - spin_unlock_irqrestore(&xchg->xchg_state_lock, flags); - } else { - xchg = (struct unf_xchg *)pkg->xchg_contex; - } - - if (!xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr) { - unf_cm_free_xchg((void *)lport, (void *)xchg); - - return NULL; - } - - return xchg; -} - -static u8 *unf_calc_big_cmnd_pld_buffer(struct unf_xchg *xchg, u32 cmnd_code) -{ - u8 *cmnd_pld = NULL; - void *buf = NULL; - u8 *dest = NULL; - - FC_CHECK_RETURN_VALUE(xchg, NULL); - - if (cmnd_code == ELS_RSCN) - cmnd_pld = (u8 *)xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr->rscn.rscn_pld; - else - cmnd_pld = (u8 *)xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr->echo.echo_pld; - - if (!cmnd_pld) { - buf = unf_get_one_big_sfs_buf(xchg); - if (!buf) - return NULL; - - if (cmnd_code == ELS_RSCN) { - memset(buf, 0, sizeof(struct unf_rscn_pld)); - xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr->rscn.rscn_pld = buf; - } else { - memset(buf, 0, sizeof(struct unf_echo_payload)); - xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr->echo.echo_pld = buf; - } - - dest = (u8 *)buf; - } else { - dest = (u8 *)(cmnd_pld + xchg->fcp_sfs_union.sfs_entry.cur_offset); - } - - return dest; -} - -static u8 *unf_calc_other_pld_buffer(struct unf_xchg *xchg) -{ - u8 *dest = NULL; - u32 offset = 0; - - FC_CHECK_RETURN_VALUE(xchg, NULL); - - offset = (sizeof(struct unf_fc_head)) + (xchg->fcp_sfs_union.sfs_entry.cur_offset); - dest = (u8 *)((u8 *)(xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr) + offset); - - return dest; -} - -struct unf_xchg *unf_mv_data_2_xchg(struct unf_lport *lport, struct unf_frame_pkg *pkg) -{ - struct unf_xchg *xchg = NULL; - u8 *dest = NULL; - u32 length = 0; - ulong flags = 0; - - FC_CHECK_RETURN_VALUE(lport, NULL); - FC_CHECK_RETURN_VALUE(pkg, NULL); - - xchg = unf_alloc_xchg_for_rcv_cmnd(lport, pkg); - if (!xchg) - return NULL; - - spin_lock_irqsave(&xchg->xchg_state_lock, flags); - - memcpy(&xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr->sfs_common.frame_head, - &pkg->frame_head, sizeof(pkg->frame_head)); - - if (pkg->cmnd == ELS_RSCN || pkg->cmnd == ELS_ECHO) - dest = unf_calc_big_cmnd_pld_buffer(xchg, pkg->cmnd); - else - dest = unf_calc_other_pld_buffer(xchg); - - if (!dest) { - spin_unlock_irqrestore(&xchg->xchg_state_lock, flags); - unf_cm_free_xchg((void *)lport, (void *)xchg); - - return NULL; - } - - if (((xchg->fcp_sfs_union.sfs_entry.cur_offset + - pkg->unf_cmnd_pload_bl.length) > (u32)sizeof(union unf_sfs_u)) && - pkg->cmnd != ELS_RSCN && pkg->cmnd != ELS_ECHO) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) excange(0x%p) command(0x%x,0x%x) copy payload overrun(0x%x:0x%x:0x%x)", - lport->port_id, xchg, pkg->cmnd, xchg->hotpooltag, - xchg->fcp_sfs_union.sfs_entry.cur_offset, - pkg->unf_cmnd_pload_bl.length, (u32)sizeof(union unf_sfs_u)); - - spin_unlock_irqrestore(&xchg->xchg_state_lock, flags); - unf_cm_free_xchg((void *)lport, (void *)xchg); - - return NULL; - } - - length = pkg->unf_cmnd_pload_bl.length; - if (length > 0) - memcpy(dest, pkg->unf_cmnd_pload_bl.buffer_ptr, length); - - xchg->fcp_sfs_union.sfs_entry.cur_offset += length; - spin_unlock_irqrestore(&xchg->xchg_state_lock, flags); - - return xchg; -} - -static u32 unf_check_els_cmnd_valid(struct unf_lport *lport, struct unf_frame_pkg *pkg, - struct unf_xchg *xchg) -{ - struct unf_rjt_info rjt_info = {0}; - struct unf_lport *vport = NULL; - u32 sid = 0; - u32 did = 0; - - sid = (pkg->frame_head.csctl_sid) & UNF_NPORTID_MASK; - did = (pkg->frame_head.rctl_did) & UNF_NPORTID_MASK; - - memset(&rjt_info, 0, sizeof(struct unf_rjt_info)); - - if (pkg->class_mode != UNF_FC_PROTOCOL_CLASS_3) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) unsupport class 0x%x cmd 0x%x and send RJT", - lport->port_id, pkg->class_mode, pkg->cmnd); - - rjt_info.reason_code = UNF_LS_RJT_CLASS_ERROR; - rjt_info.els_cmnd_code = pkg->cmnd; - rjt_info.class_mode = pkg->class_mode; - (void)unf_send_els_rjt_by_did(lport, xchg, sid, &rjt_info); - - return UNF_RETURN_ERROR; - } - - rjt_info.reason_code = UNF_LS_RJT_NOT_SUPPORTED; - - if (pkg->cmnd == ELS_FLOGI && lport->act_topo == UNF_ACT_TOP_PRIVATE_LOOP) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]LOGIN: Port(0x%x) receive FLOGI in top (0x%x) and send LS_RJT", - lport->port_id, lport->act_topo); - - rjt_info.els_cmnd_code = ELS_FLOGI; - (void)unf_send_els_rjt_by_did(lport, xchg, sid, &rjt_info); - - return UNF_RETURN_ERROR; - } - - if (pkg->cmnd == ELS_PLOGI && did >= UNF_FC_FID_DOM_MGR) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x)receive PLOGI with wellknown address(0x%x) and Send LS_RJT", - lport->port_id, did); - - rjt_info.els_cmnd_code = ELS_PLOGI; - (void)unf_send_els_rjt_by_did(lport, xchg, sid, &rjt_info); - - return UNF_RETURN_ERROR; - } - - if ((lport->nport_id == 0 || lport->nport_id == INVALID_VALUE32) && - (NEED_REFRESH_NPORTID(pkg))) { - lport->nport_id = did; - } else if ((lport->nport_id != did) && (pkg->cmnd != ELS_FLOGI)) { - vport = unf_cm_lookup_vport_by_did(lport, did); - if (!vport) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) receive ELS cmd(0x%x) with abnormal D_ID(0x%x)", - lport->nport_id, pkg->cmnd, did); - - unf_cm_free_xchg(lport, xchg); - return UNF_RETURN_ERROR; - } - } - - return RETURN_OK; -} - -static u32 unf_rcv_els_cmnd_req(struct unf_lport *lport, struct unf_frame_pkg *pkg) -{ - struct unf_xchg *xchg = NULL; - u32 ret = UNF_RETURN_ERROR; - u32 i = 0; - u32 sid = 0; - u32 did = 0; - struct unf_lport *vport = NULL; - u32 (*els_cmnd_handler)(struct unf_lport *, u32, struct unf_xchg *) = NULL; - - sid = (pkg->frame_head.csctl_sid) & UNF_NPORTID_MASK; - did = (pkg->frame_head.rctl_did) & UNF_NPORTID_MASK; - - xchg = unf_mv_data_2_xchg(lport, pkg); - if (!xchg) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) receive ElsCmnd(0x%x), exchange is NULL", - lport->port_id, pkg->cmnd); - return UNF_RETURN_ERROR; - } - - if (!pkg->last_pkg_flag) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "[info]Exchange(%u) waiting for last WQE", - xchg->hotpooltag); - return RETURN_OK; - } - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "[info]Exchange(%u) get last WQE", xchg->hotpooltag); - - xchg->oxid = UNF_GET_OXID(pkg); - xchg->abort_oxid = xchg->oxid; - xchg->rxid = UNF_GET_RXID(pkg); - xchg->cmnd_code = pkg->cmnd; - - ret = unf_check_els_cmnd_valid(lport, pkg, xchg); - if (ret != RETURN_OK) - return UNF_RETURN_ERROR; - - if (lport->nport_id != did && pkg->cmnd != ELS_FLOGI) { - vport = unf_cm_lookup_vport_by_did(lport, did); - if (!vport) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x) received unknown ELS command with S_ID(0x%x) D_ID(0x%x))", - lport->port_id, sid, did); - return UNF_RETURN_ERROR; - } - lport = vport; - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_INFO, - "[info]VPort(0x%x) received ELS command with S_ID(0x%x) D_ID(0x%x)", - lport->port_id, sid, did); - } - - do { - if (pkg->cmnd == els_handle_table[i].cmnd) { - els_cmnd_handler = els_handle_table[i].els_cmnd_handler; - break; - } - i++; - } while (i < (sizeof(els_handle_table) / sizeof(struct unf_els_handle_table))); - - if (els_cmnd_handler) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "[info]Port(0x%x) receive ELS(0x%x) from RPort(0x%x) and process it", - lport->port_id, pkg->cmnd, sid); - ret = els_cmnd_handler(lport, sid, xchg); - } else { - ret = unf_els_cmnd_default_handler(lport, xchg, sid, pkg->cmnd); - } - return ret; -} - -u32 unf_send_els_rsp_succ(struct unf_lport *lport, struct unf_frame_pkg *pkg) -{ - struct unf_xchg *xchg = NULL; - u32 ret = RETURN_OK; - u16 hot_pool_tag = 0; - ulong flags = 0; - void (*ob_callback)(struct unf_xchg *) = NULL; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(pkg, UNF_RETURN_ERROR); - - if (!lport->xchg_mgr_temp.unf_look_up_xchg_by_tag) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) lookup exchange by tag function is NULL", - lport->port_id); - - return UNF_RETURN_ERROR; - } - - hot_pool_tag = (u16)(pkg->private_data[PKG_PRIVATE_XCHG_HOT_POOL_INDEX]); - xchg = (struct unf_xchg *)(lport->xchg_mgr_temp.unf_look_up_xchg_by_tag((void *)lport, - hot_pool_tag)); - if (!xchg) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) find exhange by tag(0x%x) failed", - lport->port_id, hot_pool_tag); - - return UNF_RETURN_ERROR; - } - - lport->xchg_mgr_temp.unf_xchg_cancel_timer((void *)xchg); - - spin_lock_irqsave(&xchg->xchg_state_lock, flags); - if (xchg->ob_callback && - (!(xchg->io_state & TGT_IO_STATE_ABORT))) { - ob_callback = xchg->ob_callback; - spin_unlock_irqrestore(&xchg->xchg_state_lock, flags); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "[info]Port(0x%x) with exchange(0x%p) tag(0x%x) do callback", - lport->port_id, xchg, hot_pool_tag); - - ob_callback(xchg); - } else { - spin_unlock_irqrestore(&xchg->xchg_state_lock, flags); - } - - unf_cm_free_xchg((void *)lport, (void *)xchg); - return ret; -} - -static u8 *unf_calc_big_resp_pld_buffer(struct unf_xchg *xchg, u32 cmnd_code) -{ - u8 *resp_pld = NULL; - u8 *dest = NULL; - - FC_CHECK_RETURN_VALUE(xchg, NULL); - - if (cmnd_code == ELS_ECHO) { - resp_pld = (u8 *)xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr->echo.echo_pld; - } else { - resp_pld = (u8 *)xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr - ->get_id.gid_rsp.gid_acc_pld; - } - - if (resp_pld) - dest = (u8 *)(resp_pld + xchg->fcp_sfs_union.sfs_entry.cur_offset); - - return dest; -} - -static u8 *unf_calc_other_resp_pld_buffer(struct unf_xchg *xchg) -{ - u8 *dest = NULL; - u32 offset = 0; - - FC_CHECK_RETURN_VALUE(xchg, NULL); - - offset = xchg->fcp_sfs_union.sfs_entry.cur_offset; - dest = (u8 *)((u8 *)(xchg->fcp_sfs_union.sfs_entry.fc_sfs_entry_ptr) + offset); - - return dest; -} - -u32 unf_mv_resp_2_xchg(struct unf_xchg *xchg, struct unf_frame_pkg *pkg) -{ - u8 *dest = NULL; - u32 length = 0; - u32 offset = 0; - u32 max_frame_len = 0; - ulong flags = 0; - - spin_lock_irqsave(&xchg->xchg_state_lock, flags); - - if (UNF_NEED_BIG_RESPONSE_BUFF(xchg->cmnd_code)) { - dest = unf_calc_big_resp_pld_buffer(xchg, xchg->cmnd_code); - offset = 0; - max_frame_len = sizeof(struct unf_gid_acc_pld); - } else if (NS_GA_NXT == xchg->cmnd_code || NS_GIEL == xchg->cmnd_code) { - dest = unf_calc_big_resp_pld_buffer(xchg, xchg->cmnd_code); - offset = 0; - max_frame_len = xchg->fcp_sfs_union.sfs_entry.sfs_buff_len; - } else { - dest = unf_calc_other_resp_pld_buffer(xchg); - offset = sizeof(struct unf_fc_head); - max_frame_len = sizeof(union unf_sfs_u); - } - - if (!dest) { - spin_unlock_irqrestore(&xchg->xchg_state_lock, flags); - - return UNF_RETURN_ERROR; - } - - if (xchg->fcp_sfs_union.sfs_entry.cur_offset == 0) { - xchg->fcp_sfs_union.sfs_entry.cur_offset += offset; - dest = dest + offset; - } - - length = pkg->unf_cmnd_pload_bl.length; - - if ((xchg->fcp_sfs_union.sfs_entry.cur_offset + length) > - max_frame_len) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Exchange(0x%p) command(0x%x) hotpooltag(0x%x) OX_RX_ID(0x%x) S_ID(0x%x) D_ID(0x%x) copy payload overrun(0x%x:0x%x:0x%x)", - xchg, xchg->cmnd_code, xchg->hotpooltag, pkg->frame_head.oxid_rxid, - pkg->frame_head.csctl_sid & UNF_NPORTID_MASK, - pkg->frame_head.rctl_did & UNF_NPORTID_MASK, - xchg->fcp_sfs_union.sfs_entry.cur_offset, - pkg->unf_cmnd_pload_bl.length, max_frame_len); - - length = max_frame_len - xchg->fcp_sfs_union.sfs_entry.cur_offset; - } - - if (length > 0) - memcpy(dest, pkg->unf_cmnd_pload_bl.buffer_ptr, length); - - xchg->fcp_sfs_union.sfs_entry.cur_offset += length; - spin_unlock_irqrestore(&xchg->xchg_state_lock, flags); - - return RETURN_OK; -} - -static void unf_ls_gs_do_callback(struct unf_xchg *xchg, - struct unf_frame_pkg *pkg) -{ - ulong flags = 0; - void (*callback)(void *, void *, void *) = NULL; - - spin_lock_irqsave(&xchg->xchg_state_lock, flags); - if (xchg->callback && - (xchg->cmnd_code == ELS_RRQ || - xchg->cmnd_code == ELS_LOGO || - !(xchg->io_state & TGT_IO_STATE_ABORT))) { - callback = xchg->callback; - - if (xchg->cmnd_code == ELS_FLOGI || xchg->cmnd_code == ELS_FDISC) - xchg->sid = pkg->frame_head.rctl_did & UNF_NPORTID_MASK; - - if (xchg->cmnd_code == ELS_ECHO) { - xchg->private_data[PKG_PRIVATE_ECHO_CMD_RCV_TIME] = - pkg->private_data[PKG_PRIVATE_ECHO_CMD_RCV_TIME]; - xchg->private_data[PKG_PRIVATE_ECHO_RSP_SND_TIME] = - pkg->private_data[PKG_PRIVATE_ECHO_RSP_SND_TIME]; - xchg->private_data[PKG_PRIVATE_ECHO_CMD_SND_TIME] = - pkg->private_data[PKG_PRIVATE_ECHO_CMD_SND_TIME]; - xchg->private_data[PKG_PRIVATE_ECHO_ACC_RCV_TIME] = - pkg->private_data[PKG_PRIVATE_ECHO_ACC_RCV_TIME]; - } - spin_unlock_irqrestore(&xchg->xchg_state_lock, flags); - callback(xchg->lport, xchg->rport, xchg); - } else { - spin_unlock_irqrestore(&xchg->xchg_state_lock, flags); - } -} - -u32 unf_send_ls_gs_cmnd_succ(struct unf_lport *lport, struct unf_frame_pkg *pkg) -{ - struct unf_xchg *xchg = NULL; - u32 ret = RETURN_OK; - u16 hot_pool_tag = 0; - struct unf_lport *unf_lport = NULL; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(pkg, UNF_RETURN_ERROR); - unf_lport = lport; - - if (!unf_lport->xchg_mgr_temp.unf_look_up_xchg_by_tag) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) lookup exchange by tag function can't be NULL", - unf_lport->port_id); - - return UNF_RETURN_ERROR; - } - - hot_pool_tag = (u16)(pkg->private_data[PKG_PRIVATE_XCHG_HOT_POOL_INDEX]); - xchg = (struct unf_xchg *)(unf_lport->xchg_mgr_temp - .unf_look_up_xchg_by_tag((void *)unf_lport, hot_pool_tag)); - if (!xchg) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x_0x%x) find exchange by tag(0x%x) failed", - unf_lport->port_id, unf_lport->nport_id, hot_pool_tag); - - return UNF_RETURN_ERROR; - } - - UNF_CHECK_ALLOCTIME_VALID(unf_lport, hot_pool_tag, xchg, - pkg->private_data[PKG_PRIVATE_XCHG_ALLOC_TIME], - xchg->private_data[PKG_PRIVATE_XCHG_ALLOC_TIME]); - - if ((pkg->frame_head.csctl_sid & UNF_NPORTID_MASK) != xchg->did) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) find exhange invalid, package S_ID(0x%x) exchange S_ID(0x%x) D_ID(0x%x)", - unf_lport->port_id, pkg->frame_head.csctl_sid, xchg->sid, xchg->did); - - return UNF_RETURN_ERROR; - } - - if (pkg->last_pkg_flag == UNF_PKG_NOT_LAST_RESPONSE) { - ret = unf_mv_resp_2_xchg(xchg, pkg); - return ret; - } - - xchg->byte_orders = pkg->byte_orders; - unf_lport->xchg_mgr_temp.unf_xchg_cancel_timer((void *)xchg); - unf_ls_gs_do_callback(xchg, pkg); - unf_cm_free_xchg((void *)unf_lport, (void *)xchg); - return ret; -} - -u32 unf_send_ls_gs_cmnd_failed(struct unf_lport *lport, - struct unf_frame_pkg *pkg) -{ - struct unf_xchg *xchg = NULL; - u32 ret = RETURN_OK; - u16 hot_pool_tag = 0; - ulong flags = 0; - void (*ob_callback)(struct unf_xchg *) = NULL; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(pkg, UNF_RETURN_ERROR); - - if (!lport->xchg_mgr_temp.unf_look_up_xchg_by_tag) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) lookup exchange by tag function can't be NULL", - lport->port_id); - - return UNF_RETURN_ERROR; - } - - hot_pool_tag = (u16)(pkg->private_data[PKG_PRIVATE_XCHG_HOT_POOL_INDEX]); - xchg = (struct unf_xchg *)(lport->xchg_mgr_temp.unf_look_up_xchg_by_tag((void *)lport, - hot_pool_tag)); - if (!xchg) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x_0x%x) find exhange by tag(0x%x) failed", - lport->port_id, lport->nport_id, hot_pool_tag); - - return UNF_RETURN_ERROR; - } - - UNF_CHECK_ALLOCTIME_VALID(lport, hot_pool_tag, xchg, - pkg->private_data[PKG_PRIVATE_XCHG_ALLOC_TIME], - xchg->private_data[PKG_PRIVATE_XCHG_ALLOC_TIME]); - - lport->xchg_mgr_temp.unf_xchg_cancel_timer((void *)xchg); - - spin_lock_irqsave(&xchg->xchg_state_lock, flags); - if (xchg->ob_callback && - (xchg->cmnd_code == ELS_RRQ || xchg->cmnd_code == ELS_LOGO || - (!(xchg->io_state & TGT_IO_STATE_ABORT)))) { - ob_callback = xchg->ob_callback; - xchg->ob_callback_sts = pkg->status; - spin_unlock_irqrestore(&xchg->xchg_state_lock, flags); - - ob_callback(xchg); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "[info]Port(0x%x) exchange(0x%p) tag(0x%x) do callback", - lport->port_id, xchg, hot_pool_tag); - } else { - spin_unlock_irqrestore(&xchg->xchg_state_lock, flags); - } - - unf_cm_free_xchg((void *)lport, (void *)xchg); - return ret; -} - -static u32 unf_rcv_ls_gs_cmnd_reply(struct unf_lport *lport, - struct unf_frame_pkg *pkg) -{ - u32 ret = RETURN_OK; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(pkg, UNF_RETURN_ERROR); - - if (pkg->status == UNF_IO_SUCCESS || pkg->status == UNF_IO_UNDER_FLOW) - ret = unf_send_ls_gs_cmnd_succ(lport, pkg); - else - ret = unf_send_ls_gs_cmnd_failed(lport, pkg); - - return ret; -} - -u32 unf_receive_ls_gs_pkg(void *lport, struct unf_frame_pkg *pkg) -{ - struct unf_lport *unf_lport = NULL; - u32 ret = UNF_RETURN_ERROR; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(pkg, UNF_RETURN_ERROR); - unf_lport = (struct unf_lport *)lport; - - switch (pkg->type) { - case UNF_PKG_ELS_REQ_DONE: - case UNF_PKG_GS_REQ_DONE: - ret = unf_rcv_ls_gs_cmnd_reply(unf_lport, pkg); - break; - - case UNF_PKG_ELS_REQ: - ret = unf_rcv_els_cmnd_req(unf_lport, pkg); - break; - - default: - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x_0x%x) with exchange type(0x%x) abnormal", - unf_lport->port_id, unf_lport->nport_id, pkg->type); - break; - } - - return ret; -} - -u32 unf_send_els_done(void *lport, struct unf_frame_pkg *pkg) -{ - u32 ret = UNF_RETURN_ERROR; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(pkg, UNF_RETURN_ERROR); - - if (pkg->type == UNF_PKG_ELS_REPLY_DONE) { - if (pkg->status == UNF_IO_SUCCESS || pkg->status == UNF_IO_UNDER_FLOW) - ret = unf_send_els_rsp_succ(lport, pkg); - else - ret = unf_send_ls_gs_cmnd_failed(lport, pkg); - } - - return ret; -} - -void unf_rport_immediate_link_down(struct unf_lport *lport, struct unf_rport *rport) -{ - /* Swap case: Report Link Down immediately & release R_Port */ - ulong flags = 0; - struct unf_disc *disc = NULL; - - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(rport); - - spin_lock_irqsave(&rport->rport_state_lock, flags); - /* 1. Inc R_Port ref_cnt */ - if (unf_rport_ref_inc(rport) != RETURN_OK) { - spin_unlock_irqrestore(&rport->rport_state_lock, flags); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) Rport(0x%p,0x%x) is removing and no need process", - lport->port_id, rport, rport->nport_id); - - return; - } - - /* 2. R_PORT state update: Link Down Event --->>> closing state */ - unf_rport_state_ma(rport, UNF_EVENT_RPORT_LINK_DOWN); - spin_unlock_irqrestore(&rport->rport_state_lock, flags); - - /* 3. Put R_Port from busy to destroy list */ - disc = &lport->disc; - spin_lock_irqsave(&disc->rport_busy_pool_lock, flags); - list_del_init(&rport->entry_rport); - list_add_tail(&rport->entry_rport, &disc->list_destroy_rports); - spin_unlock_irqrestore(&disc->rport_busy_pool_lock, flags); - - /* 4. Schedule Closing work (Enqueuing workqueue) */ - unf_schedule_closing_work(lport, rport); - - unf_rport_ref_dec(rport); -} - -struct unf_rport *unf_find_rport(struct unf_lport *lport, u32 rport_nport_id, - u64 lport_name) -{ - struct unf_lport *unf_lport = lport; - struct unf_rport *unf_rport = NULL; - - FC_CHECK_RETURN_VALUE(lport, NULL); - - if (rport_nport_id >= UNF_FC_FID_DOM_MGR) { - /* R_Port is Fabric: by N_Port_ID */ - unf_rport = unf_get_rport_by_nport_id(unf_lport, rport_nport_id); - } else { - /* Others: by WWPN & N_Port_ID */ - unf_rport = unf_find_valid_rport(unf_lport, lport_name, rport_nport_id); - } - - return unf_rport; -} - -void unf_process_logo_in_pri_loop(struct unf_lport *lport, struct unf_rport *rport) -{ - /* Send PLOGI or LOGO */ - struct unf_rport *unf_rport = rport; - ulong flag = 0; - - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(rport); - - spin_lock_irqsave(&unf_rport->rport_state_lock, flag); - unf_rport_state_ma(unf_rport, UNF_EVENT_RPORT_ENTER_PLOGI); /* PLOGI WAIT */ - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flag); - - /* Private Loop with INI mode, Avoid COM Mode problem */ - unf_rport_delay_login(unf_rport); -} - -void unf_process_logo_in_n2n(struct unf_lport *lport, struct unf_rport *rport) -{ - /* Send PLOGI or LOGO */ - struct unf_lport *unf_lport = lport; - struct unf_rport *unf_rport = rport; - ulong flag = 0; - u32 ret = UNF_RETURN_ERROR; - - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(rport); - - spin_lock_irqsave(&unf_rport->rport_state_lock, flag); - - unf_rport_state_ma(unf_rport, UNF_EVENT_RPORT_ENTER_PLOGI); - spin_unlock_irqrestore(&unf_rport->rport_state_lock, flag); - - if (unf_lport->port_name > unf_rport->port_name) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x)'s WWN(0x%llx) is larger than(0x%llx), should be master", - unf_lport->port_id, unf_lport->port_name, unf_rport->port_name); - - ret = unf_send_plogi(unf_lport, unf_rport); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]LOGIN: Port(0x%x) send PLOGI failed, enter recovery", - lport->port_id); - - unf_rport_error_recovery(unf_rport); - } - } else { - unf_rport_enter_logo(unf_lport, unf_rport); - } -} - -void unf_process_logo_in_fabric(struct unf_lport *lport, - struct unf_rport *rport) -{ - /* Send GFF_ID or LOGO */ - struct unf_lport *unf_lport = lport; - struct unf_rport *unf_rport = rport; - struct unf_rport *sns_port = NULL; - u32 ret = UNF_RETURN_ERROR; - - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(rport); - - /* L_Port with INI Mode: Send GFF_ID */ - sns_port = unf_get_rport_by_nport_id(unf_lport, UNF_FC_FID_DIR_SERV); - if (!sns_port) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) can't find fabric port", - unf_lport->port_id); - return; - } - - ret = unf_get_and_post_disc_event(lport, sns_port, unf_rport->nport_id, - UNF_DISC_GET_FEATURE); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) add discovery event(0x%x) failed Rport(0x%x)", - unf_lport->port_id, UNF_DISC_GET_FEATURE, - unf_rport->nport_id); - - unf_rcv_gff_id_rsp_unknown(unf_lport, unf_rport->nport_id); - } -} - -void unf_process_rport_after_logo(struct unf_lport *lport, struct unf_rport *rport) -{ - /* - * 1. LOGO handler - * 2. RPLO handler - * 3. LOGO_CALL_BACK (send LOGO ACC) handler - */ - struct unf_lport *unf_lport = lport; - struct unf_rport *unf_rport = rport; - - FC_CHECK_RETURN_VOID(lport); - FC_CHECK_RETURN_VOID(rport); - - if (unf_rport->nport_id < UNF_FC_FID_DOM_MGR) { - /* R_Port is not fabric port (retry LOGIN or LOGO) */ - if (unf_lport->act_topo == UNF_ACT_TOP_PRIVATE_LOOP) { - /* Private Loop: PLOGI or LOGO */ - unf_process_logo_in_pri_loop(unf_lport, unf_rport); - } else if (unf_lport->act_topo == UNF_ACT_TOP_P2P_DIRECT) { - /* Point to Point: LOGIN or LOGO */ - unf_process_logo_in_n2n(unf_lport, unf_rport); - } else { - /* Fabric or Public Loop: GFF_ID or LOGO */ - unf_process_logo_in_fabric(unf_lport, unf_rport); - } - } else { - /* Rport is fabric port: link down now */ - unf_rport_linkdown(unf_lport, unf_rport); - } -} - -static u32 unf_rcv_bls_req_done(struct unf_lport *lport, struct unf_frame_pkg *pkg) -{ - /* - * About I/O resource: - * 1. normal: Release I/O resource during RRQ processer - * 2. exception: Release I/O resource immediately - */ - struct unf_xchg *xchg = NULL; - u16 hot_pool_tag = 0; - ulong flags = 0; - ulong time_ms = 0; - u32 ret = RETURN_OK; - struct unf_lport *unf_lport = NULL; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(pkg, UNF_RETURN_ERROR); - unf_lport = lport; - - hot_pool_tag = (u16)pkg->private_data[PKG_PRIVATE_XCHG_HOT_POOL_INDEX]; - xchg = (struct unf_xchg *)unf_cm_lookup_xchg_by_tag((void *)unf_lport, hot_pool_tag); - if (!xchg) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x) can't find exchange by tag(0x%x) when receiving ABTS response", - unf_lport->port_id, hot_pool_tag); - return UNF_RETURN_ERROR; - } - - UNF_CHECK_ALLOCTIME_VALID(lport, hot_pool_tag, xchg, - pkg->private_data[PKG_PRIVATE_XCHG_ALLOC_TIME], - xchg->private_data[PKG_PRIVATE_XCHG_ALLOC_TIME]); - - ret = unf_xchg_ref_inc(xchg, TGT_ABTS_DONE); - FC_CHECK_RETURN_VALUE((ret == RETURN_OK), UNF_RETURN_ERROR); - - spin_lock_irqsave(&xchg->xchg_state_lock, flags); - xchg->oxid = UNF_GET_OXID(pkg); - xchg->rxid = UNF_GET_RXID(pkg); - xchg->io_state |= INI_IO_STATE_DONE; - xchg->abts_state |= ABTS_RESPONSE_RECEIVED; - if (!(INI_IO_STATE_UPABORT & xchg->io_state)) { - /* NOTE: I/O exchange has been released and used again */ - spin_unlock_irqrestore(&xchg->xchg_state_lock, flags); - - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x_0x%x) SID(0x%x) exch(0x%p) (0x%x:0x%x:0x%x:0x%x) state(0x%x) is abnormal with cnt(0x%x)", - unf_lport->port_id, unf_lport->nport_id, xchg->sid, - xchg, xchg->hotpooltag, xchg->oxid, xchg->rxid, - xchg->oid, xchg->io_state, - atomic_read(&xchg->ref_cnt)); - - unf_xchg_ref_dec(xchg, TGT_ABTS_DONE); - return UNF_RETURN_ERROR; - } - spin_unlock_irqrestore(&xchg->xchg_state_lock, flags); - unf_lport->xchg_mgr_temp.unf_xchg_cancel_timer((void *)xchg); - /* - * Exchage I/O Status check: Succ-> Add RRQ Timer - * ***** pkg->status --- to --->>> scsi_cmnd->result ***** - * * - * FAILED: ERR_Code or X_ID is err, or BA_RSP type is err - */ - spin_lock_irqsave(&xchg->xchg_state_lock, flags); - if (pkg->status == UNF_IO_SUCCESS) { - /* Succeed: PKG status -->> EXCH status -->> scsi status */ - UNF_SET_SCSI_CMND_RESULT(xchg, UNF_IO_SUCCESS); - xchg->io_state |= INI_IO_STATE_WAIT_RRQ; - xchg->rxid = UNF_GET_RXID(pkg); - spin_unlock_irqrestore(&xchg->xchg_state_lock, flags); - - /* Add RRQ timer */ - time_ms = (ulong)(unf_lport->ra_tov); - unf_lport->xchg_mgr_temp.unf_xchg_add_timer((void *)xchg, time_ms, - UNF_TIMER_TYPE_INI_RRQ); - } else { - /* Failed: PKG status -->> EXCH status -->> scsi status */ - UNF_SET_SCSI_CMND_RESULT(xchg, UNF_IO_FAILED); - if (MARKER_STS_RECEIVED & xchg->abts_state) { - spin_unlock_irqrestore(&xchg->xchg_state_lock, flags); - - /* NOTE: release I/O resource immediately */ - unf_cm_free_xchg(unf_lport, xchg); - } else { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x) exch(0x%p) OX_RX(0x%x:0x%x) IOstate(0x%x) ABTSstate(0x%x) receive response abnormal ref(0x%x)", - unf_lport->port_id, xchg, xchg->oxid, xchg->rxid, - xchg->io_state, xchg->abts_state, atomic_read(&xchg->ref_cnt)); - spin_unlock_irqrestore(&xchg->xchg_state_lock, flags); - } - } - - /* - * If abts response arrived before - * marker sts received just wake up abts marker sema - */ - spin_lock_irqsave(&xchg->xchg_state_lock, flags); - if (!(MARKER_STS_RECEIVED & xchg->abts_state)) { - xchg->ucode_abts_state = pkg->status; - spin_unlock_irqrestore(&xchg->xchg_state_lock, flags); - up(&xchg->task_sema); - } else { - spin_unlock_irqrestore(&xchg->xchg_state_lock, flags); - } - - unf_xchg_ref_dec(xchg, TGT_ABTS_DONE); - return ret; -} - -u32 unf_receive_bls_pkg(void *lport, struct unf_frame_pkg *pkg) -{ - struct unf_lport *unf_lport = NULL; - u32 ret = UNF_RETURN_ERROR; - - unf_lport = (struct unf_lport *)lport; - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(pkg, UNF_RETURN_ERROR); - - if (pkg->type == UNF_PKG_BLS_REQ_DONE) { - /* INI: RCVD BLS Req Done */ - ret = unf_rcv_bls_req_done(lport, pkg); - } else { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) received BLS packet type(%xh) is error", - unf_lport->port_id, pkg->type); - - return UNF_RETURN_ERROR; - } - - return ret; -} - -static void unf_fill_free_xid_pkg(struct unf_xchg *xchg, struct unf_frame_pkg *pkg) -{ - pkg->frame_head.csctl_sid = xchg->sid; - pkg->frame_head.rctl_did = xchg->did; - pkg->frame_head.oxid_rxid = (u32)(((u32)xchg->oxid << UNF_SHIFT_16) | xchg->rxid); - pkg->private_data[PKG_PRIVATE_XCHG_HOT_POOL_INDEX] = xchg->hotpooltag; - UNF_SET_XCHG_ALLOC_TIME(pkg, xchg); - - if (xchg->xchg_type == UNF_XCHG_TYPE_SFS) { - if (UNF_XCHG_IS_ELS_REPLY(xchg)) { - pkg->type = UNF_PKG_ELS_REPLY; - pkg->rx_or_ox_id = UNF_PKG_FREE_RXID; - pkg->private_data[PKG_PRIVATE_XCHG_HOT_POOL_INDEX] = INVALID_VALUE32; - pkg->private_data[PKG_PRIVATE_XCHG_ALLOC_TIME] = INVALID_VALUE32; - } else { - pkg->type = UNF_PKG_ELS_REQ; - pkg->rx_or_ox_id = UNF_PKG_FREE_OXID; - } - } else if (xchg->xchg_type == UNF_XCHG_TYPE_INI) { - pkg->type = UNF_PKG_INI_IO; - pkg->rx_or_ox_id = UNF_PKG_FREE_OXID; - } -} - -void unf_notify_chip_free_xid(struct unf_xchg *xchg) -{ - struct unf_lport *unf_lport = NULL; - u32 ret = RETURN_ERROR; - struct unf_frame_pkg pkg = {0}; - - FC_CHECK_RETURN_VOID(xchg); - unf_lport = xchg->lport; - FC_CHECK_RETURN_VOID(unf_lport); - - unf_fill_free_xid_pkg(xchg, &pkg); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "[info]Sid_Did(0x%x)(0x%x) Xchg(0x%p) RXorOX(0x%x) tag(0x%x) xid(0x%x) magic(0x%x) Stat(0x%x)type(0x%x) wait timeout.", - xchg->sid, xchg->did, xchg, pkg.rx_or_ox_id, - pkg.private_data[PKG_PRIVATE_XCHG_HOT_POOL_INDEX], pkg.frame_head.oxid_rxid, - pkg.private_data[PKG_PRIVATE_XCHG_ALLOC_TIME], xchg->io_state, pkg.type); - - ret = unf_lport->low_level_func.service_op.ll_release_xid(unf_lport->fc_port, &pkg); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Free xid abnormal:Sid_Did(0x%x 0x%x) Xchg(0x%p) RXorOX(0x%x) xid(0x%x) Stat(0x%x) tag(0x%x) magic(0x%x) type(0x%x).", - xchg->sid, xchg->did, xchg, pkg.rx_or_ox_id, - pkg.frame_head.oxid_rxid, xchg->io_state, - pkg.private_data[PKG_PRIVATE_XCHG_HOT_POOL_INDEX], - pkg.private_data[PKG_PRIVATE_XCHG_ALLOC_TIME], - pkg.type); - } -} diff --git a/drivers/scsi/spfc/common/unf_service.h b/drivers/scsi/spfc/common/unf_service.h deleted file mode 100644 index 0dd2975c6a7b..000000000000 --- a/drivers/scsi/spfc/common/unf_service.h +++ /dev/null @@ -1,66 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef UNF_SERVICE_H -#define UNF_SERVICE_H - -#include "unf_type.h" -#include "unf_exchg.h" -#include "unf_rport.h" - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -extern u32 max_frame_size; -#define UNF_INIT_DISC 0x1 /* first time DISC */ -#define UNF_RSCN_DISC 0x2 /* RSCN Port Addr DISC */ -#define UNF_SET_ELS_ACC_TYPE(els_cmd) ((u32)(els_cmd) << 16 | ELS_ACC) -#define UNF_SET_ELS_RJT_TYPE(els_cmd) ((u32)(els_cmd) << 16 | ELS_RJT) -#define UNF_XCHG_IS_ELS_REPLY(xchg) \ - ((ELS_ACC == ((xchg)->cmnd_code & 0x0ffff)) || \ - (ELS_RJT == ((xchg)->cmnd_code & 0x0ffff))) - -struct unf_els_handle_table { - u32 cmnd; - u32 (*els_cmnd_handler)(struct unf_lport *lport, u32 sid, struct unf_xchg *xchg); -}; - -void unf_select_sq(struct unf_xchg *xchg, struct unf_frame_pkg *pkg); -void unf_fill_package(struct unf_frame_pkg *pkg, struct unf_xchg *xchg, - struct unf_rport *rport); -struct unf_xchg *unf_get_sfs_free_xchg_and_init(struct unf_lport *lport, - u32 did, - struct unf_rport *rport, - union unf_sfs_u **fc_entry); -void *unf_get_one_big_sfs_buf(struct unf_xchg *xchg); -u32 unf_mv_resp_2_xchg(struct unf_xchg *xchg, struct unf_frame_pkg *pkg); -void unf_rport_immediate_link_down(struct unf_lport *lport, - struct unf_rport *rport); -struct unf_rport *unf_find_rport(struct unf_lport *lport, u32 rport_nport_id, - u64 port_name); -void unf_process_logo_in_fabric(struct unf_lport *lport, - struct unf_rport *rport); -void unf_notify_chip_free_xid(struct unf_xchg *xchg); - -u32 unf_ls_gs_cmnd_send(struct unf_lport *lport, struct unf_frame_pkg *pkg, - struct unf_xchg *xchg); -u32 unf_receive_ls_gs_pkg(void *lport, struct unf_frame_pkg *pkg); -struct unf_xchg *unf_mv_data_2_xchg(struct unf_lport *lport, - struct unf_frame_pkg *pkg); -u32 unf_receive_bls_pkg(void *lport, struct unf_frame_pkg *pkg); -u32 unf_send_els_done(void *lport, struct unf_frame_pkg *pkg); -u32 unf_send_els_rjt_by_did(struct unf_lport *lport, struct unf_xchg *xchg, - u32 did, struct unf_rjt_info *rjt_info); -u32 unf_send_els_rjt_by_rport(struct unf_lport *lport, struct unf_xchg *xchg, - struct unf_rport *rport, - struct unf_rjt_info *rjt_info); -u32 unf_send_abts(struct unf_lport *lport, struct unf_xchg *xchg); -void unf_process_rport_after_logo(struct unf_lport *lport, - struct unf_rport *rport); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __UNF_SERVICE_H__ */ diff --git a/drivers/scsi/spfc/common/unf_type.h b/drivers/scsi/spfc/common/unf_type.h deleted file mode 100644 index 28e163d0543c..000000000000 --- a/drivers/scsi/spfc/common/unf_type.h +++ /dev/null @@ -1,216 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef UNF_TYPE_H -#define UNF_TYPE_H - -#include <linux/sched.h> -#include <linux/kthread.h> -#include <linux/fs.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/kref.h> -#include <linux/scatterlist.h> -#include <linux/crc-t10dif.h> -#include <linux/ctype.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/random.h> -#include <linux/jiffies.h> -#include <linux/cpufreq.h> -#include <linux/semaphore.h> -#include <linux/jiffies.h> - -#include <scsi/scsi.h> -#include <scsi/scsi_host.h> -#include <scsi/scsi_device.h> -#include <scsi/scsi_cmnd.h> -#include <scsi/scsi_transport_fc.h> -#include <linux/sched/signal.h> - -#ifndef SPFC_FT -#define SPFC_FT -#endif - -#define BUF_LIST_PAGE_SIZE (PAGE_SIZE << 8) - -#define UNF_S_TO_NS (1000000000) -#define UNF_S_TO_MS (1000) - -enum UNF_OS_THRD_PRI_E { - UNF_OS_THRD_PRI_HIGHEST = 0, - UNF_OS_THRD_PRI_HIGH, - UNF_OS_THRD_PRI_SUBHIGH, - UNF_OS_THRD_PRI_MIDDLE, - UNF_OS_THRD_PRI_LOW, - UNF_OS_THRD_PRI_BUTT -}; - -#define UNF_OS_LIST_NEXT(a) ((a)->next) -#define UNF_OS_LIST_PREV(a) ((a)->prev) - -#define UNF_OS_PER_NS (1000000000) -#define UNF_OS_MS_TO_NS (1000000) - -#ifndef MIN -#define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) -#endif - -#ifndef MAX -#define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) -#endif - -#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) - -/* define shift bits */ -#define UNF_SHIFT_1 1 -#define UNF_SHIFT_2 2 -#define UNF_SHIFT_3 3 -#define UNF_SHIFT_4 4 -#define UNF_SHIFT_6 6 -#define UNF_SHIFT_7 7 -#define UNF_SHIFT_8 8 -#define UNF_SHIFT_11 11 -#define UNF_SHIFT_12 12 -#define UNF_SHIFT_15 15 -#define UNF_SHIFT_16 16 -#define UNF_SHIFT_17 17 -#define UNF_SHIFT_19 19 -#define UNF_SHIFT_20 20 -#define UNF_SHIFT_23 23 -#define UNF_SHIFT_24 24 -#define UNF_SHIFT_25 25 -#define UNF_SHIFT_26 26 -#define UNF_SHIFT_28 28 -#define UNF_SHIFT_29 29 -#define UNF_SHIFT_32 32 -#define UNF_SHIFT_35 35 -#define UNF_SHIFT_37 37 -#define UNF_SHIFT_39 39 -#define UNF_SHIFT_40 40 -#define UNF_SHIFT_43 43 -#define UNF_SHIFT_48 48 -#define UNF_SHIFT_51 51 -#define UNF_SHIFT_56 56 -#define UNF_SHIFT_57 57 -#define UNF_SHIFT_59 59 -#define UNF_SHIFT_60 60 -#define UNF_SHIFT_61 61 - -/* array index */ -#define ARRAY_INDEX_0 0 -#define ARRAY_INDEX_1 1 -#define ARRAY_INDEX_2 2 -#define ARRAY_INDEX_3 3 -#define ARRAY_INDEX_4 4 -#define ARRAY_INDEX_5 5 -#define ARRAY_INDEX_6 6 -#define ARRAY_INDEX_7 7 -#define ARRAY_INDEX_8 8 -#define ARRAY_INDEX_10 10 -#define ARRAY_INDEX_11 11 -#define ARRAY_INDEX_12 12 -#define ARRAY_INDEX_13 13 - -/* define mask bits */ -#define UNF_MASK_BIT_7_0 0xff -#define UNF_MASK_BIT_15_0 0x0000ffff -#define UNF_MASK_BIT_31_16 0xffff0000 - -#define UNF_IO_SUCCESS 0x00000000 -#define UNF_IO_ABORTED 0x00000001 /* the host system aborted the command */ -#define UNF_IO_FAILED 0x00000002 -#define UNF_IO_ABORT_ABTS 0x00000003 -#define UNF_IO_ABORT_LOGIN 0x00000004 /* abort login */ -#define UNF_IO_ABORT_REET 0x00000005 /* reset event aborted the transport */ -#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 - -#endif diff --git a/drivers/scsi/spfc/hw/spfc_chipitf.c b/drivers/scsi/spfc/hw/spfc_chipitf.c deleted file mode 100644 index be6073ff4dc0..000000000000 --- a/drivers/scsi/spfc/hw/spfc_chipitf.c +++ /dev/null @@ -1,1105 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#include "spfc_chipitf.h" -#include "sphw_hw.h" -#include "sphw_crm.h" - -#define SPFC_MBOX_TIME_SEC_MAX (60) - -#define SPFC_LINK_UP_COUNT 1 -#define SPFC_LINK_DOWN_COUNT 2 -#define SPFC_FC_DELETE_CMND_COUNT 3 - -#define SPFC_MBX_MAX_TIMEOUT 10000 - -u32 spfc_get_chip_msg(void *hba, void *mac) -{ - struct spfc_hba_info *spfc_hba = NULL; - struct unf_get_chip_info_argout *wwn = NULL; - struct spfc_inmbox_get_chip_info get_chip_info; - union spfc_outmbox_generic *get_chip_info_sts = NULL; - u32 ret = UNF_RETURN_ERROR; - - FC_CHECK_RETURN_VALUE(hba, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(mac, UNF_RETURN_ERROR); - - spfc_hba = (struct spfc_hba_info *)hba; - wwn = (struct unf_get_chip_info_argout *)mac; - - memset(&get_chip_info, 0, sizeof(struct spfc_inmbox_get_chip_info)); - - get_chip_info_sts = kmalloc(sizeof(union spfc_outmbox_generic), GFP_ATOMIC); - if (!get_chip_info_sts) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]malloc outmbox memory failed"); - return UNF_RETURN_ERROR; - } - memset(get_chip_info_sts, 0, sizeof(union spfc_outmbox_generic)); - - get_chip_info.header.cmnd_type = SPFC_MBOX_GET_CHIP_INFO; - get_chip_info.header.length = - SPFC_BYTES_TO_DW_NUM(sizeof(struct spfc_inmbox_get_chip_info)); - - if (spfc_mb_send_and_wait_mbox(spfc_hba, &get_chip_info, - sizeof(struct spfc_inmbox_get_chip_info), - get_chip_info_sts) != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]spfc can't send and wait mailbox, command type: 0x%x.", - get_chip_info.header.cmnd_type); - - goto exit; - } - - if (get_chip_info_sts->get_chip_info_sts.status != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Port(0x%x) mailbox status incorrect status(0x%x) .", - spfc_hba->port_cfg.port_id, - get_chip_info_sts->get_chip_info_sts.status); - - goto exit; - } - - if (get_chip_info_sts->get_chip_info_sts.header.cmnd_type != SPFC_MBOX_GET_CHIP_INFO_STS) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "Port(0x%x) receive mailbox type incorrect type: 0x%x.", - spfc_hba->port_cfg.port_id, - get_chip_info_sts->get_chip_info_sts.header.cmnd_type); - - goto exit; - } - - wwn->board_type = get_chip_info_sts->get_chip_info_sts.board_type; - spfc_hba->card_info.card_type = get_chip_info_sts->get_chip_info_sts.board_type; - wwn->wwnn = get_chip_info_sts->get_chip_info_sts.wwnn; - wwn->wwpn = get_chip_info_sts->get_chip_info_sts.wwpn; - - ret = RETURN_OK; -exit: - kfree(get_chip_info_sts); - - return ret; -} - -u32 spfc_get_chip_capability(void *hwdev_handle, - struct spfc_chip_info *chip_info) -{ - struct spfc_inmbox_get_chip_info get_chip_info; - union spfc_outmbox_generic *get_chip_info_sts = NULL; - u16 out_size = 0; - u32 ret = UNF_RETURN_ERROR; - - FC_CHECK_RETURN_VALUE(hwdev_handle, UNF_RETURN_ERROR); - - memset(&get_chip_info, 0, sizeof(struct spfc_inmbox_get_chip_info)); - - get_chip_info_sts = kmalloc(sizeof(union spfc_outmbox_generic), GFP_ATOMIC); - if (!get_chip_info_sts) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "malloc outmbox memory failed"); - return UNF_RETURN_ERROR; - } - memset(get_chip_info_sts, 0, sizeof(union spfc_outmbox_generic)); - - get_chip_info.header.cmnd_type = SPFC_MBOX_GET_CHIP_INFO; - get_chip_info.header.length = - SPFC_BYTES_TO_DW_NUM(sizeof(struct spfc_inmbox_get_chip_info)); - get_chip_info.header.port_id = (u8)sphw_global_func_id(hwdev_handle); - out_size = sizeof(union spfc_outmbox_generic); - - if (sphw_msg_to_mgmt_sync(hwdev_handle, COMM_MOD_FC, SPFC_MBOX_GET_CHIP_INFO, - (void *)&get_chip_info.header, - sizeof(struct spfc_inmbox_get_chip_info), - (union spfc_outmbox_generic *)(get_chip_info_sts), &out_size, - (SPFC_MBX_MAX_TIMEOUT), SPHW_CHANNEL_FC) != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "spfc can't send and wait mailbox, command type: 0x%x.", - SPFC_MBOX_GET_CHIP_INFO); - - goto exit; - } - - if (get_chip_info_sts->get_chip_info_sts.status != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Port mailbox status incorrect status(0x%x) .", - get_chip_info_sts->get_chip_info_sts.status); - - goto exit; - } - - if (get_chip_info_sts->get_chip_info_sts.header.cmnd_type != SPFC_MBOX_GET_CHIP_INFO_STS) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Port receive mailbox type incorrect type: 0x%x.", - get_chip_info_sts->get_chip_info_sts.header.cmnd_type); - - goto exit; - } - - chip_info->wwnn = get_chip_info_sts->get_chip_info_sts.wwnn; - chip_info->wwpn = get_chip_info_sts->get_chip_info_sts.wwpn; - - ret = RETURN_OK; -exit: - kfree(get_chip_info_sts); - - return ret; -} - -u32 spfc_config_port_table(struct spfc_hba_info *hba) -{ - struct spfc_inmbox_config_api config_api; - union spfc_outmbox_generic *out_mbox = NULL; - u32 ret = UNF_RETURN_ERROR; - - FC_CHECK_RETURN_VALUE(hba, UNF_RETURN_ERROR); - - memset(&config_api, 0, sizeof(config_api)); - out_mbox = kmalloc(sizeof(union spfc_outmbox_generic), GFP_ATOMIC); - if (!out_mbox) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]malloc outmbox memory failed"); - return UNF_RETURN_ERROR; - } - memset(out_mbox, 0, sizeof(union spfc_outmbox_generic)); - - config_api.header.cmnd_type = SPFC_MBOX_CONFIG_API; - config_api.header.length = SPFC_BYTES_TO_DW_NUM(sizeof(struct spfc_inmbox_config_api)); - - config_api.op_code = UNDEFINEOPCODE; - - /* change switching top cmd of CM to the cmd that up recognize */ - /* if the cmd equals UNF_TOP_P2P_MASK sending in CM means that it - * should be changed into P2P top, LL using SPFC_TOP_NON_LOOP_MASK - */ - if (((u8)(hba->port_topo_cfg)) == UNF_TOP_P2P_MASK) { - config_api.topy_mode = 0x2; - /* if the cmd equals UNF_TOP_LOOP_MASK sending in CM means that it - *should be changed into loop top, LL using SPFC_TOP_LOOP_MASK - */ - } else if (((u8)(hba->port_topo_cfg)) == UNF_TOP_LOOP_MASK) { - config_api.topy_mode = 0x1; - /* if the cmd equals UNF_TOP_AUTO_MASK sending in CM means that it - *should be changed into loop top, LL using SPFC_TOP_AUTO_MASK - */ - } else if (((u8)(hba->port_topo_cfg)) == UNF_TOP_AUTO_MASK) { - config_api.topy_mode = 0x0; - } else { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Port(0x%x) topo cmd is error, command type: 0x%x", - hba->port_cfg.port_id, (u8)(hba->port_topo_cfg)); - - goto exit; - } - - /* About speed */ - config_api.sfp_speed = (u8)(hba->port_speed_cfg); - config_api.max_speed = (u8)(hba->max_support_speed); - - config_api.rx_6432g_bb_credit = SPFC_LOWLEVEL_DEFAULT_32G_BB_CREDIT; - config_api.rx_16g_bb_credit = SPFC_LOWLEVEL_DEFAULT_16G_BB_CREDIT; - config_api.rx_84g_bb_credit = SPFC_LOWLEVEL_DEFAULT_8G_BB_CREDIT; - config_api.rdy_cnt_bf_fst_frm = SPFC_LOWLEVEL_DEFAULT_LOOP_BB_CREDIT; - config_api.esch_32g_value = SPFC_LOWLEVEL_DEFAULT_32G_ESCH_VALUE; - config_api.esch_16g_value = SPFC_LOWLEVEL_DEFAULT_16G_ESCH_VALUE; - config_api.esch_8g_value = SPFC_LOWLEVEL_DEFAULT_8G_ESCH_VALUE; - config_api.esch_4g_value = SPFC_LOWLEVEL_DEFAULT_8G_ESCH_VALUE; - config_api.esch_64g_value = SPFC_LOWLEVEL_DEFAULT_8G_ESCH_VALUE; - config_api.esch_bust_size = SPFC_LOWLEVEL_DEFAULT_ESCH_BUST_SIZE; - - /* default value:0xFF */ - config_api.hard_alpa = 0xFF; - memcpy(config_api.port_name, hba->sys_port_name, UNF_WWN_LEN); - - /* if only for slave, the value is 1; if participate master choosing, - * the value is 0 - */ - config_api.slave = hba->port_loop_role; - - /* 1:auto negotiate, 0:fixed mode negotiate */ - if (config_api.sfp_speed == 0) - config_api.auto_sneg = 0x1; - else - config_api.auto_sneg = 0x0; - - if (spfc_mb_send_and_wait_mbox(hba, &config_api, sizeof(config_api), - out_mbox) != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[warn]Port(0x%x) SPFC can't send and wait mailbox, command type: 0x%x", - hba->port_cfg.port_id, - config_api.header.cmnd_type); - - goto exit; - } - - if (out_mbox->config_api_sts.status != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_EQUIP_ATT, UNF_ERR, - "[err]Port(0x%x) receive mailbox type(0x%x) with status(0x%x) error", - hba->port_cfg.port_id, - out_mbox->config_api_sts.header.cmnd_type, - out_mbox->config_api_sts.status); - - goto exit; - } - - if (out_mbox->config_api_sts.header.cmnd_type != SPFC_MBOX_CONFIG_API_STS) { - FC_DRV_PRINT(UNF_LOG_EQUIP_ATT, UNF_ERR, - "[err]Port(0x%x) receive mailbox type(0x%x) error", - hba->port_cfg.port_id, - out_mbox->config_api_sts.header.cmnd_type); - - goto exit; - } - - ret = RETURN_OK; -exit: - kfree(out_mbox); - - return ret; -} - -u32 spfc_port_switch(struct spfc_hba_info *hba, bool turn_on) -{ - struct spfc_inmbox_port_switch port_switch; - union spfc_outmbox_generic *port_switch_sts = NULL; - u32 ret = UNF_RETURN_ERROR; - - FC_CHECK_RETURN_VALUE(hba, UNF_RETURN_ERROR); - - memset(&port_switch, 0, sizeof(port_switch)); - - port_switch_sts = kmalloc(sizeof(union spfc_outmbox_generic), GFP_ATOMIC); - if (!port_switch_sts) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]malloc outmbox memory failed"); - return UNF_RETURN_ERROR; - } - memset(port_switch_sts, 0, sizeof(union spfc_outmbox_generic)); - - port_switch.header.cmnd_type = SPFC_MBOX_PORT_SWITCH; - port_switch.header.length = SPFC_BYTES_TO_DW_NUM(sizeof(struct spfc_inmbox_port_switch)); - port_switch.op_code = (u8)turn_on; - - if (spfc_mb_send_and_wait_mbox(hba, &port_switch, sizeof(port_switch), - (union spfc_outmbox_generic *)((void *)port_switch_sts)) != - RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[warn]Port(0x%x) SPFC can't send and wait mailbox, command type(0x%x) opcode(0x%x)", - hba->port_cfg.port_id, - port_switch.header.cmnd_type, port_switch.op_code); - - goto exit; - } - - if (port_switch_sts->port_switch_sts.status != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_EQUIP_ATT, UNF_ERR, - "[err]Port(0x%x) receive mailbox type(0x%x) status(0x%x) error", - hba->port_cfg.port_id, - port_switch_sts->port_switch_sts.header.cmnd_type, - port_switch_sts->port_switch_sts.status); - - goto exit; - } - - if (port_switch_sts->port_switch_sts.header.cmnd_type != SPFC_MBOX_PORT_SWITCH_STS) { - FC_DRV_PRINT(UNF_LOG_EQUIP_ATT, UNF_ERR, - "[err]Port(0x%x) receive mailbox type(0x%x) error", - hba->port_cfg.port_id, - port_switch_sts->port_switch_sts.header.cmnd_type); - - goto exit; - } - - FC_DRV_PRINT(UNF_LOG_EQUIP_ATT, UNF_MAJOR, - "[event]Port(0x%x) switch succeed, turns to %s", - hba->port_cfg.port_id, (turn_on) ? "on" : "off"); - - ret = RETURN_OK; -exit: - kfree(port_switch_sts); - - return ret; -} - -u32 spfc_config_login_api(struct spfc_hba_info *hba, - struct unf_port_login_parms *login_parms) -{ -#define SPFC_LOOP_RDYNUM 8 - int iret = RETURN_OK; - u32 ret = UNF_RETURN_ERROR; - struct spfc_inmbox_config_login config_login; - union spfc_outmbox_generic *cfg_login_sts = NULL; - - FC_CHECK_RETURN_VALUE(hba, UNF_RETURN_ERROR); - - memset(&config_login, 0, sizeof(config_login)); - cfg_login_sts = kmalloc(sizeof(union spfc_outmbox_generic), GFP_ATOMIC); - if (!cfg_login_sts) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]malloc outmbox memory failed"); - return UNF_RETURN_ERROR; - } - memset(cfg_login_sts, 0, sizeof(union spfc_outmbox_generic)); - - config_login.header.cmnd_type = SPFC_MBOX_CONFIG_LOGIN_API; - config_login.header.length = SPFC_BYTES_TO_DW_NUM(sizeof(struct spfc_inmbox_config_login)); - config_login.header.port_id = hba->port_index; - - config_login.op_code = UNDEFINEOPCODE; - - config_login.tx_bb_credit = hba->remote_bb_credit; - - config_login.etov = hba->compared_edtov_val; - config_login.rtov = hba->compared_ratov_val; - - config_login.rt_tov_tag = hba->remote_rttov_tag; - config_login.ed_tov_tag = hba->remote_edtov_tag; - config_login.bb_credit = hba->remote_bb_credit; - config_login.bb_scn = SPFC_LSB(hba->compared_bb_scn); - - if (config_login.bb_scn) { - config_login.lr_flag = (login_parms->els_cmnd_code == ELS_PLOGI) ? 0 : 1; - ret = spfc_mb_send_and_wait_mbox(hba, &config_login, sizeof(config_login), - (union spfc_outmbox_generic *)cfg_login_sts); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Port(0x%x) SPFC can't send and wait mailbox, command type: 0x%x.", - hba->port_cfg.port_id, config_login.header.cmnd_type); - - goto exit; - } - - if (cfg_login_sts->config_login_sts.header.cmnd_type != - SPFC_MBOX_CONFIG_LOGIN_API_STS) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_INFO, - "Port(0x%x) Receive mailbox type incorrect. Type: 0x%x.", - hba->port_cfg.port_id, - cfg_login_sts->config_login_sts.header.cmnd_type); - - goto exit; - } - - if (cfg_login_sts->config_login_sts.status != STATUS_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "Port(0x%x) Receive mailbox type(0x%x) status incorrect. Status: 0x%x.", - hba->port_cfg.port_id, - cfg_login_sts->config_login_sts.header.cmnd_type, - cfg_login_sts->config_login_sts.status); - - goto exit; - } - } else { - iret = sphw_msg_to_mgmt_async(hba->dev_handle, COMM_MOD_FC, - SPFC_MBOX_CONFIG_LOGIN_API, &config_login, - sizeof(config_login), SPHW_CHANNEL_FC); - - if (iret != 0) { - SPFC_MAILBOX_STAT(hba, SPFC_SEND_CONFIG_LOGINAPI_FAIL); - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Port(0x%x) spfc can't send config login cmd to up,ret:%d.", - hba->port_cfg.port_id, iret); - - goto exit; - } - - SPFC_MAILBOX_STAT(hba, SPFC_SEND_CONFIG_LOGINAPI); - } - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "Port(0x%x) Topo(0x%x) Config login param to up: txbbcredit(0x%x), BB_SC_N(0x%x).", - hba->port_cfg.port_id, hba->active_topo, - config_login.tx_bb_credit, config_login.bb_scn); - - ret = RETURN_OK; -exit: - kfree(cfg_login_sts); - - return ret; -} - -u32 spfc_mb_send_and_wait_mbox(struct spfc_hba_info *hba, const void *in_mbox, - u16 in_size, - union spfc_outmbox_generic *out_mbox) -{ - void *handle = NULL; - u16 out_size = 0; - ulong time_out = 0; - int ret = 0; - struct spfc_mbox_header *header = NULL; - - FC_CHECK_RETURN_VALUE(hba, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(in_mbox, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(out_mbox, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(hba->dev_handle, UNF_RETURN_ERROR); - header = (struct spfc_mbox_header *)in_mbox; - out_size = sizeof(union spfc_outmbox_generic); - handle = hba->dev_handle; - header->port_id = (u8)sphw_global_func_id(handle); - - /* Wait for las mailbox completion: */ - time_out = wait_for_completion_timeout(&hba->mbox_complete, - (ulong)msecs_to_jiffies(SPFC_MBOX_TIME_SEC_MAX * - UNF_S_TO_MS)); - if (time_out == SPFC_ZERO) { - FC_DRV_PRINT(UNF_LOG_EQUIP_ATT, UNF_ERR, - "[err]Port(0x%x) wait mailbox(0x%x) completion timeout: %d sec", - hba->port_cfg.port_id, header->cmnd_type, - SPFC_MBOX_TIME_SEC_MAX); - - return UNF_RETURN_ERROR; - } - - /* Send Msg to uP Sync: timer 10s */ - ret = sphw_msg_to_mgmt_sync(handle, COMM_MOD_FC, header->cmnd_type, - (void *)in_mbox, in_size, - (union spfc_outmbox_generic *)out_mbox, - &out_size, (SPFC_MBX_MAX_TIMEOUT), - SPHW_CHANNEL_FC); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[warn]Port(0x%x) can not send mailbox(0x%x) with ret:%d", - hba->port_cfg.port_id, header->cmnd_type, ret); - - complete(&hba->mbox_complete); - return UNF_RETURN_ERROR; - } - - complete(&hba->mbox_complete); - - return RETURN_OK; -} - -void spfc_initial_dynamic_info(struct spfc_hba_info *fc_port) -{ - struct spfc_hba_info *hba = fc_port; - ulong flag = 0; - - FC_CHECK_RETURN_VOID(hba); - - spin_lock_irqsave(&hba->hba_lock, flag); - hba->active_port_speed = UNF_PORT_SPEED_UNKNOWN; - hba->active_topo = UNF_ACT_TOP_UNKNOWN; - hba->phy_link = UNF_PORT_LINK_DOWN; - hba->queue_set_stage = SPFC_QUEUE_SET_STAGE_INIT; - hba->loop_map_valid = LOOP_MAP_INVALID; - hba->srq_delay_info.srq_delay_flag = 0; - hba->srq_delay_info.root_rq_rcvd_flag = 0; - spin_unlock_irqrestore(&hba->hba_lock, flag); -} - -static u32 spfc_recv_fc_linkup(struct spfc_hba_info *hba, void *buf_in) -{ -#define SPFC_LOOP_MASK 0x1 -#define SPFC_LOOPMAP_COUNT 128 - - u32 ret = UNF_RETURN_ERROR; - struct spfc_link_event *link_event = NULL; - - link_event = (struct spfc_link_event *)buf_in; - hba->phy_link = UNF_PORT_LINK_UP; - hba->active_port_speed = link_event->speed; - hba->led_states.green_speed_led = (u8)(link_event->green_speed_led); - hba->led_states.yellow_speed_led = (u8)(link_event->yellow_speed_led); - hba->led_states.ac_led = (u8)(link_event->ac_led); - - if (link_event->top_type == SPFC_LOOP_MASK && - (link_event->loop_map_info[ARRAY_INDEX_1] == UNF_FL_PORT_LOOP_ADDR || - link_event->loop_map_info[ARRAY_INDEX_2] == UNF_FL_PORT_LOOP_ADDR)) { - hba->active_topo = UNF_ACT_TOP_PUBLIC_LOOP; /* Public Loop */ - hba->active_alpa = link_event->alpa_value; /* AL_PA */ - memcpy(hba->loop_map, link_event->loop_map_info, SPFC_LOOPMAP_COUNT); - hba->loop_map_valid = LOOP_MAP_VALID; - } else if (link_event->top_type == SPFC_LOOP_MASK) { - hba->active_topo = UNF_ACT_TOP_PRIVATE_LOOP; /* Private Loop */ - hba->active_alpa = link_event->alpa_value; /* AL_PA */ - memcpy(hba->loop_map, link_event->loop_map_info, SPFC_LOOPMAP_COUNT); - hba->loop_map_valid = LOOP_MAP_VALID; - } else { - hba->active_topo = UNF_TOP_P2P_MASK; /* P2P_D or P2P_F */ - } - - FC_DRV_PRINT(UNF_LOG_EVENT, UNF_KEVENT, - "[event]Port(0x%x) receive link up event(0x%x) with speed(0x%x) uP_topo(0x%x) driver_topo(0x%x)", - hba->port_cfg.port_id, link_event->link_event, - link_event->speed, link_event->top_type, hba->active_topo); - - /* Set clear & flush state */ - spfc_set_hba_clear_state(hba, false); - spfc_set_hba_flush_state(hba, false); - spfc_set_rport_flush_state(hba, false); - - /* Report link up event to COM */ - UNF_LOWLEVEL_PORT_EVENT(ret, hba->lport, UNF_PORT_LINK_UP, - &hba->active_port_speed); - - SPFC_LINK_EVENT_STAT(hba, SPFC_LINK_UP_COUNT); - - return ret; -} - -static u32 spfc_recv_fc_linkdown(struct spfc_hba_info *hba, void *buf_in) -{ - u32 ret = UNF_RETURN_ERROR; - struct spfc_link_event *link_event = NULL; - - link_event = (struct spfc_link_event *)buf_in; - - /* 1. Led state setting */ - hba->led_states.green_speed_led = (u8)(link_event->green_speed_led); - hba->led_states.yellow_speed_led = (u8)(link_event->yellow_speed_led); - hba->led_states.ac_led = (u8)(link_event->ac_led); - - FC_DRV_PRINT(UNF_LOG_EVENT, UNF_KEVENT, - "[event]Port(0x%x) receive link down event(0x%x) reason(0x%x)", - hba->port_cfg.port_id, link_event->link_event, link_event->reason); - - spfc_initial_dynamic_info(hba); - - /* 2. set HBA flush state */ - spfc_set_hba_flush_state(hba, true); - - /* 3. set R_Port (parent SQ) flush state */ - spfc_set_rport_flush_state(hba, true); - - /* 4. Report link down event to COM */ - UNF_LOWLEVEL_PORT_EVENT(ret, hba->lport, UNF_PORT_LINK_DOWN, 0); - - /* DFX setting */ - SPFC_LINK_REASON_STAT(hba, link_event->reason); - SPFC_LINK_EVENT_STAT(hba, SPFC_LINK_DOWN_COUNT); - - return ret; -} - -static u32 spfc_recv_fc_delcmd(struct spfc_hba_info *hba, void *buf_in) -{ - u32 ret = UNF_RETURN_ERROR; - struct spfc_link_event *link_event = NULL; - - link_event = (struct spfc_link_event *)buf_in; - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_KEVENT, - "[event]Port(0x%x) receive delete cmd event(0x%x)", - hba->port_cfg.port_id, link_event->link_event); - - /* Send buffer clear cmnd */ - ret = spfc_clear_fetched_sq_wqe(hba); - - hba->queue_set_stage = SPFC_QUEUE_SET_STAGE_SCANNING; - SPFC_LINK_EVENT_STAT(hba, SPFC_FC_DELETE_CMND_COUNT); - - return ret; -} - -static u32 spfc_recv_fc_error(struct spfc_hba_info *hba, void *buf_in) -{ -#define FC_ERR_LEVEL_DEAD 0 -#define FC_ERR_LEVEL_HIGH 1 -#define FC_ERR_LEVEL_LOW 2 - - u32 ret = UNF_RETURN_ERROR; - struct spfc_up_error_event *up_error_event = NULL; - - up_error_event = (struct spfc_up_error_event *)buf_in; - if (up_error_event->error_type >= SPFC_UP_ERR_BUTT || - up_error_event->error_value >= SPFC_ERR_VALUE_BUTT) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "Port(0x%x) receive a unsupported UP Error Event Type(0x%x) Value(0x%x).", - hba->port_cfg.port_id, up_error_event->error_type, - up_error_event->error_value); - return ret; - } - - switch (up_error_event->error_level) { - case FC_ERR_LEVEL_DEAD: - ret = RETURN_OK; - break; - - case FC_ERR_LEVEL_HIGH: - /* port reset */ - UNF_LOWLEVEL_PORT_EVENT(ret, hba->lport, - UNF_PORT_ABNORMAL_RESET, NULL); - break; - - case FC_ERR_LEVEL_LOW: - ret = RETURN_OK; - break; - - default: - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "Port(0x%x) receive a unsupported UP Error Event Level(0x%x), Can not Process.", - hba->port_cfg.port_id, - up_error_event->error_level); - return ret; - } - if (up_error_event->error_value < SPFC_ERR_VALUE_BUTT) - SPFC_UP_ERR_EVENT_STAT(hba, up_error_event->error_value); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_KEVENT, - "[event]Port(0x%x) process UP Error Event Level(0x%x) Type(0x%x) Value(0x%x) %s.", - hba->port_cfg.port_id, up_error_event->error_level, - up_error_event->error_type, up_error_event->error_value, - (ret == UNF_RETURN_ERROR) ? "ERROR" : "OK"); - - return ret; -} - -static struct spfc_up2drv_msg_handle up_msg_handle[] = { - {SPFC_MBOX_RECV_FC_LINKUP, spfc_recv_fc_linkup}, - {SPFC_MBOX_RECV_FC_LINKDOWN, spfc_recv_fc_linkdown}, - {SPFC_MBOX_RECV_FC_DELCMD, spfc_recv_fc_delcmd}, - {SPFC_MBOX_RECV_FC_ERROR, spfc_recv_fc_error} -}; - -void spfc_up_msg2driver_proc(void *hwdev_handle, void *pri_handle, u16 cmd, - void *buf_in, u16 in_size, void *buf_out, - u16 *out_size) -{ - u32 ret = UNF_RETURN_ERROR; - u32 index = 0; - struct spfc_hba_info *hba = NULL; - struct spfc_mbox_header *mbx_header = NULL; - - FC_CHECK_RETURN_VOID(hwdev_handle); - FC_CHECK_RETURN_VOID(pri_handle); - FC_CHECK_RETURN_VOID(buf_in); - FC_CHECK_RETURN_VOID(buf_out); - FC_CHECK_RETURN_VOID(out_size); - - hba = (struct spfc_hba_info *)pri_handle; - if (!hba) { - FC_DRV_PRINT(UNF_LOG_EVENT, UNF_ERR, "[err]Hba is null"); - return; - } - - mbx_header = (struct spfc_mbox_header *)buf_in; - if (mbx_header->cmnd_type != cmd) { - *out_size = sizeof(struct spfc_link_event); - FC_DRV_PRINT(UNF_LOG_EVENT, UNF_ERR, - "[err]Port(0x%x) cmd(0x%x) is not matched with header cmd type(0x%x)", - hba->port_cfg.port_id, cmd, mbx_header->cmnd_type); - return; - } - - while (index < (sizeof(up_msg_handle) / sizeof(struct spfc_up2drv_msg_handle))) { - if (up_msg_handle[index].cmd == cmd && - up_msg_handle[index].spfc_msg_up2driver_handler) { - ret = up_msg_handle[index].spfc_msg_up2driver_handler(hba, buf_in); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_EVENT, UNF_ERR, - "[warn]Port(0x%x) process up cmd(0x%x) failed", - hba->port_cfg.port_id, cmd); - } - *out_size = sizeof(struct spfc_link_event); - return; - } - index++; - } - - *out_size = sizeof(struct spfc_link_event); - - FC_DRV_PRINT(UNF_LOG_EVENT, UNF_ERR, - "[err]Port(0x%x) process up cmd(0x%x) failed", - hba->port_cfg.port_id, cmd); -} - -u32 spfc_get_topo_act(void *hba, void *topo_act) -{ - struct spfc_hba_info *spfc_hba = hba; - enum unf_act_topo *pen_topo_act = topo_act; - - FC_CHECK_RETURN_VALUE(hba, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(topo_act, UNF_RETURN_ERROR); - - /* Get topo from low_level */ - *pen_topo_act = spfc_hba->active_topo; - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]Get active topology: 0x%x", *pen_topo_act); - - return RETURN_OK; -} - -u32 spfc_get_loop_alpa(void *hba, void *alpa) -{ - ulong flags = 0; - struct spfc_hba_info *spfc_hba = hba; - u8 *alpa_temp = alpa; - - FC_CHECK_RETURN_VALUE(spfc_hba, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(alpa, UNF_RETURN_ERROR); - - spin_lock_irqsave(&spfc_hba->hba_lock, flags); - *alpa_temp = spfc_hba->active_alpa; - spin_unlock_irqrestore(&spfc_hba->hba_lock, flags); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_INFO, - "[info]Get active AL_PA(0x%x)", *alpa_temp); - - return RETURN_OK; -} - -static void spfc_get_fabric_login_params(struct spfc_hba_info *hba, - struct unf_port_login_parms *params_addr) -{ - ulong flag = 0; - - spin_lock_irqsave(&hba->hba_lock, flag); - hba->active_topo = params_addr->act_topo; - hba->compared_ratov_val = params_addr->compared_ratov_val; - hba->compared_edtov_val = params_addr->compared_edtov_val; - hba->compared_bb_scn = params_addr->compared_bbscn; - hba->remote_edtov_tag = params_addr->remote_edtov_tag; - hba->remote_rttov_tag = params_addr->remote_rttov_tag; - hba->remote_bb_credit = params_addr->remote_bb_credit; - spin_unlock_irqrestore(&hba->hba_lock, flag); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "[info]Port(0x%x) topo(0x%x) get fabric params: R_A_TOV(0x%x) E_D_TOV(%u) BB_CREDIT(0x%x) BB_SC_N(0x%x)", - hba->port_cfg.port_id, hba->active_topo, - hba->compared_ratov_val, hba->compared_edtov_val, - hba->remote_bb_credit, hba->compared_bb_scn); -} - -static void spfc_get_port_login_params(struct spfc_hba_info *hba, - struct unf_port_login_parms *params_addr) -{ - ulong flag = 0; - - spin_lock_irqsave(&hba->hba_lock, flag); - hba->compared_ratov_val = params_addr->compared_ratov_val; - hba->compared_edtov_val = params_addr->compared_edtov_val; - hba->compared_bb_scn = params_addr->compared_bbscn; - hba->remote_edtov_tag = params_addr->remote_edtov_tag; - hba->remote_rttov_tag = params_addr->remote_rttov_tag; - hba->remote_bb_credit = params_addr->remote_bb_credit; - spin_unlock_irqrestore(&hba->hba_lock, flag); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "Port(0x%x) Topo(0x%x) Get Port Params: R_A_TOV(0x%x), E_D_TOV(0x%x), BB_CREDIT(0x%x), BB_SC_N(0x%x).", - hba->port_cfg.port_id, hba->active_topo, - hba->compared_ratov_val, hba->compared_edtov_val, - hba->remote_bb_credit, hba->compared_bb_scn); -} - -u32 spfc_update_fabric_param(void *hba, void *para_in) -{ - u32 ret = RETURN_OK; - struct spfc_hba_info *spfc_hba = hba; - struct unf_port_login_parms *login_coparms = para_in; - - FC_CHECK_RETURN_VALUE(spfc_hba, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(para_in, UNF_RETURN_ERROR); - - spfc_get_fabric_login_params(spfc_hba, login_coparms); - - if (spfc_hba->active_topo == UNF_ACT_TOP_P2P_FABRIC || - spfc_hba->active_topo == UNF_ACT_TOP_PUBLIC_LOOP) { - if (spfc_hba->work_mode == SPFC_SMARTIO_WORK_MODE_FC) - ret = spfc_config_login_api(spfc_hba, login_coparms); - } - - return ret; -} - -u32 spfc_update_port_param(void *hba, void *para_in) -{ - u32 ret = RETURN_OK; - struct spfc_hba_info *spfc_hba = hba; - struct unf_port_login_parms *login_coparms = - (struct unf_port_login_parms *)para_in; - - FC_CHECK_RETURN_VALUE(spfc_hba, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(para_in, UNF_RETURN_ERROR); - - if (spfc_hba->active_topo == UNF_ACT_TOP_PRIVATE_LOOP || - spfc_hba->active_topo == UNF_ACT_TOP_P2P_DIRECT) { - spfc_get_port_login_params(spfc_hba, login_coparms); - ret = spfc_config_login_api(spfc_hba, login_coparms); - } - - spfc_save_login_parms_in_sq_info(spfc_hba, login_coparms); - - return ret; -} - -u32 spfc_get_workable_bb_credit(void *hba, void *bb_credit) -{ - u32 *bb_credit_temp = (u32 *)bb_credit; - struct spfc_hba_info *spfc_hba = hba; - - FC_CHECK_RETURN_VALUE(spfc_hba, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(bb_credit, UNF_RETURN_ERROR); - if (spfc_hba->active_port_speed == UNF_PORT_SPEED_32_G) - *bb_credit_temp = SPFC_LOWLEVEL_DEFAULT_32G_BB_CREDIT; - else if (spfc_hba->active_port_speed == UNF_PORT_SPEED_16_G) - *bb_credit_temp = SPFC_LOWLEVEL_DEFAULT_16G_BB_CREDIT; - else - *bb_credit_temp = SPFC_LOWLEVEL_DEFAULT_8G_BB_CREDIT; - - return RETURN_OK; -} - -u32 spfc_get_workable_bb_scn(void *hba, void *bb_scn) -{ - u32 *bb_scn_temp = (u32 *)bb_scn; - struct spfc_hba_info *spfc_hba = (struct spfc_hba_info *)hba; - - FC_CHECK_RETURN_VALUE(hba, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(bb_scn, UNF_RETURN_ERROR); - - *bb_scn_temp = spfc_hba->port_bb_scn_cfg; - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_INFO, - "Return BBSCN(0x%x) to CM", *bb_scn_temp); - - return RETURN_OK; -} - -u32 spfc_get_loop_map(void *hba, void *buf) -{ - ulong flags = 0; - struct unf_buf *buf_temp = (struct unf_buf *)buf; - struct spfc_hba_info *spfc_hba = hba; - - FC_CHECK_RETURN_VALUE(spfc_hba, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(buf_temp, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(buf_temp->buf, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(buf_temp->buf_len, UNF_RETURN_ERROR); - - if (buf_temp->buf_len > UNF_LOOPMAP_COUNT) - return UNF_RETURN_ERROR; - - spin_lock_irqsave(&spfc_hba->hba_lock, flags); - if (spfc_hba->loop_map_valid != LOOP_MAP_VALID) { - spin_unlock_irqrestore(&spfc_hba->hba_lock, flags); - return UNF_RETURN_ERROR; - } - memcpy(buf_temp->buf, spfc_hba->loop_map, buf_temp->buf_len); - spin_unlock_irqrestore(&spfc_hba->hba_lock, flags); - - return RETURN_OK; -} - -u32 spfc_mb_reset_chip(struct spfc_hba_info *hba, u8 sub_type) -{ - struct spfc_inmbox_port_reset port_reset; - union spfc_outmbox_generic *port_reset_sts = NULL; - u32 ret = UNF_RETURN_ERROR; - - FC_CHECK_RETURN_VALUE(hba, UNF_RETURN_ERROR); - - memset(&port_reset, 0, sizeof(port_reset)); - - port_reset_sts = kmalloc(sizeof(union spfc_outmbox_generic), GFP_ATOMIC); - if (!port_reset_sts) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "malloc outmbox memory failed"); - return UNF_RETURN_ERROR; - } - memset(port_reset_sts, 0, sizeof(union spfc_outmbox_generic)); - port_reset.header.cmnd_type = SPFC_MBOX_PORT_RESET; - port_reset.header.length = SPFC_BYTES_TO_DW_NUM(sizeof(struct spfc_inmbox_port_reset)); - port_reset.op_code = sub_type; - - if (spfc_mb_send_and_wait_mbox(hba, &port_reset, sizeof(port_reset), - port_reset_sts) != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[warn]Port(0x%x) can't send and wait mailbox with command type(0x%x)", - hba->port_cfg.port_id, port_reset.header.cmnd_type); - - goto exit; - } - - if (port_reset_sts->port_reset_sts.status != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_EQUIP_ATT, UNF_ERR, - "[warn]Port(0x%x) receive mailbox type(0x%x) status(0x%x) incorrect", - hba->port_cfg.port_id, - port_reset_sts->port_reset_sts.header.cmnd_type, - port_reset_sts->port_reset_sts.status); - - goto exit; - } - - if (port_reset_sts->port_reset_sts.header.cmnd_type != SPFC_MBOX_PORT_RESET_STS) { - FC_DRV_PRINT(UNF_LOG_EQUIP_ATT, UNF_ERR, - "[warn]Port(0x%x) recv mailbox type(0x%x) incorrect", - hba->port_cfg.port_id, - port_reset_sts->port_reset_sts.header.cmnd_type); - - goto exit; - } - - FC_DRV_PRINT(UNF_LOG_EQUIP_ATT, UNF_MAJOR, - "[info]Port(0x%x) reset chip mailbox success", - hba->port_cfg.port_id); - - ret = RETURN_OK; -exit: - kfree(port_reset_sts); - - return ret; -} - -u32 spfc_clear_sq_wqe_done(struct spfc_hba_info *hba) -{ - int ret1 = RETURN_OK; - u32 ret2 = RETURN_OK; - struct spfc_inmbox_clear_done clear_done; - - clear_done.header.cmnd_type = SPFC_MBOX_BUFFER_CLEAR_DONE; - clear_done.header.length = SPFC_BYTES_TO_DW_NUM(sizeof(struct spfc_inmbox_clear_done)); - clear_done.header.port_id = hba->port_index; - - ret1 = sphw_msg_to_mgmt_async(hba->dev_handle, COMM_MOD_FC, - SPFC_MBOX_BUFFER_CLEAR_DONE, &clear_done, - sizeof(clear_done), SPHW_CHANNEL_FC); - - if (ret1 != 0) { - SPFC_MAILBOX_STAT(hba, SPFC_SEND_CLEAR_DONE_FAIL); - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]SPFC Port(0x%x) can't send clear done cmd to up, ret:%d", - hba->port_cfg.port_id, ret1); - - return UNF_RETURN_ERROR; - } - - SPFC_MAILBOX_STAT(hba, SPFC_SEND_CLEAR_DONE); - hba->queue_set_stage = SPFC_QUEUE_SET_STAGE_FLUSHDONE; - hba->next_clear_sq = 0; - - FC_DRV_PRINT(UNF_LOG_EVENT, UNF_KEVENT, - "[info]Port(0x%x) clear done msg(0x%x) sent to up succeed with stage(0x%x)", - hba->port_cfg.port_id, clear_done.header.cmnd_type, - hba->queue_set_stage); - - return ret2; -} - -u32 spfc_mbx_get_fw_clear_stat(struct spfc_hba_info *hba, u32 *clear_state) -{ - struct spfc_inmbox_get_clear_state get_clr_state; - union spfc_outmbox_generic *port_clear_state_sts = NULL; - u32 ret = UNF_RETURN_ERROR; - - FC_CHECK_RETURN_VALUE(hba, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(clear_state, UNF_RETURN_ERROR); - - memset(&get_clr_state, 0, sizeof(get_clr_state)); - - port_clear_state_sts = kmalloc(sizeof(union spfc_outmbox_generic), GFP_ATOMIC); - if (!port_clear_state_sts) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "malloc outmbox memory failed"); - return UNF_RETURN_ERROR; - } - memset(port_clear_state_sts, 0, sizeof(union spfc_outmbox_generic)); - - get_clr_state.header.cmnd_type = SPFC_MBOX_GET_CLEAR_STATE; - get_clr_state.header.length = - SPFC_BYTES_TO_DW_NUM(sizeof(struct spfc_inmbox_get_clear_state)); - - if (spfc_mb_send_and_wait_mbox(hba, &get_clr_state, sizeof(get_clr_state), - port_clear_state_sts) != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "spfc can't send and wait mailbox, command type: 0x%x", - get_clr_state.header.cmnd_type); - - goto exit; - } - - if (port_clear_state_sts->get_clr_state_sts.status != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_EQUIP_ATT, UNF_ERR, - "Port(0x%x) Receive mailbox type(0x%x) status incorrect. Status: 0x%x, state 0x%x.", - hba->port_cfg.port_id, - port_clear_state_sts->get_clr_state_sts.header.cmnd_type, - port_clear_state_sts->get_clr_state_sts.status, - port_clear_state_sts->get_clr_state_sts.state); - - goto exit; - } - - if (port_clear_state_sts->get_clr_state_sts.header.cmnd_type != - SPFC_MBOX_GET_CLEAR_STATE_STS) { - FC_DRV_PRINT(UNF_LOG_EQUIP_ATT, UNF_ERR, - "Port(0x%x) recv mailbox type(0x%x) incorrect.", - hba->port_cfg.port_id, - port_clear_state_sts->get_clr_state_sts.header.cmnd_type); - - goto exit; - } - - FC_DRV_PRINT(UNF_LOG_EVENT, UNF_MAJOR, - "Port(0x%x) get port clear state 0x%x.", - hba->port_cfg.port_id, - port_clear_state_sts->get_clr_state_sts.state); - - *clear_state = port_clear_state_sts->get_clr_state_sts.state; - - ret = RETURN_OK; -exit: - kfree(port_clear_state_sts); - - return ret; -} - -u32 spfc_mbx_config_default_session(void *hba, u32 flag) -{ - struct spfc_hba_info *spfc_hba = NULL; - struct spfc_inmbox_default_sq_info default_sq_info; - union spfc_outmbox_generic default_sq_info_sts; - u32 ret = UNF_RETURN_ERROR; - - FC_CHECK_RETURN_VALUE(hba, UNF_RETURN_ERROR); - - spfc_hba = (struct spfc_hba_info *)hba; - - memset(&default_sq_info, 0, sizeof(struct spfc_inmbox_default_sq_info)); - memset(&default_sq_info_sts, 0, sizeof(union spfc_outmbox_generic)); - - default_sq_info.header.cmnd_type = SPFC_MBOX_SEND_DEFAULT_SQ_INFO; - default_sq_info.header.length = - SPFC_BYTES_TO_DW_NUM(sizeof(struct spfc_inmbox_default_sq_info)); - default_sq_info.func_id = sphw_global_func_id(spfc_hba->dev_handle); - - /* When flag is 1, set default SQ info when probe, when 0, clear when - * remove - */ - if (flag) { - default_sq_info.sq_cid = spfc_hba->default_sq_info.sq_cid; - default_sq_info.sq_xid = spfc_hba->default_sq_info.sq_xid; - default_sq_info.valid = 1; - } - - ret = - spfc_mb_send_and_wait_mbox(spfc_hba, &default_sq_info, sizeof(default_sq_info), - (union spfc_outmbox_generic *)(void *)&default_sq_info_sts); - - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "spfc can't send and wait mailbox, command type: 0x%x.", - default_sq_info.header.cmnd_type); - - return UNF_RETURN_ERROR; - } - - if (default_sq_info_sts.default_sq_sts.status != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "Port(0x%x) mailbox status incorrect status(0x%x) .", - spfc_hba->port_cfg.port_id, - default_sq_info_sts.default_sq_sts.status); - - return UNF_RETURN_ERROR; - } - - if (SPFC_MBOX_SEND_DEFAULT_SQ_INFO_STS != - default_sq_info_sts.default_sq_sts.header.cmnd_type) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "Port(0x%x) receive mailbox type incorrect type: 0x%x.", - spfc_hba->port_cfg.port_id, - default_sq_info_sts.default_sq_sts.header.cmnd_type); - - return UNF_RETURN_ERROR; - } - - return RETURN_OK; -} diff --git a/drivers/scsi/spfc/hw/spfc_chipitf.h b/drivers/scsi/spfc/hw/spfc_chipitf.h deleted file mode 100644 index acd770514edf..000000000000 --- a/drivers/scsi/spfc/hw/spfc_chipitf.h +++ /dev/null @@ -1,797 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPFC_CHIPITF_H -#define SPFC_CHIPITF_H - -#include "unf_type.h" -#include "unf_log.h" -#include "spfc_utils.h" -#include "spfc_module.h" - -#include "spfc_service.h" - -/* CONF_API_CMND */ -#define SPFC_MBOX_CONFIG_API (0x00) -#define SPFC_MBOX_CONFIG_API_STS (0xA0) - -/* GET_CHIP_INFO_API_CMD */ -#define SPFC_MBOX_GET_CHIP_INFO (0x01) -#define SPFC_MBOX_GET_CHIP_INFO_STS (0xA1) - -/* PORT_RESET */ -#define SPFC_MBOX_PORT_RESET (0x02) -#define SPFC_MBOX_PORT_RESET_STS (0xA2) - -/* SFP_SWITCH_API_CMND */ -#define SPFC_MBOX_PORT_SWITCH (0x03) -#define SPFC_MBOX_PORT_SWITCH_STS (0xA3) - -/* CONF_AF_LOGIN_API_CMND */ -#define SPFC_MBOX_CONFIG_LOGIN_API (0x06) -#define SPFC_MBOX_CONFIG_LOGIN_API_STS (0xA6) - -/* BUFFER_CLEAR_DONE_CMND */ -#define SPFC_MBOX_BUFFER_CLEAR_DONE (0x07) -#define SPFC_MBOX_BUFFER_CLEAR_DONE_STS (0xA7) - -#define SPFC_MBOX_GET_UP_STATE (0x09) -#define SPFC_MBOX_GET_UP_STATE_STS (0xA9) - -/* GET CLEAR DONE STATE */ -#define SPFC_MBOX_GET_CLEAR_STATE (0x0E) -#define SPFC_MBOX_GET_CLEAR_STATE_STS (0xAE) - -/* CONFIG TIMER */ -#define SPFC_MBOX_CONFIG_TIMER (0x10) -#define SPFC_MBOX_CONFIG_TIMER_STS (0xB0) - -/* Led Test */ -#define SPFC_MBOX_LED_TEST (0x12) -#define SPFC_MBOX_LED_TEST_STS (0xB2) - -/* set esch */ -#define SPFC_MBOX_SET_ESCH (0x13) -#define SPFC_MBOX_SET_ESCH_STS (0xB3) - -/* set get tx serdes */ -#define SPFC_MBOX_SET_GET_SERDES_TX (0x14) -#define SPFC_MBOX_SET_GET_SERDES_TX_STS (0xB4) - -/* get rx serdes */ -#define SPFC_MBOX_GET_SERDES_RX (0x15) -#define SPFC_MBOX_GET_SERDES_RX_STS (0xB5) - -/* i2c read write */ -#define SPFC_MBOX_I2C_WR_RD (0x16) -#define SPFC_MBOX_I2C_WR_RD_STS (0xB6) - -/* GET UCODE STATS CMD */ -#define SPFC_MBOX_GET_UCODE_STAT (0x18) -#define SPFC_MBOX_GET_UCODE_STAT_STS (0xB8) - -/* gpio read write */ -#define SPFC_MBOX_GPIO_WR_RD (0x19) -#define SPFC_MBOX_GPIO_WR_RD_STS (0xB9) - -#define SPFC_MBOX_SEND_DEFAULT_SQ_INFO (0x26) -#define SPFC_MBOX_SEND_DEFAULT_SQ_INFO_STS (0xc6) - -/* FC: DRV->UP */ -#define SPFC_MBOX_SEND_ELS_CMD (0x2A) -#define SPFC_MBOX_SEND_VPORT_INFO (0x2B) - -/* FC: UP->DRV */ -#define SPFC_MBOX_RECV_FC_LINKUP (0x40) -#define SPFC_MBOX_RECV_FC_LINKDOWN (0x41) -#define SPFC_MBOX_RECV_FC_DELCMD (0x42) -#define SPFC_MBOX_RECV_FC_ERROR (0x43) - -#define LOOP_MAP_VALID (1) -#define LOOP_MAP_INVALID (0) - -#define SPFC_MBOX_SIZE (1024) -#define SPFC_MBOX_HEADER_SIZE (4) - -#define UNDEFINEOPCODE (0) - -#define VALUEMASK_L 0x00000000FFFFFFFF -#define VALUEMASK_H 0xFFFFFFFF00000000 - -#define STATUS_OK (0) -#define STATUS_FAIL (1) - -enum spfc_drv2up_unblock_msg_cmd_code { - SPFC_SEND_ELS_CMD, - SPFC_SEND_ELS_CMD_FAIL, - SPFC_RCV_ELS_CMD_RSP, - SPFC_SEND_CONFIG_LOGINAPI, - SPFC_SEND_CONFIG_LOGINAPI_FAIL, - SPFC_RCV_CONFIG_LOGIN_API_RSP, - SPFC_SEND_CLEAR_DONE, - SPFC_SEND_CLEAR_DONE_FAIL, - SPFC_RCV_CLEAR_DONE_RSP, - SPFC_SEND_VPORT_INFO_DONE, - SPFC_SEND_VPORT_INFO_FAIL, - SPFC_SEND_VPORT_INFO_RSP, - SPFC_MBOX_CMD_BUTT -}; - -/* up to dirver cmd code */ -enum spfc_up2drv_msg_cmd_code { - SPFC_UP2DRV_MSG_CMD_LINKUP = 0x1, - SPFC_UP2DRV_MSG_CMD_LINKDOWN = 0x2, - SPFC_UP2DRV_MSG_CMD_BUTT -}; - -/* up to driver handle templete */ -struct spfc_up2drv_msg_handle { - u8 cmd; - u32 (*spfc_msg_up2driver_handler)(struct spfc_hba_info *hba, void *buf_in); -}; - -/* tile to driver cmd code */ -enum spfc_tile2drv_msg_cmd_code { - SPFC_TILE2DRV_MSG_CMD_SCAN_DONE, - SPFC_TILE2DRV_MSG_CMD_FLUSH_DONE, - SPFC_TILE2DRV_MSG_CMD_BUTT -}; - -/* tile to driver handle templete */ -struct spfc_tile2drv_msg_handle { - u8 cmd; - u32 (*spfc_msg_tile2driver_handler)(struct spfc_hba_info *hba, u8 cmd, u64 val); -}; - -/* Mbox Common Header */ -struct spfc_mbox_header { - u8 cmnd_type; - u8 length; - u8 port_id; - u8 reserved; -}; - -/* open or close the sfp */ -struct spfc_inmbox_port_switch { - struct spfc_mbox_header header; - u32 op_code : 8; - u32 rsvd0 : 24; - u32 rsvd1[6]; -}; - -struct spfc_inmbox_send_vport_info { - struct spfc_mbox_header header; - - u64 sys_port_wwn; - u64 sys_node_name; - - u32 nport_id : 24; - u32 vpi : 8; -}; - -struct spfc_outmbox_port_switch_sts { - struct spfc_mbox_header header; - - u16 reserved1; - u8 reserved2; - u8 status; -}; - -/* config API */ -struct spfc_inmbox_config_api { - struct spfc_mbox_header header; - - u32 op_code : 8; - u32 reserved1 : 24; - - u8 topy_mode; - u8 sfp_speed; - u8 max_speed; - u8 hard_alpa; - - u8 port_name[UNF_WWN_LEN]; - - u32 slave : 1; - u32 auto_sneg : 1; - u32 reserved2 : 30; - - u32 rx_6432g_bb_credit : 16; /* 160 */ - u32 rx_16g_bb_credit : 16; /* 80 */ - u32 rx_84g_bb_credit : 16; /* 50 */ - u32 rdy_cnt_bf_fst_frm : 16; /* 8 */ - - u32 esch_32g_value; - u32 esch_16g_value; - u32 esch_8g_value; - u32 esch_4g_value; - u32 esch_64g_value; - u32 esch_bust_size; -}; - -struct spfc_outmbox_config_api_sts { - struct spfc_mbox_header header; - u16 reserved1; - u8 reserved2; - u8 status; -}; - -/* Get chip info */ -struct spfc_inmbox_get_chip_info { - struct spfc_mbox_header header; -}; - -struct spfc_outmbox_get_chip_info_sts { - struct spfc_mbox_header header; - u8 status; - u8 board_type; - u8 rvsd0[2]; - u64 wwpn; - u64 wwnn; - u64 rsvd1; -}; - -/* Get reg info */ -struct spfc_inmbox_get_reg_info { - struct spfc_mbox_header header; - u32 op_code : 1; - u32 reg_len : 8; - u32 rsvd1 : 23; - u32 reg_addr; - u32 reg_value_l32; - u32 reg_value_h32; - u32 rsvd2[27]; -}; - -/* Get reg info sts */ -struct spfc_outmbox_get_reg_info_sts { - struct spfc_mbox_header header; - - u16 rsvd0; - u8 rsvd1; - u8 status; - u32 reg_value_l32; - u32 reg_value_h32; - u32 rsvd2[28]; -}; - -/* Config login API */ -struct spfc_inmbox_config_login { - struct spfc_mbox_header header; - - u32 op_code : 8; - u32 reserved1 : 24; - - u16 tx_bb_credit; - u16 reserved2; - - u32 rtov; - u32 etov; - - u32 rt_tov_tag : 1; - u32 ed_tov_tag : 1; - u32 bb_credit : 6; - u32 bb_scn : 8; - u32 lr_flag : 16; -}; - -struct spfc_outmbox_config_login_sts { - struct spfc_mbox_header header; - - u16 reserved1; - u8 reserved2; - u8 status; -}; - -/* port reset */ -#define SPFC_MBOX_SUBTYPE_LIGHT_RESET (0x0) -#define SPFC_MBOX_SUBTYPE_HEAVY_RESET (0x1) - -struct spfc_inmbox_port_reset { - struct spfc_mbox_header header; - - u32 op_code : 8; - u32 reserved : 24; -}; - -struct spfc_outmbox_port_reset_sts { - struct spfc_mbox_header header; - - u16 reserved1; - u8 reserved2; - u8 status; -}; - -/* led test */ -struct spfc_inmbox_led_test { - struct spfc_mbox_header header; - - /* 0->act type;1->low speed;1->high speed */ - u8 led_type; - /* 0:twinkle;1:light on;2:light off;0xff:defalut */ - u8 led_mode; - u8 resvd[ARRAY_INDEX_2]; -}; - -struct spfc_outmbox_led_test_sts { - struct spfc_mbox_header header; - - u16 rsvd1; - u8 rsvd2; - u8 status; -}; - -/* set esch */ -struct spfc_inmbox_set_esch { - struct spfc_mbox_header header; - - u32 esch_value; - u32 esch_bust_size; -}; - -struct spfc_outmbox_set_esch_sts { - struct spfc_mbox_header header; - - u16 rsvd1; - u8 rsvd2; - u8 status; -}; - -struct spfc_inmbox_set_serdes_tx { - struct spfc_mbox_header header; - - u8 swing; /* amplitude setting */ - char serdes_pre1; /* pre1 setting */ - char serdes_pre2; /* pre2 setting */ - char serdes_post; /* post setting */ - u8 serdes_main; /* main setting */ - u8 op_code; /* opcode,0:setting;1:read */ - u8 rsvd[ARRAY_INDEX_2]; -}; - -struct spfc_outmbox_set_serdes_tx_sts { - struct spfc_mbox_header header; - u16 rvsd0; - u8 rvsd1; - u8 status; - u8 swing; - char serdes_pre1; - char serdes_pre2; - char serdes_post; - u8 serdes_main; - u8 rsvd2[ARRAY_INDEX_3]; -}; - -struct spfc_inmbox_i2c_wr_rd { - struct spfc_mbox_header header; - u8 op_code; /* 0 write, 1 read */ - u8 rsvd[ARRAY_INDEX_3]; - - u32 dev_addr; - u32 offset; - u32 wr_data; -}; - -struct spfc_outmbox_i2c_wr_rd_sts { - struct spfc_mbox_header header; - u8 status; - u8 resvd[ARRAY_INDEX_3]; - - u32 rd_data; -}; - -struct spfc_inmbox_gpio_wr_rd { - struct spfc_mbox_header header; - u8 op_code; /* 0 write,1 read */ - u8 rsvd[ARRAY_INDEX_3]; - - u32 pin; - u32 wr_data; -}; - -struct spfc_outmbox_gpio_wr_rd_sts { - struct spfc_mbox_header header; - u8 status; - u8 resvd[ARRAY_INDEX_3]; - - u32 rd_data; -}; - -struct spfc_inmbox_get_serdes_rx { - struct spfc_mbox_header header; - - u8 op_code; - u8 h16_macro; - u8 h16_lane; - u8 rsvd; -}; - -struct spfc_inmbox_get_serdes_rx_sts { - struct spfc_mbox_header header; - u16 rvsd0; - u8 rvsd1; - u8 status; - int left_eye; - int right_eye; - int low_eye; - int high_eye; -}; - -struct spfc_ser_op_m_l { - u8 op_code; - u8 h16_macro; - u8 h16_lane; - u8 rsvd; -}; - -/* get sfp info */ -#define SPFC_MBOX_GET_SFP_INFO_MB_LENGTH 1 -#define OFFSET_TWO_DWORD 2 -#define OFFSET_ONE_DWORD 1 - -struct spfc_inmbox_get_sfp_info { - struct spfc_mbox_header header; -}; - -struct spfc_outmbox_get_sfp_info_sts { - struct spfc_mbox_header header; - - u32 rcvd : 8; - u32 length : 16; - u32 status : 8; -}; - -/* get ucode stats */ -#define SPFC_UCODE_STAT_NUM 64 - -struct spfc_outmbox_get_ucode_stat { - struct spfc_mbox_header header; -}; - -struct spfc_outmbox_get_ucode_stat_sts { - struct spfc_mbox_header header; - - u16 rsvd; - u8 rsvd2; - u8 status; - - u32 ucode_stat[SPFC_UCODE_STAT_NUM]; -}; - -/* uP-->Driver asyn event API */ -struct spfc_link_event { - struct spfc_mbox_header header; - - u8 link_event; - u8 reason; - u8 speed; - u8 top_type; - - u8 alpa_value; - u8 reserved1; - u16 paticpate : 1; - u16 ac_led : 1; - u16 yellow_speed_led : 1; - u16 green_speed_led : 1; - u16 reserved2 : 12; - - u8 loop_map_info[128]; -}; - -enum spfc_up_err_type { - SPFC_UP_ERR_DRV_PARA = 0, - SPFC_UP_ERR_SFP = 1, - SPFC_UP_ERR_32G_PUB = 2, - SPFC_UP_ERR_32G_UA = 3, - SPFC_UP_ERR_32G_MAC = 4, - SPFC_UP_ERR_NON32G_DFX = 5, - SPFC_UP_ERR_NON32G_MAC = 6, - SPFC_UP_ERR_BUTT - -}; - -enum spfc_up_err_value { - /* ERR type 0 */ - SPFC_DRV_2_UP_PARA_ERR = 0, - - /* ERR type 1 */ - SPFC_SFP_SPEED_ERR, - - /* ERR type 2 */ - SPFC_32GPUB_UA_RXESCH_FIFO_OF, - SPFC_32GPUB_UA_RXESCH_FIFO_UCERR, - - /* ERR type 3 */ - SPFC_32G_UA_UATX_LEN_ABN, - SPFC_32G_UA_RXAFIFO_OF, - SPFC_32G_UA_TXAFIFO_OF, - SPFC_32G_UA_RXAFIFO_UCERR, - SPFC_32G_UA_TXAFIFO_UCERR, - - /* ERR type 4 */ - SPFC_32G_MAC_RX_BBC_FATAL, - SPFC_32G_MAC_TX_BBC_FATAL, - SPFC_32G_MAC_TXFIFO_UF, - SPFC_32G_MAC_PCS_TXFIFO_UF, - SPFC_32G_MAC_RXBBC_CRDT_TO, - SPFC_32G_MAC_PCS_RXAFIFO_OF, - SPFC_32G_MAC_PCS_TXFIFO_OF, - SPFC_32G_MAC_FC2P_RXFIFO_OF, - SPFC_32G_MAC_FC2P_TXFIFO_OF, - SPFC_32G_MAC_FC2P_CAFIFO_OF, - SPFC_32G_MAC_PCS_RXRSFECM_UCEER, - SPFC_32G_MAC_PCS_RXAFIFO_UCEER, - SPFC_32G_MAC_PCS_TXFIFO_UCEER, - SPFC_32G_MAC_FC2P_RXFIFO_UCEER, - SPFC_32G_MAC_FC2P_TXFIFO_UCEER, - - /* ERR type 5 */ - SPFC_NON32G_DFX_FC1_DFX_BF_FIFO, - SPFC_NON32G_DFX_FC1_DFX_BP_FIFO, - SPFC_NON32G_DFX_FC1_DFX_RX_AFIFO_ERR, - SPFC_NON32G_DFX_FC1_DFX_TX_AFIFO_ERR, - SPFC_NON32G_DFX_FC1_DFX_DIRQ_RXBUF_FIFO1, - SPFC_NON32G_DFX_FC1_DFX_DIRQ_RXBBC_TO, - SPFC_NON32G_DFX_FC1_DFX_DIRQ_TXDAT_FIFO, - SPFC_NON32G_DFX_FC1_DFX_DIRQ_TXCMD_FIFO, - SPFC_NON32G_DFX_FC1_ERR_R_RDY, - - /* ERR type 6 */ - SPFC_NON32G_MAC_FC1_FAIRNESS_ERROR, - - SPFC_ERR_VALUE_BUTT - -}; - -struct spfc_up_error_event { - struct spfc_mbox_header header; - - u8 link_event; - u8 error_level; - u8 error_type; - u8 error_value; -}; - -struct spfc_inmbox_clear_done { - struct spfc_mbox_header header; -}; - -/* receive els cmd */ -struct spfc_inmbox_rcv_els { - struct spfc_mbox_header header; - u16 pkt_type; - u16 pkt_len; - u8 frame[ARRAY_INDEX_0]; -}; - -/* FCF event type */ -enum spfc_fcf_event_type { - SPFC_FCF_SELECTED = 0, - SPFC_FCF_DEAD, - SPFC_FCF_CLEAR_VLINK, - SPFC_FCF_CLEAR_VLINK_APPOINTED -}; - -struct spfc_nport_id_info { - u32 nport_id : 24; - u32 vp_index : 8; -}; - -struct spfc_inmbox_fcf_event { - struct spfc_mbox_header header; - - u8 fcf_map[ARRAY_INDEX_3]; - u8 event_type; - - u8 fcf_mac_h4[ARRAY_INDEX_4]; - - u16 vlan_info; - u8 fcf_mac_l2[ARRAY_INDEX_2]; - - struct spfc_nport_id_info nport_id_info[UNF_SPFC_MAXNPIV_NUM + 1]; -}; - -/* send els cmd */ -struct spfc_inmbox_send_els { - struct spfc_mbox_header header; - - u8 oper_code; - u8 rsvd[ARRAY_INDEX_3]; - - u8 resvd; - u8 els_cmd_type; - u16 pkt_len; - - u8 fcf_mac_h4[ARRAY_INDEX_4]; - - u16 vlan_info; - u8 fcf_mac_l2[ARRAY_INDEX_2]; - - u8 fc_frame[SPFC_FC_HEAD_LEN + UNF_FLOGI_PAYLOAD_LEN]; -}; - -struct spfc_inmbox_send_els_sts { - struct spfc_mbox_header header; - - u16 rx_id; - u16 err_code; - - u16 ox_id; - u16 rsvd; -}; - -struct spfc_inmbox_get_clear_state { - struct spfc_mbox_header header; - u32 resvd[31]; -}; - -struct spfc_outmbox_get_clear_state_sts { - struct spfc_mbox_header header; - u16 rsvd1; - u8 state; /* 1--clear doing. 0---clear done. */ - u8 status; /* 0--ok,!0---fail */ - u32 rsvd2[30]; -}; - -#define SPFC_FIP_MODE_VN2VF (0) -#define SPFC_FIP_MODE_VN2VN (1) - -/* get up state */ -struct spfc_inmbox_get_up_state { - struct spfc_mbox_header header; - - u64 cur_jiff_time; -}; - -/* get port state */ -struct spfc_inmbox_get_port_info { - struct spfc_mbox_header header; -}; - -struct spfc_outmbox_get_up_state_sts { - struct spfc_mbox_header header; - - u8 status; - u8 rsv0; - u16 rsv1; - struct unf_port_dynamic_info dymic_info; -}; - -struct spfc_outmbox_get_port_info_sts { - struct spfc_mbox_header header; - - u32 status : 8; - u32 fe_16g_cvis_tts : 8; - u32 bb_scn : 8; - u32 loop_credit : 8; - - u32 non_loop_rx_credit : 8; - u32 non_loop_tx_credit : 8; - u32 sfp_speed : 8; - u32 present : 8; -}; - -struct spfc_inmbox_config_timer { - struct spfc_mbox_header header; - - u16 op_code; - u16 fun_id; - u32 user_data; -}; - -struct spfc_inmbox_config_srqc { - struct spfc_mbox_header header; - - u16 valid; - u16 fun_id; - u32 srqc_gpa_hi; - u32 srqc_gpa_lo; -}; - -struct spfc_outmbox_config_timer_sts { - struct spfc_mbox_header header; - - u8 status; - u8 rsv[ARRAY_INDEX_3]; -}; - -struct spfc_outmbox_config_srqc_sts { - struct spfc_mbox_header header; - - u8 status; - u8 rsv[ARRAY_INDEX_3]; -}; - -struct spfc_inmbox_default_sq_info { - struct spfc_mbox_header header; - u32 sq_cid; - u32 sq_xid; - u16 func_id; - u16 valid; -}; - -struct spfc_outmbox_default_sq_info_sts { - struct spfc_mbox_header header; - u8 status; - u8 rsv[ARRAY_INDEX_3]; -}; - -/* Generic Inmailbox and Outmailbox */ -union spfc_inmbox_generic { - struct { - struct spfc_mbox_header header; - u32 rsvd[(SPFC_MBOX_SIZE - SPFC_MBOX_HEADER_SIZE) / sizeof(u32)]; - } generic; - - struct spfc_inmbox_port_switch port_switch; - struct spfc_inmbox_config_api config_api; - struct spfc_inmbox_get_chip_info get_chip_info; - struct spfc_inmbox_config_login config_login; - struct spfc_inmbox_port_reset port_reset; - struct spfc_inmbox_set_esch esch_set; - struct spfc_inmbox_led_test led_test; - struct spfc_inmbox_get_sfp_info get_sfp_info; - struct spfc_inmbox_clear_done clear_done; - struct spfc_outmbox_get_ucode_stat get_ucode_stat; - struct spfc_inmbox_get_clear_state get_clr_state; - struct spfc_inmbox_send_vport_info send_vport_info; - struct spfc_inmbox_get_up_state get_up_state; - struct spfc_inmbox_config_timer timer_config; - struct spfc_inmbox_config_srqc config_srqc; - struct spfc_inmbox_get_port_info get_port_info; -}; - -union spfc_outmbox_generic { - struct { - struct spfc_mbox_header header; - u32 rsvd[(SPFC_MBOX_SIZE - SPFC_MBOX_HEADER_SIZE) / sizeof(u32)]; - } generic; - - struct spfc_outmbox_port_switch_sts port_switch_sts; - struct spfc_outmbox_config_api_sts config_api_sts; - struct spfc_outmbox_get_chip_info_sts get_chip_info_sts; - struct spfc_outmbox_get_reg_info_sts get_reg_info_sts; - struct spfc_outmbox_config_login_sts config_login_sts; - struct spfc_outmbox_port_reset_sts port_reset_sts; - struct spfc_outmbox_led_test_sts led_test_sts; - struct spfc_outmbox_set_esch_sts esch_set_sts; - struct spfc_inmbox_get_serdes_rx_sts serdes_rx_get_sts; - struct spfc_outmbox_set_serdes_tx_sts serdes_tx_set_sts; - struct spfc_outmbox_i2c_wr_rd_sts i2c_wr_rd_sts; - struct spfc_outmbox_gpio_wr_rd_sts gpio_wr_rd_sts; - struct spfc_outmbox_get_sfp_info_sts get_sfp_info_sts; - struct spfc_outmbox_get_ucode_stat_sts get_ucode_stat_sts; - struct spfc_outmbox_get_clear_state_sts get_clr_state_sts; - struct spfc_outmbox_get_up_state_sts get_up_state_sts; - struct spfc_outmbox_config_timer_sts timer_config_sts; - struct spfc_outmbox_config_srqc_sts config_srqc_sts; - struct spfc_outmbox_get_port_info_sts get_port_info_sts; - struct spfc_outmbox_default_sq_info_sts default_sq_sts; -}; - -u32 spfc_get_chip_msg(void *hba, void *mac); -u32 spfc_config_port_table(struct spfc_hba_info *hba); -u32 spfc_port_switch(struct spfc_hba_info *hba, bool turn_on); -u32 spfc_get_loop_map(void *hba, void *buf); -u32 spfc_get_workable_bb_credit(void *hba, void *bb_credit); -u32 spfc_get_workable_bb_scn(void *hba, void *bb_scn); -u32 spfc_get_port_current_info(void *hba, void *port_info); -u32 spfc_get_port_fec(void *hba, void *para_out); - -u32 spfc_get_loop_alpa(void *hba, void *alpa); -u32 spfc_get_topo_act(void *hba, void *topo_act); -u32 spfc_config_login_api(struct spfc_hba_info *hba, struct unf_port_login_parms *login_parms); -u32 spfc_mb_send_and_wait_mbox(struct spfc_hba_info *hba, const void *in_mbox, u16 in_size, - union spfc_outmbox_generic *out_mbox); -void spfc_up_msg2driver_proc(void *hwdev_handle, void *pri_handle, u16 cmd, - void *buf_in, u16 in_size, void *buf_out, u16 *out_size); - -u32 spfc_mb_reset_chip(struct spfc_hba_info *hba, u8 sub_type); -u32 spfc_clear_sq_wqe_done(struct spfc_hba_info *hba); -u32 spfc_update_fabric_param(void *hba, void *para_in); -u32 spfc_update_port_param(void *hba, void *para_in); -u32 spfc_update_fdisc_param(void *hba, void *vport_info); -u32 spfc_mbx_get_fw_clear_stat(struct spfc_hba_info *hba, u32 *clear_state); -u32 spfc_get_chip_capability(void *hwdev_handle, struct spfc_chip_info *chip_info); -u32 spfc_mbx_config_default_session(void *hba, u32 flag); - -#endif diff --git a/drivers/scsi/spfc/hw/spfc_cqm_bat_cla.c b/drivers/scsi/spfc/hw/spfc_cqm_bat_cla.c deleted file mode 100644 index 0c1d97d9e3e6..000000000000 --- a/drivers/scsi/spfc/hw/spfc_cqm_bat_cla.c +++ /dev/null @@ -1,1611 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#include <linux/types.h> -#include <linux/sched.h> -#include <linux/pci.h> -#include <linux/module.h> -#include <linux/vmalloc.h> -#include <linux/mm.h> -#include <linux/device.h> -#include <linux/gfp.h> -#include "sphw_crm.h" -#include "sphw_hw.h" -#include "sphw_hwdev.h" -#include "sphw_hwif.h" - -#include "spfc_cqm_object.h" -#include "spfc_cqm_bitmap_table.h" -#include "spfc_cqm_bat_cla.h" -#include "spfc_cqm_main.h" - -static unsigned char cqm_ver = 8; -module_param(cqm_ver, byte, 0644); -MODULE_PARM_DESC(cqm_ver, "for cqm version control (default=8)"); - -static void -cqm_bat_fill_cla_common_gpa(struct cqm_handle *cqm_handle, - struct cqm_cla_table *cla_table, - struct cqm_bat_entry_standerd *bat_entry_standerd) -{ - u8 gpa_check_enable = cqm_handle->func_capability.gpa_check_enable; - struct sphw_func_attr *func_attr = NULL; - struct cqm_bat_entry_vf2pf gpa = {0}; - u32 cla_gpa_h = 0; - dma_addr_t pa; - - if (cla_table->cla_lvl == CQM_CLA_LVL_0) - pa = cla_table->cla_z_buf.buf_list[0].pa; - else if (cla_table->cla_lvl == CQM_CLA_LVL_1) - pa = cla_table->cla_y_buf.buf_list[0].pa; - else - pa = cla_table->cla_x_buf.buf_list[0].pa; - - gpa.cla_gpa_h = CQM_ADDR_HI(pa) & CQM_CHIP_GPA_HIMASK; - - /* On the SPU, the value of spu_en in the GPA address - * in the BAT is determined by the host ID and fun IDx. - */ - if (sphw_host_id(cqm_handle->ex_handle) == CQM_SPU_HOST_ID) { - func_attr = &cqm_handle->func_attribute; - gpa.acs_spu_en = func_attr->func_global_idx & 0x1; - } else { - gpa.acs_spu_en = 0; - } - - memcpy(&cla_gpa_h, &gpa, sizeof(u32)); - bat_entry_standerd->cla_gpa_h = cla_gpa_h; - - /* GPA is valid when gpa[0] = 1. - * CQM_BAT_ENTRY_T_REORDER does not support GPA validity check. - */ - if (cla_table->type == CQM_BAT_ENTRY_T_REORDER) - bat_entry_standerd->cla_gpa_l = CQM_ADDR_LW(pa); - else - bat_entry_standerd->cla_gpa_l = CQM_ADDR_LW(pa) | gpa_check_enable; -} - -static void cqm_bat_fill_cla_common(struct cqm_handle *cqm_handle, - struct cqm_cla_table *cla_table, - u8 *entry_base_addr) -{ - struct cqm_bat_entry_standerd *bat_entry_standerd = NULL; - struct sphw_hwdev *handle = cqm_handle->ex_handle; - u32 cache_line = 0; - - if (cla_table->type == CQM_BAT_ENTRY_T_TIMER && cqm_ver == 8) - cache_line = CQM_CHIP_TIMER_CACHELINE; - else - cache_line = CQM_CHIP_CACHELINE; - - if (cla_table->obj_num == 0) { - cqm_info(handle->dev_hdl, - "Cla alloc: cla_type %u, obj_num=0, don't init bat entry\n", - cla_table->type); - return; - } - - bat_entry_standerd = (struct cqm_bat_entry_standerd *)entry_base_addr; - - /* The QPC value is 256/512/1024 and the timer value is 512. - * The other cacheline value is 256B. - * The conversion operation is performed inside the chip. - */ - if (cla_table->obj_size > cache_line) { - if (cla_table->obj_size == CQM_OBJECT_512) - bat_entry_standerd->entry_size = CQM_BAT_ENTRY_SIZE_512; - else - bat_entry_standerd->entry_size = CQM_BAT_ENTRY_SIZE_1024; - bat_entry_standerd->max_number = cla_table->max_buffer_size / cla_table->obj_size; - } else { - if (cache_line == CQM_CHIP_CACHELINE) { - bat_entry_standerd->entry_size = CQM_BAT_ENTRY_SIZE_256; - bat_entry_standerd->max_number = cla_table->max_buffer_size / cache_line; - } else { - bat_entry_standerd->entry_size = CQM_BAT_ENTRY_SIZE_512; - bat_entry_standerd->max_number = cla_table->max_buffer_size / cache_line; - } - } - - bat_entry_standerd->max_number = bat_entry_standerd->max_number - 1; - - bat_entry_standerd->bypass = CQM_BAT_NO_BYPASS_CACHE; - bat_entry_standerd->z = cla_table->cacheline_z; - bat_entry_standerd->y = cla_table->cacheline_y; - bat_entry_standerd->x = cla_table->cacheline_x; - bat_entry_standerd->cla_level = cla_table->cla_lvl; - - cqm_bat_fill_cla_common_gpa(cqm_handle, cla_table, bat_entry_standerd); -} - -static void cqm_bat_fill_cla_cfg(struct cqm_handle *cqm_handle, - struct cqm_cla_table *cla_table, - u8 **entry_base_addr) -{ - struct cqm_func_capability *func_cap = &cqm_handle->func_capability; - struct cqm_bat_entry_cfg *bat_entry_cfg = NULL; - - bat_entry_cfg = (struct cqm_bat_entry_cfg *)(*entry_base_addr); - bat_entry_cfg->cur_conn_cache = 0; - bat_entry_cfg->max_conn_cache = - func_cap->flow_table_based_conn_cache_number; - bat_entry_cfg->cur_conn_num_h_4 = 0; - bat_entry_cfg->cur_conn_num_l_16 = 0; - bat_entry_cfg->max_conn_num = func_cap->flow_table_based_conn_number; - - /* Aligns with 64 buckets and shifts rightward by 6 bits. - * The maximum value of this field is 16 bits. A maximum of 4M buckets - * can be supported. The value is subtracted by 1. It is used for &hash - * value. - */ - if ((func_cap->hash_number >> CQM_HASH_NUMBER_UNIT) != 0) { - bat_entry_cfg->bucket_num = ((func_cap->hash_number >> - CQM_HASH_NUMBER_UNIT) - 1); - } - if (func_cap->bloomfilter_length != 0) { - bat_entry_cfg->bloom_filter_len = func_cap->bloomfilter_length - - 1; - bat_entry_cfg->bloom_filter_addr = func_cap->bloomfilter_addr; - } - - (*entry_base_addr) += sizeof(struct cqm_bat_entry_cfg); -} - -static void cqm_bat_fill_cla_other(struct cqm_handle *cqm_handle, - struct cqm_cla_table *cla_table, - u8 **entry_base_addr) -{ - cqm_bat_fill_cla_common(cqm_handle, cla_table, *entry_base_addr); - - (*entry_base_addr) += sizeof(struct cqm_bat_entry_standerd); -} - -static void cqm_bat_fill_cla_taskmap(struct cqm_handle *cqm_handle, - struct cqm_cla_table *cla_table, - u8 **entry_base_addr) -{ - struct cqm_bat_entry_taskmap *bat_entry_taskmap = NULL; - struct sphw_hwdev *handle = cqm_handle->ex_handle; - int i; - - if (cqm_handle->func_capability.taskmap_number != 0) { - bat_entry_taskmap = - (struct cqm_bat_entry_taskmap *)(*entry_base_addr); - for (i = 0; i < CQM_BAT_ENTRY_TASKMAP_NUM; i++) { - bat_entry_taskmap->addr[i].gpa_h = - (u32)(cla_table->cla_z_buf.buf_list[i].pa >> - CQM_CHIP_GPA_HSHIFT); - bat_entry_taskmap->addr[i].gpa_l = - (u32)(cla_table->cla_z_buf.buf_list[i].pa & - CQM_CHIP_GPA_LOMASK); - cqm_info(handle->dev_hdl, - "Cla alloc: taskmap bat entry: 0x%x 0x%x\n", - bat_entry_taskmap->addr[i].gpa_h, - bat_entry_taskmap->addr[i].gpa_l); - } - } - - (*entry_base_addr) += sizeof(struct cqm_bat_entry_taskmap); -} - -static void cqm_bat_fill_cla_timer(struct cqm_handle *cqm_handle, - struct cqm_cla_table *cla_table, - u8 **entry_base_addr) -{ - /* Only the PPF allocates timer resources. */ - if (cqm_handle->func_attribute.func_type != CQM_PPF) { - (*entry_base_addr) += CQM_BAT_ENTRY_SIZE; - } else { - cqm_bat_fill_cla_common(cqm_handle, cla_table, *entry_base_addr); - - (*entry_base_addr) += sizeof(struct cqm_bat_entry_standerd); - } -} - -static void cqm_bat_fill_cla_invalid(struct cqm_handle *cqm_handle, - struct cqm_cla_table *cla_table, - u8 **entry_base_addr) -{ - (*entry_base_addr) += CQM_BAT_ENTRY_SIZE; -} - -static void cqm_bat_fill_cla(struct cqm_handle *cqm_handle) -{ - struct cqm_bat_table *bat_table = &cqm_handle->bat_table; - struct cqm_cla_table *cla_table = NULL; - u32 entry_type = CQM_BAT_ENTRY_T_INVALID; - u8 *entry_base_addr = NULL; - u32 i = 0; - - /* Fills each item in the BAT table according to the BAT format. */ - entry_base_addr = bat_table->bat; - for (i = 0; i < CQM_BAT_ENTRY_MAX; i++) { - entry_type = bat_table->bat_entry_type[i]; - cla_table = &bat_table->entry[i]; - - if (entry_type == CQM_BAT_ENTRY_T_CFG) - cqm_bat_fill_cla_cfg(cqm_handle, cla_table, &entry_base_addr); - else if (entry_type == CQM_BAT_ENTRY_T_TASKMAP) - cqm_bat_fill_cla_taskmap(cqm_handle, cla_table, &entry_base_addr); - else if (entry_type == CQM_BAT_ENTRY_T_INVALID) - cqm_bat_fill_cla_invalid(cqm_handle, cla_table, &entry_base_addr); - else if (entry_type == CQM_BAT_ENTRY_T_TIMER) - cqm_bat_fill_cla_timer(cqm_handle, cla_table, &entry_base_addr); - else - cqm_bat_fill_cla_other(cqm_handle, cla_table, &entry_base_addr); - - /* Check whether entry_base_addr is out-of-bounds array. */ - if (entry_base_addr >= (bat_table->bat + CQM_BAT_ENTRY_MAX * CQM_BAT_ENTRY_SIZE)) - break; - } -} - -u32 cqm_funcid2smfid(struct cqm_handle *cqm_handle) -{ - u32 funcid = 0; - u32 smf_sel = 0; - u32 smf_id = 0; - u32 smf_pg_partial = 0; - /* SMF_Selection is selected based on - * the lower two bits of the function id - */ - u32 lbf_smfsel[4] = {0, 2, 1, 3}; - /* SMFID is selected based on SMF_PG[1:0] and SMF_Selection(0-1) */ - u32 smfsel_smfid01[4][2] = { {0, 0}, {0, 0}, {1, 1}, {0, 1} }; - /* SMFID is selected based on SMF_PG[3:2] and SMF_Selection(2-4) */ - u32 smfsel_smfid23[4][2] = { {2, 2}, {2, 2}, {3, 3}, {2, 3} }; - - /* When the LB mode is disabled, SMF0 is always returned. */ - if (cqm_handle->func_capability.lb_mode == CQM_LB_MODE_NORMAL) { - smf_id = 0; - } else { - funcid = cqm_handle->func_attribute.func_global_idx & 0x3; - smf_sel = lbf_smfsel[funcid]; - - if (smf_sel < 2) { - smf_pg_partial = cqm_handle->func_capability.smf_pg & 0x3; - smf_id = smfsel_smfid01[smf_pg_partial][smf_sel]; - } else { - smf_pg_partial = (cqm_handle->func_capability.smf_pg >> 2) & 0x3; - smf_id = smfsel_smfid23[smf_pg_partial][smf_sel - 2]; - } - } - - return smf_id; -} - -/* This function is used in LB mode 1/2. The timer spoker info - * of independent space needs to be configured for 4 SMFs. - */ -static void cqm_update_timer_gpa(struct cqm_handle *cqm_handle, u32 smf_id) -{ - struct cqm_bat_table *bat_table = &cqm_handle->bat_table; - struct cqm_cla_table *cla_table = NULL; - u32 entry_type = CQM_BAT_ENTRY_T_INVALID; - u8 *entry_base_addr = NULL; - u32 i = 0; - - if (cqm_handle->func_attribute.func_type != CQM_PPF) - return; - - if (cqm_handle->func_capability.lb_mode != CQM_LB_MODE_1 && - cqm_handle->func_capability.lb_mode != CQM_LB_MODE_2) - return; - - cla_table = &bat_table->timer_entry[smf_id]; - entry_base_addr = bat_table->bat; - for (i = 0; i < CQM_BAT_ENTRY_MAX; i++) { - entry_type = bat_table->bat_entry_type[i]; - - if (entry_type == CQM_BAT_ENTRY_T_TIMER) { - cqm_bat_fill_cla_timer(cqm_handle, cla_table, &entry_base_addr); - break; - } - - if (entry_type == CQM_BAT_ENTRY_T_TASKMAP) - entry_base_addr += sizeof(struct cqm_bat_entry_taskmap); - else - entry_base_addr += CQM_BAT_ENTRY_SIZE; - - /* Check whether entry_base_addr is out-of-bounds array. */ - if (entry_base_addr >= - (bat_table->bat + CQM_BAT_ENTRY_MAX * CQM_BAT_ENTRY_SIZE)) - break; - } -} - -static s32 cqm_bat_update_cmd(struct cqm_handle *cqm_handle, struct cqm_cmd_buf *buf_in, - u32 smf_id, u32 func_id) -{ - struct sphw_hwdev *handle = cqm_handle->ex_handle; - struct cqm_cmdq_bat_update *bat_update_cmd = NULL; - s32 ret = CQM_FAIL; - - bat_update_cmd = (struct cqm_cmdq_bat_update *)(buf_in->buf); - bat_update_cmd->offset = 0; - - if (cqm_handle->bat_table.bat_size > CQM_BAT_MAX_SIZE) { - cqm_err(handle->dev_hdl, - "bat_size = %u, which is more than %d.\n", - cqm_handle->bat_table.bat_size, CQM_BAT_MAX_SIZE); - return CQM_FAIL; - } - bat_update_cmd->byte_len = cqm_handle->bat_table.bat_size; - - memcpy(bat_update_cmd->data, cqm_handle->bat_table.bat, bat_update_cmd->byte_len); - - bat_update_cmd->smf_id = smf_id; - bat_update_cmd->func_id = func_id; - - cqm_info(handle->dev_hdl, "Bat update: smf_id=%u\n", bat_update_cmd->smf_id); - cqm_info(handle->dev_hdl, "Bat update: func_id=%u\n", bat_update_cmd->func_id); - - cqm_swab32((u8 *)bat_update_cmd, sizeof(struct cqm_cmdq_bat_update) >> CQM_DW_SHIFT); - - ret = cqm3_send_cmd_box((void *)(cqm_handle->ex_handle), CQM_MOD_CQM, - CQM_CMD_T_BAT_UPDATE, buf_in, NULL, NULL, - CQM_CMD_TIMEOUT, SPHW_CHANNEL_DEFAULT); - if (ret != CQM_SUCCESS) { - cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm3_send_cmd_box)); - cqm_err(handle->dev_hdl, "%s: send_cmd_box ret=%d\n", __func__, - ret); - return CQM_FAIL; - } - - return CQM_SUCCESS; -} - -s32 cqm_bat_update(struct cqm_handle *cqm_handle) -{ - struct sphw_hwdev *handle = cqm_handle->ex_handle; - struct cqm_cmd_buf *buf_in = NULL; - s32 ret = CQM_FAIL; - u32 smf_id = 0; - u32 func_id = 0; - u32 i = 0; - - buf_in = cqm3_cmd_alloc((void *)(cqm_handle->ex_handle)); - CQM_PTR_CHECK_RET(buf_in, CQM_FAIL, CQM_ALLOC_FAIL(buf_in)); - buf_in->size = sizeof(struct cqm_cmdq_bat_update); - - /* In non-fake mode, func_id is set to 0xffff */ - func_id = 0xffff; - - /* The LB scenario is supported. - * The normal mode is the traditional mode and is configured on SMF0. - * In mode 0, load is balanced to four SMFs based on the func ID (except - * the PPF func ID). The PPF in mode 0 needs to be configured on four - * SMF, so the timer resources can be shared by the four timer engine. - * Mode 1/2 is load balanced to four SMF by flow. Therefore, one - * function needs to be configured to four SMF. - */ - if (cqm_handle->func_capability.lb_mode == CQM_LB_MODE_NORMAL || - (cqm_handle->func_capability.lb_mode == CQM_LB_MODE_0 && - cqm_handle->func_attribute.func_type != CQM_PPF)) { - smf_id = cqm_funcid2smfid(cqm_handle); - ret = cqm_bat_update_cmd(cqm_handle, buf_in, smf_id, func_id); - } else if ((cqm_handle->func_capability.lb_mode == CQM_LB_MODE_1) || - (cqm_handle->func_capability.lb_mode == CQM_LB_MODE_2) || - ((cqm_handle->func_capability.lb_mode == CQM_LB_MODE_0) && - (cqm_handle->func_attribute.func_type == CQM_PPF))) { - for (i = 0; i < CQM_LB_SMF_MAX; i++) { - cqm_update_timer_gpa(cqm_handle, i); - - /* The smf_pg variable stores the currently enabled SMF. */ - if (cqm_handle->func_capability.smf_pg & (1U << i)) { - smf_id = i; - ret = cqm_bat_update_cmd(cqm_handle, buf_in, smf_id, func_id); - if (ret != CQM_SUCCESS) - goto out; - } - } - } else { - cqm_err(handle->dev_hdl, "Bat update: unsupport lb mode=%u\n", - cqm_handle->func_capability.lb_mode); - ret = CQM_FAIL; - } - -out: - cqm3_cmd_free((void *)(cqm_handle->ex_handle), buf_in); - return ret; -} - -s32 cqm_bat_init_ft(struct cqm_handle *cqm_handle, struct cqm_bat_table *bat_table, - enum func_type function_type) -{ - struct sphw_hwdev *handle = cqm_handle->ex_handle; - u32 i = 0; - - bat_table->bat_entry_type[CQM_BAT_INDEX0] = CQM_BAT_ENTRY_T_CFG; - bat_table->bat_entry_type[CQM_BAT_INDEX1] = CQM_BAT_ENTRY_T_HASH; - bat_table->bat_entry_type[CQM_BAT_INDEX2] = CQM_BAT_ENTRY_T_QPC; - bat_table->bat_entry_type[CQM_BAT_INDEX3] = CQM_BAT_ENTRY_T_SCQC; - bat_table->bat_entry_type[CQM_BAT_INDEX4] = CQM_BAT_ENTRY_T_LUN; - bat_table->bat_entry_type[CQM_BAT_INDEX5] = CQM_BAT_ENTRY_T_TASKMAP; - - if (function_type == CQM_PF || function_type == CQM_PPF) { - bat_table->bat_entry_type[CQM_BAT_INDEX6] = CQM_BAT_ENTRY_T_L3I; - bat_table->bat_entry_type[CQM_BAT_INDEX7] = CQM_BAT_ENTRY_T_CHILDC; - bat_table->bat_entry_type[CQM_BAT_INDEX8] = CQM_BAT_ENTRY_T_TIMER; - bat_table->bat_entry_type[CQM_BAT_INDEX9] = CQM_BAT_ENTRY_T_XID2CID; - bat_table->bat_entry_type[CQM_BAT_INDEX10] = CQM_BAT_ENTRY_T_REORDER; - bat_table->bat_size = CQM_BAT_SIZE_FT_PF; - } else if (function_type == CQM_VF) { - bat_table->bat_size = CQM_BAT_SIZE_FT_VF; - } else { - for (i = 0; i < CQM_BAT_ENTRY_MAX; i++) - bat_table->bat_entry_type[i] = CQM_BAT_ENTRY_T_INVALID; - - cqm_err(handle->dev_hdl, CQM_WRONG_VALUE(function_type)); - return CQM_FAIL; - } - - return CQM_SUCCESS; -} - -s32 cqm_bat_init(struct cqm_handle *cqm_handle) -{ - struct cqm_func_capability *capability = &cqm_handle->func_capability; - enum func_type function_type = cqm_handle->func_attribute.func_type; - struct cqm_bat_table *bat_table = &cqm_handle->bat_table; - struct sphw_hwdev *handle = cqm_handle->ex_handle; - u32 i; - - memset(bat_table, 0, sizeof(struct cqm_bat_table)); - - /* Initialize the type of each bat entry. */ - for (i = 0; i < CQM_BAT_ENTRY_MAX; i++) - bat_table->bat_entry_type[i] = CQM_BAT_ENTRY_T_INVALID; - - /* Select BATs based on service types. Currently, - * feature-related resources of the VF are stored in the BATs of the VF. - */ - if (capability->ft_enable) - return cqm_bat_init_ft(cqm_handle, bat_table, function_type); - - cqm_err(handle->dev_hdl, CQM_WRONG_VALUE(capability->ft_enable)); - - return CQM_FAIL; -} - -void cqm_bat_uninit(struct cqm_handle *cqm_handle) -{ - struct cqm_bat_table *bat_table = &cqm_handle->bat_table; - struct sphw_hwdev *handle = cqm_handle->ex_handle; - u32 i; - - for (i = 0; i < CQM_BAT_ENTRY_MAX; i++) - bat_table->bat_entry_type[i] = CQM_BAT_ENTRY_T_INVALID; - - memset(bat_table->bat, 0, CQM_BAT_ENTRY_MAX * CQM_BAT_ENTRY_SIZE); - - /* Instruct the chip to update the BAT table. */ - if (cqm_bat_update(cqm_handle) != CQM_SUCCESS) - cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_bat_update)); -} - -s32 cqm_cla_fill_buf(struct cqm_handle *cqm_handle, struct cqm_buf *cla_base_buf, - struct cqm_buf *cla_sub_buf, u8 gpa_check_enable) -{ - struct sphw_hwdev *handle = cqm_handle->ex_handle; - struct sphw_func_attr *func_attr = NULL; - dma_addr_t *base = NULL; - u64 fake_en = 0; - u64 spu_en = 0; - u64 pf_id = 0; - u32 i = 0; - u32 addr_num; - u32 buf_index = 0; - - /* Apply for space for base_buf */ - if (!cla_base_buf->buf_list) { - if (cqm_buf_alloc(cqm_handle, cla_base_buf, false) == - CQM_FAIL) { - cqm_err(handle->dev_hdl, CQM_ALLOC_FAIL(cla_base_buf)); - return CQM_FAIL; - } - } - - /* Apply for space for sub_buf */ - if (!cla_sub_buf->buf_list) { - if (cqm_buf_alloc(cqm_handle, cla_sub_buf, false) == CQM_FAIL) { - cqm_err(handle->dev_hdl, CQM_ALLOC_FAIL(cla_sub_buf)); - cqm_buf_free(cla_base_buf, cqm_handle->dev); - return CQM_FAIL; - } - } - - /* Fill base_buff with the gpa of sub_buf */ - addr_num = cla_base_buf->buf_size / sizeof(dma_addr_t); - base = (dma_addr_t *)(cla_base_buf->buf_list[0].va); - for (i = 0; i < cla_sub_buf->buf_number; i++) { - /* The SPU SMF supports load balancing from the SMF to the CPI, - * depending on the host ID and func ID. - */ - if (sphw_host_id(cqm_handle->ex_handle) == CQM_SPU_HOST_ID) { - func_attr = &cqm_handle->func_attribute; - spu_en = (u64)(func_attr->func_global_idx & 0x1) << 63; - } else { - spu_en = 0; - } - - *base = (((((cla_sub_buf->buf_list[i].pa & CQM_CHIP_GPA_MASK) | - spu_en) | - fake_en) | - pf_id) | - gpa_check_enable); - - cqm_swab64((u8 *)base, 1); - if ((i + 1) % addr_num == 0) { - buf_index++; - if (buf_index < cla_base_buf->buf_number) - base = cla_base_buf->buf_list[buf_index].va; - } else { - base++; - } - } - - return CQM_SUCCESS; -} - -s32 cqm_cla_xyz_lvl1(struct cqm_handle *cqm_handle, struct cqm_cla_table *cla_table, - u32 trunk_size) -{ - struct sphw_hwdev *handle = cqm_handle->ex_handle; - struct cqm_buf *cla_y_buf = NULL; - struct cqm_buf *cla_z_buf = NULL; - s32 shift = 0; - s32 ret = CQM_FAIL; - u8 gpa_check_enable = cqm_handle->func_capability.gpa_check_enable; - u32 cache_line = 0; - - if (cla_table->type == CQM_BAT_ENTRY_T_TIMER && cqm_ver == 8) - cache_line = CQM_CHIP_TIMER_CACHELINE; - else - cache_line = CQM_CHIP_CACHELINE; - - if (cla_table->type == CQM_BAT_ENTRY_T_REORDER) - gpa_check_enable = 0; - - cla_table->cla_lvl = CQM_CLA_LVL_1; - - shift = cqm_shift(trunk_size / cla_table->obj_size); - cla_table->z = shift ? (shift - 1) : (shift); - cla_table->y = CQM_MAX_INDEX_BIT; - cla_table->x = 0; - - if (cla_table->obj_size >= cache_line) { - cla_table->cacheline_z = cla_table->z; - cla_table->cacheline_y = cla_table->y; - cla_table->cacheline_x = cla_table->x; - } else { - shift = cqm_shift(trunk_size / cache_line); - cla_table->cacheline_z = shift ? (shift - 1) : (shift); - cla_table->cacheline_y = CQM_MAX_INDEX_BIT; - cla_table->cacheline_x = 0; - } - - /* Applying for CLA_Y_BUF Space */ - cla_y_buf = &cla_table->cla_y_buf; - cla_y_buf->buf_size = trunk_size; - cla_y_buf->buf_number = 1; - cla_y_buf->page_number = cla_y_buf->buf_number << - cla_table->trunk_order; - ret = cqm_buf_alloc(cqm_handle, cla_y_buf, false); - CQM_CHECK_EQUAL_RET(handle->dev_hdl, ret, CQM_SUCCESS, CQM_FAIL, - CQM_ALLOC_FAIL(lvl_1_y_buf)); - - /* Applying for CLA_Z_BUF Space */ - cla_z_buf = &cla_table->cla_z_buf; - cla_z_buf->buf_size = trunk_size; - cla_z_buf->buf_number = - (ALIGN(cla_table->max_buffer_size, trunk_size)) / trunk_size; - cla_z_buf->page_number = cla_z_buf->buf_number << - cla_table->trunk_order; - /* All buffer space must be statically allocated. */ - if (cla_table->alloc_static) { - ret = cqm_cla_fill_buf(cqm_handle, cla_y_buf, cla_z_buf, - gpa_check_enable); - CQM_CHECK_EQUAL_RET(handle->dev_hdl, ret, CQM_SUCCESS, CQM_FAIL, - CQM_FUNCTION_FAIL(cqm_cla_fill_buf)); - } else { /* Only the buffer list space is initialized. The buffer space - * is dynamically allocated in services. - */ - cla_z_buf->buf_list = vmalloc(cla_z_buf->buf_number * - sizeof(struct cqm_buf_list)); - if (!cla_z_buf->buf_list) { - cqm_err(handle->dev_hdl, CQM_ALLOC_FAIL(lvl_1_z_buf)); - cqm_buf_free(cla_y_buf, cqm_handle->dev); - return CQM_FAIL; - } - memset(cla_z_buf->buf_list, 0, - cla_z_buf->buf_number * sizeof(struct cqm_buf_list)); - } - - return CQM_SUCCESS; -} - -s32 cqm_cla_xyz_lvl2(struct cqm_handle *cqm_handle, struct cqm_cla_table *cla_table, - u32 trunk_size) -{ - struct sphw_hwdev *handle = cqm_handle->ex_handle; - struct cqm_buf *cla_x_buf = NULL; - struct cqm_buf *cla_y_buf = NULL; - struct cqm_buf *cla_z_buf = NULL; - s32 shift = 0; - s32 ret = CQM_FAIL; - u8 gpa_check_enable = cqm_handle->func_capability.gpa_check_enable; - u32 cache_line = 0; - - if (cla_table->type == CQM_BAT_ENTRY_T_TIMER && cqm_ver == 8) - cache_line = CQM_CHIP_TIMER_CACHELINE; - else - cache_line = CQM_CHIP_CACHELINE; - - if (cla_table->type == CQM_BAT_ENTRY_T_REORDER) - gpa_check_enable = 0; - - cla_table->cla_lvl = CQM_CLA_LVL_2; - - shift = cqm_shift(trunk_size / cla_table->obj_size); - cla_table->z = shift ? (shift - 1) : (shift); - shift = cqm_shift(trunk_size / sizeof(dma_addr_t)); - cla_table->y = cla_table->z + shift; - cla_table->x = CQM_MAX_INDEX_BIT; - - if (cla_table->obj_size >= cache_line) { - cla_table->cacheline_z = cla_table->z; - cla_table->cacheline_y = cla_table->y; - cla_table->cacheline_x = cla_table->x; - } else { - shift = cqm_shift(trunk_size / cache_line); - cla_table->cacheline_z = shift ? (shift - 1) : (shift); - shift = cqm_shift(trunk_size / sizeof(dma_addr_t)); - cla_table->cacheline_y = cla_table->cacheline_z + shift; - cla_table->cacheline_x = CQM_MAX_INDEX_BIT; - } - - /* Apply for CLA_X_BUF Space */ - cla_x_buf = &cla_table->cla_x_buf; - cla_x_buf->buf_size = trunk_size; - cla_x_buf->buf_number = 1; - cla_x_buf->page_number = cla_x_buf->buf_number << - cla_table->trunk_order; - ret = cqm_buf_alloc(cqm_handle, cla_x_buf, false); - CQM_CHECK_EQUAL_RET(handle->dev_hdl, ret, CQM_SUCCESS, CQM_FAIL, - CQM_ALLOC_FAIL(lvl_2_x_buf)); - - /* Apply for CLA_Z_BUF and CLA_Y_BUF Space */ - cla_z_buf = &cla_table->cla_z_buf; - cla_z_buf->buf_size = trunk_size; - cla_z_buf->buf_number = - (ALIGN(cla_table->max_buffer_size, trunk_size)) / trunk_size; - cla_z_buf->page_number = cla_z_buf->buf_number << - cla_table->trunk_order; - - cla_y_buf = &cla_table->cla_y_buf; - cla_y_buf->buf_size = trunk_size; - cla_y_buf->buf_number = - (ALIGN(cla_z_buf->buf_number * sizeof(dma_addr_t), trunk_size)) / - trunk_size; - cla_y_buf->page_number = cla_y_buf->buf_number << - cla_table->trunk_order; - /* All buffer space must be statically allocated. */ - if (cla_table->alloc_static) { - /* Apply for y buf and z buf, and fill the gpa of - * z buf list in y buf - */ - if (cqm_cla_fill_buf(cqm_handle, cla_y_buf, cla_z_buf, - gpa_check_enable) == CQM_FAIL) { - cqm_err(handle->dev_hdl, - CQM_FUNCTION_FAIL(cqm_cla_fill_buf)); - cqm_buf_free(cla_x_buf, cqm_handle->dev); - return CQM_FAIL; - } - - /* Fill the gpa of the y buf list into the x buf. - * After the x and y bufs are applied for, - * this function will not fail. - * Use void to forcibly convert the return of the function. - */ - (void)cqm_cla_fill_buf(cqm_handle, cla_x_buf, cla_y_buf, - gpa_check_enable); - } else { /* Only the buffer list space is initialized. The buffer space - * is dynamically allocated in services. - */ - cla_z_buf->buf_list = vmalloc(cla_z_buf->buf_number * - sizeof(struct cqm_buf_list)); - if (!cla_z_buf->buf_list) { - cqm_err(handle->dev_hdl, CQM_ALLOC_FAIL(lvl_2_z_buf)); - cqm_buf_free(cla_x_buf, cqm_handle->dev); - return CQM_FAIL; - } - memset(cla_z_buf->buf_list, 0, - cla_z_buf->buf_number * sizeof(struct cqm_buf_list)); - - cla_y_buf->buf_list = vmalloc(cla_y_buf->buf_number * - sizeof(struct cqm_buf_list)); - if (!cla_y_buf->buf_list) { - cqm_err(handle->dev_hdl, CQM_ALLOC_FAIL(lvl_2_y_buf)); - cqm_buf_free(cla_z_buf, cqm_handle->dev); - cqm_buf_free(cla_x_buf, cqm_handle->dev); - return CQM_FAIL; - } - memset(cla_y_buf->buf_list, 0, - cla_y_buf->buf_number * sizeof(struct cqm_buf_list)); - } - - return CQM_SUCCESS; -} - -s32 cqm_cla_xyz_check(struct cqm_handle *cqm_handle, struct cqm_cla_table *cla_table, - u32 *size) -{ - struct sphw_hwdev *handle = cqm_handle->ex_handle; - u32 trunk_size = 0; - - /* If the capability(obj_num) is set to 0, the CLA does not need to be - * initialized and exits directly. - */ - if (cla_table->obj_num == 0) { - cqm_info(handle->dev_hdl, - "Cla alloc: cla_type %u, obj_num=0, don't alloc buffer\n", - cla_table->type); - return CQM_SUCCESS; - } - - cqm_info(handle->dev_hdl, - "Cla alloc: cla_type %u, obj_num=0x%x, gpa_check_enable=%d\n", - cla_table->type, cla_table->obj_num, - cqm_handle->func_capability.gpa_check_enable); - - /* Check whether obj_size is 2^n-aligned. An error is reported when - * obj_size is 0 or 1. - */ - if (!cqm_check_align(cla_table->obj_size)) { - cqm_err(handle->dev_hdl, - "Cla alloc: cla_type %u, obj_size 0x%x is not align on 2^n\n", - cla_table->type, cla_table->obj_size); - return CQM_FAIL; - } - - trunk_size = (u32)(PAGE_SIZE << cla_table->trunk_order); - - if (trunk_size < cla_table->obj_size) { - cqm_err(handle->dev_hdl, - "Cla alloc: cla type %u, obj_size 0x%x is out of trunk size\n", - cla_table->type, cla_table->obj_size); - return CQM_FAIL; - } - - *size = trunk_size; - - return CQM_CONTINUE; -} - -s32 cqm_cla_xyz(struct cqm_handle *cqm_handle, struct cqm_cla_table *cla_table) -{ - struct sphw_hwdev *handle = cqm_handle->ex_handle; - struct cqm_buf *cla_z_buf = NULL; - u32 trunk_size = 0; - s32 ret = CQM_FAIL; - - ret = cqm_cla_xyz_check(cqm_handle, cla_table, &trunk_size); - if (ret != CQM_CONTINUE) - return ret; - - /* Level-0 CLA occupies a small space. - * Only CLA_Z_BUF can be allocated during initialization. - */ - if (cla_table->max_buffer_size <= trunk_size) { - cla_table->cla_lvl = CQM_CLA_LVL_0; - - cla_table->z = CQM_MAX_INDEX_BIT; - cla_table->y = 0; - cla_table->x = 0; - - cla_table->cacheline_z = cla_table->z; - cla_table->cacheline_y = cla_table->y; - cla_table->cacheline_x = cla_table->x; - - /* Applying for CLA_Z_BUF Space */ - cla_z_buf = &cla_table->cla_z_buf; - cla_z_buf->buf_size = trunk_size; /* (u32)(PAGE_SIZE << - * cla_table->trunk_order); - */ - cla_z_buf->buf_number = 1; - cla_z_buf->page_number = cla_z_buf->buf_number << cla_table->trunk_order; - ret = cqm_buf_alloc(cqm_handle, cla_z_buf, false); - CQM_CHECK_EQUAL_RET(handle->dev_hdl, ret, CQM_SUCCESS, CQM_FAIL, - CQM_ALLOC_FAIL(lvl_0_z_buf)); - } - /* Level-1 CLA - * Allocates CLA_Y_BUF and CLA_Z_BUF during initialization. - */ - else if (cla_table->max_buffer_size <= (trunk_size * (trunk_size / sizeof(dma_addr_t)))) { - if (cqm_cla_xyz_lvl1(cqm_handle, cla_table, trunk_size) == CQM_FAIL) { - cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_cla_xyz_lvl1)); - return CQM_FAIL; - } - } - /* Level-2 CLA - * Allocates CLA_X_BUF, CLA_Y_BUF, and CLA_Z_BUF during initialization. - */ - else if (cla_table->max_buffer_size <= - (trunk_size * (trunk_size / sizeof(dma_addr_t)) * - (trunk_size / sizeof(dma_addr_t)))) { - if (cqm_cla_xyz_lvl2(cqm_handle, cla_table, trunk_size) == - CQM_FAIL) { - cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_cla_xyz_lvl2)); - return CQM_FAIL; - } - } else { /* The current memory management mode does not support such - * a large buffer addressing. The order value needs to - * be increased. - */ - cqm_err(handle->dev_hdl, - "Cla alloc: cla max_buffer_size 0x%x exceeds support range\n", - cla_table->max_buffer_size); - return CQM_FAIL; - } - - return CQM_SUCCESS; -} - -void cqm_cla_init_entry_normal(struct cqm_handle *cqm_handle, - struct cqm_cla_table *cla_table, - struct cqm_func_capability *capability) -{ - struct sphw_hwdev *handle = cqm_handle->ex_handle; - - switch (cla_table->type) { - case CQM_BAT_ENTRY_T_HASH: - cla_table->trunk_order = capability->pagesize_reorder; - cla_table->max_buffer_size = capability->hash_number * capability->hash_basic_size; - cla_table->obj_size = capability->hash_basic_size; - cla_table->obj_num = capability->hash_number; - cla_table->alloc_static = true; - break; - case CQM_BAT_ENTRY_T_QPC: - cla_table->trunk_order = capability->pagesize_reorder; - cla_table->max_buffer_size = capability->qpc_number * capability->qpc_basic_size; - cla_table->obj_size = capability->qpc_basic_size; - cla_table->obj_num = capability->qpc_number; - cla_table->alloc_static = capability->qpc_alloc_static; - cqm_info(handle->dev_hdl, "Cla alloc: qpc alloc_static=%d\n", - cla_table->alloc_static); - break; - case CQM_BAT_ENTRY_T_MPT: - cla_table->trunk_order = capability->pagesize_reorder; - cla_table->max_buffer_size = capability->mpt_number * capability->mpt_basic_size; - cla_table->obj_size = capability->mpt_basic_size; - cla_table->obj_num = capability->mpt_number; - /* CCB decided. MPT uses only static application scenarios. */ - cla_table->alloc_static = true; - break; - case CQM_BAT_ENTRY_T_SCQC: - cla_table->trunk_order = capability->pagesize_reorder; - cla_table->max_buffer_size = capability->scqc_number * capability->scqc_basic_size; - cla_table->obj_size = capability->scqc_basic_size; - cla_table->obj_num = capability->scqc_number; - cla_table->alloc_static = capability->scqc_alloc_static; - cqm_info(handle->dev_hdl, "Cla alloc: scqc alloc_static=%d\n", - cla_table->alloc_static); - break; - case CQM_BAT_ENTRY_T_SRQC: - cla_table->trunk_order = capability->pagesize_reorder; - cla_table->max_buffer_size = capability->srqc_number * capability->srqc_basic_size; - cla_table->obj_size = capability->srqc_basic_size; - cla_table->obj_num = capability->srqc_number; - cla_table->alloc_static = false; - break; - default: - break; - } -} - -void cqm_cla_init_entry_extern(struct cqm_handle *cqm_handle, - struct cqm_cla_table *cla_table, - struct cqm_func_capability *capability) -{ - switch (cla_table->type) { - case CQM_BAT_ENTRY_T_GID: - /* Level-0 CLA table required */ - cla_table->max_buffer_size = capability->gid_number * capability->gid_basic_size; - cla_table->trunk_order = - (u32)cqm_shift(ALIGN(cla_table->max_buffer_size, PAGE_SIZE) / PAGE_SIZE); - cla_table->obj_size = capability->gid_basic_size; - cla_table->obj_num = capability->gid_number; - cla_table->alloc_static = true; - break; - case CQM_BAT_ENTRY_T_LUN: - cla_table->trunk_order = CLA_TABLE_PAGE_ORDER; - cla_table->max_buffer_size = capability->lun_number * capability->lun_basic_size; - cla_table->obj_size = capability->lun_basic_size; - cla_table->obj_num = capability->lun_number; - cla_table->alloc_static = true; - break; - case CQM_BAT_ENTRY_T_TASKMAP: - cla_table->trunk_order = CQM_4K_PAGE_ORDER; - cla_table->max_buffer_size = capability->taskmap_number * - capability->taskmap_basic_size; - cla_table->obj_size = capability->taskmap_basic_size; - cla_table->obj_num = capability->taskmap_number; - cla_table->alloc_static = true; - break; - case CQM_BAT_ENTRY_T_L3I: - cla_table->trunk_order = CLA_TABLE_PAGE_ORDER; - cla_table->max_buffer_size = capability->l3i_number * capability->l3i_basic_size; - cla_table->obj_size = capability->l3i_basic_size; - cla_table->obj_num = capability->l3i_number; - cla_table->alloc_static = true; - break; - case CQM_BAT_ENTRY_T_CHILDC: - cla_table->trunk_order = capability->pagesize_reorder; - cla_table->max_buffer_size = capability->childc_number * - capability->childc_basic_size; - cla_table->obj_size = capability->childc_basic_size; - cla_table->obj_num = capability->childc_number; - cla_table->alloc_static = true; - break; - case CQM_BAT_ENTRY_T_TIMER: - /* Ensure that the basic size of the timer buffer page does not - * exceed 128 x 4 KB. Otherwise, clearing the timer buffer of - * the function is complex. - */ - cla_table->trunk_order = CQM_4K_PAGE_ORDER; - cla_table->max_buffer_size = capability->timer_number * - capability->timer_basic_size; - cla_table->obj_size = capability->timer_basic_size; - cla_table->obj_num = capability->timer_number; - cla_table->alloc_static = true; - break; - case CQM_BAT_ENTRY_T_XID2CID: - cla_table->trunk_order = capability->pagesize_reorder; - cla_table->max_buffer_size = capability->xid2cid_number * - capability->xid2cid_basic_size; - cla_table->obj_size = capability->xid2cid_basic_size; - cla_table->obj_num = capability->xid2cid_number; - cla_table->alloc_static = true; - break; - case CQM_BAT_ENTRY_T_REORDER: - /* This entry supports only IWARP and does not support GPA validity check. */ - cla_table->trunk_order = capability->pagesize_reorder; - cla_table->max_buffer_size = capability->reorder_number * - capability->reorder_basic_size; - cla_table->obj_size = capability->reorder_basic_size; - cla_table->obj_num = capability->reorder_number; - cla_table->alloc_static = true; - break; - default: - break; - } -} - -s32 cqm_cla_init_entry_condition(struct cqm_handle *cqm_handle, u32 entry_type) -{ - struct cqm_bat_table *bat_table = &cqm_handle->bat_table; - struct cqm_cla_table *cla_table = &bat_table->entry[entry_type]; - struct cqm_cla_table *cla_table_timer = NULL; - u32 i; - - /* When the timer is in LB mode 1 or 2, the timer needs to be - * configured for four SMFs and the address space is independent. - */ - if (cla_table->type == CQM_BAT_ENTRY_T_TIMER && - (cqm_handle->func_capability.lb_mode == CQM_LB_MODE_1 || - cqm_handle->func_capability.lb_mode == CQM_LB_MODE_2)) { - for (i = 0; i < CQM_LB_SMF_MAX; i++) { - cla_table_timer = &bat_table->timer_entry[i]; - memcpy(cla_table_timer, cla_table, sizeof(struct cqm_cla_table)); - - if (cqm_cla_xyz(cqm_handle, cla_table_timer) == CQM_FAIL) { - cqm_cla_uninit(cqm_handle, entry_type); - return CQM_FAIL; - } - } - } - - if (cqm_cla_xyz(cqm_handle, cla_table) == CQM_FAIL) { - cqm_cla_uninit(cqm_handle, entry_type); - return CQM_FAIL; - } - - return CQM_SUCCESS; -} - -s32 cqm_cla_init_entry(struct cqm_handle *cqm_handle, - struct cqm_func_capability *capability) -{ - struct cqm_bat_table *bat_table = &cqm_handle->bat_table; - struct cqm_cla_table *cla_table = NULL; - s32 ret; - u32 i = 0; - - for (i = 0; i < CQM_BAT_ENTRY_MAX; i++) { - cla_table = &bat_table->entry[i]; - cla_table->type = bat_table->bat_entry_type[i]; - - cqm_cla_init_entry_normal(cqm_handle, cla_table, capability); - cqm_cla_init_entry_extern(cqm_handle, cla_table, capability); - - /* Allocate CLA entry space at each level. */ - if (cla_table->type < CQM_BAT_ENTRY_T_HASH || - cla_table->type > CQM_BAT_ENTRY_T_REORDER) { - mutex_init(&cla_table->lock); - continue; - } - - /* For the PPF, resources (8 wheels x 2k scales x 32B x - * func_num) need to be applied for to the timer. The - * structure of the timer entry in the BAT table needs - * to be filled. For the PF, no resource needs to be - * applied for the timer and no structure needs to be - * filled in the timer entry in the BAT table. - */ - if (!(cla_table->type == CQM_BAT_ENTRY_T_TIMER && - cqm_handle->func_attribute.func_type != CQM_PPF)) { - ret = cqm_cla_init_entry_condition(cqm_handle, i); - if (ret != CQM_SUCCESS) - return CQM_FAIL; - } - mutex_init(&cla_table->lock); - } - - return CQM_SUCCESS; -} - -s32 cqm_cla_init(struct cqm_handle *cqm_handle) -{ - struct cqm_func_capability *capability = &cqm_handle->func_capability; - struct sphw_hwdev *handle = cqm_handle->ex_handle; - s32 ret; - - /* Applying for CLA Entries */ - ret = cqm_cla_init_entry(cqm_handle, capability); - if (ret != CQM_SUCCESS) { - cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_cla_init_entry)); - return ret; - } - - /* After the CLA entry is applied, the address is filled in the BAT table. */ - cqm_bat_fill_cla(cqm_handle); - - /* Instruct the chip to update the BAT table. */ - ret = cqm_bat_update(cqm_handle); - if (ret != CQM_SUCCESS) { - cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_bat_update)); - goto err; - } - - cqm_info(handle->dev_hdl, "Timer start: func_type=%d, timer_enable=%u\n", - cqm_handle->func_attribute.func_type, - cqm_handle->func_capability.timer_enable); - - if (cqm_handle->func_attribute.func_type == CQM_PPF && - cqm_handle->func_capability.timer_enable == CQM_TIMER_ENABLE) { - /* Enable the timer after the timer resources are applied for */ - cqm_info(handle->dev_hdl, "Timer start: spfc ppf timer start\n"); - ret = sphw_ppf_tmr_start((void *)(cqm_handle->ex_handle)); - if (ret != CQM_SUCCESS) { - cqm_err(handle->dev_hdl, "Timer start: spfc ppf timer start, ret=%d\n", - ret); - goto err; - } - } - - return CQM_SUCCESS; - -err: - cqm_cla_uninit(cqm_handle, CQM_BAT_ENTRY_MAX); - return CQM_FAIL; -} - -void cqm_cla_uninit(struct cqm_handle *cqm_handle, u32 entry_numb) -{ - struct cqm_bat_table *bat_table = &cqm_handle->bat_table; - struct cqm_cla_table *cla_table = NULL; - s32 inv_flag = 0; - u32 i; - - for (i = 0; i < entry_numb; i++) { - cla_table = &bat_table->entry[i]; - if (cla_table->type != CQM_BAT_ENTRY_T_INVALID) { - cqm_buf_free_cache_inv(cqm_handle, &cla_table->cla_x_buf, &inv_flag); - cqm_buf_free_cache_inv(cqm_handle, &cla_table->cla_y_buf, &inv_flag); - cqm_buf_free_cache_inv(cqm_handle, &cla_table->cla_z_buf, &inv_flag); - } - } - - /* When the lb mode is 1/2, the timer space allocated to the 4 SMFs - * needs to be released. - */ - if (cqm_handle->func_attribute.func_type == CQM_PPF && - (cqm_handle->func_capability.lb_mode == CQM_LB_MODE_1 || - cqm_handle->func_capability.lb_mode == CQM_LB_MODE_2)) { - for (i = 0; i < CQM_LB_SMF_MAX; i++) { - cla_table = &bat_table->timer_entry[i]; - cqm_buf_free_cache_inv(cqm_handle, &cla_table->cla_x_buf, &inv_flag); - cqm_buf_free_cache_inv(cqm_handle, &cla_table->cla_y_buf, &inv_flag); - cqm_buf_free_cache_inv(cqm_handle, &cla_table->cla_z_buf, &inv_flag); - } - } -} - -s32 cqm_cla_update_cmd(struct cqm_handle *cqm_handle, struct cqm_cmd_buf *buf_in, - struct cqm_cla_update_cmd *cmd) -{ - struct sphw_hwdev *handle = cqm_handle->ex_handle; - struct cqm_cla_update_cmd *cla_update_cmd = NULL; - s32 ret = CQM_FAIL; - - cla_update_cmd = (struct cqm_cla_update_cmd *)(buf_in->buf); - - cla_update_cmd->gpa_h = cmd->gpa_h; - cla_update_cmd->gpa_l = cmd->gpa_l; - cla_update_cmd->value_h = cmd->value_h; - cla_update_cmd->value_l = cmd->value_l; - cla_update_cmd->smf_id = cmd->smf_id; - cla_update_cmd->func_id = cmd->func_id; - - cqm_swab32((u8 *)cla_update_cmd, - (sizeof(struct cqm_cla_update_cmd) >> CQM_DW_SHIFT)); - - ret = cqm3_send_cmd_box((void *)(cqm_handle->ex_handle), CQM_MOD_CQM, - CQM_CMD_T_CLA_UPDATE, buf_in, NULL, NULL, - CQM_CMD_TIMEOUT, SPHW_CHANNEL_DEFAULT); - if (ret != CQM_SUCCESS) { - cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm3_send_cmd_box)); - cqm_err(handle->dev_hdl, "Cla alloc: cqm_cla_update, cqm3_send_cmd_box_ret=%d\n", - ret); - cqm_err(handle->dev_hdl, "Cla alloc: cqm_cla_update, cla_update_cmd: 0x%x 0x%x 0x%x 0x%x\n", - cmd->gpa_h, cmd->gpa_l, cmd->value_h, cmd->value_l); - return CQM_FAIL; - } - - return CQM_SUCCESS; -} - -s32 cqm_cla_update(struct cqm_handle *cqm_handle, struct cqm_buf_list *buf_node_parent, - struct cqm_buf_list *buf_node_child, u32 child_index, u8 cla_update_mode) -{ - struct sphw_hwdev *handle = cqm_handle->ex_handle; - struct cqm_cmd_buf *buf_in = NULL; - struct cqm_cla_update_cmd cmd; - dma_addr_t pa = 0; - s32 ret = CQM_FAIL; - u8 gpa_check_enable = cqm_handle->func_capability.gpa_check_enable; - u32 i = 0; - u64 spu_en; - - buf_in = cqm3_cmd_alloc(cqm_handle->ex_handle); - CQM_PTR_CHECK_RET(buf_in, CQM_FAIL, CQM_ALLOC_FAIL(buf_in)); - buf_in->size = sizeof(struct cqm_cla_update_cmd); - - /* Fill command format, convert to big endian. */ - /* SPU function sets bit63: acs_spu_en based on function id. */ - if (sphw_host_id(cqm_handle->ex_handle) == CQM_SPU_HOST_ID) - spu_en = ((u64)(cqm_handle->func_attribute.func_global_idx & - 0x1)) << 63; - else - spu_en = 0; - - pa = ((buf_node_parent->pa + (child_index * sizeof(dma_addr_t))) | - spu_en); - cmd.gpa_h = CQM_ADDR_HI(pa); - cmd.gpa_l = CQM_ADDR_LW(pa); - - pa = (buf_node_child->pa | spu_en); - cmd.value_h = CQM_ADDR_HI(pa); - cmd.value_l = CQM_ADDR_LW(pa); - - /* current CLA GPA CHECK */ - if (gpa_check_enable) { - switch (cla_update_mode) { - /* gpa[0]=1 means this GPA is valid */ - case CQM_CLA_RECORD_NEW_GPA: - cmd.value_l |= 1; - break; - /* gpa[0]=0 means this GPA is valid */ - case CQM_CLA_DEL_GPA_WITHOUT_CACHE_INVALID: - case CQM_CLA_DEL_GPA_WITH_CACHE_INVALID: - cmd.value_l &= (~1); - break; - default: - cqm_err(handle->dev_hdl, - "Cla alloc: %s, wrong cla_update_mode=%u\n", - __func__, cla_update_mode); - break; - } - } - - /* In non-fake mode, set func_id to 0xffff. */ - cmd.func_id = 0xffff; - - /* Mode 0 is hashed to 4 SMF engines (excluding PPF) by func ID. */ - if (cqm_handle->func_capability.lb_mode == CQM_LB_MODE_NORMAL || - (cqm_handle->func_capability.lb_mode == CQM_LB_MODE_0 && - cqm_handle->func_attribute.func_type != CQM_PPF)) { - cmd.smf_id = cqm_funcid2smfid(cqm_handle); - ret = cqm_cla_update_cmd(cqm_handle, buf_in, &cmd); - } - /* Modes 1/2 are allocated to four SMF engines by flow. - * Therefore, one function needs to be allocated to four SMF engines. - */ - /* Mode 0 PPF needs to be configured on 4 engines, - * and the timer resources need to be shared by the 4 engines. - */ - else if (cqm_handle->func_capability.lb_mode == CQM_LB_MODE_1 || - cqm_handle->func_capability.lb_mode == CQM_LB_MODE_2 || - (cqm_handle->func_capability.lb_mode == CQM_LB_MODE_0 && - cqm_handle->func_attribute.func_type == CQM_PPF)) { - for (i = 0; i < CQM_LB_SMF_MAX; i++) { - /* The smf_pg variable stores currently enabled SMF. */ - if (cqm_handle->func_capability.smf_pg & (1U << i)) { - cmd.smf_id = i; - ret = cqm_cla_update_cmd(cqm_handle, buf_in, - &cmd); - if (ret != CQM_SUCCESS) - goto out; - } - } - } else { - cqm_err(handle->dev_hdl, "Cla update: unsupport lb mode=%u\n", - cqm_handle->func_capability.lb_mode); - ret = CQM_FAIL; - } - -out: - cqm3_cmd_free((void *)(cqm_handle->ex_handle), buf_in); - return ret; -} - -s32 cqm_cla_alloc(struct cqm_handle *cqm_handle, struct cqm_cla_table *cla_table, - struct cqm_buf_list *buf_node_parent, - struct cqm_buf_list *buf_node_child, u32 child_index) -{ - struct sphw_hwdev *handle = cqm_handle->ex_handle; - s32 ret = CQM_FAIL; - - /* Apply for trunk page */ - buf_node_child->va = (u8 *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, - cla_table->trunk_order); - CQM_PTR_CHECK_RET(buf_node_child->va, CQM_FAIL, CQM_ALLOC_FAIL(va)); - - /* PCI mapping */ - buf_node_child->pa = pci_map_single(cqm_handle->dev, buf_node_child->va, - PAGE_SIZE << cla_table->trunk_order, - PCI_DMA_BIDIRECTIONAL); - if (pci_dma_mapping_error(cqm_handle->dev, buf_node_child->pa)) { - cqm_err(handle->dev_hdl, CQM_MAP_FAIL(buf_node_child->pa)); - goto err1; - } - - /* Notify the chip of trunk_pa so that the chip fills in cla entry */ - ret = cqm_cla_update(cqm_handle, buf_node_parent, buf_node_child, - child_index, CQM_CLA_RECORD_NEW_GPA); - if (ret != CQM_SUCCESS) { - cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_cla_update)); - goto err2; - } - - return CQM_SUCCESS; - -err2: - pci_unmap_single(cqm_handle->dev, buf_node_child->pa, - PAGE_SIZE << cla_table->trunk_order, - PCI_DMA_BIDIRECTIONAL); -err1: - free_pages((ulong)(buf_node_child->va), cla_table->trunk_order); - buf_node_child->va = NULL; - return CQM_FAIL; -} - -void cqm_cla_free(struct cqm_handle *cqm_handle, struct cqm_cla_table *cla_table, - struct cqm_buf_list *buf_node_parent, - struct cqm_buf_list *buf_node_child, u32 child_index, u8 cla_update_mode) -{ - struct sphw_hwdev *handle = cqm_handle->ex_handle; - u32 trunk_size; - - if (cqm_cla_update(cqm_handle, buf_node_parent, buf_node_child, - child_index, cla_update_mode) != CQM_SUCCESS) { - cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_cla_update)); - return; - } - - if (cla_update_mode == CQM_CLA_DEL_GPA_WITH_CACHE_INVALID) { - trunk_size = (u32)(PAGE_SIZE << cla_table->trunk_order); - if (cqm_cla_cache_invalid(cqm_handle, buf_node_child->pa, - trunk_size) != CQM_SUCCESS) { - cqm_err(handle->dev_hdl, - CQM_FUNCTION_FAIL(cqm_cla_cache_invalid)); - return; - } - } - - /* Remove PCI mapping from the trunk page */ - pci_unmap_single(cqm_handle->dev, buf_node_child->pa, - PAGE_SIZE << cla_table->trunk_order, - PCI_DMA_BIDIRECTIONAL); - - /* Rlease trunk page */ - free_pages((ulong)(buf_node_child->va), cla_table->trunk_order); - buf_node_child->va = NULL; -} - -u8 *cqm_cla_get_unlock_lvl0(struct cqm_handle *cqm_handle, - struct cqm_cla_table *cla_table, - u32 index, u32 count, dma_addr_t *pa) -{ - struct cqm_buf *cla_z_buf = &cla_table->cla_z_buf; - u8 *ret_addr = NULL; - u32 offset = 0; - - /* Level 0 CLA pages are statically allocated. */ - offset = index * cla_table->obj_size; - ret_addr = (u8 *)(cla_z_buf->buf_list->va) + offset; - *pa = cla_z_buf->buf_list->pa + offset; - - return ret_addr; -} - -u8 *cqm_cla_get_unlock_lvl1(struct cqm_handle *cqm_handle, - struct cqm_cla_table *cla_table, - u32 index, u32 count, dma_addr_t *pa) -{ - struct cqm_buf *cla_y_buf = &cla_table->cla_y_buf; - struct cqm_buf *cla_z_buf = &cla_table->cla_z_buf; - struct sphw_hwdev *handle = cqm_handle->ex_handle; - struct cqm_buf_list *buf_node_y = NULL; - struct cqm_buf_list *buf_node_z = NULL; - u32 y_index = 0; - u32 z_index = 0; - u8 *ret_addr = NULL; - u32 offset = 0; - - z_index = index & ((1U << (cla_table->z + 1)) - 1); - y_index = index >> (cla_table->z + 1); - - if (y_index >= cla_z_buf->buf_number) { - cqm_err(handle->dev_hdl, - "Cla get: index exceeds buf_number, y_index %u, z_buf_number %u\n", - y_index, cla_z_buf->buf_number); - return NULL; - } - buf_node_z = &cla_z_buf->buf_list[y_index]; - buf_node_y = cla_y_buf->buf_list; - - /* The z buf node does not exist, applying for a page first. */ - if (!buf_node_z->va) { - if (cqm_cla_alloc(cqm_handle, cla_table, buf_node_y, buf_node_z, - y_index) == CQM_FAIL) { - cqm_err(handle->dev_hdl, - CQM_FUNCTION_FAIL(cqm_cla_alloc)); - cqm_err(handle->dev_hdl, - "Cla get: cla_table->type=%u\n", - cla_table->type); - return NULL; - } - } - - buf_node_z->refcount += count; - offset = z_index * cla_table->obj_size; - ret_addr = (u8 *)(buf_node_z->va) + offset; - *pa = buf_node_z->pa + offset; - - return ret_addr; -} - -u8 *cqm_cla_get_unlock_lvl2(struct cqm_handle *cqm_handle, - struct cqm_cla_table *cla_table, - u32 index, u32 count, dma_addr_t *pa) -{ - struct cqm_buf *cla_x_buf = &cla_table->cla_x_buf; - struct cqm_buf *cla_y_buf = &cla_table->cla_y_buf; - struct cqm_buf *cla_z_buf = &cla_table->cla_z_buf; - struct sphw_hwdev *handle = cqm_handle->ex_handle; - struct cqm_buf_list *buf_node_x = NULL; - struct cqm_buf_list *buf_node_y = NULL; - struct cqm_buf_list *buf_node_z = NULL; - u32 x_index = 0; - u32 y_index = 0; - u32 z_index = 0; - u32 trunk_size = (u32)(PAGE_SIZE << cla_table->trunk_order); - u8 *ret_addr = NULL; - u32 offset = 0; - u64 tmp; - - z_index = index & ((1U << (cla_table->z + 1)) - 1); - y_index = (index >> (cla_table->z + 1)) & - ((1U << (cla_table->y - cla_table->z)) - 1); - x_index = index >> (cla_table->y + 1); - tmp = x_index * (trunk_size / sizeof(dma_addr_t)) + y_index; - - if (x_index >= cla_y_buf->buf_number || tmp >= cla_z_buf->buf_number) { - cqm_err(handle->dev_hdl, - "Cla get: index exceeds buf_number, x_index %u, y_index %u, y_buf_number %u, z_buf_number %u\n", - x_index, y_index, cla_y_buf->buf_number, - cla_z_buf->buf_number); - return NULL; - } - - buf_node_x = cla_x_buf->buf_list; - buf_node_y = &cla_y_buf->buf_list[x_index]; - buf_node_z = &cla_z_buf->buf_list[tmp]; - - /* The y buf node does not exist, applying for pages for y node. */ - if (!buf_node_y->va) { - if (cqm_cla_alloc(cqm_handle, cla_table, buf_node_x, buf_node_y, - x_index) == CQM_FAIL) { - cqm_err(handle->dev_hdl, - CQM_FUNCTION_FAIL(cqm_cla_alloc)); - return NULL; - } - } - - /* The z buf node does not exist, applying for pages for z node. */ - if (!buf_node_z->va) { - if (cqm_cla_alloc(cqm_handle, cla_table, buf_node_y, buf_node_z, - y_index) == CQM_FAIL) { - cqm_err(handle->dev_hdl, - CQM_FUNCTION_FAIL(cqm_cla_alloc)); - if (buf_node_y->refcount == 0) - /* To release node Y, cache_invalid is - * required. - */ - cqm_cla_free(cqm_handle, cla_table, buf_node_x, buf_node_y, x_index, - CQM_CLA_DEL_GPA_WITH_CACHE_INVALID); - return NULL; - } - - /* reference counting of the y buffer node needs to increase - * by 1. - */ - buf_node_y->refcount++; - } - - buf_node_z->refcount += count; - offset = z_index * cla_table->obj_size; - ret_addr = (u8 *)(buf_node_z->va) + offset; - *pa = buf_node_z->pa + offset; - - return ret_addr; -} - -u8 *cqm_cla_get_unlock(struct cqm_handle *cqm_handle, struct cqm_cla_table *cla_table, - u32 index, u32 count, dma_addr_t *pa) -{ - u8 *ret_addr = NULL; - - if (cla_table->cla_lvl == CQM_CLA_LVL_0) - ret_addr = cqm_cla_get_unlock_lvl0(cqm_handle, cla_table, index, - count, pa); - else if (cla_table->cla_lvl == CQM_CLA_LVL_1) - ret_addr = cqm_cla_get_unlock_lvl1(cqm_handle, cla_table, index, - count, pa); - else - ret_addr = cqm_cla_get_unlock_lvl2(cqm_handle, cla_table, index, - count, pa); - - return ret_addr; -} - -u8 *cqm_cla_get_lock(struct cqm_handle *cqm_handle, struct cqm_cla_table *cla_table, - u32 index, u32 count, dma_addr_t *pa) -{ - u8 *ret_addr = NULL; - - mutex_lock(&cla_table->lock); - - ret_addr = cqm_cla_get_unlock(cqm_handle, cla_table, index, count, pa); - - mutex_unlock(&cla_table->lock); - - return ret_addr; -} - -void cqm_cla_put(struct cqm_handle *cqm_handle, struct cqm_cla_table *cla_table, - u32 index, u32 count) -{ - struct cqm_buf *cla_z_buf = &cla_table->cla_z_buf; - struct cqm_buf *cla_y_buf = &cla_table->cla_y_buf; - struct cqm_buf *cla_x_buf = &cla_table->cla_x_buf; - struct sphw_hwdev *handle = cqm_handle->ex_handle; - struct cqm_buf_list *buf_node_z = NULL; - struct cqm_buf_list *buf_node_y = NULL; - struct cqm_buf_list *buf_node_x = NULL; - u32 x_index = 0; - u32 y_index = 0; - u32 trunk_size = (u32)(PAGE_SIZE << cla_table->trunk_order); - u64 tmp; - - /* The buffer is applied statically, and the reference counting - * does not need to be controlled. - */ - if (cla_table->alloc_static) - return; - - mutex_lock(&cla_table->lock); - - if (cla_table->cla_lvl == CQM_CLA_LVL_1) { - y_index = index >> (cla_table->z + 1); - - if (y_index >= cla_z_buf->buf_number) { - cqm_err(handle->dev_hdl, - "Cla put: index exceeds buf_number, y_index %u, z_buf_number %u\n", - y_index, cla_z_buf->buf_number); - cqm_err(handle->dev_hdl, - "Cla put: cla_table->type=%u\n", - cla_table->type); - mutex_unlock(&cla_table->lock); - return; - } - - buf_node_z = &cla_z_buf->buf_list[y_index]; - buf_node_y = cla_y_buf->buf_list; - - /* When the value of reference counting on the z node page is 0, - * the z node page is released. - */ - buf_node_z->refcount -= count; - if (buf_node_z->refcount == 0) - /* The cache invalid is not required for the Z node. */ - cqm_cla_free(cqm_handle, cla_table, buf_node_y, - buf_node_z, y_index, - CQM_CLA_DEL_GPA_WITHOUT_CACHE_INVALID); - } else if (cla_table->cla_lvl == CQM_CLA_LVL_2) { - y_index = (index >> (cla_table->z + 1)) & - ((1U << (cla_table->y - cla_table->z)) - 1); - x_index = index >> (cla_table->y + 1); - tmp = x_index * (trunk_size / sizeof(dma_addr_t)) + y_index; - - if (x_index >= cla_y_buf->buf_number || tmp >= cla_z_buf->buf_number) { - cqm_err(handle->dev_hdl, - "Cla put: index exceeds buf_number, x_index %u, y_index %u, y_buf_number %u, z_buf_number %u\n", - x_index, y_index, cla_y_buf->buf_number, - cla_z_buf->buf_number); - mutex_unlock(&cla_table->lock); - return; - } - - buf_node_x = cla_x_buf->buf_list; - buf_node_y = &cla_y_buf->buf_list[x_index]; - buf_node_z = &cla_z_buf->buf_list[tmp]; - - /* When the value of reference counting on the z node page is 0, - * the z node page is released. - */ - buf_node_z->refcount -= count; - if (buf_node_z->refcount == 0) { - cqm_cla_free(cqm_handle, cla_table, buf_node_y, - buf_node_z, y_index, - CQM_CLA_DEL_GPA_WITHOUT_CACHE_INVALID); - - /* When the value of reference counting on the y node - * page is 0, the y node page is released. - */ - buf_node_y->refcount--; - if (buf_node_y->refcount == 0) - /* Node y requires cache to be invalid. */ - cqm_cla_free(cqm_handle, cla_table, buf_node_x, buf_node_y, x_index, - CQM_CLA_DEL_GPA_WITH_CACHE_INVALID); - } - } - - mutex_unlock(&cla_table->lock); -} - -struct cqm_cla_table *cqm_cla_table_get(struct cqm_bat_table *bat_table, u32 entry_type) -{ - struct cqm_cla_table *cla_table = NULL; - u32 i = 0; - - for (i = 0; i < CQM_BAT_ENTRY_MAX; i++) { - cla_table = &bat_table->entry[i]; - if (entry_type == cla_table->type) - return cla_table; - } - - return NULL; -} diff --git a/drivers/scsi/spfc/hw/spfc_cqm_bat_cla.h b/drivers/scsi/spfc/hw/spfc_cqm_bat_cla.h deleted file mode 100644 index 85b060e7935c..000000000000 --- a/drivers/scsi/spfc/hw/spfc_cqm_bat_cla.h +++ /dev/null @@ -1,215 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPFC_CQM_BAT_CLA_H -#define SPFC_CQM_BAT_CLA_H - -/* When the connection check is enabled, the maximum number of connections - * supported by the chip is 1M - 63, which cannot reach 1M - */ -#define CQM_BAT_MAX_CONN_NUM (0x100000 - 63) -#define CQM_BAT_MAX_CACHE_CONN_NUM (0x100000 - 63) - -#define CLA_TABLE_PAGE_ORDER 0 -#define CQM_4K_PAGE_ORDER 0 -#define CQM_4K_PAGE_SIZE 4096 - -#define CQM_BAT_ENTRY_MAX 16 -#define CQM_BAT_ENTRY_SIZE 16 - -#define CQM_BAT_SIZE_FT_PF 192 -#define CQM_BAT_SIZE_FT_VF 112 - -#define CQM_BAT_INDEX0 0 -#define CQM_BAT_INDEX1 1 -#define CQM_BAT_INDEX2 2 -#define CQM_BAT_INDEX3 3 -#define CQM_BAT_INDEX4 4 -#define CQM_BAT_INDEX5 5 -#define CQM_BAT_INDEX6 6 -#define CQM_BAT_INDEX7 7 -#define CQM_BAT_INDEX8 8 -#define CQM_BAT_INDEX9 9 -#define CQM_BAT_INDEX10 10 -#define CQM_BAT_INDEX11 11 -#define CQM_BAT_INDEX12 12 -#define CQM_BAT_INDEX13 13 -#define CQM_BAT_INDEX14 14 -#define CQM_BAT_INDEX15 15 - -enum cqm_bat_entry_type { - CQM_BAT_ENTRY_T_CFG = 0, - CQM_BAT_ENTRY_T_HASH = 1, - CQM_BAT_ENTRY_T_QPC = 2, - CQM_BAT_ENTRY_T_SCQC = 3, - CQM_BAT_ENTRY_T_SRQC = 4, - CQM_BAT_ENTRY_T_MPT = 5, - CQM_BAT_ENTRY_T_GID = 6, - CQM_BAT_ENTRY_T_LUN = 7, - CQM_BAT_ENTRY_T_TASKMAP = 8, - CQM_BAT_ENTRY_T_L3I = 9, - CQM_BAT_ENTRY_T_CHILDC = 10, - CQM_BAT_ENTRY_T_TIMER = 11, - CQM_BAT_ENTRY_T_XID2CID = 12, - CQM_BAT_ENTRY_T_REORDER = 13, - CQM_BAT_ENTRY_T_INVALID = 14, - CQM_BAT_ENTRY_T_MAX = 15, -}; - -/* CLA update mode */ -#define CQM_CLA_RECORD_NEW_GPA 0 -#define CQM_CLA_DEL_GPA_WITHOUT_CACHE_INVALID 1 -#define CQM_CLA_DEL_GPA_WITH_CACHE_INVALID 2 - -#define CQM_CLA_LVL_0 0 -#define CQM_CLA_LVL_1 1 -#define CQM_CLA_LVL_2 2 - -#define CQM_MAX_INDEX_BIT 19 - -#define CQM_CHIP_CACHELINE 256 -#define CQM_CHIP_TIMER_CACHELINE 512 -#define CQM_OBJECT_256 256 -#define CQM_OBJECT_512 512 -#define CQM_OBJECT_1024 1024 -#define CQM_CHIP_GPA_MASK 0x1ffffffffffffff -#define CQM_CHIP_GPA_HIMASK 0x1ffffff -#define CQM_CHIP_GPA_LOMASK 0xffffffff -#define CQM_CHIP_GPA_HSHIFT 32 - -/* Aligns with 64 buckets and shifts rightward by 6 bits */ -#define CQM_HASH_NUMBER_UNIT 6 - -struct cqm_cla_table { - u32 type; - u32 max_buffer_size; - u32 obj_num; - bool alloc_static; /* Whether the buffer is statically allocated */ - u32 cla_lvl; - u32 cacheline_x; /* x value calculated based on cacheline, used by the chip */ - u32 cacheline_y; /* y value calculated based on cacheline, used by the chip */ - u32 cacheline_z; /* z value calculated based on cacheline, used by the chip */ - u32 x; /* x value calculated based on obj_size, used by software */ - u32 y; /* y value calculated based on obj_size, used by software */ - u32 z; /* z value calculated based on obj_size, used by software */ - struct cqm_buf cla_x_buf; - struct cqm_buf cla_y_buf; - struct cqm_buf cla_z_buf; - u32 trunk_order; /* A continuous physical page contains 2^order pages */ - u32 obj_size; - struct mutex lock; /* Lock for cla buffer allocation and free */ - - struct cqm_bitmap bitmap; - - struct cqm_object_table obj_table; /* Mapping table between indexes and objects */ -}; - -struct cqm_bat_entry_cfg { - u32 cur_conn_num_h_4 : 4; - u32 rsv1 : 4; - u32 max_conn_num : 20; - u32 rsv2 : 4; - - u32 max_conn_cache : 10; - u32 rsv3 : 6; - u32 cur_conn_num_l_16 : 16; - - u32 bloom_filter_addr : 16; - u32 cur_conn_cache : 10; - u32 rsv4 : 6; - - u32 bucket_num : 16; - u32 bloom_filter_len : 16; -}; - -#define CQM_BAT_NO_BYPASS_CACHE 0 -#define CQM_BAT_BYPASS_CACHE 1 - -#define CQM_BAT_ENTRY_SIZE_256 0 -#define CQM_BAT_ENTRY_SIZE_512 1 -#define CQM_BAT_ENTRY_SIZE_1024 2 - -struct cqm_bat_entry_standerd { - u32 entry_size : 2; - u32 rsv1 : 6; - u32 max_number : 20; - u32 rsv2 : 4; - - u32 cla_gpa_h : 32; - - u32 cla_gpa_l : 32; - - u32 rsv3 : 8; - u32 z : 5; - u32 y : 5; - u32 x : 5; - u32 rsv24 : 1; - u32 bypass : 1; - u32 cla_level : 2; - u32 rsv5 : 5; -}; - -struct cqm_bat_entry_vf2pf { - u32 cla_gpa_h : 25; - u32 pf_id : 5; - u32 fake_vf_en : 1; - u32 acs_spu_en : 1; -}; - -#define CQM_BAT_ENTRY_TASKMAP_NUM 4 -struct cqm_bat_entry_taskmap_addr { - u32 gpa_h; - u32 gpa_l; -}; - -struct cqm_bat_entry_taskmap { - struct cqm_bat_entry_taskmap_addr addr[CQM_BAT_ENTRY_TASKMAP_NUM]; -}; - -struct cqm_bat_table { - u32 bat_entry_type[CQM_BAT_ENTRY_MAX]; - u8 bat[CQM_BAT_ENTRY_MAX * CQM_BAT_ENTRY_SIZE]; - struct cqm_cla_table entry[CQM_BAT_ENTRY_MAX]; - /* In LB mode 1, the timer needs to be configured in 4 SMFs, - * and the GPAs must be different and independent. - */ - struct cqm_cla_table timer_entry[4]; - u32 bat_size; -}; - -#define CQM_BAT_MAX_SIZE 256 -struct cqm_cmdq_bat_update { - u32 offset; - u32 byte_len; - u8 data[CQM_BAT_MAX_SIZE]; - u32 smf_id; - u32 func_id; -}; - -struct cqm_cla_update_cmd { - /* Gpa address to be updated */ - u32 gpa_h; - u32 gpa_l; - - /* Updated Value */ - u32 value_h; - u32 value_l; - - u32 smf_id; - u32 func_id; -}; - -s32 cqm_bat_init(struct cqm_handle *cqm_handle); -void cqm_bat_uninit(struct cqm_handle *cqm_handle); -s32 cqm_cla_init(struct cqm_handle *cqm_handle); -void cqm_cla_uninit(struct cqm_handle *cqm_handle, u32 entry_numb); -u8 *cqm_cla_get_unlock(struct cqm_handle *cqm_handle, struct cqm_cla_table *cla_table, - u32 index, u32 count, dma_addr_t *pa); -u8 *cqm_cla_get_lock(struct cqm_handle *cqm_handle, struct cqm_cla_table *cla_table, - u32 index, u32 count, dma_addr_t *pa); -void cqm_cla_put(struct cqm_handle *cqm_handle, struct cqm_cla_table *cla_table, - u32 index, u32 count); -struct cqm_cla_table *cqm_cla_table_get(struct cqm_bat_table *bat_table, u32 entry_type); -u32 cqm_funcid2smfid(struct cqm_handle *cqm_handle); - -#endif /* SPFC_CQM_BAT_CLA_H */ diff --git a/drivers/scsi/spfc/hw/spfc_cqm_bitmap_table.c b/drivers/scsi/spfc/hw/spfc_cqm_bitmap_table.c deleted file mode 100644 index 21100e8db8f4..000000000000 --- a/drivers/scsi/spfc/hw/spfc_cqm_bitmap_table.c +++ /dev/null @@ -1,885 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#include <linux/types.h> -#include <linux/sched.h> -#include <linux/pci.h> -#include <linux/module.h> -#include <linux/vmalloc.h> -#include <linux/device.h> -#include <linux/mm.h> -#include <linux/gfp.h> - -#include "sphw_crm.h" -#include "sphw_hw.h" -#include "sphw_hwdev.h" -#include "sphw_hwif.h" - -#include "spfc_cqm_object.h" -#include "spfc_cqm_bitmap_table.h" -#include "spfc_cqm_bat_cla.h" -#include "spfc_cqm_main.h" - -#define common_section - -void cqm_swab64(u8 *addr, u32 cnt) -{ - u64 *temp = (u64 *)addr; - u64 value = 0; - u32 i; - - for (i = 0; i < cnt; i++) { - value = __swab64(*temp); - *temp = value; - temp++; - } -} - -void cqm_swab32(u8 *addr, u32 cnt) -{ - u32 *temp = (u32 *)addr; - u32 value = 0; - u32 i; - - for (i = 0; i < cnt; i++) { - value = __swab32(*temp); - *temp = value; - temp++; - } -} - -s32 cqm_shift(u32 data) -{ - s32 shift = -1; - - do { - data >>= 1; - shift++; - } while (data); - - return shift; -} - -bool cqm_check_align(u32 data) -{ - if (data == 0) - return false; - - do { - /* When the value can be exactly divided by 2, - * the value of data is shifted right by one bit, that is, - * divided by 2. - */ - if ((data & 0x1) == 0) - data >>= 1; - /* If the value cannot be divisible by 2, the value is - * not 2^n-aligned and false is returned. - */ - else - return false; - } while (data != 1); - - return true; -} - -void *cqm_kmalloc_align(size_t size, gfp_t flags, u16 align_order) -{ - void *orig_addr = NULL; - void *align_addr = NULL; - void *index_addr = NULL; - - orig_addr = kmalloc(size + ((u64)1 << align_order) + sizeof(void *), - flags); - if (!orig_addr) - return NULL; - - index_addr = (void *)((char *)orig_addr + sizeof(void *)); - align_addr = - (void *)((((u64)index_addr + ((u64)1 << align_order) - 1) >> - align_order) << align_order); - - /* Record the original memory address for memory release. */ - index_addr = (void *)((char *)align_addr - sizeof(void *)); - *(void **)index_addr = orig_addr; - - return align_addr; -} - -void cqm_kfree_align(void *addr) -{ - void *index_addr = NULL; - - /* Release the original memory address. */ - index_addr = (void *)((char *)addr - sizeof(void *)); - - kfree(*(void **)index_addr); -} - -void cqm_write_lock(rwlock_t *lock, bool bh) -{ - if (bh) - write_lock_bh(lock); - else - write_lock(lock); -} - -void cqm_write_unlock(rwlock_t *lock, bool bh) -{ - if (bh) - write_unlock_bh(lock); - else - write_unlock(lock); -} - -void cqm_read_lock(rwlock_t *lock, bool bh) -{ - if (bh) - read_lock_bh(lock); - else - read_lock(lock); -} - -void cqm_read_unlock(rwlock_t *lock, bool bh) -{ - if (bh) - read_unlock_bh(lock); - else - read_unlock(lock); -} - -s32 cqm_buf_alloc_direct(struct cqm_handle *cqm_handle, struct cqm_buf *buf, bool direct) -{ - struct sphw_hwdev *handle = cqm_handle->ex_handle; - struct page **pages = NULL; - u32 i, j, order; - - order = get_order(buf->buf_size); - - if (!direct) { - buf->direct.va = NULL; - return CQM_SUCCESS; - } - - pages = vmalloc(sizeof(struct page *) * buf->page_number); - if (!pages) { - cqm_err(handle->dev_hdl, CQM_ALLOC_FAIL(pages)); - return CQM_FAIL; - } - - for (i = 0; i < buf->buf_number; i++) { - for (j = 0; j < ((u32)1 << order); j++) - pages[(ulong)(unsigned int)((i << order) + j)] = - (void *)virt_to_page((u8 *)(buf->buf_list[i].va) + - (PAGE_SIZE * j)); - } - - buf->direct.va = vmap(pages, buf->page_number, VM_MAP, PAGE_KERNEL); - vfree(pages); - if (!buf->direct.va) { - cqm_err(handle->dev_hdl, CQM_MAP_FAIL(buf->direct.va)); - return CQM_FAIL; - } - - return CQM_SUCCESS; -} - -s32 cqm_buf_alloc_page(struct cqm_handle *cqm_handle, struct cqm_buf *buf) -{ - struct sphw_hwdev *handle = cqm_handle->ex_handle; - struct page *newpage = NULL; - u32 order; - void *va = NULL; - s32 i, node; - - order = get_order(buf->buf_size); - /* Page for applying for each buffer for non-ovs */ - if (handle->board_info.service_mode != 0) { - for (i = 0; i < (s32)buf->buf_number; i++) { - va = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, - order); - if (!va) { - cqm_err(handle->dev_hdl, - CQM_ALLOC_FAIL(buf_page)); - break; - } - /* Initialize the page after the page is applied for. - * If hash entries are involved, the initialization - * value must be 0. - */ - memset(va, 0, buf->buf_size); - buf->buf_list[i].va = va; - } - } else { - node = dev_to_node(handle->dev_hdl); - for (i = 0; i < (s32)buf->buf_number; i++) { - newpage = alloc_pages_node(node, - GFP_KERNEL | __GFP_ZERO, - order); - if (!newpage) { - cqm_err(handle->dev_hdl, - CQM_ALLOC_FAIL(buf_page)); - break; - } - va = (void *)page_address(newpage); - /* Initialize the page after the page is applied for. - * If hash entries are involved, the initialization - * value must be 0. - */ - memset(va, 0, buf->buf_size); - buf->buf_list[i].va = va; - } - } - - if (i != buf->buf_number) { - i--; - for (; i >= 0; i--) { - free_pages((ulong)(buf->buf_list[i].va), order); - buf->buf_list[i].va = NULL; - } - return CQM_FAIL; - } - - return CQM_SUCCESS; -} - -s32 cqm_buf_alloc_map(struct cqm_handle *cqm_handle, struct cqm_buf *buf) -{ - struct sphw_hwdev *handle = cqm_handle->ex_handle; - struct pci_dev *dev = cqm_handle->dev; - void *va = NULL; - s32 i; - - for (i = 0; i < (s32)buf->buf_number; i++) { - va = buf->buf_list[i].va; - buf->buf_list[i].pa = pci_map_single(dev, va, buf->buf_size, - PCI_DMA_BIDIRECTIONAL); - if (pci_dma_mapping_error(dev, buf->buf_list[i].pa)) { - cqm_err(handle->dev_hdl, CQM_MAP_FAIL(buf_list)); - break; - } - } - - if (i != buf->buf_number) { - i--; - for (; i >= 0; i--) - pci_unmap_single(dev, buf->buf_list[i].pa, - buf->buf_size, PCI_DMA_BIDIRECTIONAL); - return CQM_FAIL; - } - - return CQM_SUCCESS; -} - -s32 cqm_buf_alloc(struct cqm_handle *cqm_handle, struct cqm_buf *buf, bool direct) -{ - struct sphw_hwdev *handle = cqm_handle->ex_handle; - struct pci_dev *dev = cqm_handle->dev; - u32 order; - s32 i; - - order = get_order(buf->buf_size); - - /* Applying for the buffer list descriptor space */ - buf->buf_list = vmalloc(buf->buf_number * sizeof(struct cqm_buf_list)); - CQM_PTR_CHECK_RET(buf->buf_list, CQM_FAIL, - CQM_ALLOC_FAIL(linux_buf_list)); - memset(buf->buf_list, 0, buf->buf_number * sizeof(struct cqm_buf_list)); - - /* Page for applying for each buffer */ - if (cqm_buf_alloc_page(cqm_handle, buf) == CQM_FAIL) { - cqm_err(handle->dev_hdl, - CQM_FUNCTION_FAIL(linux_cqm_buf_alloc_page)); - goto err1; - } - - /* PCI mapping of the buffer */ - if (cqm_buf_alloc_map(cqm_handle, buf) == CQM_FAIL) { - cqm_err(handle->dev_hdl, - CQM_FUNCTION_FAIL(linux_cqm_buf_alloc_map)); - goto err2; - } - - /* direct remapping */ - if (cqm_buf_alloc_direct(cqm_handle, buf, direct) == CQM_FAIL) { - cqm_err(handle->dev_hdl, - CQM_FUNCTION_FAIL(cqm_buf_alloc_direct)); - goto err3; - } - - return CQM_SUCCESS; - -err3: - for (i = 0; i < (s32)buf->buf_number; i++) - pci_unmap_single(dev, buf->buf_list[i].pa, buf->buf_size, - PCI_DMA_BIDIRECTIONAL); -err2: - for (i = 0; i < (s32)buf->buf_number; i++) { - free_pages((ulong)(buf->buf_list[i].va), order); - buf->buf_list[i].va = NULL; - } -err1: - vfree(buf->buf_list); - buf->buf_list = NULL; - return CQM_FAIL; -} - -void cqm_buf_free(struct cqm_buf *buf, struct pci_dev *dev) -{ - u32 order; - s32 i; - - order = get_order(buf->buf_size); - - if (buf->direct.va) { - vunmap(buf->direct.va); - buf->direct.va = NULL; - } - - if (buf->buf_list) { - for (i = 0; i < (s32)(buf->buf_number); i++) { - if (buf->buf_list[i].va) { - pci_unmap_single(dev, buf->buf_list[i].pa, - buf->buf_size, - PCI_DMA_BIDIRECTIONAL); - - free_pages((ulong)(buf->buf_list[i].va), order); - buf->buf_list[i].va = NULL; - } - } - - vfree(buf->buf_list); - buf->buf_list = NULL; - } -} - -s32 cqm_cla_cache_invalid_cmd(struct cqm_handle *cqm_handle, struct cqm_cmd_buf *buf_in, - struct cqm_cla_cache_invalid_cmd *cmd) -{ - struct sphw_hwdev *handle = cqm_handle->ex_handle; - struct cqm_cla_cache_invalid_cmd *cla_cache_invalid_cmd = NULL; - s32 ret; - - cla_cache_invalid_cmd = (struct cqm_cla_cache_invalid_cmd *)(buf_in->buf); - cla_cache_invalid_cmd->gpa_h = cmd->gpa_h; - cla_cache_invalid_cmd->gpa_l = cmd->gpa_l; - cla_cache_invalid_cmd->cache_size = cmd->cache_size; - cla_cache_invalid_cmd->smf_id = cmd->smf_id; - cla_cache_invalid_cmd->func_id = cmd->func_id; - - cqm_swab32((u8 *)cla_cache_invalid_cmd, - /* shift 2 bits by right to get length of dw(4B) */ - (sizeof(struct cqm_cla_cache_invalid_cmd) >> 2)); - - /* Send the cmdq command. */ - ret = cqm3_send_cmd_box((void *)(cqm_handle->ex_handle), CQM_MOD_CQM, - CQM_CMD_T_CLA_CACHE_INVALID, buf_in, NULL, NULL, - CQM_CMD_TIMEOUT, SPHW_CHANNEL_DEFAULT); - if (ret != CQM_SUCCESS) { - cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm3_send_cmd_box)); - cqm_err(handle->dev_hdl, - "Cla cache invalid: cqm3_send_cmd_box_ret=%d\n", - ret); - cqm_err(handle->dev_hdl, - "Cla cache invalid: cla_cache_invalid_cmd: 0x%x 0x%x 0x%x\n", - cmd->gpa_h, cmd->gpa_l, cmd->cache_size); - return CQM_FAIL; - } - - return CQM_SUCCESS; -} - -s32 cqm_cla_cache_invalid(struct cqm_handle *cqm_handle, dma_addr_t gpa, u32 cache_size) -{ - struct sphw_hwdev *handle = cqm_handle->ex_handle; - struct cqm_cmd_buf *buf_in = NULL; - struct cqm_cla_cache_invalid_cmd cmd; - s32 ret = CQM_FAIL; - u32 i; - - buf_in = cqm3_cmd_alloc((void *)(cqm_handle->ex_handle)); - CQM_PTR_CHECK_RET(buf_in, CQM_FAIL, CQM_ALLOC_FAIL(buf_in)); - buf_in->size = sizeof(struct cqm_cla_cache_invalid_cmd); - - /* Fill command and convert it to big endian */ - cmd.cache_size = cache_size; - cmd.gpa_h = CQM_ADDR_HI(gpa); - cmd.gpa_l = CQM_ADDR_LW(gpa); - - /* In non-fake mode, set func_id to 0xffff. */ - cmd.func_id = 0xffff; - - /* Mode 0 is hashed to 4 SMF engines (excluding PPF) by func ID. */ - if (cqm_handle->func_capability.lb_mode == CQM_LB_MODE_NORMAL || - (cqm_handle->func_capability.lb_mode == CQM_LB_MODE_0 && - cqm_handle->func_attribute.func_type != CQM_PPF)) { - cmd.smf_id = cqm_funcid2smfid(cqm_handle); - ret = cqm_cla_cache_invalid_cmd(cqm_handle, buf_in, &cmd); - } - /* Mode 1/2 are allocated to 4 SMF engines by flow. Therefore, - * one function needs to be allocated to 4 SMF engines. - */ - /* The PPF in mode 0 needs to be configured on 4 engines, - * and the timer resources need to be shared by the 4 engines. - */ - else if (cqm_handle->func_capability.lb_mode == CQM_LB_MODE_1 || - cqm_handle->func_capability.lb_mode == CQM_LB_MODE_2 || - (cqm_handle->func_capability.lb_mode == CQM_LB_MODE_0 && - cqm_handle->func_attribute.func_type == CQM_PPF)) { - for (i = 0; i < CQM_LB_SMF_MAX; i++) { - /* The smf_pg stored currently enabled SMF engine. */ - if (cqm_handle->func_capability.smf_pg & (1U << i)) { - cmd.smf_id = i; - ret = cqm_cla_cache_invalid_cmd(cqm_handle, - buf_in, &cmd); - if (ret != CQM_SUCCESS) - goto out; - } - } - } else { - cqm_err(handle->dev_hdl, "Cla cache invalid: unsupport lb mode=%u\n", - cqm_handle->func_capability.lb_mode); - ret = CQM_FAIL; - } - -out: - cqm3_cmd_free((void *)(cqm_handle->ex_handle), buf_in); - return ret; -} - -static void free_cache_inv(struct cqm_handle *cqm_handle, struct cqm_buf *buf, - s32 *inv_flag) -{ - struct sphw_hwdev *handle = cqm_handle->ex_handle; - u32 order; - s32 i; - - order = get_order(buf->buf_size); - - if (!handle->chip_present_flag) - return; - - if (!buf->buf_list) - return; - - for (i = 0; i < (s32)(buf->buf_number); i++) { - if (!buf->buf_list[i].va) - continue; - - if (*inv_flag != CQM_SUCCESS) - continue; - - /* In the Pangea environment, if the cmdq times out, - * no subsequent message is sent. - */ - *inv_flag = cqm_cla_cache_invalid(cqm_handle, buf->buf_list[i].pa, - (u32)(PAGE_SIZE << order)); - if (*inv_flag != CQM_SUCCESS) - cqm_err(handle->dev_hdl, - "Buffer free: fail to invalid buf_list pa cache, inv_flag=%d\n", - *inv_flag); - } -} - -void cqm_buf_free_cache_inv(struct cqm_handle *cqm_handle, struct cqm_buf *buf, - s32 *inv_flag) -{ - /* Send a command to the chip to kick out the cache. */ - free_cache_inv(cqm_handle, buf, inv_flag); - - /* Clear host resources */ - cqm_buf_free(buf, cqm_handle->dev); -} - -#define bitmap_section - -s32 cqm_single_bitmap_init(struct cqm_bitmap *bitmap) -{ - u32 bit_number; - - spin_lock_init(&bitmap->lock); - - /* Max_num of the bitmap is 8-aligned and then - * shifted rightward by 3 bits to obtain the number of bytes required. - */ - bit_number = (ALIGN(bitmap->max_num, CQM_NUM_BIT_BYTE) >> CQM_BYTE_BIT_SHIFT); - bitmap->table = vmalloc(bit_number); - CQM_PTR_CHECK_RET(bitmap->table, CQM_FAIL, CQM_ALLOC_FAIL(bitmap->table)); - memset(bitmap->table, 0, bit_number); - - return CQM_SUCCESS; -} - -s32 cqm_bitmap_init(struct cqm_handle *cqm_handle) -{ - struct cqm_func_capability *capability = &cqm_handle->func_capability; - struct cqm_bat_table *bat_table = &cqm_handle->bat_table; - struct sphw_hwdev *handle = cqm_handle->ex_handle; - struct cqm_cla_table *cla_table = NULL; - struct cqm_bitmap *bitmap = NULL; - s32 ret = CQM_SUCCESS; - u32 i; - - for (i = 0; i < CQM_BAT_ENTRY_MAX; i++) { - cla_table = &bat_table->entry[i]; - if (cla_table->obj_num == 0) { - cqm_info(handle->dev_hdl, - "Cla alloc: cla_type %u, obj_num=0, don't init bitmap\n", - cla_table->type); - continue; - } - - bitmap = &cla_table->bitmap; - - switch (cla_table->type) { - case CQM_BAT_ENTRY_T_QPC: - bitmap->max_num = capability->qpc_number; - bitmap->reserved_top = capability->qpc_reserved; - bitmap->last = capability->qpc_reserved; - cqm_info(handle->dev_hdl, - "Bitmap init: cla_table_type=%u, max_num=0x%x\n", - cla_table->type, bitmap->max_num); - ret = cqm_single_bitmap_init(bitmap); - break; - case CQM_BAT_ENTRY_T_MPT: - bitmap->max_num = capability->mpt_number; - bitmap->reserved_top = capability->mpt_reserved; - bitmap->last = capability->mpt_reserved; - cqm_info(handle->dev_hdl, - "Bitmap init: cla_table_type=%u, max_num=0x%x\n", - cla_table->type, bitmap->max_num); - ret = cqm_single_bitmap_init(bitmap); - break; - case CQM_BAT_ENTRY_T_SCQC: - bitmap->max_num = capability->scqc_number; - bitmap->reserved_top = capability->scq_reserved; - bitmap->last = capability->scq_reserved; - cqm_info(handle->dev_hdl, - "Bitmap init: cla_table_type=%u, max_num=0x%x\n", - cla_table->type, bitmap->max_num); - ret = cqm_single_bitmap_init(bitmap); - break; - case CQM_BAT_ENTRY_T_SRQC: - bitmap->max_num = capability->srqc_number; - bitmap->reserved_top = capability->srq_reserved; - bitmap->last = capability->srq_reserved; - cqm_info(handle->dev_hdl, - "Bitmap init: cla_table_type=%u, max_num=0x%x\n", - cla_table->type, bitmap->max_num); - ret = cqm_single_bitmap_init(bitmap); - break; - default: - break; - } - - if (ret != CQM_SUCCESS) { - cqm_err(handle->dev_hdl, - "Bitmap init: failed to init cla_table_type=%u, obj_num=0x%x\n", - cla_table->type, cla_table->obj_num); - goto err; - } - } - - return CQM_SUCCESS; - -err: - cqm_bitmap_uninit(cqm_handle); - return CQM_FAIL; -} - -void cqm_bitmap_uninit(struct cqm_handle *cqm_handle) -{ - struct cqm_bat_table *bat_table = &cqm_handle->bat_table; - struct cqm_cla_table *cla_table = NULL; - struct cqm_bitmap *bitmap = NULL; - u32 i; - - for (i = 0; i < CQM_BAT_ENTRY_MAX; i++) { - cla_table = &bat_table->entry[i]; - bitmap = &cla_table->bitmap; - if (cla_table->type != CQM_BAT_ENTRY_T_INVALID) { - if (bitmap->table) { - vfree(bitmap->table); - bitmap->table = NULL; - } - } - } -} - -u32 cqm_bitmap_check_range(const ulong *table, u32 step, u32 max_num, u32 begin, - u32 count) -{ - u32 end = (begin + (count - 1)); - u32 i; - - /* Single-bit check is not performed. */ - if (count == 1) - return begin; - - /* The end value exceeds the threshold. */ - if (end >= max_num) - return max_num; - - /* Bit check, the next bit is returned when a non-zero bit is found. */ - for (i = (begin + 1); i <= end; i++) { - if (test_bit((s32)i, table)) - return i + 1; - } - - /* Check whether it's in different steps. */ - if ((begin & (~(step - 1))) != (end & (~(step - 1)))) - return (end & (~(step - 1))); - - /* If the check succeeds, begin is returned. */ - return begin; -} - -void cqm_bitmap_find(struct cqm_bitmap *bitmap, u32 *index, u32 last, u32 step, u32 count) -{ - u32 max_num = bitmap->max_num; - ulong *table = bitmap->table; - - do { - *index = (u32)find_next_zero_bit(table, max_num, last); - if (*index < max_num) - last = cqm_bitmap_check_range(table, step, max_num, - *index, count); - else - break; - } while (last != *index); -} - -u32 cqm_bitmap_alloc(struct cqm_bitmap *bitmap, u32 step, u32 count, bool update_last) -{ - u32 index = 0; - u32 max_num = bitmap->max_num; - u32 last = bitmap->last; - ulong *table = bitmap->table; - u32 i; - - spin_lock(&bitmap->lock); - - /* Search for an idle bit from the last position. */ - cqm_bitmap_find(bitmap, &index, last, step, count); - - /* The preceding search fails. Search for an idle bit - * from the beginning. - */ - if (index >= max_num) { - last = bitmap->reserved_top; - cqm_bitmap_find(bitmap, &index, last, step, count); - } - - /* Set the found bit to 1 and reset last. */ - if (index < max_num) { - for (i = index; i < (index + count); i++) - set_bit(i, table); - - if (update_last) { - bitmap->last = (index + count); - if (bitmap->last >= bitmap->max_num) - bitmap->last = bitmap->reserved_top; - } - } - - spin_unlock(&bitmap->lock); - return index; -} - -u32 cqm_bitmap_alloc_reserved(struct cqm_bitmap *bitmap, u32 count, u32 index) -{ - ulong *table = bitmap->table; - u32 ret_index; - - if (index >= bitmap->reserved_top || index >= bitmap->max_num || count != 1) - return CQM_INDEX_INVALID; - - spin_lock(&bitmap->lock); - - if (test_bit((s32)index, table)) { - ret_index = CQM_INDEX_INVALID; - } else { - set_bit(index, table); - ret_index = index; - } - - spin_unlock(&bitmap->lock); - return ret_index; -} - -void cqm_bitmap_free(struct cqm_bitmap *bitmap, u32 index, u32 count) -{ - u32 i; - - spin_lock(&bitmap->lock); - - for (i = index; i < (index + count); i++) - clear_bit((s32)i, bitmap->table); - - spin_unlock(&bitmap->lock); -} - -#define obj_table_section -s32 cqm_single_object_table_init(struct cqm_object_table *obj_table) -{ - rwlock_init(&obj_table->lock); - - obj_table->table = vmalloc(obj_table->max_num * sizeof(void *)); - CQM_PTR_CHECK_RET(obj_table->table, CQM_FAIL, CQM_ALLOC_FAIL(table)); - memset(obj_table->table, 0, obj_table->max_num * sizeof(void *)); - return CQM_SUCCESS; -} - -s32 cqm_object_table_init(struct cqm_handle *cqm_handle) -{ - struct cqm_func_capability *capability = &cqm_handle->func_capability; - struct cqm_bat_table *bat_table = &cqm_handle->bat_table; - struct sphw_hwdev *handle = cqm_handle->ex_handle; - struct cqm_object_table *obj_table = NULL; - struct cqm_cla_table *cla_table = NULL; - s32 ret = CQM_SUCCESS; - u32 i; - - for (i = 0; i < CQM_BAT_ENTRY_MAX; i++) { - cla_table = &bat_table->entry[i]; - if (cla_table->obj_num == 0) { - cqm_info(handle->dev_hdl, - "Obj table init: cla_table_type %u, obj_num=0, don't init obj table\n", - cla_table->type); - continue; - } - - obj_table = &cla_table->obj_table; - - switch (cla_table->type) { - case CQM_BAT_ENTRY_T_QPC: - obj_table->max_num = capability->qpc_number; - ret = cqm_single_object_table_init(obj_table); - break; - case CQM_BAT_ENTRY_T_MPT: - obj_table->max_num = capability->mpt_number; - ret = cqm_single_object_table_init(obj_table); - break; - case CQM_BAT_ENTRY_T_SCQC: - obj_table->max_num = capability->scqc_number; - ret = cqm_single_object_table_init(obj_table); - break; - case CQM_BAT_ENTRY_T_SRQC: - obj_table->max_num = capability->srqc_number; - ret = cqm_single_object_table_init(obj_table); - break; - default: - break; - } - - if (ret != CQM_SUCCESS) { - cqm_err(handle->dev_hdl, - "Obj table init: failed to init cla_table_type=%u, obj_num=0x%x\n", - cla_table->type, cla_table->obj_num); - goto err; - } - } - - return CQM_SUCCESS; - -err: - cqm_object_table_uninit(cqm_handle); - return CQM_FAIL; -} - -void cqm_object_table_uninit(struct cqm_handle *cqm_handle) -{ - struct cqm_bat_table *bat_table = &cqm_handle->bat_table; - struct cqm_object_table *obj_table = NULL; - struct cqm_cla_table *cla_table = NULL; - u32 i; - - for (i = 0; i < CQM_BAT_ENTRY_MAX; i++) { - cla_table = &bat_table->entry[i]; - obj_table = &cla_table->obj_table; - if (cla_table->type != CQM_BAT_ENTRY_T_INVALID) { - if (obj_table->table) { - vfree(obj_table->table); - obj_table->table = NULL; - } - } - } -} - -s32 cqm_object_table_insert(struct cqm_handle *cqm_handle, - struct cqm_object_table *object_table, - u32 index, struct cqm_object *obj, bool bh) -{ - struct sphw_hwdev *handle = cqm_handle->ex_handle; - - if (index >= object_table->max_num) { - cqm_err(handle->dev_hdl, - "Obj table insert: index 0x%x exceeds max_num 0x%x\n", - index, object_table->max_num); - return CQM_FAIL; - } - - cqm_write_lock(&object_table->lock, bh); - - if (!object_table->table[index]) { - object_table->table[index] = obj; - cqm_write_unlock(&object_table->lock, bh); - return CQM_SUCCESS; - } - - cqm_write_unlock(&object_table->lock, bh); - cqm_err(handle->dev_hdl, - "Obj table insert: object_table->table[0x%x] has been inserted\n", - index); - - return CQM_FAIL; -} - -void cqm_object_table_remove(struct cqm_handle *cqm_handle, - struct cqm_object_table *object_table, - u32 index, const struct cqm_object *obj, bool bh) -{ - struct sphw_hwdev *handle = cqm_handle->ex_handle; - - if (index >= object_table->max_num) { - cqm_err(handle->dev_hdl, - "Obj table remove: index 0x%x exceeds max_num 0x%x\n", - index, object_table->max_num); - return; - } - - cqm_write_lock(&object_table->lock, bh); - - if (object_table->table[index] && object_table->table[index] == obj) - object_table->table[index] = NULL; - else - cqm_err(handle->dev_hdl, - "Obj table remove: object_table->table[0x%x] has been removed\n", - index); - - cqm_write_unlock(&object_table->lock, bh); -} - -struct cqm_object *cqm_object_table_get(struct cqm_handle *cqm_handle, - struct cqm_object_table *object_table, - u32 index, bool bh) -{ - struct sphw_hwdev *handle = cqm_handle->ex_handle; - struct cqm_object *obj = NULL; - - if (index >= object_table->max_num) { - cqm_err(handle->dev_hdl, - "Obj table get: index 0x%x exceeds max_num 0x%x\n", - index, object_table->max_num); - return NULL; - } - - cqm_read_lock(&object_table->lock, bh); - - obj = object_table->table[index]; - if (obj) - atomic_inc(&obj->refcount); - - cqm_read_unlock(&object_table->lock, bh); - - return obj; -} diff --git a/drivers/scsi/spfc/hw/spfc_cqm_bitmap_table.h b/drivers/scsi/spfc/hw/spfc_cqm_bitmap_table.h deleted file mode 100644 index 5ae554eac54a..000000000000 --- a/drivers/scsi/spfc/hw/spfc_cqm_bitmap_table.h +++ /dev/null @@ -1,65 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPFC_CQM_BITMAP_TABLE_H -#define SPFC_CQM_BITMAP_TABLE_H - -struct cqm_bitmap { - ulong *table; - u32 max_num; - u32 last; - u32 reserved_top; /* reserved index */ - spinlock_t lock; -}; - -struct cqm_object_table { - /* Now is big array. Later will be optimized as a red-black tree. */ - struct cqm_object **table; - u32 max_num; - rwlock_t lock; -}; - -struct cqm_cla_cache_invalid_cmd { - u32 gpa_h; - u32 gpa_l; - - u32 cache_size; /* CLA cache size=4096B */ - - u32 smf_id; - u32 func_id; -}; - -struct cqm_handle; - -s32 cqm_bitmap_init(struct cqm_handle *cqm_handle); -void cqm_bitmap_uninit(struct cqm_handle *cqm_handle); -u32 cqm_bitmap_alloc(struct cqm_bitmap *bitmap, u32 step, u32 count, bool update_last); -u32 cqm_bitmap_alloc_reserved(struct cqm_bitmap *bitmap, u32 count, u32 index); -void cqm_bitmap_free(struct cqm_bitmap *bitmap, u32 index, u32 count); -s32 cqm_object_table_init(struct cqm_handle *cqm_handle); -void cqm_object_table_uninit(struct cqm_handle *cqm_handle); -s32 cqm_object_table_insert(struct cqm_handle *cqm_handle, - struct cqm_object_table *object_table, - u32 index, struct cqm_object *obj, bool bh); -void cqm_object_table_remove(struct cqm_handle *cqm_handle, - struct cqm_object_table *object_table, - u32 index, const struct cqm_object *obj, bool bh); -struct cqm_object *cqm_object_table_get(struct cqm_handle *cqm_handle, - struct cqm_object_table *object_table, - u32 index, bool bh); - -void cqm_swab64(u8 *addr, u32 cnt); -void cqm_swab32(u8 *addr, u32 cnt); -bool cqm_check_align(u32 data); -s32 cqm_shift(u32 data); -s32 cqm_buf_alloc(struct cqm_handle *cqm_handle, struct cqm_buf *buf, bool direct); -s32 cqm_buf_alloc_direct(struct cqm_handle *cqm_handle, struct cqm_buf *buf, bool direct); -void cqm_buf_free(struct cqm_buf *buf, struct pci_dev *dev); -void cqm_buf_free_cache_inv(struct cqm_handle *cqm_handle, struct cqm_buf *buf, - s32 *inv_flag); -s32 cqm_cla_cache_invalid(struct cqm_handle *cqm_handle, dma_addr_t gpa, - u32 cache_size); -void *cqm_kmalloc_align(size_t size, gfp_t flags, u16 align_order); -void cqm_kfree_align(void *addr); - -#endif diff --git a/drivers/scsi/spfc/hw/spfc_cqm_main.c b/drivers/scsi/spfc/hw/spfc_cqm_main.c deleted file mode 100644 index 52cc2c7838e9..000000000000 --- a/drivers/scsi/spfc/hw/spfc_cqm_main.c +++ /dev/null @@ -1,987 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#include <linux/types.h> -#include <linux/sched.h> -#include <linux/pci.h> -#include <linux/module.h> -#include <linux/delay.h> -#include <linux/vmalloc.h> - -#include "sphw_crm.h" -#include "sphw_hw.h" -#include "sphw_hw_cfg.h" -#include "spfc_cqm_main.h" - -s32 cqm3_init(void *ex_handle) -{ - struct sphw_hwdev *handle = (struct sphw_hwdev *)ex_handle; - struct cqm_handle *cqm_handle = NULL; - s32 ret; - - CQM_PTR_CHECK_RET(ex_handle, CQM_FAIL, CQM_PTR_NULL(ex_handle)); - - cqm_handle = kmalloc(sizeof(*cqm_handle), GFP_KERNEL | __GFP_ZERO); - CQM_PTR_CHECK_RET(cqm_handle, CQM_FAIL, CQM_ALLOC_FAIL(cqm_handle)); - - /* Clear the memory to prevent other systems from - * not clearing the memory. - */ - memset(cqm_handle, 0, sizeof(struct cqm_handle)); - - cqm_handle->ex_handle = handle; - cqm_handle->dev = (struct pci_dev *)(handle->pcidev_hdl); - handle->cqm_hdl = (void *)cqm_handle; - - /* Clearing Statistics */ - memset(&handle->hw_stats.cqm_stats, 0, sizeof(struct cqm_stats)); - - /* Reads VF/PF information. */ - cqm_handle->func_attribute = handle->hwif->attr; - cqm_info(handle->dev_hdl, "Func init: function[%u] type %d(0:PF,1:VF,2:PPF)\n", - cqm_handle->func_attribute.func_global_idx, - cqm_handle->func_attribute.func_type); - - /* Read capability from configuration management module */ - ret = cqm_capability_init(ex_handle); - if (ret == CQM_FAIL) { - cqm_err(handle->dev_hdl, - CQM_FUNCTION_FAIL(cqm_capability_init)); - goto err1; - } - - /* Initialize memory entries such as BAT, CLA, and bitmap. */ - if (cqm_mem_init(ex_handle) != CQM_SUCCESS) { - cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_mem_init)); - goto err1; - } - - /* Event callback initialization */ - if (cqm_event_init(ex_handle) != CQM_SUCCESS) { - cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_event_init)); - goto err2; - } - - /* Doorbell initiation */ - if (cqm_db_init(ex_handle) != CQM_SUCCESS) { - cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_db_init)); - goto err3; - } - - /* Initialize the bloom filter. */ - if (cqm_bloomfilter_init(ex_handle) != CQM_SUCCESS) { - cqm_err(handle->dev_hdl, - CQM_FUNCTION_FAIL(cqm_bloomfilter_init)); - goto err4; - } - - /* The timer bitmap is set directly at the beginning of the CQM. - * The ifconfig up/down command is not used to set or clear the bitmap. - */ - if (sphw_func_tmr_bitmap_set(ex_handle, true) != CQM_SUCCESS) { - cqm_err(handle->dev_hdl, "Timer start: enable timer bitmap failed\n"); - goto err5; - } - - return CQM_SUCCESS; - -err5: - cqm_bloomfilter_uninit(ex_handle); -err4: - cqm_db_uninit(ex_handle); -err3: - cqm_event_uninit(ex_handle); -err2: - cqm_mem_uninit(ex_handle); -err1: - handle->cqm_hdl = NULL; - kfree(cqm_handle); - return CQM_FAIL; -} - -void cqm3_uninit(void *ex_handle) -{ - struct sphw_hwdev *handle = (struct sphw_hwdev *)ex_handle; - struct cqm_handle *cqm_handle = NULL; - s32 ret; - - CQM_PTR_CHECK_NO_RET(ex_handle, CQM_PTR_NULL(ex_handle)); - - cqm_handle = (struct cqm_handle *)(handle->cqm_hdl); - CQM_PTR_CHECK_NO_RET(cqm_handle, CQM_PTR_NULL(cqm_handle)); - - /* The timer bitmap is set directly at the beginning of the CQM. - * The ifconfig up/down command is not used to set or clear the bitmap. - */ - cqm_info(handle->dev_hdl, "Timer stop: disable timer\n"); - if (sphw_func_tmr_bitmap_set(ex_handle, false) != CQM_SUCCESS) - cqm_err(handle->dev_hdl, "Timer stop: disable timer bitmap failed\n"); - - /* After the TMR timer stops, the system releases resources - * after a delay of one or two milliseconds. - */ - if (cqm_handle->func_attribute.func_type == CQM_PPF && - cqm_handle->func_capability.timer_enable == CQM_TIMER_ENABLE) { - cqm_info(handle->dev_hdl, "Timer stop: spfc ppf timer stop\n"); - ret = sphw_ppf_tmr_stop(handle); - if (ret != CQM_SUCCESS) - /* The timer fails to be stopped, - * and the resource release is not affected. - */ - cqm_info(handle->dev_hdl, "Timer stop: spfc ppf timer stop, ret=%d\n", - ret); - /* Somebody requires a delay of 1 ms, which is inaccurate. */ - usleep_range(900, 1000); - } - - /* Release Bloom Filter Table */ - cqm_bloomfilter_uninit(ex_handle); - - /* Release hardware doorbell */ - cqm_db_uninit(ex_handle); - - /* Cancel the callback of the event */ - cqm_event_uninit(ex_handle); - - /* Release various memory tables and require the service - * to release all objects. - */ - cqm_mem_uninit(ex_handle); - - /* Release cqm_handle */ - handle->cqm_hdl = NULL; - kfree(cqm_handle); -} - -void cqm_test_mode_init(struct cqm_handle *cqm_handle, - struct service_cap *service_capability) -{ - struct cqm_func_capability *func_cap = &cqm_handle->func_capability; - struct sphw_hwdev *handle = cqm_handle->ex_handle; - - if (service_capability->test_mode == 0) - return; - - cqm_info(handle->dev_hdl, "Enter CQM test mode\n"); - - func_cap->qpc_number = service_capability->test_qpc_num; - func_cap->qpc_reserved = - GET_MAX(func_cap->qpc_reserved, - service_capability->test_qpc_resvd_num); - func_cap->xid_alloc_mode = service_capability->test_xid_alloc_mode; - func_cap->gpa_check_enable = service_capability->test_gpa_check_enable; - func_cap->pagesize_reorder = service_capability->test_page_size_reorder; - func_cap->qpc_alloc_static = - (bool)(service_capability->test_qpc_alloc_mode); - func_cap->scqc_alloc_static = - (bool)(service_capability->test_scqc_alloc_mode); - func_cap->flow_table_based_conn_number = - service_capability->test_max_conn_num; - func_cap->flow_table_based_conn_cache_number = - service_capability->test_max_cache_conn_num; - func_cap->scqc_number = service_capability->test_scqc_num; - func_cap->mpt_number = service_capability->test_mpt_num; - func_cap->mpt_reserved = service_capability->test_mpt_recvd_num; - func_cap->reorder_number = service_capability->test_reorder_num; - /* 256K buckets, 256K*64B = 16MB */ - func_cap->hash_number = service_capability->test_hash_num; -} - -void cqm_service_capability_update(struct cqm_handle *cqm_handle) -{ - struct cqm_func_capability *func_cap = &cqm_handle->func_capability; - - func_cap->qpc_number = GET_MIN(CQM_MAX_QPC_NUM, func_cap->qpc_number); - func_cap->scqc_number = GET_MIN(CQM_MAX_SCQC_NUM, func_cap->scqc_number); - func_cap->srqc_number = GET_MIN(CQM_MAX_SRQC_NUM, func_cap->srqc_number); - func_cap->childc_number = GET_MIN(CQM_MAX_CHILDC_NUM, func_cap->childc_number); -} - -void cqm_service_valid_init(struct cqm_handle *cqm_handle, - struct service_cap *service_capability) -{ - enum cfg_svc_type_en type = service_capability->chip_svc_type; - struct cqm_service *svc = cqm_handle->service; - - svc[CQM_SERVICE_T_FC].valid = ((u32)type & CFG_SVC_FC_BIT5) ? true : false; -} - -void cqm_service_capability_init_fc(struct cqm_handle *cqm_handle, void *pra) -{ - struct cqm_func_capability *func_cap = &cqm_handle->func_capability; - struct service_cap *service_capability = (struct service_cap *)pra; - struct fc_service_cap *fc_cap = &service_capability->fc_cap; - struct dev_fc_svc_cap *dev_fc_cap = &fc_cap->dev_fc_cap; - struct sphw_hwdev *handle = cqm_handle->ex_handle; - - cqm_info(handle->dev_hdl, "Cap init: fc is valid\n"); - cqm_info(handle->dev_hdl, "Cap init: fc qpc 0x%x, scqc 0x%x, srqc 0x%x\n", - dev_fc_cap->max_parent_qpc_num, dev_fc_cap->scq_num, - dev_fc_cap->srq_num); - func_cap->hash_number += dev_fc_cap->max_parent_qpc_num; - func_cap->hash_basic_size = CQM_HASH_BUCKET_SIZE_64; - func_cap->qpc_number += dev_fc_cap->max_parent_qpc_num; - func_cap->qpc_basic_size = GET_MAX(fc_cap->parent_qpc_size, - func_cap->qpc_basic_size); - func_cap->qpc_alloc_static = true; - func_cap->scqc_number += dev_fc_cap->scq_num; - func_cap->scqc_basic_size = GET_MAX(fc_cap->scqc_size, - func_cap->scqc_basic_size); - func_cap->srqc_number += dev_fc_cap->srq_num; - func_cap->srqc_basic_size = GET_MAX(fc_cap->srqc_size, - func_cap->srqc_basic_size); - func_cap->lun_number = CQM_LUN_FC_NUM; - func_cap->lun_basic_size = CQM_LUN_SIZE_8; - func_cap->taskmap_number = CQM_TASKMAP_FC_NUM; - func_cap->taskmap_basic_size = PAGE_SIZE; - func_cap->childc_number += dev_fc_cap->max_child_qpc_num; - func_cap->childc_basic_size = GET_MAX(fc_cap->child_qpc_size, - func_cap->childc_basic_size); - func_cap->pagesize_reorder = CQM_FC_PAGESIZE_ORDER; -} - -void cqm_service_capability_init(struct cqm_handle *cqm_handle, - struct service_cap *service_capability) -{ - struct sphw_hwdev *handle = cqm_handle->ex_handle; - u32 i; - - for (i = 0; i < CQM_SERVICE_T_MAX; i++) { - cqm_handle->service[i].valid = false; - cqm_handle->service[i].has_register = false; - cqm_handle->service[i].buf_order = 0; - } - - cqm_service_valid_init(cqm_handle, service_capability); - - cqm_info(handle->dev_hdl, "Cap init: service type %d\n", - service_capability->chip_svc_type); - - if (cqm_handle->service[CQM_SERVICE_T_FC].valid) - cqm_service_capability_init_fc(cqm_handle, (void *)service_capability); -} - -/* Set func_type in fake_cqm_handle to ppf, pf, or vf. */ -void cqm_set_func_type(struct cqm_handle *cqm_handle) -{ - u32 idx = cqm_handle->func_attribute.func_global_idx; - - if (idx == 0) - cqm_handle->func_attribute.func_type = CQM_PPF; - else if (idx < CQM_MAX_PF_NUM) - cqm_handle->func_attribute.func_type = CQM_PF; - else - cqm_handle->func_attribute.func_type = CQM_VF; -} - -void cqm_lb_fake_mode_init(struct cqm_handle *cqm_handle, struct service_cap *svc_cap) -{ - struct cqm_func_capability *func_cap = &cqm_handle->func_capability; - - func_cap->lb_mode = svc_cap->lb_mode; - - /* Initializing the LB Mode */ - if (func_cap->lb_mode == CQM_LB_MODE_NORMAL) - func_cap->smf_pg = 0; - else - func_cap->smf_pg = svc_cap->smf_pg; - - func_cap->fake_cfg_number = 0; - func_cap->fake_func_type = CQM_FAKE_FUNC_NORMAL; -} - -s32 cqm_capability_init(void *ex_handle) -{ - struct sphw_hwdev *handle = (struct sphw_hwdev *)ex_handle; - struct cqm_handle *cqm_handle = (struct cqm_handle *)(handle->cqm_hdl); - struct service_cap *service_capability = &handle->cfg_mgmt->svc_cap; - struct sphw_func_attr *func_attr = &cqm_handle->func_attribute; - struct cqm_func_capability *func_cap = &cqm_handle->func_capability; - u32 total_function_num = 0; - int err = 0; - - /* Initializes the PPF capabilities: include timer, pf, vf. */ - if (func_attr->func_type == CQM_PPF) { - total_function_num = service_capability->host_total_function; - func_cap->timer_enable = service_capability->timer_en; - func_cap->pf_num = service_capability->pf_num; - func_cap->pf_id_start = service_capability->pf_id_start; - func_cap->vf_num = service_capability->vf_num; - func_cap->vf_id_start = service_capability->vf_id_start; - - cqm_info(handle->dev_hdl, "Cap init: total function num 0x%x\n", - total_function_num); - cqm_info(handle->dev_hdl, "Cap init: pf_num 0x%x, pf_id_start 0x%x, vf_num 0x%x, vf_id_start 0x%x\n", - func_cap->pf_num, func_cap->pf_id_start, - func_cap->vf_num, func_cap->vf_id_start); - cqm_info(handle->dev_hdl, "Cap init: timer_enable %u (1: enable; 0: disable)\n", - func_cap->timer_enable); - } - - func_cap->flow_table_based_conn_number = service_capability->max_connect_num; - func_cap->flow_table_based_conn_cache_number = service_capability->max_stick2cache_num; - cqm_info(handle->dev_hdl, "Cap init: cfg max_conn_num 0x%x, max_cache_conn_num 0x%x\n", - func_cap->flow_table_based_conn_number, - func_cap->flow_table_based_conn_cache_number); - - func_cap->bloomfilter_enable = service_capability->bloomfilter_en; - cqm_info(handle->dev_hdl, "Cap init: bloomfilter_enable %u (1: enable; 0: disable)\n", - func_cap->bloomfilter_enable); - - if (func_cap->bloomfilter_enable) { - func_cap->bloomfilter_length = service_capability->bfilter_len; - func_cap->bloomfilter_addr = - service_capability->bfilter_start_addr; - if (func_cap->bloomfilter_length != 0 && - !cqm_check_align(func_cap->bloomfilter_length)) { - cqm_err(handle->dev_hdl, "Cap init: bloomfilter_length %u is not the power of 2\n", - func_cap->bloomfilter_length); - - err = CQM_FAIL; - goto out; - } - } - - cqm_info(handle->dev_hdl, "Cap init: bloomfilter_length 0x%x, bloomfilter_addr 0x%x\n", - func_cap->bloomfilter_length, func_cap->bloomfilter_addr); - - func_cap->qpc_reserved = 0; - func_cap->mpt_reserved = 0; - func_cap->scq_reserved = 0; - func_cap->srq_reserved = 0; - func_cap->qpc_alloc_static = false; - func_cap->scqc_alloc_static = false; - - func_cap->l3i_number = CQM_L3I_COMM_NUM; - func_cap->l3i_basic_size = CQM_L3I_SIZE_8; - - func_cap->timer_number = CQM_TIMER_ALIGN_SCALE_NUM * total_function_num; - func_cap->timer_basic_size = CQM_TIMER_SIZE_32; - - func_cap->gpa_check_enable = true; - - cqm_lb_fake_mode_init(cqm_handle, service_capability); - cqm_info(handle->dev_hdl, "Cap init: lb_mode=%u\n", func_cap->lb_mode); - cqm_info(handle->dev_hdl, "Cap init: smf_pg=%u\n", func_cap->smf_pg); - cqm_info(handle->dev_hdl, "Cap init: fake_func_type=%u\n", func_cap->fake_func_type); - cqm_info(handle->dev_hdl, "Cap init: fake_cfg_number=%u\n", func_cap->fake_cfg_number); - - cqm_service_capability_init(cqm_handle, service_capability); - - cqm_test_mode_init(cqm_handle, service_capability); - - cqm_service_capability_update(cqm_handle); - - func_cap->ft_enable = service_capability->sf_svc_attr.ft_en; - func_cap->rdma_enable = service_capability->sf_svc_attr.rdma_en; - - cqm_info(handle->dev_hdl, "Cap init: pagesize_reorder %u\n", func_cap->pagesize_reorder); - cqm_info(handle->dev_hdl, "Cap init: xid_alloc_mode %d, gpa_check_enable %d\n", - func_cap->xid_alloc_mode, func_cap->gpa_check_enable); - cqm_info(handle->dev_hdl, "Cap init: qpc_alloc_mode %d, scqc_alloc_mode %d\n", - func_cap->qpc_alloc_static, func_cap->scqc_alloc_static); - cqm_info(handle->dev_hdl, "Cap init: hash_number 0x%x\n", func_cap->hash_number); - cqm_info(handle->dev_hdl, "Cap init: qpc_number 0x%x, qpc_reserved 0x%x, qpc_basic_size 0x%x\n", - func_cap->qpc_number, func_cap->qpc_reserved, func_cap->qpc_basic_size); - cqm_info(handle->dev_hdl, "Cap init: scqc_number 0x%x scqc_reserved 0x%x, scqc_basic_size 0x%x\n", - func_cap->scqc_number, func_cap->scq_reserved, func_cap->scqc_basic_size); - cqm_info(handle->dev_hdl, "Cap init: srqc_number 0x%x, srqc_basic_size 0x%x\n", - func_cap->srqc_number, func_cap->srqc_basic_size); - cqm_info(handle->dev_hdl, "Cap init: mpt_number 0x%x, mpt_reserved 0x%x\n", - func_cap->mpt_number, func_cap->mpt_reserved); - cqm_info(handle->dev_hdl, "Cap init: gid_number 0x%x, lun_number 0x%x\n", - func_cap->gid_number, func_cap->lun_number); - cqm_info(handle->dev_hdl, "Cap init: taskmap_number 0x%x, l3i_number 0x%x\n", - func_cap->taskmap_number, func_cap->l3i_number); - cqm_info(handle->dev_hdl, "Cap init: timer_number 0x%x, childc_number 0x%x\n", - func_cap->timer_number, func_cap->childc_number); - cqm_info(handle->dev_hdl, "Cap init: childc_basic_size 0x%x\n", - func_cap->childc_basic_size); - cqm_info(handle->dev_hdl, "Cap init: xid2cid_number 0x%x, reorder_number 0x%x\n", - func_cap->xid2cid_number, func_cap->reorder_number); - cqm_info(handle->dev_hdl, "Cap init: ft_enable %d, rdma_enable %d\n", - func_cap->ft_enable, func_cap->rdma_enable); - - return CQM_SUCCESS; - -out: - if (func_attr->func_type == CQM_PPF) - func_cap->timer_enable = 0; - - return err; -} - -s32 cqm_mem_init(void *ex_handle) -{ - struct sphw_hwdev *handle = (struct sphw_hwdev *)ex_handle; - struct cqm_handle *cqm_handle = NULL; - - cqm_handle = (struct cqm_handle *)(handle->cqm_hdl); - - if (cqm_bat_init(cqm_handle) != CQM_SUCCESS) { - cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_bat_init)); - return CQM_FAIL; - } - - if (cqm_cla_init(cqm_handle) != CQM_SUCCESS) { - cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_cla_init)); - goto err1; - } - - if (cqm_bitmap_init(cqm_handle) != CQM_SUCCESS) { - cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_bitmap_init)); - goto err2; - } - - if (cqm_object_table_init(cqm_handle) != CQM_SUCCESS) { - cqm_err(handle->dev_hdl, - CQM_FUNCTION_FAIL(cqm_object_table_init)); - goto err3; - } - - return CQM_SUCCESS; - -err3: - cqm_bitmap_uninit(cqm_handle); -err2: - cqm_cla_uninit(cqm_handle, CQM_BAT_ENTRY_MAX); -err1: - cqm_bat_uninit(cqm_handle); - return CQM_FAIL; -} - -void cqm_mem_uninit(void *ex_handle) -{ - struct sphw_hwdev *handle = (struct sphw_hwdev *)ex_handle; - struct cqm_handle *cqm_handle = NULL; - - cqm_handle = (struct cqm_handle *)(handle->cqm_hdl); - - cqm_object_table_uninit(cqm_handle); - cqm_bitmap_uninit(cqm_handle); - cqm_cla_uninit(cqm_handle, CQM_BAT_ENTRY_MAX); - cqm_bat_uninit(cqm_handle); -} - -s32 cqm_event_init(void *ex_handle) -{ - struct sphw_hwdev *handle = (struct sphw_hwdev *)ex_handle; - - if (sphw_aeq_register_swe_cb(ex_handle, SPHW_STATEFULL_EVENT, - cqm_aeq_callback) != CHIPIF_SUCCESS) { - cqm_err(handle->dev_hdl, "Event: fail to register aeq callback\n"); - return CQM_FAIL; - } - - return CQM_SUCCESS; -} - -void cqm_event_uninit(void *ex_handle) -{ - sphw_aeq_unregister_swe_cb(ex_handle, SPHW_STATEFULL_EVENT); -} - -u32 cqm_aeq_event2type(u8 event) -{ - u32 service_type; - - /* Distributes events to different service modules - * based on the event type. - */ - if (event >= CQM_AEQ_BASE_T_FC && event < CQM_AEQ_MAX_T_FC) - service_type = CQM_SERVICE_T_FC; - else - service_type = CQM_SERVICE_T_MAX; - - return service_type; -} - -u8 cqm_aeq_callback(void *ex_handle, u8 event, u8 *data) -{ - struct sphw_hwdev *handle = (struct sphw_hwdev *)ex_handle; - struct service_register_template *service_template = NULL; - struct cqm_handle *cqm_handle = NULL; - struct cqm_service *service = NULL; - u8 event_level = FAULT_LEVEL_MAX; - u32 service_type; - - CQM_PTR_CHECK_RET(ex_handle, event_level, - CQM_PTR_NULL(aeq_callback_ex_handle)); - - atomic_inc(&handle->hw_stats.cqm_stats.cqm_aeq_callback_cnt[event]); - - cqm_handle = (struct cqm_handle *)(handle->cqm_hdl); - CQM_PTR_CHECK_RET(cqm_handle, event_level, - CQM_PTR_NULL(aeq_callback_cqm_handle)); - - /* Distributes events to different service modules - * based on the event type. - */ - service_type = cqm_aeq_event2type(event); - if (service_type == CQM_SERVICE_T_MAX) { - cqm_err(handle->dev_hdl, CQM_WRONG_VALUE(event)); - return event_level; - } - - service = &cqm_handle->service[service_type]; - service_template = &service->service_template; - - if (!service_template->aeq_level_callback) - cqm_err(handle->dev_hdl, "Event: service_type %u aeq_level_callback unregistered\n", - service_type); - else - event_level = service_template->aeq_level_callback(service_template->service_handle, - event, data); - - if (!service_template->aeq_callback) - cqm_err(handle->dev_hdl, "Event: service_type %u aeq_callback unregistered\n", - service_type); - else - service_template->aeq_callback(service_template->service_handle, - event, data); - - return event_level; -} - -s32 cqm3_service_register(void *ex_handle, struct service_register_template *service_template) -{ - struct sphw_hwdev *handle = (struct sphw_hwdev *)ex_handle; - struct cqm_handle *cqm_handle = NULL; - struct cqm_service *service = NULL; - - CQM_PTR_CHECK_RET(ex_handle, CQM_FAIL, CQM_PTR_NULL(ex_handle)); - - cqm_handle = (struct cqm_handle *)(handle->cqm_hdl); - CQM_PTR_CHECK_RET(cqm_handle, CQM_FAIL, CQM_PTR_NULL(cqm_handle)); - CQM_PTR_CHECK_RET(service_template, CQM_FAIL, - CQM_PTR_NULL(service_template)); - - if (service_template->service_type >= CQM_SERVICE_T_MAX) { - cqm_err(handle->dev_hdl, - CQM_WRONG_VALUE(service_template->service_type)); - return CQM_FAIL; - } - service = &cqm_handle->service[service_template->service_type]; - if (!service->valid) { - cqm_err(handle->dev_hdl, "Service register: service_type %u is invalid\n", - service_template->service_type); - return CQM_FAIL; - } - - if (service->has_register) { - cqm_err(handle->dev_hdl, "Service register: service_type %u has registered\n", - service_template->service_type); - return CQM_FAIL; - } - - service->has_register = true; - (void)memcpy((void *)(&service->service_template), - (void *)service_template, - sizeof(struct service_register_template)); - - return CQM_SUCCESS; -} - -void cqm3_service_unregister(void *ex_handle, u32 service_type) -{ - struct sphw_hwdev *handle = (struct sphw_hwdev *)ex_handle; - struct cqm_handle *cqm_handle = NULL; - struct cqm_service *service = NULL; - - CQM_PTR_CHECK_NO_RET(ex_handle, CQM_PTR_NULL(ex_handle)); - - cqm_handle = (struct cqm_handle *)(handle->cqm_hdl); - CQM_PTR_CHECK_NO_RET(cqm_handle, CQM_PTR_NULL(cqm_handle)); - - if (service_type >= CQM_SERVICE_T_MAX) { - cqm_err(handle->dev_hdl, CQM_WRONG_VALUE(service_type)); - return; - } - - service = &cqm_handle->service[service_type]; - if (!service->valid) - cqm_err(handle->dev_hdl, "Service unregister: service_type %u is disable\n", - service_type); - - service->has_register = false; - memset(&service->service_template, 0, sizeof(struct service_register_template)); -} - -struct cqm_cmd_buf *cqm3_cmd_alloc(void *ex_handle) -{ - struct sphw_hwdev *handle = (struct sphw_hwdev *)ex_handle; - - CQM_PTR_CHECK_RET(ex_handle, NULL, CQM_PTR_NULL(ex_handle)); - - atomic_inc(&handle->hw_stats.cqm_stats.cqm_cmd_alloc_cnt); - - return (struct cqm_cmd_buf *)sphw_alloc_cmd_buf(ex_handle); -} - -void cqm3_cmd_free(void *ex_handle, struct cqm_cmd_buf *cmd_buf) -{ - struct sphw_hwdev *handle = (struct sphw_hwdev *)ex_handle; - - CQM_PTR_CHECK_NO_RET(ex_handle, CQM_PTR_NULL(ex_handle)); - CQM_PTR_CHECK_NO_RET(cmd_buf, CQM_PTR_NULL(cmd_buf)); - CQM_PTR_CHECK_NO_RET(cmd_buf->buf, CQM_PTR_NULL(buf)); - - atomic_inc(&handle->hw_stats.cqm_stats.cqm_cmd_free_cnt); - - sphw_free_cmd_buf(ex_handle, (struct sphw_cmd_buf *)cmd_buf); -} - -s32 cqm3_send_cmd_box(void *ex_handle, u8 mod, u8 cmd, struct cqm_cmd_buf *buf_in, - struct cqm_cmd_buf *buf_out, u64 *out_param, u32 timeout, - u16 channel) -{ - struct sphw_hwdev *handle = (struct sphw_hwdev *)ex_handle; - - CQM_PTR_CHECK_RET(ex_handle, CQM_FAIL, CQM_PTR_NULL(ex_handle)); - CQM_PTR_CHECK_RET(buf_in, CQM_FAIL, CQM_PTR_NULL(buf_in)); - CQM_PTR_CHECK_RET(buf_in->buf, CQM_FAIL, CQM_PTR_NULL(buf)); - - atomic_inc(&handle->hw_stats.cqm_stats.cqm_send_cmd_box_cnt); - - return sphw_cmdq_detail_resp(ex_handle, mod, cmd, - (struct sphw_cmd_buf *)buf_in, - (struct sphw_cmd_buf *)buf_out, - out_param, timeout, channel); -} - -int cqm_alloc_fc_db_addr(void *hwdev, void __iomem **db_base, - void __iomem **dwqe_base) -{ - struct sphw_hwif *hwif = NULL; - u32 idx = 0; -#define SPFC_DB_ADDR_RSVD 12 -#define SPFC_DB_MASK 128 - u64 db_base_phy_fc; - - if (!hwdev || !db_base) - return -EINVAL; - - hwif = ((struct sphw_hwdev *)hwdev)->hwif; - - db_base_phy_fc = hwif->db_base_phy >> SPFC_DB_ADDR_RSVD; - - if (db_base_phy_fc & (SPFC_DB_MASK - 1)) - idx = SPFC_DB_MASK - (db_base_phy_fc && (SPFC_DB_MASK - 1)); - - *db_base = hwif->db_base + idx * SPHW_DB_PAGE_SIZE; - - if (!dwqe_base) - return 0; - - *dwqe_base = (u8 *)*db_base + SPHW_DWQE_OFFSET; - - return 0; -} - -s32 cqm3_db_addr_alloc(void *ex_handle, void __iomem **db_addr, - void __iomem **dwqe_addr) -{ - struct sphw_hwdev *handle = (struct sphw_hwdev *)ex_handle; - - CQM_PTR_CHECK_RET(ex_handle, CQM_FAIL, CQM_PTR_NULL(ex_handle)); - CQM_PTR_CHECK_RET(db_addr, CQM_FAIL, CQM_PTR_NULL(db_addr)); - CQM_PTR_CHECK_RET(dwqe_addr, CQM_FAIL, CQM_PTR_NULL(dwqe_addr)); - - atomic_inc(&handle->hw_stats.cqm_stats.cqm_db_addr_alloc_cnt); - - return cqm_alloc_fc_db_addr(ex_handle, db_addr, dwqe_addr); -} - -s32 cqm_db_phy_addr_alloc(void *ex_handle, u64 *db_paddr, u64 *dwqe_addr) -{ - return sphw_alloc_db_phy_addr(ex_handle, db_paddr, dwqe_addr); -} - -void cqm3_db_addr_free(void *ex_handle, const void __iomem *db_addr, - void __iomem *dwqe_addr) -{ - struct sphw_hwdev *handle = (struct sphw_hwdev *)ex_handle; - - CQM_PTR_CHECK_NO_RET(ex_handle, CQM_PTR_NULL(ex_handle)); - - atomic_inc(&handle->hw_stats.cqm_stats.cqm_db_addr_free_cnt); - - sphw_free_db_addr(ex_handle, db_addr, dwqe_addr); -} - -void cqm_db_phy_addr_free(void *ex_handle, u64 *db_paddr, u64 *dwqe_addr) -{ - sphw_free_db_phy_addr(ex_handle, *db_paddr, *dwqe_addr); -} - -s32 cqm_db_init(void *ex_handle) -{ - struct sphw_hwdev *handle = (struct sphw_hwdev *)ex_handle; - struct cqm_handle *cqm_handle = NULL; - struct cqm_service *service = NULL; - s32 i; - - cqm_handle = (struct cqm_handle *)(handle->cqm_hdl); - - /* Allocate hardware doorbells to services. */ - for (i = 0; i < CQM_SERVICE_T_MAX; i++) { - service = &cqm_handle->service[i]; - if (!service->valid) - continue; - - if (cqm3_db_addr_alloc(ex_handle, &service->hardware_db_vaddr, - &service->dwqe_vaddr) != CQM_SUCCESS) { - cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm3_db_addr_alloc)); - break; - } - - if (cqm_db_phy_addr_alloc(handle, &service->hardware_db_paddr, - &service->dwqe_paddr) != CQM_SUCCESS) { - cqm3_db_addr_free(ex_handle, service->hardware_db_vaddr, - service->dwqe_vaddr); - cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_db_phy_addr_alloc)); - break; - } - } - - if (i != CQM_SERVICE_T_MAX) { - i--; - for (; i >= 0; i--) { - service = &cqm_handle->service[i]; - if (!service->valid) - continue; - - cqm3_db_addr_free(ex_handle, service->hardware_db_vaddr, - service->dwqe_vaddr); - cqm_db_phy_addr_free(ex_handle, - &service->hardware_db_paddr, - &service->dwqe_paddr); - } - return CQM_FAIL; - } - - return CQM_SUCCESS; -} - -void cqm_db_uninit(void *ex_handle) -{ - struct sphw_hwdev *handle = (struct sphw_hwdev *)ex_handle; - struct cqm_handle *cqm_handle = NULL; - struct cqm_service *service = NULL; - s32 i; - - cqm_handle = (struct cqm_handle *)(handle->cqm_hdl); - - /* Release hardware doorbell. */ - for (i = 0; i < CQM_SERVICE_T_MAX; i++) { - service = &cqm_handle->service[i]; - if (service->valid) - cqm3_db_addr_free(ex_handle, service->hardware_db_vaddr, - service->dwqe_vaddr); - } -} - -s32 cqm3_ring_hardware_db_fc(void *ex_handle, u32 service_type, u8 db_count, - u8 pagenum, u64 db) -{ -#define SPFC_DB_FAKE_VF_OFFSET 32 - struct cqm_handle *cqm_handle = NULL; - struct cqm_service *service = NULL; - struct sphw_hwdev *handle = NULL; - void *dbaddr = NULL; - - handle = (struct sphw_hwdev *)ex_handle; - cqm_handle = (struct cqm_handle *)(handle->cqm_hdl); - service = &cqm_handle->service[service_type]; - /* Considering the performance of ringing hardware db, - * the parameter is not checked. - */ - wmb(); - dbaddr = (u8 *)service->hardware_db_vaddr + - ((pagenum + SPFC_DB_FAKE_VF_OFFSET) * SPHW_DB_PAGE_SIZE); - *((u64 *)dbaddr + db_count) = db; - return CQM_SUCCESS; -} - -s32 cqm_ring_direct_wqe_db_fc(void *ex_handle, u32 service_type, - void *direct_wqe) -{ - struct cqm_handle *cqm_handle = NULL; - struct cqm_service *service = NULL; - struct sphw_hwdev *handle = NULL; - u64 *tmp = (u64 *)direct_wqe; - int i; - - handle = (struct sphw_hwdev *)ex_handle; - cqm_handle = (struct cqm_handle *)(handle->cqm_hdl); - service = &cqm_handle->service[service_type]; - - /* Considering the performance of ringing hardware db, - * the parameter is not checked. - */ - wmb(); - *((u64 *)service->dwqe_vaddr + 0) = tmp[2]; - *((u64 *)service->dwqe_vaddr + 1) = tmp[3]; - *((u64 *)service->dwqe_vaddr + 2) = tmp[0]; - *((u64 *)service->dwqe_vaddr + 3) = tmp[1]; - tmp += 4; - - /* The FC use 256B WQE. The directwqe is written at block0, - * and the length is 256B - */ - for (i = 4; i < 32; i++) - *((u64 *)service->dwqe_vaddr + i) = *tmp++; - - return CQM_SUCCESS; -} - -static s32 bloomfilter_init_cmd(void *ex_handle) -{ - struct sphw_hwdev *handle = (struct sphw_hwdev *)ex_handle; - struct cqm_handle *cqm_handle = (struct cqm_handle *)(handle->cqm_hdl); - struct cqm_func_capability *capability = &cqm_handle->func_capability; - struct cqm_bloomfilter_init_cmd *cmd = NULL; - struct cqm_cmd_buf *buf_in = NULL; - s32 ret; - - buf_in = cqm3_cmd_alloc((void *)(cqm_handle->ex_handle)); - CQM_PTR_CHECK_RET(buf_in, CQM_FAIL, CQM_ALLOC_FAIL(buf_in)); - - /* Fill the command format and convert it to big-endian. */ - buf_in->size = sizeof(struct cqm_bloomfilter_init_cmd); - cmd = (struct cqm_bloomfilter_init_cmd *)(buf_in->buf); - cmd->bloom_filter_addr = capability->bloomfilter_addr; - cmd->bloom_filter_len = capability->bloomfilter_length; - - cqm_swab32((u8 *)cmd, (sizeof(struct cqm_bloomfilter_init_cmd) >> CQM_DW_SHIFT)); - - ret = cqm3_send_cmd_box((void *)(cqm_handle->ex_handle), - CQM_MOD_CQM, CQM_CMD_T_BLOOMFILTER_INIT, buf_in, - NULL, NULL, CQM_CMD_TIMEOUT, - SPHW_CHANNEL_DEFAULT); - if (ret != CQM_SUCCESS) { - cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm3_send_cmd_box)); - cqm_err(handle->dev_hdl, "Bloomfilter: %s ret=%d\n", __func__, - ret); - cqm_err(handle->dev_hdl, "Bloomfilter: %s: 0x%x 0x%x\n", - __func__, cmd->bloom_filter_addr, - cmd->bloom_filter_len); - cqm3_cmd_free((void *)(cqm_handle->ex_handle), buf_in); - return CQM_FAIL; - } - cqm3_cmd_free((void *)(cqm_handle->ex_handle), buf_in); - return CQM_SUCCESS; -} - -s32 cqm_bloomfilter_init(void *ex_handle) -{ - struct sphw_hwdev *handle = (struct sphw_hwdev *)ex_handle; - struct cqm_bloomfilter_table *bloomfilter_table = NULL; - struct cqm_func_capability *capability = NULL; - struct cqm_handle *cqm_handle = NULL; - u32 array_size; - s32 ret; - - cqm_handle = (struct cqm_handle *)(handle->cqm_hdl); - bloomfilter_table = &cqm_handle->bloomfilter_table; - capability = &cqm_handle->func_capability; - - if (capability->bloomfilter_length == 0) { - cqm_info(handle->dev_hdl, - "Bloomfilter: bf_length=0, don't need to init bloomfilter\n"); - return CQM_SUCCESS; - } - - /* The unit of bloomfilter_length is 64B(512bits). Each bit is a table - * node. Therefore the value must be shift 9 bits to the left. - */ - bloomfilter_table->table_size = capability->bloomfilter_length << - CQM_BF_LENGTH_UNIT; - /* The unit of bloomfilter_length is 64B. The unit of array entryis 32B. - */ - array_size = capability->bloomfilter_length << 1; - if (array_size == 0 || array_size > CQM_BF_BITARRAY_MAX) { - cqm_err(handle->dev_hdl, CQM_WRONG_VALUE(array_size)); - return CQM_FAIL; - } - - bloomfilter_table->array_mask = array_size - 1; - /* This table is not a bitmap, it is the counter of corresponding bit. - */ - bloomfilter_table->table = vmalloc(bloomfilter_table->table_size * (sizeof(u32))); - CQM_PTR_CHECK_RET(bloomfilter_table->table, CQM_FAIL, CQM_ALLOC_FAIL(table)); - - memset(bloomfilter_table->table, 0, - (bloomfilter_table->table_size * sizeof(u32))); - - /* The the bloomfilter must be initialized to 0 by ucode, - * because the bloomfilter is mem mode - */ - if (cqm_handle->func_capability.bloomfilter_enable) { - ret = bloomfilter_init_cmd(ex_handle); - if (ret != CQM_SUCCESS) { - cqm_err(handle->dev_hdl, - "Bloomfilter: bloomfilter_init_cmd ret=%d\n", - ret); - vfree(bloomfilter_table->table); - bloomfilter_table->table = NULL; - return CQM_FAIL; - } - } - - mutex_init(&bloomfilter_table->lock); - return CQM_SUCCESS; -} - -void cqm_bloomfilter_uninit(void *ex_handle) -{ - struct sphw_hwdev *handle = (struct sphw_hwdev *)ex_handle; - struct cqm_bloomfilter_table *bloomfilter_table = NULL; - struct cqm_handle *cqm_handle = NULL; - - cqm_handle = (struct cqm_handle *)(handle->cqm_hdl); - bloomfilter_table = &cqm_handle->bloomfilter_table; - - if (bloomfilter_table->table) { - vfree(bloomfilter_table->table); - bloomfilter_table->table = NULL; - } -} - -s32 cqm_bloomfilter_cmd(void *ex_handle, u32 op, u32 k_flag, u64 id) -{ - struct sphw_hwdev *handle = (struct sphw_hwdev *)ex_handle; - struct cqm_cmd_buf *buf_in = NULL; - struct cqm_bloomfilter_cmd *cmd = NULL; - s32 ret; - - buf_in = cqm3_cmd_alloc(ex_handle); - CQM_PTR_CHECK_RET(buf_in, CQM_FAIL, CQM_ALLOC_FAIL(buf_in)); - - /* Fill the command format and convert it to big-endian. */ - buf_in->size = sizeof(struct cqm_bloomfilter_cmd); - cmd = (struct cqm_bloomfilter_cmd *)(buf_in->buf); - memset((void *)cmd, 0, sizeof(struct cqm_bloomfilter_cmd)); - cmd->k_en = k_flag; - cmd->index_h = (u32)(id >> CQM_DW_OFFSET); - cmd->index_l = (u32)(id & CQM_DW_MASK); - - cqm_swab32((u8 *)cmd, (sizeof(struct cqm_bloomfilter_cmd) >> CQM_DW_SHIFT)); - - ret = cqm3_send_cmd_box(ex_handle, CQM_MOD_CQM, (u8)op, buf_in, NULL, - NULL, CQM_CMD_TIMEOUT, SPHW_CHANNEL_DEFAULT); - if (ret != CQM_SUCCESS) { - cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm3_send_cmd_box)); - cqm_err(handle->dev_hdl, "Bloomfilter: bloomfilter_cmd ret=%d\n", ret); - cqm_err(handle->dev_hdl, "Bloomfilter: op=0x%x, cmd: 0x%x 0x%x 0x%x 0x%x\n", - op, *((u32 *)cmd), *(((u32 *)cmd) + CQM_DW_INDEX1), - *(((u32 *)cmd) + CQM_DW_INDEX2), - *(((u32 *)cmd) + CQM_DW_INDEX3)); - cqm3_cmd_free(ex_handle, buf_in); - return CQM_FAIL; - } - - cqm3_cmd_free(ex_handle, buf_in); - - return CQM_SUCCESS; -} diff --git a/drivers/scsi/spfc/hw/spfc_cqm_main.h b/drivers/scsi/spfc/hw/spfc_cqm_main.h deleted file mode 100644 index cf10d7f5c339..000000000000 --- a/drivers/scsi/spfc/hw/spfc_cqm_main.h +++ /dev/null @@ -1,411 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPFC_CQM_MAIN_H -#define SPFC_CQM_MAIN_H - -#include "sphw_hwdev.h" -#include "sphw_hwif.h" -#include "spfc_cqm_object.h" -#include "spfc_cqm_bitmap_table.h" -#include "spfc_cqm_bat_cla.h" - -#define GET_MAX(a, b) ((a) > (b) ? (a) : (b)) -#define GET_MIN(a, b) ((a) < (b) ? (a) : (b)) -#define CQM_DW_SHIFT 2 -#define CQM_QW_SHIFT 3 -#define CQM_BYTE_BIT_SHIFT 3 -#define CQM_NUM_BIT_BYTE 8 - -#define CHIPIF_SUCCESS 0 -#define CHIPIF_FAIL (-1) - -#define CQM_TIMER_ENABLE 1 -#define CQM_TIMER_DISABLE 0 - -/* The value must be the same as that of sphw_service_type in sphw_crm.h. */ -#define CQM_SERVICE_T_FC SERVICE_T_FC -#define CQM_SERVICE_T_MAX SERVICE_T_MAX - -struct cqm_service { - bool valid; /* Whether to enable this service on the function. */ - bool has_register; /* Registered or Not */ - u64 hardware_db_paddr; - void __iomem *hardware_db_vaddr; - u64 dwqe_paddr; - void __iomem *dwqe_vaddr; - u32 buf_order; /* The size of each buf node is 2^buf_order pages. */ - struct service_register_template service_template; -}; - -struct cqm_fake_cfg { - u32 parent_func; /* The parent func_id of the fake vfs. */ - u32 child_func_start; /* The start func_id of the child fake vfs. */ - u32 child_func_number; /* The number of the child fake vfs. */ -}; - -#define CQM_MAX_FACKVF_GROUP 4 - -struct cqm_func_capability { - /* BAT_PTR table(SMLC) */ - bool ft_enable; /* BAT for flow table enable: support fc service - */ - bool rdma_enable; /* BAT for rdma enable: support RoCE */ - /* VAT table(SMIR) */ - bool ft_pf_enable; /* Same as ft_enable. BAT entry for fc on pf - */ - bool rdma_pf_enable; /* Same as rdma_enable. BAT entry for rdma on pf */ - - /* Dynamic or static memory allocation during the application of - * specified QPC/SCQC for each service. - */ - bool qpc_alloc_static; - bool scqc_alloc_static; - - u8 timer_enable; /* Whether the timer function is enabled */ - u8 bloomfilter_enable; /* Whether the bloomgfilter function is enabled */ - /* Maximum number of connections for fc, whitch cannot excedd qpc_number */ - u32 flow_table_based_conn_number; - u32 flow_table_based_conn_cache_number; /* Maximum number of sticky caches */ - u32 bloomfilter_length; /* Size of the bloomfilter table, 64-byte aligned */ - u32 bloomfilter_addr; /* Start position of the bloomfilter table in the SMF main cache. */ - u32 qpc_reserved; /* Reserved bit in bitmap */ - u32 mpt_reserved; /* The ROCE/IWARP MPT also has a reserved bit. */ - - /* All basic_size must be 2^n-aligned. */ - /* The number of hash bucket. The size of BAT table is aliaed with 64 bucket. - *At least 64 buckets is required. - */ - u32 hash_number; - /* THe basic size of hash bucket is 64B, including 5 valid entry and one next entry. */ - u32 hash_basic_size; - u32 qpc_number; - u32 qpc_basic_size; - - /* NUmber of PFs/VFs on the current host */ - u32 pf_num; - u32 pf_id_start; - u32 vf_num; - u32 vf_id_start; - - u32 lb_mode; - /* Only lower 4bit is valid, indicating which SMFs are enabled. - * For example, 0101B indicates that SMF0 and SMF2 are enabled. - */ - u32 smf_pg; - - u32 fake_mode; - /* Whether the current function belongs to the fake group (parent or child) */ - u32 fake_func_type; - u32 fake_cfg_number; /* Number of current configuration groups */ - struct cqm_fake_cfg fake_cfg[CQM_MAX_FACKVF_GROUP]; - - /* Note: for cqm specail test */ - u32 pagesize_reorder; - bool xid_alloc_mode; - bool gpa_check_enable; - u32 scq_reserved; - u32 srq_reserved; - - u32 mpt_number; - u32 mpt_basic_size; - u32 scqc_number; - u32 scqc_basic_size; - u32 srqc_number; - u32 srqc_basic_size; - - u32 gid_number; - u32 gid_basic_size; - u32 lun_number; - u32 lun_basic_size; - u32 taskmap_number; - u32 taskmap_basic_size; - u32 l3i_number; - u32 l3i_basic_size; - u32 childc_number; - u32 childc_basic_size; - u32 child_qpc_id_start; /* FC service Child CTX is global addressing. */ - u32 childc_number_all_function; /* The chip supports a maximum of 8096 child CTXs. */ - u32 timer_number; - u32 timer_basic_size; - u32 xid2cid_number; - u32 xid2cid_basic_size; - u32 reorder_number; - u32 reorder_basic_size; -}; - -#define CQM_PF TYPE_PF -#define CQM_VF TYPE_VF -#define CQM_PPF TYPE_PPF -#define CQM_UNKNOWN TYPE_UNKNOWN -#define CQM_MAX_PF_NUM 32 - -#define CQM_LB_MODE_NORMAL 0xff -#define CQM_LB_MODE_0 0 -#define CQM_LB_MODE_1 1 -#define CQM_LB_MODE_2 2 - -#define CQM_LB_SMF_MAX 4 - -#define CQM_FPGA_MODE 0 -#define CQM_EMU_MODE 1 -#define CQM_FAKE_MODE_DISABLE 0 -#define CQM_FAKE_CFUNC_START 32 - -#define CQM_FAKE_FUNC_NORMAL 0 -#define CQM_FAKE_FUNC_PARENT 1 -#define CQM_FAKE_FUNC_CHILD 2 -#define CQM_FAKE_FUNC_CHILD_CONFLICT 3 -#define CQM_FAKE_FUNC_MAX 32 - -#define CQM_SPU_HOST_ID 4 - -#define CQM_QPC_ROCE_PER_DRCT 12 -#define CQM_QPC_NORMAL_RESERVE_DRC 0 -#define CQM_QPC_ROCEAA_ENABLE 1 -#define CQM_QPC_ROCE_VBS_MODE 2 -#define CQM_QPC_NORMAL_WITHOUT_RSERVER_DRC 3 - -struct cqm_db_common { - u32 rsvd1 : 23; - u32 c : 1; - u32 cos : 3; - u32 service_type : 5; - - u32 rsvd2; -}; - -struct cqm_bloomfilter_table { - u32 *table; - u32 table_size; /* The unit is bit */ - u32 array_mask; /* The unit of array entry is 32B, used to address entry - */ - struct mutex lock; -}; - -struct cqm_bloomfilter_init_cmd { - u32 bloom_filter_len; - u32 bloom_filter_addr; -}; - -struct cqm_bloomfilter_cmd { - u32 rsv1; - - u32 k_en : 4; - u32 rsv2 : 28; - - u32 index_h; - u32 index_l; -}; - -struct cqm_handle { - struct sphw_hwdev *ex_handle; - struct pci_dev *dev; - struct sphw_func_attr func_attribute; /* vf/pf attributes */ - struct cqm_func_capability func_capability; /* function capability set */ - struct cqm_service service[CQM_SERVICE_T_MAX]; /* Service-related structure */ - struct cqm_bat_table bat_table; - struct cqm_bloomfilter_table bloomfilter_table; - /* fake-vf-related structure */ - struct cqm_handle *fake_cqm_handle[CQM_FAKE_FUNC_MAX]; - struct cqm_handle *parent_cqm_handle; -}; - -enum cqm_cmd_type { - CQM_CMD_T_INVALID = 0, - CQM_CMD_T_BAT_UPDATE, - CQM_CMD_T_CLA_UPDATE, - CQM_CMD_T_CLA_CACHE_INVALID = 6, - CQM_CMD_T_BLOOMFILTER_INIT, - CQM_CMD_T_MAX -}; - -#define CQM_CQN_FROM_CEQE(data) ((data) & 0xfffff) -#define CQM_XID_FROM_CEQE(data) ((data) & 0xfffff) -#define CQM_QID_FROM_CEQE(data) (((data) >> 20) & 0x7) -#define CQM_TYPE_FROM_CEQE(data) (((data) >> 23) & 0x7) - -#define CQM_HASH_BUCKET_SIZE_64 64 - -#define CQM_MAX_QPC_NUM 0x100000 -#define CQM_MAX_SCQC_NUM 0x100000 -#define CQM_MAX_SRQC_NUM 0x100000 -#define CQM_MAX_CHILDC_NUM 0x100000 - -#define CQM_QPC_SIZE_256 256 -#define CQM_QPC_SIZE_512 512 -#define CQM_QPC_SIZE_1024 1024 - -#define CQM_SCQC_SIZE_32 32 -#define CQM_SCQC_SIZE_64 64 -#define CQM_SCQC_SIZE_128 128 - -#define CQM_SRQC_SIZE_32 32 -#define CQM_SRQC_SIZE_64 64 -#define CQM_SRQC_SIZE_128 128 - -#define CQM_MPT_SIZE_64 64 - -#define CQM_GID_SIZE_32 32 - -#define CQM_LUN_SIZE_8 8 - -#define CQM_L3I_SIZE_8 8 - -#define CQM_TIMER_SIZE_32 32 - -#define CQM_XID2CID_SIZE_8 8 - -#define CQM_XID2CID_SIZE_8K 8192 - -#define CQM_REORDER_SIZE_256 256 - -#define CQM_CHILDC_SIZE_256 256 - -#define CQM_XID2CID_VBS_NUM (18 * 1024) /* 16K virtio VQ + 2K nvme Q */ - -#define CQM_VBS_QPC_NUM 2048 /* 2K VOLQ */ - -#define CQM_VBS_QPC_SIZE 512 - -#define CQM_XID2CID_VIRTIO_NUM (16 * 1024) - -#define CQM_GID_RDMA_NUM 128 - -#define CQM_LUN_FC_NUM 64 - -#define CQM_TASKMAP_FC_NUM 4 - -#define CQM_L3I_COMM_NUM 64 - -#define CQM_CHILDC_ROCE_NUM (8 * 1024) -#define CQM_CHILDC_OVS_VBS_NUM (8 * 1024) -#define CQM_CHILDC_TOE_NUM 256 -#define CQM_CHILDC_IPSEC_NUM (4 * 1024) - -#define CQM_TIMER_SCALE_NUM (2 * 1024) -#define CQM_TIMER_ALIGN_WHEEL_NUM 8 -#define CQM_TIMER_ALIGN_SCALE_NUM \ - (CQM_TIMER_SCALE_NUM * CQM_TIMER_ALIGN_WHEEL_NUM) - -#define CQM_QPC_OVS_RSVD (1024 * 1024) -#define CQM_QPC_ROCE_RSVD 2 -#define CQM_QPC_ROCEAA_SWITCH_QP_NUM 4 -#define CQM_QPC_ROCEAA_RSVD \ - (4 * 1024 + CQM_QPC_ROCEAA_SWITCH_QP_NUM) /* 4096 Normal QP + 4 Switch QP */ -#define CQM_CQ_ROCEAA_RSVD 64 -#define CQM_SRQ_ROCEAA_RSVD 64 -#define CQM_QPC_ROCE_VBS_RSVD \ - (1024 + CQM_QPC_ROCE_RSVD) /* (204800 + CQM_QPC_ROCE_RSVD) */ - -#define CQM_OVS_PAGESIZE_ORDER 8 -#define CQM_OVS_MAX_TIMER_FUNC 48 - -#define CQM_FC_PAGESIZE_ORDER 0 - -#define CQM_QHEAD_ALIGN_ORDER 6 - -#define CQM_CMD_TIMEOUT 300000 /* ms */ - -#define CQM_DW_MASK 0xffffffff -#define CQM_DW_OFFSET 32 -#define CQM_DW_INDEX0 0 -#define CQM_DW_INDEX1 1 -#define CQM_DW_INDEX2 2 -#define CQM_DW_INDEX3 3 - -/* The unit of bloomfilter_length is 64B(512bits). */ -#define CQM_BF_LENGTH_UNIT 9 -#define CQM_BF_BITARRAY_MAX BIT(17) - -typedef void (*serv_cap_init_cb)(struct cqm_handle *, void *); - -/* Only for llt test */ -s32 cqm_capability_init(void *ex_handle); -/* Can be defined as static */ -s32 cqm_mem_init(void *ex_handle); -void cqm_mem_uninit(void *ex_handle); -s32 cqm_event_init(void *ex_handle); -void cqm_event_uninit(void *ex_handle); -u8 cqm_aeq_callback(void *ex_handle, u8 event, u8 *data); - -s32 cqm3_init(void *ex_handle); -void cqm3_uninit(void *ex_handle); -s32 cqm3_service_register(void *ex_handle, struct service_register_template *service_template); -void cqm3_service_unregister(void *ex_handle, u32 service_type); - -struct cqm_cmd_buf *cqm3_cmd_alloc(void *ex_handle); -void cqm3_cmd_free(void *ex_handle, struct cqm_cmd_buf *cmd_buf); -s32 cqm3_send_cmd_box(void *ex_handle, u8 mod, u8 cmd, struct cqm_cmd_buf *buf_in, - struct cqm_cmd_buf *buf_out, u64 *out_param, u32 timeout, - u16 channel); - -s32 cqm3_db_addr_alloc(void *ex_handle, void __iomem **db_addr, void __iomem **dwqe_addr); -s32 cqm_db_phy_addr_alloc(void *ex_handle, u64 *db_paddr, u64 *dwqe_addr); -s32 cqm_db_init(void *ex_handle); -void cqm_db_uninit(void *ex_handle); - -s32 cqm_bloomfilter_cmd(void *ex_handle, u32 op, u32 k_flag, u64 id); -s32 cqm_bloomfilter_init(void *ex_handle); -void cqm_bloomfilter_uninit(void *ex_handle); - -#define CQM_LOG_ID 0 - -#define CQM_PTR_NULL(x) "%s: " #x " is null\n", __func__ -#define CQM_ALLOC_FAIL(x) "%s: " #x " alloc fail\n", __func__ -#define CQM_MAP_FAIL(x) "%s: " #x " map fail\n", __func__ -#define CQM_FUNCTION_FAIL(x) "%s: " #x " return failure\n", __func__ -#define CQM_WRONG_VALUE(x) "%s: " #x " %u is wrong\n", __func__, (u32)(x) - -#define cqm_err(dev, format, ...) dev_err(dev, "[CQM]" format, ##__VA_ARGS__) -#define cqm_warn(dev, format, ...) dev_warn(dev, "[CQM]" format, ##__VA_ARGS__) -#define cqm_notice(dev, format, ...) \ - dev_notice(dev, "[CQM]" format, ##__VA_ARGS__) -#define cqm_info(dev, format, ...) dev_info(dev, "[CQM]" format, ##__VA_ARGS__) - -#define CQM_32_ALIGN_CHECK_RET(dev_hdl, x, ret, desc) \ - do { \ - if (unlikely(((x) & 0x1f) != 0)) { \ - cqm_err(dev_hdl, desc); \ - return ret; \ - } \ - } while (0) -#define CQM_64_ALIGN_CHECK_RET(dev_hdl, x, ret, desc) \ - do { \ - if (unlikely(((x) & 0x3f) != 0)) { \ - cqm_err(dev_hdl, desc); \ - return ret; \ - } \ - } while (0) - -#define CQM_PTR_CHECK_RET(ptr, ret, desc) \ - do { \ - if (unlikely((ptr) == NULL)) { \ - pr_err("[CQM]" desc); \ - return ret; \ - } \ - } while (0) - -#define CQM_PTR_CHECK_NO_RET(ptr, desc) \ - do { \ - if (unlikely((ptr) == NULL)) { \ - pr_err("[CQM]" desc); \ - return; \ - } \ - } while (0) -#define CQM_CHECK_EQUAL_RET(dev_hdl, actual, expect, ret, desc) \ - do { \ - if (unlikely((expect) != (actual))) { \ - cqm_err(dev_hdl, desc); \ - return ret; \ - } \ - } while (0) -#define CQM_CHECK_EQUAL_NO_RET(dev_hdl, actual, expect, desc) \ - do { \ - if (unlikely((expect) != (actual))) { \ - cqm_err(dev_hdl, desc); \ - return; \ - } \ - } while (0) - -#endif /* SPFC_CQM_MAIN_H */ diff --git a/drivers/scsi/spfc/hw/spfc_cqm_object.c b/drivers/scsi/spfc/hw/spfc_cqm_object.c deleted file mode 100644 index 165794e9c7e5..000000000000 --- a/drivers/scsi/spfc/hw/spfc_cqm_object.c +++ /dev/null @@ -1,937 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#include <linux/types.h> -#include <linux/sched.h> -#include <linux/pci.h> -#include <linux/module.h> -#include <linux/vmalloc.h> -#include <linux/device.h> -#include <linux/gfp.h> -#include <linux/mm.h> - -#include "sphw_crm.h" -#include "sphw_hw.h" -#include "sphw_hwdev.h" -#include "sphw_hwif.h" - -#include "spfc_cqm_object.h" -#include "spfc_cqm_bitmap_table.h" -#include "spfc_cqm_bat_cla.h" -#include "spfc_cqm_main.h" - -s32 cqm_qpc_mpt_bitmap_alloc(struct cqm_object *object, struct cqm_cla_table *cla_table) -{ - struct cqm_qpc_mpt *common = container_of(object, struct cqm_qpc_mpt, object); - struct cqm_qpc_mpt_info *qpc_mpt_info = container_of(common, - struct cqm_qpc_mpt_info, - common); - struct cqm_handle *cqm_handle = (struct cqm_handle *)object->cqm_handle; - struct cqm_func_capability *func_cap = &cqm_handle->func_capability; - struct sphw_hwdev *handle = cqm_handle->ex_handle; - struct cqm_bitmap *bitmap = &cla_table->bitmap; - u32 index, count; - - count = (ALIGN(object->object_size, cla_table->obj_size)) / cla_table->obj_size; - qpc_mpt_info->index_count = count; - - if (qpc_mpt_info->common.xid == CQM_INDEX_INVALID) { - /* apply for an index normally */ - index = cqm_bitmap_alloc(bitmap, 1U << (cla_table->z + 1), - count, func_cap->xid_alloc_mode); - if (index < bitmap->max_num) { - qpc_mpt_info->common.xid = index; - } else { - cqm_err(handle->dev_hdl, - CQM_FUNCTION_FAIL(cqm_bitmap_alloc)); - return CQM_FAIL; - } - } else { - /* apply for index to be reserved */ - index = cqm_bitmap_alloc_reserved(bitmap, count, - qpc_mpt_info->common.xid); - if (index != qpc_mpt_info->common.xid) { - cqm_err(handle->dev_hdl, - CQM_FUNCTION_FAIL(cqm_bitmap_alloc_reserved)); - return CQM_FAIL; - } - } - - return CQM_SUCCESS; -} - -s32 cqm_qpc_mpt_create(struct cqm_object *object) -{ - struct cqm_qpc_mpt *common = container_of(object, struct cqm_qpc_mpt, object); - struct cqm_qpc_mpt_info *qpc_mpt_info = container_of(common, - struct cqm_qpc_mpt_info, - common); - struct cqm_handle *cqm_handle = (struct cqm_handle *)object->cqm_handle; - struct cqm_bat_table *bat_table = &cqm_handle->bat_table; - struct sphw_hwdev *handle = cqm_handle->ex_handle; - struct cqm_object_table *object_table = NULL; - struct cqm_cla_table *cla_table = NULL; - struct cqm_bitmap *bitmap = NULL; - u32 index, count; - - /* find the corresponding cla table */ - if (object->object_type == CQM_OBJECT_SERVICE_CTX) { - cla_table = cqm_cla_table_get(bat_table, CQM_BAT_ENTRY_T_QPC); - } else { - cqm_err(handle->dev_hdl, CQM_WRONG_VALUE(object->object_type)); - return CQM_FAIL; - } - - CQM_PTR_CHECK_RET(cla_table, CQM_FAIL, - CQM_FUNCTION_FAIL(cqm_cla_table_get)); - - /* Bitmap applies for index. */ - if (cqm_qpc_mpt_bitmap_alloc(object, cla_table) == CQM_FAIL) { - cqm_err(handle->dev_hdl, - CQM_FUNCTION_FAIL(cqm_qpc_mpt_bitmap_alloc)); - return CQM_FAIL; - } - - bitmap = &cla_table->bitmap; - index = qpc_mpt_info->common.xid; - count = qpc_mpt_info->index_count; - - /* Find the trunk page from the BAT/CLA and allocate the buffer. - * Ensure that the released buffer has been cleared. - */ - if (cla_table->alloc_static) - qpc_mpt_info->common.vaddr = cqm_cla_get_unlock(cqm_handle, - cla_table, - index, count, - &common->paddr); - else - qpc_mpt_info->common.vaddr = cqm_cla_get_lock(cqm_handle, - cla_table, index, - count, - &common->paddr); - - if (!qpc_mpt_info->common.vaddr) { - cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_cla_get_lock)); - cqm_err(handle->dev_hdl, "Qpc mpt init: qpc mpt vaddr is null, cla_table->alloc_static=%d\n", - cla_table->alloc_static); - goto err1; - } - - /* Indexes are associated with objects, and FC is executed - * in the interrupt context. - */ - object_table = &cla_table->obj_table; - if (object->service_type == CQM_SERVICE_T_FC) { - if (cqm_object_table_insert(cqm_handle, object_table, index, - object, false) != CQM_SUCCESS) { - cqm_err(handle->dev_hdl, - CQM_FUNCTION_FAIL(cqm_object_table_insert)); - goto err2; - } - } else { - if (cqm_object_table_insert(cqm_handle, object_table, index, - object, true) != CQM_SUCCESS) { - cqm_err(handle->dev_hdl, - CQM_FUNCTION_FAIL(cqm_object_table_insert)); - goto err2; - } - } - - return CQM_SUCCESS; - -err2: - cqm_cla_put(cqm_handle, cla_table, index, count); -err1: - cqm_bitmap_free(bitmap, index, count); - return CQM_FAIL; -} - -struct cqm_qpc_mpt *cqm3_object_qpc_mpt_create(void *ex_handle, u32 service_type, - enum cqm_object_type object_type, - u32 object_size, void *object_priv, - u32 index) -{ - struct sphw_hwdev *handle = (struct sphw_hwdev *)ex_handle; - struct cqm_qpc_mpt_info *qpc_mpt_info = NULL; - struct cqm_handle *cqm_handle = NULL; - s32 ret = CQM_FAIL; - - CQM_PTR_CHECK_RET(ex_handle, NULL, CQM_PTR_NULL(ex_handle)); - - atomic_inc(&handle->hw_stats.cqm_stats.cqm_qpc_mpt_create_cnt); - - cqm_handle = (struct cqm_handle *)(handle->cqm_hdl); - CQM_PTR_CHECK_RET(cqm_handle, NULL, CQM_PTR_NULL(cqm_handle)); - - if (service_type >= CQM_SERVICE_T_MAX) { - cqm_err(handle->dev_hdl, CQM_WRONG_VALUE(service_type)); - return NULL; - } - /* exception of service registrion check */ - if (!cqm_handle->service[service_type].has_register) { - cqm_err(handle->dev_hdl, CQM_WRONG_VALUE(service_type)); - return NULL; - } - - if (object_type != CQM_OBJECT_SERVICE_CTX) { - cqm_err(handle->dev_hdl, CQM_WRONG_VALUE(object_type)); - return NULL; - } - - qpc_mpt_info = kmalloc(sizeof(*qpc_mpt_info), GFP_ATOMIC | __GFP_ZERO); - CQM_PTR_CHECK_RET(qpc_mpt_info, NULL, CQM_ALLOC_FAIL(qpc_mpt_info)); - - qpc_mpt_info->common.object.service_type = service_type; - qpc_mpt_info->common.object.object_type = object_type; - qpc_mpt_info->common.object.object_size = object_size; - atomic_set(&qpc_mpt_info->common.object.refcount, 1); - init_completion(&qpc_mpt_info->common.object.free); - qpc_mpt_info->common.object.cqm_handle = cqm_handle; - qpc_mpt_info->common.xid = index; - - qpc_mpt_info->common.priv = object_priv; - - ret = cqm_qpc_mpt_create(&qpc_mpt_info->common.object); - if (ret == CQM_SUCCESS) - return &qpc_mpt_info->common; - - cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_qpc_mpt_create)); - kfree(qpc_mpt_info); - return NULL; -} - -void cqm_linkwqe_fill(struct cqm_buf *buf, u32 wqe_per_buf, u32 wqe_size, - u32 wqe_number, bool tail, u8 link_mode) -{ - struct cqm_linkwqe_128B *linkwqe = NULL; - struct cqm_linkwqe *wqe = NULL; - dma_addr_t addr; - u8 *tmp = NULL; - u8 *va = NULL; - u32 i; - - /* The linkwqe of other buffer except the last buffer - * is directly filled to the tail. - */ - for (i = 0; i < buf->buf_number; i++) { - va = (u8 *)(buf->buf_list[i].va); - - if (i != (buf->buf_number - 1)) { - wqe = (struct cqm_linkwqe *)(va + (u32)(wqe_size * wqe_per_buf)); - wqe->wf = CQM_WQE_WF_LINK; - wqe->ctrlsl = CQM_LINK_WQE_CTRLSL_VALUE; - wqe->lp = CQM_LINK_WQE_LP_INVALID; - /* The valid value of link wqe needs to be set to 1. - * Each service ensures that o-bit=1 indicates that - * link wqe is valid and o-bit=0 indicates that - * link wqe is invalid. - */ - wqe->o = CQM_LINK_WQE_OWNER_VALID; - addr = buf->buf_list[(u32)(i + 1)].pa; - wqe->next_page_gpa_h = CQM_ADDR_HI(addr); - wqe->next_page_gpa_l = CQM_ADDR_LW(addr); - } else { /* linkwqe special padding of the last buffer */ - if (tail) { - /* must be filled at the end of the page */ - tmp = va + (u32)(wqe_size * wqe_per_buf); - wqe = (struct cqm_linkwqe *)tmp; - } else { - /* The last linkwqe is filled - * following the last wqe. - */ - tmp = va + (u32)(wqe_size * (wqe_number - - wqe_per_buf * - (buf->buf_number - - 1))); - wqe = (struct cqm_linkwqe *)tmp; - } - wqe->wf = CQM_WQE_WF_LINK; - wqe->ctrlsl = CQM_LINK_WQE_CTRLSL_VALUE; - - /* In link mode, the last link WQE is invalid; - * In ring mode, the last link wqe is valid, pointing to - * the home page, and the lp is set. - */ - if (link_mode == CQM_QUEUE_LINK_MODE) { - wqe->o = CQM_LINK_WQE_OWNER_INVALID; - } else { - /* The lp field of the last link_wqe is set to - * 1, indicating that the meaning of the o-bit - * is reversed. - */ - wqe->lp = CQM_LINK_WQE_LP_VALID; - wqe->o = CQM_LINK_WQE_OWNER_VALID; - addr = buf->buf_list[0].pa; - wqe->next_page_gpa_h = CQM_ADDR_HI(addr); - wqe->next_page_gpa_l = CQM_ADDR_LW(addr); - } - } - - if (wqe_size == CQM_LINKWQE_128B) { - /* After the B800 version, the WQE obit scheme is - * changed. The 64B bits before and after the 128B WQE - * need to be assigned a value: - * ifoe the 63rd bit from the end of the last 64B is - * obit; - * toe the 157th bit from the end of the last 64B is - * obit. - */ - linkwqe = (struct cqm_linkwqe_128B *)wqe; - linkwqe->second64B.forth_16B.bs.ifoe_o = CQM_LINK_WQE_OWNER_VALID; - - /* shift 2 bits by right to get length of dw(4B) */ - cqm_swab32((u8 *)wqe, sizeof(struct cqm_linkwqe_128B) >> 2); - } else { - /* shift 2 bits by right to get length of dw(4B) */ - cqm_swab32((u8 *)wqe, sizeof(struct cqm_linkwqe) >> 2); - } - } -} - -s32 cqm_nonrdma_queue_ctx_create(struct cqm_object *object) -{ - struct cqm_queue *common = container_of(object, struct cqm_queue, object); - struct cqm_nonrdma_qinfo *qinfo = container_of(common, struct cqm_nonrdma_qinfo, - common); - struct cqm_handle *cqm_handle = (struct cqm_handle *)object->cqm_handle; - struct cqm_bat_table *bat_table = &cqm_handle->bat_table; - struct sphw_hwdev *handle = cqm_handle->ex_handle; - struct cqm_object_table *object_table = NULL; - struct cqm_cla_table *cla_table = NULL; - struct cqm_bitmap *bitmap = NULL; - s32 shift; - - if (object->object_type == CQM_OBJECT_NONRDMA_SRQ) { - shift = cqm_shift(qinfo->q_ctx_size); - common->q_ctx_vaddr = cqm_kmalloc_align(qinfo->q_ctx_size, - GFP_KERNEL | __GFP_ZERO, - (u16)shift); - if (!common->q_ctx_vaddr) { - cqm_err(handle->dev_hdl, CQM_ALLOC_FAIL(q_ctx_vaddr)); - return CQM_FAIL; - } - - common->q_ctx_paddr = pci_map_single(cqm_handle->dev, - common->q_ctx_vaddr, - qinfo->q_ctx_size, - PCI_DMA_BIDIRECTIONAL); - if (pci_dma_mapping_error(cqm_handle->dev, - common->q_ctx_paddr)) { - cqm_err(handle->dev_hdl, CQM_MAP_FAIL(q_ctx_vaddr)); - cqm_kfree_align(common->q_ctx_vaddr); - common->q_ctx_vaddr = NULL; - return CQM_FAIL; - } - } else if (object->object_type == CQM_OBJECT_NONRDMA_SCQ) { - /* find the corresponding cla table */ - cla_table = cqm_cla_table_get(bat_table, CQM_BAT_ENTRY_T_SCQC); - if (!cla_table) { - cqm_err(handle->dev_hdl, - CQM_FUNCTION_FAIL(nonrdma_cqm_cla_table_get)); - return CQM_FAIL; - } - - /* bitmap applies for index */ - bitmap = &cla_table->bitmap; - qinfo->index_count = - (ALIGN(qinfo->q_ctx_size, cla_table->obj_size)) / - cla_table->obj_size; - qinfo->common.index = cqm_bitmap_alloc(bitmap, 1U << (cla_table->z + 1), - qinfo->index_count, - cqm_handle->func_capability.xid_alloc_mode); - if (qinfo->common.index >= bitmap->max_num) { - cqm_err(handle->dev_hdl, - CQM_FUNCTION_FAIL(nonrdma_cqm_bitmap_alloc)); - return CQM_FAIL; - } - - /* find the trunk page from BAT/CLA and allocate the buffer */ - common->q_ctx_vaddr = cqm_cla_get_lock(cqm_handle, cla_table, - qinfo->common.index, - qinfo->index_count, - &common->q_ctx_paddr); - if (!common->q_ctx_vaddr) { - cqm_err(handle->dev_hdl, - CQM_FUNCTION_FAIL(nonrdma_cqm_cla_get_lock)); - cqm_bitmap_free(bitmap, qinfo->common.index, - qinfo->index_count); - return CQM_FAIL; - } - - /* index and object association */ - object_table = &cla_table->obj_table; - if (object->service_type == CQM_SERVICE_T_FC) { - if (cqm_object_table_insert(cqm_handle, object_table, - qinfo->common.index, object, - false) != CQM_SUCCESS) { - cqm_err(handle->dev_hdl, - CQM_FUNCTION_FAIL(nonrdma_cqm_object_table_insert)); - cqm_cla_put(cqm_handle, cla_table, - qinfo->common.index, - qinfo->index_count); - cqm_bitmap_free(bitmap, qinfo->common.index, - qinfo->index_count); - return CQM_FAIL; - } - } else { - if (cqm_object_table_insert(cqm_handle, object_table, - qinfo->common.index, object, - true) != CQM_SUCCESS) { - cqm_err(handle->dev_hdl, - CQM_FUNCTION_FAIL(nonrdma_cqm_object_table_insert)); - cqm_cla_put(cqm_handle, cla_table, - qinfo->common.index, - qinfo->index_count); - cqm_bitmap_free(bitmap, qinfo->common.index, - qinfo->index_count); - return CQM_FAIL; - } - } - } - - return CQM_SUCCESS; -} - -s32 cqm_nonrdma_queue_create(struct cqm_object *object) -{ - struct cqm_queue *common = container_of(object, struct cqm_queue, object); - struct cqm_nonrdma_qinfo *qinfo = container_of(common, struct cqm_nonrdma_qinfo, - common); - struct cqm_handle *cqm_handle = (struct cqm_handle *)object->cqm_handle; - struct cqm_service *service = cqm_handle->service + object->service_type; - struct cqm_buf *q_room_buf = &common->q_room_buf_1; - struct sphw_hwdev *handle = cqm_handle->ex_handle; - u32 wqe_number = qinfo->common.object.object_size; - u32 wqe_size = qinfo->wqe_size; - u32 order = service->buf_order; - u32 buf_number, buf_size; - bool tail = false; /* determine whether the linkwqe is at the end of the page */ - - /* When creating a CQ/SCQ queue, the page size is 4 KB, - * the linkwqe must be at the end of the page. - */ - if (object->object_type == CQM_OBJECT_NONRDMA_EMBEDDED_CQ || - object->object_type == CQM_OBJECT_NONRDMA_SCQ) { - /* depth: 2^n-aligned; depth range: 256-32 K */ - if (wqe_number < CQM_CQ_DEPTH_MIN || - wqe_number > CQM_CQ_DEPTH_MAX) { - cqm_err(handle->dev_hdl, CQM_WRONG_VALUE(wqe_number)); - return CQM_FAIL; - } - if (!cqm_check_align(wqe_number)) { - cqm_err(handle->dev_hdl, "Nonrdma queue alloc: wqe_number is not align on 2^n\n"); - return CQM_FAIL; - } - - order = CQM_4K_PAGE_ORDER; /* wqe page 4k */ - tail = true; /* The linkwqe must be at the end of the page. */ - buf_size = CQM_4K_PAGE_SIZE; - } else { - buf_size = (u32)(PAGE_SIZE << order); - } - - /* Calculate the total number of buffers required, - * -1 indicates that the link wqe in a buffer is deducted. - */ - qinfo->wqe_per_buf = (buf_size / wqe_size) - 1; - /* number of linkwqes that are included in the depth transferred - * by the service - */ - buf_number = ALIGN((wqe_size * wqe_number), buf_size) / buf_size; - - /* apply for buffer */ - q_room_buf->buf_number = buf_number; - q_room_buf->buf_size = buf_size; - q_room_buf->page_number = buf_number << order; - if (cqm_buf_alloc(cqm_handle, q_room_buf, false) == CQM_FAIL) { - cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_buf_alloc)); - return CQM_FAIL; - } - /* fill link wqe, wqe_number - buf_number is the number of wqe without - * link wqe - */ - cqm_linkwqe_fill(q_room_buf, qinfo->wqe_per_buf, wqe_size, - wqe_number - buf_number, tail, - common->queue_link_mode); - - /* create queue header */ - qinfo->common.q_header_vaddr = cqm_kmalloc_align(sizeof(struct cqm_queue_header), - GFP_KERNEL | __GFP_ZERO, - CQM_QHEAD_ALIGN_ORDER); - if (!qinfo->common.q_header_vaddr) { - cqm_err(handle->dev_hdl, CQM_ALLOC_FAIL(q_header_vaddr)); - goto err1; - } - - common->q_header_paddr = pci_map_single(cqm_handle->dev, - qinfo->common.q_header_vaddr, - sizeof(struct cqm_queue_header), - PCI_DMA_BIDIRECTIONAL); - if (pci_dma_mapping_error(cqm_handle->dev, common->q_header_paddr)) { - cqm_err(handle->dev_hdl, CQM_MAP_FAIL(q_header_vaddr)); - goto err2; - } - - /* create queue ctx */ - if (cqm_nonrdma_queue_ctx_create(object) == CQM_FAIL) { - cqm_err(handle->dev_hdl, - CQM_FUNCTION_FAIL(cqm_nonrdma_queue_ctx_create)); - goto err3; - } - - return CQM_SUCCESS; - -err3: - pci_unmap_single(cqm_handle->dev, common->q_header_paddr, - sizeof(struct cqm_queue_header), PCI_DMA_BIDIRECTIONAL); -err2: - cqm_kfree_align(qinfo->common.q_header_vaddr); - qinfo->common.q_header_vaddr = NULL; -err1: - cqm_buf_free(q_room_buf, cqm_handle->dev); - return CQM_FAIL; -} - -struct cqm_queue *cqm3_object_fc_srq_create(void *ex_handle, u32 service_type, - enum cqm_object_type object_type, - u32 wqe_number, u32 wqe_size, - void *object_priv) -{ - struct sphw_hwdev *handle = (struct sphw_hwdev *)ex_handle; - struct cqm_nonrdma_qinfo *nonrdma_qinfo = NULL; - struct cqm_handle *cqm_handle = NULL; - struct cqm_service *service = NULL; - u32 valid_wqe_per_buffer; - u32 wqe_sum; /* include linkwqe, normal wqe */ - u32 buf_size; - u32 buf_num; - s32 ret; - - CQM_PTR_CHECK_RET(ex_handle, NULL, CQM_PTR_NULL(ex_handle)); - - atomic_inc(&handle->hw_stats.cqm_stats.cqm_fc_srq_create_cnt); - - cqm_handle = (struct cqm_handle *)(handle->cqm_hdl); - CQM_PTR_CHECK_RET(cqm_handle, NULL, CQM_PTR_NULL(cqm_handle)); - - /* service_type must be fc */ - if (service_type != CQM_SERVICE_T_FC) { - cqm_err(handle->dev_hdl, CQM_WRONG_VALUE(service_type)); - return NULL; - } - - /* exception of service unregistered check */ - if (!cqm_handle->service[service_type].has_register) { - cqm_err(handle->dev_hdl, CQM_WRONG_VALUE(service_type)); - return NULL; - } - - /* wqe_size cannot exceed PAGE_SIZE and must be 2^n aligned. */ - if (wqe_size >= PAGE_SIZE || (!cqm_check_align(wqe_size))) { - cqm_err(handle->dev_hdl, CQM_WRONG_VALUE(wqe_size)); - return NULL; - } - - /* FC RQ is SRQ. (Different from the SRQ concept of TOE, FC indicates - * that packets received by all flows are placed on the same RQ. - * The SRQ of TOE is similar to the RQ resource pool.) - */ - if (object_type != CQM_OBJECT_NONRDMA_SRQ) { - cqm_err(handle->dev_hdl, CQM_WRONG_VALUE(object_type)); - return NULL; - } - - service = &cqm_handle->service[service_type]; - buf_size = (u32)(PAGE_SIZE << (service->buf_order)); - /* subtract 1 link wqe */ - valid_wqe_per_buffer = buf_size / wqe_size - 1; - buf_num = wqe_number / valid_wqe_per_buffer; - if (wqe_number % valid_wqe_per_buffer != 0) - buf_num++; - - /* calculate the total number of WQEs */ - wqe_sum = buf_num * (valid_wqe_per_buffer + 1); - nonrdma_qinfo = kmalloc(sizeof(*nonrdma_qinfo), GFP_KERNEL | __GFP_ZERO); - CQM_PTR_CHECK_RET(nonrdma_qinfo, NULL, CQM_ALLOC_FAIL(nonrdma_qinfo)); - - /* initialize object member */ - nonrdma_qinfo->common.object.service_type = service_type; - nonrdma_qinfo->common.object.object_type = object_type; - /* total number of WQEs */ - nonrdma_qinfo->common.object.object_size = wqe_sum; - atomic_set(&nonrdma_qinfo->common.object.refcount, 1); - init_completion(&nonrdma_qinfo->common.object.free); - nonrdma_qinfo->common.object.cqm_handle = cqm_handle; - - /* Initialize the doorbell used by the current queue. - * The default doorbell is the hardware doorbell. - */ - nonrdma_qinfo->common.current_q_doorbell = CQM_HARDWARE_DOORBELL; - /* Currently, the connection mode is fixed. In the future, - * the service needs to transfer the connection mode. - */ - nonrdma_qinfo->common.queue_link_mode = CQM_QUEUE_RING_MODE; - - /* initialize public members */ - nonrdma_qinfo->common.priv = object_priv; - nonrdma_qinfo->common.valid_wqe_num = wqe_sum - buf_num; - - /* initialize internal private members */ - nonrdma_qinfo->wqe_size = wqe_size; - /* RQ (also called SRQ of FC) created by FC services, - * CTX needs to be created. - */ - nonrdma_qinfo->q_ctx_size = service->service_template.srq_ctx_size; - - ret = cqm_nonrdma_queue_create(&nonrdma_qinfo->common.object); - if (ret == CQM_SUCCESS) - return &nonrdma_qinfo->common; - - cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_fc_queue_create)); - kfree(nonrdma_qinfo); - return NULL; -} - -struct cqm_queue *cqm3_object_nonrdma_queue_create(void *ex_handle, u32 service_type, - enum cqm_object_type object_type, - u32 wqe_number, u32 wqe_size, - void *object_priv) -{ - struct sphw_hwdev *handle = (struct sphw_hwdev *)ex_handle; - struct cqm_nonrdma_qinfo *nonrdma_qinfo = NULL; - struct cqm_handle *cqm_handle = NULL; - struct cqm_service *service = NULL; - s32 ret; - - CQM_PTR_CHECK_RET(ex_handle, NULL, CQM_PTR_NULL(ex_handle)); - - atomic_inc(&handle->hw_stats.cqm_stats.cqm_nonrdma_queue_create_cnt); - - cqm_handle = (struct cqm_handle *)(handle->cqm_hdl); - CQM_PTR_CHECK_RET(cqm_handle, NULL, CQM_PTR_NULL(cqm_handle)); - - /* exception of service registrion check */ - if (!cqm_handle->service[service_type].has_register) { - cqm_err(handle->dev_hdl, CQM_WRONG_VALUE(service_type)); - return NULL; - } - /* wqe_size can't be more than PAGE_SIZE, can't be zero, must be power - * of 2 the function of cqm_check_align is to check above - */ - if (wqe_size >= PAGE_SIZE || (!cqm_check_align(wqe_size))) { - cqm_err(handle->dev_hdl, CQM_WRONG_VALUE(wqe_size)); - return NULL; - } - - /* nonrdma supports: RQ, SQ, SRQ, CQ, SCQ */ - if (object_type < CQM_OBJECT_NONRDMA_EMBEDDED_RQ || - object_type > CQM_OBJECT_NONRDMA_SCQ) { - cqm_err(handle->dev_hdl, CQM_WRONG_VALUE(object_type)); - return NULL; - } - - nonrdma_qinfo = kmalloc(sizeof(*nonrdma_qinfo), GFP_KERNEL | __GFP_ZERO); - CQM_PTR_CHECK_RET(nonrdma_qinfo, NULL, CQM_ALLOC_FAIL(nonrdma_qinfo)); - - nonrdma_qinfo->common.object.service_type = service_type; - nonrdma_qinfo->common.object.object_type = object_type; - nonrdma_qinfo->common.object.object_size = wqe_number; - atomic_set(&nonrdma_qinfo->common.object.refcount, 1); - init_completion(&nonrdma_qinfo->common.object.free); - nonrdma_qinfo->common.object.cqm_handle = cqm_handle; - - /* Initialize the doorbell used by the current queue. - * The default value is hardware doorbell - */ - nonrdma_qinfo->common.current_q_doorbell = CQM_HARDWARE_DOORBELL; - /* Currently, the link mode is hardcoded and needs to be transferred by - * the service side. - */ - nonrdma_qinfo->common.queue_link_mode = CQM_QUEUE_RING_MODE; - - nonrdma_qinfo->common.priv = object_priv; - - /* Initialize internal private members */ - nonrdma_qinfo->wqe_size = wqe_size; - service = &cqm_handle->service[service_type]; - switch (object_type) { - case CQM_OBJECT_NONRDMA_SCQ: - nonrdma_qinfo->q_ctx_size = - service->service_template.scq_ctx_size; - break; - case CQM_OBJECT_NONRDMA_SRQ: - /* Currently, the SRQ of the service is created through a - * dedicated interface. - */ - nonrdma_qinfo->q_ctx_size = - service->service_template.srq_ctx_size; - break; - default: - break; - } - - ret = cqm_nonrdma_queue_create(&nonrdma_qinfo->common.object); - if (ret == CQM_SUCCESS) - return &nonrdma_qinfo->common; - - cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_nonrdma_queue_create)); - kfree(nonrdma_qinfo); - return NULL; -} - -void cqm_qpc_mpt_delete(struct cqm_object *object) -{ - struct cqm_qpc_mpt *common = container_of(object, struct cqm_qpc_mpt, object); - struct cqm_qpc_mpt_info *qpc_mpt_info = container_of(common, - struct cqm_qpc_mpt_info, - common); - struct cqm_handle *cqm_handle = (struct cqm_handle *)object->cqm_handle; - struct cqm_bat_table *bat_table = &cqm_handle->bat_table; - struct sphw_hwdev *handle = cqm_handle->ex_handle; - struct cqm_object_table *object_table = NULL; - struct cqm_cla_table *cla_table = NULL; - u32 count = qpc_mpt_info->index_count; - u32 index = qpc_mpt_info->common.xid; - struct cqm_bitmap *bitmap = NULL; - - atomic_inc(&handle->hw_stats.cqm_stats.cqm_qpc_mpt_delete_cnt); - - /* find the corresponding cla table */ - if (object->object_type == CQM_OBJECT_SERVICE_CTX) { - cla_table = cqm_cla_table_get(bat_table, CQM_BAT_ENTRY_T_QPC); - } else { - cqm_err(handle->dev_hdl, CQM_WRONG_VALUE(object->object_type)); - return; - } - - CQM_PTR_CHECK_NO_RET(cla_table, - CQM_FUNCTION_FAIL(cqm_cla_table_get_qpc)); - - /* disassociate index and object */ - object_table = &cla_table->obj_table; - if (object->service_type == CQM_SERVICE_T_FC) - cqm_object_table_remove(cqm_handle, object_table, index, object, - false); - else - cqm_object_table_remove(cqm_handle, object_table, index, object, - true); - - /* wait for completion to ensure that all references to - * the QPC are complete - */ - if (atomic_dec_and_test(&object->refcount)) - complete(&object->free); - else - cqm_err(handle->dev_hdl, "Qpc mpt del: object is referred by others, has to wait for completion\n"); - - /* Static QPC allocation must be non-blocking. - * Services ensure that the QPC is referenced - * when the QPC is deleted. - */ - if (!cla_table->alloc_static) - wait_for_completion(&object->free); - - /* release qpc buffer */ - cqm_cla_put(cqm_handle, cla_table, index, count); - - /* release the index to the bitmap */ - bitmap = &cla_table->bitmap; - cqm_bitmap_free(bitmap, index, count); -} - -s32 cqm_qpc_mpt_delete_ret(struct cqm_object *object) -{ - u32 object_type; - - object_type = object->object_type; - switch (object_type) { - case CQM_OBJECT_SERVICE_CTX: - cqm_qpc_mpt_delete(object); - return CQM_SUCCESS; - default: - return CQM_FAIL; - } -} - -void cqm_nonrdma_queue_delete(struct cqm_object *object) -{ - struct cqm_queue *common = container_of(object, struct cqm_queue, object); - struct cqm_nonrdma_qinfo *qinfo = container_of(common, struct cqm_nonrdma_qinfo, - common); - struct cqm_handle *cqm_handle = (struct cqm_handle *)object->cqm_handle; - struct cqm_bat_table *bat_table = &cqm_handle->bat_table; - struct cqm_buf *q_room_buf = &common->q_room_buf_1; - struct sphw_hwdev *handle = cqm_handle->ex_handle; - struct cqm_object_table *object_table = NULL; - struct cqm_cla_table *cla_table = NULL; - struct cqm_bitmap *bitmap = NULL; - u32 index = qinfo->common.index; - u32 count = qinfo->index_count; - - atomic_inc(&handle->hw_stats.cqm_stats.cqm_nonrdma_queue_delete_cnt); - - /* The SCQ has an independent SCQN association. */ - if (object->object_type == CQM_OBJECT_NONRDMA_SCQ) { - cla_table = cqm_cla_table_get(bat_table, CQM_BAT_ENTRY_T_SCQC); - CQM_PTR_CHECK_NO_RET(cla_table, CQM_FUNCTION_FAIL(cqm_cla_table_get_queue)); - - /* disassociate index and object */ - object_table = &cla_table->obj_table; - if (object->service_type == CQM_SERVICE_T_FC) - cqm_object_table_remove(cqm_handle, object_table, index, - object, false); - else - cqm_object_table_remove(cqm_handle, object_table, index, - object, true); - } - - /* wait for completion to ensure that all references to - * the QPC are complete - */ - if (atomic_dec_and_test(&object->refcount)) - complete(&object->free); - else - cqm_err(handle->dev_hdl, "Nonrdma queue del: object is referred by others, has to wait for completion\n"); - - wait_for_completion(&object->free); - - /* If the q header exists, release. */ - if (qinfo->common.q_header_vaddr) { - pci_unmap_single(cqm_handle->dev, common->q_header_paddr, - sizeof(struct cqm_queue_header), - PCI_DMA_BIDIRECTIONAL); - - cqm_kfree_align(qinfo->common.q_header_vaddr); - qinfo->common.q_header_vaddr = NULL; - } - - cqm_buf_free(q_room_buf, cqm_handle->dev); - /* SRQ and SCQ have independent CTXs and release. */ - if (object->object_type == CQM_OBJECT_NONRDMA_SRQ) { - /* The CTX of the SRQ of the nordma is - * applied for independently. - */ - if (common->q_ctx_vaddr) { - pci_unmap_single(cqm_handle->dev, common->q_ctx_paddr, - qinfo->q_ctx_size, - PCI_DMA_BIDIRECTIONAL); - - cqm_kfree_align(common->q_ctx_vaddr); - common->q_ctx_vaddr = NULL; - } - } else if (object->object_type == CQM_OBJECT_NONRDMA_SCQ) { - /* The CTX of the SCQ of the nordma is managed by BAT/CLA. */ - cqm_cla_put(cqm_handle, cla_table, index, count); - - /* release the index to the bitmap */ - bitmap = &cla_table->bitmap; - cqm_bitmap_free(bitmap, index, count); - } -} - -s32 cqm_nonrdma_queue_delete_ret(struct cqm_object *object) -{ - u32 object_type; - - object_type = object->object_type; - switch (object_type) { - case CQM_OBJECT_NONRDMA_EMBEDDED_RQ: - case CQM_OBJECT_NONRDMA_EMBEDDED_SQ: - case CQM_OBJECT_NONRDMA_EMBEDDED_CQ: - case CQM_OBJECT_NONRDMA_SCQ: - cqm_nonrdma_queue_delete(object); - return CQM_SUCCESS; - case CQM_OBJECT_NONRDMA_SRQ: - cqm_nonrdma_queue_delete(object); - return CQM_SUCCESS; - default: - return CQM_FAIL; - } -} - -void cqm3_object_delete(struct cqm_object *object) -{ - struct cqm_handle *cqm_handle = NULL; - struct sphw_hwdev *handle = NULL; - - CQM_PTR_CHECK_NO_RET(object, CQM_PTR_NULL(object)); - if (!object->cqm_handle) { - pr_err("[CQM]object del: cqm_handle is null, service type %u, refcount %d\n", - object->service_type, (int)object->refcount.counter); - kfree(object); - return; - } - - cqm_handle = (struct cqm_handle *)object->cqm_handle; - - if (!cqm_handle->ex_handle) { - pr_err("[CQM]object del: ex_handle is null, service type %u, refcount %d\n", - object->service_type, (int)object->refcount.counter); - kfree(object); - return; - } - - handle = cqm_handle->ex_handle; - - if (object->service_type >= CQM_SERVICE_T_MAX) { - cqm_err(handle->dev_hdl, CQM_WRONG_VALUE(object->service_type)); - kfree(object); - return; - } - - if (cqm_qpc_mpt_delete_ret(object) == CQM_SUCCESS) { - kfree(object); - return; - } - - if (cqm_nonrdma_queue_delete_ret(object) == CQM_SUCCESS) { - kfree(object); - return; - } - - cqm_err(handle->dev_hdl, CQM_WRONG_VALUE(object->object_type)); - kfree(object); -} - -struct cqm_object *cqm3_object_get(void *ex_handle, enum cqm_object_type object_type, - u32 index, bool bh) -{ - struct sphw_hwdev *handle = (struct sphw_hwdev *)ex_handle; - struct cqm_handle *cqm_handle = (struct cqm_handle *)(handle->cqm_hdl); - struct cqm_bat_table *bat_table = &cqm_handle->bat_table; - struct cqm_object_table *object_table = NULL; - struct cqm_cla_table *cla_table = NULL; - struct cqm_object *object = NULL; - - /* The data flow path takes performance into consideration and - * does not check input parameters. - */ - switch (object_type) { - case CQM_OBJECT_SERVICE_CTX: - cla_table = cqm_cla_table_get(bat_table, CQM_BAT_ENTRY_T_QPC); - break; - case CQM_OBJECT_NONRDMA_SCQ: - cla_table = cqm_cla_table_get(bat_table, CQM_BAT_ENTRY_T_SCQC); - break; - default: - return NULL; - } - - if (!cla_table) { - cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_cla_table_get)); - return NULL; - } - - object_table = &cla_table->obj_table; - object = cqm_object_table_get(cqm_handle, object_table, index, bh); - return object; -} - -void cqm3_object_put(struct cqm_object *object) -{ - /* The data flow path takes performance into consideration and - * does not check input parameters. - */ - if (atomic_dec_and_test(&object->refcount)) - complete(&object->free); -} diff --git a/drivers/scsi/spfc/hw/spfc_cqm_object.h b/drivers/scsi/spfc/hw/spfc_cqm_object.h deleted file mode 100644 index 02a3e9070162..000000000000 --- a/drivers/scsi/spfc/hw/spfc_cqm_object.h +++ /dev/null @@ -1,279 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPFC_CQM_OBJECT_H -#define SPFC_CQM_OBJECT_H - -#ifdef __cplusplus -#if __cplusplus -extern "C" { -#endif -#endif /* __cplusplus */ - -#define CQM_SUCCESS 0 -#define CQM_FAIL (-1) -/* Ignore the return value and continue */ -#define CQM_CONTINUE 1 - -/* type of WQE is LINK WQE */ -#define CQM_WQE_WF_LINK 1 - -/* chain queue mode */ -#define CQM_QUEUE_LINK_MODE 0 -/* RING queue mode */ -#define CQM_QUEUE_RING_MODE 1 - -#define CQM_CQ_DEPTH_MAX 32768 -#define CQM_CQ_DEPTH_MIN 256 - -/* linkwqe */ -#define CQM_LINK_WQE_CTRLSL_VALUE 2 -#define CQM_LINK_WQE_LP_VALID 1 -#define CQM_LINK_WQE_LP_INVALID 0 -#define CQM_LINK_WQE_OWNER_VALID 1 -#define CQM_LINK_WQE_OWNER_INVALID 0 - -#define CQM_ADDR_HI(addr) ((u32)((u64)(addr) >> 32)) -#define CQM_ADDR_LW(addr) ((u32)((u64)(addr) & 0xffffffff)) - -#define CQM_QPC_LAYOUT_TABLE_SIZE 16 - -#define CQM_MOD_CQM 8 - -/* generic linkwqe structure */ -struct cqm_linkwqe { - u32 rsv1 : 14; /* <reserved field */ - u32 wf : 1; /* <wf */ - u32 rsv2 : 14; /* <reserved field */ - u32 ctrlsl : 2; /* <ctrlsl */ - u32 o : 1; /* <o bit */ - - u32 rsv3 : 31; /* <reserved field */ - u32 lp : 1; /* The lp field determines whether the o-bit meaning is reversed. */ - u32 next_page_gpa_h; - u32 next_page_gpa_l; - u32 next_buffer_addr_h; - u32 next_buffer_addr_l; -}; - -/* SRQ linkwqe structure. The wqe size must not exceed the common RQE size. */ -struct cqm_srq_linkwqe { - struct cqm_linkwqe linkwqe; /* <generic linkwqe structure */ - u32 current_buffer_gpa_h; - u32 current_buffer_gpa_l; - u32 current_buffer_addr_h; - u32 current_buffer_addr_l; - - u32 fast_link_page_addr_h; - u32 fast_link_page_addr_l; - - u32 fixed_next_buffer_addr_h; - u32 fixed_next_buffer_addr_l; -}; - -#define CQM_LINKWQE_128B 128 - -/* first 64B of standard 128B WQE */ -union cqm_linkwqe_first64B { - struct cqm_linkwqe basic_linkwqe; /* <generic linkwqe structure */ - u32 value[16]; /* <reserved field */ -}; - -/* second 64B of standard 128B WQE */ -struct cqm_linkwqe_second64B { - u32 rsvd0[4]; /* <first 16B reserved field */ - u32 rsvd1[4]; /* <second 16B reserved field */ - u32 rsvd2[4]; - - union { - struct { - u32 rsvd0[2]; - u32 rsvd1 : 31; - u32 ifoe_o : 1; /* <o bit of ifoe */ - u32 rsvd2; - } bs; - u32 value[4]; - } forth_16B; /* <fourth 16B */ -}; - -/* standard 128B WQE structure */ -struct cqm_linkwqe_128B { - union cqm_linkwqe_first64B first64B; /* <first 64B of standard 128B WQE */ - struct cqm_linkwqe_second64B second64B; /* <back 64B of standard 128B WQE */ -}; - -/* AEQ type definition */ -enum cqm_aeq_event_type { - CQM_AEQ_BASE_T_FC = 48, /* <FC consists of 8 events:48~55 */ - CQM_AEQ_MAX_T_FC = 56 -}; - -/* service registration template */ -struct service_register_template { - u32 service_type; /* <service type */ - u32 srq_ctx_size; /* <SRQ context size */ - u32 scq_ctx_size; /* <SCQ context size */ - void *service_handle; - u8 (*aeq_level_callback)(void *service_handle, u8 event_type, u8 *val); - void (*aeq_callback)(void *service_handle, u8 event_type, u8 *val); -}; - -/* object operation type definition */ -enum cqm_object_type { - CQM_OBJECT_ROOT_CTX = 0, /* <0:root context, which is compatible with root CTX management */ - CQM_OBJECT_SERVICE_CTX, /* <1:QPC, connection management object */ - CQM_OBJECT_NONRDMA_EMBEDDED_RQ = 10, /* <10:RQ of non-RDMA services, managed by LINKWQE */ - CQM_OBJECT_NONRDMA_EMBEDDED_SQ, /* <11:SQ of non-RDMA services, managed by LINKWQE */ - /* <12:SRQ of non-RDMA services, managed by MTT, but the CQM needs to apply for MTT. */ - CQM_OBJECT_NONRDMA_SRQ, - /* <13:Embedded CQ for non-RDMA services, managed by LINKWQE */ - CQM_OBJECT_NONRDMA_EMBEDDED_CQ, - CQM_OBJECT_NONRDMA_SCQ, /* <14:SCQ of non-RDMA services, managed by LINKWQE */ -}; - -/* return value of the failure to apply for the BITMAP table */ -#define CQM_INDEX_INVALID (~(0U)) - -/* doorbell mode selected by the current Q, hardware doorbell */ -#define CQM_HARDWARE_DOORBELL 1 - -/* single-node structure of the CQM buffer */ -struct cqm_buf_list { - void *va; /* <virtual address */ - dma_addr_t pa; /* <physical address */ - u32 refcount; /* <reference count of the buf, which is used for internal buf management. */ -}; - -/* common management structure of the CQM buffer */ -struct cqm_buf { - struct cqm_buf_list *buf_list; /* <buffer list */ - /* <map the discrete buffer list to a group of consecutive addresses */ - struct cqm_buf_list direct; - u32 page_number; /* <buf_number in quantity of page_number=2^n */ - u32 buf_number; /* <number of buf_list nodes */ - u32 buf_size; /* <PAGE_SIZE in quantity of buf_size=2^n */ -}; - -/* CQM object structure, which can be considered - * as the base class abstracted from all queues/CTX. - */ -struct cqm_object { - u32 service_type; /* <service type */ - u32 object_type; /* <object type, such as context, queue, mpt, and mtt, etc */ - u32 object_size; /* <object Size, for queue/CTX/MPT, the unit is Byte*/ - atomic_t refcount; /* <reference counting */ - struct completion free; /* <release completed quantity */ - void *cqm_handle; /* <cqm_handle */ -}; - -/* structure of the QPC and MPT objects of the CQM */ -struct cqm_qpc_mpt { - struct cqm_object object; - u32 xid; - dma_addr_t paddr; /* <physical address of the QPC/MTT memory */ - void *priv; /* <private information about the object of the service driver. */ - u8 *vaddr; /* <virtual address of the QPC/MTT memory */ -}; - -/* queue header structure */ -struct cqm_queue_header { - u64 doorbell_record; /* <SQ/RQ DB content */ - u64 ci_record; /* <CQ DB content */ - u64 rsv1; - u64 rsv2; -}; - -/* queue management structure: for queues of non-RDMA services, embedded queues - * are managed by LinkWQE, SRQ and SCQ are managed by MTT, but MTT needs to be - * applied by CQM; the queue of the RDMA service is managed by the MTT. - */ -struct cqm_queue { - struct cqm_object object; /* <object base class */ - /* <The embedded queue and QP do not have indexes, but the SRQ and SCQ do. */ - u32 index; - /* <private information about the object of the service driver */ - void *priv; - /* <doorbell type selected by the current queue. HW/SW are used for the roce QP. */ - u32 current_q_doorbell; - u32 current_q_room; - struct cqm_buf q_room_buf_1; /* <nonrdma:only q_room_buf_1 can be set to q_room_buf */ - struct cqm_buf q_room_buf_2; /* <The CQ of RDMA reallocates the size of the queue room. */ - struct cqm_queue_header *q_header_vaddr; /* <queue header virtual address */ - dma_addr_t q_header_paddr; /* <physical address of the queue header */ - u8 *q_ctx_vaddr; /* <CTX virtual addresses of SRQ and SCQ */ - dma_addr_t q_ctx_paddr; /* <CTX physical addresses of SRQ and SCQ */ - u32 valid_wqe_num; /* <number of valid WQEs that are successfully created */ - u8 *tail_container; /* <tail pointer of the SRQ container */ - u8 *head_container; /* <head pointer of SRQ container */ - /* <Determine the connection mode during queue creation, such as link and ring. */ - u8 queue_link_mode; -}; - -struct cqm_qpc_layout_table_node { - u32 type; - u32 size; - u32 offset; - struct cqm_object *object; -}; - -struct cqm_qpc_mpt_info { - struct cqm_qpc_mpt common; - /* Different service has different QPC. - * The large QPC/mpt will occupy some continuous indexes in bitmap. - */ - u32 index_count; - struct cqm_qpc_layout_table_node qpc_layout_table[CQM_QPC_LAYOUT_TABLE_SIZE]; -}; - -struct cqm_nonrdma_qinfo { - struct cqm_queue common; - u32 wqe_size; - /* Number of WQEs in each buffer (excluding link WQEs) - * For SRQ, the value is the number of WQEs contained in a container. - */ - u32 wqe_per_buf; - u32 q_ctx_size; - /* When different services use CTXs of different sizes, - * a large CTX occupies multiple consecutive indexes in the bitmap. - */ - u32 index_count; - /* add for srq */ - u32 container_size; -}; - -/* sending command structure */ -struct cqm_cmd_buf { - void *buf; - dma_addr_t dma; - u16 size; -}; - -struct cqm_queue *cqm3_object_fc_srq_create(void *ex_handle, u32 service_type, - enum cqm_object_type object_type, - u32 wqe_number, u32 wqe_size, - void *object_priv); -struct cqm_qpc_mpt *cqm3_object_qpc_mpt_create(void *ex_handle, u32 service_type, - enum cqm_object_type object_type, - u32 object_size, void *object_priv, - u32 index); -struct cqm_queue *cqm3_object_nonrdma_queue_create(void *ex_handle, u32 service_type, - enum cqm_object_type object_type, - u32 wqe_number, u32 wqe_size, - void *object_priv); -void cqm3_object_delete(struct cqm_object *object); -struct cqm_object *cqm3_object_get(void *ex_handle, enum cqm_object_type object_type, - u32 index, bool bh); -void cqm3_object_put(struct cqm_object *object); - -s32 cqm3_ring_hardware_db_fc(void *ex_handle, u32 service_type, u8 db_count, - u8 pagenum, u64 db); -s32 cqm_ring_direct_wqe_db(void *ex_handle, u32 service_type, u8 db_count, void *direct_wqe); -s32 cqm_ring_direct_wqe_db_fc(void *ex_handle, u32 service_type, void *direct_wqe); - -#ifdef __cplusplus -#if __cplusplus -} -#endif -#endif /* __cplusplus */ - -#endif /* SPFC_CQM_OBJECT_H */ diff --git a/drivers/scsi/spfc/hw/spfc_hba.c b/drivers/scsi/spfc/hw/spfc_hba.c deleted file mode 100644 index b033dcb78bb3..000000000000 --- a/drivers/scsi/spfc/hw/spfc_hba.c +++ /dev/null @@ -1,1751 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#include "spfc_hba.h" -#include "spfc_module.h" -#include "spfc_utils.h" -#include "spfc_chipitf.h" -#include "spfc_io.h" -#include "spfc_lld.h" -#include "sphw_hw.h" -#include "spfc_cqm_main.h" - -struct spfc_hba_info *spfc_hba[SPFC_HBA_PORT_MAX_NUM]; -ulong probe_bit_map[SPFC_MAX_PROBE_PORT_NUM / SPFC_PORT_NUM_PER_TABLE]; -static ulong card_num_bit_map[SPFC_MAX_PROBE_PORT_NUM / SPFC_PORT_NUM_PER_TABLE]; -static struct spfc_card_num_manage card_num_manage[SPFC_MAX_CARD_NUM]; -spinlock_t probe_spin_lock; -u32 max_parent_qpc_num; - -static int spfc_probe(struct spfc_lld_dev *lld_dev, void **uld_dev, char *uld_dev_name); -static void spfc_remove(struct spfc_lld_dev *lld_dev, void *uld_dev); -static u32 spfc_initial_chip_access(struct spfc_hba_info *hba); -static void spfc_release_chip_access(struct spfc_hba_info *hba); -static u32 spfc_port_config_set(void *hba, enum unf_port_config_set_op opcode, void *var_in); -static u32 spfc_port_config_get(void *hba, enum unf_port_cfg_get_op opcode, void *para_out); -static u32 spfc_port_update_wwn(void *hba, void *para_in); -static u32 spfc_get_chip_info(struct spfc_hba_info *hba); -static u32 spfc_delete_scqc_via_cmdq_sync(struct spfc_hba_info *hba, u32 scqn); -static u32 spfc_delete_srqc_via_cmdq_sync(struct spfc_hba_info *hba, u64 sqrc_gpa); -static u32 spfc_get_hba_pcie_link_state(void *hba, void *link_state); -static u32 spfc_port_check_fw_ready(struct spfc_hba_info *hba); -static u32 spfc_set_port_state(void *hba, void *para_in); - -struct spfc_uld_info fc_uld_info = { - .probe = spfc_probe, - .remove = spfc_remove, - .resume = NULL, - .event = NULL, - .suspend = NULL, - .ioctl = NULL -}; - -struct service_register_template service_cqm_temp = { - .service_type = SERVICE_T_FC, - .scq_ctx_size = SPFC_SCQ_CNTX_SIZE, - .srq_ctx_size = SPFC_SRQ_CNTX_SIZE, /* srq, scq context_size configuration */ - .aeq_callback = spfc_process_aeqe, /* the API of asynchronous event from TILE to driver */ -}; - -/* default configuration: auto speed, auto topology, INI+TGT */ -static struct unf_cfg_item spfc_port_cfg_parm[] = { - {"port_id", 0, 0x110000, 0xffffff}, - /* port mode:INI(0x20), TGT(0x10), BOTH(0x30) */ - {"port_mode", 0, 0x20, 0xff}, - /* port topology, 0x3: loop , 0xc:p2p, 0xf:auto, 0x10:vn2vn */ - {"port_topology", 0, 0xf, 0x20}, - {"port_alpa", 0, 0xdead, 0xffff}, /* alpa address of port */ - /* queue depth of originator registered to SCSI midlayer */ - {"max_queue_depth", 0, 512, 512}, - {"sest_num", 0, 2048, 2048}, - {"max_login", 0, 2048, 2048}, - /* nodename from 32 bit to 64 bit */ - {"node_name_high", 0, 0x1000286e, 0xffffffff}, - /* nodename from 0 bit to 31 bit */ - {"node_name_low", 0, 0xd4bbf12f, 0xffffffff}, - /* portname from 32 bit to 64 bit */ - {"port_name_high", 0, 0x2000286e, 0xffffffff}, - /* portname from 0 bit to 31 bit */ - {"port_name_low", 0, 0xd4bbf12f, 0xffffffff}, - /* port speed 0:auto 1:1Gbps 2:2Gbps 3:4Gbps 4:8Gbps 5:16Gbps */ - {"port_speed", 0, 0, 32}, - {"interrupt_delay", 0, 0, 100}, /* unit: us */ - {"tape_support", 0, 0, 1}, /* tape support */ - {"End", 0, 0, 0} -}; - -struct unf_low_level_functioon_op spfc_func_op = { - .low_level_type = UNF_SPFC_FC, - .name = "SPFC", - .xchg_mgr_type = UNF_LOW_LEVEL_MGR_TYPE_PASSTIVE, - .abts_xchg = UNF_NO_EXTRA_ABTS_XCHG, - .passthrough_flag = UNF_LOW_LEVEL_PASS_THROUGH_PORT_LOGIN, - .support_max_npiv_num = UNF_SPFC_MAXNPIV_NUM, - .support_max_ssq_num = SPFC_MAX_SSQ_NUM - 1, - .chip_id = 0, - .support_max_speed = UNF_PORT_SPEED_32_G, - .support_max_rport = UNF_SPFC_MAXRPORT_NUM, - .sfp_type = UNF_PORT_TYPE_FC_SFP, - .rport_release_type = UNF_LOW_LEVEL_RELEASE_RPORT_ASYNC, - .sirt_page_mode = UNF_LOW_LEVEL_SIRT_PAGE_MODE_XCHG, - - /* Link service */ - .service_op = { - .unf_ls_gs_send = spfc_send_ls_gs_cmnd, - .unf_bls_send = spfc_send_bls_cmnd, - .unf_cmnd_send = spfc_send_scsi_cmnd, - .unf_release_rport_res = spfc_free_parent_resource, - .unf_flush_ini_resp_que = spfc_flush_ini_resp_queue, - .unf_alloc_rport_res = spfc_alloc_parent_resource, - .ll_release_xid = spfc_free_xid, - }, - - /* Port Mgr */ - .port_mgr_op = { - .ll_port_config_set = spfc_port_config_set, - .ll_port_config_get = spfc_port_config_get, - } -}; - -struct spfc_port_cfg_op { - enum unf_port_config_set_op opcode; - u32 (*spfc_operation)(void *hba, void *para); -}; - -struct spfc_port_cfg_op spfc_config_set_op[] = { - {UNF_PORT_CFG_SET_PORT_SWITCH, spfc_sfp_switch}, - {UNF_PORT_CFG_UPDATE_WWN, spfc_port_update_wwn}, - {UNF_PORT_CFG_SET_PORT_STATE, spfc_set_port_state}, - {UNF_PORT_CFG_UPDATE_FABRIC_PARAM, spfc_update_fabric_param}, - {UNF_PORT_CFG_UPDATE_PLOGI_PARAM, spfc_update_port_param}, - {UNF_PORT_CFG_SET_BUTT, NULL} -}; - -struct spfc_port_cfg_get_op { - enum unf_port_cfg_get_op opcode; - u32 (*spfc_operation)(void *hba, void *para); -}; - -struct spfc_port_cfg_get_op spfc_config_get_op[] = { - {UNF_PORT_CFG_GET_TOPO_ACT, spfc_get_topo_act}, - {UNF_PORT_CFG_GET_LOOP_MAP, spfc_get_loop_map}, - {UNF_PORT_CFG_GET_WORKBALE_BBCREDIT, spfc_get_workable_bb_credit}, - {UNF_PORT_CFG_GET_WORKBALE_BBSCN, spfc_get_workable_bb_scn}, - {UNF_PORT_CFG_GET_LOOP_ALPA, spfc_get_loop_alpa}, - {UNF_PORT_CFG_GET_MAC_ADDR, spfc_get_chip_msg}, - {UNF_PORT_CFG_GET_PCIE_LINK_STATE, spfc_get_hba_pcie_link_state}, - {UNF_PORT_CFG_GET_BUTT, NULL}, -}; - -static u32 spfc_set_port_state(void *hba, void *para_in) -{ - u32 ret = UNF_RETURN_ERROR; - enum unf_port_config_state port_state = UNF_PORT_CONFIG_STATE_START; - - - FC_CHECK_RETURN_VALUE(hba, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(para_in, UNF_RETURN_ERROR); - - port_state = *((enum unf_port_config_state *)para_in); - switch (port_state) { - case UNF_PORT_CONFIG_STATE_RESET: - ret = (u32)spfc_port_reset(hba); - break; - - default: - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[warn]Cannot set port_state(0x%x)", port_state); - break; - } - - return ret; - -} - -static u32 spfc_port_update_wwn(void *hba, void *para_in) -{ - struct unf_port_wwn *port_wwn = NULL; - struct spfc_hba_info *spfc_hba = hba; - - FC_CHECK_RETURN_VALUE(spfc_hba, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(para_in, UNF_RETURN_ERROR); - - port_wwn = (struct unf_port_wwn *)para_in; - - /* Update it to the hba in the later */ - *(u64 *)spfc_hba->sys_node_name = port_wwn->sys_node_name; - *(u64 *)spfc_hba->sys_port_name = port_wwn->sys_port_wwn; - - FC_DRV_PRINT(UNF_LOG_EQUIP_ATT, UNF_INFO, - "[info]Port(0x%x) updates WWNN(0x%llx) WWPN(0x%llx)", - spfc_hba->port_cfg.port_id, - *(u64 *)spfc_hba->sys_node_name, - *(u64 *)spfc_hba->sys_port_name); - - return RETURN_OK; -} - -static u32 spfc_port_config_set(void *hba, enum unf_port_config_set_op opcode, - void *var_in) -{ - u32 op_idx = 0; - - FC_CHECK_RETURN_VALUE(hba, UNF_RETURN_ERROR); - - for (op_idx = 0; op_idx < sizeof(spfc_config_set_op) / - sizeof(struct spfc_port_cfg_op); op_idx++) { - if (opcode == spfc_config_set_op[op_idx].opcode) { - if (!spfc_config_set_op[op_idx].spfc_operation) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[warn]Null operation for configuration, opcode(0x%x), operation ID(0x%x)", - opcode, op_idx); - - return UNF_RETURN_ERROR; - } - return spfc_config_set_op[op_idx].spfc_operation(hba, var_in); - } - } - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[warn]No operation code for configuration, opcode(0x%x)", - opcode); - - return UNF_RETURN_ERROR; -} - -static u32 spfc_port_config_get(void *hba, enum unf_port_cfg_get_op opcode, - void *para_out) -{ - u32 op_idx = 0; - - FC_CHECK_RETURN_VALUE(hba, UNF_RETURN_ERROR); - - for (op_idx = 0; op_idx < sizeof(spfc_config_get_op) / - sizeof(struct spfc_port_cfg_get_op); op_idx++) { - if (opcode == spfc_config_get_op[op_idx].opcode) { - if (!spfc_config_get_op[op_idx].spfc_operation) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[warn]Null operation to get configuration, opcode(0x%x), operation ID(0x%x)", - opcode, op_idx); - return UNF_RETURN_ERROR; - } - return spfc_config_get_op[op_idx].spfc_operation(hba, para_out); - } - } - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[warn]No operation to get configuration, opcode(0x%x)", - opcode); - - return UNF_RETURN_ERROR; -} - -static u32 spfc_fc_mode_check(void *hw_dev_handle) -{ - FC_CHECK_RETURN_VALUE(hw_dev_handle, UNF_RETURN_ERROR); - - if (!sphw_support_fc(hw_dev_handle, NULL)) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Work mode is error"); - return UNF_RETURN_ERROR; - } - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]Selected work mode is FC"); - - return RETURN_OK; -} - -static u32 spfc_check_port_cfg(const struct spfc_port_cfg *port_cfg) -{ - bool topo_condition = false; - bool speed_condition = false; - /* About Work Topology */ - topo_condition = ((port_cfg->port_topology != UNF_TOP_LOOP_MASK) && - (port_cfg->port_topology != UNF_TOP_P2P_MASK) && - (port_cfg->port_topology != UNF_TOP_AUTO_MASK)); - if (topo_condition) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Configured port topology(0x%x) is incorrect", - port_cfg->port_topology); - - return UNF_RETURN_ERROR; - } - - /* About Work Mode */ - if (port_cfg->port_mode != UNF_PORT_MODE_INI) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Configured port mode(0x%x) is incorrect", - port_cfg->port_mode); - - return UNF_RETURN_ERROR; - } - - /* About Work Speed */ - speed_condition = ((port_cfg->port_speed != UNF_PORT_SPEED_AUTO) && - (port_cfg->port_speed != UNF_PORT_SPEED_2_G) && - (port_cfg->port_speed != UNF_PORT_SPEED_4_G) && - (port_cfg->port_speed != UNF_PORT_SPEED_8_G) && - (port_cfg->port_speed != UNF_PORT_SPEED_16_G) && - (port_cfg->port_speed != UNF_PORT_SPEED_32_G)); - if (speed_condition) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Configured port speed(0x%x) is incorrect", - port_cfg->port_speed); - - return UNF_RETURN_ERROR; - } - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_INFO, - "[info]Check port configuration OK"); - - return RETURN_OK; -} - -static u32 spfc_get_port_cfg(struct spfc_hba_info *hba, - struct spfc_chip_info *chip_info, u8 card_num) -{ -#define UNF_CONFIG_ITEM_LEN 15 - /* Maximum length of a configuration item name, including the end - * character - */ -#define UNF_MAX_ITEM_NAME_LEN (32 + 1) - - /* Get and check parameters */ - char cfg_item[UNF_MAX_ITEM_NAME_LEN]; - u32 ret = UNF_RETURN_ERROR; - struct spfc_hba_info *spfc_hba = hba; - - FC_CHECK_RETURN_VALUE(spfc_hba, UNF_RETURN_ERROR); - memset((void *)cfg_item, 0, sizeof(cfg_item)); - - spfc_hba->card_info.func_num = (sphw_global_func_id(hba->dev_handle)) & UNF_FUN_ID_MASK; - spfc_hba->card_info.card_num = card_num; - - /* The range of PF of FC server is from PF1 to PF2 */ - snprintf(cfg_item, UNF_MAX_ITEM_NAME_LEN, "spfc_cfg_%1u", (spfc_hba->card_info.func_num)); - - cfg_item[UNF_MAX_ITEM_NAME_LEN - 1] = 0; - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_INFO, - "[info]Get port configuration: %s", cfg_item); - - /* Get configuration parameters from file */ - UNF_LOWLEVEL_GET_CFG_PARMS(ret, cfg_item, &spfc_port_cfg_parm[ARRAY_INDEX_0], - (u32 *)(void *)(&spfc_hba->port_cfg), - sizeof(spfc_port_cfg_parm) / sizeof(struct unf_cfg_item)); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Port(0x%x) can't get configuration", - spfc_hba->port_cfg.port_id); - - return ret; - } - - if (max_parent_qpc_num <= SPFC_MAX_PARENT_QPC_NUM) { - spfc_hba->port_cfg.sest_num = UNF_SPFC_MAXRPORT_NUM; - spfc_hba->port_cfg.max_login = UNF_SPFC_MAXRPORT_NUM; - } - - spfc_hba->port_cfg.port_id &= SPFC_PORT_ID_MASK; - spfc_hba->port_cfg.port_id |= spfc_hba->card_info.card_num << UNF_SHIFT_8; - spfc_hba->port_cfg.port_id |= spfc_hba->card_info.func_num; - spfc_hba->port_cfg.tape_support = (u32)chip_info->tape_support; - - /* Parameters check */ - ret = spfc_check_port_cfg(&spfc_hba->port_cfg); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Port(0x%x) check configuration incorrect", - spfc_hba->port_cfg.port_id); - - return ret; - } - - /* Set configuration which is got from file */ - spfc_hba->port_speed_cfg = spfc_hba->port_cfg.port_speed; - spfc_hba->port_topo_cfg = spfc_hba->port_cfg.port_topology; - spfc_hba->port_mode = (enum unf_port_mode)(spfc_hba->port_cfg.port_mode); - - return ret; -} - -void spfc_generate_sys_wwn(struct spfc_hba_info *hba) -{ - FC_CHECK_RETURN_VOID(hba); - - *(u64 *)hba->sys_node_name = (((u64)hba->port_cfg.node_name_hi << UNF_SHIFT_32) | - (hba->port_cfg.node_name_lo)); - *(u64 *)hba->sys_port_name = (((u64)hba->port_cfg.port_name_hi << UNF_SHIFT_32) | - (hba->port_cfg.port_name_lo)); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_INFO, - "[info]NodeName = 0x%llx, PortName = 0x%llx", - *(u64 *)hba->sys_node_name, *(u64 *)hba->sys_port_name); -} - -static u32 spfc_create_queues(struct spfc_hba_info *hba) -{ - u32 ret = UNF_RETURN_ERROR; - - FC_CHECK_RETURN_VALUE(hba, UNF_RETURN_ERROR); - - SPFC_FUNCTION_ENTER; - - /* Initialize shared resources of SCQ and SRQ in parent queue */ - ret = spfc_create_common_share_queues(hba); - if (ret != RETURN_OK) - goto out_create_common_queue_fail; - - /* Initialize parent queue manager resources */ - ret = spfc_alloc_parent_queue_mgr(hba); - if (ret != RETURN_OK) - goto out_free_share_queue_resource; - - /* Initialize shared WQE page pool in parent SQ */ - ret = spfc_alloc_parent_sq_wqe_page_pool(hba); - if (ret != RETURN_OK) - goto out_free_parent_queue_resource; - - ret = spfc_create_ssq(hba); - if (ret != RETURN_OK) - goto out_free_parent_wqe_page_pool; - - /* - * Notice: the configuration of SQ and QID(default_sqid) - * must be the same in FC - */ - hba->next_clear_sq = 0; - hba->default_sqid = SPFC_QID_SQ; - - SPFC_FUNCTION_RETURN; - return RETURN_OK; -out_free_parent_wqe_page_pool: - spfc_free_parent_sq_wqe_page_pool(hba); - -out_free_parent_queue_resource: - spfc_free_parent_queue_mgr(hba); - -out_free_share_queue_resource: - spfc_flush_scq_ctx(hba); - spfc_flush_srq_ctx(hba); - spfc_destroy_common_share_queues(hba); - -out_create_common_queue_fail: - SPFC_FUNCTION_RETURN; - - return ret; -} - -static u32 spfc_alloc_dma_buffers(struct spfc_hba_info *hba) -{ - struct pci_dev *pci_dev = NULL; - - FC_CHECK_RETURN_VALUE(hba, UNF_RETURN_ERROR); - pci_dev = hba->pci_dev; - FC_CHECK_RETURN_VALUE(pci_dev, UNF_RETURN_ERROR); - - hba->sfp_buf = dma_alloc_coherent(&hba->pci_dev->dev, - sizeof(struct unf_sfp_err_rome_info), - &hba->sfp_dma_addr, GFP_KERNEL); - if (!hba->sfp_buf) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Port(0x%x) can't allocate SFP DMA buffer", - hba->port_cfg.port_id); - - return UNF_RETURN_ERROR; - } - memset(hba->sfp_buf, 0, sizeof(struct unf_sfp_err_rome_info)); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]Port(0x%x) allocate sfp buffer(0x%p 0x%llx)", - hba->port_cfg.port_id, hba->sfp_buf, - (u64)hba->sfp_dma_addr); - - return RETURN_OK; -} - -static void spfc_free_dma_buffers(struct spfc_hba_info *hba) -{ - struct pci_dev *pci_dev = NULL; - - FC_CHECK_RETURN_VOID(hba); - pci_dev = hba->pci_dev; - FC_CHECK_RETURN_VOID(pci_dev); - - if (hba->sfp_buf) { - dma_free_coherent(&pci_dev->dev, sizeof(struct unf_sfp_err_rome_info), - hba->sfp_buf, hba->sfp_dma_addr); - - hba->sfp_buf = NULL; - hba->sfp_dma_addr = 0; - } -} - -static void spfc_destroy_queues(struct spfc_hba_info *hba) -{ - /* Free ssq */ - spfc_free_ssq(hba, SPFC_MAX_SSQ_NUM); - - /* Free parent queue resource */ - spfc_free_parent_queues(hba); - - /* Free queue manager resource */ - spfc_free_parent_queue_mgr(hba); - - /* Free linked List SQ and WQE page pool resource */ - spfc_free_parent_sq_wqe_page_pool(hba); - - /* Free shared SRQ and SCQ queue resource */ - spfc_destroy_common_share_queues(hba); -} - -static u32 spfc_alloc_default_session(struct spfc_hba_info *hba) -{ - struct unf_port_info rport_info = {0}; - u32 wait_sq_cnt = 0; - - rport_info.nport_id = 0xffffff; - rport_info.rport_index = SPFC_DEFAULT_RPORT_INDEX; - rport_info.local_nport_id = 0xffffff; - rport_info.port_name = 0; - rport_info.cs_ctrl = 0x81; - - if (spfc_alloc_parent_resource((void *)hba, &rport_info) != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Alloc default session resource failed"); - goto failed; - } - - for (;;) { - if (hba->default_sq_info.default_sq_flag == 1) - break; - - msleep(SPFC_WAIT_SESS_ENABLE_ONE_TIME_MS); - wait_sq_cnt++; - if (wait_sq_cnt >= SPFC_MAX_WAIT_LOOP_TIMES) { - hba->default_sq_info.default_sq_flag = 0xF; - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Wait Default Session enable timeout"); - goto failed; - } - } - - if (spfc_mbx_config_default_session(hba, 1) != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Notify up config default session table fail"); - goto failed; - } - - return RETURN_OK; - -failed: - spfc_sess_resource_free_sync((void *)hba, &rport_info); - return UNF_RETURN_ERROR; -} - -static u32 spfc_init_host_res(struct spfc_hba_info *hba) -{ - u32 ret = RETURN_OK; - struct spfc_hba_info *spfc_hba = hba; - - FC_CHECK_RETURN_VALUE(spfc_hba, UNF_RETURN_ERROR); - - SPFC_FUNCTION_ENTER; - - /* Initialize spin lock */ - spin_lock_init(&spfc_hba->hba_lock); - spin_lock_init(&spfc_hba->flush_state_lock); - spin_lock_init(&spfc_hba->clear_state_lock); - spin_lock_init(&spfc_hba->spin_lock); - spin_lock_init(&spfc_hba->srq_delay_info.srq_lock); - /* Initialize init_completion */ - init_completion(&spfc_hba->hba_init_complete); - init_completion(&spfc_hba->mbox_complete); - init_completion(&spfc_hba->vpf_complete); - init_completion(&spfc_hba->fcfi_complete); - init_completion(&spfc_hba->get_sfp_complete); - /* Step-1: initialize the communication channel between driver and uP */ - ret = spfc_initial_chip_access(spfc_hba); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]SPFC port(0x%x) can't initialize chip access", - spfc_hba->port_cfg.port_id); - - goto out_unmap_memory; - } - /* Step-2: get chip configuration information before creating - * queue resources - */ - ret = spfc_get_chip_info(spfc_hba); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]SPFC port(0x%x) can't get chip information", - spfc_hba->port_cfg.port_id); - - goto out_unmap_memory; - } - - /* Step-3: create queue resources */ - ret = spfc_create_queues(spfc_hba); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]SPFC port(0x%x) can't create queues", - spfc_hba->port_cfg.port_id); - - goto out_release_chip_access; - } - /* Allocate DMA buffer (SFP information) */ - ret = spfc_alloc_dma_buffers(spfc_hba); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]SPFC port(0x%x) can't allocate DMA buffers", - spfc_hba->port_cfg.port_id); - - goto out_destroy_queues; - } - /* Initialize status parameters */ - spfc_hba->active_port_speed = UNF_PORT_SPEED_UNKNOWN; - spfc_hba->active_topo = UNF_ACT_TOP_UNKNOWN; - spfc_hba->sfp_on = false; - spfc_hba->port_loop_role = UNF_LOOP_ROLE_MASTER_OR_SLAVE; - spfc_hba->phy_link = UNF_PORT_LINK_DOWN; - spfc_hba->queue_set_stage = SPFC_QUEUE_SET_STAGE_INIT; - - /* Initialize parameters referring to the lowlevel */ - spfc_hba->remote_rttov_tag = 0; - spfc_hba->port_bb_scn_cfg = SPFC_LOWLEVEL_DEFAULT_BB_SCN; - - /* Initialize timer, and the unit of E_D_TOV is ms */ - spfc_hba->remote_edtov_tag = 0; - spfc_hba->remote_bb_credit = 0; - spfc_hba->compared_bb_scn = 0; - spfc_hba->compared_edtov_val = UNF_DEFAULT_EDTOV; - spfc_hba->compared_ratov_val = UNF_DEFAULT_RATOV; - spfc_hba->removing = false; - spfc_hba->dev_present = true; - - /* Initialize parameters about cos */ - spfc_hba->cos_bitmap = cos_bit_map; - memset(spfc_hba->cos_rport_cnt, 0, SPFC_MAX_COS_NUM * sizeof(atomic_t)); - - /* Mailbox access completion */ - complete(&spfc_hba->mbox_complete); - - ret = spfc_alloc_default_session(spfc_hba); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]SPFC port(0x%x) can't allocate Default Session", - spfc_hba->port_cfg.port_id); - - goto out_destroy_dma_buff; - } - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]SPFC port(0x%x) initialize host resources succeeded", - spfc_hba->port_cfg.port_id); - - return ret; - -out_destroy_dma_buff: - spfc_free_dma_buffers(spfc_hba); -out_destroy_queues: - spfc_flush_scq_ctx(spfc_hba); - spfc_flush_srq_ctx(spfc_hba); - spfc_destroy_queues(spfc_hba); - -out_release_chip_access: - spfc_release_chip_access(spfc_hba); - -out_unmap_memory: - return ret; -} - -static u32 spfc_get_chip_info(struct spfc_hba_info *hba) -{ - u32 ret = RETURN_OK; - u32 exi_count = 0; - u32 exi_base = 0; - u32 exi_stride = 0; - u32 fun_idx = 0; - - FC_CHECK_RETURN_VALUE(hba, UNF_RETURN_ERROR); - - hba->vpid_start = hba->service_cap.dev_fc_cap.vp_id_start; - hba->vpid_end = hba->service_cap.dev_fc_cap.vp_id_end; - fun_idx = sphw_global_func_id(hba->dev_handle); - - exi_count = (max_parent_qpc_num <= SPFC_MAX_PARENT_QPC_NUM) ? - exit_count >> UNF_SHIFT_1 : exit_count; - exi_stride = (max_parent_qpc_num <= SPFC_MAX_PARENT_QPC_NUM) ? - exit_stride >> UNF_SHIFT_1 : exit_stride; - exi_base = exit_base; - - exi_base += (fun_idx * exi_stride); - hba->exi_base = SPFC_LSW(exi_base); - hba->exi_count = SPFC_LSW(exi_count); - hba->max_support_speed = max_speed; - hba->port_index = SPFC_LSB(fun_idx); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]Port(0x%x) base information: PortIndex=0x%x, ExiBase=0x%x, ExiCount=0x%x, VpIdStart=0x%x, VpIdEnd=0x%x, MaxSpeed=0x%x, Speed=0x%x, Topo=0x%x", - hba->port_cfg.port_id, hba->port_index, hba->exi_base, - hba->exi_count, hba->vpid_start, hba->vpid_end, - hba->max_support_speed, hba->port_speed_cfg, hba->port_topo_cfg); - - return ret; -} - -static u32 spfc_initial_chip_access(struct spfc_hba_info *hba) -{ - int ret = RETURN_OK; - - FC_CHECK_RETURN_VALUE(hba, UNF_RETURN_ERROR); - - /* 1. Initialize cqm access related with scq, emb cq, aeq(ucode-->driver) */ - service_cqm_temp.service_handle = hba; - - ret = cqm3_service_register(hba->dev_handle, &service_cqm_temp); - if (ret != CQM_SUCCESS) - return UNF_RETURN_ERROR; - - /* 2. Initialize mailbox(driver-->up), aeq(up--->driver) access */ - ret = sphw_register_mgmt_msg_cb(hba->dev_handle, COMM_MOD_FC, hba, - spfc_up_msg2driver_proc); - if (ret != CQM_SUCCESS) - goto out_unreg_cqm; - - return RETURN_OK; - -out_unreg_cqm: - cqm3_service_unregister(hba->dev_handle, SERVICE_T_FC); - - return UNF_RETURN_ERROR; -} - -static void spfc_release_chip_access(struct spfc_hba_info *hba) -{ - FC_CHECK_RETURN_VOID(hba); - FC_CHECK_RETURN_VOID(hba->dev_handle); - - sphw_unregister_mgmt_msg_cb(hba->dev_handle, COMM_MOD_FC); - - cqm3_service_unregister(hba->dev_handle, SERVICE_T_FC); -} - -static void spfc_update_lport_config(struct spfc_hba_info *hba, - struct unf_low_level_functioon_op *lowlevel_func) -{ -#define SPFC_MULTI_CONF_NONSUPPORT 0 - - struct unf_lport_cfg_item *lport_cfg = NULL; - - lport_cfg = &lowlevel_func->lport_cfg_items; - - if (hba->port_cfg.max_login < lowlevel_func->support_max_rport) - lport_cfg->max_login = hba->port_cfg.max_login; - else - lport_cfg->max_login = lowlevel_func->support_max_rport; - - if (hba->port_cfg.sest_num >> UNF_SHIFT_1 < UNF_RESERVE_SFS_XCHG) - lport_cfg->max_io = hba->port_cfg.sest_num; - else - lport_cfg->max_io = hba->port_cfg.sest_num - UNF_RESERVE_SFS_XCHG; - - lport_cfg->max_sfs_xchg = UNF_MAX_SFS_XCHG; - lport_cfg->port_id = hba->port_cfg.port_id; - lport_cfg->port_mode = hba->port_cfg.port_mode; - lport_cfg->port_topology = hba->port_cfg.port_topology; - lport_cfg->max_queue_depth = hba->port_cfg.max_queue_depth; - - lport_cfg->port_speed = hba->port_cfg.port_speed; - lport_cfg->tape_support = hba->port_cfg.tape_support; - - lowlevel_func->sys_port_name = *(u64 *)hba->sys_port_name; - lowlevel_func->sys_node_name = *(u64 *)hba->sys_node_name; - - /* Update chip information */ - lowlevel_func->dev = hba->pci_dev; - lowlevel_func->chip_info.chip_work_mode = hba->work_mode; - lowlevel_func->chip_info.chip_type = hba->chip_type; - lowlevel_func->chip_info.disable_err_flag = 0; - lowlevel_func->support_max_speed = hba->max_support_speed; - lowlevel_func->support_min_speed = hba->min_support_speed; - - lowlevel_func->chip_id = 0; - - lowlevel_func->sfp_type = UNF_PORT_TYPE_FC_SFP; - - lowlevel_func->multi_conf_support = SPFC_MULTI_CONF_NONSUPPORT; - lowlevel_func->support_max_hot_tag_range = hba->port_cfg.sest_num; - lowlevel_func->update_fw_reset_active = UNF_PORT_UNGRADE_FW_RESET_INACTIVE; - lowlevel_func->port_type = 0; /* DRV_PORT_ENTITY_TYPE_PHYSICAL */ - - if ((lport_cfg->port_id & UNF_FIRST_LPORT_ID_MASK) == lport_cfg->port_id) - lowlevel_func->support_upgrade_report = UNF_PORT_SUPPORT_UPGRADE_REPORT; - else - lowlevel_func->support_upgrade_report = UNF_PORT_UNSUPPORT_UPGRADE_REPORT; -} - -static u32 spfc_create_lport(struct spfc_hba_info *hba) -{ - void *lport = NULL; - struct unf_low_level_functioon_op lowlevel_func; - - FC_CHECK_RETURN_VALUE(hba, UNF_RETURN_ERROR); - spfc_func_op.dev = hba->pci_dev; - memcpy(&lowlevel_func, &spfc_func_op, sizeof(struct unf_low_level_functioon_op)); - - /* Update port configuration table */ - spfc_update_lport_config(hba, &lowlevel_func); - - /* Apply for lport resources */ - UNF_LOWLEVEL_ALLOC_LPORT(lport, hba, &lowlevel_func); - if (!lport) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Port(0x%x) can't allocate Lport", - hba->port_cfg.port_id); - - return UNF_RETURN_ERROR; - } - hba->lport = lport; - - return RETURN_OK; -} - -void spfc_release_probe_index(u32 probe_index) -{ - if (probe_index >= SPFC_MAX_PROBE_PORT_NUM) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[warn]Probe index(0x%x) is invalid", probe_index); - - return; - } - - spin_lock(&probe_spin_lock); - if (!test_bit((int)probe_index, (const ulong *)probe_bit_map)) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[warn]Probe index(0x%x) is not probed", - probe_index); - - spin_unlock(&probe_spin_lock); - - return; - } - - clear_bit((int)probe_index, probe_bit_map); - spin_unlock(&probe_spin_lock); -} - -static void spfc_delete_default_session(struct spfc_hba_info *hba) -{ - struct unf_port_info rport_info = {0}; - - rport_info.nport_id = 0xffffff; - rport_info.rport_index = SPFC_DEFAULT_RPORT_INDEX; - rport_info.local_nport_id = 0xffffff; - rport_info.port_name = 0; - rport_info.cs_ctrl = 0x81; - - /* Need config table to up first, then delete default session */ - (void)spfc_mbx_config_default_session(hba, 0); - spfc_sess_resource_free_sync((void *)hba, &rport_info); -} - -static void spfc_release_host_res(struct spfc_hba_info *hba) -{ - spfc_free_dma_buffers(hba); - - spfc_destroy_queues(hba); - - spfc_release_chip_access(hba); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x) release low level resource done", - hba->port_cfg.port_id); -} - -static struct spfc_hba_info *spfc_init_hba(struct pci_dev *pci_dev, - void *hw_dev_handle, - struct spfc_chip_info *chip_info, - u8 card_num) -{ - u32 ret = RETURN_OK; - struct spfc_hba_info *hba = NULL; - - FC_CHECK_RETURN_VALUE(pci_dev, NULL); - FC_CHECK_RETURN_VALUE(hw_dev_handle, NULL); - - /* Allocate HBA */ - hba = kmalloc(sizeof(struct spfc_hba_info), GFP_ATOMIC); - FC_CHECK_RETURN_VALUE(hba, NULL); - memset(hba, 0, sizeof(struct spfc_hba_info)); - - /* Heartbeat default */ - hba->heart_status = 1; - /* Private data in pciDev */ - hba->pci_dev = pci_dev; - hba->dev_handle = hw_dev_handle; - - /* Work mode */ - hba->work_mode = chip_info->work_mode; - /* Create work queue */ - hba->work_queue = create_singlethread_workqueue("spfc"); - if (!hba->work_queue) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[err]Spfc creat workqueue failed"); - - goto out_free_hba; - } - /* Init delay work */ - INIT_DELAYED_WORK(&hba->srq_delay_info.del_work, spfc_rcvd_els_from_srq_timeout); - INIT_WORK(&hba->els_srq_clear_work, spfc_wq_destroy_els_srq); - - /* Notice: Only use FC features */ - (void)sphw_support_fc(hw_dev_handle, &hba->service_cap); - /* Check parent context available */ - if (hba->service_cap.dev_fc_cap.max_parent_qpc_num == 0) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]FC parent context is not allocated in this function"); - - goto out_destroy_workqueue; - } - max_parent_qpc_num = hba->service_cap.dev_fc_cap.max_parent_qpc_num; - - /* Get port configuration */ - ret = spfc_get_port_cfg(hba, chip_info, card_num); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[err]Can't get port configuration"); - - goto out_destroy_workqueue; - } - /* Get WWN */ - spfc_generate_sys_wwn(hba); - - /* Initialize host resources */ - ret = spfc_init_host_res(hba); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]SPFC port(0x%x) can't initialize host resource", - hba->port_cfg.port_id); - - goto out_destroy_workqueue; - } - /* Local Port create */ - ret = spfc_create_lport(hba); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]SPFC port(0x%x) can't create lport", - hba->port_cfg.port_id); - goto out_release_host_res; - } - complete(&hba->hba_init_complete); - - /* Print reference count */ - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_KEVENT, - "[info]Port(0x%x) probe succeeded. Memory reference is 0x%x", - hba->port_cfg.port_id, atomic_read(&fc_mem_ref)); - - return hba; - -out_release_host_res: - spfc_delete_default_session(hba); - spfc_flush_scq_ctx(hba); - spfc_flush_srq_ctx(hba); - spfc_release_host_res(hba); - -out_destroy_workqueue: - flush_workqueue(hba->work_queue); - destroy_workqueue(hba->work_queue); - hba->work_queue = NULL; - -out_free_hba: - kfree(hba); - - return NULL; -} - -void spfc_get_total_probed_num(u32 *probe_cnt) -{ - u32 i = 0; - u32 cnt = 0; - - spin_lock(&probe_spin_lock); - for (i = 0; i < SPFC_MAX_PROBE_PORT_NUM; i++) { - if (test_bit((int)i, (const ulong *)probe_bit_map)) - cnt++; - } - - *probe_cnt = cnt; - spin_unlock(&probe_spin_lock); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_INFO, - "[info]Probed port total number is 0x%x", cnt); -} - -u32 spfc_assign_card_num(struct spfc_lld_dev *lld_dev, - struct spfc_chip_info *chip_info, u8 *card_num) -{ - u8 i = 0; - u64 card_index = 0; - - card_index = (!pci_is_root_bus(lld_dev->pdev->bus)) ? - lld_dev->pdev->bus->parent->number : lld_dev->pdev->bus->number; - - spin_lock(&probe_spin_lock); - - for (i = 0; i < SPFC_MAX_CARD_NUM; i++) { - if (test_bit((int)i, (const ulong *)card_num_bit_map)) { - if (card_num_manage[i].card_number == - card_index && !card_num_manage[i].is_removing - ) { - card_num_manage[i].port_count++; - *card_num = i; - spin_unlock(&probe_spin_lock); - return RETURN_OK; - } - } - } - - for (i = 0; i < SPFC_MAX_CARD_NUM; i++) { - if (!test_bit((int)i, (const ulong *)card_num_bit_map)) { - card_num_manage[i].card_number = card_index; - card_num_manage[i].port_count = 1; - card_num_manage[i].is_removing = false; - - *card_num = i; - set_bit(i, card_num_bit_map); - - spin_unlock(&probe_spin_lock); - - return RETURN_OK; - } - } - - spin_unlock(&probe_spin_lock); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Have probe more than 0x%x port, probe failed", i); - - return UNF_RETURN_ERROR; -} - -static void spfc_dec_and_free_card_num(u8 card_num) -{ - /* 2 ports per card */ - if (card_num >= SPFC_MAX_CARD_NUM) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Card number(0x%x) is invalid", card_num); - - return; - } - - spin_lock(&probe_spin_lock); - - if (test_bit((int)card_num, (const ulong *)card_num_bit_map)) { - card_num_manage[card_num].port_count--; - card_num_manage[card_num].is_removing = true; - - if (card_num_manage[card_num].port_count == 0) { - card_num_manage[card_num].card_number = 0; - card_num_manage[card_num].is_removing = false; - clear_bit((int)card_num, card_num_bit_map); - } - } else { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Can not find card number(0x%x)", card_num); - } - - spin_unlock(&probe_spin_lock); -} - -u32 spfc_assign_probe_index(u32 *probe_index) -{ - u32 i = 0; - - spin_lock(&probe_spin_lock); - for (i = 0; i < SPFC_MAX_PROBE_PORT_NUM; i++) { - if (!test_bit((int)i, (const ulong *)probe_bit_map)) { - *probe_index = i; - set_bit(i, probe_bit_map); - - spin_unlock(&probe_spin_lock); - - return RETURN_OK; - } - } - spin_unlock(&probe_spin_lock); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Have probe more than 0x%x port, probe failed", i); - - return UNF_RETURN_ERROR; -} - -u32 spfc_get_probe_index_by_port_id(u32 port_id, u32 *probe_index) -{ - u32 total_probe_num = 0; - u32 i = 0; - u32 probe_cnt = 0; - - spfc_get_total_probed_num(&total_probe_num); - - for (i = 0; i < SPFC_MAX_PROBE_PORT_NUM; i++) { - if (!spfc_hba[i]) - continue; - - if (total_probe_num == probe_cnt) - break; - - if (port_id == spfc_hba[i]->port_cfg.port_id) { - *probe_index = spfc_hba[i]->probe_index; - - return RETURN_OK; - } - - probe_cnt++; - } - - return UNF_RETURN_ERROR; -} - -static int spfc_probe(struct spfc_lld_dev *lld_dev, void **uld_dev, - char *uld_dev_name) -{ - struct pci_dev *pci_dev = NULL; - struct spfc_hba_info *hba = NULL; - u32 ret = UNF_RETURN_ERROR; - const u8 work_mode = SPFC_SMARTIO_WORK_MODE_FC; - u32 probe_index = 0; - u32 probe_total_num = 0; - u8 card_num = INVALID_VALUE8; - struct spfc_chip_info chip_info; - - FC_CHECK_RETURN_VALUE(lld_dev, UNF_RETURN_ERROR_S32); - FC_CHECK_RETURN_VALUE(lld_dev->hwdev, UNF_RETURN_ERROR_S32); - FC_CHECK_RETURN_VALUE(lld_dev->pdev, UNF_RETURN_ERROR_S32); - FC_CHECK_RETURN_VALUE(uld_dev, UNF_RETURN_ERROR_S32); - FC_CHECK_RETURN_VALUE(uld_dev_name, UNF_RETURN_ERROR_S32); - - pci_dev = lld_dev->pdev; - memset(&chip_info, 0, sizeof(struct spfc_chip_info)); - /* 1. Get & check Total_Probed_number */ - spfc_get_total_probed_num(&probe_total_num); - if (probe_total_num >= allowed_probe_num) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Total probe num (0x%x) is larger than allowed number(0x%x)", - probe_total_num, allowed_probe_num); - - return UNF_RETURN_ERROR_S32; - } - /* 2. Check device work mode */ - ret = spfc_fc_mode_check(lld_dev->hwdev); - if (ret != RETURN_OK) - return UNF_RETURN_ERROR_S32; - - /* 3. Assign & Get new Probe index */ - ret = spfc_assign_probe_index(&probe_index); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]AssignProbeIndex fail"); - - return UNF_RETURN_ERROR_S32; - } - - ret = spfc_get_chip_capability((void *)lld_dev->hwdev, &chip_info); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]GetChipCapability fail"); - return UNF_RETURN_ERROR_S32; - } - chip_info.work_mode = work_mode; - - /* Assign & Get new Card number */ - ret = spfc_assign_card_num(lld_dev, &chip_info, &card_num); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]spfc_assign_card_num fail"); - spfc_release_probe_index(probe_index); - - return UNF_RETURN_ERROR_S32; - } - - /* Init HBA resource */ - hba = spfc_init_hba(pci_dev, lld_dev->hwdev, &chip_info, card_num); - if (!hba) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Probe HBA(0x%x) failed. Memory reference = 0x%x", - probe_index, atomic_read(&fc_mem_ref)); - - spfc_release_probe_index(probe_index); - spfc_dec_and_free_card_num(card_num); - - return UNF_RETURN_ERROR_S32; - } - - /* Name by the order of probe */ - *uld_dev = hba; - snprintf(uld_dev_name, SPFC_PORT_NAME_STR_LEN, "%s%02x%02x", - SPFC_PORT_NAME_LABEL, hba->card_info.card_num, - hba->card_info.func_num); - memcpy(hba->port_name, uld_dev_name, SPFC_PORT_NAME_STR_LEN); - hba->probe_index = probe_index; - spfc_hba[probe_index] = hba; - - return RETURN_OK; -} - -u32 spfc_sfp_switch(void *hba, void *para_in) -{ - struct spfc_hba_info *spfc_hba = (struct spfc_hba_info *)hba; - bool turn_on = false; - u32 ret = RETURN_OK; - - FC_CHECK_RETURN_VALUE(spfc_hba, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(para_in, UNF_RETURN_ERROR); - - /* Redundancy check */ - turn_on = *((bool *)para_in); - if ((u32)turn_on == (u32)spfc_hba->sfp_on) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_INFO, - "[info]Port(0x%x) FC physical port is already %s", - spfc_hba->port_cfg.port_id, (turn_on) ? "on" : "off"); - - return ret; - } - - if (turn_on) { - ret = spfc_port_check_fw_ready(spfc_hba); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[warn]Get port(0x%x) clear state failed, turn on fail", - spfc_hba->port_cfg.port_id); - return ret; - } - /* At first, configure port table info if necessary */ - ret = spfc_config_port_table(spfc_hba); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Port(0x%x) can't configurate port table", - spfc_hba->port_cfg.port_id); - - return ret; - } - } - - /* Switch physical port */ - ret = spfc_port_switch(spfc_hba, turn_on); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[err]Port(0x%x) switch failed", - spfc_hba->port_cfg.port_id); - - return ret; - } - - /* Update HBA's sfp state */ - spfc_hba->sfp_on = turn_on; - - return ret; -} - -static u32 spfc_destroy_lport(struct spfc_hba_info *hba) -{ - u32 ret = UNF_RETURN_ERROR; - - FC_CHECK_RETURN_VALUE(hba, UNF_RETURN_ERROR); - - UNF_LOWLEVEL_RELEASE_LOCAL_PORT(ret, hba->lport); - hba->lport = NULL; - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x) destroy L_Port done", - hba->port_cfg.port_id); - - return ret; -} - -static u32 spfc_port_check_fw_ready(struct spfc_hba_info *hba) -{ -#define SPFC_PORT_CLEAR_DONE 0 -#define SPFC_PORT_CLEAR_DOING 1 -#define SPFC_WAIT_ONE_TIME_MS 1000 -#define SPFC_LOOP_TIMES 30 - - u32 clear_state = SPFC_PORT_CLEAR_DOING; - u32 ret = RETURN_OK; - u32 wait_timeout = 0; - - do { - msleep(SPFC_WAIT_ONE_TIME_MS); - wait_timeout += SPFC_WAIT_ONE_TIME_MS; - ret = spfc_mbx_get_fw_clear_stat(hba, &clear_state); - if (ret != RETURN_OK) - return UNF_RETURN_ERROR; - - /* Total time more than 30s retry more than 3 times failed */ - if (wait_timeout > SPFC_LOOP_TIMES * SPFC_WAIT_ONE_TIME_MS && - clear_state != SPFC_PORT_CLEAR_DONE) - return UNF_RETURN_ERROR; - } while (clear_state != SPFC_PORT_CLEAR_DONE); - - return RETURN_OK; -} - -u32 spfc_port_reset(struct spfc_hba_info *hba) -{ - u32 ret = RETURN_OK; - ulong timeout = 0; - bool sfp_before_reset = false; - bool off_para_in = false; - struct pci_dev *pci_dev = NULL; - struct spfc_hba_info *spfc_hba = hba; - - FC_CHECK_RETURN_VALUE(spfc_hba, UNF_RETURN_ERROR); - pci_dev = spfc_hba->pci_dev; - FC_CHECK_RETURN_VALUE(pci_dev, UNF_RETURN_ERROR); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_KEVENT, - "[event]Port(0x%x) reset HBA begin", - spfc_hba->port_cfg.port_id); - - /* Wait for last init/reset completion */ - timeout = wait_for_completion_timeout(&spfc_hba->hba_init_complete, - (ulong)SPFC_PORT_INIT_TIME_SEC_MAX * HZ); - - if (timeout == SPFC_ZERO) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Last HBA initialize/reset timeout: %d second", - SPFC_PORT_INIT_TIME_SEC_MAX); - - return UNF_RETURN_ERROR; - } - - /* Save current port state */ - sfp_before_reset = spfc_hba->sfp_on; - - /* Inform the reset event to CM level before beginning */ - UNF_LOWLEVEL_PORT_EVENT(ret, spfc_hba->lport, UNF_PORT_RESET_START, NULL); - spfc_hba->reset_time = jiffies; - - /* Close SFP */ - ret = spfc_sfp_switch(spfc_hba, &off_para_in); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Port(0x%x) can't close SFP", - spfc_hba->port_cfg.port_id); - spfc_hba->sfp_on = sfp_before_reset; - - complete(&spfc_hba->hba_init_complete); - - return ret; - } - - ret = spfc_port_check_fw_ready(spfc_hba); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Get port(0x%x) clear state failed, hang port and report chip error", - spfc_hba->port_cfg.port_id); - - complete(&spfc_hba->hba_init_complete); - - return ret; - } - - spfc_queue_pre_process(spfc_hba, false); - - ret = spfc_mb_reset_chip(spfc_hba, SPFC_MBOX_SUBTYPE_LIGHT_RESET); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]SPFC port(0x%x) can't reset chip mailbox", - spfc_hba->port_cfg.port_id); - - UNF_LOWLEVEL_PORT_EVENT(ret, spfc_hba->lport, UNF_PORT_GET_FWLOG, NULL); - UNF_LOWLEVEL_PORT_EVENT(ret, spfc_hba->lport, UNF_PORT_DEBUG_DUMP, NULL); - } - - /* Inform the success to CM level */ - UNF_LOWLEVEL_PORT_EVENT(ret, spfc_hba->lport, UNF_PORT_RESET_END, NULL); - - /* Queue open */ - spfc_queue_post_process(spfc_hba); - - /* Open SFP */ - (void)spfc_sfp_switch(spfc_hba, &sfp_before_reset); - - complete(&spfc_hba->hba_init_complete); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[event]Port(0x%x) reset HBA done", - spfc_hba->port_cfg.port_id); - - return ret; -#undef SPFC_WAIT_LINKDOWN_EVENT_MS -} - -static u32 spfc_delete_scqc_via_cmdq_sync(struct spfc_hba_info *hba, u32 scqn) -{ - /* Via CMND Queue */ -#define SPFC_DEL_SCQC_TIMEOUT 3000 - - int ret; - struct spfc_cmdqe_delete_scqc del_scqc_cmd; - struct sphw_cmd_buf *cmd_buf; - - /* Alloc cmd buffer */ - cmd_buf = sphw_alloc_cmd_buf(hba->dev_handle); - if (!cmd_buf) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[err]cmdq in_cmd_buf alloc failed"); - - SPFC_ERR_IO_STAT(hba, SPFC_TASK_T_DEL_SCQC); - return UNF_RETURN_ERROR; - } - - /* Build & Send Cmnd */ - memset(&del_scqc_cmd, 0, sizeof(del_scqc_cmd)); - del_scqc_cmd.wd0.task_type = SPFC_TASK_T_DEL_SCQC; - del_scqc_cmd.wd1.scqn = SPFC_LSW(scqn); - spfc_cpu_to_big32(&del_scqc_cmd, sizeof(del_scqc_cmd)); - memcpy(cmd_buf->buf, &del_scqc_cmd, sizeof(del_scqc_cmd)); - cmd_buf->size = sizeof(del_scqc_cmd); - - ret = sphw_cmdq_detail_resp(hba->dev_handle, COMM_MOD_FC, 0, cmd_buf, - NULL, NULL, SPFC_DEL_SCQC_TIMEOUT, - SPHW_CHANNEL_FC); - - /* Free cmnd buffer */ - sphw_free_cmd_buf(hba->dev_handle, cmd_buf); - - if (ret) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[err]Send del scqc via cmdq failed, ret=0x%x", - ret); - - SPFC_ERR_IO_STAT(hba, SPFC_TASK_T_DEL_SCQC); - return UNF_RETURN_ERROR; - } - - SPFC_IO_STAT(hba, SPFC_TASK_T_DEL_SCQC); - - return RETURN_OK; -} - -static u32 spfc_delete_srqc_via_cmdq_sync(struct spfc_hba_info *hba, u64 sqrc_gpa) -{ - /* Via CMND Queue */ -#define SPFC_DEL_SRQC_TIMEOUT 3000 - - int ret; - struct spfc_cmdqe_delete_srqc del_srqc_cmd; - struct sphw_cmd_buf *cmd_buf; - - /* Alloc Cmnd buffer */ - cmd_buf = sphw_alloc_cmd_buf(hba->dev_handle); - if (!cmd_buf) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[err]cmdq in_cmd_buf allocate failed"); - - SPFC_ERR_IO_STAT(hba, SPFC_TASK_T_DEL_SRQC); - return UNF_RETURN_ERROR; - } - - /* Build & Send Cmnd */ - memset(&del_srqc_cmd, 0, sizeof(del_srqc_cmd)); - del_srqc_cmd.wd0.task_type = SPFC_TASK_T_DEL_SRQC; - del_srqc_cmd.srqc_gpa_h = SPFC_HIGH_32_BITS(sqrc_gpa); - del_srqc_cmd.srqc_gpa_l = SPFC_LOW_32_BITS(sqrc_gpa); - spfc_cpu_to_big32(&del_srqc_cmd, sizeof(del_srqc_cmd)); - memcpy(cmd_buf->buf, &del_srqc_cmd, sizeof(del_srqc_cmd)); - cmd_buf->size = sizeof(del_srqc_cmd); - - ret = sphw_cmdq_detail_resp(hba->dev_handle, COMM_MOD_FC, 0, cmd_buf, - NULL, NULL, SPFC_DEL_SRQC_TIMEOUT, - SPHW_CHANNEL_FC); - - /* Free Cmnd Buffer */ - sphw_free_cmd_buf(hba->dev_handle, cmd_buf); - - if (ret) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[err]Send del srqc via cmdq failed, ret=0x%x", - ret); - - SPFC_ERR_IO_STAT(hba, SPFC_TASK_T_DEL_SRQC); - return UNF_RETURN_ERROR; - } - - SPFC_IO_STAT(hba, SPFC_TASK_T_DEL_SRQC); - - return RETURN_OK; -} - -void spfc_flush_scq_ctx(struct spfc_hba_info *hba) -{ - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]Start destroy total 0x%x SCQC", SPFC_TOTAL_SCQ_NUM); - - FC_CHECK_RETURN_VOID(hba); - - (void)spfc_delete_scqc_via_cmdq_sync(hba, 0); -} - -void spfc_flush_srq_ctx(struct spfc_hba_info *hba) -{ - struct spfc_srq_info *srq_info = NULL; - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]Start destroy ELS&IMMI SRQC"); - - FC_CHECK_RETURN_VOID(hba); - - /* Check state to avoid to flush SRQC again */ - srq_info = &hba->els_srq_info; - if (srq_info->srq_type == SPFC_SRQ_ELS && srq_info->enable) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_MAJOR, - "[event]HBA(0x%x) flush ELS SRQC", - hba->port_index); - - (void)spfc_delete_srqc_via_cmdq_sync(hba, srq_info->cqm_srq_info->q_ctx_paddr); - } -} - -void spfc_set_hba_flush_state(struct spfc_hba_info *hba, bool in_flush) -{ - ulong flag = 0; - - spin_lock_irqsave(&hba->flush_state_lock, flag); - hba->in_flushing = in_flush; - spin_unlock_irqrestore(&hba->flush_state_lock, flag); -} - -void spfc_set_hba_clear_state(struct spfc_hba_info *hba, bool clear_flag) -{ - ulong flag = 0; - - spin_lock_irqsave(&hba->clear_state_lock, flag); - hba->port_is_cleared = clear_flag; - spin_unlock_irqrestore(&hba->clear_state_lock, flag); -} - -bool spfc_hba_is_present(struct spfc_hba_info *hba) -{ - int ret_val = RETURN_OK; - bool present_flag = false; - u32 vendor_id = 0; - - ret_val = pci_read_config_dword(hba->pci_dev, 0, &vendor_id); - vendor_id &= SPFC_PCI_VENDOR_ID_MASK; - if (ret_val == RETURN_OK && vendor_id == SPFC_PCI_VENDOR_ID_RAMAXEL) { - present_flag = true; - } else { - present_flag = false; - hba->dev_present = false; - } - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_KEVENT, - "[info]Port %s remove: vender_id=0x%x, ret=0x%x", - present_flag ? "normal" : "surprise", vendor_id, ret_val); - - return present_flag; -} - -static void spfc_exit(struct pci_dev *pci_dev, struct spfc_hba_info *hba) -{ -#define SPFC_WAIT_CLR_RESOURCE_MS 1000 - u32 ret = UNF_RETURN_ERROR; - bool sfp_switch = false; - bool present_flag = true; - - FC_CHECK_RETURN_VOID(pci_dev); - FC_CHECK_RETURN_VOID(hba); - - hba->removing = true; - - /* 1. Check HBA present or not */ - present_flag = spfc_hba_is_present(hba); - if (present_flag) { - if (hba->phy_link == UNF_PORT_LINK_DOWN) - hba->queue_set_stage = SPFC_QUEUE_SET_STAGE_FLUSHDONE; - - /* At first, close sfp */ - sfp_switch = false; - (void)spfc_sfp_switch((void *)hba, (void *)&sfp_switch); - } - - /* 2. Report COM with HBA removing: delete route timer delay work */ - UNF_LOWLEVEL_PORT_EVENT(ret, hba->lport, UNF_PORT_BEGIN_REMOVE, NULL); - - /* 3. Report COM with HBA Nop, COM release I/O(s) & R_Port(s) forcely */ - UNF_LOWLEVEL_PORT_EVENT(ret, hba->lport, UNF_PORT_NOP, NULL); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]PCI device(%p) remove port(0x%x) failed", - pci_dev, hba->port_index); - } - - spfc_delete_default_session(hba); - - if (present_flag) - /* 4.1 Wait for all SQ empty, free SRQ buffer & SRQC */ - spfc_queue_pre_process(hba, true); - - /* 5. Destroy L_Port */ - (void)spfc_destroy_lport(hba); - - /* 6. With HBA is present */ - if (present_flag) { - /* Enable Queues dispatch */ - spfc_queue_post_process(hba); - - /* Need reset port if necessary */ - (void)spfc_mb_reset_chip(hba, SPFC_MBOX_SUBTYPE_HEAVY_RESET); - - /* Flush SCQ context */ - spfc_flush_scq_ctx(hba); - - /* Flush SRQ context */ - spfc_flush_srq_ctx(hba); - - sphw_func_rx_tx_flush(hba->dev_handle, SPHW_CHANNEL_FC); - - /* NOTE: while flushing txrx, hash bucket will be cached out in - * UP. Wait to clear resources completely - */ - msleep(SPFC_WAIT_CLR_RESOURCE_MS); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x) flush scq & srq & root context done", - hba->port_cfg.port_id); - } - - /* 7. Release host resources */ - spfc_release_host_res(hba); - - /* 8. Destroy FC work queue */ - if (hba->work_queue) { - flush_workqueue(hba->work_queue); - destroy_workqueue(hba->work_queue); - hba->work_queue = NULL; - } - - /* 9. Release Probe index & Decrease card number */ - spfc_release_probe_index(hba->probe_index); - spfc_dec_and_free_card_num((u8)hba->card_info.card_num); - - /* 10. Free HBA memory */ - kfree(hba); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[event]PCI device(%p) remove succeed, memory reference is 0x%x", - pci_dev, atomic_read(&fc_mem_ref)); -} - -static void spfc_remove(struct spfc_lld_dev *lld_dev, void *uld_dev) -{ - struct pci_dev *pci_dev = NULL; - struct spfc_hba_info *hba = (struct spfc_hba_info *)uld_dev; - u32 probe_total_num = 0; - u32 probe_index = 0; - - FC_CHECK_RETURN_VOID(lld_dev); - FC_CHECK_RETURN_VOID(uld_dev); - FC_CHECK_RETURN_VOID(lld_dev->hwdev); - FC_CHECK_RETURN_VOID(lld_dev->pdev); - - pci_dev = hba->pci_dev; - - /* Get total probed port number */ - spfc_get_total_probed_num(&probe_total_num); - if (probe_total_num < 1) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[warn]Port manager is empty and no need to remove"); - return; - } - - /* check pci vendor id */ - if (pci_dev->vendor != SPFC_PCI_VENDOR_ID_RAMAXEL) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[warn]Wrong vendor id(0x%x) and exit", - pci_dev->vendor); - return; - } - - /* Check function ability */ - if (!sphw_support_fc(lld_dev->hwdev, NULL)) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]FC is not enable in this function"); - return; - } - - /* Get probe index */ - probe_index = hba->probe_index; - - /* Parent context alloc check */ - if (hba->service_cap.dev_fc_cap.max_parent_qpc_num == 0) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]FC parent context not allocate in this function"); - return; - } - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]HBA(0x%x) start removing...", hba->port_index); - - /* HBA removinig... */ - spfc_exit(pci_dev, hba); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_KEVENT, - "[event]Port(0x%x) pci device removed, vendorid(0x%04x) devid(0x%04x)", - probe_index, pci_dev->vendor, pci_dev->device); - - /* Probe index check */ - if (probe_index < SPFC_HBA_PORT_MAX_NUM) { - spfc_hba[probe_index] = NULL; - } else { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Probe index(0x%x) is invalid and remove failed", - probe_index); - } - - spfc_get_total_probed_num(&probe_total_num); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[event]Removed index=%u, RemainNum=%u, AllowNum=%u", - probe_index, probe_total_num, allowed_probe_num); -} - -static u32 spfc_get_hba_pcie_link_state(void *hba, void *link_state) -{ - bool *link_state_info = link_state; - bool present_flag = true; - struct spfc_hba_info *spfc_hba = hba; - int ret; - bool last_dev_state = true; - bool cur_dev_state = true; - - FC_CHECK_RETURN_VALUE(hba, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(link_state, UNF_RETURN_ERROR); - last_dev_state = spfc_hba->dev_present; - ret = sphw_get_card_present_state(spfc_hba->dev_handle, (bool *)&present_flag); - if (ret || !present_flag) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_KEVENT, - "[event]port(0x%x) is not present,ret:%d, present_flag:%d", - spfc_hba->port_cfg.port_id, ret, present_flag); - cur_dev_state = false; - } else { - cur_dev_state = true; - } - - spfc_hba->dev_present = cur_dev_state; - - /* To prevent false alarms, the heartbeat is considered lost only - * when the PCIe link is down for two consecutive times. - */ - if (!last_dev_state && !cur_dev_state) - spfc_hba->heart_status = false; - - *link_state_info = spfc_hba->dev_present; - - return RETURN_OK; -} diff --git a/drivers/scsi/spfc/hw/spfc_hba.h b/drivers/scsi/spfc/hw/spfc_hba.h deleted file mode 100644 index 937f00ea8fc7..000000000000 --- a/drivers/scsi/spfc/hw/spfc_hba.h +++ /dev/null @@ -1,341 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPFC_HBA_H -#define SPFC_HBA_H - -#include "unf_type.h" -#include "unf_common.h" -#include "spfc_queue.h" -#include "sphw_crm.h" -#define SPFC_PCI_VENDOR_ID_MASK (0xffff) - -#define FW_VER_LEN (32) -#define HW_VER_LEN (32) -#define FW_SUB_VER_LEN (24) - -#define SPFC_LOWLEVEL_RTTOV_TAG 0 -#define SPFC_LOWLEVEL_EDTOV_TAG 0 -#define SPFC_LOWLEVEL_DEFAULT_LOOP_BB_CREDIT (8) -#define SPFC_LOWLEVEL_DEFAULT_32G_BB_CREDIT (255) -#define SPFC_LOWLEVEL_DEFAULT_16G_BB_CREDIT (255) -#define SPFC_LOWLEVEL_DEFAULT_8G_BB_CREDIT (255) -#define SPFC_LOWLEVEL_DEFAULT_BB_SCN 0 -#define SPFC_LOWLEVEL_DEFAULT_RA_TOV UNF_DEFAULT_RATOV -#define SPFC_LOWLEVEL_DEFAULT_ED_TOV UNF_DEFAULT_EDTOV - -#define SPFC_LOWLEVEL_DEFAULT_32G_ESCH_VALUE 28081 -#define SPFC_LOWLEVEL_DEFAULT_16G_ESCH_VALUE 14100 -#define SPFC_LOWLEVEL_DEFAULT_8G_ESCH_VALUE 7000 -#define SPFC_LOWLEVEL_DEFAULT_ESCH_BUST_SIZE 0x2000 - -#define SPFC_PCI_STATUS 0x06 - -#define SPFC_SMARTIO_WORK_MODE_FC 0x1 -#define SPFC_SMARTIO_WORK_MODE_OTHER 0xF -#define UNF_FUN_ID_MASK 0x07 - -#define UNF_SPFC_FC (0x01) -#define UNF_SPFC_MAXNPIV_NUM 64 /* If not support NPIV, Initialized to 0 */ - -#define SPFC_MAX_COS_NUM (8) - -#define SPFC_INTR_ENABLE 0x5 -#define SPFC_INTR_DISABLE 0x0 -#define SPFC_CLEAR_FW_INTR 0x1 -#define SPFC_REG_ENABLE_INTR 0x00000200 - -#define SPFC_PCI_VENDOR_ID_RAMAXEL 0x1E81 - -#define SPFC_SCQ_CNTX_SIZE 32 -#define SPFC_SRQ_CNTX_SIZE 64 - -#define SPFC_PORT_INIT_TIME_SEC_MAX 1 - -#define SPFC_PORT_NAME_LABEL "spfc" -#define SPFC_PORT_NAME_STR_LEN (16) - -#define SPFC_MAX_PROBE_PORT_NUM (64) -#define SPFC_PORT_NUM_PER_TABLE (64) -#define SPFC_MAX_CARD_NUM (32) - -#define SPFC_HBA_PORT_MAX_NUM SPFC_MAX_PROBE_PORT_NUM -#define SPFC_SIRT_MIN_RXID 0 -#define SPFC_SIRT_MAX_RXID 255 - -#define SPFC_GET_HBA_PORT_ID(hba) ((hba)->port_index) - -#define SPFC_MAX_WAIT_LOOP_TIMES 10000 -#define SPFC_WAIT_SESS_ENABLE_ONE_TIME_MS 1 -#define SPFC_WAIT_SESS_FREE_ONE_TIME_MS 1 - -#define SPFC_PORT_ID_MASK 0xff0000 - -#define SPFC_MAX_PARENT_QPC_NUM 2048 -struct spfc_port_cfg { - u32 port_id; /* Port ID */ - u32 port_mode; /* Port mode:INI(0x20), TGT(0x10), BOTH(0x30) */ - u32 port_topology; /* Port topo:0x3:loop,0xc:p2p,0xf:auto */ - u32 port_alpa; /* Port ALPA */ - u32 max_queue_depth; /* Max Queue depth Registration to SCSI */ - u32 sest_num; /* IO burst num:512-4096 */ - u32 max_login; /* Max Login Session. */ - u32 node_name_hi; /* nodename high 32 bits */ - u32 node_name_lo; /* nodename low 32 bits */ - u32 port_name_hi; /* portname high 32 bits */ - u32 port_name_lo; /* portname low 32 bits */ - u32 port_speed; /* Port speed 0:auto 4:4Gbps 8:8Gbps 16:16Gbps */ - u32 interrupt_delay; /* Delay times(ms) in interrupt */ - u32 tape_support; /* tape support */ -}; - -#define SPFC_VER_INFO_SIZE 128 -struct spfc_drv_version { - char ver[SPFC_VER_INFO_SIZE]; -}; - -struct spfc_card_info { - u32 card_num : 8; - u32 func_num : 8; - u32 base_func : 8; - /* Card type:UNF_FC_SERVER_BOARD_32_G(6) 32G mode, - * UNF_FC_SERVER_BOARD_16_G(7)16G mode - */ - u32 card_type : 8; -}; - -struct spfc_card_num_manage { - bool is_removing; - u32 port_count; - u64 card_number; -}; - -struct spfc_sim_ini_err { - u32 err_code; - u32 times; -}; - -struct spfc_sim_pcie_err { - u32 err_code; - u32 times; -}; - -struct spfc_led_state { - u8 green_speed_led; - u8 yellow_speed_led; - u8 ac_led; - u8 rsvd; -}; - -enum spfc_led_activity { - SPFC_LED_CFG_ACTVE_FRAME = 0, - SPFC_LED_CFG_ACTVE_FC = 3 -}; - -enum spfc_queue_set_stage { - SPFC_QUEUE_SET_STAGE_INIT = 0, - SPFC_QUEUE_SET_STAGE_SCANNING, - SPFC_QUEUE_SET_STAGE_FLUSHING, - SPFC_QUEUE_SET_STAGE_FLUSHDONE, - SPFC_QUEUE_SET_STAGE_BUTT -}; - -struct spfc_vport_info { - u64 node_name; - u64 port_name; - u32 port_mode; /* INI, TGT or both */ - u32 nport_id; /* maybe acquired by lowlevel and update to common */ - void *vport; - u16 vp_index; -}; - -struct spfc_srq_delay_info { - u8 srq_delay_flag; /* Check whether need to delay */ - u8 root_rq_rcvd_flag; - u16 rsd; - - spinlock_t srq_lock; - struct unf_frame_pkg frame_pkg; - - struct delayed_work del_work; -}; - -struct spfc_fw_ver_detail { - u8 ucode_ver[SPFC_VER_LEN]; - u8 ucode_compile_time[SPFC_COMPILE_TIME_LEN]; - - u8 up_ver[SPFC_VER_LEN]; - u8 up_compile_time[SPFC_COMPILE_TIME_LEN]; - - u8 boot_ver[SPFC_VER_LEN]; - u8 boot_compile_time[SPFC_COMPILE_TIME_LEN]; -}; - -/* get wwpn and wwnn */ -struct spfc_chip_info { - u8 work_mode; - u8 tape_support; - u64 wwpn; - u64 wwnn; -}; - -/* Default SQ info */ -struct spfc_default_sq_info { - u32 sq_cid; - u32 sq_xid; - u32 fun_cid; - u32 default_sq_flag; -}; - -struct spfc_hba_info { - struct pci_dev *pci_dev; - void *dev_handle; - - struct fc_service_cap service_cap; /* struct fc_service_cap pstFcoeServiceCap; */ - - struct spfc_scq_info scq_info[SPFC_TOTAL_SCQ_NUM]; - struct spfc_srq_info els_srq_info; - - struct spfc_vport_info vport_info[UNF_SPFC_MAXNPIV_NUM + 1]; - - /* PCI IO Memory */ - void __iomem *bar0; - u32 bar0_len; - - struct spfc_parent_queue_mgr *parent_queue_mgr; - - /* Link list Sq WqePage Pool */ - struct spfc_sq_wqepage_pool sq_wpg_pool; - - enum spfc_queue_set_stage queue_set_stage; - u32 next_clear_sq; - u32 default_sqid; - - /* Port parameters, Obtained through firmware */ - u16 queue_set_max_count; - u8 port_type; /* FC or FCoE Port */ - u8 port_index; /* Phy Port */ - u32 default_scqn; - char fw_ver[FW_VER_LEN]; /* FW version */ - char hw_ver[HW_VER_LEN]; /* HW version */ - char mst_fw_ver[FW_SUB_VER_LEN]; - char fc_fw_ver[FW_SUB_VER_LEN]; - u8 chip_type; /* chiptype:Smart or fc */ - u8 work_mode; - struct spfc_card_info card_info; - char port_name[SPFC_PORT_NAME_STR_LEN]; - u32 probe_index; - - u16 exi_base; - u16 exi_count; - u16 vpf_count; - u8 vpid_start; - u8 vpid_end; - - spinlock_t flush_state_lock; - bool in_flushing; - - spinlock_t clear_state_lock; - bool port_is_cleared; - - struct spfc_port_cfg port_cfg; /* Obtained through Config */ - - void *lport; /* Used in UNF level */ - - u8 sys_node_name[UNF_WWN_LEN]; - u8 sys_port_name[UNF_WWN_LEN]; - - struct completion hba_init_complete; - struct completion mbox_complete; - struct completion vpf_complete; - struct completion fcfi_complete; - struct completion get_sfp_complete; - - u16 init_stage; - u16 removing; - bool sfp_on; - bool dev_present; - bool heart_status; - spinlock_t hba_lock; - u32 port_topo_cfg; - u32 port_bb_scn_cfg; - u32 port_loop_role; - u32 port_speed_cfg; - u32 max_support_speed; - u32 min_support_speed; - u32 server_max_speed; - - u8 remote_rttov_tag; - u8 remote_edtov_tag; - u16 compared_bb_scn; - u16 remote_bb_credit; - u32 compared_edtov_val; - u32 compared_ratov_val; - enum unf_act_topo active_topo; - u32 active_port_speed; - u32 active_rxbb_credit; - u32 active_bb_scn; - - u32 phy_link; - - enum unf_port_mode port_mode; - - u32 fcp_cfg; - - /* loop */ - u8 active_alpa; - u8 loop_map_valid; - u8 loop_map[UNF_LOOPMAP_COUNT]; - - /* sfp info dma */ - void *sfp_buf; - dma_addr_t sfp_dma_addr; - u32 sfp_status; - int chip_temp; - u32 sfp_posion; - - u32 cos_bitmap; - atomic_t cos_rport_cnt[SPFC_MAX_COS_NUM]; - - /* fw debug dma buffer */ - void *debug_buf; - dma_addr_t debug_buf_dma_addr; - void *log_buf; - dma_addr_t fw_log_dma_addr; - - void *dma_addr; - dma_addr_t update_dma_addr; - - struct spfc_sim_ini_err sim_ini_err; - struct spfc_sim_pcie_err sim_pcie_err; - - struct spfc_led_state led_states; - - u32 fec_status; - - struct workqueue_struct *work_queue; - struct work_struct els_srq_clear_work; - u64 reset_time; - - spinlock_t spin_lock; - - struct spfc_srq_delay_info srq_delay_info; - struct spfc_fw_ver_detail hardinfo; - struct spfc_default_sq_info default_sq_info; -}; - -extern struct spfc_hba_info *spfc_hba[SPFC_HBA_PORT_MAX_NUM]; -extern spinlock_t probe_spin_lock; -extern ulong probe_bit_map[SPFC_MAX_PROBE_PORT_NUM / SPFC_PORT_NUM_PER_TABLE]; - -u32 spfc_port_reset(struct spfc_hba_info *hba); -void spfc_flush_scq_ctx(struct spfc_hba_info *hba); -void spfc_flush_srq_ctx(struct spfc_hba_info *hba); -void spfc_set_hba_flush_state(struct spfc_hba_info *hba, bool in_flush); -void spfc_set_hba_clear_state(struct spfc_hba_info *hba, bool clear_flag); -u32 spfc_get_probe_index_by_port_id(u32 port_id, u32 *probe_index); -void spfc_get_total_probed_num(u32 *probe_cnt); -u32 spfc_sfp_switch(void *hba, void *para_in); -bool spfc_hba_is_present(struct spfc_hba_info *hba); - -#endif diff --git a/drivers/scsi/spfc/hw/spfc_hw_wqe.h b/drivers/scsi/spfc/hw/spfc_hw_wqe.h deleted file mode 100644 index e03d24a98579..000000000000 --- a/drivers/scsi/spfc/hw/spfc_hw_wqe.h +++ /dev/null @@ -1,1645 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPFC_HW_WQE_H -#define SPFC_HW_WQE_H - -#define FC_ICQ_EN -#define FC_SCSI_CMDIU_LEN 48 -#define FC_NVME_CMDIU_LEN 96 -#define FC_LS_GS_USERID_CNT_MAX 10 -#define FC_SENSEDATA_USERID_CNT_MAX 2 -#define FC_INVALID_MAGIC_NUM 0xFFFFFFFF -#define FC_INVALID_HOTPOOLTAG 0xFFFF - -/* TASK TYPE: in order to compatible wiht EDA, please add new type before BUTT. */ -enum spfc_task_type { - SPFC_TASK_T_EMPTY = 0, /* SCQE TYPE: means task type not initialize */ - - SPFC_TASK_T_IWRITE = 1, /* SQE TYPE: ini send FCP Write Command */ - SPFC_TASK_T_IREAD = 2, /* SQE TYPE: ini send FCP Read Command */ - SPFC_TASK_T_IRESP = 3, /* SCQE TYPE: ini recv fcp rsp for IREAD/IWRITE/ITMF */ - SPFC_TASK_T_TCMND = 4, /* NA */ - SPFC_TASK_T_TREAD = 5, /* SQE TYPE: tgt send FCP Read Command */ - SPFC_TASK_T_TWRITE = 6, /* SQE TYPE: tgt send FCP Write Command (XFER_RDY) */ - SPFC_TASK_T_TRESP = 7, /* SQE TYPE: tgt send fcp rsp of Read/Write */ - SPFC_TASK_T_TSTS = 8, /* SCQE TYPE: tgt sts for TREAD/TWRITE/TRESP */ - SPFC_TASK_T_ABTS = 9, /* SQE TYPE: ini send abts request Command */ - SPFC_TASK_T_IELS = 10, /* NA */ - SPFC_TASK_T_ITMF = 11, /* SQE TYPE: ini send tmf request Command */ - SPFC_TASK_T_CLEAN_UP = 12, /* NA */ - SPFC_TASK_T_CLEAN_UP_ALL = 13, /* NA */ - SPFC_TASK_T_UNSOLICITED = 14, /* NA */ - SPFC_TASK_T_ERR_WARN = 15, /* NA */ - SPFC_TASK_T_SESS_EN = 16, /* CMDQ TYPE: enable session */ - SPFC_TASK_T_SESS_DIS = 17, /* NA */ - SPFC_TASK_T_SESS_DEL = 18, /* NA */ - SPFC_TASK_T_RQE_REPLENISH = 19, /* NA */ - - SPFC_TASK_T_RCV_TCMND = 20, /* SCQE TYPE: tgt recv fcp cmd */ - SPFC_TASK_T_RCV_ELS_CMD = 21, /* SCQE TYPE: tgt recv els cmd */ - SPFC_TASK_T_RCV_ABTS_CMD = 22, /* SCQE TYPE: tgt recv abts cmd */ - SPFC_TASK_T_RCV_IMMEDIATE = 23, /* SCQE TYPE: tgt recv immediate data */ - /* SQE TYPE: send ESL rsp. PLOGI_ACC, PRLI_ACC will carry the parent - *context parameter indication. - */ - SPFC_TASK_T_ELS_RSP = 24, - SPFC_TASK_T_ELS_RSP_STS = 25, /* SCQE TYPE: ELS rsp sts */ - SPFC_TASK_T_ABTS_RSP = 26, /* CMDQ TYPE: tgt send abts rsp */ - SPFC_TASK_T_ABTS_RSP_STS = 27, /* SCQE TYPE: tgt abts rsp sts */ - - SPFC_TASK_T_ABORT = 28, /* CMDQ TYPE: tgt send Abort Command */ - SPFC_TASK_T_ABORT_STS = 29, /* SCQE TYPE: Abort sts */ - - SPFC_TASK_T_ELS = 30, /* SQE TYPE: send ELS request Command */ - SPFC_TASK_T_RCV_ELS_RSP = 31, /* SCQE TYPE: recv ELS response */ - - SPFC_TASK_T_GS = 32, /* SQE TYPE: send GS request Command */ - SPFC_TASK_T_RCV_GS_RSP = 33, /* SCQE TYPE: recv GS response */ - - SPFC_TASK_T_SESS_EN_STS = 34, /* SCQE TYPE: enable session sts */ - SPFC_TASK_T_SESS_DIS_STS = 35, /* NA */ - SPFC_TASK_T_SESS_DEL_STS = 36, /* NA */ - - SPFC_TASK_T_RCV_ABTS_RSP = 37, /* SCQE TYPE: ini recv abts rsp */ - - SPFC_TASK_T_BUFFER_CLEAR = 38, /* CMDQ TYPE: Buffer Clear */ - SPFC_TASK_T_BUFFER_CLEAR_STS = 39, /* SCQE TYPE: Buffer Clear sts */ - SPFC_TASK_T_FLUSH_SQ = 40, /* CMDQ TYPE: flush sq */ - SPFC_TASK_T_FLUSH_SQ_STS = 41, /* SCQE TYPE: flush sq sts */ - - SPFC_TASK_T_SESS_RESET = 42, /* SQE TYPE: Reset session */ - SPFC_TASK_T_SESS_RESET_STS = 43, /* SCQE TYPE: Reset session sts */ - SPFC_TASK_T_RQE_REPLENISH_STS = 44, /* NA */ - SPFC_TASK_T_DUMP_EXCH = 45, /* CMDQ TYPE: dump exch */ - SPFC_TASK_T_INIT_SRQC = 46, /* CMDQ TYPE: init SRQC */ - SPFC_TASK_T_CLEAR_SRQ = 47, /* CMDQ TYPE: clear SRQ */ - SPFC_TASK_T_CLEAR_SRQ_STS = 48, /* SCQE TYPE: clear SRQ sts */ - SPFC_TASK_T_INIT_SCQC = 49, /* CMDQ TYPE: init SCQC */ - SPFC_TASK_T_DEL_SCQC = 50, /* CMDQ TYPE: delete SCQC */ - SPFC_TASK_T_TMF_RESP = 51, /* SQE TYPE: tgt send tmf rsp */ - SPFC_TASK_T_DEL_SRQC = 52, /* CMDQ TYPE: delete SRQC */ - SPFC_TASK_T_RCV_IMMI_CONTINUE = 53, /* SCQE TYPE: tgt recv continue immediate data */ - - SPFC_TASK_T_ITMF_RESP = 54, /* SCQE TYPE: ini recv tmf rsp */ - SPFC_TASK_T_ITMF_MARKER_STS = 55, /* SCQE TYPE: tmf marker sts */ - SPFC_TASK_T_TACK = 56, - SPFC_TASK_T_SEND_AEQERR = 57, - SPFC_TASK_T_ABTS_MARKER_STS = 58, /* SCQE TYPE: abts marker sts */ - SPFC_TASK_T_FLR_CLEAR_IO = 59, /* FLR clear io type */ - SPFC_TASK_T_CREATE_SSQ_CONTEXT = 60, - SPFC_TASK_T_CLEAR_SSQ_CONTEXT = 61, - SPFC_TASK_T_EXCH_ID_FREE = 62, - SPFC_TASK_T_DIFX_RESULT_STS = 63, - SPFC_TASK_T_EXCH_ID_FREE_ABORT = 64, - SPFC_TASK_T_EXCH_ID_FREE_ABORT_STS = 65, - SPFC_TASK_T_PARAM_CHECK_FAIL = 66, - SPFC_TASK_T_TGT_UNKNOWN = 67, - SPFC_TASK_T_NVME_LS = 70, /* SQE TYPE: Snd Ls Req */ - SPFC_TASK_T_RCV_NVME_LS_RSP = 71, /* SCQE TYPE: Rcv Ls Rsp */ - - SPFC_TASK_T_NVME_LS_RSP = 72, /* SQE TYPE: Snd Ls Rsp */ - SPFC_TASK_T_RCV_NVME_LS_RSP_STS = 73, /* SCQE TYPE: Rcv Ls Rsp sts */ - - SPFC_TASK_T_RCV_NVME_LS_CMD = 74, /* SCQE TYPE: Rcv ls cmd */ - - SPFC_TASK_T_NVME_IREAD = 75, /* SQE TYPE: Ini Snd Nvme Read Cmd */ - SPFC_TASK_T_NVME_IWRITE = 76, /* SQE TYPE: Ini Snd Nvme write Cmd */ - - SPFC_TASK_T_NVME_TREAD = 77, /* SQE TYPE: Tgt Snd Nvme Read Cmd */ - SPFC_TASK_T_NVME_TWRITE = 78, /* SQE TYPE: Tgt Snd Nvme write Cmd */ - - SPFC_TASK_T_NVME_IRESP = 79, /* SCQE TYPE: Ini recv nvme rsp for NVMEIREAD/NVMEIWRITE */ - - SPFC_TASK_T_INI_IO_ABORT = 80, /* SQE type: INI Abort Cmd */ - SPFC_TASK_T_INI_IO_ABORT_STS = 81, /* SCQE type: INI Abort sts */ - - SPFC_TASK_T_INI_LS_ABORT = 82, /* SQE type: INI ls abort Cmd */ - SPFC_TASK_T_INI_LS_ABORT_STS = 83, /* SCQE type: INI ls abort sts */ - SPFC_TASK_T_EXCHID_TIMEOUT_STS = 84, /* SCQE TYPE: EXCH_ID TIME OUT */ - SPFC_TASK_T_PARENT_ERR_STS = 85, /* SCQE TYPE: PARENT ERR */ - - SPFC_TASK_T_NOP = 86, - SPFC_TASK_T_NOP_STS = 87, - - SPFC_TASK_T_DFX_INFO = 126, - SPFC_TASK_T_BUTT -}; - -/* error code for error report */ - -enum spfc_err_code { - FC_CQE_COMPLETED = 0, /* Successful */ - FC_SESS_HT_INSERT_FAIL = 1, /* Offload fail: hash insert fail */ - FC_SESS_HT_INSERT_DUPLICATE = 2, /* Offload fail: duplicate offload */ - FC_SESS_HT_BIT_SET_FAIL = 3, /* Offload fail: bloom filter set fail */ - FC_SESS_HT_DELETE_FAIL = 4, /* Offload fail: hash delete fail(duplicate delete) */ - FC_CQE_BUFFER_CLEAR_IO_COMPLETED = 5, /* IO done in buffer clear */ - FC_CQE_SESSION_ONLY_CLEAR_IO_COMPLETED = 6, /* IO done in session rst mode=1 */ - FC_CQE_SESSION_RST_CLEAR_IO_COMPLETED = 7, /* IO done in session rst mode=3 */ - FC_CQE_TMF_RSP_IO_COMPLETED = 8, /* IO done in tgt tmf rsp */ - FC_CQE_TMF_IO_COMPLETED = 9, /* IO done in ini tmf */ - FC_CQE_DRV_ABORT_IO_COMPLETED = 10, /* IO done in tgt abort */ - /* - *IO done in fcp rsp process. Used for the sceanrio: 1.abort before cmd 2. - *send fcp rsp directly after recv cmd. - */ - FC_CQE_DRV_ABORT_IO_IN_RSP_COMPLETED = 11, - /* - *IO done in fcp cmd process. Used for the sceanrio: 1.abort before cmd 2.child setup fail. - */ - FC_CQE_DRV_ABORT_IO_IN_CMD_COMPLETED = 12, - FC_CQE_WQE_FLUSH_IO_COMPLETED = 13, /* IO done in FLUSH SQ */ - FC_ERROR_CODE_DATA_DIFX_FAILED = 14, /* fcp data format check: DIFX check error */ - /* fcp data format check: task_type is not read */ - FC_ERROR_CODE_DATA_TASK_TYPE_INCORRECT = 15, - FC_ERROR_CODE_DATA_OOO_RO = 16, /* fcp data format check: data offset is not continuous */ - FC_ERROR_CODE_DATA_EXCEEDS_DATA2TRNS = 17, /* fcp data format check: data is over run */ - /* fcp rsp format check: payload is too short */ - FC_ERROR_CODE_FCP_RSP_INVALID_LENGTH_FIELD = 18, - /* fcp rsp format check: fcp_conf need, but exch don't hold seq initiative */ - FC_ERROR_CODE_FCP_RSP_CONF_REQ_NOT_SUPPORTED_YET = 19, - /* fcp rsp format check: fcp_conf is required, but it's the last seq */ - FC_ERROR_CODE_FCP_RSP_OPENED_SEQ = 20, - /* xfer rdy format check: payload is too short */ - FC_ERROR_CODE_XFER_INVALID_PAYLOAD_SIZE = 21, - /* xfer rdy format check: last data out havn't finished */ - FC_ERROR_CODE_XFER_PEND_XFER_SET = 22, - /* xfer rdy format check: data offset is not continuous */ - FC_ERROR_CODE_XFER_OOO_RO = 23, - FC_ERROR_CODE_XFER_NULL_BURST_LEN = 24, /* xfer rdy format check: burst len is 0 */ - FC_ERROR_CODE_REC_TIMER_EXPIRE = 25, /* Timer expire: REC_TIMER */ - FC_ERROR_CODE_E_D_TIMER_EXPIRE = 26, /* Timer expire: E_D_TIMER */ - FC_ERROR_CODE_ABORT_TIMER_EXPIRE = 27, /* Timer expire: Abort timer */ - FC_ERROR_CODE_ABORT_MAGIC_NUM_NOT_MATCH = 28, /* Abort IO magic number mismatch */ - FC_IMMI_CMDPKT_SETUP_FAIL = 29, /* RX immediate data cmd pkt child setup fail */ - FC_ERROR_CODE_DATA_SEQ_ID_NOT_EQUAL = 30, /* RX fcp data sequence id not equal */ - FC_ELS_GS_RSP_EXCH_CHECK_FAIL = 31, /* ELS/GS exch info check fail */ - FC_CQE_ELS_GS_SRQE_GET_FAIL = 32, /* ELS/GS process get SRQE fail */ - FC_CQE_DATA_DMA_REQ_FAIL = 33, /* SMF soli-childdma rsp error */ - FC_CQE_SESSION_CLOSED = 34, /* Session is closed */ - FC_SCQ_IS_FULL = 35, /* SCQ is full */ - FC_SRQ_IS_FULL = 36, /* SRQ is full */ - FC_ERROR_DUCHILDCTX_SETUP_FAIL = 37, /* dpchild ctx setup fail */ - FC_ERROR_INVALID_TXMFS = 38, /* invalid txmfs */ - FC_ERROR_OFFLOAD_LACKOF_SCQE_FAIL = 39, /* offload fail,lack of SCQE,through AEQ */ - FC_ERROR_INVALID_TASK_ID = 40, /* tx invlaid task id */ - FC_ERROR_INVALID_PKT_LEN = 41, /* tx els gs pakcet len check */ - FC_CQE_ELS_GS_REQ_CLR_IO_COMPLETED = 42, /* IO done in els gs tx */ - FC_CQE_ELS_RSP_CLR_IO_COMPLETED = 43, /* IO done in els rsp tx */ - FC_ERROR_CODE_RESID_UNDER_ERR = 44, /* FCP RSP RESID ERROR */ - FC_ERROR_EXCH_ID_FREE_ERR = 45, /* Abnormal free xid failed */ - FC_ALLOC_EXCH_ID_FAILED = 46, /* ucode alloc EXCH ID failed */ - FC_ERROR_DUPLICATE_IO_RECEIVED = 47, /* Duplicate tcmnd or tmf rsp received */ - FC_ERROR_RXID_MISCOMPARE = 48, - FC_ERROR_FAILOVER_CLEAR_VALID_HOST = 49, /* Failover cleared valid host io */ - FC_ERROR_EXCH_ID_NOT_MATCH = 50, /* SCQ TYPE: xid not match */ - FC_ERROR_ABORT_FAIL = 51, /* SCQ TYPE: abort fail */ - FC_ERROR_SHARD_TABLE_OP_FAIL = 52, /* SCQ TYPE: shard table OP fail */ - FC_ERROR_E0E1_FAIL = 53, - FC_INSERT_EXCH_ID_HASH_FAILED = 54, /* ucode INSERT EXCH ID HASH failed */ - FC_ERROR_CODE_FCP_RSP_UPDMA_FAILED = 55, /* up dma req failed,while fcp rsp is rcving */ - FC_ERROR_CODE_SID_DID_NOT_MATCH = 56, /* sid or did not match */ - FC_ERROR_DATA_NOT_REL_OFF = 57, /* data not rel off */ - FC_ERROR_CODE_EXCH_ID_TIMEOUT = 58, /* exch id timeout */ - FC_ERROR_PARENT_CHECK_FAIL = 59, - FC_ERROR_RECV_REC_REJECT = 60, /* RECV REC RSP REJECT */ - FC_ERROR_RECV_SRR_REJECT = 61, /* RECV REC SRR REJECT */ - FC_ERROR_REC_NOT_FIND_EXID_INVALID = 62, - FC_ERROR_RECV_REC_NO_ERR = 63, - FC_ERROR_PARENT_CTX_ERR = 64 -}; - -/* AEQ EVENT TYPE */ -enum spfc_aeq_evt_type { - /* SCQ and SRQ not enough, HOST will initiate a operation to associated SCQ/SRQ */ - FC_AEQ_EVENT_QUEUE_ERROR = 48, - FC_AEQ_EVENT_WQE_FATAL_ERROR = 49, /* WQE MSN check error,HOST will reset port */ - FC_AEQ_EVENT_CTX_FATAL_ERROR = 50, /* serious chip error, HOST will reset chip */ - FC_AEQ_EVENT_OFFLOAD_ERROR = 51, - FC_FC_AEQ_EVENT_TYPE_LAST -}; - -enum spfc_protocol_class { - FC_PROTOCOL_CLASS_3 = 0x0, - FC_PROTOCOL_CLASS_2 = 0x1, - FC_PROTOCOL_CLASS_1 = 0x2, - FC_PROTOCOL_CLASS_F = 0x3, - FC_PROTOCOL_CLASS_OTHER = 0x4 -}; - -enum spfc_aeq_evt_err_code { - /* detail type of resource lack */ - FC_SCQ_IS_FULL_ERR = 0, - FC_SRQ_IS_FULL_ERR, - - /* detail type of FC_AEQ_EVENT_WQE_FATAL_ERROR */ - FC_SQE_CHILD_SETUP_WQE_MSN_ERR = 2, - FC_SQE_CHILD_SETUP_WQE_GPA_ERR, - FC_CMDPKT_CHILD_SETUP_INVALID_WQE_ERR_1, - FC_CMDPKT_CHILD_SETUP_INVALID_WQE_ERR_2, - FC_CLEAEQ_WQE_ERR, - FC_WQEFETCH_WQE_MSN_ERR, - FC_WQEFETCH_QUINFO_ERR, - - /* detail type of FC_AEQ_EVENT_CTX_FATAL_ERROR */ - FC_SCQE_ERR_BIT_ERR = 9, - FC_UPDMA_ADDR_REQ_SRQ_ERR, - FC_SOLICHILDDMA_ADDR_REQ_ERR, - FC_UNSOLICHILDDMA_ADDR_REQ_ERR, - FC_SQE_CHILD_SETUP_QINFO_ERR_1, - FC_SQE_CHILD_SETUP_QINFO_ERR_2, - FC_CMDPKT_CHILD_SETUP_QINFO_ERR_1, - FC_CMDPKT_CHILD_SETUP_QINFO_ERR_2, - FC_CMDPKT_CHILD_SETUP_PMSN_ERR, - FC_CLEAEQ_CTX_ERR, - FC_WQEFETCH_CTX_ERR, - FC_FLUSH_QPC_ERR_LQP, - FC_FLUSH_QPC_ERR_SMF, - FC_PREFETCH_QPC_ERR_PCM_MHIT_LQP, - FC_PREFETCH_QPC_ERR_PCM_MHIT_FQG, - FC_PREFETCH_QPC_ERR_PCM_ABM_FQG, - FC_PREFETCH_QPC_ERR_MAP_FQG, - FC_PREFETCH_QPC_ERR_MAP_LQP, - FC_PREFETCH_QPC_ERR_SMF_RTN, - FC_PREFETCH_QPC_ERR_CFG, - FC_PREFETCH_QPC_ERR_FLSH_HIT, - FC_PREFETCH_QPC_ERR_FLSH_ACT, - FC_PREFETCH_QPC_ERR_ABM_W_RSC, - FC_PREFETCH_QPC_ERR_RW_ABM, - FC_PREFETCH_QPC_ERR_DEFAULT, - FC_CHILDHASH_INSERT_SW_ERR, - FC_CHILDHASH_LOOKUP_SW_ERR, - FC_CHILDHASH_DEL_SW_ERR, - FC_EXCH_ID_FREE_SW_ERR, - FC_FLOWHASH_INSERT_SW_ERR, - FC_FLOWHASH_LOOKUP_SW_ERR, - FC_FLOWHASH_DEL_SW_ERR, - FC_FLUSH_QPC_ERR_USED, - FC_FLUSH_QPC_ERR_OUTER_LOCK, - FC_SETUP_SESSION_ERR, - - FC_AEQ_EVT_ERR_CODE_BUTT - -}; - -/* AEQ data structure */ -struct spfc_aqe_data { - union { - struct { - u32 conn_id : 16; - u32 rsvd : 8; - u32 evt_code : 8; - } wd0; - - u32 data0; - }; - - union { - struct { - u32 xid : 20; - u32 rsvd : 12; - } wd1; - - u32 data1; - }; -}; - -/* Control Section: Common Header */ -struct spfc_wqe_ctrl_ch { - union { - struct { - u32 bdsl : 8; - u32 drv_sl : 2; - u32 rsvd0 : 4; - u32 wf : 1; - u32 cf : 1; - u32 tsl : 5; - u32 va : 1; - u32 df : 1; - u32 cr : 1; - u32 dif_sl : 3; - u32 csl : 2; - u32 ctrl_sl : 2; - u32 owner : 1; - } wd0; - - u32 ctrl_ch_val; - }; -}; - -/* Control Section: Queue Specific Field */ -struct spfc_wqe_ctrl_qsf { - u32 wqe_sn : 16; - u32 dump_wqe_sn : 16; -}; - -/* DIF info definition in WQE */ -struct spfc_fc_dif_info { - struct { - u32 app_tag_ctrl : 3; /* DIF/DIX APP TAG Control */ - /* Bit 0: scenario of the reference tag verify mode. - *Bit 1: scenario of the reference tag insert/replace mode. - */ - u32 ref_tag_mode : 2; - /* 0: fixed; 1: increasement; */ - u32 ref_tag_ctrl : 3; /* The DIF/DIX Reference tag control */ - u32 grd_agm_ini_ctrl : 3; - u32 grd_agm_ctrl : 2; /* Bit 0: DIF/DIX guard verify algorithm control */ - /* Bit 1: DIF/DIX guard replace or insert algorithm control */ - u32 grd_ctrl : 3; /* The DIF/DIX Guard control */ - u32 dif_verify_type : 2; /* verify type */ - u32 difx_ref_esc : 1; /* Check blocks whose reference tag contains 0xFFFF flag */ - u32 difx_app_esc : 1;/* Check blocks whose application tag contains 0xFFFF flag */ - u32 rsvd : 8; - u32 sct_size : 1; /* Sector size, 1: 4K; 0: 512 */ - u32 smd_tp : 2; - u32 difx_en : 1; - } wd0; - - struct { - u32 cmp_app_tag_msk : 16; - u32 rsvd : 7; - u32 lun_qos_en : 2; - u32 vpid : 7; - } wd1; - - u16 cmp_app_tag; - u16 rep_app_tag; - - u32 cmp_ref_tag; - u32 rep_ref_tag; -}; - -/* Task Section: TMF SQE for INI */ -struct spfc_tmf_info { - union { - struct { - u32 reset_exch_end : 16; - u32 reset_exch_start : 16; - } bs; - u32 value; - } w0; - - union { - struct { - u32 reset_did : 24; - u32 reset_type : 2; - u32 marker_sts : 1; - u32 rsvd0 : 5; - } bs; - u32 value; - } w1; - - union { - struct { - u32 reset_sid : 24; - u32 rsvd0 : 8; - } bs; - u32 value; - } w2; - - u8 reset_lun[8]; -}; - -/* Task Section: CMND SQE for INI */ -struct spfc_sqe_icmnd { - u8 fcp_cmnd_iu[FC_SCSI_CMDIU_LEN]; - union { - struct spfc_fc_dif_info dif_info; - struct spfc_tmf_info tmf; - } info; -}; - -/* Task Section: ABTS SQE */ -struct spfc_sqe_abts { - u32 fh_parm_abts; - u32 hotpooltag; - u32 release_timer; -}; - -struct spfc_keys { - struct { - u32 smac1 : 8; - u32 smac0 : 8; - u32 rsv : 16; - } wd0; - - u8 smac[4]; - - u8 dmac[6]; - u8 sid[3]; - u8 did[3]; - - struct { - u32 port_id : 3; - u32 host_id : 2; - u32 rsvd : 27; - } wd5; - u32 rsvd; -}; - -/* BDSL: Session Enable WQE.keys field only use 26 bytes room */ -struct spfc_cmdqe_sess_en { - struct { - u32 rx_id : 16; - u32 port_id : 8; - u32 task_type : 8; - } wd0; - - struct { - u32 cid : 20; - u32 rsvd1 : 12; - } wd1; - - struct { - u32 conn_id : 16; - u32 scqn : 16; - } wd2; - - struct { - u32 xid_p : 20; - u32 rsvd3 : 12; - } wd3; - - u32 context_gpa_hi; - u32 context_gpa_lo; - struct spfc_keys keys; - u32 context[64]; -}; - -/* Control Section */ -struct spfc_wqe_ctrl { - struct spfc_wqe_ctrl_ch ch; - struct spfc_wqe_ctrl_qsf qsf; -}; - -struct spfc_sqe_els_rsp { - struct { - u32 echo_flag : 16; - u32 data_len : 16; - } wd0; - - struct { - u32 rsvd1 : 27; - u32 offload_flag : 1; - u32 lp_bflag : 1; - u32 clr_io : 1; - u32 para_update : 2; - } wd1; - - struct { - u32 seq_cnt : 1; - u32 e_d_tov : 1; - u32 rsvd2 : 6; - u32 class_mode : 8; /* 0:class3, 1:class2*/ - u32 tx_mfs : 16; - } wd2; - - u32 e_d_tov_timer_val; - - struct { - u32 conf : 1; - u32 rec : 1; - u32 xfer_dis : 1; - u32 immi_taskid_cnt : 13; - u32 immi_taskid_start : 16; - } wd4; - - u32 first_burst_len; - - struct { - u32 reset_exch_end : 16; - u32 reset_exch_start : 16; - } wd6; - - struct { - u32 scqn : 16; - u32 hotpooltag : 16; - } wd7; - - u32 magic_local; - u32 magic_remote; - u32 ts_rcv_echo_req; - u32 sid; - u32 did; - u32 context_gpa_hi; - u32 context_gpa_lo; -}; - -struct spfc_sqe_reset_session { - struct { - u32 reset_exch_end : 16; - u32 reset_exch_start : 16; - } wd0; - - struct { - u32 reset_did : 24; - u32 mode : 2; - u32 rsvd : 6; - } wd1; - - struct { - u32 reset_sid : 24; - u32 rsvd : 8; - } wd2; - - struct { - u32 scqn : 16; - u32 rsvd : 16; - } wd3; -}; - -struct spfc_sqe_nop_sq { - struct { - u32 scqn : 16; - u32 rsvd : 16; - } wd0; - u32 magic_num; -}; - -struct spfc_sqe_t_els_gs { - u16 echo_flag; - u16 data_len; - - struct { - u32 rsvd1 : 9; - u32 offload_flag : 1; - u32 origin_hottag : 16; - u32 rec_flag : 1; - u32 rec_support : 1; - u32 lp_bflag : 1; - u32 clr_io : 1; - u32 para_update : 2; - } wd4; - - struct { - u32 seq_cnt : 1; - u32 e_d_tov : 1; - u32 rsvd2 : 14; - u32 tx_mfs : 16; - } wd5; - - u32 e_d_tov_timer_val; - - struct { - u32 reset_exch_end : 16; - u32 reset_exch_start : 16; - } wd6; - - struct { - u32 scqn : 16; - u32 hotpooltag : 16; /* used for send ELS rsp */ - } wd7; - - u32 sid; - u32 did; - u32 context_gpa_hi; - u32 context_gpa_lo; - u32 origin_magicnum; -}; - -struct spfc_sqe_els_gs_elsrsp_comm { - u16 rsvd; - u16 data_len; -}; - -struct spfc_sqe_lpb_msg { - struct { - u32 reset_exch_end : 16; - u32 reset_exch_start : 16; - } w0; - - struct { - u32 reset_did : 24; - u32 reset_type : 2; - u32 rsvd0 : 6; - } w1; - - struct { - u32 reset_sid : 24; - u32 rsvd0 : 8; - } w2; - - u16 tmf_exch_id; - u16 rsvd1; - - u8 reset_lun[8]; -}; - -/* SQE Task Section's Contents except Common Header */ -union spfc_sqe_ts_cont { - struct spfc_sqe_icmnd icmnd; - struct spfc_sqe_abts abts; - struct spfc_sqe_els_rsp els_rsp; - struct spfc_sqe_t_els_gs t_els_gs; - struct spfc_sqe_els_gs_elsrsp_comm els_gs_elsrsp_comm; - struct spfc_sqe_reset_session reset_session; - struct spfc_sqe_lpb_msg lpb_msg; - struct spfc_sqe_nop_sq nop_sq; - u32 value[17]; -}; - -struct spfc_sqe_nvme_icmnd_part2 { - u8 nvme_cmnd_iu_part2_data[FC_NVME_CMDIU_LEN - FC_SCSI_CMDIU_LEN]; -}; - -union spfc_sqe_ts_ex { - struct spfc_sqe_nvme_icmnd_part2 nvme_icmnd_part2; - u32 value[12]; -}; - -struct spfc_sqe_ts { - /* SQE Task Section's Common Header */ - u32 local_xid : 16; /* local exch_id, icmnd/els send used for hotpooltag */ - u32 crc_inj : 1; - u32 immi_std : 1; - u32 cdb_type : 1; /* cdb_type = 0:CDB_LEN = 16B, cdb_type = 1:CDB_LEN = 32B */ - u32 rsvd : 5; /* used for loopback saving bdsl's num */ - u32 task_type : 8; - - struct { - u16 conn_id; - u16 remote_xid; - } wd0; - - u32 xid : 20; - u32 sqn : 12; - u32 cid; - u32 magic_num; - union spfc_sqe_ts_cont cont; -}; - -struct spfc_constant_sge { - u32 buf_addr_hi; - u32 buf_addr_lo; -}; - -struct spfc_variable_sge { - u32 buf_addr_hi; - u32 buf_addr_lo; - - struct { - u32 buf_len : 31; - u32 r_flag : 1; - } wd0; - - struct { - u32 buf_addr_gpa : 16; - u32 xid : 14; - u32 extension_flag : 1; - u32 last_flag : 1; - } wd1; -}; - -#define FC_WQE_SIZE 256 -/* SQE, should not be over 256B */ -struct spfc_sqe { - struct spfc_wqe_ctrl ctrl_sl; - u32 sid; - u32 did; - u64 wqe_gpa; /* gpa shift 6 bit to right*/ - u64 db_val; - union spfc_sqe_ts_ex ts_ex; - struct spfc_variable_sge esge[3]; - struct spfc_wqe_ctrl ectrl_sl; - struct spfc_sqe_ts ts_sl; - struct spfc_variable_sge sge[2]; -}; - -struct spfc_rqe_ctrl { - struct spfc_wqe_ctrl_ch ch; - - struct { - u16 wqe_msn; - u16 dump_wqe_msn; - } wd0; -}; - -struct spfc_rqe_drv { - struct { - u32 rsvd0 : 16; - u32 user_id : 16; - } wd0; - - u32 rsvd1; -}; - -/* RQE,should not be over 32B */ -struct spfc_rqe { - struct spfc_rqe_ctrl ctrl_sl; - u32 cqe_gpa_h; - u32 cqe_gpa_l; - struct spfc_constant_sge bds_sl; - struct spfc_rqe_drv drv_sl; -}; - -struct spfc_cmdqe_abort { - struct { - u32 rx_id : 16; - u32 rsvd0 : 8; - u32 task_type : 8; - } wd0; - - struct { - u32 ox_id : 16; - u32 rsvd1 : 12; - u32 trsp_send : 1; - u32 tcmd_send : 1; - u32 immi : 1; - u32 reply_sts : 1; - } wd1; - - struct { - u32 conn_id : 16; - u32 scqn : 16; - } wd2; - - struct { - u32 xid : 20; - u32 rsvd : 12; - } wd3; - - struct { - u32 cid : 20; - u32 rsvd : 12; - } wd4; - struct { - u32 hotpooltag : 16; - u32 rsvd : 16; - } wd5; /* v6 new define */ - /* abort time out. Used for abort and io cmd reach ucode in different path - * and io cmd will not arrive. - */ - u32 time_out; - u32 magic_num; -}; - -struct spfc_cmdqe_abts_rsp { - struct { - u32 rx_id : 16; - u32 rsvd0 : 8; - u32 task_type : 8; - } wd0; - - struct { - u32 ox_id : 16; - u32 rsvd1 : 4; - u32 port_id : 4; - u32 payload_len : 7; - u32 rsp_type : 1; - } wd1; - - struct { - u32 conn_id : 16; - u32 scqn : 16; - } wd2; - - struct { - u32 xid : 20; - u32 rsvd : 12; - } wd3; - - struct { - u32 cid : 20; - u32 rsvd : 12; - } wd4; - - struct { - u32 req_rx_id : 16; - u32 hotpooltag : 16; - } wd5; - - /* payload length is according to rsp_type:1DWORD or 3DWORD */ - u32 payload[3]; -}; - -struct spfc_cmdqe_buffer_clear { - struct { - u32 rsvd1 : 16; - u32 rsvd0 : 8; - u32 wqe_type : 8; - } wd0; - - struct { - u32 rx_id_end : 16; - u32 rx_id_start : 16; - } wd1; - - u32 scqn; - u32 wd3; -}; - -struct spfc_cmdqe_flush_sq { - struct { - u32 entry_count : 16; - u32 rsvd : 8; - u32 wqe_type : 8; - } wd0; - - struct { - u32 scqn : 16; - u32 port_id : 4; - u32 pos : 11; - u32 last_wqe : 1; - } wd1; - - struct { - u32 rsvd : 4; - u32 clr_pos : 12; - u32 pkt_ptr : 16; - } wd2; - - struct { - u32 first_sq_xid : 24; - u32 sqqid_start_per_session : 4; - u32 sqcnt_per_session : 4; - } wd3; -}; - -struct spfc_cmdqe_dump_exch { - struct { - u32 rsvd1 : 16; - u32 rsvd0 : 8; - u32 task_type : 8; - } wd0; - - u16 oqid_wr; - u16 oqid_rd; - - u32 host_id; - u32 func_id; - u32 cache_id; - u32 exch_id; -}; - -struct spfc_cmdqe_creat_srqc { - struct { - u32 rsvd1 : 16; - u32 rsvd0 : 8; - u32 task_type : 8; - } wd0; - - u32 srqc_gpa_h; - u32 srqc_gpa_l; - - u32 srqc[16]; /* srqc_size=64B */ -}; - -struct spfc_cmdqe_delete_srqc { - struct { - u32 rsvd1 : 16; - u32 rsvd0 : 8; - u32 task_type : 8; - } wd0; - - u32 srqc_gpa_h; - u32 srqc_gpa_l; -}; - -struct spfc_cmdqe_clr_srq { - struct { - u32 rsvd1 : 16; - u32 rsvd0 : 8; - u32 task_type : 8; - } wd0; - - struct { - u32 scqn : 16; - u32 srq_type : 16; - } wd1; - - u32 srqc_gpa_h; - u32 srqc_gpa_l; -}; - -struct spfc_cmdqe_creat_scqc { - struct { - u32 rsvd1 : 16; - u32 rsvd0 : 8; - u32 task_type : 8; - } wd0; - - struct { - u32 scqn : 16; - u32 rsvd2 : 16; - } wd1; - - u32 scqc[16]; /* scqc_size=64B */ -}; - -struct spfc_cmdqe_delete_scqc { - struct { - u32 rsvd1 : 16; - u32 rsvd0 : 8; - u32 task_type : 8; - } wd0; - - struct { - u32 scqn : 16; - u32 rsvd2 : 16; - } wd1; -}; - -struct spfc_cmdqe_creat_ssqc { - struct { - u32 rsvd1 : 4; - u32 xid : 20; - u32 task_type : 8; - } wd0; - - struct { - u32 scqn : 16; - u32 rsvd2 : 16; - } wd1; - u32 context_gpa_hi; - u32 context_gpa_lo; - - u32 ssqc[64]; /* ssqc_size=256B */ -}; - -struct spfc_cmdqe_delete_ssqc { - struct { - u32 entry_count : 4; - u32 xid : 20; - u32 task_type : 8; - } wd0; - - struct { - u32 scqn : 16; - u32 rsvd2 : 16; - } wd1; - u32 context_gpa_hi; - u32 context_gpa_lo; -}; - -/* add xid free via cmdq */ -struct spfc_cmdqe_exch_id_free { - struct { - u32 task_id : 16; - u32 port_id : 8; - u32 rsvd0 : 8; - } wd0; - - u32 magic_num; - - struct { - u32 scqn : 16; - u32 hotpool_tag : 16; - } wd2; - struct { - u32 rsvd1 : 31; - u32 clear_abort_flag : 1; - } wd3; - u32 sid; - u32 did; - u32 type; /* ELS/ELS RSP/IO */ -}; - -struct spfc_cmdqe_cmdqe_dfx { - struct { - u32 rsvd1 : 4; - u32 xid : 20; - u32 task_type : 8; - } wd0; - - struct { - u32 qid_crclen : 12; - u32 cid : 20; - } wd1; - u32 context_gpa_hi; - u32 context_gpa_lo; - u32 dfx_type; - - u32 rsv[16]; -}; - -struct spfc_sqe_t_rsp { - struct { - u32 rsvd1 : 16; - u32 fcp_rsp_len : 8; - u32 busy_rsp : 3; - u32 immi : 1; - u32 mode : 1; - u32 conf : 1; - u32 fill : 2; - } wd0; - - u32 hotpooltag; - - union { - struct { - u32 addr_h; - u32 addr_l; - } gpa; - - struct { - u32 data[23]; /* FCP_RESP payload buf, 92B rsvd */ - } buf; - } payload; -}; - -struct spfc_sqe_tmf_t_rsp { - struct { - u32 scqn : 16; - u32 fcp_rsp_len : 8; - u32 pkt_nosnd_flag : 3; /* tmf rsp snd flag, 0:snd, 1: not snd, Driver ignore */ - u32 reset_type : 2; - u32 conf : 1; - u32 fill : 2; - } wd0; - - struct { - u32 reset_exch_end : 16; - u32 reset_exch_start : 16; - } wd1; - - struct { - u16 hotpooltag; /*tmf rsp hotpooltag, Driver ignore */ - u16 rsvd; - } wd2; - - u8 lun[8]; /* Lun ID */ - u32 data[20]; /* FCP_RESP payload buf, 80B rsvd */ -}; - -struct spfc_sqe_tresp_ts { - /* SQE Task Section's Common Header */ - u16 local_xid; - u8 rsvd0; - u8 task_type; - - struct { - u16 conn_id; - u16 remote_xid; - } wd0; - - u32 xid : 20; - u32 sqn : 12; - u32 cid; - u32 magic_num; - struct spfc_sqe_t_rsp t_rsp; -}; - -struct spfc_sqe_tmf_resp_ts { - /* SQE Task Section's Common Header */ - u16 local_xid; - u8 rsvd0; - u8 task_type; - - struct { - u16 conn_id; - u16 remote_xid; - } wd0; - - u32 xid : 20; - u32 sqn : 12; - u32 cid; - u32 magic_num; /* magic num */ - struct spfc_sqe_tmf_t_rsp tmf_rsp; -}; - -/* SQE for fcp response, max TSL is 120B */ -struct spfc_sqe_tresp { - struct spfc_wqe_ctrl ctrl_sl; - u64 taskrsvd; - u64 wqe_gpa; - u64 db_val; - union spfc_sqe_ts_ex ts_ex; - struct spfc_variable_sge esge[3]; - struct spfc_wqe_ctrl ectrl_sl; - struct spfc_sqe_tresp_ts ts_sl; -}; - -/* SQE for tmf response, max TSL is 120B */ -struct spfc_sqe_tmf_rsp { - struct spfc_wqe_ctrl ctrl_sl; - u64 taskrsvd; - u64 wqe_gpa; - u64 db_val; - union spfc_sqe_ts_ex ts_ex; - struct spfc_variable_sge esge[3]; - struct spfc_wqe_ctrl ectrl_sl; - struct spfc_sqe_tmf_resp_ts ts_sl; -}; - -/* SCQE Common Header */ -struct spfc_scqe_ch { - struct { - u32 task_type : 8; - u32 sqn : 13; - u32 cqe_remain_cnt : 3; - u32 err_code : 7; - u32 owner : 1; - } wd0; -}; - -struct spfc_scqe_type { - struct spfc_scqe_ch ch; - - u32 rsvd0; - - u16 conn_id; - u16 rsvd4; - - u32 rsvd1[12]; - - struct { - u32 done : 1; - u32 rsvd : 23; - u32 dif_vry_rst : 8; - } wd0; -}; - -struct spfc_scqe_sess_sts { - struct spfc_scqe_ch ch; - - struct { - u32 xid_qpn : 20; - u32 rsvd1 : 12; - } wd0; - - struct { - u32 conn_id : 16; - u32 rsvd3 : 16; - } wd1; - - struct { - u32 cid : 20; - u32 rsvd2 : 12; - } wd2; - - u64 rsvd3; -}; - -struct spfc_scqe_comm_rsp_sts { - struct spfc_scqe_ch ch; - - struct { - u32 rx_id : 16; - u32 ox_id : 16; - } wd0; - - struct { - u32 conn_id : 16; - u32 hotpooltag : 16; /* ucode return hotpooltag to drv */ - } wd1; - - u32 magic_num; -}; - -struct spfc_scqe_iresp { - struct spfc_scqe_ch ch; - - struct { - u32 rx_id : 16; - u32 ox_id : 16; - } wd0; - - struct { - u32 conn_id : 16; - u32 rsvd0 : 3; - u32 user_id_num : 8; - u32 dif_info : 5; - } wd1; - - struct { - u32 scsi_status : 8; - u32 fcp_flag : 8; - u32 hotpooltag : 16; /* ucode return hotpooltag to drv */ - } wd2; - - u32 fcp_resid; - u32 fcp_sns_len; - u32 fcp_rsp_len; - u32 magic_num; - u16 user_id[FC_SENSEDATA_USERID_CNT_MAX]; - u32 rsv1; -}; - -struct spfc_scqe_nvme_iresp { - struct spfc_scqe_ch ch; - - struct { - u32 rx_id : 16; - u32 ox_id : 16; - } wd0; - - struct { - u32 conn_id : 16; - u32 eresp_flag : 8; - u32 user_id_num : 8; - } wd1; - - struct { - u32 scsi_status : 8; - u32 fcp_flag : 8; - u32 hotpooltag : 16; /* ucode return hotpooltag to drv */ - } wd2; - u32 magic_num; - u32 eresp[8]; -}; - -#pragma pack(1) -struct spfc_dif_result { - u8 vrd_rpt; - u16 pad; - u8 rcv_pi_vb; - u32 rcv_pi_h; - u32 rcv_pi_l; - u16 vrf_agm_imm; - u16 ri_agm_imm; -}; - -#pragma pack() - -struct spfc_scqe_dif_result { - struct spfc_scqe_ch ch; - - struct { - u32 rx_id : 16; - u32 ox_id : 16; - } wd0; - - struct { - u32 conn_id : 16; - u32 rsvd0 : 11; - u32 dif_info : 5; - } wd1; - - struct { - u32 scsi_status : 8; - u32 fcp_flag : 8; - u32 hotpooltag : 16; /* ucode return hotpooltag to drv */ - } wd2; - - u32 fcp_resid; - u32 fcp_sns_len; - u32 fcp_rsp_len; - u32 magic_num; - - u32 rsv1[3]; - struct spfc_dif_result difinfo; -}; - -struct spfc_scqe_rcv_abts_rsp { - struct spfc_scqe_ch ch; - - struct { - u32 rx_id : 16; - u32 ox_id : 16; - } wd0; - - struct { - u32 conn_id : 16; - u32 hotpooltag : 16; - } wd1; - - struct { - u32 fh_rctrl : 8; - u32 rsvd0 : 24; - } wd2; - - struct { - u32 did : 24; - u32 rsvd1 : 8; - } wd3; - - struct { - u32 sid : 24; - u32 rsvd2 : 8; - } wd4; - - /* payload length is according to fh_rctrl:1DWORD or 3DWORD */ - u32 payload[3]; - u32 magic_num; -}; - -struct spfc_scqe_fcp_rsp_sts { - struct spfc_scqe_ch ch; - - struct { - u32 rx_id : 16; - u32 ox_id : 16; - } wd0; - - struct { - u32 conn_id : 16; - u32 rsvd0 : 10; - u32 immi : 1; - u32 dif_info : 5; - } wd1; - - u32 magic_num; - u32 hotpooltag; - u32 xfer_rsp; - u32 rsvd[5]; - - u32 dif_tmp[4]; /* HW will overwrite it */ -}; - -struct spfc_scqe_rcv_els_cmd { - struct spfc_scqe_ch ch; - - struct { - u32 did : 24; - u32 class_mode : 8; /* 0:class3, 1:class2 */ - } wd0; - - struct { - u32 sid : 24; - u32 rsvd1 : 8; - } wd1; - - struct { - u32 rx_id : 16; - u32 ox_id : 16; - } wd2; - - struct { - u32 user_id_num : 16; - u32 data_len : 16; - } wd3; - /* User ID of SRQ SGE, used for drvier buffer release */ - u16 user_id[FC_LS_GS_USERID_CNT_MAX]; - u32 ts; -}; - -struct spfc_scqe_param_check_scq { - struct spfc_scqe_ch ch; - - u8 rsvd0[3]; - u8 port_id; - - u16 scqn; - u16 check_item; - - u16 exch_id_load; - u16 exch_id; - - u16 historty_type; - u16 entry_count; - - u32 xid; - - u32 gpa_h; - u32 gpa_l; - - u32 magic_num; - u32 hotpool_tag; - - u32 payload_len; - u32 sub_err; - - u32 rsvd2[3]; -}; - -struct spfc_scqe_rcv_abts_cmd { - struct spfc_scqe_ch ch; - - struct { - u32 did : 24; - u32 rsvd0 : 8; - } wd0; - - struct { - u32 sid : 24; - u32 rsvd1 : 8; - } wd1; - - struct { - u32 rx_id : 16; - u32 ox_id : 16; - } wd2; -}; - -struct spfc_scqe_rcv_els_gs_rsp { - struct spfc_scqe_ch ch; - - struct { - u32 rx_id : 16; - u32 ox_id : 16; - } wd1; - - struct { - u32 conn_id : 16; - u32 data_len : 16; /* ELS/GS RSP Payload length */ - } wd2; - - struct { - u32 did : 24; - u32 rsvd : 6; - u32 echo_rsp : 1; - u32 end_rsp : 1; - } wd3; - - struct { - u32 sid : 24; - u32 user_id_num : 8; - } wd4; - - struct { - u32 rsvd : 16; - u32 hotpooltag : 16; - } wd5; - - u32 magic_num; - u16 user_id[FC_LS_GS_USERID_CNT_MAX]; -}; - -struct spfc_scqe_rcv_flush_sts { - struct spfc_scqe_ch ch; - - struct { - u32 rsvd0 : 4; - u32 clr_pos : 12; - u32 port_id : 8; - u32 last_flush : 8; - } wd0; -}; - -struct spfc_scqe_rcv_clear_buf_sts { - struct spfc_scqe_ch ch; - - struct { - u32 rsvd0 : 24; - u32 port_id : 8; - } wd0; -}; - -struct spfc_scqe_clr_srq_rsp { - struct spfc_scqe_ch ch; - - struct { - u32 srq_type : 16; - u32 cur_wqe_msn : 16; - } wd0; -}; - -struct spfc_scqe_itmf_marker_sts { - struct spfc_scqe_ch ch; - - struct { - u32 rx_id : 16; - u32 ox_id : 16; - } wd1; - - struct { - u32 did : 24; - u32 end_rsp : 8; - } wd2; - - struct { - u32 sid : 24; - u32 rsvd1 : 8; - } wd3; - - struct { - u32 hotpooltag : 16; - u32 rsvd : 16; - } wd4; - - u32 magic_num; -}; - -struct spfc_scqe_abts_marker_sts { - struct spfc_scqe_ch ch; - - struct { - u32 rx_id : 16; - u32 ox_id : 16; - } wd1; - - struct { - u32 did : 24; - u32 end_rsp : 8; - } wd2; - - struct { - u32 sid : 24; - u32 io_state : 8; - } wd3; - - struct { - u32 hotpooltag : 16; - u32 rsvd : 16; - } wd4; - - u32 magic_num; -}; - -struct spfc_scqe_ini_abort_sts { - struct spfc_scqe_ch ch; - - struct { - u32 rx_id : 16; - u32 ox_id : 16; - } wd1; - - struct { - u32 did : 24; - u32 rsvd : 8; - } wd2; - - struct { - u32 sid : 24; - u32 io_state : 8; - } wd3; - - struct { - u32 hotpooltag : 16; - u32 rsvd : 16; - } wd4; - - u32 magic_num; -}; - -struct spfc_scqe_sq_nop_sts { - struct spfc_scqe_ch ch; - struct { - u32 rsvd : 16; - u32 sqn : 16; - } wd0; - struct { - u32 rsvd : 16; - u32 conn_id : 16; - } wd1; - u32 magic_num; -}; - -/* SCQE, should not be over 64B */ -#define FC_SCQE_SIZE 64 -union spfc_scqe { - struct spfc_scqe_type common; - struct spfc_scqe_sess_sts sess_sts; /* session enable/disable/delete sts */ - struct spfc_scqe_comm_rsp_sts comm_sts; /* aborts/abts_rsp/els rsp sts */ - struct spfc_scqe_rcv_clear_buf_sts clear_sts; /* clear buffer sts */ - struct spfc_scqe_rcv_flush_sts flush_sts; /* flush sq sts */ - struct spfc_scqe_iresp iresp; - struct spfc_scqe_rcv_abts_rsp rcv_abts_rsp; /* recv abts rsp */ - struct spfc_scqe_fcp_rsp_sts fcp_rsp_sts; /* Read/Write/Rsp sts */ - struct spfc_scqe_rcv_els_cmd rcv_els_cmd; /* recv els cmd */ - struct spfc_scqe_rcv_abts_cmd rcv_abts_cmd; /* recv abts cmd */ - struct spfc_scqe_rcv_els_gs_rsp rcv_els_gs_rsp; /* recv els/gs rsp */ - struct spfc_scqe_clr_srq_rsp clr_srq_sts; - struct spfc_scqe_itmf_marker_sts itmf_marker_sts; /* tmf marker */ - struct spfc_scqe_abts_marker_sts abts_marker_sts; /* abts marker */ - struct spfc_scqe_dif_result dif_result; - struct spfc_scqe_param_check_scq param_check_sts; - struct spfc_scqe_nvme_iresp nvme_iresp; - struct spfc_scqe_ini_abort_sts ini_abort_sts; - struct spfc_scqe_sq_nop_sts sq_nop_sts; -}; - -struct spfc_cmdqe_type { - struct { - u32 rx_id : 16; - u32 rsvd0 : 8; - u32 task_type : 8; - } wd0; -}; - -struct spfc_cmdqe_send_ack { - struct { - u32 rx_id : 16; - u32 immi_stand : 1; - u32 rsvd0 : 7; - u32 task_type : 8; - } wd0; - - u32 xid; - u32 cid; -}; - -struct spfc_cmdqe_send_aeq_err { - struct { - u32 errorevent : 8; - u32 errortype : 8; - u32 portid : 8; - u32 task_type : 8; - } wd0; -}; - -/* CMDQE, variable length */ -union spfc_cmdqe { - struct spfc_cmdqe_type common; - struct spfc_cmdqe_sess_en session_enable; - struct spfc_cmdqe_abts_rsp snd_abts_rsp; - struct spfc_cmdqe_abort snd_abort; - struct spfc_cmdqe_buffer_clear buffer_clear; - struct spfc_cmdqe_flush_sq flush_sq; - struct spfc_cmdqe_dump_exch dump_exch; - struct spfc_cmdqe_creat_srqc create_srqc; - struct spfc_cmdqe_delete_srqc delete_srqc; - struct spfc_cmdqe_clr_srq clear_srq; - struct spfc_cmdqe_creat_scqc create_scqc; - struct spfc_cmdqe_delete_scqc delete_scqc; - struct spfc_cmdqe_send_ack send_ack; - struct spfc_cmdqe_send_aeq_err send_aeqerr; - struct spfc_cmdqe_creat_ssqc createssqc; - struct spfc_cmdqe_delete_ssqc deletessqc; - struct spfc_cmdqe_cmdqe_dfx dfx_info; - struct spfc_cmdqe_exch_id_free xid_free; -}; - -#endif diff --git a/drivers/scsi/spfc/hw/spfc_io.c b/drivers/scsi/spfc/hw/spfc_io.c deleted file mode 100644 index 7184eb6a10af..000000000000 --- a/drivers/scsi/spfc/hw/spfc_io.c +++ /dev/null @@ -1,1193 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#include "spfc_io.h" -#include "spfc_module.h" -#include "spfc_service.h" - -#define SPFC_SGE_WD1_XID_MASK 0x3fff - -u32 dif_protect_opcode = INVALID_VALUE32; -u32 dif_app_esc_check = SPFC_DIF_APP_REF_ESC_CHECK; -u32 dif_ref_esc_check = SPFC_DIF_APP_REF_ESC_CHECK; -u32 grd_agm_ini_ctrl = SPFC_DIF_CRC_CS_INITIAL_CONFIG_BY_BIT0_1; -u32 ref_tag_no_increase; -u32 dix_flag; -u32 grd_ctrl; -u32 grd_agm_ctrl = SPFC_DIF_GUARD_VERIFY_ALGORITHM_CTL_T10_CRC16; -u32 cmp_app_tag_mask = 0xffff; -u32 app_tag_ctrl; -u32 ref_tag_ctrl; -u32 ref_tag_mod = INVALID_VALUE32; -u32 rep_ref_tag; -u32 rx_rep_ref_tag; -u16 cmp_app_tag; -u16 rep_app_tag; - -static void spfc_dif_err_count(struct spfc_hba_info *hba, u8 info) -{ - u8 dif_info = info; - - if (dif_info & SPFC_TX_DIF_ERROR_FLAG) { - SPFC_DIF_ERR_STAT(hba, SPFC_DIF_SEND_DIFERR_ALL); - if (dif_info & SPFC_DIF_ERROR_CODE_CRC) - SPFC_DIF_ERR_STAT(hba, SPFC_DIF_SEND_DIFERR_CRC); - - if (dif_info & SPFC_DIF_ERROR_CODE_APP) - SPFC_DIF_ERR_STAT(hba, SPFC_DIF_SEND_DIFERR_APP); - - if (dif_info & SPFC_DIF_ERROR_CODE_REF) - SPFC_DIF_ERR_STAT(hba, SPFC_DIF_SEND_DIFERR_REF); - } else { - SPFC_DIF_ERR_STAT(hba, SPFC_DIF_RECV_DIFERR_ALL); - if (dif_info & SPFC_DIF_ERROR_CODE_CRC) - SPFC_DIF_ERR_STAT(hba, SPFC_DIF_RECV_DIFERR_CRC); - - if (dif_info & SPFC_DIF_ERROR_CODE_APP) - SPFC_DIF_ERR_STAT(hba, SPFC_DIF_RECV_DIFERR_APP); - - if (dif_info & SPFC_DIF_ERROR_CODE_REF) - SPFC_DIF_ERR_STAT(hba, SPFC_DIF_RECV_DIFERR_REF); - } -} - -void spfc_build_no_dif_control(struct unf_frame_pkg *pkg, - struct spfc_fc_dif_info *info) -{ - struct spfc_fc_dif_info *dif_info = info; - - /* dif enable or disable */ - dif_info->wd0.difx_en = SPFC_DIF_DISABLE; - - dif_info->wd1.vpid = pkg->qos_level; - dif_info->wd1.lun_qos_en = 1; -} - -void spfc_dif_action_forward(struct spfc_fc_dif_info *dif_info_l1, - struct unf_dif_control_info *dif_ctrl_u1) -{ - dif_info_l1->wd0.grd_ctrl |= - (dif_ctrl_u1->protect_opcode & UNF_VERIFY_CRC_MASK) - ? SPFC_DIF_GARD_REF_APP_CTRL_VERIFY - : SPFC_DIF_GARD_REF_APP_CTRL_NOT_VERIFY; - dif_info_l1->wd0.grd_ctrl |= - (dif_ctrl_u1->protect_opcode & UNF_REPLACE_CRC_MASK) - ? SPFC_DIF_GARD_REF_APP_CTRL_REPLACE - : SPFC_DIF_GARD_REF_APP_CTRL_FORWARD; - - dif_info_l1->wd0.ref_tag_ctrl |= - (dif_ctrl_u1->protect_opcode & UNF_VERIFY_LBA_MASK) - ? SPFC_DIF_GARD_REF_APP_CTRL_VERIFY - : SPFC_DIF_GARD_REF_APP_CTRL_NOT_VERIFY; - dif_info_l1->wd0.ref_tag_ctrl |= - (dif_ctrl_u1->protect_opcode & UNF_REPLACE_LBA_MASK) - ? SPFC_DIF_GARD_REF_APP_CTRL_REPLACE - : SPFC_DIF_GARD_REF_APP_CTRL_FORWARD; - - dif_info_l1->wd0.app_tag_ctrl |= - (dif_ctrl_u1->protect_opcode & UNF_VERIFY_APP_MASK) - ? SPFC_DIF_GARD_REF_APP_CTRL_VERIFY - : SPFC_DIF_GARD_REF_APP_CTRL_NOT_VERIFY; - dif_info_l1->wd0.app_tag_ctrl |= - (dif_ctrl_u1->protect_opcode & UNF_REPLACE_APP_MASK) - ? SPFC_DIF_GARD_REF_APP_CTRL_REPLACE - : SPFC_DIF_GARD_REF_APP_CTRL_FORWARD; -} - -void spfc_dif_action_delete(struct spfc_fc_dif_info *dif_info_l1, - struct unf_dif_control_info *dif_ctrl_u1) -{ - dif_info_l1->wd0.grd_ctrl |= - (dif_ctrl_u1->protect_opcode & UNF_VERIFY_CRC_MASK) - ? SPFC_DIF_GARD_REF_APP_CTRL_VERIFY - : SPFC_DIF_GARD_REF_APP_CTRL_NOT_VERIFY; - dif_info_l1->wd0.grd_ctrl |= SPFC_DIF_GARD_REF_APP_CTRL_DELETE; - - dif_info_l1->wd0.ref_tag_ctrl |= - (dif_ctrl_u1->protect_opcode & UNF_VERIFY_LBA_MASK) - ? SPFC_DIF_GARD_REF_APP_CTRL_VERIFY - : SPFC_DIF_GARD_REF_APP_CTRL_NOT_VERIFY; - dif_info_l1->wd0.ref_tag_ctrl |= SPFC_DIF_GARD_REF_APP_CTRL_DELETE; - - dif_info_l1->wd0.app_tag_ctrl |= - (dif_ctrl_u1->protect_opcode & UNF_VERIFY_APP_MASK) - ? SPFC_DIF_GARD_REF_APP_CTRL_VERIFY - : SPFC_DIF_GARD_REF_APP_CTRL_NOT_VERIFY; - dif_info_l1->wd0.app_tag_ctrl |= SPFC_DIF_GARD_REF_APP_CTRL_DELETE; -} - -static void spfc_convert_dif_action(struct unf_dif_control_info *dif_ctrl, - struct spfc_fc_dif_info *dif_info) -{ - struct spfc_fc_dif_info *dif_info_l1 = NULL; - struct unf_dif_control_info *dif_ctrl_u1 = NULL; - - dif_info_l1 = dif_info; - dif_ctrl_u1 = dif_ctrl; - - switch (UNF_DIF_ACTION_MASK & dif_ctrl_u1->protect_opcode) { - case UNF_DIF_ACTION_VERIFY_AND_REPLACE: - case UNF_DIF_ACTION_VERIFY_AND_FORWARD: - spfc_dif_action_forward(dif_info_l1, dif_ctrl_u1); - break; - - case UNF_DIF_ACTION_INSERT: - dif_info_l1->wd0.grd_ctrl |= - SPFC_DIF_GARD_REF_APP_CTRL_NOT_VERIFY; - dif_info_l1->wd0.grd_ctrl |= SPFC_DIF_GARD_REF_APP_CTRL_INSERT; - dif_info_l1->wd0.ref_tag_ctrl |= - SPFC_DIF_GARD_REF_APP_CTRL_NOT_VERIFY; - dif_info_l1->wd0.ref_tag_ctrl |= - SPFC_DIF_GARD_REF_APP_CTRL_INSERT; - dif_info_l1->wd0.app_tag_ctrl |= - SPFC_DIF_GARD_REF_APP_CTRL_NOT_VERIFY; - dif_info_l1->wd0.app_tag_ctrl |= - SPFC_DIF_GARD_REF_APP_CTRL_INSERT; - break; - - case UNF_DIF_ACTION_VERIFY_AND_DELETE: - spfc_dif_action_delete(dif_info_l1, dif_ctrl_u1); - break; - - default: - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "Unknown dif protect opcode 0x%x", - dif_ctrl_u1->protect_opcode); - break; - } -} - -void spfc_get_dif_info_l1(struct spfc_fc_dif_info *dif_info_l1, - struct unf_dif_control_info *dif_ctrl_u1) -{ - dif_info_l1->wd1.cmp_app_tag_msk = cmp_app_tag_mask; - - dif_info_l1->rep_app_tag = dif_ctrl_u1->app_tag; - dif_info_l1->rep_ref_tag = dif_ctrl_u1->start_lba; - - dif_info_l1->cmp_app_tag = dif_ctrl_u1->app_tag; - dif_info_l1->cmp_ref_tag = dif_ctrl_u1->start_lba; - - if (cmp_app_tag != 0) - dif_info_l1->cmp_app_tag = cmp_app_tag; - - if (rep_app_tag != 0) - dif_info_l1->rep_app_tag = rep_app_tag; - - if (rep_ref_tag != 0) - dif_info_l1->rep_ref_tag = rep_ref_tag; -} - -void spfc_build_dif_control(struct spfc_hba_info *hba, - struct unf_frame_pkg *pkg, - struct spfc_fc_dif_info *dif_info) -{ - struct spfc_fc_dif_info *dif_info_l1 = NULL; - struct unf_dif_control_info *dif_ctrl_u1 = NULL; - - dif_info_l1 = dif_info; - dif_ctrl_u1 = &pkg->dif_control; - - /* dif enable or disable */ - dif_info_l1->wd0.difx_en = SPFC_DIF_ENABLE; - - dif_info_l1->wd1.vpid = pkg->qos_level; - dif_info_l1->wd1.lun_qos_en = 1; - - /* 512B + 8 size mode */ - dif_info_l1->wd0.sct_size = (dif_ctrl_u1->flags & UNF_DIF_SECTSIZE_4KB) - ? SPFC_DIF_SECTOR_4KB_MODE - : SPFC_DIF_SECTOR_512B_MODE; - - /* dif type 1 */ - dif_info_l1->wd0.dif_verify_type = dif_type; - - /* Check whether the 0xffff app or ref domain is isolated */ - /* If all ff messages are displayed in type1 app, checkcheck sector - * dif_info_l1->wd0.difx_app_esc = SPFC_DIF_APP_REF_ESC_CHECK - */ - - dif_info_l1->wd0.difx_app_esc = dif_app_esc_check; - - /* type1 ref tag If all ff is displayed, check sector is required */ - dif_info_l1->wd0.difx_ref_esc = dif_ref_esc_check; - - /* Currently, only t10 crc is supported */ - dif_info_l1->wd0.grd_agm_ctrl = 0; - - /* Set this parameter based on the values of bit zero and bit one. - * The initial value is 0, and the value is UNF_DEFAULT_CRC_GUARD_SEED - */ - dif_info_l1->wd0.grd_agm_ini_ctrl = grd_agm_ini_ctrl; - dif_info_l1->wd0.app_tag_ctrl = 0; - dif_info_l1->wd0.grd_ctrl = 0; - dif_info_l1->wd0.ref_tag_ctrl = 0; - - /* Convert the verify operation, replace, forward, insert, - * and delete operations based on the actual operation code of the upper - * layer - */ - if (dif_protect_opcode != INVALID_VALUE32) { - dif_ctrl_u1->protect_opcode = - dif_protect_opcode | - (dif_ctrl_u1->protect_opcode & UNF_DIF_ACTION_MASK); - } - - spfc_convert_dif_action(dif_ctrl_u1, dif_info_l1); - dif_info_l1->wd0.app_tag_ctrl |= app_tag_ctrl; - - /* Address self-increase mode */ - dif_info_l1->wd0.ref_tag_mode = - (dif_ctrl_u1->protect_opcode & UNF_DIF_ACTION_NO_INCREASE_REFTAG) - ? (BOTH_NONE) - : (BOTH_INCREASE); - - if (ref_tag_mod != INVALID_VALUE32) - dif_info_l1->wd0.ref_tag_mode = ref_tag_mod; - - /* This parameter is used only when type 3 is set to 0xffff. */ - spfc_get_dif_info_l1(dif_info_l1, dif_ctrl_u1); - - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_MAJOR, - "Port(0x%x) sid_did(0x%x_0x%x) package type(0x%x) apptag(0x%x) flag(0x%x) opcode(0x%x) fcpdl(0x%x) statlba(0x%x)", - hba->port_cfg.port_id, pkg->frame_head.csctl_sid, - pkg->frame_head.rctl_did, pkg->type, pkg->dif_control.app_tag, - pkg->dif_control.flags, pkg->dif_control.protect_opcode, - pkg->dif_control.fcp_dl, pkg->dif_control.start_lba); - - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_MAJOR, - "Port(0x%x) cover dif control info, app:cmp_tag(0x%x) cmp_tag_mask(0x%x) rep_tag(0x%x), ref:tag_mode(0x%x) cmp_tag(0x%x) rep_tag(0x%x).", - hba->port_cfg.port_id, dif_info_l1->cmp_app_tag, - dif_info_l1->wd1.cmp_app_tag_msk, dif_info_l1->rep_app_tag, - dif_info_l1->wd0.ref_tag_mode, dif_info_l1->cmp_ref_tag, - dif_info_l1->rep_ref_tag); - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_MAJOR, - "Port(0x%x) cover dif control info, ctrl:grd(0x%x) ref(0x%x) app(0x%x).", - hba->port_cfg.port_id, dif_info_l1->wd0.grd_ctrl, - dif_info_l1->wd0.ref_tag_ctrl, - dif_info_l1->wd0.app_tag_ctrl); -} - -static u32 spfc_fill_external_sgl_page(struct spfc_hba_info *hba, - struct unf_frame_pkg *pkg, - struct unf_esgl_page *esgl_page, - u32 sge_num, int direction, - u32 context_id, u32 dif_flag) -{ - u32 ret = UNF_RETURN_ERROR; - u32 index = 0; - u32 sge_num_per_page = 0; - u32 buffer_addr = 0; - u32 buf_len = 0; - char *buf = NULL; - ulong phys = 0; - struct unf_esgl_page *unf_esgl_page = NULL; - struct spfc_variable_sge *sge = NULL; - - unf_esgl_page = esgl_page; - while (sge_num > 0) { - /* Obtains the initial address of the sge page */ - sge = (struct spfc_variable_sge *)unf_esgl_page->page_address; - - /* Calculate the number of sge on each page */ - sge_num_per_page = (unf_esgl_page->page_size) / sizeof(struct spfc_variable_sge); - - /* Fill in sgl page. The last sge of each page is link sge by - * default - */ - for (index = 0; index < (sge_num_per_page - 1); index++) { - UNF_GET_SGL_ENTRY(ret, (void *)pkg, &buf, &buf_len, dif_flag); - if (ret != RETURN_OK) - return UNF_RETURN_ERROR; - phys = (ulong)buf; - sge[index].buf_addr_hi = UNF_DMA_HI32(phys); - sge[index].buf_addr_lo = UNF_DMA_LO32(phys); - sge[index].wd0.buf_len = buf_len; - sge[index].wd0.r_flag = 0; - sge[index].wd1.extension_flag = SPFC_WQE_SGE_NOT_EXTEND_FLAG; - sge[index].wd1.last_flag = SPFC_WQE_SGE_NOT_LAST_FLAG; - - /* Parity bit */ - sge[index].wd1.buf_addr_gpa = (sge[index].buf_addr_lo >> UNF_SHIFT_16); - sge[index].wd1.xid = (context_id & SPFC_SGE_WD1_XID_MASK); - - spfc_cpu_to_big32(&sge[index], sizeof(struct spfc_variable_sge)); - - sge_num--; - if (sge_num == 0) - break; - } - - /* sge Set the end flag on the last sge of the page if all the - * pages have been filled. - */ - if (sge_num == 0) { - sge[index].wd1.extension_flag = SPFC_WQE_SGE_NOT_EXTEND_FLAG; - sge[index].wd1.last_flag = SPFC_WQE_SGE_LAST_FLAG; - - /* Parity bit */ - buffer_addr = be32_to_cpu(sge[index].buf_addr_lo); - sge[index].wd1.buf_addr_gpa = (buffer_addr >> UNF_SHIFT_16); - sge[index].wd1.xid = (context_id & SPFC_SGE_WD1_XID_MASK); - - spfc_cpu_to_big32(&sge[index].wd1, SPFC_DWORD_BYTE); - } - /* If only one sge is left empty, the sge reserved on the page - * is used for filling. - */ - else if (sge_num == 1) { - UNF_GET_SGL_ENTRY(ret, (void *)pkg, &buf, &buf_len, - dif_flag); - if (ret != RETURN_OK) - return UNF_RETURN_ERROR; - phys = (ulong)buf; - sge[index].buf_addr_hi = UNF_DMA_HI32(phys); - sge[index].buf_addr_lo = UNF_DMA_LO32(phys); - sge[index].wd0.buf_len = buf_len; - sge[index].wd0.r_flag = 0; - sge[index].wd1.extension_flag = SPFC_WQE_SGE_NOT_EXTEND_FLAG; - sge[index].wd1.last_flag = SPFC_WQE_SGE_LAST_FLAG; - - /* Parity bit */ - sge[index].wd1.buf_addr_gpa = (sge[index].buf_addr_lo >> UNF_SHIFT_16); - sge[index].wd1.xid = (context_id & SPFC_SGE_WD1_XID_MASK); - - spfc_cpu_to_big32(&sge[index], sizeof(struct spfc_variable_sge)); - - sge_num--; - } else { - /* Apply for a new sgl page and fill in link sge */ - UNF_GET_FREE_ESGL_PAGE(unf_esgl_page, hba->lport, pkg); - if (!unf_esgl_page) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Get free esgl page failed."); - return UNF_RETURN_ERROR; - } - phys = unf_esgl_page->esgl_phy_addr; - sge[index].buf_addr_hi = UNF_DMA_HI32(phys); - sge[index].buf_addr_lo = UNF_DMA_LO32(phys); - - /* For the cascaded wqe, you only need to enter the - * cascading buffer address and extension flag, and do - * not need to fill in other fields - */ - sge[index].wd0.buf_len = 0; - sge[index].wd0.r_flag = 0; - sge[index].wd1.extension_flag = SPFC_WQE_SGE_EXTEND_FLAG; - sge[index].wd1.last_flag = SPFC_WQE_SGE_NOT_LAST_FLAG; - - /* parity bit */ - sge[index].wd1.buf_addr_gpa = (sge[index].buf_addr_lo >> UNF_SHIFT_16); - sge[index].wd1.xid = (context_id & SPFC_SGE_WD1_XID_MASK); - - spfc_cpu_to_big32(&sge[index], sizeof(struct spfc_variable_sge)); - } - - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_INFO, - "[info]Port(0x%x) SID(0x%x) DID(0x%x) RXID(0x%x) build esgl left sge num: %u.", - hba->port_cfg.port_id, pkg->frame_head.csctl_sid, - pkg->frame_head.rctl_did, - pkg->frame_head.oxid_rxid, sge_num); - } - - return RETURN_OK; -} - -static u32 spfc_build_local_dif_sgl(struct spfc_hba_info *hba, - struct unf_frame_pkg *pkg, struct spfc_sqe *sqe, - int direction, u32 bd_sge_num) -{ - u32 ret = UNF_RETURN_ERROR; - char *buf = NULL; - u32 buf_len = 0; - ulong phys = 0; - u32 dif_sge_place = 0; - - /* DIF SGE must be followed by BD SGE */ - dif_sge_place = ((bd_sge_num <= pkg->entry_count) ? bd_sge_num : pkg->entry_count); - - /* The entry_count= 0 needs to be specially processed and does not need - * to be mounted. As long as len is set to zero, Last-bit is set to one, - * and E-bit is set to 0. - */ - if (pkg->dif_control.dif_sge_count == 0) { - sqe->sge[dif_sge_place].buf_addr_hi = 0; - sqe->sge[dif_sge_place].buf_addr_lo = 0; - sqe->sge[dif_sge_place].wd0.buf_len = 0; - } else { - UNF_CM_GET_DIF_SGL_ENTRY(ret, (void *)pkg, &buf, &buf_len); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "DOUBLE DIF Get Dif Buf Fail."); - return UNF_RETURN_ERROR; - } - phys = (ulong)buf; - sqe->sge[dif_sge_place].buf_addr_hi = UNF_DMA_HI32(phys); - sqe->sge[dif_sge_place].buf_addr_lo = UNF_DMA_LO32(phys); - sqe->sge[dif_sge_place].wd0.buf_len = buf_len; - } - - /* rdma flag. If the fc is not used, enter 0. */ - sqe->sge[dif_sge_place].wd0.r_flag = 0; - - /* parity bit */ - sqe->sge[dif_sge_place].wd1.buf_addr_gpa = 0; - sqe->sge[dif_sge_place].wd1.xid = 0; - - /* The local sgl does not use the cascading SGE. Therefore, the value of - * this field is always 0. - */ - sqe->sge[dif_sge_place].wd1.extension_flag = SPFC_WQE_SGE_NOT_EXTEND_FLAG; - sqe->sge[dif_sge_place].wd1.last_flag = SPFC_WQE_SGE_LAST_FLAG; - - spfc_cpu_to_big32(&sqe->sge[dif_sge_place], sizeof(struct spfc_variable_sge)); - - return RETURN_OK; -} - -static u32 spfc_build_external_dif_sgl(struct spfc_hba_info *hba, - struct unf_frame_pkg *pkg, - struct spfc_sqe *sqe, int direction, - u32 bd_sge_num) -{ - u32 ret = UNF_RETURN_ERROR; - struct unf_esgl_page *esgl_page = NULL; - ulong phys = 0; - u32 left_sge_num = 0; - u32 dif_sge_place = 0; - struct spfc_parent_ssq_info *ssq = NULL; - u32 ssqn = 0; - - ssqn = (u16)pkg->private_data[PKG_PRIVATE_XCHG_SSQ_INDEX]; - ssq = &hba->parent_queue_mgr->shared_queue[ssqn].parent_ssq_info; - - /* DIF SGE must be followed by BD SGE */ - dif_sge_place = ((bd_sge_num <= pkg->entry_count) ? bd_sge_num : pkg->entry_count); - - /* Allocate the first page first */ - UNF_GET_FREE_ESGL_PAGE(esgl_page, hba->lport, pkg); - if (!esgl_page) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "DOUBLE DIF Get External Page Fail."); - return UNF_RETURN_ERROR; - } - - phys = esgl_page->esgl_phy_addr; - - /* Configuring the Address of the Cascading Page */ - sqe->sge[dif_sge_place].buf_addr_hi = UNF_DMA_HI32(phys); - sqe->sge[dif_sge_place].buf_addr_lo = UNF_DMA_LO32(phys); - - /* Configuring Control Information About the Cascading Page */ - sqe->sge[dif_sge_place].wd0.buf_len = 0; - sqe->sge[dif_sge_place].wd0.r_flag = 0; - sqe->sge[dif_sge_place].wd1.extension_flag = SPFC_WQE_SGE_EXTEND_FLAG; - sqe->sge[dif_sge_place].wd1.last_flag = SPFC_WQE_SGE_NOT_LAST_FLAG; - - /* parity bit */ - sqe->sge[dif_sge_place].wd1.buf_addr_gpa = 0; - sqe->sge[dif_sge_place].wd1.xid = 0; - - spfc_cpu_to_big32(&sqe->sge[dif_sge_place], sizeof(struct spfc_variable_sge)); - - /* Fill in the sge information on the cascading page */ - left_sge_num = pkg->dif_control.dif_sge_count; - ret = spfc_fill_external_sgl_page(hba, pkg, esgl_page, left_sge_num, - direction, ssq->context_id, true); - if (ret != RETURN_OK) - return UNF_RETURN_ERROR; - - return RETURN_OK; -} - -static u32 spfc_build_local_sgl(struct spfc_hba_info *hba, - struct unf_frame_pkg *pkg, struct spfc_sqe *sqe, - int direction) -{ - u32 ret = UNF_RETURN_ERROR; - char *buf = NULL; - u32 buf_len = 0; - u32 index = 0; - ulong phys = 0; - - for (index = 0; index < pkg->entry_count; index++) { - UNF_CM_GET_SGL_ENTRY(ret, (void *)pkg, &buf, &buf_len); - if (ret != RETURN_OK) - return UNF_RETURN_ERROR; - - phys = (ulong)buf; - sqe->sge[index].buf_addr_hi = UNF_DMA_HI32(phys); - sqe->sge[index].buf_addr_lo = UNF_DMA_LO32(phys); - sqe->sge[index].wd0.buf_len = buf_len; - - /* rdma flag. If the fc is not used, enter 0. */ - sqe->sge[index].wd0.r_flag = 0; - - /* parity bit */ - sqe->sge[index].wd1.buf_addr_gpa = SPFC_ZEROCOPY_PCIE_TEMPLATE_VALUE; - sqe->sge[index].wd1.xid = 0; - - /* The local sgl does not use the cascading SGE. Therefore, the - * value of this field is always 0. - */ - sqe->sge[index].wd1.extension_flag = SPFC_WQE_SGE_NOT_EXTEND_FLAG; - sqe->sge[index].wd1.last_flag = SPFC_WQE_SGE_NOT_LAST_FLAG; - - if (index == (pkg->entry_count - 1)) { - /* Sets the last WQE end flag 1 */ - sqe->sge[index].wd1.last_flag = SPFC_WQE_SGE_LAST_FLAG; - } - - spfc_cpu_to_big32(&sqe->sge[index], sizeof(struct spfc_variable_sge)); - } - - /* Adjust the length of the BDSL field in the CTRL domain. */ - SPFC_ADJUST_DATA(sqe->ctrl_sl.ch.wd0.bdsl, - SPFC_BYTES_TO_QW_NUM((pkg->entry_count * - sizeof(struct spfc_variable_sge)))); - - /* The entry_count= 0 needs to be specially processed and does not need - * to be mounted. As long as len is set to zero, Last-bit is set to one, - * and E-bit is set to 0. - */ - if (pkg->entry_count == 0) { - sqe->sge[ARRAY_INDEX_0].buf_addr_hi = 0; - sqe->sge[ARRAY_INDEX_0].buf_addr_lo = 0; - sqe->sge[ARRAY_INDEX_0].wd0.buf_len = 0; - - /* rdma flag. This field is not used in fc. Set it to 0. */ - sqe->sge[ARRAY_INDEX_0].wd0.r_flag = 0; - - /* parity bit */ - sqe->sge[ARRAY_INDEX_0].wd1.buf_addr_gpa = SPFC_ZEROCOPY_PCIE_TEMPLATE_VALUE; - sqe->sge[ARRAY_INDEX_0].wd1.xid = 0; - - /* The local sgl does not use the cascading SGE. Therefore, the - * value of this field is always 0. - */ - sqe->sge[ARRAY_INDEX_0].wd1.extension_flag = SPFC_WQE_SGE_NOT_EXTEND_FLAG; - sqe->sge[ARRAY_INDEX_0].wd1.last_flag = SPFC_WQE_SGE_LAST_FLAG; - - spfc_cpu_to_big32(&sqe->sge[ARRAY_INDEX_0], sizeof(struct spfc_variable_sge)); - - /* Adjust the length of the BDSL field in the CTRL domain. */ - SPFC_ADJUST_DATA(sqe->ctrl_sl.ch.wd0.bdsl, - SPFC_BYTES_TO_QW_NUM(sizeof(struct spfc_variable_sge))); - } - - return RETURN_OK; -} - -static u32 spfc_build_external_sgl(struct spfc_hba_info *hba, - struct unf_frame_pkg *pkg, struct spfc_sqe *sqe, - int direction, u32 bd_sge_num) -{ - u32 ret = UNF_RETURN_ERROR; - char *buf = NULL; - struct unf_esgl_page *esgl_page = NULL; - ulong phys = 0; - u32 buf_len = 0; - u32 index = 0; - u32 left_sge_num = 0; - u32 local_sge_num = 0; - struct spfc_parent_ssq_info *ssq = NULL; - u16 ssqn = 0; - - ssqn = (u16)pkg->private_data[PKG_PRIVATE_XCHG_SSQ_INDEX]; - ssq = &hba->parent_queue_mgr->shared_queue[ssqn].parent_ssq_info; - - /* Ensure that the value of bd_sge_num is greater than or equal to one - */ - local_sge_num = bd_sge_num - 1; - - for (index = 0; index < local_sge_num; index++) { - UNF_CM_GET_SGL_ENTRY(ret, (void *)pkg, &buf, &buf_len); - if (unlikely(ret != RETURN_OK)) - return UNF_RETURN_ERROR; - - phys = (ulong)buf; - - sqe->sge[index].buf_addr_hi = UNF_DMA_HI32(phys); - sqe->sge[index].buf_addr_lo = UNF_DMA_LO32(phys); - sqe->sge[index].wd0.buf_len = buf_len; - - /* RDMA flag, which is not used by FC. */ - sqe->sge[index].wd0.r_flag = 0; - sqe->sge[index].wd1.extension_flag = SPFC_WQE_SGE_NOT_EXTEND_FLAG; - sqe->sge[index].wd1.last_flag = SPFC_WQE_SGE_NOT_LAST_FLAG; - - /* parity bit */ - sqe->sge[index].wd1.buf_addr_gpa = SPFC_ZEROCOPY_PCIE_TEMPLATE_VALUE; - sqe->sge[index].wd1.xid = 0; - - spfc_cpu_to_big32(&sqe->sge[index], sizeof(struct spfc_variable_sge)); - } - - /* Calculate the number of remaining sge. */ - left_sge_num = pkg->entry_count - local_sge_num; - /* Adjust the length of the BDSL field in the CTRL domain. */ - SPFC_ADJUST_DATA(sqe->ctrl_sl.ch.wd0.bdsl, - SPFC_BYTES_TO_QW_NUM((bd_sge_num * sizeof(struct spfc_variable_sge)))); - - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_INFO, - "alloc extended sgl page,leftsge:%d", left_sge_num); - /* Allocating the first cascading page */ - UNF_GET_FREE_ESGL_PAGE(esgl_page, hba->lport, pkg); - if (unlikely(!esgl_page)) - return UNF_RETURN_ERROR; - - phys = esgl_page->esgl_phy_addr; - - /* Configuring the Address of the Cascading Page */ - sqe->sge[index].buf_addr_hi = (u32)UNF_DMA_HI32(phys); - sqe->sge[index].buf_addr_lo = (u32)UNF_DMA_LO32(phys); - - /* Configuring Control Information About the Cascading Page */ - sqe->sge[index].wd0.buf_len = 0; - sqe->sge[index].wd0.r_flag = 0; - sqe->sge[index].wd1.extension_flag = SPFC_WQE_SGE_EXTEND_FLAG; - sqe->sge[index].wd1.last_flag = SPFC_WQE_SGE_NOT_LAST_FLAG; - - /* parity bit */ - sqe->sge[index].wd1.buf_addr_gpa = SPFC_ZEROCOPY_PCIE_TEMPLATE_VALUE; - sqe->sge[index].wd1.xid = 0; - - spfc_cpu_to_big32(&sqe->sge[index], sizeof(struct spfc_variable_sge)); - - /* Fill in the sge information on the cascading page. */ - ret = spfc_fill_external_sgl_page(hba, pkg, esgl_page, left_sge_num, - direction, ssq->context_id, false); - if (ret != RETURN_OK) - return UNF_RETURN_ERROR; - /* Copy the extended data sge to the extended sge of the extended wqe.*/ - if (left_sge_num > 0) { - memcpy(sqe->esge, (void *)esgl_page->page_address, - SPFC_WQE_MAX_ESGE_NUM * sizeof(struct spfc_variable_sge)); - } - - return RETURN_OK; -} - -u32 spfc_build_sgl_by_local_sge_num(struct unf_frame_pkg *pkg, - struct spfc_hba_info *hba, struct spfc_sqe *sqe, - int direction, u32 bd_sge_num) -{ - u32 ret = RETURN_OK; - - if (pkg->entry_count <= bd_sge_num) - ret = spfc_build_local_sgl(hba, pkg, sqe, direction); - else - ret = spfc_build_external_sgl(hba, pkg, sqe, direction, bd_sge_num); - - return ret; -} - -u32 spfc_conf_dual_sgl_info(struct unf_frame_pkg *pkg, - struct spfc_hba_info *hba, struct spfc_sqe *sqe, - int direction, u32 bd_sge_num, bool double_sgl) -{ - u32 ret = RETURN_OK; - - if (double_sgl) { - /* Adjust the length of the DIF_SL field in the CTRL domain */ - SPFC_ADJUST_DATA(sqe->ctrl_sl.ch.wd0.dif_sl, - SPFC_BYTES_TO_QW_NUM(sizeof(struct spfc_variable_sge))); - - if (pkg->dif_control.dif_sge_count <= SPFC_WQE_SGE_DIF_ENTRY_NUM) - ret = spfc_build_local_dif_sgl(hba, pkg, sqe, direction, bd_sge_num); - else - ret = spfc_build_external_dif_sgl(hba, pkg, sqe, direction, bd_sge_num); - } - - return ret; -} - -u32 spfc_build_sgl(struct spfc_hba_info *hba, struct unf_frame_pkg *pkg, - struct spfc_sqe *sqe, int direction, u32 dif_flag) -{ -#define SPFC_ESGE_CNT 3 - u32 ret = RETURN_OK; - u32 bd_sge_num = SPFC_WQE_SGE_ENTRY_NUM; - bool double_sgl = false; - - if (dif_flag != 0 && (pkg->dif_control.flags & UNF_DIF_DOUBLE_SGL)) { - bd_sge_num = SPFC_WQE_SGE_ENTRY_NUM - SPFC_WQE_SGE_DIF_ENTRY_NUM; - double_sgl = true; - } - - /* Only one wqe local sge can be loaded. If more than one wqe local sge - * is used, use the esgl - */ - ret = spfc_build_sgl_by_local_sge_num(pkg, hba, sqe, direction, bd_sge_num); - - if (unlikely(ret != RETURN_OK)) - return ret; - - /* Configuring Dual SGL Information for DIF */ - ret = spfc_conf_dual_sgl_info(pkg, hba, sqe, direction, bd_sge_num, double_sgl); - - return ret; -} - -void spfc_adjust_dix(struct unf_frame_pkg *pkg, struct spfc_fc_dif_info *dif_info, - u8 task_type) -{ - u8 tasktype = task_type; - struct spfc_fc_dif_info *dif_info_l1 = NULL; - - dif_info_l1 = dif_info; - - if (dix_flag == 1) { - if (tasktype == SPFC_SQE_FCP_IWRITE || - tasktype == SPFC_SQE_FCP_TRD) { - if ((UNF_DIF_ACTION_MASK & pkg->dif_control.protect_opcode) == - UNF_DIF_ACTION_VERIFY_AND_FORWARD) { - dif_info_l1->wd0.grd_ctrl |= - SPFC_DIF_GARD_REF_APP_CTRL_REPLACE; - dif_info_l1->wd0.grd_agm_ctrl = - SPFC_DIF_GUARD_VERIFY_IP_CHECKSUM_REPLACE_CRC16; - } - - if ((UNF_DIF_ACTION_MASK & pkg->dif_control.protect_opcode) == - UNF_DIF_ACTION_VERIFY_AND_DELETE) { - dif_info_l1->wd0.grd_agm_ctrl = - SPFC_DIF_GUARD_VERIFY_IP_CHECKSUM_REPLACE_CRC16; - } - } - - if (tasktype == SPFC_SQE_FCP_IREAD || - tasktype == SPFC_SQE_FCP_TWR) { - if ((UNF_DIF_ACTION_MASK & - pkg->dif_control.protect_opcode) == - UNF_DIF_ACTION_VERIFY_AND_FORWARD) { - dif_info_l1->wd0.grd_ctrl |= - SPFC_DIF_GARD_REF_APP_CTRL_REPLACE; - dif_info_l1->wd0.grd_agm_ctrl = - SPFC_DIF_GUARD_VERIFY_CRC16_REPLACE_IP_CHECKSUM; - } - - if ((UNF_DIF_ACTION_MASK & - pkg->dif_control.protect_opcode) == - UNF_DIF_ACTION_INSERT) { - dif_info_l1->wd0.grd_agm_ctrl = - SPFC_DIF_GUARD_VERIFY_CRC16_REPLACE_IP_CHECKSUM; - } - } - } - - if (grd_agm_ctrl != 0) - dif_info_l1->wd0.grd_agm_ctrl = grd_agm_ctrl; - - if (grd_ctrl != 0) - dif_info_l1->wd0.grd_ctrl = grd_ctrl; -} - -void spfc_get_dma_direction_by_fcp_cmnd(const struct unf_fcp_cmnd *fcp_cmnd, - int *dma_direction, u8 *task_type) -{ - if (UNF_FCP_WR_DATA & fcp_cmnd->control) { - *task_type = SPFC_SQE_FCP_IWRITE; - *dma_direction = DMA_TO_DEVICE; - } else if (UNF_GET_TASK_MGMT_FLAGS(fcp_cmnd->control) != 0) { - *task_type = SPFC_SQE_FCP_ITMF; - *dma_direction = DMA_FROM_DEVICE; - } else { - *task_type = SPFC_SQE_FCP_IREAD; - *dma_direction = DMA_FROM_DEVICE; - } -} - -static inline u32 spfc_build_icmnd_wqe(struct spfc_hba_info *hba, - struct unf_frame_pkg *pkg, - struct spfc_sqe *sge) -{ - u32 ret = RETURN_OK; - int direction = 0; - u8 tasktype = 0; - struct unf_fcp_cmnd *fcp_cmnd = NULL; - struct spfc_sqe *sqe = sge; - u32 dif_flag = 0; - - fcp_cmnd = pkg->fcp_cmnd; - if (unlikely(!fcp_cmnd)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[err]Package's FCP commond pointer is NULL."); - - return UNF_RETURN_ERROR; - } - - spfc_get_dma_direction_by_fcp_cmnd(fcp_cmnd, &direction, &tasktype); - - spfc_build_icmnd_wqe_ts_header(pkg, sqe, tasktype, hba->exi_base, hba->port_index); - - spfc_build_icmnd_wqe_ctrls(pkg, sqe); - - spfc_build_icmnd_wqe_ts(hba, pkg, &sqe->ts_sl, &sqe->ts_ex); - - if (sqe->ts_sl.task_type != SPFC_SQE_FCP_ITMF) { - if (pkg->dif_control.protect_opcode == UNF_DIF_ACTION_NONE) { - dif_flag = 0; - spfc_build_no_dif_control(pkg, &sqe->ts_sl.cont.icmnd.info.dif_info); - } else { - dif_flag = 1; - spfc_build_dif_control(hba, pkg, &sqe->ts_sl.cont.icmnd.info.dif_info); - spfc_adjust_dix(pkg, - &sqe->ts_sl.cont.icmnd.info.dif_info, - tasktype); - } - } - - ret = spfc_build_sgl(hba, pkg, sqe, direction, dif_flag); - - sqe->sid = UNF_GET_SID(pkg); - sqe->did = UNF_GET_DID(pkg); - - return ret; -} - -u32 spfc_send_scsi_cmnd(void *hba, struct unf_frame_pkg *pkg) -{ - struct spfc_hba_info *spfc_hba = NULL; - struct spfc_parent_sq_info *parent_sq = NULL; - u32 ret = UNF_RETURN_ERROR; - struct spfc_sqe sqe; - u16 ssqn; - struct spfc_parent_queue_info *parent_queue = NULL; - - /* input param check */ - FC_CHECK_RETURN_VALUE(hba, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(pkg, UNF_RETURN_ERROR); - - SPFC_CHECK_PKG_ALLOCTIME(pkg); - memset(&sqe, 0, sizeof(struct spfc_sqe)); - spfc_hba = hba; - - /* 1. find parent sq for scsi_cmnd(pkg) */ - parent_sq = spfc_find_parent_sq_by_pkg(spfc_hba, pkg); - if (unlikely(!parent_sq)) { - /* Do not need to print info */ - return UNF_RETURN_ERROR; - } - - pkg->qos_level += spfc_hba->vpid_start; - - /* 2. build cmnd wqe (to sqe) for scsi_cmnd(pkg) */ - ret = spfc_build_icmnd_wqe(spfc_hba, pkg, &sqe); - if (unlikely(ret != RETURN_OK)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[fail]Port(0x%x) Build WQE failed, SID(0x%x) DID(0x%x) pkg type(0x%x) hottag(0x%x).", - spfc_hba->port_cfg.port_id, pkg->frame_head.csctl_sid, - pkg->frame_head.rctl_did, pkg->type, UNF_GET_XCHG_TAG(pkg)); - - return ret; - } - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_INFO, - "Port(0x%x) RPort(0x%x) send FCP_CMND TYPE(0x%x) Local_Xid(0x%x) hottag(0x%x) LBA(0x%llx)", - spfc_hba->port_cfg.port_id, parent_sq->rport_index, - sqe.ts_sl.task_type, sqe.ts_sl.local_xid, - pkg->private_data[PKG_PRIVATE_XCHG_HOT_POOL_INDEX], - *((u64 *)pkg->fcp_cmnd->cdb)); - - ssqn = (u16)pkg->private_data[PKG_PRIVATE_XCHG_SSQ_INDEX]; - if (sqe.ts_sl.task_type == SPFC_SQE_FCP_ITMF) { - parent_queue = container_of(parent_sq, struct spfc_parent_queue_info, - parent_sq_info); - ret = spfc_suspend_sqe_and_send_nop(spfc_hba, parent_queue, &sqe, pkg); - return ret; - } - /* 3. En-Queue Parent SQ for scsi_cmnd(pkg) sqe */ - ret = spfc_parent_sq_enqueue(parent_sq, &sqe, ssqn); - - return ret; -} - -static void spfc_ini_status_default_handler(struct spfc_scqe_iresp *iresp, - struct unf_frame_pkg *pkg) -{ - u8 control = 0; - u16 com_err_code = 0; - - control = iresp->wd2.fcp_flag & SPFC_CTRL_MASK; - - if (iresp->fcp_resid != 0) { - com_err_code = UNF_IO_FAILED; - pkg->residus_len = iresp->fcp_resid; - } else { - com_err_code = UNF_IO_SUCCESS; - pkg->residus_len = 0; - } - - pkg->status = spfc_fill_pkg_status(com_err_code, control, iresp->wd2.scsi_status); - - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_INFO, - "[info]Fill package with status: 0x%x, residus len: 0x%x", - pkg->status, pkg->residus_len); -} - -static void spfc_check_fcp_rsp_iu(struct spfc_scqe_iresp *iresp, - struct spfc_hba_info *hba, - struct unf_frame_pkg *pkg) -{ - u8 scsi_status = 0; - u8 control = 0; - - control = (u8)iresp->wd2.fcp_flag; - scsi_status = (u8)iresp->wd2.scsi_status; - - /* FcpRspIU with Little End from IOB WQE to COM's pkg also */ - if (control & FCP_RESID_UNDER_MASK) { - /* under flow: usually occurs in inquiry */ - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_INFO, - "[info]I_STS IOB posts under flow with residus len: %u, FCP residue: %u.", - pkg->residus_len, iresp->fcp_resid); - - if (pkg->residus_len != iresp->fcp_resid) - pkg->status = spfc_fill_pkg_status(UNF_IO_FAILED, control, scsi_status); - else - pkg->status = spfc_fill_pkg_status(UNF_IO_UNDER_FLOW, control, scsi_status); - } - - if (control & FCP_RESID_OVER_MASK) { - /* over flow: error happened */ - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]I_STS IOB posts over flow with residus len: %u, FCP residue: %u.", - pkg->residus_len, iresp->fcp_resid); - - if (pkg->residus_len != iresp->fcp_resid) - pkg->status = spfc_fill_pkg_status(UNF_IO_FAILED, control, scsi_status); - else - pkg->status = spfc_fill_pkg_status(UNF_IO_OVER_FLOW, control, scsi_status); - } - - pkg->unf_rsp_pload_bl.length = 0; - pkg->unf_sense_pload_bl.length = 0; - - if (control & FCP_RSP_LEN_VALID_MASK) { - /* dma by chip */ - pkg->unf_rsp_pload_bl.buffer_ptr = NULL; - - pkg->unf_rsp_pload_bl.length = iresp->fcp_rsp_len; - pkg->byte_orders |= UNF_BIT_3; - } - - if (control & FCP_SNS_LEN_VALID_MASK) { - /* dma by chip */ - pkg->unf_sense_pload_bl.buffer_ptr = NULL; - - pkg->unf_sense_pload_bl.length = iresp->fcp_sns_len; - pkg->byte_orders |= UNF_BIT_4; - } - - if (iresp->wd1.user_id_num == 1 && - (pkg->unf_sense_pload_bl.length + pkg->unf_rsp_pload_bl.length > 0)) { - pkg->unf_rsp_pload_bl.buffer_ptr = - (u8 *)spfc_get_els_buf_by_user_id(hba, (u16)iresp->user_id[ARRAY_INDEX_0]); - } else if (iresp->wd1.user_id_num > 1) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]receive buff num 0x%x > 1 0x%x", - iresp->wd1.user_id_num, control); - } -} - -u16 spfc_get_com_err_code(struct unf_frame_pkg *pkg) -{ - u16 com_err_code = UNF_IO_FAILED; - u32 status_subcode = 0; - - status_subcode = pkg->status_sub_code; - - if (likely(status_subcode == 0)) - com_err_code = 0; - else if (status_subcode == UNF_DIF_CRC_ERR) - com_err_code = UNF_IO_DIF_ERROR; - else if (status_subcode == UNF_DIF_LBA_ERR) - com_err_code = UNF_IO_DIF_REF_ERROR; - else if (status_subcode == UNF_DIF_APP_ERR) - com_err_code = UNF_IO_DIF_GEN_ERROR; - - return com_err_code; -} - -void spfc_process_ini_fail_io(struct spfc_hba_info *hba, union spfc_scqe *iresp, - struct unf_frame_pkg *pkg) -{ - u16 com_err_code = UNF_IO_FAILED; - - /* 1. error stats process */ - if (SPFC_GET_SCQE_STATUS((union spfc_scqe *)(void *)iresp) != 0) { - switch (SPFC_GET_SCQE_STATUS((union spfc_scqe *)(void *)iresp)) { - /* I/O not complete: 1.session reset; 2.clear buffer */ - case FC_CQE_BUFFER_CLEAR_IO_COMPLETED: - case FC_CQE_SESSION_RST_CLEAR_IO_COMPLETED: - case FC_CQE_SESSION_ONLY_CLEAR_IO_COMPLETED: - case FC_CQE_WQE_FLUSH_IO_COMPLETED: - com_err_code = UNF_IO_CLEAN_UP; - - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_MAJOR, - "[warn]Port(0x%x) INI IO not complete, OX_ID(0x%x) RX_ID(0x%x) status(0x%x)", - hba->port_cfg.port_id, - ((struct spfc_scqe_iresp *)iresp)->wd0.ox_id, - ((struct spfc_scqe_iresp *)iresp)->wd0.rx_id, - com_err_code); - - break; - /* Allocate task id(oxid) fail */ - case FC_ERROR_INVALID_TASK_ID: - com_err_code = UNF_IO_NO_XCHG; - break; - case FC_ALLOC_EXCH_ID_FAILED: - com_err_code = UNF_IO_NO_XCHG; - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_MAJOR, - "[warn]Port(0x%x) INI IO, tag 0x%x alloc oxid fail.", - hba->port_cfg.port_id, - ((struct spfc_scqe_iresp *)iresp)->wd2.hotpooltag); - break; - case FC_ERROR_CODE_DATA_DIFX_FAILED: - com_err_code = pkg->status >> UNF_SHIFT_16; - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_MAJOR, - "[warn]Port(0x%x) INI IO, tag 0x%x tx dif error.", - hba->port_cfg.port_id, - ((struct spfc_scqe_iresp *)iresp)->wd2.hotpooltag); - break; - /* any other: I/O failed --->>> DID error */ - default: - com_err_code = UNF_IO_FAILED; - break; - } - - /* fill pkg status & return directly */ - pkg->status = - spfc_fill_pkg_status(com_err_code, - ((struct spfc_scqe_iresp *)iresp)->wd2.fcp_flag, - ((struct spfc_scqe_iresp *)iresp)->wd2.scsi_status); - - return; - } - - /* 2. default stats process */ - spfc_ini_status_default_handler((struct spfc_scqe_iresp *)iresp, pkg); - - /* 3. FCP RSP IU check */ - spfc_check_fcp_rsp_iu((struct spfc_scqe_iresp *)iresp, hba, pkg); -} - -void spfc_process_dif_result(struct spfc_hba_info *hba, union spfc_scqe *wqe, - struct unf_frame_pkg *pkg) -{ - u16 com_err_code = UNF_IO_FAILED; - u8 dif_info = 0; - - dif_info = wqe->common.wd0.dif_vry_rst; - if (dif_info == SPFC_TX_DIF_ERROR_FLAG) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[error]Port(0x%x) TGT recv tx dif result abnormal.", - hba->port_cfg.port_id); - } - - pkg->status_sub_code = - (dif_info & SPFC_DIF_ERROR_CODE_CRC) - ? UNF_DIF_CRC_ERR - : ((dif_info & SPFC_DIF_ERROR_CODE_REF) - ? UNF_DIF_LBA_ERR - : ((dif_info & SPFC_DIF_ERROR_CODE_APP) ? UNF_DIF_APP_ERR : 0)); - com_err_code = spfc_get_com_err_code(pkg); - pkg->status = (u32)(com_err_code) << UNF_SHIFT_16; - - if (unlikely(com_err_code != 0)) { - spfc_dif_err_count(hba, dif_info); - - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_INFO, - "[error]Port(0x%x) INI io status with dif result(0x%x),subcode(0x%x) pkg->status(0x%x)", - hba->port_cfg.port_id, dif_info, - pkg->status_sub_code, pkg->status); - } -} - -u32 spfc_scq_recv_iresp(struct spfc_hba_info *hba, union spfc_scqe *wqe) -{ -#define SPFC_IRSP_USERID_LEN ((FC_SENSEDATA_USERID_CNT_MAX + 1) / 2) - struct spfc_scqe_iresp *iresp = NULL; - struct unf_frame_pkg pkg; - u32 ret = RETURN_OK; - u16 hot_tag; - - FC_CHECK_RETURN_VALUE((hba), UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE((wqe), UNF_RETURN_ERROR); - - iresp = (struct spfc_scqe_iresp *)(void *)wqe; - - /* 1. Constraints: I_STS remain cnt must be zero */ - if (unlikely(SPFC_GET_SCQE_REMAIN_CNT(wqe) != 0)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[err]Port(0x%x) ini_wqe(OX_ID:0x%x RX_ID:0x%x) HotTag(0x%x) remain_cnt(0x%x) abnormal, status(0x%x)", - hba->port_cfg.port_id, iresp->wd0.ox_id, - iresp->wd0.rx_id, iresp->wd2.hotpooltag, - SPFC_GET_SCQE_REMAIN_CNT(wqe), - SPFC_GET_SCQE_STATUS(wqe)); - - UNF_PRINT_SFS_LIMIT(UNF_MAJOR, hba->port_cfg.port_id, wqe, sizeof(union spfc_scqe)); - - /* return directly */ - return UNF_RETURN_ERROR; - } - - spfc_swap_16_in_32((u32 *)iresp->user_id, SPFC_IRSP_USERID_LEN); - - memset(&pkg, 0, sizeof(struct unf_frame_pkg)); - pkg.private_data[PKG_PRIVATE_XCHG_ALLOC_TIME] = iresp->magic_num; - pkg.frame_head.oxid_rxid = (((iresp->wd0.ox_id) << UNF_SHIFT_16) | (iresp->wd0.rx_id)); - - hot_tag = (u16)iresp->wd2.hotpooltag; - /* 2. HotTag validity check */ - if (likely(hot_tag >= hba->exi_base && (hot_tag < hba->exi_base + hba->exi_count))) { - pkg.status = UNF_IO_SUCCESS; - pkg.private_data[PKG_PRIVATE_XCHG_HOT_POOL_INDEX] = - hot_tag - hba->exi_base; - } else { - /* OX_ID error: return by COM */ - pkg.status = UNF_IO_FAILED; - pkg.private_data[PKG_PRIVATE_XCHG_HOT_POOL_INDEX] = INVALID_VALUE16; - - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[err]Port(0x%x) ini_cmnd_wqe(OX_ID:0x%x RX_ID:0x%x) ox_id invalid, status(0x%x)", - hba->port_cfg.port_id, iresp->wd0.ox_id, iresp->wd0.rx_id, - SPFC_GET_SCQE_STATUS(wqe)); - - UNF_PRINT_SFS_LIMIT(UNF_MAJOR, hba->port_cfg.port_id, wqe, - sizeof(union spfc_scqe)); - } - - /* process dif result */ - spfc_process_dif_result(hba, wqe, &pkg); - - /* 3. status check */ - if (unlikely(SPFC_GET_SCQE_STATUS(wqe) || - iresp->wd2.scsi_status != 0 || iresp->fcp_resid != 0 || - ((iresp->wd2.fcp_flag & SPFC_CTRL_MASK) != 0))) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_INFO, - "[warn]Port(0x%x) scq_status(0x%x) scsi_status(0x%x) fcp_resid(0x%x) fcp_flag(0x%x)", - hba->port_cfg.port_id, SPFC_GET_SCQE_STATUS(wqe), - iresp->wd2.scsi_status, iresp->fcp_resid, - iresp->wd2.fcp_flag); - - /* set pkg status & check fcp_rsp IU */ - spfc_process_ini_fail_io(hba, (union spfc_scqe *)iresp, &pkg); - } - - /* 4. LL_Driver ---to--->>> COM_Driver */ - UNF_LOWLEVEL_SCSI_COMPLETED(ret, hba->lport, &pkg); - if (iresp->wd1.user_id_num == 1 && - (pkg.unf_sense_pload_bl.length + pkg.unf_rsp_pload_bl.length > 0)) { - spfc_post_els_srq_wqe(&hba->els_srq_info, (u16)iresp->user_id[ARRAY_INDEX_0]); - } - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_INFO, - "[info]Port(0x%x) rport(0x%x) recv(%s) hottag(0x%x) OX_ID(0x%x) RX_ID(0x%x) return(%s)", - hba->port_cfg.port_id, iresp->wd1.conn_id, - (SPFC_SCQE_FCP_IRSP == (SPFC_GET_SCQE_TYPE(wqe)) ? "IRESP" : "ITMF_RSP"), - pkg.private_data[PKG_PRIVATE_XCHG_HOT_POOL_INDEX], iresp->wd0.ox_id, - iresp->wd0.rx_id, (ret == RETURN_OK) ? "OK" : "ERROR"); - - return ret; -} diff --git a/drivers/scsi/spfc/hw/spfc_io.h b/drivers/scsi/spfc/hw/spfc_io.h deleted file mode 100644 index 26d10a51bbe4..000000000000 --- a/drivers/scsi/spfc/hw/spfc_io.h +++ /dev/null @@ -1,138 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPFC_IO_H -#define SPFC_IO_H - -#include "unf_type.h" -#include "unf_common.h" -#include "spfc_hba.h" - -#ifdef __cplusplus -#if __cplusplus -extern "C" { -#endif -#endif /* __cplusplus */ - -#define BYTE_PER_DWORD 4 -#define SPFC_TRESP_DIRECT_CARRY_LEN (23 * 4) -#define FCP_RESP_IU_LEN_BYTE_GOOD_STATUS 24 -#define SPFC_TRSP_IU_CONTROL_OFFSET 2 -#define SPFC_TRSP_IU_FCP_CONF_REP (1 << 12) - -struct spfc_dif_io_param { - u32 all_len; - u32 buf_len; - char **buf; - char *in_buf; - int drect; -}; - -enum dif_mode_type { - DIF_MODE_NONE = 0x0, - DIF_MODE_INSERT = 0x1, - DIF_MODE_REMOVE = 0x2, - DIF_MODE_FORWARD_OR_REPLACE = 0x3 -}; - -enum ref_tag_mode_type { - BOTH_NONE = 0x0, - RECEIVE_INCREASE = 0x1, - REPLACE_INCREASE = 0x2, - BOTH_INCREASE = 0x3 -}; - -#define SPFC_DIF_DISABLE 0 -#define SPFC_DIF_ENABLE 1 -#define SPFC_DIF_SINGLE_SGL 0 -#define SPFC_DIF_DOUBLE_SGL 1 -#define SPFC_DIF_SECTOR_512B_MODE 0 -#define SPFC_DIF_SECTOR_4KB_MODE 1 -#define SPFC_DIF_TYPE1 0x01 -#define SPFC_DIF_TYPE3 0x03 -#define SPFC_DIF_GUARD_VERIFY_ALGORITHM_CTL_T10_CRC16 0x0 -#define SPFC_DIF_GUARD_VERIFY_CRC16_REPLACE_IP_CHECKSUM 0x1 -#define SPFC_DIF_GUARD_VERIFY_IP_CHECKSUM_REPLACE_CRC16 0x2 -#define SPFC_DIF_GUARD_VERIFY_ALGORITHM_CTL_IP_CHECKSUM 0x3 -#define SPFC_DIF_CRC16_INITIAL_SELECTOR_DEFAUL 0 -#define SPFC_DIF_CRC_CS_INITIAL_CONFIG_BY_REGISTER 0 -#define SPFC_DIF_CRC_CS_INITIAL_CONFIG_BY_BIT0_1 0x4 - -#define SPFC_DIF_GARD_REF_APP_CTRL_VERIFY 0x4 -#define SPFC_DIF_GARD_REF_APP_CTRL_NOT_VERIFY 0x0 -#define SPFC_DIF_GARD_REF_APP_CTRL_INSERT 0x0 -#define SPFC_DIF_GARD_REF_APP_CTRL_DELETE 0x1 -#define SPFC_DIF_GARD_REF_APP_CTRL_FORWARD 0x2 -#define SPFC_DIF_GARD_REF_APP_CTRL_REPLACE 0x3 - -#define SPFC_BUILD_RESPONSE_INFO_NON_GAP_MODE0 0 -#define SPFC_BUILD_RESPONSE_INFO_GPA_MODE1 1 -#define SPFC_CONF_SUPPORT 1 -#define SPFC_CONF_NOT_SUPPORT 0 -#define SPFC_XID_INTERVAL 2048 - -#define SPFC_DIF_ERROR_CODE_MASK 0xe -#define SPFC_DIF_ERROR_CODE_CRC 0x2 -#define SPFC_DIF_ERROR_CODE_REF 0x4 -#define SPFC_DIF_ERROR_CODE_APP 0x8 -#define SPFC_TX_DIF_ERROR_FLAG (1 << 7) - -#define SPFC_DIF_PAYLOAD_TYPE (1 << 0) -#define SPFC_DIF_CRC_TYPE (1 << 1) -#define SPFC_DIF_APP_TYPE (1 << 2) -#define SPFC_DIF_REF_TYPE (1 << 3) - -#define SPFC_DIF_SEND_DIFERR_ALL (0) -#define SPFC_DIF_SEND_DIFERR_CRC (1) -#define SPFC_DIF_SEND_DIFERR_APP (2) -#define SPFC_DIF_SEND_DIFERR_REF (3) -#define SPFC_DIF_RECV_DIFERR_ALL (4) -#define SPFC_DIF_RECV_DIFERR_CRC (5) -#define SPFC_DIF_RECV_DIFERR_APP (6) -#define SPFC_DIF_RECV_DIFERR_REF (7) -#define SPFC_DIF_ERR_ENABLE (382855) -#define SPFC_DIF_ERR_DISABLE (0) - -#define SPFC_DIF_LENGTH (8) -#define SPFC_SECT_SIZE_512 (512) -#define SPFC_SECT_SIZE_4096 (4096) -#define SPFC_SECT_SIZE_512_8 (520) -#define SPFC_SECT_SIZE_4096_8 (4104) -#define SPFC_DIF_SECT_SIZE_APP_OFFSET (2) -#define SPFC_DIF_SECT_SIZE_LBA_OFFSET (4) - -#define SPFC_MAX_IO_TAG (2048) -#define SPFC_PRINT_WORD (8) - -extern u32 dif_protect_opcode; -extern u32 dif_sect_size; -extern u32 no_dif_sect_size; -extern u32 grd_agm_ini_ctrl; -extern u32 ref_tag_mod; -extern u32 grd_ctrl; -extern u32 grd_agm_ctrl; -extern u32 cmp_app_tag_mask; -extern u32 app_tag_ctrl; -extern u32 ref_tag_ctrl; -extern u32 rep_ref_tag; -extern u32 rx_rep_ref_tag; -extern u16 cmp_app_tag; -extern u16 rep_app_tag; - -#define spfc_fill_pkg_status(com_err_code, control, scsi_status) \ - (((u32)(com_err_code) << 16) | ((u32)(control) << 8) | \ - (u32)(scsi_status)) -#define SPFC_CTRL_MASK 0x1f - -u32 spfc_send_scsi_cmnd(void *hba, struct unf_frame_pkg *pkg); -u32 spfc_scq_recv_iresp(struct spfc_hba_info *hba, union spfc_scqe *wqe); -void spfc_process_dif_result(struct spfc_hba_info *hba, union spfc_scqe *wqe, - struct unf_frame_pkg *pkg); - -#ifdef __cplusplus -#if __cplusplus -} -#endif -#endif /* __cplusplus */ - -#endif /* __SPFC_IO_H__ */ diff --git a/drivers/scsi/spfc/hw/spfc_lld.c b/drivers/scsi/spfc/hw/spfc_lld.c deleted file mode 100644 index a35484f1c917..000000000000 --- a/drivers/scsi/spfc/hw/spfc_lld.c +++ /dev/null @@ -1,997 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/pci.h> -#include <linux/device.h> -#include <linux/io-mapping.h> -#include <linux/interrupt.h> -#include <linux/inetdevice.h> -#include <net/addrconf.h> -#include <linux/time.h> -#include <linux/timex.h> -#include <linux/rtc.h> -#include <linux/aer.h> -#include <linux/debugfs.h> - -#include "spfc_lld.h" -#include "sphw_hw.h" -#include "sphw_mt.h" -#include "sphw_hw_cfg.h" -#include "sphw_hw_comm.h" -#include "sphw_common.h" -#include "spfc_cqm_main.h" -#include "spfc_module.h" - -#define SPFC_DRV_NAME "spfc" -#define SPFC_CHIP_NAME "spfc" - -#define PCI_VENDOR_ID_RAMAXEL 0x1E81 -#define SPFC_DEV_ID_PF_STD 0x9010 -#define SPFC_DEV_ID_VF 0x9008 - -#define SPFC_VF_PCI_CFG_REG_BAR 0 -#define SPFC_PF_PCI_CFG_REG_BAR 1 - -#define SPFC_PCI_INTR_REG_BAR 2 -#define SPFC_PCI_MGMT_REG_BAR 3 -#define SPFC_PCI_DB_BAR 4 - -#define SPFC_SECOND_BASE (1000) -#define SPFC_SYNC_YEAR_OFFSET (1900) -#define SPFC_SYNC_MONTH_OFFSET (1) -#define SPFC_MINUTE_BASE (60) -#define SPFC_WAIT_TOOL_CNT_TIMEOUT 10000 - -#define SPFC_MIN_TIME_IN_USECS 900 -#define SPFC_MAX_TIME_IN_USECS 1000 -#define SPFC_MAX_LOOP_TIMES 10000 - -#define SPFC_TOOL_MIN_TIME_IN_USECS 9900 -#define SPFC_TOOL_MAX_TIME_IN_USECS 10000 - -#define SPFC_EVENT_PROCESS_TIMEOUT 10000 - -#define FIND_BIT(num, n) (((num) & (1UL << (n))) ? 1 : 0) -#define SET_BIT(num, n) ((num) | (1UL << (n))) -#define CLEAR_BIT(num, n) ((num) & (~(1UL << (n)))) - -#define MAX_CARD_ID 64 -static unsigned long card_bit_map; -LIST_HEAD(g_spfc_chip_list); -struct spfc_uld_info g_uld_info[SERVICE_T_MAX] = { {0} }; - -struct unf_cm_handle_op spfc_cm_op_handle = {0}; - -u32 allowed_probe_num = SPFC_MAX_PORT_NUM; -u32 dif_sgl_mode; -u32 max_speed = SPFC_SPEED_32G; -u32 accum_db_num = 1; -u32 dif_type = 0x1; -u32 wqe_page_size = 4096; -u32 wqe_pre_load = 6; -u32 combo_length = 128; -u32 cos_bit_map = 0x1f; -u32 spfc_dif_type; -u32 spfc_dif_enable; -u8 spfc_guard; -int link_lose_tmo = 30; - -u32 exit_count = 4096; -u32 exit_stride = 4096; -u32 exit_base; - -/* dfx counter */ -atomic64_t rx_tx_stat[SPFC_MAX_PORT_NUM][SPFC_MAX_PORT_TASK_TYPE_STAT_NUM]; -atomic64_t rx_tx_err[SPFC_MAX_PORT_NUM][SPFC_MAX_PORT_TASK_TYPE_STAT_NUM]; -atomic64_t scq_err_stat[SPFC_MAX_PORT_NUM][SPFC_MAX_PORT_TASK_TYPE_STAT_NUM]; -atomic64_t aeq_err_stat[SPFC_MAX_PORT_NUM][SPFC_MAX_PORT_TASK_TYPE_STAT_NUM]; -atomic64_t dif_err_stat[SPFC_MAX_PORT_NUM][SPFC_MAX_PORT_TASK_TYPE_STAT_NUM]; -atomic64_t mail_box_stat[SPFC_MAX_PORT_NUM][SPFC_MAX_PORT_TASK_TYPE_STAT_NUM]; -atomic64_t up_err_event_stat[SPFC_MAX_PORT_NUM][SPFC_MAX_PORT_TASK_TYPE_STAT_NUM]; -u64 link_event_stat[SPFC_MAX_PORT_NUM][SPFC_MAX_LINK_EVENT_CNT]; -u64 link_reason_stat[SPFC_MAX_PORT_NUM][SPFC_MAX_LINK_REASON_CNT]; -u64 hba_stat[SPFC_MAX_PORT_NUM][SPFC_HBA_STAT_BUTT]; -atomic64_t com_up_event_err_stat[SPFC_MAX_PORT_NUM][SPFC_MAX_PORT_TASK_TYPE_STAT_NUM]; - -#ifndef MAX_SIZE -#define MAX_SIZE (16) -#endif - -struct spfc_lld_lock g_lld_lock; - -/* g_device_mutex */ -struct mutex g_device_mutex; - -/* pci device initialize lock */ -struct mutex g_pci_init_mutex; - -#define WAIT_LLD_DEV_HOLD_TIMEOUT (10 * 60 * 1000) /* 10minutes */ -#define WAIT_LLD_DEV_NODE_CHANGED (10 * 60 * 1000) /* 10minutes */ -#define WAIT_LLD_DEV_REF_CNT_EMPTY (2 * 60 * 1000) /* 2minutes */ - -void lld_dev_cnt_init(struct spfc_pcidev *pci_adapter) -{ - atomic_set(&pci_adapter->ref_cnt, 0); -} - -void lld_dev_hold(struct spfc_lld_dev *dev) -{ - struct spfc_pcidev *pci_adapter = pci_get_drvdata(dev->pdev); - - atomic_inc(&pci_adapter->ref_cnt); -} - -void lld_dev_put(struct spfc_lld_dev *dev) -{ - struct spfc_pcidev *pci_adapter = pci_get_drvdata(dev->pdev); - - atomic_dec(&pci_adapter->ref_cnt); -} - -static void spfc_sync_time_to_fmw(struct spfc_pcidev *pdev_pri) -{ - struct tm tm = {0}; - u64 tv_msec; - int err; - - tv_msec = ktime_to_ms(ktime_get_real()); - err = sphw_sync_time(pdev_pri->hwdev, tv_msec); - if (err) { - sdk_err(&pdev_pri->pcidev->dev, "Synchronize UTC time to firmware failed, errno:%d.\n", - err); - } else { - time64_to_tm(tv_msec / MSEC_PER_SEC, 0, &tm); - sdk_info(&pdev_pri->pcidev->dev, "Synchronize UTC time to firmware succeed. UTC time %ld-%02d-%02d %02d:%02d:%02d.\n", - tm.tm_year + 1900, tm.tm_mon + 1, - tm.tm_mday, tm.tm_hour, - tm.tm_min, tm.tm_sec); - } -} - -void wait_lld_dev_unused(struct spfc_pcidev *pci_adapter) -{ - u32 loop_cnt = 0; - - while (loop_cnt < SPFC_WAIT_TOOL_CNT_TIMEOUT) { - if (!atomic_read(&pci_adapter->ref_cnt)) - return; - - usleep_range(SPFC_TOOL_MIN_TIME_IN_USECS, SPFC_TOOL_MAX_TIME_IN_USECS); - loop_cnt++; - } -} - -static void lld_lock_chip_node(void) -{ - u32 loop_cnt; - - mutex_lock(&g_lld_lock.lld_mutex); - - loop_cnt = 0; - while (loop_cnt < WAIT_LLD_DEV_NODE_CHANGED) { - if (!test_and_set_bit(SPFC_NODE_CHANGE, &g_lld_lock.status)) - break; - - loop_cnt++; - - if (loop_cnt % SPFC_MAX_LOOP_TIMES == 0) - pr_warn("[warn]Wait for lld node change complete for %us", - loop_cnt / UNF_S_TO_MS); - - usleep_range(SPFC_MIN_TIME_IN_USECS, SPFC_MAX_TIME_IN_USECS); - } - - if (loop_cnt == WAIT_LLD_DEV_NODE_CHANGED) - pr_warn("[warn]Wait for lld node change complete timeout when try to get lld lock"); - - loop_cnt = 0; - while (loop_cnt < WAIT_LLD_DEV_REF_CNT_EMPTY) { - if (!atomic_read(&g_lld_lock.dev_ref_cnt)) - break; - - loop_cnt++; - - if (loop_cnt % SPFC_MAX_LOOP_TIMES == 0) - pr_warn("[warn]Wait for lld dev unused for %us, reference count: %d", - loop_cnt / UNF_S_TO_MS, atomic_read(&g_lld_lock.dev_ref_cnt)); - - usleep_range(SPFC_MIN_TIME_IN_USECS, SPFC_MAX_TIME_IN_USECS); - } - - if (loop_cnt == WAIT_LLD_DEV_REF_CNT_EMPTY) - pr_warn("[warn]Wait for lld dev unused timeout"); - - mutex_unlock(&g_lld_lock.lld_mutex); -} - -static void lld_unlock_chip_node(void) -{ - clear_bit(SPFC_NODE_CHANGE, &g_lld_lock.status); -} - -void lld_hold(void) -{ - u32 loop_cnt = 0; - - /* ensure there have not any chip node in changing */ - mutex_lock(&g_lld_lock.lld_mutex); - - while (loop_cnt < WAIT_LLD_DEV_HOLD_TIMEOUT) { - if (!test_bit(SPFC_NODE_CHANGE, &g_lld_lock.status)) - break; - - loop_cnt++; - - if (loop_cnt % SPFC_MAX_LOOP_TIMES == 0) - pr_warn("[warn]Wait lld node change complete for %u", - loop_cnt / UNF_S_TO_MS); - - usleep_range(SPFC_MIN_TIME_IN_USECS, SPFC_MAX_TIME_IN_USECS); - } - - if (loop_cnt == WAIT_LLD_DEV_HOLD_TIMEOUT) - pr_warn("[warn]Wait lld node change complete timeout when try to hode lld dev %u", - loop_cnt / UNF_S_TO_MS); - - atomic_inc(&g_lld_lock.dev_ref_cnt); - - mutex_unlock(&g_lld_lock.lld_mutex); -} - -void lld_put(void) -{ - atomic_dec(&g_lld_lock.dev_ref_cnt); -} - -static void spfc_lld_lock_init(void) -{ - mutex_init(&g_lld_lock.lld_mutex); - atomic_set(&g_lld_lock.dev_ref_cnt, 0); -} - -static void spfc_realease_cmo_op_handle(void) -{ - memset(&spfc_cm_op_handle, 0, sizeof(struct unf_cm_handle_op)); -} - -static void spfc_check_module_para(void) -{ - if (spfc_dif_enable) { - dif_sgl_mode = true; - spfc_dif_type = SHOST_DIF_TYPE1_PROTECTION | SHOST_DIX_TYPE1_PROTECTION; - dix_flag = 1; - } - - if (dif_sgl_mode != 0) - dif_sgl_mode = 1; -} - -void spfc_event_process(void *adapter, struct sphw_event_info *event) -{ - struct spfc_pcidev *dev = adapter; - - if (test_and_set_bit(SERVICE_T_FC, &dev->state)) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[WARN]Event: fc is in detach"); - return; - } - - if (g_uld_info[SERVICE_T_FC].event) - g_uld_info[SERVICE_T_FC].event(&dev->lld_dev, dev->uld_dev[SERVICE_T_FC], event); - - clear_bit(SERVICE_T_FC, &dev->state); -} - -int spfc_stateful_init(void *hwdev) -{ - struct sphw_hwdev *dev = hwdev; - int stateful_en; - int err; - - if (!dev) - return -EINVAL; - - if (dev->statufull_ref_cnt++) - return 0; - - stateful_en = IS_FT_TYPE(dev) | IS_RDMA_TYPE(dev); - if (stateful_en && SPHW_IS_PPF(dev)) { - err = sphw_ppf_ext_db_init(dev); - if (err) - goto out; - } - - err = cqm3_init(dev); - if (err) { - sdk_err(dev->dev_hdl, "Failed to init cqm, err: %d\n", err); - goto init_cqm_err; - } - - sdk_info(dev->dev_hdl, "Initialize statefull resource success\n"); - - return 0; - -init_cqm_err: - if (stateful_en) - sphw_ppf_ext_db_deinit(dev); - -out: - dev->statufull_ref_cnt--; - - return err; -} - -void spfc_stateful_deinit(void *hwdev) -{ - struct sphw_hwdev *dev = hwdev; - u32 stateful_en; - - if (!dev || !dev->statufull_ref_cnt) - return; - - if (--dev->statufull_ref_cnt) - return; - - cqm3_uninit(hwdev); - - stateful_en = IS_FT_TYPE(dev) | IS_RDMA_TYPE(dev); - if (stateful_en) - sphw_ppf_ext_db_deinit(hwdev); - - sdk_info(dev->dev_hdl, "Clear statefull resource success\n"); -} - -static int attach_uld(struct spfc_pcidev *dev, struct spfc_uld_info *uld_info) -{ - void *uld_dev = NULL; - int err; - - mutex_lock(&dev->pdev_mutex); - if (dev->uld_dev[SERVICE_T_FC]) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]fc driver has attached to pcie device"); - err = 0; - goto out_unlock; - } - - err = spfc_stateful_init(dev->hwdev); - if (err) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Failed to initialize statefull resources"); - goto out_unlock; - } - - err = uld_info->probe(&dev->lld_dev, &uld_dev, - dev->uld_dev_name[SERVICE_T_FC]); - if (err || !uld_dev) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Failed to add object for fc driver to pcie device"); - goto probe_failed; - } - - dev->uld_dev[SERVICE_T_FC] = uld_dev; - mutex_unlock(&dev->pdev_mutex); - - return RETURN_OK; - -probe_failed: - spfc_stateful_deinit(dev->hwdev); - -out_unlock: - mutex_unlock(&dev->pdev_mutex); - - return err; -} - -static void detach_uld(struct spfc_pcidev *dev) -{ - struct spfc_uld_info *uld_info = &g_uld_info[SERVICE_T_FC]; - u32 cnt = 0; - - mutex_lock(&dev->pdev_mutex); - if (!dev->uld_dev[SERVICE_T_FC]) { - mutex_unlock(&dev->pdev_mutex); - return; - } - - while (cnt < SPFC_EVENT_PROCESS_TIMEOUT) { - if (!test_and_set_bit(SERVICE_T_FC, &dev->state)) - break; - usleep_range(900, 1000); - cnt++; - } - - uld_info->remove(&dev->lld_dev, dev->uld_dev[SERVICE_T_FC]); - dev->uld_dev[SERVICE_T_FC] = NULL; - spfc_stateful_deinit(dev->hwdev); - if (cnt < SPFC_EVENT_PROCESS_TIMEOUT) - clear_bit(SERVICE_T_FC, &dev->state); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_KEVENT, - "Detach fc driver from pcie device succeed"); - mutex_unlock(&dev->pdev_mutex); -} - -int spfc_register_uld(struct spfc_uld_info *uld_info) -{ - memset(g_uld_info, 0, sizeof(g_uld_info)); - spfc_lld_lock_init(); - mutex_init(&g_device_mutex); - mutex_init(&g_pci_init_mutex); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_KEVENT, - "[event]Module Init Success, wait for pci init and probe"); - - if (!uld_info || !uld_info->probe || !uld_info->remove) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Invalid information of fc driver to register"); - return -EINVAL; - } - - lld_hold(); - - if (g_uld_info[SERVICE_T_FC].probe) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]fc driver has registered"); - lld_put(); - return -EINVAL; - } - - memcpy(&g_uld_info[SERVICE_T_FC], uld_info, sizeof(*uld_info)); - - lld_put(); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_KEVENT, - "[KEVENT]Register spfc driver succeed"); - return RETURN_OK; -} - -void spfc_unregister_uld(void) -{ - struct spfc_uld_info *uld_info = NULL; - - lld_hold(); - uld_info = &g_uld_info[SERVICE_T_FC]; - memset(uld_info, 0, sizeof(*uld_info)); - lld_put(); -} - -static int spfc_pci_init(struct pci_dev *pdev) -{ - struct spfc_pcidev *pci_adapter = NULL; - int err = 0; - - pci_adapter = kzalloc(sizeof(*pci_adapter), GFP_KERNEL); - if (!pci_adapter) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Failed to alloc pci device adapter"); - return -ENOMEM; - } - pci_adapter->pcidev = pdev; - mutex_init(&pci_adapter->pdev_mutex); - - pci_set_drvdata(pdev, pci_adapter); - - err = pci_enable_device(pdev); - if (err) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Failed to enable PCI device"); - goto pci_enable_err; - } - - err = pci_request_regions(pdev, SPFC_DRV_NAME); - if (err) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Failed to request regions"); - goto pci_regions_err; - } - - pci_enable_pcie_error_reporting(pdev); - - pci_set_master(pdev); - - err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); - if (err) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[warn]Couldn't set 64-bit DMA mask"); - err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); - if (err) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, - UNF_ERR, "[err]Failed to set DMA mask"); - goto dma_mask_err; - } - } - - err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); - if (err) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[warn]Couldn't set 64-bit coherent DMA mask"); - err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); - if (err) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, - UNF_ERR, - "[err]Failed to set coherent DMA mask"); - goto dma_consistnet_mask_err; - } - } - - return 0; - -dma_consistnet_mask_err: -dma_mask_err: - pci_clear_master(pdev); - pci_release_regions(pdev); - -pci_regions_err: - pci_disable_device(pdev); - -pci_enable_err: - pci_set_drvdata(pdev, NULL); - kfree(pci_adapter); - - return err; -} - -static void spfc_pci_deinit(struct pci_dev *pdev) -{ - struct spfc_pcidev *pci_adapter = pci_get_drvdata(pdev); - - pci_clear_master(pdev); - pci_release_regions(pdev); - pci_disable_pcie_error_reporting(pdev); - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); - kfree(pci_adapter); -} - -static int alloc_chip_node(struct spfc_pcidev *pci_adapter) -{ - struct card_node *chip_node = NULL; - unsigned char i; - unsigned char bus_number = 0; - - if (!pci_is_root_bus(pci_adapter->pcidev->bus)) - bus_number = pci_adapter->pcidev->bus->number; - - if (bus_number != 0) { - list_for_each_entry(chip_node, &g_spfc_chip_list, node) { - if (chip_node->bus_num == bus_number) { - pci_adapter->chip_node = chip_node; - return 0; - } - } - } else if (pci_adapter->pcidev->device == SPFC_DEV_ID_VF) { - list_for_each_entry(chip_node, &g_spfc_chip_list, node) { - if (chip_node) { - pci_adapter->chip_node = chip_node; - return 0; - } - } - } - - for (i = 0; i < MAX_CARD_ID; i++) { - if (!test_and_set_bit(i, &card_bit_map)) - break; - } - - if (i == MAX_CARD_ID) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Failed to alloc card id"); - return -EFAULT; - } - - chip_node = kzalloc(sizeof(*chip_node), GFP_KERNEL); - if (!chip_node) { - clear_bit(i, &card_bit_map); - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Failed to alloc chip node"); - return -ENOMEM; - } - - /* bus number */ - chip_node->bus_num = bus_number; - - snprintf(chip_node->chip_name, IFNAMSIZ, "%s%d", SPFC_CHIP_NAME, i); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_INFO, - "[INFO]Add new chip %s to global list succeed", - chip_node->chip_name); - - list_add_tail(&chip_node->node, &g_spfc_chip_list); - - INIT_LIST_HEAD(&chip_node->func_list); - pci_adapter->chip_node = chip_node; - - return 0; -} - -#ifdef CONFIG_X86 -void cfg_order_reg(struct spfc_pcidev *pci_adapter) -{ - u8 cpu_model[] = {0x3c, 0x3f, 0x45, 0x46, 0x3d, 0x47, 0x4f, 0x56}; - struct cpuinfo_x86 *cpuinfo = NULL; - u32 i; - - if (sphw_func_type(pci_adapter->hwdev) == TYPE_VF) - return; - - cpuinfo = &cpu_data(0); - - for (i = 0; i < sizeof(cpu_model); i++) { - if (cpu_model[i] == cpuinfo->x86_model) - sphw_set_pcie_order_cfg(pci_adapter->hwdev); - } -} -#endif - -static int mapping_bar(struct pci_dev *pdev, struct spfc_pcidev *pci_adapter) -{ - int cfg_bar; - - cfg_bar = pdev->is_virtfn ? SPFC_VF_PCI_CFG_REG_BAR : SPFC_PF_PCI_CFG_REG_BAR; - - pci_adapter->cfg_reg_base = pci_ioremap_bar(pdev, cfg_bar); - if (!pci_adapter->cfg_reg_base) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "Failed to map configuration regs"); - return -ENOMEM; - } - - pci_adapter->intr_reg_base = pci_ioremap_bar(pdev, SPFC_PCI_INTR_REG_BAR); - if (!pci_adapter->intr_reg_base) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "Failed to map interrupt regs"); - goto map_intr_bar_err; - } - - if (!pdev->is_virtfn) { - pci_adapter->mgmt_reg_base = pci_ioremap_bar(pdev, SPFC_PCI_MGMT_REG_BAR); - if (!pci_adapter->mgmt_reg_base) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, - UNF_ERR, "Failed to map mgmt regs"); - goto map_mgmt_bar_err; - } - } - - pci_adapter->db_base_phy = pci_resource_start(pdev, SPFC_PCI_DB_BAR); - pci_adapter->db_dwqe_len = pci_resource_len(pdev, SPFC_PCI_DB_BAR); - pci_adapter->db_base = pci_ioremap_bar(pdev, SPFC_PCI_DB_BAR); - if (!pci_adapter->db_base) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "Failed to map doorbell regs"); - goto map_db_err; - } - - return 0; - -map_db_err: - if (!pdev->is_virtfn) - iounmap(pci_adapter->mgmt_reg_base); - -map_mgmt_bar_err: - iounmap(pci_adapter->intr_reg_base); - -map_intr_bar_err: - iounmap(pci_adapter->cfg_reg_base); - - return -ENOMEM; -} - -static void unmapping_bar(struct spfc_pcidev *pci_adapter) -{ - iounmap(pci_adapter->db_base); - - if (!pci_adapter->pcidev->is_virtfn) - iounmap(pci_adapter->mgmt_reg_base); - - iounmap(pci_adapter->intr_reg_base); - iounmap(pci_adapter->cfg_reg_base); -} - -static int spfc_func_init(struct pci_dev *pdev, struct spfc_pcidev *pci_adapter) -{ - struct sphw_init_para init_para = {0}; - int err; - - init_para.adapter_hdl = pci_adapter; - init_para.pcidev_hdl = pdev; - init_para.dev_hdl = &pdev->dev; - init_para.cfg_reg_base = pci_adapter->cfg_reg_base; - init_para.intr_reg_base = pci_adapter->intr_reg_base; - init_para.mgmt_reg_base = pci_adapter->mgmt_reg_base; - init_para.db_base = pci_adapter->db_base; - init_para.db_base_phy = pci_adapter->db_base_phy; - init_para.db_dwqe_len = pci_adapter->db_dwqe_len; - init_para.hwdev = &pci_adapter->hwdev; - init_para.chip_node = pci_adapter->chip_node; - err = sphw_init_hwdev(&init_para); - if (err) { - pci_adapter->hwdev = NULL; - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Failed to initialize hardware device"); - return -EFAULT; - } - - pci_adapter->lld_dev.pdev = pdev; - pci_adapter->lld_dev.hwdev = pci_adapter->hwdev; - - sphw_event_register(pci_adapter->hwdev, pci_adapter, spfc_event_process); - - if (sphw_func_type(pci_adapter->hwdev) != TYPE_VF) - spfc_sync_time_to_fmw(pci_adapter); - lld_lock_chip_node(); - list_add_tail(&pci_adapter->node, &pci_adapter->chip_node->func_list); - lld_unlock_chip_node(); - err = attach_uld(pci_adapter, &g_uld_info[SERVICE_T_FC]); - - if (err) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Spfc3 attach uld fail"); - goto attach_fc_err; - } - -#ifdef CONFIG_X86 - cfg_order_reg(pci_adapter); -#endif - - return 0; - -attach_fc_err: - lld_lock_chip_node(); - list_del(&pci_adapter->node); - lld_unlock_chip_node(); - wait_lld_dev_unused(pci_adapter); - - return err; -} - -static void spfc_func_deinit(struct pci_dev *pdev) -{ - struct spfc_pcidev *pci_adapter = pci_get_drvdata(pdev); - - lld_lock_chip_node(); - list_del(&pci_adapter->node); - lld_unlock_chip_node(); - wait_lld_dev_unused(pci_adapter); - - detach_uld(pci_adapter); - sphw_disable_mgmt_msg_report(pci_adapter->hwdev); - sphw_flush_mgmt_workq(pci_adapter->hwdev); - sphw_event_unregister(pci_adapter->hwdev); - sphw_free_hwdev(pci_adapter->hwdev); -} - -static void free_chip_node(struct spfc_pcidev *pci_adapter) -{ - struct card_node *chip_node = pci_adapter->chip_node; - int id, err; - - if (list_empty(&chip_node->func_list)) { - list_del(&chip_node->node); - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_INFO, - "[INFO]Delete chip %s from global list succeed", - chip_node->chip_name); - err = sscanf(chip_node->chip_name, SPFC_CHIP_NAME "%d", &id); - if (err < 0) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, - UNF_ERR, "[err]Failed to get spfc id"); - } - - clear_bit(id, &card_bit_map); - - kfree(chip_node); - } -} - -static int spfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) -{ - struct spfc_pcidev *pci_adapter = NULL; - int err; - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_KEVENT, - "[event]Spfc3 Pcie device probe begin"); - - mutex_lock(&g_pci_init_mutex); - err = spfc_pci_init(pdev); - if (err) { - mutex_unlock(&g_pci_init_mutex); - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]pci init fail, return %d", err); - return err; - } - pci_adapter = pci_get_drvdata(pdev); - err = mapping_bar(pdev, pci_adapter); - if (err) { - mutex_unlock(&g_pci_init_mutex); - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Failed to map bar"); - goto map_bar_failed; - } - mutex_unlock(&g_pci_init_mutex); - pci_adapter->id = *id; - lld_dev_cnt_init(pci_adapter); - - /* if chip information of pcie function exist, add the function into chip */ - lld_lock_chip_node(); - err = alloc_chip_node(pci_adapter); - if (err) { - lld_unlock_chip_node(); - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Failed to add new chip node to global list"); - goto alloc_chip_node_fail; - } - - lld_unlock_chip_node(); - err = spfc_func_init(pdev, pci_adapter); - if (err) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]spfc func init fail"); - goto func_init_err; - } - - return 0; - -func_init_err: - lld_lock_chip_node(); - free_chip_node(pci_adapter); - lld_unlock_chip_node(); - -alloc_chip_node_fail: - unmapping_bar(pci_adapter); - -map_bar_failed: - spfc_pci_deinit(pdev); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Pcie device probe failed"); - return err; -} - -static void spfc_remove(struct pci_dev *pdev) -{ - struct spfc_pcidev *pci_adapter = pci_get_drvdata(pdev); - - if (!pci_adapter) - return; - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_INFO, - "[INFO]Pcie device remove begin"); - sphw_detect_hw_present(pci_adapter->hwdev); - spfc_func_deinit(pdev); - lld_lock_chip_node(); - free_chip_node(pci_adapter); - lld_unlock_chip_node(); - unmapping_bar(pci_adapter); - mutex_lock(&g_pci_init_mutex); - spfc_pci_deinit(pdev); - mutex_unlock(&g_pci_init_mutex); - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_INFO, - "[INFO]Pcie device removed"); -} - -static void spfc_shutdown(struct pci_dev *pdev) -{ - struct spfc_pcidev *pci_adapter = pci_get_drvdata(pdev); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Shutdown device"); - - if (pci_adapter) - sphw_shutdown_hwdev(pci_adapter->hwdev); - - pci_disable_device(pdev); -} - -static pci_ers_result_t spfc_io_error_detected(struct pci_dev *pdev, - pci_channel_state_t state) -{ - struct spfc_pcidev *pci_adapter = NULL; - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Uncorrectable error detected, log and cleanup error status: 0x%08x", - state); - - pci_aer_clear_nonfatal_status(pdev); - pci_adapter = pci_get_drvdata(pdev); - - if (pci_adapter) - sphw_record_pcie_error(pci_adapter->hwdev); - - return PCI_ERS_RESULT_CAN_RECOVER; -} - -static int unf_global_value_init(void) -{ - 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(&spfc_cm_op_handle, 0, sizeof(struct unf_cm_handle_op)); - memset(up_err_event_stat, 0, sizeof(up_err_event_stat)); - memset(mail_box_stat, 0, sizeof(mail_box_stat)); - memset(spfc_hba, 0, sizeof(spfc_hba)); - - spin_lock_init(&probe_spin_lock); - - /* 4. Get COM Handlers used for low_level */ - if (unf_get_cm_handle_ops(&spfc_cm_op_handle) != RETURN_OK) { - spfc_realease_cmo_op_handle(); - return RETURN_ERROR_S32; - } - - return RETURN_OK; -} - -static const struct pci_device_id spfc_pci_table[] = { - {PCI_VDEVICE(RAMAXEL, SPFC_DEV_ID_PF_STD), 0}, - {0, 0} -}; - -MODULE_DEVICE_TABLE(pci, spfc_pci_table); - -static struct pci_error_handlers spfc_err_handler = { - .error_detected = spfc_io_error_detected, -}; - -static struct pci_driver spfc_driver = {.name = SPFC_DRV_NAME, - .id_table = spfc_pci_table, - .probe = spfc_probe, - .remove = spfc_remove, - .shutdown = spfc_shutdown, - .err_handler = &spfc_err_handler}; - -static __init int spfc_lld_init(void) -{ - if (unf_common_init() != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]UNF_Common_init failed"); - return RETURN_ERROR_S32; - } - - spfc_check_module_para(); - - if (unf_global_value_init() != RETURN_OK) - return RETURN_ERROR_S32; - - spfc_register_uld(&fc_uld_info); - return pci_register_driver(&spfc_driver); -} - -static __exit void spfc_lld_exit(void) -{ - pci_unregister_driver(&spfc_driver); - spfc_unregister_uld(); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[event]SPFC module removing..."); - - spfc_realease_cmo_op_handle(); - - /* 2. Unregister FC COM module(level) */ - unf_common_exit(); -} - -module_init(spfc_lld_init); -module_exit(spfc_lld_exit); - -MODULE_AUTHOR("Ramaxel Memory Technology, Ltd"); -MODULE_DESCRIPTION(SPFC_DRV_DESC); -MODULE_VERSION(SPFC_DRV_VERSION); -MODULE_LICENSE("GPL"); - -module_param(allowed_probe_num, uint, 0444); -module_param(dif_sgl_mode, uint, 0444); -module_param(max_speed, uint, 0444); -module_param(wqe_page_size, uint, 0444); -module_param(combo_length, uint, 0444); -module_param(cos_bit_map, uint, 0444); -module_param(spfc_dif_enable, uint, 0444); -MODULE_PARM_DESC(spfc_dif_enable, "set dif enable/disable(1/0), default is 0(disable)."); -module_param(link_lose_tmo, uint, 0444); -MODULE_PARM_DESC(link_lose_tmo, "set link time out, default is 30s."); diff --git a/drivers/scsi/spfc/hw/spfc_lld.h b/drivers/scsi/spfc/hw/spfc_lld.h deleted file mode 100644 index f7b4a5e5ce07..000000000000 --- a/drivers/scsi/spfc/hw/spfc_lld.h +++ /dev/null @@ -1,76 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPFC_LLD_H -#define SPFC_LLD_H - -#include "sphw_crm.h" - -struct spfc_lld_dev { - struct pci_dev *pdev; - void *hwdev; -}; - -struct spfc_uld_info { - /* uld_dev: should not return null even the function capability - * is not support the up layer driver - * uld_dev_name: NIC driver should copy net device name. - * FC driver could copy fc device name. - * other up layer driver don`t need copy anything - */ - int (*probe)(struct spfc_lld_dev *lld_dev, void **uld_dev, - char *uld_dev_name); - void (*remove)(struct spfc_lld_dev *lld_dev, void *uld_dev); - int (*suspend)(struct spfc_lld_dev *lld_dev, void *uld_dev, - pm_message_t state); - int (*resume)(struct spfc_lld_dev *lld_dev, void *uld_dev); - void (*event)(struct spfc_lld_dev *lld_dev, void *uld_dev, - struct sphw_event_info *event); - int (*ioctl)(void *uld_dev, u32 cmd, const void *buf_in, u32 in_size, - void *buf_out, u32 *out_size); -}; - -/* Structure pcidev private */ -struct spfc_pcidev { - struct pci_dev *pcidev; - void *hwdev; - struct card_node *chip_node; - struct spfc_lld_dev lld_dev; - /* such as fc_dev */ - void *uld_dev[SERVICE_T_MAX]; - /* Record the service object name */ - char uld_dev_name[SERVICE_T_MAX][IFNAMSIZ]; - /* It is a the global variable for driver to manage - * all function device linked list - */ - struct list_head node; - void __iomem *cfg_reg_base; - void __iomem *intr_reg_base; - void __iomem *mgmt_reg_base; - u64 db_dwqe_len; - u64 db_base_phy; - void __iomem *db_base; - /* lock for attach/detach uld */ - struct mutex pdev_mutex; - /* setted when uld driver processing event */ - unsigned long state; - struct pci_device_id id; - atomic_t ref_cnt; -}; - -enum spfc_lld_status { - SPFC_NODE_CHANGE = BIT(0), -}; - -struct spfc_lld_lock { - /* lock for chip list */ - struct mutex lld_mutex; - unsigned long status; - atomic_t dev_ref_cnt; -}; - -#ifndef MAX_SIZE -#define MAX_SIZE (16) -#endif - -#endif diff --git a/drivers/scsi/spfc/hw/spfc_module.h b/drivers/scsi/spfc/hw/spfc_module.h deleted file mode 100644 index 153d59955339..000000000000 --- a/drivers/scsi/spfc/hw/spfc_module.h +++ /dev/null @@ -1,297 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPFC_MODULE_H -#define SPFC_MODULE_H -#include "unf_type.h" -#include "unf_log.h" -#include "unf_common.h" -#include "spfc_utils.h" -#include "spfc_hba.h" - -#define SPFC_FT_ENABLE (1) -#define SPFC_FC_DISABLE (0) - -#define SPFC_P2P_DIRECT (0) -#define SPFC_P2P_FABRIC (1) -#define SPFC_LOOP (2) -#define SPFC_ATUOSPEED (1) -#define SPFC_FIXEDSPEED (0) -#define SPFC_AUTOTOPO (0) -#define SPFC_P2PTOPO (0x2) -#define SPFC_LOOPTOPO (0x1) -#define SPFC_SPEED_2G (0x2) -#define SPFC_SPEED_4G (0x4) -#define SPFC_SPEED_8G (0x8) -#define SPFC_SPEED_16G (0x10) -#define SPFC_SPEED_32G (0x20) - -#define SPFC_MAX_PORT_NUM SPFC_MAX_PROBE_PORT_NUM -#define SPFC_MAX_PORT_TASK_TYPE_STAT_NUM (128) -#define SPFC_MAX_LINK_EVENT_CNT (4) -#define SPFC_MAX_LINK_REASON_CNT (256) - -#define SPFC_MML_LOGCTRO_NUM (14) - -#define WWN_SIZE 8 /* Size of WWPN, WWN & WWNN */ - -/* - * Define the data type - */ -struct spfc_log_ctrl { - char *log_option; - u32 state; -}; - -/* - * Declare the global function. - */ -extern struct unf_cm_handle_op spfc_cm_op_handle; -extern struct spfc_uld_info fc_uld_info; -extern u32 allowed_probe_num; -extern u32 max_speed; -extern u32 accum_db_num; -extern u32 wqe_page_size; -extern u32 dif_type; -extern u32 wqe_pre_load; -extern u32 combo_length; -extern u32 cos_bit_map; -extern u32 exit_count; -extern u32 exit_stride; -extern u32 exit_base; - -extern atomic64_t rx_tx_stat[SPFC_MAX_PORT_NUM][SPFC_MAX_PORT_TASK_TYPE_STAT_NUM]; -extern atomic64_t rx_tx_err[SPFC_MAX_PORT_NUM][SPFC_MAX_PORT_TASK_TYPE_STAT_NUM]; -extern atomic64_t scq_err_stat[SPFC_MAX_PORT_NUM][SPFC_MAX_PORT_TASK_TYPE_STAT_NUM]; -extern atomic64_t aeq_err_stat[SPFC_MAX_PORT_NUM][SPFC_MAX_PORT_TASK_TYPE_STAT_NUM]; -extern atomic64_t dif_err_stat[SPFC_MAX_PORT_NUM][SPFC_MAX_PORT_TASK_TYPE_STAT_NUM]; -extern atomic64_t mail_box_stat[SPFC_MAX_PORT_NUM][SPFC_MAX_PORT_TASK_TYPE_STAT_NUM]; -extern atomic64_t com_up_event_err_stat[SPFC_MAX_PORT_NUM][SPFC_MAX_PORT_TASK_TYPE_STAT_NUM]; -extern u64 link_event_stat[SPFC_MAX_PORT_NUM][SPFC_MAX_LINK_EVENT_CNT]; -extern u64 link_reason_stat[SPFC_MAX_PORT_NUM][SPFC_MAX_LINK_REASON_CNT]; -extern atomic64_t up_err_event_stat[SPFC_MAX_PORT_NUM][SPFC_MAX_PORT_TASK_TYPE_STAT_NUM]; -extern u64 hba_stat[SPFC_MAX_PORT_NUM][SPFC_HBA_STAT_BUTT]; -#define SPFC_LINK_EVENT_STAT(hba, link_ent) \ - (link_event_stat[(hba)->probe_index][link_ent]++) -#define SPFC_LINK_REASON_STAT(hba, link_rsn) \ - (link_reason_stat[(hba)->probe_index][link_rsn]++) -#define SPFC_HBA_STAT(hba, hba_stat_type) \ - (hba_stat[(hba)->probe_index][hba_stat_type]++) - -#define SPFC_UP_ERR_EVENT_STAT(hba, err_type) \ - (atomic64_inc(&up_err_event_stat[(hba)->probe_index][err_type])) -#define SPFC_UP_ERR_EVENT_STAT_READ(probe_index, io_type) \ - (atomic64_read(&up_err_event_stat[probe_index][io_type])) -#define SPFC_DIF_ERR_STAT(hba, dif_err) \ - (atomic64_inc(&dif_err_stat[(hba)->probe_index][dif_err])) -#define SPFC_DIF_ERR_STAT_READ(probe_index, dif_err) \ - (atomic64_read(&dif_err_stat[probe_index][dif_err])) - -#define SPFC_IO_STAT(hba, io_type) \ - (atomic64_inc(&rx_tx_stat[(hba)->probe_index][io_type])) -#define SPFC_IO_STAT_READ(probe_index, io_type) \ - (atomic64_read(&rx_tx_stat[probe_index][io_type])) - -#define SPFC_ERR_IO_STAT(hba, io_type) \ - (atomic64_inc(&rx_tx_err[(hba)->probe_index][io_type])) -#define SPFC_ERR_IO_STAT_READ(probe_index, io_type) \ - (atomic64_read(&rx_tx_err[probe_index][io_type])) - -#define SPFC_SCQ_ERR_TYPE_STAT(hba, err_type) \ - (atomic64_inc(&scq_err_stat[(hba)->probe_index][err_type])) -#define SPFC_SCQ_ERR_TYPE_STAT_READ(probe_index, io_type) \ - (atomic64_read(&scq_err_stat[probe_index][io_type])) -#define SPFC_AEQ_ERR_TYPE_STAT(hba, err_type) \ - (atomic64_inc(&aeq_err_stat[(hba)->probe_index][err_type])) -#define SPFC_AEQ_ERR_TYPE_STAT_READ(probe_index, io_type) \ - (atomic64_read(&aeq_err_stat[probe_index][io_type])) - -#define SPFC_MAILBOX_STAT(hba, io_type) \ - (atomic64_inc(&mail_box_stat[(hba)->probe_index][io_type])) -#define SPFC_MAILBOX_STAT_READ(probe_index, io_type) \ - (atomic64_read(&mail_box_stat[probe_index][io_type])) - -#define SPFC_COM_UP_ERR_EVENT_STAT(hba, err_type) \ - (atomic64_inc( \ - &com_up_event_err_stat[(hba)->probe_index][err_type])) -#define SPFC_COM_UP_ERR_EVENT_STAT_READ(probe_index, err_type) \ - (atomic64_read(&com_up_event_err_stat[probe_index][err_type])) - -#define UNF_LOWLEVEL_ALLOC_LPORT(lport, fc_port, low_level) \ - do { \ - if (spfc_cm_op_handle.unf_alloc_local_port) { \ - lport = spfc_cm_op_handle.unf_alloc_local_port( \ - (fc_port), (low_level)); \ - } else { \ - lport = NULL; \ - } \ - } while (0) - -#define UNF_LOWLEVEL_RECEIVE_LS_GS_PKG(ret, fc_port, pkg) \ - do { \ - if (spfc_cm_op_handle.unf_receive_ls_gs_pkg) { \ - ret = spfc_cm_op_handle.unf_receive_ls_gs_pkg( \ - (fc_port), (pkg)); \ - } else { \ - ret = UNF_RETURN_ERROR; \ - } \ - } while (0) - -#define UNF_LOWLEVEL_SEND_ELS_DONE(ret, fc_port, pkg) \ - do { \ - if (spfc_cm_op_handle.unf_send_els_done) { \ - ret = spfc_cm_op_handle.unf_send_els_done((fc_port), \ - (pkg)); \ - } else { \ - ret = UNF_RETURN_ERROR; \ - } \ - } while (0) - -#define UNF_LOWLEVEL_GET_CFG_PARMS(ret, section_name, cfg_parm, cfg_value, \ - item_num) \ - do { \ - if (spfc_cm_op_handle.unf_get_cfg_parms) { \ - ret = (u32)spfc_cm_op_handle.unf_get_cfg_parms( \ - (section_name), (cfg_parm), (cfg_value), \ - (item_num)); \ - } else { \ - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, \ - "Get config parameter function is NULL."); \ - ret = UNF_RETURN_ERROR; \ - } \ - } while (0) - -#define UNF_LOWLEVEL_RELEASE_LOCAL_PORT(ret, lport) \ - do { \ - if (unlikely(!spfc_cm_op_handle.unf_release_local_port)) { \ - ret = UNF_RETURN_ERROR; \ - } else { \ - ret = \ - spfc_cm_op_handle.unf_release_local_port(lport); \ - } \ - } while (0) - -#define UNF_CM_GET_SGL_ENTRY(ret, pkg, buf, buf_len) \ - do { \ - if (unlikely(!spfc_cm_op_handle.unf_cm_get_sgl_entry)) { \ - ret = UNF_RETURN_ERROR; \ - } else { \ - ret = spfc_cm_op_handle.unf_cm_get_sgl_entry( \ - pkg, buf, buf_len); \ - } \ - } while (0) - -#define UNF_CM_GET_DIF_SGL_ENTRY(ret, pkg, buf, buf_len) \ - do { \ - if (unlikely(!spfc_cm_op_handle.unf_cm_get_dif_sgl_entry)) { \ - ret = UNF_RETURN_ERROR; \ - } else { \ - ret = spfc_cm_op_handle.unf_cm_get_dif_sgl_entry( \ - pkg, buf, buf_len); \ - } \ - } while (0) - -#define UNF_GET_SGL_ENTRY(ret, pkg, buf, buf_len, dif_flag) \ - do { \ - if (dif_flag) { \ - UNF_CM_GET_DIF_SGL_ENTRY(ret, pkg, buf, buf_len); \ - } else { \ - UNF_CM_GET_SGL_ENTRY(ret, pkg, buf, buf_len); \ - } \ - } while (0) - -#define UNF_GET_FREE_ESGL_PAGE(ret, lport, pkg) \ - do { \ - if (unlikely( \ - !spfc_cm_op_handle.unf_get_one_free_esgl_page)) { \ - ret = NULL; \ - } else { \ - ret = \ - spfc_cm_op_handle.unf_get_one_free_esgl_page( \ - lport, pkg); \ - } \ - } while (0) - -#define UNF_LOWLEVEL_FCP_CMND_RECEIVED(ret, lport, pkg) \ - do { \ - if (unlikely(!spfc_cm_op_handle.unf_process_fcp_cmnd)) { \ - ret = UNF_RETURN_ERROR; \ - } else { \ - ret = spfc_cm_op_handle.unf_process_fcp_cmnd(lport, \ - pkg); \ - } \ - } while (0) - -#define UNF_LOWLEVEL_SCSI_COMPLETED(ret, lport, pkg) \ - do { \ - if (unlikely(NULL == \ - spfc_cm_op_handle.unf_receive_ini_response)) { \ - ret = UNF_RETURN_ERROR; \ - } else { \ - ret = spfc_cm_op_handle.unf_receive_ini_response( \ - lport, pkg); \ - } \ - } while (0) - -#define UNF_LOWLEVEL_PORT_EVENT(ret, lport, event, input) \ - do { \ - if (unlikely(!spfc_cm_op_handle.unf_fc_port_event)) { \ - ret = UNF_RETURN_ERROR; \ - } else { \ - ret = spfc_cm_op_handle.unf_fc_port_event( \ - lport, event, input); \ - } \ - } while (0) - -#define UNF_LOWLEVEL_RECEIVE_FC4LS_PKG(ret, fc_port, pkg) \ - do { \ - if (spfc_cm_op_handle.unf_receive_fc4ls_pkg) { \ - ret = spfc_cm_op_handle.unf_receive_fc4ls_pkg( \ - (fc_port), (pkg)); \ - } else { \ - ret = UNF_RETURN_ERROR; \ - } \ - } while (0) - -#define UNF_LOWLEVEL_SEND_FC4LS_DONE(ret, lport, pkg) \ - do { \ - if (spfc_cm_op_handle.unf_send_fc4ls_done) { \ - ret = spfc_cm_op_handle.unf_send_fc4ls_done((lport), \ - (pkg)); \ - } else { \ - ret = UNF_RETURN_ERROR; \ - } \ - } while (0) - -#define UNF_LOWLEVEL_RECEIVE_BLS_PKG(ret, lport, pkg) \ - do { \ - if (spfc_cm_op_handle.unf_receive_bls_pkg) { \ - ret = spfc_cm_op_handle.unf_receive_bls_pkg((lport), \ - (pkg)); \ - } else { \ - ret = UNF_RETURN_ERROR; \ - } \ - } while (0) - -#define UNF_LOWLEVEL_RECEIVE_MARKER_STS(ret, lport, pkg) \ - do { \ - if (spfc_cm_op_handle.unf_receive_marker_status) { \ - ret = spfc_cm_op_handle.unf_receive_marker_status( \ - (lport), (pkg)); \ - } else { \ - ret = UNF_RETURN_ERROR; \ - } \ - } while (0) - -#define UNF_LOWLEVEL_RECEIVE_ABTS_MARKER_STS(ret, lport, pkg) \ - do { \ - if (spfc_cm_op_handle.unf_receive_abts_marker_status) { \ - ret = \ - spfc_cm_op_handle.unf_receive_abts_marker_status( \ - (lport), (pkg)); \ - } else { \ - ret = UNF_RETURN_ERROR; \ - } \ - } while (0) - -#endif diff --git a/drivers/scsi/spfc/hw/spfc_parent_context.h b/drivers/scsi/spfc/hw/spfc_parent_context.h deleted file mode 100644 index dc4baffe5c44..000000000000 --- a/drivers/scsi/spfc/hw/spfc_parent_context.h +++ /dev/null @@ -1,269 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPFC_PARENT_CONTEXT_H -#define SPFC_PARENT_CONTEXT_H - -enum fc_parent_status { - FC_PARENT_STATUS_INVALID = 0, - FC_PARENT_STATUS_NORMAL, - FC_PARENT_STATUS_CLOSING -}; - -#define SPFC_PARENT_CONTEXT_KEY_ALIGN_SIZE (48) - -#define SPFC_PARENT_CONTEXT_TIMER_SIZE (32) /* 24+2*N,N=timer count */ - -#define FC_CALC_CID(_xid) \ - (((((_xid) >> 5) & 0x1ff) << 11) | ((((_xid) >> 5) & 0x1ff) << 2) | \ - (((_xid) >> 3) & 0x3)) - -#define MAX_PKT_SIZE_PER_DISPATCH (fc_child_ctx_ex->per_xmit_data_size) - -/* immediate data DIF info definition in parent context */ -struct immi_dif_info { - union { - u32 value; - struct { - u32 app_tag_ctrl : 3; /* DIF/DIX APP TAG Control */ - u32 ref_tag_mode : 2; /* Bit 0: scenario of the reference tag verify mode */ - /* Bit 1: scenario of the reference tag insert/replace - * mode 0: fixed; 1: increasement; - */ - u32 ref_tag_ctrl : 3; /* The DIF/DIX Reference tag control */ - u32 grd_agm_ini_ctrl : 3; - u32 grd_agm_ctrl : 2; /* Bit 0: DIF/DIX guard verify algorithm control */ - /* Bit 1: DIF/DIX guard replace or insert algorithm control */ - u32 grd_ctrl : 3; /* The DIF/DIX Guard control */ - u32 dif_verify_type : 2; /* verify type */ - /* Check blocks whose reference tag contains 0xFFFF flag */ - u32 difx_ref_esc : 1; - /* Check blocks whose application tag contains 0xFFFF flag */ - u32 difx_app_esc : 1; - u32 rsvd : 8; - u32 sct_size : 1; /* Sector size, 1: 4K; 0: 512 */ - u32 smd_tp : 2; - u32 difx_en : 1; - } info; - } dif_dw3; - - u32 cmp_app_tag : 16; - u32 rep_app_tag : 16; - /* The ref tag value for verify compare, do not support replace or insert ref tag */ - u32 cmp_ref_tag; - u32 rep_ref_tag; - - u32 rsv1 : 16; - u32 cmp_app_tag_msk : 16; -}; - -/* parent context SW section definition: SW(80B) */ -struct spfc_sw_section { - u16 scq_num_rcv_cmd; - u16 scq_num_max_scqn; - - struct { - u32 xid : 13; - u32 vport : 7; - u32 csctrl : 8; - u32 rsvd0 : 4; - } sw_ctxt_vport_xid; - - u32 scq_num_scqn_mask : 12; - u32 cid : 20; /* ucode init */ - - u16 conn_id; - u16 immi_rq_page_size; - - u16 immi_taskid_min; - u16 immi_taskid_max; - - union { - u32 pctxt_val0; - struct { - u32 srv_type : 5; /* driver init */ - u32 srr_support : 2; /* sequence retransmition support flag */ - u32 rsvd1 : 5; - u32 port_id : 4; /* driver init */ - u32 vlan_id : 16; /* driver init */ - } dw; - } sw_ctxt_misc; - - u32 rsvd2; - u32 per_xmit_data_size; - - /* RW fields */ - u32 cmd_scq_gpa_h; - u32 cmd_scq_gpa_l; - u32 e_d_tov_timer_val; /* E_D_TOV timer value: value should be set on ms by driver */ - u16 mfs_unaligned_bytes; /* mfs unalined bytes of per 64KB dispatch*/ - u16 tx_mfs; /* remote port max receive fc payload length */ - u32 xfer_rdy_dis_max_len_remote; /* max data len allowed in xfer_rdy dis scenario */ - u32 xfer_rdy_dis_max_len_local; - - union { - struct { - u32 priority : 3; /* vlan priority */ - u32 rsvd4 : 2; - u32 status : 8; /* status of flow */ - u32 cos : 3; /* doorbell cos value */ - u32 oq_cos_data : 3; /* esch oq cos for data */ - u32 oq_cos_cmd : 3; /* esch oq cos for cmd/xferrdy/rsp */ - /* used for parent context cache Consistency judgment,1: done */ - u32 flush_done : 1; - u32 work_mode : 2; /* 0:Target, 1:Initiator, 2:Target&Initiator */ - u32 seq_cnt : 1; /* seq_cnt */ - u32 e_d_tov : 1; /* E_D_TOV resolution */ - u32 vlan_enable : 1; /* Vlan enable flag */ - u32 conf_support : 1; /* Response confirm support flag */ - u32 rec_support : 1; /* REC support flag */ - u32 write_xfer_rdy : 1; /* WRITE Xfer_Rdy disable or enable */ - u32 sgl_num : 1; /* Double or single SGL, 1: double; 0: single */ - } dw; - u32 pctxt_val1; - } sw_ctxt_config; - struct immi_dif_info immi_dif_info; /* immediate data dif control info(20B) */ -}; - -struct spfc_hw_rsvd_queue { - /* bitmap[0]:255-192 */ - /* bitmap[1]:191-128 */ - /* bitmap[2]:127-64 */ - /* bitmap[3]:63-0 */ - u64 seq_id_bitmap[4]; - struct { - u64 last_req_seq_id : 8; - u64 xid : 20; - u64 rsvd0 : 36; - } wd0; -}; - -struct spfc_sq_qinfo { - u64 rsvd_0 : 10; - u64 pmsn_type : 1; /* 0: get pmsn from queue header; 1: get pmsn from ucode */ - u64 rsvd_1 : 4; - u64 cur_wqe_o : 1; /* should be opposite from loop_o */ - u64 rsvd_2 : 48; - - u64 cur_sqe_gpa; - u64 pmsn_gpa; /* sq's queue header gpa */ - - u64 sqe_dmaattr_idx : 6; - u64 sq_so_ro : 2; - u64 rsvd_3 : 2; - u64 ring : 1; /* 0: link; 1: ring */ - u64 loop_o : 1; /* init to be the first round o-bit */ - u64 rsvd_4 : 4; - u64 zerocopy_dmaattr_idx : 6; - u64 zerocopy_so_ro : 2; - u64 parity : 8; - u64 r : 1; - u64 s : 1; - u64 enable_256 : 1; - u64 rsvd_5 : 23; - u64 pcie_template : 6; -}; - -struct spfc_cq_qinfo { - u64 pcie_template_hi : 3; - u64 parity_2 : 1; - u64 cur_cqe_gpa : 60; - - u64 pi : 15; - u64 pi_o : 1; - u64 ci : 15; - u64 ci_o : 1; - u64 c_eqn_msi_x : 10; /* if init_mode = 2, is msi/msi-x; other the low-5-bit means c_eqn */ - u64 parity_1 : 1; - u64 ci_type : 1; /* 0: get ci from queue header; 1: get ci from ucode */ - u64 cq_depth : 3; /* valid when ring = 1 */ - u64 armq : 1; /* 0: IDLE state; 1: NEXT state */ - u64 cur_cqe_cnt : 8; - u64 cqe_max_cnt : 8; - - u64 cqe_dmaattr_idx : 6; - u64 cq_so_ro : 2; - u64 init_mode : 2; /* 1: armQ; 2: msi/msi-x; others: rsvd */ - u64 next_o : 1; /* next pate valid o-bit */ - u64 loop_o : 1; /* init to be the first round o-bit */ - u64 next_cq_wqe_page_gpa : 52; - - u64 pcie_template_lo : 3; - u64 parity_0 : 1; - u64 ci_gpa : 60; /* cq's queue header gpa */ -}; - -struct spfc_scq_qinfo { - union { - struct { - u64 scq_n : 20; /* scq number */ - u64 sq_min_preld_cache_num : 4; - u64 sq_th0_preld_cache_num : 5; - u64 sq_th1_preld_cache_num : 5; - u64 sq_th2_preld_cache_num : 5; - u64 rq_min_preld_cache_num : 4; - u64 rq_th0_preld_cache_num : 5; - u64 rq_th1_preld_cache_num : 5; - u64 rq_th2_preld_cache_num : 5; - u64 parity : 6; - } info; - - u64 pctxt_val1; - } hw_scqc_config; -}; - -struct spfc_srq_qinfo { - u64 parity : 4; - u64 srqc_gpa : 60; -}; - -/* here is the layout of service type 12/13 */ -struct spfc_parent_context { - u8 key[SPFC_PARENT_CONTEXT_KEY_ALIGN_SIZE]; - struct spfc_scq_qinfo resp_scq_qinfo; - struct spfc_srq_qinfo imm_srq_info; - struct spfc_sq_qinfo sq_qinfo; - u8 timer_section[SPFC_PARENT_CONTEXT_TIMER_SIZE]; - struct spfc_hw_rsvd_queue hw_rsvdq; - struct spfc_srq_qinfo els_srq_info; - struct spfc_sw_section sw_section; -}; - -/* here is the layout of service type 13 */ -struct spfc_ssq_parent_context { - u8 rsvd0[64]; - struct spfc_sq_qinfo sq1_qinfo; - u8 rsvd1[32]; - struct spfc_sq_qinfo sq2_qinfo; - u8 rsvd2[32]; - struct spfc_sq_qinfo sq3_qinfo; - struct spfc_scq_qinfo sq_pretchinfo; - u8 rsvd3[24]; -}; - -/* FC Key Section */ -struct spfc_fc_key_section { - u32 xid_h : 4; - u32 key_size : 2; - u32 rsvd1 : 1; - u32 srv_type : 5; - u32 csize : 2; - u32 rsvd0 : 17; - u32 v : 1; - - u32 tag_fp_h : 4; - u32 rsvd2 : 12; - u32 xid_l : 16; - - u16 tag_fp_l; - u8 smac[6]; /* Source MAC */ - u8 dmac[6]; /* Dest MAC */ - u8 sid[3]; /* Source FC ID */ - u8 did[3]; /* Dest FC ID */ - u8 svlan[4]; /* Svlan */ - u8 cvlan[4]; /* Cvlan */ - - u32 next_ptr_h; -}; - -#endif diff --git a/drivers/scsi/spfc/hw/spfc_queue.c b/drivers/scsi/spfc/hw/spfc_queue.c deleted file mode 100644 index fa4295832da7..000000000000 --- a/drivers/scsi/spfc/hw/spfc_queue.c +++ /dev/null @@ -1,4852 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#include "spfc_queue.h" -#include "unf_log.h" -#include "unf_lport.h" -#include "spfc_module.h" -#include "spfc_utils.h" -#include "spfc_service.h" -#include "spfc_chipitf.h" -#include "spfc_parent_context.h" -#include "sphw_hw.h" -#include "sphw_crm.h" - -#define SPFC_UCODE_CMD_MODIFY_QUEUE_CONTEXT 0 - -#define SPFC_DONE_MASK (0x00000001) -#define SPFC_OWNER_MASK (0x80000000) - -#define SPFC_SQ_LINK_PRE (1 << 2) - -#define SPFC_SQ_HEADER_ADDR_ALIGN_SIZE (64) -#define SPFC_SQ_HEADER_ADDR_ALIGN_SIZE_MASK (SPFC_SQ_HEADER_ADDR_ALIGN_SIZE - 1) - -#define SPFC_ADDR_64_ALIGN(addr) \ - (((addr) + (SPFC_SQ_HEADER_ADDR_ALIGN_SIZE_MASK)) & \ - ~(SPFC_SQ_HEADER_ADDR_ALIGN_SIZE_MASK)) - -u32 spfc_get_parity_value(u64 *src_data, u32 row, u32 col) -{ - u32 i = 0; - u32 j = 0; - u32 offset = 0; - u32 group = 0; - u32 bit_offset = 0; - u32 bit_val = 0; - u32 tmp_val = 0; - u32 dest_data = 0; - - for (i = 0; i < row; i++) { - for (j = 0; j < col; j++) { - offset = (row * j + i); - group = offset / (sizeof(src_data[ARRAY_INDEX_0]) * UNF_BITS_PER_BYTE); - bit_offset = offset % (sizeof(src_data[ARRAY_INDEX_0]) * UNF_BITS_PER_BYTE); - tmp_val = (src_data[group] >> bit_offset) & SPFC_PARITY_MASK; - - if (j == 0) { - bit_val = tmp_val; - continue; - } - - bit_val ^= tmp_val; - } - - bit_val = (~bit_val) & SPFC_PARITY_MASK; - - dest_data |= (bit_val << i); - } - - return dest_data; -} - -static void spfc_update_producer_info(u16 q_depth, u16 *pus_pi, u16 *pus_owner) -{ - u16 current_pi = 0; - u16 next_pi = 0; - u16 owner = 0; - - current_pi = *pus_pi; - next_pi = current_pi + 1; - - if (next_pi < q_depth) { - *pus_pi = next_pi; - } else { - /* PI reversal */ - *pus_pi = 0; - - /* obit reversal */ - owner = *pus_owner; - *pus_owner = !owner; - } -} - -static void spfc_update_consumer_info(u16 q_depth, u16 *pus_ci, u16 *pus_owner) -{ - u16 current_ci = 0; - u16 next_ci = 0; - u16 owner = 0; - - current_ci = *pus_ci; - next_ci = current_ci + 1; - - if (next_ci < q_depth) { - *pus_ci = next_ci; - } else { - /* CI reversal */ - *pus_ci = 0; - - /* obit reversal */ - owner = *pus_owner; - *pus_owner = !owner; - } -} - -static inline void spfc_update_cq_header(struct ci_record *ci_record, u16 ci, - u16 owner) -{ - u32 size = 0; - struct ci_record record = {0}; - - size = sizeof(struct ci_record); - memcpy(&record, ci_record, size); - spfc_big_to_cpu64(&record, size); - record.cmsn = ci + (u16)(owner << SPFC_CQ_HEADER_OWNER_SHIFT); - record.dump_cmsn = record.cmsn; - spfc_cpu_to_big64(&record, size); - - wmb(); - memcpy(ci_record, &record, size); -} - -static void spfc_update_srq_header(struct db_record *pmsn_record, u16 pmsn) -{ - u32 size = 0; - struct db_record record = {0}; - - size = sizeof(struct db_record); - memcpy(&record, pmsn_record, size); - spfc_big_to_cpu64(&record, size); - record.pmsn = pmsn; - record.dump_pmsn = record.pmsn; - spfc_cpu_to_big64(&record, sizeof(struct db_record)); - - wmb(); - memcpy(pmsn_record, &record, size); -} - -static void spfc_set_srq_wqe_owner_be(struct spfc_wqe_ctrl *sqe_ctrl_in_wp, - u32 owner) -{ - struct spfc_wqe_ctrl_ch wqe_ctrl_ch; - - mb(); - - wqe_ctrl_ch.ctrl_ch_val = be32_to_cpu(sqe_ctrl_in_wp->ch.ctrl_ch_val); - wqe_ctrl_ch.wd0.owner = owner; - sqe_ctrl_in_wp->ch.ctrl_ch_val = cpu_to_be32(wqe_ctrl_ch.ctrl_ch_val); - - mb(); -} - -static inline void spfc_set_sq_wqe_owner_be(void *sqe) -{ - u32 *sqe_dw = (u32 *)sqe; - u32 *e_sqe_dw = (u32 *)((u8 *)sqe + SPFC_EXTEND_WQE_OFFSET); - - /* Ensure that the write of WQE is complete */ - mb(); - e_sqe_dw[SPFC_SQE_SECOND_OBIT_DW_POS] |= SPFC_SQE_OBIT_SET_MASK_BE; - e_sqe_dw[SPFC_SQE_FIRST_OBIT_DW_POS] |= SPFC_SQE_OBIT_SET_MASK_BE; - sqe_dw[SPFC_SQE_SECOND_OBIT_DW_POS] |= SPFC_SQE_OBIT_SET_MASK_BE; - sqe_dw[SPFC_SQE_FIRST_OBIT_DW_POS] |= SPFC_SQE_OBIT_SET_MASK_BE; - mb(); -} - -void spfc_clear_sq_wqe_owner_be(struct spfc_sqe *sqe) -{ - u32 *sqe_dw = (u32 *)sqe; - u32 *e_sqe_dw = (u32 *)((u8 *)sqe + SPFC_EXTEND_WQE_OFFSET); - - mb(); - sqe_dw[SPFC_SQE_SECOND_OBIT_DW_POS] &= SPFC_SQE_OBIT_CLEAR_MASK_BE; - mb(); - sqe_dw[SPFC_SQE_FIRST_OBIT_DW_POS] &= SPFC_SQE_OBIT_CLEAR_MASK_BE; - e_sqe_dw[SPFC_SQE_SECOND_OBIT_DW_POS] &= SPFC_SQE_OBIT_CLEAR_MASK_BE; - e_sqe_dw[SPFC_SQE_FIRST_OBIT_DW_POS] &= SPFC_SQE_OBIT_CLEAR_MASK_BE; -} - -static void spfc_set_direct_wqe_owner_be(void *sqe, u16 owner) -{ - if (owner) - spfc_set_sq_wqe_owner_be(sqe); - else - spfc_clear_sq_wqe_owner_be(sqe); -} - -static void spfc_set_srq_link_wqe_owner_be(struct spfc_linkwqe *link_wqe, - u32 owner, u16 pmsn) -{ - struct spfc_linkwqe local_lw; - - mb(); - local_lw.val_wd1 = be32_to_cpu(link_wqe->val_wd1); - local_lw.wd1.msn = pmsn; - local_lw.wd1.dump_msn = (local_lw.wd1.msn & SPFC_LOCAL_LW_WD1_DUMP_MSN_MASK); - link_wqe->val_wd1 = cpu_to_be32(local_lw.val_wd1); - - local_lw.val_wd0 = be32_to_cpu(link_wqe->val_wd0); - local_lw.wd0.o = owner; - link_wqe->val_wd0 = cpu_to_be32(local_lw.val_wd0); - mb(); -} - -static inline bool spfc_is_scq_link_wqe(struct spfc_scq_info *scq_info) -{ - u16 custom_scqe_num = 0; - - custom_scqe_num = scq_info->ci + 1; - - if ((custom_scqe_num % scq_info->wqe_num_per_buf == 0) || - scq_info->valid_wqe_num == custom_scqe_num) - return true; - else - return false; -} - -static struct spfc_wqe_page * -spfc_add_tail_wqe_page(struct spfc_parent_ssq_info *ssq) -{ - struct spfc_hba_info *hba = NULL; - struct spfc_wqe_page *esgl = NULL; - struct list_head *free_list_head = NULL; - ulong flag = 0; - - hba = (struct spfc_hba_info *)ssq->hba; - - spin_lock_irqsave(&hba->sq_wpg_pool.wpg_pool_lock, flag); - - /* Get a WqePage from hba->sq_wpg_pool.list_free_wpg_pool, and add to - * sq.list_SqTailWqePage - */ - if (!list_empty(&hba->sq_wpg_pool.list_free_wpg_pool)) { - free_list_head = UNF_OS_LIST_NEXT(&hba->sq_wpg_pool.list_free_wpg_pool); - list_del(free_list_head); - list_add_tail(free_list_head, &ssq->list_linked_list_sq); - esgl = list_entry(free_list_head, struct spfc_wqe_page, entry_wpg); - - /* WqePage Pool counter */ - atomic_inc(&hba->sq_wpg_pool.wpg_in_use); - } else { - esgl = NULL; - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]SQ pool is empty when SQ(0x%x) try to get wqe page", - ssq->sqn); - SPFC_HBA_STAT(hba, SPFC_STAT_SQ_POOL_EMPTY); - } - - spin_unlock_irqrestore(&hba->sq_wpg_pool.wpg_pool_lock, flag); - - return esgl; -} - -static inline struct spfc_sqe *spfc_get_wqe_page_entry(struct spfc_wqe_page *wpg, - u32 wqe_offset) -{ - struct spfc_sqe *sqe_wpg = NULL; - - sqe_wpg = (struct spfc_sqe *)(wpg->wpg_addr); - sqe_wpg += wqe_offset; - - return sqe_wpg; -} - -static void spfc_free_head_wqe_page(struct spfc_parent_ssq_info *ssq) -{ - struct spfc_hba_info *hba = NULL; - struct spfc_wqe_page *sq_wpg = NULL; - struct list_head *entry_head_wqe_page = NULL; - ulong flag = 0; - - atomic_dec(&ssq->wqe_page_cnt); - - hba = (struct spfc_hba_info *)ssq->hba; - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_INFO, - "Port(0x%x) free wqe page nowpagecnt:%d", - hba->port_cfg.port_id, - atomic_read(&ssq->wqe_page_cnt)); - sq_wpg = SPFC_GET_SQ_HEAD(ssq); - - memset((void *)sq_wpg->wpg_addr, WQE_MARKER_0, hba->sq_wpg_pool.wpg_size); - - spin_lock_irqsave(&hba->sq_wpg_pool.wpg_pool_lock, flag); - entry_head_wqe_page = &sq_wpg->entry_wpg; - list_del(entry_head_wqe_page); - list_add_tail(entry_head_wqe_page, &hba->sq_wpg_pool.list_free_wpg_pool); - - /* WqePage Pool counter */ - atomic_dec(&hba->sq_wpg_pool.wpg_in_use); - spin_unlock_irqrestore(&hba->sq_wpg_pool.wpg_pool_lock, flag); -} - -static void spfc_free_link_list_wpg(struct spfc_parent_ssq_info *ssq) -{ - ulong flag = 0; - struct spfc_hba_info *hba = NULL; - struct list_head *node = NULL; - struct list_head *next_node = NULL; - struct list_head *entry_head_wqe_page = NULL; - struct spfc_wqe_page *sq_wpg = NULL; - - hba = (struct spfc_hba_info *)ssq->hba; - - list_for_each_safe(node, next_node, &ssq->list_linked_list_sq) { - sq_wpg = list_entry(node, struct spfc_wqe_page, entry_wpg); - memset((void *)sq_wpg->wpg_addr, WQE_MARKER_0, hba->sq_wpg_pool.wpg_size); - - spin_lock_irqsave(&hba->sq_wpg_pool.wpg_pool_lock, flag); - entry_head_wqe_page = &sq_wpg->entry_wpg; - list_del(entry_head_wqe_page); - list_add_tail(entry_head_wqe_page, &hba->sq_wpg_pool.list_free_wpg_pool); - - /* WqePage Pool counter */ - atomic_dec(&ssq->wqe_page_cnt); - atomic_dec(&hba->sq_wpg_pool.wpg_in_use); - - spin_unlock_irqrestore(&hba->sq_wpg_pool.wpg_pool_lock, flag); - } - - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_INFO, - "[info]Port(0x%x) RPort(0x%x) Sq(0x%x) link list destroyed, Sq.WqePageCnt=0x%x, SqWpgPool.wpg_in_use=0x%x", - hba->port_cfg.port_id, ssq->sqn, ssq->context_id, - atomic_read(&ssq->wqe_page_cnt), atomic_read(&hba->sq_wpg_pool.wpg_in_use)); -} - -struct spfc_wqe_page * -spfc_add_one_wqe_page(struct spfc_parent_ssq_info *ssq) -{ - u32 wqe_inx = 0; - struct spfc_wqe_page *wqe_page = NULL; - struct spfc_sqe *sqe_in_wp = NULL; - struct spfc_linkwqe *link_wqe_in_wpg = NULL; - struct spfc_linkwqe link_wqe; - - /* Add a new Wqe Page */ - wqe_page = spfc_add_tail_wqe_page(ssq); - - if (!wqe_page) - return NULL; - - for (wqe_inx = 0; wqe_inx <= ssq->wqe_num_per_buf; wqe_inx++) { - sqe_in_wp = spfc_get_wqe_page_entry(wqe_page, wqe_inx); - sqe_in_wp->ctrl_sl.ch.ctrl_ch_val = 0; - sqe_in_wp->ectrl_sl.ch.ctrl_ch_val = 0; - } - - /* Set last WqePage as linkwqe */ - link_wqe_in_wpg = (struct spfc_linkwqe *)spfc_get_wqe_page_entry(wqe_page, - ssq->wqe_num_per_buf); - link_wqe.val_wd0 = 0; - link_wqe.val_wd1 = 0; - link_wqe.next_page_addr_hi = (ssq->queue_style == SPFC_QUEUE_RING_STYLE) - ? SPFC_MSD(wqe_page->wpg_phy_addr) - : 0; - link_wqe.next_page_addr_lo = (ssq->queue_style == SPFC_QUEUE_RING_STYLE) - ? SPFC_LSD(wqe_page->wpg_phy_addr) - : 0; - link_wqe.wd0.wf = CQM_WQE_WF_LINK; - link_wqe.wd0.ctrlsl = CQM_LINK_WQE_CTRLSL_VALUE; - link_wqe.wd0.o = !(ssq->last_pi_owner); - link_wqe.wd1.lp = (ssq->queue_style == SPFC_QUEUE_RING_STYLE) - ? CQM_LINK_WQE_LP_VALID - : CQM_LINK_WQE_LP_INVALID; - spfc_cpu_to_big32(&link_wqe, sizeof(struct spfc_linkwqe)); - memcpy(link_wqe_in_wpg, &link_wqe, sizeof(struct spfc_linkwqe)); - memcpy((u8 *)link_wqe_in_wpg + SPFC_EXTEND_WQE_OFFSET, - &link_wqe, sizeof(struct spfc_linkwqe)); - - return wqe_page; -} - -static inline struct spfc_scqe_type * -spfc_get_scq_entry(struct spfc_scq_info *scq_info) -{ - u32 buf_id = 0; - u16 buf_offset = 0; - u16 ci = 0; - struct cqm_buf_list *buf = NULL; - - FC_CHECK_RETURN_VALUE(scq_info, NULL); - - ci = scq_info->ci; - buf_id = ci / scq_info->wqe_num_per_buf; - buf = &scq_info->cqm_scq_info->q_room_buf_1.buf_list[buf_id]; - buf_offset = (u16)(ci % scq_info->wqe_num_per_buf); - - return (struct spfc_scqe_type *)(buf->va) + buf_offset; -} - -static inline bool spfc_is_cqe_done(u32 *done, u32 *owner, u16 driver_owner) -{ - return ((((u16)(!!(*done & SPFC_DONE_MASK)) == driver_owner) && - ((u16)(!!(*owner & SPFC_OWNER_MASK)) == driver_owner)) ? true : false); -} - -u32 spfc_process_scq_cqe_entity(ulong info, u32 proc_cnt) -{ - u32 ret = UNF_RETURN_ERROR; - u32 index = 0; - struct wq_header *queue_header = NULL; - struct spfc_scqe_type *scqe = NULL; - struct spfc_scqe_type tmp_scqe; - struct spfc_scq_info *scq_info = (struct spfc_scq_info *)info; - - FC_CHECK_RETURN_VALUE(scq_info, ret); - SPFC_FUNCTION_ENTER; - - queue_header = (struct wq_header *)(void *)(scq_info->cqm_scq_info->q_header_vaddr); - - for (index = 0; index < proc_cnt;) { - /* If linked wqe, then update CI */ - if (spfc_is_scq_link_wqe(scq_info)) { - spfc_update_consumer_info(scq_info->valid_wqe_num, - &scq_info->ci, - &scq_info->ci_owner); - spfc_update_cq_header(&queue_header->ci_record, - scq_info->ci, scq_info->ci_owner); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, - UNF_INFO, - "[info]Current wqe is a linked wqe"); - continue; - } - - /* Get SCQE and then check obit & donebit whether been set */ - scqe = spfc_get_scq_entry(scq_info); - if (unlikely(!scqe)) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[warn]Scqe is NULL"); - break; - } - - if (!spfc_is_cqe_done((u32 *)(void *)&scqe->wd0, - (u32 *)(void *)&scqe->ch.wd0, - scq_info->ci_owner)) { - atomic_set(&scq_info->flush_stat, SPFC_QUEUE_FLUSH_DONE); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, - UNF_INFO, "[info]Now has no valid scqe"); - break; - } - - /* rmb & do memory copy */ - rmb(); - memcpy(&tmp_scqe, scqe, sizeof(struct spfc_scqe_type)); - /* process SCQ entry */ - ret = spfc_rcv_scq_entry_from_scq(scq_info->hba, (void *)&tmp_scqe, - scq_info->queue_id); - if (unlikely(ret != RETURN_OK)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]QueueId(0x%x) scqn(0x%x) scqe process error at CI(0x%x)", - scq_info->queue_id, scq_info->scqn, scq_info->ci); - } - - /* Update Driver's CI & Obit */ - spfc_update_consumer_info(scq_info->valid_wqe_num, - &scq_info->ci, &scq_info->ci_owner); - spfc_update_cq_header(&queue_header->ci_record, scq_info->ci, - scq_info->ci_owner); - index++; - } - - /* Re-schedule again if necessary */ - if (index == proc_cnt) - tasklet_schedule(&scq_info->tasklet); - - SPFC_FUNCTION_RETURN; - - return index; -} - -void spfc_set_scq_irg_cfg(struct spfc_hba_info *hba, u32 mode, u16 msix_index) -{ -#define SPFC_POLLING_MODE_ITERRUPT_PENDING_CNT 5 -#define SPFC_POLLING_MODE_ITERRUPT_COALESC_TIMER_CFG 10 - u8 pending_limt = 0; - u8 coalesc_timer_cfg = 0; - - struct interrupt_info info = {0}; - - if (mode != SPFC_SCQ_INTR_LOW_LATENCY_MODE) { - pending_limt = SPFC_POLLING_MODE_ITERRUPT_PENDING_CNT; - coalesc_timer_cfg = - SPFC_POLLING_MODE_ITERRUPT_COALESC_TIMER_CFG; - } - - memset(&info, 0, sizeof(info)); - info.interrupt_coalesc_set = 1; - info.lli_set = 0; - info.pending_limt = pending_limt; - info.coalesc_timer_cfg = coalesc_timer_cfg; - info.resend_timer_cfg = 0; - info.msix_index = msix_index; - - sphw_set_interrupt_cfg(hba->dev_handle, info, SPHW_CHANNEL_FC); -} - -void spfc_process_scq_cqe(ulong info) -{ - struct spfc_scq_info *scq_info = (struct spfc_scq_info *)info; - - FC_CHECK_RETURN_VOID(scq_info); - - spfc_process_scq_cqe_entity(info, SPFC_CQE_MAX_PROCESS_NUM_PER_INTR); -} - -irqreturn_t spfc_scq_irq(int irq, void *scq_info) -{ - SPFC_FUNCTION_ENTER; - - FC_CHECK_RETURN_VALUE(scq_info, IRQ_NONE); - - tasklet_schedule(&((struct spfc_scq_info *)scq_info)->tasklet); - - SPFC_FUNCTION_RETURN; - - return IRQ_HANDLED; -} - -static u32 spfc_alloc_scq_int(struct spfc_scq_info *scq_info) -{ - int ret = UNF_RETURN_ERROR_S32; - u16 act_num = 0; - struct irq_info irq_info; - struct spfc_hba_info *hba = NULL; - - FC_CHECK_RETURN_VALUE(scq_info, UNF_RETURN_ERROR); - - /* 1. Alloc & check SCQ IRQ */ - hba = (struct spfc_hba_info *)(scq_info->hba); - ret = sphw_alloc_irqs(hba->dev_handle, SERVICE_T_FC, SPFC_INT_NUM_PER_QUEUE, - &irq_info, &act_num); - if (ret != RETURN_OK || act_num != SPFC_INT_NUM_PER_QUEUE) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[err]Allocate scq irq failed, return %d", ret); - return UNF_RETURN_ERROR; - } - - if (irq_info.msix_entry_idx >= SPFC_SCQ_INT_ID_MAX) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]SCQ irq id exceed %d, msix_entry_idx %d", - SPFC_SCQ_INT_ID_MAX, irq_info.msix_entry_idx); - sphw_free_irq(hba->dev_handle, SERVICE_T_FC, irq_info.irq_id); - return UNF_RETURN_ERROR; - } - - scq_info->irq_id = (u32)(irq_info.irq_id); - scq_info->msix_entry_idx = (u16)(irq_info.msix_entry_idx); - - snprintf(scq_info->irq_name, SPFC_IRQ_NAME_MAX, "fc_scq%u_%x_msix%u", - scq_info->queue_id, hba->port_cfg.port_id, scq_info->msix_entry_idx); - - /* 2. SCQ IRQ tasklet init */ - tasklet_init(&scq_info->tasklet, spfc_process_scq_cqe, (ulong)(uintptr_t)scq_info); - - /* 3. Request IRQ for SCQ */ - ret = request_irq(scq_info->irq_id, spfc_scq_irq, 0, scq_info->irq_name, scq_info); - - sphw_set_msix_state(hba->dev_handle, scq_info->msix_entry_idx, SPHW_MSIX_ENABLE); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[err]Request SCQ irq failed, SCQ Index = %u, return %d", - scq_info->queue_id, ret); - sphw_free_irq(hba->dev_handle, SERVICE_T_FC, scq_info->irq_id); - memset(scq_info->irq_name, 0, SPFC_IRQ_NAME_MAX); - scq_info->irq_id = 0; - scq_info->msix_entry_idx = 0; - return UNF_RETURN_ERROR; - } - - return RETURN_OK; -} - -static void spfc_free_scq_int(struct spfc_scq_info *scq_info) -{ - struct spfc_hba_info *hba = NULL; - - FC_CHECK_RETURN_VOID(scq_info); - - hba = (struct spfc_hba_info *)(scq_info->hba); - sphw_set_msix_state(hba->dev_handle, scq_info->msix_entry_idx, SPHW_MSIX_DISABLE); - free_irq(scq_info->irq_id, scq_info); - tasklet_kill(&scq_info->tasklet); - sphw_free_irq(hba->dev_handle, SERVICE_T_FC, scq_info->irq_id); - memset(scq_info->irq_name, 0, SPFC_IRQ_NAME_MAX); - scq_info->irq_id = 0; - scq_info->msix_entry_idx = 0; -} - -static void spfc_init_scq_info(struct spfc_hba_info *hba, struct cqm_queue *cqm_scq, - u32 queue_id, struct spfc_scq_info **scq_info) -{ - FC_CHECK_RETURN_VOID(hba); - FC_CHECK_RETURN_VOID(cqm_scq); - FC_CHECK_RETURN_VOID(scq_info); - - *scq_info = &hba->scq_info[queue_id]; - (*scq_info)->queue_id = queue_id; - (*scq_info)->scqn = cqm_scq->index; - (*scq_info)->hba = (void *)hba; - - (*scq_info)->cqm_scq_info = cqm_scq; - (*scq_info)->wqe_num_per_buf = - cqm_scq->q_room_buf_1.buf_size / SPFC_SCQE_SIZE; - (*scq_info)->wqe_size = SPFC_SCQE_SIZE; - (*scq_info)->valid_wqe_num = (SPFC_SCQ_IS_STS(queue_id) ? SPFC_STS_SCQ_DEPTH - : SPFC_CMD_SCQ_DEPTH); - (*scq_info)->scqc_cq_depth = (SPFC_SCQ_IS_STS(queue_id) ? SPFC_STS_SCQC_CQ_DEPTH - : SPFC_CMD_SCQC_CQ_DEPTH); - (*scq_info)->scqc_ci_type = SPFC_STS_SCQ_CI_TYPE; - (*scq_info)->ci = 0; - (*scq_info)->ci_owner = 1; -} - -static void spfc_init_scq_header(struct wq_header *queue_header) -{ - FC_CHECK_RETURN_VOID(queue_header); - - memset(queue_header, 0, sizeof(struct wq_header)); - - /* Obit default is 1 */ - queue_header->db_record.pmsn = 1 << UNF_SHIFT_15; - queue_header->db_record.dump_pmsn = queue_header->db_record.pmsn; - queue_header->ci_record.cmsn = 1 << UNF_SHIFT_15; - queue_header->ci_record.dump_cmsn = queue_header->ci_record.cmsn; - - /* Big endian convert */ - spfc_cpu_to_big64((void *)queue_header, sizeof(struct wq_header)); -} - -static void spfc_cfg_scq_ctx(struct spfc_scq_info *scq_info, - struct spfc_cq_qinfo *scq_ctx) -{ - struct cqm_queue *cqm_scq_info = NULL; - struct spfc_queue_info_bus queue_bus; - u64 parity = 0; - - FC_CHECK_RETURN_VOID(scq_info); - - cqm_scq_info = scq_info->cqm_scq_info; - - scq_ctx->pcie_template_hi = 0; - scq_ctx->cur_cqe_gpa = cqm_scq_info->q_room_buf_1.buf_list->pa >> SPFC_CQE_GPA_SHIFT; - scq_ctx->pi = 0; - scq_ctx->pi_o = 1; - scq_ctx->ci = scq_info->ci; - scq_ctx->ci_o = scq_info->ci_owner; - scq_ctx->c_eqn_msi_x = scq_info->msix_entry_idx; - scq_ctx->ci_type = scq_info->scqc_ci_type; - scq_ctx->cq_depth = scq_info->scqc_cq_depth; - scq_ctx->armq = SPFC_ARMQ_IDLE; - scq_ctx->cur_cqe_cnt = 0; - scq_ctx->cqe_max_cnt = 0; - scq_ctx->cqe_dmaattr_idx = 0; - scq_ctx->cq_so_ro = 0; - scq_ctx->init_mode = SPFC_CQ_INT_MODE; - scq_ctx->next_o = 1; - scq_ctx->loop_o = 1; - scq_ctx->next_cq_wqe_page_gpa = cqm_scq_info->q_room_buf_1.buf_list[ARRAY_INDEX_1].pa >> - SPFC_NEXT_CQE_GPA_SHIFT; - scq_ctx->pcie_template_lo = 0; - - scq_ctx->ci_gpa = (cqm_scq_info->q_header_paddr + offsetof(struct wq_header, ci_record)) >> - SPFC_CQE_GPA_SHIFT; - - memset(&queue_bus, 0, sizeof(struct spfc_queue_info_bus)); - queue_bus.bus[ARRAY_INDEX_0] |= ((u64)(scq_info->scqn & SPFC_SCQN_MASK)); /* bits 20 */ - queue_bus.bus[ARRAY_INDEX_0] |= (((u64)(scq_ctx->pcie_template_lo)) << UNF_SHIFT_20); - queue_bus.bus[ARRAY_INDEX_0] |= (((u64)(scq_ctx->ci_gpa & SPFC_SCQ_CTX_CI_GPA_MASK)) << - UNF_SHIFT_23); /* bits 28 */ - queue_bus.bus[ARRAY_INDEX_0] |= (((u64)(scq_ctx->cqe_dmaattr_idx)) << UNF_SHIFT_51); - queue_bus.bus[ARRAY_INDEX_0] |= (((u64)(scq_ctx->cq_so_ro)) << UNF_SHIFT_57); /* bits 2 */ - queue_bus.bus[ARRAY_INDEX_0] |= (((u64)(scq_ctx->init_mode)) << UNF_SHIFT_59); /* bits 2 */ - queue_bus.bus[ARRAY_INDEX_0] |= (((u64)(scq_ctx->c_eqn_msi_x & - SPFC_SCQ_CTX_C_EQN_MSI_X_MASK)) << UNF_SHIFT_61); - queue_bus.bus[ARRAY_INDEX_1] |= ((u64)(scq_ctx->c_eqn_msi_x >> UNF_SHIFT_3)); /* bits 7 */ - queue_bus.bus[ARRAY_INDEX_1] |= (((u64)(scq_ctx->ci_type)) << UNF_SHIFT_7); /* bits 1 */ - queue_bus.bus[ARRAY_INDEX_1] |= (((u64)(scq_ctx->cq_depth)) << UNF_SHIFT_8); /* bits 3 */ - queue_bus.bus[ARRAY_INDEX_1] |= (((u64)(scq_ctx->cqe_max_cnt)) << UNF_SHIFT_11); - queue_bus.bus[ARRAY_INDEX_1] |= (((u64)(scq_ctx->pcie_template_hi)) << UNF_SHIFT_19); - - parity = spfc_get_parity_value(queue_bus.bus, SPFC_SCQC_BUS_ROW, SPFC_SCQC_BUS_COL); - scq_ctx->parity_0 = parity & SPFC_PARITY_MASK; - scq_ctx->parity_1 = (parity >> UNF_SHIFT_1) & SPFC_PARITY_MASK; - scq_ctx->parity_2 = (parity >> UNF_SHIFT_2) & SPFC_PARITY_MASK; - - spfc_cpu_to_big64((void *)scq_ctx, sizeof(struct spfc_cq_qinfo)); -} - -static u32 spfc_creat_scqc_via_cmdq_sync(struct spfc_hba_info *hba, - struct spfc_cq_qinfo *scqc, u32 scqn) -{ -#define SPFC_INIT_SCQC_TIMEOUT 3000 - int ret; - u32 covrt_size; - struct spfc_cmdqe_creat_scqc init_scqc_cmd; - struct sphw_cmd_buf *cmdq_in_buf; - - cmdq_in_buf = sphw_alloc_cmd_buf(hba->dev_handle); - if (!cmdq_in_buf) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[err]cmdq in_cmd_buf alloc failed"); - - SPFC_ERR_IO_STAT(hba, SPFC_TASK_T_INIT_SCQC); - return UNF_RETURN_ERROR; - } - - memset(&init_scqc_cmd, 0, sizeof(init_scqc_cmd)); - init_scqc_cmd.wd0.task_type = SPFC_TASK_T_INIT_SCQC; - init_scqc_cmd.wd1.scqn = SPFC_LSW(scqn); - covrt_size = sizeof(init_scqc_cmd) - sizeof(init_scqc_cmd.scqc); - spfc_cpu_to_big32(&init_scqc_cmd, covrt_size); - - /* scqc is already big endian */ - memcpy(init_scqc_cmd.scqc, scqc, sizeof(*scqc)); - memcpy(cmdq_in_buf->buf, &init_scqc_cmd, sizeof(init_scqc_cmd)); - cmdq_in_buf->size = sizeof(init_scqc_cmd); - - ret = sphw_cmdq_detail_resp(hba->dev_handle, COMM_MOD_FC, 0, - cmdq_in_buf, NULL, NULL, - SPFC_INIT_SCQC_TIMEOUT, SPHW_CHANNEL_FC); - sphw_free_cmd_buf(hba->dev_handle, cmdq_in_buf); - if (ret) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[err]Send creat scqc via cmdq failed, ret=%d", - ret); - - SPFC_ERR_IO_STAT(hba, SPFC_TASK_T_INIT_SCQC); - return UNF_RETURN_ERROR; - } - - SPFC_IO_STAT(hba, SPFC_TASK_T_INIT_SCQC); - - return RETURN_OK; -} - -static u32 spfc_delete_ssqc_via_cmdq_sync(struct spfc_hba_info *hba, u32 xid, - u64 context_gpa, u32 entry_count) -{ -#define SPFC_DELETE_SSQC_TIMEOUT 3000 - int ret = RETURN_OK; - struct spfc_cmdqe_delete_ssqc delete_ssqc_cmd; - struct sphw_cmd_buf *cmdq_in_buf = NULL; - - cmdq_in_buf = sphw_alloc_cmd_buf(hba->dev_handle); - if (!cmdq_in_buf) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[err]cmdq in_cmd_buf alloc failed"); - return UNF_RETURN_ERROR; - } - - memset(&delete_ssqc_cmd, 0, sizeof(delete_ssqc_cmd)); - delete_ssqc_cmd.wd0.task_type = SPFC_TASK_T_CLEAR_SSQ_CONTEXT; - delete_ssqc_cmd.wd0.xid = xid; - delete_ssqc_cmd.wd0.entry_count = entry_count; - delete_ssqc_cmd.wd1.scqn = SPFC_LSW(0); - delete_ssqc_cmd.context_gpa_hi = SPFC_HIGH_32_BITS(context_gpa); - delete_ssqc_cmd.context_gpa_lo = SPFC_LOW_32_BITS(context_gpa); - spfc_cpu_to_big32(&delete_ssqc_cmd, sizeof(delete_ssqc_cmd)); - memcpy(cmdq_in_buf->buf, &delete_ssqc_cmd, sizeof(delete_ssqc_cmd)); - cmdq_in_buf->size = sizeof(delete_ssqc_cmd); - - ret = sphw_cmdq_detail_resp(hba->dev_handle, COMM_MOD_FC, 0, - cmdq_in_buf, NULL, NULL, - SPFC_DELETE_SSQC_TIMEOUT, - SPHW_CHANNEL_FC); - - sphw_free_cmd_buf(hba->dev_handle, cmdq_in_buf); - - return ret; -} - -static void spfc_free_ssq_qpc(struct spfc_hba_info *hba, u32 free_sq_num) -{ - u32 global_sq_index = 0; - u32 qid = 0; - struct spfc_parent_shared_queue_info *ssq_info = NULL; - - SPFC_FUNCTION_ENTER; - for (global_sq_index = 0; global_sq_index < free_sq_num;) { - for (qid = 1; qid <= SPFC_SQ_NUM_PER_QPC; qid++) { - ssq_info = &hba->parent_queue_mgr->shared_queue[global_sq_index]; - if (qid == SPFC_SQ_NUM_PER_QPC || - global_sq_index == free_sq_num - 1) { - if (ssq_info->parent_ctx.cqm_parent_ctx_obj) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_INFO, - "[INFO]qid 0x%x, global_sq_index 0x%x, free_sq_num 0x%x", - qid, global_sq_index, free_sq_num); - cqm3_object_delete(&ssq_info->parent_ctx - .cqm_parent_ctx_obj->object); - ssq_info->parent_ctx.cqm_parent_ctx_obj = NULL; - } - } - global_sq_index++; - if (global_sq_index >= free_sq_num) - break; - } - } -} - -void spfc_free_ssq(void *handle, u32 free_sq_num) -{ -#define SPFC_FREE_SSQ_WAIT_MS 1000 - u32 global_sq_index = 0; - u32 qid = 0; - struct spfc_parent_shared_queue_info *ssq_info = NULL; - struct spfc_parent_ssq_info *sq_ctrl = NULL; - struct cqm_qpc_mpt *prnt_ctx = NULL; - u32 ret = UNF_RETURN_ERROR; - u32 entry_count = 0; - struct spfc_hba_info *hba = NULL; - - SPFC_FUNCTION_ENTER; - - hba = (struct spfc_hba_info *)handle; - for (global_sq_index = 0; global_sq_index < free_sq_num;) { - for (qid = 1; qid <= SPFC_SQ_NUM_PER_QPC; qid++) { - ssq_info = &hba->parent_queue_mgr->shared_queue[global_sq_index]; - sq_ctrl = &ssq_info->parent_ssq_info; - /* Free data cos */ - spfc_free_link_list_wpg(sq_ctrl); - if (sq_ctrl->queue_head_original) { - pci_unmap_single(hba->pci_dev, - sq_ctrl->queue_hdr_phy_addr_original, - sizeof(struct spfc_queue_header) + - SPFC_SQ_HEADER_ADDR_ALIGN_SIZE, - DMA_BIDIRECTIONAL); - kfree(sq_ctrl->queue_head_original); - sq_ctrl->queue_head_original = NULL; - } - if (qid == SPFC_SQ_NUM_PER_QPC || global_sq_index == free_sq_num - 1) { - if (ssq_info->parent_ctx.cqm_parent_ctx_obj) { - prnt_ctx = ssq_info->parent_ctx.cqm_parent_ctx_obj; - entry_count = (qid == SPFC_SQ_NUM_PER_QPC ? - SPFC_SQ_NUM_PER_QPC : - free_sq_num - global_sq_index); - ret = spfc_delete_ssqc_via_cmdq_sync(hba, prnt_ctx->xid, - prnt_ctx->paddr, - entry_count); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[err]ucode delete ssq fail, glbindex 0x%x, qid 0x%x, glsqindex 0x%x", - global_sq_index, qid, free_sq_num); - } - } - } - global_sq_index++; - if (global_sq_index >= free_sq_num) - break; - } - } - - msleep(SPFC_FREE_SSQ_WAIT_MS); - - spfc_free_ssq_qpc(hba, free_sq_num); -} - -u32 spfc_creat_ssqc_via_cmdq_sync(struct spfc_hba_info *hba, - struct spfc_ssq_parent_context *ssqc, - u32 xid, u64 context_gpa) -{ -#define SPFC_INIT_SSQC_TIMEOUT 3000 - int ret; - u32 covrt_size; - struct spfc_cmdqe_creat_ssqc create_ssqc_cmd; - struct sphw_cmd_buf *cmdq_in_buf = NULL; - - cmdq_in_buf = sphw_alloc_cmd_buf(hba->dev_handle); - if (!cmdq_in_buf) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[err]cmdq in_cmd_buf alloc failed"); - return UNF_RETURN_ERROR; - } - - memset(&create_ssqc_cmd, 0, sizeof(create_ssqc_cmd)); - create_ssqc_cmd.wd0.task_type = SPFC_TASK_T_CREATE_SSQ_CONTEXT; - create_ssqc_cmd.wd0.xid = xid; - create_ssqc_cmd.wd1.scqn = SPFC_LSW(0); - create_ssqc_cmd.context_gpa_hi = SPFC_HIGH_32_BITS(context_gpa); - create_ssqc_cmd.context_gpa_lo = SPFC_LOW_32_BITS(context_gpa); - covrt_size = sizeof(create_ssqc_cmd) - sizeof(create_ssqc_cmd.ssqc); - spfc_cpu_to_big32(&create_ssqc_cmd, covrt_size); - - /* scqc is already big endian */ - memcpy(create_ssqc_cmd.ssqc, ssqc, sizeof(*ssqc)); - memcpy(cmdq_in_buf->buf, &create_ssqc_cmd, sizeof(create_ssqc_cmd)); - cmdq_in_buf->size = sizeof(create_ssqc_cmd); - ret = sphw_cmdq_detail_resp(hba->dev_handle, COMM_MOD_FC, 0, - cmdq_in_buf, NULL, NULL, - SPFC_INIT_SSQC_TIMEOUT, SPHW_CHANNEL_FC); - sphw_free_cmd_buf(hba->dev_handle, cmdq_in_buf); - if (ret) - return UNF_RETURN_ERROR; - return RETURN_OK; -} - -void spfc_init_sq_prnt_ctxt_sq_qinfo(struct spfc_sq_qinfo *sq_info, - struct spfc_parent_ssq_info *ssq) -{ - struct spfc_wqe_page *head_wqe_page = NULL; - struct spfc_sq_qinfo *prnt_sq_ctx = NULL; - struct spfc_queue_info_bus queue_bus; - - SPFC_FUNCTION_ENTER; - - /* Obtains the Parent Context address */ - head_wqe_page = SPFC_GET_SQ_HEAD(ssq); - - prnt_sq_ctx = sq_info; - - /* The PMSN is updated by the host driver */ - prnt_sq_ctx->pmsn_type = SPFC_PMSN_CI_TYPE_FROM_HOST; - - /* Indicates the value of O of the valid SQE in the current round of SQ. - * * The value of Linked List SQ is always one, and the value of 0 is - * invalid. - */ - prnt_sq_ctx->loop_o = - SPFC_OWNER_DRIVER_PRODUCT; /* current valid o-bit */ - - /* should be opposite from loop_o */ - prnt_sq_ctx->cur_wqe_o = ~(prnt_sq_ctx->loop_o); - - /* the first sqe's gpa */ - prnt_sq_ctx->cur_sqe_gpa = head_wqe_page->wpg_phy_addr; - - /* Indicates the GPA of the Queue header that is initialized to the SQ - * in * the Host memory. The value must be 16-byte aligned. - */ - prnt_sq_ctx->pmsn_gpa = ssq->queue_hdr_phy_addr; - if (wqe_pre_load != 0) - prnt_sq_ctx->pmsn_gpa |= SPFC_SQ_LINK_PRE; - - /* This field is used to fill in the dmaattr_idx field of the ComboDMA. - * The default value is 0 - */ - prnt_sq_ctx->sqe_dmaattr_idx = SPFC_DMA_ATTR_OFST; - - /* This field is filled using the value of RO_SO in the SGL0 of the - * ComboDMA - */ - prnt_sq_ctx->sq_so_ro = SPFC_PCIE_RELAXED_ORDERING; - - prnt_sq_ctx->ring = ssq->queue_style; - - /* This field is used to set the SGL0 field of the Child solicDMA */ - prnt_sq_ctx->zerocopy_dmaattr_idx = SPFC_DMA_ATTR_OFST; - - prnt_sq_ctx->zerocopy_so_ro = SPFC_PCIE_RELAXED_ORDERING; - prnt_sq_ctx->enable_256 = SPFC_256BWQE_ENABLE; - - /* PCIe attribute information */ - prnt_sq_ctx->pcie_template = SPFC_PCIE_TEMPLATE; - - memset(&queue_bus, 0, sizeof(struct spfc_queue_info_bus)); - queue_bus.bus[ARRAY_INDEX_0] |= ((u64)(ssq->context_id & SPFC_SSQ_CTX_MASK)); /* bits 20 */ - queue_bus.bus[ARRAY_INDEX_0] |= (((u64)(prnt_sq_ctx->sqe_dmaattr_idx)) << UNF_SHIFT_20); - queue_bus.bus[ARRAY_INDEX_0] |= (((u64)(prnt_sq_ctx->sq_so_ro)) << UNF_SHIFT_26); - queue_bus.bus[ARRAY_INDEX_0] |= (((u64)(prnt_sq_ctx->ring)) << UNF_SHIFT_28); /* bits 1 */ - queue_bus.bus[ARRAY_INDEX_0] |= (((u64)(prnt_sq_ctx->zerocopy_dmaattr_idx)) - << UNF_SHIFT_29); /* bits 6 */ - queue_bus.bus[ARRAY_INDEX_0] |= (((u64)(prnt_sq_ctx->zerocopy_so_ro)) << UNF_SHIFT_35); - queue_bus.bus[ARRAY_INDEX_0] |= (((u64)(prnt_sq_ctx->pcie_template)) << UNF_SHIFT_37); - queue_bus.bus[ARRAY_INDEX_0] |= (((u64)(prnt_sq_ctx->pmsn_gpa >> UNF_SHIFT_4)) - << UNF_SHIFT_43); /* bits 21 */ - queue_bus.bus[ARRAY_INDEX_1] |= ((u64)(prnt_sq_ctx->pmsn_gpa >> UNF_SHIFT_25)); - queue_bus.bus[ARRAY_INDEX_1] |= (((u64)(prnt_sq_ctx->pmsn_type)) << UNF_SHIFT_39); - prnt_sq_ctx->parity = spfc_get_parity_value(queue_bus.bus, SPFC_SQC_BUS_ROW, - SPFC_SQC_BUS_COL); - spfc_cpu_to_big64(prnt_sq_ctx, sizeof(struct spfc_sq_qinfo)); - - SPFC_FUNCTION_RETURN; -} - -u32 spfc_create_ssq(void *handle) -{ - u32 ret = RETURN_OK; - u32 global_sq_index = 0; - u32 qid = 0; - struct cqm_qpc_mpt *prnt_ctx = NULL; - struct spfc_parent_shared_queue_info *ssq_info = NULL; - struct spfc_parent_ssq_info *sq_ctrl = NULL; - u32 queue_header_alloc_size = 0; - struct spfc_wqe_page *head_wpg = NULL; - struct spfc_ssq_parent_context prnt_ctx_info; - struct spfc_sq_qinfo *sq_info = NULL; - struct spfc_scq_qinfo *psq_pretchinfo = NULL; - struct spfc_queue_info_bus queue_bus; - struct spfc_fc_key_section *keysection = NULL; - struct spfc_hba_info *hba = NULL; - dma_addr_t origin_addr; - - FC_CHECK_RETURN_VALUE(handle, UNF_RETURN_ERROR); - hba = (struct spfc_hba_info *)handle; - for (global_sq_index = 0; global_sq_index < SPFC_MAX_SSQ_NUM;) { - qid = 0; - prnt_ctx = cqm3_object_qpc_mpt_create(hba->dev_handle, SERVICE_T_FC, - CQM_OBJECT_SERVICE_CTX, - SPFC_CNTX_SIZE_256B, NULL, - CQM_INDEX_INVALID); - if (!prnt_ctx) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Create ssq context failed, CQM_INDEX is 0x%x", - CQM_INDEX_INVALID); - goto ssq_ctx_create_fail; - } - memset(&prnt_ctx_info, 0, sizeof(prnt_ctx_info)); - keysection = (struct spfc_fc_key_section *)&prnt_ctx_info; - keysection->xid_h = (prnt_ctx->xid >> UNF_SHIFT_16) & SPFC_KEYSECTION_XID_H_MASK; - keysection->xid_l = prnt_ctx->xid & SPFC_KEYSECTION_XID_L_MASK; - spfc_cpu_to_big32(keysection, sizeof(struct spfc_fc_key_section)); - for (qid = 0; qid < SPFC_SQ_NUM_PER_QPC; qid++) { - sq_info = (struct spfc_sq_qinfo *)((u8 *)(&prnt_ctx_info) + ((qid + 1) * - SPFC_SQ_SPACE_OFFSET)); - ssq_info = &hba->parent_queue_mgr->shared_queue[global_sq_index]; - ssq_info->parent_ctx.cqm_parent_ctx_obj = prnt_ctx; - /* Initialize struct spfc_parent_sq_info */ - sq_ctrl = &ssq_info->parent_ssq_info; - sq_ctrl->hba = (void *)hba; - sq_ctrl->context_id = prnt_ctx->xid; - sq_ctrl->sq_queue_id = qid + SPFC_SQ_QID_START_PER_QPC; - sq_ctrl->cache_id = FC_CALC_CID(prnt_ctx->xid); - sq_ctrl->sqn = global_sq_index; - sq_ctrl->max_sqe_num = hba->exi_count; - /* Reduce one Link Wqe */ - sq_ctrl->wqe_num_per_buf = hba->sq_wpg_pool.wqe_per_wpg - 1; - sq_ctrl->wqe_size = SPFC_SQE_SIZE; - sq_ctrl->wqe_offset = 0; - sq_ctrl->head_start_cmsn = 0; - sq_ctrl->head_end_cmsn = SPFC_GET_WP_END_CMSN(0, sq_ctrl->wqe_num_per_buf); - sq_ctrl->last_pmsn = 0; - /* Linked List SQ Owner Bit 1 valid,0 invalid */ - sq_ctrl->last_pi_owner = 1; - atomic_set(&sq_ctrl->sq_valid, true); - sq_ctrl->accum_wqe_cnt = 0; - sq_ctrl->service_type = SPFC_SERVICE_TYPE_FC_SQ; - sq_ctrl->queue_style = (global_sq_index == SPFC_DIRECTWQE_SQ_INDEX) ? - SPFC_QUEUE_RING_STYLE : SPFC_QUEUE_LINK_STYLE; - INIT_LIST_HEAD(&sq_ctrl->list_linked_list_sq); - atomic_set(&sq_ctrl->wqe_page_cnt, 0); - atomic_set(&sq_ctrl->sq_db_cnt, 0); - atomic_set(&sq_ctrl->sqe_minus_cqe_cnt, 1); - atomic_set(&sq_ctrl->sq_wqe_cnt, 0); - atomic_set(&sq_ctrl->sq_cqe_cnt, 0); - spin_lock_init(&sq_ctrl->parent_sq_enqueue_lock); - memset(sq_ctrl->io_stat, 0, sizeof(sq_ctrl->io_stat)); - - /* Allocate and initialize the Queue Header space. 64B - * alignment is required. * Additional 64B is applied - * for alignment - */ - queue_header_alloc_size = sizeof(struct spfc_queue_header) + - SPFC_SQ_HEADER_ADDR_ALIGN_SIZE; - sq_ctrl->queue_head_original = kmalloc(queue_header_alloc_size, GFP_ATOMIC); - if (!sq_ctrl->queue_head_original) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]SQ(0x%x) create SQ queue header failed", - global_sq_index); - goto ssq_qheader_create_fail; - } - - memset((u8 *)sq_ctrl->queue_head_original, 0, queue_header_alloc_size); - - sq_ctrl->queue_hdr_phy_addr_original = - pci_map_single(hba->pci_dev, sq_ctrl->queue_head_original, - queue_header_alloc_size, DMA_BIDIRECTIONAL); - origin_addr = sq_ctrl->queue_hdr_phy_addr_original; - if (pci_dma_mapping_error(hba->pci_dev, origin_addr)) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]SQ(0x%x) SQ queue header DMA mapping failed", - global_sq_index); - goto ssq_qheader_dma_map_fail; - } - - /* Obtains the 64B alignment address */ - sq_ctrl->queue_header = (struct spfc_queue_header *)(uintptr_t) - SPFC_ADDR_64_ALIGN((u64)((uintptr_t)(sq_ctrl->queue_head_original))); - sq_ctrl->queue_hdr_phy_addr = SPFC_ADDR_64_ALIGN(origin_addr); - - /* Each SQ is allocated with a Wqe Page by default. The - * WqePageCnt is incremented by one - */ - head_wpg = spfc_add_one_wqe_page(sq_ctrl); - if (!head_wpg) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[err]SQ(0x%x) create SQ first wqe page failed", - global_sq_index); - goto ssq_headwpg_create_fail; - } - - atomic_inc(&sq_ctrl->wqe_page_cnt); - spfc_init_sq_prnt_ctxt_sq_qinfo(sq_info, sq_ctrl); - global_sq_index++; - if (global_sq_index == SPFC_MAX_SSQ_NUM) - break; - } - psq_pretchinfo = &prnt_ctx_info.sq_pretchinfo; - psq_pretchinfo->hw_scqc_config.info.rq_th2_preld_cache_num = wqe_pre_load; - psq_pretchinfo->hw_scqc_config.info.rq_th1_preld_cache_num = wqe_pre_load; - psq_pretchinfo->hw_scqc_config.info.rq_th0_preld_cache_num = wqe_pre_load; - psq_pretchinfo->hw_scqc_config.info.rq_min_preld_cache_num = wqe_pre_load; - psq_pretchinfo->hw_scqc_config.info.sq_th2_preld_cache_num = wqe_pre_load; - psq_pretchinfo->hw_scqc_config.info.sq_th1_preld_cache_num = wqe_pre_load; - psq_pretchinfo->hw_scqc_config.info.sq_th0_preld_cache_num = wqe_pre_load; - psq_pretchinfo->hw_scqc_config.info.sq_min_preld_cache_num = wqe_pre_load; - psq_pretchinfo->hw_scqc_config.info.scq_n = (u64)0; - psq_pretchinfo->hw_scqc_config.info.parity = 0; - - memset(&queue_bus, 0, sizeof(struct spfc_queue_info_bus)); - queue_bus.bus[ARRAY_INDEX_0] = psq_pretchinfo->hw_scqc_config.pctxt_val1; - psq_pretchinfo->hw_scqc_config.info.parity = - spfc_get_parity_value(queue_bus.bus, SPFC_HW_SCQC_BUS_ROW, - SPFC_HW_SCQC_BUS_COL); - spfc_cpu_to_big64(psq_pretchinfo, sizeof(struct spfc_scq_qinfo)); - ret = spfc_creat_ssqc_via_cmdq_sync(hba, &prnt_ctx_info, - prnt_ctx->xid, prnt_ctx->paddr); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[err]SQ(0x%x) create ssqc failed.", - global_sq_index); - goto ssq_cmdqsync_fail; - } - } - - return RETURN_OK; - -ssq_headwpg_create_fail: - pci_unmap_single(hba->pci_dev, sq_ctrl->queue_hdr_phy_addr_original, - queue_header_alloc_size, DMA_BIDIRECTIONAL); - -ssq_qheader_dma_map_fail: - kfree(sq_ctrl->queue_head_original); - sq_ctrl->queue_head_original = NULL; - -ssq_qheader_create_fail: - cqm3_object_delete(&prnt_ctx->object); - ssq_info->parent_ctx.cqm_parent_ctx_obj = NULL; - if (qid > 0) { - while (qid--) { - ssq_info = &hba->parent_queue_mgr->shared_queue[global_sq_index - qid]; - ssq_info->parent_ctx.cqm_parent_ctx_obj = NULL; - } - } - -ssq_ctx_create_fail: -ssq_cmdqsync_fail: - if (global_sq_index > 0) - spfc_free_ssq(hba, global_sq_index); - - return UNF_RETURN_ERROR; -} - -static u32 spfc_create_scq(struct spfc_hba_info *hba) -{ - u32 ret = UNF_RETURN_ERROR; - u32 scq_index = 0; - u32 scq_cfg_num = 0; - struct cqm_queue *cqm_scq = NULL; - void *handle = NULL; - struct spfc_scq_info *scq_info = NULL; - struct spfc_cq_qinfo cq_qinfo; - - FC_CHECK_RETURN_VALUE(hba, UNF_RETURN_ERROR); - handle = hba->dev_handle; - /* Create SCQ by CQM interface */ - for (scq_index = 0; scq_index < SPFC_TOTAL_SCQ_NUM; scq_index++) { - /* - * 1. Create/Allocate SCQ - * * - * Notice: SCQ[0, 2, 4 ...]--->CMD SCQ, - * SCQ[1, 3, 5 ...]--->STS SCQ, - * SCQ[SPFC_TOTAL_SCQ_NUM-1]--->Defaul SCQ - */ - cqm_scq = cqm3_object_nonrdma_queue_create(handle, SERVICE_T_FC, - CQM_OBJECT_NONRDMA_SCQ, - SPFC_SCQ_IS_STS(scq_index) ? - SPFC_STS_SCQ_DEPTH : - SPFC_CMD_SCQ_DEPTH, - SPFC_SCQE_SIZE, hba); - if (!cqm_scq) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, - UNF_WARN, "[err]Create scq failed"); - - goto free_scq; - } - - /* 2. Initialize SCQ (info) */ - spfc_init_scq_info(hba, cqm_scq, scq_index, &scq_info); - - /* 3. Allocate & Initialize SCQ interrupt */ - ret = spfc_alloc_scq_int(scq_info); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[err]Allocate scq interrupt failed"); - - cqm3_object_delete(&cqm_scq->object); - memset(scq_info, 0, sizeof(struct spfc_scq_info)); - goto free_scq; - } - - /* 4. Initialize SCQ queue header */ - spfc_init_scq_header((struct wq_header *)(void *)cqm_scq->q_header_vaddr); - - /* 5. Initialize & Create SCQ CTX */ - memset(&cq_qinfo, 0, sizeof(cq_qinfo)); - spfc_cfg_scq_ctx(scq_info, &cq_qinfo); - ret = spfc_creat_scqc_via_cmdq_sync(hba, &cq_qinfo, scq_info->scqn); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[err]Create scq context failed"); - - cqm3_object_delete(&cqm_scq->object); - memset(scq_info, 0, sizeof(struct spfc_scq_info)); - goto free_scq; - } - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_INFO, - "[info]Create SCQ[%u] Scqn=%u WqeNum=%u WqeSize=%u WqePerBuf=%u CqDepth=%u CiType=%u irq=%u msix=%u", - scq_info->queue_id, scq_info->scqn, - scq_info->valid_wqe_num, scq_info->wqe_size, - scq_info->wqe_num_per_buf, scq_info->scqc_cq_depth, - scq_info->scqc_ci_type, scq_info->irq_id, - scq_info->msix_entry_idx); - } - - /* Last SCQ is used to handle SCQE delivery access when clearing buffer - */ - hba->default_scqn = scq_info->scqn; - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]Default Scqn=%u CqmScqIndex=%u", hba->default_scqn, - cqm_scq->index); - - return RETURN_OK; - -free_scq: - spfc_flush_scq_ctx(hba); - - scq_cfg_num = scq_index; - for (scq_index = 0; scq_index < scq_cfg_num; scq_index++) { - scq_info = &hba->scq_info[scq_index]; - spfc_free_scq_int(scq_info); - cqm_scq = scq_info->cqm_scq_info; - cqm3_object_delete(&cqm_scq->object); - memset(scq_info, 0, sizeof(struct spfc_scq_info)); - } - - return UNF_RETURN_ERROR; -} - -static void spfc_destroy_scq(struct spfc_hba_info *hba) -{ - u32 scq_index = 0; - struct cqm_queue *cqm_scq = NULL; - struct spfc_scq_info *scq_info = NULL; - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]Start destroy total %d SCQ", SPFC_TOTAL_SCQ_NUM); - - FC_CHECK_RETURN_VOID(hba); - - /* Use CQM to delete SCQ */ - for (scq_index = 0; scq_index < SPFC_TOTAL_SCQ_NUM; scq_index++) { - scq_info = &hba->scq_info[scq_index]; - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ALL, - "[info]Destroy SCQ%u, Scqn=%u, Irq=%u, msix=%u, name=%s", - scq_index, scq_info->scqn, scq_info->irq_id, - scq_info->msix_entry_idx, scq_info->irq_name); - - spfc_free_scq_int(scq_info); - cqm_scq = scq_info->cqm_scq_info; - cqm3_object_delete(&cqm_scq->object); - memset(scq_info, 0, sizeof(struct spfc_scq_info)); - } -} - -static void spfc_init_srq_info(struct spfc_hba_info *hba, struct cqm_queue *cqm_srq, - struct spfc_srq_info *srq_info) -{ - FC_CHECK_RETURN_VOID(hba); - FC_CHECK_RETURN_VOID(cqm_srq); - FC_CHECK_RETURN_VOID(srq_info); - - srq_info->hba = (void *)hba; - - srq_info->cqm_srq_info = cqm_srq; - srq_info->wqe_num_per_buf = cqm_srq->q_room_buf_1.buf_size / SPFC_SRQE_SIZE - 1; - srq_info->wqe_size = SPFC_SRQE_SIZE; - srq_info->valid_wqe_num = cqm_srq->valid_wqe_num; - srq_info->pi = 0; - srq_info->pi_owner = SPFC_SRQ_INIT_LOOP_O; - srq_info->pmsn = 0; - srq_info->srqn = cqm_srq->index; - srq_info->first_rqe_recv_dma = 0; - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]Init srq info(srq index 0x%x) valid wqe num 0x%x, buffer size 0x%x, wqe num per buf 0x%x", - cqm_srq->index, srq_info->valid_wqe_num, - cqm_srq->q_room_buf_1.buf_size, srq_info->wqe_num_per_buf); -} - -static void spfc_init_srq_header(struct wq_header *queue_header) -{ - FC_CHECK_RETURN_VOID(queue_header); - - memset(queue_header, 0, sizeof(struct wq_header)); -} - -/* - *Function Name : spfc_get_srq_entry - *Function Description: Obtain RQE in SRQ via PI. - *Input Parameters : *srq_info, - * **linked_rqe, - * position - *Output Parameters : N/A - *Return Type : struct spfc_rqe* - */ -static struct spfc_rqe *spfc_get_srq_entry(struct spfc_srq_info *srq_info, - struct spfc_rqe **linked_rqe, u16 position) -{ - u32 buf_id = 0; - u32 wqe_num_per_buf = 0; - u16 buf_offset = 0; - struct cqm_buf_list *buf = NULL; - - FC_CHECK_RETURN_VALUE(srq_info, NULL); - - wqe_num_per_buf = srq_info->wqe_num_per_buf; - - buf_id = position / wqe_num_per_buf; - buf = &srq_info->cqm_srq_info->q_room_buf_1.buf_list[buf_id]; - buf_offset = position % ((u16)wqe_num_per_buf); - - if (buf_offset + 1 == wqe_num_per_buf) - *linked_rqe = (struct spfc_rqe *)(buf->va) + wqe_num_per_buf; - else - *linked_rqe = NULL; - - return (struct spfc_rqe *)(buf->va) + buf_offset; -} - -void spfc_post_els_srq_wqe(struct spfc_srq_info *srq_info, u16 buf_id) -{ - struct spfc_rqe *rqe = NULL; - struct spfc_rqe tmp_rqe; - struct spfc_rqe *linked_rqe = NULL; - struct wq_header *wq_header = NULL; - struct spfc_drq_buff_entry *buff_entry = NULL; - - FC_CHECK_RETURN_VOID(srq_info); - FC_CHECK_RETURN_VOID(buf_id < srq_info->valid_wqe_num); - - buff_entry = srq_info->els_buff_entry_head + buf_id; - - spin_lock(&srq_info->srq_spin_lock); - - /* Obtain RQE, not include link wqe */ - rqe = spfc_get_srq_entry(srq_info, &linked_rqe, srq_info->pi); - if (!rqe) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]post els srq,get srqe failed, valid wqe num 0x%x, pi 0x%x, pmsn 0x%x", - srq_info->valid_wqe_num, srq_info->pi, - srq_info->pmsn); - - spin_unlock(&srq_info->srq_spin_lock); - return; - } - - /* Initialize RQE */ - /* cs section is not used */ - memset(&tmp_rqe, 0, sizeof(struct spfc_rqe)); - - /* default Obit is invalid, and set valid finally */ - spfc_build_srq_wqe_ctrls(&tmp_rqe, !srq_info->pi_owner, srq_info->pmsn + 1); - - tmp_rqe.bds_sl.buf_addr_hi = SPFC_HIGH_32_BITS(buff_entry->buff_dma); - tmp_rqe.bds_sl.buf_addr_lo = SPFC_LOW_32_BITS(buff_entry->buff_dma); - tmp_rqe.drv_sl.wd0.user_id = buf_id; - - /* convert to big endian */ - spfc_cpu_to_big32(&tmp_rqe, sizeof(struct spfc_rqe)); - - memcpy(rqe, &tmp_rqe, sizeof(struct spfc_rqe)); - - /* reset Obit */ - spfc_set_srq_wqe_owner_be((struct spfc_wqe_ctrl *)(void *)(&rqe->ctrl_sl), - srq_info->pi_owner); - - if (linked_rqe) { - /* Update Obit in linked WQE */ - spfc_set_srq_link_wqe_owner_be((struct spfc_linkwqe *)(void *)linked_rqe, - srq_info->pi_owner, srq_info->pmsn + 1); - } - - /* Update PI and PMSN */ - spfc_update_producer_info((u16)(srq_info->valid_wqe_num), - &srq_info->pi, &srq_info->pi_owner); - - /* pmsn is 16bit. The value is added to the maximum value and is - * automatically reversed - */ - srq_info->pmsn++; - - /* Update pmsn in queue header */ - wq_header = (struct wq_header *)(void *)srq_info->cqm_srq_info->q_header_vaddr; - spfc_update_srq_header(&wq_header->db_record, srq_info->pmsn); - - spin_unlock(&srq_info->srq_spin_lock); -} - -/* - *Function Name : spfc_cfg_srq_ctx - *Function Description: Initialize the CTX of the SRQ that receives the - * immediate data. The RQE of the SRQ - * needs to be - *initialized when the RQE is filled. Input Parameters : *srq_info, *srq_ctx, - * sge_size, - * rqe_gpa - *Output Parameters : N/A - *Return Type : void - */ -static void spfc_cfg_srq_ctx(struct spfc_srq_info *srq_info, - struct spfc_srq_ctx *ctx, u32 sge_size, - u64 rqe_gpa) -{ - struct spfc_srq_ctx *srq_ctx = NULL; - struct cqm_queue *cqm_srq_info = NULL; - struct spfc_queue_info_bus queue_bus; - - FC_CHECK_RETURN_VOID(srq_info); - FC_CHECK_RETURN_VOID(ctx); - - cqm_srq_info = srq_info->cqm_srq_info; - srq_ctx = ctx; - srq_ctx->last_rq_pmsn = 0; - srq_ctx->cur_rqe_msn = 0; - srq_ctx->pcie_template = 0; - /* The value of CTX needs to be updated - *when RQE is configured - */ - srq_ctx->cur_rqe_gpa = rqe_gpa; - srq_ctx->cur_sge_v = 0; - srq_ctx->cur_sge_l = 0; - /* The information received by the SRQ is reported through the - *SCQ. The interrupt and ArmCQ are disabled. - */ - srq_ctx->int_mode = 0; - srq_ctx->ceqn_msix = 0; - srq_ctx->cur_sge_remain_len = 0; - srq_ctx->cur_sge_id = 0; - srq_ctx->consant_sge_len = sge_size; - srq_ctx->cur_wqe_o = 0; - srq_ctx->pmsn_type = SPFC_PMSN_CI_TYPE_FROM_HOST; - srq_ctx->bdsl = 0; - srq_ctx->cr = 0; - srq_ctx->csl = 0; - srq_ctx->cf = 0; - srq_ctx->ctrl_sl = 0; - srq_ctx->cur_sge_gpa = 0; - srq_ctx->cur_pmsn_gpa = cqm_srq_info->q_header_paddr; - srq_ctx->prefetch_max_masn = 0; - srq_ctx->cqe_max_cnt = 0; - srq_ctx->cur_cqe_cnt = 0; - srq_ctx->arm_q = 0; - srq_ctx->cq_so_ro = 0; - srq_ctx->cqe_dma_attr_idx = 0; - srq_ctx->rq_so_ro = 0; - srq_ctx->rqe_dma_attr_idx = 0; - srq_ctx->loop_o = SPFC_SRQ_INIT_LOOP_O; - srq_ctx->ring = SPFC_QUEUE_RING; - - memset(&queue_bus, 0, sizeof(struct spfc_queue_info_bus)); - queue_bus.bus[ARRAY_INDEX_0] |= ((u64)(cqm_srq_info->q_ctx_paddr >> UNF_SHIFT_4)); - queue_bus.bus[ARRAY_INDEX_0] |= (((u64)(srq_ctx->rqe_dma_attr_idx & - SPFC_SRQ_CTX_rqe_dma_attr_idx_MASK)) - << UNF_SHIFT_60); /* bits 4 */ - - queue_bus.bus[ARRAY_INDEX_1] |= ((u64)(srq_ctx->rqe_dma_attr_idx >> UNF_SHIFT_4)); - queue_bus.bus[ARRAY_INDEX_1] |= (((u64)(srq_ctx->rq_so_ro)) << UNF_SHIFT_2); /* bits 2 */ - queue_bus.bus[ARRAY_INDEX_1] |= (((u64)(srq_ctx->cur_pmsn_gpa >> UNF_SHIFT_4)) - << UNF_SHIFT_4); /* bits 60 */ - - queue_bus.bus[ARRAY_INDEX_2] |= ((u64)(srq_ctx->consant_sge_len)); /* bits 17 */ - queue_bus.bus[ARRAY_INDEX_2] |= (((u64)(srq_ctx->pcie_template)) << UNF_SHIFT_17); - - srq_ctx->parity = spfc_get_parity_value((void *)queue_bus.bus, SPFC_SRQC_BUS_ROW, - SPFC_SRQC_BUS_COL); - - spfc_cpu_to_big64((void *)srq_ctx, sizeof(struct spfc_srq_ctx)); -} - -static u32 spfc_creat_srqc_via_cmdq_sync(struct spfc_hba_info *hba, - struct spfc_srq_ctx *srqc, - u64 ctx_gpa) -{ -#define SPFC_INIT_SRQC_TIMEOUT 3000 - - int ret; - u32 covrt_size; - struct spfc_cmdqe_creat_srqc init_srq_cmd; - struct sphw_cmd_buf *cmdq_in_buf; - - cmdq_in_buf = sphw_alloc_cmd_buf(hba->dev_handle); - if (!cmdq_in_buf) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[err]cmdq in_cmd_buf alloc failed"); - - SPFC_ERR_IO_STAT(hba, SPFC_TASK_T_INIT_SRQC); - return UNF_RETURN_ERROR; - } - - memset(&init_srq_cmd, 0, sizeof(init_srq_cmd)); - init_srq_cmd.wd0.task_type = SPFC_TASK_T_INIT_SRQC; - init_srq_cmd.srqc_gpa_h = SPFC_HIGH_32_BITS(ctx_gpa); - init_srq_cmd.srqc_gpa_l = SPFC_LOW_32_BITS(ctx_gpa); - covrt_size = sizeof(init_srq_cmd) - sizeof(init_srq_cmd.srqc); - spfc_cpu_to_big32(&init_srq_cmd, covrt_size); - - /* srqc is already big-endian */ - memcpy(init_srq_cmd.srqc, srqc, sizeof(*srqc)); - memcpy(cmdq_in_buf->buf, &init_srq_cmd, sizeof(init_srq_cmd)); - cmdq_in_buf->size = sizeof(init_srq_cmd); - - ret = sphw_cmdq_detail_resp(hba->dev_handle, COMM_MOD_FC, 0, - cmdq_in_buf, NULL, NULL, - SPFC_INIT_SRQC_TIMEOUT, SPHW_CHANNEL_FC); - - sphw_free_cmd_buf(hba->dev_handle, cmdq_in_buf); - - if (ret) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[err]Send creat srqc via cmdq failed, ret=%d", - ret); - - SPFC_ERR_IO_STAT(hba, SPFC_TASK_T_INIT_SRQC); - return UNF_RETURN_ERROR; - } - - SPFC_IO_STAT(hba, SPFC_TASK_T_INIT_SRQC); - - return RETURN_OK; -} - -static void spfc_init_els_srq_wqe(struct spfc_srq_info *srq_info) -{ - u32 rqe_index = 0; - struct spfc_drq_buff_entry *buf_entry = NULL; - - FC_CHECK_RETURN_VOID(srq_info); - - for (rqe_index = 0; rqe_index < srq_info->valid_wqe_num - 1; rqe_index++) { - buf_entry = srq_info->els_buff_entry_head + rqe_index; - spfc_post_els_srq_wqe(srq_info, buf_entry->buff_id); - } -} - -static void spfc_free_els_srq_buff(struct spfc_hba_info *hba, u32 srq_valid_wqe) -{ - u32 buff_index = 0; - struct spfc_srq_info *srq_info = NULL; - struct spfc_drq_buff_entry *buff_entry = NULL; - - FC_CHECK_RETURN_VOID(hba); - - srq_info = &hba->els_srq_info; - - if (!srq_info->els_buff_entry_head) - return; - - for (buff_index = 0; buff_index < srq_valid_wqe; buff_index++) { - buff_entry = &srq_info->els_buff_entry_head[buff_index]; - buff_entry->buff_addr = NULL; - } - - if (srq_info->buf_list.buflist) { - for (buff_index = 0; buff_index < srq_info->buf_list.buf_num; - buff_index++) { - if (srq_info->buf_list.buflist[buff_index].paddr != 0) { - pci_unmap_single(hba->pci_dev, - srq_info->buf_list.buflist[buff_index].paddr, - srq_info->buf_list.buf_size, - DMA_FROM_DEVICE); - srq_info->buf_list.buflist[buff_index].paddr = 0; - } - kfree(srq_info->buf_list.buflist[buff_index].vaddr); - srq_info->buf_list.buflist[buff_index].vaddr = NULL; - } - - kfree(srq_info->buf_list.buflist); - srq_info->buf_list.buflist = NULL; - } - - kfree(srq_info->els_buff_entry_head); - srq_info->els_buff_entry_head = NULL; -} - -static u32 spfc_alloc_els_srq_buff(struct spfc_hba_info *hba, u32 srq_valid_wqe) -{ - u32 req_buff_size = 0; - u32 buff_index = 0; - struct spfc_srq_info *srq_info = NULL; - struct spfc_drq_buff_entry *buff_entry = NULL; - u32 buf_total_size; - u32 buf_num; - u32 alloc_idx; - u32 cur_buf_idx = 0; - u32 cur_buf_offset = 0; - u32 buf_cnt_perhugebuf; - - srq_info = &hba->els_srq_info; - - /* Apply for entry buffer */ - req_buff_size = (u32)(srq_valid_wqe * sizeof(struct spfc_drq_buff_entry)); - srq_info->els_buff_entry_head = (struct spfc_drq_buff_entry *)kmalloc(req_buff_size, - GFP_KERNEL); - if (!srq_info->els_buff_entry_head) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[err]Allocate ELS Srq receive buffer entries failed"); - - return UNF_RETURN_ERROR; - } - memset(srq_info->els_buff_entry_head, 0, req_buff_size); - - buf_total_size = SPFC_SRQ_ELS_SGE_LEN * srq_valid_wqe; - - srq_info->buf_list.buf_size = buf_total_size > BUF_LIST_PAGE_SIZE - ? BUF_LIST_PAGE_SIZE - : buf_total_size; - buf_cnt_perhugebuf = srq_info->buf_list.buf_size / SPFC_SRQ_ELS_SGE_LEN; - buf_num = srq_valid_wqe % buf_cnt_perhugebuf ? - srq_valid_wqe / buf_cnt_perhugebuf + 1 : - srq_valid_wqe / buf_cnt_perhugebuf; - srq_info->buf_list.buflist = (struct buff_list *)kmalloc(buf_num * sizeof(struct buff_list), - GFP_KERNEL); - srq_info->buf_list.buf_num = buf_num; - - if (!srq_info->buf_list.buflist) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[err]Allocate ELS buf list failed out of memory"); - goto free_buff; - } - memset(srq_info->buf_list.buflist, 0, buf_num * sizeof(struct buff_list)); - - for (alloc_idx = 0; alloc_idx < buf_num; alloc_idx++) { - srq_info->buf_list.buflist[alloc_idx].vaddr = kmalloc(srq_info->buf_list.buf_size, - GFP_KERNEL); - if (!srq_info->buf_list.buflist[alloc_idx].vaddr) - goto free_buff; - - memset(srq_info->buf_list.buflist[alloc_idx].vaddr, 0, srq_info->buf_list.buf_size); - - srq_info->buf_list.buflist[alloc_idx].paddr = - pci_map_single(hba->pci_dev, srq_info->buf_list.buflist[alloc_idx].vaddr, - srq_info->buf_list.buf_size, DMA_FROM_DEVICE); - if (pci_dma_mapping_error(hba->pci_dev, - srq_info->buf_list.buflist[alloc_idx].paddr)) { - srq_info->buf_list.buflist[alloc_idx].paddr = 0; - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[err]Map els srq buffer failed"); - - goto free_buff; - } - } - - /* Apply for receiving buffer and attach it to the free linked list */ - for (buff_index = 0; buff_index < srq_valid_wqe; buff_index++) { - buff_entry = &srq_info->els_buff_entry_head[buff_index]; - cur_buf_idx = buff_index / buf_cnt_perhugebuf; - cur_buf_offset = SPFC_SRQ_ELS_SGE_LEN * (buff_index % buf_cnt_perhugebuf); - buff_entry->buff_addr = srq_info->buf_list.buflist[cur_buf_idx].vaddr + - cur_buf_offset; - buff_entry->buff_dma = srq_info->buf_list.buflist[cur_buf_idx].paddr + - cur_buf_offset; - buff_entry->buff_id = (u16)buff_index; - } - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_INFO, - "[EVENT]Allocate bufnum:%u,buf_total_size:%u", buf_num, - buf_total_size); - - return RETURN_OK; - -free_buff: - spfc_free_els_srq_buff(hba, srq_valid_wqe); - return UNF_RETURN_ERROR; -} - -void spfc_send_clear_srq_cmd(struct spfc_hba_info *hba, - struct spfc_srq_info *srq_info) -{ - union spfc_cmdqe cmdqe; - struct cqm_queue *cqm_fcp_srq = NULL; - ulong flag = 0; - - memset(&cmdqe, 0, sizeof(union spfc_cmdqe)); - - spin_lock_irqsave(&srq_info->srq_spin_lock, flag); - cqm_fcp_srq = srq_info->cqm_srq_info; - if (!cqm_fcp_srq) { - srq_info->state = SPFC_CLEAN_DONE; - spin_unlock_irqrestore(&srq_info->srq_spin_lock, flag); - return; - } - - cmdqe.clear_srq.wd0.task_type = SPFC_TASK_T_CLEAR_SRQ; - cmdqe.clear_srq.wd1.scqn = SPFC_LSW(hba->default_scqn); - cmdqe.clear_srq.wd1.srq_type = srq_info->srq_type; - cmdqe.clear_srq.srqc_gpa_h = SPFC_HIGH_32_BITS(cqm_fcp_srq->q_ctx_paddr); - cmdqe.clear_srq.srqc_gpa_l = SPFC_LOW_32_BITS(cqm_fcp_srq->q_ctx_paddr); - - (void)queue_delayed_work(hba->work_queue, &srq_info->del_work, - (ulong)msecs_to_jiffies(SPFC_SRQ_DEL_STAGE_TIMEOUT_MS)); - spin_unlock_irqrestore(&srq_info->srq_spin_lock, flag); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]Port 0x%x begin to clear srq 0x%x(0x%x,0x%llx)", - hba->port_cfg.port_id, srq_info->srq_type, - SPFC_LSW(hba->default_scqn), - (u64)cqm_fcp_srq->q_ctx_paddr); - - /* Run the ROOT CMDQ command to issue the clear srq command. If the - * command fails to be delivered, retry upon timeout. - */ - (void)spfc_root_cmdq_enqueue(hba, &cmdqe, sizeof(cmdqe.clear_srq)); -} - -/* - *Function Name : spfc_srq_clr_timeout - *Function Description: Delete srq when timeout. - *Input Parameters : *work - *Output Parameters : N/A - *Return Type : void - */ -static void spfc_srq_clr_timeout(struct work_struct *work) -{ -#define SPFC_MAX_DEL_SRQ_RETRY_TIMES 2 - struct spfc_srq_info *srq = NULL; - struct spfc_hba_info *hba = NULL; - struct cqm_queue *cqm_fcp_imm_srq = NULL; - ulong flag = 0; - - srq = container_of(work, struct spfc_srq_info, del_work.work); - - spin_lock_irqsave(&srq->srq_spin_lock, flag); - hba = srq->hba; - cqm_fcp_imm_srq = srq->cqm_srq_info; - spin_unlock_irqrestore(&srq->srq_spin_lock, flag); - - if (hba && cqm_fcp_imm_srq) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[warn]Port 0x%x clear srq 0x%x stat 0x%x timeout", - hba->port_cfg.port_id, srq->srq_type, srq->state); - - /* If the delivery fails or the execution times out after the - * delivery, try again once - */ - srq->del_retry_time++; - if (srq->del_retry_time < SPFC_MAX_DEL_SRQ_RETRY_TIMES) - spfc_send_clear_srq_cmd(hba, srq); - else - srq->del_retry_time = 0; - } -} - -static u32 spfc_create_els_srq(struct spfc_hba_info *hba) -{ - u32 ret = UNF_RETURN_ERROR; - struct cqm_queue *cqm_srq = NULL; - struct wq_header *wq_header = NULL; - struct spfc_srq_info *srq_info = NULL; - struct spfc_srq_ctx srq_ctx = {0}; - - FC_CHECK_RETURN_VALUE(hba, UNF_RETURN_ERROR); - - cqm_srq = cqm3_object_fc_srq_create(hba->dev_handle, SERVICE_T_FC, - CQM_OBJECT_NONRDMA_SRQ, SPFC_SRQ_ELS_DATA_DEPTH, - SPFC_SRQE_SIZE, hba); - if (!cqm_srq) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[err]Create Els Srq failed"); - - return UNF_RETURN_ERROR; - } - - /* Initialize SRQ */ - srq_info = &hba->els_srq_info; - spfc_init_srq_info(hba, cqm_srq, srq_info); - srq_info->srq_type = SPFC_SRQ_ELS; - srq_info->enable = true; - srq_info->state = SPFC_CLEAN_DONE; - srq_info->del_retry_time = 0; - - /* The srq lock is initialized and can be created repeatedly */ - spin_lock_init(&srq_info->srq_spin_lock); - srq_info->spin_lock_init = true; - - /* Initialize queue header */ - wq_header = (struct wq_header *)(void *)cqm_srq->q_header_vaddr; - spfc_init_srq_header(wq_header); - INIT_DELAYED_WORK(&srq_info->del_work, spfc_srq_clr_timeout); - - /* Apply for RQ buffer */ - ret = spfc_alloc_els_srq_buff(hba, srq_info->valid_wqe_num); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[err]Allocate Els Srq buffer failed"); - - cqm3_object_delete(&cqm_srq->object); - memset(srq_info, 0, sizeof(struct spfc_srq_info)); - return UNF_RETURN_ERROR; - } - - /* Fill RQE, update queue header */ - spfc_init_els_srq_wqe(srq_info); - - /* Fill SRQ CTX */ - memset(&srq_ctx, 0, sizeof(srq_ctx)); - spfc_cfg_srq_ctx(srq_info, &srq_ctx, SPFC_SRQ_ELS_SGE_LEN, - srq_info->cqm_srq_info->q_room_buf_1.buf_list->pa); - - ret = spfc_creat_srqc_via_cmdq_sync(hba, &srq_ctx, srq_info->cqm_srq_info->q_ctx_paddr); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Creat Els Srqc failed"); - - spfc_free_els_srq_buff(hba, srq_info->valid_wqe_num); - cqm3_object_delete(&cqm_srq->object); - memset(srq_info, 0, sizeof(struct spfc_srq_info)); - - return UNF_RETURN_ERROR; - } - - return RETURN_OK; -} - -void spfc_wq_destroy_els_srq(struct work_struct *work) -{ - struct spfc_hba_info *hba = NULL; - - FC_CHECK_RETURN_VOID(work); - hba = - container_of(work, struct spfc_hba_info, els_srq_clear_work); - spfc_destroy_els_srq(hba); -} - -void spfc_destroy_els_srq(void *handle) -{ - /* - * Receive clear els srq sts - * ---then--->>> destroy els srq - */ - struct spfc_srq_info *srq_info = NULL; - struct spfc_hba_info *hba = NULL; - - FC_CHECK_RETURN_VOID(handle); - - hba = (struct spfc_hba_info *)handle; - srq_info = &hba->els_srq_info; - - /* release receive buffer */ - spfc_free_els_srq_buff(hba, srq_info->valid_wqe_num); - - /* release srq info */ - if (srq_info->cqm_srq_info) { - cqm3_object_delete(&srq_info->cqm_srq_info->object); - srq_info->cqm_srq_info = NULL; - } - if (srq_info->spin_lock_init) - srq_info->spin_lock_init = false; - srq_info->hba = NULL; - srq_info->enable = false; - srq_info->state = SPFC_CLEAN_DONE; -} - -/* - *Function Name : spfc_create_srq - *Function Description: Create SRQ, which contains four SRQ for receiving - * instant data and a SRQ for receiving - * ELS data. - *Input Parameters : *hba Output Parameters : N/A Return Type :u32 - */ -static u32 spfc_create_srq(struct spfc_hba_info *hba) -{ - u32 ret = UNF_RETURN_ERROR; - - FC_CHECK_RETURN_VALUE(hba, UNF_RETURN_ERROR); - - /* Create ELS SRQ */ - ret = spfc_create_els_srq(hba); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[err]Create Els Srq failed"); - return UNF_RETURN_ERROR; - } - - return RETURN_OK; -} - -/* - *Function Name : spfc_destroy_srq - *Function Description: Release the SRQ resource, including the SRQ for - * receiving the immediate data and the - * SRQ forreceiving the ELS data. - *Input Parameters : *hba Output Parameters : N/A - *Return Type : void - */ -static void spfc_destroy_srq(struct spfc_hba_info *hba) -{ - FC_CHECK_RETURN_VOID(hba); - - spfc_destroy_els_srq(hba); -} - -u32 spfc_create_common_share_queues(void *handle) -{ - u32 ret = UNF_RETURN_ERROR; - struct spfc_hba_info *hba = NULL; - - FC_CHECK_RETURN_VALUE(handle, UNF_RETURN_ERROR); - hba = (struct spfc_hba_info *)handle; - /* Create & Init 8 pairs SCQ */ - ret = spfc_create_scq(hba); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[err]Create scq failed"); - - return UNF_RETURN_ERROR; - } - - /* Alloc SRQ resource for SIRT & ELS */ - ret = spfc_create_srq(hba); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[err]Create srq failed"); - - spfc_flush_scq_ctx(hba); - spfc_destroy_scq(hba); - - return UNF_RETURN_ERROR; - } - - return RETURN_OK; -} - -void spfc_destroy_common_share_queues(void *hba) -{ - FC_CHECK_RETURN_VOID(hba); - - spfc_destroy_scq((struct spfc_hba_info *)hba); - spfc_destroy_srq((struct spfc_hba_info *)hba); -} - -static u8 spfc_map_fcp_data_cos(struct spfc_hba_info *hba) -{ - u8 i = 0; - u8 min_cnt_index = SPFC_PACKET_COS_FC_DATA; - bool get_init_index = false; - - for (i = 0; i < SPFC_MAX_COS_NUM; i++) { - /* Check whether the CoS is valid for the FC and cannot be - * occupied by the CMD - */ - if ((!(hba->cos_bitmap & ((u32)1 << i))) || i == SPFC_PACKET_COS_FC_CMD) - continue; - - if (!get_init_index) { - min_cnt_index = i; - get_init_index = true; - continue; - } - - if (atomic_read(&hba->cos_rport_cnt[i]) < - atomic_read(&hba->cos_rport_cnt[min_cnt_index])) - min_cnt_index = i; - } - - atomic_inc(&hba->cos_rport_cnt[min_cnt_index]); - - return min_cnt_index; -} - -static void spfc_update_cos_rport_cnt(struct spfc_hba_info *hba, u8 cos_index) -{ - if (cos_index >= SPFC_MAX_COS_NUM || - cos_index == SPFC_PACKET_COS_FC_CMD || - (!(hba->cos_bitmap & ((u32)1 << cos_index))) || - (atomic_read(&hba->cos_rport_cnt[cos_index]) == 0)) - return; - - atomic_dec(&hba->cos_rport_cnt[cos_index]); -} - -void spfc_invalid_parent_sq(struct spfc_parent_sq_info *sq_info) -{ - sq_info->rport_index = INVALID_VALUE32; - sq_info->context_id = INVALID_VALUE32; - sq_info->sq_queue_id = INVALID_VALUE32; - sq_info->cache_id = INVALID_VALUE32; - sq_info->local_port_id = INVALID_VALUE32; - sq_info->remote_port_id = INVALID_VALUE32; - sq_info->hba = NULL; - sq_info->del_start_jiff = INVALID_VALUE64; - sq_info->port_in_flush = false; - sq_info->sq_in_sess_rst = false; - sq_info->oqid_rd = INVALID_VALUE16; - sq_info->oqid_wr = INVALID_VALUE16; - sq_info->srq_ctx_addr = 0; - sq_info->sqn_base = 0; - atomic_set(&sq_info->sq_cached, false); - sq_info->vport_id = 0; - sq_info->sirt_dif_control.protect_opcode = UNF_DIF_ACTION_NONE; - sq_info->need_offloaded = INVALID_VALUE8; - atomic_set(&sq_info->sq_valid, false); - atomic_set(&sq_info->flush_done_wait_cnt, 0); - memset(&sq_info->delay_sqe, 0, sizeof(struct spfc_delay_sqe_ctrl_info)); - memset(sq_info->io_stat, 0, sizeof(sq_info->io_stat)); -} - -static void spfc_parent_sq_opreate_timeout(struct work_struct *work) -{ - ulong flag = 0; - struct spfc_parent_sq_info *parent_sq = NULL; - struct spfc_parent_queue_info *parent_queue = NULL; - struct spfc_hba_info *hba = NULL; - - FC_CHECK_RETURN_VOID(work); - - parent_sq = container_of(work, struct spfc_parent_sq_info, del_work.work); - parent_queue = container_of(parent_sq, struct spfc_parent_queue_info, parent_sq_info); - hba = (struct spfc_hba_info *)parent_sq->hba; - FC_CHECK_RETURN_VOID(hba); - - spin_lock_irqsave(&parent_queue->parent_queue_state_lock, flag); - if (parent_queue->offload_state == SPFC_QUEUE_STATE_DESTROYING) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "Port(0x%x) sq rport index(0x%x) local nportid(0x%x),remote nportid(0x%x) reset timeout.", - hba->port_cfg.port_id, parent_sq->rport_index, - parent_sq->local_port_id, - parent_sq->remote_port_id); - } - spin_unlock_irqrestore(&parent_queue->parent_queue_state_lock, flag); -} - -static void spfc_parent_sq_wait_flush_done_timeout(struct work_struct *work) -{ - ulong flag = 0; - struct spfc_parent_sq_info *parent_sq = NULL; - struct spfc_parent_queue_info *parent_queue = NULL; - struct spfc_hba_info *hba = NULL; - u32 ctx_flush_done; - u32 *ctx_dw = NULL; - int ret; - int sq_state = SPFC_STAT_PARENT_SQ_QUEUE_DELAYED_WORK; - spinlock_t *prtq_state_lock = NULL; - - FC_CHECK_RETURN_VOID(work); - - parent_sq = container_of(work, struct spfc_parent_sq_info, flush_done_timeout_work.work); - - FC_CHECK_RETURN_VOID(parent_sq); - - parent_queue = container_of(parent_sq, struct spfc_parent_queue_info, parent_sq_info); - prtq_state_lock = &parent_queue->parent_queue_state_lock; - hba = (struct spfc_hba_info *)parent_sq->hba; - FC_CHECK_RETURN_VOID(hba); - FC_CHECK_RETURN_VOID(parent_queue); - - spin_lock_irqsave(prtq_state_lock, flag); - if (parent_queue->offload_state != SPFC_QUEUE_STATE_DESTROYING) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) sq rport index(0x%x) is not destroying status,offloadsts is %d", - hba->port_cfg.port_id, parent_sq->rport_index, - parent_queue->offload_state); - spin_unlock_irqrestore(prtq_state_lock, flag); - return; - } - - if (parent_queue->parent_ctx.cqm_parent_ctx_obj) { - ctx_dw = (u32 *)((void *)(parent_queue->parent_ctx.cqm_parent_ctx_obj->vaddr)); - ctx_flush_done = ctx_dw[SPFC_CTXT_FLUSH_DONE_DW_POS] & SPFC_CTXT_FLUSH_DONE_MASK_BE; - if (ctx_flush_done == 0) { - spin_unlock_irqrestore(prtq_state_lock, flag); - - if (atomic_read(&parent_queue->parent_sq_info.flush_done_wait_cnt) < - SPFC_SQ_WAIT_FLUSH_DONE_TIMEOUT_CNT) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[info]Port(0x%x) sq rport index(0x%x) wait flush done timeout %d times", - hba->port_cfg.port_id, parent_sq->rport_index, - atomic_read(&(parent_queue->parent_sq_info - .flush_done_wait_cnt))); - - atomic_inc(&parent_queue->parent_sq_info.flush_done_wait_cnt); - - /* Delay Free Sq info */ - ret = queue_delayed_work(hba->work_queue, - &(parent_queue->parent_sq_info - .flush_done_timeout_work), - (ulong)msecs_to_jiffies((u32) - SPFC_SQ_WAIT_FLUSH_DONE_TIMEOUT_MS)); - if (!ret) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) rport(0x%x) queue delayed work failed ret:%d", - hba->port_cfg.port_id, - parent_sq->rport_index, ret); - SPFC_HBA_STAT(hba, sq_state); - } - - return; - } - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) sq rport index(0x%x) has wait flush done %d times,do not free sq", - hba->port_cfg.port_id, - parent_sq->rport_index, - atomic_read(&(parent_queue->parent_sq_info - .flush_done_wait_cnt))); - - SPFC_HBA_STAT(hba, SPFC_STAT_CTXT_FLUSH_DONE); - return; - } - } - - spin_unlock_irqrestore(prtq_state_lock, flag); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x) sq rport index(0x%x) flush done bit is ok,free sq now", - hba->port_cfg.port_id, parent_sq->rport_index); - - spfc_free_parent_queue_info(hba, parent_queue); -} - -static void spfc_free_parent_sq(struct spfc_hba_info *hba, - struct spfc_parent_queue_info *parq_info) -{ -#define SPFC_WAIT_PRT_CTX_FUSH_DONE_LOOP_TIMES 100 - u32 ctx_flush_done = 0; - u32 *ctx_dw = NULL; - struct spfc_parent_sq_info *sq_info = NULL; - u32 uidelaycnt = 0; - struct list_head *list = NULL; - struct spfc_suspend_sqe_info *suspend_sqe = NULL; - - sq_info = &parq_info->parent_sq_info; - - while (!list_empty(&sq_info->suspend_sqe_list)) { - list = UNF_OS_LIST_NEXT(&sq_info->suspend_sqe_list); - list_del(list); - suspend_sqe = list_entry(list, struct spfc_suspend_sqe_info, list_sqe_entry); - if (suspend_sqe) { - if (!cancel_delayed_work(&suspend_sqe->timeout_work)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[warn]reset worker timer maybe timeout"); - } - - kfree(suspend_sqe); - } - } - - /* Free data cos */ - spfc_update_cos_rport_cnt(hba, parq_info->queue_data_cos); - - if (parq_info->parent_ctx.cqm_parent_ctx_obj) { - ctx_dw = (u32 *)((void *)(parq_info->parent_ctx.cqm_parent_ctx_obj->vaddr)); - ctx_flush_done = ctx_dw[SPFC_CTXT_FLUSH_DONE_DW_POS] & SPFC_CTXT_FLUSH_DONE_MASK_BE; - mb(); - if (parq_info->offload_state == SPFC_QUEUE_STATE_DESTROYING && - ctx_flush_done == 0) { - do { - ctx_flush_done = ctx_dw[SPFC_CTXT_FLUSH_DONE_DW_POS] & - SPFC_CTXT_FLUSH_DONE_MASK_BE; - mb(); - if (ctx_flush_done != 0) - break; - uidelaycnt++; - } while (uidelaycnt < SPFC_WAIT_PRT_CTX_FUSH_DONE_LOOP_TIMES); - - if (ctx_flush_done == 0) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[warn]Port(0x%x) Rport(0x%x) flush done is not set", - hba->port_cfg.port_id, - sq_info->rport_index); - } - } - - cqm3_object_delete(&parq_info->parent_ctx.cqm_parent_ctx_obj->object); - parq_info->parent_ctx.cqm_parent_ctx_obj = NULL; - } - - spfc_invalid_parent_sq(sq_info); -} - -u32 spfc_alloc_parent_sq(struct spfc_hba_info *hba, - struct spfc_parent_queue_info *parq_info, - struct unf_port_info *rport_info) -{ - struct spfc_parent_sq_info *sq_ctrl = NULL; - struct cqm_qpc_mpt *prnt_ctx = NULL; - ulong flag = 0; - - /* Craete parent context via CQM */ - prnt_ctx = cqm3_object_qpc_mpt_create(hba->dev_handle, SERVICE_T_FC, - CQM_OBJECT_SERVICE_CTX, SPFC_CNTX_SIZE_256B, - parq_info, CQM_INDEX_INVALID); - if (!prnt_ctx) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Create parent context failed, CQM_INDEX is 0x%x", - CQM_INDEX_INVALID); - goto parent_create_fail; - } - - parq_info->parent_ctx.cqm_parent_ctx_obj = prnt_ctx; - /* Initialize struct spfc_parent_sq_info */ - sq_ctrl = &parq_info->parent_sq_info; - sq_ctrl->hba = (void *)hba; - sq_ctrl->rport_index = rport_info->rport_index; - sq_ctrl->sqn_base = rport_info->sqn_base; - sq_ctrl->context_id = prnt_ctx->xid; - sq_ctrl->sq_queue_id = SPFC_QID_SQ; - sq_ctrl->cache_id = INVALID_VALUE32; - sq_ctrl->local_port_id = INVALID_VALUE32; - sq_ctrl->remote_port_id = INVALID_VALUE32; - sq_ctrl->sq_in_sess_rst = false; - atomic_set(&sq_ctrl->sq_valid, true); - sq_ctrl->del_start_jiff = INVALID_VALUE64; - sq_ctrl->service_type = SPFC_SERVICE_TYPE_FC; - sq_ctrl->vport_id = (u8)rport_info->qos_level; - sq_ctrl->cs_ctrl = (u8)rport_info->cs_ctrl; - sq_ctrl->sirt_dif_control.protect_opcode = UNF_DIF_ACTION_NONE; - sq_ctrl->need_offloaded = INVALID_VALUE8; - atomic_set(&sq_ctrl->flush_done_wait_cnt, 0); - - /* Check whether the HBA is in the Linkdown state. Note that - * offload_state must be in the non-FREE state. - */ - spin_lock_irqsave(&hba->flush_state_lock, flag); - sq_ctrl->port_in_flush = hba->in_flushing; - spin_unlock_irqrestore(&hba->flush_state_lock, flag); - memset(sq_ctrl->io_stat, 0, sizeof(sq_ctrl->io_stat)); - - INIT_DELAYED_WORK(&sq_ctrl->del_work, spfc_parent_sq_opreate_timeout); - INIT_DELAYED_WORK(&sq_ctrl->flush_done_timeout_work, - spfc_parent_sq_wait_flush_done_timeout); - INIT_LIST_HEAD(&sq_ctrl->suspend_sqe_list); - - memset(&sq_ctrl->delay_sqe, 0, sizeof(struct spfc_delay_sqe_ctrl_info)); - - return RETURN_OK; - -parent_create_fail: - parq_info->parent_ctx.cqm_parent_ctx_obj = NULL; - - return UNF_RETURN_ERROR; -} - -static void -spfc_init_prnt_ctxt_scq_qinfo(void *hba, - struct spfc_parent_queue_info *prnt_qinfo) -{ - u32 resp_scqn = 0; - struct spfc_parent_context *ctx = NULL; - struct spfc_scq_qinfo *resp_prnt_scq_ctxt = NULL; - struct spfc_queue_info_bus queue_bus; - - /* Obtains the queue id of the scq returned by the CQM when the SCQ is - * created - */ - resp_scqn = prnt_qinfo->parent_sts_scq_info.cqm_queue_id; - - /* Obtains the Parent Context address */ - ctx = (struct spfc_parent_context *)(prnt_qinfo->parent_ctx.parent_ctx); - - resp_prnt_scq_ctxt = &ctx->resp_scq_qinfo; - resp_prnt_scq_ctxt->hw_scqc_config.info.rq_th2_preld_cache_num = wqe_pre_load; - resp_prnt_scq_ctxt->hw_scqc_config.info.rq_th1_preld_cache_num = wqe_pre_load; - resp_prnt_scq_ctxt->hw_scqc_config.info.rq_th0_preld_cache_num = wqe_pre_load; - resp_prnt_scq_ctxt->hw_scqc_config.info.rq_min_preld_cache_num = wqe_pre_load; - resp_prnt_scq_ctxt->hw_scqc_config.info.sq_th2_preld_cache_num = wqe_pre_load; - resp_prnt_scq_ctxt->hw_scqc_config.info.sq_th1_preld_cache_num = wqe_pre_load; - resp_prnt_scq_ctxt->hw_scqc_config.info.sq_th0_preld_cache_num = wqe_pre_load; - resp_prnt_scq_ctxt->hw_scqc_config.info.sq_min_preld_cache_num = wqe_pre_load; - resp_prnt_scq_ctxt->hw_scqc_config.info.scq_n = (u64)resp_scqn; - resp_prnt_scq_ctxt->hw_scqc_config.info.parity = 0; - - memset(&queue_bus, 0, sizeof(struct spfc_queue_info_bus)); - queue_bus.bus[ARRAY_INDEX_0] = resp_prnt_scq_ctxt->hw_scqc_config.pctxt_val1; - resp_prnt_scq_ctxt->hw_scqc_config.info.parity = spfc_get_parity_value(queue_bus.bus, - SPFC_HW_SCQC_BUS_ROW, - SPFC_HW_SCQC_BUS_COL - ); - spfc_cpu_to_big64(resp_prnt_scq_ctxt, sizeof(struct spfc_scq_qinfo)); -} - -static void -spfc_init_prnt_ctxt_srq_qinfo(void *handle, struct spfc_parent_queue_info *prnt_qinfo) -{ - struct spfc_parent_context *ctx = NULL; - struct cqm_queue *cqm_els_srq = NULL; - struct spfc_parent_sq_info *sq = NULL; - struct spfc_queue_info_bus queue_bus; - struct spfc_hba_info *hba = NULL; - - hba = (struct spfc_hba_info *)handle; - /* Obtains the SQ address */ - sq = &prnt_qinfo->parent_sq_info; - - /* Obtains the Parent Context address */ - ctx = (struct spfc_parent_context *)(prnt_qinfo->parent_ctx.parent_ctx); - - cqm_els_srq = hba->els_srq_info.cqm_srq_info; - - /* Initialize the Parent SRQ INFO used when the ELS is received */ - ctx->els_srq_info.srqc_gpa = cqm_els_srq->q_ctx_paddr >> UNF_SHIFT_4; - - memset(&queue_bus, 0, sizeof(struct spfc_queue_info_bus)); - queue_bus.bus[ARRAY_INDEX_0] = ctx->els_srq_info.srqc_gpa; - ctx->els_srq_info.parity = spfc_get_parity_value(queue_bus.bus, SPFC_HW_SRQC_BUS_ROW, - SPFC_HW_SRQC_BUS_COL); - spfc_cpu_to_big64(&ctx->els_srq_info, sizeof(struct spfc_srq_qinfo)); - - ctx->imm_srq_info.srqc_gpa = 0; - sq->srq_ctx_addr = 0; -} - -static u16 spfc_get_max_sequence_id(void) -{ - return SPFC_HRQI_SEQ_ID_MAX; -} - -static void spfc_init_prnt_rsvd_qinfo(struct spfc_parent_queue_info *prnt_qinfo) -{ - struct spfc_parent_context *ctx = NULL; - struct spfc_hw_rsvd_queue *hw_rsvd_qinfo = NULL; - u16 max_seq = 0; - u32 each = 0, seq_index = 0; - - /* Obtains the Parent Context address */ - ctx = (struct spfc_parent_context *)(prnt_qinfo->parent_ctx.parent_ctx); - hw_rsvd_qinfo = (struct spfc_hw_rsvd_queue *)&ctx->hw_rsvdq; - memset(hw_rsvd_qinfo->seq_id_bitmap, 0, sizeof(hw_rsvd_qinfo->seq_id_bitmap)); - - max_seq = spfc_get_max_sequence_id(); - - /* special set for sequence id 0, which is always kept by ucode for - * sending fcp-cmd - */ - hw_rsvd_qinfo->seq_id_bitmap[SPFC_HRQI_SEQ_SEPCIAL_ID] = 1; - seq_index = SPFC_HRQI_SEQ_SEPCIAL_ID - (max_seq >> SPFC_HRQI_SEQ_INDEX_SHIFT); - - /* Set the unavailable mask to start from max + 1 */ - for (each = (max_seq % SPFC_HRQI_SEQ_INDEX_MAX) + 1; - each < SPFC_HRQI_SEQ_INDEX_MAX; each++) { - hw_rsvd_qinfo->seq_id_bitmap[seq_index] |= ((u64)0x1) << each; - } - - hw_rsvd_qinfo->seq_id_bitmap[seq_index] = - cpu_to_be64(hw_rsvd_qinfo->seq_id_bitmap[seq_index]); - - /* sepcial set for sequence id 0 */ - if (seq_index != SPFC_HRQI_SEQ_SEPCIAL_ID) - hw_rsvd_qinfo->seq_id_bitmap[SPFC_HRQI_SEQ_SEPCIAL_ID] = - cpu_to_be64(hw_rsvd_qinfo->seq_id_bitmap[SPFC_HRQI_SEQ_SEPCIAL_ID]); - - for (each = 0; each < seq_index; each++) - hw_rsvd_qinfo->seq_id_bitmap[each] = SPFC_HRQI_SEQ_INVALID_ID; - - /* no matter what the range of seq id, last_req_seq_id is fixed value - * 0xff - */ - hw_rsvd_qinfo->wd0.last_req_seq_id = SPFC_HRQI_SEQ_ID_MAX; - hw_rsvd_qinfo->wd0.xid = prnt_qinfo->parent_sq_info.context_id; - - *(u64 *)&hw_rsvd_qinfo->wd0 = - cpu_to_be64(*(u64 *)&hw_rsvd_qinfo->wd0); -} - -/* - *Function Name : spfc_init_prnt_sw_section_info - *Function Description: Initialize the SW Section area that can be accessed by - * the Parent Context uCode. - *Input Parameters : *hba, - * *prnt_qinfo - *Output Parameters : N/A - *Return Type : void - */ -static void spfc_init_prnt_sw_section_info(struct spfc_hba_info *hba, - struct spfc_parent_queue_info *prnt_qinfo) -{ -#define SPFC_VLAN_ENABLE (1) -#define SPFC_MB_PER_KB 1024 - u16 rport_index; - struct spfc_parent_context *ctx = NULL; - struct spfc_sw_section *sw_setion = NULL; - u16 total_scq_num = SPFC_TOTAL_SCQ_NUM; - u32 queue_id; - dma_addr_t queue_hdr_paddr; - - /* Obtains the Parent Context address */ - ctx = (struct spfc_parent_context *)(prnt_qinfo->parent_ctx.parent_ctx); - sw_setion = &ctx->sw_section; - - /* xid+vPortId */ - sw_setion->sw_ctxt_vport_xid.xid = prnt_qinfo->parent_sq_info.context_id; - spfc_cpu_to_big32(&sw_setion->sw_ctxt_vport_xid, sizeof(sw_setion->sw_ctxt_vport_xid)); - - /* conn_id */ - rport_index = SPFC_LSW(prnt_qinfo->parent_sq_info.rport_index); - sw_setion->conn_id = cpu_to_be16(rport_index); - - /* Immediate parameters */ - sw_setion->immi_rq_page_size = 0; - - /* Parent SCQ INFO used for sending packets to the Cmnd */ - sw_setion->scq_num_rcv_cmd = cpu_to_be16((u16)prnt_qinfo->parent_cmd_scq_info.cqm_queue_id); - sw_setion->scq_num_max_scqn = cpu_to_be16(total_scq_num); - - /* sw_ctxt_misc */ - sw_setion->sw_ctxt_misc.dw.srv_type = prnt_qinfo->parent_sq_info.service_type; - sw_setion->sw_ctxt_misc.dw.port_id = hba->port_index; - - /* only the VN2VF mode is supported */ - sw_setion->sw_ctxt_misc.dw.vlan_id = 0; - spfc_cpu_to_big32(&sw_setion->sw_ctxt_misc.pctxt_val0, - sizeof(sw_setion->sw_ctxt_misc.pctxt_val0)); - - /* Configuring the combo length */ - sw_setion->per_xmit_data_size = cpu_to_be32(combo_length * SPFC_MB_PER_KB); - sw_setion->sw_ctxt_config.dw.work_mode = SPFC_PORT_MODE_INI; - sw_setion->sw_ctxt_config.dw.status = FC_PARENT_STATUS_INVALID; - sw_setion->sw_ctxt_config.dw.cos = 0; - sw_setion->sw_ctxt_config.dw.oq_cos_cmd = SPFC_PACKET_COS_FC_CMD; - sw_setion->sw_ctxt_config.dw.oq_cos_data = prnt_qinfo->queue_data_cos; - sw_setion->sw_ctxt_config.dw.priority = 0; - sw_setion->sw_ctxt_config.dw.vlan_enable = SPFC_VLAN_ENABLE; - sw_setion->sw_ctxt_config.dw.sgl_num = dif_sgl_mode; - spfc_cpu_to_big32(&sw_setion->sw_ctxt_config.pctxt_val1, - sizeof(sw_setion->sw_ctxt_config.pctxt_val1)); - spfc_cpu_to_big32(&sw_setion->immi_dif_info, sizeof(sw_setion->immi_dif_info)); - - queue_id = prnt_qinfo->parent_cmd_scq_info.local_queue_id; - queue_hdr_paddr = hba->scq_info[queue_id].cqm_scq_info->q_header_paddr; - sw_setion->cmd_scq_gpa_h = SPFC_HIGH_32_BITS(queue_hdr_paddr); - sw_setion->cmd_scq_gpa_l = SPFC_LOW_32_BITS(queue_hdr_paddr); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_INFO, - "[info]Port(0x%x) RPort(0x%x) CmdLocalScqn(0x%x) QheaderGpaH(0x%x) QheaderGpaL(0x%x)", - hba->port_cfg.port_id, prnt_qinfo->parent_sq_info.rport_index, queue_id, - sw_setion->cmd_scq_gpa_h, sw_setion->cmd_scq_gpa_l); - - spfc_cpu_to_big32(&sw_setion->cmd_scq_gpa_h, sizeof(sw_setion->cmd_scq_gpa_h)); - spfc_cpu_to_big32(&sw_setion->cmd_scq_gpa_l, sizeof(sw_setion->cmd_scq_gpa_l)); -} - -static void spfc_init_parent_context(void *hba, struct spfc_parent_queue_info *prnt_qinfo) -{ - struct spfc_parent_context *ctx = NULL; - - ctx = (struct spfc_parent_context *)(prnt_qinfo->parent_ctx.parent_ctx); - - /* Initialize Parent Context */ - memset(ctx, 0, SPFC_CNTX_SIZE_256B); - - /* Initialize the Queue Info hardware area */ - spfc_init_prnt_ctxt_scq_qinfo(hba, prnt_qinfo); - spfc_init_prnt_ctxt_srq_qinfo(hba, prnt_qinfo); - spfc_init_prnt_rsvd_qinfo(prnt_qinfo); - - /* Initialize Software Section */ - spfc_init_prnt_sw_section_info(hba, prnt_qinfo); -} - -void spfc_map_shared_queue_qid(struct spfc_hba_info *hba, - struct spfc_parent_queue_info *parent_queue_info, - u32 rport_index) -{ - u32 cmd_scqn_local = 0; - u32 sts_scqn_local = 0; - - /* The SCQ is used for each connection based on the balanced * - * distribution of commands and responses - */ - cmd_scqn_local = SPFC_RPORTID_TO_CMD_SCQN(rport_index); - sts_scqn_local = SPFC_RPORTID_TO_STS_SCQN(rport_index); - parent_queue_info->parent_cmd_scq_info.local_queue_id = cmd_scqn_local; - parent_queue_info->parent_sts_scq_info.local_queue_id = sts_scqn_local; - parent_queue_info->parent_cmd_scq_info.cqm_queue_id = - hba->scq_info[cmd_scqn_local].scqn; - parent_queue_info->parent_sts_scq_info.cqm_queue_id = - hba->scq_info[sts_scqn_local].scqn; - - /* Each session share with immediate SRQ and ElsSRQ */ - parent_queue_info->parent_els_srq_info.local_queue_id = 0; - parent_queue_info->parent_els_srq_info.cqm_queue_id = hba->els_srq_info.srqn; - - /* Allocate fcp data cos value */ - parent_queue_info->queue_data_cos = spfc_map_fcp_data_cos(hba); - - /* Allocate Parent SQ vPort */ - parent_queue_info->parent_sq_info.vport_id += parent_queue_info->queue_vport_id; -} - -u32 spfc_send_session_enable(struct spfc_hba_info *hba, struct unf_port_info *rport_info) -{ - struct spfc_parent_queue_info *parent_queue_info = NULL; - dma_addr_t ctx_phy_addr = 0; - void *ctx_addr = NULL; - union spfc_cmdqe session_enable; - u32 ret = UNF_RETURN_ERROR; - struct spfc_parent_context *ctx = NULL; - struct spfc_sw_section *sw_setion = NULL; - struct spfc_host_keys key; - u32 tx_mfs = 2048; - u32 edtov_timer = 2000; - ulong flag = 0; - spinlock_t *prtq_state_lock = NULL; - u32 index; - - memset(&session_enable, 0, sizeof(union spfc_cmdqe)); - memset(&key, 0, sizeof(struct spfc_host_keys)); - index = rport_info->rport_index; - parent_queue_info = &hba->parent_queue_mgr->parent_queue[index]; - prtq_state_lock = &parent_queue_info->parent_queue_state_lock; - spin_lock_irqsave(prtq_state_lock, flag); - - ctx = (struct spfc_parent_context *)(parent_queue_info->parent_ctx.parent_ctx); - sw_setion = &ctx->sw_section; - - sw_setion->tx_mfs = cpu_to_be16((u16)(tx_mfs)); - sw_setion->e_d_tov_timer_val = cpu_to_be32(edtov_timer); - - spfc_big_to_cpu32(&sw_setion->sw_ctxt_misc.pctxt_val0, - sizeof(sw_setion->sw_ctxt_misc.pctxt_val0)); - sw_setion->sw_ctxt_misc.dw.port_id = SPFC_GET_NETWORK_PORT_ID(hba); - spfc_cpu_to_big32(&sw_setion->sw_ctxt_misc.pctxt_val0, - sizeof(sw_setion->sw_ctxt_misc.pctxt_val0)); - - spfc_big_to_cpu32(&sw_setion->sw_ctxt_config.pctxt_val1, - sizeof(sw_setion->sw_ctxt_config.pctxt_val1)); - spfc_cpu_to_big32(&sw_setion->sw_ctxt_config.pctxt_val1, - sizeof(sw_setion->sw_ctxt_config.pctxt_val1)); - - parent_queue_info->parent_sq_info.rport_index = rport_info->rport_index; - parent_queue_info->parent_sq_info.local_port_id = rport_info->local_nport_id; - parent_queue_info->parent_sq_info.remote_port_id = rport_info->nport_id; - parent_queue_info->parent_sq_info.context_id = - parent_queue_info->parent_ctx.cqm_parent_ctx_obj->xid; - - /* Fill in contex to the chip */ - ctx_phy_addr = parent_queue_info->parent_ctx.cqm_parent_ctx_obj->paddr; - ctx_addr = parent_queue_info->parent_ctx.cqm_parent_ctx_obj->vaddr; - memcpy(ctx_addr, parent_queue_info->parent_ctx.parent_ctx, - sizeof(struct spfc_parent_context)); - session_enable.session_enable.wd0.task_type = SPFC_TASK_T_SESS_EN; - session_enable.session_enable.wd2.conn_id = rport_info->rport_index; - session_enable.session_enable.wd2.scqn = hba->default_scqn; - session_enable.session_enable.wd3.xid_p = - parent_queue_info->parent_ctx.cqm_parent_ctx_obj->xid; - session_enable.session_enable.context_gpa_hi = SPFC_HIGH_32_BITS(ctx_phy_addr); - session_enable.session_enable.context_gpa_lo = SPFC_LOW_32_BITS(ctx_phy_addr); - - spin_unlock_irqrestore(prtq_state_lock, flag); - - key.wd3.sid_2 = (rport_info->local_nport_id & SPFC_KEY_WD3_SID_2_MASK) >> UNF_SHIFT_16; - key.wd3.sid_1 = (rport_info->local_nport_id & SPFC_KEY_WD3_SID_1_MASK) >> UNF_SHIFT_8; - key.wd4.sid_0 = rport_info->local_nport_id & SPFC_KEY_WD3_SID_0_MASK; - key.wd4.did_0 = rport_info->nport_id & SPFC_KEY_WD4_DID_0_MASK; - key.wd4.did_1 = (rport_info->nport_id & SPFC_KEY_WD4_DID_1_MASK) >> UNF_SHIFT_8; - key.wd4.did_2 = (rport_info->nport_id & SPFC_KEY_WD4_DID_2_MASK) >> UNF_SHIFT_16; - key.wd5.host_id = 0; - key.wd5.port_id = hba->port_index; - - memcpy(&session_enable.session_enable.keys, &key, sizeof(struct spfc_host_keys)); - - memcpy((void *)(uintptr_t)session_enable.session_enable.context, - parent_queue_info->parent_ctx.parent_ctx, - sizeof(struct spfc_parent_context)); - spfc_big_to_cpu32((void *)(uintptr_t)session_enable.session_enable.context, - sizeof(struct spfc_parent_context)); - - FC_DRV_PRINT(UNF_LOG_NORMAL, UNF_MAJOR, - "[info] xid:0x%x, sid:0x%x,did:0x%x parentcontext:", - parent_queue_info->parent_ctx.cqm_parent_ctx_obj->xid, - rport_info->local_nport_id, rport_info->nport_id); - - ret = spfc_root_cmdq_enqueue(hba, &session_enable, sizeof(session_enable.session_enable)); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_NORMAL, UNF_ERR, - "[err]RootCMDQEnqueue Error, free default session parent resource"); - return UNF_RETURN_ERROR; - } - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x) send default session enable success,rport index(0x%x),context id(0x%x) SID=(0x%x), DID=(0x%x)", - hba->port_cfg.port_id, rport_info->rport_index, - parent_queue_info->parent_sq_info.context_id, - rport_info->local_nport_id, rport_info->nport_id); - - return RETURN_OK; -} - -u32 spfc_alloc_parent_resource(void *handle, struct unf_port_info *rport_info) -{ - u32 ret = UNF_RETURN_ERROR; - struct spfc_hba_info *hba = NULL; - struct spfc_parent_queue_info *parent_queue_info = NULL; - ulong flag = 0; - spinlock_t *prtq_state_lock = NULL; - u32 index; - - FC_CHECK_RETURN_VALUE(handle, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(rport_info, UNF_RETURN_ERROR); - - hba = (struct spfc_hba_info *)handle; - if (!hba->parent_queue_mgr) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) cannot find parent queue pool", - hba->port_cfg.port_id); - - return UNF_RETURN_ERROR; - } - - index = rport_info->rport_index; - if (index >= UNF_SPFC_MAXRPORT_NUM) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) allocate parent resource failed, invlaid rport index(0x%x),rport nportid(0x%x)", - hba->port_cfg.port_id, index, - rport_info->nport_id); - - return UNF_RETURN_ERROR; - } - - parent_queue_info = &hba->parent_queue_mgr->parent_queue[index]; - prtq_state_lock = &parent_queue_info->parent_queue_state_lock; - spin_lock_irqsave(prtq_state_lock, flag); - - if (parent_queue_info->offload_state != SPFC_QUEUE_STATE_FREE) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) allocate parent resource failed, invlaid rport index(0x%x),rport nportid(0x%x), offload state(0x%x)", - hba->port_cfg.port_id, index, rport_info->nport_id, - parent_queue_info->offload_state); - - spin_unlock_irqrestore(prtq_state_lock, flag); - return UNF_RETURN_ERROR; - } - - parent_queue_info->offload_state = SPFC_QUEUE_STATE_INITIALIZED; - /* Create Parent Context and Link List SQ */ - ret = spfc_alloc_parent_sq(hba, parent_queue_info, rport_info); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "Port(0x%x) alloc session resoure failed.rport index(0x%x),rport nportid(0x%x).", - hba->port_cfg.port_id, index, - rport_info->nport_id); - - parent_queue_info->offload_state = SPFC_QUEUE_STATE_FREE; - spfc_invalid_parent_sq(&parent_queue_info->parent_sq_info); - spin_unlock_irqrestore(prtq_state_lock, flag); - - return UNF_RETURN_ERROR; - } - - /* Allocate the corresponding queue xid to each parent */ - spfc_map_shared_queue_qid(hba, parent_queue_info, rport_info->rport_index); - - /* Initialize Parent Context, including hardware area and ucode area */ - spfc_init_parent_context(hba, parent_queue_info); - - spin_unlock_irqrestore(prtq_state_lock, flag); - - /* Only default enable session obviously, other will enable secertly */ - if (unlikely(rport_info->rport_index == SPFC_DEFAULT_RPORT_INDEX)) - return spfc_send_session_enable(handle, rport_info); - - parent_queue_info->parent_sq_info.local_port_id = rport_info->local_nport_id; - parent_queue_info->parent_sq_info.remote_port_id = rport_info->nport_id; - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x) allocate parent sq success,rport index(0x%x),rport nportid(0x%x),context id(0x%x)", - hba->port_cfg.port_id, rport_info->rport_index, - rport_info->nport_id, - parent_queue_info->parent_sq_info.context_id); - - return ret; -} - -u32 spfc_free_parent_resource(void *handle, struct unf_port_info *rport_info) -{ - struct spfc_parent_queue_info *parent_queue_info = NULL; - ulong flag = 0; - ulong rst_flag = 0; - u32 ret = UNF_RETURN_ERROR; - enum spfc_session_reset_mode mode = SPFC_SESS_RST_DELETE_IO_CONN_BOTH; - struct spfc_hba_info *hba = NULL; - spinlock_t *prtq_state_lock = NULL; - spinlock_t *sq_enq_lock = NULL; - u32 index; - - FC_CHECK_RETURN_VALUE(handle, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(rport_info, UNF_RETURN_ERROR); - - hba = (struct spfc_hba_info *)handle; - if (!hba->parent_queue_mgr) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[warn]Port(0x%x) cannot find parent queue pool", - hba->port_cfg.port_id); - - return UNF_RETURN_ERROR; - } - - /* get parent queue info (by rport index) */ - if (rport_info->rport_index >= UNF_SPFC_MAXRPORT_NUM) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[warn]Port(0x%x) free parent resource failed, invlaid rport_index(%u) rport_nport_id(0x%x)", - hba->port_cfg.port_id, rport_info->rport_index, rport_info->nport_id); - - return UNF_RETURN_ERROR; - } - - index = rport_info->rport_index; - parent_queue_info = &hba->parent_queue_mgr->parent_queue[index]; - prtq_state_lock = &parent_queue_info->parent_queue_state_lock; - sq_enq_lock = &parent_queue_info->parent_sq_info.parent_sq_enqueue_lock; - - spin_lock_irqsave(prtq_state_lock, flag); - /* 1. for has been offload */ - if (parent_queue_info->offload_state == SPFC_QUEUE_STATE_OFFLOADED) { - parent_queue_info->offload_state = SPFC_QUEUE_STATE_DESTROYING; - spin_unlock_irqrestore(prtq_state_lock, flag); - - /* set reset state, in order to prevent I/O in_SQ */ - spin_lock_irqsave(sq_enq_lock, rst_flag); - parent_queue_info->parent_sq_info.sq_in_sess_rst = true; - spin_unlock_irqrestore(sq_enq_lock, rst_flag); - - /* check pcie device state */ - if (!hba->dev_present) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x) hba is not present, free directly. rport_index(0x%x:0x%x) local_nportid(0x%x) remote_nportid(0x%x:0x%x)", - hba->port_cfg.port_id, rport_info->rport_index, - parent_queue_info->parent_sq_info.rport_index, - parent_queue_info->parent_sq_info.local_port_id, - rport_info->nport_id, - parent_queue_info->parent_sq_info.remote_port_id); - - spfc_free_parent_queue_info(hba, parent_queue_info); - return RETURN_OK; - } - - parent_queue_info->parent_sq_info.del_start_jiff = jiffies; - (void)queue_delayed_work(hba->work_queue, - &parent_queue_info->parent_sq_info.del_work, - (ulong)msecs_to_jiffies((u32) - SPFC_SQ_DEL_STAGE_TIMEOUT_MS)); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x) begin to reset parent session, rport_index(0x%x:0x%x) local_nportid(0x%x) remote_nportid(0x%x:0x%x)", - hba->port_cfg.port_id, rport_info->rport_index, - parent_queue_info->parent_sq_info.rport_index, - parent_queue_info->parent_sq_info.local_port_id, - rport_info->nport_id, - parent_queue_info->parent_sq_info.remote_port_id); - /* Forcibly set both mode */ - mode = SPFC_SESS_RST_DELETE_IO_CONN_BOTH; - ret = spfc_send_session_rst_cmd(hba, parent_queue_info, mode); - - return ret; - } else if (parent_queue_info->offload_state == SPFC_QUEUE_STATE_INITIALIZED) { - /* 2. for resource has been alloc, but not offload */ - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x) parent sq is not offloaded, free directly. rport_index(0x%x:0x%x) local_nportid(0x%x) remote_nportid(0x%x:0x%x)", - hba->port_cfg.port_id, rport_info->rport_index, - parent_queue_info->parent_sq_info.rport_index, - parent_queue_info->parent_sq_info.local_port_id, - rport_info->nport_id, - parent_queue_info->parent_sq_info.remote_port_id); - - spin_unlock_irqrestore(prtq_state_lock, flag); - spfc_free_parent_queue_info(hba, parent_queue_info); - - return RETURN_OK; - } else if (parent_queue_info->offload_state == - SPFC_QUEUE_STATE_OFFLOADING) { - /* 3. for driver has offloading CMND to uCode */ - spfc_push_destroy_parent_queue_sqe(hba, parent_queue_info, rport_info); - spin_unlock_irqrestore(prtq_state_lock, flag); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x) parent sq is offloading, push to delay free. rport_index(0x%x:0x%x) local_nportid(0x%x) remote_nportid(0x%x:0x%x)", - hba->port_cfg.port_id, rport_info->rport_index, - parent_queue_info->parent_sq_info.rport_index, - parent_queue_info->parent_sq_info.local_port_id, - rport_info->nport_id, - parent_queue_info->parent_sq_info.remote_port_id); - - return RETURN_OK; - } - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) parent sq is not created, do not need free state(0x%x) rport_index(0x%x:0x%x) local_nportid(0x%x) remote_nportid(0x%x:0x%x)", - hba->port_cfg.port_id, parent_queue_info->offload_state, - rport_info->rport_index, - parent_queue_info->parent_sq_info.rport_index, - parent_queue_info->parent_sq_info.local_port_id, - rport_info->nport_id, - parent_queue_info->parent_sq_info.remote_port_id); - - spin_unlock_irqrestore(prtq_state_lock, flag); - - return RETURN_OK; -} - -void spfc_free_parent_queue_mgr(void *handle) -{ - u32 index = 0; - struct spfc_parent_queue_mgr *parent_queue_mgr = NULL; - struct spfc_hba_info *hba = NULL; - - FC_CHECK_RETURN_VOID(handle); - - hba = (struct spfc_hba_info *)handle; - if (!hba->parent_queue_mgr) - return; - parent_queue_mgr = hba->parent_queue_mgr; - - for (index = 0; index < UNF_SPFC_MAXRPORT_NUM; index++) { - if (parent_queue_mgr->parent_queue[index].parent_ctx.parent_ctx) - parent_queue_mgr->parent_queue[index].parent_ctx.parent_ctx = NULL; - } - - if (parent_queue_mgr->parent_sq_buf_list.buflist) { - for (index = 0; index < parent_queue_mgr->parent_sq_buf_list.buf_num; index++) { - if (parent_queue_mgr->parent_sq_buf_list.buflist[index].paddr != 0) { - pci_unmap_single(hba->pci_dev, - parent_queue_mgr->parent_sq_buf_list - .buflist[index].paddr, - parent_queue_mgr->parent_sq_buf_list.buf_size, - DMA_BIDIRECTIONAL); - parent_queue_mgr->parent_sq_buf_list.buflist[index].paddr = 0; - } - kfree(parent_queue_mgr->parent_sq_buf_list.buflist[index].vaddr); - parent_queue_mgr->parent_sq_buf_list.buflist[index].vaddr = NULL; - } - - kfree(parent_queue_mgr->parent_sq_buf_list.buflist); - parent_queue_mgr->parent_sq_buf_list.buflist = NULL; - } - - vfree(parent_queue_mgr); - hba->parent_queue_mgr = NULL; -} - -void spfc_free_parent_queues(void *handle) -{ - u32 index = 0; - ulong flag = 0; - struct spfc_parent_queue_mgr *parent_queue_mgr = NULL; - struct spfc_hba_info *hba = NULL; - spinlock_t *prtq_state_lock = NULL; - - FC_CHECK_RETURN_VOID(handle); - - hba = (struct spfc_hba_info *)handle; - parent_queue_mgr = hba->parent_queue_mgr; - - for (index = 0; index < UNF_SPFC_MAXRPORT_NUM; index++) { - prtq_state_lock = &parent_queue_mgr->parent_queue[index].parent_queue_state_lock; - spin_lock_irqsave(prtq_state_lock, flag); - - if (SPFC_QUEUE_STATE_DESTROYING == - parent_queue_mgr->parent_queue[index].offload_state) { - spin_unlock_irqrestore(prtq_state_lock, flag); - - (void)cancel_delayed_work_sync(&parent_queue_mgr->parent_queue[index] - .parent_sq_info.del_work); - (void)cancel_delayed_work_sync(&parent_queue_mgr->parent_queue[index] - .parent_sq_info.flush_done_timeout_work); - - /* free parent queue */ - spfc_free_parent_queue_info(hba, &parent_queue_mgr->parent_queue[index]); - continue; - } - - spin_unlock_irqrestore(prtq_state_lock, flag); - } -} - -/* - *Function Name : spfc_alloc_parent_queue_mgr - *Function Description: Allocate and initialize parent queue manager. - *Input Parameters : *handle - *Output Parameters : N/A - *Return Type : void - */ -u32 spfc_alloc_parent_queue_mgr(void *handle) -{ - u32 index = 0; - struct spfc_parent_queue_mgr *parent_queue_mgr = NULL; - u32 buf_total_size; - u32 buf_num; - u32 alloc_idx; - u32 cur_buf_idx = 0; - u32 cur_buf_offset = 0; - u32 prt_ctx_size = sizeof(struct spfc_parent_context); - u32 buf_cnt_perhugebuf; - struct spfc_hba_info *hba = NULL; - u32 init_val = INVALID_VALUE32; - dma_addr_t paddr; - - FC_CHECK_RETURN_VALUE(handle, UNF_RETURN_ERROR); - - hba = (struct spfc_hba_info *)handle; - parent_queue_mgr = (struct spfc_parent_queue_mgr *)vmalloc(sizeof - (struct spfc_parent_queue_mgr)); - if (!parent_queue_mgr) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Port(0x%x) cannot allocate queue manager", - hba->port_cfg.port_id); - - return UNF_RETURN_ERROR; - } - - hba->parent_queue_mgr = parent_queue_mgr; - memset(parent_queue_mgr, 0, sizeof(struct spfc_parent_queue_mgr)); - - for (index = 0; index < UNF_SPFC_MAXRPORT_NUM; index++) { - spin_lock_init(&parent_queue_mgr->parent_queue[index].parent_queue_state_lock); - parent_queue_mgr->parent_queue[index].offload_state = SPFC_QUEUE_STATE_FREE; - spin_lock_init(&(parent_queue_mgr->parent_queue[index] - .parent_sq_info.parent_sq_enqueue_lock)); - parent_queue_mgr->parent_queue[index].parent_cmd_scq_info.cqm_queue_id = init_val; - parent_queue_mgr->parent_queue[index].parent_sts_scq_info.cqm_queue_id = init_val; - parent_queue_mgr->parent_queue[index].parent_els_srq_info.cqm_queue_id = init_val; - parent_queue_mgr->parent_queue[index].parent_sq_info.del_start_jiff = init_val; - parent_queue_mgr->parent_queue[index].queue_vport_id = hba->vpid_start; - } - - buf_total_size = prt_ctx_size * UNF_SPFC_MAXRPORT_NUM; - parent_queue_mgr->parent_sq_buf_list.buf_size = buf_total_size > BUF_LIST_PAGE_SIZE ? - BUF_LIST_PAGE_SIZE : buf_total_size; - buf_cnt_perhugebuf = parent_queue_mgr->parent_sq_buf_list.buf_size / prt_ctx_size; - buf_num = UNF_SPFC_MAXRPORT_NUM % buf_cnt_perhugebuf ? - UNF_SPFC_MAXRPORT_NUM / buf_cnt_perhugebuf + 1 : - UNF_SPFC_MAXRPORT_NUM / buf_cnt_perhugebuf; - parent_queue_mgr->parent_sq_buf_list.buflist = - (struct buff_list *)kmalloc(buf_num * sizeof(struct buff_list), GFP_KERNEL); - parent_queue_mgr->parent_sq_buf_list.buf_num = buf_num; - - if (!parent_queue_mgr->parent_sq_buf_list.buflist) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[err]Allocate QueuMgr buf list failed out of memory"); - goto free_parent_queue; - } - memset(parent_queue_mgr->parent_sq_buf_list.buflist, 0, buf_num * sizeof(struct buff_list)); - - for (alloc_idx = 0; alloc_idx < buf_num; alloc_idx++) { - parent_queue_mgr->parent_sq_buf_list.buflist[alloc_idx].vaddr = - kmalloc(parent_queue_mgr->parent_sq_buf_list.buf_size, GFP_KERNEL); - if (!parent_queue_mgr->parent_sq_buf_list.buflist[alloc_idx].vaddr) - goto free_parent_queue; - - memset(parent_queue_mgr->parent_sq_buf_list.buflist[alloc_idx].vaddr, 0, - parent_queue_mgr->parent_sq_buf_list.buf_size); - - parent_queue_mgr->parent_sq_buf_list.buflist[alloc_idx].paddr = - pci_map_single(hba->pci_dev, - parent_queue_mgr->parent_sq_buf_list.buflist[alloc_idx].vaddr, - parent_queue_mgr->parent_sq_buf_list.buf_size, - DMA_BIDIRECTIONAL); - paddr = parent_queue_mgr->parent_sq_buf_list.buflist[alloc_idx].paddr; - if (pci_dma_mapping_error(hba->pci_dev, paddr)) { - parent_queue_mgr->parent_sq_buf_list.buflist[alloc_idx].paddr = 0; - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[err]Map QueuMgr address failed"); - - goto free_parent_queue; - } - } - - for (index = 0; index < UNF_SPFC_MAXRPORT_NUM; index++) { - cur_buf_idx = index / buf_cnt_perhugebuf; - cur_buf_offset = prt_ctx_size * (index % buf_cnt_perhugebuf); - - parent_queue_mgr->parent_queue[index].parent_ctx.parent_ctx = - parent_queue_mgr->parent_sq_buf_list.buflist[cur_buf_idx].vaddr + - cur_buf_offset; - parent_queue_mgr->parent_queue[index].parent_ctx.parent_ctx_addr = - parent_queue_mgr->parent_sq_buf_list.buflist[cur_buf_idx].paddr + - cur_buf_offset; - } - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_INFO, - "[EVENT]Allocate bufnum:%u,buf_total_size:%u", buf_num, buf_total_size); - - return RETURN_OK; - -free_parent_queue: - spfc_free_parent_queue_mgr(hba); - return UNF_RETURN_ERROR; -} - -static void spfc_rlease_all_wqe_pages(struct spfc_hba_info *hba) -{ - u32 index; - struct spfc_wqe_page *wpg = NULL; - - FC_CHECK_RETURN_VOID((hba)); - - wpg = hba->sq_wpg_pool.wpg_pool_addr; - - for (index = 0; index < hba->sq_wpg_pool.wpg_cnt; index++) { - if (wpg->wpg_addr) { - dma_pool_free(hba->sq_wpg_pool.wpg_dma_pool, - wpg->wpg_addr, wpg->wpg_phy_addr); - wpg->wpg_addr = NULL; - wpg->wpg_phy_addr = 0; - } - - wpg++; - } - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]Port[%u] free total %u wqepages", hba->port_index, - index); -} - -u32 spfc_alloc_parent_sq_wqe_page_pool(void *handle) -{ - u32 index = 0; - struct spfc_sq_wqepage_pool *wpg_pool = NULL; - struct spfc_wqe_page *wpg = NULL; - struct spfc_hba_info *hba = NULL; - - hba = (struct spfc_hba_info *)handle; - wpg_pool = &hba->sq_wpg_pool; - - INIT_LIST_HEAD(&wpg_pool->list_free_wpg_pool); - spin_lock_init(&wpg_pool->wpg_pool_lock); - atomic_set(&wpg_pool->wpg_in_use, 0); - - /* Calculate the number of Wqe Page required in the pool */ - wpg_pool->wpg_size = wqe_page_size; - wpg_pool->wpg_cnt = SPFC_MIN_WP_NUM * SPFC_MAX_SSQ_NUM + - ((hba->exi_count * SPFC_SQE_SIZE) / wpg_pool->wpg_size); - wpg_pool->wqe_per_wpg = wpg_pool->wpg_size / SPFC_SQE_SIZE; - - /* Craete DMA POOL */ - wpg_pool->wpg_dma_pool = dma_pool_create("spfc_wpg_pool", - &hba->pci_dev->dev, - wpg_pool->wpg_size, - SPFC_SQE_SIZE, 0); - if (!wpg_pool->wpg_dma_pool) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Cannot allocate SQ WqePage DMA pool"); - - goto out_create_dma_pool_err; - } - - /* Allocate arrays to record all WqePage addresses */ - wpg_pool->wpg_pool_addr = (struct spfc_wqe_page *)vmalloc(wpg_pool->wpg_cnt * - sizeof(struct spfc_wqe_page)); - if (!wpg_pool->wpg_pool_addr) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Allocate SQ WqePageAddr array failed"); - - goto out_alloc_wpg_array_err; - } - wpg = wpg_pool->wpg_pool_addr; - memset(wpg, 0, wpg_pool->wpg_cnt * sizeof(struct spfc_wqe_page)); - - for (index = 0; index < wpg_pool->wpg_cnt; index++) { - wpg->wpg_addr = dma_pool_alloc(wpg_pool->wpg_dma_pool, GFP_KERNEL, - (u64 *)&wpg->wpg_phy_addr); - if (!wpg->wpg_addr) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, - UNF_ERR, "[err]Dma pool allocated failed"); - break; - } - - /* To ensure security, clear the memory */ - memset(wpg->wpg_addr, 0, wpg_pool->wpg_size); - - /* Add to the idle linked list */ - INIT_LIST_HEAD(&wpg->entry_wpg); - list_add_tail(&wpg->entry_wpg, &wpg_pool->list_free_wpg_pool); - - wpg++; - } - /* ALL allocated successfully */ - if (wpg_pool->wpg_cnt == index) - return RETURN_OK; - - spfc_rlease_all_wqe_pages(hba); - vfree(wpg_pool->wpg_pool_addr); - wpg_pool->wpg_pool_addr = NULL; - -out_alloc_wpg_array_err: - dma_pool_destroy(wpg_pool->wpg_dma_pool); - wpg_pool->wpg_dma_pool = NULL; - -out_create_dma_pool_err: - return UNF_RETURN_ERROR; -} - -void spfc_free_parent_sq_wqe_page_pool(void *handle) -{ - struct spfc_hba_info *hba = NULL; - - FC_CHECK_RETURN_VOID((handle)); - hba = (struct spfc_hba_info *)handle; - spfc_rlease_all_wqe_pages(hba); - hba->sq_wpg_pool.wpg_cnt = 0; - - if (hba->sq_wpg_pool.wpg_pool_addr) { - vfree(hba->sq_wpg_pool.wpg_pool_addr); - hba->sq_wpg_pool.wpg_pool_addr = NULL; - } - - dma_pool_destroy(hba->sq_wpg_pool.wpg_dma_pool); - hba->sq_wpg_pool.wpg_dma_pool = NULL; -} - -static u32 spfc_parent_sq_ring_direct_wqe_doorbell(struct spfc_parent_ssq_info *sq, u8 *direct_wqe) -{ - u32 ret = RETURN_OK; - int ravl; - u16 pmsn; - u64 queue_hdr_db_val; - struct spfc_hba_info *hba; - - hba = (struct spfc_hba_info *)sq->hba; - pmsn = sq->last_pmsn; - - if (sq->cache_id == INVALID_VALUE32) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[err]SQ(0x%x) invalid cid", sq->context_id); - return RETURN_ERROR; - } - /* Fill Doorbell Record */ - queue_hdr_db_val = sq->queue_header->door_bell_record; - queue_hdr_db_val &= (u64)(~(0xFFFFFFFF)); - queue_hdr_db_val |= (u64)((u64)pmsn << UNF_SHIFT_16 | pmsn); - sq->queue_header->door_bell_record = - cpu_to_be64(queue_hdr_db_val); - - ravl = cqm_ring_direct_wqe_db_fc(hba->dev_handle, SERVICE_T_FC, direct_wqe); - if (unlikely(ravl != CQM_SUCCESS)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[err]SQ(0x%x) send DB failed", sq->context_id); - - ret = RETURN_ERROR; - } - - atomic_inc(&sq->sq_db_cnt); - - return ret; -} - -u32 spfc_parent_sq_ring_doorbell(struct spfc_parent_ssq_info *sq, u8 qos_level, u32 c) -{ - u32 ret = RETURN_OK; - int ravl; - u16 pmsn; - u8 pmsn_lo; - u8 pmsn_hi; - u64 db_val_qw; - struct spfc_hba_info *hba; - struct spfc_parent_sq_db door_bell; - - hba = (struct spfc_hba_info *)sq->hba; - pmsn = sq->last_pmsn; - /* Obtain the low 8 Bit of PMSN */ - pmsn_lo = (u8)(pmsn & SPFC_PMSN_MASK); - /* Obtain the high 8 Bit of PMSN */ - pmsn_hi = (u8)((pmsn >> UNF_SHIFT_8) & SPFC_PMSN_MASK); - door_bell.wd0.service_type = SPFC_LSW(sq->service_type); - door_bell.wd0.cos = 0; - /* c = 0 data type, c = 1 control type, two type are different in mqm */ - door_bell.wd0.c = c; - door_bell.wd0.arm = SPFC_DB_ARM_DISABLE; - door_bell.wd0.cntx_size = SPFC_CNTX_SIZE_T_256B; - door_bell.wd0.xid = sq->context_id; - door_bell.wd1.sm_data = sq->cache_id; - door_bell.wd1.qid = sq->sq_queue_id; - door_bell.wd1.pi_hi = (u32)pmsn_hi; - - if (sq->cache_id == INVALID_VALUE32) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[err]SQ(0x%x) invalid cid", sq->context_id); - return UNF_RETURN_ERROR; - } - /* Fill Doorbell Record */ - db_val_qw = sq->queue_header->door_bell_record; - db_val_qw &= (u64)(~(SPFC_DB_VAL_MASK)); - db_val_qw |= (u64)((u64)pmsn << UNF_SHIFT_16 | pmsn); - sq->queue_header->door_bell_record = cpu_to_be64(db_val_qw); - - /* ring doorbell */ - db_val_qw = *(u64 *)&door_bell; - ravl = cqm3_ring_hardware_db_fc(hba->dev_handle, SERVICE_T_FC, pmsn_lo, - (qos_level & SPFC_QOS_LEVEL_MASK), - db_val_qw); - if (unlikely(ravl != CQM_SUCCESS)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[err]SQ(0x%x) send DB(0x%llx) failed", - sq->context_id, db_val_qw); - - ret = UNF_RETURN_ERROR; - } - - /* Doorbell success counter */ - atomic_inc(&sq->sq_db_cnt); - - return ret; -} - -u32 spfc_direct_sq_enqueue(struct spfc_parent_ssq_info *ssq, struct spfc_sqe *io_sqe, u8 wqe_type) -{ - u32 ret = RETURN_OK; - u32 msn_wd = INVALID_VALUE32; - u16 link_wqe_msn = 0; - ulong flag = 0; - struct spfc_wqe_page *tail_wpg = NULL; - struct spfc_sqe *sqe_in_wp = NULL; - struct spfc_linkwqe *link_wqe = NULL; - struct spfc_linkwqe *link_wqe_last_part = NULL; - u64 wqe_gpa; - struct spfc_direct_wqe_db dre_door_bell; - - spin_lock_irqsave(&ssq->parent_sq_enqueue_lock, flag); - tail_wpg = SPFC_GET_SQ_TAIL(ssq); - if (ssq->wqe_offset == ssq->wqe_num_per_buf) { - FC_DRV_PRINT(UNF_LOG_NORMAL, UNF_INFO, - "[info]Ssq(0x%x), xid(0x%x) qid(0x%x) add wqepage at Pmsn(0x%x), sqe_minus_cqe_cnt(0x%x)", - ssq->sqn, ssq->context_id, ssq->sq_queue_id, - ssq->last_pmsn, - atomic_read(&ssq->sqe_minus_cqe_cnt)); - - link_wqe_msn = SPFC_MSN_DEC(ssq->last_pmsn); - link_wqe = (struct spfc_linkwqe *)spfc_get_wqe_page_entry(tail_wpg, - ssq->wqe_offset); - msn_wd = be32_to_cpu(link_wqe->val_wd1); - msn_wd |= ((u32)(link_wqe_msn & SPFC_MSNWD_L_MASK)); - msn_wd |= (((u32)(link_wqe_msn & SPFC_MSNWD_H_MASK)) << UNF_SHIFT_16); - link_wqe->val_wd1 = cpu_to_be32(msn_wd); - link_wqe_last_part = (struct spfc_linkwqe *)((u8 *)link_wqe + - SPFC_EXTEND_WQE_OFFSET); - link_wqe_last_part->val_wd1 = link_wqe->val_wd1; - spfc_set_direct_wqe_owner_be(link_wqe, ssq->last_pi_owner); - ssq->wqe_offset = 0; - ssq->last_pi_owner = !ssq->last_pi_owner; - } - sqe_in_wp = - (struct spfc_sqe *)spfc_get_wqe_page_entry(tail_wpg, ssq->wqe_offset); - spfc_build_wqe_owner_pmsn(io_sqe, (ssq->last_pi_owner), ssq->last_pmsn); - SPFC_IO_STAT((struct spfc_hba_info *)ssq->hba, wqe_type); - - wqe_gpa = tail_wpg->wpg_phy_addr + (ssq->wqe_offset * sizeof(struct spfc_sqe)); - io_sqe->wqe_gpa = (wqe_gpa >> UNF_SHIFT_6); - - dre_door_bell.wd0.ddb = IWARP_FC_DDB_TYPE; - dre_door_bell.wd0.cos = 0; - dre_door_bell.wd0.c = 0; - dre_door_bell.wd0.pi_hi = - (u32)(ssq->last_pmsn >> UNF_SHIFT_12) & SPFC_DB_WD0_PI_H_MASK; - dre_door_bell.wd0.cntx_size = SPFC_CNTX_SIZE_T_256B; - dre_door_bell.wd0.xid = ssq->context_id; - dre_door_bell.wd1.sm_data = ssq->cache_id; - dre_door_bell.wd1.pi_lo = (u32)(ssq->last_pmsn & SPFC_DB_WD0_PI_L_MASK); - io_sqe->db_val = *(u64 *)&dre_door_bell; - - spfc_convert_parent_wqe_to_big_endian(io_sqe); - memcpy(sqe_in_wp, io_sqe, sizeof(struct spfc_sqe)); - spfc_set_direct_wqe_owner_be(sqe_in_wp, ssq->last_pi_owner); - - FC_DRV_PRINT(UNF_LOG_NORMAL, UNF_INFO, - "[INFO]Ssq(0x%x) xid:0x%x,qid:0x%x wqegpa:0x%llx,o:0x%x,outstandind:0x%x,pmsn:0x%x,cmsn:0x%x", - ssq->sqn, ssq->context_id, ssq->sq_queue_id, wqe_gpa, - ssq->last_pi_owner, atomic_read(&ssq->sqe_minus_cqe_cnt), - ssq->last_pmsn, SPFC_GET_QUEUE_CMSN(ssq)); - - ssq->accum_wqe_cnt++; - if (ssq->accum_wqe_cnt == accum_db_num) { - ret = spfc_parent_sq_ring_direct_wqe_doorbell(ssq, (void *)sqe_in_wp); - if (unlikely(ret != RETURN_OK)) - SPFC_ERR_IO_STAT((struct spfc_hba_info *)ssq->hba, wqe_type); - ssq->accum_wqe_cnt = 0; - } - - ssq->wqe_offset += 1; - ssq->last_pmsn = SPFC_MSN_INC(ssq->last_pmsn); - atomic_inc(&ssq->sq_wqe_cnt); - atomic_inc(&ssq->sqe_minus_cqe_cnt); - SPFC_SQ_IO_STAT(ssq, wqe_type); - spin_unlock_irqrestore(&ssq->parent_sq_enqueue_lock, flag); - return ret; -} - -u32 spfc_parent_ssq_enqueue(struct spfc_parent_ssq_info *ssq, struct spfc_sqe *io_sqe, u8 wqe_type) -{ - u32 ret = RETURN_OK; - u32 addr_wd = INVALID_VALUE32; - u32 msn_wd = INVALID_VALUE32; - u16 link_wqe_msn = 0; - ulong flag = 0; - struct spfc_wqe_page *new_wqe_page = NULL; - struct spfc_wqe_page *tail_wpg = NULL; - struct spfc_sqe *sqe_in_wp = NULL; - struct spfc_linkwqe *link_wqe = NULL; - struct spfc_linkwqe *link_wqe_last_part = NULL; - u32 cur_cmsn = 0; - u8 qos_level = (u8)io_sqe->ts_sl.cont.icmnd.info.dif_info.wd1.vpid; - u32 c = SPFC_DB_C_BIT_CONTROL_TYPE; - - if (ssq->queue_style == SPFC_QUEUE_RING_STYLE) - return spfc_direct_sq_enqueue(ssq, io_sqe, wqe_type); - - spin_lock_irqsave(&ssq->parent_sq_enqueue_lock, flag); - tail_wpg = SPFC_GET_SQ_TAIL(ssq); - if (ssq->wqe_offset == ssq->wqe_num_per_buf) { - FC_DRV_PRINT(UNF_LOG_NORMAL, UNF_INFO, - "[info]Ssq(0x%x), xid(0x%x) qid(0x%x) add wqepage at Pmsn(0x%x), WpgCnt(0x%x)", - ssq->sqn, ssq->context_id, ssq->sq_queue_id, - ssq->last_pmsn, - atomic_read(&ssq->wqe_page_cnt)); - cur_cmsn = SPFC_GET_QUEUE_CMSN(ssq); - spfc_free_sq_wqe_page(ssq, cur_cmsn); - new_wqe_page = spfc_add_one_wqe_page(ssq); - if (unlikely(!new_wqe_page)) { - SPFC_ERR_IO_STAT((struct spfc_hba_info *)ssq->hba, wqe_type); - spin_unlock_irqrestore(&ssq->parent_sq_enqueue_lock, flag); - return UNF_RETURN_ERROR; - } - link_wqe = (struct spfc_linkwqe *)spfc_get_wqe_page_entry(tail_wpg, - ssq->wqe_offset); - addr_wd = SPFC_MSD(new_wqe_page->wpg_phy_addr); - link_wqe->next_page_addr_hi = cpu_to_be32(addr_wd); - addr_wd = SPFC_LSD(new_wqe_page->wpg_phy_addr); - link_wqe->next_page_addr_lo = cpu_to_be32(addr_wd); - link_wqe_msn = SPFC_MSN_DEC(ssq->last_pmsn); - msn_wd = be32_to_cpu(link_wqe->val_wd1); - msn_wd |= ((u32)(link_wqe_msn & SPFC_MSNWD_L_MASK)); - msn_wd |= (((u32)(link_wqe_msn & SPFC_MSNWD_H_MASK)) << UNF_SHIFT_16); - link_wqe->val_wd1 = cpu_to_be32(msn_wd); - link_wqe_last_part = (struct spfc_linkwqe *)((u8 *)link_wqe + - SPFC_EXTEND_WQE_OFFSET); - link_wqe_last_part->next_page_addr_hi = link_wqe->next_page_addr_hi; - link_wqe_last_part->next_page_addr_lo = link_wqe->next_page_addr_lo; - link_wqe_last_part->val_wd1 = link_wqe->val_wd1; - spfc_set_sq_wqe_owner_be(link_wqe); - ssq->wqe_offset = 0; - tail_wpg = SPFC_GET_SQ_TAIL(ssq); - atomic_inc(&ssq->wqe_page_cnt); - } - - spfc_build_wqe_owner_pmsn(io_sqe, !(ssq->last_pi_owner), ssq->last_pmsn); - SPFC_IO_STAT((struct spfc_hba_info *)ssq->hba, wqe_type); - spfc_convert_parent_wqe_to_big_endian(io_sqe); - sqe_in_wp = (struct spfc_sqe *)spfc_get_wqe_page_entry(tail_wpg, ssq->wqe_offset); - memcpy(sqe_in_wp, io_sqe, sizeof(struct spfc_sqe)); - spfc_set_sq_wqe_owner_be(sqe_in_wp); - - FC_DRV_PRINT(UNF_LOG_NORMAL, UNF_INFO, - "[INFO]Ssq(0x%x) xid:0x%x,qid:0x%x wqegpa:0x%llx, qos_level:0x%x, c:0x%x", - ssq->sqn, ssq->context_id, ssq->sq_queue_id, - virt_to_phys(sqe_in_wp), qos_level, c); - - ssq->accum_wqe_cnt++; - if (ssq->accum_wqe_cnt == accum_db_num) { - ret = spfc_parent_sq_ring_doorbell(ssq, qos_level, c); - if (unlikely(ret != RETURN_OK)) - SPFC_ERR_IO_STAT((struct spfc_hba_info *)ssq->hba, wqe_type); - ssq->accum_wqe_cnt = 0; - } - ssq->wqe_offset += 1; - ssq->last_pmsn = SPFC_MSN_INC(ssq->last_pmsn); - atomic_inc(&ssq->sq_wqe_cnt); - atomic_inc(&ssq->sqe_minus_cqe_cnt); - SPFC_SQ_IO_STAT(ssq, wqe_type); - spin_unlock_irqrestore(&ssq->parent_sq_enqueue_lock, flag); - return ret; -} - -u32 spfc_parent_sq_enqueue(struct spfc_parent_sq_info *sq, struct spfc_sqe *io_sqe, u16 ssqn) -{ - u8 wqe_type = 0; - struct spfc_hba_info *hba = (struct spfc_hba_info *)sq->hba; - struct spfc_parent_ssq_info *ssq = NULL; - - if (unlikely(ssqn >= SPFC_MAX_SSQ_NUM)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[err]Ssqn 0x%x is invalid.", ssqn); - - return UNF_RETURN_ERROR; - } - - wqe_type = (u8)SPFC_GET_WQE_TYPE(io_sqe); - - /* Serial enqueue */ - io_sqe->ts_sl.xid = sq->context_id; - io_sqe->ts_sl.cid = sq->cache_id; - io_sqe->ts_sl.sqn = ssqn; - - /* Choose SSQ */ - ssq = &hba->parent_queue_mgr->shared_queue[ssqn].parent_ssq_info; - - /* If the SQ is invalid, the wqe is discarded */ - if (unlikely(!atomic_read(&sq->sq_valid))) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[err]SQ is invalid, reject wqe(0x%x)", wqe_type); - - return UNF_RETURN_ERROR; - } - - /* The heartbeat detection status is 0, which allows control sessions - * enqueuing - */ - if (unlikely(!hba->heart_status && SPFC_WQE_IS_IO(io_sqe))) { - FC_DRV_PRINT(UNF_LOG_NORMAL, UNF_ERR, - "[err]Heart status is false"); - - return UNF_RETURN_ERROR; - } - - if (sq->need_offloaded != SPFC_NEED_DO_OFFLOAD) { - /* Ensure to be offloaded */ - if (unlikely(!atomic_read(&sq->sq_cached))) { - SPFC_ERR_IO_STAT((struct spfc_hba_info *)sq->hba, wqe_type); - SPFC_HBA_STAT((struct spfc_hba_info *)sq->hba, - SPFC_STAT_PARENT_SQ_NOT_OFFLOADED); - - FC_DRV_PRINT(UNF_LOG_NORMAL, UNF_ERR, - "[err]RPort(0x%x) Session(0x%x) is not offloaded, reject wqe(0x%x)", - sq->rport_index, sq->context_id, wqe_type); - - return UNF_RETURN_ERROR; - } - } - - /* Whether the SQ is in the flush state. Temporarily allow the control - * sessions to enqueue. - */ - if (unlikely(sq->port_in_flush && SPFC_WQE_IS_IO(io_sqe))) { - SPFC_ERR_IO_STAT((struct spfc_hba_info *)sq->hba, wqe_type); - SPFC_HBA_STAT((struct spfc_hba_info *)sq->hba, SPFC_STAT_PARENT_IO_FLUSHED); - - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Session(0x%x) in flush, Sqn(0x%x) cmsn(0x%x), reject wqe(0x%x)", - sq->context_id, ssqn, SPFC_GET_QUEUE_CMSN(ssq), - wqe_type); - - return UNF_RETURN_ERROR; - } - - /* If the SQ is in the Seesion deletion state and is the WQE of the I/O - * path, * the I/O failure is directly returned - */ - if (unlikely(sq->sq_in_sess_rst && SPFC_WQE_IS_IO(io_sqe))) { - SPFC_ERR_IO_STAT((struct spfc_hba_info *)sq->hba, wqe_type); - SPFC_HBA_STAT((struct spfc_hba_info *)sq->hba, SPFC_STAT_PARENT_IO_FLUSHED); - - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[err]Session(0x%x) in session reset, reject wqe(0x%x)", - sq->context_id, wqe_type); - - return UNF_RETURN_ERROR; - } - - return spfc_parent_ssq_enqueue(ssq, io_sqe, wqe_type); -} - -static bool spfc_msn_in_wqe_page(u32 start_msn, u32 end_msn, u32 cur_cmsn) -{ - bool ret = true; - - if (end_msn >= start_msn) { - if (cur_cmsn < start_msn || cur_cmsn > end_msn) - ret = false; - else - ret = true; - } else { - if (cur_cmsn > end_msn && cur_cmsn < start_msn) - ret = false; - else - ret = true; - } - - return ret; -} - -void spfc_free_sq_wqe_page(struct spfc_parent_ssq_info *ssq, u32 cur_cmsn) -{ - u16 wpg_start_cmsn = 0; - u16 wpg_end_cmsn = 0; - bool wqe_page_in_use = false; - - /* If there is only zero or one Wqe Page, no release is required */ - if (atomic_read(&ssq->wqe_page_cnt) <= SPFC_MIN_WP_NUM) - return; - - /* Check whether the current MSN is within the MSN range covered by the - * WqePage - */ - wpg_start_cmsn = ssq->head_start_cmsn; - wpg_end_cmsn = ssq->head_end_cmsn; - wqe_page_in_use = spfc_msn_in_wqe_page(wpg_start_cmsn, wpg_end_cmsn, cur_cmsn); - - /* If the value of CMSN is within the current Wqe Page, no release is - * required - */ - if (wqe_page_in_use) - return; - - /* If the next WqePage is available and the CMSN is not in the current - * WqePage, * the current WqePage is released - */ - while (!wqe_page_in_use && - (atomic_read(&ssq->wqe_page_cnt) > SPFC_MIN_WP_NUM)) { - /* Free WqePage */ - spfc_free_head_wqe_page(ssq); - - /* Obtain the start MSN of the next WqePage */ - wpg_start_cmsn = SPFC_MSN_INC(wpg_end_cmsn); - - /* obtain the end MSN of the next WqePage */ - wpg_end_cmsn = - SPFC_GET_WP_END_CMSN(wpg_start_cmsn, ssq->wqe_num_per_buf); - - /* Set new MSN range */ - ssq->head_start_cmsn = wpg_start_cmsn; - ssq->head_end_cmsn = wpg_end_cmsn; - cur_cmsn = SPFC_GET_QUEUE_CMSN(ssq); - /* Check whether the current MSN is within the MSN range covered - * by the WqePage - */ - wqe_page_in_use = spfc_msn_in_wqe_page(wpg_start_cmsn, wpg_end_cmsn, cur_cmsn); - } -} - -/* - *Function Name : SPFC_UpdateSqCompletionStat - *Function Description: Update the calculation statistics of the CQE - *corresponding to the WQE on the connection SQ. - *Input Parameters : *sq, *scqe - *Output Parameters : N/A - *Return Type : void - */ -static void spfc_update_sq_wqe_completion_stat(struct spfc_parent_ssq_info *ssq, - union spfc_scqe *scqe) -{ - struct spfc_scqe_rcv_els_gs_rsp *els_gs_rsp = NULL; - - els_gs_rsp = (struct spfc_scqe_rcv_els_gs_rsp *)scqe; - - /* For the ELS/GS RSP intermediate frame and the CQE that is more than - * the ELS_GS_RSP_EXCH_CHECK_FAIL, no statistics are required - */ - if (unlikely(SPFC_GET_SCQE_TYPE(scqe) == SPFC_SCQE_ELS_RSP) || - (SPFC_GET_SCQE_TYPE(scqe) == SPFC_SCQE_GS_RSP)) { - if (!els_gs_rsp->wd3.end_rsp || !SPFC_SCQE_ERR_TO_CM(scqe)) - return; - } - - /* When the SQ statistics are updated, the PlogiAcc or PlogiAccSts that - * is * implicitly unloaded will enter here, and one more CQE count is - * added - */ - atomic_inc(&ssq->sq_cqe_cnt); - atomic_dec(&ssq->sqe_minus_cqe_cnt); - SPFC_SQ_IO_STAT(ssq, SPFC_GET_SCQE_TYPE(scqe)); -} - -/* - *Function Name : spfc_reclaim_sq_wqe_page - *Function Description: Reclaim the Wqe Pgae that has been used up in the Linked - * List SQ. - *Input Parameters : *handle, - * *scqe - *Output Parameters : N/A - *Return Type : u32 - */ -u32 spfc_reclaim_sq_wqe_page(void *handle, union spfc_scqe *scqe) -{ - u32 ret = RETURN_OK; - u32 cur_cmsn = 0; - u32 sqn = INVALID_VALUE32; - struct spfc_parent_ssq_info *ssq = NULL; - struct spfc_parent_shared_queue_info *parent_queue_info = NULL; - struct spfc_hba_info *hba = NULL; - ulong flag = 0; - - hba = (struct spfc_hba_info *)handle; - sqn = SPFC_GET_SCQE_SQN(scqe); - if (sqn >= SPFC_MAX_SSQ_NUM) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[err]Port(0x%x) do not have sqn: 0x%x", - hba->port_cfg.port_id, sqn); - - return UNF_RETURN_ERROR; - } - - parent_queue_info = &hba->parent_queue_mgr->shared_queue[sqn]; - ssq = &parent_queue_info->parent_ssq_info; - /* If there is only zero or one Wqe Page, no release is required */ - if (atomic_read(&ssq->wqe_page_cnt) <= SPFC_MIN_WP_NUM) { - spfc_update_sq_wqe_completion_stat(ssq, scqe); - return RETURN_OK; - } - - spin_lock_irqsave(&ssq->parent_sq_enqueue_lock, flag); - cur_cmsn = SPFC_GET_QUEUE_CMSN(ssq); - spfc_free_sq_wqe_page(ssq, cur_cmsn); - spin_unlock_irqrestore(&ssq->parent_sq_enqueue_lock, flag); - - spfc_update_sq_wqe_completion_stat(ssq, scqe); - - return ret; -} - -u32 spfc_root_cmdq_enqueue(void *handle, union spfc_cmdqe *cmdqe, u16 cmd_len) -{ -#define SPFC_ROOTCMDQ_TIMEOUT_MS 3000 - u8 wqe_type = 0; - int cmq_ret = 0; - struct sphw_cmd_buf *cmd_buf = NULL; - struct spfc_hba_info *hba = NULL; - - hba = (struct spfc_hba_info *)handle; - wqe_type = (u8)cmdqe->common.wd0.task_type; - SPFC_IO_STAT(hba, wqe_type); - - cmd_buf = sphw_alloc_cmd_buf(hba->dev_handle); - if (!cmd_buf) { - SPFC_ERR_IO_STAT(hba, wqe_type); - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x) CqmHandle(0x%p) allocate cmdq buffer failed", - hba->port_cfg.port_id, hba->dev_handle); - - return UNF_RETURN_ERROR; - } - - memcpy(cmd_buf->buf, cmdqe, cmd_len); - spfc_cpu_to_big32(cmd_buf->buf, cmd_len); - cmd_buf->size = cmd_len; - - cmq_ret = sphw_cmdq_async(hba->dev_handle, COMM_MOD_FC, 0, cmd_buf, SPHW_CHANNEL_FC); - - if (cmq_ret != RETURN_OK) { - sphw_free_cmd_buf(hba->dev_handle, cmd_buf); - SPFC_ERR_IO_STAT(hba, wqe_type); - - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x) CqmHandle(0x%p) send buff clear cmnd failed(0x%x)", - hba->port_cfg.port_id, hba->dev_handle, cmq_ret); - return UNF_RETURN_ERROR; - } - - return RETURN_OK; -} - -struct spfc_parent_queue_info * -spfc_find_parent_queue_info_by_pkg(void *handle, struct unf_frame_pkg *pkg) -{ - u32 rport_index = 0; - struct spfc_parent_queue_info *parent_queue_info = NULL; - struct spfc_hba_info *hba = NULL; - - hba = (struct spfc_hba_info *)handle; - rport_index = pkg->private_data[PKG_PRIVATE_XCHG_RPORT_INDEX]; - - if (unlikely(rport_index >= UNF_SPFC_MAXRPORT_NUM)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[warn]Port(0x%x) send pkg sid_did(0x%x_0x%x), but uplevel allocate invalid rport index: 0x%x", - hba->port_cfg.port_id, pkg->frame_head.csctl_sid, - pkg->frame_head.rctl_did, rport_index); - - return NULL; - } - - /* parent -->> session */ - parent_queue_info = &hba->parent_queue_mgr->parent_queue[rport_index]; - - return parent_queue_info; -} - -struct spfc_parent_queue_info *spfc_find_parent_queue_info_by_id(struct spfc_hba_info *hba, - u32 local_id, u32 remote_id) -{ - u32 index = 0; - ulong flag = 0; - struct spfc_parent_queue_mgr *parent_queue_mgr = NULL; - struct spfc_parent_queue_info *parent_queue_info = NULL; - spinlock_t *prtq_state_lock = NULL; - u32 lport_id; - u32 rport_id; - - parent_queue_mgr = hba->parent_queue_mgr; - if (!parent_queue_mgr) - return NULL; - - /* rport_number -->> parent_number -->> session_number */ - for (index = 0; index < UNF_SPFC_MAXRPORT_NUM; index++) { - prtq_state_lock = &parent_queue_mgr->parent_queue[index].parent_queue_state_lock; - lport_id = parent_queue_mgr->parent_queue[index].parent_sq_info.local_port_id; - rport_id = parent_queue_mgr->parent_queue[index].parent_sq_info.remote_port_id; - spin_lock_irqsave(prtq_state_lock, flag); - - /* local_id & remote_id & offload */ - if (local_id == lport_id && remote_id == rport_id && - parent_queue_mgr->parent_queue[index].offload_state == - SPFC_QUEUE_STATE_OFFLOADED) { - parent_queue_info = &parent_queue_mgr->parent_queue[index]; - spin_unlock_irqrestore(prtq_state_lock, flag); - - return parent_queue_info; - } - - spin_unlock_irqrestore(prtq_state_lock, flag); - } - - return NULL; -} - -struct spfc_parent_queue_info *spfc_find_offload_parent_queue(void *handle, u32 local_id, - u32 remote_id, u32 rport_index) -{ - u32 index = 0; - ulong flag = 0; - struct spfc_parent_queue_mgr *parent_queue_mgr = NULL; - struct spfc_parent_queue_info *parent_queue_info = NULL; - struct spfc_hba_info *hba = NULL; - spinlock_t *prtq_state_lock = NULL; - - hba = (struct spfc_hba_info *)handle; - parent_queue_mgr = hba->parent_queue_mgr; - if (!parent_queue_mgr) - return NULL; - - for (index = 0; index < UNF_SPFC_MAXRPORT_NUM; index++) { - if (rport_index == index) - continue; - prtq_state_lock = &parent_queue_mgr->parent_queue[index].parent_queue_state_lock; - spin_lock_irqsave(prtq_state_lock, flag); - - if (local_id == parent_queue_mgr->parent_queue[index] - .parent_sq_info.local_port_id && - remote_id == parent_queue_mgr->parent_queue[index] - .parent_sq_info.remote_port_id && - parent_queue_mgr->parent_queue[index].offload_state != - SPFC_QUEUE_STATE_FREE && - parent_queue_mgr->parent_queue[index].offload_state != - SPFC_QUEUE_STATE_INITIALIZED) { - parent_queue_info = &parent_queue_mgr->parent_queue[index]; - spin_unlock_irqrestore(prtq_state_lock, flag); - - return parent_queue_info; - } - - spin_unlock_irqrestore(prtq_state_lock, flag); - } - - return NULL; -} - -struct spfc_parent_sq_info *spfc_find_parent_sq_by_pkg(void *handle, struct unf_frame_pkg *pkg) -{ - struct spfc_parent_queue_info *parent_queue_info = NULL; - struct cqm_qpc_mpt *cqm_parent_ctxt_obj = NULL; - struct spfc_hba_info *hba = NULL; - - hba = (struct spfc_hba_info *)handle; - parent_queue_info = spfc_find_parent_queue_info_by_pkg(hba, pkg); - if (unlikely(!parent_queue_info)) { - parent_queue_info = spfc_find_parent_queue_info_by_id(hba, - pkg->frame_head.csctl_sid & - UNF_NPORTID_MASK, - pkg->frame_head.rctl_did & - UNF_NPORTID_MASK); - if (!parent_queue_info) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[err]Port(0x%x) send pkg sid_did(0x%x_0x%x), get a null parent queue information", - hba->port_cfg.port_id, pkg->frame_head.csctl_sid, - pkg->frame_head.rctl_did); - - return NULL; - } - } - - cqm_parent_ctxt_obj = (parent_queue_info->parent_ctx.cqm_parent_ctx_obj); - if (unlikely(!cqm_parent_ctxt_obj)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[err]Port(0x%x) send pkg sid_did(0x%x_0x%x) with this rport has not alloc parent sq information", - hba->port_cfg.port_id, pkg->frame_head.csctl_sid, - pkg->frame_head.rctl_did); - - return NULL; - } - - return &parent_queue_info->parent_sq_info; -} - -u32 spfc_check_all_parent_queue_free(struct spfc_hba_info *hba) -{ - u32 index = 0; - ulong flag = 0; - struct spfc_parent_queue_mgr *parent_queue_mgr = NULL; - spinlock_t *prtq_state_lock = NULL; - - parent_queue_mgr = hba->parent_queue_mgr; - if (!parent_queue_mgr) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[err]Port(0x%x) get a null parent queue mgr", - hba->port_cfg.port_id); - - return UNF_RETURN_ERROR; - } - - for (index = 0; index < UNF_SPFC_MAXRPORT_NUM; index++) { - prtq_state_lock = &parent_queue_mgr->parent_queue[index].parent_queue_state_lock; - spin_lock_irqsave(prtq_state_lock, flag); - - if (parent_queue_mgr->parent_queue[index].offload_state != SPFC_QUEUE_STATE_FREE) { - spin_unlock_irqrestore(prtq_state_lock, flag); - return UNF_RETURN_ERROR; - } - - spin_unlock_irqrestore(prtq_state_lock, flag); - } - - return RETURN_OK; -} - -void spfc_flush_specific_scq(struct spfc_hba_info *hba, u32 index) -{ - /* The software interrupt is scheduled and processed during the second - * timeout period - */ - struct spfc_scq_info *scq_info = NULL; - u32 flush_done_time = 0; - - scq_info = &hba->scq_info[index]; - atomic_set(&scq_info->flush_stat, SPFC_QUEUE_FLUSH_DOING); - tasklet_schedule(&scq_info->tasklet); - - /* Wait for a maximum of 2 seconds. If the SCQ soft interrupt is not - * scheduled * within 2 seconds, only timeout is returned - */ - while ((atomic_read(&scq_info->flush_stat) != SPFC_QUEUE_FLUSH_DONE) && - (flush_done_time < SPFC_QUEUE_FLUSH_WAIT_TIMEOUT_MS)) { - msleep(SPFC_QUEUE_FLUSH_WAIT_MS); - flush_done_time += SPFC_QUEUE_FLUSH_WAIT_MS; - tasklet_schedule(&scq_info->tasklet); - } - - if (atomic_read(&scq_info->flush_stat) != SPFC_QUEUE_FLUSH_DONE) { - FC_DRV_PRINT(UNF_LOG_NORMAL, UNF_WARN, - "[warn]Port(0x%x) special scq(0x%x) flush timeout", - hba->port_cfg.port_id, index); - } -} - -static void spfc_flush_cmd_scq(struct spfc_hba_info *hba) -{ - u32 index = 0; - - for (index = SPFC_CMD_SCQN_START; index < SPFC_SESSION_SCQ_NUM; - index += SPFC_SCQS_PER_SESSION) { - spfc_flush_specific_scq(hba, index); - } -} - -static void spfc_flush_sts_scq(struct spfc_hba_info *hba) -{ - u32 index = 0; - - /* for each STS SCQ */ - for (index = SPFC_STS_SCQN_START; index < SPFC_SESSION_SCQ_NUM; - index += SPFC_SCQS_PER_SESSION) { - spfc_flush_specific_scq(hba, index); - } -} - -static void spfc_flush_all_scq(struct spfc_hba_info *hba) -{ - spfc_flush_cmd_scq(hba); - spfc_flush_sts_scq(hba); - /* Flush Default SCQ */ - spfc_flush_specific_scq(hba, SPFC_SESSION_SCQ_NUM); -} - -void spfc_wait_all_queues_empty(struct spfc_hba_info *hba) -{ - spfc_flush_all_scq(hba); -} - -void spfc_set_rport_flush_state(void *handle, bool in_flush) -{ - u32 index = 0; - ulong flag = 0; - struct spfc_parent_queue_mgr *parent_queue_mgr = NULL; - struct spfc_hba_info *hba = NULL; - - hba = (struct spfc_hba_info *)handle; - parent_queue_mgr = hba->parent_queue_mgr; - if (!parent_queue_mgr) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Port(0x%x) parent queue manager is empty", - hba->port_cfg.port_id); - return; - } - - /* - * for each HBA's R_Port(SQ), - * set state with been flushing or flush done - */ - for (index = 0; index < UNF_SPFC_MAXRPORT_NUM; index++) { - spin_lock_irqsave(&parent_queue_mgr->parent_queue[index] - .parent_sq_info.parent_sq_enqueue_lock, flag); - if (parent_queue_mgr->parent_queue[index].offload_state != SPFC_QUEUE_STATE_FREE) { - parent_queue_mgr->parent_queue[index] - .parent_sq_info.port_in_flush = in_flush; - } - spin_unlock_irqrestore(&parent_queue_mgr->parent_queue[index] - .parent_sq_info.parent_sq_enqueue_lock, flag); - } -} - -u32 spfc_clear_fetched_sq_wqe(void *handle) -{ - u32 ret = UNF_RETURN_ERROR; - union spfc_cmdqe cmdqe; - struct spfc_hba_info *hba = NULL; - - FC_CHECK_RETURN_VALUE(handle, UNF_RETURN_ERROR); - - hba = (struct spfc_hba_info *)handle; - /* - * The ROOT SQ cannot control the WQE in the empty queue of the ROOT SQ. - * Therefore, the ROOT SQ does not enqueue the WQE after the hardware - * obtains the. Link down after the wait mode is used. Therefore, the - * WQE of the hardware driver needs to enter the WQE of the queue after - * the Link down of the Link down is reported. - */ - memset(&cmdqe, 0, sizeof(union spfc_cmdqe)); - spfc_build_cmdqe_common(&cmdqe, SPFC_TASK_T_BUFFER_CLEAR, 0); - cmdqe.buffer_clear.wd1.rx_id_start = hba->exi_base; - cmdqe.buffer_clear.wd1.rx_id_end = hba->exi_base + hba->exi_count - 1; - cmdqe.buffer_clear.scqn = hba->default_scqn; - - FC_DRV_PRINT(UNF_LOG_EVENT, UNF_MAJOR, - "[info]Port(0x%x) start clear all fetched wqe in start(0x%x) - end(0x%x) scqn(0x%x) stage(0x%x)", - hba->port_cfg.port_id, cmdqe.buffer_clear.wd1.rx_id_start, - cmdqe.buffer_clear.wd1.rx_id_end, cmdqe.buffer_clear.scqn, - hba->queue_set_stage); - - /* Send BUFFER_CLEAR command via ROOT CMDQ */ - ret = spfc_root_cmdq_enqueue(hba, &cmdqe, sizeof(cmdqe.buffer_clear)); - - return ret; -} - -u32 spfc_clear_pending_sq_wqe(void *handle) -{ - u32 ret = UNF_RETURN_ERROR; - u32 cmdqe_len = 0; - ulong flag = 0; - struct spfc_parent_ssq_info *ssq_info = NULL; - union spfc_cmdqe cmdqe; - struct spfc_hba_info *hba = NULL; - - hba = (struct spfc_hba_info *)handle; - memset(&cmdqe, 0, sizeof(union spfc_cmdqe)); - spfc_build_cmdqe_common(&cmdqe, SPFC_TASK_T_FLUSH_SQ, 0); - cmdqe.flush_sq.wd0.wqe_type = SPFC_TASK_T_FLUSH_SQ; - cmdqe.flush_sq.wd1.scqn = SPFC_LSW(hba->default_scqn); - cmdqe.flush_sq.wd1.port_id = hba->port_index; - - ssq_info = &hba->parent_queue_mgr->shared_queue[ARRAY_INDEX_0].parent_ssq_info; - - spin_lock_irqsave(&ssq_info->parent_sq_enqueue_lock, flag); - cmdqe.flush_sq.wd3.first_sq_xid = ssq_info->context_id; - spin_unlock_irqrestore(&ssq_info->parent_sq_enqueue_lock, flag); - cmdqe.flush_sq.wd0.entry_count = SPFC_MAX_SSQ_NUM; - cmdqe.flush_sq.wd3.sqqid_start_per_session = SPFC_SQ_QID_START_PER_QPC; - cmdqe.flush_sq.wd3.sqcnt_per_session = SPFC_SQ_NUM_PER_QPC; - cmdqe.flush_sq.wd1.last_wqe = 1; - - /* Clear pending Queue */ - cmdqe_len = (u32)(sizeof(cmdqe.flush_sq)); - ret = spfc_root_cmdq_enqueue(hba, &cmdqe, (u16)cmdqe_len); - - FC_DRV_PRINT(UNF_LOG_EVENT, UNF_MAJOR, - "[info]Port(0x%x) clear total 0x%x SQ in this CMDQE(last=%u), stage (0x%x)", - hba->port_cfg.port_id, SPFC_MAX_SSQ_NUM, - cmdqe.flush_sq.wd1.last_wqe, hba->queue_set_stage); - - return ret; -} - -u32 spfc_wait_queue_set_flush_done(struct spfc_hba_info *hba) -{ - u32 flush_done_time = 0; - u32 ret = RETURN_OK; - - while ((hba->queue_set_stage != SPFC_QUEUE_SET_STAGE_FLUSHDONE) && - (flush_done_time < SPFC_QUEUE_FLUSH_WAIT_TIMEOUT_MS)) { - msleep(SPFC_QUEUE_FLUSH_WAIT_MS); - flush_done_time += SPFC_QUEUE_FLUSH_WAIT_MS; - } - - if (hba->queue_set_stage != SPFC_QUEUE_SET_STAGE_FLUSHDONE) { - FC_DRV_PRINT(UNF_LOG_NORMAL, UNF_WARN, - "[warn]Port(0x%x) queue sets flush timeout with stage(0x%x)", - hba->port_cfg.port_id, hba->queue_set_stage); - - ret = UNF_RETURN_ERROR; - } - - return ret; -} - -void spfc_disable_all_scq_schedule(struct spfc_hba_info *hba) -{ - struct spfc_scq_info *scq_info = NULL; - u32 index = 0; - - for (index = 0; index < SPFC_TOTAL_SCQ_NUM; index++) { - scq_info = &hba->scq_info[index]; - tasklet_disable(&scq_info->tasklet); - } -} - -void spfc_disable_queues_dispatch(struct spfc_hba_info *hba) -{ - spfc_disable_all_scq_schedule(hba); -} - -void spfc_enable_all_scq_schedule(struct spfc_hba_info *hba) -{ - struct spfc_scq_info *scq_info = NULL; - u32 index = 0; - - for (index = 0; index < SPFC_TOTAL_SCQ_NUM; index++) { - scq_info = &hba->scq_info[index]; - tasklet_enable(&scq_info->tasklet); - } -} - -void spfc_enalbe_queues_dispatch(void *handle) -{ - spfc_enable_all_scq_schedule((struct spfc_hba_info *)handle); -} - -/* - *Function Name : spfc_clear_els_srq - *Function Description: When the port is used as the remove, the resources - *related to the els srq are deleted. - *Input Parameters : *hba Output Parameters - *Return Type : void - */ -void spfc_clear_els_srq(struct spfc_hba_info *hba) -{ -#define SPFC_WAIT_CLR_SRQ_CTX_MS 500 -#define SPFC_WAIT_CLR_SRQ_CTX_LOOP_TIMES 60 - - u32 index = 0; - ulong flag = 0; - struct spfc_srq_info *srq_info = NULL; - - srq_info = &hba->els_srq_info; - - spin_lock_irqsave(&srq_info->srq_spin_lock, flag); - if (!srq_info->enable || srq_info->state == SPFC_CLEAN_DOING) { - spin_unlock_irqrestore(&srq_info->srq_spin_lock, flag); - - return; - } - srq_info->enable = false; - srq_info->state = SPFC_CLEAN_DOING; - spin_unlock_irqrestore(&srq_info->srq_spin_lock, flag); - - spfc_send_clear_srq_cmd(hba, &hba->els_srq_info); - - /* wait for uCode to clear SRQ context, the timer is 30S */ - while ((srq_info->state != SPFC_CLEAN_DONE) && - (index < SPFC_WAIT_CLR_SRQ_CTX_LOOP_TIMES)) { - msleep(SPFC_WAIT_CLR_SRQ_CTX_MS); - index++; - } - - if (srq_info->state != SPFC_CLEAN_DONE) { - FC_DRV_PRINT(UNF_LOG_NORMAL, UNF_WARN, - "[warn]SPFC Port(0x%x) clear els srq timeout", - hba->port_cfg.port_id); - } -} - -u32 spfc_wait_all_parent_queue_free(struct spfc_hba_info *hba) -{ -#define SPFC_MAX_LOOP_TIMES 6000 -#define SPFC_WAIT_ONE_TIME_MS 5 - u32 index = 0; - u32 ret = UNF_RETURN_ERROR; - - do { - ret = spfc_check_all_parent_queue_free(hba); - if (ret == RETURN_OK) - break; - - index++; - msleep(SPFC_WAIT_ONE_TIME_MS); - } while (index < SPFC_MAX_LOOP_TIMES); - - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_NORMAL, UNF_ERR, - "[warn]Port(0x%x) wait all parent queue state free timeout", - hba->port_cfg.port_id); - } - - return ret; -} - -/* - *Function Name : spfc_queue_pre_process - *Function Description: When the port functions as the remove, the queue needs - * to be preprocessed. - *Input Parameters : *handle, - * clean - *Output Parameters : N/A - *Return Type : void - */ -void spfc_queue_pre_process(void *handle, bool clean) -{ -#define SPFC_WAIT_LINKDOWN_EVENT_MS 500 - struct spfc_hba_info *hba = NULL; - - hba = (struct spfc_hba_info *)handle; - /* From port reset & port remove */ - /* 1. Wait for 2s and wait for QUEUE to be FLUSH Done. */ - if (spfc_wait_queue_set_flush_done(hba) != RETURN_OK) { - /* - * During the process of removing the card, if the port is - * disabled and the flush done is not available, the chip is - * powered off or the pcie link is disconnected. In this case, - * you can proceed with the next step. - */ - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[warn]SPFC Port(0x%x) clean queue sets timeout", - hba->port_cfg.port_id); - } - - /* - * 2. Port remove: - * 2.1 free parent queue - * 2.2 clear & destroy ELS/SIRT SRQ - */ - if (clean) { - if (spfc_wait_all_parent_queue_free(hba) != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, - UNF_WARN, - "[warn]SPFC Port(0x%x) free all parent queue timeout", - hba->port_cfg.port_id); - } - - /* clear & than destroy ELS/SIRT SRQ */ - spfc_clear_els_srq(hba); - } - - msleep(SPFC_WAIT_LINKDOWN_EVENT_MS); - - /* - * 3. The internal resources of the port chip are flush done. However, - * there may be residual scqe or rq in the queue. The scheduling is - * forcibly refreshed once. - */ - spfc_wait_all_queues_empty(hba); - - /* 4. Disable tasklet scheduling for upstream queues on the software - * layer - */ - spfc_disable_queues_dispatch(hba); -} - -void spfc_queue_post_process(void *hba) -{ - spfc_enalbe_queues_dispatch((struct spfc_hba_info *)hba); -} - -/* - *Function Name : spfc_push_delay_sqe - *Function Description: Check whether there is a sq that is being deleted. - * If yes, add the sq to the sq. - *Input Parameters : *hba, - * *offload_parent_queue, - * *sqe, - * *pkg - *Output Parameters : N/A - *Return Type : u32 - */ -u32 spfc_push_delay_sqe(void *hba, - struct spfc_parent_queue_info *offload_parent_queue, - struct spfc_sqe *sqe, struct unf_frame_pkg *pkg) -{ - ulong flag = 0; - spinlock_t *prtq_state_lock = NULL; - - prtq_state_lock = &offload_parent_queue->parent_queue_state_lock; - spin_lock_irqsave(prtq_state_lock, flag); - - if (offload_parent_queue->offload_state != SPFC_QUEUE_STATE_INITIALIZED && - offload_parent_queue->offload_state != SPFC_QUEUE_STATE_FREE) { - memcpy(&offload_parent_queue->parent_sq_info.delay_sqe.sqe, - sqe, sizeof(struct spfc_sqe)); - offload_parent_queue->parent_sq_info.delay_sqe.start_jiff = jiffies; - offload_parent_queue->parent_sq_info.delay_sqe.time_out = - pkg->private_data[PKG_PRIVATE_XCHG_TIMEER]; - offload_parent_queue->parent_sq_info.delay_sqe.valid = true; - offload_parent_queue->parent_sq_info.delay_sqe.rport_index = - pkg->private_data[PKG_PRIVATE_XCHG_RPORT_INDEX]; - offload_parent_queue->parent_sq_info.delay_sqe.sid = - pkg->frame_head.csctl_sid & UNF_NPORTID_MASK; - offload_parent_queue->parent_sq_info.delay_sqe.did = - pkg->frame_head.rctl_did & UNF_NPORTID_MASK; - offload_parent_queue->parent_sq_info.delay_sqe.xid = - sqe->ts_sl.xid; - offload_parent_queue->parent_sq_info.delay_sqe.ssqn = - (u16)pkg->private_data[PKG_PRIVATE_XCHG_SSQ_INDEX]; - - spin_unlock_irqrestore(prtq_state_lock, flag); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]Port(0x%x) RPort(0x%x) delay send ELS, OXID(0x%x), RXID(0x%x)", - ((struct spfc_hba_info *)hba)->port_cfg.port_id, - pkg->private_data[PKG_PRIVATE_XCHG_RPORT_INDEX], - UNF_GET_OXID(pkg), UNF_GET_RXID(pkg)); - - return RETURN_OK; - } - - spin_unlock_irqrestore(prtq_state_lock, flag); - - return UNF_RETURN_ERROR; -} - -static u32 spfc_pop_session_valid_check(struct spfc_hba_info *hba, - struct spfc_delay_sqe_ctrl_info *sqe_info, u32 rport_index) -{ - if (!sqe_info->valid) - return UNF_RETURN_ERROR; - - if (jiffies_to_msecs(jiffies - sqe_info->start_jiff) >= sqe_info->time_out) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) pop delay enable session failed, start time 0x%llx, timeout value 0x%x", - hba->port_cfg.port_id, sqe_info->start_jiff, - sqe_info->time_out); - - return UNF_RETURN_ERROR; - } - - if (rport_index >= UNF_SPFC_MAXRPORT_NUM) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) pop delay enable session failed, rport index(0x%x) is invalid", - hba->port_cfg.port_id, rport_index); - - return UNF_RETURN_ERROR; - } - - return RETURN_OK; -} - -/* - *Function Name : spfc_pop_delay_sqe - *Function Description: The sqe that is delayed due to the deletion of the old - * connection is sent to the root sq for - *processing. Input Parameters : *hba, *sqe_info Output Parameters : N/A - *Return Type : void - */ -static void spfc_pop_delay_sqe(struct spfc_hba_info *hba, - struct spfc_delay_sqe_ctrl_info *sqe_info) -{ - ulong flag; - u32 delay_rport_index = INVALID_VALUE32; - struct spfc_parent_queue_info *parent_queue = NULL; - enum spfc_parent_queue_state offload_state = - SPFC_QUEUE_STATE_DESTROYING; - struct spfc_delay_destroy_ctrl_info destroy_sqe_info; - u32 ret = UNF_RETURN_ERROR; - struct spfc_parent_sq_info *sq_info = NULL; - spinlock_t *prtq_state_lock = NULL; - - memset(&destroy_sqe_info, 0, sizeof(struct spfc_delay_destroy_ctrl_info)); - delay_rport_index = sqe_info->rport_index; - - /* According to the sequence, the rport index id is reported and then - * the sqe of the new link setup request is delivered. - */ - ret = spfc_pop_session_valid_check(hba, sqe_info, delay_rport_index); - - if (ret != RETURN_OK) - return; - - parent_queue = &hba->parent_queue_mgr->parent_queue[delay_rport_index]; - sq_info = &parent_queue->parent_sq_info; - prtq_state_lock = &parent_queue->parent_queue_state_lock; - /* Before the root sq is delivered, check the status again to - * ensure that the initialization status is not uninstalled. Other - * states are not processed and are discarded directly. - */ - spin_lock_irqsave(prtq_state_lock, flag); - offload_state = parent_queue->offload_state; - - /* Before re-enqueuing the rootsq, check whether the offload status and - * connection information is consistent to prevent the old request from - * being sent after the connection status is changed. - */ - if (offload_state == SPFC_QUEUE_STATE_INITIALIZED && - parent_queue->parent_sq_info.local_port_id == sqe_info->sid && - parent_queue->parent_sq_info.remote_port_id == sqe_info->did && - SPFC_CHECK_XID_MATCHED(parent_queue->parent_sq_info.context_id, - sqe_info->sqe.ts_sl.xid)) { - parent_queue->offload_state = SPFC_QUEUE_STATE_OFFLOADING; - spin_unlock_irqrestore(prtq_state_lock, flag); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x) pop up delay session enable, sqe start time 0x%llx, timeout value 0x%x, rport index 0x%x, offload state 0x%x", - hba->port_cfg.port_id, sqe_info->start_jiff, - sqe_info->time_out, delay_rport_index, offload_state); - - if (spfc_parent_sq_enqueue(sq_info, &sqe_info->sqe, sqe_info->ssqn) != RETURN_OK) { - spin_lock_irqsave(prtq_state_lock, flag); - - if (parent_queue->offload_state == SPFC_QUEUE_STATE_OFFLOADING) - parent_queue->offload_state = offload_state; - - if (parent_queue->parent_sq_info.destroy_sqe.valid) { - memcpy(&destroy_sqe_info, - &parent_queue->parent_sq_info.destroy_sqe, - sizeof(struct spfc_delay_destroy_ctrl_info)); - - parent_queue->parent_sq_info.destroy_sqe.valid = false; - } - - spin_unlock_irqrestore(prtq_state_lock, flag); - - spfc_pop_destroy_parent_queue_sqe((void *)hba, &destroy_sqe_info); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) pop up delay session enable fail, recover offload state 0x%x", - hba->port_cfg.port_id, parent_queue->offload_state); - return; - } - } else { - spin_unlock_irqrestore(prtq_state_lock, flag); - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port 0x%x pop delay session enable failed, sqe start time 0x%llx, timeout value 0x%x, rport index 0x%x, offload state 0x%x", - hba->port_cfg.port_id, sqe_info->start_jiff, - sqe_info->time_out, delay_rport_index, - offload_state); - } -} - -void spfc_push_destroy_parent_queue_sqe(void *hba, - struct spfc_parent_queue_info *offloading_parent_queue, - struct unf_port_info *rport_info) -{ - offloading_parent_queue->parent_sq_info.destroy_sqe.valid = true; - offloading_parent_queue->parent_sq_info.destroy_sqe.rport_index = rport_info->rport_index; - offloading_parent_queue->parent_sq_info.destroy_sqe.time_out = - SPFC_SQ_DEL_STAGE_TIMEOUT_MS; - offloading_parent_queue->parent_sq_info.destroy_sqe.start_jiff = jiffies; - offloading_parent_queue->parent_sq_info.destroy_sqe.rport_info.nport_id = - rport_info->nport_id; - offloading_parent_queue->parent_sq_info.destroy_sqe.rport_info.rport_index = - rport_info->rport_index; - offloading_parent_queue->parent_sq_info.destroy_sqe.rport_info.port_name = - rport_info->port_name; -} - -/* - *Function Name : spfc_pop_destroy_parent_queue_sqe - *Function Description: The deletion connection sqe that is delayed due to - * connection uninstallation is sent to - *the parent sq for processing. Input Parameters : *handle, *destroy_sqe_info - *Output Parameters : N/A - *Return Type : void - */ -void spfc_pop_destroy_parent_queue_sqe(void *handle, - struct spfc_delay_destroy_ctrl_info *destroy_sqe_info) -{ - u32 ret = UNF_RETURN_ERROR; - ulong flag; - u32 index = INVALID_VALUE32; - struct spfc_parent_queue_info *parent_queue = NULL; - enum spfc_parent_queue_state offload_state = - SPFC_QUEUE_STATE_DESTROYING; - struct spfc_hba_info *hba = NULL; - spinlock_t *prtq_state_lock = NULL; - - hba = (struct spfc_hba_info *)handle; - if (!destroy_sqe_info->valid) - return; - - if (jiffies_to_msecs(jiffies - destroy_sqe_info->start_jiff) < destroy_sqe_info->time_out) { - index = destroy_sqe_info->rport_index; - parent_queue = &hba->parent_queue_mgr->parent_queue[index]; - prtq_state_lock = &parent_queue->parent_queue_state_lock; - /* Before delivery, check the status again to ensure that the - * initialization status is not uninstalled. Other states are - * not processed and are discarded directly. - */ - spin_lock_irqsave(prtq_state_lock, flag); - - offload_state = parent_queue->offload_state; - if (offload_state == SPFC_QUEUE_STATE_OFFLOADED || - offload_state == SPFC_QUEUE_STATE_INITIALIZED) { - spin_unlock_irqrestore(prtq_state_lock, flag); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port 0x%x pop up delay destroy parent sq, sqe start time 0x%llx, timeout value 0x%x, rport index 0x%x, offload state 0x%x", - hba->port_cfg.port_id, - destroy_sqe_info->start_jiff, - destroy_sqe_info->time_out, - index, offload_state); - ret = spfc_free_parent_resource(hba, &destroy_sqe_info->rport_info); - } else { - ret = UNF_RETURN_ERROR; - spin_unlock_irqrestore(prtq_state_lock, flag); - } - } - - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port 0x%x pop delay destroy parent sq failed, sqe start time 0x%llx, timeout value 0x%x, rport index 0x%x, rport nport id 0x%x,offload state 0x%x", - hba->port_cfg.port_id, destroy_sqe_info->start_jiff, - destroy_sqe_info->time_out, index, - destroy_sqe_info->rport_info.nport_id, offload_state); - } -} - -void spfc_free_parent_queue_info(void *handle, struct spfc_parent_queue_info *parent_queue_info) -{ - ulong flag = 0; - u32 ret = UNF_RETURN_ERROR; - u32 rport_index = INVALID_VALUE32; - struct spfc_hba_info *hba = NULL; - struct spfc_delay_sqe_ctrl_info sqe_info; - spinlock_t *prtq_state_lock = NULL; - - memset(&sqe_info, 0, sizeof(struct spfc_delay_sqe_ctrl_info)); - hba = (struct spfc_hba_info *)handle; - prtq_state_lock = &parent_queue_info->parent_queue_state_lock; - spin_lock_irqsave(prtq_state_lock, flag); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "[info]Port(0x%x) begin to free parent sq, rport_index(0x%x)", - hba->port_cfg.port_id, parent_queue_info->parent_sq_info.rport_index); - - if (parent_queue_info->offload_state == SPFC_QUEUE_STATE_FREE) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[info]Port(0x%x) duplicate free parent sq, rport_index(0x%x)", - hba->port_cfg.port_id, - parent_queue_info->parent_sq_info.rport_index); - - spin_unlock_irqrestore(prtq_state_lock, flag); - return; - } - - if (parent_queue_info->parent_sq_info.delay_sqe.valid) { - memcpy(&sqe_info, &parent_queue_info->parent_sq_info.delay_sqe, - sizeof(struct spfc_delay_sqe_ctrl_info)); - } - - rport_index = parent_queue_info->parent_sq_info.rport_index; - - /* The Parent Contexe and SQ information is released. After - * initialization, the Parent Contexe and SQ information is associated - * with the sq in the queue of the parent - */ - - spfc_free_parent_sq(hba, parent_queue_info); - - /* The initialization of all queue id is invalid */ - parent_queue_info->parent_cmd_scq_info.cqm_queue_id = INVALID_VALUE32; - parent_queue_info->parent_sts_scq_info.cqm_queue_id = INVALID_VALUE32; - parent_queue_info->parent_els_srq_info.cqm_queue_id = INVALID_VALUE32; - parent_queue_info->offload_state = SPFC_QUEUE_STATE_FREE; - - spin_unlock_irqrestore(prtq_state_lock, flag); - - UNF_LOWLEVEL_PORT_EVENT(ret, hba->lport, UNF_PORT_RELEASE_RPORT_INDEX, - (void *)&rport_index); - - spfc_pop_delay_sqe(hba, &sqe_info); - - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[warn]Port(0x%x) free parent sq with rport_index(0x%x) failed", - hba->port_cfg.port_id, rport_index); - } -} - -static void spfc_do_port_reset(struct work_struct *work) -{ - struct spfc_suspend_sqe_info *suspend_sqe = NULL; - struct spfc_hba_info *hba = NULL; - - FC_CHECK_RETURN_VOID(work); - - suspend_sqe = container_of(work, struct spfc_suspend_sqe_info, - timeout_work.work); - hba = (struct spfc_hba_info *)suspend_sqe->hba; - FC_CHECK_RETURN_VOID(hba); - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x) magic num (0x%x)do port reset.", - hba->port_cfg.port_id, suspend_sqe->magic_num); - - spfc_port_reset(hba); -} - -static void -spfc_push_sqe_suspend(void *hba, struct spfc_parent_queue_info *parent_queue, - struct spfc_sqe *sqe, struct unf_frame_pkg *pkg, u32 magic_num) -{ -#define SPFC_SQ_NOP_TIMEOUT_MS 1000 - ulong flag = 0; - u32 sqn_base; - struct spfc_parent_sq_info *sq = NULL; - struct spfc_suspend_sqe_info *suspend_sqe = NULL; - - sq = &parent_queue->parent_sq_info; - suspend_sqe = - kmalloc(sizeof(struct spfc_suspend_sqe_info), GFP_ATOMIC); - if (!suspend_sqe) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[err]alloc suspend sqe memory failed"); - return; - } - memset(suspend_sqe, 0, sizeof(struct spfc_suspend_sqe_info)); - memcpy(&suspend_sqe->sqe, sqe, sizeof(struct spfc_sqe)); - suspend_sqe->magic_num = magic_num; - suspend_sqe->old_offload_sts = sq->need_offloaded; - suspend_sqe->hba = sq->hba; - - if (pkg) { - memcpy(&suspend_sqe->pkg, pkg, sizeof(struct unf_frame_pkg)); - } else { - sqn_base = sq->sqn_base; - suspend_sqe->pkg.private_data[PKG_PRIVATE_XCHG_SSQ_INDEX] = - sqn_base; - } - - INIT_DELAYED_WORK(&suspend_sqe->timeout_work, spfc_do_port_reset); - INIT_LIST_HEAD(&suspend_sqe->list_sqe_entry); - - spin_lock_irqsave(&parent_queue->parent_queue_state_lock, flag); - list_add_tail(&suspend_sqe->list_sqe_entry, &sq->suspend_sqe_list); - spin_unlock_irqrestore(&parent_queue->parent_queue_state_lock, flag); - - (void)queue_delayed_work(((struct spfc_hba_info *)hba)->work_queue, - &suspend_sqe->timeout_work, - (ulong)msecs_to_jiffies((u32)SPFC_SQ_NOP_TIMEOUT_MS)); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]Port(0x%x) magic num(0x%x)suspend sqe", - ((struct spfc_hba_info *)hba)->port_cfg.port_id, magic_num); -} - -u32 spfc_pop_suspend_sqe(void *handle, struct spfc_parent_queue_info *parent_queue, - struct spfc_suspend_sqe_info *suspen_sqe) -{ - ulong flag; - u32 ret = UNF_RETURN_ERROR; - struct spfc_parent_sq_info *sq = NULL; - u16 ssqn; - struct unf_frame_pkg *pkg = NULL; - struct spfc_hba_info *hba = (struct spfc_hba_info *)handle; - u8 task_type; - spinlock_t *prtq_state_lock = NULL; - - sq = &parent_queue->parent_sq_info; - task_type = suspen_sqe->sqe.ts_sl.task_type; - pkg = &suspen_sqe->pkg; - if (!pkg) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, - UNF_MAJOR, "[error]pkt is null."); - return UNF_RETURN_ERROR; - } - - ssqn = (u16)pkg->private_data[PKG_PRIVATE_XCHG_SSQ_INDEX]; - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x) pop up suspend wqe sqn (0x%x) TaskType(0x%x)", - hba->port_cfg.port_id, ssqn, task_type); - - prtq_state_lock = &parent_queue->parent_queue_state_lock; - spin_lock_irqsave(prtq_state_lock, flag); - if (SPFC_RPORT_NOT_OFFLOADED(parent_queue) && - (task_type == SPFC_SQE_ELS_RSP || - task_type == SPFC_TASK_T_ELS)) { - spin_unlock_irqrestore(prtq_state_lock, flag); - /* Send PLOGI or PLOGI ACC or SCR if session not offload */ - ret = spfc_send_els_via_default_session(hba, &suspen_sqe->sqe, pkg, parent_queue); - } else { - spin_unlock_irqrestore(prtq_state_lock, flag); - ret = spfc_parent_sq_enqueue(sq, &suspen_sqe->sqe, ssqn); - } - return ret; -} - -static void spfc_build_nop_sqe(struct spfc_hba_info *hba, struct spfc_parent_sq_info *sq, - struct spfc_sqe *sqe, u32 magic_num, u32 scqn) -{ - sqe->ts_sl.task_type = SPFC_SQE_NOP; - sqe->ts_sl.wd0.conn_id = (u16)(sq->rport_index); - sqe->ts_sl.cont.nop_sq.wd0.scqn = scqn; - sqe->ts_sl.cont.nop_sq.magic_num = magic_num; - spfc_build_common_wqe_ctrls(&sqe->ctrl_sl, - sizeof(struct spfc_sqe_ts) / SPFC_WQE_SECTION_CHUNK_SIZE); -} - -u32 spfc_send_nop_cmd(void *handle, struct spfc_parent_sq_info *parent_sq_info, - u32 magic_num, u16 sqn) -{ - struct spfc_sqe empty_sq_sqe; - struct spfc_hba_info *hba = (struct spfc_hba_info *)handle; - u32 ret; - - memset(&empty_sq_sqe, 0, sizeof(struct spfc_sqe)); - - spfc_build_nop_sqe(hba, parent_sq_info, &empty_sq_sqe, magic_num, hba->default_scqn); - ret = spfc_parent_sq_enqueue(parent_sq_info, &empty_sq_sqe, sqn); - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]send nop cmd scqn(0x%x) sq(0x%x).", - hba->default_scqn, sqn); - return ret; -} - -u32 spfc_suspend_sqe_and_send_nop(void *handle, - struct spfc_parent_queue_info *parent_queue, - struct spfc_sqe *sqe, struct unf_frame_pkg *pkg) -{ - u32 ret = UNF_RETURN_ERROR; - u32 magic_num; - struct spfc_hba_info *hba = (struct spfc_hba_info *)handle; - struct spfc_parent_sq_info *parent_sq = &parent_queue->parent_sq_info; - struct unf_lport *lport = (struct unf_lport *)hba->lport; - - FC_CHECK_RETURN_VALUE(lport, UNF_RETURN_ERROR); - - if (pkg) { - magic_num = pkg->private_data[PKG_PRIVATE_XCHG_ALLOC_TIME]; - } else { - magic_num = (u32)atomic64_inc_return(&((struct unf_lport *) - lport->root_lport)->exchg_index); - } - - spfc_push_sqe_suspend(hba, parent_queue, sqe, pkg, magic_num); - if (SPFC_RPORT_NOT_OFFLOADED(parent_queue)) - parent_sq->need_offloaded = SPFC_NEED_DO_OFFLOAD; - - ret = spfc_send_nop_cmd(hba, parent_sq, magic_num, - (u16)parent_sq->sqn_base); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[err]Port(0x%x) rport_index(0x%x)send sq empty failed.", - hba->port_cfg.port_id, parent_sq->rport_index); - } - return ret; -} - -void spfc_build_session_rst_wqe(void *handle, struct spfc_parent_sq_info *sq, - struct spfc_sqe *sqe, enum spfc_session_reset_mode mode, u32 scqn) -{ - struct spfc_hba_info *hba = NULL; - - hba = (struct spfc_hba_info *)handle; - /* The reset session command does not occupy xid. Therefore, - * 0xffff can be used to align with the microcode. - */ - sqe->ts_sl.task_type = SPFC_SQE_SESS_RST; - sqe->ts_sl.local_xid = 0xffff; - sqe->ts_sl.wd0.conn_id = (u16)(sq->rport_index); - sqe->ts_sl.wd0.remote_xid = 0xffff; - sqe->ts_sl.cont.reset_session.wd0.reset_exch_start = hba->exi_base; - sqe->ts_sl.cont.reset_session.wd0.reset_exch_end = hba->exi_base + (hba->exi_count - 1); - sqe->ts_sl.cont.reset_session.wd1.reset_did = sq->remote_port_id; - sqe->ts_sl.cont.reset_session.wd1.mode = mode; - sqe->ts_sl.cont.reset_session.wd2.reset_sid = sq->local_port_id; - sqe->ts_sl.cont.reset_session.wd3.scqn = scqn; - - spfc_build_common_wqe_ctrls(&sqe->ctrl_sl, - sizeof(struct spfc_sqe_ts) / SPFC_WQE_SECTION_CHUNK_SIZE); -} - -u32 spfc_send_session_rst_cmd(void *handle, - struct spfc_parent_queue_info *parent_queue_info, - enum spfc_session_reset_mode mode) -{ - struct spfc_parent_sq_info *sq = NULL; - struct spfc_sqe rst_sess_sqe; - u32 ret = UNF_RETURN_ERROR; - u32 sts_scqn = 0; - struct spfc_hba_info *hba = NULL; - - hba = (struct spfc_hba_info *)handle; - memset(&rst_sess_sqe, 0, sizeof(struct spfc_sqe)); - sq = &parent_queue_info->parent_sq_info; - sts_scqn = hba->default_scqn; - - spfc_build_session_rst_wqe(hba, sq, &rst_sess_sqe, mode, sts_scqn); - ret = spfc_suspend_sqe_and_send_nop(hba, parent_queue_info, &rst_sess_sqe, NULL); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]RPort(0x%x) send SESS_RST(%d) start_exch_id(0x%x) end_exch_id(0x%x), scqn(0x%x) ctx_id(0x%x) cid(0x%x)", - sq->rport_index, mode, - rst_sess_sqe.ts_sl.cont.reset_session.wd0.reset_exch_start, - rst_sess_sqe.ts_sl.cont.reset_session.wd0.reset_exch_end, - rst_sess_sqe.ts_sl.cont.reset_session.wd3.scqn, - sq->context_id, sq->cache_id); - return ret; -} - -void spfc_rcvd_els_from_srq_timeout(struct work_struct *work) -{ - struct spfc_hba_info *hba = NULL; - - hba = container_of(work, struct spfc_hba_info, srq_delay_info.del_work.work); - - /* If the frame is not processed, the frame is pushed to the CM layer: - * The frame may have been processed when the root rq receives data. - */ - if (hba->srq_delay_info.srq_delay_flag) { - spfc_recv_els_cmnd(hba, &hba->srq_delay_info.frame_pkg, - hba->srq_delay_info.frame_pkg.unf_cmnd_pload_bl.buffer_ptr, - 0, false); - hba->srq_delay_info.srq_delay_flag = 0; - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]Port(0x%x) srq delay work timeout, send saved plgoi to CM", - hba->port_cfg.port_id); - } -} - -u32 spfc_flush_ini_resp_queue(void *handle) -{ - struct spfc_hba_info *hba = NULL; - - FC_CHECK_RETURN_VALUE(handle, UNF_RETURN_ERROR); - hba = (struct spfc_hba_info *)handle; - - spfc_flush_sts_scq(hba); - - return RETURN_OK; -} - -static void spfc_handle_aeq_queue_error(struct spfc_hba_info *hba, - struct spfc_aqe_data *aeq_msg) -{ - u32 sts_scqn_local = 0; - u32 full_ci = INVALID_VALUE32; - u32 full_ci_owner = INVALID_VALUE32; - struct spfc_scq_info *scq_info = NULL; - - sts_scqn_local = SPFC_RPORTID_TO_STS_SCQN(aeq_msg->wd0.conn_id); - scq_info = &hba->scq_info[sts_scqn_local]; - full_ci = scq_info->ci; - full_ci_owner = scq_info->ci_owner; - - /* Currently, Flush is forcibly set to StsScq. No matter whether scq is - * processed, AEQE is returned - */ - tasklet_schedule(&scq_info->tasklet); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]Port(0x%x) RPort(0x%x) LocalScqn(0x%x) CqmScqn(0x%x) is full, force flush CI from (%u|0x%x) to (%u|0x%x)", - hba->port_cfg.port_id, aeq_msg->wd0.conn_id, - sts_scqn_local, scq_info->scqn, full_ci_owner, full_ci, - scq_info->ci_owner, scq_info->ci); -} - -void spfc_process_aeqe(void *handle, u8 event_type, u8 *val) -{ - u32 ret = RETURN_OK; - struct spfc_hba_info *hba = (struct spfc_hba_info *)handle; - struct spfc_aqe_data aeq_msg; - u8 event_code = INVALID_VALUE8; - u64 event_val = *((u64 *)val); - - FC_CHECK_RETURN_VOID(hba); - - memcpy(&aeq_msg, (struct spfc_aqe_data *)&event_val, sizeof(struct spfc_aqe_data)); - event_code = (u8)aeq_msg.wd0.evt_code; - - switch (event_type) { - case FC_AEQ_EVENT_QUEUE_ERROR: - spfc_handle_aeq_queue_error(hba, &aeq_msg); - break; - - case FC_AEQ_EVENT_WQE_FATAL_ERROR: - UNF_LOWLEVEL_PORT_EVENT(ret, hba->lport, - UNF_PORT_ABNORMAL_RESET, NULL); - break; - - case FC_AEQ_EVENT_CTX_FATAL_ERROR: - break; - - case FC_AEQ_EVENT_OFFLOAD_ERROR: - ret = spfc_handle_aeq_off_load_err(hba, &aeq_msg); - break; - - default: - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[warn]Port(0x%x) receive a unsupported AEQ EventType(0x%x) EventVal(0x%llx).", - hba->port_cfg.port_id, event_type, (u64)event_val); - return; - } - - if (event_code < FC_AEQ_EVT_ERR_CODE_BUTT) - SPFC_AEQ_ERR_TYPE_STAT(hba, aeq_msg.wd0.evt_code); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_KEVENT, - "[info]Port(0x%x) receive AEQ EventType(0x%x) EventVal(0x%llx) EvtCode(0x%x) Conn_id(0x%x) Xid(0x%x) %s", - hba->port_cfg.port_id, event_type, (u64)event_val, event_code, - aeq_msg.wd0.conn_id, aeq_msg.wd1.xid, - (ret == UNF_RETURN_ERROR) ? "ERROR" : "OK"); -} - -void spfc_sess_resource_free_sync(void *handle, - struct unf_port_info *rport_info) -{ - struct spfc_parent_queue_info *parent_queue_info = NULL; - ulong flag = 0; - u32 wait_sq_cnt = 0; - struct spfc_hba_info *hba = NULL; - spinlock_t *prtq_state_lock = NULL; - u32 index = SPFC_DEFAULT_RPORT_INDEX; - - FC_CHECK_RETURN_VOID(handle); - FC_CHECK_RETURN_VOID(rport_info); - - hba = (struct spfc_hba_info *)handle; - parent_queue_info = &hba->parent_queue_mgr->parent_queue[index]; - prtq_state_lock = &parent_queue_info->parent_queue_state_lock; - (void)spfc_free_parent_resource((void *)hba, rport_info); - - for (;;) { - spin_lock_irqsave(prtq_state_lock, flag); - if (parent_queue_info->offload_state == SPFC_QUEUE_STATE_FREE) { - spin_unlock_irqrestore(prtq_state_lock, flag); - break; - } - spin_unlock_irqrestore(prtq_state_lock, flag); - msleep(SPFC_WAIT_SESS_FREE_ONE_TIME_MS); - wait_sq_cnt++; - if (wait_sq_cnt >= SPFC_MAX_WAIT_LOOP_TIMES) - break; - } -} diff --git a/drivers/scsi/spfc/hw/spfc_queue.h b/drivers/scsi/spfc/hw/spfc_queue.h deleted file mode 100644 index c09f098e7324..000000000000 --- a/drivers/scsi/spfc/hw/spfc_queue.h +++ /dev/null @@ -1,711 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPFC_QUEUE_H -#define SPFC_QUEUE_H - -#include "unf_type.h" -#include "spfc_wqe.h" -#include "spfc_cqm_main.h" -#define SPFC_MIN_WP_NUM (2) -#define SPFC_EXTEND_WQE_OFFSET (128) -#define SPFC_SQE_SIZE (256) -#define WQE_MARKER_0 (0x0) -#define WQE_MARKER_6B (0x6b) - -/* PARENT SQ & Context defines */ -#define SPFC_MAX_MSN (65535) -#define SPFC_MSN_MASK (0xffff000000000000LL) -#define SPFC_SQE_TS_SIZE (72) -#define SPFC_SQE_FIRST_OBIT_DW_POS (0) -#define SPFC_SQE_SECOND_OBIT_DW_POS (30) -#define SPFC_SQE_OBIT_SET_MASK_BE (0x80) -#define SPFC_SQE_OBIT_CLEAR_MASK_BE (0xffffff7f) -#define SPFC_MAX_SQ_TASK_TYPE_CNT (128) -#define SPFC_SQ_NUM_PER_QPC (3) -#define SPFC_SQ_QID_START_PER_QPC 0 -#define SPFC_SQ_SPACE_OFFSET (64) -#define SPFC_MAX_SSQ_NUM (SPFC_SQ_NUM_PER_QPC * 63 + 1) /* must be a multiple of 3 */ -#define SPFC_DIRECTWQE_SQ_INDEX (SPFC_MAX_SSQ_NUM - 1) - -/* Note: if the location of flush done bit changes, the definition must be - * modifyed again - */ -#define SPFC_CTXT_FLUSH_DONE_DW_POS (58) -#define SPFC_CTXT_FLUSH_DONE_MASK_BE (0x4000) -#define SPFC_CTXT_FLUSH_DONE_MASK_LE (0x400000) - -#define SPFC_PCIE_TEMPLATE (0) -#define SPFC_DMA_ATTR_OFST (0) - -/* - *When driver assembles WQE SGE, the GPA parity bit is multiplexed as follows: - * {rsvd'2,zerocopysoro'2,zerocopy_dmaattr_idx'6,pcie_template'6} - */ -#define SPFC_PCIE_TEMPLATE_OFFSET 0 -#define SPFC_PCIE_ZEROCOPY_DMAATTR_IDX_OFFSET 6 -#define SPFC_PCIE_ZEROCOPY_SO_RO_OFFSET 12 -#define SPFC_PCIE_RELAXED_ORDERING (1) -#define SPFC_ZEROCOPY_PCIE_TEMPLATE_VALUE \ - (SPFC_PCIE_RELAXED_ORDERING << SPFC_PCIE_ZEROCOPY_SO_RO_OFFSET | \ - SPFC_DMA_ATTR_OFST << SPFC_PCIE_ZEROCOPY_DMAATTR_IDX_OFFSET | \ - SPFC_PCIE_TEMPLATE) - -#define SPFC_GET_SQ_HEAD(sq) \ - list_entry(UNF_OS_LIST_NEXT(&(sq)->list_linked_list_sq), \ - struct spfc_wqe_page, entry_wpg) -#define SPFC_GET_SQ_TAIL(sq) \ - list_entry(UNF_OS_LIST_PREV(&(sq)->list_linked_list_sq), \ - struct spfc_wqe_page, entry_wpg) -#define SPFC_SQ_IO_STAT(ssq, io_type) \ - (atomic_inc(&(ssq)->io_stat[io_type])) -#define SPFC_SQ_IO_STAT_READ(ssq, io_type) \ - (atomic_read(&(ssq)->io_stat[io_type])) -#define SPFC_GET_QUEUE_CMSN(ssq) \ - ((u32)(be64_to_cpu(((((ssq)->queue_header)->ci_record) & SPFC_MSN_MASK)))) -#define SPFC_GET_WP_END_CMSN(head_start_cmsn, wqe_num_per_buf) \ - ((u16)(((u32)(head_start_cmsn) + (u32)(wqe_num_per_buf) - 1) % (SPFC_MAX_MSN + 1))) -#define SPFC_MSN_INC(msn) (((SPFC_MAX_MSN) == (msn)) ? 0 : ((msn) + 1)) -#define SPFC_MSN_DEC(msn) (((msn) == 0) ? (SPFC_MAX_MSN) : ((msn) - 1)) -#define SPFC_QUEUE_MSN_OFFSET(start_cmsn, end_cmsn) \ - ((u32)((((u32)(end_cmsn) + (SPFC_MAX_MSN)) - (u32)(start_cmsn)) % (SPFC_MAX_MSN + 1))) -#define SPFC_MSN32_ADD(msn, inc) (((msn) + (inc)) % (SPFC_MAX_MSN + 1)) - -/* - *SCQ defines - */ -#define SPFC_INT_NUM_PER_QUEUE (1) -#define SPFC_SCQ_INT_ID_MAX (2048) /* 11BIT */ -#define SPFC_SCQE_SIZE (64) -#define SPFC_CQE_GPA_SHIFT (4) -#define SPFC_NEXT_CQE_GPA_SHIFT (12) -/* 1-Update Ci by Tile, 0-Update Ci by Hardware */ -#define SPFC_PMSN_CI_TYPE_FROM_HOST (0) -#define SPFC_PMSN_CI_TYPE_FROM_UCODE (1) -#define SPFC_ARMQ_IDLE (0) -#define SPFC_CQ_INT_MODE (2) -#define SPFC_CQ_HEADER_OWNER_SHIFT (15) - -/* SCQC_CQ_DEPTH 0-256, 1-512, 2-1k, 3-2k, 4-4k, 5-8k, 6-16k, 7-32k. - * include LinkWqe - */ -#define SPFC_CMD_SCQ_DEPTH (4096) -#define SPFC_STS_SCQ_DEPTH (8192) - -#define SPFC_CMD_SCQC_CQ_DEPTH (spfc_log2n(SPFC_CMD_SCQ_DEPTH >> 8)) -#define SPFC_STS_SCQC_CQ_DEPTH (spfc_log2n(SPFC_STS_SCQ_DEPTH >> 8)) -#define SPFC_STS_SCQ_CI_TYPE SPFC_PMSN_CI_TYPE_FROM_HOST - -#define SPFC_CMD_SCQ_CI_TYPE SPFC_PMSN_CI_TYPE_FROM_UCODE - -#define SPFC_SCQ_INTR_LOW_LATENCY_MODE 0 -#define SPFC_SCQ_INTR_POLLING_MODE 1 -#define SPFC_SCQ_PROC_CNT_PER_SECOND_THRESHOLD (30000) - -#define SPFC_CQE_MAX_PROCESS_NUM_PER_INTR (128) -#define SPFC_SESSION_SCQ_NUM (16) - -/* SCQ[0, 2, 4 ...]CMD SCQ,SCQ[1, 3, 5 ...]STS - * SCQ,SCQ[SPFC_TOTAL_SCQ_NUM-1]Defaul SCQ - */ -#define SPFC_CMD_SCQN_START (0) -#define SPFC_STS_SCQN_START (1) -#define SPFC_SCQS_PER_SESSION (2) - -#define SPFC_TOTAL_SCQ_NUM (SPFC_SESSION_SCQ_NUM + 1) - -#define SPFC_SCQ_IS_STS(scq_index) \ - (((scq_index) % SPFC_SCQS_PER_SESSION) || ((scq_index) == SPFC_SESSION_SCQ_NUM)) -#define SPFC_SCQ_IS_CMD(scq_index) (!SPFC_SCQ_IS_STS(scq_index)) -#define SPFC_RPORTID_TO_CMD_SCQN(rport_index) \ - (((rport_index) * SPFC_SCQS_PER_SESSION) % SPFC_SESSION_SCQ_NUM) -#define SPFC_RPORTID_TO_STS_SCQN(rport_index) \ - ((((rport_index) * SPFC_SCQS_PER_SESSION) + 1) % SPFC_SESSION_SCQ_NUM) - -/* - *SRQ defines - */ -#define SPFC_SRQE_SIZE (32) -#define SPFC_SRQ_INIT_LOOP_O (1) -#define SPFC_QUEUE_RING (1) -#define SPFC_SRQ_ELS_DATA_NUM (1) -#define SPFC_SRQ_ELS_SGE_LEN (256) -#define SPFC_SRQ_ELS_DATA_DEPTH (31750) /* depth should Divide 127 */ - -#define SPFC_IRQ_NAME_MAX (30) - -/* Support 2048 sessions(xid) */ -#define SPFC_CQM_XID_MASK (0x7ff) - -#define SPFC_QUEUE_FLUSH_DOING (0) -#define SPFC_QUEUE_FLUSH_DONE (1) -#define SPFC_QUEUE_FLUSH_WAIT_TIMEOUT_MS (2000) -#define SPFC_QUEUE_FLUSH_WAIT_MS (2) - -/* - *RPort defines - */ -#define SPFC_RPORT_OFFLOADED(prnt_qinfo) \ - ((prnt_qinfo)->offload_state == SPFC_QUEUE_STATE_OFFLOADED) -#define SPFC_RPORT_NOT_OFFLOADED(prnt_qinfo) \ - ((prnt_qinfo)->offload_state != SPFC_QUEUE_STATE_OFFLOADED) -#define SPFC_RPORT_FLUSH_NOT_NEEDED(prnt_qinfo) \ - (((prnt_qinfo)->offload_state == SPFC_QUEUE_STATE_INITIALIZED) || \ - ((prnt_qinfo)->offload_state == SPFC_QUEUE_STATE_OFFLOADING) || \ - ((prnt_qinfo)->offload_state == SPFC_QUEUE_STATE_FREE)) -#define SPFC_CHECK_XID_MATCHED(sq_xid, sqe_xid) \ - (((sq_xid) & SPFC_CQM_XID_MASK) == ((sqe_xid) & SPFC_CQM_XID_MASK)) -#define SPFC_PORT_MODE_TGT (0) /* Port mode */ -#define SPFC_PORT_MODE_INI (1) -#define SPFC_PORT_MODE_BOTH (2) - -/* - *Hardware Reserved Queue Info defines - */ -#define SPFC_HRQI_SEQ_ID_MAX (255) -#define SPFC_HRQI_SEQ_INDEX_MAX (64) -#define SPFC_HRQI_SEQ_INDEX_SHIFT (6) -#define SPFC_HRQI_SEQ_SEPCIAL_ID (3) -#define SPFC_HRQI_SEQ_INVALID_ID (~0LL) - -enum spfc_session_reset_mode { - SPFC_SESS_RST_DELETE_IO_ONLY = 1, - SPFC_SESS_RST_DELETE_CONN_ONLY = 2, - SPFC_SESS_RST_DELETE_IO_CONN_BOTH = 3, - SPFC_SESS_RST_MODE_BUTT -}; - -/* linkwqe */ -#define CQM_LINK_WQE_CTRLSL_VALUE 2 -#define CQM_LINK_WQE_LP_VALID 1 -#define CQM_LINK_WQE_LP_INVALID 0 - -/* bit mask */ -#define SPFC_SCQN_MASK 0xfffff -#define SPFC_SCQ_CTX_CI_GPA_MASK 0xfffffff -#define SPFC_SCQ_CTX_C_EQN_MSI_X_MASK 0x7 -#define SPFC_PARITY_MASK 0x1 -#define SPFC_KEYSECTION_XID_H_MASK 0xf -#define SPFC_KEYSECTION_XID_L_MASK 0xffff -#define SPFC_SRQ_CTX_rqe_dma_attr_idx_MASK 0xf -#define SPFC_SSQ_CTX_MASK 0xfffff -#define SPFC_KEY_WD3_SID_2_MASK 0x00ff0000 -#define SPFC_KEY_WD3_SID_1_MASK 0x00ff00 -#define SPFC_KEY_WD3_SID_0_MASK 0x0000ff -#define SPFC_KEY_WD4_DID_2_MASK 0x00ff0000 -#define SPFC_KEY_WD4_DID_1_MASK 0x00ff00 -#define SPFC_KEY_WD4_DID_0_MASK 0x0000ff -#define SPFC_LOCAL_LW_WD1_DUMP_MSN_MASK 0x7fff -#define SPFC_PMSN_MASK 0xff -#define SPFC_QOS_LEVEL_MASK 0x3 -#define SPFC_DB_VAL_MASK 0xFFFFFFFF -#define SPFC_MSNWD_L_MASK 0xffff -#define SPFC_MSNWD_H_MASK 0x7fff -#define SPFC_DB_WD0_PI_H_MASK 0xf -#define SPFC_DB_WD0_PI_L_MASK 0xfff - -#define SPFC_DB_C_BIT_DATA_TYPE 0 -#define SPFC_DB_C_BIT_CONTROL_TYPE 1 - -#define SPFC_OWNER_DRIVER_PRODUCT (1) - -#define SPFC_256BWQE_ENABLE (1) -#define SPFC_DB_ARM_DISABLE (0) - -#define SPFC_CNTX_SIZE_T_256B (0) -#define SPFC_CNTX_SIZE_256B (256) - -#define SPFC_SERVICE_TYPE_FC (12) -#define SPFC_SERVICE_TYPE_FC_SQ (13) - -#define SPFC_PACKET_COS_FC_CMD (0) -#define SPFC_PACKET_COS_FC_DATA (1) - -#define SPFC_QUEUE_LINK_STYLE (0) -#define SPFC_QUEUE_RING_STYLE (1) - -#define SPFC_NEED_DO_OFFLOAD (1) -#define SPFC_QID_SQ (0) - -/* - *SCQ defines - */ -struct spfc_scq_info { - struct cqm_queue *cqm_scq_info; - u32 wqe_num_per_buf; - u32 wqe_size; - u32 scqc_cq_depth; /* 0-256, 1-512, 2-1k, 3-2k, 4-4k, 5-8k, 6-16k, 7-32k */ - u16 scqc_ci_type; - u16 valid_wqe_num; /* ScQ depth include link wqe */ - u16 ci; - u16 ci_owner; - u32 queue_id; - u32 scqn; - char irq_name[SPFC_IRQ_NAME_MAX]; - u16 msix_entry_idx; - u32 irq_id; - struct tasklet_struct tasklet; - atomic_t flush_stat; - void *hba; - u32 reserved; - struct task_struct *delay_task; - bool task_exit; - u32 intr_mode; -}; - -struct spfc_srq_ctx { - /* DW0 */ - u64 pcie_template : 6; - u64 rsvd0 : 2; - u64 parity : 8; - u64 cur_rqe_usr_id : 16; - u64 cur_rqe_msn : 16; - u64 last_rq_pmsn : 16; - - /* DW1 */ - u64 cur_rqe_gpa; - - /* DW2 */ - u64 ctrl_sl : 1; - u64 cf : 1; - u64 csl : 2; - u64 cr : 1; - u64 bdsl : 4; - u64 pmsn_type : 1; - u64 cur_wqe_o : 1; - u64 consant_sge_len : 17; - u64 cur_sge_id : 4; - u64 cur_sge_remain_len : 17; - u64 ceqn_msix : 11; - u64 int_mode : 2; - u64 cur_sge_l : 1; - u64 cur_sge_v : 1; - - /* DW3 */ - u64 cur_sge_gpa; - - /* DW4 */ - u64 cur_pmsn_gpa; - - /* DW5 */ - u64 rsvd3 : 5; - u64 ring : 1; - u64 loop_o : 1; - u64 rsvd2 : 1; - u64 rqe_dma_attr_idx : 6; - u64 rq_so_ro : 2; - u64 cqe_dma_attr_idx : 6; - u64 cq_so_ro : 2; - u64 rsvd1 : 7; - u64 arm_q : 1; - u64 cur_cqe_cnt : 8; - u64 cqe_max_cnt : 8; - u64 prefetch_max_masn : 16; - - /* DW6~DW7 */ - u64 rsvd4; - u64 rsvd5; -}; - -struct spfc_drq_buff_entry { - u16 buff_id; - void *buff_addr; - dma_addr_t buff_dma; -}; - -enum spfc_clean_state { SPFC_CLEAN_DONE, SPFC_CLEAN_DOING, SPFC_CLEAN_BUTT }; -enum spfc_srq_type { SPFC_SRQ_ELS = 1, SPFC_SRQ_IMMI, SPFC_SRQ_BUTT }; - -struct spfc_srq_info { - enum spfc_srq_type srq_type; - - struct cqm_queue *cqm_srq_info; - u32 wqe_num_per_buf; /* Wqe number per buf, dont't inlcude link wqe */ - u32 wqe_size; - u32 valid_wqe_num; /* valid wqe number, dont't include link wqe */ - u16 pi; - u16 pi_owner; - u16 pmsn; - u16 ci; - u16 cmsn; - u32 srqn; - - dma_addr_t first_rqe_recv_dma; - - struct spfc_drq_buff_entry *els_buff_entry_head; - struct buf_describe buf_list; - spinlock_t srq_spin_lock; - bool spin_lock_init; - bool enable; - enum spfc_clean_state state; - - atomic_t ref; - - struct delayed_work del_work; - u32 del_retry_time; - void *hba; -}; - -/* - * The doorbell record keeps PI of WQE, which will be produced next time. - * The PI is 15 bits width o-bit - */ -struct db_record { - u64 pmsn : 16; - u64 dump_pmsn : 16; - u64 rsvd0 : 32; -}; - -/* - * The ci record keeps CI of WQE, which will be consumed next time. - * The ci is 15 bits width with 1 o-bit - */ -struct ci_record { - u64 cmsn : 16; - u64 dump_cmsn : 16; - u64 rsvd0 : 32; -}; - -/* The accumulate data in WQ header */ -struct accumulate { - u64 data_2_uc; - u64 data_2_drv; -}; - -/* The WQ header structure */ -struct wq_header { - struct db_record db_record; - struct ci_record ci_record; - struct accumulate soft_data; -}; - -/* Link list Sq WqePage Pool */ -/* queue header struct */ -struct spfc_queue_header { - u64 door_bell_record; - u64 ci_record; - u64 rsv1; - u64 rsv2; -}; - -/* WPG-WQEPAGE, LLSQ-LINKED LIST SQ */ -struct spfc_wqe_page { - struct list_head entry_wpg; - - /* Wqe Page virtual addr */ - void *wpg_addr; - - /* Wqe Page physical addr */ - u64 wpg_phy_addr; -}; - -struct spfc_sq_wqepage_pool { - u32 wpg_cnt; - u32 wpg_size; - u32 wqe_per_wpg; - - /* PCI DMA Pool */ - struct dma_pool *wpg_dma_pool; - struct spfc_wqe_page *wpg_pool_addr; - struct list_head list_free_wpg_pool; - spinlock_t wpg_pool_lock; - atomic_t wpg_in_use; -}; - -#define SPFC_SQ_DEL_STAGE_TIMEOUT_MS (3 * 1000) -#define SPFC_SRQ_DEL_STAGE_TIMEOUT_MS (10 * 1000) -#define SPFC_SQ_WAIT_FLUSH_DONE_TIMEOUT_MS (10 * 1000) -#define SPFC_SQ_WAIT_FLUSH_DONE_TIMEOUT_CNT (3) - -#define SPFC_SRQ_PROCESS_DELAY_MS (20) - -/* PLOGI parameters */ -struct spfc_plogi_copram { - u32 seq_cnt : 1; - u32 ed_tov : 1; - u32 rsvd : 14; - u32 tx_mfs : 16; - u32 ed_tov_time; -}; - -struct spfc_delay_sqe_ctrl_info { - bool valid; - u32 rport_index; - u32 time_out; - u64 start_jiff; - u32 sid; - u32 did; - u32 xid; - u16 ssqn; - struct spfc_sqe sqe; -}; - -struct spfc_suspend_sqe_info { - void *hba; - u32 magic_num; - u8 old_offload_sts; - struct unf_frame_pkg pkg; - struct spfc_sqe sqe; - struct delayed_work timeout_work; - struct list_head list_sqe_entry; -}; - -struct spfc_delay_destroy_ctrl_info { - bool valid; - u32 rport_index; - u32 time_out; - u64 start_jiff; - struct unf_port_info rport_info; -}; - -/* PARENT SQ Info */ -struct spfc_parent_sq_info { - void *hba; - spinlock_t parent_sq_enqueue_lock; - u32 rport_index; - u32 context_id; - /* Fixed value,used for Doorbell */ - u32 sq_queue_id; - /* When a session is offloaded, tile will return the CacheId to the - * driver,which is used for Doorbell - */ - u32 cache_id; - /* service type, fc or fc */ - u32 service_type; - /* OQID */ - u16 oqid_rd; - u16 oqid_wr; - u32 local_port_id; - u32 remote_port_id; - u32 sqn_base; - bool port_in_flush; - bool sq_in_sess_rst; - atomic_t sq_valid; - /* Used by NPIV QoS */ - u8 vport_id; - /* Used by NPIV QoS */ - u8 cs_ctrl; - struct delayed_work del_work; - struct delayed_work flush_done_timeout_work; - u64 del_start_jiff; - dma_addr_t srq_ctx_addr; - atomic_t sq_cached; - atomic_t flush_done_wait_cnt; - struct spfc_plogi_copram plogi_co_parms; - /* dif control info for immi */ - struct unf_dif_control_info sirt_dif_control; - struct spfc_delay_sqe_ctrl_info delay_sqe; - struct spfc_delay_destroy_ctrl_info destroy_sqe; - struct list_head suspend_sqe_list; - atomic_t io_stat[SPFC_MAX_SQ_TASK_TYPE_CNT]; - u8 need_offloaded; -}; - -/* parent context doorbell */ -struct spfc_parent_sq_db { - struct { - u32 xid : 20; - u32 cntx_size : 2; - u32 arm : 1; - u32 c : 1; - u32 cos : 3; - u32 service_type : 5; - } wd0; - - struct { - u32 pi_hi : 8; - u32 sm_data : 20; - u32 qid : 4; - } wd1; -}; - -#define IWARP_FC_DDB_TYPE 3 - -/* direct wqe doorbell */ -struct spfc_direct_wqe_db { - struct { - u32 xid : 20; - u32 cntx_size : 2; - u32 pi_hi : 4; - u32 c : 1; - u32 cos : 3; - u32 ddb : 2; - } wd0; - - struct { - u32 pi_lo : 12; - u32 sm_data : 20; - } wd1; -}; - -struct spfc_parent_cmd_scq_info { - u32 cqm_queue_id; - u32 local_queue_id; -}; - -struct spfc_parent_st_scq_info { - u32 cqm_queue_id; - u32 local_queue_id; -}; - -struct spfc_parent_els_srq_info { - u32 cqm_queue_id; - u32 local_queue_id; -}; - -enum spfc_parent_queue_state { - SPFC_QUEUE_STATE_INITIALIZED = 0, - SPFC_QUEUE_STATE_OFFLOADING = 1, - SPFC_QUEUE_STATE_OFFLOADED = 2, - SPFC_QUEUE_STATE_DESTROYING = 3, - SPFC_QUEUE_STATE_FREE = 4, - SPFC_QUEUE_STATE_BUTT -}; - -struct spfc_parent_ctx { - dma_addr_t parent_ctx_addr; - void *parent_ctx; - struct cqm_qpc_mpt *cqm_parent_ctx_obj; -}; - -struct spfc_parent_queue_info { - spinlock_t parent_queue_state_lock; - struct spfc_parent_ctx parent_ctx; - enum spfc_parent_queue_state offload_state; - struct spfc_parent_sq_info parent_sq_info; - struct spfc_parent_cmd_scq_info parent_cmd_scq_info; - struct spfc_parent_st_scq_info - parent_sts_scq_info; - struct spfc_parent_els_srq_info parent_els_srq_info; - u8 queue_vport_id; - u8 queue_data_cos; -}; - -struct spfc_parent_ssq_info { - void *hba; - spinlock_t parent_sq_enqueue_lock; - atomic_t wqe_page_cnt; - u32 context_id; - u32 cache_id; - u32 sq_queue_id; - u32 sqn; - u32 service_type; - u32 max_sqe_num; /* SQ depth */ - u32 wqe_num_per_buf; - u32 wqe_size; - u32 accum_wqe_cnt; - u32 wqe_offset; - u16 head_start_cmsn; - u16 head_end_cmsn; - u16 last_pmsn; - u16 last_pi_owner; - u32 queue_style; - atomic_t sq_valid; - void *queue_head_original; - struct spfc_queue_header *queue_header; - dma_addr_t queue_hdr_phy_addr_original; - dma_addr_t queue_hdr_phy_addr; - struct list_head list_linked_list_sq; - atomic_t sq_db_cnt; - atomic_t sq_wqe_cnt; - atomic_t sq_cqe_cnt; - atomic_t sqe_minus_cqe_cnt; - atomic_t io_stat[SPFC_MAX_SQ_TASK_TYPE_CNT]; -}; - -struct spfc_parent_shared_queue_info { - struct spfc_parent_ctx parent_ctx; - struct spfc_parent_ssq_info parent_ssq_info; -}; - -struct spfc_parent_queue_mgr { - struct spfc_parent_queue_info parent_queue[UNF_SPFC_MAXRPORT_NUM]; - struct spfc_parent_shared_queue_info shared_queue[SPFC_MAX_SSQ_NUM]; - struct buf_describe parent_sq_buf_list; -}; - -#define SPFC_SRQC_BUS_ROW 8 -#define SPFC_SRQC_BUS_COL 19 -#define SPFC_SQC_BUS_ROW 8 -#define SPFC_SQC_BUS_COL 13 -#define SPFC_HW_SCQC_BUS_ROW 6 -#define SPFC_HW_SCQC_BUS_COL 10 -#define SPFC_HW_SRQC_BUS_ROW 4 -#define SPFC_HW_SRQC_BUS_COL 15 -#define SPFC_SCQC_BUS_ROW 3 -#define SPFC_SCQC_BUS_COL 29 - -#define SPFC_QUEUE_INFO_BUS_NUM 4 -struct spfc_queue_info_bus { - u64 bus[SPFC_QUEUE_INFO_BUS_NUM]; -}; - -u32 spfc_free_parent_resource(void *handle, struct unf_port_info *rport_info); -u32 spfc_alloc_parent_resource(void *handle, struct unf_port_info *rport_info); -u32 spfc_alloc_parent_queue_mgr(void *handle); -void spfc_free_parent_queue_mgr(void *handle); -u32 spfc_create_common_share_queues(void *handle); -u32 spfc_create_ssq(void *handle); -void spfc_destroy_common_share_queues(void *v_pstHba); -u32 spfc_alloc_parent_sq_wqe_page_pool(void *handle); -void spfc_free_parent_sq_wqe_page_pool(void *handle); -struct spfc_parent_queue_info * -spfc_find_parent_queue_info_by_pkg(void *handle, struct unf_frame_pkg *pkg); -struct spfc_parent_sq_info * -spfc_find_parent_sq_by_pkg(void *handle, struct unf_frame_pkg *pkg); -u32 spfc_root_cmdq_enqueue(void *handle, union spfc_cmdqe *cmdqe, u16 cmd_len); -void spfc_process_scq_cqe(ulong scq_info); -u32 spfc_process_scq_cqe_entity(ulong scq_info, u32 proc_cnt); -void spfc_post_els_srq_wqe(struct spfc_srq_info *srq_info, u16 buf_id); -void spfc_process_aeqe(void *handle, u8 event_type, u8 *event_val); -u32 spfc_parent_sq_enqueue(struct spfc_parent_sq_info *sq, struct spfc_sqe *io_sqe, - u16 ssqn); -u32 spfc_parent_ssq_enqueue(struct spfc_parent_ssq_info *ssq, - struct spfc_sqe *io_sqe, u8 wqe_type); -void spfc_free_sq_wqe_page(struct spfc_parent_ssq_info *ssq, u32 cur_cmsn); -u32 spfc_reclaim_sq_wqe_page(void *handle, union spfc_scqe *scqe); -void spfc_set_rport_flush_state(void *handle, bool in_flush); -u32 spfc_clear_fetched_sq_wqe(void *handle); -u32 spfc_clear_pending_sq_wqe(void *handle); -void spfc_free_parent_queues(void *handle); -void spfc_free_ssq(void *handle, u32 free_sq_num); -void spfc_enalbe_queues_dispatch(void *handle); -void spfc_queue_pre_process(void *handle, bool clean); -void spfc_queue_post_process(void *handle); -void spfc_free_parent_queue_info(void *handle, struct spfc_parent_queue_info *parent_queue_info); -u32 spfc_send_session_rst_cmd(void *handle, - struct spfc_parent_queue_info *parent_queue_info, - enum spfc_session_reset_mode mode); -u32 spfc_send_nop_cmd(void *handle, struct spfc_parent_sq_info *parent_sq_info, - u32 magic_num, u16 sqn); -void spfc_build_session_rst_wqe(void *handle, struct spfc_parent_sq_info *sq, - struct spfc_sqe *sqe, - enum spfc_session_reset_mode mode, u32 scqn); -void spfc_wq_destroy_els_srq(struct work_struct *work); -void spfc_destroy_els_srq(void *handle); -u32 spfc_push_delay_sqe(void *hba, - struct spfc_parent_queue_info *offload_parent_queue, - struct spfc_sqe *sqe, struct unf_frame_pkg *pkg); -void spfc_push_destroy_parent_queue_sqe(void *hba, - struct spfc_parent_queue_info *offloading_parent_queue, - struct unf_port_info *rport_info); -void spfc_pop_destroy_parent_queue_sqe(void *handle, - struct spfc_delay_destroy_ctrl_info *destroy_sqe_info); -struct spfc_parent_queue_info *spfc_find_offload_parent_queue(void *handle, - u32 local_id, - u32 remote_id, - u32 rport_index); -u32 spfc_flush_ini_resp_queue(void *handle); -void spfc_rcvd_els_from_srq_timeout(struct work_struct *work); -u32 spfc_send_aeq_info_via_cmdq(void *hba, u32 aeq_error_type); -u32 spfc_parent_sq_ring_doorbell(struct spfc_parent_ssq_info *sq, u8 qos_level, - u32 c); -void spfc_sess_resource_free_sync(void *handle, - struct unf_port_info *rport_info); -u32 spfc_suspend_sqe_and_send_nop(void *handle, - struct spfc_parent_queue_info *parent_queue, - struct spfc_sqe *sqe, struct unf_frame_pkg *pkg); -u32 spfc_pop_suspend_sqe(void *handle, - struct spfc_parent_queue_info *parent_queue, - struct spfc_suspend_sqe_info *suspen_sqe); -#endif diff --git a/drivers/scsi/spfc/hw/spfc_service.c b/drivers/scsi/spfc/hw/spfc_service.c deleted file mode 100644 index 1da58e3f9fbe..000000000000 --- a/drivers/scsi/spfc/hw/spfc_service.c +++ /dev/null @@ -1,2170 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#include "spfc_service.h" -#include "unf_log.h" -#include "spfc_io.h" -#include "spfc_chipitf.h" - -#define SPFC_ELS_SRQ_BUF_NUM (0x9) -#define SPFC_LS_GS_USERID_LEN ((FC_LS_GS_USERID_CNT_MAX + 1) / 2) - -struct unf_scqe_handle_table { - u32 scqe_type; /* ELS type */ - bool reclaim_sq_wpg; - u32 (*scqe_handle_func)(struct spfc_hba_info *hba, union spfc_scqe *scqe); -}; - -static u32 spfc_get_els_rsp_pld_len(u16 els_type, u16 els_cmnd, - u32 *els_acc_pld_len) -{ - u32 ret = RETURN_OK; - - FC_CHECK_RETURN_VALUE(els_acc_pld_len, UNF_RETURN_ERROR); - - /* RJT */ - if (els_type == ELS_RJT) { - *els_acc_pld_len = UNF_ELS_ACC_RJT_LEN; - return RETURN_OK; - } - - /* ACC */ - switch (els_cmnd) { - /* uses the same PAYLOAD length as PLOGI. */ - case ELS_FLOGI: - case ELS_PDISC: - case ELS_PLOGI: - *els_acc_pld_len = UNF_PLOGI_ACC_PAYLOAD_LEN; - break; - - case ELS_PRLI: - /* If sirt is enabled, The PRLI ACC payload extends 12 bytes */ - *els_acc_pld_len = (UNF_PRLI_ACC_PAYLOAD_LEN - UNF_PRLI_SIRT_EXTRA_SIZE); - - break; - - case ELS_LOGO: - *els_acc_pld_len = UNF_LOGO_ACC_PAYLOAD_LEN; - break; - - case ELS_PRLO: - *els_acc_pld_len = UNF_PRLO_ACC_PAYLOAD_LEN; - break; - - case ELS_RSCN: - *els_acc_pld_len = UNF_RSCN_ACC_PAYLOAD_LEN; - break; - - case ELS_ADISC: - *els_acc_pld_len = UNF_ADISC_ACC_PAYLOAD_LEN; - break; - - case ELS_RRQ: - *els_acc_pld_len = UNF_RRQ_ACC_PAYLOAD_LEN; - break; - - case ELS_SCR: - *els_acc_pld_len = UNF_SCR_RSP_PAYLOAD_LEN; - break; - - case ELS_ECHO: - *els_acc_pld_len = UNF_ECHO_ACC_PAYLOAD_LEN; - break; - - case ELS_REC: - *els_acc_pld_len = UNF_REC_ACC_PAYLOAD_LEN; - break; - - default: - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, - UNF_WARN, "[warn]Unknown ELS command(0x%x)", - els_cmnd); - ret = UNF_RETURN_ERROR; - break; - } - - return ret; -} - -struct unf_els_cmd_paylod_table { - u16 els_cmnd; /* ELS type */ - u32 els_req_pld_len; - u32 els_rsp_pld_len; -}; - -static const struct unf_els_cmd_paylod_table els_pld_table_map[] = { - {ELS_FDISC, UNF_FDISC_PAYLOAD_LEN, UNF_FDISC_ACC_PAYLOAD_LEN}, - {ELS_FLOGI, UNF_FLOGI_PAYLOAD_LEN, UNF_FLOGI_ACC_PAYLOAD_LEN}, - {ELS_PLOGI, UNF_PLOGI_PAYLOAD_LEN, UNF_PLOGI_ACC_PAYLOAD_LEN}, - {ELS_SCR, UNF_SCR_PAYLOAD_LEN, UNF_SCR_RSP_PAYLOAD_LEN}, - {ELS_PDISC, UNF_PDISC_PAYLOAD_LEN, UNF_PDISC_ACC_PAYLOAD_LEN}, - {ELS_LOGO, UNF_LOGO_PAYLOAD_LEN, UNF_LOGO_ACC_PAYLOAD_LEN}, - {ELS_PRLO, UNF_PRLO_PAYLOAD_LEN, UNF_PRLO_ACC_PAYLOAD_LEN}, - {ELS_ADISC, UNF_ADISC_PAYLOAD_LEN, UNF_ADISC_ACC_PAYLOAD_LEN}, - {ELS_RRQ, UNF_RRQ_PAYLOAD_LEN, UNF_RRQ_ACC_PAYLOAD_LEN}, - {ELS_RSCN, 0, UNF_RSCN_ACC_PAYLOAD_LEN}, - {ELS_ECHO, UNF_ECHO_PAYLOAD_LEN, UNF_ECHO_ACC_PAYLOAD_LEN}, - {ELS_REC, UNF_REC_PAYLOAD_LEN, UNF_REC_ACC_PAYLOAD_LEN} -}; - -static u32 spfc_get_els_req_acc_pld_len(u16 els_cmnd, u32 *req_pld_len, u32 *rsp_pld_len) -{ - u32 ret = RETURN_OK; - u32 i; - - FC_CHECK_RETURN_VALUE(req_pld_len, UNF_RETURN_ERROR); - - for (i = 0; i < (sizeof(els_pld_table_map) / - sizeof(struct unf_els_cmd_paylod_table)); - i++) { - if (els_pld_table_map[i].els_cmnd == els_cmnd) { - *req_pld_len = els_pld_table_map[i].els_req_pld_len; - *rsp_pld_len = els_pld_table_map[i].els_rsp_pld_len; - return ret; - } - } - - switch (els_cmnd) { - case ELS_PRLI: - /* If sirt is enabled, The PRLI ACC payload extends 12 bytes */ - *req_pld_len = SPFC_GET_PRLI_PAYLOAD_LEN; - *rsp_pld_len = SPFC_GET_PRLI_PAYLOAD_LEN; - - break; - - default: - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Unknown ELS_CMD(0x%x)", els_cmnd); - ret = UNF_RETURN_ERROR; - break; - } - - return ret; -} - -static u32 spfc_check_parent_qinfo_valid(struct spfc_hba_info *hba, struct unf_frame_pkg *pkg, - struct spfc_parent_queue_info **prt_qinfo) -{ - if (!*prt_qinfo) { - if (pkg->type == UNF_PKG_ELS_REQ || pkg->type == UNF_PKG_ELS_REPLY) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x) send LS SID(0x%x) DID(0x%x) with null prtqinfo", - hba->port_cfg.port_id, pkg->frame_head.csctl_sid, - pkg->frame_head.rctl_did); - pkg->private_data[PKG_PRIVATE_XCHG_RPORT_INDEX] = SPFC_DEFAULT_RPORT_INDEX; - *prt_qinfo = spfc_find_parent_queue_info_by_pkg(hba, pkg); - if (!*prt_qinfo) - return UNF_RETURN_ERROR; - } else { - return UNF_RETURN_ERROR; - } - } - - if (pkg->type == UNF_PKG_GS_REQ && SPFC_RPORT_NOT_OFFLOADED(*prt_qinfo)) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_MAJOR, - "[info]Port(0x%x) send GS SID(0x%x) DID(0x%x), send GS Request before PLOGI", - hba->port_cfg.port_id, pkg->frame_head.csctl_sid, - pkg->frame_head.rctl_did); - return UNF_RETURN_ERROR; - } - return RETURN_OK; -} - -static void spfc_get_pkt_cmnd_type_code(struct unf_frame_pkg *pkg, - u16 *ls_gs_cmnd_code, - u16 *ls_gs_cmnd_type) -{ - *ls_gs_cmnd_type = SPFC_GET_LS_GS_CMND_CODE(pkg->cmnd); - if (SPFC_PKG_IS_ELS_RSP(*ls_gs_cmnd_type)) { - *ls_gs_cmnd_code = SPFC_GET_ELS_RSP_CODE(pkg->cmnd); - } else if (pkg->type == UNF_PKG_GS_REQ) { - *ls_gs_cmnd_code = *ls_gs_cmnd_type; - } else { - *ls_gs_cmnd_code = *ls_gs_cmnd_type; - *ls_gs_cmnd_type = ELS_CMND; - } -} - -static u32 spfc_get_gs_req_rsp_pld_len(u16 cmnd_code, u32 *gs_pld_len, u32 *gs_rsp_pld_len) -{ - FC_CHECK_RETURN_VALUE(gs_pld_len, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(gs_rsp_pld_len, UNF_RETURN_ERROR); - - switch (cmnd_code) { - case NS_GPN_ID: - *gs_pld_len = UNF_GPNID_PAYLOAD_LEN; - *gs_rsp_pld_len = UNF_GPNID_RSP_PAYLOAD_LEN; - break; - - case NS_GNN_ID: - *gs_pld_len = UNF_GNNID_PAYLOAD_LEN; - *gs_rsp_pld_len = UNF_GNNID_RSP_PAYLOAD_LEN; - break; - - case NS_GFF_ID: - *gs_pld_len = UNF_GFFID_PAYLOAD_LEN; - *gs_rsp_pld_len = UNF_GFFID_RSP_PAYLOAD_LEN; - break; - - case NS_GID_FT: - case NS_GID_PT: - *gs_pld_len = UNF_GID_PAYLOAD_LEN; - *gs_rsp_pld_len = UNF_GID_ACC_PAYLOAD_LEN; - break; - - case NS_RFT_ID: - *gs_pld_len = UNF_RFTID_PAYLOAD_LEN; - *gs_rsp_pld_len = UNF_RFTID_RSP_PAYLOAD_LEN; - break; - - case NS_RFF_ID: - *gs_pld_len = UNF_RFFID_PAYLOAD_LEN; - *gs_rsp_pld_len = UNF_RFFID_RSP_PAYLOAD_LEN; - break; - case NS_GA_NXT: - *gs_pld_len = UNF_GID_PAYLOAD_LEN; - *gs_rsp_pld_len = UNF_GID_ACC_PAYLOAD_LEN; - break; - - case NS_GIEL: - *gs_pld_len = UNF_RFTID_RSP_PAYLOAD_LEN; - *gs_rsp_pld_len = UNF_GID_ACC_PAYLOAD_LEN; - break; - - default: - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[warn]Unknown GS commond type(0x%x)", cmnd_code); - return UNF_RETURN_ERROR; - } - - return RETURN_OK; -} - -static void *spfc_get_els_frame_addr(struct spfc_hba_info *hba, - struct unf_frame_pkg *pkg, - u16 els_cmnd_code, u16 els_cmnd_type, - u64 *phy_addr) -{ - void *frame_pld_addr = NULL; - dma_addr_t els_frame_addr = 0; - - if (els_cmnd_code == ELS_ECHO) { - frame_pld_addr = (void *)UNF_GET_ECHO_PAYLOAD(pkg); - els_frame_addr = UNF_GET_ECHO_PAYLOAD_PHYADDR(pkg); - } else if (els_cmnd_code == ELS_RSCN) { - if (els_cmnd_type == ELS_CMND) { - /* Not Support */ - frame_pld_addr = NULL; - els_frame_addr = 0; - } else { - frame_pld_addr = (void *)UNF_GET_RSCN_ACC_PAYLOAD(pkg); - els_frame_addr = pkg->unf_cmnd_pload_bl.buf_dma_addr + - sizeof(struct unf_fc_head); - } - } else { - frame_pld_addr = (void *)SPFC_GET_CMND_PAYLOAD_ADDR(pkg); - els_frame_addr = pkg->unf_cmnd_pload_bl.buf_dma_addr + - sizeof(struct unf_fc_head); - } - *phy_addr = els_frame_addr; - return frame_pld_addr; -} - -static u32 spfc_get_frame_info(struct spfc_hba_info *hba, - struct unf_frame_pkg *pkg, void **frame_pld_addr, - u32 *frame_pld_len, u64 *frame_phy_addr, - u32 *acc_pld_len) -{ - u32 ret = RETURN_OK; - u16 ls_gs_cmnd_code = SPFC_ZERO; - u16 ls_gs_cmnd_type = SPFC_ZERO; - - spfc_get_pkt_cmnd_type_code(pkg, &ls_gs_cmnd_code, &ls_gs_cmnd_type); - - if (pkg->type == UNF_PKG_GS_REQ) { - ret = spfc_get_gs_req_rsp_pld_len(ls_gs_cmnd_code, - frame_pld_len, acc_pld_len); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[err]Port(0x%x) send GS SID(0x%x) DID(0x%x), get error GS request and response payload length", - hba->port_cfg.port_id, - pkg->frame_head.csctl_sid, - pkg->frame_head.rctl_did); - - return ret; - } - *frame_pld_addr = (void *)(SPFC_GET_CMND_PAYLOAD_ADDR(pkg)); - *frame_phy_addr = pkg->unf_cmnd_pload_bl.buf_dma_addr + sizeof(struct unf_fc_head); - if (ls_gs_cmnd_code == NS_GID_FT || ls_gs_cmnd_code == NS_GID_PT) - *frame_pld_addr = (void *)(UNF_GET_GID_PAYLOAD(pkg)); - } else { - *frame_pld_addr = spfc_get_els_frame_addr(hba, pkg, ls_gs_cmnd_code, - ls_gs_cmnd_type, frame_phy_addr); - if (SPFC_PKG_IS_ELS_RSP(ls_gs_cmnd_type)) { - ret = spfc_get_els_rsp_pld_len(ls_gs_cmnd_type, ls_gs_cmnd_code, - frame_pld_len); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]Port(0x%x) get els cmd (0x%x) rsp len failed.", - hba->port_cfg.port_id, - ls_gs_cmnd_code); - return ret; - } - } else { - ret = spfc_get_els_req_acc_pld_len(ls_gs_cmnd_code, frame_pld_len, - acc_pld_len); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]Port(0x%x) get els cmd (0x%x) req and acc len failed.", - hba->port_cfg.port_id, - ls_gs_cmnd_code); - return ret; - } - } - } - return ret; -} - -static u32 -spfc_send_ls_gs_via_parent(struct spfc_hba_info *hba, struct unf_frame_pkg *pkg, - struct spfc_parent_queue_info *prt_queue_info) -{ - u32 ret = UNF_RETURN_ERROR; - u16 ls_gs_cmnd_code = SPFC_ZERO; - u16 ls_gs_cmnd_type = SPFC_ZERO; - u16 remote_exid = 0; - u16 hot_tag = 0; - struct spfc_parent_sq_info *parent_sq_info = NULL; - struct spfc_sqe tmp_sqe; - struct spfc_sqe *sqe = NULL; - void *frame_pld_addr = NULL; - u32 frame_pld_len = 0; - u32 acc_pld_len = 0; - u64 frame_pa = 0; - ulong flags = 0; - u16 ssqn = 0; - spinlock_t *prtq_state_lock = NULL; - - ssqn = (u16)pkg->private_data[PKG_PRIVATE_XCHG_SSQ_INDEX]; - sqe = &tmp_sqe; - memset(sqe, 0, sizeof(struct spfc_sqe)); - - parent_sq_info = &prt_queue_info->parent_sq_info; - hot_tag = (u16)UNF_GET_HOTPOOL_TAG(pkg) + hba->exi_base; - - spfc_get_pkt_cmnd_type_code(pkg, &ls_gs_cmnd_code, &ls_gs_cmnd_type); - - ret = spfc_get_frame_info(hba, pkg, &frame_pld_addr, &frame_pld_len, - &frame_pa, &acc_pld_len); - if (ret != RETURN_OK) - return ret; - - if (SPFC_PKG_IS_ELS_RSP(ls_gs_cmnd_type)) { - remote_exid = UNF_GET_OXID(pkg); - spfc_build_els_wqe_ts_rsp(sqe, prt_queue_info, pkg, - frame_pld_addr, ls_gs_cmnd_type, - ls_gs_cmnd_code); - - /* Assemble the SQE Task Section Els Common part */ - spfc_build_service_wqe_ts_common(&sqe->ts_sl, parent_sq_info->rport_index, - UNF_GET_RXID(pkg), remote_exid, - SPFC_LSW(frame_pld_len)); - } else { - remote_exid = UNF_GET_RXID(pkg); - /* send els req ,only use local_xid for hotpooltag */ - spfc_build_els_wqe_ts_req(sqe, parent_sq_info, - prt_queue_info->parent_sts_scq_info.cqm_queue_id, - frame_pld_addr, pkg); - spfc_build_service_wqe_ts_common(&sqe->ts_sl, parent_sq_info->rport_index, hot_tag, - remote_exid, SPFC_LSW(frame_pld_len)); - } - /* Assemble the SQE Control Section part */ - spfc_build_service_wqe_ctrl_section(&sqe->ctrl_sl, SPFC_BYTES_TO_QW_NUM(SPFC_SQE_TS_SIZE), - SPFC_BYTES_TO_QW_NUM(sizeof(struct spfc_variable_sge))); - - /* Build SGE */ - spfc_build_els_gs_wqe_sge(sqe, frame_pld_addr, frame_pa, frame_pld_len, - parent_sq_info->context_id, hba); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]Port(0x%x) RPort(0x%x) send ELS/GS Type(0x%x) Code(0x%x) HotTag(0x%x)", - hba->port_cfg.port_id, parent_sq_info->rport_index, ls_gs_cmnd_type, - ls_gs_cmnd_code, hot_tag); - if (ls_gs_cmnd_code == ELS_PLOGI || ls_gs_cmnd_code == ELS_LOGO) { - ret = spfc_suspend_sqe_and_send_nop(hba, prt_queue_info, sqe, pkg); - return ret; - } - prtq_state_lock = &prt_queue_info->parent_queue_state_lock; - spin_lock_irqsave(prtq_state_lock, flags); - if (SPFC_RPORT_NOT_OFFLOADED(prt_queue_info)) { - spin_unlock_irqrestore(prtq_state_lock, flags); - /* Send PLOGI or PLOGI ACC or SCR if session not offload */ - ret = spfc_send_els_via_default_session(hba, sqe, pkg, prt_queue_info); - } else { - spin_unlock_irqrestore(prtq_state_lock, flags); - ret = spfc_parent_sq_enqueue(parent_sq_info, sqe, ssqn); - } - - return ret; -} - -u32 spfc_send_ls_gs_cmnd(void *handle, struct unf_frame_pkg *pkg) -{ - u32 ret = UNF_RETURN_ERROR; - struct spfc_hba_info *hba = NULL; - struct spfc_parent_queue_info *prt_qinfo = NULL; - u16 ls_gs_cmnd_code = SPFC_ZERO; - union unf_sfs_u *sfs_entry = NULL; - struct unf_rrq *rrq_pld = NULL; - u16 ox_id = 0; - u16 rx_id = 0; - - /* Check Parameters */ - FC_CHECK_RETURN_VALUE(handle, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(pkg, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(UNF_GET_SFS_ENTRY(pkg), UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(SPFC_GET_CMND_PAYLOAD_ADDR(pkg), UNF_RETURN_ERROR); - - SPFC_CHECK_PKG_ALLOCTIME(pkg); - hba = (struct spfc_hba_info *)handle; - ls_gs_cmnd_code = SPFC_GET_LS_GS_CMND_CODE(pkg->cmnd); - - /* If RRQ Req, Special processing */ - if (ls_gs_cmnd_code == ELS_RRQ) { - sfs_entry = UNF_GET_SFS_ENTRY(pkg); - rrq_pld = &sfs_entry->rrq; - ox_id = (u16)(rrq_pld->oxid_rxid >> UNF_SHIFT_16); - rx_id = (u16)(rrq_pld->oxid_rxid & SPFC_RXID_MASK); - rrq_pld->oxid_rxid = (u32)ox_id << UNF_SHIFT_16 | rx_id; - } - - prt_qinfo = spfc_find_parent_queue_info_by_pkg(hba, pkg); - ret = spfc_check_parent_qinfo_valid(hba, pkg, &prt_qinfo); - - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_MAJOR, - "[error]Port(0x%x) send ELS/GS SID(0x%x) DID(0x%x) check qinfo invalid", - hba->port_cfg.port_id, pkg->frame_head.csctl_sid, - pkg->frame_head.rctl_did); - return UNF_RETURN_ERROR; - } - - ret = spfc_send_ls_gs_via_parent(hba, pkg, prt_qinfo); - - return ret; -} - -void spfc_save_login_parms_in_sq_info(struct spfc_hba_info *hba, - struct unf_port_login_parms *login_params) -{ - u32 rport_index = login_params->rport_index; - struct spfc_parent_sq_info *parent_sq_info = NULL; - - if (rport_index >= UNF_SPFC_MAXRPORT_NUM) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[err]Port(0x%x) save login parms,but uplevel alloc invalid rport index: 0x%x", - hba->port_cfg.port_id, rport_index); - - return; - } - - parent_sq_info = &hba->parent_queue_mgr->parent_queue[rport_index].parent_sq_info; - - parent_sq_info->plogi_co_parms.seq_cnt = login_params->seq_cnt; - parent_sq_info->plogi_co_parms.ed_tov = login_params->ed_tov; - parent_sq_info->plogi_co_parms.tx_mfs = (login_params->tx_mfs < - SPFC_DEFAULT_TX_MAX_FREAM_SIZE) ? - SPFC_DEFAULT_TX_MAX_FREAM_SIZE : - login_params->tx_mfs; - parent_sq_info->plogi_co_parms.ed_tov_time = login_params->ed_tov_timer_val; -} - -static void -spfc_recover_offloading_state(struct spfc_parent_queue_info *prt_queue_info, - enum spfc_parent_queue_state offload_state) -{ - ulong flags = 0; - - spin_lock_irqsave(&prt_queue_info->parent_queue_state_lock, flags); - - if (prt_queue_info->offload_state == SPFC_QUEUE_STATE_OFFLOADING) - prt_queue_info->offload_state = offload_state; - - spin_unlock_irqrestore(&prt_queue_info->parent_queue_state_lock, flags); -} - -static bool spfc_check_need_delay_offload(void *hba, struct unf_frame_pkg *pkg, u32 rport_index, - struct spfc_parent_queue_info *cur_prt_queue_info, - struct spfc_parent_queue_info **offload_prt_queue_info) -{ - ulong flags = 0; - struct spfc_parent_queue_info *prt_queue_info = NULL; - spinlock_t *prtq_state_lock = NULL; - - prtq_state_lock = &cur_prt_queue_info->parent_queue_state_lock; - spin_lock_irqsave(prtq_state_lock, flags); - - if (cur_prt_queue_info->offload_state == SPFC_QUEUE_STATE_OFFLOADING) { - spin_unlock_irqrestore(prtq_state_lock, flags); - - prt_queue_info = spfc_find_offload_parent_queue(hba, pkg->frame_head.csctl_sid & - UNF_NPORTID_MASK, - pkg->frame_head.rctl_did & - UNF_NPORTID_MASK, rport_index); - if (prt_queue_info) { - *offload_prt_queue_info = prt_queue_info; - return true; - } - } else { - spin_unlock_irqrestore(prtq_state_lock, flags); - } - - return false; -} - -static u16 spfc_build_wqe_with_offload(struct spfc_hba_info *hba, struct spfc_sqe *sqe, - struct spfc_parent_queue_info *prt_queue_info, - struct unf_frame_pkg *pkg, - enum spfc_parent_queue_state last_offload_state) -{ - u32 tx_mfs = 2048; - u32 edtov_timer = 2000; - dma_addr_t ctx_pa = 0; - u16 els_cmnd_type = SPFC_ZERO; - u16 els_cmnd_code = SPFC_ZERO; - void *ctx_va = NULL; - struct spfc_parent_context *parent_ctx_info = NULL; - struct spfc_sw_section *sw_setction = NULL; - struct spfc_parent_sq_info *parent_sq_info = &prt_queue_info->parent_sq_info; - u16 offload_flag = 0; - - els_cmnd_type = SPFC_GET_ELS_RSP_TYPE(pkg->cmnd); - if (SPFC_PKG_IS_ELS_RSP(els_cmnd_type)) { - els_cmnd_code = SPFC_GET_ELS_RSP_CODE(pkg->cmnd); - } else { - els_cmnd_code = els_cmnd_type; - els_cmnd_type = ELS_CMND; - } - - offload_flag = SPFC_CHECK_NEED_OFFLOAD(els_cmnd_code, els_cmnd_type, last_offload_state); - - parent_ctx_info = (struct spfc_parent_context *)(prt_queue_info->parent_ctx.parent_ctx); - sw_setction = &parent_ctx_info->sw_section; - - sw_setction->tx_mfs = cpu_to_be16((u16)(tx_mfs)); - sw_setction->e_d_tov_timer_val = cpu_to_be32(edtov_timer); - - spfc_big_to_cpu32(&sw_setction->sw_ctxt_misc.pctxt_val0, - sizeof(sw_setction->sw_ctxt_misc.pctxt_val0)); - sw_setction->sw_ctxt_misc.dw.port_id = SPFC_GET_NETWORK_PORT_ID(hba); - spfc_cpu_to_big32(&sw_setction->sw_ctxt_misc.pctxt_val0, - sizeof(sw_setction->sw_ctxt_misc.pctxt_val0)); - - spfc_big_to_cpu32(&sw_setction->sw_ctxt_config.pctxt_val1, - sizeof(sw_setction->sw_ctxt_config.pctxt_val1)); - spfc_cpu_to_big32(&sw_setction->sw_ctxt_config.pctxt_val1, - sizeof(sw_setction->sw_ctxt_config.pctxt_val1)); - - /* Fill in contex to the chip */ - ctx_pa = prt_queue_info->parent_ctx.cqm_parent_ctx_obj->paddr; - ctx_va = prt_queue_info->parent_ctx.cqm_parent_ctx_obj->vaddr; - - /* No need write key and no need do BIG TO CPU32 */ - memcpy(ctx_va, prt_queue_info->parent_ctx.parent_ctx, sizeof(struct spfc_parent_context)); - - if (SPFC_PKG_IS_ELS_RSP(els_cmnd_type)) { - sqe->ts_sl.cont.els_rsp.context_gpa_hi = SPFC_HIGH_32_BITS(ctx_pa); - sqe->ts_sl.cont.els_rsp.context_gpa_lo = SPFC_LOW_32_BITS(ctx_pa); - sqe->ts_sl.cont.els_rsp.wd1.offload_flag = offload_flag; - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_INFO, - "[info]sid 0x%x, did 0x%x, GPA HIGH 0x%x,GPA LOW 0x%x, scq 0x%x,offload flag 0x%x", - parent_sq_info->local_port_id, - parent_sq_info->remote_port_id, - sqe->ts_sl.cont.els_rsp.context_gpa_hi, - sqe->ts_sl.cont.els_rsp.context_gpa_lo, - prt_queue_info->parent_sts_scq_info.cqm_queue_id, - offload_flag); - } else { - sqe->ts_sl.cont.t_els_gs.context_gpa_hi = SPFC_HIGH_32_BITS(ctx_pa); - sqe->ts_sl.cont.t_els_gs.context_gpa_lo = SPFC_LOW_32_BITS(ctx_pa); - sqe->ts_sl.cont.t_els_gs.wd4.offload_flag = offload_flag; - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_INFO, - "[info]sid 0x%x, did 0x%x, GPA HIGH 0x%x,GPA LOW 0x%x, scq 0x%x,offload flag 0x%x", - parent_sq_info->local_port_id, - parent_sq_info->remote_port_id, - sqe->ts_sl.cont.t_els_gs.context_gpa_hi, - sqe->ts_sl.cont.t_els_gs.context_gpa_lo, - prt_queue_info->parent_sts_scq_info.cqm_queue_id, - offload_flag); - } - - if (offload_flag) { - prt_queue_info->offload_state = SPFC_QUEUE_STATE_OFFLOADING; - parent_sq_info->need_offloaded = SPFC_NEED_DO_OFFLOAD; - } - - return offload_flag; -} - -u32 spfc_send_els_via_default_session(struct spfc_hba_info *hba, struct spfc_sqe *io_sqe, - struct unf_frame_pkg *pkg, - struct spfc_parent_queue_info *prt_queue_info) -{ - ulong flags = 0; - bool sqe_delay = false; - u32 ret = UNF_RETURN_ERROR; - u16 els_cmnd_code = SPFC_ZERO; - u16 els_cmnd_type = SPFC_ZERO; - u16 ssqn = (u16)pkg->private_data[PKG_PRIVATE_XCHG_SSQ_INDEX]; - u32 rport_index = pkg->private_data[PKG_PRIVATE_XCHG_RPORT_INDEX]; - struct spfc_sqe *sqe = io_sqe; - struct spfc_parent_queue_info *default_prt_queue_info = NULL; - struct spfc_parent_sq_info *parent_sq_info = &prt_queue_info->parent_sq_info; - struct spfc_parent_queue_info *offload_queue_info = NULL; - enum spfc_parent_queue_state last_offload_state = SPFC_QUEUE_STATE_INITIALIZED; - struct spfc_delay_destroy_ctrl_info delay_ctl_info; - u16 offload_flag = 0; - u32 default_index = SPFC_DEFAULT_RPORT_INDEX; - - memset(&delay_ctl_info, 0, sizeof(struct spfc_delay_destroy_ctrl_info)); - /* Determine the ELS type in pkg */ - els_cmnd_type = SPFC_GET_LS_GS_CMND_CODE(pkg->cmnd); - - if (SPFC_PKG_IS_ELS_RSP(els_cmnd_type)) { - els_cmnd_code = SPFC_GET_ELS_RSP_CODE(pkg->cmnd); - } else { - els_cmnd_code = els_cmnd_type; - els_cmnd_type = ELS_CMND; - } - - spin_lock_irqsave(&prt_queue_info->parent_queue_state_lock, flags); - - last_offload_state = prt_queue_info->offload_state; - - offload_flag = spfc_build_wqe_with_offload(hba, sqe, prt_queue_info, - pkg, last_offload_state); - - spin_unlock_irqrestore(&prt_queue_info->parent_queue_state_lock, flags); - - if (!offload_flag) { - default_prt_queue_info = &hba->parent_queue_mgr->parent_queue[default_index]; - if (!default_prt_queue_info) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_ERR, - "[ERR]cmd(0x%x), type(0x%x) send fail, default session null", - els_cmnd_code, els_cmnd_type); - return UNF_RETURN_ERROR; - } - parent_sq_info = &default_prt_queue_info->parent_sq_info; - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_INFO, - "[info]cmd(0x%x), type(0x%x) send via default session", - els_cmnd_code, els_cmnd_type); - } else { - /* Need this xid to judge delay offload, when Sqe Enqueue will - * write again - */ - sqe->ts_sl.xid = parent_sq_info->context_id; - sqe_delay = spfc_check_need_delay_offload(hba, pkg, rport_index, prt_queue_info, - &offload_queue_info); - - if (sqe_delay) { - ret = spfc_push_delay_sqe(hba, offload_queue_info, sqe, pkg); - if (ret == RETURN_OK) { - spfc_recover_offloading_state(prt_queue_info, last_offload_state); - return ret; - } - } - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_INFO, - "[info]cmd(0x%x), type(0x%x) do secretly offload", - els_cmnd_code, els_cmnd_type); - } - - ret = spfc_parent_sq_enqueue(parent_sq_info, sqe, ssqn); - - if (ret != RETURN_OK) { - spfc_recover_offloading_state(prt_queue_info, last_offload_state); - - spin_lock_irqsave(&prt_queue_info->parent_queue_state_lock, - flags); - - if (prt_queue_info->parent_sq_info.destroy_sqe.valid) { - memcpy(&delay_ctl_info, &prt_queue_info->parent_sq_info.destroy_sqe, - sizeof(struct spfc_delay_destroy_ctrl_info)); - - prt_queue_info->parent_sq_info.destroy_sqe.valid = false; - } - - spin_unlock_irqrestore(&prt_queue_info->parent_queue_state_lock, flags); - - spfc_pop_destroy_parent_queue_sqe((void *)hba, &delay_ctl_info); - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_WARN, - "[warn]Port(0x%x) RPort(0x%x) send ELS Type(0x%x) Code(0x%x) fail,recover offloadstatus(%u)", - hba->port_cfg.port_id, rport_index, els_cmnd_type, - els_cmnd_code, prt_queue_info->offload_state); - } - - return ret; -} - -static u32 spfc_rcv_ls_gs_rsp_payload(struct spfc_hba_info *hba, - struct unf_frame_pkg *pkg, u32 hot_tag, - u8 *els_pld_buf, u32 pld_len) -{ - u32 ret = UNF_RETURN_ERROR; - - pkg->private_data[PKG_PRIVATE_XCHG_HOT_POOL_INDEX] = hot_tag; - if (pkg->type == UNF_PKG_GS_REQ_DONE) - spfc_big_to_cpu32(els_pld_buf, pld_len); - else - pkg->byte_orders |= SPFC_BIT_2; - - pkg->unf_cmnd_pload_bl.buffer_ptr = els_pld_buf; - pkg->unf_cmnd_pload_bl.length = pld_len; - - pkg->last_pkg_flag = UNF_PKG_NOT_LAST_RESPONSE; - - UNF_LOWLEVEL_RECEIVE_LS_GS_PKG(ret, hba->lport, pkg); - - return ret; -} - -u32 spfc_scq_recv_abts_rsp(struct spfc_hba_info *hba, union spfc_scqe *scqe) -{ - /* Default path, which is sent from SCQ to the driver */ - u8 status = 0; - u32 ret = UNF_RETURN_ERROR; - u32 ox_id = INVALID_VALUE32; - u32 hot_tag = INVALID_VALUE32; - struct unf_frame_pkg pkg = {0}; - struct spfc_scqe_rcv_abts_rsp *abts_rsp = NULL; - - abts_rsp = &scqe->rcv_abts_rsp; - pkg.private_data[PKG_PRIVATE_XCHG_ALLOC_TIME] = abts_rsp->magic_num; - - ox_id = (u32)(abts_rsp->wd0.ox_id); - - hot_tag = abts_rsp->wd1.hotpooltag; - if (unlikely(hot_tag < (u32)hba->exi_base || - hot_tag >= (u32)(hba->exi_base + hba->exi_count))) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) has bad HotTag(0x%x) for bls_rsp", - hba->port_cfg.port_id, hot_tag); - - status = UNF_IO_FAILED; - hot_tag = INVALID_VALUE32; - } else { - hot_tag -= hba->exi_base; - if (unlikely(SPFC_SCQE_HAS_ERRCODE(scqe))) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) BLS response has error code(0x%x) tag(0x%x)", - hba->port_cfg.port_id, - SPFC_GET_SCQE_STATUS(scqe), (u32)hot_tag); - - status = UNF_IO_FAILED; - } else { - pkg.frame_head.rctl_did = abts_rsp->wd3.did; - pkg.frame_head.csctl_sid = abts_rsp->wd4.sid; - pkg.frame_head.oxid_rxid = (u32)(abts_rsp->wd0.rx_id) | ox_id << - UNF_SHIFT_16; - - /* BLS_ACC/BLS_RJT: IO_succeed */ - if (abts_rsp->wd2.fh_rctrl == SPFC_RCTL_BLS_ACC) { - status = UNF_IO_SUCCESS; - } else if (abts_rsp->wd2.fh_rctrl == SPFC_RCTL_BLS_RJT) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x) ABTS RJT: %08x-%08x-%08x", - hba->port_cfg.port_id, - abts_rsp->payload[ARRAY_INDEX_0], - abts_rsp->payload[ARRAY_INDEX_1], - abts_rsp->payload[ARRAY_INDEX_2]); - - status = UNF_IO_SUCCESS; - } else { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) BLS response RCTL is error", - hba->port_cfg.port_id); - SPFC_ERR_IO_STAT(hba, SPFC_SCQE_ABTS_RSP); - status = UNF_IO_FAILED; - } - } - } - - /* Set PKG/exchange status & Process BLS_RSP */ - pkg.status = status; - ret = spfc_rcv_bls_rsp(hba, &pkg, hot_tag); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]Port(0x%x) recv ABTS rsp OX_ID(0x%x) RX_ID(0x%x) HotTag(0x%x) SID(0x%x) DID(0x%x) %s", - hba->port_cfg.port_id, ox_id, abts_rsp->wd0.rx_id, hot_tag, - abts_rsp->wd4.sid, abts_rsp->wd3.did, - (ret == RETURN_OK) ? "OK" : "ERROR"); - - return ret; -} - -u32 spfc_recv_els_cmnd(const struct spfc_hba_info *hba, - struct unf_frame_pkg *pkg, u8 *els_pld, u32 pld_len, - bool first) -{ - u32 ret = UNF_RETURN_ERROR; - - /* Convert Payload to small endian */ - spfc_big_to_cpu32(els_pld, pld_len); - - pkg->type = UNF_PKG_ELS_REQ; - - pkg->unf_cmnd_pload_bl.buffer_ptr = els_pld; - - /* Payload length */ - pkg->unf_cmnd_pload_bl.length = pld_len; - - /* Obtain the Cmnd type from the Paylaod. The Cmnd is in small endian */ - if (first) - pkg->cmnd = UNF_GET_FC_PAYLOAD_ELS_CMND(pkg->unf_cmnd_pload_bl.buffer_ptr); - - /* Errors have been processed in SPFC_RecvElsError */ - pkg->status = UNF_IO_SUCCESS; - - /* Send PKG to the CM layer */ - UNF_LOWLEVEL_RECEIVE_LS_GS_PKG(ret, hba->lport, pkg); - - if (ret != RETURN_OK) { - pkg->rx_or_ox_id = UNF_PKG_FREE_RXID; - pkg->private_data[PKG_PRIVATE_XCHG_HOT_POOL_INDEX] = INVALID_VALUE32; - pkg->private_data[PKG_PRIVATE_XCHG_ALLOC_TIME] = INVALID_VALUE32; - ret = spfc_free_xid((void *)hba, pkg); - - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x) recv %s ox_id(0x%x) RXID(0x%x) PldLen(0x%x) failed, Free xid %s", - hba->port_cfg.port_id, - UNF_GET_FC_HEADER_RCTL(&pkg->frame_head) == SPFC_FC_RCTL_ELS_REQ ? - "ELS REQ" : "ELS RSP", - UNF_GET_OXID(pkg), UNF_GET_RXID(pkg), pld_len, - (ret == RETURN_OK) ? "OK" : "ERROR"); - } - - return ret; -} - -u32 spfc_rcv_ls_gs_rsp(const struct spfc_hba_info *hba, - struct unf_frame_pkg *pkg, u32 hot_tag) -{ - u32 ret = UNF_RETURN_ERROR; - - pkg->private_data[PKG_PRIVATE_XCHG_HOT_POOL_INDEX] = hot_tag; - if (pkg->type == UNF_PKG_ELS_REQ_DONE) - pkg->byte_orders |= SPFC_BIT_2; - - pkg->last_pkg_flag = UNF_PKG_LAST_RESPONSE; - - UNF_LOWLEVEL_RECEIVE_LS_GS_PKG(ret, hba->lport, pkg); - - return ret; -} - -u32 spfc_rcv_els_rsp_sts(const struct spfc_hba_info *hba, - struct unf_frame_pkg *pkg, u32 hot_tag) -{ - u32 ret = UNF_RETURN_ERROR; - - pkg->type = UNF_PKG_ELS_REPLY_DONE; - pkg->private_data[PKG_PRIVATE_XCHG_HOT_POOL_INDEX] = hot_tag; - - UNF_LOWLEVEL_SEND_ELS_DONE(ret, hba->lport, pkg); - - return ret; -} - -u32 spfc_rcv_bls_rsp(const struct spfc_hba_info *hba, struct unf_frame_pkg *pkg, - u32 hot_tag) -{ - /* - * 1. SCQ (normal) - * 2. from Root RQ (parent no existence) - * * - * single frame, single sequence - */ - u32 ret = UNF_RETURN_ERROR; - - pkg->type = UNF_PKG_BLS_REQ_DONE; - pkg->private_data[PKG_PRIVATE_XCHG_HOT_POOL_INDEX] = hot_tag; - pkg->last_pkg_flag = UNF_PKG_LAST_RESPONSE; - - UNF_LOWLEVEL_RECEIVE_BLS_PKG(ret, hba->lport, pkg); - - return ret; -} - -u32 spfc_rsv_bls_rsp_sts(const struct spfc_hba_info *hba, - struct unf_frame_pkg *pkg, u32 rx_id) -{ - u32 ret = UNF_RETURN_ERROR; - - pkg->type = UNF_PKG_BLS_REPLY_DONE; - pkg->private_data[PKG_PRIVATE_XCHG_HOT_POOL_INDEX] = rx_id; - - UNF_LOWLEVEL_RECEIVE_BLS_PKG(ret, hba->lport, pkg); - - return ret; -} - -u32 spfc_rcv_tmf_marker_sts(const struct spfc_hba_info *hba, - struct unf_frame_pkg *pkg, u32 hot_tag) -{ - u32 ret = UNF_RETURN_ERROR; - - pkg->private_data[PKG_PRIVATE_XCHG_HOT_POOL_INDEX] = hot_tag; - - /* Send PKG info to COM */ - UNF_LOWLEVEL_RECEIVE_MARKER_STS(ret, hba->lport, pkg); - - return ret; -} - -u32 spfc_rcv_abts_marker_sts(const struct spfc_hba_info *hba, - struct unf_frame_pkg *pkg, u32 hot_tag) -{ - u32 ret = UNF_RETURN_ERROR; - - pkg->private_data[PKG_PRIVATE_XCHG_HOT_POOL_INDEX] = hot_tag; - - UNF_LOWLEVEL_RECEIVE_ABTS_MARKER_STS(ret, hba->lport, pkg); - - return ret; -} - -static void spfc_scqe_error_pre_proc(struct spfc_hba_info *hba, union spfc_scqe *scqe) -{ - /* Currently, only printing and statistics collection are performed */ - SPFC_ERR_IO_STAT(hba, SPFC_GET_SCQE_TYPE(scqe)); - SPFC_SCQ_ERR_TYPE_STAT(hba, SPFC_GET_SCQE_STATUS(scqe)); - - FC_DRV_PRINT(UNF_LOG_ABNORMAL, UNF_WARN, - "[warn]Port(0x%x)-Task_type(%u) SCQE contain error code(%u),additional info(0x%x)", - hba->port_cfg.port_id, scqe->common.ch.wd0.task_type, - scqe->common.ch.wd0.err_code, scqe->common.conn_id); -} - -void *spfc_get_els_buf_by_user_id(struct spfc_hba_info *hba, u16 user_id) -{ - struct spfc_drq_buff_entry *srq_buf_entry = NULL; - struct spfc_srq_info *srq_info = NULL; - - FC_CHECK_RETURN_VALUE(hba, NULL); - - srq_info = &hba->els_srq_info; - FC_CHECK_RETURN_VALUE(user_id < srq_info->valid_wqe_num, NULL); - - srq_buf_entry = &srq_info->els_buff_entry_head[user_id]; - - return srq_buf_entry->buff_addr; -} - -static u32 spfc_check_srq_buf_valid(struct spfc_hba_info *hba, - u16 *buf_id_array, u32 buf_num) -{ - u32 index = 0; - u32 buf_id = 0; - void *srq_buf = NULL; - - for (index = 0; index < buf_num; index++) { - buf_id = buf_id_array[index]; - - if (buf_id < hba->els_srq_info.valid_wqe_num) - srq_buf = spfc_get_els_buf_by_user_id(hba, (u16)buf_id); - else - srq_buf = NULL; - - if (!srq_buf) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) get srq buffer user id(0x%x) is null", - hba->port_cfg.port_id, buf_id); - - return UNF_RETURN_ERROR; - } - } - - return RETURN_OK; -} - -static void spfc_reclaim_srq_buf(struct spfc_hba_info *hba, u16 *buf_id_array, - u32 buf_num) -{ - u32 index = 0; - u32 buf_id = 0; - void *srq_buf = NULL; - - for (index = 0; index < buf_num; index++) { - buf_id = buf_id_array[index]; - if (buf_id < hba->els_srq_info.valid_wqe_num) - srq_buf = spfc_get_els_buf_by_user_id(hba, (u16)buf_id); - else - srq_buf = NULL; - - /* If the value of buffer is NULL, it indicates that the value - * of buffer is invalid. In this case, exit directly. - */ - if (!srq_buf) - break; - - spfc_post_els_srq_wqe(&hba->els_srq_info, (u16)buf_id); - } -} - -static u32 spfc_check_ls_gs_valid(struct spfc_hba_info *hba, union spfc_scqe *scqe, - struct unf_frame_pkg *pkg, u16 *buf_id_array, - u32 buf_num, u32 frame_len) -{ - u32 hot_tag; - - hot_tag = UNF_GET_HOTPOOL_TAG(pkg); - - /* The ELS CMD returns an error code and discards it directly */ - if ((sizeof(struct spfc_fc_frame_header) > frame_len) || - (SPFC_SCQE_HAS_ERRCODE(scqe)) || buf_num > SPFC_ELS_SRQ_BUF_NUM) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) get scqe type(0x%x) payload len(0x%x),scq status(0x%x),user id num(0x%x) abnormal", - hba->port_cfg.port_id, SPFC_GET_SCQE_TYPE(scqe), frame_len, - SPFC_GET_SCQE_STATUS(scqe), buf_num); - - /* ELS RSP Special Processing */ - if (SPFC_GET_SCQE_TYPE(scqe) == SPFC_SCQE_ELS_RSP || - SPFC_GET_SCQE_TYPE(scqe) == SPFC_SCQE_GS_RSP) { - if (SPFC_SCQE_ERR_TO_CM(scqe)) { - pkg->status = UNF_IO_FAILED; - (void)spfc_rcv_ls_gs_rsp(hba, pkg, hot_tag); - } else { - if (SPFC_GET_SCQE_TYPE(scqe) == SPFC_SCQE_ELS_RSP) - SPFC_HBA_STAT(hba, SPFC_STAT_ELS_RSP_EXCH_REUSE); - else - SPFC_HBA_STAT(hba, SPFC_STAT_GS_RSP_EXCH_REUSE); - } - } - - /* Reclaim srq */ - if (buf_num <= SPFC_ELS_SRQ_BUF_NUM) - spfc_reclaim_srq_buf(hba, buf_id_array, buf_num); - - return UNF_RETURN_ERROR; - } - - /* ELS CMD Check the validity of the buffer sent by the ucode */ - if (SPFC_GET_SCQE_TYPE(scqe) == SPFC_SCQE_ELS_CMND) { - if (spfc_check_srq_buf_valid(hba, buf_id_array, buf_num) != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) get els cmnd scqe user id num(0x%x) abnormal, as some srq buff is null", - hba->port_cfg.port_id, buf_num); - - spfc_reclaim_srq_buf(hba, buf_id_array, buf_num); - - return UNF_RETURN_ERROR; - } - } - - return RETURN_OK; -} - -u32 spfc_scq_recv_els_cmnd(struct spfc_hba_info *hba, union spfc_scqe *scqe) -{ - u32 ret = RETURN_OK; - u32 pld_len = 0; - u32 header_len = 0; - u32 frame_len = 0; - u32 rcv_data_len = 0; - u32 max_buf_num = 0; - u16 buf_id = 0; - u32 index = 0; - u8 *pld_addr = NULL; - struct unf_frame_pkg pkg = {0}; - struct spfc_scqe_rcv_els_cmd *els_cmd = NULL; - struct spfc_fc_frame_header *els_frame = NULL; - struct spfc_fc_frame_header tmp_frame = {0}; - void *els_buf = NULL; - bool first = false; - - els_cmd = &scqe->rcv_els_cmd; - frame_len = els_cmd->wd3.data_len; - max_buf_num = els_cmd->wd3.user_id_num; - spfc_swap_16_in_32((u32 *)els_cmd->user_id, SPFC_LS_GS_USERID_LEN); - - pkg.xchg_contex = NULL; - pkg.status = UNF_IO_SUCCESS; - - /* Check the validity of error codes and buff. If an exception occurs, - * discard the error code - */ - ret = spfc_check_ls_gs_valid(hba, scqe, &pkg, els_cmd->user_id, - max_buf_num, frame_len); - if (ret != RETURN_OK) { - pkg.rx_or_ox_id = UNF_PKG_FREE_RXID; - pkg.frame_head.oxid_rxid = - (u32)(els_cmd->wd2.rx_id) | (u32)(els_cmd->wd2.ox_id) << UNF_SHIFT_16; - pkg.private_data[PKG_PRIVATE_XCHG_HOT_POOL_INDEX] = INVALID_VALUE32; - pkg.private_data[PKG_PRIVATE_XCHG_ALLOC_TIME] = INVALID_VALUE32; - pkg.frame_head.csctl_sid = els_cmd->wd1.sid; - pkg.frame_head.rctl_did = els_cmd->wd0.did; - spfc_free_xid((void *)hba, &pkg); - return RETURN_OK; - } - - /* Send data to COM cyclically */ - for (index = 0; index < max_buf_num; index++) { - /* Exception record, which is not processed currently */ - if (rcv_data_len >= frame_len) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) get els cmd date len(0x%x) is bigger than fream len(0x%x)", - hba->port_cfg.port_id, rcv_data_len, frame_len); - } - - buf_id = (u16)els_cmd->user_id[index]; - els_buf = spfc_get_els_buf_by_user_id(hba, buf_id); - - /* Obtain playload address */ - pld_addr = (u8 *)(els_buf); - header_len = 0; - first = false; - if (index == 0) { - els_frame = (struct spfc_fc_frame_header *)els_buf; - pld_addr = (u8 *)(els_frame + 1); - - header_len = sizeof(struct spfc_fc_frame_header); - first = true; - - memcpy(&tmp_frame, els_frame, sizeof(struct spfc_fc_frame_header)); - spfc_big_to_cpu32(&tmp_frame, sizeof(struct spfc_fc_frame_header)); - memcpy(&pkg.frame_head, &tmp_frame, sizeof(pkg.frame_head)); - pkg.frame_head.oxid_rxid = (u32)((pkg.frame_head.oxid_rxid & - SPFC_OXID_MASK) | (els_cmd->wd2.rx_id)); - } - - /* Calculate the playload length */ - pkg.last_pkg_flag = 0; - pld_len = SPFC_SRQ_ELS_SGE_LEN; - - if ((rcv_data_len + SPFC_SRQ_ELS_SGE_LEN) >= frame_len) { - pkg.last_pkg_flag = 1; - pld_len = frame_len - rcv_data_len; - } - - pkg.class_mode = els_cmd->wd0.class_mode; - - /* Push data to COM */ - if (ret == RETURN_OK) { - ret = spfc_recv_els_cmnd(hba, &pkg, pld_addr, - (pld_len - header_len), first); - } - - /* Reclaim srq buffer */ - spfc_post_els_srq_wqe(&hba->els_srq_info, buf_id); - - rcv_data_len += pld_len; - } - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]Port(0x%x) recv ELS Type(0x%x) Cmnd(0x%x) ox_id(0x%x) RXID(0x%x) SID(0x%x) DID(0x%x) %u", - hba->port_cfg.port_id, pkg.type, pkg.cmnd, els_cmd->wd2.ox_id, - els_cmd->wd2.rx_id, els_cmd->wd1.sid, els_cmd->wd0.did, ret); - - return ret; -} - -static u32 spfc_get_ls_gs_pld_len(struct spfc_hba_info *hba, u32 rcv_data_len, u32 frame_len) -{ - u32 pld_len; - - /* Exception record, which is not processed currently */ - if (rcv_data_len >= frame_len) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) get els rsp data len(0x%x) is bigger than fream len(0x%x)", - hba->port_cfg.port_id, rcv_data_len, frame_len); - } - - pld_len = SPFC_SRQ_ELS_SGE_LEN; - if ((rcv_data_len + SPFC_SRQ_ELS_SGE_LEN) >= frame_len) - pld_len = frame_len - rcv_data_len; - - return pld_len; -} - -u32 spfc_scq_recv_ls_gs_rsp(struct spfc_hba_info *hba, union spfc_scqe *scqe) -{ - u32 ret = RETURN_OK; - u32 pld_len = 0; - u32 header_len = 0; - u32 frame_len = 0; - u32 rcv_data_len = 0; - u32 max_buf_num = 0; - u16 buf_id = 0; - u32 hot_tag = INVALID_VALUE32; - u32 index = 0; - u32 ox_id = (~0); - struct unf_frame_pkg pkg = {0}; - struct spfc_scqe_rcv_els_gs_rsp *ls_gs_rsp_scqe = NULL; - struct spfc_fc_frame_header *els_frame = NULL; - void *ls_gs_buf = NULL; - u8 *pld_addr = NULL; - u8 task_type; - - ls_gs_rsp_scqe = &scqe->rcv_els_gs_rsp; - frame_len = ls_gs_rsp_scqe->wd2.data_len; - max_buf_num = ls_gs_rsp_scqe->wd4.user_id_num; - spfc_swap_16_in_32((u32 *)ls_gs_rsp_scqe->user_id, SPFC_LS_GS_USERID_LEN); - - ox_id = ls_gs_rsp_scqe->wd1.ox_id; - hot_tag = ((u16)ls_gs_rsp_scqe->wd5.hotpooltag) - hba->exi_base; - pkg.frame_head.oxid_rxid = (u32)(ls_gs_rsp_scqe->wd1.rx_id) | ox_id << UNF_SHIFT_16; - pkg.private_data[PKG_PRIVATE_XCHG_ALLOC_TIME] = ls_gs_rsp_scqe->magic_num; - pkg.private_data[PKG_PRIVATE_XCHG_HOT_POOL_INDEX] = hot_tag; - pkg.frame_head.csctl_sid = ls_gs_rsp_scqe->wd4.sid; - pkg.frame_head.rctl_did = ls_gs_rsp_scqe->wd3.did; - pkg.status = UNF_IO_SUCCESS; - pkg.type = UNF_PKG_ELS_REQ_DONE; - - task_type = SPFC_GET_SCQE_TYPE(scqe); - if (task_type == SPFC_SCQE_GS_RSP) { - if (ls_gs_rsp_scqe->wd3.end_rsp) - SPFC_HBA_STAT(hba, SPFC_STAT_LAST_GS_SCQE); - pkg.type = UNF_PKG_GS_REQ_DONE; - } - - /* Handle the exception first. The LS/GS RSP returns the error code. - * Only the ox_id can submit the error code to the CM layer. - */ - ret = spfc_check_ls_gs_valid(hba, scqe, &pkg, ls_gs_rsp_scqe->user_id, - max_buf_num, frame_len); - if (ret != RETURN_OK) - return RETURN_OK; - - if (ls_gs_rsp_scqe->wd3.echo_rsp) { - pkg.private_data[PKG_PRIVATE_ECHO_CMD_RCV_TIME] = - ls_gs_rsp_scqe->user_id[ARRAY_INDEX_5]; - pkg.private_data[PKG_PRIVATE_ECHO_RSP_SND_TIME] = - ls_gs_rsp_scqe->user_id[ARRAY_INDEX_6]; - pkg.private_data[PKG_PRIVATE_ECHO_CMD_SND_TIME] = - ls_gs_rsp_scqe->user_id[ARRAY_INDEX_7]; - pkg.private_data[PKG_PRIVATE_ECHO_ACC_RCV_TIME] = - ls_gs_rsp_scqe->user_id[ARRAY_INDEX_8]; - } - - /* Send data to COM cyclically */ - for (index = 0; index < max_buf_num; index++) { - /* Obtain buffer address */ - ls_gs_buf = NULL; - buf_id = (u16)ls_gs_rsp_scqe->user_id[index]; - ls_gs_buf = spfc_get_els_buf_by_user_id(hba, buf_id); - - if (unlikely(!ls_gs_buf)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) ox_id(0x%x) RXID(0x%x) SID(0x%x) DID(0x%x) Index(0x%x) get els rsp buff user id(0x%x) abnormal", - hba->port_cfg.port_id, ox_id, - ls_gs_rsp_scqe->wd1.rx_id, ls_gs_rsp_scqe->wd4.sid, - ls_gs_rsp_scqe->wd3.did, index, buf_id); - - if (index == 0) { - pkg.status = UNF_IO_FAILED; - ret = spfc_rcv_ls_gs_rsp(hba, &pkg, hot_tag); - } - - return ret; - } - - header_len = 0; - pld_addr = (u8 *)(ls_gs_buf); - if (index == 0) { - header_len = sizeof(struct spfc_fc_frame_header); - els_frame = (struct spfc_fc_frame_header *)ls_gs_buf; - pld_addr = (u8 *)(els_frame + 1); - } - - /* Calculate the playload length */ - pld_len = spfc_get_ls_gs_pld_len(hba, rcv_data_len, frame_len); - - /* Push data to COM */ - if (ret == RETURN_OK) { - ret = spfc_rcv_ls_gs_rsp_payload(hba, &pkg, hot_tag, pld_addr, - (pld_len - header_len)); - } - - /* Reclaim srq buffer */ - spfc_post_els_srq_wqe(&hba->els_srq_info, buf_id); - - rcv_data_len += pld_len; - } - - if (ls_gs_rsp_scqe->wd3.end_rsp && ret == RETURN_OK) - ret = spfc_rcv_ls_gs_rsp(hba, &pkg, hot_tag); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]Port(0x%x) receive LS/GS RSP ox_id(0x%x) RXID(0x%x) SID(0x%x) DID(0x%x) end_rsp(0x%x) user_num(0x%x)", - hba->port_cfg.port_id, ox_id, ls_gs_rsp_scqe->wd1.rx_id, - ls_gs_rsp_scqe->wd4.sid, ls_gs_rsp_scqe->wd3.did, - ls_gs_rsp_scqe->wd3.end_rsp, - ls_gs_rsp_scqe->wd4.user_id_num); - - return ret; -} - -u32 spfc_scq_recv_els_rsp_sts(struct spfc_hba_info *hba, union spfc_scqe *scqe) -{ - u32 ret = UNF_RETURN_ERROR; - u32 rx_id = INVALID_VALUE32; - u32 hot_tag = INVALID_VALUE32; - struct unf_frame_pkg pkg = {0}; - struct spfc_scqe_comm_rsp_sts *els_rsp_sts_scqe = NULL; - - els_rsp_sts_scqe = &scqe->comm_sts; - rx_id = (u32)els_rsp_sts_scqe->wd0.rx_id; - - pkg.private_data[PKG_PRIVATE_XCHG_ALLOC_TIME] = - els_rsp_sts_scqe->magic_num; - pkg.frame_head.oxid_rxid = rx_id | (u32)(els_rsp_sts_scqe->wd0.ox_id) << UNF_SHIFT_16; - hot_tag = (u32)(els_rsp_sts_scqe->wd1.hotpooltag - hba->exi_base); - - if (unlikely(SPFC_SCQE_HAS_ERRCODE(scqe))) - pkg.status = UNF_IO_FAILED; - else - pkg.status = UNF_IO_SUCCESS; - - ret = spfc_rcv_els_rsp_sts(hba, &pkg, hot_tag); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]Port(0x%x) recv ELS RSP STS ox_id(0x%x) RXID(0x%x) HotTag(0x%x) %s", - hba->port_cfg.port_id, els_rsp_sts_scqe->wd0.ox_id, rx_id, - hot_tag, (ret == RETURN_OK) ? "OK" : "ERROR"); - - return ret; -} - -static u32 spfc_check_rport_valid(const struct spfc_parent_queue_info *prt_queue_info, u32 scqe_xid) -{ - if (prt_queue_info->parent_ctx.cqm_parent_ctx_obj) { - if ((prt_queue_info->parent_sq_info.context_id & SPFC_CQM_XID_MASK) == - (scqe_xid & SPFC_CQM_XID_MASK)) { - return RETURN_OK; - } - } - - return UNF_RETURN_ERROR; -} - -u32 spfc_scq_recv_offload_sts(struct spfc_hba_info *hba, union spfc_scqe *scqe) -{ - u32 valid = UNF_RETURN_ERROR; - u32 rport_index = 0; - u32 cid = 0; - u32 xid = 0; - ulong flags = 0; - struct spfc_parent_queue_info *prt_qinfo = NULL; - struct spfc_parent_sq_info *parent_sq_info = NULL; - struct spfc_scqe_sess_sts *offload_sts_scqe = NULL; - struct spfc_delay_destroy_ctrl_info delay_ctl_info; - - memset(&delay_ctl_info, 0, sizeof(struct spfc_delay_destroy_ctrl_info)); - offload_sts_scqe = &scqe->sess_sts; - rport_index = offload_sts_scqe->wd1.conn_id; - cid = offload_sts_scqe->wd2.cid; - xid = offload_sts_scqe->wd0.xid_qpn; - - if (rport_index >= UNF_SPFC_MAXRPORT_NUM) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) receive an error offload status: rport(0x%x) is invalid, cacheid(0x%x)", - hba->port_cfg.port_id, rport_index, cid); - - return UNF_RETURN_ERROR; - } - - if (rport_index == SPFC_DEFAULT_RPORT_INDEX && - hba->default_sq_info.default_sq_flag == 0xF) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) default session timeout: rport(0x%x) cacheid(0x%x)", - hba->port_cfg.port_id, rport_index, cid); - return UNF_RETURN_ERROR; - } - - prt_qinfo = &hba->parent_queue_mgr->parent_queue[rport_index]; - parent_sq_info = &prt_qinfo->parent_sq_info; - - valid = spfc_check_rport_valid(prt_qinfo, xid); - if (valid != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) receive an error offload status: rport(0x%x), context id(0x%x) is invalid", - hba->port_cfg.port_id, rport_index, xid); - - return UNF_RETURN_ERROR; - } - - /* Offload failed */ - if (SPFC_GET_SCQE_STATUS(scqe) != SPFC_COMPLETION_STATUS_SUCCESS) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x), rport(0x%x), context id(0x%x), cache id(0x%x), offload failed", - hba->port_cfg.port_id, rport_index, xid, cid); - - spin_lock_irqsave(&prt_qinfo->parent_queue_state_lock, flags); - if (prt_qinfo->offload_state != SPFC_QUEUE_STATE_OFFLOADED) { - prt_qinfo->offload_state = SPFC_QUEUE_STATE_INITIALIZED; - parent_sq_info->need_offloaded = INVALID_VALUE8; - } - spin_unlock_irqrestore(&prt_qinfo->parent_queue_state_lock, - flags); - - return UNF_RETURN_ERROR; - } - - spin_lock_irqsave(&prt_qinfo->parent_queue_state_lock, flags); - prt_qinfo->parent_sq_info.cache_id = cid; - prt_qinfo->offload_state = SPFC_QUEUE_STATE_OFFLOADED; - parent_sq_info->need_offloaded = SPFC_HAVE_OFFLOAD; - atomic_set(&prt_qinfo->parent_sq_info.sq_cached, true); - - if (prt_qinfo->parent_sq_info.destroy_sqe.valid) { - delay_ctl_info.valid = prt_qinfo->parent_sq_info.destroy_sqe.valid; - delay_ctl_info.rport_index = prt_qinfo->parent_sq_info.destroy_sqe.rport_index; - delay_ctl_info.time_out = prt_qinfo->parent_sq_info.destroy_sqe.time_out; - delay_ctl_info.start_jiff = prt_qinfo->parent_sq_info.destroy_sqe.start_jiff; - delay_ctl_info.rport_info.nport_id = - prt_qinfo->parent_sq_info.destroy_sqe.rport_info.nport_id; - delay_ctl_info.rport_info.rport_index = - prt_qinfo->parent_sq_info.destroy_sqe.rport_info.rport_index; - delay_ctl_info.rport_info.port_name = - prt_qinfo->parent_sq_info.destroy_sqe.rport_info.port_name; - prt_qinfo->parent_sq_info.destroy_sqe.valid = false; - } - spin_unlock_irqrestore(&prt_qinfo->parent_queue_state_lock, flags); - - if (rport_index == SPFC_DEFAULT_RPORT_INDEX) { - hba->default_sq_info.sq_cid = cid; - hba->default_sq_info.sq_xid = xid; - hba->default_sq_info.default_sq_flag = 1; - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, - UNF_MAJOR, "[info]Receive default Session info"); - } - - spfc_pop_destroy_parent_queue_sqe((void *)hba, &delay_ctl_info); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x) offload success: rport index(0x%x),rport nportid(0x%x),context id(0x%x),cache id(0x%x).", - hba->port_cfg.port_id, rport_index, - prt_qinfo->parent_sq_info.remote_port_id, xid, cid); - - return RETURN_OK; -} - -static u32 spfc_send_bls_via_parent(struct spfc_hba_info *hba, struct unf_frame_pkg *pkg) -{ - u32 ret = UNF_RETURN_ERROR; - u16 ox_id = INVALID_VALUE16; - u16 rx_id = INVALID_VALUE16; - struct spfc_sqe tmp_sqe; - struct spfc_sqe *sqe = NULL; - struct spfc_parent_sq_info *parent_sq_info = NULL; - struct spfc_parent_queue_info *prt_qinfo = NULL; - u16 ssqn; - - FC_CHECK_RETURN_VALUE((pkg->type == UNF_PKG_BLS_REQ), UNF_RETURN_ERROR); - - sqe = &tmp_sqe; - memset(sqe, 0, sizeof(struct spfc_sqe)); - - prt_qinfo = spfc_find_parent_queue_info_by_pkg(hba, pkg); - if (!prt_qinfo) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x) send BLS SID_DID(0x%x_0x%x) with null parent queue information", - hba->port_cfg.port_id, pkg->frame_head.csctl_sid, - pkg->frame_head.rctl_did); - - return ret; - } - - parent_sq_info = spfc_find_parent_sq_by_pkg(hba, pkg); - if (!parent_sq_info) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x) send ABTS SID_DID(0x%x_0x%x) with null parent queue information", - hba->port_cfg.port_id, pkg->frame_head.csctl_sid, - pkg->frame_head.rctl_did); - - return ret; - } - - rx_id = UNF_GET_RXID(pkg); - ox_id = UNF_GET_OXID(pkg); - - /* Assemble the SQE Control Section part. The ABTS does not have - * Payload. bdsl=0 - */ - spfc_build_service_wqe_ctrl_section(&sqe->ctrl_sl, SPFC_BYTES_TO_QW_NUM(SPFC_SQE_TS_SIZE), - 0); - - /* Assemble the SQE Task Section BLS Common part. The value of DW2 of - * BLS WQE is Rsvd, and the value of DW2 is 0 - */ - spfc_build_service_wqe_ts_common(&sqe->ts_sl, parent_sq_info->rport_index, ox_id, rx_id, 0); - - /* Assemble the special part of the ABTS */ - spfc_build_bls_wqe_ts_req(sqe, pkg, hba); - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]Port(0x%x) RPort(0x%x) send ABTS_REQ ox_id(0x%x) RXID(0x%x), HotTag(0x%x)", - hba->port_cfg.port_id, parent_sq_info->rport_index, ox_id, - rx_id, (u16)(UNF_GET_HOTPOOL_TAG(pkg) + hba->exi_base)); - - ssqn = (u16)pkg->private_data[PKG_PRIVATE_XCHG_SSQ_INDEX]; - ret = spfc_parent_sq_enqueue(parent_sq_info, sqe, ssqn); - - return ret; -} - -u32 spfc_send_bls_cmnd(void *handle, struct unf_frame_pkg *pkg) -{ - u32 ret = UNF_RETURN_ERROR; - struct spfc_hba_info *hba = NULL; - ulong flags = 0; - struct spfc_parent_queue_info *prt_qinfo = NULL; - - FC_CHECK_RETURN_VALUE(handle, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(pkg, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(pkg->type == UNF_PKG_BLS_REQ || pkg->type == UNF_PKG_BLS_REPLY, - UNF_RETURN_ERROR); - - SPFC_CHECK_PKG_ALLOCTIME(pkg); - hba = (struct spfc_hba_info *)handle; - - prt_qinfo = spfc_find_parent_queue_info_by_pkg(hba, pkg); - if (!prt_qinfo) { - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[warn]Port(0x%x) send BLS SID_DID(0x%x_0x%x) with null parent queue information", - hba->port_cfg.port_id, pkg->frame_head.csctl_sid, - pkg->frame_head.rctl_did); - - return ret; - } - - spin_lock_irqsave(&prt_qinfo->parent_queue_state_lock, flags); - - if (SPFC_RPORT_OFFLOADED(prt_qinfo)) { - spin_unlock_irqrestore(&prt_qinfo->parent_queue_state_lock, flags); - ret = spfc_send_bls_via_parent(hba, pkg); - } else { - spin_unlock_irqrestore(&prt_qinfo->parent_queue_state_lock, flags); - FC_DRV_PRINT(UNF_LOG_IO_ATT, UNF_WARN, - "[error]Port(0x%x) send BLS SID_DID(0x%x_0x%x) with no offloaded, do noting", - hba->port_cfg.port_id, pkg->frame_head.csctl_sid, - pkg->frame_head.rctl_did); - } - - return ret; -} - -static u32 spfc_scq_rcv_flush_sq_sts(struct spfc_hba_info *hba, union spfc_scqe *scqe) -{ - /* - * RCVD sq flush sts - * --->>> continue flush or clear done - */ - u32 ret = UNF_RETURN_ERROR; - - if (scqe->flush_sts.wd0.port_id != hba->port_index) { - FC_DRV_PRINT(UNF_LOG_EVENT, UNF_CRITICAL, - "[err]Port(0x%x) clear_sts_port_idx(0x%x) not match hba_port_idx(0x%x), stage(0x%x)", - hba->port_cfg.port_id, scqe->clear_sts.wd0.port_id, - hba->port_index, hba->queue_set_stage); - - return UNF_RETURN_ERROR; - } - - if (scqe->flush_sts.wd0.last_flush) { - FC_DRV_PRINT(UNF_LOG_EVENT, UNF_INFO, - "[info]Port(0x%x) flush sq(0x%x) done, stage(0x%x)", - hba->port_cfg.port_id, hba->next_clear_sq, hba->queue_set_stage); - - /* If the Flush STS is last one, send cmd done */ - ret = spfc_clear_sq_wqe_done(hba); - } else { - FC_DRV_PRINT(UNF_LOG_EVENT, UNF_MAJOR, - "[info]Port(0x%x) continue flush sq(0x%x), stage(0x%x)", - hba->port_cfg.port_id, hba->next_clear_sq, hba->queue_set_stage); - - ret = spfc_clear_pending_sq_wqe(hba); - } - - return ret; -} - -static u32 spfc_scq_rcv_buf_clear_sts(struct spfc_hba_info *hba, union spfc_scqe *scqe) -{ - /* - * clear: fetched sq wqe - * ---to--->>> pending sq wqe - */ - u32 ret = UNF_RETURN_ERROR; - - if (scqe->clear_sts.wd0.port_id != hba->port_index) { - FC_DRV_PRINT(UNF_LOG_EVENT, UNF_CRITICAL, - "[err]Port(0x%x) clear_sts_port_idx(0x%x) not match hba_port_idx(0x%x), stage(0x%x)", - hba->port_cfg.port_id, scqe->clear_sts.wd0.port_id, - hba->port_index, hba->queue_set_stage); - - return UNF_RETURN_ERROR; - } - - /* set port with I/O cleared state */ - spfc_set_hba_clear_state(hba, true); - - FC_DRV_PRINT(UNF_LOG_EVENT, UNF_KEVENT, - "[info]Port(0x%x) cleared all fetched wqe, start clear sq pending wqe, stage (0x%x)", - hba->port_cfg.port_id, hba->queue_set_stage); - - hba->queue_set_stage = SPFC_QUEUE_SET_STAGE_FLUSHING; - ret = spfc_clear_pending_sq_wqe(hba); - - return ret; -} - -u32 spfc_scq_recv_sess_rst_sts(struct spfc_hba_info *hba, union spfc_scqe *scqe) -{ - u32 rport_index = INVALID_VALUE32; - ulong flags = 0; - struct spfc_parent_queue_info *parent_queue_info = NULL; - struct spfc_scqe_sess_sts *sess_sts_scqe = (struct spfc_scqe_sess_sts *)(void *)scqe; - u32 flush_done; - u32 *ctx_array = NULL; - int ret; - spinlock_t *prtq_state_lock = NULL; - - rport_index = sess_sts_scqe->wd1.conn_id; - if (rport_index >= UNF_SPFC_MAXRPORT_NUM) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) receive reset session cmd sts failed, invlaid rport(0x%x) status_code(0x%x) remain_cnt(0x%x)", - hba->port_cfg.port_id, rport_index, - sess_sts_scqe->ch.wd0.err_code, - sess_sts_scqe->ch.wd0.cqe_remain_cnt); - - return UNF_RETURN_ERROR; - } - - parent_queue_info = &hba->parent_queue_mgr->parent_queue[rport_index]; - prtq_state_lock = &parent_queue_info->parent_queue_state_lock; - /* - * If only session reset is used, the offload status of sq remains - * unchanged. If a link is deleted, the offload status is set to - * destroying and is irreversible. - */ - spin_lock_irqsave(prtq_state_lock, flags); - - /* - * According to the fault tolerance principle, even if the connection - * deletion times out and the sts returns to delete the connection, one - * indicates that the cancel timer is successful, and 0 indicates that - * the timer is being processed. - */ - if (!cancel_delayed_work(&parent_queue_info->parent_sq_info.del_work)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x) rport_index(0x%x) delete rport timer maybe timeout", - hba->port_cfg.port_id, rport_index); - } - - /* - * If the SessRstSts is returned too late and the Parent Queue Info - * resource is released, OK is returned. - */ - if (parent_queue_info->offload_state != SPFC_QUEUE_STATE_DESTROYING) { - spin_unlock_irqrestore(prtq_state_lock, flags); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[info]Port(0x%x) reset session cmd complete, no need to free parent qinfo, rport(0x%x) status_code(0x%x) remain_cnt(0x%x)", - hba->port_cfg.port_id, rport_index, - sess_sts_scqe->ch.wd0.err_code, - sess_sts_scqe->ch.wd0.cqe_remain_cnt); - - return RETURN_OK; - } - - if (parent_queue_info->parent_ctx.cqm_parent_ctx_obj) { - ctx_array = (u32 *)((void *)(parent_queue_info->parent_ctx - .cqm_parent_ctx_obj->vaddr)); - flush_done = ctx_array[SPFC_CTXT_FLUSH_DONE_DW_POS] & SPFC_CTXT_FLUSH_DONE_MASK_BE; - mb(); - if (flush_done == 0) { - spin_unlock_irqrestore(prtq_state_lock, flags); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) rport(0x%x) flushdone is not set, delay to free parent session", - hba->port_cfg.port_id, rport_index); - - /* If flushdone bit is not set,delay free Sq info */ - ret = queue_delayed_work(hba->work_queue, - &(parent_queue_info->parent_sq_info - .flush_done_timeout_work), - (ulong)msecs_to_jiffies((u32) - SPFC_SQ_WAIT_FLUSH_DONE_TIMEOUT_MS)); - if (!ret) { - SPFC_HBA_STAT(hba, SPFC_STAT_PARENT_SQ_QUEUE_DELAYED_WORK); - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) rport(0x%x) queue delayed work failed ret:%d", - hba->port_cfg.port_id, rport_index, - ret); - } - - return RETURN_OK; - } - } - - spin_unlock_irqrestore(prtq_state_lock, flags); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x) begin to free parent session with rport(0x%x)", - hba->port_cfg.port_id, rport_index); - - spfc_free_parent_queue_info(hba, parent_queue_info); - - return RETURN_OK; -} - -static u32 spfc_scq_rcv_clear_srq_sts(struct spfc_hba_info *hba, union spfc_scqe *scqe) -{ - /* - * clear ELS/Immi SRQ - * ---then--->>> Destroy SRQ - */ - struct spfc_srq_info *srq_info = NULL; - - if (SPFC_GET_SCQE_STATUS(scqe) != 0) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) clear srq failed, status(0x%x)", - hba->port_cfg.port_id, SPFC_GET_SCQE_STATUS(scqe)); - - return RETURN_OK; - } - - srq_info = &hba->els_srq_info; - - /* - * 1: cancel timer succeed - * 0: the timer is being processed, the SQ is released when the timer - * times out - */ - if (cancel_delayed_work(&srq_info->del_work)) - queue_work(hba->work_queue, &hba->els_srq_clear_work); - - return RETURN_OK; -} - -u32 spfc_scq_recv_marker_sts(struct spfc_hba_info *hba, union spfc_scqe *scqe) -{ - u32 ret = UNF_RETURN_ERROR; - u32 ox_id = INVALID_VALUE32; - u32 rx_id = INVALID_VALUE32; - u32 hot_tag = INVALID_VALUE32; - struct unf_frame_pkg pkg = {0}; - struct spfc_scqe_itmf_marker_sts *tmf_marker_sts_scqe = NULL; - - tmf_marker_sts_scqe = &scqe->itmf_marker_sts; - ox_id = (u32)tmf_marker_sts_scqe->wd1.ox_id; - rx_id = (u32)tmf_marker_sts_scqe->wd1.rx_id; - hot_tag = tmf_marker_sts_scqe->wd4.hotpooltag - hba->exi_base; - pkg.frame_head.oxid_rxid = rx_id | (u32)(ox_id) << UNF_SHIFT_16; - pkg.private_data[PKG_PRIVATE_XCHG_ALLOC_TIME] = tmf_marker_sts_scqe->magic_num; - pkg.frame_head.csctl_sid = tmf_marker_sts_scqe->wd3.sid; - pkg.frame_head.rctl_did = tmf_marker_sts_scqe->wd2.did; - - /* 1. set pkg status */ - if (unlikely(SPFC_SCQE_HAS_ERRCODE(scqe))) - pkg.status = UNF_IO_FAILED; - else - pkg.status = UNF_IO_SUCCESS; - - /* 2 .process rcvd marker STS: set exchange state */ - ret = spfc_rcv_tmf_marker_sts(hba, &pkg, hot_tag); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[event]Port(0x%x) recv marker STS OX_ID(0x%x) RX_ID(0x%x) HotTag(0x%x) result %s", - hba->port_cfg.port_id, ox_id, rx_id, hot_tag, - (ret == RETURN_OK) ? "succeed" : "failed"); - - return ret; -} - -u32 spfc_scq_recv_abts_marker_sts(struct spfc_hba_info *hba, union spfc_scqe *scqe) -{ - u32 ret = UNF_RETURN_ERROR; - u32 ox_id = INVALID_VALUE32; - u32 rx_id = INVALID_VALUE32; - u32 hot_tag = INVALID_VALUE32; - struct unf_frame_pkg pkg = {0}; - struct spfc_scqe_abts_marker_sts *abts_marker_sts_scqe = NULL; - - abts_marker_sts_scqe = &scqe->abts_marker_sts; - if (!abts_marker_sts_scqe) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]ABTS marker STS is NULL"); - return ret; - } - - ox_id = (u32)abts_marker_sts_scqe->wd1.ox_id; - rx_id = (u32)abts_marker_sts_scqe->wd1.rx_id; - hot_tag = abts_marker_sts_scqe->wd4.hotpooltag - hba->exi_base; - pkg.frame_head.oxid_rxid = rx_id | (u32)(ox_id) << UNF_SHIFT_16; - pkg.frame_head.csctl_sid = abts_marker_sts_scqe->wd3.sid; - pkg.frame_head.rctl_did = abts_marker_sts_scqe->wd2.did; - pkg.abts_maker_status = (u32)abts_marker_sts_scqe->wd3.io_state; - pkg.private_data[PKG_PRIVATE_XCHG_ALLOC_TIME] = abts_marker_sts_scqe->magic_num; - - if (unlikely(SPFC_SCQE_HAS_ERRCODE(scqe))) - pkg.status = UNF_IO_FAILED; - else - pkg.status = UNF_IO_SUCCESS; - - ret = spfc_rcv_abts_marker_sts(hba, &pkg, hot_tag); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_MAJOR, - "[info]Port(0x%x) recv abts marker STS ox_id(0x%x) RXID(0x%x) HotTag(0x%x) %s", - hba->port_cfg.port_id, ox_id, rx_id, hot_tag, - (ret == RETURN_OK) ? "SUCCEED" : "FAILED"); - - return ret; -} - -u32 spfc_handle_aeq_off_load_err(struct spfc_hba_info *hba, struct spfc_aqe_data *aeq_msg) -{ - u32 ret = RETURN_OK; - u32 rport_index = 0; - u32 xid = 0; - struct spfc_parent_queue_info *prt_qinfo = NULL; - struct spfc_delay_destroy_ctrl_info delay_ctl_info; - ulong flags = 0; - - memset(&delay_ctl_info, 0, sizeof(struct spfc_delay_destroy_ctrl_info)); - - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Port(0x%x) receive Offload Err Event, EvtCode(0x%x) Conn_id(0x%x) Xid(0x%x)", - hba->port_cfg.port_id, aeq_msg->wd0.evt_code, - aeq_msg->wd0.conn_id, aeq_msg->wd1.xid); - - /* Currently, only the offload failure caused by insufficient scqe is - * processed. Other errors are not processed temporarily. - */ - if (unlikely(aeq_msg->wd0.evt_code != FC_ERROR_OFFLOAD_LACKOF_SCQE_FAIL)) { - FC_DRV_PRINT(UNF_LOG_REG_ATT, UNF_ERR, - "[err]Port(0x%x) receive an unsupported error code of AEQ Event,EvtCode(0x%x) Conn_id(0x%x)", - hba->port_cfg.port_id, aeq_msg->wd0.evt_code, - aeq_msg->wd0.conn_id); - - return UNF_RETURN_ERROR; - } - SPFC_SCQ_ERR_TYPE_STAT(hba, FC_ERROR_OFFLOAD_LACKOF_SCQE_FAIL); - - rport_index = aeq_msg->wd0.conn_id; - xid = aeq_msg->wd1.xid; - - if (rport_index >= UNF_SPFC_MAXRPORT_NUM) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) receive an error offload status: rport(0x%x) is invalid, Xid(0x%x)", - hba->port_cfg.port_id, rport_index, aeq_msg->wd1.xid); - - return UNF_RETURN_ERROR; - } - - prt_qinfo = &hba->parent_queue_mgr->parent_queue[rport_index]; - if (spfc_check_rport_valid(prt_qinfo, xid) != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) receive an error offload status: rport(0x%x), context id(0x%x) is invalid", - hba->port_cfg.port_id, rport_index, xid); - - return UNF_RETURN_ERROR; - } - - /* The offload status is restored only when the offload status is offloading */ - spin_lock_irqsave(&prt_qinfo->parent_queue_state_lock, flags); - if (prt_qinfo->offload_state == SPFC_QUEUE_STATE_OFFLOADING) - prt_qinfo->offload_state = SPFC_QUEUE_STATE_INITIALIZED; - spin_unlock_irqrestore(&prt_qinfo->parent_queue_state_lock, flags); - - if (prt_qinfo->parent_sq_info.destroy_sqe.valid) { - delay_ctl_info.valid = prt_qinfo->parent_sq_info.destroy_sqe.valid; - delay_ctl_info.rport_index = prt_qinfo->parent_sq_info.destroy_sqe.rport_index; - delay_ctl_info.time_out = prt_qinfo->parent_sq_info.destroy_sqe.time_out; - delay_ctl_info.start_jiff = prt_qinfo->parent_sq_info.destroy_sqe.start_jiff; - delay_ctl_info.rport_info.nport_id = - prt_qinfo->parent_sq_info.destroy_sqe.rport_info.nport_id; - delay_ctl_info.rport_info.rport_index = - prt_qinfo->parent_sq_info.destroy_sqe.rport_info.rport_index; - delay_ctl_info.rport_info.port_name = - prt_qinfo->parent_sq_info.destroy_sqe.rport_info.port_name; - prt_qinfo->parent_sq_info.destroy_sqe.valid = false; - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[info]Port(0x%x) pop up delay sqe, start:0x%llx, timeout:0x%x, rport:0x%x, offload state:0x%x", - hba->port_cfg.port_id, delay_ctl_info.start_jiff, - delay_ctl_info.time_out, - prt_qinfo->parent_sq_info.destroy_sqe.rport_info.rport_index, - SPFC_QUEUE_STATE_INITIALIZED); - - ret = spfc_free_parent_resource(hba, &delay_ctl_info.rport_info); - if (ret != RETURN_OK) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[err]Port(0x%x) pop delay destroy parent sq failed, rport(0x%x), rport nport id 0x%x", - hba->port_cfg.port_id, - delay_ctl_info.rport_info.rport_index, - delay_ctl_info.rport_info.nport_id); - } - } - - return ret; -} - -u32 spfc_free_xid(void *handle, struct unf_frame_pkg *pkg) -{ - u32 ret = RETURN_ERROR; - u16 rx_id = INVALID_VALUE16; - u16 ox_id = INVALID_VALUE16; - u16 hot_tag = INVALID_VALUE16; - struct spfc_hba_info *hba = (struct spfc_hba_info *)handle; - union spfc_cmdqe tmp_cmd_wqe; - union spfc_cmdqe *cmd_wqe = NULL; - - FC_CHECK_RETURN_VALUE(hba, RETURN_ERROR); - FC_CHECK_RETURN_VALUE(pkg, RETURN_ERROR); - SPFC_CHECK_PKG_ALLOCTIME(pkg); - - cmd_wqe = &tmp_cmd_wqe; - memset(cmd_wqe, 0, sizeof(union spfc_cmdqe)); - - rx_id = UNF_GET_RXID(pkg); - ox_id = UNF_GET_OXID(pkg); - if (UNF_GET_HOTPOOL_TAG(pkg) != INVALID_VALUE32) - hot_tag = (u16)UNF_GET_HOTPOOL_TAG(pkg) + hba->exi_base; - - spfc_build_cmdqe_common(cmd_wqe, SPFC_TASK_T_EXCH_ID_FREE, rx_id); - cmd_wqe->xid_free.wd2.hotpool_tag = hot_tag; - cmd_wqe->xid_free.magic_num = UNF_GETXCHGALLOCTIME(pkg); - cmd_wqe->xid_free.sid = pkg->frame_head.csctl_sid; - cmd_wqe->xid_free.did = pkg->frame_head.rctl_did; - cmd_wqe->xid_free.type = pkg->type; - - if (pkg->rx_or_ox_id == UNF_PKG_FREE_OXID) - cmd_wqe->xid_free.wd0.task_id = ox_id; - else - cmd_wqe->xid_free.wd0.task_id = rx_id; - - cmd_wqe->xid_free.wd0.port_id = hba->port_index; - cmd_wqe->xid_free.wd2.scqn = hba->default_scqn; - ret = spfc_root_cmdq_enqueue(hba, cmd_wqe, sizeof(cmd_wqe->xid_free)); - - FC_DRV_PRINT(UNF_LOG_EQUIP_ATT, UNF_INFO, - "[info]Port(0x%x) ox_id(0x%x) RXID(0x%x) hottag(0x%x) magic_num(0x%x) Sid(0x%x) Did(0x%x), send free xid %s", - hba->port_cfg.port_id, ox_id, rx_id, hot_tag, - cmd_wqe->xid_free.magic_num, cmd_wqe->xid_free.sid, - cmd_wqe->xid_free.did, - (ret == RETURN_OK) ? "OK" : "ERROR"); - - return ret; -} - -u32 spfc_scq_free_xid_sts(struct spfc_hba_info *hba, union spfc_scqe *scqe) -{ - u32 hot_tag = INVALID_VALUE32; - u32 magic_num = INVALID_VALUE32; - u32 ox_id = INVALID_VALUE32; - u32 rx_id = INVALID_VALUE32; - struct spfc_scqe_comm_rsp_sts *free_xid_sts_scqe = NULL; - - free_xid_sts_scqe = &scqe->comm_sts; - magic_num = free_xid_sts_scqe->magic_num; - ox_id = (u32)free_xid_sts_scqe->wd0.ox_id; - rx_id = (u32)free_xid_sts_scqe->wd0.rx_id; - - if (free_xid_sts_scqe->wd1.hotpooltag != INVALID_VALUE16) { - hot_tag = free_xid_sts_scqe->wd1.hotpooltag - hba->exi_base; - } - - FC_DRV_PRINT(UNF_LOG_EQUIP_ATT, UNF_INFO, - "Port(0x%x) hottag(0x%x) magicnum(0x%x) ox_id(0x%x) rxid(0x%x) sts(%d)", - hba->port_cfg.port_id, hot_tag, magic_num, ox_id, rx_id, - SPFC_GET_SCQE_STATUS(scqe)); - - return RETURN_OK; -} - -u32 spfc_scq_exchg_timeout_sts(struct spfc_hba_info *hba, union spfc_scqe *scqe) -{ - u32 hot_tag = INVALID_VALUE32; - u32 magic_num = INVALID_VALUE32; - u32 ox_id = INVALID_VALUE32; - u32 rx_id = INVALID_VALUE32; - struct spfc_scqe_comm_rsp_sts *time_out_scqe = NULL; - - time_out_scqe = &scqe->comm_sts; - magic_num = time_out_scqe->magic_num; - ox_id = (u32)time_out_scqe->wd0.ox_id; - rx_id = (u32)time_out_scqe->wd0.rx_id; - - if (time_out_scqe->wd1.hotpooltag != INVALID_VALUE16) - hot_tag = time_out_scqe->wd1.hotpooltag - hba->exi_base; - - FC_DRV_PRINT(UNF_LOG_EQUIP_ATT, UNF_INFO, - "Port(0x%x) recv timer time out sts hotpooltag(0x%x) magicnum(0x%x) ox_id(0x%x) rxid(0x%x) sts(%d)", - hba->port_cfg.port_id, hot_tag, magic_num, ox_id, rx_id, - SPFC_GET_SCQE_STATUS(scqe)); - - return RETURN_OK; -} - -u32 spfc_scq_rcv_sq_nop_sts(struct spfc_hba_info *hba, union spfc_scqe *scqe) -{ - struct spfc_scqe_sq_nop_sts *sq_nop_scqe = NULL; - struct spfc_parent_queue_info *prt_qinfo = NULL; - struct spfc_parent_sq_info *parent_sq_info = NULL; - struct list_head *node = NULL; - struct list_head *next_node = NULL; - struct spfc_suspend_sqe_info *suspend_sqe = NULL; - struct spfc_suspend_sqe_info *sqe = NULL; - u32 rport_index = 0; - u32 magic_num; - u16 sqn; - u32 sqn_base; - u32 sqn_max; - u32 ret = RETURN_OK; - ulong flags = 0; - - sq_nop_scqe = &scqe->sq_nop_sts; - rport_index = sq_nop_scqe->wd1.conn_id; - magic_num = sq_nop_scqe->magic_num; - sqn = sq_nop_scqe->wd0.sqn; - prt_qinfo = &hba->parent_queue_mgr->parent_queue[rport_index]; - parent_sq_info = &prt_qinfo->parent_sq_info; - sqn_base = parent_sq_info->sqn_base; - sqn_max = sqn_base + UNF_SQ_NUM_PER_SESSION - 1; - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "[info]Port(0x%x) rport(0x%x), magic_num(0x%x) receive nop sq sts form sq(0x%x)", - hba->port_cfg.port_id, rport_index, magic_num, sqn); - - spin_lock_irqsave(&prt_qinfo->parent_queue_state_lock, flags); - list_for_each_safe(node, next_node, &parent_sq_info->suspend_sqe_list) { - sqe = list_entry(node, struct spfc_suspend_sqe_info, list_sqe_entry); - if (sqe->magic_num != magic_num) - continue; - suspend_sqe = sqe; - if (sqn == sqn_max) - list_del(node); - break; - } - spin_unlock_irqrestore(&prt_qinfo->parent_queue_state_lock, flags); - - if (suspend_sqe) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "[info]Port(0x%x) rport_index(0x%x) find suspend sqe.", - hba->port_cfg.port_id, rport_index); - if ((sqn < sqn_max) && (sqn >= sqn_base)) { - ret = spfc_send_nop_cmd(hba, parent_sq_info, magic_num, sqn + 1); - } else if (sqn == sqn_max) { - if (!cancel_delayed_work(&suspend_sqe->timeout_work)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "[warn]Port(0x%x) rport(0x%x) reset worker timer maybe timeout", - hba->port_cfg.port_id, rport_index); - } - parent_sq_info->need_offloaded = suspend_sqe->old_offload_sts; - ret = spfc_pop_suspend_sqe(hba, prt_qinfo, suspend_sqe); - kfree(suspend_sqe); - } else { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) rport(0x%x) rcv error sqn(0x%x)", - hba->port_cfg.port_id, rport_index, sqn); - } - } else { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_WARN, - "[warn]Port(0x%x) rport(0x%x) magicnum(0x%x)can't find suspend sqe", - hba->port_cfg.port_id, rport_index, magic_num); - } - return ret; -} - -static const struct unf_scqe_handle_table scqe_handle_table[] = { - {/* INI rcvd FCP RSP */ - SPFC_SCQE_FCP_IRSP, true, spfc_scq_recv_iresp}, - {/* INI/TGT rcvd ELS_CMND */ - SPFC_SCQE_ELS_CMND, false, spfc_scq_recv_els_cmnd}, - {/* INI/TGT rcvd ELS_RSP */ - SPFC_SCQE_ELS_RSP, true, spfc_scq_recv_ls_gs_rsp}, - {/* INI/TGT rcvd GS_RSP */ - SPFC_SCQE_GS_RSP, true, spfc_scq_recv_ls_gs_rsp}, - {/* INI rcvd BLS_RSP */ - SPFC_SCQE_ABTS_RSP, true, spfc_scq_recv_abts_rsp}, - {/* INI/TGT rcvd ELS_RSP STS(Done) */ - SPFC_SCQE_ELS_RSP_STS, true, spfc_scq_recv_els_rsp_sts}, - {/* INI or TGT rcvd Session enable STS */ - SPFC_SCQE_SESS_EN_STS, false, spfc_scq_recv_offload_sts}, - {/* INI or TGT rcvd flush (pending) SQ STS */ - SPFC_SCQE_FLUSH_SQ_STS, false, spfc_scq_rcv_flush_sq_sts}, - {/* INI or TGT rcvd Buffer clear STS */ - SPFC_SCQE_BUF_CLEAR_STS, false, spfc_scq_rcv_buf_clear_sts}, - {/* INI or TGT rcvd session reset STS */ - SPFC_SCQE_SESS_RST_STS, false, spfc_scq_recv_sess_rst_sts}, - {/* ELS/IMMI SRQ */ - SPFC_SCQE_CLEAR_SRQ_STS, false, spfc_scq_rcv_clear_srq_sts}, - {/* INI rcvd TMF RSP */ - SPFC_SCQE_FCP_ITMF_RSP, true, spfc_scq_recv_iresp}, - {/* INI rcvd TMF Marker STS */ - SPFC_SCQE_ITMF_MARKER_STS, false, spfc_scq_recv_marker_sts}, - {/* INI rcvd ABTS Marker STS */ - SPFC_SCQE_ABTS_MARKER_STS, false, spfc_scq_recv_abts_marker_sts}, - {SPFC_SCQE_XID_FREE_ABORT_STS, false, spfc_scq_free_xid_sts}, - {SPFC_SCQE_EXCHID_TIMEOUT_STS, false, spfc_scq_exchg_timeout_sts}, - {SPFC_SQE_NOP_STS, true, spfc_scq_rcv_sq_nop_sts}, - -}; - -u32 spfc_rcv_scq_entry_from_scq(struct spfc_hba_info *hba, union spfc_scqe *scqe, u32 scqn) -{ - u32 ret = UNF_RETURN_ERROR; - bool reclaim = false; - u32 index = 0; - u32 total = 0; - - FC_CHECK_RETURN_VALUE(hba, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(scqe, UNF_RETURN_ERROR); - FC_CHECK_RETURN_VALUE(scqn < SPFC_TOTAL_SCQ_NUM, UNF_RETURN_ERROR); - - SPFC_IO_STAT(hba, SPFC_GET_SCQE_TYPE(scqe)); - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_INFO, - "[info]Port(0x%x) receive scqe type %d from SCQ[%u]", - hba->port_cfg.port_id, SPFC_GET_SCQE_TYPE(scqe), scqn); - - /* 1. error code cheking */ - if (unlikely(SPFC_SCQE_HAS_ERRCODE(scqe))) { - /* So far, just print & counter */ - spfc_scqe_error_pre_proc(hba, scqe); - } - - /* 2. Process SCQE by corresponding processer */ - total = sizeof(scqe_handle_table) / sizeof(struct unf_scqe_handle_table); - while (index < total) { - if (SPFC_GET_SCQE_TYPE(scqe) == scqe_handle_table[index].scqe_type) { - ret = scqe_handle_table[index].scqe_handle_func(hba, scqe); - reclaim = scqe_handle_table[index].reclaim_sq_wpg; - - break; - } - - index++; - } - - /* 3. SCQE type check */ - if (unlikely(total == index)) { - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_ERR, - "[warn]Unknown SCQE type %d", - SPFC_GET_SCQE_TYPE(scqe)); - - UNF_PRINT_SFS_LIMIT(UNF_ERR, hba->port_cfg.port_id, scqe, sizeof(union spfc_scqe)); - } - - /* 4. If SCQE is for SQ-WQE then recovery Link List SQ free page */ - if (reclaim) { - if (SPFC_GET_SCQE_SQN(scqe) < SPFC_MAX_SSQ_NUM) { - ret = spfc_reclaim_sq_wqe_page(hba, scqe); - } else { - /* NOTE: for buffer clear, the SCQE conn_id is 0xFFFF,count with HBA */ - SPFC_HBA_STAT((struct spfc_hba_info *)hba, SPFC_STAT_SQ_IO_BUFFER_CLEARED); - } - } - - return ret; -} diff --git a/drivers/scsi/spfc/hw/spfc_service.h b/drivers/scsi/spfc/hw/spfc_service.h deleted file mode 100644 index e2555c55f4d1..000000000000 --- a/drivers/scsi/spfc/hw/spfc_service.h +++ /dev/null @@ -1,282 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPFC_SERVICE_H -#define SPFC_SERVICE_H - -#include "unf_type.h" -#include "unf_common.h" -#include "unf_scsi_common.h" -#include "spfc_hba.h" - -#define SPFC_HAVE_OFFLOAD (0) - -/* FC txmfs */ -#define SPFC_DEFAULT_TX_MAX_FREAM_SIZE (256) - -#define SPFC_GET_NETWORK_PORT_ID(hba) \ - (((hba)->port_index > 1) ? ((hba)->port_index + 2) : (hba)->port_index) - -#define SPFC_GET_PRLI_PAYLOAD_LEN \ - (UNF_PRLI_PAYLOAD_LEN - UNF_PRLI_SIRT_EXTRA_SIZE) -/* Start addr of the header/payloed of the cmnd buffer in the pkg */ -#define SPFC_FC_HEAD_LEN (sizeof(struct unf_fc_head)) -#define SPFC_PAYLOAD_OFFSET (sizeof(struct unf_fc_head)) -#define SPFC_GET_CMND_PAYLOAD_ADDR(pkg) UNF_GET_FLOGI_PAYLOAD(pkg) -#define SPFC_GET_CMND_HEADER_ADDR(pkg) \ - ((pkg)->unf_cmnd_pload_bl.buffer_ptr) -#define SPFC_GET_RSP_HEADER_ADDR(pkg) \ - ((pkg)->unf_rsp_pload_bl.buffer_ptr) -#define SPFC_GET_RSP_PAYLOAD_ADDR(pkg) \ - ((pkg)->unf_rsp_pload_bl.buffer_ptr + SPFC_PAYLOAD_OFFSET) -#define SPFC_GET_CMND_FC_HEADER(pkg) \ - (&(UNF_GET_SFS_ENTRY(pkg)->sfs_common.frame_head)) -#define SPFC_PKG_IS_ELS_RSP(cmd_type) \ - (((cmd_type) == ELS_ACC) || ((cmd_type) == ELS_RJT)) -#define SPFC_XID_IS_VALID(exid, base, exi_count) \ - (((exid) >= (base)) && ((exid) < ((base) + (exi_count)))) -#define SPFC_CHECK_NEED_OFFLOAD(cmd_code, cmd_type, offload_state) \ - (((cmd_code) == ELS_PLOGI) && ((cmd_type) != ELS_RJT) && \ - ((offload_state) == SPFC_QUEUE_STATE_INITIALIZED)) - -#define UNF_FC_PAYLOAD_ELS_MASK (0xFF000000) -#define UNF_FC_PAYLOAD_ELS_SHIFT (24) -#define UNF_FC_PAYLOAD_ELS_DWORD (0) - -/* Note: this pfcpayload is little endian */ -#define UNF_GET_FC_PAYLOAD_ELS_CMND(pfcpayload) \ - UNF_GET_SHIFTMASK(((u32 *)(void *)(pfcpayload))[UNF_FC_PAYLOAD_ELS_DWORD], \ - UNF_FC_PAYLOAD_ELS_SHIFT, UNF_FC_PAYLOAD_ELS_MASK) - -/* Note: this pfcpayload is big endian */ -#define SPFC_GET_FC_PAYLOAD_ELS_CMND(pfcpayload) \ - UNF_GET_SHIFTMASK(be32_to_cpu(((u32 *)(void *)(pfcpayload))[UNF_FC_PAYLOAD_ELS_DWORD]), \ - UNF_FC_PAYLOAD_ELS_SHIFT, UNF_FC_PAYLOAD_ELS_MASK) - -#define UNF_FC_PAYLOAD_RX_SZ_MASK (0x00000FFF) -#define UNF_FC_PAYLOAD_RX_SZ_SHIFT (16) -#define UNF_FC_PAYLOAD_RX_SZ_DWORD (2) - -/* Note: this pfcpayload is little endian */ -#define UNF_GET_FC_PAYLOAD_RX_SZ(pfcpayload) \ - ((u16)(((u32 *)(void *)(pfcpayload))[UNF_FC_PAYLOAD_RX_SZ_DWORD] & \ - UNF_FC_PAYLOAD_RX_SZ_MASK)) - -/* Note: this pfcpayload is big endian */ -#define SPFC_GET_FC_PAYLOAD_RX_SZ(pfcpayload) \ - (be32_to_cpu((u16)(((u32 *)(void *)(pfcpayload))[UNF_FC_PAYLOAD_RX_SZ_DWORD]) & \ - UNF_FC_PAYLOAD_RX_SZ_MASK)) - -#define SPFC_GET_RA_TOV_FROM_PAYLOAD(pfcpayload) \ - (((struct unf_flogi_fdisc_payload *)(pfcpayload))->fabric_parms.co_parms.r_a_tov) -#define SPFC_GET_RT_TOV_FROM_PAYLOAD(pfcpayload) \ - (((struct unf_flogi_fdisc_payload *)(pfcpayload))->fabric_parms.co_parms.r_t_tov) -#define SPFC_GET_E_D_TOV_FROM_PAYLOAD(pfcpayload) \ - (((struct unf_flogi_fdisc_payload *)(pfcpayload))->fabric_parms.co_parms.e_d_tov) -#define SPFC_GET_E_D_TOV_RESOLUTION_FROM_PAYLOAD(pfcpayload) \ - (((struct unf_flogi_fdisc_payload *)(pfcpayload))->fabric_parms.co_parms.e_d_tov_resolution) -#define SPFC_GET_BB_SC_N_FROM_PAYLOAD(pfcpayload) \ - (((struct unf_flogi_fdisc_payload *)(pfcpayload))->fabric_parms.co_parms.bbscn) -#define SPFC_GET_BB_CREDIT_FROM_PAYLOAD(pfcpayload) \ - (((struct unf_flogi_fdisc_payload *)(pfcpayload))->fabric_parms.co_parms.bb_credit) - -#define SPFC_GET_RA_TOV_FROM_PARAMS(pfcparams) \ - (((struct unf_fabric_parm *)(pfcparams))->co_parms.r_a_tov) -#define SPFC_GET_RT_TOV_FROM_PARAMS(pfcparams) \ - (((struct unf_fabric_parm *)(pfcparams))->co_parms.r_t_tov) -#define SPFC_GET_E_D_TOV_FROM_PARAMS(pfcparams) \ - (((struct unf_fabric_parm *)(pfcparams))->co_parms.e_d_tov) -#define SPFC_GET_E_D_TOV_RESOLUTION_FROM_PARAMS(pfcparams) \ - (((struct unf_fabric_parm *)(pfcparams))->co_parms.e_d_tov_resolution) -#define SPFC_GET_BB_SC_N_FROM_PARAMS(pfcparams) \ - (((struct unf_fabric_parm *)(pfcparams))->co_parms.bbscn) -#define SPFC_GET_BB_CREDIT_FROM_PARAMS(pfcparams) \ - (((struct unf_fabric_parm *)(pfcparams))->co_parms.bb_credit) -#define SPFC_CHECK_NPORT_FPORT_BIT(pfcparams) \ - (((struct unf_fabric_parm *)(pfcparams))->co_parms.nport) - -#define UNF_FC_RCTL_BLS_MASK (0x80) -#define SPFC_UNSOLICITED_FRAME_IS_BLS(hdr) (UNF_GET_FC_HEADER_RCTL(hdr) & UNF_FC_RCTL_BLS_MASK) - -#define SPFC_LOW_SEQ_CNT (0) -#define SPFC_HIGH_SEQ_CNT (0xFFFF) - -/* struct unf_frame_pkg.cmnd meaning: - * The least significant 16 bits indicate whether to send ELS CMND or ELS RSP - * (ACC or RJT). The most significant 16 bits indicate the corresponding ELS - * CMND when the lower 16 bits are ELS RSP. - */ -#define SPFC_ELS_CMND_MASK (0xffff) -#define SPFC_ELS_CMND__RELEVANT_SHIFT (16UL) -#define SPFC_GET_LS_GS_CMND_CODE(cmnd) ((u16)((cmnd) & SPFC_ELS_CMND_MASK)) -#define SPFC_GET_ELS_RSP_TYPE(cmnd) ((u16)((cmnd) & SPFC_ELS_CMND_MASK)) -#define SPFC_GET_ELS_RSP_CODE(cmnd) \ - ((u16)((cmnd) >> SPFC_ELS_CMND__RELEVANT_SHIFT & SPFC_ELS_CMND_MASK)) - -/* ELS CMND Request */ -#define ELS_CMND (0) - -/* fh_f_ctl - Frame control flags. */ -#define SPFC_FC_EX_CTX BIT(23) /* sent by responder to exchange */ -#define SPFC_FC_SEQ_CTX BIT(22) /* sent by responder to sequence */ -#define SPFC_FC_FIRST_SEQ BIT(21) /* first sequence of this exchange */ -#define SPFC_FC_LAST_SEQ BIT(20) /* last sequence of this exchange */ -#define SPFC_FC_END_SEQ BIT(19) /* last frame of sequence */ -#define SPFC_FC_END_CONN BIT(18) /* end of class 1 connection pending */ -#define SPFC_FC_RES_B17 BIT(17) /* reserved */ -#define SPFC_FC_SEQ_INIT BIT(16) /* transfer of sequence initiative */ -#define SPFC_FC_X_ID_REASS BIT(15) /* exchange ID has been changed */ -#define SPFC_FC_X_ID_INVAL BIT(14) /* exchange ID invalidated */ -#define SPFC_FC_ACK_1 BIT(12) /* 13:12 = 1: ACK_1 expected */ -#define SPFC_FC_ACK_N (2 << 12) /* 13:12 = 2: ACK_N expected */ -#define SPFC_FC_ACK_0 (3 << 12) /* 13:12 = 3: ACK_0 expected */ -#define SPFC_FC_RES_B11 BIT(11) /* reserved */ -#define SPFC_FC_RES_B10 BIT(10) /* reserved */ -#define SPFC_FC_RETX_SEQ BIT(9) /* retransmitted sequence */ -#define SPFC_FC_UNI_TX BIT(8) /* unidirectional transmit (class 1) */ -#define SPFC_FC_CONT_SEQ(i) ((i) << 6) -#define SPFC_FC_ABT_SEQ(i) ((i) << 4) -#define SPFC_FC_REL_OFF BIT(3) /* parameter is relative offset */ -#define SPFC_FC_RES2 BIT(2) /* reserved */ -#define SPFC_FC_FILL(i) ((i) & 3) /* 1:0: bytes of trailing fill */ - -#define SPFC_FCTL_REQ (SPFC_FC_FIRST_SEQ | SPFC_FC_END_SEQ | SPFC_FC_SEQ_INIT) -#define SPFC_FCTL_RESP \ - (SPFC_FC_EX_CTX | SPFC_FC_LAST_SEQ | SPFC_FC_END_SEQ | SPFC_FC_SEQ_INIT) -#define SPFC_RCTL_BLS_REQ (0x81) -#define SPFC_RCTL_BLS_ACC (0x84) -#define SPFC_RCTL_BLS_RJT (0x85) - -#define PHY_PORT_TYPE_FC 0x1 /* Physical port type of FC */ -#define PHY_PORT_TYPE_FCOE 0x2 /* Physical port type of FCoE */ -#define SPFC_FC_COS_VALUE (0X4) - -#define SPFC_CDB16_LBA_MASK 0xffff -#define SPFC_CDB16_TRANSFERLEN_MASK 0xff -#define SPFC_RXID_MASK 0xffff -#define SPFC_OXID_MASK 0xffff0000 - -enum spfc_fc_fh_type { - SPFC_FC_TYPE_BLS = 0x00, /* basic link service */ - SPFC_FC_TYPE_ELS = 0x01, /* extended link service */ - SPFC_FC_TYPE_IP = 0x05, /* IP over FC, RFC 4338 */ - SPFC_FC_TYPE_FCP = 0x08, /* SCSI FCP */ - SPFC_FC_TYPE_CT = 0x20, /* Fibre Channel Services (FC-CT) */ - SPFC_FC_TYPE_ILS = 0x22 /* internal link service */ -}; - -enum spfc_fc_fh_rctl { - SPFC_FC_RCTL_DD_UNCAT = 0x00, /* uncategorized information */ - SPFC_FC_RCTL_DD_SOL_DATA = 0x01, /* solicited data */ - SPFC_FC_RCTL_DD_UNSOL_CTL = 0x02, /* unsolicited control */ - SPFC_FC_RCTL_DD_SOL_CTL = 0x03, /* solicited control or reply */ - SPFC_FC_RCTL_DD_UNSOL_DATA = 0x04, /* unsolicited data */ - SPFC_FC_RCTL_DD_DATA_DESC = 0x05, /* data descriptor */ - SPFC_FC_RCTL_DD_UNSOL_CMD = 0x06, /* unsolicited command */ - SPFC_FC_RCTL_DD_CMD_STATUS = 0x07, /* command status */ - -#define SPFC_FC_RCTL_ILS_REQ SPFC_FC_RCTL_DD_UNSOL_CTL /* ILS request */ -#define SPFC_FC_RCTL_ILS_REP SPFC_FC_RCTL_DD_SOL_CTL /* ILS reply */ - - /* - * Extended Link_Data - */ - SPFC_FC_RCTL_ELS_REQ = 0x22, /* extended link services request */ - SPFC_FC_RCTL_ELS_RSP = 0x23, /* extended link services reply */ - SPFC_FC_RCTL_ELS4_REQ = 0x32, /* FC-4 ELS request */ - SPFC_FC_RCTL_ELS4_RSP = 0x33, /* FC-4 ELS reply */ - /* - * Optional Extended Headers - */ - SPFC_FC_RCTL_VFTH = 0x50, /* virtual fabric tagging header */ - SPFC_FC_RCTL_IFRH = 0x51, /* inter-fabric routing header */ - SPFC_FC_RCTL_ENCH = 0x52, /* encapsulation header */ - /* - * Basic Link Services fh_r_ctl values. - */ - SPFC_FC_RCTL_BA_NOP = 0x80, /* basic link service NOP */ - SPFC_FC_RCTL_BA_ABTS = 0x81, /* basic link service abort */ - SPFC_FC_RCTL_BA_RMC = 0x82, /* remove connection */ - SPFC_FC_RCTL_BA_ACC = 0x84, /* basic accept */ - SPFC_FC_RCTL_BA_RJT = 0x85, /* basic reject */ - SPFC_FC_RCTL_BA_PRMT = 0x86, /* dedicated connection preempted */ - /* - * Link Control Information. - */ - SPFC_FC_RCTL_ACK_1 = 0xc0, /* acknowledge_1 */ - SPFC_FC_RCTL_ACK_0 = 0xc1, /* acknowledge_0 */ - SPFC_FC_RCTL_P_RJT = 0xc2, /* port reject */ - SPFC_FC_RCTL_F_RJT = 0xc3, /* fabric reject */ - SPFC_FC_RCTL_P_BSY = 0xc4, /* port busy */ - SPFC_FC_RCTL_F_BSY = 0xc5, /* fabric busy to data frame */ - SPFC_FC_RCTL_F_BSYL = 0xc6, /* fabric busy to link control frame */ - SPFC_FC_RCTL_LCR = 0xc7, /* link credit reset */ - SPFC_FC_RCTL_END = 0xc9 /* end */ -}; - -struct spfc_fc_frame_header { - u8 rctl; /* routing control */ - u8 did[ARRAY_INDEX_3]; /* Destination ID */ - - u8 cs_ctrl; /* class of service control / pri */ - u8 sid[ARRAY_INDEX_3]; /* Source ID */ - - u8 type; /* see enum fc_fh_type below */ - u8 frame_ctrl[ARRAY_INDEX_3]; /* frame control */ - - u8 seq_id; /* sequence ID */ - u8 df_ctrl; /* data field control */ - u16 seq_cnt; /* sequence count */ - - u16 oxid; /* originator exchange ID */ - u16 rxid; /* responder exchange ID */ - u32 param_offset; /* parameter or relative offset */ -}; - -u32 spfc_recv_els_cmnd(const struct spfc_hba_info *hba, - struct unf_frame_pkg *pkg, u8 *els_pld, u32 pld_len, - bool first); -u32 spfc_rcv_ls_gs_rsp(const struct spfc_hba_info *hba, - struct unf_frame_pkg *pkg, u32 hot_tag); -u32 spfc_rcv_els_rsp_sts(const struct spfc_hba_info *hba, - struct unf_frame_pkg *pkg, u32 hot_tag); -u32 spfc_rcv_bls_rsp(const struct spfc_hba_info *hba, struct unf_frame_pkg *pkg, - u32 hot_tag); -u32 spfc_rsv_bls_rsp_sts(const struct spfc_hba_info *hba, - struct unf_frame_pkg *pkg, u32 rx_id); -void spfc_save_login_parms_in_sq_info(struct spfc_hba_info *hba, - struct unf_port_login_parms *login_params); -u32 spfc_handle_aeq_off_load_err(struct spfc_hba_info *hba, - struct spfc_aqe_data *aeq_msg); -u32 spfc_free_xid(void *handle, struct unf_frame_pkg *pkg); -u32 spfc_scq_free_xid_sts(struct spfc_hba_info *hba, union spfc_scqe *scqe); -u32 spfc_scq_exchg_timeout_sts(struct spfc_hba_info *hba, union spfc_scqe *scqe); -u32 spfc_scq_rcv_sq_nop_sts(struct spfc_hba_info *hba, union spfc_scqe *scqe); -u32 spfc_send_els_via_default_session(struct spfc_hba_info *hba, struct spfc_sqe *io_sqe, - struct unf_frame_pkg *pkg, - struct spfc_parent_queue_info *prt_queue_info); -u32 spfc_send_ls_gs_cmnd(void *handle, struct unf_frame_pkg *pkg); -u32 spfc_send_bls_cmnd(void *handle, struct unf_frame_pkg *pkg); - -/* Receive Frame from SCQ */ -u32 spfc_rcv_scq_entry_from_scq(struct spfc_hba_info *hba, - union spfc_scqe *scqe, u32 scqn); -void *spfc_get_els_buf_by_user_id(struct spfc_hba_info *hba, u16 user_id); - -#define SPFC_CHECK_PKG_ALLOCTIME(pkg) \ - do { \ - if (unlikely(UNF_GETXCHGALLOCTIME(pkg) == 0)) { \ - FC_DRV_PRINT(UNF_LOG_NORMAL, \ - UNF_WARN, \ - "[warn]Invalid MagicNum,S_ID(0x%x) " \ - "D_ID(0x%x) OXID(0x%x) " \ - "RX_ID(0x%x) Pkg type(0x%x) hot " \ - "pooltag(0x%x)", \ - UNF_GET_SID(pkg), UNF_GET_DID(pkg), \ - UNF_GET_OXID(pkg), UNF_GET_RXID(pkg), \ - ((struct unf_frame_pkg *)(pkg))->type, \ - UNF_GET_XCHG_TAG(pkg)); \ - } \ - } while (0) - -#endif diff --git a/drivers/scsi/spfc/hw/spfc_utils.c b/drivers/scsi/spfc/hw/spfc_utils.c deleted file mode 100644 index 328c388c95fe..000000000000 --- a/drivers/scsi/spfc/hw/spfc_utils.c +++ /dev/null @@ -1,102 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#include "spfc_utils.h" -#include "unf_log.h" -#include "unf_common.h" - -void spfc_cpu_to_big64(void *addr, u32 size) -{ - u32 index = 0; - u32 cnt = 0; - u64 *temp = NULL; - - FC_CHECK_VALID(addr, dump_stack(); return); - FC_CHECK_VALID((size % SPFC_QWORD_BYTE) == 0, dump_stack(); return); - - temp = (u64 *)addr; - cnt = SPFC_SHIFT_TO_U64(size); - - for (index = 0; index < cnt; index++) { - *temp = cpu_to_be64(*temp); - temp++; - } -} - -void spfc_big_to_cpu64(void *addr, u32 size) -{ - u32 index = 0; - u32 cnt = 0; - u64 *temp = NULL; - - FC_CHECK_VALID(addr, dump_stack(); return); - FC_CHECK_VALID((size % SPFC_QWORD_BYTE) == 0, dump_stack(); return); - - temp = (u64 *)addr; - cnt = SPFC_SHIFT_TO_U64(size); - - for (index = 0; index < cnt; index++) { - *temp = be64_to_cpu(*temp); - temp++; - } -} - -void spfc_cpu_to_big32(void *addr, u32 size) -{ - unf_cpu_to_big_end(addr, size); -} - -void spfc_big_to_cpu32(void *addr, u32 size) -{ - if (size % UNF_BYTES_OF_DWORD) - dump_stack(); - - unf_big_end_to_cpu(addr, size); -} - -void spfc_cpu_to_be24(u8 *data, u32 value) -{ - data[ARRAY_INDEX_0] = (value >> UNF_SHIFT_16) & UNF_MASK_BIT_7_0; - data[ARRAY_INDEX_1] = (value >> UNF_SHIFT_8) & UNF_MASK_BIT_7_0; - data[ARRAY_INDEX_2] = value & UNF_MASK_BIT_7_0; -} - -u32 spfc_big_to_cpu24(u8 *data) -{ - return (data[ARRAY_INDEX_0] << UNF_SHIFT_16) | - (data[ARRAY_INDEX_1] << UNF_SHIFT_8) | data[ARRAY_INDEX_2]; -} - -void spfc_print_buff(u32 dbg_level, void *buff, u32 size) -{ - u32 *spfc_buff = NULL; - u32 loop = 0; - u32 index = 0; - - FC_CHECK_VALID(buff, dump_stack(); return); - FC_CHECK_VALID(0 == (size % SPFC_DWORD_BYTE), dump_stack(); return); - - if ((dbg_level) <= unf_dgb_level) { - spfc_buff = (u32 *)buff; - loop = size / SPFC_DWORD_BYTE; - - for (index = 0; index < loop; index++) { - spfc_buff = (u32 *)buff + index; - FC_DRV_PRINT(UNF_LOG_NORMAL, - UNF_MAJOR, "Buff DW%u 0x%08x.", index, *spfc_buff); - } - } -} - -u32 spfc_log2n(u32 val) -{ - u32 result = 0; - u32 logn = (val >> UNF_SHIFT_1); - - while (logn) { - logn >>= UNF_SHIFT_1; - result++; - } - - return result; -} diff --git a/drivers/scsi/spfc/hw/spfc_utils.h b/drivers/scsi/spfc/hw/spfc_utils.h deleted file mode 100644 index 6b4330da3f1d..000000000000 --- a/drivers/scsi/spfc/hw/spfc_utils.h +++ /dev/null @@ -1,202 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPFC_UTILS_H -#define SPFC_UTILS_H - -#include "unf_type.h" -#include "unf_log.h" - -#define SPFC_ZERO (0) - -#define SPFC_BIT(n) (0x1UL << (n)) -#define SPFC_BIT_0 SPFC_BIT(0) -#define SPFC_BIT_1 SPFC_BIT(1) -#define SPFC_BIT_2 SPFC_BIT(2) -#define SPFC_BIT_3 SPFC_BIT(3) -#define SPFC_BIT_4 SPFC_BIT(4) -#define SPFC_BIT_5 SPFC_BIT(5) -#define SPFC_BIT_6 SPFC_BIT(6) -#define SPFC_BIT_7 SPFC_BIT(7) -#define SPFC_BIT_8 SPFC_BIT(8) -#define SPFC_BIT_9 SPFC_BIT(9) -#define SPFC_BIT_10 SPFC_BIT(10) -#define SPFC_BIT_11 SPFC_BIT(11) -#define SPFC_BIT_12 SPFC_BIT(12) -#define SPFC_BIT_13 SPFC_BIT(13) -#define SPFC_BIT_14 SPFC_BIT(14) -#define SPFC_BIT_15 SPFC_BIT(15) -#define SPFC_BIT_16 SPFC_BIT(16) -#define SPFC_BIT_17 SPFC_BIT(17) -#define SPFC_BIT_18 SPFC_BIT(18) -#define SPFC_BIT_19 SPFC_BIT(19) -#define SPFC_BIT_20 SPFC_BIT(20) -#define SPFC_BIT_21 SPFC_BIT(21) -#define SPFC_BIT_22 SPFC_BIT(22) -#define SPFC_BIT_23 SPFC_BIT(23) -#define SPFC_BIT_24 SPFC_BIT(24) -#define SPFC_BIT_25 SPFC_BIT(25) -#define SPFC_BIT_26 SPFC_BIT(26) -#define SPFC_BIT_27 SPFC_BIT(27) -#define SPFC_BIT_28 SPFC_BIT(28) -#define SPFC_BIT_29 SPFC_BIT(29) -#define SPFC_BIT_30 SPFC_BIT(30) -#define SPFC_BIT_31 SPFC_BIT(31) - -#define SPFC_GET_BITS(data, mask) ((data) & (mask)) /* Obtains the bit */ -#define SPFC_SET_BITS(data, mask) ((data) |= (mask)) /* set the bit */ -#define SPFC_CLR_BITS(data, mask) ((data) &= ~(mask)) /* clear the bit */ - -#define SPFC_LSB(x) ((u8)(x)) -#define SPFC_MSB(x) ((u8)((u16)(x) >> 8)) - -#define SPFC_LSW(x) ((u16)(x)) -#define SPFC_MSW(x) ((u16)((u32)(x) >> 16)) - -#define SPFC_LSD(x) ((u32)((u64)(x))) -#define SPFC_MSD(x) ((u32)((((u64)(x)) >> 16) >> 16)) - -#define SPFC_BYTES_TO_QW_NUM(x) ((x) >> 3) -#define SPFC_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)))) - -/* 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(((u32 *)(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) \ - do { \ - UNF_FC_SET_SHIFTMASK(((u32 *)(void *)(__pfcheader)[UNF_FC_HEADER_RCTL_DWORD], \ - __val, UNF_FC_HEADER_RCTL_SHIFT, UNF_FC_HEADER_RCTL_MASK) \ - } while (0) - -/* PRLI PARAM 3 */ -#define SPFC_PRLI_PARAM_WXFER_ENABLE_MASK (0x00000001) -#define SPFC_PRLI_PARAM_WXFER_ENABLE_SHIFT (0) -#define SPFC_PRLI_PARAM_WXFER_DWORD (3) -#define SPFC_GET_PRLI_PARAM_WXFER(__pfcheader) \ - UNF_GET_SHIFTMASK(((u32 *)(void *)(__pfcheader))[SPFC_PRLI_PARAM_WXFER_DWORD], \ - SPFC_PRLI_PARAM_WXFER_ENABLE_SHIFT, \ - SPFC_PRLI_PARAM_WXFER_ENABLE_MASK) - -#define SPFC_PRLI_PARAM_CONF_ENABLE_MASK (0x00000080) -#define SPFC_PRLI_PARAM_CONF_ENABLE_SHIFT (7) -#define SPFC_PRLI_PARAM_CONF_DWORD (3) -#define SPFC_GET_PRLI_PARAM_CONF(__pfcheader) \ - UNF_GET_SHIFTMASK(((u32 *)(void *)(__pfcheader))[SPFC_PRLI_PARAM_CONF_DWORD], \ - SPFC_PRLI_PARAM_CONF_ENABLE_SHIFT, \ - SPFC_PRLI_PARAM_CONF_ENABLE_MASK) - -#define SPFC_PRLI_PARAM_REC_ENABLE_MASK (0x00000400) -#define SPFC_PRLI_PARAM_REC_ENABLE_SHIFT (10) -#define SPFC_PRLI_PARAM_CONF_REC (3) -#define SPFC_GET_PRLI_PARAM_REC(__pfcheader) \ - UNF_GET_SHIFTMASK(((u32 *)(void *)(__pfcheader))[SPFC_PRLI_PARAM_CONF_REC], \ - SPFC_PRLI_PARAM_REC_ENABLE_SHIFT, SPFC_PRLI_PARAM_REC_ENABLE_MASK) - -#define SPFC_FUNCTION_ENTER \ - FC_DRV_PRINT(UNF_LOG_NORMAL, UNF_ALL, \ - "%s Enter.", __func__) -#define SPFC_FUNCTION_RETURN \ - FC_DRV_PRINT(UNF_LOG_NORMAL, UNF_ALL, \ - "%s Return.", __func__) - -#define SPFC_SPIN_LOCK_IRQSAVE(interrupt, hw_adapt_lock, flags) \ - do { \ - if ((interrupt) == false) { \ - spin_lock_irqsave(&(hw_adapt_lock), flags); \ - } \ - } while (0) - -#define SPFC_SPIN_UNLOCK_IRQRESTORE(interrupt, hw_adapt_lock, flags) \ - do { \ - if ((interrupt) == false) { \ - spin_unlock_irqrestore(&(hw_adapt_lock), flags); \ - } \ - } while (0) - -#define FC_CHECK_VALID(condition, fail_do) \ - do { \ - if (unlikely(!(condition))) { \ - FC_DRV_PRINT(UNF_LOG_REG_ATT, \ - UNF_ERR, "Para check(%s) invalid", \ - #condition); \ - fail_do; \ - } \ - } while (0) - -#define RETURN_ERROR_S32 (-1) -#define UNF_RETURN_ERROR_S32 (-1) - -enum SPFC_LOG_CTRL_E { - SPFC_LOG_ALL = 0, - SPFC_LOG_SCQE_RX, - SPFC_LOG_ELS_TX, - SPFC_LOG_ELS_RX, - SPFC_LOG_GS_TX, - SPFC_LOG_GS_RX, - SPFC_LOG_BLS_TX, - SPFC_LOG_BLS_RX, - SPFC_LOG_FCP_TX, - SPFC_LOG_FCP_RX, - SPFC_LOG_SESS_TX, - SPFC_LOG_SESS_RX, - SPFC_LOG_DIF_TX, - SPFC_LOG_DIF_RX -}; - -extern u32 spfc_log_en; -#define SPFC_LOG_EN(hba, log_ctrl) (spfc_log_en + (log_ctrl)) - -enum SPFC_HBA_ERR_STAT_E { - SPFC_STAT_CTXT_FLUSH_DONE = 0, - SPFC_STAT_SQ_WAIT_EMPTY, - SPFC_STAT_LAST_GS_SCQE, - SPFC_STAT_SQ_POOL_EMPTY, - SPFC_STAT_PARENT_IO_FLUSHED, - SPFC_STAT_ROOT_IO_FLUSHED, /* 5 */ - SPFC_STAT_ROOT_SQ_FULL, - SPFC_STAT_ELS_RSP_EXCH_REUSE, - SPFC_STAT_GS_RSP_EXCH_REUSE, - SPFC_STAT_SQ_IO_BUFFER_CLEARED, - SPFC_STAT_PARENT_SQ_NOT_OFFLOADED, /* 10 */ - SPFC_STAT_PARENT_SQ_QUEUE_DELAYED_WORK, - SPFC_STAT_PARENT_SQ_INVALID_CACHED_ID, - SPFC_HBA_STAT_BUTT -}; - -#define SPFC_DWORD_BYTE (4) -#define SPFC_QWORD_BYTE (8) -#define SPFC_SHIFT_TO_U64(x) ((x) >> 3) -#define SPFC_SHIFT_TO_U32(x) ((x) >> 2) - -void spfc_cpu_to_big64(void *addr, u32 size); -void spfc_big_to_cpu64(void *addr, u32 size); -void spfc_cpu_to_big32(void *addr, u32 size); -void spfc_big_to_cpu32(void *addr, u32 size); -void spfc_cpu_to_be24(u8 *data, u32 value); -u32 spfc_big_to_cpu24(u8 *data); - -void spfc_print_buff(u32 dbg_level, void *buff, u32 size); - -u32 spfc_log2n(u32 val); - -static inline void spfc_swap_16_in_32(u32 *paddr, u32 length) -{ - u32 i; - - for (i = 0; i < length; i++) { - paddr[i] = - ((((paddr[i]) & UNF_MASK_BIT_31_16) >> UNF_SHIFT_16) | - (((paddr[i]) & UNF_MASK_BIT_15_0) << UNF_SHIFT_16)); - } -} - -#endif /* __SPFC_UTILS_H__ */ diff --git a/drivers/scsi/spfc/hw/spfc_wqe.c b/drivers/scsi/spfc/hw/spfc_wqe.c deleted file mode 100644 index 61909c51bc8c..000000000000 --- a/drivers/scsi/spfc/hw/spfc_wqe.c +++ /dev/null @@ -1,646 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#include "spfc_wqe.h" -#include "spfc_module.h" -#include "spfc_service.h" - -void spfc_build_tmf_rsp_wqe_ts_header(struct unf_frame_pkg *pkg, - struct spfc_sqe_tmf_rsp *sqe, u16 exi_base, - u32 scqn) -{ - sqe->ts_sl.task_type = SPFC_SQE_FCP_TMF_TRSP; - sqe->ts_sl.wd0.conn_id = - (u16)(pkg->private_data[PKG_PRIVATE_XCHG_RPORT_INDEX]); - - if (UNF_GET_RXID(pkg) == INVALID_VALUE16) - sqe->ts_sl.local_xid = INVALID_VALUE16; - else - sqe->ts_sl.local_xid = UNF_GET_RXID(pkg) + exi_base; - - sqe->ts_sl.tmf_rsp.wd0.scqn = scqn; - sqe->ts_sl.magic_num = UNF_GETXCHGALLOCTIME(pkg); -} - -void spfc_build_common_wqe_ctrls(struct spfc_wqe_ctrl *ctrl_sl, u8 task_len) -{ - /* "BDSL" field of CtrlS - defines the size of BDS, which varies from 0 - * to 2040 bytes (8 bits of 8 bytes' chunk) - */ - ctrl_sl->ch.wd0.bdsl = 0; - - /* "DrvSL" field of CtrlS - defines the size of DrvS, which varies from - * 0 to 24 bytes - */ - ctrl_sl->ch.wd0.drv_sl = 0; - - /* a. - * b1 - linking WQE, which will be only used in linked page architecture - * instead of ring, it's a special control WQE which does not contain - * any buffer or inline data information, and will only be consumed by - * hardware. The size is aligned to WQEBB/WQE b0 - normal WQE, either - * normal SEG WQE or inline data WQE - */ - ctrl_sl->ch.wd0.wf = 0; - - /* - * "CF" field of CtrlS - Completion Format - defines the format of CS. - * a. b0 - Status information is embedded inside of Completion Section - * b. b1 - Completion Section keeps SGL, where Status information - * should be written. (For the definition of SGLs see ?4.1 - * .) - */ - ctrl_sl->ch.wd0.cf = 0; - - /* "TSL" field of CtrlS - defines the size of TS, which varies from 0 to - * 248 bytes - */ - ctrl_sl->ch.wd0.tsl = task_len; - - /* - * Variable length SGE (vSGE). The size of SGE is 16 bytes. The vSGE - * format is of two types, which are defined by "VA " field of CtrlS. - * "VA" stands for Virtual Address: o b0. SGE comprises 64-bits - * buffer's pointer and 31-bits Length, each SGE can only support up to - * 2G-1B, it can guarantee each single SGE length can not exceed 2GB by - * nature, A byte count value of zero means a 0byte data transfer. o b1. - * SGE comprises 64-bits buffer's pointer, 31-bits Length and 30-bits - * Key of the Translation table , each SGE can only support up to 2G-1B, - * it can guarantee each single SGE length can not exceed 2GB by nature, - * A byte count value of zero means a 0byte data transfer - */ - ctrl_sl->ch.wd0.va = 0; - - /* - * "DF" field of CtrlS - Data Format - defines the format of BDS - * a. b0 - BDS carries the list of SGEs (SGL) - * b. b1 - BDS carries the inline data - */ - ctrl_sl->ch.wd0.df = 0; - - /* "CR" - Completion is Required - marks CQE generation request per WQE - */ - ctrl_sl->ch.wd0.cr = 1; - - /* "DIFSL" field of CtrlS - defines the size of DIFS, which varies from - * 0 to 56 bytes - */ - ctrl_sl->ch.wd0.dif_sl = 0; - - /* "CSL" field of CtrlS - defines the size of CS, which varies from 0 to - * 24 bytes - */ - ctrl_sl->ch.wd0.csl = 0; - - /* CtrlSL describes the size of CtrlS in 8 bytes chunks. The - * value Zero is not valid - */ - ctrl_sl->ch.wd0.ctrl_sl = 1; - - /* "O" - Owner - marks ownership of WQE */ - ctrl_sl->ch.wd0.owner = 0; -} - -void spfc_build_trd_twr_wqe_ctrls(struct unf_frame_pkg *pkg, struct spfc_sqe *sqe) -{ - /* "BDSL" field of CtrlS - defines the size of BDS, which varies from 0 - * to 2040 bytes (8 bits of 8 bytes' chunk) - */ - /* TrdWqe carry 2 SGE defaultly, 4DW per SGE, the value is 4 because - * unit is 2DW, in double SGL mode, bdsl is 2 - */ - sqe->ctrl_sl.ch.wd0.bdsl = SPFC_T_RD_WR_WQE_CTR_BDSL_SIZE; - - /* "DrvSL" field of CtrlS - defines the size of DrvS, which varies from - * 0 to 24 bytes - */ - /* DrvSL = 0 */ - sqe->ctrl_sl.ch.wd0.drv_sl = 0; - - /* a. - * b1 - linking WQE, which will be only used in linked page architecture - * instead of ring, it's a special control WQE which does not contain - * any buffer or inline data information, and will only be consumed by - * hardware. The size is aligned to WQEBB/WQE b0 - normal WQE, either - * normal SEG WQE or inline data WQE - */ - /* normal wqe */ - sqe->ctrl_sl.ch.wd0.wf = 0; - - /* - * "CF" field of CtrlS - Completion Format - defines the format of CS. - * a. b0 - Status information is embedded inside of Completion Section - * b. b1 - Completion Section keeps SGL, where Status information - * should be written. (For the definition of SGLs see ?4.1) - */ - /* by SCQE mode, the value is ignored */ - sqe->ctrl_sl.ch.wd0.cf = 0; - - /* "TSL" field of CtrlS - defines the size of TS, which varies from 0 to - * 248 bytes - */ - /* TSL is configured by 56 bytes */ - sqe->ctrl_sl.ch.wd0.tsl = - sizeof(struct spfc_sqe_ts) / SPFC_WQE_SECTION_CHUNK_SIZE; - - /* - * Variable length SGE (vSGE). The size of SGE is 16 bytes. The vSGE - * format is of two types, which are defined by "VA " field of CtrlS. - * "VA" stands for Virtual Address: o b0. SGE comprises 64-bits buffer's - * pointer and 31-bits Length, each SGE can only support up to 2G-1B, it - * can guarantee each single SGE length can not exceed 2GB by nature, A - * byte count value of zero means a 0byte data transfer. o b1. SGE - * comprises 64-bits buffer's pointer, 31-bits Length and 30-bits Key of - * the Translation table , each SGE can only support up to 2G-1B, it can - * guarantee each single SGE length can not exceed 2GB by nature, A byte - * count value of zero means a 0byte data transfer - */ - sqe->ctrl_sl.ch.wd0.va = 0; - - /* - * "DF" field of CtrlS - Data Format - defines the format of BDS - * a. b0 - BDS carries the list of SGEs (SGL) - * b. b1 - BDS carries the inline data - */ - sqe->ctrl_sl.ch.wd0.df = 0; - - /* "CR" - Completion is Required - marks CQE generation request per WQE - */ - /* by SCQE mode, this value is ignored */ - sqe->ctrl_sl.ch.wd0.cr = 1; - - /* "DIFSL" field of CtrlS - defines the size of DIFS, which varies from - * 0 to 56 bytes. - */ - sqe->ctrl_sl.ch.wd0.dif_sl = 0; - - /* "CSL" field of CtrlS - defines the size of CS, which varies from 0 to - * 24 bytes - */ - sqe->ctrl_sl.ch.wd0.csl = 0; - - /* CtrlSL describes the size of CtrlS in 8 bytes chunks. The - * value Zero is not valid. - */ - sqe->ctrl_sl.ch.wd0.ctrl_sl = SPFC_T_RD_WR_WQE_CTR_CTRLSL_SIZE; - - /* "O" - Owner - marks ownership of WQE */ - sqe->ctrl_sl.ch.wd0.owner = 0; -} - -/* **************************************************************************** - * Function Name : spfc_build_service_wqe_ts_common - * Function Description : Construct the DW1~DW3 field in the Parent SQ WQE - * request of the ELS and ELS_RSP requests. - * Input Parameters : struct spfc_sqe_ts *sqe_ts u32 rport_index u16 local_xid - * u16 remote_xid u16 data_len - * Output Parameters : N/A - * Return Type : void - **************************************************************************** - */ -void spfc_build_service_wqe_ts_common(struct spfc_sqe_ts *sqe_ts, u32 rport_index, - u16 local_xid, u16 remote_xid, u16 data_len) -{ - sqe_ts->local_xid = local_xid; - - sqe_ts->wd0.conn_id = (u16)rport_index; - sqe_ts->wd0.remote_xid = remote_xid; - - sqe_ts->cont.els_gs_elsrsp_comm.data_len = data_len; -} - -/* **************************************************************************** - * Function Name : spfc_build_els_gs_wqe_sge - * Function Description : Construct the SGE field of the ELS and ELS_RSP WQE. - * The SGE and frame content have been converted to large ends in this - * function. - * Input Parameters: struct spfc_sqe *sqe void *buf_addr u32 buf_len u32 xid - * Output Parameters : N/A - * Return Type : void - **************************************************************************** - */ -void spfc_build_els_gs_wqe_sge(struct spfc_sqe *sqe, void *buf_addr, u64 phy_addr, - u32 buf_len, u32 xid, void *handle) -{ - u64 els_rsp_phy_addr; - struct spfc_variable_sge *sge = NULL; - - /* Fill in SGE and convert it to big-endian. */ - sge = &sqe->sge[ARRAY_INDEX_0]; - els_rsp_phy_addr = phy_addr; - sge->buf_addr_hi = SPFC_HIGH_32_BITS(els_rsp_phy_addr); - sge->buf_addr_lo = SPFC_LOW_32_BITS(els_rsp_phy_addr); - sge->wd0.buf_len = buf_len; - sge->wd0.r_flag = 0; - sge->wd1.extension_flag = SPFC_WQE_SGE_NOT_EXTEND_FLAG; - sge->wd1.buf_addr_gpa = SPFC_ZEROCOPY_PCIE_TEMPLATE_VALUE; - sge->wd1.xid = 0; - sge->wd1.last_flag = SPFC_WQE_SGE_LAST_FLAG; - spfc_cpu_to_big32(sge, sizeof(*sge)); - - /* Converts the payload of an FC frame into a big end. */ - if (buf_addr) - spfc_cpu_to_big32(buf_addr, buf_len); -} - -/* **************************************************************************** - * Function Name : spfc_build_els_wqe_ts_rsp - * Function Description : Construct the DW2~DW6 field in the Parent SQ WQE - * of the ELS_RSP request. - * Input Parameters : struct spfc_sqe *sqe void *sq_info void *frame_pld - * u16 type u16 cmnd u32 scqn - * Output Parameters: N/A - * Return Type : void - **************************************************************************** - */ -void spfc_build_els_wqe_ts_rsp(struct spfc_sqe *sqe, void *info, - struct unf_frame_pkg *pkg, void *frame_pld, - u16 type, u16 cmnd) -{ - struct unf_prli_payload *prli_acc_pld = NULL; - struct spfc_sqe_els_rsp *els_rsp = NULL; - struct spfc_sqe_ts *sqe_ts = NULL; - struct spfc_parent_sq_info *sq_info = NULL; - struct spfc_hba_info *hba = NULL; - struct unf_fc_head *pkg_fc_hdr_info = NULL; - struct spfc_parent_queue_info *prnt_q_info = (struct spfc_parent_queue_info *)info; - - FC_CHECK_RETURN_VOID(sqe); - FC_CHECK_RETURN_VOID(frame_pld); - - sqe_ts = &sqe->ts_sl; - els_rsp = &sqe_ts->cont.els_rsp; - sqe_ts->task_type = SPFC_SQE_ELS_RSP; - - /* The default chip does not need to update parameters. */ - els_rsp->wd1.para_update = 0x0; - - sq_info = &prnt_q_info->parent_sq_info; - hba = (struct spfc_hba_info *)sq_info->hba; - - pkg_fc_hdr_info = &pkg->frame_head; - els_rsp->sid = pkg_fc_hdr_info->csctl_sid; - els_rsp->did = pkg_fc_hdr_info->rctl_did; - els_rsp->wd7.hotpooltag = UNF_GET_HOTPOOL_TAG(pkg) + hba->exi_base; - els_rsp->wd2.class_mode = FC_PROTOCOL_CLASS_3; - - if (type == ELS_RJT) - els_rsp->wd2.class_mode = pkg->class_mode; - - /* When the PLOGI request is sent, the microcode needs to be instructed - * to clear the I/O related to the link to avoid data inconsistency - * caused by the disorder of the IO. - */ - if ((cmnd == ELS_LOGO || cmnd == ELS_PLOGI)) { - els_rsp->wd1.clr_io = 1; - els_rsp->wd6.reset_exch_start = hba->exi_base; - els_rsp->wd6.reset_exch_end = - hba->exi_base + (hba->exi_count - 1); - els_rsp->wd7.scqn = - prnt_q_info->parent_sts_scq_info.cqm_queue_id; - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "Port(0x%x) send cmd(0x%x) to RPort(0x%x),rport index(0x%x), notify clean io start 0x%x, end 0x%x, scqn 0x%x.", - sq_info->local_port_id, cmnd, sq_info->remote_port_id, - sq_info->rport_index, els_rsp->wd6.reset_exch_start, - els_rsp->wd6.reset_exch_end, els_rsp->wd7.scqn); - - return; - } - - if (type == ELS_RJT) - return; - - /* Enter WQE in the PrliAcc negotiation parameter, and fill in the - * Update flag in WQE. - */ - if (cmnd == ELS_PRLI) { - /* The chip updates the PLOGI ACC negotiation parameters. */ - els_rsp->wd2.seq_cnt = sq_info->plogi_co_parms.seq_cnt; - els_rsp->wd2.e_d_tov = sq_info->plogi_co_parms.ed_tov; - els_rsp->wd2.tx_mfs = sq_info->plogi_co_parms.tx_mfs; - els_rsp->e_d_tov_timer_val = sq_info->plogi_co_parms.ed_tov_time; - - /* The chip updates the PRLI ACC parameter. */ - prli_acc_pld = (struct unf_prli_payload *)frame_pld; - els_rsp->wd4.xfer_dis = SPFC_GET_PRLI_PARAM_WXFER(prli_acc_pld->parms); - els_rsp->wd4.conf = SPFC_GET_PRLI_PARAM_CONF(prli_acc_pld->parms); - els_rsp->wd4.rec = SPFC_GET_PRLI_PARAM_REC(prli_acc_pld->parms); - - els_rsp->wd1.para_update = 0x03; - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "Port(0x%x) save rport index(0x%x) login parms,seqcnt:0x%x,e_d_tov:0x%x,txmfs:0x%x,e_d_tovtimerval:0x%x, xfer_dis:0x%x,conf:0x%x,rec:0x%x.", - sq_info->local_port_id, sq_info->rport_index, - els_rsp->wd2.seq_cnt, els_rsp->wd2.e_d_tov, - els_rsp->wd2.tx_mfs, els_rsp->e_d_tov_timer_val, - els_rsp->wd4.xfer_dis, els_rsp->wd4.conf, els_rsp->wd4.rec); - } -} - -/* **************************************************************************** - * Function Name : spfc_build_els_wqe_ts_req - * Function Description: Construct the DW2~DW4 field in the Parent SQ WQE - * of the ELS request. - * Input Parameters: struct spfc_sqe *sqe void *sq_info u16 cmnd u32 scqn - * Output Parameters: N/A - * Return Type: void - **************************************************************************** - */ -void spfc_build_els_wqe_ts_req(struct spfc_sqe *sqe, void *info, u32 scqn, - void *frame_pld, struct unf_frame_pkg *pkg) -{ - struct spfc_sqe_ts *sqe_ts = NULL; - struct spfc_sqe_t_els_gs *els_req = NULL; - struct spfc_parent_sq_info *sq_info = NULL; - struct spfc_hba_info *hba = NULL; - struct unf_fc_head *pkg_fc_hdr_info = NULL; - u16 cmnd; - - cmnd = SPFC_GET_LS_GS_CMND_CODE(pkg->cmnd); - - sqe_ts = &sqe->ts_sl; - if (pkg->type == UNF_PKG_GS_REQ) - sqe_ts->task_type = SPFC_SQE_GS_CMND; - else - sqe_ts->task_type = SPFC_SQE_ELS_CMND; - - sqe_ts->magic_num = UNF_GETXCHGALLOCTIME(pkg); - - els_req = &sqe_ts->cont.t_els_gs; - pkg_fc_hdr_info = &pkg->frame_head; - - sq_info = (struct spfc_parent_sq_info *)info; - hba = (struct spfc_hba_info *)sq_info->hba; - els_req->sid = pkg_fc_hdr_info->csctl_sid; - els_req->did = pkg_fc_hdr_info->rctl_did; - - /* When the PLOGI request is sent, the microcode needs to be instructed - * to clear the I/O related to the link to avoid data inconsistency - * caused by the disorder of the IO. - */ - if ((cmnd == ELS_LOGO || cmnd == ELS_PLOGI) && hba) { - els_req->wd4.clr_io = 1; - els_req->wd6.reset_exch_start = hba->exi_base; - els_req->wd6.reset_exch_end = hba->exi_base + (hba->exi_count - 1); - els_req->wd7.scqn = scqn; - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "Port(0x%x) Rport(0x%x) SID(0x%x) send %s to DID(0x%x), notify clean io start 0x%x, end 0x%x, scqn 0x%x.", - hba->port_cfg.port_id, sq_info->rport_index, - sq_info->local_port_id, (cmnd == ELS_PLOGI) ? "PLOGI" : "LOGO", - sq_info->remote_port_id, els_req->wd6.reset_exch_start, - els_req->wd6.reset_exch_end, scqn); - - return; - } - - /* The chip updates the PLOGI ACC negotiation parameters. */ - if (cmnd == ELS_PRLI) { - els_req->wd5.seq_cnt = sq_info->plogi_co_parms.seq_cnt; - els_req->wd5.e_d_tov = sq_info->plogi_co_parms.ed_tov; - els_req->wd5.tx_mfs = sq_info->plogi_co_parms.tx_mfs; - els_req->e_d_tov_timer_val = sq_info->plogi_co_parms.ed_tov_time; - - els_req->wd4.rec_support = hba->port_cfg.tape_support ? 1 : 0; - els_req->wd4.para_update = 0x01; - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, - UNF_INFO, - "Port(0x%x) save rport index(0x%x) login parms,seqcnt:0x%x,e_d_tov:0x%x,txmfs:0x%x,e_d_tovtimerval:0x%x.", - sq_info->local_port_id, sq_info->rport_index, - els_req->wd5.seq_cnt, els_req->wd5.e_d_tov, - els_req->wd5.tx_mfs, els_req->e_d_tov_timer_val); - } - - if (cmnd == ELS_ECHO) - els_req->echo_flag = true; - - if (cmnd == ELS_REC) { - els_req->wd4.rec_flag = 1; - els_req->wd4.origin_hottag = pkg->origin_hottag + hba->exi_base; - els_req->origin_magicnum = pkg->origin_magicnum; - - FC_DRV_PRINT(UNF_LOG_LOGIN_ATT, UNF_MAJOR, - "Port(0x%x) Rport(0x%x) SID(0x%x) send Rec to DID(0x%x), origin_hottag 0x%x", - hba->port_cfg.port_id, sq_info->rport_index, - sq_info->local_port_id, sq_info->remote_port_id, - els_req->wd4.origin_hottag); - } -} - -/* **************************************************************************** - * Function Name : spfc_build_bls_wqe_ts_req - * Function Description: Construct the DW2 field in the Parent SQ WQE of - * the ELS request, that is, ABTS parameter. - * Input Parameters:struct unf_frame_pkg *pkg void *hba - * Output Parameters: N/A - * Return Type: void - **************************************************************************** - */ -void spfc_build_bls_wqe_ts_req(struct spfc_sqe *sqe, struct unf_frame_pkg *pkg, void *handle) -{ - struct spfc_sqe_abts *abts; - - sqe->ts_sl.task_type = SPFC_SQE_BLS_CMND; - sqe->ts_sl.magic_num = UNF_GETXCHGALLOCTIME(pkg); - - abts = &sqe->ts_sl.cont.abts; - abts->fh_parm_abts = pkg->frame_head.parameter; - abts->hotpooltag = UNF_GET_HOTPOOL_TAG(pkg) + - ((struct spfc_hba_info *)handle)->exi_base; - abts->release_timer = UNF_GET_XID_RELEASE_TIMER(pkg); -} - -/* **************************************************************************** - * Function Name : spfc_build_service_wqe_ctrl_section - * Function Description: fill Parent SQ WQE and Root SQ WQE's Control Section - * Input Parameters : struct spfc_wqe_ctrl *wqe_cs u32 ts_size u32 bdsl - * Output Parameters : N/A - * Return Type : void - **************************************************************************** - */ -void spfc_build_service_wqe_ctrl_section(struct spfc_wqe_ctrl *wqe_cs, u32 ts_size, - u32 bdsl) -{ - wqe_cs->ch.wd0.bdsl = bdsl; - wqe_cs->ch.wd0.drv_sl = 0; - wqe_cs->ch.wd0.rsvd0 = 0; - wqe_cs->ch.wd0.wf = 0; - wqe_cs->ch.wd0.cf = 0; - wqe_cs->ch.wd0.tsl = ts_size; - wqe_cs->ch.wd0.va = 0; - wqe_cs->ch.wd0.df = 0; - wqe_cs->ch.wd0.cr = 1; - wqe_cs->ch.wd0.dif_sl = 0; - wqe_cs->ch.wd0.csl = 0; - wqe_cs->ch.wd0.ctrl_sl = SPFC_BYTES_TO_QW_NUM(sizeof(*wqe_cs)); /* divided by 8 */ - wqe_cs->ch.wd0.owner = 0; -} - -/* **************************************************************************** - * Function Name : spfc_build_wqe_owner_pmsn - * Function Description: This field is filled using the value of Control - * Section of Parent SQ WQE. - * Input Parameters: struct spfc_wqe_ctrl *wqe_cs u16 owner u16 pmsn - * Output Parameters : N/A - * Return Type: void - **************************************************************************** - */ -void spfc_build_wqe_owner_pmsn(struct spfc_sqe *io_sqe, u16 owner, u16 pmsn) -{ - struct spfc_wqe_ctrl *wqe_cs = &io_sqe->ctrl_sl; - struct spfc_wqe_ctrl *wqee_cs = &io_sqe->ectrl_sl; - - wqe_cs->qsf.wqe_sn = pmsn; - wqe_cs->qsf.dump_wqe_sn = wqe_cs->qsf.wqe_sn; - wqe_cs->ch.wd0.owner = (u32)owner; - wqee_cs->ch.ctrl_ch_val = wqe_cs->ch.ctrl_ch_val; - wqee_cs->qsf.wqe_sn = wqe_cs->qsf.wqe_sn; - wqee_cs->qsf.dump_wqe_sn = wqe_cs->qsf.dump_wqe_sn; -} - -/* **************************************************************************** - * Function Name : spfc_convert_parent_wqe_to_big_endian - * Function Description: Set the Done field of Parent SQ WQE and convert - * Control Section and Task Section to big-endian. - * Input Parameters:struct spfc_sqe *sqe - * Output Parameters : N/A - * Return Type : void - **************************************************************************** - */ -void spfc_convert_parent_wqe_to_big_endian(struct spfc_sqe *sqe) -{ - if (likely(sqe->ts_sl.task_type != SPFC_TASK_T_TRESP && - sqe->ts_sl.task_type != SPFC_TASK_T_TMF_RESP)) { - /* Convert Control Secton and Task Section to big-endian. Before - * the SGE enters the queue, the upper-layer driver converts the - * SGE and Task Section to the big-endian mode. - */ - spfc_cpu_to_big32(&sqe->ctrl_sl, sizeof(sqe->ctrl_sl)); - spfc_cpu_to_big32(&sqe->ts_sl, sizeof(sqe->ts_sl)); - spfc_cpu_to_big32(&sqe->ectrl_sl, sizeof(sqe->ectrl_sl)); - spfc_cpu_to_big32(&sqe->sid, sizeof(sqe->sid)); - spfc_cpu_to_big32(&sqe->did, sizeof(sqe->did)); - spfc_cpu_to_big32(&sqe->wqe_gpa, sizeof(sqe->wqe_gpa)); - spfc_cpu_to_big32(&sqe->db_val, sizeof(sqe->db_val)); - } else { - /* The SPFC_TASK_T_TRESP may use the SGE as the Task Section to - * convert the entire SQE into a large end. - */ - spfc_cpu_to_big32(sqe, sizeof(struct spfc_sqe_tresp)); - } -} - -/* **************************************************************************** - * Function Name : spfc_build_cmdqe_common - * Function Description : Assemble the Cmdqe Common part. - * Input Parameters: union spfc_cmdqe *cmd_qe enum spfc_task_type task_type u16 rxid - * Output Parameters : N/A - * Return Type: void - **************************************************************************** - */ -void spfc_build_cmdqe_common(union spfc_cmdqe *cmd_qe, enum spfc_task_type task_type, - u16 rxid) -{ - cmd_qe->common.wd0.task_type = task_type; - cmd_qe->common.wd0.rx_id = rxid; - cmd_qe->common.wd0.rsvd0 = 0; -} - -#define SPFC_STANDARD_SIRT_ENABLE (1) -#define SPFC_STANDARD_SIRT_DISABLE (0) -#define SPFC_UNKNOWN_ID (0xFFFF) - -void spfc_build_icmnd_wqe_ts_header(struct unf_frame_pkg *pkg, struct spfc_sqe *sqe, - u8 task_type, u16 exi_base, u8 port_idx) -{ - sqe->ts_sl.local_xid = (u16)UNF_GET_HOTPOOL_TAG(pkg) + exi_base; - sqe->ts_sl.task_type = task_type; - sqe->ts_sl.wd0.conn_id = - (u16)(pkg->private_data[PKG_PRIVATE_XCHG_RPORT_INDEX]); - - sqe->ts_sl.wd0.remote_xid = SPFC_UNKNOWN_ID; - sqe->ts_sl.magic_num = UNF_GETXCHGALLOCTIME(pkg); -} - -/* **************************************************************************** - * Function Name : spfc_build_icmnd_wqe_ts - * Function Description : Constructing the TS Domain of the ICmnd - * Input Parameters: void *hba struct unf_frame_pkg *pkg - * struct spfc_sqe_ts *sqe_ts - * Output Parameters :N/A - * Return Type : void - **************************************************************************** - */ -void spfc_build_icmnd_wqe_ts(void *handle, struct unf_frame_pkg *pkg, - struct spfc_sqe_ts *sqe_ts, union spfc_sqe_ts_ex *sqe_tsex) -{ - struct spfc_sqe_icmnd *icmnd = &sqe_ts->cont.icmnd; - struct spfc_hba_info *hba = NULL; - - hba = (struct spfc_hba_info *)handle; - - sqe_ts->cdb_type = 0; - memcpy(icmnd->fcp_cmnd_iu, pkg->fcp_cmnd, sizeof(struct unf_fcp_cmnd)); - - if (sqe_ts->task_type == SPFC_SQE_FCP_ITMF) { - icmnd->info.tmf.w0.bs.reset_exch_start = hba->exi_base; - icmnd->info.tmf.w0.bs.reset_exch_end = hba->exi_base + hba->exi_count - 1; - - icmnd->info.tmf.w1.bs.reset_did = UNF_GET_DID(pkg); - /* delivers the marker status flag to the microcode. */ - icmnd->info.tmf.w1.bs.marker_sts = 1; - SPFC_GET_RESET_TYPE(UNF_GET_TASK_MGMT_FLAGS(pkg->fcp_cmnd->control), - icmnd->info.tmf.w1.bs.reset_type); - - icmnd->info.tmf.w2.bs.reset_sid = UNF_GET_SID(pkg); - - memcpy(icmnd->info.tmf.reset_lun, pkg->fcp_cmnd->lun, - sizeof(icmnd->info.tmf.reset_lun)); - } -} - -/* **************************************************************************** - * Function Name : spfc_build_icmnd_wqe_ctrls - * Function Description : The CtrlS domain of the ICmnd is constructed. The - * analysis result is the same as that of the TWTR. - * Input Parameters: struct unf_frame_pkg *pkg struct spfc_sqe *sqe - * Output Parameters: N/A - * Return Type: void - **************************************************************************** - */ -void spfc_build_icmnd_wqe_ctrls(struct unf_frame_pkg *pkg, struct spfc_sqe *sqe) -{ - spfc_build_trd_twr_wqe_ctrls(pkg, sqe); -} - -/* **************************************************************************** - * Function Name : spfc_build_srq_wqe_ctrls - * Function Description : Construct the CtrlS domain of the ICmnd. The analysis - * result is the same as that of the TWTR. - * Input Parameters : struct spfc_rqe *rqe u16 owner u16 pmsn - * Output Parameters : N/A - * Return Type : void - **************************************************************************** - */ -void spfc_build_srq_wqe_ctrls(struct spfc_rqe *rqe, u16 owner, u16 pmsn) -{ - struct spfc_wqe_ctrl_ch *wqe_ctrls = NULL; - - wqe_ctrls = &rqe->ctrl_sl.ch; - wqe_ctrls->wd0.owner = owner; - wqe_ctrls->wd0.ctrl_sl = sizeof(struct spfc_wqe_ctrl) >> UNF_SHIFT_3; - wqe_ctrls->wd0.csl = 1; - wqe_ctrls->wd0.dif_sl = 0; - wqe_ctrls->wd0.cr = 1; - wqe_ctrls->wd0.df = 0; - wqe_ctrls->wd0.va = 0; - wqe_ctrls->wd0.tsl = 0; - wqe_ctrls->wd0.cf = 0; - wqe_ctrls->wd0.wf = 0; - wqe_ctrls->wd0.drv_sl = sizeof(struct spfc_rqe_drv) >> UNF_SHIFT_3; - wqe_ctrls->wd0.bdsl = sizeof(struct spfc_constant_sge) >> UNF_SHIFT_3; - - rqe->ctrl_sl.wd0.wqe_msn = pmsn; - rqe->ctrl_sl.wd0.dump_wqe_msn = rqe->ctrl_sl.wd0.wqe_msn; -} diff --git a/drivers/scsi/spfc/hw/spfc_wqe.h b/drivers/scsi/spfc/hw/spfc_wqe.h deleted file mode 100644 index ec6d7bbdf8f9..000000000000 --- a/drivers/scsi/spfc/hw/spfc_wqe.h +++ /dev/null @@ -1,239 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPFC_WQE_H -#define SPFC_WQE_H - -#include "unf_type.h" -#include "unf_common.h" -#include "spfc_hw_wqe.h" -#include "spfc_parent_context.h" - -/* TGT WQE type */ -/* DRV->uCode via Parent SQ */ -#define SPFC_SQE_FCP_TRD SPFC_TASK_T_TREAD -#define SPFC_SQE_FCP_TWR SPFC_TASK_T_TWRITE -#define SPFC_SQE_FCP_TRSP SPFC_TASK_T_TRESP -#define SPFC_SQE_FCP_TACK SPFC_TASK_T_TACK -#define SPFC_SQE_ELS_CMND SPFC_TASK_T_ELS -#define SPFC_SQE_ELS_RSP SPFC_TASK_T_ELS_RSP -#define SPFC_SQE_GS_CMND SPFC_TASK_T_GS -#define SPFC_SQE_BLS_CMND SPFC_TASK_T_ABTS -#define SPFC_SQE_FCP_IREAD SPFC_TASK_T_IREAD -#define SPFC_SQE_FCP_IWRITE SPFC_TASK_T_IWRITE -#define SPFC_SQE_FCP_ITMF SPFC_TASK_T_ITMF -#define SPFC_SQE_SESS_RST SPFC_TASK_T_SESS_RESET -#define SPFC_SQE_FCP_TMF_TRSP SPFC_TASK_T_TMF_RESP -#define SPFC_SQE_NOP SPFC_TASK_T_NOP -/* DRV->uCode Via CMDQ */ -#define SPFC_CMDQE_ABTS_RSP SPFC_TASK_T_ABTS_RSP -#define SPFC_CMDQE_ABORT SPFC_TASK_T_ABORT -#define SPFC_CMDQE_SESS_DIS SPFC_TASK_T_SESS_DIS -#define SPFC_CMDQE_SESS_DEL SPFC_TASK_T_SESS_DEL - -/* uCode->Drv Via CMD SCQ */ -#define SPFC_SCQE_FCP_TCMND SPFC_TASK_T_RCV_TCMND -#define SPFC_SCQE_ELS_CMND SPFC_TASK_T_RCV_ELS_CMD -#define SPFC_SCQE_ABTS_CMD SPFC_TASK_T_RCV_ABTS_CMD -#define SPFC_SCQE_FCP_IRSP SPFC_TASK_T_IRESP -#define SPFC_SCQE_FCP_ITMF_RSP SPFC_TASK_T_ITMF_RESP - -/* uCode->Drv Via STS SCQ */ -#define SPFC_SCQE_FCP_TSTS SPFC_TASK_T_TSTS -#define SPFC_SCQE_GS_RSP SPFC_TASK_T_RCV_GS_RSP -#define SPFC_SCQE_ELS_RSP SPFC_TASK_T_RCV_ELS_RSP -#define SPFC_SCQE_ABTS_RSP SPFC_TASK_T_RCV_ABTS_RSP -#define SPFC_SCQE_ELS_RSP_STS SPFC_TASK_T_ELS_RSP_STS -#define SPFC_SCQE_ABORT_STS SPFC_TASK_T_ABORT_STS -#define SPFC_SCQE_SESS_EN_STS SPFC_TASK_T_SESS_EN_STS -#define SPFC_SCQE_SESS_DIS_STS SPFC_TASK_T_SESS_DIS_STS -#define SPFC_SCQE_SESS_DEL_STS SPFC_TASK_T_SESS_DEL_STS -#define SPFC_SCQE_SESS_RST_STS SPFC_TASK_T_SESS_RESET_STS -#define SPFC_SCQE_ITMF_MARKER_STS SPFC_TASK_T_ITMF_MARKER_STS -#define SPFC_SCQE_ABTS_MARKER_STS SPFC_TASK_T_ABTS_MARKER_STS -#define SPFC_SCQE_FLUSH_SQ_STS SPFC_TASK_T_FLUSH_SQ_STS -#define SPFC_SCQE_BUF_CLEAR_STS SPFC_TASK_T_BUFFER_CLEAR_STS -#define SPFC_SCQE_CLEAR_SRQ_STS SPFC_TASK_T_CLEAR_SRQ_STS -#define SPFC_SCQE_DIFX_RESULT_STS SPFC_TASK_T_DIFX_RESULT_STS -#define SPFC_SCQE_XID_FREE_ABORT_STS SPFC_TASK_T_EXCH_ID_FREE_ABORT_STS -#define SPFC_SCQE_EXCHID_TIMEOUT_STS SPFC_TASK_T_EXCHID_TIMEOUT_STS -#define SPFC_SQE_NOP_STS SPFC_TASK_T_NOP_STS - -#define SPFC_LOW_32_BITS(__addr) ((u32)((u64)(__addr) & 0xffffffff)) -#define SPFC_HIGH_32_BITS(__addr) ((u32)(((u64)(__addr) >> 32) & 0xffffffff)) - -/* Error Code from SCQ */ -#define SPFC_COMPLETION_STATUS_SUCCESS FC_CQE_COMPLETED -#define SPFC_COMPLETION_STATUS_ABORTED_SETUP_FAIL FC_IMMI_CMDPKT_SETUP_FAIL - -#define SPFC_COMPLETION_STATUS_TIMEOUT FC_ERROR_CODE_E_D_TIMER_EXPIRE -#define SPFC_COMPLETION_STATUS_DIF_ERROR FC_ERROR_CODE_DATA_DIFX_FAILED -#define SPFC_COMPLETION_STATUS_DATA_OOO FC_ERROR_CODE_DATA_OOO_RO -#define SPFC_COMPLETION_STATUS_DATA_OVERFLOW \ - FC_ERROR_CODE_DATA_EXCEEDS_DATA2TRNS - -#define SPFC_SCQE_INVALID_CONN_ID (0xffff) -#define SPFC_GET_SCQE_TYPE(scqe) ((scqe)->common.ch.wd0.task_type) -#define SPFC_GET_SCQE_STATUS(scqe) ((scqe)->common.ch.wd0.err_code) -#define SPFC_GET_SCQE_REMAIN_CNT(scqe) ((scqe)->common.ch.wd0.cqe_remain_cnt) -#define SPFC_GET_SCQE_CONN_ID(scqe) ((scqe)->common.conn_id) -#define SPFC_GET_SCQE_SQN(scqe) ((scqe)->common.ch.wd0.sqn) -#define SPFC_GET_WQE_TYPE(wqe) ((wqe)->ts_sl.task_type) - -#define SPFC_WQE_IS_IO(wqe) \ - ((SPFC_GET_WQE_TYPE(wqe) != SPFC_SQE_SESS_RST) && \ - (SPFC_GET_WQE_TYPE(wqe) != SPFC_SQE_NOP)) -#define SPFC_SCQE_HAS_ERRCODE(scqe) \ - (SPFC_GET_SCQE_STATUS(scqe) != SPFC_COMPLETION_STATUS_SUCCESS) -#define SPFC_SCQE_ERR_TO_CM(scqe) \ - (SPFC_GET_SCQE_STATUS(scqe) != FC_ELS_GS_RSP_EXCH_CHECK_FAIL) -#define SPFC_SCQE_EXCH_ABORTED(scqe) \ - ((SPFC_GET_SCQE_STATUS(scqe) >= \ - FC_CQE_BUFFER_CLEAR_IO_COMPLETED) && \ - (SPFC_GET_SCQE_STATUS(scqe) <= FC_CQE_WQE_FLUSH_IO_COMPLETED)) -#define SPFC_SCQE_CONN_ID_VALID(scqe) \ - (SPFC_GET_SCQE_CONN_ID(scqe) != SPFC_SCQE_INVALID_CONN_ID) - -/* - * checksum error bitmap define - */ -#define NIC_RX_CSUM_HW_BYPASS_ERR (1) -#define NIC_RX_CSUM_IP_CSUM_ERR (1 << 1) -#define NIC_RX_CSUM_TCP_CSUM_ERR (1 << 2) -#define NIC_RX_CSUM_UDP_CSUM_ERR (1 << 3) -#define NIC_RX_CSUM_SCTP_CRC_ERR (1 << 4) - -#define SPFC_WQE_SECTION_CHUNK_SIZE 8 /* 8 bytes' chunk */ -#define SPFC_T_RESP_WQE_CTR_TSL_SIZE 15 /* 8 bytes' chunk */ -#define SPFC_T_RD_WR_WQE_CTR_TSL_SIZE 9 /* 8 bytes' chunk */ -#define SPFC_T_RD_WR_WQE_CTR_BDSL_SIZE 4 /* 8 bytes' chunk */ -#define SPFC_T_RD_WR_WQE_CTR_CTRLSL_SIZE 1 /* 8 bytes' chunk */ - -#define SPFC_WQE_MAX_ESGE_NUM 3 /* 3 ESGE In Extended wqe */ -#define SPFC_WQE_SGE_ENTRY_NUM 2 /* BD SGE and DIF SGE count */ -#define SPFC_WQE_SGE_DIF_ENTRY_NUM 1 /* DIF SGE count */ -#define SPFC_WQE_SGE_LAST_FLAG 1 -#define SPFC_WQE_SGE_NOT_LAST_FLAG 0 -#define SPFC_WQE_SGE_EXTEND_FLAG 1 -#define SPFC_WQE_SGE_NOT_EXTEND_FLAG 0 - -#define SPFC_FCP_TMF_PORT_RESET (0) -#define SPFC_FCP_TMF_LUN_RESET (1) -#define SPFC_FCP_TMF_TGT_RESET (2) -#define SPFC_FCP_TMF_RSVD (3) - -#define SPFC_ADJUST_DATA(old_va, new_va) \ - { \ - (old_va) = new_va; \ - } - -#define SPFC_GET_RESET_TYPE(tmf_flag, reset_flag) \ - { \ - switch (tmf_flag) { \ - case UNF_FCP_TM_ABORT_TASK_SET: \ - case UNF_FCP_TM_LOGICAL_UNIT_RESET: \ - (reset_flag) = SPFC_FCP_TMF_LUN_RESET; \ - break; \ - case UNF_FCP_TM_TARGET_RESET: \ - (reset_flag) = SPFC_FCP_TMF_TGT_RESET; \ - break; \ - case UNF_FCP_TM_CLEAR_TASK_SET: \ - (reset_flag) = SPFC_FCP_TMF_PORT_RESET; \ - break; \ - default: \ - (reset_flag) = SPFC_FCP_TMF_RSVD; \ - } \ - } - -/* Link WQE structure */ -struct spfc_linkwqe { - union { - struct { - u32 rsv1 : 14; - u32 wf : 1; - u32 rsv2 : 14; - u32 ctrlsl : 2; - u32 o : 1; - } wd0; - - u32 val_wd0; - }; - - union { - struct { - u32 msn : 16; - u32 dump_msn : 15; - u32 lp : 1; /* lp means whether O bit is overturn */ - } wd1; - - u32 val_wd1; - }; - - u32 next_page_addr_hi; - u32 next_page_addr_lo; -}; - -/* Session Enable */ -struct spfc_host_keys { - struct { - u32 smac1 : 8; - u32 smac0 : 8; - u32 rsv : 16; - } wd0; - - u8 smac[ARRAY_INDEX_4]; - - u8 dmac[ARRAY_INDEX_4]; - struct { - u8 sid_1; - u8 sid_2; - u8 dmac_rvd[ARRAY_INDEX_2]; - } wd3; - struct { - u8 did_0; - u8 did_1; - u8 did_2; - u8 sid_0; - } wd4; - - struct { - u32 port_id : 3; - u32 host_id : 2; - u32 rsvd : 27; - } wd5; - u32 rsvd; -}; - -/* Parent SQ WQE Related function */ -void spfc_build_service_wqe_ctrl_section(struct spfc_wqe_ctrl *wqe_cs, u32 ts_size, - u32 bdsl); -void spfc_build_service_wqe_ts_common(struct spfc_sqe_ts *sqe_ts, u32 rport_index, - u16 local_xid, u16 remote_xid, - u16 data_len); -void spfc_build_els_gs_wqe_sge(struct spfc_sqe *sqe, void *buf_addr, u64 phy_addr, - u32 buf_len, u32 xid, void *handle); -void spfc_build_els_wqe_ts_req(struct spfc_sqe *sqe, void *info, u32 scqn, - void *frame_pld, struct unf_frame_pkg *pkg); -void spfc_build_els_wqe_ts_rsp(struct spfc_sqe *sqe, void *info, - struct unf_frame_pkg *pkg, void *frame_pld, - u16 type, u16 cmnd); -void spfc_build_bls_wqe_ts_req(struct spfc_sqe *sqe, struct unf_frame_pkg *pkg, - void *handle); -void spfc_build_trd_twr_wqe_ctrls(struct unf_frame_pkg *pkg, struct spfc_sqe *sqe); -void spfc_build_wqe_owner_pmsn(struct spfc_sqe *io_sqe, u16 owner, u16 pmsn); -void spfc_convert_parent_wqe_to_big_endian(struct spfc_sqe *sqe); -void spfc_build_icmnd_wqe_ctrls(struct unf_frame_pkg *pkg, struct spfc_sqe *sqe); -void spfc_build_icmnd_wqe_ts(void *handle, struct unf_frame_pkg *pkg, - struct spfc_sqe_ts *sqe_ts, union spfc_sqe_ts_ex *sqe_tsex); -void spfc_build_icmnd_wqe_ts_header(struct unf_frame_pkg *pkg, struct spfc_sqe *sqe, - u8 task_type, u16 exi_base, u8 port_idx); - -void spfc_build_cmdqe_common(union spfc_cmdqe *cmd_qe, enum spfc_task_type task_type, - u16 rxid); -void spfc_build_srq_wqe_ctrls(struct spfc_rqe *rqe, u16 owner, u16 pmsn); -void spfc_build_common_wqe_ctrls(struct spfc_wqe_ctrl *ctrl_sl, u8 task_len); -void spfc_build_tmf_rsp_wqe_ts_header(struct unf_frame_pkg *pkg, - struct spfc_sqe_tmf_rsp *sqe, u16 exi_base, - u32 scqn); - -#endif diff --git a/drivers/scsi/spfc/sphw_api_cmd.c b/drivers/scsi/spfc/sphw_api_cmd.c deleted file mode 120000 index 27c7c0770fa3..000000000000 --- a/drivers/scsi/spfc/sphw_api_cmd.c +++ /dev/null @@ -1 +0,0 @@ -../../net/ethernet/ramaxel/spnic/hw/sphw_api_cmd.c \ No newline at end of file diff --git a/drivers/scsi/spfc/sphw_cmdq.c b/drivers/scsi/spfc/sphw_cmdq.c deleted file mode 120000 index 5ac779ba274b..000000000000 --- a/drivers/scsi/spfc/sphw_cmdq.c +++ /dev/null @@ -1 +0,0 @@ -../../net/ethernet/ramaxel/spnic/hw/sphw_cmdq.c \ No newline at end of file diff --git a/drivers/scsi/spfc/sphw_common.c b/drivers/scsi/spfc/sphw_common.c deleted file mode 120000 index a1a30a4840e1..000000000000 --- a/drivers/scsi/spfc/sphw_common.c +++ /dev/null @@ -1 +0,0 @@ -../../net/ethernet/ramaxel/spnic/hw/sphw_common.c \ No newline at end of file diff --git a/drivers/scsi/spfc/sphw_eqs.c b/drivers/scsi/spfc/sphw_eqs.c deleted file mode 120000 index 74430dcb9dc5..000000000000 --- a/drivers/scsi/spfc/sphw_eqs.c +++ /dev/null @@ -1 +0,0 @@ -../../net/ethernet/ramaxel/spnic/hw/sphw_eqs.c \ No newline at end of file diff --git a/drivers/scsi/spfc/sphw_hw_cfg.c b/drivers/scsi/spfc/sphw_hw_cfg.c deleted file mode 120000 index 4f43d68624c1..000000000000 --- a/drivers/scsi/spfc/sphw_hw_cfg.c +++ /dev/null @@ -1 +0,0 @@ -../../net/ethernet/ramaxel/spnic/hw/sphw_hw_cfg.c \ No newline at end of file diff --git a/drivers/scsi/spfc/sphw_hw_comm.c b/drivers/scsi/spfc/sphw_hw_comm.c deleted file mode 120000 index c943b3b2933a..000000000000 --- a/drivers/scsi/spfc/sphw_hw_comm.c +++ /dev/null @@ -1 +0,0 @@ -../../net/ethernet/ramaxel/spnic/hw/sphw_hw_comm.c \ No newline at end of file diff --git a/drivers/scsi/spfc/sphw_hwdev.c b/drivers/scsi/spfc/sphw_hwdev.c deleted file mode 120000 index b7279f17eaa2..000000000000 --- a/drivers/scsi/spfc/sphw_hwdev.c +++ /dev/null @@ -1 +0,0 @@ -../../net/ethernet/ramaxel/spnic/hw/sphw_hwdev.c \ No newline at end of file diff --git a/drivers/scsi/spfc/sphw_hwif.c b/drivers/scsi/spfc/sphw_hwif.c deleted file mode 120000 index d40ef71f9033..000000000000 --- a/drivers/scsi/spfc/sphw_hwif.c +++ /dev/null @@ -1 +0,0 @@ -../../net/ethernet/ramaxel/spnic/hw/sphw_hwif.c \ No newline at end of file diff --git a/drivers/scsi/spfc/sphw_mbox.c b/drivers/scsi/spfc/sphw_mbox.c deleted file mode 120000 index 1b00fe7289cc..000000000000 --- a/drivers/scsi/spfc/sphw_mbox.c +++ /dev/null @@ -1 +0,0 @@ -../../net/ethernet/ramaxel/spnic/hw/sphw_mbox.c \ No newline at end of file diff --git a/drivers/scsi/spfc/sphw_mgmt.c b/drivers/scsi/spfc/sphw_mgmt.c deleted file mode 120000 index fd18a73e9d3a..000000000000 --- a/drivers/scsi/spfc/sphw_mgmt.c +++ /dev/null @@ -1 +0,0 @@ -../../net/ethernet/ramaxel/spnic/hw/sphw_mgmt.c \ No newline at end of file diff --git a/drivers/scsi/spfc/sphw_prof_adap.c b/drivers/scsi/spfc/sphw_prof_adap.c deleted file mode 120000 index fbc7db05dd27..000000000000 --- a/drivers/scsi/spfc/sphw_prof_adap.c +++ /dev/null @@ -1 +0,0 @@ -../../net/ethernet/ramaxel/spnic/hw/sphw_prof_adap.c \ No newline at end of file diff --git a/drivers/scsi/spfc/sphw_wq.c b/drivers/scsi/spfc/sphw_wq.c deleted file mode 120000 index cdfcb3a610c0..000000000000 --- a/drivers/scsi/spfc/sphw_wq.c +++ /dev/null @@ -1 +0,0 @@ -../../net/ethernet/ramaxel/spnic/hw/sphw_wq.c \ No newline at end of file
From: Yanling Song songyl@ramaxel.com
Ramaxel inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4ZR0O CVE: NA
----------------------------------
There are some issues of the driver that cannot be fixed now. The driver is not good enough for the LTS quality requirements of openEuler,so remove it.
Signed-off-by: Yanling Song songyl@ramaxel.com Reviewed-by: Yang Gan yanggan@ramaxel.com Acked-by: Xie Xiuqi xiexiuqi@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- arch/arm64/configs/openeuler_defconfig | 2 - arch/x86/configs/openeuler_defconfig | 2 - drivers/net/ethernet/Kconfig | 1 - drivers/net/ethernet/Makefile | 1 - drivers/net/ethernet/ramaxel/Kconfig | 20 - drivers/net/ethernet/ramaxel/Makefile | 6 - drivers/net/ethernet/ramaxel/spnic/Kconfig | 14 - drivers/net/ethernet/ramaxel/spnic/Makefile | 39 - .../ethernet/ramaxel/spnic/hw/sphw_api_cmd.c | 1165 ----------- .../ethernet/ramaxel/spnic/hw/sphw_api_cmd.h | 277 --- .../ethernet/ramaxel/spnic/hw/sphw_cfg_cmd.h | 127 -- .../net/ethernet/ramaxel/spnic/hw/sphw_cmdq.c | 1573 --------------- .../net/ethernet/ramaxel/spnic/hw/sphw_cmdq.h | 195 -- .../ethernet/ramaxel/spnic/hw/sphw_comm_cmd.h | 60 - .../ramaxel/spnic/hw/sphw_comm_msg_intf.h | 273 --- .../ethernet/ramaxel/spnic/hw/sphw_common.c | 88 - .../ethernet/ramaxel/spnic/hw/sphw_common.h | 106 - .../net/ethernet/ramaxel/spnic/hw/sphw_crm.h | 982 --------- .../net/ethernet/ramaxel/spnic/hw/sphw_csr.h | 158 -- .../net/ethernet/ramaxel/spnic/hw/sphw_eqs.c | 1272 ------------ .../net/ethernet/ramaxel/spnic/hw/sphw_eqs.h | 157 -- .../net/ethernet/ramaxel/spnic/hw/sphw_hw.h | 643 ------ .../ethernet/ramaxel/spnic/hw/sphw_hw_cfg.c | 1341 ------------ .../ethernet/ramaxel/spnic/hw/sphw_hw_cfg.h | 329 --- .../ethernet/ramaxel/spnic/hw/sphw_hw_comm.c | 1280 ------------ .../ethernet/ramaxel/spnic/hw/sphw_hw_comm.h | 45 - .../ethernet/ramaxel/spnic/hw/sphw_hwdev.c | 1324 ------------ .../ethernet/ramaxel/spnic/hw/sphw_hwdev.h | 93 - .../net/ethernet/ramaxel/spnic/hw/sphw_hwif.c | 886 -------- .../net/ethernet/ramaxel/spnic/hw/sphw_hwif.h | 102 - .../net/ethernet/ramaxel/spnic/hw/sphw_mbox.c | 1792 ----------------- .../net/ethernet/ramaxel/spnic/hw/sphw_mbox.h | 271 --- .../net/ethernet/ramaxel/spnic/hw/sphw_mgmt.c | 895 -------- .../net/ethernet/ramaxel/spnic/hw/sphw_mgmt.h | 106 - .../ramaxel/spnic/hw/sphw_mgmt_msg_base.h | 19 - .../net/ethernet/ramaxel/spnic/hw/sphw_mt.h | 533 ----- .../ramaxel/spnic/hw/sphw_prof_adap.c | 94 - .../ramaxel/spnic/hw/sphw_prof_adap.h | 49 - .../ethernet/ramaxel/spnic/hw/sphw_profile.h | 36 - .../net/ethernet/ramaxel/spnic/hw/sphw_wq.c | 152 -- .../net/ethernet/ramaxel/spnic/hw/sphw_wq.h | 119 -- .../net/ethernet/ramaxel/spnic/spnic_dbg.c | 752 ------- .../net/ethernet/ramaxel/spnic/spnic_dcb.c | 965 --------- .../net/ethernet/ramaxel/spnic/spnic_dcb.h | 56 - .../ethernet/ramaxel/spnic/spnic_dev_mgmt.c | 811 -------- .../ethernet/ramaxel/spnic/spnic_dev_mgmt.h | 78 - .../ethernet/ramaxel/spnic/spnic_ethtool.c | 994 --------- .../ramaxel/spnic/spnic_ethtool_stats.c | 1035 ---------- .../net/ethernet/ramaxel/spnic/spnic_filter.c | 411 ---- .../net/ethernet/ramaxel/spnic/spnic_irq.c | 178 -- .../net/ethernet/ramaxel/spnic/spnic_lld.c | 937 --------- .../net/ethernet/ramaxel/spnic/spnic_lld.h | 75 - .../ethernet/ramaxel/spnic/spnic_mag_cfg.c | 778 ------- .../ethernet/ramaxel/spnic/spnic_mag_cmd.h | 643 ------ .../net/ethernet/ramaxel/spnic/spnic_main.c | 924 --------- .../ramaxel/spnic/spnic_mgmt_interface.h | 605 ------ .../ethernet/ramaxel/spnic/spnic_netdev_ops.c | 1526 -------------- .../net/ethernet/ramaxel/spnic/spnic_nic.h | 148 -- .../ethernet/ramaxel/spnic/spnic_nic_cfg.c | 1334 ------------ .../ethernet/ramaxel/spnic/spnic_nic_cfg.h | 709 ------- .../ethernet/ramaxel/spnic/spnic_nic_cfg_vf.c | 658 ------ .../ethernet/ramaxel/spnic/spnic_nic_cmd.h | 105 - .../ethernet/ramaxel/spnic/spnic_nic_dbg.c | 151 -- .../ethernet/ramaxel/spnic/spnic_nic_dbg.h | 16 - .../ethernet/ramaxel/spnic/spnic_nic_dev.h | 354 ---- .../ethernet/ramaxel/spnic/spnic_nic_event.c | 506 ----- .../net/ethernet/ramaxel/spnic/spnic_nic_io.c | 1123 ----------- .../net/ethernet/ramaxel/spnic/spnic_nic_io.h | 305 --- .../net/ethernet/ramaxel/spnic/spnic_nic_qp.h | 416 ---- .../net/ethernet/ramaxel/spnic/spnic_ntuple.c | 841 -------- .../ethernet/ramaxel/spnic/spnic_pci_id_tbl.h | 12 - .../net/ethernet/ramaxel/spnic/spnic_rss.c | 741 ------- .../net/ethernet/ramaxel/spnic/spnic_rss.h | 50 - .../ethernet/ramaxel/spnic/spnic_rss_cfg.c | 333 --- drivers/net/ethernet/ramaxel/spnic/spnic_rx.c | 1238 ------------ drivers/net/ethernet/ramaxel/spnic/spnic_rx.h | 118 -- .../net/ethernet/ramaxel/spnic/spnic_sriov.c | 200 -- .../net/ethernet/ramaxel/spnic/spnic_sriov.h | 24 - drivers/net/ethernet/ramaxel/spnic/spnic_tx.c | 877 -------- drivers/net/ethernet/ramaxel/spnic/spnic_tx.h | 129 -- 80 files changed, 37783 deletions(-) delete mode 100644 drivers/net/ethernet/ramaxel/Kconfig delete mode 100644 drivers/net/ethernet/ramaxel/Makefile delete mode 100644 drivers/net/ethernet/ramaxel/spnic/Kconfig delete mode 100644 drivers/net/ethernet/ramaxel/spnic/Makefile delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_api_cmd.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_api_cmd.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_cfg_cmd.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_cmdq.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_cmdq.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_comm_cmd.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_comm_msg_intf.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_common.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_common.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_crm.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_csr.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_eqs.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_eqs.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw_cfg.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw_cfg.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw_comm.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw_comm.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_hwdev.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_hwdev.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_hwif.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_hwif.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_mbox.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_mbox.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_mgmt.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_mgmt.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_mgmt_msg_base.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_mt.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_prof_adap.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_prof_adap.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_profile.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_wq.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_wq.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_dbg.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_dcb.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_dcb.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_dev_mgmt.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_dev_mgmt.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_ethtool.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_ethtool_stats.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_filter.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_irq.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_lld.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_lld.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_mag_cfg.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_mag_cmd.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_main.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_mgmt_interface.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_netdev_ops.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_nic.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_nic_cfg.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_nic_cfg.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_nic_cfg_vf.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_nic_cmd.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_nic_dbg.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_nic_dbg.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_nic_dev.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_nic_event.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_nic_io.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_nic_io.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_nic_qp.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_ntuple.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_pci_id_tbl.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_rss.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_rss.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_rss_cfg.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_rx.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_rx.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_sriov.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_sriov.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_tx.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_tx.h
diff --git a/arch/arm64/configs/openeuler_defconfig b/arch/arm64/configs/openeuler_defconfig index 1fd250cc103c..5020f94eea34 100644 --- a/arch/arm64/configs/openeuler_defconfig +++ b/arch/arm64/configs/openeuler_defconfig @@ -2815,8 +2815,6 @@ CONFIG_NET_VENDOR_QUALCOMM=y # CONFIG_QCA7000_SPI is not set CONFIG_QCOM_EMAC=m # CONFIG_RMNET is not set -CONFIG_NET_VENDOR_RAMAXEL=y -CONFIG_SPNIC=m # CONFIG_NET_VENDOR_RDC is not set CONFIG_NET_VENDOR_REALTEK=y CONFIG_8139CP=m diff --git a/arch/x86/configs/openeuler_defconfig b/arch/x86/configs/openeuler_defconfig index cd9aaba18fa4..351a89b54d7f 100644 --- a/arch/x86/configs/openeuler_defconfig +++ b/arch/x86/configs/openeuler_defconfig @@ -2792,8 +2792,6 @@ CONFIG_QED_ISCSI=y CONFIG_QED_FCOE=y CONFIG_QED_OOO=y # CONFIG_NET_VENDOR_QUALCOMM is not set -CONFIG_NET_VENDOR_RAMAXEL=y -CONFIG_SPNIC=m # CONFIG_NET_VENDOR_RDC is not set CONFIG_NET_VENDOR_REALTEK=y # CONFIG_ATP is not set diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig index 7d7f6a972c28..6998a8cb3faa 100644 --- a/drivers/net/ethernet/Kconfig +++ b/drivers/net/ethernet/Kconfig @@ -160,7 +160,6 @@ source "drivers/net/ethernet/pasemi/Kconfig" source "drivers/net/ethernet/pensando/Kconfig" source "drivers/net/ethernet/qlogic/Kconfig" source "drivers/net/ethernet/qualcomm/Kconfig" -source "drivers/net/ethernet/ramaxel/Kconfig" source "drivers/net/ethernet/rdc/Kconfig" source "drivers/net/ethernet/realtek/Kconfig" source "drivers/net/ethernet/renesas/Kconfig" diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile index 5e375d5a6230..6a7d68ea63ed 100644 --- a/drivers/net/ethernet/Makefile +++ b/drivers/net/ethernet/Makefile @@ -71,7 +71,6 @@ obj-$(CONFIG_NET_VENDOR_PACKET_ENGINES) += packetengines/ obj-$(CONFIG_NET_VENDOR_PASEMI) += pasemi/ obj-$(CONFIG_NET_VENDOR_QLOGIC) += qlogic/ obj-$(CONFIG_NET_VENDOR_QUALCOMM) += qualcomm/ -obj-$(CONFIG_NET_VENDOR_RAMAXEL) += ramaxel/ obj-$(CONFIG_NET_VENDOR_REALTEK) += realtek/ obj-$(CONFIG_NET_VENDOR_RENESAS) += renesas/ obj-$(CONFIG_NET_VENDOR_RDC) += rdc/ diff --git a/drivers/net/ethernet/ramaxel/Kconfig b/drivers/net/ethernet/ramaxel/Kconfig deleted file mode 100644 index 987c7eb4880b..000000000000 --- a/drivers/net/ethernet/ramaxel/Kconfig +++ /dev/null @@ -1,20 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -# -# Ramaxel driver configuration -# - -config NET_VENDOR_RAMAXEL - bool "Ramaxel devices" - default y - help - If you have a network (Ethernet) card belonging to this class, say Y. - Note that the answer to this question doesn't directly affect the - kernel: saying N will just cause the configurator to skip all - the questions about Ramaxel cards. If you say Y, you will be asked - for your specific card in the following questions. - -if NET_VENDOR_RAMAXEL - - source "drivers/net/ethernet/ramaxel/spnic/Kconfig" - -endif # NET_VENDOR_RAMAXEL diff --git a/drivers/net/ethernet/ramaxel/Makefile b/drivers/net/ethernet/ramaxel/Makefile deleted file mode 100644 index 087f570c2257..000000000000 --- a/drivers/net/ethernet/ramaxel/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -# -# Makefile for the Ramaxel device drivers. -# - -obj-$(CONFIG_SPNIC) += spnic/ \ No newline at end of file diff --git a/drivers/net/ethernet/ramaxel/spnic/Kconfig b/drivers/net/ethernet/ramaxel/spnic/Kconfig deleted file mode 100644 index d0cb81041e8c..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/Kconfig +++ /dev/null @@ -1,14 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -# -# Ramaxel SPNIC driver configuration -# - -config SPNIC - tristate "Ramaxel PCIE Network Interface Card" - default n - depends on PCI_MSI && NUMA && PCI_IOV && (X86 || ARM64) - help - This driver supports Ramaxel PCIE Ethernet cards. - To compile this driver as part of the kernel, choose Y here. - If unsure, choose N. - The default is N. diff --git a/drivers/net/ethernet/ramaxel/spnic/Makefile b/drivers/net/ethernet/ramaxel/spnic/Makefile deleted file mode 100644 index 207e1d9c431a..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/Makefile +++ /dev/null @@ -1,39 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -obj-$(CONFIG_SPNIC) += spnic.o - -subdir-ccflags-y += -I$(srctree)/$(src)/hw - -spnic-objs := hw/sphw_common.o \ - hw/sphw_hwif.o \ - hw/sphw_eqs.o \ - hw/sphw_mbox.o \ - hw/sphw_api_cmd.o \ - hw/sphw_mgmt.o \ - hw/sphw_wq.o \ - hw/sphw_cmdq.o \ - hw/sphw_prof_adap.o \ - hw/sphw_hw_cfg.o \ - hw/sphw_hw_comm.o \ - hw/sphw_hwdev.o \ - spnic_sriov.o \ - spnic_lld.o \ - spnic_dev_mgmt.o \ - spnic_main.o \ - spnic_tx.o \ - spnic_rx.o \ - spnic_rss.o \ - spnic_ntuple.o \ - spnic_dcb.o \ - spnic_ethtool.o \ - spnic_ethtool_stats.o \ - spnic_dbg.o \ - spnic_irq.o \ - spnic_filter.o \ - spnic_netdev_ops.o \ - spnic_nic_cfg.o \ - spnic_mag_cfg.o \ - spnic_nic_cfg_vf.o \ - spnic_rss_cfg.o \ - spnic_nic_event.o \ - spnic_nic_io.o \ - spnic_nic_dbg.o diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_api_cmd.c b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_api_cmd.c deleted file mode 100644 index b459ca322515..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_api_cmd.c +++ /dev/null @@ -1,1165 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [COMM]" fmt - -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/completion.h> -#include <linux/kernel.h> -#include <linux/device.h> -#include <linux/pci.h> -#include <linux/dma-mapping.h> -#include <linux/semaphore.h> -#include <linux/jiffies.h> -#include <linux/delay.h> - -#include "sphw_crm.h" -#include "sphw_hw.h" -#include "sphw_common.h" -#include "sphw_hwdev.h" -#include "sphw_csr.h" -#include "sphw_hwif.h" -#include "sphw_api_cmd.h" - -#define API_CMD_CHAIN_CELL_SIZE_SHIFT 6U - -#define API_CMD_CELL_DESC_SIZE 8 -#define API_CMD_CELL_DATA_ADDR_SIZE 8 - -#define API_CHAIN_NUM_CELLS 32 -#define API_CHAIN_CELL_SIZE 128 -#define API_CHAIN_RSP_DATA_SIZE 128 - -#define API_CMD_CELL_WB_ADDR_SIZE 8 - -#define API_CHAIN_CELL_ALIGNMENT 8 - -#define API_CMD_TIMEOUT 10000 -#define API_CMD_STATUS_TIMEOUT 100000 - -#define API_CMD_BUF_SIZE 2048ULL - -#define API_CMD_NODE_ALIGN_SIZE 512ULL -#define API_PAYLOAD_ALIGN_SIZE 64ULL - -#define API_CHAIN_RESP_ALIGNMENT 128ULL - -#define COMPLETION_TIMEOUT_DEFAULT 1000UL -#define POLLING_COMPLETION_TIMEOUT_DEFAULT 1000U - -#define API_CMD_RESPONSE_DATA_PADDR(val) be64_to_cpu(*((u64 *)(val))) - -#define READ_API_CMD_PRIV_DATA(id, token) ((((u32)(id)) << 16) + (token)) -#define WRITE_API_CMD_PRIV_DATA(id) (((u8)(id)) << 16) - -#define MASKED_IDX(chain, idx) ((idx) & ((chain)->num_cells - 1)) - -#define SIZE_4BYTES(size) (ALIGN((u32)(size), 4U) >> 2) -#define SIZE_8BYTES(size) (ALIGN((u32)(size), 8U) >> 3) - -enum api_cmd_data_format { - SGL_DATA = 1, -}; - -enum api_cmd_type { - API_CMD_WRITE_TYPE = 0, - API_CMD_READ_TYPE = 1, -}; - -enum api_cmd_bypass { - NOT_BYPASS = 0, - BYPASS = 1, -}; - -enum api_cmd_resp_aeq { - NOT_TRIGGER = 0, - TRIGGER = 1, -}; - -enum api_cmd_chn_code { - APICHN_0 = 0, -}; - -enum api_cmd_chn_rsvd { - APICHN_VALID = 0, - APICHN_INVALID = 1, -}; - -#define API_DESC_LEN 7 - -static u8 xor_chksum_set(void *data) -{ - int idx; - u8 checksum = 0; - u8 *val = data; - - for (idx = 0; idx < API_DESC_LEN; idx++) - checksum ^= val[idx]; - - return checksum; -} - -static void set_prod_idx(struct sphw_api_cmd_chain *chain) -{ - enum sphw_api_cmd_chain_type chain_type = chain->chain_type; - struct sphw_hwif *hwif = chain->hwdev->hwif; - u32 hw_prod_idx_addr = SPHW_CSR_API_CMD_CHAIN_PI_ADDR(chain_type); - u32 prod_idx = chain->prod_idx; - - sphw_hwif_write_reg(hwif, hw_prod_idx_addr, prod_idx); -} - -static u32 get_hw_cons_idx(struct sphw_api_cmd_chain *chain) -{ - u32 addr, val; - - addr = SPHW_CSR_API_CMD_STATUS_0_ADDR(chain->chain_type); - val = sphw_hwif_read_reg(chain->hwdev->hwif, addr); - - return SPHW_API_CMD_STATUS_GET(val, CONS_IDX); -} - -static void dump_api_chain_reg(struct sphw_api_cmd_chain *chain) -{ - void *dev = chain->hwdev->dev_hdl; - u32 addr, val; - - addr = SPHW_CSR_API_CMD_STATUS_0_ADDR(chain->chain_type); - val = sphw_hwif_read_reg(chain->hwdev->hwif, addr); - - sdk_err(dev, "Chain type: 0x%x, cpld error: 0x%x, check error: 0x%x, current fsm: 0x%x\n", - chain->chain_type, SPHW_API_CMD_STATUS_GET(val, CPLD_ERR), - SPHW_API_CMD_STATUS_GET(val, CHKSUM_ERR), - SPHW_API_CMD_STATUS_GET(val, FSM)); - - sdk_err(dev, "Chain hw current ci: 0x%x\n", - SPHW_API_CMD_STATUS_GET(val, CONS_IDX)); - - addr = SPHW_CSR_API_CMD_CHAIN_PI_ADDR(chain->chain_type); - val = sphw_hwif_read_reg(chain->hwdev->hwif, addr); - sdk_err(dev, "Chain hw current pi: 0x%x\n", val); -} - -/** - * chain_busy - check if the chain is still processing last requests - * @chain: chain to check - **/ -static int chain_busy(struct sphw_api_cmd_chain *chain) -{ - void *dev = chain->hwdev->dev_hdl; - struct sphw_api_cmd_cell_ctxt *ctxt; - u64 resp_header; - - ctxt = &chain->cell_ctxt[chain->prod_idx]; - - switch (chain->chain_type) { - case SPHW_API_CMD_MULTI_READ: - case SPHW_API_CMD_POLL_READ: - resp_header = be64_to_cpu(ctxt->resp->header); - if (ctxt->status && - !SPHW_API_CMD_RESP_HEADER_VALID(resp_header)) { - sdk_err(dev, "Context(0x%x) busy!, pi: %u, resp_header: 0x%08x%08x\n", - ctxt->status, chain->prod_idx, - upper_32_bits(resp_header), - lower_32_bits(resp_header)); - dump_api_chain_reg(chain); - return -EBUSY; - } - break; - case SPHW_API_CMD_POLL_WRITE: - case SPHW_API_CMD_WRITE_TO_MGMT_CPU: - case SPHW_API_CMD_WRITE_ASYNC_TO_MGMT_CPU: - chain->cons_idx = get_hw_cons_idx(chain); - - if (chain->cons_idx == MASKED_IDX(chain, chain->prod_idx + 1)) { - sdk_err(dev, "API CMD chain %d is busy, cons_idx = %u, prod_idx = %u\n", - chain->chain_type, chain->cons_idx, - chain->prod_idx); - dump_api_chain_reg(chain); - return -EBUSY; - } - break; - default: - sdk_err(dev, "Unknown Chain type %d\n", chain->chain_type); - return -EINVAL; - } - - return 0; -} - -/** - * get_cell_data_size - get the data size of specific cell type - * @type: chain type - **/ -static u16 get_cell_data_size(enum sphw_api_cmd_chain_type type) -{ - u16 cell_data_size = 0; - - switch (type) { - case SPHW_API_CMD_POLL_READ: - cell_data_size = ALIGN(API_CMD_CELL_DESC_SIZE + - API_CMD_CELL_WB_ADDR_SIZE + - API_CMD_CELL_DATA_ADDR_SIZE, - API_CHAIN_CELL_ALIGNMENT); - break; - - case SPHW_API_CMD_WRITE_TO_MGMT_CPU: - case SPHW_API_CMD_POLL_WRITE: - case SPHW_API_CMD_WRITE_ASYNC_TO_MGMT_CPU: - cell_data_size = ALIGN(API_CMD_CELL_DESC_SIZE + - API_CMD_CELL_DATA_ADDR_SIZE, - API_CHAIN_CELL_ALIGNMENT); - break; - default: - break; - } - - return cell_data_size; -} - -/** - * prepare_cell_ctrl - prepare the ctrl of the cell for the command - * @cell_ctrl: the control of the cell to set the control into it - * @cell_len: the size of the cell - **/ -static void prepare_cell_ctrl(u64 *cell_ctrl, u16 cell_len) -{ - u64 ctrl; - u8 chksum; - - ctrl = SPHW_API_CMD_CELL_CTRL_SET(SIZE_8BYTES(cell_len), CELL_LEN) | - SPHW_API_CMD_CELL_CTRL_SET(0ULL, RD_DMA_ATTR_OFF) | - SPHW_API_CMD_CELL_CTRL_SET(0ULL, WR_DMA_ATTR_OFF); - - chksum = xor_chksum_set(&ctrl); - - ctrl |= SPHW_API_CMD_CELL_CTRL_SET(chksum, XOR_CHKSUM); - - /* The data in the HW should be in Big Endian Format */ - *cell_ctrl = cpu_to_be64(ctrl); -} - -/** - * prepare_api_cmd - prepare API CMD command - * @chain: chain for the command - * @cell: the cell of the command - * @node_id: destination node on the card that will receive the command - * @cmd: command data - * @cmd_size: the command size - **/ -static void prepare_api_cmd(struct sphw_api_cmd_chain *chain, - struct sphw_api_cmd_cell *cell, u8 node_id, - const void *cmd, u16 cmd_size) -{ - struct sphw_api_cmd_cell_ctxt *cell_ctxt; - u32 priv; - - cell_ctxt = &chain->cell_ctxt[chain->prod_idx]; - - switch (chain->chain_type) { - case SPHW_API_CMD_POLL_READ: - priv = READ_API_CMD_PRIV_DATA(chain->chain_type, - cell_ctxt->saved_prod_idx); - cell->desc = SPHW_API_CMD_DESC_SET(SGL_DATA, API_TYPE) | - SPHW_API_CMD_DESC_SET(API_CMD_READ_TYPE, RD_WR) | - SPHW_API_CMD_DESC_SET(BYPASS, MGMT_BYPASS) | - SPHW_API_CMD_DESC_SET(NOT_TRIGGER, RESP_AEQE_EN) | - SPHW_API_CMD_DESC_SET(priv, PRIV_DATA); - break; - case SPHW_API_CMD_POLL_WRITE: - priv = WRITE_API_CMD_PRIV_DATA(chain->chain_type); - cell->desc = SPHW_API_CMD_DESC_SET(SGL_DATA, API_TYPE) | - SPHW_API_CMD_DESC_SET(API_CMD_WRITE_TYPE, RD_WR) | - SPHW_API_CMD_DESC_SET(BYPASS, MGMT_BYPASS) | - SPHW_API_CMD_DESC_SET(NOT_TRIGGER, RESP_AEQE_EN) | - SPHW_API_CMD_DESC_SET(priv, PRIV_DATA); - break; - case SPHW_API_CMD_WRITE_ASYNC_TO_MGMT_CPU: - case SPHW_API_CMD_WRITE_TO_MGMT_CPU: - priv = WRITE_API_CMD_PRIV_DATA(chain->chain_type); - cell->desc = SPHW_API_CMD_DESC_SET(SGL_DATA, API_TYPE) | - SPHW_API_CMD_DESC_SET(API_CMD_WRITE_TYPE, RD_WR) | - SPHW_API_CMD_DESC_SET(NOT_BYPASS, MGMT_BYPASS) | - SPHW_API_CMD_DESC_SET(TRIGGER, RESP_AEQE_EN) | - SPHW_API_CMD_DESC_SET(priv, PRIV_DATA); - break; - default: - sdk_err(chain->hwdev->dev_hdl, "Unknown Chain type: %d\n", - chain->chain_type); - return; - } - - cell->desc |= SPHW_API_CMD_DESC_SET(APICHN_0, APICHN_CODE) | - SPHW_API_CMD_DESC_SET(APICHN_VALID, APICHN_RSVD); - - cell->desc |= SPHW_API_CMD_DESC_SET(node_id, DEST) | - SPHW_API_CMD_DESC_SET(SIZE_4BYTES(cmd_size), SIZE); - - cell->desc |= SPHW_API_CMD_DESC_SET(xor_chksum_set(&cell->desc), - XOR_CHKSUM); - - /* The data in the HW should be in Big Endian Format */ - cell->desc = cpu_to_be64(cell->desc); - - memcpy(cell_ctxt->api_cmd_vaddr, cmd, cmd_size); -} - -/** - * prepare_cell - prepare cell ctrl and cmd in the current producer cell - * @chain: chain for the command - * @node_id: destination node on the card that will receive the command - * @cmd: command data - * @cmd_size: the command size - * Return: 0 - success, negative - failure - **/ -static void prepare_cell(struct sphw_api_cmd_chain *chain, u8 node_id, - const void *cmd, u16 cmd_size) -{ - struct sphw_api_cmd_cell *curr_node; - u16 cell_size; - - curr_node = chain->curr_node; - - cell_size = get_cell_data_size(chain->chain_type); - - prepare_cell_ctrl(&curr_node->ctrl, cell_size); - prepare_api_cmd(chain, curr_node, node_id, cmd, cmd_size); -} - -static inline void cmd_chain_prod_idx_inc(struct sphw_api_cmd_chain *chain) -{ - chain->prod_idx = MASKED_IDX(chain, chain->prod_idx + 1); -} - -static void issue_api_cmd(struct sphw_api_cmd_chain *chain) -{ - set_prod_idx(chain); -} - -/** - * api_cmd_status_update - update the status of the chain - * @chain: chain to update - **/ -static void api_cmd_status_update(struct sphw_api_cmd_chain *chain) -{ - struct sphw_api_cmd_status *wb_status; - enum sphw_api_cmd_chain_type chain_type; - u64 status_header; - u32 buf_desc; - - wb_status = chain->wb_status; - - buf_desc = be32_to_cpu(wb_status->buf_desc); - if (SPHW_API_CMD_STATUS_GET(buf_desc, CHKSUM_ERR)) - return; - - status_header = be64_to_cpu(wb_status->header); - chain_type = SPHW_API_CMD_STATUS_HEADER_GET(status_header, CHAIN_ID); - if (chain_type >= SPHW_API_CMD_MAX) - return; - - if (chain_type != chain->chain_type) - return; - - chain->cons_idx = SPHW_API_CMD_STATUS_GET(buf_desc, CONS_IDX); -} - -static enum sphw_wait_return wait_for_status_poll_handler(void *priv_data) -{ - struct sphw_api_cmd_chain *chain = priv_data; - - if (!chain->hwdev->chip_present_flag) - return WAIT_PROCESS_ERR; - - api_cmd_status_update(chain); - /* SYNC API CMD cmd should start after prev cmd finished */ - if (chain->cons_idx == chain->prod_idx) - return WAIT_PROCESS_CPL; - - return WAIT_PROCESS_WAITING; -} - -/** - * wait_for_status_poll - wait for write to mgmt command to complete - * @chain: the chain of the command - * Return: 0 - success, negative - failure - **/ -static int wait_for_status_poll(struct sphw_api_cmd_chain *chain) -{ - return sphw_wait_for_timeout(chain, wait_for_status_poll_handler, - API_CMD_STATUS_TIMEOUT, 100); -} - -static void copy_resp_data(struct sphw_api_cmd_cell_ctxt *ctxt, void *ack, - u16 ack_size) -{ - struct sphw_api_cmd_resp_fmt *resp = ctxt->resp; - - memcpy(ack, &resp->resp_data, ack_size); - ctxt->status = 0; -} - -static enum sphw_wait_return check_cmd_resp_handler(void *priv_data) -{ - struct sphw_api_cmd_cell_ctxt *ctxt = priv_data; - u64 resp_header; - u8 resp_status; - - resp_header = be64_to_cpu(ctxt->resp->header); - rmb(); /* read the latest header */ - - if (SPHW_API_CMD_RESP_HEADER_VALID(resp_header)) { - resp_status = SPHW_API_CMD_RESP_HEAD_GET(resp_header, STATUS); - if (resp_status) { - pr_err("Api chain response data err, status: %u\n", - resp_status); - return WAIT_PROCESS_ERR; - } - - return WAIT_PROCESS_CPL; - } - - return WAIT_PROCESS_WAITING; -} - -/** - * prepare_cell - polling for respense data of the read api-command - * @chain: pointer to api cmd chain - * - * Return: 0 - success, negative - failure - **/ -static int wait_for_resp_polling(struct sphw_api_cmd_cell_ctxt *ctxt) -{ - return sphw_wait_for_timeout(ctxt, check_cmd_resp_handler, - POLLING_COMPLETION_TIMEOUT_DEFAULT, - USEC_PER_MSEC); -} - -/** - * wait_for_api_cmd_completion - wait for command to complete - * @chain: chain for the command - * Return: 0 - success, negative - failure - **/ -static int wait_for_api_cmd_completion(struct sphw_api_cmd_chain *chain, - struct sphw_api_cmd_cell_ctxt *ctxt, - void *ack, u16 ack_size) -{ - void *dev = chain->hwdev->dev_hdl; - int err = 0; - - switch (chain->chain_type) { - case SPHW_API_CMD_POLL_READ: - err = wait_for_resp_polling(ctxt); - if (!err) - copy_resp_data(ctxt, ack, ack_size); - else - sdk_err(dev, "API CMD poll response timeout\n"); - break; - case SPHW_API_CMD_POLL_WRITE: - case SPHW_API_CMD_WRITE_TO_MGMT_CPU: - err = wait_for_status_poll(chain); - if (err) { - sdk_err(dev, "API CMD Poll status timeout, chain type: %d\n", - chain->chain_type); - break; - } - break; - case SPHW_API_CMD_WRITE_ASYNC_TO_MGMT_CPU: - /* No need to wait */ - break; - default: - sdk_err(dev, "Unknown API CMD Chain type: %d\n", - chain->chain_type); - err = -EINVAL; - break; - } - - if (err) - dump_api_chain_reg(chain); - - return err; -} - -static inline void update_api_cmd_ctxt(struct sphw_api_cmd_chain *chain, - struct sphw_api_cmd_cell_ctxt *ctxt) -{ - ctxt->status = 1; - ctxt->saved_prod_idx = chain->prod_idx; - if (ctxt->resp) { - ctxt->resp->header = 0; - - /* make sure "header" was cleared */ - wmb(); - } -} - -/** - * api_cmd - API CMD command - * @chain: chain for the command - * @node_id: destination node on the card that will receive the command - * @cmd: command data - * @size: the command size - * Return: 0 - success, negative - failure - **/ -static int api_cmd(struct sphw_api_cmd_chain *chain, u8 node_id, - const void *cmd, u16 cmd_size, void *ack, u16 ack_size) -{ - struct sphw_api_cmd_cell_ctxt *ctxt = NULL; - - if (chain->chain_type == SPHW_API_CMD_WRITE_ASYNC_TO_MGMT_CPU) - spin_lock(&chain->async_lock); - else - down(&chain->sem); - ctxt = &chain->cell_ctxt[chain->prod_idx]; - if (chain_busy(chain)) { - if (chain->chain_type == SPHW_API_CMD_WRITE_ASYNC_TO_MGMT_CPU) - spin_unlock(&chain->async_lock); - else - up(&chain->sem); - return -EBUSY; - } - update_api_cmd_ctxt(chain, ctxt); - - prepare_cell(chain, node_id, cmd, cmd_size); - - cmd_chain_prod_idx_inc(chain); - - wmb(); /* issue the command */ - - issue_api_cmd(chain); - - /* incremented prod idx, update ctxt */ - - chain->curr_node = chain->cell_ctxt[chain->prod_idx].cell_vaddr; - if (chain->chain_type == SPHW_API_CMD_WRITE_ASYNC_TO_MGMT_CPU) - spin_unlock(&chain->async_lock); - else - up(&chain->sem); - - return wait_for_api_cmd_completion(chain, ctxt, ack, ack_size); -} - -/** - * sphw_api_cmd_write - Write API CMD command - * @chain: chain for write command - * @node_id: destination node on the card that will receive the command - * @cmd: command data - * @size: the command size - * Return: 0 - success, negative - failure - **/ -int sphw_api_cmd_write(struct sphw_api_cmd_chain *chain, u8 node_id, const void *cmd, u16 size) -{ - /* Verify the chain type */ - return api_cmd(chain, node_id, cmd, size, NULL, 0); -} - -/** - * sphw_api_cmd_read - Read API CMD command - * @chain: chain for read command - * @node_id: destination node on the card that will receive the command - * @cmd: command data - * @size: the command size - * Return: 0 - success, negative - failure - **/ -int sphw_api_cmd_read(struct sphw_api_cmd_chain *chain, u8 node_id, const void *cmd, u16 size, - void *ack, u16 ack_size) -{ - return api_cmd(chain, node_id, cmd, size, ack, ack_size); -} - -static enum sphw_wait_return check_chain_restart_handler(void *priv_data) -{ - struct sphw_api_cmd_chain *cmd_chain = priv_data; - u32 reg_addr, val; - - reg_addr = SPHW_CSR_API_CMD_CHAIN_REQ_ADDR(cmd_chain->chain_type); - val = sphw_hwif_read_reg(cmd_chain->hwdev->hwif, reg_addr); - if (!SPHW_API_CMD_CHAIN_REQ_GET(val, RESTART)) - return WAIT_PROCESS_CPL; - - return WAIT_PROCESS_WAITING; -} - -/** - * api_cmd_hw_restart - restart the chain in the HW - * @chain: the API CMD specific chain to restart - **/ -static int api_cmd_hw_restart(struct sphw_api_cmd_chain *cmd_chain) -{ - struct sphw_hwif *hwif = cmd_chain->hwdev->hwif; - u32 reg_addr, val; - - /* Read Modify Write */ - reg_addr = SPHW_CSR_API_CMD_CHAIN_REQ_ADDR(cmd_chain->chain_type); - val = sphw_hwif_read_reg(hwif, reg_addr); - - val = SPHW_API_CMD_CHAIN_REQ_CLEAR(val, RESTART); - val |= SPHW_API_CMD_CHAIN_REQ_SET(1, RESTART); - - sphw_hwif_write_reg(hwif, reg_addr, val); - - return sphw_wait_for_timeout(cmd_chain, check_chain_restart_handler, - API_CMD_TIMEOUT, USEC_PER_MSEC); -} - -/** - * api_cmd_ctrl_init - set the control register of a chain - * @chain: the API CMD specific chain to set control register for - **/ -static void api_cmd_ctrl_init(struct sphw_api_cmd_chain *chain) -{ - struct sphw_hwif *hwif = chain->hwdev->hwif; - u32 reg_addr, ctrl; - u32 size; - - /* Read Modify Write */ - reg_addr = SPHW_CSR_API_CMD_CHAIN_CTRL_ADDR(chain->chain_type); - - size = (u32)ilog2(chain->cell_size >> API_CMD_CHAIN_CELL_SIZE_SHIFT); - - ctrl = sphw_hwif_read_reg(hwif, reg_addr); - - ctrl = SPHW_API_CMD_CHAIN_CTRL_CLEAR(ctrl, AEQE_EN) & - SPHW_API_CMD_CHAIN_CTRL_CLEAR(ctrl, CELL_SIZE); - - ctrl |= SPHW_API_CMD_CHAIN_CTRL_SET(0, AEQE_EN) | - SPHW_API_CMD_CHAIN_CTRL_SET(size, CELL_SIZE); - - sphw_hwif_write_reg(hwif, reg_addr, ctrl); -} - -/** - * api_cmd_set_status_addr - set the status address of a chain in the HW - * @chain: the API CMD specific chain to set status address for - **/ -static void api_cmd_set_status_addr(struct sphw_api_cmd_chain *chain) -{ - struct sphw_hwif *hwif = chain->hwdev->hwif; - u32 addr, val; - - addr = SPHW_CSR_API_CMD_STATUS_HI_ADDR(chain->chain_type); - val = upper_32_bits(chain->wb_status_paddr); - sphw_hwif_write_reg(hwif, addr, val); - - addr = SPHW_CSR_API_CMD_STATUS_LO_ADDR(chain->chain_type); - val = lower_32_bits(chain->wb_status_paddr); - sphw_hwif_write_reg(hwif, addr, val); -} - -/** - * api_cmd_set_num_cells - set the number cells of a chain in the HW - * @chain: the API CMD specific chain to set the number of cells for - **/ -static void api_cmd_set_num_cells(struct sphw_api_cmd_chain *chain) -{ - struct sphw_hwif *hwif = chain->hwdev->hwif; - u32 addr, val; - - addr = SPHW_CSR_API_CMD_CHAIN_NUM_CELLS_ADDR(chain->chain_type); - val = chain->num_cells; - sphw_hwif_write_reg(hwif, addr, val); -} - -/** - * api_cmd_head_init - set the head cell of a chain in the HW - * @chain: the API CMD specific chain to set the head for - **/ -static void api_cmd_head_init(struct sphw_api_cmd_chain *chain) -{ - struct sphw_hwif *hwif = chain->hwdev->hwif; - u32 addr, val; - - addr = SPHW_CSR_API_CMD_CHAIN_HEAD_HI_ADDR(chain->chain_type); - val = upper_32_bits(chain->head_cell_paddr); - sphw_hwif_write_reg(hwif, addr, val); - - addr = SPHW_CSR_API_CMD_CHAIN_HEAD_LO_ADDR(chain->chain_type); - val = lower_32_bits(chain->head_cell_paddr); - sphw_hwif_write_reg(hwif, addr, val); -} - -static enum sphw_wait_return check_chain_ready_handler(void *priv_data) -{ - struct sphw_api_cmd_chain *chain = priv_data; - u32 addr, val; - u32 hw_cons_idx; - - addr = SPHW_CSR_API_CMD_STATUS_0_ADDR(chain->chain_type); - val = sphw_hwif_read_reg(chain->hwdev->hwif, addr); - hw_cons_idx = SPHW_API_CMD_STATUS_GET(val, CONS_IDX); - - /* wait for HW cons idx to be updated */ - if (hw_cons_idx == chain->cons_idx) - return WAIT_PROCESS_CPL; - return WAIT_PROCESS_WAITING; -} - -/** - * wait_for_ready_chain - wait for the chain to be ready - * @chain: the API CMD specific chain to wait for - * Return: 0 - success, negative - failure - **/ -static int wait_for_ready_chain(struct sphw_api_cmd_chain *chain) -{ - return sphw_wait_for_timeout(chain, check_chain_ready_handler, - API_CMD_TIMEOUT, USEC_PER_MSEC); -} - -/** - * api_cmd_chain_hw_clean - clean the HW - * @chain: the API CMD specific chain - **/ -static void api_cmd_chain_hw_clean(struct sphw_api_cmd_chain *chain) -{ - struct sphw_hwif *hwif = chain->hwdev->hwif; - u32 addr, ctrl; - - addr = SPHW_CSR_API_CMD_CHAIN_CTRL_ADDR(chain->chain_type); - - ctrl = sphw_hwif_read_reg(hwif, addr); - ctrl = SPHW_API_CMD_CHAIN_CTRL_CLEAR(ctrl, RESTART_EN) & - SPHW_API_CMD_CHAIN_CTRL_CLEAR(ctrl, XOR_ERR) & - SPHW_API_CMD_CHAIN_CTRL_CLEAR(ctrl, AEQE_EN) & - SPHW_API_CMD_CHAIN_CTRL_CLEAR(ctrl, XOR_CHK_EN) & - SPHW_API_CMD_CHAIN_CTRL_CLEAR(ctrl, CELL_SIZE); - - sphw_hwif_write_reg(hwif, addr, ctrl); -} - -/** - * api_cmd_chain_hw_init - initialize the chain in the HW - * @chain: the API CMD specific chain to initialize in HW - * Return: 0 - success, negative - failure - **/ -static int api_cmd_chain_hw_init(struct sphw_api_cmd_chain *chain) -{ - api_cmd_chain_hw_clean(chain); - - api_cmd_set_status_addr(chain); - - if (api_cmd_hw_restart(chain)) { - sdk_err(chain->hwdev->dev_hdl, "Failed to restart api_cmd_hw\n"); - return -EBUSY; - } - - api_cmd_ctrl_init(chain); - api_cmd_set_num_cells(chain); - api_cmd_head_init(chain); - - return wait_for_ready_chain(chain); -} - -/** - * alloc_cmd_buf - allocate a dma buffer for API CMD command - * @chain: the API CMD specific chain for the cmd - * @cell: the cell in the HW for the cmd - * @cell_idx: the index of the cell - * Return: 0 - success, negative - failure - **/ -static int alloc_cmd_buf(struct sphw_api_cmd_chain *chain, - struct sphw_api_cmd_cell *cell, u32 cell_idx) -{ - struct sphw_api_cmd_cell_ctxt *cell_ctxt; - void *dev = chain->hwdev->dev_hdl; - void *buf_vaddr; - u64 buf_paddr; - int err = 0; - - buf_vaddr = (u8 *)((u64)chain->buf_vaddr_base + - chain->buf_size_align * cell_idx); - buf_paddr = chain->buf_paddr_base + - chain->buf_size_align * cell_idx; - - cell_ctxt = &chain->cell_ctxt[cell_idx]; - - cell_ctxt->api_cmd_vaddr = buf_vaddr; - - /* set the cmd DMA address in the cell */ - switch (chain->chain_type) { - case SPHW_API_CMD_POLL_READ: - cell->read.hw_cmd_paddr = cpu_to_be64(buf_paddr); - break; - case SPHW_API_CMD_WRITE_TO_MGMT_CPU: - case SPHW_API_CMD_POLL_WRITE: - case SPHW_API_CMD_WRITE_ASYNC_TO_MGMT_CPU: - /* The data in the HW should be in Big Endian Format */ - cell->write.hw_cmd_paddr = cpu_to_be64(buf_paddr); - break; - default: - sdk_err(dev, "Unknown API CMD Chain type: %d\n", - chain->chain_type); - err = -EINVAL; - break; - } - - return err; -} - -/** - * alloc_cmd_buf - allocate a resp buffer for API CMD command - * @chain: the API CMD specific chain for the cmd - * @cell: the cell in the HW for the cmd - * @cell_idx: the index of the cell - **/ -static void alloc_resp_buf(struct sphw_api_cmd_chain *chain, - struct sphw_api_cmd_cell *cell, u32 cell_idx) -{ - struct sphw_api_cmd_cell_ctxt *cell_ctxt; - void *resp_vaddr; - u64 resp_paddr; - - resp_vaddr = (u8 *)((u64)chain->rsp_vaddr_base + - chain->rsp_size_align * cell_idx); - resp_paddr = chain->rsp_paddr_base + - chain->rsp_size_align * cell_idx; - - cell_ctxt = &chain->cell_ctxt[cell_idx]; - - cell_ctxt->resp = resp_vaddr; - cell->read.hw_wb_resp_paddr = cpu_to_be64(resp_paddr); -} - -static int sphw_alloc_api_cmd_cell_buf(struct sphw_api_cmd_chain *chain, u32 cell_idx, - struct sphw_api_cmd_cell *node) -{ - void *dev = chain->hwdev->dev_hdl; - int err; - - /* For read chain, we should allocate buffer for the response data */ - if (chain->chain_type == SPHW_API_CMD_MULTI_READ || - chain->chain_type == SPHW_API_CMD_POLL_READ) - alloc_resp_buf(chain, node, cell_idx); - - switch (chain->chain_type) { - case SPHW_API_CMD_WRITE_TO_MGMT_CPU: - case SPHW_API_CMD_POLL_WRITE: - case SPHW_API_CMD_POLL_READ: - case SPHW_API_CMD_WRITE_ASYNC_TO_MGMT_CPU: - err = alloc_cmd_buf(chain, node, cell_idx); - if (err) { - sdk_err(dev, "Failed to allocate cmd buffer\n"); - goto alloc_cmd_buf_err; - } - break; - /* For api command write and api command read, the data section - * is directly inserted in the cell, so no need to allocate. - */ - case SPHW_API_CMD_MULTI_READ: - chain->cell_ctxt[cell_idx].api_cmd_vaddr = - &node->read.hw_cmd_paddr; /* to do: who int this*/ - break; - default: - sdk_err(dev, "Unsupported API CMD chain type\n"); - err = -EINVAL; - goto alloc_cmd_buf_err; - } - - return 0; - -alloc_cmd_buf_err: - - return err; -} - -/** - * api_cmd_create_cell - create API CMD cell of specific chain - * @chain: the API CMD specific chain to create its cell - * @cell_idx: the cell index to create - * @pre_node: previous cell - * @node_vaddr: the virt addr of the cell - * Return: 0 - success, negative - failure - **/ -static int api_cmd_create_cell(struct sphw_api_cmd_chain *chain, u32 cell_idx, - struct sphw_api_cmd_cell *pre_node, - struct sphw_api_cmd_cell **node_vaddr) -{ - struct sphw_api_cmd_cell_ctxt *cell_ctxt; - struct sphw_api_cmd_cell *node; - void *cell_vaddr; - u64 cell_paddr; - int err; - - cell_vaddr = (void *)((u64)chain->cell_vaddr_base + - chain->cell_size_align * cell_idx); - cell_paddr = chain->cell_paddr_base + - chain->cell_size_align * cell_idx; - - cell_ctxt = &chain->cell_ctxt[cell_idx]; - cell_ctxt->cell_vaddr = cell_vaddr; - node = cell_ctxt->cell_vaddr; - - if (!pre_node) { - chain->head_node = cell_vaddr; - chain->head_cell_paddr = cell_paddr; - } else { - /* The data in the HW should be in Big Endian Format */ - pre_node->next_cell_paddr = cpu_to_be64(cell_paddr); - } - - /* Driver software should make sure that there is an empty API - * command cell at the end the chain - */ - node->next_cell_paddr = 0; - - err = sphw_alloc_api_cmd_cell_buf(chain, cell_idx, node); - if (err) - return err; - - *node_vaddr = node; - - return 0; -} - -/** - * api_cmd_create_cells - create API CMD cells for specific chain - * @chain: the API CMD specific chain - * Return: 0 - success, negative - failure - **/ -static int api_cmd_create_cells(struct sphw_api_cmd_chain *chain) -{ - struct sphw_api_cmd_cell *node = NULL, *pre_node = NULL; - void *dev = chain->hwdev->dev_hdl; - u32 cell_idx; - int err; - - for (cell_idx = 0; cell_idx < chain->num_cells; cell_idx++) { - err = api_cmd_create_cell(chain, cell_idx, pre_node, &node); - if (err) { - sdk_err(dev, "Failed to create API CMD cell\n"); - return err; - } - - pre_node = node; - } - - if (!node) - return -EFAULT; - - /* set the Final node to point on the start */ - node->next_cell_paddr = cpu_to_be64(chain->head_cell_paddr); - - /* set the current node to be the head */ - chain->curr_node = chain->head_node; - return 0; -} - -/** - * api_chain_init - initialize API CMD specific chain - * @chain: the API CMD specific chain to initialize - * @attr: attributes to set in the chain - * Return: 0 - success, negative - failure - **/ -static int api_chain_init(struct sphw_api_cmd_chain *chain, - struct sphw_api_cmd_chain_attr *attr) -{ - void *dev = chain->hwdev->dev_hdl; - size_t cell_ctxt_size; - size_t cells_buf_size; - int err; - - chain->chain_type = attr->chain_type; - chain->num_cells = attr->num_cells; - chain->cell_size = attr->cell_size; - chain->rsp_size = attr->rsp_size; - - chain->prod_idx = 0; - chain->cons_idx = 0; - - if (chain->chain_type == SPHW_API_CMD_WRITE_ASYNC_TO_MGMT_CPU) - spin_lock_init(&chain->async_lock); - else - sema_init(&chain->sem, 1); - - cell_ctxt_size = chain->num_cells * sizeof(*chain->cell_ctxt); - if (!cell_ctxt_size) { - sdk_err(dev, "Api chain cell size cannot be zero\n"); - return -EINVAL; - } - - chain->cell_ctxt = kzalloc(cell_ctxt_size, GFP_KERNEL); - if (!chain->cell_ctxt) { - sdk_err(dev, "Failed to allocate cell contexts for a chain\n"); - return -ENOMEM; - } - - chain->wb_status = dma_alloc_coherent(dev, sizeof(*chain->wb_status), - &chain->wb_status_paddr, GFP_KERNEL); - if (!chain->wb_status) { - sdk_err(dev, "Failed to allocate DMA wb status\n"); - err = -ENOMEM; - goto alloc_wb_status_err; - } - - chain->cell_size_align = ALIGN((u64)chain->cell_size, - API_CMD_NODE_ALIGN_SIZE); - chain->rsp_size_align = ALIGN((u64)chain->rsp_size, - API_CHAIN_RESP_ALIGNMENT); - chain->buf_size_align = ALIGN(API_CMD_BUF_SIZE, API_PAYLOAD_ALIGN_SIZE); - - cells_buf_size = (chain->cell_size_align + chain->rsp_size_align + - chain->buf_size_align) * chain->num_cells; - - err = sphw_dma_alloc_coherent_align(dev, cells_buf_size, API_CMD_NODE_ALIGN_SIZE, - GFP_KERNEL, &chain->cells_addr); - if (err) { - sdk_err(dev, "Failed to allocate API CMD cells buffer\n"); - goto alloc_cells_buf_err; - } - - chain->cell_vaddr_base = chain->cells_addr.align_vaddr; - chain->cell_paddr_base = chain->cells_addr.align_paddr; - - chain->rsp_vaddr_base = (u8 *)((u64)chain->cell_vaddr_base + - chain->cell_size_align * chain->num_cells); - chain->rsp_paddr_base = chain->cell_paddr_base + - chain->cell_size_align * chain->num_cells; - - chain->buf_vaddr_base = (u8 *)((u64)chain->rsp_vaddr_base + - chain->rsp_size_align * chain->num_cells); - chain->buf_paddr_base = chain->rsp_paddr_base + - chain->rsp_size_align * chain->num_cells; - - return 0; - -alloc_cells_buf_err: - dma_free_coherent(dev, sizeof(*chain->wb_status), - chain->wb_status, chain->wb_status_paddr); - -alloc_wb_status_err: - kfree(chain->cell_ctxt); - - return err; -} - -/** - * api_chain_free - free API CMD specific chain - * @chain: the API CMD specific chain to free - **/ -static void api_chain_free(struct sphw_api_cmd_chain *chain) -{ - void *dev = chain->hwdev->dev_hdl; - - sphw_dma_free_coherent_align(dev, &chain->cells_addr); - - dma_free_coherent(dev, sizeof(*chain->wb_status), - chain->wb_status, chain->wb_status_paddr); - kfree(chain->cell_ctxt); -} - -/** - * api_cmd_create_chain - create API CMD specific chain - * @chain: the API CMD specific chain to create - * @attr: attributes to set in the chain - * Return: 0 - success, negative - failure - **/ -static int api_cmd_create_chain(struct sphw_api_cmd_chain **cmd_chain, - struct sphw_api_cmd_chain_attr *attr) -{ - struct sphw_hwdev *hwdev = attr->hwdev; - struct sphw_api_cmd_chain *chain = NULL; - int err; - - if (attr->num_cells & (attr->num_cells - 1)) { - sdk_err(hwdev->dev_hdl, "Invalid number of cells, must be power of 2\n"); - return -EINVAL; - } - - chain = kzalloc(sizeof(*chain), GFP_KERNEL); - if (!chain) - return -ENOMEM; - - chain->hwdev = hwdev; - - err = api_chain_init(chain, attr); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to initialize chain\n"); - goto chain_init_err; - } - - err = api_cmd_create_cells(chain); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to create cells for API CMD chain\n"); - goto create_cells_err; - } - - err = api_cmd_chain_hw_init(chain); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to initialize chain HW\n"); - goto chain_hw_init_err; - } - - *cmd_chain = chain; - return 0; - -chain_hw_init_err: -create_cells_err: - api_chain_free(chain); - -chain_init_err: - kfree(chain); - return err; -} - -/** - * api_cmd_destroy_chain - destroy API CMD specific chain - * @chain: the API CMD specific chain to destroy - **/ -static void api_cmd_destroy_chain(struct sphw_api_cmd_chain *chain) -{ - api_chain_free(chain); - kfree(chain); -} - -/** - * sphw_api_cmd_init - Initialize all the API CMD chains - * @hwif: the hardware interface of a pci function device - * @chain: the API CMD chains that will be initialized - * Return: 0 - success, negative - failure - **/ -int sphw_api_cmd_init(struct sphw_hwdev *hwdev, struct sphw_api_cmd_chain **chain) -{ - void *dev = hwdev->dev_hdl; - struct sphw_api_cmd_chain_attr attr; - enum sphw_api_cmd_chain_type chain_type, i; - int err; - - attr.hwdev = hwdev; - attr.num_cells = API_CHAIN_NUM_CELLS; - attr.cell_size = API_CHAIN_CELL_SIZE; - attr.rsp_size = API_CHAIN_RSP_DATA_SIZE; - - chain_type = SPHW_API_CMD_WRITE_TO_MGMT_CPU; - for (; chain_type < SPHW_API_CMD_MAX; chain_type++) { - attr.chain_type = chain_type; - - err = api_cmd_create_chain(&chain[chain_type], &attr); - if (err) { - sdk_err(dev, "Failed to create chain %d\n", chain_type); - goto create_chain_err; - } - } - - return 0; - -create_chain_err: - i = SPHW_API_CMD_WRITE_TO_MGMT_CPU; - for (; i < chain_type; i++) - api_cmd_destroy_chain(chain[i]); - - return err; -} - -/** - * sphw_api_cmd_free - free the API CMD chains - * @chain: the API CMD chains that will be freed - **/ -void sphw_api_cmd_free(struct sphw_api_cmd_chain **chain) -{ - enum sphw_api_cmd_chain_type chain_type; - - chain_type = SPHW_API_CMD_WRITE_TO_MGMT_CPU; - - for (; chain_type < SPHW_API_CMD_MAX; chain_type++) - api_cmd_destroy_chain(chain[chain_type]); -} diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_api_cmd.h b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_api_cmd.h deleted file mode 100644 index 14a6c0b50e17..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_api_cmd.h +++ /dev/null @@ -1,277 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPHW_API_CMD_H -#define SPHW_API_CMD_H - -#include "sphw_hwif.h" - -/*api_cmd_cell.ctrl structure*/ -#define SPHW_API_CMD_CELL_CTRL_CELL_LEN_SHIFT 0 -#define SPHW_API_CMD_CELL_CTRL_RD_DMA_ATTR_OFF_SHIFT 16 -#define SPHW_API_CMD_CELL_CTRL_WR_DMA_ATTR_OFF_SHIFT 24 -#define SPHW_API_CMD_CELL_CTRL_XOR_CHKSUM_SHIFT 56 - -#define SPHW_API_CMD_CELL_CTRL_CELL_LEN_MASK 0x3FU -#define SPHW_API_CMD_CELL_CTRL_RD_DMA_ATTR_OFF_MASK 0x3FU -#define SPHW_API_CMD_CELL_CTRL_WR_DMA_ATTR_OFF_MASK 0x3FU -#define SPHW_API_CMD_CELL_CTRL_XOR_CHKSUM_MASK 0xFFU - -#define SPHW_API_CMD_CELL_CTRL_SET(val, member) \ - ((((u64)(val)) & SPHW_API_CMD_CELL_CTRL_##member##_MASK) << \ - SPHW_API_CMD_CELL_CTRL_##member##_SHIFT) - -/*api_cmd_cell.desc structure*/ -#define SPHW_API_CMD_DESC_API_TYPE_SHIFT 0 -#define SPHW_API_CMD_DESC_RD_WR_SHIFT 1 -#define SPHW_API_CMD_DESC_MGMT_BYPASS_SHIFT 2 -#define SPHW_API_CMD_DESC_RESP_AEQE_EN_SHIFT 3 -#define SPHW_API_CMD_DESC_APICHN_RSVD_SHIFT 4 -#define SPHW_API_CMD_DESC_APICHN_CODE_SHIFT 6 -#define SPHW_API_CMD_DESC_PRIV_DATA_SHIFT 8 -#define SPHW_API_CMD_DESC_DEST_SHIFT 32 -#define SPHW_API_CMD_DESC_SIZE_SHIFT 40 -#define SPHW_API_CMD_DESC_XOR_CHKSUM_SHIFT 56 - -#define SPHW_API_CMD_DESC_API_TYPE_MASK 0x1U -#define SPHW_API_CMD_DESC_RD_WR_MASK 0x1U -#define SPHW_API_CMD_DESC_MGMT_BYPASS_MASK 0x1U -#define SPHW_API_CMD_DESC_RESP_AEQE_EN_MASK 0x1U -#define SPHW_API_CMD_DESC_APICHN_RSVD_MASK 0x3U -#define SPHW_API_CMD_DESC_APICHN_CODE_MASK 0x3U -#define SPHW_API_CMD_DESC_PRIV_DATA_MASK 0xFFFFFFU -#define SPHW_API_CMD_DESC_DEST_MASK 0x1FU -#define SPHW_API_CMD_DESC_SIZE_MASK 0x7FFU -#define SPHW_API_CMD_DESC_XOR_CHKSUM_MASK 0xFFU - -#define SPHW_API_CMD_DESC_SET(val, member) \ - ((((u64)(val)) & SPHW_API_CMD_DESC_##member##_MASK) << \ - SPHW_API_CMD_DESC_##member##_SHIFT) - -/*api_cmd_status header*/ -#define SPHW_API_CMD_STATUS_HEADER_VALID_SHIFT 0 -#define SPHW_API_CMD_STATUS_HEADER_CHAIN_ID_SHIFT 16 - -#define SPHW_API_CMD_STATUS_HEADER_VALID_MASK 0xFFU -#define SPHW_API_CMD_STATUS_HEADER_CHAIN_ID_MASK 0xFFU - -#define SPHW_API_CMD_STATUS_HEADER_GET(val, member) \ - (((val) >> SPHW_API_CMD_STATUS_HEADER_##member##_SHIFT) & \ - SPHW_API_CMD_STATUS_HEADER_##member##_MASK) - -/*API_CHAIN_REQ CSR: 0x0020+api_idx*0x080*/ -#define SPHW_API_CMD_CHAIN_REQ_RESTART_SHIFT 1 -#define SPHW_API_CMD_CHAIN_REQ_WB_TRIGGER_SHIFT 2 - -#define SPHW_API_CMD_CHAIN_REQ_RESTART_MASK 0x1U -#define SPHW_API_CMD_CHAIN_REQ_WB_TRIGGER_MASK 0x1U - -#define SPHW_API_CMD_CHAIN_REQ_SET(val, member) \ - (((val) & SPHW_API_CMD_CHAIN_REQ_##member##_MASK) << \ - SPHW_API_CMD_CHAIN_REQ_##member##_SHIFT) - -#define SPHW_API_CMD_CHAIN_REQ_GET(val, member) \ - (((val) >> SPHW_API_CMD_CHAIN_REQ_##member##_SHIFT) & \ - SPHW_API_CMD_CHAIN_REQ_##member##_MASK) - -#define SPHW_API_CMD_CHAIN_REQ_CLEAR(val, member) \ - ((val) & (~(SPHW_API_CMD_CHAIN_REQ_##member##_MASK \ - << SPHW_API_CMD_CHAIN_REQ_##member##_SHIFT))) - -/*API_CHAIN_CTL CSR: 0x0014+api_idx*0x080*/ -#define SPHW_API_CMD_CHAIN_CTRL_RESTART_EN_SHIFT 1 -#define SPHW_API_CMD_CHAIN_CTRL_XOR_ERR_SHIFT 2 -#define SPHW_API_CMD_CHAIN_CTRL_AEQE_EN_SHIFT 4 -#define SPHW_API_CMD_CHAIN_CTRL_AEQ_ID_SHIFT 8 -#define SPHW_API_CMD_CHAIN_CTRL_XOR_CHK_EN_SHIFT 28 -#define SPHW_API_CMD_CHAIN_CTRL_CELL_SIZE_SHIFT 30 - -#define SPHW_API_CMD_CHAIN_CTRL_RESTART_EN_MASK 0x1U -#define SPHW_API_CMD_CHAIN_CTRL_XOR_ERR_MASK 0x1U -#define SPHW_API_CMD_CHAIN_CTRL_AEQE_EN_MASK 0x1U -#define SPHW_API_CMD_CHAIN_CTRL_AEQ_ID_MASK 0x3U -#define SPHW_API_CMD_CHAIN_CTRL_XOR_CHK_EN_MASK 0x3U -#define SPHW_API_CMD_CHAIN_CTRL_CELL_SIZE_MASK 0x3U - -#define SPHW_API_CMD_CHAIN_CTRL_SET(val, member) \ - (((val) & SPHW_API_CMD_CHAIN_CTRL_##member##_MASK) << \ - SPHW_API_CMD_CHAIN_CTRL_##member##_SHIFT) - -#define SPHW_API_CMD_CHAIN_CTRL_CLEAR(val, member) \ - ((val) & (~(SPHW_API_CMD_CHAIN_CTRL_##member##_MASK \ - << SPHW_API_CMD_CHAIN_CTRL_##member##_SHIFT))) - -/*api_cmd rsp header*/ -#define SPHW_API_CMD_RESP_HEAD_VALID_SHIFT 0 -#define SPHW_API_CMD_RESP_HEAD_STATUS_SHIFT 8 -#define SPHW_API_CMD_RESP_HEAD_CHAIN_ID_SHIFT 16 -#define SPHW_API_CMD_RESP_HEAD_RESP_LEN_SHIFT 24 -#define SPHW_API_CMD_RESP_HEAD_DRIVER_PRIV_SHIFT 40 - -#define SPHW_API_CMD_RESP_HEAD_VALID_MASK 0xFF -#define SPHW_API_CMD_RESP_HEAD_STATUS_MASK 0xFFU -#define SPHW_API_CMD_RESP_HEAD_CHAIN_ID_MASK 0xFFU -#define SPHW_API_CMD_RESP_HEAD_RESP_LEN_MASK 0x1FFU -#define SPHW_API_CMD_RESP_HEAD_DRIVER_PRIV_MASK 0xFFFFFFU - -#define SPHW_API_CMD_RESP_HEAD_VALID_CODE 0xFF - -#define SPHW_API_CMD_RESP_HEADER_VALID(val) \ - (((val) & SPHW_API_CMD_RESP_HEAD_VALID_MASK) == \ - SPHW_API_CMD_RESP_HEAD_VALID_CODE) - -#define SPHW_API_CMD_RESP_HEAD_GET(val, member) \ - (((val) >> SPHW_API_CMD_RESP_HEAD_##member##_SHIFT) & \ - SPHW_API_CMD_RESP_HEAD_##member##_MASK) - -#define SPHW_API_CMD_RESP_HEAD_CHAIN_ID(val) \ - (((val) >> SPHW_API_CMD_RESP_HEAD_CHAIN_ID_SHIFT) & \ - SPHW_API_CMD_RESP_HEAD_CHAIN_ID_MASK) - -#define SPHW_API_CMD_RESP_HEAD_DRIVER_PRIV(val) \ - ((u16)(((val) >> SPHW_API_CMD_RESP_HEAD_DRIVER_PRIV_SHIFT) & \ - SPHW_API_CMD_RESP_HEAD_DRIVER_PRIV_MASK)) -/*API_STATUS_0 CSR: 0x0030+api_idx*0x080*/ -#define SPHW_API_CMD_STATUS_CONS_IDX_MASK 0xFFFFFFU -#define SPHW_API_CMD_STATUS_CONS_IDX_SHIFT 0 - -#define SPHW_API_CMD_STATUS_FSM_MASK 0xFU -#define SPHW_API_CMD_STATUS_FSM_SHIFT 24 - -#define SPHW_API_CMD_STATUS_CHKSUM_ERR_MASK 0x3U -#define SPHW_API_CMD_STATUS_CHKSUM_ERR_SHIFT 28 - -#define SPHW_API_CMD_STATUS_CPLD_ERR_MASK 0x1U -#define SPHW_API_CMD_STATUS_CPLD_ERR_SHIFT 30 - -#define SPHW_API_CMD_STATUS_CONS_IDX(val) \ - ((val) & SPHW_API_CMD_STATUS_CONS_IDX_MASK) - -#define SPHW_API_CMD_STATUS_CHKSUM_ERR(val) \ - (((val) >> SPHW_API_CMD_STATUS_CHKSUM_ERR_SHIFT) & \ - SPHW_API_CMD_STATUS_CHKSUM_ERR_MASK) - -#define SPHW_API_CMD_STATUS_GET(val, member) \ - (((val) >> SPHW_API_CMD_STATUS_##member##_SHIFT) & \ - SPHW_API_CMD_STATUS_##member##_MASK) - -enum sphw_api_cmd_chain_type { - /* write to mgmt cpu command with completion */ - SPHW_API_CMD_WRITE_TO_MGMT_CPU = 2, - /* multi read command with completion notification - not used */ - SPHW_API_CMD_MULTI_READ = 3, - /* write command without completion notification */ - SPHW_API_CMD_POLL_WRITE = 4, - /* read command without completion notification */ - SPHW_API_CMD_POLL_READ = 5, - /* read from mgmt cpu command with completion */ - SPHW_API_CMD_WRITE_ASYNC_TO_MGMT_CPU = 6, - SPHW_API_CMD_MAX, -}; - -struct sphw_api_cmd_status { - u64 header; - u32 buf_desc; - u32 cell_addr_hi; - u32 cell_addr_lo; - u32 rsvd0; - u64 rsvd1; -}; - -/* HW struct */ -struct sphw_api_cmd_cell { - u64 ctrl; - - /* address is 64 bit in HW struct */ - u64 next_cell_paddr; - - u64 desc; - - /* HW struct */ - union { - struct { - u64 hw_cmd_paddr; - } write; - - struct { - u64 hw_wb_resp_paddr; - u64 hw_cmd_paddr; - } read; - }; -}; - -struct sphw_api_cmd_resp_fmt { - u64 header; - u64 resp_data; -}; - -struct sphw_api_cmd_cell_ctxt { - struct sphw_api_cmd_cell *cell_vaddr; - - void *api_cmd_vaddr; - - struct sphw_api_cmd_resp_fmt *resp; - - struct completion done; - int status; - - u32 saved_prod_idx; -}; - -struct sphw_api_cmd_chain_attr { - struct sphw_hwdev *hwdev; - enum sphw_api_cmd_chain_type chain_type; - - u32 num_cells; - u16 rsp_size; - u16 cell_size; -}; - -struct sphw_api_cmd_chain { - struct sphw_hwdev *hwdev; - enum sphw_api_cmd_chain_type chain_type; - - u32 num_cells; - u16 cell_size; - u16 rsp_size; - - /* HW members is 24 bit format */ - u32 prod_idx; - u32 cons_idx; - - struct semaphore sem; - /* Async cmd can not be scheduling */ - spinlock_t async_lock; - - dma_addr_t wb_status_paddr; - struct sphw_api_cmd_status *wb_status; - - dma_addr_t head_cell_paddr; - struct sphw_api_cmd_cell *head_node; - - struct sphw_api_cmd_cell_ctxt *cell_ctxt; - struct sphw_api_cmd_cell *curr_node; - - struct sphw_dma_addr_align cells_addr; - - u8 *cell_vaddr_base; - u64 cell_paddr_base; - u8 *rsp_vaddr_base; - u64 rsp_paddr_base; - u8 *buf_vaddr_base; - u64 buf_paddr_base; - u64 cell_size_align; - u64 rsp_size_align; - u64 buf_size_align; -}; - -int sphw_api_cmd_write(struct sphw_api_cmd_chain *chain, u8 node_id, const void *cmd, u16 size); - -int sphw_api_cmd_read(struct sphw_api_cmd_chain *chain, u8 node_id, const void *cmd, u16 size, - void *ack, u16 ack_size); - -int sphw_api_cmd_init(struct sphw_hwdev *hwdev, struct sphw_api_cmd_chain **chain); - -void sphw_api_cmd_free(struct sphw_api_cmd_chain **chain); - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_cfg_cmd.h b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_cfg_cmd.h deleted file mode 100644 index 63b89e71c552..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_cfg_cmd.h +++ /dev/null @@ -1,127 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPHW_CFG_CMD_H -#define SPHW_CFG_CMD_H - -#include "sphw_mgmt_msg_base.h" - -enum cfg_cmd { - CFG_CMD_GET_DEV_CAP = 0, -}; - -struct cfg_cmd_dev_cap { - struct mgmt_msg_head head; - - u16 func_id; - u16 rsvd1; - - /* Public resources */ - u8 host_id; - u8 ep_id; - u8 er_id; - u8 port_id; - - u16 host_total_func; - u8 host_pf_num; - u8 pf_id_start; - u16 host_vf_num; - u16 vf_id_start; - u8 host_oq_id_mask_val; - u8 rsvd_host[3]; - - u16 svc_cap_en; - u16 max_vf; - u8 flexq_en; - u8 valid_cos_bitmap; - /* Reserved for func_valid_cos_bitmap */ - u16 rsvd_func1; - u32 rsvd_func2; - - u8 sf_svc_attr; - u8 func_sf_en; - u8 lb_mode; - u8 smf_pg; - - u32 max_conn_num; - u16 max_stick2cache_num; - u16 max_bfilter_start_addr; - u16 bfilter_len; - u16 hash_bucket_num; - - /* shared resource */ - u8 host_sf_en; - u8 rsvd2_sr[3]; - u32 host_pctx_num; - u32 host_ccxt_num; - u32 host_scq_num; - u32 host_srq_num; - u32 host_mpt_num; - - /* l2nic */ - u16 nic_max_sq_id; - u16 nic_max_rq_id; - u32 rsvd_nic[3]; - - /* RoCE */ - u32 roce_max_qp; - u32 roce_max_cq; - u32 roce_max_srq; - u32 roce_max_mpt; - u32 roce_max_drc_qp; - - u32 roce_cmtt_cl_start; - u32 roce_cmtt_cl_end; - u32 roce_cmtt_cl_size; - - u32 roce_dmtt_cl_start; - u32 roce_dmtt_cl_end; - u32 roce_dmtt_cl_size; - - u32 roce_wqe_cl_start; - u32 roce_wqe_cl_end; - u32 roce_wqe_cl_size; - u8 roce_srq_container_mode; - u8 rsvd_roce1[3]; - u32 rsvd_roce2[5]; - - /* IPsec */ - u32 ipsec_max_sactx; - u32 rsvd_ipsec[3]; - - /* OVS */ - u32 ovs_max_qpc; - u16 fake_vf_start_id; - u8 fake_vf_num; - u8 rsvd_ovs1; - u32 rsvd_ovs2[2]; - - /* ToE */ - u32 toe_max_pctx; - u32 toe_max_cq; - u16 toe_max_srq; - u16 toe_srq_id_start; - u16 toe_max_mpt; - u16 toe_max_cctxt; - u32 rsvd_toe[2]; - - /* FC */ - u32 fc_max_pctx; - u32 fc_max_scq; - u32 fc_max_srq; - - u32 fc_max_cctx; - u32 fc_cctx_id_start; - - u8 fc_vp_id_start; - u8 fc_vp_id_end; - u8 rsvd_fc1[2]; - u32 rsvd_fc2[5]; - - /* VBS */ - u32 rsvd_vbs[4]; - - u32 rsvd_glb[11]; -}; - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_cmdq.c b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_cmdq.c deleted file mode 100644 index 9ebff6f8ac97..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_cmdq.c +++ /dev/null @@ -1,1573 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [COMM]" fmt - -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/device.h> -#include <linux/pci.h> -#include <linux/errno.h> -#include <linux/completion.h> -#include <linux/interrupt.h> -#include <linux/io.h> -#include <linux/spinlock.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/delay.h> - -#include "sphw_crm.h" -#include "sphw_hw.h" -#include "sphw_hwdev.h" -#include "sphw_eqs.h" -#include "sphw_common.h" -#include "sphw_wq.h" -#include "sphw_hw_comm.h" -#include "sphw_cmdq.h" - -#define SPHW_CMDQ_BUF_SIZE 2048U -#define SPHW_CMDQ_BUF_HW_RSVD 8 -#define SPHW_CMDQ_MAX_DATA_SIZE \ - (SPHW_CMDQ_BUF_SIZE - SPHW_CMDQ_BUF_HW_RSVD) - -#define CMDQ_CMD_TIMEOUT 5000 /* millisecond */ - -#define UPPER_8_BITS(data) (((data) >> 8) & 0xFF) -#define LOWER_8_BITS(data) ((data) & 0xFF) - -#define CMDQ_DB_INFO_HI_PROD_IDX_SHIFT 0 -#define CMDQ_DB_INFO_HI_PROD_IDX_MASK 0xFFU -#define CMDQ_DB_INFO_SET(val, member) \ - ((((u32)(val)) & CMDQ_DB_INFO_##member##_MASK) << \ - CMDQ_DB_INFO_##member##_SHIFT) - -#define CMDQ_DB_HEAD_QUEUE_TYPE_SHIFT 23 -#define CMDQ_DB_HEAD_CMDQ_TYPE_SHIFT 24 -#define CMDQ_DB_HEAD_SRC_TYPE_SHIFT 27 -#define CMDQ_DB_HEAD_QUEUE_TYPE_MASK 0x1U -#define CMDQ_DB_HEAD_CMDQ_TYPE_MASK 0x7U -#define CMDQ_DB_HEAD_SRC_TYPE_MASK 0x1FU -#define CMDQ_DB_HEAD_SET(val, member) \ - ((((u32)(val)) & CMDQ_DB_HEAD_##member##_MASK) << \ - CMDQ_DB_HEAD_##member##_SHIFT) - -#define CMDQ_CTRL_PI_SHIFT 0 -#define CMDQ_CTRL_CMD_SHIFT 16 -#define CMDQ_CTRL_MOD_SHIFT 24 -#define CMDQ_CTRL_ACK_TYPE_SHIFT 29 -#define CMDQ_CTRL_HW_BUSY_BIT_SHIFT 31 - -#define CMDQ_CTRL_PI_MASK 0xFFFFU -#define CMDQ_CTRL_CMD_MASK 0xFFU -#define CMDQ_CTRL_MOD_MASK 0x1FU -#define CMDQ_CTRL_ACK_TYPE_MASK 0x3U -#define CMDQ_CTRL_HW_BUSY_BIT_MASK 0x1U - -#define CMDQ_CTRL_SET(val, member) \ - ((((u32)(val)) & CMDQ_CTRL_##member##_MASK) << \ - CMDQ_CTRL_##member##_SHIFT) - -#define CMDQ_CTRL_GET(val, member) \ - (((val) >> CMDQ_CTRL_##member##_SHIFT) & \ - CMDQ_CTRL_##member##_MASK) - -#define CMDQ_WQE_HEADER_BUFDESC_LEN_SHIFT 0 -#define CMDQ_WQE_HEADER_COMPLETE_FMT_SHIFT 15 -#define CMDQ_WQE_HEADER_DATA_FMT_SHIFT 22 -#define CMDQ_WQE_HEADER_COMPLETE_REQ_SHIFT 23 -#define CMDQ_WQE_HEADER_COMPLETE_SECT_LEN_SHIFT 27 -#define CMDQ_WQE_HEADER_CTRL_LEN_SHIFT 29 -#define CMDQ_WQE_HEADER_HW_BUSY_BIT_SHIFT 31 - -#define CMDQ_WQE_HEADER_BUFDESC_LEN_MASK 0xFFU -#define CMDQ_WQE_HEADER_COMPLETE_FMT_MASK 0x1U -#define CMDQ_WQE_HEADER_DATA_FMT_MASK 0x1U -#define CMDQ_WQE_HEADER_COMPLETE_REQ_MASK 0x1U -#define CMDQ_WQE_HEADER_COMPLETE_SECT_LEN_MASK 0x3U -#define CMDQ_WQE_HEADER_CTRL_LEN_MASK 0x3U -#define CMDQ_WQE_HEADER_HW_BUSY_BIT_MASK 0x1U - -#define CMDQ_WQE_HEADER_SET(val, member) \ - ((((u32)(val)) & CMDQ_WQE_HEADER_##member##_MASK) << \ - CMDQ_WQE_HEADER_##member##_SHIFT) - -#define CMDQ_WQE_HEADER_GET(val, member) \ - (((val) >> CMDQ_WQE_HEADER_##member##_SHIFT) & \ - CMDQ_WQE_HEADER_##member##_MASK) - -#define CMDQ_CTXT_CURR_WQE_PAGE_PFN_SHIFT 0 -#define CMDQ_CTXT_EQ_ID_SHIFT 53 -#define CMDQ_CTXT_CEQ_ARM_SHIFT 61 -#define CMDQ_CTXT_CEQ_EN_SHIFT 62 -#define CMDQ_CTXT_HW_BUSY_BIT_SHIFT 63 - -#define CMDQ_CTXT_CURR_WQE_PAGE_PFN_MASK 0xFFFFFFFFFFFFF -#define CMDQ_CTXT_EQ_ID_MASK 0xFF -#define CMDQ_CTXT_CEQ_ARM_MASK 0x1 -#define CMDQ_CTXT_CEQ_EN_MASK 0x1 -#define CMDQ_CTXT_HW_BUSY_BIT_MASK 0x1 - -#define CMDQ_CTXT_PAGE_INFO_SET(val, member) \ - (((u64)(val) & CMDQ_CTXT_##member##_MASK) << \ - CMDQ_CTXT_##member##_SHIFT) - -#define CMDQ_CTXT_PAGE_INFO_GET(val, member) \ - (((u64)(val) >> CMDQ_CTXT_##member##_SHIFT) & \ - CMDQ_CTXT_##member##_MASK) - -#define CMDQ_CTXT_WQ_BLOCK_PFN_SHIFT 0 -#define CMDQ_CTXT_CI_SHIFT 52 - -#define CMDQ_CTXT_WQ_BLOCK_PFN_MASK 0xFFFFFFFFFFFFF -#define CMDQ_CTXT_CI_MASK 0xFFF - -#define CMDQ_CTXT_BLOCK_INFO_SET(val, member) \ - (((u64)(val) & CMDQ_CTXT_##member##_MASK) << \ - CMDQ_CTXT_##member##_SHIFT) - -#define CMDQ_CTXT_BLOCK_INFO_GET(val, member) \ - (((u64)(val) >> CMDQ_CTXT_##member##_SHIFT) & \ - CMDQ_CTXT_##member##_MASK) - -#define SAVED_DATA_ARM_SHIFT 31 - -#define SAVED_DATA_ARM_MASK 0x1U - -#define SAVED_DATA_SET(val, member) \ - (((val) & SAVED_DATA_##member##_MASK) << \ - SAVED_DATA_##member##_SHIFT) - -#define SAVED_DATA_CLEAR(val, member) \ - ((val) & (~(SAVED_DATA_##member##_MASK << \ - SAVED_DATA_##member##_SHIFT))) - -#define WQE_ERRCODE_VAL_SHIFT 0 - -#define WQE_ERRCODE_VAL_MASK 0x7FFFFFFF - -#define WQE_ERRCODE_GET(val, member) \ - (((val) >> WQE_ERRCODE_##member##_SHIFT) & \ - WQE_ERRCODE_##member##_MASK) - -#define CEQE_CMDQ_TYPE_SHIFT 0 - -#define CEQE_CMDQ_TYPE_MASK 0x7 - -#define CEQE_CMDQ_GET(val, member) \ - (((val) >> CEQE_CMDQ_##member##_SHIFT) & \ - CEQE_CMDQ_##member##_MASK) - -#define WQE_COMPLETED(ctrl_info) CMDQ_CTRL_GET(ctrl_info, HW_BUSY_BIT) - -#define WQE_HEADER(wqe) ((struct sphw_cmdq_header *)(wqe)) - -#define CMDQ_DB_PI_OFF(pi) (((u16)LOWER_8_BITS(pi)) << 3) - -#define CMDQ_DB_ADDR(db_base, pi) \ - (((u8 *)(db_base)) + CMDQ_DB_PI_OFF(pi)) - -#define CMDQ_PFN_SHIFT 12 -#define CMDQ_PFN(addr) ((addr) >> CMDQ_PFN_SHIFT) - -#define FIRST_DATA_TO_WRITE_LAST sizeof(u64) - -#define WQE_LCMD_SIZE 64 -#define WQE_SCMD_SIZE 64 - -#define COMPLETE_LEN 3 - -#define CMDQ_WQEBB_SIZE 64 -#define CMDQ_WQE_SIZE 64 - -#define cmdq_to_cmdqs(cmdq) container_of((cmdq) - (cmdq)->cmdq_type, \ - struct sphw_cmdqs, cmdq[0]) - -#define CMDQ_SEND_CMPT_CODE 10 -#define CMDQ_COMPLETE_CMPT_CODE 11 -#define CMDQ_FORCE_STOP_CMPT_CODE 12 - -enum cmdq_scmd_type { - CMDQ_SET_ARM_CMD = 2, -}; - -enum cmdq_wqe_type { - WQE_LCMD_TYPE, - WQE_SCMD_TYPE, -}; - -enum ctrl_sect_len { - CTRL_SECT_LEN = 1, - CTRL_DIRECT_SECT_LEN = 2, -}; - -enum bufdesc_len { - BUFDESC_LCMD_LEN = 2, - BUFDESC_SCMD_LEN = 3, -}; - -enum data_format { - DATA_SGE, - DATA_DIRECT, -}; - -enum completion_format { - COMPLETE_DIRECT, - COMPLETE_SGE, -}; - -enum completion_request { - CEQ_SET = 1, -}; - -enum cmdq_cmd_type { - SYNC_CMD_DIRECT_RESP, - SYNC_CMD_SGE_RESP, - ASYNC_CMD, -}; - -#define NUM_WQEBBS_FOR_CMDQ_WQE 1 - -bool sphw_cmdq_idle(struct sphw_cmdq *cmdq) -{ - return sphw_wq_is_empty(&cmdq->wq); -} - -static void *cmdq_read_wqe(struct sphw_wq *wq, u16 *ci) -{ - if (sphw_wq_is_empty(wq)) - return NULL; - - return sphw_wq_read_one_wqebb(wq, ci); -} - -static void *cmdq_get_wqe(struct sphw_wq *wq, u16 *pi) -{ - if (!sphw_wq_free_wqebbs(wq)) - return NULL; - - return sphw_wq_get_one_wqebb(wq, pi); -} - -struct sphw_cmd_buf *sphw_alloc_cmd_buf(void *hwdev) -{ - struct sphw_cmdqs *cmdqs = NULL; - struct sphw_cmd_buf *cmd_buf = NULL; - void *dev = NULL; - - if (!hwdev) { - pr_err("Failed to alloc cmd buf, Invalid hwdev\n"); - return NULL; - } - - cmdqs = ((struct sphw_hwdev *)hwdev)->cmdqs; - dev = ((struct sphw_hwdev *)hwdev)->dev_hdl; - - cmd_buf = kzalloc(sizeof(*cmd_buf), GFP_ATOMIC); - if (!cmd_buf) { - sdk_err(dev, "Failed to allocate cmd buf\n"); - return NULL; - } - - cmd_buf->buf = pci_pool_alloc(cmdqs->cmd_buf_pool, GFP_ATOMIC, - &cmd_buf->dma_addr); - if (!cmd_buf->buf) { - sdk_err(dev, "Failed to allocate cmdq cmd buf from the pool\n"); - goto alloc_pci_buf_err; - } - - atomic_set(&cmd_buf->ref_cnt, 1); - - return cmd_buf; - -alloc_pci_buf_err: - kfree(cmd_buf); - return NULL; -} - -void sphw_free_cmd_buf(void *hwdev, struct sphw_cmd_buf *cmd_buf) -{ - struct sphw_cmdqs *cmdqs = NULL; - - if (!hwdev || !cmd_buf) { - pr_err("Failed to free cmd buf: hwdev: %p, cmd_buf: %p\n", - hwdev, cmd_buf); - return; - } - - if (!atomic_dec_and_test(&cmd_buf->ref_cnt)) - return; - - cmdqs = ((struct sphw_hwdev *)hwdev)->cmdqs; - - pci_pool_free(cmdqs->cmd_buf_pool, cmd_buf->buf, cmd_buf->dma_addr); - kfree(cmd_buf); -} - -static void cmdq_set_completion(struct sphw_cmdq_completion *complete, - struct sphw_cmd_buf *buf_out) -{ - struct sphw_sge_resp *sge_resp = &complete->sge_resp; - - sphw_set_sge(&sge_resp->sge, buf_out->dma_addr, SPHW_CMDQ_BUF_SIZE); -} - -static void cmdq_set_lcmd_bufdesc(struct sphw_cmdq_wqe_lcmd *wqe, - struct sphw_cmd_buf *buf_in) -{ - sphw_set_sge(&wqe->buf_desc.sge, buf_in->dma_addr, buf_in->size); -} - -static void cmdq_set_inline_wqe_data(struct sphw_cmdq_inline_wqe *wqe, - const void *buf_in, u32 in_size) -{ - struct sphw_cmdq_wqe_scmd *wqe_scmd = &wqe->wqe_scmd; - - wqe_scmd->buf_desc.buf_len = in_size; - memcpy(wqe_scmd->buf_desc.data, buf_in, in_size); -} - -static void cmdq_fill_db(struct sphw_cmdq_db *db, - enum sphw_cmdq_type cmdq_type, u16 prod_idx) -{ - db->db_info = CMDQ_DB_INFO_SET(UPPER_8_BITS(prod_idx), HI_PROD_IDX); - - db->db_head = CMDQ_DB_HEAD_SET(SPHW_DB_CMDQ_TYPE, QUEUE_TYPE) | - CMDQ_DB_HEAD_SET(cmdq_type, CMDQ_TYPE) | - CMDQ_DB_HEAD_SET(SPHW_DB_SRC_CMDQ_TYPE, SRC_TYPE); -} - -static void cmdq_set_db(struct sphw_cmdq *cmdq, - enum sphw_cmdq_type cmdq_type, u16 prod_idx) -{ - struct sphw_cmdq_db db = {0}; - - cmdq_fill_db(&db, cmdq_type, prod_idx); - - wmb(); /* write all before the doorbell */ - writeq(*((u64 *)&db), CMDQ_DB_ADDR(cmdq->db_base, prod_idx)); -} - -static void cmdq_wqe_fill(void *dst, const void *src) -{ - memcpy((u8 *)dst + FIRST_DATA_TO_WRITE_LAST, - (u8 *)src + FIRST_DATA_TO_WRITE_LAST, - CMDQ_WQE_SIZE - FIRST_DATA_TO_WRITE_LAST); - - wmb(); /* The first 8 bytes should be written last */ - - *(u64 *)dst = *(u64 *)src; -} - -static void cmdq_prepare_wqe_ctrl(struct sphw_cmdq_wqe *wqe, int wrapped, - u8 mod, u8 cmd, u16 prod_idx, - enum completion_format complete_format, - enum data_format data_format, - enum bufdesc_len buf_len) -{ - struct sphw_ctrl *ctrl = NULL; - enum ctrl_sect_len ctrl_len; - struct sphw_cmdq_wqe_lcmd *wqe_lcmd = NULL; - struct sphw_cmdq_wqe_scmd *wqe_scmd = NULL; - u32 saved_data = WQE_HEADER(wqe)->saved_data; - - if (data_format == DATA_SGE) { - wqe_lcmd = &wqe->wqe_lcmd; - - wqe_lcmd->status.status_info = 0; - ctrl = &wqe_lcmd->ctrl; - ctrl_len = CTRL_SECT_LEN; - } else { - wqe_scmd = &wqe->inline_wqe.wqe_scmd; - - wqe_scmd->status.status_info = 0; - ctrl = &wqe_scmd->ctrl; - ctrl_len = CTRL_DIRECT_SECT_LEN; - } - - ctrl->ctrl_info = CMDQ_CTRL_SET(prod_idx, PI) | - CMDQ_CTRL_SET(cmd, CMD) | - CMDQ_CTRL_SET(mod, MOD); - - WQE_HEADER(wqe)->header_info = - CMDQ_WQE_HEADER_SET(buf_len, BUFDESC_LEN) | - CMDQ_WQE_HEADER_SET(complete_format, COMPLETE_FMT) | - CMDQ_WQE_HEADER_SET(data_format, DATA_FMT) | - CMDQ_WQE_HEADER_SET(CEQ_SET, COMPLETE_REQ) | - CMDQ_WQE_HEADER_SET(COMPLETE_LEN, COMPLETE_SECT_LEN) | - CMDQ_WQE_HEADER_SET(ctrl_len, CTRL_LEN) | - CMDQ_WQE_HEADER_SET((u32)wrapped, HW_BUSY_BIT); - - if (cmd == CMDQ_SET_ARM_CMD && mod == SPHW_MOD_COMM) { - saved_data &= SAVED_DATA_CLEAR(saved_data, ARM); - WQE_HEADER(wqe)->saved_data = saved_data | - SAVED_DATA_SET(1, ARM); - } else { - saved_data &= SAVED_DATA_CLEAR(saved_data, ARM); - WQE_HEADER(wqe)->saved_data = saved_data; - } -} - -static void cmdq_set_lcmd_wqe(struct sphw_cmdq_wqe *wqe, - enum cmdq_cmd_type cmd_type, - struct sphw_cmd_buf *buf_in, - struct sphw_cmd_buf *buf_out, int wrapped, - u8 mod, u8 cmd, u16 prod_idx) -{ - struct sphw_cmdq_wqe_lcmd *wqe_lcmd = &wqe->wqe_lcmd; - enum completion_format complete_format = COMPLETE_DIRECT; - - switch (cmd_type) { - case SYNC_CMD_DIRECT_RESP: - wqe_lcmd->completion.direct_resp = 0; - break; - case SYNC_CMD_SGE_RESP: - if (buf_out) { - complete_format = COMPLETE_SGE; - cmdq_set_completion(&wqe_lcmd->completion, - buf_out); - } - break; - case ASYNC_CMD: - wqe_lcmd->completion.direct_resp = 0; - wqe_lcmd->buf_desc.saved_async_buf = (u64)(buf_in); - break; - } - - cmdq_prepare_wqe_ctrl(wqe, wrapped, mod, cmd, prod_idx, complete_format, - DATA_SGE, BUFDESC_LCMD_LEN); - - cmdq_set_lcmd_bufdesc(wqe_lcmd, buf_in); -} - -static void cmdq_set_inline_wqe(struct sphw_cmdq_wqe *wqe, - enum cmdq_cmd_type cmd_type, - const void *buf_in, u16 in_size, - struct sphw_cmd_buf *buf_out, int wrapped, - u8 mod, u8 cmd, u16 prod_idx) -{ - struct sphw_cmdq_wqe_scmd *wqe_scmd = &wqe->inline_wqe.wqe_scmd; - enum completion_format complete_format = COMPLETE_DIRECT; - - switch (cmd_type) { - case SYNC_CMD_SGE_RESP: - complete_format = COMPLETE_SGE; - cmdq_set_completion(&wqe_scmd->completion, buf_out); - break; - case SYNC_CMD_DIRECT_RESP: - complete_format = COMPLETE_DIRECT; - wqe_scmd->completion.direct_resp = 0; - break; - default: - break; - } - - cmdq_prepare_wqe_ctrl(wqe, wrapped, mod, cmd, prod_idx, - complete_format, DATA_DIRECT, BUFDESC_SCMD_LEN); - - cmdq_set_inline_wqe_data(&wqe->inline_wqe, buf_in, in_size); -} - -static void cmdq_update_cmd_status(struct sphw_cmdq *cmdq, u16 prod_idx, - struct sphw_cmdq_wqe *wqe) -{ - struct sphw_cmdq_cmd_info *cmd_info; - struct sphw_cmdq_wqe_lcmd *wqe_lcmd; - u32 status_info; - - wqe_lcmd = &wqe->wqe_lcmd; - cmd_info = &cmdq->cmd_infos[prod_idx]; - - if (cmd_info->errcode) { - status_info = wqe_lcmd->status.status_info; - *cmd_info->errcode = WQE_ERRCODE_GET(status_info, VAL); - } - - if (cmd_info->direct_resp) - *cmd_info->direct_resp = wqe_lcmd->completion.direct_resp; -} - -static int sphw_cmdq_sync_timeout_check(struct sphw_cmdq *cmdq, struct sphw_cmdq_wqe *wqe, u16 pi) -{ - struct sphw_cmdq_wqe_lcmd *wqe_lcmd; - u32 ctrl_info; - - wqe_lcmd = &wqe->wqe_lcmd; - ctrl_info = wqe_lcmd->ctrl.ctrl_info; - if (!WQE_COMPLETED(ctrl_info)) { - sdk_info(cmdq->hwdev->dev_hdl, "Cmdq sync command check busy bit not set\n"); - return -EFAULT; - } - - cmdq_update_cmd_status(cmdq, pi, wqe); - - sdk_info(cmdq->hwdev->dev_hdl, "Cmdq sync command check succeed\n"); - return 0; -} - -static void clear_cmd_info(struct sphw_cmdq_cmd_info *cmd_info, - struct sphw_cmdq_cmd_info *saved_cmd_info) -{ - if (cmd_info->errcode == saved_cmd_info->errcode) - cmd_info->errcode = NULL; - - if (cmd_info->done == saved_cmd_info->done) - cmd_info->done = NULL; - - if (cmd_info->direct_resp == saved_cmd_info->direct_resp) - cmd_info->direct_resp = NULL; -} - -static int cmdq_ceq_handler_status(struct sphw_cmdq *cmdq, - struct sphw_cmdq_cmd_info *cmd_info, - struct sphw_cmdq_cmd_info *saved_cmd_info, - u64 curr_msg_id, u16 curr_prod_idx, - struct sphw_cmdq_wqe *curr_wqe, - u32 timeout) -{ - ulong timeo; - int err; - - timeo = msecs_to_jiffies(timeout); - if (wait_for_completion_timeout(saved_cmd_info->done, timeo)) - return 0; - - spin_lock_bh(&cmdq->cmdq_lock); - - if (cmd_info->cmpt_code == saved_cmd_info->cmpt_code) - cmd_info->cmpt_code = NULL; - - if (*saved_cmd_info->cmpt_code == CMDQ_COMPLETE_CMPT_CODE) { - sdk_info(cmdq->hwdev->dev_hdl, "Cmdq direct sync command has been completed\n"); - spin_unlock_bh(&cmdq->cmdq_lock); - return 0; - } - - if (curr_msg_id == cmd_info->cmdq_msg_id) { - err = sphw_cmdq_sync_timeout_check(cmdq, curr_wqe, curr_prod_idx); - if (err) - cmd_info->cmd_type = SPHW_CMD_TYPE_TIMEOUT; - else - cmd_info->cmd_type = SPHW_CMD_TYPE_FAKE_TIMEOUT; - } else { - err = -ETIMEDOUT; - sdk_err(cmdq->hwdev->dev_hdl, "Cmdq sync command current msg id dismatch with cmd_info msg id\n"); - } - - clear_cmd_info(cmd_info, saved_cmd_info); - - spin_unlock_bh(&cmdq->cmdq_lock); - - if (!err) - return 0; - - sphw_dump_ceq_info(cmdq->hwdev); - - return -ETIMEDOUT; -} - -static int wait_cmdq_sync_cmd_completion(struct sphw_cmdq *cmdq, - struct sphw_cmdq_cmd_info *cmd_info, - struct sphw_cmdq_cmd_info *saved_cmd_info, - u64 curr_msg_id, u16 curr_prod_idx, - struct sphw_cmdq_wqe *curr_wqe, u32 timeout) -{ - return cmdq_ceq_handler_status(cmdq, cmd_info, saved_cmd_info, - curr_msg_id, curr_prod_idx, - curr_wqe, timeout); -} - -static int cmdq_msg_lock(struct sphw_cmdq *cmdq, u16 channel) -{ - struct sphw_cmdqs *cmdqs = cmdq_to_cmdqs(cmdq); - - /* Keep wrapped and doorbell index correct. bh - for tasklet(ceq) */ - spin_lock_bh(&cmdq->cmdq_lock); - - if (cmdqs->lock_channel_en && test_bit(channel, &cmdqs->channel_stop)) { - spin_unlock_bh(&cmdq->cmdq_lock); - return -EAGAIN; - } - - return 0; -} - -static void cmdq_msg_unlock(struct sphw_cmdq *cmdq) -{ - spin_unlock_bh(&cmdq->cmdq_lock); -} - -static void cmdq_clear_cmd_buf(struct sphw_cmdq_cmd_info *cmd_info, - struct sphw_hwdev *hwdev) -{ - if (cmd_info->buf_in) - sphw_free_cmd_buf(hwdev, cmd_info->buf_in); - - if (cmd_info->buf_out) - sphw_free_cmd_buf(hwdev, cmd_info->buf_out); - - cmd_info->buf_in = NULL; - cmd_info->buf_out = NULL; -} - -static void cmdq_set_cmd_buf(struct sphw_cmdq_cmd_info *cmd_info, - struct sphw_hwdev *hwdev, - struct sphw_cmd_buf *buf_in, - struct sphw_cmd_buf *buf_out) -{ - cmd_info->buf_in = buf_in; - cmd_info->buf_out = buf_out; - - if (buf_in) - atomic_inc(&buf_in->ref_cnt); - - if (buf_out) - atomic_inc(&buf_out->ref_cnt); -} - -static int cmdq_sync_cmd_direct_resp(struct sphw_cmdq *cmdq, u8 mod, - u8 cmd, struct sphw_cmd_buf *buf_in, - u64 *out_param, u32 timeout, u16 channel) -{ - struct sphw_wq *wq = &cmdq->wq; - struct sphw_cmdq_wqe *curr_wqe = NULL, wqe; - struct sphw_cmdq_cmd_info *cmd_info = NULL, saved_cmd_info; - struct completion done; - u16 curr_prod_idx, next_prod_idx; - int wrapped, errcode = 0; - int cmpt_code = CMDQ_SEND_CMPT_CODE; - u64 curr_msg_id; - int err; - - err = cmdq_msg_lock(cmdq, channel); - if (err) - return err; - - curr_wqe = cmdq_get_wqe(wq, &curr_prod_idx); - if (!curr_wqe) { - cmdq_msg_unlock(cmdq); - return -EBUSY; - } - - memset(&wqe, 0, sizeof(wqe)); - - wrapped = cmdq->wrapped; - - next_prod_idx = curr_prod_idx + NUM_WQEBBS_FOR_CMDQ_WQE; - if (next_prod_idx >= wq->q_depth) { - cmdq->wrapped = !cmdq->wrapped; - next_prod_idx -= (u16)wq->q_depth; - } - - cmd_info = &cmdq->cmd_infos[curr_prod_idx]; - - init_completion(&done); - - cmd_info->cmd_type = SPHW_CMD_TYPE_DIRECT_RESP; - cmd_info->done = &done; - cmd_info->errcode = &errcode; - cmd_info->direct_resp = out_param; - cmd_info->cmpt_code = &cmpt_code; - cmd_info->channel = channel; - cmdq_set_cmd_buf(cmd_info, cmdq->hwdev, buf_in, NULL); - - memcpy(&saved_cmd_info, cmd_info, sizeof(*cmd_info)); - - cmdq_set_lcmd_wqe(&wqe, SYNC_CMD_DIRECT_RESP, buf_in, NULL, - wrapped, mod, cmd, curr_prod_idx); - - /* CMDQ WQE is not shadow, therefore wqe will be written to wq */ - cmdq_wqe_fill(curr_wqe, &wqe); - - (cmd_info->cmdq_msg_id)++; - curr_msg_id = cmd_info->cmdq_msg_id; - - cmdq_set_db(cmdq, SPHW_CMDQ_SYNC, next_prod_idx); - - cmdq_msg_unlock(cmdq); - - timeout = timeout ? timeout : CMDQ_CMD_TIMEOUT; - err = wait_cmdq_sync_cmd_completion(cmdq, cmd_info, &saved_cmd_info, - curr_msg_id, curr_prod_idx, - curr_wqe, timeout); - if (err) { - sdk_err(cmdq->hwdev->dev_hdl, "Cmdq sync command(mod: %u, cmd: %u) timeout, prod idx: 0x%x\n", - mod, cmd, curr_prod_idx); - err = -ETIMEDOUT; - } - - if (cmpt_code == CMDQ_FORCE_STOP_CMPT_CODE) { - sdk_info(cmdq->hwdev->dev_hdl, "Force stop cmdq cmd, mod: %u, cmd: %u\n", - mod, cmd); - err = -EAGAIN; - } - - smp_rmb(); /* read error code after completion */ - - return err ? err : errcode; -} - -static int cmdq_sync_cmd_detail_resp(struct sphw_cmdq *cmdq, u8 mod, u8 cmd, - struct sphw_cmd_buf *buf_in, - struct sphw_cmd_buf *buf_out, - u64 *out_param, u32 timeout, u16 channel) -{ - struct sphw_wq *wq = &cmdq->wq; - struct sphw_cmdq_wqe *curr_wqe = NULL, wqe; - struct sphw_cmdq_cmd_info *cmd_info = NULL, saved_cmd_info; - struct completion done; - u16 curr_prod_idx, next_prod_idx; - int wrapped, errcode = 0; - int cmpt_code = CMDQ_SEND_CMPT_CODE; - u64 curr_msg_id; - int err; - - err = cmdq_msg_lock(cmdq, channel); - if (err) - return err; - - curr_wqe = cmdq_get_wqe(wq, &curr_prod_idx); - if (!curr_wqe) { - cmdq_msg_unlock(cmdq); - return -EBUSY; - } - - memset(&wqe, 0, sizeof(wqe)); - - wrapped = cmdq->wrapped; - - next_prod_idx = curr_prod_idx + NUM_WQEBBS_FOR_CMDQ_WQE; - if (next_prod_idx >= wq->q_depth) { - cmdq->wrapped = !cmdq->wrapped; - next_prod_idx -= (u16)wq->q_depth; - } - - cmd_info = &cmdq->cmd_infos[curr_prod_idx]; - - init_completion(&done); - - cmd_info->cmd_type = SPHW_CMD_TYPE_SGE_RESP; - cmd_info->done = &done; - cmd_info->errcode = &errcode; - cmd_info->direct_resp = out_param; - cmd_info->cmpt_code = &cmpt_code; - cmd_info->channel = channel; - cmdq_set_cmd_buf(cmd_info, cmdq->hwdev, buf_in, buf_out); - - memcpy(&saved_cmd_info, cmd_info, sizeof(*cmd_info)); - - cmdq_set_lcmd_wqe(&wqe, SYNC_CMD_SGE_RESP, buf_in, buf_out, - wrapped, mod, cmd, curr_prod_idx); - - cmdq_wqe_fill(curr_wqe, &wqe); - - (cmd_info->cmdq_msg_id)++; - curr_msg_id = cmd_info->cmdq_msg_id; - - cmdq_set_db(cmdq, cmdq->cmdq_type, next_prod_idx); - - cmdq_msg_unlock(cmdq); - - timeout = timeout ? timeout : CMDQ_CMD_TIMEOUT; - err = wait_cmdq_sync_cmd_completion(cmdq, cmd_info, &saved_cmd_info, - curr_msg_id, curr_prod_idx, - curr_wqe, timeout); - if (err) { - sdk_err(cmdq->hwdev->dev_hdl, "Cmdq sync command(mod: %u, cmd: %u) timeout, prod idx: 0x%x\n", - mod, cmd, curr_prod_idx); - err = -ETIMEDOUT; - } - - if (cmpt_code == CMDQ_FORCE_STOP_CMPT_CODE) { - sdk_info(cmdq->hwdev->dev_hdl, "Force stop cmdq cmd, mod: %u, cmd: %u\n", - mod, cmd); - err = -EAGAIN; - } - - smp_rmb(); /* read error code after completion */ - - return err ? err : errcode; -} - -static int cmdq_async_cmd(struct sphw_cmdq *cmdq, u8 mod, u8 cmd, - struct sphw_cmd_buf *buf_in, u16 channel) -{ - struct sphw_cmdq_cmd_info *cmd_info = NULL; - struct sphw_wq *wq = &cmdq->wq; - u16 curr_prod_idx, next_prod_idx; - struct sphw_cmdq_wqe *curr_wqe = NULL, wqe; - int wrapped, err; - - err = cmdq_msg_lock(cmdq, channel); - if (err) - return err; - - curr_wqe = cmdq_get_wqe(wq, &curr_prod_idx); - if (!curr_wqe) { - cmdq_msg_unlock(cmdq); - return -EBUSY; - } - - memset(&wqe, 0, sizeof(wqe)); - - wrapped = cmdq->wrapped; - next_prod_idx = curr_prod_idx + NUM_WQEBBS_FOR_CMDQ_WQE; - if (next_prod_idx >= wq->q_depth) { - cmdq->wrapped = !cmdq->wrapped; - next_prod_idx -= (u16)wq->q_depth; - } - - cmdq_set_lcmd_wqe(&wqe, ASYNC_CMD, buf_in, NULL, wrapped, - mod, cmd, curr_prod_idx); - - cmdq_wqe_fill(curr_wqe, &wqe); - - cmd_info = &cmdq->cmd_infos[curr_prod_idx]; - cmd_info->cmd_type = SPHW_CMD_TYPE_ASYNC; - cmd_info->channel = channel; - /* The caller will not free the cmd_buf of the asynchronous command, - * so there is no need to increase the reference count here - */ - cmd_info->buf_in = buf_in; - - /* LB mode 1 compatible, cmdq 0 also for async, which is sync_no_wait */ - cmdq_set_db(cmdq, SPHW_CMDQ_SYNC, next_prod_idx); - - cmdq_msg_unlock(cmdq); - - return 0; -} - -int cmdq_set_arm_bit(struct sphw_cmdq *cmdq, const void *buf_in, - u16 in_size) -{ - struct sphw_wq *wq = &cmdq->wq; - struct sphw_cmdq_wqe *curr_wqe = NULL, wqe; - u16 curr_prod_idx, next_prod_idx; - int wrapped; - - /* Keep wrapped and doorbell index correct. bh - for tasklet(ceq) */ - spin_lock_bh(&cmdq->cmdq_lock); - - curr_wqe = cmdq_get_wqe(wq, &curr_prod_idx); - if (!curr_wqe) { - spin_unlock_bh(&cmdq->cmdq_lock); - return -EBUSY; - } - - memset(&wqe, 0, sizeof(wqe)); - - wrapped = cmdq->wrapped; - - next_prod_idx = curr_prod_idx + NUM_WQEBBS_FOR_CMDQ_WQE; - if (next_prod_idx >= wq->q_depth) { - cmdq->wrapped = !cmdq->wrapped; - next_prod_idx -= (u16)wq->q_depth; - } - - cmdq_set_inline_wqe(&wqe, SYNC_CMD_DIRECT_RESP, buf_in, in_size, NULL, - wrapped, SPHW_MOD_COMM, CMDQ_SET_ARM_CMD, - curr_prod_idx); - - /* cmdq wqe is not shadow, therefore wqe will be written to wq */ - cmdq_wqe_fill(curr_wqe, &wqe); - - cmdq->cmd_infos[curr_prod_idx].cmd_type = SPHW_CMD_TYPE_SET_ARM; - - cmdq_set_db(cmdq, cmdq->cmdq_type, next_prod_idx); - - spin_unlock_bh(&cmdq->cmdq_lock); - - return 0; -} - -static int cmdq_params_valid(void *hwdev, struct sphw_cmd_buf *buf_in) -{ - if (!buf_in || !hwdev) { - pr_err("Invalid CMDQ buffer addr: %p or hwdev: %p\n", - buf_in, hwdev); - return -EINVAL; - } - - if (!buf_in->size || buf_in->size > SPHW_CMDQ_MAX_DATA_SIZE) { - pr_err("Invalid CMDQ buffer size: 0x%x\n", buf_in->size); - return -EINVAL; - } - - return 0; -} - -#define WAIT_CMDQ_ENABLE_TIMEOUT 300 -static int wait_cmdqs_enable(struct sphw_cmdqs *cmdqs) -{ - unsigned long end; - - end = jiffies + msecs_to_jiffies(WAIT_CMDQ_ENABLE_TIMEOUT); - do { - if (cmdqs->status & SPHW_CMDQ_ENABLE) - return 0; - } while (time_before(jiffies, end) && cmdqs->hwdev->chip_present_flag && - !cmdqs->disable_flag); - - cmdqs->disable_flag = 1; - - return -EBUSY; -} - -int sphw_cmdq_direct_resp(void *hwdev, u8 mod, u8 cmd, struct sphw_cmd_buf *buf_in, - u64 *out_param, u32 timeout, u16 channel) -{ - struct sphw_cmdqs *cmdqs = NULL; - int err = cmdq_params_valid(hwdev, buf_in); - - if (err) { - pr_err("Invalid CMDQ parameters\n"); - return err; - } - - /* to do : support send cmdq only when cmdq init*/ - if (!(((struct sphw_hwdev *)hwdev)->chip_present_flag)) - return -EPERM; - - cmdqs = ((struct sphw_hwdev *)hwdev)->cmdqs; - err = wait_cmdqs_enable(cmdqs); - if (err) { - sdk_err(cmdqs->hwdev->dev_hdl, "Cmdq is disable\n"); - return err; - } - - err = cmdq_sync_cmd_direct_resp(&cmdqs->cmdq[SPHW_CMDQ_SYNC], - mod, cmd, buf_in, out_param, - timeout, channel); - - if (!(((struct sphw_hwdev *)hwdev)->chip_present_flag)) - return -ETIMEDOUT; - else - return err; -} - -int sphw_cmdq_detail_resp(void *hwdev, u8 mod, u8 cmd, struct sphw_cmd_buf *buf_in, - struct sphw_cmd_buf *buf_out, u64 *out_param, u32 timeout, u16 channel) -{ - struct sphw_cmdqs *cmdqs = NULL; - int err = cmdq_params_valid(hwdev, buf_in); - - if (err) - return err; - - cmdqs = ((struct sphw_hwdev *)hwdev)->cmdqs; - - if (!(((struct sphw_hwdev *)hwdev)->chip_present_flag)) /*to do*/ - return -EPERM; - - err = wait_cmdqs_enable(cmdqs); - if (err) { - sdk_err(cmdqs->hwdev->dev_hdl, "Cmdq is disable\n"); - return err; - } - - err = cmdq_sync_cmd_detail_resp(&cmdqs->cmdq[SPHW_CMDQ_SYNC], - mod, cmd, buf_in, buf_out, out_param, - timeout, channel); - if (!(((struct sphw_hwdev *)hwdev)->chip_present_flag)) - return -ETIMEDOUT; - else - return err; -} - -int sphw_cos_id_detail_resp(void *hwdev, u8 mod, u8 cmd, u8 cos_id, struct sphw_cmd_buf *buf_in, - struct sphw_cmd_buf *buf_out, u64 *out_param, u32 timeout, u16 channel) -{ - struct sphw_cmdqs *cmdqs = NULL; - int err = cmdq_params_valid(hwdev, buf_in); - - if (err) - return err; - - cmdqs = ((struct sphw_hwdev *)hwdev)->cmdqs; - - if (!(((struct sphw_hwdev *)hwdev)->chip_present_flag)) /*to do*/ - return -EPERM; - - err = wait_cmdqs_enable(cmdqs); - if (err) { - sdk_err(cmdqs->hwdev->dev_hdl, "Cmdq is disable\n"); - return err; - } - - if (cos_id >= SPHW_MAX_CMDQ_TYPES) { - sdk_err(cmdqs->hwdev->dev_hdl, "Cmdq id is invalid\n"); - return -EINVAL; - } - - err = cmdq_sync_cmd_detail_resp(&cmdqs->cmdq[cos_id], mod, cmd, - buf_in, buf_out, out_param, - timeout, channel); - if (!(((struct sphw_hwdev *)hwdev)->chip_present_flag)) - return -ETIMEDOUT; - else - return err; -} - -int sphw_cmdq_async(void *hwdev, u8 mod, u8 cmd, struct sphw_cmd_buf *buf_in, u16 channel) -{ - struct sphw_cmdqs *cmdqs = NULL; - int err = cmdq_params_valid(hwdev, buf_in); - - if (err) - return err; - - cmdqs = ((struct sphw_hwdev *)hwdev)->cmdqs; - - if (!(((struct sphw_hwdev *)hwdev)->chip_present_flag)) /*to do*/ - return -EPERM; - - err = wait_cmdqs_enable(cmdqs); - if (err) { - sdk_err(cmdqs->hwdev->dev_hdl, "Cmdq is disable\n"); - return err; - } - /* LB mode 1 compatible, cmdq 0 also for async, which is sync_no_wait*/ - return cmdq_async_cmd(&cmdqs->cmdq[SPHW_CMDQ_SYNC], mod, - cmd, buf_in, channel); -} - -int sphw_set_arm_bit(void *hwdev, enum sphw_set_arm_type q_type, u16 q_id) -{ - struct sphw_cmdqs *cmdqs = NULL; - struct sphw_cmdq *cmdq = NULL; - struct sphw_cmdq_arm_bit arm_bit; - enum sphw_cmdq_type cmdq_type = SPHW_CMDQ_SYNC; - u16 in_size; - int err; - - if (!hwdev) - return -EINVAL; - - if (!(((struct sphw_hwdev *)hwdev)->chip_present_flag))/* to do*/ - return -EPERM; - - cmdqs = ((struct sphw_hwdev *)hwdev)->cmdqs; - - if (!(cmdqs->status & SPHW_CMDQ_ENABLE)) - return -EBUSY; - - if (q_type == SPHW_SET_ARM_CMDQ) { - if (q_id >= SPHW_MAX_CMDQ_TYPES) - return -EFAULT; - - cmdq_type = q_id; - } - /* sq is using interrupt now, so we only need to set arm bit for cmdq, - * remove comment below if need to set sq arm bit - * else - * cmdq_type = SPHW_CMDQ_SYNC; - */ - - cmdq = &cmdqs->cmdq[cmdq_type]; - - arm_bit.q_type = q_type; - arm_bit.q_id = q_id; - in_size = sizeof(arm_bit); - - err = cmdq_set_arm_bit(cmdq, &arm_bit, in_size); - if (err) { - sdk_err(cmdqs->hwdev->dev_hdl, - "Failed to set arm for q_type: %d, qid %d\n", - q_type, q_id); - return err; - } - - return 0; -} - -static void clear_wqe_complete_bit(struct sphw_cmdq *cmdq, - struct sphw_cmdq_wqe *wqe, u16 ci) -{ - struct sphw_ctrl *ctrl = NULL; - u32 header_info = WQE_HEADER(wqe)->header_info; - enum data_format df = CMDQ_WQE_HEADER_GET(header_info, DATA_FMT); - - if (df == DATA_SGE) - ctrl = &wqe->wqe_lcmd.ctrl; - else - ctrl = &wqe->inline_wqe.wqe_scmd.ctrl; - - /* clear HW busy bit */ - ctrl->ctrl_info = 0; - cmdq->cmd_infos[ci].cmd_type = SPHW_CMD_TYPE_NONE; - - wmb(); /* verify wqe is clear */ - - sphw_wq_put_wqebbs(&cmdq->wq, NUM_WQEBBS_FOR_CMDQ_WQE); -} - -static void cmdq_sync_cmd_handler(struct sphw_cmdq *cmdq, - struct sphw_cmdq_wqe *wqe, u16 ci) -{ - spin_lock(&cmdq->cmdq_lock); - - cmdq_update_cmd_status(cmdq, ci, wqe); - - if (cmdq->cmd_infos[ci].cmpt_code) { - *cmdq->cmd_infos[ci].cmpt_code = CMDQ_COMPLETE_CMPT_CODE; - cmdq->cmd_infos[ci].cmpt_code = NULL; - } - - /* make sure cmpt_code operation before done operation */ - smp_rmb(); - - if (cmdq->cmd_infos[ci].done) { - complete(cmdq->cmd_infos[ci].done); - cmdq->cmd_infos[ci].done = NULL; - } - - spin_unlock(&cmdq->cmdq_lock); - - cmdq_clear_cmd_buf(&cmdq->cmd_infos[ci], cmdq->hwdev); - clear_wqe_complete_bit(cmdq, wqe, ci); -} - -static void cmdq_async_cmd_handler(struct sphw_hwdev *hwdev, - struct sphw_cmdq *cmdq, - struct sphw_cmdq_wqe *wqe, u16 ci) -{ - cmdq_clear_cmd_buf(&cmdq->cmd_infos[ci], hwdev); - clear_wqe_complete_bit(cmdq, wqe, ci); -} - -static int cmdq_arm_ceq_handler(struct sphw_cmdq *cmdq, - struct sphw_cmdq_wqe *wqe, u16 ci) -{ - struct sphw_ctrl *ctrl = &wqe->inline_wqe.wqe_scmd.ctrl; - u32 ctrl_info = ctrl->ctrl_info; - - if (!WQE_COMPLETED(ctrl_info)) - return -EBUSY; - - clear_wqe_complete_bit(cmdq, wqe, ci); - - return 0; -} - -#define SPHW_CMDQ_WQE_HEAD_LEN 32 -static void sphw_dump_cmdq_wqe_head(struct sphw_hwdev *hwdev, struct sphw_cmdq_wqe *wqe) -{ - u32 i; - u32 *data = (u32 *)wqe; - - for (i = 0; i < (SPHW_CMDQ_WQE_HEAD_LEN / sizeof(u32)); i += 4) { - sdk_info(hwdev->dev_hdl, "wqe data: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n", - *(data + i), *(data + i + 1), *(data + i + 2), - *(data + i + 3)); - } -} - -void sphw_cmdq_ceq_handler(void *handle, u32 ceqe_data) -{ - struct sphw_cmdqs *cmdqs = ((struct sphw_hwdev *)handle)->cmdqs; - enum sphw_cmdq_type cmdq_type = CEQE_CMDQ_GET(ceqe_data, TYPE); - struct sphw_cmdq *cmdq = &cmdqs->cmdq[cmdq_type]; - struct sphw_hwdev *hwdev = cmdqs->hwdev; - struct sphw_cmdq_wqe *wqe = NULL; - struct sphw_cmdq_wqe_lcmd *wqe_lcmd = NULL; - struct sphw_cmdq_cmd_info *cmd_info = NULL; - u32 ctrl_info; - u16 ci; - - while ((wqe = cmdq_read_wqe(&cmdq->wq, &ci)) != NULL) { - cmd_info = &cmdq->cmd_infos[ci]; - - switch (cmd_info->cmd_type) { - case SPHW_CMD_TYPE_NONE: - return; - case SPHW_CMD_TYPE_TIMEOUT: - sdk_warn(hwdev->dev_hdl, "Cmdq timeout, q_id: %u, ci: %u\n", - cmdq_type, ci); - sphw_dump_cmdq_wqe_head(hwdev, wqe); - fallthrough; - case SPHW_CMD_TYPE_FAKE_TIMEOUT: - cmdq_clear_cmd_buf(cmd_info, hwdev); - clear_wqe_complete_bit(cmdq, wqe, ci); - break; - case SPHW_CMD_TYPE_SET_ARM: - if (cmdq_arm_ceq_handler(cmdq, wqe, ci)) - return; - - break; - default: - /* only arm bit is using scmd wqe, the wqe is lcmd */ - wqe_lcmd = &wqe->wqe_lcmd; - ctrl_info = wqe_lcmd->ctrl.ctrl_info; - - if (!WQE_COMPLETED(ctrl_info)) - return; - - /* For FORCE_STOP cmd_type, we also need to wait for - * the firmware processing to complete to prevent the - * firmware from accessing the released cmd_buf - */ - if (cmd_info->cmd_type == SPHW_CMD_TYPE_FORCE_STOP) { - cmdq_clear_cmd_buf(cmd_info, hwdev); - clear_wqe_complete_bit(cmdq, wqe, ci); - } else if (cmd_info->cmd_type == SPHW_CMD_TYPE_ASYNC) { - cmdq_async_cmd_handler(hwdev, cmdq, wqe, ci); - } else { - cmdq_sync_cmd_handler(cmdq, wqe, ci); - } - - break; - } - } -} - -static void cmdq_init_queue_ctxt(struct sphw_cmdqs *cmdqs, - struct sphw_cmdq *cmdq, - struct cmdq_ctxt_info *ctxt_info) -{ - struct sphw_wq *wq = &cmdq->wq; - u64 cmdq_first_block_paddr, pfn; - u16 start_ci = (u16)wq->cons_idx; - - pfn = CMDQ_PFN(sphw_wq_get_first_wqe_page_addr(wq)); - - ctxt_info->curr_wqe_page_pfn = - CMDQ_CTXT_PAGE_INFO_SET(1, HW_BUSY_BIT) | - CMDQ_CTXT_PAGE_INFO_SET(1, CEQ_EN) | - CMDQ_CTXT_PAGE_INFO_SET(1, CEQ_ARM) | - CMDQ_CTXT_PAGE_INFO_SET(SPHW_CEQ_ID_CMDQ, EQ_ID) | - CMDQ_CTXT_PAGE_INFO_SET(pfn, CURR_WQE_PAGE_PFN); - - if (!WQ_IS_0_LEVEL_CLA(wq)) { - cmdq_first_block_paddr = cmdqs->wq_block_paddr; - pfn = CMDQ_PFN(cmdq_first_block_paddr); - } - - ctxt_info->wq_block_pfn = CMDQ_CTXT_BLOCK_INFO_SET(start_ci, CI) | - CMDQ_CTXT_BLOCK_INFO_SET(pfn, WQ_BLOCK_PFN); -} - -static int init_cmdq(struct sphw_cmdq *cmdq, struct sphw_hwdev *hwdev, - enum sphw_cmdq_type q_type) -{ - void __iomem *db_base; - int err; - - cmdq->cmdq_type = q_type; - cmdq->wrapped = 1; - cmdq->hwdev = hwdev; - - spin_lock_init(&cmdq->cmdq_lock); - - cmdq->cmd_infos = kcalloc(cmdq->wq.q_depth, sizeof(*cmdq->cmd_infos), - GFP_KERNEL); - if (!cmdq->cmd_infos) { - sdk_err(hwdev->dev_hdl, "Failed to allocate cmdq infos\n"); - err = -ENOMEM; - goto cmd_infos_err; - } - - err = sphw_alloc_db_addr(hwdev, &db_base, NULL); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to allocate doorbell address\n"); - goto alloc_db_err; - } - - cmdq->db_base = (u8 *)db_base; - return 0; - -alloc_db_err: - kfree(cmdq->cmd_infos); - -cmd_infos_err: - - return err; -} - -static void free_cmdq(struct sphw_hwdev *hwdev, struct sphw_cmdq *cmdq) -{ - sphw_free_db_addr(hwdev, cmdq->db_base, NULL); - kfree(cmdq->cmd_infos); -} - -static int sphw_set_cmdq_ctxts(struct sphw_hwdev *hwdev) -{ - struct sphw_cmdqs *cmdqs = hwdev->cmdqs; - enum sphw_cmdq_type cmdq_type; - int err; - - cmdq_type = SPHW_CMDQ_SYNC; - for (; cmdq_type < SPHW_MAX_CMDQ_TYPES; cmdq_type++) { - err = sphw_set_cmdq_ctxt(hwdev, (u8)cmdq_type, &cmdqs->cmdq[cmdq_type].cmdq_ctxt); - if (err) - return err; - } - - cmdqs->status |= SPHW_CMDQ_ENABLE; - cmdqs->disable_flag = 0; - - return 0; -} - -static void cmdq_flush_sync_cmd(struct sphw_cmdq_cmd_info *cmd_info) -{ - if (cmd_info->cmd_type != SPHW_CMD_TYPE_DIRECT_RESP && - cmd_info->cmd_type != SPHW_CMD_TYPE_SGE_RESP) - return; - - cmd_info->cmd_type = SPHW_CMD_TYPE_FORCE_STOP; - - if (cmd_info->cmpt_code && - *cmd_info->cmpt_code == CMDQ_SEND_CMPT_CODE) - *cmd_info->cmpt_code = CMDQ_FORCE_STOP_CMPT_CODE; - - if (cmd_info->done) { - complete(cmd_info->done); - cmd_info->done = NULL; - cmd_info->cmpt_code = NULL; - cmd_info->direct_resp = NULL; - cmd_info->errcode = NULL; - } -} - -void sphw_cmdq_flush_cmd(struct sphw_hwdev *hwdev, struct sphw_cmdq *cmdq) -{ - struct sphw_cmdq_cmd_info *cmd_info = NULL; - u16 ci = 0; - - spin_lock_bh(&cmdq->cmdq_lock); - - while (cmdq_read_wqe(&cmdq->wq, &ci)) { - sphw_wq_put_wqebbs(&cmdq->wq, NUM_WQEBBS_FOR_CMDQ_WQE); - cmd_info = &cmdq->cmd_infos[ci]; - - if (cmd_info->cmd_type == SPHW_CMD_TYPE_DIRECT_RESP || - cmd_info->cmd_type == SPHW_CMD_TYPE_SGE_RESP) - cmdq_flush_sync_cmd(cmd_info); - } - - spin_unlock_bh(&cmdq->cmdq_lock); -} - -void sphw_cmdq_flush_channel_sync_cmd(struct sphw_hwdev *hwdev, u16 channel) -{ - struct sphw_cmdq_cmd_info *cmd_info = NULL; - struct sphw_cmdq *cmdq = NULL; - struct sphw_wq *wq = NULL; - u16 wqe_cnt, ci, i; - - if (channel >= SPHW_CHANNEL_MAX) - return; - - cmdq = &hwdev->cmdqs->cmdq[SPHW_CMDQ_SYNC]; - - spin_lock_bh(&cmdq->cmdq_lock); - - wq = &cmdq->wq; - ci = wq->cons_idx; - wqe_cnt = (u16)WQ_MASK_IDX(wq, wq->prod_idx + - wq->q_depth - wq->cons_idx); - for (i = 0; i < wqe_cnt; i++) { - cmd_info = &cmdq->cmd_infos[WQ_MASK_IDX(wq, ci + i)]; - - if (cmd_info->channel == channel) - cmdq_flush_sync_cmd(cmd_info); - } - - spin_unlock_bh(&cmdq->cmdq_lock); -} - -static void cmdq_reset_all_cmd_buff(struct sphw_cmdq *cmdq) -{ - u16 i; - - for (i = 0; i < cmdq->wq.q_depth; i++) - cmdq_clear_cmd_buf(&cmdq->cmd_infos[i], cmdq->hwdev); -} - -int sphw_cmdq_set_channel_status(struct sphw_hwdev *hwdev, u16 channel, bool enable) -{ - if (channel >= SPHW_CHANNEL_MAX) - return -EINVAL; - - if (enable) { - clear_bit(channel, &hwdev->cmdqs->channel_stop); - } else { - set_bit(channel, &hwdev->cmdqs->channel_stop); - sphw_cmdq_flush_channel_sync_cmd(hwdev, channel); - } - - sdk_info(hwdev->dev_hdl, "%s cmdq channel 0x%x\n", - enable ? "Enable" : "Disable", channel); - - return 0; -} - -void sphw_cmdq_enable_channel_lock(struct sphw_hwdev *hwdev, bool enable) -{ - hwdev->cmdqs->lock_channel_en = enable; - - sdk_info(hwdev->dev_hdl, "%s cmdq channel lock\n", - enable ? "Enable" : "Disable"); -} - -int sphw_reinit_cmdq_ctxts(struct sphw_hwdev *hwdev) -{ - struct sphw_cmdqs *cmdqs = hwdev->cmdqs; - enum sphw_cmdq_type cmdq_type; - - cmdq_type = SPHW_CMDQ_SYNC; - for (; cmdq_type < SPHW_MAX_CMDQ_TYPES; cmdq_type++) { - sphw_cmdq_flush_cmd(hwdev, &cmdqs->cmdq[cmdq_type]); - cmdq_reset_all_cmd_buff(&cmdqs->cmdq[cmdq_type]); - cmdqs->cmdq[cmdq_type].wrapped = 1; - sphw_wq_reset(&cmdqs->cmdq[cmdq_type].wq); - } - - return sphw_set_cmdq_ctxts(hwdev); -} - -static int create_cmdq_wq(struct sphw_cmdqs *cmdqs) -{ - enum sphw_cmdq_type type, cmdq_type; - int err; - - cmdq_type = SPHW_CMDQ_SYNC; - for (; cmdq_type < SPHW_MAX_CMDQ_TYPES; cmdq_type++) { - err = sphw_wq_create(cmdqs->hwdev, &cmdqs->cmdq[cmdq_type].wq, SPHW_CMDQ_DEPTH, - CMDQ_WQEBB_SIZE); - if (err) { - sdk_err(cmdqs->hwdev->dev_hdl, "Failed to create cmdq wq\n"); - goto destroy_wq; - } - } - - /* 1-level CLA must put all cmdq's wq page addr in one wq block */ - if (!WQ_IS_0_LEVEL_CLA(&cmdqs->cmdq[SPHW_CMDQ_SYNC].wq)) { - /* cmdq wq's CLA table is up to 512B */ -#define CMDQ_WQ_CLA_SIZE 512 - if (cmdqs->cmdq[SPHW_CMDQ_SYNC].wq.num_wq_pages > - CMDQ_WQ_CLA_SIZE / sizeof(u64)) { - sdk_err(cmdqs->hwdev->dev_hdl, "Cmdq wq page exceed limit: %lu\n", - CMDQ_WQ_CLA_SIZE / sizeof(u64)); - goto destroy_wq; - } - - cmdqs->wq_block_vaddr = - dma_alloc_coherent(cmdqs->hwdev->dev_hdl, PAGE_SIZE, - &cmdqs->wq_block_paddr, GFP_KERNEL); - if (!cmdqs->wq_block_vaddr) { - sdk_err(cmdqs->hwdev->dev_hdl, "Failed to alloc cmdq wq block\n"); - goto destroy_wq; - } - - type = SPHW_CMDQ_SYNC; - for (; type < SPHW_MAX_CMDQ_TYPES; type++) - memcpy((u8 *)cmdqs->wq_block_vaddr + - CMDQ_WQ_CLA_SIZE * type, - cmdqs->cmdq[type].wq.wq_block_vaddr, - cmdqs->cmdq[type].wq.num_wq_pages * sizeof(u64)); - } - - return 0; - -destroy_wq: - type = SPHW_CMDQ_SYNC; - for (; type < cmdq_type; type++) - sphw_wq_destroy(&cmdqs->cmdq[type].wq); - - return err; -} - -static void destroy_cmdq_wq(struct sphw_cmdqs *cmdqs) -{ - enum sphw_cmdq_type cmdq_type; - - if (cmdqs->wq_block_vaddr) - dma_free_coherent(cmdqs->hwdev->dev_hdl, PAGE_SIZE, - cmdqs->wq_block_vaddr, cmdqs->wq_block_paddr); - - cmdq_type = SPHW_CMDQ_SYNC; - for (; cmdq_type < SPHW_MAX_CMDQ_TYPES; cmdq_type++) - sphw_wq_destroy(&cmdqs->cmdq[cmdq_type].wq); -} - -int sphw_cmdqs_init(struct sphw_hwdev *hwdev) -{ - struct sphw_cmdqs *cmdqs = NULL; - enum sphw_cmdq_type type, cmdq_type; - int err; - - cmdqs = kzalloc(sizeof(*cmdqs), GFP_KERNEL); - if (!cmdqs) - return -ENOMEM; - - hwdev->cmdqs = cmdqs; - cmdqs->hwdev = hwdev; - - cmdqs->cmd_buf_pool = dma_pool_create("sphw_cmdq", hwdev->dev_hdl, - SPHW_CMDQ_BUF_SIZE, - SPHW_CMDQ_BUF_SIZE, 0ULL); - if (!cmdqs->cmd_buf_pool) { - sdk_err(hwdev->dev_hdl, "Failed to create cmdq buffer pool\n"); - err = -ENOMEM; - goto pool_create_err; - } - - err = create_cmdq_wq(cmdqs); - if (err) - goto create_wq_err; - - cmdq_type = SPHW_CMDQ_SYNC; - for (; cmdq_type < SPHW_MAX_CMDQ_TYPES; cmdq_type++) { - err = init_cmdq(&cmdqs->cmdq[cmdq_type], hwdev, cmdq_type); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to initialize cmdq type :%d\n", - cmdq_type); - goto init_cmdq_err; - } - - cmdq_init_queue_ctxt(cmdqs, &cmdqs->cmdq[cmdq_type], - &cmdqs->cmdq[cmdq_type].cmdq_ctxt); - } - - err = sphw_set_cmdq_ctxts(hwdev); - if (err) - goto init_cmdq_err; - - return 0; - -init_cmdq_err: - type = SPHW_CMDQ_SYNC; - for (; type < cmdq_type; type++) - free_cmdq(hwdev, &cmdqs->cmdq[type]); - - destroy_cmdq_wq(cmdqs); - -create_wq_err: - dma_pool_destroy(cmdqs->cmd_buf_pool); - -pool_create_err: - kfree(cmdqs); - - return err; -} - -void sphw_cmdqs_free(struct sphw_hwdev *hwdev) -{ - struct sphw_cmdqs *cmdqs = hwdev->cmdqs; - enum sphw_cmdq_type cmdq_type = SPHW_CMDQ_SYNC; - - cmdqs->status &= ~SPHW_CMDQ_ENABLE; - - for (; cmdq_type < SPHW_MAX_CMDQ_TYPES; cmdq_type++) { - sphw_cmdq_flush_cmd(hwdev, &cmdqs->cmdq[cmdq_type]); - cmdq_reset_all_cmd_buff(&cmdqs->cmdq[cmdq_type]); - free_cmdq(cmdqs->hwdev, &cmdqs->cmdq[cmdq_type]); - } - - destroy_cmdq_wq(cmdqs); - - dma_pool_destroy(cmdqs->cmd_buf_pool); - - kfree(cmdqs); -} diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_cmdq.h b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_cmdq.h deleted file mode 100644 index 2c1f1bbda4ad..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_cmdq.h +++ /dev/null @@ -1,195 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPHW_CMDQ_H -#define SPHW_CMDQ_H - -#include "sphw_comm_msg_intf.h" - -#define SPHW_SCMD_DATA_LEN 16 - -#define SPHW_CMDQ_DEPTH 4096 - -enum sphw_cmdq_type { - SPHW_CMDQ_SYNC, - SPHW_CMDQ_ASYNC, - SPHW_MAX_CMDQ_TYPES, -}; - -enum sphw_db_src_type { - SPHW_DB_SRC_CMDQ_TYPE, - SPHW_DB_SRC_L2NIC_SQ_TYPE, -}; - -enum sphw_cmdq_db_type { - SPHW_DB_SQ_RQ_TYPE, - SPHW_DB_CMDQ_TYPE, -}; - -/*hardware define: cmdq wqe*/ -struct sphw_cmdq_header { - u32 header_info; - u32 saved_data; -}; - -struct sphw_scmd_bufdesc { - u32 buf_len; - u32 rsvd; - u8 data[SPHW_SCMD_DATA_LEN]; -}; - -struct sphw_lcmd_bufdesc { - struct sphw_sge sge; - u32 rsvd1; - u64 saved_async_buf; - u64 rsvd3; -}; - -struct sphw_cmdq_db { - u32 db_head; - u32 db_info; -}; - -struct sphw_status { - u32 status_info; -}; - -struct sphw_ctrl { - u32 ctrl_info; -}; - -struct sphw_sge_resp { - struct sphw_sge sge; - u32 rsvd; -}; - -struct sphw_cmdq_completion { - union { - struct sphw_sge_resp sge_resp; - u64 direct_resp; - }; -}; - -struct sphw_cmdq_wqe_scmd { - struct sphw_cmdq_header header; - u64 rsvd; - struct sphw_status status; - struct sphw_ctrl ctrl; - struct sphw_cmdq_completion completion; - struct sphw_scmd_bufdesc buf_desc; -}; - -struct sphw_cmdq_wqe_lcmd { - struct sphw_cmdq_header header; - struct sphw_status status; - struct sphw_ctrl ctrl; - struct sphw_cmdq_completion completion; - struct sphw_lcmd_bufdesc buf_desc; -}; - -struct sphw_cmdq_inline_wqe { - struct sphw_cmdq_wqe_scmd wqe_scmd; -}; - -struct sphw_cmdq_wqe { - union { - struct sphw_cmdq_inline_wqe inline_wqe; - struct sphw_cmdq_wqe_lcmd wqe_lcmd; - }; -}; - -struct sphw_cmdq_arm_bit { - u32 q_type; - u32 q_id; -}; - -enum sphw_cmdq_status { - SPHW_CMDQ_ENABLE = BIT(0), -}; - -enum sphw_cmdq_cmd_type { - SPHW_CMD_TYPE_NONE, - SPHW_CMD_TYPE_SET_ARM, - SPHW_CMD_TYPE_DIRECT_RESP, - SPHW_CMD_TYPE_SGE_RESP, - SPHW_CMD_TYPE_ASYNC, - SPHW_CMD_TYPE_FAKE_TIMEOUT, - SPHW_CMD_TYPE_TIMEOUT, - SPHW_CMD_TYPE_FORCE_STOP, -}; - -struct sphw_cmdq_cmd_info { - enum sphw_cmdq_cmd_type cmd_type; - u16 channel; - - struct completion *done; - int *errcode; - int *cmpt_code; - u64 *direct_resp; - u64 cmdq_msg_id; - - struct sphw_cmd_buf *buf_in; - struct sphw_cmd_buf *buf_out; -}; - -struct sphw_cmdq { - struct sphw_wq wq; - - enum sphw_cmdq_type cmdq_type; - int wrapped; - - /* spinlock for send cmdq commands */ - spinlock_t cmdq_lock; - - /* doorbell area */ - u8 __iomem *db_base; - - struct cmdq_ctxt_info cmdq_ctxt; - - struct sphw_cmdq_cmd_info *cmd_infos; - - struct sphw_hwdev *hwdev; -}; - -struct sphw_cmdqs { - struct sphw_hwdev *hwdev; - - struct pci_pool *cmd_buf_pool; - - /* All cmdq's CLA of a VF occupy a PAGE when cmdq wq is 1-level CLA */ - dma_addr_t wq_block_paddr; - void *wq_block_vaddr; - struct sphw_cmdq cmdq[SPHW_MAX_CMDQ_TYPES]; - - u32 status; - u32 disable_flag; - - bool lock_channel_en; - unsigned long channel_stop; -}; - -enum sphw_set_arm_type { - SPHW_SET_ARM_CMDQ, - SPHW_SET_ARM_SQ, - SPHW_SET_ARM_TYPE_NUM, -}; - -int sphw_set_arm_bit(void *hwdev, enum sphw_set_arm_type q_type, u16 q_id); - -void sphw_cmdq_ceq_handler(void *hwdev, u32 ceqe_data); - -int sphw_reinit_cmdq_ctxts(struct sphw_hwdev *hwdev); - -bool sphw_cmdq_idle(struct sphw_cmdq *cmdq); - -int sphw_cmdqs_init(struct sphw_hwdev *hwdev); - -void sphw_cmdqs_free(struct sphw_hwdev *hwdev); - -void sphw_cmdq_flush_cmd(struct sphw_hwdev *hwdev, struct sphw_cmdq *cmdq); - -int sphw_cmdq_set_channel_status(struct sphw_hwdev *hwdev, u16 channel, bool enable); - -void sphw_cmdq_enable_channel_lock(struct sphw_hwdev *hwdev, bool enable); - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_comm_cmd.h b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_comm_cmd.h deleted file mode 100644 index d0e4c87942b5..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_comm_cmd.h +++ /dev/null @@ -1,60 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPHW_COMMON_CMD_H -#define SPHW_COMMON_CMD_H - -/* COMM Commands between Driver to MPU */ -enum sphw_mgmt_cmd { - COMM_MGMT_CMD_FUNC_RESET = 0, - COMM_MGMT_CMD_FEATURE_NEGO, - COMM_MGMT_CMD_FLUSH_DOORBELL, - COMM_MGMT_CMD_START_FLUSH, - COMM_MGMT_CMD_SET_FUNC_FLR, - COMM_MGMT_CMD_GET_GLOBAL_ATTR, - - COMM_MGMT_CMD_SET_CMDQ_CTXT = 20, - COMM_MGMT_CMD_SET_VAT, - COMM_MGMT_CMD_CFG_PAGESIZE, - COMM_MGMT_CMD_CFG_MSIX_CTRL_REG, - COMM_MGMT_CMD_SET_CEQ_CTRL_REG, - COMM_MGMT_CMD_SET_DMA_ATTR, - - COMM_MGMT_CMD_GET_MQM_FIX_INFO = 40, - COMM_MGMT_CMD_SET_MQM_CFG_INFO, - COMM_MGMT_CMD_SET_MQM_SRCH_GPA, - COMM_MGMT_CMD_SET_PPF_TMR, - COMM_MGMT_CMD_SET_PPF_HT_GPA, - COMM_MGMT_CMD_SET_FUNC_TMR_BITMAT, - - COMM_MGMT_CMD_GET_FW_VERSION = 60, - COMM_MGMT_CMD_GET_BOARD_INFO, - COMM_MGMT_CMD_SYNC_TIME, - COMM_MGMT_CMD_GET_HW_PF_INFOS, - COMM_MGMT_CMD_SEND_BDF_INFO, - COMM_MGMT_CMD_GET_VIRTIO_BDF_INFO, - - COMM_MGMT_CMD_UPDATE_FW = 80, - COMM_MGMT_CMD_ACTIVE_FW, - COMM_MGMT_CMD_HOT_ACTIVE_FW, - COMM_MGMT_CMD_HOT_ACTIVE_DONE_NOTICE, - COMM_MGMT_CMD_SWITCH_CFG, - COMM_MGMT_CMD_CHECK_FLASH, - COMM_MGMT_CMD_CHECK_FLASH_RW, - COMM_MGMT_CMD_RESOURCE_CFG, - - COMM_MGMT_CMD_FAULT_REPORT = 100, - COMM_MGMT_CMD_WATCHDOG_INFO, - COMM_MGMT_CMD_MGMT_RESET, - COMM_MGMT_CMD_FFM_SET, - - COMM_MGMT_CMD_GET_LOG = 120, - COMM_MGMT_CMD_TEMP_OP, - COMM_MGMT_CMD_EN_AUTO_RST_CHIP, - COMM_MGMT_CMD_CFG_REG, - COMM_MGMT_CMD_GET_CHIP_ID, - COMM_MGMT_CMD_SYSINFO_DFX, - COMM_MGMT_CMD_PCIE_DFX_NTC, -}; - -#endif /* SPHW_COMMON_CMD_H */ diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_comm_msg_intf.h b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_comm_msg_intf.h deleted file mode 100644 index fd12a47e5bb5..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_comm_msg_intf.h +++ /dev/null @@ -1,273 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPHW_COMM_MSG_INTF_H -#define SPHW_COMM_MSG_INTF_H - -#include "sphw_mgmt_msg_base.h" - -#define FUNC_RESET_FLAG_MAX_VALUE ((1U << (RES_TYPE_IPSEC + 1)) - 1) -struct comm_cmd_func_reset { - struct mgmt_msg_head head; - - u16 func_id; - u16 rsvd1[3]; - u64 reset_flag; -}; - -enum { - COMM_F_API_CHAIN = 1U << 0, -}; - -#define COMM_MAX_FEATURE_QWORD 4 -struct comm_cmd_feature_nego { - struct mgmt_msg_head head; - - u16 func_id; - u8 opcode; /* 1: set, 0: get */ - u8 rsvd; - u64 s_feature[COMM_MAX_FEATURE_QWORD]; -}; - -struct comm_cmd_clear_doorbell { - struct mgmt_msg_head head; - - u16 func_id; - u16 rsvd1[3]; -}; - -struct comm_cmd_clear_resource { - struct mgmt_msg_head head; - - u16 func_id; - u16 rsvd1[3]; -}; - -struct comm_global_attr { - u8 max_host_num; - u8 max_pf_num; - u16 vf_id_start; - - u8 mgmt_host_node_id; /* for api cmd to mgmt cpu */ - u8 rsvd1[3]; - - u32 rsvd2[8]; -}; - -struct comm_cmd_get_glb_attr { - struct mgmt_msg_head head; - - struct comm_global_attr attr; -}; - -enum sphw_fw_ver_type { - SPHW_FW_VER_TYPE_BOOT, - SPHW_FW_VER_TYPE_MPU, - SPHW_FW_VER_TYPE_NPU, - SPHW_FW_VER_TYPE_SMU, - SPHW_FW_VER_TYPE_CFG, -}; - -#define SPHW_FW_VERSION_LEN 16 -#define SPHW_FW_COMPILE_TIME_LEN 20 -struct comm_cmd_get_fw_version { - struct mgmt_msg_head head; - - u16 fw_type; - u16 rsvd1; - u8 ver[SPHW_FW_VERSION_LEN]; - u8 time[SPHW_FW_COMPILE_TIME_LEN]; -}; - -/* hardware define: cmdq context */ -struct cmdq_ctxt_info { - u64 curr_wqe_page_pfn; - u64 wq_block_pfn; -}; - -struct comm_cmd_cmdq_ctxt { - struct mgmt_msg_head head; - - u16 func_id; - u8 cmdq_id; - u8 rsvd1[5]; - - struct cmdq_ctxt_info ctxt; -}; - -struct comm_cmd_root_ctxt { - struct mgmt_msg_head head; - - u16 func_id; - u8 set_cmdq_depth; - u8 cmdq_depth; - u16 rx_buf_sz; - u8 lro_en; - u8 rsvd1; - u16 sq_depth; - u16 rq_depth; - u64 rsvd2; -}; - -struct comm_cmd_wq_page_size { - struct mgmt_msg_head head; - - u16 func_id; - u8 opcode; - /* real_size=4KB*2^page_size, range(0~20) must be checked by driver */ - u8 page_size; - - u32 rsvd1; -}; - -struct comm_cmd_msix_config { - struct mgmt_msg_head head; - - u16 func_id; - u8 opcode; - u8 rsvd1; - u16 msix_index; - u8 pending_cnt; - u8 coalesce_timer_cnt; - u8 resend_timer_cnt; - u8 lli_timer_cnt; - u8 lli_credit_cnt; - u8 rsvd2[5]; -}; - -struct comm_cmd_dma_attr_config { - struct mgmt_msg_head head; - - u16 func_id; - u8 entry_idx; - u8 st; - u8 at; - u8 ph; - u8 no_snooping; - u8 tph_en; - u32 resv1; -}; - -struct comm_cmd_ceq_ctrl_reg { - struct mgmt_msg_head head; - - u16 func_id; - u16 q_id; - u32 ctrl0; - u32 ctrl1; - u32 rsvd1; -}; - -struct comm_cmd_func_tmr_bitmap_op { - struct mgmt_msg_head head; - - u16 func_id; - u8 opcode; /* 1: start, 0: stop */ - u8 rsvd1[5]; -}; - -struct comm_cmd_ppf_tmr_op { - struct mgmt_msg_head head; - - u8 ppf_id; - u8 opcode; /* 1: start, 0: stop */ - u8 rsvd1[6]; -}; - -struct comm_cmd_ht_gpa { - struct mgmt_msg_head head; - - u8 host_id; - u32 rsvd1[7]; - u64 page_pa0; - u64 page_pa1; -}; - -struct comm_cmd_get_eqm_num { - struct mgmt_msg_head head; - - u8 host_id; - u8 rsvd1[3]; - u32 chunk_num; - u32 search_gpa_num; -}; - -struct comm_cmd_eqm_cfg { - struct mgmt_msg_head head; - - u8 host_id; - u8 valid; - u16 rsvd1; - u32 page_size; - u32 rsvd2; -}; - -struct comm_cmd_eqm_search_gpa { - struct mgmt_msg_head head; - - u8 host_id; - u8 rsvd1[3]; - u32 start_idx; - u32 num; - u32 rsvd2; - u64 gpa_hi52[0]; -}; - -struct comm_cmd_ffm_info { - struct mgmt_msg_head head; - - u8 node_id; - /* error level of the interrupt source */ - u8 err_level; - /* Classification by interrupt source properties */ - u16 err_type; - u32 err_csr_addr; - u32 err_csr_value; - u32 rsvd1; -}; - -struct sphw_board_info { - u8 board_type; - u8 port_num; - u8 port_speed; - u8 pcie_width; - u8 host_num; - u8 pf_num; - u16 vf_total_num; - u8 tile_num; - u8 qcm_num; - u8 core_num; - u8 work_mode; - u8 service_mode; - u8 pcie_mode; - u8 boot_sel; - u8 board_id; - u32 cfg_addr; -}; - -struct comm_cmd_board_info { - struct mgmt_msg_head head; - - struct sphw_board_info info; - u32 rsvd[25]; -}; - -struct comm_cmd_sync_time { - struct mgmt_msg_head head; - - u64 mstime; - u64 rsvd1; -}; - -struct comm_cmd_bdf_info { - struct mgmt_msg_head head; - - u16 function_idx; - u8 rsvd1[2]; - u8 bus; - u8 device; - u8 function; - u8 rsvd2[5]; -}; - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_common.c b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_common.c deleted file mode 100644 index aaba9e68ba31..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_common.c +++ /dev/null @@ -1,88 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#include <linux/kernel.h> -#include <linux/dma-mapping.h> -#include <linux/delay.h> - -#include "sphw_common.h" - -int sphw_dma_alloc_coherent_align(void *dev_hdl, u64 size, u64 align, unsigned int flag, - struct sphw_dma_addr_align *mem_align) -{ - void *vaddr = NULL, *align_vaddr = NULL; - dma_addr_t paddr, align_paddr; - u64 real_size = size; - - vaddr = dma_alloc_coherent(dev_hdl, real_size, &paddr, flag); - if (!vaddr) - return -ENOMEM; - - align_paddr = ALIGN(paddr, align); - /* align */ - if (align_paddr == paddr) { - align_vaddr = vaddr; - goto out; - } - - dma_free_coherent(dev_hdl, real_size, vaddr, paddr); - - /* realloc memory for align */ - real_size = size + align; - vaddr = dma_alloc_coherent(dev_hdl, real_size, &paddr, flag); - if (!vaddr) - return -ENOMEM; - - align_paddr = ALIGN(paddr, align); - align_vaddr = (void *)((u64)vaddr + (align_paddr - paddr)); - -out: - mem_align->real_size = (u32)real_size; - mem_align->ori_vaddr = vaddr; - mem_align->ori_paddr = paddr; - mem_align->align_vaddr = align_vaddr; - mem_align->align_paddr = align_paddr; - - return 0; -} - -void sphw_dma_free_coherent_align(void *dev_hdl, struct sphw_dma_addr_align *mem_align) -{ - dma_free_coherent(dev_hdl, mem_align->real_size, - mem_align->ori_vaddr, mem_align->ori_paddr); -} - -int sphw_wait_for_timeout(void *priv_data, wait_cpl_handler handler, - u32 wait_total_ms, u32 wait_once_us) -{ - enum sphw_wait_return ret; - unsigned long end; - /* Take 9/10 * wait_once_us as the minimum sleep time of usleep_range */ - u32 usleep_min = wait_once_us - wait_once_us / 10; - - if (!handler) - return -EINVAL; - - end = jiffies + msecs_to_jiffies(wait_total_ms); - do { - ret = handler(priv_data); - if (ret == WAIT_PROCESS_CPL) - return 0; - else if (ret == WAIT_PROCESS_ERR) - return -EIO; - - /* Sleep more than 20ms using msleep is accurate */ - if (wait_once_us >= 20 * USEC_PER_MSEC) - msleep(wait_once_us / USEC_PER_MSEC); - else - usleep_range(usleep_min, wait_once_us); - } while (time_before(jiffies, end)); - - ret = handler(priv_data); - if (ret == WAIT_PROCESS_CPL) - return 0; - else if (ret == WAIT_PROCESS_ERR) - return -EIO; - - return -ETIMEDOUT; -} diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_common.h b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_common.h deleted file mode 100644 index 05327bd4bcfe..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_common.h +++ /dev/null @@ -1,106 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPHW_COMMON_H -#define SPHW_COMMON_H - -#include <linux/types.h> - -struct sphw_dma_addr_align { - u32 real_size; - - void *ori_vaddr; - dma_addr_t ori_paddr; - - void *align_vaddr; - dma_addr_t align_paddr; -}; - -int sphw_dma_alloc_coherent_align(void *dev_hdl, u64 size, u64 align, unsigned int flag, - struct sphw_dma_addr_align *mem_align); - -void sphw_dma_free_coherent_align(void *dev_hdl, struct sphw_dma_addr_align *mem_align); - -enum sphw_wait_return { - WAIT_PROCESS_CPL = 0, - WAIT_PROCESS_WAITING = 1, - WAIT_PROCESS_ERR = 2, -}; - -typedef enum sphw_wait_return (*wait_cpl_handler)(void *priv_data); - -int sphw_wait_for_timeout(void *priv_data, wait_cpl_handler handler, - u32 wait_total_ms, u32 wait_once_us); - -/* * - * sphw_cpu_to_be32 - convert data to big endian 32 bit format - * @data: the data to convert - * @len: length of data to convert, must be Multiple of 4B - */ -static inline void sphw_cpu_to_be32(void *data, int len) -{ - int i, chunk_sz = sizeof(u32); - u32 *mem = data; - - if (!data) - return; - - len = len / chunk_sz; - - for (i = 0; i < len; i++) { - *mem = cpu_to_be32(*mem); - mem++; - } -} - -/* * - * sphw_cpu_to_be32 - convert data from big endian 32 bit format - * @data: the data to convert - * @len: length of data to convert - */ -static inline void sphw_be32_to_cpu(void *data, int len) -{ - int i, chunk_sz = sizeof(u32); - u32 *mem = data; - - if (!data) - return; - - len = len / chunk_sz; - - for (i = 0; i < len; i++) { - *mem = be32_to_cpu(*mem); - mem++; - } -} - -struct sphw_sge { - u32 hi_addr; - u32 lo_addr; - u32 len; -}; - -/* * - * sphw_set_sge - set dma area in scatter gather entry - * @sge: scatter gather entry - * @addr: dma address - * @len: length of relevant data in the dma address - */ -static inline void sphw_set_sge(struct sphw_sge *sge, dma_addr_t addr, int len) -{ - sge->hi_addr = upper_32_bits(addr); - sge->lo_addr = lower_32_bits(addr); - sge->len = len; -} - -#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__) - -#define nic_err(dev, format, ...) dev_err(dev, "[NIC]" format, ##__VA_ARGS__) -#define nic_warn(dev, format, ...) dev_warn(dev, "[NIC]" format, ##__VA_ARGS__) -#define nic_notice(dev, format, ...) dev_notice(dev, "[NIC]" format, ##__VA_ARGS__) -#define nic_info(dev, format, ...) dev_info(dev, "[NIC]" format, ##__VA_ARGS__) - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_crm.h b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_crm.h deleted file mode 100644 index 8cce36698e3d..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_crm.h +++ /dev/null @@ -1,982 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPHW_CRM_H -#define SPHW_CRM_H - -#define ARRAY_LEN(arr) ((int)((int)sizeof(arr) / (int)sizeof((arr)[0]))) - -#define SPHW_MGMT_VERSION_MAX_LEN 32 - -#define SPHW_FW_VERSION_NAME 16 -#define SPHW_FW_VERSION_SECTION_CNT 4 -#define SPHW_FW_VERSION_SECTION_BORDER 0xFF -struct sphw_fw_version { - u8 mgmt_ver[SPHW_FW_VERSION_NAME]; - u8 microcode_ver[SPHW_FW_VERSION_NAME]; - u8 boot_ver[SPHW_FW_VERSION_NAME]; -}; - -#define SPHW_MGMT_CMD_UNSUPPORTED 0xFF - -/* show each drivers only such as nic_service_cap, - * toe_service_cap structure, but not show service_cap - */ -enum sphw_service_type { - SERVICE_T_NIC = 0, - SERVICE_T_OVS, - SERVICE_T_ROCE, - SERVICE_T_TOE, - SERVICE_T_IOE, - SERVICE_T_FC, - SERVICE_T_VBS, - SERVICE_T_IPSEC, - SERVICE_T_VIRTIO, - SERVICE_T_MIGRATE, - SERVICE_T_MAX, - - /* Only used for interruption resource management, - * mark the request module - */ - SERVICE_T_INTF = (1 << 15), - SERVICE_T_CQM = (1 << 16), -}; - -struct nic_service_cap { - u16 max_sqs; - u16 max_rqs; -}; - -/* PF/VF ToE service resource structure */ -struct dev_toe_svc_cap { - /* PF resources */ - u32 max_pctxs; /* Parent Context: max specifications 1M */ - u32 max_cqs; - u16 max_srqs; - u32 srq_id_start; - u32 max_mpts; -}; - -/* ToE services */ -struct toe_service_cap { - struct dev_toe_svc_cap dev_toe_cap; - - bool alloc_flag; - u32 pctx_sz; /* 1KB */ - u32 scqc_sz; /* 64B */ -}; - -/* PF FC service resource structure defined */ -struct dev_fc_svc_cap { - /* PF Parent QPC */ - u32 max_parent_qpc_num; /* max number is 2048 */ - - /* PF Child QPC */ - u32 max_child_qpc_num; /* max number is 2048 */ - u32 child_qpc_id_start; - - /* PF SCQ */ - u32 scq_num; /* 16 */ - - /* PF supports SRQ */ - u32 srq_num; /* Number of SRQ is 2 */ - - u8 vp_id_start; - u8 vp_id_end; -}; - -/* FC services */ -struct fc_service_cap { - struct dev_fc_svc_cap dev_fc_cap; - - /* Parent QPC */ - u32 parent_qpc_size; /* 256B */ - - /* Child QPC */ - u32 child_qpc_size; /* 256B */ - - /* SQ */ - u32 sqe_size; /* 128B(in linked list mode) */ - - /* SCQ */ - u32 scqc_size; /* Size of the Context 32B */ - u32 scqe_size; /* 64B */ - - /* SRQ */ - u32 srqc_size; /* Size of SRQ Context (64B) */ - u32 srqe_size; /* 32B */ -}; - -struct dev_roce_svc_own_cap { - u32 max_qps; - u32 max_cqs; - u32 max_srqs; - u32 max_mpts; - u32 max_drc_qps; - - u32 cmtt_cl_start; - u32 cmtt_cl_end; - u32 cmtt_cl_sz; - - u32 dmtt_cl_start; - u32 dmtt_cl_end; - u32 dmtt_cl_sz; - - u32 wqe_cl_start; - u32 wqe_cl_end; - u32 wqe_cl_sz; - - u32 qpc_entry_sz; - u32 max_wqes; - u32 max_rq_sg; - u32 max_sq_inline_data_sz; - u32 max_rq_desc_sz; - - u32 rdmarc_entry_sz; - u32 max_qp_init_rdma; - u32 max_qp_dest_rdma; - - u32 max_srq_wqes; - u32 reserved_srqs; - u32 max_srq_sge; - u32 srqc_entry_sz; - - u32 max_msg_sz; /* Message size 2GB */ -}; - -/* RDMA service capability structure */ -struct dev_rdma_svc_cap { - /* ROCE service unique parameter structure */ - struct dev_roce_svc_own_cap roce_own_cap; -}; - -/* Defines the RDMA service capability flag */ -enum { - RDMA_BMME_FLAG_LOCAL_INV = (1 << 0), - RDMA_BMME_FLAG_REMOTE_INV = (1 << 1), - RDMA_BMME_FLAG_FAST_REG_WR = (1 << 2), - RDMA_BMME_FLAG_RESERVED_LKEY = (1 << 3), - RDMA_BMME_FLAG_TYPE_2_WIN = (1 << 4), - RDMA_BMME_FLAG_WIN_TYPE_2B = (1 << 5), - - RDMA_DEV_CAP_FLAG_XRC = (1 << 6), - RDMA_DEV_CAP_FLAG_MEM_WINDOW = (1 << 7), - RDMA_DEV_CAP_FLAG_ATOMIC = (1 << 8), - RDMA_DEV_CAP_FLAG_APM = (1 << 9), -}; - -/* RDMA services */ -struct rdma_service_cap { - struct dev_rdma_svc_cap dev_rdma_cap; - - u8 log_mtt; /* 1. the number of MTT PA must be integer power of 2 - * 2. represented by logarithm. Each MTT table can - * contain 1, 2, 4, 8, and 16 PA) - */ - /* todo: need to check whether related to max_mtt_seg */ - u32 num_mtts; /* Number of MTT table (4M), - * is actually MTT seg number - */ - u32 log_mtt_seg; - u32 mtt_entry_sz; /* MTT table size 8B, including 1 PA(64bits) */ - u32 mpt_entry_sz; /* MPT table size (64B) */ - - u32 dmtt_cl_start; - u32 dmtt_cl_end; - u32 dmtt_cl_sz; - - u8 log_rdmarc; /* 1. the number of RDMArc PA must be integer power of 2 - * 2. represented by logarithm. Each MTT table can - * contain 1, 2, 4, 8, and 16 PA) - */ - - u32 reserved_qps; /* Number of reserved QP */ - u32 max_sq_sg; /* Maximum SGE number of SQ (8) */ - u32 max_sq_desc_sz; /* WQE maximum size of SQ(1024B), inline maximum - * size if 960B(944B aligned to the 960B), - * 960B=>wqebb alignment=>1024B - */ - u32 wqebb_size; /* Currently, the supports 64B and 128B, - * defined as 64Bytes - */ - - u32 max_cqes; /* Size of the depth of the CQ (64K-1) */ - u32 reserved_cqs; /* Number of reserved CQ */ - u32 cqc_entry_sz; /* Size of the CQC (64B/128B) */ - u32 cqe_size; /* Size of CQE (32B) */ - - u32 reserved_mrws; /* Number of reserved MR/MR Window */ - - u32 max_fmr_maps; /* max MAP of FMR, - * (1 << (32-ilog2(num_mpt)))-1; - */ - - /* todo: max value needs to be confirmed */ - /* MTT table number of Each MTT seg(3) */ - - u32 log_rdmarc_seg; /* table number of each RDMArc seg(3) */ - - /* Timeout time. Formula:Tr=4.096us*2(local_ca_ack_delay), [Tr,4Tr] */ - u32 local_ca_ack_delay; - u32 num_ports; /* Physical port number */ - - u32 db_page_size; /* Size of the DB (4KB) */ - u32 direct_wqe_size; /* Size of the DWQE (256B) */ - - u32 num_pds; /* Maximum number of PD (128K) */ - u32 reserved_pds; /* Number of reserved PD */ - u32 max_xrcds; /* Maximum number of xrcd (64K) */ - u32 reserved_xrcds; /* Number of reserved xrcd */ - - u32 max_gid_per_port; /* gid number (16) of each port */ - u32 gid_entry_sz; /* RoCE v2 GID table is 32B, - * compatible RoCE v1 expansion - */ - - u32 reserved_lkey; /* local_dma_lkey */ - u32 num_comp_vectors; /* Number of complete vector (32) */ - u32 page_size_cap; /* Supports 4K,8K,64K,256K,1M and 4M page_size */ - - u32 flags; /* RDMA some identity */ - u32 max_frpl_len; /* Maximum number of pages frmr registration */ - u32 max_pkeys; /* Number of supported pkey group */ -}; - -/* PF OVS service resource structure defined */ -struct dev_ovs_svc_cap { - u32 max_pctxs; /* Parent Context: max specifications 1M */ - u8 dynamic_qp_en; - u8 fake_vf_num; - u16 fake_vf_start_id; -}; - -/* OVS services */ -struct ovs_service_cap { - struct dev_ovs_svc_cap dev_ovs_cap; - - u32 pctx_sz; /* 512B */ -}; - -/* PF IPsec service resource structure defined */ -struct dev_ipsec_svc_cap { - /* PF resources */ - u32 max_sa_ctxs; /* Parent Context: max specifications 8192 */ -}; - -/* IPsec services */ -struct ipsec_service_cap { - struct dev_ipsec_svc_cap dev_ipsec_cap; - u32 sactx_sz; /* 512B */ -}; - -/* Defines the IRQ information structure */ -struct irq_info { - u16 msix_entry_idx; /* IRQ corresponding index number */ - u32 irq_id; /* the IRQ number from OS */ -}; - -struct interrupt_info { - u32 lli_set; - u32 interrupt_coalesc_set; - u16 msix_index; - u8 lli_credit_limit; - u8 lli_timer_cfg; - u8 pending_limt; - u8 coalesc_timer_cfg; - u8 resend_timer_cfg; -}; - -enum sphw_msix_state { - SPHW_MSIX_ENABLE, - SPHW_MSIX_DISABLE, -}; - -enum sphw_msix_auto_mask { - SPHW_SET_MSIX_AUTO_MASK, - SPHW_CLR_MSIX_AUTO_MASK, -}; - -enum func_type { - TYPE_PF, - TYPE_VF, - TYPE_PPF, - TYPE_UNKNOWN, -}; - -struct sphw_init_para { - /* Record spnic_pcidev or NDIS_Adapter pointer address */ - void *adapter_hdl; - /* Record pcidev or Handler pointer address - * for example: ioremap interface input parameter - */ - void *pcidev_hdl; - /* Record pcidev->dev or Handler pointer address which used to - * dma address application or dev_err print the parameter - */ - void *dev_hdl; - - /* Configure virtual address, PF is bar1, VF is bar0/1 */ - void *cfg_reg_base; - /* interrupt configuration register address, PF is bar2, VF is bar2/3 - */ - void *intr_reg_base; - /* for PF bar3 virtual address, if function is VF should set to NULL */ - void *mgmt_reg_base; - - u64 db_dwqe_len; - u64 db_base_phy; - /* the doorbell address, bar4/5 higher 4M space */ - void *db_base; - /* direct wqe 4M, follow the doorbell address space */ - void *dwqe_mapping; - void **hwdev; - void *chip_node; - /* In bmgw x86 host, driver can't send message to mgmt cpu directly, - * need to trasmit message ppf mbox to bmgw arm host. - */ - void *ppf_hwdev; -}; - -/* B200 config BAR45 4MB, DB & DWQE both 2MB */ -#define SPHW_DB_DWQE_SIZE 0x00400000 - -/* db/dwqe page size: 4K */ -#define SPHW_DB_PAGE_SIZE 0x00001000ULL -#define SPHW_DWQE_OFFSET 0x00000800ULL - -#define SPHW_DB_MAX_AREAS (SPHW_DB_DWQE_SIZE / SPHW_DB_PAGE_SIZE) - -#ifndef IFNAMSIZ -#define IFNAMSIZ 16 -#endif -#define MAX_FUNCTION_NUM 4096 -#define SPHW_MAX_COS 8 - -struct card_node { - struct list_head node; - struct list_head func_list; - char chip_name[IFNAMSIZ]; - void *log_info; - void *dbgtool_info; - void *func_handle_array[MAX_FUNCTION_NUM]; - unsigned char bus_num; - u8 func_num; - bool up_bitmap_setted; - u8 valid_up_bitmap; -}; - -#define FAULT_SHOW_STR_LEN 16 - -enum sphw_fault_source_type { - /* same as FAULT_TYPE_CHIP */ - SPHW_FAULT_SRC_HW_MGMT_CHIP = 0, - /* same as FAULT_TYPE_UCODE */ - SPHW_FAULT_SRC_HW_MGMT_UCODE, - /* same as FAULT_TYPE_MEM_RD_TIMEOUT */ - SPHW_FAULT_SRC_HW_MGMT_MEM_RD_TIMEOUT, - /* same as FAULT_TYPE_MEM_WR_TIMEOUT */ - SPHW_FAULT_SRC_HW_MGMT_MEM_WR_TIMEOUT, - /* same as FAULT_TYPE_REG_RD_TIMEOUT */ - SPHW_FAULT_SRC_HW_MGMT_REG_RD_TIMEOUT, - /* same as FAULT_TYPE_REG_WR_TIMEOUT */ - SPHW_FAULT_SRC_HW_MGMT_REG_WR_TIMEOUT, - SPHW_FAULT_SRC_SW_MGMT_UCODE, - SPHW_FAULT_SRC_MGMT_WATCHDOG, - SPHW_FAULT_SRC_MGMT_RESET = 8, - SPHW_FAULT_SRC_HW_PHY_FAULT, - SPHW_FAULT_SRC_TX_PAUSE_EXCP, - SPHW_FAULT_SRC_PCIE_LINK_DOWN = 20, - SPHW_FAULT_SRC_HOST_HEARTBEAT_LOST = 21, - SPHW_FAULT_SRC_TX_TIMEOUT, - SPHW_FAULT_SRC_TYPE_MAX, -}; - -union sphw_fault_hw_mgmt { - u32 val[4]; - /* valid only type == FAULT_TYPE_CHIP */ - struct { - u8 node_id; - /* enum sphw_fault_err_level */ - u8 err_level; - u16 err_type; - u32 err_csr_addr; - u32 err_csr_value; - /* func_id valid only if err_level == FAULT_LEVEL_SERIOUS_FLR */ - u16 func_id; - u16 rsvd2; - } chip; - - /* valid only if type == FAULT_TYPE_UCODE */ - struct { - u8 cause_id; - u8 core_id; - u8 c_id; - u8 rsvd3; - u32 epc; - u32 rsvd4; - u32 rsvd5; - } ucode; - - /* valid only if type == FAULT_TYPE_MEM_RD_TIMEOUT || - * FAULT_TYPE_MEM_WR_TIMEOUT - */ - struct { - u32 err_csr_ctrl; - u32 err_csr_data; - u32 ctrl_tab; - u32 mem_index; - } mem_timeout; - - /* valid only if type == FAULT_TYPE_REG_RD_TIMEOUT || - * FAULT_TYPE_REG_WR_TIMEOUT - */ - struct { - u32 err_csr; - u32 rsvd6; - u32 rsvd7; - u32 rsvd8; - } reg_timeout; - - struct { - /* 0: read; 1: write */ - u8 op_type; - u8 port_id; - u8 dev_ad; - u8 rsvd9; - u32 csr_addr; - u32 op_data; - u32 rsvd10; - } phy_fault; -}; - -/* defined by chip */ -struct sphw_fault_event { - /* enum sphw_fault_type */ - u8 type; - u8 fault_level; /* sdk write fault level for uld event */ - u8 rsvd0[2]; - union sphw_fault_hw_mgmt event; -}; - -struct sphw_cmd_fault_event { - u8 status; - u8 version; - u8 rsvd0[6]; - struct sphw_fault_event event; -}; - -enum sphw_event_type { - SPHW_EVENT_LINK_DOWN = 0, - SPHW_EVENT_LINK_UP = 1, - SPHW_EVENT_FAULT = 3, - SPHW_EVENT_DCB_STATE_CHANGE = 5, - SPHW_EVENT_INIT_MIGRATE_PF, - SPHW_EVENT_SRIOV_STATE_CHANGE, - SPHW_EVENT_PORT_MODULE_EVENT, - SPHW_EVENT_PCIE_LINK_DOWN, - SPHW_EVENT_HEART_LOST, -}; - -struct sphw_event_link_info { - u8 valid; - u8 port_type; - u8 autoneg_cap; - u8 autoneg_state; - u8 duplex; - u8 speed; -}; - -struct sphw_dcb_info { - u8 dcb_on; - u8 default_cos; - u8 up_cos[SPHW_MAX_COS]; -}; - -struct sphw_sriov_state_info { - u8 enable; - u16 num_vfs; -}; - -enum link_err_type { - LINK_ERR_MODULE_UNRECOGENIZED, - LINK_ERR_NUM, -}; - -enum port_module_event_type { - SPHW_PORT_MODULE_CABLE_PLUGGED, - SPHW_PORT_MODULE_CABLE_UNPLUGGED, - SPHW_PORT_MODULE_LINK_ERR, - SPHW_PORT_MODULE_MAX_EVENT, -}; - -struct sphw_port_module_event { - enum port_module_event_type type; - enum link_err_type err_type; -}; - -struct sphw_event_info { - enum sphw_event_type type; - union { - struct sphw_event_link_info link_info; - struct sphw_fault_event info; - struct sphw_dcb_info dcb_state; - struct sphw_sriov_state_info sriov_state; - struct sphw_port_module_event module_event; - }; -}; - -typedef void (*sphw_event_handler)(void *handle, struct sphw_event_info *event); - -/* * - * @brief sphw_event_register - register hardware event - * @param dev: device pointer to hwdev - * @param pri_handle: private data will be used by the callback - * @param callback: callback function - */ -void sphw_event_register(void *dev, void *pri_handle, sphw_event_handler callback); - -/* * - * @brief sphw_event_unregister - unregister hardware event - * @param dev: device pointer to hwdev - */ -void sphw_event_unregister(void *dev); - -/* * - * @brief sphw_set_msix_auto_mask_state - set msix auto mask function - * @param hwdev: device pointer to hwdev - * @param msix_idx: msix id - * @param flag: msix auto_mask flag, 1-enable, 2-clear - */ -void sphw_set_msix_auto_mask_state(void *hwdev, u16 msix_idx, enum sphw_msix_auto_mask flag); - -/* * - * @brief sphw_set_msix_state - set msix state - * @param hwdev: device pointer to hwdev - * @param msix_idx: msix id - * @param flag: msix state flag, 0-enable, 1-disable - */ -void sphw_set_msix_state(void *hwdev, u16 msix_idx, enum sphw_msix_state flag); - -/* * - * @brief sphw_misx_intr_clear_resend_bit - clear msix resend bit - * @param hwdev: device pointer to hwdev - * @param msix_idx: msix id - * @param clear_resend_en: 1-clear - */ -void sphw_misx_intr_clear_resend_bit(void *hwdev, u16 msix_idx, u8 clear_resend_en); - -/* * - * @brief sphw_set_interrupt_cfg_direct - set interrupt cfg - * @param hwdev: device pointer to hwdev - * @param interrupt_para: interrupt info - * @param channel: channel id - * @retval zero: success - * @retval non-zero: failure - */ -int sphw_set_interrupt_cfg_direct(void *hwdev, struct interrupt_info *interrupt_para, u16 channel); - -int sphw_set_interrupt_cfg(void *hwdev, struct interrupt_info interrupt_info, u16 channel); - -/* * - * @brief sphw_get_interrupt_cfg - get interrupt cfg - * @param dev: device pointer to hwdev - * @param info: interrupt info - * @param channel: channel id - * @retval zero: success - * @retval non-zero: failure - */ -int sphw_get_interrupt_cfg(void *dev, struct interrupt_info *info, u16 channel); - -/* * - * @brief sphw_alloc_irqs - alloc irq - * @param hwdev: device pointer to hwdev - * @param type: service type - * @param num: alloc number - * @param irq_info_array: alloc irq info - * @param act_num: alloc actual number - * @retval zero: success - * @retval non-zero: failure - */ -int sphw_alloc_irqs(void *hwdev, enum sphw_service_type type, u16 num, - struct irq_info *irq_info_array, u16 *act_num); - -/* * - * @brief sphw_free_irq - free irq - * @param hwdev: device pointer to hwdev - * @param type: service type - * @param irq_id: irq id - */ -void sphw_free_irq(void *hwdev, enum sphw_service_type type, u32 irq_id); - -/* * - * @brief sphw_alloc_ceqs - alloc ceqs - * @param hwdev: device pointer to hwdev - * @param type: service type - * @param num: alloc ceq number - * @param ceq_id_array: alloc ceq_id_array - * @param act_num: alloc actual number - * @retval zero: success - * @retval non-zero: failure - */ -int sphw_alloc_ceqs(void *hwdev, enum sphw_service_type type, int num, int *ceq_id_array, - int *act_num); - -/* * - * @brief sphw_free_irq - free ceq - * @param hwdev: device pointer to hwdev - * @param type: service type - * @param irq_id: ceq id - */ -void sphw_free_ceq(void *hwdev, enum sphw_service_type type, int ceq_id); - -/* * - * @brief sphw_get_pcidev_hdl - get pcidev_hdl - * @param hwdev: device pointer to hwdev - * @retval non-null: success - * @retval null: failure - */ -void *sphw_get_pcidev_hdl(void *hwdev); - -/* * - * @brief sphw_ppf_idx - get ppf id - * @param hwdev: device pointer to hwdev - * @retval ppf id - */ -u8 sphw_ppf_idx(void *hwdev); - -/* * - * @brief sphw_get_chip_present_flag - get chip present flag - * @param hwdev: device pointer to hwdev - * @retval 1: chip is present - * @retval 0: chip is absent - */ -int sphw_get_chip_present_flag(const void *hwdev); - -/* * - * @brief sphw_support_nic - function support nic - * @param hwdev: device pointer to hwdev - * @param cap: nic service capbility - * @retval true: function support nic - * @retval false: function not support nic - */ -bool sphw_support_nic(void *hwdev, struct nic_service_cap *cap); - -/* * - * @brief sphw_support_ipsec - function support ipsec - * @param hwdev: device pointer to hwdev - * @param cap: ipsec service capbility - * @retval true: function support ipsec - * @retval false: function not support ipsec - */ -bool sphw_support_ipsec(void *hwdev, struct ipsec_service_cap *cap); - -/* * - * @brief sphw_support_roce - function support roce - * @param hwdev: device pointer to hwdev - * @param cap: roce service capbility - * @retval true: function support roce - * @retval false: function not support roce - */ -bool sphw_support_roce(void *hwdev, struct rdma_service_cap *cap); - -/* * - * @brief sphw_support_fc - function support fc - * @param hwdev: device pointer to hwdev - * @param cap: fc service capbility - * @retval true: function support fc - * @retval false: function not support fc - */ -bool sphw_support_fc(void *hwdev, struct fc_service_cap *cap); - -/* * - * @brief sphw_support_rdma - function support rdma - * @param hwdev: device pointer to hwdev - * @param cap: rdma service capbility - * @retval true: function support rdma - * @retval false: function not support rdma - */ -bool sphw_support_rdma(void *hwdev, struct rdma_service_cap *cap); - -/* * - * @brief sphw_support_ovs - function support ovs - * @param hwdev: device pointer to hwdev - * @param cap: ovs service capbility - * @retval true: function support ovs - * @retval false: function not support ovs - */ -bool sphw_support_ovs(void *hwdev, struct ovs_service_cap *cap); - -/* * - * @brief sphw_support_toe - sync time to hardware - * @param hwdev: device pointer to hwdev - * @param cap: toe service capbility - * @retval zero: success - * @retval non-zero: failure - */ -bool sphw_support_toe(void *hwdev, struct toe_service_cap *cap); - -/* * - * @brief sphw_sync_time - sync time to hardware - * @param hwdev: device pointer to hwdev - * @param time: time to sync - * @retval zero: success - * @retval non-zero: failure - */ -int sphw_sync_time(void *hwdev, u64 time); - -/* * - * @brief sphw_disable_mgmt_msg_report - disable mgmt report msg - * @param hwdev: device pointer to hwdev - */ -void sphw_disable_mgmt_msg_report(void *hwdev); - -/* * - * @brief sphw_func_for_mgmt - get function service type - * @param hwdev: device pointer to hwdev - * @retval true: function for mgmt - * @retval false: function is not for mgmt - */ -bool sphw_func_for_mgmt(void *hwdev); - -/* * - * @brief sphw_set_pcie_order_cfg - set pcie order cfg - * @param handle: device pointer to hwdev - */ -void sphw_set_pcie_order_cfg(void *handle); - -/* * - * @brief sphw_init_hwdev - call to init hwdev - * @param para: device pointer to para - * @retval zero: success - * @retval non-zero: failure - */ -int sphw_init_hwdev(struct sphw_init_para *para); - -/* * - * @brief sphw_free_hwdev - free hwdev - * @param hwdev: device pointer to hwdev - */ -void sphw_free_hwdev(void *hwdev); - -/* * - * @brief sphw_detect_hw_present - detect hardware present - * @param hwdev: device pointer to hwdev - */ -void sphw_detect_hw_present(void *hwdev); - -/* * - * @brief sphw_record_pcie_error - record pcie error - * @param hwdev: device pointer to hwdev - */ -void sphw_record_pcie_error(void *hwdev); - -/* * - * @brief sphw_shutdown_hwdev - shutdown hwdev - * @param hwdev: device pointer to hwdev - */ -void sphw_shutdown_hwdev(void *hwdev); - -/* * - * @brief sphw_get_mgmt_version - get management cpu version - * @param hwdev: device pointer to hwdev - * @param mgmt_ver: output management version - * @param channel: channel id - * @retval zero: success - * @retval non-zero: failure - */ -int sphw_get_mgmt_version(void *hwdev, u8 *mgmt_ver, u8 version_size, u16 channel); - -/* * - * @brief sphw_get_fw_version - get firmware version - * @param hwdev: device pointer to hwdev - * @param fw_ver: firmware version - * @param channel: channel id - * @retval zero: success - * @retval non-zero: failure - */ -int sphw_get_fw_version(void *hwdev, struct sphw_fw_version *fw_ver, u16 channel); - -/* * - * @brief sphw_global_func_id - get global function id - * @param hwdev: device pointer to hwdev - * @retval global function id - */ -u16 sphw_global_func_id(void *hwdev); - -/* * - * @brief sphw_vector_to_eqn - vector to eq id - * @param hwdev: device pointer to hwdev - * @param type: service type - * @param vector: vertor - * @retval eq id - */ -int sphw_vector_to_eqn(void *hwdev, enum sphw_service_type type, int vector); - -/* * - * @brief sphw_glb_pf_vf_offset - get vf offset id of pf - * @param hwdev: device pointer to hwdev - * @retval vf offset id - */ -u16 sphw_glb_pf_vf_offset(void *hwdev); - -/* * - * @brief sphw_pf_id_of_vf - get pf id of vf - * @param hwdev: device pointer to hwdev - * @retval pf id - */ -u8 sphw_pf_id_of_vf(void *hwdev); - -/* * - * @brief sphw_func_type - get function type - * @param hwdev: device pointer to hwdev - * @retval function type - */ -enum func_type sphw_func_type(void *hwdev); - -/* * - * @brief sphw_host_oq_id_mask - get oq id - * @param hwdev: device pointer to hwdev - * @retval oq id - */ -u8 sphw_host_oq_id_mask(void *hwdev); - -/* * - * @brief sphw_host_id - get host id - * @param hwdev: device pointer to hwdev - * @retval host id - */ -u8 sphw_host_id(void *hwdev); - -/* * - * @brief sphw_func_max_qnum - get host total function number - * @param hwdev: device pointer to hwdev - * @retval non-zero: host total function number - * @retval zero: failure - */ -u16 sphw_host_total_func(void *hwdev); - -/* * - * @brief sphw_func_max_qnum - get max nic queue number - * @param hwdev: device pointer to hwdev - * @retval non-zero: max nic queue number - * @retval zero: failure - */ -u16 sphw_func_max_nic_qnum(void *hwdev); - -/* * - * @brief sphw_func_max_qnum - get max queue number - * @param hwdev: device pointer to hwdev - * @retval non-zero: max queue number - * @retval zero: failure - */ -u16 sphw_func_max_qnum(void *hwdev); - -/* * - * @brief sphw_er_id - get ep id - * @param hwdev: device pointer to hwdev - * @retval ep id - */ -u8 sphw_ep_id(void *hwdev); /* Obtain service_cap.ep_id */ - -/* * - * @brief sphw_er_id - get er id - * @param hwdev: device pointer to hwdev - * @retval er id - */ -u8 sphw_er_id(void *hwdev); /* Obtain service_cap.er_id */ - -/* * - * @brief sphw_physical_port_id - get physical port id - * @param hwdev: device pointer to hwdev - * @retval physical port id - */ -u8 sphw_physical_port_id(void *hwdev); /* Obtain service_cap.port_id */ - -/* * - * @brief sphw_func_max_vf - get vf number - * @param hwdev: device pointer to hwdev - * @retval non-zero: vf number - * @retval zero: failure - */ -u16 sphw_func_max_vf(void *hwdev); /* Obtain service_cap.max_vf */ - -/* @brief sphw_max_pf_num - get global max pf number - */ -u8 sphw_max_pf_num(void *hwdev); - -/* * - * @brief sphw_host_pf_num - get current host pf number - * @param hwdev: device pointer to hwdev - * @retval non-zero: pf number - * @retval zero: failure - */ -u32 sphw_host_pf_num(void *hwdev); /* Obtain service_cap.pf_num */ - -/* * - * @brief sphw_pcie_itf_id - get pcie port id - * @param hwdev: device pointer to hwdev - * @retval pcie port id - */ -u8 sphw_pcie_itf_id(void *hwdev); - -/* * - * @brief sphw_vf_in_pf - get vf offset in pf - * @param hwdev: device pointer to hwdev - * @retval vf offset in pf - */ -u8 sphw_vf_in_pf(void *hwdev); - -/* * - * @brief sphw_cos_valid_bitmap - get cos valid bitmap - * @param hwdev: device pointer to hwdev - * @retval non-zero: valid cos bit map - * @retval zero: failure - */ -u8 sphw_cos_valid_bitmap(void *hwdev); - -/* * - * @brief sphw_get_card_present_state - get card present state - * @param hwdev: device pointer to hwdev - * @param card_present_state: return card present state - * @retval zero: success - * @retval non-zero: failure - */ -int sphw_get_card_present_state(void *hwdev, bool *card_present_state); - -/* * - * @brief sphw_func_rx_tx_flush - function flush - * @param hwdev: device pointer to hwdev - * @param channel: channel id - * @retval zero: success - * @retval non-zero: failure - */ -int sphw_func_rx_tx_flush(void *hwdev, u16 channel); - -/* * - * @brief sphw_flush_mgmt_workq - when remove function should flush work queue - * @param hwdev: device pointer to hwdev - */ -void sphw_flush_mgmt_workq(void *hwdev); - -/* @brief sphw_ceq_num get toe ceq num - */ -u8 sphw_ceq_num(void *hwdev); - -/* * - * @brief sphw_intr_num get intr num - */ -u16 sphw_intr_num(void *hwdev); - -/* @brief sphw_flexq_en get flexq en - */ -u8 sphw_flexq_en(void *hwdev); - -/** - * @brief sphw_fault_event_report - report fault event - * @param hwdev: device pointer to hwdev - * @param src: fault event source, reference to enum sphw_fault_source_type - * @param level: fault level, reference to enum sphw_fault_err_level - */ -void sphw_fault_event_report(void *hwdev, u16 src, u16 level); - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_csr.h b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_csr.h deleted file mode 100644 index d283c1456615..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_csr.h +++ /dev/null @@ -1,158 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPHW_CSR_H -#define SPHW_CSR_H - -/* bit30/bit31 for bar index flag - * 00: bar0 - * 01: bar1 - * 10: bar2 - * 11: bar3 - */ -#define SPHW_CFG_REGS_FLAG 0x40000000 - -#define SPHW_MGMT_REGS_FLAG 0xC0000000 - -#define SPHW_REGS_FLAG_MAKS 0x3FFFFFFF - -#define SPHW_VF_CFG_REG_OFFSET 0x2000 - -#define SPHW_HOST_CSR_BASE_ADDR (SPHW_MGMT_REGS_FLAG + 0x6000) -#define SPHW_CSR_GLOBAL_BASE_ADDR (SPHW_MGMT_REGS_FLAG + 0x6400) - -/* HW interface registers */ -#define SPHW_CSR_FUNC_ATTR0_ADDR (SPHW_CFG_REGS_FLAG + 0x0) -#define SPHW_CSR_FUNC_ATTR1_ADDR (SPHW_CFG_REGS_FLAG + 0x4) -#define SPHW_CSR_FUNC_ATTR2_ADDR (SPHW_CFG_REGS_FLAG + 0x8) -#define SPHW_CSR_FUNC_ATTR3_ADDR (SPHW_CFG_REGS_FLAG + 0xC) -#define SPHW_CSR_FUNC_ATTR4_ADDR (SPHW_CFG_REGS_FLAG + 0x10) -#define SPHW_CSR_FUNC_ATTR5_ADDR (SPHW_CFG_REGS_FLAG + 0x14) -#define SPHW_CSR_FUNC_ATTR6_ADDR (SPHW_CFG_REGS_FLAG + 0x18) - -#define SPHW_FUNC_CSR_MAILBOX_DATA_OFF 0x80 -#define SPHW_FUNC_CSR_MAILBOX_CONTROL_OFF \ - (SPHW_CFG_REGS_FLAG + 0x0100) -#define SPHW_FUNC_CSR_MAILBOX_INT_OFFSET_OFF \ - (SPHW_CFG_REGS_FLAG + 0x0104) -#define SPHW_FUNC_CSR_MAILBOX_RESULT_H_OFF \ - (SPHW_CFG_REGS_FLAG + 0x0108) -#define SPHW_FUNC_CSR_MAILBOX_RESULT_L_OFF \ - (SPHW_CFG_REGS_FLAG + 0x010C) - -#define SPHW_PPF_ELECTION_OFFSET 0x0 -#define SPHW_MPF_ELECTION_OFFSET 0x20 - -#define SPHW_CSR_PPF_ELECTION_ADDR \ - (SPHW_HOST_CSR_BASE_ADDR + SPHW_PPF_ELECTION_OFFSET) - -#define SPHW_CSR_GLOBAL_MPF_ELECTION_ADDR \ - (SPHW_HOST_CSR_BASE_ADDR + SPHW_MPF_ELECTION_OFFSET) - -#define SPHW_CSR_FUNC_PPF_ELECT_BASE_ADDR (SPHW_CFG_REGS_FLAG + 0x60) -#define SPHW_CSR_FUNC_PPF_ELECT_PORT_STRIDE 0x4 - -#define SPHW_CSR_FUNC_PPF_ELECT(host_idx) \ - (SPHW_CSR_FUNC_PPF_ELECT_BASE_ADDR + \ - (host_idx) * SPHW_CSR_FUNC_PPF_ELECT_PORT_STRIDE) - -#define SPHW_CSR_DMA_ATTR_TBL_ADDR (SPHW_CFG_REGS_FLAG + 0x380) -#define SPHW_CSR_DMA_ATTR_INDIR_IDX_ADDR (SPHW_CFG_REGS_FLAG + 0x390) - -/* MSI-X registers */ -#define SPHW_CSR_MSIX_INDIR_IDX_ADDR (SPHW_CFG_REGS_FLAG + 0x310) -#define SPHW_CSR_MSIX_CTRL_ADDR (SPHW_CFG_REGS_FLAG + 0x300) -#define SPHW_CSR_MSIX_CNT_ADDR (SPHW_CFG_REGS_FLAG + 0x304) -#define SPHW_CSR_FUNC_MSI_CLR_WR_ADDR (SPHW_CFG_REGS_FLAG + 0x58) - -#define SPHW_MSI_CLR_INDIR_RESEND_TIMER_CLR_SHIFT 0 -#define SPHW_MSI_CLR_INDIR_INT_MSK_SET_SHIFT 1 -#define SPHW_MSI_CLR_INDIR_INT_MSK_CLR_SHIFT 2 -#define SPHW_MSI_CLR_INDIR_AUTO_MSK_SET_SHIFT 3 -#define SPHW_MSI_CLR_INDIR_AUTO_MSK_CLR_SHIFT 4 -#define SPHW_MSI_CLR_INDIR_SIMPLE_INDIR_IDX_SHIFT 22 - -#define SPHW_MSI_CLR_INDIR_RESEND_TIMER_CLR_MASK 0x1U -#define SPHW_MSI_CLR_INDIR_INT_MSK_SET_MASK 0x1U -#define SPHW_MSI_CLR_INDIR_INT_MSK_CLR_MASK 0x1U -#define SPHW_MSI_CLR_INDIR_AUTO_MSK_SET_MASK 0x1U -#define SPHW_MSI_CLR_INDIR_AUTO_MSK_CLR_MASK 0x1U -#define SPHW_MSI_CLR_INDIR_SIMPLE_INDIR_IDX_MASK 0x3FFU - -#define SPHW_MSI_CLR_INDIR_SET(val, member) \ - (((val) & SPHW_MSI_CLR_INDIR_##member##_MASK) << \ - SPHW_MSI_CLR_INDIR_##member##_SHIFT) - -/* EQ registers */ -#define SPHW_AEQ_INDIR_IDX_ADDR (SPHW_CFG_REGS_FLAG + 0x210) -#define SPHW_CEQ_INDIR_IDX_ADDR (SPHW_CFG_REGS_FLAG + 0x290) - -#define SPHW_EQ_INDIR_IDX_ADDR(type) \ - ((type == SPHW_AEQ) ? SPHW_AEQ_INDIR_IDX_ADDR : SPHW_CEQ_INDIR_IDX_ADDR) - -#define SPHW_AEQ_MTT_OFF_BASE_ADDR (SPHW_CFG_REGS_FLAG + 0x240) -#define SPHW_CEQ_MTT_OFF_BASE_ADDR (SPHW_CFG_REGS_FLAG + 0x2C0) - -#define SPHW_CSR_EQ_PAGE_OFF_STRIDE 8 - -#define SPHW_AEQ_HI_PHYS_ADDR_REG(pg_num) \ - (SPHW_AEQ_MTT_OFF_BASE_ADDR + \ - (pg_num) * SPHW_CSR_EQ_PAGE_OFF_STRIDE) - -#define SPHW_AEQ_LO_PHYS_ADDR_REG(pg_num) \ - (SPHW_AEQ_MTT_OFF_BASE_ADDR + \ - (pg_num) * SPHW_CSR_EQ_PAGE_OFF_STRIDE + 4) - -#define SPHW_CEQ_HI_PHYS_ADDR_REG(pg_num) \ - (SPHW_CEQ_MTT_OFF_BASE_ADDR + \ - (pg_num) * SPHW_CSR_EQ_PAGE_OFF_STRIDE) - -#define SPHW_CEQ_LO_PHYS_ADDR_REG(pg_num) \ - (SPHW_CEQ_MTT_OFF_BASE_ADDR + \ - (pg_num) * SPHW_CSR_EQ_PAGE_OFF_STRIDE + 4) - -#define SPHW_CSR_AEQ_CTRL_0_ADDR (SPHW_CFG_REGS_FLAG + 0x200) -#define SPHW_CSR_AEQ_CTRL_1_ADDR (SPHW_CFG_REGS_FLAG + 0x204) -#define SPHW_CSR_AEQ_CONS_IDX_ADDR (SPHW_CFG_REGS_FLAG + 0x208) -#define SPHW_CSR_AEQ_PROD_IDX_ADDR (SPHW_CFG_REGS_FLAG + 0x20C) -#define SPHW_CSR_AEQ_CI_SIMPLE_INDIR_ADDR (SPHW_CFG_REGS_FLAG + 0x50) - -#define SPHW_CSR_CEQ_CTRL_0_ADDR (SPHW_CFG_REGS_FLAG + 0x280) -#define SPHW_CSR_CEQ_CTRL_1_ADDR (SPHW_CFG_REGS_FLAG + 0x284) -#define SPHW_CSR_CEQ_CONS_IDX_ADDR (SPHW_CFG_REGS_FLAG + 0x288) -#define SPHW_CSR_CEQ_PROD_IDX_ADDR (SPHW_CFG_REGS_FLAG + 0x28c) -#define SPHW_CSR_CEQ_CI_SIMPLE_INDIR_ADDR (SPHW_CFG_REGS_FLAG + 0x54) - -/* API CMD registers */ -#define SPHW_CSR_API_CMD_BASE (SPHW_MGMT_REGS_FLAG + 0x2000) - -#define SPHW_CSR_API_CMD_STRIDE 0x80 - -#define SPHW_CSR_API_CMD_CHAIN_HEAD_HI_ADDR(idx) \ - (SPHW_CSR_API_CMD_BASE + 0x0 + (idx) * SPHW_CSR_API_CMD_STRIDE) - -#define SPHW_CSR_API_CMD_CHAIN_HEAD_LO_ADDR(idx) \ - (SPHW_CSR_API_CMD_BASE + 0x4 + (idx) * SPHW_CSR_API_CMD_STRIDE) - -#define SPHW_CSR_API_CMD_STATUS_HI_ADDR(idx) \ - (SPHW_CSR_API_CMD_BASE + 0x8 + (idx) * SPHW_CSR_API_CMD_STRIDE) - -#define SPHW_CSR_API_CMD_STATUS_LO_ADDR(idx) \ - (SPHW_CSR_API_CMD_BASE + 0xC + (idx) * SPHW_CSR_API_CMD_STRIDE) - -#define SPHW_CSR_API_CMD_CHAIN_NUM_CELLS_ADDR(idx) \ - (SPHW_CSR_API_CMD_BASE + 0x10 + (idx) * SPHW_CSR_API_CMD_STRIDE) - -#define SPHW_CSR_API_CMD_CHAIN_CTRL_ADDR(idx) \ - (SPHW_CSR_API_CMD_BASE + 0x14 + (idx) * SPHW_CSR_API_CMD_STRIDE) - -#define SPHW_CSR_API_CMD_CHAIN_PI_ADDR(idx) \ - (SPHW_CSR_API_CMD_BASE + 0x1C + (idx) * SPHW_CSR_API_CMD_STRIDE) - -#define SPHW_CSR_API_CMD_CHAIN_REQ_ADDR(idx) \ - (SPHW_CSR_API_CMD_BASE + 0x20 + (idx) * SPHW_CSR_API_CMD_STRIDE) - -#define SPHW_CSR_API_CMD_STATUS_0_ADDR(idx) \ - (SPHW_CSR_API_CMD_BASE + 0x30 + (idx) * SPHW_CSR_API_CMD_STRIDE) - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_eqs.c b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_eqs.c deleted file mode 100644 index 24c55d656f9c..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_eqs.c +++ /dev/null @@ -1,1272 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [COMM]" fmt - -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/interrupt.h> -#include <linux/workqueue.h> -#include <linux/pci.h> -#include <linux/kernel.h> -#include <linux/device.h> -#include <linux/dma-mapping.h> -#include <linux/module.h> -#include <linux/spinlock.h> -#include <linux/delay.h> - -#include "sphw_crm.h" -#include "sphw_hw.h" -#include "sphw_common.h" -#include "sphw_hwdev.h" -#include "sphw_hwif.h" -#include "sphw_hw.h" -#include "sphw_csr.h" -#include "sphw_hw_comm.h" -#include "sphw_prof_adap.h" -#include "sphw_eqs.h" - -#define SPHW_EQS_WQ_NAME "sphw_eqs" - -#define AEQ_CTRL_0_INTR_IDX_SHIFT 0 -#define AEQ_CTRL_0_DMA_ATTR_SHIFT 12 -#define AEQ_CTRL_0_PCI_INTF_IDX_SHIFT 20 -#define AEQ_CTRL_0_INTR_MODE_SHIFT 31 - -#define AEQ_CTRL_0_INTR_IDX_MASK 0x3FFU -#define AEQ_CTRL_0_DMA_ATTR_MASK 0x3FU -#define AEQ_CTRL_0_PCI_INTF_IDX_MASK 0x7U -#define AEQ_CTRL_0_INTR_MODE_MASK 0x1U - -#define AEQ_CTRL_0_SET(val, member) \ - (((val) & AEQ_CTRL_0_##member##_MASK) << \ - AEQ_CTRL_0_##member##_SHIFT) - -#define AEQ_CTRL_0_CLEAR(val, member) \ - ((val) & (~(AEQ_CTRL_0_##member##_MASK << \ - AEQ_CTRL_0_##member##_SHIFT))) - -#define AEQ_CTRL_1_LEN_SHIFT 0 -#define AEQ_CTRL_1_ELEM_SIZE_SHIFT 24 -#define AEQ_CTRL_1_PAGE_SIZE_SHIFT 28 - -#define AEQ_CTRL_1_LEN_MASK 0x1FFFFFU -#define AEQ_CTRL_1_ELEM_SIZE_MASK 0x3U -#define AEQ_CTRL_1_PAGE_SIZE_MASK 0xFU - -#define AEQ_CTRL_1_SET(val, member) \ - (((val) & AEQ_CTRL_1_##member##_MASK) << \ - AEQ_CTRL_1_##member##_SHIFT) - -#define AEQ_CTRL_1_CLEAR(val, member) \ - ((val) & (~(AEQ_CTRL_1_##member##_MASK << \ - AEQ_CTRL_1_##member##_SHIFT))) - -#define SPHW_EQ_PROD_IDX_MASK 0xFFFFF -#define SPHW_TASK_PROCESS_EQE_LIMIT 1024 -#define SPHW_EQ_UPDATE_CI_STEP 64 - -static uint g_aeq_len = SPHW_DEFAULT_AEQ_LEN; -module_param(g_aeq_len, uint, 0444); -MODULE_PARM_DESC(g_aeq_len, - "aeq depth, valid range is " __stringify(SPHW_MIN_AEQ_LEN) - " - " __stringify(SPHW_MAX_AEQ_LEN)); - -static uint g_ceq_len = SPHW_DEFAULT_CEQ_LEN; -module_param(g_ceq_len, uint, 0444); -MODULE_PARM_DESC(g_ceq_len, - "ceq depth, valid range is " __stringify(SPHW_MIN_CEQ_LEN) - " - " __stringify(SPHW_MAX_CEQ_LEN)); - -static uint g_num_ceqe_in_tasklet = SPHW_TASK_PROCESS_EQE_LIMIT; -module_param(g_num_ceqe_in_tasklet, uint, 0444); -MODULE_PARM_DESC(g_num_ceqe_in_tasklet, - "The max number of ceqe can be processed in tasklet, default = 1024"); - -#define CEQ_CTRL_0_INTR_IDX_SHIFT 0 -#define CEQ_CTRL_0_DMA_ATTR_SHIFT 12 -#define CEQ_CTRL_0_LIMIT_KICK_SHIFT 20 -#define CEQ_CTRL_0_PCI_INTF_IDX_SHIFT 24 -#define CEQ_CTRL_0_PAGE_SIZE_SHIFT 27 -#define CEQ_CTRL_0_INTR_MODE_SHIFT 31 - -#define CEQ_CTRL_0_INTR_IDX_MASK 0x3FFU -#define CEQ_CTRL_0_DMA_ATTR_MASK 0x3FU -#define CEQ_CTRL_0_LIMIT_KICK_MASK 0xFU -#define CEQ_CTRL_0_PCI_INTF_IDX_MASK 0x3U -#define CEQ_CTRL_0_PAGE_SIZE_MASK 0xF -#define CEQ_CTRL_0_INTR_MODE_MASK 0x1U - -#define CEQ_CTRL_0_SET(val, member) \ - (((val) & CEQ_CTRL_0_##member##_MASK) << \ - CEQ_CTRL_0_##member##_SHIFT) - -#define CEQ_CTRL_1_LEN_SHIFT 0 -#define CEQ_CTRL_1_GLB_FUNC_ID_SHIFT 20 - -#define CEQ_CTRL_1_LEN_MASK 0xFFFFFU -#define CEQ_CTRL_1_GLB_FUNC_ID_MASK 0xFFFU - -#define CEQ_CTRL_1_SET(val, member) \ - (((val) & CEQ_CTRL_1_##member##_MASK) << \ - CEQ_CTRL_1_##member##_SHIFT) - -#define EQ_ELEM_DESC_TYPE_SHIFT 0 -#define EQ_ELEM_DESC_SRC_SHIFT 7 -#define EQ_ELEM_DESC_SIZE_SHIFT 8 -#define EQ_ELEM_DESC_WRAPPED_SHIFT 31 - -#define EQ_ELEM_DESC_TYPE_MASK 0x7FU -#define EQ_ELEM_DESC_SRC_MASK 0x1U -#define EQ_ELEM_DESC_SIZE_MASK 0xFFU -#define EQ_ELEM_DESC_WRAPPED_MASK 0x1U - -#define EQ_ELEM_DESC_GET(val, member) \ - (((val) >> EQ_ELEM_DESC_##member##_SHIFT) & \ - EQ_ELEM_DESC_##member##_MASK) - -#define EQ_CONS_IDX_CONS_IDX_SHIFT 0 -#define EQ_CONS_IDX_INT_ARMED_SHIFT 31 - -#define EQ_CONS_IDX_CONS_IDX_MASK 0x1FFFFFU -#define EQ_CONS_IDX_INT_ARMED_MASK 0x1U - -#define EQ_CONS_IDX_SET(val, member) \ - (((val) & EQ_CONS_IDX_##member##_MASK) << \ - EQ_CONS_IDX_##member##_SHIFT) - -#define EQ_CONS_IDX_CLEAR(val, member) \ - ((val) & (~(EQ_CONS_IDX_##member##_MASK << \ - EQ_CONS_IDX_##member##_SHIFT))) - -#define EQ_CI_SIMPLE_INDIR_CI_SHIFT 0 -#define EQ_CI_SIMPLE_INDIR_ARMED_SHIFT 21 -#define EQ_CI_SIMPLE_INDIR_AEQ_IDX_SHIFT 30 -#define EQ_CI_SIMPLE_INDIR_CEQ_IDX_SHIFT 24 - -#define EQ_CI_SIMPLE_INDIR_CI_MASK 0x1FFFFFU -#define EQ_CI_SIMPLE_INDIR_ARMED_MASK 0x1U -#define EQ_CI_SIMPLE_INDIR_AEQ_IDX_MASK 0x3U -#define EQ_CI_SIMPLE_INDIR_CEQ_IDX_MASK 0xFFU - -#define EQ_CI_SIMPLE_INDIR_SET(val, member) \ - (((val) & EQ_CI_SIMPLE_INDIR_##member##_MASK) << \ - EQ_CI_SIMPLE_INDIR_##member##_SHIFT) - -#define EQ_CI_SIMPLE_INDIR_CLEAR(val, member) \ - ((val) & (~(EQ_CI_SIMPLE_INDIR_##member##_MASK << \ - EQ_CI_SIMPLE_INDIR_##member##_SHIFT))) - -#define EQ_WRAPPED(eq) ((u32)(eq)->wrapped << EQ_VALID_SHIFT) - -#define EQ_CONS_IDX(eq) ((eq)->cons_idx | \ - ((u32)(eq)->wrapped << EQ_WRAPPED_SHIFT)) - -#define EQ_CONS_IDX_REG_ADDR(eq) \ - (((eq)->type == SPHW_AEQ) ? \ - SPHW_CSR_AEQ_CONS_IDX_ADDR : \ - SPHW_CSR_CEQ_CONS_IDX_ADDR) -#define EQ_CI_SIMPLE_INDIR_REG_ADDR(eq) \ - (((eq)->type == SPHW_AEQ) ? \ - SPHW_CSR_AEQ_CI_SIMPLE_INDIR_ADDR : \ - SPHW_CSR_CEQ_CI_SIMPLE_INDIR_ADDR) - -#define EQ_PROD_IDX_REG_ADDR(eq) \ - (((eq)->type == SPHW_AEQ) ? \ - SPHW_CSR_AEQ_PROD_IDX_ADDR : \ - SPHW_CSR_CEQ_PROD_IDX_ADDR) - -#define SPHW_EQ_HI_PHYS_ADDR_REG(type, pg_num) \ - ((u32)((type == SPHW_AEQ) ? \ - SPHW_AEQ_HI_PHYS_ADDR_REG(pg_num) : \ - SPHW_CEQ_HI_PHYS_ADDR_REG(pg_num))) - -#define SPHW_EQ_LO_PHYS_ADDR_REG(type, pg_num) \ - ((u32)((type == SPHW_AEQ) ? \ - SPHW_AEQ_LO_PHYS_ADDR_REG(pg_num) : \ - SPHW_CEQ_LO_PHYS_ADDR_REG(pg_num))) - -#define GET_EQ_NUM_PAGES(eq, size) \ - ((u16)(ALIGN((u32)((eq)->eq_len * (eq)->elem_size), \ - (size)) / (size))) - -#define SPHW_EQ_MAX_PAGES(eq) \ - ((eq)->type == SPHW_AEQ ? SPHW_AEQ_MAX_PAGES : \ - SPHW_CEQ_MAX_PAGES) - -#define GET_EQ_NUM_ELEMS(eq, pg_size) ((pg_size) / (u32)(eq)->elem_size) - -#define GET_EQ_ELEMENT(eq, idx) \ - (((u8 *)(eq)->eq_pages[(idx) / (eq)->num_elem_in_pg].align_vaddr) + \ - (u32)(((idx) & ((eq)->num_elem_in_pg - 1)) * (eq)->elem_size)) - -#define GET_AEQ_ELEM(eq, idx) \ - ((struct sphw_aeq_elem *)GET_EQ_ELEMENT((eq), (idx))) - -#define GET_CEQ_ELEM(eq, idx) ((u32 *)GET_EQ_ELEMENT((eq), (idx))) - -#define GET_CURR_AEQ_ELEM(eq) GET_AEQ_ELEM((eq), (eq)->cons_idx) - -#define GET_CURR_CEQ_ELEM(eq) GET_CEQ_ELEM((eq), (eq)->cons_idx) - -#define PAGE_IN_4K(page_size) ((page_size) >> 12) -#define EQ_SET_HW_PAGE_SIZE_VAL(eq) \ - ((u32)ilog2(PAGE_IN_4K((eq)->page_size))) - -#define ELEMENT_SIZE_IN_32B(eq) (((eq)->elem_size) >> 5) -#define EQ_SET_HW_ELEM_SIZE_VAL(eq) ((u32)ilog2(ELEMENT_SIZE_IN_32B(eq))) - -#define AEQ_DMA_ATTR_DEFAULT 0 -#define CEQ_DMA_ATTR_DEFAULT 0 - -#define CEQ_LMT_KICK_DEFAULT 0 - -#define EQ_MSIX_RESEND_TIMER_CLEAR 1 - -#define EQ_WRAPPED_SHIFT 20 - -#define EQ_VALID_SHIFT 31 - -#define CEQE_TYPE_SHIFT 23 -#define CEQE_TYPE_MASK 0x7 - -#define CEQE_TYPE(type) (((type) >> CEQE_TYPE_SHIFT) & \ - CEQE_TYPE_MASK) - -#define CEQE_DATA_MASK 0x3FFFFFF -#define CEQE_DATA(data) ((data) & CEQE_DATA_MASK) - -#define aeq_to_aeqs(eq) \ - container_of((eq) - (eq)->q_id, struct sphw_aeqs, aeq[0]) - -#define ceq_to_ceqs(eq) \ - container_of((eq) - (eq)->q_id, struct sphw_ceqs, ceq[0]) - -static irqreturn_t ceq_interrupt(int irq, void *data); -static irqreturn_t aeq_interrupt(int irq, void *data); - -static void ceq_tasklet(ulong eq_tasklet); - -/** - * sphw_aeq_register_hw_cb - register aeq callback for specific event - * @hwdev: the pointer to hw device - * @event: event for the handler - * @hw_cb: callback function - **/ -int sphw_aeq_register_hw_cb(void *hwdev, enum sphw_aeq_type event, sphw_aeq_hwe_cb hwe_cb) -{ - struct sphw_aeqs *aeqs = NULL; - - if (!hwdev || !hwe_cb || event >= SPHW_MAX_AEQ_EVENTS) - return -EINVAL; - - aeqs = ((struct sphw_hwdev *)hwdev)->aeqs; - - aeqs->aeq_hwe_cb[event] = hwe_cb; - - set_bit(SPHW_AEQ_HW_CB_REG, &aeqs->aeq_hw_cb_state[event]); - - return 0; -} - -/** - * sphw_aeq_unregister_hw_cb - unregister the aeq callback for specific event - * @hwdev: the pointer to hw device - * @event: event for the handler - **/ -void sphw_aeq_unregister_hw_cb(void *hwdev, enum sphw_aeq_type event) -{ - struct sphw_aeqs *aeqs = NULL; - - if (!hwdev || event >= SPHW_MAX_AEQ_EVENTS) - return; - - aeqs = ((struct sphw_hwdev *)hwdev)->aeqs; - - clear_bit(SPHW_AEQ_HW_CB_REG, &aeqs->aeq_hw_cb_state[event]); - - while (test_bit(SPHW_AEQ_HW_CB_RUNNING, - &aeqs->aeq_hw_cb_state[event])) - usleep_range(EQ_USLEEP_LOW_BOUND, EQ_USLEEP_HIG_BOUND); - - aeqs->aeq_hwe_cb[event] = NULL; -} - -/** - * sphw_aeq_register_swe_cb - register aeq callback for sw event - * @hwdev: the pointer to hw device - * @event: soft event for the handler - * @sw_cb: callback function - **/ -int sphw_aeq_register_swe_cb(void *hwdev, enum sphw_aeq_sw_type event, sphw_aeq_swe_cb aeq_swe_cb) -{ - struct sphw_aeqs *aeqs = NULL; - - if (!hwdev || !aeq_swe_cb || event >= SPHW_MAX_AEQ_SW_EVENTS) - return -EINVAL; - - aeqs = ((struct sphw_hwdev *)hwdev)->aeqs; - - aeqs->aeq_swe_cb[event] = aeq_swe_cb; - - set_bit(SPHW_AEQ_SW_CB_REG, &aeqs->aeq_sw_cb_state[event]); - - return 0; -} - -/** - * sphw_aeq_unregister_swe_cb - unregister the aeq callback for sw event - * @hwdev: the pointer to hw device - * @event: soft event for the handler - **/ -void sphw_aeq_unregister_swe_cb(void *hwdev, enum sphw_aeq_sw_type event) -{ - struct sphw_aeqs *aeqs = NULL; - - if (!hwdev || event >= SPHW_MAX_AEQ_SW_EVENTS) - return; - - aeqs = ((struct sphw_hwdev *)hwdev)->aeqs; - - clear_bit(SPHW_AEQ_SW_CB_REG, &aeqs->aeq_sw_cb_state[event]); - - while (test_bit(SPHW_AEQ_SW_CB_RUNNING, - &aeqs->aeq_sw_cb_state[event])) - usleep_range(EQ_USLEEP_LOW_BOUND, EQ_USLEEP_HIG_BOUND); - - aeqs->aeq_swe_cb[event] = NULL; -} - -/** - * sphw_ceq_register_cb - register ceq callback for specific event - * @hwdev: the pointer to hw device - * @event: event for the handler - * @ceq_cb: callback function - **/ -int sphw_ceq_register_cb(void *hwdev, enum sphw_ceq_event event, sphw_ceq_event_cb callback) -{ - struct sphw_ceqs *ceqs = NULL; - - if (!hwdev || event >= SPHW_MAX_CEQ_EVENTS) - return -EINVAL; - - ceqs = ((struct sphw_hwdev *)hwdev)->ceqs; - - ceqs->ceq_cb[event] = callback; - - set_bit(SPHW_CEQ_CB_REG, &ceqs->ceq_cb_state[event]); - - return 0; -} - -/** - * sphw_ceq_unregister_cb - unregister ceq callback for specific event - * @hwdev: the pointer to hw device - * @event: event for the handler - **/ -void sphw_ceq_unregister_cb(void *hwdev, enum sphw_ceq_event event) -{ - struct sphw_ceqs *ceqs = NULL; - - if (!hwdev || event >= SPHW_MAX_CEQ_EVENTS) - return; - - ceqs = ((struct sphw_hwdev *)hwdev)->ceqs; - - clear_bit(SPHW_CEQ_CB_REG, &ceqs->ceq_cb_state[event]); - - while (test_bit(SPHW_CEQ_CB_RUNNING, &ceqs->ceq_cb_state[event])) - usleep_range(EQ_USLEEP_LOW_BOUND, EQ_USLEEP_HIG_BOUND); - - ceqs->ceq_cb[event] = NULL; -} - -/** - * set_eq_cons_idx - write the cons idx to the hw - * @eq: The event queue to update the cons idx for - * @cons idx: consumer index value - **/ -static void set_eq_cons_idx(struct sphw_eq *eq, u32 arm_state) -{ - u32 eq_wrap_ci, val; - u32 addr = EQ_CI_SIMPLE_INDIR_REG_ADDR(eq); - - eq_wrap_ci = EQ_CONS_IDX(eq); - val = EQ_CI_SIMPLE_INDIR_SET(arm_state, ARMED); - if (eq->type == SPHW_AEQ) { - val = val | - EQ_CI_SIMPLE_INDIR_SET(eq_wrap_ci, CI) | - EQ_CI_SIMPLE_INDIR_SET(eq->q_id, AEQ_IDX); - } else { - val = val | - EQ_CI_SIMPLE_INDIR_SET(eq_wrap_ci, CI) | - EQ_CI_SIMPLE_INDIR_SET(eq->q_id, CEQ_IDX); - } - - sphw_hwif_write_reg(eq->hwdev->hwif, addr, val); -} - -/** - * ceq_event_handler - handle for the ceq events - * @ceqs: ceqs part of the chip - * @ceqe: ceq element of the event - **/ -static void ceq_event_handler(struct sphw_ceqs *ceqs, u32 ceqe) -{ - struct sphw_hwdev *hwdev = ceqs->hwdev; - enum sphw_ceq_event event = CEQE_TYPE(ceqe); - u32 ceqe_data = CEQE_DATA(ceqe); - - if (event >= SPHW_MAX_CEQ_EVENTS) { - sdk_err(hwdev->dev_hdl, "Ceq unknown event:%d, ceqe date: 0x%x\n", - event, ceqe_data); - return; - } - - set_bit(SPHW_CEQ_CB_RUNNING, &ceqs->ceq_cb_state[event]); - - if (ceqs->ceq_cb[event] && - test_bit(SPHW_CEQ_CB_REG, &ceqs->ceq_cb_state[event])) - ceqs->ceq_cb[event](hwdev, ceqe_data); - - clear_bit(SPHW_CEQ_CB_RUNNING, &ceqs->ceq_cb_state[event]); -} - -static void aeq_elem_handler(struct sphw_eq *eq, u32 aeqe_desc) -{ - struct sphw_aeqs *aeqs = aeq_to_aeqs(eq); - struct sphw_aeq_elem *aeqe_pos; - enum sphw_aeq_type event; - enum sphw_aeq_sw_type sw_type; - u32 sw_event; - u8 data[SPHW_AEQE_DATA_SIZE], size; - - aeqe_pos = GET_CURR_AEQ_ELEM(eq); - - event = EQ_ELEM_DESC_GET(aeqe_desc, TYPE); - if (EQ_ELEM_DESC_GET(aeqe_desc, SRC)) { - sw_event = event; - sw_type = sw_event >= SPHW_NIC_FATAL_ERROR_MAX ? - SPHW_STATEFULL_EVENT : - SPHW_STATELESS_EVENT; - /* SW event uses only the first 8B */ - memcpy(data, aeqe_pos->aeqe_data, SPHW_AEQE_DATA_SIZE); - sphw_be32_to_cpu(data, SPHW_AEQE_DATA_SIZE); - set_bit(SPHW_AEQ_SW_CB_RUNNING, - &aeqs->aeq_sw_cb_state[sw_type]); - if (aeqs->aeq_swe_cb[sw_type] && - test_bit(SPHW_AEQ_SW_CB_REG, - &aeqs->aeq_sw_cb_state[sw_type])) - aeqs->aeq_swe_cb[sw_type](aeqs->hwdev, event, data); - - clear_bit(SPHW_AEQ_SW_CB_RUNNING, - &aeqs->aeq_sw_cb_state[sw_type]); - return; - } - - if (event < SPHW_MAX_AEQ_EVENTS) { - memcpy(data, aeqe_pos->aeqe_data, SPHW_AEQE_DATA_SIZE); - sphw_be32_to_cpu(data, SPHW_AEQE_DATA_SIZE); - - size = EQ_ELEM_DESC_GET(aeqe_desc, SIZE); - set_bit(SPHW_AEQ_HW_CB_RUNNING, - &aeqs->aeq_hw_cb_state[event]); - if (aeqs->aeq_hwe_cb[event] && - test_bit(SPHW_AEQ_HW_CB_REG, - &aeqs->aeq_hw_cb_state[event])) - aeqs->aeq_hwe_cb[event](aeqs->hwdev, data, size); - clear_bit(SPHW_AEQ_HW_CB_RUNNING, - &aeqs->aeq_hw_cb_state[event]); - return; - } - sdk_warn(eq->hwdev->dev_hdl, "Unknown aeq hw event %d\n", event); -} - -/** - * aeq_irq_handler - handler for the aeq event - * @eq: the async event queue of the event - **/ -static bool aeq_irq_handler(struct sphw_eq *eq) -{ - struct sphw_aeq_elem *aeqe_pos = NULL; - u32 aeqe_desc; - u32 i, eqe_cnt = 0; - - for (i = 0; i < SPHW_TASK_PROCESS_EQE_LIMIT; i++) { - aeqe_pos = GET_CURR_AEQ_ELEM(eq); - - /* Data in HW is in Big endian Format */ - aeqe_desc = be32_to_cpu(aeqe_pos->desc); - - /* HW updates wrapped bit, when it adds eq element event */ - if (EQ_ELEM_DESC_GET(aeqe_desc, WRAPPED) == eq->wrapped) - return false; - - aeq_elem_handler(eq, aeqe_desc); - - eq->cons_idx++; - - if (eq->cons_idx == eq->eq_len) { - eq->cons_idx = 0; - eq->wrapped = !eq->wrapped; - } - - if (++eqe_cnt >= SPHW_EQ_UPDATE_CI_STEP) { - eqe_cnt = 0; - set_eq_cons_idx(eq, SPHW_EQ_NOT_ARMED); - } - } - - return true; -} - -/** - * ceq_irq_handler - handler for the ceq event - * @eq: the completion event queue of the event - **/ -static bool ceq_irq_handler(struct sphw_eq *eq) -{ - struct sphw_ceqs *ceqs = ceq_to_ceqs(eq); - u32 ceqe, eqe_cnt = 0; - u32 i; - - for (i = 0; i < g_num_ceqe_in_tasklet; i++) { - ceqe = *(GET_CURR_CEQ_ELEM(eq)); - ceqe = be32_to_cpu(ceqe); - - /* HW updates wrapped bit, when it adds eq element event */ - if (EQ_ELEM_DESC_GET(ceqe, WRAPPED) == eq->wrapped) - return false; - - ceq_event_handler(ceqs, ceqe); - - eq->cons_idx++; - - if (eq->cons_idx == eq->eq_len) { - eq->cons_idx = 0; - eq->wrapped = !eq->wrapped; - } - - if (++eqe_cnt >= SPHW_EQ_UPDATE_CI_STEP) { - eqe_cnt = 0; - set_eq_cons_idx(eq, SPHW_EQ_NOT_ARMED); - } - } - - return true; -} - -static void reschedule_eq_handler(struct sphw_eq *eq) -{ - if (eq->type == SPHW_AEQ) { - struct sphw_aeqs *aeqs = aeq_to_aeqs(eq); - struct workqueue_struct *workq = aeqs->workq; - struct sphw_eq_work *aeq_work = &eq->aeq_work; - - queue_work_on(sphw_get_work_cpu_affinity(eq->hwdev, WORK_TYPE_AEQ), - workq, &aeq_work->work); - } else { - tasklet_schedule(&eq->ceq_tasklet); - } -} - -/** - * eq_irq_handler - handler for the eq event - * @data: the event queue of the event - **/ -static bool eq_irq_handler(void *data) -{ - struct sphw_eq *eq = (struct sphw_eq *)data; - bool uncompleted = false; - - if (eq->type == SPHW_AEQ) - uncompleted = aeq_irq_handler(eq); - else - uncompleted = ceq_irq_handler(eq); - - set_eq_cons_idx(eq, uncompleted ? SPHW_EQ_NOT_ARMED : - SPHW_EQ_ARMED); - - return uncompleted; -} - -/** - * eq_irq_work - eq work for the event - * @work: the work that is associated with the eq - **/ -static void eq_irq_work(struct work_struct *work) -{ - struct sphw_eq_work *aeq_work = - container_of(work, struct sphw_eq_work, work); - - if (eq_irq_handler(aeq_work->data)) - reschedule_eq_handler(aeq_work->data); -} - -/** - * aeq_interrupt - aeq interrupt handler - * @irq: irq number - * @data: the async event queue of the event - **/ -static irqreturn_t aeq_interrupt(int irq, void *data) -{ - struct sphw_eq *aeq = (struct sphw_eq *)data; - struct sphw_hwdev *hwdev = aeq->hwdev; - struct sphw_aeqs *aeqs = aeq_to_aeqs(aeq); - struct workqueue_struct *workq = aeqs->workq; - struct sphw_eq_work *aeq_work = NULL; - - /* clear resend timer cnt register */ - sphw_misx_intr_clear_resend_bit(hwdev, aeq->eq_irq.msix_entry_idx, - EQ_MSIX_RESEND_TIMER_CLEAR); - - aeq_work = &aeq->aeq_work; - aeq_work->data = aeq; - - queue_work_on(sphw_get_work_cpu_affinity(hwdev, WORK_TYPE_AEQ), - workq, &aeq_work->work); - - return IRQ_HANDLED; -} - -/** - * ceq_tasklet - ceq tasklet for the event - * @ceq_data: data that will be used by the tasklet(ceq) - **/ -static void ceq_tasklet(ulong ceq_data) -{ - struct sphw_ceq_tasklet_data *ceq_tasklet_data = - (struct sphw_ceq_tasklet_data *)ceq_data; - struct sphw_eq *eq = (struct sphw_eq *)ceq_tasklet_data->data; - - eq->soft_intr_jif = jiffies; - - if (eq_irq_handler(ceq_tasklet_data->data)) - reschedule_eq_handler(ceq_tasklet_data->data); -} - -/** - * ceq_interrupt - ceq interrupt handler - * @irq: irq number - * @data: the completion event queue of the event - **/ -static irqreturn_t ceq_interrupt(int irq, void *data) -{ - struct sphw_eq *ceq = (struct sphw_eq *)data; - struct sphw_ceq_tasklet_data *ceq_tasklet_data = NULL; - - ceq->hard_intr_jif = jiffies; - - /* clear resend timer counters */ - sphw_misx_intr_clear_resend_bit(ceq->hwdev, ceq->eq_irq.msix_entry_idx, - EQ_MSIX_RESEND_TIMER_CLEAR); - - ceq_tasklet_data = &ceq->ceq_tasklet_data; - ceq_tasklet_data->data = data; - tasklet_schedule(&ceq->ceq_tasklet); - - return IRQ_HANDLED; -} - -/** - * set_eq_ctrls - setting eq's ctrls registers - * @eq: the event queue for setting - **/ -static int set_eq_ctrls(struct sphw_eq *eq) -{ - enum sphw_eq_type type = eq->type; - struct sphw_hwif *hwif = eq->hwdev->hwif; - struct irq_info *eq_irq = &eq->eq_irq; - u32 addr, val, ctrl0, ctrl1, page_size_val, elem_size; - u32 pci_intf_idx = SPHW_PCI_INTF_IDX(hwif); - int err; - - if (type == SPHW_AEQ) { - /* set ctrl0 */ - addr = SPHW_CSR_AEQ_CTRL_0_ADDR; - - val = sphw_hwif_read_reg(hwif, addr); - - val = AEQ_CTRL_0_CLEAR(val, INTR_IDX) & - AEQ_CTRL_0_CLEAR(val, DMA_ATTR) & - AEQ_CTRL_0_CLEAR(val, PCI_INTF_IDX) & - AEQ_CTRL_0_CLEAR(val, INTR_MODE); - - ctrl0 = AEQ_CTRL_0_SET(eq_irq->msix_entry_idx, INTR_IDX) | - AEQ_CTRL_0_SET(AEQ_DMA_ATTR_DEFAULT, DMA_ATTR) | - AEQ_CTRL_0_SET(pci_intf_idx, PCI_INTF_IDX) | - AEQ_CTRL_0_SET(SPHW_INTR_MODE_ARMED, INTR_MODE); - - val |= ctrl0; - - sphw_hwif_write_reg(hwif, addr, val); - - /* set ctrl1 */ - addr = SPHW_CSR_AEQ_CTRL_1_ADDR; - - page_size_val = EQ_SET_HW_PAGE_SIZE_VAL(eq); - elem_size = EQ_SET_HW_ELEM_SIZE_VAL(eq); - - ctrl1 = AEQ_CTRL_1_SET(eq->eq_len, LEN) | - AEQ_CTRL_1_SET(elem_size, ELEM_SIZE) | - AEQ_CTRL_1_SET(page_size_val, PAGE_SIZE); - - sphw_hwif_write_reg(hwif, addr, ctrl1); - - } else { - page_size_val = EQ_SET_HW_PAGE_SIZE_VAL(eq); - ctrl0 = CEQ_CTRL_0_SET(eq_irq->msix_entry_idx, INTR_IDX) | - CEQ_CTRL_0_SET(CEQ_DMA_ATTR_DEFAULT, DMA_ATTR) | - CEQ_CTRL_0_SET(CEQ_LMT_KICK_DEFAULT, LIMIT_KICK) | - CEQ_CTRL_0_SET(pci_intf_idx, PCI_INTF_IDX) | - CEQ_CTRL_0_SET(page_size_val, PAGE_SIZE) | - CEQ_CTRL_0_SET(SPHW_INTR_MODE_ARMED, INTR_MODE); - - ctrl1 = CEQ_CTRL_1_SET(eq->eq_len, LEN); - - /* set ceq ctrl reg through mgmt cpu */ - err = sphw_set_ceq_ctrl_reg(eq->hwdev, eq->q_id, ctrl0, ctrl1); - if (err) - return err; - } - - return 0; -} - -/** - * ceq_elements_init - Initialize all the elements in the ceq - * @eq: the event queue - * @init_val: value to init with it the elements - **/ -static void ceq_elements_init(struct sphw_eq *eq, u32 init_val) -{ - u32 *ceqe = NULL; - u32 i; - - for (i = 0; i < eq->eq_len; i++) { - ceqe = GET_CEQ_ELEM(eq, i); - *(ceqe) = cpu_to_be32(init_val); - } - - wmb(); /* Write the init values */ -} - -/** - * aeq_elements_init - initialize all the elements in the aeq - * @eq: the event queue - * @init_val: value to init with it the elements - **/ -static void aeq_elements_init(struct sphw_eq *eq, u32 init_val) -{ - struct sphw_aeq_elem *aeqe = NULL; - u32 i; - - for (i = 0; i < eq->eq_len; i++) { - aeqe = GET_AEQ_ELEM(eq, i); - aeqe->desc = cpu_to_be32(init_val); - } - - wmb(); /* Write the init values */ -} - -static void eq_elements_init(struct sphw_eq *eq, u32 init_val) -{ - if (eq->type == SPHW_AEQ) - aeq_elements_init(eq, init_val); - else - ceq_elements_init(eq, init_val); -} - -/** - * alloc_eq_pages - allocate the pages for the queue - * @eq: the event queue - **/ -static int alloc_eq_pages(struct sphw_eq *eq) -{ - struct sphw_hwif *hwif = eq->hwdev->hwif; - struct sphw_dma_addr_align *eq_page = NULL; - u32 reg, init_val; - u16 pg_idx, i; - int err; - - eq->eq_pages = kcalloc(eq->num_pages, sizeof(*eq->eq_pages), - GFP_KERNEL); - if (!eq->eq_pages) { - sdk_err(eq->hwdev->dev_hdl, "Failed to alloc eq pages description\n"); - return -ENOMEM; - } - - for (pg_idx = 0; pg_idx < eq->num_pages; pg_idx++) { - eq_page = &eq->eq_pages[pg_idx]; - err = sphw_dma_alloc_coherent_align(eq->hwdev->dev_hdl, eq->page_size, - SPHW_MIN_EQ_PAGE_SIZE, GFP_KERNEL, eq_page); - if (err) { - sdk_err(eq->hwdev->dev_hdl, "Failed to alloc eq page, page index: %hu\n", - pg_idx); - goto dma_alloc_err; - } - - reg = SPHW_EQ_HI_PHYS_ADDR_REG(eq->type, pg_idx); - sphw_hwif_write_reg(hwif, reg, upper_32_bits(eq_page->align_paddr)); - - reg = SPHW_EQ_LO_PHYS_ADDR_REG(eq->type, pg_idx); - sphw_hwif_write_reg(hwif, reg, lower_32_bits(eq_page->align_paddr)); - } - - eq->num_elem_in_pg = GET_EQ_NUM_ELEMS(eq, eq->page_size); - if (eq->num_elem_in_pg & (eq->num_elem_in_pg - 1)) { - sdk_err(eq->hwdev->dev_hdl, "Number element in eq page != power of 2\n"); - err = -EINVAL; - goto dma_alloc_err; - } - init_val = EQ_WRAPPED(eq); - - eq_elements_init(eq, init_val); - - return 0; - -dma_alloc_err: - for (i = 0; i < pg_idx; i++) - sphw_dma_free_coherent_align(eq->hwdev->dev_hdl, &eq->eq_pages[i]); - - kfree(eq->eq_pages); - - return err; -} - -/** - * free_eq_pages - free the pages of the queue - * @eq: the event queue - **/ -static void free_eq_pages(struct sphw_eq *eq) -{ - u16 pg_idx; - - for (pg_idx = 0; pg_idx < eq->num_pages; pg_idx++) - sphw_dma_free_coherent_align(eq->hwdev->dev_hdl, &eq->eq_pages[pg_idx]); - - kfree(eq->eq_pages); -} - -static inline u32 get_page_size(struct sphw_eq *eq) -{ - u32 total_size; - u32 count; - - total_size = ALIGN((eq->eq_len * eq->elem_size), - SPHW_MIN_EQ_PAGE_SIZE); - - if (total_size <= (SPHW_EQ_MAX_PAGES(eq) * SPHW_MIN_EQ_PAGE_SIZE)) - return SPHW_MIN_EQ_PAGE_SIZE; - - count = (u32)(ALIGN((total_size / SPHW_EQ_MAX_PAGES(eq)), - SPHW_MIN_EQ_PAGE_SIZE) / SPHW_MIN_EQ_PAGE_SIZE); - - /* round up to nearest power of two */ - count = 1U << (u8)fls((int)(count - 1)); - - return ((u32)SPHW_MIN_EQ_PAGE_SIZE) * count; -} - -static int request_eq_irq(struct sphw_eq *eq, struct irq_info *entry) -{ - int err = 0; - - if (eq->type == SPHW_AEQ) { - struct sphw_eq_work *aeq_work = &eq->aeq_work; - - INIT_WORK(&aeq_work->work, eq_irq_work); - } else { - tasklet_init(&eq->ceq_tasklet, ceq_tasklet, - (ulong)(&eq->ceq_tasklet_data)); - } - - if (eq->type == SPHW_AEQ) { - snprintf(eq->irq_name, sizeof(eq->irq_name), - "sphw_aeq%u@pci:%s", eq->q_id, - pci_name(eq->hwdev->pcidev_hdl)); - - err = request_irq(entry->irq_id, aeq_interrupt, 0UL, - eq->irq_name, eq); - } else { - snprintf(eq->irq_name, sizeof(eq->irq_name), - "sphw_ceq%u@pci:%s", eq->q_id, - pci_name(eq->hwdev->pcidev_hdl)); - err = request_irq(entry->irq_id, ceq_interrupt, 0UL, - eq->irq_name, eq); - } - - return err; -} - -static void reset_eq(struct sphw_eq *eq) -{ - /* clear eq_len to force eqe drop in hardware */ - if (eq->type == SPHW_AEQ) - sphw_hwif_write_reg(eq->hwdev->hwif, SPHW_CSR_AEQ_CTRL_1_ADDR, 0); - else - sphw_set_ceq_ctrl_reg(eq->hwdev, eq->q_id, 0, 0); - - wmb(); /* clear eq_len before clear prod idx */ - - sphw_hwif_write_reg(eq->hwdev->hwif, EQ_PROD_IDX_REG_ADDR(eq), 0); -} - -/** - * init_eq - initialize eq - * @eq: the event queue - * @hwdev: the pointer to hw device - * @q_id: Queue id number - * @q_len: the number of EQ elements - * @type: the type of the event queue, ceq or aeq - * @entry: msix entry associated with the event queue - * Return: 0 - Success, Negative - failure - **/ -static int init_eq(struct sphw_eq *eq, struct sphw_hwdev *hwdev, u16 q_id, - u32 q_len, enum sphw_eq_type type, struct irq_info *entry) -{ - int err = 0; - - eq->hwdev = hwdev; - eq->q_id = q_id; - eq->type = type; - eq->eq_len = q_len; - - /* Indirect access should set q_id first */ - sphw_hwif_write_reg(hwdev->hwif, SPHW_EQ_INDIR_IDX_ADDR(eq->type), eq->q_id); - wmb(); /* write index before config */ - - reset_eq(eq); - - eq->cons_idx = 0; - eq->wrapped = 0; - - eq->elem_size = (type == SPHW_AEQ) ? SPHW_AEQE_SIZE : SPHW_CEQE_SIZE; - - eq->page_size = get_page_size(eq); - eq->orig_page_size = eq->page_size; - eq->num_pages = GET_EQ_NUM_PAGES(eq, eq->page_size); - if (eq->num_pages > SPHW_EQ_MAX_PAGES(eq)) { - sdk_err(hwdev->dev_hdl, "Number pages: %u too many pages for eq\n", - eq->num_pages); - return -EINVAL; - } - - err = alloc_eq_pages(eq); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to allocate pages for eq\n"); - return err; - } - - eq->eq_irq.msix_entry_idx = entry->msix_entry_idx; - eq->eq_irq.irq_id = entry->irq_id; - - err = set_eq_ctrls(eq); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to set ctrls for eq\n"); - goto init_eq_ctrls_err; - } - - set_eq_cons_idx(eq, SPHW_EQ_ARMED); - - err = request_eq_irq(eq, entry); - if (err) { - sdk_err(hwdev->dev_hdl, - "Failed to request irq for the eq, err: %d\n", err); - goto req_irq_err; - } - - sphw_set_msix_state(hwdev, entry->msix_entry_idx, SPHW_MSIX_DISABLE); - - return 0; - -init_eq_ctrls_err: -req_irq_err: - free_eq_pages(eq); - return err; -} - -/** - * remove_eq - remove eq - * @eq: the event queue - **/ -static void remove_eq(struct sphw_eq *eq) -{ - struct irq_info *entry = &eq->eq_irq; - - sphw_set_msix_state(eq->hwdev, entry->msix_entry_idx, SPHW_MSIX_DISABLE); - synchronize_irq(entry->irq_id); - - free_irq(entry->irq_id, eq); - - /* Indirect access should set q_id first */ - sphw_hwif_write_reg(eq->hwdev->hwif, SPHW_EQ_INDIR_IDX_ADDR(eq->type), eq->q_id); - - wmb(); /* write index before config */ - - if (eq->type == SPHW_AEQ) { - struct sphw_eq_work *aeq_work = &eq->aeq_work; - - cancel_work_sync(&aeq_work->work); - - /* clear eq_len to avoid hw access host memory */ - sphw_hwif_write_reg(eq->hwdev->hwif, SPHW_CSR_AEQ_CTRL_1_ADDR, 0); - } else { - tasklet_kill(&eq->ceq_tasklet); - - sphw_set_ceq_ctrl_reg(eq->hwdev, eq->q_id, 0, 0); - } - - /* update cons_idx to avoid invalid interrupt */ - eq->cons_idx = sphw_hwif_read_reg(eq->hwdev->hwif, EQ_PROD_IDX_REG_ADDR(eq)); - set_eq_cons_idx(eq, SPHW_EQ_NOT_ARMED); - - free_eq_pages(eq); -} - -/** - * sphw_aeqs_init - init all the aeqs - * @hwdev: the pointer to hw device - * @num_aeqs: number of AEQs - * @msix_entries: msix entries associated with the event queues - * Return: 0 - Success, Negative - failure - **/ -int sphw_aeqs_init(struct sphw_hwdev *hwdev, u16 num_aeqs, struct irq_info *msix_entries) -{ - struct sphw_aeqs *aeqs = NULL; - int err; - u16 i, q_id; - - if (!hwdev) - return -EINVAL; - - aeqs = kzalloc(sizeof(*aeqs), GFP_KERNEL); - if (!aeqs) - return -ENOMEM; - - hwdev->aeqs = aeqs; - aeqs->hwdev = hwdev; - aeqs->num_aeqs = num_aeqs; - aeqs->workq = alloc_workqueue(SPHW_EQS_WQ_NAME, WQ_MEM_RECLAIM, SPHW_MAX_AEQS); - if (!aeqs->workq) { - sdk_err(hwdev->dev_hdl, "Failed to initialize aeq workqueue\n"); - err = -ENOMEM; - goto create_work_err; - } - - if (g_aeq_len < SPHW_MIN_AEQ_LEN || g_aeq_len > SPHW_MAX_AEQ_LEN) { - sdk_warn(hwdev->dev_hdl, "Module Parameter g_aeq_len value %u out of range, resetting to %d\n", - g_aeq_len, SPHW_DEFAULT_AEQ_LEN); - g_aeq_len = SPHW_DEFAULT_AEQ_LEN; - } - - for (q_id = 0; q_id < num_aeqs; q_id++) { - err = init_eq(&aeqs->aeq[q_id], hwdev, q_id, g_aeq_len, - SPHW_AEQ, &msix_entries[q_id]); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to init aeq %u\n", - q_id); - goto init_aeq_err; - } - } - for (q_id = 0; q_id < num_aeqs; q_id++) - sphw_set_msix_state(hwdev, msix_entries[q_id].msix_entry_idx, SPHW_MSIX_ENABLE); - - return 0; - -init_aeq_err: - for (i = 0; i < q_id; i++) - remove_eq(&aeqs->aeq[i]); - - destroy_workqueue(aeqs->workq); - -create_work_err: - kfree(aeqs); - - return err; -} - -/** - * sphw_aeqs_free - free all the aeqs - * @hwdev: the pointer to hw device - **/ -void sphw_aeqs_free(struct sphw_hwdev *hwdev) -{ - struct sphw_aeqs *aeqs = hwdev->aeqs; - enum sphw_aeq_type aeq_event = SPHW_HW_INTER_INT; - enum sphw_aeq_sw_type sw_aeq_event = SPHW_STATELESS_EVENT; - u16 q_id; - - for (q_id = 0; q_id < aeqs->num_aeqs; q_id++) - remove_eq(&aeqs->aeq[q_id]); - - for (; sw_aeq_event < SPHW_MAX_AEQ_SW_EVENTS; sw_aeq_event++) - sphw_aeq_unregister_swe_cb(hwdev, sw_aeq_event); - - for (; aeq_event < SPHW_MAX_AEQ_EVENTS; aeq_event++) - sphw_aeq_unregister_hw_cb(hwdev, aeq_event); - - destroy_workqueue(aeqs->workq); - - kfree(aeqs); -} - -/** - * sphw_ceqs_init - init all the ceqs - * @hwdev: the pointer to hw device - * @num_ceqs: number of CEQs - * @msix_entries: msix entries associated with the event queues - * Return: 0 - Success, Negative - failure - **/ -int sphw_ceqs_init(struct sphw_hwdev *hwdev, u16 num_ceqs, struct irq_info *msix_entries) -{ - struct sphw_ceqs *ceqs; - int err; - u16 i, q_id; - - ceqs = kzalloc(sizeof(*ceqs), GFP_KERNEL); - if (!ceqs) - return -ENOMEM; - - hwdev->ceqs = ceqs; - - ceqs->hwdev = hwdev; - ceqs->num_ceqs = num_ceqs; - - if (g_ceq_len < SPHW_MIN_CEQ_LEN || g_ceq_len > SPHW_MAX_CEQ_LEN) { - sdk_warn(hwdev->dev_hdl, "Module Parameter g_ceq_len value %u out of range, resetting to %d\n", - g_ceq_len, SPHW_DEFAULT_CEQ_LEN); - g_ceq_len = SPHW_DEFAULT_CEQ_LEN; - } - - if (!g_num_ceqe_in_tasklet) { - sdk_warn(hwdev->dev_hdl, "Module Parameter g_num_ceqe_in_tasklet can not be zero, resetting to %d\n", - SPHW_TASK_PROCESS_EQE_LIMIT); - g_num_ceqe_in_tasklet = SPHW_TASK_PROCESS_EQE_LIMIT; - } - for (q_id = 0; q_id < num_ceqs; q_id++) { - err = init_eq(&ceqs->ceq[q_id], hwdev, q_id, g_ceq_len, - SPHW_CEQ, &msix_entries[q_id]); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to init ceq %u\n", - q_id); - goto init_ceq_err; - } - } - for (q_id = 0; q_id < num_ceqs; q_id++) - sphw_set_msix_state(hwdev, msix_entries[q_id].msix_entry_idx, SPHW_MSIX_ENABLE); - - return 0; - -init_ceq_err: - for (i = 0; i < q_id; i++) - remove_eq(&ceqs->ceq[i]); - - kfree(ceqs); - - return err; -} - -/** - * sphw_ceqs_free - free all the ceqs - * @hwdev: the pointer to hw device - **/ -void sphw_ceqs_free(struct sphw_hwdev *hwdev) -{ - struct sphw_ceqs *ceqs = hwdev->ceqs; - enum sphw_ceq_event ceq_event = SPHW_CMDQ; - u16 q_id; - - for (q_id = 0; q_id < ceqs->num_ceqs; q_id++) - remove_eq(&ceqs->ceq[q_id]); - - for (; ceq_event < SPHW_MAX_CEQ_EVENTS; ceq_event++) - sphw_ceq_unregister_cb(hwdev, ceq_event); - - kfree(ceqs); -} - -void sphw_get_ceq_irqs(struct sphw_hwdev *hwdev, struct irq_info *irqs, u16 *num_irqs) -{ - struct sphw_ceqs *ceqs = hwdev->ceqs; - u16 q_id; - - for (q_id = 0; q_id < ceqs->num_ceqs; q_id++) { - irqs[q_id].irq_id = ceqs->ceq[q_id].eq_irq.irq_id; - irqs[q_id].msix_entry_idx = - ceqs->ceq[q_id].eq_irq.msix_entry_idx; - } - - *num_irqs = ceqs->num_ceqs; -} - -void sphw_get_aeq_irqs(struct sphw_hwdev *hwdev, struct irq_info *irqs, u16 *num_irqs) -{ - struct sphw_aeqs *aeqs = hwdev->aeqs; - u16 q_id; - - for (q_id = 0; q_id < aeqs->num_aeqs; q_id++) { - irqs[q_id].irq_id = aeqs->aeq[q_id].eq_irq.irq_id; - irqs[q_id].msix_entry_idx = - aeqs->aeq[q_id].eq_irq.msix_entry_idx; - } - - *num_irqs = aeqs->num_aeqs; -} - -void sphw_dump_aeq_info(struct sphw_hwdev *hwdev) -{ - struct sphw_aeq_elem *aeqe_pos = NULL; - struct sphw_eq *eq = NULL; - u32 addr, ci, pi, ctrl0, idx; - int q_id; - - for (q_id = 0; q_id < hwdev->aeqs->num_aeqs; q_id++) { - eq = &hwdev->aeqs->aeq[q_id]; - /* Indirect access should set q_id first */ - sphw_hwif_write_reg(eq->hwdev->hwif, SPHW_EQ_INDIR_IDX_ADDR(eq->type), eq->q_id); - wmb(); /* write index before config */ - - addr = SPHW_CSR_AEQ_CTRL_0_ADDR; - - ctrl0 = sphw_hwif_read_reg(hwdev->hwif, addr); - - idx = sphw_hwif_read_reg(hwdev->hwif, SPHW_EQ_INDIR_IDX_ADDR(eq->type)); - - addr = EQ_CONS_IDX_REG_ADDR(eq); - ci = sphw_hwif_read_reg(hwdev->hwif, addr); - addr = EQ_PROD_IDX_REG_ADDR(eq); - pi = sphw_hwif_read_reg(hwdev->hwif, addr); - aeqe_pos = GET_CURR_AEQ_ELEM(eq); - sdk_err(hwdev->dev_hdl, "Aeq id: %d, idx: %u, ctrl0: 0x%08x, ci: 0x%08x, pi: 0x%x, work_state: 0x%x, wrap: %u, desc: 0x%x\n", - q_id, idx, ctrl0, ci, pi, work_busy(&eq->aeq_work.work), - eq->wrapped, be32_to_cpu(aeqe_pos->desc)); - } -} - -void sphw_dump_ceq_info(struct sphw_hwdev *hwdev) -{ - struct sphw_eq *eq = NULL; - u32 addr, ci, pi; - int q_id; - - for (q_id = 0; q_id < hwdev->ceqs->num_ceqs; q_id++) { - eq = &hwdev->ceqs->ceq[q_id]; - /* Indirect access should set q_id first */ - sphw_hwif_write_reg(eq->hwdev->hwif, SPHW_EQ_INDIR_IDX_ADDR(eq->type), eq->q_id); - wmb(); /* write index before config */ - - addr = EQ_CONS_IDX_REG_ADDR(eq); - ci = sphw_hwif_read_reg(hwdev->hwif, addr); - addr = EQ_PROD_IDX_REG_ADDR(eq); - pi = sphw_hwif_read_reg(hwdev->hwif, addr); - sdk_err(hwdev->dev_hdl, "Ceq id: %d, ci: 0x%08x, sw_ci: 0x%08x, pi: 0x%x, tasklet_state: 0x%lx, wrap: %u, ceqe: 0x%x\n", - q_id, ci, eq->cons_idx, pi, eq->ceq_tasklet.state, - eq->wrapped, be32_to_cpu(*(GET_CURR_CEQ_ELEM(eq)))); - - sdk_err(hwdev->dev_hdl, "Ceq last response hard interrupt time: %u\n", - jiffies_to_msecs(jiffies - eq->hard_intr_jif)); - sdk_err(hwdev->dev_hdl, "Ceq last response soft interrupt time: %u\n", - jiffies_to_msecs(jiffies - eq->soft_intr_jif)); - } -} diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_eqs.h b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_eqs.h deleted file mode 100644 index df25b5a5fdcf..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_eqs.h +++ /dev/null @@ -1,157 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPHW_EQS_H -#define SPHW_EQS_H - -#define SPHW_MAX_AEQS 4 -#define SPHW_MAX_CEQS 32 - -#define SPHW_AEQ_MAX_PAGES 4 -#define SPHW_CEQ_MAX_PAGES 8 - -#define SPHW_AEQE_SIZE 64 -#define SPHW_CEQE_SIZE 4 - -#define SPHW_AEQE_DESC_SIZE 4 -#define SPHW_AEQE_DATA_SIZE \ - (SPHW_AEQE_SIZE - SPHW_AEQE_DESC_SIZE) - -#define SPHW_DEFAULT_AEQ_LEN 4096 -#define SPHW_DEFAULT_CEQ_LEN 8192 - -#define SPHW_MIN_EQ_PAGE_SIZE 0x1000 /* min eq page size 4K Bytes */ -#define SPHW_MAX_EQ_PAGE_SIZE 0x400000 /* max eq page size 4M Bytes */ - -#define SPHW_MIN_AEQ_LEN 64 -#define SPHW_MAX_AEQ_LEN \ - ((SPHW_MAX_EQ_PAGE_SIZE / SPHW_AEQE_SIZE) * SPHW_AEQ_MAX_PAGES) - -#define SPHW_MIN_CEQ_LEN 64 -#define SPHW_MAX_CEQ_LEN \ - ((SPHW_MAX_EQ_PAGE_SIZE / SPHW_CEQE_SIZE) * SPHW_CEQ_MAX_PAGES) -#define SPHW_CEQ_ID_CMDQ 0 - -#define EQ_IRQ_NAME_LEN 64 - -#define EQ_USLEEP_LOW_BOUND 900 -#define EQ_USLEEP_HIG_BOUND 1000 - -enum sphw_eq_type { - SPHW_AEQ, - SPHW_CEQ -}; - -enum sphw_eq_intr_mode { - SPHW_INTR_MODE_ARMED, - SPHW_INTR_MODE_ALWAYS, -}; - -enum sphw_eq_ci_arm_state { - SPHW_EQ_NOT_ARMED, - SPHW_EQ_ARMED, -}; - -struct sphw_eq_work { - struct work_struct work; - void *data; -}; - -struct sphw_ceq_tasklet_data { - void *data; -}; - -struct sphw_eq { - struct sphw_hwdev *hwdev; - u16 q_id; - enum sphw_eq_type type; - u32 page_size; - u32 orig_page_size; - u32 eq_len; - - u32 cons_idx; - u16 wrapped; - - u16 elem_size; - u16 num_pages; - u32 num_elem_in_pg; - - struct irq_info eq_irq; - char irq_name[EQ_IRQ_NAME_LEN]; - - struct sphw_dma_addr_align *eq_pages; - - struct sphw_eq_work aeq_work; - struct tasklet_struct ceq_tasklet; - struct sphw_ceq_tasklet_data ceq_tasklet_data; - - u64 hard_intr_jif; - u64 soft_intr_jif; -}; - -struct sphw_aeq_elem { - u8 aeqe_data[SPHW_AEQE_DATA_SIZE]; - u32 desc; -}; - -enum sphw_aeq_cb_state { - SPHW_AEQ_HW_CB_REG = 0, - SPHW_AEQ_HW_CB_RUNNING, - SPHW_AEQ_SW_CB_REG, - SPHW_AEQ_SW_CB_RUNNING, -}; - -struct sphw_aeqs { - struct sphw_hwdev *hwdev; - - sphw_aeq_hwe_cb aeq_hwe_cb[SPHW_MAX_AEQ_EVENTS]; - sphw_aeq_swe_cb aeq_swe_cb[SPHW_MAX_AEQ_SW_EVENTS]; - unsigned long aeq_hw_cb_state[SPHW_MAX_AEQ_EVENTS]; - unsigned long aeq_sw_cb_state[SPHW_MAX_AEQ_SW_EVENTS]; - - struct sphw_eq aeq[SPHW_MAX_AEQS]; - u16 num_aeqs; - struct workqueue_struct *workq; -}; - -enum sphw_ceq_cb_state { - SPHW_CEQ_CB_REG = 0, - SPHW_CEQ_CB_RUNNING, -}; - -struct sphw_ceqs { - struct sphw_hwdev *hwdev; - - sphw_ceq_event_cb ceq_cb[SPHW_MAX_CEQ_EVENTS]; - void *ceq_data[SPHW_MAX_CEQ_EVENTS]; - unsigned long ceq_cb_state[SPHW_MAX_CEQ_EVENTS]; - - struct sphw_eq ceq[SPHW_MAX_CEQS]; - u16 num_ceqs; -}; - -struct sphw_ceq_info { - u32 q_len; - u32 page_size; - u16 elem_size; - u16 num_pages; - u32 num_elem_in_pg; -}; - -int sphw_aeqs_init(struct sphw_hwdev *hwdev, u16 num_aeqs, struct irq_info *msix_entries); - -void sphw_aeqs_free(struct sphw_hwdev *hwdev); - -int sphw_ceqs_init(struct sphw_hwdev *hwdev, u16 num_ceqs, struct irq_info *msix_entries); - -void sphw_ceqs_free(struct sphw_hwdev *hwdev); - -void sphw_get_ceq_irqs(struct sphw_hwdev *hwdev, struct irq_info *irqs, u16 *num_irqs); - -void sphw_get_aeq_irqs(struct sphw_hwdev *hwdev, struct irq_info *irqs, u16 *num_irqs); - -void sphw_dump_ceq_info(struct sphw_hwdev *hwdev); - -void sphw_dump_aeq_info(struct sphw_hwdev *hwdev); - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw.h b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw.h deleted file mode 100644 index 41945efe86d8..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw.h +++ /dev/null @@ -1,643 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPHW_HW_H -#define SPHW_HW_H - -#include "sphw_comm_cmd.h" -#include "sphw_comm_msg_intf.h" -#include "sphw_crm.h" - -enum sphw_mod_type { - SPHW_MOD_COMM = 0, /* HW communication module */ - SPHW_MOD_L2NIC = 1, /* L2NIC module */ - SPHW_MOD_ROCE = 2, - SPHW_MOD_PLOG = 3, - SPHW_MOD_TOE = 4, - SPHW_MOD_FLR = 5, - SPHW_MOD_FC = 6, - SPHW_MOD_CFGM = 7, /* Configuration module */ - SPHW_MOD_CQM = 8, - SPHW_MOD_VSWITCH = 9, - COMM_MOD_FC = 10, - SPHW_MOD_OVS = 11, - SPHW_MOD_DSW = 12, - SPHW_MOD_MIGRATE = 13, - SPHW_MOD_HILINK = 14, - SPHW_MOD_CRYPT = 15, /* secure crypto module */ - SPHW_MOD_VIO = 16, - SPHW_MOD_DFT = 17, /* DFT */ - SPHW_MOD_HW_MAX = 18, /* hardware max module id */ - /* Software module id, for PF/VF and multi-host */ - SPHW_MOD_SW_FUNC = 19, - SPHW_MOD_IOE = 20, - SPHW_MOD_MAX, -}; - -/* to use 0-level CLA, page size must be: SQ 16B(wqe) * 64k(max_q_depth) */ -#define SPHW_DEFAULT_WQ_PAGE_SIZE 0x100000 -#define SPHW_HW_WQ_PAGE_SIZE 0x1000 -#define SPHW_MAX_WQ_PAGE_SIZE_ORDER 8 - -enum sphw_channel_id { - SPHW_CHANNEL_DEFAULT, - SPHW_CHANNEL_COMM, - SPHW_CHANNEL_NIC, - SPHW_CHANNEL_ROCE, - SPHW_CHANNEL_TOE, - SPHW_CHANNEL_FC, - SPHW_CHANNEL_OVS, - SPHW_CHANNEL_DSW, - SPHW_CHANNEL_MIG, - SPHW_CHANNEL_CRYPT, - - SPHW_CHANNEL_MAX = 32, -}; - -struct sphw_cmd_buf { - void *buf; - dma_addr_t dma_addr; - u16 size; - /* Usage count, USERS DO NOT USE */ - atomic_t ref_cnt; -}; - -enum sphw_aeq_type { - SPHW_HW_INTER_INT = 0, - SPHW_MBX_FROM_FUNC = 1, - SPHW_MSG_FROM_MGMT_CPU = 2, - SPHW_API_RSP = 3, - SPHW_API_CHAIN_STS = 4, - SPHW_MBX_SEND_RSLT = 5, - SPHW_MAX_AEQ_EVENTS -}; - -#define SPHW_NIC_FATAL_ERROR_MAX 0x8U - -enum sphw_aeq_sw_type { - SPHW_STATELESS_EVENT = 0, - SPHW_STATEFULL_EVENT = 1, - SPHW_MAX_AEQ_SW_EVENTS -}; - -typedef void (*sphw_aeq_hwe_cb)(void *handle, u8 *data, u8 size); -typedef u8 (*sphw_aeq_swe_cb)(void *handle, u8 event, u8 *data); - -/** - * @brief sphw_aeq_register_hw_cb - register aeq hardware callback - * @param hwdev: device pointer to hwdev - * @param event: event type - * @param hwe_cb: callback function - * @retval zero: success - * @retval non-zero: failure - **/ -int sphw_aeq_register_hw_cb(void *hwdev, enum sphw_aeq_type event, sphw_aeq_hwe_cb hwe_cb); - -/** - * @brief sphw_aeq_unregister_hw_cb - unregister aeq hardware callback - * @param hwdev: device pointer to hwdev - * @param event: event type - **/ -void sphw_aeq_unregister_hw_cb(void *hwdev, enum sphw_aeq_type event); - -/** - * @brief sphw_aeq_register_swe_cb - register aeq soft event callback - * @param hwdev: device pointer to hwdev - * @param event: event type - * @param aeq_swe_cb: callback function - * @retval zero: success - * @retval non-zero: failure - **/ -int sphw_aeq_register_swe_cb(void *hwdev, enum sphw_aeq_sw_type event, sphw_aeq_swe_cb aeq_swe_cb); - -/** - * @brief sphw_aeq_unregister_swe_cb - unregister aeq soft event callback - * @param hwdev: device pointer to hwdev - * @param event: event type - **/ -void sphw_aeq_unregister_swe_cb(void *hwdev, enum sphw_aeq_sw_type event); - -enum sphw_ceq_event { - SPHW_NON_L2NIC_SCQ, - SPHW_NON_L2NIC_ECQ, - SPHW_NON_L2NIC_NO_CQ_EQ, - SPHW_CMDQ, - SPHW_L2NIC_SQ, - SPHW_L2NIC_RQ, - SPHW_MAX_CEQ_EVENTS, -}; - -typedef void (*sphw_ceq_event_cb)(void *handle, u32 ceqe_data); - -/** - * @brief sphw_ceq_register_cb - register ceq callback - * @param hwdev: device pointer to hwdev - * @param event: event type - * @param callback: callback function - * @retval zero: success - * @retval non-zero: failure - **/ -int sphw_ceq_register_cb(void *hwdev, enum sphw_ceq_event event, sphw_ceq_event_cb callback); -/** - * @brief sphw_ceq_unregister_cb - unregister ceq callback - * @param hwdev: device pointer to hwdev - * @param event: event type - **/ -void sphw_ceq_unregister_cb(void *hwdev, enum sphw_ceq_event event); - -typedef int (*sphw_vf_mbox_cb)(void *handle, void *pri_handle, u16 cmd, void *buf_in, - u16 in_size, void *buf_out, u16 *out_size); - -typedef int (*sphw_pf_mbox_cb)(void *handle, void *pri_handle, u16 vf_id, u16 cmd, void *buf_in, - u16 in_size, void *buf_out, u16 *out_size); - -typedef int (*sphw_ppf_mbox_cb)(void *handle, void *pri_handle, - u16 pf_idx, u16 vf_id, u16 cmd, - void *buf_in, u16 in_size, void *buf_out, - u16 *out_size); - -typedef int (*sphw_pf_recv_from_ppf_mbox_cb)(void *handle, void *pri_handle, u16 cmd, void *buf_in, - u16 in_size, void *buf_out, u16 *out_size); - -/** - * @brief sphw_register_ppf_mbox_cb - ppf register mbox msg callback - * @param hwdev: device pointer to hwdev - * @param mod: mod type - * @param pri_handle: private data will be used by the callback - * @param callback: callback function - * @retval zero: success - * @retval non-zero: failure - **/ -int sphw_register_ppf_mbox_cb(void *hwdev, u8 mod, void *pri_handle, sphw_ppf_mbox_cb callback); - -/** - * @brief sphw_register_pf_mbox_cb - pf register mbox msg callback - * @param hwdev: device pointer to hwdev - * @param mod: mod type - * @param pri_handle: private data will be used by the callback - * @param callback: callback function - * @retval zero: success - * @retval non-zero: failure - **/ -int sphw_register_pf_mbox_cb(void *hwdev, u8 mod, void *pri_handle, sphw_pf_mbox_cb callback); -/** - * @brief sphw_register_vf_mbox_cb - vf register mbox msg callback - * @param hwdev: device pointer to hwdev - * @param mod: mod type - * @param pri_handle: private data will be used by the callback - * @param callback: callback function - * @retval zero: success - * @retval non-zero: failure - **/ -int sphw_register_vf_mbox_cb(void *hwdev, u8 mod, void *pri_handle, sphw_vf_mbox_cb callback); -/** - * @brief sphw_register_ppf_to_pf_mbox_cb - register mbox msg callback - * @param hwdev: device pointer to hwdev - * @param mod: mod type - * @param pri_handle: private data will be used by the callback - * @param callback: callback function - * @retval zero: success - * @retval non-zero: failure - **/ -int sphw_register_ppf_to_pf_mbox_cb(void *hwdev, u8 mod, void *pri_handle, - sphw_pf_recv_from_ppf_mbox_cb callback); - -/** - * @brief sphw_unregister_ppf_mbox_cb - ppf unregister mbox msg callback - * @param hwdev: device pointer to hwdev - * @param mod: mod type - **/ -void sphw_unregister_ppf_mbox_cb(void *hwdev, u8 mod); - -/** - * @brief sphw_unregister_pf_mbox_cb - pf register mbox msg callback - * @param hwdev: device pointer to hwdev - * @param mod: mod type - **/ -void sphw_unregister_pf_mbox_cb(void *hwdev, u8 mod); - -/** - * @brief sphw_unregister_vf_mbox_cb - pf register mbox msg callback - * @param hwdev: device pointer to hwdev - * @param mod: mod type - **/ -void sphw_unregister_vf_mbox_cb(void *hwdev, u8 mod); - -/** - * @brief sphw_unregister_ppf_to_pf_mbox_cb - unregister mbox msg callback - * @param hwdev: device pointer to hwdev - * @param mod: mod type - **/ -void sphw_unregister_ppf_to_pf_mbox_cb(void *hwdev, u8 mod); - -typedef void (*sphw_mgmt_msg_cb)(void *hwdev, void *pri_handle, u16 cmd, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size); - -/** - * @brief sphw_register_mgmt_msg_cb - register mgmt msg callback - * @param hwdev: device pointer to hwdev - * @param mod: mod type - * @param pri_handle: private data will be used by the callback - * @param callback: callback function - * @retval zero: success - * @retval non-zero: failure - **/ -int sphw_register_mgmt_msg_cb(void *hwdev, u8 mod, void *pri_handle, sphw_mgmt_msg_cb callback); - -/** - * @brief sphw_unregister_mgmt_msg_cb - unregister mgmt msg callback - * @param hwdev: device pointer to hwdev - * @param mod: mod type - **/ -void sphw_unregister_mgmt_msg_cb(void *hwdev, u8 mod); - -/** - * @brief sphw_register_service_adapter - register service adapter - * @param hwdev: device pointer to hwdev - * @param service_adapter: service adapter - * @param type: service type - * @retval zero: success - * @retval non-zero: failure - **/ -int sphw_register_service_adapter(void *hwdev, void *service_adapter, - enum sphw_service_type type); - -/** - * @brief sphw_unregister_service_adapter - unregister service adapter - * @param hwdev: device pointer to hwdev - * @param type: service type - **/ -void sphw_unregister_service_adapter(void *hwdev, enum sphw_service_type type); - -/** - * @brief sphw_get_service_adapter - get service adapter - * @param hwdev: device pointer to hwdev - * @param type: service type - * @retval non-zero: success - * @retval null: failure - **/ -void *sphw_get_service_adapter(void *hwdev, enum sphw_service_type type); - -/** - * @brief sphw_alloc_db_phy_addr - alloc doorbell & direct wqe pyhsical addr - * @param hwdev: device pointer to hwdev - * @param db_base: pointer to alloc doorbell base address - * @param dwqe_base: pointer to alloc direct base address - * @retval zero: success - * @retval non-zero: failure - **/ -int sphw_alloc_db_phy_addr(void *hwdev, u64 *db_base, u64 *dwqe_base); - -/** - * @brief sphw_free_db_phy_addr - free doorbell & direct wqe physical address - * @param hwdev: device pointer to hwdev - * @param db_base: pointer to free doorbell base address - * @param dwqe_base: pointer to free direct base address - **/ -void sphw_free_db_phy_addr(void *hwdev, u64 db_base, u64 dwqe_base); - -/** - * @brief sphw_alloc_db_addr - alloc doorbell & direct wqe - * @param hwdev: device pointer to hwdev - * @param db_base: pointer to alloc doorbell base address - * @param dwqe_base: pointer to alloc direct base address - * @retval zero: success - * @retval non-zero: failure - **/ -int sphw_alloc_db_addr(void *hwdev, void __iomem **db_base, void __iomem **dwqe_base); - -/** - * @brief sphw_free_db_addr - free doorbell & direct wqe - * @param hwdev: device pointer to hwdev - * @param db_base: pointer to free doorbell base address - * @param dwqe_base: pointer to free direct base address - **/ -void sphw_free_db_addr(void *hwdev, const void __iomem *db_base, void __iomem *dwqe_base); - -/** - * @brief sphw_alloc_db_phy_addr - alloc physical doorbell & direct wqe - * @param hwdev: device pointer to hwdev - * @param db_base: pointer to alloc doorbell base address - * @param dwqe_base: pointer to alloc direct base address - * @retval zero: success - * @retval non-zero: failure - **/ -int sphw_alloc_db_phy_addr(void *hwdev, u64 *db_base, u64 *dwqe_base); - -/** - * @brief sphw_free_db_phy_addr - free physical doorbell & direct wqe - * @param hwdev: device pointer to hwdev - * @param db_base: free doorbell base address - * @param dwqe_base: free direct base address - **/ - -void sphw_free_db_phy_addr(void *hwdev, u64 db_base, u64 dwqe_base); - -/** - * @brief sphw_set_root_ctxt - set root context - * @param hwdev: device pointer to hwdev - * @param rq_depth: rq depth - * @param sq_depth: sq depth - * @param rx_buf_sz: rx buffer size - * @param channel: channel id - * @retval zero: success - * @retval non-zero: failure - **/ -int sphw_set_root_ctxt(void *hwdev, u32 rq_depth, u32 sq_depth, int rx_buf_sz, u16 channel); - -/** - * @brief sphw_clean_root_ctxt - clean root context - * @param hwdev: device pointer to hwdev - * @param channel: channel id - * @retval zero: success - * @retval non-zero: failure - **/ -int sphw_clean_root_ctxt(void *hwdev, u16 channel); - -/** - * @brief sphw_alloc_cmd_buf - alloc cmd buffer - * @param hwdev: device pointer to hwdev - * @retval non-zero: success - * @retval null: failure - **/ -struct sphw_cmd_buf *sphw_alloc_cmd_buf(void *hwdev); - -/** - * @brief sphw_free_cmd_buf - free cmd buffer - * @param hwdev: device pointer to hwdev - * @param cmd_buf: cmd buffer to free - **/ -void sphw_free_cmd_buf(void *hwdev, struct sphw_cmd_buf *cmd_buf); - -/** - * @brief sphw_dbg_get_hw_stats - get hardware stats - * @param hwdev: device pointer to hwdev - * @param hw_stats: pointer to memory caller to alloc - * @param out_size: out size - * @retval zero: success - * @retval non-zero: failure - */ -int sphw_dbg_get_hw_stats(const void *hwdev, u8 *hw_stats, u16 *out_size); - -/** - * @brief sphw_dbg_clear_hw_stats - clear hardware stats - * @param hwdev: device pointer to hwdev - * @retval clear hardware size - */ -u16 sphw_dbg_clear_hw_stats(void *hwdev); - -/** - * @brief sphw_get_chip_fault_stats - get chip fault stats - * @param hwdev: device pointer to hwdev - * @param chip_fault_stats: pointer to memory caller to alloc - * @param offset: offset - */ -void sphw_get_chip_fault_stats(const void *hwdev, u8 *chip_fault_stats, u32 offset); - -/** - * @brief sphw_msg_to_mgmt_sync - msg to management cpu - * @param hwdev: device pointer to hwdev - * @param mod: mod type - * @param cmd: cmd - * @param buf_in: message buffer in - * @param in_size: in buffer size - * @param buf_out: message buffer out - * @param out_size: out buffer size - * @param timeout: timeout - * @param channel: channel id - * @retval zero: success - * @retval non-zero: failure - */ -int sphw_msg_to_mgmt_sync(void *hwdev, u8 mod, u16 cmd, void *buf_in, u16 in_size, void *buf_out, - u16 *out_size, u32 timeout, u16 channel); - -/** - * @brief sphw_msg_to_mgmt_async - msg to management cpu async - * @param hwdev: device pointer to hwdev - * @param mod: mod type - * @param cmd: cmd - * @param buf_in: message buffer in - * @param in_size: in buffer size - * @param channel: channel id - * @retval zero: success - * @retval non-zero: failure - * - * The function does not sleep inside, allowing use in irq context - */ -int sphw_msg_to_mgmt_async(void *hwdev, u8 mod, u16 cmd, void *buf_in, u16 in_size, u16 channel); - -/** - * @brief sphw_msg_to_mgmt_no_ack - msg to management cpu don't need no ack - * @param hwdev: device pointer to hwdev - * @param mod: mod type - * @param cmd: cmd - * @param buf_in: message buffer in - * @param in_size: in buffer size - * @param channel: channel id - * @retval zero: success - * @retval non-zero: failure - * - * The function will sleep inside, and it is not allowed to be used in - * interrupt context - */ -int sphw_msg_to_mgmt_no_ack(void *hwdev, u8 mod, u16 cmd, void *buf_in, u16 in_size, u16 channel); - -int sphw_msg_to_mgmt_api_chain_async(void *hwdev, u8 mod, u16 cmd, const void *buf_in, u16 in_size); - -int sphw_msg_to_mgmt_api_chain_sync(void *hwdev, u8 mod, u16 cmd, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size, u32 timeout); - -/** - * @brief sphw_mbox_to_pf - vf mbox message to pf - * @param hwdev: device pointer to hwdev - * @param mod: mod type - * @param cmd: cmd - * @param buf_in: message buffer in - * @param in_size: in buffer size - * @param buf_out: message buffer out - * @param out_size: out buffer size - * @param timeout: timeout - * @param channel: channel id - * @retval zero: success - * @retval non-zero: failure - */ -int sphw_mbox_to_pf(void *hwdev, u8 mod, u16 cmd, void *buf_in, u16 in_size, void *buf_out, - u16 *out_size, u32 timeout, u16 channel); - -/** - * @brief sphw_mbox_to_vf - mbox message to vf - * @param hwdev: device pointer to hwdev - * @param vf_id: vf index - * @param mod: mod type - * @param cmd: cmd - * @param buf_in: message buffer in - * @param in_size: in buffer size - * @param buf_out: message buffer out - * @param out_size: out buffer size - * @param timeout: timeout - * @param channel: channel id - * @retval zero: success - * @retval non-zero: failure - */ -int sphw_mbox_to_vf(void *hwdev, u16 vf_id, u8 mod, u16 cmd, void *buf_in, - u16 in_size, void *buf_out, u16 *out_size, u32 timeout, u16 channel); - -/** - * @brief sphw_cmdq_async - cmdq asynchronous message - * @param hwdev: device pointer to hwdev - * @param mod: mod type - * @param cmd: cmd - * @param buf_in: message buffer in - * @param channel: channel id - * @retval zero: success - * @retval non-zero: failure - */ -int sphw_cmdq_async(void *hwdev, u8 mod, u8 cmd, struct sphw_cmd_buf *buf_in, u16 channel); - -/** - * @brief sphw_cmdq_direct_resp - cmdq direct message response - * @param hwdev: device pointer to hwdev - * @param mod: mod type - * @param cmd: cmd - * @param buf_in: message buffer in - * @param out_param: message out - * @param timeout: timeout - * @param channel: channel id - * @retval zero: success - * @retval non-zero: failure - */ -int sphw_cmdq_direct_resp(void *hwdev, u8 mod, u8 cmd, struct sphw_cmd_buf *buf_in, - u64 *out_param, u32 timeout, u16 channel); - -/** - * @brief sphw_cmdq_detail_resp - cmdq detail message response - * @param hwdev: device pointer to hwdev - * @param mod: mod type - * @param cmd: cmd - * @param buf_in: message buffer in - * @param buf_out: message buffer out - * @param out_param: inline output data - * @param timeout: timeout - * @param channel: channel id - * @retval zero: success - * @retval non-zero: failure - */ -int sphw_cmdq_detail_resp(void *hwdev, u8 mod, u8 cmd, struct sphw_cmd_buf *buf_in, - struct sphw_cmd_buf *buf_out, u64 *out_param, u32 timeout, u16 channel); - -/** - * @brief sphw_cos_id_detail_resp - cmdq detail message response - * @param hwdev: device pointer to hwdev - * @param mod: mod type - * @param cmd: cmd - * @param cos_id: cos id - * @param buf_in: message buffer in - * @param buf_out: message buffer out - * @param out_param: inline output data - * @param timeout: timeout - * @param channel: channel id - * @retval zero: success - * @retval non-zero: failure - */ -int sphw_cos_id_detail_resp(void *hwdev, u8 mod, u8 cmd, u8 cos_id, struct sphw_cmd_buf *buf_in, - struct sphw_cmd_buf *buf_out, u64 *out_param, u32 timeout, u16 channel); - -/** - * @brief sphw_ppf_tmr_start - start ppf timer - * @param hwdev: device pointer to hwdev - * @retval zero: success - * @retval non-zero: failure - */ -int sphw_ppf_tmr_start(void *hwdev); - -/** - * @brief sphw_ppf_tmr_stop - stop ppf timer - * @param hwdev: device pointer to hwdev - * @retval zero: success - * @retval non-zero: failure - */ -int sphw_ppf_tmr_stop(void *hwdev); - -/** - * @brief sphw_func_tmr_bitmap_set - set timer bitmap status - * @param hwdev: device pointer to hwdev - * @param enable: 0-disable, 1-enable - * @retval zero: success - * @retval non-zero: failure - */ -int sphw_func_tmr_bitmap_set(void *hwdev, bool enable); - -/** - * @brief sphw_get_board_info - get board info - * @param hwdev: device pointer to hwdev - * @param info: board info - * @param channel: channel id - * @retval zero: success - * @retval non-zero: failure - */ -int sphw_get_board_info(void *hwdev, struct sphw_board_info *info, u16 channel); - -/** - * @brief sphw_set_wq_page_size - set work queue page size - * @param hwdev: device pointer to hwdev - * @param func_idx: function id - * @param page_size: page size - * @param channel: channel id - * @retval zero: success - * @retval non-zero: failure - */ -int sphw_set_wq_page_size(void *hwdev, u16 func_idx, u32 page_size, u16 channel); - -/** - * @brief sphw_event_callback - evnet callback to notify service driver - * @param hwdev: device pointer to hwdev - * @param event: event info to service driver - */ -void sphw_event_callback(void *hwdev, struct sphw_event_info *event); - -/** - * @brief sphw_link_event_stats - link event stats - * @param hwdev: device pointer to hwdev - * @param link: link status - */ -void sphw_link_event_stats(void *dev, u8 link); - -enum func_reset_flag { - RES_TYPE_FLUSH_BIT = 0, - RES_TYPE_MQM, - RES_TYPE_SMF, - - RES_TYPE_COMM = 10, - RES_TYPE_COMM_MGMT_CH, - RES_TYPE_COMM_CMD_CH, - RES_TYPE_NIC, - RES_TYPE_OVS, - RES_TYPE_VBS, - RES_TYPE_ROCE, - RES_TYPE_FC, - RES_TYPE_TOE, - RES_TYPE_IPSEC, -}; - -#define SPHW_COMM_RES (BIT(RES_TYPE_COMM) | BIT(RES_TYPE_FLUSH_BIT) | BIT(RES_TYPE_MQM) | \ - BIT(RES_TYPE_SMF) | BIT(RES_TYPE_COMM_CMD_CH)) - -#define SPHW_NIC_RES BIT(RES_TYPE_NIC) -#define SPHW_FC_RES BIT(RES_TYPE_FC) - -/** - * @brief sphw_func_reset - reset func - * @param hwdev: device pointer to hwdev - * @param func_id: global function index - * @param reset_flag: reset flag - * @param channel: channel id - */ -int sphw_func_reset(void *dev, u16 func_id, u64 reset_flag, u16 channel); - -int sphw_get_dev_cap(void *hwdev); - -int sphw_set_bdf_ctxt(void *hwdev, u8 bus, u8 device, u8 function); - -int sphw_init_func_mbox_msg_channel(void *hwdev, u16 num_func); - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw_cfg.c b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw_cfg.c deleted file mode 100644 index 4b2674ec66f0..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw_cfg.c +++ /dev/null @@ -1,1341 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [COMM]" fmt - -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/mutex.h> -#include <linux/device.h> -#include <linux/pci.h> -#include <linux/module.h> -#include <linux/semaphore.h> - -#include "sphw_common.h" -#include "sphw_crm.h" -#include "sphw_hw.h" -#include "sphw_hwdev.h" -#include "sphw_hwif.h" -#include "sphw_cfg_cmd.h" -#include "sphw_hw_cfg.h" - -uint g_rdma_mtts_num; - -uint intr_mode; -uint timer_enable = 1; -uint bloomfilter_enable; -uint g_test_mode; -uint g_test_qpc_num; -uint g_test_qpc_resvd_num; -uint g_test_pagesize_reorder; -uint g_test_xid_alloc_mode = 1; -uint g_test_gpa_check_enable = 1; -uint g_test_qpc_alloc_mode = 2; -uint g_test_scqc_alloc_mode = 2; -uint g_test_max_conn; -uint g_test_max_cache_conn; -uint g_test_scqc_num; -uint g_test_mpt_num; -uint g_test_mpt_resvd; -uint g_test_scq_resvd; -uint g_test_hash_num; -uint g_test_reorder_num; - -static void set_cfg_test_param(struct cfg_mgmt_info *cfg_mgmt) -{ - cfg_mgmt->svc_cap.test_mode = g_test_mode; - if (cfg_mgmt->svc_cap.test_mode == 0) - return; - - cfg_mgmt->svc_cap.timer_en = (u8)timer_enable; - cfg_mgmt->svc_cap.bloomfilter_en = (u8)bloomfilter_enable; - cfg_mgmt->svc_cap.test_qpc_num = g_test_qpc_num; - cfg_mgmt->svc_cap.test_qpc_resvd_num = g_test_qpc_resvd_num; - cfg_mgmt->svc_cap.test_page_size_reorder = g_test_pagesize_reorder; - cfg_mgmt->svc_cap.test_xid_alloc_mode = (bool)g_test_xid_alloc_mode; - cfg_mgmt->svc_cap.test_gpa_check_enable = (bool)g_test_gpa_check_enable; - cfg_mgmt->svc_cap.test_qpc_alloc_mode = (u8)g_test_qpc_alloc_mode; - cfg_mgmt->svc_cap.test_scqc_alloc_mode = (u8)g_test_scqc_alloc_mode; - cfg_mgmt->svc_cap.test_max_conn_num = g_test_max_conn; - cfg_mgmt->svc_cap.test_max_cache_conn_num = g_test_max_cache_conn; - cfg_mgmt->svc_cap.test_scqc_num = g_test_scqc_num; - cfg_mgmt->svc_cap.test_mpt_num = g_test_mpt_num; - cfg_mgmt->svc_cap.test_scq_resvd_num = g_test_scq_resvd; - cfg_mgmt->svc_cap.test_mpt_recvd_num = g_test_mpt_resvd; - cfg_mgmt->svc_cap.test_hash_num = g_test_hash_num; - cfg_mgmt->svc_cap.test_reorder_num = g_test_reorder_num; -} - -static void parse_pub_res_cap(struct sphw_hwdev *hwdev, - struct service_cap *cap, - struct cfg_cmd_dev_cap *dev_cap, - enum func_type type) -{ - struct dev_sf_svc_attr *attr = &cap->sf_svc_attr; - - cap->host_id = dev_cap->host_id; - cap->ep_id = dev_cap->ep_id; - cap->er_id = dev_cap->er_id; - cap->port_id = dev_cap->port_id; - - cap->svc_type = dev_cap->svc_cap_en; - cap->chip_svc_type = cap->svc_type; - - cap->cos_valid_bitmap = dev_cap->valid_cos_bitmap; - cap->flexq_en = dev_cap->flexq_en; - - cap->host_total_function = dev_cap->host_total_func; - - if (type != TYPE_VF) { - cap->max_vf = dev_cap->max_vf; - cap->pf_num = dev_cap->host_pf_num; - cap->pf_id_start = dev_cap->pf_id_start; - cap->vf_num = dev_cap->host_vf_num; - cap->vf_id_start = dev_cap->vf_id_start; - } else { - cap->max_vf = 0; - } - - if (dev_cap->sf_svc_attr & SF_SVC_FT_BIT) - attr->ft_en = true; - else - attr->ft_en = false; - - if (dev_cap->sf_svc_attr & SF_SVC_RDMA_BIT) - attr->rdma_en = true; - else - attr->rdma_en = false; - - /* PPF will overwrite it when parse dynamic resource */ - if (dev_cap->func_sf_en) - cap->sf_en = true; - else - cap->sf_en = false; - - cap->lb_mode = dev_cap->lb_mode; - cap->smf_pg = dev_cap->smf_pg; - - cap->timer_en = (u8)timer_enable; /* timer enable */ - cap->host_oq_id_mask_val = dev_cap->host_oq_id_mask_val; - cap->max_connect_num = dev_cap->max_conn_num; - cap->max_stick2cache_num = dev_cap->max_stick2cache_num; - cap->bfilter_start_addr = dev_cap->max_bfilter_start_addr; - cap->bfilter_len = dev_cap->bfilter_len; - cap->hash_bucket_num = dev_cap->hash_bucket_num; - - sdk_info(hwdev->dev_hdl, "Get public resource capbility: svc_cap_en: 0x%x\n", - cap->svc_type); - sdk_info(hwdev->dev_hdl, "Host_id: 0x%x, ep_id: 0x%x, er_id: 0x%x, port_id: 0x%x, cos_bitmap: 0x%x, flexq: 0x%x\n", - cap->host_id, cap->ep_id, cap->er_id, cap->port_id, - cap->cos_valid_bitmap, cap->flexq_en); - sdk_info(hwdev->dev_hdl, "Host_total_function: 0x%x, host_oq_id_mask_val: 0x%x, max_vf: 0x%x\n", - cap->host_total_function, cap->host_oq_id_mask_val, - cap->max_vf); - sdk_info(hwdev->dev_hdl, "Host_pf_num: 0x%x, pf_id_start: 0x%x, host_vf_num: 0x%x, vf_id_start: 0x%x\n", - cap->pf_num, cap->pf_id_start, cap->vf_num, cap->vf_id_start); -} - -static void parse_dynamic_share_res_cap(struct sphw_hwdev *hwdev, - struct service_cap *cap, - struct cfg_cmd_dev_cap *dev_cap, - enum func_type type) -{ - struct host_shared_resource_cap *shared_cap = &cap->shared_res_cap; - - if (dev_cap->host_sf_en) - cap->sf_en = true; - else - cap->sf_en = false; - - shared_cap->host_pctxs = dev_cap->host_pctx_num; - shared_cap->host_cctxs = dev_cap->host_ccxt_num; - shared_cap->host_scqs = dev_cap->host_scq_num; - shared_cap->host_srqs = dev_cap->host_srq_num; - shared_cap->host_mpts = dev_cap->host_mpt_num; - - sdk_info(hwdev->dev_hdl, "Dynamic share resource capbility:\n"); - sdk_info(hwdev->dev_hdl, "host_pctxs: 0x%x, host_cctxs: 0x%x, host_scqs: 0x%x, host_srqs: 0x%x, host_mpts: 0x%x\n", - shared_cap->host_pctxs, shared_cap->host_cctxs, - shared_cap->host_scqs, shared_cap->host_srqs, - shared_cap->host_mpts); -} - -static void parse_l2nic_res_cap(struct sphw_hwdev *hwdev, - struct service_cap *cap, - struct cfg_cmd_dev_cap *dev_cap, - enum func_type type) -{ - struct nic_service_cap *nic_cap = &cap->nic_cap; - - nic_cap->max_sqs = dev_cap->nic_max_sq_id + 1; - nic_cap->max_rqs = dev_cap->nic_max_rq_id + 1; - - sdk_info(hwdev->dev_hdl, "L2nic resource capbility, max_sqs: 0x%x, max_rqs: 0x%x\n", - nic_cap->max_sqs, nic_cap->max_rqs); - - /* Check parameters from firmware */ - if (nic_cap->max_sqs > SPHW_CFG_MAX_QP || - nic_cap->max_rqs > SPHW_CFG_MAX_QP) { - sdk_info(hwdev->dev_hdl, "Number of qp exceed limit[1-%d]: sq: %u, rq: %u\n", - SPHW_CFG_MAX_QP, nic_cap->max_sqs, nic_cap->max_rqs); - nic_cap->max_sqs = SPHW_CFG_MAX_QP; - nic_cap->max_rqs = SPHW_CFG_MAX_QP; - } -} - -static void parse_fc_res_cap(struct sphw_hwdev *hwdev, - struct service_cap *cap, - struct cfg_cmd_dev_cap *dev_cap, - enum func_type type) -{ - struct dev_fc_svc_cap *fc_cap = &cap->fc_cap.dev_fc_cap; - - fc_cap->max_parent_qpc_num = dev_cap->fc_max_pctx; - fc_cap->scq_num = dev_cap->fc_max_scq; - fc_cap->srq_num = dev_cap->fc_max_srq; - fc_cap->max_child_qpc_num = dev_cap->fc_max_cctx; - fc_cap->child_qpc_id_start = dev_cap->fc_cctx_id_start; - fc_cap->vp_id_start = dev_cap->fc_vp_id_start; - fc_cap->vp_id_end = dev_cap->fc_vp_id_end; - - sdk_info(hwdev->dev_hdl, "Get fc resource capbility\n"); - sdk_info(hwdev->dev_hdl, "Max_parent_qpc_num: 0x%x, scq_num: 0x%x, srq_num: 0x%x, max_child_qpc_num: 0x%x, child_qpc_id_start: 0x%x\n", - fc_cap->max_parent_qpc_num, fc_cap->scq_num, fc_cap->srq_num, - fc_cap->max_child_qpc_num, fc_cap->child_qpc_id_start); - sdk_info(hwdev->dev_hdl, "Vp_id_start: 0x%x, vp_id_end: 0x%x\n", - fc_cap->vp_id_start, fc_cap->vp_id_end); -} - -static void parse_roce_res_cap(struct sphw_hwdev *hwdev, - struct service_cap *cap, - struct cfg_cmd_dev_cap *dev_cap, - enum func_type type) -{ - struct dev_roce_svc_own_cap *roce_cap = - &cap->rdma_cap.dev_rdma_cap.roce_own_cap; - - roce_cap->max_qps = dev_cap->roce_max_qp; - roce_cap->max_cqs = dev_cap->roce_max_cq; - roce_cap->max_srqs = dev_cap->roce_max_srq; - roce_cap->max_mpts = dev_cap->roce_max_mpt; - roce_cap->max_drc_qps = dev_cap->roce_max_drc_qp; - - roce_cap->wqe_cl_start = dev_cap->roce_wqe_cl_start; - roce_cap->wqe_cl_end = dev_cap->roce_wqe_cl_end; - roce_cap->wqe_cl_sz = dev_cap->roce_wqe_cl_size; - - sdk_info(hwdev->dev_hdl, "Get roce resource capbility, type: 0x%x\n", - type); - sdk_info(hwdev->dev_hdl, "Max_qps: 0x%x, max_cqs: 0x%x, max_srqs: 0x%x, max_mpts: 0x%x, max_drcts: 0x%x\n", - roce_cap->max_qps, roce_cap->max_cqs, roce_cap->max_srqs, - roce_cap->max_mpts, roce_cap->max_drc_qps); - - sdk_info(hwdev->dev_hdl, "Wqe_start: 0x%x, wqe_end: 0x%x, wqe_sz: 0x%x\n", - roce_cap->wqe_cl_start, roce_cap->wqe_cl_end, - roce_cap->wqe_cl_sz); - - if (roce_cap->max_qps == 0) { - if (type == TYPE_PF || type == TYPE_PPF) { - roce_cap->max_qps = 1024; - roce_cap->max_cqs = 2048; - roce_cap->max_srqs = 1024; - roce_cap->max_mpts = 1024; - roce_cap->max_drc_qps = 64; - } else { - roce_cap->max_qps = 512; - roce_cap->max_cqs = 1024; - roce_cap->max_srqs = 512; - roce_cap->max_mpts = 512; - roce_cap->max_drc_qps = 64; - } - } -} - -static void parse_rdma_res_cap(struct sphw_hwdev *hwdev, - struct service_cap *cap, - struct cfg_cmd_dev_cap *dev_cap, - enum func_type type) -{ - struct dev_roce_svc_own_cap *roce_cap = - &cap->rdma_cap.dev_rdma_cap.roce_own_cap; - - roce_cap->cmtt_cl_start = dev_cap->roce_cmtt_cl_start; - roce_cap->cmtt_cl_end = dev_cap->roce_cmtt_cl_end; - roce_cap->cmtt_cl_sz = dev_cap->roce_cmtt_cl_size; - - roce_cap->dmtt_cl_start = dev_cap->roce_dmtt_cl_start; - roce_cap->dmtt_cl_end = dev_cap->roce_dmtt_cl_end; - roce_cap->dmtt_cl_sz = dev_cap->roce_dmtt_cl_size; - - sdk_info(hwdev->dev_hdl, "Get rdma resource capbility, Cmtt_start: 0x%x, cmtt_end: 0x%x, cmtt_sz: 0x%x\n", - roce_cap->cmtt_cl_start, roce_cap->cmtt_cl_end, - roce_cap->cmtt_cl_sz); - - sdk_info(hwdev->dev_hdl, "Dmtt_start: 0x%x, dmtt_end: 0x%x, dmtt_sz: 0x%x\n", - roce_cap->dmtt_cl_start, roce_cap->dmtt_cl_end, - roce_cap->dmtt_cl_sz); -} - -static void parse_ovs_res_cap(struct sphw_hwdev *hwdev, - struct service_cap *cap, - struct cfg_cmd_dev_cap *dev_cap, - enum func_type type) -{ - struct ovs_service_cap *ovs_cap = &cap->ovs_cap; - - ovs_cap->dev_ovs_cap.max_pctxs = dev_cap->ovs_max_qpc; - ovs_cap->dev_ovs_cap.fake_vf_start_id = dev_cap->fake_vf_start_id; - ovs_cap->dev_ovs_cap.fake_vf_num = dev_cap->fake_vf_num; - ovs_cap->dev_ovs_cap.dynamic_qp_en = dev_cap->flexq_en; - - sdk_info(hwdev->dev_hdl, "Get ovs resource capbility, max_qpc: 0x%x, fake_vf_start_id: 0x%x, fake_vf_num: 0x%x, dynamic_qp_en: 0x%x\n", - ovs_cap->dev_ovs_cap.max_pctxs, - ovs_cap->dev_ovs_cap.fake_vf_start_id, - ovs_cap->dev_ovs_cap.fake_vf_num, - ovs_cap->dev_ovs_cap.dynamic_qp_en); -} - -static void parse_toe_res_cap(struct sphw_hwdev *hwdev, - struct service_cap *cap, - struct cfg_cmd_dev_cap *dev_cap, - enum func_type type) -{ - struct dev_toe_svc_cap *toe_cap = &cap->toe_cap.dev_toe_cap; - - toe_cap->max_pctxs = dev_cap->toe_max_pctx; - toe_cap->max_cqs = dev_cap->toe_max_cq; - toe_cap->max_srqs = dev_cap->toe_max_srq; - toe_cap->srq_id_start = dev_cap->toe_srq_id_start; - toe_cap->max_mpts = dev_cap->toe_max_mpt; - - sdk_info(hwdev->dev_hdl, "Get toe resource capbility, max_pctxs: 0x%x, max_cqs: 0x%x, max_srqs: 0x%x, srq_id_start: 0x%x, max_mpts: 0x%x\n", - toe_cap->max_pctxs, toe_cap->max_cqs, toe_cap->max_srqs, - toe_cap->srq_id_start, toe_cap->max_mpts); -} - -static void parse_ipsec_res_cap(struct sphw_hwdev *hwdev, - struct service_cap *cap, - struct cfg_cmd_dev_cap *dev_cap, - enum func_type type) -{ - struct ipsec_service_cap *ipsec_cap = &cap->ipsec_cap; - - ipsec_cap->dev_ipsec_cap.max_sa_ctxs = dev_cap->ipsec_max_sactx; - - sdk_info(hwdev->dev_hdl, "Get IPsec resource capbility, max_sa_ctxs: 0x%x\n", - ipsec_cap->dev_ipsec_cap.max_sa_ctxs); -} - -static void parse_dev_cap(struct sphw_hwdev *dev, - struct cfg_cmd_dev_cap *dev_cap, enum func_type type) -{ - struct service_cap *cap = &dev->cfg_mgmt->svc_cap; - - /* Public resource */ - parse_pub_res_cap(dev, cap, dev_cap, type); - - /* PPF managed dynamic resource */ - if (type == TYPE_PPF) - parse_dynamic_share_res_cap(dev, cap, dev_cap, type); - - /* L2 NIC resource */ - if (IS_NIC_TYPE(dev)) - parse_l2nic_res_cap(dev, cap, dev_cap, type); - - /* FC without virtulization */ - if (type == TYPE_PF || type == TYPE_PPF) { - if (IS_FC_TYPE(dev)) - parse_fc_res_cap(dev, cap, dev_cap, type); - } - - /* toe resource */ - if (IS_TOE_TYPE(dev)) - parse_toe_res_cap(dev, cap, dev_cap, type); - - /* mtt cache line */ - if (IS_RDMA_ENABLE(dev)) - parse_rdma_res_cap(dev, cap, dev_cap, type); - - /* RoCE resource */ - if (IS_ROCE_TYPE(dev)) - parse_roce_res_cap(dev, cap, dev_cap, type); - - if (IS_OVS_TYPE(dev)) - parse_ovs_res_cap(dev, cap, dev_cap, type); - - if (IS_IPSEC_TYPE(dev)) - parse_ipsec_res_cap(dev, cap, dev_cap, type); -} - -static int get_cap_from_fw(struct sphw_hwdev *dev, enum func_type type) -{ - struct cfg_cmd_dev_cap dev_cap; - u16 out_len = sizeof(dev_cap); - int err; - - memset(&dev_cap, 0, sizeof(dev_cap)); - dev_cap.func_id = sphw_global_func_id(dev); - sdk_info(dev->dev_hdl, "Get cap from fw, func_idx: %u\n", - dev_cap.func_id); - - err = sphw_msg_to_mgmt_sync(dev, SPHW_MOD_CFGM, CFG_CMD_GET_DEV_CAP, - &dev_cap, sizeof(dev_cap), &dev_cap, &out_len, 0, - SPHW_CHANNEL_COMM); - if (err || dev_cap.head.status || !out_len) { - sdk_err(dev->dev_hdl, - "Failed to get capability from FW, err: %d, status: 0x%x, out size: 0x%x\n", - err, dev_cap.head.status, out_len); - return -EIO; - } - - parse_dev_cap(dev, &dev_cap, type); - - return 0; -} - -int sphw_get_dev_cap(void *dev) -{ - struct sphw_hwdev *hwdev = dev; - enum func_type type = SPHW_FUNC_TYPE(hwdev); - int err; - - switch (type) { - case TYPE_PF: - case TYPE_PPF: - case TYPE_VF: - err = get_cap_from_fw(hwdev, type); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to get PF/PPF capability\n"); - return err; - } - break; - default: - sdk_err(hwdev->dev_hdl, "Unsupported PCI Function type: %d\n", - type); - return -EINVAL; - } - - return 0; -} - -static void nic_param_fix(struct sphw_hwdev *dev) -{ -} - -static void rdma_mtt_fix(struct sphw_hwdev *dev) -{ - struct service_cap *cap = &dev->cfg_mgmt->svc_cap; - struct rdma_service_cap *rdma_cap = &cap->rdma_cap; - - rdma_cap->log_mtt = LOG_MTT_SEG; - rdma_cap->log_mtt_seg = LOG_MTT_SEG; - rdma_cap->mtt_entry_sz = MTT_ENTRY_SZ; - rdma_cap->mpt_entry_sz = RDMA_MPT_ENTRY_SZ; - rdma_cap->num_mtts = (g_rdma_mtts_num > 0 ? - g_rdma_mtts_num : RDMA_NUM_MTTS); -} - -static void rdma_param_fix(struct sphw_hwdev *dev) -{ - struct service_cap *cap = &dev->cfg_mgmt->svc_cap; - struct rdma_service_cap *rdma_cap = &cap->rdma_cap; - struct dev_roce_svc_own_cap *roce_cap = - &rdma_cap->dev_rdma_cap.roce_own_cap; - - rdma_cap->log_mtt = LOG_MTT_SEG; - rdma_cap->log_rdmarc = LOG_RDMARC_SEG; - rdma_cap->reserved_qps = RDMA_RSVD_QPS; - rdma_cap->max_sq_sg = RDMA_MAX_SQ_SGE; - - /* RoCE */ - if (IS_ROCE_TYPE(dev)) { - roce_cap->qpc_entry_sz = ROCE_QPC_ENTRY_SZ; - roce_cap->max_wqes = ROCE_MAX_WQES; - roce_cap->max_rq_sg = ROCE_MAX_RQ_SGE; - roce_cap->max_sq_inline_data_sz = ROCE_MAX_SQ_INLINE_DATA_SZ; - roce_cap->max_rq_desc_sz = ROCE_MAX_RQ_DESC_SZ; - roce_cap->rdmarc_entry_sz = ROCE_RDMARC_ENTRY_SZ; - roce_cap->max_qp_init_rdma = ROCE_MAX_QP_INIT_RDMA; - roce_cap->max_qp_dest_rdma = ROCE_MAX_QP_DEST_RDMA; - roce_cap->max_srq_wqes = ROCE_MAX_SRQ_WQES; - roce_cap->reserved_srqs = ROCE_RSVD_SRQS; - roce_cap->max_srq_sge = ROCE_MAX_SRQ_SGE; - roce_cap->srqc_entry_sz = ROCE_SRQC_ENTERY_SZ; - roce_cap->max_msg_sz = ROCE_MAX_MSG_SZ; - } - - rdma_cap->max_sq_desc_sz = RDMA_MAX_SQ_DESC_SZ; - rdma_cap->wqebb_size = WQEBB_SZ; - rdma_cap->max_cqes = RDMA_MAX_CQES; - rdma_cap->reserved_cqs = RDMA_RSVD_CQS; - rdma_cap->cqc_entry_sz = RDMA_CQC_ENTRY_SZ; - rdma_cap->cqe_size = RDMA_CQE_SZ; - rdma_cap->reserved_mrws = RDMA_RSVD_MRWS; - rdma_cap->mpt_entry_sz = RDMA_MPT_ENTRY_SZ; - - /* 2^8 - 1 - * +------------------------+-----------+ - * | 4B | 1M(20b) | Key(8b) | - * +------------------------+-----------+ - * key = 8bit key + 24bit index, - * now Lkey of SGE uses 2bit(bit31 and bit30), so key only have 10bit, - * we use original 8bits directly for simpilification - */ - rdma_cap->max_fmr_maps = 255; - rdma_cap->num_mtts = (g_rdma_mtts_num > 0 ? - g_rdma_mtts_num : RDMA_NUM_MTTS); - rdma_cap->log_mtt_seg = LOG_MTT_SEG; - rdma_cap->mtt_entry_sz = MTT_ENTRY_SZ; - rdma_cap->log_rdmarc_seg = LOG_RDMARC_SEG; - rdma_cap->local_ca_ack_delay = LOCAL_ACK_DELAY; - rdma_cap->num_ports = RDMA_NUM_PORTS; - rdma_cap->db_page_size = DB_PAGE_SZ; - rdma_cap->direct_wqe_size = DWQE_SZ; - rdma_cap->num_pds = NUM_PD; - rdma_cap->reserved_pds = RSVD_PD; - rdma_cap->max_xrcds = MAX_XRCDS; - rdma_cap->reserved_xrcds = RSVD_XRCDS; - rdma_cap->max_gid_per_port = MAX_GID_PER_PORT; - rdma_cap->gid_entry_sz = GID_ENTRY_SZ; - rdma_cap->reserved_lkey = RSVD_LKEY; - rdma_cap->num_comp_vectors = (u32)dev->cfg_mgmt->eq_info.num_ceq; - rdma_cap->page_size_cap = PAGE_SZ_CAP; - rdma_cap->flags = (RDMA_BMME_FLAG_LOCAL_INV | - RDMA_BMME_FLAG_REMOTE_INV | - RDMA_BMME_FLAG_FAST_REG_WR | - RDMA_DEV_CAP_FLAG_XRC | - RDMA_DEV_CAP_FLAG_MEM_WINDOW | - RDMA_BMME_FLAG_TYPE_2_WIN | - RDMA_BMME_FLAG_WIN_TYPE_2B | - RDMA_DEV_CAP_FLAG_ATOMIC); - rdma_cap->max_frpl_len = MAX_FRPL_LEN; - rdma_cap->max_pkeys = MAX_PKEYS; -} - -static void toe_param_fix(struct sphw_hwdev *dev) -{ - struct service_cap *cap = &dev->cfg_mgmt->svc_cap; - struct toe_service_cap *toe_cap = &cap->toe_cap; - - toe_cap->pctx_sz = TOE_PCTX_SZ; - toe_cap->scqc_sz = TOE_CQC_SZ; -} - -static void ovs_param_fix(struct sphw_hwdev *dev) -{ - struct service_cap *cap = &dev->cfg_mgmt->svc_cap; - struct ovs_service_cap *ovs_cap = &cap->ovs_cap; - - ovs_cap->pctx_sz = OVS_PCTX_SZ; -} - -static void fc_param_fix(struct sphw_hwdev *dev) -{ - struct service_cap *cap = &dev->cfg_mgmt->svc_cap; - struct fc_service_cap *fc_cap = &cap->fc_cap; - - fc_cap->parent_qpc_size = FC_PCTX_SZ; - fc_cap->child_qpc_size = FC_CCTX_SZ; - fc_cap->sqe_size = FC_SQE_SZ; - - fc_cap->scqc_size = FC_SCQC_SZ; - fc_cap->scqe_size = FC_SCQE_SZ; - - fc_cap->srqc_size = FC_SRQC_SZ; - fc_cap->srqe_size = FC_SRQE_SZ; -} - -static void ipsec_param_fix(struct sphw_hwdev *dev) -{ - struct service_cap *cap = &dev->cfg_mgmt->svc_cap; - struct ipsec_service_cap *ipsec_cap = &cap->ipsec_cap; - - ipsec_cap->sactx_sz = IPSEC_SACTX_SZ; -} - -static void init_service_param(struct sphw_hwdev *dev) -{ - if (IS_NIC_TYPE(dev)) - nic_param_fix(dev); - if (IS_RDMA_ENABLE(dev)) - rdma_mtt_fix(dev); - if (IS_ROCE_TYPE(dev)) - rdma_param_fix(dev); - if (IS_FC_TYPE(dev)) - fc_param_fix(dev); - if (IS_TOE_TYPE(dev)) - toe_param_fix(dev); - if (IS_OVS_TYPE(dev)) - ovs_param_fix(dev); - if (IS_IPSEC_TYPE(dev)) - ipsec_param_fix(dev); -} - -static void cfg_get_eq_num(struct sphw_hwdev *dev) -{ - struct cfg_eq_info *eq_info = &dev->cfg_mgmt->eq_info; - - eq_info->num_ceq = dev->hwif->attr.num_ceqs; - eq_info->num_ceq_remain = eq_info->num_ceq; -} - -static int cfg_init_eq(struct sphw_hwdev *dev) -{ - struct cfg_mgmt_info *cfg_mgmt = dev->cfg_mgmt; - struct cfg_eq *eq = NULL; - u8 num_ceq, i = 0; - - cfg_get_eq_num(dev); - num_ceq = cfg_mgmt->eq_info.num_ceq; - - sdk_info(dev->dev_hdl, "Cfg mgmt: ceqs=0x%x, remain=0x%x\n", - cfg_mgmt->eq_info.num_ceq, cfg_mgmt->eq_info.num_ceq_remain); - - if (!num_ceq) { - sdk_err(dev->dev_hdl, "Ceq num cfg in fw is zero\n"); - return -EFAULT; - } - - eq = kcalloc(num_ceq, sizeof(*eq), GFP_KERNEL); - if (!eq) - return -ENOMEM; - - for (i = 0; i < num_ceq; ++i) { - eq[i].eqn = i; - eq[i].free = CFG_FREE; - eq[i].type = SERVICE_T_MAX; - } - - cfg_mgmt->eq_info.eq = eq; - - mutex_init(&cfg_mgmt->eq_info.eq_mutex); - - return 0; -} - -int sphw_vector_to_eqn(void *hwdev, enum sphw_service_type type, int vector) -{ - struct sphw_hwdev *dev = hwdev; - struct cfg_mgmt_info *cfg_mgmt = NULL; - struct cfg_eq *eq = NULL; - int eqn = -EINVAL; - - if (!hwdev || vector < 0) - return -EINVAL; - - if (type != SERVICE_T_ROCE) { - sdk_err(dev->dev_hdl, - "Service type :%d, only RDMA service could get eqn by vector.\n", - type); - return -EINVAL; - } - - cfg_mgmt = dev->cfg_mgmt; - vector = (vector % cfg_mgmt->eq_info.num_ceq) + CFG_RDMA_CEQ_BASE; - - eq = cfg_mgmt->eq_info.eq; - if (eq[vector].type == SERVICE_T_ROCE && eq[vector].free == CFG_BUSY) - eqn = eq[vector].eqn; - - return eqn; -} - -static int cfg_init_interrupt(struct sphw_hwdev *dev) -{ - struct cfg_mgmt_info *cfg_mgmt = dev->cfg_mgmt; - struct cfg_irq_info *irq_info = &cfg_mgmt->irq_param_info; - u16 intr_num = dev->hwif->attr.num_irqs; - - if (!intr_num) { - sdk_err(dev->dev_hdl, "Irq num cfg in fw is zero\n"); - return -EFAULT; - } - irq_info->alloc_info = kcalloc(intr_num, sizeof(*irq_info->alloc_info), - GFP_KERNEL); - if (!irq_info->alloc_info) - return -ENOMEM; - - irq_info->num_irq_hw = intr_num; - - /* Production requires VF only surppots MSI-X */ - if (SPHW_FUNC_TYPE(dev) == TYPE_VF) - cfg_mgmt->svc_cap.interrupt_type = INTR_TYPE_MSIX; - else - cfg_mgmt->svc_cap.interrupt_type = intr_mode; - - mutex_init(&irq_info->irq_mutex); - return 0; -} - -static int cfg_enable_interrupt(struct sphw_hwdev *dev) -{ - struct cfg_mgmt_info *cfg_mgmt = dev->cfg_mgmt; - u16 nreq = cfg_mgmt->irq_param_info.num_irq_hw; - - void *pcidev = dev->pcidev_hdl; - struct irq_alloc_info_st *irq_info = NULL; - struct msix_entry *entry = NULL; - u16 i = 0; - int actual_irq; - - irq_info = cfg_mgmt->irq_param_info.alloc_info; - - sdk_info(dev->dev_hdl, "Interrupt type: %u, irq num: %u.\n", - cfg_mgmt->svc_cap.interrupt_type, nreq); - - switch (cfg_mgmt->svc_cap.interrupt_type) { - case INTR_TYPE_MSIX: - if (!nreq) { - sdk_err(dev->dev_hdl, "Interrupt number cannot be zero\n"); - return -EINVAL; - } - entry = kcalloc(nreq, sizeof(*entry), GFP_KERNEL); - if (!entry) - return -ENOMEM; - - for (i = 0; i < nreq; i++) - entry[i].entry = i; - - actual_irq = pci_enable_msix_range(pcidev, entry, - VECTOR_THRESHOLD, nreq); - if (actual_irq < 0) { - sdk_err(dev->dev_hdl, "Alloc msix entries with threshold 2 failed. actual_irq: %d\n", - actual_irq); - kfree(entry); - return -ENOMEM; - } - - nreq = (u16)actual_irq; - cfg_mgmt->irq_param_info.num_total = nreq; - cfg_mgmt->irq_param_info.num_irq_remain = nreq; - sdk_info(dev->dev_hdl, "Request %u msix vector success.\n", - nreq); - - for (i = 0; i < nreq; ++i) { - /* u16 driver uses to specify entry, OS writes */ - irq_info[i].info.msix_entry_idx = entry[i].entry; - /* u32 kernel uses to write allocated vector */ - irq_info[i].info.irq_id = entry[i].vector; - irq_info[i].type = SERVICE_T_MAX; - irq_info[i].free = CFG_FREE; - } - - kfree(entry); - - break; - - default: - sdk_err(dev->dev_hdl, "Unsupport interrupt type %d\n", - cfg_mgmt->svc_cap.interrupt_type); - break; - } - - return 0; -} - -int sphw_alloc_irqs(void *hwdev, enum sphw_service_type type, u16 num, - struct irq_info *irq_info_array, u16 *act_num) -{ - struct sphw_hwdev *dev = hwdev; - struct cfg_mgmt_info *cfg_mgmt = NULL; - struct cfg_irq_info *irq_info = NULL; - struct irq_alloc_info_st *alloc_info = NULL; - int max_num_irq; - u16 free_num_irq; - int i, j; - - if (!hwdev || !irq_info_array || !act_num) - return -EINVAL; - - cfg_mgmt = dev->cfg_mgmt; - irq_info = &cfg_mgmt->irq_param_info; - alloc_info = irq_info->alloc_info; - max_num_irq = irq_info->num_total; - free_num_irq = irq_info->num_irq_remain; - - mutex_lock(&irq_info->irq_mutex); - - if (num > free_num_irq) { - if (free_num_irq == 0) { - sdk_err(dev->dev_hdl, - "no free irq resource in cfg mgmt.\n"); - mutex_unlock(&irq_info->irq_mutex); - return -ENOMEM; - } - - sdk_warn(dev->dev_hdl, "only %u irq resource in cfg mgmt.\n", - free_num_irq); - num = free_num_irq; - } - - *act_num = 0; - - for (i = 0; i < num; i++) { - for (j = 0; j < max_num_irq; j++) { - if (alloc_info[j].free == CFG_FREE) { - if (irq_info->num_irq_remain == 0) { - sdk_err(dev->dev_hdl, "No free irq resource in cfg mgmt\n"); - mutex_unlock(&irq_info->irq_mutex); - return -EINVAL; - } - alloc_info[j].type = type; - alloc_info[j].free = CFG_BUSY; - - irq_info_array[i].msix_entry_idx = - alloc_info[j].info.msix_entry_idx; - irq_info_array[i].irq_id = - alloc_info[j].info.irq_id; - (*act_num)++; - irq_info->num_irq_remain--; - - break; - } - } - } - - mutex_unlock(&irq_info->irq_mutex); - return 0; -} - -void sphw_free_irq(void *hwdev, enum sphw_service_type type, u32 irq_id) -{ - struct sphw_hwdev *dev = hwdev; - struct cfg_mgmt_info *cfg_mgmt = NULL; - struct cfg_irq_info *irq_info = NULL; - struct irq_alloc_info_st *alloc_info = NULL; - int max_num_irq; - int i; - - if (!hwdev) - return; - - cfg_mgmt = dev->cfg_mgmt; - irq_info = &cfg_mgmt->irq_param_info; - alloc_info = irq_info->alloc_info; - max_num_irq = irq_info->num_total; - - mutex_lock(&irq_info->irq_mutex); - - for (i = 0; i < max_num_irq; i++) { - if (irq_id == alloc_info[i].info.irq_id && - type == alloc_info[i].type) { - if (alloc_info[i].free == CFG_BUSY) { - alloc_info[i].free = CFG_FREE; - irq_info->num_irq_remain++; - if (irq_info->num_irq_remain > max_num_irq) { - sdk_err(dev->dev_hdl, "Find target,but over range\n"); - mutex_unlock(&irq_info->irq_mutex); - return; - } - break; - } - } - } - - if (i >= max_num_irq) - sdk_warn(dev->dev_hdl, "Irq %u don`t need to free\n", irq_id); - - mutex_unlock(&irq_info->irq_mutex); -} - -int sphw_vector_to_irq(void *hwdev, enum sphw_service_type type, int vector) -{ - struct sphw_hwdev *dev = hwdev; - struct cfg_mgmt_info *cfg_mgmt = NULL; - struct irq_alloc_info_st *irq_info = NULL; - int irq = -EINVAL; - - if (!hwdev) - return -EINVAL; - - cfg_mgmt = dev->cfg_mgmt; - if (type != SERVICE_T_ROCE) { - sdk_err(dev->dev_hdl, - "Service type: %u, only RDMA service could get eqn by vector\n", - type); - return -EINVAL; - } - - /* Current RDMA CEQ are 2 - 31, will change in the future */ - vector = ((vector % cfg_mgmt->eq_info.num_ceq) + CFG_RDMA_CEQ_BASE); - - irq_info = cfg_mgmt->irq_param_info.alloc_info; - if (irq_info[vector].type == SERVICE_T_ROCE) - if (irq_info[vector].free == CFG_BUSY) - irq = (int)irq_info[vector].info.irq_id; - - return irq; -} - -int sphw_alloc_ceqs(void *hwdev, enum sphw_service_type type, int num, int *ceq_id_array, - int *act_num) -{ - struct sphw_hwdev *dev = hwdev; - struct cfg_mgmt_info *cfg_mgmt = NULL; - struct cfg_eq_info *eq = NULL; - int free_ceq; - int i, j; - - if (!hwdev || !ceq_id_array || !act_num) - return -EINVAL; - - cfg_mgmt = dev->cfg_mgmt; - eq = &cfg_mgmt->eq_info; - free_ceq = eq->num_ceq_remain; - - mutex_lock(&eq->eq_mutex); - - if (num > free_ceq) { - if (free_ceq <= 0) { - sdk_err(dev->dev_hdl, "No free ceq resource in cfg mgmt\n"); - mutex_unlock(&eq->eq_mutex); - return -ENOMEM; - } - - sdk_warn(dev->dev_hdl, "Only %d ceq resource in cfg mgmt\n", - free_ceq); - } - - *act_num = 0; - - num = min(num, eq->num_ceq - CFG_RDMA_CEQ_BASE); - for (i = 0; i < num; i++) { - if (eq->num_ceq_remain == 0) { - sdk_warn(dev->dev_hdl, "Alloc %d ceqs, less than required %d ceqs\n", - *act_num, num); - mutex_unlock(&eq->eq_mutex); - return 0; - } - - for (j = CFG_RDMA_CEQ_BASE; j < eq->num_ceq; j++) { - if (eq->eq[j].free == CFG_FREE) { - eq->eq[j].type = type; - eq->eq[j].free = CFG_BUSY; - eq->num_ceq_remain--; - ceq_id_array[i] = eq->eq[j].eqn; - (*act_num)++; - break; - } - } - } - - mutex_unlock(&eq->eq_mutex); - return 0; -} - -void sphw_free_ceq(void *hwdev, enum sphw_service_type type, int ceq_id) -{ - struct sphw_hwdev *dev = hwdev; - struct cfg_mgmt_info *cfg_mgmt = NULL; - struct cfg_eq_info *eq = NULL; - u8 num_ceq; - u8 i = 0; - - if (!hwdev) - return; - - cfg_mgmt = dev->cfg_mgmt; - eq = &cfg_mgmt->eq_info; - num_ceq = eq->num_ceq; - - mutex_lock(&eq->eq_mutex); - - for (i = 0; i < num_ceq; i++) { - if (ceq_id == eq->eq[i].eqn && - type == cfg_mgmt->eq_info.eq[i].type) { - if (eq->eq[i].free == CFG_BUSY) { - eq->eq[i].free = CFG_FREE; - eq->num_ceq_remain++; - if (eq->num_ceq_remain > num_ceq) - eq->num_ceq_remain %= num_ceq; - - mutex_unlock(&eq->eq_mutex); - return; - } - } - } - - if (i >= num_ceq) - sdk_warn(dev->dev_hdl, "ceq %d don`t need to free.\n", ceq_id); - - mutex_unlock(&eq->eq_mutex); -} - -int init_cfg_mgmt(struct sphw_hwdev *dev) -{ - int err; - struct cfg_mgmt_info *cfg_mgmt; - - cfg_mgmt = kzalloc(sizeof(*cfg_mgmt), GFP_KERNEL); - if (!cfg_mgmt) - return -ENOMEM; - - dev->cfg_mgmt = cfg_mgmt; - cfg_mgmt->hwdev = dev; - - err = cfg_init_eq(dev); - if (err) { - sdk_err(dev->dev_hdl, "Failed to init cfg event queue, err: %d\n", - err); - goto free_mgmt_mem; - } - - err = cfg_init_interrupt(dev); - if (err) { - sdk_err(dev->dev_hdl, "Failed to init cfg interrupt, err: %d\n", - err); - goto free_eq_mem; - } - - err = cfg_enable_interrupt(dev); - if (err) { - sdk_err(dev->dev_hdl, "Failed to enable cfg interrupt, err: %d\n", - err); - goto free_interrupt_mem; - } - - return 0; - -free_interrupt_mem: - kfree(cfg_mgmt->irq_param_info.alloc_info); - cfg_mgmt->irq_param_info.alloc_info = NULL; - -free_eq_mem: - kfree(cfg_mgmt->eq_info.eq); - cfg_mgmt->eq_info.eq = NULL; - -free_mgmt_mem: - kfree(cfg_mgmt); - return err; -} - -void free_cfg_mgmt(struct sphw_hwdev *dev) -{ - struct cfg_mgmt_info *cfg_mgmt = dev->cfg_mgmt; - - /* if the allocated resource were recycled */ - if (cfg_mgmt->irq_param_info.num_irq_remain != - cfg_mgmt->irq_param_info.num_total || - cfg_mgmt->eq_info.num_ceq_remain != cfg_mgmt->eq_info.num_ceq) - sdk_err(dev->dev_hdl, "Can't reclaim all irq and event queue, please check\n"); - - switch (cfg_mgmt->svc_cap.interrupt_type) { - case INTR_TYPE_MSIX: - pci_disable_msix(dev->pcidev_hdl); - break; - - case INTR_TYPE_MSI: - pci_disable_msi(dev->pcidev_hdl); - break; - - case INTR_TYPE_INT: - default: - break; - } - - kfree(cfg_mgmt->irq_param_info.alloc_info); - cfg_mgmt->irq_param_info.alloc_info = NULL; - - kfree(cfg_mgmt->eq_info.eq); - cfg_mgmt->eq_info.eq = NULL; - - kfree(cfg_mgmt); -} - -int init_capability(struct sphw_hwdev *dev) -{ - int err; - struct cfg_mgmt_info *cfg_mgmt = dev->cfg_mgmt; - - set_cfg_test_param(cfg_mgmt); - - cfg_mgmt->svc_cap.sf_svc_attr.ft_pf_en = false; - cfg_mgmt->svc_cap.sf_svc_attr.rdma_pf_en = false; - - err = sphw_get_dev_cap(dev); - if (err) - return err; - - init_service_param(dev); - - sdk_info(dev->dev_hdl, "Init capability success\n"); - return 0; -} - -void free_capability(struct sphw_hwdev *dev) -{ - sdk_info(dev->dev_hdl, "Free capability success"); -} - -bool sphw_support_nic(void *hwdev, struct nic_service_cap *cap) -{ - struct sphw_hwdev *dev = hwdev; - - if (!hwdev) - return false; - - if (!IS_NIC_TYPE(dev)) - return false; - - if (cap) - memcpy(cap, &dev->cfg_mgmt->svc_cap.nic_cap, sizeof(*cap)); - - return true; -} - -bool sphw_support_ipsec(void *hwdev, struct ipsec_service_cap *cap) -{ - struct sphw_hwdev *dev = hwdev; - - if (!hwdev) - return false; - - if (!IS_IPSEC_TYPE(dev)) - return false; - - if (cap) - memcpy(cap, &dev->cfg_mgmt->svc_cap.ipsec_cap, sizeof(*cap)); - - return true; -} - -bool sphw_support_roce(void *hwdev, struct rdma_service_cap *cap) -{ - struct sphw_hwdev *dev = hwdev; - - if (!hwdev) - return false; - - if (!IS_ROCE_TYPE(dev)) - return false; - - if (cap) - memcpy(cap, &dev->cfg_mgmt->svc_cap.rdma_cap, sizeof(*cap)); - - return true; -} - -bool sphw_support_fc(void *hwdev, struct fc_service_cap *cap) -{ - struct sphw_hwdev *dev = hwdev; - - if (!hwdev) - return false; - - if (!IS_FC_TYPE(dev)) - return false; - - if (cap) - memcpy(cap, &dev->cfg_mgmt->svc_cap.fc_cap, sizeof(*cap)); - - return true; -} - -bool sphw_support_rdma(void *hwdev, struct rdma_service_cap *cap) -{ - struct sphw_hwdev *dev = hwdev; - - if (!hwdev) - return false; - - if (!IS_RDMA_TYPE(dev)) - return false; - - if (cap) - memcpy(cap, &dev->cfg_mgmt->svc_cap.rdma_cap, sizeof(*cap)); - - return true; -} - -bool sphw_support_ovs(void *hwdev, struct ovs_service_cap *cap) -{ - struct sphw_hwdev *dev = hwdev; - - if (!hwdev) - return false; - - if (!IS_OVS_TYPE(dev)) - return false; - - if (cap) - memcpy(cap, &dev->cfg_mgmt->svc_cap.ovs_cap, sizeof(*cap)); - - return true; -} - -/* Only PPF support it, PF is not */ -bool sphw_support_toe(void *hwdev, struct toe_service_cap *cap) -{ - struct sphw_hwdev *dev = hwdev; - - if (!hwdev) - return false; - - if (!IS_TOE_TYPE(dev)) - return false; - - if (cap) - memcpy(cap, &dev->cfg_mgmt->svc_cap.toe_cap, sizeof(*cap)); - - return true; -} - -bool sphw_func_for_mgmt(void *hwdev) -{ - struct sphw_hwdev *dev = hwdev; - - if (!hwdev) - return false; - - if (dev->cfg_mgmt->svc_cap.chip_svc_type >= CFG_SVC_NIC_BIT0) - return false; - else - return true; -} - -bool sphw_get_stateful_enable(void *hwdev) -{ - struct sphw_hwdev *dev = hwdev; - - if (!hwdev) - return false; - - return dev->cfg_mgmt->svc_cap.sf_en; -} - -u8 sphw_host_oq_id_mask(void *hwdev) -{ - struct sphw_hwdev *dev = hwdev; - - if (!dev) { - pr_err("Hwdev pointer is NULL for getting host oq id mask\n"); - return 0; - } - return dev->cfg_mgmt->svc_cap.host_oq_id_mask_val; -} - -u8 sphw_host_id(void *hwdev) -{ - struct sphw_hwdev *dev = hwdev; - - if (!dev) { - pr_err("Hwdev pointer is NULL for getting host id\n"); - return 0; - } - return dev->cfg_mgmt->svc_cap.host_id; -} - -u16 sphw_host_total_func(void *hwdev) -{ - struct sphw_hwdev *dev = hwdev; - - if (!dev) { - pr_err("Hwdev pointer is NULL for getting host total function number\n"); - return 0; - } - return dev->cfg_mgmt->svc_cap.host_total_function; -} - -u16 sphw_func_max_qnum(void *hwdev) -{ - struct sphw_hwdev *dev = hwdev; - - if (!dev) { - pr_err("Hwdev pointer is NULL for getting function max queue number\n"); - return 0; - } - return dev->cfg_mgmt->svc_cap.nic_cap.max_sqs; -} - -u16 sphw_func_max_nic_qnum(void *hwdev) -{ - struct sphw_hwdev *dev = hwdev; - - if (!dev) { - pr_err("Hwdev pointer is NULL for getting function max queue number\n"); - return 0; - } - return dev->cfg_mgmt->svc_cap.nic_cap.max_sqs; -} - -u8 sphw_ep_id(void *hwdev) -{ - struct sphw_hwdev *dev = hwdev; - - if (!dev) { - pr_err("Hwdev pointer is NULL for getting ep id\n"); - return 0; - } - return dev->cfg_mgmt->svc_cap.ep_id; -} - -u8 sphw_er_id(void *hwdev) -{ - struct sphw_hwdev *dev = hwdev; - - if (!dev) { - pr_err("Hwdev pointer is NULL for getting er id\n"); - return 0; - } - return dev->cfg_mgmt->svc_cap.er_id; -} - -u8 sphw_physical_port_id(void *hwdev) -{ - struct sphw_hwdev *dev = hwdev; - - if (!dev) { - pr_err("Hwdev pointer is NULL for getting physical port id\n"); - return 0; - } - return dev->cfg_mgmt->svc_cap.port_id; -} - -u16 sphw_func_max_vf(void *hwdev) -{ - struct sphw_hwdev *dev = hwdev; - - if (!dev) { - pr_err("Hwdev pointer is NULL for getting max vf number\n"); - return 0; - } - return dev->cfg_mgmt->svc_cap.max_vf; -} - -u8 sphw_cos_valid_bitmap(void *hwdev) -{ - struct sphw_hwdev *dev = hwdev; - - if (!dev) { - pr_err("Hwdev pointer is NULL for getting cos valid bitmap\n"); - return 0; - } - return (u8)(dev->cfg_mgmt->svc_cap.cos_valid_bitmap); -} - -void sphw_shutdown_hwdev(void *hwdev) -{ - /* to do : if IS_SLAVE_HOST*/ -} - -u32 sphw_host_pf_num(void *hwdev) -{ - struct sphw_hwdev *dev = hwdev; - - if (!dev) { - pr_err("Hwdev pointer is NULL for getting pf number capability\n"); - return 0; - } - - return dev->cfg_mgmt->svc_cap.pf_num; -} - -u8 sphw_flexq_en(void *hwdev) -{ - struct sphw_hwdev *dev = hwdev; - - if (!hwdev) - return 0; - - return dev->cfg_mgmt->svc_cap.flexq_en; -} diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw_cfg.h b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw_cfg.h deleted file mode 100644 index 1b48e0991563..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw_cfg.h +++ /dev/null @@ -1,329 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPHW_HW_CFG_H -#define SPHW_HW_CFG_H - -#include <linux/types.h> - -#define CFG_MAX_CMD_TIMEOUT 30000 /* ms */ - -enum { - CFG_FREE = 0, - CFG_BUSY = 1 -}; - -/* start position for CEQs allocation, Max number of CEQs is 32 */ -enum { - CFG_RDMA_CEQ_BASE = 0 -}; - -enum { - SF_SVC_FT_BIT = (1 << 0), - SF_SVC_RDMA_BIT = (1 << 1), -}; - -/* RDMA resource */ -#define K_UNIT BIT(10) -#define M_UNIT BIT(20) -#define G_UNIT BIT(30) - -/* L2NIC */ -#define SPHW_CFG_MAX_QP 256 - -/* RDMA */ -#define RDMA_RSVD_QPS 2 -#define ROCE_MAX_WQES (32 * K_UNIT - 1) -#define IWARP_MAX_WQES (8 * K_UNIT) - -#define RDMA_MAX_SQ_SGE 32 - -#define ROCE_MAX_RQ_SGE 16 - -#define RDMA_MAX_SQ_DESC_SZ (1 * K_UNIT) - -/* (256B(cache_line_len) - 16B(ctrl_seg_len) - 64B(max_task_seg_len)) */ -#define ROCE_MAX_SQ_INLINE_DATA_SZ 912 - -#define ROCE_MAX_RQ_DESC_SZ 256 - -#define ROCE_QPC_ENTRY_SZ 512 - -#define WQEBB_SZ 64 - -#define ROCE_RDMARC_ENTRY_SZ 32 -#define ROCE_MAX_QP_INIT_RDMA 128 -#define ROCE_MAX_QP_DEST_RDMA 128 - -#define ROCE_MAX_SRQ_WQES (16 * K_UNIT - 1) -#define ROCE_RSVD_SRQS 0 -#define ROCE_MAX_SRQ_SGE 15 -#define ROCE_SRQC_ENTERY_SZ 64 - -#define RDMA_MAX_CQES (8 * M_UNIT - 1) -#define RDMA_RSVD_CQS 0 - -#define RDMA_CQC_ENTRY_SZ 128 - -#define RDMA_CQE_SZ 64 -#define RDMA_RSVD_MRWS 128 -#define RDMA_MPT_ENTRY_SZ 64 -#define RDMA_NUM_MTTS (1 * G_UNIT) -#define LOG_MTT_SEG 5 -#define MTT_ENTRY_SZ 8 -#define LOG_RDMARC_SEG 3 - -#define LOCAL_ACK_DELAY 15 -#define RDMA_NUM_PORTS 1 -#define ROCE_MAX_MSG_SZ (2 * G_UNIT) - -#define DB_PAGE_SZ (4 * K_UNIT) -#define DWQE_SZ 256 - -#define NUM_PD (128 * K_UNIT) -#define RSVD_PD 0 - -#define MAX_XRCDS (64 * K_UNIT) -#define RSVD_XRCDS 0 - -#define MAX_GID_PER_PORT 128 -#define GID_ENTRY_SZ 32 -#define RSVD_LKEY ((RDMA_RSVD_MRWS - 1) << 8) -#define NUM_COMP_VECTORS 32 -#define PAGE_SZ_CAP ((1UL << 12) | (1UL << 16) | (1UL << 21)) -#define ROCE_MODE 1 - -#define MAX_FRPL_LEN 511 -#define MAX_PKEYS 1 - -/* ToE */ -#define TOE_PCTX_SZ 1024 -#define TOE_CQC_SZ 64 - -/* IoE */ -#define IOE_PCTX_SZ 512 - -/* FC */ -#define FC_PCTX_SZ 256 -#define FC_CCTX_SZ 256 -#define FC_SQE_SZ 128 -#define FC_SCQC_SZ 64 -#define FC_SCQE_SZ 64 -#define FC_SRQC_SZ 64 -#define FC_SRQE_SZ 32 - -/* OVS */ -#define OVS_PCTX_SZ 512 - -/* IPsec */ -#define IPSEC_SACTX_SZ 512 - -struct dev_sf_svc_attr { - bool ft_en; /* business enable flag (not include RDMA) */ - bool ft_pf_en; /* In FPGA Test VF resource is in PF or not, - * 0 - VF, 1 - PF, VF doesn't need this bit. - */ - bool rdma_en; - bool rdma_pf_en;/* In FPGA Test VF RDMA resource is in PF or not, - * 0 - VF, 1 - PF, VF doesn't need this bit. - */ -}; - -struct host_shared_resource_cap { - u32 host_pctxs; /* Parent Context max 1M, IOE and FCoE max 8K flows */ - u32 host_cctxs; /* Child Context: max 8K */ - u32 host_scqs; /* shared CQ, chip interface module uses 1 SCQ - * TOE/IOE/FCoE each uses 1 SCQ - * RoCE/IWARP uses multiple SCQs - * So 6 SCQ least - */ - u32 host_srqs; /* SRQ number: 256K */ - u32 host_mpts; /* MR number:1M */ -}; - -enum intr_type { - INTR_TYPE_MSIX, - INTR_TYPE_MSI, - INTR_TYPE_INT, - INTR_TYPE_NONE, - /* PXE,OVS need single thread processing, - * synchronization messages must use poll wait mechanism interface - */ -}; - -/* service type relates define */ -enum cfg_svc_type_en { - CFG_SVC_NIC_BIT0 = (1 << 0), - CFG_SVC_ROCE_BIT1 = (1 << 1), - CFG_SVC_VBS_BIT2 = (1 << 2), - CFG_SVC_TOE_BIT3 = (1 << 3), - CFG_SVC_IPSEC_BIT4 = (1 << 4), - CFG_SVC_FC_BIT5 = (1 << 5), - CFG_SVC_VIRTIO_BIT6 = (1 << 6), - CFG_SVC_OVS_BIT7 = (1 << 7), - CFG_SVC_RSV2_BIT8 = (1 << 8), - CFG_SVC_IOE_BIT9 = (1 << 9), - - CFG_SVC_FT_EN = (CFG_SVC_VBS_BIT2 | CFG_SVC_TOE_BIT3 | - CFG_SVC_IPSEC_BIT4 | CFG_SVC_FC_BIT5 | - CFG_SVC_VIRTIO_BIT6 | CFG_SVC_OVS_BIT7 | - CFG_SVC_IOE_BIT9), - CFG_SVC_RDMA_EN = CFG_SVC_ROCE_BIT1 -}; - -/* device capability */ -struct service_cap { - struct dev_sf_svc_attr sf_svc_attr; - enum cfg_svc_type_en svc_type; /* user input service type */ - enum cfg_svc_type_en chip_svc_type; /* HW supported service type */ - - u8 host_id; - u8 ep_id; - u8 er_id; /* PF/VF's ER */ - u8 port_id; /* PF/VF's physical port */ - - /* Host global resources */ - u16 host_total_function; - u8 pf_num; - u8 pf_id_start; - u16 vf_num; /* max numbers of vf in current host */ - u16 vf_id_start; - u8 host_oq_id_mask_val; - - u8 flexq_en; - u8 cos_valid_bitmap; - u16 max_vf; /* max VF number that PF supported */ - - /* DO NOT get interrupt_type from firmware */ - enum intr_type interrupt_type; - - bool sf_en; /* stateful business status */ - u8 timer_en; /* 0:disable, 1:enable */ - u8 bloomfilter_en; /* 0:disable, 1:enable*/ - - u8 lb_mode; - u8 smf_pg; - - /* For test */ - u32 test_mode; - u32 test_qpc_num; - u32 test_qpc_resvd_num; - u32 test_page_size_reorder; - bool test_xid_alloc_mode; - bool test_gpa_check_enable; - u8 test_qpc_alloc_mode; - u8 test_scqc_alloc_mode; - - u32 test_max_conn_num; - u32 test_max_cache_conn_num; - u32 test_scqc_num; - u32 test_mpt_num; - u32 test_scq_resvd_num; - u32 test_mpt_recvd_num; - u32 test_hash_num; - u32 test_reorder_num; - - u32 max_connect_num; /* PF/VF maximum connection number(1M) */ - /* The maximum connections which can be stick to cache memory, max 1K */ - u16 max_stick2cache_num; - /* Starting address in cache memory for bloom filter, 64Bytes aligned */ - u16 bfilter_start_addr; - /* Length for bloom filter, aligned on 64Bytes. The size is length*64B. - * Bloom filter memory size + 1 must be power of 2. - * The maximum memory size of bloom filter is 4M - */ - u16 bfilter_len; - /* The size of hash bucket tables, align on 64 entries. - * Be used to AND (&) the hash value. Bucket Size +1 must be power of 2. - * The maximum number of hash bucket is 4M - */ - u16 hash_bucket_num; - - struct host_shared_resource_cap shared_res_cap; /* shared capability */ - struct nic_service_cap nic_cap; /* NIC capability */ - struct rdma_service_cap rdma_cap; /* RDMA capability */ - struct fc_service_cap fc_cap; /* FC capability */ - struct toe_service_cap toe_cap; /* ToE capability */ - struct ovs_service_cap ovs_cap; /* OVS capability */ - struct ipsec_service_cap ipsec_cap; /* IPsec capability */ -}; - -struct cfg_eq { - enum sphw_service_type type; - int eqn; - int free; /* 1 - alocated, 0- freed */ -}; - -struct cfg_eq_info { - struct cfg_eq *eq; - - u8 num_ceq; - - u8 num_ceq_remain; - - /* mutex used for allocate EQs */ - struct mutex eq_mutex; -}; - -struct irq_alloc_info_st { - enum sphw_service_type type; - int free; /* 1 - alocated, 0- freed */ - struct irq_info info; -}; - -struct cfg_irq_info { - struct irq_alloc_info_st *alloc_info; - u16 num_total; - u16 num_irq_remain; - u16 num_irq_hw; /* device max irq number */ - - /* mutex used for allocate EQs */ - struct mutex irq_mutex; -}; - -#define VECTOR_THRESHOLD 2 - -struct cfg_mgmt_info { - struct sphw_hwdev *hwdev; - struct service_cap svc_cap; - struct cfg_eq_info eq_info; /* EQ */ - struct cfg_irq_info irq_param_info; /* IRQ */ - u32 func_seq_num; /* temporary */ -}; - -#define IS_NIC_TYPE(dev) \ - (((u32)(dev)->cfg_mgmt->svc_cap.chip_svc_type) & CFG_SVC_NIC_BIT0) -#define IS_ROCE_TYPE(dev) \ - (((u32)(dev)->cfg_mgmt->svc_cap.chip_svc_type) & CFG_SVC_ROCE_BIT1) -#define IS_FCOE_TYPE(dev) \ - (((u32)(dev)->cfg_mgmt->svc_cap.chip_svc_type) & CFG_SVC_FCOE_BIT2) -#define IS_TOE_TYPE(dev) \ - (((u32)(dev)->cfg_mgmt->svc_cap.chip_svc_type) & CFG_SVC_TOE_BIT3) -#define IS_IPSEC_TYPE(dev) \ - (((u32)(dev)->cfg_mgmt->svc_cap.chip_svc_type) & CFG_SVC_IPSEC_BIT4) -#define IS_FC_TYPE(dev) \ - (((u32)(dev)->cfg_mgmt->svc_cap.chip_svc_type) & CFG_SVC_FC_BIT5) -#define IS_FIC_TYPE(dev) \ - (((u32)(dev)->cfg_mgmt->svc_cap.chip_svc_type) & CFG_SVC_FIC_BIT6) -#define IS_OVS_TYPE(dev) \ - (((u32)(dev)->cfg_mgmt->svc_cap.chip_svc_type) & CFG_SVC_OVS_BIT7) -#define IS_ACL_TYPE(dev) \ - (((u32)(dev)->cfg_mgmt->svc_cap.chip_svc_type) & CFG_SVC_ACL_BIT8) -#define IS_IOE_TYPE(dev) \ - (((u32)(dev)->cfg_mgmt->svc_cap.chip_svc_type) & CFG_SVC_IOE_BIT9) -#define IS_FT_TYPE(dev) \ - (((u32)(dev)->cfg_mgmt->svc_cap.chip_svc_type) & CFG_SVC_FT_EN) -#define IS_RDMA_TYPE(dev) \ - (((u32)(dev)->cfg_mgmt->svc_cap.chip_svc_type) & CFG_SVC_RDMA_EN) -#define IS_RDMA_ENABLE(dev) \ - ((dev)->cfg_mgmt->svc_cap.sf_svc_attr.rdma_en) - -int init_cfg_mgmt(struct sphw_hwdev *dev); - -void free_cfg_mgmt(struct sphw_hwdev *dev); - -int init_capability(struct sphw_hwdev *dev); - -void free_capability(struct sphw_hwdev *dev); - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw_comm.c b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw_comm.c deleted file mode 100644 index b868bf8ed1cb..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw_comm.c +++ /dev/null @@ -1,1280 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/types.h> -#include <linux/delay.h> -#include <linux/module.h> -#include <linux/completion.h> -#include <linux/semaphore.h> -#include <linux/interrupt.h> - -#include "sphw_crm.h" -#include "sphw_hw.h" -#include "sphw_common.h" -#include "sphw_csr.h" -#include "sphw_hwdev.h" -#include "sphw_hwif.h" -#include "sphw_wq.h" -#include "sphw_cmdq.h" -#include "sphw_comm_msg_intf.h" -#include "sphw_hw_comm.h" - -#define SPHW_MSIX_CNT_LLI_TIMER_SHIFT 0 -#define SPHW_MSIX_CNT_LLI_CREDIT_SHIFT 8 -#define SPHW_MSIX_CNT_COALESC_TIMER_SHIFT 8 -#define SPHW_MSIX_CNT_PENDING_SHIFT 8 -#define SPHW_MSIX_CNT_RESEND_TIMER_SHIFT 29 - -#define SPHW_MSIX_CNT_LLI_TIMER_MASK 0xFFU -#define SPHW_MSIX_CNT_LLI_CREDIT_MASK 0xFFU -#define SPHW_MSIX_CNT_COALESC_TIMER_MASK 0xFFU -#define SPHW_MSIX_CNT_PENDING_MASK 0x1FU -#define SPHW_MSIX_CNT_RESEND_TIMER_MASK 0x7U - -#define SPHW_MSIX_CNT_SET(val, member) \ - (((val) & SPHW_MSIX_CNT_##member##_MASK) << \ - SPHW_MSIX_CNT_##member##_SHIFT) - -#define DEFAULT_RX_BUF_SIZE ((u16)0xB) - -enum sphw_rx_buf_size { - SPHW_RX_BUF_SIZE_32B = 0x20, - SPHW_RX_BUF_SIZE_64B = 0x40, - SPHW_RX_BUF_SIZE_96B = 0x60, - SPHW_RX_BUF_SIZE_128B = 0x80, - SPHW_RX_BUF_SIZE_192B = 0xC0, - SPHW_RX_BUF_SIZE_256B = 0x100, - SPHW_RX_BUF_SIZE_384B = 0x180, - SPHW_RX_BUF_SIZE_512B = 0x200, - SPHW_RX_BUF_SIZE_768B = 0x300, - SPHW_RX_BUF_SIZE_1K = 0x400, - SPHW_RX_BUF_SIZE_1_5K = 0x600, - SPHW_RX_BUF_SIZE_2K = 0x800, - SPHW_RX_BUF_SIZE_3K = 0xC00, - SPHW_RX_BUF_SIZE_4K = 0x1000, - SPHW_RX_BUF_SIZE_8K = 0x2000, - SPHW_RX_BUF_SIZE_16K = 0x4000, -}; - -const int sphw_hw_rx_buf_size[] = { - SPHW_RX_BUF_SIZE_32B, - SPHW_RX_BUF_SIZE_64B, - SPHW_RX_BUF_SIZE_96B, - SPHW_RX_BUF_SIZE_128B, - SPHW_RX_BUF_SIZE_192B, - SPHW_RX_BUF_SIZE_256B, - SPHW_RX_BUF_SIZE_384B, - SPHW_RX_BUF_SIZE_512B, - SPHW_RX_BUF_SIZE_768B, - SPHW_RX_BUF_SIZE_1K, - SPHW_RX_BUF_SIZE_1_5K, - SPHW_RX_BUF_SIZE_2K, - SPHW_RX_BUF_SIZE_3K, - SPHW_RX_BUF_SIZE_4K, - SPHW_RX_BUF_SIZE_8K, - SPHW_RX_BUF_SIZE_16K, -}; - -static inline int comm_msg_to_mgmt_sync(void *hwdev, u16 cmd, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size) -{ - return sphw_msg_to_mgmt_sync(hwdev, SPHW_MOD_COMM, cmd, buf_in, in_size, buf_out, - out_size, 0, SPHW_CHANNEL_COMM); -} - -static inline int comm_msg_to_mgmt_sync_ch(void *hwdev, u16 cmd, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size, u16 channel) -{ - return sphw_msg_to_mgmt_sync(hwdev, SPHW_MOD_COMM, cmd, buf_in, - in_size, buf_out, out_size, 0, channel); -} - -int sphw_get_interrupt_cfg(void *dev, struct interrupt_info *info, u16 channel) -{ - struct sphw_hwdev *hwdev = dev; - struct comm_cmd_msix_config msix_cfg; - u16 out_size = sizeof(msix_cfg); - int err; - - if (!hwdev || !info) - return -EINVAL; - - memset(&msix_cfg, 0, sizeof(msix_cfg)); - msix_cfg.func_id = sphw_global_func_id(hwdev); - msix_cfg.msix_index = info->msix_index; - msix_cfg.opcode = MGMT_MSG_CMD_OP_GET; - - err = comm_msg_to_mgmt_sync_ch(hwdev, COMM_MGMT_CMD_CFG_MSIX_CTRL_REG, - &msix_cfg, sizeof(msix_cfg), &msix_cfg, - &out_size, channel); - if (err || !out_size || msix_cfg.head.status) { - sdk_err(hwdev->dev_hdl, "Failed to get interrupt config, err: %d, status: 0x%x, out size: 0x%x, channel: 0x%x\n", - err, msix_cfg.head.status, out_size, channel); - return -EINVAL; - } - - info->lli_credit_limit = msix_cfg.lli_credit_cnt; - info->lli_timer_cfg = msix_cfg.lli_timer_cnt; - info->pending_limt = msix_cfg.pending_cnt; - info->coalesc_timer_cfg = msix_cfg.coalesce_timer_cnt; - info->resend_timer_cfg = msix_cfg.resend_timer_cnt; - - return 0; -} - -int sphw_set_interrupt_cfg_direct(void *hwdev, struct interrupt_info *info, u16 channel) -{ - struct comm_cmd_msix_config msix_cfg; - u16 out_size = sizeof(msix_cfg); - int err; - - if (!hwdev) - return -EINVAL; - - memset(&msix_cfg, 0, sizeof(msix_cfg)); - msix_cfg.func_id = sphw_global_func_id(hwdev); - msix_cfg.msix_index = (u16)info->msix_index; - msix_cfg.opcode = MGMT_MSG_CMD_OP_SET; - - msix_cfg.lli_credit_cnt = info->lli_credit_limit; - msix_cfg.lli_timer_cnt = info->lli_timer_cfg; - msix_cfg.pending_cnt = info->pending_limt; - msix_cfg.coalesce_timer_cnt = info->coalesc_timer_cfg; - msix_cfg.resend_timer_cnt = info->resend_timer_cfg; - - err = comm_msg_to_mgmt_sync_ch(hwdev, COMM_MGMT_CMD_CFG_MSIX_CTRL_REG, - &msix_cfg, sizeof(msix_cfg), &msix_cfg, - &out_size, channel); - if (err || !out_size || msix_cfg.head.status) { - sdk_err(((struct sphw_hwdev *)hwdev)->dev_hdl, - "Failed to set interrupt config, err: %d, status: 0x%x, out size: 0x%x, channel: 0x%x\n", - err, msix_cfg.head.status, out_size, channel); - return -EINVAL; - } - - return 0; -} - -int sphw_set_interrupt_cfg(void *dev, struct interrupt_info info, u16 channel) -{ - struct interrupt_info temp_info; - struct sphw_hwdev *hwdev = dev; - int err; - - if (!hwdev) - return -EINVAL; - - temp_info.msix_index = info.msix_index; - - err = sphw_get_interrupt_cfg(hwdev, &temp_info, channel); - if (err) - return -EINVAL; - - if (!info.lli_set) { - info.lli_credit_limit = temp_info.lli_credit_limit; - info.lli_timer_cfg = temp_info.lli_timer_cfg; - } - - if (!info.interrupt_coalesc_set) { - info.pending_limt = temp_info.pending_limt; - info.coalesc_timer_cfg = temp_info.coalesc_timer_cfg; - info.resend_timer_cfg = temp_info.resend_timer_cfg; - } - - return sphw_set_interrupt_cfg_direct(hwdev, &info, channel); -} - -void sphw_misx_intr_clear_resend_bit(void *hwdev, u16 msix_idx, u8 clear_resend_en) -{ - struct sphw_hwif *hwif = NULL; - u32 msix_ctrl = 0, addr; - - if (!hwdev) - return; - - hwif = ((struct sphw_hwdev *)hwdev)->hwif; - - msix_ctrl = SPHW_MSI_CLR_INDIR_SET(msix_idx, SIMPLE_INDIR_IDX) | - SPHW_MSI_CLR_INDIR_SET(clear_resend_en, RESEND_TIMER_CLR); - - addr = SPHW_CSR_FUNC_MSI_CLR_WR_ADDR; - sphw_hwif_write_reg(hwif, addr, msix_ctrl); -} - -int sphw_set_wq_page_size(void *hwdev, u16 func_idx, u32 page_size, u16 channel) -{ - struct comm_cmd_wq_page_size page_size_info; - u16 out_size = sizeof(page_size_info); - int err; - - memset(&page_size_info, 0, sizeof(page_size_info)); - page_size_info.func_id = func_idx; - page_size_info.page_size = SPHW_PAGE_SIZE_HW(page_size); - page_size_info.opcode = MGMT_MSG_CMD_OP_SET; - - err = comm_msg_to_mgmt_sync_ch(hwdev, COMM_MGMT_CMD_CFG_PAGESIZE, - &page_size_info, sizeof(page_size_info), - &page_size_info, &out_size, channel); - if (err || !out_size || page_size_info.head.status) { - sdk_err(((struct sphw_hwdev *)hwdev)->dev_hdl, "Failed to set wq page size, err: %d, status: 0x%x, out_size: 0x%0x, channel: 0x%x\n", - err, page_size_info.head.status, out_size, channel); - return -EFAULT; - } - - return 0; -} - -int sphw_func_reset(void *dev, u16 func_id, u64 reset_flag, u16 channel) -{ - struct comm_cmd_func_reset func_reset; - struct sphw_hwdev *hwdev = dev; - u16 out_size = sizeof(func_reset); - int err = 0; - - if (!dev) { - pr_err("Invalid para: dev is null.\n"); - return -EINVAL; - } - - sdk_info(hwdev->dev_hdl, "Function is reset, flag: 0x%llx, channel:0x%x\n", - reset_flag, channel); - - memset(&func_reset, 0, sizeof(func_reset)); - func_reset.func_id = func_id; - func_reset.reset_flag = reset_flag; - err = comm_msg_to_mgmt_sync_ch(hwdev, COMM_MGMT_CMD_FUNC_RESET, - &func_reset, sizeof(func_reset), - &func_reset, &out_size, channel); - if (err || !out_size || func_reset.head.status) { - sdk_err(hwdev->dev_hdl, "Failed to reset func resources, reset_flag 0x%llx, err: %d, status: 0x%x, out_size: 0x%x\n", - reset_flag, err, func_reset.head.status, out_size); - return -EIO; - } - - return 0; -} - -static u16 get_hw_rx_buf_size(int rx_buf_sz) -{ - u16 num_hw_types = - sizeof(sphw_hw_rx_buf_size) / - sizeof(sphw_hw_rx_buf_size[0]); - u16 i; - - for (i = 0; i < num_hw_types; i++) { - if (sphw_hw_rx_buf_size[i] == rx_buf_sz) - return i; - } - - pr_err("Chip can't support rx buf size of %d\n", rx_buf_sz); - - return DEFAULT_RX_BUF_SIZE; /* default 2K */ -} - -int sphw_set_root_ctxt(void *hwdev, u32 rq_depth, u32 sq_depth, int rx_buf_sz, u16 channel) -{ - struct comm_cmd_root_ctxt root_ctxt; - u16 out_size = sizeof(root_ctxt); - int err; - - if (!hwdev) - return -EINVAL; - - memset(&root_ctxt, 0, sizeof(root_ctxt)); - root_ctxt.func_id = sphw_global_func_id(hwdev); - - root_ctxt.set_cmdq_depth = 0; - root_ctxt.cmdq_depth = 0; - - root_ctxt.lro_en = 1; - - root_ctxt.rq_depth = (u16)ilog2(rq_depth); - root_ctxt.rx_buf_sz = get_hw_rx_buf_size(rx_buf_sz); - root_ctxt.sq_depth = (u16)ilog2(sq_depth); - - err = comm_msg_to_mgmt_sync_ch(hwdev, COMM_MGMT_CMD_SET_VAT, - &root_ctxt, sizeof(root_ctxt), - &root_ctxt, &out_size, channel); - if (err || !out_size || root_ctxt.head.status) { - sdk_err(((struct sphw_hwdev *)hwdev)->dev_hdl, - "Failed to set root context, err: %d, status: 0x%x, out_size: 0x%x, channel: 0x%x\n", - err, root_ctxt.head.status, out_size, channel); - return -EFAULT; - } - - return 0; -} - -int sphw_clean_root_ctxt(void *hwdev, u16 channel) -{ - struct comm_cmd_root_ctxt root_ctxt; - u16 out_size = sizeof(root_ctxt); - int err; - - if (!hwdev) - return -EINVAL; - - memset(&root_ctxt, 0, sizeof(root_ctxt)); - root_ctxt.func_id = sphw_global_func_id(hwdev); - - err = comm_msg_to_mgmt_sync_ch(hwdev, COMM_MGMT_CMD_SET_VAT, - &root_ctxt, sizeof(root_ctxt), - &root_ctxt, &out_size, channel); - if (err || !out_size || root_ctxt.head.status) { - sdk_err(((struct sphw_hwdev *)hwdev)->dev_hdl, - "Failed to set root context, err: %d, status: 0x%x, out_size: 0x%x, channel: 0x%x\n", - err, root_ctxt.head.status, out_size, channel); - return -EFAULT; - } - - return 0; -} - -int sphw_set_cmdq_depth(void *hwdev, u16 cmdq_depth) -{ - struct comm_cmd_root_ctxt root_ctxt; - u16 out_size = sizeof(root_ctxt); - int err; - - memset(&root_ctxt, 0, sizeof(root_ctxt)); - root_ctxt.func_id = sphw_global_func_id(hwdev); - - root_ctxt.set_cmdq_depth = 1; - root_ctxt.cmdq_depth = (u8)ilog2(cmdq_depth); - - err = comm_msg_to_mgmt_sync(hwdev, COMM_MGMT_CMD_SET_VAT, &root_ctxt, - sizeof(root_ctxt), &root_ctxt, &out_size); - if (err || !out_size || root_ctxt.head.status) { - sdk_err(((struct sphw_hwdev *)hwdev)->dev_hdl, - "Failed to set cmdq depth, err: %d, status: 0x%x, out_size: 0x%x\n", - err, root_ctxt.head.status, out_size); - return -EFAULT; - } - - return 0; -} - -int sphw_set_cmdq_ctxt(struct sphw_hwdev *hwdev, u8 cmdq_id, struct cmdq_ctxt_info *ctxt) -{ - struct comm_cmd_cmdq_ctxt cmdq_ctxt; - u16 out_size = sizeof(cmdq_ctxt); - int err; - - memset(&cmdq_ctxt, 0, sizeof(cmdq_ctxt)); - memcpy(&cmdq_ctxt.ctxt, ctxt, sizeof(*ctxt)); - cmdq_ctxt.func_id = sphw_global_func_id(hwdev); - cmdq_ctxt.cmdq_id = cmdq_id; - - err = comm_msg_to_mgmt_sync(hwdev, COMM_MGMT_CMD_SET_CMDQ_CTXT, - &cmdq_ctxt, sizeof(cmdq_ctxt), - &cmdq_ctxt, &out_size); - if (err || !out_size || cmdq_ctxt.head.status) { - sdk_err(hwdev->dev_hdl, "Failed to set cmdq ctxt, err: %d, status: 0x%x, out_size: 0x%x\n", - err, cmdq_ctxt.head.status, out_size); - return -EFAULT; - } - - return 0; -} - -int sphw_set_ceq_ctrl_reg(struct sphw_hwdev *hwdev, u16 q_id, u32 ctrl0, u32 ctrl1) -{ - struct comm_cmd_ceq_ctrl_reg ceq_ctrl; - u16 out_size = sizeof(ceq_ctrl); - int err; - - memset(&ceq_ctrl, 0, sizeof(ceq_ctrl)); - ceq_ctrl.func_id = sphw_global_func_id(hwdev); - ceq_ctrl.q_id = q_id; - ceq_ctrl.ctrl0 = ctrl0; - ceq_ctrl.ctrl1 = ctrl1; - - err = comm_msg_to_mgmt_sync(hwdev, COMM_MGMT_CMD_SET_CEQ_CTRL_REG, - &ceq_ctrl, sizeof(ceq_ctrl), - &ceq_ctrl, &out_size); - if (err || !out_size || ceq_ctrl.head.status) { - sdk_err(hwdev->dev_hdl, "Failed to set ceq %u ctrl reg, err: %d status: 0x%x, out_size: 0x%x\n", - q_id, err, ceq_ctrl.head.status, out_size); - return -EFAULT; - } - - return 0; -} - -int sphw_set_dma_attr_tbl(struct sphw_hwdev *hwdev, u8 entry_idx, u8 st, u8 at, u8 ph, - u8 no_snooping, u8 tph_en) -{ - struct comm_cmd_dma_attr_config dma_attr; - u16 out_size = sizeof(dma_attr); - int err; - - memset(&dma_attr, 0, sizeof(dma_attr)); - dma_attr.func_id = sphw_global_func_id(hwdev); - dma_attr.entry_idx = entry_idx; - dma_attr.st = st; - dma_attr.at = at; - dma_attr.ph = ph; - dma_attr.no_snooping = no_snooping; - dma_attr.tph_en = tph_en; - - err = comm_msg_to_mgmt_sync(hwdev, COMM_MGMT_CMD_SET_DMA_ATTR, &dma_attr, sizeof(dma_attr), - &dma_attr, &out_size); - if (err || !out_size || dma_attr.head.status) { - sdk_err(hwdev->dev_hdl, "Failed to set dma_attr, err: %d, status: 0x%x, out_size: 0x%x\n", - err, dma_attr.head.status, out_size); - return -EIO; - } - - return 0; -} - -int sphw_set_bdf_ctxt(void *hwdev, u8 bus, u8 device, u8 function) -{ - struct comm_cmd_bdf_info bdf_info; - u16 out_size = sizeof(bdf_info); - int err; - - if (!hwdev) - return -EINVAL; - - memset(&bdf_info, 0, sizeof(bdf_info)); - bdf_info.function_idx = sphw_global_func_id(hwdev); - bdf_info.bus = bus; - bdf_info.device = device; - bdf_info.function = function; - - err = comm_msg_to_mgmt_sync(hwdev, COMM_MGMT_CMD_SEND_BDF_INFO, - &bdf_info, sizeof(bdf_info), - &bdf_info, &out_size); - if (err || !out_size || bdf_info.head.status) { - sdk_err(((struct sphw_hwdev *)hwdev)->dev_hdl, - "Failed to set bdf info to MPU, err: %d, status: 0x%x, out_size: 0x%x\n", - err, bdf_info.head.status, out_size); - return -EIO; - } - - return 0; -} - -int sphw_sync_time(void *hwdev, u64 time) -{ - struct comm_cmd_sync_time time_info; - u16 out_size = sizeof(time_info); - int err; - - memset(&time_info, 0, sizeof(time_info)); - time_info.mstime = time; - err = comm_msg_to_mgmt_sync(hwdev, COMM_MGMT_CMD_SYNC_TIME, &time_info, - sizeof(time_info), &time_info, &out_size); - if (err || time_info.head.status || !out_size) { - sdk_err(((struct sphw_hwdev *)hwdev)->dev_hdl, - "Failed to sync time to mgmt, err: %d, status: 0x%x, out size: 0x%x\n", - err, time_info.head.status, out_size); - return -EIO; - } - - return 0; -} - -int sphw_get_fw_ver(void *hwdev, enum sphw_fw_ver_type type, u8 *mgmt_ver, - u8 version_size, u16 channel) -{ - struct comm_cmd_get_fw_version fw_ver; - struct sphw_hwdev *dev = hwdev; - u16 out_size = sizeof(fw_ver); - int err; - - if (!hwdev || !mgmt_ver) - return -EINVAL; - - memset(&fw_ver, 0, sizeof(fw_ver)); - fw_ver.fw_type = type; - err = comm_msg_to_mgmt_sync_ch(hwdev, COMM_MGMT_CMD_GET_FW_VERSION, - &fw_ver, sizeof(fw_ver), &fw_ver, - &out_size, channel); - if (err || !out_size || fw_ver.head.status) { - sdk_err(dev->dev_hdl, "Failed to get fw version, err: %d, status: 0x%x, out size: 0x%x, channel: 0x%x\n", - err, fw_ver.head.status, out_size, channel); - return -EIO; - } - - snprintf(mgmt_ver, version_size, "%s", fw_ver.ver); - - return 0; -} - -int sphw_get_mgmt_version(void *hwdev, u8 *mgmt_ver, u8 version_size, u16 channel) -{ - return sphw_get_fw_ver(hwdev, SPHW_FW_VER_TYPE_MPU, mgmt_ver, version_size, channel); -} - -int sphw_get_fw_version(void *hwdev, struct sphw_fw_version *fw_ver, u16 channel) -{ - int err; - - if (!hwdev || !fw_ver) - return -EINVAL; - - err = sphw_get_fw_ver(hwdev, SPHW_FW_VER_TYPE_MPU, fw_ver->mgmt_ver, - sizeof(fw_ver->mgmt_ver), channel); - if (err) - return err; - - err = sphw_get_fw_ver(hwdev, SPHW_FW_VER_TYPE_NPU, fw_ver->microcode_ver, - sizeof(fw_ver->microcode_ver), channel); - if (err) - return err; - - return sphw_get_fw_ver(hwdev, SPHW_FW_VER_TYPE_BOOT, fw_ver->boot_ver, - sizeof(fw_ver->boot_ver), channel); -} - -static int sphw_comm_features_nego(void *hwdev, u8 opcode, u64 *s_feature, u16 size) -{ - struct comm_cmd_feature_nego feature_nego; - u16 out_size = sizeof(feature_nego); - struct sphw_hwdev *dev = hwdev; - int err; - - if (!hwdev || !s_feature || size > COMM_MAX_FEATURE_QWORD) - return -EINVAL; - - memset(&feature_nego, 0, sizeof(feature_nego)); - feature_nego.func_id = sphw_global_func_id(hwdev); - feature_nego.opcode = opcode; - if (opcode == MGMT_MSG_CMD_OP_SET) - memcpy(feature_nego.s_feature, s_feature, (size * sizeof(u64))); - - err = comm_msg_to_mgmt_sync(hwdev, COMM_MGMT_CMD_FEATURE_NEGO, - &feature_nego, sizeof(feature_nego), - &feature_nego, &out_size); - if (err || !out_size || feature_nego.head.status) { - sdk_err(dev->dev_hdl, "Failed to negotiate feature, err: %d, status: 0x%x, out size: 0x%x\n", - err, feature_nego.head.status, out_size); - return -EINVAL; - } - - if (opcode == MGMT_MSG_CMD_OP_GET) - memcpy(s_feature, feature_nego.s_feature, (size * sizeof(u64))); - - return 0; -} - -int sphw_get_comm_features(void *hwdev, u64 *s_feature, u16 size) -{ - return sphw_comm_features_nego(hwdev, MGMT_MSG_CMD_OP_GET, s_feature, size); -} - -int sphw_set_comm_features(void *hwdev, u64 *s_feature, u16 size) -{ - return sphw_comm_features_nego(hwdev, MGMT_MSG_CMD_OP_SET, s_feature, size); -} - -int sphw_func_tmr_bitmap_set(void *hwdev, bool en) -{ - struct comm_cmd_func_tmr_bitmap_op bitmap_op; - u16 out_size = sizeof(bitmap_op); - int err; - - if (!hwdev) - return -EINVAL; - - memset(&bitmap_op, 0, sizeof(bitmap_op)); - bitmap_op.func_id = sphw_global_func_id(hwdev); - bitmap_op.opcode = en ? FUNC_TMR_BITMAP_ENABLE : - FUNC_TMR_BITMAP_DISABLE; - - err = comm_msg_to_mgmt_sync(hwdev, COMM_MGMT_CMD_SET_FUNC_TMR_BITMAT, - &bitmap_op, sizeof(bitmap_op), - &bitmap_op, &out_size); - if (err || !out_size || bitmap_op.head.status) { - sdk_err(((struct sphw_hwdev *)hwdev)->dev_hdl, - "Failed to set timer bitmap, err: %d, status: 0x%x, out_size: 0x%x\n", - err, bitmap_op.head.status, out_size); - return -EFAULT; - } - - return 0; -} - -int ppf_ht_gpa_set(struct sphw_hwdev *hwdev, struct sphw_page_addr *pg0, struct sphw_page_addr *pg1) -{ - struct comm_cmd_ht_gpa ht_gpa_set; - u16 out_size = sizeof(ht_gpa_set); - int ret; - - memset(&ht_gpa_set, 0, sizeof(ht_gpa_set)); - pg0->virt_addr = dma_alloc_coherent(hwdev->dev_hdl, SPHW_HT_GPA_PAGE_SIZE, - &pg0->phys_addr, GFP_KERNEL); - if (!pg0->virt_addr) { - sdk_err(hwdev->dev_hdl, "Alloc pg0 page addr failed\n"); - return -EFAULT; - } - - pg1->virt_addr = dma_alloc_coherent(hwdev->dev_hdl, SPHW_HT_GPA_PAGE_SIZE, - &pg1->phys_addr, GFP_KERNEL); - if (!pg1->virt_addr) { - sdk_err(hwdev->dev_hdl, "Alloc pg1 page addr failed\n"); - return -EFAULT; - } - - ht_gpa_set.host_id = sphw_host_id(hwdev); - ht_gpa_set.page_pa0 = pg0->phys_addr; - ht_gpa_set.page_pa1 = pg1->phys_addr; - sdk_info(hwdev->dev_hdl, "PPF ht gpa set: page_addr0.pa=0x%llx, page_addr1.pa=0x%llx\n", - pg0->phys_addr, pg1->phys_addr); - ret = comm_msg_to_mgmt_sync(hwdev, COMM_MGMT_CMD_SET_PPF_HT_GPA, - &ht_gpa_set, sizeof(ht_gpa_set), - &ht_gpa_set, &out_size); - if (ret || !out_size || ht_gpa_set.head.status) { - sdk_warn(hwdev->dev_hdl, "PPF ht gpa set failed, ret: %d, status: 0x%x, out_size: 0x%x\n", - ret, ht_gpa_set.head.status, out_size); - return -EFAULT; - } - - hwdev->page_pa0.phys_addr = pg0->phys_addr; - hwdev->page_pa0.virt_addr = pg0->virt_addr; - - hwdev->page_pa1.phys_addr = pg1->phys_addr; - hwdev->page_pa1.virt_addr = pg1->virt_addr; - - return 0; -} - -int sphw_ppf_ht_gpa_init(struct sphw_hwdev *hwdev) -{ - int ret; - int i; - int j; - int size; - - struct sphw_page_addr page_addr0[SPHW_PPF_HT_GPA_SET_RETRY_TIMES]; - struct sphw_page_addr page_addr1[SPHW_PPF_HT_GPA_SET_RETRY_TIMES]; - - size = SPHW_PPF_HT_GPA_SET_RETRY_TIMES * sizeof(page_addr0[0]); - memset(page_addr0, 0, size); - memset(page_addr1, 0, size); - - for (i = 0; i < SPHW_PPF_HT_GPA_SET_RETRY_TIMES; i++) { - ret = ppf_ht_gpa_set(hwdev, &page_addr0[i], &page_addr1[i]); - if (!ret) - break; - } - - for (j = 0; j < i; j++) { - if (page_addr0[j].virt_addr) { - dma_free_coherent(hwdev->dev_hdl, - SPHW_HT_GPA_PAGE_SIZE, - page_addr0[j].virt_addr, - page_addr0[j].phys_addr); - page_addr0[j].virt_addr = NULL; - } - if (page_addr1[j].virt_addr) { - dma_free_coherent(hwdev->dev_hdl, - SPHW_HT_GPA_PAGE_SIZE, - page_addr1[j].virt_addr, - page_addr1[j].phys_addr); - page_addr1[j].virt_addr = NULL; - } - } - - if (i >= SPHW_PPF_HT_GPA_SET_RETRY_TIMES) { - sdk_err(hwdev->dev_hdl, "PPF ht gpa init failed, retry times: %d\n", - i); - return -EFAULT; - } - - return 0; -} - -void sphw_ppf_ht_gpa_deinit(struct sphw_hwdev *hwdev) -{ - if (hwdev->page_pa0.virt_addr) { - dma_free_coherent(hwdev->dev_hdl, SPHW_HT_GPA_PAGE_SIZE, - hwdev->page_pa0.virt_addr, - hwdev->page_pa0.phys_addr); - hwdev->page_pa0.virt_addr = NULL; - } - - if (hwdev->page_pa1.virt_addr) { - dma_free_coherent(hwdev->dev_hdl, SPHW_HT_GPA_PAGE_SIZE, - hwdev->page_pa1.virt_addr, - hwdev->page_pa1.phys_addr); - hwdev->page_pa1.virt_addr = NULL; - } -} - -static int set_ppf_tmr_status(struct sphw_hwdev *hwdev, - enum ppf_tmr_status status) -{ - struct comm_cmd_ppf_tmr_op op; - u16 out_size = sizeof(op); - int err = 0; - - if (!hwdev) - return -EINVAL; - - memset(&op, 0, sizeof(op)); - - if (sphw_func_type(hwdev) != TYPE_PPF) - return -EFAULT; - - if (status == SPHW_PPF_TMR_FLAG_START) { - err = sphw_ppf_ht_gpa_init(hwdev); - if (err) { - sdk_err(hwdev->dev_hdl, "PPF ht gpa init fail!\n"); - return -EFAULT; - } - } else { - sphw_ppf_ht_gpa_deinit(hwdev); - } - - op.opcode = status; - op.ppf_id = sphw_ppf_idx(hwdev); - - err = comm_msg_to_mgmt_sync(hwdev, COMM_MGMT_CMD_SET_PPF_TMR, &op, - sizeof(op), &op, &out_size); - if (err || !out_size || op.head.status) { - sdk_err(hwdev->dev_hdl, "Failed to set ppf timer, err: %d, status: 0x%x, out_size: 0x%x\n", - err, op.head.status, out_size); - return -EFAULT; - } - - return 0; -} - -int sphw_ppf_tmr_start(void *hwdev) -{ - if (!hwdev) { - pr_err("Hwdev pointer is NULL for starting ppf timer\n"); - return -EINVAL; - } - - return set_ppf_tmr_status(hwdev, SPHW_PPF_TMR_FLAG_START); -} - -int sphw_ppf_tmr_stop(void *hwdev) -{ - if (!hwdev) { - pr_err("Hwdev pointer is NULL for stop ppf timer\n"); - return -EINVAL; - } - - return set_ppf_tmr_status(hwdev, SPHW_PPF_TMR_FLAG_STOP); -} - -int mqm_eqm_try_alloc_mem(struct sphw_hwdev *hwdev, u32 page_size, - u32 page_num) -{ - struct sphw_page_addr *page_addr = hwdev->mqm_att.brm_srch_page_addr; - u32 valid_num = 0; - u32 flag = 1; - u32 i = 0; - - for (i = 0; i < page_num; i++) { - page_addr->virt_addr = - dma_alloc_coherent(hwdev->dev_hdl, page_size, - &page_addr->phys_addr, GFP_KERNEL); - if (!page_addr->virt_addr) { - flag = 0; - break; - } - valid_num++; - page_addr++; - } - - if (flag == 1) { - hwdev->mqm_att.page_size = page_size; - hwdev->mqm_att.page_num = page_num; - } else { - page_addr = hwdev->mqm_att.brm_srch_page_addr; - for (i = 0; i < valid_num; i++) { - dma_free_coherent(hwdev->dev_hdl, page_size, - page_addr->virt_addr, - page_addr->phys_addr); - page_addr++; - } - return -EFAULT; - } - - return 0; -} - -int mqm_eqm_alloc_page_mem(struct sphw_hwdev *hwdev) -{ - int ret = 0; - int page_num; - - /* apply for 2M page, page number is chunk_num/1024 */ - page_num = (hwdev->mqm_att.chunk_num + 1023) >> 10; - ret = mqm_eqm_try_alloc_mem(hwdev, 2 * 1024 * 1024, page_num); - if (!ret) { - sdk_info(hwdev->dev_hdl, "[mqm_eqm_init] Alloc page_size 2M OK\n"); - return 0; - } - - /* apply for 64KB page, page number is chunk_num/32 */ - page_num = (hwdev->mqm_att.chunk_num + 31) >> 5; - ret = mqm_eqm_try_alloc_mem(hwdev, 64 * 1024, page_num); - if (!ret) { - sdk_info(hwdev->dev_hdl, "[mqm_eqm_init] Alloc page_size 64K OK\n"); - return 0; - } - - /* apply for 4KB page, page number is chunk_num/2 */ - page_num = (hwdev->mqm_att.chunk_num + 1) >> 1; - ret = mqm_eqm_try_alloc_mem(hwdev, 4 * 1024, page_num); - if (!ret) { - sdk_info(hwdev->dev_hdl, "[mqm_eqm_init] Alloc page_size 4K OK\n"); - return 0; - } - - return ret; -} - -void mqm_eqm_free_page_mem(struct sphw_hwdev *hwdev) -{ - u32 i; - struct sphw_page_addr *page_addr; - u32 page_size; - - page_size = hwdev->mqm_att.page_size; - page_addr = hwdev->mqm_att.brm_srch_page_addr; - - for (i = 0; i < hwdev->mqm_att.page_num; i++) { - dma_free_coherent(hwdev->dev_hdl, page_size, - page_addr->virt_addr, page_addr->phys_addr); - page_addr++; - } -} - -int mqm_eqm_set_cfg_2_hw(struct sphw_hwdev *hwdev, u8 valid) -{ - struct comm_cmd_eqm_cfg info_eqm_cfg; - u16 out_size = sizeof(info_eqm_cfg); - int err; - - memset(&info_eqm_cfg, 0, sizeof(info_eqm_cfg)); - - info_eqm_cfg.host_id = sphw_host_id(hwdev); - info_eqm_cfg.page_size = hwdev->mqm_att.page_size; - info_eqm_cfg.valid = valid; - err = comm_msg_to_mgmt_sync(hwdev, COMM_MGMT_CMD_SET_MQM_CFG_INFO, - &info_eqm_cfg, sizeof(info_eqm_cfg), - &info_eqm_cfg, &out_size); - if (err || !out_size || info_eqm_cfg.head.status) { - sdk_err(hwdev->dev_hdl, "Failed to init func table, err: %d, status: 0x%x, out_size: 0x%x\n", - err, info_eqm_cfg.head.status, out_size); - return -EFAULT; - } - - return 0; -} - -#define EQM_DATA_BUF_SIZE 1024 -#define MQM_ATT_PAGE_NUM 128 - -int mqm_eqm_set_page_2_hw(struct sphw_hwdev *hwdev) -{ - struct comm_cmd_eqm_search_gpa *info = NULL; - struct sphw_page_addr *page_addr = NULL; - void *send_buf = NULL; - u16 send_buf_size; - u32 i; - u64 *gpa_hi52 = NULL; - u64 gpa; - u32 num; - u32 start_idx; - int err = 0; - u16 out_size; - u8 cmd; - - send_buf_size = sizeof(struct comm_cmd_eqm_search_gpa) + - EQM_DATA_BUF_SIZE; - send_buf = kzalloc(send_buf_size, GFP_KERNEL); - if (!send_buf) { - sdk_err(hwdev->dev_hdl, "Alloc virtual mem failed\r\n"); - return -EFAULT; - } - - page_addr = hwdev->mqm_att.brm_srch_page_addr; - info = (struct comm_cmd_eqm_search_gpa *)send_buf; - - gpa_hi52 = info->gpa_hi52; - num = 0; - start_idx = 0; - cmd = COMM_MGMT_CMD_SET_MQM_SRCH_GPA; - for (i = 0; i < hwdev->mqm_att.page_num; i++) { - /* gpa align to 4K, save gpa[31:12] */ - gpa = page_addr->phys_addr >> 12; - gpa_hi52[num] = gpa; - num++; - if (num == MQM_ATT_PAGE_NUM) { - info->num = num; - info->start_idx = start_idx; - info->host_id = sphw_host_id(hwdev); - out_size = send_buf_size; - err = comm_msg_to_mgmt_sync(hwdev, cmd, info, - (u16)send_buf_size, - info, &out_size); - if (MSG_TO_MGMT_SYNC_RETURN_ERR(err, out_size, - info->head.status)) { - sdk_err(hwdev->dev_hdl, "Set mqm srch gpa fail, err: %d, status: 0x%x, out_size: 0x%x\n", - err, info->head.status, out_size); - err = -EFAULT; - goto set_page_2_hw_end; - } - - gpa_hi52 = info->gpa_hi52; - num = 0; - start_idx = i + 1; - } - page_addr++; - } - - if (num != 0) { - info->num = num; - info->start_idx = start_idx; - info->host_id = sphw_host_id(hwdev); - out_size = send_buf_size; - err = comm_msg_to_mgmt_sync(hwdev, cmd, info, - (u16)send_buf_size, info, - &out_size); - if (MSG_TO_MGMT_SYNC_RETURN_ERR(err, out_size, - info->head.status)) { - sdk_err(hwdev->dev_hdl, "Set mqm srch gpa fail, err: %d, status: 0x%x, out_size: 0x%x\n", - err, info->head.status, out_size); - err = -EFAULT; - goto set_page_2_hw_end; - } - } - -set_page_2_hw_end: - kfree(send_buf); - return err; -} - -int mqm_eqm_init(struct sphw_hwdev *hwdev) -{ - struct comm_cmd_get_eqm_num info_eqm_fix; - u16 len = sizeof(info_eqm_fix); - int ret; - - if (hwdev->hwif->attr.func_type != TYPE_PPF) - return 0; - - memset(&info_eqm_fix, 0, sizeof(info_eqm_fix)); - - ret = comm_msg_to_mgmt_sync(hwdev, COMM_MGMT_CMD_GET_MQM_FIX_INFO, - &info_eqm_fix, sizeof(info_eqm_fix), - &info_eqm_fix, &len); - if (ret || !len || info_eqm_fix.head.status) { - sdk_err(hwdev->dev_hdl, "Get mqm fix info fail,err: %d, status: 0x%x, out_size: 0x%x\n", - ret, info_eqm_fix.head.status, len); - return -EFAULT; - } - sdk_info(hwdev->dev_hdl, "get chunk_num: 0x%x, search_gpa_num: 0x%08x\n", - info_eqm_fix.chunk_num, info_eqm_fix.search_gpa_num); - if (!(info_eqm_fix.chunk_num)) - return 0; - - hwdev->mqm_att.chunk_num = info_eqm_fix.chunk_num; - hwdev->mqm_att.search_gpa_num = info_eqm_fix.search_gpa_num; - hwdev->mqm_att.page_size = 0; - hwdev->mqm_att.page_num = 0; - - hwdev->mqm_att.brm_srch_page_addr = - kcalloc(hwdev->mqm_att.chunk_num, - sizeof(struct sphw_page_addr), GFP_KERNEL); - if (!(hwdev->mqm_att.brm_srch_page_addr)) { - sdk_err(hwdev->dev_hdl, "Alloc virtual mem failed\r\n"); - return -EFAULT; - } - - ret = mqm_eqm_alloc_page_mem(hwdev); - if (ret) { - sdk_err(hwdev->dev_hdl, "Alloc eqm page mem failed\r\n"); - goto err_page; - } - - ret = mqm_eqm_set_page_2_hw(hwdev); - if (ret) { - sdk_err(hwdev->dev_hdl, "Set page to hw failed\r\n"); - goto err_ecmd; - } - - ret = mqm_eqm_set_cfg_2_hw(hwdev, 1); - if (ret) { - sdk_err(hwdev->dev_hdl, "Set page to hw failed\r\n"); - goto err_ecmd; - } - - return 0; - -err_ecmd: - mqm_eqm_free_page_mem(hwdev); - -err_page: - kfree(hwdev->mqm_att.brm_srch_page_addr); - - return ret; -} - -void mqm_eqm_deinit(struct sphw_hwdev *hwdev) -{ - int ret; - - if (hwdev->hwif->attr.func_type != TYPE_PPF) - return; - - if (!(hwdev->mqm_att.chunk_num)) - return; - - mqm_eqm_free_page_mem(hwdev); - kfree(hwdev->mqm_att.brm_srch_page_addr); - - ret = mqm_eqm_set_cfg_2_hw(hwdev, 0); - if (ret) { - sdk_err(hwdev->dev_hdl, "Set mqm eqm cfg to chip fail! err: %d\n", - ret); - return; - } - - hwdev->mqm_att.chunk_num = 0; - hwdev->mqm_att.search_gpa_num = 0; - hwdev->mqm_att.page_num = 0; - hwdev->mqm_att.page_size = 0; -} - -int sphw_ppf_ext_db_init(void *dev) -{ - struct sphw_hwdev *hwdev = dev; - int ret; - - /* IS OVS MODE SURPORT EXT DB NEEDED */ - - ret = mqm_eqm_init(hwdev); - if (ret) { - sdk_err(hwdev->dev_hdl, "MQM eqm init fail!\n"); - return -EFAULT; - } - sdk_info(hwdev->dev_hdl, "ppf_ext_db_init ok\r\n"); - - return 0; -} - -int sphw_ppf_ext_db_deinit(void *dev) -{ - struct sphw_hwdev *hwdev = dev; - - if (!dev) - return -EINVAL; - - if (hwdev->hwif->attr.func_type != TYPE_PPF) - return 0; - - mqm_eqm_deinit(hwdev); - - return 0; -} - -#define SPHW_FLR_TIMEOUT 1000 - -static enum sphw_wait_return check_flr_finish_handler(void *priv_data) -{ - struct sphw_hwif *hwif = priv_data; - enum sphw_pf_status status; - - status = sphw_get_pf_status(hwif); - if (status == SPHW_PF_STATUS_FLR_FINISH_FLAG) { - sphw_set_pf_status(hwif, SPHW_PF_STATUS_ACTIVE_FLAG); - return WAIT_PROCESS_CPL; - } - - return WAIT_PROCESS_WAITING; -} - -static int wait_for_flr_finish(struct sphw_hwif *hwif) -{ - return sphw_wait_for_timeout(hwif, check_flr_finish_handler, - SPHW_FLR_TIMEOUT, 10 * USEC_PER_MSEC); -} - -#define SPHW_WAIT_CMDQ_IDLE_TIMEOUT 5000 - -static enum sphw_wait_return check_cmdq_stop_handler(void *priv_data) -{ - struct sphw_hwdev *hwdev = priv_data; - struct sphw_cmdqs *cmdqs = hwdev->cmdqs; - enum sphw_cmdq_type cmdq_type; - - /* Stop waiting when card unpresent */ - if (!hwdev->chip_present_flag) - return WAIT_PROCESS_CPL; - - cmdq_type = SPHW_CMDQ_SYNC; - for (; cmdq_type < SPHW_MAX_CMDQ_TYPES; cmdq_type++) { - if (!sphw_cmdq_idle(&cmdqs->cmdq[cmdq_type])) - return WAIT_PROCESS_WAITING; - } - - return WAIT_PROCESS_CPL; -} - -static int wait_cmdq_stop(struct sphw_hwdev *hwdev) -{ - enum sphw_cmdq_type cmdq_type; - struct sphw_cmdqs *cmdqs = hwdev->cmdqs; - int err; - - if (!(cmdqs->status & SPHW_CMDQ_ENABLE)) - return 0; - - cmdqs->status &= ~SPHW_CMDQ_ENABLE; - - err = sphw_wait_for_timeout(hwdev, check_cmdq_stop_handler, - SPHW_WAIT_CMDQ_IDLE_TIMEOUT, USEC_PER_MSEC); - if (!err) - return 0; - - cmdq_type = SPHW_CMDQ_SYNC; - for (; cmdq_type < SPHW_MAX_CMDQ_TYPES; cmdq_type++) { - if (!sphw_cmdq_idle(&cmdqs->cmdq[cmdq_type])) - sdk_err(hwdev->dev_hdl, "Cmdq %d is busy\n", cmdq_type); - } - - cmdqs->status |= SPHW_CMDQ_ENABLE; - - return err; -} - -static int sphw_pf_rx_tx_flush(struct sphw_hwdev *hwdev, u16 channel) -{ - struct sphw_hwif *hwif = hwdev->hwif; - struct comm_cmd_clear_doorbell clear_db; - struct comm_cmd_clear_resource clr_res; - u16 out_size; - int err; - int ret = 0; - - /*wait ucode stop I/O */ - msleep(100); - - err = wait_cmdq_stop(hwdev); - if (err) { - sdk_warn(hwdev->dev_hdl, "CMDQ is still working, please check CMDQ timeout value is reasonable\n"); - ret = err; - } - - sphw_disable_doorbell(hwif); - - out_size = sizeof(clear_db); - memset(&clear_db, 0, sizeof(clear_db)); - clear_db.func_id = SPHW_HWIF_GLOBAL_IDX(hwif); - - err = comm_msg_to_mgmt_sync_ch(hwdev, COMM_MGMT_CMD_FLUSH_DOORBELL, - &clear_db, sizeof(clear_db), - &clear_db, &out_size, channel); - if (err || !out_size || clear_db.head.status) { - sdk_warn(hwdev->dev_hdl, "Failed to flush doorbell, err: %d, status: 0x%x, out_size: 0x%x, channel: 0x%x\n", - err, clear_db.head.status, out_size, channel); - if (err) - ret = err; - else - ret = -EFAULT; - } - - sphw_set_pf_status(hwif, SPHW_PF_STATUS_FLR_START_FLAG); - - memset(&clr_res, 0, sizeof(clr_res)); - clr_res.func_id = SPHW_HWIF_GLOBAL_IDX(hwif); - - err = sphw_msg_to_mgmt_no_ack(hwdev, SPHW_MOD_COMM, COMM_MGMT_CMD_START_FLUSH, &clr_res, - sizeof(clr_res), channel); - if (err) { - sdk_warn(hwdev->dev_hdl, "Failed to notice flush message, err: %d, channel: 0x%x\n", - err, channel); - ret = err; - } - - err = wait_for_flr_finish(hwif); - if (err) { - sdk_warn(hwdev->dev_hdl, "Wait firmware FLR timeout\n"); - ret = err; - } - - sphw_enable_doorbell(hwif); - - err = sphw_reinit_cmdq_ctxts(hwdev); - if (err) { - sdk_warn(hwdev->dev_hdl, "Failed to reinit cmdq\n"); - ret = err; - } - - return ret; -} - -int sphw_func_rx_tx_flush(void *hwdev, u16 channel) -{ - struct sphw_hwdev *dev = hwdev; - - if (!hwdev) - return -EINVAL; - - if (!dev->chip_present_flag) - return 0; - - if (SPHW_FUNC_TYPE(dev) == TYPE_VF) - /* TO DO */ - return 0; - else - return sphw_pf_rx_tx_flush(dev, channel); -} - -int sphw_get_board_info(void *hwdev, struct sphw_board_info *info, u16 channel) -{ - struct comm_cmd_board_info board_info; - u16 out_size = sizeof(board_info); - int err; - - if (!hwdev || !info) - return -EINVAL; - - memset(&board_info, 0, sizeof(board_info)); - err = comm_msg_to_mgmt_sync_ch(hwdev, COMM_MGMT_CMD_GET_BOARD_INFO, - &board_info, sizeof(board_info), - &board_info, &out_size, channel); - if (err || board_info.head.status || !out_size) { - sdk_err(((struct sphw_hwdev *)hwdev)->dev_hdl, - "Failed to get board info, err: %d, status: 0x%x, out size: 0x%x, channel: 0x%x\n", - err, board_info.head.status, out_size, channel); - return -EIO; - } - - memcpy(info, &board_info.info, sizeof(*info)); - - return 0; -} - -int sphw_get_global_attr(void *hwdev, struct comm_global_attr *attr) -{ - struct comm_cmd_get_glb_attr get_attr; - u16 out_size = sizeof(get_attr); - int err = 0; - - err = comm_msg_to_mgmt_sync(hwdev, COMM_MGMT_CMD_GET_GLOBAL_ATTR, - &get_attr, sizeof(get_attr), &get_attr, - &out_size); - if (err || !out_size || get_attr.head.status) { - sdk_err(((struct sphw_hwdev *)hwdev)->dev_hdl, - "Failed to get global attribute, err: %d, status: 0x%x, out size: 0x%x\n", - err, get_attr.head.status, out_size); - return -EIO; - } - - memcpy(attr, &get_attr.attr, sizeof(*attr)); - - return 0; -} diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw_comm.h b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw_comm.h deleted file mode 100644 index 4e0cf2dfb21e..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw_comm.h +++ /dev/null @@ -1,45 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPHW_HW_COMM_H -#define SPHW_HW_COMM_H - -#include "sphw_comm_msg_intf.h" - -#define MSG_TO_MGMT_SYNC_RETURN_ERR(err, out_size, status) \ - ((err) || (status) || !(out_size)) - -#define SPHW_PAGE_SIZE_HW(pg_size) ((u8)ilog2((u32)((pg_size) >> 12))) - -enum func_tmr_bitmap_status { - FUNC_TMR_BITMAP_DISABLE, - FUNC_TMR_BITMAP_ENABLE, -}; - -enum ppf_tmr_status { - SPHW_PPF_TMR_FLAG_STOP, - SPHW_PPF_TMR_FLAG_START, -}; - -#define SPHW_HT_GPA_PAGE_SIZE 4096UL -#define SPHW_PPF_HT_GPA_SET_RETRY_TIMES 10 - -int sphw_set_cmdq_depth(void *hwdev, u16 cmdq_depth); - -int sphw_set_cmdq_ctxt(struct sphw_hwdev *hwdev, u8 cmdq_id, struct cmdq_ctxt_info *ctxt); - -int sphw_ppf_ext_db_init(void *dev); - -int sphw_ppf_ext_db_deinit(void *dev); - -int sphw_set_ceq_ctrl_reg(struct sphw_hwdev *hwdev, u16 q_id, u32 ctrl0, u32 ctrl1); - -int sphw_set_dma_attr_tbl(struct sphw_hwdev *hwdevm, u8 entry_idx, u8 st, u8 at, u8 ph, - u8 no_snooping, u8 tph_en); - -int sphw_get_comm_features(void *hwdev, u64 *s_feature, u16 size); -int sphw_set_comm_features(void *hwdev, u64 *s_feature, u16 size); - -int sphw_get_global_attr(void *hwdev, struct comm_global_attr *attr); - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hwdev.c b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hwdev.c deleted file mode 100644 index 783fa46bcfe5..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hwdev.c +++ /dev/null @@ -1,1324 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [COMM]" fmt - -#include <linux/time.h> -#include <linux/timex.h> -#include <linux/rtc.h> -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/types.h> -#include <linux/module.h> -#include <linux/completion.h> -#include <linux/semaphore.h> -#include <linux/interrupt.h> -#include <linux/vmalloc.h> - -#include "sphw_crm.h" -#include "sphw_hw.h" -#include "sphw_common.h" -#include "sphw_hwdev.h" -#include "sphw_csr.h" -#include "sphw_hwif.h" -#include "sphw_eqs.h" -#include "sphw_api_cmd.h" -#include "sphw_mgmt.h" -#include "sphw_mbox.h" -#include "sphw_wq.h" -#include "sphw_cmdq.h" -#include "sphw_hw_cfg.h" -#include "sphw_hw_comm.h" -#include "sphw_prof_adap.h" - -static bool disable_stateful_load; -module_param(disable_stateful_load, bool, 0444); -MODULE_PARM_DESC(disable_stateful_load, "Disable stateful load - default is false"); - -static bool disable_cfg_comm; -module_param(disable_cfg_comm, bool, 0444); -MODULE_PARM_DESC(disable_cfg_comm, "disable_cfg_comm or not - default is false"); - -static unsigned int wq_page_order = SPHW_MAX_WQ_PAGE_SIZE_ORDER; -module_param(wq_page_order, uint, 0444); -MODULE_PARM_DESC(wq_page_order, "Set wq page size order, wq page size is 4K * (2 ^ wq_page_order) - default is 8"); - -enum sphw_pcie_nosnoop { - SPHW_PCIE_SNOOP = 0, - SPHW_PCIE_NO_SNOOP = 1, -}; - -enum sphw_pcie_tph { - SPHW_PCIE_TPH_DISABLE = 0, - SPHW_PCIE_TPH_ENABLE = 1, -}; - -#define SPHW_DMA_ATTR_INDIR_IDX_SHIFT 0 - -#define SPHW_DMA_ATTR_INDIR_IDX_MASK 0x3FF - -#define SPHW_DMA_ATTR_INDIR_IDX_SET(val, member) \ - (((u32)(val) & SPHW_DMA_ATTR_INDIR_##member##_MASK) << \ - SPHW_DMA_ATTR_INDIR_##member##_SHIFT) - -#define SPHW_DMA_ATTR_INDIR_IDX_CLEAR(val, member) \ - ((val) & (~(SPHW_DMA_ATTR_INDIR_##member##_MASK \ - << SPHW_DMA_ATTR_INDIR_##member##_SHIFT))) - -#define SPHW_DMA_ATTR_ENTRY_ST_SHIFT 0 -#define SPHW_DMA_ATTR_ENTRY_AT_SHIFT 8 -#define SPHW_DMA_ATTR_ENTRY_PH_SHIFT 10 -#define SPHW_DMA_ATTR_ENTRY_NO_SNOOPING_SHIFT 12 -#define SPHW_DMA_ATTR_ENTRY_TPH_EN_SHIFT 13 - -#define SPHW_DMA_ATTR_ENTRY_ST_MASK 0xFF -#define SPHW_DMA_ATTR_ENTRY_AT_MASK 0x3 -#define SPHW_DMA_ATTR_ENTRY_PH_MASK 0x3 -#define SPHW_DMA_ATTR_ENTRY_NO_SNOOPING_MASK 0x1 -#define SPHW_DMA_ATTR_ENTRY_TPH_EN_MASK 0x1 - -#define SPHW_DMA_ATTR_ENTRY_SET(val, member) \ - (((u32)(val) & SPHW_DMA_ATTR_ENTRY_##member##_MASK) << \ - SPHW_DMA_ATTR_ENTRY_##member##_SHIFT) - -#define SPHW_DMA_ATTR_ENTRY_CLEAR(val, member) \ - ((val) & (~(SPHW_DMA_ATTR_ENTRY_##member##_MASK \ - << SPHW_DMA_ATTR_ENTRY_##member##_SHIFT))) - -#define SPHW_PCIE_ST_DISABLE 0 -#define SPHW_PCIE_AT_DISABLE 0 -#define SPHW_PCIE_PH_DISABLE 0 - -#define PCIE_MSIX_ATTR_ENTRY 0 - -#define SPHW_CHIP_PRESENT 1 -#define SPHW_CHIP_ABSENT 0 - -#define SPHW_DEAULT_EQ_MSIX_PENDING_LIMIT 0 -#define SPHW_DEAULT_EQ_MSIX_COALESC_TIMER_CFG 0xFF -#define SPHW_DEAULT_EQ_MSIX_RESEND_TIMER_CFG 7 - -#define SPHW_HWDEV_WQ_NAME "sphw_hardware" -#define SPHW_WQ_MAX_REQ 10 - -static void sphw_init_heartbeat_detect(struct sphw_hwdev *hwdev); -static void sphw_destroy_heartbeat_detect(struct sphw_hwdev *hwdev); - -typedef void (*mgmt_event_cb)(void *handle, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size); - -struct mgmt_event_handle { - u16 cmd; - mgmt_event_cb proc; -}; - -int pf_handle_vf_comm_mbox(void *handle, void *pri_handle, - u16 vf_id, u16 cmd, void *buf_in, - u16 in_size, void *buf_out, u16 *out_size) -{ - struct sphw_hwdev *hwdev = handle; - - if (!hwdev) - return -EINVAL; - - sdk_warn(hwdev->dev_hdl, "Unsupported vf mbox event %u to process\n", - cmd); - - return 0; -} - -int vf_handle_pf_comm_mbox(void *handle, void *pri_handle, u16 cmd, void *buf_in, - u16 in_size, void *buf_out, u16 *out_size) -{ - struct sphw_hwdev *hwdev = handle; - - if (!hwdev) - return -EINVAL; - - sdk_warn(hwdev->dev_hdl, "Unsupported pf mbox event %u to process\n", - cmd); - return 0; -} - -static void chip_fault_show(struct sphw_hwdev *hwdev, struct sphw_fault_event *event) -{ - char fault_level[FAULT_LEVEL_MAX][FAULT_SHOW_STR_LEN + 1] = { - "fatal", "reset", "host", "flr", "general", "suggestion"}; - char level_str[FAULT_SHOW_STR_LEN + 1]; - u8 level; - - memset(level_str, 0, FAULT_SHOW_STR_LEN + 1); - level = event->event.chip.err_level; - if (level < FAULT_LEVEL_MAX) - strncpy(level_str, fault_level[level], - FAULT_SHOW_STR_LEN); - else - strncpy(level_str, "Unknown", FAULT_SHOW_STR_LEN); - - if (level == FAULT_LEVEL_SERIOUS_FLR) - dev_err(hwdev->dev_hdl, "err_level: %u [%s], flr func_id: %u\n", - level, level_str, event->event.chip.func_id); - - dev_err(hwdev->dev_hdl, "Module_id: 0x%x, err_type: 0x%x, err_level: %u[%s], err_csr_addr: 0x%08x, err_csr_value: 0x%08x\n", - event->event.chip.node_id, - event->event.chip.err_type, level, level_str, - event->event.chip.err_csr_addr, - event->event.chip.err_csr_value); -} - -static void fault_report_show(struct sphw_hwdev *hwdev, - struct sphw_fault_event *event) -{ - char fault_type[FAULT_TYPE_MAX][FAULT_SHOW_STR_LEN + 1] = { - "chip", "ucode", "mem rd timeout", "mem wr timeout", - "reg rd timeout", "reg wr timeout", "phy fault" - }; - char type_str[FAULT_SHOW_STR_LEN + 1]; - struct fault_event_stats *fault = NULL; - - sdk_err(hwdev->dev_hdl, "Fault event report received, func_id: %u\n", - sphw_global_func_id(hwdev)); - - memset(type_str, 0, FAULT_SHOW_STR_LEN + 1); - if (event->type < FAULT_TYPE_MAX) - strncpy(type_str, fault_type[event->type], - strlen(fault_type[event->type])); - else - strncpy(type_str, "Unknown", strlen("Unknown")); - - sdk_err(hwdev->dev_hdl, "Fault type: %u [%s]\n", event->type, type_str); - /* 0, 1, 2 and 3 word Represents array event->event.val index */ - sdk_err(hwdev->dev_hdl, "Fault val[0]: 0x%08x, val[1]: 0x%08x, val[2]: 0x%08x, val[3]: 0x%08x\n", - event->event.val[0], event->event.val[1], event->event.val[2], - event->event.val[3]); - - fault = &hwdev->hw_stats.fault_event_stats; - - switch (event->type) { - case FAULT_TYPE_CHIP: - chip_fault_show(hwdev, event); - break; - case FAULT_TYPE_UCODE: - atomic_inc(&fault->fault_type_stat[event->type]); - sdk_err(hwdev->dev_hdl, "Cause_id: %u, core_id: %u, c_id: %u, epc: 0x%08x\n", - event->event.ucode.cause_id, event->event.ucode.core_id, - event->event.ucode.c_id, event->event.ucode.epc); - break; - case FAULT_TYPE_MEM_RD_TIMEOUT: - case FAULT_TYPE_MEM_WR_TIMEOUT: - atomic_inc(&fault->fault_type_stat[event->type]); - sdk_err(hwdev->dev_hdl, "Err_csr_ctrl: 0x%08x, err_csr_data: 0x%08x, ctrl_tab: 0x%08x, mem_index: 0x%08x\n", - event->event.mem_timeout.err_csr_ctrl, - event->event.mem_timeout.err_csr_data, - event->event.mem_timeout.ctrl_tab, - event->event.mem_timeout.mem_index); - break; - case FAULT_TYPE_REG_RD_TIMEOUT: - case FAULT_TYPE_REG_WR_TIMEOUT: - atomic_inc(&fault->fault_type_stat[event->type]); - sdk_err(hwdev->dev_hdl, "Err_csr: 0x%08x\n", - event->event.reg_timeout.err_csr); - break; - case FAULT_TYPE_PHY_FAULT: - atomic_inc(&fault->fault_type_stat[event->type]); - sdk_err(hwdev->dev_hdl, "Op_type: %u, port_id: %u, dev_ad: %u, csr_addr: 0x%08x, op_data: 0x%08x\n", - event->event.phy_fault.op_type, - event->event.phy_fault.port_id, - event->event.phy_fault.dev_ad, - event->event.phy_fault.csr_addr, - event->event.phy_fault.op_data); - break; - default: - break; - } -} - -static void fault_event_handler(void *dev, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size) -{ - struct sphw_cmd_fault_event *fault_event = NULL; - struct sphw_event_info event_info; - struct sphw_hwdev *hwdev = dev; - u8 fault_src = SPHW_FAULT_SRC_TYPE_MAX; - u8 fault_level; - - if (in_size != sizeof(*fault_event)) { - sdk_err(hwdev->dev_hdl, "Invalid fault event report, length: %u, should be %ld\n", - in_size, sizeof(*fault_event)); - return; - } - - fault_event = buf_in; - fault_report_show(hwdev, &fault_event->event); - - if (fault_event->event.type == FAULT_TYPE_CHIP) - fault_level = fault_event->event.event.chip.err_level; - else - fault_level = FAULT_LEVEL_FATAL; - - if (hwdev->event_callback) { - event_info.type = SPHW_EVENT_FAULT; - memcpy(&event_info.info, &fault_event->event, - sizeof(struct sphw_fault_event)); - event_info.info.fault_level = fault_level; - hwdev->event_callback(hwdev->event_pri_handle, &event_info); - } - - if (fault_event->event.type <= FAULT_TYPE_REG_WR_TIMEOUT) - fault_src = fault_event->event.type; - else if (fault_event->event.type == FAULT_TYPE_PHY_FAULT) - fault_src = SPHW_FAULT_SRC_HW_PHY_FAULT; - - sphw_fault_post_process(hwdev, fault_src, fault_level); -} - -static void ffm_event_msg_handler(void *hwdev, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size) -{ - struct ffm_intr_info *intr = NULL; - struct sphw_hwdev *dev = hwdev; - - if (in_size != sizeof(*intr)) { - sdk_err(dev->dev_hdl, "Invalid fault event report, length: %u, should be %ld.\n", - in_size, sizeof(*intr)); - return; - } - - intr = buf_in; - - sdk_err(dev->dev_hdl, "node_id: 0x%x, err_type: 0x%x, err_level: %u, err_csr_addr: 0x%08x, err_csr_value: 0x%08x\n", - intr->node_id, intr->err_type, intr->err_level, - intr->err_csr_addr, intr->err_csr_value); -} - -const struct mgmt_event_handle mgmt_event_proc[] = { - { - .cmd = COMM_MGMT_CMD_FAULT_REPORT, - .proc = fault_event_handler, - }, - - { - .cmd = COMM_MGMT_CMD_FFM_SET, - .proc = ffm_event_msg_handler, - }, -}; - -void pf_handle_mgmt_comm_event(void *handle, void *pri_handle, u16 cmd, - void *buf_in, u16 in_size, void *buf_out, - u16 *out_size) -{ - struct sphw_hwdev *hwdev = handle; - u32 i, event_num = ARRAY_LEN(mgmt_event_proc); - - if (!hwdev) - return; - - for (i = 0; i < event_num; i++) { - if (cmd == mgmt_event_proc[i].cmd) { - if (mgmt_event_proc[i].proc) - mgmt_event_proc[i].proc(handle, buf_in, in_size, - buf_out, out_size); - - return; - } - } - - sdk_warn(hwdev->dev_hdl, "Unsupported mgmt cpu event %u to process\n", - cmd); -} - -void sphw_set_chip_present(void *hwdev) -{ - ((struct sphw_hwdev *)hwdev)->chip_present_flag = SPHW_CHIP_PRESENT; -} - -void sphw_set_chip_absent(void *hwdev) -{ - struct sphw_hwdev *dev = hwdev; - - sdk_err(dev->dev_hdl, "Card not present\n"); - dev->chip_present_flag = SPHW_CHIP_ABSENT; -} - -int sphw_get_chip_present_flag(const void *hwdev) -{ - if (!hwdev) - return 0; - - return ((struct sphw_hwdev *)hwdev)->chip_present_flag; -} - -/* TODO */ -void sphw_force_complete_all(void *hwdev) -{ -} - -void sphw_detect_hw_present(void *hwdev) -{ - u32 addr, attr1; - - addr = SPHW_CSR_FUNC_ATTR1_ADDR; - attr1 = sphw_hwif_read_reg(((struct sphw_hwdev *)hwdev)->hwif, addr); - if (attr1 == SPHW_PCIE_LINK_DOWN) { - sphw_set_chip_absent(hwdev); - sphw_force_complete_all(hwdev); - } -} - -/** - * dma_attr_table_init - initialize the default dma attributes - * @hwdev: the pointer to hw device - **/ -static int dma_attr_table_init(struct sphw_hwdev *hwdev) -{ - u32 addr, val, dst_attr; - - /* Use indirect access should set entry_idx first*/ - addr = SPHW_CSR_DMA_ATTR_INDIR_IDX_ADDR; - val = sphw_hwif_read_reg(hwdev->hwif, addr); - val = SPHW_DMA_ATTR_INDIR_IDX_CLEAR(val, IDX); - - val |= SPHW_DMA_ATTR_INDIR_IDX_SET(PCIE_MSIX_ATTR_ENTRY, IDX); - - sphw_hwif_write_reg(hwdev->hwif, addr, val); - - wmb(); /* write index before config */ - - addr = SPHW_CSR_DMA_ATTR_TBL_ADDR; - val = sphw_hwif_read_reg(hwdev->hwif, addr); - dst_attr = SPHW_DMA_ATTR_ENTRY_SET(SPHW_PCIE_ST_DISABLE, ST) | - SPHW_DMA_ATTR_ENTRY_SET(SPHW_PCIE_AT_DISABLE, AT) | - SPHW_DMA_ATTR_ENTRY_SET(SPHW_PCIE_PH_DISABLE, PH) | - SPHW_DMA_ATTR_ENTRY_SET(SPHW_PCIE_SNOOP, NO_SNOOPING) | - SPHW_DMA_ATTR_ENTRY_SET(SPHW_PCIE_TPH_DISABLE, TPH_EN); - if (dst_attr == val) - return 0; - - return sphw_set_dma_attr_tbl(hwdev, PCIE_MSIX_ATTR_ENTRY, SPHW_PCIE_ST_DISABLE, - SPHW_PCIE_AT_DISABLE, SPHW_PCIE_PH_DISABLE, - SPHW_PCIE_SNOOP, SPHW_PCIE_TPH_DISABLE); -} - -static int init_aeqs_msix_attr(struct sphw_hwdev *hwdev) -{ - struct sphw_aeqs *aeqs = hwdev->aeqs; - struct interrupt_info info = {0}; - struct sphw_eq *eq = NULL; - int q_id; - int err; - - info.lli_set = 0; - info.interrupt_coalesc_set = 1; - info.pending_limt = SPHW_DEAULT_EQ_MSIX_PENDING_LIMIT; - info.coalesc_timer_cfg = SPHW_DEAULT_EQ_MSIX_COALESC_TIMER_CFG; - info.resend_timer_cfg = SPHW_DEAULT_EQ_MSIX_RESEND_TIMER_CFG; - - for (q_id = aeqs->num_aeqs - 1; q_id >= 0; q_id--) { - eq = &aeqs->aeq[q_id]; - info.msix_index = eq->eq_irq.msix_entry_idx; - err = sphw_set_interrupt_cfg_direct(hwdev, &info, SPHW_CHANNEL_COMM); - if (err) { - sdk_err(hwdev->dev_hdl, "Set msix attr for aeq %d failed\n", - q_id); - return -EFAULT; - } - } - - return 0; -} - -static int init_ceqs_msix_attr(struct sphw_hwdev *hwdev) -{ - struct sphw_ceqs *ceqs = hwdev->ceqs; - struct interrupt_info info = {0}; - struct sphw_eq *eq = NULL; - u16 q_id; - int err; - - info.lli_set = 0; - info.interrupt_coalesc_set = 1; - info.pending_limt = SPHW_DEAULT_EQ_MSIX_PENDING_LIMIT; - info.coalesc_timer_cfg = SPHW_DEAULT_EQ_MSIX_COALESC_TIMER_CFG; - info.resend_timer_cfg = SPHW_DEAULT_EQ_MSIX_RESEND_TIMER_CFG; - - for (q_id = 0; q_id < ceqs->num_ceqs; q_id++) { - eq = &ceqs->ceq[q_id]; - info.msix_index = eq->eq_irq.msix_entry_idx; - err = sphw_set_interrupt_cfg(hwdev, info, SPHW_CHANNEL_COMM); - if (err) { - sdk_err(hwdev->dev_hdl, "Set msix attr for ceq %u failed\n", - q_id); - return -EFAULT; - } - } - - return 0; -} - -static int sphw_comm_aeqs_init(struct sphw_hwdev *hwdev) -{ - struct irq_info aeq_irqs[SPHW_MAX_AEQS] = {{0} }; - u16 num_aeqs, resp_num_irq = 0, i; - int err; - - num_aeqs = SPHW_HWIF_NUM_AEQS(hwdev->hwif); - if (num_aeqs > SPHW_MAX_AEQS) { - sdk_warn(hwdev->dev_hdl, "Adjust aeq num to %d\n", - SPHW_MAX_AEQS); - num_aeqs = SPHW_MAX_AEQS; - } - err = sphw_alloc_irqs(hwdev, SERVICE_T_INTF, num_aeqs, aeq_irqs, &resp_num_irq); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to alloc aeq irqs, num_aeqs: %u\n", - num_aeqs); - return err; - } - - if (resp_num_irq < num_aeqs) { - sdk_warn(hwdev->dev_hdl, "Adjust aeq num to %u\n", - resp_num_irq); - num_aeqs = resp_num_irq; - } - - err = sphw_aeqs_init(hwdev, num_aeqs, aeq_irqs); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to init aeqs\n"); - goto aeqs_init_err; - } - - return 0; - -aeqs_init_err: - for (i = 0; i < num_aeqs; i++) - sphw_free_irq(hwdev, SERVICE_T_INTF, aeq_irqs[i].irq_id); - - return err; -} - -static void sphw_comm_aeqs_free(struct sphw_hwdev *hwdev) -{ - struct irq_info aeq_irqs[SPHW_MAX_AEQS] = {{0} }; - u16 num_irqs, i; - - sphw_get_aeq_irqs(hwdev, aeq_irqs, &num_irqs); - - sphw_aeqs_free(hwdev); - - for (i = 0; i < num_irqs; i++) - sphw_free_irq(hwdev, SERVICE_T_INTF, aeq_irqs[i].irq_id); -} - -static int sphw_comm_ceqs_init(struct sphw_hwdev *hwdev) -{ - struct irq_info ceq_irqs[SPHW_MAX_CEQS] = {{0} }; - u16 num_ceqs, resp_num_irq = 0, i; - int err; - - num_ceqs = SPHW_HWIF_NUM_CEQS(hwdev->hwif); - if (num_ceqs > SPHW_MAX_CEQS) { - sdk_warn(hwdev->dev_hdl, "Adjust ceq num to %d\n", - SPHW_MAX_CEQS); - num_ceqs = SPHW_MAX_CEQS; - } - - err = sphw_alloc_irqs(hwdev, SERVICE_T_INTF, num_ceqs, ceq_irqs, &resp_num_irq); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to alloc ceq irqs, num_ceqs: %u\n", - num_ceqs); - return err; - } - - if (resp_num_irq < num_ceqs) { - sdk_warn(hwdev->dev_hdl, "Adjust ceq num to %u\n", - resp_num_irq); - num_ceqs = resp_num_irq; - } - - err = sphw_ceqs_init(hwdev, num_ceqs, ceq_irqs); - if (err) { - sdk_err(hwdev->dev_hdl, - "Failed to init ceqs, err:%d\n", err); - goto ceqs_init_err; - } - - return 0; - -ceqs_init_err: - for (i = 0; i < num_ceqs; i++) - sphw_free_irq(hwdev, SERVICE_T_INTF, ceq_irqs[i].irq_id); - - return err; -} - -static void sphw_comm_ceqs_free(struct sphw_hwdev *hwdev) -{ - struct irq_info ceq_irqs[SPHW_MAX_CEQS] = {{0} }; - u16 num_irqs; - int i; - - sphw_get_ceq_irqs(hwdev, ceq_irqs, &num_irqs); - - sphw_ceqs_free(hwdev); - - for (i = 0; i < num_irqs; i++) - sphw_free_irq(hwdev, SERVICE_T_INTF, ceq_irqs[i].irq_id); -} - -static int sphw_comm_func_to_func_init(struct sphw_hwdev *hwdev) -{ - int err; - - err = sphw_func_to_func_init(hwdev); - if (err) - return err; - - sphw_aeq_register_hw_cb(hwdev, SPHW_MBX_FROM_FUNC, sphw_mbox_func_aeqe_handler); - sphw_aeq_register_hw_cb(hwdev, SPHW_MSG_FROM_MGMT_CPU, sphw_mgmt_msg_aeqe_handler); - - if (!SPHW_IS_VF(hwdev)) - sphw_register_pf_mbox_cb(hwdev, SPHW_MOD_COMM, hwdev->func_to_func, - pf_handle_vf_comm_mbox); - else - sphw_register_vf_mbox_cb(hwdev, SPHW_MOD_COMM, hwdev->func_to_func, - vf_handle_pf_comm_mbox); - - return 0; -} - -static void sphw_comm_func_to_func_free(struct sphw_hwdev *hwdev) -{ - sphw_aeq_unregister_hw_cb(hwdev, SPHW_MBX_FROM_FUNC); - - if (!SPHW_IS_VF(hwdev)) { - sphw_unregister_pf_mbox_cb(hwdev, SPHW_MOD_COMM); - } else { - sphw_unregister_vf_mbox_cb(hwdev, SPHW_MOD_COMM); - - sphw_aeq_unregister_hw_cb(hwdev, SPHW_MSG_FROM_MGMT_CPU); - } - - sphw_func_to_func_free(hwdev); -} - -static int sphw_comm_pf_to_mgmt_init(struct sphw_hwdev *hwdev) -{ - int err; - - /* VF do not support api chain */ - if (sphw_func_type(hwdev) == TYPE_VF || - !COMM_SUPPORT_API_CHAIN(hwdev)) - return 0; - - err = sphw_pf_to_mgmt_init(hwdev); - if (err) - return err; - - sphw_register_mgmt_msg_cb(hwdev, SPHW_MOD_COMM, hwdev->pf_to_mgmt, - pf_handle_mgmt_comm_event); - - return 0; -} - -static void sphw_comm_pf_to_mgmt_free(struct sphw_hwdev *hwdev) -{ - /* VF do not support api chain */ - if (sphw_func_type(hwdev) == TYPE_VF || - !COMM_SUPPORT_API_CHAIN(hwdev)) - return; - - sphw_unregister_mgmt_msg_cb(hwdev, SPHW_MOD_COMM); - - sphw_aeq_unregister_hw_cb(hwdev, SPHW_MSG_FROM_MGMT_CPU); - - sphw_pf_to_mgmt_free(hwdev); -} - -static int sphw_comm_cmdqs_init(struct sphw_hwdev *hwdev) -{ - int err; - - err = sphw_cmdqs_init(hwdev); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to init cmd queues\n"); - return err; - } - - sphw_ceq_register_cb(hwdev, SPHW_CMDQ, sphw_cmdq_ceq_handler); - - err = sphw_set_cmdq_depth(hwdev, SPHW_CMDQ_DEPTH); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to set cmdq depth\n"); - goto set_cmdq_depth_err; - } - - return 0; - -set_cmdq_depth_err: - sphw_cmdqs_free(hwdev); - - return err; -} - -static void sphw_comm_cmdqs_free(struct sphw_hwdev *hwdev) -{ - sphw_ceq_unregister_cb(hwdev, SPHW_CMDQ); - sphw_cmdqs_free(hwdev); -} - -static void sphw_sync_mgmt_func_state(struct sphw_hwdev *hwdev) -{ - sphw_set_pf_status(hwdev->hwif, SPHW_PF_STATUS_ACTIVE_FLAG); -} - -static void sphw_unsync_mgmt_func_state(struct sphw_hwdev *hwdev) -{ - sphw_set_pf_status(hwdev->hwif, SPHW_PF_STATUS_INIT); -} - -static int init_basic_attributes(struct sphw_hwdev *hwdev) -{ - u64 drv_feature[COMM_MAX_FEATURE_QWORD] = {SPHW_DRV_FEATURE_QW0}; - int err, i; - - err = sphw_get_board_info(hwdev, &hwdev->board_info, SPHW_CHANNEL_COMM); - if (err) - return err; - - err = sphw_get_comm_features(hwdev, hwdev->features, COMM_MAX_FEATURE_QWORD); - if (err) { - sdk_err(hwdev->dev_hdl, "Get comm features failed\n"); - return err; - } - - sdk_info(hwdev->dev_hdl, "Comm hw features: 0x%llx, drv features: 0x%llx\n", - hwdev->features[0], drv_feature[0]); - - for (i = 0; i < COMM_MAX_FEATURE_QWORD; i++) - hwdev->features[i] &= drv_feature[i]; - - err = sphw_get_global_attr(hwdev, &hwdev->glb_attr); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to get global attribute\n"); - return err; - } - - sdk_info(hwdev->dev_hdl, "global attribute: max_host: 0x%x, max_pf: 0x%x, vf_id_start: 0x%x, mgmt cpu node id: 0x%x\n", - hwdev->glb_attr.max_host_num, hwdev->glb_attr.max_pf_num, - hwdev->glb_attr.vf_id_start, - hwdev->glb_attr.mgmt_host_node_id); - - sphw_init_profile_adapter(hwdev); - - return 0; -} - -static int init_basic_mgmt_channel(struct sphw_hwdev *hwdev) -{ - int err; - - err = sphw_comm_aeqs_init(hwdev); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to init async event queues\n"); - return err; - } - - err = sphw_comm_func_to_func_init(hwdev); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to init mailbox\n"); - goto func_to_func_init_err; - } - - err = init_aeqs_msix_attr(hwdev); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to init aeqs msix attr\n"); - goto aeqs_msix_attr_init_err; - } - - return 0; - -aeqs_msix_attr_init_err: - sphw_comm_func_to_func_free(hwdev); - -func_to_func_init_err: - sphw_comm_aeqs_free(hwdev); - - return err; -} - -static void free_base_mgmt_channel(struct sphw_hwdev *hwdev) -{ - sphw_comm_func_to_func_free(hwdev); - sphw_comm_aeqs_free(hwdev); -} - -static int init_pf_mgmt_channel(struct sphw_hwdev *hwdev) -{ - int err; - - err = sphw_comm_pf_to_mgmt_init(hwdev); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to init pf to mgmt\n"); - return err; - } - - return 0; -} - -static void free_pf_mgmt_channel(struct sphw_hwdev *hwdev) -{ - sphw_comm_pf_to_mgmt_free(hwdev); -} - -static int init_mgmt_channel_post(struct sphw_hwdev *hwdev) -{ - int err; - - /* mbox host channel resources will be freed in - * sphw_func_to_func_free - */ - err = sphw_mbox_init_host_msg_channel(hwdev); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to init mbox host channel\n"); - return err; - } - - err = init_pf_mgmt_channel(hwdev); - if (err) - return err; - - return 0; -} - -static void free_mgmt_msg_channel_post(struct sphw_hwdev *hwdev) -{ - free_pf_mgmt_channel(hwdev); -} - -static int init_cmdqs_channel(struct sphw_hwdev *hwdev) -{ - int err; - - err = dma_attr_table_init(hwdev); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to init dma attr table\n"); - goto dma_attr_init_err; - } - - err = sphw_comm_ceqs_init(hwdev); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to init completion event queues\n"); - goto ceqs_init_err; - } - - err = init_ceqs_msix_attr(hwdev); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to init ceqs msix attr\n"); - goto init_ceq_msix_err; - } - - /* set default wq page_size */ - if (wq_page_order > SPHW_MAX_WQ_PAGE_SIZE_ORDER) { - sdk_info(hwdev->dev_hdl, "wq_page_order exceed limit[0, %d], reset to %d\n", - SPHW_MAX_WQ_PAGE_SIZE_ORDER, - SPHW_MAX_WQ_PAGE_SIZE_ORDER); - wq_page_order = SPHW_MAX_WQ_PAGE_SIZE_ORDER; - } - hwdev->wq_page_size = SPHW_HW_WQ_PAGE_SIZE * (1U << wq_page_order); - sdk_info(hwdev->dev_hdl, "WQ page size: 0x%x\n", hwdev->wq_page_size); - err = sphw_set_wq_page_size(hwdev, sphw_global_func_id(hwdev), hwdev->wq_page_size, - SPHW_CHANNEL_COMM); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to set wq page size\n"); - goto init_wq_pg_size_err; - } - - err = sphw_comm_cmdqs_init(hwdev); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to init cmd queues\n"); - goto cmdq_init_err; - } - - return 0; - -cmdq_init_err: - if (SPHW_FUNC_TYPE(hwdev) != TYPE_VF) - sphw_set_wq_page_size(hwdev, sphw_global_func_id(hwdev), SPHW_HW_WQ_PAGE_SIZE, - SPHW_CHANNEL_COMM); -init_wq_pg_size_err: -init_ceq_msix_err: - sphw_comm_ceqs_free(hwdev); - -ceqs_init_err: -dma_attr_init_err: - - return err; -} - -int sphw_init_comm_ch(struct sphw_hwdev *hwdev) -{ - int err; - - err = init_basic_mgmt_channel(hwdev); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to init mgmt channel\n"); - return err; - } - - err = sphw_func_reset(hwdev, sphw_global_func_id(hwdev), SPHW_COMM_RES, SPHW_CHANNEL_COMM); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to reset function\n"); - goto func_reset_err; - } - - err = init_basic_attributes(hwdev); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to init basic attributes\n"); - goto init_basic_attr_err; - } - - err = init_mgmt_channel_post(hwdev); - if (err) - goto init_mgmt_channel_post_err; - - err = init_cmdqs_channel(hwdev); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to init cmdq channel\n"); - goto init_cmdqs_channel_err; - } - - sphw_sync_mgmt_func_state(hwdev); - - if (SPHW_F_CHANNEL_LOCK_EN(hwdev)) { - sphw_mbox_enable_channel_lock(hwdev, true); - sphw_cmdq_enable_channel_lock(hwdev, true); - } - - return 0; - -init_cmdqs_channel_err: - free_mgmt_msg_channel_post(hwdev); -init_mgmt_channel_post_err: -init_basic_attr_err: -func_reset_err: - free_base_mgmt_channel(hwdev); - - return err; -} - -void sphw_uninit_comm_ch(struct sphw_hwdev *hwdev) -{ - sphw_unsync_mgmt_func_state(hwdev); - - sphw_comm_cmdqs_free(hwdev); - - if (SPHW_FUNC_TYPE(hwdev) != TYPE_VF) - sphw_set_wq_page_size(hwdev, sphw_global_func_id(hwdev), SPHW_HW_WQ_PAGE_SIZE, - SPHW_CHANNEL_COMM); - - sphw_comm_ceqs_free(hwdev); - - sphw_deinit_profile_adapter(hwdev); - - free_mgmt_msg_channel_post(hwdev); - - free_base_mgmt_channel(hwdev); -} - -int sphw_init_hwdev(struct sphw_init_para *para) -{ - struct sphw_hwdev *hwdev; - int err; - - hwdev = kzalloc(sizeof(*hwdev), GFP_KERNEL); - if (!hwdev) - return -ENOMEM; - - *para->hwdev = hwdev; - hwdev->adapter_hdl = para->adapter_hdl; - hwdev->pcidev_hdl = para->pcidev_hdl; - hwdev->dev_hdl = para->dev_hdl; - hwdev->chip_node = para->chip_node; - - hwdev->chip_fault_stats = vzalloc(SPHW_CHIP_FAULT_SIZE); - if (!hwdev->chip_fault_stats) - goto alloc_chip_fault_stats_err; - - err = sphw_init_hwif(hwdev, para->cfg_reg_base, para->intr_reg_base, - para->mgmt_reg_base, para->db_base_phy, - para->db_base, para->db_dwqe_len); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to init hwif\n"); - goto init_hwif_err; - } - - sphw_set_chip_present(hwdev); - - if (disable_cfg_comm) - return 0; - - hwdev->workq = alloc_workqueue(SPHW_HWDEV_WQ_NAME, WQ_MEM_RECLAIM, - SPHW_WQ_MAX_REQ); - if (!hwdev->workq) { - sdk_err(hwdev->dev_hdl, "Failed to alloc hardware workq\n"); - goto alloc_workq_err; - } - - sphw_init_heartbeat_detect(hwdev); - - err = init_cfg_mgmt(hwdev); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to init config mgmt\n"); - goto init_cfg_mgmt_err; - } - - err = sphw_init_comm_ch(hwdev); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to init communication channel\n"); - goto init_comm_ch_err; - } - - err = init_capability(hwdev); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to init capability\n"); - goto init_cap_err; - } - - err = sphw_set_comm_features(hwdev, hwdev->features, COMM_MAX_FEATURE_QWORD); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to set comm features\n"); - goto set_feature_err; - } - - return 0; - -set_feature_err: - free_capability(hwdev); - -init_cap_err: - sphw_uninit_comm_ch(hwdev); - -init_comm_ch_err: - free_cfg_mgmt(hwdev); - -init_cfg_mgmt_err: - sphw_destroy_heartbeat_detect(hwdev); - destroy_workqueue(hwdev->workq); - -alloc_workq_err: - sphw_free_hwif(hwdev); - -init_hwif_err: - vfree(hwdev->chip_fault_stats); - -alloc_chip_fault_stats_err: - kfree(hwdev); - *para->hwdev = NULL; - - return -EFAULT; -} - -void sphw_free_hwdev(void *hwdev) -{ - struct sphw_hwdev *dev = hwdev; - - sphw_func_rx_tx_flush(hwdev, SPHW_CHANNEL_COMM); - - free_capability(dev); - - sphw_uninit_comm_ch(dev); - - free_cfg_mgmt(dev); - sphw_destroy_heartbeat_detect(hwdev); - destroy_workqueue(dev->workq); - sphw_free_hwif(dev); - vfree(dev->chip_fault_stats); - - kfree(dev); -} - -void *sphw_get_pcidev_hdl(void *hwdev) -{ - struct sphw_hwdev *dev = (struct sphw_hwdev *)hwdev; - - if (!hwdev) - return NULL; - - return dev->pcidev_hdl; -} - -int sphw_register_service_adapter(void *hwdev, void *service_adapter, enum sphw_service_type type) -{ - struct sphw_hwdev *dev = hwdev; - - if (!hwdev || !service_adapter || type >= SERVICE_T_MAX) - return -EINVAL; - - if (dev->service_adapter[type]) - return -EINVAL; - - dev->service_adapter[type] = service_adapter; - - return 0; -} - -void sphw_unregister_service_adapter(void *hwdev, enum sphw_service_type type) -{ - struct sphw_hwdev *dev = hwdev; - - if (!hwdev || type >= SERVICE_T_MAX) - return; - - dev->service_adapter[type] = NULL; -} - -void *sphw_get_service_adapter(void *hwdev, enum sphw_service_type type) -{ - struct sphw_hwdev *dev = hwdev; - - if (!hwdev || type >= SERVICE_T_MAX) - return NULL; - - return dev->service_adapter[type]; -} - -int sphw_dbg_get_hw_stats(const void *hwdev, u8 *hw_stats, u16 *out_size) -{ - if (*out_size != sizeof(struct sphw_hw_stats)) { - pr_err("Unexpect out buf size from user :%u, expect: %lu\n", - *out_size, sizeof(struct sphw_hw_stats)); - return -EFAULT; - } - - memcpy(hw_stats, &((struct sphw_hwdev *)hwdev)->hw_stats, - sizeof(struct sphw_hw_stats)); - return 0; -} - -u16 sphw_dbg_clear_hw_stats(void *hwdev) -{ - memset((void *)&((struct sphw_hwdev *)hwdev)->hw_stats, 0, - sizeof(struct sphw_hw_stats)); - memset((void *)((struct sphw_hwdev *)hwdev)->chip_fault_stats, 0, - SPHW_CHIP_FAULT_SIZE); - return sizeof(struct sphw_hw_stats); -} - -void sphw_get_chip_fault_stats(const void *hwdev, u8 *chip_fault_stats, u32 offset) -{ - u32 copy_len = offset + MAX_DRV_BUF_SIZE - SPHW_CHIP_FAULT_SIZE; - - if (offset + MAX_DRV_BUF_SIZE <= SPHW_CHIP_FAULT_SIZE) - memcpy(chip_fault_stats, - ((struct sphw_hwdev *)hwdev)->chip_fault_stats - + offset, MAX_DRV_BUF_SIZE); - else - memcpy(chip_fault_stats, - ((struct sphw_hwdev *)hwdev)->chip_fault_stats - + offset, copy_len); -} - -void sphw_event_register(void *dev, void *pri_handle, sphw_event_handler callback) -{ - struct sphw_hwdev *hwdev = dev; - - if (!dev) { - pr_err("Hwdev pointer is NULL for register event\n"); - return; - } - - hwdev->event_callback = callback; - hwdev->event_pri_handle = pri_handle; -} - -void sphw_event_unregister(void *dev) -{ - struct sphw_hwdev *hwdev = dev; - - if (!dev) { - pr_err("Hwdev pointer is NULL for register event\n"); - return; - } - - hwdev->event_callback = NULL; - hwdev->event_pri_handle = NULL; -} - -void sphw_event_callback(void *hwdev, struct sphw_event_info *event) -{ - struct sphw_hwdev *dev = hwdev; - - if (!hwdev) { - pr_err("Hwdev pointer is NULL for event callback\n"); - return; - } - - if (!dev->event_callback) { - sdk_info(dev->dev_hdl, "Event callback function not register\n"); - return; - } - - dev->event_callback(dev->event_pri_handle, event); -} - -void sphw_set_pcie_order_cfg(void *handle) -{ -} - -void sphw_disable_mgmt_msg_report(void *hwdev) -{ - struct sphw_hwdev *hw_dev = (struct sphw_hwdev *)hwdev; - - sphw_set_pf_status(hw_dev->hwif, SPHW_PF_STATUS_INIT); -} - -void sphw_record_pcie_error(void *hwdev) -{ - struct sphw_hwdev *dev = (struct sphw_hwdev *)hwdev; - - if (!hwdev) - return; - - atomic_inc(&dev->hw_stats.fault_event_stats.pcie_fault_stats); -} - -int sphw_get_card_present_state(void *hwdev, bool *card_present_state) -{ - struct sphw_hwdev *dev = hwdev; - u32 addr, attr1; - - if (!hwdev || !card_present_state) - return -EINVAL; - - addr = SPHW_CSR_FUNC_ATTR1_ADDR; - attr1 = sphw_hwif_read_reg(dev->hwif, addr); - if (attr1 == SPHW_PCIE_LINK_DOWN) { - sdk_warn(dev->dev_hdl, "Card is not present\n"); - *card_present_state = (bool)0; - } else { - *card_present_state = (bool)1; - } - - return 0; -} - -void sphw_link_event_stats(void *dev, u8 link) -{ - struct sphw_hwdev *hwdev = dev; - - if (link) - atomic_inc(&hwdev->hw_stats.link_event_stats.link_up_stats); - else - atomic_inc(&hwdev->hw_stats.link_event_stats.link_down_stats); -} - -u8 sphw_max_pf_num(void *hwdev) -{ - if (!hwdev) - return 0; - - return SPHW_MAX_PF_NUM((struct sphw_hwdev *)hwdev); -} - -void sphw_fault_event_report(void *hwdev, u16 src, u16 level) -{ - if (!hwdev) - return; - - sdk_info(((struct sphw_hwdev *)hwdev)->dev_hdl, "Fault event report, src: %u, level: %u\n", - src, level); - - sphw_fault_post_process(hwdev, src, level); -} - -void sphw_heartbeat_lost_handler(struct work_struct *work) -{ - struct sphw_event_info event_info = { 0 }; - struct sphw_hwdev *hwdev = container_of(work, struct sphw_hwdev, - heartbeat_lost_work); - u16 src, level; - - atomic_inc(&hwdev->hw_stats.heart_lost_stats); - - if (hwdev->event_callback) { - event_info.type = - hwdev->pcie_link_down ? SPHW_EVENT_PCIE_LINK_DOWN : - SPHW_EVENT_HEART_LOST; - hwdev->event_callback(hwdev->event_pri_handle, &event_info); - } - - if (hwdev->pcie_link_down) { - src = SPHW_FAULT_SRC_PCIE_LINK_DOWN; - level = FAULT_LEVEL_HOST; - sdk_err(hwdev->dev_hdl, "Detect pcie is link down\n"); - } else { - src = SPHW_FAULT_SRC_HOST_HEARTBEAT_LOST; - level = FAULT_LEVEL_FATAL; - sdk_err(hwdev->dev_hdl, "Heart lost report received, func_id: %d\n", - sphw_global_func_id(hwdev)); - } - - sphw_fault_post_process(hwdev, src, level); -} - -#define DETECT_PCIE_LINK_DOWN_RETRY 2 -#define SPHW_HEARTBEAT_START_EXPIRE 5000 -#define SPHW_HEARTBEAT_PERIOD 1000 - -static bool sphw_is_hw_abnormal(struct sphw_hwdev *hwdev) -{ - u32 status; - - if (!sphw_get_chip_present_flag(hwdev)) - return false; - - status = sphw_get_heartbeat_status(hwdev); - if (status == SPHW_PCIE_LINK_DOWN) { - sdk_warn(hwdev->dev_hdl, "Detect BAR register read failed\n"); - hwdev->rd_bar_err_cnt++; - if (hwdev->rd_bar_err_cnt >= DETECT_PCIE_LINK_DOWN_RETRY) { - sphw_set_chip_absent(hwdev); - sphw_force_complete_all(hwdev); - hwdev->pcie_link_down = true; - return true; - } - - return false; - } - - if (status) { - hwdev->heartbeat_lost = true; - return true; - } - - hwdev->rd_bar_err_cnt = 0; - - return false; -} - -static void sphw_heartbeat_timer_handler(struct timer_list *t) -{ - struct sphw_hwdev *hwdev = from_timer(hwdev, t, heartbeat_timer); - - if (sphw_is_hw_abnormal(hwdev)) - queue_work(hwdev->workq, &hwdev->heartbeat_lost_work); - else - mod_timer(&hwdev->heartbeat_timer, - jiffies + msecs_to_jiffies(SPHW_HEARTBEAT_PERIOD)); -} - -static void sphw_init_heartbeat_detect(struct sphw_hwdev *hwdev) -{ - timer_setup(&hwdev->heartbeat_timer, sphw_heartbeat_timer_handler, 0); - - hwdev->heartbeat_timer.expires = - jiffies + msecs_to_jiffies(SPHW_HEARTBEAT_START_EXPIRE); - - add_timer(&hwdev->heartbeat_timer); - - INIT_WORK(&hwdev->heartbeat_lost_work, sphw_heartbeat_lost_handler); -} - -static void sphw_destroy_heartbeat_detect(struct sphw_hwdev *hwdev) -{ - del_timer_sync(&hwdev->heartbeat_timer); -} diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hwdev.h b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hwdev.h deleted file mode 100644 index 10da31bda3d2..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hwdev.h +++ /dev/null @@ -1,93 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPHW_HWDEV_H -#define SPHW_HWDEV_H - -#include "sphw_mt.h" -#include "sphw_crm.h" -#include "sphw_hw.h" - -struct cfg_mgmt_info; - -struct sphw_hwif; -struct sphw_aeqs; -struct sphw_ceqs; -struct sphw_mbox; -struct sphw_msg_pf_to_mgmt; - -struct sphw_page_addr { - void *virt_addr; - u64 phys_addr; -}; - -struct mqm_addr_trans_tbl_info { - u32 chunk_num; - u32 search_gpa_num; - u32 page_size; - u32 page_num; - struct sphw_page_addr *brm_srch_page_addr; -}; - -struct sphw_hwdev { - void *adapter_hdl; /* pointer to spnic_pcidev or NDIS_Adapter */ - void *pcidev_hdl; /* pointer to pcidev or Handler */ - void *dev_hdl; /* pointer to pcidev->dev or Handler, for - * sdk_err() or dma_alloc() - */ - - void *service_adapter[SERVICE_T_MAX]; - void *chip_node; - void *ppf_hwdev; - - u32 wq_page_size; - int chip_present_flag; - - struct sphw_hwif *hwif; /* include void __iomem *bar */ - struct comm_global_attr glb_attr; - u64 features[COMM_MAX_FEATURE_QWORD]; - - struct cfg_mgmt_info *cfg_mgmt; - - struct sphw_cmdqs *cmdqs; - struct sphw_aeqs *aeqs; - struct sphw_ceqs *ceqs; - struct sphw_mbox *func_to_func; - struct sphw_msg_pf_to_mgmt *pf_to_mgmt; - - void *cqm_hdl; - struct mqm_addr_trans_tbl_info mqm_att; - struct sphw_page_addr page_pa0; - struct sphw_page_addr page_pa1; - u32 statufull_ref_cnt; - - struct sphw_hw_stats hw_stats; - u8 *chip_fault_stats; - - sphw_event_handler event_callback; - void *event_pri_handle; - - struct sphw_board_info board_info; - - int prof_adap_type; - struct sphw_prof_attr *prof_attr; - - struct workqueue_struct *workq; - - u32 rd_bar_err_cnt; - bool pcie_link_down; - bool heartbeat_lost; - struct timer_list heartbeat_timer; - struct work_struct heartbeat_lost_work; -}; - -#define SPHW_MAX_HOST_NUM(hwdev) ((hwdev)->glb_attr.max_host_num) -#define SPHW_MAX_PF_NUM(hwdev) ((hwdev)->glb_attr.max_pf_num) -#define SPHW_MGMT_CPU_NODE_ID(hwdev) ((hwdev)->glb_attr.mgmt_host_node_id) - -#define COMM_FEATURE_QW0(hwdev, feature) ((hwdev)->features[0] & COMM_F_##feature) -#define COMM_SUPPORT_API_CHAIN(hwdev) COMM_FEATURE_QW0(hwdev, API_CHAIN) - -#define SPHW_DRV_FEATURE_QW0 COMM_F_API_CHAIN - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hwif.c b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hwif.c deleted file mode 100644 index fbb1128957f0..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hwif.c +++ /dev/null @@ -1,886 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [COMM]" fmt - -#include <linux/types.h> -#include <linux/pci.h> -#include <linux/delay.h> -#include <linux/module.h> - -#include "sphw_csr.h" -#include "sphw_crm.h" -#include "sphw_hw.h" -#include "sphw_common.h" -#include "sphw_hwdev.h" -#include "sphw_hwif.h" - -#define WAIT_HWIF_READY_TIMEOUT 10000 -#define SPHW_WAIT_DOORBELL_AND_OUTBOUND_TIMEOUT 60000 - -#define DB_IDX(db, db_base) \ - ((u32)(((ulong)(db) - (ulong)(db_base)) / \ - SPHW_DB_PAGE_SIZE)) - -#define SPHW_AF0_FUNC_GLOBAL_IDX_SHIFT 0 -#define SPHW_AF0_P2P_IDX_SHIFT 12 -#define SPHW_AF0_PCI_INTF_IDX_SHIFT 17 -#define SPHW_AF0_VF_IN_PF_SHIFT 20 -#define SPHW_AF0_FUNC_TYPE_SHIFT 28 - -#define SPHW_AF0_FUNC_GLOBAL_IDX_MASK 0xFFF -#define SPHW_AF0_P2P_IDX_MASK 0x1F -#define SPHW_AF0_PCI_INTF_IDX_MASK 0x7 -#define SPHW_AF0_VF_IN_PF_MASK 0xFF -#define SPHW_AF0_FUNC_TYPE_MASK 0x1 - -#define SPHW_AF0_GET(val, member) \ - (((val) >> SPHW_AF0_##member##_SHIFT) & SPHW_AF0_##member##_MASK) - -#define SPHW_AF1_PPF_IDX_SHIFT 0 -#define SPHW_AF1_AEQS_PER_FUNC_SHIFT 8 -#define SPHW_AF1_MGMT_INIT_STATUS_SHIFT 30 -#define SPHW_AF1_PF_INIT_STATUS_SHIFT 31 - -#define SPHW_AF1_PPF_IDX_MASK 0x3F -#define SPHW_AF1_AEQS_PER_FUNC_MASK 0x3 -#define SPHW_AF1_MGMT_INIT_STATUS_MASK 0x1 -#define SPHW_AF1_PF_INIT_STATUS_MASK 0x1 - -#define SPHW_AF1_GET(val, member) \ - (((val) >> SPHW_AF1_##member##_SHIFT) & SPHW_AF1_##member##_MASK) - -#define SPHW_AF2_CEQS_PER_FUNC_SHIFT 0 -#define SPHW_AF2_DMA_ATTR_PER_FUNC_SHIFT 9 -#define SPHW_AF2_IRQS_PER_FUNC_SHIFT 16 - -#define SPHW_AF2_CEQS_PER_FUNC_MASK 0x1FF -#define SPHW_AF2_DMA_ATTR_PER_FUNC_MASK 0x7 -#define SPHW_AF2_IRQS_PER_FUNC_MASK 0x7FF - -#define SPHW_AF2_GET(val, member) \ - (((val) >> SPHW_AF2_##member##_SHIFT) & SPHW_AF2_##member##_MASK) - -#define SPHW_AF3_GLOBAL_VF_ID_OF_NXT_PF_SHIFT 0 -#define SPHW_AF3_GLOBAL_VF_ID_OF_PF_SHIFT 16 - -#define SPHW_AF3_GLOBAL_VF_ID_OF_NXT_PF_MASK 0xFFF -#define SPHW_AF3_GLOBAL_VF_ID_OF_PF_MASK 0xFFF - -#define SPHW_AF3_GET(val, member) \ - (((val) >> SPHW_AF3_##member##_SHIFT) & SPHW_AF3_##member##_MASK) - -#define SPHW_AF4_DOORBELL_CTRL_SHIFT 0 -#define SPHW_AF4_DOORBELL_CTRL_MASK 0x1 - -#define SPHW_AF4_GET(val, member) \ - (((val) >> SPHW_AF4_##member##_SHIFT) & SPHW_AF4_##member##_MASK) - -#define SPHW_AF4_SET(val, member) \ - (((val) & SPHW_AF4_##member##_MASK) << SPHW_AF4_##member##_SHIFT) - -#define SPHW_AF4_CLEAR(val, member) \ - ((val) & (~(SPHW_AF4_##member##_MASK << SPHW_AF4_##member##_SHIFT))) - -#define SPHW_AF5_OUTBOUND_CTRL_SHIFT 0 -#define SPHW_AF5_OUTBOUND_CTRL_MASK 0x1 - -#define SPHW_AF5_GET(val, member) \ - (((val) >> SPHW_AF5_##member##_SHIFT) & SPHW_AF5_##member##_MASK) - -#define SPHW_AF5_SET(val, member) \ - (((val) & SPHW_AF5_##member##_MASK) << SPHW_AF5_##member##_SHIFT) - -#define SPHW_AF5_CLEAR(val, member) \ - ((val) & (~(SPHW_AF5_##member##_MASK << SPHW_AF5_##member##_SHIFT))) - -#define SPHW_AF6_PF_STATUS_SHIFT 0 -#define SPHW_AF6_PF_STATUS_MASK 0xFFFF - -#define SPHW_AF6_SET(val, member) \ - ((((u32)(val)) & SPHW_AF6_##member##_MASK) << \ - SPHW_AF6_##member##_SHIFT) - -#define SPHW_AF6_GET(val, member) \ - (((val) >> SPHW_AF6_##member##_SHIFT) & SPHW_AF6_##member##_MASK) - -#define SPHW_AF6_CLEAR(val, member) \ - ((val) & (~(SPHW_AF6_##member##_MASK << \ - SPHW_AF6_##member##_SHIFT))) - -#define sphw_PPF_ELECT_PORT_IDX_SHIFT 0 - -#define sphw_PPF_ELECT_PORT_IDX_MASK 0x3F - -#define sphw_PPF_ELECT_PORT_GET(val, member) \ - (((val) >> sphw_PPF_ELECT_PORT_##member##_SHIFT) & \ - sphw_PPF_ELECT_PORT_##member##_MASK) - -#define SPHW_PPF_ELECTION_IDX_SHIFT 0 - -#define SPHW_PPF_ELECTION_IDX_MASK 0x3F - -#define SPHW_PPF_ELECTION_SET(val, member) \ - (((val) & SPHW_PPF_ELECTION_##member##_MASK) << \ - SPHW_PPF_ELECTION_##member##_SHIFT) - -#define SPHW_PPF_ELECTION_GET(val, member) \ - (((val) >> SPHW_PPF_ELECTION_##member##_SHIFT) & \ - SPHW_PPF_ELECTION_##member##_MASK) - -#define SPHW_PPF_ELECTION_CLEAR(val, member) \ - ((val) & (~(SPHW_PPF_ELECTION_##member##_MASK << \ - SPHW_PPF_ELECTION_##member##_SHIFT))) - -#define SPHW_MPF_ELECTION_IDX_SHIFT 0 - -#define SPHW_MPF_ELECTION_IDX_MASK 0x1F - -#define SPHW_MPF_ELECTION_SET(val, member) \ - (((val) & SPHW_MPF_ELECTION_##member##_MASK) << \ - SPHW_MPF_ELECTION_##member##_SHIFT) - -#define SPHW_MPF_ELECTION_GET(val, member) \ - (((val) >> SPHW_MPF_ELECTION_##member##_SHIFT) & \ - SPHW_MPF_ELECTION_##member##_MASK) - -#define SPHW_MPF_ELECTION_CLEAR(val, member) \ - ((val) & (~(SPHW_MPF_ELECTION_##member##_MASK << \ - SPHW_MPF_ELECTION_##member##_SHIFT))) - -#define SPHW_GET_REG_FLAG(reg) ((reg) & (~(SPHW_REGS_FLAG_MAKS))) - -#define SPHW_GET_REG_ADDR(reg) ((reg) & (SPHW_REGS_FLAG_MAKS)) - -u32 sphw_hwif_read_reg(struct sphw_hwif *hwif, u32 reg) -{ - if (SPHW_GET_REG_FLAG(reg) == SPHW_MGMT_REGS_FLAG) - return be32_to_cpu(readl(hwif->mgmt_regs_base + - SPHW_GET_REG_ADDR(reg))); - else - return be32_to_cpu(readl(hwif->cfg_regs_base + - SPHW_GET_REG_ADDR(reg))); -} - -void sphw_hwif_write_reg(struct sphw_hwif *hwif, u32 reg, u32 val) -{ - if (SPHW_GET_REG_FLAG(reg) == SPHW_MGMT_REGS_FLAG) - writel(cpu_to_be32(val), - hwif->mgmt_regs_base + SPHW_GET_REG_ADDR(reg)); - else - writel(cpu_to_be32(val), - hwif->cfg_regs_base + SPHW_GET_REG_ADDR(reg)); -} - -/** - * sphw_get_heartbeat_status - get heart beat status - * @hwdev: the pointer to hw device - * Return: 0 - normal, 1 - heart lost, 0xFFFFFFFF - Pcie link down - **/ -u32 sphw_get_heartbeat_status(struct sphw_hwdev *hwdev) -{ - u32 attr1; - - attr1 = sphw_hwif_read_reg(hwdev->hwif, SPHW_CSR_FUNC_ATTR1_ADDR); - if (attr1 == SPHW_PCIE_LINK_DOWN) - return attr1; - - return !SPHW_AF1_GET(attr1, MGMT_INIT_STATUS); -} - -/** - * hwif_ready - test if the HW initialization passed - * @hwdev: the pointer to hw device - * Return: 0 - success, negative - failure - **/ -static int hwif_ready(struct sphw_hwdev *hwdev) -{ - if (sphw_get_heartbeat_status(hwdev)) - return -EBUSY; - - return 0; -} - -static enum sphw_wait_return check_hwif_ready_handler(void *priv_data) -{ - if (!hwif_ready(priv_data)) - return WAIT_PROCESS_CPL; - - return WAIT_PROCESS_WAITING; -} - -static int wait_hwif_ready(struct sphw_hwdev *hwdev) -{ - if (!sphw_wait_for_timeout(hwdev, check_hwif_ready_handler, - WAIT_HWIF_READY_TIMEOUT, USEC_PER_MSEC)) - return 0; - - sdk_err(hwdev->dev_hdl, "Wait for hwif timeout\n"); - return -EBUSY; -} - -/** - * set_hwif_attr - set the attributes as members in hwif - * @hwif: the hardware interface of a pci function device - * @attr0: the first attribute that was read from the hw - * @attr1: the second attribute that was read from the hw - * @attr2: the third attribute that was read from the hw - * @attr3: the fourth attribute that was read from the hw - **/ -static void set_hwif_attr(struct sphw_hwif *hwif, u32 attr0, u32 attr1, - u32 attr2, u32 attr3) -{ - hwif->attr.func_global_idx = SPHW_AF0_GET(attr0, FUNC_GLOBAL_IDX); - hwif->attr.port_to_port_idx = SPHW_AF0_GET(attr0, P2P_IDX); - hwif->attr.pci_intf_idx = SPHW_AF0_GET(attr0, PCI_INTF_IDX); - hwif->attr.vf_in_pf = SPHW_AF0_GET(attr0, VF_IN_PF); - hwif->attr.func_type = SPHW_AF0_GET(attr0, FUNC_TYPE); - - hwif->attr.ppf_idx = SPHW_AF1_GET(attr1, PPF_IDX); - hwif->attr.num_aeqs = BIT(SPHW_AF1_GET(attr1, AEQS_PER_FUNC)); - hwif->attr.num_ceqs = (u8)SPHW_AF2_GET(attr2, CEQS_PER_FUNC); - hwif->attr.num_irqs = SPHW_AF2_GET(attr2, IRQS_PER_FUNC); - hwif->attr.num_dma_attr = BIT(SPHW_AF2_GET(attr2, DMA_ATTR_PER_FUNC)); - - hwif->attr.global_vf_id_of_pf = SPHW_AF3_GET(attr3, GLOBAL_VF_ID_OF_PF); - - pr_info("func_global_idx: 0x%x, port_to_port_idx: 0x%x, pci_intf_idx: 0x%x, vf_in_pf: 0x%x, func_type: %d\n", - hwif->attr.func_global_idx, hwif->attr.port_to_port_idx, - hwif->attr.pci_intf_idx, hwif->attr.vf_in_pf, - hwif->attr.func_type); - - pr_info("ppf_idx: 0x%x, num_aeqs: 0x%x, num_ceqs: 0x%x, num_irqs: 0x%x, num_dma_attr: 0x%x, global_vf_id_of_pf: %u\n", - hwif->attr.ppf_idx, hwif->attr.num_aeqs, - hwif->attr.num_ceqs, hwif->attr.num_irqs, - hwif->attr.num_dma_attr, hwif->attr.global_vf_id_of_pf); -} - -/** - * get_hwif_attr - read and set the attributes as members in hwif - * @hwif: the hardware interface of a pci function device - **/ -static void get_hwif_attr(struct sphw_hwif *hwif) -{ - u32 addr, attr0, attr1, attr2, attr3; - - addr = SPHW_CSR_FUNC_ATTR0_ADDR; - attr0 = sphw_hwif_read_reg(hwif, addr); - - addr = SPHW_CSR_FUNC_ATTR1_ADDR; - attr1 = sphw_hwif_read_reg(hwif, addr); - - addr = SPHW_CSR_FUNC_ATTR2_ADDR; - attr2 = sphw_hwif_read_reg(hwif, addr); - - addr = SPHW_CSR_FUNC_ATTR3_ADDR; - attr3 = sphw_hwif_read_reg(hwif, addr); - - pr_info("attr0: 0x%08x, attr1: 0x%08x, attr2: 0x%08x, attr3: 0x%08x\n", - attr0, attr1, attr2, attr3); - set_hwif_attr(hwif, attr0, attr1, attr2, attr3); -} - -void sphw_set_pf_status(struct sphw_hwif *hwif, enum sphw_pf_status status) -{ - u32 attr6 = SPHW_AF6_SET(status, PF_STATUS); - u32 addr = SPHW_CSR_FUNC_ATTR6_ADDR; - - if (hwif->attr.func_type == TYPE_VF) - return; - - sphw_hwif_write_reg(hwif, addr, attr6); -} - -enum sphw_pf_status sphw_get_pf_status(struct sphw_hwif *hwif) -{ - u32 attr6 = sphw_hwif_read_reg(hwif, SPHW_CSR_FUNC_ATTR6_ADDR); - - return SPHW_AF6_GET(attr6, PF_STATUS); -} - -enum sphw_doorbell_ctrl sphw_get_doorbell_ctrl_status(struct sphw_hwif *hwif) -{ - u32 attr4 = sphw_hwif_read_reg(hwif, SPHW_CSR_FUNC_ATTR4_ADDR); - - return SPHW_AF4_GET(attr4, DOORBELL_CTRL); -} - -enum sphw_outbound_ctrl sphw_get_outbound_ctrl_status(struct sphw_hwif *hwif) -{ - u32 attr5 = sphw_hwif_read_reg(hwif, SPHW_CSR_FUNC_ATTR5_ADDR); - - return SPHW_AF5_GET(attr5, OUTBOUND_CTRL); -} - -void sphw_enable_doorbell(struct sphw_hwif *hwif) -{ - u32 addr, attr4; - - addr = SPHW_CSR_FUNC_ATTR4_ADDR; - attr4 = sphw_hwif_read_reg(hwif, addr); - - attr4 = SPHW_AF4_CLEAR(attr4, DOORBELL_CTRL); - attr4 |= SPHW_AF4_SET(ENABLE_DOORBELL, DOORBELL_CTRL); - - sphw_hwif_write_reg(hwif, addr, attr4); -} - -void sphw_disable_doorbell(struct sphw_hwif *hwif) -{ - u32 addr, attr4; - - addr = SPHW_CSR_FUNC_ATTR4_ADDR; - attr4 = sphw_hwif_read_reg(hwif, addr); - - attr4 = SPHW_AF4_CLEAR(attr4, DOORBELL_CTRL); - attr4 |= SPHW_AF4_SET(DISABLE_DOORBELL, DOORBELL_CTRL); - - sphw_hwif_write_reg(hwif, addr, attr4); -} - -/** - * set_ppf - try to set hwif as ppf and set the type of hwif in this case - * @hwif: the hardware interface of a pci function device - **/ -static void set_ppf(struct sphw_hwif *hwif) -{ - struct sphw_func_attr *attr = &hwif->attr; - u32 addr, val, ppf_election; - - /* Read Modify Write */ - addr = SPHW_CSR_PPF_ELECTION_ADDR; - - val = sphw_hwif_read_reg(hwif, addr); - val = SPHW_PPF_ELECTION_CLEAR(val, IDX); - - ppf_election = SPHW_PPF_ELECTION_SET(attr->func_global_idx, IDX); - val |= ppf_election; - - sphw_hwif_write_reg(hwif, addr, val); - - /* Check PPF */ - val = sphw_hwif_read_reg(hwif, addr); - - attr->ppf_idx = SPHW_PPF_ELECTION_GET(val, IDX); - if (attr->ppf_idx == attr->func_global_idx) - attr->func_type = TYPE_PPF; -} - -/** - * get_mpf - get the mpf index into the hwif - * @hwif: the hardware interface of a pci function device - **/ -static void get_mpf(struct sphw_hwif *hwif) -{ - struct sphw_func_attr *attr = &hwif->attr; - u32 mpf_election, addr; - - addr = SPHW_CSR_GLOBAL_MPF_ELECTION_ADDR; - - mpf_election = sphw_hwif_read_reg(hwif, addr); - attr->mpf_idx = SPHW_MPF_ELECTION_GET(mpf_election, IDX); -} - -/** - * set_mpf - try to set hwif as mpf and set the mpf idx in hwif - * @hwif: the hardware interface of a pci function device - **/ -static void set_mpf(struct sphw_hwif *hwif) -{ - struct sphw_func_attr *attr = &hwif->attr; - u32 addr, val, mpf_election; - - /* Read Modify Write */ - addr = SPHW_CSR_GLOBAL_MPF_ELECTION_ADDR; - - val = sphw_hwif_read_reg(hwif, addr); - - val = SPHW_MPF_ELECTION_CLEAR(val, IDX); - mpf_election = SPHW_MPF_ELECTION_SET(attr->func_global_idx, IDX); - - val |= mpf_election; - sphw_hwif_write_reg(hwif, addr, val); -} - -static int init_db_area_idx(struct sphw_free_db_area *free_db_area, u64 db_dwqe_len) -{ - u32 db_max_areas; - - db_max_areas = (db_dwqe_len > SPHW_DB_DWQE_SIZE) ? SPHW_DB_MAX_AREAS : - (u32)(db_dwqe_len / SPHW_DB_PAGE_SIZE); - free_db_area->db_bitmap_array = bitmap_zalloc(db_max_areas, GFP_KERNEL); - if (!free_db_area->db_bitmap_array) { - pr_err("Failed to allocate db area.\n"); - return -ENOMEM; - } - free_db_area->db_max_areas = db_max_areas; - spin_lock_init(&free_db_area->idx_lock); - - return 0; -} - -static void free_db_area(struct sphw_free_db_area *free_db_area) -{ - kfree(free_db_area->db_bitmap_array); -} - -static int get_db_idx(struct sphw_hwif *hwif, u32 *idx) -{ - struct sphw_free_db_area *free_db_area = &hwif->free_db_area; - u32 pg_idx; - - spin_lock(&free_db_area->idx_lock); - pg_idx = (u32)find_first_zero_bit(free_db_area->db_bitmap_array, - free_db_area->db_max_areas); - if (pg_idx == free_db_area->db_max_areas) { - spin_unlock(&free_db_area->idx_lock); - return -ENOMEM; - } - set_bit(pg_idx, free_db_area->db_bitmap_array); - spin_unlock(&free_db_area->idx_lock); - - *idx = pg_idx; - - return 0; -} - -static void free_db_idx(struct sphw_hwif *hwif, u32 idx) -{ - struct sphw_free_db_area *free_db_area = &hwif->free_db_area; - - if (idx >= free_db_area->db_max_areas) - return; - - spin_lock(&free_db_area->idx_lock); - clear_bit((int)idx, free_db_area->db_bitmap_array); - - spin_unlock(&free_db_area->idx_lock); -} - -void sphw_free_db_addr(void *hwdev, const void __iomem *db_base, void __iomem *dwqe_base) -{ - struct sphw_hwif *hwif = NULL; - u32 idx; - - if (!hwdev || !db_base) - return; - - hwif = ((struct sphw_hwdev *)hwdev)->hwif; - idx = DB_IDX(db_base, hwif->db_base); - - free_db_idx(hwif, idx); -} - -int sphw_alloc_db_addr(void *hwdev, void __iomem **db_base, void __iomem **dwqe_base) -{ - struct sphw_hwif *hwif = NULL; - u32 idx = 0; - int err; - - if (!hwdev || !db_base) - return -EINVAL; - - hwif = ((struct sphw_hwdev *)hwdev)->hwif; - - err = get_db_idx(hwif, &idx); - if (err) - return -EFAULT; - - *db_base = hwif->db_base + idx * SPHW_DB_PAGE_SIZE; - - if (!dwqe_base) - return 0; - - *dwqe_base = (u8 *)*db_base + SPHW_DWQE_OFFSET; - - return 0; -} - -void sphw_free_db_phy_addr(void *hwdev, u64 db_base, u64 dwqe_base) -{ - struct sphw_hwif *hwif = NULL; - u32 idx; - - if (!hwdev) - return; - - hwif = ((struct sphw_hwdev *)hwdev)->hwif; - idx = DB_IDX(db_base, hwif->db_base_phy); - - free_db_idx(hwif, idx); -} - -int sphw_alloc_db_phy_addr(void *hwdev, u64 *db_base, u64 *dwqe_base) -{ - struct sphw_hwif *hwif = NULL; - u32 idx; - int err; - - if (!hwdev || !db_base || !dwqe_base) - return -EINVAL; - - hwif = ((struct sphw_hwdev *)hwdev)->hwif; - - err = get_db_idx(hwif, &idx); - if (err) - return -EFAULT; - - *db_base = hwif->db_base_phy + idx * SPHW_DB_PAGE_SIZE; - *dwqe_base = *db_base + SPHW_DWQE_OFFSET; - - return 0; -} - -void sphw_set_msix_auto_mask_state(void *hwdev, u16 msix_idx, enum sphw_msix_auto_mask flag) -{ - struct sphw_hwif *hwif = NULL; - u32 mask_bits; - u32 addr; - - if (!hwdev) - return; - - hwif = ((struct sphw_hwdev *)hwdev)->hwif; - - if (flag) - mask_bits = SPHW_MSI_CLR_INDIR_SET(1, AUTO_MSK_SET); - else - mask_bits = SPHW_MSI_CLR_INDIR_SET(1, AUTO_MSK_CLR); - - mask_bits = mask_bits | SPHW_MSI_CLR_INDIR_SET(msix_idx, SIMPLE_INDIR_IDX); - - addr = SPHW_CSR_FUNC_MSI_CLR_WR_ADDR; - sphw_hwif_write_reg(hwif, addr, mask_bits); -} - -void sphw_set_msix_state(void *hwdev, u16 msix_idx, enum sphw_msix_state flag) -{ - struct sphw_hwif *hwif = NULL; - u32 mask_bits; - u32 addr; - u8 int_msk = 1; - - if (!hwdev) - return; - - hwif = ((struct sphw_hwdev *)hwdev)->hwif; - - if (flag) - mask_bits = SPHW_MSI_CLR_INDIR_SET(int_msk, INT_MSK_SET); - else - mask_bits = SPHW_MSI_CLR_INDIR_SET(int_msk, INT_MSK_CLR); - mask_bits = mask_bits | SPHW_MSI_CLR_INDIR_SET(msix_idx, SIMPLE_INDIR_IDX); - - addr = SPHW_CSR_FUNC_MSI_CLR_WR_ADDR; - sphw_hwif_write_reg(hwif, addr, mask_bits); -} - -static void disable_all_msix(struct sphw_hwdev *hwdev) -{ - u16 num_irqs = hwdev->hwif->attr.num_irqs; - u16 i; - - for (i = 0; i < num_irqs; i++) - sphw_set_msix_state(hwdev, i, SPHW_MSIX_DISABLE); -} - -static enum sphw_wait_return check_db_flush_enable_handler(void *priv_data) -{ - struct sphw_hwif *hwif = priv_data; - enum sphw_doorbell_ctrl db_ctrl; - - db_ctrl = sphw_get_doorbell_ctrl_status(hwif); - if (db_ctrl == ENABLE_DOORBELL) - return WAIT_PROCESS_CPL; - - return WAIT_PROCESS_WAITING; -} - -static enum sphw_wait_return check_db_flush_disable_handler(void *priv_data) -{ - struct sphw_hwif *hwif = priv_data; - enum sphw_doorbell_ctrl db_ctrl; - - db_ctrl = sphw_get_doorbell_ctrl_status(hwif); - if (db_ctrl == DISABLE_DOORBELL) - return WAIT_PROCESS_CPL; - - return WAIT_PROCESS_WAITING; -} - -int wait_until_doorbell_flush_states(struct sphw_hwif *hwif, - enum sphw_doorbell_ctrl states) -{ - if (!hwif) - return -EFAULT; - - return sphw_wait_for_timeout(hwif, states == ENABLE_DOORBELL ? - check_db_flush_enable_handler : check_db_flush_disable_handler, - SPHW_WAIT_DOORBELL_AND_OUTBOUND_TIMEOUT, USEC_PER_MSEC); -} - -static enum sphw_wait_return check_db_outbound_enable_handler(void *priv_data) -{ - struct sphw_hwif *hwif = priv_data; - enum sphw_doorbell_ctrl db_ctrl; - enum sphw_outbound_ctrl outbound_ctrl; - - db_ctrl = sphw_get_doorbell_ctrl_status(hwif); - outbound_ctrl = sphw_get_outbound_ctrl_status(hwif); - - if (outbound_ctrl == ENABLE_OUTBOUND && db_ctrl == ENABLE_DOORBELL) - return WAIT_PROCESS_CPL; - - return WAIT_PROCESS_WAITING; -} - -static int wait_until_doorbell_and_outbound_enabled(struct sphw_hwif *hwif) -{ - return sphw_wait_for_timeout(hwif, check_db_outbound_enable_handler, - SPHW_WAIT_DOORBELL_AND_OUTBOUND_TIMEOUT, USEC_PER_MSEC); -} - -/** - * sphw_init_hwif - initialize the hw interface - * @hwif: the hardware interface of a pci function device - * @pdev: the pci device that will be part of the hwif struct - * Return: 0 - success, negative - failure - **/ -int sphw_init_hwif(struct sphw_hwdev *hwdev, void *cfg_reg_base, void *intr_reg_base, - void *mgmt_regs_base, u64 db_base_phy, void *db_base, u64 db_dwqe_len) -{ - struct sphw_hwif *hwif = NULL; - u32 attr4, attr5; - int err; - - hwif = kzalloc(sizeof(*hwif), GFP_KERNEL); - if (!hwif) - return -ENOMEM; - - hwdev->hwif = hwif; - hwif->pdev = hwdev->pcidev_hdl; - - /* if function is VF, mgmt_regs_base will be NULL */ - if (!mgmt_regs_base) - hwif->cfg_regs_base = (u8 *)cfg_reg_base + - SPHW_VF_CFG_REG_OFFSET; - else - hwif->cfg_regs_base = cfg_reg_base; - - hwif->intr_regs_base = intr_reg_base; - hwif->mgmt_regs_base = mgmt_regs_base; - sdk_info(hwdev->dev_hdl, "init intr_regs_base: %p, mgmt_regs_base: %p, db_base: %p, db_dwqe_len: 0x%llx\n", - hwif->intr_regs_base, hwif->mgmt_regs_base, - db_base, db_dwqe_len); - - hwif->db_base_phy = db_base_phy; - hwif->db_base = db_base; - hwif->db_dwqe_len = db_dwqe_len; - err = init_db_area_idx(&hwif->free_db_area, hwif->db_dwqe_len); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to init db area.\n"); - goto init_db_area_err; - } - - err = wait_hwif_ready(hwdev); - if (err) { - sdk_err(hwdev->dev_hdl, "Chip status is not ready\n"); - goto hwif_ready_err; - } - - get_hwif_attr(hwif); - - err = wait_until_doorbell_and_outbound_enabled(hwif); - if (err) { - attr4 = sphw_hwif_read_reg(hwif, SPHW_CSR_FUNC_ATTR4_ADDR); - attr5 = sphw_hwif_read_reg(hwif, SPHW_CSR_FUNC_ATTR5_ADDR); - sdk_err(hwdev->dev_hdl, "Hw doorbell/outbound is disabled, attr4 0x%x attr5 0x%x\n", - attr4, attr5); - goto hwif_ready_err; - } - - if (!SPHW_IS_VF(hwdev)) { - set_ppf(hwif); - - if (SPHW_IS_PPF(hwdev)) - set_mpf(hwif); - - get_mpf(hwif); - } - - disable_all_msix(hwdev); - /* disable mgmt cpu report any event */ - sphw_set_pf_status(hwdev->hwif, SPHW_PF_STATUS_INIT); - - sdk_info(hwdev->dev_hdl, "global_func_idx: %u, func_type: %d, host_id: %u, ppf: %u, mpf: %u\n", - hwif->attr.func_global_idx, hwif->attr.func_type, - hwif->attr.pci_intf_idx, hwif->attr.ppf_idx, - hwif->attr.mpf_idx); - - return 0; - -hwif_ready_err: - free_db_area(&hwif->free_db_area); -init_db_area_err: - kfree(hwif); - - return err; -} - -/** - * sphw_free_hwif - free the hw interface - * @hwif: the hardware interface of a pci function device - * @pdev: the pci device that will be part of the hwif struct - **/ -void sphw_free_hwif(struct sphw_hwdev *hwdev) -{ - free_db_area(&hwdev->hwif->free_db_area); - kfree(hwdev->hwif); -} - -u16 sphw_global_func_id(void *hwdev) -{ - struct sphw_hwif *hwif = NULL; - - if (!hwdev) - return 0; - - hwif = ((struct sphw_hwdev *)hwdev)->hwif; - - return hwif->attr.func_global_idx; -} - -u16 sphw_intr_num(void *hwdev) -{ - struct sphw_hwif *hwif = NULL; - - if (!hwdev) - return 0; - - hwif = ((struct sphw_hwdev *)hwdev)->hwif; - - return hwif->attr.num_irqs; -} - -u8 sphw_pf_id_of_vf(void *hwdev) -{ - struct sphw_hwif *hwif = NULL; - - if (!hwdev) - return 0; - - hwif = ((struct sphw_hwdev *)hwdev)->hwif; - - return hwif->attr.port_to_port_idx; -} - -u8 sphw_pcie_itf_id(void *hwdev) -{ - struct sphw_hwif *hwif = NULL; - - if (!hwdev) - return 0; - - hwif = ((struct sphw_hwdev *)hwdev)->hwif; - - return hwif->attr.pci_intf_idx; -} - -u8 sphw_vf_in_pf(void *hwdev) -{ - struct sphw_hwif *hwif = NULL; - - if (!hwdev) - return 0; - - hwif = ((struct sphw_hwdev *)hwdev)->hwif; - - return hwif->attr.vf_in_pf; -} - -enum func_type sphw_func_type(void *hwdev) -{ - struct sphw_hwif *hwif = NULL; - - if (!hwdev) - return 0; - - hwif = ((struct sphw_hwdev *)hwdev)->hwif; - - return hwif->attr.func_type; -} - -u8 sphw_ceq_num(void *hwdev) -{ - struct sphw_hwif *hwif = NULL; - - if (!hwdev) - return 0; - - hwif = ((struct sphw_hwdev *)hwdev)->hwif; - - return hwif->attr.num_ceqs; -} - -u8 sphw_dma_attr_entry_num(void *hwdev) -{ - struct sphw_hwif *hwif = NULL; - - if (!hwdev) - return 0; - - hwif = ((struct sphw_hwdev *)hwdev)->hwif; - - return hwif->attr.num_dma_attr; -} - -u16 sphw_glb_pf_vf_offset(void *hwdev) -{ - struct sphw_hwif *hwif = NULL; - - if (!hwdev) - return 0; - - hwif = ((struct sphw_hwdev *)hwdev)->hwif; - - return hwif->attr.global_vf_id_of_pf; -} - -u8 sphw_mpf_idx(void *hwdev) -{ - struct sphw_hwif *hwif = NULL; - - if (!hwdev) - return 0; - - hwif = ((struct sphw_hwdev *)hwdev)->hwif; - - return hwif->attr.mpf_idx; -} - -u8 sphw_ppf_idx(void *hwdev) -{ - struct sphw_hwif *hwif = NULL; - - if (!hwdev) - return 0; - - hwif = ((struct sphw_hwdev *)hwdev)->hwif; - - return hwif->attr.ppf_idx; -} - -u8 sphw_host_ppf_idx(void *hwdev, u8 host_id) -{ - struct sphw_hwdev *dev = hwdev; - u32 ppf_elect_port_addr; - u32 val; - - if (!hwdev) - return 0; - - ppf_elect_port_addr = SPHW_CSR_FUNC_PPF_ELECT(host_id); - val = sphw_hwif_read_reg(dev->hwif, ppf_elect_port_addr); - - return sphw_PPF_ELECT_PORT_GET(val, IDX); -} diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hwif.h b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hwif.h deleted file mode 100644 index 9035baf8a66e..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hwif.h +++ /dev/null @@ -1,102 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPHW_HWIF_H -#define SPHW_HWIF_H - -#define SPHW_PCIE_LINK_DOWN 0xFFFFFFFF - -struct sphw_free_db_area { - unsigned long *db_bitmap_array; - u32 db_max_areas; - /* spinlock for allocating doorbell area */ - spinlock_t idx_lock; -}; - -struct sphw_func_attr { - u16 func_global_idx; - u8 port_to_port_idx; - u8 pci_intf_idx; - u8 vf_in_pf; - enum func_type func_type; - - u8 mpf_idx; - - u8 ppf_idx; - - u16 num_irqs; - u8 num_aeqs; - u8 num_ceqs; - - u8 num_dma_attr; - - u16 global_vf_id_of_pf; -}; - -struct sphw_hwif { - u8 __iomem *cfg_regs_base; - u8 __iomem *intr_regs_base; - u8 __iomem *mgmt_regs_base; - u64 db_base_phy; - u64 db_dwqe_len; - u8 __iomem *db_base; - - struct sphw_free_db_area free_db_area; - - struct sphw_func_attr attr; - - void *pdev; -}; - -enum sphw_outbound_ctrl { - ENABLE_OUTBOUND = 0x0, - DISABLE_OUTBOUND = 0x1, -}; - -enum sphw_doorbell_ctrl { - ENABLE_DOORBELL = 0x0, - DISABLE_DOORBELL = 0x1, -}; - -enum sphw_pf_status { - SPHW_PF_STATUS_INIT = 0X0, - SPHW_PF_STATUS_ACTIVE_FLAG = 0x11, - SPHW_PF_STATUS_FLR_START_FLAG = 0x12, - SPHW_PF_STATUS_FLR_FINISH_FLAG = 0x13, -}; - -#define SPHW_HWIF_NUM_AEQS(hwif) ((hwif)->attr.num_aeqs) -#define SPHW_HWIF_NUM_CEQS(hwif) ((hwif)->attr.num_ceqs) -#define SPHW_HWIF_NUM_IRQS(hwif) ((hwif)->attr.num_irqs) -#define SPHW_HWIF_GLOBAL_IDX(hwif) ((hwif)->attr.func_global_idx) -#define SPHW_HWIF_GLOBAL_VF_OFFSET(hwif) ((hwif)->attr.global_vf_id_of_pf) -#define SPHW_HWIF_PPF_IDX(hwif) ((hwif)->attr.ppf_idx) -#define SPHW_PCI_INTF_IDX(hwif) ((hwif)->attr.pci_intf_idx) - -#define SPHW_FUNC_TYPE(dev) ((dev)->hwif->attr.func_type) -#define SPHW_IS_PF(dev) (SPHW_FUNC_TYPE(dev) == TYPE_PF) -#define SPHW_IS_VF(dev) (SPHW_FUNC_TYPE(dev) == TYPE_VF) -#define SPHW_IS_PPF(dev) (SPHW_FUNC_TYPE(dev) == TYPE_PPF) - -u32 sphw_hwif_read_reg(struct sphw_hwif *hwif, u32 reg); - -void sphw_hwif_write_reg(struct sphw_hwif *hwif, u32 reg, u32 val); - -void sphw_set_pf_status(struct sphw_hwif *hwif, enum sphw_pf_status status); - -enum sphw_pf_status sphw_get_pf_status(struct sphw_hwif *hwif); - -void sphw_disable_doorbell(struct sphw_hwif *hwif); - -void sphw_enable_doorbell(struct sphw_hwif *hwif); - -int sphw_init_hwif(struct sphw_hwdev *hwdev, void *cfg_reg_base, void *intr_reg_base, - void *mgmt_regs_base, u64 db_base_phy, void *db_base, u64 db_dwqe_len); - -void sphw_free_hwif(struct sphw_hwdev *hwdev); - -u8 sphw_host_ppf_idx(void *hwdev, u8 host_id); - -u32 sphw_get_heartbeat_status(struct sphw_hwdev *hwdev); - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_mbox.c b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_mbox.c deleted file mode 100644 index 694463ca0a93..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_mbox.c +++ /dev/null @@ -1,1792 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [COMM]" fmt - -#include <linux/pci.h> -#include <linux/delay.h> -#include <linux/types.h> -#include <linux/semaphore.h> -#include <linux/spinlock.h> -#include <linux/workqueue.h> - -#include "sphw_hw.h" -#include "sphw_hwdev.h" -#include "sphw_csr.h" -#include "sphw_hwif.h" -#include "sphw_eqs.h" -#include "sphw_prof_adap.h" -#include "sphw_mbox.h" -#include "sphw_common.h" - -#define SPHW_MBOX_INT_DST_AEQN_SHIFT 10 -#define SPHW_MBOX_INT_SRC_RESP_AEQN_SHIFT 12 -#define SPHW_MBOX_INT_STAT_DMA_SHIFT 14 -/* The size of data to be send (unit of 4 bytes) */ -#define SPHW_MBOX_INT_TX_SIZE_SHIFT 20 -/* SO_RO(strong order, relax order) */ -#define SPHW_MBOX_INT_STAT_DMA_SO_RO_SHIFT 25 -#define SPHW_MBOX_INT_WB_EN_SHIFT 28 - -#define SPHW_MBOX_INT_DST_AEQN_MASK 0x3 -#define SPHW_MBOX_INT_SRC_RESP_AEQN_MASK 0x3 -#define SPHW_MBOX_INT_STAT_DMA_MASK 0x3F -#define SPHW_MBOX_INT_TX_SIZE_MASK 0x1F -#define SPHW_MBOX_INT_STAT_DMA_SO_RO_MASK 0x3 -#define SPHW_MBOX_INT_WB_EN_MASK 0x1 - -#define SPHW_MBOX_INT_SET(val, field) \ - (((val) & SPHW_MBOX_INT_##field##_MASK) << \ - SPHW_MBOX_INT_##field##_SHIFT) - -enum sphw_mbox_tx_status { - TX_NOT_DONE = 1, -}; - -#define SPHW_MBOX_CTRL_TRIGGER_AEQE_SHIFT 0 -/* specifies the issue request for the message data. - * 0 - Tx request is done; - * 1 - Tx request is in process. - */ -#define SPHW_MBOX_CTRL_TX_STATUS_SHIFT 1 -#define SPHW_MBOX_CTRL_DST_FUNC_SHIFT 16 - -#define SPHW_MBOX_CTRL_TRIGGER_AEQE_MASK 0x1 -#define SPHW_MBOX_CTRL_TX_STATUS_MASK 0x1 -#define SPHW_MBOX_CTRL_DST_FUNC_MASK 0x1FFF - -#define SPHW_MBOX_CTRL_SET(val, field) \ - (((val) & SPHW_MBOX_CTRL_##field##_MASK) << \ - SPHW_MBOX_CTRL_##field##_SHIFT) - -#define MBOX_SEGLEN_MASK SPHW_MSG_HEADER_SET(SPHW_MSG_HEADER_SEG_LEN_MASK, SEG_LEN) - -#define MBOX_MSG_POLLING_TIMEOUT 8000 -#define SPHW_MBOX_COMP_TIME 25000U - -#define MBOX_MAX_BUF_SZ 2048U -#define MBOX_HEADER_SZ 8 -#define SPHW_MBOX_DATA_SIZE (MBOX_MAX_BUF_SZ - MBOX_HEADER_SZ) - -/* MBOX size is 64B, 8B for mbox_header, 8B reserved */ -#define MBOX_SEG_LEN 48 -#define MBOX_SEG_LEN_ALIGN 4 -#define MBOX_WB_STATUS_LEN 16UL - -#define SEQ_ID_START_VAL 0 -#define SEQ_ID_MAX_VAL 42 -#define MBOX_LAST_SEG_MAX_LEN (MBOX_MAX_BUF_SZ - \ - SEQ_ID_MAX_VAL * MBOX_SEG_LEN) - -/* mbox write back status is 16B, only first 4B is used */ -#define MBOX_WB_STATUS_ERRCODE_MASK 0xFFFF -#define MBOX_WB_STATUS_MASK 0xFF -#define MBOX_WB_ERROR_CODE_MASK 0xFF00 -#define MBOX_WB_STATUS_FINISHED_SUCCESS 0xFF -#define MBOX_WB_STATUS_FINISHED_WITH_ERR 0xFE -#define MBOX_WB_STATUS_NOT_FINISHED 0x00 - -#define MBOX_STATUS_FINISHED(wb) \ - (((wb) & MBOX_WB_STATUS_MASK) != MBOX_WB_STATUS_NOT_FINISHED) -#define MBOX_STATUS_SUCCESS(wb) \ - (((wb) & MBOX_WB_STATUS_MASK) == MBOX_WB_STATUS_FINISHED_SUCCESS) -#define MBOX_STATUS_ERRCODE(wb) \ - ((wb) & MBOX_WB_ERROR_CODE_MASK) - -#define DST_AEQ_IDX_DEFAULT_VAL 0 -#define SRC_AEQ_IDX_DEFAULT_VAL 0 -#define NO_DMA_ATTRIBUTE_VAL 0 - -#define MBOX_MSG_NO_DATA_LEN 1 - -#define MBOX_BODY_FROM_HDR(header) ((u8 *)(header) + MBOX_HEADER_SZ) -#define MBOX_AREA(hwif) \ - ((hwif)->cfg_regs_base + SPHW_FUNC_CSR_MAILBOX_DATA_OFF) - -#define MBOX_DMA_MSG_QUEUE_DEPTH 32 - -#define MBOX_MQ_CI_OFFSET (SPHW_CFG_REGS_FLAG + SPHW_FUNC_CSR_MAILBOX_DATA_OFF + \ - MBOX_HEADER_SZ + MBOX_SEG_LEN) - -#define MBOX_MQ_SYNC_CI_SHIFT 0 -#define MBOX_MQ_ASYNC_CI_SHIFT 8 - -#define MBOX_MQ_SYNC_CI_MASK 0xFF -#define MBOX_MQ_ASYNC_CI_MASK 0xFF - -#define MBOX_MQ_CI_SET(val, field) \ - (((val) & MBOX_MQ_##field##_CI_MASK) << MBOX_MQ_##field##_CI_SHIFT) -#define MBOX_MQ_CI_GET(val, field) \ - (((val) >> MBOX_MQ_##field##_CI_SHIFT) & MBOX_MQ_##field##_CI_MASK) -#define MBOX_MQ_CI_CLEAR(val, field) \ - ((val) & (~(MBOX_MQ_##field##_CI_MASK << MBOX_MQ_##field##_CI_SHIFT))) - -#define IS_PF_OR_PPF_SRC(hwdev, src_func_idx) \ - ((src_func_idx) < SPHW_MAX_PF_NUM(hwdev)) - -#define MBOX_RESPONSE_ERROR 0x1 -#define MBOX_MSG_ID_MASK 0xF -#define MBOX_MSG_ID(func_to_func) ((func_to_func)->send_msg_id) -#define MBOX_MSG_ID_INC(func_to_func) \ - (MBOX_MSG_ID(func_to_func) = \ - (MBOX_MSG_ID(func_to_func) + 1) & MBOX_MSG_ID_MASK) - -/* max message counter wait to process for one function */ -#define SPHW_MAX_MSG_CNT_TO_PROCESS 10 - -#define MBOX_MSG_CHANNEL_STOP(func_to_func) \ - ((((func_to_func)->lock_channel_en) && \ - test_bit((func_to_func)->cur_msg_channel, \ - &(func_to_func)->channel_stop)) ? true : false) - -enum mbox_ordering_type { - STRONG_ORDER, -}; - -enum mbox_write_back_type { - WRITE_BACK = 1, -}; - -enum mbox_aeq_trig_type { - NOT_TRIGGER, - TRIGGER, -}; - -static int send_mbox_msg(struct sphw_mbox *func_to_func, u8 mod, u16 cmd, - void *msg, u16 msg_len, u16 dst_func, - enum sphw_msg_direction_type direction, - enum sphw_msg_ack_type ack_type, - struct mbox_msg_info *msg_info); - -struct sphw_msg_desc *get_mbox_msg_desc(struct sphw_mbox *func_to_func, - u64 dir, u64 src_func_id); - -/** - * sphw_register_ppf_mbox_cb - register mbox callback for ppf - * @hwdev: the pointer to hw device - * @mod: specific mod that the callback will handle - * @pri_handle specific mod's private data that will be used in callback - * @callback: callback function - * Return: 0 - success, negative - failure - */ -int sphw_register_ppf_mbox_cb(void *hwdev, u8 mod, void *pri_handle, sphw_ppf_mbox_cb callback) -{ - struct sphw_mbox *func_to_func = NULL; - - if (mod >= SPHW_MOD_MAX || !hwdev) - return -EFAULT; - - func_to_func = ((struct sphw_hwdev *)hwdev)->func_to_func; - - func_to_func->ppf_mbox_cb[mod] = callback; - func_to_func->ppf_mbox_data[mod] = pri_handle; - - set_bit(SPHW_PPF_MBOX_CB_REG, &func_to_func->ppf_mbox_cb_state[mod]); - - return 0; -} - -/** - * sphw_register_pf_mbox_cb - register mbox callback for pf - * @hwdev: the pointer to hw device - * @mod: specific mod that the callback will handle - * @pri_handle specific mod's private data that will be used in callback - * @callback: callback function - * Return: 0 - success, negative - failure - */ -int sphw_register_pf_mbox_cb(void *hwdev, u8 mod, void *pri_handle, sphw_pf_mbox_cb callback) -{ - struct sphw_mbox *func_to_func = NULL; - - if (mod >= SPHW_MOD_MAX || !hwdev) - return -EFAULT; - - func_to_func = ((struct sphw_hwdev *)hwdev)->func_to_func; - - func_to_func->pf_mbox_cb[mod] = callback; - func_to_func->pf_mbox_data[mod] = pri_handle; - - set_bit(SPHW_PF_MBOX_CB_REG, &func_to_func->pf_mbox_cb_state[mod]); - - return 0; -} - -/** - * sphw_register_vf_mbox_cb - register mbox callback for vf - * @hwdev: the pointer to hw device - * @mod: specific mod that the callback will handle - * @pri_handle specific mod's private data that will be used in callback - * @callback: callback function - * Return: 0 - success, negative - failure - */ -int sphw_register_vf_mbox_cb(void *hwdev, u8 mod, void *pri_handle, sphw_vf_mbox_cb callback) -{ - struct sphw_mbox *func_to_func = NULL; - - if (mod >= SPHW_MOD_MAX || !hwdev) - return -EFAULT; - - func_to_func = ((struct sphw_hwdev *)hwdev)->func_to_func; - - func_to_func->vf_mbox_cb[mod] = callback; - func_to_func->vf_mbox_data[mod] = pri_handle; - - set_bit(SPHW_VF_MBOX_CB_REG, &func_to_func->vf_mbox_cb_state[mod]); - - return 0; -} - -/** - * sphw_register_ppf_to_pf_mbox_cb - register mbox callback for pf from ppf - * @hwdev: the pointer to hw device - * @mod: specific mod that the callback will handle - * @pri_handle specific mod's private data that will be used in callback - * @callback: callback function - * Return: 0 - success, negative - failure - */ -int sphw_register_ppf_to_pf_mbox_cb(void *hwdev, u8 mod, void *pri_handle, - sphw_pf_recv_from_ppf_mbox_cb callback) -{ - struct sphw_mbox *func_to_func = NULL; - - if (mod >= SPHW_MOD_MAX || !hwdev) - return -EFAULT; - - func_to_func = ((struct sphw_hwdev *)hwdev)->func_to_func; - - func_to_func->pf_recv_ppf_mbox_cb[mod] = callback; - func_to_func->pf_recv_ppf_mbox_data[mod] = pri_handle; - - set_bit(SPHW_PPF_TO_PF_MBOX_CB_REG, - &func_to_func->ppf_to_pf_mbox_cb_state[mod]); - - return 0; -} - -/** - * sphw_unregister_ppf_mbox_cb - unregister the mbox callback for ppf - * @hwdev: the pointer to hw device - * @mod: specific mod that the callback will handle - * Return: - */ -void sphw_unregister_ppf_mbox_cb(void *hwdev, u8 mod) -{ - struct sphw_mbox *func_to_func = NULL; - - if (mod >= SPHW_MOD_MAX || !hwdev) - return; - - func_to_func = ((struct sphw_hwdev *)hwdev)->func_to_func; - - clear_bit(SPHW_PPF_MBOX_CB_REG, - &func_to_func->ppf_mbox_cb_state[mod]); - - while (test_bit(SPHW_PPF_MBOX_CB_RUNNING, - &func_to_func->ppf_mbox_cb_state[mod])) - usleep_range(900, 1000); - - func_to_func->ppf_mbox_data[mod] = NULL; - func_to_func->ppf_mbox_cb[mod] = NULL; -} - -/** - * sphw_unregister_ppf_mbox_cb - unregister the mbox callback for pf - * @hwdev: the pointer to hw device - * @mod: specific mod that the callback will handle - * Return: - */ -void sphw_unregister_pf_mbox_cb(void *hwdev, u8 mod) -{ - struct sphw_mbox *func_to_func = NULL; - - if (mod >= SPHW_MOD_MAX || !hwdev) - return; - - func_to_func = ((struct sphw_hwdev *)hwdev)->func_to_func; - - clear_bit(SPHW_PF_MBOX_CB_REG, &func_to_func->pf_mbox_cb_state[mod]); - - while (test_bit(SPHW_PF_MBOX_CB_RUNNING, - &func_to_func->pf_mbox_cb_state[mod])) - usleep_range(900, 1000); - - func_to_func->pf_mbox_data[mod] = NULL; - func_to_func->pf_mbox_cb[mod] = NULL; -} - -/** - * sphw_unregister_vf_mbox_cb - unregister the mbox callback for vf - * @hwdev: the pointer to hw device - * @mod: specific mod that the callback will handle - * Return: - */ -void sphw_unregister_vf_mbox_cb(void *hwdev, u8 mod) -{ - struct sphw_mbox *func_to_func = NULL; - - if (mod >= SPHW_MOD_MAX || !hwdev) - return; - - func_to_func = ((struct sphw_hwdev *)hwdev)->func_to_func; - - clear_bit(SPHW_VF_MBOX_CB_REG, &func_to_func->vf_mbox_cb_state[mod]); - - while (test_bit(SPHW_VF_MBOX_CB_RUNNING, - &func_to_func->vf_mbox_cb_state[mod])) - usleep_range(900, 1000); - - func_to_func->vf_mbox_data[mod] = NULL; - func_to_func->vf_mbox_cb[mod] = NULL; -} - -/** - * sphw_unregister_ppf_mbox_cb - unregister the mbox callback for pf from ppf - * @hwdev: the pointer to hw device - * @mod: specific mod that the callback will handle - * Return: - */ -void sphw_unregister_ppf_to_pf_mbox_cb(void *hwdev, u8 mod) -{ - struct sphw_mbox *func_to_func = NULL; - - if (mod >= SPHW_MOD_MAX || !hwdev) - return; - - func_to_func = ((struct sphw_hwdev *)hwdev)->func_to_func; - - clear_bit(SPHW_PPF_TO_PF_MBOX_CB_REG, - &func_to_func->ppf_to_pf_mbox_cb_state[mod]); - - while (test_bit(SPHW_PPF_TO_PF_MBOX_CB_RUNNIG, - &func_to_func->ppf_to_pf_mbox_cb_state[mod])) - usleep_range(900, 1000); - - func_to_func->pf_recv_ppf_mbox_data[mod] = NULL; - func_to_func->pf_recv_ppf_mbox_cb[mod] = NULL; -} - -static int recv_vf_mbox_handler(struct sphw_mbox *func_to_func, - struct sphw_recv_mbox *recv_mbox, - void *buf_out, u16 *out_size) -{ - sphw_vf_mbox_cb cb; - int ret; - - if (recv_mbox->mod >= SPHW_MOD_MAX) { - sdk_warn(func_to_func->hwdev->dev_hdl, "Receive illegal mbox message, mod = %hhu\n", - recv_mbox->mod); - return -EINVAL; - } - - set_bit(SPHW_VF_MBOX_CB_RUNNING, &func_to_func->vf_mbox_cb_state[recv_mbox->mod]); - - cb = func_to_func->vf_mbox_cb[recv_mbox->mod]; - if (cb && test_bit(SPHW_VF_MBOX_CB_REG, - &func_to_func->vf_mbox_cb_state[recv_mbox->mod])) { - ret = cb(func_to_func->hwdev, - func_to_func->vf_mbox_data[recv_mbox->mod], - recv_mbox->cmd, recv_mbox->msg, - recv_mbox->msg_len, buf_out, out_size); - } else { - sdk_warn(func_to_func->hwdev->dev_hdl, "VF mbox cb is not registered\n"); - ret = -EINVAL; - } - - clear_bit(SPHW_VF_MBOX_CB_RUNNING, - &func_to_func->vf_mbox_cb_state[recv_mbox->mod]); - - return ret; -} - -static int recv_pf_from_ppf_handler(struct sphw_mbox *func_to_func, - struct sphw_recv_mbox *recv_mbox, - void *buf_out, u16 *out_size) -{ - sphw_pf_recv_from_ppf_mbox_cb cb; - enum sphw_mod_type mod = recv_mbox->mod; - int ret; - - if (mod >= SPHW_MOD_MAX) { - sdk_warn(func_to_func->hwdev->dev_hdl, "Receive illegal mbox message, mod = %d\n", - mod); - return -EINVAL; - } - - set_bit(SPHW_PPF_TO_PF_MBOX_CB_RUNNIG, - &func_to_func->ppf_to_pf_mbox_cb_state[mod]); - - cb = func_to_func->pf_recv_ppf_mbox_cb[mod]; - if (cb && test_bit(SPHW_PPF_TO_PF_MBOX_CB_REG, - &func_to_func->ppf_to_pf_mbox_cb_state[mod])) { - ret = cb(func_to_func->hwdev, - func_to_func->pf_recv_ppf_mbox_data[mod], - recv_mbox->cmd, recv_mbox->msg, recv_mbox->msg_len, - buf_out, out_size); - } else { - sdk_warn(func_to_func->hwdev->dev_hdl, "PF receive ppf mailbox callback is not registered\n"); - ret = -EINVAL; - } - - clear_bit(SPHW_PPF_TO_PF_MBOX_CB_RUNNIG, - &func_to_func->ppf_to_pf_mbox_cb_state[mod]); - - return ret; -} - -static int recv_ppf_mbox_handler(struct sphw_mbox *func_to_func, - struct sphw_recv_mbox *recv_mbox, - u8 pf_id, void *buf_out, u16 *out_size) -{ - sphw_ppf_mbox_cb cb; - u16 vf_id = 0; - int ret; - - if (recv_mbox->mod >= SPHW_MOD_MAX) { - sdk_warn(func_to_func->hwdev->dev_hdl, "Receive illegal mbox message, mod = %hhu\n", - recv_mbox->mod); - return -EINVAL; - } - - set_bit(SPHW_PPF_MBOX_CB_RUNNING, - &func_to_func->ppf_mbox_cb_state[recv_mbox->mod]); - - cb = func_to_func->ppf_mbox_cb[recv_mbox->mod]; - if (cb && test_bit(SPHW_PPF_MBOX_CB_REG, - &func_to_func->ppf_mbox_cb_state[recv_mbox->mod])) { - ret = cb(func_to_func->hwdev, - func_to_func->ppf_mbox_data[recv_mbox->mod], - pf_id, vf_id, recv_mbox->cmd, recv_mbox->msg, - recv_mbox->msg_len, buf_out, out_size); - } else { - sdk_warn(func_to_func->hwdev->dev_hdl, "PPF mbox cb is not registered, mod = %hhu\n", - recv_mbox->mod); - ret = -EINVAL; - } - - clear_bit(SPHW_PPF_MBOX_CB_RUNNING, - &func_to_func->ppf_mbox_cb_state[recv_mbox->mod]); - - return ret; -} - -static int recv_pf_from_vf_mbox_handler(struct sphw_mbox *func_to_func, - struct sphw_recv_mbox *recv_mbox, - u16 src_func_idx, void *buf_out, - u16 *out_size) -{ - sphw_pf_mbox_cb cb; - u16 vf_id = 0; - int ret; - - if (recv_mbox->mod >= SPHW_MOD_MAX) { - sdk_warn(func_to_func->hwdev->dev_hdl, "Receive illegal mbox message, mod = %hhu\n", - recv_mbox->mod); - return -EINVAL; - } - - set_bit(SPHW_PF_MBOX_CB_RUNNING, - &func_to_func->pf_mbox_cb_state[recv_mbox->mod]); - - cb = func_to_func->pf_mbox_cb[recv_mbox->mod]; - if (cb && test_bit(SPHW_PF_MBOX_CB_REG, - &func_to_func->pf_mbox_cb_state[recv_mbox->mod])) { - vf_id = src_func_idx - - sphw_glb_pf_vf_offset(func_to_func->hwdev); - ret = cb(func_to_func->hwdev, - func_to_func->pf_mbox_data[recv_mbox->mod], - vf_id, recv_mbox->cmd, recv_mbox->msg, - recv_mbox->msg_len, buf_out, out_size); - } else { - sdk_warn(func_to_func->hwdev->dev_hdl, "PF mbox mod(0x%x) cb is not registered\n", - recv_mbox->mod); - ret = -EINVAL; - } - - clear_bit(SPHW_PF_MBOX_CB_RUNNING, - &func_to_func->pf_mbox_cb_state[recv_mbox->mod]); - - return ret; -} - -static void response_for_recv_func_mbox(struct sphw_mbox *func_to_func, - struct sphw_recv_mbox *recv_mbox, - int err, u16 out_size, u16 src_func_idx) -{ - struct mbox_msg_info msg_info = {0}; - - msg_info.msg_id = recv_mbox->msg_id; - if (err) - msg_info.status = SPHW_MBOX_PF_SEND_ERR; - - /* if not data need to response, set out_size to 1 */ - if (!out_size || err) - out_size = MBOX_MSG_NO_DATA_LEN; - - send_mbox_msg(func_to_func, recv_mbox->mod, recv_mbox->cmd, - recv_mbox->resp_buff, out_size, src_func_idx, - SPHW_MSG_RESPONSE, SPHW_MSG_NO_ACK, &msg_info); -} - -static void recv_func_mbox_handler(struct sphw_mbox *func_to_func, - struct sphw_recv_mbox *recv_mbox) -{ - struct sphw_hwdev *dev = func_to_func->hwdev; - void *buf_out = recv_mbox->resp_buff; - u16 src_func_idx = recv_mbox->src_func_idx; - u16 out_size = MBOX_MAX_BUF_SZ; - int err = 0; - - if (SPHW_IS_VF(dev)) { - err = recv_vf_mbox_handler(func_to_func, recv_mbox, buf_out, - &out_size); - } else { /* pf/ppf process */ - if (IS_PF_OR_PPF_SRC(dev, src_func_idx)) { - if (SPHW_IS_PPF(dev)) { - err = recv_ppf_mbox_handler(func_to_func, - recv_mbox, - (u8)src_func_idx, - buf_out, &out_size); - if (err) - goto out; - } else { - err = recv_pf_from_ppf_handler(func_to_func, - recv_mbox, - buf_out, - &out_size); - if (err) - goto out; - } - /* The source is neither PF nor PPF, so it is from VF */ - } else { - err = recv_pf_from_vf_mbox_handler(func_to_func, - recv_mbox, - src_func_idx, - buf_out, &out_size); - } - } - -out: - if (recv_mbox->ack_type == SPHW_MSG_ACK) - response_for_recv_func_mbox(func_to_func, recv_mbox, err, - out_size, src_func_idx); -} - -static struct sphw_recv_mbox *alloc_recv_mbox(void) -{ - struct sphw_recv_mbox *recv_msg = NULL; - - recv_msg = kzalloc(sizeof(*recv_msg), GFP_KERNEL); - if (!recv_msg) - return NULL; - - recv_msg->msg = kzalloc(MBOX_MAX_BUF_SZ, GFP_KERNEL); - if (!recv_msg->msg) - goto alloc_msg_err; - - recv_msg->resp_buff = kzalloc(MBOX_MAX_BUF_SZ, GFP_KERNEL); - if (!recv_msg->resp_buff) - goto alloc_resp_bff_err; - - return recv_msg; - -alloc_resp_bff_err: - kfree(recv_msg->msg); - -alloc_msg_err: - kfree(recv_msg); - - return NULL; -} - -static void free_recv_mbox(struct sphw_recv_mbox *recv_msg) -{ - kfree(recv_msg->resp_buff); - kfree(recv_msg->msg); - kfree(recv_msg); -} - -static void recv_func_mbox_work_handler(struct work_struct *work) -{ - struct sphw_mbox_work *mbox_work = - container_of(work, struct sphw_mbox_work, work); - - recv_func_mbox_handler(mbox_work->func_to_func, mbox_work->recv_mbox); - - atomic_dec(&mbox_work->msg_ch->recv_msg_cnt); - - free_recv_mbox(mbox_work->recv_mbox); - kfree(mbox_work); -} - -static void resp_mbox_handler(struct sphw_mbox *func_to_func, - struct sphw_msg_desc *msg_desc) -{ - spin_lock(&func_to_func->mbox_lock); - if (msg_desc->msg_info.msg_id == func_to_func->send_msg_id && - func_to_func->event_flag == EVENT_START) - func_to_func->event_flag = EVENT_SUCCESS; - else - sdk_err(func_to_func->hwdev->dev_hdl, - "Mbox response timeout, current send msg id(0x%x), recv msg id(0x%x), status(0x%x)\n", - func_to_func->send_msg_id, msg_desc->msg_info.msg_id, - msg_desc->msg_info.status); - spin_unlock(&func_to_func->mbox_lock); -} - -static void recv_mbox_msg_handler(struct sphw_mbox *func_to_func, - struct sphw_msg_desc *msg_desc, - u64 mbox_header) -{ - struct sphw_hwdev *hwdev = func_to_func->hwdev; - struct sphw_recv_mbox *recv_msg = NULL; - struct sphw_mbox_work *mbox_work = NULL; - struct sphw_msg_channel *msg_ch = - container_of(msg_desc, struct sphw_msg_channel, recv_msg); - u16 src_func_idx = SPHW_MSG_HEADER_GET(mbox_header, SRC_GLB_FUNC_IDX); - - if (atomic_read(&msg_ch->recv_msg_cnt) > - SPHW_MAX_MSG_CNT_TO_PROCESS) { - sdk_warn(hwdev->dev_hdl, "This function(%u) have %d message wait to process, can't add to work queue\n", - src_func_idx, atomic_read(&msg_ch->recv_msg_cnt)); - return; - } - - recv_msg = alloc_recv_mbox(); - if (!recv_msg) { - sdk_err(hwdev->dev_hdl, "Failed to alloc receive mbox message buffer\n"); - return; - } - recv_msg->msg_len = msg_desc->msg_len; - memcpy(recv_msg->msg, msg_desc->msg, recv_msg->msg_len); - recv_msg->msg_id = msg_desc->msg_info.msg_id; - recv_msg->mod = SPHW_MSG_HEADER_GET(mbox_header, MODULE); - recv_msg->cmd = SPHW_MSG_HEADER_GET(mbox_header, CMD); - recv_msg->ack_type = SPHW_MSG_HEADER_GET(mbox_header, NO_ACK); - recv_msg->src_func_idx = src_func_idx; - - mbox_work = kzalloc(sizeof(*mbox_work), GFP_KERNEL); - if (!mbox_work) { - sdk_err(hwdev->dev_hdl, "Allocate mbox work memory failed.\n"); - free_recv_mbox(recv_msg); - return; - } - - atomic_inc(&msg_ch->recv_msg_cnt); - - mbox_work->func_to_func = func_to_func; - mbox_work->recv_mbox = recv_msg; - mbox_work->msg_ch = msg_ch; - - INIT_WORK(&mbox_work->work, recv_func_mbox_work_handler); - queue_work_on(sphw_get_work_cpu_affinity(hwdev, WORK_TYPE_MBOX), - func_to_func->workq, &mbox_work->work); -} - -static bool check_mbox_segment(struct sphw_mbox *func_to_func, - struct sphw_msg_desc *msg_desc, - u64 mbox_header) -{ - u8 seq_id, seg_len, msg_id, mod; - u16 src_func_idx, cmd; - - seq_id = SPHW_MSG_HEADER_GET(mbox_header, SEQID); - seg_len = SPHW_MSG_HEADER_GET(mbox_header, SEG_LEN); - msg_id = SPHW_MSG_HEADER_GET(mbox_header, MSG_ID); - mod = SPHW_MSG_HEADER_GET(mbox_header, MODULE); - cmd = SPHW_MSG_HEADER_GET(mbox_header, CMD); - src_func_idx = SPHW_MSG_HEADER_GET(mbox_header, SRC_GLB_FUNC_IDX); - - if (seq_id > SEQ_ID_MAX_VAL || seg_len > MBOX_SEG_LEN || - (seq_id == SEQ_ID_MAX_VAL && seg_len > MBOX_LAST_SEG_MAX_LEN)) - goto seg_err; - - if (seq_id == 0) { - msg_desc->seq_id = seq_id; - msg_desc->msg_info.msg_id = msg_id; - msg_desc->mod = mod; - msg_desc->cmd = cmd; - } else { - if (seq_id != msg_desc->seq_id + 1 || - msg_id != msg_desc->msg_info.msg_id || - mod != msg_desc->mod || cmd != msg_desc->cmd) - goto seg_err; - - msg_desc->seq_id = seq_id; - } - - return true; - -seg_err: - sdk_err(func_to_func->hwdev->dev_hdl, - "Mailbox segment check failed, src func id: 0x%x, front seg info: seq id: 0x%x, msg id: 0x%x, mod: 0x%x, cmd: 0x%x\n", - src_func_idx, msg_desc->seq_id, msg_desc->msg_info.msg_id, - msg_desc->mod, msg_desc->cmd); - sdk_err(func_to_func->hwdev->dev_hdl, - "Current seg info: seg len: 0x%x, seq id: 0x%x, msg id: 0x%x, mod: 0x%x, cmd: 0x%x\n", - seg_len, seq_id, msg_id, mod, cmd); - - return false; -} - -static void recv_mbox_handler(struct sphw_mbox *func_to_func, - void *header, struct sphw_msg_desc *msg_desc) -{ - u64 mbox_header = *((u64 *)header); - void *mbox_body = MBOX_BODY_FROM_HDR(header); - u8 seq_id, seg_len; - int pos; - - if (!check_mbox_segment(func_to_func, msg_desc, mbox_header)) { - msg_desc->seq_id = SEQ_ID_MAX_VAL; - return; - } - - seq_id = SPHW_MSG_HEADER_GET(mbox_header, SEQID); - seg_len = SPHW_MSG_HEADER_GET(mbox_header, SEG_LEN); - - pos = seq_id * MBOX_SEG_LEN; - memcpy((u8 *)msg_desc->msg + pos, mbox_body, seg_len); - - if (!SPHW_MSG_HEADER_GET(mbox_header, LAST)) - return; - - msg_desc->msg_len = SPHW_MSG_HEADER_GET(mbox_header, MSG_LEN); - msg_desc->msg_info.status = SPHW_MSG_HEADER_GET(mbox_header, STATUS); - - if (SPHW_MSG_HEADER_GET(mbox_header, DIRECTION) == - SPHW_MSG_RESPONSE) { - resp_mbox_handler(func_to_func, msg_desc); - return; - } - - recv_mbox_msg_handler(func_to_func, msg_desc, mbox_header); -} - -void sphw_mbox_func_aeqe_handler(void *handle, u8 *header, u8 size) -{ - struct sphw_mbox *func_to_func = NULL; - struct sphw_msg_desc *msg_desc = NULL; - u64 mbox_header = *((u64 *)header); - u64 src, dir; - - func_to_func = ((struct sphw_hwdev *)handle)->func_to_func; - - dir = SPHW_MSG_HEADER_GET(mbox_header, DIRECTION); - src = SPHW_MSG_HEADER_GET(mbox_header, SRC_GLB_FUNC_IDX); - - msg_desc = get_mbox_msg_desc(func_to_func, dir, src); - if (!msg_desc) { - sdk_err(func_to_func->hwdev->dev_hdl, - "Mailbox source function id: %u is invalid for current function\n", - (u32)src); - return; - } - - recv_mbox_handler(func_to_func, (u64 *)header, msg_desc); -} - -static int init_mbox_dma_queue(struct sphw_hwdev *hwdev, struct mbox_dma_queue *mq) -{ - u32 size; - - mq->depth = MBOX_DMA_MSG_QUEUE_DEPTH; - mq->prod_idx = 0; - mq->cons_idx = 0; - - size = mq->depth * MBOX_MAX_BUF_SZ; - mq->dma_buff_vaddr = dma_alloc_coherent(hwdev->dev_hdl, size, &mq->dma_buff_paddr, - GFP_KERNEL); - if (!mq->dma_buff_vaddr) { - sdk_err(hwdev->dev_hdl, "Failed to alloc dma_buffer\n"); - return -ENOMEM; - } - - return 0; -} - -static void deinit_mbox_dma_queue(struct sphw_hwdev *hwdev, struct mbox_dma_queue *mq) -{ - dma_free_coherent(hwdev->dev_hdl, mq->depth * MBOX_MAX_BUF_SZ, - mq->dma_buff_vaddr, mq->dma_buff_paddr); -} - -static int sphw_init_mbox_dma_queue(struct sphw_mbox *func_to_func) -{ - u32 val; - int err; - - err = init_mbox_dma_queue(func_to_func->hwdev, &func_to_func->sync_msg_queue); - if (err) - return err; - - err = init_mbox_dma_queue(func_to_func->hwdev, &func_to_func->async_msg_queue); - if (err) { - deinit_mbox_dma_queue(func_to_func->hwdev, &func_to_func->sync_msg_queue); - return err; - } - - val = sphw_hwif_read_reg(func_to_func->hwdev->hwif, MBOX_MQ_CI_OFFSET); - val = MBOX_MQ_CI_CLEAR(val, SYNC); - val = MBOX_MQ_CI_CLEAR(val, ASYNC); - sphw_hwif_write_reg(func_to_func->hwdev->hwif, MBOX_MQ_CI_OFFSET, val); - - return 0; -} - -static void sphw_deinit_mbox_dma_queue(struct sphw_mbox *func_to_func) -{ - deinit_mbox_dma_queue(func_to_func->hwdev, &func_to_func->sync_msg_queue); - deinit_mbox_dma_queue(func_to_func->hwdev, &func_to_func->async_msg_queue); -} - -#define MBOX_DMA_MSG_INIT_XOR_VAL 0x5a5a5a5a -static u32 mbox_dma_msg_xor(u32 *data, u16 msg_len) -{ - u32 xor = MBOX_DMA_MSG_INIT_XOR_VAL; - u16 dw_len = msg_len / sizeof(u32); - u16 i; - - for (i = 0; i < dw_len; i++) - xor ^= data[i]; - - return xor; -} - -#define MQ_ID_MASK(mq, idx) ((idx) & ((mq)->depth - 1)) -#define IS_MSG_QUEUE_FULL(mq) (MQ_ID_MASK(mq, (mq)->prod_idx + 1) == \ - MQ_ID_MASK(mq, (mq)->cons_idx)) - -static int mbox_prepare_dma_entry(struct sphw_mbox *func_to_func, struct mbox_dma_queue *mq, - struct mbox_dma_msg *dma_msg, void *msg, u16 msg_len) -{ - u64 dma_addr, offset; - void *dma_vaddr; - - if (IS_MSG_QUEUE_FULL(mq)) { - sdk_err(func_to_func->hwdev->dev_hdl, "Mbox sync message queue is busy, pi: %u, ci: %u\n", - mq->prod_idx, MQ_ID_MASK(mq, mq->cons_idx)); - return -EBUSY; - } - - /* copy data to DMA buffer */ - offset = mq->prod_idx * MBOX_MAX_BUF_SZ; - dma_vaddr = (u8 *)mq->dma_buff_vaddr + offset; - memcpy(dma_vaddr, msg, msg_len); - dma_addr = mq->dma_buff_paddr + offset; - dma_msg->dma_addr_high = upper_32_bits(dma_addr); - dma_msg->dma_addr_low = lower_32_bits(dma_addr); - dma_msg->msg_len = msg_len; - dma_msg->xor = mbox_dma_msg_xor(dma_vaddr, ALIGN(msg_len, sizeof(u32))); - - mq->prod_idx++; - mq->prod_idx = MQ_ID_MASK(mq, mq->prod_idx); - - return 0; -} - -static int mbox_prepare_dma_msg(struct sphw_mbox *func_to_func, enum sphw_msg_ack_type ack_type, - struct mbox_dma_msg *dma_msg, void *msg, u16 msg_len) -{ - struct mbox_dma_queue *mq = NULL; - u32 val; - - val = sphw_hwif_read_reg(func_to_func->hwdev->hwif, MBOX_MQ_CI_OFFSET); - if (ack_type == SPHW_MSG_ACK) { - mq = &func_to_func->sync_msg_queue; - mq->cons_idx = MBOX_MQ_CI_GET(val, SYNC); - } else { - mq = &func_to_func->async_msg_queue; - mq->cons_idx = MBOX_MQ_CI_GET(val, ASYNC); - } - - return mbox_prepare_dma_entry(func_to_func, mq, dma_msg, msg, msg_len); -} - -static void clear_mbox_status(struct sphw_send_mbox *mbox) -{ - *mbox->wb_status = 0; - - /* clear mailbox write back status */ - wmb(); -} - -static void mbox_copy_header(struct sphw_hwdev *hwdev, - struct sphw_send_mbox *mbox, u64 *header) -{ - u32 *data = (u32 *)header; - u32 i, idx_max = MBOX_HEADER_SZ / sizeof(u32); - - for (i = 0; i < idx_max; i++) - __raw_writel(cpu_to_be32(*(data + i)), mbox->data + i * sizeof(u32)); -} - -static void mbox_copy_send_data(struct sphw_hwdev *hwdev, struct sphw_send_mbox *mbox, void *seg, - u16 seg_len) -{ - u32 *data = seg; - u32 data_len, chk_sz = sizeof(u32); - u32 i, idx_max; - - data_len = seg_len; - idx_max = ALIGN(data_len, chk_sz) / chk_sz; - - for (i = 0; i < idx_max; i++) - __raw_writel(cpu_to_be32(*(data + i)), - mbox->data + MBOX_HEADER_SZ + i * sizeof(u32)); -} - -static void write_mbox_msg_attr(struct sphw_mbox *func_to_func, - u16 dst_func, u16 dst_aeqn, u16 seg_len) -{ - u32 mbox_int, mbox_ctrl; - - /* for VF to PF's message, dest func id will self-learning by HW */ - if (SPHW_IS_VF(func_to_func->hwdev) && - dst_func != SPHW_MGMT_SRC_ID) - dst_func = 0; /* the destination is the VF's PF */ - - mbox_int = SPHW_MBOX_INT_SET(dst_aeqn, DST_AEQN) | - SPHW_MBOX_INT_SET(0, SRC_RESP_AEQN) | - SPHW_MBOX_INT_SET(NO_DMA_ATTRIBUTE_VAL, STAT_DMA) | - SPHW_MBOX_INT_SET(ALIGN(seg_len + MBOX_HEADER_SZ, - MBOX_SEG_LEN_ALIGN) >> 2, TX_SIZE) | - SPHW_MBOX_INT_SET(STRONG_ORDER, STAT_DMA_SO_RO) | - SPHW_MBOX_INT_SET(WRITE_BACK, WB_EN); - - sphw_hwif_write_reg(func_to_func->hwdev->hwif, SPHW_FUNC_CSR_MAILBOX_INT_OFFSET_OFF, - mbox_int); - - wmb(); /* writing the mbox int attributes */ - mbox_ctrl = SPHW_MBOX_CTRL_SET(TX_NOT_DONE, TX_STATUS); - - mbox_ctrl |= SPHW_MBOX_CTRL_SET(NOT_TRIGGER, TRIGGER_AEQE); - - mbox_ctrl |= SPHW_MBOX_CTRL_SET(dst_func, DST_FUNC); - - sphw_hwif_write_reg(func_to_func->hwdev->hwif, - SPHW_FUNC_CSR_MAILBOX_CONTROL_OFF, mbox_ctrl); -} - -void dump_mbox_reg(struct sphw_hwdev *hwdev) -{ - u32 val; - - val = sphw_hwif_read_reg(hwdev->hwif, SPHW_FUNC_CSR_MAILBOX_CONTROL_OFF); - sdk_err(hwdev->dev_hdl, "Mailbox control reg: 0x%x\n", val); - val = sphw_hwif_read_reg(hwdev->hwif, SPHW_FUNC_CSR_MAILBOX_INT_OFFSET_OFF); - sdk_err(hwdev->dev_hdl, "Mailbox interrupt offset: 0x%x\n", val); -} - -static u16 get_mbox_status(struct sphw_send_mbox *mbox) -{ - /* write back is 16B, but only use first 4B */ - u64 wb_val = be64_to_cpu(*mbox->wb_status); - - rmb(); /* verify reading before check */ - - return (u16)(wb_val & MBOX_WB_STATUS_ERRCODE_MASK); -} - -enum sphw_wait_return check_mbox_wb_status(void *priv_data) -{ - struct sphw_mbox *func_to_func = priv_data; - u16 wb_status; - - if (MBOX_MSG_CHANNEL_STOP(func_to_func)) - return WAIT_PROCESS_ERR; - - wb_status = get_mbox_status(&func_to_func->send_mbox); - - return MBOX_STATUS_FINISHED(wb_status) ? - WAIT_PROCESS_CPL : WAIT_PROCESS_WAITING; -} - -static int send_mbox_seg(struct sphw_mbox *func_to_func, u64 header, - u16 dst_func, void *seg, u16 seg_len, void *msg_info) -{ - struct sphw_send_mbox *send_mbox = &func_to_func->send_mbox; - struct sphw_hwdev *hwdev = func_to_func->hwdev; - u8 num_aeqs = hwdev->hwif->attr.num_aeqs; - u16 dst_aeqn, wb_status = 0, errcode; - u16 seq_dir = SPHW_MSG_HEADER_GET(header, DIRECTION); - int err; - - /* mbox to mgmt cpu, hardware don't care dst aeq id*/ - if (num_aeqs > SPHW_MBOX_RSP_MSG_AEQ) - dst_aeqn = (seq_dir == SPHW_MSG_DIRECT_SEND) ? - SPHW_ASYNC_MSG_AEQ : SPHW_MBOX_RSP_MSG_AEQ; - else - dst_aeqn = 0; - - clear_mbox_status(send_mbox); - - mbox_copy_header(hwdev, send_mbox, &header); - - mbox_copy_send_data(hwdev, send_mbox, seg, seg_len); - - write_mbox_msg_attr(func_to_func, dst_func, dst_aeqn, seg_len); - - wmb(); /* writing the mbox msg attributes */ - - err = sphw_wait_for_timeout(func_to_func, check_mbox_wb_status, - MBOX_MSG_POLLING_TIMEOUT, USEC_PER_MSEC); - wb_status = get_mbox_status(send_mbox); - if (err) { - sdk_err(hwdev->dev_hdl, "Send mailbox segment timeout, wb status: 0x%x\n", - wb_status); - dump_mbox_reg(hwdev); - return -ETIMEDOUT; - } - - if (!MBOX_STATUS_SUCCESS(wb_status)) { - sdk_err(hwdev->dev_hdl, "Send mailbox segment to function %u error, wb status: 0x%x\n", - dst_func, wb_status); - errcode = MBOX_STATUS_ERRCODE(wb_status); - return errcode ? errcode : -EFAULT; - } - - return 0; -} - -static int send_mbox_msg(struct sphw_mbox *func_to_func, u8 mod, u16 cmd, - void *msg, u16 msg_len, u16 dst_func, - enum sphw_msg_direction_type direction, - enum sphw_msg_ack_type ack_type, - struct mbox_msg_info *msg_info) -{ - struct sphw_hwdev *hwdev = func_to_func->hwdev; - struct mbox_dma_msg dma_msg = {0}; - enum sphw_data_type data_type = SPHW_DATA_INLINE; - int err = 0; - u32 seq_id = 0; - u16 seg_len = MBOX_SEG_LEN; - u16 rsp_aeq_id, left; - u8 *msg_seg = NULL; - u64 header = 0; - - if (hwdev->hwif->attr.num_aeqs >= 2) - rsp_aeq_id = SPHW_MBOX_RSP_MSG_AEQ; - else - rsp_aeq_id = 0; - - mutex_lock(&func_to_func->msg_send_lock); - - if (IS_DMA_MBX_MSG(dst_func)) { - err = mbox_prepare_dma_msg(func_to_func, ack_type, &dma_msg, msg, msg_len); - if (err) - goto send_err; - - msg = &dma_msg; - msg_len = sizeof(dma_msg); - data_type = SPHW_DATA_DMA; - } - - msg_seg = (u8 *)msg; - left = msg_len; - - header = SPHW_MSG_HEADER_SET(msg_len, MSG_LEN) | - SPHW_MSG_HEADER_SET(mod, MODULE) | - SPHW_MSG_HEADER_SET(seg_len, SEG_LEN) | - SPHW_MSG_HEADER_SET(ack_type, NO_ACK) | - SPHW_MSG_HEADER_SET(data_type, DATA_TYPE) | - SPHW_MSG_HEADER_SET(SEQ_ID_START_VAL, SEQID) | - SPHW_MSG_HEADER_SET(NOT_LAST_SEGMENT, LAST) | - SPHW_MSG_HEADER_SET(direction, DIRECTION) | - SPHW_MSG_HEADER_SET(cmd, CMD) | - /* The vf's offset to it's associated pf */ - SPHW_MSG_HEADER_SET(msg_info->msg_id, MSG_ID) | - SPHW_MSG_HEADER_SET(rsp_aeq_id, AEQ_ID) | - SPHW_MSG_HEADER_SET(SPHW_MSG_FROM_MBOX, SOURCE) | - SPHW_MSG_HEADER_SET(!!msg_info->status, STATUS) | - SPHW_MSG_HEADER_SET(sphw_global_func_id(hwdev), SRC_GLB_FUNC_IDX); - - while (!(SPHW_MSG_HEADER_GET(header, LAST))) { - if (left <= MBOX_SEG_LEN) { - header &= ~MBOX_SEGLEN_MASK; - header |= SPHW_MSG_HEADER_SET(left, SEG_LEN); - header |= SPHW_MSG_HEADER_SET(LAST_SEGMENT, LAST); - - seg_len = left; - } - - err = send_mbox_seg(func_to_func, header, dst_func, msg_seg, - seg_len, msg_info); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to send mbox seg, seq_id=0x%llx\n", - SPHW_MSG_HEADER_GET(header, SEQID)); - goto send_err; - } - - left -= MBOX_SEG_LEN; - msg_seg += MBOX_SEG_LEN; - - seq_id++; - header &= ~(SPHW_MSG_HEADER_SET(SPHW_MSG_HEADER_SEQID_MASK, SEQID)); - header |= SPHW_MSG_HEADER_SET(seq_id, SEQID); - } - -send_err: - mutex_unlock(&func_to_func->msg_send_lock); - - return err; -} - -static void set_mbox_to_func_event(struct sphw_mbox *func_to_func, - enum mbox_event_state event_flag) -{ - spin_lock(&func_to_func->mbox_lock); - func_to_func->event_flag = event_flag; - spin_unlock(&func_to_func->mbox_lock); -} - -static enum sphw_wait_return check_mbox_msg_finish(void *priv_data) -{ - struct sphw_mbox *func_to_func = priv_data; - - if (MBOX_MSG_CHANNEL_STOP(func_to_func)) - return WAIT_PROCESS_ERR; - - return (func_to_func->event_flag == EVENT_SUCCESS) ? - WAIT_PROCESS_CPL : WAIT_PROCESS_WAITING; -} - -static int wait_mbox_msg_completion(struct sphw_mbox *func_to_func, - u32 timeout) -{ - int err; - - timeout = timeout ? timeout : SPHW_MBOX_COMP_TIME; - err = sphw_wait_for_timeout(func_to_func, check_mbox_msg_finish, - timeout, USEC_PER_MSEC); - if (err) { - set_mbox_to_func_event(func_to_func, EVENT_TIMEOUT); - return -ETIMEDOUT; - } - - set_mbox_to_func_event(func_to_func, EVENT_END); - - return 0; -} - -#define TRY_MBOX_LOCK_SLEPP 1000 -static int send_mbox_msg_lock(struct sphw_mbox *func_to_func, u16 channel) -{ - if (!func_to_func->lock_channel_en) { - mutex_lock(&func_to_func->mbox_send_lock); - return 0; - } - - while (!test_bit(channel, &func_to_func->channel_stop)) { - if (mutex_trylock(&func_to_func->mbox_send_lock)) - return 0; - - usleep_range(TRY_MBOX_LOCK_SLEPP - 1, TRY_MBOX_LOCK_SLEPP); - } - - return -EAGAIN; -} - -static void send_mbox_msg_unlock(struct sphw_mbox *func_to_func) -{ - mutex_unlock(&func_to_func->mbox_send_lock); -} - -int sphw_mbox_to_func(struct sphw_mbox *func_to_func, u8 mod, u16 cmd, u16 dst_func, void *buf_in, - u16 in_size, void *buf_out, u16 *out_size, u32 timeout, u16 channel) -{ - /* use mbox_resp to hole data which responsed from other function */ - struct sphw_msg_desc *msg_desc = NULL; - struct mbox_msg_info msg_info = {0}; - int err; - - if (!func_to_func->hwdev->chip_present_flag) - return -EPERM; - - /* expect response message */ - msg_desc = get_mbox_msg_desc(func_to_func, SPHW_MSG_RESPONSE, - dst_func); - if (!msg_desc) - return -EFAULT; - - err = send_mbox_msg_lock(func_to_func, channel); - if (err) - return err; - - func_to_func->cur_msg_channel = channel; - msg_info.msg_id = MBOX_MSG_ID_INC(func_to_func); - - set_mbox_to_func_event(func_to_func, EVENT_START); - - err = send_mbox_msg(func_to_func, mod, cmd, buf_in, in_size, dst_func, - SPHW_MSG_DIRECT_SEND, SPHW_MSG_ACK, &msg_info); - if (err) { - sdk_err(func_to_func->hwdev->dev_hdl, "Send mailbox mod %u, cmd %u failed, msg_id: %u, err: %d\n", - mod, cmd, msg_info.msg_id, err); - set_mbox_to_func_event(func_to_func, EVENT_FAIL); - goto send_err; - } - - if (wait_mbox_msg_completion(func_to_func, timeout)) { - sdk_err(func_to_func->hwdev->dev_hdl, - "Send mbox msg timeout, msg_id: %u\n", msg_info.msg_id); - sphw_dump_aeq_info(func_to_func->hwdev); - err = -ETIMEDOUT; - goto send_err; - } - - if (mod != msg_desc->mod || cmd != msg_desc->cmd) { - sdk_err(func_to_func->hwdev->dev_hdl, - "Invalid response mbox message, mod: 0x%x, cmd: 0x%x, expect mod: 0x%x, cmd: 0x%x\n", - msg_desc->mod, msg_desc->cmd, mod, cmd); - err = -EFAULT; - goto send_err; - } - - if (msg_desc->msg_info.status) { - err = msg_desc->msg_info.status; - goto send_err; - } - - if (buf_out && out_size) { - if (*out_size < msg_desc->msg_len) { - sdk_err(func_to_func->hwdev->dev_hdl, - "Invalid response mbox message length: %u for mod %d cmd %u, should less than: %u\n", - msg_desc->msg_len, mod, cmd, *out_size); - err = -EFAULT; - goto send_err; - } - - if (msg_desc->msg_len) - memcpy(buf_out, msg_desc->msg, msg_desc->msg_len); - - *out_size = msg_desc->msg_len; - } - -send_err: - send_mbox_msg_unlock(func_to_func); - - return err; -} - -static int mbox_func_params_valid(struct sphw_mbox *func_to_func, - void *buf_in, u16 in_size, u16 channel) -{ - if (!buf_in || !in_size) - return -EINVAL; - - if (in_size > SPHW_MBOX_DATA_SIZE) { - sdk_err(func_to_func->hwdev->dev_hdl, - "Mbox msg len %u exceed limit: [1, %u]\n", - in_size, SPHW_MBOX_DATA_SIZE); - return -EINVAL; - } - - if (channel >= SPHW_CHANNEL_MAX) { - sdk_err(func_to_func->hwdev->dev_hdl, - "Invalid channel id: 0x%x\n", channel); - return -EINVAL; - } - - return 0; -} - -int sphw_mbox_to_func_no_ack(struct sphw_hwdev *hwdev, u16 func_idx, u8 mod, u16 cmd, - void *buf_in, u16 in_size, u16 channel) -{ - struct mbox_msg_info msg_info = {0}; - int err = mbox_func_params_valid(hwdev->func_to_func, buf_in, in_size, - channel); - - if (err) - return err; - - err = send_mbox_msg_lock(hwdev->func_to_func, channel); - if (err) - return err; - - err = send_mbox_msg(hwdev->func_to_func, mod, cmd, buf_in, in_size, - func_idx, SPHW_MSG_DIRECT_SEND, - SPHW_MSG_NO_ACK, &msg_info); - if (err) - sdk_err(hwdev->dev_hdl, "Send mailbox no ack failed\n"); - - send_mbox_msg_unlock(hwdev->func_to_func); - - return err; -} - -int sphw_send_mbox_to_mgmt(struct sphw_hwdev *hwdev, u8 mod, u16 cmd, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size, u32 timeout, u16 channel) -{ - struct sphw_mbox *func_to_func = hwdev->func_to_func; - int err = mbox_func_params_valid(func_to_func, buf_in, in_size, channel); - - if (err) - return err; - - return sphw_mbox_to_func(func_to_func, mod, cmd, SPHW_MGMT_SRC_ID, - buf_in, in_size, buf_out, out_size, timeout, channel); -} - -void sphw_response_mbox_to_mgmt(struct sphw_hwdev *hwdev, u8 mod, u16 cmd, - void *buf_in, u16 in_size, u16 msg_id) -{ - struct mbox_msg_info msg_info; - - msg_info.msg_id = (u8)msg_id; - msg_info.status = 0; - - send_mbox_msg(hwdev->func_to_func, mod, cmd, buf_in, in_size, - SPHW_MGMT_SRC_ID, SPHW_MSG_RESPONSE, - SPHW_MSG_NO_ACK, &msg_info); -} - -int sphw_send_mbox_to_mgmt_no_ack(struct sphw_hwdev *hwdev, u8 mod, u16 cmd, - void *buf_in, u16 in_size, u16 channel) -{ - struct sphw_mbox *func_to_func = hwdev->func_to_func; - int err = mbox_func_params_valid(func_to_func, buf_in, in_size, - channel); - - if (err) - return err; - - return sphw_mbox_to_func_no_ack(hwdev, SPHW_MGMT_SRC_ID, mod, cmd, - buf_in, in_size, channel); -} - -int sphw_mbox_ppf_to_host(void *hwdev, u8 mod, u16 cmd, u8 host_id, - void *buf_in, u16 in_size, void *buf_out, - u16 *out_size, u32 timeout, u16 channel) -{ - struct sphw_hwdev *dev = hwdev; - u16 dst_ppf_func; - int err; - - if (!hwdev) - return -EINVAL; - - if (!(dev->chip_present_flag)) - return -EPERM; - - err = mbox_func_params_valid(dev->func_to_func, buf_in, in_size, - channel); - if (err) - return err; - - if (!SPHW_IS_PPF(dev)) { - sdk_err(dev->dev_hdl, "Params error, only ppf support send mbox to ppf. func_type: %d\n", - sphw_func_type(dev)); - return -EINVAL; - } - - if (host_id >= SPHW_MAX_HOST_NUM(dev) || - host_id == SPHW_PCI_INTF_IDX(dev->hwif)) { - sdk_err(dev->dev_hdl, "Params error, host id: %u\n", host_id); - return -EINVAL; - } - - dst_ppf_func = sphw_host_ppf_idx(dev, host_id); - if (dst_ppf_func >= SPHW_MAX_PF_NUM(dev)) { - sdk_err(dev->dev_hdl, "Dest host(%u) have not elect ppf(0x%x).\n", - host_id, dst_ppf_func); - return -EINVAL; - } - - return sphw_mbox_to_func(dev->func_to_func, mod, cmd, dst_ppf_func, buf_in, in_size, - buf_out, out_size, timeout, channel); -} - -int sphw_mbox_to_pf(void *hwdev, u8 mod, u16 cmd, void *buf_in, u16 in_size, void *buf_out, - u16 *out_size, u32 timeout, u16 channel) -{ - struct sphw_hwdev *dev = hwdev; - int err; - - if (!hwdev) - return -EINVAL; - - if (!(dev->chip_present_flag)) - return -EPERM; - - err = mbox_func_params_valid(dev->func_to_func, buf_in, in_size, - channel); - if (err) - return err; - - if (!SPHW_IS_VF(dev)) { - sdk_err(dev->dev_hdl, "Params error, func_type: %d\n", - sphw_func_type(dev)); - return -EINVAL; - } - - return sphw_mbox_to_func(dev->func_to_func, mod, cmd, sphw_pf_id_of_vf(dev), buf_in, - in_size, buf_out, out_size, timeout, channel); -} - -int sphw_mbox_to_vf(void *hwdev, u16 vf_id, u8 mod, u16 cmd, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size, u32 timeout, u16 channel) -{ - struct sphw_mbox *func_to_func = NULL; - int err = 0; - u16 dst_func_idx; - - if (!hwdev) - return -EINVAL; - - func_to_func = ((struct sphw_hwdev *)hwdev)->func_to_func; - err = mbox_func_params_valid(func_to_func, buf_in, in_size, channel); - if (err) - return err; - - if (SPHW_IS_VF((struct sphw_hwdev *)hwdev)) { - sdk_err(((struct sphw_hwdev *)hwdev)->dev_hdl, "Params error, func_type: %d\n", - sphw_func_type(hwdev)); - return -EINVAL; - } - - if (!vf_id) { - sdk_err(((struct sphw_hwdev *)hwdev)->dev_hdl, - "VF id(%u) error!\n", vf_id); - return -EINVAL; - } - - /* vf_offset_to_pf + vf_id is the vf's global function id of vf in - * this pf - */ - dst_func_idx = sphw_glb_pf_vf_offset(hwdev) + vf_id; - - return sphw_mbox_to_func(func_to_func, mod, cmd, dst_func_idx, buf_in, - in_size, buf_out, out_size, timeout, channel); -} - -void sphw_mbox_enable_channel_lock(struct sphw_hwdev *hwdev, bool enable) -{ - hwdev->func_to_func->lock_channel_en = enable; - - sdk_info(hwdev->dev_hdl, "%s mbox channel lock\n", - enable ? "Enable" : "Disable"); -} - -static int alloc_mbox_msg_channel(struct sphw_msg_channel *msg_ch) -{ - msg_ch->resp_msg.msg = kzalloc(MBOX_MAX_BUF_SZ, GFP_KERNEL); - if (!msg_ch->resp_msg.msg) - return -ENOMEM; - - msg_ch->recv_msg.msg = kzalloc(MBOX_MAX_BUF_SZ, GFP_KERNEL); - if (!msg_ch->recv_msg.msg) { - kfree(msg_ch->resp_msg.msg); - return -ENOMEM; - } - - msg_ch->resp_msg.seq_id = SEQ_ID_MAX_VAL; - msg_ch->recv_msg.seq_id = SEQ_ID_MAX_VAL; - atomic_set(&msg_ch->recv_msg_cnt, 0); - - return 0; -} - -static void free_mbox_msg_channel(struct sphw_msg_channel *msg_ch) -{ - kfree(msg_ch->recv_msg.msg); - kfree(msg_ch->resp_msg.msg); -} - -static int init_mgmt_msg_channel(struct sphw_mbox *func_to_func) -{ - int err; - - err = alloc_mbox_msg_channel(&func_to_func->mgmt_msg); - if (err) { - sdk_err(func_to_func->hwdev->dev_hdl, "Failed to alloc mgmt message channel\n"); - return err; - } - - err = sphw_init_mbox_dma_queue(func_to_func); - if (err) { - sdk_err(func_to_func->hwdev->dev_hdl, "Failed to init mbox dma queue\n"); - free_mbox_msg_channel(&func_to_func->mgmt_msg); - } - - return err; -} - -static void deinit_mgmt_msg_channel(struct sphw_mbox *func_to_func) -{ - sphw_deinit_mbox_dma_queue(func_to_func); - free_mbox_msg_channel(&func_to_func->mgmt_msg); -} - -int sphw_mbox_init_host_msg_channel(struct sphw_hwdev *hwdev) -{ - struct sphw_mbox *func_to_func = hwdev->func_to_func; - u8 host_num = SPHW_MAX_HOST_NUM(hwdev); - int i, host_id, err; - - if (host_num == 0) - return 0; - - func_to_func->host_msg = kcalloc(host_num, - sizeof(*func_to_func->host_msg), - GFP_KERNEL); - if (!func_to_func->host_msg) { - sdk_err(func_to_func->hwdev->dev_hdl, "Failed to alloc host message array\n"); - return -ENOMEM; - } - - for (host_id = 0; host_id < host_num; host_id++) { - err = alloc_mbox_msg_channel(&func_to_func->host_msg[host_id]); - if (err) { - sdk_err(func_to_func->hwdev->dev_hdl, - "Failed to alloc host %d message channel\n", - host_id); - goto alloc_msg_ch_err; - } - } - - func_to_func->support_h2h_msg = true; - - return 0; - -alloc_msg_ch_err: - for (i = 0; i < host_id; i++) - free_mbox_msg_channel(&func_to_func->host_msg[i]); - - kfree(func_to_func->host_msg); - func_to_func->host_msg = NULL; - - return -ENOMEM; -} - -static void deinit_host_msg_channel(struct sphw_mbox *func_to_func) -{ - int i; - - if (!func_to_func->host_msg) - return; - - for (i = 0; i < SPHW_MAX_HOST_NUM(func_to_func->hwdev); i++) - free_mbox_msg_channel(&func_to_func->host_msg[i]); - - kfree(func_to_func->host_msg); - func_to_func->host_msg = NULL; -} - -int sphw_init_func_mbox_msg_channel(void *hwdev, u16 num_func) -{ - struct sphw_hwdev *dev = hwdev; - struct sphw_mbox *func_to_func = NULL; - u16 func_id, i; - int err; - - if (!hwdev || !num_func || num_func > SPHW_MAX_FUNCTIONS) - return -EINVAL; - - func_to_func = dev->func_to_func; - if (func_to_func->func_msg) - return (func_to_func->num_func_msg == num_func) ? 0 : -EFAULT; - - func_to_func->func_msg = - kcalloc(num_func, sizeof(*func_to_func->func_msg), GFP_KERNEL); - if (!func_to_func->func_msg) { - sdk_err(func_to_func->hwdev->dev_hdl, "Failed to alloc func message array\n"); - return -ENOMEM; - } - - for (func_id = 0; func_id < num_func; func_id++) { - err = alloc_mbox_msg_channel(&func_to_func->func_msg[func_id]); - if (err) { - sdk_err(func_to_func->hwdev->dev_hdl, - "Failed to alloc func %hu message channel\n", - func_id); - goto alloc_msg_ch_err; - } - } - - func_to_func->num_func_msg = num_func; - - return 0; - -alloc_msg_ch_err: - for (i = 0; i < func_id; i++) - free_mbox_msg_channel(&func_to_func->func_msg[i]); - - kfree(func_to_func->func_msg); - func_to_func->func_msg = NULL; - - return -ENOMEM; -} - -void sphw_deinit_func_mbox_msg_channel(struct sphw_hwdev *hwdev) -{ - struct sphw_mbox *func_to_func = hwdev->func_to_func; - u16 i; - - if (!func_to_func->func_msg) - return; - - for (i = 0; i < func_to_func->num_func_msg; i++) - free_mbox_msg_channel(&func_to_func->func_msg[i]); - - kfree(func_to_func->func_msg); - func_to_func->func_msg = NULL; -} - -struct sphw_msg_desc *get_mbox_msg_desc(struct sphw_mbox *func_to_func, u64 dir, u64 src_func_id) -{ - struct sphw_hwdev *hwdev = func_to_func->hwdev; - struct sphw_msg_channel *msg_ch = NULL; - u16 id; - - if (src_func_id == SPHW_MGMT_SRC_ID) { - msg_ch = &func_to_func->mgmt_msg; - } else if (SPHW_IS_VF(hwdev)) { - /* message from pf */ - msg_ch = func_to_func->func_msg; - if (src_func_id != sphw_pf_id_of_vf(hwdev) || !msg_ch) - return NULL; - } else if (src_func_id > sphw_glb_pf_vf_offset(hwdev)) { - /* message from vf */ - id = (u16)(src_func_id - 1U) - sphw_glb_pf_vf_offset(hwdev); - if (id >= func_to_func->num_func_msg) - return NULL; - - msg_ch = &func_to_func->func_msg[id]; - } else { - /* message from other host's ppf */ - if (!func_to_func->support_h2h_msg) - return NULL; - - for (id = 0; id < SPHW_MAX_HOST_NUM(hwdev); id++) { - if (src_func_id == sphw_host_ppf_idx(hwdev, (u8)id)) - break; - } - - if (id == SPHW_MAX_HOST_NUM(hwdev) || !func_to_func->host_msg) - return NULL; - - msg_ch = &func_to_func->host_msg[id]; - } - - return (dir == SPHW_MSG_DIRECT_SEND) ? - &msg_ch->recv_msg : &msg_ch->resp_msg; -} - -static void prepare_send_mbox(struct sphw_mbox *func_to_func) -{ - struct sphw_send_mbox *send_mbox = &func_to_func->send_mbox; - - send_mbox->data = MBOX_AREA(func_to_func->hwdev->hwif); -} - -static int alloc_mbox_wb_status(struct sphw_mbox *func_to_func) -{ - struct sphw_send_mbox *send_mbox = &func_to_func->send_mbox; - struct sphw_hwdev *hwdev = func_to_func->hwdev; - u32 addr_h, addr_l; - - send_mbox->wb_vaddr = dma_alloc_coherent(hwdev->dev_hdl, MBOX_WB_STATUS_LEN, - &send_mbox->wb_paddr, GFP_KERNEL); - if (!send_mbox->wb_vaddr) - return -ENOMEM; - - send_mbox->wb_status = send_mbox->wb_vaddr; - - addr_h = upper_32_bits(send_mbox->wb_paddr); - addr_l = lower_32_bits(send_mbox->wb_paddr); - - sphw_hwif_write_reg(hwdev->hwif, SPHW_FUNC_CSR_MAILBOX_RESULT_H_OFF, addr_h); - sphw_hwif_write_reg(hwdev->hwif, SPHW_FUNC_CSR_MAILBOX_RESULT_L_OFF, addr_l); - - return 0; -} - -static void free_mbox_wb_status(struct sphw_mbox *func_to_func) -{ - struct sphw_send_mbox *send_mbox = &func_to_func->send_mbox; - struct sphw_hwdev *hwdev = func_to_func->hwdev; - - sphw_hwif_write_reg(hwdev->hwif, SPHW_FUNC_CSR_MAILBOX_RESULT_H_OFF, 0); - sphw_hwif_write_reg(hwdev->hwif, SPHW_FUNC_CSR_MAILBOX_RESULT_L_OFF, 0); - - dma_free_coherent(hwdev->dev_hdl, MBOX_WB_STATUS_LEN, - send_mbox->wb_vaddr, send_mbox->wb_paddr); -} - -int sphw_func_to_func_init(struct sphw_hwdev *hwdev) -{ - struct sphw_mbox *func_to_func; - int err; - - func_to_func = kzalloc(sizeof(*func_to_func), GFP_KERNEL); - if (!func_to_func) - return -ENOMEM; - - hwdev->func_to_func = func_to_func; - func_to_func->hwdev = hwdev; - mutex_init(&func_to_func->mbox_send_lock); - mutex_init(&func_to_func->msg_send_lock); - spin_lock_init(&func_to_func->mbox_lock); - func_to_func->workq = - create_singlethread_workqueue(SPHW_MBOX_WQ_NAME); - if (!func_to_func->workq) { - sdk_err(hwdev->dev_hdl, "Failed to initialize MBOX workqueue\n"); - err = -ENOMEM; - goto create_mbox_workq_err; - } - - err = init_mgmt_msg_channel(func_to_func); - if (err) - goto init_mgmt_msg_ch_err; - - if (SPHW_IS_VF(hwdev)) { - /* VF to PF mbox message channel */ - err = sphw_init_func_mbox_msg_channel(hwdev, 1); - if (err) - goto init_func_msg_ch_err; - } - - err = alloc_mbox_wb_status(func_to_func); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to alloc mbox write back status\n"); - goto alloc_wb_status_err; - } - - prepare_send_mbox(func_to_func); - - return 0; - -alloc_wb_status_err: - if (SPHW_IS_VF(hwdev)) - sphw_deinit_func_mbox_msg_channel(hwdev); - -init_func_msg_ch_err: - deinit_mgmt_msg_channel(func_to_func); - -init_mgmt_msg_ch_err: - destroy_workqueue(func_to_func->workq); - -create_mbox_workq_err: - kfree(func_to_func); - - return err; -} - -void sphw_func_to_func_free(struct sphw_hwdev *hwdev) -{ - struct sphw_mbox *func_to_func = hwdev->func_to_func; - - /* destroy workqueue before free related mbox resources in case of - * illegal resource access - */ - destroy_workqueue(func_to_func->workq); - - free_mbox_wb_status(func_to_func); - if (SPHW_IS_PPF(hwdev)) - deinit_host_msg_channel(func_to_func); - sphw_deinit_func_mbox_msg_channel(hwdev); - deinit_mgmt_msg_channel(func_to_func); - - kfree(func_to_func); -} diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_mbox.h b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_mbox.h deleted file mode 100644 index 9aebee1c088a..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_mbox.h +++ /dev/null @@ -1,271 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPHW_MBOX_H -#define SPHW_MBOX_H - -#include "sphw_crm.h" - -#define SPHW_MBOX_PF_SEND_ERR 0x1 - -#define SPHW_MGMT_SRC_ID 0x1FFF -#define SPHW_MAX_FUNCTIONS 4096 - -/* message header define */ -#define SPHW_MSG_HEADER_SRC_GLB_FUNC_IDX_SHIFT 0 -#define SPHW_MSG_HEADER_STATUS_SHIFT 13 -#define SPHW_MSG_HEADER_SOURCE_SHIFT 15 -#define SPHW_MSG_HEADER_AEQ_ID_SHIFT 16 -#define SPHW_MSG_HEADER_MSG_ID_SHIFT 18 -#define SPHW_MSG_HEADER_CMD_SHIFT 22 - -#define SPHW_MSG_HEADER_MSG_LEN_SHIFT 32 -#define SPHW_MSG_HEADER_MODULE_SHIFT 43 -#define SPHW_MSG_HEADER_SEG_LEN_SHIFT 48 -#define SPHW_MSG_HEADER_NO_ACK_SHIFT 54 -#define SPHW_MSG_HEADER_DATA_TYPE_SHIFT 55 -#define SPHW_MSG_HEADER_SEQID_SHIFT 56 -#define SPHW_MSG_HEADER_LAST_SHIFT 62 -#define SPHW_MSG_HEADER_DIRECTION_SHIFT 63 - -#define SPHW_MSG_HEADER_SRC_GLB_FUNC_IDX_MASK 0x1FFF -#define SPHW_MSG_HEADER_STATUS_MASK 0x1 -#define SPHW_MSG_HEADER_SOURCE_MASK 0x1 -#define SPHW_MSG_HEADER_AEQ_ID_MASK 0x3 -#define SPHW_MSG_HEADER_MSG_ID_MASK 0xF -#define SPHW_MSG_HEADER_CMD_MASK 0x3FF - -#define SPHW_MSG_HEADER_MSG_LEN_MASK 0x7FF -#define SPHW_MSG_HEADER_MODULE_MASK 0x1F -#define SPHW_MSG_HEADER_SEG_LEN_MASK 0x3F -#define SPHW_MSG_HEADER_NO_ACK_MASK 0x1 -#define SPHW_MSG_HEADER_DATA_TYPE_MASK 0x1 -#define SPHW_MSG_HEADER_SEQID_MASK 0x3F -#define SPHW_MSG_HEADER_LAST_MASK 0x1 -#define SPHW_MSG_HEADER_DIRECTION_MASK 0x1 - -#define SPHW_MSG_HEADER_GET(val, field) \ - (((val) >> SPHW_MSG_HEADER_##field##_SHIFT) & \ - SPHW_MSG_HEADER_##field##_MASK) -#define SPHW_MSG_HEADER_SET(val, field) \ - ((u64)(((u64)(val)) & SPHW_MSG_HEADER_##field##_MASK) << \ - SPHW_MSG_HEADER_##field##_SHIFT) - -#define IS_DMA_MBX_MSG(dst_func) ((dst_func) == SPHW_MGMT_SRC_ID) - -enum sphw_msg_direction_type { - SPHW_MSG_DIRECT_SEND = 0, - SPHW_MSG_RESPONSE = 1, -}; - -enum sphw_msg_segment_type { - NOT_LAST_SEGMENT = 0, - LAST_SEGMENT = 1, -}; - -enum sphw_msg_ack_type { - SPHW_MSG_ACK, - SPHW_MSG_NO_ACK, -}; - -enum sphw_data_type { - SPHW_DATA_INLINE = 0, - SPHW_DATA_DMA = 1, -}; - -enum sphw_msg_src_type { - SPHW_MSG_FROM_MGMT = 0, - SPHW_MSG_FROM_MBOX = 1, -}; - -enum sphw_msg_aeq_type { - SPHW_ASYNC_MSG_AEQ = 0, - /* indicate dest func or mgmt cpu which aeq to response mbox message */ - SPHW_MBOX_RSP_MSG_AEQ = 1, - /* indicate mgmt cpu which aeq to response api cmd message */ - SPHW_MGMT_RSP_MSG_AEQ = 2, -}; - -#define SPHW_MBOX_WQ_NAME "sphw_mbox" - -enum sphw_mbox_seg_errcode { - MBOX_ERRCODE_NO_ERRORS = 0, - /* VF send the mailbox data to the wrong destination functions */ - MBOX_ERRCODE_VF_TO_WRONG_FUNC = 0x100, - /* PPF send the mailbox data to the wrong destination functions */ - MBOX_ERRCODE_PPF_TO_WRONG_FUNC = 0x200, - /* PF send the mailbox data to the wrong destination functions */ - MBOX_ERRCODE_PF_TO_WRONG_FUNC = 0x300, - /* The mailbox data size is set to all zero */ - MBOX_ERRCODE_ZERO_DATA_SIZE = 0x400, - /* The sender function attribute has not been learned by hardware */ - MBOX_ERRCODE_UNKNOWN_SRC_FUNC = 0x500, - /* The receiver function attr has not been learned by hardware */ - MBOX_ERRCODE_UNKNOWN_DES_FUNC = 0x600, -}; - -struct mbox_msg_info { - u8 msg_id; - u8 status; /* can only use 1 bit */ -}; - -struct sphw_msg_desc { - void *msg; - u16 msg_len; - u8 seq_id; - u8 mod; - u16 cmd; - struct mbox_msg_info msg_info; -}; - -struct sphw_msg_channel { - struct sphw_msg_desc resp_msg; - struct sphw_msg_desc recv_msg; - - atomic_t recv_msg_cnt; -}; - -/* Receive other functions mbox message */ -struct sphw_recv_mbox { - void *msg; - u16 msg_len; - u8 msg_id; - u8 mod; - u16 cmd; - u16 src_func_idx; - enum sphw_msg_ack_type ack_type; - void *resp_buff; -}; - -struct sphw_send_mbox { - u8 *data; - - u64 *wb_status; /* write back status */ - void *wb_vaddr; - dma_addr_t wb_paddr; -}; - -enum mbox_event_state { - EVENT_START = 0, - EVENT_FAIL, - EVENT_SUCCESS, - EVENT_TIMEOUT, - EVENT_END, -}; - -enum sphw_mbox_cb_state { - SPHW_VF_MBOX_CB_REG = 0, - SPHW_VF_MBOX_CB_RUNNING, - SPHW_PF_MBOX_CB_REG, - SPHW_PF_MBOX_CB_RUNNING, - SPHW_PPF_MBOX_CB_REG, - SPHW_PPF_MBOX_CB_RUNNING, - SPHW_PPF_TO_PF_MBOX_CB_REG, - SPHW_PPF_TO_PF_MBOX_CB_RUNNIG, -}; - -struct mbox_dma_msg { - u32 xor; - u32 dma_addr_high; - u32 dma_addr_low; - u32 msg_len; - u64 rsvd; -}; - -struct mbox_dma_queue { - void *dma_buff_vaddr; - dma_addr_t dma_buff_paddr; - - u16 depth; - u16 prod_idx; - u16 cons_idx; -}; - -struct sphw_mbox { - struct sphw_hwdev *hwdev; - - bool lock_channel_en; - unsigned long channel_stop; - u16 cur_msg_channel; - - /* lock for send mbox message and ack message */ - struct mutex mbox_send_lock; - /* lock for send mbox message */ - struct mutex msg_send_lock; - struct sphw_send_mbox send_mbox; - - struct mbox_dma_queue sync_msg_queue; - struct mbox_dma_queue async_msg_queue; - - struct workqueue_struct *workq; - - struct sphw_msg_channel mgmt_msg; /* driver and MGMT CPU */ - struct sphw_msg_channel *host_msg; /* PPF message between hosts */ - struct sphw_msg_channel *func_msg; /* PF to VF or VF to PF */ - u16 num_func_msg; - bool support_h2h_msg; /* host to host */ - - /* vf receive pf/ppf callback */ - sphw_vf_mbox_cb vf_mbox_cb[SPHW_MOD_MAX]; - void *vf_mbox_data[SPHW_MOD_MAX]; - /* pf/ppf receive vf callback */ - sphw_pf_mbox_cb pf_mbox_cb[SPHW_MOD_MAX]; - void *pf_mbox_data[SPHW_MOD_MAX]; - /* ppf receive pf/ppf callback */ - sphw_ppf_mbox_cb ppf_mbox_cb[SPHW_MOD_MAX]; - void *ppf_mbox_data[SPHW_MOD_MAX]; - /* pf receive ppf callback */ - sphw_pf_recv_from_ppf_mbox_cb pf_recv_ppf_mbox_cb[SPHW_MOD_MAX]; - void *pf_recv_ppf_mbox_data[SPHW_MOD_MAX]; - unsigned long ppf_to_pf_mbox_cb_state[SPHW_MOD_MAX]; - unsigned long ppf_mbox_cb_state[SPHW_MOD_MAX]; - unsigned long pf_mbox_cb_state[SPHW_MOD_MAX]; - unsigned long vf_mbox_cb_state[SPHW_MOD_MAX]; - - u8 send_msg_id; - enum mbox_event_state event_flag; - /* lock for mbox event flag */ - spinlock_t mbox_lock; -}; - -struct sphw_mbox_work { - struct work_struct work; - struct sphw_mbox *func_to_func; - struct sphw_recv_mbox *recv_mbox; - struct sphw_msg_channel *msg_ch; -}; - -struct vf_cmd_check_handle { - u16 cmd; - bool (*check_cmd)(struct sphw_hwdev *hwdev, u16 src_func_idx, - void *buf_in, u16 in_size); -}; - -void sphw_mbox_func_aeqe_handler(void *handle, u8 *header, u8 size); - -int sphw_func_to_func_init(struct sphw_hwdev *hwdev); - -void sphw_func_to_func_free(struct sphw_hwdev *hwdev); - -int sphw_send_mbox_to_mgmt(struct sphw_hwdev *hwdev, u8 mod, u16 cmd, - void *buf_in, u16 in_size, void *buf_out, - u16 *out_size, u32 timeout, u16 channel); - -void sphw_response_mbox_to_mgmt(struct sphw_hwdev *hwdev, u8 mod, u16 cmd, - void *buf_in, u16 in_size, u16 msg_id); - -int sphw_send_mbox_to_mgmt_no_ack(struct sphw_hwdev *hwdev, u8 mod, u16 cmd, - void *buf_in, u16 in_size, u16 channel); -int sphw_mbox_to_func(struct sphw_mbox *func_to_func, u8 mod, u16 cmd, - u16 dst_func, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size, u32 timeout, u16 channel); - -int sphw_mbox_ppf_to_host(void *hwdev, u8 mod, u16 cmd, u8 host_id, - void *buf_in, u16 in_size, void *buf_out, - u16 *out_size, u32 timeout, u16 channel); - -int sphw_mbox_init_host_msg_channel(struct sphw_hwdev *hwdev); - -void sphw_mbox_enable_channel_lock(struct sphw_hwdev *hwdev, bool enable); - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_mgmt.c b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_mgmt.c deleted file mode 100644 index a66f40635963..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_mgmt.c +++ /dev/null @@ -1,895 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [COMM]" fmt - -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/pci.h> -#include <linux/device.h> -#include <linux/spinlock.h> -#include <linux/completion.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/interrupt.h> -#include <linux/semaphore.h> -#include <linux/delay.h> - -#include "sphw_crm.h" -#include "sphw_hw.h" -#include "sphw_common.h" -#include "sphw_comm_cmd.h" -#include "sphw_hwdev.h" -#include "sphw_eqs.h" -#include "sphw_mbox.h" -#include "sphw_api_cmd.h" -#include "sphw_prof_adap.h" -#include "sphw_mgmt.h" -#include "sphw_csr.h" - -#define SPHW_MSG_TO_MGMT_MAX_LEN 2016 - -#define SPHW_API_CHAIN_AEQ_ID 2 -#define MAX_PF_MGMT_BUF_SIZE 2048UL -#define SEGMENT_LEN 48 -#define ASYNC_MSG_FLAG 0x8 -#define MGMT_MSG_MAX_SEQ_ID (ALIGN(SPHW_MSG_TO_MGMT_MAX_LEN, \ - SEGMENT_LEN) / SEGMENT_LEN) - -#define BUF_OUT_DEFAULT_SIZE 1 - -#define MGMT_MSG_SIZE_MIN 20 -#define MGMT_MSG_SIZE_STEP 16 -#define MGMT_MSG_RSVD_FOR_DEV 8 - -#define SYNC_MSG_ID_MASK 0x7 -#define ASYNC_MSG_ID_MASK 0x7 - -#define SYNC_FLAG 0 -#define ASYNC_FLAG 1 - -#define MSG_NO_RESP 0xFFFF - -#define MGMT_MSG_TIMEOUT 20000 /* millisecond */ - -#define SYNC_MSG_ID(pf_to_mgmt) ((pf_to_mgmt)->sync_msg_id) - -#define SYNC_MSG_ID_INC(pf_to_mgmt) (SYNC_MSG_ID(pf_to_mgmt) = \ - (SYNC_MSG_ID(pf_to_mgmt) + 1) & SYNC_MSG_ID_MASK) -#define ASYNC_MSG_ID(pf_to_mgmt) ((pf_to_mgmt)->async_msg_id) - -#define ASYNC_MSG_ID_INC(pf_to_mgmt) (ASYNC_MSG_ID(pf_to_mgmt) = \ - ((ASYNC_MSG_ID(pf_to_mgmt) + 1) & ASYNC_MSG_ID_MASK) | ASYNC_MSG_FLAG) - -static void pf_to_mgmt_send_event_set(struct sphw_msg_pf_to_mgmt *pf_to_mgmt, - int event_flag) -{ - spin_lock(&pf_to_mgmt->sync_event_lock); - pf_to_mgmt->event_flag = event_flag; - spin_unlock(&pf_to_mgmt->sync_event_lock); -} - -/** - * sphw_register_mgmt_msg_cb - register sync msg handler for a module - * @hwdev: the pointer to hw device - * @mod: module in the chip that this handler will handle its sync messages - * @pri_handle: specific mod's private data that will be used in callback - * @callback: the handler for a sync message that will handle messages - **/ -int sphw_register_mgmt_msg_cb(void *hwdev, u8 mod, void *pri_handle, sphw_mgmt_msg_cb callback) -{ - struct sphw_msg_pf_to_mgmt *pf_to_mgmt = NULL; - - if (mod >= SPHW_MOD_HW_MAX || !hwdev) - return -EFAULT; - - pf_to_mgmt = ((struct sphw_hwdev *)hwdev)->pf_to_mgmt; - if (!pf_to_mgmt) - return -EINVAL; - - pf_to_mgmt->recv_mgmt_msg_cb[mod] = callback; - pf_to_mgmt->recv_mgmt_msg_data[mod] = pri_handle; - - set_bit(SPHW_MGMT_MSG_CB_REG, &pf_to_mgmt->mgmt_msg_cb_state[mod]); - - return 0; -} - -/** - * sphw_unregister_mgmt_msg_cb - unregister sync msg handler for a module - * @hwdev: the pointer to hw device - * @mod: module in the chip that this handler will handle its sync messages - **/ -void sphw_unregister_mgmt_msg_cb(void *hwdev, u8 mod) -{ - struct sphw_msg_pf_to_mgmt *pf_to_mgmt = NULL; - - if (!hwdev || mod >= SPHW_MOD_HW_MAX) - return; - - pf_to_mgmt = ((struct sphw_hwdev *)hwdev)->pf_to_mgmt; - if (!pf_to_mgmt) - return; - - clear_bit(SPHW_MGMT_MSG_CB_REG, &pf_to_mgmt->mgmt_msg_cb_state[mod]); - - while (test_bit(SPHW_MGMT_MSG_CB_RUNNING, &pf_to_mgmt->mgmt_msg_cb_state[mod])) - usleep_range(900, 1000); - - pf_to_mgmt->recv_mgmt_msg_cb[mod] = NULL; - pf_to_mgmt->recv_mgmt_msg_data[mod] = NULL; -} - -/** - * mgmt_msg_len - calculate the total message length - * @msg_data_len: the length of the message data - * Return: the total message length - **/ -static u16 mgmt_msg_len(u16 msg_data_len) -{ - /* u64 - the size of the header */ - u16 msg_size; - - msg_size = (u16)(MGMT_MSG_RSVD_FOR_DEV + sizeof(u64) + msg_data_len); - - if (msg_size > MGMT_MSG_SIZE_MIN) - msg_size = MGMT_MSG_SIZE_MIN + - ALIGN((msg_size - MGMT_MSG_SIZE_MIN), - MGMT_MSG_SIZE_STEP); - else - msg_size = MGMT_MSG_SIZE_MIN; - - return msg_size; -} - -/** - * prepare_header - prepare the header of the message - * @pf_to_mgmt: PF to MGMT channel - * @header: pointer of the header to prepare - * @msg_len: the length of the message - * @mod: module in the chip that will get the message - * @direction: the direction of the original message - * @msg_id: message id - **/ -static void prepare_header(struct sphw_msg_pf_to_mgmt *pf_to_mgmt, - u64 *header, u16 msg_len, u8 mod, - enum sphw_msg_ack_type ack_type, - enum sphw_msg_direction_type direction, - enum sphw_mgmt_cmd cmd, u32 msg_id) -{ - struct sphw_hwif *hwif = pf_to_mgmt->hwdev->hwif; - - *header = SPHW_MSG_HEADER_SET(msg_len, MSG_LEN) | - SPHW_MSG_HEADER_SET(mod, MODULE) | - SPHW_MSG_HEADER_SET(msg_len, SEG_LEN) | - SPHW_MSG_HEADER_SET(ack_type, NO_ACK) | - SPHW_MSG_HEADER_SET(SPHW_DATA_INLINE, DATA_TYPE) | - SPHW_MSG_HEADER_SET(0, SEQID) | - SPHW_MSG_HEADER_SET(SPHW_API_CHAIN_AEQ_ID, AEQ_ID) | - SPHW_MSG_HEADER_SET(LAST_SEGMENT, LAST) | - SPHW_MSG_HEADER_SET(direction, DIRECTION) | - SPHW_MSG_HEADER_SET(cmd, CMD) | - SPHW_MSG_HEADER_SET(SPHW_MSG_FROM_MGMT, SOURCE) | - SPHW_MSG_HEADER_SET(hwif->attr.func_global_idx, SRC_GLB_FUNC_IDX) | - SPHW_MSG_HEADER_SET(msg_id, MSG_ID); -} - -/** - * prepare_mgmt_cmd - prepare the mgmt command - * @mgmt_cmd: pointer to the command to prepare - * @header: pointer of the header to prepare - * @msg: the data of the message - * @msg_len: the length of the message - **/ -static void prepare_mgmt_cmd(u8 *mgmt_cmd, u64 *header, const void *msg, - int msg_len) -{ - memset(mgmt_cmd, 0, MGMT_MSG_RSVD_FOR_DEV); - - mgmt_cmd += MGMT_MSG_RSVD_FOR_DEV; - memcpy(mgmt_cmd, header, sizeof(*header)); - - mgmt_cmd += sizeof(*header); - memcpy(mgmt_cmd, msg, msg_len); -} - -/** - * send_msg_to_mgmt_sync - send async message - * @pf_to_mgmt: PF to MGMT channel - * @mod: module in the chip that will get the message - * @cmd: command of the message - * @msg: the msg data - * @msg_len: the msg data length - * @direction: the direction of the original message - * @resp_msg_id: msg id to response for - * Return: 0 - success, negative - failure - **/ -static int send_msg_to_mgmt_sync(struct sphw_msg_pf_to_mgmt *pf_to_mgmt, - u8 mod, u16 cmd, const void *msg, u16 msg_len, - enum sphw_msg_ack_type ack_type, - enum sphw_msg_direction_type direction, - u16 resp_msg_id) -{ - void *mgmt_cmd = pf_to_mgmt->sync_msg_buf; - struct sphw_api_cmd_chain *chain = NULL; - u8 node_id = SPHW_MGMT_CPU_NODE_ID(pf_to_mgmt->hwdev); - u64 header; - u16 cmd_size = mgmt_msg_len(msg_len); - - if (!sphw_get_chip_present_flag(pf_to_mgmt->hwdev)) - return -EFAULT; - - if (direction == SPHW_MSG_RESPONSE) - prepare_header(pf_to_mgmt, &header, msg_len, mod, ack_type, - direction, cmd, resp_msg_id); - else - prepare_header(pf_to_mgmt, &header, msg_len, mod, ack_type, - direction, cmd, SYNC_MSG_ID_INC(pf_to_mgmt)); - chain = pf_to_mgmt->cmd_chain[SPHW_API_CMD_WRITE_TO_MGMT_CPU]; - - if (ack_type == SPHW_MSG_ACK) - pf_to_mgmt_send_event_set(pf_to_mgmt, SEND_EVENT_START); - - prepare_mgmt_cmd((u8 *)mgmt_cmd, &header, msg, msg_len); - - return sphw_api_cmd_write(chain, node_id, mgmt_cmd, cmd_size); -} - -/** - * send_msg_to_mgmt_async - send async message - * @pf_to_mgmt: PF to MGMT channel - * @mod: module in the chip that will get the message - * @cmd: command of the message - * @msg: the data of the message - * @msg_len: the length of the message - * @direction: the direction of the original message - * Return: 0 - success, negative - failure - **/ -static int send_msg_to_mgmt_async(struct sphw_msg_pf_to_mgmt *pf_to_mgmt, - u8 mod, u16 cmd, const void *msg, u16 msg_len, - enum sphw_msg_direction_type direction) -{ - void *mgmt_cmd = pf_to_mgmt->async_msg_buf; - struct sphw_api_cmd_chain *chain = NULL; - u8 node_id = SPHW_MGMT_CPU_NODE_ID(pf_to_mgmt->hwdev); - u64 header; - u16 cmd_size = mgmt_msg_len(msg_len); - - if (!sphw_get_chip_present_flag(pf_to_mgmt->hwdev)) - return -EFAULT; - - prepare_header(pf_to_mgmt, &header, msg_len, mod, SPHW_MSG_NO_ACK, - direction, cmd, ASYNC_MSG_ID(pf_to_mgmt)); - - prepare_mgmt_cmd((u8 *)mgmt_cmd, &header, msg, msg_len); - - chain = pf_to_mgmt->cmd_chain[SPHW_API_CMD_WRITE_ASYNC_TO_MGMT_CPU]; - - return sphw_api_cmd_write(chain, node_id, mgmt_cmd, cmd_size); -} - -static inline void msg_to_mgmt_pre(u8 mod, void *buf_in) -{ - struct sphw_msg_head *msg_head = NULL; - - /* set aeq fix num to 3, need to ensure response aeq id < 3*/ - if (mod == SPHW_MOD_COMM || mod == SPHW_MOD_L2NIC) { - msg_head = buf_in; - - if (msg_head->resp_aeq_num >= SPHW_MAX_AEQS) - msg_head->resp_aeq_num = 0; - } -} - -int sphw_pf_to_mgmt_sync(void *hwdev, u8 mod, u16 cmd, void *buf_in, - u16 in_size, void *buf_out, u16 *out_size, u32 timeout) -{ - struct sphw_msg_pf_to_mgmt *pf_to_mgmt = NULL; - void *dev = ((struct sphw_hwdev *)hwdev)->dev_hdl; - struct sphw_recv_msg *recv_msg = NULL; - struct completion *recv_done = NULL; - ulong timeo; - int err; - ulong ret; - - msg_to_mgmt_pre(mod, buf_in); - - pf_to_mgmt = ((struct sphw_hwdev *)hwdev)->pf_to_mgmt; - - /* Lock the sync_msg_buf */ - down(&pf_to_mgmt->sync_msg_lock); - recv_msg = &pf_to_mgmt->recv_resp_msg_from_mgmt; - recv_done = &recv_msg->recv_done; - - init_completion(recv_done); - - err = send_msg_to_mgmt_sync(pf_to_mgmt, mod, cmd, buf_in, in_size, - SPHW_MSG_ACK, SPHW_MSG_DIRECT_SEND, - MSG_NO_RESP); - if (err) { - sdk_err(dev, "Failed to send sync msg to mgmt, sync_msg_id: %u\n", - pf_to_mgmt->sync_msg_id); - pf_to_mgmt_send_event_set(pf_to_mgmt, SEND_EVENT_FAIL); - goto unlock_sync_msg; - } - - timeo = msecs_to_jiffies(timeout ? timeout : MGMT_MSG_TIMEOUT); - - ret = wait_for_completion_timeout(recv_done, timeo); - if (!ret) { - sdk_err(dev, "Mgmt response sync cmd timeout, sync_msg_id: %u\n", - pf_to_mgmt->sync_msg_id); - sphw_dump_aeq_info((struct sphw_hwdev *)hwdev); - err = -ETIMEDOUT; - pf_to_mgmt_send_event_set(pf_to_mgmt, SEND_EVENT_TIMEOUT); - goto unlock_sync_msg; - } - pf_to_mgmt_send_event_set(pf_to_mgmt, SEND_EVENT_END); - - if (!(((struct sphw_hwdev *)hwdev)->chip_present_flag)) { - up(&pf_to_mgmt->sync_msg_lock); - return -ETIMEDOUT; - } - - if (buf_out && out_size) { - if (*out_size < recv_msg->msg_len) { - sdk_err(dev, "Invalid response message length: %u for mod %d cmd %u from mgmt, should less than: %u\n", - recv_msg->msg_len, mod, cmd, *out_size); - err = -EFAULT; - goto unlock_sync_msg; - } - - if (recv_msg->msg_len) - memcpy(buf_out, recv_msg->msg, recv_msg->msg_len); - - *out_size = recv_msg->msg_len; - } - -unlock_sync_msg: - up(&pf_to_mgmt->sync_msg_lock); - - return err; -} - -int sphw_pf_to_mgmt_async(void *hwdev, u8 mod, u16 cmd, const void *buf_in, u16 in_size) -{ - struct sphw_msg_pf_to_mgmt *pf_to_mgmt; - void *dev = ((struct sphw_hwdev *)hwdev)->dev_hdl; - int err; - - pf_to_mgmt = ((struct sphw_hwdev *)hwdev)->pf_to_mgmt; - - /* Lock the async_msg_buf */ - spin_lock_bh(&pf_to_mgmt->async_msg_lock); - ASYNC_MSG_ID_INC(pf_to_mgmt); - - err = send_msg_to_mgmt_async(pf_to_mgmt, mod, cmd, buf_in, in_size, - SPHW_MSG_DIRECT_SEND); - spin_unlock_bh(&pf_to_mgmt->async_msg_lock); - - if (err) { - sdk_err(dev, "Failed to send async mgmt msg\n"); - return err; - } - - return 0; -} - -int sphw_pf_msg_to_mgmt_sync(void *hwdev, u8 mod, u16 cmd, void *buf_in, - u16 in_size, void *buf_out, u16 *out_size, u32 timeout) -{ - if (!hwdev) - return -EINVAL; - - if (!sphw_get_chip_present_flag(hwdev)) - return -EPERM; - - if (in_size > SPHW_MSG_TO_MGMT_MAX_LEN) - return -EINVAL; - - return sphw_pf_to_mgmt_sync(hwdev, mod, cmd, buf_in, in_size, buf_out, out_size, timeout); -} - -int sphw_msg_to_mgmt_sync(void *hwdev, u8 mod, u16 cmd, void *buf_in, u16 in_size, void *buf_out, - u16 *out_size, u32 timeout, u16 channel) -{ - if (!hwdev) - return -EINVAL; - - if (!sphw_get_chip_present_flag(hwdev)) - return -EPERM; - - return sphw_send_mbox_to_mgmt(hwdev, mod, cmd, buf_in, in_size, - buf_out, out_size, timeout, channel); -} - -int sphw_msg_to_mgmt_no_ack(void *hwdev, u8 mod, u16 cmd, void *buf_in, u16 in_size, u16 channel) -{ - if (!hwdev) - return -EINVAL; - - if (!sphw_get_chip_present_flag(hwdev)) - return -EPERM; - - return sphw_send_mbox_to_mgmt_no_ack(hwdev, mod, cmd, buf_in, in_size, channel); -} - -int sphw_msg_to_mgmt_async(void *hwdev, u8 mod, u16 cmd, void *buf_in, u16 in_size, u16 channel) -{ - return sphw_msg_to_mgmt_api_chain_async(hwdev, mod, cmd, buf_in, in_size); -} - -int sphw_msg_to_mgmt_api_chain_sync(void *hwdev, u8 mod, u16 cmd, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size, u32 timeout) -{ - if (!hwdev) - return -EINVAL; - - if (!sphw_get_chip_present_flag(hwdev)) - return -EPERM; - - return sphw_pf_msg_to_mgmt_sync(hwdev, mod, cmd, buf_in, in_size, - buf_out, out_size, timeout); -} - -int sphw_msg_to_mgmt_api_chain_async(void *hwdev, u8 mod, u16 cmd, const void *buf_in, u16 in_size) -{ - int err; - - if (!hwdev) - return -EINVAL; - - if (sphw_func_type(hwdev) == TYPE_VF) { - err = -EFAULT; - sdk_err(((struct sphw_hwdev *)hwdev)->dev_hdl, - "VF don't support async cmd\n"); - } else { - err = sphw_pf_to_mgmt_async(hwdev, mod, cmd, buf_in, in_size); - } - - return err; -} - -static void send_mgmt_ack(struct sphw_msg_pf_to_mgmt *pf_to_mgmt, - u8 mod, u16 cmd, void *buf_in, u16 in_size, - u16 msg_id) -{ - u16 buf_size; - - if (!in_size) - buf_size = BUF_OUT_DEFAULT_SIZE; - else - buf_size = in_size; - - sphw_response_mbox_to_mgmt(pf_to_mgmt->hwdev, mod, cmd, buf_in, buf_size, msg_id); -} - -static void mgmt_recv_msg_handler(struct sphw_msg_pf_to_mgmt *pf_to_mgmt, - u8 mod, u16 cmd, void *buf_in, u16 in_size, - u16 msg_id, int need_resp) -{ - void *dev = pf_to_mgmt->hwdev->dev_hdl; - void *buf_out = pf_to_mgmt->mgmt_ack_buf; - enum sphw_mod_type tmp_mod = mod; - bool ack_first = false; - u16 out_size = 0; - - memset(buf_out, 0, MAX_PF_MGMT_BUF_SIZE); - - if (mod >= SPHW_MOD_HW_MAX) { - sdk_warn(dev, "Receive illegal message from mgmt cpu, mod = %d\n", - mod); - goto resp; - } - - set_bit(SPHW_MGMT_MSG_CB_RUNNING, &pf_to_mgmt->mgmt_msg_cb_state[tmp_mod]); - - if (!pf_to_mgmt->recv_mgmt_msg_cb[mod] || - !test_bit(SPHW_MGMT_MSG_CB_REG, - &pf_to_mgmt->mgmt_msg_cb_state[tmp_mod])) { - sdk_warn(dev, "Receive mgmt callback is null, mod = %d\n", - mod); - clear_bit(SPHW_MGMT_MSG_CB_RUNNING, &pf_to_mgmt->mgmt_msg_cb_state[tmp_mod]); - goto resp; - } - - pf_to_mgmt->recv_mgmt_msg_cb[tmp_mod](pf_to_mgmt->hwdev, - pf_to_mgmt->recv_mgmt_msg_data[tmp_mod], - cmd, buf_in, in_size, buf_out, &out_size); - - clear_bit(SPHW_MGMT_MSG_CB_RUNNING, &pf_to_mgmt->mgmt_msg_cb_state[tmp_mod]); - -resp: - if (!ack_first && need_resp) - send_mgmt_ack(pf_to_mgmt, mod, cmd, buf_out, out_size, msg_id); -} - -/** - * mgmt_resp_msg_handler - handler for response message from mgmt cpu - * @pf_to_mgmt: PF to MGMT channel - * @recv_msg: received message details - **/ -static void mgmt_resp_msg_handler(struct sphw_msg_pf_to_mgmt *pf_to_mgmt, - struct sphw_recv_msg *recv_msg) -{ - void *dev = pf_to_mgmt->hwdev->dev_hdl; - - /* delete async msg */ - if (recv_msg->msg_id & ASYNC_MSG_FLAG) - return; - - spin_lock(&pf_to_mgmt->sync_event_lock); - if (recv_msg->msg_id == pf_to_mgmt->sync_msg_id && - pf_to_mgmt->event_flag == SEND_EVENT_START) { - pf_to_mgmt->event_flag = SEND_EVENT_SUCCESS; - complete(&recv_msg->recv_done); - } else if (recv_msg->msg_id != pf_to_mgmt->sync_msg_id) { - sdk_err(dev, "Send msg id(0x%x) recv msg id(0x%x) dismatch, event state=%d\n", - pf_to_mgmt->sync_msg_id, recv_msg->msg_id, - pf_to_mgmt->event_flag); - } else { - sdk_err(dev, "Wait timeout, send msg id(0x%x) recv msg id(0x%x), event state=%d!\n", - pf_to_mgmt->sync_msg_id, recv_msg->msg_id, - pf_to_mgmt->event_flag); - } - spin_unlock(&pf_to_mgmt->sync_event_lock); -} - -static void recv_mgmt_msg_work_handler(struct work_struct *work) -{ - struct sphw_mgmt_msg_handle_work *mgmt_work = - container_of(work, struct sphw_mgmt_msg_handle_work, work); - - mgmt_recv_msg_handler(mgmt_work->pf_to_mgmt, mgmt_work->mod, - mgmt_work->cmd, mgmt_work->msg, - mgmt_work->msg_len, mgmt_work->msg_id, - !mgmt_work->async_mgmt_to_pf); - - kfree(mgmt_work->msg); - kfree(mgmt_work); -} - -static bool check_mgmt_seq_id_and_seg_len(struct sphw_recv_msg *recv_msg, - u8 seq_id, u8 seg_len) -{ - if (seq_id > MGMT_MSG_MAX_SEQ_ID || seg_len > SEGMENT_LEN) - return false; - - if (seq_id == 0) { - recv_msg->seq_id = seq_id; - } else { - if (seq_id != recv_msg->seq_id + 1) - return false; - - recv_msg->seq_id = seq_id; - } - - return true; -} - -/** - * recv_mgmt_msg_handler - handler a message from mgmt cpu - * @pf_to_mgmt: PF to MGMT channel - * @header: the header of the message - * @recv_msg: received message details - **/ -static void recv_mgmt_msg_handler(struct sphw_msg_pf_to_mgmt *pf_to_mgmt, - u8 *header, struct sphw_recv_msg *recv_msg) -{ - struct sphw_hwdev *hwdev = pf_to_mgmt->hwdev; - struct sphw_mgmt_msg_handle_work *mgmt_work = NULL; - u64 mbox_header = *((u64 *)header); - void *msg_body = header + sizeof(mbox_header); - u8 seq_id, seq_len; - u32 offset; - u64 dir; - - /* Don't need to get anything from hw when cmd is async */ - dir = SPHW_MSG_HEADER_GET(mbox_header, DIRECTION); - if (dir == SPHW_MSG_RESPONSE && SPHW_MSG_HEADER_GET(mbox_header, MSG_ID) & ASYNC_MSG_FLAG) - return; - - seq_len = SPHW_MSG_HEADER_GET(mbox_header, SEG_LEN); - seq_id = SPHW_MSG_HEADER_GET(mbox_header, SEQID); - - if (!check_mgmt_seq_id_and_seg_len(recv_msg, seq_id, seq_len)) { - sdk_err(hwdev->dev_hdl, - "Mgmt msg sequence id and segment length check fail, front seq_id: 0x%x,current seq_id: 0x%x, seg len: 0x%x\n", - recv_msg->seq_id, seq_id, seq_len); - /* set seq_id to invalid seq_id */ - recv_msg->seq_id = MGMT_MSG_MAX_SEQ_ID; - return; - } - - offset = seq_id * SEGMENT_LEN; - memcpy((u8 *)recv_msg->msg + offset, msg_body, seq_len); - - if (!SPHW_MSG_HEADER_GET(mbox_header, LAST)) - return; - - recv_msg->cmd = SPHW_MSG_HEADER_GET(mbox_header, CMD); - recv_msg->mod = SPHW_MSG_HEADER_GET(mbox_header, MODULE); - recv_msg->async_mgmt_to_pf = SPHW_MSG_HEADER_GET(mbox_header, NO_ACK); - recv_msg->msg_len = SPHW_MSG_HEADER_GET(mbox_header, MSG_LEN); - recv_msg->msg_id = SPHW_MSG_HEADER_GET(mbox_header, MSG_ID); - recv_msg->seq_id = MGMT_MSG_MAX_SEQ_ID; - - if (SPHW_MSG_HEADER_GET(mbox_header, DIRECTION) == SPHW_MSG_RESPONSE) { - mgmt_resp_msg_handler(pf_to_mgmt, recv_msg); - return; - } - - mgmt_work = kzalloc(sizeof(*mgmt_work), GFP_KERNEL); - if (!mgmt_work) { - sdk_err(hwdev->dev_hdl, "Allocate mgmt work memory failed\n"); - return; - } - - if (recv_msg->msg_len) { - mgmt_work->msg = kzalloc(recv_msg->msg_len, GFP_KERNEL); - if (!mgmt_work->msg) { - sdk_err(hwdev->dev_hdl, "Allocate mgmt msg memory failed\n"); - kfree(mgmt_work); - return; - } - } - - mgmt_work->pf_to_mgmt = pf_to_mgmt; - mgmt_work->msg_len = recv_msg->msg_len; - memcpy(mgmt_work->msg, recv_msg->msg, recv_msg->msg_len); - mgmt_work->msg_id = recv_msg->msg_id; - mgmt_work->mod = recv_msg->mod; - mgmt_work->cmd = recv_msg->cmd; - mgmt_work->async_mgmt_to_pf = recv_msg->async_mgmt_to_pf; - - INIT_WORK(&mgmt_work->work, recv_mgmt_msg_work_handler); - queue_work_on(sphw_get_work_cpu_affinity(hwdev, WORK_TYPE_MGMT_MSG), - pf_to_mgmt->workq, &mgmt_work->work); -} - -/** - * sphw_mgmt_msg_aeqe_handler - handler for a mgmt message event - * @handle: PF to MGMT channel - * @header: the header of the message - * @size: unused - **/ -void sphw_mgmt_msg_aeqe_handler(void *hwdev, u8 *header, u8 size) -{ - struct sphw_hwdev *dev = (struct sphw_hwdev *)hwdev; - struct sphw_msg_pf_to_mgmt *pf_to_mgmt = NULL; - struct sphw_recv_msg *recv_msg = NULL; - bool is_send_dir = false; - - if ((SPHW_MSG_HEADER_GET(*(u64 *)header, SOURCE) == - SPHW_MSG_FROM_MBOX)) { - sphw_mbox_func_aeqe_handler(hwdev, header, size); - return; - } - - pf_to_mgmt = dev->pf_to_mgmt; - if (!pf_to_mgmt) - return; - - is_send_dir = (SPHW_MSG_HEADER_GET(*(u64 *)header, DIRECTION) == - SPHW_MSG_DIRECT_SEND) ? true : false; - - recv_msg = is_send_dir ? &pf_to_mgmt->recv_msg_from_mgmt : - &pf_to_mgmt->recv_resp_msg_from_mgmt; - - recv_mgmt_msg_handler(pf_to_mgmt, header, recv_msg); -} - -/** - * alloc_recv_msg - allocate received message memory - * @recv_msg: pointer that will hold the allocated data - * Return: 0 - success, negative - failure - **/ -static int alloc_recv_msg(struct sphw_recv_msg *recv_msg) -{ - recv_msg->seq_id = MGMT_MSG_MAX_SEQ_ID; - - recv_msg->msg = kzalloc(MAX_PF_MGMT_BUF_SIZE, GFP_KERNEL); - if (!recv_msg->msg) - return -ENOMEM; - - return 0; -} - -/** - * free_recv_msg - free received message memory - * @recv_msg: pointer that holds the allocated data - **/ -static void free_recv_msg(struct sphw_recv_msg *recv_msg) -{ - kfree(recv_msg->msg); -} - -/** - * alloc_msg_buf - allocate all the message buffers of PF to MGMT channel - * @pf_to_mgmt: PF to MGMT channel - * Return: 0 - success, negative - failure - **/ -static int alloc_msg_buf(struct sphw_msg_pf_to_mgmt *pf_to_mgmt) -{ - int err; - void *dev = pf_to_mgmt->hwdev->dev_hdl; - - err = alloc_recv_msg(&pf_to_mgmt->recv_msg_from_mgmt); - if (err) { - sdk_err(dev, "Failed to allocate recv msg\n"); - return err; - } - - err = alloc_recv_msg(&pf_to_mgmt->recv_resp_msg_from_mgmt); - if (err) { - sdk_err(dev, "Failed to allocate resp recv msg\n"); - goto alloc_msg_for_resp_err; - } - - pf_to_mgmt->async_msg_buf = kzalloc(MAX_PF_MGMT_BUF_SIZE, GFP_KERNEL); - if (!pf_to_mgmt->async_msg_buf) { - err = -ENOMEM; - goto async_msg_buf_err; - } - - pf_to_mgmt->sync_msg_buf = kzalloc(MAX_PF_MGMT_BUF_SIZE, GFP_KERNEL); - if (!pf_to_mgmt->sync_msg_buf) { - err = -ENOMEM; - goto sync_msg_buf_err; - } - - pf_to_mgmt->mgmt_ack_buf = kzalloc(MAX_PF_MGMT_BUF_SIZE, GFP_KERNEL); - if (!pf_to_mgmt->mgmt_ack_buf) { - err = -ENOMEM; - goto ack_msg_buf_err; - } - - return 0; - -ack_msg_buf_err: - kfree(pf_to_mgmt->sync_msg_buf); - -sync_msg_buf_err: - kfree(pf_to_mgmt->async_msg_buf); - -async_msg_buf_err: - free_recv_msg(&pf_to_mgmt->recv_resp_msg_from_mgmt); - -alloc_msg_for_resp_err: - free_recv_msg(&pf_to_mgmt->recv_msg_from_mgmt); - return err; -} - -/** - * free_msg_buf - free all the message buffers of PF to MGMT channel - * @pf_to_mgmt: PF to MGMT channel - * Return: 0 - success, negative - failure - **/ -static void free_msg_buf(struct sphw_msg_pf_to_mgmt *pf_to_mgmt) -{ - kfree(pf_to_mgmt->mgmt_ack_buf); - kfree(pf_to_mgmt->sync_msg_buf); - kfree(pf_to_mgmt->async_msg_buf); - - free_recv_msg(&pf_to_mgmt->recv_resp_msg_from_mgmt); - free_recv_msg(&pf_to_mgmt->recv_msg_from_mgmt); -} - -/** - * sphw_pf_to_mgmt_init - initialize PF to MGMT channel - * @hwdev: the pointer to hw device - * Return: 0 - success, negative - failure - **/ -int sphw_pf_to_mgmt_init(struct sphw_hwdev *hwdev) -{ - struct sphw_msg_pf_to_mgmt *pf_to_mgmt; - void *dev = hwdev->dev_hdl; - int err; - - pf_to_mgmt = kzalloc(sizeof(*pf_to_mgmt), GFP_KERNEL); - if (!pf_to_mgmt) - return -ENOMEM; - - hwdev->pf_to_mgmt = pf_to_mgmt; - pf_to_mgmt->hwdev = hwdev; - spin_lock_init(&pf_to_mgmt->async_msg_lock); - spin_lock_init(&pf_to_mgmt->sync_event_lock); - sema_init(&pf_to_mgmt->sync_msg_lock, 1); - pf_to_mgmt->workq = create_singlethread_workqueue(SPHW_MGMT_WQ_NAME); - if (!pf_to_mgmt->workq) { - sdk_err(dev, "Failed to initialize MGMT workqueue\n"); - err = -ENOMEM; - goto create_mgmt_workq_err; - } - - err = alloc_msg_buf(pf_to_mgmt); - if (err) { - sdk_err(dev, "Failed to allocate msg buffers\n"); - goto alloc_msg_buf_err; - } - - err = sphw_api_cmd_init(hwdev, pf_to_mgmt->cmd_chain); - if (err) { - sdk_err(dev, "Failed to init the api cmd chains\n"); - goto api_cmd_init_err; - } - - return 0; - -api_cmd_init_err: - free_msg_buf(pf_to_mgmt); - -alloc_msg_buf_err: - destroy_workqueue(pf_to_mgmt->workq); - -create_mgmt_workq_err: - kfree(pf_to_mgmt); - - return err; -} - -/** - * sphw_pf_to_mgmt_free - free PF to MGMT channel - * @hwdev: the pointer to hw device - **/ -void sphw_pf_to_mgmt_free(struct sphw_hwdev *hwdev) -{ - struct sphw_msg_pf_to_mgmt *pf_to_mgmt = hwdev->pf_to_mgmt; - - /* destroy workqueue before free related pf_to_mgmt resources in case of - * illegal resource access - */ - destroy_workqueue(pf_to_mgmt->workq); - sphw_api_cmd_free(pf_to_mgmt->cmd_chain); - - free_msg_buf(pf_to_mgmt); - kfree(pf_to_mgmt); -} - -void sphw_flush_mgmt_workq(void *hwdev) -{ - struct sphw_hwdev *dev = (struct sphw_hwdev *)hwdev; - - flush_workqueue(dev->aeqs->workq); - - if (sphw_func_type(dev) != TYPE_VF) - flush_workqueue(dev->pf_to_mgmt->workq); -} - -int sphw_api_cmd_read_ack(void *hwdev, u8 dest, const void *cmd, u16 size, void *ack, u16 ack_size) -{ - struct sphw_msg_pf_to_mgmt *pf_to_mgmt = NULL; - struct sphw_api_cmd_chain *chain = NULL; - - if (!hwdev || !cmd || (ack_size && !ack)) - return -EINVAL; - - pf_to_mgmt = ((struct sphw_hwdev *)hwdev)->pf_to_mgmt; - chain = pf_to_mgmt->cmd_chain[SPHW_API_CMD_POLL_READ]; - - if (!(((struct sphw_hwdev *)hwdev)->chip_present_flag)) - return -EPERM; - - return sphw_api_cmd_read(chain, dest, cmd, size, ack, ack_size); -} - -/** - * api cmd write or read bypass default use poll, if want to use aeq interrupt, - * please set wb_trigger_aeqe to 1 - **/ -int sphw_api_cmd_write_nack(void *hwdev, u8 dest, const void *cmd, u16 size) -{ - struct sphw_msg_pf_to_mgmt *pf_to_mgmt = NULL; - struct sphw_api_cmd_chain *chain = NULL; - - if (!hwdev || !size || !cmd) - return -EINVAL; - - pf_to_mgmt = ((struct sphw_hwdev *)hwdev)->pf_to_mgmt; - chain = pf_to_mgmt->cmd_chain[SPHW_API_CMD_POLL_WRITE]; - - if (!(((struct sphw_hwdev *)hwdev)->chip_present_flag)) - return -EPERM; - - return sphw_api_cmd_write(chain, dest, cmd, size); -} diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_mgmt.h b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_mgmt.h deleted file mode 100644 index 802336bd5cb1..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_mgmt.h +++ /dev/null @@ -1,106 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPHW_MGMT_H -#define SPHW_MGMT_H - -#define SPHW_MGMT_WQ_NAME "sphw_mgmt" - -struct sphw_recv_msg { - void *msg; - - u16 msg_len; - enum sphw_mod_type mod; - u16 cmd; - u8 seq_id; - u16 msg_id; - int async_mgmt_to_pf; - - struct completion recv_done; -}; - -struct sphw_msg_head { - u8 status; - u8 version; - u8 resp_aeq_num; - u8 rsvd0[5]; -}; - -enum comm_pf_to_mgmt_event_state { - SEND_EVENT_UNINIT = 0, - SEND_EVENT_START, - SEND_EVENT_SUCCESS, - SEND_EVENT_FAIL, - SEND_EVENT_TIMEOUT, - SEND_EVENT_END, -}; - -enum sphw_mgmt_msg_cb_state { - SPHW_MGMT_MSG_CB_REG = 0, - SPHW_MGMT_MSG_CB_RUNNING, -}; - -struct sphw_msg_pf_to_mgmt { - struct sphw_hwdev *hwdev; - - /* Async cmd can not be scheduling */ - spinlock_t async_msg_lock; - struct semaphore sync_msg_lock; - - struct workqueue_struct *workq; - - void *async_msg_buf; - void *sync_msg_buf; - void *mgmt_ack_buf; - - struct sphw_recv_msg recv_msg_from_mgmt; - struct sphw_recv_msg recv_resp_msg_from_mgmt; - - u16 async_msg_id; - u16 sync_msg_id; - struct sphw_api_cmd_chain *cmd_chain[SPHW_API_CMD_MAX]; - - sphw_mgmt_msg_cb recv_mgmt_msg_cb[SPHW_MOD_HW_MAX]; - void *recv_mgmt_msg_data[SPHW_MOD_HW_MAX]; - unsigned long mgmt_msg_cb_state[SPHW_MOD_HW_MAX]; - - void *async_msg_cb_data[SPHW_MOD_HW_MAX]; - - /* lock when sending msg */ - spinlock_t sync_event_lock; - enum comm_pf_to_mgmt_event_state event_flag; -}; - -struct sphw_mgmt_msg_handle_work { - struct work_struct work; - struct sphw_msg_pf_to_mgmt *pf_to_mgmt; - - void *msg; - u16 msg_len; - - enum sphw_mod_type mod; - u16 cmd; - u16 msg_id; - - int async_mgmt_to_pf; -}; - -void sphw_mgmt_msg_aeqe_handler(void *handle, u8 *header, u8 size); - -int sphw_pf_to_mgmt_init(struct sphw_hwdev *hwdev); - -void sphw_pf_to_mgmt_free(struct sphw_hwdev *hwdev); - -int sphw_pf_to_mgmt_sync(void *hwdev, u8 mod, u16 cmd, void *buf_in, - u16 in_size, void *buf_out, u16 *out_size, u32 timeout); -int sphw_pf_to_mgmt_async(void *hwdev, u8 mod, u16 cmd, const void *buf_in, u16 in_size); - -int sphw_pf_msg_to_mgmt_sync(void *hwdev, u8 mod, u16 cmd, void *buf_in, - u16 in_size, void *buf_out, u16 *out_size, u32 timeout); - -int sphw_api_cmd_read_ack(void *hwdev, u8 dest, const void *cmd, u16 size, - void *ack, u16 ack_size); - -int sphw_api_cmd_write_nack(void *hwdev, u8 dest, const void *cmd, u16 size); - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_mgmt_msg_base.h b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_mgmt_msg_base.h deleted file mode 100644 index 13f726895f58..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_mgmt_msg_base.h +++ /dev/null @@ -1,19 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPHW_MGMT_MSG_BASE_H -#define SPHW_MGMT_MSG_BASE_H - -#define MGMT_MSG_CMD_OP_SET 1 -#define MGMT_MSG_CMD_OP_GET 0 - -#define MGMT_MSG_CMD_OP_START 1 -#define MGMT_MSG_CMD_OP_STOP 0 - -struct mgmt_msg_head { - u8 status; - u8 version; - u8 rsvd0[6]; -}; - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_mt.h b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_mt.h deleted file mode 100644 index d7fb58054202..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_mt.h +++ /dev/null @@ -1,533 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPHW_MT_H -#define SPHW_MT_H - -#define NICTOOL_CMD_TYPE 0x18 - -struct api_cmd_rd { - u32 pf_id; - u8 dest; - u8 *cmd; - u16 size; - void *ack; - u16 ack_size; -}; - -struct api_cmd_wr { - u32 pf_id; - u8 dest; - u8 *cmd; - u16 size; -}; - -struct pf_dev_info { - u64 bar0_size; - u8 bus; - u8 slot; - u8 func; - u64 phy_addr; -}; - -/* Indicates the maximum number of interrupts that can be recorded. - * Subsequent interrupts are not recorded in FFM. - */ -#define FFM_RECORD_NUM_MAX 64 - -struct ffm_intr_info { - u8 node_id; - /* error level of the interrupt source */ - u8 err_level; - /* Classification by interrupt source properties */ - u16 err_type; - u32 err_csr_addr; - u32 err_csr_value; -}; - -struct ffm_intr_tm_info { - struct ffm_intr_info intr_info; - u8 times; - u8 sec; - u8 min; - u8 hour; - u8 mday; - u8 mon; - u16 year; -}; - -struct ffm_record_info { - u32 ffm_num; - u32 last_err_csr_addr; - u32 last_err_csr_value; - struct ffm_intr_tm_info ffm[FFM_RECORD_NUM_MAX]; -}; - -struct dbgtool_k_glb_info { - struct semaphore dbgtool_sem; - struct ffm_record_info *ffm; -}; - -struct msg_2_up { - u8 pf_id; - u8 mod; - u8 cmd; - void *buf_in; - u16 in_size; - void *buf_out; - u16 *out_size; -}; - -struct dbgtool_param { - union { - struct api_cmd_rd api_rd; - struct api_cmd_wr api_wr; - struct pf_dev_info *dev_info; - struct ffm_record_info *ffm_rd; - struct msg_2_up msg2up; - } param; - char chip_name[16]; -}; - -/* dbgtool command type */ -/* You can add commands as required. The dbgtool command can be - * used to invoke all interfaces of the kernel-mode x86 driver. - */ -enum dbgtool_cmd { - DBGTOOL_CMD_API_RD = 0, - DBGTOOL_CMD_API_WR, - DBGTOOL_CMD_FFM_RD, - DBGTOOL_CMD_FFM_CLR, - DBGTOOL_CMD_PF_DEV_INFO_GET, - DBGTOOL_CMD_MSG_2_UP, - DBGTOOL_CMD_FREE_MEM, - DBGTOOL_CMD_NUM -}; - -#define PF_MAX_SIZE 16 -#define BUSINFO_LEN 32 -#define SELF_TEST_BAR_ADDR_OFFSET 0x883c - -enum module_name { - SEND_TO_NPU = 1, - SEND_TO_MPU, - SEND_TO_SM, - - SEND_TO_HW_DRIVER, - SEND_TO_NIC_DRIVER, - SEND_TO_OVS_DRIVER, - SEND_TO_ROCE_DRIVER, - SEND_TO_TOE_DRIVER, - SEND_TO_IWAP_DRIVER, - SEND_TO_FC_DRIVER, - SEND_FCOE_DRIVER, -}; - -enum driver_cmd_type { - TX_INFO = 1, - Q_NUM, - TX_WQE_INFO, - TX_MAPPING, - RX_INFO, - RX_WQE_INFO, - RX_CQE_INFO, - UPRINT_FUNC_EN, - UPRINT_FUNC_RESET, - UPRINT_SET_PATH, - UPRINT_GET_STATISTICS, - FUNC_TYPE, - GET_FUNC_IDX, - GET_INTER_NUM, - CLOSE_TX_STREAM, - GET_DRV_VERSION, - CLEAR_FUNC_STASTIC, - GET_HW_STATS, - CLEAR_HW_STATS, - GET_SELF_TEST_RES, - GET_CHIP_FAULT_STATS, - NIC_RSVD1, - NIC_RSVD2, - NIC_RSVD3, - GET_CHIP_ID, - GET_SINGLE_CARD_INFO, - GET_FIRMWARE_ACTIVE_STATUS, - ROCE_DFX_FUNC, - GET_DEVICE_ID, - GET_PF_DEV_INFO, - CMD_FREE_MEM, - GET_LOOPBACK_MODE = 32, - SET_LOOPBACK_MODE, - SET_LINK_MODE, - SET_PF_BW_LIMIT, - GET_PF_BW_LIMIT, - ROCE_CMD, - GET_POLL_WEIGHT, - SET_POLL_WEIGHT, - GET_HOMOLOGUE, - SET_HOMOLOGUE, - GET_SSET_COUNT, - GET_SSET_ITEMS, - IS_DRV_IN_VM, - LRO_ADPT_MGMT, - SET_INTER_COAL_PARAM, - GET_INTER_COAL_PARAM, - GET_CHIP_INFO, - GET_NIC_STATS_LEN, - GET_NIC_STATS_STRING, - GET_NIC_STATS_INFO, - GET_PF_ID, - NIC_RSVD4, - NIC_RSVD5, - DCB_QOS_INFO, - DCB_PFC_STATE, - DCB_ETS_STATE, - DCB_STATE, - NIC_RSVD6, - NIC_RSVD7, - GET_ULD_DEV_NAME, - - RSS_CFG = 0x40, - RSS_INDIR, - PORT_ID, - - GET_FUNC_CAP = 0x50, - - GET_WIN_STAT = 0x60, - WIN_CSR_READ = 0x61, - WIN_CSR_WRITE = 0x62, - WIN_API_CMD_RD = 0x63, - - VM_COMPAT_TEST = 0xFF -}; - -enum api_chain_cmd_type { - API_CSR_READ, - API_CSR_WRITE -}; - -enum sm_cmd_type { - SM_CTR_RD32 = 1, - SM_CTR_RD64_PAIR, - SM_CTR_RD64, - SM_CTR_RD32_CLEAR, - SM_CTR_RD64_PAIR_CLEAR, - SM_CTR_RD64_CLEAR -}; - -struct cqm_stats { - atomic_t cqm_cmd_alloc_cnt; - atomic_t cqm_cmd_free_cnt; - atomic_t cqm_send_cmd_box_cnt; - atomic_t cqm_send_cmd_imm_cnt; - atomic_t cqm_db_addr_alloc_cnt; - atomic_t cqm_db_addr_free_cnt; - atomic_t cqm_fc_srq_create_cnt; - atomic_t cqm_srq_create_cnt; - atomic_t cqm_rq_create_cnt; - atomic_t cqm_qpc_mpt_create_cnt; - atomic_t cqm_nonrdma_queue_create_cnt; - atomic_t cqm_rdma_queue_create_cnt; - atomic_t cqm_rdma_table_create_cnt; - atomic_t cqm_qpc_mpt_delete_cnt; - atomic_t cqm_nonrdma_queue_delete_cnt; - atomic_t cqm_rdma_queue_delete_cnt; - atomic_t cqm_rdma_table_delete_cnt; - atomic_t cqm_func_timer_clear_cnt; - atomic_t cqm_func_hash_buf_clear_cnt; - atomic_t cqm_scq_callback_cnt; - atomic_t cqm_ecq_callback_cnt; - atomic_t cqm_nocq_callback_cnt; - atomic_t cqm_aeq_callback_cnt[112]; -}; - -enum sphw_fault_err_level { - FAULT_LEVEL_FATAL, - FAULT_LEVEL_SERIOUS_RESET, - FAULT_LEVEL_HOST, - FAULT_LEVEL_SERIOUS_FLR, - FAULT_LEVEL_GENERAL, - FAULT_LEVEL_SUGGESTION, - FAULT_LEVEL_MAX, -}; - -struct link_event_stats { - atomic_t link_down_stats; - atomic_t link_up_stats; -}; - -enum sphw_fault_type { - FAULT_TYPE_CHIP, - FAULT_TYPE_UCODE, - FAULT_TYPE_MEM_RD_TIMEOUT, - FAULT_TYPE_MEM_WR_TIMEOUT, - FAULT_TYPE_REG_RD_TIMEOUT, - FAULT_TYPE_REG_WR_TIMEOUT, - FAULT_TYPE_PHY_FAULT, - FAULT_TYPE_MAX, -}; - -struct fault_event_stats { - atomic_t chip_fault_stats[22][FAULT_LEVEL_MAX]; - atomic_t fault_type_stat[FAULT_TYPE_MAX]; - atomic_t pcie_fault_stats; -}; - -struct sphw_hw_stats { - atomic_t heart_lost_stats; - struct cqm_stats cqm_stats; - struct link_event_stats link_event_stats; - struct fault_event_stats fault_event_stats; -}; - -#ifndef IFNAMSIZ -#define IFNAMSIZ 16 -#endif - -struct pf_info { - char name[IFNAMSIZ]; - char bus_info[BUSINFO_LEN]; - u32 pf_type; -}; - -struct card_info { - struct pf_info pf[PF_MAX_SIZE]; - u32 pf_num; -}; - -struct spnic_nic_loop_mode { - u32 loop_mode; - u32 loop_ctrl; -}; - -enum spnic_show_set { - SHOW_SSET_IO_STATS = 1, -}; - -#define SPNIC_SHOW_ITEM_LEN 32 -struct spnic_show_item { - char name[SPNIC_SHOW_ITEM_LEN]; - u8 hexadecimal; /* 0: decimal , 1: Hexadecimal */ - u8 rsvd[7]; - u64 value; -}; - -#define SPHW_CHIP_FAULT_SIZE (110 * 1024) -#define MAX_DRV_BUF_SIZE 4096 - -struct nic_cmd_chip_fault_stats { - u32 offset; - u8 chip_fault_stats[MAX_DRV_BUF_SIZE]; -}; - -#define NIC_TOOL_MAGIC 'x' - -#define CARD_MAX_SIZE 16 -struct nic_card_id { - u32 id[CARD_MAX_SIZE]; - u32 num; -}; - -struct func_pdev_info { - u64 bar0_phy_addr; - u64 bar0_size; - u64 bar1_phy_addr; - u64 bar1_size; - u64 bar3_phy_addr; - u64 bar3_size; - u64 rsvd1[4]; -}; - -struct sphw_card_func_info { - u32 num_pf; - u32 rsvd0; - u64 usr_api_phy_addr; - struct func_pdev_info pdev_info[CARD_MAX_SIZE]; -}; - -struct wqe_info { - int q_id; - void *slq_handle; - unsigned int wqe_id; -}; - -#define MAX_VER_INFO_LEN 128 -struct drv_version_info { - char ver[MAX_VER_INFO_LEN]; -}; - -struct spnic_tx_hw_page { - u64 phy_addr; - u64 *map_addr; -}; - -struct nic_sq_info { - u16 q_id; - u16 pi; - u16 ci; /* sw_ci */ - u16 fi; /* hw_ci */ - u32 q_depth; - u16 pi_reverse; - u16 wqebb_size; - u8 priority; - u16 *ci_addr; - u64 cla_addr; - void *slq_handle; - struct spnic_tx_hw_page direct_wqe; - struct spnic_tx_hw_page doorbell; - u32 page_idx; - u32 glb_sq_id; -}; - -struct nic_rq_info { - u16 q_id; - u16 glb_rq_id; - u16 hw_pi; - u16 ci; /* sw_ci */ - u16 sw_pi; - u16 wqebb_size; - u16 q_depth; - u16 buf_len; - - void *slq_handle; - u64 ci_wqe_page_addr; - u64 ci_cla_tbl_addr; - - u8 coalesc_timer_cfg; - u8 pending_limt; - u16 msix_idx; - u32 msix_vector; -}; - -#define MT_EPERM 1 /* Operation not permitted */ -#define MT_EIO 2 /* I/O error */ -#define MT_EINVAL 3 /* Invalid argument */ -#define MT_EBUSY 4 /* Device or resource busy */ -#define MT_EOPNOTSUPP 0xFF /* Operation not supported */ - -struct mt_msg_head { - u8 status; - u8 rsvd1[3]; -}; - -#define MT_DCB_OPCODE_WR BIT(0) /* 1 - write, 0 - read */ -struct spnic_mt_qos_info { - struct mt_msg_head head; - - u16 op_code; - u8 valid_cos_bitmap; - u8 valid_up_bitmap; - u32 rsvd1; -}; - -struct spnic_mt_dcb_state { - struct mt_msg_head head; - - u16 op_code; - u8 state; - u8 rsvd; -}; - -#define MT_DCB_ETS_UP_TC BIT(1) -#define MT_DCB_ETS_UP_BW BIT(2) -#define MT_DCB_ETS_UP_PRIO BIT(3) -#define MT_DCB_ETS_TC_BW BIT(4) -#define MT_DCB_ETS_TC_PRIO BIT(5) - -#define DCB_UP_TC_NUM 0x8 -struct spnic_mt_ets_state { - struct mt_msg_head head; - - u16 op_code; - u8 up_tc[DCB_UP_TC_NUM]; - u8 up_bw[DCB_UP_TC_NUM]; - u8 tc_bw[DCB_UP_TC_NUM]; - u8 up_prio_bitmap; - u8 tc_prio_bitmap; - u32 rsvd; -}; - -#define MT_DCB_PFC_PFC_STATE BIT(1) -#define MT_DCB_PFC_PFC_PRI_EN BIT(2) -struct spnic_mt_pfc_state { - struct mt_msg_head head; - - u16 op_code; - u8 state; - u8 pfc_en_bitpamp; - u32 rsvd; -}; - -enum mt_api_type { - API_TYPE_MBOX = 1, - API_TYPE_API_CHAIN_BYPASS, - API_TYPE_API_CHAIN_TO_MPU, -}; - -struct npu_cmd_st { - u32 mod : 8; - u32 cmd : 8; - u32 ack_type : 3; - u32 direct_resp : 1; - u32 len : 12; -}; - -struct mpu_cmd_st { - u32 api_type : 8; - u32 mod : 8; - u32 cmd : 16; -}; - -struct msg_module { - char device_name[IFNAMSIZ]; - u32 module; - union { - u32 msg_formate; /* for driver */ - struct npu_cmd_st npu_cmd; - struct mpu_cmd_st mpu_cmd; - }; - u32 timeout; /* for mpu/npu cmd */ - u32 func_idx; - u32 buf_in_size; - u32 buf_out_size; - void *in_buf; - void *out_buf; - int bus_num; - u32 rsvd2[5]; -}; - -int alloc_buff_in(void *hwdev, struct msg_module *nt_msg, u32 in_size, void **buf_in); - -int alloc_buff_out(void *hwdev, struct msg_module *nt_msg, u32 out_size, void **buf_out); - -void free_buff_in(void *hwdev, struct msg_module *nt_msg, void *buf_in); - -void free_buff_out(void *hwdev, struct msg_module *nt_msg, void *buf_out); - -int copy_buf_out_to_user(struct msg_module *nt_msg, u32 out_size, void *buf_out); - -int get_func_type(void *hwdev, const void *buf_in, u32 in_size, void *buf_out, u32 *out_size); - -int get_func_id(void *hwdev, const void *buf_in, u32 in_size, void *buf_out, u32 *out_size); - -int get_drv_version(void *hwdev, const void *buf_in, u32 in_size, void *buf_out, u32 *out_size); - -int get_hw_driver_stats(const void *hwdev, const void *buf_in, u32 in_size, void *buf_out, - u32 *out_size); - -int clear_hw_driver_stats(void *hwdev, const void *buf_in, u32 in_size, void *buf_out, - u32 *out_size); - -int get_chip_faults_stats(const void *hwdev, const void *buf_in, u32 in_size, void *buf_out, - u32 *out_size); - -int get_chip_id_test(void *hwdev, const void *buf_in, u32 in_size, void *buf_out, u32 *out_size); - -int send_to_mpu(void *hwdev, struct msg_module *nt_msg, void *buf_in, u32 in_size, void *buf_out, - u32 *out_size); -int send_to_npu(void *hwdev, struct msg_module *nt_msg, void *buf_in, u32 in_size, void *buf_out, - u32 *out_size); - -int send_to_sm(void *hwdev, struct msg_module *nt_msg, void *buf_in, u32 in_size, void *buf_out, - u32 *out_size); - -#endif /* SPHW_MT_H_ */ diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_prof_adap.c b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_prof_adap.c deleted file mode 100644 index 20ebda15cda2..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_prof_adap.c +++ /dev/null @@ -1,94 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [COMM]" fmt - -#include <linux/kernel.h> -#include <linux/semaphore.h> -#include <linux/workqueue.h> -#include <linux/dev_printk.h> - -#include "sphw_common.h" -#include "sphw_hwdev.h" -#include "sphw_profile.h" -#include "sphw_prof_adap.h" - -typedef bool (*sphw_is_match_prof)(struct sphw_hwdev *hwdev); - -static bool is_match_prof_default_adapter(struct sphw_hwdev *hwdev) -{ - /* always match default profile adapter in standard scene */ - return true; -} - -enum prof_adapter_type { - PROF_ADAP_TYPE_PANGEA = 1, - - /* Add prof adapter type before default */ - PROF_ADAP_TYPE_DEFAULT, -}; - -/** - * struct sphw_prof_adapter - custom scene's profile adapter - * @type: adapter type - * @match: Check whether the current function is used in the custom scene. - * Implemented in the current source file - * @init: When @match return true, the initialization function called in probe. - * Implemented in the source file of the custom scene - * @deinit: When @match return true, the deinitialization function called when - * remove. Implemented in the source file of the custom scene - */ -struct sphw_prof_adapter { - enum prof_adapter_type type; - sphw_is_match_prof match; - sphw_init_prof_attr init; - sphw_deinit_prof_attr deinit; -}; - -struct sphw_prof_adapter prof_adap_objs[] = { - /* Add prof adapter before default profile */ - { - .type = PROF_ADAP_TYPE_DEFAULT, - .match = is_match_prof_default_adapter, - .init = NULL, - .deinit = NULL, - }, -}; - -void sphw_init_profile_adapter(struct sphw_hwdev *hwdev) -{ - struct sphw_prof_adapter *prof_obj = NULL; - u16 num_adap = ARRAY_SIZE(prof_adap_objs); - u16 i; - - for (i = 0; i < num_adap; i++) { - prof_obj = &prof_adap_objs[i]; - if (!(prof_obj->match && prof_obj->match(hwdev))) - continue; - - hwdev->prof_adap_type = prof_obj->type; - hwdev->prof_attr = prof_obj->init ? - prof_obj->init(hwdev) : NULL; - sdk_info(hwdev->dev_hdl, "Find profile adapter, type: %d\n", - hwdev->prof_adap_type); - - break; - } -} - -void sphw_deinit_profile_adapter(struct sphw_hwdev *hwdev) -{ - struct sphw_prof_adapter *prof_obj = NULL; - u16 num_adap = ARRAY_SIZE(prof_adap_objs); - u16 i; - - for (i = 0; i < num_adap; i++) { - prof_obj = &prof_adap_objs[i]; - if (hwdev->prof_adap_type != prof_obj->type) - continue; - - if (prof_obj->deinit) - prof_obj->deinit(hwdev->prof_attr); - break; - } -} diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_prof_adap.h b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_prof_adap.h deleted file mode 100644 index f83d3a28c834..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_prof_adap.h +++ /dev/null @@ -1,49 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPHW_PROF_ADAP_H -#define SPHW_PROF_ADAP_H - -#include <linux/workqueue.h> - -#include "sphw_profile.h" - -#define GET_PROF_ATTR_OPS(hwdev) \ - ((hwdev)->prof_attr ? (hwdev)->prof_attr->ops : NULL) - -static inline int sphw_get_work_cpu_affinity(struct sphw_hwdev *hwdev, - enum cpu_affinity_work_type type) -{ - struct sphw_prof_ops *ops = GET_PROF_ATTR_OPS(hwdev); - - if (ops && ops->get_work_cpu_affinity) - return ops->get_work_cpu_affinity(hwdev->prof_attr->priv_data, type); - - return WORK_CPU_UNBOUND; -} - -static inline void sphw_fault_post_process(struct sphw_hwdev *hwdev, u16 src, u16 level) -{ - struct sphw_prof_ops *ops = GET_PROF_ATTR_OPS(hwdev); - - if (ops && ops->fault_recover) - ops->fault_recover(hwdev->prof_attr->priv_data, src, level); -} - -static inline bool sphw_sw_feature_en(struct sphw_hwdev *hwdev, u64 feature_bit) -{ - if (!hwdev->prof_attr) - return false; - - return (hwdev->prof_attr->sw_feature_cap & feature_bit) && - (hwdev->prof_attr->dft_sw_feature & feature_bit); -} - -#define SW_FEATURE_EN(hwdev, f_bit) \ - sphw_sw_feature_en(hwdev, SPHW_SW_F_##f_bit) -#define SPHW_F_CHANNEL_LOCK_EN(hwdev) SW_FEATURE_EN(hwdev, CHANNEL_LOCK) - -void sphw_init_profile_adapter(struct sphw_hwdev *hwdev); -void sphw_deinit_profile_adapter(struct sphw_hwdev *hwdev); - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_profile.h b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_profile.h deleted file mode 100644 index 0e1c6c91ba31..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_profile.h +++ /dev/null @@ -1,36 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPHW_PROFILE_H -#define SPHW_PROFILE_H - -enum cpu_affinity_work_type { - WORK_TYPE_AEQ, - WORK_TYPE_MBOX, - WORK_TYPE_MGMT_MSG, - WORK_TYPE_COMM, -}; - -enum sphw_sw_features { - SPHW_SW_F_CHANNEL_LOCK = BIT(0), -}; - -struct sphw_prof_ops { - void (*fault_recover)(void *data, u16 src, u16 level); - int (*get_work_cpu_affinity)(void *data, u32 work_type); -}; - -struct sphw_prof_attr { - void *priv_data; - u64 hw_feature_cap; - u64 sw_feature_cap; - u64 dft_hw_feature; - u64 dft_sw_feature; - - struct sphw_prof_ops *ops; -}; - -typedef struct sphw_prof_attr *(*sphw_init_prof_attr)(void *hwdev); -typedef void (*sphw_deinit_prof_attr)(struct sphw_prof_attr *porf_attr); - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_wq.c b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_wq.c deleted file mode 100644 index 0ec202dfc4d7..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_wq.c +++ /dev/null @@ -1,152 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [COMM]" fmt - -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/dma-mapping.h> -#include <linux/device.h> -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/slab.h> -#include <linux/spinlock.h> - -#include "sphw_common.h" -#include "sphw_wq.h" -#include "sphw_hwdev.h" - -#define WQ_MIN_DEPTH 64 -#define WQ_MAX_DEPTH 65536 -#define WQ_MAX_NUM_PAGES (PAGE_SIZE / sizeof(u64)) - -static int wq_init_wq_block(struct sphw_wq *wq) -{ - int i; - - if (WQ_IS_0_LEVEL_CLA(wq)) { - wq->wq_block_paddr = wq->wq_pages[0].align_paddr; - wq->wq_block_vaddr = wq->wq_pages[0].align_vaddr; - - return 0; - } - - if (wq->num_wq_pages > WQ_MAX_NUM_PAGES) { - sdk_err(wq->dev_hdl, "num_wq_pages exceed limit: %lu\n", - WQ_MAX_NUM_PAGES); - return -EFAULT; - } - - wq->wq_block_vaddr = dma_alloc_coherent(wq->dev_hdl, PAGE_SIZE, &wq->wq_block_paddr, - GFP_KERNEL); - if (!wq->wq_block_vaddr) { - sdk_err(wq->dev_hdl, "Failed to alloc wq block\n"); - return -ENOMEM; - } - - for (i = 0; i < wq->num_wq_pages; i++) - wq->wq_block_vaddr[i] = - cpu_to_be64(wq->wq_pages[i].align_paddr); - - return 0; -} - -static int wq_alloc_pages(struct sphw_wq *wq) -{ - int i, page_idx, err; - - wq->wq_pages = kcalloc(wq->num_wq_pages, sizeof(*wq->wq_pages), - GFP_KERNEL); - if (!wq->wq_pages) { - sdk_err(wq->dev_hdl, "Failed to alloc wq pages handle\n"); - return -ENOMEM; - } - - for (page_idx = 0; page_idx < wq->num_wq_pages; page_idx++) { - err = sphw_dma_alloc_coherent_align(wq->dev_hdl, wq->wq_page_size, - wq->wq_page_size, GFP_KERNEL, - &wq->wq_pages[page_idx]); - if (err) { - sdk_err(wq->dev_hdl, "Failed to alloc wq page\n"); - goto free_wq_pages; - } - } - - err = wq_init_wq_block(wq); - if (err) - goto free_wq_pages; - - return 0; - -free_wq_pages: - for (i = 0; i < page_idx; i++) - sphw_dma_free_coherent_align(wq->dev_hdl, &wq->wq_pages[i]); - - kfree(wq->wq_pages); - wq->wq_pages = NULL; - - return -ENOMEM; -} - -static void wq_free_pages(struct sphw_wq *wq) -{ - int i; - - if (!WQ_IS_0_LEVEL_CLA(wq)) - dma_free_coherent(wq->dev_hdl, PAGE_SIZE, wq->wq_block_vaddr, - wq->wq_block_paddr); - - for (i = 0; i < wq->num_wq_pages; i++) - sphw_dma_free_coherent_align(wq->dev_hdl, &wq->wq_pages[i]); - - kfree(wq->wq_pages); - wq->wq_pages = NULL; -} - -int sphw_wq_create(void *hwdev, struct sphw_wq *wq, u32 q_depth, u16 wqebb_size) -{ - struct sphw_hwdev *dev = hwdev; - u32 wq_page_size; - - if (!wq || !dev) { - pr_err("Invalid wq or dev_hdl\n"); - return -EINVAL; - } - - if (q_depth < WQ_MIN_DEPTH || q_depth > WQ_MAX_DEPTH || - (q_depth & (q_depth - 1)) || !wqebb_size || - (wqebb_size & (wqebb_size - 1))) { - sdk_err(dev->dev_hdl, "Wq q_depth(%u) or wqebb_size(%u) is invalid\n", - q_depth, wqebb_size); - return -EINVAL; - } - - wq_page_size = ALIGN(dev->wq_page_size, PAGE_SIZE); - - memset(wq, 0, sizeof(*wq)); - wq->dev_hdl = dev->dev_hdl; - wq->q_depth = q_depth; - wq->idx_mask = (u16)(q_depth - 1); - wq->wqebb_size = wqebb_size; - wq->wqebb_size_shift = (u16)ilog2(wq->wqebb_size); - wq->wq_page_size = wq_page_size; - - wq->wqebbs_per_page = wq_page_size / wqebb_size; - /* In case of wq_page_size is larger than q_depth * wqebb_size */ - if (wq->wqebbs_per_page > q_depth) - wq->wqebbs_per_page = q_depth; - wq->wqebbs_per_page_shift = (u16)ilog2(wq->wqebbs_per_page); - wq->wqebbs_per_page_mask = (u16)(wq->wqebbs_per_page - 1); - wq->num_wq_pages = (u16)(ALIGN(((u32)q_depth * wqebb_size), - wq_page_size) / wq_page_size); - - return wq_alloc_pages(wq); -} - -void sphw_wq_destroy(struct sphw_wq *wq) -{ - if (!wq) - return; - - wq_free_pages(wq); -} diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_wq.h b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_wq.h deleted file mode 100644 index 01d564ca527a..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_wq.h +++ /dev/null @@ -1,119 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPHW_WQ_H -#define SPHW_WQ_H - -struct sphw_wq { - u16 cons_idx; - u16 prod_idx; - - u32 q_depth; - u16 idx_mask; - u16 wqebb_size_shift; - u16 num_wq_pages; - u32 wqebbs_per_page; - u16 wqebbs_per_page_shift; - u16 wqebbs_per_page_mask; - - struct sphw_dma_addr_align *wq_pages; - - dma_addr_t wq_block_paddr; - u64 *wq_block_vaddr; - - void *dev_hdl; - u32 wq_page_size; - u16 wqebb_size; -} ____cacheline_aligned; - -int sphw_wq_create(void *hwdev, struct sphw_wq *wq, u32 q_depth, u16 wqebb_size); -void sphw_wq_destroy(struct sphw_wq *wq); - -#define WQ_MASK_IDX(wq, idx) ((idx) & (wq)->idx_mask) -#define WQ_MASK_PAGE(wq, pg_idx) ((pg_idx) < (wq)->num_wq_pages ? (pg_idx) : 0) -#define WQ_PAGE_IDX(wq, idx) ((idx) >> (wq)->wqebbs_per_page_shift) -#define WQ_OFFSET_IN_PAGE(wq, idx) ((idx) & (wq)->wqebbs_per_page_mask) -#define WQ_GET_WQEBB_ADDR(wq, pg_idx, idx_in_pg) \ - ((u8 *)(wq)->wq_pages[pg_idx].align_vaddr + ((idx_in_pg) << (wq)->wqebb_size_shift)) -#define WQ_IS_0_LEVEL_CLA(wq) ((wq)->num_wq_pages == 1) - -static inline u16 sphw_wq_free_wqebbs(struct sphw_wq *wq) -{ - return wq->q_depth - ((wq->q_depth + wq->prod_idx - wq->cons_idx) & - wq->idx_mask) - 1; -} - -static inline bool sphw_wq_is_empty(struct sphw_wq *wq) -{ - return WQ_MASK_IDX(wq, wq->prod_idx) == WQ_MASK_IDX(wq, wq->cons_idx); -} - -static inline void *sphw_wq_get_one_wqebb(struct sphw_wq *wq, u16 *pi) -{ - *pi = WQ_MASK_IDX(wq, wq->prod_idx); - wq->prod_idx++; - - return WQ_GET_WQEBB_ADDR(wq, WQ_PAGE_IDX(wq, *pi), - WQ_OFFSET_IN_PAGE(wq, *pi)); -} - -static inline void *sphw_wq_get_multi_wqebbs(struct sphw_wq *wq, u16 num_wqebbs, u16 *prod_idx, - void **second_part_wqebbs_addr, - u16 *first_part_wqebbs_num) -{ - u32 pg_idx, off_in_page; - - *prod_idx = WQ_MASK_IDX(wq, wq->prod_idx); - wq->prod_idx += num_wqebbs; - - pg_idx = WQ_PAGE_IDX(wq, *prod_idx); - off_in_page = WQ_OFFSET_IN_PAGE(wq, *prod_idx); - - if (off_in_page + num_wqebbs > wq->wqebbs_per_page) { - /* wqe across wq page boundary */ - *second_part_wqebbs_addr = - WQ_GET_WQEBB_ADDR(wq, WQ_MASK_PAGE(wq, pg_idx + 1), 0); - *first_part_wqebbs_num = wq->wqebbs_per_page - off_in_page; - } else { - *second_part_wqebbs_addr = NULL; - *first_part_wqebbs_num = num_wqebbs; - } - - return WQ_GET_WQEBB_ADDR(wq, pg_idx, off_in_page); -} - -static inline void sphw_wq_put_wqebbs(struct sphw_wq *wq, u16 num_wqebbs) -{ - wq->cons_idx += num_wqebbs; -} - -static inline void *sphw_wq_wqebb_addr(struct sphw_wq *wq, u16 idx) -{ - return WQ_GET_WQEBB_ADDR(wq, WQ_PAGE_IDX(wq, idx), - WQ_OFFSET_IN_PAGE(wq, idx)); -} - -static inline void *sphw_wq_read_one_wqebb(struct sphw_wq *wq, u16 *cons_idx) -{ - *cons_idx = WQ_MASK_IDX(wq, wq->cons_idx); - - return sphw_wq_wqebb_addr(wq, *cons_idx); -} - -static inline u64 sphw_wq_get_first_wqe_page_addr(struct sphw_wq *wq) -{ - return wq->wq_pages[0].align_paddr; -} - -static inline void sphw_wq_reset(struct sphw_wq *wq) -{ - u16 pg_idx; - - wq->cons_idx = 0; - wq->prod_idx = 0; - - for (pg_idx = 0; pg_idx < wq->num_wq_pages; pg_idx++) - memset(wq->wq_pages[pg_idx].align_vaddr, 0, wq->wq_page_size); -} - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_dbg.c b/drivers/net/ethernet/ramaxel/spnic/spnic_dbg.c deleted file mode 100644 index 910baed023a5..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_dbg.c +++ /dev/null @@ -1,752 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [NIC]" fmt - -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/types.h> -#include <linux/semaphore.h> - -#include "sphw_mt.h" -#include "sphw_crm.h" -#include "spnic_nic_dev.h" -#include "spnic_nic_dbg.h" -#include "spnic_nic_qp.h" -#include "spnic_rx.h" -#include "spnic_tx.h" -#include "spnic_dcb.h" - -typedef int (*nic_driv_module)(struct spnic_nic_dev *nic_dev, const void *buf_in, u32 in_size, - void *buf_out, u32 *out_size); - -struct nic_drv_module_handle { - enum driver_cmd_type driv_cmd_name; - nic_driv_module driv_func; -}; - -int get_nic_drv_version(void *buf_out, u32 *out_size) -{ - struct drv_version_info *ver_info = buf_out; - - if (!buf_out) { - pr_err("Buf_out is NULL.\n"); - return -EINVAL; - } - - if (*out_size != sizeof(*ver_info)) { - pr_err("Unexpect out buf size from user :%u, expect: %lu\n", - *out_size, sizeof(*ver_info)); - return -EINVAL; - } - - snprintf(ver_info->ver, sizeof(ver_info->ver), "%s [compiled with the kernel]", - SPNIC_DRV_VERSION); - - return 0; -} - -static int get_tx_info(struct spnic_nic_dev *nic_dev, const void *buf_in, - u32 in_size, void *buf_out, u32 *out_size) -{ - u16 q_id; - - if (!SPHW_CHANNEL_RES_VALID(nic_dev)) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Netdev is down, can't get tx info\n"); - return -EFAULT; - } - - if (!buf_in || !buf_out) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Buf_in or buf_out is NULL.\n"); - return -EINVAL; - } - - q_id = *((u16 *)buf_in); - - return spnic_dbg_get_sq_info(nic_dev->hwdev, q_id, buf_out, *out_size); -} - -static int get_q_num(struct spnic_nic_dev *nic_dev, - const void *buf_in, u32 in_size, - void *buf_out, u32 *out_size) -{ - if (!SPHW_CHANNEL_RES_VALID(nic_dev)) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Netdev is down, can't get queue number\n"); - return -EFAULT; - } - - if (!buf_out) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Get queue number para buf_out is NULL.\n"); - return -EINVAL; - } - - if (*out_size != sizeof(u16)) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Unexpect out buf size from user: %u, expect: %lu\n", - *out_size, sizeof(u16)); - return -EINVAL; - } - - *((u16 *)buf_out) = nic_dev->q_params.num_qps; - - return 0; -} - -static int get_tx_wqe_info(struct spnic_nic_dev *nic_dev, - const void *buf_in, u32 in_size, - void *buf_out, u32 *out_size) -{ - const struct wqe_info *info = buf_in; - u16 wqebb_cnt = 1; - - if (!SPHW_CHANNEL_RES_VALID(nic_dev)) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Netdev is down, can't get tx wqe info\n"); - return -EFAULT; - } - - if (!info || !buf_out) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Buf_in or buf_out is NULL.\n"); - return -EINVAL; - } - - return spnic_dbg_get_wqe_info(nic_dev->hwdev, (u16)info->q_id, - (u16)info->wqe_id, wqebb_cnt, - buf_out, (u16 *)out_size, SPNIC_SQ); -} - -static int get_rx_info(struct spnic_nic_dev *nic_dev, const void *buf_in, - u32 in_size, void *buf_out, u32 *out_size) -{ - struct nic_rq_info *rq_info = buf_out; - u16 q_id; - int err; - - if (!SPHW_CHANNEL_RES_VALID(nic_dev)) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Netdev is down, can't get rx info\n"); - return -EFAULT; - } - - if (!buf_in || !buf_out) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Buf_in or buf_out is NULL.\n"); - return -EINVAL; - } - - q_id = *((u16 *)buf_in); - - err = spnic_dbg_get_rq_info(nic_dev->hwdev, q_id, buf_out, *out_size); - - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Get rq info failed, ret is %d.\n", err); - return err; - } - - rq_info->ci = (u16)nic_dev->rxqs[q_id].cons_idx & - nic_dev->rxqs[q_id].q_mask; - - rq_info->sw_pi = nic_dev->rxqs[q_id].next_to_update; - rq_info->msix_vector = nic_dev->rxqs[q_id].irq_id; - - rq_info->coalesc_timer_cfg = nic_dev->rxqs[q_id].last_coalesc_timer_cfg; - rq_info->pending_limt = nic_dev->rxqs[q_id].last_pending_limt; - - return 0; -} - -static int get_rx_wqe_info(struct spnic_nic_dev *nic_dev, const void *buf_in, - u32 in_size, void *buf_out, u32 *out_size) -{ - const struct wqe_info *info = buf_in; - u16 wqebb_cnt = 1; - - if (!SPHW_CHANNEL_RES_VALID(nic_dev)) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Netdev is down, can't get rx wqe info\n"); - return -EFAULT; - } - - if (!info || !buf_out) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Buf_in or buf_out is NULL.\n"); - return -EINVAL; - } - - return spnic_dbg_get_wqe_info(nic_dev->hwdev, (u16)info->q_id, - (u16)info->wqe_id, wqebb_cnt, - buf_out, (u16 *)out_size, SPNIC_RQ); -} - -static int get_rx_cqe_info(struct spnic_nic_dev *nic_dev, const void *buf_in, - u32 in_size, void *buf_out, u32 *out_size) -{ - const struct wqe_info *info = buf_in; - u16 q_id = 0; - u16 idx = 0; - - if (!SPHW_CHANNEL_RES_VALID(nic_dev)) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Netdev is down, can't get rx cqe info\n"); - return -EFAULT; - } - - if (!info || !buf_out) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Buf_in or buf_out is NULL.\n"); - return -EINVAL; - } - - if (*out_size != sizeof(struct spnic_rq_cqe)) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Unexpect out buf size from user :%u, expect: %lu\n", - *out_size, sizeof(struct spnic_rq_cqe)); - return -EINVAL; - } - q_id = (u16)info->q_id; - idx = (u16)info->wqe_id; - - if (q_id >= nic_dev->q_params.num_qps || - idx >= nic_dev->rxqs[q_id].q_depth) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Invalid q_id[%u] >= %u, or wqe idx[%u] >= %u.\n", - q_id, nic_dev->q_params.num_qps, idx, - nic_dev->rxqs[q_id].q_depth); - return -EFAULT; - } - - memcpy(buf_out, nic_dev->rxqs[q_id].rx_info[idx].cqe, - sizeof(struct spnic_rq_cqe)); - - return 0; -} - -static void clean_nicdev_stats(struct spnic_nic_dev *nic_dev) -{ - u64_stats_update_begin(&nic_dev->stats.syncp); - nic_dev->stats.netdev_tx_timeout = 0; - nic_dev->stats.tx_carrier_off_drop = 0; - nic_dev->stats.tx_invalid_qid = 0; - u64_stats_update_end(&nic_dev->stats.syncp); -} - -static int clear_func_static(struct spnic_nic_dev *nic_dev, const void *buf_in, - u32 in_size, void *buf_out, u32 *out_size) -{ - int i; - - *out_size = 0; - clean_nicdev_stats(nic_dev); - for (i = 0; i < nic_dev->max_qps; i++) { - spnic_rxq_clean_stats(&nic_dev->rxqs[i].rxq_stats); - spnic_txq_clean_stats(&nic_dev->txqs[i].txq_stats); - } - - return 0; -} - -static int get_loopback_mode(struct spnic_nic_dev *nic_dev, const void *buf_in, - u32 in_size, void *buf_out, u32 *out_size) -{ - struct spnic_nic_loop_mode *mode = buf_out; - - if (!out_size || !mode) - return -EINVAL; - - if (*out_size != sizeof(*mode)) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Unexpect out buf size from user: %u, expect: %lu\n", - *out_size, sizeof(*mode)); - return -EINVAL; - } - - return spnic_get_loopback_mode(nic_dev->hwdev, (u8 *)&mode->loop_mode, - (u8 *)&mode->loop_ctrl); -} - -static int set_loopback_mode(struct spnic_nic_dev *nic_dev, const void *buf_in, - u32 in_size, void *buf_out, u32 *out_size) -{ - const struct spnic_nic_loop_mode *mode = buf_in; - int err; - - if (!test_bit(SPNIC_INTF_UP, &nic_dev->flags)) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Netdev is down, can't set loopback mode\n"); - return -EFAULT; - } - - if (!mode || !out_size || in_size != sizeof(*mode)) - return -EINVAL; - - if (*out_size != sizeof(*mode)) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Unexpect out buf size from user: %u, expect: %lu\n", - *out_size, sizeof(*mode)); - return -EINVAL; - } - - err = spnic_set_loopback_mode(nic_dev->hwdev, (u8)mode->loop_mode, (u8)mode->loop_ctrl); - if (err == 0) - nicif_info(nic_dev, drv, nic_dev->netdev, "Set loopback mode %u en %u succeed\n", - mode->loop_mode, mode->loop_ctrl); - - return err; -} - -enum spnic_nic_link_mode { - SPNIC_LINK_MODE_AUTO = 0, - SPNIC_LINK_MODE_UP, - SPNIC_LINK_MODE_DOWN, - SPNIC_LINK_MODE_MAX, -}; - -static int set_link_mode_param_valid(struct spnic_nic_dev *nic_dev, - const void *buf_in, u32 in_size, - u32 *out_size) -{ - if (!test_bit(SPNIC_INTF_UP, &nic_dev->flags)) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Netdev is down, can't set link mode\n"); - return -EFAULT; - } - - if (!buf_in || !out_size || - in_size != sizeof(enum spnic_nic_link_mode)) - return -EINVAL; - - if (*out_size != sizeof(enum spnic_nic_link_mode)) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Unexpect out buf size from user: %u, expect: %lu\n", - *out_size, sizeof(enum spnic_nic_link_mode)); - return -EINVAL; - } - - return 0; -} - -static int set_link_mode(struct spnic_nic_dev *nic_dev, const void *buf_in, - u32 in_size, void *buf_out, u32 *out_size) -{ - const enum spnic_nic_link_mode *link = buf_in; - u8 link_status; - - if (set_link_mode_param_valid(nic_dev, buf_in, in_size, out_size)) - return -EFAULT; - - switch (*link) { - case SPNIC_LINK_MODE_AUTO: - if (spnic_get_link_state(nic_dev->hwdev, &link_status)) - link_status = false; - spnic_link_status_change(nic_dev, (bool)link_status); - nicif_info(nic_dev, drv, nic_dev->netdev, - "Set link mode: auto succeed, now is link %s\n", - (link_status ? "up" : "down")); - break; - case SPNIC_LINK_MODE_UP: - spnic_link_status_change(nic_dev, true); - nicif_info(nic_dev, drv, nic_dev->netdev, - "Set link mode: up succeed\n"); - break; - case SPNIC_LINK_MODE_DOWN: - spnic_link_status_change(nic_dev, false); - nicif_info(nic_dev, drv, nic_dev->netdev, - "Set link mode: down succeed\n"); - break; - default: - nicif_err(nic_dev, drv, nic_dev->netdev, - "Invalid link mode %d to set\n", *link); - return -EINVAL; - } - - return 0; -} - -static int get_sset_count(struct spnic_nic_dev *nic_dev, const void *buf_in, - u32 in_size, void *buf_out, u32 *out_size) -{ - u32 count; - - if (!buf_in || in_size != sizeof(u32) || !out_size || - *out_size != sizeof(u32) || !buf_out) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Invalid parameters, in_size: %u\n", - in_size); - return -EINVAL; - } - - switch (*((u32 *)buf_in)) { - case SHOW_SSET_IO_STATS: - count = spnic_get_io_stats_size(nic_dev); - break; - default: - count = 0; - break; - } - - *((u32 *)buf_out) = count; - - return 0; -} - -static int get_sset_stats(struct spnic_nic_dev *nic_dev, const void *buf_in, - u32 in_size, void *buf_out, u32 *out_size) -{ - struct spnic_show_item *items = buf_out; - u32 sset, count, size; - int err; - - if (!buf_in || in_size != sizeof(u32) || !out_size || !buf_out) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Invalid parameters, in_size: %u\n", - in_size); - return -EINVAL; - } - - size = sizeof(u32); - err = get_sset_count(nic_dev, buf_in, in_size, &count, &size); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Get sset count failed, ret=%d\n", - err); - return -EINVAL; - } - if (count * sizeof(*items) != *out_size) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Unexpect out buf size from user :%u, expect: %lu\n", - *out_size, count * sizeof(*items)); - return -EINVAL; - } - - sset = *((u32 *)buf_in); - - switch (sset) { - case SHOW_SSET_IO_STATS: - spnic_get_io_stats(nic_dev, items); - break; - - default: - nicif_err(nic_dev, drv, nic_dev->netdev, "Unknown %u to get stats\n", - sset); - err = -EINVAL; - break; - } - - return err; -} - -static int dcb_mt_qos_map(struct spnic_nic_dev *nic_dev, const void *buf_in, - u32 in_size, void *buf_out, u32 *out_size) -{ - const struct spnic_mt_qos_info *qos = buf_in; - struct spnic_mt_qos_info *qos_out = buf_out; - u8 up_cnt, up; - int err; - - if (!buf_out || !out_size || !buf_in) - return -EINVAL; - - if (*out_size != sizeof(*qos_out) || in_size != sizeof(*qos)) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Unexpect buf size from user, in_size: %u, out_size: %u, expect: %lu\n", - in_size, *out_size, sizeof(*qos)); - return -EINVAL; - } - - memcpy(qos_out, qos, sizeof(*qos)); - qos_out->head.status = 0; - if (qos->op_code & MT_DCB_OPCODE_WR) { - up_cnt = 0; - for (up = 0; up < SPNIC_DCB_UP_MAX; up++) { - if (qos->valid_up_bitmap & BIT(up)) - up_cnt++; - } - - if (up_cnt != nic_dev->wanted_dcb_cfg.max_cos) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Invalid up bitmap: 0x%x", - qos->valid_up_bitmap); - qos_out->head.status = MT_EINVAL; - return 0; - } - - err = spnic_dcbcfg_set_up_bitmap(nic_dev, qos->valid_up_bitmap); - if (err) - qos_out->head.status = MT_EIO; - } else { - qos_out->valid_up_bitmap = - spnic_get_valid_up_bitmap(&nic_dev->wanted_dcb_cfg); - qos_out->valid_cos_bitmap = - nic_dev->wanted_dcb_cfg.valid_cos_bitmap; - } - - return 0; -} - -static int dcb_mt_dcb_state(struct spnic_nic_dev *nic_dev, const void *buf_in, - u32 in_size, void *buf_out, u32 *out_size) -{ - const struct spnic_mt_dcb_state *dcb = buf_in; - struct spnic_mt_dcb_state *dcb_out = buf_out; - int err; - - if (!buf_in || !buf_out || !out_size) - return -EINVAL; - - if (*out_size != sizeof(*dcb_out) || in_size != sizeof(*dcb)) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Unexpect buf size from user, in_size: %u, out_size: %u, expect: %lu\n", - in_size, *out_size, sizeof(*dcb)); - return -EINVAL; - } - - memcpy(dcb_out, dcb, sizeof(*dcb)); - dcb_out->head.status = 0; - if (dcb->op_code & MT_DCB_OPCODE_WR) { - if (test_bit(SPNIC_DCB_ENABLE, &nic_dev->flags) == dcb->state) - return 0; - - /* nic_mutex has been acquired by send_to_nic_driver and will - * also be acquired inside spnic_setup_tc - */ - mutex_unlock(&nic_dev->nic_mutex); - rtnl_lock(); - err = spnic_setup_tc(nic_dev->netdev, - dcb->state ? nic_dev->wanted_dcb_cfg.max_cos : 0); - rtnl_unlock(); - mutex_lock(&nic_dev->nic_mutex); - if (err) - dcb_out->head.status = MT_EIO; - } else { - dcb_out->state = !!test_bit(SPNIC_DCB_ENABLE, &nic_dev->flags); - } - - return 0; -} - -static int dcb_mt_pfc_state(struct spnic_nic_dev *nic_dev, const void *buf_in, - u32 in_size, void *buf_out, u32 *out_size) -{ - const struct spnic_mt_pfc_state *pfc = buf_in; - struct spnic_mt_pfc_state *pfc_out = buf_out; - u8 cur_pfc_state, cur_pfc_en_bitmap; - int err; - - if (!buf_in || !buf_out || !out_size) - return -EINVAL; - - if (*out_size != sizeof(*pfc_out) || in_size != sizeof(*pfc)) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Unexpect buf size from user, in_size: %u, out_size: %u, expect: %lu\n", - in_size, *out_size, sizeof(*pfc)); - return -EINVAL; - } - - cur_pfc_state = spnic_dcbcfg_get_pfc_state(nic_dev); - cur_pfc_en_bitmap = spnic_dcbcfg_get_pfc_pri_en(nic_dev); - - memcpy(pfc_out, pfc, sizeof(*pfc)); - pfc_out->head.status = 0; - if (pfc->op_code & MT_DCB_OPCODE_WR) { - if (pfc->op_code & MT_DCB_PFC_PFC_STATE) - spnic_dcbcfg_set_pfc_state(nic_dev, pfc->state); - - if (pfc->op_code & MT_DCB_PFC_PFC_PRI_EN) - spnic_dcbcfg_set_pfc_pri_en(nic_dev, pfc->pfc_en_bitpamp); - - if (test_bit(SPNIC_DCB_ENABLE, &nic_dev->flags)) { - err = spnic_configure_dcb(nic_dev->netdev); - if (err) { - pfc_out->head.status = MT_EIO; - goto set_err; - } - } - } else { - pfc_out->state = cur_pfc_state; - pfc_out->pfc_en_bitpamp = cur_pfc_en_bitmap; - } - - return 0; - -set_err: - spnic_dcbcfg_set_pfc_state(nic_dev, cur_pfc_state); - spnic_dcbcfg_set_pfc_pri_en(nic_dev, cur_pfc_en_bitmap); - if (test_bit(SPNIC_DCB_ENABLE, &nic_dev->flags)) { - err = spnic_configure_dcb(nic_dev->netdev); - if (err) - nicif_warn(nic_dev, drv, nic_dev->netdev, - "Failed to rollback pfc config\n"); - } - return 0; -} - -static int dcb_mt_ets_state(struct spnic_nic_dev *nic_dev, const void *buf_in, - u32 in_size, void *buf_out, u32 *out_size) -{ - const struct spnic_mt_ets_state *ets = buf_in; - struct spnic_mt_ets_state *ets_out = buf_out; - struct spnic_dcb_config dcb_cfg_backup; - int err; - - if (!buf_in || !buf_out || !out_size) - return -EINVAL; - - if (*out_size != sizeof(*ets_out) || in_size != sizeof(*ets)) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Unexpect buf size from user, in_size: %u, out_size: %u, expect: %lu\n", - in_size, *out_size, sizeof(*ets)); - return -EINVAL; - } - - memcpy(ets_out, ets, sizeof(*ets)); - ets_out->head.status = 0; - if (ets->op_code & MT_DCB_OPCODE_WR) { - if (ets->op_code & (MT_DCB_ETS_UP_BW | MT_DCB_ETS_UP_PRIO)) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Not support to set up bw and up prio\n"); - ets_out->head.status = MT_EOPNOTSUPP; - return 0; - } - - dcb_cfg_backup = nic_dev->wanted_dcb_cfg; - - if (ets->op_code & MT_DCB_ETS_UP_TC) { - err = spnic_dcbcfg_set_ets_up_tc_map(nic_dev, ets->up_tc); - if (err) { - ets_out->head.status = MT_EIO; - return 0; - } - } - if (ets->op_code & MT_DCB_ETS_TC_BW) { - err = spnic_dcbcfg_set_ets_tc_bw(nic_dev, ets->tc_bw); - if (err) { - ets_out->head.status = MT_EIO; - goto set_err; - } - } - if (ets->op_code & MT_DCB_ETS_TC_PRIO) - spnic_dcbcfg_set_ets_tc_prio_type(nic_dev, ets->tc_prio_bitmap); - - if (test_bit(SPNIC_DCB_ENABLE, &nic_dev->flags)) { - err = spnic_configure_dcb(nic_dev->netdev); - if (err) { - ets_out->head.status = MT_EIO; - goto set_err; - } - } - } else { - spnic_dcbcfg_get_ets_up_tc_map(nic_dev, ets_out->up_tc); - spnic_dcbcfg_get_ets_tc_bw(nic_dev, ets_out->tc_bw); - spnic_dcbcfg_get_ets_tc_prio_type(nic_dev, &ets_out->tc_prio_bitmap); - } - - return 0; - -set_err: - nic_dev->wanted_dcb_cfg = dcb_cfg_backup; - if (test_bit(SPNIC_DCB_ENABLE, &nic_dev->flags)) { - err = spnic_configure_dcb(nic_dev->netdev); - if (err) - nicif_warn(nic_dev, drv, nic_dev->netdev, - "Failed to rollback ets config\n"); - } - - return 0; -} - -static int get_inter_num(struct spnic_nic_dev *nic_dev, const void *buf_in, - u32 in_size, void *buf_out, u32 *out_size) -{ - u16 intr_num; - - intr_num = sphw_intr_num(nic_dev->hwdev); - - if (*out_size != sizeof(u16)) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Unexpect out buf size from user :%u, expect: %lu\n", - *out_size, sizeof(u16)); - return -EFAULT; - } - *(u16 *)buf_out = intr_num; - - *out_size = sizeof(u16); - - return 0; -} - -static int get_netdev_name(struct spnic_nic_dev *nic_dev, const void *buf_in, - u32 in_size, void *buf_out, u32 *out_size) -{ - if (*out_size != IFNAMSIZ) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Unexpect out buf size from user :%u, expect: %u\n", - *out_size, IFNAMSIZ); - return -EFAULT; - } - - strlcpy(buf_out, nic_dev->netdev->name, IFNAMSIZ); - - return 0; -} - -struct nic_drv_module_handle nic_driv_module_cmd_handle[] = { - {TX_INFO, get_tx_info}, - {Q_NUM, get_q_num}, - {TX_WQE_INFO, get_tx_wqe_info}, - {RX_INFO, get_rx_info}, - {RX_WQE_INFO, get_rx_wqe_info}, - {RX_CQE_INFO, get_rx_cqe_info}, - {GET_INTER_NUM, get_inter_num}, - {CLEAR_FUNC_STASTIC, clear_func_static}, - {GET_LOOPBACK_MODE, get_loopback_mode}, - {SET_LOOPBACK_MODE, set_loopback_mode}, - {SET_LINK_MODE, set_link_mode}, - {GET_SSET_COUNT, get_sset_count}, - {GET_SSET_ITEMS, get_sset_stats}, - {DCB_QOS_INFO, dcb_mt_qos_map}, - {DCB_STATE, dcb_mt_dcb_state}, - {DCB_PFC_STATE, dcb_mt_pfc_state}, - {DCB_ETS_STATE, dcb_mt_ets_state}, - {GET_ULD_DEV_NAME, get_netdev_name}, -}; - -static int send_to_nic_driver(struct spnic_nic_dev *nic_dev, - u32 cmd, const void *buf_in, - u32 in_size, void *buf_out, u32 *out_size) -{ - int index, num_cmds = sizeof(nic_driv_module_cmd_handle) / - sizeof(nic_driv_module_cmd_handle[0]); - enum driver_cmd_type cmd_type = (enum driver_cmd_type)cmd; - int err = 0; - - mutex_lock(&nic_dev->nic_mutex); - for (index = 0; index < num_cmds; index++) { - if (cmd_type == - nic_driv_module_cmd_handle[index].driv_cmd_name) { - err = nic_driv_module_cmd_handle[index].driv_func - (nic_dev, buf_in, - in_size, buf_out, out_size); - break; - } - } - mutex_unlock(&nic_dev->nic_mutex); - - if (index == num_cmds) - pr_err("Can't find callback for %d\n", cmd_type); - - return err; -} - -int nic_ioctl(void *uld_dev, u32 cmd, const void *buf_in, - u32 in_size, void *buf_out, u32 *out_size) -{ - if (cmd == GET_DRV_VERSION) - return get_nic_drv_version(buf_out, out_size); - else if (!uld_dev) - return -EINVAL; - - return send_to_nic_driver(uld_dev, cmd, buf_in, - in_size, buf_out, out_size); -} diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_dcb.c b/drivers/net/ethernet/ramaxel/spnic/spnic_dcb.c deleted file mode 100644 index 7108430e0618..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_dcb.c +++ /dev/null @@ -1,965 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [NIC]" fmt - -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/device.h> -#include <linux/module.h> -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/interrupt.h> -#include <linux/etherdevice.h> -#include <linux/netdevice.h> - -#include "sphw_crm.h" -#include "spnic_lld.h" -#include "spnic_nic_cfg.h" -#include "spnic_nic_dev.h" -#include "spnic_dcb.h" - -#define DCB_CFG_CHG_ETS BIT(0) -#define DCB_CFG_CHG_PFC BIT(1) -#define DCB_CFG_CHG_UP_COS BIT(2) - -#define MAX_BW_PERCENT 100 - -void spnic_set_prio_tc_map(struct spnic_nic_dev *nic_dev) -{ - struct spnic_dcb_config *dcb_cfg = &nic_dev->hw_dcb_cfg; - u8 valid_up_bitmap = spnic_get_valid_up_bitmap(dcb_cfg); - u8 default_tc = dcb_cfg->max_cos - 1; - u8 i, tc_id; - - /* use 0~max_cos-1 as tc for netdev */ - for (tc_id = 0, i = 0; i < SPNIC_DCB_COS_MAX; i++) { - if (dcb_cfg->valid_cos_bitmap & BIT(i)) { - netdev_set_prio_tc_map(nic_dev->netdev, - dcb_cfg->cos_cfg[i].up, tc_id); - tc_id++; - } - } - - /* set invalid up mapping to the default tc */ - for (i = 0; i < SPNIC_DCB_UP_MAX; i++) { - if (!(valid_up_bitmap & BIT(i))) - netdev_set_prio_tc_map(nic_dev->netdev, i, default_tc); - } -} - -void spnic_update_tx_db_cos(struct spnic_nic_dev *nic_dev) -{ - u8 i, valid_cos_bitmap, cos; - u16 num_rss; - - if (!test_bit(SPNIC_DCB_ENABLE, &nic_dev->flags)) { - spnic_set_txq_cos(nic_dev, 0, nic_dev->q_params.num_qps, - nic_dev->hw_dcb_cfg.default_cos); - return; - } - - num_rss = nic_dev->q_params.num_rss; - valid_cos_bitmap = nic_dev->hw_dcb_cfg.valid_cos_bitmap; - for (i = 0; i < nic_dev->q_params.num_tc; i++) { - cos = (u8)(ffs(valid_cos_bitmap) - 1); - spnic_set_txq_cos(nic_dev, (u16)(i * num_rss), num_rss, cos); - valid_cos_bitmap &= (~BIT(cos)); - } -} - -int spnic_set_tx_cos_state(struct spnic_nic_dev *nic_dev) -{ - struct spnic_dcb_config *dcb_cfg = &nic_dev->hw_dcb_cfg; - struct spnic_dcb_state dcb_state = {0}; - u8 default_cos, i; - int err; - - if (SPNIC_FUNC_IS_VF(nic_dev->hwdev)) { - err = spnic_get_pf_dcb_state(nic_dev->hwdev, &dcb_state); - if (err) { - spnic_err(nic_dev, drv, "Failed to get vf default cos\n"); - return err; - } - /* VF does not support DCB, use the default cos */ - dcb_cfg->default_cos = dcb_state.default_cos; - - return 0; - } - - default_cos = dcb_cfg->default_cos; - dcb_state.dcb_on = !!test_bit(SPNIC_DCB_ENABLE, &nic_dev->flags); - dcb_state.default_cos = default_cos; - memset(dcb_state.up_cos, default_cos, sizeof(dcb_state.up_cos)); - if (test_bit(SPNIC_DCB_ENABLE, &nic_dev->flags)) { - for (i = 0; i < SPNIC_DCB_COS_MAX; i++) { - if (dcb_cfg->valid_cos_bitmap & BIT(i)) - dcb_state.up_cos[dcb_cfg->cos_cfg[i].up] = i; - } - } - - err = spnic_set_dcb_state(nic_dev->hwdev, &dcb_state); - if (err) - spnic_err(nic_dev, drv, "Failed to set dcb state\n"); - - return err; -} - -static void setup_tc_reopen_handler(struct spnic_nic_dev *nic_dev, - const void *priv_data) -{ - u8 tc = *((u8 *)priv_data); - - if (tc) { - netdev_set_num_tc(nic_dev->netdev, tc); - spnic_set_prio_tc_map(nic_dev); - - set_bit(SPNIC_DCB_ENABLE, &nic_dev->flags); - } else { - netdev_reset_tc(nic_dev->netdev); - - clear_bit(SPNIC_DCB_ENABLE, &nic_dev->flags); - } - - spnic_set_tx_cos_state(nic_dev); -} - -int spnic_setup_tc(struct net_device *netdev, u8 tc) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - struct spnic_dyna_txrxq_params q_params = {0}; - u8 cur_tc; - int err; - - if (tc && test_bit(SPNIC_SAME_RXTX, &nic_dev->flags)) { - nicif_err(nic_dev, drv, netdev, "Failed to enable DCB while Symmetric RSS is enabled\n"); - return -EOPNOTSUPP; - } - - if (tc > nic_dev->hw_dcb_cfg.max_cos) { - nicif_err(nic_dev, drv, netdev, "Invalid num_tc: %u, max tc: %u\n", - tc, nic_dev->hw_dcb_cfg.max_cos); - return -EINVAL; - } - - if (tc & (tc - 1)) { - nicif_err(nic_dev, drv, netdev, - "Invalid num_tc: %u, must be power of 2\n", tc); - return -EINVAL; - } - - if (netif_running(netdev)) { - cur_tc = nic_dev->q_params.num_tc; - q_params = nic_dev->q_params; - q_params.num_tc = tc; - q_params.txqs_res = NULL; - q_params.rxqs_res = NULL; - q_params.irq_cfg = NULL; - - nicif_info(nic_dev, drv, netdev, "Change num_tc to %u, restarting channel\n", - tc); - err = spnic_change_channel_settings(nic_dev, &q_params, setup_tc_reopen_handler, - &tc); - if (err) { - if (cur_tc != nic_dev->q_params.num_tc) { - nicif_err(nic_dev, drv, netdev, - "Restore num_tc to %u\n", cur_tc); - /* In this case, the channel resource is - * invalid, so we can safely modify the number - * of tc in netdev. - */ - nic_dev->q_params.num_tc = cur_tc; - setup_tc_reopen_handler(nic_dev, &cur_tc); - } - nicif_err(nic_dev, drv, netdev, "Failed to change channel settings\n"); - return err; - } - } else { - setup_tc_reopen_handler(nic_dev, &tc); - spnic_update_num_qps(netdev); - } - - spnic_configure_dcb(netdev); - - return 0; -} - -/* Ucode thread timeout is 210ms, must be lagger then 210ms */ -#define SPNIC_WAIT_PORT_IO_STOP 250 - -static int spnic_stop_port_traffic_flow(struct spnic_nic_dev *nic_dev, bool wait) -{ - int err = 0; - - down(&nic_dev->dcb_sem); - - if (nic_dev->disable_port_cnt++ != 0) - goto out; - - err = spnic_force_port_disable(nic_dev); - if (err) { - spnic_err(nic_dev, drv, "Failed to disable port\n"); - goto set_port_err; - } - - err = spnic_set_port_funcs_state(nic_dev->hwdev, false); - if (err) { - spnic_err(nic_dev, drv, "Failed to disable all functions in port\n"); - goto set_port_funcs_err; - } - - spnic_info(nic_dev, drv, "Stop port traffic flow\n"); - - goto out; - -set_port_funcs_err: - spnic_force_set_port_state(nic_dev, !!netif_running(nic_dev->netdev)); - -set_port_err: -out: - if (err) - nic_dev->disable_port_cnt--; - - up(&nic_dev->dcb_sem); - if (!err && wait && nic_dev->netdev->reg_state == NETREG_REGISTERED) - msleep(SPNIC_WAIT_PORT_IO_STOP); - - return err; -} - -static int spnic_start_port_traffic_flow(struct spnic_nic_dev *nic_dev) -{ - int err; - - down(&nic_dev->dcb_sem); - - nic_dev->disable_port_cnt--; - if (nic_dev->disable_port_cnt > 0) { - up(&nic_dev->dcb_sem); - return 0; - } - - nic_dev->disable_port_cnt = 0; - up(&nic_dev->dcb_sem); - - err = spnic_force_set_port_state(nic_dev, !!netif_running(nic_dev->netdev)); - if (err) - spnic_err(nic_dev, drv, "Failed to disable port\n"); - - err = spnic_set_port_funcs_state(nic_dev->hwdev, true); - if (err) - spnic_err(nic_dev, drv, "Failed to disable all functions in port\n"); - - spnic_info(nic_dev, drv, "Start port traffic flow\n"); - - return err; -} - -static u8 get_cos_settings(u8 hw_valid_cos_bitmap, u8 *dst_valid_cos_bitmap) -{ - u8 support_cos = 0; - u8 num_cos, overflow; - u8 i; - - for (i = 0; i < SPNIC_DCB_COS_MAX; i++) { - if (hw_valid_cos_bitmap & BIT(i)) - support_cos++; - } - - num_cos = (u8)(1U << (u8)ilog2(support_cos)); - if (num_cos != support_cos) { - /* Remove unused cos id */ - overflow = support_cos - num_cos; - i = SPNIC_DCB_COS_MAX - 1; - while (overflow) { - if (hw_valid_cos_bitmap & BIT(i)) { - hw_valid_cos_bitmap &= (~BIT(i)); - overflow--; - } - - i--; - } - } - - *dst_valid_cos_bitmap = hw_valid_cos_bitmap; - - return num_cos; -} - -static int get_dft_valid_up_bitmap(struct spnic_nic_dev *nic_dev, u8 num_pri, - u8 *valid_up_bitmap) -{ - bool setted = false; - u8 up_bitmap = 0; - u8 up; - int err; - - err = spnic_get_chip_up_bitmap(nic_dev->pdev, &setted, &up_bitmap); - if (err) { - spnic_err(nic_dev, drv, "Get chip cos_up map failed\n"); - return -EFAULT; - } - - if (!setted) { - /* Use (num_cos-1)~0 as default user priority */ - for (up = 0; up < num_pri; up++) - up_bitmap |= (u8)BIT(up); - } - - err = spnic_set_chip_up_bitmap(nic_dev->pdev, up_bitmap); - if (err) { - spnic_err(nic_dev, drv, "Set chip cos_up map failed\n"); - return -EFAULT; - } - - *valid_up_bitmap = up_bitmap; - - return 0; -} - -u8 spnic_get_valid_up_bitmap(struct spnic_dcb_config *dcb_cfg) -{ - u8 valid_up_bitmap = 0; - u8 i; - - for (i = 0; i < SPNIC_DCB_COS_MAX; i++) { - if (dcb_cfg->valid_cos_bitmap & BIT(i)) - valid_up_bitmap |= (u8)BIT(dcb_cfg->cos_cfg[i].up); - } - - return valid_up_bitmap; -} - -static void update_valid_up_bitmap(struct spnic_dcb_config *dcb_cfg, - u8 valid_up_bitmap) -{ - u8 i, up; - - for (i = 0; i < SPNIC_DCB_COS_MAX; i++) { - if (!(dcb_cfg->valid_cos_bitmap & BIT(i))) { - dcb_cfg->cos_cfg[i].up = 0; - continue; - } - - /* get the highest priority */ - up = (u8)fls(valid_up_bitmap) - 1; - valid_up_bitmap &= (~BIT(up)); - - dcb_cfg->cos_cfg[i].up = up; - } -} - -static int init_default_dcb_cfg(struct spnic_nic_dev *nic_dev, - struct spnic_dcb_config *dcb_cfg) -{ - struct spnic_cos_cfg *cos_cfg = dcb_cfg->cos_cfg; - struct spnic_tc_cfg *tc_cfg = dcb_cfg->tc_cfg; - u8 valid_cos_bitmap, i; - u8 valid_up_bitmap = 0; - int err; - - valid_cos_bitmap = sphw_cos_valid_bitmap(nic_dev->hwdev); - if (!valid_cos_bitmap) { - spnic_err(nic_dev, drv, "None cos supported\n"); - return -EFAULT; - } - - dcb_cfg->max_cos = get_cos_settings(valid_cos_bitmap, - &dcb_cfg->valid_cos_bitmap); - dcb_cfg->default_cos = (u8)fls(dcb_cfg->valid_cos_bitmap) - 1; - - err = get_dft_valid_up_bitmap(nic_dev, dcb_cfg->max_cos, - &valid_up_bitmap); - if (err) - return err; - - for (i = 0; i < SPNIC_DCB_COS_MAX; i++) { - /* set all cos with 100 percent bw in default */ - cos_cfg[i].bw_pct = MAX_BW_PERCENT; - cos_cfg[i].prio_sp = 0; /* DWRR */ - cos_cfg[i].tc_id = 0; /* all cos mapping to tc0 */ - cos_cfg[i].up = 0; - } - - update_valid_up_bitmap(dcb_cfg, valid_up_bitmap); - - for (i = 0; i < SPNIC_DCB_TC_MAX; i++) { - /* tc0 with 100 percent bw in default */ - tc_cfg[i].bw_pct = (i == 0) ? MAX_BW_PERCENT : 0; - tc_cfg[i].prio_sp = 0; /* DWRR */ - } - - /* disable pfc */ - dcb_cfg->pfc_state = 0; - dcb_cfg->pfc_en_bitmap = 0; - - return 0; -} - -int spnic_dcb_init(struct spnic_nic_dev *nic_dev) -{ - struct spnic_dcb_config *dcb_cfg = &nic_dev->wanted_dcb_cfg; - int err; - - if (SPNIC_FUNC_IS_VF(nic_dev->hwdev)) - return spnic_set_tx_cos_state(nic_dev); - - err = init_default_dcb_cfg(nic_dev, dcb_cfg); - if (err) { - spnic_err(nic_dev, drv, "Initialize dcb configuration failed\n"); - return err; - } - - spnic_info(nic_dev, drv, "Support num cos %u, default cos %u\n", - dcb_cfg->max_cos, dcb_cfg->default_cos); - - nic_dev->dcb_changes = DCB_CFG_CHG_ETS | DCB_CFG_CHG_PFC | - DCB_CFG_CHG_UP_COS; - - memcpy(&nic_dev->hw_dcb_cfg, &nic_dev->wanted_dcb_cfg, - sizeof(nic_dev->hw_dcb_cfg)); - - err = spnic_set_tx_cos_state(nic_dev); - if (err) { - spnic_err(nic_dev, drv, "Set tx cos state failed\n"); - return err; - } - - sema_init(&nic_dev->dcb_sem, 1); - - return 0; -} - -u32 spnic_sync_dcb_cfg(struct spnic_nic_dev *nic_dev, struct spnic_dcb_config *src_dcb_cfg) -{ - struct spnic_dcb_config *wanted_cfg = src_dcb_cfg; - struct spnic_dcb_config *hw_cfg = &nic_dev->hw_dcb_cfg; - u32 changes = 0; - - if (memcmp(hw_cfg->cos_cfg, wanted_cfg->cos_cfg, - sizeof(hw_cfg->cos_cfg))) { - memcpy(hw_cfg->cos_cfg, wanted_cfg->cos_cfg, - sizeof(hw_cfg->cos_cfg)); - changes |= DCB_CFG_CHG_ETS; - } - - if (memcmp(hw_cfg->tc_cfg, wanted_cfg->tc_cfg, - sizeof(hw_cfg->tc_cfg))) { - memcpy(hw_cfg->tc_cfg, wanted_cfg->tc_cfg, - sizeof(hw_cfg->tc_cfg)); - changes |= DCB_CFG_CHG_ETS; - } - - if (hw_cfg->pfc_state != wanted_cfg->pfc_state || - (wanted_cfg->pfc_state && - hw_cfg->pfc_en_bitmap != wanted_cfg->pfc_en_bitmap)) { - hw_cfg->pfc_state = wanted_cfg->pfc_state; - hw_cfg->pfc_en_bitmap = wanted_cfg->pfc_en_bitmap; - changes |= DCB_CFG_CHG_PFC; - } - - return changes; -} - -static int dcbcfg_set_hw_cos_up_map(struct spnic_nic_dev *nic_dev, - struct spnic_dcb_config *dcb_cfg) -{ - u8 cos_up_map[SPNIC_DCB_COS_MAX] = {0}; - int err; - u8 i; - - for (i = 0; i < SPNIC_DCB_COS_MAX; i++) { - if (!(dcb_cfg->valid_cos_bitmap & BIT(i))) - continue; - - cos_up_map[i] = dcb_cfg->cos_cfg[i].up; - } - - err = spnic_dcb_set_cos_up_map(nic_dev->hwdev, dcb_cfg->valid_cos_bitmap, - cos_up_map, SPNIC_DCB_COS_MAX); - if (err) - spnic_err(nic_dev, drv, "Set cos_up map failed\n"); - - return err; -} - -/* The sum of the cos bandwidth mapped to the same TC is 100 */ -static void adjust_cos_bw(u8 valid_cos_bitmap, u8 *cos_tc, u8 *cos_bw) -{ - u8 tc, cos, cos_num; - u16 bw_all, bw_remain; - - for (tc = 0; tc < SPNIC_DCB_TC_MAX; tc++) { - bw_all = 0; - cos_num = 0; - for (cos = 0; cos < SPNIC_DCB_COS_MAX; cos++) { - if (!(valid_cos_bitmap & BIT(cos)) || cos_tc[cos] != tc) - continue; - bw_all += cos_bw[cos]; - cos_num++; - } - - if (!bw_all || !cos_num) - continue; - - bw_remain = MAX_BW_PERCENT % cos_num; - for (cos = 0; cos < SPNIC_DCB_COS_MAX; cos++) { - if (!(valid_cos_bitmap & BIT(cos)) || cos_tc[cos] != tc) - continue; - - cos_bw[cos] = - (u8)(MAX_BW_PERCENT * cos_bw[cos] / bw_all); - - if (bw_remain) { - cos_bw[cos]++; - bw_remain--; - } - } - } -} - -static void dcbcfg_dump_configuration(struct spnic_nic_dev *nic_dev, - u8 *cos_tc, u8 *cos_bw, u8 *cos_prio, - u8 *tc_bw, u8 *tc_prio) -{ - u8 i; - - for (i = 0; i < SPNIC_DCB_COS_MAX; i++) { - if (!(nic_dev->hw_dcb_cfg.valid_cos_bitmap & BIT(i))) - continue; - - spnic_info(nic_dev, drv, "cos: %u, up: %u, tc: %u, bw: %u, prio: %u\n", - i, nic_dev->hw_dcb_cfg.cos_cfg[i].up, cos_tc[i], - cos_bw[i], cos_prio[i]); - } - - for (i = 0; i < nic_dev->hw_dcb_cfg.max_cos; i++) - spnic_info(nic_dev, drv, "tc: %u, bw: %u, prio: %u\n", - i, tc_bw[i], tc_prio[i]); -} - -static int dcbcfg_set_hw_ets(struct spnic_nic_dev *nic_dev, - struct spnic_dcb_config *dcb_cfg) -{ - u8 cos_tc[SPNIC_DCB_COS_MAX] = {0}; - u8 cos_bw[SPNIC_DCB_COS_MAX] = {0}; - u8 cos_prio[SPNIC_DCB_COS_MAX] = {0}; - u8 tc_bw[SPNIC_DCB_TC_MAX] = {0}; - u8 tc_prio[SPNIC_DCB_TC_MAX] = {0}; - int err; - u8 i; - - for (i = 0; i < SPNIC_DCB_COS_MAX; i++) { - if (!(dcb_cfg->valid_cos_bitmap & BIT(i))) - continue; - - cos_tc[i] = dcb_cfg->cos_cfg[i].tc_id; - cos_bw[i] = dcb_cfg->cos_cfg[i].bw_pct; - cos_prio[i] = dcb_cfg->cos_cfg[i].prio_sp; - } - - for (i = 0; i < SPNIC_DCB_TC_MAX; i++) { - tc_bw[i] = dcb_cfg->tc_cfg[i].bw_pct; - tc_prio[i] = dcb_cfg->tc_cfg[i].prio_sp; - } - - adjust_cos_bw(dcb_cfg->valid_cos_bitmap, cos_tc, cos_bw); - - if (test_bit(SPNIC_DCB_ENABLE, &nic_dev->flags)) - dcbcfg_dump_configuration(nic_dev, cos_tc, cos_bw, cos_prio, tc_bw, tc_prio); - - err = spnic_dcb_set_ets(nic_dev->hwdev, cos_tc, cos_bw, cos_prio, tc_bw, tc_prio); - if (err) { - spnic_err(nic_dev, drv, "Failed to set ets\n"); - return err; - } - - return 0; -} - -static int dcbcfg_set_hw_pfc(struct spnic_nic_dev *nic_dev, - struct spnic_dcb_config *dcb_cfg) -{ - u8 valid_up_bitmap = spnic_get_valid_up_bitmap(dcb_cfg); - u8 outof_range_pfc = (~valid_up_bitmap) & dcb_cfg->pfc_en_bitmap; - int err; - - if (dcb_cfg->pfc_state && outof_range_pfc) - spnic_info(nic_dev, drv, "PFC setting out of range, 0x%x will be ignored\n", - outof_range_pfc); - - err = spnic_dcb_set_pfc(nic_dev->hwdev, dcb_cfg->pfc_state, dcb_cfg->pfc_en_bitmap); - if (err) { - spnic_err(nic_dev, drv, "Failed to %s PFC\n", - dcb_cfg->pfc_state ? "enable" : "disable"); - return err; - } - - if (dcb_cfg->pfc_state) - spnic_info(nic_dev, drv, "Set PFC: 0x%x to hw done\n", - dcb_cfg->pfc_en_bitmap & valid_up_bitmap); - else - spnic_info(nic_dev, drv, "Disable PFC, enable tx/rx pause\n"); - - return 0; -} - -int spnic_dcbcfg_setall_to_hw(struct spnic_nic_dev *nic_dev, struct spnic_dcb_config *src_dcb_cfg) -{ - bool stop_traffic = false; - int err = 0; - - nic_dev->dcb_changes |= spnic_sync_dcb_cfg(nic_dev, src_dcb_cfg); - if (!nic_dev->dcb_changes) - return 0; - - /* hw does not support to change up cos mapping and cos tc mapping with - * traffic flow - */ - stop_traffic = !!(nic_dev->dcb_changes & - (DCB_CFG_CHG_ETS | DCB_CFG_CHG_UP_COS)); - if (stop_traffic) { - err = spnic_stop_port_traffic_flow(nic_dev, true); - if (err) - return err; - } - - if (nic_dev->dcb_changes & DCB_CFG_CHG_UP_COS) { - err = dcbcfg_set_hw_cos_up_map(nic_dev, &nic_dev->hw_dcb_cfg); - if (err) - goto out; - - nic_dev->dcb_changes &= (~DCB_CFG_CHG_UP_COS); - } - - if (nic_dev->dcb_changes & DCB_CFG_CHG_ETS) { - err = dcbcfg_set_hw_ets(nic_dev, &nic_dev->hw_dcb_cfg); - if (err) - goto out; - - nic_dev->dcb_changes &= (~DCB_CFG_CHG_ETS); - } - - if (nic_dev->dcb_changes & DCB_CFG_CHG_PFC) { - err = dcbcfg_set_hw_pfc(nic_dev, &nic_dev->hw_dcb_cfg); - if (err) - goto out; - - nic_dev->dcb_changes &= (~DCB_CFG_CHG_PFC); - } - -out: - if (stop_traffic) - spnic_start_port_traffic_flow(nic_dev); - - return err; -} - -int spnic_dcb_reset_hw_config(struct spnic_nic_dev *nic_dev) -{ - struct spnic_dcb_config dft_cfg = {0}; - int err; - - init_default_dcb_cfg(nic_dev, &dft_cfg); - err = spnic_dcbcfg_setall_to_hw(nic_dev, &dft_cfg); - if (err) { - spnic_err(nic_dev, drv, "Failed to reset hw dcb configuration\n"); - return err; - } - - spnic_info(nic_dev, drv, "Reset hardware DCB configuration done\n"); - - return 0; -} - -int spnic_configure_dcb(struct net_device *netdev) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - - if (test_bit(SPNIC_DCB_ENABLE, &nic_dev->flags)) - return spnic_dcbcfg_setall_to_hw(nic_dev, &nic_dev->wanted_dcb_cfg); - else - return spnic_dcb_reset_hw_config(nic_dev); -} - -void spnic_dcbcfg_set_pfc_state(struct spnic_nic_dev *nic_dev, u8 pfc_state) -{ - nic_dev->wanted_dcb_cfg.pfc_state = pfc_state; -} - -u8 spnic_dcbcfg_get_pfc_state(struct spnic_nic_dev *nic_dev) -{ - return nic_dev->wanted_dcb_cfg.pfc_state; -} - -void spnic_dcbcfg_set_pfc_pri_en(struct spnic_nic_dev *nic_dev, u8 pfc_en_bitmap) -{ - nic_dev->wanted_dcb_cfg.pfc_en_bitmap = pfc_en_bitmap; -} - -u8 spnic_dcbcfg_get_pfc_pri_en(struct spnic_nic_dev *nic_dev) -{ - return nic_dev->wanted_dcb_cfg.pfc_en_bitmap; -} - -int spnic_dcbcfg_set_ets_up_tc_map(struct spnic_nic_dev *nic_dev, const u8 *up_tc_map) -{ - struct spnic_dcb_config *dcb_cfg = &nic_dev->wanted_dcb_cfg; - u8 i; - - for (i = 0; i < SPNIC_DCB_UP_MAX; i++) { - if (!(dcb_cfg->valid_cos_bitmap & BIT(i))) - continue; - - /* TC id can't exceed max cos */ - if (up_tc_map[dcb_cfg->cos_cfg[i].up] >= dcb_cfg->max_cos) - return -EINVAL; - } - - for (i = 0; i < SPNIC_DCB_UP_MAX; i++) { - if (!(dcb_cfg->valid_cos_bitmap & BIT(i))) - continue; - - dcb_cfg->cos_cfg[i].tc_id = up_tc_map[dcb_cfg->cos_cfg[i].up]; - } - - return 0; -} - -void spnic_dcbcfg_get_ets_up_tc_map(struct spnic_nic_dev *nic_dev, u8 *up_tc_map) -{ - struct spnic_dcb_config *dcb_cfg = &nic_dev->wanted_dcb_cfg; - struct spnic_cos_cfg *cos_cfg = dcb_cfg->cos_cfg; - u8 i; - - /* set unused up mapping to default tc */ - memset(up_tc_map, cos_cfg[dcb_cfg->default_cos].tc_id, - SPNIC_DCB_UP_MAX); - - for (i = 0; i < SPNIC_DCB_COS_MAX; i++) { - if (!(dcb_cfg->valid_cos_bitmap & BIT(i))) - continue; - - up_tc_map[cos_cfg[i].up] = cos_cfg[i].tc_id; - } -} - -int spnic_dcbcfg_set_ets_tc_bw(struct spnic_nic_dev *nic_dev, const u8 *tc_bw) -{ - struct spnic_dcb_config *dcb_cfg = &nic_dev->wanted_dcb_cfg; - u8 bw_sum = 0; - u8 i; - - for (i = 0; i < SPNIC_DCB_TC_MAX; i++) { - /* cannot set bandwidth for unused tc */ - if (i >= dcb_cfg->max_cos && tc_bw[i] > 0) - return -EINVAL; - - bw_sum += tc_bw[i]; - } - - if (bw_sum != MAX_BW_PERCENT && bw_sum != 0) { - spnic_err(nic_dev, drv, "Invalid total bw %u\n", bw_sum); - return -EINVAL; - } - - for (i = 0; i < dcb_cfg->max_cos; i++) - dcb_cfg->tc_cfg[i].bw_pct = tc_bw[i]; - - return 0; -} - -void spnic_dcbcfg_get_ets_tc_bw(struct spnic_nic_dev *nic_dev, u8 *tc_bw) -{ - struct spnic_dcb_config *dcb_cfg = &nic_dev->wanted_dcb_cfg; - u8 i; - - for (i = 0; i < dcb_cfg->max_cos; i++) - tc_bw[i] = dcb_cfg->tc_cfg[i].bw_pct; -} - -void spnic_dcbcfg_set_ets_tc_prio_type(struct spnic_nic_dev *nic_dev, u8 tc_prio_bitmap) -{ - struct spnic_dcb_config *dcb_cfg = &nic_dev->wanted_dcb_cfg; - u8 i; - - for (i = 0; i < dcb_cfg->max_cos; i++) - dcb_cfg->tc_cfg[i].prio_sp = !!(tc_prio_bitmap & BIT(i)); -} - -void spnic_dcbcfg_get_ets_tc_prio_type(struct spnic_nic_dev *nic_dev, u8 *tc_prio_bitmap) -{ - struct spnic_dcb_config *dcb_cfg = &nic_dev->wanted_dcb_cfg; - u8 i; - - *tc_prio_bitmap = 0; - for (i = 0; i < dcb_cfg->max_cos; i++) { - if (dcb_cfg->tc_cfg[i].prio_sp) - *tc_prio_bitmap |= (u8)BIT(i); - } -} - -/* TODO: send a command to MPU, and MPU close all port traffic */ -static int stop_all_ports_flow(void *uld_array[], u32 num_dev) -{ - struct spnic_nic_dev *tmp_dev = NULL; - u32 i, idx; - int err; - - for (idx = 0; idx < num_dev; idx++) { - tmp_dev = (struct spnic_nic_dev *)uld_array[idx]; - err = spnic_stop_port_traffic_flow(tmp_dev, false); - if (err) { - nicif_err(tmp_dev, drv, tmp_dev->netdev, "Stop port traffic flow failed\n"); - goto stop_port_err; - } - } - - /* wait all traffic flow stopped */ - msleep(SPNIC_WAIT_PORT_IO_STOP); - - return 0; - -stop_port_err: - for (i = 0; i < idx; i++) { - tmp_dev = (struct spnic_nic_dev *)uld_array[i]; - spnic_start_port_traffic_flow(tmp_dev); - } - - return err; -} - -static void start_all_ports_flow(void *uld_array[], u32 num_dev) -{ - struct spnic_nic_dev *tmp_dev = NULL; - u32 idx; - - for (idx = 0; idx < num_dev; idx++) { - tmp_dev = (struct spnic_nic_dev *)uld_array[idx]; - spnic_start_port_traffic_flow(tmp_dev); - } -} - -int change_dev_cos_up_map(struct spnic_nic_dev *nic_dev, u8 valid_up_bitmap) -{ - struct net_device *netdev = nic_dev->netdev; - int err = 0; - - if (test_and_set_bit(SPNIC_DCB_UP_COS_SETTING, &nic_dev->dcb_flags)) { - nicif_warn(nic_dev, drv, netdev, - "Cos_up map setting in inprocess, please try again later\n"); - return -EFAULT; - } - - if (spnic_get_valid_up_bitmap(&nic_dev->wanted_dcb_cfg) == - valid_up_bitmap) { - nicif_err(nic_dev, drv, netdev, "Same up bitmap, don't need to change anything\n"); - err = 0; - goto out; - } - - nicif_info(nic_dev, drv, netdev, "Set valid_up_bitmap: 0x%x\n", - valid_up_bitmap); - - update_valid_up_bitmap(&nic_dev->wanted_dcb_cfg, valid_up_bitmap); - - nic_dev->dcb_changes = DCB_CFG_CHG_ETS | DCB_CFG_CHG_PFC | DCB_CFG_CHG_UP_COS; - - if (test_bit(SPNIC_DCB_ENABLE, &nic_dev->flags)) { - err = spnic_dcbcfg_setall_to_hw(nic_dev, &nic_dev->wanted_dcb_cfg); - if (err) { - nicif_err(nic_dev, drv, netdev, "Reconfig dcb to hw failed\n"); - goto out; - } - - /* Change up/tc map for netdev */ - spnic_set_prio_tc_map(nic_dev); - spnic_update_tx_db_cos(nic_dev); - } - - err = spnic_set_tx_cos_state(nic_dev); - -out: - clear_bit(SPNIC_DCB_UP_COS_SETTING, &nic_dev->dcb_flags); - - return err; -} - -int spnic_dcbcfg_set_up_bitmap(struct spnic_nic_dev *nic_dev, u8 valid_up_bitmap) -{ - struct spnic_nic_dev *tmp_dev = NULL; - void **uld_array = NULL; - u32 i, idx, num_dev = 0; - int err, rollback_err; - bool up_setted = false; - u8 old_valid_up_bitmap = 0; - u8 max_pf; - - /* Save old valid up bitmap, in case of set failed */ - err = spnic_get_chip_up_bitmap(nic_dev->pdev, &up_setted, &old_valid_up_bitmap); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Get old chip valid up bitmap failed\n"); - return -EFAULT; - } - - if (valid_up_bitmap == old_valid_up_bitmap) { - nicif_info(nic_dev, drv, nic_dev->netdev, "Same valid up bitmap, don't need to change anything\n"); - return 0; - } - - max_pf = sphw_max_pf_num(nic_dev->hwdev); - if (!max_pf) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Invalid max pf number\n"); - return -EFAULT; - } - - uld_array = kcalloc(max_pf, sizeof(void *), GFP_KERNEL); - if (!uld_array) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to alloc uld_array\n"); - return -ENOMEM; - } - - /* Get all pf of this chip */ - err = spnic_get_pf_nic_uld_array(nic_dev->pdev, &num_dev, uld_array); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Get all pf private handle failed\n"); - err = -EFAULT; - goto out; - } - - err = stop_all_ports_flow(uld_array, num_dev); - if (err) - goto out; - - for (idx = 0; idx < num_dev; idx++) { - tmp_dev = (struct spnic_nic_dev *)uld_array[idx]; - err = change_dev_cos_up_map(tmp_dev, valid_up_bitmap); - if (err) { - nicif_err(tmp_dev, drv, tmp_dev->netdev, "Set cos_up map to hw failed\n"); - goto set_err; - } - } - - start_all_ports_flow(uld_array, num_dev); - - spnic_set_chip_up_bitmap(nic_dev->pdev, valid_up_bitmap); - kfree(uld_array); - - return 0; - -set_err: - /* undo all settings */ - for (i = 0; i <= idx; i++) { - tmp_dev = (struct spnic_nic_dev *)uld_array[i]; - rollback_err = change_dev_cos_up_map(tmp_dev, old_valid_up_bitmap); - if (rollback_err) - nicif_err(tmp_dev, drv, tmp_dev->netdev, "Failed to rollback cos_up map to hw\n"); - } - - start_all_ports_flow(uld_array, num_dev); - -out: - kfree(uld_array); - - return err; -} diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_dcb.h b/drivers/net/ethernet/ramaxel/spnic/spnic_dcb.h deleted file mode 100644 index 48ef471237e2..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_dcb.h +++ /dev/null @@ -1,56 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPNIC_DCB_H -#define SPNIC_DCB_H - -enum SPNIC_DCB_FLAGS { - SPNIC_DCB_UP_COS_SETTING, - SPNIC_DCB_TRAFFIC_STOPPED, -}; - -struct spnic_cos_cfg { - u8 up; - u8 bw_pct; - u8 tc_id; - u8 prio_sp; /* 0 - DWRR, 1 - SP */ -}; - -struct spnic_tc_cfg { - u8 bw_pct; - u8 prio_sp; /* 0 - DWRR, 1 - SP */ - u16 rsvd; -}; - -struct spnic_dcb_config { - /* The num_tc of the protocol stack is also the same */ - u8 max_cos; - u8 default_cos; - u8 valid_cos_bitmap; - u8 rsvd1; - struct spnic_cos_cfg cos_cfg[SPNIC_DCB_COS_MAX]; - struct spnic_tc_cfg tc_cfg[SPNIC_DCB_TC_MAX]; - - u8 pfc_state; - u8 pfc_en_bitmap; - u16 rsvd2; -}; - -int spnic_dcb_init(struct spnic_nic_dev *nic_dev); -int spnic_dcb_reset_hw_config(struct spnic_nic_dev *nic_dev); -int spnic_configure_dcb(struct net_device *netdev); -int spnic_setup_tc(struct net_device *netdev, u8 tc); -u8 spnic_get_valid_up_bitmap(struct spnic_dcb_config *dcb_cfg); -void spnic_dcbcfg_set_pfc_state(struct spnic_nic_dev *nic_dev, u8 pfc_state); -u8 spnic_dcbcfg_get_pfc_state(struct spnic_nic_dev *nic_dev); -void spnic_dcbcfg_set_pfc_pri_en(struct spnic_nic_dev *nic_dev, u8 pfc_en_bitmap); -u8 spnic_dcbcfg_get_pfc_pri_en(struct spnic_nic_dev *nic_dev); -int spnic_dcbcfg_set_ets_up_tc_map(struct spnic_nic_dev *nic_dev, const u8 *up_tc_map); -void spnic_dcbcfg_get_ets_up_tc_map(struct spnic_nic_dev *nic_dev, u8 *up_tc_map); -int spnic_dcbcfg_set_ets_tc_bw(struct spnic_nic_dev *nic_dev, const u8 *tc_bw); -void spnic_dcbcfg_get_ets_tc_bw(struct spnic_nic_dev *nic_dev, u8 *tc_bw); -void spnic_dcbcfg_set_ets_tc_prio_type(struct spnic_nic_dev *nic_dev, u8 tc_prio_bitmap); -void spnic_dcbcfg_get_ets_tc_prio_type(struct spnic_nic_dev *nic_dev, u8 *tc_prio_bitmap); -int spnic_dcbcfg_set_up_bitmap(struct spnic_nic_dev *nic_dev, u8 valid_up_bitmap); -void spnic_update_tx_db_cos(struct spnic_nic_dev *nic_dev); -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_dev_mgmt.c b/drivers/net/ethernet/ramaxel/spnic/spnic_dev_mgmt.c deleted file mode 100644 index 6037645c0e8b..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_dev_mgmt.c +++ /dev/null @@ -1,811 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [COMM]" fmt - -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/device.h> -#include <linux/module.h> -#include <linux/io-mapping.h> -#include <linux/interrupt.h> -#include <net/addrconf.h> -#include <linux/time.h> -#include <linux/timex.h> -#include <linux/rtc.h> -#include <linux/debugfs.h> - -#include "sphw_common.h" -#include "sphw_mt.h" -#include "sphw_crm.h" -#include "spnic_lld.h" -#include "spnic_sriov.h" -#include "spnic_pci_id_tbl.h" -#include "spnic_dev_mgmt.h" - -#define SPNIC_WAIT_TOOL_CNT_TIMEOUT 10000 -#define SPNIC_WAIT_TOOL_MIN_USLEEP_TIME 9900 -#define SPNIC_WAIT_TOOL_MAX_USLEEP_TIME 10000 - -#define MAX_CARD_ID 64 -static unsigned long card_bit_map; - -LIST_HEAD(g_spnic_chip_list); - -void lld_dev_cnt_init(struct spnic_pcidev *pci_adapter) -{ - atomic_set(&pci_adapter->ref_cnt, 0); -} - -void lld_dev_hold(struct spnic_lld_dev *dev) -{ - struct spnic_pcidev *pci_adapter = pci_get_drvdata(dev->pdev); - - atomic_inc(&pci_adapter->ref_cnt); -} - -void lld_dev_put(struct spnic_lld_dev *dev) -{ - struct spnic_pcidev *pci_adapter = pci_get_drvdata(dev->pdev); - - atomic_dec(&pci_adapter->ref_cnt); -} - -void wait_lld_dev_unused(struct spnic_pcidev *pci_adapter) -{ - unsigned long end; - - end = jiffies + msecs_to_jiffies(SPNIC_WAIT_TOOL_CNT_TIMEOUT); - do { - if (!atomic_read(&pci_adapter->ref_cnt)) - return; - - /* if sleep 10ms, use usleep_range to be more precise */ - usleep_range(SPNIC_WAIT_TOOL_MIN_USLEEP_TIME, - SPNIC_WAIT_TOOL_MAX_USLEEP_TIME); - } while (time_before(jiffies, end)); -} - -enum spnic_lld_status { - SPNIC_NODE_CHANGE = BIT(0), -}; - -struct spnic_lld_lock { - /* lock for chip list */ - struct mutex lld_mutex; - unsigned long status; - atomic_t dev_ref_cnt; -}; - -struct spnic_lld_lock g_lld_lock; - -#define WAIT_LLD_DEV_HOLD_TIMEOUT (10 * 60 * 1000) /* 10minutes */ -#define WAIT_LLD_DEV_NODE_CHANGED (10 * 60 * 1000) /* 10minutes */ -#define WAIT_LLD_DEV_REF_CNT_EMPTY (2 * 60 * 1000) /* 2minutes */ -#define PRINT_TIMEOUT_INTERVAL 10000 -#define MS_PER_SEC 1000 -#define LLD_LOCK_MIN_USLEEP_TIME 900 -#define LLD_LOCK_MAX_USLEEP_TIME 1000 - -/* node in chip_node will changed, tools or driver can't get node - * during this situation - */ -void lld_lock_chip_node(void) -{ - unsigned long end; - bool timeout = true; - u32 loop_cnt; - - mutex_lock(&g_lld_lock.lld_mutex); - - loop_cnt = 0; - end = jiffies + msecs_to_jiffies(WAIT_LLD_DEV_NODE_CHANGED); - do { - if (!test_and_set_bit(SPNIC_NODE_CHANGE, &g_lld_lock.status)) { - timeout = false; - break; - } - - loop_cnt++; - if (loop_cnt % PRINT_TIMEOUT_INTERVAL == 0) - pr_warn("Wait for lld node change complete for %us\n", - loop_cnt / MS_PER_SEC); - - /* if sleep 1ms, use usleep_range to be more precise */ - usleep_range(LLD_LOCK_MIN_USLEEP_TIME, - LLD_LOCK_MAX_USLEEP_TIME); - } while (time_before(jiffies, end)); - - if (timeout && test_and_set_bit(SPNIC_NODE_CHANGE, &g_lld_lock.status)) - pr_warn("Wait for lld node change complete timeout when trying to get lld lock\n"); - - loop_cnt = 0; - timeout = true; - end = jiffies + msecs_to_jiffies(WAIT_LLD_DEV_NODE_CHANGED); - do { - if (!atomic_read(&g_lld_lock.dev_ref_cnt)) { - timeout = false; - break; - } - - loop_cnt++; - if (loop_cnt % PRINT_TIMEOUT_INTERVAL == 0) - pr_warn("Wait for lld dev unused for %us, reference count: %d\n", - loop_cnt / MS_PER_SEC, - atomic_read(&g_lld_lock.dev_ref_cnt)); - - /* if sleep 1ms, use usleep_range to be more precise */ - usleep_range(LLD_LOCK_MIN_USLEEP_TIME, - LLD_LOCK_MAX_USLEEP_TIME); - } while (time_before(jiffies, end)); - - if (timeout && atomic_read(&g_lld_lock.dev_ref_cnt)) - pr_warn("Wait for lld dev unused timeout\n"); - - mutex_unlock(&g_lld_lock.lld_mutex); -} - -void lld_unlock_chip_node(void) -{ - clear_bit(SPNIC_NODE_CHANGE, &g_lld_lock.status); -} - -/* When tools or other drivers want to get node of chip_node, use this function - * to prevent node be freed - */ -void lld_hold(void) -{ - unsigned long end; - u32 loop_cnt = 0; - - /* ensure there have not any chip node in changing */ - mutex_lock(&g_lld_lock.lld_mutex); - - end = jiffies + msecs_to_jiffies(WAIT_LLD_DEV_HOLD_TIMEOUT); - do { - if (!test_bit(SPNIC_NODE_CHANGE, &g_lld_lock.status)) - break; - - loop_cnt++; - - if (loop_cnt % PRINT_TIMEOUT_INTERVAL == 0) - pr_warn("Wait lld node change complete for %us\n", - loop_cnt / MS_PER_SEC); - /* if sleep 1ms, use usleep_range to be more precise */ - usleep_range(LLD_LOCK_MIN_USLEEP_TIME, - LLD_LOCK_MAX_USLEEP_TIME); - } while (time_before(jiffies, end)); - - if (test_bit(SPNIC_NODE_CHANGE, &g_lld_lock.status)) - pr_warn("Wait lld node change complete timeout when trying to hode lld dev\n"); - - atomic_inc(&g_lld_lock.dev_ref_cnt); - mutex_unlock(&g_lld_lock.lld_mutex); -} - -void lld_put(void) -{ - atomic_dec(&g_lld_lock.dev_ref_cnt); -} - -void spnic_lld_lock_init(void) -{ - mutex_init(&g_lld_lock.lld_mutex); - atomic_set(&g_lld_lock.dev_ref_cnt, 0); -} - -void spnic_get_all_chip_id(void *id_info) -{ - struct nic_card_id *card_id = (struct nic_card_id *)id_info; - struct card_node *chip_node = NULL; - int i = 0; - int id, err; - - lld_hold(); - list_for_each_entry(chip_node, &g_spnic_chip_list, node) { - err = sscanf(chip_node->chip_name, SPHW_CHIP_NAME "%d", &id); - if (err < 0) - pr_err("Failed to get spnic id\n"); - card_id->id[i] = id; - i++; - } - lld_put(); - card_id->num = i; -} - -void spnic_get_card_func_info_by_card_name(const char *chip_name, - struct sphw_card_func_info *card_func) -{ - struct card_node *chip_node = NULL; - struct spnic_pcidev *dev = NULL; - struct func_pdev_info *pdev_info = NULL; - - card_func->num_pf = 0; - - lld_hold(); - - list_for_each_entry(chip_node, &g_spnic_chip_list, node) { - if (strncmp(chip_node->chip_name, chip_name, IFNAMSIZ)) - continue; - - list_for_each_entry(dev, &chip_node->func_list, node) { - if (sphw_func_type(dev->hwdev) == TYPE_VF) - continue; - - pdev_info = &card_func->pdev_info[card_func->num_pf]; - pdev_info->bar1_size = - pci_resource_len(dev->pcidev, SPNIC_PF_PCI_CFG_REG_BAR); - pdev_info->bar1_phy_addr = - pci_resource_start(dev->pcidev, SPNIC_PF_PCI_CFG_REG_BAR); - - pdev_info->bar3_size = - pci_resource_len(dev->pcidev, SPNIC_PCI_MGMT_REG_BAR); - pdev_info->bar3_phy_addr = - pci_resource_start(dev->pcidev, SPNIC_PCI_MGMT_REG_BAR); - - card_func->num_pf++; - if (card_func->num_pf >= CARD_MAX_SIZE) { - lld_put(); - return; - } - } - } - - lld_put(); -} - -static bool is_pcidev_match_chip_name(const char *ifname, struct spnic_pcidev *dev, - struct card_node *chip_node, enum func_type type) -{ - if (!strncmp(chip_node->chip_name, ifname, IFNAMSIZ)) { - if (sphw_func_type(dev->hwdev) != type) - return false; - return true; - } - - return false; -} - -static struct spnic_lld_dev *_get_lld_dev_by_chip_name(const char *ifname, enum func_type type) -{ - struct card_node *chip_node = NULL; - struct spnic_pcidev *dev = NULL; - - lld_hold(); - - list_for_each_entry(chip_node, &g_spnic_chip_list, node) { - list_for_each_entry(dev, &chip_node->func_list, node) { - if (is_pcidev_match_chip_name(ifname, dev, chip_node, type)) { - lld_put(); - return &dev->lld_dev; - } - } - } - - lld_put(); - return NULL; -} - -static struct spnic_lld_dev *spnic_get_lld_dev_by_chip_name(const char *ifname) -{ - struct spnic_lld_dev *dev_hw_init = NULL; - struct spnic_lld_dev *dev = NULL; - - /*find hw init device first*/ - dev_hw_init = _get_lld_dev_by_chip_name(ifname, TYPE_UNKNOWN); - if (dev_hw_init) { - if (sphw_func_type(dev_hw_init->hwdev) == TYPE_PPF) - return dev_hw_init; - } - - dev = _get_lld_dev_by_chip_name(ifname, TYPE_PPF); - if (dev) { - if (dev_hw_init) - return dev_hw_init; - - return dev; - } - - dev = _get_lld_dev_by_chip_name(ifname, TYPE_PF); - if (dev) { - if (dev_hw_init) - return dev_hw_init; - - return dev; - } - - dev = _get_lld_dev_by_chip_name(ifname, TYPE_VF); - if (dev) - return dev; - - return NULL; -} - -static bool is_pcidev_match_dev_name(const char *ifname, struct spnic_pcidev *dev, - enum sphw_service_type type) -{ - enum sphw_service_type i; - char nic_uld_name[IFNAMSIZ] = {0}; - int err; - - if (type == SERVICE_T_MAX) { - for (i = SERVICE_T_OVS; i < SERVICE_T_MAX; i++) { - if (!strncmp(dev->uld_dev_name[i], ifname, IFNAMSIZ)) - return true; - } - } else { - if (!strncmp(dev->uld_dev_name[type], ifname, IFNAMSIZ)) - return true; - } - - err = spnic_get_uld_dev_name(dev, SERVICE_T_NIC, (char *)nic_uld_name); - if (!err) { - if (!strncmp(nic_uld_name, ifname, IFNAMSIZ)) - return true; - } - - return false; -} - -static struct spnic_lld_dev *spnic_get_lld_dev_by_dev_name(const char *ifname, - enum sphw_service_type type) -{ - struct card_node *chip_node = NULL; - struct spnic_pcidev *dev = NULL; - - lld_hold(); - - list_for_each_entry(chip_node, &g_spnic_chip_list, node) { - list_for_each_entry(dev, &chip_node->func_list, node) { - if (is_pcidev_match_dev_name(ifname, dev, type)) { - lld_put(); - return &dev->lld_dev; - } - } - } - - lld_put(); - - return NULL; -} - -struct spnic_lld_dev *spnic_get_lld_dev_by_ifname(const char *ifname) -{ - struct spnic_lld_dev *dev = NULL; - - lld_hold(); - /* support search hwdev by chip name, net device name, - * or fc device name - */ - /* Find pcidev by chip_name first */ - dev = spnic_get_lld_dev_by_chip_name(ifname); - if (dev) - goto find_dev; - - /* If ifname not a chip name, - * find pcidev by FC name or netdevice name - */ - dev = spnic_get_lld_dev_by_dev_name(ifname, SERVICE_T_MAX); - if (!dev) { - lld_put(); - return NULL; - } - -find_dev: - lld_dev_hold(dev); - lld_put(); - return dev; -} - -void *spnic_get_hwdev_by_ifname(const char *ifname) -{ - struct spnic_lld_dev *dev = NULL; - - dev = spnic_get_lld_dev_by_ifname(ifname); - if (dev) - return dev->hwdev; - - return NULL; -} - -void *spnic_get_uld_dev_by_ifname(const char *ifname, enum sphw_service_type type) -{ - struct spnic_pcidev *dev = NULL; - struct spnic_lld_dev *lld_dev = NULL; - - if (type >= SERVICE_T_MAX) { - pr_err("Service type :%d is error\n", type); - return NULL; - } - - lld_dev = spnic_get_lld_dev_by_dev_name(ifname, type); - if (!lld_dev) - return NULL; - - dev = pci_get_drvdata(lld_dev->pdev); - if (dev) - return dev->uld_dev[type]; - - return NULL; -} - -static struct card_node *spnic_get_chip_node_by_hwdev(const void *hwdev) -{ - struct card_node *chip_node = NULL; - struct card_node *node_tmp = NULL; - struct spnic_pcidev *dev = NULL; - - if (!hwdev) - return NULL; - - lld_hold(); - - list_for_each_entry(node_tmp, &g_spnic_chip_list, node) { - if (!chip_node) { - list_for_each_entry(dev, &node_tmp->func_list, node) { - if (dev->hwdev == hwdev) { - chip_node = node_tmp; - break; - } - } - } - } - - lld_put(); - - return chip_node; -} - -int spnic_get_chip_name_by_hwdev(const void *hwdev, char *ifname) -{ - struct card_node *chip_node = NULL; - struct spnic_pcidev *dev = NULL; - - if (!hwdev || !ifname) - return -EINVAL; - - lld_hold(); - - list_for_each_entry(chip_node, &g_spnic_chip_list, node) { - list_for_each_entry(dev, &chip_node->func_list, node) { - if (dev->hwdev == hwdev) { - strncpy(ifname, chip_node->chip_name, IFNAMSIZ - 1); - ifname[IFNAMSIZ - 1] = 0; - lld_put(); - return 0; - } - } - } - - lld_put(); - - return -ENXIO; -} - -void *spnic_get_uld_dev_by_pdev(struct pci_dev *pdev, enum sphw_service_type type) -{ - struct spnic_pcidev *pci_adapter = NULL; - - if (type >= SERVICE_T_MAX) { - pr_err("Service type :%d is error\n", type); - return NULL; - } - - pci_adapter = pci_get_drvdata(pdev); - if (pci_adapter) - return pci_adapter->uld_dev[type]; - - return NULL; -} - -void *spnic_get_ppf_hwdev_by_pdev(struct pci_dev *pdev) -{ - struct spnic_pcidev *pci_adapter = NULL; - struct card_node *chip_node = NULL; - struct spnic_pcidev *dev = NULL; - - if (!pdev) - return NULL; - - pci_adapter = pci_get_drvdata(pdev); - if (!pci_adapter) - return NULL; - - chip_node = pci_adapter->chip_node; - lld_hold(); - list_for_each_entry(dev, &chip_node->func_list, node) { - if (dev->hwdev && sphw_func_type(dev->hwdev) == TYPE_PPF) { - lld_put(); - return dev->hwdev; - } - } - lld_put(); - - return NULL; -} - -/* NOTICE: nictool can't use this function, because this function can't keep - * tool context mutual exclusive with remove context - */ -void *spnic_get_ppf_uld_by_pdev(struct pci_dev *pdev, enum sphw_service_type type) -{ - struct spnic_pcidev *pci_adapter = NULL; - struct card_node *chip_node = NULL; - struct spnic_pcidev *dev = NULL; - - if (!pdev) - return NULL; - - pci_adapter = pci_get_drvdata(pdev); - if (!pci_adapter) - return NULL; - - chip_node = pci_adapter->chip_node; - lld_hold(); - list_for_each_entry(dev, &chip_node->func_list, node) { - if (sphw_func_type(dev->hwdev) == TYPE_PPF) { - lld_put(); - return dev->uld_dev[type]; - } - } - lld_put(); - - return NULL; -} - -int spnic_get_pf_nic_uld_array(struct pci_dev *pdev, u32 *dev_cnt, void *array[]) -{ - struct spnic_pcidev *dev = pci_get_drvdata(pdev); - struct card_node *chip_node = NULL; - u32 cnt; - - if (!dev || !sphw_support_nic(dev->hwdev, NULL)) - return -EINVAL; - - lld_hold(); - - cnt = 0; - chip_node = dev->chip_node; - list_for_each_entry(dev, &chip_node->func_list, node) { - if (sphw_func_type(dev->hwdev) == TYPE_VF) - continue; - - array[cnt] = dev->uld_dev[SERVICE_T_NIC]; - cnt++; - } - lld_put(); - - *dev_cnt = cnt; - - return 0; -} - -static bool is_func_valid(struct spnic_pcidev *dev) -{ - if (sphw_func_type(dev->hwdev) == TYPE_VF) - return false; - - return true; -} - -int spnic_get_uld_dev_name(struct spnic_pcidev *dev, enum sphw_service_type type, char *ifname) -{ - u32 out_size = IFNAMSIZ; - - if (!g_uld_info[type].ioctl) - return -EFAULT; - - return g_uld_info[type].ioctl(dev->uld_dev[type], GET_ULD_DEV_NAME, - NULL, 0, ifname, &out_size); -} - -void spnic_get_card_info(const void *hwdev, void *bufin) -{ - struct card_node *chip_node = NULL; - struct card_info *info = (struct card_info *)bufin; - struct spnic_pcidev *dev = NULL; - void *fun_hwdev = NULL; - u32 i = 0; - - info->pf_num = 0; - - chip_node = spnic_get_chip_node_by_hwdev(hwdev); - if (!chip_node) - return; - - lld_hold(); - - list_for_each_entry(dev, &chip_node->func_list, node) { - if (!is_func_valid(dev)) - continue; - - fun_hwdev = dev->hwdev; - - if (sphw_support_nic(fun_hwdev, NULL)) { - if (dev->uld_dev[SERVICE_T_NIC]) { - info->pf[i].pf_type |= (u32)BIT(SERVICE_T_NIC); - spnic_get_uld_dev_name(dev, SERVICE_T_NIC, info->pf[i].name); - } - } - - /* to do : get other service info*/ - - if (sphw_func_for_mgmt(fun_hwdev)) - strlcpy(info->pf[i].name, "FOR_MGMT", IFNAMSIZ); - - strlcpy(info->pf[i].bus_info, pci_name(dev->pcidev), - sizeof(info->pf[i].bus_info)); - info->pf_num++; - i = info->pf_num; - } - - lld_put(); -} - -struct spnic_sriov_info *spnic_get_sriov_info_by_pcidev(struct pci_dev *pdev) -{ - struct spnic_pcidev *pci_adapter = NULL; - - if (!pdev) - return NULL; - - pci_adapter = pci_get_drvdata(pdev); - if (!pci_adapter) - return NULL; - - return &pci_adapter->sriov_info; -} - -void *spnic_get_hwdev_by_pcidev(struct pci_dev *pdev) -{ - struct spnic_pcidev *pci_adapter = NULL; - - if (!pdev) - return NULL; - - pci_adapter = pci_get_drvdata(pdev); - if (!pci_adapter) - return NULL; - - return pci_adapter->hwdev; -} - -bool spnic_is_in_host(void) -{ - struct card_node *chip_node = NULL; - struct spnic_pcidev *dev = NULL; - - lld_hold(); - list_for_each_entry(chip_node, &g_spnic_chip_list, node) { - list_for_each_entry(dev, &chip_node->func_list, node) { - if (sphw_func_type(dev->hwdev) != TYPE_VF) { - lld_put(); - return true; - } - } - } - - lld_put(); - - return false; -} - -int spnic_get_chip_up_bitmap(struct pci_dev *pdev, bool *is_setted, u8 *valid_up_bitmap) -{ - struct spnic_pcidev *dev = pci_get_drvdata(pdev); - struct card_node *chip_node = NULL; - - if (!dev || !is_setted || !valid_up_bitmap) - return -EINVAL; - - chip_node = dev->chip_node; - *is_setted = chip_node->up_bitmap_setted; - if (chip_node->up_bitmap_setted) - *valid_up_bitmap = chip_node->valid_up_bitmap; - - return 0; -} - -int spnic_set_chip_up_bitmap(struct pci_dev *pdev, u8 valid_up_bitmap) -{ - struct spnic_pcidev *dev = pci_get_drvdata(pdev); - struct card_node *chip_node = NULL; - - if (!dev) - return -EINVAL; - - chip_node = dev->chip_node; - chip_node->up_bitmap_setted = true; - chip_node->valid_up_bitmap = valid_up_bitmap; - - return 0; -} - -static bool chip_node_is_exist(struct spnic_pcidev *pci_adapter, unsigned char *bus_number) -{ - struct card_node *chip_node = NULL; - - if (!pci_is_root_bus(pci_adapter->pcidev->bus)) - *bus_number = pci_adapter->pcidev->bus->number; - - if (*bus_number != 0) { - list_for_each_entry(chip_node, &g_spnic_chip_list, node) { - if (chip_node->bus_num == *bus_number) { - pci_adapter->chip_node = chip_node; - return true; - } - } - } else if (pci_adapter->pcidev->device == SPNIC_DEV_ID_VF || - pci_adapter->pcidev->device == SPNIC_DEV_ID_VF_HV) { - list_for_each_entry(chip_node, &g_spnic_chip_list, node) { - if (chip_node) { - pci_adapter->chip_node = chip_node; - return true; - } - } - } - - return false; -} - -int alloc_chip_node(struct spnic_pcidev *pci_adapter) -{ - struct card_node *chip_node = NULL; - unsigned char i; - unsigned char bus_number = 0; - - if (chip_node_is_exist(pci_adapter, &bus_number)) - return 0; - - for (i = 0; i < MAX_CARD_ID; i++) { - if (!test_and_set_bit(i, &card_bit_map)) - break; - } - - if (i == MAX_CARD_ID) { - sdk_err(&pci_adapter->pcidev->dev, "Failed to alloc card id\n"); - return -EFAULT; - } - - chip_node = kzalloc(sizeof(*chip_node), GFP_KERNEL); - if (!chip_node) { - clear_bit(i, &card_bit_map); - sdk_err(&pci_adapter->pcidev->dev, - "Failed to alloc chip node\n"); - return -ENOMEM; - } - - /* bus number */ - chip_node->bus_num = bus_number; - - snprintf(chip_node->chip_name, IFNAMSIZ, "%s%u", SPHW_CHIP_NAME, i); - - sdk_info(&pci_adapter->pcidev->dev, "Add new chip %s to global list succeed\n", - chip_node->chip_name); - - list_add_tail(&chip_node->node, &g_spnic_chip_list); - - INIT_LIST_HEAD(&chip_node->func_list); - pci_adapter->chip_node = chip_node; - - return 0; -} - -void free_chip_node(struct spnic_pcidev *pci_adapter) -{ - struct card_node *chip_node = pci_adapter->chip_node; - int id, err; - - if (list_empty(&chip_node->func_list)) { - list_del(&chip_node->node); - sdk_info(&pci_adapter->pcidev->dev, "Delete chip %s from global list succeed\n", - chip_node->chip_name); - err = sscanf(chip_node->chip_name, SPHW_CHIP_NAME "%d", &id); - if (err < 0) - sdk_err(&pci_adapter->pcidev->dev, "Failed to get spnic id\n"); - - clear_bit(id, &card_bit_map); - - kfree(chip_node); - } -} diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_dev_mgmt.h b/drivers/net/ethernet/ramaxel/spnic/spnic_dev_mgmt.h deleted file mode 100644 index 8f345769bec5..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_dev_mgmt.h +++ /dev/null @@ -1,78 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPNIC_DEV_MGMT_H -#define SPNIC_DEV_MGMT_H -#include <linux/types.h> -#include <linux/bitops.h> - -#define SPHW_CHIP_NAME "spnic" - -#define SPNIC_VF_PCI_CFG_REG_BAR 0 -#define SPNIC_PF_PCI_CFG_REG_BAR 1 - -#define SPNIC_PCI_INTR_REG_BAR 2 -#define SPNIC_PCI_MGMT_REG_BAR 3 /* Only PF have mgmt bar */ -#define SPNIC_PCI_DB_BAR 4 - -/* Structure pcidev private*/ -struct spnic_pcidev { - struct pci_dev *pcidev; - void *hwdev; - struct card_node *chip_node; - struct spnic_lld_dev lld_dev; - /* Record the service object address, - * such as spnic_dev and toe_dev, fc_dev - */ - void *uld_dev[SERVICE_T_MAX]; - /* Record the service object name */ - char uld_dev_name[SERVICE_T_MAX][IFNAMSIZ]; - /* It is a the global variable for driver to manage - * all function device linked list - */ - struct list_head node; - - bool disable_vf_load; - bool disable_srv_load[SERVICE_T_MAX]; - - void __iomem *cfg_reg_base; - void __iomem *intr_reg_base; - void __iomem *mgmt_reg_base; - u64 db_dwqe_len; - u64 db_base_phy; - void __iomem *db_base; - - /* lock for attach/detach uld */ - struct mutex pdev_mutex; - - struct spnic_sriov_info sriov_info; - - /* setted when uld driver processing event */ - unsigned long state; - struct pci_device_id id; - - atomic_t ref_cnt; -}; - -extern struct list_head g_spnic_chip_list; - -extern struct spnic_uld_info g_uld_info[SERVICE_T_MAX]; - -int alloc_chip_node(struct spnic_pcidev *pci_adapter); - -void free_chip_node(struct spnic_pcidev *pci_adapter); - -void lld_lock_chip_node(void); - -void lld_unlock_chip_node(void); - -void spnic_lld_lock_init(void); - -void lld_dev_cnt_init(struct spnic_pcidev *pci_adapter); -void wait_lld_dev_unused(struct spnic_pcidev *pci_adapter); - -int spnic_get_uld_dev_name(struct spnic_pcidev *dev, enum sphw_service_type type, char *ifname); - -void *spnic_get_hwdev_by_pcidev(struct pci_dev *pdev); - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_ethtool.c b/drivers/net/ethernet/ramaxel/spnic/spnic_ethtool.c deleted file mode 100644 index e3a7e81a601b..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_ethtool.c +++ /dev/null @@ -1,994 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [NIC]" fmt - -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/device.h> -#include <linux/module.h> -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/interrupt.h> -#include <linux/etherdevice.h> -#include <linux/netdevice.h> -#include <linux/if_vlan.h> -#include <linux/ethtool.h> - -#include "sphw_hw.h" -#include "sphw_crm.h" -#include "spnic_nic_dev.h" -#include "spnic_tx.h" -#include "spnic_rx.h" -#include "spnic_rss.h" - -#define COALESCE_ALL_QUEUE 0xFFFF -#define COALESCE_PENDING_LIMIT_UNIT 8 -#define COALESCE_TIMER_CFG_UNIT 5 -#define COALESCE_MAX_PENDING_LIMIT (255 * COALESCE_PENDING_LIMIT_UNIT) -#define COALESCE_MAX_TIMER_CFG (255 * COALESCE_TIMER_CFG_UNIT) - -static void spnic_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *info) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - struct pci_dev *pdev = nic_dev->pdev; - u8 mgmt_ver[SPHW_MGMT_VERSION_MAX_LEN] = {0}; - int err; - - strlcpy(info->driver, SPNIC_NIC_DRV_NAME, sizeof(info->driver)); - strlcpy(info->version, SPNIC_DRV_VERSION, sizeof(info->version)); - strlcpy(info->bus_info, pci_name(pdev), sizeof(info->bus_info)); - - err = sphw_get_mgmt_version(nic_dev->hwdev, mgmt_ver, SPHW_MGMT_VERSION_MAX_LEN, - SPHW_CHANNEL_NIC); - if (err) { - nicif_err(nic_dev, drv, netdev, "Failed to get fw version\n"); - return; - } - - snprintf(info->fw_version, sizeof(info->fw_version), "%s", mgmt_ver); -} - -static u32 spnic_get_msglevel(struct net_device *netdev) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - - return nic_dev->msg_enable; -} - -static void spnic_set_msglevel(struct net_device *netdev, u32 data) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - - nic_dev->msg_enable = data; - - nicif_info(nic_dev, drv, netdev, "Set message level: 0x%x\n", data); -} - -int spnic_nway_reset(struct net_device *netdev) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - struct nic_port_info port_info = {0}; - int err; - - err = spnic_get_port_info(nic_dev->hwdev, &port_info, SPHW_CHANNEL_NIC); - if (err) { - nicif_err(nic_dev, drv, netdev, - "Get port info failed\n"); - return -EFAULT; - } - - if (!port_info.autoneg_state) { - nicif_err(nic_dev, drv, netdev, "Autonegotiation is off, don't support to restart it\n"); - return -EINVAL; - } - - err = spnic_set_autoneg(nic_dev->hwdev, true); - if (err) { - nicif_err(nic_dev, drv, netdev, "Restart autonegotiation failed\n"); - return -EFAULT; - } - - nicif_info(nic_dev, drv, netdev, "Restart autonegotiation successfully\n"); - - return 0; -} - -static void spnic_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring, - struct kernel_ethtool_ringparam *kernel_ering, - struct netlink_ext_ack *extack) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - - ring->rx_max_pending = SPNIC_MAX_RX_QUEUE_DEPTH; - ring->tx_max_pending = SPNIC_MAX_TX_QUEUE_DEPTH; - ring->rx_pending = nic_dev->rxqs[0].q_depth; - ring->tx_pending = nic_dev->txqs[0].q_depth; -} - -static void spnic_update_qp_depth(struct spnic_nic_dev *nic_dev, u32 sq_depth, u32 rq_depth) -{ - u16 i; - - nic_dev->q_params.sq_depth = sq_depth; - nic_dev->q_params.rq_depth = rq_depth; - for (i = 0; i < nic_dev->max_qps; i++) { - nic_dev->txqs[i].q_depth = sq_depth; - nic_dev->txqs[i].q_mask = sq_depth - 1; - nic_dev->rxqs[i].q_depth = rq_depth; - nic_dev->rxqs[i].q_mask = rq_depth - 1; - } -} - -static int check_ringparam_valid(struct net_device *netdev, struct ethtool_ringparam *ring) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - - if (ring->rx_jumbo_pending || ring->rx_mini_pending) { - nicif_err(nic_dev, drv, netdev, - "Unsupported rx_jumbo_pending/rx_mini_pending\n"); - return -EINVAL; - } - - if (ring->tx_pending > SPNIC_MAX_TX_QUEUE_DEPTH || - ring->tx_pending < SPNIC_MIN_QUEUE_DEPTH || - ring->rx_pending > SPNIC_MAX_RX_QUEUE_DEPTH || - ring->rx_pending < SPNIC_MIN_QUEUE_DEPTH) { - nicif_err(nic_dev, drv, netdev, "Queue depth out of rang tx[%d-%d] rx[%d-%d]\n", - SPNIC_MIN_QUEUE_DEPTH, SPNIC_MAX_TX_QUEUE_DEPTH, - SPNIC_MIN_QUEUE_DEPTH, SPNIC_MAX_RX_QUEUE_DEPTH); - return -EINVAL; - } - - return 0; -} - -static int spnic_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring, - struct kernel_ethtool_ringparam *kernel_ering, - struct netlink_ext_ack *extack) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - struct spnic_dyna_txrxq_params q_params = {0}; - u32 new_sq_depth, new_rq_depth; - int err; - - err = check_ringparam_valid(netdev, ring); - if (err) - return err; - - new_sq_depth = (u32)(1U << (u16)ilog2(ring->tx_pending)); - new_rq_depth = (u32)(1U << (u16)ilog2(ring->rx_pending)); - - if (new_sq_depth == nic_dev->q_params.sq_depth && - new_rq_depth == nic_dev->q_params.rq_depth) - return 0; /* nothing to do */ - - nicif_info(nic_dev, drv, netdev, "Change Tx/Rx ring depth from %u/%u to %u/%u\n", - nic_dev->q_params.sq_depth, nic_dev->q_params.rq_depth, - new_sq_depth, new_rq_depth); - - if (!netif_running(netdev)) { - spnic_update_qp_depth(nic_dev, new_sq_depth, new_rq_depth); - } else { - q_params = nic_dev->q_params; - q_params.sq_depth = new_sq_depth; - q_params.rq_depth = new_rq_depth; - q_params.txqs_res = NULL; - q_params.rxqs_res = NULL; - q_params.irq_cfg = NULL; - - nicif_info(nic_dev, drv, netdev, "Restarting channel\n"); - err = spnic_change_channel_settings(nic_dev, &q_params, NULL, NULL); - if (err) { - nicif_err(nic_dev, drv, netdev, "Failed to change channel settings\n"); - return -EFAULT; - } - } - - return 0; -} - -static int get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coal, u16 queue) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - struct spnic_intr_coal_info *interrupt_info = NULL; - - if (queue == COALESCE_ALL_QUEUE) { - /* get tx/rx irq0 as default parameters */ - interrupt_info = &nic_dev->intr_coalesce[0]; - } else { - if (queue >= nic_dev->q_params.num_qps) { - nicif_err(nic_dev, drv, netdev, "Invalid queue_id: %u\n", queue); - return -EINVAL; - } - interrupt_info = &nic_dev->intr_coalesce[queue]; - } - - /* coalescs_timer is in unit of 5us */ - coal->rx_coalesce_usecs = interrupt_info->coalesce_timer_cfg * COALESCE_TIMER_CFG_UNIT; - /* coalescs_frams is in unit of 8 */ - coal->rx_max_coalesced_frames = interrupt_info->pending_limt * COALESCE_PENDING_LIMIT_UNIT; - - /* tx/rx use the same interrupt */ - coal->tx_coalesce_usecs = coal->rx_coalesce_usecs; - coal->tx_max_coalesced_frames = coal->rx_max_coalesced_frames; - coal->use_adaptive_rx_coalesce = nic_dev->adaptive_rx_coal; - - coal->pkt_rate_high = (u32)interrupt_info->pkt_rate_high; - coal->rx_coalesce_usecs_high = interrupt_info->rx_usecs_high * COALESCE_TIMER_CFG_UNIT; - coal->rx_max_coalesced_frames_high = interrupt_info->rx_pending_limt_high * - COALESCE_PENDING_LIMIT_UNIT; - - coal->pkt_rate_low = (u32)interrupt_info->pkt_rate_low; - coal->rx_coalesce_usecs_low = interrupt_info->rx_usecs_low * - COALESCE_TIMER_CFG_UNIT; - coal->rx_max_coalesced_frames_low = interrupt_info->rx_pending_limt_low * - COALESCE_PENDING_LIMIT_UNIT; - - return 0; -} - -static int set_queue_coalesce(struct spnic_nic_dev *nic_dev, u16 q_id, - struct spnic_intr_coal_info *coal) -{ - struct spnic_intr_coal_info *intr_coal; - struct interrupt_info info = {0}; - struct net_device *netdev = nic_dev->netdev; - int err; - - intr_coal = &nic_dev->intr_coalesce[q_id]; - if (intr_coal->coalesce_timer_cfg != coal->coalesce_timer_cfg || - intr_coal->pending_limt != coal->pending_limt) - intr_coal->user_set_intr_coal_flag = 1; - - intr_coal->coalesce_timer_cfg = coal->coalesce_timer_cfg; - intr_coal->pending_limt = coal->pending_limt; - intr_coal->pkt_rate_low = coal->pkt_rate_low; - intr_coal->rx_usecs_low = coal->rx_usecs_low; - intr_coal->rx_pending_limt_low = coal->rx_pending_limt_low; - intr_coal->pkt_rate_high = coal->pkt_rate_high; - intr_coal->rx_usecs_high = coal->rx_usecs_high; - intr_coal->rx_pending_limt_high = coal->rx_pending_limt_high; - - /* netdev not running or qp not in using, - * don't need to set coalesce to hw - */ - if (!test_bit(SPNIC_INTF_UP, &nic_dev->flags) || - q_id >= nic_dev->q_params.num_qps || nic_dev->adaptive_rx_coal) - return 0; - - info.msix_index = nic_dev->q_params.irq_cfg[q_id].msix_entry_idx; - info.lli_set = 0; - info.interrupt_coalesc_set = 1; - info.coalesc_timer_cfg = intr_coal->coalesce_timer_cfg; - info.pending_limt = intr_coal->pending_limt; - info.resend_timer_cfg = intr_coal->resend_timer_cfg; - nic_dev->rxqs[q_id].last_coalesc_timer_cfg = intr_coal->coalesce_timer_cfg; - nic_dev->rxqs[q_id].last_pending_limt = intr_coal->pending_limt; - err = sphw_set_interrupt_cfg(nic_dev->hwdev, info, SPHW_CHANNEL_NIC); - if (err) - nicif_warn(nic_dev, drv, netdev, "Failed to set queue%u coalesce", q_id); - - return err; -} - -static int is_coalesce_exceed_limit(struct net_device *netdev, - const struct ethtool_coalesce *coal) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - - if (coal->rx_coalesce_usecs > COALESCE_MAX_TIMER_CFG) { - nicif_err(nic_dev, drv, netdev, "rx_coalesce_usecs out of range[%d-%d]\n", 0, - COALESCE_MAX_TIMER_CFG); - return -EOPNOTSUPP; - } - - if (coal->rx_max_coalesced_frames > COALESCE_MAX_PENDING_LIMIT) { - nicif_err(nic_dev, drv, netdev, "rx_max_coalesced_frames out of range[%d-%d]\n", 0, - COALESCE_MAX_PENDING_LIMIT); - return -EOPNOTSUPP; - } - - if (coal->rx_coalesce_usecs_low > COALESCE_MAX_TIMER_CFG) { - nicif_err(nic_dev, drv, netdev, "rx_coalesce_usecs_low out of range[%d-%d]\n", 0, - COALESCE_MAX_TIMER_CFG); - return -EOPNOTSUPP; - } - - if (coal->rx_max_coalesced_frames_low > COALESCE_MAX_PENDING_LIMIT) { - nicif_err(nic_dev, drv, netdev, "rx_max_coalesced_frames_low out of range[%d-%d]\n", - 0, COALESCE_MAX_PENDING_LIMIT); - return -EOPNOTSUPP; - } - - if (coal->rx_coalesce_usecs_high > COALESCE_MAX_TIMER_CFG) { - nicif_err(nic_dev, drv, netdev, "rx_coalesce_usecs_high out of range[%d-%d]\n", 0, - COALESCE_MAX_TIMER_CFG); - return -EOPNOTSUPP; - } - - if (coal->rx_max_coalesced_frames_high > COALESCE_MAX_PENDING_LIMIT) { - nicif_err(nic_dev, drv, netdev, "rx_max_coalesced_frames_high out of range[%d-%d]\n", - 0, COALESCE_MAX_PENDING_LIMIT); - return -EOPNOTSUPP; - } - - return 0; -} - -static int is_coalesce_legal(struct net_device *netdev, - const struct ethtool_coalesce *coal) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - struct ethtool_coalesce tmp_coal = {0}; - int err; - - if (coal->rx_coalesce_usecs != coal->tx_coalesce_usecs) { - nicif_err(nic_dev, drv, netdev, "tx-usecs must be equal to rx-usecs\n"); - return -EINVAL; - } - - if (coal->rx_max_coalesced_frames != coal->tx_max_coalesced_frames) { - nicif_err(nic_dev, drv, netdev, "tx-frames must be equal to rx-frames\n"); - return -EINVAL; - } - - tmp_coal.cmd = coal->cmd; - tmp_coal.rx_coalesce_usecs = coal->rx_coalesce_usecs; - tmp_coal.rx_max_coalesced_frames = coal->rx_max_coalesced_frames; - tmp_coal.tx_coalesce_usecs = coal->tx_coalesce_usecs; - tmp_coal.tx_max_coalesced_frames = coal->tx_max_coalesced_frames; - tmp_coal.use_adaptive_rx_coalesce = coal->use_adaptive_rx_coalesce; - - tmp_coal.pkt_rate_low = coal->pkt_rate_low; - tmp_coal.rx_coalesce_usecs_low = coal->rx_coalesce_usecs_low; - tmp_coal.rx_max_coalesced_frames_low = coal->rx_max_coalesced_frames_low; - - tmp_coal.pkt_rate_high = coal->pkt_rate_high; - tmp_coal.rx_coalesce_usecs_high = coal->rx_coalesce_usecs_high; - tmp_coal.rx_max_coalesced_frames_high = coal->rx_max_coalesced_frames_high; - - if (memcmp(coal, &tmp_coal, sizeof(struct ethtool_coalesce))) { - nicif_err(nic_dev, drv, netdev, "Only support to change rx/tx-usecs and rx/tx-frames\n"); - return -EOPNOTSUPP; - } - - err = is_coalesce_exceed_limit(netdev, coal); - if (err) - return err; - - if (coal->rx_coalesce_usecs_low / COALESCE_TIMER_CFG_UNIT >= - coal->rx_coalesce_usecs_high / COALESCE_TIMER_CFG_UNIT) { - nicif_err(nic_dev, drv, netdev, - "coalesce_usecs_high(%u) must more than coalesce_usecs_low(%u), after dividing %d usecs unit\n", - coal->rx_coalesce_usecs_high, - coal->rx_coalesce_usecs_low, - COALESCE_TIMER_CFG_UNIT); - return -EOPNOTSUPP; - } - - if (coal->rx_max_coalesced_frames_low / COALESCE_PENDING_LIMIT_UNIT >= - coal->rx_max_coalesced_frames_high / COALESCE_PENDING_LIMIT_UNIT) { - nicif_err(nic_dev, drv, netdev, - "coalesced_frames_high(%u) must more than coalesced_frames_low(%u),after dividing %d frames unit\n", - coal->rx_max_coalesced_frames_high, - coal->rx_max_coalesced_frames_low, - COALESCE_PENDING_LIMIT_UNIT); - return -EOPNOTSUPP; - } - - if (coal->pkt_rate_low >= coal->pkt_rate_high) { - nicif_err(nic_dev, drv, netdev, "pkt_rate_high(%u) must more than pkt_rate_low(%u)\n", - coal->pkt_rate_high, - coal->pkt_rate_low); - return -EOPNOTSUPP; - } - - return 0; -} - -#define CHECK_COALESCE_ALIGN(coal, item, unit) \ -do { \ - if ((coal)->item % (unit)) \ - nicif_warn(nic_dev, drv, netdev, \ - "%s in %d units, change to %u\n", \ - #item, (unit), ((coal)->item - \ - (coal)->item % (unit))); \ -} while (0) - -#define CHECK_COALESCE_CHANGED(coal, item, unit, ori_val, obj_str) \ -do { \ - if (((coal)->item / (unit)) != (ori_val)) \ - nicif_info(nic_dev, drv, netdev, \ - "Change %s from %d to %u %s\n", \ - #item, (ori_val) * (unit), \ - ((coal)->item - (coal)->item % (unit)), \ - (obj_str)); \ -} while (0) - -#define CHECK_PKT_RATE_CHANGED(coal, item, ori_val, obj_str) \ -do { \ - if ((coal)->item != (ori_val)) \ - nicif_info(nic_dev, drv, netdev, \ - "Change %s from %llu to %u %s\n", \ - #item, (ori_val), (coal)->item, (obj_str)); \ -} while (0) - -static int set_hw_coal_param(struct spnic_nic_dev *nic_dev, struct spnic_intr_coal_info *intr_coal, - u16 queue) -{ - u16 i; - - if (queue == COALESCE_ALL_QUEUE) { - for (i = 0; i < nic_dev->max_qps; i++) - set_queue_coalesce(nic_dev, i, intr_coal); - } else { - if (queue >= nic_dev->q_params.num_qps) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Invalid queue_id: %u\n", queue); - return -EINVAL; - } - set_queue_coalesce(nic_dev, queue, intr_coal); - } - - return 0; -} - -static int set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coal, u16 queue) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - struct spnic_intr_coal_info intr_coal = {0}; - struct spnic_intr_coal_info *ori_intr_coal = NULL; - u32 last_adaptive_rx; - char obj_str[32] = {0}; - int err = 0; - - err = is_coalesce_legal(netdev, coal); - if (err) - return err; - - CHECK_COALESCE_ALIGN(coal, rx_coalesce_usecs, COALESCE_TIMER_CFG_UNIT); - CHECK_COALESCE_ALIGN(coal, rx_max_coalesced_frames, COALESCE_PENDING_LIMIT_UNIT); - CHECK_COALESCE_ALIGN(coal, rx_coalesce_usecs_high, COALESCE_TIMER_CFG_UNIT); - CHECK_COALESCE_ALIGN(coal, rx_max_coalesced_frames_high, COALESCE_PENDING_LIMIT_UNIT); - CHECK_COALESCE_ALIGN(coal, rx_coalesce_usecs_low, COALESCE_TIMER_CFG_UNIT); - CHECK_COALESCE_ALIGN(coal, rx_max_coalesced_frames_low, COALESCE_PENDING_LIMIT_UNIT); - - if (queue == COALESCE_ALL_QUEUE) { - ori_intr_coal = &nic_dev->intr_coalesce[0]; - snprintf(obj_str, sizeof(obj_str), "for netdev"); - } else { - ori_intr_coal = &nic_dev->intr_coalesce[queue]; - snprintf(obj_str, sizeof(obj_str), "for queue %u", queue); - } - CHECK_COALESCE_CHANGED(coal, rx_coalesce_usecs, COALESCE_TIMER_CFG_UNIT, - ori_intr_coal->coalesce_timer_cfg, obj_str); - CHECK_COALESCE_CHANGED(coal, rx_max_coalesced_frames, COALESCE_PENDING_LIMIT_UNIT, - ori_intr_coal->pending_limt, obj_str); - CHECK_PKT_RATE_CHANGED(coal, pkt_rate_high, ori_intr_coal->pkt_rate_high, obj_str); - CHECK_COALESCE_CHANGED(coal, rx_coalesce_usecs_high, COALESCE_TIMER_CFG_UNIT, - ori_intr_coal->rx_usecs_high, obj_str); - CHECK_COALESCE_CHANGED(coal, rx_max_coalesced_frames_high, COALESCE_PENDING_LIMIT_UNIT, - ori_intr_coal->rx_pending_limt_high, obj_str); - CHECK_PKT_RATE_CHANGED(coal, pkt_rate_low, ori_intr_coal->pkt_rate_low, obj_str); - CHECK_COALESCE_CHANGED(coal, rx_coalesce_usecs_low, COALESCE_TIMER_CFG_UNIT, - ori_intr_coal->rx_usecs_low, obj_str); - CHECK_COALESCE_CHANGED(coal, rx_max_coalesced_frames_low, COALESCE_PENDING_LIMIT_UNIT, - ori_intr_coal->rx_pending_limt_low, obj_str); - - intr_coal.coalesce_timer_cfg = (u8)(coal->rx_coalesce_usecs / COALESCE_TIMER_CFG_UNIT); - intr_coal.pending_limt = (u8)(coal->rx_max_coalesced_frames / COALESCE_PENDING_LIMIT_UNIT); - - last_adaptive_rx = nic_dev->adaptive_rx_coal; - nic_dev->adaptive_rx_coal = coal->use_adaptive_rx_coalesce; - - intr_coal.pkt_rate_high = coal->pkt_rate_high; - intr_coal.rx_usecs_high = (u8)(coal->rx_coalesce_usecs_high / COALESCE_TIMER_CFG_UNIT); - intr_coal.rx_pending_limt_high = (u8)(coal->rx_max_coalesced_frames_high / - COALESCE_PENDING_LIMIT_UNIT); - - intr_coal.pkt_rate_low = coal->pkt_rate_low; - intr_coal.rx_usecs_low = (u8)(coal->rx_coalesce_usecs_low / COALESCE_TIMER_CFG_UNIT); - intr_coal.rx_pending_limt_low = (u8)(coal->rx_max_coalesced_frames_low / - COALESCE_PENDING_LIMIT_UNIT); - - /* coalesce timer or pending set to zero will disable coalesce */ - if (!nic_dev->adaptive_rx_coal && - (!intr_coal.coalesce_timer_cfg || !intr_coal.pending_limt)) - nicif_warn(nic_dev, drv, netdev, "Coalesce will be disabled\n"); - - /* ensure coalesce paramester will not be changed in auto - * moderation work - */ - if (SPHW_CHANNEL_RES_VALID(nic_dev)) { - if (!nic_dev->adaptive_rx_coal) - cancel_delayed_work_sync(&nic_dev->moderation_task); - else if (!last_adaptive_rx) - queue_delayed_work(nic_dev->workq, &nic_dev->moderation_task, - SPNIC_MODERATONE_DELAY); - } - - return set_hw_coal_param(nic_dev, &intr_coal, queue); -} - -static int spnic_get_coalesce(struct net_device *netdev, - struct ethtool_coalesce *coal, - struct kernel_ethtool_coalesce *kernel_coal, - struct netlink_ext_ack *ext_ack) -{ - return get_coalesce(netdev, coal, COALESCE_ALL_QUEUE); -} - -static int spnic_set_coalesce(struct net_device *netdev, - struct ethtool_coalesce *coal, - struct kernel_ethtool_coalesce *kernel_coal, - struct netlink_ext_ack *ext_ack) -{ - return set_coalesce(netdev, coal, COALESCE_ALL_QUEUE); -} - -static int spnic_get_per_queue_coalesce(struct net_device *netdev, u32 queue, - struct ethtool_coalesce *coal) -{ - return get_coalesce(netdev, coal, queue); -} - -static int spnic_set_per_queue_coalesce(struct net_device *netdev, u32 queue, - struct ethtool_coalesce *coal) -{ - return set_coalesce(netdev, coal, queue); -} - -static int spnic_set_phys_id(struct net_device *netdev, enum ethtool_phys_id_state state) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - int err; - - switch (state) { - case ETHTOOL_ID_ACTIVE: - err = spnic_set_led_status(nic_dev->hwdev, MAG_CMD_LED_TYPE_ALARM, - MAG_CMD_LED_MODE_FORCE_BLINK_2HZ); - if (err) - nicif_err(nic_dev, drv, netdev, "Set LED blinking in 2HZ failed\n"); - else - nicif_info(nic_dev, drv, netdev, "Set LED blinking in 2HZ success\n"); - break; - - case ETHTOOL_ID_INACTIVE: - err = spnic_set_led_status(nic_dev->hwdev, MAG_CMD_LED_TYPE_ALARM, - MAG_CMD_LED_MODE_DEFAULT); - if (err) - nicif_err(nic_dev, drv, netdev, "Reset LED to original status failed\n"); - else - nicif_info(nic_dev, drv, netdev, "Reset LED to original status success\n"); - break; - - default: - return -EOPNOTSUPP; - } - - return err; -} - -static void spnic_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - struct nic_pause_config nic_pause = {0}; - int err; - - err = spnic_get_pause_info(nic_dev->hwdev, &nic_pause); - if (err) { - nicif_err(nic_dev, drv, netdev, "Failed to get pauseparam from hw\n"); - } else { - pause->autoneg = nic_pause.auto_neg; - pause->rx_pause = nic_pause.rx_pause; - pause->tx_pause = nic_pause.tx_pause; - } -} - -static int spnic_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - struct nic_pause_config nic_pause = {0}; - struct nic_port_info port_info = {0}; - int err; - - err = spnic_get_port_info(nic_dev->hwdev, &port_info, SPHW_CHANNEL_NIC); - if (err) { - nicif_err(nic_dev, drv, netdev, "Failed to get auto-negotiation state\n"); - return -EFAULT; - } - - if (pause->autoneg != port_info.autoneg_state) { - nicif_err(nic_dev, drv, netdev, "To change autoneg please use: ethtool -s <dev> autoneg <on|off>\n"); - return -EOPNOTSUPP; - } - - if (nic_dev->hw_dcb_cfg.pfc_state) { - nicif_err(nic_dev, drv, netdev, "Can not set pause when pfc is enable\n"); - return -EPERM; - } - - nic_pause.auto_neg = (u8)pause->autoneg; - nic_pause.rx_pause = (u8)pause->rx_pause; - nic_pause.tx_pause = (u8)pause->tx_pause; - - err = spnic_set_pause_info(nic_dev->hwdev, nic_pause); - if (err) { - nicif_err(nic_dev, drv, netdev, "Failed to set pauseparam\n"); - return -EFAULT; - } - - nicif_info(nic_dev, drv, netdev, "Set pause options, tx: %s, rx: %s\n", - pause->tx_pause ? "on" : "off", - pause->rx_pause ? "on" : "off"); - - return 0; -} - -static int spnic_get_module_info(struct net_device *netdev, struct ethtool_modinfo *modinfo) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - u8 sfp_type = 0; - u8 sfp_type_ext = 0; - int err; - - err = spnic_get_sfp_type(nic_dev->hwdev, &sfp_type, &sfp_type_ext); - if (err) - return err; - - switch (sfp_type) { - case MODULE_TYPE_SFP: - modinfo->type = ETH_MODULE_SFF_8472; - modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN; - break; - case MODULE_TYPE_QSFP: - modinfo->type = ETH_MODULE_SFF_8436; - modinfo->eeprom_len = ETH_MODULE_SFF_8436_MAX_LEN; - break; - case MODULE_TYPE_QSFP_PLUS: - if (sfp_type_ext >= 0x3) { - modinfo->type = ETH_MODULE_SFF_8636; - modinfo->eeprom_len = ETH_MODULE_SFF_8636_MAX_LEN; - - } else { - modinfo->type = ETH_MODULE_SFF_8436; - modinfo->eeprom_len = ETH_MODULE_SFF_8436_MAX_LEN; - } - break; - case MODULE_TYPE_QSFP28: - modinfo->type = ETH_MODULE_SFF_8636; - modinfo->eeprom_len = ETH_MODULE_SFF_8636_MAX_LEN; - break; - default: - nicif_warn(nic_dev, drv, netdev, "Optical module unknown: 0x%x\n", sfp_type); - return -EINVAL; - } - - return 0; -} - -static int spnic_get_module_eeprom(struct net_device *netdev, struct ethtool_eeprom *ee, u8 *data) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - u8 sfp_data[STD_SFP_INFO_MAX_SIZE]; - int err; - - if (!ee->len || ((ee->len + ee->offset) > STD_SFP_INFO_MAX_SIZE)) - return -EINVAL; - - memset(data, 0, ee->len); - - err = spnic_get_sfp_eeprom(nic_dev->hwdev, (u8 *)sfp_data, ee->len); - if (err) - return err; - - memcpy(data, sfp_data + ee->offset, ee->len); - - return 0; -} - -#define SPNIC_PRIV_FLAGS_SYMM_RSS BIT(0) - -static u32 spnic_get_priv_flags(struct net_device *netdev) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - u32 priv_flags = 0; - - if (test_bit(SPNIC_SAME_RXTX, &nic_dev->flags)) - priv_flags |= SPNIC_PRIV_FLAGS_SYMM_RSS; - - return priv_flags; -} - -static int spnic_set_priv_flags(struct net_device *netdev, u32 priv_flags) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - - if (priv_flags & SPNIC_PRIV_FLAGS_SYMM_RSS) { - if (test_bit(SPNIC_DCB_ENABLE, &nic_dev->flags)) { - nicif_err(nic_dev, drv, netdev, "Failed to open Symmetric RSS while DCB is enabled\n"); - return -EOPNOTSUPP; - } - set_bit(SPNIC_SAME_RXTX, &nic_dev->flags); - } else { - clear_bit(SPNIC_SAME_RXTX, &nic_dev->flags); - } - - return 0; -} - -#define BROADCAST_PACKET_SIM 0xFF -#define UNICAST_PACKET_SIM 0xFE -#define IP_PROTOCOL_TYPE 0x08 -#define IP_PROTOCOL_COMPLEMENT 0x00 - -#define PORT_DOWN_ERR_IDX 0 -#define LP_DEFAULT_TIME 5 /* seconds */ -#define LP_PKT_LEN 1514 - -#define TEST_TIME_MULTIPLE 5 -static int spnic_run_lp_test(struct spnic_nic_dev *nic_dev, u32 test_time) -{ - u32 cnt = test_time * TEST_TIME_MULTIPLE; - struct sk_buff *skb = NULL; - struct sk_buff *skb_tmp = NULL; - u8 *test_data = NULL; - u8 *lb_test_rx_buf = nic_dev->lb_test_rx_buf; - struct net_device *netdev = nic_dev->netdev; - u32 i; - u8 j; - - skb_tmp = alloc_skb(LP_PKT_LEN, GFP_ATOMIC); - if (!skb_tmp) { - nicif_err(nic_dev, drv, netdev, "Alloc xmit skb template failed for loopback test\n"); - return -ENOMEM; - } - - test_data = __skb_put(skb_tmp, LP_PKT_LEN); - - memset(test_data, BROADCAST_PACKET_SIM, ETH_ALEN + ETH_ALEN); - - test_data[ETH_ALEN] = UNICAST_PACKET_SIM; - test_data[ETH_ALEN + ETH_ALEN] = IP_PROTOCOL_TYPE; - test_data[ETH_ALEN + ETH_ALEN + 1] = IP_PROTOCOL_COMPLEMENT; - - for (i = ETH_HLEN; i < LP_PKT_LEN; i++) - test_data[i] = i & 0xFF; - - skb_tmp->queue_mapping = 0; - skb_tmp->ip_summed = CHECKSUM_COMPLETE; - skb_tmp->dev = netdev; - - for (i = 0; i < cnt; i++) { - nic_dev->lb_test_rx_idx = 0; - memset(lb_test_rx_buf, 0, LP_PKT_CNT * LP_PKT_LEN); - - for (j = 0; j < LP_PKT_CNT; j++) { - skb = pskb_copy(skb_tmp, GFP_ATOMIC); - if (!skb) { - dev_kfree_skb_any(skb_tmp); - nicif_err(nic_dev, drv, netdev, "Copy skb failed for loopback test\n"); - return -ENOMEM; - } - - /* mark index for every pkt */ - skb->data[LP_PKT_LEN - 1] = j; - - if (spnic_lb_xmit_frame(skb, netdev)) { - dev_kfree_skb_any(skb); - dev_kfree_skb_any(skb_tmp); - nicif_err(nic_dev, drv, netdev, "Xmit pkt failed for loopback test\n"); - return -EBUSY; - } - } - - /* wait till all pkts received to RX buffer */ - msleep(200); - - for (j = 0; j < LP_PKT_CNT; j++) { - if (memcmp((lb_test_rx_buf + (j * LP_PKT_LEN)), - skb_tmp->data, (LP_PKT_LEN - 1)) || - (*(lb_test_rx_buf + ((j * LP_PKT_LEN) + - (LP_PKT_LEN - 1))) != j)) { - dev_kfree_skb_any(skb_tmp); - nicif_err(nic_dev, drv, netdev, - "Compare pkt failed in loopback test(index=0x%02x, data[%d]=0x%02x)\n", - (j + (i * LP_PKT_CNT)), (LP_PKT_LEN - 1), - *(lb_test_rx_buf + - ((j * LP_PKT_LEN) + (LP_PKT_LEN - 1)))); - return -EIO; - } - } - } - - dev_kfree_skb_any(skb_tmp); - nicif_info(nic_dev, drv, netdev, "Loopback test succeed.\n"); - return 0; -} - -enum diag_test_index { - INTERNAL_LP_TEST = 0, - EXTERNAL_LP_TEST = 1, - DIAG_TEST_MAX = 2, -}; - -#define SPNIC_INTERNAL_LP_MODE 5 -static int do_lp_test(struct spnic_nic_dev *nic_dev, u32 *flags, u32 test_time, - enum diag_test_index *test_index) -{ - struct net_device *netdev = nic_dev->netdev; - u8 *lb_test_rx_buf = NULL; - int err = 0; - - if (!(*flags & ETH_TEST_FL_EXTERNAL_LB)) { - *test_index = INTERNAL_LP_TEST; - if (spnic_set_loopback_mode(nic_dev->hwdev, SPNIC_INTERNAL_LP_MODE, true)) { - nicif_err(nic_dev, drv, netdev, - "Failed to set port loopback mode before loopback test\n"); - return -EFAULT; - } - } else { - *test_index = EXTERNAL_LP_TEST; - } - - lb_test_rx_buf = vmalloc(LP_PKT_CNT * LP_PKT_LEN); - if (!lb_test_rx_buf) { - nicif_err(nic_dev, drv, netdev, "Failed to alloc RX buffer for loopback test\n"); - err = -ENOMEM; - } else { - nic_dev->lb_test_rx_buf = lb_test_rx_buf; - nic_dev->lb_pkt_len = LP_PKT_LEN; - set_bit(SPNIC_LP_TEST, &nic_dev->flags); - - if (spnic_run_lp_test(nic_dev, test_time)) - err = -EFAULT; - - clear_bit(SPNIC_LP_TEST, &nic_dev->flags); - msleep(100); - vfree(lb_test_rx_buf); - nic_dev->lb_test_rx_buf = NULL; - } - - if (!(*flags & ETH_TEST_FL_EXTERNAL_LB)) { - if (spnic_set_loopback_mode(nic_dev->hwdev, SPNIC_INTERNAL_LP_MODE, false)) { - nicif_err(nic_dev, drv, netdev, - "Failed to cancel port loopback mode after loopback test\n"); - err = -EFAULT; - } - } else { - *flags |= ETH_TEST_FL_EXTERNAL_LB_DONE; - } - - return err; -} - -void spnic_lp_test(struct net_device *netdev, struct ethtool_test *eth_test, - u64 *data, u32 test_time) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - enum diag_test_index test_index = 0; - u8 link_status = 0; - int err; - - /* don't support loopback test when netdev is closed. */ - if (!test_bit(SPNIC_INTF_UP, &nic_dev->flags)) { - nicif_err(nic_dev, drv, netdev, - "Do not support loopback test when netdev is closed\n"); - eth_test->flags |= ETH_TEST_FL_FAILED; - data[PORT_DOWN_ERR_IDX] = 1; - return; - } - - if (test_time == 0) - test_time = LP_DEFAULT_TIME; - - netif_carrier_off(netdev); - netif_tx_disable(netdev); - - err = do_lp_test(nic_dev, ð_test->flags, test_time, &test_index); - if (err) { - eth_test->flags |= ETH_TEST_FL_FAILED; - data[test_index] = 1; - } - - netif_tx_wake_all_queues(netdev); - - err = spnic_get_link_state(nic_dev->hwdev, &link_status); - if (!err && link_status) - netif_carrier_on(netdev); -} - -static void spnic_diag_test(struct net_device *netdev, struct ethtool_test *eth_test, u64 *data) -{ - memset(data, 0, DIAG_TEST_MAX * sizeof(u64)); - - spnic_lp_test(netdev, eth_test, data, 0); -} - -static const struct ethtool_ops spnic_ethtool_ops = { - .supported_coalesce_params = ETHTOOL_COALESCE_USECS | - ETHTOOL_COALESCE_PKT_RATE_RX_USECS, - .get_link_ksettings = spnic_get_link_ksettings, - .set_link_ksettings = spnic_set_link_ksettings, - - .get_drvinfo = spnic_get_drvinfo, - .get_msglevel = spnic_get_msglevel, - .set_msglevel = spnic_set_msglevel, - .nway_reset = spnic_nway_reset, - .get_link = ethtool_op_get_link, - .get_ringparam = spnic_get_ringparam, - .set_ringparam = spnic_set_ringparam, - .get_pauseparam = spnic_get_pauseparam, - .set_pauseparam = spnic_set_pauseparam, - .get_sset_count = spnic_get_sset_count, - .get_ethtool_stats = spnic_get_ethtool_stats, - .get_strings = spnic_get_strings, - - .self_test = spnic_diag_test, - .set_phys_id = spnic_set_phys_id, - - .get_coalesce = spnic_get_coalesce, - .set_coalesce = spnic_set_coalesce, - .get_per_queue_coalesce = spnic_get_per_queue_coalesce, - .set_per_queue_coalesce = spnic_set_per_queue_coalesce, - - .get_rxnfc = spnic_get_rxnfc, - .set_rxnfc = spnic_set_rxnfc, - .get_priv_flags = spnic_get_priv_flags, - .set_priv_flags = spnic_set_priv_flags, - - .get_channels = spnic_get_channels, - .set_channels = spnic_set_channels, - - .get_module_info = spnic_get_module_info, - .get_module_eeprom = spnic_get_module_eeprom, - - .get_rxfh_indir_size = spnic_get_rxfh_indir_size, - .get_rxfh_key_size = spnic_get_rxfh_key_size, - .get_rxfh = spnic_get_rxfh, - .set_rxfh = spnic_set_rxfh, -}; - -static const struct ethtool_ops spnicvf_ethtool_ops = { - .supported_coalesce_params = ETHTOOL_COALESCE_USECS | - ETHTOOL_COALESCE_PKT_RATE_RX_USECS, - .get_link_ksettings = spnic_get_link_ksettings, - .get_drvinfo = spnic_get_drvinfo, - .get_msglevel = spnic_get_msglevel, - .set_msglevel = spnic_set_msglevel, - .get_link = ethtool_op_get_link, - .get_ringparam = spnic_get_ringparam, - - .set_ringparam = spnic_set_ringparam, - .get_sset_count = spnic_get_sset_count, - .get_ethtool_stats = spnic_get_ethtool_stats, - .get_strings = spnic_get_strings, - - .get_coalesce = spnic_get_coalesce, - .set_coalesce = spnic_set_coalesce, - .get_per_queue_coalesce = spnic_get_per_queue_coalesce, - .set_per_queue_coalesce = spnic_set_per_queue_coalesce, - - .get_rxnfc = spnic_get_rxnfc, - .set_rxnfc = spnic_set_rxnfc, - .get_priv_flags = spnic_get_priv_flags, - .set_priv_flags = spnic_set_priv_flags, - - .get_channels = spnic_get_channels, - .set_channels = spnic_set_channels, - - .get_rxfh_indir_size = spnic_get_rxfh_indir_size, - .get_rxfh_key_size = spnic_get_rxfh_key_size, - .get_rxfh = spnic_get_rxfh, - .set_rxfh = spnic_set_rxfh, -}; - -void spnic_set_ethtool_ops(struct net_device *netdev) -{ - netdev->ethtool_ops = &spnic_ethtool_ops; -} - -void spnicvf_set_ethtool_ops(struct net_device *netdev) -{ - netdev->ethtool_ops = &spnicvf_ethtool_ops; -} diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_ethtool_stats.c b/drivers/net/ethernet/ramaxel/spnic/spnic_ethtool_stats.c deleted file mode 100644 index 5a830e3454d4..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_ethtool_stats.c +++ /dev/null @@ -1,1035 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [NIC]" fmt - -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/device.h> -#include <linux/module.h> -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/interrupt.h> -#include <linux/etherdevice.h> -#include <linux/netdevice.h> -#include <linux/if_vlan.h> -#include <linux/ethtool.h> - -#include "sphw_hw.h" -#include "sphw_crm.h" -#include "sphw_mt.h" -#include "spnic_nic_cfg.h" -#include "spnic_nic_dev.h" -#include "spnic_tx.h" -#include "spnic_rx.h" - -struct spnic_stats { - char name[ETH_GSTRING_LEN]; - u32 size; - int offset; -}; - -#define SPNIC_NETDEV_STAT(_stat_item) { \ - .name = #_stat_item, \ - .size = sizeof_field(struct rtnl_link_stats64, _stat_item), \ - .offset = offsetof(struct rtnl_link_stats64, _stat_item) \ -} - -static struct spnic_stats spnic_netdev_stats[] = { - SPNIC_NETDEV_STAT(rx_packets), - SPNIC_NETDEV_STAT(tx_packets), - SPNIC_NETDEV_STAT(rx_bytes), - SPNIC_NETDEV_STAT(tx_bytes), - SPNIC_NETDEV_STAT(rx_errors), - SPNIC_NETDEV_STAT(tx_errors), - SPNIC_NETDEV_STAT(rx_dropped), - SPNIC_NETDEV_STAT(tx_dropped), - SPNIC_NETDEV_STAT(multicast), - SPNIC_NETDEV_STAT(collisions), - SPNIC_NETDEV_STAT(rx_length_errors), - SPNIC_NETDEV_STAT(rx_over_errors), - SPNIC_NETDEV_STAT(rx_crc_errors), - SPNIC_NETDEV_STAT(rx_frame_errors), - SPNIC_NETDEV_STAT(rx_fifo_errors), - SPNIC_NETDEV_STAT(rx_missed_errors), - SPNIC_NETDEV_STAT(tx_aborted_errors), - SPNIC_NETDEV_STAT(tx_carrier_errors), - SPNIC_NETDEV_STAT(tx_fifo_errors), - SPNIC_NETDEV_STAT(tx_heartbeat_errors), -}; - -#define SPNIC_NIC_STAT(_stat_item) { \ - .name = #_stat_item, \ - .size = sizeof_field(struct spnic_nic_stats, _stat_item), \ - .offset = offsetof(struct spnic_nic_stats, _stat_item) \ -} - -static struct spnic_stats spnic_nic_dev_stats[] = { - SPNIC_NIC_STAT(netdev_tx_timeout), -}; - -static struct spnic_stats spnic_nic_dev_stats_extern[] = { - SPNIC_NIC_STAT(tx_carrier_off_drop), - SPNIC_NIC_STAT(tx_invalid_qid), -}; - -#define SPNIC_RXQ_STAT(_stat_item) { \ - .name = "rxq%d_"#_stat_item, \ - .size = sizeof_field(struct spnic_rxq_stats, _stat_item), \ - .offset = offsetof(struct spnic_rxq_stats, _stat_item) \ -} - -#define SPNIC_TXQ_STAT(_stat_item) { \ - .name = "txq%d_"#_stat_item, \ - .size = sizeof_field(struct spnic_txq_stats, _stat_item), \ - .offset = offsetof(struct spnic_txq_stats, _stat_item) \ -} - -static struct spnic_stats spnic_rx_queue_stats[] = { - SPNIC_RXQ_STAT(packets), - SPNIC_RXQ_STAT(bytes), - SPNIC_RXQ_STAT(errors), - SPNIC_RXQ_STAT(csum_errors), - SPNIC_RXQ_STAT(other_errors), - SPNIC_RXQ_STAT(dropped), - SPNIC_RXQ_STAT(xdp_dropped), - SPNIC_RXQ_STAT(rx_buf_empty), -}; - -static struct spnic_stats spnic_rx_queue_stats_extern[] = { - SPNIC_RXQ_STAT(alloc_skb_err), - SPNIC_RXQ_STAT(alloc_rx_buf_err), - SPNIC_RXQ_STAT(xdp_large_pkt), -}; - -static struct spnic_stats spnic_tx_queue_stats[] = { - SPNIC_TXQ_STAT(packets), - SPNIC_TXQ_STAT(bytes), - SPNIC_TXQ_STAT(busy), - SPNIC_TXQ_STAT(wake), - SPNIC_TXQ_STAT(dropped), -}; - -static struct spnic_stats spnic_tx_queue_stats_extern[] = { - SPNIC_TXQ_STAT(skb_pad_err), - SPNIC_TXQ_STAT(frag_len_overflow), - SPNIC_TXQ_STAT(offload_cow_skb_err), - SPNIC_TXQ_STAT(map_frag_err), - SPNIC_TXQ_STAT(unknown_tunnel_pkt), - SPNIC_TXQ_STAT(frag_size_err), -}; - -#define SPNIC_FUNC_STAT(_stat_item) { \ - .name = #_stat_item, \ - .size = sizeof_field(struct spnic_vport_stats, _stat_item), \ - .offset = offsetof(struct spnic_vport_stats, _stat_item) \ -} - -static struct spnic_stats spnic_function_stats[] = { - SPNIC_FUNC_STAT(tx_unicast_pkts_vport), - SPNIC_FUNC_STAT(tx_unicast_bytes_vport), - SPNIC_FUNC_STAT(tx_multicast_pkts_vport), - SPNIC_FUNC_STAT(tx_multicast_bytes_vport), - SPNIC_FUNC_STAT(tx_broadcast_pkts_vport), - SPNIC_FUNC_STAT(tx_broadcast_bytes_vport), - - SPNIC_FUNC_STAT(rx_unicast_pkts_vport), - SPNIC_FUNC_STAT(rx_unicast_bytes_vport), - SPNIC_FUNC_STAT(rx_multicast_pkts_vport), - SPNIC_FUNC_STAT(rx_multicast_bytes_vport), - SPNIC_FUNC_STAT(rx_broadcast_pkts_vport), - SPNIC_FUNC_STAT(rx_broadcast_bytes_vport), - - SPNIC_FUNC_STAT(tx_discard_vport), - SPNIC_FUNC_STAT(rx_discard_vport), - SPNIC_FUNC_STAT(tx_err_vport), - SPNIC_FUNC_STAT(rx_err_vport), -}; - -#define SPNIC_PORT_STAT(_stat_item) { \ - .name = #_stat_item, \ - .size = sizeof_field(struct mag_cmd_port_stats, _stat_item), \ - .offset = offsetof(struct mag_cmd_port_stats, _stat_item) \ -} - -static struct spnic_stats spnic_port_stats[] = { - SPNIC_PORT_STAT(mac_rx_total_pkt_num), - SPNIC_PORT_STAT(mac_rx_total_oct_num), - SPNIC_PORT_STAT(mac_rx_bad_pkt_num), - SPNIC_PORT_STAT(mac_rx_bad_oct_num), - SPNIC_PORT_STAT(mac_rx_good_pkt_num), - SPNIC_PORT_STAT(mac_rx_good_oct_num), - SPNIC_PORT_STAT(mac_rx_uni_pkt_num), - SPNIC_PORT_STAT(mac_rx_multi_pkt_num), - SPNIC_PORT_STAT(mac_rx_broad_pkt_num), - SPNIC_PORT_STAT(mac_tx_total_pkt_num), - SPNIC_PORT_STAT(mac_tx_total_oct_num), - SPNIC_PORT_STAT(mac_tx_bad_pkt_num), - SPNIC_PORT_STAT(mac_tx_bad_oct_num), - SPNIC_PORT_STAT(mac_tx_good_pkt_num), - SPNIC_PORT_STAT(mac_tx_good_oct_num), - SPNIC_PORT_STAT(mac_tx_uni_pkt_num), - SPNIC_PORT_STAT(mac_tx_multi_pkt_num), - SPNIC_PORT_STAT(mac_tx_broad_pkt_num), - SPNIC_PORT_STAT(mac_rx_fragment_pkt_num), - SPNIC_PORT_STAT(mac_rx_undersize_pkt_num), - SPNIC_PORT_STAT(mac_rx_undermin_pkt_num), - SPNIC_PORT_STAT(mac_rx_64_oct_pkt_num), - SPNIC_PORT_STAT(mac_rx_65_127_oct_pkt_num), - SPNIC_PORT_STAT(mac_rx_128_255_oct_pkt_num), - SPNIC_PORT_STAT(mac_rx_256_511_oct_pkt_num), - SPNIC_PORT_STAT(mac_rx_512_1023_oct_pkt_num), - SPNIC_PORT_STAT(mac_rx_1024_1518_oct_pkt_num), - SPNIC_PORT_STAT(mac_rx_1519_2047_oct_pkt_num), - SPNIC_PORT_STAT(mac_rx_2048_4095_oct_pkt_num), - SPNIC_PORT_STAT(mac_rx_4096_8191_oct_pkt_num), - SPNIC_PORT_STAT(mac_rx_8192_9216_oct_pkt_num), - SPNIC_PORT_STAT(mac_rx_9217_12287_oct_pkt_num), - SPNIC_PORT_STAT(mac_rx_12288_16383_oct_pkt_num), - SPNIC_PORT_STAT(mac_rx_1519_max_good_pkt_num), - SPNIC_PORT_STAT(mac_rx_1519_max_bad_pkt_num), - SPNIC_PORT_STAT(mac_rx_oversize_pkt_num), - SPNIC_PORT_STAT(mac_rx_jabber_pkt_num), - SPNIC_PORT_STAT(mac_rx_pause_num), - SPNIC_PORT_STAT(mac_rx_pfc_pkt_num), - SPNIC_PORT_STAT(mac_rx_pfc_pri0_pkt_num), - SPNIC_PORT_STAT(mac_rx_pfc_pri1_pkt_num), - SPNIC_PORT_STAT(mac_rx_pfc_pri2_pkt_num), - SPNIC_PORT_STAT(mac_rx_pfc_pri3_pkt_num), - SPNIC_PORT_STAT(mac_rx_pfc_pri4_pkt_num), - SPNIC_PORT_STAT(mac_rx_pfc_pri5_pkt_num), - SPNIC_PORT_STAT(mac_rx_pfc_pri6_pkt_num), - SPNIC_PORT_STAT(mac_rx_pfc_pri7_pkt_num), - SPNIC_PORT_STAT(mac_rx_control_pkt_num), - SPNIC_PORT_STAT(mac_rx_sym_err_pkt_num), - SPNIC_PORT_STAT(mac_rx_fcs_err_pkt_num), - SPNIC_PORT_STAT(mac_rx_send_app_good_pkt_num), - SPNIC_PORT_STAT(mac_rx_send_app_bad_pkt_num), - SPNIC_PORT_STAT(mac_tx_fragment_pkt_num), - SPNIC_PORT_STAT(mac_tx_undersize_pkt_num), - SPNIC_PORT_STAT(mac_tx_undermin_pkt_num), - SPNIC_PORT_STAT(mac_tx_64_oct_pkt_num), - SPNIC_PORT_STAT(mac_tx_65_127_oct_pkt_num), - SPNIC_PORT_STAT(mac_tx_128_255_oct_pkt_num), - SPNIC_PORT_STAT(mac_tx_256_511_oct_pkt_num), - SPNIC_PORT_STAT(mac_tx_512_1023_oct_pkt_num), - SPNIC_PORT_STAT(mac_tx_1024_1518_oct_pkt_num), - SPNIC_PORT_STAT(mac_tx_1519_2047_oct_pkt_num), - SPNIC_PORT_STAT(mac_tx_2048_4095_oct_pkt_num), - SPNIC_PORT_STAT(mac_tx_4096_8191_oct_pkt_num), - SPNIC_PORT_STAT(mac_tx_8192_9216_oct_pkt_num), - SPNIC_PORT_STAT(mac_tx_9217_12287_oct_pkt_num), - SPNIC_PORT_STAT(mac_tx_12288_16383_oct_pkt_num), - SPNIC_PORT_STAT(mac_tx_1519_max_good_pkt_num), - SPNIC_PORT_STAT(mac_tx_1519_max_bad_pkt_num), - SPNIC_PORT_STAT(mac_tx_oversize_pkt_num), - SPNIC_PORT_STAT(mac_tx_jabber_pkt_num), - SPNIC_PORT_STAT(mac_tx_pause_num), - SPNIC_PORT_STAT(mac_tx_pfc_pkt_num), - SPNIC_PORT_STAT(mac_tx_pfc_pri0_pkt_num), - SPNIC_PORT_STAT(mac_tx_pfc_pri1_pkt_num), - SPNIC_PORT_STAT(mac_tx_pfc_pri2_pkt_num), - SPNIC_PORT_STAT(mac_tx_pfc_pri3_pkt_num), - SPNIC_PORT_STAT(mac_tx_pfc_pri4_pkt_num), - SPNIC_PORT_STAT(mac_tx_pfc_pri5_pkt_num), - SPNIC_PORT_STAT(mac_tx_pfc_pri6_pkt_num), - SPNIC_PORT_STAT(mac_tx_pfc_pri7_pkt_num), - SPNIC_PORT_STAT(mac_tx_control_pkt_num), - SPNIC_PORT_STAT(mac_tx_err_all_pkt_num), - SPNIC_PORT_STAT(mac_tx_from_app_good_pkt_num), - SPNIC_PORT_STAT(mac_tx_from_app_bad_pkt_num), -}; - -static char g_spnic_priv_flags_strings[][ETH_GSTRING_LEN] = { - "Symmetric-RSS", -}; - -u32 spnic_get_io_stats_size(struct spnic_nic_dev *nic_dev) -{ - u32 count; - - count = ARRAY_LEN(spnic_nic_dev_stats) + - ARRAY_LEN(spnic_nic_dev_stats_extern) + - (ARRAY_LEN(spnic_tx_queue_stats) + - ARRAY_LEN(spnic_tx_queue_stats_extern) + - ARRAY_LEN(spnic_rx_queue_stats) + - ARRAY_LEN(spnic_rx_queue_stats_extern)) * nic_dev->max_qps; - - return count; -} - -#define GET_VALUE_OF_PTR(size, ptr) ( \ - (size) == sizeof(u64) ? *(u64 *)(ptr) : \ - (size) == sizeof(u32) ? *(u32 *)(ptr) : \ - (size) == sizeof(u16) ? *(u16 *)(ptr) : *(u8 *)(ptr) \ -) - -#define DEV_STATS_PACK(items, item_idx, array, stats_ptr) do { \ - int j; \ - for (j = 0; j < ARRAY_LEN(array); j++) { \ - memcpy((items)[item_idx].name, (array)[j].name, \ - SPNIC_SHOW_ITEM_LEN); \ - (items)[item_idx].hexadecimal = 0; \ - (items)[item_idx].value = \ - GET_VALUE_OF_PTR((array)[j].size, \ - (char *)(stats_ptr) + (array)[j].offset); \ - (item_idx)++; \ - } \ -} while (0) - -#define QUEUE_STATS_PACK(items, item_idx, array, stats_ptr, qid) do { \ - int j; \ - for (j = 0; j < ARRAY_LEN(array); j++) { \ - memcpy((items)[item_idx].name, (array)[j].name, \ - SPNIC_SHOW_ITEM_LEN); \ - snprintf((items)[item_idx].name, SPNIC_SHOW_ITEM_LEN, \ - (array)[j].name, (qid)); \ - (items)[item_idx].hexadecimal = 0; \ - (items)[item_idx].value = \ - GET_VALUE_OF_PTR((array)[j].size, \ - (char *)(stats_ptr) + (array)[j].offset); \ - (item_idx)++; \ - } \ -} while (0) - -void spnic_get_io_stats(struct spnic_nic_dev *nic_dev, void *stats) -{ - struct spnic_show_item *items = stats; - int item_idx = 0; - u16 qid; - - DEV_STATS_PACK(items, item_idx, spnic_nic_dev_stats, &nic_dev->stats); - DEV_STATS_PACK(items, item_idx, spnic_nic_dev_stats_extern, - &nic_dev->stats); - - for (qid = 0; qid < nic_dev->max_qps; qid++) { - QUEUE_STATS_PACK(items, item_idx, spnic_tx_queue_stats, - &nic_dev->txqs[qid].txq_stats, qid); - QUEUE_STATS_PACK(items, item_idx, spnic_tx_queue_stats_extern, - &nic_dev->txqs[qid].txq_stats, qid); - } - - for (qid = 0; qid < nic_dev->max_qps; qid++) { - QUEUE_STATS_PACK(items, item_idx, spnic_rx_queue_stats, - &nic_dev->rxqs[qid].rxq_stats, qid); - QUEUE_STATS_PACK(items, item_idx, spnic_rx_queue_stats_extern, - &nic_dev->rxqs[qid].rxq_stats, qid); - } -} - -static char spnic_test_strings[][ETH_GSTRING_LEN] = { - "Internal lb test (on/offline)", - "External lb test (external_lb)", -}; - -int spnic_get_sset_count(struct net_device *netdev, int sset) -{ - int count = 0, q_num = 0; - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - - switch (sset) { - case ETH_SS_TEST: - return ARRAY_LEN(spnic_test_strings); - case ETH_SS_STATS: - q_num = nic_dev->q_params.num_qps; - count = ARRAY_LEN(spnic_netdev_stats) + - ARRAY_LEN(spnic_nic_dev_stats) + - ARRAY_LEN(spnic_function_stats) + - (ARRAY_LEN(spnic_tx_queue_stats) + - ARRAY_LEN(spnic_rx_queue_stats)) * q_num; - - if (!SPNIC_FUNC_IS_VF(nic_dev->hwdev)) - count += ARRAY_LEN(spnic_port_stats); - - return count; - case ETH_SS_PRIV_FLAGS: - return ARRAY_LEN(g_spnic_priv_flags_strings); - default: - return -EOPNOTSUPP; - } -} - -static void get_drv_queue_stats(struct spnic_nic_dev *nic_dev, u64 *data) -{ - struct spnic_txq_stats txq_stats; - struct spnic_rxq_stats rxq_stats; - u16 i = 0, j = 0, qid = 0; - char *p = NULL; - - for (qid = 0; qid < nic_dev->q_params.num_qps; qid++) { - if (!nic_dev->txqs) - break; - - spnic_txq_get_stats(&nic_dev->txqs[qid], &txq_stats); - for (j = 0; j < ARRAY_LEN(spnic_tx_queue_stats); j++, i++) { - p = (char *)(&txq_stats) + - spnic_tx_queue_stats[j].offset; - data[i] = (spnic_tx_queue_stats[j].size == - sizeof(u64)) ? *(u64 *)p : *(u32 *)p; - } - } - - for (qid = 0; qid < nic_dev->q_params.num_qps; qid++) { - if (!nic_dev->rxqs) - break; - - spnic_rxq_get_stats(&nic_dev->rxqs[qid], &rxq_stats); - for (j = 0; j < ARRAY_LEN(spnic_rx_queue_stats); j++, i++) { - p = (char *)(&rxq_stats) + - spnic_rx_queue_stats[j].offset; - data[i] = (spnic_rx_queue_stats[j].size == - sizeof(u64)) ? *(u64 *)p : *(u32 *)p; - } - } -} - -static u16 get_ethtool_port_stats(struct spnic_nic_dev *nic_dev, u64 *data) -{ - struct mag_cmd_port_stats *port_stats; - char *p = NULL; - u16 i = 0, j = 0; - int err; - - port_stats = kzalloc(sizeof(*port_stats), GFP_KERNEL); - if (!port_stats) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Failed to malloc port stats\n"); - memset(&data[i], 0, - ARRAY_LEN(spnic_port_stats) * sizeof(*data)); - i += ARRAY_LEN(spnic_port_stats); - return i; - } - - err = spnic_get_phy_port_stats(nic_dev->hwdev, port_stats); - if (err) - nicif_err(nic_dev, drv, nic_dev->netdev, - "Failed to get port stats from fw\n"); - - for (j = 0; j < ARRAY_LEN(spnic_port_stats); j++, i++) { - p = (char *)(port_stats) + spnic_port_stats[j].offset; - data[i] = (spnic_port_stats[j].size == - sizeof(u64)) ? *(u64 *)p : *(u32 *)p; - } - - kfree(port_stats); - - return i; -} - -void spnic_get_ethtool_stats(struct net_device *netdev, struct ethtool_stats *stats, u64 *data) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - struct rtnl_link_stats64 temp; - const struct rtnl_link_stats64 *net_stats = NULL; - struct spnic_nic_stats *nic_stats = NULL; - - struct spnic_vport_stats vport_stats = {0}; - u16 i = 0, j = 0; - char *p = NULL; - int err; - - net_stats = dev_get_stats(netdev, &temp); - for (j = 0; j < ARRAY_LEN(spnic_netdev_stats); j++, i++) { - p = (char *)(net_stats) + spnic_netdev_stats[j].offset; - data[i] = GET_VALUE_OF_PTR(spnic_netdev_stats[j].size, p); - } - - nic_stats = &nic_dev->stats; - for (j = 0; j < ARRAY_LEN(spnic_nic_dev_stats); j++, i++) { - p = (char *)(nic_stats) + spnic_nic_dev_stats[j].offset; - data[i] = GET_VALUE_OF_PTR(spnic_nic_dev_stats[j].size, p); - } - - err = spnic_get_vport_stats(nic_dev->hwdev, &vport_stats); - if (err) - nicif_err(nic_dev, drv, netdev, - "Failed to get function stats from fw\n"); - - for (j = 0; j < ARRAY_LEN(spnic_function_stats); j++, i++) { - p = (char *)(&vport_stats) + spnic_function_stats[j].offset; - data[i] = GET_VALUE_OF_PTR(spnic_function_stats[j].size, p); - } - - if (!SPNIC_FUNC_IS_VF(nic_dev->hwdev)) - i += get_ethtool_port_stats(nic_dev, data + i); - - get_drv_queue_stats(nic_dev, data + i); -} - -static u16 get_drv_dev_strings(struct spnic_nic_dev *nic_dev, char *p) -{ - u16 i, cnt = 0; - - for (i = 0; i < ARRAY_LEN(spnic_netdev_stats); i++) { - memcpy(p, spnic_netdev_stats[i].name, - ETH_GSTRING_LEN); - p += ETH_GSTRING_LEN; - cnt++; - } - - for (i = 0; i < ARRAY_LEN(spnic_nic_dev_stats); i++) { - memcpy(p, spnic_nic_dev_stats[i].name, ETH_GSTRING_LEN); - p += ETH_GSTRING_LEN; - cnt++; - } - - return cnt; -} - -static u16 get_hw_stats_strings(struct spnic_nic_dev *nic_dev, char *p) -{ - u16 i, cnt = 0; - - for (i = 0; i < ARRAY_LEN(spnic_function_stats); i++) { - memcpy(p, spnic_function_stats[i].name, - ETH_GSTRING_LEN); - p += ETH_GSTRING_LEN; - cnt++; - } - - if (!SPNIC_FUNC_IS_VF(nic_dev->hwdev)) { - for (i = 0; i < ARRAY_LEN(spnic_port_stats); i++) { - memcpy(p, spnic_port_stats[i].name, - ETH_GSTRING_LEN); - p += ETH_GSTRING_LEN; - cnt++; - } - } - - return cnt; -} - -static u16 get_qp_stats_strings(struct spnic_nic_dev *nic_dev, char *p) -{ - u16 i = 0, j = 0, cnt = 0; - - for (i = 0; i < nic_dev->q_params.num_qps; i++) { - for (j = 0; j < ARRAY_LEN(spnic_tx_queue_stats); j++) { - sprintf(p, spnic_tx_queue_stats[j].name, i); - p += ETH_GSTRING_LEN; - cnt++; - } - } - - for (i = 0; i < nic_dev->q_params.num_qps; i++) { - for (j = 0; j < ARRAY_LEN(spnic_rx_queue_stats); j++) { - sprintf(p, spnic_rx_queue_stats[j].name, i); - p += ETH_GSTRING_LEN; - cnt++; - } - } - - return cnt; -} - -void spnic_get_strings(struct net_device *netdev, u32 stringset, u8 *data) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - char *p = (char *)data; - u16 offset = 0; - - switch (stringset) { - case ETH_SS_TEST: - memcpy(data, *spnic_test_strings, sizeof(spnic_test_strings)); - return; - case ETH_SS_STATS: - offset = get_drv_dev_strings(nic_dev, p); - offset += get_hw_stats_strings(nic_dev, - p + offset * ETH_GSTRING_LEN); - get_qp_stats_strings(nic_dev, p + offset * ETH_GSTRING_LEN); - - return; - case ETH_SS_PRIV_FLAGS: - memcpy(data, g_spnic_priv_flags_strings, - sizeof(g_spnic_priv_flags_strings)); - return; - default: - nicif_err(nic_dev, drv, netdev, - "Invalid string set %u.", stringset); - return; - } -} - -static const u32 spnic_mag_link_mode_ge[] = { - ETHTOOL_LINK_MODE_1000baseT_Full_BIT, - ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, - ETHTOOL_LINK_MODE_1000baseX_Full_BIT, -}; - -static const u32 spnic_mag_link_mode_10ge_base_r[] = { - ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, - ETHTOOL_LINK_MODE_10000baseR_FEC_BIT, - ETHTOOL_LINK_MODE_10000baseCR_Full_BIT, - ETHTOOL_LINK_MODE_10000baseSR_Full_BIT, - ETHTOOL_LINK_MODE_10000baseLR_Full_BIT, - ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT, -}; - -static const u32 spnic_mag_link_mode_25ge_base_r[] = { - ETHTOOL_LINK_MODE_25000baseCR_Full_BIT, - ETHTOOL_LINK_MODE_25000baseKR_Full_BIT, - ETHTOOL_LINK_MODE_25000baseSR_Full_BIT, -}; - -static const u32 spnic_mag_link_mode_40ge_base_r4[] = { - ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT, - ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT, - ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT, - ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT, -}; - -static const u32 spnic_mag_link_mode_50ge_base_r[] = { - ETHTOOL_LINK_MODE_50000baseKR_Full_BIT, - ETHTOOL_LINK_MODE_50000baseSR_Full_BIT, - ETHTOOL_LINK_MODE_50000baseCR_Full_BIT, -}; - -static const u32 spnic_mag_link_mode_50ge_base_r2[] = { - ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT, - ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT, - ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT, -}; - -static const u32 spnic_mag_link_mode_100ge_base_r[] = { - ETHTOOL_LINK_MODE_100000baseKR_Full_BIT, - ETHTOOL_LINK_MODE_100000baseSR_Full_BIT, - ETHTOOL_LINK_MODE_100000baseCR_Full_BIT, -}; - -static const u32 spnic_mag_link_mode_100ge_base_r2[] = { - ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT, - ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT, - ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT, -}; - -static const u32 spnic_mag_link_mode_100ge_base_r4[] = { - ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT, - ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT, - ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT, -}; - -static const u32 spnic_mag_link_mode_200ge_base_r2[] = { - ETHTOOL_LINK_MODE_200000baseKR2_Full_BIT, - ETHTOOL_LINK_MODE_200000baseSR2_Full_BIT, - ETHTOOL_LINK_MODE_200000baseCR2_Full_BIT, -}; - -static const u32 spnic_mag_link_mode_200ge_base_r4[] = { - ETHTOOL_LINK_MODE_200000baseKR4_Full_BIT, - ETHTOOL_LINK_MODE_200000baseSR4_Full_BIT, - ETHTOOL_LINK_MODE_200000baseCR4_Full_BIT, -}; - -struct hw2ethtool_link_mode { - const u32 *link_mode_bit_arr; - u32 arr_size; - u32 speed; -}; - -static const struct hw2ethtool_link_mode - hw2ethtool_link_mode_table[LINK_MODE_MAX_NUMBERS] = { - [LINK_MODE_GE] = { - .link_mode_bit_arr = spnic_mag_link_mode_ge, - .arr_size = ARRAY_LEN(spnic_mag_link_mode_ge), - .speed = SPEED_1000, - }, - [LINK_MODE_10GE_BASE_R] = { - .link_mode_bit_arr = spnic_mag_link_mode_10ge_base_r, - .arr_size = ARRAY_LEN(spnic_mag_link_mode_10ge_base_r), - .speed = SPEED_10000, - }, - [LINK_MODE_25GE_BASE_R] = { - .link_mode_bit_arr = spnic_mag_link_mode_25ge_base_r, - .arr_size = ARRAY_LEN(spnic_mag_link_mode_25ge_base_r), - .speed = SPEED_25000, - }, - [LINK_MODE_40GE_BASE_R4] = { - .link_mode_bit_arr = spnic_mag_link_mode_40ge_base_r4, - .arr_size = ARRAY_LEN(spnic_mag_link_mode_40ge_base_r4), - .speed = SPEED_40000, - }, - [LINK_MODE_50GE_BASE_R] = { - .link_mode_bit_arr = spnic_mag_link_mode_50ge_base_r, - .arr_size = ARRAY_LEN(spnic_mag_link_mode_50ge_base_r), - .speed = SPEED_50000, - }, - [LINK_MODE_50GE_BASE_R2] = { - .link_mode_bit_arr = spnic_mag_link_mode_50ge_base_r2, - .arr_size = ARRAY_LEN(spnic_mag_link_mode_50ge_base_r2), - .speed = SPEED_50000, - }, - [LINK_MODE_100GE_BASE_R] = { - .link_mode_bit_arr = spnic_mag_link_mode_100ge_base_r, - .arr_size = ARRAY_LEN(spnic_mag_link_mode_100ge_base_r), - .speed = SPEED_100000, - }, - [LINK_MODE_100GE_BASE_R2] = { - .link_mode_bit_arr = spnic_mag_link_mode_100ge_base_r2, - .arr_size = ARRAY_LEN(spnic_mag_link_mode_100ge_base_r2), - .speed = SPEED_100000, - }, - [LINK_MODE_100GE_BASE_R4] = { - .link_mode_bit_arr = spnic_mag_link_mode_100ge_base_r4, - .arr_size = ARRAY_LEN(spnic_mag_link_mode_100ge_base_r4), - .speed = SPEED_100000, - }, - [LINK_MODE_200GE_BASE_R2] = { - .link_mode_bit_arr = spnic_mag_link_mode_200ge_base_r2, - .arr_size = ARRAY_LEN(spnic_mag_link_mode_200ge_base_r2), - .speed = SPEED_200000, - }, - [LINK_MODE_200GE_BASE_R4] = { - .link_mode_bit_arr = spnic_mag_link_mode_200ge_base_r4, - .arr_size = ARRAY_LEN(spnic_mag_link_mode_200ge_base_r4), - .speed = SPEED_200000, - }, -}; - -#define GET_SUPPORTED_MODE 0 -#define GET_ADVERTISED_MODE 1 - -struct cmd_link_settings { - __ETHTOOL_DECLARE_LINK_MODE_MASK(supported); - __ETHTOOL_DECLARE_LINK_MODE_MASK(advertising); - - u32 speed; - u8 duplex; - u8 port; - u8 autoneg; -}; - -#define ETHTOOL_ADD_SUPPORTED_LINK_MODE(ecmd, mode) \ - set_bit(ETHTOOL_LINK_MODE_##mode##_BIT, (ecmd)->supported) -#define ETHTOOL_ADD_ADVERTISED_LINK_MODE(ecmd, mode) \ - set_bit(ETHTOOL_LINK_MODE_##mode##_BIT, (ecmd)->advertising) - -#define ETHTOOL_ADD_SUPPORTED_SPEED_LINK_MODE(ecmd, mode) \ -do { \ - u32 i; \ - for (i = 0; i < hw2ethtool_link_mode_table[mode].arr_size; i++) \ - set_bit(hw2ethtool_link_mode_table[mode].link_mode_bit_arr[i], \ - (ecmd)->supported); \ -} while (0) - -#define ETHTOOL_ADD_ADVERTISED_SPEED_LINK_MODE(ecmd, mode) \ -do { \ - u32 i; \ - for (i = 0; i < hw2ethtool_link_mode_table[mode].arr_size; i++) \ - set_bit(hw2ethtool_link_mode_table[mode].link_mode_bit_arr[i], \ - (ecmd)->advertising); \ -} while (0) - -/* Related to enum mag_cmd_port_speed */ -static u32 hw_to_ethtool_speed[] = { - (u32)SPEED_UNKNOWN, SPEED_10, SPEED_100, SPEED_1000, SPEED_10000, - SPEED_25000, SPEED_40000, SPEED_50000, SPEED_100000, SPEED_200000 -}; - -static int spnic_ethtool_to_hw_speed_level(u32 speed) -{ - int i; - - for (i = 0; i < ARRAY_LEN(hw_to_ethtool_speed); i++) { - if (hw_to_ethtool_speed[i] == speed) - break; - } - - return i; -} - -static void -spnic_add_ethtool_link_mode(struct cmd_link_settings *link_settings, u32 hw_link_mode, u32 name) -{ - u32 link_mode; - - for (link_mode = 0; link_mode < LINK_MODE_MAX_NUMBERS; link_mode++) { - if (hw_link_mode & BIT(link_mode)) { - if (name == GET_SUPPORTED_MODE) - ETHTOOL_ADD_SUPPORTED_SPEED_LINK_MODE(link_settings, link_mode); - else - ETHTOOL_ADD_ADVERTISED_SPEED_LINK_MODE(link_settings, link_mode); - } - } -} - -static int spnic_link_speed_set(struct spnic_nic_dev *nic_dev, - struct cmd_link_settings *link_settings, - struct nic_port_info *port_info) -{ - u8 link_state = 0; - int err; - - if (port_info->supported_mode != LINK_MODE_UNKNOWN) - spnic_add_ethtool_link_mode(link_settings, port_info->supported_mode, - GET_SUPPORTED_MODE); - if (port_info->advertised_mode != LINK_MODE_UNKNOWN) - spnic_add_ethtool_link_mode(link_settings, port_info->advertised_mode, - GET_ADVERTISED_MODE); - - err = spnic_get_link_state(nic_dev->hwdev, &link_state); - if (!err && link_state) { - link_settings->speed = - port_info->speed < ARRAY_LEN(hw_to_ethtool_speed) ? - hw_to_ethtool_speed[port_info->speed] : - (u32)SPEED_UNKNOWN; - - link_settings->duplex = port_info->duplex; - } else { - link_settings->speed = (u32)SPEED_UNKNOWN; - link_settings->duplex = DUPLEX_UNKNOWN; - } - - return 0; -} - -static void spnic_link_port_type(struct cmd_link_settings *link_settings, u8 port_type) -{ - switch (port_type) { - case MAG_CMD_WIRE_TYPE_ELECTRIC: - ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, TP); - ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, TP); - link_settings->port = PORT_TP; - break; - - case MAG_CMD_WIRE_TYPE_AOC: - case MAG_CMD_WIRE_TYPE_MM: - case MAG_CMD_WIRE_TYPE_SM: - ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, FIBRE); - ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, FIBRE); - link_settings->port = PORT_FIBRE; - break; - - case MAG_CMD_WIRE_TYPE_COPPER: - ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, FIBRE); - ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, FIBRE); - link_settings->port = PORT_DA; - break; - - case MAG_CMD_WIRE_TYPE_BACKPLANE: - ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, Backplane); - ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, Backplane); - link_settings->port = PORT_NONE; - break; - - default: - link_settings->port = PORT_OTHER; - break; - } -} - -static int get_link_pause_settings(struct spnic_nic_dev *nic_dev, - struct cmd_link_settings *link_settings) -{ - struct nic_pause_config nic_pause = {0}; - int err; - - err = spnic_get_pause_info(nic_dev->hwdev, &nic_pause); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Failed to get pauseparam from hw\n"); - return err; - } - - ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, Pause); - if (nic_pause.rx_pause && nic_pause.tx_pause) { - ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, Pause); - } else if (nic_pause.tx_pause) { - ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, Asym_Pause); - } else if (nic_pause.rx_pause) { - ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, Pause); - ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, Asym_Pause); - } - - return 0; -} - -int get_link_settings(struct net_device *netdev, struct cmd_link_settings *link_settings) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - struct nic_port_info port_info = {0}; - int err; - - err = spnic_get_port_info(nic_dev->hwdev, &port_info, SPHW_CHANNEL_NIC); - if (err) { - nicif_err(nic_dev, drv, netdev, "Failed to get port info\n"); - return err; - } - - err = spnic_link_speed_set(nic_dev, link_settings, &port_info); - if (err) - return err; - - spnic_link_port_type(link_settings, port_info.port_type); - - link_settings->autoneg = port_info.autoneg_state == PORT_CFG_AN_ON ? - AUTONEG_ENABLE : AUTONEG_DISABLE; - if (port_info.autoneg_cap) - ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, Autoneg); - if (port_info.autoneg_state == PORT_CFG_AN_ON) - ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, Autoneg); - - if (!SPNIC_FUNC_IS_VF(nic_dev->hwdev)) - err = get_link_pause_settings(nic_dev, link_settings); - - return err; -} - -int spnic_get_link_ksettings(struct net_device *netdev, - struct ethtool_link_ksettings *link_settings) -{ - struct cmd_link_settings settings = { { 0 } }; - struct ethtool_link_settings *base = &link_settings->base; - int err; - - ethtool_link_ksettings_zero_link_mode(link_settings, supported); - ethtool_link_ksettings_zero_link_mode(link_settings, advertising); - - err = get_link_settings(netdev, &settings); - if (err) - return err; - - bitmap_copy(link_settings->link_modes.supported, settings.supported, - __ETHTOOL_LINK_MODE_MASK_NBITS); - bitmap_copy(link_settings->link_modes.advertising, settings.advertising, - __ETHTOOL_LINK_MODE_MASK_NBITS); - - base->autoneg = settings.autoneg; - base->speed = settings.speed; - base->duplex = settings.duplex; - base->port = settings.port; - - return 0; -} - -static bool spnic_is_support_speed(u32 supported_link, u32 speed) -{ - u32 link_mode; - - for (link_mode = 0; link_mode < LINK_MODE_MAX_NUMBERS; link_mode++) { - if (!(supported_link & BIT(link_mode))) - continue; - - if (hw2ethtool_link_mode_table[link_mode].speed == speed) - return true; - } - - return false; -} - -static int spnic_is_speed_legal(struct spnic_nic_dev *nic_dev, - struct nic_port_info *port_info, u32 speed) -{ - struct net_device *netdev = nic_dev->netdev; - int speed_level = 0; - - if (port_info->supported_mode == LINK_MODE_UNKNOWN || - port_info->advertised_mode == LINK_MODE_UNKNOWN) { - nicif_err(nic_dev, drv, netdev, "Unknown supported link modes\n"); - return -EAGAIN; - } - - speed_level = spnic_ethtool_to_hw_speed_level(speed); - if (speed_level >= PORT_SPEED_UNKNOWN || - !spnic_is_support_speed(port_info->supported_mode, speed)) { - nicif_err(nic_dev, drv, netdev, - "Not supported speed: %u\n", speed); - return -EINVAL; - } - - return 0; -} - -static int get_link_settings_type(struct spnic_nic_dev *nic_dev, - u8 autoneg, u32 speed, u32 *set_settings) -{ - struct nic_port_info port_info = {0}; - int err; - - err = spnic_get_port_info(nic_dev->hwdev, &port_info, SPHW_CHANNEL_NIC); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to get current settings\n"); - return -EAGAIN; - } - - /* Alwayse set autonegation */ - if (port_info.autoneg_cap) - *set_settings |= HILINK_LINK_SET_AUTONEG; - - if (autoneg == AUTONEG_ENABLE) { - if (!port_info.autoneg_cap) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Not support autoneg\n"); - return -EOPNOTSUPP; - } - } else if (speed != (u32)SPEED_UNKNOWN) { - /* Set speed only when autoneg is disable */ - err = spnic_is_speed_legal(nic_dev, &port_info, speed); - if (err) - return err; - - *set_settings |= HILINK_LINK_SET_SPEED; - } else { - nicif_err(nic_dev, drv, nic_dev->netdev, "Need to set speed when autoneg is off\n"); - return -EOPNOTSUPP; - } - - return 0; -} - -static int spnic_set_settings_to_hw(struct spnic_nic_dev *nic_dev, - u32 set_settings, u8 autoneg, u32 speed) -{ - struct net_device *netdev = nic_dev->netdev; - struct spnic_link_ksettings settings = {0}; - int speed_level = 0; - char set_link_str[128] = {0}; - int err = 0; - - snprintf(set_link_str, sizeof(set_link_str), "%s", - (set_settings & HILINK_LINK_SET_AUTONEG) ? - (autoneg ? "autong enable " : "autong disable ") : ""); - if (set_settings & HILINK_LINK_SET_SPEED) { - speed_level = spnic_ethtool_to_hw_speed_level(speed); - snprintf(set_link_str, sizeof(set_link_str), - "%sspeed %u ", set_link_str, speed); - } - - settings.valid_bitmap = set_settings; - settings.autoneg = autoneg ? PORT_CFG_AN_ON : PORT_CFG_AN_OFF; - settings.speed = (u8)speed_level; - - err = spnic_set_link_settings(nic_dev->hwdev, &settings); - if (err) - nicif_err(nic_dev, drv, netdev, "Set %sfailed\n", - set_link_str); - else - nicif_info(nic_dev, drv, netdev, "Set %ssuccess\n", - set_link_str); - - return err; -} - -int set_link_settings(struct net_device *netdev, u8 autoneg, u32 speed) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - u32 set_settings = 0; - int err = 0; - - err = get_link_settings_type(nic_dev, autoneg, speed, &set_settings); - if (err) - return err; - - if (set_settings) - err = spnic_set_settings_to_hw(nic_dev, set_settings, autoneg, speed); - else - nicif_info(nic_dev, drv, netdev, "Nothing changed, exiting without setting anything\n"); - - return err; -} - -int spnic_set_link_ksettings(struct net_device *netdev, - const struct ethtool_link_ksettings *link_settings) -{ - /* Only support to set autoneg and speed */ - return set_link_settings(netdev, link_settings->base.autoneg, - link_settings->base.speed); -} diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_filter.c b/drivers/net/ethernet/ramaxel/spnic/spnic_filter.c deleted file mode 100644 index d7ca2bed454b..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_filter.c +++ /dev/null @@ -1,411 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [NIC]" fmt -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/device.h> -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/etherdevice.h> -#include <linux/netdevice.h> -#include <linux/debugfs.h> -#include <linux/module.h> -#include <linux/moduleparam.h> - -#include "sphw_hw.h" -#include "sphw_crm.h" -#include "spnic_nic_dev.h" - -enum spnic_rx_mod { - SPNIC_RX_MODE_UC = 1 << 0, - SPNIC_RX_MODE_MC = 1 << 1, - SPNIC_RX_MODE_BC = 1 << 2, - SPNIC_RX_MODE_MC_ALL = 1 << 3, - SPNIC_RX_MODE_PROMISC = 1 << 4, -}; - -static int spnic_uc_sync(struct net_device *netdev, u8 *addr) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - - return spnic_set_mac(nic_dev->hwdev, addr, 0, sphw_global_func_id(nic_dev->hwdev), - SPHW_CHANNEL_NIC); -} - -static int spnic_uc_unsync(struct net_device *netdev, u8 *addr) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - - /* The addr is in use */ - if (ether_addr_equal(addr, netdev->dev_addr)) - return 0; - - return spnic_del_mac(nic_dev->hwdev, addr, 0, sphw_global_func_id(nic_dev->hwdev), - SPHW_CHANNEL_NIC); -} - -void spnic_clean_mac_list_filter(struct spnic_nic_dev *nic_dev) -{ - struct net_device *netdev = nic_dev->netdev; - struct spnic_mac_filter *ftmp = NULL; - struct spnic_mac_filter *f = NULL; - - list_for_each_entry_safe(f, ftmp, &nic_dev->uc_filter_list, list) { - if (f->state == SPNIC_MAC_HW_SYNCED) - spnic_uc_unsync(netdev, f->addr); - list_del(&f->list); - kfree(f); - } - - list_for_each_entry_safe(f, ftmp, &nic_dev->mc_filter_list, list) { - if (f->state == SPNIC_MAC_HW_SYNCED) - spnic_uc_unsync(netdev, f->addr); - list_del(&f->list); - kfree(f); - } -} - -static struct spnic_mac_filter *spnic_find_mac(struct list_head *filter_list, u8 *addr) -{ - struct spnic_mac_filter *f = NULL; - - list_for_each_entry(f, filter_list, list) { - if (ether_addr_equal(addr, f->addr)) - return f; - } - return NULL; -} - -static struct spnic_mac_filter *spnic_add_filter(struct spnic_nic_dev *nic_dev, - struct list_head *mac_filter_list, u8 *addr) -{ - struct spnic_mac_filter *f; - - f = kzalloc(sizeof(*f), GFP_ATOMIC); - if (!f) - goto out; - - ether_addr_copy(f->addr, addr); - - INIT_LIST_HEAD(&f->list); - list_add_tail(&f->list, mac_filter_list); - - f->state = SPNIC_MAC_WAIT_HW_SYNC; - set_bit(SPNIC_MAC_FILTER_CHANGED, &nic_dev->flags); - -out: - return f; -} - -static void spnic_del_filter(struct spnic_nic_dev *nic_dev, struct spnic_mac_filter *f) -{ - set_bit(SPNIC_MAC_FILTER_CHANGED, &nic_dev->flags); - - if (f->state == SPNIC_MAC_WAIT_HW_SYNC) { - /* have not added to hw, delete it directly */ - list_del(&f->list); - kfree(f); - return; - } - - f->state = SPNIC_MAC_WAIT_HW_UNSYNC; -} - -static struct spnic_mac_filter *spnic_mac_filter_entry_clone(struct spnic_mac_filter *src) -{ - struct spnic_mac_filter *f; - - f = kzalloc(sizeof(*f), GFP_ATOMIC); - if (!f) - return NULL; - - *f = *src; - INIT_LIST_HEAD(&f->list); - - return f; -} - -static void spnic_undo_del_filter_entries(struct list_head *filter_list, struct list_head *from) -{ - struct spnic_mac_filter *ftmp = NULL; - struct spnic_mac_filter *f = NULL; - - list_for_each_entry_safe(f, ftmp, from, list) { - if (spnic_find_mac(filter_list, f->addr)) - continue; - - if (f->state == SPNIC_MAC_HW_SYNCED) - f->state = SPNIC_MAC_WAIT_HW_UNSYNC; - - list_move_tail(&f->list, filter_list); - } -} - -static void spnic_undo_add_filter_entries(struct list_head *filter_list, struct list_head *from) -{ - struct spnic_mac_filter *ftmp = NULL; - struct spnic_mac_filter *tmp = NULL; - struct spnic_mac_filter *f = NULL; - - list_for_each_entry_safe(f, ftmp, from, list) { - tmp = spnic_find_mac(filter_list, f->addr); - if (tmp && tmp->state == SPNIC_MAC_HW_SYNCED) - tmp->state = SPNIC_MAC_WAIT_HW_SYNC; - } -} - -static void spnic_cleanup_filter_list(struct list_head *head) -{ - struct spnic_mac_filter *ftmp = NULL; - struct spnic_mac_filter *f = NULL; - - list_for_each_entry_safe(f, ftmp, head, list) { - list_del(&f->list); - kfree(f); - } -} - -static int spnic_mac_filter_sync_hw(struct spnic_nic_dev *nic_dev, struct list_head *del_list, - struct list_head *add_list) -{ - struct net_device *netdev = nic_dev->netdev; - struct spnic_mac_filter *ftmp = NULL; - struct spnic_mac_filter *f = NULL; - int err = 0, add_count = 0; - - if (!list_empty(del_list)) { - list_for_each_entry_safe(f, ftmp, del_list, list) { - err = spnic_uc_unsync(netdev, f->addr); - if (err) { /* ignore errors when delete mac */ - nic_err(&nic_dev->pdev->dev, "Failed to delete mac\n"); - } - - list_del(&f->list); - kfree(f); - } - } - - if (!list_empty(add_list)) { - list_for_each_entry_safe(f, ftmp, add_list, list) { - err = spnic_uc_sync(netdev, f->addr); - if (err) { - nic_err(&nic_dev->pdev->dev, "Failed to add mac\n"); - return err; - } - - add_count++; - list_del(&f->list); - kfree(f); - } - } - - return add_count; -} - -static int spnic_mac_filter_sync(struct spnic_nic_dev *nic_dev, - struct list_head *mac_filter_list, bool uc) -{ - struct net_device *netdev = nic_dev->netdev; - struct list_head tmp_del_list, tmp_add_list; - struct spnic_mac_filter *fclone = NULL; - struct spnic_mac_filter *ftmp = NULL; - struct spnic_mac_filter *f = NULL; - int err = 0, add_count = 0; - - INIT_LIST_HEAD(&tmp_del_list); - INIT_LIST_HEAD(&tmp_add_list); - - list_for_each_entry_safe(f, ftmp, mac_filter_list, list) { - if (f->state != SPNIC_MAC_WAIT_HW_UNSYNC) - continue; - - f->state = SPNIC_MAC_HW_UNSYNCED; - list_move_tail(&f->list, &tmp_del_list); - } - - list_for_each_entry_safe(f, ftmp, mac_filter_list, list) { - if (f->state != SPNIC_MAC_WAIT_HW_SYNC) - continue; - - fclone = spnic_mac_filter_entry_clone(f); - if (!fclone) { - err = -ENOMEM; - break; - } - - f->state = SPNIC_MAC_HW_SYNCED; - list_add_tail(&fclone->list, &tmp_add_list); - } - - if (err) { - spnic_undo_del_filter_entries(mac_filter_list, &tmp_del_list); - spnic_undo_add_filter_entries(mac_filter_list, &tmp_add_list); - nicif_err(nic_dev, drv, netdev, "Failed to clone mac_filter_entry\n"); - - spnic_cleanup_filter_list(&tmp_del_list); - spnic_cleanup_filter_list(&tmp_add_list); - return -ENOMEM; - } - - add_count = spnic_mac_filter_sync_hw(nic_dev, &tmp_del_list, &tmp_add_list); - if (list_empty(&tmp_add_list)) - return add_count; - - /* there are errors when add mac to hw, delete all mac in hw */ - spnic_undo_add_filter_entries(mac_filter_list, &tmp_add_list); - /* VF don't support to enter promisc mode, - * so we can't delete any other uc mac - */ - if (!SPNIC_FUNC_IS_VF(nic_dev->hwdev) || !uc) { - list_for_each_entry_safe(f, ftmp, mac_filter_list, list) { - if (f->state != SPNIC_MAC_HW_SYNCED) - continue; - - fclone = spnic_mac_filter_entry_clone(f); - if (!fclone) - break; - - f->state = SPNIC_MAC_WAIT_HW_SYNC; - list_add_tail(&fclone->list, &tmp_del_list); - } - } - - spnic_cleanup_filter_list(&tmp_add_list); - spnic_mac_filter_sync_hw(nic_dev, &tmp_del_list, &tmp_add_list); - - /* need to enter promisc/allmulti mode */ - return -ENOMEM; -} - -static void spnic_mac_filter_sync_all(struct spnic_nic_dev *nic_dev) -{ - struct net_device *netdev = nic_dev->netdev; - int add_count; - - if (test_bit(SPNIC_MAC_FILTER_CHANGED, &nic_dev->flags)) { - clear_bit(SPNIC_MAC_FILTER_CHANGED, &nic_dev->flags); - add_count = spnic_mac_filter_sync(nic_dev, &nic_dev->uc_filter_list, true); - if (add_count < 0 && SPNIC_SUPPORT_PROMISC(nic_dev->hwdev)) { - set_bit(SPNIC_PROMISC_FORCE_ON, &nic_dev->rx_mod_state); - nicif_info(nic_dev, drv, netdev, "Promisc mode forced on\n"); - } else if (add_count) { - clear_bit(SPNIC_PROMISC_FORCE_ON, &nic_dev->rx_mod_state); - } - - add_count = spnic_mac_filter_sync(nic_dev, &nic_dev->mc_filter_list, false); - if (add_count < 0 && SPNIC_SUPPORT_ALLMULTI(nic_dev->hwdev)) { - set_bit(SPNIC_ALLMULTI_FORCE_ON, &nic_dev->rx_mod_state); - nicif_info(nic_dev, drv, netdev, "All multicast mode forced on\n"); - } else if (add_count) { - clear_bit(SPNIC_ALLMULTI_FORCE_ON, &nic_dev->rx_mod_state); - } - } -} - -#define SPNIC_DEFAULT_RX_MODE (SPNIC_RX_MODE_UC | SPNIC_RX_MODE_MC | \ - SPNIC_RX_MODE_BC) - -static void spnic_update_mac_filter(struct spnic_nic_dev *nic_dev, - struct netdev_hw_addr_list *src_list, - struct list_head *filter_list) -{ - struct spnic_mac_filter *filter = NULL; - struct spnic_mac_filter *ftmp = NULL; - struct spnic_mac_filter *f = NULL; - struct netdev_hw_addr *ha = NULL; - - /* add addr if not already in the filter list */ - netif_addr_lock_bh(nic_dev->netdev); - netdev_hw_addr_list_for_each(ha, src_list) { - filter = spnic_find_mac(filter_list, ha->addr); - if (!filter) - spnic_add_filter(nic_dev, filter_list, ha->addr); - else if (filter->state == SPNIC_MAC_WAIT_HW_UNSYNC) - filter->state = SPNIC_MAC_HW_SYNCED; - } - netif_addr_unlock_bh(nic_dev->netdev); - - /* delete addr if not in netdev list */ - list_for_each_entry_safe(f, ftmp, filter_list, list) { - bool found = false; - - netif_addr_lock_bh(nic_dev->netdev); - netdev_hw_addr_list_for_each(ha, src_list) - if (ether_addr_equal(ha->addr, f->addr)) { - found = true; - break; - } - netif_addr_unlock_bh(nic_dev->netdev); - - if (found) - continue; - - spnic_del_filter(nic_dev, f); - } -} - -static void update_mac_filter(struct spnic_nic_dev *nic_dev) -{ - struct net_device *netdev = nic_dev->netdev; - - if (test_and_clear_bit(SPNIC_UPDATE_MAC_FILTER, &nic_dev->flags)) { - spnic_update_mac_filter(nic_dev, &netdev->uc, &nic_dev->uc_filter_list); - spnic_update_mac_filter(nic_dev, &netdev->mc, &nic_dev->mc_filter_list); - } -} - -static void sync_rx_mode_to_hw(struct spnic_nic_dev *nic_dev, int promisc_en, - int allmulti_en) -{ - struct net_device *netdev = nic_dev->netdev; - u32 rx_mod = SPNIC_DEFAULT_RX_MODE; - int err; - - rx_mod |= (promisc_en ? SPNIC_RX_MODE_PROMISC : 0); - rx_mod |= (allmulti_en ? SPNIC_RX_MODE_MC_ALL : 0); - - if (promisc_en != test_bit(SPNIC_HW_PROMISC_ON, &nic_dev->rx_mod_state)) - nicif_info(nic_dev, drv, netdev, "%s promisc mode\n", - promisc_en ? "Enter" : "Left"); - if (allmulti_en != - test_bit(SPNIC_HW_ALLMULTI_ON, &nic_dev->rx_mod_state)) - nicif_info(nic_dev, drv, netdev, "%s all_multi mode\n", - allmulti_en ? "Enter" : "Left"); - - err = spnic_set_rx_mode(nic_dev->hwdev, rx_mod); - if (err) { - nicif_err(nic_dev, drv, netdev, "Failed to set rx_mode\n"); - return; - } - - promisc_en ? set_bit(SPNIC_HW_PROMISC_ON, &nic_dev->rx_mod_state) : - clear_bit(SPNIC_HW_PROMISC_ON, &nic_dev->rx_mod_state); - - allmulti_en ? set_bit(SPNIC_HW_ALLMULTI_ON, &nic_dev->rx_mod_state) : - clear_bit(SPNIC_HW_ALLMULTI_ON, &nic_dev->rx_mod_state); -} - -void spnic_set_rx_mode_work(struct work_struct *work) -{ - struct spnic_nic_dev *nic_dev = - container_of(work, struct spnic_nic_dev, rx_mode_work); - struct net_device *netdev = nic_dev->netdev; - int promisc_en = 0, allmulti_en = 0; - - update_mac_filter(nic_dev); - - spnic_mac_filter_sync_all(nic_dev); - - if (SPNIC_SUPPORT_PROMISC(nic_dev->hwdev)) - promisc_en = !!(netdev->flags & IFF_PROMISC) || - test_bit(SPNIC_PROMISC_FORCE_ON, &nic_dev->rx_mod_state); - - if (SPNIC_SUPPORT_ALLMULTI(nic_dev->hwdev)) - allmulti_en = !!(netdev->flags & IFF_ALLMULTI) || - test_bit(SPNIC_ALLMULTI_FORCE_ON, &nic_dev->rx_mod_state); - - if (promisc_en != test_bit(SPNIC_HW_PROMISC_ON, &nic_dev->rx_mod_state) || - allmulti_en != test_bit(SPNIC_HW_ALLMULTI_ON, &nic_dev->rx_mod_state)) - sync_rx_mode_to_hw(nic_dev, promisc_en, allmulti_en); -} diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_irq.c b/drivers/net/ethernet/ramaxel/spnic/spnic_irq.c deleted file mode 100644 index 872a94a73590..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_irq.c +++ /dev/null @@ -1,178 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [NIC]" fmt -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/device.h> -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/interrupt.h> -#include <linux/etherdevice.h> -#include <linux/netdevice.h> -#include <linux/debugfs.h> - -#include "sphw_hw.h" -#include "sphw_crm.h" -#include "spnic_nic_io.h" -#include "spnic_nic_dev.h" -#include "spnic_tx.h" -#include "spnic_rx.h" - -int spnic_poll(struct napi_struct *napi, int budget) -{ - struct spnic_irq *irq_cfg = container_of(napi, struct spnic_irq, napi); - struct spnic_nic_dev *nic_dev = netdev_priv(irq_cfg->netdev); - int tx_pkts, rx_pkts; - - rx_pkts = spnic_rx_poll(irq_cfg->rxq, budget); - - tx_pkts = spnic_tx_poll(irq_cfg->txq, budget); - - if (tx_pkts >= budget || rx_pkts >= budget) - return budget; - - napi_complete(napi); - - sphw_set_msix_state(nic_dev->hwdev, irq_cfg->msix_entry_idx, SPHW_MSIX_ENABLE); - - return max(tx_pkts, rx_pkts); -} - -static void qp_add_napi(struct spnic_irq *irq_cfg) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(irq_cfg->netdev); - - netif_napi_add(nic_dev->netdev, &irq_cfg->napi, spnic_poll, nic_dev->poll_weight); - napi_enable(&irq_cfg->napi); -} - -static void qp_del_napi(struct spnic_irq *irq_cfg) -{ - napi_disable(&irq_cfg->napi); - netif_napi_del(&irq_cfg->napi); -} - -static irqreturn_t qp_irq(int irq, void *data) -{ - struct spnic_irq *irq_cfg = (struct spnic_irq *)data; - struct spnic_nic_dev *nic_dev = netdev_priv(irq_cfg->netdev); - - /* 1 is resend_timer */ - sphw_misx_intr_clear_resend_bit(nic_dev->hwdev, irq_cfg->msix_entry_idx, 1); - - napi_schedule(&irq_cfg->napi); - return IRQ_HANDLED; -} - -static int spnic_request_irq(struct spnic_irq *irq_cfg, u16 q_id) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(irq_cfg->netdev); - struct interrupt_info info = {0}; - int err; - - qp_add_napi(irq_cfg); - - info.msix_index = irq_cfg->msix_entry_idx; - info.lli_set = 0; - info.interrupt_coalesc_set = 1; - info.pending_limt = nic_dev->intr_coalesce[q_id].pending_limt; - info.coalesc_timer_cfg = nic_dev->intr_coalesce[q_id].coalesce_timer_cfg; - info.resend_timer_cfg = nic_dev->intr_coalesce[q_id].resend_timer_cfg; - nic_dev->rxqs[q_id].last_coalesc_timer_cfg = - nic_dev->intr_coalesce[q_id].coalesce_timer_cfg; - nic_dev->rxqs[q_id].last_pending_limt = nic_dev->intr_coalesce[q_id].pending_limt; - err = sphw_set_interrupt_cfg(nic_dev->hwdev, info, SPHW_CHANNEL_NIC); - if (err) { - nicif_err(nic_dev, drv, irq_cfg->netdev, - "Failed to set RX interrupt coalescing attribute.\n"); - qp_del_napi(irq_cfg); - return err; - } - - err = request_irq(irq_cfg->irq_id, &qp_irq, 0, irq_cfg->irq_name, irq_cfg); - if (err) { - nicif_err(nic_dev, drv, irq_cfg->netdev, "Failed to request Rx irq\n"); - qp_del_napi(irq_cfg); - return err; - } - - irq_set_affinity_hint(irq_cfg->irq_id, &irq_cfg->affinity_mask); - - return 0; -} - -static void spnic_release_irq(struct spnic_irq *irq_cfg) -{ - irq_set_affinity_hint(irq_cfg->irq_id, NULL); - synchronize_irq(irq_cfg->irq_id); - free_irq(irq_cfg->irq_id, irq_cfg); - qp_del_napi(irq_cfg); -} - -int spnic_qps_irq_init(struct spnic_nic_dev *nic_dev) -{ - struct pci_dev *pdev = nic_dev->pdev; - struct irq_info *qp_irq_info = NULL; - struct spnic_irq *irq_cfg = NULL; - u16 q_id, i; - u32 local_cpu; - int err; - - for (q_id = 0; q_id < nic_dev->q_params.num_qps; q_id++) { - qp_irq_info = &nic_dev->qps_irq_info[q_id]; - irq_cfg = &nic_dev->q_params.irq_cfg[q_id]; - - irq_cfg->irq_id = qp_irq_info->irq_id; - irq_cfg->msix_entry_idx = qp_irq_info->msix_entry_idx; - irq_cfg->netdev = nic_dev->netdev; - irq_cfg->txq = &nic_dev->txqs[q_id]; - irq_cfg->rxq = &nic_dev->rxqs[q_id]; - nic_dev->rxqs[q_id].irq_cfg = irq_cfg; - - local_cpu = cpumask_local_spread(q_id, dev_to_node(&pdev->dev)); - cpumask_set_cpu(local_cpu, &irq_cfg->affinity_mask); - - snprintf(irq_cfg->irq_name, sizeof(irq_cfg->irq_name), - "%s_qp%u", nic_dev->netdev->name, q_id); - - err = spnic_request_irq(irq_cfg, q_id); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to request Rx irq\n"); - goto req_tx_irq_err; - } - - sphw_set_msix_auto_mask_state(nic_dev->hwdev, irq_cfg->msix_entry_idx, - SPHW_SET_MSIX_AUTO_MASK); - sphw_set_msix_state(nic_dev->hwdev, irq_cfg->msix_entry_idx, SPHW_MSIX_ENABLE); - } - - INIT_DELAYED_WORK(&nic_dev->moderation_task, spnic_auto_moderation_work); - - return 0; - -req_tx_irq_err: - for (i = 0; i < q_id; i++) { - irq_cfg = &nic_dev->q_params.irq_cfg[i]; - sphw_set_msix_state(nic_dev->hwdev, irq_cfg->msix_entry_idx, SPHW_MSIX_DISABLE); - sphw_set_msix_auto_mask_state(nic_dev->hwdev, irq_cfg->msix_entry_idx, - SPHW_CLR_MSIX_AUTO_MASK); - spnic_release_irq(irq_cfg); - } - - return err; -} - -void spnic_qps_irq_deinit(struct spnic_nic_dev *nic_dev) -{ - struct spnic_irq *irq_cfg = NULL; - u16 q_id; - - for (q_id = 0; q_id < nic_dev->q_params.num_qps; q_id++) { - irq_cfg = &nic_dev->q_params.irq_cfg[q_id]; - sphw_set_msix_state(nic_dev->hwdev, irq_cfg->msix_entry_idx, SPHW_MSIX_DISABLE); - sphw_set_msix_auto_mask_state(nic_dev->hwdev, irq_cfg->msix_entry_idx, - SPHW_CLR_MSIX_AUTO_MASK); - spnic_release_irq(irq_cfg); - } -} diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_lld.c b/drivers/net/ethernet/ramaxel/spnic/spnic_lld.c deleted file mode 100644 index f09a4c186aae..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_lld.c +++ /dev/null @@ -1,937 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [COMM]" fmt - -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/device.h> -#include <linux/module.h> -#include <linux/io-mapping.h> -#include <linux/interrupt.h> -#include <linux/inetdevice.h> -#include <net/addrconf.h> -#include <linux/time.h> -#include <linux/timex.h> -#include <linux/rtc.h> -#include <linux/aer.h> -#include <linux/debugfs.h> - -#include "sphw_common.h" -#include "sphw_mt.h" -#include "sphw_crm.h" -#include "spnic_lld.h" -#include "spnic_pci_id_tbl.h" -#include "spnic_sriov.h" -#include "spnic_dev_mgmt.h" -#include "sphw_hw.h" -#include "spnic_nic_dev.h" - -static bool disable_vf_load; -module_param(disable_vf_load, bool, 0444); -MODULE_PARM_DESC(disable_vf_load, "Disable virtual functions probe or not - default is false"); - -static bool disable_attach; -module_param(disable_attach, bool, 0444); -MODULE_PARM_DESC(disable_attach, "disable_attach or not - default is false"); - -#define SPNIC_WAIT_SRIOV_CFG_TIMEOUT 15000 -#define SPNIC_SYNC_YEAR_OFFSET 1900 - -MODULE_AUTHOR("Ramaxel Technologies CO., Ltd"); -MODULE_DESCRIPTION(SPNIC_DRV_DESC); -MODULE_VERSION(SPNIC_DRV_VERSION); -MODULE_LICENSE("GPL"); - -struct spnic_uld_info g_uld_info[SERVICE_T_MAX] = { {0} }; - -#define SPHW_EVENT_PROCESS_TIMEOUT 10000 - -static const char *s_uld_name[SERVICE_T_MAX] = { - "nic", "ovs", "roce", "toe", "ioe", - "fc", "vbs", "ipsec", "virtio", "migrate"}; - -static int attach_uld(struct spnic_pcidev *dev, enum sphw_service_type type, - struct spnic_uld_info *uld_info) -{ - void *uld_dev = NULL; - int err; - - mutex_lock(&dev->pdev_mutex); - - if (dev->uld_dev[type]) { - sdk_err(&dev->pcidev->dev, "%s driver has attached to pcie device\n", - s_uld_name[type]); - err = 0; - goto out_unlock; - } - - err = uld_info->probe(&dev->lld_dev, &uld_dev, dev->uld_dev_name[type]); - if (err || !uld_dev) { - sdk_err(&dev->pcidev->dev, "Failed to add object for %s driver to pcie device\n", - s_uld_name[type]); - goto probe_failed; - } - - dev->uld_dev[type] = uld_dev; - mutex_unlock(&dev->pdev_mutex); - - sdk_info(&dev->pcidev->dev, "Attach %s driver to pcie device succeed\n", s_uld_name[type]); - return 0; - -probe_failed: -out_unlock: - mutex_unlock(&dev->pdev_mutex); - - return err; -} - -static void detach_uld(struct spnic_pcidev *dev, enum sphw_service_type type) -{ - struct spnic_uld_info *uld_info = &g_uld_info[type]; - unsigned long end; - bool timeout = true; - - mutex_lock(&dev->pdev_mutex); - if (!dev->uld_dev[type]) { - mutex_unlock(&dev->pdev_mutex); - return; - } - - end = jiffies + msecs_to_jiffies(SPHW_EVENT_PROCESS_TIMEOUT); - do { - if (!test_and_set_bit(type, &dev->state)) { - timeout = false; - break; - } - usleep_range(900, 1000); - } while (time_before(jiffies, end)); - - if (timeout && !test_and_set_bit(type, &dev->state)) - timeout = false; - - uld_info->remove(&dev->lld_dev, dev->uld_dev[type]); - dev->uld_dev[type] = NULL; - if (!timeout) - clear_bit(type, &dev->state); - - sdk_info(&dev->pcidev->dev, "Detach %s driver from pcie device succeed\n", - s_uld_name[type]); - mutex_unlock(&dev->pdev_mutex); -} - -static void attach_ulds(struct spnic_pcidev *dev) -{ - enum sphw_service_type type; - struct pci_dev *pdev = dev->pcidev; - - for (type = SERVICE_T_NIC; type < SERVICE_T_MAX; type++) { - if (g_uld_info[type].probe) { - if (pdev->is_virtfn && (!spnic_get_vf_service_load(pdev, (u16)type))) { - sdk_info(&pdev->dev, "VF device disable service_type = %d load in host\n", - type); - continue; - } - attach_uld(dev, type, &g_uld_info[type]); - } - } -} - -static void detach_ulds(struct spnic_pcidev *dev) -{ - enum sphw_service_type type; - - for (type = SERVICE_T_MAX - 1; type > SERVICE_T_NIC; type--) { - if (g_uld_info[type].probe) - detach_uld(dev, type); - } - - if (g_uld_info[SERVICE_T_NIC].probe) - detach_uld(dev, SERVICE_T_NIC); -} - -int spnic_register_uld(enum sphw_service_type type, struct spnic_uld_info *uld_info) -{ - struct card_node *chip_node = NULL; - struct spnic_pcidev *dev = NULL; - - if (type >= SERVICE_T_MAX) { - pr_err("Unknown type %d of up layer driver to register\n", type); - return -EINVAL; - } - - if (!uld_info || !uld_info->probe || !uld_info->remove) { - pr_err("Invalid information of %s driver to register\n", s_uld_name[type]); - return -EINVAL; - } - - lld_hold(); - - if (g_uld_info[type].probe) { - pr_err("%s driver has registered\n", s_uld_name[type]); - lld_put(); - return -EINVAL; - } - - memcpy(&g_uld_info[type], uld_info, sizeof(*uld_info)); - list_for_each_entry(chip_node, &g_spnic_chip_list, node) { - list_for_each_entry(dev, &chip_node->func_list, node) { - if (attach_uld(dev, type, uld_info)) { - sdk_err(&dev->pcidev->dev, "Attach %s driver to pcie device failed\n", - s_uld_name[type]); - continue; - } - } - } - - lld_put(); - - pr_info("Register %s driver succeed\n", s_uld_name[type]); - return 0; -} - -void spnic_unregister_uld(enum sphw_service_type type) -{ - struct card_node *chip_node = NULL; - struct spnic_pcidev *dev = NULL; - struct spnic_uld_info *uld_info = NULL; - - if (type >= SERVICE_T_MAX) { - pr_err("Unknown type %d of up layer driver to unregister\n", type); - return; - } - - lld_hold(); - list_for_each_entry(chip_node, &g_spnic_chip_list, node) { - /* detach vf first */ - list_for_each_entry(dev, &chip_node->func_list, node) { - if (sphw_func_type(dev->hwdev) != TYPE_VF) - continue; - - detach_uld(dev, type); - } - - list_for_each_entry(dev, &chip_node->func_list, node) { - if (sphw_func_type(dev->hwdev) == TYPE_VF) - continue; - - detach_uld(dev, type); - } - } - - uld_info = &g_uld_info[type]; - memset(uld_info, 0, sizeof(*uld_info)); - lld_put(); -} - -int spnic_attach_nic(struct spnic_lld_dev *lld_dev) -{ - struct spnic_pcidev *dev = NULL; - - if (!lld_dev) - return -EINVAL; - - dev = container_of(lld_dev, struct spnic_pcidev, lld_dev); - return attach_uld(dev, SERVICE_T_NIC, &g_uld_info[SERVICE_T_NIC]); -} - -void spnic_detach_nic(struct spnic_lld_dev *lld_dev) -{ - struct spnic_pcidev *dev = NULL; - - if (!lld_dev) - return; - - dev = container_of(lld_dev, struct spnic_pcidev, lld_dev); - detach_uld(dev, SERVICE_T_NIC); -} - -static void sphw_sync_time_to_fmw(struct spnic_pcidev *pdev_pri) -{ - struct tm tm = {0}; - u64 tv_msec; - int err; - - tv_msec = ktime_to_ms(ktime_get_real()); - err = sphw_sync_time(pdev_pri->hwdev, tv_msec); - if (err) { - sdk_err(&pdev_pri->pcidev->dev, "Synchronize UTC time to firmware failed, errno:%d.\n", - err); - } else { - time64_to_tm(tv_msec / MSEC_PER_SEC, 0, &tm); - sdk_info(&pdev_pri->pcidev->dev, "Synchronize UTC time to firmware succeed. UTC time %ld-%02d-%02d %02d:%02d:%02d.\n", - tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, - tm.tm_min, tm.tm_sec); - } -} - -static void send_uld_dev_event(struct spnic_pcidev *dev, - struct sphw_event_info *event) -{ - enum sphw_service_type type; - - for (type = SERVICE_T_NIC; type < SERVICE_T_MAX; type++) { - if (test_and_set_bit(type, &dev->state)) { - sdk_warn(&dev->pcidev->dev, "Event: 0x%x can't handler, %s is in detach\n", - event->type, s_uld_name[type]); - continue; - } - - if (g_uld_info[type].event) - g_uld_info[type].event(&dev->lld_dev, dev->uld_dev[type], event); - clear_bit(type, &dev->state); - } -} - -static void send_event_to_dst_pf(struct spnic_pcidev *dev, u16 func_id, - struct sphw_event_info *event) -{ - struct spnic_pcidev *des_dev = NULL; - - lld_hold(); - list_for_each_entry(des_dev, &dev->chip_node->func_list, node) { - if (sphw_func_type(des_dev->hwdev) == TYPE_VF) - continue; - - if (sphw_global_func_id(des_dev->hwdev) == func_id) { - send_uld_dev_event(des_dev, event); - break; - } - } - lld_put(); -} - -void spnic_event_process(void *adapter, struct sphw_event_info *event) -{ - struct spnic_pcidev *dev = adapter; - u16 func_id; - - if (event->type == SPHW_EVENT_FAULT && - event->info.fault_level == FAULT_LEVEL_SERIOUS_FLR && - event->info.event.chip.func_id < sphw_max_pf_num(dev->hwdev)) { - func_id = event->info.event.chip.func_id; - return send_event_to_dst_pf(adapter, func_id, event); - } - - send_uld_dev_event(adapter, event); -} - -#define SPNIC_IS_VF_DEV(pdev) ((pdev)->device == SPNIC_DEV_ID_VF) - -static int mapping_bar(struct pci_dev *pdev, struct spnic_pcidev *pci_adapter) -{ - int cfg_bar; - - cfg_bar = SPNIC_IS_VF_DEV(pdev) ? SPNIC_VF_PCI_CFG_REG_BAR : SPNIC_PF_PCI_CFG_REG_BAR; - - pci_adapter->cfg_reg_base = pci_ioremap_bar(pdev, cfg_bar); - if (!pci_adapter->cfg_reg_base) { - sdk_err(&pdev->dev, "Failed to map configuration regs\n"); - return -ENOMEM; - } - - pci_adapter->intr_reg_base = pci_ioremap_bar(pdev, SPNIC_PCI_INTR_REG_BAR); - if (!pci_adapter->intr_reg_base) { - sdk_err(&pdev->dev, - "Failed to map interrupt regs\n"); - goto map_intr_bar_err; - } - - if (!SPNIC_IS_VF_DEV(pdev)) { - pci_adapter->mgmt_reg_base = pci_ioremap_bar(pdev, SPNIC_PCI_MGMT_REG_BAR); - if (!pci_adapter->mgmt_reg_base) { - sdk_err(&pdev->dev, "Failed to map mgmt regs\n"); - goto map_mgmt_bar_err; - } - } - - pci_adapter->db_base_phy = pci_resource_start(pdev, SPNIC_PCI_DB_BAR); - pci_adapter->db_dwqe_len = pci_resource_len(pdev, SPNIC_PCI_DB_BAR); - pci_adapter->db_base = pci_ioremap_bar(pdev, SPNIC_PCI_DB_BAR); - if (!pci_adapter->db_base) { - sdk_err(&pdev->dev, "Failed to map doorbell regs\n"); - goto map_db_err; - } - - return 0; - -map_db_err: - if (!SPNIC_IS_VF_DEV(pdev)) - iounmap(pci_adapter->mgmt_reg_base); - -map_mgmt_bar_err: - iounmap(pci_adapter->intr_reg_base); - -map_intr_bar_err: - iounmap(pci_adapter->cfg_reg_base); - - return -ENOMEM; -} - -static void unmapping_bar(struct spnic_pcidev *pci_adapter) -{ - iounmap(pci_adapter->db_base); - - if (!SPNIC_IS_VF_DEV(pci_adapter->pcidev)) - iounmap(pci_adapter->mgmt_reg_base); - - iounmap(pci_adapter->intr_reg_base); - iounmap(pci_adapter->cfg_reg_base); -} - -static int spnic_pci_init(struct pci_dev *pdev) -{ - struct spnic_pcidev *pci_adapter = NULL; - int err; - - pci_adapter = kzalloc(sizeof(*pci_adapter), GFP_KERNEL); - if (!pci_adapter) { - sdk_err(&pdev->dev, "Failed to alloc pci device adapter\n"); - return -ENOMEM; - } - pci_adapter->pcidev = pdev; - mutex_init(&pci_adapter->pdev_mutex); - - pci_set_drvdata(pdev, pci_adapter); - - /* to do CONFIG_PCI_IOV */ - - err = pci_enable_device(pdev); - if (err) { - sdk_err(&pdev->dev, "Failed to enable PCI device\n"); - goto pci_enable_err; - } - - err = pci_request_regions(pdev, SPNIC_NIC_DRV_NAME); - if (err) { - sdk_err(&pdev->dev, "Failed to request regions\n"); - goto pci_regions_err; - } - - pci_enable_pcie_error_reporting(pdev); - - pci_set_master(pdev); - - err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); - if (err) { - sdk_warn(&pdev->dev, "Couldn't set 64-bit DMA mask\n"); - err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); - if (err) { - sdk_err(&pdev->dev, "Failed to set DMA mask\n"); - goto dma_mask_err; - } - } - - err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); - if (err) { - sdk_warn(&pdev->dev, "Couldn't set 64-bit coherent DMA mask\n"); - err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); - if (err) { - sdk_err(&pdev->dev, "Failed to set coherent DMA mask\n"); - goto dma_consistnet_mask_err; - } - } - - return 0; - -dma_consistnet_mask_err: -dma_mask_err: - pci_clear_master(pdev); - pci_release_regions(pdev); - -pci_regions_err: - pci_disable_device(pdev); - -pci_enable_err: - pci_set_drvdata(pdev, NULL); - kfree(pci_adapter); - - return err; -} - -static void spnic_pci_deinit(struct pci_dev *pdev) -{ - struct spnic_pcidev *pci_adapter = pci_get_drvdata(pdev); - - pci_clear_master(pdev); - pci_release_regions(pdev); - pci_disable_pcie_error_reporting(pdev); - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); - kfree(pci_adapter); -} - -#ifdef CONFIG_X86 -/** - * cfg_order_reg - when cpu model is haswell or broadwell, should configure dma - * order register to zero - * @pci_adapter: pci_adapter - **/ -static void cfg_order_reg(struct spnic_pcidev *pci_adapter) -{ - u8 cpu_model[] = {0x3c, 0x3f, 0x45, 0x46, 0x3d, 0x47, 0x4f, 0x56}; - struct cpuinfo_x86 *cpuinfo = NULL; - u32 i; - - if (sphw_func_type(pci_adapter->hwdev) == TYPE_VF) - return; - - cpuinfo = &cpu_data(0); - for (i = 0; i < sizeof(cpu_model); i++) { - if (cpu_model[i] == cpuinfo->x86_model) - sphw_set_pcie_order_cfg(pci_adapter->hwdev); - } -} -#endif - -static int spnic_func_init(struct pci_dev *pdev, struct spnic_pcidev *pci_adapter) -{ - struct sphw_init_para init_para = {0}; - int err; - - init_para.adapter_hdl = pci_adapter; - init_para.pcidev_hdl = pdev; - init_para.dev_hdl = &pdev->dev; - init_para.cfg_reg_base = pci_adapter->cfg_reg_base; - init_para.intr_reg_base = pci_adapter->intr_reg_base; - init_para.mgmt_reg_base = pci_adapter->mgmt_reg_base; - init_para.db_base = pci_adapter->db_base; - init_para.db_base_phy = pci_adapter->db_base_phy; - init_para.db_dwqe_len = pci_adapter->db_dwqe_len; - init_para.hwdev = &pci_adapter->hwdev; - init_para.chip_node = pci_adapter->chip_node; - err = sphw_init_hwdev(&init_para); - if (err) { - pci_adapter->hwdev = NULL; - sdk_err(&pdev->dev, "Failed to initialize hardware device\n"); - return -EFAULT; - } - - pci_adapter->lld_dev.pdev = pdev; - pci_adapter->lld_dev.hwdev = pci_adapter->hwdev; - if (sphw_func_type(pci_adapter->hwdev) != TYPE_VF) - set_bit(SPNIC_FUNC_PERSENT, &pci_adapter->sriov_info.state); - - sphw_event_register(pci_adapter->hwdev, pci_adapter, spnic_event_process); - - if (sphw_func_type(pci_adapter->hwdev) != TYPE_VF) - sphw_sync_time_to_fmw(pci_adapter); - - lld_lock_chip_node(); - list_add_tail(&pci_adapter->node, &pci_adapter->chip_node->func_list); - lld_unlock_chip_node(); - - if (!disable_attach) { - attach_ulds(pci_adapter); -#ifdef CONFIG_X86 - cfg_order_reg(pci_adapter); -#endif - } - - sdk_info(&pdev->dev, "Pcie device probed\n"); - - return 0; -} - -static void spnic_func_deinit(struct pci_dev *pdev) -{ - struct spnic_pcidev *pci_adapter = pci_get_drvdata(pdev); - - /* When function deinit, disable mgmt initiative report events firstly, - * then flush mgmt work-queue. - */ - sphw_disable_mgmt_msg_report(pci_adapter->hwdev); - - sphw_flush_mgmt_workq(pci_adapter->hwdev); - - lld_lock_chip_node(); - list_del(&pci_adapter->node); - lld_unlock_chip_node(); - - wait_lld_dev_unused(pci_adapter); - - detach_ulds(pci_adapter); - - sphw_event_unregister(pci_adapter->hwdev); - - sphw_free_hwdev(pci_adapter->hwdev); -} - -static inline void wait_sriov_cfg_complete(struct spnic_pcidev *pci_adapter) -{ - struct spnic_sriov_info *sriov_info; - unsigned long end; - - sriov_info = &pci_adapter->sriov_info; - clear_bit(SPNIC_FUNC_PERSENT, &sriov_info->state); - usleep_range(9900, 10000); - - end = jiffies + msecs_to_jiffies(SPNIC_WAIT_SRIOV_CFG_TIMEOUT); - do { - if (!test_bit(SPNIC_SRIOV_ENABLE, &sriov_info->state) && - !test_bit(SPNIC_SRIOV_DISABLE, &sriov_info->state)) - return; - - usleep_range(9900, 10000); - } while (time_before(jiffies, end)); -} - -bool spnic_get_vf_load_state(struct pci_dev *pdev) -{ - struct spnic_pcidev *pci_adapter = NULL; - struct pci_dev *pf_pdev = NULL; - - if (!pdev) { - pr_err("pdev is null.\n"); - return false; - } - - /* vf used in vm */ - if (pci_is_root_bus(pdev->bus)) - return false; - - if (pdev->is_virtfn) - pf_pdev = pdev->physfn; - else - pf_pdev = pdev; - - pci_adapter = pci_get_drvdata(pf_pdev); - if (!pci_adapter) { - sdk_err(&pdev->dev, "pci_adapter is null.\n"); - return false; - } - - return !pci_adapter->disable_vf_load; -} - -int spnic_set_vf_load_state(struct pci_dev *pdev, bool vf_load_state) -{ - struct spnic_pcidev *pci_adapter = NULL; - - if (!pdev) { - pr_err("pdev is null.\n"); - return -EINVAL; - } - - pci_adapter = pci_get_drvdata(pdev); - if (!pci_adapter) { - sdk_err(&pdev->dev, "pci_adapter is null.\n"); - return -EINVAL; - } - - if (sphw_func_type(pci_adapter->hwdev) == TYPE_VF) - return 0; - - pci_adapter->disable_vf_load = !vf_load_state; - sdk_info(&pci_adapter->pcidev->dev, "Current function %s vf load in host\n", - vf_load_state ? "enable" : "disable"); - - return 0; -} - -bool spnic_get_vf_service_load(struct pci_dev *pdev, u16 service) -{ - struct spnic_pcidev *pci_adapter = NULL; - struct pci_dev *pf_pdev = NULL; - - if (!pdev) { - pr_err("pdev is null.\n"); - return false; - } - - if (pdev->is_virtfn) - pf_pdev = pdev->physfn; - else - pf_pdev = pdev; - - pci_adapter = pci_get_drvdata(pf_pdev); - if (!pci_adapter) { - sdk_err(&pdev->dev, "pci_adapter is null.\n"); - return false; - } - - if (service >= SERVICE_T_MAX) { - sdk_err(&pdev->dev, "service_type = %u state is error\n", - service); - return false; - } - - return !pci_adapter->disable_srv_load[service]; -} - -int spnic_set_vf_service_load(struct pci_dev *pdev, u16 service, bool vf_srv_load) -{ - struct spnic_pcidev *pci_adapter = NULL; - - if (!pdev) { - pr_err("pdev is null.\n"); - return -EINVAL; - } - - if (service >= SERVICE_T_MAX) { - sdk_err(&pdev->dev, "service_type = %u state is error\n", - service); - return -EFAULT; - } - - pci_adapter = pci_get_drvdata(pdev); - if (!pci_adapter) { - sdk_err(&pdev->dev, "pci_adapter is null.\n"); - return -EINVAL; - } - - if (sphw_func_type(pci_adapter->hwdev) == TYPE_VF) - return 0; - - pci_adapter->disable_srv_load[service] = !vf_srv_load; - sdk_info(&pci_adapter->pcidev->dev, "Current function %s vf load in host\n", - vf_srv_load ? "enable" : "disable"); - - return 0; -} - -static int enable_vf_service_state(struct spnic_pcidev *dst_dev, u16 service) -{ - int err; - - err = sphw_get_dev_cap(dst_dev->hwdev); - if (err) { - sdk_err(&dst_dev->pcidev->dev, "Failed to get current device capabilities\n"); - return -EFAULT; - } - return attach_uld(dst_dev, service, &g_uld_info[service]); -} - -int spnic_set_vf_service_state(struct pci_dev *pdev, u16 vf_func_id, u16 service, bool en) -{ - struct spnic_pcidev *dev = NULL; - struct spnic_pcidev *dst_dev = NULL; - int err = -EFAULT; - - if (!pdev) - return -EINVAL; - - dev = pci_get_drvdata(pdev); - if (!dev) - return -EFAULT; - - if (service >= SERVICE_T_MAX) { - sdk_err(&pdev->dev, "Current vf do not supports set service_type = %u state in host\n", - service); - return -EFAULT; - } - - /* find func_idx pci_adapter and disable or enable service */ - lld_hold(); - list_for_each_entry(dst_dev, &dev->chip_node->func_list, node) { - if (sphw_global_func_id(dst_dev->hwdev) != vf_func_id) - continue; - if (en) { - err = enable_vf_service_state(dst_dev, service); - if (err) - sdk_err(&dev->pcidev->dev, "Failed to set functio_id = %u service_type = %u\n", - vf_func_id, service); - } else { - detach_uld(dst_dev, service); - err = 0; - } - break; - } - lld_put(); - - return err; -} - -static void spnic_remove(struct pci_dev *pdev) -{ - struct spnic_pcidev *pci_adapter = pci_get_drvdata(pdev); - - if (!pci_adapter) - return; - - sdk_info(&pdev->dev, "Pcie device remove begin\n"); - - sphw_detect_hw_present(pci_adapter->hwdev); - - if (sphw_func_type(pci_adapter->hwdev) != TYPE_VF) { - wait_sriov_cfg_complete(pci_adapter); - spnic_pci_sriov_disable(pdev); - } - - spnic_func_deinit(pdev); - - lld_lock_chip_node(); - free_chip_node(pci_adapter); - lld_unlock_chip_node(); - - unmapping_bar(pci_adapter); - spnic_pci_deinit(pdev); - - sdk_info(&pdev->dev, "Pcie device removed\n"); -} - -static int spnic_probe(struct pci_dev *pdev, const struct pci_device_id *id) -{ - struct spnic_pcidev *pci_adapter = NULL; - int err; - - sdk_info(&pdev->dev, "Pcie device probe begin\n"); - - if (pdev->is_virtfn && (!spnic_get_vf_load_state(pdev))) { - sdk_info(&pdev->dev, "VF device disable load in host\n"); - return 0; - } - - err = spnic_pci_init(pdev); - if (err) - return err; - - pci_adapter = pci_get_drvdata(pdev); - err = mapping_bar(pdev, pci_adapter); - if (err) { - sdk_err(&pdev->dev, "Failed to map bar\n"); - goto map_bar_failed; - } - - pci_adapter->disable_vf_load = disable_vf_load; - pci_adapter->id = *id; - lld_dev_cnt_init(pci_adapter); - - /* if chip information of pcie function exist, add the function into chip */ - lld_lock_chip_node(); - err = alloc_chip_node(pci_adapter); - if (err) { - lld_unlock_chip_node(); - sdk_err(&pdev->dev, - "Failed to add new chip node to global list\n"); - goto alloc_chip_node_fail; - } - - lld_unlock_chip_node(); - - err = spnic_func_init(pdev, pci_adapter); - if (err) - goto func_init_err; - - if (sphw_func_type(pci_adapter->hwdev) != TYPE_VF) { - err = sphw_set_bdf_ctxt(pci_adapter->hwdev, pdev->bus->number, - PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); - if (err) { - sdk_err(&pdev->dev, "Failed to set BDF info to MPU\n"); - goto set_bdf_err; - } - } - - return 0; - -set_bdf_err: - spnic_func_deinit(pdev); - -func_init_err: - lld_lock_chip_node(); - free_chip_node(pci_adapter); - lld_unlock_chip_node(); - -alloc_chip_node_fail: - unmapping_bar(pci_adapter); - -map_bar_failed: - spnic_pci_deinit(pdev); - - sdk_err(&pdev->dev, "Pcie device probe failed\n"); - return err; -} - -static const struct pci_device_id spnic_pci_table[] = { - {PCI_VDEVICE(RAMAXEL, SPNIC_DEV_ID_PF_STD), 0}, - {PCI_VDEVICE(RAMAXEL, SPNIC_DEV_ID_VF), 0}, - {PCI_VDEVICE(RAMAXEL, SPNIC_DEV_ID_VF_HV), 0}, - {0, 0} -}; - -MODULE_DEVICE_TABLE(pci, spnic_pci_table); - -/** - * spnic_io_error_detected - called when PCI error is detected - * @pdev: Pointer to PCI device - * @state: The current pci connection state - * - * This function is called after a PCI bus error affecting - * this device has been detected. - * - * Since we only need error detecting not error handling, so we - * always return PCI_ERS_RESULT_CAN_RECOVER to tell the AER - * driver that we don't need reset(error handling). - */ -static pci_ers_result_t spnic_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state) -{ - struct spnic_pcidev *pci_adapter = NULL; - - sdk_err(&pdev->dev, - "Uncorrectable error detected, log and cleanup error status: 0x%08x\n", - state); - - pci_aer_clear_nonfatal_status(pdev); - pci_adapter = pci_get_drvdata(pdev); - - if (pci_adapter) - sphw_record_pcie_error(pci_adapter->hwdev); - - return PCI_ERS_RESULT_CAN_RECOVER; -} - -static void spnic_shutdown(struct pci_dev *pdev) -{ - struct spnic_pcidev *pci_adapter = pci_get_drvdata(pdev); - - sdk_err(&pdev->dev, "Shutdown device\n"); - - if (pci_adapter) - sphw_shutdown_hwdev(pci_adapter->hwdev); - - pci_disable_device(pdev); -} - -/* Cause we only need error detecting not error handling, so only error_detected - * callback is enough. - */ -static struct pci_error_handlers spnic_err_handler = { - .error_detected = spnic_io_error_detected, -}; - -static struct pci_driver spnic_driver = { - .name = SPNIC_NIC_DRV_NAME, - .id_table = spnic_pci_table, - .probe = spnic_probe, - .remove = spnic_remove, - .shutdown = spnic_shutdown, - .sriov_configure = spnic_pci_sriov_configure, - .err_handler = &spnic_err_handler -}; - -static __init int spnic_lld_init(void) -{ - int err; - - pr_info("%s - version %s\n", SPNIC_DRV_DESC, SPNIC_DRV_VERSION); - memset(g_uld_info, 0, sizeof(g_uld_info)); - - spnic_lld_lock_init(); - - err = spnic_register_uld(SERVICE_T_NIC, &nic_uld_info); - if (err) { - pr_err("Register spnic uld failed\n"); - return err; - } - - return pci_register_driver(&spnic_driver); -} - -static __exit void spnic_lld_exit(void) -{ - pci_unregister_driver(&spnic_driver); - spnic_unregister_uld(SERVICE_T_NIC); -} - -module_init(spnic_lld_init); -module_exit(spnic_lld_exit); diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_lld.h b/drivers/net/ethernet/ramaxel/spnic/spnic_lld.h deleted file mode 100644 index e1864f1b6c5b..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_lld.h +++ /dev/null @@ -1,75 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPNIC_LLD_H -#define SPNIC_LLD_H - -#include "sphw_crm.h" - -struct spnic_lld_dev { - struct pci_dev *pdev; - void *hwdev; -}; - -struct spnic_uld_info { - /* uld_dev: should not return null even the function capability - * is not support the up layer driver - * uld_dev_name: NIC driver should copy net device name. - * FC driver could copy fc device name. - * other up layer driver don`t need copy anything - */ - int (*probe)(struct spnic_lld_dev *lld_dev, void **uld_dev, - char *uld_dev_name); - void (*remove)(struct spnic_lld_dev *lld_dev, void *uld_dev); - int (*suspend)(struct spnic_lld_dev *lld_dev, void *uld_dev, - pm_message_t state); - int (*resume)(struct spnic_lld_dev *lld_dev, void *uld_dev); - void (*event)(struct spnic_lld_dev *lld_dev, void *uld_dev, - struct sphw_event_info *event); - int (*ioctl)(void *uld_dev, u32 cmd, const void *buf_in, u32 in_size, - void *buf_out, u32 *out_size); -}; - -int spnic_register_uld(enum sphw_service_type type, struct spnic_uld_info *uld_info); - -void spnic_unregister_uld(enum sphw_service_type type); - -void *spnic_get_uld_dev_by_pdev(struct pci_dev *pdev, enum sphw_service_type type); - -void *spnic_get_ppf_uld_by_pdev(struct pci_dev *pdev, enum sphw_service_type type); - -int spnic_get_chip_name_by_hwdev(const void *hwdev, char *ifname); - -void *spnic_get_uld_dev_by_ifname(const char *ifname, enum sphw_service_type type); - -int spnic_get_pf_nic_uld_array(struct pci_dev *pdev, u32 *dev_cnt, void *array[]); - -int spnic_get_chip_up_bitmap(struct pci_dev *pdev, bool *is_setted, u8 *valid_up_bitmap); - -int spnic_set_chip_up_bitmap(struct pci_dev *pdev, u8 valid_up_bitmap); - -bool spnic_get_vf_service_load(struct pci_dev *pdev, u16 service); - -int spnic_set_vf_service_load(struct pci_dev *pdev, u16 service, bool vf_srv_load); - -int spnic_set_vf_service_state(struct pci_dev *pdev, u16 vf_func_id, u16 service, bool en); - -bool spnic_get_vf_load_state(struct pci_dev *pdev); - -int spnic_set_vf_load_state(struct pci_dev *pdev, bool vf_load_state); - -int spnic_attach_nic(struct spnic_lld_dev *lld_dev); - -void spnic_detach_nic(struct spnic_lld_dev *lld_dev); - -void lld_hold(void); -void lld_put(void); -void lld_dev_hold(struct spnic_lld_dev *dev); -void lld_dev_put(struct spnic_lld_dev *dev); -struct spnic_lld_dev *spnic_get_lld_dev_by_ifname(const char *ifname); - -void *spnic_get_ppf_hwdev_by_pdev(struct pci_dev *pdev); - -void spnic_send_event_to_uld(struct pci_dev *pdev, enum sphw_service_type type, - struct sphw_event_info *event); -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_mag_cfg.c b/drivers/net/ethernet/ramaxel/spnic/spnic_mag_cfg.c deleted file mode 100644 index d0448d1a6bd3..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_mag_cfg.c +++ /dev/null @@ -1,778 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [NIC]" fmt - -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/etherdevice.h> -#include <linux/if_vlan.h> -#include <linux/ethtool.h> -#include <linux/kernel.h> -#include <linux/device.h> -#include <linux/pci.h> -#include <linux/netdevice.h> -#include <linux/module.h> - -#include "sphw_crm.h" -#include "sphw_hw.h" -#include "spnic_mag_cmd.h" -#include "spnic_nic_io.h" -#include "spnic_nic_cfg.h" -#include "spnic_nic.h" -#include "sphw_common.h" - -static int mag_msg_to_mgmt_sync(void *hwdev, u16 cmd, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size); -static int mag_msg_to_mgmt_sync_ch(void *hwdev, u16 cmd, void *buf_in, - u16 in_size, void *buf_out, u16 *out_size, - u16 channel); - -int spnic_set_port_enable(void *hwdev, bool enable, u16 channel) -{ - struct mag_cmd_set_port_enable en_state; - u16 out_size = sizeof(en_state); - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - if (!hwdev) - return -EINVAL; - - if (sphw_func_type(hwdev) == TYPE_VF) - return 0; - - memset(&en_state, 0, sizeof(en_state)); - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - en_state.function_id = sphw_global_func_id(hwdev); - en_state.state = enable ? MAG_CMD_TX_ENABLE | MAG_CMD_RX_ENABLE : - MAG_CMD_PORT_DISABLE; - - err = mag_msg_to_mgmt_sync_ch(hwdev, MAG_CMD_SET_PORT_ENABLE, &en_state, - sizeof(en_state), &en_state, &out_size, channel); - if (err || !out_size || en_state.head.status) { - nic_err(nic_cfg->dev_hdl, "Failed to set port state, err: %d, status: 0x%x, out size: 0x%x, channel: 0x%x\n", - err, en_state.head.status, out_size, channel); - return -EIO; - } - - return 0; -} - -int spnic_get_phy_port_stats(void *hwdev, struct mag_cmd_port_stats *stats) -{ - struct mag_cmd_get_port_stat *port_stats = NULL; - struct mag_cmd_port_stats_info stats_info; - u16 out_size = sizeof(*port_stats); - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - port_stats = kzalloc(sizeof(*port_stats), GFP_KERNEL); - if (!port_stats) - return -ENOMEM; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - memset(&stats_info, 0, sizeof(stats_info)); - stats_info.port_id = sphw_physical_port_id(hwdev); - - err = mag_msg_to_mgmt_sync(hwdev, MAG_CMD_GET_PORT_STAT, - &stats_info, sizeof(stats_info), - port_stats, &out_size); - if (err || !out_size || port_stats->head.status) { - nic_err(nic_cfg->dev_hdl, - "Failed to get port statistics, err: %d, status: 0x%x, out size: 0x%x\n", - err, port_stats->head.status, out_size); - err = -EIO; - goto out; - } - - memcpy(stats, &port_stats->counter, sizeof(*stats)); - -out: - kfree(port_stats); - - return err; -} - -int spnic_set_port_funcs_state(void *hwdev, bool enable) -{ - return 0; -} - -int spnic_reset_port_link_cfg(void *hwdev) -{ - return 0; -} - -int spnic_force_port_relink(void *hwdev) -{ - return 0; -} - -int spnic_set_autoneg(void *hwdev, bool enable) -{ - /* TODO */ - - return 0; -} - -static int spnic_cfg_loopback_mode(struct spnic_nic_cfg *nic_cfg, u8 opcode, u8 *mode, u8 *enable) -{ - struct mag_cmd_cfg_loopback_mode lp; - u16 out_size = sizeof(lp); - int err; - - memset(&lp, 0, sizeof(lp)); - lp.port_id = sphw_physical_port_id(nic_cfg->hwdev); - lp.opcode = opcode; - if (opcode == MGMT_MSG_CMD_OP_SET) { - lp.lp_mode = *mode; - lp.lp_en = *enable; - } - - err = mag_msg_to_mgmt_sync(nic_cfg->hwdev, MAG_CMD_CFG_LOOPBACK_MODE, - &lp, sizeof(lp), &lp, &out_size); - if (err || !out_size || lp.head.status) { - nic_err(nic_cfg->dev_hdl, - "Failed to %s loopback mode, err: %d, status: 0x%x, out size: 0x%x\n", - opcode == MGMT_MSG_CMD_OP_SET ? "set" : "get", - err, lp.head.status, out_size); - return -EIO; - } - - if (opcode == MGMT_MSG_CMD_OP_GET) { - *mode = lp.lp_mode; - *enable = lp.lp_en; - } - - return 0; -} - -int spnic_get_loopback_mode(void *hwdev, u8 *mode, u8 *enable) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - - if (!hwdev || !mode || !enable) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - return spnic_cfg_loopback_mode(nic_cfg, MGMT_MSG_CMD_OP_GET, mode, enable); -} - -#define LOOP_MODE_MIN 1 -#define LOOP_MODE_MAX 6 -int spnic_set_loopback_mode(void *hwdev, u8 mode, u8 enable) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - - if (!hwdev) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - if (mode < LOOP_MODE_MIN || mode > LOOP_MODE_MAX) { - nic_err(nic_cfg->dev_hdl, "Invalid loopback mode %u to set\n", - mode); - return -EINVAL; - } - - return spnic_cfg_loopback_mode(nic_cfg, MGMT_MSG_CMD_OP_SET, &mode, &enable); -} - -int spnic_set_led_status(void *hwdev, enum mag_led_type type, enum mag_led_mode mode) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - struct mag_cmd_set_led_cfg led_info; - u16 out_size = sizeof(led_info); - int err; - - if (!hwdev) - return -EFAULT; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - memset(&led_info, 0, sizeof(led_info)); - - led_info.function_id = sphw_global_func_id(hwdev); - led_info.type = type; - led_info.mode = mode; - - err = mag_msg_to_mgmt_sync(hwdev, MAG_CMD_SET_LED_CFG, &led_info, - sizeof(led_info), &led_info, &out_size); - if (err || led_info.head.status || !out_size) { - nic_err(nic_cfg->dev_hdl, "Failed to set led status, err: %d, status: 0x%x, out size: 0x%x\n", - err, led_info.head.status, out_size); - return -EIO; - } - - return 0; -} - -int spnic_get_port_info(void *hwdev, struct nic_port_info *port_info, u16 channel) -{ - struct mag_cmd_get_port_info port_msg; - u16 out_size = sizeof(port_msg); - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - if (!hwdev || !port_info) - return -EINVAL; - - memset(&port_msg, 0, sizeof(port_msg)); - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - port_msg.port_id = sphw_physical_port_id(hwdev); - - err = mag_msg_to_mgmt_sync_ch(hwdev, MAG_CMD_GET_PORT_INFO, &port_msg, - sizeof(port_msg), &port_msg, &out_size, - channel); - if (err || !out_size || port_msg.head.status) { - nic_err(nic_cfg->dev_hdl, - "Failed to get port info, err: %d, status: 0x%x, out size: 0x%x, channel: 0x%x\n", - err, port_msg.head.status, out_size, channel); - return -EIO; - } - - port_info->autoneg_cap = port_msg.an_support; - port_info->autoneg_state = port_msg.an_en; - port_info->duplex = port_msg.duplex; - port_info->port_type = port_msg.wire_type; - port_info->speed = port_msg.speed; - port_info->fec = port_msg.fec; - port_info->supported_mode = port_msg.supported_mode; - port_info->advertised_mode = port_msg.advertised_mode; - - return 0; -} - -int spnic_get_speed(void *hwdev, enum mag_cmd_port_speed *speed, u16 channel) -{ - struct nic_port_info port_info = {0}; - int err; - - if (!hwdev || !speed) - return -EINVAL; - - err = spnic_get_port_info(hwdev, &port_info, channel); - if (err) - return err; - - *speed = port_info.speed; - - return 0; -} - -int spnic_set_link_settings(void *hwdev, struct spnic_link_ksettings *settings) -{ - struct mag_cmd_set_port_cfg info; - u16 out_size = sizeof(info); - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - if (!hwdev || !settings) - return -EINVAL; - - memset(&info, 0, sizeof(info)); - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - info.port_id = sphw_physical_port_id(hwdev); - info.config_bitmap = settings->valid_bitmap; - info.autoneg = settings->autoneg; - info.speed = settings->speed; - info.fec = settings->fec; - - err = mag_msg_to_mgmt_sync(hwdev, MAG_CMD_SET_PORT_CFG, &info, - sizeof(info), &info, &out_size); - if (err || !out_size || info.head.status) { - nic_err(nic_cfg->dev_hdl, "Failed to set link settings, err: %d, status: 0x%x, out size: 0x%x\n", - err, info.head.status, out_size); - return -EIO; - } - - return info.head.status; -} - -int spnic_get_link_state(void *hwdev, u8 *link_state) -{ - struct mag_cmd_get_link_status get_link; - u16 out_size = sizeof(get_link); - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - if (!hwdev || !link_state) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - memset(&get_link, 0, sizeof(get_link)); - get_link.port_id = sphw_physical_port_id(hwdev); - - err = mag_msg_to_mgmt_sync(hwdev, MAG_CMD_GET_LINK_STATUS, &get_link, - sizeof(get_link), &get_link, &out_size); - if (err || !out_size || get_link.head.status) { - nic_err(nic_cfg->dev_hdl, "Failed to get link state, err: %d, status: 0x%x, out size: 0x%x\n", - err, get_link.head.status, out_size); - return -EIO; - } - - *link_state = get_link.status; - - return 0; -} - -void spnic_notify_vf_link_status(struct spnic_nic_cfg *nic_cfg, u16 vf_id, u8 link_status) -{ - struct mag_cmd_get_link_status link; - struct vf_data_storage *vf_infos = nic_cfg->vf_infos; - u16 out_size = sizeof(link); - int err; - - memset(&link, 0, sizeof(link)); - if (vf_infos[HW_VF_ID_TO_OS(vf_id)].registered) { - link.status = link_status; - link.port_id = sphw_physical_port_id(nic_cfg->hwdev); - err = sphw_mbox_to_vf(nic_cfg->hwdev, vf_id, SPHW_MOD_HILINK, - MAG_CMD_GET_LINK_STATUS, &link, sizeof(link), &link, - &out_size, 0, SPHW_CHANNEL_NIC); - if (err || !out_size || link.head.status) - nic_err(nic_cfg->dev_hdl, - "Send link change event to VF %d failed, err: %d, status: 0x%x, out_size: 0x%x\n", - HW_VF_ID_TO_OS(vf_id), err, - link.head.status, out_size); - } -} - -void spnic_notify_all_vfs_link_changed(void *hwdev, u8 link_status) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - u16 i; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - nic_cfg->link_status = link_status; - for (i = 1; i <= nic_cfg->max_vfs; i++) { - if (!nic_cfg->vf_infos[HW_VF_ID_TO_OS(i)].link_forced) - spnic_notify_vf_link_status(nic_cfg, i, link_status); - } -} - -static int spnic_get_vf_link_status_msg_handler(struct spnic_nic_cfg *nic_cfg, u16 vf_id, - void *buf_in, u16 in_size, void *buf_out, - u16 *out_size) -{ - struct vf_data_storage *vf_infos = nic_cfg->vf_infos; - struct mag_cmd_get_link_status *get_link = buf_out; - bool link_forced, link_up; - - link_forced = vf_infos[HW_VF_ID_TO_OS(vf_id)].link_forced; - link_up = vf_infos[HW_VF_ID_TO_OS(vf_id)].link_up; - - if (link_forced) - get_link->status = link_up ? SPNIC_LINK_UP : SPNIC_LINK_DOWN; - else - get_link->status = nic_cfg->link_status; - - get_link->head.status = 0; - *out_size = sizeof(*get_link); - - return 0; -} - -int spnic_refresh_nic_cfg(void *hwdev, struct nic_port_info *port_info) -{ - /*TO DO */ - return 0; -} - -static void get_port_info(void *hwdev, struct mag_cmd_get_link_status *link_status, - struct sphw_event_link_info *link_info) -{ - struct nic_port_info port_info = {0}; - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - if (sphw_func_type(hwdev) != TYPE_VF && - link_status->status == SPHW_EVENT_LINK_UP) { - err = spnic_get_port_info(hwdev, &port_info, SPHW_CHANNEL_NIC); - if (err) { - nic_warn(nic_cfg->dev_hdl, "Failed to get port info\n"); - } else { - link_info->valid = 1; - link_info->port_type = port_info.port_type; - link_info->autoneg_cap = port_info.autoneg_cap; - link_info->autoneg_state = port_info.autoneg_state; - link_info->duplex = port_info.duplex; - link_info->speed = port_info.speed; - spnic_refresh_nic_cfg(hwdev, &port_info); - } - } -} - -static void link_status_event_handler(void *hwdev, void *buf_in, - u16 in_size, void *buf_out, u16 *out_size) -{ - struct mag_cmd_get_link_status *link_status = NULL; - struct mag_cmd_get_link_status *ret_link_status = NULL; - struct sphw_event_info event_info = {0}; - struct sphw_event_link_info *link_info = &event_info.link_info; - struct spnic_nic_cfg *nic_cfg = NULL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - link_status = buf_in; - sdk_info(nic_cfg->dev_hdl, "Link status report received, func_id: %u, status: %u\n", - sphw_global_func_id(hwdev), link_status->status); - - sphw_link_event_stats(hwdev, link_status->status); - - /* link event reported only after set vport enable */ - get_port_info(hwdev, link_status, link_info); - - event_info.type = link_status->status ? SPHW_EVENT_LINK_UP : SPHW_EVENT_LINK_DOWN; - - sphw_event_callback(hwdev, &event_info); - - if (sphw_func_type(hwdev) != TYPE_VF) { - spnic_notify_all_vfs_link_changed(hwdev, link_status->status); - ret_link_status = buf_out; - ret_link_status->head.status = 0; - *out_size = sizeof(*ret_link_status); - } -} - -static void cable_plug_event(void *hwdev, void *buf_in, u16 in_size, void *buf_out, u16 *out_size) -{ - struct mag_cmd_wire_event *plug_event = buf_in; - struct spnic_port_routine_cmd *rt_cmd = NULL; - struct spnic_nic_cfg *nic_cfg = NULL; - struct sphw_event_info event_info; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - rt_cmd = &nic_cfg->rt_cmd; - - mutex_lock(&nic_cfg->sfp_mutex); - rt_cmd->mpu_send_sfp_abs = false; - rt_cmd->mpu_send_sfp_info = false; - mutex_unlock(&nic_cfg->sfp_mutex); - - memset(&event_info, 0, sizeof(event_info)); - event_info.type = SPHW_EVENT_PORT_MODULE_EVENT; - event_info.module_event.type = plug_event->status ? - SPHW_PORT_MODULE_CABLE_PLUGGED : - SPHW_PORT_MODULE_CABLE_UNPLUGGED; - - *out_size = sizeof(*plug_event); - plug_event = buf_out; - plug_event->head.status = 0; - - sphw_event_callback(hwdev, &event_info); -} - -static void port_sfp_info_event(void *hwdev, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size) -{ - struct mag_cmd_get_xsfp_info *sfp_info = buf_in; - struct spnic_port_routine_cmd *rt_cmd = NULL; - struct spnic_nic_cfg *nic_cfg = NULL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - if (in_size != sizeof(*sfp_info)) { - sdk_err(nic_cfg->dev_hdl, "Invalid sfp info cmd, length: %u, should be %ld\n", - in_size, sizeof(*sfp_info)); - return; - } - - rt_cmd = &nic_cfg->rt_cmd; - mutex_lock(&nic_cfg->sfp_mutex); - memcpy(&rt_cmd->std_sfp_info, sfp_info, - sizeof(struct mag_cmd_get_xsfp_info)); - rt_cmd->mpu_send_sfp_info = true; - mutex_unlock(&nic_cfg->sfp_mutex); -} - -static void port_sfp_abs_event(void *hwdev, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size) -{ - struct mag_cmd_get_xsfp_present *sfp_abs = buf_in; - struct spnic_port_routine_cmd *rt_cmd = NULL; - struct spnic_nic_cfg *nic_cfg = NULL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - if (in_size != sizeof(*sfp_abs)) { - sdk_err(nic_cfg->dev_hdl, "Invalid sfp absent cmd, length: %u, should be %ld\n", - in_size, sizeof(*sfp_abs)); - return; - } - - rt_cmd = &nic_cfg->rt_cmd; - mutex_lock(&nic_cfg->sfp_mutex); - memcpy(&rt_cmd->abs, sfp_abs, sizeof(struct mag_cmd_get_xsfp_present)); - rt_cmd->mpu_send_sfp_abs = true; - mutex_unlock(&nic_cfg->sfp_mutex); -} - -static bool spnic_if_sfp_absent(void *hwdev) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - struct spnic_port_routine_cmd *rt_cmd = NULL; - struct mag_cmd_get_xsfp_present sfp_abs; - u8 port_id = sphw_physical_port_id(hwdev); - u16 out_size = sizeof(sfp_abs); - int err; - bool sfp_abs_status; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - memset(&sfp_abs, 0, sizeof(sfp_abs)); - - rt_cmd = &nic_cfg->rt_cmd; - mutex_lock(&nic_cfg->sfp_mutex); - if (rt_cmd->mpu_send_sfp_abs) { - if (rt_cmd->abs.head.status) { - mutex_unlock(&nic_cfg->sfp_mutex); - return true; - } - - sfp_abs_status = (bool)rt_cmd->abs.abs_status; - mutex_unlock(&nic_cfg->sfp_mutex); - return sfp_abs_status; - } - mutex_unlock(&nic_cfg->sfp_mutex); - - sfp_abs.port_id = port_id; - err = mag_msg_to_mgmt_sync(hwdev, MAG_CMD_GET_XSFP_PRESENT, - &sfp_abs, sizeof(sfp_abs), &sfp_abs, - &out_size); - if (sfp_abs.head.status || err || !out_size) { - nic_err(nic_cfg->dev_hdl, - "Failed to get port%u sfp absent status, err: %d, status: 0x%x, out size: 0x%x\n", - port_id, err, sfp_abs.head.status, out_size); - return true; - } - - return (sfp_abs.abs_status == 0 ? false : true); -} - -int spnic_get_sfp_eeprom(void *hwdev, u8 *data, u32 len) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - struct spnic_port_routine_cmd *rt_cmd = NULL; - struct mag_cmd_get_xsfp_info sfp_info; - u16 out_size = sizeof(sfp_info); - int err; - - if (!hwdev || !data) - return -EINVAL; - - if (spnic_if_sfp_absent(hwdev)) - return -ENXIO; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - memset(&sfp_info, 0, sizeof(sfp_info)); - - rt_cmd = &nic_cfg->rt_cmd; - mutex_lock(&nic_cfg->sfp_mutex); - if (rt_cmd->mpu_send_sfp_info) { - if (rt_cmd->std_sfp_info.head.status) { - mutex_unlock(&nic_cfg->sfp_mutex); - return -EIO; - } - - memcpy(data, rt_cmd->std_sfp_info.sfp_info, len); - mutex_unlock(&nic_cfg->sfp_mutex); - return 0; - } - mutex_unlock(&nic_cfg->sfp_mutex); - - sfp_info.port_id = sphw_physical_port_id(hwdev); - err = mag_msg_to_mgmt_sync(hwdev, MAG_CMD_GET_XSFP_INFO, &sfp_info, - sizeof(sfp_info), &sfp_info, &out_size); - if (sfp_info.head.status || err || !out_size) { - nic_err(nic_cfg->dev_hdl, - "Failed to get port%u sfp eeprom information, err: %d, status: 0x%x, out size: 0x%x\n", - sphw_physical_port_id(hwdev), err, - sfp_info.head.status, out_size); - return -EIO; - } - - memcpy(data, sfp_info.sfp_info, len); - - return 0; -} - -int spnic_get_sfp_type(void *hwdev, u8 *sfp_type, u8 *sfp_type_ext) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - struct spnic_port_routine_cmd *rt_cmd = NULL; - u8 sfp_data[STD_SFP_INFO_MAX_SIZE]; - int err; - - if (!hwdev || !sfp_type || !sfp_type_ext) - return -EINVAL; - - if (spnic_if_sfp_absent(hwdev)) - return -ENXIO; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - rt_cmd = &nic_cfg->rt_cmd; - - mutex_lock(&nic_cfg->sfp_mutex); - if (rt_cmd->mpu_send_sfp_info) { - if (rt_cmd->std_sfp_info.head.status) { - mutex_unlock(&nic_cfg->sfp_mutex); - return -EIO; - } - - *sfp_type = rt_cmd->std_sfp_info.sfp_info[0]; - *sfp_type_ext = rt_cmd->std_sfp_info.sfp_info[1]; - mutex_unlock(&nic_cfg->sfp_mutex); - return 0; - } - mutex_unlock(&nic_cfg->sfp_mutex); - - err = spnic_get_sfp_eeprom(hwdev, (u8 *)sfp_data, STD_SFP_INFO_MAX_SIZE); - if (err) - return err; - - *sfp_type = sfp_data[0]; - *sfp_type_ext = sfp_data[1]; - - return 0; -} - -static const struct vf_msg_handler vf_mag_cmd_handler[] = { - { - .cmd = MAG_CMD_GET_LINK_STATUS, - .handler = spnic_get_vf_link_status_msg_handler, - }, -}; - -/* pf/ppf handler mbox msg from vf */ -int spnic_pf_mag_mbox_handler(void *hwdev, void *pri_handle, u16 vf_id, - u16 cmd, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size) -{ - u32 index, cmd_size = ARRAY_LEN(vf_mag_cmd_handler); - struct spnic_nic_cfg *nic_cfg = NULL; - const struct vf_msg_handler *handler = NULL; - - if (!hwdev) - return -EFAULT; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - for (index = 0; index < cmd_size; index++) { - handler = &vf_mag_cmd_handler[index]; - if (cmd == handler->cmd) - return handler->handler(nic_cfg, vf_id, buf_in, in_size, - buf_out, out_size); - } - - nic_warn(nic_cfg->dev_hdl, "NO handler for mag cmd: %u received from vf id: %u\n", - cmd, vf_id); - - return -EINVAL; -} - -static struct nic_event_handler mag_cmd_handler[] = { - { - .cmd = MAG_CMD_GET_LINK_STATUS, - .handler = link_status_event_handler, - }, - - { - .cmd = MAG_CMD_WIRE_EVENT, - .handler = cable_plug_event, - }, - - { - .cmd = MAG_CMD_GET_XSFP_INFO, - .handler = port_sfp_info_event, - }, - - { - .cmd = MAG_CMD_GET_XSFP_PRESENT, - .handler = port_sfp_abs_event, - }, -}; - -int spnic_mag_event_handler(void *hwdev, void *pri_handle, u16 cmd, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - u32 size = ARRAY_LEN(mag_cmd_handler); - u32 i; - - if (!hwdev) - return -EINVAL; - - *out_size = 0; - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - for (i = 0; i < size; i++) { - if (cmd == mag_cmd_handler[i].cmd) { - mag_cmd_handler[i].handler(hwdev, buf_in, in_size, - buf_out, out_size); - break; - } - } - - /* can't find this event cmd */ - if (i == size) - sdk_warn(nic_cfg->dev_hdl, "Unsupported mag event, cmd: %u\n", - cmd); - - return 0; -} - -int spnic_vf_mag_event_handler(void *hwdev, void *pri_handle, u16 cmd, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size) -{ - return spnic_mag_event_handler(hwdev, pri_handle, cmd, buf_in, in_size, buf_out, out_size); -} - -/* pf/ppf handler mgmt cpu report hilink event*/ -void spnic_pf_mag_event_handler(void *hwdev, void *pri_handle, u16 cmd, - void *buf_in, u16 in_size, void *buf_out, u16 *out_size) -{ - spnic_mag_event_handler(hwdev, pri_handle, cmd, buf_in, in_size, buf_out, out_size); -} - -static int _mag_msg_to_mgmt_sync(void *hwdev, u16 cmd, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size, u16 channel) -{ - u32 i, cmd_cnt = ARRAY_LEN(vf_mag_cmd_handler); - bool cmd_to_pf = false; - - if (sphw_func_type(hwdev) == TYPE_VF) { - for (i = 0; i < cmd_cnt; i++) { - if (cmd == vf_mag_cmd_handler[i].cmd) { - cmd_to_pf = true; - break; - } - } - } - - if (cmd_to_pf) - return sphw_mbox_to_pf(hwdev, SPHW_MOD_HILINK, cmd, buf_in, in_size, buf_out, - out_size, 0, channel); - - return sphw_msg_to_mgmt_sync(hwdev, SPHW_MOD_HILINK, cmd, buf_in, - in_size, buf_out, out_size, 0, channel); -} - -static int mag_msg_to_mgmt_sync(void *hwdev, u16 cmd, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size) -{ - return _mag_msg_to_mgmt_sync(hwdev, cmd, buf_in, in_size, buf_out, - out_size, SPHW_CHANNEL_NIC); -} - -static int mag_msg_to_mgmt_sync_ch(void *hwdev, u16 cmd, void *buf_in, - u16 in_size, void *buf_out, u16 *out_size, - u16 channel) -{ - return _mag_msg_to_mgmt_sync(hwdev, cmd, buf_in, in_size, buf_out, - out_size, channel); -} diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_mag_cmd.h b/drivers/net/ethernet/ramaxel/spnic/spnic_mag_cmd.h deleted file mode 100644 index 4e65b7af115b..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_mag_cmd.h +++ /dev/null @@ -1,643 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPNIC_MAG_CMD_H -#define SPNIC_MAG_CMD_H - -#include "sphw_mgmt_msg_base.h" - -enum mag_cmd { - SERDES_CMD_PROCESS = 0, - - MAG_CMD_SET_PORT_CFG = 1, - MAG_CMD_SET_PORT_ADAPT = 2, - MAG_CMD_CFG_LOOPBACK_MODE = 3, - - MAG_CMD_GET_PORT_ENABLE = 5, - MAG_CMD_SET_PORT_ENABLE = 6, - MAG_CMD_GET_LINK_STATUS = 7, - MAG_CMD_SET_LINK_FOLLOW = 8, - MAG_CMD_SET_PMA_ENABLE = 9, - MAG_CMD_CFG_FEC_MODE = 10, - - MAG_CMD_CFG_AN_TYPE = 12, /* reserved for furture use */ - - MAG_CMD_SET_PANGEA_ADAPT = 15, - - MAG_CMD_CFG_BIOS_LINK_CFG = 31, - MAG_CMD_RESTORE_LINK_CFG = 32, - MAG_CMD_ACTIVATE_BIOS_LINK_CFG = 33, - - /* LED */ - MAG_CMD_SET_LED_CFG = 50, - - /* PHY */ - MAG_CMD_GET_PHY_INIT_STATUS = 55, /* reserved for furture use */ - - MAG_CMD_GET_XSFP_INFO = 60, - MAG_CMD_SET_XSFP_ENABLE = 61, - MAG_CMD_GET_XSFP_PRESENT = 62, - MAG_CMD_SET_XSFP_RW = 63, - MAG_CMD_CFG_XSFP_TEMPERATURE = 64, - - MAG_CMD_WIRE_EVENT = 100, - MAG_CMD_LINK_ERR_EVENT = 101, - - MAG_CMD_EVENT_PORT_INFO = 150, - MAG_CMD_GET_PORT_STAT = 151, - MAG_CMD_CLR_PORT_STAT = 152, - MAG_CMD_GET_PORT_INFO = 153, - MAG_CMD_GET_PCS_ERR_CNT = 154, - MAG_CMD_GET_MAG_CNT = 155, - MAG_CMD_DUMP_ANTRAIN_INFO = 156, - - MAG_CMD_MAX = 0xFF, -}; - -enum mag_cmd_port_speed { - PORT_SPEED_NOT_SET = 0, - PORT_SPEED_10MB = 1, - PORT_SPEED_100MB = 2, - PORT_SPEED_1GB = 3, - PORT_SPEED_10GB = 4, - PORT_SPEED_25GB = 5, - PORT_SPEED_40GB = 6, - PORT_SPEED_50GB = 7, - PORT_SPEED_100GB = 8, - PORT_SPEED_200GB = 9, - PORT_SPEED_UNKNOWN -}; - -enum mag_cmd_port_an { - PORT_AN_NOT_SET = 0, - PORT_CFG_AN_ON = 1, - PORT_CFG_AN_OFF = 2 -}; - -enum mag_cmd_port_fec { - PORT_FEC_NOT_SET = 0, - PORT_FEC_RSFEC = 1, - PORT_FEC_BASEFEC = 2, - PORT_FEC_NOFEC = 3, - PORT_FEC_LLRSFEC = 4 -}; - -enum mag_cmd_port_lanes { - PORT_LANES_NOT_SET = 0, - PORT_LANES_X1 = 1, - PORT_LANES_X2 = 2, - PORT_LANES_X4 = 4, - PORT_LANES_X8 = 8, /* reserved for future use */ -}; - -enum mag_cmd_port_duplex { - PORT_DUPLEX_HALF = 0, - PORT_DUPLEX_FULL = 1 -}; - -/* mag_cmd_set_port_cfg config bitmap */ -#define MAG_CMD_SET_SPEED 0x1 -#define MAG_CMD_SET_AUTONEG 0x2 -#define MAG_CMD_SET_FEC 0x4 -#define MAG_CMD_SET_LANES 0x8 -struct mag_cmd_set_port_cfg { - struct mgmt_msg_head head; - - u8 port_id; - u8 rsvd0[3]; - - u32 config_bitmap; - u8 speed; - u8 autoneg; - u8 fec; - u8 lanes; - u8 rsvd1[20]; -}; - -/* mag supported/advertised link mode bitmap */ -enum mag_cmd_link_mode { - LINK_MODE_GE = 0, - LINK_MODE_10GE_BASE_R = 1, - LINK_MODE_25GE_BASE_R = 2, - LINK_MODE_40GE_BASE_R4 = 3, - LINK_MODE_50GE_BASE_R = 4, - LINK_MODE_50GE_BASE_R2 = 5, - LINK_MODE_100GE_BASE_R = 6, - LINK_MODE_100GE_BASE_R2 = 7, - LINK_MODE_100GE_BASE_R4 = 8, - LINK_MODE_200GE_BASE_R2 = 9, - LINK_MODE_200GE_BASE_R4 = 10, - LINK_MODE_MAX_NUMBERS, - - LINK_MODE_UNKNOWN = 0xFFFF -}; - -struct mag_cmd_get_port_info { - struct mgmt_msg_head head; - - u8 port_id; - u8 rsvd0[3]; - - u8 wire_type; - u8 an_support; - u8 an_en; - u8 duplex; - - u8 speed; - u8 fec; - u8 lanes; - u8 rsvd1; - - u32 supported_mode; - u32 advertised_mode; - u8 rsvd2[8]; -}; - -#define MAG_CMD_OPCODE_GET 0 -#define MAG_CMD_OPCODE_SET 1 -struct mag_cmd_set_port_adapt { - struct mgmt_msg_head head; - - u8 port_id; - u8 opcode; /* 0:get adapt info 1:set adapt */ - u8 enable; - u8 rsvd0; - u32 speed_mode; - u32 rsvd1[3]; -}; - -#define MAG_CMD_LP_MODE_SDS_S_TX2RX 1 -#define MAG_CMD_LP_MODE_SDS_P_RX2TX 2 -#define MAG_CMD_LP_MODE_SDS_P_TX2RX 3 -#define MAG_CMD_LP_MODE_MAC_RX2TX 4 -#define MAG_CMD_LP_MODE_MAC_TX2RX 5 -#define MAG_CMD_LP_MODE_TXDP2RXDP 6 -struct mag_cmd_cfg_loopback_mode { - struct mgmt_msg_head head; - - u8 port_id; - u8 opcode; /* 0:get loopback mode 1:set loopback mode */ - u8 lp_mode; - u8 lp_en; /* 0:disable 1:enable */ - - u32 rsvd0[2]; -}; - -#define MAG_CMD_PORT_DISABLE 0x0 -#define MAG_CMD_TX_ENABLE 0x1 -#define MAG_CMD_RX_ENABLE 0x2 - -struct mag_cmd_set_port_enable { - struct mgmt_msg_head head; - - u16 function_id; /* function_id should not more than the max support pf_id(32) */ - u16 rsvd0; - - u8 state; /* bitmap bit0:tx_en bit1:rx_en */ - u8 rsvd1[3]; -}; - -struct mag_cmd_get_port_enable { - struct mgmt_msg_head head; - - u8 port; - u8 state; /* bitmap bit0:tx_en bit1:rx_en */ - u8 rsvd0[2]; -}; - -#define PMA_FOLLOW_DEFAULT 0x0 -#define PMA_FOLLOW_ENABLE 0x1 -#define PMA_FOLLOW_DISABLE 0x2 -/* the physical port disable link follow only when all pf of the port are set to follow disable */ -struct mag_cmd_set_link_follow { - struct mgmt_msg_head head; - - u16 function_id; /* function_id should not more than the max support pf_id(32) */ - u16 rsvd0; - - u8 follow; - u8 rsvd1[3]; -}; - -/* firmware also use this cmd report link event to driver */ -struct mag_cmd_get_link_status { - struct mgmt_msg_head head; - - u8 port_id; - u8 status; /* 0:link down 1:link up */ - u8 rsvd0[2]; -}; - -struct mag_cmd_set_pma_enable { - struct mgmt_msg_head head; - - u16 function_id; /* function_id should not more than the max support pf_id(32) */ - u16 enable; -}; - -struct mag_cmd_cfg_an_type { - struct mgmt_msg_head head; - - u8 port_id; - u8 opcode; /* 0:get an type 1:set an type */ - u8 rsvd0[2]; - - u32 an_type; /* 0:ieee 1:25G/50 eth consortium */ -}; - -struct mag_cmd_cfg_fec_mode { - struct mgmt_msg_head head; - - u8 port_id; - u8 opcode; /* 0:get fec mode 1:set fec mode */ - u8 fec; - u8 rsvd0; -}; - -struct mag_cmd_cfg_bios_link_cfg { - struct mgmt_msg_head head; - - u8 port_id; - u8 opcode; /* 0:get bios link info 1:set bios link cfg */ - u8 clear; - u8 rsvd0; - - u32 wire_type; - u8 an_en; - u8 speed; - u8 fec; - u8 rsvd1; - u32 speed_mode; - u32 rsvd2[3]; -}; - -struct mag_cmd_restore_link_cfg { - struct mgmt_msg_head head; - - u8 port_id; - u8 rsvd[7]; -}; - -struct mag_cmd_activate_bios_link_cfg { - struct mgmt_msg_head head; - - u32 rsvd[8]; -}; - -/* led type */ -enum mag_led_type { - MAG_CMD_LED_TYPE_ALARM = 0x0, - MAG_CMD_LED_TYPE_LOW_SPEED = 0x1, - MAG_CMD_LED_TYPE_HIGH_SPEED = 0x2 -}; - -/* led mode */ -enum mag_led_mode { - MAG_CMD_LED_MODE_DEFAULT = 0x0, - MAG_CMD_LED_MODE_FORCE_ON = 0x1, - MAG_CMD_LED_MODE_FORCE_OFF = 0x2, - MAG_CMD_LED_MODE_FORCE_BLINK_1HZ = 0x3, - MAG_CMD_LED_MODE_FORCE_BLINK_2HZ = 0x4, - MAG_CMD_LED_MODE_FORCE_BLINK_4HZ = 0x5, - MAG_CMD_LED_MODE_1HZ = 0x6, - MAG_CMD_LED_MODE_2HZ = 0x7, - MAG_CMD_LED_MODE_4HZ = 0x8, -}; - -/* the led is report alarm when any pf of the port is alram */ -struct mag_cmd_set_led_cfg { - struct mgmt_msg_head head; - - u16 function_id; - u8 type; - u8 mode; -}; - -#define XSFP_INFO_MAX_SIZE 640 -/* xsfp wire type, refer to cmis protocol definition */ -enum mag_wire_type { - MAG_CMD_WIRE_TYPE_UNKNOWN = 0x0, - MAG_CMD_WIRE_TYPE_MM = 0x1, - MAG_CMD_WIRE_TYPE_SM = 0x2, - MAG_CMD_WIRE_TYPE_COPPER = 0x3, - MAG_CMD_WIRE_TYPE_ACC = 0x4, - MAG_CMD_WIRE_TYPE_BASET = 0x5, - MAG_CMD_WIRE_TYPE_AOC = 0x40, - MAG_CMD_WIRE_TYPE_ELECTRIC = 0x41, - MAG_CMD_WIRE_TYPE_BACKPLANE = 0x42 -}; - -struct mag_cmd_get_xsfp_info { - struct mgmt_msg_head head; - - u8 port_id; - u8 wire_type; - u16 out_len; - u32 rsvd; - u8 sfp_info[XSFP_INFO_MAX_SIZE]; -}; - -#define MAG_CMD_XSFP_DISABLE 0x0 -#define MAG_CMD_XSFP_ENABLE 0x1 - -struct mag_cmd_set_xsfp_enable { - struct mgmt_msg_head head; - - u16 function_id; /* function_id should not more than the max support pf_id(32) */ - u16 rsvd0; - - u8 status; - u8 rsvd1[3]; -}; - -#define MAG_CMD_XSFP_PRESENT 0x0 -#define MAG_CMD_XSFP_ABSENT 0x1 -struct mag_cmd_get_xsfp_present { - struct mgmt_msg_head head; - - u8 port_id; - u8 abs_status; /* 0:present, 1:absent */ - u8 rsvd[2]; -}; - -#define MAG_CMD_XSFP_READ 0x0 -#define MAG_CMD_XSFP_WRITE 0x1 -struct mag_cmd_set_xsfp_rw { - struct mgmt_msg_head head; - - u8 port_id; - u8 operation; /* 0: read; 1: write */ - u8 value; - u8 rsvd0; - u32 devaddr; - u32 offset; - u32 rsvd1; -}; - -struct mag_cmd_cfg_xsfp_temperature { - struct mgmt_msg_head head; - - u8 opcode; /* 0:read 1:write */ - u8 rsvd0[3]; - s32 max_temp; - s32 min_temp; -}; - -struct mag_cmd_get_xsfp_temperature { - struct mgmt_msg_head head; - - s16 sfp_temp[8]; - u8 rsvd[32]; - s32 max_temp; - s32 min_temp; -}; - -/* xsfp plug event */ -struct mag_cmd_wire_event { - struct mgmt_msg_head head; - - u8 port_id; - u8 status; /* 0:present, 1:absent */ - u8 rsvd[2]; -}; - -/* link err type definition */ -#define MAG_CMD_ERR_XSFP_UNKNOWN 0x0 -struct mag_cmd_link_err_event { - struct mgmt_msg_head head; - - u8 port_id; - u8 link_err_type; - u8 rsvd[2]; -}; - -#define MAG_PARAM_TYPE_DEFAULT_CFG 0x0 -#define MAG_PARAM_TYPE_BIOS_CFG 0x1 -#define MAG_PARAM_TYPE_TOOL_CFG 0x2 -#define MAG_PARAM_TYPE_FINAL_CFG 0x3 -#define MAG_PARAM_TYPE_WIRE_INFO 0x4 -#define MAG_PARAM_TYPE_ADAPT_INFO 0x5 -#define MAG_PARAM_TYPE_MAX_CNT 0x6 -struct param_head { - u8 valid_len; - u8 info_type; - u8 rsvd[2]; -}; - -struct mag_port_link_param { - struct param_head head; - - u8 an; - u8 fec; - u8 speed; - u8 rsvd0; - - u32 used; - u32 an_fec_ability; - u32 an_speed_ability; - u32 an_pause_ability; -}; - -struct mag_port_wire_info { - struct param_head head; - - u8 status; - u8 rsvd0[3]; - - u8 wire_type; - u8 default_fec; - u8 speed; - u8 rsvd1; - u32 speed_ability; -}; - -struct mag_port_adapt_info { - struct param_head head; - - u32 adapt_en; - u32 flash_adapt; - u32 rsvd0[2]; - - u32 wire_node; - u32 an_en; - u32 speed; - u32 fec; -}; - -struct mag_port_param_info { - u8 parameter_cnt; - u8 lane_id; - u8 lane_num; - u8 rsvd0; - - struct mag_port_link_param default_cfg; - struct mag_port_link_param bios_cfg; - struct mag_port_link_param tool_cfg; - struct mag_port_link_param final_cfg; - - struct mag_port_wire_info wire_info; - struct mag_port_adapt_info adapt_info; -}; - -struct mag_cmd_event_port_info { - struct mgmt_msg_head head; - - u8 port_id; - u8 event_type; - u8 rsvd0[2]; - - u8 vendor_name[16]; - u32 port_type; - u32 port_sub_type; - u32 cable_length; - u8 cable_temp; - u8 max_speed; - u8 sfp_type; - u8 rsvd1; - u32 power[4]; - - u8 an_state; - u8 fec; - u16 speed; - - u8 gpio_insert; /* 0:present 1:absent */ - u8 alos; - u8 rx_los; - u8 pma_ctrl; - - u32 pma_fifo_reg; - u32 pma_signal_ok_reg; - u32 pcs_64_66b_reg; - u32 rf_lf; - u8 pcs_link; - u8 pcs_mac_link; - u8 tx_enable; - u8 rx_enable; - u32 pcs_err_cnt; - - u8 eq_data[38]; - u8 rsvd2[2]; - - u32 his_link_machine_state; - u32 cur_link_machine_state; - u8 his_machine_state_data[128]; - u8 cur_machine_state_data[128]; - u8 his_machine_state_length; - u8 cur_machine_state_length; - - struct mag_port_param_info param_info; - u8 rsvd3[360]; -}; - -struct mag_cmd_port_stats { - u64 mac_tx_fragment_pkt_num; - u64 mac_tx_undersize_pkt_num; - u64 mac_tx_undermin_pkt_num; - u64 mac_tx_64_oct_pkt_num; - u64 mac_tx_65_127_oct_pkt_num; - u64 mac_tx_128_255_oct_pkt_num; - u64 mac_tx_256_511_oct_pkt_num; - u64 mac_tx_512_1023_oct_pkt_num; - u64 mac_tx_1024_1518_oct_pkt_num; - u64 mac_tx_1519_2047_oct_pkt_num; - u64 mac_tx_2048_4095_oct_pkt_num; - u64 mac_tx_4096_8191_oct_pkt_num; - u64 mac_tx_8192_9216_oct_pkt_num; - u64 mac_tx_9217_12287_oct_pkt_num; - u64 mac_tx_12288_16383_oct_pkt_num; - u64 mac_tx_1519_max_bad_pkt_num; - u64 mac_tx_1519_max_good_pkt_num; - u64 mac_tx_oversize_pkt_num; - u64 mac_tx_jabber_pkt_num; - u64 mac_tx_bad_pkt_num; - u64 mac_tx_bad_oct_num; - u64 mac_tx_good_pkt_num; - u64 mac_tx_good_oct_num; - u64 mac_tx_total_pkt_num; - u64 mac_tx_total_oct_num; - u64 mac_tx_uni_pkt_num; - u64 mac_tx_multi_pkt_num; - u64 mac_tx_broad_pkt_num; - u64 mac_tx_pause_num; - u64 mac_tx_pfc_pkt_num; - u64 mac_tx_pfc_pri0_pkt_num; - u64 mac_tx_pfc_pri1_pkt_num; - u64 mac_tx_pfc_pri2_pkt_num; - u64 mac_tx_pfc_pri3_pkt_num; - u64 mac_tx_pfc_pri4_pkt_num; - u64 mac_tx_pfc_pri5_pkt_num; - u64 mac_tx_pfc_pri6_pkt_num; - u64 mac_tx_pfc_pri7_pkt_num; - u64 mac_tx_control_pkt_num; - u64 mac_tx_err_all_pkt_num; - u64 mac_tx_from_app_good_pkt_num; - u64 mac_tx_from_app_bad_pkt_num; - - u64 mac_rx_fragment_pkt_num; - u64 mac_rx_undersize_pkt_num; - u64 mac_rx_undermin_pkt_num; - u64 mac_rx_64_oct_pkt_num; - u64 mac_rx_65_127_oct_pkt_num; - u64 mac_rx_128_255_oct_pkt_num; - u64 mac_rx_256_511_oct_pkt_num; - u64 mac_rx_512_1023_oct_pkt_num; - u64 mac_rx_1024_1518_oct_pkt_num; - u64 mac_rx_1519_2047_oct_pkt_num; - u64 mac_rx_2048_4095_oct_pkt_num; - u64 mac_rx_4096_8191_oct_pkt_num; - u64 mac_rx_8192_9216_oct_pkt_num; - u64 mac_rx_9217_12287_oct_pkt_num; - u64 mac_rx_12288_16383_oct_pkt_num; - u64 mac_rx_1519_max_bad_pkt_num; - u64 mac_rx_1519_max_good_pkt_num; - u64 mac_rx_oversize_pkt_num; - u64 mac_rx_jabber_pkt_num; - u64 mac_rx_bad_pkt_num; - u64 mac_rx_bad_oct_num; - u64 mac_rx_good_pkt_num; - u64 mac_rx_good_oct_num; - u64 mac_rx_total_pkt_num; - u64 mac_rx_total_oct_num; - u64 mac_rx_uni_pkt_num; - u64 mac_rx_multi_pkt_num; - u64 mac_rx_broad_pkt_num; - u64 mac_rx_pause_num; - u64 mac_rx_pfc_pkt_num; - u64 mac_rx_pfc_pri0_pkt_num; - u64 mac_rx_pfc_pri1_pkt_num; - u64 mac_rx_pfc_pri2_pkt_num; - u64 mac_rx_pfc_pri3_pkt_num; - u64 mac_rx_pfc_pri4_pkt_num; - u64 mac_rx_pfc_pri5_pkt_num; - u64 mac_rx_pfc_pri6_pkt_num; - u64 mac_rx_pfc_pri7_pkt_num; - u64 mac_rx_control_pkt_num; - u64 mac_rx_sym_err_pkt_num; - u64 mac_rx_fcs_err_pkt_num; - u64 mac_rx_send_app_good_pkt_num; - u64 mac_rx_send_app_bad_pkt_num; - u64 mac_rx_unfilter_pkt_num; -}; - -struct mag_cmd_port_stats_info { - struct mgmt_msg_head head; - - u8 port_id; - u8 rsvd0[3]; -}; - -struct mag_cmd_get_port_stat { - struct mgmt_msg_head head; - - struct mag_cmd_port_stats counter; - u64 rsvd1[15]; -}; - -struct mag_cmd_clr_port_stat { - struct mgmt_msg_head head; - - u8 port_id; - u8 rsvd0[3]; -}; - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_main.c b/drivers/net/ethernet/ramaxel/spnic/spnic_main.c deleted file mode 100644 index 5b9822ebd806..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_main.c +++ /dev/null @@ -1,924 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [NIC]" fmt -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/device.h> -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/interrupt.h> -#include <linux/etherdevice.h> -#include <linux/netdevice.h> -#include <linux/if_vlan.h> -#include <linux/ethtool.h> -#include <linux/dcbnl.h> -#include <linux/tcp.h> -#include <linux/ip.h> -#include <linux/debugfs.h> - -#include "sphw_common.h" -#include "sphw_hw.h" -#include "sphw_crm.h" -#include "sphw_mt.h" -#include "spnic_nic_cfg.h" -#include "spnic_nic_io.h" -#include "spnic_nic_dev.h" -#include "spnic_tx.h" -#include "spnic_rx.h" -#include "spnic_lld.h" -#include "spnic_rss.h" -#include "spnic_dcb.h" - -#define DEFAULT_POLL_WEIGHT 64 -static unsigned int poll_weight = DEFAULT_POLL_WEIGHT; -module_param(poll_weight, uint, 0444); -MODULE_PARM_DESC(poll_weight, "Number packets for NAPI budget (default=64)"); - -#define SPNIC_DEAULT_TXRX_MSIX_PENDING_LIMIT 0 -#define SPNIC_DEAULT_TXRX_MSIX_COALESC_TIMER_CFG 0 -#define SPNIC_DEAULT_TXRX_MSIX_RESEND_TIMER_CFG 7 - -static unsigned char qp_pending_limit = SPNIC_DEAULT_TXRX_MSIX_PENDING_LIMIT; -module_param(qp_pending_limit, byte, 0444); -MODULE_PARM_DESC(qp_pending_limit, "QP MSI-X Interrupt coalescing parameter pending_limit (default=2)"); - -static unsigned char qp_coalesc_timer_cfg = - SPNIC_DEAULT_TXRX_MSIX_COALESC_TIMER_CFG; -module_param(qp_coalesc_timer_cfg, byte, 0444); -MODULE_PARM_DESC(qp_coalesc_timer_cfg, "QP MSI-X Interrupt coalescing parameter coalesc_timer_cfg (default=32)"); - -#define DEFAULT_RX_BUFF_LEN 2 -u16 rx_buff = DEFAULT_RX_BUFF_LEN; -module_param(rx_buff, ushort, 0444); -MODULE_PARM_DESC(rx_buff, "Set rx_buff size, buffer len must be 2^n. 2 - 16, default is 2KB"); - -static unsigned int lro_replenish_thld = 256; -module_param(lro_replenish_thld, uint, 0444); -MODULE_PARM_DESC(lro_replenish_thld, "Number wqe for lro replenish buffer (default=256)"); - -#define SPNIC_NIC_DEV_WQ_NAME "spnic_nic_dev_wq" - -#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_LINK) - -#define QID_MASKED(q_id, nic_dev) ((q_id) & ((nic_dev)->num_qps - 1)) -#define WATCHDOG_TIMEOUT 5 - -#define SPNIC_SQ_DEPTH 1024 -#define SPNIC_RQ_DEPTH 1024 - -enum spnic_rx_buff_len { - RX_BUFF_VALID_2KB = 2, - RX_BUFF_VALID_4KB = 4, - RX_BUFF_VALID_8KB = 8, - RX_BUFF_VALID_16KB = 16, -}; - -#define CONVERT_UNIT 1024 - -static int spnic_netdev_event(struct notifier_block *notifier, unsigned long event, void *ptr); - -/* used for netdev notifier register/unregister */ -DEFINE_MUTEX(spnic_netdev_notifiers_mutex); -static int spnic_netdev_notifiers_ref_cnt; -static struct notifier_block spnic_netdev_notifier = { - .notifier_call = spnic_netdev_event, -}; - -static void spnic_register_notifier(struct spnic_nic_dev *nic_dev) -{ - int err; - - mutex_lock(&spnic_netdev_notifiers_mutex); - spnic_netdev_notifiers_ref_cnt++; - if (spnic_netdev_notifiers_ref_cnt == 1) { - err = register_netdevice_notifier(&spnic_netdev_notifier); - if (err) { - nic_info(&nic_dev->pdev->dev, "Register netdevice notifier failed, err: %d\n", - err); - spnic_netdev_notifiers_ref_cnt--; - } - } - mutex_unlock(&spnic_netdev_notifiers_mutex); -} - -static void spnic_unregister_notifier(struct spnic_nic_dev *nic_dev) -{ - mutex_lock(&spnic_netdev_notifiers_mutex); - if (spnic_netdev_notifiers_ref_cnt == 1) - unregister_netdevice_notifier(&spnic_netdev_notifier); - - if (spnic_netdev_notifiers_ref_cnt) - spnic_netdev_notifiers_ref_cnt--; - mutex_unlock(&spnic_netdev_notifiers_mutex); -} - -#define SPNIC_MAX_VLAN_DEPTH_OFFLOAD_SUPPORT 1 -#define SPNIC_VLAN_CLEAR_OFFLOAD (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | \ - NETIF_F_SCTP_CRC | NETIF_F_RXCSUM | \ - NETIF_F_ALL_TSO) - -int spnic_netdev_event(struct notifier_block *notifier, unsigned long event, void *ptr) -{ - struct net_device *ndev = netdev_notifier_info_to_dev(ptr); - struct net_device *real_dev = NULL; - struct net_device *ret = NULL; - struct spnic_nic_dev *nic_dev = NULL; - u16 vlan_depth; - - if (!is_vlan_dev(ndev)) - return NOTIFY_DONE; - - dev_hold(ndev); - - switch (event) { - case NETDEV_REGISTER: - real_dev = vlan_dev_real_dev(ndev); - nic_dev = spnic_get_uld_dev_by_ifname(real_dev->name, SERVICE_T_NIC); - if (!nic_dev) - goto out; - - vlan_depth = 1; - ret = vlan_dev_priv(ndev)->real_dev; - while (is_vlan_dev(ret)) { - ret = vlan_dev_priv(ret)->real_dev; - vlan_depth++; - } - - if (vlan_depth == SPNIC_MAX_VLAN_DEPTH_OFFLOAD_SUPPORT) { - ndev->vlan_features &= (~SPNIC_VLAN_CLEAR_OFFLOAD); - } else if (vlan_depth > SPNIC_MAX_VLAN_DEPTH_OFFLOAD_SUPPORT) { - ndev->hw_features &= (~SPNIC_VLAN_CLEAR_OFFLOAD); - ndev->features &= (~SPNIC_VLAN_CLEAR_OFFLOAD); - } - - break; - - default: - break; - }; - -out: - dev_put(ndev); - - return NOTIFY_DONE; -} - -void spnic_link_status_change(struct spnic_nic_dev *nic_dev, bool status) -{ - struct net_device *netdev = nic_dev->netdev; - - if (!SPHW_CHANNEL_RES_VALID(nic_dev) || test_bit(SPNIC_LP_TEST, &nic_dev->flags)) - return; - - if (status) { - if (netif_carrier_ok(netdev)) - return; - - nic_dev->link_status = status; - netif_carrier_on(netdev); - nicif_info(nic_dev, link, netdev, "Link is up\n"); - } else { - if (!netif_carrier_ok(netdev)) - return; - - nic_dev->link_status = status; - netif_carrier_off(netdev); - nicif_info(nic_dev, link, netdev, "Link is down\n"); - } -} - -static void netdev_feature_init(struct net_device *netdev) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - netdev_features_t dft_fts = 0; - netdev_features_t cso_fts = 0; - netdev_features_t vlan_fts = 0; - netdev_features_t tso_fts = 0; - netdev_features_t hw_features = 0; - - dft_fts |= NETIF_F_SG | NETIF_F_HIGHDMA; - - if (SPNIC_SUPPORT_CSUM(nic_dev->hwdev)) - cso_fts |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM; - if (SPNIC_SUPPORT_SCTP_CRC(nic_dev->hwdev)) - cso_fts |= NETIF_F_SCTP_CRC; - - if (SPNIC_SUPPORT_TSO(nic_dev->hwdev)) - tso_fts |= NETIF_F_TSO | NETIF_F_TSO6; - - if (SPNIC_SUPPORT_VLAN_OFFLOAD(nic_dev->hwdev)) { - vlan_fts |= NETIF_F_HW_VLAN_CTAG_TX; - vlan_fts |= NETIF_F_HW_VLAN_CTAG_RX; - } - - if (SPNIC_SUPPORT_RXVLAN_FILTER(nic_dev->hwdev)) - vlan_fts |= NETIF_F_HW_VLAN_CTAG_FILTER; - - if (SPNIC_SUPPORT_VXLAN_OFFLOAD(nic_dev->hwdev)) - tso_fts |= NETIF_F_GSO_UDP_TUNNEL | NETIF_F_GSO_UDP_TUNNEL_CSUM; - - /* LRO is disable in default, only set hw features */ - if (SPNIC_SUPPORT_LRO(nic_dev->hwdev)) - hw_features |= NETIF_F_LRO; - - netdev->features |= dft_fts | cso_fts | tso_fts | vlan_fts; - netdev->vlan_features |= dft_fts | cso_fts | tso_fts; - - hw_features |= netdev->hw_features; - - hw_features |= netdev->features; - - netdev->hw_features = hw_features; - - netdev->priv_flags |= IFF_UNICAST_FLT; - - netdev->hw_enc_features |= dft_fts; - if (SPNIC_SUPPORT_VXLAN_OFFLOAD(nic_dev->hwdev)) { - netdev->hw_enc_features |= cso_fts; - netdev->hw_enc_features |= tso_fts | NETIF_F_TSO_ECN; - } -} - -static void init_intr_coal_param(struct spnic_nic_dev *nic_dev) -{ - struct spnic_intr_coal_info *info = NULL; - u16 i; - - for (i = 0; i < nic_dev->max_qps; i++) { - info = &nic_dev->intr_coalesce[i]; - - info->pending_limt = qp_pending_limit; - info->coalesce_timer_cfg = qp_coalesc_timer_cfg; - - info->resend_timer_cfg = SPNIC_DEAULT_TXRX_MSIX_RESEND_TIMER_CFG; - - info->pkt_rate_high = SPNIC_RX_RATE_HIGH; - info->rx_usecs_high = SPNIC_RX_COAL_TIME_HIGH; - info->rx_pending_limt_high = SPNIC_RX_PENDING_LIMIT_HIGH; - info->pkt_rate_low = SPNIC_RX_RATE_LOW; - info->rx_usecs_low = SPNIC_RX_COAL_TIME_LOW; - info->rx_pending_limt_low = SPNIC_RX_PENDING_LIMIT_LOW; - } -} - -static int spnic_init_intr_coalesce(struct spnic_nic_dev *nic_dev) -{ - u64 size; - - if (qp_pending_limit != SPNIC_DEAULT_TXRX_MSIX_PENDING_LIMIT || - qp_coalesc_timer_cfg != SPNIC_DEAULT_TXRX_MSIX_COALESC_TIMER_CFG) - nic_dev->intr_coal_set_flag = 1; - else - nic_dev->intr_coal_set_flag = 0; - - size = sizeof(*nic_dev->intr_coalesce) * nic_dev->max_qps; - if (!size) { - nic_err(&nic_dev->pdev->dev, "Cannot allocate zero size intr coalesce\n"); - return -EINVAL; - } - nic_dev->intr_coalesce = kzalloc(size, GFP_KERNEL); - if (!nic_dev->intr_coalesce) { - nic_err(&nic_dev->pdev->dev, "Failed to alloc intr coalesce\n"); - return -ENOMEM; - } - - init_intr_coal_param(nic_dev); - - if (test_bit(SPNIC_INTR_ADAPT, &nic_dev->flags)) - nic_dev->adaptive_rx_coal = 1; - else - nic_dev->adaptive_rx_coal = 0; - - return 0; -} - -static void spnic_free_intr_coalesce(struct spnic_nic_dev *nic_dev) -{ - kfree(nic_dev->intr_coalesce); -} - -static int spnic_alloc_txrxqs(struct spnic_nic_dev *nic_dev) -{ - struct net_device *netdev = nic_dev->netdev; - int err; - - err = spnic_alloc_txqs(netdev); - if (err) { - nic_err(&nic_dev->pdev->dev, "Failed to alloc txqs\n"); - return err; - } - - err = spnic_alloc_rxqs(netdev); - if (err) { - nic_err(&nic_dev->pdev->dev, "Failed to alloc rxqs\n"); - goto alloc_rxqs_err; - } - - err = spnic_init_intr_coalesce(nic_dev); - if (err) { - nic_err(&nic_dev->pdev->dev, "Failed to init_intr_coalesce\n"); - goto init_intr_err; - } - - return 0; - -init_intr_err: - spnic_free_rxqs(netdev); - -alloc_rxqs_err: - spnic_free_txqs(netdev); - - return err; -} - -static void spnic_free_txrxqs(struct spnic_nic_dev *nic_dev) -{ - spnic_free_intr_coalesce(nic_dev); - spnic_free_rxqs(nic_dev->netdev); - spnic_free_txqs(nic_dev->netdev); -} - -static void spnic_sw_deinit(struct spnic_nic_dev *nic_dev) -{ - spnic_free_txrxqs(nic_dev); - - spnic_clean_mac_list_filter(nic_dev); - - spnic_del_mac(nic_dev->hwdev, nic_dev->netdev->dev_addr, 0, - sphw_global_func_id(nic_dev->hwdev), SPHW_CHANNEL_NIC); - - spnic_clear_rss_config(nic_dev); -} - -static int spnic_sw_init(struct spnic_nic_dev *nic_dev) -{ - struct net_device *netdev = nic_dev->netdev; - u64 nic_feature; - int err = 0; - - nic_feature = spnic_get_feature_cap(nic_dev->hwdev); - nic_feature &= SPNIC_DRV_FEATURE; - spnic_update_nic_feature(nic_dev->hwdev, nic_feature); - - sema_init(&nic_dev->port_state_sem, 1); - - err = spnic_dcb_init(nic_dev); - if (err) { - nic_err(&nic_dev->pdev->dev, "Failed to init dcb\n"); - return -EFAULT; - } - - nic_dev->q_params.sq_depth = SPNIC_SQ_DEPTH; - nic_dev->q_params.rq_depth = SPNIC_RQ_DEPTH; - - spnic_try_to_enable_rss(nic_dev); - - err = spnic_get_default_mac(nic_dev->hwdev, netdev->dev_addr); - if (err) { - nic_err(&nic_dev->pdev->dev, "Failed to get MAC address\n"); - goto get_mac_err; - } - - if (!is_valid_ether_addr(netdev->dev_addr)) { - if (!SPNIC_FUNC_IS_VF(nic_dev->hwdev)) { - nic_err(&nic_dev->pdev->dev, "Invalid MAC address %pM\n", netdev->dev_addr); - err = -EIO; - goto err_mac; - } - - nic_info(&nic_dev->pdev->dev, "Invalid MAC address %pM, using random\n", - netdev->dev_addr); - eth_hw_addr_random(netdev); - } - - err = spnic_set_mac(nic_dev->hwdev, netdev->dev_addr, 0, - sphw_global_func_id(nic_dev->hwdev), SPHW_CHANNEL_NIC); - /* When this is VF driver, we must consider that PF has already set VF - * MAC, and we can't consider this condition is error status during - * driver probe procedure. - */ - if (err && err != SPNIC_PF_SET_VF_ALREADY) { - nic_err(&nic_dev->pdev->dev, "Failed to set default MAC\n"); - goto set_mac_err; - } - - /* MTU range: 384 - 9600 */ - netdev->min_mtu = SPNIC_MIN_MTU_SIZE; - netdev->max_mtu = SPNIC_MAX_JUMBO_FRAME_SIZE; - - err = spnic_alloc_txrxqs(nic_dev); - if (err) { - nic_err(&nic_dev->pdev->dev, "Failed to alloc qps\n"); - goto alloc_qps_err; - } - - return 0; - -alloc_qps_err: - spnic_del_mac(nic_dev->hwdev, netdev->dev_addr, 0, sphw_global_func_id(nic_dev->hwdev), - SPHW_CHANNEL_NIC); - -set_mac_err: -err_mac: -get_mac_err: - spnic_clear_rss_config(nic_dev); - - return err; -} - -static void spnic_assign_netdev_ops(struct spnic_nic_dev *adapter) -{ - spnic_set_netdev_ops(adapter); - if (!SPNIC_FUNC_IS_VF(adapter->hwdev)) - spnic_set_ethtool_ops(adapter->netdev); - else - spnicvf_set_ethtool_ops(adapter->netdev); - - adapter->netdev->watchdog_timeo = WATCHDOG_TIMEOUT * HZ; -} - -static int spnic_validate_parameters(struct spnic_lld_dev *lld_dev) -{ - struct pci_dev *pdev = lld_dev->pdev; - - /* If weight exceeds the queue depth, the queue resources will be - * exhausted, and increasing it has no effect. - */ - if (!poll_weight || poll_weight > SPNIC_MAX_RX_QUEUE_DEPTH) { - nic_warn(&pdev->dev, "Module Parameter poll_weight is out of range: [1, %d], resetting to %d\n", - SPNIC_MAX_RX_QUEUE_DEPTH, DEFAULT_POLL_WEIGHT); - poll_weight = DEFAULT_POLL_WEIGHT; - } - - /* check rx_buff value, default rx_buff is 2KB. - * Valid rx_buff include 2KB/4KB/8KB/16KB. - */ - if (rx_buff != RX_BUFF_VALID_2KB && rx_buff != RX_BUFF_VALID_4KB && - rx_buff != RX_BUFF_VALID_8KB && rx_buff != RX_BUFF_VALID_16KB) { - nic_warn(&pdev->dev, "Module Parameter rx_buff value %u is out of range, must be 2^n. Valid range is 2 - 16, resetting to %dKB", - rx_buff, DEFAULT_RX_BUFF_LEN); - rx_buff = DEFAULT_RX_BUFF_LEN; - } - - return 0; -} - -static void adaptive_configuration_init(struct spnic_nic_dev *nic_dev) -{ - /* TODO: */ -} - -static int set_interrupt_moder(struct spnic_nic_dev *nic_dev, u16 q_id, - u8 coalesc_timer_cfg, u8 pending_limt) -{ - struct interrupt_info info; - int err; - - memset(&info, 0, sizeof(info)); - - if (coalesc_timer_cfg == nic_dev->rxqs[q_id].last_coalesc_timer_cfg && - pending_limt == nic_dev->rxqs[q_id].last_pending_limt) - return 0; - - /* netdev not running or qp not in using, - * don't need to set coalesce to hw - */ - if (!SPHW_CHANNEL_RES_VALID(nic_dev) || q_id >= nic_dev->q_params.num_qps) - return 0; - - info.lli_set = 0; - info.interrupt_coalesc_set = 1; - info.coalesc_timer_cfg = coalesc_timer_cfg; - info.pending_limt = pending_limt; - info.msix_index = nic_dev->q_params.irq_cfg[q_id].msix_entry_idx; - info.resend_timer_cfg = nic_dev->intr_coalesce[q_id].resend_timer_cfg; - - err = sphw_set_interrupt_cfg(nic_dev->hwdev, info, SPHW_CHANNEL_NIC); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Failed to modify moderation for Queue: %u\n", q_id); - } else { - nic_dev->rxqs[q_id].last_coalesc_timer_cfg = coalesc_timer_cfg; - nic_dev->rxqs[q_id].last_pending_limt = pending_limt; - } - - return err; -} - -static void calc_coal_para(struct spnic_nic_dev *nic_dev, struct spnic_intr_coal_info *q_coal, - u64 rx_rate, u8 *coalesc_timer_cfg, u8 *pending_limt) -{ - if (rx_rate < q_coal->pkt_rate_low) { - *coalesc_timer_cfg = q_coal->rx_usecs_low; - *pending_limt = q_coal->rx_pending_limt_low; - } else if (rx_rate > q_coal->pkt_rate_high) { - *coalesc_timer_cfg = q_coal->rx_usecs_high; - *pending_limt = q_coal->rx_pending_limt_high; - } else { - *coalesc_timer_cfg = - (u8)((rx_rate - q_coal->pkt_rate_low) * - (q_coal->rx_usecs_high - q_coal->rx_usecs_low) / - (q_coal->pkt_rate_high - q_coal->pkt_rate_low) + q_coal->rx_usecs_low); - - *pending_limt = q_coal->rx_pending_limt_low; - } -} - -static void update_queue_coal(struct spnic_nic_dev *nic_dev, u16 qid, - u64 rx_rate, u64 avg_pkt_size, u64 tx_rate) -{ - struct spnic_intr_coal_info *q_coal = NULL; - u8 coalesc_timer_cfg, pending_limt; - - q_coal = &nic_dev->intr_coalesce[qid]; - - if (rx_rate > SPNIC_RX_RATE_THRESH && - avg_pkt_size > SPNIC_AVG_PKT_SMALL) { - calc_coal_para(nic_dev, q_coal, rx_rate, &coalesc_timer_cfg, &pending_limt); - } else { - coalesc_timer_cfg = SPNIC_LOWEST_LATENCY; - pending_limt = q_coal->rx_pending_limt_low; - } - - set_interrupt_moder(nic_dev, qid, coalesc_timer_cfg, pending_limt); -} - -void spnic_auto_moderation_work(struct work_struct *work) -{ - struct delayed_work *delay = to_delayed_work(work); - struct spnic_nic_dev *nic_dev = container_of(delay, struct spnic_nic_dev, moderation_task); - unsigned long period = (unsigned long)(jiffies - nic_dev->last_moder_jiffies); - u64 rx_packets, rx_bytes, rx_pkt_diff, rx_rate, avg_pkt_size; - u64 tx_packets, tx_bytes, tx_pkt_diff, tx_rate; - u16 qid; - - if (!test_bit(SPNIC_INTF_UP, &nic_dev->flags)) - return; - - queue_delayed_work(nic_dev->workq, &nic_dev->moderation_task, SPNIC_MODERATONE_DELAY); - - if (!nic_dev->adaptive_rx_coal || !period) - return; - - for (qid = 0; qid < nic_dev->q_params.num_qps; qid++) { - rx_packets = nic_dev->rxqs[qid].rxq_stats.packets; - rx_bytes = nic_dev->rxqs[qid].rxq_stats.bytes; - tx_packets = nic_dev->txqs[qid].txq_stats.packets; - tx_bytes = nic_dev->txqs[qid].txq_stats.bytes; - - rx_pkt_diff = rx_packets - nic_dev->rxqs[qid].last_moder_packets; - avg_pkt_size = rx_pkt_diff ? - ((unsigned long)(rx_bytes - nic_dev->rxqs[qid].last_moder_bytes)) / - rx_pkt_diff : 0; - - rx_rate = rx_pkt_diff * HZ / period; - tx_pkt_diff = tx_packets - nic_dev->txqs[qid].last_moder_packets; - tx_rate = tx_pkt_diff * HZ / period; - - update_queue_coal(nic_dev, qid, rx_rate, avg_pkt_size, tx_rate); - - nic_dev->rxqs[qid].last_moder_packets = rx_packets; - nic_dev->rxqs[qid].last_moder_bytes = rx_bytes; - nic_dev->txqs[qid].last_moder_packets = tx_packets; - nic_dev->txqs[qid].last_moder_bytes = tx_bytes; - } - - nic_dev->last_moder_jiffies = jiffies; -} - -void spnic_periodic_work_handler(struct work_struct *work) -{ - struct delayed_work *delay = to_delayed_work(work); - struct spnic_nic_dev *nic_dev = container_of(delay, struct spnic_nic_dev, periodic_work); - - if (test_and_clear_bit(EVENT_WORK_TX_TIMEOUT, &nic_dev->event_flag)) - sphw_fault_event_report(nic_dev->hwdev, SPHW_FAULT_SRC_TX_TIMEOUT, - FAULT_LEVEL_SERIOUS_FLR); - - queue_delayed_work(nic_dev->workq, &nic_dev->periodic_work, HZ); -} - -static void free_nic_dev(struct spnic_nic_dev *nic_dev) -{ - destroy_workqueue(nic_dev->workq); - kfree(nic_dev->vlan_bitmap); -} - -static int setup_nic_dev(struct net_device *netdev, struct spnic_lld_dev *lld_dev) -{ - struct pci_dev *pdev = lld_dev->pdev; - struct spnic_nic_dev *nic_dev; - u32 page_num; - - nic_dev = (struct spnic_nic_dev *)netdev_priv(netdev); - nic_dev->netdev = netdev; - SET_NETDEV_DEV(netdev, &pdev->dev); - nic_dev->hwdev = lld_dev->hwdev; - nic_dev->pdev = pdev; - nic_dev->poll_weight = (int)poll_weight; - nic_dev->msg_enable = DEFAULT_MSG_ENABLE; - nic_dev->lro_replenish_thld = lro_replenish_thld; - nic_dev->rx_buff_len = (u16)(rx_buff * CONVERT_UNIT); - nic_dev->dma_rx_buff_size = RX_BUFF_NUM_PER_PAGE * nic_dev->rx_buff_len; - page_num = nic_dev->dma_rx_buff_size / PAGE_SIZE; - nic_dev->page_order = page_num > 0 ? ilog2(page_num) : 0; - - mutex_init(&nic_dev->nic_mutex); - - nic_dev->vlan_bitmap = kzalloc(VLAN_BITMAP_SIZE(nic_dev), GFP_KERNEL); - if (!nic_dev->vlan_bitmap) { - nic_err(&pdev->dev, "Failed to allocate vlan bitmap\n"); - return -ENOMEM; - } - - nic_dev->workq = create_singlethread_workqueue(SPNIC_NIC_DEV_WQ_NAME); - if (!nic_dev->workq) { - nic_err(&pdev->dev, "Failed to initialize nic workqueue\n"); - kfree(nic_dev->vlan_bitmap); - return -ENOMEM; - } - - INIT_DELAYED_WORK(&nic_dev->periodic_work, spnic_periodic_work_handler); - - INIT_LIST_HEAD(&nic_dev->uc_filter_list); - INIT_LIST_HEAD(&nic_dev->mc_filter_list); - INIT_WORK(&nic_dev->rx_mode_work, spnic_set_rx_mode_work); - - INIT_LIST_HEAD(&nic_dev->rx_flow_rule.rules); - INIT_LIST_HEAD(&nic_dev->tcam.tcam_list); - INIT_LIST_HEAD(&nic_dev->tcam.tcam_dynamic_info.tcam_dynamic_list); - - return 0; -} - -static int spnic_set_default_hw_feature(struct spnic_nic_dev *nic_dev) -{ - int err; - - if (!SPNIC_FUNC_IS_VF(nic_dev->hwdev)) { - err = spnic_dcb_reset_hw_config(nic_dev); - if (err) { - nic_err(&nic_dev->pdev->dev, "Failed to reset hw dcb configuration\n"); - return err; - } - } - - err = spnic_set_nic_feature_to_hw(nic_dev->hwdev); - if (err) { - nic_err(&nic_dev->pdev->dev, "Failed to set nic features\n"); - return err; - } - - /* enable all hw features in netdev->features */ - return spnic_set_hw_features(nic_dev); -} - -static int nic_probe(struct spnic_lld_dev *lld_dev, void **uld_dev, char *uld_dev_name) -{ - struct pci_dev *pdev = lld_dev->pdev; - struct spnic_nic_dev *nic_dev = NULL; - struct net_device *netdev = NULL; - u16 max_qps, glb_func_id; - int err; - - /* *uld_dev should always no be NULL */ - *uld_dev = lld_dev; - - if (!sphw_support_nic(lld_dev->hwdev, NULL)) { - nic_info(&pdev->dev, "Hw don't support nic\n"); - return 0; - } - - nic_info(&pdev->dev, "NIC service probe begin\n"); - - err = spnic_validate_parameters(lld_dev); - if (err) { - err = -EINVAL; - goto err_out; - } - - glb_func_id = sphw_global_func_id(lld_dev->hwdev); - err = sphw_func_reset(lld_dev->hwdev, glb_func_id, SPHW_NIC_RES, SPHW_CHANNEL_NIC); - if (err) { - nic_err(&pdev->dev, "Failed to reset function\n"); - goto err_out; - } - - max_qps = sphw_func_max_nic_qnum(lld_dev->hwdev); - netdev = alloc_etherdev_mq(sizeof(*nic_dev), max_qps); - if (!netdev) { - nic_err(&pdev->dev, "Failed to allocate ETH device\n"); - err = -ENOMEM; - goto err_out; - } - - nic_dev = (struct spnic_nic_dev *)netdev_priv(netdev); - err = setup_nic_dev(netdev, lld_dev); - if (err) - goto setup_dev_err; - - adaptive_configuration_init(nic_dev); - - /* get nic cap from hw */ - sphw_support_nic(lld_dev->hwdev, &nic_dev->nic_cap); - - err = spnic_init_nic_hwdev(nic_dev->hwdev, pdev, &pdev->dev, nic_dev->rx_buff_len); - if (err) { - nic_err(&pdev->dev, "Failed to init nic hwdev\n"); - goto init_nic_hwdev_err; - } - - err = spnic_sw_init(nic_dev); - if (err) - goto sw_init_err; - - spnic_assign_netdev_ops(nic_dev); - netdev_feature_init(netdev); - - err = spnic_set_default_hw_feature(nic_dev); - if (err) - goto set_features_err; - - spnic_register_notifier(nic_dev); - - err = register_netdev(netdev); - if (err) { - nic_err(&pdev->dev, "Failed to register netdev\n"); - err = -ENOMEM; - goto netdev_err; - } - - queue_delayed_work(nic_dev->workq, &nic_dev->periodic_work, HZ); - netif_carrier_off(netdev); - - *uld_dev = nic_dev; - nicif_info(nic_dev, probe, netdev, "Register netdev succeed\n"); - nic_info(&pdev->dev, "NIC service probed\n"); - - return 0; - -netdev_err: - spnic_unregister_notifier(nic_dev); - -set_features_err: - spnic_sw_deinit(nic_dev); - -sw_init_err: - spnic_free_nic_hwdev(nic_dev->hwdev); - -init_nic_hwdev_err: - free_nic_dev(nic_dev); -setup_dev_err: - free_netdev(netdev); - -err_out: - nic_err(&pdev->dev, "NIC service probe failed\n"); - - return err; -} - -static void nic_remove(struct spnic_lld_dev *lld_dev, void *adapter) -{ - struct spnic_nic_dev *nic_dev = adapter; - struct net_device *netdev = NULL; - - if (!nic_dev || !sphw_support_nic(lld_dev->hwdev, NULL)) - return; - - nic_info(&lld_dev->pdev->dev, "NIC service remove begin\n"); - - netdev = nic_dev->netdev; - - unregister_netdev(netdev); - spnic_unregister_notifier(nic_dev); - - cancel_delayed_work_sync(&nic_dev->periodic_work); - cancel_work_sync(&nic_dev->rx_mode_work); - destroy_workqueue(nic_dev->workq); - - spnic_sw_deinit(nic_dev); - - spnic_flush_rx_flow_rule(nic_dev); - spnic_free_nic_hwdev(nic_dev->hwdev); - - kfree(nic_dev->vlan_bitmap); - - free_netdev(netdev); - - nic_info(&lld_dev->pdev->dev, "NIC service removed\n"); -} - -static void sriov_state_change(struct spnic_nic_dev *nic_dev, - const struct sphw_sriov_state_info *info) -{ - if (!info->enable) - spnic_clear_vfs_info(nic_dev->hwdev); -} - -const char *g_spnic_module_link_err[LINK_ERR_NUM] = { - "Unrecognized module", -}; - -void sphw_port_module_event_handler(struct spnic_nic_dev *nic_dev, struct sphw_event_info *event) -{ - enum port_module_event_type type = event->module_event.type; - enum link_err_type err_type = event->module_event.err_type; - - switch (type) { - case SPHW_PORT_MODULE_CABLE_PLUGGED: - case SPHW_PORT_MODULE_CABLE_UNPLUGGED: - nicif_info(nic_dev, link, nic_dev->netdev, - "Port module event: Cable %s\n", - type == SPHW_PORT_MODULE_CABLE_PLUGGED ? - "plugged" : "unplugged"); - break; - case SPHW_PORT_MODULE_LINK_ERR: - if (err_type >= LINK_ERR_NUM) { - nicif_info(nic_dev, link, nic_dev->netdev, - "Link failed, Unknown error type: 0x%x\n", err_type); - } else { - nicif_info(nic_dev, link, nic_dev->netdev, "Link failed, error type: 0x%x: %s\n", - err_type, g_spnic_module_link_err[err_type]); - } - break; - default: - nicif_err(nic_dev, link, nic_dev->netdev, "Unknown port module type %d\n", type); - break; - } -} - -void nic_event(struct spnic_lld_dev *lld_dev, void *adapter, struct sphw_event_info *event) -{ - struct spnic_nic_dev *nic_dev = adapter; - enum sphw_event_type type; - - if (!nic_dev || !event || !sphw_support_nic(lld_dev->hwdev, NULL)) - return; - - type = event->type; - - switch (type) { - case SPHW_EVENT_LINK_DOWN: - spnic_link_status_change(nic_dev, false); - break; - case SPHW_EVENT_LINK_UP: - spnic_link_status_change(nic_dev, true); - break; - case SPHW_EVENT_SRIOV_STATE_CHANGE: - sriov_state_change(nic_dev, &event->sriov_state); - break; - case SPHW_EVENT_PORT_MODULE_EVENT: - sphw_port_module_event_handler(nic_dev, event); - break; - case SPHW_EVENT_FAULT: - if (event->info.fault_level == FAULT_LEVEL_SERIOUS_FLR && - event->info.event.chip.func_id == sphw_global_func_id(lld_dev->hwdev)) - spnic_link_status_change(nic_dev, false); - break; - case SPHW_EVENT_PCIE_LINK_DOWN: - case SPHW_EVENT_HEART_LOST: - spnic_link_status_change(nic_dev, false); - break; - default: - break; - } -} - -struct net_device *spnic_get_netdev_by_lld(struct spnic_lld_dev *lld_dev) -{ - struct spnic_nic_dev *nic_dev = NULL; - - if (!lld_dev || !sphw_support_nic(lld_dev->hwdev, NULL)) - return NULL; - - nic_dev = spnic_get_uld_dev_by_pdev(lld_dev->pdev, SERVICE_T_NIC); - if (!nic_dev) { - sdk_err(&lld_dev->pdev->dev, - "There's no net device attached on the pci device"); - return NULL; - } - - return nic_dev->netdev; -} - -void *spnic_get_hwdev_by_netdev(struct net_device *netdev) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - - if (!nic_dev || !netdev) - return NULL; - - return nic_dev->hwdev; -} - -struct spnic_uld_info nic_uld_info = { - .probe = nic_probe, - .remove = nic_remove, - .suspend = NULL, - .resume = NULL, - .event = nic_event, - .ioctl = nic_ioctl, -}; diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_mgmt_interface.h b/drivers/net/ethernet/ramaxel/spnic/spnic_mgmt_interface.h deleted file mode 100644 index 720f6fcf5f0a..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_mgmt_interface.h +++ /dev/null @@ -1,605 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPNIC_MGMT_INTERFACE_H -#define SPNIC_MGMT_INTERFACE_H - -#include <linux/if_ether.h> - -#include "sphw_mgmt_msg_base.h" - -#define SPNIC_CMD_OP_SET MGMT_MSG_CMD_OP_SET -#define SPNIC_CMD_OP_GET MGMT_MSG_CMD_OP_GET - -#define SPNIC_CMD_OP_ADD 1 -#define SPNIC_CMD_OP_DEL 0 - -enum nic_feature_cap { - NIC_F_CSUM = BIT(0), - NIC_F_SCTP_CRC = BIT(1), - NIC_F_TSO = BIT(2), - NIC_F_LRO = BIT(3), - NIC_F_UFO = BIT(4), - NIC_F_RSS = BIT(5), - NIC_F_RX_VLAN_FILTER = BIT(6), - NIC_F_RX_VLAN_STRIP = BIT(7), - NIC_F_TX_VLAN_INSERT = BIT(8), - NIC_F_VXLAN_OFFLOAD = BIT(9), - NIC_F_IPSEC_OFFLOAD = BIT(10), - NIC_F_FDIR = BIT(11), - NIC_F_PROMISC = BIT(12), - NIC_F_ALLMULTI = BIT(13), -}; - -#define NIC_F_ALL_MASK 0x3FFF - -#define NIC_MAX_FEATURE_QWORD 4 -struct spnic_cmd_feature_nego { - struct mgmt_msg_head msg_head; - - u16 func_id; - u8 opcode; /* 1: set, 0: get */ - u8 rsvd; - u64 s_feature[NIC_MAX_FEATURE_QWORD]; -}; - -struct spnic_port_mac_set { - struct mgmt_msg_head msg_head; - - u16 func_id; - u16 vlan_id; - u16 rsvd1; - u8 mac[ETH_ALEN]; -}; - -struct spnic_port_mac_update { - struct mgmt_msg_head msg_head; - - u16 func_id; - u16 vlan_id; - u16 rsvd1; - u8 old_mac[ETH_ALEN]; - u16 rsvd2; - u8 new_mac[ETH_ALEN]; -}; - -struct spnic_vport_state { - struct mgmt_msg_head msg_head; - - u16 func_id; - u16 rsvd1; - u8 state; /* 0--disable, 1--enable */ - u8 rsvd2[3]; -}; - -struct spnic_port_state { - struct mgmt_msg_head msg_head; - - u16 func_id; - u16 rsvd1; - u8 state; /* 0--disable, 1--enable */ - u8 rsvd2[3]; -}; - -struct spnic_cmd_clear_qp_resource { - struct mgmt_msg_head msg_head; - - u16 func_id; - u16 rsvd1; -}; - -struct spnic_port_stats_info { - struct mgmt_msg_head msg_head; - - u16 func_id; - u16 rsvd1; -}; - -struct spnic_vport_stats { - u64 tx_unicast_pkts_vport; - u64 tx_unicast_bytes_vport; - u64 tx_multicast_pkts_vport; - u64 tx_multicast_bytes_vport; - u64 tx_broadcast_pkts_vport; - u64 tx_broadcast_bytes_vport; - - u64 rx_unicast_pkts_vport; - u64 rx_unicast_bytes_vport; - u64 rx_multicast_pkts_vport; - u64 rx_multicast_bytes_vport; - u64 rx_broadcast_pkts_vport; - u64 rx_broadcast_bytes_vport; - - u64 tx_discard_vport; - u64 rx_discard_vport; - u64 tx_err_vport; - u64 rx_err_vport; -}; - -struct spnic_cmd_vport_stats { - struct mgmt_msg_head msg_head; - - u32 stats_size; - u32 rsvd1; - struct spnic_vport_stats stats; - u64 rsvd2[6]; -}; - -struct spnic_cmd_qpn { - struct mgmt_msg_head msg_head; - - u16 func_id; - u16 base_qpn; -}; - -enum spnic_func_tbl_cfg_bitmap { - FUNC_CFG_INIT, - FUNC_CFG_RX_BUF_SIZE, - FUNC_CFG_MTU, -}; - -struct spnic_func_tbl_cfg { - u16 rx_wqe_buf_size; - u16 mtu; - u32 rsvd[9]; -}; - -struct spnic_cmd_set_func_tbl { - struct mgmt_msg_head msg_head; - - u16 func_id; - u16 rsvd; - - u32 cfg_bitmap; - struct spnic_func_tbl_cfg tbl_cfg; -}; - -struct spnic_cmd_cons_idx_attr { - struct mgmt_msg_head msg_head; - - u16 func_idx; - u8 dma_attr_off; - u8 pending_limit; - u8 coalescing_time; - u8 intr_en; - u16 intr_idx; - u32 l2nic_sqn; - u32 rsvd; - u64 ci_addr; -}; - -struct spnic_cmd_vlan_offload { - struct mgmt_msg_head msg_head; - - u16 func_id; - u8 vlan_offload; - u8 rsvd1[5]; -}; - -struct spnic_cmd_lro_config { - struct mgmt_msg_head msg_head; - - u16 func_id; - u8 opcode; - u8 rsvd1; - u8 lro_ipv4_en; - u8 lro_ipv6_en; - u8 lro_max_pkt_len; /* unit is 1K */ - u8 resv2[13]; -}; - -struct spnic_cmd_lro_timer { - struct mgmt_msg_head msg_head; - - u8 opcode; /* 1: set timer value, 0: get timer value */ - u8 rsvd1; - u16 rsvd2; - u32 timer; -}; - -struct spnic_cmd_vf_vlan_config { - struct mgmt_msg_head msg_head; - - u16 func_id; - u8 opcode; - u8 rsvd1; - u16 vlan_id; - u8 qos; - u8 rsvd2[5]; -}; - -struct spnic_cmd_spoofchk_set { - struct mgmt_msg_head msg_head; - - u16 func_id; - u8 state; - u8 rsvd1; -}; - -struct spnic_cmd_tx_rate_cfg { - struct mgmt_msg_head msg_head; - - u16 func_id; - u16 rsvd1; - u32 min_rate; - u32 max_rate; - u8 rsvd2[8]; -}; - -struct spnic_cmd_port_info { - struct mgmt_msg_head msg_head; - - u8 port_id; - u8 rsvd1[3]; - u8 port_type; - u8 autoneg_cap; - u8 autoneg_state; - u8 duplex; - u8 speed; - u8 fec; - u16 rsvd2; - u32 rsvd3[4]; -}; - -struct spnic_cmd_register_vf { - struct mgmt_msg_head msg_head; - - u8 op_register; /* 0 - unregister, 1 - register */ - u8 rsvd[39]; -}; - -struct spnic_cmd_link_state { - struct mgmt_msg_head msg_head; - - u8 port_id; - u8 state; - u16 rsvd1; -}; - -struct spnic_cmd_vlan_config { - struct mgmt_msg_head msg_head; - - u16 func_id; - u8 opcode; - u8 rsvd1; - u16 vlan_id; - u16 rsvd2; -}; - -/* set vlan filter */ -struct spnic_cmd_set_vlan_filter { - struct mgmt_msg_head msg_head; - - u16 func_id; - u8 resvd[2]; - u32 vlan_filter_ctrl; /* bit0:vlan filter en; bit1:broadcast_filter_en */ -}; - -struct spnic_cmd_link_ksettings_info { - struct mgmt_msg_head msg_head; - - u8 port_id; - u8 rsvd1[3]; - - u32 valid_bitmap; - u8 speed; /* enum nic_speed_level */ - u8 autoneg; /* 0 - off, 1 - on */ - u8 fec; /* 0 - RSFEC, 1 - BASEFEC, 2 - NOFEC */ - u8 rsvd2[21]; /* reserved for duplex, port, etc. */ -}; - -struct mpu_lt_info { - u8 node; - u8 inst; - u8 entry_size; - u8 rsvd; - u32 lt_index; - u32 offset; - u32 len; -}; - -struct nic_mpu_lt_opera { - struct mgmt_msg_head msg_head; - struct mpu_lt_info net_lt_cmd; - u8 data[100]; -}; - -struct spnic_rx_mode_config { - struct mgmt_msg_head msg_head; - - u16 func_id; - u16 rsvd1; - u32 rx_mode; -}; - -/* rss */ -struct spnic_rss_context_table { - struct mgmt_msg_head msg_head; - - u16 func_id; - u16 rsvd1; - u32 context; -}; - -struct spnic_cmd_rss_engine_type { - struct mgmt_msg_head msg_head; - - u16 func_id; - u8 opcode; - u8 hash_engine; - u8 rsvd1[4]; -}; - -#define SPNIC_RSS_INDIR_SIZE 256 -#define SPNIC_RSS_KEY_SIZE 40 - -struct spnic_cmd_rss_hash_key { - struct mgmt_msg_head msg_head; - - u16 func_id; - u8 opcode; - u8 rsvd1; - u8 key[SPNIC_RSS_KEY_SIZE]; -}; - -struct spnic_rss_indir_table { - struct mgmt_msg_head msg_head; - - u16 func_id; - u16 rsvd1; - u8 indir[SPNIC_RSS_INDIR_SIZE]; -}; - -#define SPNIC_DCB_UP_MAX 0x8 -#define SPNIC_DCB_COS_MAX 0x8 -#define SPNIC_DCB_TC_MAX 0x8 - -struct spnic_cmd_rss_config { - struct mgmt_msg_head msg_head; - - u16 func_id; - u8 rss_en; - u8 rq_priority_number; - u8 prio_tc[SPNIC_DCB_COS_MAX]; - u16 num_qps; - u16 rsvd1; -}; - -struct spnic_dcb_state { - u8 dcb_on; - u8 default_cos; - u16 rsvd1; - u8 up_cos[SPNIC_DCB_UP_MAX]; - u32 rsvd2[7]; -}; - -struct spnic_cmd_vf_dcb_state { - struct mgmt_msg_head msg_head; - - struct spnic_dcb_state state; -}; - -struct spnic_up_ets_cfg { - struct mgmt_msg_head msg_head; - - u8 port_id; - u8 rsvd1[3]; - - u8 cos_tc[SPNIC_DCB_COS_MAX]; - u8 tc_bw[SPNIC_DCB_TC_MAX]; - u8 cos_prio[SPNIC_DCB_COS_MAX]; - u8 cos_bw[SPNIC_DCB_COS_MAX]; - u8 tc_prio[SPNIC_DCB_TC_MAX]; -}; - -struct spnic_cmd_set_pfc { - struct mgmt_msg_head msg_head; - - u8 port_id; - u8 rsvd1; - u8 pfc_en; - u8 pfc_bitmap; - u8 rsvd2[4]; -}; - -struct spnic_cos_up_map { - struct mgmt_msg_head msg_head; - - u8 port_id; - /* every bit indicate index of map is valid 1 or not 0*/ - u8 cos_valid_mask; - u16 rsvd1; - - /* user priority in cos(index:cos, value: up pri) */ - u8 map[SPNIC_DCB_UP_MAX]; -}; - -struct spnic_cmd_pause_config { - struct mgmt_msg_head msg_head; - - u8 port_id; - u8 opcode; - u16 rsvd1; - u8 auto_neg; - u8 rx_pause; - u8 tx_pause; - u8 rsvd2[5]; -}; - -struct nic_cmd_tx_pause_notice { - struct mgmt_msg_head head; - - u32 tx_pause_except; - u32 except_level; - u32 rsvd; -}; - -#define SPNIC_CMD_OP_FREE 0 -#define SPNIC_CMD_OP_ALLOC 1 - -struct spnic_cmd_cfg_qps { - struct mgmt_msg_head msg_head; - - u16 func_id; - u8 opcode; /* 1: alloc qp, 0: free qp */ - u8 rsvd1; - u16 num_qps; - u16 rsvd2; -}; - -struct spnic_cmd_led_config { - struct mgmt_msg_head msg_head; - - u8 port; - u8 type; - u8 mode; - u8 rsvd1; -}; - -struct spnic_cmd_port_loopback { - struct mgmt_msg_head msg_head; - - u8 port_id; - u8 opcode; - u8 mode; - u8 en; - u32 rsvd1[2]; -}; - -struct spnic_cmd_get_light_module_abs { - struct mgmt_msg_head msg_head; - - u8 port_id; - u8 abs_status; /* 0:present, 1:absent */ - u8 rsv[2]; -}; - -#define STD_SFP_INFO_MAX_SIZE 640 -struct spnic_cmd_get_std_sfp_info { - struct mgmt_msg_head msg_head; - - u8 port_id; - u8 wire_type; - u16 eeprom_len; - u32 rsvd; - u8 sfp_info[STD_SFP_INFO_MAX_SIZE]; -}; - -struct spnic_cable_plug_event { - struct mgmt_msg_head msg_head; - - u16 func_id; - u8 plugged; /* 0: unplugged, 1: plugged */ - u8 port_id; -}; - -struct nic_cmd_mac_info { - struct mgmt_msg_head head; - - u32 valid_bitmap; - u16 rsvd; - - u8 host_id[32]; - u8 port_id[32]; - u8 mac_addr[192]; -}; - -#define SPNIC_TCAM_BLOCK_ENABLE 1 -#define SPNIC_TCAM_BLOCK_DISABLE 0 -#define SPNIC_TCAM_BLOCK_NORMAL_TYPE 0 -#define SPNIC_MAX_TCAM_RULES_NUM 4096 - -struct nic_cmd_set_tcam_enable { - struct mgmt_msg_head head; - - u16 func_id; - u8 tcam_enable; - u8 rsvd1; - u32 rsvd2; -}; - -/* alloc tcam block input struct */ -struct nic_cmd_ctrl_tcam_block_in { - struct mgmt_msg_head head; - - u16 func_id; /* func_id */ - u8 alloc_en; /* 0: free tcam block, 1: alloc tcam block */ - u8 tcam_type; /* 0: alloc 16 size tcam block, 1: alloc 0 size tcam block */ - u16 tcam_block_index; - u16 alloc_block_num; -}; - -/* alloc tcam block output struct */ -struct nic_cmd_ctrl_tcam_block_out { - struct mgmt_msg_head head; - - u16 func_id; - u8 alloc_en; - u8 tcam_type; - u16 tcam_block_index; - u16 mpu_alloc_block_size; -}; - -struct nic_cmd_flush_tcam_rules { - struct mgmt_msg_head head; - - u16 func_id; /* func_id */ - u16 rsvd; -}; - -struct nic_cmd_dfx_fdir_tcam_block_table { - struct mgmt_msg_head head; - u8 tcam_type; - u8 valid; - u16 tcam_block_index; - u16 use_function_id; - u16 rsvd; -}; - -struct tcam_result { - u32 qid; - u32 rsvd; -}; - -#define TCAM_FLOW_KEY_SIZE 44 - -struct tcam_key_x_y { - u8 x[TCAM_FLOW_KEY_SIZE]; - u8 y[TCAM_FLOW_KEY_SIZE]; -}; - -struct nic_tcam_cfg_rule { - u32 index; - struct tcam_result data; - struct tcam_key_x_y key; -}; - -struct nic_cmd_fdir_add_rule { - struct mgmt_msg_head head; - - u16 func_id; - u16 rsvd; - struct nic_tcam_cfg_rule rule; -}; - -struct nic_cmd_fdir_del_rules { - struct mgmt_msg_head head; - - u16 func_id; - u16 rsvd; - u32 index_start; - u32 index_num; -}; - -struct nic_cmd_fdir_get_rule { - struct mgmt_msg_head head; - - u32 index; - u32 valid; - struct tcam_key_x_y key; - struct tcam_result data; - u64 packet_count; - u64 byte_count; -}; - -#endif /* SPNIC_MGMT_INTERFACE_H */ diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_netdev_ops.c b/drivers/net/ethernet/ramaxel/spnic/spnic_netdev_ops.c deleted file mode 100644 index a4f668682f37..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_netdev_ops.c +++ /dev/null @@ -1,1526 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [NIC]" fmt -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/device.h> -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/etherdevice.h> -#include <linux/netdevice.h> -#include <linux/netlink.h> -#include <linux/debugfs.h> -#include <linux/ip.h> -#include <linux/bpf.h> - -#include "sphw_hw.h" -#include "sphw_crm.h" -#include "spnic_nic_io.h" -#include "spnic_nic_dev.h" -#include "spnic_tx.h" -#include "spnic_rx.h" -#include "spnic_dcb.h" - -#define SPNIC_DEFAULT_RX_CSUM_OFFLOAD 0xFFF - -#define SPNIC_LRO_DEFAULT_COAL_PKT_SIZE 32 -#define SPNIC_LRO_DEFAULT_TIME_LIMIT 16 -#define SPNIC_WAIT_FLUSH_QP_RESOURCE_TIMEOUT 2000 -static void spnic_nic_set_rx_mode(struct net_device *netdev) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - - if (netdev_uc_count(netdev) != nic_dev->netdev_uc_cnt || - netdev_mc_count(netdev) != nic_dev->netdev_mc_cnt) { - set_bit(SPNIC_UPDATE_MAC_FILTER, &nic_dev->flags); - nic_dev->netdev_uc_cnt = netdev_uc_count(netdev); - nic_dev->netdev_mc_cnt = netdev_mc_count(netdev); - } - - queue_work(nic_dev->workq, &nic_dev->rx_mode_work); -} - -int spnic_alloc_txrxq_resources(struct spnic_nic_dev *nic_dev, - struct spnic_dyna_txrxq_params *q_params) -{ - u32 size; - int err; - - size = sizeof(*q_params->txqs_res) * q_params->num_qps; - q_params->txqs_res = kzalloc(size, GFP_KERNEL); - if (!q_params->txqs_res) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to alloc txqs resources array\n"); - return -ENOMEM; - } - - size = sizeof(*q_params->rxqs_res) * q_params->num_qps; - q_params->rxqs_res = kzalloc(size, GFP_KERNEL); - if (!q_params->rxqs_res) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to alloc rxqs resource array\n"); - err = -ENOMEM; - goto alloc_rxqs_res_arr_err; - } - - size = sizeof(*q_params->irq_cfg) * q_params->num_qps; - q_params->irq_cfg = kzalloc(size, GFP_KERNEL); - if (!q_params->irq_cfg) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to alloc irq resource array\n"); - err = -ENOMEM; - goto alloc_irq_cfg_err; - } - - err = spnic_alloc_txqs_res(nic_dev, q_params->num_qps, - q_params->sq_depth, q_params->txqs_res); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Failed to alloc txqs resource\n"); - goto alloc_txqs_res_err; - } - - err = spnic_alloc_rxqs_res(nic_dev, q_params->num_qps, - q_params->rq_depth, q_params->rxqs_res); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to alloc rxqs resource\n"); - goto alloc_rxqs_res_err; - } - - return 0; - -alloc_rxqs_res_err: - spnic_free_txqs_res(nic_dev, q_params->num_qps, q_params->sq_depth, - q_params->txqs_res); - -alloc_txqs_res_err: - kfree(q_params->irq_cfg); - q_params->irq_cfg = NULL; - -alloc_irq_cfg_err: - kfree(q_params->rxqs_res); - q_params->rxqs_res = NULL; - -alloc_rxqs_res_arr_err: - kfree(q_params->txqs_res); - q_params->txqs_res = NULL; - - return err; -} - -void spnic_free_txrxq_resources(struct spnic_nic_dev *nic_dev, - struct spnic_dyna_txrxq_params *q_params) -{ - spnic_free_rxqs_res(nic_dev, q_params->num_qps, q_params->rq_depth, q_params->rxqs_res); - spnic_free_txqs_res(nic_dev, q_params->num_qps, q_params->sq_depth, q_params->txqs_res); - - kfree(q_params->irq_cfg); - q_params->irq_cfg = NULL; - - kfree(q_params->rxqs_res); - q_params->rxqs_res = NULL; - - kfree(q_params->txqs_res); - q_params->txqs_res = NULL; -} - -int spnic_configure_txrxqs(struct spnic_nic_dev *nic_dev, - struct spnic_dyna_txrxq_params *q_params) -{ - int err; - - err = spnic_configure_txqs(nic_dev, q_params->num_qps, - q_params->sq_depth, q_params->txqs_res); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Failed to configure txqs\n"); - return err; - } - - err = spnic_configure_rxqs(nic_dev, q_params->num_qps, - q_params->rq_depth, q_params->rxqs_res); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to configure rxqs\n"); - return err; - } - - return 0; -} - -static void config_dcb_qps_map(struct spnic_nic_dev *nic_dev) -{ - struct net_device *netdev = nic_dev->netdev; - u8 i, num_tcs; - u16 num_rss; - - if (!test_bit(SPNIC_DCB_ENABLE, &nic_dev->flags)) { - spnic_update_tx_db_cos(nic_dev); - return; - } - - num_tcs = (u8)netdev_get_num_tc(netdev); - /* For now, we don't support to change num_tcs */ - if (num_tcs != nic_dev->hw_dcb_cfg.max_cos || - nic_dev->q_params.num_qps < num_tcs || - !test_bit(SPNIC_RSS_ENABLE, &nic_dev->flags)) { - nicif_err(nic_dev, drv, netdev, "Invalid num_tcs: %u or num_qps: %u, disable DCB\n", - num_tcs, nic_dev->q_params.num_qps); - netdev_reset_tc(netdev); - nic_dev->q_params.num_tc = 0; - clear_bit(SPNIC_DCB_ENABLE, &nic_dev->flags); - /* if we can't enable rss or get enough num_qps, - * need to sync default configure to hw - */ - spnic_configure_dcb(netdev); - } else { - /* use 0~max_cos-1 as tc for netdev */ - num_rss = nic_dev->q_params.num_rss; - for (i = 0; i < num_tcs; i++) - netdev_set_tc_queue(netdev, i, num_rss, (u16)(num_rss * i)); - } - - spnic_update_tx_db_cos(nic_dev); -} - -static int spnic_configure(struct spnic_nic_dev *nic_dev) -{ - struct net_device *netdev = nic_dev->netdev; - int err; - - err = spnic_set_port_mtu(nic_dev->hwdev, (u16)netdev->mtu); - if (err) { - nicif_err(nic_dev, drv, netdev, "Failed to set mtu\n"); - return err; - } - - config_dcb_qps_map(nic_dev); - - /* rx rss init */ - err = spnic_rx_configure(netdev); - if (err) { - nicif_err(nic_dev, drv, netdev, "Failed to configure rx\n"); - return err; - } - - return 0; -} - -static void spnic_remove_configure(struct spnic_nic_dev *nic_dev) -{ - spnic_rx_remove_configure(nic_dev->netdev); -} - -/* try to modify the number of irq to the target number, - * and return the actual number of irq. - */ -static u16 spnic_qp_irq_change(struct spnic_nic_dev *nic_dev, u16 dst_num_qp_irq) -{ - struct irq_info *qps_irq_info = nic_dev->qps_irq_info; - u16 resp_irq_num, irq_num_gap, i; - u16 idx; - int err; - - if (dst_num_qp_irq > nic_dev->num_qp_irq) { - irq_num_gap = dst_num_qp_irq - nic_dev->num_qp_irq; - err = sphw_alloc_irqs(nic_dev->hwdev, SERVICE_T_NIC, irq_num_gap, - &qps_irq_info[nic_dev->num_qp_irq], &resp_irq_num); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to alloc irqs\n"); - return nic_dev->num_qp_irq; - } - - nic_dev->num_qp_irq += resp_irq_num; - } else if (dst_num_qp_irq < nic_dev->num_qp_irq) { - irq_num_gap = nic_dev->num_qp_irq - dst_num_qp_irq; - for (i = 0; i < irq_num_gap; i++) { - idx = (nic_dev->num_qp_irq - i) - 1; - sphw_free_irq(nic_dev->hwdev, SERVICE_T_NIC, qps_irq_info[idx].irq_id); - qps_irq_info[idx].irq_id = 0; - qps_irq_info[idx].msix_entry_idx = 0; - } - nic_dev->num_qp_irq = dst_num_qp_irq; - } - - return nic_dev->num_qp_irq; -} - -static void config_dcb_num_qps(struct spnic_nic_dev *nic_dev, - struct spnic_dyna_txrxq_params *q_params, - u16 max_qps) -{ - u8 num_tcs = q_params->num_tc; - u16 num_rss; - - if (!num_tcs || !test_bit(SPNIC_RSS_ENABLE, &nic_dev->flags)) - return; - - if (num_tcs == nic_dev->hw_dcb_cfg.max_cos && max_qps >= num_tcs) { - num_rss = max_qps / num_tcs; - num_rss = min_t(u16, num_rss, q_params->rss_limit); - q_params->num_rss = num_rss; - q_params->num_qps = (u16)(num_tcs * num_rss); - } /* else will disable DCB in config_dcb_qps_map() */ -} - -static void spnic_config_num_qps(struct spnic_nic_dev *nic_dev, - struct spnic_dyna_txrxq_params *q_params) -{ - u16 alloc_num_irq, cur_num_irq; - u16 dst_num_irq; - - if (test_bit(SPNIC_RSS_ENABLE, &nic_dev->flags)) { - q_params->num_rss = q_params->rss_limit; - q_params->num_qps = q_params->rss_limit; - } else { - q_params->num_rss = 0; - q_params->num_qps = 1; - } - - config_dcb_num_qps(nic_dev, q_params, nic_dev->max_qps); - - if (nic_dev->num_qp_irq >= q_params->num_qps) - goto out; - - cur_num_irq = nic_dev->num_qp_irq; - - alloc_num_irq = spnic_qp_irq_change(nic_dev, q_params->num_qps); - if (alloc_num_irq < q_params->num_qps) { - q_params->num_qps = alloc_num_irq; - q_params->num_rss = q_params->num_qps; - config_dcb_num_qps(nic_dev, q_params, q_params->num_qps); - nicif_warn(nic_dev, drv, nic_dev->netdev, - "Can not get enough irqs, adjust num_qps to %u\n", - q_params->num_qps); - - /* The current irq may be in use, we must keep it */ - dst_num_irq = max_t(u16, cur_num_irq, q_params->num_qps); - spnic_qp_irq_change(nic_dev, dst_num_irq); - } - -out: - nicif_info(nic_dev, drv, nic_dev->netdev, "Finally num_qps: %u, num_rss: %u\n", - q_params->num_qps, q_params->num_rss); -} - -/* determin num_qps from rss_tmpl_id/irq_num/dcb_en */ -int spnic_setup_num_qps(struct spnic_nic_dev *nic_dev) -{ - struct net_device *netdev = nic_dev->netdev; - u32 irq_size; - - nic_dev->num_qp_irq = 0; - - irq_size = sizeof(*nic_dev->qps_irq_info) * nic_dev->max_qps; - if (!irq_size) { - nicif_err(nic_dev, drv, netdev, "Cannot allocate zero size entries\n"); - return -EINVAL; - } - nic_dev->qps_irq_info = kzalloc(irq_size, GFP_KERNEL); - if (!nic_dev->qps_irq_info) { - nicif_err(nic_dev, drv, netdev, "Failed to alloc qps_irq_info\n"); - return -ENOMEM; - } - - spnic_config_num_qps(nic_dev, &nic_dev->q_params); - - return 0; -} - -static void spnic_destroy_num_qps(struct spnic_nic_dev *nic_dev) -{ - u16 i; - - for (i = 0; i < nic_dev->num_qp_irq; i++) - sphw_free_irq(nic_dev->hwdev, SERVICE_T_NIC, nic_dev->qps_irq_info[i].irq_id); - - kfree(nic_dev->qps_irq_info); -} - -int spnic_force_port_disable(struct spnic_nic_dev *nic_dev) -{ - int err; - - down(&nic_dev->port_state_sem); - - err = spnic_set_port_enable(nic_dev->hwdev, false, SPHW_CHANNEL_NIC); - if (!err) - nic_dev->force_port_disable = true; - - up(&nic_dev->port_state_sem); - - return err; -} - -int spnic_force_set_port_state(struct spnic_nic_dev *nic_dev, bool enable) -{ - int err = 0; - - down(&nic_dev->port_state_sem); - - nic_dev->force_port_disable = false; - err = spnic_set_port_enable(nic_dev->hwdev, enable, SPHW_CHANNEL_NIC); - - up(&nic_dev->port_state_sem); - - return err; -} - -int spnic_maybe_set_port_state(struct spnic_nic_dev *nic_dev, bool enable) -{ - int err; - - down(&nic_dev->port_state_sem); - - /* Do nothing when force disable - * Port will disable when call force port disable - * and should not enable port when in force mode - */ - if (nic_dev->force_port_disable) { - up(&nic_dev->port_state_sem); - return 0; - } - - err = spnic_set_port_enable(nic_dev->hwdev, enable, SPHW_CHANNEL_NIC); - - up(&nic_dev->port_state_sem); - - return err; -} - -static void spnic_print_link_message(struct spnic_nic_dev *nic_dev, u8 link_status) -{ - if (nic_dev->link_status == link_status) - return; - - nic_dev->link_status = link_status; - - nicif_info(nic_dev, link, nic_dev->netdev, "Link is %s\n", - (link_status ? "up" : "down")); -} - -int spnic_alloc_channel_resources(struct spnic_nic_dev *nic_dev, - struct spnic_dyna_qp_params *qp_params, - struct spnic_dyna_txrxq_params *trxq_params) -{ - int err; - - qp_params->num_qps = trxq_params->num_qps; - qp_params->sq_depth = trxq_params->sq_depth; - qp_params->rq_depth = trxq_params->rq_depth; - - err = spnic_alloc_qps(nic_dev->hwdev, nic_dev->qps_irq_info, qp_params); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to alloc qps\n"); - return err; - } - - err = spnic_alloc_txrxq_resources(nic_dev, trxq_params); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to alloc txrxq resources\n"); - spnic_free_qps(nic_dev->hwdev, qp_params); - return err; - } - - return 0; -} - -void spnic_free_channel_resources(struct spnic_nic_dev *nic_dev, - struct spnic_dyna_qp_params *qp_params, - struct spnic_dyna_txrxq_params *trxq_params) -{ - mutex_lock(&nic_dev->nic_mutex); - spnic_free_txrxq_resources(nic_dev, trxq_params); - spnic_free_qps(nic_dev->hwdev, qp_params); - mutex_unlock(&nic_dev->nic_mutex); -} - -int spnic_open_channel(struct spnic_nic_dev *nic_dev, struct spnic_dyna_qp_params *qp_params, - struct spnic_dyna_txrxq_params *trxq_params) -{ - int err; - - err = spnic_init_qps(nic_dev->hwdev, qp_params); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to init qps\n"); - return err; - } - - err = spnic_configure_txrxqs(nic_dev, trxq_params); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to configure txrxqs\n"); - goto cfg_txrxqs_err; - } - - err = spnic_qps_irq_init(nic_dev); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to init txrxq irq\n"); - goto init_qp_irq_err; - } - - err = spnic_configure(nic_dev); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to init txrxq irq\n"); - goto configure_err; - } - - return 0; - -configure_err: - spnic_qps_irq_deinit(nic_dev); - -init_qp_irq_err: -cfg_txrxqs_err: - spnic_deinit_qps(nic_dev->hwdev, qp_params); - - return err; -} - -void spnic_close_channel(struct spnic_nic_dev *nic_dev, - struct spnic_dyna_qp_params *qp_params) -{ - spnic_remove_configure(nic_dev); - spnic_qps_irq_deinit(nic_dev); - spnic_deinit_qps(nic_dev->hwdev, qp_params); -} - -int spnic_vport_up(struct spnic_nic_dev *nic_dev) -{ - struct net_device *netdev = nic_dev->netdev; - u8 link_status = 0; - u16 glb_func_id; - int err; - - glb_func_id = sphw_global_func_id(nic_dev->hwdev); - err = spnic_set_vport_enable(nic_dev->hwdev, glb_func_id, true, - SPHW_CHANNEL_NIC); - if (err) { - nicif_err(nic_dev, drv, netdev, "Failed to enable vport\n"); - goto vport_enable_err; - } - - err = spnic_maybe_set_port_state(nic_dev, true); - if (err) { - nicif_err(nic_dev, drv, netdev, "Failed to enable port\n"); - goto port_enable_err; - } - - netif_set_real_num_tx_queues(netdev, nic_dev->q_params.num_qps); - netif_set_real_num_rx_queues(netdev, nic_dev->q_params.num_qps); - netif_tx_wake_all_queues(netdev); - - err = spnic_get_link_state(nic_dev->hwdev, &link_status); - if (!err && link_status) - netif_carrier_on(netdev); - - queue_delayed_work(nic_dev->workq, &nic_dev->moderation_task, SPNIC_MODERATONE_DELAY); - - spnic_print_link_message(nic_dev, link_status); - - if (!SPNIC_FUNC_IS_VF(nic_dev->hwdev)) - spnic_notify_all_vfs_link_changed(nic_dev->hwdev, link_status); - - return 0; - -port_enable_err: - spnic_set_vport_enable(nic_dev->hwdev, glb_func_id, false, SPHW_CHANNEL_NIC); - -vport_enable_err: - spnic_flush_qps_res(nic_dev->hwdev); - /* After set vport disable 100ms, no packets will be send to host */ - msleep(100); - - return err; -} - -void spnic_vport_down(struct spnic_nic_dev *nic_dev) -{ - u16 glb_func_id; - - netif_carrier_off(nic_dev->netdev); - netif_tx_disable(nic_dev->netdev); - - cancel_delayed_work_sync(&nic_dev->moderation_task); - - if (sphw_get_chip_present_flag(nic_dev->hwdev)) { - if (!SPNIC_FUNC_IS_VF(nic_dev->hwdev)) - spnic_notify_all_vfs_link_changed(nic_dev->hwdev, 0); - - spnic_maybe_set_port_state(nic_dev, false); - - glb_func_id = sphw_global_func_id(nic_dev->hwdev); - spnic_set_vport_enable(nic_dev->hwdev, glb_func_id, false, SPHW_CHANNEL_NIC); - - spnic_flush_txqs(nic_dev->netdev); - spnic_flush_qps_res(nic_dev->hwdev); - /* After set vport disable 100ms, - * no packets will be send to host - * FPGA set 2000ms - */ - msleep(SPNIC_WAIT_FLUSH_QP_RESOURCE_TIMEOUT); - } -} - -int spnic_change_channel_settings(struct spnic_nic_dev *nic_dev, - struct spnic_dyna_txrxq_params *trxq_params, - spnic_reopen_handler reopen_handler, const void *priv_data) -{ - struct spnic_dyna_qp_params new_qp_params = {0}; - struct spnic_dyna_qp_params cur_qp_params = {0}; - int err; - - spnic_config_num_qps(nic_dev, trxq_params); - - err = spnic_alloc_channel_resources(nic_dev, &new_qp_params, trxq_params); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Failed to alloc channel resources\n"); - return err; - } - - if (!test_and_set_bit(SPNIC_CHANGE_RES_INVALID, &nic_dev->flags)) { - spnic_vport_down(nic_dev); - spnic_close_channel(nic_dev, &cur_qp_params); - spnic_free_channel_resources(nic_dev, &cur_qp_params, &nic_dev->q_params); - } - - if (nic_dev->num_qp_irq > trxq_params->num_qps) - spnic_qp_irq_change(nic_dev, trxq_params->num_qps); - nic_dev->q_params = *trxq_params; - - if (reopen_handler) - reopen_handler(nic_dev, priv_data); - - err = spnic_open_channel(nic_dev, &new_qp_params, trxq_params); - if (err) - goto open_channel_err; - - err = spnic_vport_up(nic_dev); - if (err) - goto vport_up_err; - - clear_bit(SPNIC_CHANGE_RES_INVALID, &nic_dev->flags); - nicif_info(nic_dev, drv, nic_dev->netdev, "Change channel settings success\n"); - - return 0; - -vport_up_err: - spnic_close_channel(nic_dev, &new_qp_params); - -open_channel_err: - spnic_free_channel_resources(nic_dev, &new_qp_params, trxq_params); - - return err; -} - -int spnic_open(struct net_device *netdev) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - struct spnic_dyna_qp_params qp_params = {0}; - int err; - - if (test_bit(SPNIC_INTF_UP, &nic_dev->flags)) { - nicif_info(nic_dev, drv, netdev, "Netdev already open, do nothing\n"); - return 0; - } - - err = spnic_init_nicio_res(nic_dev->hwdev); - if (err) { - nicif_err(nic_dev, drv, netdev, "Failed to init nicio resources\n"); - return err; - } - - err = spnic_setup_num_qps(nic_dev); - if (err) { - nicif_err(nic_dev, drv, netdev, "Failed to setup num_qps\n"); - goto setup_qps_err; - } - - err = spnic_alloc_channel_resources(nic_dev, &qp_params, &nic_dev->q_params); - if (err) - goto alloc_channel_res_err; - - err = spnic_open_channel(nic_dev, &qp_params, &nic_dev->q_params); - if (err) - goto open_channel_err; - - err = spnic_vport_up(nic_dev); - if (err) - goto vport_up_err; - - set_bit(SPNIC_INTF_UP, &nic_dev->flags); - nicif_info(nic_dev, drv, nic_dev->netdev, "Netdev is up\n"); - - return 0; - -vport_up_err: - spnic_close_channel(nic_dev, &qp_params); - -open_channel_err: - spnic_free_channel_resources(nic_dev, &qp_params, &nic_dev->q_params); - -alloc_channel_res_err: - spnic_destroy_num_qps(nic_dev); - -setup_qps_err: - spnic_deinit_nicio_res(nic_dev->hwdev); - - return err; -} - -int spnic_close(struct net_device *netdev) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - struct spnic_dyna_qp_params qp_params = {0}; - - if (!test_and_clear_bit(SPNIC_INTF_UP, &nic_dev->flags)) { - nicif_info(nic_dev, drv, netdev, "Netdev already close, do nothing\n"); - return 0; - } - - if (test_and_clear_bit(SPNIC_CHANGE_RES_INVALID, &nic_dev->flags)) - goto out; - - spnic_vport_down(nic_dev); - spnic_close_channel(nic_dev, &qp_params); - spnic_free_channel_resources(nic_dev, &qp_params, &nic_dev->q_params); - -out: - spnic_deinit_nicio_res(nic_dev->hwdev); - spnic_destroy_num_qps(nic_dev); - - nicif_info(nic_dev, drv, nic_dev->netdev, "Netdev is down\n"); - - return 0; -} - -#define IPV6_ADDR_LEN 4 -#define PKT_INFO_LEN 9 -#define BITS_PER_TUPLE 32 -static u32 calc_xor_rss(u8 *rss_tunple, u32 len) -{ - u32 hash_value; - u32 i; - - hash_value = rss_tunple[0]; - for (i = 1; i < len; i++) - hash_value = hash_value ^ rss_tunple[i]; - - return hash_value; -} - -static u32 calc_toep_rss(u32 *rss_tunple, u32 len, const u32 *rss_key) -{ - u32 rss = 0; - u32 i, j; - - for (i = 1; i <= len; i++) { - for (j = 0; j < BITS_PER_TUPLE; j++) - if (rss_tunple[i - 1] & ((u32)1 << - (u32)((BITS_PER_TUPLE - 1) - j))) - rss ^= (rss_key[i - 1] << j) | - (u32)((u64)rss_key[i] >> (BITS_PER_TUPLE - j)); - } - - return rss; -} - -#define RSS_VAL(val, type) \ - (((type) == SPNIC_RSS_HASH_ENGINE_TYPE_TOEP) ? ntohl(val) : (val)) - -static u8 parse_ipv6_info(struct sk_buff *skb, u32 *rss_tunple, u8 hash_engine, u32 *len) -{ - struct ipv6hdr *ipv6hdr = ipv6_hdr(skb); - u32 *saddr = (u32 *)&ipv6hdr->saddr; - u32 *daddr = (u32 *)&ipv6hdr->daddr; - u8 i; - - for (i = 0; i < IPV6_ADDR_LEN; i++) { - rss_tunple[i] = RSS_VAL(daddr[i], hash_engine); - /* The offset of the sport relative to the dport is 4 */ - rss_tunple[(u32)(i + IPV6_ADDR_LEN)] = RSS_VAL(saddr[i], hash_engine); - } - *len = IPV6_ADDR_LEN + IPV6_ADDR_LEN; - - if (skb_network_header(skb) + sizeof(*ipv6hdr) == skb_transport_header(skb)) - return ipv6hdr->nexthdr; - return 0; -} - -u16 select_queue_by_hash_func(struct net_device *dev, struct sk_buff *skb, - unsigned int num_tx_queues) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(dev); - struct nic_rss_type rss_type = nic_dev->rss_type; - struct iphdr *iphdr = NULL; - u32 rss_tunple[PKT_INFO_LEN] = {0}; - u32 len = 0; - u32 hash = 0; - u8 hash_engine = nic_dev->rss_hash_engine; - u8 l4_proto; - unsigned char *l4_hdr = NULL; - - if (skb_rx_queue_recorded(skb)) { - hash = skb_get_rx_queue(skb); - - if (unlikely(hash >= num_tx_queues)) - hash %= num_tx_queues; - return (u16)hash; - } - - iphdr = ip_hdr(skb); - if (iphdr->version == IPV4_VERSION) { - rss_tunple[len++] = RSS_VAL(iphdr->daddr, hash_engine); - rss_tunple[len++] = RSS_VAL(iphdr->saddr, hash_engine); - l4_proto = iphdr->protocol; - } else if (iphdr->version == IPV6_VERSION) { - l4_proto = parse_ipv6_info(skb, (u32 *)rss_tunple, hash_engine, &len); - } else { - return (u16)hash; - } - - if ((iphdr->version == IPV4_VERSION && - ((l4_proto == IPPROTO_UDP && rss_type.udp_ipv4) || - (l4_proto == IPPROTO_TCP && rss_type.tcp_ipv4))) || - (iphdr->version == IPV6_VERSION && - ((l4_proto == IPPROTO_UDP && rss_type.udp_ipv6) || - (l4_proto == IPPROTO_TCP && rss_type.tcp_ipv6)))) { - l4_hdr = skb_transport_header(skb); - /* High 16 bits are dport, low 16 bits are sport. */ - rss_tunple[len++] = ((u32)ntohs(*((u16 *)l4_hdr + 1U)) << 16) | - ntohs(*(u16 *)l4_hdr); - } /* rss_type.ipv4 and rss_type.ipv6 default on. */ - - if (hash_engine == SPNIC_RSS_HASH_ENGINE_TYPE_TOEP) - hash = calc_toep_rss((u32 *)rss_tunple, len, nic_dev->rss_hkey_be); - else - hash = calc_xor_rss((u8 *)rss_tunple, len * (u32)sizeof(u32)); - - return (u16)nic_dev->rss_indir[hash & 0xFF]; -} - -static u16 spnic_select_queue(struct net_device *netdev, struct sk_buff *skb, - struct net_device *sb_dev) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - - if (skb->vlan_tci) - skb->priority = skb->vlan_tci >> VLAN_PRIO_SHIFT; - - if (netdev_get_num_tc(netdev)) - goto fall_back; - - if (test_bit(SPNIC_SAME_RXTX, &nic_dev->flags)) - return select_queue_by_hash_func(netdev, skb, netdev->real_num_tx_queues); - -fall_back: - return netdev_pick_tx(netdev, skb, NULL); -} - -static void spnic_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats) - -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - struct spnic_txq_stats *txq_stats = NULL; - struct spnic_rxq_stats *rxq_stats = NULL; - struct spnic_txq *txq = NULL; - struct spnic_rxq *rxq = NULL; - u64 bytes, packets, dropped, errors; - unsigned int start; - int i; - - bytes = 0; - packets = 0; - dropped = 0; - for (i = 0; i < nic_dev->max_qps; i++) { - if (!nic_dev->txqs) - break; - - txq = &nic_dev->txqs[i]; - txq_stats = &txq->txq_stats; - do { - start = u64_stats_fetch_begin(&txq_stats->syncp); - bytes += txq_stats->bytes; - packets += txq_stats->packets; - dropped += txq_stats->dropped; - } while (u64_stats_fetch_retry(&txq_stats->syncp, start)); - } - stats->tx_packets = packets; - stats->tx_bytes = bytes; - stats->tx_dropped = dropped; - - bytes = 0; - packets = 0; - errors = 0; - dropped = 0; - for (i = 0; i < nic_dev->max_qps; i++) { - if (!nic_dev->rxqs) - break; - - rxq = &nic_dev->rxqs[i]; - rxq_stats = &rxq->rxq_stats; - do { - start = u64_stats_fetch_begin(&rxq_stats->syncp); - bytes += rxq_stats->bytes; - packets += rxq_stats->packets; - errors += rxq_stats->csum_errors + rxq_stats->other_errors; - dropped += rxq_stats->dropped; - } while (u64_stats_fetch_retry(&rxq_stats->syncp, start)); - } - stats->rx_packets = packets; - stats->rx_bytes = bytes; - stats->rx_errors = errors; - stats->rx_dropped = dropped; -} - -static void spnic_tx_timeout(struct net_device *netdev, unsigned int txqueue) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - struct spnic_io_queue *sq = NULL; - bool hw_err = false; - u32 sw_pi, hw_ci; - u8 q_id; - - SPNIC_NIC_STATS_INC(nic_dev, netdev_tx_timeout); - nicif_err(nic_dev, drv, netdev, "Tx timeout\n"); - - for (q_id = 0; q_id < nic_dev->q_params.num_qps; q_id++) { - if (!netif_xmit_stopped(netdev_get_tx_queue(netdev, q_id))) - continue; - - sq = nic_dev->txqs[q_id].sq; - sw_pi = spnic_get_sq_local_pi(sq); - hw_ci = spnic_get_sq_hw_ci(sq); - nicif_info(nic_dev, drv, netdev, "txq%u: sw_pi: %hu, hw_ci: %u, sw_ci: %u, napi->state: 0x%lx\n", - q_id, sw_pi, hw_ci, spnic_get_sq_local_ci(sq), - nic_dev->q_params.irq_cfg[q_id].napi.state); - - if (sw_pi != hw_ci) - hw_err = true; - } - - if (hw_err) - set_bit(EVENT_WORK_TX_TIMEOUT, &nic_dev->event_flag); -} - -static int spnic_change_mtu(struct net_device *netdev, int new_mtu) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - u32 mtu = (u32)new_mtu; - int err = 0; - - u32 xdp_max_mtu; - - if (spnic_is_xdp_enable(nic_dev)) { - xdp_max_mtu = spnic_xdp_max_mtu(nic_dev); - if (mtu > xdp_max_mtu) { - nicif_err(nic_dev, drv, netdev, "Max MTU for xdp usage is %d\n", - xdp_max_mtu); - return -EINVAL; - } - } - - err = spnic_set_port_mtu(nic_dev->hwdev, (u16)mtu); - if (err) { - nicif_err(nic_dev, drv, netdev, "Failed to change port mtu to %d\n", - new_mtu); - } else { - nicif_info(nic_dev, drv, nic_dev->netdev, "Change mtu from %u to %d\n", - netdev->mtu, new_mtu); - netdev->mtu = mtu; - } - - return err; -} - -static int spnic_set_mac_addr(struct net_device *netdev, void *addr) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - struct sockaddr *saddr = addr; - int err; - - if (!is_valid_ether_addr(saddr->sa_data)) - return -EADDRNOTAVAIL; - - if (ether_addr_equal(netdev->dev_addr, saddr->sa_data)) { - nicif_info(nic_dev, drv, netdev, "Already using mac address %pM\n", - saddr->sa_data); - return 0; - } - - err = spnic_update_mac(nic_dev->hwdev, netdev->dev_addr, saddr->sa_data, 0, - sphw_global_func_id(nic_dev->hwdev)); - if (err) - return err; - - ether_addr_copy(netdev->dev_addr, saddr->sa_data); - - nicif_info(nic_dev, drv, netdev, "Set new mac address %pM\n", saddr->sa_data); - - return 0; -} - -static int spnic_vlan_rx_add_vid(struct net_device *netdev, __always_unused __be16 proto, u16 vid) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - unsigned long *vlan_bitmap = nic_dev->vlan_bitmap; - u16 func_id; - u32 col, line; - int err = 0; - - /* VLAN 0 donot be added, which is the same as VLAN 0 deleted. */ - if (vid == 0) - goto end; - - col = VID_COL(nic_dev, vid); - line = VID_LINE(nic_dev, vid); - - func_id = sphw_global_func_id(nic_dev->hwdev); - - err = spnic_add_vlan(nic_dev->hwdev, vid, func_id); - if (err) { - nicif_err(nic_dev, drv, netdev, "Failed to add vlan %u\n", vid); - goto end; - } - - set_bit(col, &vlan_bitmap[line]); - - nicif_info(nic_dev, drv, netdev, "Add vlan %u\n", vid); - -end: - return err; -} - -static int spnic_vlan_rx_kill_vid(struct net_device *netdev, __always_unused __be16 proto, u16 vid) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - unsigned long *vlan_bitmap = nic_dev->vlan_bitmap; - u16 func_id; - int col, line; - int err = 0; - - col = VID_COL(nic_dev, vid); - line = VID_LINE(nic_dev, vid); - - /* In the broadcast scenario, ucode finds the corresponding function - * based on VLAN 0 of vlan table. If we delete VLAN 0, the VLAN function - * is affected. - */ - if (vid == 0) - goto end; - - func_id = sphw_global_func_id(nic_dev->hwdev); - err = spnic_del_vlan(nic_dev->hwdev, vid, func_id); - if (err) { - nicif_err(nic_dev, drv, netdev, "Failed to delete vlan\n"); - goto end; - } - - clear_bit(col, &vlan_bitmap[line]); - - nicif_info(nic_dev, drv, netdev, "Remove vlan %u\n", vid); - -end: - return err; -} - -#define SET_FEATURES_OP_STR(op) ((op) ? "Enable" : "Disable") - -static int set_feature_rx_csum(struct spnic_nic_dev *nic_dev, netdev_features_t wanted_features, - netdev_features_t features, netdev_features_t *failed_features) -{ - netdev_features_t changed = wanted_features ^ features; - - if (changed & NETIF_F_RXCSUM) - spnic_info(nic_dev, drv, "%s rx csum success\n", - SET_FEATURES_OP_STR(wanted_features & NETIF_F_RXCSUM)); - - return 0; -} - -static int set_feature_tso(struct spnic_nic_dev *nic_dev, netdev_features_t wanted_features, - netdev_features_t features, netdev_features_t *failed_features) -{ - netdev_features_t changed = wanted_features ^ features; - - if (changed & NETIF_F_TSO) - spnic_info(nic_dev, drv, "%s tso success\n", - SET_FEATURES_OP_STR(wanted_features & NETIF_F_TSO)); - - return 0; -} - -static int set_feature_lro(struct spnic_nic_dev *nic_dev, netdev_features_t wanted_features, - netdev_features_t features, netdev_features_t *failed_features) -{ - netdev_features_t changed = wanted_features ^ features; - bool en = !!(wanted_features & NETIF_F_LRO); - int err; - - if (!(changed & NETIF_F_LRO)) - return 0; - - if (en && spnic_is_xdp_enable(nic_dev)) { - spnic_err(nic_dev, drv, "Can not enable LRO when xdp is enable\n"); - *failed_features |= NETIF_F_LRO; - return -EINVAL; - } - - err = spnic_set_rx_lro_state(nic_dev->hwdev, en, SPNIC_LRO_DEFAULT_TIME_LIMIT, - SPNIC_LRO_DEFAULT_COAL_PKT_SIZE); - if (err) { - spnic_err(nic_dev, drv, "%s lro failed\n", SET_FEATURES_OP_STR(en)); - *failed_features |= NETIF_F_LRO; - } else { - spnic_info(nic_dev, drv, "%s lro success\n", SET_FEATURES_OP_STR(en)); - } - - return err; -} - -static int set_feature_rx_cvlan(struct spnic_nic_dev *nic_dev, netdev_features_t wanted_features, - netdev_features_t features, netdev_features_t *failed_features) -{ - netdev_features_t changed = wanted_features ^ features; - netdev_features_t vlan_feature = NETIF_F_HW_VLAN_CTAG_RX; - bool en = !!(wanted_features & vlan_feature); - int err; - - if (!(changed & vlan_feature)) - return 0; - - err = spnic_set_rx_vlan_offload(nic_dev->hwdev, en); - if (err) { - spnic_err(nic_dev, drv, "%s rxvlan failed\n", SET_FEATURES_OP_STR(en)); - *failed_features |= vlan_feature; - } else { - spnic_info(nic_dev, drv, "%s rxvlan success\n", SET_FEATURES_OP_STR(en)); - } - - return err; -} - -static int set_feature_vlan_filter(struct spnic_nic_dev *nic_dev, netdev_features_t wanted_features, - netdev_features_t features, netdev_features_t *failed_features) -{ - netdev_features_t changed = wanted_features ^ features; - netdev_features_t vlan_filter_feature = NETIF_F_HW_VLAN_CTAG_FILTER; - bool en = !!(wanted_features & vlan_filter_feature); - int err = 0; - - if (!(changed & vlan_filter_feature)) - return 0; - - if (err == 0) - err = spnic_set_vlan_fliter(nic_dev->hwdev, en); - if (err) { - spnic_err(nic_dev, drv, "%s rx vlan filter failed\n", SET_FEATURES_OP_STR(en)); - *failed_features |= vlan_filter_feature; - } else { - spnic_info(nic_dev, drv, "%s rx vlan filter success\n", SET_FEATURES_OP_STR(en)); - } - - return err; -} - -static int set_features(struct spnic_nic_dev *nic_dev, netdev_features_t pre_features, - netdev_features_t features) -{ - netdev_features_t failed_features = 0; - u32 err = 0; - - err |= (u32)set_feature_rx_csum(nic_dev, features, pre_features, &failed_features); - err |= (u32)set_feature_tso(nic_dev, features, pre_features, &failed_features); - err |= (u32)set_feature_lro(nic_dev, features, pre_features, &failed_features); - err |= (u32)set_feature_rx_cvlan(nic_dev, features, pre_features, &failed_features); - err |= (u32)set_feature_vlan_filter(nic_dev, features, pre_features, &failed_features); - if (err) { - nic_dev->netdev->features = features ^ failed_features; - return -EIO; - } - - return 0; -} - -static int spnic_set_features(struct net_device *netdev, netdev_features_t features) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - - return set_features(nic_dev, nic_dev->netdev->features, features); -} - -int spnic_set_hw_features(struct spnic_nic_dev *nic_dev) -{ - /* enable all hw features in netdev->features */ - return set_features(nic_dev, ~nic_dev->netdev->features, nic_dev->netdev->features); -} - -static netdev_features_t spnic_fix_features(struct net_device *netdev, netdev_features_t features) -{ - /* If Rx checksum is disabled, then LRO should also be disabled */ - if (!(features & NETIF_F_RXCSUM)) - features &= ~NETIF_F_LRO; - - return features; -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -static void spnic_netpoll(struct net_device *netdev) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - u16 i; - - for (i = 0; i < nic_dev->q_params.num_qps; i++) - napi_schedule(&nic_dev->q_params.irq_cfg[i].napi); -} -#endif /* CONFIG_NET_POLL_CONTROLLER */ - -static int spnic_ndo_set_vf_mac(struct net_device *netdev, int vf, u8 *mac) -{ - struct spnic_nic_dev *adapter = netdev_priv(netdev); - int err; - - if (is_multicast_ether_addr(mac) || vf >= pci_num_vf(adapter->pdev)) - return -EINVAL; - - err = spnic_set_vf_mac(adapter->hwdev, OS_VF_ID_TO_HW(vf), mac); - if (err) - return err; - - if (!is_zero_ether_addr(mac)) - nic_info(&adapter->pdev->dev, "Setting MAC %pM on VF %d\n", mac, vf); - else - nic_info(&adapter->pdev->dev, "Deleting MAC on VF %d\n", vf); - - nic_info(&adapter->pdev->dev, "Please reload the VF driver to make this change effective."); - - return 0; -} - -static int set_hw_vf_vlan(void *hwdev, u16 cur_vlanprio, int vf, u16 vlan, u8 qos) -{ - int err = 0; - u16 old_vlan = cur_vlanprio & VLAN_VID_MASK; - - if (vlan || qos) { - if (cur_vlanprio) { - err = spnic_kill_vf_vlan(hwdev, OS_VF_ID_TO_HW(vf)); - if (err) - return err; - } - err = spnic_add_vf_vlan(hwdev, OS_VF_ID_TO_HW(vf), vlan, qos); - } else { - err = spnic_kill_vf_vlan(hwdev, OS_VF_ID_TO_HW(vf)); - } - - if (err) - return err; - - return spnic_update_mac_vlan(hwdev, old_vlan, vlan, OS_VF_ID_TO_HW(vf)); -} - -#define SPNIC_MAX_VLAN_ID 4094 -#define SPNIC_MAX_QOS_NUM 7 - -static int spnic_ndo_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, - u8 qos, __be16 vlan_proto) -{ - struct spnic_nic_dev *adapter = netdev_priv(netdev); - u16 vlanprio, cur_vlanprio; - - if (vf >= pci_num_vf(adapter->pdev) || vlan > SPNIC_MAX_VLAN_ID || qos > SPNIC_MAX_QOS_NUM) - return -EINVAL; - if (vlan_proto != htons(ETH_P_8021Q)) - return -EPROTONOSUPPORT; - vlanprio = vlan | qos << SPNIC_VLAN_PRIORITY_SHIFT; - cur_vlanprio = spnic_vf_info_vlanprio(adapter->hwdev, OS_VF_ID_TO_HW(vf)); - /* duplicate request, so just return success */ - if (vlanprio == cur_vlanprio) - return 0; - - return set_hw_vf_vlan(adapter->hwdev, cur_vlanprio, vf, vlan, qos); -} - -static int spnic_ndo_set_vf_spoofchk(struct net_device *netdev, int vf, bool setting) -{ - struct spnic_nic_dev *adapter = netdev_priv(netdev); - int err = 0; - bool cur_spoofchk = false; - - if (vf >= pci_num_vf(adapter->pdev)) - return -EINVAL; - - cur_spoofchk = spnic_vf_info_spoofchk(adapter->hwdev, OS_VF_ID_TO_HW(vf)); - /* same request, so just return success */ - if ((setting && cur_spoofchk) || (!setting && !cur_spoofchk)) - return 0; - - err = spnic_set_vf_spoofchk(adapter->hwdev, OS_VF_ID_TO_HW(vf), setting); - if (!err) - nicif_info(adapter, drv, netdev, "Set VF %d spoofchk %s\n", - vf, setting ? "on" : "off"); - - return err; -} - -int spnic_ndo_set_vf_trust(struct net_device *netdev, int vf, bool setting) -{ - struct spnic_nic_dev *adapter = netdev_priv(netdev); - int err; - bool cur_trust; - - if (vf >= pci_num_vf(adapter->pdev)) - return -EINVAL; - - cur_trust = spnic_get_vf_trust(adapter->hwdev, OS_VF_ID_TO_HW(vf)); - /* same request, so just return success */ - if ((setting && cur_trust) || (!setting && !cur_trust)) - return 0; - - err = spnic_set_vf_trust(adapter->hwdev, OS_VF_ID_TO_HW(vf), setting); - if (!err) - nicif_info(adapter, drv, netdev, "Set VF %d trusted %s successfully\n", - vf, setting ? "on" : "off"); - else - nicif_err(adapter, drv, netdev, "Failed set VF %d trusted %s\n", - vf, setting ? "on" : "off"); - - return err; -} - -static int spnic_ndo_get_vf_config(struct net_device *netdev, int vf, struct ifla_vf_info *ivi) -{ - struct spnic_nic_dev *adapter = netdev_priv(netdev); - - if (vf >= pci_num_vf(adapter->pdev)) - return -EINVAL; - - spnic_get_vf_config(adapter->hwdev, OS_VF_ID_TO_HW(vf), ivi); - - return 0; -} - -/** - * spnic_ndo_set_vf_link_state - * @netdev: network interface device structure - * @vf_id: VF identifier - * @link: required link state - * - * Set the link state of a specified VF, regardless of physical link state - **/ -int spnic_ndo_set_vf_link_state(struct net_device *netdev, int vf_id, int link) -{ - static const char * const vf_link[] = {"auto", "enable", "disable"}; - struct spnic_nic_dev *adapter = netdev_priv(netdev); - int err; - - /* validate the request */ - if (vf_id >= pci_num_vf(adapter->pdev)) { - nicif_err(adapter, drv, netdev, "Invalid VF Identifier %d\n", vf_id); - return -EINVAL; - } - - err = spnic_set_vf_link_state(adapter->hwdev, OS_VF_ID_TO_HW(vf_id), link); - if (!err) - nicif_info(adapter, drv, netdev, "Set VF %d link state: %s\n", - vf_id, vf_link[link]); - - return err; -} - -static int is_set_vf_bw_param_valid(const struct spnic_nic_dev *adapter, - int vf, int min_tx_rate, int max_tx_rate) -{ - /* verify VF is active */ - if (vf >= pci_num_vf(adapter->pdev)) { - nicif_err(adapter, drv, adapter->netdev, "VF number must be less than %d\n", - pci_num_vf(adapter->pdev)); - return -EINVAL; - } - - if (max_tx_rate < min_tx_rate) { - nicif_err(adapter, drv, adapter->netdev, "Invalid rate, max rate %d must greater than min rate %d\n", - max_tx_rate, min_tx_rate); - return -EINVAL; - } - - return 0; -} - -#define SPNIC_TX_RATE_TABLE_FULL 12 - -static int spnic_ndo_set_vf_bw(struct net_device *netdev, int vf, int min_tx_rate, int max_tx_rate) -{ - struct spnic_nic_dev *adapter = netdev_priv(netdev); - struct nic_port_info port_info = {0}; - u8 link_status = 0; - u32 speeds[] = {0, SPEED_10, SPEED_100, SPEED_1000, SPEED_10000, - SPEED_25000, SPEED_40000, SPEED_50000, SPEED_100000, - SPEED_200000}; - int err = 0; - - err = is_set_vf_bw_param_valid(adapter, vf, min_tx_rate, max_tx_rate); - if (err) - return err; - - err = spnic_get_link_state(adapter->hwdev, &link_status); - if (err) { - nicif_err(adapter, drv, netdev, "Get link status failed when set vf tx rate\n"); - return -EIO; - } - - if (!link_status) { - nicif_err(adapter, drv, netdev, "Link status must be up when set vf tx rate\n"); - return -EINVAL; - } - - err = spnic_get_port_info(adapter->hwdev, &port_info, SPHW_CHANNEL_NIC); - if (err || port_info.speed >= PORT_SPEED_UNKNOWN) - return -EIO; - - /* rate limit cannot be less than 0 and greater than link speed */ - if (max_tx_rate < 0 || max_tx_rate > speeds[port_info.speed]) { - nicif_err(adapter, drv, netdev, "Set vf max tx rate must be in [0 - %u]\n", - speeds[port_info.speed]); - return -EINVAL; - } - - err = spnic_set_vf_tx_rate(adapter->hwdev, OS_VF_ID_TO_HW(vf), max_tx_rate, min_tx_rate); - if (err) { - nicif_err(adapter, drv, netdev, "Unable to set VF %d max rate %d min rate %d%s\n", - vf, max_tx_rate, min_tx_rate, - err == SPNIC_TX_RATE_TABLE_FULL ? ", tx rate profile is full" : ""); - return -EIO; - } - - nicif_info(adapter, drv, netdev, "Set VF %d max tx rate %d min tx rate %d successfully\n", - vf, max_tx_rate, min_tx_rate); - - return 0; -} - -bool spnic_is_xdp_enable(struct spnic_nic_dev *nic_dev) -{ - return !!nic_dev->xdp_prog; -} - -int spnic_xdp_max_mtu(struct spnic_nic_dev *nic_dev) -{ - return nic_dev->rx_buff_len - (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN); -} - -static int spnic_xdp_setup(struct spnic_nic_dev *nic_dev, struct bpf_prog *prog, - struct netlink_ext_ack *extack) -{ - struct bpf_prog *old_prog = NULL; - int max_mtu = spnic_xdp_max_mtu(nic_dev); - int q_id; - - if (nic_dev->netdev->mtu > max_mtu) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Failed to setup xdp program, the current MTU %d is larger than max allowed MTU %d\n", - nic_dev->netdev->mtu, max_mtu); - NL_SET_ERR_MSG_MOD(extack, "MTU too large for loading xdp program"); - return -EINVAL; - } - - if (nic_dev->netdev->features & NETIF_F_LRO) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to setup xdp program while LRO is on\n"); - NL_SET_ERR_MSG_MOD(extack, "Failed to setup xdp program while LRO is on\n"); - return -EINVAL; - } - - old_prog = xchg(&nic_dev->xdp_prog, prog); - for (q_id = 0; q_id < nic_dev->max_qps; q_id++) - xchg(&nic_dev->rxqs[q_id].xdp_prog, nic_dev->xdp_prog); - - if (old_prog) - bpf_prog_put(old_prog); - - return 0; -} - -static int spnic_xdp(struct net_device *netdev, struct netdev_bpf *xdp) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - - switch (xdp->command) { - case XDP_SETUP_PROG: - return spnic_xdp_setup(nic_dev, xdp->prog, xdp->extack); - default: - return -EINVAL; - } -} - -static const struct net_device_ops spnic_netdev_ops = { - .ndo_open = spnic_open, - .ndo_stop = spnic_close, - .ndo_start_xmit = spnic_xmit_frame, - - .ndo_get_stats64 = spnic_get_stats64, - - .ndo_tx_timeout = spnic_tx_timeout, - .ndo_select_queue = spnic_select_queue, - .ndo_change_mtu = spnic_change_mtu, - .ndo_set_mac_address = spnic_set_mac_addr, - .ndo_validate_addr = eth_validate_addr, - - .ndo_vlan_rx_add_vid = spnic_vlan_rx_add_vid, - .ndo_vlan_rx_kill_vid = spnic_vlan_rx_kill_vid, - - .ndo_set_vf_mac = spnic_ndo_set_vf_mac, - .ndo_set_vf_vlan = spnic_ndo_set_vf_vlan, - .ndo_set_vf_rate = spnic_ndo_set_vf_bw, - .ndo_set_vf_spoofchk = spnic_ndo_set_vf_spoofchk, - - .ndo_set_vf_trust = spnic_ndo_set_vf_trust, - - .ndo_get_vf_config = spnic_ndo_get_vf_config, - -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = spnic_netpoll, -#endif /* CONFIG_NET_POLL_CONTROLLER */ - - .ndo_set_rx_mode = spnic_nic_set_rx_mode, - - .ndo_bpf = spnic_xdp, - - .ndo_set_vf_link_state = spnic_ndo_set_vf_link_state, - - .ndo_fix_features = spnic_fix_features, - .ndo_set_features = spnic_set_features, -}; - -static const struct net_device_ops spnicvf_netdev_ops = { - .ndo_open = spnic_open, - .ndo_stop = spnic_close, - .ndo_start_xmit = spnic_xmit_frame, - - .ndo_get_stats64 = spnic_get_stats64, - - .ndo_tx_timeout = spnic_tx_timeout, - .ndo_select_queue = spnic_select_queue, - - .ndo_change_mtu = spnic_change_mtu, - .ndo_set_mac_address = spnic_set_mac_addr, - .ndo_validate_addr = eth_validate_addr, - - .ndo_vlan_rx_add_vid = spnic_vlan_rx_add_vid, - .ndo_vlan_rx_kill_vid = spnic_vlan_rx_kill_vid, - -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = spnic_netpoll, -#endif /* CONFIG_NET_POLL_CONTROLLER */ - - .ndo_set_rx_mode = spnic_nic_set_rx_mode, - - .ndo_bpf = spnic_xdp, - - .ndo_fix_features = spnic_fix_features, - .ndo_set_features = spnic_set_features, -}; - -void spnic_set_netdev_ops(struct spnic_nic_dev *nic_dev) -{ - if (!SPNIC_FUNC_IS_VF(nic_dev->hwdev)) - nic_dev->netdev->netdev_ops = &spnic_netdev_ops; - else - nic_dev->netdev->netdev_ops = &spnicvf_netdev_ops; -} diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_nic.h b/drivers/net/ethernet/ramaxel/spnic/spnic_nic.h deleted file mode 100644 index 83c904bc0f72..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_nic.h +++ /dev/null @@ -1,148 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPNIC_NIC_H -#define SPNIC_NIC_H -#include <linux/types.h> -#include "sphw_common.h" -#include "spnic_nic_io.h" -#include "spnic_nic_cfg.h" -#include "spnic_mag_cmd.h" - -#define MSG_TO_MGMT_SYNC_RETURN_ERR(err, status, out_size) \ - ((err) || (status) || !(out_size)) - -struct spnic_sq_attr { - u8 dma_attr_off; - u8 pending_limit; - u8 coalescing_time; - u8 intr_en; - u16 intr_idx; - u32 l2nic_sqn; - u64 ci_dma_base; -}; - -struct vf_data_storage { - u8 drv_mac_addr[ETH_ALEN]; - u8 user_mac_addr[ETH_ALEN]; - bool registered; - bool use_specified_mac; - u16 pf_vlan; - u8 pf_qos; - u32 max_rate; - u32 min_rate; - - bool link_forced; - bool link_up; /* only valid if VF link is forced */ - bool spoofchk; - bool trust; - u16 num_qps; -}; - -struct spnic_port_routine_cmd { - bool mpu_send_sfp_info; - bool mpu_send_sfp_abs; - - struct mag_cmd_get_xsfp_info std_sfp_info; - struct mag_cmd_get_xsfp_present abs; -}; - -struct spnic_nic_cfg { - void *hwdev; - void *pcidev_hdl; - void *dev_hdl; - - struct spnic_io_queue *sq; - struct spnic_io_queue *rq; - - u16 rx_buff_len; - - u16 num_qps; - u16 max_qps; - - void *ci_vaddr_base; - dma_addr_t ci_dma_base; - - /* including rq and rx doorbell */ - u16 allocated_num_db; - u8 __iomem **db_addr; - - u8 link_status; - - u16 max_vfs; - struct vf_data_storage *vf_infos; - struct spnic_dcb_state dcb_state; - - u64 feature_cap; - - struct semaphore cfg_lock; - - /* Valid when pfc is disable */ - bool pause_set; - struct nic_pause_config nic_pause; - - u8 pfc_en; - u8 pfc_bitmap; - - struct nic_port_info port_info; - - /* percentage of pf link bandwidth */ - u32 pf_bw_limit; - - struct spnic_port_routine_cmd rt_cmd; - /* mutex used for copy sfp info */ - struct mutex sfp_mutex; -}; - -struct vf_msg_handler { - u16 cmd; - int (*handler)(struct spnic_nic_cfg *nic_cfg, u16 vf, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size); -}; - -struct nic_event_handler { - u16 cmd; - void (*handler)(void *hwdev, void *buf_in, u16 in_size, void *buf_out, u16 *out_size); -}; - -int spnic_set_ci_table(void *hwdev, struct spnic_sq_attr *attr); - -int l2nic_msg_to_mgmt_sync(void *hwdev, u16 cmd, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size); - -int l2nic_msg_to_mgmt_sync_ch(void *hwdev, u16 cmd, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size, u16 channel); - -int spnic_cfg_vf_vlan(struct spnic_nic_cfg *nic_cfg, u8 opcode, u16 vid, u8 qos, int vf_id); - -int spnic_vf_event_handler(void *hwdev, void *pri_handle, u16 cmd, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size); - -void spnic_pf_event_handler(void *hwdev, void *pri_handle, u16 cmd, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size); - -int spnic_pf_mbox_handler(void *hwdev, void *pri_handle, u16 vf_id, u16 cmd, void *buf_in, - u16 in_size, void *buf_out, u16 *out_size); - -u8 spnic_nic_sw_aeqe_handler(void *hwdev, u8 event, u8 *data); - -int spnic_vf_func_init(struct spnic_nic_cfg *nic_cfg); - -void spnic_vf_func_free(struct spnic_nic_cfg *nic_cfg); - -void spnic_notify_dcb_state_event(struct spnic_nic_cfg *nic_cfg, struct spnic_dcb_state *dcb_state); - -int spnic_save_dcb_state(struct spnic_nic_cfg *nic_cfg, struct spnic_dcb_state *dcb_state); - -void spnic_notify_vf_link_status(struct spnic_nic_cfg *nic_cfg, u16 vf_id, u8 link_status); - -int spnic_vf_mag_event_handler(void *hwdev, void *pri_handle, u16 cmd, - void *buf_in, u16 in_size, void *buf_out, u16 *out_size); - -void spnic_pf_mag_event_handler(void *hwdev, void *pri_handle, u16 cmd, - void *buf_in, u16 in_size, void *buf_out, u16 *out_size); - -int spnic_pf_mag_mbox_handler(void *hwdev, void *pri_handle, u16 vf_id, - u16 cmd, void *buf_in, u16 in_size, void *buf_out, u16 *out_size); - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_nic_cfg.c b/drivers/net/ethernet/ramaxel/spnic/spnic_nic_cfg.c deleted file mode 100644 index d241f6a7947d..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_nic_cfg.c +++ /dev/null @@ -1,1334 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [NIC]" fmt - -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/etherdevice.h> -#include <linux/if_vlan.h> -#include <linux/ethtool.h> -#include <linux/kernel.h> -#include <linux/device.h> -#include <linux/pci.h> -#include <linux/netdevice.h> -#include <linux/module.h> - -#include "sphw_crm.h" -#include "sphw_hw.h" -#include "spnic_nic_io.h" -#include "spnic_nic_cfg.h" -#include "spnic_nic.h" -#include "spnic_nic_cmd.h" -#include "sphw_common.h" - -int spnic_set_ci_table(void *hwdev, struct spnic_sq_attr *attr) -{ - struct spnic_cmd_cons_idx_attr cons_idx_attr; - u16 out_size = sizeof(cons_idx_attr); - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - if (!hwdev || !attr) - return -EINVAL; - - memset(&cons_idx_attr, 0, sizeof(cons_idx_attr)); - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - cons_idx_attr.func_idx = sphw_global_func_id(hwdev); - - cons_idx_attr.dma_attr_off = attr->dma_attr_off; - cons_idx_attr.pending_limit = attr->pending_limit; - cons_idx_attr.coalescing_time = attr->coalescing_time; - - if (attr->intr_en) { - cons_idx_attr.intr_en = attr->intr_en; - cons_idx_attr.intr_idx = attr->intr_idx; - } - - cons_idx_attr.l2nic_sqn = attr->l2nic_sqn; - cons_idx_attr.ci_addr = attr->ci_dma_base; - - err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_NIC_CMD_SQ_CI_ATTR_SET, - &cons_idx_attr, sizeof(cons_idx_attr), - &cons_idx_attr, &out_size); - if (err || !out_size || cons_idx_attr.msg_head.status) { - sdk_err(nic_cfg->dev_hdl, - "Failed to set ci attribute table, err: %d, status: 0x%x, out_size: 0x%x\n", - err, cons_idx_attr.msg_head.status, out_size); - return -EFAULT; - } - - return 0; -} - -static int spnic_check_mac_info(u8 status, u16 vlan_id) -{ - if (status && status != SPNIC_MGMT_STATUS_EXIST && status != SPNIC_PF_SET_VF_ALREADY) - return -EINVAL; - - return 0; -} - -#define SPNIC_VLAN_ID_MASK 0x7FFF - -int spnic_set_mac(void *hwdev, const u8 *mac_addr, u16 vlan_id, u16 func_id, u16 channel) -{ - struct spnic_port_mac_set mac_info; - u16 out_size = sizeof(mac_info); - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - if (!hwdev || !mac_addr) - return -EINVAL; - - memset(&mac_info, 0, sizeof(mac_info)); - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - if ((vlan_id & SPNIC_VLAN_ID_MASK) >= VLAN_N_VID) { - nic_err(nic_cfg->dev_hdl, "Invalid VLAN number: %d\n", - vlan_id & SPNIC_VLAN_ID_MASK); - return -EINVAL; - } - - mac_info.func_id = func_id; - mac_info.vlan_id = vlan_id; - ether_addr_copy(mac_info.mac, mac_addr); - - err = l2nic_msg_to_mgmt_sync_ch(hwdev, SPNIC_NIC_CMD_SET_MAC, - &mac_info, sizeof(mac_info), - &mac_info, &out_size, channel); - if (err || !out_size || spnic_check_mac_info(mac_info.msg_head.status, mac_info.vlan_id)) { - nic_err(nic_cfg->dev_hdl, - "Failed to update MAC, err: %d, status: 0x%x, out size: 0x%x, channel: 0x%x\n", - err, mac_info.msg_head.status, out_size, channel); - return -EINVAL; - } - - if (mac_info.msg_head.status == SPNIC_PF_SET_VF_ALREADY) { - nic_warn(nic_cfg->dev_hdl, "PF has already set VF mac, Ignore set operation\n"); - return SPNIC_PF_SET_VF_ALREADY; - } - - if (mac_info.msg_head.status == SPNIC_MGMT_STATUS_EXIST) { - nic_warn(nic_cfg->dev_hdl, "MAC is repeated. Ignore update operation\n"); - return 0; - } - - return 0; -} - -int spnic_del_mac(void *hwdev, const u8 *mac_addr, u16 vlan_id, u16 func_id, u16 channel) -{ - struct spnic_port_mac_set mac_info; - u16 out_size = sizeof(mac_info); - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - if (!hwdev || !mac_addr) - return -EINVAL; - - memset(&mac_info, 0, sizeof(mac_info)); - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - if ((vlan_id & SPNIC_VLAN_ID_MASK) >= VLAN_N_VID) { - nic_err(nic_cfg->dev_hdl, "Invalid VLAN number: %d\n", - (vlan_id & SPNIC_VLAN_ID_MASK)); - return -EINVAL; - } - - mac_info.func_id = func_id; - mac_info.vlan_id = vlan_id; - ether_addr_copy(mac_info.mac, mac_addr); - - err = l2nic_msg_to_mgmt_sync_ch(hwdev, SPNIC_NIC_CMD_DEL_MAC, - &mac_info, sizeof(mac_info), &mac_info, - &out_size, channel); - if (err || !out_size || - (mac_info.msg_head.status && mac_info.msg_head.status != - SPNIC_PF_SET_VF_ALREADY)) { - nic_err(nic_cfg->dev_hdl, - "Failed to delete MAC, err: %d, status: 0x%x, out size: 0x%x, channel: 0x%x\n", - err, mac_info.msg_head.status, out_size, channel); - return -EINVAL; - } - - if (mac_info.msg_head.status == SPNIC_PF_SET_VF_ALREADY) { - nic_warn(nic_cfg->dev_hdl, "PF has already set VF mac, Ignore delete operation.\n"); - return SPNIC_PF_SET_VF_ALREADY; - } - - return 0; -} - -int spnic_update_mac(void *hwdev, u8 *old_mac, u8 *new_mac, u16 vlan_id, u16 func_id) -{ - struct spnic_port_mac_update mac_info; - u16 out_size = sizeof(mac_info); - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - if (!hwdev || !old_mac || !new_mac) - return -EINVAL; - - memset(&mac_info, 0, sizeof(mac_info)); - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - if ((vlan_id & SPNIC_VLAN_ID_MASK) >= VLAN_N_VID) { - nic_err(nic_cfg->dev_hdl, "Invalid VLAN number: %d\n", - vlan_id & SPNIC_VLAN_ID_MASK); - return -EINVAL; - } - - mac_info.func_id = func_id; - mac_info.vlan_id = vlan_id; - ether_addr_copy(mac_info.old_mac, old_mac); - ether_addr_copy(mac_info.new_mac, new_mac); - - err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_NIC_CMD_UPDATE_MAC, - &mac_info, sizeof(mac_info), - &mac_info, &out_size); - if (err || !out_size || spnic_check_mac_info(mac_info.msg_head.status, mac_info.vlan_id)) { - nic_err(nic_cfg->dev_hdl, - "Failed to update MAC, err: %d, status: 0x%x, out size: 0x%x\n", - err, mac_info.msg_head.status, out_size); - return -EINVAL; - } - - if (mac_info.msg_head.status == SPNIC_PF_SET_VF_ALREADY) { - nic_warn(nic_cfg->dev_hdl, "PF has already set VF MAC. Ignore update operation\n"); - return SPNIC_PF_SET_VF_ALREADY; - } - - if (mac_info.msg_head.status == SPNIC_MGMT_STATUS_EXIST) { - nic_warn(nic_cfg->dev_hdl, "MAC is repeated. Ignore update operation\n"); - return 0; - } - - return 0; -} - -int spnic_get_default_mac(void *hwdev, u8 *mac_addr) -{ - struct spnic_port_mac_set mac_info; - u16 out_size = sizeof(mac_info); - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - if (!hwdev || !mac_addr) - return -EINVAL; - - memset(&mac_info, 0, sizeof(mac_info)); - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - mac_info.func_id = sphw_global_func_id(hwdev); - - err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_NIC_CMD_GET_MAC, &mac_info, sizeof(mac_info), - &mac_info, &out_size); - if (err || !out_size || mac_info.msg_head.status) { - nic_err(nic_cfg->dev_hdl, - "Failed to get mac, err: %d, status: 0x%x, out size: 0x%x\n", - err, mac_info.msg_head.status, out_size); - return -EINVAL; - } - - ether_addr_copy(mac_addr, mac_info.mac); - - return 0; -} - -static int spnic_config_vlan(struct spnic_nic_cfg *nic_cfg, u8 opcode, u16 vlan_id, u16 func_id) -{ - struct spnic_cmd_vlan_config vlan_info; - u16 out_size = sizeof(vlan_info); - int err; - - memset(&vlan_info, 0, sizeof(vlan_info)); - vlan_info.opcode = opcode; - vlan_info.func_id = func_id; - vlan_info.vlan_id = vlan_id; - - err = l2nic_msg_to_mgmt_sync(nic_cfg->hwdev, SPNIC_NIC_CMD_CFG_FUNC_VLAN, - &vlan_info, sizeof(vlan_info), - &vlan_info, &out_size); - if (err || !out_size || vlan_info.msg_head.status) { - nic_err(nic_cfg->dev_hdl, - "Failed to %s vlan, err: %d, status: 0x%x, out size: 0x%x\n", - opcode == SPNIC_CMD_OP_ADD ? "add" : "delete", - err, vlan_info.msg_head.status, out_size); - return -EINVAL; - } - - return 0; -} - -int spnic_add_vlan(void *hwdev, u16 vlan_id, u16 func_id) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - - if (!hwdev) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - return spnic_config_vlan(nic_cfg, SPNIC_CMD_OP_ADD, vlan_id, func_id); -} - -int spnic_del_vlan(void *hwdev, u16 vlan_id, u16 func_id) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - - if (!hwdev) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - return spnic_config_vlan(nic_cfg, SPNIC_CMD_OP_DEL, vlan_id, func_id); -} - -int spnic_set_vport_enable(void *hwdev, u16 func_id, bool enable, u16 channel) -{ - struct spnic_vport_state en_state; - u16 out_size = sizeof(en_state); - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - if (!hwdev) - return -EINVAL; - - memset(&en_state, 0, sizeof(en_state)); - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - en_state.func_id = func_id; - en_state.state = enable ? 1 : 0; - - err = l2nic_msg_to_mgmt_sync_ch(hwdev, SPNIC_NIC_CMD_SET_VPORT_ENABLE, - &en_state, sizeof(en_state), - &en_state, &out_size, channel); - if (err || !out_size || en_state.msg_head.status) { - nic_err(nic_cfg->dev_hdl, "Failed to set vport state, err: %d, status: 0x%x, out size: 0x%x, channel: 0x%x\n", - err, en_state.msg_head.status, out_size, channel); - return -EINVAL; - } - - return 0; -} - -int spnic_set_dcb_state(void *hwdev, struct spnic_dcb_state *dcb_state) -{ - struct vf_data_storage *vf_infos = NULL; - struct spnic_cmd_vf_dcb_state vf_dcb; - struct spnic_nic_cfg *nic_cfg = NULL; - u16 vf_id, out_size = 0; - int err; - - if (!hwdev || !dcb_state) - return -EINVAL; - - memset(&vf_dcb, 0, sizeof(vf_dcb)); - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - if (!memcmp(&nic_cfg->dcb_state, dcb_state, sizeof(nic_cfg->dcb_state))) - return 0; - - memcpy(&vf_dcb.state, dcb_state, sizeof(vf_dcb.state)); - /* save in sdk, vf will get dcb state when probing */ - spnic_save_dcb_state(nic_cfg, dcb_state); - - /* notify statefull in pf, than notify all vf */ - spnic_notify_dcb_state_event(nic_cfg, dcb_state); - - /* not vf supported, don't need to notify vf */ - if (!nic_cfg->vf_infos) - return 0; - - vf_infos = nic_cfg->vf_infos; - for (vf_id = 0; vf_id < nic_cfg->max_vfs; vf_id++) { - if (vf_infos[vf_id].registered) { - vf_dcb.msg_head.status = 0; - out_size = sizeof(vf_dcb); - err = sphw_mbox_to_vf(hwdev, OS_VF_ID_TO_HW(vf_id), SPHW_MOD_L2NIC, - SPNIC_NIC_CMD_VF_COS, &vf_dcb, sizeof(vf_dcb), - &vf_dcb, &out_size, 0, SPHW_CHANNEL_NIC); - if (MSG_TO_MGMT_SYNC_RETURN_ERR(err, vf_dcb.msg_head.status, out_size)) - nic_err(nic_cfg->dev_hdl, - "Failed to notify dcb state to VF %u, err: %d, status: 0x%x, out size: 0x%x\n", - vf_id, err, vf_dcb.msg_head.status, out_size); - } - } - - return 0; -} - -int spnic_get_dcb_state(void *hwdev, struct spnic_dcb_state *dcb_state) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - - if (!hwdev || !dcb_state) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - memcpy(dcb_state, &nic_cfg->dcb_state, sizeof(*dcb_state)); - - return 0; -} - -int spnic_save_dcb_state(struct spnic_nic_cfg *nic_cfg, struct spnic_dcb_state *dcb_state) -{ - memcpy(&nic_cfg->dcb_state, dcb_state, sizeof(*dcb_state)); - - return 0; -} - -int spnic_get_pf_dcb_state(void *hwdev, struct spnic_dcb_state *dcb_state) -{ - struct spnic_cmd_vf_dcb_state vf_dcb; - struct spnic_nic_cfg *nic_cfg = NULL; - u16 out_size = sizeof(vf_dcb); - int err; - - if (!hwdev || !dcb_state) - return -EINVAL; - - memset(&vf_dcb, 0, sizeof(vf_dcb)); - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - if (sphw_func_type(hwdev) != TYPE_VF) { - nic_err(nic_cfg->dev_hdl, "Only vf need to get pf dcb state\n"); - return -EINVAL; - } - - err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_NIC_CMD_VF_COS, &vf_dcb, - sizeof(vf_dcb), &vf_dcb, &out_size); - if (err || !out_size || vf_dcb.msg_head.status) { - nic_err(nic_cfg->dev_hdl, "Failed to get vf default cos, err: %d, status: 0x%x, out size: 0x%x\n", - err, vf_dcb.msg_head.status, out_size); - return -EFAULT; - } - - memcpy(dcb_state, &vf_dcb.state, sizeof(*dcb_state)); - /* Save dcb_state in hw for statefull module */ - spnic_save_dcb_state(nic_cfg, dcb_state); - - return 0; -} - -static int spnic_cfg_hw_pause(struct spnic_nic_cfg *nic_cfg, u8 opcode, - struct nic_pause_config *nic_pause) -{ - struct spnic_cmd_pause_config pause_info; - u16 out_size = sizeof(pause_info); - int err; - - memset(&pause_info, 0, sizeof(pause_info)); - - pause_info.port_id = sphw_physical_port_id(nic_cfg->hwdev); - pause_info.opcode = opcode; - if (opcode == SPNIC_CMD_OP_SET) { - pause_info.auto_neg = nic_pause->auto_neg; - pause_info.rx_pause = nic_pause->rx_pause; - pause_info.tx_pause = nic_pause->tx_pause; - } - - err = l2nic_msg_to_mgmt_sync(nic_cfg->hwdev, SPNIC_NIC_CMD_CFG_PAUSE_INFO, - &pause_info, sizeof(pause_info), - &pause_info, &out_size); - if (err || !out_size || pause_info.msg_head.status) { - nic_err(nic_cfg->dev_hdl, "Failed to %s pause info, err: %d, status: 0x%x, out size: 0x%x\n", - opcode == SPNIC_CMD_OP_SET ? "set" : "get", - err, pause_info.msg_head.status, out_size); - return -EINVAL; - } - - if (opcode == SPNIC_CMD_OP_GET) { - nic_pause->auto_neg = pause_info.auto_neg; - nic_pause->rx_pause = pause_info.rx_pause; - nic_pause->tx_pause = pause_info.tx_pause; - } - - return 0; -} - -int spnic_set_pause_info(void *hwdev, struct nic_pause_config nic_pause) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - if (!hwdev) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - down(&nic_cfg->cfg_lock); - - err = spnic_cfg_hw_pause(nic_cfg, SPNIC_CMD_OP_SET, &nic_pause); - if (err) { - up(&nic_cfg->cfg_lock); - return err; - } - - nic_cfg->pfc_en = 0; - nic_cfg->pfc_bitmap = 0; - nic_cfg->pause_set = true; - nic_cfg->nic_pause.auto_neg = nic_pause.auto_neg; - nic_cfg->nic_pause.rx_pause = nic_pause.rx_pause; - nic_cfg->nic_pause.tx_pause = nic_pause.tx_pause; - - up(&nic_cfg->cfg_lock); - - return 0; -} - -int spnic_get_pause_info(void *hwdev, struct nic_pause_config *nic_pause) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - int err = 0; - - if (!hwdev || !nic_pause) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - err = spnic_cfg_hw_pause(nic_cfg, SPNIC_CMD_OP_GET, nic_pause); - if (err) - return err; - - if (nic_cfg->pause_set || !nic_pause->auto_neg) { - nic_pause->rx_pause = nic_cfg->nic_pause.rx_pause; - nic_pause->tx_pause = nic_cfg->nic_pause.tx_pause; - } - - return 0; -} - -static int spnic_dcb_set_hw_pfc(struct spnic_nic_cfg *nic_cfg, u8 pfc_en, u8 pfc_bitmap) -{ - struct spnic_cmd_set_pfc pfc; - u16 out_size = sizeof(pfc); - int err; - - memset(&pfc, 0, sizeof(pfc)); - - pfc.port_id = sphw_physical_port_id(nic_cfg->hwdev); - pfc.pfc_bitmap = pfc_bitmap; - pfc.pfc_en = pfc_en; - - err = l2nic_msg_to_mgmt_sync(nic_cfg->hwdev, SPNIC_NIC_CMD_SET_PFC, - &pfc, sizeof(pfc), &pfc, &out_size); - if (err || pfc.msg_head.status || !out_size) { - nic_err(nic_cfg->dev_hdl, "Failed to set pfc, err: %d, status: 0x%x, out size: 0x%x\n", - err, pfc.msg_head.status, out_size); - return -EINVAL; - } - - return 0; -} - -int spnic_dcb_set_pfc(void *hwdev, u8 pfc_en, u8 pfc_bitmap) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - down(&nic_cfg->cfg_lock); - - err = spnic_dcb_set_hw_pfc(nic_cfg, pfc_en, pfc_bitmap); - if (err) { - up(&nic_cfg->cfg_lock); - return err; - } - - nic_cfg->pfc_en = pfc_en; - nic_cfg->pfc_bitmap = pfc_bitmap; - - /* pause settings is opposite from pfc */ - nic_cfg->nic_pause.rx_pause = pfc_en ? 0 : 1; - nic_cfg->nic_pause.tx_pause = pfc_en ? 0 : 1; - - up(&nic_cfg->cfg_lock); - - return 0; -} - -int spnic_dcb_set_ets(void *hwdev, u8 *cos_tc, u8 *cos_bw, u8 *cos_prio, - u8 *tc_bw, u8 *tc_prio) -{ - struct spnic_up_ets_cfg ets; - struct spnic_nic_cfg *nic_cfg = NULL; - u16 out_size = sizeof(ets); - u16 cos_bw_t = 0; - u8 tc_bw_t = 0; - int i, err; - - memset(&ets, 0, sizeof(ets)); - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - for (i = 0; i < SPNIC_DCB_COS_MAX; i++) { - cos_bw_t += *(cos_bw + i); - tc_bw_t += *(tc_bw + i); - - if (*(cos_tc + i) > SPNIC_DCB_TC_MAX) { - nic_err(nic_cfg->dev_hdl, "Invalid cos %d mapping tc: %u\n", - i, *(cos_tc + i)); - return -EINVAL; - } - } - - /* The sum of all TCs must be 100%, and the same for cos */ - if ((tc_bw_t != 100 && tc_bw_t != 0) || (cos_bw_t % 100) != 0) { - nic_err(nic_cfg->dev_hdl, - "Invalid pg_bw: %u or up_bw: %u\n", tc_bw_t, cos_bw_t); - return -EINVAL; - } - - ets.port_id = sphw_physical_port_id(hwdev); - memcpy(ets.cos_tc, cos_tc, SPNIC_DCB_COS_MAX); - memcpy(ets.cos_bw, cos_bw, SPNIC_DCB_COS_MAX); - memcpy(ets.cos_prio, cos_prio, SPNIC_DCB_COS_MAX); - memcpy(ets.tc_bw, tc_bw, SPNIC_DCB_TC_MAX); - memcpy(ets.tc_prio, tc_prio, SPNIC_DCB_TC_MAX); - - err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_NIC_CMD_SET_ETS, - &ets, sizeof(ets), &ets, &out_size); - if (err || ets.msg_head.status || !out_size) { - nic_err(nic_cfg->dev_hdl, - "Failed to set ets, err: %d, status: 0x%x, out size: 0x%x\n", - err, ets.msg_head.status, out_size); - return -EINVAL; - } - - return 0; -} - -int spnic_dcb_set_cos_up_map(void *hwdev, u8 cos_valid_bitmap, u8 *cos_up, u8 max_cos_num) -{ - struct spnic_cos_up_map map; - struct spnic_nic_cfg *nic_cfg = NULL; - u16 out_size = sizeof(map); - int err; - - if (!hwdev || !cos_up) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - memset(&map, 0, sizeof(map)); - - map.port_id = sphw_physical_port_id(hwdev); - map.cos_valid_mask = cos_valid_bitmap; - memcpy(map.map, cos_up, sizeof(map.map)); - - err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_NIC_CMD_SETUP_COS_MAPPING, - &map, sizeof(map), &map, &out_size); - if (err || map.msg_head.status || !out_size) { - nic_err(nic_cfg->dev_hdl, - "Failed to set cos2up map, err: %d, status: 0x%x, out size: 0x%x\n", - err, map.msg_head.status, out_size); - return -EFAULT; - } - - return 0; -} - -int spnic_flush_qps_res(void *hwdev) -{ - struct spnic_cmd_clear_qp_resource sq_res; - u16 out_size = sizeof(sq_res); - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - if (!hwdev) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - memset(&sq_res, 0, sizeof(sq_res)); - - sq_res.func_id = sphw_global_func_id(hwdev); - - err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_NIC_CMD_CLEAR_QP_RESOURCE, - &sq_res, sizeof(sq_res), &sq_res, - &out_size); - if (err || !out_size || sq_res.msg_head.status) { - nic_err(nic_cfg->dev_hdl, "Failed to clear sq resources, err: %d, status: 0x%x, out size: 0x%x\n", - err, sq_res.msg_head.status, out_size); - return -EINVAL; - } - - return 0; -} - -int spnic_get_vport_stats(void *hwdev, struct spnic_vport_stats *stats) -{ - struct spnic_port_stats_info stats_info; - struct spnic_cmd_vport_stats vport_stats; - u16 out_size = sizeof(vport_stats); - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - if (!hwdev || !stats) - return -EINVAL; - - memset(&stats_info, 0, sizeof(stats_info)); - memset(&vport_stats, 0, sizeof(vport_stats)); - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - stats_info.func_id = sphw_global_func_id(hwdev); - - err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_NIC_CMD_GET_VPORT_STAT, - &stats_info, sizeof(stats_info), - &vport_stats, &out_size); - if (err || !out_size || vport_stats.msg_head.status) { - nic_err(nic_cfg->dev_hdl, - "Failed to get function statistics, err: %d, status: 0x%x, out size: 0x%x\n", - err, vport_stats.msg_head.status, out_size); - return -EFAULT; - } - - memcpy(stats, &vport_stats.stats, sizeof(*stats)); - - return 0; -} - -int spnic_set_function_table(struct spnic_nic_cfg *nic_cfg, u32 cfg_bitmap, - struct spnic_func_tbl_cfg *cfg) -{ - struct spnic_cmd_set_func_tbl cmd_func_tbl; - u16 out_size = sizeof(cmd_func_tbl); - int err; - - memset(&cmd_func_tbl, 0, sizeof(cmd_func_tbl)); - cmd_func_tbl.func_id = sphw_global_func_id(nic_cfg->hwdev); - cmd_func_tbl.cfg_bitmap = cfg_bitmap; - cmd_func_tbl.tbl_cfg = *cfg; - - err = l2nic_msg_to_mgmt_sync(nic_cfg->hwdev, SPNIC_NIC_CMD_SET_FUNC_TBL, - &cmd_func_tbl, sizeof(cmd_func_tbl), - &cmd_func_tbl, &out_size); - if (err || cmd_func_tbl.msg_head.status || !out_size) { - nic_err(nic_cfg->dev_hdl, - "Failed to set func table, bitmap: 0x%x, err: %d, status: 0x%x, out size: 0x%x\n", - cfg_bitmap, err, cmd_func_tbl.msg_head.status, out_size); - return -EFAULT; - } - - return 0; -} - -int spnic_init_function_table(struct spnic_nic_cfg *nic_cfg) -{ - struct spnic_func_tbl_cfg func_tbl_cfg = {0}; - u32 cfg_bitmap = BIT(FUNC_CFG_INIT) | BIT(FUNC_CFG_MTU) | - BIT(FUNC_CFG_RX_BUF_SIZE); - - func_tbl_cfg.mtu = 0x3FFF; /* default, max mtu */ - func_tbl_cfg.rx_wqe_buf_size = nic_cfg->rx_buff_len; - - return spnic_set_function_table(nic_cfg, cfg_bitmap, &func_tbl_cfg); -} - -int spnic_set_port_mtu(void *hwdev, u16 new_mtu) -{ - struct spnic_func_tbl_cfg func_tbl_cfg = {0}; - struct spnic_nic_cfg *nic_cfg = NULL; - - if (!hwdev) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - if (new_mtu < SPNIC_MIN_MTU_SIZE) { - nic_err(nic_cfg->dev_hdl, "Invalid mtu size: %ubytes, mtu size < %ubytes", - new_mtu, SPNIC_MIN_MTU_SIZE); - return -EINVAL; - } - - if (new_mtu > SPNIC_MAX_JUMBO_FRAME_SIZE) { - nic_err(nic_cfg->dev_hdl, "Invalid mtu size: %ubytes, mtu size > %ubytes", - new_mtu, SPNIC_MAX_JUMBO_FRAME_SIZE); - return -EINVAL; - } - - func_tbl_cfg.mtu = new_mtu; - return spnic_set_function_table(nic_cfg, BIT(FUNC_CFG_MTU), &func_tbl_cfg); -} - -static int nic_feature_nego(void *hwdev, u8 opcode, u64 *s_feature, u16 size) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - struct spnic_cmd_feature_nego feature_nego; - u16 out_size = sizeof(feature_nego); - int err; - - if (!hwdev || !s_feature || size > NIC_MAX_FEATURE_QWORD) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - memset(&feature_nego, 0, sizeof(feature_nego)); - feature_nego.func_id = sphw_global_func_id(hwdev); - feature_nego.opcode = opcode; - if (opcode == SPNIC_CMD_OP_SET) - memcpy(feature_nego.s_feature, s_feature, size * sizeof(u64)); - - err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_NIC_CMD_FEATURE_NEGO, - &feature_nego, sizeof(feature_nego), - &feature_nego, &out_size); - if (err || !out_size || feature_nego.msg_head.status) { - nic_err(nic_cfg->dev_hdl, "Failed to negotiate nic feature, err:%d, status: 0x%x, out_size: 0x%x\n", - err, feature_nego.msg_head.status, out_size); - return -EIO; - } - - if (opcode == SPNIC_CMD_OP_GET) - memcpy(s_feature, feature_nego.s_feature, size * sizeof(u64)); - - return 0; -} - -static int spnic_get_nic_feature_from_hw(void *hwdev, u64 *s_feature, u16 size) -{ - return nic_feature_nego(hwdev, SPNIC_CMD_OP_GET, s_feature, size); -} - -int spnic_set_nic_feature_to_hw(void *hwdev) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - return nic_feature_nego(hwdev, SPNIC_CMD_OP_SET, &nic_cfg->feature_cap, 1); -} - -u64 spnic_get_feature_cap(void *hwdev) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - return nic_cfg->feature_cap; -} - -void spnic_update_nic_feature(void *hwdev, u64 feature) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - nic_cfg->feature_cap = feature; - - nic_info(nic_cfg->dev_hdl, "Update nic feature to 0x%llx\n", nic_cfg->feature_cap); -} - -static inline int init_nic_hwdev_param_valid(void *hwdev, void *pcidev_hdl, void *dev_hdl) -{ - if (!hwdev || !pcidev_hdl || !dev_hdl) - return -EINVAL; - - return 0; -} - -/* spnic_init_nic_hwdev - init nic hwdev - * @hwdev: pointer to hwdev - * @pcidev_hdl: pointer to pcidev or handler - * @dev_hdl: pointer to pcidev->dev or handler, for sdk_err() or dma_alloc() - * @rx_buff_len: rx_buff_len is receive buffer length - */ -int spnic_init_nic_hwdev(void *hwdev, void *pcidev_hdl, void *dev_hdl, u16 rx_buff_len) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - if (init_nic_hwdev_param_valid(hwdev, pcidev_hdl, dev_hdl)) - return -EINVAL; - - nic_cfg = kzalloc(sizeof(*nic_cfg), GFP_KERNEL); - if (!nic_cfg) - return -ENOMEM; - - nic_cfg->dev_hdl = dev_hdl; - nic_cfg->pcidev_hdl = pcidev_hdl; - nic_cfg->hwdev = hwdev; - - sema_init(&nic_cfg->cfg_lock, 1); - mutex_init(&nic_cfg->sfp_mutex); - - err = sphw_register_service_adapter(hwdev, nic_cfg, SERVICE_T_NIC); - if (err) { - nic_err(nic_cfg->dev_hdl, "Failed to register service adapter\n"); - goto register_sa_err; - } - - err = spnic_init_function_table(nic_cfg); - if (err) { - nic_err(nic_cfg->dev_hdl, "Failed to init function table\n"); - goto init_func_tbl_err; - } - - err = spnic_get_nic_feature_from_hw(hwdev, &nic_cfg->feature_cap, 1); - if (err) { - nic_err(nic_cfg->dev_hdl, "Failed to get nic features\n"); - goto get_feature_err; - } - - sdk_info(dev_hdl, "nic features: 0x%llx\n", nic_cfg->feature_cap); - - err = sphw_aeq_register_swe_cb(hwdev, SPHW_STATELESS_EVENT, spnic_nic_sw_aeqe_handler); - if (err) { - nic_err(nic_cfg->dev_hdl, - "Failed to register sw aeqe handler\n"); - goto register_sw_aeqe_err; - } - - err = spnic_vf_func_init(nic_cfg); - if (err) { - nic_err(nic_cfg->dev_hdl, "Failed to init vf info\n"); - goto vf_init_err; - } - - nic_cfg->rx_buff_len = rx_buff_len; - - return 0; - -vf_init_err: - sphw_aeq_unregister_swe_cb(hwdev, SPHW_STATELESS_EVENT); - -register_sw_aeqe_err: -get_feature_err: -init_func_tbl_err: - sphw_unregister_service_adapter(hwdev, SERVICE_T_NIC); - -register_sa_err: - kfree(nic_cfg); - - return err; -} - -void spnic_free_nic_hwdev(void *hwdev) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - - if (!hwdev) - return; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - if (!nic_cfg) - return; - - spnic_vf_func_free(nic_cfg); - - sphw_aeq_unregister_swe_cb(hwdev, SPHW_STATELESS_EVENT); - - sphw_unregister_service_adapter(hwdev, SERVICE_T_NIC); - - kfree(nic_cfg); -} - -/* to do : send cmd to MPU to drop nic tx pkt*/ -int spnic_force_drop_tx_pkt(void *hwdev) -{ - return 0; -} - -int spnic_set_rx_mode(void *hwdev, u32 enable) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - struct spnic_rx_mode_config rx_mode_cfg; - u16 out_size = sizeof(rx_mode_cfg); - int err; - - if (!hwdev) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - memset(&rx_mode_cfg, 0, sizeof(rx_mode_cfg)); - rx_mode_cfg.func_id = sphw_global_func_id(hwdev); - rx_mode_cfg.rx_mode = enable; - - err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_NIC_CMD_SET_RX_MODE, - &rx_mode_cfg, sizeof(rx_mode_cfg), - &rx_mode_cfg, &out_size); - if (err || !out_size || rx_mode_cfg.msg_head.status) { - nic_err(nic_cfg->dev_hdl, "Failed to set rx mode, err: %d, status: 0x%x, out size: 0x%x\n", - err, rx_mode_cfg.msg_head.status, out_size); - return -EINVAL; - } - - return 0; -} - -int spnic_set_rx_vlan_offload(void *hwdev, u8 en) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - struct spnic_cmd_vlan_offload vlan_cfg; - u16 out_size = sizeof(vlan_cfg); - int err; - - if (!hwdev) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - memset(&vlan_cfg, 0, sizeof(vlan_cfg)); - vlan_cfg.func_id = sphw_global_func_id(hwdev); - vlan_cfg.vlan_offload = en; - - err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_NIC_CMD_SET_RX_VLAN_OFFLOAD, - &vlan_cfg, sizeof(vlan_cfg), - &vlan_cfg, &out_size); - if (err || !out_size || vlan_cfg.msg_head.status) { - nic_err(nic_cfg->dev_hdl, "Failed to set rx vlan offload, err: %d, status: 0x%x, out size: 0x%x\n", - err, vlan_cfg.msg_head.status, out_size); - return -EINVAL; - } - - return 0; -} - -int spnic_update_mac_vlan(void *hwdev, u16 old_vlan, u16 new_vlan, int vf_id) -{ - struct vf_data_storage *vf_info = NULL; - struct spnic_nic_cfg *nic_cfg = NULL; - u16 func_id; - int err; - - if (!hwdev || old_vlan >= VLAN_N_VID || new_vlan >= VLAN_N_VID) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - vf_info = nic_cfg->vf_infos + HW_VF_ID_TO_OS(vf_id); - - if (!nic_cfg->vf_infos || is_zero_ether_addr(vf_info->drv_mac_addr)) - return 0; - - func_id = sphw_glb_pf_vf_offset(nic_cfg->hwdev) + (u16)vf_id; - - err = spnic_del_mac(nic_cfg->hwdev, vf_info->drv_mac_addr, - old_vlan, func_id, SPHW_CHANNEL_NIC); - if (err) { - nic_err(nic_cfg->dev_hdl, "Failed to delete VF %d MAC %pM vlan %u\n", - HW_VF_ID_TO_OS(vf_id), vf_info->drv_mac_addr, old_vlan); - return err; - } - - err = spnic_set_mac(nic_cfg->hwdev, vf_info->drv_mac_addr, - new_vlan, func_id, SPHW_CHANNEL_NIC); - if (err) { - nic_err(nic_cfg->dev_hdl, "Failed to add VF %d MAC %pM vlan %u\n", - HW_VF_ID_TO_OS(vf_id), vf_info->drv_mac_addr, new_vlan); - spnic_set_mac(nic_cfg->hwdev, vf_info->drv_mac_addr, - old_vlan, func_id, SPHW_CHANNEL_NIC); - return err; - } - - return 0; -} - -static int spnic_set_rx_lro(void *hwdev, u8 ipv4_en, u8 ipv6_en, u8 lro_max_pkt_len) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - struct spnic_cmd_lro_config lro_cfg; - u16 out_size = sizeof(lro_cfg); - int err; - - if (!hwdev) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - memset(&lro_cfg, 0, sizeof(lro_cfg)); - lro_cfg.func_id = sphw_global_func_id(hwdev); - lro_cfg.opcode = SPNIC_CMD_OP_SET; - lro_cfg.lro_ipv4_en = ipv4_en; - lro_cfg.lro_ipv6_en = ipv6_en; - lro_cfg.lro_max_pkt_len = lro_max_pkt_len; - - err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_NIC_CMD_CFG_RX_LRO, - &lro_cfg, sizeof(lro_cfg), - &lro_cfg, &out_size); - if (err || !out_size || lro_cfg.msg_head.status) { - nic_err(nic_cfg->dev_hdl, "Failed to set lro offload, err: %d, status: 0x%x, out size: 0x%x\n", - err, lro_cfg.msg_head.status, out_size); - return -EINVAL; - } - - return 0; -} - -static int spnic_set_rx_lro_timer(void *hwdev, u32 timer_value) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - struct spnic_cmd_lro_timer lro_timer; - u16 out_size = sizeof(lro_timer); - int err; - - if (!hwdev) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - memset(&lro_timer, 0, sizeof(lro_timer)); - lro_timer.opcode = SPNIC_CMD_OP_SET; - lro_timer.timer = timer_value; - - err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_NIC_CMD_CFG_LRO_TIMER, - &lro_timer, sizeof(lro_timer), - &lro_timer, &out_size); - if (err || !out_size || lro_timer.msg_head.status) { - nic_err(nic_cfg->dev_hdl, "Failed to set lro timer, err: %d, status: 0x%x, out size: 0x%x\n", - err, lro_timer.msg_head.status, out_size); - - return -EINVAL; - } - - return 0; -} - -int spnic_set_rx_lro_state(void *hwdev, u8 lro_en, u32 lro_timer, u32 lro_max_pkt_len) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - u8 ipv4_en = 0, ipv6_en = 0; - int err; - - if (!hwdev) - return -EINVAL; - - ipv4_en = lro_en ? 1 : 0; - ipv6_en = lro_en ? 1 : 0; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - nic_info(nic_cfg->dev_hdl, "Set LRO max coalesce packet size to %uK\n", - lro_max_pkt_len); - - err = spnic_set_rx_lro(hwdev, ipv4_en, ipv6_en, (u8)lro_max_pkt_len); - if (err) - return err; - - /* we don't set LRO timer for VF */ - if (sphw_func_type(hwdev) == TYPE_VF) - return 0; - - nic_info(nic_cfg->dev_hdl, "Set LRO timer to %u\n", lro_timer); - - return spnic_set_rx_lro_timer(hwdev, lro_timer); -} - -int spnic_set_vlan_fliter(void *hwdev, u32 vlan_filter_ctrl) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - struct spnic_cmd_set_vlan_filter vlan_filter; - u16 out_size = sizeof(vlan_filter); - int err; - - if (!hwdev) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - memset(&vlan_filter, 0, sizeof(vlan_filter)); - vlan_filter.func_id = sphw_global_func_id(hwdev); - vlan_filter.vlan_filter_ctrl = vlan_filter_ctrl; - - err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_NIC_CMD_SET_VLAN_FILTER_EN, - &vlan_filter, sizeof(vlan_filter), - &vlan_filter, &out_size); - if (err || !out_size || vlan_filter.msg_head.status) { - nic_err(nic_cfg->dev_hdl, "Failed to set vlan filter, err: %d, status: 0x%x, out size: 0x%x\n", - err, vlan_filter.msg_head.status, out_size); - return -EINVAL; - } - - return 0; -} - -int spnic_add_tcam_rule(void *hwdev, struct nic_tcam_cfg_rule *tcam_rule) -{ - u16 out_size = sizeof(struct nic_cmd_fdir_add_rule); - struct nic_cmd_fdir_add_rule tcam_cmd; - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - if (!hwdev || !tcam_rule) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - if (tcam_rule->index >= SPNIC_MAX_TCAM_RULES_NUM) { - nic_err(nic_cfg->dev_hdl, "Tcam rules num to add is invalid\n"); - return -EINVAL; - } - - memset(&tcam_cmd, 0, sizeof(struct nic_cmd_fdir_add_rule)); - memcpy((void *)&tcam_cmd.rule, (void *)tcam_rule, - sizeof(struct nic_tcam_cfg_rule)); - tcam_cmd.func_id = sphw_global_func_id(hwdev); - - err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_NIC_CMD_ADD_TC_FLOW, - &tcam_cmd, sizeof(tcam_cmd), - &tcam_cmd, &out_size); - if (err || tcam_cmd.head.status || !out_size) { - nic_err(nic_cfg->dev_hdl, - "Add tcam rule failed, err: %d, status: 0x%x, out size: 0x%x\n", - err, tcam_cmd.head.status, out_size); - return -EIO; - } - - return 0; -} - -int spnic_del_tcam_rule(void *hwdev, u32 index) -{ - u16 out_size = sizeof(struct nic_cmd_fdir_del_rules); - struct nic_cmd_fdir_del_rules tcam_cmd; - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - if (!hwdev) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - if (index >= SPNIC_MAX_TCAM_RULES_NUM) { - nic_err(nic_cfg->dev_hdl, "Tcam rules num to del is invalid\n"); - return -EINVAL; - } - - memset(&tcam_cmd, 0, sizeof(struct nic_cmd_fdir_del_rules)); - tcam_cmd.index_start = index; - tcam_cmd.index_num = 1; - tcam_cmd.func_id = sphw_global_func_id(hwdev); - - err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_NIC_CMD_DEL_TC_FLOW, - &tcam_cmd, sizeof(tcam_cmd), - &tcam_cmd, &out_size); - if (err || tcam_cmd.head.status || !out_size) { - nic_err(nic_cfg->dev_hdl, "Del tcam rule failed, err: %d, status: 0x%x, out size: 0x%x\n", - err, tcam_cmd.head.status, out_size); - return -EIO; - } - - return 0; -} - -/** - * spnic_mgmt_tcam_block - alloc or free tcam block for IO packet. - * - * @param hwdev - * The hardware interface of a nic device. - * @param alloc_en - * 1 alloc block. - * 0 free block. - * @param index - * block index from firmware. - * @return - * 0 on success, - * negative error value otherwise. - */ -static int spnic_mgmt_tcam_block(void *hwdev, u8 alloc_en, u16 *index) -{ - struct nic_cmd_ctrl_tcam_block_out tcam_block_info; - u16 out_size = sizeof(struct nic_cmd_ctrl_tcam_block_out); - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - if (!hwdev || !index) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - memset(&tcam_block_info, 0, sizeof(struct nic_cmd_ctrl_tcam_block_out)); - - tcam_block_info.func_id = sphw_global_func_id(hwdev); - tcam_block_info.alloc_en = alloc_en; - tcam_block_info.tcam_type = SPNIC_TCAM_BLOCK_NORMAL_TYPE; - tcam_block_info.tcam_block_index = *index; - - err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_NIC_CMD_CFG_TCAM_BLOCK, - &tcam_block_info, sizeof(tcam_block_info), - &tcam_block_info, &out_size); - if (err || tcam_block_info.head.status || !out_size) { - nic_err(nic_cfg->dev_hdl, - "Set tcam block failed, err: %d, status: 0x%x, out size: 0x%x\n", - err, tcam_block_info.head.status, out_size); - return -EIO; - } - - if (alloc_en) - *index = tcam_block_info.tcam_block_index; - - return 0; -} - -int spnic_alloc_tcam_block(void *hwdev, u16 *index) -{ - return spnic_mgmt_tcam_block(hwdev, SPNIC_TCAM_BLOCK_ENABLE, index); -} - -int spnic_free_tcam_block(void *hwdev, u16 *index) -{ - return spnic_mgmt_tcam_block(hwdev, SPNIC_TCAM_BLOCK_DISABLE, index); -} - -int spnic_set_fdir_tcam_rule_filter(void *hwdev, bool enable) -{ - struct nic_cmd_set_tcam_enable port_tcam_cmd; - u16 out_size = sizeof(port_tcam_cmd); - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - if (!hwdev) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - memset(&port_tcam_cmd, 0, sizeof(port_tcam_cmd)); - port_tcam_cmd.func_id = sphw_global_func_id(hwdev); - port_tcam_cmd.tcam_enable = (u8)enable; - - err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_NIC_CMD_ENABLE_TCAM, - &port_tcam_cmd, sizeof(port_tcam_cmd), - &port_tcam_cmd, &out_size); - if (err || port_tcam_cmd.head.status || !out_size) { - nic_err(nic_cfg->dev_hdl, "Set fdir tcam filter failed, err: %d, status: 0x%x, out size: 0x%x, enable: 0x%x\n", - err, port_tcam_cmd.head.status, out_size, - enable); - return -EIO; - } - - return 0; -} - -int spnic_flush_tcam_rule(void *hwdev) -{ - struct nic_cmd_flush_tcam_rules tcam_flush; - u16 out_size = sizeof(struct nic_cmd_flush_tcam_rules); - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - if (!hwdev) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - memset(&tcam_flush, 0, sizeof(struct nic_cmd_flush_tcam_rules)); - tcam_flush.func_id = sphw_global_func_id(hwdev); - - err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_NIC_CMD_FLUSH_TCAM, - &tcam_flush, - sizeof(struct nic_cmd_flush_tcam_rules), - &tcam_flush, &out_size); - if (err || tcam_flush.head.status || !out_size) { - nic_err(nic_cfg->dev_hdl, - "Flush tcam fdir rules failed, err: %d, status: 0x%x, out size: 0x%x\n", - err, tcam_flush.head.status, out_size); - return -EIO; - } - - return 0; -} diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_nic_cfg.h b/drivers/net/ethernet/ramaxel/spnic/spnic_nic_cfg.h deleted file mode 100644 index f280b41fe362..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_nic_cfg.h +++ /dev/null @@ -1,709 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPNIC_NIC_CFG_H -#define SPNIC_NIC_CFG_H - -#include <linux/if_link.h> - -#include "spnic_nic_cmd.h" -#include "spnic_mgmt_interface.h" -#include "spnic_mag_cmd.h" - -#define OS_VF_ID_TO_HW(os_vf_id) ((os_vf_id) + 1) -#define HW_VF_ID_TO_OS(hw_vf_id) ((hw_vf_id) - 1) - -#define SPNIC_VLAN_PRIORITY_SHIFT 13 - -#define SPNIC_RSS_KEY_RSV_NUM 2 - -#define SPNIC_MIN_MTU_SIZE 256 -#define SPNIC_MAX_JUMBO_FRAME_SIZE 9600 - -#define SPNIC_PF_SET_VF_ALREADY 0x4 -#define SPNIC_MGMT_STATUS_EXIST 0x6 - -#define SPNIC_LOWEST_LATENCY 1 -#define SPNIC_MULTI_VM_LATENCY 32 -#define SPNIC_MULTI_VM_PENDING_LIMIT 4 -#define SPNIC_RX_RATE_LOW 400000 -#define SPNIC_RX_COAL_TIME_LOW 16 -#define SPNIC_RX_PENDING_LIMIT_LOW 2 -#define SPNIC_RX_RATE_HIGH 1000000 -#define SPNIC_RX_COAL_TIME_HIGH 225 -#define SPNIC_RX_PENDING_LIMIT_HIGH 8 -#define SPNIC_RX_RATE_THRESH 50000 -#define SPNIC_TX_RATE_THRESH 50000 -#define SPNIC_RX_RATE_LOW_VM 100000 -#define SPNIC_RX_PENDING_LIMIT_HIGH_VM 87 - -enum spnic_valid_link_settings { - HILINK_LINK_SET_SPEED = 0x1, - HILINK_LINK_SET_AUTONEG = 0x2, - HILINK_LINK_SET_FEC = 0x4, -}; - -struct spnic_link_ksettings { - u32 valid_bitmap; - u8 speed; /* enum nic_speed_level */ - u8 autoneg; /* 0 - off; 1 - on */ - u8 fec; /* 0 - RSFEC; 1 - BASEFEC; 2 - NOFEC */ -}; - -u64 spnic_get_feature_cap(void *hwdev); - -#define SPNIC_SUPPORT_FEATURE(hwdev, feature) (spnic_get_feature_cap(hwdev) & NIC_F_##feature) -#define SPNIC_SUPPORT_CSUM(hwdev) SPNIC_SUPPORT_FEATURE(hwdev, CSUM) -#define SPNIC_SUPPORT_SCTP_CRC(hwdev) SPNIC_SUPPORT_FEATURE(hwdev, SCTP_CRC) -#define SPNIC_SUPPORT_TSO(hwdev) SPNIC_SUPPORT_FEATURE(hwdev, TSO) -#define SPNIC_SUPPORT_UFO(hwdev) SPNIC_SUPPORT_FEATURE(hwdev, UFO) -#define SPNIC_SUPPORT_LRO(hwdev) SPNIC_SUPPORT_FEATURE(hwdev, LRO) -#define SPNIC_SUPPORT_RSS(hwdev) SPNIC_SUPPORT_FEATURE(hwdev, RSS) -#define SPNIC_SUPPORT_RXVLAN_FILTER(hwdev) SPNIC_SUPPORT_FEATURE(hwdev, RX_VLAN_FILTER) -#define SPNIC_SUPPORT_VLAN_OFFLOAD(hwdev) (SPNIC_SUPPORT_FEATURE(hwdev, RX_VLAN_STRIP) && \ - SPNIC_SUPPORT_FEATURE(hwdev, TX_VLAN_INSERT)) -#define SPNIC_SUPPORT_VXLAN_OFFLOAD(hwdev) SPNIC_SUPPORT_FEATURE(hwdev, VXLAN_OFFLOAD) -#define SPNIC_SUPPORT_IPSEC_OFFLOAD(hwdev) SPNIC_SUPPORT_FEATURE(hwdev, IPSEC_OFFLOAD) -#define SPNIC_SUPPORT_FDIR(hwdev) SPNIC_SUPPORT_FEATURE(hwdev, FDIR) -#define SPNIC_SUPPORT_PROMISC(hwdev) SPNIC_SUPPORT_FEATURE(hwdev, PROMISC) -#define SPNIC_SUPPORT_ALLMULTI(hwdev) SPNIC_SUPPORT_FEATURE(hwdev, ALLMULTI) - -struct nic_rss_type { - u8 tcp_ipv6_ext; - u8 ipv6_ext; - u8 tcp_ipv6; - u8 ipv6; - u8 tcp_ipv4; - u8 ipv4; - u8 udp_ipv6; - u8 udp_ipv4; -}; - -enum spnic_rss_hash_type { - SPNIC_RSS_HASH_ENGINE_TYPE_XOR = 0, - SPNIC_RSS_HASH_ENGINE_TYPE_TOEP, - SPNIC_RSS_HASH_ENGINE_TYPE_MAX, -}; - -/* rss */ -struct nic_rss_indirect_tbl { - u32 rsvd[4]; /* Make sure that 16B beyond entry[] */ - u16 entry[SPNIC_RSS_INDIR_SIZE]; -}; - -struct nic_rss_context_tbl { - u32 rsvd[4]; - u32 ctx; -}; - -#define NIC_CONFIG_ALL_QUEUE_VLAN_CTX 0xFFFF -struct nic_vlan_ctx { - u32 func_id; - u32 qid; /* if qid = 0xFFFF, config current function all queue */ - u32 vlan_tag; - u32 vlan_mode; - u32 vlan_sel; -}; - -enum spnic_link_status { - SPNIC_LINK_DOWN = 0, - SPNIC_LINK_UP -}; - -struct nic_port_info { - u8 port_type; - u8 autoneg_cap; - u8 autoneg_state; - u8 duplex; - u8 speed; - u8 fec; - u32 supported_mode; - u32 advertised_mode; -}; - -struct nic_pause_config { - u8 auto_neg; - u8 rx_pause; - u8 tx_pause; -}; - -#define MODULE_TYPE_SFP 0x3 -#define MODULE_TYPE_QSFP28 0x11 -#define MODULE_TYPE_QSFP 0x0C -#define MODULE_TYPE_QSFP_PLUS 0x0D - -#define TCAM_IP_TYPE_MASK 0x1 -#define TCAM_TUNNEL_TYPE_MASK 0xF -#define TCAM_FUNC_ID_MASK 0x7FFF - -struct spnic_tcam_key_ipv4_mem { - u32 rsvd1:4; - u32 tunnel_type:4; - u32 ip_proto:8; - u32 rsvd0:16; - u32 sipv4_h:16; - u32 ip_type:1; - u32 function_id:15; - u32 dipv4_h:16; - u32 sipv4_l:16; - u32 rsvd2:16; - u32 dipv4_l:16; - u32 rsvd3; - u32 dport:16; - u32 rsvd4:16; - u32 rsvd5:16; - u32 sport:16; - u32 outer_sipv4_h:16; - u32 rsvd6:16; - u32 outer_dipv4_h:16; - u32 outer_sipv4_l:16; - u32 vni_h:16; - u32 outer_dipv4_l:16; - u32 rsvd7:16; - u32 vni_l:16; -}; - -struct spnic_tcam_key_ipv6_mem { - u32 rsvd1:4; - u32 tunnel_type:4; - u32 ip_proto:8; - u32 rsvd0:16; - u32 sipv6_key0:16; - u32 ip_type:1; - u32 function_id:15; - u32 sipv6_key2:16; - u32 sipv6_key1:16; - u32 sipv6_key4:16; - u32 sipv6_key3:16; - u32 sipv6_key6:16; - u32 sipv6_key5:16; - u32 dport:16; - u32 sipv6_key7:16; - u32 dipv6_key0:16; - u32 sport:16; - u32 dipv6_key2:16; - u32 dipv6_key1:16; - u32 dipv6_key4:16; - u32 dipv6_key3:16; - u32 dipv6_key6:16; - u32 dipv6_key5:16; - u32 rsvd2:16; - u32 dipv6_key7:16; -}; - -struct tag_tcam_key { - union { - struct spnic_tcam_key_ipv4_mem key_info; - struct spnic_tcam_key_ipv6_mem key_info_ipv6; - }; - - union { - struct spnic_tcam_key_ipv4_mem key_mask; - struct spnic_tcam_key_ipv6_mem key_mask_ipv6; - }; -}; - -int spnic_add_tcam_rule(void *hwdev, struct nic_tcam_cfg_rule *tcam_rule); -int spnic_del_tcam_rule(void *hwdev, u32 index); - -int spnic_alloc_tcam_block(void *hwdev, u16 *index); -int spnic_free_tcam_block(void *hwdev, u16 *index); - -int spnic_set_fdir_tcam_rule_filter(void *hwdev, bool enable); - -int spnic_flush_tcam_rule(void *hwdev); - -/* * - * @brief spnic_update_mac - update mac address to hardware - * @param hwdev: device pointer to hwdev - * @param old_mac: old mac to delete - * @param new_mac: new mac to update - * @param vlan_id: vlan id - * @param func_id: function index - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_update_mac(void *hwdev, u8 *old_mac, u8 *new_mac, u16 vlan_id, u16 func_id); - -/* * - * @brief spnic_get_default_mac - get default mac address - * @param hwdev: device pointer to hwdev - * @param mac_addr: mac address from hardware - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_get_default_mac(void *hwdev, u8 *mac_addr); - -/* * - * @brief spnic_set_port_mtu - set function mtu - * @param hwdev: device pointer to hwdev - * @param new_mtu: mtu - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_set_port_mtu(void *hwdev, u16 new_mtu); - -/* * - * @brief spnic_get_link_state - get link state - * @param hwdev: device pointer to hwdev - * @param link_state: link state, 0-link down, 1-link up - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_get_link_state(void *hwdev, u8 *link_state); - -/* * - * @brief spnic_get_vport_stats - get function stats - * @param hwdev: device pointer to hwdev - * @param stats: function stats - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_get_vport_stats(void *hwdev, struct spnic_vport_stats *stats); - -/* * - * @brief spnic_notify_all_vfs_link_changed - notify to all vfs link changed - * @param hwdev: device pointer to hwdev - * @param link_status: link state, 0-link down, 1-link up - */ -void spnic_notify_all_vfs_link_changed(void *hwdev, u8 link_status); - -/* * - * @brief spnic_force_drop_tx_pkt - force drop tx packet - * @param hwdev: device pointer to hwdev - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_force_drop_tx_pkt(void *hwdev); - -/* * - * @brief spnic_set_rx_mode - set function rx mode - * @param hwdev: device pointer to hwdev - * @param enable: rx mode state - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_set_rx_mode(void *hwdev, u32 enable); - -/* * - * @brief spnic_set_rx_vlan_offload - set function vlan offload valid state - * @param hwdev: device pointer to hwdev - * @param en: 0-disable, 1-enable - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_set_rx_vlan_offload(void *hwdev, u8 en); - -/* * - * @brief spnic_set_rx_lro_state - set rx LRO configuration - * @param hwdev: device pointer to hwdev - * @param lro_en: 0-disable, 1-enable - * @param lro_timer: LRO aggregation timeout - * @param lro_max_pkt_len: LRO coalesce packet size(unit is 1K) - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_set_rx_lro_state(void *hwdev, u8 lro_en, u32 lro_timer, u32 lro_max_pkt_len); - -/* * - * @brief spnic_set_vf_spoofchk - set vf spoofchk - * @param hwdev: device pointer to hwdev - * @param vf_id: vf id - * @param spoofchk: spoofchk - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_set_vf_spoofchk(void *hwdev, u16 vf_id, bool spoofchk); - -/* * - * @brief spnic_vf_info_spoofchk - get vf spoofchk info - * @param hwdev: device pointer to hwdev - * @param vf_id: vf id - * @retval spoofchk state - */ -bool spnic_vf_info_spoofchk(void *hwdev, int vf_id); - -/* * - * @brief spnic_add_vf_vlan - add vf vlan id - * @param hwdev: device pointer to hwdev - * @param vf_id: vf id - * @param vlan: vlan id - * @param qos: qos - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_add_vf_vlan(void *hwdev, int vf_id, u16 vlan, u8 qos); - -/* * - * @brief spnic_kill_vf_vlan - kill vf vlan - * @param hwdev: device pointer to hwdev - * @param vf_id: vf id - * @param vlan: vlan id - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_kill_vf_vlan(void *hwdev, int vf_id); - -/* * - * @brief spnic_set_vf_mac - set vf mac - * @param hwdev: device pointer to hwdev - * @param vf_id: vf id - * @param mac_addr: vf mac address - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_set_vf_mac(void *hwdev, int vf_id, unsigned char *mac_addr); - -/* * - * @brief spnic_vf_info_vlanprio - get vf vlan priority - * @param hwdev: device pointer to hwdev - * @param vf_id: vf id - * @retval zero: vlan priority - */ -u16 spnic_vf_info_vlanprio(void *hwdev, int vf_id); - -/* * - * @brief spnic_set_vf_tx_rate - set vf tx rate - * @param hwdev: device pointer to hwdev - * @param vf_id: vf id - * @param max_rate: max rate - * @param min_rate: min rate - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_set_vf_tx_rate(void *hwdev, u16 vf_id, u32 max_rate, u32 min_rate); - -/* * - * @brief spnic_set_vf_tx_rate - set vf tx rate - * @param hwdev: device pointer to hwdev - * @param vf_id: vf id - * @param ivi: vf info - * @retval zero: success - * @retval non-zero: failure - */ -void spnic_get_vf_config(void *hwdev, u16 vf_id, struct ifla_vf_info *ivi); - -/* * - * @brief spnic_set_vf_link_state - set vf link state - * @param hwdev: device pointer to hwdev - * @param vf_id: vf id - * @param link: link state - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_set_vf_link_state(void *hwdev, u16 vf_id, int link); - -/* * - * @brief spnic_get_port_info - set port info - * @param hwdev: device pointer to hwdev - * @param port_info: port info - * @param channel: channel id - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_get_port_info(void *hwdev, struct nic_port_info *port_info, u16 channel); - -/* * - * @brief spnic_set_rss_type - set rss type - * @param hwdev: device pointer to hwdev - * @param rss_type: rss type - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_set_rss_type(void *hwdev, struct nic_rss_type rss_type); - -/* * - * @brief spnic_get_rss_type - get rss type - * @param hwdev: device pointer to hwdev - * @param rss_type: rss type - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_get_rss_type(void *hwdev, struct nic_rss_type *rss_type); - -/* * - * @brief spnic_rss_get_hash_engine - get rss hash engine - * @param hwdev: device pointer to hwdev - * @param type: hash engine - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_rss_get_hash_engine(void *hwdev, u8 *type); - -/* * - * @brief spnic_rss_set_hash_engine - set rss hash engine - * @param hwdev: device pointer to hwdev - * @param type: hash engine - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_rss_set_hash_engine(void *hwdev, u8 type); - -/* * - * @brief spnic_rss_cfg - set rss configuration - * @param hwdev: device pointer to hwdev - * @param rss_en: enable rss flag - * @param type: number of TC - * @param prio_tc: priorityof TC - * @param num_qps: number of queue - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_rss_cfg(void *hwdev, u8 rss_en, u8 tc_num, u8 *prio_tc, u16 num_qps); - -/* * - * @brief spnic_rss_set_template_tbl - set template table - * @param hwdev: device pointer to hwdev - * @param key: rss key - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_rss_set_hash_key(void *hwdev, const u8 *key); - -/* * - * @brief spnic_rss_get_template_tbl - get template table - * @param hwdev: device pointer to hwdev - * @param key: rss key - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_rss_get_hash_key(void *hwdev, u8 *key); - -/* * - * @brief spnic_refresh_nic_cfg - refresh port cfg - * @param hwdev: device pointer to hwdev - * @param port_info: port information - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_refresh_nic_cfg(void *hwdev, struct nic_port_info *port_info); - -/* * - * @brief spnic_add_vlan - add vlan - * @param hwdev: device pointer to hwdev - * @param vlan_id: vlan id - * @param func_id: function id - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_add_vlan(void *hwdev, u16 vlan_id, u16 func_id); - -/* * - * @brief spnic_del_vlan - delete vlan - * @param hwdev: device pointer to hwdev - * @param vlan_id: vlan id - * @param func_id: function id - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_del_vlan(void *hwdev, u16 vlan_id, u16 func_id); - -/* * - * @brief spnic_set_mac - set mac address - * @param hwdev: device pointer to hwdev - * @param mac_addr: mac address from hardware - * @param vlan_id: vlan id - * @param func_id: function index - * @param channel: channel id - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_set_mac(void *hwdev, const u8 *mac_addr, u16 vlan_id, u16 func_id, u16 channel); - -/* * - * @brief spnic_del_mac - delete mac address - * @param hwdev: device pointer to hwdev - * @param mac_addr: mac address from hardware - * @param vlan_id: vlan id - * @param func_id: function index - * @param channel: channel id - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_del_mac(void *hwdev, const u8 *mac_addr, u16 vlan_id, u16 func_id, u16 channel); - -/* * - * @brief spnic_set_vport_enable - set function valid status - * @param hwdev: device pointer to hwdev - * @param func_id: global function index - * @param enable: 0-disable, 1-enable - * @param channel: channel id - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_set_vport_enable(void *hwdev, u16 func_id, bool enable, u16 channel); - -/* * - * @brief spnic_set_port_enable - set port status - * @param hwdev: device pointer to hwdev - * @param enable: 0-disable, 1-enable - * @param channel: channel id - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_set_port_enable(void *hwdev, bool enable, u16 channel); - -/* * - * @brief spnic_flush_qps_res - flush queue pairs resource in hardware - * @param hwdev: device pointer to hwdev - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_flush_qps_res(void *hwdev); - -/* * - * @brief spnic_init_nic_hwdev - init nic hwdev - * @param hwdev: device pointer to hwdev - * @param pcidev_hdl: pointer to pcidev or handler - * @param dev_hdl: pointer to pcidev->dev or handler, for sdk_err() or - * dma_alloc() - * @param rx_buff_len: rx_buff_len is receive buffer length - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_init_nic_hwdev(void *hwdev, void *pcidev_hdl, void *dev_hdl, u16 rx_buff_len); - -/* * - * @brief spnic_free_nic_hwdev - free nic hwdev - * @param hwdev: device pointer to hwdev - * @retval zero: success - * @retval non-zero: failure - */ -void spnic_free_nic_hwdev(void *hwdev); - -/* * - * @brief spnic_get_speed - set link speed - * @param hwdev: device pointer to hwdev - * @param port_info: link speed - * @param channel: channel id - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_get_speed(void *hwdev, enum mag_cmd_port_speed *speed, u16 channel); - -int spnic_get_dcb_state(void *hwdev, struct spnic_dcb_state *dcb_state); - -int spnic_get_pf_dcb_state(void *hwdev, struct spnic_dcb_state *dcb_state); - -/* * - * @brief spnic_create_qps - create queue pairs - * @param hwdev: device pointer to hwdev - * @param num_qp: number of queue pairs - * @param sq_depth: sq depth - * @param rq_depth: rq depth - * @param qps_msix_arry: msix info - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_create_qps(void *hwdev, u16 num_qp, u32 sq_depth, u32 rq_depth, - struct irq_info *qps_msix_arry); - -/* * - * @brief spnic_destroy_qps - destroy queue pairs - * @param hwdev: device pointer to hwdev - */ -void spnic_destroy_qps(void *hwdev); - -enum spnic_queue_type { - SPNIC_SQ, - SPNIC_RQ, - SPNIC_MAX_QUEUE_TYPE -}; - -/* * - * @brief spnic_get_nic_queue - get nic queue - * @param hwdev: device pointer to hwdev - * @param q_id: queue index - * @param q_type: queue type - * @retval queue address - */ -void *spnic_get_nic_queue(void *hwdev, u16 q_id, enum spnic_queue_type q_type); - -/* * - * @brief spnic_init_qp_ctxts - init queue pair context - * @param hwdev: device pointer to hwdev - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_init_qp_ctxts(void *hwdev); - -/* * - * @brief spnic_free_qp_ctxts - free queue pairs - * @param hwdev: device pointer to hwdev - */ -void spnic_free_qp_ctxts(void *hwdev); - -/* * - * @brief spnic_rss_set_indir_tbl - set rss indirect table - * @param hwdev: device pointer to hwdev - * @param indir_table: rss indirect table - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_rss_set_indir_tbl(void *hwdev, const u32 *indir_table); - -/* * - * @brief spnic_rss_get_indir_tbl - get rss indirect table - * @param hwdev: device pointer to hwdev - * @param indir_table: rss indirect table - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_rss_get_indir_tbl(void *hwdev, u32 *indir_table); - -/* * - * @brief spnic_get_phy_port_stats - get port stats - * @param hwdev: device pointer to hwdev - * @param stats: port stats - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_get_phy_port_stats(void *hwdev, struct mag_cmd_port_stats *stats); - -int spnic_set_port_funcs_state(void *hwdev, bool enable); - -int spnic_reset_port_link_cfg(void *hwdev); - -int spnic_force_port_relink(void *hwdev); - -int spnic_set_dcb_state(void *hwdev, struct spnic_dcb_state *dcb_state); - -int spnic_dcb_set_pfc(void *hwdev, u8 pfc_en, u8 pfc_bitmap); - -int spnic_dcb_get_pfc(void *hwdev, u8 *pfc_en_bitmap); - -int spnic_dcb_set_ets(void *hwdev, u8 *cos_tc, u8 *cos_bw, u8 *cos_prio, u8 *tc_bw, u8 *tc_prio); - -int spnic_dcb_set_cos_up_map(void *hwdev, u8 cos_valid_bitmap, u8 *cos_up, u8 max_cos_num); - -int spnic_get_pause_info(void *hwdev, struct nic_pause_config *nic_pause); - -int spnic_set_pause_info(void *hwdev, struct nic_pause_config nic_pause); - -int spnic_set_link_settings(void *hwdev, struct spnic_link_ksettings *settings); - -int spnic_set_vlan_fliter(void *hwdev, u32 vlan_filter_ctrl); - -void spnic_clear_vfs_info(void *hwdev); - -int spnic_update_mac_vlan(void *hwdev, u16 old_vlan, u16 new_vlan, int vf_id); - -int spnic_set_led_status(void *hwdev, enum mag_led_type type, enum mag_led_mode mode); - -int spnic_set_func_capture_en(void *hwdev, u16 func_id, bool cap_en); - -int spnic_set_loopback_mode(void *hwdev, u8 mode, u8 enable); -int spnic_get_loopback_mode(void *hwdev, u8 *mode, u8 *enable); - -bool spnic_get_vf_trust(void *hwdev, int vf_id); -int spnic_set_vf_trust(void *hwdev, u16 vf_id, bool trust); - -int spnic_set_autoneg(void *hwdev, bool enable); - -int spnic_get_sfp_type(void *hwdev, u8 *sfp_type, u8 *sfp_type_ext); -int spnic_get_sfp_eeprom(void *hwdev, u8 *data, u32 len); - -int spnic_set_nic_feature_to_hw(void *hwdeve); -void spnic_update_nic_feature(void *hwdev, u64 feature); - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_nic_cfg_vf.c b/drivers/net/ethernet/ramaxel/spnic/spnic_nic_cfg_vf.c deleted file mode 100644 index 634f82153dff..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_nic_cfg_vf.c +++ /dev/null @@ -1,658 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [NIC]" fmt - -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/etherdevice.h> -#include <linux/if_vlan.h> -#include <linux/ethtool.h> -#include <linux/kernel.h> -#include <linux/device.h> -#include <linux/pci.h> -#include <linux/netdevice.h> -#include <linux/module.h> - -#include "sphw_crm.h" -#include "sphw_hw.h" -#include "spnic_nic_io.h" -#include "spnic_nic_cfg.h" -#include "spnic_nic.h" -#include "spnic_nic_cmd.h" - -static unsigned char set_vf_link_state; -module_param(set_vf_link_state, byte, 0444); -MODULE_PARM_DESC(set_vf_link_state, "Set vf link state, 0 represents link auto, 1 represents link always up, 2 represents link always down. - default is 0."); - -/* In order to adapt different linux version */ -enum { - SPNIC_IFLA_VF_LINK_STATE_AUTO, /* link state of the uplink */ - SPNIC_IFLA_VF_LINK_STATE_ENABLE, /* link always up */ - SPNIC_IFLA_VF_LINK_STATE_DISABLE, /* link always down */ -}; - -#define NIC_CVLAN_INSERT_ENABLE 0x1 -#define NIC_QINQ_INSERT_ENABLE 0X3 -static int spnic_set_vlan_ctx(struct spnic_nic_cfg *nic_cfg, u16 func_id, - u16 vlan_tag, u16 q_id, bool add) -{ - struct nic_vlan_ctx *vlan_ctx = NULL; - struct sphw_cmd_buf *cmd_buf = NULL; - u64 out_param = 0; - int err; - - cmd_buf = sphw_alloc_cmd_buf(nic_cfg->hwdev); - if (!cmd_buf) { - nic_err(nic_cfg->dev_hdl, "Failed to allocate cmd buf\n"); - return -ENOMEM; - } - - cmd_buf->size = sizeof(struct nic_vlan_ctx); - vlan_ctx = (struct nic_vlan_ctx *)cmd_buf->buf; - - vlan_ctx->func_id = func_id; - vlan_ctx->qid = q_id; - vlan_ctx->vlan_tag = vlan_tag; - vlan_ctx->vlan_sel = 0; /* TPID0 in IPSU */ - vlan_ctx->vlan_mode = add ? - NIC_QINQ_INSERT_ENABLE : NIC_CVLAN_INSERT_ENABLE; - - sphw_cpu_to_be32(vlan_ctx, sizeof(struct nic_vlan_ctx)); - - err = sphw_cmdq_direct_resp(nic_cfg->hwdev, SPHW_MOD_L2NIC, SPNIC_UCODE_CMD_MODIFY_VLAN_CTX, - cmd_buf, &out_param, 0, SPHW_CHANNEL_NIC); - - sphw_free_cmd_buf(nic_cfg->hwdev, cmd_buf); - - if (err || out_param != 0) { - nic_err(nic_cfg->dev_hdl, "Failed to set vlan context, err: %d, out_param: 0x%llx\n", - err, out_param); - return -EFAULT; - } - - return err; -} - -int spnic_cfg_vf_vlan(struct spnic_nic_cfg *nic_cfg, u8 opcode, u16 vid, u8 qos, int vf_id) -{ - struct spnic_cmd_vf_vlan_config vf_vlan; - u16 out_size = sizeof(vf_vlan); - u16 glb_func_id; - int err; - u16 vlan_tag; - - /* VLAN 0 is a special case, don't allow it to be removed */ - if (!vid && opcode == SPNIC_CMD_OP_DEL) - return 0; - - memset(&vf_vlan, 0, sizeof(vf_vlan)); - - vf_vlan.opcode = opcode; - vf_vlan.func_id = sphw_glb_pf_vf_offset(nic_cfg->hwdev) + (u16)vf_id; - vf_vlan.vlan_id = vid; - vf_vlan.qos = qos; - - err = l2nic_msg_to_mgmt_sync(nic_cfg->hwdev, SPNIC_NIC_CMD_CFG_VF_VLAN, - &vf_vlan, sizeof(vf_vlan), &vf_vlan, &out_size); - if (err || !out_size || vf_vlan.msg_head.status) { - nic_err(nic_cfg->dev_hdl, "Failed to set VF %d vlan, err: %d, status: 0x%x,out size: 0x%x\n", - HW_VF_ID_TO_OS(vf_id), err, vf_vlan.msg_head.status, out_size); - return -EFAULT; - } - - vlan_tag = vid + (u16)(qos << VLAN_PRIO_SHIFT); - - glb_func_id = sphw_glb_pf_vf_offset(nic_cfg->hwdev) + (u16)vf_id; - err = spnic_set_vlan_ctx(nic_cfg, glb_func_id, vlan_tag, NIC_CONFIG_ALL_QUEUE_VLAN_CTX, - opcode == SPNIC_CMD_OP_ADD); - if (err) { - nic_err(nic_cfg->dev_hdl, "Failed to set VF %d vlan ctx, err: %d\n", - HW_VF_ID_TO_OS(vf_id), err); - - /* rollback vlan config */ - if (opcode == SPNIC_CMD_OP_DEL) - vf_vlan.opcode = SPNIC_CMD_OP_ADD; - else - vf_vlan.opcode = SPNIC_CMD_OP_DEL; - l2nic_msg_to_mgmt_sync(nic_cfg->hwdev, SPNIC_NIC_CMD_CFG_VF_VLAN, &vf_vlan, - sizeof(vf_vlan), &vf_vlan, &out_size); - return err; - } - - return 0; -} - -/* this function just be called by spnic_ndo_set_vf_mac, - * others are not permitted. - */ -int spnic_set_vf_mac(void *hwdev, int vf, unsigned char *mac_addr) -{ - struct vf_data_storage *vf_info; - struct spnic_nic_cfg *nic_cfg; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - vf_info = nic_cfg->vf_infos + HW_VF_ID_TO_OS(vf); - - /* duplicate request, so just return success */ - if (ether_addr_equal(vf_info->user_mac_addr, mac_addr)) - return 0; - - ether_addr_copy(vf_info->user_mac_addr, mac_addr); - - return 0; -} - -int spnic_add_vf_vlan(void *hwdev, int vf_id, u16 vlan, u8 qos) -{ - struct spnic_nic_cfg *nic_cfg; - int err; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - err = spnic_cfg_vf_vlan(nic_cfg, SPNIC_CMD_OP_ADD, vlan, qos, vf_id); - if (err) - return err; - - nic_cfg->vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_vlan = vlan; - nic_cfg->vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_qos = qos; - - nic_info(nic_cfg->dev_hdl, "Setting VLAN %u, QOS 0x%x on VF %d\n", - vlan, qos, HW_VF_ID_TO_OS(vf_id)); - - return 0; -} - -int spnic_kill_vf_vlan(void *hwdev, int vf_id) -{ - struct vf_data_storage *vf_infos; - struct spnic_nic_cfg *nic_cfg; - int err; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - vf_infos = nic_cfg->vf_infos; - - err = spnic_cfg_vf_vlan(nic_cfg, SPNIC_CMD_OP_DEL, vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_vlan, - vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_qos, vf_id); - if (err) - return err; - - nic_info(nic_cfg->dev_hdl, "Remove VLAN %u on VF %d\n", - vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_vlan, HW_VF_ID_TO_OS(vf_id)); - - vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_vlan = 0; - vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_qos = 0; - - return 0; -} - -u16 spnic_vf_info_vlanprio(void *hwdev, int vf_id) -{ - struct spnic_nic_cfg *nic_cfg; - u16 pf_vlan, vlanprio; - u8 pf_qos; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - pf_vlan = nic_cfg->vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_vlan; - pf_qos = nic_cfg->vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_qos; - vlanprio = (u16)(pf_vlan | pf_qos << SPNIC_VLAN_PRIORITY_SHIFT); - - return vlanprio; -} - -int spnic_set_vf_link_state(void *hwdev, u16 vf_id, int link) -{ - struct spnic_nic_cfg *nic_cfg = - sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - struct vf_data_storage *vf_infos = nic_cfg->vf_infos; - u8 link_status = 0; - - switch (link) { - case SPNIC_IFLA_VF_LINK_STATE_AUTO: - vf_infos[HW_VF_ID_TO_OS(vf_id)].link_forced = false; - vf_infos[HW_VF_ID_TO_OS(vf_id)].link_up = nic_cfg->link_status ? true : false; - link_status = nic_cfg->link_status; - break; - case SPNIC_IFLA_VF_LINK_STATE_ENABLE: - vf_infos[HW_VF_ID_TO_OS(vf_id)].link_forced = true; - vf_infos[HW_VF_ID_TO_OS(vf_id)].link_up = true; - link_status = SPNIC_LINK_UP; - break; - case SPNIC_IFLA_VF_LINK_STATE_DISABLE: - vf_infos[HW_VF_ID_TO_OS(vf_id)].link_forced = true; - vf_infos[HW_VF_ID_TO_OS(vf_id)].link_up = false; - link_status = SPNIC_LINK_DOWN; - break; - default: - return -EINVAL; - } - - /* Notify the VF of its new link state */ - spnic_notify_vf_link_status(nic_cfg, vf_id, link_status); - - return 0; -} - -int spnic_set_vf_spoofchk(void *hwdev, u16 vf_id, bool spoofchk) -{ - struct spnic_cmd_spoofchk_set spoofchk_cfg; - struct vf_data_storage *vf_infos = NULL; - u16 out_size = sizeof(spoofchk_cfg); - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - if (!hwdev) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - vf_infos = nic_cfg->vf_infos; - - memset(&spoofchk_cfg, 0, sizeof(spoofchk_cfg)); - - spoofchk_cfg.func_id = sphw_glb_pf_vf_offset(hwdev) + vf_id; - spoofchk_cfg.state = spoofchk ? 1 : 0; - err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_NIC_CMD_SET_SPOOPCHK_STATE, - &spoofchk_cfg, sizeof(spoofchk_cfg), &spoofchk_cfg, &out_size); - if (err || !out_size || spoofchk_cfg.msg_head.status) { - nic_err(nic_cfg->dev_hdl, "Failed to set VF(%d) spoofchk, err: %d, status: 0x%x, out size: 0x%x\n", - HW_VF_ID_TO_OS(vf_id), err, spoofchk_cfg.msg_head.status, out_size); - err = -EINVAL; - } - - vf_infos[HW_VF_ID_TO_OS(vf_id)].spoofchk = spoofchk; - - return err; -} - -bool spnic_vf_info_spoofchk(void *hwdev, int vf_id) -{ - struct spnic_nic_cfg *nic_cfg; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - return nic_cfg->vf_infos[HW_VF_ID_TO_OS(vf_id)].spoofchk; -} - -int spnic_set_vf_trust(void *hwdev, u16 vf_id, bool trust) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - - if (!hwdev) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - if (vf_id > nic_cfg->max_vfs) - return -EINVAL; - - nic_cfg->vf_infos[HW_VF_ID_TO_OS(vf_id)].trust = trust; - - return 0; -} - -bool spnic_get_vf_trust(void *hwdev, int vf_id) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - - if (!hwdev) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - if (vf_id > nic_cfg->max_vfs) - return -EINVAL; - - return nic_cfg->vf_infos[HW_VF_ID_TO_OS(vf_id)].trust; -} - -static int spnic_cfg_vf_qps(struct spnic_nic_cfg *nic_cfg, u8 opcode, u16 vf_id, u16 num_qps) -{ - struct spnic_cmd_cfg_qps qps_info; - u16 out_size = sizeof(qps_info); - int err; - - memset(&qps_info, 0, sizeof(qps_info)); - - qps_info.func_id = sphw_glb_pf_vf_offset(nic_cfg->hwdev) + vf_id; - qps_info.opcode = opcode; - qps_info.num_qps = num_qps; - err = l2nic_msg_to_mgmt_sync(nic_cfg->hwdev, SPNIC_NIC_CMD_CFG_FLEX_QUEUE, &qps_info, - sizeof(qps_info), &qps_info, &out_size); - if (err || !out_size || qps_info.msg_head.status) { - nic_err(nic_cfg->dev_hdl, "Failed to %s VF(%d) qps, err: %d, status: 0x%x, out size: 0x%x\n", - opcode == SPNIC_CMD_OP_ALLOC ? "alloc" : "free", - HW_VF_ID_TO_OS(vf_id), err, qps_info.msg_head.status, out_size); - return -EFAULT; - } - - return 0; -} - -int spnic_alloc_vf_qps(void *hwdev, u16 vf_id, u16 num_qps) -{ - struct vf_data_storage *vf_infos = NULL; - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - if (!hwdev) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - if (vf_id > nic_cfg->max_vfs) - return -EINVAL; - - err = spnic_cfg_vf_qps(nic_cfg, SPNIC_CMD_OP_ALLOC, vf_id, num_qps); - if (err) - return err; - - vf_infos = nic_cfg->vf_infos; - vf_infos[HW_VF_ID_TO_OS(vf_id)].num_qps = num_qps; - - return 0; -} - -int spnic_free_vf_qps(void *hwdev, u16 vf_id) -{ - struct vf_data_storage *vf_infos = NULL; - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - if (!hwdev) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - if (vf_id > nic_cfg->max_vfs) - return -EINVAL; - - vf_infos = nic_cfg->vf_infos; - err = spnic_cfg_vf_qps(nic_cfg, SPNIC_CMD_OP_FREE, vf_id, - vf_infos[HW_VF_ID_TO_OS(vf_id)].num_qps); - if (err) - return err; - - vf_infos[HW_VF_ID_TO_OS(vf_id)].num_qps = 0; - - return 0; -} - -static int spnic_set_vf_tx_rate_max_min(struct spnic_nic_cfg *nic_cfg, u16 vf_id, - u32 max_rate, u32 min_rate) -{ - struct spnic_cmd_tx_rate_cfg rate_cfg; - u16 out_size = sizeof(rate_cfg); - int err; - - memset(&rate_cfg, 0, sizeof(rate_cfg)); - - rate_cfg.func_id = sphw_glb_pf_vf_offset(nic_cfg->hwdev) + vf_id; - rate_cfg.max_rate = max_rate; - rate_cfg.min_rate = min_rate; - err = l2nic_msg_to_mgmt_sync(nic_cfg->hwdev, SPNIC_NIC_CMD_SET_MAX_MIN_RATE, - &rate_cfg, sizeof(rate_cfg), &rate_cfg, &out_size); - if (rate_cfg.msg_head.status || err || !out_size) { - nic_err(nic_cfg->dev_hdl, "Failed to set VF %d max rate %u, min rate %u, err: %d, status: 0x%x, out size: 0x%x\n", - HW_VF_ID_TO_OS(vf_id), max_rate, min_rate, err, - rate_cfg.msg_head.status, out_size); - return -EIO; - } - - return 0; -} - -int spnic_set_vf_tx_rate(void *hwdev, u16 vf_id, u32 max_rate, u32 min_rate) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - err = spnic_set_vf_tx_rate_max_min(nic_cfg, vf_id, max_rate, min_rate); - if (err) - return err; - - nic_cfg->vf_infos[HW_VF_ID_TO_OS(vf_id)].max_rate = max_rate; - nic_cfg->vf_infos[HW_VF_ID_TO_OS(vf_id)].min_rate = min_rate; - - return 0; -} - -void spnic_get_vf_config(void *hwdev, u16 vf_id, struct ifla_vf_info *ivi) -{ - struct vf_data_storage *vfinfo; - struct spnic_nic_cfg *nic_cfg; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - vfinfo = nic_cfg->vf_infos + HW_VF_ID_TO_OS(vf_id); - - ivi->vf = HW_VF_ID_TO_OS(vf_id); - ether_addr_copy(ivi->mac, vfinfo->user_mac_addr); - ivi->vlan = vfinfo->pf_vlan; - ivi->qos = vfinfo->pf_qos; - - ivi->spoofchk = vfinfo->spoofchk; - - ivi->trusted = vfinfo->trust; - - ivi->max_tx_rate = vfinfo->max_rate; - ivi->min_tx_rate = vfinfo->min_rate; - - if (!vfinfo->link_forced) - ivi->linkstate = IFLA_VF_LINK_STATE_AUTO; - else if (vfinfo->link_up) - ivi->linkstate = IFLA_VF_LINK_STATE_ENABLE; - else - ivi->linkstate = IFLA_VF_LINK_STATE_DISABLE; -} - -static int spnic_init_vf_infos(struct spnic_nic_cfg *nic_cfg, u16 vf_id) -{ - struct vf_data_storage *vf_infos = nic_cfg->vf_infos; - u8 vf_link_state; - - if (set_vf_link_state > SPNIC_IFLA_VF_LINK_STATE_DISABLE) { - nic_warn(nic_cfg->dev_hdl, "Module Parameter set_vf_link_state value %u is out of range, resetting to %d\n", - set_vf_link_state, SPNIC_IFLA_VF_LINK_STATE_AUTO); - set_vf_link_state = SPNIC_IFLA_VF_LINK_STATE_AUTO; - } - - vf_link_state = set_vf_link_state; - - switch (vf_link_state) { - case SPNIC_IFLA_VF_LINK_STATE_AUTO: - vf_infos[vf_id].link_forced = false; - break; - case SPNIC_IFLA_VF_LINK_STATE_ENABLE: - vf_infos[vf_id].link_forced = true; - vf_infos[vf_id].link_up = true; - break; - case SPNIC_IFLA_VF_LINK_STATE_DISABLE: - vf_infos[vf_id].link_forced = true; - vf_infos[vf_id].link_up = false; - break; - default: - nic_err(nic_cfg->dev_hdl, "Input parameter set_vf_link_state error: %u\n", - vf_link_state); - return -EINVAL; - } - - return 0; -} - -static int vf_func_register(struct spnic_nic_cfg *nic_cfg) -{ - struct spnic_cmd_register_vf register_info; - u16 out_size = sizeof(register_info); - int err; - - err = sphw_register_vf_mbox_cb(nic_cfg->hwdev, SPHW_MOD_L2NIC, nic_cfg, - spnic_vf_event_handler); - if (err) - return err; - - err = sphw_register_vf_mbox_cb(nic_cfg->hwdev, SPHW_MOD_HILINK, nic_cfg, - spnic_vf_mag_event_handler); - if (err) - goto reg_hilink_err; - - memset(®ister_info, 0, sizeof(register_info)); - register_info.op_register = 1; - err = sphw_mbox_to_pf(nic_cfg->hwdev, SPHW_MOD_L2NIC, SPNIC_NIC_CMD_VF_REGISTER, - ®ister_info, sizeof(register_info), ®ister_info, &out_size, 0, - SPHW_CHANNEL_NIC); - if (err || !out_size || register_info.msg_head.status) { - nic_err(nic_cfg->dev_hdl, "Failed to register VF, err: %d, status: 0x%x, out size: 0x%x\n", - err, register_info.msg_head.status, out_size); - err = -EIO; - goto register_err; - } - - return 0; - -register_err: - sphw_unregister_vf_mbox_cb(nic_cfg->hwdev, SPHW_MOD_HILINK); - -reg_hilink_err: - sphw_unregister_vf_mbox_cb(nic_cfg->hwdev, SPHW_MOD_L2NIC); - - return err; -} - -static int pf_init_vf_infos(struct spnic_nic_cfg *nic_cfg) -{ - u32 size; - int err; - u16 i; - - err = sphw_register_mgmt_msg_cb(nic_cfg->hwdev, SPHW_MOD_L2NIC, nic_cfg, - spnic_pf_event_handler); - if (err) - return err; - - err = sphw_register_mgmt_msg_cb(nic_cfg->hwdev, SPHW_MOD_HILINK, nic_cfg, - spnic_pf_mag_event_handler); - if (err) - goto register_mag_mgmt_cb_err; - - nic_cfg->max_vfs = sphw_func_max_vf(nic_cfg->hwdev); - size = sizeof(*nic_cfg->vf_infos) * nic_cfg->max_vfs; - if (!size) - return 0; - - nic_cfg->vf_infos = kzalloc(size, GFP_KERNEL); - if (!nic_cfg->vf_infos) { - err = -ENOMEM; - goto alloc_vf_infos_err; - } - - for (i = 0; i < nic_cfg->max_vfs; i++) { - err = spnic_init_vf_infos(nic_cfg, i); - if (err) - goto init_vf_infos_err; - } - - err = sphw_register_pf_mbox_cb(nic_cfg->hwdev, SPHW_MOD_L2NIC, nic_cfg, - spnic_pf_mbox_handler); - if (err) - goto register_nic_mbox_cb_err; - - err = sphw_register_pf_mbox_cb(nic_cfg->hwdev, SPHW_MOD_HILINK, nic_cfg, - spnic_pf_mag_mbox_handler); - if (err) - goto register_mag_mbox_cb_err; - - return 0; - -register_mag_mbox_cb_err: - sphw_unregister_pf_mbox_cb(nic_cfg->hwdev, SPHW_MOD_L2NIC); - -register_nic_mbox_cb_err: -init_vf_infos_err: - kfree(nic_cfg->vf_infos); - -alloc_vf_infos_err: - sphw_unregister_mgmt_msg_cb(nic_cfg->hwdev, SPHW_MOD_HILINK); - -register_mag_mgmt_cb_err: - sphw_unregister_mgmt_msg_cb(nic_cfg->hwdev, SPHW_MOD_L2NIC); - - return err; -} - -int spnic_vf_func_init(struct spnic_nic_cfg *nic_cfg) -{ - if (sphw_func_type(nic_cfg->hwdev) == TYPE_VF) - return vf_func_register(nic_cfg); - - return pf_init_vf_infos(nic_cfg); -} - -void spnic_vf_func_free(struct spnic_nic_cfg *nic_cfg) -{ - struct spnic_cmd_register_vf unregister; - u16 out_size = sizeof(unregister); - int err; - - memset(&unregister, 0, sizeof(unregister)); - unregister.op_register = 0; - if (sphw_func_type(nic_cfg->hwdev) == TYPE_VF) { - err = sphw_mbox_to_pf(nic_cfg->hwdev, SPHW_MOD_L2NIC, SPNIC_NIC_CMD_VF_REGISTER, - &unregister, sizeof(unregister), &unregister, &out_size, 0, - SPHW_CHANNEL_NIC); - if (err || !out_size || unregister.msg_head.status) - nic_err(nic_cfg->dev_hdl, "Failed to unregister VF, err: %d, status: 0x%x, out_size: 0x%x\n", - err, unregister.msg_head.status, out_size); - - sphw_unregister_vf_mbox_cb(nic_cfg->hwdev, SPHW_MOD_L2NIC); - sphw_unregister_vf_mbox_cb(nic_cfg->hwdev, SPHW_MOD_HILINK); - } else { - if (nic_cfg->vf_infos) { - sphw_unregister_pf_mbox_cb(nic_cfg->hwdev, SPHW_MOD_L2NIC); - sphw_unregister_pf_mbox_cb(nic_cfg->hwdev, SPHW_MOD_HILINK); - spnic_clear_vfs_info(nic_cfg->hwdev); - kfree(nic_cfg->vf_infos); - } - - sphw_unregister_mgmt_msg_cb(nic_cfg->hwdev, SPHW_MOD_L2NIC); - sphw_unregister_mgmt_msg_cb(nic_cfg->hwdev, SPHW_MOD_HILINK); - } -} - -static void clear_vf_infos(void *hwdev, u16 vf_id) -{ - struct vf_data_storage *vf_infos; - struct spnic_nic_cfg *nic_cfg; - u16 func_id; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - func_id = sphw_glb_pf_vf_offset(hwdev) + vf_id; - vf_infos = nic_cfg->vf_infos + HW_VF_ID_TO_OS(vf_id); - if (vf_infos->use_specified_mac) - spnic_del_mac(hwdev, vf_infos->drv_mac_addr, vf_infos->pf_vlan, - func_id, SPHW_CHANNEL_NIC); - - if (spnic_vf_info_vlanprio(hwdev, vf_id)) - spnic_kill_vf_vlan(hwdev, vf_id); - - if (vf_infos->max_rate) - spnic_set_vf_tx_rate(hwdev, vf_id, 0, 0); - - if (vf_infos->spoofchk) - spnic_set_vf_spoofchk(hwdev, vf_id, false); - - if (vf_infos->trust) - spnic_set_vf_trust(hwdev, vf_id, false); - - memset(vf_infos, 0, sizeof(*vf_infos)); - /* set vf_infos to default */ - spnic_init_vf_infos(nic_cfg, HW_VF_ID_TO_OS(vf_id)); -} - -void spnic_clear_vfs_info(void *hwdev) -{ - struct spnic_nic_cfg *nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - u16 i; - - for (i = 0; i < nic_cfg->max_vfs; i++) - clear_vf_infos(hwdev, OS_VF_ID_TO_HW(i)); -} diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_nic_cmd.h b/drivers/net/ethernet/ramaxel/spnic/spnic_nic_cmd.h deleted file mode 100644 index 689e84d90e97..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_nic_cmd.h +++ /dev/null @@ -1,105 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPNIC_NIC_CMD_H -#define SPNIC_NIC_CMD_H - -/* Commands between NIC to MPU - */ -enum spnic_nic_cmd { - SPNIC_NIC_CMD_VF_REGISTER = 0, /* only for PFD and VFD */ - - /* FUNC CFG */ - SPNIC_NIC_CMD_SET_FUNC_TBL = 5, - SPNIC_NIC_CMD_SET_VPORT_ENABLE, - SPNIC_NIC_CMD_SET_RX_MODE, - SPNIC_NIC_CMD_SQ_CI_ATTR_SET, - SPNIC_NIC_CMD_GET_VPORT_STAT, - SPNIC_NIC_CMD_CLEAN_VPORT_STAT, - SPNIC_NIC_CMD_CLEAR_QP_RESOURCE, - SPNIC_NIC_CMD_CFG_FLEX_QUEUE, - /* LRO CFG */ - SPNIC_NIC_CMD_CFG_RX_LRO, - SPNIC_NIC_CMD_CFG_LRO_TIMER, - SPNIC_NIC_CMD_FEATURE_NEGO, - - /* MAC & VLAN CFG */ - SPNIC_NIC_CMD_GET_MAC = 20, - SPNIC_NIC_CMD_SET_MAC, - SPNIC_NIC_CMD_DEL_MAC, - SPNIC_NIC_CMD_UPDATE_MAC, - SPNIC_NIC_CMD_GET_ALL_DEFAULT_MAC, - - SPNIC_NIC_CMD_CFG_FUNC_VLAN, - SPNIC_NIC_CMD_SET_VLAN_FILTER_EN, - SPNIC_NIC_CMD_SET_RX_VLAN_OFFLOAD, - - /* SR-IOV */ - SPNIC_NIC_CMD_CFG_VF_VLAN = 40, - SPNIC_NIC_CMD_SET_SPOOPCHK_STATE, - /* RATE LIMIT */ - SPNIC_NIC_CMD_SET_MAX_MIN_RATE, - - /* RSS CFG */ - SPNIC_NIC_CMD_RSS_CFG = 60, - SPNIC_NIC_CMD_RSS_TEMP_MGR, - SPNIC_NIC_CMD_GET_RSS_CTX_TBL, - SPNIC_NIC_CMD_CFG_RSS_HASH_KEY, - SPNIC_NIC_CMD_CFG_RSS_HASH_ENGINE, - SPNIC_NIC_CMD_GET_INDIR_TBL, - - /* DPI/FDIR */ - SPNIC_NIC_CMD_ADD_TC_FLOW = 80, - SPNIC_NIC_CMD_DEL_TC_FLOW, - SPNIC_NIC_CMD_GET_TC_FLOW, - SPNIC_NIC_CMD_FLUSH_TCAM, - SPNIC_NIC_CMD_CFG_TCAM_BLOCK, - SPNIC_NIC_CMD_ENABLE_TCAM, - SPNIC_NIC_CMD_GET_TCAM_BLOCK, - SPNIC_NIC_CMD_CFG_DPI_TABLE_ID, - - /* PORT CFG */ - SPNIC_NIC_CMD_SET_PORT_ENABLE = 100, - SPNIC_NIC_CMD_CFG_PAUSE_INFO, - - SPNIC_NIC_CMD_SET_PORT_CAR, - SPNIC_NIC_CMD_SET_ER_DROP_PKT, - - SPNIC_NIC_CMD_VF_COS, - SPNIC_NIC_CMD_SETUP_COS_MAPPING, - SPNIC_NIC_CMD_SET_ETS, - SPNIC_NIC_CMD_SET_PFC, - - SPNIC_NIC_CMD_TX_PAUSE_EXCP_NOTICE = 118, - SPNIC_NIC_CMD_INQUIRT_PAUSE_CFG = 119, - - /* MISC */ - SPNIC_NIC_CMD_BIOS_CFG = 120, - SPNIC_NIC_CMD_SET_FIRMWARE_CUSTOM_PACKETS_MSG, - - /* DFX */ - SPNIC_NIC_CMD_GET_SM_TABLE = 140, - SPNIC_NIC_CMD_RD_LINE_TBL, - - SPNIC_NIC_CMD_SET_VHD_CFG = 161, - - SPNIC_NIC_CMD_MAX = 256, -}; - -/* NIC CMDQ MODE */ -enum spnic_ucode_cmd { - SPNIC_UCODE_CMD_MODIFY_QUEUE_CTX = 0, - SPNIC_UCODE_CMD_CLEAN_QUEUE_CONTEXT, - SPNIC_UCODE_CMD_ARM_SQ, - SPNIC_UCODE_CMD_ARM_RQ, - SPNIC_UCODE_CMD_SET_RSS_INDIR_TABLE, - SPNIC_UCODE_CMD_SET_RSS_CONTEXT_TABLE, - SPNIC_UCODE_CMD_GET_RSS_INDIR_TABLE, - SPNIC_UCODE_CMD_GET_RSS_CONTEXT_TABLE, - SPNIC_UCODE_CMD_SET_IQ_ENABLE, - SPNIC_UCODE_CMD_SET_RQ_FLUSH = 10, - SPNIC_UCODE_CMD_MODIFY_VLAN_CTX, - SPNIC_UCODE_CMD_DPI_HASH_TABLE, -}; - -#endif /* SPNIC_NIC_CMD_H */ diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_nic_dbg.c b/drivers/net/ethernet/ramaxel/spnic/spnic_nic_dbg.c deleted file mode 100644 index 08fe958a6d00..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_nic_dbg.c +++ /dev/null @@ -1,151 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [NIC]" fmt - -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/types.h> - -#include "sphw_crm.h" -#include "sphw_hw.h" -#include "sphw_mt.h" -#include "spnic_nic_qp.h" -#include "spnic_nic_io.h" -#include "spnic_nic_cfg.h" -#include "spnic_nic.h" - -int spnic_dbg_get_wqe_info(void *hwdev, u16 q_id, u16 idx, u16 wqebb_cnt, - u8 *wqe, u16 *wqe_size, enum spnic_queue_type q_type) -{ - struct spnic_io_queue *queue = NULL; - struct spnic_nic_cfg *nic_cfg = NULL; - void *src_wqebb = NULL; - u32 i, offset; - - if (!hwdev) { - pr_err("hwdev is NULL.\n"); - return -EINVAL; - } - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - if (q_id >= nic_cfg->num_qps) { - pr_err("q_id[%u] > num_qps_cfg[%u].\n", q_id, nic_cfg->num_qps); - return -EINVAL; - } - - queue = (q_type == SPNIC_SQ) ? &nic_cfg->sq[q_id] : &nic_cfg->rq[q_id]; - - if ((idx + wqebb_cnt) > queue->wq.q_depth) { - pr_err("(idx[%u] + idx[%u]) > q_depth[%u].\n", - idx, wqebb_cnt, queue->wq.q_depth); - return -EINVAL; - } - - if (*wqe_size != (queue->wq.wqebb_size * wqebb_cnt)) { - pr_err("Unexpect out buf size from user :%u, expect: %d\n", - *wqe_size, (queue->wq.wqebb_size * wqebb_cnt)); - return -EINVAL; - } - - for (i = 0; i < wqebb_cnt; i++) { - src_wqebb = sphw_wq_wqebb_addr(&queue->wq, WQ_MASK_IDX(&queue->wq, idx + i)); - offset = queue->wq.wqebb_size * i; - memcpy(wqe + offset, src_wqebb, queue->wq.wqebb_size); - } - - return 0; -} - -int spnic_dbg_get_sq_info(void *hwdev, u16 q_id, struct nic_sq_info *sq_info, u32 msg_size) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - struct spnic_io_queue *sq = NULL; - - if (!hwdev || !sq_info) { - pr_err("hwdev or sq_info is NULL.\n"); - return -EINVAL; - } - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - if (q_id >= nic_cfg->num_qps) { - nic_err(nic_cfg->dev_hdl, "Input queue id(%u) is larger than the actual queue number\n", - q_id); - return -EINVAL; - } - - if (msg_size != sizeof(*sq_info)) { - nic_err(nic_cfg->dev_hdl, "Unexpect out buf size from user :%u, expect: %lu\n", - msg_size, sizeof(*sq_info)); - return -EINVAL; - } - - sq = &nic_cfg->sq[q_id]; - - sq_info->q_id = q_id; - sq_info->pi = spnic_get_sq_local_pi(sq); - sq_info->ci = spnic_get_sq_local_ci(sq); - sq_info->fi = spnic_get_sq_hw_ci(sq); - sq_info->q_depth = sq->wq.q_depth; - sq_info->wqebb_size = sq->wq.wqebb_size; - - sq_info->ci_addr = sq->tx.cons_idx_addr; - - sq_info->cla_addr = sq->wq.wq_block_paddr; - sq_info->slq_handle = sq; - - sq_info->doorbell.map_addr = (u64 *)sq->db_addr; - - return 0; -} - -int spnic_dbg_get_rq_info(void *hwdev, u16 q_id, struct nic_rq_info *rq_info, u32 msg_size) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - struct spnic_io_queue *rq = NULL; - - if (!hwdev || !rq_info) { - pr_err("hwdev or rq_info is NULL.\n"); - return -EINVAL; - } - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - if (q_id >= nic_cfg->num_qps) { - nic_err(nic_cfg->dev_hdl, "Input queue id(%u) is larger than the actual queue number\n", - q_id); - return -EINVAL; - } - - if (msg_size != sizeof(*rq_info)) { - nic_err(nic_cfg->dev_hdl, "Unexpect out buf size from user: %u, expect: %lu\n", - msg_size, sizeof(*rq_info)); - return -EINVAL; - } - - rq = &nic_cfg->rq[q_id]; - - rq_info->q_id = q_id; - - rq_info->hw_pi = cpu_to_be16(*rq->rx.pi_virt_addr); - rq_info->ci = spnic_get_rq_local_ci(rq); - - rq_info->sw_pi = 0; - - rq_info->wqebb_size = rq->wq.wqebb_size; - rq_info->q_depth = (u16)rq->wq.q_depth; - - rq_info->buf_len = nic_cfg->rx_buff_len; - - rq_info->slq_handle = rq; - - rq_info->ci_wqe_page_addr = sphw_wq_get_first_wqe_page_addr(&rq->wq); - rq_info->ci_cla_tbl_addr = rq->wq.wq_block_paddr; - - rq_info->msix_idx = rq->msix_entry_idx; - rq_info->msix_vector = 0; - - return 0; -} diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_nic_dbg.h b/drivers/net/ethernet/ramaxel/spnic/spnic_nic_dbg.h deleted file mode 100644 index d86c65ed5f4f..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_nic_dbg.h +++ /dev/null @@ -1,16 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPNIC_NIC_DBG_H -#define SPNIC_NIC_DBG_H - -#include "spnic_nic_io.h" - -int spnic_dbg_get_sq_info(void *hwdev, u16 q_id, struct nic_sq_info *sq_info, u32 msg_size); - -int spnic_dbg_get_rq_info(void *hwdev, u16 q_id, struct nic_rq_info *rq_info, u32 msg_size); - -int spnic_dbg_get_wqe_info(void *hwdev, u16 q_id, u16 idx, u16 wqebb_cnt, - u8 *wqe, u16 *wqe_size, enum spnic_queue_type q_type); - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_nic_dev.h b/drivers/net/ethernet/ramaxel/spnic/spnic_nic_dev.h deleted file mode 100644 index 8a0708fda19a..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_nic_dev.h +++ /dev/null @@ -1,354 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPNIC_NIC_DEV_H -#define SPNIC_NIC_DEV_H - -#include <linux/netdevice.h> -#include <linux/semaphore.h> -#include <linux/types.h> -#include <linux/bitops.h> - -#include "spnic_nic_io.h" -#include "spnic_nic_cfg.h" -#include "spnic_tx.h" -#include "spnic_rx.h" -#include "spnic_dcb.h" - -#define SPNIC_NIC_DRV_NAME "spnic" -#define SPNIC_DRV_VERSION "B090" -#define SPNIC_DRV_DESC "Ramaxel(R) Network Interface Card Driver" - -#define SPNIC_FUNC_IS_VF(hwdev) (sphw_func_type(hwdev) == TYPE_VF) - -#define SPNIC_AVG_PKT_SMALL 256U -#define SPNIC_MODERATONE_DELAY HZ - -#define LP_PKT_CNT 64 - -enum spnic_flags { - SPNIC_INTF_UP, - SPNIC_MAC_FILTER_CHANGED, - SPNIC_LP_TEST, - SPNIC_RSS_ENABLE, - SPNIC_DCB_ENABLE, - SPNIC_SAME_RXTX, - SPNIC_INTR_ADAPT, - SPNIC_UPDATE_MAC_FILTER, - SPNIC_CHANGE_RES_INVALID, - SPNIC_RSS_DEFAULT_INDIR, -}; - -#define SPHW_CHANNEL_RES_VALID(nic_dev) \ - (test_bit(SPNIC_INTF_UP, &(nic_dev)->flags) && \ - !test_bit(SPNIC_CHANGE_RES_INVALID, &(nic_dev)->flags)) - -#define RX_BUFF_NUM_PER_PAGE 2 - -#define VLAN_BITMAP_BYTE_SIZE(nic_dev) (sizeof(*(nic_dev)->vlan_bitmap)) -#define VLAN_BITMAP_BITS_SIZE(nic_dev) (VLAN_BITMAP_BYTE_SIZE(nic_dev) * 8) -#define VLAN_NUM_BITMAPS(nic_dev) (VLAN_N_VID / \ - VLAN_BITMAP_BITS_SIZE(nic_dev)) -#define VLAN_BITMAP_SIZE(nic_dev) (VLAN_N_VID / \ - VLAN_BITMAP_BYTE_SIZE(nic_dev)) -#define VID_LINE(nic_dev, vid) ((vid) / VLAN_BITMAP_BITS_SIZE(nic_dev)) -#define VID_COL(nic_dev, vid) ((vid) & (VLAN_BITMAP_BITS_SIZE(nic_dev) - 1)) - -#define SPNIC_DRV_FEATURE NIC_F_ALL_MASK - -enum spnic_event_work_flags { - EVENT_WORK_TX_TIMEOUT, -}; - -enum spnic_rx_mode_state { - SPNIC_HW_PROMISC_ON, - SPNIC_HW_ALLMULTI_ON, - SPNIC_PROMISC_FORCE_ON, - SPNIC_ALLMULTI_FORCE_ON, -}; - -enum mac_filter_state { - SPNIC_MAC_WAIT_HW_SYNC, - SPNIC_MAC_HW_SYNCED, - SPNIC_MAC_WAIT_HW_UNSYNC, - SPNIC_MAC_HW_UNSYNCED, -}; - -struct spnic_mac_filter { - struct list_head list; - u8 addr[ETH_ALEN]; - unsigned long state; -}; - -struct spnic_irq { - struct net_device *netdev; - /* IRQ corresponding index number */ - u16 msix_entry_idx; - u32 irq_id; /* The IRQ number from OS */ - char irq_name[IFNAMSIZ + 16]; - struct napi_struct napi; - cpumask_t affinity_mask; - struct spnic_txq *txq; - struct spnic_rxq *rxq; -}; - -struct spnic_intr_coal_info { - u8 pending_limt; - u8 coalesce_timer_cfg; - u8 resend_timer_cfg; - - u64 pkt_rate_low; - u8 rx_usecs_low; - u8 rx_pending_limt_low; - u64 pkt_rate_high; - u8 rx_usecs_high; - u8 rx_pending_limt_high; - - u8 user_set_intr_coal_flag; -}; - -struct spnic_dyna_txrxq_params { - u16 num_qps; - u16 num_rss; - u16 rss_limit; - u8 num_tc; - u8 rsvd1; - u32 sq_depth; - u32 rq_depth; - - struct spnic_dyna_txq_res *txqs_res; - struct spnic_dyna_rxq_res *rxqs_res; - struct spnic_irq *irq_cfg; -}; - -#define SPNIC_NIC_STATS_INC(nic_dev, field) \ -do { \ - u64_stats_update_begin(&(nic_dev)->stats.syncp);\ - (nic_dev)->stats.field++; \ - u64_stats_update_end(&(nic_dev)->stats.syncp); \ -} while (0) - -struct spnic_nic_stats { - u64 netdev_tx_timeout; - - /* Subdivision statistics show in private tool */ - u64 tx_carrier_off_drop; - u64 tx_invalid_qid; - - struct u64_stats_sync syncp; -}; - -#define SPNIC_TCAM_DYNAMIC_BLOCK_SIZE 16 -#define SPNIC_MAX_TCAM_FILTERS 512 - -#define SPNIC_PKT_TCAM_DYNAMIC_INDEX_START(block_index) \ - (SPNIC_TCAM_DYNAMIC_BLOCK_SIZE * (block_index)) - -struct spnic_rx_flow_rule { - struct list_head rules; - int tot_num_rules; -}; - -struct spnic_tcam_dynamic_block { - struct list_head block_list; - u16 dynamic_block_id; - u16 dynamic_index_cnt; - u8 dynamic_index_used[SPNIC_TCAM_DYNAMIC_BLOCK_SIZE]; -}; - -struct spnic_tcam_dynamic_block_info { - struct list_head tcam_dynamic_list; - u16 dynamic_block_cnt; -}; - -struct spnic_tcam_filter { - struct list_head tcam_filter_list; - u16 dynamic_block_id; - u16 index; - struct tag_tcam_key tcam_key; - u16 queue; -}; - -/* function level struct info */ -struct spnic_tcam_info { - u16 tcam_rule_nums; - struct list_head tcam_list; - struct spnic_tcam_dynamic_block_info tcam_dynamic_info; -}; - -struct spnic_nic_dev { - struct pci_dev *pdev; - struct net_device *netdev; - void *hwdev; - - int poll_weight; - - unsigned long *vlan_bitmap; - - u16 max_qps; - - u32 msg_enable; - unsigned long flags; - - u32 lro_replenish_thld; - u32 dma_rx_buff_size; - u16 rx_buff_len; - u32 page_order; - - /* Rss related varibles */ - u8 rss_hash_engine; - struct nic_rss_type rss_type; - u8 *rss_hkey; - /* hkey in big endian */ - u32 *rss_hkey_be; - u32 *rss_indir; - - u32 dcb_changes; - struct spnic_dcb_config hw_dcb_cfg; - struct spnic_dcb_config wanted_dcb_cfg; - unsigned long dcb_flags; - int disable_port_cnt; - /* lock for disable or enable traffic flow */ - struct semaphore dcb_sem; - - struct spnic_intr_coal_info *intr_coalesce; - unsigned long last_moder_jiffies; - u32 adaptive_rx_coal; - u8 intr_coal_set_flag; - - struct spnic_nic_stats stats; - - /* lock for nic resource */ - struct mutex nic_mutex; - bool force_port_disable; - struct semaphore port_state_sem; - u8 link_status; - - struct nic_service_cap nic_cap; - - struct spnic_txq *txqs; - struct spnic_rxq *rxqs; - struct spnic_dyna_txrxq_params q_params; - - u16 num_qp_irq; - struct irq_info *qps_irq_info; - - struct workqueue_struct *workq; - - struct work_struct rx_mode_work; - struct delayed_work moderation_task; - - struct list_head uc_filter_list; - struct list_head mc_filter_list; - unsigned long rx_mod_state; - int netdev_uc_cnt; - int netdev_mc_cnt; - - int lb_test_rx_idx; - int lb_pkt_len; - u8 *lb_test_rx_buf; - - struct spnic_tcam_info tcam; - struct spnic_rx_flow_rule rx_flow_rule; - - struct bpf_prog *xdp_prog; - - struct delayed_work periodic_work; - /* reference to enum spnic_event_work_flags */ - unsigned long event_flag; -}; - -#define IPSEC_CAP_IS_SUPPORT(nic_dev) ((nic_dev)->ipsec) - -#define spnic_msg(level, nic_dev, msglvl, format, arg...) \ -do { \ - if ((nic_dev)->netdev && (nic_dev)->netdev->reg_state \ - == NETREG_REGISTERED) \ - nicif_##level((nic_dev), msglvl, (nic_dev)->netdev, \ - format, ## arg); \ - else \ - nic_##level(&(nic_dev)->pdev->dev, \ - format, ## arg); \ -} while (0) - -#define spnic_info(nic_dev, msglvl, format, arg...) \ - spnic_msg(info, nic_dev, msglvl, format, ## arg) - -#define spnic_warn(nic_dev, msglvl, format, arg...) \ - spnic_msg(warn, nic_dev, msglvl, format, ## arg) - -#define spnic_err(nic_dev, msglvl, format, arg...) \ - spnic_msg(err, nic_dev, msglvl, format, ## arg) - -#define nicif_err(priv, type, dev, fmt, args...) \ - netif_level(err, priv, type, dev, "[NIC]" fmt, ##args) -#define nicif_warn(priv, type, dev, fmt, args...) \ - netif_level(warn, priv, type, dev, "[NIC]" fmt, ##args) -#define nicif_notice(priv, type, dev, fmt, args...) \ - netif_level(notice, priv, type, dev, "[NIC]" fmt, ##args) -#define nicif_info(priv, type, dev, fmt, args...) \ - netif_level(info, priv, type, dev, "[NIC]" fmt, ##args) -#define nicif_dbg(priv, type, dev, fmt, args...) \ - netif_level(dbg, priv, type, dev, "[NIC]" fmt, ##args) - -extern struct spnic_uld_info nic_uld_info; - -u32 spnic_get_io_stats_size(struct spnic_nic_dev *nic_dev); - -void spnic_get_io_stats(struct spnic_nic_dev *nic_dev, void *stats); - -int spnic_open(struct net_device *netdev); - -int spnic_close(struct net_device *netdev); - -void spnic_set_ethtool_ops(struct net_device *netdev); - -void spnicvf_set_ethtool_ops(struct net_device *netdev); - -int nic_ioctl(void *uld_dev, u32 cmd, const void *buf_in, - u32 in_size, void *buf_out, u32 *out_size); - -void spnic_update_num_qps(struct net_device *netdev); - -int spnic_qps_irq_init(struct spnic_nic_dev *nic_dev); - -void spnic_qps_irq_deinit(struct spnic_nic_dev *nic_dev); - -void spnic_set_netdev_ops(struct spnic_nic_dev *nic_dev); - -int spnic_set_hw_features(struct spnic_nic_dev *nic_dev); - -void spnic_set_rx_mode_work(struct work_struct *work); - -void spnic_clean_mac_list_filter(struct spnic_nic_dev *nic_dev); - -void spnic_get_strings(struct net_device *netdev, u32 stringset, u8 *data); - -void spnic_get_ethtool_stats(struct net_device *netdev, struct ethtool_stats *stats, u64 *data); - -int spnic_get_sset_count(struct net_device *netdev, int sset); - -int spnic_force_port_disable(struct spnic_nic_dev *nic_dev); - -int spnic_force_set_port_state(struct spnic_nic_dev *nic_dev, bool enable); - -int spnic_maybe_set_port_state(struct spnic_nic_dev *nic_dev, bool enable); - -int spnic_get_link_ksettings(struct net_device *netdev, - struct ethtool_link_ksettings *link_settings); -int spnic_set_link_ksettings(struct net_device *netdev, - const struct ethtool_link_ksettings *link_settings); - -void spnic_auto_moderation_work(struct work_struct *work); - -typedef void (*spnic_reopen_handler)(struct spnic_nic_dev *nic_dev, const void *priv_data); -int spnic_change_channel_settings(struct spnic_nic_dev *nic_dev, - struct spnic_dyna_txrxq_params *trxq_params, - spnic_reopen_handler reopen_handler, const void *priv_data); - -void spnic_link_status_change(struct spnic_nic_dev *nic_dev, bool status); - -bool spnic_is_xdp_enable(struct spnic_nic_dev *nic_dev); -int spnic_xdp_max_mtu(struct spnic_nic_dev *nic_dev); - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_nic_event.c b/drivers/net/ethernet/ramaxel/spnic/spnic_nic_event.c deleted file mode 100644 index 0e8a2c4a3961..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_nic_event.c +++ /dev/null @@ -1,506 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [NIC]" fmt - -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/etherdevice.h> -#include <linux/if_vlan.h> -#include <linux/ethtool.h> -#include <linux/kernel.h> -#include <linux/device.h> -#include <linux/pci.h> -#include <linux/netdevice.h> -#include <linux/module.h> - -#include "sphw_crm.h" -#include "sphw_hw.h" -#include "spnic_nic_io.h" -#include "spnic_nic_cfg.h" -#include "spnic_nic.h" -#include "spnic_nic_cmd.h" - -static int spnic_init_vf_config(struct spnic_nic_cfg *nic_cfg, u16 vf_id) -{ - struct vf_data_storage *vf_info; - u16 func_id; - int err = 0; - - vf_info = nic_cfg->vf_infos + HW_VF_ID_TO_OS(vf_id); - ether_addr_copy(vf_info->drv_mac_addr, vf_info->user_mac_addr); - if (!is_zero_ether_addr(vf_info->drv_mac_addr)) { - vf_info->use_specified_mac = true; - func_id = sphw_glb_pf_vf_offset(nic_cfg->hwdev) + vf_id; - - err = spnic_set_mac(nic_cfg->hwdev, vf_info->drv_mac_addr, - vf_info->pf_vlan, func_id, SPHW_CHANNEL_NIC); - if (err) { - nic_err(nic_cfg->dev_hdl, "Failed to set VF %d MAC\n", - HW_VF_ID_TO_OS(vf_id)); - return err; - } - } else { - vf_info->use_specified_mac = false; - } - - if (spnic_vf_info_vlanprio(nic_cfg->hwdev, vf_id)) { - err = spnic_cfg_vf_vlan(nic_cfg, SPNIC_CMD_OP_ADD, - vf_info->pf_vlan, vf_info->pf_qos, vf_id); - if (err) { - nic_err(nic_cfg->dev_hdl, "Failed to add VF %d VLAN_QOS\n", - HW_VF_ID_TO_OS(vf_id)); - return err; - } - } - - if (vf_info->max_rate) { - err = spnic_set_vf_tx_rate(nic_cfg->hwdev, vf_id, vf_info->max_rate, - vf_info->min_rate); - if (err) { - nic_err(nic_cfg->dev_hdl, "Failed to set VF %d max rate %u, min rate %u\n", - HW_VF_ID_TO_OS(vf_id), vf_info->max_rate, - vf_info->min_rate); - return err; - } - } - - return 0; -} - -static int register_vf_msg_handler(struct spnic_nic_cfg *nic_cfg, u16 vf_id) -{ - int err; - - if (vf_id > nic_cfg->max_vfs) { - nic_err(nic_cfg->dev_hdl, "Register VF id %d exceed limit[0-%d]\n", - HW_VF_ID_TO_OS(vf_id), HW_VF_ID_TO_OS(nic_cfg->max_vfs)); - return -EFAULT; - } - - err = spnic_init_vf_config(nic_cfg, vf_id); - if (err) - return err; - - nic_cfg->vf_infos[HW_VF_ID_TO_OS(vf_id)].registered = true; - - return 0; -} - -static int unregister_vf_msg_handler(struct spnic_nic_cfg *nic_cfg, u16 vf_id) -{ - struct vf_data_storage *vf_info = - nic_cfg->vf_infos + HW_VF_ID_TO_OS(vf_id); - struct spnic_port_mac_set mac_info; - u16 out_size = sizeof(mac_info); - int err; - - if (vf_id > nic_cfg->max_vfs) - return -EFAULT; - - vf_info->registered = false; - - memset(&mac_info, 0, sizeof(mac_info)); - mac_info.func_id = sphw_glb_pf_vf_offset(nic_cfg->hwdev) + (u16)vf_id; - mac_info.vlan_id = vf_info->pf_vlan; - ether_addr_copy(mac_info.mac, vf_info->drv_mac_addr); - - if (vf_info->use_specified_mac || vf_info->pf_vlan) { - err = l2nic_msg_to_mgmt_sync(nic_cfg->hwdev, SPNIC_NIC_CMD_DEL_MAC, - &mac_info, sizeof(mac_info), &mac_info, &out_size); - if (err || mac_info.msg_head.status || !out_size) { - nic_err(nic_cfg->dev_hdl, "Failed to delete VF %d MAC, err: %d, status: 0x%x, out size: 0x%x\n", - HW_VF_ID_TO_OS(vf_id), err, - mac_info.msg_head.status, out_size); - return -EFAULT; - } - } - - memset(vf_info->drv_mac_addr, 0, ETH_ALEN); - - return 0; -} - -static int spnic_register_vf_msg_handler(struct spnic_nic_cfg *nic_cfg, - u16 vf_id, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size) -{ - struct spnic_cmd_register_vf *register_vf = buf_in; - struct spnic_cmd_register_vf *register_info = buf_out; - int err; - - if (register_vf->op_register) - err = register_vf_msg_handler(nic_cfg, vf_id); - else - err = unregister_vf_msg_handler(nic_cfg, vf_id); - - if (err) - register_info->msg_head.status = EFAULT; - - *out_size = sizeof(*register_info); - - return 0; -} - -static int spnic_get_vf_cos_msg_handler(struct spnic_nic_cfg *nic_cfg, u16 vf_id, void *buf_in, - u16 in_size, void *buf_out, u16 *out_size) -{ - struct spnic_cmd_vf_dcb_state *dcb_state = buf_out; - - memcpy(&dcb_state->state, &nic_cfg->dcb_state, - sizeof(nic_cfg->dcb_state)); - - dcb_state->msg_head.status = 0; - *out_size = sizeof(*dcb_state); - return 0; -} - -static int spnic_get_vf_mac_msg_handler(struct spnic_nic_cfg *nic_cfg, u16 vf, - void *buf_in, u16 in_size, void *buf_out, u16 *out_size) -{ - struct vf_data_storage *vf_info = nic_cfg->vf_infos + HW_VF_ID_TO_OS(vf); - struct spnic_port_mac_set *mac_info = buf_out; - - int err; - - if (sphw_support_ovs(nic_cfg->hwdev, NULL)) { - err = l2nic_msg_to_mgmt_sync(nic_cfg->hwdev, SPNIC_NIC_CMD_GET_MAC, buf_in, - in_size, buf_out, out_size); - if (!err) { - if (is_zero_ether_addr(mac_info->mac)) - ether_addr_copy(mac_info->mac, vf_info->drv_mac_addr); - } - return err; - } - - ether_addr_copy(mac_info->mac, vf_info->drv_mac_addr); - mac_info->msg_head.status = 0; - *out_size = sizeof(*mac_info); - - return 0; -} - -static int spnic_set_vf_mac_msg_handler(struct spnic_nic_cfg *nic_cfg, u16 vf, - void *buf_in, u16 in_size, void *buf_out, u16 *out_size) -{ - struct vf_data_storage *vf_info = nic_cfg->vf_infos + HW_VF_ID_TO_OS(vf); - struct spnic_port_mac_set *mac_in = buf_in; - struct spnic_port_mac_set *mac_out = buf_out; - int err; - - if (vf_info->use_specified_mac && !vf_info->trust && - is_valid_ether_addr(mac_in->mac)) { - nic_warn(nic_cfg->dev_hdl, "PF has already set VF %d MAC address, and vf trust is off.\n", - HW_VF_ID_TO_OS(vf)); - mac_out->msg_head.status = SPNIC_PF_SET_VF_ALREADY; - *out_size = sizeof(*mac_out); - return 0; - } - - if (is_valid_ether_addr(mac_in->mac)) - mac_in->vlan_id = vf_info->pf_vlan; - - err = l2nic_msg_to_mgmt_sync(nic_cfg->hwdev, SPNIC_NIC_CMD_SET_MAC, - buf_in, in_size, buf_out, out_size); - if (err || !(*out_size)) { - nic_err(nic_cfg->dev_hdl, "Failed to set VF %d MAC address, err: %d,status: 0x%x, out size: 0x%x\n", - HW_VF_ID_TO_OS(vf), err, mac_out->msg_head.status, - *out_size); - return -EFAULT; - } - - if (is_valid_ether_addr(mac_in->mac) && !mac_out->msg_head.status) - ether_addr_copy(vf_info->drv_mac_addr, mac_in->mac); - - return err; -} - -static int spnic_del_vf_mac_msg_handler(struct spnic_nic_cfg *nic_cfg, u16 vf, - void *buf_in, u16 in_size, void *buf_out, u16 *out_size) -{ - struct vf_data_storage *vf_info = nic_cfg->vf_infos + HW_VF_ID_TO_OS(vf); - struct spnic_port_mac_set *mac_in = buf_in; - struct spnic_port_mac_set *mac_out = buf_out; - int err; - - if (vf_info->use_specified_mac && !vf_info->trust && - is_valid_ether_addr(mac_in->mac)) { - nic_warn(nic_cfg->dev_hdl, "PF has already set VF %d MAC address, and vf trust is off.\n", - HW_VF_ID_TO_OS(vf)); - mac_out->msg_head.status = SPNIC_PF_SET_VF_ALREADY; - *out_size = sizeof(*mac_out); - return 0; - } - - if (is_valid_ether_addr(mac_in->mac)) - mac_in->vlan_id = vf_info->pf_vlan; - - err = l2nic_msg_to_mgmt_sync(nic_cfg->hwdev, SPNIC_NIC_CMD_DEL_MAC, - buf_in, in_size, buf_out, out_size); - if (err || !(*out_size)) { - nic_err(nic_cfg->dev_hdl, "Failed to delete VF %d MAC, err: %d, status: 0x%x, out size: 0x%x\n", - HW_VF_ID_TO_OS(vf), err, mac_out->msg_head.status, - *out_size); - return -EFAULT; - } - - if (is_valid_ether_addr(mac_in->mac) && !mac_out->msg_head.status) - eth_zero_addr(vf_info->drv_mac_addr); - - return err; -} - -static int spnic_update_vf_mac_msg_handler(struct spnic_nic_cfg *nic_cfg, - u16 vf, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size) -{ - struct vf_data_storage *vf_info = nic_cfg->vf_infos + HW_VF_ID_TO_OS(vf); - struct spnic_port_mac_update *mac_in = buf_in; - struct spnic_port_mac_update *mac_out = buf_out; - int err; - - if (!is_valid_ether_addr(mac_in->new_mac)) { - nic_err(nic_cfg->dev_hdl, "Update VF MAC is invalid.\n"); - return -EINVAL; - } - - if (vf_info->use_specified_mac && !vf_info->trust) { - nic_warn(nic_cfg->dev_hdl, "PF has already set VF %d MAC address, and vf trust is off.\n", - HW_VF_ID_TO_OS(vf)); - mac_out->msg_head.status = SPNIC_PF_SET_VF_ALREADY; - *out_size = sizeof(*mac_out); - return 0; - } - - mac_in->vlan_id = vf_info->pf_vlan; - err = l2nic_msg_to_mgmt_sync(nic_cfg->hwdev, SPNIC_NIC_CMD_UPDATE_MAC, - buf_in, in_size, buf_out, out_size); - if (err || !(*out_size)) { - nic_warn(nic_cfg->dev_hdl, "Failed to update VF %d MAC, err: %d,status: 0x%x, out size: 0x%x\n", - HW_VF_ID_TO_OS(vf), err, mac_out->msg_head.status, - *out_size); - return -EFAULT; - } - - if (!mac_out->msg_head.status) - ether_addr_copy(vf_info->drv_mac_addr, mac_in->new_mac); - - return err; -} - -const struct vf_msg_handler vf_cmd_handler[] = { - { - .cmd = SPNIC_NIC_CMD_VF_REGISTER, - .handler = spnic_register_vf_msg_handler, - }, - - { - .cmd = SPNIC_NIC_CMD_GET_MAC, - .handler = spnic_get_vf_mac_msg_handler, - }, - - { - .cmd = SPNIC_NIC_CMD_SET_MAC, - .handler = spnic_set_vf_mac_msg_handler, - }, - - { - .cmd = SPNIC_NIC_CMD_DEL_MAC, - .handler = spnic_del_vf_mac_msg_handler, - }, - - { - .cmd = SPNIC_NIC_CMD_UPDATE_MAC, - .handler = spnic_update_vf_mac_msg_handler, - }, - - { - .cmd = SPNIC_NIC_CMD_VF_COS, - .handler = spnic_get_vf_cos_msg_handler - }, -}; - -static int _l2nic_msg_to_mgmt_sync(void *hwdev, u16 cmd, void *buf_in, - u16 in_size, void *buf_out, u16 *out_size, u16 channel) -{ - u32 i, cmd_cnt = ARRAY_LEN(vf_cmd_handler); - bool cmd_to_pf = false; - - if (sphw_func_type(hwdev) == TYPE_VF) { - for (i = 0; i < cmd_cnt; i++) { - if (cmd == vf_cmd_handler[i].cmd) - cmd_to_pf = true; - } - } - - if (cmd_to_pf) - return sphw_mbox_to_pf(hwdev, SPHW_MOD_L2NIC, cmd, buf_in, in_size, buf_out, - out_size, 0, channel); - - return sphw_msg_to_mgmt_sync(hwdev, SPHW_MOD_L2NIC, cmd, buf_in, in_size, buf_out, - out_size, 0, channel); -} - -int l2nic_msg_to_mgmt_sync(void *hwdev, u16 cmd, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size) -{ - return _l2nic_msg_to_mgmt_sync(hwdev, cmd, buf_in, in_size, buf_out, - out_size, SPHW_CHANNEL_NIC); -} - -int l2nic_msg_to_mgmt_sync_ch(void *hwdev, u16 cmd, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size, u16 channel) -{ - return _l2nic_msg_to_mgmt_sync(hwdev, cmd, buf_in, in_size, buf_out, out_size, channel); -} - -/* pf/ppf handler mbox msg from vf */ -int spnic_pf_mbox_handler(void *hwdev, void *pri_handle, - u16 vf_id, u16 cmd, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size) -{ - u32 index, cmd_size = ARRAY_LEN(vf_cmd_handler); - struct spnic_nic_cfg *nic_cfg = NULL; - - if (!hwdev) - return -EFAULT; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - for (index = 0; index < cmd_size; index++) { - if (cmd == vf_cmd_handler[index].cmd) - return vf_cmd_handler[index].handler(nic_cfg, vf_id, buf_in, in_size, - buf_out, out_size); - } - - nic_warn(nic_cfg->dev_hdl, "NO handler for nic cmd(%u) received from vf id: %u\n", - cmd, vf_id); - - return -EINVAL; -} - -void spnic_notify_dcb_state_event(struct spnic_nic_cfg *nic_cfg, struct spnic_dcb_state *dcb_state) -{ - struct sphw_event_info event_info = {0}; - - /* This is 8 user priority to cos mapping relationships */ - sdk_info(nic_cfg->dev_hdl, "DCB %s, default cos %u, up2cos %u%u%u%u%u%u%u%u\n", - dcb_state->dcb_on ? "on" : "off", dcb_state->default_cos, - dcb_state->up_cos[0], dcb_state->up_cos[1], - dcb_state->up_cos[2], dcb_state->up_cos[3], - dcb_state->up_cos[4], dcb_state->up_cos[5], - dcb_state->up_cos[6], dcb_state->up_cos[7]); - - /* Saved in sdk for statefull module */ - spnic_save_dcb_state(nic_cfg, dcb_state); - - event_info.type = SPHW_EVENT_DCB_STATE_CHANGE; - memcpy(&event_info.dcb_state, dcb_state, sizeof(event_info.dcb_state)); - - sphw_event_callback(nic_cfg->hwdev, &event_info); -} - -void dcb_state_event(void *hwdev, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size) -{ - struct spnic_cmd_vf_dcb_state *vf_dcb; - struct spnic_nic_cfg *nic_cfg; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - vf_dcb = buf_in; - if (!vf_dcb) - return; - - spnic_notify_dcb_state_event(nic_cfg, &vf_dcb->state); -} - -void tx_pause_excp_event_handler(void *hwdev, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size) -{ - struct nic_cmd_tx_pause_notice *excp_info = buf_in; - struct spnic_nic_cfg *nic_cfg = NULL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - if (in_size != sizeof(*excp_info)) { - nic_err(nic_cfg->dev_hdl, "Invalid in_size: %u, should be %ld\n", - in_size, sizeof(*excp_info)); - return; - } - - nic_warn(nic_cfg->dev_hdl, "Receive tx pause exception event, excp: %u, level: %u\n", - excp_info->tx_pause_except, excp_info->except_level); - - sphw_fault_event_report(hwdev, SPHW_FAULT_SRC_TX_PAUSE_EXCP, (u16)excp_info->except_level); -} - -struct nic_event_handler nic_cmd_handler[] = { - { - .cmd = SPNIC_NIC_CMD_VF_COS, - .handler = dcb_state_event, - }, - { - .cmd = SPNIC_NIC_CMD_TX_PAUSE_EXCP_NOTICE, - .handler = tx_pause_excp_event_handler, - }, -}; - -static void _event_handler(void *hwdev, u16 cmd, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - u32 size = sizeof(nic_cmd_handler) / sizeof(struct nic_event_handler); - u32 i; - - if (!hwdev) - return; - - *out_size = 0; - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - for (i = 0; i < size; i++) { - if (cmd == nic_cmd_handler[i].cmd) { - nic_cmd_handler[i].handler(hwdev, buf_in, in_size, buf_out, out_size); - break; - } - } - - /* can't find this event cmd */ - if (i == size) - sdk_warn(nic_cfg->dev_hdl, "Unsupported event cmd(%u) to process\n", - cmd); -} - -/* vf handler mbox msg from ppf/pf */ -/* vf link change event - * vf fault report event, TBD - */ -int spnic_vf_event_handler(void *hwdev, void *pri_handle, u16 cmd, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size) -{ - _event_handler(hwdev, cmd, buf_in, in_size, buf_out, out_size); - return 0; -} - -/* pf/ppf handler mgmt cpu report nic event*/ -void spnic_pf_event_handler(void *hwdev, void *pri_handle, u16 cmd, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size) -{ - _event_handler(hwdev, cmd, buf_in, in_size, buf_out, out_size); -} - -u8 spnic_nic_sw_aeqe_handler(void *hwdev, u8 event, u8 *data) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - - if (!hwdev) - return 0; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - nic_err(nic_cfg->dev_hdl, "Received nic ucode aeq event type: 0x%x, data: 0x%llx\n", - event, *((u64 *)data)); - - return 0; -} diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_nic_io.c b/drivers/net/ethernet/ramaxel/spnic/spnic_nic_io.c deleted file mode 100644 index 3f1fb1381844..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_nic_io.c +++ /dev/null @@ -1,1123 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [NIC]" fmt - -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/types.h> -#include <linux/module.h> - -#include "sphw_crm.h" -#include "sphw_hw.h" -#include "sphw_common.h" -#include "spnic_nic_qp.h" -#include "spnic_nic_io.h" -#include "spnic_nic_cfg.h" -#include "spnic_nic.h" -#include "spnic_nic_cmd.h" - -#define SPNIC_DEAULT_TX_CI_PENDING_LIMIT 0 -#define SPNIC_DEAULT_TX_CI_COALESCING_TIME 0 -#define SPNIC_DEAULT_DROP_THD_ON 0xFFFF -#define SPNIC_DEAULT_DROP_THD_OFF 0 - -static unsigned char tx_pending_limit = SPNIC_DEAULT_TX_CI_PENDING_LIMIT; -module_param(tx_pending_limit, byte, 0444); -MODULE_PARM_DESC(tx_pending_limit, "TX CI coalescing parameter pending_limit (default=0)"); - -static unsigned char tx_coalescing_time = SPNIC_DEAULT_TX_CI_COALESCING_TIME; -module_param(tx_coalescing_time, byte, 0444); -MODULE_PARM_DESC(tx_coalescing_time, "TX CI coalescing parameter coalescing_time (default=0)"); - -static unsigned char rq_wqe_type = SPNIC_NORMAL_RQ_WQE; -module_param(rq_wqe_type, byte, 0444); -MODULE_PARM_DESC(rq_wqe_type, "RQ WQE type 0-8Bytes, 1-16Bytes, 2-32Bytes (default=2)"); - -static u32 tx_drop_thd_on = SPNIC_DEAULT_DROP_THD_ON; -module_param(tx_drop_thd_on, uint, 0644); -MODULE_PARM_DESC(tx_drop_thd_on, "TX parameter drop_thd_on (default=0xffff)"); - -static u32 tx_drop_thd_off = SPNIC_DEAULT_DROP_THD_OFF; -module_param(tx_drop_thd_off, uint, 0644); -MODULE_PARM_DESC(tx_drop_thd_off, "TX parameter drop_thd_off (default=0)"); -/* performance: ci addr RTE_CACHE_SIZE(64B) alignment */ -#define SPNIC_CI_Q_ADDR_SIZE 64 - -#define CI_TABLE_SIZE(num_qps, pg_sz) (ALIGN((num_qps) * SPNIC_CI_Q_ADDR_SIZE, pg_sz)) - -#define SPNIC_CI_VADDR(base_addr, q_id) ((u8 *)(base_addr) + (q_id) * SPNIC_CI_Q_ADDR_SIZE) - -#define SPNIC_CI_PADDR(base_paddr, q_id) ((base_paddr) + (q_id) * SPNIC_CI_Q_ADDR_SIZE) - -#define WQ_PREFETCH_MAX 4 -#define WQ_PREFETCH_MIN 1 -#define WQ_PREFETCH_THRESHOLD 256 - -#define SPNIC_Q_CTXT_MAX 31 /* (2048 - 8) / 64 */ - -enum spnic_qp_ctxt_type { - SPNIC_QP_CTXT_TYPE_SQ, - SPNIC_QP_CTXT_TYPE_RQ, -}; - -struct spnic_qp_ctxt_header { - u16 num_queues; - u16 queue_type; - u16 start_qid; - u16 rsvd; -}; - -struct spnic_sq_ctxt { - u32 ci_pi; - u32 drop_mode_sp; - u32 wq_pfn_hi_owner; - u32 wq_pfn_lo; - - u32 rsvd0; - u32 pkt_drop_thd; - u32 global_sq_id; - u32 vlan_ceq_attr; - - u32 pref_cache; - u32 pref_ci_owner; - u32 pref_wq_pfn_hi_ci; - u32 pref_wq_pfn_lo; - - u32 rsvd8; - u32 rsvd9; - u32 wq_block_pfn_hi; - u32 wq_block_pfn_lo; -}; - -struct spnic_rq_ctxt { - u32 ci_pi; - u32 ceq_attr; - u32 wq_pfn_hi_type_owner; - u32 wq_pfn_lo; - - u32 rsvd[3]; - u32 cqe_sge_len; - - u32 pref_cache; - u32 pref_ci_owner; - u32 pref_wq_pfn_hi_ci; - u32 pref_wq_pfn_lo; - - u32 pi_paddr_hi; - u32 pi_paddr_lo; - u32 wq_block_pfn_hi; - u32 wq_block_pfn_lo; -}; - -struct spnic_sq_ctxt_block { - struct spnic_qp_ctxt_header cmdq_hdr; - struct spnic_sq_ctxt sq_ctxt[SPNIC_Q_CTXT_MAX]; -}; - -struct spnic_rq_ctxt_block { - struct spnic_qp_ctxt_header cmdq_hdr; - struct spnic_rq_ctxt rq_ctxt[SPNIC_Q_CTXT_MAX]; -}; - -struct spnic_clean_queue_ctxt { - struct spnic_qp_ctxt_header cmdq_hdr; - u32 rsvd; -}; - -#define SQ_CTXT_SIZE(num_sqs) ((u16)(sizeof(struct spnic_qp_ctxt_header) + \ - (num_sqs) * sizeof(struct spnic_sq_ctxt))) - -#define RQ_CTXT_SIZE(num_rqs) ((u16)(sizeof(struct spnic_qp_ctxt_header) + \ - (num_rqs) * sizeof(struct spnic_rq_ctxt))) - -#define CI_IDX_HIGH_SHIFH 12 - -#define CI_HIGN_IDX(val) ((val) >> CI_IDX_HIGH_SHIFH) - -#define SQ_CTXT_PI_IDX_SHIFT 0 -#define SQ_CTXT_CI_IDX_SHIFT 16 - -#define SQ_CTXT_PI_IDX_MASK 0xFFFFU -#define SQ_CTXT_CI_IDX_MASK 0xFFFFU - -#define SQ_CTXT_CI_PI_SET(val, member) (((val) & SQ_CTXT_##member##_MASK) << \ - SQ_CTXT_##member##_SHIFT) - -#define SQ_CTXT_MODE_SP_FLAG_SHIFT 0 -#define SQ_CTXT_MODE_PKT_DROP_SHIFT 1 - -#define SQ_CTXT_MODE_SP_FLAG_MASK 0x1U -#define SQ_CTXT_MODE_PKT_DROP_MASK 0x1U - -#define SQ_CTXT_MODE_SET(val, member) (((val) & SQ_CTXT_MODE_##member##_MASK) << \ - SQ_CTXT_MODE_##member##_SHIFT) - -#define SQ_CTXT_WQ_PAGE_HI_PFN_SHIFT 0 -#define SQ_CTXT_WQ_PAGE_OWNER_SHIFT 23 - -#define SQ_CTXT_WQ_PAGE_HI_PFN_MASK 0xFFFFFU -#define SQ_CTXT_WQ_PAGE_OWNER_MASK 0x1U - -#define SQ_CTXT_WQ_PAGE_SET(val, member) (((val) & SQ_CTXT_WQ_PAGE_##member##_MASK) << \ - SQ_CTXT_WQ_PAGE_##member##_SHIFT) - -#define SQ_CTXT_PKT_DROP_THD_ON_SHIFT 0 -#define SQ_CTXT_PKT_DROP_THD_OFF_SHIFT 16 - -#define SQ_CTXT_PKT_DROP_THD_ON_MASK 0xFFFFU -#define SQ_CTXT_PKT_DROP_THD_OFF_MASK 0xFFFFU - -#define SQ_CTXT_PKT_DROP_THD_SET(val, member) (((val) & SQ_CTXT_PKT_DROP_##member##_MASK) << \ - SQ_CTXT_PKT_DROP_##member##_SHIFT) - -#define SQ_CTXT_GLOBAL_SQ_ID_SHIFT 0 - -#define SQ_CTXT_GLOBAL_SQ_ID_MASK 0x1FFFU - -#define SQ_CTXT_GLOBAL_QUEUE_ID_SET(val, member) (((val) & SQ_CTXT_##member##_MASK) << \ - SQ_CTXT_##member##_SHIFT) - -#define SQ_CTXT_VLAN_TAG_SHIFT 0 -#define SQ_CTXT_VLAN_TYPE_SEL_SHIFT 16 -#define SQ_CTXT_VLAN_INSERT_MODE_SHIFT 19 -#define SQ_CTXT_VLAN_CEQ_EN_SHIFT 23 - -#define SQ_CTXT_VLAN_TAG_MASK 0xFFFFU -#define SQ_CTXT_VLAN_TYPE_SEL_MASK 0x7U -#define SQ_CTXT_VLAN_INSERT_MODE_MASK 0x3U -#define SQ_CTXT_VLAN_CEQ_EN_MASK 0x1U - -#define SQ_CTXT_VLAN_CEQ_SET(val, member) (((val) & SQ_CTXT_VLAN_##member##_MASK) << \ - SQ_CTXT_VLAN_##member##_SHIFT) - -#define SQ_CTXT_PREF_CACHE_THRESHOLD_SHIFT 0 -#define SQ_CTXT_PREF_CACHE_MAX_SHIFT 14 -#define SQ_CTXT_PREF_CACHE_MIN_SHIFT 25 - -#define SQ_CTXT_PREF_CACHE_THRESHOLD_MASK 0x3FFFU -#define SQ_CTXT_PREF_CACHE_MAX_MASK 0x7FFU -#define SQ_CTXT_PREF_CACHE_MIN_MASK 0x7FU - -#define SQ_CTXT_PREF_CI_HI_SHIFT 0 -#define SQ_CTXT_PREF_OWNER_SHIFT 4 - -#define SQ_CTXT_PREF_CI_HI_MASK 0xFU -#define SQ_CTXT_PREF_OWNER_MASK 0x1U - -#define SQ_CTXT_PREF_WQ_PFN_HI_SHIFT 0 -#define SQ_CTXT_PREF_CI_LOW_SHIFT 20 - -#define SQ_CTXT_PREF_WQ_PFN_HI_MASK 0xFFFFFU -#define SQ_CTXT_PREF_CI_LOW_MASK 0xFFFU - -#define SQ_CTXT_PREF_SET(val, member) (((val) & SQ_CTXT_PREF_##member##_MASK) << \ - SQ_CTXT_PREF_##member##_SHIFT) - -#define SQ_CTXT_WQ_BLOCK_PFN_HI_SHIFT 0 - -#define SQ_CTXT_WQ_BLOCK_PFN_HI_MASK 0x7FFFFFU - -#define SQ_CTXT_WQ_BLOCK_SET(val, member) (((val) & SQ_CTXT_WQ_BLOCK_##member##_MASK) << \ - SQ_CTXT_WQ_BLOCK_##member##_SHIFT) - -#define RQ_CTXT_PI_IDX_SHIFT 0 -#define RQ_CTXT_CI_IDX_SHIFT 16 - -#define RQ_CTXT_PI_IDX_MASK 0xFFFFU -#define RQ_CTXT_CI_IDX_MASK 0xFFFFU - -#define RQ_CTXT_CI_PI_SET(val, member) (((val) & RQ_CTXT_##member##_MASK) << \ - RQ_CTXT_##member##_SHIFT) - -#define RQ_CTXT_CEQ_ATTR_INTR_SHIFT 21 -#define RQ_CTXT_CEQ_ATTR_EN_SHIFT 31 - -#define RQ_CTXT_CEQ_ATTR_INTR_MASK 0x3FFU -#define RQ_CTXT_CEQ_ATTR_EN_MASK 0x1U - -#define RQ_CTXT_CEQ_ATTR_SET(val, member) (((val) & RQ_CTXT_CEQ_ATTR_##member##_MASK) << \ - RQ_CTXT_CEQ_ATTR_##member##_SHIFT) - -#define RQ_CTXT_WQ_PAGE_HI_PFN_SHIFT 0 -#define RQ_CTXT_WQ_PAGE_WQE_TYPE_SHIFT 28 -#define RQ_CTXT_WQ_PAGE_OWNER_SHIFT 31 - -#define RQ_CTXT_WQ_PAGE_HI_PFN_MASK 0xFFFFFU -#define RQ_CTXT_WQ_PAGE_WQE_TYPE_MASK 0x3U -#define RQ_CTXT_WQ_PAGE_OWNER_MASK 0x1U - -#define RQ_CTXT_WQ_PAGE_SET(val, member) (((val) & RQ_CTXT_WQ_PAGE_##member##_MASK) << \ - RQ_CTXT_WQ_PAGE_##member##_SHIFT) - -#define RQ_CTXT_CQE_LEN_SHIFT 28 - -#define RQ_CTXT_CQE_LEN_MASK 0x3U - -#define RQ_CTXT_CQE_LEN_SET(val, member) (((val) & RQ_CTXT_##member##_MASK) << \ - RQ_CTXT_##member##_SHIFT) - -#define RQ_CTXT_PREF_CACHE_THRESHOLD_SHIFT 0 -#define RQ_CTXT_PREF_CACHE_MAX_SHIFT 14 -#define RQ_CTXT_PREF_CACHE_MIN_SHIFT 25 - -#define RQ_CTXT_PREF_CACHE_THRESHOLD_MASK 0x3FFFU -#define RQ_CTXT_PREF_CACHE_MAX_MASK 0x7FFU -#define RQ_CTXT_PREF_CACHE_MIN_MASK 0x7FU - -#define RQ_CTXT_PREF_CI_HI_SHIFT 0 -#define RQ_CTXT_PREF_OWNER_SHIFT 4 - -#define RQ_CTXT_PREF_CI_HI_MASK 0xFU -#define RQ_CTXT_PREF_OWNER_MASK 0x1U - -#define RQ_CTXT_PREF_WQ_PFN_HI_SHIFT 0 -#define RQ_CTXT_PREF_CI_LOW_SHIFT 20 - -#define RQ_CTXT_PREF_WQ_PFN_HI_MASK 0xFFFFFU -#define RQ_CTXT_PREF_CI_LOW_MASK 0xFFFU - -#define RQ_CTXT_PREF_SET(val, member) (((val) & RQ_CTXT_PREF_##member##_MASK) << \ - RQ_CTXT_PREF_##member##_SHIFT) - -#define RQ_CTXT_WQ_BLOCK_PFN_HI_SHIFT 0 - -#define RQ_CTXT_WQ_BLOCK_PFN_HI_MASK 0x7FFFFFU - -#define RQ_CTXT_WQ_BLOCK_SET(val, member) (((val) & RQ_CTXT_WQ_BLOCK_##member##_MASK) << \ - RQ_CTXT_WQ_BLOCK_##member##_SHIFT) - -#define SIZE_16BYTES(size) (ALIGN((size), 16) >> 4) - -#define WQ_PAGE_PFN_SHIFT 12 -#define WQ_BLOCK_PFN_SHIFT 9 - -#define WQ_PAGE_PFN(page_addr) ((page_addr) >> WQ_PAGE_PFN_SHIFT) -#define WQ_BLOCK_PFN(page_addr) ((page_addr) >> WQ_BLOCK_PFN_SHIFT) - -/* sq and rq */ -#define TOTAL_DB_NUM(num_qps) ((u16)(2 * (num_qps))) - -int spnic_create_sq(struct spnic_nic_cfg *nic_cfg, struct spnic_io_queue *sq, - u16 q_id, u32 sq_depth, u16 sq_msix_idx) -{ - int err; - - /* sq used & hardware request init 1*/ - sq->owner = 1; - - sq->q_id = q_id; - sq->msix_entry_idx = sq_msix_idx; - - err = sphw_wq_create(nic_cfg->hwdev, &sq->wq, sq_depth, (u16)BIT(SPNIC_SQ_WQEBB_SHIFT)); - if (err) { - sdk_err(nic_cfg->dev_hdl, "Failed to create tx queue(%u) wq\n", - q_id); - return err; - } - - return 0; -} - -void spnic_destroy_sq(struct spnic_nic_cfg *nic_cfg, struct spnic_io_queue *sq) -{ - sphw_wq_destroy(&sq->wq); -} - -int spnic_create_rq(struct spnic_nic_cfg *nic_cfg, struct spnic_io_queue *rq, - u16 q_id, u32 rq_depth, u16 rq_msix_idx) -{ - int err; - - rq->wqe_type = rq_wqe_type; - rq->q_id = q_id; - rq->msix_entry_idx = rq_msix_idx; - - err = sphw_wq_create(nic_cfg->hwdev, &rq->wq, rq_depth, - (u16)BIT(SPNIC_RQ_WQEBB_SHIFT + rq_wqe_type)); - if (err) { - sdk_err(nic_cfg->dev_hdl, "Failed to create rx queue(%u) wq\n", - q_id); - return err; - } - - rq->rx.pi_virt_addr = dma_alloc_coherent(nic_cfg->dev_hdl, PAGE_SIZE, - &rq->rx.pi_dma_addr, GFP_KERNEL); - if (!rq->rx.pi_virt_addr) { - sphw_wq_destroy(&rq->wq); - nic_err(nic_cfg->dev_hdl, "Failed to allocate rq pi virt addr\n"); - return -ENOMEM; - } - - return 0; -} - -void spnic_destroy_rq(struct spnic_nic_cfg *nic_cfg, struct spnic_io_queue *rq) -{ - dma_free_coherent(nic_cfg->dev_hdl, PAGE_SIZE, rq->rx.pi_virt_addr, - rq->rx.pi_dma_addr); - - sphw_wq_destroy(&rq->wq); -} - -static int create_qp(struct spnic_nic_cfg *nic_cfg, struct spnic_io_queue *sq, - struct spnic_io_queue *rq, u16 q_id, u32 sq_depth, - u32 rq_depth, u16 qp_msix_idx) -{ - int err; - - err = spnic_create_sq(nic_cfg, sq, q_id, sq_depth, qp_msix_idx); - if (err) { - nic_err(nic_cfg->dev_hdl, "Failed to create sq, qid: %u\n", - q_id); - return err; - } - - err = spnic_create_rq(nic_cfg, rq, q_id, rq_depth, qp_msix_idx); - if (err) { - nic_err(nic_cfg->dev_hdl, "Failed to create rq, qid: %u\n", - q_id); - goto create_rq_err; - } - - return 0; - -create_rq_err: - spnic_destroy_sq(nic_cfg->hwdev, sq); - - return err; -} - -void destroy_qp(struct spnic_nic_cfg *nic_cfg, struct spnic_io_queue *sq, - struct spnic_io_queue *rq) -{ - spnic_destroy_sq(nic_cfg, sq); - spnic_destroy_rq(nic_cfg, rq); -} - -/* try to alloc the expect number of doorbell, and return the actual number - * of doorbell. - */ -static int spnic_doorbell_change(struct spnic_nic_cfg *nic_cfg, u16 dst_num_db) -{ - void __iomem *db_addr = NULL; - u16 cur_db_num = nic_cfg->allocated_num_db; - u16 db_num_gap, idx, i, cur_db_alloc; - int err; - - if (dst_num_db > nic_cfg->allocated_num_db) { - db_num_gap = dst_num_db - nic_cfg->allocated_num_db; - for (idx = 0; idx < db_num_gap; idx++) { - /* we don't use direct wqe for sq */ - err = sphw_alloc_db_addr(nic_cfg->hwdev, &db_addr, NULL); - if (err) { - nic_err(nic_cfg->dev_hdl, "Failed to alloc sq doorbell addr\n"); - goto alloc_db_err; - } - nic_cfg->db_addr[cur_db_num + idx] = db_addr; - } - - nic_cfg->allocated_num_db = dst_num_db; - } else if (dst_num_db < nic_cfg->allocated_num_db) { - db_num_gap = nic_cfg->allocated_num_db - dst_num_db; - for (idx = 0; idx < db_num_gap; idx++) { - cur_db_alloc = (cur_db_num - idx) - 1; - sphw_free_db_addr(nic_cfg->hwdev, nic_cfg->db_addr[cur_db_alloc], NULL); - nic_cfg->db_addr[cur_db_alloc] = NULL; - } - - nic_cfg->allocated_num_db = dst_num_db; - } - - return 0; - -alloc_db_err: - for (i = 0; i < idx; i++) { - sphw_free_db_addr(nic_cfg->hwdev, nic_cfg->db_addr[cur_db_num + i], NULL); - nic_cfg->db_addr[cur_db_num + i] = NULL; - } - - return -EFAULT; -} - -int spnic_init_nicio_res(void *hwdev) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - - if (!hwdev) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - if (!nic_cfg) { - pr_err("Failed to get nic service adapter\n"); - return -EFAULT; - } - - nic_cfg->max_qps = sphw_func_max_qnum(hwdev); - - nic_cfg->allocated_num_db = 0; - nic_cfg->db_addr = kcalloc(TOTAL_DB_NUM(nic_cfg->max_qps), - sizeof(*nic_cfg->db_addr), GFP_KERNEL); - if (!nic_cfg->db_addr) { - nic_err(nic_cfg->dev_hdl, "Failed to alloc db addr array\n"); - return -ENOMEM; - } - - nic_cfg->ci_vaddr_base = - dma_alloc_coherent(nic_cfg->dev_hdl, CI_TABLE_SIZE(nic_cfg->max_qps, PAGE_SIZE), - &nic_cfg->ci_dma_base, GFP_KERNEL); - if (!nic_cfg->ci_vaddr_base) { - kfree(nic_cfg->db_addr); - nic_err(nic_cfg->dev_hdl, "Failed to allocate ci area\n"); - return -ENOMEM; - } - - return 0; -} - -void spnic_deinit_nicio_res(void *hwdev) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - - if (!hwdev) - return; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - if (!nic_cfg) { - pr_err("Failed to get nic service adapter\n"); - return; - } - - dma_free_coherent(nic_cfg->dev_hdl, CI_TABLE_SIZE(nic_cfg->max_qps, PAGE_SIZE), - nic_cfg->ci_vaddr_base, nic_cfg->ci_dma_base); - /* free all doorbell */ - spnic_doorbell_change(nic_cfg, 0); - kfree(nic_cfg->db_addr); -} - -int spnic_alloc_qps(void *hwdev, struct irq_info *qps_msix_arry, - struct spnic_dyna_qp_params *qp_params) -{ - struct spnic_io_queue *sqs = NULL; - struct spnic_io_queue *rqs = NULL; - struct spnic_nic_cfg *nic_cfg = NULL; - u16 q_id, i, cur_allocated_db, num_qps; - int err; - - if (!hwdev || !qps_msix_arry || !qp_params) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - if (!nic_cfg) { - pr_err("Failed to get nic service adapter\n"); - return -EFAULT; - } - - if (qp_params->num_qps > nic_cfg->max_qps) - return -EINVAL; - - num_qps = qp_params->num_qps; - - cur_allocated_db = nic_cfg->allocated_num_db; - if (cur_allocated_db < TOTAL_DB_NUM(num_qps)) { - err = spnic_doorbell_change(nic_cfg, TOTAL_DB_NUM(num_qps)); - if (err) - return err; - } - - sqs = kcalloc(num_qps, sizeof(*sqs), GFP_KERNEL); - if (!sqs) { - nic_err(nic_cfg->dev_hdl, "Failed to allocate sq\n"); - err = -ENOMEM; - goto alloc_sqs_err; - } - - rqs = kcalloc(num_qps, sizeof(*rqs), GFP_KERNEL); - if (!rqs) { - nic_err(nic_cfg->dev_hdl, "Failed to allocate rq\n"); - err = -ENOMEM; - goto alloc_rqs_err; - } - - for (q_id = 0; q_id < num_qps; q_id++) { - err = create_qp(nic_cfg, &sqs[q_id], &rqs[q_id], q_id, - qp_params->sq_depth, qp_params->rq_depth, - qps_msix_arry[q_id].msix_entry_idx); - if (err) { - nic_err(nic_cfg->dev_hdl, "Failed to allocate qp %u, err: %d\n", - q_id, err); - goto create_qp_err; - } - } - - qp_params->sqs = sqs; - qp_params->rqs = rqs; - - return 0; - -create_qp_err: - for (i = 0; i < q_id; i++) - destroy_qp(nic_cfg, &sqs[i], &rqs[i]); - - kfree(rqs); - -alloc_rqs_err: - kfree(sqs); - -alloc_sqs_err: - /* Only release the newly added doorbell resource, - * the old resource is still in use - */ - spnic_doorbell_change(nic_cfg, cur_allocated_db); - - return err; -} - -void spnic_free_qps(void *hwdev, struct spnic_dyna_qp_params *qp_params) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - u16 q_id; - - if (!hwdev || !qp_params) - return; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - if (!nic_cfg) { - pr_err("Failed to get nic service adapter\n"); - return; - } - - for (q_id = 0; q_id < qp_params->num_qps; q_id++) - destroy_qp(nic_cfg, &qp_params->sqs[q_id], - &qp_params->rqs[q_id]); - - kfree(qp_params->sqs); - kfree(qp_params->rqs); -} - -void init_qps_info(struct spnic_nic_cfg *nic_cfg, struct spnic_dyna_qp_params *qp_params) -{ - struct spnic_io_queue *sqs = qp_params->sqs; - struct spnic_io_queue *rqs = qp_params->rqs; - u16 q_id; - - nic_cfg->num_qps = qp_params->num_qps; - nic_cfg->sq = qp_params->sqs; - nic_cfg->rq = qp_params->rqs; - for (q_id = 0; q_id < nic_cfg->num_qps; q_id++) { - sqs[q_id].tx.cons_idx_addr = SPNIC_CI_VADDR(nic_cfg->ci_vaddr_base, q_id); - /* clear ci value */ - *(u16 *)sqs[q_id].tx.cons_idx_addr = 0; - sqs[q_id].db_addr = nic_cfg->db_addr[q_id]; - - /* The first num_qps doorbell is used by sq */ - rqs[q_id].db_addr = nic_cfg->db_addr[nic_cfg->num_qps + q_id]; - } -} - -int spnic_init_qps(void *hwdev, struct spnic_dyna_qp_params *qp_params) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - - if (!hwdev || !qp_params) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - if (!nic_cfg) { - pr_err("Failed to get nic service adapter\n"); - return -EFAULT; - } - - if (nic_cfg->allocated_num_db > TOTAL_DB_NUM(qp_params->num_qps)) - spnic_doorbell_change(nic_cfg, TOTAL_DB_NUM(qp_params->num_qps)); - - init_qps_info(nic_cfg, qp_params); - - return spnic_init_qp_ctxts(hwdev); -} - -void spnic_deinit_qps(void *hwdev, struct spnic_dyna_qp_params *qp_params) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - - if (!hwdev || !qp_params) - return; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - if (!nic_cfg) { - pr_err("Failed to get nic service adapter\n"); - return; - } - - qp_params->sqs = nic_cfg->sq; - qp_params->rqs = nic_cfg->rq; - qp_params->num_qps = nic_cfg->num_qps; - - spnic_free_qp_ctxts(hwdev); -} - -int spnic_create_qps(void *hwdev, u16 num_qp, u32 sq_depth, u32 rq_depth, - struct irq_info *qps_msix_arry) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - struct spnic_dyna_qp_params qp_params = {0}; - int err; - - if (!hwdev || !qps_msix_arry) - return -EFAULT; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - if (!nic_cfg) { - pr_err("Failed to get nic service adapter\n"); - return -EFAULT; - } - - err = spnic_init_nicio_res(hwdev); - if (err) - return err; - - qp_params.num_qps = num_qp; - qp_params.sq_depth = sq_depth; - qp_params.rq_depth = rq_depth; - err = spnic_alloc_qps(hwdev, qps_msix_arry, &qp_params); - if (err) { - spnic_deinit_nicio_res(hwdev); - nic_err(nic_cfg->dev_hdl, "Failed to allocate qps, err: %d\n", err); - return err; - } - - init_qps_info(nic_cfg, &qp_params); - - return 0; -} - -void spnic_destroy_qps(void *hwdev) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - struct spnic_dyna_qp_params qp_params = {0}; - - if (!hwdev) - return; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - if (!nic_cfg) - return; - - spnic_deinit_qps(hwdev, &qp_params); - spnic_free_qps(hwdev, &qp_params); - spnic_deinit_nicio_res(hwdev); -} - -void *spnic_get_nic_queue(void *hwdev, u16 q_id, enum spnic_queue_type q_type) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - - if (!hwdev || q_type >= SPNIC_MAX_QUEUE_TYPE) - return NULL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - if (!nic_cfg) - return NULL; - - return ((q_type == SPNIC_SQ) ? &nic_cfg->sq[q_id] : &nic_cfg->rq[q_id]); -} - -void spnic_qp_prepare_cmdq_header(struct spnic_qp_ctxt_header *qp_ctxt_hdr, - enum spnic_qp_ctxt_type ctxt_type, - u16 num_queues, u16 q_id) -{ - qp_ctxt_hdr->queue_type = ctxt_type; - qp_ctxt_hdr->num_queues = num_queues; - qp_ctxt_hdr->start_qid = q_id; - qp_ctxt_hdr->rsvd = 0; - - sphw_cpu_to_be32(qp_ctxt_hdr, sizeof(*qp_ctxt_hdr)); -} - -void spnic_sq_prepare_ctxt(struct spnic_io_queue *sq, u16 sq_id, struct spnic_sq_ctxt *sq_ctxt) -{ - u64 wq_page_addr; - u64 wq_page_pfn, wq_block_pfn; - u32 wq_page_pfn_hi, wq_page_pfn_lo; - u32 wq_block_pfn_hi, wq_block_pfn_lo; - u16 pi_start, ci_start; - - ci_start = spnic_get_sq_local_ci(sq); - pi_start = spnic_get_sq_local_pi(sq); - - wq_page_addr = sphw_wq_get_first_wqe_page_addr(&sq->wq); - - wq_page_pfn = WQ_PAGE_PFN(wq_page_addr); - wq_page_pfn_hi = upper_32_bits(wq_page_pfn); - wq_page_pfn_lo = lower_32_bits(wq_page_pfn); - - wq_block_pfn = WQ_BLOCK_PFN(sq->wq.wq_block_paddr); - wq_block_pfn_hi = upper_32_bits(wq_block_pfn); - wq_block_pfn_lo = lower_32_bits(wq_block_pfn); - - sq_ctxt->ci_pi = - SQ_CTXT_CI_PI_SET(ci_start, CI_IDX) | - SQ_CTXT_CI_PI_SET(pi_start, PI_IDX); - - sq_ctxt->drop_mode_sp = - SQ_CTXT_MODE_SET(0, SP_FLAG) | - SQ_CTXT_MODE_SET(0, PKT_DROP); - - sq_ctxt->wq_pfn_hi_owner = - SQ_CTXT_WQ_PAGE_SET(wq_page_pfn_hi, HI_PFN) | - SQ_CTXT_WQ_PAGE_SET(1, OWNER); - - sq_ctxt->wq_pfn_lo = wq_page_pfn_lo; - - /* TO DO */ - sq_ctxt->pkt_drop_thd = - SQ_CTXT_PKT_DROP_THD_SET(tx_drop_thd_on, THD_ON) | - SQ_CTXT_PKT_DROP_THD_SET(tx_drop_thd_off, THD_OFF); - - sq_ctxt->global_sq_id = - SQ_CTXT_GLOBAL_QUEUE_ID_SET(sq_id, GLOBAL_SQ_ID); - - /* enable insert c-vlan in default */ - sq_ctxt->vlan_ceq_attr = - SQ_CTXT_VLAN_CEQ_SET(0, CEQ_EN) | - SQ_CTXT_VLAN_CEQ_SET(1, INSERT_MODE); - - sq_ctxt->rsvd0 = 0; - - sq_ctxt->pref_cache = - SQ_CTXT_PREF_SET(WQ_PREFETCH_MIN, CACHE_MIN) | - SQ_CTXT_PREF_SET(WQ_PREFETCH_MAX, CACHE_MAX) | - SQ_CTXT_PREF_SET(WQ_PREFETCH_THRESHOLD, CACHE_THRESHOLD); - - sq_ctxt->pref_ci_owner = - SQ_CTXT_PREF_SET(CI_HIGN_IDX(ci_start), CI_HI) | - SQ_CTXT_PREF_SET(1, OWNER); - - sq_ctxt->pref_wq_pfn_hi_ci = - SQ_CTXT_PREF_SET(ci_start, CI_LOW) | - SQ_CTXT_PREF_SET(wq_page_pfn_hi, WQ_PFN_HI); - - sq_ctxt->pref_wq_pfn_lo = wq_page_pfn_lo; - - sq_ctxt->wq_block_pfn_hi = SQ_CTXT_WQ_BLOCK_SET(wq_block_pfn_hi, PFN_HI); - - sq_ctxt->wq_block_pfn_lo = wq_block_pfn_lo; - - sphw_cpu_to_be32(sq_ctxt, sizeof(*sq_ctxt)); -} - -void spnic_rq_prepare_ctxt(struct spnic_io_queue *rq, struct spnic_rq_ctxt *rq_ctxt) -{ - u64 wq_page_addr; - u64 wq_page_pfn, wq_block_pfn; - u32 wq_page_pfn_hi, wq_page_pfn_lo; - u32 wq_block_pfn_hi, wq_block_pfn_lo; - u16 pi_start, ci_start; - u16 wqe_type = rq->wqe_type; - - /* RQ depth is in unit of 8Bytes */ - ci_start = (u16)((u32)spnic_get_rq_local_ci(rq) << wqe_type); - pi_start = (u16)((u32)spnic_get_rq_local_pi(rq) << wqe_type); - - wq_page_addr = sphw_wq_get_first_wqe_page_addr(&rq->wq); - - wq_page_pfn = WQ_PAGE_PFN(wq_page_addr); - wq_page_pfn_hi = upper_32_bits(wq_page_pfn); - wq_page_pfn_lo = lower_32_bits(wq_page_pfn); - - wq_block_pfn = WQ_BLOCK_PFN(rq->wq.wq_block_paddr); - wq_block_pfn_hi = upper_32_bits(wq_block_pfn); - wq_block_pfn_lo = lower_32_bits(wq_block_pfn); - - rq_ctxt->ci_pi = - RQ_CTXT_CI_PI_SET(ci_start, CI_IDX) | - RQ_CTXT_CI_PI_SET(pi_start, PI_IDX); - - rq_ctxt->ceq_attr = RQ_CTXT_CEQ_ATTR_SET(0, EN) | - RQ_CTXT_CEQ_ATTR_SET(rq->msix_entry_idx, INTR); - - rq_ctxt->wq_pfn_hi_type_owner = - RQ_CTXT_WQ_PAGE_SET(wq_page_pfn_hi, HI_PFN) | - RQ_CTXT_WQ_PAGE_SET(1, OWNER); - - switch (wqe_type) { - case SPNIC_EXTEND_RQ_WQE: - /* use 32Byte WQE with SGE for CQE */ - rq_ctxt->wq_pfn_hi_type_owner |= RQ_CTXT_WQ_PAGE_SET(0, WQE_TYPE); - break; - case SPNIC_NORMAL_RQ_WQE: - /* use 16Byte WQE with 32Bytes SGE for CQE */ - rq_ctxt->wq_pfn_hi_type_owner |= RQ_CTXT_WQ_PAGE_SET(2, WQE_TYPE); - rq_ctxt->cqe_sge_len = RQ_CTXT_CQE_LEN_SET(1, CQE_LEN); - break; - default: - pr_err("Invalid rq wqe type: %u", wqe_type); - } - - rq_ctxt->wq_pfn_lo = wq_page_pfn_lo; - - rq_ctxt->pref_cache = - RQ_CTXT_PREF_SET(WQ_PREFETCH_MIN, CACHE_MIN) | - RQ_CTXT_PREF_SET(WQ_PREFETCH_MAX, CACHE_MAX) | - RQ_CTXT_PREF_SET(WQ_PREFETCH_THRESHOLD, CACHE_THRESHOLD); - - rq_ctxt->pref_ci_owner = - RQ_CTXT_PREF_SET(CI_HIGN_IDX(ci_start), CI_HI) | - RQ_CTXT_PREF_SET(1, OWNER); - - rq_ctxt->pref_wq_pfn_hi_ci = - RQ_CTXT_PREF_SET(wq_page_pfn_hi, WQ_PFN_HI) | - RQ_CTXT_PREF_SET(ci_start, CI_LOW); - - rq_ctxt->pref_wq_pfn_lo = wq_page_pfn_lo; - - rq_ctxt->pi_paddr_hi = upper_32_bits(rq->rx.pi_dma_addr); - rq_ctxt->pi_paddr_lo = lower_32_bits(rq->rx.pi_dma_addr); - - rq_ctxt->wq_block_pfn_hi = RQ_CTXT_WQ_BLOCK_SET(wq_block_pfn_hi, PFN_HI); - - rq_ctxt->wq_block_pfn_lo = wq_block_pfn_lo; - - sphw_cpu_to_be32(rq_ctxt, sizeof(*rq_ctxt)); -} - -static int init_sq_ctxts(struct spnic_nic_cfg *nic_cfg) -{ - struct spnic_sq_ctxt_block *sq_ctxt_block = NULL; - struct spnic_sq_ctxt *sq_ctxt = NULL; - struct sphw_cmd_buf *cmd_buf = NULL; - struct spnic_io_queue *sq = NULL; - u64 out_param = 0; - u16 q_id, curr_id, max_ctxts, i; - int err = 0; - - cmd_buf = sphw_alloc_cmd_buf(nic_cfg->hwdev); - if (!cmd_buf) { - nic_err(nic_cfg->dev_hdl, "Failed to allocate cmd buf\n"); - return -ENOMEM; - } - - q_id = 0; - while (q_id < nic_cfg->num_qps) { - sq_ctxt_block = cmd_buf->buf; - sq_ctxt = sq_ctxt_block->sq_ctxt; - - max_ctxts = (nic_cfg->num_qps - q_id) > SPNIC_Q_CTXT_MAX ? - SPNIC_Q_CTXT_MAX : (nic_cfg->num_qps - q_id); - - spnic_qp_prepare_cmdq_header(&sq_ctxt_block->cmdq_hdr, SPNIC_QP_CTXT_TYPE_SQ, - max_ctxts, q_id); - - for (i = 0; i < max_ctxts; i++) { - curr_id = q_id + i; - sq = &nic_cfg->sq[curr_id]; - - spnic_sq_prepare_ctxt(sq, curr_id, &sq_ctxt[i]); - } - - cmd_buf->size = SQ_CTXT_SIZE(max_ctxts); - - err = sphw_cmdq_direct_resp(nic_cfg->hwdev, SPHW_MOD_L2NIC, - SPNIC_UCODE_CMD_MODIFY_QUEUE_CTX, - cmd_buf, &out_param, 0, SPHW_CHANNEL_NIC); - if (err || out_param != 0) { - nic_err(nic_cfg->dev_hdl, "Failed to set SQ ctxts, err: %d, out_param: 0x%llx\n", - err, out_param); - - err = -EFAULT; - break; - } - - q_id += max_ctxts; - } - - sphw_free_cmd_buf(nic_cfg->hwdev, cmd_buf); - - return err; -} - -static int init_rq_ctxts(struct spnic_nic_cfg *nic_cfg) -{ - struct spnic_rq_ctxt_block *rq_ctxt_block = NULL; - struct spnic_rq_ctxt *rq_ctxt = NULL; - struct sphw_cmd_buf *cmd_buf = NULL; - struct spnic_io_queue *rq = NULL; - u64 out_param = 0; - u16 q_id, curr_id, max_ctxts, i; - int err = 0; - - cmd_buf = sphw_alloc_cmd_buf(nic_cfg->hwdev); - if (!cmd_buf) { - nic_err(nic_cfg->dev_hdl, "Failed to allocate cmd buf\n"); - return -ENOMEM; - } - - q_id = 0; - while (q_id < nic_cfg->num_qps) { - rq_ctxt_block = cmd_buf->buf; - rq_ctxt = rq_ctxt_block->rq_ctxt; - - max_ctxts = (nic_cfg->num_qps - q_id) > SPNIC_Q_CTXT_MAX ? - SPNIC_Q_CTXT_MAX : (nic_cfg->num_qps - q_id); - - spnic_qp_prepare_cmdq_header(&rq_ctxt_block->cmdq_hdr, SPNIC_QP_CTXT_TYPE_RQ, - max_ctxts, q_id); - - for (i = 0; i < max_ctxts; i++) { - curr_id = q_id + i; - rq = &nic_cfg->rq[curr_id]; - - spnic_rq_prepare_ctxt(rq, &rq_ctxt[i]); - } - - cmd_buf->size = RQ_CTXT_SIZE(max_ctxts); - - err = sphw_cmdq_direct_resp(nic_cfg->hwdev, SPHW_MOD_L2NIC, - SPNIC_UCODE_CMD_MODIFY_QUEUE_CTX, - cmd_buf, &out_param, 0, SPHW_CHANNEL_NIC); - - if (err || out_param != 0) { - nic_err(nic_cfg->dev_hdl, "Failed to set RQ ctxts, err: %d, out_param: 0x%llx\n", - err, out_param); - - err = -EFAULT; - break; - } - - q_id += max_ctxts; - } - - sphw_free_cmd_buf(nic_cfg->hwdev, cmd_buf); - - return err; -} - -static int init_qp_ctxts(struct spnic_nic_cfg *nic_cfg) -{ - int err; - - err = init_sq_ctxts(nic_cfg); - if (err) - return err; - - err = init_rq_ctxts(nic_cfg); - if (err) - return err; - - return 0; -} - -static int clean_queue_offload_ctxt(struct spnic_nic_cfg *nic_cfg, - enum spnic_qp_ctxt_type ctxt_type) -{ - struct spnic_clean_queue_ctxt *ctxt_block = NULL; - struct sphw_cmd_buf *cmd_buf = NULL; - u64 out_param = 0; - int err; - - cmd_buf = sphw_alloc_cmd_buf(nic_cfg->hwdev); - if (!cmd_buf) { - nic_err(nic_cfg->dev_hdl, "Failed to allocate cmd buf\n"); - return -ENOMEM; - } - - ctxt_block = cmd_buf->buf; - ctxt_block->cmdq_hdr.num_queues = nic_cfg->max_qps; - ctxt_block->cmdq_hdr.queue_type = ctxt_type; - ctxt_block->cmdq_hdr.start_qid = 0; - - sphw_cpu_to_be32(ctxt_block, sizeof(*ctxt_block)); - - cmd_buf->size = sizeof(*ctxt_block); - - err = sphw_cmdq_direct_resp(nic_cfg->hwdev, SPHW_MOD_L2NIC, - SPNIC_UCODE_CMD_CLEAN_QUEUE_CONTEXT, - cmd_buf, &out_param, 0, SPHW_CHANNEL_NIC); - - if ((err) || (out_param)) { - nic_err(nic_cfg->dev_hdl, "Failed to clean queue offload ctxts, err: %d,out_param: 0x%llx\n", - err, out_param); - - err = -EFAULT; - } - - sphw_free_cmd_buf(nic_cfg->hwdev, cmd_buf); - - return err; -} - -static int clean_qp_offload_ctxt(struct spnic_nic_cfg *nic_cfg) -{ - /* clean LRO/TSO context space */ - return (clean_queue_offload_ctxt(nic_cfg, SPNIC_QP_CTXT_TYPE_SQ) || - clean_queue_offload_ctxt(nic_cfg, SPNIC_QP_CTXT_TYPE_RQ)); -} - -/* init qps ctxt and set sq ci attr and arm all sq*/ -int spnic_init_qp_ctxts(void *hwdev) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - struct spnic_sq_attr sq_attr; - u32 rq_depth; - u16 q_id; - int err; - - if (!hwdev) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - if (!nic_cfg) - return -EFAULT; - - err = init_qp_ctxts(nic_cfg); - if (err) { - nic_err(nic_cfg->dev_hdl, "Failed to init QP ctxts\n"); - return err; - } - - /* clean LRO/TSO context space */ - err = clean_qp_offload_ctxt(nic_cfg); - if (err) { - nic_err(nic_cfg->dev_hdl, "Failed to clean qp offload ctxts\n"); - return err; - } - - rq_depth = nic_cfg->rq[0].wq.q_depth << nic_cfg->rq[0].wqe_type; - - err = sphw_set_root_ctxt(hwdev, rq_depth, nic_cfg->sq[0].wq.q_depth, - nic_cfg->rx_buff_len, SPHW_CHANNEL_NIC); - if (err) { - nic_err(nic_cfg->dev_hdl, "Failed to set root context\n"); - return err; - } - - for (q_id = 0; q_id < nic_cfg->num_qps; q_id++) { - sq_attr.ci_dma_base = SPNIC_CI_PADDR(nic_cfg->ci_dma_base, q_id) >> 2; - sq_attr.pending_limit = tx_pending_limit; - sq_attr.coalescing_time = tx_coalescing_time; - sq_attr.intr_en = 1; - sq_attr.intr_idx = nic_cfg->sq[q_id].msix_entry_idx; - sq_attr.l2nic_sqn = q_id; - sq_attr.dma_attr_off = 0; - err = spnic_set_ci_table(hwdev, &sq_attr); - if (err) { - nic_err(nic_cfg->dev_hdl, "Failed to set ci table\n"); - goto set_cons_idx_table_err; - } - } - - return 0; - -set_cons_idx_table_err: - sphw_clean_root_ctxt(hwdev, SPHW_CHANNEL_NIC); - - return err; -} - -void spnic_free_qp_ctxts(void *hwdev) -{ - if (!hwdev) - return; - - sphw_clean_root_ctxt(hwdev, SPHW_CHANNEL_NIC); -} diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_nic_io.h b/drivers/net/ethernet/ramaxel/spnic/spnic_nic_io.h deleted file mode 100644 index e237ba33d82d..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_nic_io.h +++ /dev/null @@ -1,305 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPNIC_NIC_IO_H -#define SPNIC_NIC_IO_H - -#include "sphw_crm.h" -#include "sphw_common.h" -#include "sphw_wq.h" - -#define SPNIC_MAX_TX_QUEUE_DEPTH 65536 -#define SPNIC_MAX_RX_QUEUE_DEPTH 16384 - -#define SPNIC_MIN_QUEUE_DEPTH 128 - -#define SPNIC_SQ_WQEBB_SHIFT 4 -#define SPNIC_RQ_WQEBB_SHIFT 3 - -#define SPNIC_SQ_WQEBB_SIZE BIT(SPNIC_SQ_WQEBB_SHIFT) -#define SPNIC_CQE_SIZE_SHIFT 4 - -enum spnic_rq_wqe_type { - SPNIC_COMPACT_RQ_WQE, - SPNIC_NORMAL_RQ_WQE, - SPNIC_EXTEND_RQ_WQE, -}; - -struct spnic_io_queue { - struct sphw_wq wq; - union { - u8 wqe_type; /* for rq */ - u8 owner; /* for sq */ - }; - - u16 q_id; - u16 msix_entry_idx; - - u8 __iomem *db_addr; - - union { - struct { - void *cons_idx_addr; - } tx; - - struct { - u16 *pi_virt_addr; - dma_addr_t pi_dma_addr; - } rx; - }; -} ____cacheline_aligned; - -struct spnic_nic_db { - u32 db_info; - u32 pi_hi; -}; - -/* * - * @brief spnic_get_sq_free_wqebbs - get send queue free wqebb - * @param sq: send queue - * @retval : number of free wqebb - */ -static inline u16 spnic_get_sq_free_wqebbs(struct spnic_io_queue *sq) -{ - return sphw_wq_free_wqebbs(&sq->wq); -} - -/* * - * @brief spnic_update_sq_local_ci - update send queue local consumer index - * @param sq: send queue - * @param wqe_cnt: number of wqebb - */ -static inline void spnic_update_sq_local_ci(struct spnic_io_queue *sq, u16 wqebb_cnt) -{ - sphw_wq_put_wqebbs(&sq->wq, wqebb_cnt); -} - -/* * - * @brief spnic_get_sq_local_ci - get send queue local consumer index - * @param sq: send queue - * @retval : local consumer index - */ -static inline u16 spnic_get_sq_local_ci(struct spnic_io_queue *sq) -{ - return WQ_MASK_IDX(&sq->wq, sq->wq.cons_idx); -} - -/* * - * @brief spnic_get_sq_local_pi - get send queue local producer index - * @param sq: send queue - * @retval : local producer index - */ -static inline u16 spnic_get_sq_local_pi(struct spnic_io_queue *sq) -{ - return WQ_MASK_IDX(&sq->wq, sq->wq.prod_idx); -} - -/* * - * @brief spnic_get_sq_hw_ci - get send queue hardware consumer index - * @param sq: send queue - * @retval : hardware consumer index - */ -static inline u16 spnic_get_sq_hw_ci(struct spnic_io_queue *sq) -{ - return WQ_MASK_IDX(&sq->wq, *(u16 *)sq->tx.cons_idx_addr); -} - -/* * - * @brief spnic_get_sq_one_wqebb - get send queue wqe with single wqebb - * @param sq: send queue - * @param pi: return current pi - * @retval : wqe base address - */ -static inline void *spnic_get_sq_one_wqebb(struct spnic_io_queue *sq, u16 *pi) -{ - return sphw_wq_get_one_wqebb(&sq->wq, pi); -} - -/* * - * @brief spnic_get_sq_multi_wqebb - get send queue wqe with multiple wqebbs - * @param sq: send queue - * @param wqebb_cnt: wqebb counter - * @param pi: return current pi - * @param second_part_wqebbs_addr: second part wqebbs base address - * @param first_part_wqebbs_num: number wqebbs of first part - * @retval : first part wqebbs base address - */ -static inline void *spnic_get_sq_multi_wqebbs(struct spnic_io_queue *sq, u16 wqebb_cnt, u16 *pi, - void **second_part_wqebbs_addr, - u16 *first_part_wqebbs_num) -{ - return sphw_wq_get_multi_wqebbs(&sq->wq, wqebb_cnt, pi, second_part_wqebbs_addr, - first_part_wqebbs_num); -} - -/* * - * @brief spnic_get_and_update_sq_owner - get and update send queue owner bit - * @param sq: send queue - * @param curr_pi: current pi - * @param wqebb_cnt: wqebb counter - * @retval : owner bit - */ -static inline u16 spnic_get_and_update_sq_owner(struct spnic_io_queue *sq, - u16 curr_pi, u16 wqebb_cnt) -{ - u16 owner = sq->owner; - - if (unlikely(curr_pi + wqebb_cnt >= sq->wq.q_depth)) - sq->owner = !sq->owner; - - return owner; -} - -/* * - * @brief spnic_get_sq_wqe_with_owner - get send queue wqe with owner - * @param sq: send queue - * @param wqebb_cnt: wqebb counter - * @param pi: return current pi - * @param owner: return owner bit - * @param second_part_wqebbs_addr: second part wqebbs base address - * @param first_part_wqebbs_num: number wqebbs of first part - * @retval : first part wqebbs base address - */ -static inline void *spnic_get_sq_wqe_with_owner(struct spnic_io_queue *sq, - u16 wqebb_cnt, u16 *pi, u16 *owner, - void **second_part_wqebbs_addr, - u16 *first_part_wqebbs_num) -{ - void *wqe = sphw_wq_get_multi_wqebbs(&sq->wq, wqebb_cnt, pi, second_part_wqebbs_addr, - first_part_wqebbs_num); - - *owner = sq->owner; - if (unlikely(*pi + wqebb_cnt >= sq->wq.q_depth)) - sq->owner = !sq->owner; - - return wqe; -} - -/* * - * @brief spnic_rollback_sq_wqebbs - rollback send queue wqe - * @param sq: send queue - * @param wqebb_cnt: wqebb counter - * @param owner: owner bit - */ -static inline void spnic_rollback_sq_wqebbs(struct spnic_io_queue *sq, u16 wqebb_cnt, u16 owner) -{ - if (owner != sq->owner) - sq->owner = owner; - sq->wq.prod_idx -= wqebb_cnt; -} - -/* * - * @brief spnic_rq_wqe_addr - get receive queue wqe address by queue index - * @param rq: receive queue - * @param idx: wq index - * @retval: wqe base address - */ -static inline void *spnic_rq_wqe_addr(struct spnic_io_queue *rq, u16 idx) -{ - return sphw_wq_wqebb_addr(&rq->wq, idx); -} - -/* * - * @brief spnic_update_rq_hw_pi - update receive queue hardware pi - * @param rq: receive queue - * @param pi: pi - */ -static inline void spnic_update_rq_hw_pi(struct spnic_io_queue *rq, u16 pi) -{ - *rq->rx.pi_virt_addr = cpu_to_be16((pi & rq->wq.idx_mask) << rq->wqe_type); -} - -/* * - * @brief spnic_update_rq_local_ci - update receive queue local consumer index - * @param sq: receive queue - * @param wqe_cnt: number of wqebb - */ -static inline void spnic_update_rq_local_ci(struct spnic_io_queue *rq, u16 wqebb_cnt) -{ - sphw_wq_put_wqebbs(&rq->wq, wqebb_cnt); -} - -/* * - * @brief spnic_get_rq_local_ci - get receive queue local ci - * @param rq: receive queue - * @retval: receive queue local ci - */ -static inline u16 spnic_get_rq_local_ci(struct spnic_io_queue *rq) -{ - return WQ_MASK_IDX(&rq->wq, rq->wq.cons_idx); -} - -/* * - * @brief spnic_get_rq_local_pi - get receive queue local pi - * @param rq: receive queue - * @retval: receive queue local pi - */ -static inline u16 spnic_get_rq_local_pi(struct spnic_io_queue *rq) -{ - return WQ_MASK_IDX(&rq->wq, rq->wq.prod_idx); -} - -/* ******************** DB INFO ******************** */ -#define DB_INFO_QID_SHIFT 0 -#define DB_INFO_NON_FILTER_SHIFT 22 -#define DB_INFO_CFLAG_SHIFT 23 -#define DB_INFO_COS_SHIFT 24 -#define DB_INFO_TYPE_SHIFT 27 - -#define DB_INFO_QID_MASK 0x1FFFU -#define DB_INFO_NON_FILTER_MASK 0x1U -#define DB_INFO_CFLAG_MASK 0x1U -#define DB_INFO_COS_MASK 0x7U -#define DB_INFO_TYPE_MASK 0x1FU -#define DB_INFO_SET(val, member) \ - (((u32)(val) & DB_INFO_##member##_MASK) << \ - DB_INFO_##member##_SHIFT) - -#define DB_PI_LOW_MASK 0xFFU -#define DB_PI_HIGH_MASK 0xFFU -#define DB_PI_LOW(pi) ((pi) & DB_PI_LOW_MASK) -#define DB_PI_HI_SHIFT 8 -#define DB_PI_HIGH(pi) (((pi) >> DB_PI_HI_SHIFT) & DB_PI_HIGH_MASK) -#define DB_ADDR(queue, pi) ((u64 *)((queue)->db_addr) + DB_PI_LOW(pi)) -#define SRC_TYPE 1 - -/* CFLAG_DATA_PATH */ -#define SQ_CFLAG_DP 0 -#define RQ_CFLAG_DP 1 -/* * - * @brief spnic_write_db - write doorbell - * @param queue: nic io queue - * @param cos: cos index - * @param cflag: 0--sq, 1--rq - * @param pi: product index - */ -static inline void spnic_write_db(struct spnic_io_queue *queue, int cos, u8 cflag, u16 pi) -{ - struct spnic_nic_db db; - - db.db_info = DB_INFO_SET(SRC_TYPE, TYPE) | DB_INFO_SET(cflag, CFLAG) | - DB_INFO_SET(cos, COS) | DB_INFO_SET(queue->q_id, QID); - db.pi_hi = DB_PI_HIGH(pi); - - wmb(); /* Write all before the doorbell */ - - writeq(*((u64 *)&db), DB_ADDR(queue, pi)); -} - -struct spnic_dyna_qp_params { - u16 num_qps; - u32 sq_depth; - u32 rq_depth; - - struct spnic_io_queue *sqs; - struct spnic_io_queue *rqs; -}; - -int spnic_alloc_qps(void *hwdev, struct irq_info *qps_msix_arry, - struct spnic_dyna_qp_params *qp_params); -void spnic_free_qps(void *hwdev, struct spnic_dyna_qp_params *qp_params); -int spnic_init_qps(void *hwdev, struct spnic_dyna_qp_params *qp_params); -void spnic_deinit_qps(void *hwdev, struct spnic_dyna_qp_params *qp_params); -int spnic_init_nicio_res(void *hwdev); -void spnic_deinit_nicio_res(void *hwdev); -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_nic_qp.h b/drivers/net/ethernet/ramaxel/spnic/spnic_nic_qp.h deleted file mode 100644 index a8abdc1734d3..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_nic_qp.h +++ /dev/null @@ -1,416 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPNIC_NIC_QP_H -#define SPNIC_NIC_QP_H - -#include "sphw_common.h" - -#define TX_MSS_DEFAULT 0x3E00 -#define TX_MSS_MIN 0x50 - -#define SPNIC_MAX_SQ_SGE 18 - -#define RQ_CQE_OFFOLAD_TYPE_PKT_TYPE_SHIFT 0 -#define RQ_CQE_OFFOLAD_TYPE_IP_TYPE_SHIFT 5 -#define RQ_CQE_OFFOLAD_TYPE_ENC_L3_TYPE_SHIFT 7 -#define RQ_CQE_OFFOLAD_TYPE_TUNNEL_PKT_FORMAT_SHIFT 8 -#define RQ_CQE_OFFOLAD_TYPE_PKT_UMBCAST_SHIFT 19 -#define RQ_CQE_OFFOLAD_TYPE_VLAN_EN_SHIFT 21 -#define RQ_CQE_OFFOLAD_TYPE_RSS_TYPE_SHIFT 24 - -#define RQ_CQE_OFFOLAD_TYPE_PKT_TYPE_MASK 0x1FU -#define RQ_CQE_OFFOLAD_TYPE_IP_TYPE_MASK 0x3U -#define RQ_CQE_OFFOLAD_TYPE_ENC_L3_TYPE_MASK 0x1U -#define RQ_CQE_OFFOLAD_TYPE_TUNNEL_PKT_FORMAT_MASK 0xFU -#define RQ_CQE_OFFOLAD_TYPE_PKT_UMBCAST_MASK 0x3U -#define RQ_CQE_OFFOLAD_TYPE_VLAN_EN_MASK 0x1U -#define RQ_CQE_OFFOLAD_TYPE_RSS_TYPE_MASK 0xFFU - -#define RQ_CQE_OFFOLAD_TYPE_GET(val, member) \ - (((val) >> RQ_CQE_OFFOLAD_TYPE_##member##_SHIFT) & \ - RQ_CQE_OFFOLAD_TYPE_##member##_MASK) - -#define SPNIC_GET_RX_PKT_TYPE(offload_type) \ - RQ_CQE_OFFOLAD_TYPE_GET(offload_type, PKT_TYPE) -#define SPNIC_GET_RX_IP_TYPE(offload_type) \ - RQ_CQE_OFFOLAD_TYPE_GET(offload_type, IP_TYPE) -#define SPNIC_GET_RX_ENC_L3_TYPE(offload_type) \ - RQ_CQE_OFFOLAD_TYPE_GET(offload_type, ENC_L3_TYPE) -#define SPNIC_GET_RX_TUNNEL_PKT_FORMAT(offload_type) \ - RQ_CQE_OFFOLAD_TYPE_GET(offload_type, TUNNEL_PKT_FORMAT) - -#define SPNIC_GET_RX_PKT_UMBCAST(offload_type) \ - RQ_CQE_OFFOLAD_TYPE_GET(offload_type, PKT_UMBCAST) - -#define SPNIC_GET_RX_VLAN_OFFLOAD_EN(offload_type) \ - RQ_CQE_OFFOLAD_TYPE_GET(offload_type, VLAN_EN) - -#define SPNIC_GET_RSS_TYPES(offload_type) \ - RQ_CQE_OFFOLAD_TYPE_GET(offload_type, RSS_TYPE) - -#define RQ_CQE_SGE_VLAN_SHIFT 0 -#define RQ_CQE_SGE_LEN_SHIFT 16 - -#define RQ_CQE_SGE_VLAN_MASK 0xFFFFU -#define RQ_CQE_SGE_LEN_MASK 0xFFFFU - -#define RQ_CQE_SGE_GET(val, member) \ - (((val) >> RQ_CQE_SGE_##member##_SHIFT) & RQ_CQE_SGE_##member##_MASK) - -#define SPNIC_GET_RX_VLAN_TAG(vlan_len) RQ_CQE_SGE_GET(vlan_len, VLAN) - -#define SPNIC_GET_RX_PKT_LEN(vlan_len) RQ_CQE_SGE_GET(vlan_len, LEN) - -#define RQ_CQE_STATUS_CSUM_ERR_SHIFT 0 -#define RQ_CQE_STATUS_NUM_LRO_SHIFT 16 -#define RQ_CQE_STATUS_LRO_PUSH_SHIFT 25 -#define RQ_CQE_STATUS_LRO_ENTER_SHIFT 26 -#define RQ_CQE_STATUS_LRO_INTR_SHIFT 27 - -#define RQ_CQE_STATUS_BP_EN_SHIFT 30 -#define RQ_CQE_STATUS_RXDONE_SHIFT 31 -#define RQ_CQE_STATUS_DECRY_PKT_SHIFT 29 -#define RQ_CQE_STATUS_FLUSH_SHIFT 28 - -#define RQ_CQE_STATUS_CSUM_ERR_MASK 0xFFFFU -#define RQ_CQE_STATUS_NUM_LRO_MASK 0xFFU -#define RQ_CQE_STATUS_LRO_PUSH_MASK 0X1U -#define RQ_CQE_STATUS_LRO_ENTER_MASK 0X1U -#define RQ_CQE_STATUS_LRO_INTR_MASK 0X1U -#define RQ_CQE_STATUS_BP_EN_MASK 0X1U -#define RQ_CQE_STATUS_RXDONE_MASK 0x1U -#define RQ_CQE_STATUS_FLUSH_MASK 0x1U -#define RQ_CQE_STATUS_DECRY_PKT_MASK 0x1U - -#define RQ_CQE_STATUS_GET(val, member) \ - (((val) >> RQ_CQE_STATUS_##member##_SHIFT) & \ - RQ_CQE_STATUS_##member##_MASK) - -#define SPNIC_GET_RX_CSUM_ERR(status) RQ_CQE_STATUS_GET(status, CSUM_ERR) - -#define SPNIC_GET_RX_DONE(status) RQ_CQE_STATUS_GET(status, RXDONE) - -#define SPNIC_GET_RX_FLUSH(status) RQ_CQE_STATUS_GET(status, FLUSH) - -#define SPNIC_GET_RX_BP_EN(status) RQ_CQE_STATUS_GET(status, BP_EN) - -#define SPNIC_GET_RX_NUM_LRO(status) RQ_CQE_STATUS_GET(status, NUM_LRO) - -#define SPNIC_RX_IS_DECRY_PKT(status) RQ_CQE_STATUS_GET(status, DECRY_PKT) - -#define RQ_CQE_SUPER_CQE_EN_SHIFT 0 -#define RQ_CQE_PKT_NUM_SHIFT 1 -#define RQ_CQE_PKT_LAST_LEN_SHIFT 6 -#define RQ_CQE_PKT_FIRST_LEN_SHIFT 19 - -#define RQ_CQE_SUPER_CQE_EN_MASK 0x1 -#define RQ_CQE_PKT_NUM_MASK 0x1FU -#define RQ_CQE_PKT_FIRST_LEN_MASK 0x1FFFU -#define RQ_CQE_PKT_LAST_LEN_MASK 0x1FFFU - -#define RQ_CQE_PKT_NUM_GET(val, member) \ - (((val) >> RQ_CQE_PKT_##member##_SHIFT) & RQ_CQE_PKT_##member##_MASK) -#define SPNIC_GET_RQ_CQE_PKT_NUM(pkt_info) RQ_CQE_PKT_NUM_GET(pkt_info, NUM) - -#define RQ_CQE_SUPER_CQE_EN_GET(val, member) \ - (((val) >> RQ_CQE_##member##_SHIFT) & RQ_CQE_##member##_MASK) -#define SPNIC_GET_SUPER_CQE_EN(pkt_info) \ - RQ_CQE_SUPER_CQE_EN_GET(pkt_info, SUPER_CQE_EN) - -#define RQ_CQE_PKT_LEN_GET(val, member) \ - (((val) >> RQ_CQE_PKT_##member##_SHIFT) & RQ_CQE_PKT_##member##_MASK) - -#define RQ_CQE_DECRY_INFO_DECRY_STATUS_SHIFT 8 -#define RQ_CQE_DECRY_INFO_ESP_NEXT_HEAD_SHIFT 0 - -#define RQ_CQE_DECRY_INFO_DECRY_STATUS_MASK 0xFFU -#define RQ_CQE_DECRY_INFO_ESP_NEXT_HEAD_MASK 0xFFU - -#define RQ_CQE_DECRY_INFO_GET(val, member) \ - (((val) >> RQ_CQE_DECRY_INFO_##member##_SHIFT) & \ - RQ_CQE_DECRY_INFO_##member##_MASK) - -#define SPNIC_GET_DECRYPT_STATUS(decry_info) \ - RQ_CQE_DECRY_INFO_GET(decry_info, DECRY_STATUS) - -#define SPNIC_GET_ESP_NEXT_HEAD(decry_info) \ - RQ_CQE_DECRY_INFO_GET(decry_info, ESP_NEXT_HEAD) - -struct spnic_rq_cqe { - u32 status; - u32 vlan_len; - - u32 offload_type; - u32 hash_val; - u32 xid; - u32 decrypt_info; - u32 rsvd6; - u32 pkt_info; -}; - -struct spnic_sge_sect { - struct sphw_sge sge; - u32 rsvd; -}; - -struct spnic_rq_extend_wqe { - struct spnic_sge_sect buf_desc; - struct spnic_sge_sect cqe_sect; -}; - -struct spnic_rq_normal_wqe { - u32 buf_hi_addr; - u32 buf_lo_addr; - u32 cqe_hi_addr; - u32 cqe_lo_addr; -}; - -struct spnic_rq_wqe { - union { - struct spnic_rq_normal_wqe normal_wqe; - struct spnic_rq_extend_wqe extend_wqe; - }; -}; - -struct spnic_sq_wqe_desc { - u32 ctrl_len; - u32 queue_info; - u32 hi_addr; - u32 lo_addr; -}; - -/* Engine only pass first 12B TS field directly to uCode through metadata - * vlan_offoad is used for hardware when vlan insert in tx - */ -struct spnic_sq_task { - u32 pkt_info0; - u32 ip_identify; - u32 pkt_info2; /* ipsec used as spi */ - u32 vlan_offload; -}; - -struct spnic_sq_bufdesc { - u32 len; /* 31-bits Length, L2NIC only use length[17:0] */ - u32 rsvd; - u32 hi_addr; - u32 lo_addr; -}; - -struct spnic_sq_compact_wqe { - struct spnic_sq_wqe_desc wqe_desc; -}; - -struct spnic_sq_extend_wqe { - struct spnic_sq_wqe_desc wqe_desc; - struct spnic_sq_task task; - struct spnic_sq_bufdesc buf_desc[0]; -}; - -struct spnic_sq_wqe { - union { - struct spnic_sq_compact_wqe compact_wqe; - struct spnic_sq_extend_wqe extend_wqe; - }; -}; - -/* use section pointer for support non continuous wqe */ -struct spnic_sq_wqe_combo { - struct spnic_sq_wqe_desc *ctrl_bd0; - struct spnic_sq_task *task; - struct spnic_sq_bufdesc *bds_head; - struct spnic_sq_bufdesc *bds_sec2; - u16 first_bds_num; - u32 wqe_type; - u32 task_type; -}; - -/* ************* SQ_CTRL ************** */ -enum sq_wqe_data_format { - SQ_NORMAL_WQE = 0, -}; - -enum sq_wqe_ec_type { - SQ_WQE_COMPACT_TYPE = 0, - SQ_WQE_EXTENDED_TYPE = 1, -}; - -enum sq_wqe_tasksect_len_type { - SQ_WQE_TASKSECT_46BITS = 0, - SQ_WQE_TASKSECT_16BYTES = 1, -}; - -#define SQ_CTRL_BD0_LEN_SHIFT 0 -#define SQ_CTRL_RSVD_SHIFT 18 -#define SQ_CTRL_BUFDESC_NUM_SHIFT 19 -#define SQ_CTRL_TASKSECT_LEN_SHIFT 27 -#define SQ_CTRL_DATA_FORMAT_SHIFT 28 -#define SQ_CTRL_DIRECT_SHIFT 29 -#define SQ_CTRL_EXTENDED_SHIFT 30 -#define SQ_CTRL_OWNER_SHIFT 31 - -#define SQ_CTRL_BD0_LEN_MASK 0x3FFFFU -#define SQ_CTRL_RSVD_MASK 0x1U -#define SQ_CTRL_BUFDESC_NUM_MASK 0xFFU -#define SQ_CTRL_TASKSECT_LEN_MASK 0x1U -#define SQ_CTRL_DATA_FORMAT_MASK 0x1U -#define SQ_CTRL_DIRECT_MASK 0x1U -#define SQ_CTRL_EXTENDED_MASK 0x1U -#define SQ_CTRL_OWNER_MASK 0x1U - -#define SQ_CTRL_SET(val, member) \ - (((u32)(val) & SQ_CTRL_##member##_MASK) << SQ_CTRL_##member##_SHIFT) - -#define SQ_CTRL_GET(val, member) \ - (((val) >> SQ_CTRL_##member##_SHIFT) & SQ_CTRL_##member##_MASK) - -#define SQ_CTRL_CLEAR(val, member) \ - ((val) & (~(SQ_CTRL_##member##_MASK << SQ_CTRL_##member##_SHIFT))) - -#define SQ_CTRL_QUEUE_INFO_PKT_TYPE_SHIFT 0 -#define SQ_CTRL_QUEUE_INFO_PLDOFF_SHIFT 2 -#define SQ_CTRL_QUEUE_INFO_UFO_SHIFT 10 -#define SQ_CTRL_QUEUE_INFO_TSO_SHIFT 11 -#define SQ_CTRL_QUEUE_INFO_TCPUDP_CS_SHIFT 12 -#define SQ_CTRL_QUEUE_INFO_MSS_SHIFT 13 -#define SQ_CTRL_QUEUE_INFO_SCTP_SHIFT 27 -#define SQ_CTRL_QUEUE_INFO_UC_SHIFT 28 -#define SQ_CTRL_QUEUE_INFO_PRI_SHIFT 29 - -#define SQ_CTRL_QUEUE_INFO_PKT_TYPE_MASK 0x3U -#define SQ_CTRL_QUEUE_INFO_PLDOFF_MASK 0xFFU -#define SQ_CTRL_QUEUE_INFO_UFO_MASK 0x1U -#define SQ_CTRL_QUEUE_INFO_TSO_MASK 0x1U -#define SQ_CTRL_QUEUE_INFO_TCPUDP_CS_MASK 0x1U -#define SQ_CTRL_QUEUE_INFO_MSS_MASK 0x3FFFU -#define SQ_CTRL_QUEUE_INFO_SCTP_MASK 0x1U -#define SQ_CTRL_QUEUE_INFO_UC_MASK 0x1U -#define SQ_CTRL_QUEUE_INFO_PRI_MASK 0x7U - -#define SQ_CTRL_QUEUE_INFO_SET(val, member) \ - (((u32)(val) & SQ_CTRL_QUEUE_INFO_##member##_MASK) << \ - SQ_CTRL_QUEUE_INFO_##member##_SHIFT) - -#define SQ_CTRL_QUEUE_INFO_GET(val, member) \ - (((val) >> SQ_CTRL_QUEUE_INFO_##member##_SHIFT) & \ - SQ_CTRL_QUEUE_INFO_##member##_MASK) - -#define SQ_CTRL_QUEUE_INFO_CLEAR(val, member) \ - ((val) & (~(SQ_CTRL_QUEUE_INFO_##member##_MASK << \ - SQ_CTRL_QUEUE_INFO_##member##_SHIFT))) - -#define SQ_TASK_INFO0_TUNNEL_FLAG_SHIFT 19 -#define SQ_TASK_INFO0_ESP_NEXT_PROTO_SHIFT 22 -#define SQ_TASK_INFO0_INNER_L4_EN_SHIFT 24 -#define SQ_TASK_INFO0_INNER_L3_EN_SHIFT 25 -#define SQ_TASK_INFO0_INNER_L4_PSEUDO_SHIFT 26 -#define SQ_TASK_INFO0_OUT_L4_EN_SHIFT 27 -#define SQ_TASK_INFO0_OUT_L3_EN_SHIFT 28 -#define SQ_TASK_INFO0_OUT_L4_PSEUDO_SHIFT 29 -#define SQ_TASK_INFO0_ESP_OFFLOAD_SHIFT 30 -#define SQ_TASK_INFO0_IPSEC_PROTO_SHIFT 31 - -#define SQ_TASK_INFO0_TUNNEL_FLAG_MASK 0x1U -#define SQ_TASK_INFO0_ESP_NEXT_PROTO_MASK 0x3U -#define SQ_TASK_INFO0_INNER_L4_EN_MASK 0x1U -#define SQ_TASK_INFO0_INNER_L3_EN_MASK 0x1U -#define SQ_TASK_INFO0_INNER_L4_PSEUDO_MASK 0x1U -#define SQ_TASK_INFO0_OUT_L4_EN_MASK 0x1U -#define SQ_TASK_INFO0_OUT_L3_EN_MASK 0x1U -#define SQ_TASK_INFO0_OUT_L4_PSEUDO_MASK 0x1U -#define SQ_TASK_INFO0_ESP_OFFLOAD_MASK 0x1U -#define SQ_TASK_INFO0_IPSEC_PROTO_MASK 0x1U - -#define SQ_TASK_INFO0_SET(val, member) \ - (((u32)(val) & SQ_TASK_INFO0_##member##_MASK) << \ - SQ_TASK_INFO0_##member##_SHIFT) -#define SQ_TASK_INFO0_GET(val, member) \ - (((val) >> SQ_TASK_INFO0_##member##_SHIFT) & \ - SQ_TASK_INFO0_##member##_MASK) - -#define SQ_TASK_INFO1_SET(val, member) \ - (((val) & SQ_TASK_INFO1_##member##_MASK) << \ - SQ_TASK_INFO1_##member##_SHIFT) -#define SQ_TASK_INFO1_GET(val, member) \ - (((val) >> SQ_TASK_INFO1_##member##_SHIFT) & \ - SQ_TASK_INFO1_##member##_MASK) - -#define SQ_TASK_INFO3_VLAN_TAG_SHIFT 0 -#define SQ_TASK_INFO3_VLAN_TYPE_SHIFT 16 -#define SQ_TASK_INFO3_VLAN_TAG_VALID_SHIFT 19 - -#define SQ_TASK_INFO3_VLAN_TAG_MASK 0xFFFFU -#define SQ_TASK_INFO3_VLAN_TYPE_MASK 0x7U -#define SQ_TASK_INFO3_VLAN_TAG_VALID_MASK 0x1U - -#define SQ_TASK_INFO3_SET(val, member) \ - (((val) & SQ_TASK_INFO3_##member##_MASK) << \ - SQ_TASK_INFO3_##member##_SHIFT) -#define SQ_TASK_INFO3_GET(val, member) \ - (((val) >> SQ_TASK_INFO3_##member##_SHIFT) & \ - SQ_TASK_INFO3_##member##_MASK) - -static inline u32 spnic_get_pkt_len_for_super_cqe(struct spnic_rq_cqe *cqe, bool last) -{ - u32 pkt_len = cqe->pkt_info; - - if (!last) - return RQ_CQE_PKT_LEN_GET(pkt_len, FIRST_LEN); - else - return RQ_CQE_PKT_LEN_GET(pkt_len, LAST_LEN); -} - -/* * - * spnic_prepare_sq_ctrl - init sq wqe cs - * @nr_descs: total sge_num, include bd0 in cs - * to do : check with zhangxingguo to confirm WQE init - */ -static inline void spnic_prepare_sq_ctrl(struct spnic_sq_wqe_combo *wqe_combo, - u32 queue_info, int nr_descs, u16 owner) -{ - struct spnic_sq_wqe_desc *wqe_desc = wqe_combo->ctrl_bd0; - - if (wqe_combo->wqe_type == SQ_WQE_COMPACT_TYPE) { - wqe_desc->ctrl_len |= - SQ_CTRL_SET(SQ_NORMAL_WQE, DATA_FORMAT) | - SQ_CTRL_SET(wqe_combo->wqe_type, EXTENDED) | - SQ_CTRL_SET(owner, OWNER); - - /* compact wqe queue_info will transfer to ucode */ - wqe_desc->queue_info = 0; - return; - } - - wqe_desc->ctrl_len |= SQ_CTRL_SET(nr_descs, BUFDESC_NUM) | - SQ_CTRL_SET(wqe_combo->task_type, TASKSECT_LEN) | - SQ_CTRL_SET(SQ_NORMAL_WQE, DATA_FORMAT) | - SQ_CTRL_SET(wqe_combo->wqe_type, EXTENDED) | - SQ_CTRL_SET(owner, OWNER); - - wqe_desc->queue_info = queue_info; - wqe_desc->queue_info |= SQ_CTRL_QUEUE_INFO_SET(1U, UC); - - if (!SQ_CTRL_QUEUE_INFO_GET(wqe_desc->queue_info, MSS)) { - wqe_desc->queue_info |= SQ_CTRL_QUEUE_INFO_SET(TX_MSS_DEFAULT, MSS); - } else if (SQ_CTRL_QUEUE_INFO_GET(wqe_desc->queue_info, MSS) < TX_MSS_MIN) { - /* mss should not less than 80 */ - wqe_desc->queue_info = SQ_CTRL_QUEUE_INFO_CLEAR(wqe_desc->queue_info, MSS); - wqe_desc->queue_info |= SQ_CTRL_QUEUE_INFO_SET(TX_MSS_MIN, MSS); - } -} - -/* * - * spnic_set_vlan_tx_offload - set vlan offload info - * @task: wqe task section - * @vlan_tag: vlan tag - * @vlan_type: 0--select TPID0 in IPSU, 1--select TPID0 in IPSU - * 2--select TPID2 in IPSU, 3--select TPID3 in IPSU, 4--select TPID4 in IPSU - */ -static inline void spnic_set_vlan_tx_offload(struct spnic_sq_task *task, u16 vlan_tag, u8 vlan_type) -{ - task->vlan_offload = SQ_TASK_INFO3_SET(vlan_tag, VLAN_TAG) | - SQ_TASK_INFO3_SET(vlan_type, VLAN_TYPE) | - SQ_TASK_INFO3_SET(1U, VLAN_TAG_VALID); -} - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_ntuple.c b/drivers/net/ethernet/ramaxel/spnic/spnic_ntuple.c deleted file mode 100644 index cd92de93a57e..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_ntuple.c +++ /dev/null @@ -1,841 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [NIC]" fmt - -#include <linux/kernel.h> -#include <linux/etherdevice.h> -#include <linux/netdevice.h> -#include <linux/device.h> -#include <linux/ethtool.h> -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/types.h> -#include <linux/errno.h> - -#include "sphw_common.h" -#include "sphw_crm.h" -#include "spnic_nic_cfg.h" -#include "spnic_nic_dev.h" - -#define MAX_NUM_OF_ETHTOOL_NTUPLE_RULES BIT(9) -struct spnic_ethtool_rx_flow_rule { - struct list_head list; - struct ethtool_rx_flow_spec flow_spec; -}; - -static void tcam_translate_key_y(u8 *key_y, u8 *src_input, u8 *mask, u8 len) -{ - u8 idx; - - for (idx = 0; idx < len; idx++) - key_y[idx] = src_input[idx] & mask[idx]; -} - -static void tcam_translate_key_x(u8 *key_x, u8 *key_y, u8 *mask, u8 len) -{ - u8 idx; - - for (idx = 0; idx < len; idx++) - key_x[idx] = key_y[idx] ^ mask[idx]; -} - -static void tcam_key_calculate(struct tag_tcam_key *tcam_key, - struct nic_tcam_cfg_rule *fdir_tcam_rule) -{ - tcam_translate_key_y(fdir_tcam_rule->key.y, (u8 *)(&tcam_key->key_info), - (u8 *)(&tcam_key->key_mask), TCAM_FLOW_KEY_SIZE); - tcam_translate_key_x(fdir_tcam_rule->key.x, fdir_tcam_rule->key.y, - (u8 *)(&tcam_key->key_mask), TCAM_FLOW_KEY_SIZE); -} - -#define TCAM_IPV4_TYPE 0 -#define TCAM_IPV6_TYPE 1 - -static int spnic_base_ipv4_parse(struct spnic_nic_dev *nic_dev, struct ethtool_rx_flow_spec *fs, - struct tag_tcam_key *tcam_key) -{ - struct ethtool_tcpip4_spec *mask = &fs->m_u.tcp_ip4_spec; - struct ethtool_tcpip4_spec *val = &fs->h_u.tcp_ip4_spec; - u32 temp; - - switch (mask->ip4src) { - case U32_MAX: - temp = ntohl(val->ip4src); - tcam_key->key_info.sipv4_h = high_16_bits(temp); - tcam_key->key_info.sipv4_l = low_16_bits(temp); - - tcam_key->key_mask.sipv4_h = U16_MAX; - tcam_key->key_mask.sipv4_l = U16_MAX; - break; - case 0: - break; - - default: - nicif_err(nic_dev, drv, nic_dev->netdev, "invalid src_ip mask\n"); - return -EINVAL; - } - - switch (mask->ip4dst) { - case U32_MAX: - temp = ntohl(val->ip4dst); - tcam_key->key_info.dipv4_h = high_16_bits(temp); - tcam_key->key_info.dipv4_l = low_16_bits(temp); - - tcam_key->key_mask.dipv4_h = U16_MAX; - tcam_key->key_mask.dipv4_l = U16_MAX; - break; - case 0: - break; - - default: - nicif_err(nic_dev, drv, nic_dev->netdev, "invalid src_ip mask\n"); - return -EINVAL; - } - - tcam_key->key_info.ip_type = TCAM_IPV4_TYPE; - tcam_key->key_mask.ip_type = TCAM_IP_TYPE_MASK; - - tcam_key->key_info.function_id = sphw_global_func_id(nic_dev->hwdev); - tcam_key->key_mask.function_id = TCAM_FUNC_ID_MASK; - - return 0; -} - -static int spnic_fdir_tcam_ipv4_l4_init(struct spnic_nic_dev *nic_dev, - struct ethtool_rx_flow_spec *fs, - struct tag_tcam_key *tcam_key) -{ - struct ethtool_tcpip4_spec *l4_mask = &fs->m_u.tcp_ip4_spec; - struct ethtool_tcpip4_spec *l4_val = &fs->h_u.tcp_ip4_spec; - int err; - - err = spnic_base_ipv4_parse(nic_dev, fs, tcam_key); - if (err) - return err; - - tcam_key->key_info.dport = ntohs(l4_val->pdst); - tcam_key->key_mask.dport = l4_mask->pdst; - - tcam_key->key_info.sport = ntohs(l4_val->psrc); - tcam_key->key_mask.sport = l4_mask->psrc; - - if (fs->flow_type == TCP_V4_FLOW) - tcam_key->key_info.ip_proto = IPPROTO_TCP; - else - tcam_key->key_info.ip_proto = IPPROTO_UDP; - tcam_key->key_mask.ip_proto = U8_MAX; - - return 0; -} - -static int spnic_fdir_tcam_ipv4_init(struct spnic_nic_dev *nic_dev, - struct ethtool_rx_flow_spec *fs, - struct tag_tcam_key *tcam_key) -{ - struct ethtool_usrip4_spec *l3_mask = &fs->m_u.usr_ip4_spec; - struct ethtool_usrip4_spec *l3_val = &fs->h_u.usr_ip4_spec; - int err; - - err = spnic_base_ipv4_parse(nic_dev, fs, tcam_key); - if (err) - return err; - - tcam_key->key_info.ip_proto = l3_val->proto; - tcam_key->key_mask.ip_proto = l3_mask->proto; - - return 0; -} - -#ifndef UNSUPPORT_NTUPLE_IPV6 -enum ipv6_parse_res { - IPV6_MASK_INVALID, - IPV6_MASK_ALL_MASK, - IPV6_MASK_ALL_ZERO, -}; - -enum ipv6_index { - IPV6_IDX0, - IPV6_IDX1, - IPV6_IDX2, - IPV6_IDX3, -}; - -static int ipv6_mask_parse(u32 *ipv6_mask) -{ - if (ipv6_mask[IPV6_IDX0] == 0 && ipv6_mask[IPV6_IDX1] == 0 && - ipv6_mask[IPV6_IDX2] == 0 && ipv6_mask[IPV6_IDX3] == 0) - return IPV6_MASK_ALL_ZERO; - - if (ipv6_mask[IPV6_IDX0] == U32_MAX && - ipv6_mask[IPV6_IDX1] == U32_MAX && - ipv6_mask[IPV6_IDX2] == U32_MAX && ipv6_mask[IPV6_IDX3] == U32_MAX) - return IPV6_MASK_ALL_MASK; - - return IPV6_MASK_INVALID; -} - -static int spnic_base_ipv6_parse(struct spnic_nic_dev *nic_dev, - struct ethtool_rx_flow_spec *fs, - struct tag_tcam_key *tcam_key) -{ - struct ethtool_tcpip6_spec *mask = &fs->m_u.tcp_ip6_spec; - struct ethtool_tcpip6_spec *val = &fs->h_u.tcp_ip6_spec; - int parse_res; - u32 temp; - - parse_res = ipv6_mask_parse((u32 *)mask->ip6src); - if (parse_res == IPV6_MASK_ALL_MASK) { - temp = ntohl(val->ip6src[IPV6_IDX0]); - tcam_key->key_info_ipv6.sipv6_key0 = high_16_bits(temp); - tcam_key->key_info_ipv6.sipv6_key1 = low_16_bits(temp); - temp = ntohl(val->ip6src[IPV6_IDX1]); - tcam_key->key_info_ipv6.sipv6_key2 = high_16_bits(temp); - tcam_key->key_info_ipv6.sipv6_key3 = low_16_bits(temp); - temp = ntohl(val->ip6src[IPV6_IDX2]); - tcam_key->key_info_ipv6.sipv6_key4 = high_16_bits(temp); - tcam_key->key_info_ipv6.sipv6_key5 = low_16_bits(temp); - temp = ntohl(val->ip6src[IPV6_IDX3]); - tcam_key->key_info_ipv6.sipv6_key6 = high_16_bits(temp); - tcam_key->key_info_ipv6.sipv6_key7 = low_16_bits(temp); - - tcam_key->key_mask_ipv6.sipv6_key0 = U16_MAX; - tcam_key->key_mask_ipv6.sipv6_key1 = U16_MAX; - tcam_key->key_mask_ipv6.sipv6_key2 = U16_MAX; - tcam_key->key_mask_ipv6.sipv6_key3 = U16_MAX; - tcam_key->key_mask_ipv6.sipv6_key4 = U16_MAX; - tcam_key->key_mask_ipv6.sipv6_key5 = U16_MAX; - tcam_key->key_mask_ipv6.sipv6_key6 = U16_MAX; - tcam_key->key_mask_ipv6.sipv6_key7 = U16_MAX; - } else if (parse_res == IPV6_MASK_INVALID) { - nicif_err(nic_dev, drv, nic_dev->netdev, "invalid src_ipv6 mask\n"); - return -EINVAL; - } - - parse_res = ipv6_mask_parse((u32 *)mask->ip6dst); - if (parse_res == IPV6_MASK_ALL_MASK) { - temp = ntohl(val->ip6dst[IPV6_IDX0]); - tcam_key->key_info_ipv6.dipv6_key0 = high_16_bits(temp); - tcam_key->key_info_ipv6.dipv6_key1 = low_16_bits(temp); - temp = ntohl(val->ip6dst[IPV6_IDX1]); - tcam_key->key_info_ipv6.dipv6_key2 = high_16_bits(temp); - tcam_key->key_info_ipv6.dipv6_key3 = low_16_bits(temp); - temp = ntohl(val->ip6dst[IPV6_IDX2]); - tcam_key->key_info_ipv6.dipv6_key4 = high_16_bits(temp); - tcam_key->key_info_ipv6.dipv6_key5 = low_16_bits(temp); - temp = ntohl(val->ip6dst[IPV6_IDX3]); - tcam_key->key_info_ipv6.dipv6_key6 = high_16_bits(temp); - tcam_key->key_info_ipv6.dipv6_key7 = low_16_bits(temp); - - tcam_key->key_mask_ipv6.dipv6_key0 = U16_MAX; - tcam_key->key_mask_ipv6.dipv6_key1 = U16_MAX; - tcam_key->key_mask_ipv6.dipv6_key2 = U16_MAX; - tcam_key->key_mask_ipv6.dipv6_key3 = U16_MAX; - tcam_key->key_mask_ipv6.dipv6_key4 = U16_MAX; - tcam_key->key_mask_ipv6.dipv6_key5 = U16_MAX; - tcam_key->key_mask_ipv6.dipv6_key6 = U16_MAX; - tcam_key->key_mask_ipv6.dipv6_key7 = U16_MAX; - } else if (parse_res == IPV6_MASK_INVALID) { - nicif_err(nic_dev, drv, nic_dev->netdev, "invalid dst_ipv6 mask\n"); - return -EINVAL; - } - - tcam_key->key_info_ipv6.ip_type = TCAM_IPV6_TYPE; - tcam_key->key_mask_ipv6.ip_type = TCAM_IP_TYPE_MASK; - - tcam_key->key_info_ipv6.function_id = sphw_global_func_id(nic_dev->hwdev); - tcam_key->key_mask_ipv6.function_id = TCAM_FUNC_ID_MASK; - - return 0; -} - -static int spnic_fdir_tcam_ipv6_l4_init(struct spnic_nic_dev *nic_dev, - struct ethtool_rx_flow_spec *fs, - struct tag_tcam_key *tcam_key) -{ - struct ethtool_tcpip6_spec *l4_mask = &fs->m_u.tcp_ip6_spec; - struct ethtool_tcpip6_spec *l4_val = &fs->h_u.tcp_ip6_spec; - int err; - - err = spnic_base_ipv6_parse(nic_dev, fs, tcam_key); - if (err) - return err; - - tcam_key->key_info_ipv6.dport = ntohs(l4_val->pdst); - tcam_key->key_mask_ipv6.dport = l4_mask->pdst; - - tcam_key->key_info_ipv6.sport = ntohs(l4_val->psrc); - tcam_key->key_mask_ipv6.sport = l4_mask->psrc; - - if (fs->flow_type == TCP_V6_FLOW) - tcam_key->key_info_ipv6.ip_proto = NEXTHDR_TCP; - else - tcam_key->key_info_ipv6.ip_proto = NEXTHDR_UDP; - tcam_key->key_mask_ipv6.ip_proto = U8_MAX; - - return 0; -} - -static int spnic_fdir_tcam_ipv6_init(struct spnic_nic_dev *nic_dev, - struct ethtool_rx_flow_spec *fs, - struct tag_tcam_key *tcam_key) -{ - struct ethtool_usrip6_spec *l3_mask = &fs->m_u.usr_ip6_spec; - struct ethtool_usrip6_spec *l3_val = &fs->h_u.usr_ip6_spec; - int err; - - err = spnic_base_ipv6_parse(nic_dev, fs, tcam_key); - if (err) - return err; - - tcam_key->key_info_ipv6.ip_proto = l3_val->l4_proto; - tcam_key->key_mask_ipv6.ip_proto = l3_mask->l4_proto; - - return 0; -} -#endif - -static int spnic_fdir_tcam_info_init(struct spnic_nic_dev *nic_dev, - struct ethtool_rx_flow_spec *fs, - struct tag_tcam_key *tcam_key, - struct nic_tcam_cfg_rule *fdir_tcam_rule) -{ - int err; - - switch (fs->flow_type) { - case TCP_V4_FLOW: - case UDP_V4_FLOW: - err = spnic_fdir_tcam_ipv4_l4_init(nic_dev, fs, tcam_key); - if (err) - return err; - break; - case IP_USER_FLOW: - err = spnic_fdir_tcam_ipv4_init(nic_dev, fs, tcam_key); - if (err) - return err; - break; -#ifndef UNSUPPORT_NTUPLE_IPV6 - case TCP_V6_FLOW: - case UDP_V6_FLOW: - err = spnic_fdir_tcam_ipv6_l4_init(nic_dev, fs, tcam_key); - if (err) - return err; - break; - case IPV6_USER_FLOW: - err = spnic_fdir_tcam_ipv6_init(nic_dev, fs, tcam_key); - if (err) - return err; - break; -#endif - default: - return -EOPNOTSUPP; - } - - tcam_key->key_info.tunnel_type = 0; - tcam_key->key_mask.tunnel_type = TCAM_TUNNEL_TYPE_MASK; - - fdir_tcam_rule->data.qid = (u32)fs->ring_cookie; - tcam_key_calculate(tcam_key, fdir_tcam_rule); - - return 0; -} - -void spnic_flush_rx_flow_rule(struct spnic_nic_dev *nic_dev) -{ - struct spnic_tcam_info *tcam_info = &nic_dev->tcam; - struct spnic_ethtool_rx_flow_rule *eth_rule = NULL; - struct spnic_ethtool_rx_flow_rule *eth_rule_tmp = NULL; - struct spnic_tcam_filter *tcam_iter = NULL; - struct spnic_tcam_filter *tcam_iter_tmp = NULL; - struct spnic_tcam_dynamic_block *block = NULL; - struct spnic_tcam_dynamic_block *block_tmp = NULL; - struct list_head *dynamic_list = &tcam_info->tcam_dynamic_info.tcam_dynamic_list; - - if (!list_empty(&tcam_info->tcam_list)) { - list_for_each_entry_safe(tcam_iter, tcam_iter_tmp, &tcam_info->tcam_list, - tcam_filter_list) { - list_del(&tcam_iter->tcam_filter_list); - kfree(tcam_iter); - } - } - if (!list_empty(dynamic_list)) { - list_for_each_entry_safe(block, block_tmp, dynamic_list, block_list) { - list_del(&block->block_list); - kfree(block); - } - } - - if (!list_empty(&nic_dev->rx_flow_rule.rules)) { - list_for_each_entry_safe(eth_rule, eth_rule_tmp, - &nic_dev->rx_flow_rule.rules, list) { - list_del(ð_rule->list); - kfree(eth_rule); - } - } - -#ifndef FPGA_SUPPORT - spnic_flush_tcam_rule(nic_dev->hwdev); - spnic_set_fdir_tcam_rule_filter(nic_dev->hwdev, false); -#endif -} - -static struct spnic_tcam_dynamic_block * -spnic_alloc_dynamic_block_resource(struct spnic_nic_dev *nic_dev, - struct spnic_tcam_info *tcam_info, u16 dynamic_block_id) -{ - struct spnic_tcam_dynamic_block *dynamic_block_ptr = NULL; - - dynamic_block_ptr = kzalloc(sizeof(*dynamic_block_ptr), GFP_KERNEL); - if (!dynamic_block_ptr) { - nicif_err(nic_dev, drv, nic_dev->netdev, "fdir filter dynamic alloc block index %d memory failed\n", - dynamic_block_id); - return NULL; - } - - dynamic_block_ptr->dynamic_block_id = dynamic_block_id; - list_add_tail(&dynamic_block_ptr->block_list, - &tcam_info->tcam_dynamic_info.tcam_dynamic_list); - - tcam_info->tcam_dynamic_info.dynamic_block_cnt++; - - return dynamic_block_ptr; -} - -static void -spnic_free_dynamic_block_resource(struct spnic_tcam_info *tcam_info, - struct spnic_tcam_dynamic_block *block_ptr) -{ - if (!block_ptr) - return; - - list_del(&block_ptr->block_list); - kfree(block_ptr); - - tcam_info->tcam_dynamic_info.dynamic_block_cnt--; -} - -static struct spnic_tcam_dynamic_block * -spnic_dynamic_lookup_tcam_filter(struct spnic_nic_dev *nic_dev, - struct nic_tcam_cfg_rule *fdir_tcam_rule, - struct spnic_tcam_info *tcam_info, - struct spnic_tcam_filter *tcam_filter, u16 *tcam_index) -{ - struct spnic_tcam_dynamic_block *tmp = NULL; - u16 index; - - list_for_each_entry(tmp, &tcam_info->tcam_dynamic_info.tcam_dynamic_list, block_list) - if (tmp->dynamic_index_cnt < SPNIC_TCAM_DYNAMIC_BLOCK_SIZE) - break; - - if (!tmp || tmp->dynamic_index_cnt >= SPNIC_TCAM_DYNAMIC_BLOCK_SIZE) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Fdir filter dynamic lookup for index failed\n"); - return NULL; - } - - for (index = 0; index < SPNIC_TCAM_DYNAMIC_BLOCK_SIZE; index++) - if (tmp->dynamic_index_used[index] == 0) - break; - - if (index == SPNIC_TCAM_DYNAMIC_BLOCK_SIZE) { - nicif_err(nic_dev, drv, nic_dev->netdev, "tcam block 0x%x supports filter rules is full\n", - tmp->dynamic_block_id); - return NULL; - } - - tcam_filter->dynamic_block_id = tmp->dynamic_block_id; - tcam_filter->index = index; - *tcam_index = index; - - fdir_tcam_rule->index = index + - SPNIC_PKT_TCAM_DYNAMIC_INDEX_START(tmp->dynamic_block_id); - - return tmp; -} - -static int spnic_add_tcam_filter(struct spnic_nic_dev *nic_dev, - struct spnic_tcam_filter *tcam_filter, - struct nic_tcam_cfg_rule *fdir_tcam_rule) -{ - struct spnic_tcam_info *tcam_info = &nic_dev->tcam; - struct spnic_tcam_dynamic_block *dynamic_block_ptr = NULL; - struct spnic_tcam_dynamic_block *tmp = NULL; - u16 block_cnt = tcam_info->tcam_dynamic_info.dynamic_block_cnt; - u16 tcam_block_index = 0; - int block_alloc_flag = 0; - u16 index = 0; - int err; - - if (tcam_info->tcam_rule_nums >= - block_cnt * SPNIC_TCAM_DYNAMIC_BLOCK_SIZE) { - if (block_cnt >= (SPNIC_MAX_TCAM_FILTERS / SPNIC_TCAM_DYNAMIC_BLOCK_SIZE)) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Dynamic tcam block is full, alloc failed\n"); - goto failed; - } - - err = spnic_alloc_tcam_block(nic_dev->hwdev, &tcam_block_index); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Fdir filter dynamic tcam alloc block failed\n"); - goto failed; - } - - block_alloc_flag = 1; - - dynamic_block_ptr = - spnic_alloc_dynamic_block_resource(nic_dev, tcam_info, tcam_block_index); - if (!dynamic_block_ptr) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Fdir filter dynamic alloc block memory failed\n"); - goto block_alloc_failed; - } - } - - tmp = spnic_dynamic_lookup_tcam_filter(nic_dev, fdir_tcam_rule, tcam_info, - tcam_filter, &index); - if (!tmp) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Dynamic lookup tcam filter failed\n"); - goto lookup_tcam_index_failed; - } - - err = spnic_add_tcam_rule(nic_dev->hwdev, fdir_tcam_rule); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Fdir_tcam_rule add failed\n"); - goto add_tcam_rules_failed; - } - - nicif_info(nic_dev, drv, nic_dev->netdev, - "Add fdir tcam rule, function_id: 0x%x, tcam_block_id: %d, local_index: %d, global_index: %d, queue: %d, tcam_rule_nums: %d succeed\n", - sphw_global_func_id(nic_dev->hwdev), - tcam_filter->dynamic_block_id, index, fdir_tcam_rule->index, - fdir_tcam_rule->data.qid, tcam_info->tcam_rule_nums + 1); - - if (tcam_info->tcam_rule_nums == 0) { - err = spnic_set_fdir_tcam_rule_filter(nic_dev->hwdev, true); - if (err) - goto enable_failed; - } - - list_add_tail(&tcam_filter->tcam_filter_list, &tcam_info->tcam_list); - - tmp->dynamic_index_used[index] = 1; - tmp->dynamic_index_cnt++; - - tcam_info->tcam_rule_nums++; - - return 0; - -enable_failed: - spnic_del_tcam_rule(nic_dev->hwdev, fdir_tcam_rule->index); - -add_tcam_rules_failed: -lookup_tcam_index_failed: - if (block_alloc_flag == 1) - spnic_free_dynamic_block_resource(tcam_info, dynamic_block_ptr); - -block_alloc_failed: - if (block_alloc_flag == 1) - spnic_free_tcam_block(nic_dev->hwdev, &tcam_block_index); - -failed: - return -EFAULT; -} - -static int spnic_del_tcam_filter(struct spnic_nic_dev *nic_dev, - struct spnic_tcam_filter *tcam_filter) -{ - struct spnic_tcam_info *tcam_info = &nic_dev->tcam; - u16 dynamic_block_id = tcam_filter->dynamic_block_id; - struct spnic_tcam_dynamic_block *tmp = NULL; - u32 index = 0; - int err; - - list_for_each_entry(tmp, &tcam_info->tcam_dynamic_info.tcam_dynamic_list, block_list) { - if (tmp->dynamic_block_id == dynamic_block_id) - break; - } - if (!tmp || tmp->dynamic_block_id != dynamic_block_id) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Fdir filter del dynamic lookup for block failed\n"); - return -EFAULT; - } - - index = SPNIC_PKT_TCAM_DYNAMIC_INDEX_START(tmp->dynamic_block_id) + tcam_filter->index; - - err = spnic_del_tcam_rule(nic_dev->hwdev, index); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, "fdir_tcam_rule del failed\n"); - return -EFAULT; - } - - nicif_info(nic_dev, drv, nic_dev->netdev, - "Del fdir_tcam_dynamic_rule function_id: 0x%x, tcam_block_id: %d, local_index: %d, global_index: %d, local_rules_nums: %d, global_rule_nums: %d succeed\n", - sphw_global_func_id(nic_dev->hwdev), dynamic_block_id, - tcam_filter->index, index, tmp->dynamic_index_cnt - 1, - tcam_info->tcam_rule_nums - 1); - - tmp->dynamic_index_used[tcam_filter->index] = 0; - tmp->dynamic_index_cnt--; - tcam_info->tcam_rule_nums--; - if (tmp->dynamic_index_cnt == 0) { - spnic_free_tcam_block(nic_dev->hwdev, &dynamic_block_id); - spnic_free_dynamic_block_resource(tcam_info, tmp); - } - - if (tcam_info->tcam_rule_nums == 0) - spnic_set_fdir_tcam_rule_filter(nic_dev->hwdev, false); - - list_del(&tcam_filter->tcam_filter_list); - kfree(tcam_filter); - - return 0; -} - -static inline struct spnic_tcam_filter * -spnic_tcam_filter_lookup(struct list_head *filter_list, struct tag_tcam_key *key) -{ - struct spnic_tcam_filter *iter; - - list_for_each_entry(iter, filter_list, tcam_filter_list) { - if (memcmp(key, &iter->tcam_key, sizeof(struct tag_tcam_key)) == 0) - return iter; - } - - return NULL; -} - -static void del_ethtool_rule(struct spnic_nic_dev *nic_dev, - struct spnic_ethtool_rx_flow_rule *eth_rule) -{ - list_del(ð_rule->list); - nic_dev->rx_flow_rule.tot_num_rules--; - - kfree(eth_rule); -} - -static int spnic_remove_one_rule(struct spnic_nic_dev *nic_dev, - struct spnic_ethtool_rx_flow_rule *eth_rule) -{ - struct spnic_tcam_info *tcam_info = &nic_dev->tcam; - struct spnic_tcam_filter *tcam_filter; - struct nic_tcam_cfg_rule fdir_tcam_rule; - struct tag_tcam_key tcam_key; - int err; - - memset(&fdir_tcam_rule, 0, sizeof(fdir_tcam_rule)); - memset(&tcam_key, 0, sizeof(tcam_key)); - - err = spnic_fdir_tcam_info_init(nic_dev, ð_rule->flow_spec, &tcam_key, &fdir_tcam_rule); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Init fdir info failed\n"); - return err; - } - - tcam_filter = spnic_tcam_filter_lookup(&tcam_info->tcam_list, &tcam_key); - if (!tcam_filter) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Filter does not exists\n"); - return -EEXIST; - } - - err = spnic_del_tcam_filter(nic_dev, tcam_filter); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Delete tcam filter failed\n"); - return err; - } - - del_ethtool_rule(nic_dev, eth_rule); - - return 0; -} - -static void add_rule_to_list(struct spnic_nic_dev *nic_dev, - struct spnic_ethtool_rx_flow_rule *rule) -{ - struct spnic_ethtool_rx_flow_rule *iter = NULL; - struct list_head *head = &nic_dev->rx_flow_rule.rules; - - list_for_each_entry(iter, &nic_dev->rx_flow_rule.rules, list) { - if (iter->flow_spec.location > rule->flow_spec.location) - break; - head = &iter->list; - } - nic_dev->rx_flow_rule.tot_num_rules++; - list_add(&rule->list, head); -} - -static int spnic_add_one_rule(struct spnic_nic_dev *nic_dev, struct ethtool_rx_flow_spec *fs) -{ - struct nic_tcam_cfg_rule fdir_tcam_rule; - struct tag_tcam_key tcam_key; - struct spnic_ethtool_rx_flow_rule *eth_rule = NULL; - struct spnic_tcam_filter *tcam_filter = NULL; - struct spnic_tcam_info *tcam_info = &nic_dev->tcam; - int err; - - memset(&fdir_tcam_rule, 0, sizeof(fdir_tcam_rule)); - memset(&tcam_key, 0, sizeof(tcam_key)); - err = spnic_fdir_tcam_info_init(nic_dev, fs, &tcam_key, &fdir_tcam_rule); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Init fdir info failed\n"); - return err; - } - - tcam_filter = spnic_tcam_filter_lookup(&tcam_info->tcam_list, &tcam_key); - if (tcam_filter) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Filter exists\n"); - return -EEXIST; - } - - tcam_filter = kzalloc(sizeof(*tcam_filter), GFP_KERNEL); - if (!tcam_filter) - return -ENOMEM; - memcpy(&tcam_filter->tcam_key, &tcam_key, sizeof(struct tag_tcam_key)); - tcam_filter->queue = (u16)fdir_tcam_rule.data.qid; - - err = spnic_add_tcam_filter(nic_dev, tcam_filter, &fdir_tcam_rule); - if (err) - goto add_tcam_filter_fail; - - /* driver save new rule filter */ - eth_rule = kzalloc(sizeof(*eth_rule), GFP_KERNEL); - if (!eth_rule) { - err = -ENOMEM; - goto alloc_eth_rule_fail; - } - - eth_rule->flow_spec = *fs; - add_rule_to_list(nic_dev, eth_rule); - - return 0; - -alloc_eth_rule_fail: - spnic_del_tcam_filter(nic_dev, tcam_filter); -add_tcam_filter_fail: - kfree(tcam_filter); - return err; -} - -static struct spnic_ethtool_rx_flow_rule * -find_ethtool_rule(struct spnic_nic_dev *nic_dev, u32 location) -{ - struct spnic_ethtool_rx_flow_rule *iter = NULL; - - list_for_each_entry(iter, &nic_dev->rx_flow_rule.rules, list) { - if (iter->flow_spec.location == location) - return iter; - } - return NULL; -} - -static int validate_flow(struct spnic_nic_dev *nic_dev, struct ethtool_rx_flow_spec *fs) -{ - if (fs->location >= MAX_NUM_OF_ETHTOOL_NTUPLE_RULES) { - nicif_err(nic_dev, drv, nic_dev->netdev, "loc exceed limit[0,%lu]\n", - MAX_NUM_OF_ETHTOOL_NTUPLE_RULES); - return -EINVAL; - } - - if (fs->ring_cookie >= nic_dev->q_params.num_qps) { - nicif_err(nic_dev, drv, nic_dev->netdev, "action is larger than queue number %u\n", - nic_dev->q_params.num_qps); - return -EINVAL; - } - - switch (fs->flow_type) { - case TCP_V4_FLOW: - case UDP_V4_FLOW: - case IP_USER_FLOW: -#ifndef UNSUPPORT_NTUPLE_IPV6 - case TCP_V6_FLOW: - case UDP_V6_FLOW: - case IPV6_USER_FLOW: -#endif - break; - default: - nicif_err(nic_dev, drv, nic_dev->netdev, "flow type is not supported\n"); - return -EOPNOTSUPP; - } - - return 0; -} - -int spnic_ethtool_flow_replace(struct spnic_nic_dev *nic_dev, struct ethtool_rx_flow_spec *fs) -{ - struct spnic_ethtool_rx_flow_rule *eth_rule = NULL; - struct ethtool_rx_flow_spec flow_spec_temp; - int loc_exit_flag = 0; - int err; - - err = validate_flow(nic_dev, fs); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, "flow is not valid %d\n", err); - return err; - } - - eth_rule = find_ethtool_rule(nic_dev, fs->location); - /* when location is same, delete old location rule. */ - if (eth_rule) { - memcpy(&flow_spec_temp, ð_rule->flow_spec, sizeof(struct ethtool_rx_flow_spec)); - err = spnic_remove_one_rule(nic_dev, eth_rule); - if (err) - return err; - - loc_exit_flag = 1; - } - - /* add new rule filter */ - err = spnic_add_one_rule(nic_dev, fs); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Add new rule filter failed\n"); - if (loc_exit_flag) - spnic_add_one_rule(nic_dev, &flow_spec_temp); - - return -ENOENT; - } - - return 0; -} - -int spnic_ethtool_flow_remove(struct spnic_nic_dev *nic_dev, u32 location) -{ - struct spnic_ethtool_rx_flow_rule *eth_rule = NULL; - int err; - - if (location >= MAX_NUM_OF_ETHTOOL_NTUPLE_RULES) - return -ENOSPC; - - eth_rule = find_ethtool_rule(nic_dev, location); - if (!eth_rule) - return -ENOENT; - - err = spnic_remove_one_rule(nic_dev, eth_rule); - - return err; -} - -int spnic_ethtool_get_flow(struct spnic_nic_dev *nic_dev, - struct ethtool_rxnfc *info, u32 location) -{ - struct spnic_ethtool_rx_flow_rule *eth_rule = NULL; - - if (location >= MAX_NUM_OF_ETHTOOL_NTUPLE_RULES) - return -EINVAL; - - list_for_each_entry(eth_rule, &nic_dev->rx_flow_rule.rules, list) { - if (eth_rule->flow_spec.location == location) { - info->fs = eth_rule->flow_spec; - return 0; - } - } - - return -ENOENT; -} - -int spnic_ethtool_get_all_flows(struct spnic_nic_dev *nic_dev, - struct ethtool_rxnfc *info, u32 *rule_locs) -{ - int idx = 0; - struct spnic_ethtool_rx_flow_rule *eth_rule = NULL; - - info->data = MAX_NUM_OF_ETHTOOL_NTUPLE_RULES; - list_for_each_entry(eth_rule, &nic_dev->rx_flow_rule.rules, list) - rule_locs[idx++] = eth_rule->flow_spec.location; - - return info->rule_cnt == idx ? 0 : -ENOENT; -} diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_pci_id_tbl.h b/drivers/net/ethernet/ramaxel/spnic/spnic_pci_id_tbl.h deleted file mode 100644 index 9d32608e6bb7..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_pci_id_tbl.h +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPNIC_PCI_ID_TBL_H -#define SPNIC_PCI_ID_TBL_H - -#define PCI_VENDOR_ID_RAMAXEL 0x1E81 -#define SPNIC_DEV_ID_PF_STD 0x9020 -#define SPNIC_DEV_ID_VF 0x9001 -#define SPNIC_DEV_ID_VF_HV 0x9002 - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_rss.c b/drivers/net/ethernet/ramaxel/spnic/spnic_rss.c deleted file mode 100644 index 956d868df5b5..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_rss.c +++ /dev/null @@ -1,741 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [NIC]" fmt - -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/interrupt.h> -#include <linux/etherdevice.h> -#include <linux/netdevice.h> -#include <linux/device.h> -#include <linux/ethtool.h> -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/dcbnl.h> - -#include "sphw_crm.h" -#include "spnic_nic_cfg.h" -#include "spnic_nic_dev.h" -#include "sphw_hw.h" -#include "spnic_rss.h" - -static u16 num_qps; -module_param(num_qps, ushort, 0444); -MODULE_PARM_DESC(num_qps, "Number of Queue Pairs (default=0)"); - -#define MOD_PARA_VALIDATE_NUM_QPS(nic_dev, num_qps, out_qps) do { \ - if ((num_qps) > (nic_dev)->max_qps) \ - nic_warn(&(nic_dev)->pdev->dev, \ - "Module Parameter %s value %u is out of range, " \ - "Maximum value for the device: %u, using %u\n", \ - #num_qps, num_qps, (nic_dev)->max_qps, \ - (nic_dev)->max_qps); \ - if (!(num_qps) || (num_qps) > (nic_dev)->max_qps) \ - (out_qps) = (nic_dev)->max_qps; \ - else \ - (out_qps) = (num_qps); \ -} while (0) - -static void spnic_fillout_indir_tbl(struct spnic_nic_dev *nic_dev, u8 num_tcs, u32 *indir) -{ - u16 num_rss, tc_group_size; - int i; - - if (num_tcs) - tc_group_size = SPNIC_RSS_INDIR_SIZE / num_tcs; - else - tc_group_size = SPNIC_RSS_INDIR_SIZE; - - num_rss = nic_dev->q_params.num_rss; - for (i = 0; i < SPNIC_RSS_INDIR_SIZE; i++) - indir[i] = (i / tc_group_size) * num_rss + i % num_rss; -} - -int spnic_rss_init(struct spnic_nic_dev *nic_dev) -{ - struct net_device *netdev = nic_dev->netdev; - u8 cos, num_tc = 0; - u8 prio_tc[SPNIC_DCB_UP_MAX] = {0}; - u8 max_cos = nic_dev->hw_dcb_cfg.max_cos; - - if (test_bit(SPNIC_DCB_ENABLE, &nic_dev->flags)) { - num_tc = max_cos; - for (cos = 0; cos < SPNIC_DCB_COS_MAX; cos++) { - if (cos < SPNIC_DCB_COS_MAX - max_cos) - prio_tc[cos] = max_cos - 1; - else - prio_tc[cos] = (SPNIC_DCB_COS_MAX - 1) - cos; - } - } else { - num_tc = 0; - } - - return spnic_set_hw_rss_parameters(netdev, 1, num_tc, prio_tc); -} - -void spnic_rss_deinit(struct spnic_nic_dev *nic_dev) -{ - u8 prio_tc[SPNIC_DCB_UP_MAX] = {0}; - - spnic_rss_cfg(nic_dev->hwdev, 0, 0, prio_tc, 1); -} - -void spnic_init_rss_parameters(struct net_device *netdev) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - - nic_dev->rss_hash_engine = SPNIC_RSS_HASH_ENGINE_TYPE_XOR; - nic_dev->rss_type.tcp_ipv6_ext = 1; - nic_dev->rss_type.ipv6_ext = 1; - nic_dev->rss_type.tcp_ipv6 = 1; - nic_dev->rss_type.ipv6 = 1; - nic_dev->rss_type.tcp_ipv4 = 1; - nic_dev->rss_type.ipv4 = 1; - nic_dev->rss_type.udp_ipv6 = 1; - nic_dev->rss_type.udp_ipv4 = 1; -} - -void spnic_clear_rss_config(struct spnic_nic_dev *nic_dev) -{ - kfree(nic_dev->rss_hkey); - nic_dev->rss_hkey = NULL; - - kfree(nic_dev->rss_indir); - nic_dev->rss_indir = NULL; -} - -void spnic_set_default_rss_indir(struct net_device *netdev) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - - set_bit(SPNIC_RSS_DEFAULT_INDIR, &nic_dev->flags); -} - -static void spnic_maybe_reconfig_rss_indir(struct net_device *netdev) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - int i; - - /* if dcb is enabled, user can not config rss indir table */ - if (test_bit(SPNIC_DCB_ENABLE, &nic_dev->flags)) { - nicif_info(nic_dev, drv, netdev, "DCB is enabled, set default rss indir\n"); - goto discard_user_rss_indir; - } - - for (i = 0; i < SPNIC_RSS_INDIR_SIZE; i++) { - if (nic_dev->rss_indir[i] >= nic_dev->q_params.num_qps) - goto discard_user_rss_indir; - } - - return; - -discard_user_rss_indir: - spnic_set_default_rss_indir(netdev); -} - -static void decide_num_qps(struct spnic_nic_dev *nic_dev) -{ - u16 tmp_num_qps = nic_dev->q_params.num_qps; - u16 num_cpus = 0; - int i, node; - - MOD_PARA_VALIDATE_NUM_QPS(nic_dev, num_qps, tmp_num_qps); - - /* To reduce memory footprint in ovs mode. - * VF can't get board info correctly with early pf driver. - */ - /* if ((spnic_get_func_mode(nic_dev->hwdev) == FUNC_MOD_NORMAL_HOST) && - * service_mode == SPNIC_WORK_MODE_OVS && - * sphw_func_type(nic_dev->hwdev) != TYPE_VF) - * MOD_PARA_VALIDATE_NUM_QPS(nic_dev, ovs_num_qps, - * tmp_num_qps); - */ - - for (i = 0; i < (int)num_online_cpus(); i++) { - node = (int)cpu_to_node(i); - if (node == dev_to_node(&nic_dev->pdev->dev)) - num_cpus++; - } - - if (!num_cpus) - num_cpus = (u16)num_online_cpus(); - - nic_dev->q_params.num_qps = min_t(u16, tmp_num_qps, num_cpus); -} - -static void copy_value_to_rss_hkey(struct spnic_nic_dev *nic_dev, const u8 *hkey) -{ - u32 i; - u32 *rss_hkey = (u32 *)nic_dev->rss_hkey; - - memcpy(nic_dev->rss_hkey, hkey, SPNIC_RSS_KEY_SIZE); - - /* make a copy of the key, and convert it to Big Endian */ - for (i = 0; i < SPNIC_RSS_KEY_SIZE / sizeof(u32); i++) - nic_dev->rss_hkey_be[i] = cpu_to_be32(rss_hkey[i]); -} - -int alloc_rss_resource(struct spnic_nic_dev *nic_dev) -{ - u8 default_rss_key[SPNIC_RSS_KEY_SIZE] = { - 0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2, - 0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0, - 0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4, - 0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c, - 0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa}; - - /* We request double spaces for the hash key, - * the second one holds the key of Big Edian - * format. - */ - nic_dev->rss_hkey = - kzalloc(SPNIC_RSS_KEY_SIZE * SPNIC_RSS_KEY_RSV_NUM, GFP_KERNEL); - if (!nic_dev->rss_hkey) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to alloc memory for rss_hkey\n"); - return -ENOMEM; - } - - /* The second space is for big edian hash key */ - nic_dev->rss_hkey_be = (u32 *)(nic_dev->rss_hkey + SPNIC_RSS_KEY_SIZE); - copy_value_to_rss_hkey(nic_dev, (u8 *)default_rss_key); - - nic_dev->rss_indir = kzalloc(sizeof(u32) * SPNIC_RSS_INDIR_SIZE, GFP_KERNEL); - if (!nic_dev->rss_indir) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to alloc memory for rss_indir\n"); - kfree(nic_dev->rss_hkey); - nic_dev->rss_hkey = NULL; - return -ENOMEM; - } - - set_bit(SPNIC_RSS_DEFAULT_INDIR, &nic_dev->flags); - - return 0; -} - -void spnic_try_to_enable_rss(struct spnic_nic_dev *nic_dev) -{ - u8 prio_tc[SPNIC_DCB_UP_MAX] = {0}; - int err = 0; - - if (!nic_dev) - return; - - nic_dev->max_qps = sphw_func_max_nic_qnum(nic_dev->hwdev); - if (nic_dev->max_qps <= 1 || !SPNIC_SUPPORT_RSS(nic_dev->hwdev)) - goto set_q_params; - - err = alloc_rss_resource(nic_dev); - if (err) { - nic_dev->max_qps = 1; - goto set_q_params; - } - - set_bit(SPNIC_RSS_ENABLE, &nic_dev->flags); - nic_dev->max_qps = sphw_func_max_nic_qnum(nic_dev->hwdev); - - decide_num_qps(nic_dev); - - nic_dev->q_params.rss_limit = nic_dev->q_params.num_qps; - nic_dev->q_params.num_rss = nic_dev->q_params.num_qps; - - spnic_init_rss_parameters(nic_dev->netdev); - err = spnic_set_hw_rss_parameters(nic_dev->netdev, 0, 0, prio_tc); - if (err) { - nic_err(&nic_dev->pdev->dev, "Failed to set hardware rss parameters\n"); - - spnic_clear_rss_config(nic_dev); - nic_dev->max_qps = 1; - goto set_q_params; - } - return; - -set_q_params: - clear_bit(SPNIC_RSS_ENABLE, &nic_dev->flags); - nic_dev->q_params.rss_limit = nic_dev->max_qps; - nic_dev->q_params.num_qps = nic_dev->max_qps; - nic_dev->q_params.num_rss = nic_dev->max_qps; -} - -static int spnic_config_rss_hw_resource(struct spnic_nic_dev *nic_dev, u32 *indir_tbl) -{ - int err; - - err = spnic_rss_set_indir_tbl(nic_dev->hwdev, indir_tbl); - if (err) - return err; - - err = spnic_set_rss_type(nic_dev->hwdev, nic_dev->rss_type); - if (err) - return err; - - return spnic_rss_set_hash_engine(nic_dev->hwdev, nic_dev->rss_hash_engine); -} - -int spnic_set_hw_rss_parameters(struct net_device *netdev, u8 rss_en, u8 num_tc, u8 *prio_tc) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - int err; - - /* RSS key */ - err = spnic_rss_set_hash_key(nic_dev->hwdev, nic_dev->rss_hkey); - if (err) - return err; - - spnic_maybe_reconfig_rss_indir(netdev); - - if (test_bit(SPNIC_RSS_DEFAULT_INDIR, &nic_dev->flags)) - spnic_fillout_indir_tbl(nic_dev, num_tc, nic_dev->rss_indir); - - err = spnic_config_rss_hw_resource(nic_dev, nic_dev->rss_indir); - if (err) - return err; - - err = spnic_rss_cfg(nic_dev->hwdev, rss_en, num_tc, prio_tc, nic_dev->q_params.num_qps); - if (err) - return err; - - return 0; -} - -/* for ethtool */ -static int set_l4_rss_hash_ops(struct ethtool_rxnfc *cmd, struct nic_rss_type *rss_type) -{ - u8 rss_l4_en = 0; - - switch (cmd->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { - case 0: - rss_l4_en = 0; - break; - case (RXH_L4_B_0_1 | RXH_L4_B_2_3): - rss_l4_en = 1; - break; - default: - return -EINVAL; - } - - switch (cmd->flow_type) { - case TCP_V4_FLOW: - rss_type->tcp_ipv4 = rss_l4_en; - break; - case TCP_V6_FLOW: - rss_type->tcp_ipv6 = rss_l4_en; - break; - case UDP_V4_FLOW: - rss_type->udp_ipv4 = rss_l4_en; - break; - case UDP_V6_FLOW: - rss_type->udp_ipv6 = rss_l4_en; - break; - default: - return -EINVAL; - } - - return 0; -} - -static int update_rss_hash_opts(struct spnic_nic_dev *nic_dev, struct ethtool_rxnfc *cmd, - struct nic_rss_type *rss_type) -{ - int err; - - switch (cmd->flow_type) { - case TCP_V4_FLOW: - case TCP_V6_FLOW: - case UDP_V4_FLOW: - case UDP_V6_FLOW: - err = set_l4_rss_hash_ops(cmd, rss_type); - if (err) - return err; - - break; - case IPV4_FLOW: - rss_type->ipv4 = 1; - break; - case IPV6_FLOW: - rss_type->ipv6 = 1; - break; - default: - nicif_err(nic_dev, drv, nic_dev->netdev, "Unsupported flow type\n"); - return -EINVAL; - } - - return 0; -} - -static int spnic_set_rss_hash_opts(struct spnic_nic_dev *nic_dev, struct ethtool_rxnfc *cmd) -{ - struct nic_rss_type *rss_type = &nic_dev->rss_type; - int err; - - if (!test_bit(SPNIC_RSS_ENABLE, &nic_dev->flags)) { - cmd->data = 0; - nicif_err(nic_dev, drv, nic_dev->netdev, - "RSS is disable, not support to set flow-hash\n"); - return -EOPNOTSUPP; - } - - /* RSS does not support anything other than hashing - * to queues on src and dst IPs and ports - */ - if (cmd->data & ~(RXH_IP_SRC | RXH_IP_DST | RXH_L4_B_0_1 | - RXH_L4_B_2_3)) - return -EINVAL; - - /* We need at least the IP SRC and DEST fields for hashing */ - if (!(cmd->data & RXH_IP_SRC) || !(cmd->data & RXH_IP_DST)) - return -EINVAL; - - err = spnic_get_rss_type(nic_dev->hwdev, rss_type); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to get rss type\n"); - return -EFAULT; - } - - err = update_rss_hash_opts(nic_dev, cmd, rss_type); - if (err) - return err; - - err = spnic_set_rss_type(nic_dev->hwdev, *rss_type); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Failed to set rss type\n"); - return -EFAULT; - } - - nicif_info(nic_dev, drv, nic_dev->netdev, "Set rss hash options success\n"); - - return 0; -} - -static void convert_rss_type(u8 rss_opt, struct ethtool_rxnfc *cmd) -{ - if (rss_opt) - cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; -} - -static int spnic_convert_rss_type(struct spnic_nic_dev *nic_dev, struct nic_rss_type *rss_type, - struct ethtool_rxnfc *cmd) -{ - cmd->data = RXH_IP_SRC | RXH_IP_DST; - switch (cmd->flow_type) { - case TCP_V4_FLOW: - convert_rss_type(rss_type->tcp_ipv4, cmd); - break; - case TCP_V6_FLOW: - convert_rss_type(rss_type->tcp_ipv6, cmd); - break; - case UDP_V4_FLOW: - convert_rss_type(rss_type->udp_ipv4, cmd); - break; - case UDP_V6_FLOW: - convert_rss_type(rss_type->udp_ipv6, cmd); - break; - case IPV4_FLOW: - case IPV6_FLOW: - break; - default: - nicif_err(nic_dev, drv, nic_dev->netdev, "Unsupported flow type\n"); - cmd->data = 0; - return -EINVAL; - } - - return 0; -} - -static int spnic_get_rss_hash_opts(struct spnic_nic_dev *nic_dev, struct ethtool_rxnfc *cmd) -{ - struct nic_rss_type rss_type = {0}; - int err; - - cmd->data = 0; - - if (!test_bit(SPNIC_RSS_ENABLE, &nic_dev->flags)) - return 0; - - err = spnic_get_rss_type(nic_dev->hwdev, &rss_type); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to get rss type\n"); - return err; - } - - return spnic_convert_rss_type(nic_dev, &rss_type, cmd); -} - -int spnic_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd, u32 *rule_locs) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - int err = 0; - - switch (cmd->cmd) { - case ETHTOOL_GRXRINGS: - cmd->data = nic_dev->q_params.num_qps; - break; - case ETHTOOL_GRXCLSRLCNT: - cmd->rule_cnt = nic_dev->rx_flow_rule.tot_num_rules; - break; - case ETHTOOL_GRXCLSRULE: - err = spnic_ethtool_get_flow(nic_dev, cmd, cmd->fs.location); - break; - case ETHTOOL_GRXCLSRLALL: - err = spnic_ethtool_get_all_flows(nic_dev, cmd, rule_locs); - break; - case ETHTOOL_GRXFH: - err = spnic_get_rss_hash_opts(nic_dev, cmd); - break; - default: - err = -EOPNOTSUPP; - break; - } - - return err; -} - -int spnic_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - int err = 0; - - switch (cmd->cmd) { - case ETHTOOL_SRXFH: - err = spnic_set_rss_hash_opts(nic_dev, cmd); - break; - case ETHTOOL_SRXCLSRLINS: - err = spnic_ethtool_flow_replace(nic_dev, &cmd->fs); - break; - case ETHTOOL_SRXCLSRLDEL: - err = spnic_ethtool_flow_remove(nic_dev, cmd->fs.location); - break; - default: - err = -EOPNOTSUPP; - break; - } - - return err; -} - -static u16 spnic_max_channels(struct spnic_nic_dev *nic_dev) -{ - u8 tcs = (u8)netdev_get_num_tc(nic_dev->netdev); - - return tcs ? nic_dev->max_qps / tcs : nic_dev->max_qps; -} - -static u16 spnic_curr_channels(struct spnic_nic_dev *nic_dev) -{ - if (netif_running(nic_dev->netdev)) - return nic_dev->q_params.num_rss ? nic_dev->q_params.num_rss : 1; - else - return min_t(u16, spnic_max_channels(nic_dev), - nic_dev->q_params.rss_limit); -} - -void spnic_get_channels(struct net_device *netdev, struct ethtool_channels *channels) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - - channels->max_rx = 0; - channels->max_tx = 0; - channels->max_other = 0; - /* report maximum channels */ - channels->max_combined = spnic_max_channels(nic_dev); - channels->rx_count = 0; - channels->tx_count = 0; - channels->other_count = 0; - /* report flow director queues as maximum channels */ - channels->combined_count = spnic_curr_channels(nic_dev); -} - -void spnic_update_num_qps(struct net_device *netdev) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - u16 num_qps; - u8 tcs; - - /* change num_qps to change counter in ethtool -S */ - tcs = (u8)netdev_get_num_tc(nic_dev->netdev); - nic_dev->q_params.num_tc = tcs; - num_qps = (u16)(nic_dev->q_params.rss_limit * (tcs ? tcs : 1)); - nic_dev->q_params.num_qps = min_t(u16, nic_dev->max_qps, num_qps); -} - -static int spnic_validate_channel_parameter(struct net_device *netdev, - struct ethtool_channels *channels) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - u16 max_channel = spnic_max_channels(nic_dev); - unsigned int count = channels->combined_count; - - if (!count) { - nicif_err(nic_dev, drv, netdev, "Unsupported combined_count=0\n"); - return -EINVAL; - } - - if (channels->tx_count || channels->rx_count || channels->other_count) { - nicif_err(nic_dev, drv, netdev, "Setting rx/tx/other count not supported\n"); - return -EINVAL; - } - - if (count > max_channel) { - nicif_err(nic_dev, drv, netdev, "Combined count %u exceed limit %u\n", - count, max_channel); - return -EINVAL; - } - - return 0; -} - -static void change_num_channel_reopen_handler(struct spnic_nic_dev *nic_dev, const void *priv_data) -{ - spnic_set_default_rss_indir(nic_dev->netdev); -} - -int spnic_set_channels(struct net_device *netdev, struct ethtool_channels *channels) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - struct spnic_dyna_txrxq_params q_params = {0}; - unsigned int count = channels->combined_count; - int err; - - if (spnic_validate_channel_parameter(netdev, channels)) - return -EINVAL; - - if (!test_bit(SPNIC_RSS_ENABLE, &nic_dev->flags)) { - nicif_err(nic_dev, drv, netdev, - "This function don't support RSS, only support 1 queue pair\n"); - return -EOPNOTSUPP; - } - - nicif_info(nic_dev, drv, netdev, "Set max combined queue number from %u to %u\n", - nic_dev->q_params.rss_limit, count); - - if (netif_running(netdev)) { - q_params = nic_dev->q_params; - q_params.rss_limit = (u16)count; - q_params.txqs_res = NULL; - q_params.rxqs_res = NULL; - q_params.irq_cfg = NULL; - - nicif_info(nic_dev, drv, netdev, "Restarting channel\n"); - err = spnic_change_channel_settings(nic_dev, &q_params, - change_num_channel_reopen_handler, NULL); - if (err) { - nicif_err(nic_dev, drv, netdev, "Failed to change channel settings\n"); - return -EFAULT; - } - } else { - /* Discard user configured rss */ - spnic_set_default_rss_indir(netdev); - nic_dev->q_params.rss_limit = (u16)count; - spnic_update_num_qps(netdev); - } - - return 0; -} - -static int set_rss_rxfh(struct net_device *netdev, const u32 *indir, const u8 *key) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - int err; - - if (indir) { - err = spnic_rss_set_indir_tbl(nic_dev->hwdev, indir); - if (err) { - nicif_err(nic_dev, drv, netdev, "Failed to set rss indir table\n"); - return -EFAULT; - } - clear_bit(SPNIC_RSS_DEFAULT_INDIR, &nic_dev->flags); - - memcpy(nic_dev->rss_indir, indir, - sizeof(u32) * SPNIC_RSS_INDIR_SIZE); - nicif_info(nic_dev, drv, netdev, "Change rss indir success\n"); - } - - if (key) { - err = spnic_rss_set_hash_key(nic_dev->hwdev, key); - if (err) { - nicif_err(nic_dev, drv, netdev, "Failed to set rss key\n"); - return -EFAULT; - } - - copy_value_to_rss_hkey(nic_dev, key); - nicif_info(nic_dev, drv, netdev, "Change rss key success\n"); - } - - return 0; -} - -u32 spnic_get_rxfh_indir_size(struct net_device *netdev) -{ - return SPNIC_RSS_INDIR_SIZE; -} - -u32 spnic_get_rxfh_key_size(struct net_device *netdev) -{ - return SPNIC_RSS_KEY_SIZE; -} - -int spnic_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key, u8 *hfunc) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - int err = 0; - - if (!test_bit(SPNIC_RSS_ENABLE, &nic_dev->flags)) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Rss is disable\n"); - return -EOPNOTSUPP; - } - - if (hfunc) - *hfunc = nic_dev->rss_hash_engine ? - ETH_RSS_HASH_TOP : ETH_RSS_HASH_XOR; - - if (indir) { - err = spnic_rss_get_indir_tbl(nic_dev->hwdev, indir); - if (err) - return -EFAULT; - } - - if (key) - memcpy(key, nic_dev->rss_hkey, SPNIC_RSS_KEY_SIZE); - - return err; -} - -int spnic_set_rxfh(struct net_device *netdev, const u32 *indir, const u8 *key, const u8 hfunc) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - int err = 0; - - if (!test_bit(SPNIC_RSS_ENABLE, &nic_dev->flags)) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Not support to set rss parameters when rss is disable\n"); - return -EOPNOTSUPP; - } - - if (test_bit(SPNIC_DCB_ENABLE, &nic_dev->flags) && indir) { - nicif_err(nic_dev, drv, netdev, "Not support to set indir when DCB is enabled\n"); - return -EOPNOTSUPP; - } - - if (hfunc != ETH_RSS_HASH_NO_CHANGE) { - if (hfunc != ETH_RSS_HASH_TOP && hfunc != ETH_RSS_HASH_XOR) { - nicif_err(nic_dev, drv, netdev, "Not support to set hfunc type except TOP and XOR\n"); - return -EOPNOTSUPP; - } - - nic_dev->rss_hash_engine = (hfunc == ETH_RSS_HASH_XOR) ? - SPNIC_RSS_HASH_ENGINE_TYPE_XOR : - SPNIC_RSS_HASH_ENGINE_TYPE_TOEP; - err = spnic_rss_set_hash_engine(nic_dev->hwdev, nic_dev->rss_hash_engine); - if (err) - return -EFAULT; - - nicif_info(nic_dev, drv, netdev, "Change hfunc to RSS_HASH_%s success\n", - (hfunc == ETH_RSS_HASH_XOR) ? "XOR" : "TOP"); - } - err = set_rss_rxfh(netdev, indir, key); - - return err; -} diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_rss.h b/drivers/net/ethernet/ramaxel/spnic/spnic_rss.h deleted file mode 100644 index e64a4dcf39dd..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_rss.h +++ /dev/null @@ -1,50 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPNIC_RSS_H -#define SPNIC_RSS_H - -#include "spnic_nic_dev.h" - -int spnic_rss_init(struct spnic_nic_dev *nic_dev); - -void spnic_rss_deinit(struct spnic_nic_dev *nic_dev); - -int spnic_set_hw_rss_parameters(struct net_device *netdev, u8 rss_en, u8 num_tc, u8 *prio_tc); - -void spnic_init_rss_parameters(struct net_device *netdev); - -void spnic_set_default_rss_indir(struct net_device *netdev); - -void spnic_try_to_enable_rss(struct spnic_nic_dev *nic_dev); - -void spnic_clear_rss_config(struct spnic_nic_dev *nic_dev); - -void spnic_flush_rx_flow_rule(struct spnic_nic_dev *nic_dev); -int spnic_ethtool_get_flow(struct spnic_nic_dev *nic_dev, struct ethtool_rxnfc *info, u32 location); - -int spnic_ethtool_get_all_flows(struct spnic_nic_dev *nic_dev, - struct ethtool_rxnfc *info, u32 *rule_locs); - -int spnic_ethtool_flow_remove(struct spnic_nic_dev *nic_dev, u32 location); - -int spnic_ethtool_flow_replace(struct spnic_nic_dev *nic_dev, struct ethtool_rx_flow_spec *fs); - -/* for ethtool */ -int spnic_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd, u32 *rule_locs); - -int spnic_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd); - -void spnic_get_channels(struct net_device *netdev, struct ethtool_channels *channels); - -int spnic_set_channels(struct net_device *netdev, struct ethtool_channels *channels); - -u32 spnic_get_rxfh_indir_size(struct net_device *netdev); - -u32 spnic_get_rxfh_key_size(struct net_device *netdev); - -int spnic_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key, u8 *hfunc); - -int spnic_set_rxfh(struct net_device *netdev, const u32 *indir, const u8 *key, const u8 hfunc); - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_rss_cfg.c b/drivers/net/ethernet/ramaxel/spnic/spnic_rss_cfg.c deleted file mode 100644 index 12da3aa59400..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_rss_cfg.c +++ /dev/null @@ -1,333 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [NIC]" fmt - -#include <linux/kernel.h> -#include <linux/etherdevice.h> -#include <linux/netdevice.h> -#include <linux/device.h> -#include <linux/module.h> -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/dcbnl.h> - -#include "sphw_crm.h" -#include "spnic_nic_cfg.h" -#include "sphw_hw.h" -#include "spnic_nic.h" -#include "sphw_common.h" - -static int spnic_rss_cfg_hash_key(struct spnic_nic_cfg *nic_cfg, u8 opcode, u8 *key) -{ - struct spnic_cmd_rss_hash_key hash_key; - u16 out_size = sizeof(hash_key); - int err; - - memset(&hash_key, 0, sizeof(struct spnic_cmd_rss_hash_key)); - hash_key.func_id = sphw_global_func_id(nic_cfg->hwdev); - hash_key.opcode = opcode; - - if (opcode == SPNIC_CMD_OP_SET) - memcpy(hash_key.key, key, SPNIC_RSS_KEY_SIZE); - - err = l2nic_msg_to_mgmt_sync(nic_cfg->hwdev, - SPNIC_NIC_CMD_CFG_RSS_HASH_KEY, - &hash_key, sizeof(hash_key), - &hash_key, &out_size); - if (err || !out_size || hash_key.msg_head.status) { - nic_err(nic_cfg->dev_hdl, "Failed to %s hash key, err: %d, status: 0x%x, out size: 0x%x\n", - opcode == SPNIC_CMD_OP_SET ? "set" : "get", - err, hash_key.msg_head.status, out_size); - return -EINVAL; - } - - if (opcode == SPNIC_CMD_OP_GET) - memcpy(key, hash_key.key, SPNIC_RSS_KEY_SIZE); - - return 0; -} - -int spnic_rss_set_hash_key(void *hwdev, const u8 *key) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - u8 hash_key[SPNIC_RSS_KEY_SIZE]; - - if (!hwdev || !key) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - memcpy(hash_key, key, SPNIC_RSS_KEY_SIZE); - return spnic_rss_cfg_hash_key(nic_cfg, SPNIC_CMD_OP_SET, hash_key); -} - -int spnic_rss_get_hash_key(void *hwdev, u8 *key) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - - if (!hwdev || !key) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - return spnic_rss_cfg_hash_key(nic_cfg, SPNIC_CMD_OP_GET, key); -} - -int spnic_rss_get_indir_tbl(void *hwdev, u32 *indir_table) -{ - struct sphw_cmd_buf *cmd_buf = NULL; - struct spnic_nic_cfg *nic_cfg = NULL; - u16 *indir_tbl = NULL; - int err, i; - - if (!hwdev || !indir_table) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - cmd_buf = sphw_alloc_cmd_buf(hwdev); - if (!cmd_buf) { - nic_err(nic_cfg->dev_hdl, "Failed to allocate cmd_buf.\n"); - return -ENOMEM; - } - - cmd_buf->size = sizeof(struct nic_rss_indirect_tbl); - err = sphw_cmdq_detail_resp(hwdev, SPHW_MOD_L2NIC, SPNIC_UCODE_CMD_GET_RSS_INDIR_TABLE, - cmd_buf, cmd_buf, NULL, 0, SPHW_CHANNEL_NIC); - if (err) { - nic_err(nic_cfg->dev_hdl, "Failed to get rss indir table\n"); - goto get_indir_tbl_failed; - } - - indir_tbl = (u16 *)cmd_buf->buf; - for (i = 0; i < SPNIC_RSS_INDIR_SIZE; i++) - indir_table[i] = *(indir_tbl + i); - -get_indir_tbl_failed: - sphw_free_cmd_buf(hwdev, cmd_buf); - - return err; -} - -int spnic_rss_set_indir_tbl(void *hwdev, const u32 *indir_table) -{ - struct nic_rss_indirect_tbl *indir_tbl = NULL; - struct sphw_cmd_buf *cmd_buf = NULL; - struct spnic_nic_cfg *nic_cfg = NULL; - u32 *temp = NULL; - u32 i, size; - u64 out_param = 0; - int err; - - if (!hwdev || !indir_table) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - cmd_buf = sphw_alloc_cmd_buf(hwdev); - if (!cmd_buf) { - nic_err(nic_cfg->dev_hdl, "Failed to allocate cmd buf\n"); - return -ENOMEM; - } - - cmd_buf->size = sizeof(struct nic_rss_indirect_tbl); - indir_tbl = (struct nic_rss_indirect_tbl *)cmd_buf->buf; - memset(indir_tbl, 0, sizeof(*indir_tbl)); - - for (i = 0; i < SPNIC_RSS_INDIR_SIZE; i++) - indir_tbl->entry[i] = (u16)(*(indir_table + i)); - - size = sizeof(indir_tbl->entry) / sizeof(u32); - temp = (u32 *)indir_tbl->entry; - for (i = 0; i < size; i++) - temp[i] = cpu_to_be32(temp[i]); - - err = sphw_cmdq_direct_resp(hwdev, SPHW_MOD_L2NIC, SPNIC_UCODE_CMD_SET_RSS_INDIR_TABLE, - cmd_buf, &out_param, 0, SPHW_CHANNEL_NIC); - if (err || out_param != 0) { - nic_err(nic_cfg->dev_hdl, "Failed to set rss indir table\n"); - err = -EFAULT; - } - - sphw_free_cmd_buf(hwdev, cmd_buf); - return err; -} - -#define SPNIC_RSS_TYPE_VALID_SHIFT 23 -#define SPNIC_RSS_TYPE_TCP_IPV6_EXT_SHIFT 24 -#define SPNIC_RSS_TYPE_IPV6_EXT_SHIFT 25 -#define SPNIC_RSS_TYPE_TCP_IPV6_SHIFT 26 -#define SPNIC_RSS_TYPE_IPV6_SHIFT 27 -#define SPNIC_RSS_TYPE_TCP_IPV4_SHIFT 28 -#define SPNIC_RSS_TYPE_IPV4_SHIFT 29 -#define SPNIC_RSS_TYPE_UDP_IPV6_SHIFT 30 -#define SPNIC_RSS_TYPE_UDP_IPV4_SHIFT 31 -#define SPNIC_RSS_TYPE_SET(val, member) (((u32)(val) & 0x1) << SPNIC_RSS_TYPE_##member##_SHIFT) - -#define SPNIC_RSS_TYPE_GET(val, member) (((u32)(val) >> SPNIC_RSS_TYPE_##member##_SHIFT) & 0x1) - -int spnic_set_rss_type(void *hwdev, struct nic_rss_type rss_type) -{ - struct nic_rss_context_tbl *ctx_tbl = NULL; - struct sphw_cmd_buf *cmd_buf = NULL; - struct spnic_nic_cfg *nic_cfg = NULL; - u32 ctx = 0; - u64 out_param = 0; - int err; - - if (!hwdev) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - cmd_buf = sphw_alloc_cmd_buf(hwdev); - if (!cmd_buf) { - nic_err(nic_cfg->dev_hdl, "Failed to allocate cmd buf\n"); - return -ENOMEM; - } - - ctx |= SPNIC_RSS_TYPE_SET(1, VALID) | - SPNIC_RSS_TYPE_SET(rss_type.ipv4, IPV4) | - SPNIC_RSS_TYPE_SET(rss_type.ipv6, IPV6) | - SPNIC_RSS_TYPE_SET(rss_type.ipv6_ext, IPV6_EXT) | - SPNIC_RSS_TYPE_SET(rss_type.tcp_ipv4, TCP_IPV4) | - SPNIC_RSS_TYPE_SET(rss_type.tcp_ipv6, TCP_IPV6) | - SPNIC_RSS_TYPE_SET(rss_type.tcp_ipv6_ext, TCP_IPV6_EXT) | - SPNIC_RSS_TYPE_SET(rss_type.udp_ipv4, UDP_IPV4) | - SPNIC_RSS_TYPE_SET(rss_type.udp_ipv6, UDP_IPV6); - - cmd_buf->size = sizeof(struct nic_rss_context_tbl); - ctx_tbl = (struct nic_rss_context_tbl *)cmd_buf->buf; - memset(ctx_tbl, 0, sizeof(*ctx_tbl)); - ctx_tbl->ctx = cpu_to_be32(ctx); - - /* cfg the rss context table by command queue */ - err = sphw_cmdq_direct_resp(hwdev, SPHW_MOD_L2NIC, SPNIC_UCODE_CMD_SET_RSS_CONTEXT_TABLE, - cmd_buf, &out_param, 0, SPHW_CHANNEL_NIC); - - sphw_free_cmd_buf(hwdev, cmd_buf); - - if (err || out_param != 0) { - nic_err(nic_cfg->dev_hdl, "Failed to set rss context table, err: %d\n", - err); - return -EFAULT; - } - - return 0; -} - -int spnic_get_rss_type(void *hwdev, struct nic_rss_type *rss_type) -{ - struct spnic_rss_context_table ctx_tbl; - u16 out_size = sizeof(ctx_tbl); - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - if (!hwdev || !rss_type) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - memset(&ctx_tbl, 0, sizeof(struct spnic_rss_context_table)); - ctx_tbl.func_id = sphw_global_func_id(hwdev); - - err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_NIC_CMD_GET_RSS_CTX_TBL, - &ctx_tbl, sizeof(ctx_tbl), - &ctx_tbl, &out_size); - if (err || !out_size || ctx_tbl.msg_head.status) { - nic_err(nic_cfg->dev_hdl, "Failed to get hash type, err: %d, status: 0x%x, out size: 0x%x\n", - err, ctx_tbl.msg_head.status, out_size); - return -EINVAL; - } - - rss_type->ipv4 = SPNIC_RSS_TYPE_GET(ctx_tbl.context, IPV4); - rss_type->ipv6 = SPNIC_RSS_TYPE_GET(ctx_tbl.context, IPV6); - rss_type->ipv6_ext = SPNIC_RSS_TYPE_GET(ctx_tbl.context, IPV6_EXT); - rss_type->tcp_ipv4 = SPNIC_RSS_TYPE_GET(ctx_tbl.context, TCP_IPV4); - rss_type->tcp_ipv6 = SPNIC_RSS_TYPE_GET(ctx_tbl.context, TCP_IPV6); - rss_type->tcp_ipv6_ext = SPNIC_RSS_TYPE_GET(ctx_tbl.context, TCP_IPV6_EXT); - rss_type->udp_ipv4 = SPNIC_RSS_TYPE_GET(ctx_tbl.context, UDP_IPV4); - rss_type->udp_ipv6 = SPNIC_RSS_TYPE_GET(ctx_tbl.context, UDP_IPV6); - - return 0; -} - -static int spnic_rss_cfg_hash_engine(struct spnic_nic_cfg *nic_cfg, u8 opcode, u8 *type) -{ - struct spnic_cmd_rss_engine_type hash_type; - u16 out_size = sizeof(hash_type); - int err; - - memset(&hash_type, 0, sizeof(struct spnic_cmd_rss_engine_type)); - - hash_type.func_id = sphw_global_func_id(nic_cfg->hwdev); - hash_type.opcode = opcode; - - if (opcode == SPNIC_CMD_OP_SET) - hash_type.hash_engine = *type; - - err = l2nic_msg_to_mgmt_sync(nic_cfg->hwdev, SPNIC_NIC_CMD_CFG_RSS_HASH_ENGINE, - &hash_type, sizeof(hash_type), - &hash_type, &out_size); - if (err || !out_size || hash_type.msg_head.status) { - nic_err(nic_cfg->dev_hdl, "Failed to %s hash engine, err: %d, status: 0x%x, out size: 0x%x\n", - opcode == SPNIC_CMD_OP_SET ? "set" : "get", - err, hash_type.msg_head.status, out_size); - return -EIO; - } - - if (opcode == SPNIC_CMD_OP_GET) - *type = hash_type.hash_engine; - - return 0; -} - -int spnic_rss_set_hash_engine(void *hwdev, u8 type) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - - if (!hwdev) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - return spnic_rss_cfg_hash_engine(nic_cfg, SPNIC_CMD_OP_SET, &type); -} - -int spnic_rss_get_hash_engine(void *hwdev, u8 *type) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - - if (!hwdev || !type) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - return spnic_rss_cfg_hash_engine(nic_cfg, SPNIC_CMD_OP_GET, type); -} - -int spnic_rss_cfg(void *hwdev, u8 rss_en, u8 tc_num, u8 *prio_tc, u16 num_qps) -{ - struct spnic_cmd_rss_config rss_cfg; - u16 out_size = sizeof(rss_cfg); - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - /* micro code required: number of TC should be power of 2 */ - if (!hwdev || !prio_tc || (tc_num & (tc_num - 1))) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - memset(&rss_cfg, 0, sizeof(struct spnic_cmd_rss_config)); - rss_cfg.func_id = sphw_global_func_id(hwdev); - rss_cfg.rss_en = rss_en; - rss_cfg.rq_priority_number = tc_num ? (u8)ilog2(tc_num) : 0; - rss_cfg.num_qps = num_qps; - - memcpy(rss_cfg.prio_tc, prio_tc, SPNIC_DCB_UP_MAX); - err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_NIC_CMD_RSS_CFG, - &rss_cfg, sizeof(rss_cfg), - &rss_cfg, &out_size); - if (err || !out_size || rss_cfg.msg_head.status) { - nic_err(nic_cfg->dev_hdl, "Failed to set rss cfg, err: %d, status: 0x%x, out size: 0x%x\n", - err, rss_cfg.msg_head.status, out_size); - return -EINVAL; - } - - return 0; -} diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_rx.c b/drivers/net/ethernet/ramaxel/spnic/spnic_rx.c deleted file mode 100644 index 3ae2f15c727b..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_rx.c +++ /dev/null @@ -1,1238 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [NIC]" fmt -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/kernel.h> -#include <linux/skbuff.h> -#include <linux/dma-mapping.h> -#include <linux/interrupt.h> -#include <linux/etherdevice.h> -#include <linux/netdevice.h> -#include <linux/device.h> -#include <linux/pci.h> -#include <linux/u64_stats_sync.h> -#include <linux/ip.h> -#include <linux/tcp.h> -#include <linux/sctp.h> -#include <linux/pkt_sched.h> -#include <linux/ipv6.h> -#include <linux/module.h> -#include <linux/compiler.h> - -#include "sphw_crm.h" -#include "sphw_common.h" -#include "spnic_nic_qp.h" -#include "spnic_nic_io.h" -#include "spnic_nic_dev.h" -#include "spnic_rx.h" -#include "spnic_rss.h" - -static u32 rq_pi_rd_en; -module_param(rq_pi_rd_en, uint, 0644); -MODULE_PARM_DESC(rq_pi_rd_en, "Enable rq read pi from host, defaut update pi by doorbell (default=0)"); - -/* performance: ci addr RTE_CACHE_SIZE(64B) alignment */ -#define SPNIC_RX_HDR_SIZE 256 -#define SPNIC_RX_BUFFER_WRITE 16 - -#define SPNIC_RX_TCP_PKT 0x3 -#define SPNIC_RX_UDP_PKT 0x4 -#define SPNIC_RX_SCTP_PKT 0x7 - -#define SPNIC_RX_IPV4_PKT 0 -#define SPNIC_RX_IPV6_PKT 1 -#define SPNIC_RX_INVALID_IP_TYPE 2 - -#define SPNIC_RX_PKT_FORMAT_NON_TUNNEL 0 -#define SPNIC_RX_PKT_FORMAT_VXLAN 1 - -#define RXQ_STATS_INC(rxq, field) \ -do { \ - u64_stats_update_begin(&(rxq)->rxq_stats.syncp); \ - (rxq)->rxq_stats.field++; \ - u64_stats_update_end(&(rxq)->rxq_stats.syncp); \ -} while (0) - -static bool rx_alloc_mapped_page(struct spnic_nic_dev *nic_dev, - struct spnic_rx_info *rx_info) -{ - struct pci_dev *pdev = nic_dev->pdev; - struct page *page = rx_info->page; - dma_addr_t dma = rx_info->buf_dma_addr; - - if (likely(dma)) - return true; - - /* alloc new page for storage */ - page = alloc_pages_node(NUMA_NO_NODE, GFP_ATOMIC | __GFP_COMP, nic_dev->page_order); - if (unlikely(!page)) - return false; - - /* map page for use */ - dma = dma_map_page(&pdev->dev, page, 0, nic_dev->dma_rx_buff_size, DMA_FROM_DEVICE); - - /* if mapping failed free memory back to system since - * there isn't much point in holding memory we can't use - */ - if (unlikely(dma_mapping_error(&pdev->dev, dma))) { - __free_pages(page, nic_dev->page_order); - return false; - } - - rx_info->page = page; - rx_info->buf_dma_addr = dma; - rx_info->page_offset = 0; - - return true; -} - -static u32 spnic_rx_fill_wqe(struct spnic_rxq *rxq) -{ - struct net_device *netdev = rxq->netdev; - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - struct spnic_rq_wqe *rq_wqe = NULL; - struct spnic_rx_info *rx_info = NULL; - u32 i; - - for (i = 0; i < rxq->q_depth; i++) { - rx_info = &rxq->rx_info[i]; - rq_wqe = spnic_rq_wqe_addr(rxq->rq, (u16)i); - - if (rxq->rq->wqe_type == SPNIC_EXTEND_RQ_WQE) { - /* unit of cqe length is 16B */ - sphw_set_sge(&rq_wqe->extend_wqe.cqe_sect.sge, rx_info->cqe_dma, - (sizeof(struct spnic_rq_cqe) >> SPNIC_CQE_SIZE_SHIFT)); - /* use fixed len */ - rq_wqe->extend_wqe.buf_desc.sge.len = - nic_dev->rx_buff_len; - } else { - rq_wqe->normal_wqe.cqe_hi_addr = upper_32_bits(rx_info->cqe_dma); - rq_wqe->normal_wqe.cqe_lo_addr = lower_32_bits(rx_info->cqe_dma); - } - - rx_info->rq_wqe = rq_wqe; - } - - return i; -} - -static struct sk_buff *stub_rx_alloc_skb(struct spnic_rxq *rxq, struct spnic_rx_info *rx_info) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(rxq->netdev); - struct sk_buff *skb = NULL; - u16 random_id; - dma_addr_t addr; - int err; - - get_random_bytes(&random_id, sizeof(u16)); - - rx_info->skb_len = SPNIC_RX_HDR_SIZE + (random_id & 0x3EFF); - skb = netdev_alloc_skb_ip_align(rxq->netdev, rx_info->skb_len); - if (!skb) { - nicif_err(nic_dev, drv, rxq->netdev, "Failed to allocate Rx SKB\n"); - return NULL; - } - - addr = dma_map_single(&nic_dev->pdev->dev, skb->data, rx_info->skb_len, - DMA_FROM_DEVICE); - - err = dma_mapping_error(&nic_dev->pdev->dev, addr); - if (err) { - nicif_err(nic_dev, drv, rxq->netdev, "Failed to map Rx DMA, err = %d\n", err); - goto err_rx_map; - } - - rx_info->buf_dma_addr = addr; - - return skb; - -err_rx_map: - dev_kfree_skb_any(skb); - return NULL; -} - -static u32 stub_spnic_rx_fill_buffers(struct spnic_rxq *rxq) -{ - struct net_device *netdev = rxq->netdev; - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - u32 i, free_wqebbs = rxq->delta - 1; - struct spnic_rq_wqe *rq_wqe = NULL; - struct spnic_rx_info *rx_info = NULL; - struct sk_buff *skb = NULL; - dma_addr_t dma_addr; - - for (i = 0; i < free_wqebbs; i++) { - rx_info = &rxq->rx_info[rxq->next_to_update]; - - skb = stub_rx_alloc_skb(rxq, rx_info); - if (!skb) { - nicif_err(nic_dev, drv, rxq->netdev, "Failed to alloc Rx skb\n"); - break; - } - - rq_wqe = rx_info->rq_wqe; - rx_info->saved_skb = skb; - dma_addr = rx_info->buf_dma_addr; - - if (rxq->rq->wqe_type == SPNIC_EXTEND_RQ_WQE) { - rq_wqe->extend_wqe.buf_desc.sge.hi_addr = upper_32_bits(dma_addr); - rq_wqe->extend_wqe.buf_desc.sge.lo_addr = lower_32_bits(dma_addr); - rq_wqe->extend_wqe.buf_desc.sge.len = rx_info->skb_len; - } else { - rq_wqe->normal_wqe.buf_hi_addr = upper_32_bits(dma_addr); - rq_wqe->normal_wqe.buf_lo_addr = lower_32_bits(dma_addr); - } - rxq->next_to_update = (rxq->next_to_update + 1) & rxq->q_mask; - } - - if (likely(i)) { - if (!rq_pi_rd_en) { - spnic_write_db(rxq->rq, rxq->q_id & (SPNIC_DCB_COS_MAX - 1), RQ_CFLAG_DP, - (u16)((u32)rxq->next_to_update << rxq->rq->wqe_type)); - } else { - /* Write all the wqes before pi update */ - wmb(); - - spnic_update_rq_hw_pi(rxq->rq, rxq->next_to_update); - } - rxq->delta -= i; - rxq->next_to_alloc = rxq->next_to_update; - } else { - nicif_err(nic_dev, drv, netdev, "Failed to allocate rx buffers, rxq id: %u\n", - rxq->q_id); - } - - return i; -} - -static u32 spnic_rx_fill_buffers(struct spnic_rxq *rxq) -{ - struct net_device *netdev = rxq->netdev; - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - struct spnic_rq_wqe *rq_wqe = NULL; - struct spnic_rx_info *rx_info = NULL; - dma_addr_t dma_addr; - u32 i, free_wqebbs = rxq->delta - 1; - - for (i = 0; i < free_wqebbs; i++) { - rx_info = &rxq->rx_info[rxq->next_to_update]; - - if (unlikely(!rx_alloc_mapped_page(nic_dev, rx_info))) { - RXQ_STATS_INC(rxq, alloc_rx_buf_err); - break; - } - - dma_addr = rx_info->buf_dma_addr + rx_info->page_offset; - - rq_wqe = rx_info->rq_wqe; - - if (rxq->rq->wqe_type == SPNIC_EXTEND_RQ_WQE) { - rq_wqe->extend_wqe.buf_desc.sge.hi_addr = upper_32_bits(dma_addr); - rq_wqe->extend_wqe.buf_desc.sge.lo_addr = lower_32_bits(dma_addr); - } else { - rq_wqe->normal_wqe.buf_hi_addr = upper_32_bits(dma_addr); - rq_wqe->normal_wqe.buf_lo_addr = lower_32_bits(dma_addr); - } - rxq->next_to_update = (rxq->next_to_update + 1) & rxq->q_mask; - } - - if (likely(i)) { - if (!rq_pi_rd_en) { - spnic_write_db(rxq->rq, rxq->q_id & (SPNIC_DCB_COS_MAX - 1), RQ_CFLAG_DP, - (u16)((u32)rxq->next_to_update << rxq->rq->wqe_type)); - } else { - /* Write all the wqes before pi update */ - wmb(); - - spnic_update_rq_hw_pi(rxq->rq, rxq->next_to_update); - } - rxq->delta -= i; - rxq->next_to_alloc = rxq->next_to_update; - } else if (free_wqebbs == rxq->q_depth - 1) { - RXQ_STATS_INC(rxq, rx_buf_empty); - } - - return i; -} - -static u32 spnic_rx_alloc_buffers(struct spnic_nic_dev *nic_dev, u32 rq_depth, - struct spnic_rx_info *rx_info_arr) -{ - u32 free_wqebbs = rq_depth - 1; - u32 idx; - - for (idx = 0; idx < free_wqebbs; idx++) { - if (!rx_alloc_mapped_page(nic_dev, &rx_info_arr[idx])) - break; - } - - return idx; -} - -void spnic_rx_free_buffers(struct spnic_nic_dev *nic_dev, u32 q_depth, - struct spnic_rx_info *rx_info_arr) -{ - struct spnic_rx_info *rx_info = NULL; - u32 i; - - /* Free all the Rx ring sk_buffs */ - for (i = 0; i < q_depth; i++) { - rx_info = &rx_info_arr[i]; - - if (rx_info->buf_dma_addr) { - dma_unmap_page(&nic_dev->pdev->dev, rx_info->buf_dma_addr, - nic_dev->dma_rx_buff_size, DMA_FROM_DEVICE); - rx_info->buf_dma_addr = 0; - } - - if (rx_info->page) { - __free_pages(rx_info->page, nic_dev->page_order); - rx_info->page = NULL; - } - } -} - -void stub_spnic_rx_free_buffers(struct spnic_rxq *rxq) -{ - struct spnic_rx_info *rx_info = NULL; - u32 i; - - /* Free all the Rx ring sk_buffs */ - for (i = 0; i < rxq->q_depth; i++) { - rx_info = &rxq->rx_info[i]; - - if (rx_info->buf_dma_addr) { - dma_unmap_page(rxq->dev, rx_info->buf_dma_addr, rx_info->skb_len, - DMA_FROM_DEVICE); - rx_info->buf_dma_addr = 0; - } - - if (rx_info->saved_skb) { - dev_kfree_skb_any(rx_info->saved_skb); - rx_info->saved_skb = NULL; - } - } -} - -static void spnic_reuse_rx_page(struct spnic_rxq *rxq, struct spnic_rx_info *old_rx_info) -{ - struct spnic_rx_info *new_rx_info; - u16 nta = rxq->next_to_alloc; - - new_rx_info = &rxq->rx_info[nta]; - - /* update, and store next to alloc */ - nta++; - rxq->next_to_alloc = (nta < rxq->q_depth) ? nta : 0; - - new_rx_info->page = old_rx_info->page; - new_rx_info->page_offset = old_rx_info->page_offset; - new_rx_info->buf_dma_addr = old_rx_info->buf_dma_addr; - - /* sync the buffer for use by the device */ - dma_sync_single_range_for_device(rxq->dev, new_rx_info->buf_dma_addr, - new_rx_info->page_offset, rxq->buf_len, - DMA_FROM_DEVICE); -} - -static bool spnic_add_rx_frag(struct spnic_rxq *rxq, struct spnic_rx_info *rx_info, - struct sk_buff *skb, u32 size) -{ - struct page *page; - u8 *va; - - page = rx_info->page; - va = (u8 *)page_address(page) + rx_info->page_offset; - prefetch(va); -#if L1_CACHE_BYTES < 128 - prefetch(va + L1_CACHE_BYTES); -#endif - - dma_sync_single_range_for_cpu(rxq->dev, rx_info->buf_dma_addr, - rx_info->page_offset, - rxq->buf_len, DMA_FROM_DEVICE); - - if (size <= SPNIC_RX_HDR_SIZE && !skb_is_nonlinear(skb)) { - memcpy(__skb_put(skb, size), va, ALIGN(size, sizeof(long))); - - /* page is not reserved, we can reuse buffer as-is */ - if (likely(page_to_nid(page) == numa_node_id())) - return true; - - /* this page cannot be reused so discard it */ - put_page(page); - return false; - } - - skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page, - (int)rx_info->page_offset, (int)size, rxq->buf_len); - - /* avoid re-using remote pages */ - if (unlikely(page_to_nid(page) != numa_node_id())) - return false; - - /* if we are only owner of page we can reuse it */ - if (unlikely(page_count(page) != 1)) - return false; - - /* flip page offset to other buffer */ - rx_info->page_offset ^= rxq->buf_len; - get_page(page); - - return true; -} - -static void packaging_skb(struct spnic_rxq *rxq, struct sk_buff *head_skb, u8 sge_num, u32 pkt_len) -{ - struct spnic_rx_info *rx_info = NULL; - struct sk_buff *skb = NULL; - u8 frag_num = 0; - u32 size; - u32 sw_ci; - - sw_ci = rxq->cons_idx & rxq->q_mask; - skb = head_skb; - while (sge_num) { - rx_info = &rxq->rx_info[sw_ci]; - sw_ci = (sw_ci + 1) & rxq->q_mask; - if (unlikely(pkt_len > rxq->buf_len)) { - size = rxq->buf_len; - pkt_len -= rxq->buf_len; - } else { - size = pkt_len; - } - - if (unlikely(frag_num == MAX_SKB_FRAGS)) { - frag_num = 0; - if (skb == head_skb) - skb = skb_shinfo(skb)->frag_list; - else - skb = skb->next; - } - - if (unlikely(skb != head_skb)) { - head_skb->len += size; - head_skb->data_len += size; - head_skb->truesize += rxq->buf_len; - } - - if (likely(spnic_add_rx_frag(rxq, rx_info, skb, size))) { - spnic_reuse_rx_page(rxq, rx_info); - } else { - /* we are not reusing the buffer so unmap it */ - dma_unmap_page(rxq->dev, rx_info->buf_dma_addr, - rxq->dma_rx_buff_size, DMA_FROM_DEVICE); - } - /* clear contents of buffer_info */ - rx_info->buf_dma_addr = 0; - rx_info->page = NULL; - sge_num--; - frag_num++; - } -} - -#define SPNIC_GET_SGE_NUM(pkt_len, rxq) \ - ((u8)(((pkt_len) >> (rxq)->rx_buff_shift) + \ - (((pkt_len) & ((rxq)->buf_len - 1)) ? 1 : 0))) - -static struct sk_buff *spnic_fetch_rx_buffer(struct spnic_rxq *rxq, u32 pkt_len) -{ - struct sk_buff *head_skb = NULL; - struct sk_buff *cur_skb = NULL; - struct sk_buff *skb = NULL; - struct net_device *netdev = rxq->netdev; - u8 sge_num, skb_num; - u16 wqebb_cnt = 0; - - head_skb = netdev_alloc_skb_ip_align(netdev, SPNIC_RX_HDR_SIZE); - if (unlikely(!head_skb)) - return NULL; - - sge_num = SPNIC_GET_SGE_NUM(pkt_len, rxq); - if (likely(sge_num <= MAX_SKB_FRAGS)) - skb_num = 1; - else - skb_num = (sge_num / MAX_SKB_FRAGS) + ((sge_num % MAX_SKB_FRAGS) ? 1 : 0); - - while (unlikely(skb_num > 1)) { - cur_skb = netdev_alloc_skb_ip_align(netdev, SPNIC_RX_HDR_SIZE); - if (unlikely(!cur_skb)) - goto alloc_skb_fail; - - if (!skb) { - skb_shinfo(head_skb)->frag_list = cur_skb; - skb = cur_skb; - } else { - skb->next = cur_skb; - skb = cur_skb; - } - - skb_num--; - } - - prefetchw(head_skb->data); - wqebb_cnt = sge_num; - - packaging_skb(rxq, head_skb, sge_num, pkt_len); - - rxq->cons_idx += wqebb_cnt; - rxq->delta += wqebb_cnt; - - return head_skb; - -alloc_skb_fail: - dev_kfree_skb_any(head_skb); - return NULL; -} - -void spnic_rxq_get_stats(struct spnic_rxq *rxq, struct spnic_rxq_stats *stats) -{ - struct spnic_rxq_stats *rxq_stats = &rxq->rxq_stats; - unsigned int start; - - u64_stats_update_begin(&stats->syncp); - do { - start = u64_stats_fetch_begin(&rxq_stats->syncp); - stats->bytes = rxq_stats->bytes; - stats->packets = rxq_stats->packets; - stats->errors = rxq_stats->csum_errors + - rxq_stats->other_errors; - stats->csum_errors = rxq_stats->csum_errors; - stats->other_errors = rxq_stats->other_errors; - stats->dropped = rxq_stats->dropped; - stats->xdp_dropped = rxq_stats->xdp_dropped; - stats->rx_buf_empty = rxq_stats->rx_buf_empty; - } while (u64_stats_fetch_retry(&rxq_stats->syncp, start)); - u64_stats_update_end(&stats->syncp); -} - -void spnic_rxq_clean_stats(struct spnic_rxq_stats *rxq_stats) -{ - u64_stats_update_begin(&rxq_stats->syncp); - rxq_stats->bytes = 0; - rxq_stats->packets = 0; - rxq_stats->errors = 0; - rxq_stats->csum_errors = 0; - rxq_stats->other_errors = 0; - rxq_stats->dropped = 0; - rxq_stats->xdp_dropped = 0; - rxq_stats->rx_buf_empty = 0; - - rxq_stats->alloc_skb_err = 0; - rxq_stats->alloc_rx_buf_err = 0; - rxq_stats->xdp_large_pkt = 0; - u64_stats_update_end(&rxq_stats->syncp); -} - -static void rxq_stats_init(struct spnic_rxq *rxq) -{ - struct spnic_rxq_stats *rxq_stats = &rxq->rxq_stats; - - u64_stats_init(&rxq_stats->syncp); - spnic_rxq_clean_stats(rxq_stats); -} - -static void spnic_pull_tail(struct sk_buff *skb) -{ - skb_frag_t *frag = &skb_shinfo(skb)->frags[0]; - unsigned char *va = NULL; - unsigned int pull_len; - - /* it is valid to use page_address instead of kmap since we are - * working with pages allocated out of the lomem pool per - * alloc_page(GFP_ATOMIC) - */ - va = skb_frag_address(frag); - - /* we need the header to contain the greater of either ETH_HLEN or - * 60 bytes if the skb->len is less than 60 for skb_pad. - */ - pull_len = eth_get_headlen(skb->dev, va, SPNIC_RX_HDR_SIZE); - - /* align pull length to size of long to optimize memcpy performance */ - skb_copy_to_linear_data(skb, va, ALIGN(pull_len, sizeof(long))); - - /* update all of the pointers */ - skb_frag_size_sub(frag, (int)pull_len); - skb_frag_off_add(frag, (int)pull_len); - - skb->data_len -= pull_len; - skb->tail += pull_len; -} - -static void spnic_rx_csum(struct spnic_rxq *rxq, u32 offload_type, u32 status, struct sk_buff *skb) -{ - struct net_device *netdev = rxq->netdev; - u32 pkt_type = SPNIC_GET_RX_PKT_TYPE(offload_type); - u32 ip_type = SPNIC_GET_RX_IP_TYPE(offload_type); - u32 pkt_fmt = SPNIC_GET_RX_TUNNEL_PKT_FORMAT(offload_type); - - u32 csum_err; - - csum_err = SPNIC_GET_RX_CSUM_ERR(status); - - if (unlikely(csum_err == SPNIC_RX_CSUM_IPSU_OTHER_ERR)) - rxq->rxq_stats.other_errors++; - - if (!(netdev->features & NETIF_F_RXCSUM)) - return; - - if (unlikely(csum_err)) { - /* pkt type is recognized by HW, and csum is wrong */ - if (!(csum_err & (SPNIC_RX_CSUM_HW_CHECK_NONE | SPNIC_RX_CSUM_IPSU_OTHER_ERR))) - rxq->rxq_stats.csum_errors++; - skb->ip_summed = CHECKSUM_NONE; - return; - } - - if (ip_type == SPNIC_RX_INVALID_IP_TYPE || - !(pkt_fmt == SPNIC_RX_PKT_FORMAT_NON_TUNNEL || - pkt_fmt == SPNIC_RX_PKT_FORMAT_VXLAN)) { - skb->ip_summed = CHECKSUM_NONE; - return; - } - - switch (pkt_type) { - case SPNIC_RX_TCP_PKT: - case SPNIC_RX_UDP_PKT: - case SPNIC_RX_SCTP_PKT: - skb->ip_summed = CHECKSUM_UNNECESSARY; - break; - default: - skb->ip_summed = CHECKSUM_NONE; - break; - } -} - -static void spnic_rx_gro(struct spnic_rxq *rxq, u32 offload_type, struct sk_buff *skb) -{ - struct net_device *netdev = rxq->netdev; - bool l2_tunnel = false; - - if (!(netdev->features & NETIF_F_GRO)) - return; - - l2_tunnel = - SPNIC_GET_RX_TUNNEL_PKT_FORMAT(offload_type) == SPNIC_RX_PKT_FORMAT_VXLAN ? 1 : 0; - - if (l2_tunnel && skb->ip_summed == CHECKSUM_UNNECESSARY) - /* If we checked the outer header let the stack know */ - skb->csum_level = 1; -} - -static void spnic_copy_lp_data(struct spnic_nic_dev *nic_dev, struct sk_buff *skb) -{ - struct net_device *netdev = nic_dev->netdev; - u8 *lb_buf = nic_dev->lb_test_rx_buf; - void *frag_data = NULL; - int lb_len = nic_dev->lb_pkt_len; - int pkt_offset, frag_len, i; - - if (nic_dev->lb_test_rx_idx == LP_PKT_CNT) { - nic_dev->lb_test_rx_idx = 0; - nicif_warn(nic_dev, rx_err, netdev, "Loopback test warning, receive too many test pkts\n"); - } - - if (skb->len != nic_dev->lb_pkt_len) { - nicif_warn(nic_dev, rx_err, netdev, "Wrong packet length\n"); - nic_dev->lb_test_rx_idx++; - return; - } - - pkt_offset = nic_dev->lb_test_rx_idx * lb_len; - frag_len = (int)skb_headlen(skb); - memcpy(lb_buf + pkt_offset, skb->data, frag_len); - - pkt_offset += frag_len; - for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - frag_data = skb_frag_address(&skb_shinfo(skb)->frags[i]); - frag_len = (int)skb_frag_size(&skb_shinfo(skb)->frags[i]); - memcpy(lb_buf + pkt_offset, frag_data, frag_len); - - pkt_offset += frag_len; - } - nic_dev->lb_test_rx_idx++; -} - -static inline void spnic_lro_set_gso_params(struct sk_buff *skb, u16 num_lro) -{ - struct ethhdr *eth = (struct ethhdr *)(skb->data); - __be16 proto; - - proto = __vlan_get_protocol(skb, eth->h_proto, NULL); - - skb_shinfo(skb)->gso_size = (u16)DIV_ROUND_UP((skb->len - skb_headlen(skb)), num_lro); - skb_shinfo(skb)->gso_type = (proto == htons(ETH_P_IP)) ? SKB_GSO_TCPV4 : SKB_GSO_TCPV6; -} - -enum spnic_xdp_pkt { - SPNIC_XDP_PKT_PASS, - SPNIC_XDP_PKT_DROP, -}; - -static inline void update_drop_rx_info(struct spnic_rxq *rxq, u16 weqbb_num) -{ - struct spnic_rx_info *rx_info = NULL; - - while (weqbb_num) { - rx_info = &rxq->rx_info[rxq->cons_idx & rxq->q_mask]; - if (likely(page_to_nid(rx_info->page) == numa_node_id())) - spnic_reuse_rx_page(rxq, rx_info); - - rx_info->buf_dma_addr = 0; - rx_info->page = NULL; - rxq->cons_idx++; - rxq->delta++; - - weqbb_num--; - } -} - -int spnic_run_xdp(struct spnic_rxq *rxq, u32 pkt_len) -{ - struct bpf_prog *xdp_prog = NULL; - struct spnic_rx_info *rx_info = NULL; - struct xdp_buff xdp; - int result = SPNIC_XDP_PKT_PASS; - u16 weqbb_num = 1; /* xdp can only use one rx_buff */ - u8 *va = NULL; - u32 act; - - rcu_read_lock(); - xdp_prog = READ_ONCE(rxq->xdp_prog); - if (!xdp_prog) - goto unlock_rcu; - - if (unlikely(pkt_len > rxq->buf_len)) { - RXQ_STATS_INC(rxq, xdp_large_pkt); - weqbb_num = (u16)(pkt_len >> rxq->rx_buff_shift) + - ((pkt_len & (rxq->buf_len - 1)) ? 1 : 0); - result = SPNIC_XDP_PKT_DROP; - goto xdp_out; - } - - rx_info = &rxq->rx_info[rxq->cons_idx & rxq->q_mask]; - va = (u8 *)page_address(rx_info->page) + rx_info->page_offset; - prefetch(va); - dma_sync_single_range_for_cpu(rxq->dev, rx_info->buf_dma_addr, rx_info->page_offset, - rxq->buf_len, DMA_FROM_DEVICE); - xdp.data = va; - xdp.data_hard_start = xdp.data; - xdp.data_end = xdp.data + pkt_len; - xdp.frame_sz = rxq->buf_len; - xdp_set_data_meta_invalid(&xdp); - prefetchw(xdp.data_hard_start); - act = bpf_prog_run_xdp(xdp_prog, &xdp); - switch (act) { - case XDP_PASS: - break; - case XDP_DROP: - result = SPNIC_XDP_PKT_DROP; - break; - default: - result = SPNIC_XDP_PKT_DROP; - bpf_warn_invalid_xdp_action(act); - } - -xdp_out: - if (result == SPNIC_XDP_PKT_DROP) { - RXQ_STATS_INC(rxq, xdp_dropped); - update_drop_rx_info(rxq, weqbb_num); - } - -unlock_rcu: - rcu_read_unlock(); - - return result; -} - -int recv_one_pkt(struct spnic_rxq *rxq, struct spnic_rq_cqe *rx_cqe, - u32 pkt_len, u32 vlan_len, u32 status) -{ - struct sk_buff *skb; - struct net_device *netdev = rxq->netdev; - u32 offload_type; - u16 num_lro; - struct spnic_nic_dev *nic_dev = netdev_priv(rxq->netdev); - - u32 xdp_status; - - xdp_status = spnic_run_xdp(rxq, pkt_len); - if (xdp_status == SPNIC_XDP_PKT_DROP) - return 0; - - skb = spnic_fetch_rx_buffer(rxq, pkt_len); - if (unlikely(!skb)) { - RXQ_STATS_INC(rxq, alloc_skb_err); - return -ENOMEM; - } - - /* place header in linear portion of buffer */ - if (skb_is_nonlinear(skb)) - spnic_pull_tail(skb); - - offload_type = rx_cqe->offload_type; - spnic_rx_csum(rxq, offload_type, status, skb); - - spnic_rx_gro(rxq, offload_type, skb); - - if ((netdev->features & NETIF_F_HW_VLAN_CTAG_RX) && - SPNIC_GET_RX_VLAN_OFFLOAD_EN(offload_type)) { - u16 vid = SPNIC_GET_RX_VLAN_TAG(vlan_len); - - /* if the packet is a vlan pkt, the vid may be 0 */ - __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vid); - } - - if (unlikely(test_bit(SPNIC_LP_TEST, &nic_dev->flags))) - spnic_copy_lp_data(nic_dev, skb); - - num_lro = SPNIC_GET_RX_NUM_LRO(status); - if (num_lro) - spnic_lro_set_gso_params(skb, num_lro); - - skb_record_rx_queue(skb, rxq->q_id); - skb->protocol = eth_type_trans(skb, netdev); - - if (skb_has_frag_list(skb)) { - napi_gro_flush(&rxq->irq_cfg->napi, false); - netif_receive_skb(skb); - } else { - napi_gro_receive(&rxq->irq_cfg->napi, skb); - } - - return 0; -} - -void rx_pass_super_cqe(struct spnic_rxq *rxq, u32 index, u32 pkt_num, struct spnic_rq_cqe *cqe) -{ - u8 sge_num = 0; - u32 pkt_len; - - while (index < pkt_num) { - pkt_len = spnic_get_pkt_len_for_super_cqe(cqe, index == (pkt_num - 1)); - sge_num += (u8)(pkt_len >> rxq->rx_buff_shift) + - ((pkt_len & (rxq->buf_len - 1)) ? 1 : 0); - index++; - } - - rxq->cons_idx += sge_num; - rxq->delta += sge_num; -} - -static inline int recv_supper_cqe(struct spnic_rxq *rxq, struct spnic_rq_cqe *rx_cqe, u32 pkt_info, - u32 vlan_len, u32 status, int *pkts, u64 *rx_bytes, u32 *dropped) -{ - u32 pkt_len; - int i, pkt_num = 0; - - pkt_num = SPNIC_GET_RQ_CQE_PKT_NUM(pkt_info); - i = 0; - while (i < pkt_num) { - pkt_len = ((i == (pkt_num - 1)) ? - RQ_CQE_PKT_LEN_GET(pkt_info, LAST_LEN) : - RQ_CQE_PKT_LEN_GET(pkt_info, FIRST_LEN)); - if (unlikely(recv_one_pkt(rxq, rx_cqe, pkt_len, vlan_len, status))) { - if (i) { - rx_pass_super_cqe(rxq, i, pkt_num, rx_cqe); - *dropped += (pkt_num - i); - } - break; - } - - *rx_bytes += pkt_len; - (*pkts)++; - i++; - } - - if (!i) - return -EFAULT; - - return 0; -} - -#define LRO_PKT_HDR_LEN_IPV4 66 -#define LRO_PKT_HDR_LEN_IPV6 86 -#define LRO_PKT_HDR_LEN(cqe) \ - (SPNIC_GET_RX_IP_TYPE((cqe)->offload_type) == \ - SPNIC_RX_IPV6_PKT ? LRO_PKT_HDR_LEN_IPV6 : LRO_PKT_HDR_LEN_IPV4) - -static void stub_rx_recv_jumbo_pkt(struct spnic_rxq *rxq, struct sk_buff *head_skb, - unsigned int left_pkt_len) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(rxq->netdev); - struct sk_buff *skb = NULL; - struct sk_buff *curr_skb = head_skb; - struct spnic_rx_info *rx_info = NULL; - unsigned int curr_len; - - while (left_pkt_len > 0) { - rx_info = &rxq->rx_info[rxq->cons_idx & rxq->q_mask]; - skb = rx_info->saved_skb; - - dma_unmap_single(&nic_dev->pdev->dev, rx_info->buf_dma_addr, - rx_info->skb_len, DMA_FROM_DEVICE); - - rx_info->buf_dma_addr = 0; - rx_info->saved_skb = NULL; - - prefetch(skb->data); - - curr_len = (left_pkt_len > rx_info->skb_len) ? rx_info->skb_len : left_pkt_len; - - left_pkt_len -= curr_len; - - __skb_put(skb, curr_len); - - if (curr_skb == head_skb) - skb_shinfo(head_skb)->frag_list = skb; - else - curr_skb->next = skb; - - head_skb->len += skb->len; - head_skb->data_len += skb->len; - head_skb->truesize += skb->truesize; - - curr_skb = skb; - rxq->cons_idx++; - rxq->delta++; - } -} - -int stub_spnic_rx_poll(struct spnic_rxq *rxq, int budget) -{ - u32 sw_ci, status, pkt_len, vlan_len = 0; - struct spnic_nic_dev *nic_dev = netdev_priv(rxq->netdev); - struct spnic_rq_cqe *rx_cqe = NULL; - u64 rx_bytes = 0; - int pkts = 0; - struct sk_buff *skb = NULL; - struct spnic_rx_info *rx_info = NULL; - u32 offload_type; - - while (likely(pkts < budget)) { - sw_ci = rxq->cons_idx & rxq->q_mask; - rx_info = &rxq->rx_info[sw_ci]; - rx_cqe = rxq->rx_info[sw_ci].cqe; - status = be32_to_cpu(rx_cqe->status); - - if (!SPNIC_GET_RX_DONE(status)) - break; - - /* make sure we read rx_done before packet length */ - rmb(); - - vlan_len = be32_to_cpu(rx_cqe->vlan_len); - pkt_len = SPNIC_GET_RX_PKT_LEN(vlan_len); - skb = rx_info->saved_skb; - - dma_unmap_single(&nic_dev->pdev->dev, rx_info->buf_dma_addr, - rx_info->skb_len, DMA_FROM_DEVICE); - - rx_info->buf_dma_addr = 0; - rx_info->saved_skb = NULL; - - rxq->cons_idx++; - rxq->delta++; - - if (pkt_len <= rx_info->skb_len) { - __skb_put(skb, pkt_len); - } else { - __skb_put(skb, rx_info->skb_len); - stub_rx_recv_jumbo_pkt(rxq, skb, pkt_len - rx_info->skb_len); - } - - offload_type = be32_to_cpu(rx_cqe->offload_type); - spnic_rx_csum(rxq, offload_type, status, skb); - - spnic_rx_gro(rxq, offload_type, skb); - - skb_record_rx_queue(skb, rxq->q_id); - skb->protocol = eth_type_trans(skb, rxq->netdev); - - if (skb_has_frag_list(skb)) { - napi_gro_flush(&rxq->irq_cfg->napi, false); - netif_receive_skb(skb); - } else { - napi_gro_receive(&rxq->irq_cfg->napi, skb); - } - rx_bytes += pkt_len; - pkts++; - rx_cqe->status = 0; - } - - if (rxq->delta >= SPNIC_RX_BUFFER_WRITE) - stub_spnic_rx_fill_buffers(rxq); - - u64_stats_update_begin(&rxq->rxq_stats.syncp); - rxq->rxq_stats.packets += pkts; - rxq->rxq_stats.bytes += rx_bytes; - u64_stats_update_end(&rxq->rxq_stats.syncp); - return pkts; -} - -int spnic_rx_poll(struct spnic_rxq *rxq, int budget) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(rxq->netdev); - u32 sw_ci, status, pkt_len, vlan_len, pkt_info, dropped = 0; - struct spnic_rq_cqe *rx_cqe = NULL; - u64 rx_bytes = 0; - u16 num_lro; - int pkts = 0, nr_pkts = 0; - u16 num_wqe = 0; - - while (likely(pkts < budget)) { - sw_ci = rxq->cons_idx & rxq->q_mask; - rx_cqe = rxq->rx_info[sw_ci].cqe; - status = rx_cqe->status; - - if (!SPNIC_GET_RX_DONE(status)) - break; - - /* make sure we read rx_done before packet length */ - rmb(); - - vlan_len = rx_cqe->vlan_len; - pkt_info = rx_cqe->pkt_info; - pkt_len = SPNIC_GET_RX_PKT_LEN(vlan_len); - - if (unlikely(SPNIC_GET_SUPER_CQE_EN(pkt_info))) { - if (unlikely(recv_supper_cqe(rxq, rx_cqe, pkt_info, vlan_len, status, &pkts, - &rx_bytes, &dropped))) - break; - nr_pkts += (int)SPNIC_GET_RQ_CQE_PKT_NUM(pkt_info); - } else { - if (recv_one_pkt(rxq, rx_cqe, pkt_len, - vlan_len, status)) - break; - rx_bytes += pkt_len; - pkts++; - nr_pkts++; - - num_lro = SPNIC_GET_RX_NUM_LRO(status); - if (num_lro) { - rx_bytes += ((num_lro - 1) * LRO_PKT_HDR_LEN(rx_cqe)); - num_wqe += SPNIC_GET_SGE_NUM(pkt_len, rxq); - } - } - - rx_cqe->status = 0; - - if (num_wqe >= nic_dev->lro_replenish_thld) - break; - } - - if (rxq->delta >= SPNIC_RX_BUFFER_WRITE) - spnic_rx_fill_buffers(rxq); - - u64_stats_update_begin(&rxq->rxq_stats.syncp); - rxq->rxq_stats.packets += nr_pkts; - rxq->rxq_stats.bytes += rx_bytes; - rxq->rxq_stats.dropped += dropped; - u64_stats_update_end(&rxq->rxq_stats.syncp); - return pkts; -} - -int spnic_alloc_rxqs_res(struct spnic_nic_dev *nic_dev, u16 num_rq, - u32 rq_depth, struct spnic_dyna_rxq_res *rxqs_res) -{ - struct spnic_dyna_rxq_res *rqres = NULL; - u64 cqe_mem_size = sizeof(struct spnic_rq_cqe) * rq_depth; - int idx, i; - u32 pkts; - u64 size; - - for (idx = 0; idx < num_rq; idx++) { - rqres = &rxqs_res[idx]; - size = sizeof(*rqres->rx_info) * rq_depth; - rqres->rx_info = kzalloc(size, GFP_KERNEL); - if (!rqres->rx_info) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Failed to alloc rxq%d rx info\n", idx); - goto err_out; - } - - rqres->cqe_start_vaddr = - dma_alloc_coherent(&nic_dev->pdev->dev, cqe_mem_size, - &rqres->cqe_start_paddr, GFP_KERNEL); - if (!rqres->cqe_start_vaddr) { - kfree(rqres->rx_info); - nicif_err(nic_dev, drv, nic_dev->netdev, - "Failed to alloc rxq%d cqe\n", idx); - goto err_out; - } - - pkts = spnic_rx_alloc_buffers(nic_dev, rq_depth, rqres->rx_info); - if (!pkts) { - dma_free_coherent(&nic_dev->pdev->dev, cqe_mem_size, - rqres->cqe_start_vaddr, - rqres->cqe_start_paddr); - kfree(rqres->rx_info); - nicif_err(nic_dev, drv, nic_dev->netdev, - "Failed to alloc rxq%d rx buffers\n", idx); - goto err_out; - } - rqres->next_to_alloc = (u16)pkts; - } - return 0; - -err_out: - for (i = 0; i < idx; i++) { - rqres = &rxqs_res[i]; - - spnic_rx_free_buffers(nic_dev, rq_depth, rqres->rx_info); - dma_free_coherent(&nic_dev->pdev->dev, cqe_mem_size, - rqres->cqe_start_vaddr, rqres->cqe_start_paddr); - kfree(rqres->rx_info); - } - - return -ENOMEM; -} - -void spnic_free_rxqs_res(struct spnic_nic_dev *nic_dev, u16 num_rq, - u32 rq_depth, struct spnic_dyna_rxq_res *rxqs_res) -{ - struct spnic_dyna_rxq_res *rqres = NULL; - u64 cqe_mem_size = sizeof(struct spnic_rq_cqe) * rq_depth; - int idx; - - for (idx = 0; idx < num_rq; idx++) { - rqres = &rxqs_res[idx]; - - spnic_rx_free_buffers(nic_dev, rq_depth, rqres->rx_info); - dma_free_coherent(&nic_dev->pdev->dev, cqe_mem_size, rqres->cqe_start_vaddr, - rqres->cqe_start_paddr); - kfree(rqres->rx_info); - } -} - -int spnic_configure_rxqs(struct spnic_nic_dev *nic_dev, u16 num_rq, - u32 rq_depth, struct spnic_dyna_rxq_res *rxqs_res) -{ - struct spnic_dyna_rxq_res *rqres = NULL; - struct irq_info *msix_entry = NULL; - struct spnic_rxq *rxq = NULL; - struct spnic_rq_cqe *cqe_va = NULL; - dma_addr_t cqe_pa; - u16 q_id; - u32 idx; - u32 pkts; - - for (q_id = 0; q_id < num_rq; q_id++) { - rxq = &nic_dev->rxqs[q_id]; - rqres = &rxqs_res[q_id]; - msix_entry = &nic_dev->qps_irq_info[q_id]; - - rxq->irq_id = msix_entry->irq_id; - rxq->msix_entry_idx = msix_entry->msix_entry_idx; - rxq->next_to_update = 0; - rxq->next_to_alloc = rqres->next_to_alloc; - rxq->q_depth = rq_depth; - rxq->delta = rxq->q_depth; - rxq->q_mask = rxq->q_depth - 1; - rxq->cons_idx = 0; - - rxq->rx_info = rqres->rx_info; - - /* fill cqe */ - cqe_va = (struct spnic_rq_cqe *)rqres->cqe_start_vaddr; - cqe_pa = rqres->cqe_start_paddr; - for (idx = 0; idx < rq_depth; idx++) { - rxq->rx_info[idx].cqe = cqe_va; - rxq->rx_info[idx].cqe_dma = cqe_pa; - cqe_va++; - cqe_pa += sizeof(*rxq->rx_info->cqe); - } - - rxq->rq = spnic_get_nic_queue(nic_dev->hwdev, rxq->q_id, SPNIC_RQ); - if (!rxq->rq) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to get rq\n"); - return -EINVAL; - } - - pkts = spnic_rx_fill_wqe(rxq); - if (pkts != rxq->q_depth) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to fill rx wqe\n"); - return -EFAULT; - } - - pkts = spnic_rx_fill_buffers(rxq); - if (!pkts) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to fill Rx buffer\n"); - return -ENOMEM; - } - } - - return 0; -} - -void spnic_free_rxqs(struct net_device *netdev) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - - kfree(nic_dev->rxqs); -} - -int spnic_alloc_rxqs(struct net_device *netdev) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - struct pci_dev *pdev = nic_dev->pdev; - struct spnic_rxq *rxq = NULL; - u16 num_rxqs = nic_dev->max_qps; - u16 q_id; - u64 rxq_size; - - rxq_size = num_rxqs * sizeof(*nic_dev->rxqs); - if (!rxq_size) { - nic_err(&pdev->dev, "Cannot allocate zero size rxqs\n"); - return -EINVAL; - } - - nic_dev->rxqs = kzalloc(rxq_size, GFP_KERNEL); - if (!nic_dev->rxqs) { - nic_err(&pdev->dev, "Failed to allocate rxqs\n"); - return -ENOMEM; - } - - for (q_id = 0; q_id < num_rxqs; q_id++) { - rxq = &nic_dev->rxqs[q_id]; - rxq->netdev = netdev; - rxq->dev = &pdev->dev; - rxq->q_id = q_id; - rxq->buf_len = nic_dev->rx_buff_len; - rxq->rx_buff_shift = ilog2(nic_dev->rx_buff_len); - rxq->dma_rx_buff_size = nic_dev->dma_rx_buff_size; - rxq->q_depth = nic_dev->q_params.rq_depth; - rxq->q_mask = nic_dev->q_params.rq_depth - 1; - - rxq_stats_init(rxq); - } - - return 0; -} - -int spnic_rx_configure(struct net_device *netdev) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - int err; - - if (test_bit(SPNIC_RSS_ENABLE, &nic_dev->flags)) { - err = spnic_rss_init(nic_dev); - if (err) { - nicif_err(nic_dev, drv, netdev, "Failed to init rss\n"); - return -EFAULT; - } - } - - return 0; -} - -void spnic_rx_remove_configure(struct net_device *netdev) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - - if (test_bit(SPNIC_RSS_ENABLE, &nic_dev->flags)) - spnic_rss_deinit(nic_dev); -} diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_rx.h b/drivers/net/ethernet/ramaxel/spnic/spnic_rx.h deleted file mode 100644 index 564b5765a41b..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_rx.h +++ /dev/null @@ -1,118 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPNIC_RX_H -#define SPNIC_RX_H - -#include <linux/types.h> - -/*rx cqe checksum err*/ -#define SPNIC_RX_CSUM_IP_CSUM_ERR BIT(0) -#define SPNIC_RX_CSUM_TCP_CSUM_ERR BIT(1) -#define SPNIC_RX_CSUM_UDP_CSUM_ERR BIT(2) -#define SPNIC_RX_CSUM_IGMP_CSUM_ERR BIT(3) -#define SPNIC_RX_CSUM_ICMPV4_CSUM_ERR BIT(4) -#define SPNIC_RX_CSUM_ICMPV6_CSUM_ERR BIT(5) -#define SPNIC_RX_CSUM_SCTP_CRC_ERR BIT(6) -#define SPNIC_RX_CSUM_HW_CHECK_NONE BIT(7) -#define SPNIC_RX_CSUM_IPSU_OTHER_ERR BIT(8) - -#define SPNIC_HEADER_DATA_UNIT 2 - -struct spnic_rxq_stats { - u64 packets; - u64 bytes; - u64 errors; - u64 csum_errors; - u64 other_errors; - u64 dropped; - u64 xdp_dropped; - u64 rx_buf_empty; - - u64 alloc_skb_err; - u64 alloc_rx_buf_err; - u64 xdp_large_pkt; - struct u64_stats_sync syncp; -}; - -struct spnic_rx_info { - dma_addr_t buf_dma_addr; - - struct spnic_rq_cqe *cqe; - dma_addr_t cqe_dma; - struct page *page; - u32 page_offset; - struct spnic_rq_wqe *rq_wqe; - struct sk_buff *saved_skb; - u32 skb_len; -}; - -struct spnic_rxq { - struct net_device *netdev; - - u16 q_id; - u32 q_depth; - u32 q_mask; - - u16 buf_len; - u32 rx_buff_shift; - u32 dma_rx_buff_size; - - struct spnic_rxq_stats rxq_stats; - u32 cons_idx; - u32 delta; - - u32 irq_id; - u16 msix_entry_idx; - - struct spnic_rx_info *rx_info; - struct spnic_io_queue *rq; - struct bpf_prog *xdp_prog; - - struct spnic_irq *irq_cfg; - u16 next_to_alloc; - u16 next_to_update; - struct device *dev; /* device for DMA mapping */ - - unsigned long status; - dma_addr_t cqe_start_paddr; - void *cqe_start_vaddr; - - u64 last_moder_packets; - u64 last_moder_bytes; - u8 last_coalesc_timer_cfg; - u8 last_pending_limt; -} ____cacheline_aligned; - -struct spnic_dyna_rxq_res { - u16 next_to_alloc; - struct spnic_rx_info *rx_info; - dma_addr_t cqe_start_paddr; - void *cqe_start_vaddr; -}; - -int spnic_alloc_rxqs(struct net_device *netdev); - -void spnic_free_rxqs(struct net_device *netdev); - -int spnic_alloc_rxqs_res(struct spnic_nic_dev *nic_dev, u16 num_rq, - u32 rq_depth, struct spnic_dyna_rxq_res *rxqs_res); - -void spnic_free_rxqs_res(struct spnic_nic_dev *nic_dev, u16 num_rq, - u32 rq_depth, struct spnic_dyna_rxq_res *rxqs_res); - -int spnic_configure_rxqs(struct spnic_nic_dev *nic_dev, u16 num_rq, - u32 rq_depth, struct spnic_dyna_rxq_res *rxqs_res); - -int spnic_rx_configure(struct net_device *netdev); - -void spnic_rx_remove_configure(struct net_device *netdev); - -int spnic_rx_poll(struct spnic_rxq *rxq, int budget); -int stub_spnic_rx_poll(struct spnic_rxq *rxq, int budget); - -void spnic_rxq_get_stats(struct spnic_rxq *rxq, struct spnic_rxq_stats *stats); - -void spnic_rxq_clean_stats(struct spnic_rxq_stats *rxq_stats); - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_sriov.c b/drivers/net/ethernet/ramaxel/spnic/spnic_sriov.c deleted file mode 100644 index aac22cb302ea..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_sriov.c +++ /dev/null @@ -1,200 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [NIC]" fmt - -#include <linux/pci.h> -#include <linux/interrupt.h> - -#include "sphw_common.h" -#include "sphw_crm.h" -#include "sphw_hw.h" -#include "spnic_lld.h" -#include "spnic_sriov.h" -#include "spnic_dev_mgmt.h" - -int spnic_init_vf_hw(void *hwdev, u16 start_vf_id, u16 end_vf_id) -{ - u16 i, func_idx; - int err; - - /* mbox msg channel resources will be freed during remove process */ - err = sphw_init_func_mbox_msg_channel(hwdev, sphw_func_max_vf(hwdev)); - if (err) - return err; - - /* vf use 256K as default wq page size, and can't change it */ - for (i = start_vf_id; i <= end_vf_id; i++) { - func_idx = sphw_glb_pf_vf_offset(hwdev) + i; - err = sphw_set_wq_page_size(hwdev, func_idx, SPHW_DEFAULT_WQ_PAGE_SIZE, - SPHW_CHANNEL_COMM); - if (err) - return err; - } - - return 0; -} - -int spnic_deinit_vf_hw(void *hwdev, u16 start_vf_id, u16 end_vf_id) -{ - u16 func_idx, idx; - - for (idx = start_vf_id; idx <= end_vf_id; idx++) { - func_idx = sphw_glb_pf_vf_offset(hwdev) + idx; - sphw_set_wq_page_size(hwdev, func_idx, SPHW_HW_WQ_PAGE_SIZE, SPHW_CHANNEL_COMM); - } - - return 0; -} - -int spnic_pci_sriov_disable(struct pci_dev *dev) -{ -#ifdef CONFIG_PCI_IOV - struct spnic_sriov_info *sriov_info = NULL; - struct sphw_event_info event = {0}; - void *hwdev = NULL; - u16 tmp_vfs; - - sriov_info = spnic_get_sriov_info_by_pcidev(dev); - hwdev = spnic_get_hwdev_by_pcidev(dev); - if (!hwdev) { - sdk_err(&dev->dev, "SR-IOV disable is not permitted, please wait...\n"); - return -EPERM; - } - - /* if SR-IOV is already disabled then there is nothing to do */ - if (!sriov_info->sriov_enabled) - return 0; - - if (test_and_set_bit(SPNIC_SRIOV_DISABLE, &sriov_info->state)) { - sdk_err(&dev->dev, "SR-IOV disable in process, please wait"); - return -EPERM; - } - - /* If our VFs are assigned we cannot shut down SR-IOV - * without causing issues, so just leave the hardware - * available but disabled - */ - if (pci_vfs_assigned(dev)) { - clear_bit(SPNIC_SRIOV_DISABLE, &sriov_info->state); - sdk_warn(&dev->dev, "Unloading driver while VFs are assigned - VFs will not be deallocated\n"); - return -EPERM; - } - - event.type = SPHW_EVENT_SRIOV_STATE_CHANGE; - event.sriov_state.enable = 0; - sphw_event_callback(hwdev, &event); - - sriov_info->sriov_enabled = false; - - /* disable iov and allow time for transactions to clear */ - pci_disable_sriov(dev); - - tmp_vfs = (u16)sriov_info->num_vfs; - sriov_info->num_vfs = 0; - spnic_deinit_vf_hw(hwdev, 1, tmp_vfs); - - clear_bit(SPNIC_SRIOV_DISABLE, &sriov_info->state); - -#endif - - return 0; -} - -int spnic_pci_sriov_enable(struct pci_dev *dev, int num_vfs) -{ -#ifdef CONFIG_PCI_IOV - struct spnic_sriov_info *sriov_info = NULL; - struct sphw_event_info event = {0}; - void *hwdev = NULL; - int pre_existing_vfs = 0; - int err = 0; - - sriov_info = spnic_get_sriov_info_by_pcidev(dev); - hwdev = spnic_get_hwdev_by_pcidev(dev); - if (!hwdev) { - sdk_err(&dev->dev, "SR-IOV enable is not permitted, please wait...\n"); - return -EPERM; - } - - if (test_and_set_bit(SPNIC_SRIOV_ENABLE, &sriov_info->state)) { - sdk_err(&dev->dev, "SR-IOV enable in process, please wait, num_vfs %d\n", - num_vfs); - return -EPERM; - } - - pre_existing_vfs = pci_num_vf(dev); - - if (num_vfs > pci_sriov_get_totalvfs(dev)) { - clear_bit(SPNIC_SRIOV_ENABLE, &sriov_info->state); - return -ERANGE; - } - if (pre_existing_vfs && pre_existing_vfs != num_vfs) { - err = spnic_pci_sriov_disable(dev); - if (err) { - clear_bit(SPNIC_SRIOV_ENABLE, &sriov_info->state); - return err; - } - } else if (pre_existing_vfs == num_vfs) { - clear_bit(SPNIC_SRIOV_ENABLE, &sriov_info->state); - return num_vfs; - } - - err = spnic_init_vf_hw(hwdev, 1, (u16)num_vfs); - if (err) { - sdk_err(&dev->dev, "Failed to init vf in hardware before enable sriov, error %d\n", - err); - clear_bit(SPNIC_SRIOV_ENABLE, &sriov_info->state); - return err; - } - - err = pci_enable_sriov(dev, num_vfs); - if (err) { - sdk_err(&dev->dev, "Failed to enable SR-IOV, error %d\n", err); - clear_bit(SPNIC_SRIOV_ENABLE, &sriov_info->state); - return err; - } - - sriov_info->sriov_enabled = true; - sriov_info->num_vfs = num_vfs; - - event.type = SPHW_EVENT_SRIOV_STATE_CHANGE; - event.sriov_state.enable = 1; - event.sriov_state.num_vfs = (u16)num_vfs; - sphw_event_callback(hwdev, &event); - - clear_bit(SPNIC_SRIOV_ENABLE, &sriov_info->state); - - return num_vfs; -#else - - return 0; -#endif -} - -static bool spnic_is_support_sriov_configure(struct pci_dev *pdev) -{ - /* TODO: get cap from firmware */ - - return true; -} - -int spnic_pci_sriov_configure(struct pci_dev *dev, int num_vfs) -{ - struct spnic_sriov_info *sriov_info = NULL; - - if (!spnic_is_support_sriov_configure(dev)) - return -EFAULT; - - sriov_info = spnic_get_sriov_info_by_pcidev(dev); - if (!sriov_info) - return -EFAULT; - - if (!test_bit(SPNIC_FUNC_PERSENT, &sriov_info->state)) - return -EFAULT; - - if (!num_vfs) - return spnic_pci_sriov_disable(dev); - else - return spnic_pci_sriov_enable(dev, num_vfs); -} diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_sriov.h b/drivers/net/ethernet/ramaxel/spnic/spnic_sriov.h deleted file mode 100644 index 622845e30427..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_sriov.h +++ /dev/null @@ -1,24 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPNIC_SRIOV_H -#define SPNIC_SRIOV_H -#include <linux/types.h> - -enum spnic_sriov_state { - SPNIC_SRIOV_DISABLE, - SPNIC_SRIOV_ENABLE, - SPNIC_FUNC_PERSENT, -}; - -struct spnic_sriov_info { - bool sriov_enabled; - unsigned int num_vfs; - unsigned long state; -}; - -struct spnic_sriov_info *spnic_get_sriov_info_by_pcidev(struct pci_dev *pdev); -int spnic_pci_sriov_disable(struct pci_dev *dev); -int spnic_pci_sriov_enable(struct pci_dev *dev, int num_vfs); -int spnic_pci_sriov_configure(struct pci_dev *dev, int num_vfs); -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_tx.c b/drivers/net/ethernet/ramaxel/spnic/spnic_tx.c deleted file mode 100644 index 7478e76aa729..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_tx.c +++ /dev/null @@ -1,877 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [NIC]" fmt - -#include <linux/netdevice.h> -#include <linux/kernel.h> -#include <linux/skbuff.h> -#include <linux/interrupt.h> -#include <linux/device.h> -#include <linux/pci.h> -#include <linux/tcp.h> -#include <linux/sctp.h> -#include <net/xfrm.h> -#include <linux/dma-mapping.h> -#include <linux/types.h> -#include <linux/u64_stats_sync.h> -#include <linux/module.h> -#include <linux/vmalloc.h> - -#include "sphw_crm.h" -#include "spnic_nic_qp.h" -#include "spnic_nic_io.h" -#include "spnic_nic_cfg.h" -#include "spnic_nic_dev.h" -#include "spnic_tx.h" - -#define MIN_SKB_LEN 32 - -#define MAX_PAYLOAD_OFFSET 221 - -#define NIC_QID(q_id, nic_dev) ((q_id) & ((nic_dev)->num_qps - 1)) - -#define SPNIC_TX_TASK_WRAPPED 1 -#define SPNIC_TX_BD_DESC_WRAPPED 2 - -#define TXQ_STATS_INC(txq, field) \ -do { \ - u64_stats_update_begin(&(txq)->txq_stats.syncp); \ - (txq)->txq_stats.field++; \ - u64_stats_update_end(&(txq)->txq_stats.syncp); \ -} while (0) - -void spnic_txq_get_stats(struct spnic_txq *txq, struct spnic_txq_stats *stats) -{ - struct spnic_txq_stats *txq_stats = &txq->txq_stats; - unsigned int start; - - u64_stats_update_begin(&stats->syncp); - do { - start = u64_stats_fetch_begin(&txq_stats->syncp); - stats->bytes = txq_stats->bytes; - stats->packets = txq_stats->packets; - stats->busy = txq_stats->busy; - stats->wake = txq_stats->wake; - stats->dropped = txq_stats->dropped; - } while (u64_stats_fetch_retry(&txq_stats->syncp, start)); - u64_stats_update_end(&stats->syncp); -} - -void spnic_txq_clean_stats(struct spnic_txq_stats *txq_stats) -{ - u64_stats_update_begin(&txq_stats->syncp); - txq_stats->bytes = 0; - txq_stats->packets = 0; - txq_stats->busy = 0; - txq_stats->wake = 0; - txq_stats->dropped = 0; - - txq_stats->skb_pad_err = 0; - txq_stats->frag_len_overflow = 0; - txq_stats->offload_cow_skb_err = 0; - txq_stats->map_frag_err = 0; - txq_stats->unknown_tunnel_pkt = 0; - txq_stats->frag_size_err = 0; - u64_stats_update_end(&txq_stats->syncp); -} - -static void txq_stats_init(struct spnic_txq *txq) -{ - struct spnic_txq_stats *txq_stats = &txq->txq_stats; - - u64_stats_init(&txq_stats->syncp); - spnic_txq_clean_stats(txq_stats); -} - -static inline void spnic_set_buf_desc(struct spnic_sq_bufdesc *buf_descs, dma_addr_t addr, u32 len) -{ - buf_descs->hi_addr = upper_32_bits(addr); - buf_descs->lo_addr = lower_32_bits(addr); - buf_descs->len = len; -} - -static int tx_map_skb(struct spnic_nic_dev *nic_dev, struct sk_buff *skb, - u16 valid_nr_frags, struct spnic_txq *txq, - struct spnic_tx_info *tx_info, - struct spnic_sq_wqe_combo *wqe_combo) -{ - struct spnic_sq_wqe_desc *wqe_desc = wqe_combo->ctrl_bd0; - struct spnic_sq_bufdesc *buf_desc = wqe_combo->bds_head; - struct spnic_dma_info *dma_info = tx_info->dma_info; - struct pci_dev *pdev = nic_dev->pdev; - skb_frag_t *frag = NULL; - u32 j, i; - int err; - - dma_info[0].dma = dma_map_single(&pdev->dev, skb->data, skb_headlen(skb), DMA_TO_DEVICE); - if (dma_mapping_error(&pdev->dev, dma_info[0].dma)) { - TXQ_STATS_INC(txq, map_frag_err); - return -EFAULT; - } - - dma_info[0].len = skb_headlen(skb); - - wqe_desc->hi_addr = upper_32_bits(dma_info[0].dma); - wqe_desc->lo_addr = lower_32_bits(dma_info[0].dma); - - wqe_desc->ctrl_len = dma_info[0].len; - - for (i = 0; i < valid_nr_frags;) { - frag = &(skb_shinfo(skb)->frags[i]); - if (unlikely(i == wqe_combo->first_bds_num)) - buf_desc = wqe_combo->bds_sec2; - - i++; - dma_info[i].dma = skb_frag_dma_map(&pdev->dev, frag, 0, skb_frag_size(frag), - DMA_TO_DEVICE); - if (dma_mapping_error(&pdev->dev, dma_info[i].dma)) { - TXQ_STATS_INC(txq, map_frag_err); - i--; - err = -EFAULT; - goto frag_map_err; - } - dma_info[i].len = skb_frag_size(frag); - - spnic_set_buf_desc(buf_desc, dma_info[i].dma, dma_info[i].len); - buf_desc++; - } - - return 0; - -frag_map_err: - for (j = 0; j < i;) { - j++; - dma_unmap_page(&pdev->dev, dma_info[j].dma, - dma_info[j].len, DMA_TO_DEVICE); - } - dma_unmap_single(&pdev->dev, dma_info[0].dma, dma_info[0].len, DMA_TO_DEVICE); - return err; -} - -static inline void tx_unmap_skb(struct spnic_nic_dev *nic_dev, - struct sk_buff *skb, u16 valid_nr_frags, - struct spnic_dma_info *dma_info) -{ - struct pci_dev *pdev = nic_dev->pdev; - int i; - - for (i = 0; i < valid_nr_frags; ) { - i++; - dma_unmap_page(&pdev->dev, dma_info[i].dma, dma_info[i].len, DMA_TO_DEVICE); - } - - dma_unmap_single(&pdev->dev, dma_info[0].dma, dma_info[0].len, DMA_TO_DEVICE); -} - -union spnic_l4 { - struct tcphdr *tcp; - struct udphdr *udp; - unsigned char *hdr; -}; - -enum sq_l3_type { - UNKNOWN_L3TYPE = 0, - IPV6_PKT = 1, - IPV4_PKT_NO_CHKSUM_OFFLOAD = 2, - IPV4_PKT_WITH_CHKSUM_OFFLOAD = 3, -}; - -enum sq_l4offload_type { - OFFLOAD_DISABLE = 0, - TCP_OFFLOAD_ENABLE = 1, - SCTP_OFFLOAD_ENABLE = 2, - UDP_OFFLOAD_ENABLE = 3, -}; - -/*initialize l4_len and offset*/ -static inline void get_inner_l4_info(struct sk_buff *skb, union spnic_l4 *l4, - u8 l4_proto, u32 *offset, - enum sq_l4offload_type *l4_offload) -{ - switch (l4_proto) { - case IPPROTO_TCP: - *l4_offload = TCP_OFFLOAD_ENABLE; - /* To keep same with TSO, payload offset begins from paylaod */ - *offset = (l4->tcp->doff << 2) + TRANSPORT_OFFSET(l4->hdr, skb); - break; - - case IPPROTO_UDP: - *l4_offload = UDP_OFFLOAD_ENABLE; - *offset = TRANSPORT_OFFSET(l4->hdr, skb); - break; - default: - break; - } -} - -static int spnic_tx_csum(struct spnic_txq *txq, struct spnic_sq_task *task, struct sk_buff *skb) -{ - if (skb->ip_summed != CHECKSUM_PARTIAL) - return 0; - - if (skb->encapsulation) { - union spnic_ip ip; - u8 l4_proto; - - task->pkt_info0 |= SQ_TASK_INFO0_SET(1U, TUNNEL_FLAG); - - ip.hdr = skb_network_header(skb); - if (ip.v4->version == IPV4_VERSION) { - l4_proto = ip.v4->protocol; - } else if (ip.v4->version == IPV6_VERSION) { - union spnic_l4 l4; - unsigned char *exthdr; - __be16 frag_off; - - exthdr = ip.hdr + sizeof(*ip.v6); - l4_proto = ip.v6->nexthdr; - l4.hdr = skb_transport_header(skb); - if (l4.hdr != exthdr) - ipv6_skip_exthdr(skb, exthdr - skb->data, &l4_proto, &frag_off); - } else { - l4_proto = IPPROTO_RAW; - } - - if (l4_proto != IPPROTO_UDP || - ((struct udphdr *)skb_transport_header(skb))->dest != VXLAN_OFFLOAD_PORT_BE) { - TXQ_STATS_INC(txq, unknown_tunnel_pkt); - /* Unsupport tunnel packet, disable csum offload */ - skb_checksum_help(skb); - return 0; - } - } - - task->pkt_info0 |= SQ_TASK_INFO0_SET(1U, INNER_L4_EN); - - return 1; -} - -static void get_inner_l3_l4_type(struct sk_buff *skb, union spnic_ip *ip, - union spnic_l4 *l4, enum sq_l3_type *l3_type, u8 *l4_proto) -{ - unsigned char *exthdr = NULL; - - if (ip->v4->version == 4) { - *l3_type = IPV4_PKT_WITH_CHKSUM_OFFLOAD; - *l4_proto = ip->v4->protocol; - - } else if (ip->v4->version == 6) { - *l3_type = IPV6_PKT; - exthdr = ip->hdr + sizeof(*ip->v6); - *l4_proto = ip->v6->nexthdr; - if (exthdr != l4->hdr) { - __be16 frag_off = 0; - - ipv6_skip_exthdr(skb, (int)(exthdr - skb->data), l4_proto, &frag_off); - } - } else { - *l3_type = UNKNOWN_L3TYPE; - *l4_proto = 0; - } -} - -static inline void spnic_set_tso_info(struct spnic_sq_task *task, u32 *queue_info, - enum sq_l4offload_type l4_offload, u32 offset, u32 mss) -{ - if (l4_offload == TCP_OFFLOAD_ENABLE) { - *queue_info |= SQ_CTRL_QUEUE_INFO_SET(1U, TSO); - task->pkt_info0 |= SQ_TASK_INFO0_SET(1U, INNER_L4_EN); - } else if (l4_offload == UDP_OFFLOAD_ENABLE) { - *queue_info |= SQ_CTRL_QUEUE_INFO_SET(1U, UFO); - task->pkt_info0 |= SQ_TASK_INFO0_SET(1U, INNER_L4_EN); - } - - /*Default enable L3 calculation*/ - task->pkt_info0 |= SQ_TASK_INFO0_SET(1U, INNER_L3_EN); - - *queue_info |= SQ_CTRL_QUEUE_INFO_SET(offset >> 1, PLDOFF); - - /* set MSS value */ - *queue_info = SQ_CTRL_QUEUE_INFO_CLEAR(*queue_info, MSS); - *queue_info |= SQ_CTRL_QUEUE_INFO_SET(mss, MSS); -} - -static int spnic_tso(struct spnic_sq_task *task, u32 *queue_info, struct sk_buff *skb) -{ - enum sq_l4offload_type l4_offload = OFFLOAD_DISABLE; - enum sq_l3_type l3_type; - union spnic_ip ip; - union spnic_l4 l4; - u32 offset = 0; - u8 l4_proto; - int err; - - if (!skb_is_gso(skb)) - return 0; - - err = skb_cow_head(skb, 0); - if (err < 0) - return err; - - if (skb->encapsulation) { - u32 gso_type = skb_shinfo(skb)->gso_type; - /* L3 checksum always enable */ - task->pkt_info0 |= SQ_TASK_INFO0_SET(1U, OUT_L3_EN); - task->pkt_info0 |= SQ_TASK_INFO0_SET(1U, TUNNEL_FLAG); - - l4.hdr = skb_transport_header(skb); - ip.hdr = skb_network_header(skb); - - if (gso_type & SKB_GSO_UDP_TUNNEL_CSUM) { - l4.udp->check = ~csum_magic(&ip, IPPROTO_UDP); - task->pkt_info0 |= SQ_TASK_INFO0_SET(1U, OUT_L4_EN); - } else if (gso_type & SKB_GSO_UDP_TUNNEL) { - } - - ip.hdr = skb_inner_network_header(skb); - l4.hdr = skb_inner_transport_header(skb); - } else { - ip.hdr = skb_network_header(skb); - l4.hdr = skb_transport_header(skb); - } - - get_inner_l3_l4_type(skb, &ip, &l4, &l3_type, &l4_proto); - - if (l4_proto == IPPROTO_TCP) - l4.tcp->check = ~csum_magic(&ip, IPPROTO_TCP); - - get_inner_l4_info(skb, &l4, l4_proto, &offset, &l4_offload); - - spnic_set_tso_info(task, queue_info, l4_offload, offset, skb_shinfo(skb)->gso_size); - - return 1; -} - -static u32 spnic_tx_offload(struct sk_buff *skb, struct spnic_sq_task *task, - u32 *queue_info, struct spnic_txq *txq) -{ - u32 offload = 0; - int tso_cs_en; - - task->pkt_info0 = 0; - task->ip_identify = 0; - task->pkt_info2 = 0; - task->vlan_offload = 0; - - tso_cs_en = spnic_tso(task, queue_info, skb); - if (tso_cs_en < 0) { - offload = TX_OFFLOAD_INVALID; - return offload; - } else if (tso_cs_en) { - offload |= TX_OFFLOAD_TSO; - } else { - tso_cs_en = spnic_tx_csum(txq, task, skb); - if (tso_cs_en) - offload |= TX_OFFLOAD_CSUM; - } - -#define VLAN_INSERT_MODE_MAX 5 - if (unlikely(skb_vlan_tag_present(skb))) { - /* select vlan insert mode by qid, default 802.1Q Tag type*/ - spnic_set_vlan_tx_offload(task, skb_vlan_tag_get(skb), - txq->q_id % VLAN_INSERT_MODE_MAX); - offload |= TX_OFFLOAD_VLAN; - } - - if (unlikely(SQ_CTRL_QUEUE_INFO_GET(*queue_info, PLDOFF) > MAX_PAYLOAD_OFFSET)) { - offload = TX_OFFLOAD_INVALID; - return offload; - } - - return offload; -} - -static inline void get_pkt_stats(struct spnic_tx_info *tx_info, struct sk_buff *skb) -{ - u32 ihs, hdr_len; - - if (skb_is_gso(skb)) { - if (skb->encapsulation) - ihs = skb_inner_transport_offset(skb) + inner_tcp_hdrlen(skb); - else - ihs = skb_transport_offset(skb) + tcp_hdrlen(skb); - - hdr_len = (skb_shinfo(skb)->gso_segs - 1) * ihs; - tx_info->num_bytes = skb->len + (u64)hdr_len; - - } else { - tx_info->num_bytes = skb->len > ETH_ZLEN ? skb->len : ETH_ZLEN; - } - - tx_info->num_pkts = 1; -} - -static inline int spnic_maybe_stop_tx(struct spnic_txq *txq, u16 wqebb_cnt) -{ - if (likely(spnic_get_sq_free_wqebbs(txq->sq) >= wqebb_cnt)) - return 0; - - /* We need to check again in a case another CPU has just - * made room available. - */ - netif_stop_subqueue(txq->netdev, txq->q_id); - - if (likely(spnic_get_sq_free_wqebbs(txq->sq) < wqebb_cnt)) - return -EBUSY; - - /* there have enough wqebbs after queue is wake up */ - netif_start_subqueue(txq->netdev, txq->q_id); - - return 0; -} - -static inline u16 spnic_set_wqe_combo(struct spnic_txq *txq, struct spnic_sq_wqe_combo *wqe_combo, - u32 offload, u16 num_sge, u16 *curr_pi) -{ - void *second_part_wqebbs_addr = NULL; - void *wqe = NULL; - u16 first_part_wqebbs_num, tmp_pi; - - wqe_combo->ctrl_bd0 = spnic_get_sq_one_wqebb(txq->sq, curr_pi); - if (!offload && num_sge == 1) { - wqe_combo->wqe_type = SQ_WQE_COMPACT_TYPE; - return spnic_get_and_update_sq_owner(txq->sq, *curr_pi, 1); - } - - wqe_combo->wqe_type = SQ_WQE_EXTENDED_TYPE; - - if (offload) { - wqe_combo->task = spnic_get_sq_one_wqebb(txq->sq, &tmp_pi); - wqe_combo->task_type = SQ_WQE_TASKSECT_16BYTES; - } else { - wqe_combo->task_type = SQ_WQE_TASKSECT_46BITS; - } - - if (num_sge > 1) { - /* first wqebb contain bd0, and bd size is equal to sq wqebb - * size, so we use (num_sge - 1) as wanted weqbb_cnt - */ - wqe = spnic_get_sq_multi_wqebbs(txq->sq, num_sge - 1, &tmp_pi, - &second_part_wqebbs_addr, - &first_part_wqebbs_num); - wqe_combo->bds_head = wqe; - wqe_combo->bds_sec2 = second_part_wqebbs_addr; - wqe_combo->first_bds_num = first_part_wqebbs_num; - } - - return spnic_get_and_update_sq_owner(txq->sq, *curr_pi, num_sge + (u16)!!offload); -} - -inline u8 spnic_get_vlan_pri(struct sk_buff *skb) -{ - u16 vlan_tci = 0; - int err; - - err = vlan_get_tag(skb, &vlan_tci); - if (err) - return 0; - - return (vlan_tci & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT; -} - -static netdev_tx_t spnic_send_one_skb(struct sk_buff *skb, struct net_device *netdev, - struct spnic_txq *txq) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - struct spnic_sq_wqe_combo wqe_combo = {0}; - struct spnic_tx_info *tx_info = NULL; - struct spnic_sq_task task; - u32 offload, queue_info = 0; - u16 owner = 0, pi = 0; - u16 wqebb_cnt, num_sge, valid_nr_frags; - bool find_zero_sge_len = false; - int err, i; - - if (unlikely(skb->len < MIN_SKB_LEN)) { - if (skb_pad(skb, (int)(MIN_SKB_LEN - skb->len))) { - TXQ_STATS_INC(txq, skb_pad_err); - goto tx_skb_pad_err; - } - - skb->len = MIN_SKB_LEN; - } - - valid_nr_frags = 0; - for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - if (!skb_frag_size(&skb_shinfo(skb)->frags[i])) { - find_zero_sge_len = true; - continue; - } else if (find_zero_sge_len) { - TXQ_STATS_INC(txq, frag_size_err); - goto tx_drop_pkts; - } - - valid_nr_frags++; - } - - num_sge = valid_nr_frags + 1; - - /* assume need normal TS format wqe, task info need 1 wqebb */ - wqebb_cnt = num_sge + 1; - if (unlikely(spnic_maybe_stop_tx(txq, wqebb_cnt))) { - TXQ_STATS_INC(txq, busy); - return NETDEV_TX_BUSY; - } - - offload = spnic_tx_offload(skb, &task, &queue_info, txq); - if (unlikely(offload == TX_OFFLOAD_INVALID)) { - TXQ_STATS_INC(txq, offload_cow_skb_err); - goto tx_drop_pkts; - } else if (!offload) { - /* no TS in current wqe */ - wqebb_cnt -= 1; - } - - owner = spnic_set_wqe_combo(txq, &wqe_combo, offload, num_sge, &pi); - if (offload) { - wqe_combo.task->ip_identify = task.ip_identify; - wqe_combo.task->pkt_info0 = task.pkt_info0; - wqe_combo.task->pkt_info2 = task.pkt_info2; - wqe_combo.task->vlan_offload = task.vlan_offload; - } - - tx_info = &txq->tx_info[pi]; - tx_info->skb = skb; - tx_info->wqebb_cnt = wqebb_cnt; - tx_info->valid_nr_frags = valid_nr_frags; - - err = tx_map_skb(nic_dev, skb, valid_nr_frags, txq, tx_info, &wqe_combo); - if (err) { - spnic_rollback_sq_wqebbs(txq->sq, wqebb_cnt, owner); - goto tx_drop_pkts; - } - - get_pkt_stats(tx_info, skb); - - spnic_prepare_sq_ctrl(&wqe_combo, queue_info, num_sge, owner); - - spnic_write_db(txq->sq, txq->cos, SQ_CFLAG_DP, spnic_get_sq_local_pi(txq->sq)); - - return NETDEV_TX_OK; - -tx_drop_pkts: - dev_kfree_skb_any(skb); - -tx_skb_pad_err: - TXQ_STATS_INC(txq, dropped); - - return NETDEV_TX_OK; -} - -netdev_tx_t spnic_lb_xmit_frame(struct sk_buff *skb, struct net_device *netdev) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - u16 q_id = skb_get_queue_mapping(skb); - struct spnic_txq *txq = &nic_dev->txqs[q_id]; - - return spnic_send_one_skb(skb, netdev, txq); -} - -netdev_tx_t spnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - struct spnic_txq *txq = NULL; - u16 q_id = skb_get_queue_mapping(skb); - - if (unlikely(!netif_carrier_ok(netdev))) { - dev_kfree_skb_any(skb); - SPNIC_NIC_STATS_INC(nic_dev, tx_carrier_off_drop); - return NETDEV_TX_OK; - } - - if (unlikely(q_id >= nic_dev->q_params.num_qps)) { - txq = &nic_dev->txqs[0]; - SPNIC_NIC_STATS_INC(nic_dev, tx_invalid_qid); - goto tx_drop_pkts; - } - txq = &nic_dev->txqs[q_id]; - - return spnic_send_one_skb(skb, netdev, txq); - -tx_drop_pkts: - dev_kfree_skb_any(skb); - u64_stats_update_begin(&txq->txq_stats.syncp); - txq->txq_stats.dropped++; - u64_stats_update_end(&txq->txq_stats.syncp); - - return NETDEV_TX_OK; -} - -static inline void tx_free_skb(struct spnic_nic_dev *nic_dev, struct spnic_tx_info *tx_info) -{ - tx_unmap_skb(nic_dev, tx_info->skb, tx_info->valid_nr_frags, - tx_info->dma_info); - dev_kfree_skb_any(tx_info->skb); - tx_info->skb = NULL; -} - -static void free_all_tx_skbs(struct spnic_nic_dev *nic_dev, u32 sq_depth, - struct spnic_tx_info *tx_info_arr) -{ - struct spnic_tx_info *tx_info = NULL; - u32 idx; - - for (idx = 0; idx < sq_depth; idx++) { - tx_info = &tx_info_arr[idx]; - if (tx_info->skb) - tx_free_skb(nic_dev, tx_info); - } -} - -int spnic_tx_poll(struct spnic_txq *txq, int budget) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(txq->netdev); - struct spnic_tx_info *tx_info = NULL; - u64 tx_bytes = 0, wake = 0; - int pkts = 0, nr_pkts = 0; - u16 wqebb_cnt = 0; - u16 hw_ci, sw_ci = 0, q_id = txq->sq->q_id; - - hw_ci = spnic_get_sq_hw_ci(txq->sq); - dma_rmb(); - sw_ci = spnic_get_sq_local_ci(txq->sq); - - do { - tx_info = &txq->tx_info[sw_ci]; - - /* Whether all of the wqebb of this wqe is completed */ - if (hw_ci == sw_ci || - ((hw_ci - sw_ci) & txq->q_mask) < tx_info->wqebb_cnt) - break; - - sw_ci = (u16)(sw_ci + tx_info->wqebb_cnt) & txq->q_mask; - prefetch(&txq->tx_info[sw_ci]); - - wqebb_cnt += tx_info->wqebb_cnt; - - tx_bytes += tx_info->num_bytes; - nr_pkts += tx_info->num_pkts; - pkts++; - - tx_free_skb(nic_dev, tx_info); - - } while (likely(pkts < budget)); - - spnic_update_sq_local_ci(txq->sq, wqebb_cnt); - - if (unlikely(__netif_subqueue_stopped(nic_dev->netdev, q_id) && - spnic_get_sq_free_wqebbs(txq->sq) >= 1 && - test_bit(SPNIC_INTF_UP, &nic_dev->flags))) { - struct netdev_queue *netdev_txq = netdev_get_tx_queue(txq->netdev, q_id); - - __netif_tx_lock(netdev_txq, smp_processor_id()); - /* To avoid re-waking subqueue with xmit_frame */ - if (__netif_subqueue_stopped(nic_dev->netdev, q_id)) { - netif_wake_subqueue(nic_dev->netdev, q_id); - wake++; - } - __netif_tx_unlock(netdev_txq); - } - - u64_stats_update_begin(&txq->txq_stats.syncp); - txq->txq_stats.bytes += tx_bytes; - txq->txq_stats.packets += nr_pkts; - txq->txq_stats.wake += wake; - u64_stats_update_end(&txq->txq_stats.syncp); - - return pkts; -} - -void spnic_set_txq_cos(struct spnic_nic_dev *nic_dev, u16 start_qid, u16 q_num, u8 cos) -{ - u16 idx; - - for (idx = 0; idx < q_num; idx++) - nic_dev->txqs[idx + start_qid].cos = cos; -} - -#define SPNIC_BDS_PER_SQ_WQEBB \ - (SPNIC_SQ_WQEBB_SIZE / sizeof(struct spnic_sq_bufdesc)) - -int spnic_alloc_txqs_res(struct spnic_nic_dev *nic_dev, u16 num_sq, - u32 sq_depth, struct spnic_dyna_txq_res *txqs_res) -{ - struct spnic_dyna_txq_res *tqres = NULL; - int idx, i; - u64 size; - - for (idx = 0; idx < num_sq; idx++) { - tqres = &txqs_res[idx]; - - size = sizeof(*tqres->tx_info) * sq_depth; - tqres->tx_info = kzalloc(size, GFP_KERNEL); - if (!tqres->tx_info) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Failed to alloc txq%d tx info\n", idx); - goto err_out; - } - - size = sizeof(*tqres->bds) * (sq_depth * SPNIC_BDS_PER_SQ_WQEBB + SPNIC_MAX_SQ_SGE); - tqres->bds = kzalloc(size, GFP_KERNEL); - if (!tqres->bds) { - kfree(tqres->tx_info); - nicif_err(nic_dev, drv, nic_dev->netdev, - "Failed to alloc txq%d bds info\n", idx); - goto err_out; - } - } - - return 0; - -err_out: - for (i = 0; i < idx; i++) { - tqres = &txqs_res[i]; - - kfree(tqres->bds); - kfree(tqres->tx_info); - } - - return -ENOMEM; -} - -void spnic_free_txqs_res(struct spnic_nic_dev *nic_dev, u16 num_sq, - u32 sq_depth, struct spnic_dyna_txq_res *txqs_res) -{ - struct spnic_dyna_txq_res *tqres = NULL; - int idx; - - for (idx = 0; idx < num_sq; idx++) { - tqres = &txqs_res[idx]; - - free_all_tx_skbs(nic_dev, sq_depth, tqres->tx_info); - kfree(tqres->bds); - kfree(tqres->tx_info); - } -} - -int spnic_configure_txqs(struct spnic_nic_dev *nic_dev, u16 num_sq, - u32 sq_depth, struct spnic_dyna_txq_res *txqs_res) -{ - struct spnic_dyna_txq_res *tqres = NULL; - struct spnic_txq *txq = NULL; - u16 q_id; - u32 idx; - - for (q_id = 0; q_id < num_sq; q_id++) { - txq = &nic_dev->txqs[q_id]; - tqres = &txqs_res[q_id]; - - txq->q_depth = sq_depth; - txq->q_mask = sq_depth - 1; - - txq->tx_info = tqres->tx_info; - for (idx = 0; idx < sq_depth; idx++) - txq->tx_info[idx].dma_info = &tqres->bds[idx * SPNIC_BDS_PER_SQ_WQEBB]; - - txq->sq = spnic_get_nic_queue(nic_dev->hwdev, q_id, SPNIC_SQ); - if (!txq->sq) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to get %u sq\n", q_id); - return -EFAULT; - } - } - - return 0; -} - -int spnic_alloc_txqs(struct net_device *netdev) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - struct pci_dev *pdev = nic_dev->pdev; - struct spnic_txq *txq = NULL; - u16 q_id, num_txqs = nic_dev->max_qps; - u64 txq_size; - - txq_size = num_txqs * sizeof(*nic_dev->txqs); - if (!txq_size) { - nic_err(&pdev->dev, "Cannot allocate zero size txqs\n"); - return -EINVAL; - } - - nic_dev->txqs = kzalloc(txq_size, GFP_KERNEL); - if (!nic_dev->txqs) { - nic_err(&pdev->dev, "Failed to allocate txqs\n"); - return -ENOMEM; - } - - for (q_id = 0; q_id < num_txqs; q_id++) { - txq = &nic_dev->txqs[q_id]; - txq->netdev = netdev; - txq->q_id = q_id; - txq->q_depth = nic_dev->q_params.sq_depth; - txq->q_mask = nic_dev->q_params.sq_depth - 1; - txq->dev = &pdev->dev; - - txq_stats_init(txq); - } - - return 0; -} - -void spnic_free_txqs(struct net_device *netdev) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - - kfree(nic_dev->txqs); -} - -static bool is_hw_complete_sq_process(struct spnic_io_queue *sq) -{ - u16 sw_pi, hw_ci; - - sw_pi = spnic_get_sq_local_pi(sq); - hw_ci = spnic_get_sq_hw_ci(sq); - - return sw_pi == hw_ci; -} - -#define SPNIC_FLUSH_QUEUE_TIMEOUT 1000 -static int spnic_stop_sq(struct spnic_txq *txq) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(txq->netdev); - unsigned long timeout; - int err; - - timeout = msecs_to_jiffies(SPNIC_FLUSH_QUEUE_TIMEOUT) + jiffies; - do { - if (is_hw_complete_sq_process(txq->sq)) - return 0; - - usleep_range(900, 1000); - } while (time_before(jiffies, timeout)); - - /* force hardware to drop packets */ - timeout = msecs_to_jiffies(SPNIC_FLUSH_QUEUE_TIMEOUT) + jiffies; - do { - if (is_hw_complete_sq_process(txq->sq)) - return 0; - - err = spnic_force_drop_tx_pkt(nic_dev->hwdev); - if (err) - break; - - usleep_range(9900, 10000); - } while (time_before(jiffies, timeout)); - - /* Avoid msleep takes too long and get a fake result */ - if (is_hw_complete_sq_process(txq->sq)) - return 0; - - return -EFAULT; -} - -/* should stop transmit any packets before calling this function */ -int spnic_flush_txqs(struct net_device *netdev) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - u16 qid; - int err; - - for (qid = 0; qid < nic_dev->q_params.num_qps; qid++) { - err = spnic_stop_sq(&nic_dev->txqs[qid]); - if (err) - nicif_err(nic_dev, drv, netdev, "Failed to stop sq%u\n", qid); - } - - return 0; -} diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_tx.h b/drivers/net/ethernet/ramaxel/spnic/spnic_tx.h deleted file mode 100644 index c3109db83299..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_tx.h +++ /dev/null @@ -1,129 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPNIC_TX_H -#define SPNIC_TX_H - -#include <linux/ip.h> -#include <linux/ipv6.h> -#include <net/ipv6.h> -#include <net/checksum.h> -#include <net/ip6_checksum.h> - -#include "spnic_nic_qp.h" - -#define VXLAN_OFFLOAD_PORT_BE htons(4789) - -enum tx_offload_type { - TX_OFFLOAD_TSO = BIT(0), - TX_OFFLOAD_CSUM = BIT(1), - TX_OFFLOAD_VLAN = BIT(2), - TX_OFFLOAD_INVALID = BIT(3), - TX_OFFLOAD_ESP = BIT(4), -}; - -struct spnic_txq_stats { - u64 packets; - u64 bytes; - u64 busy; - u64 wake; - u64 dropped; - - /* Subdivision statistics show in private tool */ - u64 skb_pad_err; - u64 frag_len_overflow; - u64 offload_cow_skb_err; - u64 map_frag_err; - u64 unknown_tunnel_pkt; - u64 frag_size_err; - - struct u64_stats_sync syncp; -}; - -struct spnic_dma_info { - dma_addr_t dma; - u32 len; -}; - -#define IPV4_VERSION 4 -#define IPV6_VERSION 6 -#define TCP_HDR_DOFF_UNIT 2 -#define TRANSPORT_OFFSET(l4_hdr, skb) ((u32)((l4_hdr) - (skb)->data)) - -union spnic_ip { - struct iphdr *v4; - struct ipv6hdr *v6; - unsigned char *hdr; -}; - -struct spnic_tx_info { - struct sk_buff *skb; - - u16 wqebb_cnt; - u16 valid_nr_frags; - - int num_sge; - u16 num_pkts; - u64 num_bytes; - struct spnic_dma_info *dma_info; -}; - -struct spnic_txq { - struct net_device *netdev; - struct device *dev; - - struct spnic_txq_stats txq_stats; - - u8 cos; - u16 q_id; - u32 q_mask; - u32 q_depth; - - struct spnic_tx_info *tx_info; - struct spnic_io_queue *sq; - - u64 last_moder_packets; - u64 last_moder_bytes; -} ____cacheline_aligned; - -netdev_tx_t spnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev); - -netdev_tx_t spnic_lb_xmit_frame(struct sk_buff *skb, struct net_device *netdev); - -struct spnic_dyna_txq_res { - struct spnic_tx_info *tx_info; - struct spnic_dma_info *bds; -}; - -void spnic_txq_get_stats(struct spnic_txq *txq, struct spnic_txq_stats *stats); - -void spnic_txq_clean_stats(struct spnic_txq_stats *txq_stats); - -struct spnic_nic_dev; -int spnic_alloc_txqs_res(struct spnic_nic_dev *nic_dev, u16 num_sq, - u32 sq_depth, struct spnic_dyna_txq_res *txqs_res); - -void spnic_free_txqs_res(struct spnic_nic_dev *nic_dev, u16 num_sq, - u32 sq_depth, struct spnic_dyna_txq_res *txqs_res); - -int spnic_configure_txqs(struct spnic_nic_dev *nic_dev, u16 num_sq, - u32 sq_depth, struct spnic_dyna_txq_res *txqs_res); - -int spnic_alloc_txqs(struct net_device *netdev); - -void spnic_free_txqs(struct net_device *netdev); - -int spnic_tx_poll(struct spnic_txq *txq, int budget); - -int spnic_flush_txqs(struct net_device *netdev); - -void spnic_set_txq_cos(struct spnic_nic_dev *nic_dev, u16 start_qid, u16 q_num, u8 cos); - -static inline __sum16 csum_magic(union spnic_ip *ip, unsigned short proto) -{ - return (ip->v4->version == IPV4_VERSION) ? - csum_tcpudp_magic(ip->v4->saddr, ip->v4->daddr, 0, proto, 0) : - csum_ipv6_magic(&ip->v6->saddr, &ip->v6->daddr, 0, proto, 0); -} - -#endif