xref: /freebsd/sys/dev/qlnx/qlnxe/ecore_sriov.c (revision be909a79)
1217ec208SDavid C Somayajulu /*
2217ec208SDavid C Somayajulu  * Copyright (c) 2018-2019 Cavium, Inc.
3217ec208SDavid C Somayajulu  * All rights reserved.
4217ec208SDavid C Somayajulu  *
5217ec208SDavid C Somayajulu  *  Redistribution and use in source and binary forms, with or without
6217ec208SDavid C Somayajulu  *  modification, are permitted provided that the following conditions
7217ec208SDavid C Somayajulu  *  are met:
8217ec208SDavid C Somayajulu  *
9217ec208SDavid C Somayajulu  *  1. Redistributions of source code must retain the above copyright
10217ec208SDavid C Somayajulu  *     notice, this list of conditions and the following disclaimer.
11217ec208SDavid C Somayajulu  *  2. Redistributions in binary form must reproduce the above copyright
12217ec208SDavid C Somayajulu  *     notice, this list of conditions and the following disclaimer in the
13217ec208SDavid C Somayajulu  *     documentation and/or other materials provided with the distribution.
14217ec208SDavid C Somayajulu  *
15217ec208SDavid C Somayajulu  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16217ec208SDavid C Somayajulu  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17217ec208SDavid C Somayajulu  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18217ec208SDavid C Somayajulu  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19217ec208SDavid C Somayajulu  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20217ec208SDavid C Somayajulu  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21217ec208SDavid C Somayajulu  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22217ec208SDavid C Somayajulu  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23217ec208SDavid C Somayajulu  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24217ec208SDavid C Somayajulu  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25217ec208SDavid C Somayajulu  *  POSSIBILITY OF SUCH DAMAGE.
26217ec208SDavid C Somayajulu  */
27217ec208SDavid C Somayajulu 
28217ec208SDavid C Somayajulu #include <sys/cdefs.h>
29217ec208SDavid C Somayajulu #include "bcm_osal.h"
30217ec208SDavid C Somayajulu #include "ecore.h"
31217ec208SDavid C Somayajulu #include "reg_addr.h"
32217ec208SDavid C Somayajulu #include "ecore_sriov.h"
33217ec208SDavid C Somayajulu #include "ecore_status.h"
34217ec208SDavid C Somayajulu #include "ecore_hw.h"
35217ec208SDavid C Somayajulu #include "ecore_hw_defs.h"
36217ec208SDavid C Somayajulu #include "ecore_int.h"
37217ec208SDavid C Somayajulu #include "ecore_hsi_eth.h"
38217ec208SDavid C Somayajulu #include "ecore_l2.h"
39217ec208SDavid C Somayajulu #include "ecore_vfpf_if.h"
40217ec208SDavid C Somayajulu #include "ecore_rt_defs.h"
41217ec208SDavid C Somayajulu #include "ecore_init_ops.h"
42217ec208SDavid C Somayajulu #include "pcics_reg_driver.h"
43217ec208SDavid C Somayajulu #include "ecore_gtt_reg_addr.h"
44217ec208SDavid C Somayajulu #include "ecore_iro.h"
45217ec208SDavid C Somayajulu #include "ecore_mcp.h"
46217ec208SDavid C Somayajulu #include "ecore_cxt.h"
47217ec208SDavid C Somayajulu #include "ecore_vf.h"
48217ec208SDavid C Somayajulu #include "ecore_init_fw_funcs.h"
49217ec208SDavid C Somayajulu #include "ecore_sp_commands.h"
50217ec208SDavid C Somayajulu 
51217ec208SDavid C Somayajulu static enum _ecore_status_t ecore_sriov_eqe_event(struct ecore_hwfn *p_hwfn,
52217ec208SDavid C Somayajulu 						  u8 opcode,
53217ec208SDavid C Somayajulu 						  __le16 echo,
54217ec208SDavid C Somayajulu 						  union event_ring_data *data,
55217ec208SDavid C Somayajulu 						  u8 fw_return_code);
56217ec208SDavid C Somayajulu 
57217ec208SDavid C Somayajulu const char *ecore_channel_tlvs_string[] = {
58217ec208SDavid C Somayajulu 	"CHANNEL_TLV_NONE", /* ends tlv sequence */
59217ec208SDavid C Somayajulu 	"CHANNEL_TLV_ACQUIRE",
60217ec208SDavid C Somayajulu 	"CHANNEL_TLV_VPORT_START",
61217ec208SDavid C Somayajulu 	"CHANNEL_TLV_VPORT_UPDATE",
62217ec208SDavid C Somayajulu 	"CHANNEL_TLV_VPORT_TEARDOWN",
63217ec208SDavid C Somayajulu 	"CHANNEL_TLV_START_RXQ",
64217ec208SDavid C Somayajulu 	"CHANNEL_TLV_START_TXQ",
65217ec208SDavid C Somayajulu 	"CHANNEL_TLV_STOP_RXQ",
66217ec208SDavid C Somayajulu 	"CHANNEL_TLV_STOP_TXQ",
67217ec208SDavid C Somayajulu 	"CHANNEL_TLV_UPDATE_RXQ",
68217ec208SDavid C Somayajulu 	"CHANNEL_TLV_INT_CLEANUP",
69217ec208SDavid C Somayajulu 	"CHANNEL_TLV_CLOSE",
70217ec208SDavid C Somayajulu 	"CHANNEL_TLV_RELEASE",
71217ec208SDavid C Somayajulu 	"CHANNEL_TLV_LIST_END",
72217ec208SDavid C Somayajulu 	"CHANNEL_TLV_UCAST_FILTER",
73217ec208SDavid C Somayajulu 	"CHANNEL_TLV_VPORT_UPDATE_ACTIVATE",
74217ec208SDavid C Somayajulu 	"CHANNEL_TLV_VPORT_UPDATE_TX_SWITCH",
75217ec208SDavid C Somayajulu 	"CHANNEL_TLV_VPORT_UPDATE_VLAN_STRIP",
76217ec208SDavid C Somayajulu 	"CHANNEL_TLV_VPORT_UPDATE_MCAST",
77217ec208SDavid C Somayajulu 	"CHANNEL_TLV_VPORT_UPDATE_ACCEPT_PARAM",
78217ec208SDavid C Somayajulu 	"CHANNEL_TLV_VPORT_UPDATE_RSS",
79217ec208SDavid C Somayajulu 	"CHANNEL_TLV_VPORT_UPDATE_ACCEPT_ANY_VLAN",
80217ec208SDavid C Somayajulu 	"CHANNEL_TLV_VPORT_UPDATE_SGE_TPA",
81217ec208SDavid C Somayajulu 	"CHANNEL_TLV_UPDATE_TUNN_PARAM",
82217ec208SDavid C Somayajulu 	"CHANNEL_TLV_COALESCE_UPDATE",
83217ec208SDavid C Somayajulu 	"CHANNEL_TLV_QID",
84217ec208SDavid C Somayajulu 	"CHANNEL_TLV_COALESCE_READ",
85217ec208SDavid C Somayajulu 	"CHANNEL_TLV_MAX"
86217ec208SDavid C Somayajulu };
87217ec208SDavid C Somayajulu 
ecore_vf_calculate_legacy(struct ecore_vf_info * p_vf)88217ec208SDavid C Somayajulu static u8 ecore_vf_calculate_legacy(struct ecore_vf_info *p_vf)
89217ec208SDavid C Somayajulu {
90217ec208SDavid C Somayajulu 	u8 legacy = 0;
91217ec208SDavid C Somayajulu 
92217ec208SDavid C Somayajulu 	if (p_vf->acquire.vfdev_info.eth_fp_hsi_minor ==
93217ec208SDavid C Somayajulu 	    ETH_HSI_VER_NO_PKT_LEN_TUNN)
94217ec208SDavid C Somayajulu 		legacy |= ECORE_QCID_LEGACY_VF_RX_PROD;
95217ec208SDavid C Somayajulu 
96217ec208SDavid C Somayajulu 	if (!(p_vf->acquire.vfdev_info.capabilities &
97217ec208SDavid C Somayajulu 	     VFPF_ACQUIRE_CAP_QUEUE_QIDS))
98217ec208SDavid C Somayajulu 		legacy |= ECORE_QCID_LEGACY_VF_CID;
99217ec208SDavid C Somayajulu 
100217ec208SDavid C Somayajulu 	return legacy;
101217ec208SDavid C Somayajulu }
102217ec208SDavid C Somayajulu 
103217ec208SDavid C Somayajulu /* IOV ramrods */
ecore_sp_vf_start(struct ecore_hwfn * p_hwfn,struct ecore_vf_info * p_vf)104217ec208SDavid C Somayajulu static enum _ecore_status_t ecore_sp_vf_start(struct ecore_hwfn *p_hwfn,
105217ec208SDavid C Somayajulu 					      struct ecore_vf_info *p_vf)
106217ec208SDavid C Somayajulu {
107217ec208SDavid C Somayajulu 	struct vf_start_ramrod_data *p_ramrod = OSAL_NULL;
108217ec208SDavid C Somayajulu 	struct ecore_spq_entry *p_ent = OSAL_NULL;
109217ec208SDavid C Somayajulu 	struct ecore_sp_init_data init_data;
110217ec208SDavid C Somayajulu 	enum _ecore_status_t rc = ECORE_NOTIMPL;
111217ec208SDavid C Somayajulu 	u8 fp_minor;
112217ec208SDavid C Somayajulu 
113217ec208SDavid C Somayajulu 	/* Get SPQ entry */
114217ec208SDavid C Somayajulu 	OSAL_MEMSET(&init_data, 0, sizeof(init_data));
115217ec208SDavid C Somayajulu 	init_data.cid = ecore_spq_get_cid(p_hwfn);
116217ec208SDavid C Somayajulu 	init_data.opaque_fid = p_vf->opaque_fid;
117217ec208SDavid C Somayajulu 	init_data.comp_mode = ECORE_SPQ_MODE_EBLOCK;
118217ec208SDavid C Somayajulu 
119217ec208SDavid C Somayajulu 	rc = ecore_sp_init_request(p_hwfn, &p_ent,
120217ec208SDavid C Somayajulu 				   COMMON_RAMROD_VF_START,
121217ec208SDavid C Somayajulu 				   PROTOCOLID_COMMON, &init_data);
122217ec208SDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
123217ec208SDavid C Somayajulu 		return rc;
124217ec208SDavid C Somayajulu 
125217ec208SDavid C Somayajulu 	p_ramrod = &p_ent->ramrod.vf_start;
126217ec208SDavid C Somayajulu 
127217ec208SDavid C Somayajulu 	p_ramrod->vf_id = GET_FIELD(p_vf->concrete_fid, PXP_CONCRETE_FID_VFID);
128217ec208SDavid C Somayajulu 	p_ramrod->opaque_fid = OSAL_CPU_TO_LE16(p_vf->opaque_fid);
129217ec208SDavid C Somayajulu 
130217ec208SDavid C Somayajulu 	switch (p_hwfn->hw_info.personality) {
131217ec208SDavid C Somayajulu 	case ECORE_PCI_ETH:
132217ec208SDavid C Somayajulu 		p_ramrod->personality = PERSONALITY_ETH;
133217ec208SDavid C Somayajulu 		break;
134217ec208SDavid C Somayajulu 	case ECORE_PCI_ETH_ROCE:
135217ec208SDavid C Somayajulu 	case ECORE_PCI_ETH_IWARP:
136217ec208SDavid C Somayajulu 		p_ramrod->personality = PERSONALITY_RDMA_AND_ETH;
137217ec208SDavid C Somayajulu 		break;
138217ec208SDavid C Somayajulu 	default:
139217ec208SDavid C Somayajulu 		DP_NOTICE(p_hwfn, true, "Unknown VF personality %d\n",
140217ec208SDavid C Somayajulu 			  p_hwfn->hw_info.personality);
141217ec208SDavid C Somayajulu 		return ECORE_INVAL;
142217ec208SDavid C Somayajulu 	}
143217ec208SDavid C Somayajulu 
144217ec208SDavid C Somayajulu 	fp_minor = p_vf->acquire.vfdev_info.eth_fp_hsi_minor;
145217ec208SDavid C Somayajulu 	if (fp_minor > ETH_HSI_VER_MINOR &&
146217ec208SDavid C Somayajulu 	    fp_minor != ETH_HSI_VER_NO_PKT_LEN_TUNN) {
147217ec208SDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
148217ec208SDavid C Somayajulu 			   "VF [%d] - Requested fp hsi %02x.%02x which is slightly newer than PF's %02x.%02x; Configuring PFs version\n",
149217ec208SDavid C Somayajulu 			   p_vf->abs_vf_id,
150217ec208SDavid C Somayajulu 			   ETH_HSI_VER_MAJOR, fp_minor,
151217ec208SDavid C Somayajulu 			   ETH_HSI_VER_MAJOR, ETH_HSI_VER_MINOR);
152217ec208SDavid C Somayajulu 		fp_minor = ETH_HSI_VER_MINOR;
153217ec208SDavid C Somayajulu 	}
154217ec208SDavid C Somayajulu 
155217ec208SDavid C Somayajulu 	p_ramrod->hsi_fp_ver.major_ver_arr[ETH_VER_KEY] = ETH_HSI_VER_MAJOR;
156217ec208SDavid C Somayajulu 	p_ramrod->hsi_fp_ver.minor_ver_arr[ETH_VER_KEY] = fp_minor;
157217ec208SDavid C Somayajulu 
158217ec208SDavid C Somayajulu 	DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
159217ec208SDavid C Somayajulu 		   "VF[%d] - Starting using HSI %02x.%02x\n",
160217ec208SDavid C Somayajulu 		   p_vf->abs_vf_id, ETH_HSI_VER_MAJOR, fp_minor);
161217ec208SDavid C Somayajulu 
162217ec208SDavid C Somayajulu 	return ecore_spq_post(p_hwfn, p_ent, OSAL_NULL);
163217ec208SDavid C Somayajulu }
164217ec208SDavid C Somayajulu 
ecore_sp_vf_stop(struct ecore_hwfn * p_hwfn,u32 concrete_vfid,u16 opaque_vfid)165217ec208SDavid C Somayajulu static enum _ecore_status_t ecore_sp_vf_stop(struct ecore_hwfn *p_hwfn,
166217ec208SDavid C Somayajulu 					     u32 concrete_vfid,
167217ec208SDavid C Somayajulu 					     u16 opaque_vfid)
168217ec208SDavid C Somayajulu {
169217ec208SDavid C Somayajulu 	struct vf_stop_ramrod_data *p_ramrod = OSAL_NULL;
170217ec208SDavid C Somayajulu 	struct ecore_spq_entry *p_ent = OSAL_NULL;
171217ec208SDavid C Somayajulu 	struct ecore_sp_init_data init_data;
172217ec208SDavid C Somayajulu 	enum _ecore_status_t rc = ECORE_NOTIMPL;
173217ec208SDavid C Somayajulu 
174217ec208SDavid C Somayajulu 	/* Get SPQ entry */
175217ec208SDavid C Somayajulu 	OSAL_MEMSET(&init_data, 0, sizeof(init_data));
176217ec208SDavid C Somayajulu 	init_data.cid = ecore_spq_get_cid(p_hwfn);
177217ec208SDavid C Somayajulu 	init_data.opaque_fid = opaque_vfid;
178217ec208SDavid C Somayajulu 	init_data.comp_mode = ECORE_SPQ_MODE_EBLOCK;
179217ec208SDavid C Somayajulu 
180217ec208SDavid C Somayajulu 	rc = ecore_sp_init_request(p_hwfn, &p_ent,
181217ec208SDavid C Somayajulu 				   COMMON_RAMROD_VF_STOP,
182217ec208SDavid C Somayajulu 				   PROTOCOLID_COMMON, &init_data);
183217ec208SDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
184217ec208SDavid C Somayajulu 		return rc;
185217ec208SDavid C Somayajulu 
186217ec208SDavid C Somayajulu 	p_ramrod = &p_ent->ramrod.vf_stop;
187217ec208SDavid C Somayajulu 
188217ec208SDavid C Somayajulu 	p_ramrod->vf_id = GET_FIELD(concrete_vfid, PXP_CONCRETE_FID_VFID);
189217ec208SDavid C Somayajulu 
190217ec208SDavid C Somayajulu 	return ecore_spq_post(p_hwfn, p_ent, OSAL_NULL);
191217ec208SDavid C Somayajulu }
192217ec208SDavid C Somayajulu 
ecore_iov_is_valid_vfid(struct ecore_hwfn * p_hwfn,int rel_vf_id,bool b_enabled_only,bool b_non_malicious)193217ec208SDavid C Somayajulu bool ecore_iov_is_valid_vfid(struct ecore_hwfn *p_hwfn, int rel_vf_id,
194217ec208SDavid C Somayajulu 			     bool b_enabled_only, bool b_non_malicious)
195217ec208SDavid C Somayajulu {
196217ec208SDavid C Somayajulu 	if (!p_hwfn->pf_iov_info) {
197217ec208SDavid C Somayajulu 		DP_NOTICE(p_hwfn->p_dev, true, "No iov info\n");
198217ec208SDavid C Somayajulu 		return false;
199217ec208SDavid C Somayajulu 	}
200217ec208SDavid C Somayajulu 
201217ec208SDavid C Somayajulu 	if ((rel_vf_id >= p_hwfn->p_dev->p_iov_info->total_vfs) ||
202217ec208SDavid C Somayajulu 	    (rel_vf_id < 0))
203217ec208SDavid C Somayajulu 		return false;
204217ec208SDavid C Somayajulu 
205217ec208SDavid C Somayajulu 	if ((!p_hwfn->pf_iov_info->vfs_array[rel_vf_id].b_init) &&
206217ec208SDavid C Somayajulu 	    b_enabled_only)
207217ec208SDavid C Somayajulu 		return false;
208217ec208SDavid C Somayajulu 
209217ec208SDavid C Somayajulu 	if ((p_hwfn->pf_iov_info->vfs_array[rel_vf_id].b_malicious) &&
210217ec208SDavid C Somayajulu 	    b_non_malicious)
211217ec208SDavid C Somayajulu 		return false;
212217ec208SDavid C Somayajulu 
213217ec208SDavid C Somayajulu 	return true;
214217ec208SDavid C Somayajulu }
215217ec208SDavid C Somayajulu 
ecore_iov_get_vf_info(struct ecore_hwfn * p_hwfn,u16 relative_vf_id,bool b_enabled_only)216217ec208SDavid C Somayajulu struct ecore_vf_info *ecore_iov_get_vf_info(struct ecore_hwfn *p_hwfn,
217217ec208SDavid C Somayajulu 					    u16 relative_vf_id,
218217ec208SDavid C Somayajulu 					    bool b_enabled_only)
219217ec208SDavid C Somayajulu {
220217ec208SDavid C Somayajulu 	struct ecore_vf_info *vf = OSAL_NULL;
221217ec208SDavid C Somayajulu 
222217ec208SDavid C Somayajulu 	if (!p_hwfn->pf_iov_info) {
223217ec208SDavid C Somayajulu 		DP_NOTICE(p_hwfn->p_dev, true, "No iov info\n");
224217ec208SDavid C Somayajulu 		return OSAL_NULL;
225217ec208SDavid C Somayajulu 	}
226217ec208SDavid C Somayajulu 
227217ec208SDavid C Somayajulu 	if (ecore_iov_is_valid_vfid(p_hwfn, relative_vf_id,
228217ec208SDavid C Somayajulu 				    b_enabled_only, false))
229217ec208SDavid C Somayajulu 		vf = &p_hwfn->pf_iov_info->vfs_array[relative_vf_id];
230217ec208SDavid C Somayajulu 	else
231217ec208SDavid C Somayajulu 		DP_ERR(p_hwfn, "ecore_iov_get_vf_info: VF[%d] is not enabled\n",
232217ec208SDavid C Somayajulu 		       relative_vf_id);
233217ec208SDavid C Somayajulu 
234217ec208SDavid C Somayajulu 	return vf;
235217ec208SDavid C Somayajulu }
236217ec208SDavid C Somayajulu 
237217ec208SDavid C Somayajulu static struct ecore_queue_cid *
ecore_iov_get_vf_rx_queue_cid(struct ecore_vf_queue * p_queue)238217ec208SDavid C Somayajulu ecore_iov_get_vf_rx_queue_cid(struct ecore_vf_queue *p_queue)
239217ec208SDavid C Somayajulu {
240217ec208SDavid C Somayajulu 	int i;
241217ec208SDavid C Somayajulu 
242217ec208SDavid C Somayajulu 	for (i = 0; i < MAX_QUEUES_PER_QZONE; i++) {
243217ec208SDavid C Somayajulu 		if (p_queue->cids[i].p_cid &&
244217ec208SDavid C Somayajulu 		    !p_queue->cids[i].b_is_tx)
245217ec208SDavid C Somayajulu 			return p_queue->cids[i].p_cid;
246217ec208SDavid C Somayajulu 	}
247217ec208SDavid C Somayajulu 
248217ec208SDavid C Somayajulu 	return OSAL_NULL;
249217ec208SDavid C Somayajulu }
250217ec208SDavid C Somayajulu 
251217ec208SDavid C Somayajulu enum ecore_iov_validate_q_mode {
252217ec208SDavid C Somayajulu 	ECORE_IOV_VALIDATE_Q_NA,
253217ec208SDavid C Somayajulu 	ECORE_IOV_VALIDATE_Q_ENABLE,
254217ec208SDavid C Somayajulu 	ECORE_IOV_VALIDATE_Q_DISABLE,
255217ec208SDavid C Somayajulu };
256217ec208SDavid C Somayajulu 
ecore_iov_validate_queue_mode(struct ecore_vf_info * p_vf,u16 qid,enum ecore_iov_validate_q_mode mode,bool b_is_tx)257217ec208SDavid C Somayajulu static bool ecore_iov_validate_queue_mode(struct ecore_vf_info *p_vf,
258217ec208SDavid C Somayajulu 					  u16 qid,
259217ec208SDavid C Somayajulu 					  enum ecore_iov_validate_q_mode mode,
260217ec208SDavid C Somayajulu 					  bool b_is_tx)
261217ec208SDavid C Somayajulu {
262217ec208SDavid C Somayajulu 	int i;
263217ec208SDavid C Somayajulu 
264217ec208SDavid C Somayajulu 	if (mode == ECORE_IOV_VALIDATE_Q_NA)
265217ec208SDavid C Somayajulu 		return true;
266217ec208SDavid C Somayajulu 
267217ec208SDavid C Somayajulu 	for (i = 0; i < MAX_QUEUES_PER_QZONE; i++) {
268217ec208SDavid C Somayajulu 		struct ecore_vf_queue_cid *p_qcid;
269217ec208SDavid C Somayajulu 
270217ec208SDavid C Somayajulu 		p_qcid = &p_vf->vf_queues[qid].cids[i];
271217ec208SDavid C Somayajulu 
272217ec208SDavid C Somayajulu 		if (p_qcid->p_cid == OSAL_NULL)
273217ec208SDavid C Somayajulu 			continue;
274217ec208SDavid C Somayajulu 
275217ec208SDavid C Somayajulu 		if (p_qcid->b_is_tx != b_is_tx)
276217ec208SDavid C Somayajulu 			continue;
277217ec208SDavid C Somayajulu 
278217ec208SDavid C Somayajulu 		/* Found. It's enabled. */
279217ec208SDavid C Somayajulu 		return (mode == ECORE_IOV_VALIDATE_Q_ENABLE);
280217ec208SDavid C Somayajulu 	}
281217ec208SDavid C Somayajulu 
282217ec208SDavid C Somayajulu 	/* In case we haven't found any valid cid, then its disabled */
283217ec208SDavid C Somayajulu 	return (mode == ECORE_IOV_VALIDATE_Q_DISABLE);
284217ec208SDavid C Somayajulu }
285217ec208SDavid C Somayajulu 
ecore_iov_validate_rxq(struct ecore_hwfn * p_hwfn,struct ecore_vf_info * p_vf,u16 rx_qid,enum ecore_iov_validate_q_mode mode)286217ec208SDavid C Somayajulu static bool ecore_iov_validate_rxq(struct ecore_hwfn *p_hwfn,
287217ec208SDavid C Somayajulu 				   struct ecore_vf_info *p_vf,
288217ec208SDavid C Somayajulu 				   u16 rx_qid,
289217ec208SDavid C Somayajulu 				   enum ecore_iov_validate_q_mode mode)
290217ec208SDavid C Somayajulu {
291217ec208SDavid C Somayajulu 	if (rx_qid >= p_vf->num_rxqs) {
292217ec208SDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
293217ec208SDavid C Somayajulu 			   "VF[0x%02x] - can't touch Rx queue[%04x]; Only 0x%04x are allocated\n",
294217ec208SDavid C Somayajulu 			   p_vf->abs_vf_id, rx_qid, p_vf->num_rxqs);
295217ec208SDavid C Somayajulu 		return false;
296217ec208SDavid C Somayajulu 	}
297217ec208SDavid C Somayajulu 
298217ec208SDavid C Somayajulu 	return ecore_iov_validate_queue_mode(p_vf, rx_qid, mode, false);
299217ec208SDavid C Somayajulu }
300217ec208SDavid C Somayajulu 
ecore_iov_validate_txq(struct ecore_hwfn * p_hwfn,struct ecore_vf_info * p_vf,u16 tx_qid,enum ecore_iov_validate_q_mode mode)301217ec208SDavid C Somayajulu static bool ecore_iov_validate_txq(struct ecore_hwfn *p_hwfn,
302217ec208SDavid C Somayajulu 				   struct ecore_vf_info *p_vf,
303217ec208SDavid C Somayajulu 				   u16 tx_qid,
304217ec208SDavid C Somayajulu 				   enum ecore_iov_validate_q_mode mode)
305217ec208SDavid C Somayajulu {
306217ec208SDavid C Somayajulu 	if (tx_qid >= p_vf->num_txqs) {
307217ec208SDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
308217ec208SDavid C Somayajulu 			   "VF[0x%02x] - can't touch Tx queue[%04x]; Only 0x%04x are allocated\n",
309217ec208SDavid C Somayajulu 			   p_vf->abs_vf_id, tx_qid, p_vf->num_txqs);
310217ec208SDavid C Somayajulu 		return false;
311217ec208SDavid C Somayajulu 	}
312217ec208SDavid C Somayajulu 
313217ec208SDavid C Somayajulu 	return ecore_iov_validate_queue_mode(p_vf, tx_qid, mode, true);
314217ec208SDavid C Somayajulu }
315217ec208SDavid C Somayajulu 
ecore_iov_validate_sb(struct ecore_hwfn * p_hwfn,struct ecore_vf_info * p_vf,u16 sb_idx)316217ec208SDavid C Somayajulu static bool ecore_iov_validate_sb(struct ecore_hwfn *p_hwfn,
317217ec208SDavid C Somayajulu 				  struct ecore_vf_info *p_vf,
318217ec208SDavid C Somayajulu 				  u16 sb_idx)
319217ec208SDavid C Somayajulu {
320217ec208SDavid C Somayajulu 	int i;
321217ec208SDavid C Somayajulu 
322217ec208SDavid C Somayajulu 	for (i = 0; i < p_vf->num_sbs; i++)
323217ec208SDavid C Somayajulu 		if (p_vf->igu_sbs[i] == sb_idx)
324217ec208SDavid C Somayajulu 			return true;
325217ec208SDavid C Somayajulu 
326217ec208SDavid C Somayajulu 	DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
327217ec208SDavid C Somayajulu 		   "VF[0%02x] - tried using sb_idx %04x which doesn't exist as one of its 0x%02x SBs\n",
328217ec208SDavid C Somayajulu 		   p_vf->abs_vf_id, sb_idx, p_vf->num_sbs);
329217ec208SDavid C Somayajulu 
330217ec208SDavid C Somayajulu 	return false;
331217ec208SDavid C Somayajulu }
332217ec208SDavid C Somayajulu 
333217ec208SDavid C Somayajulu /* Is there at least 1 queue open? */
ecore_iov_validate_active_rxq(struct ecore_vf_info * p_vf)334217ec208SDavid C Somayajulu static bool ecore_iov_validate_active_rxq(struct ecore_vf_info *p_vf)
335217ec208SDavid C Somayajulu {
336217ec208SDavid C Somayajulu 	u8 i;
337217ec208SDavid C Somayajulu 
338217ec208SDavid C Somayajulu 	for (i = 0; i < p_vf->num_rxqs; i++)
339217ec208SDavid C Somayajulu 		if (ecore_iov_validate_queue_mode(p_vf, i,
340217ec208SDavid C Somayajulu 						  ECORE_IOV_VALIDATE_Q_ENABLE,
341217ec208SDavid C Somayajulu 						  false))
342217ec208SDavid C Somayajulu 			return true;
343217ec208SDavid C Somayajulu 
344217ec208SDavid C Somayajulu 	return false;
345217ec208SDavid C Somayajulu }
346217ec208SDavid C Somayajulu 
ecore_iov_validate_active_txq(struct ecore_vf_info * p_vf)347217ec208SDavid C Somayajulu static bool ecore_iov_validate_active_txq(struct ecore_vf_info *p_vf)
348217ec208SDavid C Somayajulu {
349217ec208SDavid C Somayajulu 	u8 i;
350217ec208SDavid C Somayajulu 
351217ec208SDavid C Somayajulu 	for (i = 0; i < p_vf->num_txqs; i++)
352217ec208SDavid C Somayajulu 		if (ecore_iov_validate_queue_mode(p_vf, i,
353217ec208SDavid C Somayajulu 						  ECORE_IOV_VALIDATE_Q_ENABLE,
354217ec208SDavid C Somayajulu 						  true))
355217ec208SDavid C Somayajulu 			return true;
356217ec208SDavid C Somayajulu 
357217ec208SDavid C Somayajulu 	return false;
358217ec208SDavid C Somayajulu }
359217ec208SDavid C Somayajulu 
ecore_iov_post_vf_bulletin(struct ecore_hwfn * p_hwfn,int vfid,struct ecore_ptt * p_ptt)360217ec208SDavid C Somayajulu enum _ecore_status_t ecore_iov_post_vf_bulletin(struct ecore_hwfn *p_hwfn,
361217ec208SDavid C Somayajulu 						int vfid,
362217ec208SDavid C Somayajulu 						struct ecore_ptt *p_ptt)
363217ec208SDavid C Somayajulu {
364217ec208SDavid C Somayajulu 	struct ecore_bulletin_content *p_bulletin;
365217ec208SDavid C Somayajulu 	int crc_size = sizeof(p_bulletin->crc);
366217ec208SDavid C Somayajulu 	struct ecore_dmae_params params;
367217ec208SDavid C Somayajulu 	struct ecore_vf_info *p_vf;
368217ec208SDavid C Somayajulu 
369217ec208SDavid C Somayajulu 	p_vf = ecore_iov_get_vf_info(p_hwfn, (u16)vfid, true);
370217ec208SDavid C Somayajulu 	if (!p_vf)
371217ec208SDavid C Somayajulu 		return ECORE_INVAL;
372217ec208SDavid C Somayajulu 
373217ec208SDavid C Somayajulu 	/* TODO - check VF is in a state where it can accept message */
374217ec208SDavid C Somayajulu 	if (!p_vf->vf_bulletin)
375217ec208SDavid C Somayajulu 		return ECORE_INVAL;
376217ec208SDavid C Somayajulu 
377217ec208SDavid C Somayajulu 	p_bulletin = p_vf->bulletin.p_virt;
378217ec208SDavid C Somayajulu 
379217ec208SDavid C Somayajulu 	/* Increment bulletin board version and compute crc */
380217ec208SDavid C Somayajulu 	p_bulletin->version++;
381217ec208SDavid C Somayajulu 	p_bulletin->crc = OSAL_CRC32(0, (u8 *)p_bulletin + crc_size,
382217ec208SDavid C Somayajulu 				     p_vf->bulletin.size - crc_size);
383217ec208SDavid C Somayajulu 
384217ec208SDavid C Somayajulu 	DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
385217ec208SDavid C Somayajulu 		   "Posting Bulletin 0x%08x to VF[%d] (CRC 0x%08x)\n",
386217ec208SDavid C Somayajulu 		   p_bulletin->version, p_vf->relative_vf_id,
387217ec208SDavid C Somayajulu 		   p_bulletin->crc);
388217ec208SDavid C Somayajulu 
389217ec208SDavid C Somayajulu 	/* propagate bulletin board via dmae to vm memory */
390217ec208SDavid C Somayajulu 	OSAL_MEMSET(&params, 0, sizeof(params));
391217ec208SDavid C Somayajulu 	params.flags = ECORE_DMAE_FLAG_VF_DST;
392217ec208SDavid C Somayajulu 	params.dst_vfid = p_vf->abs_vf_id;
393217ec208SDavid C Somayajulu 	return ecore_dmae_host2host(p_hwfn, p_ptt, p_vf->bulletin.phys,
394217ec208SDavid C Somayajulu 				    p_vf->vf_bulletin, p_vf->bulletin.size / 4,
395217ec208SDavid C Somayajulu 				    &params);
396217ec208SDavid C Somayajulu }
397217ec208SDavid C Somayajulu 
ecore_iov_pci_cfg_info(struct ecore_dev * p_dev)398217ec208SDavid C Somayajulu static enum _ecore_status_t ecore_iov_pci_cfg_info(struct ecore_dev *p_dev)
399217ec208SDavid C Somayajulu {
400217ec208SDavid C Somayajulu 	struct ecore_hw_sriov_info *iov = p_dev->p_iov_info;
401217ec208SDavid C Somayajulu 	int pos = iov->pos;
402217ec208SDavid C Somayajulu 
403217ec208SDavid C Somayajulu 	DP_VERBOSE(p_dev, ECORE_MSG_IOV, "sriov ext pos %d\n", pos);
404217ec208SDavid C Somayajulu 	OSAL_PCI_READ_CONFIG_WORD(p_dev,
405217ec208SDavid C Somayajulu 				  pos + PCI_SRIOV_CTRL,
406217ec208SDavid C Somayajulu 				  &iov->ctrl);
407217ec208SDavid C Somayajulu 
408217ec208SDavid C Somayajulu 	OSAL_PCI_READ_CONFIG_WORD(p_dev,
409217ec208SDavid C Somayajulu 				  pos + PCI_SRIOV_TOTAL_VF,
410217ec208SDavid C Somayajulu 				  &iov->total_vfs);
411217ec208SDavid C Somayajulu 	OSAL_PCI_READ_CONFIG_WORD(p_dev,
412217ec208SDavid C Somayajulu 				  pos + PCI_SRIOV_INITIAL_VF,
413217ec208SDavid C Somayajulu 				  &iov->initial_vfs);
414217ec208SDavid C Somayajulu 
415217ec208SDavid C Somayajulu 	OSAL_PCI_READ_CONFIG_WORD(p_dev,
416217ec208SDavid C Somayajulu 				  pos + PCI_SRIOV_NUM_VF,
417217ec208SDavid C Somayajulu 				  &iov->num_vfs);
418217ec208SDavid C Somayajulu 	if (iov->num_vfs) {
419217ec208SDavid C Somayajulu 		/* @@@TODO - in future we might want to add an OSAL here to
420217ec208SDavid C Somayajulu 		 * allow each OS to decide on its own how to act.
421217ec208SDavid C Somayajulu 		 */
422217ec208SDavid C Somayajulu 		DP_VERBOSE(p_dev, ECORE_MSG_IOV,
423217ec208SDavid C Somayajulu 			   "Number of VFs are already set to non-zero value. Ignoring PCI configuration value\n");
424217ec208SDavid C Somayajulu 		iov->num_vfs = 0;
425217ec208SDavid C Somayajulu 	}
426217ec208SDavid C Somayajulu 
427217ec208SDavid C Somayajulu 	OSAL_PCI_READ_CONFIG_WORD(p_dev,
428217ec208SDavid C Somayajulu 				  pos + PCI_SRIOV_VF_OFFSET,
429217ec208SDavid C Somayajulu 				  &iov->offset);
430217ec208SDavid C Somayajulu 
431217ec208SDavid C Somayajulu 	OSAL_PCI_READ_CONFIG_WORD(p_dev,
432217ec208SDavid C Somayajulu 				  pos + PCI_SRIOV_VF_STRIDE,
433217ec208SDavid C Somayajulu 				  &iov->stride);
434217ec208SDavid C Somayajulu 
435217ec208SDavid C Somayajulu 	OSAL_PCI_READ_CONFIG_WORD(p_dev,
436217ec208SDavid C Somayajulu 				  pos + PCI_SRIOV_VF_DID,
437217ec208SDavid C Somayajulu 				  &iov->vf_device_id);
438217ec208SDavid C Somayajulu 
439217ec208SDavid C Somayajulu 	OSAL_PCI_READ_CONFIG_DWORD(p_dev,
440217ec208SDavid C Somayajulu 				   pos + PCI_SRIOV_SUP_PGSIZE,
441217ec208SDavid C Somayajulu 				   &iov->pgsz);
442217ec208SDavid C Somayajulu 
443217ec208SDavid C Somayajulu 	OSAL_PCI_READ_CONFIG_DWORD(p_dev,
444217ec208SDavid C Somayajulu 				   pos + PCI_SRIOV_CAP,
445217ec208SDavid C Somayajulu 				   &iov->cap);
446217ec208SDavid C Somayajulu 
447217ec208SDavid C Somayajulu 	OSAL_PCI_READ_CONFIG_BYTE(p_dev,
448217ec208SDavid C Somayajulu 				  pos + PCI_SRIOV_FUNC_LINK,
449217ec208SDavid C Somayajulu 				  &iov->link);
450217ec208SDavid C Somayajulu 
451217ec208SDavid C Somayajulu 	DP_VERBOSE(p_dev, ECORE_MSG_IOV,
452217ec208SDavid C Somayajulu 		   "IOV info: nres %d, cap 0x%x, ctrl 0x%x, total %d, initial %d, num vfs %d, offset %d, stride %d, page size 0x%x\n",
453217ec208SDavid C Somayajulu 		   iov->nres, iov->cap, iov->ctrl,
454217ec208SDavid C Somayajulu 		   iov->total_vfs, iov->initial_vfs, iov->nr_virtfn,
455217ec208SDavid C Somayajulu 		   iov->offset, iov->stride, iov->pgsz);
456217ec208SDavid C Somayajulu 
457217ec208SDavid C Somayajulu 	/* Some sanity checks */
458217ec208SDavid C Somayajulu 	if (iov->num_vfs > NUM_OF_VFS(p_dev) ||
459217ec208SDavid C Somayajulu 	    iov->total_vfs > NUM_OF_VFS(p_dev)) {
460217ec208SDavid C Somayajulu 		/* This can happen only due to a bug. In this case we set
461217ec208SDavid C Somayajulu 		 * num_vfs to zero to avoid memory corruption in the code that
462217ec208SDavid C Somayajulu 		 * assumes max number of vfs
463217ec208SDavid C Somayajulu 		 */
464217ec208SDavid C Somayajulu 		DP_NOTICE(p_dev, false, "IOV: Unexpected number of vfs set: %d setting num_vf to zero\n",
465217ec208SDavid C Somayajulu 			  iov->num_vfs);
466217ec208SDavid C Somayajulu 
467217ec208SDavid C Somayajulu 		iov->num_vfs = 0;
468217ec208SDavid C Somayajulu 		iov->total_vfs = 0;
469217ec208SDavid C Somayajulu 	}
470217ec208SDavid C Somayajulu 
471217ec208SDavid C Somayajulu 	return ECORE_SUCCESS;
472217ec208SDavid C Somayajulu }
473217ec208SDavid C Somayajulu 
ecore_iov_setup_vfdb(struct ecore_hwfn * p_hwfn)474217ec208SDavid C Somayajulu static void ecore_iov_setup_vfdb(struct ecore_hwfn *p_hwfn)
475217ec208SDavid C Somayajulu {
476217ec208SDavid C Somayajulu 	struct ecore_hw_sriov_info *p_iov = p_hwfn->p_dev->p_iov_info;
477217ec208SDavid C Somayajulu 	struct ecore_pf_iov *p_iov_info = p_hwfn->pf_iov_info;
478217ec208SDavid C Somayajulu 	struct ecore_bulletin_content *p_bulletin_virt;
479217ec208SDavid C Somayajulu 	dma_addr_t req_p, rply_p, bulletin_p;
480217ec208SDavid C Somayajulu 	union pfvf_tlvs *p_reply_virt_addr;
481217ec208SDavid C Somayajulu 	union vfpf_tlvs *p_req_virt_addr;
482217ec208SDavid C Somayajulu 	u8 idx = 0;
483217ec208SDavid C Somayajulu 
484217ec208SDavid C Somayajulu 	OSAL_MEMSET(p_iov_info->vfs_array, 0, sizeof(p_iov_info->vfs_array));
485217ec208SDavid C Somayajulu 
486217ec208SDavid C Somayajulu 	p_req_virt_addr = p_iov_info->mbx_msg_virt_addr;
487217ec208SDavid C Somayajulu 	req_p = p_iov_info->mbx_msg_phys_addr;
488217ec208SDavid C Somayajulu 	p_reply_virt_addr = p_iov_info->mbx_reply_virt_addr;
489217ec208SDavid C Somayajulu 	rply_p = p_iov_info->mbx_reply_phys_addr;
490217ec208SDavid C Somayajulu 	p_bulletin_virt = p_iov_info->p_bulletins;
491217ec208SDavid C Somayajulu 	bulletin_p = p_iov_info->bulletins_phys;
492217ec208SDavid C Somayajulu 	if (!p_req_virt_addr || !p_reply_virt_addr || !p_bulletin_virt) {
493217ec208SDavid C Somayajulu 		DP_ERR(p_hwfn, "ecore_iov_setup_vfdb called without allocating mem first\n");
494217ec208SDavid C Somayajulu 		return;
495217ec208SDavid C Somayajulu 	}
496217ec208SDavid C Somayajulu 
497217ec208SDavid C Somayajulu 	for (idx = 0; idx < p_iov->total_vfs; idx++) {
498217ec208SDavid C Somayajulu 		struct ecore_vf_info *vf = &p_iov_info->vfs_array[idx];
499217ec208SDavid C Somayajulu 		u32 concrete;
500217ec208SDavid C Somayajulu 
501217ec208SDavid C Somayajulu 		vf->vf_mbx.req_virt = p_req_virt_addr + idx;
502217ec208SDavid C Somayajulu 		vf->vf_mbx.req_phys = req_p + idx * sizeof(union vfpf_tlvs);
503217ec208SDavid C Somayajulu 		vf->vf_mbx.reply_virt = p_reply_virt_addr + idx;
504217ec208SDavid C Somayajulu 		vf->vf_mbx.reply_phys = rply_p + idx * sizeof(union pfvf_tlvs);
505217ec208SDavid C Somayajulu 
506217ec208SDavid C Somayajulu #ifdef CONFIG_ECORE_SW_CHANNEL
507217ec208SDavid C Somayajulu 		vf->vf_mbx.sw_mbx.request_size = sizeof(union vfpf_tlvs);
508217ec208SDavid C Somayajulu 		vf->vf_mbx.sw_mbx.mbx_state = VF_PF_WAIT_FOR_START_REQUEST;
509217ec208SDavid C Somayajulu #endif
510217ec208SDavid C Somayajulu 		vf->state = VF_STOPPED;
511217ec208SDavid C Somayajulu 		vf->b_init = false;
512217ec208SDavid C Somayajulu 
513217ec208SDavid C Somayajulu 		vf->bulletin.phys = idx *
514217ec208SDavid C Somayajulu 				    sizeof(struct ecore_bulletin_content) +
515217ec208SDavid C Somayajulu 				    bulletin_p;
516217ec208SDavid C Somayajulu 		vf->bulletin.p_virt = p_bulletin_virt + idx;
517217ec208SDavid C Somayajulu 		vf->bulletin.size = sizeof(struct ecore_bulletin_content);
518217ec208SDavid C Somayajulu 
519217ec208SDavid C Somayajulu 		vf->relative_vf_id = idx;
520217ec208SDavid C Somayajulu 		vf->abs_vf_id = idx + p_iov->first_vf_in_pf;
521217ec208SDavid C Somayajulu 		concrete = ecore_vfid_to_concrete(p_hwfn, vf->abs_vf_id);
522217ec208SDavid C Somayajulu 		vf->concrete_fid = concrete;
523217ec208SDavid C Somayajulu 		/* TODO - need to devise a better way of getting opaque */
524217ec208SDavid C Somayajulu 		vf->opaque_fid = (p_hwfn->hw_info.opaque_fid & 0xff) |
525217ec208SDavid C Somayajulu 				 (vf->abs_vf_id << 8);
526217ec208SDavid C Somayajulu 
527217ec208SDavid C Somayajulu 		vf->num_mac_filters = ECORE_ETH_VF_NUM_MAC_FILTERS;
528217ec208SDavid C Somayajulu 		vf->num_vlan_filters = ECORE_ETH_VF_NUM_VLAN_FILTERS;
529217ec208SDavid C Somayajulu 	}
530217ec208SDavid C Somayajulu }
531217ec208SDavid C Somayajulu 
ecore_iov_allocate_vfdb(struct ecore_hwfn * p_hwfn)532217ec208SDavid C Somayajulu static enum _ecore_status_t ecore_iov_allocate_vfdb(struct ecore_hwfn *p_hwfn)
533217ec208SDavid C Somayajulu {
534217ec208SDavid C Somayajulu 	struct ecore_pf_iov *p_iov_info = p_hwfn->pf_iov_info;
535217ec208SDavid C Somayajulu 	void **p_v_addr;
536217ec208SDavid C Somayajulu 	u16 num_vfs = 0;
537217ec208SDavid C Somayajulu 
538217ec208SDavid C Somayajulu 	num_vfs = p_hwfn->p_dev->p_iov_info->total_vfs;
539217ec208SDavid C Somayajulu 
540217ec208SDavid C Somayajulu 	DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
541217ec208SDavid C Somayajulu 		   "ecore_iov_allocate_vfdb for %d VFs\n", num_vfs);
542217ec208SDavid C Somayajulu 
543217ec208SDavid C Somayajulu 	/* Allocate PF Mailbox buffer (per-VF) */
544217ec208SDavid C Somayajulu 	p_iov_info->mbx_msg_size = sizeof(union vfpf_tlvs) * num_vfs;
545217ec208SDavid C Somayajulu 	p_v_addr = &p_iov_info->mbx_msg_virt_addr;
546217ec208SDavid C Somayajulu 	*p_v_addr = OSAL_DMA_ALLOC_COHERENT(p_hwfn->p_dev,
547217ec208SDavid C Somayajulu 					    &p_iov_info->mbx_msg_phys_addr,
548217ec208SDavid C Somayajulu 					    p_iov_info->mbx_msg_size);
549217ec208SDavid C Somayajulu 	if (!*p_v_addr)
550217ec208SDavid C Somayajulu 		return ECORE_NOMEM;
551217ec208SDavid C Somayajulu 
552217ec208SDavid C Somayajulu 	/* Allocate PF Mailbox Reply buffer (per-VF) */
553217ec208SDavid C Somayajulu 	p_iov_info->mbx_reply_size = sizeof(union pfvf_tlvs) * num_vfs;
554217ec208SDavid C Somayajulu 	p_v_addr = &p_iov_info->mbx_reply_virt_addr;
555217ec208SDavid C Somayajulu 	*p_v_addr = OSAL_DMA_ALLOC_COHERENT(p_hwfn->p_dev,
556217ec208SDavid C Somayajulu 					    &p_iov_info->mbx_reply_phys_addr,
557217ec208SDavid C Somayajulu 					    p_iov_info->mbx_reply_size);
558217ec208SDavid C Somayajulu 	if (!*p_v_addr)
559217ec208SDavid C Somayajulu 		return ECORE_NOMEM;
560217ec208SDavid C Somayajulu 
561217ec208SDavid C Somayajulu 	p_iov_info->bulletins_size = sizeof(struct ecore_bulletin_content) *
562217ec208SDavid C Somayajulu 				     num_vfs;
563217ec208SDavid C Somayajulu 	p_v_addr = &p_iov_info->p_bulletins;
564217ec208SDavid C Somayajulu 	*p_v_addr = OSAL_DMA_ALLOC_COHERENT(p_hwfn->p_dev,
565217ec208SDavid C Somayajulu 					    &p_iov_info->bulletins_phys,
566217ec208SDavid C Somayajulu 					    p_iov_info->bulletins_size);
567217ec208SDavid C Somayajulu 	if (!*p_v_addr)
568217ec208SDavid C Somayajulu 		return ECORE_NOMEM;
569217ec208SDavid C Somayajulu 
570217ec208SDavid C Somayajulu 	DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
571217ec208SDavid C Somayajulu 		   "PF's Requests mailbox [%p virt 0x%llx phys],  Response mailbox [%p virt 0x%llx phys] Bulletins [%p virt 0x%llx phys]\n",
572217ec208SDavid C Somayajulu 		   p_iov_info->mbx_msg_virt_addr,
573217ec208SDavid C Somayajulu 		   (unsigned long long)p_iov_info->mbx_msg_phys_addr,
574217ec208SDavid C Somayajulu 		   p_iov_info->mbx_reply_virt_addr,
575217ec208SDavid C Somayajulu 		   (unsigned long long)p_iov_info->mbx_reply_phys_addr,
576217ec208SDavid C Somayajulu 		   p_iov_info->p_bulletins,
577217ec208SDavid C Somayajulu 		   (unsigned long long)p_iov_info->bulletins_phys);
578217ec208SDavid C Somayajulu 
579217ec208SDavid C Somayajulu 	return ECORE_SUCCESS;
580217ec208SDavid C Somayajulu }
581217ec208SDavid C Somayajulu 
ecore_iov_free_vfdb(struct ecore_hwfn * p_hwfn)582217ec208SDavid C Somayajulu static void ecore_iov_free_vfdb(struct ecore_hwfn *p_hwfn)
583217ec208SDavid C Somayajulu {
584217ec208SDavid C Somayajulu 	struct ecore_pf_iov *p_iov_info = p_hwfn->pf_iov_info;
585217ec208SDavid C Somayajulu 
586217ec208SDavid C Somayajulu 	if (p_hwfn->pf_iov_info->mbx_msg_virt_addr)
587217ec208SDavid C Somayajulu 		OSAL_DMA_FREE_COHERENT(p_hwfn->p_dev,
588217ec208SDavid C Somayajulu 				       p_iov_info->mbx_msg_virt_addr,
589217ec208SDavid C Somayajulu 				       p_iov_info->mbx_msg_phys_addr,
590217ec208SDavid C Somayajulu 				       p_iov_info->mbx_msg_size);
591217ec208SDavid C Somayajulu 
592217ec208SDavid C Somayajulu 	if (p_hwfn->pf_iov_info->mbx_reply_virt_addr)
593217ec208SDavid C Somayajulu 		OSAL_DMA_FREE_COHERENT(p_hwfn->p_dev,
594217ec208SDavid C Somayajulu 				       p_iov_info->mbx_reply_virt_addr,
595217ec208SDavid C Somayajulu 				       p_iov_info->mbx_reply_phys_addr,
596217ec208SDavid C Somayajulu 				       p_iov_info->mbx_reply_size);
597217ec208SDavid C Somayajulu 
598217ec208SDavid C Somayajulu 	if (p_iov_info->p_bulletins)
599217ec208SDavid C Somayajulu 		OSAL_DMA_FREE_COHERENT(p_hwfn->p_dev,
600217ec208SDavid C Somayajulu 				       p_iov_info->p_bulletins,
601217ec208SDavid C Somayajulu 				       p_iov_info->bulletins_phys,
602217ec208SDavid C Somayajulu 				       p_iov_info->bulletins_size);
603217ec208SDavid C Somayajulu }
604217ec208SDavid C Somayajulu 
ecore_iov_alloc(struct ecore_hwfn * p_hwfn)605217ec208SDavid C Somayajulu enum _ecore_status_t ecore_iov_alloc(struct ecore_hwfn *p_hwfn)
606217ec208SDavid C Somayajulu {
607217ec208SDavid C Somayajulu 	struct ecore_pf_iov *p_sriov;
608217ec208SDavid C Somayajulu 
609217ec208SDavid C Somayajulu 	if (!IS_PF_SRIOV(p_hwfn)) {
610217ec208SDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
611217ec208SDavid C Somayajulu 			   "No SR-IOV - no need for IOV db\n");
612217ec208SDavid C Somayajulu 		return ECORE_SUCCESS;
613217ec208SDavid C Somayajulu 	}
614217ec208SDavid C Somayajulu 
615217ec208SDavid C Somayajulu 	p_sriov = OSAL_ZALLOC(p_hwfn->p_dev, GFP_KERNEL, sizeof(*p_sriov));
616217ec208SDavid C Somayajulu 	if (!p_sriov) {
617217ec208SDavid C Somayajulu 		DP_NOTICE(p_hwfn, false, "Failed to allocate `struct ecore_sriov'\n");
618217ec208SDavid C Somayajulu 		return ECORE_NOMEM;
619217ec208SDavid C Somayajulu 	}
620217ec208SDavid C Somayajulu 
621217ec208SDavid C Somayajulu 	p_hwfn->pf_iov_info = p_sriov;
622217ec208SDavid C Somayajulu 
623217ec208SDavid C Somayajulu 	ecore_spq_register_async_cb(p_hwfn, PROTOCOLID_COMMON,
624217ec208SDavid C Somayajulu 				    ecore_sriov_eqe_event);
625217ec208SDavid C Somayajulu 
626217ec208SDavid C Somayajulu 	return ecore_iov_allocate_vfdb(p_hwfn);
627217ec208SDavid C Somayajulu }
628217ec208SDavid C Somayajulu 
ecore_iov_setup(struct ecore_hwfn * p_hwfn)629217ec208SDavid C Somayajulu void ecore_iov_setup(struct ecore_hwfn	*p_hwfn)
630217ec208SDavid C Somayajulu {
631217ec208SDavid C Somayajulu 	if (!IS_PF_SRIOV(p_hwfn) || !IS_PF_SRIOV_ALLOC(p_hwfn))
632217ec208SDavid C Somayajulu 		return;
633217ec208SDavid C Somayajulu 
634217ec208SDavid C Somayajulu 	ecore_iov_setup_vfdb(p_hwfn);
635217ec208SDavid C Somayajulu }
636217ec208SDavid C Somayajulu 
ecore_iov_free(struct ecore_hwfn * p_hwfn)637217ec208SDavid C Somayajulu void ecore_iov_free(struct ecore_hwfn *p_hwfn)
638217ec208SDavid C Somayajulu {
639217ec208SDavid C Somayajulu 	ecore_spq_unregister_async_cb(p_hwfn, PROTOCOLID_COMMON);
640217ec208SDavid C Somayajulu 
641217ec208SDavid C Somayajulu 	if (IS_PF_SRIOV_ALLOC(p_hwfn)) {
642217ec208SDavid C Somayajulu 		ecore_iov_free_vfdb(p_hwfn);
643217ec208SDavid C Somayajulu 		OSAL_FREE(p_hwfn->p_dev, p_hwfn->pf_iov_info);
644217ec208SDavid C Somayajulu 		p_hwfn->pf_iov_info = OSAL_NULL;
645217ec208SDavid C Somayajulu 	}
646217ec208SDavid C Somayajulu }
647217ec208SDavid C Somayajulu 
ecore_iov_free_hw_info(struct ecore_dev * p_dev)648217ec208SDavid C Somayajulu void ecore_iov_free_hw_info(struct ecore_dev *p_dev)
649217ec208SDavid C Somayajulu {
650217ec208SDavid C Somayajulu 	OSAL_FREE(p_dev, p_dev->p_iov_info);
651217ec208SDavid C Somayajulu 	p_dev->p_iov_info = OSAL_NULL;
652217ec208SDavid C Somayajulu }
653217ec208SDavid C Somayajulu 
ecore_iov_hw_info(struct ecore_hwfn * p_hwfn)654217ec208SDavid C Somayajulu enum _ecore_status_t ecore_iov_hw_info(struct ecore_hwfn *p_hwfn)
655217ec208SDavid C Somayajulu {
656217ec208SDavid C Somayajulu 	struct ecore_dev *p_dev = p_hwfn->p_dev;
657217ec208SDavid C Somayajulu 	int pos;
658217ec208SDavid C Somayajulu 	enum _ecore_status_t rc;
659217ec208SDavid C Somayajulu 
660217ec208SDavid C Somayajulu 	if (IS_VF(p_hwfn->p_dev))
661217ec208SDavid C Somayajulu 		return ECORE_SUCCESS;
662217ec208SDavid C Somayajulu 
663217ec208SDavid C Somayajulu 	/* Learn the PCI configuration */
664217ec208SDavid C Somayajulu 	pos = OSAL_PCI_FIND_EXT_CAPABILITY(p_hwfn->p_dev,
665217ec208SDavid C Somayajulu 					   PCI_EXT_CAP_ID_SRIOV);
666217ec208SDavid C Somayajulu 	if (!pos) {
667217ec208SDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV, "No PCIe IOV support\n");
668217ec208SDavid C Somayajulu 		return ECORE_SUCCESS;
669217ec208SDavid C Somayajulu 	}
670217ec208SDavid C Somayajulu 
671217ec208SDavid C Somayajulu 	/* Allocate a new struct for IOV information */
672217ec208SDavid C Somayajulu 	/* TODO - can change to VALLOC when its available */
673217ec208SDavid C Somayajulu 	p_dev->p_iov_info = OSAL_ZALLOC(p_dev, GFP_KERNEL,
674217ec208SDavid C Somayajulu 					sizeof(*p_dev->p_iov_info));
675217ec208SDavid C Somayajulu 	if (!p_dev->p_iov_info) {
676217ec208SDavid C Somayajulu 		DP_NOTICE(p_hwfn, false,
677217ec208SDavid C Somayajulu 			  "Can't support IOV due to lack of memory\n");
678217ec208SDavid C Somayajulu 		return ECORE_NOMEM;
679217ec208SDavid C Somayajulu 	}
680217ec208SDavid C Somayajulu 	p_dev->p_iov_info->pos = pos;
681217ec208SDavid C Somayajulu 
682217ec208SDavid C Somayajulu 	rc = ecore_iov_pci_cfg_info(p_dev);
683217ec208SDavid C Somayajulu 	if (rc)
684217ec208SDavid C Somayajulu 		return rc;
685217ec208SDavid C Somayajulu 
686a216b9c2SGordon Bergling 	/* We want PF IOV to be synonemous with the existence of p_iov_info;
687217ec208SDavid C Somayajulu 	 * In case the capability is published but there are no VFs, simply
688217ec208SDavid C Somayajulu 	 * de-allocate the struct.
689217ec208SDavid C Somayajulu 	 */
690217ec208SDavid C Somayajulu 	if (!p_dev->p_iov_info->total_vfs) {
691217ec208SDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
692217ec208SDavid C Somayajulu 			   "IOV capabilities, but no VFs are published\n");
693217ec208SDavid C Somayajulu 		OSAL_FREE(p_dev, p_dev->p_iov_info);
694217ec208SDavid C Somayajulu 		p_dev->p_iov_info = OSAL_NULL;
695217ec208SDavid C Somayajulu 		return ECORE_SUCCESS;
696217ec208SDavid C Somayajulu 	}
697217ec208SDavid C Somayajulu 
698217ec208SDavid C Somayajulu 	/* First VF index based on offset is tricky:
699217ec208SDavid C Somayajulu 	 *  - If ARI is supported [likely], offset - (16 - pf_id) would
700217ec208SDavid C Somayajulu 	 *    provide the number for eng0. 2nd engine Vfs would begin
701217ec208SDavid C Somayajulu 	 *    after the first engine's VFs.
702217ec208SDavid C Somayajulu 	 *  - If !ARI, VFs would start on next device.
703217ec208SDavid C Somayajulu 	 *    so offset - (256 - pf_id) would provide the number.
704217ec208SDavid C Somayajulu 	 * Utilize the fact that (256 - pf_id) is achieved only be later
705217ec208SDavid C Somayajulu 	 * to diffrentiate between the two.
706217ec208SDavid C Somayajulu 	 */
707217ec208SDavid C Somayajulu 
708217ec208SDavid C Somayajulu 	if (p_hwfn->p_dev->p_iov_info->offset < (256 - p_hwfn->abs_pf_id)) {
709217ec208SDavid C Somayajulu 		u32 first = p_hwfn->p_dev->p_iov_info->offset +
710217ec208SDavid C Somayajulu 			    p_hwfn->abs_pf_id - 16;
711217ec208SDavid C Somayajulu 
712217ec208SDavid C Somayajulu 		p_dev->p_iov_info->first_vf_in_pf = first;
713217ec208SDavid C Somayajulu 
714217ec208SDavid C Somayajulu 		if (ECORE_PATH_ID(p_hwfn))
715217ec208SDavid C Somayajulu 			p_dev->p_iov_info->first_vf_in_pf -= MAX_NUM_VFS_BB;
716217ec208SDavid C Somayajulu 	} else {
717217ec208SDavid C Somayajulu 		u32 first = p_hwfn->p_dev->p_iov_info->offset +
718217ec208SDavid C Somayajulu 			    p_hwfn->abs_pf_id - 256;
719217ec208SDavid C Somayajulu 
720217ec208SDavid C Somayajulu 		p_dev->p_iov_info->first_vf_in_pf = first;
721217ec208SDavid C Somayajulu 	}
722217ec208SDavid C Somayajulu 
723217ec208SDavid C Somayajulu 	DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
724217ec208SDavid C Somayajulu 		   "First VF in hwfn 0x%08x\n",
725217ec208SDavid C Somayajulu 		   p_dev->p_iov_info->first_vf_in_pf);
726217ec208SDavid C Somayajulu 
727217ec208SDavid C Somayajulu 	return ECORE_SUCCESS;
728217ec208SDavid C Somayajulu }
729217ec208SDavid C Somayajulu 
_ecore_iov_pf_sanity_check(struct ecore_hwfn * p_hwfn,int vfid,bool b_fail_malicious)730217ec208SDavid C Somayajulu static bool _ecore_iov_pf_sanity_check(struct ecore_hwfn *p_hwfn, int vfid,
731217ec208SDavid C Somayajulu 				       bool b_fail_malicious)
732217ec208SDavid C Somayajulu {
733217ec208SDavid C Somayajulu 	/* Check PF supports sriov */
734217ec208SDavid C Somayajulu 	if (IS_VF(p_hwfn->p_dev) || !IS_ECORE_SRIOV(p_hwfn->p_dev) ||
735217ec208SDavid C Somayajulu 	    !IS_PF_SRIOV_ALLOC(p_hwfn))
736217ec208SDavid C Somayajulu 		return false;
737217ec208SDavid C Somayajulu 
738217ec208SDavid C Somayajulu 	/* Check VF validity */
739217ec208SDavid C Somayajulu 	if (!ecore_iov_is_valid_vfid(p_hwfn, vfid, true, b_fail_malicious))
740217ec208SDavid C Somayajulu 		return false;
741217ec208SDavid C Somayajulu 
742217ec208SDavid C Somayajulu 	return true;
743217ec208SDavid C Somayajulu }
744217ec208SDavid C Somayajulu 
ecore_iov_pf_sanity_check(struct ecore_hwfn * p_hwfn,int vfid)745217ec208SDavid C Somayajulu bool ecore_iov_pf_sanity_check(struct ecore_hwfn *p_hwfn, int vfid)
746217ec208SDavid C Somayajulu {
747217ec208SDavid C Somayajulu 	return _ecore_iov_pf_sanity_check(p_hwfn, vfid, true);
748217ec208SDavid C Somayajulu }
749217ec208SDavid C Somayajulu 
ecore_iov_set_vf_to_disable(struct ecore_dev * p_dev,u16 rel_vf_id,u8 to_disable)750217ec208SDavid C Somayajulu void ecore_iov_set_vf_to_disable(struct ecore_dev *p_dev,
751217ec208SDavid C Somayajulu 				 u16 rel_vf_id,
752217ec208SDavid C Somayajulu 				 u8 to_disable)
753217ec208SDavid C Somayajulu {
754217ec208SDavid C Somayajulu 	struct ecore_vf_info *vf;
755217ec208SDavid C Somayajulu 	int i;
756217ec208SDavid C Somayajulu 
757217ec208SDavid C Somayajulu 	for_each_hwfn(p_dev, i) {
758217ec208SDavid C Somayajulu 		struct ecore_hwfn *p_hwfn = &p_dev->hwfns[i];
759217ec208SDavid C Somayajulu 
760217ec208SDavid C Somayajulu 		vf = ecore_iov_get_vf_info(p_hwfn, rel_vf_id, false);
761217ec208SDavid C Somayajulu 		if (!vf)
762217ec208SDavid C Somayajulu 			continue;
763217ec208SDavid C Somayajulu 
764217ec208SDavid C Somayajulu 		vf->to_disable = to_disable;
765217ec208SDavid C Somayajulu 	}
766217ec208SDavid C Somayajulu }
767217ec208SDavid C Somayajulu 
ecore_iov_set_vfs_to_disable(struct ecore_dev * p_dev,u8 to_disable)768217ec208SDavid C Somayajulu void ecore_iov_set_vfs_to_disable(struct ecore_dev *p_dev,
769217ec208SDavid C Somayajulu 				  u8 to_disable)
770217ec208SDavid C Somayajulu {
771217ec208SDavid C Somayajulu 	u16 i;
772217ec208SDavid C Somayajulu 
773217ec208SDavid C Somayajulu 	if (!IS_ECORE_SRIOV(p_dev))
774217ec208SDavid C Somayajulu 		return;
775217ec208SDavid C Somayajulu 
776217ec208SDavid C Somayajulu 	for (i = 0; i < p_dev->p_iov_info->total_vfs; i++)
777217ec208SDavid C Somayajulu 		ecore_iov_set_vf_to_disable(p_dev, i, to_disable);
778217ec208SDavid C Somayajulu }
779217ec208SDavid C Somayajulu 
780217ec208SDavid C Somayajulu #ifndef LINUX_REMOVE
781217ec208SDavid C Somayajulu /* @@@TBD Consider taking outside of ecore... */
ecore_iov_set_vf_ctx(struct ecore_hwfn * p_hwfn,u16 vf_id,void * ctx)782217ec208SDavid C Somayajulu enum _ecore_status_t ecore_iov_set_vf_ctx(struct ecore_hwfn *p_hwfn,
783217ec208SDavid C Somayajulu 					  u16		    vf_id,
784217ec208SDavid C Somayajulu 					  void		    *ctx)
785217ec208SDavid C Somayajulu {
786217ec208SDavid C Somayajulu 	enum _ecore_status_t rc = ECORE_SUCCESS;
787217ec208SDavid C Somayajulu 	struct ecore_vf_info *vf = ecore_iov_get_vf_info(p_hwfn, vf_id, true);
788217ec208SDavid C Somayajulu 
789217ec208SDavid C Somayajulu 	if (vf != OSAL_NULL) {
790217ec208SDavid C Somayajulu 		vf->ctx = ctx;
791217ec208SDavid C Somayajulu #ifdef CONFIG_ECORE_SW_CHANNEL
792217ec208SDavid C Somayajulu 		vf->vf_mbx.sw_mbx.mbx_state = VF_PF_WAIT_FOR_START_REQUEST;
793217ec208SDavid C Somayajulu #endif
794217ec208SDavid C Somayajulu 	} else {
795217ec208SDavid C Somayajulu 		rc = ECORE_UNKNOWN_ERROR;
796217ec208SDavid C Somayajulu 	}
797217ec208SDavid C Somayajulu 	return rc;
798217ec208SDavid C Somayajulu }
799217ec208SDavid C Somayajulu #endif
800217ec208SDavid C Somayajulu 
ecore_iov_vf_pglue_clear_err(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u8 abs_vfid)801217ec208SDavid C Somayajulu static void ecore_iov_vf_pglue_clear_err(struct ecore_hwfn      *p_hwfn,
802217ec208SDavid C Somayajulu 					 struct ecore_ptt	*p_ptt,
803217ec208SDavid C Somayajulu 					 u8			abs_vfid)
804217ec208SDavid C Somayajulu {
805217ec208SDavid C Somayajulu 	ecore_wr(p_hwfn, p_ptt,
806217ec208SDavid C Somayajulu 		 PGLUE_B_REG_WAS_ERROR_VF_31_0_CLR + (abs_vfid >> 5) * 4,
807217ec208SDavid C Somayajulu 		 1 << (abs_vfid & 0x1f));
808217ec208SDavid C Somayajulu }
809217ec208SDavid C Somayajulu 
ecore_iov_vf_igu_reset(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * vf)810217ec208SDavid C Somayajulu static void ecore_iov_vf_igu_reset(struct ecore_hwfn *p_hwfn,
811217ec208SDavid C Somayajulu 				   struct ecore_ptt *p_ptt,
812217ec208SDavid C Somayajulu 				   struct ecore_vf_info *vf)
813217ec208SDavid C Somayajulu {
814217ec208SDavid C Somayajulu 	int i;
815217ec208SDavid C Somayajulu 
816217ec208SDavid C Somayajulu 	/* Set VF masks and configuration - pretend */
817217ec208SDavid C Somayajulu 	ecore_fid_pretend(p_hwfn, p_ptt, (u16)vf->concrete_fid);
818217ec208SDavid C Somayajulu 
819217ec208SDavid C Somayajulu 	ecore_wr(p_hwfn, p_ptt, IGU_REG_STATISTIC_NUM_VF_MSG_SENT, 0);
820217ec208SDavid C Somayajulu 
821217ec208SDavid C Somayajulu 	/* unpretend */
822217ec208SDavid C Somayajulu 	ecore_fid_pretend(p_hwfn, p_ptt, (u16)p_hwfn->hw_info.concrete_fid);
823217ec208SDavid C Somayajulu 
824217ec208SDavid C Somayajulu 	/* iterate over all queues, clear sb consumer */
825217ec208SDavid C Somayajulu 	for (i = 0; i < vf->num_sbs; i++)
826217ec208SDavid C Somayajulu 		ecore_int_igu_init_pure_rt_single(p_hwfn, p_ptt,
827217ec208SDavid C Somayajulu 						  vf->igu_sbs[i],
828217ec208SDavid C Somayajulu 						  vf->opaque_fid, true);
829217ec208SDavid C Somayajulu }
830217ec208SDavid C Somayajulu 
ecore_iov_vf_igu_set_int(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * vf,bool enable)831217ec208SDavid C Somayajulu static void ecore_iov_vf_igu_set_int(struct ecore_hwfn		*p_hwfn,
832217ec208SDavid C Somayajulu 				     struct ecore_ptt		*p_ptt,
833217ec208SDavid C Somayajulu 				     struct ecore_vf_info	*vf,
834217ec208SDavid C Somayajulu 				     bool			enable)
835217ec208SDavid C Somayajulu {
836217ec208SDavid C Somayajulu 	u32 igu_vf_conf;
837217ec208SDavid C Somayajulu 
838217ec208SDavid C Somayajulu 	ecore_fid_pretend(p_hwfn, p_ptt, (u16)vf->concrete_fid);
839217ec208SDavid C Somayajulu 
840217ec208SDavid C Somayajulu 	igu_vf_conf = ecore_rd(p_hwfn, p_ptt, IGU_REG_VF_CONFIGURATION);
841217ec208SDavid C Somayajulu 
842217ec208SDavid C Somayajulu 	if (enable) {
843217ec208SDavid C Somayajulu 		igu_vf_conf |= IGU_VF_CONF_MSI_MSIX_EN;
844217ec208SDavid C Somayajulu 	} else {
845217ec208SDavid C Somayajulu 		igu_vf_conf &= ~IGU_VF_CONF_MSI_MSIX_EN;
846217ec208SDavid C Somayajulu 	}
847217ec208SDavid C Somayajulu 
848217ec208SDavid C Somayajulu 	ecore_wr(p_hwfn, p_ptt, IGU_REG_VF_CONFIGURATION, igu_vf_conf);
849217ec208SDavid C Somayajulu 
850217ec208SDavid C Somayajulu 	/* unpretend */
851217ec208SDavid C Somayajulu 	ecore_fid_pretend(p_hwfn, p_ptt, (u16)p_hwfn->hw_info.concrete_fid);
852217ec208SDavid C Somayajulu }
853217ec208SDavid C Somayajulu 
854217ec208SDavid C Somayajulu static enum _ecore_status_t
ecore_iov_enable_vf_access_msix(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u8 abs_vf_id,u8 num_sbs)855217ec208SDavid C Somayajulu ecore_iov_enable_vf_access_msix(struct ecore_hwfn *p_hwfn,
856217ec208SDavid C Somayajulu 				struct ecore_ptt *p_ptt,
857217ec208SDavid C Somayajulu 				u8 abs_vf_id,
858217ec208SDavid C Somayajulu 				u8 num_sbs)
859217ec208SDavid C Somayajulu {
860217ec208SDavid C Somayajulu 	u8 current_max = 0;
861217ec208SDavid C Somayajulu 	int i;
862217ec208SDavid C Somayajulu 
863217ec208SDavid C Somayajulu 	/* If client overrides this, don't do anything */
864217ec208SDavid C Somayajulu 	if (p_hwfn->p_dev->b_dont_override_vf_msix)
865217ec208SDavid C Somayajulu 		return ECORE_SUCCESS;
866217ec208SDavid C Somayajulu 
867217ec208SDavid C Somayajulu 	/* For AH onward, configuration is per-PF. Find maximum of all
868217ec208SDavid C Somayajulu 	 * the currently enabled child VFs, and set the number to be that.
869217ec208SDavid C Somayajulu 	 */
870217ec208SDavid C Somayajulu 	if (!ECORE_IS_BB(p_hwfn->p_dev)) {
871217ec208SDavid C Somayajulu 		ecore_for_each_vf(p_hwfn, i) {
872217ec208SDavid C Somayajulu 			struct ecore_vf_info *p_vf;
873217ec208SDavid C Somayajulu 
874217ec208SDavid C Somayajulu 			p_vf  = ecore_iov_get_vf_info(p_hwfn, (u16)i, true);
875217ec208SDavid C Somayajulu 			if (!p_vf)
876217ec208SDavid C Somayajulu 				continue;
877217ec208SDavid C Somayajulu 
878217ec208SDavid C Somayajulu 			current_max = OSAL_MAX_T(u8, current_max,
879217ec208SDavid C Somayajulu 						 p_vf->num_sbs);
880217ec208SDavid C Somayajulu 		}
881217ec208SDavid C Somayajulu 	}
882217ec208SDavid C Somayajulu 
883217ec208SDavid C Somayajulu 	if (num_sbs > current_max)
884217ec208SDavid C Somayajulu 		return ecore_mcp_config_vf_msix(p_hwfn, p_ptt,
885217ec208SDavid C Somayajulu 						abs_vf_id, num_sbs);
886217ec208SDavid C Somayajulu 
887217ec208SDavid C Somayajulu 	return ECORE_SUCCESS;
888217ec208SDavid C Somayajulu }
889217ec208SDavid C Somayajulu 
ecore_iov_enable_vf_access(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * vf)890217ec208SDavid C Somayajulu static enum _ecore_status_t ecore_iov_enable_vf_access(struct ecore_hwfn *p_hwfn,
891217ec208SDavid C Somayajulu 						       struct ecore_ptt *p_ptt,
892217ec208SDavid C Somayajulu 						       struct ecore_vf_info *vf)
893217ec208SDavid C Somayajulu {
894217ec208SDavid C Somayajulu 	u32 igu_vf_conf = IGU_VF_CONF_FUNC_EN;
895217ec208SDavid C Somayajulu 	enum _ecore_status_t rc = ECORE_SUCCESS;
896217ec208SDavid C Somayajulu 
897217ec208SDavid C Somayajulu 	/* It's possible VF was previously considered malicious -
898217ec208SDavid C Somayajulu 	 * clear the indication even if we're only going to disable VF.
899217ec208SDavid C Somayajulu 	 */
900217ec208SDavid C Somayajulu 	vf->b_malicious = false;
901217ec208SDavid C Somayajulu 
902217ec208SDavid C Somayajulu 	if (vf->to_disable)
903217ec208SDavid C Somayajulu 		return ECORE_SUCCESS;
904217ec208SDavid C Somayajulu 
905217ec208SDavid C Somayajulu 	DP_VERBOSE(p_hwfn, ECORE_MSG_IOV, "Enable internal access for vf %x [abs %x]\n",
906217ec208SDavid C Somayajulu 		   vf->abs_vf_id, ECORE_VF_ABS_ID(p_hwfn, vf));
907217ec208SDavid C Somayajulu 
908217ec208SDavid C Somayajulu 	ecore_iov_vf_pglue_clear_err(p_hwfn, p_ptt,
909217ec208SDavid C Somayajulu 				     ECORE_VF_ABS_ID(p_hwfn, vf));
910217ec208SDavid C Somayajulu 
911217ec208SDavid C Somayajulu 	ecore_iov_vf_igu_reset(p_hwfn, p_ptt, vf);
912217ec208SDavid C Somayajulu 
913217ec208SDavid C Somayajulu 	rc = ecore_iov_enable_vf_access_msix(p_hwfn, p_ptt,
914217ec208SDavid C Somayajulu 					     vf->abs_vf_id, vf->num_sbs);
915217ec208SDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
916217ec208SDavid C Somayajulu 		return rc;
917217ec208SDavid C Somayajulu 
918217ec208SDavid C Somayajulu 	ecore_fid_pretend(p_hwfn, p_ptt, (u16)vf->concrete_fid);
919217ec208SDavid C Somayajulu 
920217ec208SDavid C Somayajulu 	SET_FIELD(igu_vf_conf, IGU_VF_CONF_PARENT, p_hwfn->rel_pf_id);
921217ec208SDavid C Somayajulu 	STORE_RT_REG(p_hwfn, IGU_REG_VF_CONFIGURATION_RT_OFFSET, igu_vf_conf);
922217ec208SDavid C Somayajulu 
923217ec208SDavid C Somayajulu 	ecore_init_run(p_hwfn, p_ptt, PHASE_VF, vf->abs_vf_id,
924217ec208SDavid C Somayajulu 		       p_hwfn->hw_info.hw_mode);
925217ec208SDavid C Somayajulu 
926217ec208SDavid C Somayajulu 	/* unpretend */
927217ec208SDavid C Somayajulu 	ecore_fid_pretend(p_hwfn, p_ptt, (u16)p_hwfn->hw_info.concrete_fid);
928217ec208SDavid C Somayajulu 
929217ec208SDavid C Somayajulu 	vf->state = VF_FREE;
930217ec208SDavid C Somayajulu 
931217ec208SDavid C Somayajulu 	return rc;
932217ec208SDavid C Somayajulu }
933217ec208SDavid C Somayajulu 
934217ec208SDavid C Somayajulu /**
935217ec208SDavid C Somayajulu  * @brief ecore_iov_config_perm_table - configure the permission
936217ec208SDavid C Somayajulu  *      zone table.
937217ec208SDavid C Somayajulu  *      In E4, queue zone permission table size is 320x9. There
938217ec208SDavid C Somayajulu  *      are 320 VF queues for single engine device (256 for dual
939217ec208SDavid C Somayajulu  *      engine device), and each entry has the following format:
940217ec208SDavid C Somayajulu  *      {Valid, VF[7:0]}
941217ec208SDavid C Somayajulu  * @param p_hwfn
942217ec208SDavid C Somayajulu  * @param p_ptt
943217ec208SDavid C Somayajulu  * @param vf
944217ec208SDavid C Somayajulu  * @param enable
945217ec208SDavid C Somayajulu  */
ecore_iov_config_perm_table(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * vf,u8 enable)946217ec208SDavid C Somayajulu static void ecore_iov_config_perm_table(struct ecore_hwfn	*p_hwfn,
947217ec208SDavid C Somayajulu 					struct ecore_ptt	*p_ptt,
948217ec208SDavid C Somayajulu 					struct ecore_vf_info	*vf,
949217ec208SDavid C Somayajulu 					u8			enable)
950217ec208SDavid C Somayajulu {
951217ec208SDavid C Somayajulu 	u32 reg_addr, val;
952217ec208SDavid C Somayajulu 	u16 qzone_id = 0;
953217ec208SDavid C Somayajulu 	int qid;
954217ec208SDavid C Somayajulu 
955217ec208SDavid C Somayajulu 	for (qid = 0; qid < vf->num_rxqs; qid++) {
956217ec208SDavid C Somayajulu 		ecore_fw_l2_queue(p_hwfn, vf->vf_queues[qid].fw_rx_qid,
957217ec208SDavid C Somayajulu 				  &qzone_id);
958217ec208SDavid C Somayajulu 
959217ec208SDavid C Somayajulu 		reg_addr = PSWHST_REG_ZONE_PERMISSION_TABLE + qzone_id * 4;
960217ec208SDavid C Somayajulu 		val = enable ? (vf->abs_vf_id | (1 << 8)) : 0;
961217ec208SDavid C Somayajulu 		ecore_wr(p_hwfn, p_ptt, reg_addr, val);
962217ec208SDavid C Somayajulu 	}
963217ec208SDavid C Somayajulu }
964217ec208SDavid C Somayajulu 
ecore_iov_enable_vf_traffic(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * vf)965217ec208SDavid C Somayajulu static void ecore_iov_enable_vf_traffic(struct ecore_hwfn *p_hwfn,
966217ec208SDavid C Somayajulu 					struct ecore_ptt *p_ptt,
967217ec208SDavid C Somayajulu 					struct ecore_vf_info *vf)
968217ec208SDavid C Somayajulu {
969217ec208SDavid C Somayajulu 	/* Reset vf in IGU - interrupts are still disabled */
970217ec208SDavid C Somayajulu 	ecore_iov_vf_igu_reset(p_hwfn, p_ptt, vf);
971217ec208SDavid C Somayajulu 
972217ec208SDavid C Somayajulu 	ecore_iov_vf_igu_set_int(p_hwfn, p_ptt, vf, 1);
973217ec208SDavid C Somayajulu 
974217ec208SDavid C Somayajulu 	/* Permission Table */
975217ec208SDavid C Somayajulu 	ecore_iov_config_perm_table(p_hwfn, p_ptt, vf, true);
976217ec208SDavid C Somayajulu }
977217ec208SDavid C Somayajulu 
ecore_iov_alloc_vf_igu_sbs(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * vf,u16 num_rx_queues)978217ec208SDavid C Somayajulu static u8 ecore_iov_alloc_vf_igu_sbs(struct ecore_hwfn *p_hwfn,
979217ec208SDavid C Somayajulu 				     struct ecore_ptt *p_ptt,
980217ec208SDavid C Somayajulu 				     struct ecore_vf_info *vf,
981217ec208SDavid C Somayajulu 				     u16 num_rx_queues)
982217ec208SDavid C Somayajulu {
983217ec208SDavid C Somayajulu 	struct ecore_igu_block *p_block;
984217ec208SDavid C Somayajulu 	struct cau_sb_entry sb_entry;
985217ec208SDavid C Somayajulu 	int qid = 0;
986217ec208SDavid C Somayajulu 	u32 val = 0;
987217ec208SDavid C Somayajulu 
988217ec208SDavid C Somayajulu 	if (num_rx_queues > p_hwfn->hw_info.p_igu_info->usage.free_cnt_iov)
989217ec208SDavid C Somayajulu 		num_rx_queues =
990217ec208SDavid C Somayajulu 		(u16)p_hwfn->hw_info.p_igu_info->usage.free_cnt_iov;
991217ec208SDavid C Somayajulu 	p_hwfn->hw_info.p_igu_info->usage.free_cnt_iov -= num_rx_queues;
992217ec208SDavid C Somayajulu 
993217ec208SDavid C Somayajulu 	SET_FIELD(val, IGU_MAPPING_LINE_FUNCTION_NUMBER, vf->abs_vf_id);
994217ec208SDavid C Somayajulu 	SET_FIELD(val, IGU_MAPPING_LINE_VALID, 1);
995217ec208SDavid C Somayajulu 	SET_FIELD(val, IGU_MAPPING_LINE_PF_VALID, 0);
996217ec208SDavid C Somayajulu 
997217ec208SDavid C Somayajulu 	for (qid = 0; qid < num_rx_queues; qid++) {
998217ec208SDavid C Somayajulu 		p_block = ecore_get_igu_free_sb(p_hwfn, false);
999217ec208SDavid C Somayajulu 		vf->igu_sbs[qid] = p_block->igu_sb_id;
1000217ec208SDavid C Somayajulu 		p_block->status &= ~ECORE_IGU_STATUS_FREE;
1001217ec208SDavid C Somayajulu 		SET_FIELD(val, IGU_MAPPING_LINE_VECTOR_NUMBER, qid);
1002217ec208SDavid C Somayajulu 
1003217ec208SDavid C Somayajulu 		ecore_wr(p_hwfn, p_ptt,
1004217ec208SDavid C Somayajulu 			 IGU_REG_MAPPING_MEMORY +
1005217ec208SDavid C Somayajulu 			 sizeof(u32) * p_block->igu_sb_id, val);
1006217ec208SDavid C Somayajulu 
1007217ec208SDavid C Somayajulu 		/* Configure igu sb in CAU which were marked valid */
1008217ec208SDavid C Somayajulu 		ecore_init_cau_sb_entry(p_hwfn, &sb_entry,
1009217ec208SDavid C Somayajulu 					p_hwfn->rel_pf_id,
1010217ec208SDavid C Somayajulu 					vf->abs_vf_id, 1);
1011217ec208SDavid C Somayajulu 
1012217ec208SDavid C Somayajulu 		ecore_dmae_host2grc(p_hwfn, p_ptt,
1013217ec208SDavid C Somayajulu 				    (u64)(osal_uintptr_t)&sb_entry,
1014217ec208SDavid C Somayajulu 				    CAU_REG_SB_VAR_MEMORY +
1015217ec208SDavid C Somayajulu 				    p_block->igu_sb_id * sizeof(u64), 2,
1016217ec208SDavid C Somayajulu 				    OSAL_NULL /* default parameters */);
1017217ec208SDavid C Somayajulu 	}
1018217ec208SDavid C Somayajulu 
1019217ec208SDavid C Somayajulu 	vf->num_sbs = (u8)num_rx_queues;
1020217ec208SDavid C Somayajulu 
1021217ec208SDavid C Somayajulu 	return vf->num_sbs;
1022217ec208SDavid C Somayajulu }
1023217ec208SDavid C Somayajulu 
1024217ec208SDavid C Somayajulu /**
1025217ec208SDavid C Somayajulu  *
1026217ec208SDavid C Somayajulu  * @brief The function invalidates all the VF entries,
1027217ec208SDavid C Somayajulu  *        technically this isn't required, but added for
1028217ec208SDavid C Somayajulu  *        cleaness and ease of debugging incase a VF attempts to
1029217ec208SDavid C Somayajulu  *        produce an interrupt after it has been taken down.
1030217ec208SDavid C Somayajulu  *
1031217ec208SDavid C Somayajulu  * @param p_hwfn
1032217ec208SDavid C Somayajulu  * @param p_ptt
1033217ec208SDavid C Somayajulu  * @param vf
1034217ec208SDavid C Somayajulu  */
ecore_iov_free_vf_igu_sbs(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * vf)1035217ec208SDavid C Somayajulu static void ecore_iov_free_vf_igu_sbs(struct ecore_hwfn *p_hwfn,
1036217ec208SDavid C Somayajulu 				      struct ecore_ptt *p_ptt,
1037217ec208SDavid C Somayajulu 				      struct ecore_vf_info *vf)
1038217ec208SDavid C Somayajulu 
1039217ec208SDavid C Somayajulu {
1040217ec208SDavid C Somayajulu 	struct ecore_igu_info *p_info = p_hwfn->hw_info.p_igu_info;
1041217ec208SDavid C Somayajulu 	int idx, igu_id;
1042217ec208SDavid C Somayajulu 	u32 addr, val;
1043217ec208SDavid C Somayajulu 
1044217ec208SDavid C Somayajulu 	/* Invalidate igu CAM lines and mark them as free */
1045217ec208SDavid C Somayajulu 	for (idx = 0; idx < vf->num_sbs; idx++) {
1046217ec208SDavid C Somayajulu 		igu_id = vf->igu_sbs[idx];
1047217ec208SDavid C Somayajulu 		addr = IGU_REG_MAPPING_MEMORY +
1048217ec208SDavid C Somayajulu 		       sizeof(u32) * igu_id;
1049217ec208SDavid C Somayajulu 
1050217ec208SDavid C Somayajulu 		val = ecore_rd(p_hwfn, p_ptt, addr);
1051217ec208SDavid C Somayajulu 		SET_FIELD(val, IGU_MAPPING_LINE_VALID, 0);
1052217ec208SDavid C Somayajulu 		ecore_wr(p_hwfn, p_ptt, addr, val);
1053217ec208SDavid C Somayajulu 
1054217ec208SDavid C Somayajulu 		p_info->entry[igu_id].status |= ECORE_IGU_STATUS_FREE;
1055217ec208SDavid C Somayajulu 		p_hwfn->hw_info.p_igu_info->usage.free_cnt_iov++;
1056217ec208SDavid C Somayajulu 	}
1057217ec208SDavid C Somayajulu 
1058217ec208SDavid C Somayajulu 	vf->num_sbs = 0;
1059217ec208SDavid C Somayajulu }
1060217ec208SDavid C Somayajulu 
ecore_iov_set_link(struct ecore_hwfn * p_hwfn,u16 vfid,struct ecore_mcp_link_params * params,struct ecore_mcp_link_state * link,struct ecore_mcp_link_capabilities * p_caps)1061217ec208SDavid C Somayajulu void ecore_iov_set_link(struct ecore_hwfn *p_hwfn,
1062217ec208SDavid C Somayajulu 			u16 vfid,
1063217ec208SDavid C Somayajulu 			struct ecore_mcp_link_params *params,
1064217ec208SDavid C Somayajulu 			struct ecore_mcp_link_state *link,
1065217ec208SDavid C Somayajulu 			struct ecore_mcp_link_capabilities *p_caps)
1066217ec208SDavid C Somayajulu {
1067217ec208SDavid C Somayajulu 	struct ecore_vf_info *p_vf = ecore_iov_get_vf_info(p_hwfn, vfid, false);
1068217ec208SDavid C Somayajulu 	struct ecore_bulletin_content *p_bulletin;
1069217ec208SDavid C Somayajulu 
1070217ec208SDavid C Somayajulu 	if (!p_vf)
1071217ec208SDavid C Somayajulu 		return;
1072217ec208SDavid C Somayajulu 
1073217ec208SDavid C Somayajulu 	p_bulletin = p_vf->bulletin.p_virt;
1074217ec208SDavid C Somayajulu 	p_bulletin->req_autoneg = params->speed.autoneg;
1075217ec208SDavid C Somayajulu 	p_bulletin->req_adv_speed = params->speed.advertised_speeds;
1076217ec208SDavid C Somayajulu 	p_bulletin->req_forced_speed = params->speed.forced_speed;
1077217ec208SDavid C Somayajulu 	p_bulletin->req_autoneg_pause = params->pause.autoneg;
1078217ec208SDavid C Somayajulu 	p_bulletin->req_forced_rx = params->pause.forced_rx;
1079217ec208SDavid C Somayajulu 	p_bulletin->req_forced_tx = params->pause.forced_tx;
1080217ec208SDavid C Somayajulu 	p_bulletin->req_loopback = params->loopback_mode;
1081217ec208SDavid C Somayajulu 
1082217ec208SDavid C Somayajulu 	p_bulletin->link_up = link->link_up;
1083217ec208SDavid C Somayajulu 	p_bulletin->speed = link->speed;
1084217ec208SDavid C Somayajulu 	p_bulletin->full_duplex = link->full_duplex;
1085217ec208SDavid C Somayajulu 	p_bulletin->autoneg = link->an;
1086217ec208SDavid C Somayajulu 	p_bulletin->autoneg_complete = link->an_complete;
1087217ec208SDavid C Somayajulu 	p_bulletin->parallel_detection = link->parallel_detection;
1088217ec208SDavid C Somayajulu 	p_bulletin->pfc_enabled = link->pfc_enabled;
1089217ec208SDavid C Somayajulu 	p_bulletin->partner_adv_speed = link->partner_adv_speed;
1090217ec208SDavid C Somayajulu 	p_bulletin->partner_tx_flow_ctrl_en = link->partner_tx_flow_ctrl_en;
1091217ec208SDavid C Somayajulu 	p_bulletin->partner_rx_flow_ctrl_en = link->partner_rx_flow_ctrl_en;
1092217ec208SDavid C Somayajulu 	p_bulletin->partner_adv_pause = link->partner_adv_pause;
1093217ec208SDavid C Somayajulu 	p_bulletin->sfp_tx_fault = link->sfp_tx_fault;
1094217ec208SDavid C Somayajulu 
1095217ec208SDavid C Somayajulu 	p_bulletin->capability_speed = p_caps->speed_capabilities;
1096217ec208SDavid C Somayajulu }
1097217ec208SDavid C Somayajulu 
1098217ec208SDavid C Somayajulu enum _ecore_status_t
ecore_iov_init_hw_for_vf(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_iov_vf_init_params * p_params)1099217ec208SDavid C Somayajulu ecore_iov_init_hw_for_vf(struct ecore_hwfn *p_hwfn,
1100217ec208SDavid C Somayajulu 			 struct ecore_ptt *p_ptt,
1101217ec208SDavid C Somayajulu 			 struct ecore_iov_vf_init_params *p_params)
1102217ec208SDavid C Somayajulu {
1103217ec208SDavid C Somayajulu 	struct ecore_mcp_link_capabilities link_caps;
1104217ec208SDavid C Somayajulu 	struct ecore_mcp_link_params link_params;
1105217ec208SDavid C Somayajulu 	struct ecore_mcp_link_state link_state;
1106217ec208SDavid C Somayajulu 	u8 num_of_vf_avaiable_chains  = 0;
1107217ec208SDavid C Somayajulu 	struct ecore_vf_info *vf = OSAL_NULL;
1108217ec208SDavid C Somayajulu 	u16 qid, num_irqs;
1109217ec208SDavid C Somayajulu 	enum _ecore_status_t rc = ECORE_SUCCESS;
1110217ec208SDavid C Somayajulu 	u32 cids;
1111217ec208SDavid C Somayajulu 	u8 i;
1112217ec208SDavid C Somayajulu 
1113217ec208SDavid C Somayajulu 	vf = ecore_iov_get_vf_info(p_hwfn, p_params->rel_vf_id, false);
1114217ec208SDavid C Somayajulu 	if (!vf) {
1115217ec208SDavid C Somayajulu 		DP_ERR(p_hwfn, "ecore_iov_init_hw_for_vf : vf is OSAL_NULL\n");
1116217ec208SDavid C Somayajulu 		return ECORE_UNKNOWN_ERROR;
1117217ec208SDavid C Somayajulu 	}
1118217ec208SDavid C Somayajulu 
1119217ec208SDavid C Somayajulu 	if (vf->b_init) {
1120217ec208SDavid C Somayajulu 		DP_NOTICE(p_hwfn, true, "VF[%d] is already active.\n",
1121217ec208SDavid C Somayajulu 			  p_params->rel_vf_id);
1122217ec208SDavid C Somayajulu 		return ECORE_INVAL;
1123217ec208SDavid C Somayajulu 	}
1124217ec208SDavid C Somayajulu 
1125217ec208SDavid C Somayajulu 	/* Perform sanity checking on the requested vport/rss */
1126217ec208SDavid C Somayajulu 	if (p_params->vport_id >= RESC_NUM(p_hwfn, ECORE_VPORT)) {
1127217ec208SDavid C Somayajulu 		DP_NOTICE(p_hwfn, true, "VF[%d] - can't use VPORT %02x\n",
1128217ec208SDavid C Somayajulu 			  p_params->rel_vf_id, p_params->vport_id);
1129217ec208SDavid C Somayajulu 		return ECORE_INVAL;
1130217ec208SDavid C Somayajulu 	}
1131217ec208SDavid C Somayajulu 
1132217ec208SDavid C Somayajulu 	if ((p_params->num_queues > 1) &&
1133217ec208SDavid C Somayajulu 	    (p_params->rss_eng_id >= RESC_NUM(p_hwfn, ECORE_RSS_ENG))) {
1134217ec208SDavid C Somayajulu 		DP_NOTICE(p_hwfn, true, "VF[%d] - can't use RSS_ENG %02x\n",
1135217ec208SDavid C Somayajulu 			  p_params->rel_vf_id, p_params->rss_eng_id);
1136217ec208SDavid C Somayajulu 		return ECORE_INVAL;
1137217ec208SDavid C Somayajulu 	}
1138217ec208SDavid C Somayajulu 
1139217ec208SDavid C Somayajulu 	/* TODO - remove this once we get confidence of change */
1140217ec208SDavid C Somayajulu 	if (!p_params->vport_id) {
1141217ec208SDavid C Somayajulu 		DP_NOTICE(p_hwfn, false,
1142217ec208SDavid C Somayajulu 			  "VF[%d] - Unlikely that VF uses vport0. Forgotten?\n",
1143217ec208SDavid C Somayajulu 			  p_params->rel_vf_id);
1144217ec208SDavid C Somayajulu 	}
1145217ec208SDavid C Somayajulu 	if ((!p_params->rss_eng_id) && (p_params->num_queues > 1)) {
1146217ec208SDavid C Somayajulu 		DP_NOTICE(p_hwfn, false,
1147217ec208SDavid C Somayajulu 			  "VF[%d] - Unlikely that VF uses RSS_eng0. Forgotten?\n",
1148217ec208SDavid C Somayajulu 			  p_params->rel_vf_id);
1149217ec208SDavid C Somayajulu 	}
1150217ec208SDavid C Somayajulu 	vf->vport_id = p_params->vport_id;
1151217ec208SDavid C Somayajulu 	vf->rss_eng_id = p_params->rss_eng_id;
1152217ec208SDavid C Somayajulu 
1153217ec208SDavid C Somayajulu 	/* Since it's possible to relocate SBs, it's a bit difficult to check
1154217ec208SDavid C Somayajulu 	 * things here. Simply check whether the index falls in the range
1155217ec208SDavid C Somayajulu 	 * belonging to the PF.
1156217ec208SDavid C Somayajulu 	 */
1157217ec208SDavid C Somayajulu 	for (i = 0; i < p_params->num_queues; i++) {
1158217ec208SDavid C Somayajulu 		qid = p_params->req_rx_queue[i];
1159217ec208SDavid C Somayajulu 		if (qid > (u16)RESC_NUM(p_hwfn, ECORE_L2_QUEUE)) {
1160217ec208SDavid C Somayajulu 			DP_NOTICE(p_hwfn, true,
1161217ec208SDavid C Somayajulu 				  "Can't enable Rx qid [%04x] for VF[%d]: qids [0,,...,0x%04x] available\n",
1162217ec208SDavid C Somayajulu 				  qid, p_params->rel_vf_id,
1163217ec208SDavid C Somayajulu 				  (u16)RESC_NUM(p_hwfn, ECORE_L2_QUEUE));
1164217ec208SDavid C Somayajulu 			return ECORE_INVAL;
1165217ec208SDavid C Somayajulu 		}
1166217ec208SDavid C Somayajulu 
1167217ec208SDavid C Somayajulu 		qid = p_params->req_tx_queue[i];
1168217ec208SDavid C Somayajulu 		if (qid > (u16)RESC_NUM(p_hwfn, ECORE_L2_QUEUE)) {
1169217ec208SDavid C Somayajulu 			DP_NOTICE(p_hwfn, true,
1170217ec208SDavid C Somayajulu 				  "Can't enable Tx qid [%04x] for VF[%d]: qids [0,,...,0x%04x] available\n",
1171217ec208SDavid C Somayajulu 				  qid, p_params->rel_vf_id,
1172217ec208SDavid C Somayajulu 				  (u16)RESC_NUM(p_hwfn, ECORE_L2_QUEUE));
1173217ec208SDavid C Somayajulu 			return ECORE_INVAL;
1174217ec208SDavid C Somayajulu 		}
1175217ec208SDavid C Somayajulu 	}
1176217ec208SDavid C Somayajulu 
1177217ec208SDavid C Somayajulu 	/* Limit number of queues according to number of CIDs */
1178217ec208SDavid C Somayajulu 	ecore_cxt_get_proto_cid_count(p_hwfn, PROTOCOLID_ETH, &cids);
1179217ec208SDavid C Somayajulu 	DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
1180217ec208SDavid C Somayajulu 		   "VF[%d] - requesting to initialize for 0x%04x queues [0x%04x CIDs available]\n",
1181217ec208SDavid C Somayajulu 		   vf->relative_vf_id, p_params->num_queues, (u16)cids);
1182217ec208SDavid C Somayajulu 	num_irqs = OSAL_MIN_T(u16, p_params->num_queues, ((u16)cids));
1183217ec208SDavid C Somayajulu 
1184217ec208SDavid C Somayajulu 	num_of_vf_avaiable_chains = ecore_iov_alloc_vf_igu_sbs(p_hwfn,
1185217ec208SDavid C Somayajulu 							       p_ptt,
1186217ec208SDavid C Somayajulu 							       vf,
1187217ec208SDavid C Somayajulu 							       num_irqs);
1188217ec208SDavid C Somayajulu 	if (num_of_vf_avaiable_chains == 0) {
1189217ec208SDavid C Somayajulu 		DP_ERR(p_hwfn, "no available igu sbs\n");
1190217ec208SDavid C Somayajulu 		return ECORE_NOMEM;
1191217ec208SDavid C Somayajulu 	}
1192217ec208SDavid C Somayajulu 
1193217ec208SDavid C Somayajulu 	/* Choose queue number and index ranges */
1194217ec208SDavid C Somayajulu 	vf->num_rxqs = num_of_vf_avaiable_chains;
1195217ec208SDavid C Somayajulu 	vf->num_txqs = num_of_vf_avaiable_chains;
1196217ec208SDavid C Somayajulu 
1197217ec208SDavid C Somayajulu 	for (i = 0; i < vf->num_rxqs; i++) {
1198217ec208SDavid C Somayajulu 		struct ecore_vf_queue *p_queue = &vf->vf_queues[i];
1199217ec208SDavid C Somayajulu 
1200217ec208SDavid C Somayajulu 		p_queue->fw_rx_qid = p_params->req_rx_queue[i];
1201217ec208SDavid C Somayajulu 		p_queue->fw_tx_qid = p_params->req_tx_queue[i];
1202217ec208SDavid C Somayajulu 
1203217ec208SDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
1204217ec208SDavid C Somayajulu 			   "VF[%d] - Q[%d] SB %04x, qid [Rx %04x Tx %04x]\n",
1205217ec208SDavid C Somayajulu 			   vf->relative_vf_id, i, vf->igu_sbs[i],
1206217ec208SDavid C Somayajulu 			   p_queue->fw_rx_qid, p_queue->fw_tx_qid);
1207217ec208SDavid C Somayajulu 	}
1208217ec208SDavid C Somayajulu 
1209217ec208SDavid C Somayajulu 	/* Update the link configuration in bulletin.
1210217ec208SDavid C Somayajulu 	 */
1211217ec208SDavid C Somayajulu 	OSAL_MEMCPY(&link_params, ecore_mcp_get_link_params(p_hwfn),
1212217ec208SDavid C Somayajulu 		    sizeof(link_params));
1213217ec208SDavid C Somayajulu 	OSAL_MEMCPY(&link_state, ecore_mcp_get_link_state(p_hwfn),
1214217ec208SDavid C Somayajulu 		    sizeof(link_state));
1215217ec208SDavid C Somayajulu 	OSAL_MEMCPY(&link_caps, ecore_mcp_get_link_capabilities(p_hwfn),
1216217ec208SDavid C Somayajulu 		    sizeof(link_caps));
1217217ec208SDavid C Somayajulu 	ecore_iov_set_link(p_hwfn, p_params->rel_vf_id,
1218217ec208SDavid C Somayajulu 			   &link_params, &link_state, &link_caps);
1219217ec208SDavid C Somayajulu 
1220217ec208SDavid C Somayajulu 	rc = ecore_iov_enable_vf_access(p_hwfn, p_ptt, vf);
1221217ec208SDavid C Somayajulu 
1222217ec208SDavid C Somayajulu 	if (rc == ECORE_SUCCESS) {
1223217ec208SDavid C Somayajulu 		vf->b_init = true;
1224217ec208SDavid C Somayajulu #ifndef REMOVE_DBG
1225217ec208SDavid C Somayajulu 		p_hwfn->pf_iov_info->active_vfs[vf->relative_vf_id / 64] |=
1226217ec208SDavid C Somayajulu 			(1ULL << (vf->relative_vf_id % 64));
1227217ec208SDavid C Somayajulu #endif
1228217ec208SDavid C Somayajulu 
1229217ec208SDavid C Somayajulu 		if (IS_LEAD_HWFN(p_hwfn))
1230217ec208SDavid C Somayajulu 			p_hwfn->p_dev->p_iov_info->num_vfs++;
1231217ec208SDavid C Somayajulu 	}
1232217ec208SDavid C Somayajulu 
1233217ec208SDavid C Somayajulu 	return rc;
1234217ec208SDavid C Somayajulu }
1235217ec208SDavid C Somayajulu 
ecore_iov_release_hw_for_vf(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u16 rel_vf_id)1236217ec208SDavid C Somayajulu enum _ecore_status_t ecore_iov_release_hw_for_vf(struct ecore_hwfn *p_hwfn,
1237217ec208SDavid C Somayajulu 						 struct ecore_ptt  *p_ptt,
1238217ec208SDavid C Somayajulu 						 u16               rel_vf_id)
1239217ec208SDavid C Somayajulu {
1240217ec208SDavid C Somayajulu 	struct ecore_mcp_link_capabilities caps;
1241217ec208SDavid C Somayajulu 	struct ecore_mcp_link_params params;
1242217ec208SDavid C Somayajulu 	struct ecore_mcp_link_state link;
1243217ec208SDavid C Somayajulu 	struct ecore_vf_info *vf = OSAL_NULL;
1244217ec208SDavid C Somayajulu 
1245217ec208SDavid C Somayajulu 	vf = ecore_iov_get_vf_info(p_hwfn, rel_vf_id, true);
1246217ec208SDavid C Somayajulu 	if (!vf) {
1247217ec208SDavid C Somayajulu 		DP_ERR(p_hwfn, "ecore_iov_release_hw_for_vf : vf is NULL\n");
1248217ec208SDavid C Somayajulu 		return ECORE_UNKNOWN_ERROR;
1249217ec208SDavid C Somayajulu 	}
1250217ec208SDavid C Somayajulu 
1251217ec208SDavid C Somayajulu 	if (vf->bulletin.p_virt)
1252217ec208SDavid C Somayajulu 		OSAL_MEMSET(vf->bulletin.p_virt, 0,
1253217ec208SDavid C Somayajulu 			    sizeof(*vf->bulletin.p_virt));
1254217ec208SDavid C Somayajulu 
1255217ec208SDavid C Somayajulu 	OSAL_MEMSET(&vf->p_vf_info, 0, sizeof(vf->p_vf_info));
1256217ec208SDavid C Somayajulu 
1257217ec208SDavid C Somayajulu 	/* Get the link configuration back in bulletin so
1258217ec208SDavid C Somayajulu 	 * that when VFs are re-enabled they get the actual
1259217ec208SDavid C Somayajulu 	 * link configuration.
1260217ec208SDavid C Somayajulu 	 */
1261217ec208SDavid C Somayajulu 	OSAL_MEMCPY(&params, ecore_mcp_get_link_params(p_hwfn), sizeof(params));
1262217ec208SDavid C Somayajulu 	OSAL_MEMCPY(&link, ecore_mcp_get_link_state(p_hwfn), sizeof(link));
1263217ec208SDavid C Somayajulu 	OSAL_MEMCPY(&caps, ecore_mcp_get_link_capabilities(p_hwfn),
1264217ec208SDavid C Somayajulu 		    sizeof(caps));
1265217ec208SDavid C Somayajulu 	ecore_iov_set_link(p_hwfn, rel_vf_id, &params, &link, &caps);
1266217ec208SDavid C Somayajulu 
1267217ec208SDavid C Somayajulu 	/* Forget the VF's acquisition message */
1268217ec208SDavid C Somayajulu 	OSAL_MEMSET(&vf->acquire, 0, sizeof(vf->acquire));
1269217ec208SDavid C Somayajulu 
1270217ec208SDavid C Somayajulu 	/* disablng interrupts and resetting permission table was done during
1271217ec208SDavid C Somayajulu 	 * vf-close, however, we could get here without going through vf_close
1272217ec208SDavid C Somayajulu 	 */
1273217ec208SDavid C Somayajulu 	/* Disable Interrupts for VF */
1274217ec208SDavid C Somayajulu 	ecore_iov_vf_igu_set_int(p_hwfn, p_ptt, vf, 0);
1275217ec208SDavid C Somayajulu 
1276217ec208SDavid C Somayajulu 	/* Reset Permission table */
1277217ec208SDavid C Somayajulu 	ecore_iov_config_perm_table(p_hwfn, p_ptt, vf, 0);
1278217ec208SDavid C Somayajulu 
1279217ec208SDavid C Somayajulu 	vf->num_rxqs = 0;
1280217ec208SDavid C Somayajulu 	vf->num_txqs = 0;
1281217ec208SDavid C Somayajulu 	ecore_iov_free_vf_igu_sbs(p_hwfn, p_ptt, vf);
1282217ec208SDavid C Somayajulu 
1283217ec208SDavid C Somayajulu 	if (vf->b_init) {
1284217ec208SDavid C Somayajulu 		vf->b_init = false;
1285217ec208SDavid C Somayajulu #ifndef REMOVE_DBG
1286217ec208SDavid C Somayajulu 		p_hwfn->pf_iov_info->active_vfs[vf->relative_vf_id / 64] &=
1287217ec208SDavid C Somayajulu 					~(1ULL << (vf->relative_vf_id / 64));
1288217ec208SDavid C Somayajulu #endif
1289217ec208SDavid C Somayajulu 
1290217ec208SDavid C Somayajulu 		if (IS_LEAD_HWFN(p_hwfn))
1291217ec208SDavid C Somayajulu 			p_hwfn->p_dev->p_iov_info->num_vfs--;
1292217ec208SDavid C Somayajulu 	}
1293217ec208SDavid C Somayajulu 
1294217ec208SDavid C Somayajulu 	return ECORE_SUCCESS;
1295217ec208SDavid C Somayajulu }
1296217ec208SDavid C Somayajulu 
ecore_iov_tlv_supported(u16 tlvtype)1297217ec208SDavid C Somayajulu static bool ecore_iov_tlv_supported(u16 tlvtype)
1298217ec208SDavid C Somayajulu {
1299217ec208SDavid C Somayajulu 	return CHANNEL_TLV_NONE < tlvtype && tlvtype < CHANNEL_TLV_MAX;
1300217ec208SDavid C Somayajulu }
1301217ec208SDavid C Somayajulu 
ecore_iov_lock_vf_pf_channel(struct ecore_hwfn * p_hwfn,struct ecore_vf_info * vf,u16 tlv)1302217ec208SDavid C Somayajulu static void ecore_iov_lock_vf_pf_channel(struct ecore_hwfn *p_hwfn,
1303217ec208SDavid C Somayajulu 					 struct ecore_vf_info *vf,
1304217ec208SDavid C Somayajulu 					 u16 tlv)
1305217ec208SDavid C Somayajulu {
1306217ec208SDavid C Somayajulu 	/* lock the channel */
1307217ec208SDavid C Somayajulu 	/* mutex_lock(&vf->op_mutex); @@@TBD MichalK - add lock... */
1308217ec208SDavid C Somayajulu 
1309217ec208SDavid C Somayajulu 	/* record the locking op */
1310217ec208SDavid C Somayajulu 	/* vf->op_current = tlv; @@@TBD MichalK */
1311217ec208SDavid C Somayajulu 
1312217ec208SDavid C Somayajulu 	/* log the lock */
1313217ec208SDavid C Somayajulu 	if (ecore_iov_tlv_supported(tlv))
1314217ec208SDavid C Somayajulu 		DP_VERBOSE(p_hwfn,
1315217ec208SDavid C Somayajulu 			   ECORE_MSG_IOV,
1316217ec208SDavid C Somayajulu 			   "VF[%d]: vf pf channel locked by %s\n",
1317217ec208SDavid C Somayajulu 			   vf->abs_vf_id,
1318217ec208SDavid C Somayajulu 			   ecore_channel_tlvs_string[tlv]);
1319217ec208SDavid C Somayajulu 	else
1320217ec208SDavid C Somayajulu 		DP_VERBOSE(p_hwfn,
1321217ec208SDavid C Somayajulu 			   ECORE_MSG_IOV,
1322217ec208SDavid C Somayajulu 			   "VF[%d]: vf pf channel locked by %04x\n",
1323217ec208SDavid C Somayajulu 			   vf->abs_vf_id, tlv);
1324217ec208SDavid C Somayajulu }
1325217ec208SDavid C Somayajulu 
ecore_iov_unlock_vf_pf_channel(struct ecore_hwfn * p_hwfn,struct ecore_vf_info * vf,u16 expected_tlv)1326217ec208SDavid C Somayajulu static void ecore_iov_unlock_vf_pf_channel(struct ecore_hwfn *p_hwfn,
1327217ec208SDavid C Somayajulu 					   struct ecore_vf_info *vf,
1328217ec208SDavid C Somayajulu 					   u16 expected_tlv)
1329217ec208SDavid C Somayajulu {
1330217ec208SDavid C Somayajulu 	/*WARN(expected_tlv != vf->op_current,
1331217ec208SDavid C Somayajulu 	     "lock mismatch: expected %s found %s",
1332217ec208SDavid C Somayajulu 	     channel_tlvs_string[expected_tlv],
1333217ec208SDavid C Somayajulu 	     channel_tlvs_string[vf->op_current]);
1334217ec208SDavid C Somayajulu 	     @@@TBD MichalK
1335217ec208SDavid C Somayajulu 	*/
1336217ec208SDavid C Somayajulu 
1337217ec208SDavid C Somayajulu 	/* lock the channel */
1338217ec208SDavid C Somayajulu 	/* mutex_unlock(&vf->op_mutex); @@@TBD MichalK add the lock */
1339217ec208SDavid C Somayajulu 
1340217ec208SDavid C Somayajulu 	/* log the unlock */
1341217ec208SDavid C Somayajulu 	if (ecore_iov_tlv_supported(expected_tlv))
1342217ec208SDavid C Somayajulu 		DP_VERBOSE(p_hwfn,
1343217ec208SDavid C Somayajulu 			   ECORE_MSG_IOV,
1344217ec208SDavid C Somayajulu 			   "VF[%d]: vf pf channel unlocked by %s\n",
1345217ec208SDavid C Somayajulu 			   vf->abs_vf_id,
1346217ec208SDavid C Somayajulu 			   ecore_channel_tlvs_string[expected_tlv]);
1347217ec208SDavid C Somayajulu 	else
1348217ec208SDavid C Somayajulu 		DP_VERBOSE(p_hwfn,
1349217ec208SDavid C Somayajulu 			   ECORE_MSG_IOV,
1350217ec208SDavid C Somayajulu 			   "VF[%d]: vf pf channel unlocked by %04x\n",
1351217ec208SDavid C Somayajulu 			   vf->abs_vf_id, expected_tlv);
1352217ec208SDavid C Somayajulu 
1353217ec208SDavid C Somayajulu 	/* record the locking op */
1354217ec208SDavid C Somayajulu 	/* vf->op_current = CHANNEL_TLV_NONE;*/
1355217ec208SDavid C Somayajulu }
1356217ec208SDavid C Somayajulu 
1357217ec208SDavid C Somayajulu /* place a given tlv on the tlv buffer, continuing current tlv list */
ecore_add_tlv(u8 ** offset,u16 type,u16 length)1358217ec208SDavid C Somayajulu void *ecore_add_tlv(u8 **offset, u16 type, u16 length)
1359217ec208SDavid C Somayajulu {
1360217ec208SDavid C Somayajulu 	struct channel_tlv *tl = (struct channel_tlv *)*offset;
1361217ec208SDavid C Somayajulu 
1362217ec208SDavid C Somayajulu 	tl->type = type;
1363217ec208SDavid C Somayajulu 	tl->length = length;
1364217ec208SDavid C Somayajulu 
1365217ec208SDavid C Somayajulu 	/* Offset should keep pointing to next TLV (the end of the last) */
1366217ec208SDavid C Somayajulu 	*offset += length;
1367217ec208SDavid C Somayajulu 
1368217ec208SDavid C Somayajulu 	/* Return a pointer to the start of the added tlv */
1369217ec208SDavid C Somayajulu 	return *offset - length;
1370217ec208SDavid C Somayajulu }
1371217ec208SDavid C Somayajulu 
1372217ec208SDavid C Somayajulu /* list the types and lengths of the tlvs on the buffer */
ecore_dp_tlv_list(struct ecore_hwfn * p_hwfn,void * tlvs_list)1373217ec208SDavid C Somayajulu void ecore_dp_tlv_list(struct ecore_hwfn *p_hwfn, void *tlvs_list)
1374217ec208SDavid C Somayajulu {
1375217ec208SDavid C Somayajulu 	u16 i = 1, total_length = 0;
1376217ec208SDavid C Somayajulu 	struct channel_tlv *tlv;
1377217ec208SDavid C Somayajulu 
1378217ec208SDavid C Somayajulu 	do {
1379217ec208SDavid C Somayajulu 		/* cast current tlv list entry to channel tlv header*/
1380217ec208SDavid C Somayajulu 		tlv = (struct channel_tlv *)((u8 *)tlvs_list + total_length);
1381217ec208SDavid C Somayajulu 
1382217ec208SDavid C Somayajulu 		/* output tlv */
1383217ec208SDavid C Somayajulu 		if (ecore_iov_tlv_supported(tlv->type))
1384217ec208SDavid C Somayajulu 			DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
1385217ec208SDavid C Somayajulu 				   "TLV number %d: type %s, length %d\n",
1386217ec208SDavid C Somayajulu 				   i, ecore_channel_tlvs_string[tlv->type],
1387217ec208SDavid C Somayajulu 				   tlv->length);
1388217ec208SDavid C Somayajulu 		else
1389217ec208SDavid C Somayajulu 			DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
1390217ec208SDavid C Somayajulu 				   "TLV number %d: type %d, length %d\n",
1391217ec208SDavid C Somayajulu 				   i, tlv->type, tlv->length);
1392217ec208SDavid C Somayajulu 
1393217ec208SDavid C Somayajulu 		if (tlv->type == CHANNEL_TLV_LIST_END)
1394217ec208SDavid C Somayajulu 			return;
1395217ec208SDavid C Somayajulu 
1396217ec208SDavid C Somayajulu 		/* Validate entry - protect against malicious VFs */
1397217ec208SDavid C Somayajulu 		if (!tlv->length) {
1398217ec208SDavid C Somayajulu 			DP_NOTICE(p_hwfn, false, "TLV of length 0 found\n");
1399217ec208SDavid C Somayajulu 			return;
1400217ec208SDavid C Somayajulu 		}
1401217ec208SDavid C Somayajulu 
1402217ec208SDavid C Somayajulu 		total_length += tlv->length;
1403217ec208SDavid C Somayajulu 
1404217ec208SDavid C Somayajulu 		if (total_length >= sizeof(struct tlv_buffer_size)) {
1405217ec208SDavid C Somayajulu 			DP_NOTICE(p_hwfn, false, "TLV ==> Buffer overflow\n");
1406217ec208SDavid C Somayajulu 			return;
1407217ec208SDavid C Somayajulu 		}
1408217ec208SDavid C Somayajulu 
1409217ec208SDavid C Somayajulu 		i++;
1410217ec208SDavid C Somayajulu 	} while (1);
1411217ec208SDavid C Somayajulu }
1412217ec208SDavid C Somayajulu 
ecore_iov_send_response(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * p_vf,u16 length,u8 status)1413217ec208SDavid C Somayajulu static void ecore_iov_send_response(struct ecore_hwfn *p_hwfn,
1414217ec208SDavid C Somayajulu 				    struct ecore_ptt *p_ptt,
1415217ec208SDavid C Somayajulu 				    struct ecore_vf_info *p_vf,
1416217ec208SDavid C Somayajulu #ifdef CONFIG_ECORE_SW_CHANNEL
1417217ec208SDavid C Somayajulu 				    u16 length,
1418217ec208SDavid C Somayajulu #else
1419217ec208SDavid C Somayajulu 				    u16 OSAL_UNUSED length,
1420217ec208SDavid C Somayajulu #endif
1421217ec208SDavid C Somayajulu 				    u8 status)
1422217ec208SDavid C Somayajulu {
1423217ec208SDavid C Somayajulu 	struct ecore_iov_vf_mbx *mbx = &p_vf->vf_mbx;
1424217ec208SDavid C Somayajulu 	struct ecore_dmae_params params;
1425217ec208SDavid C Somayajulu 	u8 eng_vf_id;
1426217ec208SDavid C Somayajulu 
1427217ec208SDavid C Somayajulu 	mbx->reply_virt->default_resp.hdr.status = status;
1428217ec208SDavid C Somayajulu 
1429217ec208SDavid C Somayajulu 	ecore_dp_tlv_list(p_hwfn, mbx->reply_virt);
1430217ec208SDavid C Somayajulu 
1431217ec208SDavid C Somayajulu #ifdef CONFIG_ECORE_SW_CHANNEL
1432217ec208SDavid C Somayajulu 	mbx->sw_mbx.response_size =
1433217ec208SDavid C Somayajulu 		length + sizeof(struct channel_list_end_tlv);
1434217ec208SDavid C Somayajulu 
1435217ec208SDavid C Somayajulu 	if (!p_vf->b_hw_channel)
1436217ec208SDavid C Somayajulu 		return;
1437217ec208SDavid C Somayajulu #endif
1438217ec208SDavid C Somayajulu 
1439217ec208SDavid C Somayajulu 	eng_vf_id = p_vf->abs_vf_id;
1440217ec208SDavid C Somayajulu 
1441217ec208SDavid C Somayajulu 	OSAL_MEMSET(&params, 0, sizeof(struct ecore_dmae_params));
1442217ec208SDavid C Somayajulu 	params.flags = ECORE_DMAE_FLAG_VF_DST;
1443217ec208SDavid C Somayajulu 	params.dst_vfid = eng_vf_id;
1444217ec208SDavid C Somayajulu 
1445217ec208SDavid C Somayajulu 	ecore_dmae_host2host(p_hwfn, p_ptt, mbx->reply_phys + sizeof(u64),
1446217ec208SDavid C Somayajulu 			     mbx->req_virt->first_tlv.reply_address +
1447217ec208SDavid C Somayajulu 			     sizeof(u64),
1448217ec208SDavid C Somayajulu 			     (sizeof(union pfvf_tlvs) - sizeof(u64)) / 4 ,
1449217ec208SDavid C Somayajulu 			     &params);
1450217ec208SDavid C Somayajulu 
1451217ec208SDavid C Somayajulu 	/* Once PF copies the rc to the VF, the latter can continue and
1452217ec208SDavid C Somayajulu 	 * and send an additional message. So we have to make sure the
1453217ec208SDavid C Somayajulu 	 * channel would be re-set to ready prior to that.
1454217ec208SDavid C Somayajulu 	 */
1455217ec208SDavid C Somayajulu 	REG_WR(p_hwfn,
1456217ec208SDavid C Somayajulu 	       GTT_BAR0_MAP_REG_USDM_RAM +
1457217ec208SDavid C Somayajulu 	       USTORM_VF_PF_CHANNEL_READY_OFFSET(eng_vf_id),
1458217ec208SDavid C Somayajulu 	       1);
1459217ec208SDavid C Somayajulu 
1460217ec208SDavid C Somayajulu 	ecore_dmae_host2host(p_hwfn, p_ptt, mbx->reply_phys,
1461217ec208SDavid C Somayajulu 			     mbx->req_virt->first_tlv.reply_address,
1462217ec208SDavid C Somayajulu 			     sizeof(u64) / 4, &params);
1463217ec208SDavid C Somayajulu 
1464217ec208SDavid C Somayajulu 	OSAL_IOV_PF_RESP_TYPE(p_hwfn, p_vf->relative_vf_id, status);
1465217ec208SDavid C Somayajulu }
1466217ec208SDavid C Somayajulu 
ecore_iov_vport_to_tlv(enum ecore_iov_vport_update_flag flag)1467217ec208SDavid C Somayajulu static u16 ecore_iov_vport_to_tlv(enum ecore_iov_vport_update_flag flag)
1468217ec208SDavid C Somayajulu {
1469217ec208SDavid C Somayajulu 	switch (flag) {
1470217ec208SDavid C Somayajulu 	case ECORE_IOV_VP_UPDATE_ACTIVATE:
1471217ec208SDavid C Somayajulu 		return CHANNEL_TLV_VPORT_UPDATE_ACTIVATE;
1472217ec208SDavid C Somayajulu 	case ECORE_IOV_VP_UPDATE_VLAN_STRIP:
1473217ec208SDavid C Somayajulu 		return CHANNEL_TLV_VPORT_UPDATE_VLAN_STRIP;
1474217ec208SDavid C Somayajulu 	case ECORE_IOV_VP_UPDATE_TX_SWITCH:
1475217ec208SDavid C Somayajulu 		return CHANNEL_TLV_VPORT_UPDATE_TX_SWITCH;
1476217ec208SDavid C Somayajulu 	case ECORE_IOV_VP_UPDATE_MCAST:
1477217ec208SDavid C Somayajulu 		return CHANNEL_TLV_VPORT_UPDATE_MCAST;
1478217ec208SDavid C Somayajulu 	case ECORE_IOV_VP_UPDATE_ACCEPT_PARAM:
1479217ec208SDavid C Somayajulu 		return CHANNEL_TLV_VPORT_UPDATE_ACCEPT_PARAM;
1480217ec208SDavid C Somayajulu 	case ECORE_IOV_VP_UPDATE_RSS:
1481217ec208SDavid C Somayajulu 		return CHANNEL_TLV_VPORT_UPDATE_RSS;
1482217ec208SDavid C Somayajulu 	case ECORE_IOV_VP_UPDATE_ACCEPT_ANY_VLAN:
1483217ec208SDavid C Somayajulu 		return CHANNEL_TLV_VPORT_UPDATE_ACCEPT_ANY_VLAN;
1484217ec208SDavid C Somayajulu 	case ECORE_IOV_VP_UPDATE_SGE_TPA:
1485217ec208SDavid C Somayajulu 		return CHANNEL_TLV_VPORT_UPDATE_SGE_TPA;
1486217ec208SDavid C Somayajulu 	default:
1487217ec208SDavid C Somayajulu 		return 0;
1488217ec208SDavid C Somayajulu 	}
1489217ec208SDavid C Somayajulu }
1490217ec208SDavid C Somayajulu 
ecore_iov_prep_vp_update_resp_tlvs(struct ecore_hwfn * p_hwfn,struct ecore_vf_info * p_vf,struct ecore_iov_vf_mbx * p_mbx,u8 status,u16 tlvs_mask,u16 tlvs_accepted)1491217ec208SDavid C Somayajulu static u16 ecore_iov_prep_vp_update_resp_tlvs(struct ecore_hwfn *p_hwfn,
1492217ec208SDavid C Somayajulu 					      struct ecore_vf_info *p_vf,
1493217ec208SDavid C Somayajulu 					      struct ecore_iov_vf_mbx *p_mbx,
1494217ec208SDavid C Somayajulu 					      u8 status, u16 tlvs_mask,
1495217ec208SDavid C Somayajulu 					      u16 tlvs_accepted)
1496217ec208SDavid C Somayajulu {
1497217ec208SDavid C Somayajulu 	struct pfvf_def_resp_tlv *resp;
1498217ec208SDavid C Somayajulu 	u16 size, total_len, i;
1499217ec208SDavid C Somayajulu 
1500217ec208SDavid C Somayajulu 	OSAL_MEMSET(p_mbx->reply_virt, 0, sizeof(union pfvf_tlvs));
1501217ec208SDavid C Somayajulu 	p_mbx->offset = (u8 *)p_mbx->reply_virt;
1502217ec208SDavid C Somayajulu 	size = sizeof(struct pfvf_def_resp_tlv);
1503217ec208SDavid C Somayajulu 	total_len = size;
1504217ec208SDavid C Somayajulu 
1505217ec208SDavid C Somayajulu 	ecore_add_tlv(&p_mbx->offset, CHANNEL_TLV_VPORT_UPDATE, size);
1506217ec208SDavid C Somayajulu 
1507217ec208SDavid C Somayajulu 	/* Prepare response for all extended tlvs if they are found by PF */
1508217ec208SDavid C Somayajulu 	for (i = 0; i < ECORE_IOV_VP_UPDATE_MAX; i++) {
1509217ec208SDavid C Somayajulu 		if (!(tlvs_mask & (1 << i)))
1510217ec208SDavid C Somayajulu 			continue;
1511217ec208SDavid C Somayajulu 
1512217ec208SDavid C Somayajulu 		resp = ecore_add_tlv(&p_mbx->offset, ecore_iov_vport_to_tlv(i),
1513217ec208SDavid C Somayajulu 				     size);
1514217ec208SDavid C Somayajulu 
1515217ec208SDavid C Somayajulu 		if (tlvs_accepted & (1 << i))
1516217ec208SDavid C Somayajulu 			resp->hdr.status = status;
1517217ec208SDavid C Somayajulu 		else
1518217ec208SDavid C Somayajulu 			resp->hdr.status = PFVF_STATUS_NOT_SUPPORTED;
1519217ec208SDavid C Somayajulu 
1520217ec208SDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
1521217ec208SDavid C Somayajulu 			   "VF[%d] - vport_update response: TLV %d, status %02x\n",
1522217ec208SDavid C Somayajulu 			   p_vf->relative_vf_id,
1523217ec208SDavid C Somayajulu 			   ecore_iov_vport_to_tlv(i),
1524217ec208SDavid C Somayajulu 			   resp->hdr.status);
1525217ec208SDavid C Somayajulu 
1526217ec208SDavid C Somayajulu 		total_len += size;
1527217ec208SDavid C Somayajulu 	}
1528217ec208SDavid C Somayajulu 
1529217ec208SDavid C Somayajulu 	ecore_add_tlv(&p_mbx->offset, CHANNEL_TLV_LIST_END,
1530217ec208SDavid C Somayajulu 		      sizeof(struct channel_list_end_tlv));
1531217ec208SDavid C Somayajulu 
1532217ec208SDavid C Somayajulu 	return total_len;
1533217ec208SDavid C Somayajulu }
1534217ec208SDavid C Somayajulu 
ecore_iov_prepare_resp(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * vf_info,u16 type,u16 length,u8 status)1535217ec208SDavid C Somayajulu static void ecore_iov_prepare_resp(struct ecore_hwfn *p_hwfn,
1536217ec208SDavid C Somayajulu 				   struct ecore_ptt *p_ptt,
1537217ec208SDavid C Somayajulu 				   struct ecore_vf_info *vf_info,
1538217ec208SDavid C Somayajulu 				   u16 type, u16 length, u8 status)
1539217ec208SDavid C Somayajulu {
1540217ec208SDavid C Somayajulu 	struct ecore_iov_vf_mbx *mbx = &vf_info->vf_mbx;
1541217ec208SDavid C Somayajulu 
1542217ec208SDavid C Somayajulu 	mbx->offset = (u8 *)mbx->reply_virt;
1543217ec208SDavid C Somayajulu 
1544217ec208SDavid C Somayajulu 	ecore_add_tlv(&mbx->offset, type, length);
1545217ec208SDavid C Somayajulu 	ecore_add_tlv(&mbx->offset, CHANNEL_TLV_LIST_END,
1546217ec208SDavid C Somayajulu 		      sizeof(struct channel_list_end_tlv));
1547217ec208SDavid C Somayajulu 
1548217ec208SDavid C Somayajulu 	ecore_iov_send_response(p_hwfn, p_ptt, vf_info, length, status);
1549217ec208SDavid C Somayajulu }
1550217ec208SDavid C Somayajulu 
ecore_iov_get_public_vf_info(struct ecore_hwfn * p_hwfn,u16 relative_vf_id,bool b_enabled_only)1551217ec208SDavid C Somayajulu struct ecore_public_vf_info * ecore_iov_get_public_vf_info(struct ecore_hwfn *p_hwfn,
1552217ec208SDavid C Somayajulu 							   u16 relative_vf_id,
1553217ec208SDavid C Somayajulu 							   bool b_enabled_only)
1554217ec208SDavid C Somayajulu {
1555217ec208SDavid C Somayajulu 	struct ecore_vf_info *vf = OSAL_NULL;
1556217ec208SDavid C Somayajulu 
1557217ec208SDavid C Somayajulu 	vf = ecore_iov_get_vf_info(p_hwfn, relative_vf_id, b_enabled_only);
1558217ec208SDavid C Somayajulu 	if (!vf)
1559217ec208SDavid C Somayajulu 		return OSAL_NULL;
1560217ec208SDavid C Somayajulu 
1561217ec208SDavid C Somayajulu 	return &vf->p_vf_info;
1562217ec208SDavid C Somayajulu }
1563217ec208SDavid C Somayajulu 
ecore_iov_vf_cleanup(struct ecore_hwfn * p_hwfn,struct ecore_vf_info * p_vf)1564217ec208SDavid C Somayajulu static void ecore_iov_vf_cleanup(struct ecore_hwfn *p_hwfn,
1565217ec208SDavid C Somayajulu 				 struct ecore_vf_info *p_vf)
1566217ec208SDavid C Somayajulu {
1567217ec208SDavid C Somayajulu 	u32 i, j;
1568217ec208SDavid C Somayajulu 
1569217ec208SDavid C Somayajulu 	p_vf->vf_bulletin = 0;
1570217ec208SDavid C Somayajulu 	p_vf->vport_instance = 0;
1571217ec208SDavid C Somayajulu 	p_vf->configured_features = 0;
1572217ec208SDavid C Somayajulu 
1573217ec208SDavid C Somayajulu 	/* If VF previously requested less resources, go back to default */
1574217ec208SDavid C Somayajulu 	p_vf->num_rxqs = p_vf->num_sbs;
1575217ec208SDavid C Somayajulu 	p_vf->num_txqs = p_vf->num_sbs;
1576217ec208SDavid C Somayajulu 
1577217ec208SDavid C Somayajulu 	p_vf->num_active_rxqs = 0;
1578217ec208SDavid C Somayajulu 
1579217ec208SDavid C Somayajulu 	for (i = 0; i < ECORE_MAX_VF_CHAINS_PER_PF; i++) {
1580217ec208SDavid C Somayajulu 		struct ecore_vf_queue *p_queue = &p_vf->vf_queues[i];
1581217ec208SDavid C Somayajulu 
1582217ec208SDavid C Somayajulu 		for (j = 0; j < MAX_QUEUES_PER_QZONE; j++) {
1583217ec208SDavid C Somayajulu 			if (!p_queue->cids[j].p_cid)
1584217ec208SDavid C Somayajulu 				continue;
1585217ec208SDavid C Somayajulu 
1586217ec208SDavid C Somayajulu 			ecore_eth_queue_cid_release(p_hwfn,
1587217ec208SDavid C Somayajulu 						    p_queue->cids[j].p_cid);
1588217ec208SDavid C Somayajulu 			p_queue->cids[j].p_cid = OSAL_NULL;
1589217ec208SDavid C Somayajulu 		}
1590217ec208SDavid C Somayajulu 	}
1591217ec208SDavid C Somayajulu 
1592217ec208SDavid C Somayajulu 	OSAL_MEMSET(&p_vf->shadow_config, 0, sizeof(p_vf->shadow_config));
1593217ec208SDavid C Somayajulu 	OSAL_MEMSET(&p_vf->acquire, 0, sizeof(p_vf->acquire));
1594217ec208SDavid C Somayajulu 	OSAL_IOV_VF_CLEANUP(p_hwfn, p_vf->relative_vf_id);
1595217ec208SDavid C Somayajulu }
1596217ec208SDavid C Somayajulu 
1597217ec208SDavid C Somayajulu /* Returns either 0, or log(size) */
ecore_iov_vf_db_bar_size(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)1598217ec208SDavid C Somayajulu static u32 ecore_iov_vf_db_bar_size(struct ecore_hwfn *p_hwfn,
1599217ec208SDavid C Somayajulu 				    struct ecore_ptt *p_ptt)
1600217ec208SDavid C Somayajulu {
1601217ec208SDavid C Somayajulu 	u32 val = ecore_rd(p_hwfn, p_ptt, PGLUE_B_REG_VF_BAR1_SIZE);
1602217ec208SDavid C Somayajulu 
1603217ec208SDavid C Somayajulu 	if (val)
1604217ec208SDavid C Somayajulu 		return val + 11;
1605217ec208SDavid C Somayajulu 	return 0;
1606217ec208SDavid C Somayajulu }
1607217ec208SDavid C Somayajulu 
1608217ec208SDavid C Somayajulu static void
ecore_iov_vf_mbx_acquire_resc_cids(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * p_vf,struct vf_pf_resc_request * p_req,struct pf_vf_resc * p_resp)1609217ec208SDavid C Somayajulu ecore_iov_vf_mbx_acquire_resc_cids(struct ecore_hwfn *p_hwfn,
1610217ec208SDavid C Somayajulu 				   struct ecore_ptt *p_ptt,
1611217ec208SDavid C Somayajulu 				   struct ecore_vf_info *p_vf,
1612217ec208SDavid C Somayajulu 				   struct vf_pf_resc_request *p_req,
1613217ec208SDavid C Somayajulu 				   struct pf_vf_resc *p_resp)
1614217ec208SDavid C Somayajulu {
1615217ec208SDavid C Somayajulu 	u8 num_vf_cons = p_hwfn->pf_params.eth_pf_params.num_vf_cons;
1616217ec208SDavid C Somayajulu 	u8 db_size = DB_ADDR_VF(1, DQ_DEMS_LEGACY) -
1617217ec208SDavid C Somayajulu 		     DB_ADDR_VF(0, DQ_DEMS_LEGACY);
1618217ec208SDavid C Somayajulu 	u32 bar_size;
1619217ec208SDavid C Somayajulu 
1620217ec208SDavid C Somayajulu 	p_resp->num_cids = OSAL_MIN_T(u8, p_req->num_cids, num_vf_cons);
1621217ec208SDavid C Somayajulu 
1622217ec208SDavid C Somayajulu 	/* If VF didn't bother asking for QIDs than don't bother limiting
1623217ec208SDavid C Somayajulu 	 * number of CIDs. The VF doesn't care about the number, and this
1624217ec208SDavid C Somayajulu 	 * has the likely result of causing an additional acquisition.
1625217ec208SDavid C Somayajulu 	 */
1626217ec208SDavid C Somayajulu 	if (!(p_vf->acquire.vfdev_info.capabilities &
1627217ec208SDavid C Somayajulu 	      VFPF_ACQUIRE_CAP_QUEUE_QIDS))
1628217ec208SDavid C Somayajulu 		return;
1629217ec208SDavid C Somayajulu 
1630217ec208SDavid C Somayajulu 	/* If doorbell bar was mapped by VF, limit the VF CIDs to an amount
1631217ec208SDavid C Somayajulu 	 * that would make sure doorbells for all CIDs fall within the bar.
1632217ec208SDavid C Somayajulu 	 * If it doesn't, make sure regview window is sufficient.
1633217ec208SDavid C Somayajulu 	 */
1634217ec208SDavid C Somayajulu 	if (p_vf->acquire.vfdev_info.capabilities &
1635217ec208SDavid C Somayajulu 	    VFPF_ACQUIRE_CAP_PHYSICAL_BAR) {
1636217ec208SDavid C Somayajulu 		bar_size = ecore_iov_vf_db_bar_size(p_hwfn, p_ptt);
1637217ec208SDavid C Somayajulu 		if (bar_size)
1638217ec208SDavid C Somayajulu 			bar_size = 1 << bar_size;
1639217ec208SDavid C Somayajulu 
1640217ec208SDavid C Somayajulu 		if (ECORE_IS_CMT(p_hwfn->p_dev))
1641217ec208SDavid C Somayajulu 			bar_size /= 2;
1642217ec208SDavid C Somayajulu 	} else {
1643217ec208SDavid C Somayajulu 		bar_size = PXP_VF_BAR0_DQ_LENGTH;
1644217ec208SDavid C Somayajulu 	}
1645217ec208SDavid C Somayajulu 
1646217ec208SDavid C Somayajulu 	if (bar_size / db_size < 256)
1647217ec208SDavid C Somayajulu 		p_resp->num_cids = OSAL_MIN_T(u8, p_resp->num_cids,
1648217ec208SDavid C Somayajulu 					      (u8)(bar_size / db_size));
1649217ec208SDavid C Somayajulu }
1650217ec208SDavid C Somayajulu 
ecore_iov_vf_mbx_acquire_resc(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * p_vf,struct vf_pf_resc_request * p_req,struct pf_vf_resc * p_resp)1651217ec208SDavid C Somayajulu static u8 ecore_iov_vf_mbx_acquire_resc(struct ecore_hwfn *p_hwfn,
1652217ec208SDavid C Somayajulu 					struct ecore_ptt *p_ptt,
1653217ec208SDavid C Somayajulu 					struct ecore_vf_info *p_vf,
1654217ec208SDavid C Somayajulu 					struct vf_pf_resc_request *p_req,
1655217ec208SDavid C Somayajulu 					struct pf_vf_resc *p_resp)
1656217ec208SDavid C Somayajulu {
1657217ec208SDavid C Somayajulu 	u8 i;
1658217ec208SDavid C Somayajulu 
1659217ec208SDavid C Somayajulu 	/* Queue related information */
1660217ec208SDavid C Somayajulu 	p_resp->num_rxqs = p_vf->num_rxqs;
1661217ec208SDavid C Somayajulu 	p_resp->num_txqs = p_vf->num_txqs;
1662217ec208SDavid C Somayajulu 	p_resp->num_sbs = p_vf->num_sbs;
1663217ec208SDavid C Somayajulu 
1664217ec208SDavid C Somayajulu 	for (i = 0; i < p_resp->num_sbs; i++) {
1665217ec208SDavid C Somayajulu 		p_resp->hw_sbs[i].hw_sb_id = p_vf->igu_sbs[i];
1666217ec208SDavid C Somayajulu 		/* TODO - what's this sb_qid field? Is it deprecated?
1667217ec208SDavid C Somayajulu 		 * or is there an ecore_client that looks at this?
1668217ec208SDavid C Somayajulu 		 */
1669217ec208SDavid C Somayajulu 		p_resp->hw_sbs[i].sb_qid = 0;
1670217ec208SDavid C Somayajulu 	}
1671217ec208SDavid C Somayajulu 
1672217ec208SDavid C Somayajulu 	/* These fields are filled for backward compatibility.
1673217ec208SDavid C Somayajulu 	 * Unused by modern vfs.
1674217ec208SDavid C Somayajulu 	 */
1675217ec208SDavid C Somayajulu 	for (i = 0; i < p_resp->num_rxqs; i++) {
1676217ec208SDavid C Somayajulu 		ecore_fw_l2_queue(p_hwfn, p_vf->vf_queues[i].fw_rx_qid,
1677217ec208SDavid C Somayajulu 				  (u16 *)&p_resp->hw_qid[i]);
1678217ec208SDavid C Somayajulu 		p_resp->cid[i] = i;
1679217ec208SDavid C Somayajulu 	}
1680217ec208SDavid C Somayajulu 
1681217ec208SDavid C Somayajulu 	/* Filter related information */
1682217ec208SDavid C Somayajulu 	p_resp->num_mac_filters = OSAL_MIN_T(u8, p_vf->num_mac_filters,
1683217ec208SDavid C Somayajulu 					     p_req->num_mac_filters);
1684217ec208SDavid C Somayajulu 	p_resp->num_vlan_filters = OSAL_MIN_T(u8, p_vf->num_vlan_filters,
1685217ec208SDavid C Somayajulu 					      p_req->num_vlan_filters);
1686217ec208SDavid C Somayajulu 
1687217ec208SDavid C Somayajulu 	ecore_iov_vf_mbx_acquire_resc_cids(p_hwfn, p_ptt, p_vf, p_req, p_resp);
1688217ec208SDavid C Somayajulu 
1689217ec208SDavid C Somayajulu 	/* This isn't really needed/enforced, but some legacy VFs might depend
1690217ec208SDavid C Somayajulu 	 * on the correct filling of this field.
1691217ec208SDavid C Somayajulu 	 */
1692217ec208SDavid C Somayajulu 	p_resp->num_mc_filters = ECORE_MAX_MC_ADDRS;
1693217ec208SDavid C Somayajulu 
1694217ec208SDavid C Somayajulu 	/* Validate sufficient resources for VF */
1695217ec208SDavid C Somayajulu 	if (p_resp->num_rxqs < p_req->num_rxqs ||
1696217ec208SDavid C Somayajulu 	    p_resp->num_txqs < p_req->num_txqs ||
1697217ec208SDavid C Somayajulu 	    p_resp->num_sbs < p_req->num_sbs ||
1698217ec208SDavid C Somayajulu 	    p_resp->num_mac_filters < p_req->num_mac_filters ||
1699217ec208SDavid C Somayajulu 	    p_resp->num_vlan_filters < p_req->num_vlan_filters ||
1700217ec208SDavid C Somayajulu 	    p_resp->num_mc_filters < p_req->num_mc_filters ||
1701217ec208SDavid C Somayajulu 	    p_resp->num_cids < p_req->num_cids) {
1702217ec208SDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
1703217ec208SDavid C Somayajulu 			   "VF[%d] - Insufficient resources: rxq [%02x/%02x] txq [%02x/%02x] sbs [%02x/%02x] mac [%02x/%02x] vlan [%02x/%02x] mc [%02x/%02x] cids [%02x/%02x]\n",
1704217ec208SDavid C Somayajulu 			   p_vf->abs_vf_id,
1705217ec208SDavid C Somayajulu 			   p_req->num_rxqs, p_resp->num_rxqs,
1706217ec208SDavid C Somayajulu 			   p_req->num_rxqs, p_resp->num_txqs,
1707217ec208SDavid C Somayajulu 			   p_req->num_sbs, p_resp->num_sbs,
1708217ec208SDavid C Somayajulu 			   p_req->num_mac_filters, p_resp->num_mac_filters,
1709217ec208SDavid C Somayajulu 			   p_req->num_vlan_filters, p_resp->num_vlan_filters,
1710217ec208SDavid C Somayajulu 			   p_req->num_mc_filters, p_resp->num_mc_filters,
1711217ec208SDavid C Somayajulu 			   p_req->num_cids, p_resp->num_cids);
1712217ec208SDavid C Somayajulu 
1713217ec208SDavid C Somayajulu 		/* Some legacy OSes are incapable of correctly handling this
1714217ec208SDavid C Somayajulu 		 * failure.
1715217ec208SDavid C Somayajulu 		 */
1716217ec208SDavid C Somayajulu 		if ((p_vf->acquire.vfdev_info.eth_fp_hsi_minor ==
1717217ec208SDavid C Somayajulu 		     ETH_HSI_VER_NO_PKT_LEN_TUNN) &&
1718217ec208SDavid C Somayajulu 		    (p_vf->acquire.vfdev_info.os_type ==
1719217ec208SDavid C Somayajulu 		     VFPF_ACQUIRE_OS_WINDOWS))
1720217ec208SDavid C Somayajulu 			return PFVF_STATUS_SUCCESS;
1721217ec208SDavid C Somayajulu 
1722217ec208SDavid C Somayajulu 		return PFVF_STATUS_NO_RESOURCE;
1723217ec208SDavid C Somayajulu 	}
1724217ec208SDavid C Somayajulu 
1725217ec208SDavid C Somayajulu 	return PFVF_STATUS_SUCCESS;
1726217ec208SDavid C Somayajulu }
1727217ec208SDavid C Somayajulu 
ecore_iov_vf_mbx_acquire_stats(struct pfvf_stats_info * p_stats)1728217ec208SDavid C Somayajulu static void ecore_iov_vf_mbx_acquire_stats(struct pfvf_stats_info *p_stats)
1729217ec208SDavid C Somayajulu {
1730217ec208SDavid C Somayajulu 	p_stats->mstats.address = PXP_VF_BAR0_START_MSDM_ZONE_B +
1731217ec208SDavid C Somayajulu 				  OFFSETOF(struct mstorm_vf_zone,
1732217ec208SDavid C Somayajulu 					   non_trigger.eth_queue_stat);
1733217ec208SDavid C Somayajulu 	p_stats->mstats.len = sizeof(struct eth_mstorm_per_queue_stat);
1734217ec208SDavid C Somayajulu 	p_stats->ustats.address = PXP_VF_BAR0_START_USDM_ZONE_B +
1735217ec208SDavid C Somayajulu 				  OFFSETOF(struct ustorm_vf_zone,
1736217ec208SDavid C Somayajulu 					   non_trigger.eth_queue_stat);
1737217ec208SDavid C Somayajulu 	p_stats->ustats.len = sizeof(struct eth_ustorm_per_queue_stat);
1738217ec208SDavid C Somayajulu 	p_stats->pstats.address = PXP_VF_BAR0_START_PSDM_ZONE_B +
1739217ec208SDavid C Somayajulu 				  OFFSETOF(struct pstorm_vf_zone,
1740217ec208SDavid C Somayajulu 					   non_trigger.eth_queue_stat);
1741217ec208SDavid C Somayajulu 	p_stats->pstats.len = sizeof(struct eth_pstorm_per_queue_stat);
1742217ec208SDavid C Somayajulu 	p_stats->tstats.address = 0;
1743217ec208SDavid C Somayajulu 	p_stats->tstats.len = 0;
1744217ec208SDavid C Somayajulu }
1745217ec208SDavid C Somayajulu 
ecore_iov_vf_mbx_acquire(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * vf)1746217ec208SDavid C Somayajulu static void ecore_iov_vf_mbx_acquire(struct ecore_hwfn       *p_hwfn,
1747217ec208SDavid C Somayajulu 				     struct ecore_ptt	     *p_ptt,
1748217ec208SDavid C Somayajulu 				     struct ecore_vf_info    *vf)
1749217ec208SDavid C Somayajulu {
1750217ec208SDavid C Somayajulu 	struct ecore_iov_vf_mbx *mbx = &vf->vf_mbx;
1751217ec208SDavid C Somayajulu 	struct pfvf_acquire_resp_tlv *resp = &mbx->reply_virt->acquire_resp;
1752217ec208SDavid C Somayajulu 	struct pf_vf_pfdev_info *pfdev_info = &resp->pfdev_info;
1753217ec208SDavid C Somayajulu 	struct vfpf_acquire_tlv *req = &mbx->req_virt->acquire;
1754217ec208SDavid C Somayajulu 	u8 vfpf_status = PFVF_STATUS_NOT_SUPPORTED;
1755217ec208SDavid C Somayajulu 	struct pf_vf_resc *resc = &resp->resc;
1756217ec208SDavid C Somayajulu 	enum _ecore_status_t rc;
1757217ec208SDavid C Somayajulu 
1758217ec208SDavid C Somayajulu 	OSAL_MEMSET(resp, 0, sizeof(*resp));
1759217ec208SDavid C Somayajulu 
1760217ec208SDavid C Somayajulu 	/* Write the PF version so that VF would know which version
1761217ec208SDavid C Somayajulu 	 * is supported - might be later overriden. This guarantees that
1762217ec208SDavid C Somayajulu 	 * VF could recognize legacy PF based on lack of versions in reply.
1763217ec208SDavid C Somayajulu 	 */
1764217ec208SDavid C Somayajulu 	pfdev_info->major_fp_hsi = ETH_HSI_VER_MAJOR;
1765217ec208SDavid C Somayajulu 	pfdev_info->minor_fp_hsi = ETH_HSI_VER_MINOR;
1766217ec208SDavid C Somayajulu 
1767217ec208SDavid C Somayajulu 	/* TODO - not doing anything is bad since we'll assert, but this isn't
1768217ec208SDavid C Somayajulu 	 * necessarily the right behavior - perhaps we should have allowed some
1769217ec208SDavid C Somayajulu 	 * versatility here.
1770217ec208SDavid C Somayajulu 	 */
1771217ec208SDavid C Somayajulu 	if (vf->state != VF_FREE &&
1772217ec208SDavid C Somayajulu 	    vf->state != VF_STOPPED) {
1773217ec208SDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
1774217ec208SDavid C Somayajulu 			   "VF[%d] sent ACQUIRE but is already in state %d - fail request\n",
1775217ec208SDavid C Somayajulu 			   vf->abs_vf_id, vf->state);
1776217ec208SDavid C Somayajulu 		goto out;
1777217ec208SDavid C Somayajulu 	}
1778217ec208SDavid C Somayajulu 
1779217ec208SDavid C Somayajulu 	/* Validate FW compatibility */
1780217ec208SDavid C Somayajulu 	if (req->vfdev_info.eth_fp_hsi_major != ETH_HSI_VER_MAJOR) {
1781217ec208SDavid C Somayajulu 		if (req->vfdev_info.capabilities &
1782217ec208SDavid C Somayajulu 		    VFPF_ACQUIRE_CAP_PRE_FP_HSI) {
1783217ec208SDavid C Somayajulu 			struct vf_pf_vfdev_info *p_vfdev = &req->vfdev_info;
1784217ec208SDavid C Somayajulu 
1785217ec208SDavid C Somayajulu 			/* This legacy support would need to be removed once
1786217ec208SDavid C Somayajulu 			 * the major has changed.
1787217ec208SDavid C Somayajulu 			 */
1788217ec208SDavid C Somayajulu 			OSAL_BUILD_BUG_ON(ETH_HSI_VER_MAJOR != 3);
1789217ec208SDavid C Somayajulu 
1790217ec208SDavid C Somayajulu 			DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
1791217ec208SDavid C Somayajulu 				   "VF[%d] is pre-fastpath HSI\n",
1792217ec208SDavid C Somayajulu 				   vf->abs_vf_id);
1793217ec208SDavid C Somayajulu 			p_vfdev->eth_fp_hsi_major = ETH_HSI_VER_MAJOR;
1794217ec208SDavid C Somayajulu 			p_vfdev->eth_fp_hsi_minor = ETH_HSI_VER_NO_PKT_LEN_TUNN;
1795217ec208SDavid C Somayajulu 		} else {
1796217ec208SDavid C Somayajulu 			DP_INFO(p_hwfn,
1797217ec208SDavid C Somayajulu 				"VF[%d] needs fastpath HSI %02x.%02x, which is incompatible with loaded FW's faspath HSI %02x.%02x\n",
1798217ec208SDavid C Somayajulu 				vf->abs_vf_id,
1799217ec208SDavid C Somayajulu 				req->vfdev_info.eth_fp_hsi_major,
1800217ec208SDavid C Somayajulu 				req->vfdev_info.eth_fp_hsi_minor,
1801217ec208SDavid C Somayajulu 				ETH_HSI_VER_MAJOR, ETH_HSI_VER_MINOR);
1802217ec208SDavid C Somayajulu 
1803217ec208SDavid C Somayajulu 			goto out;
1804217ec208SDavid C Somayajulu 		}
1805217ec208SDavid C Somayajulu 	}
1806217ec208SDavid C Somayajulu 
1807217ec208SDavid C Somayajulu 	/* On 100g PFs, prevent old VFs from loading */
1808217ec208SDavid C Somayajulu 	if (ECORE_IS_CMT(p_hwfn->p_dev) &&
1809217ec208SDavid C Somayajulu 	    !(req->vfdev_info.capabilities & VFPF_ACQUIRE_CAP_100G)) {
1810217ec208SDavid C Somayajulu 		DP_INFO(p_hwfn, "VF[%d] is running an old driver that doesn't support 100g\n",
1811217ec208SDavid C Somayajulu 			vf->abs_vf_id);
1812217ec208SDavid C Somayajulu 		goto out;
1813217ec208SDavid C Somayajulu 	}
1814217ec208SDavid C Somayajulu 
1815217ec208SDavid C Somayajulu #ifndef __EXTRACT__LINUX__
1816217ec208SDavid C Somayajulu 	if (OSAL_IOV_VF_ACQUIRE(p_hwfn, vf->relative_vf_id) != ECORE_SUCCESS) {
1817217ec208SDavid C Somayajulu 		vfpf_status = PFVF_STATUS_NOT_SUPPORTED;
1818217ec208SDavid C Somayajulu 		goto out;
1819217ec208SDavid C Somayajulu 	}
1820217ec208SDavid C Somayajulu #endif
1821217ec208SDavid C Somayajulu 
1822217ec208SDavid C Somayajulu 	/* Store the acquire message */
1823217ec208SDavid C Somayajulu 	OSAL_MEMCPY(&vf->acquire, req, sizeof(vf->acquire));
1824217ec208SDavid C Somayajulu 
1825217ec208SDavid C Somayajulu 	vf->opaque_fid = req->vfdev_info.opaque_fid;
1826217ec208SDavid C Somayajulu 
1827217ec208SDavid C Somayajulu 	vf->vf_bulletin = req->bulletin_addr;
1828217ec208SDavid C Somayajulu 	vf->bulletin.size = (vf->bulletin.size < req->bulletin_size) ?
1829217ec208SDavid C Somayajulu 			    vf->bulletin.size : req->bulletin_size;
1830217ec208SDavid C Somayajulu 
1831217ec208SDavid C Somayajulu 	/* fill in pfdev info */
1832217ec208SDavid C Somayajulu 	pfdev_info->chip_num = p_hwfn->p_dev->chip_num;
1833217ec208SDavid C Somayajulu 	pfdev_info->db_size = 0; /* @@@ TBD MichalK Vf Doorbells */
1834217ec208SDavid C Somayajulu 	pfdev_info->indices_per_sb = PIS_PER_SB_E4;
1835217ec208SDavid C Somayajulu 
1836217ec208SDavid C Somayajulu 	pfdev_info->capabilities = PFVF_ACQUIRE_CAP_DEFAULT_UNTAGGED |
1837217ec208SDavid C Somayajulu 				   PFVF_ACQUIRE_CAP_POST_FW_OVERRIDE;
1838217ec208SDavid C Somayajulu 	if (ECORE_IS_CMT(p_hwfn->p_dev))
1839217ec208SDavid C Somayajulu 		pfdev_info->capabilities |= PFVF_ACQUIRE_CAP_100G;
1840217ec208SDavid C Somayajulu 
1841217ec208SDavid C Somayajulu 	/* Share our ability to use multiple queue-ids only with VFs
1842217ec208SDavid C Somayajulu 	 * that request it.
1843217ec208SDavid C Somayajulu 	 */
1844217ec208SDavid C Somayajulu 	if (req->vfdev_info.capabilities & VFPF_ACQUIRE_CAP_QUEUE_QIDS)
1845217ec208SDavid C Somayajulu 		pfdev_info->capabilities |= PFVF_ACQUIRE_CAP_QUEUE_QIDS;
1846217ec208SDavid C Somayajulu 
1847217ec208SDavid C Somayajulu 	/* Share the sizes of the bars with VF */
1848217ec208SDavid C Somayajulu 	resp->pfdev_info.bar_size = (u8)ecore_iov_vf_db_bar_size(p_hwfn,
1849217ec208SDavid C Somayajulu 							     p_ptt);
1850217ec208SDavid C Somayajulu 
1851217ec208SDavid C Somayajulu 	ecore_iov_vf_mbx_acquire_stats(&pfdev_info->stats_info);
1852217ec208SDavid C Somayajulu 
1853217ec208SDavid C Somayajulu 	OSAL_MEMCPY(pfdev_info->port_mac, p_hwfn->hw_info.hw_mac_addr,
1854217ec208SDavid C Somayajulu 		    ETH_ALEN);
1855217ec208SDavid C Somayajulu 
1856217ec208SDavid C Somayajulu 	pfdev_info->fw_major = FW_MAJOR_VERSION;
1857217ec208SDavid C Somayajulu 	pfdev_info->fw_minor = FW_MINOR_VERSION;
1858217ec208SDavid C Somayajulu 	pfdev_info->fw_rev = FW_REVISION_VERSION;
1859217ec208SDavid C Somayajulu 	pfdev_info->fw_eng = FW_ENGINEERING_VERSION;
1860217ec208SDavid C Somayajulu 
1861217ec208SDavid C Somayajulu 	/* Incorrect when legacy, but doesn't matter as legacy isn't reading
1862217ec208SDavid C Somayajulu 	 * this field.
1863217ec208SDavid C Somayajulu 	 */
1864217ec208SDavid C Somayajulu 	pfdev_info->minor_fp_hsi = OSAL_MIN_T(u8, ETH_HSI_VER_MINOR,
1865217ec208SDavid C Somayajulu 					      req->vfdev_info.eth_fp_hsi_minor);
1866217ec208SDavid C Somayajulu 	pfdev_info->os_type = OSAL_IOV_GET_OS_TYPE();
1867217ec208SDavid C Somayajulu 	ecore_mcp_get_mfw_ver(p_hwfn, p_ptt, &pfdev_info->mfw_ver,
1868217ec208SDavid C Somayajulu 			      OSAL_NULL);
1869217ec208SDavid C Somayajulu 
1870217ec208SDavid C Somayajulu 	pfdev_info->dev_type = p_hwfn->p_dev->type;
1871217ec208SDavid C Somayajulu 	pfdev_info->chip_rev = p_hwfn->p_dev->chip_rev;
1872217ec208SDavid C Somayajulu 
1873217ec208SDavid C Somayajulu 	/* Fill resources available to VF; Make sure there are enough to
1874217ec208SDavid C Somayajulu 	 * satisfy the VF's request.
1875217ec208SDavid C Somayajulu 	 */
1876217ec208SDavid C Somayajulu 	vfpf_status = ecore_iov_vf_mbx_acquire_resc(p_hwfn, p_ptt, vf,
1877217ec208SDavid C Somayajulu 						    &req->resc_request, resc);
1878217ec208SDavid C Somayajulu 	if (vfpf_status != PFVF_STATUS_SUCCESS)
1879217ec208SDavid C Somayajulu 		goto out;
1880217ec208SDavid C Somayajulu 
1881217ec208SDavid C Somayajulu 	/* Start the VF in FW */
1882217ec208SDavid C Somayajulu 	rc = ecore_sp_vf_start(p_hwfn, vf);
1883217ec208SDavid C Somayajulu 	if (rc != ECORE_SUCCESS) {
1884217ec208SDavid C Somayajulu 		DP_NOTICE(p_hwfn, true, "Failed to start VF[%02x]\n",
1885217ec208SDavid C Somayajulu 			  vf->abs_vf_id);
1886217ec208SDavid C Somayajulu 		vfpf_status = PFVF_STATUS_FAILURE;
1887217ec208SDavid C Somayajulu 		goto out;
1888217ec208SDavid C Somayajulu 	}
1889217ec208SDavid C Somayajulu 
1890217ec208SDavid C Somayajulu 	/* Fill agreed size of bulletin board in response, and post
1891217ec208SDavid C Somayajulu 	 * an initial image to the bulletin board.
1892217ec208SDavid C Somayajulu 	 */
1893217ec208SDavid C Somayajulu 	resp->bulletin_size = vf->bulletin.size;
1894217ec208SDavid C Somayajulu 	ecore_iov_post_vf_bulletin(p_hwfn, vf->relative_vf_id, p_ptt);
1895217ec208SDavid C Somayajulu 
1896217ec208SDavid C Somayajulu 	DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
1897217ec208SDavid C Somayajulu 		   "VF[%d] ACQUIRE_RESPONSE: pfdev_info- chip_num=0x%x, db_size=%d, idx_per_sb=%d, pf_cap=0x%llx\n"
1898217ec208SDavid C Somayajulu 		   "resources- n_rxq-%d, n_txq-%d, n_sbs-%d, n_macs-%d, n_vlans-%d\n",
1899217ec208SDavid C Somayajulu 		   vf->abs_vf_id, resp->pfdev_info.chip_num,
1900217ec208SDavid C Somayajulu 		   resp->pfdev_info.db_size, resp->pfdev_info.indices_per_sb,
1901217ec208SDavid C Somayajulu 		   (unsigned long long)resp->pfdev_info.capabilities, resc->num_rxqs,
1902217ec208SDavid C Somayajulu 		   resc->num_txqs, resc->num_sbs, resc->num_mac_filters,
1903217ec208SDavid C Somayajulu 		   resc->num_vlan_filters);
1904217ec208SDavid C Somayajulu 
1905217ec208SDavid C Somayajulu 	vf->state = VF_ACQUIRED;
1906217ec208SDavid C Somayajulu 
1907217ec208SDavid C Somayajulu out:
1908217ec208SDavid C Somayajulu 	/* Prepare Response */
1909217ec208SDavid C Somayajulu 	ecore_iov_prepare_resp(p_hwfn, p_ptt, vf, CHANNEL_TLV_ACQUIRE,
1910217ec208SDavid C Somayajulu 			       sizeof(struct pfvf_acquire_resp_tlv),
1911217ec208SDavid C Somayajulu 			       vfpf_status);
1912217ec208SDavid C Somayajulu }
1913217ec208SDavid C Somayajulu 
__ecore_iov_spoofchk_set(struct ecore_hwfn * p_hwfn,struct ecore_vf_info * p_vf,bool val)1914217ec208SDavid C Somayajulu static enum _ecore_status_t __ecore_iov_spoofchk_set(struct ecore_hwfn *p_hwfn,
1915217ec208SDavid C Somayajulu 						     struct ecore_vf_info *p_vf, bool val)
1916217ec208SDavid C Somayajulu {
1917217ec208SDavid C Somayajulu 	struct ecore_sp_vport_update_params params;
1918217ec208SDavid C Somayajulu 	enum _ecore_status_t rc;
1919217ec208SDavid C Somayajulu 
1920217ec208SDavid C Somayajulu 	if (val == p_vf->spoof_chk) {
1921217ec208SDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
1922217ec208SDavid C Somayajulu 			   "Spoofchk value[%d] is already configured\n",
1923217ec208SDavid C Somayajulu 			   val);
1924217ec208SDavid C Somayajulu 		return ECORE_SUCCESS;
1925217ec208SDavid C Somayajulu 	}
1926217ec208SDavid C Somayajulu 
1927217ec208SDavid C Somayajulu 	OSAL_MEMSET(&params, 0, sizeof(struct ecore_sp_vport_update_params));
1928217ec208SDavid C Somayajulu 	params.opaque_fid = p_vf->opaque_fid;
1929217ec208SDavid C Somayajulu 	params.vport_id = p_vf->vport_id;
1930217ec208SDavid C Somayajulu 	params.update_anti_spoofing_en_flg = 1;
1931217ec208SDavid C Somayajulu 	params.anti_spoofing_en = val;
1932217ec208SDavid C Somayajulu 
1933217ec208SDavid C Somayajulu 	rc = ecore_sp_vport_update(p_hwfn, &params, ECORE_SPQ_MODE_EBLOCK,
1934217ec208SDavid C Somayajulu 				   OSAL_NULL);
1935217ec208SDavid C Somayajulu 	if (rc == ECORE_SUCCESS) {
1936217ec208SDavid C Somayajulu 		p_vf->spoof_chk = val;
1937217ec208SDavid C Somayajulu 		p_vf->req_spoofchk_val = p_vf->spoof_chk;
1938217ec208SDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
1939217ec208SDavid C Somayajulu 			   "Spoofchk val[%d] configured\n", val);
1940217ec208SDavid C Somayajulu 	} else {
1941217ec208SDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
1942217ec208SDavid C Somayajulu 			   "Spoofchk configuration[val:%d] failed for VF[%d]\n",
1943217ec208SDavid C Somayajulu 			   val, p_vf->relative_vf_id);
1944217ec208SDavid C Somayajulu 	}
1945217ec208SDavid C Somayajulu 
1946217ec208SDavid C Somayajulu 	return rc;
1947217ec208SDavid C Somayajulu }
1948217ec208SDavid C Somayajulu 
ecore_iov_reconfigure_unicast_vlan(struct ecore_hwfn * p_hwfn,struct ecore_vf_info * p_vf)1949217ec208SDavid C Somayajulu static enum _ecore_status_t ecore_iov_reconfigure_unicast_vlan(struct ecore_hwfn *p_hwfn,
1950217ec208SDavid C Somayajulu 							       struct ecore_vf_info *p_vf)
1951217ec208SDavid C Somayajulu {
1952217ec208SDavid C Somayajulu 	struct ecore_filter_ucast filter;
1953217ec208SDavid C Somayajulu 	enum _ecore_status_t rc = ECORE_SUCCESS;
1954217ec208SDavid C Somayajulu 	int i;
1955217ec208SDavid C Somayajulu 
1956217ec208SDavid C Somayajulu 	OSAL_MEMSET(&filter, 0, sizeof(filter));
1957217ec208SDavid C Somayajulu 	filter.is_rx_filter = 1;
1958217ec208SDavid C Somayajulu 	filter.is_tx_filter = 1;
1959217ec208SDavid C Somayajulu 	filter.vport_to_add_to = p_vf->vport_id;
1960217ec208SDavid C Somayajulu 	filter.opcode = ECORE_FILTER_ADD;
1961217ec208SDavid C Somayajulu 
1962217ec208SDavid C Somayajulu 	/* Reconfigure vlans */
1963217ec208SDavid C Somayajulu 	for (i = 0; i < ECORE_ETH_VF_NUM_VLAN_FILTERS + 1; i++) {
1964217ec208SDavid C Somayajulu 		if (!p_vf->shadow_config.vlans[i].used)
1965217ec208SDavid C Somayajulu 			continue;
1966217ec208SDavid C Somayajulu 
1967217ec208SDavid C Somayajulu 		filter.type = ECORE_FILTER_VLAN;
1968217ec208SDavid C Somayajulu 		filter.vlan = p_vf->shadow_config.vlans[i].vid;
1969217ec208SDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
1970217ec208SDavid C Somayajulu 			   "Reconfiguring VLAN [0x%04x] for VF [%04x]\n",
1971217ec208SDavid C Somayajulu 			   filter.vlan, p_vf->relative_vf_id);
1972217ec208SDavid C Somayajulu 		rc = ecore_sp_eth_filter_ucast(p_hwfn, p_vf->opaque_fid,
1973217ec208SDavid C Somayajulu 					       &filter, ECORE_SPQ_MODE_CB, OSAL_NULL);
1974217ec208SDavid C Somayajulu 		if (rc) {
1975217ec208SDavid C Somayajulu 			DP_NOTICE(p_hwfn, true, "Failed to configure VLAN [%04x] to VF [%04x]\n",
1976217ec208SDavid C Somayajulu 				  filter.vlan,
1977217ec208SDavid C Somayajulu 				  p_vf->relative_vf_id);
1978217ec208SDavid C Somayajulu 			break;
1979217ec208SDavid C Somayajulu 		}
1980217ec208SDavid C Somayajulu 	}
1981217ec208SDavid C Somayajulu 
1982217ec208SDavid C Somayajulu 	return rc;
1983217ec208SDavid C Somayajulu }
1984217ec208SDavid C Somayajulu 
1985217ec208SDavid C Somayajulu static enum _ecore_status_t
ecore_iov_reconfigure_unicast_shadow(struct ecore_hwfn * p_hwfn,struct ecore_vf_info * p_vf,u64 events)1986217ec208SDavid C Somayajulu ecore_iov_reconfigure_unicast_shadow(struct ecore_hwfn *p_hwfn,
1987217ec208SDavid C Somayajulu 				     struct ecore_vf_info *p_vf,
1988217ec208SDavid C Somayajulu 				     u64 events)
1989217ec208SDavid C Somayajulu {
1990217ec208SDavid C Somayajulu 	enum _ecore_status_t rc = ECORE_SUCCESS;
1991217ec208SDavid C Somayajulu 
1992217ec208SDavid C Somayajulu 	/*TODO - what about MACs? */
1993217ec208SDavid C Somayajulu 
1994217ec208SDavid C Somayajulu 	if ((events & (1 << VLAN_ADDR_FORCED)) &&
1995217ec208SDavid C Somayajulu 	    !(p_vf->configured_features & (1 << VLAN_ADDR_FORCED)))
1996217ec208SDavid C Somayajulu 		rc = ecore_iov_reconfigure_unicast_vlan(p_hwfn, p_vf);
1997217ec208SDavid C Somayajulu 
1998217ec208SDavid C Somayajulu 	return rc;
1999217ec208SDavid C Somayajulu }
2000217ec208SDavid C Somayajulu 
2001217ec208SDavid C Somayajulu static  enum _ecore_status_t
ecore_iov_configure_vport_forced(struct ecore_hwfn * p_hwfn,struct ecore_vf_info * p_vf,u64 events)2002217ec208SDavid C Somayajulu ecore_iov_configure_vport_forced(struct ecore_hwfn *p_hwfn,
2003217ec208SDavid C Somayajulu 				 struct ecore_vf_info *p_vf,
2004217ec208SDavid C Somayajulu 				 u64 events)
2005217ec208SDavid C Somayajulu {
2006217ec208SDavid C Somayajulu 	enum _ecore_status_t rc = ECORE_SUCCESS;
2007217ec208SDavid C Somayajulu 	struct ecore_filter_ucast filter;
2008217ec208SDavid C Somayajulu 
2009217ec208SDavid C Somayajulu 	if (!p_vf->vport_instance)
2010217ec208SDavid C Somayajulu 		return ECORE_INVAL;
2011217ec208SDavid C Somayajulu 
2012217ec208SDavid C Somayajulu 	if (events & (1 << MAC_ADDR_FORCED)) {
2013217ec208SDavid C Somayajulu 		/* Since there's no way [currently] of removing the MAC,
2014217ec208SDavid C Somayajulu 		 * we can always assume this means we need to force it.
2015217ec208SDavid C Somayajulu 		 */
2016217ec208SDavid C Somayajulu 		OSAL_MEMSET(&filter, 0, sizeof(filter));
2017217ec208SDavid C Somayajulu 		filter.type = ECORE_FILTER_MAC;
2018217ec208SDavid C Somayajulu 		filter.opcode = ECORE_FILTER_REPLACE;
2019217ec208SDavid C Somayajulu 		filter.is_rx_filter = 1;
2020217ec208SDavid C Somayajulu 		filter.is_tx_filter = 1;
2021217ec208SDavid C Somayajulu 		filter.vport_to_add_to = p_vf->vport_id;
2022217ec208SDavid C Somayajulu 		OSAL_MEMCPY(filter.mac,
2023217ec208SDavid C Somayajulu 			    p_vf->bulletin.p_virt->mac,
2024217ec208SDavid C Somayajulu 			    ETH_ALEN);
2025217ec208SDavid C Somayajulu 
2026217ec208SDavid C Somayajulu 		rc = ecore_sp_eth_filter_ucast(p_hwfn, p_vf->opaque_fid,
2027217ec208SDavid C Somayajulu 					       &filter,
2028217ec208SDavid C Somayajulu 					       ECORE_SPQ_MODE_CB, OSAL_NULL);
2029217ec208SDavid C Somayajulu 		if (rc) {
2030217ec208SDavid C Somayajulu 			DP_NOTICE(p_hwfn, true,
2031217ec208SDavid C Somayajulu 				  "PF failed to configure MAC for VF\n");
2032217ec208SDavid C Somayajulu 			return rc;
2033217ec208SDavid C Somayajulu 		}
2034217ec208SDavid C Somayajulu 
2035217ec208SDavid C Somayajulu 		p_vf->configured_features |= 1 << MAC_ADDR_FORCED;
2036217ec208SDavid C Somayajulu 	}
2037217ec208SDavid C Somayajulu 
2038217ec208SDavid C Somayajulu 	if (events & (1 << VLAN_ADDR_FORCED)) {
2039217ec208SDavid C Somayajulu 		struct ecore_sp_vport_update_params vport_update;
2040217ec208SDavid C Somayajulu 		u8 removal;
2041217ec208SDavid C Somayajulu 		int i;
2042217ec208SDavid C Somayajulu 
2043217ec208SDavid C Somayajulu 		OSAL_MEMSET(&filter, 0, sizeof(filter));
2044217ec208SDavid C Somayajulu 		filter.type = ECORE_FILTER_VLAN;
2045217ec208SDavid C Somayajulu 		filter.is_rx_filter = 1;
2046217ec208SDavid C Somayajulu 		filter.is_tx_filter = 1;
2047217ec208SDavid C Somayajulu 		filter.vport_to_add_to = p_vf->vport_id;
2048217ec208SDavid C Somayajulu 		filter.vlan = p_vf->bulletin.p_virt->pvid;
2049217ec208SDavid C Somayajulu 		filter.opcode = filter.vlan ? ECORE_FILTER_REPLACE :
2050217ec208SDavid C Somayajulu 					      ECORE_FILTER_FLUSH;
2051217ec208SDavid C Somayajulu 
2052217ec208SDavid C Somayajulu 		/* Send the ramrod */
2053217ec208SDavid C Somayajulu 		rc = ecore_sp_eth_filter_ucast(p_hwfn, p_vf->opaque_fid,
2054217ec208SDavid C Somayajulu 					       &filter,
2055217ec208SDavid C Somayajulu 					       ECORE_SPQ_MODE_CB, OSAL_NULL);
2056217ec208SDavid C Somayajulu 		if (rc) {
2057217ec208SDavid C Somayajulu 			DP_NOTICE(p_hwfn, true,
2058217ec208SDavid C Somayajulu 				  "PF failed to configure VLAN for VF\n");
2059217ec208SDavid C Somayajulu 			return rc;
2060217ec208SDavid C Somayajulu 		}
2061217ec208SDavid C Somayajulu 
2062217ec208SDavid C Somayajulu 		/* Update the default-vlan & silent vlan stripping */
2063217ec208SDavid C Somayajulu 		OSAL_MEMSET(&vport_update, 0, sizeof(vport_update));
2064217ec208SDavid C Somayajulu 		vport_update.opaque_fid = p_vf->opaque_fid;
2065217ec208SDavid C Somayajulu 		vport_update.vport_id = p_vf->vport_id;
2066217ec208SDavid C Somayajulu 		vport_update.update_default_vlan_enable_flg = 1;
2067217ec208SDavid C Somayajulu 		vport_update.default_vlan_enable_flg = filter.vlan ? 1 : 0;
2068217ec208SDavid C Somayajulu 		vport_update.update_default_vlan_flg = 1;
2069217ec208SDavid C Somayajulu 		vport_update.default_vlan = filter.vlan;
2070217ec208SDavid C Somayajulu 
2071217ec208SDavid C Somayajulu 		vport_update.update_inner_vlan_removal_flg = 1;
2072217ec208SDavid C Somayajulu 		removal = filter.vlan ?
2073217ec208SDavid C Somayajulu 			  1 : p_vf->shadow_config.inner_vlan_removal;
2074217ec208SDavid C Somayajulu 		vport_update.inner_vlan_removal_flg = removal;
2075217ec208SDavid C Somayajulu 		vport_update.silent_vlan_removal_flg = filter.vlan ? 1 : 0;
2076217ec208SDavid C Somayajulu 		rc = ecore_sp_vport_update(p_hwfn, &vport_update,
2077217ec208SDavid C Somayajulu 					   ECORE_SPQ_MODE_EBLOCK,
2078217ec208SDavid C Somayajulu 					   OSAL_NULL);
2079217ec208SDavid C Somayajulu 		if (rc) {
2080217ec208SDavid C Somayajulu 			DP_NOTICE(p_hwfn, true,
2081217ec208SDavid C Somayajulu 				  "PF failed to configure VF vport for vlan\n");
2082217ec208SDavid C Somayajulu 			return rc;
2083217ec208SDavid C Somayajulu 		}
2084217ec208SDavid C Somayajulu 
2085217ec208SDavid C Somayajulu 		/* Update all the Rx queues */
2086217ec208SDavid C Somayajulu 		for (i = 0; i < ECORE_MAX_VF_CHAINS_PER_PF; i++) {
2087217ec208SDavid C Somayajulu 			struct ecore_vf_queue *p_queue = &p_vf->vf_queues[i];
2088217ec208SDavid C Somayajulu 			struct ecore_queue_cid *p_cid = OSAL_NULL;
2089217ec208SDavid C Somayajulu 
2090217ec208SDavid C Somayajulu 			/* There can be at most 1 Rx queue on qzone. Find it */
2091217ec208SDavid C Somayajulu 			p_cid = ecore_iov_get_vf_rx_queue_cid(p_queue);
2092217ec208SDavid C Somayajulu 			if (p_cid == OSAL_NULL)
2093217ec208SDavid C Somayajulu 				continue;
2094217ec208SDavid C Somayajulu 
2095217ec208SDavid C Somayajulu 			rc = ecore_sp_eth_rx_queues_update(p_hwfn,
2096217ec208SDavid C Somayajulu 							   (void **)&p_cid,
2097217ec208SDavid C Somayajulu 							   1, 0, 1,
2098217ec208SDavid C Somayajulu 							   ECORE_SPQ_MODE_EBLOCK,
2099217ec208SDavid C Somayajulu 							   OSAL_NULL);
2100217ec208SDavid C Somayajulu 			if (rc) {
2101217ec208SDavid C Somayajulu 				DP_NOTICE(p_hwfn, true,
2102217ec208SDavid C Somayajulu 					  "Failed to send Rx update fo queue[0x%04x]\n",
2103217ec208SDavid C Somayajulu 					  p_cid->rel.queue_id);
2104217ec208SDavid C Somayajulu 				return rc;
2105217ec208SDavid C Somayajulu 			}
2106217ec208SDavid C Somayajulu 		}
2107217ec208SDavid C Somayajulu 
2108217ec208SDavid C Somayajulu 		if (filter.vlan)
2109217ec208SDavid C Somayajulu 			p_vf->configured_features |= 1 << VLAN_ADDR_FORCED;
2110217ec208SDavid C Somayajulu 		else
2111217ec208SDavid C Somayajulu 			p_vf->configured_features &= ~(1 << VLAN_ADDR_FORCED);
2112217ec208SDavid C Somayajulu 	}
2113217ec208SDavid C Somayajulu 
2114217ec208SDavid C Somayajulu 	/* If forced features are terminated, we need to configure the shadow
2115217ec208SDavid C Somayajulu 	 * configuration back again.
2116217ec208SDavid C Somayajulu 	 */
2117217ec208SDavid C Somayajulu 	if (events)
2118217ec208SDavid C Somayajulu 		ecore_iov_reconfigure_unicast_shadow(p_hwfn, p_vf, events);
2119217ec208SDavid C Somayajulu 
2120217ec208SDavid C Somayajulu 	return rc;
2121217ec208SDavid C Somayajulu }
2122217ec208SDavid C Somayajulu 
ecore_iov_vf_mbx_start_vport(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * vf)2123217ec208SDavid C Somayajulu static void ecore_iov_vf_mbx_start_vport(struct ecore_hwfn *p_hwfn,
2124217ec208SDavid C Somayajulu 					 struct ecore_ptt *p_ptt,
2125217ec208SDavid C Somayajulu 					 struct ecore_vf_info *vf)
2126217ec208SDavid C Somayajulu {
2127217ec208SDavid C Somayajulu 	struct ecore_sp_vport_start_params params = {0};
2128217ec208SDavid C Somayajulu 	struct ecore_iov_vf_mbx *mbx = &vf->vf_mbx;
2129217ec208SDavid C Somayajulu 	struct vfpf_vport_start_tlv *start;
2130217ec208SDavid C Somayajulu 	u8 status = PFVF_STATUS_SUCCESS;
2131217ec208SDavid C Somayajulu 	struct ecore_vf_info *vf_info;
2132217ec208SDavid C Somayajulu 	u64 *p_bitmap;
2133217ec208SDavid C Somayajulu 	int sb_id;
2134217ec208SDavid C Somayajulu 	enum _ecore_status_t rc;
2135217ec208SDavid C Somayajulu 
2136217ec208SDavid C Somayajulu 	vf_info = ecore_iov_get_vf_info(p_hwfn, (u16)vf->relative_vf_id, true);
2137217ec208SDavid C Somayajulu 	if (!vf_info) {
2138217ec208SDavid C Somayajulu 		DP_NOTICE(p_hwfn->p_dev, true,
2139217ec208SDavid C Somayajulu 			  "Failed to get VF info, invalid vfid [%d]\n",
2140217ec208SDavid C Somayajulu 			  vf->relative_vf_id);
2141217ec208SDavid C Somayajulu 		return;
2142217ec208SDavid C Somayajulu 	}
2143217ec208SDavid C Somayajulu 
2144217ec208SDavid C Somayajulu 	vf->state = VF_ENABLED;
2145217ec208SDavid C Somayajulu 	start = &mbx->req_virt->start_vport;
2146217ec208SDavid C Somayajulu 
2147217ec208SDavid C Somayajulu 	ecore_iov_enable_vf_traffic(p_hwfn, p_ptt, vf);
2148217ec208SDavid C Somayajulu 
2149217ec208SDavid C Somayajulu 	/* Initialize Status block in CAU */
2150217ec208SDavid C Somayajulu 	for (sb_id = 0; sb_id < vf->num_sbs; sb_id++) {
2151217ec208SDavid C Somayajulu 		if (!start->sb_addr[sb_id]) {
2152217ec208SDavid C Somayajulu 			DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
2153217ec208SDavid C Somayajulu 				   "VF[%d] did not fill the address of SB %d\n",
2154217ec208SDavid C Somayajulu 				   vf->relative_vf_id, sb_id);
2155217ec208SDavid C Somayajulu 			break;
2156217ec208SDavid C Somayajulu 		}
2157217ec208SDavid C Somayajulu 
2158217ec208SDavid C Somayajulu 		ecore_int_cau_conf_sb(p_hwfn, p_ptt,
2159217ec208SDavid C Somayajulu 				      start->sb_addr[sb_id],
2160217ec208SDavid C Somayajulu 				      vf->igu_sbs[sb_id],
2161217ec208SDavid C Somayajulu 				      vf->abs_vf_id, 1);
2162217ec208SDavid C Somayajulu 	}
2163217ec208SDavid C Somayajulu 
2164217ec208SDavid C Somayajulu 	vf->mtu = start->mtu;
2165217ec208SDavid C Somayajulu 	vf->shadow_config.inner_vlan_removal = start->inner_vlan_removal;
2166217ec208SDavid C Somayajulu 
2167217ec208SDavid C Somayajulu 	/* Take into consideration configuration forced by hypervisor;
2168217ec208SDavid C Somayajulu 	 * If none is configured, use the supplied VF values [for old
2169217ec208SDavid C Somayajulu 	 * vfs that would still be fine, since they passed '0' as padding].
2170217ec208SDavid C Somayajulu 	 */
2171217ec208SDavid C Somayajulu 	p_bitmap = &vf_info->bulletin.p_virt->valid_bitmap;
2172217ec208SDavid C Somayajulu 	if (!(*p_bitmap & (1 << VFPF_BULLETIN_UNTAGGED_DEFAULT_FORCED))) {
2173217ec208SDavid C Somayajulu 		u8 vf_req = start->only_untagged;
2174217ec208SDavid C Somayajulu 
2175217ec208SDavid C Somayajulu 		vf_info->bulletin.p_virt->default_only_untagged = vf_req;
2176217ec208SDavid C Somayajulu 		*p_bitmap |= 1 << VFPF_BULLETIN_UNTAGGED_DEFAULT;
2177217ec208SDavid C Somayajulu 	}
2178217ec208SDavid C Somayajulu 
2179217ec208SDavid C Somayajulu 	params.tpa_mode =  start->tpa_mode;
2180217ec208SDavid C Somayajulu 	params.remove_inner_vlan = start->inner_vlan_removal;
2181217ec208SDavid C Somayajulu 	params.tx_switching = true;
2182217ec208SDavid C Somayajulu 	params.zero_placement_offset = start->zero_placement_offset;
2183217ec208SDavid C Somayajulu 
2184217ec208SDavid C Somayajulu #ifndef ASIC_ONLY
2185217ec208SDavid C Somayajulu 	if (CHIP_REV_IS_FPGA(p_hwfn->p_dev)) {
2186217ec208SDavid C Somayajulu 		DP_NOTICE(p_hwfn, false, "FPGA: Don't configure VF for Tx-switching [no pVFC]\n");
2187217ec208SDavid C Somayajulu 		params.tx_switching = false;
2188217ec208SDavid C Somayajulu 	}
2189217ec208SDavid C Somayajulu #endif
2190217ec208SDavid C Somayajulu 
2191217ec208SDavid C Somayajulu 	params.only_untagged = vf_info->bulletin.p_virt->default_only_untagged;
2192217ec208SDavid C Somayajulu 	params.drop_ttl0 = false;
2193217ec208SDavid C Somayajulu 	params.concrete_fid = vf->concrete_fid;
2194217ec208SDavid C Somayajulu 	params.opaque_fid = vf->opaque_fid;
2195217ec208SDavid C Somayajulu 	params.vport_id = vf->vport_id;
2196217ec208SDavid C Somayajulu 	params.max_buffers_per_cqe = start->max_buffers_per_cqe;
2197217ec208SDavid C Somayajulu 	params.mtu = vf->mtu;
2198217ec208SDavid C Somayajulu 	params.check_mac = true;
2199217ec208SDavid C Somayajulu 
2200217ec208SDavid C Somayajulu #ifndef ECORE_UPSTREAM
2201217ec208SDavid C Somayajulu 	rc = OSAL_IOV_PRE_START_VPORT(p_hwfn, vf->relative_vf_id, &params);
2202217ec208SDavid C Somayajulu 	if (rc != ECORE_SUCCESS) {
2203217ec208SDavid C Somayajulu 		DP_ERR(p_hwfn, "OSAL_IOV_PRE_START_VPORT returned error %d\n", rc);
2204217ec208SDavid C Somayajulu 		status = PFVF_STATUS_FAILURE;
2205217ec208SDavid C Somayajulu 		goto exit;
2206217ec208SDavid C Somayajulu 	}
2207217ec208SDavid C Somayajulu #endif
2208217ec208SDavid C Somayajulu 
2209217ec208SDavid C Somayajulu 	rc = ecore_sp_eth_vport_start(p_hwfn, &params);
2210217ec208SDavid C Somayajulu 	if (rc != ECORE_SUCCESS) {
2211217ec208SDavid C Somayajulu 		DP_ERR(p_hwfn, "ecore_iov_vf_mbx_start_vport returned error %d\n", rc);
2212217ec208SDavid C Somayajulu 		status = PFVF_STATUS_FAILURE;
2213217ec208SDavid C Somayajulu 	} else {
2214217ec208SDavid C Somayajulu 		vf->vport_instance++;
2215217ec208SDavid C Somayajulu 
2216217ec208SDavid C Somayajulu 		/* Force configuration if needed on the newly opened vport */
2217217ec208SDavid C Somayajulu 		ecore_iov_configure_vport_forced(p_hwfn, vf, *p_bitmap);
2218217ec208SDavid C Somayajulu 		OSAL_IOV_POST_START_VPORT(p_hwfn, vf->relative_vf_id,
2219217ec208SDavid C Somayajulu 					  vf->vport_id, vf->opaque_fid);
2220217ec208SDavid C Somayajulu 		__ecore_iov_spoofchk_set(p_hwfn, vf, vf->req_spoofchk_val);
2221217ec208SDavid C Somayajulu 	}
2222217ec208SDavid C Somayajulu #ifndef ECORE_UPSTREAM
2223217ec208SDavid C Somayajulu exit:
2224217ec208SDavid C Somayajulu #endif
2225217ec208SDavid C Somayajulu 	ecore_iov_prepare_resp(p_hwfn, p_ptt, vf, CHANNEL_TLV_VPORT_START,
2226217ec208SDavid C Somayajulu 			       sizeof(struct pfvf_def_resp_tlv), status);
2227217ec208SDavid C Somayajulu }
2228217ec208SDavid C Somayajulu 
ecore_iov_vf_mbx_stop_vport(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * vf)2229217ec208SDavid C Somayajulu static void ecore_iov_vf_mbx_stop_vport(struct ecore_hwfn *p_hwfn,
2230217ec208SDavid C Somayajulu 					struct ecore_ptt *p_ptt,
2231217ec208SDavid C Somayajulu 					struct ecore_vf_info *vf)
2232217ec208SDavid C Somayajulu {
2233217ec208SDavid C Somayajulu 	u8 status = PFVF_STATUS_SUCCESS;
2234217ec208SDavid C Somayajulu 	enum _ecore_status_t rc;
2235217ec208SDavid C Somayajulu 
2236217ec208SDavid C Somayajulu 	OSAL_IOV_VF_VPORT_STOP(p_hwfn, vf);
2237217ec208SDavid C Somayajulu 	vf->vport_instance--;
2238217ec208SDavid C Somayajulu 	vf->spoof_chk = false;
2239217ec208SDavid C Somayajulu 
2240217ec208SDavid C Somayajulu 	if ((ecore_iov_validate_active_rxq(vf)) ||
2241217ec208SDavid C Somayajulu 	    (ecore_iov_validate_active_txq(vf))) {
2242217ec208SDavid C Somayajulu 		vf->b_malicious = true;
2243217ec208SDavid C Somayajulu 		DP_NOTICE(p_hwfn,
2244217ec208SDavid C Somayajulu 			  false, " VF [%02x] - considered malicious; Unable to stop RX/TX queuess\n",
2245217ec208SDavid C Somayajulu 			  vf->abs_vf_id);
2246217ec208SDavid C Somayajulu 		status = PFVF_STATUS_MALICIOUS;
2247217ec208SDavid C Somayajulu 		goto out;
2248217ec208SDavid C Somayajulu 	}
2249217ec208SDavid C Somayajulu 
2250217ec208SDavid C Somayajulu 	rc = ecore_sp_vport_stop(p_hwfn, vf->opaque_fid, vf->vport_id);
2251217ec208SDavid C Somayajulu 	if (rc != ECORE_SUCCESS) {
2252217ec208SDavid C Somayajulu 		DP_ERR(p_hwfn, "ecore_iov_vf_mbx_stop_vport returned error %d\n",
2253217ec208SDavid C Somayajulu 		       rc);
2254217ec208SDavid C Somayajulu 		status = PFVF_STATUS_FAILURE;
2255217ec208SDavid C Somayajulu 	}
2256217ec208SDavid C Somayajulu 
2257217ec208SDavid C Somayajulu 	/* Forget the configuration on the vport */
2258217ec208SDavid C Somayajulu 	vf->configured_features = 0;
2259217ec208SDavid C Somayajulu 	OSAL_MEMSET(&vf->shadow_config, 0, sizeof(vf->shadow_config));
2260217ec208SDavid C Somayajulu 
2261217ec208SDavid C Somayajulu out:
2262217ec208SDavid C Somayajulu 	ecore_iov_prepare_resp(p_hwfn, p_ptt, vf, CHANNEL_TLV_VPORT_TEARDOWN,
2263217ec208SDavid C Somayajulu 			       sizeof(struct pfvf_def_resp_tlv), status);
2264217ec208SDavid C Somayajulu }
2265217ec208SDavid C Somayajulu 
ecore_iov_vf_mbx_start_rxq_resp(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * vf,u8 status,bool b_legacy)2266217ec208SDavid C Somayajulu static void ecore_iov_vf_mbx_start_rxq_resp(struct ecore_hwfn *p_hwfn,
2267217ec208SDavid C Somayajulu 					    struct ecore_ptt *p_ptt,
2268217ec208SDavid C Somayajulu 					    struct ecore_vf_info *vf,
2269217ec208SDavid C Somayajulu 					    u8 status, bool b_legacy)
2270217ec208SDavid C Somayajulu {
2271217ec208SDavid C Somayajulu 	struct ecore_iov_vf_mbx *mbx = &vf->vf_mbx;
2272217ec208SDavid C Somayajulu 	struct pfvf_start_queue_resp_tlv *p_tlv;
2273217ec208SDavid C Somayajulu 	struct vfpf_start_rxq_tlv *req;
2274217ec208SDavid C Somayajulu 	u16 length;
2275217ec208SDavid C Somayajulu 
2276217ec208SDavid C Somayajulu 	mbx->offset = (u8 *)mbx->reply_virt;
2277217ec208SDavid C Somayajulu 
2278217ec208SDavid C Somayajulu 	/* Taking a bigger struct instead of adding a TLV to list was a
2279217ec208SDavid C Somayajulu 	 * mistake, but one which we're now stuck with, as some older
2280217ec208SDavid C Somayajulu 	 * clients assume the size of the previous response.
2281217ec208SDavid C Somayajulu 	 */
2282217ec208SDavid C Somayajulu 	if (!b_legacy)
2283217ec208SDavid C Somayajulu 		length = sizeof(*p_tlv);
2284217ec208SDavid C Somayajulu 	else
2285217ec208SDavid C Somayajulu 		length = sizeof(struct pfvf_def_resp_tlv);
2286217ec208SDavid C Somayajulu 
2287217ec208SDavid C Somayajulu 	p_tlv = ecore_add_tlv(&mbx->offset, CHANNEL_TLV_START_RXQ, length);
2288217ec208SDavid C Somayajulu 	ecore_add_tlv(&mbx->offset, CHANNEL_TLV_LIST_END,
2289217ec208SDavid C Somayajulu 		      sizeof(struct channel_list_end_tlv));
2290217ec208SDavid C Somayajulu 
2291217ec208SDavid C Somayajulu 	/* Update the TLV with the response */
2292217ec208SDavid C Somayajulu 	if ((status == PFVF_STATUS_SUCCESS) && !b_legacy) {
2293217ec208SDavid C Somayajulu 		req = &mbx->req_virt->start_rxq;
2294217ec208SDavid C Somayajulu 		p_tlv->offset = PXP_VF_BAR0_START_MSDM_ZONE_B +
2295217ec208SDavid C Somayajulu 				OFFSETOF(struct mstorm_vf_zone,
2296217ec208SDavid C Somayajulu 					 non_trigger.eth_rx_queue_producers) +
2297217ec208SDavid C Somayajulu 				sizeof(struct eth_rx_prod_data) * req->rx_qid;
2298217ec208SDavid C Somayajulu 	}
2299217ec208SDavid C Somayajulu 
2300217ec208SDavid C Somayajulu 	ecore_iov_send_response(p_hwfn, p_ptt, vf, length, status);
2301217ec208SDavid C Somayajulu }
2302217ec208SDavid C Somayajulu 
ecore_iov_vf_mbx_qid(struct ecore_hwfn * p_hwfn,struct ecore_vf_info * p_vf,bool b_is_tx)2303217ec208SDavid C Somayajulu static u8 ecore_iov_vf_mbx_qid(struct ecore_hwfn *p_hwfn,
2304217ec208SDavid C Somayajulu 			       struct ecore_vf_info *p_vf, bool b_is_tx)
2305217ec208SDavid C Somayajulu {
2306217ec208SDavid C Somayajulu 	struct ecore_iov_vf_mbx *p_mbx = &p_vf->vf_mbx;
2307217ec208SDavid C Somayajulu 	struct vfpf_qid_tlv *p_qid_tlv;
2308217ec208SDavid C Somayajulu 
2309217ec208SDavid C Somayajulu 	/* Search for the qid if the VF published if its going to provide it */
2310217ec208SDavid C Somayajulu 	if (!(p_vf->acquire.vfdev_info.capabilities &
2311217ec208SDavid C Somayajulu 	      VFPF_ACQUIRE_CAP_QUEUE_QIDS)) {
2312217ec208SDavid C Somayajulu 		if (b_is_tx)
2313217ec208SDavid C Somayajulu 			return ECORE_IOV_LEGACY_QID_TX;
2314217ec208SDavid C Somayajulu 		else
2315217ec208SDavid C Somayajulu 			return ECORE_IOV_LEGACY_QID_RX;
2316217ec208SDavid C Somayajulu 	}
2317217ec208SDavid C Somayajulu 
2318217ec208SDavid C Somayajulu 	p_qid_tlv = (struct vfpf_qid_tlv *)
2319217ec208SDavid C Somayajulu 		    ecore_iov_search_list_tlvs(p_hwfn, p_mbx->req_virt,
2320217ec208SDavid C Somayajulu 					       CHANNEL_TLV_QID);
2321217ec208SDavid C Somayajulu 	if (p_qid_tlv == OSAL_NULL) {
2322217ec208SDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
2323217ec208SDavid C Somayajulu 			   "VF[%2x]: Failed to provide qid\n",
2324217ec208SDavid C Somayajulu 			   p_vf->relative_vf_id);
2325217ec208SDavid C Somayajulu 
2326217ec208SDavid C Somayajulu 		return ECORE_IOV_QID_INVALID;
2327217ec208SDavid C Somayajulu 	}
2328217ec208SDavid C Somayajulu 
2329217ec208SDavid C Somayajulu 	if (p_qid_tlv->qid >= MAX_QUEUES_PER_QZONE) {
2330217ec208SDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
2331217ec208SDavid C Somayajulu 			   "VF[%02x]: Provided qid out-of-bounds %02x\n",
2332217ec208SDavid C Somayajulu 			   p_vf->relative_vf_id, p_qid_tlv->qid);
2333217ec208SDavid C Somayajulu 		return ECORE_IOV_QID_INVALID;
2334217ec208SDavid C Somayajulu 	}
2335217ec208SDavid C Somayajulu 
2336217ec208SDavid C Somayajulu 	return p_qid_tlv->qid;
2337217ec208SDavid C Somayajulu }
2338217ec208SDavid C Somayajulu 
ecore_iov_vf_mbx_start_rxq(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * vf)2339217ec208SDavid C Somayajulu static void ecore_iov_vf_mbx_start_rxq(struct ecore_hwfn *p_hwfn,
2340217ec208SDavid C Somayajulu 				       struct ecore_ptt *p_ptt,
2341217ec208SDavid C Somayajulu 				       struct ecore_vf_info *vf)
2342217ec208SDavid C Somayajulu {
2343217ec208SDavid C Somayajulu 	struct ecore_queue_start_common_params params;
2344217ec208SDavid C Somayajulu 	struct ecore_queue_cid_vf_params vf_params;
2345217ec208SDavid C Somayajulu 	struct ecore_iov_vf_mbx *mbx = &vf->vf_mbx;
2346217ec208SDavid C Somayajulu 	u8 status = PFVF_STATUS_NO_RESOURCE;
2347217ec208SDavid C Somayajulu 	u8 qid_usage_idx, vf_legacy = 0;
2348217ec208SDavid C Somayajulu 	struct ecore_vf_queue *p_queue;
2349217ec208SDavid C Somayajulu 	struct vfpf_start_rxq_tlv *req;
2350217ec208SDavid C Somayajulu 	struct ecore_queue_cid *p_cid;
2351217ec208SDavid C Somayajulu 	struct ecore_sb_info sb_dummy;
2352217ec208SDavid C Somayajulu 	enum _ecore_status_t rc;
2353217ec208SDavid C Somayajulu 
2354217ec208SDavid C Somayajulu 	req = &mbx->req_virt->start_rxq;
2355217ec208SDavid C Somayajulu 
2356217ec208SDavid C Somayajulu 	if (!ecore_iov_validate_rxq(p_hwfn, vf, req->rx_qid,
2357217ec208SDavid C Somayajulu 				    ECORE_IOV_VALIDATE_Q_DISABLE) ||
2358217ec208SDavid C Somayajulu 	    !ecore_iov_validate_sb(p_hwfn, vf, req->hw_sb))
2359217ec208SDavid C Somayajulu 		goto out;
2360217ec208SDavid C Somayajulu 
2361217ec208SDavid C Somayajulu 	qid_usage_idx = ecore_iov_vf_mbx_qid(p_hwfn, vf, false);
2362217ec208SDavid C Somayajulu 	if (qid_usage_idx == ECORE_IOV_QID_INVALID)
2363217ec208SDavid C Somayajulu 		goto out;
2364217ec208SDavid C Somayajulu 
2365217ec208SDavid C Somayajulu 	p_queue = &vf->vf_queues[req->rx_qid];
2366217ec208SDavid C Somayajulu 	if (p_queue->cids[qid_usage_idx].p_cid)
2367217ec208SDavid C Somayajulu 		goto out;
2368217ec208SDavid C Somayajulu 
2369217ec208SDavid C Somayajulu 	vf_legacy = ecore_vf_calculate_legacy(vf);
2370217ec208SDavid C Somayajulu 
2371217ec208SDavid C Somayajulu 	/* Acquire a new queue-cid */
2372217ec208SDavid C Somayajulu 	OSAL_MEMSET(&params, 0, sizeof(params));
2373217ec208SDavid C Somayajulu 	params.queue_id = (u8)p_queue->fw_rx_qid;
2374217ec208SDavid C Somayajulu 	params.vport_id = vf->vport_id;
2375217ec208SDavid C Somayajulu 	params.stats_id = vf->abs_vf_id + 0x10;
2376217ec208SDavid C Somayajulu 
2377217ec208SDavid C Somayajulu 	/* Since IGU index is passed via sb_info, construct a dummy one */
2378217ec208SDavid C Somayajulu 	OSAL_MEM_ZERO(&sb_dummy, sizeof(sb_dummy));
2379217ec208SDavid C Somayajulu 	sb_dummy.igu_sb_id = req->hw_sb;
2380217ec208SDavid C Somayajulu 	params.p_sb = &sb_dummy;
2381217ec208SDavid C Somayajulu 	params.sb_idx = req->sb_index;
2382217ec208SDavid C Somayajulu 
2383217ec208SDavid C Somayajulu 	OSAL_MEM_ZERO(&vf_params, sizeof(vf_params));
2384217ec208SDavid C Somayajulu 	vf_params.vfid = vf->relative_vf_id;
2385217ec208SDavid C Somayajulu 	vf_params.vf_qid = (u8)req->rx_qid;
2386217ec208SDavid C Somayajulu 	vf_params.vf_legacy = vf_legacy;
2387217ec208SDavid C Somayajulu 	vf_params.qid_usage_idx = qid_usage_idx;
2388217ec208SDavid C Somayajulu 
2389217ec208SDavid C Somayajulu 	p_cid = ecore_eth_queue_to_cid(p_hwfn, vf->opaque_fid,
2390217ec208SDavid C Somayajulu 				       &params, true, &vf_params);
2391217ec208SDavid C Somayajulu 	if (p_cid == OSAL_NULL)
2392217ec208SDavid C Somayajulu 		goto out;
2393217ec208SDavid C Somayajulu 
2394217ec208SDavid C Somayajulu 	/* Legacy VFs have their Producers in a different location, which they
2395217ec208SDavid C Somayajulu 	 * calculate on their own and clean the producer prior to this.
2396217ec208SDavid C Somayajulu 	 */
2397217ec208SDavid C Somayajulu 	if (!(vf_legacy & ECORE_QCID_LEGACY_VF_RX_PROD))
2398217ec208SDavid C Somayajulu 		REG_WR(p_hwfn,
2399217ec208SDavid C Somayajulu 		       GTT_BAR0_MAP_REG_MSDM_RAM +
2400217ec208SDavid C Somayajulu 		       MSTORM_ETH_VF_PRODS_OFFSET(vf->abs_vf_id, req->rx_qid),
2401217ec208SDavid C Somayajulu 		       0);
2402217ec208SDavid C Somayajulu 
2403217ec208SDavid C Somayajulu 	rc = ecore_eth_rxq_start_ramrod(p_hwfn, p_cid,
2404217ec208SDavid C Somayajulu 					req->bd_max_bytes,
2405217ec208SDavid C Somayajulu 					req->rxq_addr,
2406217ec208SDavid C Somayajulu 					req->cqe_pbl_addr,
2407217ec208SDavid C Somayajulu 					req->cqe_pbl_size);
2408217ec208SDavid C Somayajulu 	if (rc != ECORE_SUCCESS) {
2409217ec208SDavid C Somayajulu 		status = PFVF_STATUS_FAILURE;
2410217ec208SDavid C Somayajulu 		ecore_eth_queue_cid_release(p_hwfn, p_cid);
2411217ec208SDavid C Somayajulu 	} else {
2412217ec208SDavid C Somayajulu 		p_queue->cids[qid_usage_idx].p_cid = p_cid;
2413217ec208SDavid C Somayajulu 		p_queue->cids[qid_usage_idx].b_is_tx = false;
2414217ec208SDavid C Somayajulu 		status = PFVF_STATUS_SUCCESS;
2415217ec208SDavid C Somayajulu 		vf->num_active_rxqs++;
2416217ec208SDavid C Somayajulu 	}
2417217ec208SDavid C Somayajulu 
2418217ec208SDavid C Somayajulu out:
2419217ec208SDavid C Somayajulu 	ecore_iov_vf_mbx_start_rxq_resp(p_hwfn, p_ptt, vf, status,
2420217ec208SDavid C Somayajulu 					!!(vf_legacy &
2421217ec208SDavid C Somayajulu 					   ECORE_QCID_LEGACY_VF_RX_PROD));
2422217ec208SDavid C Somayajulu }
2423217ec208SDavid C Somayajulu 
2424217ec208SDavid C Somayajulu static void
ecore_iov_pf_update_tun_response(struct pfvf_update_tunn_param_tlv * p_resp,struct ecore_tunnel_info * p_tun,u16 tunn_feature_mask)2425217ec208SDavid C Somayajulu ecore_iov_pf_update_tun_response(struct pfvf_update_tunn_param_tlv *p_resp,
2426217ec208SDavid C Somayajulu 				 struct ecore_tunnel_info *p_tun,
2427217ec208SDavid C Somayajulu 				 u16 tunn_feature_mask)
2428217ec208SDavid C Somayajulu {
2429217ec208SDavid C Somayajulu 	p_resp->tunn_feature_mask = tunn_feature_mask;
2430217ec208SDavid C Somayajulu 	p_resp->vxlan_mode = p_tun->vxlan.b_mode_enabled;
2431217ec208SDavid C Somayajulu 	p_resp->l2geneve_mode = p_tun->l2_geneve.b_mode_enabled;
2432217ec208SDavid C Somayajulu 	p_resp->ipgeneve_mode = p_tun->ip_geneve.b_mode_enabled;
2433217ec208SDavid C Somayajulu 	p_resp->l2gre_mode = p_tun->l2_gre.b_mode_enabled;
2434217ec208SDavid C Somayajulu 	p_resp->ipgre_mode = p_tun->l2_gre.b_mode_enabled;
2435217ec208SDavid C Somayajulu 	p_resp->vxlan_clss = p_tun->vxlan.tun_cls;
2436217ec208SDavid C Somayajulu 	p_resp->l2gre_clss = p_tun->l2_gre.tun_cls;
2437217ec208SDavid C Somayajulu 	p_resp->ipgre_clss = p_tun->ip_gre.tun_cls;
2438217ec208SDavid C Somayajulu 	p_resp->l2geneve_clss = p_tun->l2_geneve.tun_cls;
2439217ec208SDavid C Somayajulu 	p_resp->ipgeneve_clss = p_tun->ip_geneve.tun_cls;
2440217ec208SDavid C Somayajulu 	p_resp->geneve_udp_port = p_tun->geneve_port.port;
2441217ec208SDavid C Somayajulu 	p_resp->vxlan_udp_port = p_tun->vxlan_port.port;
2442217ec208SDavid C Somayajulu }
2443217ec208SDavid C Somayajulu 
2444217ec208SDavid C Somayajulu static void
__ecore_iov_pf_update_tun_param(struct vfpf_update_tunn_param_tlv * p_req,struct ecore_tunn_update_type * p_tun,enum ecore_tunn_mode mask,u8 tun_cls)2445217ec208SDavid C Somayajulu __ecore_iov_pf_update_tun_param(struct vfpf_update_tunn_param_tlv *p_req,
2446217ec208SDavid C Somayajulu 				struct ecore_tunn_update_type *p_tun,
2447217ec208SDavid C Somayajulu 				enum ecore_tunn_mode mask, u8 tun_cls)
2448217ec208SDavid C Somayajulu {
2449217ec208SDavid C Somayajulu 	if (p_req->tun_mode_update_mask & (1 << mask)) {
2450217ec208SDavid C Somayajulu 		p_tun->b_update_mode = true;
2451217ec208SDavid C Somayajulu 
2452217ec208SDavid C Somayajulu 		if (p_req->tunn_mode & (1 << mask))
2453217ec208SDavid C Somayajulu 			p_tun->b_mode_enabled = true;
2454217ec208SDavid C Somayajulu 	}
2455217ec208SDavid C Somayajulu 
2456217ec208SDavid C Somayajulu 	p_tun->tun_cls = tun_cls;
2457217ec208SDavid C Somayajulu }
2458217ec208SDavid C Somayajulu 
2459217ec208SDavid C Somayajulu static void
ecore_iov_pf_update_tun_param(struct vfpf_update_tunn_param_tlv * p_req,struct ecore_tunn_update_type * p_tun,struct ecore_tunn_update_udp_port * p_port,enum ecore_tunn_mode mask,u8 tun_cls,u8 update_port,u16 port)2460217ec208SDavid C Somayajulu ecore_iov_pf_update_tun_param(struct vfpf_update_tunn_param_tlv *p_req,
2461217ec208SDavid C Somayajulu 			      struct ecore_tunn_update_type *p_tun,
2462217ec208SDavid C Somayajulu 			      struct ecore_tunn_update_udp_port *p_port,
2463217ec208SDavid C Somayajulu 			      enum ecore_tunn_mode mask,
2464217ec208SDavid C Somayajulu 			      u8 tun_cls, u8 update_port, u16 port)
2465217ec208SDavid C Somayajulu {
2466217ec208SDavid C Somayajulu 	if (update_port) {
2467217ec208SDavid C Somayajulu 		p_port->b_update_port = true;
2468217ec208SDavid C Somayajulu 		p_port->port = port;
2469217ec208SDavid C Somayajulu 	}
2470217ec208SDavid C Somayajulu 
2471217ec208SDavid C Somayajulu 	__ecore_iov_pf_update_tun_param(p_req, p_tun, mask, tun_cls);
2472217ec208SDavid C Somayajulu }
2473217ec208SDavid C Somayajulu 
2474217ec208SDavid C Somayajulu static bool
ecore_iov_pf_validate_tunn_param(struct vfpf_update_tunn_param_tlv * p_req)2475217ec208SDavid C Somayajulu ecore_iov_pf_validate_tunn_param(struct vfpf_update_tunn_param_tlv *p_req)
2476217ec208SDavid C Somayajulu {
2477217ec208SDavid C Somayajulu 	bool b_update_requested = false;
2478217ec208SDavid C Somayajulu 
2479217ec208SDavid C Somayajulu 	if (p_req->tun_mode_update_mask || p_req->update_tun_cls ||
2480217ec208SDavid C Somayajulu 	    p_req->update_geneve_port || p_req->update_vxlan_port)
2481217ec208SDavid C Somayajulu 		b_update_requested = true;
2482217ec208SDavid C Somayajulu 
2483217ec208SDavid C Somayajulu 	return b_update_requested;
2484217ec208SDavid C Somayajulu }
2485217ec208SDavid C Somayajulu 
ecore_iov_vf_mbx_update_tunn_param(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * p_vf)2486217ec208SDavid C Somayajulu static void ecore_iov_vf_mbx_update_tunn_param(struct ecore_hwfn *p_hwfn,
2487217ec208SDavid C Somayajulu 					       struct ecore_ptt *p_ptt,
2488217ec208SDavid C Somayajulu 					       struct ecore_vf_info *p_vf)
2489217ec208SDavid C Somayajulu {
2490217ec208SDavid C Somayajulu 	struct ecore_tunnel_info *p_tun = &p_hwfn->p_dev->tunnel;
2491217ec208SDavid C Somayajulu 	struct ecore_iov_vf_mbx *mbx = &p_vf->vf_mbx;
2492217ec208SDavid C Somayajulu 	struct pfvf_update_tunn_param_tlv *p_resp;
2493217ec208SDavid C Somayajulu 	struct vfpf_update_tunn_param_tlv *p_req;
2494217ec208SDavid C Somayajulu 	enum _ecore_status_t rc = ECORE_SUCCESS;
2495217ec208SDavid C Somayajulu 	u8 status = PFVF_STATUS_SUCCESS;
2496217ec208SDavid C Somayajulu 	bool b_update_required = false;
2497217ec208SDavid C Somayajulu 	struct ecore_tunnel_info tunn;
2498217ec208SDavid C Somayajulu 	u16 tunn_feature_mask = 0;
2499217ec208SDavid C Somayajulu 	int i;
2500217ec208SDavid C Somayajulu 
2501217ec208SDavid C Somayajulu 	mbx->offset = (u8 *)mbx->reply_virt;
2502217ec208SDavid C Somayajulu 
2503217ec208SDavid C Somayajulu 	OSAL_MEM_ZERO(&tunn, sizeof(tunn));
2504217ec208SDavid C Somayajulu 	p_req = &mbx->req_virt->tunn_param_update;
2505217ec208SDavid C Somayajulu 
2506217ec208SDavid C Somayajulu 	if (!ecore_iov_pf_validate_tunn_param(p_req)) {
2507217ec208SDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
2508217ec208SDavid C Somayajulu 			   "No tunnel update requested by VF\n");
2509217ec208SDavid C Somayajulu 		status = PFVF_STATUS_FAILURE;
2510217ec208SDavid C Somayajulu 		goto send_resp;
2511217ec208SDavid C Somayajulu 	}
2512217ec208SDavid C Somayajulu 
2513217ec208SDavid C Somayajulu 	tunn.b_update_rx_cls = p_req->update_tun_cls;
2514217ec208SDavid C Somayajulu 	tunn.b_update_tx_cls = p_req->update_tun_cls;
2515217ec208SDavid C Somayajulu 
2516217ec208SDavid C Somayajulu 	ecore_iov_pf_update_tun_param(p_req, &tunn.vxlan, &tunn.vxlan_port,
2517217ec208SDavid C Somayajulu 				      ECORE_MODE_VXLAN_TUNN, p_req->vxlan_clss,
2518217ec208SDavid C Somayajulu 				      p_req->update_vxlan_port,
2519217ec208SDavid C Somayajulu 				      p_req->vxlan_port);
2520217ec208SDavid C Somayajulu 	ecore_iov_pf_update_tun_param(p_req, &tunn.l2_geneve, &tunn.geneve_port,
2521217ec208SDavid C Somayajulu 				      ECORE_MODE_L2GENEVE_TUNN,
2522217ec208SDavid C Somayajulu 				      p_req->l2geneve_clss,
2523217ec208SDavid C Somayajulu 				      p_req->update_geneve_port,
2524217ec208SDavid C Somayajulu 				      p_req->geneve_port);
2525217ec208SDavid C Somayajulu 	__ecore_iov_pf_update_tun_param(p_req, &tunn.ip_geneve,
2526217ec208SDavid C Somayajulu 					ECORE_MODE_IPGENEVE_TUNN,
2527217ec208SDavid C Somayajulu 					p_req->ipgeneve_clss);
2528217ec208SDavid C Somayajulu 	__ecore_iov_pf_update_tun_param(p_req, &tunn.l2_gre,
2529217ec208SDavid C Somayajulu 					ECORE_MODE_L2GRE_TUNN,
2530217ec208SDavid C Somayajulu 					p_req->l2gre_clss);
2531217ec208SDavid C Somayajulu 	__ecore_iov_pf_update_tun_param(p_req, &tunn.ip_gre,
2532217ec208SDavid C Somayajulu 					ECORE_MODE_IPGRE_TUNN,
2533217ec208SDavid C Somayajulu 					p_req->ipgre_clss);
2534217ec208SDavid C Somayajulu 
2535217ec208SDavid C Somayajulu 	/* If PF modifies VF's req then it should
2536217ec208SDavid C Somayajulu 	 * still return an error in case of partial configuration
2537217ec208SDavid C Somayajulu 	 * or modified configuration as opposed to requested one.
2538217ec208SDavid C Somayajulu 	 */
2539217ec208SDavid C Somayajulu 	rc = OSAL_PF_VALIDATE_MODIFY_TUNN_CONFIG(p_hwfn, &tunn_feature_mask,
2540217ec208SDavid C Somayajulu 						 &b_update_required, &tunn);
2541217ec208SDavid C Somayajulu 
2542217ec208SDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
2543217ec208SDavid C Somayajulu 		status = PFVF_STATUS_FAILURE;
2544217ec208SDavid C Somayajulu 
2545217ec208SDavid C Somayajulu 	/* If ECORE client is willing to update anything ? */
2546217ec208SDavid C Somayajulu 	if (b_update_required) {
2547217ec208SDavid C Somayajulu 		u16 geneve_port;
2548217ec208SDavid C Somayajulu 
2549217ec208SDavid C Somayajulu 		rc = ecore_sp_pf_update_tunn_cfg(p_hwfn, p_ptt, &tunn,
2550217ec208SDavid C Somayajulu 						 ECORE_SPQ_MODE_EBLOCK,
2551217ec208SDavid C Somayajulu 						 OSAL_NULL);
2552217ec208SDavid C Somayajulu 		if (rc != ECORE_SUCCESS)
2553217ec208SDavid C Somayajulu 			status = PFVF_STATUS_FAILURE;
2554217ec208SDavid C Somayajulu 
2555217ec208SDavid C Somayajulu 		geneve_port = p_tun->geneve_port.port;
2556217ec208SDavid C Somayajulu 		ecore_for_each_vf(p_hwfn, i) {
2557217ec208SDavid C Somayajulu 			ecore_iov_bulletin_set_udp_ports(p_hwfn, i,
2558217ec208SDavid C Somayajulu 							 p_tun->vxlan_port.port,
2559217ec208SDavid C Somayajulu 							 geneve_port);
2560217ec208SDavid C Somayajulu 		}
2561217ec208SDavid C Somayajulu 	}
2562217ec208SDavid C Somayajulu 
2563217ec208SDavid C Somayajulu send_resp:
2564217ec208SDavid C Somayajulu 	p_resp = ecore_add_tlv(&mbx->offset,
2565217ec208SDavid C Somayajulu 			       CHANNEL_TLV_UPDATE_TUNN_PARAM, sizeof(*p_resp));
2566217ec208SDavid C Somayajulu 
2567217ec208SDavid C Somayajulu 	ecore_iov_pf_update_tun_response(p_resp, p_tun, tunn_feature_mask);
2568217ec208SDavid C Somayajulu 	ecore_add_tlv(&mbx->offset, CHANNEL_TLV_LIST_END,
2569217ec208SDavid C Somayajulu 		      sizeof(struct channel_list_end_tlv));
2570217ec208SDavid C Somayajulu 
2571217ec208SDavid C Somayajulu 	ecore_iov_send_response(p_hwfn, p_ptt, p_vf, sizeof(*p_resp), status);
2572217ec208SDavid C Somayajulu }
2573217ec208SDavid C Somayajulu 
ecore_iov_vf_mbx_start_txq_resp(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * p_vf,u32 cid,u8 status)2574217ec208SDavid C Somayajulu static void ecore_iov_vf_mbx_start_txq_resp(struct ecore_hwfn *p_hwfn,
2575217ec208SDavid C Somayajulu 					    struct ecore_ptt *p_ptt,
2576217ec208SDavid C Somayajulu 					    struct ecore_vf_info *p_vf,
2577217ec208SDavid C Somayajulu 					    u32 cid,
2578217ec208SDavid C Somayajulu 					    u8 status)
2579217ec208SDavid C Somayajulu {
2580217ec208SDavid C Somayajulu 	struct ecore_iov_vf_mbx *mbx = &p_vf->vf_mbx;
2581217ec208SDavid C Somayajulu 	struct pfvf_start_queue_resp_tlv *p_tlv;
2582217ec208SDavid C Somayajulu 	bool b_legacy = false;
2583217ec208SDavid C Somayajulu 	u16 length;
2584217ec208SDavid C Somayajulu 
2585217ec208SDavid C Somayajulu 	mbx->offset = (u8 *)mbx->reply_virt;
2586217ec208SDavid C Somayajulu 
2587217ec208SDavid C Somayajulu 	/* Taking a bigger struct instead of adding a TLV to list was a
2588217ec208SDavid C Somayajulu 	 * mistake, but one which we're now stuck with, as some older
2589217ec208SDavid C Somayajulu 	 * clients assume the size of the previous response.
2590217ec208SDavid C Somayajulu 	 */
2591217ec208SDavid C Somayajulu 	if (p_vf->acquire.vfdev_info.eth_fp_hsi_minor ==
2592217ec208SDavid C Somayajulu 	    ETH_HSI_VER_NO_PKT_LEN_TUNN)
2593217ec208SDavid C Somayajulu 		b_legacy = true;
2594217ec208SDavid C Somayajulu 
2595217ec208SDavid C Somayajulu 	if (!b_legacy)
2596217ec208SDavid C Somayajulu 		length = sizeof(*p_tlv);
2597217ec208SDavid C Somayajulu 	else
2598217ec208SDavid C Somayajulu 		length = sizeof(struct pfvf_def_resp_tlv);
2599217ec208SDavid C Somayajulu 
2600217ec208SDavid C Somayajulu 	p_tlv = ecore_add_tlv(&mbx->offset, CHANNEL_TLV_START_TXQ, length);
2601217ec208SDavid C Somayajulu 	ecore_add_tlv(&mbx->offset, CHANNEL_TLV_LIST_END,
2602217ec208SDavid C Somayajulu 		      sizeof(struct channel_list_end_tlv));
2603217ec208SDavid C Somayajulu 
2604217ec208SDavid C Somayajulu 	/* Update the TLV with the response */
2605217ec208SDavid C Somayajulu 	if ((status == PFVF_STATUS_SUCCESS) && !b_legacy)
2606217ec208SDavid C Somayajulu 		p_tlv->offset = DB_ADDR_VF(cid, DQ_DEMS_LEGACY);
2607217ec208SDavid C Somayajulu 
2608217ec208SDavid C Somayajulu 	ecore_iov_send_response(p_hwfn, p_ptt, p_vf, length, status);
2609217ec208SDavid C Somayajulu }
2610217ec208SDavid C Somayajulu 
ecore_iov_vf_mbx_start_txq(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * vf)2611217ec208SDavid C Somayajulu static void ecore_iov_vf_mbx_start_txq(struct ecore_hwfn *p_hwfn,
2612217ec208SDavid C Somayajulu 				       struct ecore_ptt *p_ptt,
2613217ec208SDavid C Somayajulu 				       struct ecore_vf_info *vf)
2614217ec208SDavid C Somayajulu {
2615217ec208SDavid C Somayajulu 	struct ecore_queue_start_common_params params;
2616217ec208SDavid C Somayajulu 	struct ecore_queue_cid_vf_params vf_params;
2617217ec208SDavid C Somayajulu 	struct ecore_iov_vf_mbx *mbx = &vf->vf_mbx;
2618217ec208SDavid C Somayajulu 	u8 status = PFVF_STATUS_NO_RESOURCE;
2619217ec208SDavid C Somayajulu 	struct ecore_vf_queue *p_queue;
2620217ec208SDavid C Somayajulu 	struct vfpf_start_txq_tlv *req;
2621217ec208SDavid C Somayajulu 	struct ecore_queue_cid *p_cid;
2622217ec208SDavid C Somayajulu 	struct ecore_sb_info sb_dummy;
2623217ec208SDavid C Somayajulu 	u8 qid_usage_idx, vf_legacy;
2624217ec208SDavid C Somayajulu 	u32 cid = 0;
2625217ec208SDavid C Somayajulu 	enum _ecore_status_t rc;
2626217ec208SDavid C Somayajulu 	u16 pq;
2627217ec208SDavid C Somayajulu 
2628217ec208SDavid C Somayajulu 	OSAL_MEMSET(&params, 0, sizeof(params));
2629217ec208SDavid C Somayajulu 	req = &mbx->req_virt->start_txq;
2630217ec208SDavid C Somayajulu 
2631217ec208SDavid C Somayajulu 	if (!ecore_iov_validate_txq(p_hwfn, vf, req->tx_qid,
2632217ec208SDavid C Somayajulu 				    ECORE_IOV_VALIDATE_Q_NA) ||
2633217ec208SDavid C Somayajulu 	    !ecore_iov_validate_sb(p_hwfn, vf, req->hw_sb))
2634217ec208SDavid C Somayajulu 		goto out;
2635217ec208SDavid C Somayajulu 
2636217ec208SDavid C Somayajulu 	qid_usage_idx = ecore_iov_vf_mbx_qid(p_hwfn, vf, true);
2637217ec208SDavid C Somayajulu 	if (qid_usage_idx == ECORE_IOV_QID_INVALID)
2638217ec208SDavid C Somayajulu 		goto out;
2639217ec208SDavid C Somayajulu 
2640217ec208SDavid C Somayajulu 	p_queue = &vf->vf_queues[req->tx_qid];
2641217ec208SDavid C Somayajulu 	if (p_queue->cids[qid_usage_idx].p_cid)
2642217ec208SDavid C Somayajulu 		goto out;
2643217ec208SDavid C Somayajulu 
2644217ec208SDavid C Somayajulu 	vf_legacy = ecore_vf_calculate_legacy(vf);
2645217ec208SDavid C Somayajulu 
2646217ec208SDavid C Somayajulu 	/* Acquire a new queue-cid */
2647217ec208SDavid C Somayajulu 	params.queue_id = p_queue->fw_tx_qid;
2648217ec208SDavid C Somayajulu 	params.vport_id = vf->vport_id;
2649217ec208SDavid C Somayajulu 	params.stats_id = vf->abs_vf_id + 0x10;
2650217ec208SDavid C Somayajulu 
2651217ec208SDavid C Somayajulu 	/* Since IGU index is passed via sb_info, construct a dummy one */
2652217ec208SDavid C Somayajulu 	OSAL_MEM_ZERO(&sb_dummy, sizeof(sb_dummy));
2653217ec208SDavid C Somayajulu 	sb_dummy.igu_sb_id = req->hw_sb;
2654217ec208SDavid C Somayajulu 	params.p_sb = &sb_dummy;
2655217ec208SDavid C Somayajulu 	params.sb_idx = req->sb_index;
2656217ec208SDavid C Somayajulu 
2657217ec208SDavid C Somayajulu 	OSAL_MEM_ZERO(&vf_params, sizeof(vf_params));
2658217ec208SDavid C Somayajulu 	vf_params.vfid = vf->relative_vf_id;
2659217ec208SDavid C Somayajulu 	vf_params.vf_qid = (u8)req->tx_qid;
2660217ec208SDavid C Somayajulu 	vf_params.vf_legacy = vf_legacy;
2661217ec208SDavid C Somayajulu 	vf_params.qid_usage_idx = qid_usage_idx;
2662217ec208SDavid C Somayajulu 
2663217ec208SDavid C Somayajulu 	p_cid = ecore_eth_queue_to_cid(p_hwfn, vf->opaque_fid,
2664217ec208SDavid C Somayajulu 				       &params, false, &vf_params);
2665217ec208SDavid C Somayajulu 	if (p_cid == OSAL_NULL)
2666217ec208SDavid C Somayajulu 		goto out;
2667217ec208SDavid C Somayajulu 
2668217ec208SDavid C Somayajulu 	pq = ecore_get_cm_pq_idx_vf(p_hwfn,
2669217ec208SDavid C Somayajulu 				    vf->relative_vf_id);
2670217ec208SDavid C Somayajulu 	rc = ecore_eth_txq_start_ramrod(p_hwfn, p_cid,
2671217ec208SDavid C Somayajulu 					req->pbl_addr, req->pbl_size, pq);
2672217ec208SDavid C Somayajulu 	if (rc != ECORE_SUCCESS) {
2673217ec208SDavid C Somayajulu 		status = PFVF_STATUS_FAILURE;
2674217ec208SDavid C Somayajulu 		ecore_eth_queue_cid_release(p_hwfn, p_cid);
2675217ec208SDavid C Somayajulu 	} else {
2676217ec208SDavid C Somayajulu 		status = PFVF_STATUS_SUCCESS;
2677217ec208SDavid C Somayajulu 		p_queue->cids[qid_usage_idx].p_cid = p_cid;
2678217ec208SDavid C Somayajulu 		p_queue->cids[qid_usage_idx].b_is_tx = true;
2679217ec208SDavid C Somayajulu 		cid = p_cid->cid;
2680217ec208SDavid C Somayajulu 	}
2681217ec208SDavid C Somayajulu 
2682217ec208SDavid C Somayajulu out:
2683217ec208SDavid C Somayajulu 	ecore_iov_vf_mbx_start_txq_resp(p_hwfn, p_ptt, vf,
2684217ec208SDavid C Somayajulu 					cid, status);
2685217ec208SDavid C Somayajulu }
2686217ec208SDavid C Somayajulu 
ecore_iov_vf_stop_rxqs(struct ecore_hwfn * p_hwfn,struct ecore_vf_info * vf,u16 rxq_id,u8 qid_usage_idx,bool cqe_completion)2687217ec208SDavid C Somayajulu static enum _ecore_status_t ecore_iov_vf_stop_rxqs(struct ecore_hwfn *p_hwfn,
2688217ec208SDavid C Somayajulu 						   struct ecore_vf_info *vf,
2689217ec208SDavid C Somayajulu 						   u16 rxq_id,
2690217ec208SDavid C Somayajulu 						   u8 qid_usage_idx,
2691217ec208SDavid C Somayajulu 						   bool cqe_completion)
2692217ec208SDavid C Somayajulu {
2693217ec208SDavid C Somayajulu 	struct ecore_vf_queue *p_queue;
2694217ec208SDavid C Somayajulu 	enum _ecore_status_t rc = ECORE_SUCCESS;
2695217ec208SDavid C Somayajulu 
2696217ec208SDavid C Somayajulu 	if (!ecore_iov_validate_rxq(p_hwfn, vf, rxq_id,
2697217ec208SDavid C Somayajulu 				    ECORE_IOV_VALIDATE_Q_NA)) {
2698217ec208SDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
2699217ec208SDavid C Somayajulu 			   "VF[%d] Tried Closing Rx 0x%04x.%02x which is inactive\n",
2700217ec208SDavid C Somayajulu 			   vf->relative_vf_id, rxq_id, qid_usage_idx);
2701217ec208SDavid C Somayajulu 		return ECORE_INVAL;
2702217ec208SDavid C Somayajulu 	}
2703217ec208SDavid C Somayajulu 
2704217ec208SDavid C Somayajulu 	p_queue = &vf->vf_queues[rxq_id];
2705217ec208SDavid C Somayajulu 
2706a216b9c2SGordon Bergling 	/* We've validated the index and the existence of the active RXQ -
2707217ec208SDavid C Somayajulu 	 * now we need to make sure that it's using the correct qid.
2708217ec208SDavid C Somayajulu 	 */
2709217ec208SDavid C Somayajulu 	if (!p_queue->cids[qid_usage_idx].p_cid ||
2710217ec208SDavid C Somayajulu 	    p_queue->cids[qid_usage_idx].b_is_tx) {
2711217ec208SDavid C Somayajulu 		struct ecore_queue_cid *p_cid;
2712217ec208SDavid C Somayajulu 
2713217ec208SDavid C Somayajulu 		p_cid = ecore_iov_get_vf_rx_queue_cid(p_queue);
2714217ec208SDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
2715217ec208SDavid C Somayajulu 			   "VF[%d] - Tried Closing Rx 0x%04x.%02x, but Rx is at %04x.%02x\n",
2716217ec208SDavid C Somayajulu 			    vf->relative_vf_id, rxq_id, qid_usage_idx,
2717217ec208SDavid C Somayajulu 			    rxq_id, p_cid->qid_usage_idx);
2718217ec208SDavid C Somayajulu 		return ECORE_INVAL;
2719217ec208SDavid C Somayajulu 	}
2720217ec208SDavid C Somayajulu 
2721217ec208SDavid C Somayajulu 	/* Now that we know we have a valid Rx-queue - close it */
2722217ec208SDavid C Somayajulu 	rc = ecore_eth_rx_queue_stop(p_hwfn,
2723217ec208SDavid C Somayajulu 				     p_queue->cids[qid_usage_idx].p_cid,
2724217ec208SDavid C Somayajulu 				     false, cqe_completion);
2725217ec208SDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
2726217ec208SDavid C Somayajulu 		return rc;
2727217ec208SDavid C Somayajulu 
2728217ec208SDavid C Somayajulu 	p_queue->cids[qid_usage_idx].p_cid = OSAL_NULL;
2729217ec208SDavid C Somayajulu 	vf->num_active_rxqs--;
2730217ec208SDavid C Somayajulu 
2731217ec208SDavid C Somayajulu 	return ECORE_SUCCESS;
2732217ec208SDavid C Somayajulu }
2733217ec208SDavid C Somayajulu 
ecore_iov_vf_stop_txqs(struct ecore_hwfn * p_hwfn,struct ecore_vf_info * vf,u16 txq_id,u8 qid_usage_idx)2734217ec208SDavid C Somayajulu static enum _ecore_status_t ecore_iov_vf_stop_txqs(struct ecore_hwfn *p_hwfn,
2735217ec208SDavid C Somayajulu 						   struct ecore_vf_info *vf,
2736217ec208SDavid C Somayajulu 						   u16 txq_id,
2737217ec208SDavid C Somayajulu 						   u8 qid_usage_idx)
2738217ec208SDavid C Somayajulu {
2739217ec208SDavid C Somayajulu 	struct ecore_vf_queue *p_queue;
2740217ec208SDavid C Somayajulu 	enum _ecore_status_t rc = ECORE_SUCCESS;
2741217ec208SDavid C Somayajulu 
2742217ec208SDavid C Somayajulu 	if (!ecore_iov_validate_txq(p_hwfn, vf, txq_id,
2743217ec208SDavid C Somayajulu 				    ECORE_IOV_VALIDATE_Q_NA))
2744217ec208SDavid C Somayajulu 		return ECORE_INVAL;
2745217ec208SDavid C Somayajulu 
2746217ec208SDavid C Somayajulu 	p_queue = &vf->vf_queues[txq_id];
2747217ec208SDavid C Somayajulu 	if (!p_queue->cids[qid_usage_idx].p_cid ||
2748217ec208SDavid C Somayajulu 	    !p_queue->cids[qid_usage_idx].b_is_tx)
2749217ec208SDavid C Somayajulu 		return ECORE_INVAL;
2750217ec208SDavid C Somayajulu 
2751217ec208SDavid C Somayajulu 	rc = ecore_eth_tx_queue_stop(p_hwfn,
2752217ec208SDavid C Somayajulu 				     p_queue->cids[qid_usage_idx].p_cid);
2753217ec208SDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
2754217ec208SDavid C Somayajulu 		return rc;
2755217ec208SDavid C Somayajulu 
2756217ec208SDavid C Somayajulu 	p_queue->cids[qid_usage_idx].p_cid = OSAL_NULL;
2757217ec208SDavid C Somayajulu 	return ECORE_SUCCESS;
2758217ec208SDavid C Somayajulu }
2759217ec208SDavid C Somayajulu 
ecore_iov_vf_mbx_stop_rxqs(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * vf)2760217ec208SDavid C Somayajulu static void ecore_iov_vf_mbx_stop_rxqs(struct ecore_hwfn *p_hwfn,
2761217ec208SDavid C Somayajulu 				       struct ecore_ptt *p_ptt,
2762217ec208SDavid C Somayajulu 				       struct ecore_vf_info *vf)
2763217ec208SDavid C Somayajulu {
2764217ec208SDavid C Somayajulu 	u16 length = sizeof(struct pfvf_def_resp_tlv);
2765217ec208SDavid C Somayajulu 	struct ecore_iov_vf_mbx *mbx = &vf->vf_mbx;
2766217ec208SDavid C Somayajulu 	u8 status = PFVF_STATUS_FAILURE;
2767217ec208SDavid C Somayajulu 	struct vfpf_stop_rxqs_tlv *req;
2768217ec208SDavid C Somayajulu 	u8 qid_usage_idx;
2769217ec208SDavid C Somayajulu 	enum _ecore_status_t rc;
2770217ec208SDavid C Somayajulu 
2771217ec208SDavid C Somayajulu 	/* Starting with CHANNEL_TLV_QID, it's assumed the 'num_rxqs'
2772217ec208SDavid C Somayajulu 	 * would be one. Since no older ecore passed multiple queues
2773217ec208SDavid C Somayajulu 	 * using this API, sanitize on the value.
2774217ec208SDavid C Somayajulu 	 */
2775217ec208SDavid C Somayajulu 	req = &mbx->req_virt->stop_rxqs;
2776217ec208SDavid C Somayajulu 	if (req->num_rxqs != 1) {
2777217ec208SDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
2778217ec208SDavid C Somayajulu 			   "Odd; VF[%d] tried stopping multiple Rx queues\n",
2779217ec208SDavid C Somayajulu 			   vf->relative_vf_id);
2780217ec208SDavid C Somayajulu 		status = PFVF_STATUS_NOT_SUPPORTED;
2781217ec208SDavid C Somayajulu 		goto out;
2782217ec208SDavid C Somayajulu 	}
2783217ec208SDavid C Somayajulu 
2784217ec208SDavid C Somayajulu 	/* Find which qid-index is associated with the queue */
2785217ec208SDavid C Somayajulu 	qid_usage_idx = ecore_iov_vf_mbx_qid(p_hwfn, vf, false);
2786217ec208SDavid C Somayajulu 	if (qid_usage_idx == ECORE_IOV_QID_INVALID)
2787217ec208SDavid C Somayajulu 		goto out;
2788217ec208SDavid C Somayajulu 
2789217ec208SDavid C Somayajulu 	rc = ecore_iov_vf_stop_rxqs(p_hwfn, vf, req->rx_qid,
2790217ec208SDavid C Somayajulu 				    qid_usage_idx, req->cqe_completion);
2791217ec208SDavid C Somayajulu 	if (rc == ECORE_SUCCESS)
2792217ec208SDavid C Somayajulu 		status = PFVF_STATUS_SUCCESS;
2793217ec208SDavid C Somayajulu out:
2794217ec208SDavid C Somayajulu 	ecore_iov_prepare_resp(p_hwfn, p_ptt, vf, CHANNEL_TLV_STOP_RXQS,
2795217ec208SDavid C Somayajulu 			       length, status);
2796217ec208SDavid C Somayajulu }
2797217ec208SDavid C Somayajulu 
ecore_iov_vf_mbx_stop_txqs(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * vf)2798217ec208SDavid C Somayajulu static void ecore_iov_vf_mbx_stop_txqs(struct ecore_hwfn *p_hwfn,
2799217ec208SDavid C Somayajulu 				       struct ecore_ptt *p_ptt,
2800217ec208SDavid C Somayajulu 				       struct ecore_vf_info *vf)
2801217ec208SDavid C Somayajulu {
2802217ec208SDavid C Somayajulu 	u16 length = sizeof(struct pfvf_def_resp_tlv);
2803217ec208SDavid C Somayajulu 	struct ecore_iov_vf_mbx *mbx = &vf->vf_mbx;
2804217ec208SDavid C Somayajulu 	u8 status = PFVF_STATUS_FAILURE;
2805217ec208SDavid C Somayajulu 	struct vfpf_stop_txqs_tlv *req;
2806217ec208SDavid C Somayajulu 	u8 qid_usage_idx;
2807217ec208SDavid C Somayajulu 	enum _ecore_status_t rc;
2808217ec208SDavid C Somayajulu 
2809217ec208SDavid C Somayajulu 	/* Starting with CHANNEL_TLV_QID, it's assumed the 'num_txqs'
2810217ec208SDavid C Somayajulu 	 * would be one. Since no older ecore passed multiple queues
2811217ec208SDavid C Somayajulu 	 * using this API, sanitize on the value.
2812217ec208SDavid C Somayajulu 	 */
2813217ec208SDavid C Somayajulu 	req = &mbx->req_virt->stop_txqs;
2814217ec208SDavid C Somayajulu 	if (req->num_txqs != 1) {
2815217ec208SDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
2816217ec208SDavid C Somayajulu 			   "Odd; VF[%d] tried stopping multiple Tx queues\n",
2817217ec208SDavid C Somayajulu 			   vf->relative_vf_id);
2818217ec208SDavid C Somayajulu 		status = PFVF_STATUS_NOT_SUPPORTED;
2819217ec208SDavid C Somayajulu 		goto out;
2820217ec208SDavid C Somayajulu 	}
2821217ec208SDavid C Somayajulu 
2822217ec208SDavid C Somayajulu 	/* Find which qid-index is associated with the queue */
2823217ec208SDavid C Somayajulu 	qid_usage_idx = ecore_iov_vf_mbx_qid(p_hwfn, vf, true);
2824217ec208SDavid C Somayajulu 	if (qid_usage_idx == ECORE_IOV_QID_INVALID)
2825217ec208SDavid C Somayajulu 		goto out;
2826217ec208SDavid C Somayajulu 
2827217ec208SDavid C Somayajulu 	rc = ecore_iov_vf_stop_txqs(p_hwfn, vf, req->tx_qid,
2828217ec208SDavid C Somayajulu 				    qid_usage_idx);
2829217ec208SDavid C Somayajulu 	if (rc == ECORE_SUCCESS)
2830217ec208SDavid C Somayajulu 		status = PFVF_STATUS_SUCCESS;
2831217ec208SDavid C Somayajulu 
2832217ec208SDavid C Somayajulu out:
2833217ec208SDavid C Somayajulu 	ecore_iov_prepare_resp(p_hwfn, p_ptt, vf, CHANNEL_TLV_STOP_TXQS,
2834217ec208SDavid C Somayajulu 			       length, status);
2835217ec208SDavid C Somayajulu }
2836217ec208SDavid C Somayajulu 
ecore_iov_vf_mbx_update_rxqs(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * vf)2837217ec208SDavid C Somayajulu static void ecore_iov_vf_mbx_update_rxqs(struct ecore_hwfn *p_hwfn,
2838217ec208SDavid C Somayajulu 					 struct ecore_ptt *p_ptt,
2839217ec208SDavid C Somayajulu 					 struct ecore_vf_info *vf)
2840217ec208SDavid C Somayajulu {
2841217ec208SDavid C Somayajulu 	struct ecore_queue_cid *handlers[ECORE_MAX_VF_CHAINS_PER_PF];
2842217ec208SDavid C Somayajulu 	u16 length = sizeof(struct pfvf_def_resp_tlv);
2843217ec208SDavid C Somayajulu 	struct ecore_iov_vf_mbx *mbx = &vf->vf_mbx;
2844217ec208SDavid C Somayajulu 	struct vfpf_update_rxq_tlv *req;
2845217ec208SDavid C Somayajulu 	u8 status = PFVF_STATUS_FAILURE;
2846217ec208SDavid C Somayajulu 	u8 complete_event_flg;
2847217ec208SDavid C Somayajulu 	u8 complete_cqe_flg;
2848217ec208SDavid C Somayajulu 	u8 qid_usage_idx;
2849217ec208SDavid C Somayajulu 	enum _ecore_status_t rc;
2850217ec208SDavid C Somayajulu 	u16 i;
2851217ec208SDavid C Somayajulu 
2852217ec208SDavid C Somayajulu 	req = &mbx->req_virt->update_rxq;
2853217ec208SDavid C Somayajulu 	complete_cqe_flg = !!(req->flags & VFPF_RXQ_UPD_COMPLETE_CQE_FLAG);
2854217ec208SDavid C Somayajulu 	complete_event_flg = !!(req->flags & VFPF_RXQ_UPD_COMPLETE_EVENT_FLAG);
2855217ec208SDavid C Somayajulu 
2856217ec208SDavid C Somayajulu 	qid_usage_idx = ecore_iov_vf_mbx_qid(p_hwfn, vf, false);
2857217ec208SDavid C Somayajulu 	if (qid_usage_idx == ECORE_IOV_QID_INVALID)
2858217ec208SDavid C Somayajulu 		goto out;
2859217ec208SDavid C Somayajulu 
2860217ec208SDavid C Somayajulu 	/* Starting with the addition of CHANNEL_TLV_QID, this API started
2861217ec208SDavid C Somayajulu 	 * expecting a single queue at a time. Validate this.
2862217ec208SDavid C Somayajulu 	 */
2863217ec208SDavid C Somayajulu 	if ((vf->acquire.vfdev_info.capabilities &
2864217ec208SDavid C Somayajulu 	     VFPF_ACQUIRE_CAP_QUEUE_QIDS) &&
2865217ec208SDavid C Somayajulu 	     req->num_rxqs != 1) {
2866217ec208SDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
2867217ec208SDavid C Somayajulu 			   "VF[%d] supports QIDs but sends multiple queues\n",
2868217ec208SDavid C Somayajulu 			   vf->relative_vf_id);
2869217ec208SDavid C Somayajulu 		goto out;
2870217ec208SDavid C Somayajulu 	}
2871217ec208SDavid C Somayajulu 
2872217ec208SDavid C Somayajulu 	/* Validate inputs - for the legacy case this is still true since
2873217ec208SDavid C Somayajulu 	 * qid_usage_idx for each Rx queue would be LEGACY_QID_RX.
2874217ec208SDavid C Somayajulu 	 */
2875217ec208SDavid C Somayajulu 	for (i = req->rx_qid; i < req->rx_qid + req->num_rxqs; i++) {
2876217ec208SDavid C Somayajulu 		if (!ecore_iov_validate_rxq(p_hwfn, vf, i,
2877217ec208SDavid C Somayajulu 					    ECORE_IOV_VALIDATE_Q_NA) ||
2878217ec208SDavid C Somayajulu 		    !vf->vf_queues[i].cids[qid_usage_idx].p_cid ||
2879217ec208SDavid C Somayajulu 		    vf->vf_queues[i].cids[qid_usage_idx].b_is_tx) {
2880217ec208SDavid C Somayajulu 			DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
2881217ec208SDavid C Somayajulu 				   "VF[%d]: Incorrect Rxqs [%04x, %02x]\n",
2882217ec208SDavid C Somayajulu 				   vf->relative_vf_id, req->rx_qid,
2883217ec208SDavid C Somayajulu 				   req->num_rxqs);
2884217ec208SDavid C Somayajulu 			goto out;
2885217ec208SDavid C Somayajulu 		}
2886217ec208SDavid C Somayajulu 	}
2887217ec208SDavid C Somayajulu 
2888217ec208SDavid C Somayajulu 	for (i = 0; i < req->num_rxqs; i++) {
2889217ec208SDavid C Somayajulu 		u16 qid = req->rx_qid + i;
2890217ec208SDavid C Somayajulu 
2891217ec208SDavid C Somayajulu 		handlers[i] = vf->vf_queues[qid].cids[qid_usage_idx].p_cid;
2892217ec208SDavid C Somayajulu 	}
2893217ec208SDavid C Somayajulu 
2894217ec208SDavid C Somayajulu 	rc = ecore_sp_eth_rx_queues_update(p_hwfn, (void **)&handlers,
2895217ec208SDavid C Somayajulu 					   req->num_rxqs,
2896217ec208SDavid C Somayajulu 					   complete_cqe_flg,
2897217ec208SDavid C Somayajulu 					   complete_event_flg,
2898217ec208SDavid C Somayajulu 					   ECORE_SPQ_MODE_EBLOCK,
2899217ec208SDavid C Somayajulu 					   OSAL_NULL);
2900217ec208SDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
2901217ec208SDavid C Somayajulu 		goto out;
2902217ec208SDavid C Somayajulu 
2903217ec208SDavid C Somayajulu 	status = PFVF_STATUS_SUCCESS;
2904217ec208SDavid C Somayajulu out:
2905217ec208SDavid C Somayajulu 	ecore_iov_prepare_resp(p_hwfn, p_ptt, vf, CHANNEL_TLV_UPDATE_RXQ,
2906217ec208SDavid C Somayajulu 			       length, status);
2907217ec208SDavid C Somayajulu }
2908217ec208SDavid C Somayajulu 
ecore_iov_search_list_tlvs(struct ecore_hwfn * p_hwfn,void * p_tlvs_list,u16 req_type)2909217ec208SDavid C Somayajulu void *ecore_iov_search_list_tlvs(struct ecore_hwfn *p_hwfn,
2910217ec208SDavid C Somayajulu 					void *p_tlvs_list, u16 req_type)
2911217ec208SDavid C Somayajulu {
2912217ec208SDavid C Somayajulu 	struct channel_tlv *p_tlv = (struct channel_tlv *)p_tlvs_list;
2913217ec208SDavid C Somayajulu 	int len = 0;
2914217ec208SDavid C Somayajulu 
2915217ec208SDavid C Somayajulu 	do {
2916217ec208SDavid C Somayajulu 		if (!p_tlv->length) {
2917217ec208SDavid C Somayajulu 			DP_NOTICE(p_hwfn, true,
2918217ec208SDavid C Somayajulu 				  "Zero length TLV found\n");
2919217ec208SDavid C Somayajulu 			return OSAL_NULL;
2920217ec208SDavid C Somayajulu 		}
2921217ec208SDavid C Somayajulu 
2922217ec208SDavid C Somayajulu 		if (p_tlv->type == req_type) {
2923217ec208SDavid C Somayajulu 			DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
2924217ec208SDavid C Somayajulu 				   "Extended tlv type %s, length %d found\n",
2925217ec208SDavid C Somayajulu 				   ecore_channel_tlvs_string[p_tlv->type],
2926217ec208SDavid C Somayajulu 				   p_tlv->length);
2927217ec208SDavid C Somayajulu 			return p_tlv;
2928217ec208SDavid C Somayajulu 		}
2929217ec208SDavid C Somayajulu 
2930217ec208SDavid C Somayajulu 		len += p_tlv->length;
2931217ec208SDavid C Somayajulu 		p_tlv = (struct channel_tlv *)((u8 *)p_tlv + p_tlv->length);
2932217ec208SDavid C Somayajulu 
2933217ec208SDavid C Somayajulu 		if ((len + p_tlv->length) > TLV_BUFFER_SIZE) {
2934217ec208SDavid C Somayajulu 			DP_NOTICE(p_hwfn, true,
2935217ec208SDavid C Somayajulu 				  "TLVs has overrun the buffer size\n");
2936217ec208SDavid C Somayajulu 			return OSAL_NULL;
2937217ec208SDavid C Somayajulu 		}
2938217ec208SDavid C Somayajulu 	} while (p_tlv->type != CHANNEL_TLV_LIST_END);
2939217ec208SDavid C Somayajulu 
2940217ec208SDavid C Somayajulu 	return OSAL_NULL;
2941217ec208SDavid C Somayajulu }
2942217ec208SDavid C Somayajulu 
2943217ec208SDavid C Somayajulu static void
ecore_iov_vp_update_act_param(struct ecore_hwfn * p_hwfn,struct ecore_sp_vport_update_params * p_data,struct ecore_iov_vf_mbx * p_mbx,u16 * tlvs_mask)2944217ec208SDavid C Somayajulu ecore_iov_vp_update_act_param(struct ecore_hwfn *p_hwfn,
2945217ec208SDavid C Somayajulu 			      struct ecore_sp_vport_update_params *p_data,
2946217ec208SDavid C Somayajulu 			      struct ecore_iov_vf_mbx *p_mbx, u16 *tlvs_mask)
2947217ec208SDavid C Somayajulu {
2948217ec208SDavid C Somayajulu 	struct vfpf_vport_update_activate_tlv *p_act_tlv;
2949217ec208SDavid C Somayajulu 	u16 tlv = CHANNEL_TLV_VPORT_UPDATE_ACTIVATE;
2950217ec208SDavid C Somayajulu 
2951217ec208SDavid C Somayajulu 	p_act_tlv = (struct vfpf_vport_update_activate_tlv *)
2952217ec208SDavid C Somayajulu 		    ecore_iov_search_list_tlvs(p_hwfn, p_mbx->req_virt,
2953217ec208SDavid C Somayajulu 					       tlv);
2954217ec208SDavid C Somayajulu 	if (!p_act_tlv)
2955217ec208SDavid C Somayajulu 		return;
2956217ec208SDavid C Somayajulu 
2957217ec208SDavid C Somayajulu 	p_data->update_vport_active_rx_flg = p_act_tlv->update_rx;
2958217ec208SDavid C Somayajulu 	p_data->vport_active_rx_flg = p_act_tlv->active_rx;
2959217ec208SDavid C Somayajulu 	p_data->update_vport_active_tx_flg = p_act_tlv->update_tx;
2960217ec208SDavid C Somayajulu 	p_data->vport_active_tx_flg = p_act_tlv->active_tx;
2961217ec208SDavid C Somayajulu 	*tlvs_mask |= 1 << ECORE_IOV_VP_UPDATE_ACTIVATE;
2962217ec208SDavid C Somayajulu }
2963217ec208SDavid C Somayajulu 
2964217ec208SDavid C Somayajulu static void
ecore_iov_vp_update_vlan_param(struct ecore_hwfn * p_hwfn,struct ecore_sp_vport_update_params * p_data,struct ecore_vf_info * p_vf,struct ecore_iov_vf_mbx * p_mbx,u16 * tlvs_mask)2965217ec208SDavid C Somayajulu ecore_iov_vp_update_vlan_param(struct ecore_hwfn *p_hwfn,
2966217ec208SDavid C Somayajulu 			       struct ecore_sp_vport_update_params *p_data,
2967217ec208SDavid C Somayajulu 			       struct ecore_vf_info *p_vf,
2968217ec208SDavid C Somayajulu 			       struct ecore_iov_vf_mbx *p_mbx, u16 *tlvs_mask)
2969217ec208SDavid C Somayajulu {
2970217ec208SDavid C Somayajulu 	struct vfpf_vport_update_vlan_strip_tlv *p_vlan_tlv;
2971217ec208SDavid C Somayajulu 	u16 tlv = CHANNEL_TLV_VPORT_UPDATE_VLAN_STRIP;
2972217ec208SDavid C Somayajulu 
2973217ec208SDavid C Somayajulu 	p_vlan_tlv = (struct vfpf_vport_update_vlan_strip_tlv *)
2974217ec208SDavid C Somayajulu 		     ecore_iov_search_list_tlvs(p_hwfn, p_mbx->req_virt,
2975217ec208SDavid C Somayajulu 						tlv);
2976217ec208SDavid C Somayajulu 	if (!p_vlan_tlv)
2977217ec208SDavid C Somayajulu 		return;
2978217ec208SDavid C Somayajulu 
2979217ec208SDavid C Somayajulu 	p_vf->shadow_config.inner_vlan_removal = p_vlan_tlv->remove_vlan;
2980217ec208SDavid C Somayajulu 
2981217ec208SDavid C Somayajulu 	/* Ignore the VF request if we're forcing a vlan */
2982217ec208SDavid C Somayajulu 	if (!(p_vf->configured_features & (1 << VLAN_ADDR_FORCED))) {
2983217ec208SDavid C Somayajulu 		p_data->update_inner_vlan_removal_flg = 1;
2984217ec208SDavid C Somayajulu 		p_data->inner_vlan_removal_flg = p_vlan_tlv->remove_vlan;
2985217ec208SDavid C Somayajulu 	}
2986217ec208SDavid C Somayajulu 
2987217ec208SDavid C Somayajulu 	*tlvs_mask |= 1 << ECORE_IOV_VP_UPDATE_VLAN_STRIP;
2988217ec208SDavid C Somayajulu }
2989217ec208SDavid C Somayajulu 
2990217ec208SDavid C Somayajulu static void
ecore_iov_vp_update_tx_switch(struct ecore_hwfn * p_hwfn,struct ecore_sp_vport_update_params * p_data,struct ecore_iov_vf_mbx * p_mbx,u16 * tlvs_mask)2991217ec208SDavid C Somayajulu ecore_iov_vp_update_tx_switch(struct ecore_hwfn *p_hwfn,
2992217ec208SDavid C Somayajulu 			      struct ecore_sp_vport_update_params *p_data,
2993217ec208SDavid C Somayajulu 			      struct ecore_iov_vf_mbx *p_mbx, u16 *tlvs_mask)
2994217ec208SDavid C Somayajulu {
2995217ec208SDavid C Somayajulu 	struct vfpf_vport_update_tx_switch_tlv *p_tx_switch_tlv;
2996217ec208SDavid C Somayajulu 	u16 tlv = CHANNEL_TLV_VPORT_UPDATE_TX_SWITCH;
2997217ec208SDavid C Somayajulu 
2998217ec208SDavid C Somayajulu 	p_tx_switch_tlv = (struct vfpf_vport_update_tx_switch_tlv *)
2999217ec208SDavid C Somayajulu 			  ecore_iov_search_list_tlvs(p_hwfn, p_mbx->req_virt,
3000217ec208SDavid C Somayajulu 						     tlv);
3001217ec208SDavid C Somayajulu 	if (!p_tx_switch_tlv)
3002217ec208SDavid C Somayajulu 		return;
3003217ec208SDavid C Somayajulu 
3004217ec208SDavid C Somayajulu #ifndef ASIC_ONLY
3005217ec208SDavid C Somayajulu 	if (CHIP_REV_IS_FPGA(p_hwfn->p_dev)) {
3006217ec208SDavid C Somayajulu 		DP_NOTICE(p_hwfn, false, "FPGA: Ignore tx-switching configuration originating from VFs\n");
3007217ec208SDavid C Somayajulu 		return;
3008217ec208SDavid C Somayajulu 	}
3009217ec208SDavid C Somayajulu #endif
3010217ec208SDavid C Somayajulu 
3011217ec208SDavid C Somayajulu 	p_data->update_tx_switching_flg = 1;
3012217ec208SDavid C Somayajulu 	p_data->tx_switching_flg = p_tx_switch_tlv->tx_switching;
3013217ec208SDavid C Somayajulu 	*tlvs_mask |= 1 << ECORE_IOV_VP_UPDATE_TX_SWITCH;
3014217ec208SDavid C Somayajulu }
3015217ec208SDavid C Somayajulu 
3016217ec208SDavid C Somayajulu static void
ecore_iov_vp_update_mcast_bin_param(struct ecore_hwfn * p_hwfn,struct ecore_sp_vport_update_params * p_data,struct ecore_iov_vf_mbx * p_mbx,u16 * tlvs_mask)3017217ec208SDavid C Somayajulu ecore_iov_vp_update_mcast_bin_param(struct ecore_hwfn *p_hwfn,
3018217ec208SDavid C Somayajulu 				    struct ecore_sp_vport_update_params *p_data,
3019217ec208SDavid C Somayajulu 				    struct ecore_iov_vf_mbx *p_mbx,
3020217ec208SDavid C Somayajulu 				    u16 *tlvs_mask)
3021217ec208SDavid C Somayajulu {
3022217ec208SDavid C Somayajulu 	struct vfpf_vport_update_mcast_bin_tlv *p_mcast_tlv;
3023217ec208SDavid C Somayajulu 	u16 tlv = CHANNEL_TLV_VPORT_UPDATE_MCAST;
3024217ec208SDavid C Somayajulu 
3025217ec208SDavid C Somayajulu 	p_mcast_tlv = (struct vfpf_vport_update_mcast_bin_tlv *)
3026217ec208SDavid C Somayajulu 		      ecore_iov_search_list_tlvs(p_hwfn, p_mbx->req_virt,
3027217ec208SDavid C Somayajulu 						 tlv);
3028217ec208SDavid C Somayajulu 	if (!p_mcast_tlv)
3029217ec208SDavid C Somayajulu 		return;
3030217ec208SDavid C Somayajulu 
3031217ec208SDavid C Somayajulu 	p_data->update_approx_mcast_flg = 1;
3032217ec208SDavid C Somayajulu 	OSAL_MEMCPY(p_data->bins, p_mcast_tlv->bins,
3033217ec208SDavid C Somayajulu 		    sizeof(u32) * ETH_MULTICAST_MAC_BINS_IN_REGS);
3034217ec208SDavid C Somayajulu 	*tlvs_mask |= 1 << ECORE_IOV_VP_UPDATE_MCAST;
3035217ec208SDavid C Somayajulu }
3036217ec208SDavid C Somayajulu 
3037217ec208SDavid C Somayajulu static void
ecore_iov_vp_update_accept_flag(struct ecore_hwfn * p_hwfn,struct ecore_sp_vport_update_params * p_data,struct ecore_iov_vf_mbx * p_mbx,u16 * tlvs_mask)3038217ec208SDavid C Somayajulu ecore_iov_vp_update_accept_flag(struct ecore_hwfn *p_hwfn,
3039217ec208SDavid C Somayajulu 				struct ecore_sp_vport_update_params *p_data,
3040217ec208SDavid C Somayajulu 				struct ecore_iov_vf_mbx *p_mbx, u16 *tlvs_mask)
3041217ec208SDavid C Somayajulu {
3042217ec208SDavid C Somayajulu 	struct ecore_filter_accept_flags *p_flags = &p_data->accept_flags;
3043217ec208SDavid C Somayajulu 	struct vfpf_vport_update_accept_param_tlv *p_accept_tlv;
3044217ec208SDavid C Somayajulu 	u16 tlv = CHANNEL_TLV_VPORT_UPDATE_ACCEPT_PARAM;
3045217ec208SDavid C Somayajulu 
3046217ec208SDavid C Somayajulu 	p_accept_tlv = (struct vfpf_vport_update_accept_param_tlv *)
3047217ec208SDavid C Somayajulu 		       ecore_iov_search_list_tlvs(p_hwfn, p_mbx->req_virt,
3048217ec208SDavid C Somayajulu 						  tlv);
3049217ec208SDavid C Somayajulu 	if (!p_accept_tlv)
3050217ec208SDavid C Somayajulu 		return;
3051217ec208SDavid C Somayajulu 
3052217ec208SDavid C Somayajulu 	p_flags->update_rx_mode_config = p_accept_tlv->update_rx_mode;
3053217ec208SDavid C Somayajulu 	p_flags->rx_accept_filter = p_accept_tlv->rx_accept_filter;
3054217ec208SDavid C Somayajulu 	p_flags->update_tx_mode_config = p_accept_tlv->update_tx_mode;
3055217ec208SDavid C Somayajulu 	p_flags->tx_accept_filter = p_accept_tlv->tx_accept_filter;
3056217ec208SDavid C Somayajulu 	*tlvs_mask |= 1 << ECORE_IOV_VP_UPDATE_ACCEPT_PARAM;
3057217ec208SDavid C Somayajulu }
3058217ec208SDavid C Somayajulu 
3059217ec208SDavid C Somayajulu static void
ecore_iov_vp_update_accept_any_vlan(struct ecore_hwfn * p_hwfn,struct ecore_sp_vport_update_params * p_data,struct ecore_iov_vf_mbx * p_mbx,u16 * tlvs_mask)3060217ec208SDavid C Somayajulu ecore_iov_vp_update_accept_any_vlan(struct ecore_hwfn *p_hwfn,
3061217ec208SDavid C Somayajulu 				    struct ecore_sp_vport_update_params *p_data,
3062217ec208SDavid C Somayajulu 				    struct ecore_iov_vf_mbx *p_mbx,
3063217ec208SDavid C Somayajulu 				    u16 *tlvs_mask)
3064217ec208SDavid C Somayajulu {
3065217ec208SDavid C Somayajulu 	struct vfpf_vport_update_accept_any_vlan_tlv *p_accept_any_vlan;
3066217ec208SDavid C Somayajulu 	u16 tlv = CHANNEL_TLV_VPORT_UPDATE_ACCEPT_ANY_VLAN;
3067217ec208SDavid C Somayajulu 
3068217ec208SDavid C Somayajulu 	p_accept_any_vlan = (struct vfpf_vport_update_accept_any_vlan_tlv *)
3069217ec208SDavid C Somayajulu 			    ecore_iov_search_list_tlvs(p_hwfn, p_mbx->req_virt,
3070217ec208SDavid C Somayajulu 						       tlv);
3071217ec208SDavid C Somayajulu 	if (!p_accept_any_vlan)
3072217ec208SDavid C Somayajulu 		return;
3073217ec208SDavid C Somayajulu 
3074217ec208SDavid C Somayajulu 	p_data->accept_any_vlan = p_accept_any_vlan->accept_any_vlan;
3075217ec208SDavid C Somayajulu 	p_data->update_accept_any_vlan_flg =
3076217ec208SDavid C Somayajulu 			p_accept_any_vlan->update_accept_any_vlan_flg;
3077217ec208SDavid C Somayajulu 	*tlvs_mask |= 1 << ECORE_IOV_VP_UPDATE_ACCEPT_ANY_VLAN;
3078217ec208SDavid C Somayajulu }
3079217ec208SDavid C Somayajulu 
3080217ec208SDavid C Somayajulu static void
ecore_iov_vp_update_rss_param(struct ecore_hwfn * p_hwfn,struct ecore_vf_info * vf,struct ecore_sp_vport_update_params * p_data,struct ecore_rss_params * p_rss,struct ecore_iov_vf_mbx * p_mbx,u16 * tlvs_mask,u16 * tlvs_accepted)3081217ec208SDavid C Somayajulu ecore_iov_vp_update_rss_param(struct ecore_hwfn *p_hwfn,
3082217ec208SDavid C Somayajulu 			      struct ecore_vf_info *vf,
3083217ec208SDavid C Somayajulu 			      struct ecore_sp_vport_update_params *p_data,
3084217ec208SDavid C Somayajulu 			      struct ecore_rss_params *p_rss,
3085217ec208SDavid C Somayajulu 			      struct ecore_iov_vf_mbx *p_mbx,
3086217ec208SDavid C Somayajulu 			      u16 *tlvs_mask, u16 *tlvs_accepted)
3087217ec208SDavid C Somayajulu {
3088217ec208SDavid C Somayajulu 	struct vfpf_vport_update_rss_tlv *p_rss_tlv;
3089217ec208SDavid C Somayajulu 	u16 tlv = CHANNEL_TLV_VPORT_UPDATE_RSS;
3090217ec208SDavid C Somayajulu 	bool b_reject = false;
3091217ec208SDavid C Somayajulu 	u16 table_size;
3092217ec208SDavid C Somayajulu 	u16 i, q_idx;
3093217ec208SDavid C Somayajulu 
3094217ec208SDavid C Somayajulu 	p_rss_tlv = (struct vfpf_vport_update_rss_tlv *)
3095217ec208SDavid C Somayajulu 		    ecore_iov_search_list_tlvs(p_hwfn, p_mbx->req_virt,
3096217ec208SDavid C Somayajulu 					       tlv);
3097217ec208SDavid C Somayajulu 	if (!p_rss_tlv) {
3098217ec208SDavid C Somayajulu 		p_data->rss_params = OSAL_NULL;
3099217ec208SDavid C Somayajulu 		return;
3100217ec208SDavid C Somayajulu 	}
3101217ec208SDavid C Somayajulu 
3102217ec208SDavid C Somayajulu 	OSAL_MEMSET(p_rss, 0, sizeof(struct ecore_rss_params));
3103217ec208SDavid C Somayajulu 
3104217ec208SDavid C Somayajulu 	p_rss->update_rss_config = !!(p_rss_tlv->update_rss_flags &
3105217ec208SDavid C Somayajulu 				      VFPF_UPDATE_RSS_CONFIG_FLAG);
3106217ec208SDavid C Somayajulu 	p_rss->update_rss_capabilities = !!(p_rss_tlv->update_rss_flags &
3107217ec208SDavid C Somayajulu 					    VFPF_UPDATE_RSS_CAPS_FLAG);
3108217ec208SDavid C Somayajulu 	p_rss->update_rss_ind_table = !!(p_rss_tlv->update_rss_flags &
3109217ec208SDavid C Somayajulu 					 VFPF_UPDATE_RSS_IND_TABLE_FLAG);
3110217ec208SDavid C Somayajulu 	p_rss->update_rss_key = !!(p_rss_tlv->update_rss_flags &
3111217ec208SDavid C Somayajulu 				   VFPF_UPDATE_RSS_KEY_FLAG);
3112217ec208SDavid C Somayajulu 
3113217ec208SDavid C Somayajulu 	p_rss->rss_enable = p_rss_tlv->rss_enable;
3114217ec208SDavid C Somayajulu 	p_rss->rss_eng_id = vf->rss_eng_id;
3115217ec208SDavid C Somayajulu 	p_rss->rss_caps = p_rss_tlv->rss_caps;
3116217ec208SDavid C Somayajulu 	p_rss->rss_table_size_log = p_rss_tlv->rss_table_size_log;
3117217ec208SDavid C Somayajulu 	OSAL_MEMCPY(p_rss->rss_key, p_rss_tlv->rss_key,
3118217ec208SDavid C Somayajulu 		    sizeof(p_rss->rss_key));
3119217ec208SDavid C Somayajulu 
3120217ec208SDavid C Somayajulu 	table_size = OSAL_MIN_T(u16, OSAL_ARRAY_SIZE(p_rss->rss_ind_table),
3121217ec208SDavid C Somayajulu 				(1 << p_rss_tlv->rss_table_size_log));
3122217ec208SDavid C Somayajulu 
3123217ec208SDavid C Somayajulu 	for (i = 0; i < table_size; i++) {
3124217ec208SDavid C Somayajulu 		struct ecore_queue_cid *p_cid;
3125217ec208SDavid C Somayajulu 
3126217ec208SDavid C Somayajulu 		q_idx = p_rss_tlv->rss_ind_table[i];
3127217ec208SDavid C Somayajulu 		if (!ecore_iov_validate_rxq(p_hwfn, vf, q_idx,
3128217ec208SDavid C Somayajulu 					    ECORE_IOV_VALIDATE_Q_ENABLE)) {
3129217ec208SDavid C Somayajulu 			DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
3130217ec208SDavid C Somayajulu 				   "VF[%d]: Omitting RSS due to wrong queue %04x\n",
3131217ec208SDavid C Somayajulu 				   vf->relative_vf_id, q_idx);
3132217ec208SDavid C Somayajulu 			b_reject = true;
3133217ec208SDavid C Somayajulu 			goto out;
3134217ec208SDavid C Somayajulu 		}
3135217ec208SDavid C Somayajulu 
3136217ec208SDavid C Somayajulu 		p_cid = ecore_iov_get_vf_rx_queue_cid(&vf->vf_queues[q_idx]);
3137217ec208SDavid C Somayajulu 		p_rss->rss_ind_table[i] = p_cid;
3138217ec208SDavid C Somayajulu 	}
3139217ec208SDavid C Somayajulu 
3140217ec208SDavid C Somayajulu 	p_data->rss_params = p_rss;
3141217ec208SDavid C Somayajulu out:
3142217ec208SDavid C Somayajulu 	*tlvs_mask |= 1 << ECORE_IOV_VP_UPDATE_RSS;
3143217ec208SDavid C Somayajulu 	if (!b_reject)
3144217ec208SDavid C Somayajulu 		*tlvs_accepted |= 1 << ECORE_IOV_VP_UPDATE_RSS;
3145217ec208SDavid C Somayajulu }
3146217ec208SDavid C Somayajulu 
3147217ec208SDavid C Somayajulu static void
ecore_iov_vp_update_sge_tpa_param(struct ecore_hwfn * p_hwfn,struct ecore_sp_vport_update_params * p_data,struct ecore_sge_tpa_params * p_sge_tpa,struct ecore_iov_vf_mbx * p_mbx,u16 * tlvs_mask)3148217ec208SDavid C Somayajulu ecore_iov_vp_update_sge_tpa_param(struct ecore_hwfn *p_hwfn,
3149217ec208SDavid C Somayajulu 				  struct ecore_sp_vport_update_params *p_data,
3150217ec208SDavid C Somayajulu 				  struct ecore_sge_tpa_params *p_sge_tpa,
3151217ec208SDavid C Somayajulu 				  struct ecore_iov_vf_mbx *p_mbx,
3152217ec208SDavid C Somayajulu 				  u16 *tlvs_mask)
3153217ec208SDavid C Somayajulu {
3154217ec208SDavid C Somayajulu 	struct vfpf_vport_update_sge_tpa_tlv *p_sge_tpa_tlv;
3155217ec208SDavid C Somayajulu 	u16 tlv = CHANNEL_TLV_VPORT_UPDATE_SGE_TPA;
3156217ec208SDavid C Somayajulu 
3157217ec208SDavid C Somayajulu 	p_sge_tpa_tlv = (struct vfpf_vport_update_sge_tpa_tlv *)
3158217ec208SDavid C Somayajulu 			ecore_iov_search_list_tlvs(p_hwfn,
3159217ec208SDavid C Somayajulu 						   p_mbx->req_virt, tlv);
3160217ec208SDavid C Somayajulu 
3161217ec208SDavid C Somayajulu 	if (!p_sge_tpa_tlv) {
3162217ec208SDavid C Somayajulu 		p_data->sge_tpa_params = OSAL_NULL;
3163217ec208SDavid C Somayajulu 		return;
3164217ec208SDavid C Somayajulu 	}
3165217ec208SDavid C Somayajulu 
3166217ec208SDavid C Somayajulu 	OSAL_MEMSET(p_sge_tpa, 0, sizeof(struct ecore_sge_tpa_params));
3167217ec208SDavid C Somayajulu 
3168217ec208SDavid C Somayajulu 	p_sge_tpa->update_tpa_en_flg =
3169217ec208SDavid C Somayajulu 		!!(p_sge_tpa_tlv->update_sge_tpa_flags &
3170217ec208SDavid C Somayajulu 		   VFPF_UPDATE_TPA_EN_FLAG);
3171217ec208SDavid C Somayajulu 	p_sge_tpa->update_tpa_param_flg =
3172217ec208SDavid C Somayajulu 		!!(p_sge_tpa_tlv->update_sge_tpa_flags &
3173217ec208SDavid C Somayajulu 		   VFPF_UPDATE_TPA_PARAM_FLAG);
3174217ec208SDavid C Somayajulu 
3175217ec208SDavid C Somayajulu 	p_sge_tpa->tpa_ipv4_en_flg =
3176217ec208SDavid C Somayajulu 		!!(p_sge_tpa_tlv->sge_tpa_flags &
3177217ec208SDavid C Somayajulu 		   VFPF_TPA_IPV4_EN_FLAG);
3178217ec208SDavid C Somayajulu 	p_sge_tpa->tpa_ipv6_en_flg =
3179217ec208SDavid C Somayajulu 		!!(p_sge_tpa_tlv->sge_tpa_flags &
3180217ec208SDavid C Somayajulu 		   VFPF_TPA_IPV6_EN_FLAG);
3181217ec208SDavid C Somayajulu 	p_sge_tpa->tpa_pkt_split_flg =
3182217ec208SDavid C Somayajulu 		!!(p_sge_tpa_tlv->sge_tpa_flags &
3183217ec208SDavid C Somayajulu 		   VFPF_TPA_PKT_SPLIT_FLAG);
3184217ec208SDavid C Somayajulu 	p_sge_tpa->tpa_hdr_data_split_flg =
3185217ec208SDavid C Somayajulu 		!!(p_sge_tpa_tlv->sge_tpa_flags &
3186217ec208SDavid C Somayajulu 		   VFPF_TPA_HDR_DATA_SPLIT_FLAG);
3187217ec208SDavid C Somayajulu 	p_sge_tpa->tpa_gro_consistent_flg =
3188217ec208SDavid C Somayajulu 		!!(p_sge_tpa_tlv->sge_tpa_flags &
3189217ec208SDavid C Somayajulu 		   VFPF_TPA_GRO_CONSIST_FLAG);
3190217ec208SDavid C Somayajulu 
3191217ec208SDavid C Somayajulu 	p_sge_tpa->tpa_max_aggs_num = p_sge_tpa_tlv->tpa_max_aggs_num;
3192217ec208SDavid C Somayajulu 	p_sge_tpa->tpa_max_size = p_sge_tpa_tlv->tpa_max_size;
3193217ec208SDavid C Somayajulu 	p_sge_tpa->tpa_min_size_to_start =
3194217ec208SDavid C Somayajulu 		p_sge_tpa_tlv->tpa_min_size_to_start;
3195217ec208SDavid C Somayajulu 	p_sge_tpa->tpa_min_size_to_cont =
3196217ec208SDavid C Somayajulu 		p_sge_tpa_tlv->tpa_min_size_to_cont;
3197217ec208SDavid C Somayajulu 	p_sge_tpa->max_buffers_per_cqe =
3198217ec208SDavid C Somayajulu 		p_sge_tpa_tlv->max_buffers_per_cqe;
3199217ec208SDavid C Somayajulu 
3200217ec208SDavid C Somayajulu 	p_data->sge_tpa_params = p_sge_tpa;
3201217ec208SDavid C Somayajulu 
3202217ec208SDavid C Somayajulu 	*tlvs_mask |= 1 << ECORE_IOV_VP_UPDATE_SGE_TPA;
3203217ec208SDavid C Somayajulu }
3204217ec208SDavid C Somayajulu 
ecore_iov_vf_mbx_vport_update(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * vf)3205217ec208SDavid C Somayajulu static void ecore_iov_vf_mbx_vport_update(struct ecore_hwfn *p_hwfn,
3206217ec208SDavid C Somayajulu 					  struct ecore_ptt *p_ptt,
3207217ec208SDavid C Somayajulu 					  struct ecore_vf_info *vf)
3208217ec208SDavid C Somayajulu {
3209217ec208SDavid C Somayajulu 	struct ecore_rss_params *p_rss_params = OSAL_NULL;
3210217ec208SDavid C Somayajulu 	struct ecore_sp_vport_update_params params;
3211217ec208SDavid C Somayajulu 	struct ecore_iov_vf_mbx *mbx = &vf->vf_mbx;
3212217ec208SDavid C Somayajulu 	struct ecore_sge_tpa_params sge_tpa_params;
3213217ec208SDavid C Somayajulu 	u16 tlvs_mask = 0, tlvs_accepted = 0;
3214217ec208SDavid C Somayajulu 	u8 status = PFVF_STATUS_SUCCESS;
3215217ec208SDavid C Somayajulu 	u16 length;
3216217ec208SDavid C Somayajulu 	enum _ecore_status_t rc;
3217217ec208SDavid C Somayajulu 
3218217ec208SDavid C Somayajulu 	/* Valiate PF can send such a request */
3219217ec208SDavid C Somayajulu 	if (!vf->vport_instance) {
3220217ec208SDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
3221217ec208SDavid C Somayajulu 			   "No VPORT instance available for VF[%d], failing vport update\n",
3222217ec208SDavid C Somayajulu 			   vf->abs_vf_id);
3223217ec208SDavid C Somayajulu 		status = PFVF_STATUS_FAILURE;
3224217ec208SDavid C Somayajulu 		goto out;
3225217ec208SDavid C Somayajulu 	}
3226217ec208SDavid C Somayajulu 
3227217ec208SDavid C Somayajulu 	p_rss_params = OSAL_VZALLOC(p_hwfn->p_dev, sizeof(*p_rss_params));
3228217ec208SDavid C Somayajulu 	if (p_rss_params == OSAL_NULL) {
3229217ec208SDavid C Somayajulu 		status = PFVF_STATUS_FAILURE;
3230217ec208SDavid C Somayajulu 		goto out;
3231217ec208SDavid C Somayajulu 	}
3232217ec208SDavid C Somayajulu 
3233217ec208SDavid C Somayajulu 	OSAL_MEMSET(&params, 0, sizeof(params));
3234217ec208SDavid C Somayajulu 	params.opaque_fid =  vf->opaque_fid;
3235217ec208SDavid C Somayajulu 	params.vport_id = vf->vport_id;
3236217ec208SDavid C Somayajulu 	params.rss_params = OSAL_NULL;
3237217ec208SDavid C Somayajulu 
3238217ec208SDavid C Somayajulu 	/* Search for extended tlvs list and update values
3239217ec208SDavid C Somayajulu 	 * from VF in struct ecore_sp_vport_update_params.
3240217ec208SDavid C Somayajulu 	 */
3241217ec208SDavid C Somayajulu 	ecore_iov_vp_update_act_param(p_hwfn, &params, mbx, &tlvs_mask);
3242217ec208SDavid C Somayajulu 	ecore_iov_vp_update_vlan_param(p_hwfn, &params, vf, mbx, &tlvs_mask);
3243217ec208SDavid C Somayajulu 	ecore_iov_vp_update_tx_switch(p_hwfn, &params, mbx, &tlvs_mask);
3244217ec208SDavid C Somayajulu 	ecore_iov_vp_update_mcast_bin_param(p_hwfn, &params, mbx, &tlvs_mask);
3245217ec208SDavid C Somayajulu 	ecore_iov_vp_update_accept_flag(p_hwfn, &params, mbx, &tlvs_mask);
3246217ec208SDavid C Somayajulu 	ecore_iov_vp_update_accept_any_vlan(p_hwfn, &params, mbx, &tlvs_mask);
3247217ec208SDavid C Somayajulu 	ecore_iov_vp_update_sge_tpa_param(p_hwfn, &params,
3248217ec208SDavid C Somayajulu 					  &sge_tpa_params, mbx, &tlvs_mask);
3249217ec208SDavid C Somayajulu 
3250217ec208SDavid C Somayajulu 	tlvs_accepted = tlvs_mask;
3251217ec208SDavid C Somayajulu 
3252217ec208SDavid C Somayajulu 	/* Some of the extended TLVs need to be validated first; In that case,
3253217ec208SDavid C Somayajulu 	 * they can update the mask without updating the accepted [so that
3254217ec208SDavid C Somayajulu 	 * PF could communicate to VF it has rejected request].
3255217ec208SDavid C Somayajulu 	 */
3256217ec208SDavid C Somayajulu 	ecore_iov_vp_update_rss_param(p_hwfn, vf, &params, p_rss_params,
3257217ec208SDavid C Somayajulu 				      mbx, &tlvs_mask, &tlvs_accepted);
3258217ec208SDavid C Somayajulu 
3259217ec208SDavid C Somayajulu 	/* Just log a message if there is no single extended tlv in buffer.
3260217ec208SDavid C Somayajulu 	 * When all features of vport update ramrod would be requested by VF
3261217ec208SDavid C Somayajulu 	 * as extended TLVs in buffer then an error can be returned in response
3262217ec208SDavid C Somayajulu 	 * if there is no extended TLV present in buffer.
3263217ec208SDavid C Somayajulu 	 */
3264217ec208SDavid C Somayajulu 	if (OSAL_IOV_VF_VPORT_UPDATE(p_hwfn, vf->relative_vf_id,
3265217ec208SDavid C Somayajulu 				     &params, &tlvs_accepted) !=
3266217ec208SDavid C Somayajulu 	    ECORE_SUCCESS) {
3267217ec208SDavid C Somayajulu 		tlvs_accepted = 0;
3268217ec208SDavid C Somayajulu 		status = PFVF_STATUS_NOT_SUPPORTED;
3269217ec208SDavid C Somayajulu 		goto out;
3270217ec208SDavid C Somayajulu 	}
3271217ec208SDavid C Somayajulu 
3272217ec208SDavid C Somayajulu 	if (!tlvs_accepted) {
3273217ec208SDavid C Somayajulu 		if (tlvs_mask)
3274217ec208SDavid C Somayajulu 			DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
3275217ec208SDavid C Somayajulu 				   "Upper-layer prevents said VF configuration\n");
3276217ec208SDavid C Somayajulu 		else
3277217ec208SDavid C Somayajulu 			DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
3278217ec208SDavid C Somayajulu 				   "No feature tlvs found for vport update\n");
3279217ec208SDavid C Somayajulu 		status = PFVF_STATUS_NOT_SUPPORTED;
3280217ec208SDavid C Somayajulu 		goto out;
3281217ec208SDavid C Somayajulu 	}
3282217ec208SDavid C Somayajulu 
3283217ec208SDavid C Somayajulu 	rc = ecore_sp_vport_update(p_hwfn, &params, ECORE_SPQ_MODE_EBLOCK,
3284217ec208SDavid C Somayajulu 				   OSAL_NULL);
3285217ec208SDavid C Somayajulu 
3286217ec208SDavid C Somayajulu 	if (rc)
3287217ec208SDavid C Somayajulu 		status = PFVF_STATUS_FAILURE;
3288217ec208SDavid C Somayajulu 
3289217ec208SDavid C Somayajulu out:
3290217ec208SDavid C Somayajulu 	OSAL_VFREE(p_hwfn->p_dev, p_rss_params);
3291217ec208SDavid C Somayajulu 	length = ecore_iov_prep_vp_update_resp_tlvs(p_hwfn, vf, mbx, status,
3292217ec208SDavid C Somayajulu 						    tlvs_mask, tlvs_accepted);
3293217ec208SDavid C Somayajulu 	ecore_iov_send_response(p_hwfn, p_ptt, vf, length, status);
3294217ec208SDavid C Somayajulu }
3295217ec208SDavid C Somayajulu 
ecore_iov_vf_update_vlan_shadow(struct ecore_hwfn * p_hwfn,struct ecore_vf_info * p_vf,struct ecore_filter_ucast * p_params)3296217ec208SDavid C Somayajulu static enum _ecore_status_t ecore_iov_vf_update_vlan_shadow(struct ecore_hwfn *p_hwfn,
3297217ec208SDavid C Somayajulu 							    struct ecore_vf_info *p_vf,
3298217ec208SDavid C Somayajulu 							    struct ecore_filter_ucast *p_params)
3299217ec208SDavid C Somayajulu {
3300217ec208SDavid C Somayajulu 	int i;
3301217ec208SDavid C Somayajulu 
3302217ec208SDavid C Somayajulu 	/* First remove entries and then add new ones */
3303217ec208SDavid C Somayajulu 	if (p_params->opcode == ECORE_FILTER_REMOVE) {
3304217ec208SDavid C Somayajulu 		for (i = 0; i < ECORE_ETH_VF_NUM_VLAN_FILTERS + 1; i++)
3305217ec208SDavid C Somayajulu 			if (p_vf->shadow_config.vlans[i].used &&
3306217ec208SDavid C Somayajulu 			    p_vf->shadow_config.vlans[i].vid ==
3307217ec208SDavid C Somayajulu 			    p_params->vlan) {
3308217ec208SDavid C Somayajulu 				p_vf->shadow_config.vlans[i].used = false;
3309217ec208SDavid C Somayajulu 				break;
3310217ec208SDavid C Somayajulu 			}
3311217ec208SDavid C Somayajulu 		if (i == ECORE_ETH_VF_NUM_VLAN_FILTERS + 1) {
3312217ec208SDavid C Somayajulu 			DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
3313217ec208SDavid C Somayajulu 				   "VF [%d] - Tries to remove a non-existing vlan\n",
3314217ec208SDavid C Somayajulu 				    p_vf->relative_vf_id);
3315217ec208SDavid C Somayajulu 			return ECORE_INVAL;
3316217ec208SDavid C Somayajulu 		}
3317217ec208SDavid C Somayajulu 	} else if (p_params->opcode == ECORE_FILTER_REPLACE ||
3318217ec208SDavid C Somayajulu 		   p_params->opcode == ECORE_FILTER_FLUSH) {
3319217ec208SDavid C Somayajulu 		for (i = 0; i < ECORE_ETH_VF_NUM_VLAN_FILTERS + 1; i++)
3320217ec208SDavid C Somayajulu 			p_vf->shadow_config.vlans[i].used = false;
3321217ec208SDavid C Somayajulu 	}
3322217ec208SDavid C Somayajulu 
3323217ec208SDavid C Somayajulu 	/* In forced mode, we're willing to remove entries - but we don't add
3324217ec208SDavid C Somayajulu 	 * new ones.
3325217ec208SDavid C Somayajulu 	 */
3326217ec208SDavid C Somayajulu 	if (p_vf->bulletin.p_virt->valid_bitmap & (1 << VLAN_ADDR_FORCED))
3327217ec208SDavid C Somayajulu 		return ECORE_SUCCESS;
3328217ec208SDavid C Somayajulu 
3329217ec208SDavid C Somayajulu 	if (p_params->opcode == ECORE_FILTER_ADD ||
3330217ec208SDavid C Somayajulu 	    p_params->opcode == ECORE_FILTER_REPLACE) {
3331217ec208SDavid C Somayajulu 		for (i = 0; i < ECORE_ETH_VF_NUM_VLAN_FILTERS + 1; i++) {
3332217ec208SDavid C Somayajulu 			if (p_vf->shadow_config.vlans[i].used)
3333217ec208SDavid C Somayajulu 				continue;
3334217ec208SDavid C Somayajulu 
3335217ec208SDavid C Somayajulu 			p_vf->shadow_config.vlans[i].used = true;
3336217ec208SDavid C Somayajulu 			p_vf->shadow_config.vlans[i].vid = p_params->vlan;
3337217ec208SDavid C Somayajulu 			break;
3338217ec208SDavid C Somayajulu 		}
3339217ec208SDavid C Somayajulu 
3340217ec208SDavid C Somayajulu 		if (i == ECORE_ETH_VF_NUM_VLAN_FILTERS + 1) {
3341217ec208SDavid C Somayajulu 			DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
3342217ec208SDavid C Somayajulu 				   "VF [%d] - Tries to configure more than %d vlan filters\n",
3343217ec208SDavid C Somayajulu 				   p_vf->relative_vf_id,
3344217ec208SDavid C Somayajulu 				   ECORE_ETH_VF_NUM_VLAN_FILTERS + 1);
3345217ec208SDavid C Somayajulu 			return ECORE_INVAL;
3346217ec208SDavid C Somayajulu 		}
3347217ec208SDavid C Somayajulu 	}
3348217ec208SDavid C Somayajulu 
3349217ec208SDavid C Somayajulu 	return ECORE_SUCCESS;
3350217ec208SDavid C Somayajulu }
3351217ec208SDavid C Somayajulu 
ecore_iov_vf_update_mac_shadow(struct ecore_hwfn * p_hwfn,struct ecore_vf_info * p_vf,struct ecore_filter_ucast * p_params)3352217ec208SDavid C Somayajulu static enum _ecore_status_t ecore_iov_vf_update_mac_shadow(struct ecore_hwfn *p_hwfn,
3353217ec208SDavid C Somayajulu 							   struct ecore_vf_info *p_vf,
3354217ec208SDavid C Somayajulu 							   struct ecore_filter_ucast *p_params)
3355217ec208SDavid C Somayajulu {
3356217ec208SDavid C Somayajulu 	char empty_mac[ETH_ALEN];
3357217ec208SDavid C Somayajulu 	int i;
3358217ec208SDavid C Somayajulu 
3359217ec208SDavid C Somayajulu 	OSAL_MEM_ZERO(empty_mac, ETH_ALEN);
3360217ec208SDavid C Somayajulu 
3361217ec208SDavid C Somayajulu 	/* If we're in forced-mode, we don't allow any change */
3362217ec208SDavid C Somayajulu 	/* TODO - this would change if we were ever to implement logic for
3363217ec208SDavid C Somayajulu 	 * removing a forced MAC altogether [in which case, like for vlans,
3364217ec208SDavid C Somayajulu 	 * we should be able to re-trace previous configuration.
3365217ec208SDavid C Somayajulu 	 */
3366217ec208SDavid C Somayajulu 	if (p_vf->bulletin.p_virt->valid_bitmap & (1 << MAC_ADDR_FORCED))
3367217ec208SDavid C Somayajulu 		return ECORE_SUCCESS;
3368217ec208SDavid C Somayajulu 
3369217ec208SDavid C Somayajulu 	/* First remove entries and then add new ones */
3370217ec208SDavid C Somayajulu 	if (p_params->opcode == ECORE_FILTER_REMOVE) {
3371217ec208SDavid C Somayajulu 		for (i = 0; i < ECORE_ETH_VF_NUM_MAC_FILTERS; i++) {
3372217ec208SDavid C Somayajulu 			if (!OSAL_MEMCMP(p_vf->shadow_config.macs[i],
3373217ec208SDavid C Somayajulu 					 p_params->mac, ETH_ALEN)) {
3374217ec208SDavid C Somayajulu 				OSAL_MEM_ZERO(p_vf->shadow_config.macs[i],
3375217ec208SDavid C Somayajulu 					      ETH_ALEN);
3376217ec208SDavid C Somayajulu 				break;
3377217ec208SDavid C Somayajulu 			}
3378217ec208SDavid C Somayajulu 		}
3379217ec208SDavid C Somayajulu 
3380217ec208SDavid C Somayajulu 		if (i == ECORE_ETH_VF_NUM_MAC_FILTERS) {
3381217ec208SDavid C Somayajulu 			DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
3382217ec208SDavid C Somayajulu 				   "MAC isn't configured\n");
3383217ec208SDavid C Somayajulu 			return ECORE_INVAL;
3384217ec208SDavid C Somayajulu 		}
3385217ec208SDavid C Somayajulu 	} else if (p_params->opcode == ECORE_FILTER_REPLACE ||
3386217ec208SDavid C Somayajulu 		   p_params->opcode == ECORE_FILTER_FLUSH) {
3387217ec208SDavid C Somayajulu 		for (i = 0; i < ECORE_ETH_VF_NUM_MAC_FILTERS; i++)
3388217ec208SDavid C Somayajulu 			OSAL_MEM_ZERO(p_vf->shadow_config.macs[i], ETH_ALEN);
3389217ec208SDavid C Somayajulu 	}
3390217ec208SDavid C Somayajulu 
3391217ec208SDavid C Somayajulu 	/* List the new MAC address */
3392217ec208SDavid C Somayajulu 	if (p_params->opcode != ECORE_FILTER_ADD &&
3393217ec208SDavid C Somayajulu 	    p_params->opcode != ECORE_FILTER_REPLACE)
3394217ec208SDavid C Somayajulu 		return ECORE_SUCCESS;
3395217ec208SDavid C Somayajulu 
3396217ec208SDavid C Somayajulu 	for (i = 0; i < ECORE_ETH_VF_NUM_MAC_FILTERS; i++) {
3397217ec208SDavid C Somayajulu 		if (!OSAL_MEMCMP(p_vf->shadow_config.macs[i],
3398217ec208SDavid C Somayajulu 				 empty_mac, ETH_ALEN)) {
3399217ec208SDavid C Somayajulu 			OSAL_MEMCPY(p_vf->shadow_config.macs[i],
3400217ec208SDavid C Somayajulu 				    p_params->mac, ETH_ALEN);
3401217ec208SDavid C Somayajulu 			DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
3402217ec208SDavid C Somayajulu 				   "Added MAC at %d entry in shadow\n", i);
3403217ec208SDavid C Somayajulu 			break;
3404217ec208SDavid C Somayajulu 		}
3405217ec208SDavid C Somayajulu 	}
3406217ec208SDavid C Somayajulu 
3407217ec208SDavid C Somayajulu 	if (i == ECORE_ETH_VF_NUM_MAC_FILTERS) {
3408217ec208SDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
3409217ec208SDavid C Somayajulu 			   "No available place for MAC\n");
3410217ec208SDavid C Somayajulu 		return ECORE_INVAL;
3411217ec208SDavid C Somayajulu 	}
3412217ec208SDavid C Somayajulu 
3413217ec208SDavid C Somayajulu 	return ECORE_SUCCESS;
3414217ec208SDavid C Somayajulu }
3415217ec208SDavid C Somayajulu 
3416217ec208SDavid C Somayajulu static enum _ecore_status_t
ecore_iov_vf_update_unicast_shadow(struct ecore_hwfn * p_hwfn,struct ecore_vf_info * p_vf,struct ecore_filter_ucast * p_params)3417217ec208SDavid C Somayajulu ecore_iov_vf_update_unicast_shadow(struct ecore_hwfn *p_hwfn,
3418217ec208SDavid C Somayajulu 				   struct ecore_vf_info *p_vf,
3419217ec208SDavid C Somayajulu 				   struct ecore_filter_ucast *p_params)
3420217ec208SDavid C Somayajulu {
3421217ec208SDavid C Somayajulu 	enum _ecore_status_t rc = ECORE_SUCCESS;
3422217ec208SDavid C Somayajulu 
3423217ec208SDavid C Somayajulu 	if (p_params->type == ECORE_FILTER_MAC) {
3424217ec208SDavid C Somayajulu 		rc = ecore_iov_vf_update_mac_shadow(p_hwfn, p_vf, p_params);
3425217ec208SDavid C Somayajulu 		if (rc != ECORE_SUCCESS)
3426217ec208SDavid C Somayajulu 			return rc;
3427217ec208SDavid C Somayajulu 	}
3428217ec208SDavid C Somayajulu 
3429217ec208SDavid C Somayajulu 	if (p_params->type == ECORE_FILTER_VLAN)
3430217ec208SDavid C Somayajulu 		rc = ecore_iov_vf_update_vlan_shadow(p_hwfn, p_vf, p_params);
3431217ec208SDavid C Somayajulu 
3432217ec208SDavid C Somayajulu 	return rc;
3433217ec208SDavid C Somayajulu }
3434217ec208SDavid C Somayajulu 
ecore_iov_vf_mbx_ucast_filter(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * vf)3435217ec208SDavid C Somayajulu static void ecore_iov_vf_mbx_ucast_filter(struct ecore_hwfn *p_hwfn,
3436217ec208SDavid C Somayajulu 					  struct ecore_ptt *p_ptt,
3437217ec208SDavid C Somayajulu 					  struct ecore_vf_info *vf)
3438217ec208SDavid C Somayajulu {
3439217ec208SDavid C Somayajulu 	struct ecore_bulletin_content *p_bulletin = vf->bulletin.p_virt;
3440217ec208SDavid C Somayajulu 	struct ecore_iov_vf_mbx *mbx = &vf->vf_mbx;
3441217ec208SDavid C Somayajulu 	struct vfpf_ucast_filter_tlv *req;
3442217ec208SDavid C Somayajulu 	u8 status = PFVF_STATUS_SUCCESS;
3443217ec208SDavid C Somayajulu 	struct ecore_filter_ucast params;
3444217ec208SDavid C Somayajulu 	enum _ecore_status_t rc;
3445217ec208SDavid C Somayajulu 
3446217ec208SDavid C Somayajulu 	/* Prepare the unicast filter params */
3447217ec208SDavid C Somayajulu 	OSAL_MEMSET(&params, 0, sizeof(struct ecore_filter_ucast));
3448217ec208SDavid C Somayajulu 	req = &mbx->req_virt->ucast_filter;
3449217ec208SDavid C Somayajulu 	params.opcode = (enum ecore_filter_opcode)req->opcode;
3450217ec208SDavid C Somayajulu 	params.type = (enum ecore_filter_ucast_type)req->type;
3451217ec208SDavid C Somayajulu 
3452217ec208SDavid C Somayajulu 	/* @@@TBD - We might need logic on HV side in determining this */
3453217ec208SDavid C Somayajulu 	params.is_rx_filter = 1;
3454217ec208SDavid C Somayajulu 	params.is_tx_filter = 1;
3455217ec208SDavid C Somayajulu 	params.vport_to_remove_from = vf->vport_id;
3456217ec208SDavid C Somayajulu 	params.vport_to_add_to = vf->vport_id;
3457217ec208SDavid C Somayajulu 	OSAL_MEMCPY(params.mac, req->mac, ETH_ALEN);
3458217ec208SDavid C Somayajulu 	params.vlan = req->vlan;
3459217ec208SDavid C Somayajulu 
3460217ec208SDavid C Somayajulu 	DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
3461217ec208SDavid C Somayajulu 		   "VF[%d]: opcode 0x%02x type 0x%02x [%s %s] [vport 0x%02x] MAC %02x:%02x:%02x:%02x:%02x:%02x, vlan 0x%04x\n",
3462217ec208SDavid C Somayajulu 		   vf->abs_vf_id, params.opcode, params.type,
3463217ec208SDavid C Somayajulu 		   params.is_rx_filter ? "RX" : "",
3464217ec208SDavid C Somayajulu 		   params.is_tx_filter ? "TX" : "",
3465217ec208SDavid C Somayajulu 		   params.vport_to_add_to,
3466217ec208SDavid C Somayajulu 		   params.mac[0], params.mac[1], params.mac[2],
3467217ec208SDavid C Somayajulu 		   params.mac[3], params.mac[4], params.mac[5], params.vlan);
3468217ec208SDavid C Somayajulu 
3469217ec208SDavid C Somayajulu 	if (!vf->vport_instance) {
3470217ec208SDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
3471217ec208SDavid C Somayajulu 			   "No VPORT instance available for VF[%d], failing ucast MAC configuration\n",
3472217ec208SDavid C Somayajulu 			   vf->abs_vf_id);
3473217ec208SDavid C Somayajulu 		status = PFVF_STATUS_FAILURE;
3474217ec208SDavid C Somayajulu 		goto out;
3475217ec208SDavid C Somayajulu 	}
3476217ec208SDavid C Somayajulu 
3477217ec208SDavid C Somayajulu 	/* Update shadow copy of the VF configuration. In case shadow indicates
3478217ec208SDavid C Somayajulu 	 * the action should be blocked return success to VF to imitate the
3479217ec208SDavid C Somayajulu 	 * firmware behaviour in such case.
3480217ec208SDavid C Somayajulu 	 */
3481217ec208SDavid C Somayajulu 	if (ecore_iov_vf_update_unicast_shadow(p_hwfn, vf, &params) !=
3482217ec208SDavid C Somayajulu 	    ECORE_SUCCESS)
3483217ec208SDavid C Somayajulu 		goto out;
3484217ec208SDavid C Somayajulu 
3485217ec208SDavid C Somayajulu 	/* Determine if the unicast filtering is acceptible by PF */
3486217ec208SDavid C Somayajulu 	if ((p_bulletin->valid_bitmap & (1 << VLAN_ADDR_FORCED)) &&
3487217ec208SDavid C Somayajulu 	    (params.type == ECORE_FILTER_VLAN ||
3488217ec208SDavid C Somayajulu 	     params.type == ECORE_FILTER_MAC_VLAN)) {
3489217ec208SDavid C Somayajulu 		/* Once VLAN is forced or PVID is set, do not allow
3490217ec208SDavid C Somayajulu 		 * to add/replace any further VLANs.
3491217ec208SDavid C Somayajulu 		 */
3492217ec208SDavid C Somayajulu 		if (params.opcode == ECORE_FILTER_ADD ||
3493217ec208SDavid C Somayajulu 		    params.opcode == ECORE_FILTER_REPLACE)
3494217ec208SDavid C Somayajulu 			status = PFVF_STATUS_FORCED;
3495217ec208SDavid C Somayajulu 		goto out;
3496217ec208SDavid C Somayajulu 	}
3497217ec208SDavid C Somayajulu 
3498217ec208SDavid C Somayajulu 	if ((p_bulletin->valid_bitmap & (1 << MAC_ADDR_FORCED)) &&
3499217ec208SDavid C Somayajulu 	    (params.type == ECORE_FILTER_MAC ||
3500217ec208SDavid C Somayajulu 	     params.type == ECORE_FILTER_MAC_VLAN)) {
3501217ec208SDavid C Somayajulu 		if (OSAL_MEMCMP(p_bulletin->mac, params.mac, ETH_ALEN) ||
3502217ec208SDavid C Somayajulu 		    (params.opcode != ECORE_FILTER_ADD &&
3503217ec208SDavid C Somayajulu 		     params.opcode != ECORE_FILTER_REPLACE))
3504217ec208SDavid C Somayajulu 			status = PFVF_STATUS_FORCED;
3505217ec208SDavid C Somayajulu 		goto out;
3506217ec208SDavid C Somayajulu 	}
3507217ec208SDavid C Somayajulu 
3508217ec208SDavid C Somayajulu 	rc = OSAL_IOV_CHK_UCAST(p_hwfn, vf->relative_vf_id, &params);
3509217ec208SDavid C Somayajulu 	if (rc == ECORE_EXISTS) {
3510217ec208SDavid C Somayajulu 		goto out;
3511217ec208SDavid C Somayajulu 	} else if (rc == ECORE_INVAL) {
3512217ec208SDavid C Somayajulu 		status = PFVF_STATUS_FAILURE;
3513217ec208SDavid C Somayajulu 		goto out;
3514217ec208SDavid C Somayajulu 	}
3515217ec208SDavid C Somayajulu 
3516217ec208SDavid C Somayajulu 	rc = ecore_sp_eth_filter_ucast(p_hwfn, vf->opaque_fid, &params,
3517217ec208SDavid C Somayajulu 				       ECORE_SPQ_MODE_CB, OSAL_NULL);
3518217ec208SDavid C Somayajulu 	if (rc)
3519217ec208SDavid C Somayajulu 		status = PFVF_STATUS_FAILURE;
3520217ec208SDavid C Somayajulu 
3521217ec208SDavid C Somayajulu out:
3522217ec208SDavid C Somayajulu 	ecore_iov_prepare_resp(p_hwfn, p_ptt, vf, CHANNEL_TLV_UCAST_FILTER,
3523217ec208SDavid C Somayajulu 			       sizeof(struct pfvf_def_resp_tlv), status);
3524217ec208SDavid C Somayajulu }
3525217ec208SDavid C Somayajulu 
ecore_iov_vf_mbx_int_cleanup(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * vf)3526217ec208SDavid C Somayajulu static void ecore_iov_vf_mbx_int_cleanup(struct ecore_hwfn *p_hwfn,
3527217ec208SDavid C Somayajulu 					 struct ecore_ptt *p_ptt,
3528217ec208SDavid C Somayajulu 					 struct ecore_vf_info *vf)
3529217ec208SDavid C Somayajulu {
3530217ec208SDavid C Somayajulu 	int i;
3531217ec208SDavid C Somayajulu 
3532217ec208SDavid C Somayajulu 	/* Reset the SBs */
3533217ec208SDavid C Somayajulu 	for (i = 0; i < vf->num_sbs; i++)
3534217ec208SDavid C Somayajulu 		ecore_int_igu_init_pure_rt_single(p_hwfn, p_ptt,
3535217ec208SDavid C Somayajulu 						  vf->igu_sbs[i],
3536217ec208SDavid C Somayajulu 						  vf->opaque_fid, false);
3537217ec208SDavid C Somayajulu 
3538217ec208SDavid C Somayajulu 	ecore_iov_prepare_resp(p_hwfn, p_ptt, vf, CHANNEL_TLV_INT_CLEANUP,
3539217ec208SDavid C Somayajulu 			       sizeof(struct pfvf_def_resp_tlv),
3540217ec208SDavid C Somayajulu 			       PFVF_STATUS_SUCCESS);
3541217ec208SDavid C Somayajulu }
3542217ec208SDavid C Somayajulu 
ecore_iov_vf_mbx_close(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * vf)3543217ec208SDavid C Somayajulu static void ecore_iov_vf_mbx_close(struct ecore_hwfn *p_hwfn,
3544217ec208SDavid C Somayajulu 				   struct ecore_ptt *p_ptt,
3545217ec208SDavid C Somayajulu 				   struct ecore_vf_info	*vf)
3546217ec208SDavid C Somayajulu {
3547217ec208SDavid C Somayajulu 	u16                      length = sizeof(struct pfvf_def_resp_tlv);
3548217ec208SDavid C Somayajulu 	u8                       status = PFVF_STATUS_SUCCESS;
3549217ec208SDavid C Somayajulu 
3550217ec208SDavid C Somayajulu 	/* Disable Interrupts for VF */
3551217ec208SDavid C Somayajulu 	ecore_iov_vf_igu_set_int(p_hwfn, p_ptt, vf, 0);
3552217ec208SDavid C Somayajulu 
3553217ec208SDavid C Somayajulu 	/* Reset Permission table */
3554217ec208SDavid C Somayajulu 	ecore_iov_config_perm_table(p_hwfn, p_ptt, vf, 0);
3555217ec208SDavid C Somayajulu 
3556217ec208SDavid C Somayajulu 	ecore_iov_prepare_resp(p_hwfn, p_ptt, vf, CHANNEL_TLV_CLOSE,
3557217ec208SDavid C Somayajulu 			       length, status);
3558217ec208SDavid C Somayajulu }
3559217ec208SDavid C Somayajulu 
ecore_iov_vf_mbx_release(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * p_vf)3560217ec208SDavid C Somayajulu static void ecore_iov_vf_mbx_release(struct ecore_hwfn *p_hwfn,
3561217ec208SDavid C Somayajulu 				     struct ecore_ptt *p_ptt,
3562217ec208SDavid C Somayajulu 				     struct ecore_vf_info *p_vf)
3563217ec208SDavid C Somayajulu {
3564217ec208SDavid C Somayajulu 	u16 length = sizeof(struct pfvf_def_resp_tlv);
3565217ec208SDavid C Somayajulu 	u8 status = PFVF_STATUS_SUCCESS;
3566217ec208SDavid C Somayajulu 	enum _ecore_status_t rc = ECORE_SUCCESS;
3567217ec208SDavid C Somayajulu 
3568217ec208SDavid C Somayajulu 	ecore_iov_vf_cleanup(p_hwfn, p_vf);
3569217ec208SDavid C Somayajulu 
3570217ec208SDavid C Somayajulu 	if (p_vf->state != VF_STOPPED && p_vf->state != VF_FREE) {
3571217ec208SDavid C Somayajulu 		/* Stopping the VF */
3572217ec208SDavid C Somayajulu 		rc = ecore_sp_vf_stop(p_hwfn, p_vf->concrete_fid,
3573217ec208SDavid C Somayajulu 				      p_vf->opaque_fid);
3574217ec208SDavid C Somayajulu 
3575217ec208SDavid C Somayajulu 		if (rc != ECORE_SUCCESS) {
3576217ec208SDavid C Somayajulu 			DP_ERR(p_hwfn, "ecore_sp_vf_stop returned error %d\n",
3577217ec208SDavid C Somayajulu 			       rc);
3578217ec208SDavid C Somayajulu 			status = PFVF_STATUS_FAILURE;
3579217ec208SDavid C Somayajulu 		}
3580217ec208SDavid C Somayajulu 
3581217ec208SDavid C Somayajulu 		p_vf->state = VF_STOPPED;
3582217ec208SDavid C Somayajulu 	}
3583217ec208SDavid C Somayajulu 
3584217ec208SDavid C Somayajulu 	ecore_iov_prepare_resp(p_hwfn, p_ptt, p_vf, CHANNEL_TLV_RELEASE,
3585217ec208SDavid C Somayajulu 			       length, status);
3586217ec208SDavid C Somayajulu }
3587217ec208SDavid C Somayajulu 
ecore_iov_vf_pf_get_coalesce(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * p_vf)3588217ec208SDavid C Somayajulu static void ecore_iov_vf_pf_get_coalesce(struct ecore_hwfn *p_hwfn,
3589217ec208SDavid C Somayajulu 					 struct ecore_ptt *p_ptt,
3590217ec208SDavid C Somayajulu 					 struct ecore_vf_info *p_vf)
3591217ec208SDavid C Somayajulu {
3592217ec208SDavid C Somayajulu 	struct ecore_iov_vf_mbx *mbx = &p_vf->vf_mbx;
3593217ec208SDavid C Somayajulu 	struct pfvf_read_coal_resp_tlv *p_resp;
3594217ec208SDavid C Somayajulu 	struct vfpf_read_coal_req_tlv *req;
3595217ec208SDavid C Somayajulu 	u8 status = PFVF_STATUS_FAILURE;
3596217ec208SDavid C Somayajulu 	struct ecore_vf_queue *p_queue;
3597217ec208SDavid C Somayajulu 	struct ecore_queue_cid *p_cid;
3598217ec208SDavid C Somayajulu 	enum _ecore_status_t rc = ECORE_SUCCESS;
3599217ec208SDavid C Somayajulu 	u16 coal = 0, qid, i;
3600217ec208SDavid C Somayajulu 	bool b_is_rx;
3601217ec208SDavid C Somayajulu 
3602217ec208SDavid C Somayajulu 	mbx->offset = (u8 *)mbx->reply_virt;
3603217ec208SDavid C Somayajulu 	req = &mbx->req_virt->read_coal_req;
3604217ec208SDavid C Somayajulu 
3605217ec208SDavid C Somayajulu 	qid = req->qid;
3606217ec208SDavid C Somayajulu 	b_is_rx = req->is_rx ? true : false;
3607217ec208SDavid C Somayajulu 
3608217ec208SDavid C Somayajulu 	if (b_is_rx) {
3609217ec208SDavid C Somayajulu 		if (!ecore_iov_validate_rxq(p_hwfn, p_vf, qid,
3610217ec208SDavid C Somayajulu 					    ECORE_IOV_VALIDATE_Q_ENABLE)) {
3611217ec208SDavid C Somayajulu 			DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
3612217ec208SDavid C Somayajulu 				   "VF[%d]: Invalid Rx queue_id = %d\n",
3613217ec208SDavid C Somayajulu 				   p_vf->abs_vf_id, qid);
3614217ec208SDavid C Somayajulu 			goto send_resp;
3615217ec208SDavid C Somayajulu 		}
3616217ec208SDavid C Somayajulu 
3617217ec208SDavid C Somayajulu 		p_cid = ecore_iov_get_vf_rx_queue_cid(&p_vf->vf_queues[qid]);
3618217ec208SDavid C Somayajulu 		rc = ecore_get_rxq_coalesce(p_hwfn, p_ptt, p_cid, &coal);
3619217ec208SDavid C Somayajulu 		if (rc != ECORE_SUCCESS)
3620217ec208SDavid C Somayajulu 			goto send_resp;
3621217ec208SDavid C Somayajulu 	} else {
3622217ec208SDavid C Somayajulu 		if (!ecore_iov_validate_txq(p_hwfn, p_vf, qid,
3623217ec208SDavid C Somayajulu 					    ECORE_IOV_VALIDATE_Q_ENABLE)) {
3624217ec208SDavid C Somayajulu 			DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
3625217ec208SDavid C Somayajulu 				   "VF[%d]: Invalid Tx queue_id = %d\n",
3626217ec208SDavid C Somayajulu 				   p_vf->abs_vf_id, qid);
3627217ec208SDavid C Somayajulu 			goto send_resp;
3628217ec208SDavid C Somayajulu 		}
3629217ec208SDavid C Somayajulu 		for (i = 0; i < MAX_QUEUES_PER_QZONE; i++) {
3630217ec208SDavid C Somayajulu 			p_queue = &p_vf->vf_queues[qid];
3631217ec208SDavid C Somayajulu 			if ((p_queue->cids[i].p_cid == OSAL_NULL) ||
3632217ec208SDavid C Somayajulu 			    (!p_queue->cids[i].b_is_tx))
3633217ec208SDavid C Somayajulu 				continue;
3634217ec208SDavid C Somayajulu 
3635217ec208SDavid C Somayajulu 			p_cid = p_queue->cids[i].p_cid;
3636217ec208SDavid C Somayajulu 
3637217ec208SDavid C Somayajulu 			rc = ecore_get_txq_coalesce(p_hwfn, p_ptt,
3638217ec208SDavid C Somayajulu 						    p_cid, &coal);
3639217ec208SDavid C Somayajulu 			if (rc != ECORE_SUCCESS)
3640217ec208SDavid C Somayajulu 				goto send_resp;
3641217ec208SDavid C Somayajulu 			break;
3642217ec208SDavid C Somayajulu 		}
3643217ec208SDavid C Somayajulu 	}
3644217ec208SDavid C Somayajulu 
3645217ec208SDavid C Somayajulu 	status = PFVF_STATUS_SUCCESS;
3646217ec208SDavid C Somayajulu 
3647217ec208SDavid C Somayajulu send_resp:
3648217ec208SDavid C Somayajulu 	p_resp = ecore_add_tlv(&mbx->offset, CHANNEL_TLV_COALESCE_READ,
3649217ec208SDavid C Somayajulu 			       sizeof(*p_resp));
3650217ec208SDavid C Somayajulu 	p_resp->coal = coal;
3651217ec208SDavid C Somayajulu 
3652217ec208SDavid C Somayajulu 	ecore_add_tlv(&mbx->offset, CHANNEL_TLV_LIST_END,
3653217ec208SDavid C Somayajulu 		      sizeof(struct channel_list_end_tlv));
3654217ec208SDavid C Somayajulu 
3655217ec208SDavid C Somayajulu 	ecore_iov_send_response(p_hwfn, p_ptt, p_vf, sizeof(*p_resp), status);
3656217ec208SDavid C Somayajulu }
3657217ec208SDavid C Somayajulu 
ecore_iov_vf_pf_set_coalesce(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * vf)3658217ec208SDavid C Somayajulu static void ecore_iov_vf_pf_set_coalesce(struct ecore_hwfn *p_hwfn,
3659217ec208SDavid C Somayajulu 					 struct ecore_ptt *p_ptt,
3660217ec208SDavid C Somayajulu 					 struct ecore_vf_info *vf)
3661217ec208SDavid C Somayajulu {
3662217ec208SDavid C Somayajulu 	struct ecore_iov_vf_mbx *mbx = &vf->vf_mbx;
3663217ec208SDavid C Somayajulu 	enum _ecore_status_t rc = ECORE_SUCCESS;
3664217ec208SDavid C Somayajulu 	struct vfpf_update_coalesce *req;
3665217ec208SDavid C Somayajulu 	u8 status = PFVF_STATUS_FAILURE;
3666217ec208SDavid C Somayajulu 	struct ecore_queue_cid *p_cid;
3667217ec208SDavid C Somayajulu 	u16 rx_coal, tx_coal;
3668217ec208SDavid C Somayajulu 	u16 qid;
3669217ec208SDavid C Somayajulu 	int i;
3670217ec208SDavid C Somayajulu 
3671217ec208SDavid C Somayajulu 	req = &mbx->req_virt->update_coalesce;
3672217ec208SDavid C Somayajulu 
3673217ec208SDavid C Somayajulu 	rx_coal = req->rx_coal;
3674217ec208SDavid C Somayajulu 	tx_coal = req->tx_coal;
3675217ec208SDavid C Somayajulu 	qid = req->qid;
3676217ec208SDavid C Somayajulu 
3677217ec208SDavid C Somayajulu 	if (!ecore_iov_validate_rxq(p_hwfn, vf, qid,
3678217ec208SDavid C Somayajulu 				    ECORE_IOV_VALIDATE_Q_ENABLE) &&
3679217ec208SDavid C Somayajulu 	    rx_coal) {
3680217ec208SDavid C Somayajulu 		DP_ERR(p_hwfn, "VF[%d]: Invalid Rx queue_id = %d\n",
3681217ec208SDavid C Somayajulu 		       vf->abs_vf_id, qid);
3682217ec208SDavid C Somayajulu 		goto out;
3683217ec208SDavid C Somayajulu 	}
3684217ec208SDavid C Somayajulu 
3685217ec208SDavid C Somayajulu 	if (!ecore_iov_validate_txq(p_hwfn, vf, qid,
3686217ec208SDavid C Somayajulu 				    ECORE_IOV_VALIDATE_Q_ENABLE) &&
3687217ec208SDavid C Somayajulu 	    tx_coal) {
3688217ec208SDavid C Somayajulu 		DP_ERR(p_hwfn, "VF[%d]: Invalid Tx queue_id = %d\n",
3689217ec208SDavid C Somayajulu 		       vf->abs_vf_id, qid);
3690217ec208SDavid C Somayajulu 		goto out;
3691217ec208SDavid C Somayajulu 	}
3692217ec208SDavid C Somayajulu 
3693217ec208SDavid C Somayajulu 	DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
3694217ec208SDavid C Somayajulu 		   "VF[%d]: Setting coalesce for VF rx_coal = %d, tx_coal = %d at queue = %d\n",
3695217ec208SDavid C Somayajulu 		   vf->abs_vf_id, rx_coal, tx_coal, qid);
3696217ec208SDavid C Somayajulu 
3697217ec208SDavid C Somayajulu 	if (rx_coal) {
3698217ec208SDavid C Somayajulu 		p_cid = ecore_iov_get_vf_rx_queue_cid(&vf->vf_queues[qid]);
3699217ec208SDavid C Somayajulu 
3700217ec208SDavid C Somayajulu 		rc = ecore_set_rxq_coalesce(p_hwfn, p_ptt, rx_coal, p_cid);
3701217ec208SDavid C Somayajulu 		if (rc != ECORE_SUCCESS) {
3702217ec208SDavid C Somayajulu 			DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
3703217ec208SDavid C Somayajulu 				   "VF[%d]: Unable to set rx queue = %d coalesce\n",
3704217ec208SDavid C Somayajulu 				   vf->abs_vf_id, vf->vf_queues[qid].fw_rx_qid);
3705217ec208SDavid C Somayajulu 			goto out;
3706217ec208SDavid C Somayajulu 		}
3707217ec208SDavid C Somayajulu 		vf->rx_coal = rx_coal;
3708217ec208SDavid C Somayajulu 	}
3709217ec208SDavid C Somayajulu 
3710217ec208SDavid C Somayajulu 	/* TODO - in future, it might be possible to pass this in a per-cid
3711217ec208SDavid C Somayajulu 	 * granularity. For now, do this for all Tx queues.
3712217ec208SDavid C Somayajulu 	 */
3713217ec208SDavid C Somayajulu 	if (tx_coal) {
3714217ec208SDavid C Somayajulu 		struct ecore_vf_queue *p_queue = &vf->vf_queues[qid];
3715217ec208SDavid C Somayajulu 
3716217ec208SDavid C Somayajulu 		for (i = 0; i < MAX_QUEUES_PER_QZONE; i++) {
3717217ec208SDavid C Somayajulu 			if (p_queue->cids[i].p_cid == OSAL_NULL)
3718217ec208SDavid C Somayajulu 				continue;
3719217ec208SDavid C Somayajulu 
3720217ec208SDavid C Somayajulu 			if (!p_queue->cids[i].b_is_tx)
3721217ec208SDavid C Somayajulu 				continue;
3722217ec208SDavid C Somayajulu 
3723217ec208SDavid C Somayajulu 			rc = ecore_set_txq_coalesce(p_hwfn, p_ptt, tx_coal,
3724217ec208SDavid C Somayajulu 						    p_queue->cids[i].p_cid);
3725217ec208SDavid C Somayajulu 			if (rc != ECORE_SUCCESS) {
3726217ec208SDavid C Somayajulu 				DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
3727217ec208SDavid C Somayajulu 					   "VF[%d]: Unable to set tx queue coalesce\n",
3728217ec208SDavid C Somayajulu 					   vf->abs_vf_id);
3729217ec208SDavid C Somayajulu 				goto out;
3730217ec208SDavid C Somayajulu 			}
3731217ec208SDavid C Somayajulu 		}
3732217ec208SDavid C Somayajulu 		vf->tx_coal = tx_coal;
3733217ec208SDavid C Somayajulu 	}
3734217ec208SDavid C Somayajulu 
3735217ec208SDavid C Somayajulu 	status = PFVF_STATUS_SUCCESS;
3736217ec208SDavid C Somayajulu out:
3737217ec208SDavid C Somayajulu 	ecore_iov_prepare_resp(p_hwfn, p_ptt, vf, CHANNEL_TLV_COALESCE_UPDATE,
3738217ec208SDavid C Somayajulu 			       sizeof(struct pfvf_def_resp_tlv), status);
3739217ec208SDavid C Somayajulu }
3740217ec208SDavid C Somayajulu 
3741217ec208SDavid C Somayajulu enum _ecore_status_t
ecore_iov_pf_configure_vf_queue_coalesce(struct ecore_hwfn * p_hwfn,u16 rx_coal,u16 tx_coal,u16 vf_id,u16 qid)3742217ec208SDavid C Somayajulu ecore_iov_pf_configure_vf_queue_coalesce(struct ecore_hwfn *p_hwfn,
3743217ec208SDavid C Somayajulu 					 u16 rx_coal, u16 tx_coal,
3744217ec208SDavid C Somayajulu 					 u16 vf_id, u16 qid)
3745217ec208SDavid C Somayajulu {
3746217ec208SDavid C Somayajulu 	struct ecore_queue_cid *p_cid;
3747217ec208SDavid C Somayajulu 	struct ecore_vf_info *vf;
3748217ec208SDavid C Somayajulu 	struct ecore_ptt *p_ptt;
3749217ec208SDavid C Somayajulu 	int i, rc = 0;
3750217ec208SDavid C Somayajulu 
3751217ec208SDavid C Somayajulu 	if (!ecore_iov_is_valid_vfid(p_hwfn, vf_id, true, true)) {
3752217ec208SDavid C Somayajulu 		DP_NOTICE(p_hwfn, true,
3753217ec208SDavid C Somayajulu 			  "VF[%d] - Can not set coalescing: VF is not active\n",
3754217ec208SDavid C Somayajulu 			  vf_id);
3755217ec208SDavid C Somayajulu 		return ECORE_INVAL;
3756217ec208SDavid C Somayajulu 	}
3757217ec208SDavid C Somayajulu 
3758217ec208SDavid C Somayajulu 	vf = &p_hwfn->pf_iov_info->vfs_array[vf_id];
3759217ec208SDavid C Somayajulu 	p_ptt = ecore_ptt_acquire(p_hwfn);
3760217ec208SDavid C Somayajulu 	if (!p_ptt)
3761217ec208SDavid C Somayajulu 		return ECORE_AGAIN;
3762217ec208SDavid C Somayajulu 
3763217ec208SDavid C Somayajulu 	if (!ecore_iov_validate_rxq(p_hwfn, vf, qid,
3764217ec208SDavid C Somayajulu 				    ECORE_IOV_VALIDATE_Q_ENABLE) &&
3765217ec208SDavid C Somayajulu 	    rx_coal) {
3766217ec208SDavid C Somayajulu 		DP_ERR(p_hwfn, "VF[%d]: Invalid Rx queue_id = %d\n",
3767217ec208SDavid C Somayajulu 		       vf->abs_vf_id, qid);
3768217ec208SDavid C Somayajulu 		goto out;
3769217ec208SDavid C Somayajulu 	}
3770217ec208SDavid C Somayajulu 
3771217ec208SDavid C Somayajulu 	if (!ecore_iov_validate_txq(p_hwfn, vf, qid,
3772217ec208SDavid C Somayajulu 				    ECORE_IOV_VALIDATE_Q_ENABLE) &&
3773217ec208SDavid C Somayajulu 	    tx_coal) {
3774217ec208SDavid C Somayajulu 		DP_ERR(p_hwfn, "VF[%d]: Invalid Tx queue_id = %d\n",
3775217ec208SDavid C Somayajulu 		       vf->abs_vf_id, qid);
3776217ec208SDavid C Somayajulu 		goto out;
3777217ec208SDavid C Somayajulu 	}
3778217ec208SDavid C Somayajulu 
3779217ec208SDavid C Somayajulu 	DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
3780217ec208SDavid C Somayajulu 		   "VF[%d]: Setting coalesce for VF rx_coal = %d, tx_coal = %d at queue = %d\n",
3781217ec208SDavid C Somayajulu 		   vf->abs_vf_id, rx_coal, tx_coal, qid);
3782217ec208SDavid C Somayajulu 
3783217ec208SDavid C Somayajulu 	if (rx_coal) {
3784217ec208SDavid C Somayajulu 		p_cid = ecore_iov_get_vf_rx_queue_cid(&vf->vf_queues[qid]);
3785217ec208SDavid C Somayajulu 
3786217ec208SDavid C Somayajulu 		rc = ecore_set_rxq_coalesce(p_hwfn, p_ptt, rx_coal, p_cid);
3787217ec208SDavid C Somayajulu 		if (rc != ECORE_SUCCESS) {
3788217ec208SDavid C Somayajulu 			DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
3789217ec208SDavid C Somayajulu 				   "VF[%d]: Unable to set rx queue = %d coalesce\n",
3790217ec208SDavid C Somayajulu 				   vf->abs_vf_id, vf->vf_queues[qid].fw_rx_qid);
3791217ec208SDavid C Somayajulu 			goto out;
3792217ec208SDavid C Somayajulu 		}
3793217ec208SDavid C Somayajulu 		vf->rx_coal = rx_coal;
3794217ec208SDavid C Somayajulu 	}
3795217ec208SDavid C Somayajulu 
3796217ec208SDavid C Somayajulu 	/* TODO - in future, it might be possible to pass this in a per-cid
3797217ec208SDavid C Somayajulu 	 * granularity. For now, do this for all Tx queues.
3798217ec208SDavid C Somayajulu 	 */
3799217ec208SDavid C Somayajulu 	if (tx_coal) {
3800217ec208SDavid C Somayajulu 		struct ecore_vf_queue *p_queue = &vf->vf_queues[qid];
3801217ec208SDavid C Somayajulu 
3802217ec208SDavid C Somayajulu 		for (i = 0; i < MAX_QUEUES_PER_QZONE; i++) {
3803217ec208SDavid C Somayajulu 			if (p_queue->cids[i].p_cid == OSAL_NULL)
3804217ec208SDavid C Somayajulu 				continue;
3805217ec208SDavid C Somayajulu 
3806217ec208SDavid C Somayajulu 			if (!p_queue->cids[i].b_is_tx)
3807217ec208SDavid C Somayajulu 				continue;
3808217ec208SDavid C Somayajulu 
3809217ec208SDavid C Somayajulu 			rc = ecore_set_txq_coalesce(p_hwfn, p_ptt, tx_coal,
3810217ec208SDavid C Somayajulu 						    p_queue->cids[i].p_cid);
3811217ec208SDavid C Somayajulu 			if (rc != ECORE_SUCCESS) {
3812217ec208SDavid C Somayajulu 				DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
3813217ec208SDavid C Somayajulu 					   "VF[%d]: Unable to set tx queue coalesce\n",
3814217ec208SDavid C Somayajulu 					   vf->abs_vf_id);
3815217ec208SDavid C Somayajulu 				goto out;
3816217ec208SDavid C Somayajulu 			}
3817217ec208SDavid C Somayajulu 		}
3818217ec208SDavid C Somayajulu 		vf->tx_coal = tx_coal;
3819217ec208SDavid C Somayajulu 	}
3820217ec208SDavid C Somayajulu 
3821217ec208SDavid C Somayajulu out:
3822217ec208SDavid C Somayajulu 	ecore_ptt_release(p_hwfn, p_ptt);
3823217ec208SDavid C Somayajulu 
3824217ec208SDavid C Somayajulu 	return rc;
3825217ec208SDavid C Somayajulu }
3826217ec208SDavid C Somayajulu 
3827217ec208SDavid C Somayajulu static enum _ecore_status_t
ecore_iov_vf_flr_poll_dorq(struct ecore_hwfn * p_hwfn,struct ecore_vf_info * p_vf,struct ecore_ptt * p_ptt)3828217ec208SDavid C Somayajulu ecore_iov_vf_flr_poll_dorq(struct ecore_hwfn *p_hwfn,
3829217ec208SDavid C Somayajulu 			   struct ecore_vf_info *p_vf,
3830217ec208SDavid C Somayajulu 			   struct ecore_ptt *p_ptt)
3831217ec208SDavid C Somayajulu {
3832217ec208SDavid C Somayajulu 	int cnt;
3833217ec208SDavid C Somayajulu 	u32 val;
3834217ec208SDavid C Somayajulu 
3835217ec208SDavid C Somayajulu 	ecore_fid_pretend(p_hwfn, p_ptt, (u16)p_vf->concrete_fid);
3836217ec208SDavid C Somayajulu 
3837217ec208SDavid C Somayajulu 	for (cnt = 0; cnt < 50; cnt++) {
3838217ec208SDavid C Somayajulu 		val = ecore_rd(p_hwfn, p_ptt, DORQ_REG_VF_USAGE_CNT);
3839217ec208SDavid C Somayajulu 		if (!val)
3840217ec208SDavid C Somayajulu 			break;
3841217ec208SDavid C Somayajulu 		OSAL_MSLEEP(20);
3842217ec208SDavid C Somayajulu 	}
3843217ec208SDavid C Somayajulu 	ecore_fid_pretend(p_hwfn, p_ptt, (u16)p_hwfn->hw_info.concrete_fid);
3844217ec208SDavid C Somayajulu 
3845217ec208SDavid C Somayajulu 	if (cnt == 50) {
3846217ec208SDavid C Somayajulu 		DP_ERR(p_hwfn, "VF[%d] - dorq failed to cleanup [usage 0x%08x]\n",
3847217ec208SDavid C Somayajulu 		       p_vf->abs_vf_id, val);
3848217ec208SDavid C Somayajulu 		return ECORE_TIMEOUT;
3849217ec208SDavid C Somayajulu 	}
3850217ec208SDavid C Somayajulu 
3851217ec208SDavid C Somayajulu 	return ECORE_SUCCESS;
3852217ec208SDavid C Somayajulu }
3853217ec208SDavid C Somayajulu 
3854217ec208SDavid C Somayajulu static enum _ecore_status_t
ecore_iov_vf_flr_poll_pbf(struct ecore_hwfn * p_hwfn,struct ecore_vf_info * p_vf,struct ecore_ptt * p_ptt)3855217ec208SDavid C Somayajulu ecore_iov_vf_flr_poll_pbf(struct ecore_hwfn *p_hwfn,
3856217ec208SDavid C Somayajulu 			  struct ecore_vf_info *p_vf,
3857217ec208SDavid C Somayajulu 			  struct ecore_ptt *p_ptt)
3858217ec208SDavid C Somayajulu {
3859217ec208SDavid C Somayajulu 	u32 cons[MAX_NUM_VOQS_E4], distance[MAX_NUM_VOQS_E4];
3860217ec208SDavid C Somayajulu 	int i, cnt;
3861217ec208SDavid C Somayajulu 
3862217ec208SDavid C Somayajulu 	/* Read initial consumers & producers */
3863217ec208SDavid C Somayajulu 	for (i = 0; i < MAX_NUM_VOQS_E4; i++) {
3864217ec208SDavid C Somayajulu 		u32 prod;
3865217ec208SDavid C Somayajulu 
3866217ec208SDavid C Somayajulu 		cons[i] = ecore_rd(p_hwfn, p_ptt,
3867217ec208SDavid C Somayajulu 				   PBF_REG_NUM_BLOCKS_ALLOCATED_CONS_VOQ0 +
3868217ec208SDavid C Somayajulu 				   i * 0x40);
3869217ec208SDavid C Somayajulu 		prod = ecore_rd(p_hwfn, p_ptt,
3870217ec208SDavid C Somayajulu 				PBF_REG_NUM_BLOCKS_ALLOCATED_PROD_VOQ0 +
3871217ec208SDavid C Somayajulu 				i * 0x40);
3872217ec208SDavid C Somayajulu 		distance[i] = prod - cons[i];
3873217ec208SDavid C Somayajulu 	}
3874217ec208SDavid C Somayajulu 
3875217ec208SDavid C Somayajulu 	/* Wait for consumers to pass the producers */
3876217ec208SDavid C Somayajulu 	i = 0;
3877217ec208SDavid C Somayajulu 	for (cnt = 0; cnt < 50; cnt++) {
3878217ec208SDavid C Somayajulu 		for (; i < MAX_NUM_VOQS_E4; i++) {
3879217ec208SDavid C Somayajulu 			u32 tmp;
3880217ec208SDavid C Somayajulu 
3881217ec208SDavid C Somayajulu 			tmp = ecore_rd(p_hwfn, p_ptt,
3882217ec208SDavid C Somayajulu 				       PBF_REG_NUM_BLOCKS_ALLOCATED_CONS_VOQ0 +
3883217ec208SDavid C Somayajulu 				       i * 0x40);
3884217ec208SDavid C Somayajulu 			if (distance[i] > tmp - cons[i])
3885217ec208SDavid C Somayajulu 				break;
3886217ec208SDavid C Somayajulu 		}
3887217ec208SDavid C Somayajulu 
3888217ec208SDavid C Somayajulu 		if (i == MAX_NUM_VOQS_E4)
3889217ec208SDavid C Somayajulu 			break;
3890217ec208SDavid C Somayajulu 
3891217ec208SDavid C Somayajulu 		OSAL_MSLEEP(20);
3892217ec208SDavid C Somayajulu 	}
3893217ec208SDavid C Somayajulu 
3894217ec208SDavid C Somayajulu 	if (cnt == 50) {
3895217ec208SDavid C Somayajulu 		DP_ERR(p_hwfn, "VF[%d] - pbf polling failed on VOQ %d\n",
3896217ec208SDavid C Somayajulu 		       p_vf->abs_vf_id, i);
3897217ec208SDavid C Somayajulu 		return ECORE_TIMEOUT;
3898217ec208SDavid C Somayajulu 	}
3899217ec208SDavid C Somayajulu 
3900217ec208SDavid C Somayajulu 	return ECORE_SUCCESS;
3901217ec208SDavid C Somayajulu }
3902217ec208SDavid C Somayajulu 
ecore_iov_vf_flr_poll(struct ecore_hwfn * p_hwfn,struct ecore_vf_info * p_vf,struct ecore_ptt * p_ptt)3903217ec208SDavid C Somayajulu static enum _ecore_status_t ecore_iov_vf_flr_poll(struct ecore_hwfn *p_hwfn,
3904217ec208SDavid C Somayajulu 						  struct ecore_vf_info *p_vf,
3905217ec208SDavid C Somayajulu 						  struct ecore_ptt *p_ptt)
3906217ec208SDavid C Somayajulu {
3907217ec208SDavid C Somayajulu 	enum _ecore_status_t rc;
3908217ec208SDavid C Somayajulu 
3909217ec208SDavid C Somayajulu 	/* TODO - add SRC and TM polling once we add storage IOV */
3910217ec208SDavid C Somayajulu 
3911217ec208SDavid C Somayajulu 	rc = ecore_iov_vf_flr_poll_dorq(p_hwfn, p_vf, p_ptt);
3912217ec208SDavid C Somayajulu 	if (rc)
3913217ec208SDavid C Somayajulu 		return rc;
3914217ec208SDavid C Somayajulu 
3915217ec208SDavid C Somayajulu 	rc = ecore_iov_vf_flr_poll_pbf(p_hwfn, p_vf, p_ptt);
3916217ec208SDavid C Somayajulu 	if (rc)
3917217ec208SDavid C Somayajulu 		return rc;
3918217ec208SDavid C Somayajulu 
3919217ec208SDavid C Somayajulu 	return ECORE_SUCCESS;
3920217ec208SDavid C Somayajulu }
3921217ec208SDavid C Somayajulu 
3922217ec208SDavid C Somayajulu static enum _ecore_status_t
ecore_iov_execute_vf_flr_cleanup(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u16 rel_vf_id,u32 * ack_vfs)3923217ec208SDavid C Somayajulu ecore_iov_execute_vf_flr_cleanup(struct ecore_hwfn *p_hwfn,
3924217ec208SDavid C Somayajulu 				 struct ecore_ptt  *p_ptt,
3925217ec208SDavid C Somayajulu 				 u16		   rel_vf_id,
3926217ec208SDavid C Somayajulu 				 u32		   *ack_vfs)
3927217ec208SDavid C Somayajulu {
3928217ec208SDavid C Somayajulu 	struct ecore_vf_info *p_vf;
3929217ec208SDavid C Somayajulu 	enum _ecore_status_t rc = ECORE_SUCCESS;
3930217ec208SDavid C Somayajulu 
3931217ec208SDavid C Somayajulu 	p_vf = ecore_iov_get_vf_info(p_hwfn, rel_vf_id, false);
3932217ec208SDavid C Somayajulu 	if (!p_vf)
3933217ec208SDavid C Somayajulu 		return ECORE_SUCCESS;
3934217ec208SDavid C Somayajulu 
3935217ec208SDavid C Somayajulu 	if (p_hwfn->pf_iov_info->pending_flr[rel_vf_id / 64] &
3936217ec208SDavid C Somayajulu 	    (1ULL << (rel_vf_id % 64))) {
3937217ec208SDavid C Somayajulu 		u16 vfid = p_vf->abs_vf_id;
3938217ec208SDavid C Somayajulu 
3939217ec208SDavid C Somayajulu 		/* TODO - should we lock channel? */
3940217ec208SDavid C Somayajulu 
3941217ec208SDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
3942217ec208SDavid C Somayajulu 			   "VF[%d] - Handling FLR\n", vfid);
3943217ec208SDavid C Somayajulu 
3944217ec208SDavid C Somayajulu 		ecore_iov_vf_cleanup(p_hwfn, p_vf);
3945217ec208SDavid C Somayajulu 
3946217ec208SDavid C Somayajulu 		/* If VF isn't active, no need for anything but SW */
3947217ec208SDavid C Somayajulu 		if (!p_vf->b_init)
3948217ec208SDavid C Somayajulu 			goto cleanup;
3949217ec208SDavid C Somayajulu 
3950217ec208SDavid C Somayajulu 		/* TODO - what to do in case of failure? */
3951217ec208SDavid C Somayajulu 		rc = ecore_iov_vf_flr_poll(p_hwfn, p_vf, p_ptt);
3952217ec208SDavid C Somayajulu 		if (rc != ECORE_SUCCESS)
3953217ec208SDavid C Somayajulu 			goto cleanup;
3954217ec208SDavid C Somayajulu 
3955217ec208SDavid C Somayajulu 		rc = ecore_final_cleanup(p_hwfn, p_ptt, vfid, true);
3956217ec208SDavid C Somayajulu 		if (rc) {
3957217ec208SDavid C Somayajulu 			/* TODO - what's now? What a mess.... */
3958217ec208SDavid C Somayajulu 			DP_ERR(p_hwfn, "Failed handle FLR of VF[%d]\n",
3959217ec208SDavid C Somayajulu 			       vfid);
3960217ec208SDavid C Somayajulu 			return rc;
3961217ec208SDavid C Somayajulu 		}
3962217ec208SDavid C Somayajulu 
3963217ec208SDavid C Somayajulu 		/* Workaround to make VF-PF channel ready, as FW
3964217ec208SDavid C Somayajulu 		 * doesn't do that as a part of FLR.
3965217ec208SDavid C Somayajulu 		 */
3966217ec208SDavid C Somayajulu 		REG_WR(p_hwfn,
3967217ec208SDavid C Somayajulu 		       GTT_BAR0_MAP_REG_USDM_RAM +
3968217ec208SDavid C Somayajulu 		       USTORM_VF_PF_CHANNEL_READY_OFFSET(vfid), 1);
3969217ec208SDavid C Somayajulu 
3970217ec208SDavid C Somayajulu 		/* VF_STOPPED has to be set only after final cleanup
3971217ec208SDavid C Somayajulu 		 * but prior to re-enabling the VF.
3972217ec208SDavid C Somayajulu 		 */
3973217ec208SDavid C Somayajulu 		p_vf->state = VF_STOPPED;
3974217ec208SDavid C Somayajulu 
3975217ec208SDavid C Somayajulu 		rc = ecore_iov_enable_vf_access(p_hwfn, p_ptt, p_vf);
3976217ec208SDavid C Somayajulu 		if (rc) {
3977217ec208SDavid C Somayajulu 			/* TODO - again, a mess... */
3978217ec208SDavid C Somayajulu 			DP_ERR(p_hwfn, "Failed to re-enable VF[%d] acces\n",
3979217ec208SDavid C Somayajulu 			       vfid);
3980217ec208SDavid C Somayajulu 			return rc;
3981217ec208SDavid C Somayajulu 		}
3982217ec208SDavid C Somayajulu cleanup:
3983217ec208SDavid C Somayajulu 		/* Mark VF for ack and clean pending state */
3984217ec208SDavid C Somayajulu 		if (p_vf->state == VF_RESET)
3985217ec208SDavid C Somayajulu 			p_vf->state = VF_STOPPED;
3986217ec208SDavid C Somayajulu 		ack_vfs[vfid / 32] |= (1 << (vfid % 32));
3987217ec208SDavid C Somayajulu 		p_hwfn->pf_iov_info->pending_flr[rel_vf_id / 64] &=
3988217ec208SDavid C Somayajulu 				~(1ULL << (rel_vf_id % 64));
3989217ec208SDavid C Somayajulu 		p_vf->vf_mbx.b_pending_msg = false;
3990217ec208SDavid C Somayajulu 	}
3991217ec208SDavid C Somayajulu 
3992217ec208SDavid C Somayajulu 	return rc;
3993217ec208SDavid C Somayajulu }
3994217ec208SDavid C Somayajulu 
ecore_iov_vf_flr_cleanup(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)3995217ec208SDavid C Somayajulu enum _ecore_status_t ecore_iov_vf_flr_cleanup(struct ecore_hwfn *p_hwfn,
3996217ec208SDavid C Somayajulu 					      struct ecore_ptt  *p_ptt)
3997217ec208SDavid C Somayajulu 
3998217ec208SDavid C Somayajulu {
3999217ec208SDavid C Somayajulu 	u32 ack_vfs[VF_MAX_STATIC / 32];
4000217ec208SDavid C Somayajulu 	enum _ecore_status_t rc = ECORE_SUCCESS;
4001217ec208SDavid C Somayajulu 	u16 i;
4002217ec208SDavid C Somayajulu 
4003217ec208SDavid C Somayajulu 	OSAL_MEMSET(ack_vfs, 0, sizeof(u32) * (VF_MAX_STATIC / 32));
4004217ec208SDavid C Somayajulu 
4005217ec208SDavid C Somayajulu 	/* Since BRB <-> PRS interface can't be tested as part of the flr
4006217ec208SDavid C Somayajulu 	 * polling due to HW limitations, simply sleep a bit. And since
4007217ec208SDavid C Somayajulu 	 * there's no need to wait per-vf, do it before looping.
4008217ec208SDavid C Somayajulu 	 */
4009217ec208SDavid C Somayajulu 	OSAL_MSLEEP(100);
4010217ec208SDavid C Somayajulu 
4011217ec208SDavid C Somayajulu 	for (i = 0; i < p_hwfn->p_dev->p_iov_info->total_vfs; i++)
4012217ec208SDavid C Somayajulu 		ecore_iov_execute_vf_flr_cleanup(p_hwfn, p_ptt, i, ack_vfs);
4013217ec208SDavid C Somayajulu 
4014217ec208SDavid C Somayajulu 	rc = ecore_mcp_ack_vf_flr(p_hwfn, p_ptt, ack_vfs);
4015217ec208SDavid C Somayajulu 	return rc;
4016217ec208SDavid C Somayajulu }
4017217ec208SDavid C Somayajulu 
4018217ec208SDavid C Somayajulu #ifndef LINUX_REMOVE
4019217ec208SDavid C Somayajulu enum _ecore_status_t
ecore_iov_single_vf_flr_cleanup(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u16 rel_vf_id)4020217ec208SDavid C Somayajulu ecore_iov_single_vf_flr_cleanup(struct ecore_hwfn *p_hwfn,
4021217ec208SDavid C Somayajulu 				struct ecore_ptt  *p_ptt,
4022217ec208SDavid C Somayajulu 				u16		  rel_vf_id)
4023217ec208SDavid C Somayajulu 
4024217ec208SDavid C Somayajulu {
4025217ec208SDavid C Somayajulu 	u32 ack_vfs[VF_MAX_STATIC / 32];
4026217ec208SDavid C Somayajulu 	enum _ecore_status_t rc = ECORE_SUCCESS;
4027217ec208SDavid C Somayajulu 
4028217ec208SDavid C Somayajulu 	OSAL_MEMSET(ack_vfs, 0, sizeof(u32) * (VF_MAX_STATIC / 32));
4029217ec208SDavid C Somayajulu 
4030217ec208SDavid C Somayajulu 	/* Wait instead of polling the BRB <-> PRS interface */
4031217ec208SDavid C Somayajulu 	OSAL_MSLEEP(100);
4032217ec208SDavid C Somayajulu 
4033217ec208SDavid C Somayajulu 	ecore_iov_execute_vf_flr_cleanup(p_hwfn, p_ptt, rel_vf_id, ack_vfs);
4034217ec208SDavid C Somayajulu 
4035217ec208SDavid C Somayajulu 	rc = ecore_mcp_ack_vf_flr(p_hwfn, p_ptt, ack_vfs);
4036217ec208SDavid C Somayajulu 	return rc;
4037217ec208SDavid C Somayajulu }
4038217ec208SDavid C Somayajulu #endif
4039217ec208SDavid C Somayajulu 
ecore_iov_mark_vf_flr(struct ecore_hwfn * p_hwfn,u32 * p_disabled_vfs)4040217ec208SDavid C Somayajulu bool ecore_iov_mark_vf_flr(struct ecore_hwfn *p_hwfn,
4041217ec208SDavid C Somayajulu 			  u32 *p_disabled_vfs)
4042217ec208SDavid C Somayajulu {
4043217ec208SDavid C Somayajulu 	bool found = false;
4044217ec208SDavid C Somayajulu 	u16 i;
4045217ec208SDavid C Somayajulu 
4046217ec208SDavid C Somayajulu 	DP_VERBOSE(p_hwfn, ECORE_MSG_IOV, "Marking FLR-ed VFs\n");
4047217ec208SDavid C Somayajulu 	for (i = 0; i < (VF_MAX_STATIC / 32); i++)
4048217ec208SDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
4049217ec208SDavid C Somayajulu 			   "[%08x,...,%08x]: %08x\n",
4050217ec208SDavid C Somayajulu 			   i * 32, (i + 1) * 32 - 1, p_disabled_vfs[i]);
4051217ec208SDavid C Somayajulu 
4052217ec208SDavid C Somayajulu 	if (!p_hwfn->p_dev->p_iov_info) {
4053217ec208SDavid C Somayajulu 		DP_NOTICE(p_hwfn, true, "VF flr but no IOV\n");
4054217ec208SDavid C Somayajulu 		return false;
4055217ec208SDavid C Somayajulu 	}
4056217ec208SDavid C Somayajulu 
4057217ec208SDavid C Somayajulu 	/* Mark VFs */
4058217ec208SDavid C Somayajulu 	for (i = 0; i < p_hwfn->p_dev->p_iov_info->total_vfs; i++) {
4059217ec208SDavid C Somayajulu 		struct ecore_vf_info *p_vf;
4060217ec208SDavid C Somayajulu 		u8 vfid;
4061217ec208SDavid C Somayajulu 
4062217ec208SDavid C Somayajulu 		p_vf = ecore_iov_get_vf_info(p_hwfn, i, false);
4063217ec208SDavid C Somayajulu 		if (!p_vf)
4064217ec208SDavid C Somayajulu 			continue;
4065217ec208SDavid C Somayajulu 
4066217ec208SDavid C Somayajulu 		vfid = p_vf->abs_vf_id;
4067217ec208SDavid C Somayajulu 		if ((1 << (vfid % 32)) & p_disabled_vfs[vfid / 32]) {
4068217ec208SDavid C Somayajulu 			u64 *p_flr =  p_hwfn->pf_iov_info->pending_flr;
4069217ec208SDavid C Somayajulu 			u16 rel_vf_id = p_vf->relative_vf_id;
4070217ec208SDavid C Somayajulu 
4071217ec208SDavid C Somayajulu 			DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
4072217ec208SDavid C Somayajulu 				   "VF[%d] [rel %d] got FLR-ed\n",
4073217ec208SDavid C Somayajulu 				   vfid, rel_vf_id);
4074217ec208SDavid C Somayajulu 
4075217ec208SDavid C Somayajulu 			p_vf->state = VF_RESET;
4076217ec208SDavid C Somayajulu 
4077217ec208SDavid C Somayajulu 			/* No need to lock here, since pending_flr should
4078217ec208SDavid C Somayajulu 			 * only change here and before ACKing MFw. Since
4079217ec208SDavid C Somayajulu 			 * MFW will not trigger an additional attention for
4080217ec208SDavid C Somayajulu 			 * VF flr until ACKs, we're safe.
4081217ec208SDavid C Somayajulu 			 */
4082217ec208SDavid C Somayajulu 			p_flr[rel_vf_id / 64] |= 1ULL << (rel_vf_id % 64);
4083217ec208SDavid C Somayajulu 			found = true;
4084217ec208SDavid C Somayajulu 		}
4085217ec208SDavid C Somayajulu 	}
4086217ec208SDavid C Somayajulu 
4087217ec208SDavid C Somayajulu 	return found;
4088217ec208SDavid C Somayajulu }
4089217ec208SDavid C Somayajulu 
ecore_iov_get_link(struct ecore_hwfn * p_hwfn,u16 vfid,struct ecore_mcp_link_params * p_params,struct ecore_mcp_link_state * p_link,struct ecore_mcp_link_capabilities * p_caps)4090217ec208SDavid C Somayajulu void ecore_iov_get_link(struct ecore_hwfn *p_hwfn,
4091217ec208SDavid C Somayajulu 			u16 vfid,
4092217ec208SDavid C Somayajulu 			struct ecore_mcp_link_params *p_params,
4093217ec208SDavid C Somayajulu 			struct ecore_mcp_link_state *p_link,
4094217ec208SDavid C Somayajulu 			struct ecore_mcp_link_capabilities *p_caps)
4095217ec208SDavid C Somayajulu {
4096217ec208SDavid C Somayajulu 	struct ecore_vf_info *p_vf = ecore_iov_get_vf_info(p_hwfn, vfid, false);
4097217ec208SDavid C Somayajulu 	struct ecore_bulletin_content *p_bulletin;
4098217ec208SDavid C Somayajulu 
4099217ec208SDavid C Somayajulu 	if (!p_vf)
4100217ec208SDavid C Somayajulu 		return;
4101217ec208SDavid C Somayajulu 
4102217ec208SDavid C Somayajulu 	p_bulletin = p_vf->bulletin.p_virt;
4103217ec208SDavid C Somayajulu 
4104217ec208SDavid C Somayajulu 	if (p_params)
4105217ec208SDavid C Somayajulu 		__ecore_vf_get_link_params(p_params, p_bulletin);
4106217ec208SDavid C Somayajulu 	if (p_link)
4107217ec208SDavid C Somayajulu 		__ecore_vf_get_link_state(p_link, p_bulletin);
4108217ec208SDavid C Somayajulu 	if (p_caps)
4109217ec208SDavid C Somayajulu 		__ecore_vf_get_link_caps(p_caps, p_bulletin);
4110217ec208SDavid C Somayajulu }
4111217ec208SDavid C Somayajulu 
ecore_iov_process_mbx_req(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,int vfid)4112217ec208SDavid C Somayajulu void ecore_iov_process_mbx_req(struct ecore_hwfn    *p_hwfn,
4113217ec208SDavid C Somayajulu 			       struct ecore_ptt     *p_ptt,
4114217ec208SDavid C Somayajulu 			       int vfid)
4115217ec208SDavid C Somayajulu {
4116217ec208SDavid C Somayajulu 	struct ecore_iov_vf_mbx *mbx;
4117217ec208SDavid C Somayajulu 	struct ecore_vf_info *p_vf;
4118217ec208SDavid C Somayajulu 
4119217ec208SDavid C Somayajulu 	p_vf = ecore_iov_get_vf_info(p_hwfn, (u16)vfid, true);
4120217ec208SDavid C Somayajulu 	if (!p_vf)
4121217ec208SDavid C Somayajulu 		return;
4122217ec208SDavid C Somayajulu 
4123217ec208SDavid C Somayajulu 	mbx = &p_vf->vf_mbx;
4124217ec208SDavid C Somayajulu 
4125217ec208SDavid C Somayajulu 	/* ecore_iov_process_mbx_request */
4126217ec208SDavid C Somayajulu #ifndef CONFIG_ECORE_SW_CHANNEL
4127217ec208SDavid C Somayajulu 	if (!mbx->b_pending_msg) {
4128217ec208SDavid C Somayajulu 		DP_NOTICE(p_hwfn, true,
4129217ec208SDavid C Somayajulu 			  "VF[%02x]: Trying to process mailbox message when none is pending\n",
4130217ec208SDavid C Somayajulu 			  p_vf->abs_vf_id);
4131217ec208SDavid C Somayajulu 		return;
4132217ec208SDavid C Somayajulu 	}
4133217ec208SDavid C Somayajulu 	mbx->b_pending_msg = false;
4134217ec208SDavid C Somayajulu #endif
4135217ec208SDavid C Somayajulu 
4136217ec208SDavid C Somayajulu 	mbx->first_tlv = mbx->req_virt->first_tlv;
4137217ec208SDavid C Somayajulu 
4138217ec208SDavid C Somayajulu 	DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
4139217ec208SDavid C Somayajulu 		   "VF[%02x]: Processing mailbox message [type %04x]\n",
4140217ec208SDavid C Somayajulu 		   p_vf->abs_vf_id, mbx->first_tlv.tl.type);
4141217ec208SDavid C Somayajulu 
4142217ec208SDavid C Somayajulu 	OSAL_IOV_VF_MSG_TYPE(p_hwfn,
4143217ec208SDavid C Somayajulu                              p_vf->relative_vf_id,
4144217ec208SDavid C Somayajulu                              mbx->first_tlv.tl.type);
4145217ec208SDavid C Somayajulu 
4146217ec208SDavid C Somayajulu 	/* Lock the per vf op mutex and note the locker's identity.
4147217ec208SDavid C Somayajulu 	 * The unlock will take place in mbx response.
4148217ec208SDavid C Somayajulu 	 */
4149217ec208SDavid C Somayajulu 	ecore_iov_lock_vf_pf_channel(p_hwfn, p_vf,
4150217ec208SDavid C Somayajulu 				     mbx->first_tlv.tl.type);
4151217ec208SDavid C Somayajulu 
4152217ec208SDavid C Somayajulu 	/* check if tlv type is known */
4153217ec208SDavid C Somayajulu 	if (ecore_iov_tlv_supported(mbx->first_tlv.tl.type) &&
4154217ec208SDavid C Somayajulu 	    !p_vf->b_malicious) {
4155217ec208SDavid C Somayajulu 		/* switch on the opcode */
4156217ec208SDavid C Somayajulu 		switch (mbx->first_tlv.tl.type) {
4157217ec208SDavid C Somayajulu 		case CHANNEL_TLV_ACQUIRE:
4158217ec208SDavid C Somayajulu 			ecore_iov_vf_mbx_acquire(p_hwfn, p_ptt, p_vf);
4159217ec208SDavid C Somayajulu 			break;
4160217ec208SDavid C Somayajulu 		case CHANNEL_TLV_VPORT_START:
4161217ec208SDavid C Somayajulu 			ecore_iov_vf_mbx_start_vport(p_hwfn, p_ptt, p_vf);
4162217ec208SDavid C Somayajulu 			break;
4163217ec208SDavid C Somayajulu 		case CHANNEL_TLV_VPORT_TEARDOWN:
4164217ec208SDavid C Somayajulu 			ecore_iov_vf_mbx_stop_vport(p_hwfn, p_ptt, p_vf);
4165217ec208SDavid C Somayajulu 			break;
4166217ec208SDavid C Somayajulu 		case CHANNEL_TLV_START_RXQ:
4167217ec208SDavid C Somayajulu 			ecore_iov_vf_mbx_start_rxq(p_hwfn, p_ptt, p_vf);
4168217ec208SDavid C Somayajulu 			break;
4169217ec208SDavid C Somayajulu 		case CHANNEL_TLV_START_TXQ:
4170217ec208SDavid C Somayajulu 			ecore_iov_vf_mbx_start_txq(p_hwfn, p_ptt, p_vf);
4171217ec208SDavid C Somayajulu 			break;
4172217ec208SDavid C Somayajulu 		case CHANNEL_TLV_STOP_RXQS:
4173217ec208SDavid C Somayajulu 			ecore_iov_vf_mbx_stop_rxqs(p_hwfn, p_ptt, p_vf);
4174217ec208SDavid C Somayajulu 			break;
4175217ec208SDavid C Somayajulu 		case CHANNEL_TLV_STOP_TXQS:
4176217ec208SDavid C Somayajulu 			ecore_iov_vf_mbx_stop_txqs(p_hwfn, p_ptt, p_vf);
4177217ec208SDavid C Somayajulu 			break;
4178217ec208SDavid C Somayajulu 		case CHANNEL_TLV_UPDATE_RXQ:
4179217ec208SDavid C Somayajulu 			ecore_iov_vf_mbx_update_rxqs(p_hwfn, p_ptt, p_vf);
4180217ec208SDavid C Somayajulu 			break;
4181217ec208SDavid C Somayajulu 		case CHANNEL_TLV_VPORT_UPDATE:
4182217ec208SDavid C Somayajulu 			ecore_iov_vf_mbx_vport_update(p_hwfn, p_ptt, p_vf);
4183217ec208SDavid C Somayajulu 			break;
4184217ec208SDavid C Somayajulu 		case CHANNEL_TLV_UCAST_FILTER:
4185217ec208SDavid C Somayajulu 			ecore_iov_vf_mbx_ucast_filter(p_hwfn, p_ptt, p_vf);
4186217ec208SDavid C Somayajulu 			break;
4187217ec208SDavid C Somayajulu 		case CHANNEL_TLV_CLOSE:
4188217ec208SDavid C Somayajulu 			ecore_iov_vf_mbx_close(p_hwfn, p_ptt, p_vf);
4189217ec208SDavid C Somayajulu 			break;
4190217ec208SDavid C Somayajulu 		case CHANNEL_TLV_INT_CLEANUP:
4191217ec208SDavid C Somayajulu 			ecore_iov_vf_mbx_int_cleanup(p_hwfn, p_ptt, p_vf);
4192217ec208SDavid C Somayajulu 			break;
4193217ec208SDavid C Somayajulu 		case CHANNEL_TLV_RELEASE:
4194217ec208SDavid C Somayajulu 			ecore_iov_vf_mbx_release(p_hwfn, p_ptt, p_vf);
4195217ec208SDavid C Somayajulu 			break;
4196217ec208SDavid C Somayajulu 		case CHANNEL_TLV_UPDATE_TUNN_PARAM:
4197217ec208SDavid C Somayajulu 			ecore_iov_vf_mbx_update_tunn_param(p_hwfn, p_ptt, p_vf);
4198217ec208SDavid C Somayajulu 			break;
4199217ec208SDavid C Somayajulu 		case CHANNEL_TLV_COALESCE_UPDATE:
4200217ec208SDavid C Somayajulu 			ecore_iov_vf_pf_set_coalesce(p_hwfn, p_ptt, p_vf);
4201217ec208SDavid C Somayajulu 			break;
4202217ec208SDavid C Somayajulu 		case CHANNEL_TLV_COALESCE_READ:
4203217ec208SDavid C Somayajulu 			ecore_iov_vf_pf_get_coalesce(p_hwfn, p_ptt, p_vf);
4204217ec208SDavid C Somayajulu 			break;
4205217ec208SDavid C Somayajulu 		}
4206217ec208SDavid C Somayajulu 	} else if (ecore_iov_tlv_supported(mbx->first_tlv.tl.type)) {
4207217ec208SDavid C Somayajulu 		/* If we've received a message from a VF we consider malicious
4208217ec208SDavid C Somayajulu 		 * we ignore the messasge unless it's one for RELEASE, in which
4209217ec208SDavid C Somayajulu 		 * case we'll let it have the benefit of doubt, allowing the
4210217ec208SDavid C Somayajulu 		 * next loaded driver to start again.
4211217ec208SDavid C Somayajulu 		 */
4212217ec208SDavid C Somayajulu 		if (mbx->first_tlv.tl.type == CHANNEL_TLV_RELEASE) {
4213217ec208SDavid C Somayajulu 			/* TODO - initiate FLR, remove malicious indication */
4214217ec208SDavid C Somayajulu 			DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
4215217ec208SDavid C Somayajulu 				   "VF [%02x] - considered malicious, but wanted to RELEASE. TODO\n",
4216217ec208SDavid C Somayajulu 				   p_vf->abs_vf_id);
4217217ec208SDavid C Somayajulu 		} else {
4218217ec208SDavid C Somayajulu 			DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
4219217ec208SDavid C Somayajulu 				   "VF [%02x] - considered malicious; Ignoring TLV [%04x]\n",
4220217ec208SDavid C Somayajulu 				   p_vf->abs_vf_id, mbx->first_tlv.tl.type);
4221217ec208SDavid C Somayajulu 		}
4222217ec208SDavid C Somayajulu 
4223217ec208SDavid C Somayajulu 		ecore_iov_prepare_resp(p_hwfn, p_ptt, p_vf,
4224217ec208SDavid C Somayajulu 				       mbx->first_tlv.tl.type,
4225217ec208SDavid C Somayajulu 				       sizeof(struct pfvf_def_resp_tlv),
4226217ec208SDavid C Somayajulu 				       PFVF_STATUS_MALICIOUS);
4227217ec208SDavid C Somayajulu 	} else {
4228217ec208SDavid C Somayajulu 		/* unknown TLV - this may belong to a VF driver from the future
4229217ec208SDavid C Somayajulu 		 * - a version written after this PF driver was written, which
4230217ec208SDavid C Somayajulu 		 * supports features unknown as of yet. Too bad since we don't
4231217ec208SDavid C Somayajulu 		 * support them. Or this may be because someone wrote a crappy
4232217ec208SDavid C Somayajulu 		 * VF driver and is sending garbage over the channel.
4233217ec208SDavid C Somayajulu 		 */
4234217ec208SDavid C Somayajulu 		DP_NOTICE(p_hwfn, false,
4235217ec208SDavid C Somayajulu 			  "VF[%02x]: unknown TLV. type %04x length %04x padding %08x reply address %llu\n",
4236217ec208SDavid C Somayajulu 			  p_vf->abs_vf_id,
4237217ec208SDavid C Somayajulu 			  mbx->first_tlv.tl.type,
4238217ec208SDavid C Somayajulu 			  mbx->first_tlv.tl.length,
4239217ec208SDavid C Somayajulu 			  mbx->first_tlv.padding,
4240217ec208SDavid C Somayajulu 			  (unsigned long long)mbx->first_tlv.reply_address);
4241217ec208SDavid C Somayajulu 
4242217ec208SDavid C Somayajulu 		/* Try replying in case reply address matches the acquisition's
4243217ec208SDavid C Somayajulu 		 * posted address.
4244217ec208SDavid C Somayajulu 		 */
4245217ec208SDavid C Somayajulu 		if (p_vf->acquire.first_tlv.reply_address &&
4246217ec208SDavid C Somayajulu 		    (mbx->first_tlv.reply_address ==
4247217ec208SDavid C Somayajulu 		     p_vf->acquire.first_tlv.reply_address))
4248217ec208SDavid C Somayajulu 			ecore_iov_prepare_resp(p_hwfn, p_ptt, p_vf,
4249217ec208SDavid C Somayajulu 					       mbx->first_tlv.tl.type,
4250217ec208SDavid C Somayajulu 					       sizeof(struct pfvf_def_resp_tlv),
4251217ec208SDavid C Somayajulu 					       PFVF_STATUS_NOT_SUPPORTED);
4252217ec208SDavid C Somayajulu 		else
4253217ec208SDavid C Somayajulu 			DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
4254217ec208SDavid C Somayajulu 				   "VF[%02x]: Can't respond to TLV - no valid reply address\n",
4255217ec208SDavid C Somayajulu 				   p_vf->abs_vf_id);
4256217ec208SDavid C Somayajulu 	}
4257217ec208SDavid C Somayajulu 
4258217ec208SDavid C Somayajulu 	ecore_iov_unlock_vf_pf_channel(p_hwfn, p_vf,
4259217ec208SDavid C Somayajulu 				       mbx->first_tlv.tl.type);
4260217ec208SDavid C Somayajulu 
4261217ec208SDavid C Somayajulu #ifdef CONFIG_ECORE_SW_CHANNEL
4262217ec208SDavid C Somayajulu 	mbx->sw_mbx.mbx_state = VF_PF_RESPONSE_READY;
4263217ec208SDavid C Somayajulu 	mbx->sw_mbx.response_offset = 0;
4264217ec208SDavid C Somayajulu #endif
4265217ec208SDavid C Somayajulu }
4266217ec208SDavid C Somayajulu 
ecore_iov_pf_get_pending_events(struct ecore_hwfn * p_hwfn,u64 * events)4267217ec208SDavid C Somayajulu void ecore_iov_pf_get_pending_events(struct ecore_hwfn *p_hwfn,
4268217ec208SDavid C Somayajulu 				     u64 *events)
4269217ec208SDavid C Somayajulu {
4270217ec208SDavid C Somayajulu 	int i;
4271217ec208SDavid C Somayajulu 
4272217ec208SDavid C Somayajulu 	OSAL_MEM_ZERO(events, sizeof(u64) * ECORE_VF_ARRAY_LENGTH);
4273217ec208SDavid C Somayajulu 
4274217ec208SDavid C Somayajulu 	ecore_for_each_vf(p_hwfn, i) {
4275217ec208SDavid C Somayajulu 		struct ecore_vf_info *p_vf;
4276217ec208SDavid C Somayajulu 
4277217ec208SDavid C Somayajulu 		p_vf = &p_hwfn->pf_iov_info->vfs_array[i];
4278217ec208SDavid C Somayajulu 		if (p_vf->vf_mbx.b_pending_msg)
4279217ec208SDavid C Somayajulu 			events[i / 64] |= 1ULL << (i % 64);
4280217ec208SDavid C Somayajulu 	}
4281217ec208SDavid C Somayajulu }
4282217ec208SDavid C Somayajulu 
4283217ec208SDavid C Somayajulu static struct ecore_vf_info *
ecore_sriov_get_vf_from_absid(struct ecore_hwfn * p_hwfn,u16 abs_vfid)4284217ec208SDavid C Somayajulu ecore_sriov_get_vf_from_absid(struct ecore_hwfn *p_hwfn, u16 abs_vfid)
4285217ec208SDavid C Somayajulu {
4286217ec208SDavid C Somayajulu 	u8 min = (u8)p_hwfn->p_dev->p_iov_info->first_vf_in_pf;
4287217ec208SDavid C Somayajulu 
4288217ec208SDavid C Somayajulu 	if (!_ecore_iov_pf_sanity_check(p_hwfn, (int)abs_vfid - min, false)) {
4289217ec208SDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
4290217ec208SDavid C Somayajulu 			   "Got indication for VF [abs 0x%08x] that cannot be handled by PF\n",
4291217ec208SDavid C Somayajulu 			   abs_vfid);
4292217ec208SDavid C Somayajulu 		return OSAL_NULL;
4293217ec208SDavid C Somayajulu 	}
4294217ec208SDavid C Somayajulu 
4295217ec208SDavid C Somayajulu 	return &p_hwfn->pf_iov_info->vfs_array[(u8)abs_vfid - min];
4296217ec208SDavid C Somayajulu }
4297217ec208SDavid C Somayajulu 
ecore_sriov_vfpf_msg(struct ecore_hwfn * p_hwfn,u16 abs_vfid,struct regpair * vf_msg)4298217ec208SDavid C Somayajulu static enum _ecore_status_t ecore_sriov_vfpf_msg(struct ecore_hwfn *p_hwfn,
4299217ec208SDavid C Somayajulu 						 u16 abs_vfid,
4300217ec208SDavid C Somayajulu 						 struct regpair *vf_msg)
4301217ec208SDavid C Somayajulu {
4302217ec208SDavid C Somayajulu 	struct ecore_vf_info *p_vf = ecore_sriov_get_vf_from_absid(p_hwfn,
4303217ec208SDavid C Somayajulu 								   abs_vfid);
4304217ec208SDavid C Somayajulu 
4305217ec208SDavid C Somayajulu 	if (!p_vf)
4306217ec208SDavid C Somayajulu 		return ECORE_SUCCESS;
4307217ec208SDavid C Somayajulu 
4308217ec208SDavid C Somayajulu 	/* List the physical address of the request so that handler
4309217ec208SDavid C Somayajulu 	 * could later on copy the message from it.
4310217ec208SDavid C Somayajulu 	 */
4311217ec208SDavid C Somayajulu 	p_vf->vf_mbx.pending_req = (((u64)vf_msg->hi) << 32) |
4312217ec208SDavid C Somayajulu 				   vf_msg->lo;
4313217ec208SDavid C Somayajulu 
4314217ec208SDavid C Somayajulu 	p_vf->vf_mbx.b_pending_msg = true;
4315217ec208SDavid C Somayajulu 
4316217ec208SDavid C Somayajulu 	return OSAL_PF_VF_MSG(p_hwfn, p_vf->relative_vf_id);
4317217ec208SDavid C Somayajulu }
4318217ec208SDavid C Somayajulu 
ecore_sriov_vfpf_malicious(struct ecore_hwfn * p_hwfn,struct malicious_vf_eqe_data * p_data)4319217ec208SDavid C Somayajulu static void ecore_sriov_vfpf_malicious(struct ecore_hwfn *p_hwfn,
4320217ec208SDavid C Somayajulu 				       struct malicious_vf_eqe_data *p_data)
4321217ec208SDavid C Somayajulu {
4322217ec208SDavid C Somayajulu 	struct ecore_vf_info *p_vf;
4323217ec208SDavid C Somayajulu 
4324217ec208SDavid C Somayajulu 	p_vf = ecore_sriov_get_vf_from_absid(p_hwfn, p_data->vf_id);
4325217ec208SDavid C Somayajulu 
4326217ec208SDavid C Somayajulu 	if (!p_vf)
4327217ec208SDavid C Somayajulu 		return;
4328217ec208SDavid C Somayajulu 
4329217ec208SDavid C Somayajulu 	if (!p_vf->b_malicious) {
4330217ec208SDavid C Somayajulu 		DP_NOTICE(p_hwfn, false,
4331217ec208SDavid C Somayajulu 			  "VF [%d] - Malicious behavior [%02x]\n",
4332217ec208SDavid C Somayajulu 			  p_vf->abs_vf_id, p_data->err_id);
4333217ec208SDavid C Somayajulu 
4334217ec208SDavid C Somayajulu 		p_vf->b_malicious = true;
4335217ec208SDavid C Somayajulu 	} else {
4336217ec208SDavid C Somayajulu 		DP_INFO(p_hwfn,
4337217ec208SDavid C Somayajulu 			"VF [%d] - Malicious behavior [%02x]\n",
4338217ec208SDavid C Somayajulu 			p_vf->abs_vf_id, p_data->err_id);
4339217ec208SDavid C Somayajulu 	}
4340217ec208SDavid C Somayajulu 
4341217ec208SDavid C Somayajulu 	OSAL_PF_VF_MALICIOUS(p_hwfn, p_vf->relative_vf_id);
4342217ec208SDavid C Somayajulu }
4343217ec208SDavid C Somayajulu 
ecore_sriov_eqe_event(struct ecore_hwfn * p_hwfn,u8 opcode,__le16 echo,union event_ring_data * data,u8 OSAL_UNUSED fw_return_code)4344217ec208SDavid C Somayajulu static enum _ecore_status_t ecore_sriov_eqe_event(struct ecore_hwfn *p_hwfn,
4345217ec208SDavid C Somayajulu 						  u8 opcode,
4346217ec208SDavid C Somayajulu 						  __le16 echo,
4347217ec208SDavid C Somayajulu 						  union event_ring_data *data,
4348217ec208SDavid C Somayajulu 						  u8 OSAL_UNUSED fw_return_code)
4349217ec208SDavid C Somayajulu {
4350217ec208SDavid C Somayajulu 	switch (opcode) {
4351217ec208SDavid C Somayajulu 	case COMMON_EVENT_VF_PF_CHANNEL:
4352217ec208SDavid C Somayajulu 		return ecore_sriov_vfpf_msg(p_hwfn, OSAL_LE16_TO_CPU(echo),
4353217ec208SDavid C Somayajulu 					    &data->vf_pf_channel.msg_addr);
4354217ec208SDavid C Somayajulu 	case COMMON_EVENT_VF_FLR:
4355217ec208SDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
4356217ec208SDavid C Somayajulu 			   "VF-FLR is still not supported\n");
4357217ec208SDavid C Somayajulu 		return ECORE_SUCCESS;
4358217ec208SDavid C Somayajulu 	case COMMON_EVENT_MALICIOUS_VF:
4359217ec208SDavid C Somayajulu 		ecore_sriov_vfpf_malicious(p_hwfn, &data->malicious_vf);
4360217ec208SDavid C Somayajulu 		return ECORE_SUCCESS;
4361217ec208SDavid C Somayajulu 	default:
4362217ec208SDavid C Somayajulu 		DP_INFO(p_hwfn->p_dev, "Unknown sriov eqe event 0x%02x\n",
4363217ec208SDavid C Somayajulu 			opcode);
4364217ec208SDavid C Somayajulu 		return ECORE_INVAL;
4365217ec208SDavid C Somayajulu 	}
4366217ec208SDavid C Somayajulu }
4367217ec208SDavid C Somayajulu 
4368217ec208SDavid C Somayajulu #ifndef LINUX_REMOVE
ecore_iov_is_vf_pending_flr(struct ecore_hwfn * p_hwfn,u16 rel_vf_id)4369217ec208SDavid C Somayajulu bool ecore_iov_is_vf_pending_flr(struct ecore_hwfn *p_hwfn,
4370217ec208SDavid C Somayajulu 				 u16		   rel_vf_id)
4371217ec208SDavid C Somayajulu {
4372217ec208SDavid C Somayajulu 	return !!(p_hwfn->pf_iov_info->pending_flr[rel_vf_id / 64] &
4373217ec208SDavid C Somayajulu 		  (1ULL << (rel_vf_id % 64)));
4374217ec208SDavid C Somayajulu }
4375217ec208SDavid C Somayajulu #endif
4376217ec208SDavid C Somayajulu 
ecore_iov_get_next_active_vf(struct ecore_hwfn * p_hwfn,u16 rel_vf_id)4377217ec208SDavid C Somayajulu u16 ecore_iov_get_next_active_vf(struct ecore_hwfn *p_hwfn, u16 rel_vf_id)
4378217ec208SDavid C Somayajulu {
4379217ec208SDavid C Somayajulu 	struct ecore_hw_sriov_info *p_iov = p_hwfn->p_dev->p_iov_info;
4380217ec208SDavid C Somayajulu 	u16 i;
4381217ec208SDavid C Somayajulu 
4382217ec208SDavid C Somayajulu 	if (!p_iov)
4383217ec208SDavid C Somayajulu 		goto out;
4384217ec208SDavid C Somayajulu 
4385217ec208SDavid C Somayajulu 	for (i = rel_vf_id; i < p_iov->total_vfs; i++)
4386217ec208SDavid C Somayajulu 		if (ecore_iov_is_valid_vfid(p_hwfn, rel_vf_id, true, false))
4387217ec208SDavid C Somayajulu 			return i;
4388217ec208SDavid C Somayajulu 
4389217ec208SDavid C Somayajulu out:
4390217ec208SDavid C Somayajulu 	return MAX_NUM_VFS_E4;
4391217ec208SDavid C Somayajulu }
4392217ec208SDavid C Somayajulu 
ecore_iov_copy_vf_msg(struct ecore_hwfn * p_hwfn,struct ecore_ptt * ptt,int vfid)4393217ec208SDavid C Somayajulu enum _ecore_status_t ecore_iov_copy_vf_msg(struct ecore_hwfn *p_hwfn,
4394217ec208SDavid C Somayajulu 					   struct ecore_ptt *ptt,
4395217ec208SDavid C Somayajulu 					   int vfid)
4396217ec208SDavid C Somayajulu {
4397217ec208SDavid C Somayajulu 	struct ecore_dmae_params params;
4398217ec208SDavid C Somayajulu 	struct ecore_vf_info *vf_info;
4399217ec208SDavid C Somayajulu 
4400217ec208SDavid C Somayajulu 	vf_info = ecore_iov_get_vf_info(p_hwfn, (u16)vfid, true);
4401217ec208SDavid C Somayajulu 	if (!vf_info)
4402217ec208SDavid C Somayajulu 		return ECORE_INVAL;
4403217ec208SDavid C Somayajulu 
4404217ec208SDavid C Somayajulu 	OSAL_MEMSET(&params, 0, sizeof(struct ecore_dmae_params));
4405217ec208SDavid C Somayajulu 	params.flags = ECORE_DMAE_FLAG_VF_SRC |
4406217ec208SDavid C Somayajulu 		       ECORE_DMAE_FLAG_COMPLETION_DST;
4407217ec208SDavid C Somayajulu 	params.src_vfid = vf_info->abs_vf_id;
4408217ec208SDavid C Somayajulu 
4409217ec208SDavid C Somayajulu 	if (ecore_dmae_host2host(p_hwfn, ptt,
4410217ec208SDavid C Somayajulu 				 vf_info->vf_mbx.pending_req,
4411217ec208SDavid C Somayajulu 				 vf_info->vf_mbx.req_phys,
4412217ec208SDavid C Somayajulu 				 sizeof(union vfpf_tlvs) / 4,
4413217ec208SDavid C Somayajulu 				 &params)) {
4414217ec208SDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
4415217ec208SDavid C Somayajulu 			   "Failed to copy message from VF 0x%02x\n",
4416217ec208SDavid C Somayajulu 			   vfid);
4417217ec208SDavid C Somayajulu 
4418217ec208SDavid C Somayajulu 		return ECORE_IO;
4419217ec208SDavid C Somayajulu 	}
4420217ec208SDavid C Somayajulu 
4421217ec208SDavid C Somayajulu 	return ECORE_SUCCESS;
4422217ec208SDavid C Somayajulu }
4423217ec208SDavid C Somayajulu 
ecore_iov_bulletin_set_forced_mac(struct ecore_hwfn * p_hwfn,u8 * mac,int vfid)4424217ec208SDavid C Somayajulu void ecore_iov_bulletin_set_forced_mac(struct ecore_hwfn *p_hwfn,
4425217ec208SDavid C Somayajulu 				       u8 *mac, int vfid)
4426217ec208SDavid C Somayajulu {
4427217ec208SDavid C Somayajulu 	struct ecore_vf_info *vf_info;
4428217ec208SDavid C Somayajulu 	u64 feature;
4429217ec208SDavid C Somayajulu 
4430217ec208SDavid C Somayajulu 	vf_info = ecore_iov_get_vf_info(p_hwfn, (u16)vfid, true);
4431217ec208SDavid C Somayajulu 	if (!vf_info) {
4432217ec208SDavid C Somayajulu 		DP_NOTICE(p_hwfn->p_dev, true, "Can not set forced MAC, invalid vfid [%d]\n",
4433217ec208SDavid C Somayajulu 			  vfid);
4434217ec208SDavid C Somayajulu 		return;
4435217ec208SDavid C Somayajulu 	}
4436217ec208SDavid C Somayajulu 	if (vf_info->b_malicious) {
4437217ec208SDavid C Somayajulu 		DP_NOTICE(p_hwfn->p_dev, false, "Can't set forced MAC to malicious VF [%d]\n",
4438217ec208SDavid C Somayajulu 			  vfid);
4439217ec208SDavid C Somayajulu 		return;
4440217ec208SDavid C Somayajulu 	}
4441217ec208SDavid C Somayajulu 
4442217ec208SDavid C Somayajulu 	feature = 1 << MAC_ADDR_FORCED;
4443217ec208SDavid C Somayajulu 	OSAL_MEMCPY(vf_info->bulletin.p_virt->mac,
4444217ec208SDavid C Somayajulu 		    mac, ETH_ALEN);
4445217ec208SDavid C Somayajulu 
4446217ec208SDavid C Somayajulu 	vf_info->bulletin.p_virt->valid_bitmap |= feature;
4447217ec208SDavid C Somayajulu 	/* Forced MAC will disable MAC_ADDR */
4448217ec208SDavid C Somayajulu 	vf_info->bulletin.p_virt->valid_bitmap &=
4449217ec208SDavid C Somayajulu 		~(1 << VFPF_BULLETIN_MAC_ADDR);
4450217ec208SDavid C Somayajulu 
4451217ec208SDavid C Somayajulu 	ecore_iov_configure_vport_forced(p_hwfn, vf_info, feature);
4452217ec208SDavid C Somayajulu }
4453217ec208SDavid C Somayajulu 
4454217ec208SDavid C Somayajulu #ifndef LINUX_REMOVE
ecore_iov_bulletin_set_mac(struct ecore_hwfn * p_hwfn,u8 * mac,int vfid)4455217ec208SDavid C Somayajulu enum _ecore_status_t ecore_iov_bulletin_set_mac(struct ecore_hwfn *p_hwfn,
4456217ec208SDavid C Somayajulu 						u8 *mac, int vfid)
4457217ec208SDavid C Somayajulu {
4458217ec208SDavid C Somayajulu 	struct ecore_vf_info *vf_info;
4459217ec208SDavid C Somayajulu 	u64 feature;
4460217ec208SDavid C Somayajulu 
4461217ec208SDavid C Somayajulu 	vf_info = ecore_iov_get_vf_info(p_hwfn, (u16)vfid, true);
4462217ec208SDavid C Somayajulu 	if (!vf_info) {
4463217ec208SDavid C Somayajulu 		DP_NOTICE(p_hwfn->p_dev, true, "Can not set MAC, invalid vfid [%d]\n",
4464217ec208SDavid C Somayajulu 			  vfid);
4465217ec208SDavid C Somayajulu 		return ECORE_INVAL;
4466217ec208SDavid C Somayajulu 	}
4467217ec208SDavid C Somayajulu 	if (vf_info->b_malicious) {
4468217ec208SDavid C Somayajulu 		DP_NOTICE(p_hwfn->p_dev, false, "Can't set MAC to malicious VF [%d]\n",
4469217ec208SDavid C Somayajulu 			  vfid);
4470217ec208SDavid C Somayajulu 		return ECORE_INVAL;
4471217ec208SDavid C Somayajulu 	}
4472217ec208SDavid C Somayajulu 
4473217ec208SDavid C Somayajulu 	if (vf_info->bulletin.p_virt->valid_bitmap & (1 << MAC_ADDR_FORCED)) {
4474217ec208SDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV, "Can not set MAC, Forced MAC is configured\n");
4475217ec208SDavid C Somayajulu 		return ECORE_INVAL;
4476217ec208SDavid C Somayajulu 	}
4477217ec208SDavid C Somayajulu 
4478217ec208SDavid C Somayajulu 	feature = 1 << VFPF_BULLETIN_MAC_ADDR;
4479217ec208SDavid C Somayajulu 	OSAL_MEMCPY(vf_info->bulletin.p_virt->mac,
4480217ec208SDavid C Somayajulu 		    mac, ETH_ALEN);
4481217ec208SDavid C Somayajulu 
4482217ec208SDavid C Somayajulu 	vf_info->bulletin.p_virt->valid_bitmap |= feature;
4483217ec208SDavid C Somayajulu 
4484217ec208SDavid C Somayajulu 	return ECORE_SUCCESS;
4485217ec208SDavid C Somayajulu }
4486217ec208SDavid C Somayajulu 
4487217ec208SDavid C Somayajulu enum _ecore_status_t
ecore_iov_bulletin_set_forced_untagged_default(struct ecore_hwfn * p_hwfn,bool b_untagged_only,int vfid)4488217ec208SDavid C Somayajulu ecore_iov_bulletin_set_forced_untagged_default(struct ecore_hwfn *p_hwfn,
4489217ec208SDavid C Somayajulu 					       bool b_untagged_only,
4490217ec208SDavid C Somayajulu 					       int vfid)
4491217ec208SDavid C Somayajulu {
4492217ec208SDavid C Somayajulu 	struct ecore_vf_info *vf_info;
4493217ec208SDavid C Somayajulu 	u64 feature;
4494217ec208SDavid C Somayajulu 
4495217ec208SDavid C Somayajulu 	vf_info = ecore_iov_get_vf_info(p_hwfn, (u16)vfid, true);
4496217ec208SDavid C Somayajulu 	if (!vf_info) {
4497217ec208SDavid C Somayajulu 		DP_NOTICE(p_hwfn->p_dev, true,
4498217ec208SDavid C Somayajulu 			  "Can not set untagged default, invalid vfid [%d]\n",
4499217ec208SDavid C Somayajulu 			  vfid);
4500217ec208SDavid C Somayajulu 		return ECORE_INVAL;
4501217ec208SDavid C Somayajulu 	}
4502217ec208SDavid C Somayajulu 	if (vf_info->b_malicious) {
4503217ec208SDavid C Somayajulu 		DP_NOTICE(p_hwfn->p_dev, false,
4504217ec208SDavid C Somayajulu 			  "Can't set untagged default to malicious VF [%d]\n",
4505217ec208SDavid C Somayajulu 			  vfid);
4506217ec208SDavid C Somayajulu 		return ECORE_INVAL;
4507217ec208SDavid C Somayajulu 	}
4508217ec208SDavid C Somayajulu 
4509217ec208SDavid C Somayajulu 	/* Since this is configurable only during vport-start, don't take it
4510217ec208SDavid C Somayajulu 	 * if we're past that point.
4511217ec208SDavid C Somayajulu 	 */
4512217ec208SDavid C Somayajulu 	if (vf_info->state == VF_ENABLED) {
4513217ec208SDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
4514217ec208SDavid C Somayajulu 			   "Can't support untagged change for vfid[%d] - VF is already active\n",
4515217ec208SDavid C Somayajulu 			   vfid);
4516217ec208SDavid C Somayajulu 		return ECORE_INVAL;
4517217ec208SDavid C Somayajulu 	}
4518217ec208SDavid C Somayajulu 
4519217ec208SDavid C Somayajulu 	/* Set configuration; This will later be taken into account during the
4520217ec208SDavid C Somayajulu 	 * VF initialization.
4521217ec208SDavid C Somayajulu 	 */
4522217ec208SDavid C Somayajulu 	feature = (1 << VFPF_BULLETIN_UNTAGGED_DEFAULT) |
4523217ec208SDavid C Somayajulu 		  (1 << VFPF_BULLETIN_UNTAGGED_DEFAULT_FORCED);
4524217ec208SDavid C Somayajulu 	vf_info->bulletin.p_virt->valid_bitmap |= feature;
4525217ec208SDavid C Somayajulu 
4526217ec208SDavid C Somayajulu 	vf_info->bulletin.p_virt->default_only_untagged = b_untagged_only ? 1
4527217ec208SDavid C Somayajulu 									  : 0;
4528217ec208SDavid C Somayajulu 
4529217ec208SDavid C Somayajulu 	return ECORE_SUCCESS;
4530217ec208SDavid C Somayajulu }
4531217ec208SDavid C Somayajulu 
ecore_iov_get_vfs_opaque_fid(struct ecore_hwfn * p_hwfn,int vfid,u16 * opaque_fid)4532217ec208SDavid C Somayajulu void ecore_iov_get_vfs_opaque_fid(struct ecore_hwfn *p_hwfn, int vfid,
4533217ec208SDavid C Somayajulu 				  u16 *opaque_fid)
4534217ec208SDavid C Somayajulu {
4535217ec208SDavid C Somayajulu 	struct ecore_vf_info *vf_info;
4536217ec208SDavid C Somayajulu 
4537217ec208SDavid C Somayajulu 	vf_info = ecore_iov_get_vf_info(p_hwfn, (u16)vfid, true);
4538217ec208SDavid C Somayajulu 	if (!vf_info)
4539217ec208SDavid C Somayajulu 		return;
4540217ec208SDavid C Somayajulu 
4541217ec208SDavid C Somayajulu 	*opaque_fid = vf_info->opaque_fid;
4542217ec208SDavid C Somayajulu }
4543217ec208SDavid C Somayajulu #endif
4544217ec208SDavid C Somayajulu 
ecore_iov_bulletin_set_forced_vlan(struct ecore_hwfn * p_hwfn,u16 pvid,int vfid)4545217ec208SDavid C Somayajulu void ecore_iov_bulletin_set_forced_vlan(struct ecore_hwfn *p_hwfn,
4546217ec208SDavid C Somayajulu 					u16 pvid, int vfid)
4547217ec208SDavid C Somayajulu {
4548217ec208SDavid C Somayajulu 	struct ecore_vf_info *vf_info;
4549217ec208SDavid C Somayajulu 	u64 feature;
4550217ec208SDavid C Somayajulu 
4551217ec208SDavid C Somayajulu 	vf_info = ecore_iov_get_vf_info(p_hwfn, (u16)vfid, true);
4552217ec208SDavid C Somayajulu 	if (!vf_info) {
4553217ec208SDavid C Somayajulu 		DP_NOTICE(p_hwfn->p_dev, true, "Can not set forced MAC, invalid vfid [%d]\n",
4554217ec208SDavid C Somayajulu 			  vfid);
4555217ec208SDavid C Somayajulu 		return;
4556217ec208SDavid C Somayajulu 	}
4557217ec208SDavid C Somayajulu 	if (vf_info->b_malicious) {
4558217ec208SDavid C Somayajulu 		DP_NOTICE(p_hwfn->p_dev, false,
4559217ec208SDavid C Somayajulu 			  "Can't set forced vlan to malicious VF [%d]\n",
4560217ec208SDavid C Somayajulu 			  vfid);
4561217ec208SDavid C Somayajulu 		return;
4562217ec208SDavid C Somayajulu 	}
4563217ec208SDavid C Somayajulu 
4564217ec208SDavid C Somayajulu 	feature = 1 << VLAN_ADDR_FORCED;
4565217ec208SDavid C Somayajulu 	vf_info->bulletin.p_virt->pvid = pvid;
4566217ec208SDavid C Somayajulu 	if (pvid)
4567217ec208SDavid C Somayajulu 		vf_info->bulletin.p_virt->valid_bitmap |= feature;
4568217ec208SDavid C Somayajulu 	else
4569217ec208SDavid C Somayajulu 		vf_info->bulletin.p_virt->valid_bitmap &= ~feature;
4570217ec208SDavid C Somayajulu 
4571217ec208SDavid C Somayajulu 	ecore_iov_configure_vport_forced(p_hwfn, vf_info, feature);
4572217ec208SDavid C Somayajulu }
4573217ec208SDavid C Somayajulu 
ecore_iov_bulletin_set_udp_ports(struct ecore_hwfn * p_hwfn,int vfid,u16 vxlan_port,u16 geneve_port)4574217ec208SDavid C Somayajulu void ecore_iov_bulletin_set_udp_ports(struct ecore_hwfn *p_hwfn,
4575217ec208SDavid C Somayajulu 				      int vfid, u16 vxlan_port, u16 geneve_port)
4576217ec208SDavid C Somayajulu {
4577217ec208SDavid C Somayajulu 	struct ecore_vf_info *vf_info;
4578217ec208SDavid C Somayajulu 
4579217ec208SDavid C Somayajulu 	vf_info = ecore_iov_get_vf_info(p_hwfn, (u16)vfid, true);
4580217ec208SDavid C Somayajulu 	if (!vf_info) {
4581217ec208SDavid C Somayajulu 		DP_NOTICE(p_hwfn->p_dev, true,
4582217ec208SDavid C Somayajulu 			  "Can not set udp ports, invalid vfid [%d]\n", vfid);
4583217ec208SDavid C Somayajulu 		return;
4584217ec208SDavid C Somayajulu 	}
4585217ec208SDavid C Somayajulu 
4586217ec208SDavid C Somayajulu 	if (vf_info->b_malicious) {
4587217ec208SDavid C Somayajulu 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
4588217ec208SDavid C Somayajulu 			   "Can not set udp ports to malicious VF [%d]\n",
4589217ec208SDavid C Somayajulu 			   vfid);
4590217ec208SDavid C Somayajulu 		return;
4591217ec208SDavid C Somayajulu 	}
4592217ec208SDavid C Somayajulu 
4593217ec208SDavid C Somayajulu 	vf_info->bulletin.p_virt->vxlan_udp_port = vxlan_port;
4594217ec208SDavid C Somayajulu 	vf_info->bulletin.p_virt->geneve_udp_port = geneve_port;
4595217ec208SDavid C Somayajulu }
4596217ec208SDavid C Somayajulu 
ecore_iov_vf_has_vport_instance(struct ecore_hwfn * p_hwfn,int vfid)4597217ec208SDavid C Somayajulu bool ecore_iov_vf_has_vport_instance(struct ecore_hwfn *p_hwfn, int vfid)
4598217ec208SDavid C Somayajulu {
4599217ec208SDavid C Somayajulu 	struct ecore_vf_info *p_vf_info;
4600217ec208SDavid C Somayajulu 
4601217ec208SDavid C Somayajulu 	p_vf_info = ecore_iov_get_vf_info(p_hwfn, (u16)vfid, true);
4602217ec208SDavid C Somayajulu 	if (!p_vf_info)
4603217ec208SDavid C Somayajulu 		return false;
4604217ec208SDavid C Somayajulu 
4605217ec208SDavid C Somayajulu 	return !!p_vf_info->vport_instance;
4606217ec208SDavid C Somayajulu }
4607217ec208SDavid C Somayajulu 
ecore_iov_is_vf_stopped(struct ecore_hwfn * p_hwfn,int vfid)4608217ec208SDavid C Somayajulu bool ecore_iov_is_vf_stopped(struct ecore_hwfn *p_hwfn, int vfid)
4609217ec208SDavid C Somayajulu {
4610217ec208SDavid C Somayajulu 	struct ecore_vf_info *p_vf_info;
4611217ec208SDavid C Somayajulu 
4612217ec208SDavid C Somayajulu 	p_vf_info = ecore_iov_get_vf_info(p_hwfn, (u16)vfid, true);
4613217ec208SDavid C Somayajulu 	if (!p_vf_info)
4614217ec208SDavid C Somayajulu 		return true;
4615217ec208SDavid C Somayajulu 
4616217ec208SDavid C Somayajulu 	return p_vf_info->state == VF_STOPPED;
4617217ec208SDavid C Somayajulu }
4618217ec208SDavid C Somayajulu 
ecore_iov_spoofchk_get(struct ecore_hwfn * p_hwfn,int vfid)4619217ec208SDavid C Somayajulu bool ecore_iov_spoofchk_get(struct ecore_hwfn *p_hwfn, int vfid)
4620217ec208SDavid C Somayajulu {
4621217ec208SDavid C Somayajulu 	struct ecore_vf_info *vf_info;
4622217ec208SDavid C Somayajulu 
4623217ec208SDavid C Somayajulu 	vf_info = ecore_iov_get_vf_info(p_hwfn, (u16)vfid, true);
4624217ec208SDavid C Somayajulu 	if (!vf_info)
4625217ec208SDavid C Somayajulu 		return false;
4626217ec208SDavid C Somayajulu 
4627217ec208SDavid C Somayajulu 	return vf_info->spoof_chk;
4628217ec208SDavid C Somayajulu }
4629217ec208SDavid C Somayajulu 
ecore_iov_spoofchk_set(struct ecore_hwfn * p_hwfn,int vfid,bool val)4630217ec208SDavid C Somayajulu enum _ecore_status_t ecore_iov_spoofchk_set(struct ecore_hwfn *p_hwfn,
4631217ec208SDavid C Somayajulu 					    int vfid, bool val)
4632217ec208SDavid C Somayajulu {
4633217ec208SDavid C Somayajulu 	struct ecore_vf_info *vf;
4634217ec208SDavid C Somayajulu 	enum _ecore_status_t rc = ECORE_INVAL;
4635217ec208SDavid C Somayajulu 
4636217ec208SDavid C Somayajulu 	if (!ecore_iov_pf_sanity_check(p_hwfn, vfid)) {
4637217ec208SDavid C Somayajulu 		DP_NOTICE(p_hwfn, true,
4638217ec208SDavid C Somayajulu 			  "SR-IOV sanity check failed, can't set spoofchk\n");
4639217ec208SDavid C Somayajulu 		goto out;
4640217ec208SDavid C Somayajulu 	}
4641217ec208SDavid C Somayajulu 
4642217ec208SDavid C Somayajulu 	vf = ecore_iov_get_vf_info(p_hwfn, (u16)vfid, true);
4643217ec208SDavid C Somayajulu 	if (!vf)
4644217ec208SDavid C Somayajulu 		goto out;
4645217ec208SDavid C Somayajulu 
4646217ec208SDavid C Somayajulu 	if (!ecore_iov_vf_has_vport_instance(p_hwfn, vfid)) {
4647217ec208SDavid C Somayajulu 		/* After VF VPORT start PF will configure spoof check */
4648217ec208SDavid C Somayajulu 		vf->req_spoofchk_val = val;
4649217ec208SDavid C Somayajulu 		rc = ECORE_SUCCESS;
4650217ec208SDavid C Somayajulu 		goto out;
4651217ec208SDavid C Somayajulu 	}
4652217ec208SDavid C Somayajulu 
4653217ec208SDavid C Somayajulu 	rc = __ecore_iov_spoofchk_set(p_hwfn, vf, val);
4654217ec208SDavid C Somayajulu 
4655217ec208SDavid C Somayajulu out:
4656217ec208SDavid C Somayajulu 	return rc;
4657217ec208SDavid C Somayajulu }
4658217ec208SDavid C Somayajulu 
4659217ec208SDavid C Somayajulu #ifndef LINUX_REMOVE
ecore_iov_vf_chains_per_pf(struct ecore_hwfn * p_hwfn)4660217ec208SDavid C Somayajulu u8 ecore_iov_vf_chains_per_pf(struct ecore_hwfn *p_hwfn)
4661217ec208SDavid C Somayajulu {
4662217ec208SDavid C Somayajulu 	u8 max_chains_per_vf = p_hwfn->hw_info.max_chains_per_vf;
4663217ec208SDavid C Somayajulu 
4664217ec208SDavid C Somayajulu 	max_chains_per_vf = (max_chains_per_vf) ? max_chains_per_vf
4665217ec208SDavid C Somayajulu 						: ECORE_MAX_VF_CHAINS_PER_PF;
4666217ec208SDavid C Somayajulu 
4667217ec208SDavid C Somayajulu 	return max_chains_per_vf;
4668217ec208SDavid C Somayajulu }
4669217ec208SDavid C Somayajulu 
ecore_iov_get_vf_req_virt_mbx_params(struct ecore_hwfn * p_hwfn,u16 rel_vf_id,void ** pp_req_virt_addr,u16 * p_req_virt_size)4670217ec208SDavid C Somayajulu void ecore_iov_get_vf_req_virt_mbx_params(struct ecore_hwfn *p_hwfn,
4671217ec208SDavid C Somayajulu 					  u16 rel_vf_id,
4672217ec208SDavid C Somayajulu 					  void **pp_req_virt_addr,
4673217ec208SDavid C Somayajulu 					  u16 *p_req_virt_size)
4674217ec208SDavid C Somayajulu {
4675217ec208SDavid C Somayajulu 	struct ecore_vf_info *vf_info =
4676217ec208SDavid C Somayajulu 		ecore_iov_get_vf_info(p_hwfn, rel_vf_id, true);
4677217ec208SDavid C Somayajulu 
4678217ec208SDavid C Somayajulu 	if (!vf_info)
4679217ec208SDavid C Somayajulu 		return;
4680217ec208SDavid C Somayajulu 
4681217ec208SDavid C Somayajulu 	if (pp_req_virt_addr)
4682217ec208SDavid C Somayajulu 		*pp_req_virt_addr = vf_info->vf_mbx.req_virt;
4683217ec208SDavid C Somayajulu 
4684217ec208SDavid C Somayajulu 	if (p_req_virt_size)
4685217ec208SDavid C Somayajulu 		*p_req_virt_size = sizeof(*vf_info->vf_mbx.req_virt);
4686217ec208SDavid C Somayajulu }
4687217ec208SDavid C Somayajulu 
ecore_iov_get_vf_reply_virt_mbx_params(struct ecore_hwfn * p_hwfn,u16 rel_vf_id,void ** pp_reply_virt_addr,u16 * p_reply_virt_size)4688217ec208SDavid C Somayajulu void ecore_iov_get_vf_reply_virt_mbx_params(struct ecore_hwfn *p_hwfn,
4689217ec208SDavid C Somayajulu 					    u16	rel_vf_id,
4690217ec208SDavid C Somayajulu 					    void **pp_reply_virt_addr,
4691217ec208SDavid C Somayajulu 					    u16	*p_reply_virt_size)
4692217ec208SDavid C Somayajulu {
4693217ec208SDavid C Somayajulu 	struct ecore_vf_info *vf_info =
4694217ec208SDavid C Somayajulu 		ecore_iov_get_vf_info(p_hwfn, rel_vf_id, true);
4695217ec208SDavid C Somayajulu 
4696217ec208SDavid C Somayajulu 	if (!vf_info)
4697217ec208SDavid C Somayajulu 		return;
4698217ec208SDavid C Somayajulu 
4699217ec208SDavid C Somayajulu 	if (pp_reply_virt_addr)
4700217ec208SDavid C Somayajulu 		*pp_reply_virt_addr = vf_info->vf_mbx.reply_virt;
4701217ec208SDavid C Somayajulu 
4702217ec208SDavid C Somayajulu 	if (p_reply_virt_size)
4703217ec208SDavid C Somayajulu 		*p_reply_virt_size = sizeof(*vf_info->vf_mbx.reply_virt);
4704217ec208SDavid C Somayajulu }
4705217ec208SDavid C Somayajulu 
4706217ec208SDavid C Somayajulu #ifdef CONFIG_ECORE_SW_CHANNEL
4707217ec208SDavid C Somayajulu struct ecore_iov_sw_mbx*
ecore_iov_get_vf_sw_mbx(struct ecore_hwfn * p_hwfn,u16 rel_vf_id)4708217ec208SDavid C Somayajulu ecore_iov_get_vf_sw_mbx(struct ecore_hwfn *p_hwfn,
4709217ec208SDavid C Somayajulu 			u16 rel_vf_id)
4710217ec208SDavid C Somayajulu {
4711217ec208SDavid C Somayajulu 	struct ecore_vf_info *vf_info =
4712217ec208SDavid C Somayajulu 		ecore_iov_get_vf_info(p_hwfn, rel_vf_id, true);
4713217ec208SDavid C Somayajulu 
4714217ec208SDavid C Somayajulu 	if (!vf_info)
4715217ec208SDavid C Somayajulu 		return OSAL_NULL;
4716217ec208SDavid C Somayajulu 
4717217ec208SDavid C Somayajulu 	return &vf_info->vf_mbx.sw_mbx;
4718217ec208SDavid C Somayajulu }
4719217ec208SDavid C Somayajulu #endif
4720217ec208SDavid C Somayajulu 
ecore_iov_is_valid_vfpf_msg_length(u32 length)4721217ec208SDavid C Somayajulu bool ecore_iov_is_valid_vfpf_msg_length(u32 length)
4722217ec208SDavid C Somayajulu {
4723217ec208SDavid C Somayajulu 	return (length >= sizeof(struct vfpf_first_tlv) &&
4724217ec208SDavid C Somayajulu 		(length <= sizeof(union vfpf_tlvs)));
4725217ec208SDavid C Somayajulu }
4726217ec208SDavid C Somayajulu 
ecore_iov_pfvf_msg_length(void)4727217ec208SDavid C Somayajulu u32 ecore_iov_pfvf_msg_length(void)
4728217ec208SDavid C Somayajulu {
4729217ec208SDavid C Somayajulu 	return sizeof(union pfvf_tlvs);
4730217ec208SDavid C Somayajulu }
4731217ec208SDavid C Somayajulu #endif
4732217ec208SDavid C Somayajulu 
ecore_iov_bulletin_get_forced_mac(struct ecore_hwfn * p_hwfn,u16 rel_vf_id)4733217ec208SDavid C Somayajulu u8 *ecore_iov_bulletin_get_forced_mac(struct ecore_hwfn *p_hwfn,
4734217ec208SDavid C Somayajulu 				      u16 rel_vf_id)
4735217ec208SDavid C Somayajulu {
4736217ec208SDavid C Somayajulu 	struct ecore_vf_info *p_vf;
4737217ec208SDavid C Somayajulu 
4738217ec208SDavid C Somayajulu 	p_vf = ecore_iov_get_vf_info(p_hwfn, rel_vf_id, true);
4739217ec208SDavid C Somayajulu 	if (!p_vf || !p_vf->bulletin.p_virt)
4740217ec208SDavid C Somayajulu 		return OSAL_NULL;
4741217ec208SDavid C Somayajulu 
4742217ec208SDavid C Somayajulu 	if (!(p_vf->bulletin.p_virt->valid_bitmap & (1 << MAC_ADDR_FORCED)))
4743217ec208SDavid C Somayajulu 		return OSAL_NULL;
4744217ec208SDavid C Somayajulu 
4745217ec208SDavid C Somayajulu 	return p_vf->bulletin.p_virt->mac;
4746217ec208SDavid C Somayajulu }
4747217ec208SDavid C Somayajulu 
ecore_iov_bulletin_get_forced_vlan(struct ecore_hwfn * p_hwfn,u16 rel_vf_id)4748217ec208SDavid C Somayajulu u16 ecore_iov_bulletin_get_forced_vlan(struct ecore_hwfn *p_hwfn,
4749217ec208SDavid C Somayajulu 				       u16 rel_vf_id)
4750217ec208SDavid C Somayajulu {
4751217ec208SDavid C Somayajulu 	struct ecore_vf_info *p_vf;
4752217ec208SDavid C Somayajulu 
4753217ec208SDavid C Somayajulu 	p_vf = ecore_iov_get_vf_info(p_hwfn, rel_vf_id, true);
4754217ec208SDavid C Somayajulu 	if (!p_vf || !p_vf->bulletin.p_virt)
4755217ec208SDavid C Somayajulu 		return 0;
4756217ec208SDavid C Somayajulu 
4757217ec208SDavid C Somayajulu 	if (!(p_vf->bulletin.p_virt->valid_bitmap & (1 << VLAN_ADDR_FORCED)))
4758217ec208SDavid C Somayajulu 		return 0;
4759217ec208SDavid C Somayajulu 
4760217ec208SDavid C Somayajulu 	return p_vf->bulletin.p_virt->pvid;
4761217ec208SDavid C Somayajulu }
4762217ec208SDavid C Somayajulu 
ecore_iov_configure_tx_rate(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,int vfid,int val)4763217ec208SDavid C Somayajulu enum _ecore_status_t ecore_iov_configure_tx_rate(struct ecore_hwfn *p_hwfn,
4764217ec208SDavid C Somayajulu 						 struct ecore_ptt *p_ptt,
4765217ec208SDavid C Somayajulu 						 int vfid, int val)
4766217ec208SDavid C Somayajulu {
4767217ec208SDavid C Somayajulu 	struct ecore_mcp_link_state *p_link;
4768217ec208SDavid C Somayajulu 	struct ecore_vf_info *vf;
4769217ec208SDavid C Somayajulu 	u8 abs_vp_id = 0;
4770217ec208SDavid C Somayajulu 	enum _ecore_status_t rc;
4771217ec208SDavid C Somayajulu 
4772217ec208SDavid C Somayajulu 	vf = ecore_iov_get_vf_info(p_hwfn, (u16)vfid, true);
4773217ec208SDavid C Somayajulu 
4774217ec208SDavid C Somayajulu 	if (!vf)
4775217ec208SDavid C Somayajulu 		return ECORE_INVAL;
4776217ec208SDavid C Somayajulu 
4777217ec208SDavid C Somayajulu 	rc = ecore_fw_vport(p_hwfn, vf->vport_id, &abs_vp_id);
4778217ec208SDavid C Somayajulu 	if (rc != ECORE_SUCCESS)
4779217ec208SDavid C Somayajulu 		return rc;
4780217ec208SDavid C Somayajulu 
4781217ec208SDavid C Somayajulu 	p_link = &ECORE_LEADING_HWFN(p_hwfn->p_dev)->mcp_info->link_output;
4782217ec208SDavid C Somayajulu 
4783217ec208SDavid C Somayajulu 	return ecore_init_vport_rl(p_hwfn, p_ptt, abs_vp_id, (u32)val,
4784217ec208SDavid C Somayajulu 				   p_link->speed);
4785217ec208SDavid C Somayajulu }
4786217ec208SDavid C Somayajulu 
ecore_iov_configure_min_tx_rate(struct ecore_dev * p_dev,int vfid,u32 rate)4787217ec208SDavid C Somayajulu enum _ecore_status_t ecore_iov_configure_min_tx_rate(struct ecore_dev *p_dev,
4788217ec208SDavid C Somayajulu 						     int vfid, u32 rate)
4789217ec208SDavid C Somayajulu {
4790217ec208SDavid C Somayajulu 	struct ecore_vf_info *vf;
4791217ec208SDavid C Somayajulu 	u8 vport_id;
4792217ec208SDavid C Somayajulu 	int i;
4793217ec208SDavid C Somayajulu 
4794217ec208SDavid C Somayajulu 	for_each_hwfn(p_dev, i) {
4795217ec208SDavid C Somayajulu 		struct ecore_hwfn *p_hwfn = &p_dev->hwfns[i];
4796217ec208SDavid C Somayajulu 
4797217ec208SDavid C Somayajulu 		if (!ecore_iov_pf_sanity_check(p_hwfn, vfid)) {
4798217ec208SDavid C Somayajulu 			DP_NOTICE(p_hwfn, true,
4799217ec208SDavid C Somayajulu 				  "SR-IOV sanity check failed, can't set min rate\n");
4800217ec208SDavid C Somayajulu 			return ECORE_INVAL;
4801217ec208SDavid C Somayajulu 		}
4802217ec208SDavid C Somayajulu 	}
4803217ec208SDavid C Somayajulu 
4804217ec208SDavid C Somayajulu 	vf = ecore_iov_get_vf_info(ECORE_LEADING_HWFN(p_dev), (u16)vfid, true);
4805217ec208SDavid C Somayajulu 	vport_id = vf->vport_id;
4806217ec208SDavid C Somayajulu 
4807217ec208SDavid C Somayajulu 	return ecore_configure_vport_wfq(p_dev, vport_id, rate);
4808217ec208SDavid C Somayajulu }
4809217ec208SDavid C Somayajulu 
4810217ec208SDavid C Somayajulu #ifndef LINUX_REMOVE
ecore_iov_get_vf_stats(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,int vfid,struct ecore_eth_stats * p_stats)4811217ec208SDavid C Somayajulu enum _ecore_status_t ecore_iov_get_vf_stats(struct ecore_hwfn *p_hwfn,
4812217ec208SDavid C Somayajulu 					    struct ecore_ptt *p_ptt,
4813217ec208SDavid C Somayajulu 					    int vfid,
4814217ec208SDavid C Somayajulu 					    struct ecore_eth_stats *p_stats)
4815217ec208SDavid C Somayajulu {
4816217ec208SDavid C Somayajulu 	struct ecore_vf_info *vf;
4817217ec208SDavid C Somayajulu 
4818217ec208SDavid C Somayajulu 	vf = ecore_iov_get_vf_info(p_hwfn, (u16)vfid, true);
4819217ec208SDavid C Somayajulu 	if (!vf)
4820217ec208SDavid C Somayajulu 		return ECORE_INVAL;
4821217ec208SDavid C Somayajulu 
4822217ec208SDavid C Somayajulu 	if (vf->state != VF_ENABLED)
4823217ec208SDavid C Somayajulu 		return ECORE_INVAL;
4824217ec208SDavid C Somayajulu 
4825217ec208SDavid C Somayajulu 	__ecore_get_vport_stats(p_hwfn, p_ptt, p_stats,
4826217ec208SDavid C Somayajulu 				vf->abs_vf_id + 0x10, false);
4827217ec208SDavid C Somayajulu 
4828217ec208SDavid C Somayajulu 	return ECORE_SUCCESS;
4829217ec208SDavid C Somayajulu }
4830217ec208SDavid C Somayajulu 
ecore_iov_get_vf_num_rxqs(struct ecore_hwfn * p_hwfn,u16 rel_vf_id)4831217ec208SDavid C Somayajulu u8 ecore_iov_get_vf_num_rxqs(struct ecore_hwfn *p_hwfn,
4832217ec208SDavid C Somayajulu 			     u16 rel_vf_id)
4833217ec208SDavid C Somayajulu {
4834217ec208SDavid C Somayajulu 	struct ecore_vf_info *p_vf;
4835217ec208SDavid C Somayajulu 
4836217ec208SDavid C Somayajulu 	p_vf = ecore_iov_get_vf_info(p_hwfn, rel_vf_id, true);
4837217ec208SDavid C Somayajulu 	if (!p_vf)
4838217ec208SDavid C Somayajulu 		return 0;
4839217ec208SDavid C Somayajulu 
4840217ec208SDavid C Somayajulu 	return p_vf->num_rxqs;
4841217ec208SDavid C Somayajulu }
4842217ec208SDavid C Somayajulu 
ecore_iov_get_vf_num_active_rxqs(struct ecore_hwfn * p_hwfn,u16 rel_vf_id)4843217ec208SDavid C Somayajulu u8 ecore_iov_get_vf_num_active_rxqs(struct ecore_hwfn *p_hwfn,
4844217ec208SDavid C Somayajulu 				    u16 rel_vf_id)
4845217ec208SDavid C Somayajulu {
4846217ec208SDavid C Somayajulu 	struct ecore_vf_info *p_vf;
4847217ec208SDavid C Somayajulu 
4848217ec208SDavid C Somayajulu 	p_vf = ecore_iov_get_vf_info(p_hwfn, rel_vf_id, true);
4849217ec208SDavid C Somayajulu 	if (!p_vf)
4850217ec208SDavid C Somayajulu 		return 0;
4851217ec208SDavid C Somayajulu 
4852217ec208SDavid C Somayajulu 	return p_vf->num_active_rxqs;
4853217ec208SDavid C Somayajulu }
4854217ec208SDavid C Somayajulu 
ecore_iov_get_vf_ctx(struct ecore_hwfn * p_hwfn,u16 rel_vf_id)4855217ec208SDavid C Somayajulu void *ecore_iov_get_vf_ctx(struct ecore_hwfn *p_hwfn,
4856217ec208SDavid C Somayajulu 			   u16 rel_vf_id)
4857217ec208SDavid C Somayajulu {
4858217ec208SDavid C Somayajulu 	struct ecore_vf_info *p_vf;
4859217ec208SDavid C Somayajulu 
4860217ec208SDavid C Somayajulu 	p_vf = ecore_iov_get_vf_info(p_hwfn, rel_vf_id, true);
4861217ec208SDavid C Somayajulu 	if (!p_vf)
4862217ec208SDavid C Somayajulu 		return OSAL_NULL;
4863217ec208SDavid C Somayajulu 
4864217ec208SDavid C Somayajulu 	return p_vf->ctx;
4865217ec208SDavid C Somayajulu }
4866217ec208SDavid C Somayajulu 
ecore_iov_get_vf_num_sbs(struct ecore_hwfn * p_hwfn,u16 rel_vf_id)4867217ec208SDavid C Somayajulu u8 ecore_iov_get_vf_num_sbs(struct ecore_hwfn *p_hwfn,
4868217ec208SDavid C Somayajulu 			    u16 rel_vf_id)
4869217ec208SDavid C Somayajulu {
4870217ec208SDavid C Somayajulu 	struct ecore_vf_info *p_vf;
4871217ec208SDavid C Somayajulu 
4872217ec208SDavid C Somayajulu 	p_vf = ecore_iov_get_vf_info(p_hwfn, rel_vf_id, true);
4873217ec208SDavid C Somayajulu 	if (!p_vf)
4874217ec208SDavid C Somayajulu 		return 0;
4875217ec208SDavid C Somayajulu 
4876217ec208SDavid C Somayajulu 	return p_vf->num_sbs;
4877217ec208SDavid C Somayajulu }
4878217ec208SDavid C Somayajulu 
ecore_iov_is_vf_wait_for_acquire(struct ecore_hwfn * p_hwfn,u16 rel_vf_id)4879217ec208SDavid C Somayajulu bool ecore_iov_is_vf_wait_for_acquire(struct ecore_hwfn *p_hwfn,
4880217ec208SDavid C Somayajulu 				      u16 rel_vf_id)
4881217ec208SDavid C Somayajulu {
4882217ec208SDavid C Somayajulu 	struct ecore_vf_info *p_vf;
4883217ec208SDavid C Somayajulu 
4884217ec208SDavid C Somayajulu 	p_vf = ecore_iov_get_vf_info(p_hwfn, rel_vf_id, true);
4885217ec208SDavid C Somayajulu 	if (!p_vf)
4886217ec208SDavid C Somayajulu 		return false;
4887217ec208SDavid C Somayajulu 
4888217ec208SDavid C Somayajulu 	return (p_vf->state == VF_FREE);
4889217ec208SDavid C Somayajulu }
4890217ec208SDavid C Somayajulu 
ecore_iov_is_vf_acquired_not_initialized(struct ecore_hwfn * p_hwfn,u16 rel_vf_id)4891217ec208SDavid C Somayajulu bool ecore_iov_is_vf_acquired_not_initialized(struct ecore_hwfn *p_hwfn,
4892217ec208SDavid C Somayajulu 					      u16 rel_vf_id)
4893217ec208SDavid C Somayajulu {
4894217ec208SDavid C Somayajulu 	struct ecore_vf_info *p_vf;
4895217ec208SDavid C Somayajulu 
4896217ec208SDavid C Somayajulu 	p_vf = ecore_iov_get_vf_info(p_hwfn, rel_vf_id, true);
4897217ec208SDavid C Somayajulu 	if (!p_vf)
4898217ec208SDavid C Somayajulu 		return false;
4899217ec208SDavid C Somayajulu 
4900217ec208SDavid C Somayajulu 	return (p_vf->state == VF_ACQUIRED);
4901217ec208SDavid C Somayajulu }
4902217ec208SDavid C Somayajulu 
ecore_iov_is_vf_initialized(struct ecore_hwfn * p_hwfn,u16 rel_vf_id)4903217ec208SDavid C Somayajulu bool ecore_iov_is_vf_initialized(struct ecore_hwfn *p_hwfn,
4904217ec208SDavid C Somayajulu 				 u16 rel_vf_id)
4905217ec208SDavid C Somayajulu {
4906217ec208SDavid C Somayajulu 	struct ecore_vf_info *p_vf;
4907217ec208SDavid C Somayajulu 
4908217ec208SDavid C Somayajulu 	p_vf = ecore_iov_get_vf_info(p_hwfn, rel_vf_id, true);
4909217ec208SDavid C Somayajulu 	if (!p_vf)
4910217ec208SDavid C Somayajulu 		return false;
4911217ec208SDavid C Somayajulu 
4912217ec208SDavid C Somayajulu 	return (p_vf->state == VF_ENABLED);
4913217ec208SDavid C Somayajulu }
4914217ec208SDavid C Somayajulu 
ecore_iov_is_vf_started(struct ecore_hwfn * p_hwfn,u16 rel_vf_id)4915217ec208SDavid C Somayajulu bool ecore_iov_is_vf_started(struct ecore_hwfn *p_hwfn,
4916217ec208SDavid C Somayajulu 			     u16 rel_vf_id)
4917217ec208SDavid C Somayajulu {
4918217ec208SDavid C Somayajulu 	struct ecore_vf_info *p_vf;
4919217ec208SDavid C Somayajulu 
4920217ec208SDavid C Somayajulu 	p_vf = ecore_iov_get_vf_info(p_hwfn, rel_vf_id, true);
4921217ec208SDavid C Somayajulu 	if (!p_vf)
4922217ec208SDavid C Somayajulu 		return false;
4923217ec208SDavid C Somayajulu 
4924217ec208SDavid C Somayajulu 	return (p_vf->state != VF_FREE && p_vf->state != VF_STOPPED);
4925217ec208SDavid C Somayajulu }
4926217ec208SDavid C Somayajulu #endif
4927217ec208SDavid C Somayajulu 
4928be909a79SJohn Baldwin int
ecore_iov_get_vf_min_rate(struct ecore_hwfn * p_hwfn,int vfid)4929217ec208SDavid C Somayajulu ecore_iov_get_vf_min_rate(struct ecore_hwfn *p_hwfn, int vfid)
4930217ec208SDavid C Somayajulu {
4931217ec208SDavid C Somayajulu 	struct ecore_wfq_data *vf_vp_wfq;
4932217ec208SDavid C Somayajulu 	struct ecore_vf_info *vf_info;
4933217ec208SDavid C Somayajulu 
4934217ec208SDavid C Somayajulu 	vf_info = ecore_iov_get_vf_info(p_hwfn, (u16)vfid, true);
4935217ec208SDavid C Somayajulu 	if (!vf_info)
4936217ec208SDavid C Somayajulu 		return 0;
4937217ec208SDavid C Somayajulu 
4938217ec208SDavid C Somayajulu 	vf_vp_wfq = &p_hwfn->qm_info.wfq_data[vf_info->vport_id];
4939217ec208SDavid C Somayajulu 
4940217ec208SDavid C Somayajulu 	if (vf_vp_wfq->configured)
4941217ec208SDavid C Somayajulu 		return vf_vp_wfq->min_speed;
4942217ec208SDavid C Somayajulu 	else
4943217ec208SDavid C Somayajulu 		return 0;
4944217ec208SDavid C Somayajulu }
4945217ec208SDavid C Somayajulu 
4946217ec208SDavid C Somayajulu #ifdef CONFIG_ECORE_SW_CHANNEL
ecore_iov_set_vf_hw_channel(struct ecore_hwfn * p_hwfn,int vfid,bool b_is_hw)4947217ec208SDavid C Somayajulu void ecore_iov_set_vf_hw_channel(struct ecore_hwfn *p_hwfn, int vfid,
4948217ec208SDavid C Somayajulu 				 bool b_is_hw)
4949217ec208SDavid C Somayajulu {
4950217ec208SDavid C Somayajulu 	struct ecore_vf_info *vf_info;
4951217ec208SDavid C Somayajulu 
4952217ec208SDavid C Somayajulu 	vf_info = ecore_iov_get_vf_info(p_hwfn, (u16)vfid, true);
4953217ec208SDavid C Somayajulu 	if (!vf_info)
4954217ec208SDavid C Somayajulu 		return;
4955217ec208SDavid C Somayajulu 
4956217ec208SDavid C Somayajulu 	vf_info->b_hw_channel = b_is_hw;
4957217ec208SDavid C Somayajulu }
4958217ec208SDavid C Somayajulu #endif
4959