18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) 28c2ecf20Sopenharmony_ci/* QLogic qed NIC Driver 38c2ecf20Sopenharmony_ci * Copyright (c) 2015-2017 QLogic Corporation 48c2ecf20Sopenharmony_ci * Copyright (c) 2019-2020 Marvell International Ltd. 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include <linux/types.h> 88c2ecf20Sopenharmony_ci#include <asm/byteorder.h> 98c2ecf20Sopenharmony_ci#include <asm/param.h> 108c2ecf20Sopenharmony_ci#include <linux/delay.h> 118c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h> 128c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 138c2ecf20Sopenharmony_ci#include <linux/kernel.h> 148c2ecf20Sopenharmony_ci#include <linux/log2.h> 158c2ecf20Sopenharmony_ci#include <linux/module.h> 168c2ecf20Sopenharmony_ci#include <linux/pci.h> 178c2ecf20Sopenharmony_ci#include <linux/slab.h> 188c2ecf20Sopenharmony_ci#include <linux/stddef.h> 198c2ecf20Sopenharmony_ci#include <linux/string.h> 208c2ecf20Sopenharmony_ci#include <linux/workqueue.h> 218c2ecf20Sopenharmony_ci#include <linux/errno.h> 228c2ecf20Sopenharmony_ci#include <linux/list.h> 238c2ecf20Sopenharmony_ci#include <linux/spinlock.h> 248c2ecf20Sopenharmony_ci#define __PREVENT_DUMP_MEM_ARR__ 258c2ecf20Sopenharmony_ci#define __PREVENT_PXP_GLOBAL_WIN__ 268c2ecf20Sopenharmony_ci#include "qed.h" 278c2ecf20Sopenharmony_ci#include "qed_cxt.h" 288c2ecf20Sopenharmony_ci#include "qed_dev_api.h" 298c2ecf20Sopenharmony_ci#include "qed_fcoe.h" 308c2ecf20Sopenharmony_ci#include "qed_hsi.h" 318c2ecf20Sopenharmony_ci#include "qed_hw.h" 328c2ecf20Sopenharmony_ci#include "qed_int.h" 338c2ecf20Sopenharmony_ci#include "qed_ll2.h" 348c2ecf20Sopenharmony_ci#include "qed_mcp.h" 358c2ecf20Sopenharmony_ci#include "qed_reg_addr.h" 368c2ecf20Sopenharmony_ci#include "qed_sp.h" 378c2ecf20Sopenharmony_ci#include "qed_sriov.h" 388c2ecf20Sopenharmony_ci#include <linux/qed/qed_fcoe_if.h> 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_cistruct qed_fcoe_conn { 418c2ecf20Sopenharmony_ci struct list_head list_entry; 428c2ecf20Sopenharmony_ci bool free_on_delete; 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci u16 conn_id; 458c2ecf20Sopenharmony_ci u32 icid; 468c2ecf20Sopenharmony_ci u32 fw_cid; 478c2ecf20Sopenharmony_ci u8 layer_code; 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci dma_addr_t sq_pbl_addr; 508c2ecf20Sopenharmony_ci dma_addr_t sq_curr_page_addr; 518c2ecf20Sopenharmony_ci dma_addr_t sq_next_page_addr; 528c2ecf20Sopenharmony_ci dma_addr_t xferq_pbl_addr; 538c2ecf20Sopenharmony_ci void *xferq_pbl_addr_virt_addr; 548c2ecf20Sopenharmony_ci dma_addr_t xferq_addr[4]; 558c2ecf20Sopenharmony_ci void *xferq_addr_virt_addr[4]; 568c2ecf20Sopenharmony_ci dma_addr_t confq_pbl_addr; 578c2ecf20Sopenharmony_ci void *confq_pbl_addr_virt_addr; 588c2ecf20Sopenharmony_ci dma_addr_t confq_addr[2]; 598c2ecf20Sopenharmony_ci void *confq_addr_virt_addr[2]; 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci dma_addr_t terminate_params; 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci u16 dst_mac_addr_lo; 648c2ecf20Sopenharmony_ci u16 dst_mac_addr_mid; 658c2ecf20Sopenharmony_ci u16 dst_mac_addr_hi; 668c2ecf20Sopenharmony_ci u16 src_mac_addr_lo; 678c2ecf20Sopenharmony_ci u16 src_mac_addr_mid; 688c2ecf20Sopenharmony_ci u16 src_mac_addr_hi; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci u16 tx_max_fc_pay_len; 718c2ecf20Sopenharmony_ci u16 e_d_tov_timer_val; 728c2ecf20Sopenharmony_ci u16 rec_tov_timer_val; 738c2ecf20Sopenharmony_ci u16 rx_max_fc_pay_len; 748c2ecf20Sopenharmony_ci u16 vlan_tag; 758c2ecf20Sopenharmony_ci u16 physical_q0; 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci struct fc_addr_nw s_id; 788c2ecf20Sopenharmony_ci u8 max_conc_seqs_c3; 798c2ecf20Sopenharmony_ci struct fc_addr_nw d_id; 808c2ecf20Sopenharmony_ci u8 flags; 818c2ecf20Sopenharmony_ci u8 def_q_idx; 828c2ecf20Sopenharmony_ci}; 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_cistatic int 858c2ecf20Sopenharmony_ciqed_sp_fcoe_func_start(struct qed_hwfn *p_hwfn, 868c2ecf20Sopenharmony_ci enum spq_mode comp_mode, 878c2ecf20Sopenharmony_ci struct qed_spq_comp_cb *p_comp_addr) 888c2ecf20Sopenharmony_ci{ 898c2ecf20Sopenharmony_ci struct qed_fcoe_pf_params *fcoe_pf_params = NULL; 908c2ecf20Sopenharmony_ci struct fcoe_init_ramrod_params *p_ramrod = NULL; 918c2ecf20Sopenharmony_ci struct fcoe_init_func_ramrod_data *p_data; 928c2ecf20Sopenharmony_ci struct e4_fcoe_conn_context *p_cxt = NULL; 938c2ecf20Sopenharmony_ci struct qed_spq_entry *p_ent = NULL; 948c2ecf20Sopenharmony_ci struct qed_sp_init_data init_data; 958c2ecf20Sopenharmony_ci struct qed_cxt_info cxt_info; 968c2ecf20Sopenharmony_ci u32 dummy_cid; 978c2ecf20Sopenharmony_ci int rc = 0; 988c2ecf20Sopenharmony_ci __le16 tmp; 998c2ecf20Sopenharmony_ci u8 i; 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci /* Get SPQ entry */ 1028c2ecf20Sopenharmony_ci memset(&init_data, 0, sizeof(init_data)); 1038c2ecf20Sopenharmony_ci init_data.cid = qed_spq_get_cid(p_hwfn); 1048c2ecf20Sopenharmony_ci init_data.opaque_fid = p_hwfn->hw_info.opaque_fid; 1058c2ecf20Sopenharmony_ci init_data.comp_mode = comp_mode; 1068c2ecf20Sopenharmony_ci init_data.p_comp_data = p_comp_addr; 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci rc = qed_sp_init_request(p_hwfn, &p_ent, 1098c2ecf20Sopenharmony_ci FCOE_RAMROD_CMD_ID_INIT_FUNC, 1108c2ecf20Sopenharmony_ci PROTOCOLID_FCOE, &init_data); 1118c2ecf20Sopenharmony_ci if (rc) 1128c2ecf20Sopenharmony_ci return rc; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci p_ramrod = &p_ent->ramrod.fcoe_init; 1158c2ecf20Sopenharmony_ci p_data = &p_ramrod->init_ramrod_data; 1168c2ecf20Sopenharmony_ci fcoe_pf_params = &p_hwfn->pf_params.fcoe_pf_params; 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci /* Sanity */ 1198c2ecf20Sopenharmony_ci if (fcoe_pf_params->num_cqs > p_hwfn->hw_info.feat_num[QED_FCOE_CQ]) { 1208c2ecf20Sopenharmony_ci DP_ERR(p_hwfn, 1218c2ecf20Sopenharmony_ci "Cannot satisfy CQ amount. CQs requested %d, CQs available %d. Aborting function start\n", 1228c2ecf20Sopenharmony_ci fcoe_pf_params->num_cqs, 1238c2ecf20Sopenharmony_ci p_hwfn->hw_info.feat_num[QED_FCOE_CQ]); 1248c2ecf20Sopenharmony_ci rc = -EINVAL; 1258c2ecf20Sopenharmony_ci goto err; 1268c2ecf20Sopenharmony_ci } 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci p_data->mtu = cpu_to_le16(fcoe_pf_params->mtu); 1298c2ecf20Sopenharmony_ci tmp = cpu_to_le16(fcoe_pf_params->sq_num_pbl_pages); 1308c2ecf20Sopenharmony_ci p_data->sq_num_pages_in_pbl = tmp; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci rc = qed_cxt_acquire_cid(p_hwfn, PROTOCOLID_FCOE, &dummy_cid); 1338c2ecf20Sopenharmony_ci if (rc) 1348c2ecf20Sopenharmony_ci goto err; 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci cxt_info.iid = dummy_cid; 1378c2ecf20Sopenharmony_ci rc = qed_cxt_get_cid_info(p_hwfn, &cxt_info); 1388c2ecf20Sopenharmony_ci if (rc) { 1398c2ecf20Sopenharmony_ci DP_NOTICE(p_hwfn, "Cannot find context info for dummy cid=%d\n", 1408c2ecf20Sopenharmony_ci dummy_cid); 1418c2ecf20Sopenharmony_ci goto err; 1428c2ecf20Sopenharmony_ci } 1438c2ecf20Sopenharmony_ci p_cxt = cxt_info.p_cxt; 1448c2ecf20Sopenharmony_ci memset(p_cxt, 0, sizeof(*p_cxt)); 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci SET_FIELD(p_cxt->tstorm_ag_context.flags3, 1478c2ecf20Sopenharmony_ci E4_TSTORM_FCOE_CONN_AG_CTX_DUMMY_TIMER_CF_EN, 1); 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci fcoe_pf_params->dummy_icid = (u16)dummy_cid; 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci tmp = cpu_to_le16(fcoe_pf_params->num_tasks); 1528c2ecf20Sopenharmony_ci p_data->func_params.num_tasks = tmp; 1538c2ecf20Sopenharmony_ci p_data->func_params.log_page_size = fcoe_pf_params->log_page_size; 1548c2ecf20Sopenharmony_ci p_data->func_params.debug_mode = fcoe_pf_params->debug_mode; 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci DMA_REGPAIR_LE(p_data->q_params.glbl_q_params_addr, 1578c2ecf20Sopenharmony_ci fcoe_pf_params->glbl_q_params_addr); 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci tmp = cpu_to_le16(fcoe_pf_params->cq_num_entries); 1608c2ecf20Sopenharmony_ci p_data->q_params.cq_num_entries = tmp; 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci tmp = cpu_to_le16(fcoe_pf_params->cmdq_num_entries); 1638c2ecf20Sopenharmony_ci p_data->q_params.cmdq_num_entries = tmp; 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci p_data->q_params.num_queues = fcoe_pf_params->num_cqs; 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci tmp = (__force __le16)p_hwfn->hw_info.resc_start[QED_CMDQS_CQS]; 1688c2ecf20Sopenharmony_ci p_data->q_params.queue_relative_offset = (__force u8)tmp; 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci for (i = 0; i < fcoe_pf_params->num_cqs; i++) { 1718c2ecf20Sopenharmony_ci tmp = cpu_to_le16(qed_get_igu_sb_id(p_hwfn, i)); 1728c2ecf20Sopenharmony_ci p_data->q_params.cq_cmdq_sb_num_arr[i] = tmp; 1738c2ecf20Sopenharmony_ci } 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci p_data->q_params.cq_sb_pi = fcoe_pf_params->gl_rq_pi; 1768c2ecf20Sopenharmony_ci p_data->q_params.cmdq_sb_pi = fcoe_pf_params->gl_cmd_pi; 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci p_data->q_params.bdq_resource_id = (u8)RESC_START(p_hwfn, QED_BDQ); 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci DMA_REGPAIR_LE(p_data->q_params.bdq_pbl_base_address[BDQ_ID_RQ], 1818c2ecf20Sopenharmony_ci fcoe_pf_params->bdq_pbl_base_addr[BDQ_ID_RQ]); 1828c2ecf20Sopenharmony_ci p_data->q_params.bdq_pbl_num_entries[BDQ_ID_RQ] = 1838c2ecf20Sopenharmony_ci fcoe_pf_params->bdq_pbl_num_entries[BDQ_ID_RQ]; 1848c2ecf20Sopenharmony_ci tmp = cpu_to_le16(fcoe_pf_params->bdq_xoff_threshold[BDQ_ID_RQ]); 1858c2ecf20Sopenharmony_ci p_data->q_params.bdq_xoff_threshold[BDQ_ID_RQ] = tmp; 1868c2ecf20Sopenharmony_ci tmp = cpu_to_le16(fcoe_pf_params->bdq_xon_threshold[BDQ_ID_RQ]); 1878c2ecf20Sopenharmony_ci p_data->q_params.bdq_xon_threshold[BDQ_ID_RQ] = tmp; 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci DMA_REGPAIR_LE(p_data->q_params.bdq_pbl_base_address[BDQ_ID_IMM_DATA], 1908c2ecf20Sopenharmony_ci fcoe_pf_params->bdq_pbl_base_addr[BDQ_ID_IMM_DATA]); 1918c2ecf20Sopenharmony_ci p_data->q_params.bdq_pbl_num_entries[BDQ_ID_IMM_DATA] = 1928c2ecf20Sopenharmony_ci fcoe_pf_params->bdq_pbl_num_entries[BDQ_ID_IMM_DATA]; 1938c2ecf20Sopenharmony_ci tmp = cpu_to_le16(fcoe_pf_params->bdq_xoff_threshold[BDQ_ID_IMM_DATA]); 1948c2ecf20Sopenharmony_ci p_data->q_params.bdq_xoff_threshold[BDQ_ID_IMM_DATA] = tmp; 1958c2ecf20Sopenharmony_ci tmp = cpu_to_le16(fcoe_pf_params->bdq_xon_threshold[BDQ_ID_IMM_DATA]); 1968c2ecf20Sopenharmony_ci p_data->q_params.bdq_xon_threshold[BDQ_ID_IMM_DATA] = tmp; 1978c2ecf20Sopenharmony_ci tmp = cpu_to_le16(fcoe_pf_params->rq_buffer_size); 1988c2ecf20Sopenharmony_ci p_data->q_params.rq_buffer_size = tmp; 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci if (fcoe_pf_params->is_target) { 2018c2ecf20Sopenharmony_ci SET_FIELD(p_data->q_params.q_validity, 2028c2ecf20Sopenharmony_ci SCSI_INIT_FUNC_QUEUES_RQ_VALID, 1); 2038c2ecf20Sopenharmony_ci if (p_data->q_params.bdq_pbl_num_entries[BDQ_ID_IMM_DATA]) 2048c2ecf20Sopenharmony_ci SET_FIELD(p_data->q_params.q_validity, 2058c2ecf20Sopenharmony_ci SCSI_INIT_FUNC_QUEUES_IMM_DATA_VALID, 1); 2068c2ecf20Sopenharmony_ci SET_FIELD(p_data->q_params.q_validity, 2078c2ecf20Sopenharmony_ci SCSI_INIT_FUNC_QUEUES_CMD_VALID, 1); 2088c2ecf20Sopenharmony_ci } else { 2098c2ecf20Sopenharmony_ci SET_FIELD(p_data->q_params.q_validity, 2108c2ecf20Sopenharmony_ci SCSI_INIT_FUNC_QUEUES_RQ_VALID, 1); 2118c2ecf20Sopenharmony_ci } 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci rc = qed_spq_post(p_hwfn, p_ent, NULL); 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci return rc; 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_cierr: 2188c2ecf20Sopenharmony_ci qed_sp_destroy_request(p_hwfn, p_ent); 2198c2ecf20Sopenharmony_ci return rc; 2208c2ecf20Sopenharmony_ci} 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_cistatic int 2238c2ecf20Sopenharmony_ciqed_sp_fcoe_conn_offload(struct qed_hwfn *p_hwfn, 2248c2ecf20Sopenharmony_ci struct qed_fcoe_conn *p_conn, 2258c2ecf20Sopenharmony_ci enum spq_mode comp_mode, 2268c2ecf20Sopenharmony_ci struct qed_spq_comp_cb *p_comp_addr) 2278c2ecf20Sopenharmony_ci{ 2288c2ecf20Sopenharmony_ci struct fcoe_conn_offload_ramrod_params *p_ramrod = NULL; 2298c2ecf20Sopenharmony_ci struct fcoe_conn_offload_ramrod_data *p_data; 2308c2ecf20Sopenharmony_ci struct qed_spq_entry *p_ent = NULL; 2318c2ecf20Sopenharmony_ci struct qed_sp_init_data init_data; 2328c2ecf20Sopenharmony_ci u16 physical_q0; 2338c2ecf20Sopenharmony_ci __le16 tmp; 2348c2ecf20Sopenharmony_ci int rc; 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci /* Get SPQ entry */ 2378c2ecf20Sopenharmony_ci memset(&init_data, 0, sizeof(init_data)); 2388c2ecf20Sopenharmony_ci init_data.cid = p_conn->icid; 2398c2ecf20Sopenharmony_ci init_data.opaque_fid = p_hwfn->hw_info.opaque_fid; 2408c2ecf20Sopenharmony_ci init_data.comp_mode = comp_mode; 2418c2ecf20Sopenharmony_ci init_data.p_comp_data = p_comp_addr; 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci rc = qed_sp_init_request(p_hwfn, &p_ent, 2448c2ecf20Sopenharmony_ci FCOE_RAMROD_CMD_ID_OFFLOAD_CONN, 2458c2ecf20Sopenharmony_ci PROTOCOLID_FCOE, &init_data); 2468c2ecf20Sopenharmony_ci if (rc) 2478c2ecf20Sopenharmony_ci return rc; 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci p_ramrod = &p_ent->ramrod.fcoe_conn_ofld; 2508c2ecf20Sopenharmony_ci p_data = &p_ramrod->offload_ramrod_data; 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci /* Transmission PQ is the first of the PF */ 2538c2ecf20Sopenharmony_ci physical_q0 = qed_get_cm_pq_idx(p_hwfn, PQ_FLAGS_OFLD); 2548c2ecf20Sopenharmony_ci p_conn->physical_q0 = physical_q0; 2558c2ecf20Sopenharmony_ci p_data->physical_q0 = cpu_to_le16(physical_q0); 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci p_data->conn_id = cpu_to_le16(p_conn->conn_id); 2588c2ecf20Sopenharmony_ci DMA_REGPAIR_LE(p_data->sq_pbl_addr, p_conn->sq_pbl_addr); 2598c2ecf20Sopenharmony_ci DMA_REGPAIR_LE(p_data->sq_curr_page_addr, p_conn->sq_curr_page_addr); 2608c2ecf20Sopenharmony_ci DMA_REGPAIR_LE(p_data->sq_next_page_addr, p_conn->sq_next_page_addr); 2618c2ecf20Sopenharmony_ci DMA_REGPAIR_LE(p_data->xferq_pbl_addr, p_conn->xferq_pbl_addr); 2628c2ecf20Sopenharmony_ci DMA_REGPAIR_LE(p_data->xferq_curr_page_addr, p_conn->xferq_addr[0]); 2638c2ecf20Sopenharmony_ci DMA_REGPAIR_LE(p_data->xferq_next_page_addr, p_conn->xferq_addr[1]); 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci DMA_REGPAIR_LE(p_data->respq_pbl_addr, p_conn->confq_pbl_addr); 2668c2ecf20Sopenharmony_ci DMA_REGPAIR_LE(p_data->respq_curr_page_addr, p_conn->confq_addr[0]); 2678c2ecf20Sopenharmony_ci DMA_REGPAIR_LE(p_data->respq_next_page_addr, p_conn->confq_addr[1]); 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci p_data->dst_mac_addr_lo = cpu_to_le16(p_conn->dst_mac_addr_lo); 2708c2ecf20Sopenharmony_ci p_data->dst_mac_addr_mid = cpu_to_le16(p_conn->dst_mac_addr_mid); 2718c2ecf20Sopenharmony_ci p_data->dst_mac_addr_hi = cpu_to_le16(p_conn->dst_mac_addr_hi); 2728c2ecf20Sopenharmony_ci p_data->src_mac_addr_lo = cpu_to_le16(p_conn->src_mac_addr_lo); 2738c2ecf20Sopenharmony_ci p_data->src_mac_addr_mid = cpu_to_le16(p_conn->src_mac_addr_mid); 2748c2ecf20Sopenharmony_ci p_data->src_mac_addr_hi = cpu_to_le16(p_conn->src_mac_addr_hi); 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci tmp = cpu_to_le16(p_conn->tx_max_fc_pay_len); 2778c2ecf20Sopenharmony_ci p_data->tx_max_fc_pay_len = tmp; 2788c2ecf20Sopenharmony_ci tmp = cpu_to_le16(p_conn->e_d_tov_timer_val); 2798c2ecf20Sopenharmony_ci p_data->e_d_tov_timer_val = tmp; 2808c2ecf20Sopenharmony_ci tmp = cpu_to_le16(p_conn->rec_tov_timer_val); 2818c2ecf20Sopenharmony_ci p_data->rec_rr_tov_timer_val = tmp; 2828c2ecf20Sopenharmony_ci tmp = cpu_to_le16(p_conn->rx_max_fc_pay_len); 2838c2ecf20Sopenharmony_ci p_data->rx_max_fc_pay_len = tmp; 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci p_data->vlan_tag = cpu_to_le16(p_conn->vlan_tag); 2868c2ecf20Sopenharmony_ci p_data->s_id.addr_hi = p_conn->s_id.addr_hi; 2878c2ecf20Sopenharmony_ci p_data->s_id.addr_mid = p_conn->s_id.addr_mid; 2888c2ecf20Sopenharmony_ci p_data->s_id.addr_lo = p_conn->s_id.addr_lo; 2898c2ecf20Sopenharmony_ci p_data->max_conc_seqs_c3 = p_conn->max_conc_seqs_c3; 2908c2ecf20Sopenharmony_ci p_data->d_id.addr_hi = p_conn->d_id.addr_hi; 2918c2ecf20Sopenharmony_ci p_data->d_id.addr_mid = p_conn->d_id.addr_mid; 2928c2ecf20Sopenharmony_ci p_data->d_id.addr_lo = p_conn->d_id.addr_lo; 2938c2ecf20Sopenharmony_ci p_data->flags = p_conn->flags; 2948c2ecf20Sopenharmony_ci if (test_bit(QED_MF_UFP_SPECIFIC, &p_hwfn->cdev->mf_bits)) 2958c2ecf20Sopenharmony_ci SET_FIELD(p_data->flags, 2968c2ecf20Sopenharmony_ci FCOE_CONN_OFFLOAD_RAMROD_DATA_B_SINGLE_VLAN, 1); 2978c2ecf20Sopenharmony_ci p_data->def_q_idx = p_conn->def_q_idx; 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci return qed_spq_post(p_hwfn, p_ent, NULL); 3008c2ecf20Sopenharmony_ci} 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_cistatic int 3038c2ecf20Sopenharmony_ciqed_sp_fcoe_conn_destroy(struct qed_hwfn *p_hwfn, 3048c2ecf20Sopenharmony_ci struct qed_fcoe_conn *p_conn, 3058c2ecf20Sopenharmony_ci enum spq_mode comp_mode, 3068c2ecf20Sopenharmony_ci struct qed_spq_comp_cb *p_comp_addr) 3078c2ecf20Sopenharmony_ci{ 3088c2ecf20Sopenharmony_ci struct fcoe_conn_terminate_ramrod_params *p_ramrod = NULL; 3098c2ecf20Sopenharmony_ci struct qed_spq_entry *p_ent = NULL; 3108c2ecf20Sopenharmony_ci struct qed_sp_init_data init_data; 3118c2ecf20Sopenharmony_ci int rc = 0; 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci /* Get SPQ entry */ 3148c2ecf20Sopenharmony_ci memset(&init_data, 0, sizeof(init_data)); 3158c2ecf20Sopenharmony_ci init_data.cid = p_conn->icid; 3168c2ecf20Sopenharmony_ci init_data.opaque_fid = p_hwfn->hw_info.opaque_fid; 3178c2ecf20Sopenharmony_ci init_data.comp_mode = comp_mode; 3188c2ecf20Sopenharmony_ci init_data.p_comp_data = p_comp_addr; 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_ci rc = qed_sp_init_request(p_hwfn, &p_ent, 3218c2ecf20Sopenharmony_ci FCOE_RAMROD_CMD_ID_TERMINATE_CONN, 3228c2ecf20Sopenharmony_ci PROTOCOLID_FCOE, &init_data); 3238c2ecf20Sopenharmony_ci if (rc) 3248c2ecf20Sopenharmony_ci return rc; 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci p_ramrod = &p_ent->ramrod.fcoe_conn_terminate; 3278c2ecf20Sopenharmony_ci DMA_REGPAIR_LE(p_ramrod->terminate_ramrod_data.terminate_params_addr, 3288c2ecf20Sopenharmony_ci p_conn->terminate_params); 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci return qed_spq_post(p_hwfn, p_ent, NULL); 3318c2ecf20Sopenharmony_ci} 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_cistatic int 3348c2ecf20Sopenharmony_ciqed_sp_fcoe_func_stop(struct qed_hwfn *p_hwfn, 3358c2ecf20Sopenharmony_ci struct qed_ptt *p_ptt, 3368c2ecf20Sopenharmony_ci enum spq_mode comp_mode, 3378c2ecf20Sopenharmony_ci struct qed_spq_comp_cb *p_comp_addr) 3388c2ecf20Sopenharmony_ci{ 3398c2ecf20Sopenharmony_ci struct qed_spq_entry *p_ent = NULL; 3408c2ecf20Sopenharmony_ci struct qed_sp_init_data init_data; 3418c2ecf20Sopenharmony_ci u32 active_segs = 0; 3428c2ecf20Sopenharmony_ci int rc = 0; 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci /* Get SPQ entry */ 3458c2ecf20Sopenharmony_ci memset(&init_data, 0, sizeof(init_data)); 3468c2ecf20Sopenharmony_ci init_data.cid = p_hwfn->pf_params.fcoe_pf_params.dummy_icid; 3478c2ecf20Sopenharmony_ci init_data.opaque_fid = p_hwfn->hw_info.opaque_fid; 3488c2ecf20Sopenharmony_ci init_data.comp_mode = comp_mode; 3498c2ecf20Sopenharmony_ci init_data.p_comp_data = p_comp_addr; 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci rc = qed_sp_init_request(p_hwfn, &p_ent, 3528c2ecf20Sopenharmony_ci FCOE_RAMROD_CMD_ID_DESTROY_FUNC, 3538c2ecf20Sopenharmony_ci PROTOCOLID_FCOE, &init_data); 3548c2ecf20Sopenharmony_ci if (rc) 3558c2ecf20Sopenharmony_ci return rc; 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci active_segs = qed_rd(p_hwfn, p_ptt, TM_REG_PF_ENABLE_TASK); 3588c2ecf20Sopenharmony_ci active_segs &= ~BIT(QED_CXT_FCOE_TID_SEG); 3598c2ecf20Sopenharmony_ci qed_wr(p_hwfn, p_ptt, TM_REG_PF_ENABLE_TASK, active_segs); 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci return qed_spq_post(p_hwfn, p_ent, NULL); 3628c2ecf20Sopenharmony_ci} 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_cistatic int 3658c2ecf20Sopenharmony_ciqed_fcoe_allocate_connection(struct qed_hwfn *p_hwfn, 3668c2ecf20Sopenharmony_ci struct qed_fcoe_conn **p_out_conn) 3678c2ecf20Sopenharmony_ci{ 3688c2ecf20Sopenharmony_ci struct qed_fcoe_conn *p_conn = NULL; 3698c2ecf20Sopenharmony_ci void *p_addr; 3708c2ecf20Sopenharmony_ci u32 i; 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ci spin_lock_bh(&p_hwfn->p_fcoe_info->lock); 3738c2ecf20Sopenharmony_ci if (!list_empty(&p_hwfn->p_fcoe_info->free_list)) 3748c2ecf20Sopenharmony_ci p_conn = 3758c2ecf20Sopenharmony_ci list_first_entry(&p_hwfn->p_fcoe_info->free_list, 3768c2ecf20Sopenharmony_ci struct qed_fcoe_conn, list_entry); 3778c2ecf20Sopenharmony_ci if (p_conn) { 3788c2ecf20Sopenharmony_ci list_del(&p_conn->list_entry); 3798c2ecf20Sopenharmony_ci spin_unlock_bh(&p_hwfn->p_fcoe_info->lock); 3808c2ecf20Sopenharmony_ci *p_out_conn = p_conn; 3818c2ecf20Sopenharmony_ci return 0; 3828c2ecf20Sopenharmony_ci } 3838c2ecf20Sopenharmony_ci spin_unlock_bh(&p_hwfn->p_fcoe_info->lock); 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci p_conn = kzalloc(sizeof(*p_conn), GFP_KERNEL); 3868c2ecf20Sopenharmony_ci if (!p_conn) 3878c2ecf20Sopenharmony_ci return -ENOMEM; 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci p_addr = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev, 3908c2ecf20Sopenharmony_ci QED_CHAIN_PAGE_SIZE, 3918c2ecf20Sopenharmony_ci &p_conn->xferq_pbl_addr, GFP_KERNEL); 3928c2ecf20Sopenharmony_ci if (!p_addr) 3938c2ecf20Sopenharmony_ci goto nomem_pbl_xferq; 3948c2ecf20Sopenharmony_ci p_conn->xferq_pbl_addr_virt_addr = p_addr; 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(p_conn->xferq_addr); i++) { 3978c2ecf20Sopenharmony_ci p_addr = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev, 3988c2ecf20Sopenharmony_ci QED_CHAIN_PAGE_SIZE, 3998c2ecf20Sopenharmony_ci &p_conn->xferq_addr[i], GFP_KERNEL); 4008c2ecf20Sopenharmony_ci if (!p_addr) 4018c2ecf20Sopenharmony_ci goto nomem_xferq; 4028c2ecf20Sopenharmony_ci p_conn->xferq_addr_virt_addr[i] = p_addr; 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci p_addr = p_conn->xferq_pbl_addr_virt_addr; 4058c2ecf20Sopenharmony_ci ((dma_addr_t *)p_addr)[i] = p_conn->xferq_addr[i]; 4068c2ecf20Sopenharmony_ci } 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci p_addr = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev, 4098c2ecf20Sopenharmony_ci QED_CHAIN_PAGE_SIZE, 4108c2ecf20Sopenharmony_ci &p_conn->confq_pbl_addr, GFP_KERNEL); 4118c2ecf20Sopenharmony_ci if (!p_addr) 4128c2ecf20Sopenharmony_ci goto nomem_xferq; 4138c2ecf20Sopenharmony_ci p_conn->confq_pbl_addr_virt_addr = p_addr; 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(p_conn->confq_addr); i++) { 4168c2ecf20Sopenharmony_ci p_addr = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev, 4178c2ecf20Sopenharmony_ci QED_CHAIN_PAGE_SIZE, 4188c2ecf20Sopenharmony_ci &p_conn->confq_addr[i], GFP_KERNEL); 4198c2ecf20Sopenharmony_ci if (!p_addr) 4208c2ecf20Sopenharmony_ci goto nomem_confq; 4218c2ecf20Sopenharmony_ci p_conn->confq_addr_virt_addr[i] = p_addr; 4228c2ecf20Sopenharmony_ci 4238c2ecf20Sopenharmony_ci p_addr = p_conn->confq_pbl_addr_virt_addr; 4248c2ecf20Sopenharmony_ci ((dma_addr_t *)p_addr)[i] = p_conn->confq_addr[i]; 4258c2ecf20Sopenharmony_ci } 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_ci p_conn->free_on_delete = true; 4288c2ecf20Sopenharmony_ci *p_out_conn = p_conn; 4298c2ecf20Sopenharmony_ci return 0; 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_cinomem_confq: 4328c2ecf20Sopenharmony_ci dma_free_coherent(&p_hwfn->cdev->pdev->dev, 4338c2ecf20Sopenharmony_ci QED_CHAIN_PAGE_SIZE, 4348c2ecf20Sopenharmony_ci p_conn->confq_pbl_addr_virt_addr, 4358c2ecf20Sopenharmony_ci p_conn->confq_pbl_addr); 4368c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(p_conn->confq_addr); i++) 4378c2ecf20Sopenharmony_ci if (p_conn->confq_addr_virt_addr[i]) 4388c2ecf20Sopenharmony_ci dma_free_coherent(&p_hwfn->cdev->pdev->dev, 4398c2ecf20Sopenharmony_ci QED_CHAIN_PAGE_SIZE, 4408c2ecf20Sopenharmony_ci p_conn->confq_addr_virt_addr[i], 4418c2ecf20Sopenharmony_ci p_conn->confq_addr[i]); 4428c2ecf20Sopenharmony_cinomem_xferq: 4438c2ecf20Sopenharmony_ci dma_free_coherent(&p_hwfn->cdev->pdev->dev, 4448c2ecf20Sopenharmony_ci QED_CHAIN_PAGE_SIZE, 4458c2ecf20Sopenharmony_ci p_conn->xferq_pbl_addr_virt_addr, 4468c2ecf20Sopenharmony_ci p_conn->xferq_pbl_addr); 4478c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(p_conn->xferq_addr); i++) 4488c2ecf20Sopenharmony_ci if (p_conn->xferq_addr_virt_addr[i]) 4498c2ecf20Sopenharmony_ci dma_free_coherent(&p_hwfn->cdev->pdev->dev, 4508c2ecf20Sopenharmony_ci QED_CHAIN_PAGE_SIZE, 4518c2ecf20Sopenharmony_ci p_conn->xferq_addr_virt_addr[i], 4528c2ecf20Sopenharmony_ci p_conn->xferq_addr[i]); 4538c2ecf20Sopenharmony_cinomem_pbl_xferq: 4548c2ecf20Sopenharmony_ci kfree(p_conn); 4558c2ecf20Sopenharmony_ci return -ENOMEM; 4568c2ecf20Sopenharmony_ci} 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_cistatic void qed_fcoe_free_connection(struct qed_hwfn *p_hwfn, 4598c2ecf20Sopenharmony_ci struct qed_fcoe_conn *p_conn) 4608c2ecf20Sopenharmony_ci{ 4618c2ecf20Sopenharmony_ci u32 i; 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_ci if (!p_conn) 4648c2ecf20Sopenharmony_ci return; 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_ci if (p_conn->confq_pbl_addr_virt_addr) 4678c2ecf20Sopenharmony_ci dma_free_coherent(&p_hwfn->cdev->pdev->dev, 4688c2ecf20Sopenharmony_ci QED_CHAIN_PAGE_SIZE, 4698c2ecf20Sopenharmony_ci p_conn->confq_pbl_addr_virt_addr, 4708c2ecf20Sopenharmony_ci p_conn->confq_pbl_addr); 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(p_conn->confq_addr); i++) { 4738c2ecf20Sopenharmony_ci if (!p_conn->confq_addr_virt_addr[i]) 4748c2ecf20Sopenharmony_ci continue; 4758c2ecf20Sopenharmony_ci dma_free_coherent(&p_hwfn->cdev->pdev->dev, 4768c2ecf20Sopenharmony_ci QED_CHAIN_PAGE_SIZE, 4778c2ecf20Sopenharmony_ci p_conn->confq_addr_virt_addr[i], 4788c2ecf20Sopenharmony_ci p_conn->confq_addr[i]); 4798c2ecf20Sopenharmony_ci } 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_ci if (p_conn->xferq_pbl_addr_virt_addr) 4828c2ecf20Sopenharmony_ci dma_free_coherent(&p_hwfn->cdev->pdev->dev, 4838c2ecf20Sopenharmony_ci QED_CHAIN_PAGE_SIZE, 4848c2ecf20Sopenharmony_ci p_conn->xferq_pbl_addr_virt_addr, 4858c2ecf20Sopenharmony_ci p_conn->xferq_pbl_addr); 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(p_conn->xferq_addr); i++) { 4888c2ecf20Sopenharmony_ci if (!p_conn->xferq_addr_virt_addr[i]) 4898c2ecf20Sopenharmony_ci continue; 4908c2ecf20Sopenharmony_ci dma_free_coherent(&p_hwfn->cdev->pdev->dev, 4918c2ecf20Sopenharmony_ci QED_CHAIN_PAGE_SIZE, 4928c2ecf20Sopenharmony_ci p_conn->xferq_addr_virt_addr[i], 4938c2ecf20Sopenharmony_ci p_conn->xferq_addr[i]); 4948c2ecf20Sopenharmony_ci } 4958c2ecf20Sopenharmony_ci kfree(p_conn); 4968c2ecf20Sopenharmony_ci} 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_cistatic void __iomem *qed_fcoe_get_db_addr(struct qed_hwfn *p_hwfn, u32 cid) 4998c2ecf20Sopenharmony_ci{ 5008c2ecf20Sopenharmony_ci return (u8 __iomem *)p_hwfn->doorbells + 5018c2ecf20Sopenharmony_ci qed_db_addr(cid, DQ_DEMS_LEGACY); 5028c2ecf20Sopenharmony_ci} 5038c2ecf20Sopenharmony_ci 5048c2ecf20Sopenharmony_cistatic void __iomem *qed_fcoe_get_primary_bdq_prod(struct qed_hwfn *p_hwfn, 5058c2ecf20Sopenharmony_ci u8 bdq_id) 5068c2ecf20Sopenharmony_ci{ 5078c2ecf20Sopenharmony_ci if (RESC_NUM(p_hwfn, QED_BDQ)) { 5088c2ecf20Sopenharmony_ci return (u8 __iomem *)p_hwfn->regview + 5098c2ecf20Sopenharmony_ci GTT_BAR0_MAP_REG_MSDM_RAM + 5108c2ecf20Sopenharmony_ci MSTORM_SCSI_BDQ_EXT_PROD_OFFSET(RESC_START(p_hwfn, 5118c2ecf20Sopenharmony_ci QED_BDQ), 5128c2ecf20Sopenharmony_ci bdq_id); 5138c2ecf20Sopenharmony_ci } else { 5148c2ecf20Sopenharmony_ci DP_NOTICE(p_hwfn, "BDQ is not allocated!\n"); 5158c2ecf20Sopenharmony_ci return NULL; 5168c2ecf20Sopenharmony_ci } 5178c2ecf20Sopenharmony_ci} 5188c2ecf20Sopenharmony_ci 5198c2ecf20Sopenharmony_cistatic void __iomem *qed_fcoe_get_secondary_bdq_prod(struct qed_hwfn *p_hwfn, 5208c2ecf20Sopenharmony_ci u8 bdq_id) 5218c2ecf20Sopenharmony_ci{ 5228c2ecf20Sopenharmony_ci if (RESC_NUM(p_hwfn, QED_BDQ)) { 5238c2ecf20Sopenharmony_ci return (u8 __iomem *)p_hwfn->regview + 5248c2ecf20Sopenharmony_ci GTT_BAR0_MAP_REG_TSDM_RAM + 5258c2ecf20Sopenharmony_ci TSTORM_SCSI_BDQ_EXT_PROD_OFFSET(RESC_START(p_hwfn, 5268c2ecf20Sopenharmony_ci QED_BDQ), 5278c2ecf20Sopenharmony_ci bdq_id); 5288c2ecf20Sopenharmony_ci } else { 5298c2ecf20Sopenharmony_ci DP_NOTICE(p_hwfn, "BDQ is not allocated!\n"); 5308c2ecf20Sopenharmony_ci return NULL; 5318c2ecf20Sopenharmony_ci } 5328c2ecf20Sopenharmony_ci} 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_ciint qed_fcoe_alloc(struct qed_hwfn *p_hwfn) 5358c2ecf20Sopenharmony_ci{ 5368c2ecf20Sopenharmony_ci struct qed_fcoe_info *p_fcoe_info; 5378c2ecf20Sopenharmony_ci 5388c2ecf20Sopenharmony_ci /* Allocate LL2's set struct */ 5398c2ecf20Sopenharmony_ci p_fcoe_info = kzalloc(sizeof(*p_fcoe_info), GFP_KERNEL); 5408c2ecf20Sopenharmony_ci if (!p_fcoe_info) { 5418c2ecf20Sopenharmony_ci DP_NOTICE(p_hwfn, "Failed to allocate qed_fcoe_info'\n"); 5428c2ecf20Sopenharmony_ci return -ENOMEM; 5438c2ecf20Sopenharmony_ci } 5448c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&p_fcoe_info->free_list); 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_ci p_hwfn->p_fcoe_info = p_fcoe_info; 5478c2ecf20Sopenharmony_ci return 0; 5488c2ecf20Sopenharmony_ci} 5498c2ecf20Sopenharmony_ci 5508c2ecf20Sopenharmony_civoid qed_fcoe_setup(struct qed_hwfn *p_hwfn) 5518c2ecf20Sopenharmony_ci{ 5528c2ecf20Sopenharmony_ci struct e4_fcoe_task_context *p_task_ctx = NULL; 5538c2ecf20Sopenharmony_ci u32 i, lc; 5548c2ecf20Sopenharmony_ci int rc; 5558c2ecf20Sopenharmony_ci 5568c2ecf20Sopenharmony_ci spin_lock_init(&p_hwfn->p_fcoe_info->lock); 5578c2ecf20Sopenharmony_ci for (i = 0; i < p_hwfn->pf_params.fcoe_pf_params.num_tasks; i++) { 5588c2ecf20Sopenharmony_ci rc = qed_cxt_get_task_ctx(p_hwfn, i, 5598c2ecf20Sopenharmony_ci QED_CTX_WORKING_MEM, 5608c2ecf20Sopenharmony_ci (void **)&p_task_ctx); 5618c2ecf20Sopenharmony_ci if (rc) 5628c2ecf20Sopenharmony_ci continue; 5638c2ecf20Sopenharmony_ci 5648c2ecf20Sopenharmony_ci memset(p_task_ctx, 0, sizeof(struct e4_fcoe_task_context)); 5658c2ecf20Sopenharmony_ci 5668c2ecf20Sopenharmony_ci lc = 0; 5678c2ecf20Sopenharmony_ci SET_FIELD(lc, TIMERS_CONTEXT_VALIDLC0, 1); 5688c2ecf20Sopenharmony_ci p_task_ctx->timer_context.logical_client_0 = cpu_to_le32(lc); 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_ci lc = 0; 5718c2ecf20Sopenharmony_ci SET_FIELD(lc, TIMERS_CONTEXT_VALIDLC1, 1); 5728c2ecf20Sopenharmony_ci p_task_ctx->timer_context.logical_client_1 = cpu_to_le32(lc); 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_ci SET_FIELD(p_task_ctx->tstorm_ag_context.flags0, 5758c2ecf20Sopenharmony_ci E4_TSTORM_FCOE_TASK_AG_CTX_CONNECTION_TYPE, 1); 5768c2ecf20Sopenharmony_ci } 5778c2ecf20Sopenharmony_ci} 5788c2ecf20Sopenharmony_ci 5798c2ecf20Sopenharmony_civoid qed_fcoe_free(struct qed_hwfn *p_hwfn) 5808c2ecf20Sopenharmony_ci{ 5818c2ecf20Sopenharmony_ci struct qed_fcoe_conn *p_conn = NULL; 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_ci if (!p_hwfn->p_fcoe_info) 5848c2ecf20Sopenharmony_ci return; 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_ci while (!list_empty(&p_hwfn->p_fcoe_info->free_list)) { 5878c2ecf20Sopenharmony_ci p_conn = list_first_entry(&p_hwfn->p_fcoe_info->free_list, 5888c2ecf20Sopenharmony_ci struct qed_fcoe_conn, list_entry); 5898c2ecf20Sopenharmony_ci if (!p_conn) 5908c2ecf20Sopenharmony_ci break; 5918c2ecf20Sopenharmony_ci list_del(&p_conn->list_entry); 5928c2ecf20Sopenharmony_ci qed_fcoe_free_connection(p_hwfn, p_conn); 5938c2ecf20Sopenharmony_ci } 5948c2ecf20Sopenharmony_ci 5958c2ecf20Sopenharmony_ci kfree(p_hwfn->p_fcoe_info); 5968c2ecf20Sopenharmony_ci p_hwfn->p_fcoe_info = NULL; 5978c2ecf20Sopenharmony_ci} 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_cistatic int 6008c2ecf20Sopenharmony_ciqed_fcoe_acquire_connection(struct qed_hwfn *p_hwfn, 6018c2ecf20Sopenharmony_ci struct qed_fcoe_conn *p_in_conn, 6028c2ecf20Sopenharmony_ci struct qed_fcoe_conn **p_out_conn) 6038c2ecf20Sopenharmony_ci{ 6048c2ecf20Sopenharmony_ci struct qed_fcoe_conn *p_conn = NULL; 6058c2ecf20Sopenharmony_ci int rc = 0; 6068c2ecf20Sopenharmony_ci u32 icid; 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_ci spin_lock_bh(&p_hwfn->p_fcoe_info->lock); 6098c2ecf20Sopenharmony_ci rc = qed_cxt_acquire_cid(p_hwfn, PROTOCOLID_FCOE, &icid); 6108c2ecf20Sopenharmony_ci spin_unlock_bh(&p_hwfn->p_fcoe_info->lock); 6118c2ecf20Sopenharmony_ci if (rc) 6128c2ecf20Sopenharmony_ci return rc; 6138c2ecf20Sopenharmony_ci 6148c2ecf20Sopenharmony_ci /* Use input connection [if provided] or allocate a new one */ 6158c2ecf20Sopenharmony_ci if (p_in_conn) { 6168c2ecf20Sopenharmony_ci p_conn = p_in_conn; 6178c2ecf20Sopenharmony_ci } else { 6188c2ecf20Sopenharmony_ci rc = qed_fcoe_allocate_connection(p_hwfn, &p_conn); 6198c2ecf20Sopenharmony_ci if (rc) { 6208c2ecf20Sopenharmony_ci spin_lock_bh(&p_hwfn->p_fcoe_info->lock); 6218c2ecf20Sopenharmony_ci qed_cxt_release_cid(p_hwfn, icid); 6228c2ecf20Sopenharmony_ci spin_unlock_bh(&p_hwfn->p_fcoe_info->lock); 6238c2ecf20Sopenharmony_ci return rc; 6248c2ecf20Sopenharmony_ci } 6258c2ecf20Sopenharmony_ci } 6268c2ecf20Sopenharmony_ci 6278c2ecf20Sopenharmony_ci p_conn->icid = icid; 6288c2ecf20Sopenharmony_ci p_conn->fw_cid = (p_hwfn->hw_info.opaque_fid << 16) | icid; 6298c2ecf20Sopenharmony_ci *p_out_conn = p_conn; 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_ci return rc; 6328c2ecf20Sopenharmony_ci} 6338c2ecf20Sopenharmony_ci 6348c2ecf20Sopenharmony_cistatic void qed_fcoe_release_connection(struct qed_hwfn *p_hwfn, 6358c2ecf20Sopenharmony_ci struct qed_fcoe_conn *p_conn) 6368c2ecf20Sopenharmony_ci{ 6378c2ecf20Sopenharmony_ci spin_lock_bh(&p_hwfn->p_fcoe_info->lock); 6388c2ecf20Sopenharmony_ci list_add_tail(&p_conn->list_entry, &p_hwfn->p_fcoe_info->free_list); 6398c2ecf20Sopenharmony_ci qed_cxt_release_cid(p_hwfn, p_conn->icid); 6408c2ecf20Sopenharmony_ci spin_unlock_bh(&p_hwfn->p_fcoe_info->lock); 6418c2ecf20Sopenharmony_ci} 6428c2ecf20Sopenharmony_ci 6438c2ecf20Sopenharmony_cistatic void _qed_fcoe_get_tstats(struct qed_hwfn *p_hwfn, 6448c2ecf20Sopenharmony_ci struct qed_ptt *p_ptt, 6458c2ecf20Sopenharmony_ci struct qed_fcoe_stats *p_stats) 6468c2ecf20Sopenharmony_ci{ 6478c2ecf20Sopenharmony_ci struct fcoe_rx_stat tstats; 6488c2ecf20Sopenharmony_ci u32 tstats_addr; 6498c2ecf20Sopenharmony_ci 6508c2ecf20Sopenharmony_ci memset(&tstats, 0, sizeof(tstats)); 6518c2ecf20Sopenharmony_ci tstats_addr = BAR0_MAP_REG_TSDM_RAM + 6528c2ecf20Sopenharmony_ci TSTORM_FCOE_RX_STATS_OFFSET(p_hwfn->rel_pf_id); 6538c2ecf20Sopenharmony_ci qed_memcpy_from(p_hwfn, p_ptt, &tstats, tstats_addr, sizeof(tstats)); 6548c2ecf20Sopenharmony_ci 6558c2ecf20Sopenharmony_ci p_stats->fcoe_rx_byte_cnt = HILO_64_REGPAIR(tstats.fcoe_rx_byte_cnt); 6568c2ecf20Sopenharmony_ci p_stats->fcoe_rx_data_pkt_cnt = 6578c2ecf20Sopenharmony_ci HILO_64_REGPAIR(tstats.fcoe_rx_data_pkt_cnt); 6588c2ecf20Sopenharmony_ci p_stats->fcoe_rx_xfer_pkt_cnt = 6598c2ecf20Sopenharmony_ci HILO_64_REGPAIR(tstats.fcoe_rx_xfer_pkt_cnt); 6608c2ecf20Sopenharmony_ci p_stats->fcoe_rx_other_pkt_cnt = 6618c2ecf20Sopenharmony_ci HILO_64_REGPAIR(tstats.fcoe_rx_other_pkt_cnt); 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_ci p_stats->fcoe_silent_drop_pkt_cmdq_full_cnt = 6648c2ecf20Sopenharmony_ci le32_to_cpu(tstats.fcoe_silent_drop_pkt_cmdq_full_cnt); 6658c2ecf20Sopenharmony_ci p_stats->fcoe_silent_drop_pkt_rq_full_cnt = 6668c2ecf20Sopenharmony_ci le32_to_cpu(tstats.fcoe_silent_drop_pkt_rq_full_cnt); 6678c2ecf20Sopenharmony_ci p_stats->fcoe_silent_drop_pkt_crc_error_cnt = 6688c2ecf20Sopenharmony_ci le32_to_cpu(tstats.fcoe_silent_drop_pkt_crc_error_cnt); 6698c2ecf20Sopenharmony_ci p_stats->fcoe_silent_drop_pkt_task_invalid_cnt = 6708c2ecf20Sopenharmony_ci le32_to_cpu(tstats.fcoe_silent_drop_pkt_task_invalid_cnt); 6718c2ecf20Sopenharmony_ci p_stats->fcoe_silent_drop_total_pkt_cnt = 6728c2ecf20Sopenharmony_ci le32_to_cpu(tstats.fcoe_silent_drop_total_pkt_cnt); 6738c2ecf20Sopenharmony_ci} 6748c2ecf20Sopenharmony_ci 6758c2ecf20Sopenharmony_cistatic void _qed_fcoe_get_pstats(struct qed_hwfn *p_hwfn, 6768c2ecf20Sopenharmony_ci struct qed_ptt *p_ptt, 6778c2ecf20Sopenharmony_ci struct qed_fcoe_stats *p_stats) 6788c2ecf20Sopenharmony_ci{ 6798c2ecf20Sopenharmony_ci struct fcoe_tx_stat pstats; 6808c2ecf20Sopenharmony_ci u32 pstats_addr; 6818c2ecf20Sopenharmony_ci 6828c2ecf20Sopenharmony_ci memset(&pstats, 0, sizeof(pstats)); 6838c2ecf20Sopenharmony_ci pstats_addr = BAR0_MAP_REG_PSDM_RAM + 6848c2ecf20Sopenharmony_ci PSTORM_FCOE_TX_STATS_OFFSET(p_hwfn->rel_pf_id); 6858c2ecf20Sopenharmony_ci qed_memcpy_from(p_hwfn, p_ptt, &pstats, pstats_addr, sizeof(pstats)); 6868c2ecf20Sopenharmony_ci 6878c2ecf20Sopenharmony_ci p_stats->fcoe_tx_byte_cnt = HILO_64_REGPAIR(pstats.fcoe_tx_byte_cnt); 6888c2ecf20Sopenharmony_ci p_stats->fcoe_tx_data_pkt_cnt = 6898c2ecf20Sopenharmony_ci HILO_64_REGPAIR(pstats.fcoe_tx_data_pkt_cnt); 6908c2ecf20Sopenharmony_ci p_stats->fcoe_tx_xfer_pkt_cnt = 6918c2ecf20Sopenharmony_ci HILO_64_REGPAIR(pstats.fcoe_tx_xfer_pkt_cnt); 6928c2ecf20Sopenharmony_ci p_stats->fcoe_tx_other_pkt_cnt = 6938c2ecf20Sopenharmony_ci HILO_64_REGPAIR(pstats.fcoe_tx_other_pkt_cnt); 6948c2ecf20Sopenharmony_ci} 6958c2ecf20Sopenharmony_ci 6968c2ecf20Sopenharmony_cistatic int qed_fcoe_get_stats(struct qed_hwfn *p_hwfn, 6978c2ecf20Sopenharmony_ci struct qed_fcoe_stats *p_stats) 6988c2ecf20Sopenharmony_ci{ 6998c2ecf20Sopenharmony_ci struct qed_ptt *p_ptt; 7008c2ecf20Sopenharmony_ci 7018c2ecf20Sopenharmony_ci memset(p_stats, 0, sizeof(*p_stats)); 7028c2ecf20Sopenharmony_ci 7038c2ecf20Sopenharmony_ci p_ptt = qed_ptt_acquire(p_hwfn); 7048c2ecf20Sopenharmony_ci 7058c2ecf20Sopenharmony_ci if (!p_ptt) { 7068c2ecf20Sopenharmony_ci DP_ERR(p_hwfn, "Failed to acquire ptt\n"); 7078c2ecf20Sopenharmony_ci return -EINVAL; 7088c2ecf20Sopenharmony_ci } 7098c2ecf20Sopenharmony_ci 7108c2ecf20Sopenharmony_ci _qed_fcoe_get_tstats(p_hwfn, p_ptt, p_stats); 7118c2ecf20Sopenharmony_ci _qed_fcoe_get_pstats(p_hwfn, p_ptt, p_stats); 7128c2ecf20Sopenharmony_ci 7138c2ecf20Sopenharmony_ci qed_ptt_release(p_hwfn, p_ptt); 7148c2ecf20Sopenharmony_ci 7158c2ecf20Sopenharmony_ci return 0; 7168c2ecf20Sopenharmony_ci} 7178c2ecf20Sopenharmony_ci 7188c2ecf20Sopenharmony_cistruct qed_hash_fcoe_con { 7198c2ecf20Sopenharmony_ci struct hlist_node node; 7208c2ecf20Sopenharmony_ci struct qed_fcoe_conn *con; 7218c2ecf20Sopenharmony_ci}; 7228c2ecf20Sopenharmony_ci 7238c2ecf20Sopenharmony_cistatic int qed_fill_fcoe_dev_info(struct qed_dev *cdev, 7248c2ecf20Sopenharmony_ci struct qed_dev_fcoe_info *info) 7258c2ecf20Sopenharmony_ci{ 7268c2ecf20Sopenharmony_ci struct qed_hwfn *hwfn = QED_AFFIN_HWFN(cdev); 7278c2ecf20Sopenharmony_ci int rc; 7288c2ecf20Sopenharmony_ci 7298c2ecf20Sopenharmony_ci memset(info, 0, sizeof(*info)); 7308c2ecf20Sopenharmony_ci rc = qed_fill_dev_info(cdev, &info->common); 7318c2ecf20Sopenharmony_ci 7328c2ecf20Sopenharmony_ci info->primary_dbq_rq_addr = 7338c2ecf20Sopenharmony_ci qed_fcoe_get_primary_bdq_prod(hwfn, BDQ_ID_RQ); 7348c2ecf20Sopenharmony_ci info->secondary_bdq_rq_addr = 7358c2ecf20Sopenharmony_ci qed_fcoe_get_secondary_bdq_prod(hwfn, BDQ_ID_RQ); 7368c2ecf20Sopenharmony_ci 7378c2ecf20Sopenharmony_ci info->wwpn = hwfn->mcp_info->func_info.wwn_port; 7388c2ecf20Sopenharmony_ci info->wwnn = hwfn->mcp_info->func_info.wwn_node; 7398c2ecf20Sopenharmony_ci 7408c2ecf20Sopenharmony_ci info->num_cqs = FEAT_NUM(hwfn, QED_FCOE_CQ); 7418c2ecf20Sopenharmony_ci 7428c2ecf20Sopenharmony_ci return rc; 7438c2ecf20Sopenharmony_ci} 7448c2ecf20Sopenharmony_ci 7458c2ecf20Sopenharmony_cistatic void qed_register_fcoe_ops(struct qed_dev *cdev, 7468c2ecf20Sopenharmony_ci struct qed_fcoe_cb_ops *ops, void *cookie) 7478c2ecf20Sopenharmony_ci{ 7488c2ecf20Sopenharmony_ci cdev->protocol_ops.fcoe = ops; 7498c2ecf20Sopenharmony_ci cdev->ops_cookie = cookie; 7508c2ecf20Sopenharmony_ci} 7518c2ecf20Sopenharmony_ci 7528c2ecf20Sopenharmony_cistatic struct qed_hash_fcoe_con *qed_fcoe_get_hash(struct qed_dev *cdev, 7538c2ecf20Sopenharmony_ci u32 handle) 7548c2ecf20Sopenharmony_ci{ 7558c2ecf20Sopenharmony_ci struct qed_hash_fcoe_con *hash_con = NULL; 7568c2ecf20Sopenharmony_ci 7578c2ecf20Sopenharmony_ci if (!(cdev->flags & QED_FLAG_STORAGE_STARTED)) 7588c2ecf20Sopenharmony_ci return NULL; 7598c2ecf20Sopenharmony_ci 7608c2ecf20Sopenharmony_ci hash_for_each_possible(cdev->connections, hash_con, node, handle) { 7618c2ecf20Sopenharmony_ci if (hash_con->con->icid == handle) 7628c2ecf20Sopenharmony_ci break; 7638c2ecf20Sopenharmony_ci } 7648c2ecf20Sopenharmony_ci 7658c2ecf20Sopenharmony_ci if (!hash_con || (hash_con->con->icid != handle)) 7668c2ecf20Sopenharmony_ci return NULL; 7678c2ecf20Sopenharmony_ci 7688c2ecf20Sopenharmony_ci return hash_con; 7698c2ecf20Sopenharmony_ci} 7708c2ecf20Sopenharmony_ci 7718c2ecf20Sopenharmony_cistatic int qed_fcoe_stop(struct qed_dev *cdev) 7728c2ecf20Sopenharmony_ci{ 7738c2ecf20Sopenharmony_ci struct qed_ptt *p_ptt; 7748c2ecf20Sopenharmony_ci int rc; 7758c2ecf20Sopenharmony_ci 7768c2ecf20Sopenharmony_ci if (!(cdev->flags & QED_FLAG_STORAGE_STARTED)) { 7778c2ecf20Sopenharmony_ci DP_NOTICE(cdev, "fcoe already stopped\n"); 7788c2ecf20Sopenharmony_ci return 0; 7798c2ecf20Sopenharmony_ci } 7808c2ecf20Sopenharmony_ci 7818c2ecf20Sopenharmony_ci if (!hash_empty(cdev->connections)) { 7828c2ecf20Sopenharmony_ci DP_NOTICE(cdev, 7838c2ecf20Sopenharmony_ci "Can't stop fcoe - not all connections were returned\n"); 7848c2ecf20Sopenharmony_ci return -EINVAL; 7858c2ecf20Sopenharmony_ci } 7868c2ecf20Sopenharmony_ci 7878c2ecf20Sopenharmony_ci p_ptt = qed_ptt_acquire(QED_AFFIN_HWFN(cdev)); 7888c2ecf20Sopenharmony_ci if (!p_ptt) 7898c2ecf20Sopenharmony_ci return -EAGAIN; 7908c2ecf20Sopenharmony_ci 7918c2ecf20Sopenharmony_ci /* Stop the fcoe */ 7928c2ecf20Sopenharmony_ci rc = qed_sp_fcoe_func_stop(QED_AFFIN_HWFN(cdev), p_ptt, 7938c2ecf20Sopenharmony_ci QED_SPQ_MODE_EBLOCK, NULL); 7948c2ecf20Sopenharmony_ci cdev->flags &= ~QED_FLAG_STORAGE_STARTED; 7958c2ecf20Sopenharmony_ci qed_ptt_release(QED_AFFIN_HWFN(cdev), p_ptt); 7968c2ecf20Sopenharmony_ci 7978c2ecf20Sopenharmony_ci return rc; 7988c2ecf20Sopenharmony_ci} 7998c2ecf20Sopenharmony_ci 8008c2ecf20Sopenharmony_cistatic int qed_fcoe_start(struct qed_dev *cdev, struct qed_fcoe_tid *tasks) 8018c2ecf20Sopenharmony_ci{ 8028c2ecf20Sopenharmony_ci int rc; 8038c2ecf20Sopenharmony_ci 8048c2ecf20Sopenharmony_ci if (cdev->flags & QED_FLAG_STORAGE_STARTED) { 8058c2ecf20Sopenharmony_ci DP_NOTICE(cdev, "fcoe already started;\n"); 8068c2ecf20Sopenharmony_ci return 0; 8078c2ecf20Sopenharmony_ci } 8088c2ecf20Sopenharmony_ci 8098c2ecf20Sopenharmony_ci rc = qed_sp_fcoe_func_start(QED_AFFIN_HWFN(cdev), QED_SPQ_MODE_EBLOCK, 8108c2ecf20Sopenharmony_ci NULL); 8118c2ecf20Sopenharmony_ci if (rc) { 8128c2ecf20Sopenharmony_ci DP_NOTICE(cdev, "Failed to start fcoe\n"); 8138c2ecf20Sopenharmony_ci return rc; 8148c2ecf20Sopenharmony_ci } 8158c2ecf20Sopenharmony_ci 8168c2ecf20Sopenharmony_ci cdev->flags |= QED_FLAG_STORAGE_STARTED; 8178c2ecf20Sopenharmony_ci hash_init(cdev->connections); 8188c2ecf20Sopenharmony_ci 8198c2ecf20Sopenharmony_ci if (tasks) { 8208c2ecf20Sopenharmony_ci struct qed_tid_mem *tid_info = kzalloc(sizeof(*tid_info), 8218c2ecf20Sopenharmony_ci GFP_ATOMIC); 8228c2ecf20Sopenharmony_ci 8238c2ecf20Sopenharmony_ci if (!tid_info) { 8248c2ecf20Sopenharmony_ci DP_NOTICE(cdev, 8258c2ecf20Sopenharmony_ci "Failed to allocate tasks information\n"); 8268c2ecf20Sopenharmony_ci qed_fcoe_stop(cdev); 8278c2ecf20Sopenharmony_ci return -ENOMEM; 8288c2ecf20Sopenharmony_ci } 8298c2ecf20Sopenharmony_ci 8308c2ecf20Sopenharmony_ci rc = qed_cxt_get_tid_mem_info(QED_AFFIN_HWFN(cdev), tid_info); 8318c2ecf20Sopenharmony_ci if (rc) { 8328c2ecf20Sopenharmony_ci DP_NOTICE(cdev, "Failed to gather task information\n"); 8338c2ecf20Sopenharmony_ci qed_fcoe_stop(cdev); 8348c2ecf20Sopenharmony_ci kfree(tid_info); 8358c2ecf20Sopenharmony_ci return rc; 8368c2ecf20Sopenharmony_ci } 8378c2ecf20Sopenharmony_ci 8388c2ecf20Sopenharmony_ci /* Fill task information */ 8398c2ecf20Sopenharmony_ci tasks->size = tid_info->tid_size; 8408c2ecf20Sopenharmony_ci tasks->num_tids_per_block = tid_info->num_tids_per_block; 8418c2ecf20Sopenharmony_ci memcpy(tasks->blocks, tid_info->blocks, 8428c2ecf20Sopenharmony_ci MAX_TID_BLOCKS_FCOE * sizeof(u8 *)); 8438c2ecf20Sopenharmony_ci 8448c2ecf20Sopenharmony_ci kfree(tid_info); 8458c2ecf20Sopenharmony_ci } 8468c2ecf20Sopenharmony_ci 8478c2ecf20Sopenharmony_ci return 0; 8488c2ecf20Sopenharmony_ci} 8498c2ecf20Sopenharmony_ci 8508c2ecf20Sopenharmony_cistatic int qed_fcoe_acquire_conn(struct qed_dev *cdev, 8518c2ecf20Sopenharmony_ci u32 *handle, 8528c2ecf20Sopenharmony_ci u32 *fw_cid, void __iomem **p_doorbell) 8538c2ecf20Sopenharmony_ci{ 8548c2ecf20Sopenharmony_ci struct qed_hash_fcoe_con *hash_con; 8558c2ecf20Sopenharmony_ci int rc; 8568c2ecf20Sopenharmony_ci 8578c2ecf20Sopenharmony_ci /* Allocate a hashed connection */ 8588c2ecf20Sopenharmony_ci hash_con = kzalloc(sizeof(*hash_con), GFP_KERNEL); 8598c2ecf20Sopenharmony_ci if (!hash_con) { 8608c2ecf20Sopenharmony_ci DP_NOTICE(cdev, "Failed to allocate hashed connection\n"); 8618c2ecf20Sopenharmony_ci return -ENOMEM; 8628c2ecf20Sopenharmony_ci } 8638c2ecf20Sopenharmony_ci 8648c2ecf20Sopenharmony_ci /* Acquire the connection */ 8658c2ecf20Sopenharmony_ci rc = qed_fcoe_acquire_connection(QED_AFFIN_HWFN(cdev), NULL, 8668c2ecf20Sopenharmony_ci &hash_con->con); 8678c2ecf20Sopenharmony_ci if (rc) { 8688c2ecf20Sopenharmony_ci DP_NOTICE(cdev, "Failed to acquire Connection\n"); 8698c2ecf20Sopenharmony_ci kfree(hash_con); 8708c2ecf20Sopenharmony_ci return rc; 8718c2ecf20Sopenharmony_ci } 8728c2ecf20Sopenharmony_ci 8738c2ecf20Sopenharmony_ci /* Added the connection to hash table */ 8748c2ecf20Sopenharmony_ci *handle = hash_con->con->icid; 8758c2ecf20Sopenharmony_ci *fw_cid = hash_con->con->fw_cid; 8768c2ecf20Sopenharmony_ci hash_add(cdev->connections, &hash_con->node, *handle); 8778c2ecf20Sopenharmony_ci 8788c2ecf20Sopenharmony_ci if (p_doorbell) 8798c2ecf20Sopenharmony_ci *p_doorbell = qed_fcoe_get_db_addr(QED_AFFIN_HWFN(cdev), 8808c2ecf20Sopenharmony_ci *handle); 8818c2ecf20Sopenharmony_ci 8828c2ecf20Sopenharmony_ci return 0; 8838c2ecf20Sopenharmony_ci} 8848c2ecf20Sopenharmony_ci 8858c2ecf20Sopenharmony_cistatic int qed_fcoe_release_conn(struct qed_dev *cdev, u32 handle) 8868c2ecf20Sopenharmony_ci{ 8878c2ecf20Sopenharmony_ci struct qed_hash_fcoe_con *hash_con; 8888c2ecf20Sopenharmony_ci 8898c2ecf20Sopenharmony_ci hash_con = qed_fcoe_get_hash(cdev, handle); 8908c2ecf20Sopenharmony_ci if (!hash_con) { 8918c2ecf20Sopenharmony_ci DP_NOTICE(cdev, "Failed to find connection for handle %d\n", 8928c2ecf20Sopenharmony_ci handle); 8938c2ecf20Sopenharmony_ci return -EINVAL; 8948c2ecf20Sopenharmony_ci } 8958c2ecf20Sopenharmony_ci 8968c2ecf20Sopenharmony_ci hlist_del(&hash_con->node); 8978c2ecf20Sopenharmony_ci qed_fcoe_release_connection(QED_AFFIN_HWFN(cdev), hash_con->con); 8988c2ecf20Sopenharmony_ci kfree(hash_con); 8998c2ecf20Sopenharmony_ci 9008c2ecf20Sopenharmony_ci return 0; 9018c2ecf20Sopenharmony_ci} 9028c2ecf20Sopenharmony_ci 9038c2ecf20Sopenharmony_cistatic int qed_fcoe_offload_conn(struct qed_dev *cdev, 9048c2ecf20Sopenharmony_ci u32 handle, 9058c2ecf20Sopenharmony_ci struct qed_fcoe_params_offload *conn_info) 9068c2ecf20Sopenharmony_ci{ 9078c2ecf20Sopenharmony_ci struct qed_hash_fcoe_con *hash_con; 9088c2ecf20Sopenharmony_ci struct qed_fcoe_conn *con; 9098c2ecf20Sopenharmony_ci 9108c2ecf20Sopenharmony_ci hash_con = qed_fcoe_get_hash(cdev, handle); 9118c2ecf20Sopenharmony_ci if (!hash_con) { 9128c2ecf20Sopenharmony_ci DP_NOTICE(cdev, "Failed to find connection for handle %d\n", 9138c2ecf20Sopenharmony_ci handle); 9148c2ecf20Sopenharmony_ci return -EINVAL; 9158c2ecf20Sopenharmony_ci } 9168c2ecf20Sopenharmony_ci 9178c2ecf20Sopenharmony_ci /* Update the connection with information from the params */ 9188c2ecf20Sopenharmony_ci con = hash_con->con; 9198c2ecf20Sopenharmony_ci 9208c2ecf20Sopenharmony_ci con->sq_pbl_addr = conn_info->sq_pbl_addr; 9218c2ecf20Sopenharmony_ci con->sq_curr_page_addr = conn_info->sq_curr_page_addr; 9228c2ecf20Sopenharmony_ci con->sq_next_page_addr = conn_info->sq_next_page_addr; 9238c2ecf20Sopenharmony_ci con->tx_max_fc_pay_len = conn_info->tx_max_fc_pay_len; 9248c2ecf20Sopenharmony_ci con->e_d_tov_timer_val = conn_info->e_d_tov_timer_val; 9258c2ecf20Sopenharmony_ci con->rec_tov_timer_val = conn_info->rec_tov_timer_val; 9268c2ecf20Sopenharmony_ci con->rx_max_fc_pay_len = conn_info->rx_max_fc_pay_len; 9278c2ecf20Sopenharmony_ci con->vlan_tag = conn_info->vlan_tag; 9288c2ecf20Sopenharmony_ci con->max_conc_seqs_c3 = conn_info->max_conc_seqs_c3; 9298c2ecf20Sopenharmony_ci con->flags = conn_info->flags; 9308c2ecf20Sopenharmony_ci con->def_q_idx = conn_info->def_q_idx; 9318c2ecf20Sopenharmony_ci 9328c2ecf20Sopenharmony_ci con->src_mac_addr_hi = (conn_info->src_mac[5] << 8) | 9338c2ecf20Sopenharmony_ci conn_info->src_mac[4]; 9348c2ecf20Sopenharmony_ci con->src_mac_addr_mid = (conn_info->src_mac[3] << 8) | 9358c2ecf20Sopenharmony_ci conn_info->src_mac[2]; 9368c2ecf20Sopenharmony_ci con->src_mac_addr_lo = (conn_info->src_mac[1] << 8) | 9378c2ecf20Sopenharmony_ci conn_info->src_mac[0]; 9388c2ecf20Sopenharmony_ci con->dst_mac_addr_hi = (conn_info->dst_mac[5] << 8) | 9398c2ecf20Sopenharmony_ci conn_info->dst_mac[4]; 9408c2ecf20Sopenharmony_ci con->dst_mac_addr_mid = (conn_info->dst_mac[3] << 8) | 9418c2ecf20Sopenharmony_ci conn_info->dst_mac[2]; 9428c2ecf20Sopenharmony_ci con->dst_mac_addr_lo = (conn_info->dst_mac[1] << 8) | 9438c2ecf20Sopenharmony_ci conn_info->dst_mac[0]; 9448c2ecf20Sopenharmony_ci 9458c2ecf20Sopenharmony_ci con->s_id.addr_hi = conn_info->s_id.addr_hi; 9468c2ecf20Sopenharmony_ci con->s_id.addr_mid = conn_info->s_id.addr_mid; 9478c2ecf20Sopenharmony_ci con->s_id.addr_lo = conn_info->s_id.addr_lo; 9488c2ecf20Sopenharmony_ci con->d_id.addr_hi = conn_info->d_id.addr_hi; 9498c2ecf20Sopenharmony_ci con->d_id.addr_mid = conn_info->d_id.addr_mid; 9508c2ecf20Sopenharmony_ci con->d_id.addr_lo = conn_info->d_id.addr_lo; 9518c2ecf20Sopenharmony_ci 9528c2ecf20Sopenharmony_ci return qed_sp_fcoe_conn_offload(QED_AFFIN_HWFN(cdev), con, 9538c2ecf20Sopenharmony_ci QED_SPQ_MODE_EBLOCK, NULL); 9548c2ecf20Sopenharmony_ci} 9558c2ecf20Sopenharmony_ci 9568c2ecf20Sopenharmony_cistatic int qed_fcoe_destroy_conn(struct qed_dev *cdev, 9578c2ecf20Sopenharmony_ci u32 handle, dma_addr_t terminate_params) 9588c2ecf20Sopenharmony_ci{ 9598c2ecf20Sopenharmony_ci struct qed_hash_fcoe_con *hash_con; 9608c2ecf20Sopenharmony_ci struct qed_fcoe_conn *con; 9618c2ecf20Sopenharmony_ci 9628c2ecf20Sopenharmony_ci hash_con = qed_fcoe_get_hash(cdev, handle); 9638c2ecf20Sopenharmony_ci if (!hash_con) { 9648c2ecf20Sopenharmony_ci DP_NOTICE(cdev, "Failed to find connection for handle %d\n", 9658c2ecf20Sopenharmony_ci handle); 9668c2ecf20Sopenharmony_ci return -EINVAL; 9678c2ecf20Sopenharmony_ci } 9688c2ecf20Sopenharmony_ci 9698c2ecf20Sopenharmony_ci /* Update the connection with information from the params */ 9708c2ecf20Sopenharmony_ci con = hash_con->con; 9718c2ecf20Sopenharmony_ci con->terminate_params = terminate_params; 9728c2ecf20Sopenharmony_ci 9738c2ecf20Sopenharmony_ci return qed_sp_fcoe_conn_destroy(QED_AFFIN_HWFN(cdev), con, 9748c2ecf20Sopenharmony_ci QED_SPQ_MODE_EBLOCK, NULL); 9758c2ecf20Sopenharmony_ci} 9768c2ecf20Sopenharmony_ci 9778c2ecf20Sopenharmony_cistatic int qed_fcoe_stats(struct qed_dev *cdev, struct qed_fcoe_stats *stats) 9788c2ecf20Sopenharmony_ci{ 9798c2ecf20Sopenharmony_ci return qed_fcoe_get_stats(QED_AFFIN_HWFN(cdev), stats); 9808c2ecf20Sopenharmony_ci} 9818c2ecf20Sopenharmony_ci 9828c2ecf20Sopenharmony_civoid qed_get_protocol_stats_fcoe(struct qed_dev *cdev, 9838c2ecf20Sopenharmony_ci struct qed_mcp_fcoe_stats *stats) 9848c2ecf20Sopenharmony_ci{ 9858c2ecf20Sopenharmony_ci struct qed_fcoe_stats proto_stats; 9868c2ecf20Sopenharmony_ci 9878c2ecf20Sopenharmony_ci /* Retrieve FW statistics */ 9888c2ecf20Sopenharmony_ci memset(&proto_stats, 0, sizeof(proto_stats)); 9898c2ecf20Sopenharmony_ci if (qed_fcoe_stats(cdev, &proto_stats)) { 9908c2ecf20Sopenharmony_ci DP_VERBOSE(cdev, QED_MSG_STORAGE, 9918c2ecf20Sopenharmony_ci "Failed to collect FCoE statistics\n"); 9928c2ecf20Sopenharmony_ci return; 9938c2ecf20Sopenharmony_ci } 9948c2ecf20Sopenharmony_ci 9958c2ecf20Sopenharmony_ci /* Translate FW statistics into struct */ 9968c2ecf20Sopenharmony_ci stats->rx_pkts = proto_stats.fcoe_rx_data_pkt_cnt + 9978c2ecf20Sopenharmony_ci proto_stats.fcoe_rx_xfer_pkt_cnt + 9988c2ecf20Sopenharmony_ci proto_stats.fcoe_rx_other_pkt_cnt; 9998c2ecf20Sopenharmony_ci stats->tx_pkts = proto_stats.fcoe_tx_data_pkt_cnt + 10008c2ecf20Sopenharmony_ci proto_stats.fcoe_tx_xfer_pkt_cnt + 10018c2ecf20Sopenharmony_ci proto_stats.fcoe_tx_other_pkt_cnt; 10028c2ecf20Sopenharmony_ci stats->fcs_err = proto_stats.fcoe_silent_drop_pkt_crc_error_cnt; 10038c2ecf20Sopenharmony_ci 10048c2ecf20Sopenharmony_ci /* Request protocol driver to fill-in the rest */ 10058c2ecf20Sopenharmony_ci if (cdev->protocol_ops.fcoe && cdev->ops_cookie) { 10068c2ecf20Sopenharmony_ci struct qed_fcoe_cb_ops *ops = cdev->protocol_ops.fcoe; 10078c2ecf20Sopenharmony_ci void *cookie = cdev->ops_cookie; 10088c2ecf20Sopenharmony_ci 10098c2ecf20Sopenharmony_ci if (ops->get_login_failures) 10108c2ecf20Sopenharmony_ci stats->login_failure = ops->get_login_failures(cookie); 10118c2ecf20Sopenharmony_ci } 10128c2ecf20Sopenharmony_ci} 10138c2ecf20Sopenharmony_ci 10148c2ecf20Sopenharmony_cistatic const struct qed_fcoe_ops qed_fcoe_ops_pass = { 10158c2ecf20Sopenharmony_ci .common = &qed_common_ops_pass, 10168c2ecf20Sopenharmony_ci .ll2 = &qed_ll2_ops_pass, 10178c2ecf20Sopenharmony_ci .fill_dev_info = &qed_fill_fcoe_dev_info, 10188c2ecf20Sopenharmony_ci .start = &qed_fcoe_start, 10198c2ecf20Sopenharmony_ci .stop = &qed_fcoe_stop, 10208c2ecf20Sopenharmony_ci .register_ops = &qed_register_fcoe_ops, 10218c2ecf20Sopenharmony_ci .acquire_conn = &qed_fcoe_acquire_conn, 10228c2ecf20Sopenharmony_ci .release_conn = &qed_fcoe_release_conn, 10238c2ecf20Sopenharmony_ci .offload_conn = &qed_fcoe_offload_conn, 10248c2ecf20Sopenharmony_ci .destroy_conn = &qed_fcoe_destroy_conn, 10258c2ecf20Sopenharmony_ci .get_stats = &qed_fcoe_stats, 10268c2ecf20Sopenharmony_ci}; 10278c2ecf20Sopenharmony_ci 10288c2ecf20Sopenharmony_ciconst struct qed_fcoe_ops *qed_get_fcoe_ops(void) 10298c2ecf20Sopenharmony_ci{ 10308c2ecf20Sopenharmony_ci return &qed_fcoe_ops_pass; 10318c2ecf20Sopenharmony_ci} 10328c2ecf20Sopenharmony_ciEXPORT_SYMBOL(qed_get_fcoe_ops); 10338c2ecf20Sopenharmony_ci 10348c2ecf20Sopenharmony_civoid qed_put_fcoe_ops(void) 10358c2ecf20Sopenharmony_ci{ 10368c2ecf20Sopenharmony_ci} 10378c2ecf20Sopenharmony_ciEXPORT_SYMBOL(qed_put_fcoe_ops); 1038