cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

qed_fcoe.c (29427B)


      1// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
      2/* QLogic qed NIC Driver
      3 * Copyright (c) 2015-2017  QLogic Corporation
      4 * Copyright (c) 2019-2020 Marvell International Ltd.
      5 */
      6
      7#include <linux/types.h>
      8#include <asm/byteorder.h>
      9#include <asm/param.h>
     10#include <linux/delay.h>
     11#include <linux/dma-mapping.h>
     12#include <linux/interrupt.h>
     13#include <linux/kernel.h>
     14#include <linux/log2.h>
     15#include <linux/module.h>
     16#include <linux/pci.h>
     17#include <linux/slab.h>
     18#include <linux/stddef.h>
     19#include <linux/string.h>
     20#include <linux/workqueue.h>
     21#include <linux/errno.h>
     22#include <linux/list.h>
     23#include <linux/spinlock.h>
     24#define __PREVENT_DUMP_MEM_ARR__
     25#define __PREVENT_PXP_GLOBAL_WIN__
     26#include "qed.h"
     27#include "qed_cxt.h"
     28#include "qed_dev_api.h"
     29#include "qed_fcoe.h"
     30#include "qed_hsi.h"
     31#include "qed_hw.h"
     32#include "qed_int.h"
     33#include "qed_iro_hsi.h"
     34#include "qed_ll2.h"
     35#include "qed_mcp.h"
     36#include "qed_reg_addr.h"
     37#include "qed_sp.h"
     38#include "qed_sriov.h"
     39#include <linux/qed/qed_fcoe_if.h>
     40
     41struct qed_fcoe_conn {
     42	struct list_head list_entry;
     43	bool free_on_delete;
     44
     45	u16 conn_id;
     46	u32 icid;
     47	u32 fw_cid;
     48	u8 layer_code;
     49
     50	dma_addr_t sq_pbl_addr;
     51	dma_addr_t sq_curr_page_addr;
     52	dma_addr_t sq_next_page_addr;
     53	dma_addr_t xferq_pbl_addr;
     54	void *xferq_pbl_addr_virt_addr;
     55	dma_addr_t xferq_addr[4];
     56	void *xferq_addr_virt_addr[4];
     57	dma_addr_t confq_pbl_addr;
     58	void *confq_pbl_addr_virt_addr;
     59	dma_addr_t confq_addr[2];
     60	void *confq_addr_virt_addr[2];
     61
     62	dma_addr_t terminate_params;
     63
     64	u16 dst_mac_addr_lo;
     65	u16 dst_mac_addr_mid;
     66	u16 dst_mac_addr_hi;
     67	u16 src_mac_addr_lo;
     68	u16 src_mac_addr_mid;
     69	u16 src_mac_addr_hi;
     70
     71	u16 tx_max_fc_pay_len;
     72	u16 e_d_tov_timer_val;
     73	u16 rec_tov_timer_val;
     74	u16 rx_max_fc_pay_len;
     75	u16 vlan_tag;
     76	u16 physical_q0;
     77
     78	struct fc_addr_nw s_id;
     79	u8 max_conc_seqs_c3;
     80	struct fc_addr_nw d_id;
     81	u8 flags;
     82	u8 def_q_idx;
     83};
     84
     85static int
     86qed_sp_fcoe_func_start(struct qed_hwfn *p_hwfn,
     87		       enum spq_mode comp_mode,
     88		       struct qed_spq_comp_cb *p_comp_addr)
     89{
     90	struct qed_fcoe_pf_params *fcoe_pf_params = NULL;
     91	struct fcoe_init_ramrod_params *p_ramrod = NULL;
     92	struct fcoe_init_func_ramrod_data *p_data;
     93	struct fcoe_conn_context *p_cxt = NULL;
     94	struct qed_spq_entry *p_ent = NULL;
     95	struct qed_sp_init_data init_data;
     96	struct qed_cxt_info cxt_info;
     97	u32 dummy_cid;
     98	int rc = 0;
     99	__le16 tmp;
    100	u8 i;
    101
    102	/* Get SPQ entry */
    103	memset(&init_data, 0, sizeof(init_data));
    104	init_data.cid = qed_spq_get_cid(p_hwfn);
    105	init_data.opaque_fid = p_hwfn->hw_info.opaque_fid;
    106	init_data.comp_mode = comp_mode;
    107	init_data.p_comp_data = p_comp_addr;
    108
    109	rc = qed_sp_init_request(p_hwfn, &p_ent,
    110				 FCOE_RAMROD_CMD_ID_INIT_FUNC,
    111				 PROTOCOLID_FCOE, &init_data);
    112	if (rc)
    113		return rc;
    114
    115	p_ramrod = &p_ent->ramrod.fcoe_init;
    116	p_data = &p_ramrod->init_ramrod_data;
    117	fcoe_pf_params = &p_hwfn->pf_params.fcoe_pf_params;
    118
    119	/* Sanity */
    120	if (fcoe_pf_params->num_cqs > p_hwfn->hw_info.feat_num[QED_FCOE_CQ]) {
    121		DP_ERR(p_hwfn,
    122		       "Cannot satisfy CQ amount. CQs requested %d, CQs available %d. Aborting function start\n",
    123		       fcoe_pf_params->num_cqs,
    124		       p_hwfn->hw_info.feat_num[QED_FCOE_CQ]);
    125		rc = -EINVAL;
    126		goto err;
    127	}
    128
    129	p_data->mtu = cpu_to_le16(fcoe_pf_params->mtu);
    130	tmp = cpu_to_le16(fcoe_pf_params->sq_num_pbl_pages);
    131	p_data->sq_num_pages_in_pbl = tmp;
    132
    133	rc = qed_cxt_acquire_cid(p_hwfn, PROTOCOLID_FCOE, &dummy_cid);
    134	if (rc)
    135		goto err;
    136
    137	cxt_info.iid = dummy_cid;
    138	rc = qed_cxt_get_cid_info(p_hwfn, &cxt_info);
    139	if (rc) {
    140		DP_NOTICE(p_hwfn, "Cannot find context info for dummy cid=%d\n",
    141			  dummy_cid);
    142		goto err;
    143	}
    144	p_cxt = cxt_info.p_cxt;
    145	memset(p_cxt, 0, sizeof(*p_cxt));
    146
    147	SET_FIELD(p_cxt->tstorm_ag_context.flags3,
    148		  TSTORM_FCOE_CONN_AG_CTX_DUMMY_TIMER_CF_EN, 1);
    149
    150	fcoe_pf_params->dummy_icid = (u16)dummy_cid;
    151
    152	tmp = cpu_to_le16(fcoe_pf_params->num_tasks);
    153	p_data->func_params.num_tasks = tmp;
    154	p_data->func_params.log_page_size = fcoe_pf_params->log_page_size;
    155	p_data->func_params.debug_mode = fcoe_pf_params->debug_mode;
    156
    157	DMA_REGPAIR_LE(p_data->q_params.glbl_q_params_addr,
    158		       fcoe_pf_params->glbl_q_params_addr);
    159
    160	tmp = cpu_to_le16(fcoe_pf_params->cq_num_entries);
    161	p_data->q_params.cq_num_entries = tmp;
    162
    163	tmp = cpu_to_le16(fcoe_pf_params->cmdq_num_entries);
    164	p_data->q_params.cmdq_num_entries = tmp;
    165
    166	p_data->q_params.num_queues = fcoe_pf_params->num_cqs;
    167
    168	tmp = (__force __le16)p_hwfn->hw_info.resc_start[QED_CMDQS_CQS];
    169	p_data->q_params.queue_relative_offset = (__force u8)tmp;
    170
    171	for (i = 0; i < fcoe_pf_params->num_cqs; i++) {
    172		tmp = cpu_to_le16(qed_get_igu_sb_id(p_hwfn, i));
    173		p_data->q_params.cq_cmdq_sb_num_arr[i] = tmp;
    174	}
    175
    176	p_data->q_params.cq_sb_pi = fcoe_pf_params->gl_rq_pi;
    177	p_data->q_params.cmdq_sb_pi = fcoe_pf_params->gl_cmd_pi;
    178
    179	p_data->q_params.bdq_resource_id = (u8)RESC_START(p_hwfn, QED_BDQ);
    180
    181	DMA_REGPAIR_LE(p_data->q_params.bdq_pbl_base_address[BDQ_ID_RQ],
    182		       fcoe_pf_params->bdq_pbl_base_addr[BDQ_ID_RQ]);
    183	p_data->q_params.bdq_pbl_num_entries[BDQ_ID_RQ] =
    184	    fcoe_pf_params->bdq_pbl_num_entries[BDQ_ID_RQ];
    185	tmp = cpu_to_le16(fcoe_pf_params->bdq_xoff_threshold[BDQ_ID_RQ]);
    186	p_data->q_params.bdq_xoff_threshold[BDQ_ID_RQ] = tmp;
    187	tmp = cpu_to_le16(fcoe_pf_params->bdq_xon_threshold[BDQ_ID_RQ]);
    188	p_data->q_params.bdq_xon_threshold[BDQ_ID_RQ] = tmp;
    189
    190	DMA_REGPAIR_LE(p_data->q_params.bdq_pbl_base_address[BDQ_ID_IMM_DATA],
    191		       fcoe_pf_params->bdq_pbl_base_addr[BDQ_ID_IMM_DATA]);
    192	p_data->q_params.bdq_pbl_num_entries[BDQ_ID_IMM_DATA] =
    193	    fcoe_pf_params->bdq_pbl_num_entries[BDQ_ID_IMM_DATA];
    194	tmp = cpu_to_le16(fcoe_pf_params->bdq_xoff_threshold[BDQ_ID_IMM_DATA]);
    195	p_data->q_params.bdq_xoff_threshold[BDQ_ID_IMM_DATA] = tmp;
    196	tmp = cpu_to_le16(fcoe_pf_params->bdq_xon_threshold[BDQ_ID_IMM_DATA]);
    197	p_data->q_params.bdq_xon_threshold[BDQ_ID_IMM_DATA] = tmp;
    198	tmp = cpu_to_le16(fcoe_pf_params->rq_buffer_size);
    199	p_data->q_params.rq_buffer_size = tmp;
    200
    201	if (fcoe_pf_params->is_target) {
    202		SET_FIELD(p_data->q_params.q_validity,
    203			  SCSI_INIT_FUNC_QUEUES_RQ_VALID, 1);
    204		if (p_data->q_params.bdq_pbl_num_entries[BDQ_ID_IMM_DATA])
    205			SET_FIELD(p_data->q_params.q_validity,
    206				  SCSI_INIT_FUNC_QUEUES_IMM_DATA_VALID, 1);
    207		SET_FIELD(p_data->q_params.q_validity,
    208			  SCSI_INIT_FUNC_QUEUES_CMD_VALID, 1);
    209	} else {
    210		SET_FIELD(p_data->q_params.q_validity,
    211			  SCSI_INIT_FUNC_QUEUES_RQ_VALID, 1);
    212	}
    213
    214	rc = qed_spq_post(p_hwfn, p_ent, NULL);
    215
    216	return rc;
    217
    218err:
    219	qed_sp_destroy_request(p_hwfn, p_ent);
    220	return rc;
    221}
    222
    223static int
    224qed_sp_fcoe_conn_offload(struct qed_hwfn *p_hwfn,
    225			 struct qed_fcoe_conn *p_conn,
    226			 enum spq_mode comp_mode,
    227			 struct qed_spq_comp_cb *p_comp_addr)
    228{
    229	struct fcoe_conn_offload_ramrod_params *p_ramrod = NULL;
    230	struct fcoe_conn_offload_ramrod_data *p_data;
    231	struct qed_spq_entry *p_ent = NULL;
    232	struct qed_sp_init_data init_data;
    233	u16 physical_q0;
    234	__le16 tmp;
    235	int rc;
    236
    237	/* Get SPQ entry */
    238	memset(&init_data, 0, sizeof(init_data));
    239	init_data.cid = p_conn->icid;
    240	init_data.opaque_fid = p_hwfn->hw_info.opaque_fid;
    241	init_data.comp_mode = comp_mode;
    242	init_data.p_comp_data = p_comp_addr;
    243
    244	rc = qed_sp_init_request(p_hwfn, &p_ent,
    245				 FCOE_RAMROD_CMD_ID_OFFLOAD_CONN,
    246				 PROTOCOLID_FCOE, &init_data);
    247	if (rc)
    248		return rc;
    249
    250	p_ramrod = &p_ent->ramrod.fcoe_conn_ofld;
    251	p_data = &p_ramrod->offload_ramrod_data;
    252
    253	/* Transmission PQ is the first of the PF */
    254	physical_q0 = qed_get_cm_pq_idx(p_hwfn, PQ_FLAGS_OFLD);
    255	p_conn->physical_q0 = physical_q0;
    256	p_data->physical_q0 = cpu_to_le16(physical_q0);
    257
    258	p_data->conn_id = cpu_to_le16(p_conn->conn_id);
    259	DMA_REGPAIR_LE(p_data->sq_pbl_addr, p_conn->sq_pbl_addr);
    260	DMA_REGPAIR_LE(p_data->sq_curr_page_addr, p_conn->sq_curr_page_addr);
    261	DMA_REGPAIR_LE(p_data->sq_next_page_addr, p_conn->sq_next_page_addr);
    262	DMA_REGPAIR_LE(p_data->xferq_pbl_addr, p_conn->xferq_pbl_addr);
    263	DMA_REGPAIR_LE(p_data->xferq_curr_page_addr, p_conn->xferq_addr[0]);
    264	DMA_REGPAIR_LE(p_data->xferq_next_page_addr, p_conn->xferq_addr[1]);
    265
    266	DMA_REGPAIR_LE(p_data->respq_pbl_addr, p_conn->confq_pbl_addr);
    267	DMA_REGPAIR_LE(p_data->respq_curr_page_addr, p_conn->confq_addr[0]);
    268	DMA_REGPAIR_LE(p_data->respq_next_page_addr, p_conn->confq_addr[1]);
    269
    270	p_data->dst_mac_addr_lo = cpu_to_le16(p_conn->dst_mac_addr_lo);
    271	p_data->dst_mac_addr_mid = cpu_to_le16(p_conn->dst_mac_addr_mid);
    272	p_data->dst_mac_addr_hi = cpu_to_le16(p_conn->dst_mac_addr_hi);
    273	p_data->src_mac_addr_lo = cpu_to_le16(p_conn->src_mac_addr_lo);
    274	p_data->src_mac_addr_mid = cpu_to_le16(p_conn->src_mac_addr_mid);
    275	p_data->src_mac_addr_hi = cpu_to_le16(p_conn->src_mac_addr_hi);
    276
    277	tmp = cpu_to_le16(p_conn->tx_max_fc_pay_len);
    278	p_data->tx_max_fc_pay_len = tmp;
    279	tmp = cpu_to_le16(p_conn->e_d_tov_timer_val);
    280	p_data->e_d_tov_timer_val = tmp;
    281	tmp = cpu_to_le16(p_conn->rec_tov_timer_val);
    282	p_data->rec_rr_tov_timer_val = tmp;
    283	tmp = cpu_to_le16(p_conn->rx_max_fc_pay_len);
    284	p_data->rx_max_fc_pay_len = tmp;
    285
    286	p_data->vlan_tag = cpu_to_le16(p_conn->vlan_tag);
    287	p_data->s_id.addr_hi = p_conn->s_id.addr_hi;
    288	p_data->s_id.addr_mid = p_conn->s_id.addr_mid;
    289	p_data->s_id.addr_lo = p_conn->s_id.addr_lo;
    290	p_data->max_conc_seqs_c3 = p_conn->max_conc_seqs_c3;
    291	p_data->d_id.addr_hi = p_conn->d_id.addr_hi;
    292	p_data->d_id.addr_mid = p_conn->d_id.addr_mid;
    293	p_data->d_id.addr_lo = p_conn->d_id.addr_lo;
    294	p_data->flags = p_conn->flags;
    295	if (test_bit(QED_MF_UFP_SPECIFIC, &p_hwfn->cdev->mf_bits))
    296		SET_FIELD(p_data->flags,
    297			  FCOE_CONN_OFFLOAD_RAMROD_DATA_B_SINGLE_VLAN, 1);
    298	p_data->def_q_idx = p_conn->def_q_idx;
    299
    300	return qed_spq_post(p_hwfn, p_ent, NULL);
    301}
    302
    303static int
    304qed_sp_fcoe_conn_destroy(struct qed_hwfn *p_hwfn,
    305			 struct qed_fcoe_conn *p_conn,
    306			 enum spq_mode comp_mode,
    307			 struct qed_spq_comp_cb *p_comp_addr)
    308{
    309	struct fcoe_conn_terminate_ramrod_params *p_ramrod = NULL;
    310	struct qed_spq_entry *p_ent = NULL;
    311	struct qed_sp_init_data init_data;
    312	int rc = 0;
    313
    314	/* Get SPQ entry */
    315	memset(&init_data, 0, sizeof(init_data));
    316	init_data.cid = p_conn->icid;
    317	init_data.opaque_fid = p_hwfn->hw_info.opaque_fid;
    318	init_data.comp_mode = comp_mode;
    319	init_data.p_comp_data = p_comp_addr;
    320
    321	rc = qed_sp_init_request(p_hwfn, &p_ent,
    322				 FCOE_RAMROD_CMD_ID_TERMINATE_CONN,
    323				 PROTOCOLID_FCOE, &init_data);
    324	if (rc)
    325		return rc;
    326
    327	p_ramrod = &p_ent->ramrod.fcoe_conn_terminate;
    328	DMA_REGPAIR_LE(p_ramrod->terminate_ramrod_data.terminate_params_addr,
    329		       p_conn->terminate_params);
    330
    331	return qed_spq_post(p_hwfn, p_ent, NULL);
    332}
    333
    334static int
    335qed_sp_fcoe_func_stop(struct qed_hwfn *p_hwfn,
    336		      struct qed_ptt *p_ptt,
    337		      enum spq_mode comp_mode,
    338		      struct qed_spq_comp_cb *p_comp_addr)
    339{
    340	struct qed_spq_entry *p_ent = NULL;
    341	struct qed_sp_init_data init_data;
    342	u32 active_segs = 0;
    343	int rc = 0;
    344
    345	/* Get SPQ entry */
    346	memset(&init_data, 0, sizeof(init_data));
    347	init_data.cid = p_hwfn->pf_params.fcoe_pf_params.dummy_icid;
    348	init_data.opaque_fid = p_hwfn->hw_info.opaque_fid;
    349	init_data.comp_mode = comp_mode;
    350	init_data.p_comp_data = p_comp_addr;
    351
    352	rc = qed_sp_init_request(p_hwfn, &p_ent,
    353				 FCOE_RAMROD_CMD_ID_DESTROY_FUNC,
    354				 PROTOCOLID_FCOE, &init_data);
    355	if (rc)
    356		return rc;
    357
    358	active_segs = qed_rd(p_hwfn, p_ptt, TM_REG_PF_ENABLE_TASK);
    359	active_segs &= ~BIT(QED_CXT_FCOE_TID_SEG);
    360	qed_wr(p_hwfn, p_ptt, TM_REG_PF_ENABLE_TASK, active_segs);
    361
    362	return qed_spq_post(p_hwfn, p_ent, NULL);
    363}
    364
    365static int
    366qed_fcoe_allocate_connection(struct qed_hwfn *p_hwfn,
    367			     struct qed_fcoe_conn **p_out_conn)
    368{
    369	struct qed_fcoe_conn *p_conn = NULL;
    370	void *p_addr;
    371	u32 i;
    372
    373	spin_lock_bh(&p_hwfn->p_fcoe_info->lock);
    374	if (!list_empty(&p_hwfn->p_fcoe_info->free_list))
    375		p_conn =
    376		    list_first_entry(&p_hwfn->p_fcoe_info->free_list,
    377				     struct qed_fcoe_conn, list_entry);
    378	if (p_conn) {
    379		list_del(&p_conn->list_entry);
    380		spin_unlock_bh(&p_hwfn->p_fcoe_info->lock);
    381		*p_out_conn = p_conn;
    382		return 0;
    383	}
    384	spin_unlock_bh(&p_hwfn->p_fcoe_info->lock);
    385
    386	p_conn = kzalloc(sizeof(*p_conn), GFP_KERNEL);
    387	if (!p_conn)
    388		return -ENOMEM;
    389
    390	p_addr = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev,
    391				    QED_CHAIN_PAGE_SIZE,
    392				    &p_conn->xferq_pbl_addr, GFP_KERNEL);
    393	if (!p_addr)
    394		goto nomem_pbl_xferq;
    395	p_conn->xferq_pbl_addr_virt_addr = p_addr;
    396
    397	for (i = 0; i < ARRAY_SIZE(p_conn->xferq_addr); i++) {
    398		p_addr = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev,
    399					    QED_CHAIN_PAGE_SIZE,
    400					    &p_conn->xferq_addr[i], GFP_KERNEL);
    401		if (!p_addr)
    402			goto nomem_xferq;
    403		p_conn->xferq_addr_virt_addr[i] = p_addr;
    404
    405		p_addr = p_conn->xferq_pbl_addr_virt_addr;
    406		((dma_addr_t *)p_addr)[i] = p_conn->xferq_addr[i];
    407	}
    408
    409	p_addr = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev,
    410				    QED_CHAIN_PAGE_SIZE,
    411				    &p_conn->confq_pbl_addr, GFP_KERNEL);
    412	if (!p_addr)
    413		goto nomem_xferq;
    414	p_conn->confq_pbl_addr_virt_addr = p_addr;
    415
    416	for (i = 0; i < ARRAY_SIZE(p_conn->confq_addr); i++) {
    417		p_addr = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev,
    418					    QED_CHAIN_PAGE_SIZE,
    419					    &p_conn->confq_addr[i], GFP_KERNEL);
    420		if (!p_addr)
    421			goto nomem_confq;
    422		p_conn->confq_addr_virt_addr[i] = p_addr;
    423
    424		p_addr = p_conn->confq_pbl_addr_virt_addr;
    425		((dma_addr_t *)p_addr)[i] = p_conn->confq_addr[i];
    426	}
    427
    428	p_conn->free_on_delete = true;
    429	*p_out_conn = p_conn;
    430	return 0;
    431
    432nomem_confq:
    433	dma_free_coherent(&p_hwfn->cdev->pdev->dev,
    434			  QED_CHAIN_PAGE_SIZE,
    435			  p_conn->confq_pbl_addr_virt_addr,
    436			  p_conn->confq_pbl_addr);
    437	for (i = 0; i < ARRAY_SIZE(p_conn->confq_addr); i++)
    438		if (p_conn->confq_addr_virt_addr[i])
    439			dma_free_coherent(&p_hwfn->cdev->pdev->dev,
    440					  QED_CHAIN_PAGE_SIZE,
    441					  p_conn->confq_addr_virt_addr[i],
    442					  p_conn->confq_addr[i]);
    443nomem_xferq:
    444	dma_free_coherent(&p_hwfn->cdev->pdev->dev,
    445			  QED_CHAIN_PAGE_SIZE,
    446			  p_conn->xferq_pbl_addr_virt_addr,
    447			  p_conn->xferq_pbl_addr);
    448	for (i = 0; i < ARRAY_SIZE(p_conn->xferq_addr); i++)
    449		if (p_conn->xferq_addr_virt_addr[i])
    450			dma_free_coherent(&p_hwfn->cdev->pdev->dev,
    451					  QED_CHAIN_PAGE_SIZE,
    452					  p_conn->xferq_addr_virt_addr[i],
    453					  p_conn->xferq_addr[i]);
    454nomem_pbl_xferq:
    455	kfree(p_conn);
    456	return -ENOMEM;
    457}
    458
    459static void qed_fcoe_free_connection(struct qed_hwfn *p_hwfn,
    460				     struct qed_fcoe_conn *p_conn)
    461{
    462	u32 i;
    463
    464	if (!p_conn)
    465		return;
    466
    467	if (p_conn->confq_pbl_addr_virt_addr)
    468		dma_free_coherent(&p_hwfn->cdev->pdev->dev,
    469				  QED_CHAIN_PAGE_SIZE,
    470				  p_conn->confq_pbl_addr_virt_addr,
    471				  p_conn->confq_pbl_addr);
    472
    473	for (i = 0; i < ARRAY_SIZE(p_conn->confq_addr); i++) {
    474		if (!p_conn->confq_addr_virt_addr[i])
    475			continue;
    476		dma_free_coherent(&p_hwfn->cdev->pdev->dev,
    477				  QED_CHAIN_PAGE_SIZE,
    478				  p_conn->confq_addr_virt_addr[i],
    479				  p_conn->confq_addr[i]);
    480	}
    481
    482	if (p_conn->xferq_pbl_addr_virt_addr)
    483		dma_free_coherent(&p_hwfn->cdev->pdev->dev,
    484				  QED_CHAIN_PAGE_SIZE,
    485				  p_conn->xferq_pbl_addr_virt_addr,
    486				  p_conn->xferq_pbl_addr);
    487
    488	for (i = 0; i < ARRAY_SIZE(p_conn->xferq_addr); i++) {
    489		if (!p_conn->xferq_addr_virt_addr[i])
    490			continue;
    491		dma_free_coherent(&p_hwfn->cdev->pdev->dev,
    492				  QED_CHAIN_PAGE_SIZE,
    493				  p_conn->xferq_addr_virt_addr[i],
    494				  p_conn->xferq_addr[i]);
    495	}
    496	kfree(p_conn);
    497}
    498
    499static void __iomem *qed_fcoe_get_db_addr(struct qed_hwfn *p_hwfn, u32 cid)
    500{
    501	return (u8 __iomem *)p_hwfn->doorbells +
    502	       qed_db_addr(cid, DQ_DEMS_LEGACY);
    503}
    504
    505static void __iomem *qed_fcoe_get_primary_bdq_prod(struct qed_hwfn *p_hwfn,
    506						   u8 bdq_id)
    507{
    508	if (RESC_NUM(p_hwfn, QED_BDQ)) {
    509		return (u8 __iomem *)p_hwfn->regview +
    510		    GET_GTT_BDQ_REG_ADDR(GTT_BAR0_MAP_REG_MSDM_RAM,
    511					 MSTORM_SCSI_BDQ_EXT_PROD,
    512					 RESC_START(p_hwfn, QED_BDQ), bdq_id);
    513	} else {
    514		DP_NOTICE(p_hwfn, "BDQ is not allocated!\n");
    515		return NULL;
    516	}
    517}
    518
    519static void __iomem *qed_fcoe_get_secondary_bdq_prod(struct qed_hwfn *p_hwfn,
    520						     u8 bdq_id)
    521{
    522	if (RESC_NUM(p_hwfn, QED_BDQ)) {
    523		return (u8 __iomem *)p_hwfn->regview +
    524		    GET_GTT_BDQ_REG_ADDR(GTT_BAR0_MAP_REG_TSDM_RAM,
    525					 TSTORM_SCSI_BDQ_EXT_PROD,
    526					 RESC_START(p_hwfn, QED_BDQ), bdq_id);
    527	} else {
    528		DP_NOTICE(p_hwfn, "BDQ is not allocated!\n");
    529		return NULL;
    530	}
    531}
    532
    533int qed_fcoe_alloc(struct qed_hwfn *p_hwfn)
    534{
    535	struct qed_fcoe_info *p_fcoe_info;
    536
    537	/* Allocate LL2's set struct */
    538	p_fcoe_info = kzalloc(sizeof(*p_fcoe_info), GFP_KERNEL);
    539	if (!p_fcoe_info) {
    540		DP_NOTICE(p_hwfn, "Failed to allocate qed_fcoe_info'\n");
    541		return -ENOMEM;
    542	}
    543	INIT_LIST_HEAD(&p_fcoe_info->free_list);
    544
    545	p_hwfn->p_fcoe_info = p_fcoe_info;
    546	return 0;
    547}
    548
    549void qed_fcoe_setup(struct qed_hwfn *p_hwfn)
    550{
    551	struct fcoe_task_context *p_task_ctx = NULL;
    552	u32 i, lc;
    553	int rc;
    554
    555	spin_lock_init(&p_hwfn->p_fcoe_info->lock);
    556	for (i = 0; i < p_hwfn->pf_params.fcoe_pf_params.num_tasks; i++) {
    557		rc = qed_cxt_get_task_ctx(p_hwfn, i,
    558					  QED_CTX_WORKING_MEM,
    559					  (void **)&p_task_ctx);
    560		if (rc)
    561			continue;
    562
    563		memset(p_task_ctx, 0, sizeof(struct fcoe_task_context));
    564
    565		lc = 0;
    566		SET_FIELD(lc, TIMERS_CONTEXT_VALIDLC0, 1);
    567		p_task_ctx->timer_context.logical_client_0 = cpu_to_le32(lc);
    568
    569		lc = 0;
    570		SET_FIELD(lc, TIMERS_CONTEXT_VALIDLC1, 1);
    571		p_task_ctx->timer_context.logical_client_1 = cpu_to_le32(lc);
    572
    573		SET_FIELD(p_task_ctx->tstorm_ag_context.flags0,
    574			  TSTORM_FCOE_TASK_AG_CTX_CONNECTION_TYPE, 1);
    575	}
    576}
    577
    578void qed_fcoe_free(struct qed_hwfn *p_hwfn)
    579{
    580	struct qed_fcoe_conn *p_conn = NULL;
    581
    582	if (!p_hwfn->p_fcoe_info)
    583		return;
    584
    585	while (!list_empty(&p_hwfn->p_fcoe_info->free_list)) {
    586		p_conn = list_first_entry(&p_hwfn->p_fcoe_info->free_list,
    587					  struct qed_fcoe_conn, list_entry);
    588		if (!p_conn)
    589			break;
    590		list_del(&p_conn->list_entry);
    591		qed_fcoe_free_connection(p_hwfn, p_conn);
    592	}
    593
    594	kfree(p_hwfn->p_fcoe_info);
    595	p_hwfn->p_fcoe_info = NULL;
    596}
    597
    598static int
    599qed_fcoe_acquire_connection(struct qed_hwfn *p_hwfn,
    600			    struct qed_fcoe_conn *p_in_conn,
    601			    struct qed_fcoe_conn **p_out_conn)
    602{
    603	struct qed_fcoe_conn *p_conn = NULL;
    604	int rc = 0;
    605	u32 icid;
    606
    607	spin_lock_bh(&p_hwfn->p_fcoe_info->lock);
    608	rc = qed_cxt_acquire_cid(p_hwfn, PROTOCOLID_FCOE, &icid);
    609	spin_unlock_bh(&p_hwfn->p_fcoe_info->lock);
    610	if (rc)
    611		return rc;
    612
    613	/* Use input connection [if provided] or allocate a new one */
    614	if (p_in_conn) {
    615		p_conn = p_in_conn;
    616	} else {
    617		rc = qed_fcoe_allocate_connection(p_hwfn, &p_conn);
    618		if (rc) {
    619			spin_lock_bh(&p_hwfn->p_fcoe_info->lock);
    620			qed_cxt_release_cid(p_hwfn, icid);
    621			spin_unlock_bh(&p_hwfn->p_fcoe_info->lock);
    622			return rc;
    623		}
    624	}
    625
    626	p_conn->icid = icid;
    627	p_conn->fw_cid = (p_hwfn->hw_info.opaque_fid << 16) | icid;
    628	*p_out_conn = p_conn;
    629
    630	return rc;
    631}
    632
    633static void qed_fcoe_release_connection(struct qed_hwfn *p_hwfn,
    634					struct qed_fcoe_conn *p_conn)
    635{
    636	spin_lock_bh(&p_hwfn->p_fcoe_info->lock);
    637	list_add_tail(&p_conn->list_entry, &p_hwfn->p_fcoe_info->free_list);
    638	qed_cxt_release_cid(p_hwfn, p_conn->icid);
    639	spin_unlock_bh(&p_hwfn->p_fcoe_info->lock);
    640}
    641
    642static void _qed_fcoe_get_tstats(struct qed_hwfn *p_hwfn,
    643				 struct qed_ptt *p_ptt,
    644				 struct qed_fcoe_stats *p_stats)
    645{
    646	struct fcoe_rx_stat tstats;
    647	u32 tstats_addr;
    648
    649	memset(&tstats, 0, sizeof(tstats));
    650	tstats_addr = BAR0_MAP_REG_TSDM_RAM +
    651	    TSTORM_FCOE_RX_STATS_OFFSET(p_hwfn->rel_pf_id);
    652	qed_memcpy_from(p_hwfn, p_ptt, &tstats, tstats_addr, sizeof(tstats));
    653
    654	p_stats->fcoe_rx_byte_cnt = HILO_64_REGPAIR(tstats.fcoe_rx_byte_cnt);
    655	p_stats->fcoe_rx_data_pkt_cnt =
    656	    HILO_64_REGPAIR(tstats.fcoe_rx_data_pkt_cnt);
    657	p_stats->fcoe_rx_xfer_pkt_cnt =
    658	    HILO_64_REGPAIR(tstats.fcoe_rx_xfer_pkt_cnt);
    659	p_stats->fcoe_rx_other_pkt_cnt =
    660	    HILO_64_REGPAIR(tstats.fcoe_rx_other_pkt_cnt);
    661
    662	p_stats->fcoe_silent_drop_pkt_cmdq_full_cnt =
    663	    le32_to_cpu(tstats.fcoe_silent_drop_pkt_cmdq_full_cnt);
    664	p_stats->fcoe_silent_drop_pkt_rq_full_cnt =
    665	    le32_to_cpu(tstats.fcoe_silent_drop_pkt_rq_full_cnt);
    666	p_stats->fcoe_silent_drop_pkt_crc_error_cnt =
    667	    le32_to_cpu(tstats.fcoe_silent_drop_pkt_crc_error_cnt);
    668	p_stats->fcoe_silent_drop_pkt_task_invalid_cnt =
    669	    le32_to_cpu(tstats.fcoe_silent_drop_pkt_task_invalid_cnt);
    670	p_stats->fcoe_silent_drop_total_pkt_cnt =
    671	    le32_to_cpu(tstats.fcoe_silent_drop_total_pkt_cnt);
    672}
    673
    674static void _qed_fcoe_get_pstats(struct qed_hwfn *p_hwfn,
    675				 struct qed_ptt *p_ptt,
    676				 struct qed_fcoe_stats *p_stats)
    677{
    678	struct fcoe_tx_stat pstats;
    679	u32 pstats_addr;
    680
    681	memset(&pstats, 0, sizeof(pstats));
    682	pstats_addr = BAR0_MAP_REG_PSDM_RAM +
    683	    PSTORM_FCOE_TX_STATS_OFFSET(p_hwfn->rel_pf_id);
    684	qed_memcpy_from(p_hwfn, p_ptt, &pstats, pstats_addr, sizeof(pstats));
    685
    686	p_stats->fcoe_tx_byte_cnt = HILO_64_REGPAIR(pstats.fcoe_tx_byte_cnt);
    687	p_stats->fcoe_tx_data_pkt_cnt =
    688	    HILO_64_REGPAIR(pstats.fcoe_tx_data_pkt_cnt);
    689	p_stats->fcoe_tx_xfer_pkt_cnt =
    690	    HILO_64_REGPAIR(pstats.fcoe_tx_xfer_pkt_cnt);
    691	p_stats->fcoe_tx_other_pkt_cnt =
    692	    HILO_64_REGPAIR(pstats.fcoe_tx_other_pkt_cnt);
    693}
    694
    695static int qed_fcoe_get_stats(struct qed_hwfn *p_hwfn,
    696			      struct qed_fcoe_stats *p_stats)
    697{
    698	struct qed_ptt *p_ptt;
    699
    700	memset(p_stats, 0, sizeof(*p_stats));
    701
    702	p_ptt = qed_ptt_acquire(p_hwfn);
    703
    704	if (!p_ptt) {
    705		DP_ERR(p_hwfn, "Failed to acquire ptt\n");
    706		return -EINVAL;
    707	}
    708
    709	_qed_fcoe_get_tstats(p_hwfn, p_ptt, p_stats);
    710	_qed_fcoe_get_pstats(p_hwfn, p_ptt, p_stats);
    711
    712	qed_ptt_release(p_hwfn, p_ptt);
    713
    714	return 0;
    715}
    716
    717struct qed_hash_fcoe_con {
    718	struct hlist_node node;
    719	struct qed_fcoe_conn *con;
    720};
    721
    722static int qed_fill_fcoe_dev_info(struct qed_dev *cdev,
    723				  struct qed_dev_fcoe_info *info)
    724{
    725	struct qed_hwfn *hwfn = QED_AFFIN_HWFN(cdev);
    726	int rc;
    727
    728	memset(info, 0, sizeof(*info));
    729	rc = qed_fill_dev_info(cdev, &info->common);
    730
    731	info->primary_dbq_rq_addr =
    732	    qed_fcoe_get_primary_bdq_prod(hwfn, BDQ_ID_RQ);
    733	info->secondary_bdq_rq_addr =
    734	    qed_fcoe_get_secondary_bdq_prod(hwfn, BDQ_ID_RQ);
    735
    736	info->wwpn = hwfn->mcp_info->func_info.wwn_port;
    737	info->wwnn = hwfn->mcp_info->func_info.wwn_node;
    738
    739	info->num_cqs = FEAT_NUM(hwfn, QED_FCOE_CQ);
    740
    741	return rc;
    742}
    743
    744static void qed_register_fcoe_ops(struct qed_dev *cdev,
    745				  struct qed_fcoe_cb_ops *ops, void *cookie)
    746{
    747	cdev->protocol_ops.fcoe = ops;
    748	cdev->ops_cookie = cookie;
    749}
    750
    751static struct qed_hash_fcoe_con *qed_fcoe_get_hash(struct qed_dev *cdev,
    752						   u32 handle)
    753{
    754	struct qed_hash_fcoe_con *hash_con = NULL;
    755
    756	if (!(cdev->flags & QED_FLAG_STORAGE_STARTED))
    757		return NULL;
    758
    759	hash_for_each_possible(cdev->connections, hash_con, node, handle) {
    760		if (hash_con->con->icid == handle)
    761			break;
    762	}
    763
    764	if (!hash_con || (hash_con->con->icid != handle))
    765		return NULL;
    766
    767	return hash_con;
    768}
    769
    770static int qed_fcoe_stop(struct qed_dev *cdev)
    771{
    772	struct qed_ptt *p_ptt;
    773	int rc;
    774
    775	if (!(cdev->flags & QED_FLAG_STORAGE_STARTED)) {
    776		DP_NOTICE(cdev, "fcoe already stopped\n");
    777		return 0;
    778	}
    779
    780	if (!hash_empty(cdev->connections)) {
    781		DP_NOTICE(cdev,
    782			  "Can't stop fcoe - not all connections were returned\n");
    783		return -EINVAL;
    784	}
    785
    786	p_ptt = qed_ptt_acquire(QED_AFFIN_HWFN(cdev));
    787	if (!p_ptt)
    788		return -EAGAIN;
    789
    790	/* Stop the fcoe */
    791	rc = qed_sp_fcoe_func_stop(QED_AFFIN_HWFN(cdev), p_ptt,
    792				   QED_SPQ_MODE_EBLOCK, NULL);
    793	cdev->flags &= ~QED_FLAG_STORAGE_STARTED;
    794	qed_ptt_release(QED_AFFIN_HWFN(cdev), p_ptt);
    795
    796	return rc;
    797}
    798
    799static int qed_fcoe_start(struct qed_dev *cdev, struct qed_fcoe_tid *tasks)
    800{
    801	int rc;
    802
    803	if (cdev->flags & QED_FLAG_STORAGE_STARTED) {
    804		DP_NOTICE(cdev, "fcoe already started;\n");
    805		return 0;
    806	}
    807
    808	rc = qed_sp_fcoe_func_start(QED_AFFIN_HWFN(cdev), QED_SPQ_MODE_EBLOCK,
    809				    NULL);
    810	if (rc) {
    811		DP_NOTICE(cdev, "Failed to start fcoe\n");
    812		return rc;
    813	}
    814
    815	cdev->flags |= QED_FLAG_STORAGE_STARTED;
    816	hash_init(cdev->connections);
    817
    818	if (tasks) {
    819		struct qed_tid_mem *tid_info = kzalloc(sizeof(*tid_info),
    820						       GFP_ATOMIC);
    821
    822		if (!tid_info) {
    823			DP_NOTICE(cdev,
    824				  "Failed to allocate tasks information\n");
    825			qed_fcoe_stop(cdev);
    826			return -ENOMEM;
    827		}
    828
    829		rc = qed_cxt_get_tid_mem_info(QED_AFFIN_HWFN(cdev), tid_info);
    830		if (rc) {
    831			DP_NOTICE(cdev, "Failed to gather task information\n");
    832			qed_fcoe_stop(cdev);
    833			kfree(tid_info);
    834			return rc;
    835		}
    836
    837		/* Fill task information */
    838		tasks->size = tid_info->tid_size;
    839		tasks->num_tids_per_block = tid_info->num_tids_per_block;
    840		memcpy(tasks->blocks, tid_info->blocks,
    841		       MAX_TID_BLOCKS_FCOE * sizeof(u8 *));
    842
    843		kfree(tid_info);
    844	}
    845
    846	return 0;
    847}
    848
    849static int qed_fcoe_acquire_conn(struct qed_dev *cdev,
    850				 u32 *handle,
    851				 u32 *fw_cid, void __iomem **p_doorbell)
    852{
    853	struct qed_hash_fcoe_con *hash_con;
    854	int rc;
    855
    856	/* Allocate a hashed connection */
    857	hash_con = kzalloc(sizeof(*hash_con), GFP_KERNEL);
    858	if (!hash_con) {
    859		DP_NOTICE(cdev, "Failed to allocate hashed connection\n");
    860		return -ENOMEM;
    861	}
    862
    863	/* Acquire the connection */
    864	rc = qed_fcoe_acquire_connection(QED_AFFIN_HWFN(cdev), NULL,
    865					 &hash_con->con);
    866	if (rc) {
    867		DP_NOTICE(cdev, "Failed to acquire Connection\n");
    868		kfree(hash_con);
    869		return rc;
    870	}
    871
    872	/* Added the connection to hash table */
    873	*handle = hash_con->con->icid;
    874	*fw_cid = hash_con->con->fw_cid;
    875	hash_add(cdev->connections, &hash_con->node, *handle);
    876
    877	if (p_doorbell)
    878		*p_doorbell = qed_fcoe_get_db_addr(QED_AFFIN_HWFN(cdev),
    879						   *handle);
    880
    881	return 0;
    882}
    883
    884static int qed_fcoe_release_conn(struct qed_dev *cdev, u32 handle)
    885{
    886	struct qed_hash_fcoe_con *hash_con;
    887
    888	hash_con = qed_fcoe_get_hash(cdev, handle);
    889	if (!hash_con) {
    890		DP_NOTICE(cdev, "Failed to find connection for handle %d\n",
    891			  handle);
    892		return -EINVAL;
    893	}
    894
    895	hlist_del(&hash_con->node);
    896	qed_fcoe_release_connection(QED_AFFIN_HWFN(cdev), hash_con->con);
    897	kfree(hash_con);
    898
    899	return 0;
    900}
    901
    902static int qed_fcoe_offload_conn(struct qed_dev *cdev,
    903				 u32 handle,
    904				 struct qed_fcoe_params_offload *conn_info)
    905{
    906	struct qed_hash_fcoe_con *hash_con;
    907	struct qed_fcoe_conn *con;
    908
    909	hash_con = qed_fcoe_get_hash(cdev, handle);
    910	if (!hash_con) {
    911		DP_NOTICE(cdev, "Failed to find connection for handle %d\n",
    912			  handle);
    913		return -EINVAL;
    914	}
    915
    916	/* Update the connection with information from the params */
    917	con = hash_con->con;
    918
    919	con->sq_pbl_addr = conn_info->sq_pbl_addr;
    920	con->sq_curr_page_addr = conn_info->sq_curr_page_addr;
    921	con->sq_next_page_addr = conn_info->sq_next_page_addr;
    922	con->tx_max_fc_pay_len = conn_info->tx_max_fc_pay_len;
    923	con->e_d_tov_timer_val = conn_info->e_d_tov_timer_val;
    924	con->rec_tov_timer_val = conn_info->rec_tov_timer_val;
    925	con->rx_max_fc_pay_len = conn_info->rx_max_fc_pay_len;
    926	con->vlan_tag = conn_info->vlan_tag;
    927	con->max_conc_seqs_c3 = conn_info->max_conc_seqs_c3;
    928	con->flags = conn_info->flags;
    929	con->def_q_idx = conn_info->def_q_idx;
    930
    931	con->src_mac_addr_hi = (conn_info->src_mac[5] << 8) |
    932	    conn_info->src_mac[4];
    933	con->src_mac_addr_mid = (conn_info->src_mac[3] << 8) |
    934	    conn_info->src_mac[2];
    935	con->src_mac_addr_lo = (conn_info->src_mac[1] << 8) |
    936	    conn_info->src_mac[0];
    937	con->dst_mac_addr_hi = (conn_info->dst_mac[5] << 8) |
    938	    conn_info->dst_mac[4];
    939	con->dst_mac_addr_mid = (conn_info->dst_mac[3] << 8) |
    940	    conn_info->dst_mac[2];
    941	con->dst_mac_addr_lo = (conn_info->dst_mac[1] << 8) |
    942	    conn_info->dst_mac[0];
    943
    944	con->s_id.addr_hi = conn_info->s_id.addr_hi;
    945	con->s_id.addr_mid = conn_info->s_id.addr_mid;
    946	con->s_id.addr_lo = conn_info->s_id.addr_lo;
    947	con->d_id.addr_hi = conn_info->d_id.addr_hi;
    948	con->d_id.addr_mid = conn_info->d_id.addr_mid;
    949	con->d_id.addr_lo = conn_info->d_id.addr_lo;
    950
    951	return qed_sp_fcoe_conn_offload(QED_AFFIN_HWFN(cdev), con,
    952					QED_SPQ_MODE_EBLOCK, NULL);
    953}
    954
    955static int qed_fcoe_destroy_conn(struct qed_dev *cdev,
    956				 u32 handle, dma_addr_t terminate_params)
    957{
    958	struct qed_hash_fcoe_con *hash_con;
    959	struct qed_fcoe_conn *con;
    960
    961	hash_con = qed_fcoe_get_hash(cdev, handle);
    962	if (!hash_con) {
    963		DP_NOTICE(cdev, "Failed to find connection for handle %d\n",
    964			  handle);
    965		return -EINVAL;
    966	}
    967
    968	/* Update the connection with information from the params */
    969	con = hash_con->con;
    970	con->terminate_params = terminate_params;
    971
    972	return qed_sp_fcoe_conn_destroy(QED_AFFIN_HWFN(cdev), con,
    973					QED_SPQ_MODE_EBLOCK, NULL);
    974}
    975
    976static int qed_fcoe_stats(struct qed_dev *cdev, struct qed_fcoe_stats *stats)
    977{
    978	return qed_fcoe_get_stats(QED_AFFIN_HWFN(cdev), stats);
    979}
    980
    981void qed_get_protocol_stats_fcoe(struct qed_dev *cdev,
    982				 struct qed_mcp_fcoe_stats *stats)
    983{
    984	struct qed_fcoe_stats proto_stats;
    985
    986	/* Retrieve FW statistics */
    987	memset(&proto_stats, 0, sizeof(proto_stats));
    988	if (qed_fcoe_stats(cdev, &proto_stats)) {
    989		DP_VERBOSE(cdev, QED_MSG_STORAGE,
    990			   "Failed to collect FCoE statistics\n");
    991		return;
    992	}
    993
    994	/* Translate FW statistics into struct */
    995	stats->rx_pkts = proto_stats.fcoe_rx_data_pkt_cnt +
    996			 proto_stats.fcoe_rx_xfer_pkt_cnt +
    997			 proto_stats.fcoe_rx_other_pkt_cnt;
    998	stats->tx_pkts = proto_stats.fcoe_tx_data_pkt_cnt +
    999			 proto_stats.fcoe_tx_xfer_pkt_cnt +
   1000			 proto_stats.fcoe_tx_other_pkt_cnt;
   1001	stats->fcs_err = proto_stats.fcoe_silent_drop_pkt_crc_error_cnt;
   1002
   1003	/* Request protocol driver to fill-in the rest */
   1004	if (cdev->protocol_ops.fcoe && cdev->ops_cookie) {
   1005		struct qed_fcoe_cb_ops *ops = cdev->protocol_ops.fcoe;
   1006		void *cookie = cdev->ops_cookie;
   1007
   1008		if (ops->get_login_failures)
   1009			stats->login_failure = ops->get_login_failures(cookie);
   1010	}
   1011}
   1012
   1013static const struct qed_fcoe_ops qed_fcoe_ops_pass = {
   1014	.common = &qed_common_ops_pass,
   1015	.ll2 = &qed_ll2_ops_pass,
   1016	.fill_dev_info = &qed_fill_fcoe_dev_info,
   1017	.start = &qed_fcoe_start,
   1018	.stop = &qed_fcoe_stop,
   1019	.register_ops = &qed_register_fcoe_ops,
   1020	.acquire_conn = &qed_fcoe_acquire_conn,
   1021	.release_conn = &qed_fcoe_release_conn,
   1022	.offload_conn = &qed_fcoe_offload_conn,
   1023	.destroy_conn = &qed_fcoe_destroy_conn,
   1024	.get_stats = &qed_fcoe_stats,
   1025};
   1026
   1027const struct qed_fcoe_ops *qed_get_fcoe_ops(void)
   1028{
   1029	return &qed_fcoe_ops_pass;
   1030}
   1031EXPORT_SYMBOL(qed_get_fcoe_ops);
   1032
   1033void qed_put_fcoe_ops(void)
   1034{
   1035}
   1036EXPORT_SYMBOL(qed_put_fcoe_ops);