// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
/* QLogic qed NIC Driver
* Copyright (c) 2015-2017 QLogic Corporation
*/
#include <linux/types.h>
#include <asm/byteorder.h>
#include <asm/param.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/log2.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/stddef.h>
#include <linux/string.h>
#include <linux/workqueue.h>
#include <linux/errno.h>
#include <linux/list.h>
#include <linux/spinlock.h>
#define __PREVENT_DUMP_MEM_ARR__
#define __PREVENT_PXP_GLOBAL_WIN__
#include "qed.h"
#include "qed_cxt.h"
#include "qed_dev_api.h"
#include "qed_fcoe.h"
#include "qed_hsi.h"
#include "qed_hw.h"
#include "qed_int.h"
#include "qed_ll2.h"
#include "qed_mcp.h"
#include "qed_reg_addr.h"
#include "qed_sp.h"
#include "qed_sriov.h"
#include <linux/qed/qed_fcoe_if.h>
struct qed_fcoe_conn {
struct list_head list_entry;
bool free_on_delete;
u16 conn_id;
u32 icid;
u32 fw_cid;
u8 layer_code;
dma_addr_t sq_pbl_addr;
dma_addr_t sq_curr_page_addr;
dma_addr_t sq_next_page_addr;
dma_addr_t xferq_pbl_addr;
void *xferq_pbl_addr_virt_addr;
dma_addr_t xferq_addr[4];
void *xferq_addr_virt_addr[4];
dma_addr_t confq_pbl_addr;
void *confq_pbl_addr_virt_addr;
dma_addr_t confq_addr[2];
void *confq_addr_virt_addr[2];
dma_addr_t terminate_params;
u16 dst_mac_addr_lo;
u16 dst_mac_addr_mid;
u16 dst_mac_addr_hi;
u16 src_mac_addr_lo;
u16 src_mac_addr_mid;
u16 src_mac_addr_hi;
u16 tx_max_fc_pay_len;
u16 e_d_tov_timer_val;
u16 rec_tov_timer_val;
u16 rx_max_fc_pay_len;
u16 vlan_tag;
u16 physical_q0;
struct fc_addr_nw s_id;
u8 max_conc_seqs_c3;
struct fc_addr_nw d_id;
u8 flags;
u8 def_q_idx;
};
static int
qed_sp_fcoe_func_start(struct qed_hwfn *p_hwfn,
enum spq_mode comp_mode,
struct qed_spq_comp_cb *p_comp_addr)
{
struct qed_fcoe_pf_params *fcoe_pf_params = NULL;
struct fcoe_init_ramrod_params *p_ramrod = NULL;
struct fcoe_init_func_ramrod_data *p_data;
struct e4_fcoe_conn_context *p_cxt = NULL;
struct qed_spq_entry *p_ent = NULL;
struct qed_sp_init_data init_data;
struct qed_cxt_info cxt_info;
u32 dummy_cid;
int rc = 0;
u16 tmp;
u8 i;
/* Get SPQ entry */
memset(&init_data, 0, sizeof(init_data));
init_data.cid = qed_spq_get_cid(p_hwfn);
init_data.opaque_fid = p_hwfn->hw_info.opaque_fid;
init_data.comp_mode = comp_mode;
init_data.p_comp_data = p_comp_addr;
rc = qed_sp_init_request(p_hwfn, &p_ent,
FCOE_RAMROD_CMD_ID_INIT_FUNC,
PROTOCOLID_FCOE, &init_data);
if (rc)
return rc;
p_ramrod = &p_ent->ramrod.fcoe_init;
p_data = &p_ramrod->init_ramrod_data;
fcoe_pf_params = &p_hwfn->pf_params.fcoe_pf_params;
/* Sanity */
if (fcoe_pf_params->num_cqs > p_hwfn->hw_info.feat_num[QED_FCOE_CQ]) {
DP_ERR(p_hwfn,
"Cannot satisfy CQ amount. CQs requested %d, CQs available %d. Aborting function start\n",
fcoe_pf_params->num_cqs,
p_hwfn->hw_info.feat_num[QED_FCOE_CQ]);
rc = -EINVAL;
goto err;
}
p_data->mtu = cpu_to_le16(fcoe_pf_params->mtu);
tmp = cpu_to_le16(fcoe_pf_params->sq_num_pbl_pages);
p_data->sq_num_pages_in_pbl = tmp;
rc = qed_cxt_acquire_cid(p_hwfn, PROTOCOLID_FCOE, &dummy_cid);
if (rc)
goto err;
cxt_info.iid = dummy_cid;
rc = qed_cxt_get_cid_info(p_hwfn, &cxt_info);
if (rc) {
DP_NOTICE(p_hwfn, "Cannot find context info for dummy cid=%d\n",
dummy_cid);
goto err;
}
p_cxt = cxt_info.p_cxt;
memset(p_cxt, 0, sizeof(*p_cxt));
SET_FIELD(p_cxt->tstorm_ag_context.flags3,
E4_TSTORM_FCOE_CONN_AG_