xref: /dpdk/drivers/net/qede/base/ecore_sriov.c (revision c2c4f87b12590d96f549c4ef04a04d29d3b8fb97)
13126df22SRasesh Mody /* SPDX-License-Identifier: BSD-3-Clause
29adde217SRasesh Mody  * Copyright (c) 2016 - 2018 Cavium Inc.
386a2265eSRasesh Mody  * All rights reserved.
49adde217SRasesh Mody  * www.cavium.com
586a2265eSRasesh Mody  */
686a2265eSRasesh Mody 
786a2265eSRasesh Mody #include "bcm_osal.h"
886a2265eSRasesh Mody #include "ecore.h"
986a2265eSRasesh Mody #include "reg_addr.h"
1086a2265eSRasesh Mody #include "ecore_sriov.h"
1186a2265eSRasesh Mody #include "ecore_status.h"
1286a2265eSRasesh Mody #include "ecore_hw.h"
1386a2265eSRasesh Mody #include "ecore_hw_defs.h"
1486a2265eSRasesh Mody #include "ecore_int.h"
1586a2265eSRasesh Mody #include "ecore_hsi_eth.h"
1686a2265eSRasesh Mody #include "ecore_l2.h"
1786a2265eSRasesh Mody #include "ecore_vfpf_if.h"
1886a2265eSRasesh Mody #include "ecore_rt_defs.h"
1986a2265eSRasesh Mody #include "ecore_init_ops.h"
2086a2265eSRasesh Mody #include "ecore_gtt_reg_addr.h"
2186a2265eSRasesh Mody #include "ecore_iro.h"
2286a2265eSRasesh Mody #include "ecore_mcp.h"
2386a2265eSRasesh Mody #include "ecore_cxt.h"
2486a2265eSRasesh Mody #include "ecore_vf.h"
2586a2265eSRasesh Mody #include "ecore_init_fw_funcs.h"
2622d07d93SRasesh Mody #include "ecore_sp_commands.h"
2786a2265eSRasesh Mody 
287f474588SRasesh Mody static enum _ecore_status_t ecore_sriov_eqe_event(struct ecore_hwfn *p_hwfn,
297f474588SRasesh Mody 						  u8 opcode,
307f474588SRasesh Mody 						  __le16 echo,
317f474588SRasesh Mody 						  union event_ring_data *data,
327f474588SRasesh Mody 						  u8 fw_return_code);
337f474588SRasesh Mody 
34520dd992SFerruh Yigit const char *qede_ecore_channel_tlvs_string[] = {
3586a2265eSRasesh Mody 	"CHANNEL_TLV_NONE",	/* ends tlv sequence */
3686a2265eSRasesh Mody 	"CHANNEL_TLV_ACQUIRE",
3786a2265eSRasesh Mody 	"CHANNEL_TLV_VPORT_START",
3886a2265eSRasesh Mody 	"CHANNEL_TLV_VPORT_UPDATE",
3986a2265eSRasesh Mody 	"CHANNEL_TLV_VPORT_TEARDOWN",
4086a2265eSRasesh Mody 	"CHANNEL_TLV_START_RXQ",
4186a2265eSRasesh Mody 	"CHANNEL_TLV_START_TXQ",
4286a2265eSRasesh Mody 	"CHANNEL_TLV_STOP_RXQ",
4386a2265eSRasesh Mody 	"CHANNEL_TLV_STOP_TXQ",
4486a2265eSRasesh Mody 	"CHANNEL_TLV_UPDATE_RXQ",
4586a2265eSRasesh Mody 	"CHANNEL_TLV_INT_CLEANUP",
4686a2265eSRasesh Mody 	"CHANNEL_TLV_CLOSE",
4786a2265eSRasesh Mody 	"CHANNEL_TLV_RELEASE",
4886a2265eSRasesh Mody 	"CHANNEL_TLV_LIST_END",
4986a2265eSRasesh Mody 	"CHANNEL_TLV_UCAST_FILTER",
5086a2265eSRasesh Mody 	"CHANNEL_TLV_VPORT_UPDATE_ACTIVATE",
5186a2265eSRasesh Mody 	"CHANNEL_TLV_VPORT_UPDATE_TX_SWITCH",
5286a2265eSRasesh Mody 	"CHANNEL_TLV_VPORT_UPDATE_VLAN_STRIP",
5386a2265eSRasesh Mody 	"CHANNEL_TLV_VPORT_UPDATE_MCAST",
5486a2265eSRasesh Mody 	"CHANNEL_TLV_VPORT_UPDATE_ACCEPT_PARAM",
5586a2265eSRasesh Mody 	"CHANNEL_TLV_VPORT_UPDATE_RSS",
5686a2265eSRasesh Mody 	"CHANNEL_TLV_VPORT_UPDATE_ACCEPT_ANY_VLAN",
5786a2265eSRasesh Mody 	"CHANNEL_TLV_VPORT_UPDATE_SGE_TPA",
580b090fd3SRasesh Mody 	"CHANNEL_TLV_UPDATE_TUNN_PARAM",
596b8962e0SRasesh Mody 	"CHANNEL_TLV_COALESCE_UPDATE",
60a90c566fSRasesh Mody 	"CHANNEL_TLV_QID",
61823a84aaSRasesh Mody 	"CHANNEL_TLV_COALESCE_READ",
62d121a6b5SRasesh Mody 	"CHANNEL_TLV_BULLETIN_UPDATE_MAC",
63d121a6b5SRasesh Mody 	"CHANNEL_TLV_UPDATE_MTU",
64f44ca48cSManish Chopra 	"CHANNEL_TLV_RDMA_ACQUIRE",
65f44ca48cSManish Chopra 	"CHANNEL_TLV_RDMA_START",
66f44ca48cSManish Chopra 	"CHANNEL_TLV_RDMA_STOP",
67f44ca48cSManish Chopra 	"CHANNEL_TLV_RDMA_ADD_USER",
68f44ca48cSManish Chopra 	"CHANNEL_TLV_RDMA_REMOVE_USER",
69f44ca48cSManish Chopra 	"CHANNEL_TLV_RDMA_QUERY_COUNTERS",
70f44ca48cSManish Chopra 	"CHANNEL_TLV_RDMA_ALLOC_TID",
71f44ca48cSManish Chopra 	"CHANNEL_TLV_RDMA_REGISTER_TID",
72f44ca48cSManish Chopra 	"CHANNEL_TLV_RDMA_DEREGISTER_TID",
73f44ca48cSManish Chopra 	"CHANNEL_TLV_RDMA_FREE_TID",
74f44ca48cSManish Chopra 	"CHANNEL_TLV_RDMA_CREATE_CQ",
75f44ca48cSManish Chopra 	"CHANNEL_TLV_RDMA_RESIZE_CQ",
76f44ca48cSManish Chopra 	"CHANNEL_TLV_RDMA_DESTROY_CQ",
77f44ca48cSManish Chopra 	"CHANNEL_TLV_RDMA_CREATE_QP",
78f44ca48cSManish Chopra 	"CHANNEL_TLV_RDMA_MODIFY_QP",
79f44ca48cSManish Chopra 	"CHANNEL_TLV_RDMA_QUERY_QP",
80f44ca48cSManish Chopra 	"CHANNEL_TLV_RDMA_DESTROY_QP",
81f44ca48cSManish Chopra 	"CHANNEL_TLV_RDMA_CREATE_SRQ",
82f44ca48cSManish Chopra 	"CHANNEL_TLV_RDMA_MODIFY_SRQ",
83f44ca48cSManish Chopra 	"CHANNEL_TLV_RDMA_DESTROY_SRQ",
84f44ca48cSManish Chopra 	"CHANNEL_TLV_RDMA_QUERY_PORT",
85f44ca48cSManish Chopra 	"CHANNEL_TLV_RDMA_QUERY_DEVICE",
86f44ca48cSManish Chopra 	"CHANNEL_TLV_RDMA_IWARP_CONNECT",
87f44ca48cSManish Chopra 	"CHANNEL_TLV_RDMA_IWARP_ACCEPT",
88f44ca48cSManish Chopra 	"CHANNEL_TLV_RDMA_IWARP_CREATE_LISTEN",
89f44ca48cSManish Chopra 	"CHANNEL_TLV_RDMA_IWARP_DESTROY_LISTEN",
90f44ca48cSManish Chopra 	"CHANNEL_TLV_RDMA_IWARP_PAUSE_LISTEN",
91f44ca48cSManish Chopra 	"CHANNEL_TLV_RDMA_IWARP_REJECT",
92f44ca48cSManish Chopra 	"CHANNEL_TLV_RDMA_IWARP_SEND_RTR",
93f44ca48cSManish Chopra 	"CHANNEL_TLV_ESTABLISH_LL2_CONN",
94f44ca48cSManish Chopra 	"CHANNEL_TLV_TERMINATE_LL2_CONN",
95f44ca48cSManish Chopra 	"CHANNEL_TLV_ASYNC_EVENT",
96f44ca48cSManish Chopra 	"CHANNEL_TLV_SOFT_FLR",
9786a2265eSRasesh Mody 	"CHANNEL_TLV_MAX"
9886a2265eSRasesh Mody };
9986a2265eSRasesh Mody 
ecore_vf_calculate_legacy(struct ecore_vf_info * p_vf)10030ecf673SRasesh Mody static u8 ecore_vf_calculate_legacy(struct ecore_vf_info *p_vf)
101a90c566fSRasesh Mody {
102a90c566fSRasesh Mody 	u8 legacy = 0;
103a90c566fSRasesh Mody 
104a90c566fSRasesh Mody 	if (p_vf->acquire.vfdev_info.eth_fp_hsi_minor ==
105a90c566fSRasesh Mody 	    ETH_HSI_VER_NO_PKT_LEN_TUNN)
106a90c566fSRasesh Mody 		legacy |= ECORE_QCID_LEGACY_VF_RX_PROD;
107a90c566fSRasesh Mody 
108a90c566fSRasesh Mody 	if (!(p_vf->acquire.vfdev_info.capabilities &
109a90c566fSRasesh Mody 	     VFPF_ACQUIRE_CAP_QUEUE_QIDS))
110a90c566fSRasesh Mody 		legacy |= ECORE_QCID_LEGACY_VF_CID;
111a90c566fSRasesh Mody 
112a90c566fSRasesh Mody 	return legacy;
113a90c566fSRasesh Mody }
114a90c566fSRasesh Mody 
11522d07d93SRasesh Mody /* IOV ramrods */
ecore_sp_vf_start(struct ecore_hwfn * p_hwfn,struct ecore_vf_info * p_vf)11622d07d93SRasesh Mody static enum _ecore_status_t ecore_sp_vf_start(struct ecore_hwfn *p_hwfn,
11722d07d93SRasesh Mody 					      struct ecore_vf_info *p_vf)
11822d07d93SRasesh Mody {
11922d07d93SRasesh Mody 	struct vf_start_ramrod_data *p_ramrod = OSAL_NULL;
12022d07d93SRasesh Mody 	struct ecore_spq_entry *p_ent = OSAL_NULL;
12122d07d93SRasesh Mody 	struct ecore_sp_init_data init_data;
12222d07d93SRasesh Mody 	enum _ecore_status_t rc = ECORE_NOTIMPL;
12322d07d93SRasesh Mody 	u8 fp_minor;
12422d07d93SRasesh Mody 
12522d07d93SRasesh Mody 	/* Get SPQ entry */
12622d07d93SRasesh Mody 	OSAL_MEMSET(&init_data, 0, sizeof(init_data));
12722d07d93SRasesh Mody 	init_data.cid = ecore_spq_get_cid(p_hwfn);
12822d07d93SRasesh Mody 	init_data.opaque_fid = p_vf->opaque_fid;
12922d07d93SRasesh Mody 	init_data.comp_mode = ECORE_SPQ_MODE_EBLOCK;
13022d07d93SRasesh Mody 
13122d07d93SRasesh Mody 	rc = ecore_sp_init_request(p_hwfn, &p_ent,
13222d07d93SRasesh Mody 				   COMMON_RAMROD_VF_START,
13322d07d93SRasesh Mody 				   PROTOCOLID_COMMON, &init_data);
13422d07d93SRasesh Mody 	if (rc != ECORE_SUCCESS)
13522d07d93SRasesh Mody 		return rc;
13622d07d93SRasesh Mody 
13722d07d93SRasesh Mody 	p_ramrod = &p_ent->ramrod.vf_start;
13822d07d93SRasesh Mody 
13922d07d93SRasesh Mody 	p_ramrod->vf_id = GET_FIELD(p_vf->concrete_fid, PXP_CONCRETE_FID_VFID);
14022d07d93SRasesh Mody 	p_ramrod->opaque_fid = OSAL_CPU_TO_LE16(p_vf->opaque_fid);
14122d07d93SRasesh Mody 
14222d07d93SRasesh Mody 	switch (p_hwfn->hw_info.personality) {
14322d07d93SRasesh Mody 	case ECORE_PCI_ETH:
14422d07d93SRasesh Mody 		p_ramrod->personality = PERSONALITY_ETH;
14522d07d93SRasesh Mody 		break;
14622d07d93SRasesh Mody 	case ECORE_PCI_ETH_ROCE:
147bdf4267dSRasesh Mody 	case ECORE_PCI_ETH_IWARP:
14822d07d93SRasesh Mody 		p_ramrod->personality = PERSONALITY_RDMA_AND_ETH;
14922d07d93SRasesh Mody 		break;
15022d07d93SRasesh Mody 	default:
15122d07d93SRasesh Mody 		DP_NOTICE(p_hwfn, true, "Unknown VF personality %d\n",
15222d07d93SRasesh Mody 			  p_hwfn->hw_info.personality);
15322d07d93SRasesh Mody 		return ECORE_INVAL;
15422d07d93SRasesh Mody 	}
15522d07d93SRasesh Mody 
15622d07d93SRasesh Mody 	fp_minor = p_vf->acquire.vfdev_info.eth_fp_hsi_minor;
15722d07d93SRasesh Mody 	if (fp_minor > ETH_HSI_VER_MINOR &&
15822d07d93SRasesh Mody 	    fp_minor != ETH_HSI_VER_NO_PKT_LEN_TUNN) {
15922d07d93SRasesh Mody 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
16022d07d93SRasesh Mody 			   "VF [%d] - Requested fp hsi %02x.%02x which is"
16122d07d93SRasesh Mody 			   " slightly newer than PF's %02x.%02x; Configuring"
16222d07d93SRasesh Mody 			   " PFs version\n",
16322d07d93SRasesh Mody 			   p_vf->abs_vf_id,
16422d07d93SRasesh Mody 			   ETH_HSI_VER_MAJOR, fp_minor,
16522d07d93SRasesh Mody 			   ETH_HSI_VER_MAJOR, ETH_HSI_VER_MINOR);
16622d07d93SRasesh Mody 		fp_minor = ETH_HSI_VER_MINOR;
16722d07d93SRasesh Mody 	}
16822d07d93SRasesh Mody 
16922d07d93SRasesh Mody 	p_ramrod->hsi_fp_ver.major_ver_arr[ETH_VER_KEY] = ETH_HSI_VER_MAJOR;
17022d07d93SRasesh Mody 	p_ramrod->hsi_fp_ver.minor_ver_arr[ETH_VER_KEY] = fp_minor;
17122d07d93SRasesh Mody 
17222d07d93SRasesh Mody 	DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
17322d07d93SRasesh Mody 		   "VF[%d] - Starting using HSI %02x.%02x\n",
17422d07d93SRasesh Mody 		   p_vf->abs_vf_id, ETH_HSI_VER_MAJOR, fp_minor);
17522d07d93SRasesh Mody 
17622d07d93SRasesh Mody 	return ecore_spq_post(p_hwfn, p_ent, OSAL_NULL);
17722d07d93SRasesh Mody }
17822d07d93SRasesh Mody 
ecore_sp_vf_stop(struct ecore_hwfn * p_hwfn,u32 concrete_vfid,u16 opaque_vfid)17922d07d93SRasesh Mody static enum _ecore_status_t ecore_sp_vf_stop(struct ecore_hwfn *p_hwfn,
18022d07d93SRasesh Mody 					     u32 concrete_vfid,
18122d07d93SRasesh Mody 					     u16 opaque_vfid)
18222d07d93SRasesh Mody {
18322d07d93SRasesh Mody 	struct vf_stop_ramrod_data *p_ramrod = OSAL_NULL;
18422d07d93SRasesh Mody 	struct ecore_spq_entry *p_ent = OSAL_NULL;
18522d07d93SRasesh Mody 	struct ecore_sp_init_data init_data;
18622d07d93SRasesh Mody 	enum _ecore_status_t rc = ECORE_NOTIMPL;
18722d07d93SRasesh Mody 
18822d07d93SRasesh Mody 	/* Get SPQ entry */
18922d07d93SRasesh Mody 	OSAL_MEMSET(&init_data, 0, sizeof(init_data));
19022d07d93SRasesh Mody 	init_data.cid = ecore_spq_get_cid(p_hwfn);
19122d07d93SRasesh Mody 	init_data.opaque_fid = opaque_vfid;
19222d07d93SRasesh Mody 	init_data.comp_mode = ECORE_SPQ_MODE_EBLOCK;
19322d07d93SRasesh Mody 
19422d07d93SRasesh Mody 	rc = ecore_sp_init_request(p_hwfn, &p_ent,
19522d07d93SRasesh Mody 				   COMMON_RAMROD_VF_STOP,
19622d07d93SRasesh Mody 				   PROTOCOLID_COMMON, &init_data);
19722d07d93SRasesh Mody 	if (rc != ECORE_SUCCESS)
19822d07d93SRasesh Mody 		return rc;
19922d07d93SRasesh Mody 
20022d07d93SRasesh Mody 	p_ramrod = &p_ent->ramrod.vf_stop;
20122d07d93SRasesh Mody 
20222d07d93SRasesh Mody 	p_ramrod->vf_id = GET_FIELD(concrete_vfid, PXP_CONCRETE_FID_VFID);
20322d07d93SRasesh Mody 
20422d07d93SRasesh Mody 	return ecore_spq_post(p_hwfn, p_ent, OSAL_NULL);
20522d07d93SRasesh Mody }
20622d07d93SRasesh Mody 
ecore_iov_is_valid_vfid(struct ecore_hwfn * p_hwfn,int rel_vf_id,bool b_enabled_only,bool b_non_malicious)20722d07d93SRasesh Mody bool ecore_iov_is_valid_vfid(struct ecore_hwfn *p_hwfn, int rel_vf_id,
20847b302d6SRasesh Mody 			     bool b_enabled_only, bool b_non_malicious)
20922d07d93SRasesh Mody {
21022d07d93SRasesh Mody 	if (!p_hwfn->pf_iov_info) {
21122d07d93SRasesh Mody 		DP_NOTICE(p_hwfn->p_dev, true, "No iov info\n");
21222d07d93SRasesh Mody 		return false;
21322d07d93SRasesh Mody 	}
21422d07d93SRasesh Mody 
21522d07d93SRasesh Mody 	if ((rel_vf_id >= p_hwfn->p_dev->p_iov_info->total_vfs) ||
21622d07d93SRasesh Mody 	    (rel_vf_id < 0))
21722d07d93SRasesh Mody 		return false;
21822d07d93SRasesh Mody 
21922d07d93SRasesh Mody 	if ((!p_hwfn->pf_iov_info->vfs_array[rel_vf_id].b_init) &&
22022d07d93SRasesh Mody 	    b_enabled_only)
22122d07d93SRasesh Mody 		return false;
22222d07d93SRasesh Mody 
22347b302d6SRasesh Mody 	if ((p_hwfn->pf_iov_info->vfs_array[rel_vf_id].b_malicious) &&
22447b302d6SRasesh Mody 	    b_non_malicious)
22547b302d6SRasesh Mody 		return false;
22647b302d6SRasesh Mody 
22722d07d93SRasesh Mody 	return true;
22822d07d93SRasesh Mody }
22922d07d93SRasesh Mody 
ecore_iov_get_vf_info(struct ecore_hwfn * p_hwfn,u16 relative_vf_id,bool b_enabled_only)23022d07d93SRasesh Mody struct ecore_vf_info *ecore_iov_get_vf_info(struct ecore_hwfn *p_hwfn,
23122d07d93SRasesh Mody 					    u16 relative_vf_id,
23222d07d93SRasesh Mody 					    bool b_enabled_only)
23322d07d93SRasesh Mody {
23422d07d93SRasesh Mody 	struct ecore_vf_info *vf = OSAL_NULL;
23522d07d93SRasesh Mody 
23622d07d93SRasesh Mody 	if (!p_hwfn->pf_iov_info) {
23722d07d93SRasesh Mody 		DP_NOTICE(p_hwfn->p_dev, true, "No iov info\n");
23822d07d93SRasesh Mody 		return OSAL_NULL;
23922d07d93SRasesh Mody 	}
24022d07d93SRasesh Mody 
24147b302d6SRasesh Mody 	if (ecore_iov_is_valid_vfid(p_hwfn, relative_vf_id,
24247b302d6SRasesh Mody 				    b_enabled_only, false))
24322d07d93SRasesh Mody 		vf = &p_hwfn->pf_iov_info->vfs_array[relative_vf_id];
24422d07d93SRasesh Mody 	else
24522d07d93SRasesh Mody 		DP_ERR(p_hwfn, "ecore_iov_get_vf_info: VF[%d] is not enabled\n",
24622d07d93SRasesh Mody 		       relative_vf_id);
24722d07d93SRasesh Mody 
24822d07d93SRasesh Mody 	return vf;
24922d07d93SRasesh Mody }
25022d07d93SRasesh Mody 
251eb8e81adSRasesh Mody static struct ecore_queue_cid *
ecore_iov_get_vf_rx_queue_cid(struct ecore_vf_queue * p_queue)25230ecf673SRasesh Mody ecore_iov_get_vf_rx_queue_cid(struct ecore_vf_queue *p_queue)
253eb8e81adSRasesh Mody {
2549ed26bc7SRasesh Mody 	u32 i;
255eb8e81adSRasesh Mody 
256eb8e81adSRasesh Mody 	for (i = 0; i < MAX_QUEUES_PER_QZONE; i++) {
257eb8e81adSRasesh Mody 		if (p_queue->cids[i].p_cid &&
258eb8e81adSRasesh Mody 		    !p_queue->cids[i].b_is_tx)
259eb8e81adSRasesh Mody 			return p_queue->cids[i].p_cid;
260eb8e81adSRasesh Mody 	}
261eb8e81adSRasesh Mody 
262eb8e81adSRasesh Mody 	return OSAL_NULL;
263eb8e81adSRasesh Mody }
264eb8e81adSRasesh Mody 
265eb8e81adSRasesh Mody enum ecore_iov_validate_q_mode {
266eb8e81adSRasesh Mody 	ECORE_IOV_VALIDATE_Q_NA,
267eb8e81adSRasesh Mody 	ECORE_IOV_VALIDATE_Q_ENABLE,
268eb8e81adSRasesh Mody 	ECORE_IOV_VALIDATE_Q_DISABLE,
269eb8e81adSRasesh Mody };
270eb8e81adSRasesh Mody 
ecore_iov_validate_queue_mode(struct ecore_vf_info * p_vf,u16 qid,enum ecore_iov_validate_q_mode mode,bool b_is_tx)27130ecf673SRasesh Mody static bool ecore_iov_validate_queue_mode(struct ecore_vf_info *p_vf,
272eb8e81adSRasesh Mody 					  u16 qid,
273eb8e81adSRasesh Mody 					  enum ecore_iov_validate_q_mode mode,
274eb8e81adSRasesh Mody 					  bool b_is_tx)
275eb8e81adSRasesh Mody {
2769ed26bc7SRasesh Mody 	u32 i;
277eb8e81adSRasesh Mody 
278eb8e81adSRasesh Mody 	if (mode == ECORE_IOV_VALIDATE_Q_NA)
279eb8e81adSRasesh Mody 		return true;
280eb8e81adSRasesh Mody 
281eb8e81adSRasesh Mody 	for (i = 0; i < MAX_QUEUES_PER_QZONE; i++) {
282eb8e81adSRasesh Mody 		struct ecore_vf_queue_cid *p_qcid;
283eb8e81adSRasesh Mody 
284eb8e81adSRasesh Mody 		p_qcid = &p_vf->vf_queues[qid].cids[i];
285eb8e81adSRasesh Mody 
286eb8e81adSRasesh Mody 		if (p_qcid->p_cid == OSAL_NULL)
287eb8e81adSRasesh Mody 			continue;
288eb8e81adSRasesh Mody 
289eb8e81adSRasesh Mody 		if (p_qcid->b_is_tx != b_is_tx)
290eb8e81adSRasesh Mody 			continue;
291eb8e81adSRasesh Mody 
292eb8e81adSRasesh Mody 		/* Found. It's enabled. */
293eb8e81adSRasesh Mody 		return (mode == ECORE_IOV_VALIDATE_Q_ENABLE);
294eb8e81adSRasesh Mody 	}
295eb8e81adSRasesh Mody 
296eb8e81adSRasesh Mody 	/* In case we haven't found any valid cid, then its disabled */
297eb8e81adSRasesh Mody 	return (mode == ECORE_IOV_VALIDATE_Q_DISABLE);
298eb8e81adSRasesh Mody }
299eb8e81adSRasesh Mody 
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)30022d07d93SRasesh Mody static bool ecore_iov_validate_rxq(struct ecore_hwfn *p_hwfn,
30122d07d93SRasesh Mody 				   struct ecore_vf_info *p_vf,
302eb8e81adSRasesh Mody 				   u16 rx_qid,
303eb8e81adSRasesh Mody 				   enum ecore_iov_validate_q_mode mode)
30422d07d93SRasesh Mody {
305eb8e81adSRasesh Mody 	if (rx_qid >= p_vf->num_rxqs) {
30622d07d93SRasesh Mody 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
30722d07d93SRasesh Mody 			   "VF[0x%02x] - can't touch Rx queue[%04x];"
30822d07d93SRasesh Mody 			   " Only 0x%04x are allocated\n",
30922d07d93SRasesh Mody 			   p_vf->abs_vf_id, rx_qid, p_vf->num_rxqs);
310eb8e81adSRasesh Mody 		return false;
311eb8e81adSRasesh Mody 	}
312eb8e81adSRasesh Mody 
31330ecf673SRasesh Mody 	return ecore_iov_validate_queue_mode(p_vf, rx_qid, mode, false);
31422d07d93SRasesh Mody }
31522d07d93SRasesh Mody 
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)31622d07d93SRasesh Mody static bool ecore_iov_validate_txq(struct ecore_hwfn *p_hwfn,
31722d07d93SRasesh Mody 				   struct ecore_vf_info *p_vf,
318eb8e81adSRasesh Mody 				   u16 tx_qid,
319eb8e81adSRasesh Mody 				   enum ecore_iov_validate_q_mode mode)
32022d07d93SRasesh Mody {
321eb8e81adSRasesh Mody 	if (tx_qid >= p_vf->num_txqs) {
32222d07d93SRasesh Mody 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
32322d07d93SRasesh Mody 			   "VF[0x%02x] - can't touch Tx queue[%04x];"
32422d07d93SRasesh Mody 			   " Only 0x%04x are allocated\n",
32522d07d93SRasesh Mody 			   p_vf->abs_vf_id, tx_qid, p_vf->num_txqs);
326eb8e81adSRasesh Mody 		return false;
327eb8e81adSRasesh Mody 	}
328eb8e81adSRasesh Mody 
32930ecf673SRasesh Mody 	return ecore_iov_validate_queue_mode(p_vf, tx_qid, mode, true);
33022d07d93SRasesh Mody }
33122d07d93SRasesh Mody 
ecore_iov_validate_sb(struct ecore_hwfn * p_hwfn,struct ecore_vf_info * p_vf,u16 sb_idx)33222d07d93SRasesh Mody static bool ecore_iov_validate_sb(struct ecore_hwfn *p_hwfn,
33322d07d93SRasesh Mody 				  struct ecore_vf_info *p_vf,
33422d07d93SRasesh Mody 				  u16 sb_idx)
33522d07d93SRasesh Mody {
33622d07d93SRasesh Mody 	int i;
33722d07d93SRasesh Mody 
33822d07d93SRasesh Mody 	for (i = 0; i < p_vf->num_sbs; i++)
33922d07d93SRasesh Mody 		if (p_vf->igu_sbs[i] == sb_idx)
34022d07d93SRasesh Mody 			return true;
34122d07d93SRasesh Mody 
34222d07d93SRasesh Mody 	DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
34322d07d93SRasesh Mody 		   "VF[0%02x] - tried using sb_idx %04x which doesn't exist as"
34422d07d93SRasesh Mody 		   " one of its 0x%02x SBs\n",
34522d07d93SRasesh Mody 		   p_vf->abs_vf_id, sb_idx, p_vf->num_sbs);
34622d07d93SRasesh Mody 
34722d07d93SRasesh Mody 	return false;
34822d07d93SRasesh Mody }
34922d07d93SRasesh Mody 
350eb8e81adSRasesh Mody /* Is there at least 1 queue open? */
ecore_iov_validate_active_rxq(struct ecore_vf_info * p_vf)35130ecf673SRasesh Mody static bool ecore_iov_validate_active_rxq(struct ecore_vf_info *p_vf)
352bd96f72fSRasesh Mody {
353bd96f72fSRasesh Mody 	u8 i;
354bd96f72fSRasesh Mody 
355bd96f72fSRasesh Mody 	for (i = 0; i < p_vf->num_rxqs; i++)
35630ecf673SRasesh Mody 		if (ecore_iov_validate_queue_mode(p_vf, i,
357eb8e81adSRasesh Mody 						  ECORE_IOV_VALIDATE_Q_ENABLE,
358eb8e81adSRasesh Mody 						  false))
359bd96f72fSRasesh Mody 			return true;
360bd96f72fSRasesh Mody 
361bd96f72fSRasesh Mody 	return false;
362bd96f72fSRasesh Mody }
363bd96f72fSRasesh Mody 
ecore_iov_validate_active_txq(struct ecore_vf_info * p_vf)36430ecf673SRasesh Mody static bool ecore_iov_validate_active_txq(struct ecore_vf_info *p_vf)
365bd96f72fSRasesh Mody {
366bd96f72fSRasesh Mody 	u8 i;
367bd96f72fSRasesh Mody 
368eb8e81adSRasesh Mody 	for (i = 0; i < p_vf->num_txqs; i++)
36930ecf673SRasesh Mody 		if (ecore_iov_validate_queue_mode(p_vf, i,
370eb8e81adSRasesh Mody 						  ECORE_IOV_VALIDATE_Q_ENABLE,
371eb8e81adSRasesh Mody 						  true))
372bd96f72fSRasesh Mody 			return true;
373bd96f72fSRasesh Mody 
374bd96f72fSRasesh Mody 	return false;
375bd96f72fSRasesh Mody }
376bd96f72fSRasesh Mody 
ecore_iov_post_vf_bulletin(struct ecore_hwfn * p_hwfn,int vfid,struct ecore_ptt * p_ptt)37786a2265eSRasesh Mody enum _ecore_status_t ecore_iov_post_vf_bulletin(struct ecore_hwfn *p_hwfn,
37886a2265eSRasesh Mody 						int vfid,
37986a2265eSRasesh Mody 						struct ecore_ptt *p_ptt)
38086a2265eSRasesh Mody {
38186a2265eSRasesh Mody 	struct ecore_bulletin_content *p_bulletin;
38222d07d93SRasesh Mody 	int crc_size = sizeof(p_bulletin->crc);
383ea85629fSRasesh Mody 	struct dmae_params params;
38486a2265eSRasesh Mody 	struct ecore_vf_info *p_vf;
38586a2265eSRasesh Mody 
38686a2265eSRasesh Mody 	p_vf = ecore_iov_get_vf_info(p_hwfn, (u16)vfid, true);
38786a2265eSRasesh Mody 	if (!p_vf)
38886a2265eSRasesh Mody 		return ECORE_INVAL;
38986a2265eSRasesh Mody 
39086a2265eSRasesh Mody 	/* TODO - check VF is in a state where it can accept message */
39186a2265eSRasesh Mody 	if (!p_vf->vf_bulletin)
39286a2265eSRasesh Mody 		return ECORE_INVAL;
39386a2265eSRasesh Mody 
39486a2265eSRasesh Mody 	p_bulletin = p_vf->bulletin.p_virt;
39586a2265eSRasesh Mody 
39686a2265eSRasesh Mody 	/* Increment bulletin board version and compute crc */
39786a2265eSRasesh Mody 	p_bulletin->version++;
39803637634SRasesh Mody 	p_bulletin->crc = OSAL_CRC32(0, (u8 *)p_bulletin + crc_size,
39986a2265eSRasesh Mody 				     p_vf->bulletin.size - crc_size);
40086a2265eSRasesh Mody 
40186a2265eSRasesh Mody 	DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
40286a2265eSRasesh Mody 		   "Posting Bulletin 0x%08x to VF[%d] (CRC 0x%08x)\n",
40386a2265eSRasesh Mody 		   p_bulletin->version, p_vf->relative_vf_id, p_bulletin->crc);
40486a2265eSRasesh Mody 
40586a2265eSRasesh Mody 	/* propagate bulletin board via dmae to vm memory */
40686a2265eSRasesh Mody 	OSAL_MEMSET(&params, 0, sizeof(params));
407ea85629fSRasesh Mody 	SET_FIELD(params.flags, DMAE_PARAMS_DST_VF_VALID, 0x1);
408ea85629fSRasesh Mody 	params.dst_vf_id = p_vf->abs_vf_id;
40986a2265eSRasesh Mody 	return ecore_dmae_host2host(p_hwfn, p_ptt, p_vf->bulletin.phys,
41086a2265eSRasesh Mody 				    p_vf->vf_bulletin, p_vf->bulletin.size / 4,
41186a2265eSRasesh Mody 				    &params);
41286a2265eSRasesh Mody }
41386a2265eSRasesh Mody 
ecore_iov_pci_cfg_info(struct ecore_dev * p_dev)41486a2265eSRasesh Mody static enum _ecore_status_t ecore_iov_pci_cfg_info(struct ecore_dev *p_dev)
41586a2265eSRasesh Mody {
41622d07d93SRasesh Mody 	struct ecore_hw_sriov_info *iov = p_dev->p_iov_info;
41786a2265eSRasesh Mody 	int pos = iov->pos;
41886a2265eSRasesh Mody 
41986a2265eSRasesh Mody 	DP_VERBOSE(p_dev, ECORE_MSG_IOV, "sriov ext pos %d\n", pos);
42092c6786eSManish Chopra 	OSAL_PCI_READ_CONFIG_WORD(p_dev, pos + RTE_PCI_SRIOV_CTRL, &iov->ctrl);
42186a2265eSRasesh Mody 
42292c6786eSManish Chopra 	OSAL_PCI_READ_CONFIG_WORD(p_dev, pos + RTE_PCI_SRIOV_TOTAL_VF,
42392c6786eSManish Chopra 				  &iov->total_vfs);
42486a2265eSRasesh Mody 	OSAL_PCI_READ_CONFIG_WORD(p_dev,
42592c6786eSManish Chopra 				  pos + RTE_PCI_SRIOV_INITIAL_VF,
42686a2265eSRasesh Mody 				  &iov->initial_vfs);
42786a2265eSRasesh Mody 
42892c6786eSManish Chopra 	OSAL_PCI_READ_CONFIG_WORD(p_dev, pos + RTE_PCI_SRIOV_NUM_VF,
42992c6786eSManish Chopra 				  &iov->num_vfs);
43086a2265eSRasesh Mody 	if (iov->num_vfs) {
43186a2265eSRasesh Mody 		/* @@@TODO - in future we might want to add an OSAL here to
43286a2265eSRasesh Mody 		 * allow each OS to decide on its own how to act.
43386a2265eSRasesh Mody 		 */
43486a2265eSRasesh Mody 		DP_VERBOSE(p_dev, ECORE_MSG_IOV,
43586a2265eSRasesh Mody 			   "Number of VFs are already set to non-zero value."
43686a2265eSRasesh Mody 			   " Ignoring PCI configuration value\n");
43786a2265eSRasesh Mody 		iov->num_vfs = 0;
43886a2265eSRasesh Mody 	}
43986a2265eSRasesh Mody 
44086a2265eSRasesh Mody 	OSAL_PCI_READ_CONFIG_WORD(p_dev,
44192c6786eSManish Chopra 				  pos + RTE_PCI_SRIOV_VF_OFFSET, &iov->offset);
44286a2265eSRasesh Mody 
44386a2265eSRasesh Mody 	OSAL_PCI_READ_CONFIG_WORD(p_dev,
44492c6786eSManish Chopra 				  pos + RTE_PCI_SRIOV_VF_STRIDE, &iov->stride);
44586a2265eSRasesh Mody 
44692c6786eSManish Chopra 	OSAL_PCI_READ_CONFIG_WORD(p_dev, pos + RTE_PCI_SRIOV_VF_DID,
44792c6786eSManish Chopra 				  &iov->vf_device_id);
44886a2265eSRasesh Mody 
44986a2265eSRasesh Mody 	OSAL_PCI_READ_CONFIG_DWORD(p_dev,
45092c6786eSManish Chopra 				   pos + RTE_PCI_SRIOV_SUP_PGSIZE, &iov->pgsz);
45186a2265eSRasesh Mody 
45292c6786eSManish Chopra 	OSAL_PCI_READ_CONFIG_DWORD(p_dev, pos + RTE_PCI_SRIOV_CAP, &iov->cap);
45386a2265eSRasesh Mody 
45492c6786eSManish Chopra 	OSAL_PCI_READ_CONFIG_BYTE(p_dev, pos + RTE_PCI_SRIOV_FUNC_LINK,
45592c6786eSManish Chopra 				  &iov->link);
45686a2265eSRasesh Mody 
4573013f8c1SRasesh Mody 	DP_VERBOSE(p_dev, ECORE_MSG_IOV, "IOV info: nres %d, cap 0x%x,"
45886a2265eSRasesh Mody 		   "ctrl 0x%x, total %d, initial %d, num vfs %d, offset %d,"
4593013f8c1SRasesh Mody 		   " stride %d, page size 0x%x\n",
46086a2265eSRasesh Mody 		   iov->nres, iov->cap, iov->ctrl,
46186a2265eSRasesh Mody 		   iov->total_vfs, iov->initial_vfs, iov->nr_virtfn,
46286a2265eSRasesh Mody 		   iov->offset, iov->stride, iov->pgsz);
46386a2265eSRasesh Mody 
46486a2265eSRasesh Mody 	/* Some sanity checks */
46586a2265eSRasesh Mody 	if (iov->num_vfs > NUM_OF_VFS(p_dev) ||
46686a2265eSRasesh Mody 	    iov->total_vfs > NUM_OF_VFS(p_dev)) {
46786a2265eSRasesh Mody 		/* This can happen only due to a bug. In this case we set
46886a2265eSRasesh Mody 		 * num_vfs to zero to avoid memory corruption in the code that
46986a2265eSRasesh Mody 		 * assumes max number of vfs
47086a2265eSRasesh Mody 		 */
47186a2265eSRasesh Mody 		DP_NOTICE(p_dev, false,
47286a2265eSRasesh Mody 			  "IOV: Unexpected number of vfs set: %d"
47386a2265eSRasesh Mody 			  " setting num_vf to zero\n",
47486a2265eSRasesh Mody 			  iov->num_vfs);
47586a2265eSRasesh Mody 
47686a2265eSRasesh Mody 		iov->num_vfs = 0;
47786a2265eSRasesh Mody 		iov->total_vfs = 0;
47886a2265eSRasesh Mody 	}
47986a2265eSRasesh Mody 
48086a2265eSRasesh Mody 	return ECORE_SUCCESS;
48186a2265eSRasesh Mody }
48286a2265eSRasesh Mody 
ecore_iov_setup_vfdb(struct ecore_hwfn * p_hwfn)48386a2265eSRasesh Mody static void ecore_iov_setup_vfdb(struct ecore_hwfn *p_hwfn)
48486a2265eSRasesh Mody {
48522d07d93SRasesh Mody 	struct ecore_hw_sriov_info *p_iov = p_hwfn->p_dev->p_iov_info;
48622d07d93SRasesh Mody 	struct ecore_pf_iov *p_iov_info = p_hwfn->pf_iov_info;
48722d07d93SRasesh Mody 	struct ecore_bulletin_content *p_bulletin_virt;
48822d07d93SRasesh Mody 	dma_addr_t req_p, rply_p, bulletin_p;
48986a2265eSRasesh Mody 	union pfvf_tlvs *p_reply_virt_addr;
49086a2265eSRasesh Mody 	union vfpf_tlvs *p_req_virt_addr;
49186a2265eSRasesh Mody 	u8 idx = 0;
49286a2265eSRasesh Mody 
49386a2265eSRasesh Mody 	OSAL_MEMSET(p_iov_info->vfs_array, 0, sizeof(p_iov_info->vfs_array));
49486a2265eSRasesh Mody 
49586a2265eSRasesh Mody 	p_req_virt_addr = p_iov_info->mbx_msg_virt_addr;
49686a2265eSRasesh Mody 	req_p = p_iov_info->mbx_msg_phys_addr;
49786a2265eSRasesh Mody 	p_reply_virt_addr = p_iov_info->mbx_reply_virt_addr;
49886a2265eSRasesh Mody 	rply_p = p_iov_info->mbx_reply_phys_addr;
49986a2265eSRasesh Mody 	p_bulletin_virt = p_iov_info->p_bulletins;
50086a2265eSRasesh Mody 	bulletin_p = p_iov_info->bulletins_phys;
50186a2265eSRasesh Mody 	if (!p_req_virt_addr || !p_reply_virt_addr || !p_bulletin_virt) {
50286a2265eSRasesh Mody 		DP_ERR(p_hwfn,
50386a2265eSRasesh Mody 		       "ecore_iov_setup_vfdb called without alloc mem first\n");
50486a2265eSRasesh Mody 		return;
50586a2265eSRasesh Mody 	}
50686a2265eSRasesh Mody 
50722d07d93SRasesh Mody 	for (idx = 0; idx < p_iov->total_vfs; idx++) {
50886a2265eSRasesh Mody 		struct ecore_vf_info *vf = &p_iov_info->vfs_array[idx];
50986a2265eSRasesh Mody 		u32 concrete;
51086a2265eSRasesh Mody 
51186a2265eSRasesh Mody 		vf->vf_mbx.req_virt = p_req_virt_addr + idx;
51286a2265eSRasesh Mody 		vf->vf_mbx.req_phys = req_p + idx * sizeof(union vfpf_tlvs);
51386a2265eSRasesh Mody 		vf->vf_mbx.reply_virt = p_reply_virt_addr + idx;
51486a2265eSRasesh Mody 		vf->vf_mbx.reply_phys = rply_p + idx * sizeof(union pfvf_tlvs);
51586a2265eSRasesh Mody 
51686a2265eSRasesh Mody #ifdef CONFIG_ECORE_SW_CHANNEL
51786a2265eSRasesh Mody 		vf->vf_mbx.sw_mbx.request_size = sizeof(union vfpf_tlvs);
51886a2265eSRasesh Mody 		vf->vf_mbx.sw_mbx.mbx_state = VF_PF_WAIT_FOR_START_REQUEST;
51986a2265eSRasesh Mody #endif
52086a2265eSRasesh Mody 		vf->state = VF_STOPPED;
52122d07d93SRasesh Mody 		vf->b_init = false;
52286a2265eSRasesh Mody 
52386a2265eSRasesh Mody 		vf->bulletin.phys = idx *
52486a2265eSRasesh Mody 		    sizeof(struct ecore_bulletin_content) + bulletin_p;
52586a2265eSRasesh Mody 		vf->bulletin.p_virt = p_bulletin_virt + idx;
52686a2265eSRasesh Mody 		vf->bulletin.size = sizeof(struct ecore_bulletin_content);
52786a2265eSRasesh Mody 
52886a2265eSRasesh Mody 		vf->relative_vf_id = idx;
52922d07d93SRasesh Mody 		vf->abs_vf_id = idx + p_iov->first_vf_in_pf;
53086a2265eSRasesh Mody 		concrete = ecore_vfid_to_concrete(p_hwfn, vf->abs_vf_id);
53186a2265eSRasesh Mody 		vf->concrete_fid = concrete;
53286a2265eSRasesh Mody 		/* TODO - need to devise a better way of getting opaque */
53386a2265eSRasesh Mody 		vf->opaque_fid = (p_hwfn->hw_info.opaque_fid & 0xff) |
53486a2265eSRasesh Mody 		    (vf->abs_vf_id << 8);
53522d07d93SRasesh Mody 
53622d07d93SRasesh Mody 		vf->num_mac_filters = ECORE_ETH_VF_NUM_MAC_FILTERS;
53722d07d93SRasesh Mody 		vf->num_vlan_filters = ECORE_ETH_VF_NUM_VLAN_FILTERS;
53886a2265eSRasesh Mody 	}
53986a2265eSRasesh Mody }
54086a2265eSRasesh Mody 
ecore_iov_allocate_vfdb(struct ecore_hwfn * p_hwfn)54186a2265eSRasesh Mody static enum _ecore_status_t ecore_iov_allocate_vfdb(struct ecore_hwfn *p_hwfn)
54286a2265eSRasesh Mody {
54386a2265eSRasesh Mody 	struct ecore_pf_iov *p_iov_info = p_hwfn->pf_iov_info;
54486a2265eSRasesh Mody 	void **p_v_addr;
54586a2265eSRasesh Mody 	u16 num_vfs = 0;
54686a2265eSRasesh Mody 
54722d07d93SRasesh Mody 	num_vfs = p_hwfn->p_dev->p_iov_info->total_vfs;
54886a2265eSRasesh Mody 
54986a2265eSRasesh Mody 	DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
55086a2265eSRasesh Mody 		   "ecore_iov_allocate_vfdb for %d VFs\n", num_vfs);
55186a2265eSRasesh Mody 
55286a2265eSRasesh Mody 	/* Allocate PF Mailbox buffer (per-VF) */
55386a2265eSRasesh Mody 	p_iov_info->mbx_msg_size = sizeof(union vfpf_tlvs) * num_vfs;
55486a2265eSRasesh Mody 	p_v_addr = &p_iov_info->mbx_msg_virt_addr;
55586a2265eSRasesh Mody 	*p_v_addr = OSAL_DMA_ALLOC_COHERENT(p_hwfn->p_dev,
55686a2265eSRasesh Mody 					    &p_iov_info->mbx_msg_phys_addr,
55786a2265eSRasesh Mody 					    p_iov_info->mbx_msg_size);
55886a2265eSRasesh Mody 	if (!*p_v_addr)
55986a2265eSRasesh Mody 		return ECORE_NOMEM;
56086a2265eSRasesh Mody 
56186a2265eSRasesh Mody 	/* Allocate PF Mailbox Reply buffer (per-VF) */
56286a2265eSRasesh Mody 	p_iov_info->mbx_reply_size = sizeof(union pfvf_tlvs) * num_vfs;
56386a2265eSRasesh Mody 	p_v_addr = &p_iov_info->mbx_reply_virt_addr;
56486a2265eSRasesh Mody 	*p_v_addr = OSAL_DMA_ALLOC_COHERENT(p_hwfn->p_dev,
56586a2265eSRasesh Mody 					    &p_iov_info->mbx_reply_phys_addr,
56686a2265eSRasesh Mody 					    p_iov_info->mbx_reply_size);
56786a2265eSRasesh Mody 	if (!*p_v_addr)
56886a2265eSRasesh Mody 		return ECORE_NOMEM;
56986a2265eSRasesh Mody 
57086a2265eSRasesh Mody 	p_iov_info->bulletins_size = sizeof(struct ecore_bulletin_content) *
57186a2265eSRasesh Mody 	    num_vfs;
57286a2265eSRasesh Mody 	p_v_addr = &p_iov_info->p_bulletins;
57386a2265eSRasesh Mody 	*p_v_addr = OSAL_DMA_ALLOC_COHERENT(p_hwfn->p_dev,
57486a2265eSRasesh Mody 					    &p_iov_info->bulletins_phys,
57586a2265eSRasesh Mody 					    p_iov_info->bulletins_size);
57686a2265eSRasesh Mody 	if (!*p_v_addr)
57786a2265eSRasesh Mody 		return ECORE_NOMEM;
57886a2265eSRasesh Mody 
57986a2265eSRasesh Mody 	DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
58022d07d93SRasesh Mody 		   "PF's Requests mailbox [%p virt 0x%lx phys],  "
58122d07d93SRasesh Mody 		   "Response mailbox [%p virt 0x%lx phys] Bulletinsi"
58222d07d93SRasesh Mody 		   " [%p virt 0x%lx phys]\n",
58386a2265eSRasesh Mody 		   p_iov_info->mbx_msg_virt_addr,
58422d07d93SRasesh Mody 		   (unsigned long)p_iov_info->mbx_msg_phys_addr,
58586a2265eSRasesh Mody 		   p_iov_info->mbx_reply_virt_addr,
58622d07d93SRasesh Mody 		   (unsigned long)p_iov_info->mbx_reply_phys_addr,
58722d07d93SRasesh Mody 		   p_iov_info->p_bulletins,
58822d07d93SRasesh Mody 		   (unsigned long)p_iov_info->bulletins_phys);
58986a2265eSRasesh Mody 
59086a2265eSRasesh Mody 	return ECORE_SUCCESS;
59186a2265eSRasesh Mody }
59286a2265eSRasesh Mody 
ecore_iov_free_vfdb(struct ecore_hwfn * p_hwfn)59386a2265eSRasesh Mody static void ecore_iov_free_vfdb(struct ecore_hwfn *p_hwfn)
59486a2265eSRasesh Mody {
59586a2265eSRasesh Mody 	struct ecore_pf_iov *p_iov_info = p_hwfn->pf_iov_info;
59686a2265eSRasesh Mody 
59786a2265eSRasesh Mody 	if (p_hwfn->pf_iov_info->mbx_msg_virt_addr)
59886a2265eSRasesh Mody 		OSAL_DMA_FREE_COHERENT(p_hwfn->p_dev,
59986a2265eSRasesh Mody 				       p_iov_info->mbx_msg_virt_addr,
60086a2265eSRasesh Mody 				       p_iov_info->mbx_msg_phys_addr,
60186a2265eSRasesh Mody 				       p_iov_info->mbx_msg_size);
60286a2265eSRasesh Mody 
60386a2265eSRasesh Mody 	if (p_hwfn->pf_iov_info->mbx_reply_virt_addr)
60486a2265eSRasesh Mody 		OSAL_DMA_FREE_COHERENT(p_hwfn->p_dev,
60586a2265eSRasesh Mody 				       p_iov_info->mbx_reply_virt_addr,
60686a2265eSRasesh Mody 				       p_iov_info->mbx_reply_phys_addr,
60786a2265eSRasesh Mody 				       p_iov_info->mbx_reply_size);
60886a2265eSRasesh Mody 
60986a2265eSRasesh Mody 	if (p_iov_info->p_bulletins)
61086a2265eSRasesh Mody 		OSAL_DMA_FREE_COHERENT(p_hwfn->p_dev,
61186a2265eSRasesh Mody 				       p_iov_info->p_bulletins,
61286a2265eSRasesh Mody 				       p_iov_info->bulletins_phys,
61386a2265eSRasesh Mody 				       p_iov_info->bulletins_size);
61486a2265eSRasesh Mody }
61586a2265eSRasesh Mody 
ecore_iov_alloc(struct ecore_hwfn * p_hwfn)61686a2265eSRasesh Mody enum _ecore_status_t ecore_iov_alloc(struct ecore_hwfn *p_hwfn)
61786a2265eSRasesh Mody {
61886a2265eSRasesh Mody 	struct ecore_pf_iov *p_sriov;
61986a2265eSRasesh Mody 
62086a2265eSRasesh Mody 	if (!IS_PF_SRIOV(p_hwfn)) {
62186a2265eSRasesh Mody 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
62286a2265eSRasesh Mody 			   "No SR-IOV - no need for IOV db\n");
62322d07d93SRasesh Mody 		return ECORE_SUCCESS;
62486a2265eSRasesh Mody 	}
62586a2265eSRasesh Mody 
62686a2265eSRasesh Mody 	p_sriov = OSAL_ZALLOC(p_hwfn->p_dev, GFP_KERNEL, sizeof(*p_sriov));
62786a2265eSRasesh Mody 	if (!p_sriov) {
62898abf84eSRasesh Mody 		DP_NOTICE(p_hwfn, false, "Failed to allocate `struct ecore_sriov'\n");
62986a2265eSRasesh Mody 		return ECORE_NOMEM;
63086a2265eSRasesh Mody 	}
63186a2265eSRasesh Mody 
63286a2265eSRasesh Mody 	p_hwfn->pf_iov_info = p_sriov;
63386a2265eSRasesh Mody 
6347f474588SRasesh Mody 	ecore_spq_register_async_cb(p_hwfn, PROTOCOLID_COMMON,
6357f474588SRasesh Mody 				    ecore_sriov_eqe_event);
6367f474588SRasesh Mody 
63722d07d93SRasesh Mody 	return ecore_iov_allocate_vfdb(p_hwfn);
63886a2265eSRasesh Mody }
63986a2265eSRasesh Mody 
ecore_iov_setup(struct ecore_hwfn * p_hwfn)640739a5b2fSRasesh Mody void ecore_iov_setup(struct ecore_hwfn *p_hwfn)
64186a2265eSRasesh Mody {
64222d07d93SRasesh Mody 	if (!IS_PF_SRIOV(p_hwfn) || !IS_PF_SRIOV_ALLOC(p_hwfn))
64386a2265eSRasesh Mody 		return;
64486a2265eSRasesh Mody 
64586a2265eSRasesh Mody 	ecore_iov_setup_vfdb(p_hwfn);
64686a2265eSRasesh Mody }
64786a2265eSRasesh Mody 
ecore_iov_free(struct ecore_hwfn * p_hwfn)64886a2265eSRasesh Mody void ecore_iov_free(struct ecore_hwfn *p_hwfn)
64986a2265eSRasesh Mody {
6507f474588SRasesh Mody 	ecore_spq_unregister_async_cb(p_hwfn, PROTOCOLID_COMMON);
6517f474588SRasesh Mody 
65222d07d93SRasesh Mody 	if (IS_PF_SRIOV_ALLOC(p_hwfn)) {
65386a2265eSRasesh Mody 		ecore_iov_free_vfdb(p_hwfn);
65486a2265eSRasesh Mody 		OSAL_FREE(p_hwfn->p_dev, p_hwfn->pf_iov_info);
65586a2265eSRasesh Mody 	}
65686a2265eSRasesh Mody }
65786a2265eSRasesh Mody 
ecore_iov_free_hw_info(struct ecore_dev * p_dev)65822d07d93SRasesh Mody void ecore_iov_free_hw_info(struct ecore_dev *p_dev)
65986a2265eSRasesh Mody {
66022d07d93SRasesh Mody 	OSAL_FREE(p_dev, p_dev->p_iov_info);
66122d07d93SRasesh Mody }
66222d07d93SRasesh Mody 
ecore_iov_hw_info(struct ecore_hwfn * p_hwfn)66322d07d93SRasesh Mody enum _ecore_status_t ecore_iov_hw_info(struct ecore_hwfn *p_hwfn)
66422d07d93SRasesh Mody {
66522d07d93SRasesh Mody 	struct ecore_dev *p_dev = p_hwfn->p_dev;
66622d07d93SRasesh Mody 	int pos;
66786a2265eSRasesh Mody 	enum _ecore_status_t rc;
66886a2265eSRasesh Mody 
66986a2265eSRasesh Mody 	if (IS_VF(p_hwfn->p_dev))
67086a2265eSRasesh Mody 		return ECORE_SUCCESS;
67186a2265eSRasesh Mody 
67222d07d93SRasesh Mody 	/* Learn the PCI configuration */
67322d07d93SRasesh Mody 	pos = OSAL_PCI_FIND_EXT_CAPABILITY(p_hwfn->p_dev,
67492c6786eSManish Chopra 					   RTE_PCI_EXT_CAP_ID_SRIOV);
67522d07d93SRasesh Mody 	if (!pos) {
67622d07d93SRasesh Mody 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV, "No PCIe IOV support\n");
67786a2265eSRasesh Mody 		return ECORE_SUCCESS;
67886a2265eSRasesh Mody 	}
67986a2265eSRasesh Mody 
68022d07d93SRasesh Mody 	/* Allocate a new struct for IOV information */
68122d07d93SRasesh Mody 	/* TODO - can change to VALLOC when its available */
68222d07d93SRasesh Mody 	p_dev->p_iov_info = OSAL_ZALLOC(p_dev, GFP_KERNEL,
68322d07d93SRasesh Mody 					sizeof(*p_dev->p_iov_info));
68422d07d93SRasesh Mody 	if (!p_dev->p_iov_info) {
68598abf84eSRasesh Mody 		DP_NOTICE(p_hwfn, false,
68622d07d93SRasesh Mody 			  "Can't support IOV due to lack of memory\n");
68722d07d93SRasesh Mody 		return ECORE_NOMEM;
68822d07d93SRasesh Mody 	}
68922d07d93SRasesh Mody 	p_dev->p_iov_info->pos = pos;
69022d07d93SRasesh Mody 
69186a2265eSRasesh Mody 	rc = ecore_iov_pci_cfg_info(p_dev);
69286a2265eSRasesh Mody 	if (rc)
69386a2265eSRasesh Mody 		return rc;
69422d07d93SRasesh Mody 
69522d07d93SRasesh Mody 	/* We want PF IOV to be synonemous with the existence of p_iov_info;
69622d07d93SRasesh Mody 	 * In case the capability is published but there are no VFs, simply
69722d07d93SRasesh Mody 	 * de-allocate the struct.
69822d07d93SRasesh Mody 	 */
69922d07d93SRasesh Mody 	if (!p_dev->p_iov_info->total_vfs) {
70022d07d93SRasesh Mody 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
70122d07d93SRasesh Mody 			   "IOV capabilities, but no VFs are published\n");
70222d07d93SRasesh Mody 		OSAL_FREE(p_dev, p_dev->p_iov_info);
70386a2265eSRasesh Mody 		return ECORE_SUCCESS;
70486a2265eSRasesh Mody 	}
70586a2265eSRasesh Mody 
7061c46a0fcSRasesh Mody 	/* First VF index based on offset is tricky:
7071c46a0fcSRasesh Mody 	 *  - If ARI is supported [likely], offset - (16 - pf_id) would
7081c46a0fcSRasesh Mody 	 *    provide the number for eng0. 2nd engine Vfs would begin
70986a2265eSRasesh Mody 	 *    after the first engine's VFs.
7101c46a0fcSRasesh Mody 	 *  - If !ARI, VFs would start on next device.
7111c46a0fcSRasesh Mody 	 *    so offset - (256 - pf_id) would provide the number.
7121c46a0fcSRasesh Mody 	 * Utilize the fact that (256 - pf_id) is achieved only be later
7131c46a0fcSRasesh Mody 	 * to diffrentiate between the two.
71486a2265eSRasesh Mody 	 */
7151c46a0fcSRasesh Mody 
7161c46a0fcSRasesh Mody 	if (p_hwfn->p_dev->p_iov_info->offset < (256 - p_hwfn->abs_pf_id)) {
7171c46a0fcSRasesh Mody 		u32 first = p_hwfn->p_dev->p_iov_info->offset +
71886a2265eSRasesh Mody 			    p_hwfn->abs_pf_id - 16;
7191c46a0fcSRasesh Mody 
7201c46a0fcSRasesh Mody 		p_dev->p_iov_info->first_vf_in_pf = first;
7211c46a0fcSRasesh Mody 
72286a2265eSRasesh Mody 		if (ECORE_PATH_ID(p_hwfn))
72322d07d93SRasesh Mody 			p_dev->p_iov_info->first_vf_in_pf -= MAX_NUM_VFS_BB;
7241c46a0fcSRasesh Mody 	} else {
7251c46a0fcSRasesh Mody 		u32 first = p_hwfn->p_dev->p_iov_info->offset +
7261c46a0fcSRasesh Mody 			    p_hwfn->abs_pf_id - 256;
7271c46a0fcSRasesh Mody 
7281c46a0fcSRasesh Mody 		p_dev->p_iov_info->first_vf_in_pf = first;
7291c46a0fcSRasesh Mody 	}
73086a2265eSRasesh Mody 
73186a2265eSRasesh Mody 	DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
73222d07d93SRasesh Mody 		   "First VF in hwfn 0x%08x\n",
73322d07d93SRasesh Mody 		   p_dev->p_iov_info->first_vf_in_pf);
73486a2265eSRasesh Mody 
73586a2265eSRasesh Mody 	return ECORE_SUCCESS;
73686a2265eSRasesh Mody }
73786a2265eSRasesh Mody 
_ecore_iov_pf_sanity_check(struct ecore_hwfn * p_hwfn,int vfid,bool b_fail_malicious)7385ef41193SRasesh Mody static bool _ecore_iov_pf_sanity_check(struct ecore_hwfn *p_hwfn, int vfid,
73947b302d6SRasesh Mody 				       bool b_fail_malicious)
74086a2265eSRasesh Mody {
74122d07d93SRasesh Mody 	/* Check PF supports sriov */
74222d07d93SRasesh Mody 	if (IS_VF(p_hwfn->p_dev) || !IS_ECORE_SRIOV(p_hwfn->p_dev) ||
74322d07d93SRasesh Mody 	    !IS_PF_SRIOV_ALLOC(p_hwfn))
74422d07d93SRasesh Mody 		return false;
74586a2265eSRasesh Mody 
74622d07d93SRasesh Mody 	/* Check VF validity */
74747b302d6SRasesh Mody 	if (!ecore_iov_is_valid_vfid(p_hwfn, vfid, true, b_fail_malicious))
74822d07d93SRasesh Mody 		return false;
74922d07d93SRasesh Mody 
75022d07d93SRasesh Mody 	return true;
75186a2265eSRasesh Mody }
75286a2265eSRasesh Mody 
ecore_iov_pf_sanity_check(struct ecore_hwfn * p_hwfn,int vfid)75347b302d6SRasesh Mody bool ecore_iov_pf_sanity_check(struct ecore_hwfn *p_hwfn, int vfid)
75447b302d6SRasesh Mody {
75547b302d6SRasesh Mody 	return _ecore_iov_pf_sanity_check(p_hwfn, vfid, true);
75647b302d6SRasesh Mody }
75747b302d6SRasesh Mody 
ecore_iov_set_vf_to_disable(struct ecore_dev * p_dev,u16 rel_vf_id,u8 to_disable)75822d07d93SRasesh Mody void ecore_iov_set_vf_to_disable(struct ecore_dev *p_dev,
75986a2265eSRasesh Mody 				 u16 rel_vf_id, u8 to_disable)
76086a2265eSRasesh Mody {
76186a2265eSRasesh Mody 	struct ecore_vf_info *vf;
76222d07d93SRasesh Mody 	int i;
76322d07d93SRasesh Mody 
76422d07d93SRasesh Mody 	for_each_hwfn(p_dev, i) {
76522d07d93SRasesh Mody 		struct ecore_hwfn *p_hwfn = &p_dev->hwfns[i];
76686a2265eSRasesh Mody 
76786a2265eSRasesh Mody 		vf = ecore_iov_get_vf_info(p_hwfn, rel_vf_id, false);
76886a2265eSRasesh Mody 		if (!vf)
76922d07d93SRasesh Mody 			continue;
77086a2265eSRasesh Mody 
77186a2265eSRasesh Mody 		vf->to_disable = to_disable;
77286a2265eSRasesh Mody 	}
77322d07d93SRasesh Mody }
77486a2265eSRasesh Mody 
ecore_iov_set_vfs_to_disable(struct ecore_dev * p_dev,u8 to_disable)77522d07d93SRasesh Mody void ecore_iov_set_vfs_to_disable(struct ecore_dev *p_dev,
77622d07d93SRasesh Mody 				  u8 to_disable)
77786a2265eSRasesh Mody {
77886a2265eSRasesh Mody 	u16 i;
77986a2265eSRasesh Mody 
78022d07d93SRasesh Mody 	if (!IS_ECORE_SRIOV(p_dev))
78122d07d93SRasesh Mody 		return;
78222d07d93SRasesh Mody 
78322d07d93SRasesh Mody 	for (i = 0; i < p_dev->p_iov_info->total_vfs; i++)
78422d07d93SRasesh Mody 		ecore_iov_set_vf_to_disable(p_dev, i, to_disable);
78586a2265eSRasesh Mody }
78686a2265eSRasesh Mody 
78786a2265eSRasesh Mody #ifndef LINUX_REMOVE
78886a2265eSRasesh Mody /* @@@TBD Consider taking outside of ecore... */
ecore_iov_set_vf_ctx(struct ecore_hwfn * p_hwfn,u16 vf_id,void * ctx)78986a2265eSRasesh Mody enum _ecore_status_t ecore_iov_set_vf_ctx(struct ecore_hwfn *p_hwfn,
79022d07d93SRasesh Mody 					  u16		    vf_id,
79122d07d93SRasesh Mody 					  void		    *ctx)
79286a2265eSRasesh Mody {
79386a2265eSRasesh Mody 	enum _ecore_status_t rc = ECORE_SUCCESS;
79486a2265eSRasesh Mody 	struct ecore_vf_info *vf = ecore_iov_get_vf_info(p_hwfn, vf_id, true);
79586a2265eSRasesh Mody 
79686a2265eSRasesh Mody 	if (vf != OSAL_NULL) {
79786a2265eSRasesh Mody 		vf->ctx = ctx;
79886a2265eSRasesh Mody #ifdef CONFIG_ECORE_SW_CHANNEL
79986a2265eSRasesh Mody 		vf->vf_mbx.sw_mbx.mbx_state = VF_PF_WAIT_FOR_START_REQUEST;
80086a2265eSRasesh Mody #endif
80186a2265eSRasesh Mody 	} else {
80286a2265eSRasesh Mody 		rc = ECORE_UNKNOWN_ERROR;
80386a2265eSRasesh Mody 	}
80486a2265eSRasesh Mody 	return rc;
80586a2265eSRasesh Mody }
80686a2265eSRasesh Mody #endif
80786a2265eSRasesh Mody 
ecore_iov_vf_pglue_clear_err(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u8 abs_vfid)80886a2265eSRasesh Mody static void ecore_iov_vf_pglue_clear_err(struct ecore_hwfn      *p_hwfn,
80922d07d93SRasesh Mody 					 struct ecore_ptt	*p_ptt,
81022d07d93SRasesh Mody 					 u8			abs_vfid)
81186a2265eSRasesh Mody {
81286a2265eSRasesh Mody 	ecore_wr(p_hwfn, p_ptt,
81386a2265eSRasesh Mody 		 PGLUE_B_REG_WAS_ERROR_VF_31_0_CLR + (abs_vfid >> 5) * 4,
81486a2265eSRasesh Mody 		 1 << (abs_vfid & 0x1f));
81586a2265eSRasesh Mody }
81686a2265eSRasesh Mody 
ecore_iov_vf_igu_reset(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * vf)81786a2265eSRasesh Mody static void ecore_iov_vf_igu_reset(struct ecore_hwfn *p_hwfn,
81886a2265eSRasesh Mody 				   struct ecore_ptt *p_ptt,
81986a2265eSRasesh Mody 				   struct ecore_vf_info *vf)
82086a2265eSRasesh Mody {
82186a2265eSRasesh Mody 	int i;
82286a2265eSRasesh Mody 
82386a2265eSRasesh Mody 	/* Set VF masks and configuration - pretend */
82486a2265eSRasesh Mody 	ecore_fid_pretend(p_hwfn, p_ptt, (u16)vf->concrete_fid);
82586a2265eSRasesh Mody 
82686a2265eSRasesh Mody 	ecore_wr(p_hwfn, p_ptt, IGU_REG_STATISTIC_NUM_VF_MSG_SENT, 0);
82786a2265eSRasesh Mody 
82886a2265eSRasesh Mody 	/* unpretend */
82986a2265eSRasesh Mody 	ecore_fid_pretend(p_hwfn, p_ptt, (u16)p_hwfn->hw_info.concrete_fid);
83086a2265eSRasesh Mody 
83122d07d93SRasesh Mody 	/* iterate over all queues, clear sb consumer */
83222d07d93SRasesh Mody 	for (i = 0; i < vf->num_sbs; i++)
83322d07d93SRasesh Mody 		ecore_int_igu_init_pure_rt_single(p_hwfn, p_ptt,
83422d07d93SRasesh Mody 						  vf->igu_sbs[i],
83522d07d93SRasesh Mody 						  vf->opaque_fid, true);
83686a2265eSRasesh Mody }
83786a2265eSRasesh Mody 
ecore_iov_vf_igu_set_int(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * vf,bool enable)83886a2265eSRasesh Mody static void ecore_iov_vf_igu_set_int(struct ecore_hwfn *p_hwfn,
83986a2265eSRasesh Mody 				     struct ecore_ptt *p_ptt,
84086a2265eSRasesh Mody 				     struct ecore_vf_info *vf, bool enable)
84186a2265eSRasesh Mody {
84286a2265eSRasesh Mody 	u32 igu_vf_conf;
84386a2265eSRasesh Mody 
84486a2265eSRasesh Mody 	ecore_fid_pretend(p_hwfn, p_ptt, (u16)vf->concrete_fid);
84586a2265eSRasesh Mody 
84686a2265eSRasesh Mody 	igu_vf_conf = ecore_rd(p_hwfn, p_ptt, IGU_REG_VF_CONFIGURATION);
84786a2265eSRasesh Mody 
84886a2265eSRasesh Mody 	if (enable)
84986a2265eSRasesh Mody 		igu_vf_conf |= IGU_VF_CONF_MSI_MSIX_EN;
85086a2265eSRasesh Mody 	else
85186a2265eSRasesh Mody 		igu_vf_conf &= ~IGU_VF_CONF_MSI_MSIX_EN;
85286a2265eSRasesh Mody 
85386a2265eSRasesh Mody 	ecore_wr(p_hwfn, p_ptt, IGU_REG_VF_CONFIGURATION, igu_vf_conf);
85486a2265eSRasesh Mody 
85586a2265eSRasesh Mody 	/* unpretend */
85686a2265eSRasesh Mody 	ecore_fid_pretend(p_hwfn, p_ptt, (u16)p_hwfn->hw_info.concrete_fid);
85786a2265eSRasesh Mody }
85886a2265eSRasesh Mody 
85986a2265eSRasesh Mody 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)860cb051eb2SRasesh Mody ecore_iov_enable_vf_access_msix(struct ecore_hwfn *p_hwfn,
861cb051eb2SRasesh Mody 				struct ecore_ptt *p_ptt,
862cb051eb2SRasesh Mody 				u8 abs_vf_id,
863cb051eb2SRasesh Mody 				u8 num_sbs)
864cb051eb2SRasesh Mody {
865cb051eb2SRasesh Mody 	u8 current_max = 0;
866cb051eb2SRasesh Mody 	int i;
867cb051eb2SRasesh Mody 
868cb051eb2SRasesh Mody 	/* If client overrides this, don't do anything */
869cb051eb2SRasesh Mody 	if (p_hwfn->p_dev->b_dont_override_vf_msix)
870cb051eb2SRasesh Mody 		return ECORE_SUCCESS;
871cb051eb2SRasesh Mody 
872cb051eb2SRasesh Mody 	/* For AH onward, configuration is per-PF. Find maximum of all
873cb051eb2SRasesh Mody 	 * the currently enabled child VFs, and set the number to be that.
874cb051eb2SRasesh Mody 	 */
875cb051eb2SRasesh Mody 	if (!ECORE_IS_BB(p_hwfn->p_dev)) {
876cb051eb2SRasesh Mody 		ecore_for_each_vf(p_hwfn, i) {
877cb051eb2SRasesh Mody 			struct ecore_vf_info *p_vf;
878cb051eb2SRasesh Mody 
879cb051eb2SRasesh Mody 			p_vf  = ecore_iov_get_vf_info(p_hwfn, (u16)i, true);
880cb051eb2SRasesh Mody 			if (!p_vf)
881cb051eb2SRasesh Mody 				continue;
882cb051eb2SRasesh Mody 
883cb051eb2SRasesh Mody 			current_max = OSAL_MAX_T(u8, current_max,
884cb051eb2SRasesh Mody 						 p_vf->num_sbs);
885cb051eb2SRasesh Mody 		}
886cb051eb2SRasesh Mody 	}
887cb051eb2SRasesh Mody 
888cb051eb2SRasesh Mody 	if (num_sbs > current_max)
889cb051eb2SRasesh Mody 		return ecore_mcp_config_vf_msix(p_hwfn, p_ptt,
890cb051eb2SRasesh Mody 						abs_vf_id, num_sbs);
891cb051eb2SRasesh Mody 
892cb051eb2SRasesh Mody 	return ECORE_SUCCESS;
893cb051eb2SRasesh Mody }
894cb051eb2SRasesh Mody 
895cb051eb2SRasesh Mody static enum _ecore_status_t
ecore_iov_enable_vf_access(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * vf)89686a2265eSRasesh Mody ecore_iov_enable_vf_access(struct ecore_hwfn *p_hwfn,
89786a2265eSRasesh Mody 			   struct ecore_ptt *p_ptt, struct ecore_vf_info *vf)
89886a2265eSRasesh Mody {
89986a2265eSRasesh Mody 	u32 igu_vf_conf = IGU_VF_CONF_FUNC_EN;
900cb051eb2SRasesh Mody 	enum _ecore_status_t rc = ECORE_SUCCESS;
90186a2265eSRasesh Mody 
902eb35c732SRasesh Mody 	/* It's possible VF was previously considered malicious -
903eb35c732SRasesh Mody 	 * clear the indication even if we're only going to disable VF.
904eb35c732SRasesh Mody 	 */
905eb35c732SRasesh Mody 	vf->b_malicious = false;
906eb35c732SRasesh Mody 
90786a2265eSRasesh Mody 	if (vf->to_disable)
90886a2265eSRasesh Mody 		return ECORE_SUCCESS;
90986a2265eSRasesh Mody 
91086a2265eSRasesh Mody 	DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
91186a2265eSRasesh Mody 		   "Enable internal access for vf %x [abs %x]\n", vf->abs_vf_id,
91286a2265eSRasesh Mody 		   ECORE_VF_ABS_ID(p_hwfn, vf));
91386a2265eSRasesh Mody 
91486a2265eSRasesh Mody 	ecore_iov_vf_pglue_clear_err(p_hwfn, p_ptt,
91586a2265eSRasesh Mody 				     ECORE_VF_ABS_ID(p_hwfn, vf));
91686a2265eSRasesh Mody 
91722d07d93SRasesh Mody 	ecore_iov_vf_igu_reset(p_hwfn, p_ptt, vf);
91822d07d93SRasesh Mody 
919cb051eb2SRasesh Mody 	rc = ecore_iov_enable_vf_access_msix(p_hwfn, p_ptt,
92086a2265eSRasesh Mody 					     vf->abs_vf_id, vf->num_sbs);
92122d07d93SRasesh Mody 	if (rc != ECORE_SUCCESS)
92286a2265eSRasesh Mody 		return rc;
92386a2265eSRasesh Mody 
92486a2265eSRasesh Mody 	ecore_fid_pretend(p_hwfn, p_ptt, (u16)vf->concrete_fid);
92586a2265eSRasesh Mody 
92686a2265eSRasesh Mody 	SET_FIELD(igu_vf_conf, IGU_VF_CONF_PARENT, p_hwfn->rel_pf_id);
92786a2265eSRasesh Mody 	STORE_RT_REG(p_hwfn, IGU_REG_VF_CONFIGURATION_RT_OFFSET, igu_vf_conf);
92886a2265eSRasesh Mody 
92986a2265eSRasesh Mody 	ecore_init_run(p_hwfn, p_ptt, PHASE_VF, vf->abs_vf_id,
93086a2265eSRasesh Mody 		       p_hwfn->hw_info.hw_mode);
93186a2265eSRasesh Mody 
93286a2265eSRasesh Mody 	/* unpretend */
93386a2265eSRasesh Mody 	ecore_fid_pretend(p_hwfn, p_ptt, (u16)p_hwfn->hw_info.concrete_fid);
93486a2265eSRasesh Mody 
93586a2265eSRasesh Mody 	vf->state = VF_FREE;
93686a2265eSRasesh Mody 
93786a2265eSRasesh Mody 	return rc;
93886a2265eSRasesh Mody }
93986a2265eSRasesh Mody 
94086a2265eSRasesh Mody /**
94186a2265eSRasesh Mody  *
94286a2265eSRasesh Mody  * @brief ecore_iov_config_perm_table - configure the permission
94386a2265eSRasesh Mody  *      zone table.
9443b307c55SRasesh Mody  *      The queue zone permission table size is 320x9. There
94586a2265eSRasesh Mody  *      are 320 VF queues for single engine device (256 for dual
94686a2265eSRasesh Mody  *      engine device), and each entry has the following format:
94786a2265eSRasesh Mody  *      {Valid, VF[7:0]}
94886a2265eSRasesh Mody  * @param p_hwfn
94986a2265eSRasesh Mody  * @param p_ptt
95086a2265eSRasesh Mody  * @param vf
95186a2265eSRasesh Mody  * @param enable
95286a2265eSRasesh Mody  */
ecore_iov_config_perm_table(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * vf,u8 enable)95386a2265eSRasesh Mody static void ecore_iov_config_perm_table(struct ecore_hwfn *p_hwfn,
95486a2265eSRasesh Mody 					struct ecore_ptt *p_ptt,
95586a2265eSRasesh Mody 					struct ecore_vf_info *vf, u8 enable)
95686a2265eSRasesh Mody {
95722d07d93SRasesh Mody 	u32 reg_addr, val;
95886a2265eSRasesh Mody 	u16 qzone_id = 0;
95986a2265eSRasesh Mody 	int qid;
96086a2265eSRasesh Mody 
96186a2265eSRasesh Mody 	for (qid = 0; qid < vf->num_rxqs; qid++) {
96286a2265eSRasesh Mody 		ecore_fw_l2_queue(p_hwfn, vf->vf_queues[qid].fw_rx_qid,
96386a2265eSRasesh Mody 				  &qzone_id);
96486a2265eSRasesh Mody 
96586a2265eSRasesh Mody 		reg_addr = PSWHST_REG_ZONE_PERMISSION_TABLE + qzone_id * 4;
96686a2265eSRasesh Mody 		val = enable ? (vf->abs_vf_id | (1 << 8)) : 0;
96786a2265eSRasesh Mody 		ecore_wr(p_hwfn, p_ptt, reg_addr, val);
96886a2265eSRasesh Mody 	}
96986a2265eSRasesh Mody }
97086a2265eSRasesh Mody 
ecore_iov_enable_vf_traffic(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * vf)97186a2265eSRasesh Mody static void ecore_iov_enable_vf_traffic(struct ecore_hwfn *p_hwfn,
97286a2265eSRasesh Mody 					struct ecore_ptt *p_ptt,
97386a2265eSRasesh Mody 					struct ecore_vf_info *vf)
97486a2265eSRasesh Mody {
97522d07d93SRasesh Mody 	/* Reset vf in IGU - interrupts are still disabled */
97686a2265eSRasesh Mody 	ecore_iov_vf_igu_reset(p_hwfn, p_ptt, vf);
97786a2265eSRasesh Mody 
97822d07d93SRasesh Mody 	ecore_iov_vf_igu_set_int(p_hwfn, p_ptt, vf, 1);
97986a2265eSRasesh Mody 
98086a2265eSRasesh Mody 	/* Permission Table */
98122d07d93SRasesh Mody 	ecore_iov_config_perm_table(p_hwfn, p_ptt, vf, true);
98286a2265eSRasesh Mody }
98386a2265eSRasesh Mody 
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)98486a2265eSRasesh Mody static u8 ecore_iov_alloc_vf_igu_sbs(struct ecore_hwfn *p_hwfn,
98586a2265eSRasesh Mody 				     struct ecore_ptt *p_ptt,
98686a2265eSRasesh Mody 				     struct ecore_vf_info *vf,
98786a2265eSRasesh Mody 				     u16 num_rx_queues)
98886a2265eSRasesh Mody {
9896e4fcea9SRasesh Mody 	struct ecore_igu_block *p_block;
9906e4fcea9SRasesh Mody 	struct cau_sb_entry sb_entry;
9916e4fcea9SRasesh Mody 	int qid = 0;
99286a2265eSRasesh Mody 	u32 val = 0;
99322d07d93SRasesh Mody 
9946e4fcea9SRasesh Mody 	if (num_rx_queues > p_hwfn->hw_info.p_igu_info->usage.free_cnt_iov)
9956e4fcea9SRasesh Mody 		num_rx_queues =
9966e4fcea9SRasesh Mody 		(u16)p_hwfn->hw_info.p_igu_info->usage.free_cnt_iov;
9976e4fcea9SRasesh Mody 	p_hwfn->hw_info.p_igu_info->usage.free_cnt_iov -= num_rx_queues;
99886a2265eSRasesh Mody 
99986a2265eSRasesh Mody 	SET_FIELD(val, IGU_MAPPING_LINE_FUNCTION_NUMBER, vf->abs_vf_id);
100086a2265eSRasesh Mody 	SET_FIELD(val, IGU_MAPPING_LINE_VALID, 1);
100186a2265eSRasesh Mody 	SET_FIELD(val, IGU_MAPPING_LINE_PF_VALID, 0);
100286a2265eSRasesh Mody 
10036e4fcea9SRasesh Mody 	for (qid = 0; qid < num_rx_queues; qid++) {
10046e4fcea9SRasesh Mody 		p_block = ecore_get_igu_free_sb(p_hwfn, false);
10053b307c55SRasesh Mody 		if (!p_block)
10063b307c55SRasesh Mody 			continue;
10073b307c55SRasesh Mody 
10086e4fcea9SRasesh Mody 		vf->igu_sbs[qid] = p_block->igu_sb_id;
10096e4fcea9SRasesh Mody 		p_block->status &= ~ECORE_IGU_STATUS_FREE;
101086a2265eSRasesh Mody 		SET_FIELD(val, IGU_MAPPING_LINE_VECTOR_NUMBER, qid);
101186a2265eSRasesh Mody 
101286a2265eSRasesh Mody 		ecore_wr(p_hwfn, p_ptt,
10136e4fcea9SRasesh Mody 			 IGU_REG_MAPPING_MEMORY +
10146e4fcea9SRasesh Mody 			 sizeof(u32) * p_block->igu_sb_id, val);
101586a2265eSRasesh Mody 
101686a2265eSRasesh Mody 		/* Configure igu sb in CAU which were marked valid */
101786a2265eSRasesh Mody 		ecore_init_cau_sb_entry(p_hwfn, &sb_entry,
101886a2265eSRasesh Mody 					p_hwfn->rel_pf_id,
101986a2265eSRasesh Mody 					vf->abs_vf_id, 1);
10203eed444aSRasesh Mody 
102186a2265eSRasesh Mody 		ecore_dmae_host2grc(p_hwfn, p_ptt,
102286a2265eSRasesh Mody 				    (u64)(osal_uintptr_t)&sb_entry,
102386a2265eSRasesh Mody 				    CAU_REG_SB_VAR_MEMORY +
10243eed444aSRasesh Mody 				    p_block->igu_sb_id * sizeof(u64), 2,
10253eed444aSRasesh Mody 				    OSAL_NULL /* default parameters */);
102686a2265eSRasesh Mody 	}
102786a2265eSRasesh Mody 
102886a2265eSRasesh Mody 	vf->num_sbs = (u8)num_rx_queues;
102986a2265eSRasesh Mody 
103086a2265eSRasesh Mody 	return vf->num_sbs;
103186a2265eSRasesh Mody }
103286a2265eSRasesh Mody 
103386a2265eSRasesh Mody /**
103486a2265eSRasesh Mody  *
103586a2265eSRasesh Mody  * @brief The function invalidates all the VF entries,
103686a2265eSRasesh Mody  *        technically this isn't required, but added for
103786a2265eSRasesh Mody  *        cleaness and ease of debugging incase a VF attempts to
103886a2265eSRasesh Mody  *        produce an interrupt after it has been taken down.
103986a2265eSRasesh Mody  *
104086a2265eSRasesh Mody  * @param p_hwfn
104186a2265eSRasesh Mody  * @param p_ptt
104286a2265eSRasesh Mody  * @param vf
104386a2265eSRasesh Mody  */
ecore_iov_free_vf_igu_sbs(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * vf)104486a2265eSRasesh Mody static void ecore_iov_free_vf_igu_sbs(struct ecore_hwfn *p_hwfn,
104586a2265eSRasesh Mody 				      struct ecore_ptt *p_ptt,
104686a2265eSRasesh Mody 				      struct ecore_vf_info *vf)
104786a2265eSRasesh Mody {
104886a2265eSRasesh Mody 	struct ecore_igu_info *p_info = p_hwfn->hw_info.p_igu_info;
104986a2265eSRasesh Mody 	int idx, igu_id;
105086a2265eSRasesh Mody 	u32 addr, val;
105186a2265eSRasesh Mody 
105286a2265eSRasesh Mody 	/* Invalidate igu CAM lines and mark them as free */
105386a2265eSRasesh Mody 	for (idx = 0; idx < vf->num_sbs; idx++) {
105486a2265eSRasesh Mody 		igu_id = vf->igu_sbs[idx];
105586a2265eSRasesh Mody 		addr = IGU_REG_MAPPING_MEMORY + sizeof(u32) * igu_id;
105686a2265eSRasesh Mody 
105786a2265eSRasesh Mody 		val = ecore_rd(p_hwfn, p_ptt, addr);
105886a2265eSRasesh Mody 		SET_FIELD(val, IGU_MAPPING_LINE_VALID, 0);
105986a2265eSRasesh Mody 		ecore_wr(p_hwfn, p_ptt, addr, val);
106086a2265eSRasesh Mody 
10616e4fcea9SRasesh Mody 		p_info->entry[igu_id].status |= ECORE_IGU_STATUS_FREE;
10626e4fcea9SRasesh Mody 		p_hwfn->hw_info.p_igu_info->usage.free_cnt_iov++;
106386a2265eSRasesh Mody 	}
106486a2265eSRasesh Mody 
106586a2265eSRasesh Mody 	vf->num_sbs = 0;
106686a2265eSRasesh Mody }
106786a2265eSRasesh Mody 
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)10686ccecc10SRasesh Mody void ecore_iov_set_link(struct ecore_hwfn *p_hwfn,
10696ccecc10SRasesh Mody 			u16 vfid,
10706ccecc10SRasesh Mody 			struct ecore_mcp_link_params *params,
10716ccecc10SRasesh Mody 			struct ecore_mcp_link_state *link,
10726ccecc10SRasesh Mody 			struct ecore_mcp_link_capabilities *p_caps)
10736ccecc10SRasesh Mody {
10746ccecc10SRasesh Mody 	struct ecore_vf_info *p_vf = ecore_iov_get_vf_info(p_hwfn, vfid, false);
10756ccecc10SRasesh Mody 	struct ecore_bulletin_content *p_bulletin;
10766ccecc10SRasesh Mody 
10776ccecc10SRasesh Mody 	if (!p_vf)
10786ccecc10SRasesh Mody 		return;
10796ccecc10SRasesh Mody 
10806ccecc10SRasesh Mody 	p_bulletin = p_vf->bulletin.p_virt;
10816ccecc10SRasesh Mody 	p_bulletin->req_autoneg = params->speed.autoneg;
10826ccecc10SRasesh Mody 	p_bulletin->req_adv_speed = params->speed.advertised_speeds;
10836ccecc10SRasesh Mody 	p_bulletin->req_forced_speed = params->speed.forced_speed;
10846ccecc10SRasesh Mody 	p_bulletin->req_autoneg_pause = params->pause.autoneg;
10856ccecc10SRasesh Mody 	p_bulletin->req_forced_rx = params->pause.forced_rx;
10866ccecc10SRasesh Mody 	p_bulletin->req_forced_tx = params->pause.forced_tx;
10876ccecc10SRasesh Mody 	p_bulletin->req_loopback = params->loopback_mode;
10886ccecc10SRasesh Mody 
10896ccecc10SRasesh Mody 	p_bulletin->link_up = link->link_up;
10906ccecc10SRasesh Mody 	p_bulletin->speed = link->speed;
10916ccecc10SRasesh Mody 	p_bulletin->full_duplex = link->full_duplex;
10926ccecc10SRasesh Mody 	p_bulletin->autoneg = link->an;
10936ccecc10SRasesh Mody 	p_bulletin->autoneg_complete = link->an_complete;
10946ccecc10SRasesh Mody 	p_bulletin->parallel_detection = link->parallel_detection;
10956ccecc10SRasesh Mody 	p_bulletin->pfc_enabled = link->pfc_enabled;
10966ccecc10SRasesh Mody 	p_bulletin->partner_adv_speed = link->partner_adv_speed;
10976ccecc10SRasesh Mody 	p_bulletin->partner_tx_flow_ctrl_en = link->partner_tx_flow_ctrl_en;
10986ccecc10SRasesh Mody 	p_bulletin->partner_rx_flow_ctrl_en = link->partner_rx_flow_ctrl_en;
10996ccecc10SRasesh Mody 	p_bulletin->partner_adv_pause = link->partner_adv_pause;
11006ccecc10SRasesh Mody 	p_bulletin->sfp_tx_fault = link->sfp_tx_fault;
11016ccecc10SRasesh Mody 
11026ccecc10SRasesh Mody 	p_bulletin->capability_speed = p_caps->speed_capabilities;
11036ccecc10SRasesh Mody }
11046ccecc10SRasesh Mody 
11053b307c55SRasesh Mody #ifndef ASIC_ONLY
ecore_emul_iov_init_hw_for_vf(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)11063b307c55SRasesh Mody static void ecore_emul_iov_init_hw_for_vf(struct ecore_hwfn *p_hwfn,
11073b307c55SRasesh Mody 					  struct ecore_ptt *p_ptt)
11083b307c55SRasesh Mody {
11093b307c55SRasesh Mody 	/* Increase the maximum number of DORQ FIFO entries used by child VFs */
11103b307c55SRasesh Mody 	ecore_wr(p_hwfn, p_ptt, DORQ_REG_VF_USAGE_CNT_LIM, 0x3ec);
11113b307c55SRasesh Mody }
11123b307c55SRasesh Mody #endif
11133b307c55SRasesh Mody 
1114a55e422eSRasesh Mody 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)1115a55e422eSRasesh Mody ecore_iov_init_hw_for_vf(struct ecore_hwfn *p_hwfn,
111686a2265eSRasesh Mody 			 struct ecore_ptt *p_ptt,
1117a55e422eSRasesh Mody 			 struct ecore_iov_vf_init_params *p_params)
111886a2265eSRasesh Mody {
11196ccecc10SRasesh Mody 	struct ecore_mcp_link_capabilities link_caps;
11206ccecc10SRasesh Mody 	struct ecore_mcp_link_params link_params;
11216ccecc10SRasesh Mody 	struct ecore_mcp_link_state link_state;
112286a2265eSRasesh Mody 	u8 num_of_vf_available_chains  = 0;
112322d07d93SRasesh Mody 	struct ecore_vf_info *vf = OSAL_NULL;
1124a55e422eSRasesh Mody 	u16 qid, num_irqs;
112522d07d93SRasesh Mody 	enum _ecore_status_t rc = ECORE_SUCCESS;
112686a2265eSRasesh Mody 	u32 cids;
112786a2265eSRasesh Mody 	u8 i;
112886a2265eSRasesh Mody 
1129a55e422eSRasesh Mody 	vf = ecore_iov_get_vf_info(p_hwfn, p_params->rel_vf_id, false);
113086a2265eSRasesh Mody 	if (!vf) {
113186a2265eSRasesh Mody 		DP_ERR(p_hwfn, "ecore_iov_init_hw_for_vf : vf is OSAL_NULL\n");
113286a2265eSRasesh Mody 		return ECORE_UNKNOWN_ERROR;
113386a2265eSRasesh Mody 	}
113486a2265eSRasesh Mody 
113522d07d93SRasesh Mody 	if (vf->b_init) {
113622d07d93SRasesh Mody 		DP_NOTICE(p_hwfn, true, "VF[%d] is already active.\n",
1137a55e422eSRasesh Mody 			  p_params->rel_vf_id);
113822d07d93SRasesh Mody 		return ECORE_INVAL;
113922d07d93SRasesh Mody 	}
114022d07d93SRasesh Mody 
114135da9596SRasesh Mody 	/* Perform sanity checking on the requested vport/rss */
114235da9596SRasesh Mody 	if (p_params->vport_id >= RESC_NUM(p_hwfn, ECORE_VPORT)) {
114335da9596SRasesh Mody 		DP_NOTICE(p_hwfn, true, "VF[%d] - can't use VPORT %02x\n",
114435da9596SRasesh Mody 			  p_params->rel_vf_id, p_params->vport_id);
114535da9596SRasesh Mody 		return ECORE_INVAL;
114635da9596SRasesh Mody 	}
114735da9596SRasesh Mody 
114835da9596SRasesh Mody 	if ((p_params->num_queues > 1) &&
114935da9596SRasesh Mody 	    (p_params->rss_eng_id >= RESC_NUM(p_hwfn, ECORE_RSS_ENG))) {
115035da9596SRasesh Mody 		DP_NOTICE(p_hwfn, true, "VF[%d] - can't use RSS_ENG %02x\n",
115135da9596SRasesh Mody 			  p_params->rel_vf_id, p_params->rss_eng_id);
115235da9596SRasesh Mody 		return ECORE_INVAL;
115335da9596SRasesh Mody 	}
115435da9596SRasesh Mody 
115535da9596SRasesh Mody 	/* TODO - remove this once we get confidence of change */
115635da9596SRasesh Mody 	if (!p_params->vport_id) {
115735da9596SRasesh Mody 		DP_NOTICE(p_hwfn, false,
115835da9596SRasesh Mody 			  "VF[%d] - Unlikely that VF uses vport0. Forgotten?\n",
115935da9596SRasesh Mody 			  p_params->rel_vf_id);
116035da9596SRasesh Mody 	}
116135da9596SRasesh Mody 	if ((!p_params->rss_eng_id) && (p_params->num_queues > 1)) {
116235da9596SRasesh Mody 		DP_NOTICE(p_hwfn, false,
116335da9596SRasesh Mody 			  "VF[%d] - Unlikely that VF uses RSS_eng0. Forgotten?\n",
116435da9596SRasesh Mody 			  p_params->rel_vf_id);
116535da9596SRasesh Mody 	}
116635da9596SRasesh Mody 	vf->vport_id = p_params->vport_id;
116735da9596SRasesh Mody 	vf->rss_eng_id = p_params->rss_eng_id;
116835da9596SRasesh Mody 
11696e4fcea9SRasesh Mody 	/* Since it's possible to relocate SBs, it's a bit difficult to check
11706e4fcea9SRasesh Mody 	 * things here. Simply check whether the index falls in the range
11716e4fcea9SRasesh Mody 	 * belonging to the PF.
11726e4fcea9SRasesh Mody 	 */
1173a55e422eSRasesh Mody 	for (i = 0; i < p_params->num_queues; i++) {
1174a55e422eSRasesh Mody 		qid = p_params->req_rx_queue[i];
11756e4fcea9SRasesh Mody 		if (qid > (u16)RESC_NUM(p_hwfn, ECORE_L2_QUEUE)) {
1176a55e422eSRasesh Mody 			DP_NOTICE(p_hwfn, true,
11776e4fcea9SRasesh Mody 				  "Can't enable Rx qid [%04x] for VF[%d]: qids [0,,...,0x%04x] available\n",
1178a55e422eSRasesh Mody 				  qid, p_params->rel_vf_id,
11796e4fcea9SRasesh Mody 				  (u16)RESC_NUM(p_hwfn, ECORE_L2_QUEUE));
1180a55e422eSRasesh Mody 			return ECORE_INVAL;
1181a55e422eSRasesh Mody 		}
1182a55e422eSRasesh Mody 
1183a55e422eSRasesh Mody 		qid = p_params->req_tx_queue[i];
11846e4fcea9SRasesh Mody 		if (qid > (u16)RESC_NUM(p_hwfn, ECORE_L2_QUEUE)) {
1185a55e422eSRasesh Mody 			DP_NOTICE(p_hwfn, true,
11866e4fcea9SRasesh Mody 				  "Can't enable Tx qid [%04x] for VF[%d]: qids [0,,...,0x%04x] available\n",
11876e4fcea9SRasesh Mody 				  qid, p_params->rel_vf_id,
11886e4fcea9SRasesh Mody 				  (u16)RESC_NUM(p_hwfn, ECORE_L2_QUEUE));
1189a55e422eSRasesh Mody 			return ECORE_INVAL;
1190a55e422eSRasesh Mody 		}
1191a55e422eSRasesh Mody 	}
1192a55e422eSRasesh Mody 
119386a2265eSRasesh Mody 	/* Limit number of queues according to number of CIDs */
119486a2265eSRasesh Mody 	ecore_cxt_get_proto_cid_count(p_hwfn, PROTOCOLID_ETH, &cids);
119586a2265eSRasesh Mody 	DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
119686a2265eSRasesh Mody 		   "VF[%d] - requesting to initialize for 0x%04x queues"
119786a2265eSRasesh Mody 		   " [0x%04x CIDs available]\n",
1198a55e422eSRasesh Mody 		   vf->relative_vf_id, p_params->num_queues, (u16)cids);
1199a55e422eSRasesh Mody 	num_irqs = OSAL_MIN_T(u16, p_params->num_queues, ((u16)cids));
120086a2265eSRasesh Mody 
120186a2265eSRasesh Mody 	num_of_vf_available_chains = ecore_iov_alloc_vf_igu_sbs(p_hwfn,
120286a2265eSRasesh Mody 							       p_ptt,
120386a2265eSRasesh Mody 							       vf,
1204a55e422eSRasesh Mody 							       num_irqs);
120586a2265eSRasesh Mody 	if (num_of_vf_available_chains == 0) {
120686a2265eSRasesh Mody 		DP_ERR(p_hwfn, "no available igu sbs\n");
120786a2265eSRasesh Mody 		return ECORE_NOMEM;
120886a2265eSRasesh Mody 	}
120986a2265eSRasesh Mody 
121086a2265eSRasesh Mody 	/* Choose queue number and index ranges */
121186a2265eSRasesh Mody 	vf->num_rxqs = num_of_vf_available_chains;
121286a2265eSRasesh Mody 	vf->num_txqs = num_of_vf_available_chains;
121386a2265eSRasesh Mody 
121486a2265eSRasesh Mody 	for (i = 0; i < vf->num_rxqs; i++) {
1215eb8e81adSRasesh Mody 		struct ecore_vf_queue *p_queue = &vf->vf_queues[i];
121686a2265eSRasesh Mody 
1217a55e422eSRasesh Mody 		p_queue->fw_rx_qid = p_params->req_rx_queue[i];
1218a55e422eSRasesh Mody 		p_queue->fw_tx_qid = p_params->req_tx_queue[i];
121986a2265eSRasesh Mody 
122086a2265eSRasesh Mody 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
1221eb8e81adSRasesh Mody 			   "VF[%d] - Q[%d] SB %04x, qid [Rx %04x Tx %04x]\n",
1222a55e422eSRasesh Mody 			   vf->relative_vf_id, i, vf->igu_sbs[i],
1223eb8e81adSRasesh Mody 			   p_queue->fw_rx_qid, p_queue->fw_tx_qid);
122486a2265eSRasesh Mody 	}
122586a2265eSRasesh Mody 
12266ccecc10SRasesh Mody 	/* Update the link configuration in bulletin.
12276ccecc10SRasesh Mody 	 */
12286ccecc10SRasesh Mody 	OSAL_MEMCPY(&link_params, ecore_mcp_get_link_params(p_hwfn),
12296ccecc10SRasesh Mody 		    sizeof(link_params));
12306ccecc10SRasesh Mody 	OSAL_MEMCPY(&link_state, ecore_mcp_get_link_state(p_hwfn),
12316ccecc10SRasesh Mody 		    sizeof(link_state));
12326ccecc10SRasesh Mody 	OSAL_MEMCPY(&link_caps, ecore_mcp_get_link_capabilities(p_hwfn),
12336ccecc10SRasesh Mody 		    sizeof(link_caps));
12346ccecc10SRasesh Mody 	ecore_iov_set_link(p_hwfn, p_params->rel_vf_id,
12356ccecc10SRasesh Mody 			   &link_params, &link_state, &link_caps);
12366ccecc10SRasesh Mody 
123786a2265eSRasesh Mody 	rc = ecore_iov_enable_vf_access(p_hwfn, p_ptt, vf);
12383b307c55SRasesh Mody 	if (rc != ECORE_SUCCESS)
12393b307c55SRasesh Mody 		return rc;
124086a2265eSRasesh Mody 
124122d07d93SRasesh Mody 	vf->b_init = true;
12423b307c55SRasesh Mody #ifndef REMOVE_DBG
124322d07d93SRasesh Mody 	p_hwfn->pf_iov_info->active_vfs[vf->relative_vf_id / 64] |=
124422d07d93SRasesh Mody 			(1ULL << (vf->relative_vf_id % 64));
12453b307c55SRasesh Mody #endif
124686a2265eSRasesh Mody 
124722d07d93SRasesh Mody 	if (IS_LEAD_HWFN(p_hwfn))
124822d07d93SRasesh Mody 		p_hwfn->p_dev->p_iov_info->num_vfs++;
12493b307c55SRasesh Mody 
12503b307c55SRasesh Mody #ifndef ASIC_ONLY
12513b307c55SRasesh Mody 	if (CHIP_REV_IS_EMUL(p_hwfn->p_dev))
12523b307c55SRasesh Mody 		ecore_emul_iov_init_hw_for_vf(p_hwfn, p_ptt);
12533b307c55SRasesh Mody #endif
12543b307c55SRasesh Mody 
12553b307c55SRasesh Mody 	return ECORE_SUCCESS;
125686a2265eSRasesh Mody 	}
125786a2265eSRasesh Mody 
12583b307c55SRasesh Mody #ifndef ASIC_ONLY
ecore_emul_iov_release_hw_for_vf(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)12593b307c55SRasesh Mody static void ecore_emul_iov_release_hw_for_vf(struct ecore_hwfn *p_hwfn,
12603b307c55SRasesh Mody 					  struct ecore_ptt *p_ptt)
12613b307c55SRasesh Mody {
12623b307c55SRasesh Mody 	if (!ecore_mcp_is_init(p_hwfn)) {
12633b307c55SRasesh Mody 		u32 sriov_dis = ecore_rd(p_hwfn, p_ptt,
12643b307c55SRasesh Mody 					 PGLUE_B_REG_SR_IOV_DISABLED_REQUEST);
12653b307c55SRasesh Mody 
12663b307c55SRasesh Mody 		ecore_wr(p_hwfn, p_ptt, PGLUE_B_REG_SR_IOV_DISABLED_REQUEST_CLR,
12673b307c55SRasesh Mody 			 sriov_dis);
126886a2265eSRasesh Mody }
12693b307c55SRasesh Mody }
12703b307c55SRasesh Mody #endif
127186a2265eSRasesh Mody 
ecore_iov_release_hw_for_vf(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u16 rel_vf_id)127286a2265eSRasesh Mody enum _ecore_status_t ecore_iov_release_hw_for_vf(struct ecore_hwfn *p_hwfn,
127386a2265eSRasesh Mody 						 struct ecore_ptt *p_ptt,
127486a2265eSRasesh Mody 						 u16 rel_vf_id)
127586a2265eSRasesh Mody {
127622d07d93SRasesh Mody 	struct ecore_mcp_link_capabilities caps;
127722d07d93SRasesh Mody 	struct ecore_mcp_link_params params;
127822d07d93SRasesh Mody 	struct ecore_mcp_link_state link;
127986a2265eSRasesh Mody 	struct ecore_vf_info *vf = OSAL_NULL;
128086a2265eSRasesh Mody 
128186a2265eSRasesh Mody 	vf = ecore_iov_get_vf_info(p_hwfn, rel_vf_id, true);
128286a2265eSRasesh Mody 	if (!vf) {
128386a2265eSRasesh Mody 		DP_ERR(p_hwfn, "ecore_iov_release_hw_for_vf : vf is NULL\n");
128486a2265eSRasesh Mody 		return ECORE_UNKNOWN_ERROR;
128586a2265eSRasesh Mody 	}
128686a2265eSRasesh Mody 
128722d07d93SRasesh Mody 	if (vf->bulletin.p_virt)
128822d07d93SRasesh Mody 		OSAL_MEMSET(vf->bulletin.p_virt, 0,
128922d07d93SRasesh Mody 			    sizeof(*vf->bulletin.p_virt));
129086a2265eSRasesh Mody 
129122d07d93SRasesh Mody 	OSAL_MEMSET(&vf->p_vf_info, 0, sizeof(vf->p_vf_info));
129286a2265eSRasesh Mody 
129322d07d93SRasesh Mody 	/* Get the link configuration back in bulletin so
129422d07d93SRasesh Mody 	 * that when VFs are re-enabled they get the actual
129522d07d93SRasesh Mody 	 * link configuration.
129622d07d93SRasesh Mody 	 */
129722d07d93SRasesh Mody 	OSAL_MEMCPY(&params, ecore_mcp_get_link_params(p_hwfn), sizeof(params));
129822d07d93SRasesh Mody 	OSAL_MEMCPY(&link, ecore_mcp_get_link_state(p_hwfn), sizeof(link));
129922d07d93SRasesh Mody 	OSAL_MEMCPY(&caps, ecore_mcp_get_link_capabilities(p_hwfn),
130022d07d93SRasesh Mody 		    sizeof(caps));
130122d07d93SRasesh Mody 	ecore_iov_set_link(p_hwfn, rel_vf_id, &params, &link, &caps);
130222d07d93SRasesh Mody 
130322d07d93SRasesh Mody 	/* Forget the VF's acquisition message */
130422d07d93SRasesh Mody 	OSAL_MEMSET(&vf->acquire, 0, sizeof(vf->acquire));
130586a2265eSRasesh Mody 
130686a2265eSRasesh Mody 	/* disablng interrupts and resetting permission table was done during
130786a2265eSRasesh Mody 	 * vf-close, however, we could get here without going through vf_close
130886a2265eSRasesh Mody 	 */
130986a2265eSRasesh Mody 	/* Disable Interrupts for VF */
131022d07d93SRasesh Mody 	ecore_iov_vf_igu_set_int(p_hwfn, p_ptt, vf, 0);
131186a2265eSRasesh Mody 
131286a2265eSRasesh Mody 	/* Reset Permission table */
131322d07d93SRasesh Mody 	ecore_iov_config_perm_table(p_hwfn, p_ptt, vf, 0);
131486a2265eSRasesh Mody 
131586a2265eSRasesh Mody 	vf->num_rxqs = 0;
131686a2265eSRasesh Mody 	vf->num_txqs = 0;
131786a2265eSRasesh Mody 	ecore_iov_free_vf_igu_sbs(p_hwfn, p_ptt, vf);
131886a2265eSRasesh Mody 
131922d07d93SRasesh Mody 	if (vf->b_init) {
132022d07d93SRasesh Mody 		vf->b_init = false;
132122d07d93SRasesh Mody 		p_hwfn->pf_iov_info->active_vfs[vf->relative_vf_id / 64] &=
132222d07d93SRasesh Mody 					~(1ULL << (vf->relative_vf_id / 64));
132386a2265eSRasesh Mody 
132422d07d93SRasesh Mody 		if (IS_LEAD_HWFN(p_hwfn))
132522d07d93SRasesh Mody 			p_hwfn->p_dev->p_iov_info->num_vfs--;
132686a2265eSRasesh Mody 	}
132786a2265eSRasesh Mody 
13283b307c55SRasesh Mody #ifndef ASIC_ONLY
13293b307c55SRasesh Mody 	if (CHIP_REV_IS_EMUL(p_hwfn->p_dev))
13303b307c55SRasesh Mody 		ecore_emul_iov_release_hw_for_vf(p_hwfn, p_ptt);
13313b307c55SRasesh Mody #endif
13323b307c55SRasesh Mody 
133386a2265eSRasesh Mody 	return ECORE_SUCCESS;
133486a2265eSRasesh Mody }
133586a2265eSRasesh Mody 
ecore_iov_tlv_supported(u16 tlvtype)133686a2265eSRasesh Mody static bool ecore_iov_tlv_supported(u16 tlvtype)
133786a2265eSRasesh Mody {
133886a2265eSRasesh Mody 	return tlvtype > CHANNEL_TLV_NONE && tlvtype < CHANNEL_TLV_MAX;
133986a2265eSRasesh Mody }
134086a2265eSRasesh Mody 
ecore_iov_lock_vf_pf_channel(struct ecore_hwfn * p_hwfn,struct ecore_vf_info * vf,u16 tlv)134186a2265eSRasesh Mody static void ecore_iov_lock_vf_pf_channel(struct ecore_hwfn *p_hwfn,
134286a2265eSRasesh Mody 					 struct ecore_vf_info *vf, u16 tlv)
134386a2265eSRasesh Mody {
134486a2265eSRasesh Mody 	/* lock the channel */
134586a2265eSRasesh Mody 	/* mutex_lock(&vf->op_mutex); @@@TBD MichalK - add lock... */
134686a2265eSRasesh Mody 
134786a2265eSRasesh Mody 	/* record the locking op */
134886a2265eSRasesh Mody 	/* vf->op_current = tlv; @@@TBD MichalK */
134986a2265eSRasesh Mody 
135086a2265eSRasesh Mody 	/* log the lock */
135122d07d93SRasesh Mody 	if (ecore_iov_tlv_supported(tlv))
135286a2265eSRasesh Mody 		DP_VERBOSE(p_hwfn,
135386a2265eSRasesh Mody 			   ECORE_MSG_IOV,
135486a2265eSRasesh Mody 			   "VF[%d]: vf pf channel locked by %s\n",
135522d07d93SRasesh Mody 			   vf->abs_vf_id,
1356520dd992SFerruh Yigit 			   qede_ecore_channel_tlvs_string[tlv]);
135722d07d93SRasesh Mody 	else
135822d07d93SRasesh Mody 		DP_VERBOSE(p_hwfn,
135922d07d93SRasesh Mody 			   ECORE_MSG_IOV,
136022d07d93SRasesh Mody 			   "VF[%d]: vf pf channel locked by %04x\n",
136122d07d93SRasesh Mody 			   vf->abs_vf_id, tlv);
136286a2265eSRasesh Mody }
136386a2265eSRasesh Mody 
ecore_iov_unlock_vf_pf_channel(struct ecore_hwfn * p_hwfn,struct ecore_vf_info * vf,u16 expected_tlv)136486a2265eSRasesh Mody static void ecore_iov_unlock_vf_pf_channel(struct ecore_hwfn *p_hwfn,
136586a2265eSRasesh Mody 					   struct ecore_vf_info *vf,
136686a2265eSRasesh Mody 					   u16 expected_tlv)
136786a2265eSRasesh Mody {
136886a2265eSRasesh Mody 	/* log the unlock */
136922d07d93SRasesh Mody 	if (ecore_iov_tlv_supported(expected_tlv))
137086a2265eSRasesh Mody 		DP_VERBOSE(p_hwfn,
137186a2265eSRasesh Mody 			   ECORE_MSG_IOV,
137286a2265eSRasesh Mody 			   "VF[%d]: vf pf channel unlocked by %s\n",
137322d07d93SRasesh Mody 			   vf->abs_vf_id,
1374520dd992SFerruh Yigit 			   qede_ecore_channel_tlvs_string[expected_tlv]);
137522d07d93SRasesh Mody 	else
137622d07d93SRasesh Mody 		DP_VERBOSE(p_hwfn,
137722d07d93SRasesh Mody 			   ECORE_MSG_IOV,
137822d07d93SRasesh Mody 			   "VF[%d]: vf pf channel unlocked by %04x\n",
137922d07d93SRasesh Mody 			   vf->abs_vf_id, expected_tlv);
138086a2265eSRasesh Mody 
138186a2265eSRasesh Mody 	/* record the locking op */
138286a2265eSRasesh Mody 	/* vf->op_current = CHANNEL_TLV_NONE; */
138386a2265eSRasesh Mody }
138486a2265eSRasesh Mody 
138586a2265eSRasesh Mody /* place a given tlv on the tlv buffer, continuing current tlv list */
ecore_add_tlv(u8 ** offset,u16 type,u16 length)138630ecf673SRasesh Mody void *ecore_add_tlv(u8 **offset, u16 type, u16 length)
138786a2265eSRasesh Mody {
138886a2265eSRasesh Mody 	struct channel_tlv *tl = (struct channel_tlv *)*offset;
138986a2265eSRasesh Mody 
139086a2265eSRasesh Mody 	tl->type = type;
139186a2265eSRasesh Mody 	tl->length = length;
139286a2265eSRasesh Mody 
139386a2265eSRasesh Mody 	/* Offset should keep pointing to next TLV (the end of the last) */
139486a2265eSRasesh Mody 	*offset += length;
139586a2265eSRasesh Mody 
139686a2265eSRasesh Mody 	/* Return a pointer to the start of the added tlv */
139786a2265eSRasesh Mody 	return *offset - length;
139886a2265eSRasesh Mody }
139986a2265eSRasesh Mody 
140086a2265eSRasesh Mody /* list the types and lengths of the tlvs on the buffer */
ecore_dp_tlv_list(struct ecore_hwfn * p_hwfn,void * tlvs_list)140186a2265eSRasesh Mody void ecore_dp_tlv_list(struct ecore_hwfn *p_hwfn, void *tlvs_list)
140286a2265eSRasesh Mody {
140386a2265eSRasesh Mody 	u16 i = 1, total_length = 0;
140486a2265eSRasesh Mody 	struct channel_tlv *tlv;
140586a2265eSRasesh Mody 
140686a2265eSRasesh Mody 	do {
140786a2265eSRasesh Mody 		/* cast current tlv list entry to channel tlv header */
140886a2265eSRasesh Mody 		tlv = (struct channel_tlv *)((u8 *)tlvs_list + total_length);
140986a2265eSRasesh Mody 
141086a2265eSRasesh Mody 		/* output tlv */
141186a2265eSRasesh Mody 		if (ecore_iov_tlv_supported(tlv->type))
141286a2265eSRasesh Mody 			DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
141386a2265eSRasesh Mody 				   "TLV number %d: type %s, length %d\n",
1414520dd992SFerruh Yigit 				   i, qede_ecore_channel_tlvs_string[tlv->type],
141586a2265eSRasesh Mody 				   tlv->length);
141686a2265eSRasesh Mody 		else
141786a2265eSRasesh Mody 			DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
141886a2265eSRasesh Mody 				   "TLV number %d: type %d, length %d\n",
141986a2265eSRasesh Mody 				   i, tlv->type, tlv->length);
142086a2265eSRasesh Mody 
142186a2265eSRasesh Mody 		if (tlv->type == CHANNEL_TLV_LIST_END)
142286a2265eSRasesh Mody 			return;
142386a2265eSRasesh Mody 
142486a2265eSRasesh Mody 		/* Validate entry - protect against malicious VFs */
142586a2265eSRasesh Mody 		if (!tlv->length) {
142686a2265eSRasesh Mody 			DP_NOTICE(p_hwfn, false, "TLV of length 0 found\n");
142786a2265eSRasesh Mody 			return;
142886a2265eSRasesh Mody 		}
142986a2265eSRasesh Mody 		total_length += tlv->length;
143086a2265eSRasesh Mody 		if (total_length >= sizeof(struct tlv_buffer_size)) {
143186a2265eSRasesh Mody 			DP_NOTICE(p_hwfn, false, "TLV ==> Buffer overflow\n");
143286a2265eSRasesh Mody 			return;
143386a2265eSRasesh Mody 		}
143486a2265eSRasesh Mody 
143586a2265eSRasesh Mody 		i++;
143686a2265eSRasesh Mody 	} while (1);
143786a2265eSRasesh Mody }
143886a2265eSRasesh Mody 
ecore_iov_send_response(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * p_vf,u16 length,u8 status)143986a2265eSRasesh Mody static void ecore_iov_send_response(struct ecore_hwfn *p_hwfn,
144086a2265eSRasesh Mody 				    struct ecore_ptt *p_ptt,
144186a2265eSRasesh Mody 				    struct ecore_vf_info *p_vf,
144230ecf673SRasesh Mody #ifdef CONFIG_ECORE_SW_CHANNEL
144330ecf673SRasesh Mody 				    u16 length,
144430ecf673SRasesh Mody #else
144530ecf673SRasesh Mody 				    u16 OSAL_UNUSED length,
144630ecf673SRasesh Mody #endif
144730ecf673SRasesh Mody 				    u8 status)
144886a2265eSRasesh Mody {
144986a2265eSRasesh Mody 	struct ecore_iov_vf_mbx *mbx = &p_vf->vf_mbx;
1450ea85629fSRasesh Mody 	struct dmae_params params;
145186a2265eSRasesh Mody 	u8 eng_vf_id;
145286a2265eSRasesh Mody 
145386a2265eSRasesh Mody 	mbx->reply_virt->default_resp.hdr.status = status;
145486a2265eSRasesh Mody 
145522d07d93SRasesh Mody 	ecore_dp_tlv_list(p_hwfn, mbx->reply_virt);
145622d07d93SRasesh Mody 
145786a2265eSRasesh Mody #ifdef CONFIG_ECORE_SW_CHANNEL
145886a2265eSRasesh Mody 	mbx->sw_mbx.response_size =
145986a2265eSRasesh Mody 	    length + sizeof(struct channel_list_end_tlv);
146086a2265eSRasesh Mody 
146101491d29SRasesh Mody 	if (!p_vf->b_hw_channel)
146286a2265eSRasesh Mody 		return;
146322d07d93SRasesh Mody #endif
146486a2265eSRasesh Mody 
146586a2265eSRasesh Mody 	eng_vf_id = p_vf->abs_vf_id;
146686a2265eSRasesh Mody 
14673b307c55SRasesh Mody 	OSAL_MEMSET(&params, 0, sizeof(params));
1468ea85629fSRasesh Mody 	SET_FIELD(params.flags, DMAE_PARAMS_DST_VF_VALID, 0x1);
1469ea85629fSRasesh Mody 	params.dst_vf_id = eng_vf_id;
147086a2265eSRasesh Mody 
147186a2265eSRasesh Mody 	ecore_dmae_host2host(p_hwfn, p_ptt, mbx->reply_phys + sizeof(u64),
147286a2265eSRasesh Mody 			     mbx->req_virt->first_tlv.reply_address +
147386a2265eSRasesh Mody 			     sizeof(u64),
147486a2265eSRasesh Mody 			     (sizeof(union pfvf_tlvs) - sizeof(u64)) / 4,
147586a2265eSRasesh Mody 			     &params);
147686a2265eSRasesh Mody 
1477eb35c732SRasesh Mody 	/* Once PF copies the rc to the VF, the latter can continue and
1478eb35c732SRasesh Mody 	 * and send an additional message. So we have to make sure the
1479eb35c732SRasesh Mody 	 * channel would be re-set to ready prior to that.
1480eb35c732SRasesh Mody 	 */
148186a2265eSRasesh Mody 	REG_WR(p_hwfn,
148286a2265eSRasesh Mody 	       GTT_BAR0_MAP_REG_USDM_RAM +
148386a2265eSRasesh Mody 	       USTORM_VF_PF_CHANNEL_READY_OFFSET(eng_vf_id), 1);
1484823a84aaSRasesh Mody 
1485eb35c732SRasesh Mody 	ecore_dmae_host2host(p_hwfn, p_ptt, mbx->reply_phys,
1486eb35c732SRasesh Mody 			     mbx->req_virt->first_tlv.reply_address,
1487eb35c732SRasesh Mody 			     sizeof(u64) / 4, &params);
1488eb35c732SRasesh Mody 
1489823a84aaSRasesh Mody 	OSAL_IOV_PF_RESP_TYPE(p_hwfn, p_vf->relative_vf_id, status);
149086a2265eSRasesh Mody }
149186a2265eSRasesh Mody 
ecore_iov_vport_to_tlv(enum ecore_iov_vport_update_flag flag)149230ecf673SRasesh Mody static u16 ecore_iov_vport_to_tlv(enum ecore_iov_vport_update_flag flag)
149386a2265eSRasesh Mody {
149486a2265eSRasesh Mody 	switch (flag) {
149586a2265eSRasesh Mody 	case ECORE_IOV_VP_UPDATE_ACTIVATE:
149686a2265eSRasesh Mody 		return CHANNEL_TLV_VPORT_UPDATE_ACTIVATE;
149786a2265eSRasesh Mody 	case ECORE_IOV_VP_UPDATE_VLAN_STRIP:
149886a2265eSRasesh Mody 		return CHANNEL_TLV_VPORT_UPDATE_VLAN_STRIP;
149986a2265eSRasesh Mody 	case ECORE_IOV_VP_UPDATE_TX_SWITCH:
150086a2265eSRasesh Mody 		return CHANNEL_TLV_VPORT_UPDATE_TX_SWITCH;
150186a2265eSRasesh Mody 	case ECORE_IOV_VP_UPDATE_MCAST:
150286a2265eSRasesh Mody 		return CHANNEL_TLV_VPORT_UPDATE_MCAST;
150386a2265eSRasesh Mody 	case ECORE_IOV_VP_UPDATE_ACCEPT_PARAM:
150486a2265eSRasesh Mody 		return CHANNEL_TLV_VPORT_UPDATE_ACCEPT_PARAM;
150586a2265eSRasesh Mody 	case ECORE_IOV_VP_UPDATE_RSS:
150686a2265eSRasesh Mody 		return CHANNEL_TLV_VPORT_UPDATE_RSS;
150786a2265eSRasesh Mody 	case ECORE_IOV_VP_UPDATE_ACCEPT_ANY_VLAN:
150886a2265eSRasesh Mody 		return CHANNEL_TLV_VPORT_UPDATE_ACCEPT_ANY_VLAN;
150986a2265eSRasesh Mody 	case ECORE_IOV_VP_UPDATE_SGE_TPA:
151086a2265eSRasesh Mody 		return CHANNEL_TLV_VPORT_UPDATE_SGE_TPA;
151186a2265eSRasesh Mody 	default:
151286a2265eSRasesh Mody 		return 0;
151386a2265eSRasesh Mody 	}
151486a2265eSRasesh Mody }
151586a2265eSRasesh Mody 
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)151686a2265eSRasesh Mody static u16 ecore_iov_prep_vp_update_resp_tlvs(struct ecore_hwfn *p_hwfn,
151786a2265eSRasesh Mody 					      struct ecore_vf_info *p_vf,
151886a2265eSRasesh Mody 					      struct ecore_iov_vf_mbx *p_mbx,
151986a2265eSRasesh Mody 					      u8 status, u16 tlvs_mask,
152086a2265eSRasesh Mody 					      u16 tlvs_accepted)
152186a2265eSRasesh Mody {
152286a2265eSRasesh Mody 	struct pfvf_def_resp_tlv *resp;
152386a2265eSRasesh Mody 	u16 size, total_len, i;
152486a2265eSRasesh Mody 
152586a2265eSRasesh Mody 	OSAL_MEMSET(p_mbx->reply_virt, 0, sizeof(union pfvf_tlvs));
152622d07d93SRasesh Mody 	p_mbx->offset = (u8 *)p_mbx->reply_virt;
152786a2265eSRasesh Mody 	size = sizeof(struct pfvf_def_resp_tlv);
152886a2265eSRasesh Mody 	total_len = size;
152986a2265eSRasesh Mody 
153030ecf673SRasesh Mody 	ecore_add_tlv(&p_mbx->offset, CHANNEL_TLV_VPORT_UPDATE, size);
153186a2265eSRasesh Mody 
153286a2265eSRasesh Mody 	/* Prepare response for all extended tlvs if they are found by PF */
153386a2265eSRasesh Mody 	for (i = 0; i < ECORE_IOV_VP_UPDATE_MAX; i++) {
153486a2265eSRasesh Mody 		if (!(tlvs_mask & (1 << i)))
153586a2265eSRasesh Mody 			continue;
153686a2265eSRasesh Mody 
153730ecf673SRasesh Mody 		resp = ecore_add_tlv(&p_mbx->offset, ecore_iov_vport_to_tlv(i),
153830ecf673SRasesh Mody 				     size);
153986a2265eSRasesh Mody 
154086a2265eSRasesh Mody 		if (tlvs_accepted & (1 << i))
154186a2265eSRasesh Mody 			resp->hdr.status = status;
154286a2265eSRasesh Mody 		else
154386a2265eSRasesh Mody 			resp->hdr.status = PFVF_STATUS_NOT_SUPPORTED;
154486a2265eSRasesh Mody 
154586a2265eSRasesh Mody 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
154686a2265eSRasesh Mody 			   "VF[%d] - vport_update resp: TLV %d, status %02x\n",
154786a2265eSRasesh Mody 			   p_vf->relative_vf_id,
154830ecf673SRasesh Mody 			   ecore_iov_vport_to_tlv(i),
154930ecf673SRasesh Mody 			   resp->hdr.status);
155086a2265eSRasesh Mody 
155186a2265eSRasesh Mody 		total_len += size;
155286a2265eSRasesh Mody 	}
155386a2265eSRasesh Mody 
155430ecf673SRasesh Mody 	ecore_add_tlv(&p_mbx->offset, CHANNEL_TLV_LIST_END,
155586a2265eSRasesh Mody 		      sizeof(struct channel_list_end_tlv));
155686a2265eSRasesh Mody 
155786a2265eSRasesh Mody 	return total_len;
155886a2265eSRasesh Mody }
155986a2265eSRasesh Mody 
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)156086a2265eSRasesh Mody static void ecore_iov_prepare_resp(struct ecore_hwfn *p_hwfn,
156186a2265eSRasesh Mody 				   struct ecore_ptt *p_ptt,
156286a2265eSRasesh Mody 				   struct ecore_vf_info *vf_info,
156386a2265eSRasesh Mody 				   u16 type, u16 length, u8 status)
156486a2265eSRasesh Mody {
156586a2265eSRasesh Mody 	struct ecore_iov_vf_mbx *mbx = &vf_info->vf_mbx;
156686a2265eSRasesh Mody 
156722d07d93SRasesh Mody 	mbx->offset = (u8 *)mbx->reply_virt;
156886a2265eSRasesh Mody 
156930ecf673SRasesh Mody 	ecore_add_tlv(&mbx->offset, type, length);
157030ecf673SRasesh Mody 	ecore_add_tlv(&mbx->offset, CHANNEL_TLV_LIST_END,
157186a2265eSRasesh Mody 		      sizeof(struct channel_list_end_tlv));
157286a2265eSRasesh Mody 
157386a2265eSRasesh Mody 	ecore_iov_send_response(p_hwfn, p_ptt, vf_info, length, status);
157422d07d93SRasesh Mody }
157522d07d93SRasesh Mody 
157622d07d93SRasesh Mody struct ecore_public_vf_info
ecore_iov_get_public_vf_info(struct ecore_hwfn * p_hwfn,u16 relative_vf_id,bool b_enabled_only)157722d07d93SRasesh Mody *ecore_iov_get_public_vf_info(struct ecore_hwfn *p_hwfn,
157822d07d93SRasesh Mody 			      u16 relative_vf_id,
157922d07d93SRasesh Mody 			      bool b_enabled_only)
158022d07d93SRasesh Mody {
158122d07d93SRasesh Mody 	struct ecore_vf_info *vf = OSAL_NULL;
158222d07d93SRasesh Mody 
158322d07d93SRasesh Mody 	vf = ecore_iov_get_vf_info(p_hwfn, relative_vf_id, b_enabled_only);
158422d07d93SRasesh Mody 	if (!vf)
158522d07d93SRasesh Mody 		return OSAL_NULL;
158622d07d93SRasesh Mody 
158722d07d93SRasesh Mody 	return &vf->p_vf_info;
158886a2265eSRasesh Mody }
158986a2265eSRasesh Mody 
ecore_iov_vf_cleanup(struct ecore_hwfn * p_hwfn,struct ecore_vf_info * p_vf)159086a2265eSRasesh Mody static void ecore_iov_vf_cleanup(struct ecore_hwfn *p_hwfn,
159186a2265eSRasesh Mody 				 struct ecore_vf_info *p_vf)
159286a2265eSRasesh Mody {
1593eb8e81adSRasesh Mody 	u32 i, j;
159486a2265eSRasesh Mody 	p_vf->vf_bulletin = 0;
159586a2265eSRasesh Mody 	p_vf->vport_instance = 0;
159686a2265eSRasesh Mody 	p_vf->configured_features = 0;
159786a2265eSRasesh Mody 
159886a2265eSRasesh Mody 	/* If VF previously requested less resources, go back to default */
159986a2265eSRasesh Mody 	p_vf->num_rxqs = p_vf->num_sbs;
160086a2265eSRasesh Mody 	p_vf->num_txqs = p_vf->num_sbs;
160186a2265eSRasesh Mody 
160286a2265eSRasesh Mody 	p_vf->num_active_rxqs = 0;
160386a2265eSRasesh Mody 
1604bd96f72fSRasesh Mody 	for (i = 0; i < ECORE_MAX_VF_CHAINS_PER_PF; i++) {
1605eb8e81adSRasesh Mody 		struct ecore_vf_queue *p_queue = &p_vf->vf_queues[i];
1606a55e422eSRasesh Mody 
1607eb8e81adSRasesh Mody 		for (j = 0; j < MAX_QUEUES_PER_QZONE; j++) {
1608eb8e81adSRasesh Mody 			if (!p_queue->cids[j].p_cid)
1609eb8e81adSRasesh Mody 				continue;
1610a55e422eSRasesh Mody 
1611a55e422eSRasesh Mody 			ecore_eth_queue_cid_release(p_hwfn,
1612eb8e81adSRasesh Mody 						    p_queue->cids[j].p_cid);
1613eb8e81adSRasesh Mody 			p_queue->cids[j].p_cid = OSAL_NULL;
1614a55e422eSRasesh Mody 		}
1615bd96f72fSRasesh Mody 	}
161622d07d93SRasesh Mody 
161786a2265eSRasesh Mody 	OSAL_MEMSET(&p_vf->shadow_config, 0, sizeof(p_vf->shadow_config));
161822d07d93SRasesh Mody 	OSAL_MEMSET(&p_vf->acquire, 0, sizeof(p_vf->acquire));
161986a2265eSRasesh Mody 	OSAL_IOV_VF_CLEANUP(p_hwfn, p_vf->relative_vf_id);
162086a2265eSRasesh Mody }
162186a2265eSRasesh Mody 
1622c73d7da7SRasesh Mody /* Returns either 0, or log(size) */
ecore_iov_vf_db_bar_size(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)1623c73d7da7SRasesh Mody static u32 ecore_iov_vf_db_bar_size(struct ecore_hwfn *p_hwfn,
1624c73d7da7SRasesh Mody 				    struct ecore_ptt *p_ptt)
1625c73d7da7SRasesh Mody {
1626c73d7da7SRasesh Mody 	u32 val = ecore_rd(p_hwfn, p_ptt, PGLUE_B_REG_VF_BAR1_SIZE);
1627c73d7da7SRasesh Mody 
1628c73d7da7SRasesh Mody 	if (val)
1629c73d7da7SRasesh Mody 		return val + 11;
1630c73d7da7SRasesh Mody 	return 0;
1631c73d7da7SRasesh Mody }
1632c73d7da7SRasesh Mody 
1633c73d7da7SRasesh Mody 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)1634c73d7da7SRasesh Mody ecore_iov_vf_mbx_acquire_resc_cids(struct ecore_hwfn *p_hwfn,
1635c73d7da7SRasesh Mody 				   struct ecore_ptt *p_ptt,
1636c73d7da7SRasesh Mody 				   struct ecore_vf_info *p_vf,
1637c73d7da7SRasesh Mody 				   struct vf_pf_resc_request *p_req,
1638c73d7da7SRasesh Mody 				   struct pf_vf_resc *p_resp)
1639c73d7da7SRasesh Mody {
1640c73d7da7SRasesh Mody 	u8 num_vf_cons = p_hwfn->pf_params.eth_pf_params.num_vf_cons;
1641c73d7da7SRasesh Mody 	u8 db_size = DB_ADDR_VF(1, DQ_DEMS_LEGACY) -
1642c73d7da7SRasesh Mody 		     DB_ADDR_VF(0, DQ_DEMS_LEGACY);
1643c73d7da7SRasesh Mody 	u32 bar_size;
1644c73d7da7SRasesh Mody 
1645c73d7da7SRasesh Mody 	p_resp->num_cids = OSAL_MIN_T(u8, p_req->num_cids, num_vf_cons);
1646c73d7da7SRasesh Mody 
1647c73d7da7SRasesh Mody 	/* If VF didn't bother asking for QIDs than don't bother limiting
1648c73d7da7SRasesh Mody 	 * number of CIDs. The VF doesn't care about the number, and this
1649c73d7da7SRasesh Mody 	 * has the likely result of causing an additional acquisition.
1650c73d7da7SRasesh Mody 	 */
1651c73d7da7SRasesh Mody 	if (!(p_vf->acquire.vfdev_info.capabilities &
1652c73d7da7SRasesh Mody 	      VFPF_ACQUIRE_CAP_QUEUE_QIDS))
1653c73d7da7SRasesh Mody 		return;
1654c73d7da7SRasesh Mody 
1655c73d7da7SRasesh Mody 	/* If doorbell bar was mapped by VF, limit the VF CIDs to an amount
1656c73d7da7SRasesh Mody 	 * that would make sure doorbells for all CIDs fall within the bar.
1657c73d7da7SRasesh Mody 	 * If it doesn't, make sure regview window is sufficient.
1658c73d7da7SRasesh Mody 	 */
1659c73d7da7SRasesh Mody 	if (p_vf->acquire.vfdev_info.capabilities &
1660c73d7da7SRasesh Mody 	    VFPF_ACQUIRE_CAP_PHYSICAL_BAR) {
1661c73d7da7SRasesh Mody 		bar_size = ecore_iov_vf_db_bar_size(p_hwfn, p_ptt);
1662c73d7da7SRasesh Mody 		if (bar_size)
1663c73d7da7SRasesh Mody 			bar_size = 1 << bar_size;
1664c73d7da7SRasesh Mody 
1665c73d7da7SRasesh Mody 		if (ECORE_IS_CMT(p_hwfn->p_dev))
1666c73d7da7SRasesh Mody 			bar_size /= 2;
1667c73d7da7SRasesh Mody 	} else {
1668c73d7da7SRasesh Mody 		bar_size = PXP_VF_BAR0_DQ_LENGTH;
1669c73d7da7SRasesh Mody 	}
1670c73d7da7SRasesh Mody 
1671c73d7da7SRasesh Mody 	if (bar_size / db_size < 256)
1672c73d7da7SRasesh Mody 		p_resp->num_cids = OSAL_MIN_T(u8, p_resp->num_cids,
1673c73d7da7SRasesh Mody 					      (u8)(bar_size / db_size));
1674c73d7da7SRasesh Mody }
1675c73d7da7SRasesh Mody 
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)167622d07d93SRasesh Mody static u8 ecore_iov_vf_mbx_acquire_resc(struct ecore_hwfn *p_hwfn,
1677c73d7da7SRasesh Mody 					struct ecore_ptt *p_ptt,
167822d07d93SRasesh Mody 					struct ecore_vf_info *p_vf,
167922d07d93SRasesh Mody 					struct vf_pf_resc_request *p_req,
168022d07d93SRasesh Mody 					struct pf_vf_resc *p_resp)
168122d07d93SRasesh Mody {
1682eb8e81adSRasesh Mody 	u8 i;
168322d07d93SRasesh Mody 
168422d07d93SRasesh Mody 	/* Queue related information */
168522d07d93SRasesh Mody 	p_resp->num_rxqs = p_vf->num_rxqs;
168622d07d93SRasesh Mody 	p_resp->num_txqs = p_vf->num_txqs;
168722d07d93SRasesh Mody 	p_resp->num_sbs = p_vf->num_sbs;
168822d07d93SRasesh Mody 
168922d07d93SRasesh Mody 	for (i = 0; i < p_resp->num_sbs; i++) {
169022d07d93SRasesh Mody 		p_resp->hw_sbs[i].hw_sb_id = p_vf->igu_sbs[i];
169122d07d93SRasesh Mody 		/* TODO - what's this sb_qid field? Is it deprecated?
169222d07d93SRasesh Mody 		 * or is there an ecore_client that looks at this?
169322d07d93SRasesh Mody 		 */
169422d07d93SRasesh Mody 		p_resp->hw_sbs[i].sb_qid = 0;
169522d07d93SRasesh Mody 	}
169622d07d93SRasesh Mody 
169722d07d93SRasesh Mody 	/* These fields are filled for backward compatibility.
169822d07d93SRasesh Mody 	 * Unused by modern vfs.
169922d07d93SRasesh Mody 	 */
170022d07d93SRasesh Mody 	for (i = 0; i < p_resp->num_rxqs; i++) {
170122d07d93SRasesh Mody 		ecore_fw_l2_queue(p_hwfn, p_vf->vf_queues[i].fw_rx_qid,
170222d07d93SRasesh Mody 				  (u16 *)&p_resp->hw_qid[i]);
1703eb8e81adSRasesh Mody 		p_resp->cid[i] = i;
170422d07d93SRasesh Mody 	}
170522d07d93SRasesh Mody 
170622d07d93SRasesh Mody 	/* Filter related information */
170722d07d93SRasesh Mody 	p_resp->num_mac_filters = OSAL_MIN_T(u8, p_vf->num_mac_filters,
170822d07d93SRasesh Mody 					     p_req->num_mac_filters);
170922d07d93SRasesh Mody 	p_resp->num_vlan_filters = OSAL_MIN_T(u8, p_vf->num_vlan_filters,
171022d07d93SRasesh Mody 					      p_req->num_vlan_filters);
171122d07d93SRasesh Mody 
1712c73d7da7SRasesh Mody 	ecore_iov_vf_mbx_acquire_resc_cids(p_hwfn, p_ptt, p_vf, p_req, p_resp);
1713a90c566fSRasesh Mody 
171422d07d93SRasesh Mody 	/* This isn't really needed/enforced, but some legacy VFs might depend
171522d07d93SRasesh Mody 	 * on the correct filling of this field.
171622d07d93SRasesh Mody 	 */
171722d07d93SRasesh Mody 	p_resp->num_mc_filters = ECORE_MAX_MC_ADDRS;
171822d07d93SRasesh Mody 
171922d07d93SRasesh Mody 	/* Validate sufficient resources for VF */
172022d07d93SRasesh Mody 	if (p_resp->num_rxqs < p_req->num_rxqs ||
172122d07d93SRasesh Mody 	    p_resp->num_txqs < p_req->num_txqs ||
172222d07d93SRasesh Mody 	    p_resp->num_sbs < p_req->num_sbs ||
172322d07d93SRasesh Mody 	    p_resp->num_mac_filters < p_req->num_mac_filters ||
172422d07d93SRasesh Mody 	    p_resp->num_vlan_filters < p_req->num_vlan_filters ||
1725a90c566fSRasesh Mody 	    p_resp->num_mc_filters < p_req->num_mc_filters ||
1726a90c566fSRasesh Mody 	    p_resp->num_cids < p_req->num_cids) {
172722d07d93SRasesh Mody 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
1728a90c566fSRasesh Mody 			   "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",
172922d07d93SRasesh Mody 			   p_vf->abs_vf_id,
173022d07d93SRasesh Mody 			   p_req->num_rxqs, p_resp->num_rxqs,
173122d07d93SRasesh Mody 			   p_req->num_rxqs, p_resp->num_txqs,
173222d07d93SRasesh Mody 			   p_req->num_sbs, p_resp->num_sbs,
173322d07d93SRasesh Mody 			   p_req->num_mac_filters, p_resp->num_mac_filters,
173422d07d93SRasesh Mody 			   p_req->num_vlan_filters, p_resp->num_vlan_filters,
1735a90c566fSRasesh Mody 			   p_req->num_mc_filters, p_resp->num_mc_filters,
1736a90c566fSRasesh Mody 			   p_req->num_cids, p_resp->num_cids);
173722d07d93SRasesh Mody 
173822d07d93SRasesh Mody 		/* Some legacy OSes are incapable of correctly handling this
173922d07d93SRasesh Mody 		 * failure.
174022d07d93SRasesh Mody 		 */
174122d07d93SRasesh Mody 		if ((p_vf->acquire.vfdev_info.eth_fp_hsi_minor ==
174222d07d93SRasesh Mody 		     ETH_HSI_VER_NO_PKT_LEN_TUNN) &&
174322d07d93SRasesh Mody 		    (p_vf->acquire.vfdev_info.os_type ==
174422d07d93SRasesh Mody 		     VFPF_ACQUIRE_OS_WINDOWS))
174522d07d93SRasesh Mody 			return PFVF_STATUS_SUCCESS;
174622d07d93SRasesh Mody 
174722d07d93SRasesh Mody 		return PFVF_STATUS_NO_RESOURCE;
174822d07d93SRasesh Mody 	}
174922d07d93SRasesh Mody 
175022d07d93SRasesh Mody 	return PFVF_STATUS_SUCCESS;
175122d07d93SRasesh Mody }
175222d07d93SRasesh Mody 
ecore_iov_vf_mbx_acquire_stats(struct pfvf_stats_info * p_stats)175330ecf673SRasesh Mody static void ecore_iov_vf_mbx_acquire_stats(struct pfvf_stats_info *p_stats)
175422d07d93SRasesh Mody {
175522d07d93SRasesh Mody 	p_stats->mstats.address = PXP_VF_BAR0_START_MSDM_ZONE_B +
175622d07d93SRasesh Mody 				  OFFSETOF(struct mstorm_vf_zone,
175722d07d93SRasesh Mody 					   non_trigger.eth_queue_stat);
175822d07d93SRasesh Mody 	p_stats->mstats.len = sizeof(struct eth_mstorm_per_queue_stat);
175922d07d93SRasesh Mody 	p_stats->ustats.address = PXP_VF_BAR0_START_USDM_ZONE_B +
176022d07d93SRasesh Mody 				  OFFSETOF(struct ustorm_vf_zone,
176122d07d93SRasesh Mody 					   non_trigger.eth_queue_stat);
176222d07d93SRasesh Mody 	p_stats->ustats.len = sizeof(struct eth_ustorm_per_queue_stat);
176322d07d93SRasesh Mody 	p_stats->pstats.address = PXP_VF_BAR0_START_PSDM_ZONE_B +
176422d07d93SRasesh Mody 				  OFFSETOF(struct pstorm_vf_zone,
176522d07d93SRasesh Mody 					   non_trigger.eth_queue_stat);
176622d07d93SRasesh Mody 	p_stats->pstats.len = sizeof(struct eth_pstorm_per_queue_stat);
176722d07d93SRasesh Mody 	p_stats->tstats.address = 0;
176822d07d93SRasesh Mody 	p_stats->tstats.len = 0;
176922d07d93SRasesh Mody }
177022d07d93SRasesh Mody 
ecore_iov_vf_mbx_acquire(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * vf)177186a2265eSRasesh Mody static void ecore_iov_vf_mbx_acquire(struct ecore_hwfn       *p_hwfn,
177286a2265eSRasesh Mody 				     struct ecore_ptt	     *p_ptt,
177386a2265eSRasesh Mody 				     struct ecore_vf_info    *vf)
177486a2265eSRasesh Mody {
177586a2265eSRasesh Mody 	struct ecore_iov_vf_mbx *mbx = &vf->vf_mbx;
177686a2265eSRasesh Mody 	struct pfvf_acquire_resp_tlv *resp = &mbx->reply_virt->acquire_resp;
177786a2265eSRasesh Mody 	struct pf_vf_pfdev_info *pfdev_info = &resp->pfdev_info;
177822d07d93SRasesh Mody 	struct vfpf_acquire_tlv *req = &mbx->req_virt->acquire;
177922d07d93SRasesh Mody 	u8 vfpf_status = PFVF_STATUS_NOT_SUPPORTED;
178022d07d93SRasesh Mody 	struct pf_vf_resc *resc = &resp->resc;
178122d07d93SRasesh Mody 	enum _ecore_status_t rc;
178222d07d93SRasesh Mody 
178322d07d93SRasesh Mody 	OSAL_MEMSET(resp, 0, sizeof(*resp));
178422d07d93SRasesh Mody 
178522d07d93SRasesh Mody 	/* Write the PF version so that VF would know which version
178622d07d93SRasesh Mody 	 * is supported - might be later overridden. This guarantees that
178722d07d93SRasesh Mody 	 * VF could recognize legacy PF based on lack of versions in reply.
178822d07d93SRasesh Mody 	 */
178922d07d93SRasesh Mody 	pfdev_info->major_fp_hsi = ETH_HSI_VER_MAJOR;
179022d07d93SRasesh Mody 	pfdev_info->minor_fp_hsi = ETH_HSI_VER_MINOR;
179186a2265eSRasesh Mody 
1792b765730bSRasesh Mody 	/* TODO - not doing anything is bad since we'll assert, but this isn't
1793b765730bSRasesh Mody 	 * necessarily the right behavior - perhaps we should have allowed some
1794b765730bSRasesh Mody 	 * versatility here.
1795b765730bSRasesh Mody 	 */
1796b765730bSRasesh Mody 	if (vf->state != VF_FREE &&
1797b765730bSRasesh Mody 	    vf->state != VF_STOPPED) {
1798b765730bSRasesh Mody 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
1799b765730bSRasesh Mody 			   "VF[%d] sent ACQUIRE but is already in state %d - fail request\n",
1800b765730bSRasesh Mody 			   vf->abs_vf_id, vf->state);
1801b765730bSRasesh Mody 		goto out;
1802b765730bSRasesh Mody 	}
1803b765730bSRasesh Mody 
180486a2265eSRasesh Mody 	/* Validate FW compatibility */
180522d07d93SRasesh Mody 	if (req->vfdev_info.eth_fp_hsi_major != ETH_HSI_VER_MAJOR) {
180622d07d93SRasesh Mody 		if (req->vfdev_info.capabilities &
180722d07d93SRasesh Mody 		    VFPF_ACQUIRE_CAP_PRE_FP_HSI) {
180822d07d93SRasesh Mody 			struct vf_pf_vfdev_info *p_vfdev = &req->vfdev_info;
180922d07d93SRasesh Mody 
181022d07d93SRasesh Mody 			/* This legacy support would need to be removed once
181122d07d93SRasesh Mody 			 * the major has changed.
181222d07d93SRasesh Mody 			 */
181322d07d93SRasesh Mody 			OSAL_BUILD_BUG_ON(ETH_HSI_VER_MAJOR != 3);
181422d07d93SRasesh Mody 
181522d07d93SRasesh Mody 			DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
181622d07d93SRasesh Mody 				   "VF[%d] is pre-fastpath HSI\n",
181722d07d93SRasesh Mody 				   vf->abs_vf_id);
181822d07d93SRasesh Mody 			p_vfdev->eth_fp_hsi_major = ETH_HSI_VER_MAJOR;
181922d07d93SRasesh Mody 			p_vfdev->eth_fp_hsi_minor = ETH_HSI_VER_NO_PKT_LEN_TUNN;
182022d07d93SRasesh Mody 		} else {
182186a2265eSRasesh Mody 			DP_INFO(p_hwfn,
182222d07d93SRasesh Mody 				"VF[%d] needs fastpath HSI %02x.%02x, which is"
182322d07d93SRasesh Mody 				" incompatible with loaded FW's faspath"
182422d07d93SRasesh Mody 				" HSI %02x.%02x\n",
182522d07d93SRasesh Mody 				vf->abs_vf_id,
182622d07d93SRasesh Mody 				req->vfdev_info.eth_fp_hsi_major,
182722d07d93SRasesh Mody 				req->vfdev_info.eth_fp_hsi_minor,
182822d07d93SRasesh Mody 				ETH_HSI_VER_MAJOR, ETH_HSI_VER_MINOR);
182922d07d93SRasesh Mody 
183086a2265eSRasesh Mody 			goto out;
183186a2265eSRasesh Mody 		}
183222d07d93SRasesh Mody 	}
183322d07d93SRasesh Mody 
183422d07d93SRasesh Mody 	/* On 100g PFs, prevent old VFs from loading */
1835c0845c33SRasesh Mody 	if (ECORE_IS_CMT(p_hwfn->p_dev) &&
183622d07d93SRasesh Mody 	    !(req->vfdev_info.capabilities & VFPF_ACQUIRE_CAP_100G)) {
183722d07d93SRasesh Mody 		DP_INFO(p_hwfn,
183822d07d93SRasesh Mody 			"VF[%d] is running an old driver that doesn't support"
183922d07d93SRasesh Mody 			" 100g\n",
184022d07d93SRasesh Mody 			vf->abs_vf_id);
184122d07d93SRasesh Mody 		goto out;
184222d07d93SRasesh Mody 	}
184322d07d93SRasesh Mody 
184486a2265eSRasesh Mody #ifndef __EXTRACT__LINUX__
184586a2265eSRasesh Mody 	if (OSAL_IOV_VF_ACQUIRE(p_hwfn, vf->relative_vf_id) != ECORE_SUCCESS) {
184686a2265eSRasesh Mody 		vfpf_status = PFVF_STATUS_NOT_SUPPORTED;
184786a2265eSRasesh Mody 		goto out;
184886a2265eSRasesh Mody 	}
184986a2265eSRasesh Mody #endif
185086a2265eSRasesh Mody 
185122d07d93SRasesh Mody 	/* Store the acquire message */
185222d07d93SRasesh Mody 	OSAL_MEMCPY(&vf->acquire, req, sizeof(vf->acquire));
185386a2265eSRasesh Mody 
185486a2265eSRasesh Mody 	vf->opaque_fid = req->vfdev_info.opaque_fid;
185586a2265eSRasesh Mody 
185686a2265eSRasesh Mody 	vf->vf_bulletin = req->bulletin_addr;
185786a2265eSRasesh Mody 	vf->bulletin.size = (vf->bulletin.size < req->bulletin_size) ?
185886a2265eSRasesh Mody 	    vf->bulletin.size : req->bulletin_size;
185986a2265eSRasesh Mody 
186086a2265eSRasesh Mody 	/* fill in pfdev info */
186186a2265eSRasesh Mody 	pfdev_info->chip_num = p_hwfn->p_dev->chip_num;
186286a2265eSRasesh Mody 	pfdev_info->db_size = 0;	/* @@@ TBD MichalK Vf Doorbells */
18633b307c55SRasesh Mody 	pfdev_info->indices_per_sb = PIS_PER_SB;
186486a2265eSRasesh Mody 
186522d07d93SRasesh Mody 	pfdev_info->capabilities = PFVF_ACQUIRE_CAP_DEFAULT_UNTAGGED |
186622d07d93SRasesh Mody 				   PFVF_ACQUIRE_CAP_POST_FW_OVERRIDE;
1867c0845c33SRasesh Mody 	if (ECORE_IS_CMT(p_hwfn->p_dev))
186822d07d93SRasesh Mody 		pfdev_info->capabilities |= PFVF_ACQUIRE_CAP_100G;
186986a2265eSRasesh Mody 
1870a90c566fSRasesh Mody 	/* Share our ability to use multiple queue-ids only with VFs
1871a90c566fSRasesh Mody 	 * that request it.
1872a90c566fSRasesh Mody 	 */
1873a90c566fSRasesh Mody 	if (req->vfdev_info.capabilities & VFPF_ACQUIRE_CAP_QUEUE_QIDS)
1874a90c566fSRasesh Mody 		pfdev_info->capabilities |= PFVF_ACQUIRE_CAP_QUEUE_QIDS;
1875a90c566fSRasesh Mody 
1876c73d7da7SRasesh Mody 	/* Share the sizes of the bars with VF */
1877c73d7da7SRasesh Mody 	resp->pfdev_info.bar_size = (u8)ecore_iov_vf_db_bar_size(p_hwfn,
1878c73d7da7SRasesh Mody 							     p_ptt);
1879c73d7da7SRasesh Mody 
188030ecf673SRasesh Mody 	ecore_iov_vf_mbx_acquire_stats(&pfdev_info->stats_info);
188186a2265eSRasesh Mody 
188286a2265eSRasesh Mody 	OSAL_MEMCPY(pfdev_info->port_mac, p_hwfn->hw_info.hw_mac_addr,
188386a2265eSRasesh Mody 		    ETH_ALEN);
188486a2265eSRasesh Mody 
188586a2265eSRasesh Mody 	pfdev_info->fw_major = FW_MAJOR_VERSION;
188686a2265eSRasesh Mody 	pfdev_info->fw_minor = FW_MINOR_VERSION;
188786a2265eSRasesh Mody 	pfdev_info->fw_rev = FW_REVISION_VERSION;
188886a2265eSRasesh Mody 	pfdev_info->fw_eng = FW_ENGINEERING_VERSION;
188922d07d93SRasesh Mody 
189022d07d93SRasesh Mody 	/* Incorrect when legacy, but doesn't matter as legacy isn't reading
189122d07d93SRasesh Mody 	 * this field.
189222d07d93SRasesh Mody 	 */
189322d07d93SRasesh Mody 	pfdev_info->minor_fp_hsi = OSAL_MIN_T(u8, ETH_HSI_VER_MINOR,
189422d07d93SRasesh Mody 					      req->vfdev_info.eth_fp_hsi_minor);
189586a2265eSRasesh Mody 	pfdev_info->os_type = OSAL_IOV_GET_OS_TYPE();
189622d07d93SRasesh Mody 	ecore_mcp_get_mfw_ver(p_hwfn, p_ptt, &pfdev_info->mfw_ver,
189786a2265eSRasesh Mody 			      OSAL_NULL);
189886a2265eSRasesh Mody 
189986a2265eSRasesh Mody 	pfdev_info->dev_type = p_hwfn->p_dev->type;
190086a2265eSRasesh Mody 	pfdev_info->chip_rev = p_hwfn->p_dev->chip_rev;
190186a2265eSRasesh Mody 
190222d07d93SRasesh Mody 	/* Fill resources available to VF; Make sure there are enough to
190322d07d93SRasesh Mody 	 * satisfy the VF's request.
190422d07d93SRasesh Mody 	 */
1905c73d7da7SRasesh Mody 	vfpf_status = ecore_iov_vf_mbx_acquire_resc(p_hwfn, p_ptt, vf,
190622d07d93SRasesh Mody 						    &req->resc_request, resc);
190722d07d93SRasesh Mody 	if (vfpf_status != PFVF_STATUS_SUCCESS)
190822d07d93SRasesh Mody 		goto out;
190986a2265eSRasesh Mody 
191022d07d93SRasesh Mody 	/* Start the VF in FW */
191122d07d93SRasesh Mody 	rc = ecore_sp_vf_start(p_hwfn, vf);
191222d07d93SRasesh Mody 	if (rc != ECORE_SUCCESS) {
191322d07d93SRasesh Mody 		DP_NOTICE(p_hwfn, true, "Failed to start VF[%02x]\n",
191422d07d93SRasesh Mody 			  vf->abs_vf_id);
191522d07d93SRasesh Mody 		vfpf_status = PFVF_STATUS_FAILURE;
191622d07d93SRasesh Mody 		goto out;
191786a2265eSRasesh Mody 	}
191886a2265eSRasesh Mody 
191986a2265eSRasesh Mody 	/* Fill agreed size of bulletin board in response, and post
192086a2265eSRasesh Mody 	 * an initial image to the bulletin board.
192186a2265eSRasesh Mody 	 */
192286a2265eSRasesh Mody 	resp->bulletin_size = vf->bulletin.size;
192386a2265eSRasesh Mody 	ecore_iov_post_vf_bulletin(p_hwfn, vf->relative_vf_id, p_ptt);
192486a2265eSRasesh Mody 
192586a2265eSRasesh Mody 	DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
192686a2265eSRasesh Mody 		   "VF[%d] ACQUIRE_RESPONSE: pfdev_info- chip_num=0x%x,"
192722d07d93SRasesh Mody 		   " db_size=%d, idx_per_sb=%d, pf_cap=0x%lx\n"
192886a2265eSRasesh Mody 		   "resources- n_rxq-%d, n_txq-%d, n_sbs-%d, n_macs-%d,"
19293013f8c1SRasesh Mody 		   " n_vlans-%d\n",
193086a2265eSRasesh Mody 		   vf->abs_vf_id, resp->pfdev_info.chip_num,
193186a2265eSRasesh Mody 		   resp->pfdev_info.db_size, resp->pfdev_info.indices_per_sb,
193222d07d93SRasesh Mody 		   (unsigned long)resp->pfdev_info.capabilities, resc->num_rxqs,
193386a2265eSRasesh Mody 		   resc->num_txqs, resc->num_sbs, resc->num_mac_filters,
19343013f8c1SRasesh Mody 		   resc->num_vlan_filters);
193586a2265eSRasesh Mody 
193686a2265eSRasesh Mody 	vf->state = VF_ACQUIRED;
193786a2265eSRasesh Mody 
193886a2265eSRasesh Mody out:
193922d07d93SRasesh Mody 	/* Prepare Response */
194086a2265eSRasesh Mody 	ecore_iov_prepare_resp(p_hwfn, p_ptt, vf, CHANNEL_TLV_ACQUIRE,
194122d07d93SRasesh Mody 			       sizeof(struct pfvf_acquire_resp_tlv),
194222d07d93SRasesh Mody 			       vfpf_status);
194386a2265eSRasesh Mody }
194486a2265eSRasesh Mody 
194586a2265eSRasesh Mody static enum _ecore_status_t
__ecore_iov_spoofchk_set(struct ecore_hwfn * p_hwfn,struct ecore_vf_info * p_vf,bool val)194686a2265eSRasesh Mody __ecore_iov_spoofchk_set(struct ecore_hwfn *p_hwfn,
194786a2265eSRasesh Mody 			 struct ecore_vf_info *p_vf, bool val)
194886a2265eSRasesh Mody {
194986a2265eSRasesh Mody 	struct ecore_sp_vport_update_params params;
195086a2265eSRasesh Mody 	enum _ecore_status_t rc;
195186a2265eSRasesh Mody 
195286a2265eSRasesh Mody 	if (val == p_vf->spoof_chk) {
195386a2265eSRasesh Mody 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
195486a2265eSRasesh Mody 			   "Spoofchk value[%d] is already configured\n", val);
195586a2265eSRasesh Mody 		return ECORE_SUCCESS;
195686a2265eSRasesh Mody 	}
195786a2265eSRasesh Mody 
195886a2265eSRasesh Mody 	OSAL_MEMSET(&params, 0, sizeof(struct ecore_sp_vport_update_params));
195986a2265eSRasesh Mody 	params.opaque_fid = p_vf->opaque_fid;
196086a2265eSRasesh Mody 	params.vport_id = p_vf->vport_id;
196186a2265eSRasesh Mody 	params.update_anti_spoofing_en_flg = 1;
196286a2265eSRasesh Mody 	params.anti_spoofing_en = val;
196386a2265eSRasesh Mody 
196486a2265eSRasesh Mody 	rc = ecore_sp_vport_update(p_hwfn, &params, ECORE_SPQ_MODE_EBLOCK,
196586a2265eSRasesh Mody 				   OSAL_NULL);
196686a2265eSRasesh Mody 	if (rc == ECORE_SUCCESS) {
196786a2265eSRasesh Mody 		p_vf->spoof_chk = val;
196886a2265eSRasesh Mody 		p_vf->req_spoofchk_val = p_vf->spoof_chk;
196986a2265eSRasesh Mody 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
197086a2265eSRasesh Mody 			   "Spoofchk val[%d] configured\n", val);
197186a2265eSRasesh Mody 	} else {
197286a2265eSRasesh Mody 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
197386a2265eSRasesh Mody 			   "Spoofchk configuration[val:%d] failed for VF[%d]\n",
197486a2265eSRasesh Mody 			   val, p_vf->relative_vf_id);
197586a2265eSRasesh Mody 	}
197686a2265eSRasesh Mody 
197786a2265eSRasesh Mody 	return rc;
197886a2265eSRasesh Mody }
197986a2265eSRasesh Mody 
198086a2265eSRasesh Mody static enum _ecore_status_t
ecore_iov_reconfigure_unicast_vlan(struct ecore_hwfn * p_hwfn,struct ecore_vf_info * p_vf)198186a2265eSRasesh Mody ecore_iov_reconfigure_unicast_vlan(struct ecore_hwfn *p_hwfn,
198286a2265eSRasesh Mody 				   struct ecore_vf_info *p_vf)
198386a2265eSRasesh Mody {
198486a2265eSRasesh Mody 	struct ecore_filter_ucast filter;
198522d07d93SRasesh Mody 	enum _ecore_status_t rc = ECORE_SUCCESS;
198686a2265eSRasesh Mody 	int i;
198786a2265eSRasesh Mody 
198886a2265eSRasesh Mody 	OSAL_MEMSET(&filter, 0, sizeof(filter));
198986a2265eSRasesh Mody 	filter.is_rx_filter = 1;
199086a2265eSRasesh Mody 	filter.is_tx_filter = 1;
199186a2265eSRasesh Mody 	filter.vport_to_add_to = p_vf->vport_id;
199286a2265eSRasesh Mody 	filter.opcode = ECORE_FILTER_ADD;
199386a2265eSRasesh Mody 
199486a2265eSRasesh Mody 	/* Reconfigure vlans */
199586a2265eSRasesh Mody 	for (i = 0; i < ECORE_ETH_VF_NUM_VLAN_FILTERS + 1; i++) {
199622d07d93SRasesh Mody 		if (!p_vf->shadow_config.vlans[i].used)
199722d07d93SRasesh Mody 			continue;
199822d07d93SRasesh Mody 
199986a2265eSRasesh Mody 		filter.type = ECORE_FILTER_VLAN;
200086a2265eSRasesh Mody 		filter.vlan = p_vf->shadow_config.vlans[i].vid;
200186a2265eSRasesh Mody 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
200222d07d93SRasesh Mody 			   "Reconfiguring VLAN [0x%04x] for VF [%04x]\n",
200386a2265eSRasesh Mody 			   filter.vlan, p_vf->relative_vf_id);
2004ababb520SRasesh Mody 		rc = ecore_sp_eth_filter_ucast(p_hwfn, p_vf->opaque_fid,
2005ababb520SRasesh Mody 					       &filter, ECORE_SPQ_MODE_CB,
200686a2265eSRasesh Mody 					       OSAL_NULL);
200786a2265eSRasesh Mody 		if (rc) {
200886a2265eSRasesh Mody 			DP_NOTICE(p_hwfn, true,
200986a2265eSRasesh Mody 				  "Failed to configure VLAN [%04x]"
201086a2265eSRasesh Mody 				  " to VF [%04x]\n",
201186a2265eSRasesh Mody 				  filter.vlan, p_vf->relative_vf_id);
201286a2265eSRasesh Mody 			break;
201386a2265eSRasesh Mody 		}
201486a2265eSRasesh Mody 	}
201586a2265eSRasesh Mody 
201686a2265eSRasesh Mody 	return rc;
201786a2265eSRasesh Mody }
201886a2265eSRasesh Mody 
201986a2265eSRasesh Mody static enum _ecore_status_t
ecore_iov_reconfigure_unicast_shadow(struct ecore_hwfn * p_hwfn,struct ecore_vf_info * p_vf,u64 events)202086a2265eSRasesh Mody ecore_iov_reconfigure_unicast_shadow(struct ecore_hwfn *p_hwfn,
202186a2265eSRasesh Mody 				     struct ecore_vf_info *p_vf, u64 events)
202286a2265eSRasesh Mody {
202386a2265eSRasesh Mody 	enum _ecore_status_t rc = ECORE_SUCCESS;
202486a2265eSRasesh Mody 
202586a2265eSRasesh Mody 	/*TODO - what about MACs? */
202686a2265eSRasesh Mody 
202786a2265eSRasesh Mody 	if ((events & (1 << VLAN_ADDR_FORCED)) &&
202886a2265eSRasesh Mody 	    !(p_vf->configured_features & (1 << VLAN_ADDR_FORCED)))
202986a2265eSRasesh Mody 		rc = ecore_iov_reconfigure_unicast_vlan(p_hwfn, p_vf);
203086a2265eSRasesh Mody 
203186a2265eSRasesh Mody 	return rc;
203286a2265eSRasesh Mody }
203386a2265eSRasesh Mody 
203493fce904SRasesh Mody static  enum _ecore_status_t
ecore_iov_configure_vport_forced(struct ecore_hwfn * p_hwfn,struct ecore_vf_info * p_vf,u64 events)203593fce904SRasesh Mody ecore_iov_configure_vport_forced(struct ecore_hwfn *p_hwfn,
203686a2265eSRasesh Mody 				 struct ecore_vf_info *p_vf,
203786a2265eSRasesh Mody 				 u64 events)
203886a2265eSRasesh Mody {
203986a2265eSRasesh Mody 	enum _ecore_status_t rc = ECORE_SUCCESS;
204086a2265eSRasesh Mody 	struct ecore_filter_ucast filter;
204186a2265eSRasesh Mody 
204286a2265eSRasesh Mody 	if (!p_vf->vport_instance)
204386a2265eSRasesh Mody 		return ECORE_INVAL;
204486a2265eSRasesh Mody 
2045d5050d4dSRasesh Mody 	if ((events & (1 << MAC_ADDR_FORCED)) ||
20462cf7a0faSShahed Shaikh 	    p_hwfn->pf_params.eth_pf_params.allow_vf_mac_change ||
20472cf7a0faSShahed Shaikh 	    p_vf->p_vf_info.is_trusted_configured) {
204886a2265eSRasesh Mody 		/* Since there's no way [currently] of removing the MAC,
204986a2265eSRasesh Mody 		 * we can always assume this means we need to force it.
205086a2265eSRasesh Mody 		 */
205186a2265eSRasesh Mody 		OSAL_MEMSET(&filter, 0, sizeof(filter));
205286a2265eSRasesh Mody 		filter.type = ECORE_FILTER_MAC;
205386a2265eSRasesh Mody 		filter.opcode = ECORE_FILTER_REPLACE;
205486a2265eSRasesh Mody 		filter.is_rx_filter = 1;
205586a2265eSRasesh Mody 		filter.is_tx_filter = 1;
205686a2265eSRasesh Mody 		filter.vport_to_add_to = p_vf->vport_id;
205786a2265eSRasesh Mody 		OSAL_MEMCPY(filter.mac, p_vf->bulletin.p_virt->mac, ETH_ALEN);
205886a2265eSRasesh Mody 
205986a2265eSRasesh Mody 		rc = ecore_sp_eth_filter_ucast(p_hwfn, p_vf->opaque_fid,
206086a2265eSRasesh Mody 					       &filter,
206186a2265eSRasesh Mody 					       ECORE_SPQ_MODE_CB, OSAL_NULL);
206286a2265eSRasesh Mody 		if (rc) {
206386a2265eSRasesh Mody 			DP_NOTICE(p_hwfn, true,
206486a2265eSRasesh Mody 				  "PF failed to configure MAC for VF\n");
206586a2265eSRasesh Mody 			return rc;
206686a2265eSRasesh Mody 		}
206786a2265eSRasesh Mody 
20682cf7a0faSShahed Shaikh 		if (p_hwfn->pf_params.eth_pf_params.allow_vf_mac_change ||
20692cf7a0faSShahed Shaikh 		    p_vf->p_vf_info.is_trusted_configured)
2070d5050d4dSRasesh Mody 			p_vf->configured_features |=
2071d5050d4dSRasesh Mody 				1 << VFPF_BULLETIN_MAC_ADDR;
2072d5050d4dSRasesh Mody 		else
207386a2265eSRasesh Mody 			p_vf->configured_features |= 1 << MAC_ADDR_FORCED;
207486a2265eSRasesh Mody 	}
207586a2265eSRasesh Mody 
207686a2265eSRasesh Mody 	if (events & (1 << VLAN_ADDR_FORCED)) {
207786a2265eSRasesh Mody 		struct ecore_sp_vport_update_params vport_update;
207886a2265eSRasesh Mody 		u8 removal;
207986a2265eSRasesh Mody 		int i;
208086a2265eSRasesh Mody 
208186a2265eSRasesh Mody 		OSAL_MEMSET(&filter, 0, sizeof(filter));
208286a2265eSRasesh Mody 		filter.type = ECORE_FILTER_VLAN;
208386a2265eSRasesh Mody 		filter.is_rx_filter = 1;
208486a2265eSRasesh Mody 		filter.is_tx_filter = 1;
208586a2265eSRasesh Mody 		filter.vport_to_add_to = p_vf->vport_id;
208686a2265eSRasesh Mody 		filter.vlan = p_vf->bulletin.p_virt->pvid;
208786a2265eSRasesh Mody 		filter.opcode = filter.vlan ? ECORE_FILTER_REPLACE :
208886a2265eSRasesh Mody 		    ECORE_FILTER_FLUSH;
208986a2265eSRasesh Mody 
209086a2265eSRasesh Mody 		/* Send the ramrod */
209186a2265eSRasesh Mody 		rc = ecore_sp_eth_filter_ucast(p_hwfn, p_vf->opaque_fid,
209286a2265eSRasesh Mody 					       &filter,
209386a2265eSRasesh Mody 					       ECORE_SPQ_MODE_CB, OSAL_NULL);
209486a2265eSRasesh Mody 		if (rc) {
209586a2265eSRasesh Mody 			DP_NOTICE(p_hwfn, true,
209686a2265eSRasesh Mody 				  "PF failed to configure VLAN for VF\n");
209786a2265eSRasesh Mody 			return rc;
209886a2265eSRasesh Mody 		}
209986a2265eSRasesh Mody 
210086a2265eSRasesh Mody 		/* Update the default-vlan & silent vlan stripping */
210186a2265eSRasesh Mody 		OSAL_MEMSET(&vport_update, 0, sizeof(vport_update));
210286a2265eSRasesh Mody 		vport_update.opaque_fid = p_vf->opaque_fid;
210386a2265eSRasesh Mody 		vport_update.vport_id = p_vf->vport_id;
210486a2265eSRasesh Mody 		vport_update.update_default_vlan_enable_flg = 1;
210586a2265eSRasesh Mody 		vport_update.default_vlan_enable_flg = filter.vlan ? 1 : 0;
210686a2265eSRasesh Mody 		vport_update.update_default_vlan_flg = 1;
210786a2265eSRasesh Mody 		vport_update.default_vlan = filter.vlan;
210886a2265eSRasesh Mody 
210986a2265eSRasesh Mody 		vport_update.update_inner_vlan_removal_flg = 1;
211086a2265eSRasesh Mody 		removal = filter.vlan ?
211186a2265eSRasesh Mody 		    1 : p_vf->shadow_config.inner_vlan_removal;
211286a2265eSRasesh Mody 		vport_update.inner_vlan_removal_flg = removal;
211386a2265eSRasesh Mody 		vport_update.silent_vlan_removal_flg = filter.vlan ? 1 : 0;
211486a2265eSRasesh Mody 		rc = ecore_sp_vport_update(p_hwfn, &vport_update,
211586a2265eSRasesh Mody 					   ECORE_SPQ_MODE_EBLOCK, OSAL_NULL);
211686a2265eSRasesh Mody 		if (rc) {
211786a2265eSRasesh Mody 			DP_NOTICE(p_hwfn, true,
211886a2265eSRasesh Mody 				  "PF failed to configure VF vport for vlan\n");
211986a2265eSRasesh Mody 			return rc;
212086a2265eSRasesh Mody 		}
212186a2265eSRasesh Mody 
212286a2265eSRasesh Mody 		/* Update all the Rx queues */
212386a2265eSRasesh Mody 		for (i = 0; i < ECORE_MAX_VF_CHAINS_PER_PF; i++) {
2124eb8e81adSRasesh Mody 			struct ecore_vf_queue *p_queue = &p_vf->vf_queues[i];
2125eb8e81adSRasesh Mody 			struct ecore_queue_cid *p_cid = OSAL_NULL;
212686a2265eSRasesh Mody 
2127eb8e81adSRasesh Mody 			/* There can be at most 1 Rx queue on qzone. Find it */
212830ecf673SRasesh Mody 			p_cid = ecore_iov_get_vf_rx_queue_cid(p_queue);
2129a55e422eSRasesh Mody 			if (p_cid == OSAL_NULL)
213086a2265eSRasesh Mody 				continue;
213186a2265eSRasesh Mody 
2132a55e422eSRasesh Mody 			rc = ecore_sp_eth_rx_queues_update(p_hwfn,
2133a55e422eSRasesh Mody 							   (void **)&p_cid,
213486a2265eSRasesh Mody 						   1, 0, 1,
213586a2265eSRasesh Mody 						   ECORE_SPQ_MODE_EBLOCK,
213686a2265eSRasesh Mody 						   OSAL_NULL);
213786a2265eSRasesh Mody 			if (rc) {
213886a2265eSRasesh Mody 				DP_NOTICE(p_hwfn, true,
213986a2265eSRasesh Mody 					  "Failed to send Rx update"
214022d07d93SRasesh Mody 					  " fo queue[0x%04x]\n",
2141a55e422eSRasesh Mody 					  p_cid->rel.queue_id);
214286a2265eSRasesh Mody 				return rc;
214386a2265eSRasesh Mody 			}
214486a2265eSRasesh Mody 		}
214586a2265eSRasesh Mody 
214686a2265eSRasesh Mody 		if (filter.vlan)
214786a2265eSRasesh Mody 			p_vf->configured_features |= 1 << VLAN_ADDR_FORCED;
214886a2265eSRasesh Mody 		else
214986a2265eSRasesh Mody 			p_vf->configured_features &= ~(1 << VLAN_ADDR_FORCED);
215086a2265eSRasesh Mody 	}
215186a2265eSRasesh Mody 
215286a2265eSRasesh Mody 	/* If forced features are terminated, we need to configure the shadow
215386a2265eSRasesh Mody 	 * configuration back again.
215486a2265eSRasesh Mody 	 */
215586a2265eSRasesh Mody 	if (events)
215686a2265eSRasesh Mody 		ecore_iov_reconfigure_unicast_shadow(p_hwfn, p_vf, events);
215786a2265eSRasesh Mody 
215886a2265eSRasesh Mody 	return rc;
215986a2265eSRasesh Mody }
216086a2265eSRasesh Mody 
ecore_iov_vf_mbx_start_vport(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * vf)216186a2265eSRasesh Mody static void ecore_iov_vf_mbx_start_vport(struct ecore_hwfn *p_hwfn,
216286a2265eSRasesh Mody 					 struct ecore_ptt *p_ptt,
216386a2265eSRasesh Mody 					 struct ecore_vf_info *vf)
216486a2265eSRasesh Mody {
216522d07d93SRasesh Mody 	struct ecore_iov_vf_mbx *mbx = &vf->vf_mbx;
21669ed26bc7SRasesh Mody 	struct ecore_sp_vport_start_params params;
216722d07d93SRasesh Mody 	struct vfpf_vport_start_tlv *start;
216886a2265eSRasesh Mody 	u8 status = PFVF_STATUS_SUCCESS;
216986a2265eSRasesh Mody 	struct ecore_vf_info *vf_info;
217086a2265eSRasesh Mody 	u64 *p_bitmap;
217186a2265eSRasesh Mody 	int sb_id;
217222d07d93SRasesh Mody 	enum _ecore_status_t rc;
217386a2265eSRasesh Mody 
217486a2265eSRasesh Mody 	vf_info = ecore_iov_get_vf_info(p_hwfn, (u16)vf->relative_vf_id, true);
217586a2265eSRasesh Mody 	if (!vf_info) {
217686a2265eSRasesh Mody 		DP_NOTICE(p_hwfn->p_dev, true,
217786a2265eSRasesh Mody 			  "Failed to get VF info, invalid vfid [%d]\n",
217886a2265eSRasesh Mody 			  vf->relative_vf_id);
217986a2265eSRasesh Mody 		return;
218086a2265eSRasesh Mody 	}
218186a2265eSRasesh Mody 
218286a2265eSRasesh Mody 	vf->state = VF_ENABLED;
218322d07d93SRasesh Mody 	start = &mbx->req_virt->start_vport;
218486a2265eSRasesh Mody 
21856b8962e0SRasesh Mody 	ecore_iov_enable_vf_traffic(p_hwfn, p_ptt, vf);
21866b8962e0SRasesh Mody 
218786a2265eSRasesh Mody 	/* Initialize Status block in CAU */
218886a2265eSRasesh Mody 	for (sb_id = 0; sb_id < vf->num_sbs; sb_id++) {
218986a2265eSRasesh Mody 		if (!start->sb_addr[sb_id]) {
219086a2265eSRasesh Mody 			DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
219186a2265eSRasesh Mody 				   "VF[%d] did not fill the address of SB %d\n",
219286a2265eSRasesh Mody 				   vf->relative_vf_id, sb_id);
219386a2265eSRasesh Mody 			break;
219486a2265eSRasesh Mody 		}
219586a2265eSRasesh Mody 
219686a2265eSRasesh Mody 		ecore_int_cau_conf_sb(p_hwfn, p_ptt,
219786a2265eSRasesh Mody 				      start->sb_addr[sb_id],
219886a2265eSRasesh Mody 				      vf->igu_sbs[sb_id],
219922d07d93SRasesh Mody 				      vf->abs_vf_id, 1);
220086a2265eSRasesh Mody 	}
220186a2265eSRasesh Mody 
220286a2265eSRasesh Mody 	vf->mtu = start->mtu;
220386a2265eSRasesh Mody 	vf->shadow_config.inner_vlan_removal = start->inner_vlan_removal;
220486a2265eSRasesh Mody 
220586a2265eSRasesh Mody 	/* Take into consideration configuration forced by hypervisor;
220686a2265eSRasesh Mody 	 * If none is configured, use the supplied VF values [for old
220786a2265eSRasesh Mody 	 * vfs that would still be fine, since they passed '0' as padding].
220886a2265eSRasesh Mody 	 */
220986a2265eSRasesh Mody 	p_bitmap = &vf_info->bulletin.p_virt->valid_bitmap;
221086a2265eSRasesh Mody 	if (!(*p_bitmap & (1 << VFPF_BULLETIN_UNTAGGED_DEFAULT_FORCED))) {
221186a2265eSRasesh Mody 		u8 vf_req = start->only_untagged;
221286a2265eSRasesh Mody 
221386a2265eSRasesh Mody 		vf_info->bulletin.p_virt->default_only_untagged = vf_req;
221486a2265eSRasesh Mody 		*p_bitmap |= 1 << VFPF_BULLETIN_UNTAGGED_DEFAULT;
221586a2265eSRasesh Mody 	}
221686a2265eSRasesh Mody 
22179ed26bc7SRasesh Mody 	OSAL_MEMSET(&params, 0, sizeof(struct ecore_sp_vport_start_params));
221886a2265eSRasesh Mody 	params.tpa_mode = start->tpa_mode;
221986a2265eSRasesh Mody 	params.remove_inner_vlan = start->inner_vlan_removal;
222086a2265eSRasesh Mody 	params.tx_switching = true;
222186a2265eSRasesh Mody 
222286a2265eSRasesh Mody #ifndef ASIC_ONLY
222386a2265eSRasesh Mody 	if (CHIP_REV_IS_FPGA(p_hwfn->p_dev)) {
222486a2265eSRasesh Mody 		DP_NOTICE(p_hwfn, false,
222522d07d93SRasesh Mody 			  "FPGA: Don't config VF for Tx-switching [no pVFC]\n");
222686a2265eSRasesh Mody 		params.tx_switching = false;
222786a2265eSRasesh Mody 	}
222886a2265eSRasesh Mody #endif
222986a2265eSRasesh Mody 
223086a2265eSRasesh Mody 	params.only_untagged = vf_info->bulletin.p_virt->default_only_untagged;
223186a2265eSRasesh Mody 	params.drop_ttl0 = false;
223286a2265eSRasesh Mody 	params.concrete_fid = vf->concrete_fid;
223386a2265eSRasesh Mody 	params.opaque_fid = vf->opaque_fid;
223486a2265eSRasesh Mody 	params.vport_id = vf->vport_id;
223586a2265eSRasesh Mody 	params.max_buffers_per_cqe = start->max_buffers_per_cqe;
223686a2265eSRasesh Mody 	params.mtu = vf->mtu;
2237ab67e837SRasesh Mody 
2238ab67e837SRasesh Mody 	/* Non trusted VFs should enable control frame filtering */
2239ab67e837SRasesh Mody 	params.check_mac = !vf->p_vf_info.is_trusted_configured;
224086a2265eSRasesh Mody 
224186a2265eSRasesh Mody 	rc = ecore_sp_eth_vport_start(p_hwfn, &params);
224286a2265eSRasesh Mody 	if (rc != ECORE_SUCCESS) {
224386a2265eSRasesh Mody 		DP_ERR(p_hwfn,
224486a2265eSRasesh Mody 		       "ecore_iov_vf_mbx_start_vport returned error %d\n", rc);
224586a2265eSRasesh Mody 		status = PFVF_STATUS_FAILURE;
224686a2265eSRasesh Mody 	} else {
224786a2265eSRasesh Mody 		vf->vport_instance++;
224886a2265eSRasesh Mody 
224986a2265eSRasesh Mody 		/* Force configuration if needed on the newly opened vport */
225086a2265eSRasesh Mody 		ecore_iov_configure_vport_forced(p_hwfn, vf, *p_bitmap);
225186a2265eSRasesh Mody 		OSAL_IOV_POST_START_VPORT(p_hwfn, vf->relative_vf_id,
225286a2265eSRasesh Mody 					  vf->vport_id, vf->opaque_fid);
225386a2265eSRasesh Mody 		__ecore_iov_spoofchk_set(p_hwfn, vf, vf->req_spoofchk_val);
225486a2265eSRasesh Mody 	}
225586a2265eSRasesh Mody 
225686a2265eSRasesh Mody 	ecore_iov_prepare_resp(p_hwfn, p_ptt, vf, CHANNEL_TLV_VPORT_START,
225786a2265eSRasesh Mody 			       sizeof(struct pfvf_def_resp_tlv), status);
225886a2265eSRasesh Mody }
225986a2265eSRasesh Mody 
ecore_iov_vf_mbx_stop_vport(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * vf)226086a2265eSRasesh Mody static void ecore_iov_vf_mbx_stop_vport(struct ecore_hwfn *p_hwfn,
226186a2265eSRasesh Mody 					struct ecore_ptt *p_ptt,
226286a2265eSRasesh Mody 					struct ecore_vf_info *vf)
226386a2265eSRasesh Mody {
226486a2265eSRasesh Mody 	u8 status = PFVF_STATUS_SUCCESS;
226586a2265eSRasesh Mody 	enum _ecore_status_t rc;
226686a2265eSRasesh Mody 
226770f1a93dSRasesh Mody 	OSAL_IOV_VF_VPORT_STOP(p_hwfn, vf);
226886a2265eSRasesh Mody 	vf->vport_instance--;
226986a2265eSRasesh Mody 	vf->spoof_chk = false;
227086a2265eSRasesh Mody 
227130ecf673SRasesh Mody 	if ((ecore_iov_validate_active_rxq(vf)) ||
227230ecf673SRasesh Mody 	    (ecore_iov_validate_active_txq(vf))) {
2273bd96f72fSRasesh Mody 		vf->b_malicious = true;
2274bd96f72fSRasesh Mody 		DP_NOTICE(p_hwfn, false,
2275bd96f72fSRasesh Mody 			  "VF [%02x] - considered malicious;"
2276bd96f72fSRasesh Mody 			  " Unable to stop RX/TX queuess\n",
2277bd96f72fSRasesh Mody 			  vf->abs_vf_id);
2278c1454460SRasesh Mody 		status = PFVF_STATUS_MALICIOUS;
2279c1454460SRasesh Mody 		goto out;
2280bd96f72fSRasesh Mody 	}
2281bd96f72fSRasesh Mody 
228286a2265eSRasesh Mody 	rc = ecore_sp_vport_stop(p_hwfn, vf->opaque_fid, vf->vport_id);
228386a2265eSRasesh Mody 	if (rc != ECORE_SUCCESS) {
228486a2265eSRasesh Mody 		DP_ERR(p_hwfn,
228586a2265eSRasesh Mody 		       "ecore_iov_vf_mbx_stop_vport returned error %d\n", rc);
228686a2265eSRasesh Mody 		status = PFVF_STATUS_FAILURE;
228786a2265eSRasesh Mody 	}
228886a2265eSRasesh Mody 
228986a2265eSRasesh Mody 	/* Forget the configuration on the vport */
229086a2265eSRasesh Mody 	vf->configured_features = 0;
229186a2265eSRasesh Mody 	OSAL_MEMSET(&vf->shadow_config, 0, sizeof(vf->shadow_config));
229286a2265eSRasesh Mody 
2293c1454460SRasesh Mody out:
229486a2265eSRasesh Mody 	ecore_iov_prepare_resp(p_hwfn, p_ptt, vf, CHANNEL_TLV_VPORT_TEARDOWN,
229586a2265eSRasesh Mody 			       sizeof(struct pfvf_def_resp_tlv), status);
229686a2265eSRasesh Mody }
229786a2265eSRasesh Mody 
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)229822d07d93SRasesh Mody static void ecore_iov_vf_mbx_start_rxq_resp(struct ecore_hwfn *p_hwfn,
229922d07d93SRasesh Mody 					    struct ecore_ptt *p_ptt,
230022d07d93SRasesh Mody 					    struct ecore_vf_info *vf,
230122d07d93SRasesh Mody 					    u8 status, bool b_legacy)
230222d07d93SRasesh Mody {
230322d07d93SRasesh Mody 	struct ecore_iov_vf_mbx *mbx = &vf->vf_mbx;
230422d07d93SRasesh Mody 	struct pfvf_start_queue_resp_tlv *p_tlv;
230522d07d93SRasesh Mody 	struct vfpf_start_rxq_tlv *req;
230622d07d93SRasesh Mody 	u16 length;
230722d07d93SRasesh Mody 
230822d07d93SRasesh Mody 	mbx->offset = (u8 *)mbx->reply_virt;
230922d07d93SRasesh Mody 
231022d07d93SRasesh Mody 	/* Taking a bigger struct instead of adding a TLV to list was a
231122d07d93SRasesh Mody 	 * mistake, but one which we're now stuck with, as some older
231222d07d93SRasesh Mody 	 * clients assume the size of the previous response.
231322d07d93SRasesh Mody 	 */
231422d07d93SRasesh Mody 	if (!b_legacy)
231522d07d93SRasesh Mody 		length = sizeof(*p_tlv);
231622d07d93SRasesh Mody 	else
231722d07d93SRasesh Mody 		length = sizeof(struct pfvf_def_resp_tlv);
231822d07d93SRasesh Mody 
231930ecf673SRasesh Mody 	p_tlv = ecore_add_tlv(&mbx->offset, CHANNEL_TLV_START_RXQ, length);
232030ecf673SRasesh Mody 	ecore_add_tlv(&mbx->offset, CHANNEL_TLV_LIST_END,
232122d07d93SRasesh Mody 		      sizeof(struct channel_list_end_tlv));
232222d07d93SRasesh Mody 
23233b307c55SRasesh Mody 	/* Update the TLV with the response.
23243b307c55SRasesh Mody 	 * The VF Rx producers are located in the vf zone.
23253b307c55SRasesh Mody 	 */
232622d07d93SRasesh Mody 	if ((status == PFVF_STATUS_SUCCESS) && !b_legacy) {
232722d07d93SRasesh Mody 		req = &mbx->req_virt->start_rxq;
23283b307c55SRasesh Mody 
23293b307c55SRasesh Mody 		p_tlv->offset =
23303b307c55SRasesh Mody 			PXP_VF_BAR0_START_MSDM_ZONE_B +
233122d07d93SRasesh Mody 				OFFSETOF(struct mstorm_vf_zone,
233222d07d93SRasesh Mody 					 non_trigger.eth_rx_queue_producers) +
233322d07d93SRasesh Mody 				sizeof(struct eth_rx_prod_data) * req->rx_qid;
233422d07d93SRasesh Mody 	}
233522d07d93SRasesh Mody 
233622d07d93SRasesh Mody 	ecore_iov_send_response(p_hwfn, p_ptt, vf, length, status);
233722d07d93SRasesh Mody }
233822d07d93SRasesh Mody 
ecore_iov_vf_mbx_qid(struct ecore_hwfn * p_hwfn,struct ecore_vf_info * p_vf,bool b_is_tx)2339a90c566fSRasesh Mody static u8 ecore_iov_vf_mbx_qid(struct ecore_hwfn *p_hwfn,
2340a90c566fSRasesh Mody 			       struct ecore_vf_info *p_vf, bool b_is_tx)
2341a90c566fSRasesh Mody {
2342a90c566fSRasesh Mody 	struct ecore_iov_vf_mbx *p_mbx = &p_vf->vf_mbx;
2343a90c566fSRasesh Mody 	struct vfpf_qid_tlv *p_qid_tlv;
2344a90c566fSRasesh Mody 
2345a90c566fSRasesh Mody 	/* Search for the qid if the VF published if its going to provide it */
2346a90c566fSRasesh Mody 	if (!(p_vf->acquire.vfdev_info.capabilities &
2347a90c566fSRasesh Mody 	      VFPF_ACQUIRE_CAP_QUEUE_QIDS)) {
2348a90c566fSRasesh Mody 		if (b_is_tx)
2349a90c566fSRasesh Mody 			return ECORE_IOV_LEGACY_QID_TX;
2350a90c566fSRasesh Mody 		else
2351a90c566fSRasesh Mody 			return ECORE_IOV_LEGACY_QID_RX;
2352a90c566fSRasesh Mody 	}
2353a90c566fSRasesh Mody 
2354a90c566fSRasesh Mody 	p_qid_tlv = (struct vfpf_qid_tlv *)
2355a90c566fSRasesh Mody 		    ecore_iov_search_list_tlvs(p_hwfn, p_mbx->req_virt,
2356a90c566fSRasesh Mody 					       CHANNEL_TLV_QID);
2357a90c566fSRasesh Mody 	if (p_qid_tlv == OSAL_NULL) {
2358a90c566fSRasesh Mody 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
2359a90c566fSRasesh Mody 			   "VF[%2x]: Failed to provide qid\n",
2360a90c566fSRasesh Mody 			   p_vf->relative_vf_id);
2361a90c566fSRasesh Mody 
2362a90c566fSRasesh Mody 		return ECORE_IOV_QID_INVALID;
2363a90c566fSRasesh Mody 	}
2364a90c566fSRasesh Mody 
2365a90c566fSRasesh Mody 	if (p_qid_tlv->qid >= MAX_QUEUES_PER_QZONE) {
2366a90c566fSRasesh Mody 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
2367a90c566fSRasesh Mody 			   "VF[%02x]: Provided qid out-of-bounds %02x\n",
2368a90c566fSRasesh Mody 			   p_vf->relative_vf_id, p_qid_tlv->qid);
2369a90c566fSRasesh Mody 		return ECORE_IOV_QID_INVALID;
2370a90c566fSRasesh Mody 	}
2371a90c566fSRasesh Mody 
2372a90c566fSRasesh Mody 	return p_qid_tlv->qid;
2373a90c566fSRasesh Mody }
2374a90c566fSRasesh Mody 
ecore_iov_vf_mbx_start_rxq(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * vf)237586a2265eSRasesh Mody static void ecore_iov_vf_mbx_start_rxq(struct ecore_hwfn *p_hwfn,
237686a2265eSRasesh Mody 				       struct ecore_ptt *p_ptt,
237786a2265eSRasesh Mody 				       struct ecore_vf_info *vf)
237886a2265eSRasesh Mody {
2379379cbb2cSRasesh Mody 	struct ecore_queue_start_common_params params;
2380eb8e81adSRasesh Mody 	struct ecore_queue_cid_vf_params vf_params;
238186a2265eSRasesh Mody 	struct ecore_iov_vf_mbx *mbx = &vf->vf_mbx;
238222d07d93SRasesh Mody 	u8 status = PFVF_STATUS_NO_RESOURCE;
2383a90c566fSRasesh Mody 	u8 qid_usage_idx, vf_legacy = 0;
2384eb8e81adSRasesh Mody 	struct ecore_vf_queue *p_queue;
238522d07d93SRasesh Mody 	struct vfpf_start_rxq_tlv *req;
2386eb8e81adSRasesh Mody 	struct ecore_queue_cid *p_cid;
23876e4fcea9SRasesh Mody 	struct ecore_sb_info sb_dummy;
238886a2265eSRasesh Mody 	enum _ecore_status_t rc;
238986a2265eSRasesh Mody 
239022d07d93SRasesh Mody 	req = &mbx->req_virt->start_rxq;
2391917ce8bdSRasesh Mody 
2392eb8e81adSRasesh Mody 	if (!ecore_iov_validate_rxq(p_hwfn, vf, req->rx_qid,
2393eb8e81adSRasesh Mody 				    ECORE_IOV_VALIDATE_Q_DISABLE) ||
2394917ce8bdSRasesh Mody 	    !ecore_iov_validate_sb(p_hwfn, vf, req->hw_sb))
2395917ce8bdSRasesh Mody 		goto out;
2396917ce8bdSRasesh Mody 
2397a90c566fSRasesh Mody 	qid_usage_idx = ecore_iov_vf_mbx_qid(p_hwfn, vf, false);
2398a90c566fSRasesh Mody 	if (qid_usage_idx == ECORE_IOV_QID_INVALID)
2399a90c566fSRasesh Mody 		goto out;
2400a90c566fSRasesh Mody 
2401a90c566fSRasesh Mody 	p_queue = &vf->vf_queues[req->rx_qid];
2402a90c566fSRasesh Mody 	if (p_queue->cids[qid_usage_idx].p_cid)
2403a90c566fSRasesh Mody 		goto out;
2404a90c566fSRasesh Mody 
240530ecf673SRasesh Mody 	vf_legacy = ecore_vf_calculate_legacy(vf);
2406eb8e81adSRasesh Mody 
2407a55e422eSRasesh Mody 	/* Acquire a new queue-cid */
2408379cbb2cSRasesh Mody 	OSAL_MEMSET(&params, 0, sizeof(params));
2409a55e422eSRasesh Mody 	params.queue_id = (u8)p_queue->fw_rx_qid;
2410379cbb2cSRasesh Mody 	params.vport_id = vf->vport_id;
24112d5036abSRasesh Mody 	params.stats_id = vf->abs_vf_id + 0x10;
24126e4fcea9SRasesh Mody 
24136e4fcea9SRasesh Mody 	/* Since IGU index is passed via sb_info, construct a dummy one */
24146e4fcea9SRasesh Mody 	OSAL_MEM_ZERO(&sb_dummy, sizeof(sb_dummy));
24156e4fcea9SRasesh Mody 	sb_dummy.igu_sb_id = req->hw_sb;
24166e4fcea9SRasesh Mody 	params.p_sb = &sb_dummy;
2417379cbb2cSRasesh Mody 	params.sb_idx = req->sb_index;
241822d07d93SRasesh Mody 
2419eb8e81adSRasesh Mody 	OSAL_MEM_ZERO(&vf_params, sizeof(vf_params));
2420eb8e81adSRasesh Mody 	vf_params.vfid = vf->relative_vf_id;
2421eb8e81adSRasesh Mody 	vf_params.vf_qid = (u8)req->rx_qid;
2422a90c566fSRasesh Mody 	vf_params.vf_legacy = vf_legacy;
2423eb8e81adSRasesh Mody 	vf_params.qid_usage_idx = qid_usage_idx;
2424eb8e81adSRasesh Mody 
2425eb8e81adSRasesh Mody 	p_cid = ecore_eth_queue_to_cid(p_hwfn, vf->opaque_fid,
2426823a84aaSRasesh Mody 				       &params, true, &vf_params);
2427eb8e81adSRasesh Mody 	if (p_cid == OSAL_NULL)
2428a55e422eSRasesh Mody 		goto out;
2429a55e422eSRasesh Mody 
24303b307c55SRasesh Mody 	/* The VF Rx producers are located in the vf zone.
24313b307c55SRasesh Mody 	 * Legacy VFs have their producers in the queue zone, but they
24323b307c55SRasesh Mody 	 * calculate the location by their own and clean them prior to this.
243322d07d93SRasesh Mody 	 */
2434a90c566fSRasesh Mody 	if (!(vf_legacy & ECORE_QCID_LEGACY_VF_RX_PROD))
243522d07d93SRasesh Mody 		REG_WR(p_hwfn,
243622d07d93SRasesh Mody 		       GTT_BAR0_MAP_REG_MSDM_RAM +
24373b307c55SRasesh Mody 		       MSTORM_ETH_VF_PRODS_OFFSET(vf->abs_vf_id,
24383b307c55SRasesh Mody 						  req->rx_qid),
243922d07d93SRasesh Mody 		       0);
244022d07d93SRasesh Mody 
2441eb8e81adSRasesh Mody 	rc = ecore_eth_rxq_start_ramrod(p_hwfn, p_cid,
244286a2265eSRasesh Mody 					req->bd_max_bytes,
244386a2265eSRasesh Mody 					req->rxq_addr,
244486a2265eSRasesh Mody 					req->cqe_pbl_addr,
2445a55e422eSRasesh Mody 					req->cqe_pbl_size);
2446a55e422eSRasesh Mody 	if (rc != ECORE_SUCCESS) {
244786a2265eSRasesh Mody 		status = PFVF_STATUS_FAILURE;
2448eb8e81adSRasesh Mody 		ecore_eth_queue_cid_release(p_hwfn, p_cid);
244986a2265eSRasesh Mody 	} else {
2450eb8e81adSRasesh Mody 		p_queue->cids[qid_usage_idx].p_cid = p_cid;
2451eb8e81adSRasesh Mody 		p_queue->cids[qid_usage_idx].b_is_tx = false;
245222d07d93SRasesh Mody 		status = PFVF_STATUS_SUCCESS;
245386a2265eSRasesh Mody 		vf->num_active_rxqs++;
245486a2265eSRasesh Mody 	}
245586a2265eSRasesh Mody 
245622d07d93SRasesh Mody out:
2457a55e422eSRasesh Mody 	ecore_iov_vf_mbx_start_rxq_resp(p_hwfn, p_ptt, vf, status,
2458a90c566fSRasesh Mody 					!!(vf_legacy &
2459a90c566fSRasesh Mody 					   ECORE_QCID_LEGACY_VF_RX_PROD));
246022d07d93SRasesh Mody }
246122d07d93SRasesh Mody 
24620b090fd3SRasesh Mody 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)24630b090fd3SRasesh Mody ecore_iov_pf_update_tun_response(struct pfvf_update_tunn_param_tlv *p_resp,
24640b090fd3SRasesh Mody 				 struct ecore_tunnel_info *p_tun,
24650b090fd3SRasesh Mody 				 u16 tunn_feature_mask)
24660b090fd3SRasesh Mody {
24670b090fd3SRasesh Mody 	p_resp->tunn_feature_mask = tunn_feature_mask;
24680b090fd3SRasesh Mody 	p_resp->vxlan_mode = p_tun->vxlan.b_mode_enabled;
24690b090fd3SRasesh Mody 	p_resp->l2geneve_mode = p_tun->l2_geneve.b_mode_enabled;
24700b090fd3SRasesh Mody 	p_resp->ipgeneve_mode = p_tun->ip_geneve.b_mode_enabled;
24710b090fd3SRasesh Mody 	p_resp->l2gre_mode = p_tun->l2_gre.b_mode_enabled;
24720b090fd3SRasesh Mody 	p_resp->ipgre_mode = p_tun->l2_gre.b_mode_enabled;
24730b090fd3SRasesh Mody 	p_resp->vxlan_clss = p_tun->vxlan.tun_cls;
24740b090fd3SRasesh Mody 	p_resp->l2gre_clss = p_tun->l2_gre.tun_cls;
24750b090fd3SRasesh Mody 	p_resp->ipgre_clss = p_tun->ip_gre.tun_cls;
24760b090fd3SRasesh Mody 	p_resp->l2geneve_clss = p_tun->l2_geneve.tun_cls;
24770b090fd3SRasesh Mody 	p_resp->ipgeneve_clss = p_tun->ip_geneve.tun_cls;
24780b090fd3SRasesh Mody 	p_resp->geneve_udp_port = p_tun->geneve_port.port;
24790b090fd3SRasesh Mody 	p_resp->vxlan_udp_port = p_tun->vxlan_port.port;
24800b090fd3SRasesh Mody }
24810b090fd3SRasesh Mody 
24820b090fd3SRasesh Mody 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)24830b090fd3SRasesh Mody __ecore_iov_pf_update_tun_param(struct vfpf_update_tunn_param_tlv *p_req,
24840b090fd3SRasesh Mody 				struct ecore_tunn_update_type *p_tun,
24850b090fd3SRasesh Mody 				enum ecore_tunn_mode mask, u8 tun_cls)
24860b090fd3SRasesh Mody {
24870b090fd3SRasesh Mody 	if (p_req->tun_mode_update_mask & (1 << mask)) {
24880b090fd3SRasesh Mody 		p_tun->b_update_mode = true;
24890b090fd3SRasesh Mody 
24900b090fd3SRasesh Mody 		if (p_req->tunn_mode & (1 << mask))
24910b090fd3SRasesh Mody 			p_tun->b_mode_enabled = true;
24920b090fd3SRasesh Mody 	}
24930b090fd3SRasesh Mody 
24940b090fd3SRasesh Mody 	p_tun->tun_cls = tun_cls;
24950b090fd3SRasesh Mody }
24960b090fd3SRasesh Mody 
24970b090fd3SRasesh Mody 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)24980b090fd3SRasesh Mody ecore_iov_pf_update_tun_param(struct vfpf_update_tunn_param_tlv *p_req,
24990b090fd3SRasesh Mody 			      struct ecore_tunn_update_type *p_tun,
25000b090fd3SRasesh Mody 			      struct ecore_tunn_update_udp_port *p_port,
25010b090fd3SRasesh Mody 			      enum ecore_tunn_mode mask,
25020b090fd3SRasesh Mody 			      u8 tun_cls, u8 update_port, u16 port)
25030b090fd3SRasesh Mody {
25040b090fd3SRasesh Mody 	if (update_port) {
25050b090fd3SRasesh Mody 		p_port->b_update_port = true;
25060b090fd3SRasesh Mody 		p_port->port = port;
25070b090fd3SRasesh Mody 	}
25080b090fd3SRasesh Mody 
25090b090fd3SRasesh Mody 	__ecore_iov_pf_update_tun_param(p_req, p_tun, mask, tun_cls);
25100b090fd3SRasesh Mody }
25110b090fd3SRasesh Mody 
25120b090fd3SRasesh Mody static bool
ecore_iov_pf_validate_tunn_param(struct vfpf_update_tunn_param_tlv * p_req)25130b090fd3SRasesh Mody ecore_iov_pf_validate_tunn_param(struct vfpf_update_tunn_param_tlv *p_req)
25140b090fd3SRasesh Mody {
25150b090fd3SRasesh Mody 	bool b_update_requested = false;
25160b090fd3SRasesh Mody 
25170b090fd3SRasesh Mody 	if (p_req->tun_mode_update_mask || p_req->update_tun_cls ||
25180b090fd3SRasesh Mody 	    p_req->update_geneve_port || p_req->update_vxlan_port)
25190b090fd3SRasesh Mody 		b_update_requested = true;
25200b090fd3SRasesh Mody 
25210b090fd3SRasesh Mody 	return b_update_requested;
25220b090fd3SRasesh Mody }
25230b090fd3SRasesh Mody 
ecore_iov_vf_mbx_update_tunn_param(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * p_vf)25240b090fd3SRasesh Mody static void ecore_iov_vf_mbx_update_tunn_param(struct ecore_hwfn *p_hwfn,
25250b090fd3SRasesh Mody 					       struct ecore_ptt *p_ptt,
25260b090fd3SRasesh Mody 					       struct ecore_vf_info *p_vf)
25270b090fd3SRasesh Mody {
25280b090fd3SRasesh Mody 	struct ecore_tunnel_info *p_tun = &p_hwfn->p_dev->tunnel;
25290b090fd3SRasesh Mody 	struct ecore_iov_vf_mbx *mbx = &p_vf->vf_mbx;
25300b090fd3SRasesh Mody 	struct pfvf_update_tunn_param_tlv *p_resp;
25310b090fd3SRasesh Mody 	struct vfpf_update_tunn_param_tlv *p_req;
25320b090fd3SRasesh Mody 	enum _ecore_status_t rc = ECORE_SUCCESS;
25330b090fd3SRasesh Mody 	u8 status = PFVF_STATUS_SUCCESS;
25340b090fd3SRasesh Mody 	bool b_update_required = false;
25350b090fd3SRasesh Mody 	struct ecore_tunnel_info tunn;
25360b090fd3SRasesh Mody 	u16 tunn_feature_mask = 0;
25374727343dSRasesh Mody 	int i;
25380b090fd3SRasesh Mody 
25390b090fd3SRasesh Mody 	mbx->offset = (u8 *)mbx->reply_virt;
25400b090fd3SRasesh Mody 
25410b090fd3SRasesh Mody 	OSAL_MEM_ZERO(&tunn, sizeof(tunn));
25420b090fd3SRasesh Mody 	p_req = &mbx->req_virt->tunn_param_update;
25430b090fd3SRasesh Mody 
25440b090fd3SRasesh Mody 	if (!ecore_iov_pf_validate_tunn_param(p_req)) {
25450b090fd3SRasesh Mody 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
25460b090fd3SRasesh Mody 			   "No tunnel update requested by VF\n");
25470b090fd3SRasesh Mody 		status = PFVF_STATUS_FAILURE;
25480b090fd3SRasesh Mody 		goto send_resp;
25490b090fd3SRasesh Mody 	}
25500b090fd3SRasesh Mody 
25510b090fd3SRasesh Mody 	tunn.b_update_rx_cls = p_req->update_tun_cls;
25520b090fd3SRasesh Mody 	tunn.b_update_tx_cls = p_req->update_tun_cls;
25530b090fd3SRasesh Mody 
25540b090fd3SRasesh Mody 	ecore_iov_pf_update_tun_param(p_req, &tunn.vxlan, &tunn.vxlan_port,
25550b090fd3SRasesh Mody 				      ECORE_MODE_VXLAN_TUNN, p_req->vxlan_clss,
25560b090fd3SRasesh Mody 				      p_req->update_vxlan_port,
25570b090fd3SRasesh Mody 				      p_req->vxlan_port);
25580b090fd3SRasesh Mody 	ecore_iov_pf_update_tun_param(p_req, &tunn.l2_geneve, &tunn.geneve_port,
25590b090fd3SRasesh Mody 				      ECORE_MODE_L2GENEVE_TUNN,
25600b090fd3SRasesh Mody 				      p_req->l2geneve_clss,
25610b090fd3SRasesh Mody 				      p_req->update_geneve_port,
25620b090fd3SRasesh Mody 				      p_req->geneve_port);
25630b090fd3SRasesh Mody 	__ecore_iov_pf_update_tun_param(p_req, &tunn.ip_geneve,
25640b090fd3SRasesh Mody 					ECORE_MODE_IPGENEVE_TUNN,
25650b090fd3SRasesh Mody 					p_req->ipgeneve_clss);
25660b090fd3SRasesh Mody 	__ecore_iov_pf_update_tun_param(p_req, &tunn.l2_gre,
25670b090fd3SRasesh Mody 					ECORE_MODE_L2GRE_TUNN,
25680b090fd3SRasesh Mody 					p_req->l2gre_clss);
25690b090fd3SRasesh Mody 	__ecore_iov_pf_update_tun_param(p_req, &tunn.ip_gre,
25700b090fd3SRasesh Mody 					ECORE_MODE_IPGRE_TUNN,
25710b090fd3SRasesh Mody 					p_req->ipgre_clss);
25720b090fd3SRasesh Mody 
25730b090fd3SRasesh Mody 	/* If PF modifies VF's req then it should
25740b090fd3SRasesh Mody 	 * still return an error in case of partial configuration
25750b090fd3SRasesh Mody 	 * or modified configuration as opposed to requested one.
25760b090fd3SRasesh Mody 	 */
25770b090fd3SRasesh Mody 	rc = OSAL_PF_VALIDATE_MODIFY_TUNN_CONFIG(p_hwfn, &tunn_feature_mask,
25780b090fd3SRasesh Mody 						 &b_update_required, &tunn);
25790b090fd3SRasesh Mody 
25800b090fd3SRasesh Mody 	if (rc != ECORE_SUCCESS)
25810b090fd3SRasesh Mody 		status = PFVF_STATUS_FAILURE;
25820b090fd3SRasesh Mody 
25830b090fd3SRasesh Mody 	/* If ECORE client is willing to update anything ? */
25840b090fd3SRasesh Mody 	if (b_update_required) {
25854727343dSRasesh Mody 		u16 geneve_port;
25864727343dSRasesh Mody 
2587739a5b2fSRasesh Mody 		rc = ecore_sp_pf_update_tunn_cfg(p_hwfn, p_ptt, &tunn,
25880b090fd3SRasesh Mody 						 ECORE_SPQ_MODE_EBLOCK,
25890b090fd3SRasesh Mody 						 OSAL_NULL);
25900b090fd3SRasesh Mody 		if (rc != ECORE_SUCCESS)
25910b090fd3SRasesh Mody 			status = PFVF_STATUS_FAILURE;
25924727343dSRasesh Mody 
25934727343dSRasesh Mody 		geneve_port = p_tun->geneve_port.port;
25944727343dSRasesh Mody 		ecore_for_each_vf(p_hwfn, i) {
25954727343dSRasesh Mody 			ecore_iov_bulletin_set_udp_ports(p_hwfn, i,
25964727343dSRasesh Mody 							 p_tun->vxlan_port.port,
25974727343dSRasesh Mody 							 geneve_port);
25984727343dSRasesh Mody 		}
25990b090fd3SRasesh Mody 	}
26000b090fd3SRasesh Mody 
26010b090fd3SRasesh Mody send_resp:
260230ecf673SRasesh Mody 	p_resp = ecore_add_tlv(&mbx->offset,
26030b090fd3SRasesh Mody 			       CHANNEL_TLV_UPDATE_TUNN_PARAM, sizeof(*p_resp));
26040b090fd3SRasesh Mody 
26050b090fd3SRasesh Mody 	ecore_iov_pf_update_tun_response(p_resp, p_tun, tunn_feature_mask);
260630ecf673SRasesh Mody 	ecore_add_tlv(&mbx->offset, CHANNEL_TLV_LIST_END,
26070b090fd3SRasesh Mody 		      sizeof(struct channel_list_end_tlv));
26080b090fd3SRasesh Mody 
26090b090fd3SRasesh Mody 	ecore_iov_send_response(p_hwfn, p_ptt, p_vf, sizeof(*p_resp), status);
26100b090fd3SRasesh Mody }
26110b090fd3SRasesh Mody 
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)261222d07d93SRasesh Mody static void ecore_iov_vf_mbx_start_txq_resp(struct ecore_hwfn *p_hwfn,
261322d07d93SRasesh Mody 					    struct ecore_ptt *p_ptt,
261422d07d93SRasesh Mody 					    struct ecore_vf_info *p_vf,
2615eb8e81adSRasesh Mody 					    u32 cid,
261622d07d93SRasesh Mody 					    u8 status)
261722d07d93SRasesh Mody {
261822d07d93SRasesh Mody 	struct ecore_iov_vf_mbx *mbx = &p_vf->vf_mbx;
261922d07d93SRasesh Mody 	struct pfvf_start_queue_resp_tlv *p_tlv;
262022d07d93SRasesh Mody 	bool b_legacy = false;
262122d07d93SRasesh Mody 	u16 length;
262222d07d93SRasesh Mody 
262322d07d93SRasesh Mody 	mbx->offset = (u8 *)mbx->reply_virt;
262422d07d93SRasesh Mody 
262522d07d93SRasesh Mody 	/* Taking a bigger struct instead of adding a TLV to list was a
262622d07d93SRasesh Mody 	 * mistake, but one which we're now stuck with, as some older
262722d07d93SRasesh Mody 	 * clients assume the size of the previous response.
262822d07d93SRasesh Mody 	 */
262922d07d93SRasesh Mody 	if (p_vf->acquire.vfdev_info.eth_fp_hsi_minor ==
263022d07d93SRasesh Mody 	    ETH_HSI_VER_NO_PKT_LEN_TUNN)
263122d07d93SRasesh Mody 		b_legacy = true;
263222d07d93SRasesh Mody 
263322d07d93SRasesh Mody 	if (!b_legacy)
263422d07d93SRasesh Mody 		length = sizeof(*p_tlv);
263522d07d93SRasesh Mody 	else
263622d07d93SRasesh Mody 		length = sizeof(struct pfvf_def_resp_tlv);
263722d07d93SRasesh Mody 
263830ecf673SRasesh Mody 	p_tlv = ecore_add_tlv(&mbx->offset, CHANNEL_TLV_START_TXQ, length);
263930ecf673SRasesh Mody 	ecore_add_tlv(&mbx->offset, CHANNEL_TLV_LIST_END,
264022d07d93SRasesh Mody 		      sizeof(struct channel_list_end_tlv));
264122d07d93SRasesh Mody 
264222d07d93SRasesh Mody 	/* Update the TLV with the response */
2643eb8e81adSRasesh Mody 	if ((status == PFVF_STATUS_SUCCESS) && !b_legacy)
2644eb8e81adSRasesh Mody 		p_tlv->offset = DB_ADDR_VF(cid, DQ_DEMS_LEGACY);
264522d07d93SRasesh Mody 
264622d07d93SRasesh Mody 	ecore_iov_send_response(p_hwfn, p_ptt, p_vf, length, status);
264786a2265eSRasesh Mody }
264886a2265eSRasesh Mody 
ecore_iov_vf_mbx_start_txq(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * vf)264986a2265eSRasesh Mody static void ecore_iov_vf_mbx_start_txq(struct ecore_hwfn *p_hwfn,
265086a2265eSRasesh Mody 				       struct ecore_ptt *p_ptt,
265186a2265eSRasesh Mody 				       struct ecore_vf_info *vf)
265286a2265eSRasesh Mody {
2653379cbb2cSRasesh Mody 	struct ecore_queue_start_common_params params;
2654eb8e81adSRasesh Mody 	struct ecore_queue_cid_vf_params vf_params;
265586a2265eSRasesh Mody 	struct ecore_iov_vf_mbx *mbx = &vf->vf_mbx;
265622d07d93SRasesh Mody 	u8 status = PFVF_STATUS_NO_RESOURCE;
2657eb8e81adSRasesh Mody 	struct ecore_vf_queue *p_queue;
265822d07d93SRasesh Mody 	struct vfpf_start_txq_tlv *req;
2659eb8e81adSRasesh Mody 	struct ecore_queue_cid *p_cid;
26606e4fcea9SRasesh Mody 	struct ecore_sb_info sb_dummy;
2661a90c566fSRasesh Mody 	u8 qid_usage_idx, vf_legacy;
2662eb8e81adSRasesh Mody 	u32 cid = 0;
266386a2265eSRasesh Mody 	enum _ecore_status_t rc;
2664a55e422eSRasesh Mody 	u16 pq;
266586a2265eSRasesh Mody 
2666379cbb2cSRasesh Mody 	OSAL_MEMSET(&params, 0, sizeof(params));
2667153a214dSRasesh Mody 	req = &mbx->req_virt->start_txq;
2668153a214dSRasesh Mody 
2669eb8e81adSRasesh Mody 	if (!ecore_iov_validate_txq(p_hwfn, vf, req->tx_qid,
2670eb8e81adSRasesh Mody 				    ECORE_IOV_VALIDATE_Q_NA) ||
2671153a214dSRasesh Mody 	    !ecore_iov_validate_sb(p_hwfn, vf, req->hw_sb))
2672153a214dSRasesh Mody 		goto out;
2673153a214dSRasesh Mody 
2674a90c566fSRasesh Mody 	qid_usage_idx = ecore_iov_vf_mbx_qid(p_hwfn, vf, true);
2675a90c566fSRasesh Mody 	if (qid_usage_idx == ECORE_IOV_QID_INVALID)
2676a90c566fSRasesh Mody 		goto out;
2677a90c566fSRasesh Mody 
2678a90c566fSRasesh Mody 	p_queue = &vf->vf_queues[req->tx_qid];
2679a90c566fSRasesh Mody 	if (p_queue->cids[qid_usage_idx].p_cid)
2680a90c566fSRasesh Mody 		goto out;
2681a90c566fSRasesh Mody 
268230ecf673SRasesh Mody 	vf_legacy = ecore_vf_calculate_legacy(vf);
2683eb8e81adSRasesh Mody 
2684a55e422eSRasesh Mody 	/* Acquire a new queue-cid */
2685a55e422eSRasesh Mody 	params.queue_id = p_queue->fw_tx_qid;
2686379cbb2cSRasesh Mody 	params.vport_id = vf->vport_id;
26872d5036abSRasesh Mody 	params.stats_id = vf->abs_vf_id + 0x10;
26886e4fcea9SRasesh Mody 
26896e4fcea9SRasesh Mody 	/* Since IGU index is passed via sb_info, construct a dummy one */
26906e4fcea9SRasesh Mody 	OSAL_MEM_ZERO(&sb_dummy, sizeof(sb_dummy));
26916e4fcea9SRasesh Mody 	sb_dummy.igu_sb_id = req->hw_sb;
26926e4fcea9SRasesh Mody 	params.p_sb = &sb_dummy;
2693379cbb2cSRasesh Mody 	params.sb_idx = req->sb_index;
269422d07d93SRasesh Mody 
2695eb8e81adSRasesh Mody 	OSAL_MEM_ZERO(&vf_params, sizeof(vf_params));
2696eb8e81adSRasesh Mody 	vf_params.vfid = vf->relative_vf_id;
2697eb8e81adSRasesh Mody 	vf_params.vf_qid = (u8)req->tx_qid;
2698a90c566fSRasesh Mody 	vf_params.vf_legacy = vf_legacy;
2699eb8e81adSRasesh Mody 	vf_params.qid_usage_idx = qid_usage_idx;
2700eb8e81adSRasesh Mody 
2701eb8e81adSRasesh Mody 	p_cid = ecore_eth_queue_to_cid(p_hwfn, vf->opaque_fid,
2702823a84aaSRasesh Mody 				       &params, false, &vf_params);
2703eb8e81adSRasesh Mody 	if (p_cid == OSAL_NULL)
2704a55e422eSRasesh Mody 		goto out;
270586a2265eSRasesh Mody 
2706a55e422eSRasesh Mody 	pq = ecore_get_cm_pq_idx_vf(p_hwfn,
2707a55e422eSRasesh Mody 				    vf->relative_vf_id);
2708eb8e81adSRasesh Mody 	rc = ecore_eth_txq_start_ramrod(p_hwfn, p_cid,
2709a55e422eSRasesh Mody 					req->pbl_addr, req->pbl_size, pq);
2710a55e422eSRasesh Mody 	if (rc != ECORE_SUCCESS) {
271186a2265eSRasesh Mody 		status = PFVF_STATUS_FAILURE;
2712eb8e81adSRasesh Mody 		ecore_eth_queue_cid_release(p_hwfn, p_cid);
2713a55e422eSRasesh Mody 	} else {
271422d07d93SRasesh Mody 		status = PFVF_STATUS_SUCCESS;
2715eb8e81adSRasesh Mody 		p_queue->cids[qid_usage_idx].p_cid = p_cid;
2716eb8e81adSRasesh Mody 		p_queue->cids[qid_usage_idx].b_is_tx = true;
2717eb8e81adSRasesh Mody 		cid = p_cid->cid;
271822d07d93SRasesh Mody 	}
271986a2265eSRasesh Mody 
272022d07d93SRasesh Mody out:
2721eb8e81adSRasesh Mody 	ecore_iov_vf_mbx_start_txq_resp(p_hwfn, p_ptt, vf,
2722eb8e81adSRasesh Mody 					cid, status);
272386a2265eSRasesh Mody }
272486a2265eSRasesh Mody 
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)272586a2265eSRasesh Mody static enum _ecore_status_t ecore_iov_vf_stop_rxqs(struct ecore_hwfn *p_hwfn,
272686a2265eSRasesh Mody 						   struct ecore_vf_info *vf,
272786a2265eSRasesh Mody 						   u16 rxq_id,
2728a90c566fSRasesh Mody 						   u8 qid_usage_idx,
272986a2265eSRasesh Mody 						   bool cqe_completion)
273086a2265eSRasesh Mody {
2731a90c566fSRasesh Mody 	struct ecore_vf_queue *p_queue;
273286a2265eSRasesh Mody 	enum _ecore_status_t rc = ECORE_SUCCESS;
273386a2265eSRasesh Mody 
2734a90c566fSRasesh Mody 	if (!ecore_iov_validate_rxq(p_hwfn, vf, rxq_id,
2735a90c566fSRasesh Mody 				    ECORE_IOV_VALIDATE_Q_NA)) {
2736eb8e81adSRasesh Mody 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
2737a90c566fSRasesh Mody 			   "VF[%d] Tried Closing Rx 0x%04x.%02x which is inactive\n",
2738a90c566fSRasesh Mody 			   vf->relative_vf_id, rxq_id, qid_usage_idx);
2739a90c566fSRasesh Mody 		return ECORE_INVAL;
2740eb8e81adSRasesh Mody 	}
2741a55e422eSRasesh Mody 
2742a90c566fSRasesh Mody 	p_queue = &vf->vf_queues[rxq_id];
2743a90c566fSRasesh Mody 
2744a90c566fSRasesh Mody 	/* We've validated the index and the existence of the active RXQ -
2745a90c566fSRasesh Mody 	 * now we need to make sure that it's using the correct qid.
2746a90c566fSRasesh Mody 	 */
2747a90c566fSRasesh Mody 	if (!p_queue->cids[qid_usage_idx].p_cid ||
2748a90c566fSRasesh Mody 	    p_queue->cids[qid_usage_idx].b_is_tx) {
2749a90c566fSRasesh Mody 		struct ecore_queue_cid *p_cid;
2750a90c566fSRasesh Mody 
275130ecf673SRasesh Mody 		p_cid = ecore_iov_get_vf_rx_queue_cid(p_queue);
2752a90c566fSRasesh Mody 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
2753a90c566fSRasesh Mody 			   "VF[%d] - Tried Closing Rx 0x%04x.%02x, but Rx is at %04x.%02x\n",
2754a90c566fSRasesh Mody 			    vf->relative_vf_id, rxq_id, qid_usage_idx,
2755a90c566fSRasesh Mody 			    rxq_id, p_cid->qid_usage_idx);
2756a90c566fSRasesh Mody 		return ECORE_INVAL;
2757a90c566fSRasesh Mody 	}
2758a90c566fSRasesh Mody 
2759a90c566fSRasesh Mody 	/* Now that we know we have a valid Rx-queue - close it */
2760a90c566fSRasesh Mody 	rc = ecore_eth_rx_queue_stop(p_hwfn,
2761a90c566fSRasesh Mody 				     p_queue->cids[qid_usage_idx].p_cid,
2762a55e422eSRasesh Mody 				     false, cqe_completion);
2763a55e422eSRasesh Mody 	if (rc != ECORE_SUCCESS)
276486a2265eSRasesh Mody 		return rc;
2765a55e422eSRasesh Mody 
2766a90c566fSRasesh Mody 	p_queue->cids[qid_usage_idx].p_cid = OSAL_NULL;
276786a2265eSRasesh Mody 	vf->num_active_rxqs--;
276886a2265eSRasesh Mody 
2769a90c566fSRasesh Mody 	return ECORE_SUCCESS;
277086a2265eSRasesh Mody }
277186a2265eSRasesh Mody 
ecore_iov_vf_stop_txqs(struct ecore_hwfn * p_hwfn,struct ecore_vf_info * vf,u16 txq_id,u8 qid_usage_idx)277286a2265eSRasesh Mody static enum _ecore_status_t ecore_iov_vf_stop_txqs(struct ecore_hwfn *p_hwfn,
277386a2265eSRasesh Mody 						   struct ecore_vf_info *vf,
2774a90c566fSRasesh Mody 						   u16 txq_id,
2775a90c566fSRasesh Mody 						   u8 qid_usage_idx)
277686a2265eSRasesh Mody {
2777eb8e81adSRasesh Mody 	struct ecore_vf_queue *p_queue;
2778a90c566fSRasesh Mody 	enum _ecore_status_t rc = ECORE_SUCCESS;
277986a2265eSRasesh Mody 
2780eb8e81adSRasesh Mody 	if (!ecore_iov_validate_txq(p_hwfn, vf, txq_id,
2781eb8e81adSRasesh Mody 				    ECORE_IOV_VALIDATE_Q_NA))
278286a2265eSRasesh Mody 		return ECORE_INVAL;
278386a2265eSRasesh Mody 
2784a90c566fSRasesh Mody 	p_queue = &vf->vf_queues[txq_id];
2785a90c566fSRasesh Mody 	if (!p_queue->cids[qid_usage_idx].p_cid ||
2786a90c566fSRasesh Mody 	    !p_queue->cids[qid_usage_idx].b_is_tx)
2787a90c566fSRasesh Mody 		return ECORE_INVAL;
278886a2265eSRasesh Mody 
2789a55e422eSRasesh Mody 	rc = ecore_eth_tx_queue_stop(p_hwfn,
2790a90c566fSRasesh Mody 				     p_queue->cids[qid_usage_idx].p_cid);
2791a55e422eSRasesh Mody 	if (rc != ECORE_SUCCESS)
279286a2265eSRasesh Mody 		return rc;
2793a55e422eSRasesh Mody 
2794a90c566fSRasesh Mody 	p_queue->cids[qid_usage_idx].p_cid = OSAL_NULL;
2795a90c566fSRasesh Mody 	return ECORE_SUCCESS;
279686a2265eSRasesh Mody }
279786a2265eSRasesh Mody 
ecore_iov_vf_mbx_stop_rxqs(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * vf)279886a2265eSRasesh Mody static void ecore_iov_vf_mbx_stop_rxqs(struct ecore_hwfn *p_hwfn,
279986a2265eSRasesh Mody 				       struct ecore_ptt *p_ptt,
280086a2265eSRasesh Mody 				       struct ecore_vf_info *vf)
280186a2265eSRasesh Mody {
280286a2265eSRasesh Mody 	u16 length = sizeof(struct pfvf_def_resp_tlv);
280322d07d93SRasesh Mody 	struct ecore_iov_vf_mbx *mbx = &vf->vf_mbx;
2804a90c566fSRasesh Mody 	u8 status = PFVF_STATUS_FAILURE;
280522d07d93SRasesh Mody 	struct vfpf_stop_rxqs_tlv *req;
2806a90c566fSRasesh Mody 	u8 qid_usage_idx;
280786a2265eSRasesh Mody 	enum _ecore_status_t rc;
280886a2265eSRasesh Mody 
2809a90c566fSRasesh Mody 	/* Starting with CHANNEL_TLV_QID, it's assumed the 'num_rxqs'
2810a90c566fSRasesh Mody 	 * would be one. Since no older ecore passed multiple queues
2811a90c566fSRasesh Mody 	 * using this API, sanitize on the value.
281286a2265eSRasesh Mody 	 */
281322d07d93SRasesh Mody 	req = &mbx->req_virt->stop_rxqs;
2814a90c566fSRasesh Mody 	if (req->num_rxqs != 1) {
2815a90c566fSRasesh Mody 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
2816a90c566fSRasesh Mody 			   "Odd; VF[%d] tried stopping multiple Rx queues\n",
2817a90c566fSRasesh Mody 			   vf->relative_vf_id);
2818a90c566fSRasesh Mody 		status = PFVF_STATUS_NOT_SUPPORTED;
2819a90c566fSRasesh Mody 		goto out;
2820a90c566fSRasesh Mody 	}
282186a2265eSRasesh Mody 
2822a90c566fSRasesh Mody 	/* Find which qid-index is associated with the queue */
2823a90c566fSRasesh Mody 	qid_usage_idx = ecore_iov_vf_mbx_qid(p_hwfn, vf, false);
2824a90c566fSRasesh Mody 	if (qid_usage_idx == ECORE_IOV_QID_INVALID)
2825a90c566fSRasesh Mody 		goto out;
2826a90c566fSRasesh Mody 
2827a90c566fSRasesh Mody 	rc = ecore_iov_vf_stop_rxqs(p_hwfn, vf, req->rx_qid,
2828a90c566fSRasesh Mody 				    qid_usage_idx, req->cqe_completion);
2829a90c566fSRasesh Mody 	if (rc == ECORE_SUCCESS)
2830a90c566fSRasesh Mody 		status = PFVF_STATUS_SUCCESS;
2831a90c566fSRasesh Mody out:
283286a2265eSRasesh Mody 	ecore_iov_prepare_resp(p_hwfn, p_ptt, vf, CHANNEL_TLV_STOP_RXQS,
283386a2265eSRasesh Mody 			       length, status);
283486a2265eSRasesh Mody }
283586a2265eSRasesh Mody 
ecore_iov_vf_mbx_stop_txqs(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * vf)283686a2265eSRasesh Mody static void ecore_iov_vf_mbx_stop_txqs(struct ecore_hwfn *p_hwfn,
283786a2265eSRasesh Mody 				       struct ecore_ptt *p_ptt,
283886a2265eSRasesh Mody 				       struct ecore_vf_info *vf)
283986a2265eSRasesh Mody {
284086a2265eSRasesh Mody 	u16 length = sizeof(struct pfvf_def_resp_tlv);
284122d07d93SRasesh Mody 	struct ecore_iov_vf_mbx *mbx = &vf->vf_mbx;
2842a90c566fSRasesh Mody 	u8 status = PFVF_STATUS_FAILURE;
284322d07d93SRasesh Mody 	struct vfpf_stop_txqs_tlv *req;
2844a90c566fSRasesh Mody 	u8 qid_usage_idx;
284586a2265eSRasesh Mody 	enum _ecore_status_t rc;
284686a2265eSRasesh Mody 
2847a90c566fSRasesh Mody 	/* Starting with CHANNEL_TLV_QID, it's assumed the 'num_txqs'
2848a90c566fSRasesh Mody 	 * would be one. Since no older ecore passed multiple queues
2849a90c566fSRasesh Mody 	 * using this API, sanitize on the value.
285086a2265eSRasesh Mody 	 */
285122d07d93SRasesh Mody 	req = &mbx->req_virt->stop_txqs;
2852a90c566fSRasesh Mody 	if (req->num_txqs != 1) {
2853a90c566fSRasesh Mody 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
2854a90c566fSRasesh Mody 			   "Odd; VF[%d] tried stopping multiple Tx queues\n",
2855a90c566fSRasesh Mody 			   vf->relative_vf_id);
2856a90c566fSRasesh Mody 		status = PFVF_STATUS_NOT_SUPPORTED;
2857a90c566fSRasesh Mody 		goto out;
2858a90c566fSRasesh Mody 	}
285986a2265eSRasesh Mody 
2860a90c566fSRasesh Mody 	/* Find which qid-index is associated with the queue */
2861a90c566fSRasesh Mody 	qid_usage_idx = ecore_iov_vf_mbx_qid(p_hwfn, vf, true);
2862a90c566fSRasesh Mody 	if (qid_usage_idx == ECORE_IOV_QID_INVALID)
2863a90c566fSRasesh Mody 		goto out;
2864a90c566fSRasesh Mody 
2865a90c566fSRasesh Mody 	rc = ecore_iov_vf_stop_txqs(p_hwfn, vf, req->tx_qid,
2866a90c566fSRasesh Mody 				    qid_usage_idx);
2867a90c566fSRasesh Mody 	if (rc == ECORE_SUCCESS)
2868a90c566fSRasesh Mody 		status = PFVF_STATUS_SUCCESS;
2869a90c566fSRasesh Mody 
2870a90c566fSRasesh Mody out:
287186a2265eSRasesh Mody 	ecore_iov_prepare_resp(p_hwfn, p_ptt, vf, CHANNEL_TLV_STOP_TXQS,
287286a2265eSRasesh Mody 			       length, status);
287386a2265eSRasesh Mody }
287486a2265eSRasesh Mody 
ecore_iov_vf_mbx_update_rxqs(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * vf)287586a2265eSRasesh Mody static void ecore_iov_vf_mbx_update_rxqs(struct ecore_hwfn *p_hwfn,
287686a2265eSRasesh Mody 					 struct ecore_ptt *p_ptt,
287786a2265eSRasesh Mody 					 struct ecore_vf_info *vf)
287886a2265eSRasesh Mody {
2879a55e422eSRasesh Mody 	struct ecore_queue_cid *handlers[ECORE_MAX_VF_CHAINS_PER_PF];
288086a2265eSRasesh Mody 	u16 length = sizeof(struct pfvf_def_resp_tlv);
288122d07d93SRasesh Mody 	struct ecore_iov_vf_mbx *mbx = &vf->vf_mbx;
288222d07d93SRasesh Mody 	struct vfpf_update_rxq_tlv *req;
2883a55e422eSRasesh Mody 	u8 status = PFVF_STATUS_FAILURE;
288486a2265eSRasesh Mody 	u8 complete_event_flg;
288586a2265eSRasesh Mody 	u8 complete_cqe_flg;
2886a90c566fSRasesh Mody 	u8 qid_usage_idx;
288722d07d93SRasesh Mody 	enum _ecore_status_t rc;
2888eb8e81adSRasesh Mody 	u16 i;
288986a2265eSRasesh Mody 
289022d07d93SRasesh Mody 	req = &mbx->req_virt->update_rxq;
289186a2265eSRasesh Mody 	complete_cqe_flg = !!(req->flags & VFPF_RXQ_UPD_COMPLETE_CQE_FLAG);
289286a2265eSRasesh Mody 	complete_event_flg = !!(req->flags & VFPF_RXQ_UPD_COMPLETE_EVENT_FLAG);
289386a2265eSRasesh Mody 
2894a90c566fSRasesh Mody 	qid_usage_idx = ecore_iov_vf_mbx_qid(p_hwfn, vf, false);
2895a90c566fSRasesh Mody 	if (qid_usage_idx == ECORE_IOV_QID_INVALID)
2896a90c566fSRasesh Mody 		goto out;
2897a90c566fSRasesh Mody 
2898a90c566fSRasesh Mody 	/* Starting with the addition of CHANNEL_TLV_QID, this API started
2899a90c566fSRasesh Mody 	 * expecting a single queue at a time. Validate this.
2900a90c566fSRasesh Mody 	 */
2901a90c566fSRasesh Mody 	if ((vf->acquire.vfdev_info.capabilities &
2902a90c566fSRasesh Mody 	     VFPF_ACQUIRE_CAP_QUEUE_QIDS) &&
2903a90c566fSRasesh Mody 	     req->num_rxqs != 1) {
2904a90c566fSRasesh Mody 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
2905a90c566fSRasesh Mody 			   "VF[%d] supports QIDs but sends multiple queues\n",
2906a90c566fSRasesh Mody 			   vf->relative_vf_id);
2907a90c566fSRasesh Mody 		goto out;
2908a90c566fSRasesh Mody 	}
2909a90c566fSRasesh Mody 
2910a90c566fSRasesh Mody 	/* Validate inputs - for the legacy case this is still true since
2911a90c566fSRasesh Mody 	 * qid_usage_idx for each Rx queue would be LEGACY_QID_RX.
2912a90c566fSRasesh Mody 	 */
2913eb8e81adSRasesh Mody 	for (i = req->rx_qid; i < req->rx_qid + req->num_rxqs; i++) {
2914eb8e81adSRasesh Mody 		if (!ecore_iov_validate_rxq(p_hwfn, vf, i,
2915a90c566fSRasesh Mody 					    ECORE_IOV_VALIDATE_Q_NA) ||
2916a90c566fSRasesh Mody 		    !vf->vf_queues[i].cids[qid_usage_idx].p_cid ||
2917a90c566fSRasesh Mody 		    vf->vf_queues[i].cids[qid_usage_idx].b_is_tx) {
2918eb8e81adSRasesh Mody 			DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
2919eb8e81adSRasesh Mody 				   "VF[%d]: Incorrect Rxqs [%04x, %02x]\n",
2920eb8e81adSRasesh Mody 				   vf->relative_vf_id, req->rx_qid,
2921eb8e81adSRasesh Mody 				   req->num_rxqs);
2922a55e422eSRasesh Mody 			goto out;
2923a55e422eSRasesh Mody 		}
2924eb8e81adSRasesh Mody 	}
2925a55e422eSRasesh Mody 
292686a2265eSRasesh Mody 	for (i = 0; i < req->num_rxqs; i++) {
2927eb8e81adSRasesh Mody 		u16 qid = req->rx_qid + i;
292886a2265eSRasesh Mody 
2929a90c566fSRasesh Mody 		handlers[i] = vf->vf_queues[qid].cids[qid_usage_idx].p_cid;
2930a55e422eSRasesh Mody 	}
2931a55e422eSRasesh Mody 
2932a55e422eSRasesh Mody 	rc = ecore_sp_eth_rx_queues_update(p_hwfn, (void **)&handlers,
2933a55e422eSRasesh Mody 					   req->num_rxqs,
293486a2265eSRasesh Mody 					   complete_cqe_flg,
293586a2265eSRasesh Mody 					   complete_event_flg,
293686a2265eSRasesh Mody 					   ECORE_SPQ_MODE_EBLOCK,
293786a2265eSRasesh Mody 					   OSAL_NULL);
2938a90c566fSRasesh Mody 	if (rc != ECORE_SUCCESS)
2939a55e422eSRasesh Mody 		goto out;
294086a2265eSRasesh Mody 
2941a55e422eSRasesh Mody 	status = PFVF_STATUS_SUCCESS;
2942a55e422eSRasesh Mody out:
294386a2265eSRasesh Mody 	ecore_iov_prepare_resp(p_hwfn, p_ptt, vf, CHANNEL_TLV_UPDATE_RXQ,
294486a2265eSRasesh Mody 			       length, status);
294586a2265eSRasesh Mody }
294686a2265eSRasesh Mody 
2947d121a6b5SRasesh Mody static enum _ecore_status_t
ecore_iov_vf_pf_update_mtu(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * p_vf)2948d121a6b5SRasesh Mody ecore_iov_vf_pf_update_mtu(struct ecore_hwfn *p_hwfn,
2949d121a6b5SRasesh Mody 				    struct ecore_ptt *p_ptt,
2950d121a6b5SRasesh Mody 				    struct ecore_vf_info *p_vf)
2951d121a6b5SRasesh Mody {
2952d121a6b5SRasesh Mody 	struct ecore_iov_vf_mbx *mbx = &p_vf->vf_mbx;
2953d121a6b5SRasesh Mody 	struct ecore_sp_vport_update_params params;
2954d121a6b5SRasesh Mody 	enum _ecore_status_t rc = ECORE_SUCCESS;
2955d121a6b5SRasesh Mody 	struct vfpf_update_mtu_tlv *p_req;
2956d121a6b5SRasesh Mody 	u8 status = PFVF_STATUS_SUCCESS;
2957d121a6b5SRasesh Mody 
2958d121a6b5SRasesh Mody 	/* Valiate PF can send such a request */
2959d121a6b5SRasesh Mody 	if (!p_vf->vport_instance) {
2960d121a6b5SRasesh Mody 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
2961d121a6b5SRasesh Mody 			   "No VPORT instance available for VF[%d], failing MTU update\n",
2962d121a6b5SRasesh Mody 			   p_vf->abs_vf_id);
2963d121a6b5SRasesh Mody 		status = PFVF_STATUS_FAILURE;
2964d121a6b5SRasesh Mody 		goto send_status;
2965d121a6b5SRasesh Mody 	}
2966d121a6b5SRasesh Mody 
2967d121a6b5SRasesh Mody 	p_req = &mbx->req_virt->update_mtu;
2968d121a6b5SRasesh Mody 
2969d121a6b5SRasesh Mody 	OSAL_MEMSET(&params, 0, sizeof(params));
2970d121a6b5SRasesh Mody 	params.opaque_fid =  p_vf->opaque_fid;
2971d121a6b5SRasesh Mody 	params.vport_id = p_vf->vport_id;
2972d121a6b5SRasesh Mody 	params.mtu = p_req->mtu;
2973d121a6b5SRasesh Mody 	rc = ecore_sp_vport_update(p_hwfn, &params, ECORE_SPQ_MODE_EBLOCK,
2974d121a6b5SRasesh Mody 				   OSAL_NULL);
2975d121a6b5SRasesh Mody 
2976d121a6b5SRasesh Mody 	if (rc)
2977d121a6b5SRasesh Mody 		status = PFVF_STATUS_FAILURE;
2978d121a6b5SRasesh Mody send_status:
2979d121a6b5SRasesh Mody 	ecore_iov_prepare_resp(p_hwfn, p_ptt, p_vf,
2980d121a6b5SRasesh Mody 			       CHANNEL_TLV_UPDATE_MTU,
2981d121a6b5SRasesh Mody 			       sizeof(struct pfvf_def_resp_tlv),
2982d121a6b5SRasesh Mody 			       status);
2983d121a6b5SRasesh Mody 	return rc;
2984d121a6b5SRasesh Mody }
2985d121a6b5SRasesh Mody 
ecore_iov_search_list_tlvs(struct ecore_hwfn * p_hwfn,void * p_tlvs_list,u16 req_type)298686a2265eSRasesh Mody void *ecore_iov_search_list_tlvs(struct ecore_hwfn *p_hwfn,
298786a2265eSRasesh Mody 				 void *p_tlvs_list, u16 req_type)
298886a2265eSRasesh Mody {
298986a2265eSRasesh Mody 	struct channel_tlv *p_tlv = (struct channel_tlv *)p_tlvs_list;
299086a2265eSRasesh Mody 	int len = 0;
299186a2265eSRasesh Mody 
299286a2265eSRasesh Mody 	do {
299386a2265eSRasesh Mody 		if (!p_tlv->length) {
299486a2265eSRasesh Mody 			DP_NOTICE(p_hwfn, true, "Zero length TLV found\n");
299586a2265eSRasesh Mody 			return OSAL_NULL;
299686a2265eSRasesh Mody 		}
299786a2265eSRasesh Mody 
299886a2265eSRasesh Mody 		if (p_tlv->type == req_type) {
299986a2265eSRasesh Mody 			DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
300086a2265eSRasesh Mody 				   "Extended tlv type %s, length %d found\n",
3001520dd992SFerruh Yigit 				   qede_ecore_channel_tlvs_string[p_tlv->type],
300286a2265eSRasesh Mody 				   p_tlv->length);
300386a2265eSRasesh Mody 			return p_tlv;
300486a2265eSRasesh Mody 		}
300586a2265eSRasesh Mody 
300686a2265eSRasesh Mody 		len += p_tlv->length;
300786a2265eSRasesh Mody 		p_tlv = (struct channel_tlv *)((u8 *)p_tlv + p_tlv->length);
300886a2265eSRasesh Mody 
300986a2265eSRasesh Mody 		if ((len + p_tlv->length) > TLV_BUFFER_SIZE) {
301086a2265eSRasesh Mody 			DP_NOTICE(p_hwfn, true,
301186a2265eSRasesh Mody 				  "TLVs has overrun the buffer size\n");
301286a2265eSRasesh Mody 			return OSAL_NULL;
301386a2265eSRasesh Mody 		}
301486a2265eSRasesh Mody 	} while (p_tlv->type != CHANNEL_TLV_LIST_END);
301586a2265eSRasesh Mody 
301686a2265eSRasesh Mody 	return OSAL_NULL;
301786a2265eSRasesh Mody }
301886a2265eSRasesh Mody 
301986a2265eSRasesh Mody 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)302086a2265eSRasesh Mody ecore_iov_vp_update_act_param(struct ecore_hwfn *p_hwfn,
302186a2265eSRasesh Mody 			      struct ecore_sp_vport_update_params *p_data,
302286a2265eSRasesh Mody 			      struct ecore_iov_vf_mbx *p_mbx, u16 *tlvs_mask)
302386a2265eSRasesh Mody {
302486a2265eSRasesh Mody 	struct vfpf_vport_update_activate_tlv *p_act_tlv;
302586a2265eSRasesh Mody 	u16 tlv = CHANNEL_TLV_VPORT_UPDATE_ACTIVATE;
302686a2265eSRasesh Mody 
302786a2265eSRasesh Mody 	p_act_tlv = (struct vfpf_vport_update_activate_tlv *)
302886a2265eSRasesh Mody 	    ecore_iov_search_list_tlvs(p_hwfn, p_mbx->req_virt, tlv);
302922d07d93SRasesh Mody 	if (!p_act_tlv)
303022d07d93SRasesh Mody 		return;
303122d07d93SRasesh Mody 
303286a2265eSRasesh Mody 	p_data->update_vport_active_rx_flg = p_act_tlv->update_rx;
303386a2265eSRasesh Mody 	p_data->vport_active_rx_flg = p_act_tlv->active_rx;
303486a2265eSRasesh Mody 	p_data->update_vport_active_tx_flg = p_act_tlv->update_tx;
303586a2265eSRasesh Mody 	p_data->vport_active_tx_flg = p_act_tlv->active_tx;
303686a2265eSRasesh Mody 	*tlvs_mask |= 1 << ECORE_IOV_VP_UPDATE_ACTIVATE;
303786a2265eSRasesh Mody }
303886a2265eSRasesh Mody 
303986a2265eSRasesh Mody 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)304086a2265eSRasesh Mody ecore_iov_vp_update_vlan_param(struct ecore_hwfn *p_hwfn,
304186a2265eSRasesh Mody 			       struct ecore_sp_vport_update_params *p_data,
304286a2265eSRasesh Mody 			       struct ecore_vf_info *p_vf,
304386a2265eSRasesh Mody 			       struct ecore_iov_vf_mbx *p_mbx, u16 *tlvs_mask)
304486a2265eSRasesh Mody {
304586a2265eSRasesh Mody 	struct vfpf_vport_update_vlan_strip_tlv *p_vlan_tlv;
304686a2265eSRasesh Mody 	u16 tlv = CHANNEL_TLV_VPORT_UPDATE_VLAN_STRIP;
304786a2265eSRasesh Mody 
304886a2265eSRasesh Mody 	p_vlan_tlv = (struct vfpf_vport_update_vlan_strip_tlv *)
304986a2265eSRasesh Mody 	    ecore_iov_search_list_tlvs(p_hwfn, p_mbx->req_virt, tlv);
305086a2265eSRasesh Mody 	if (!p_vlan_tlv)
305186a2265eSRasesh Mody 		return;
305286a2265eSRasesh Mody 
305386a2265eSRasesh Mody 	p_vf->shadow_config.inner_vlan_removal = p_vlan_tlv->remove_vlan;
305486a2265eSRasesh Mody 
305586a2265eSRasesh Mody 	/* Ignore the VF request if we're forcing a vlan */
305686a2265eSRasesh Mody 	if (!(p_vf->configured_features & (1 << VLAN_ADDR_FORCED))) {
305786a2265eSRasesh Mody 		p_data->update_inner_vlan_removal_flg = 1;
305886a2265eSRasesh Mody 		p_data->inner_vlan_removal_flg = p_vlan_tlv->remove_vlan;
305986a2265eSRasesh Mody 	}
306086a2265eSRasesh Mody 
306186a2265eSRasesh Mody 	*tlvs_mask |= 1 << ECORE_IOV_VP_UPDATE_VLAN_STRIP;
306286a2265eSRasesh Mody }
306386a2265eSRasesh Mody 
306486a2265eSRasesh Mody 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)306586a2265eSRasesh Mody ecore_iov_vp_update_tx_switch(struct ecore_hwfn *p_hwfn,
306686a2265eSRasesh Mody 			      struct ecore_sp_vport_update_params *p_data,
306786a2265eSRasesh Mody 			      struct ecore_iov_vf_mbx *p_mbx, u16 *tlvs_mask)
306886a2265eSRasesh Mody {
306986a2265eSRasesh Mody 	struct vfpf_vport_update_tx_switch_tlv *p_tx_switch_tlv;
307086a2265eSRasesh Mody 	u16 tlv = CHANNEL_TLV_VPORT_UPDATE_TX_SWITCH;
307186a2265eSRasesh Mody 
307286a2265eSRasesh Mody 	p_tx_switch_tlv = (struct vfpf_vport_update_tx_switch_tlv *)
307386a2265eSRasesh Mody 	    ecore_iov_search_list_tlvs(p_hwfn, p_mbx->req_virt, tlv);
307422d07d93SRasesh Mody 	if (!p_tx_switch_tlv)
307522d07d93SRasesh Mody 		return;
307686a2265eSRasesh Mody 
307786a2265eSRasesh Mody #ifndef ASIC_ONLY
307886a2265eSRasesh Mody 	if (CHIP_REV_IS_FPGA(p_hwfn->p_dev)) {
307986a2265eSRasesh Mody 		DP_NOTICE(p_hwfn, false,
308022d07d93SRasesh Mody 			  "FPGA: Ignore tx-switching configuration originating"
308122d07d93SRasesh Mody 			  " from VFs\n");
308286a2265eSRasesh Mody 		return;
308386a2265eSRasesh Mody 	}
308486a2265eSRasesh Mody #endif
308586a2265eSRasesh Mody 
308686a2265eSRasesh Mody 	p_data->update_tx_switching_flg = 1;
308786a2265eSRasesh Mody 	p_data->tx_switching_flg = p_tx_switch_tlv->tx_switching;
308886a2265eSRasesh Mody 	*tlvs_mask |= 1 << ECORE_IOV_VP_UPDATE_TX_SWITCH;
308986a2265eSRasesh Mody }
309086a2265eSRasesh Mody 
309186a2265eSRasesh Mody 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)309286a2265eSRasesh Mody ecore_iov_vp_update_mcast_bin_param(struct ecore_hwfn *p_hwfn,
309386a2265eSRasesh Mody 				    struct ecore_sp_vport_update_params *p_data,
309486a2265eSRasesh Mody 				    struct ecore_iov_vf_mbx *p_mbx,
309586a2265eSRasesh Mody 				    u16 *tlvs_mask)
309686a2265eSRasesh Mody {
309786a2265eSRasesh Mody 	struct vfpf_vport_update_mcast_bin_tlv *p_mcast_tlv;
309886a2265eSRasesh Mody 	u16 tlv = CHANNEL_TLV_VPORT_UPDATE_MCAST;
309986a2265eSRasesh Mody 
310086a2265eSRasesh Mody 	p_mcast_tlv = (struct vfpf_vport_update_mcast_bin_tlv *)
310186a2265eSRasesh Mody 	    ecore_iov_search_list_tlvs(p_hwfn, p_mbx->req_virt, tlv);
310222d07d93SRasesh Mody 	if (!p_mcast_tlv)
310322d07d93SRasesh Mody 		return;
310486a2265eSRasesh Mody 
310586a2265eSRasesh Mody 	p_data->update_approx_mcast_flg = 1;
310686a2265eSRasesh Mody 	OSAL_MEMCPY(p_data->bins, p_mcast_tlv->bins,
3107413ecf29SHarish Patil 		    sizeof(u32) * ETH_MULTICAST_MAC_BINS_IN_REGS);
310886a2265eSRasesh Mody 	*tlvs_mask |= 1 << ECORE_IOV_VP_UPDATE_MCAST;
310986a2265eSRasesh Mody }
311086a2265eSRasesh Mody 
311186a2265eSRasesh Mody 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)311286a2265eSRasesh Mody ecore_iov_vp_update_accept_flag(struct ecore_hwfn *p_hwfn,
311386a2265eSRasesh Mody 				struct ecore_sp_vport_update_params *p_data,
311486a2265eSRasesh Mody 				struct ecore_iov_vf_mbx *p_mbx, u16 *tlvs_mask)
311586a2265eSRasesh Mody {
311622d07d93SRasesh Mody 	struct ecore_filter_accept_flags *p_flags = &p_data->accept_flags;
311786a2265eSRasesh Mody 	struct vfpf_vport_update_accept_param_tlv *p_accept_tlv;
311886a2265eSRasesh Mody 	u16 tlv = CHANNEL_TLV_VPORT_UPDATE_ACCEPT_PARAM;
311986a2265eSRasesh Mody 
312086a2265eSRasesh Mody 	p_accept_tlv = (struct vfpf_vport_update_accept_param_tlv *)
312186a2265eSRasesh Mody 	    ecore_iov_search_list_tlvs(p_hwfn, p_mbx->req_virt, tlv);
312222d07d93SRasesh Mody 	if (!p_accept_tlv)
312322d07d93SRasesh Mody 		return;
312486a2265eSRasesh Mody 
312522d07d93SRasesh Mody 	p_flags->update_rx_mode_config = p_accept_tlv->update_rx_mode;
312622d07d93SRasesh Mody 	p_flags->rx_accept_filter = p_accept_tlv->rx_accept_filter;
312722d07d93SRasesh Mody 	p_flags->update_tx_mode_config = p_accept_tlv->update_tx_mode;
312822d07d93SRasesh Mody 	p_flags->tx_accept_filter = p_accept_tlv->tx_accept_filter;
312986a2265eSRasesh Mody 	*tlvs_mask |= 1 << ECORE_IOV_VP_UPDATE_ACCEPT_PARAM;
313086a2265eSRasesh Mody }
313186a2265eSRasesh Mody 
313286a2265eSRasesh Mody 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)313386a2265eSRasesh Mody ecore_iov_vp_update_accept_any_vlan(struct ecore_hwfn *p_hwfn,
313486a2265eSRasesh Mody 				    struct ecore_sp_vport_update_params *p_data,
313586a2265eSRasesh Mody 				    struct ecore_iov_vf_mbx *p_mbx,
313686a2265eSRasesh Mody 				    u16 *tlvs_mask)
313786a2265eSRasesh Mody {
313886a2265eSRasesh Mody 	struct vfpf_vport_update_accept_any_vlan_tlv *p_accept_any_vlan;
313986a2265eSRasesh Mody 	u16 tlv = CHANNEL_TLV_VPORT_UPDATE_ACCEPT_ANY_VLAN;
314086a2265eSRasesh Mody 
314186a2265eSRasesh Mody 	p_accept_any_vlan = (struct vfpf_vport_update_accept_any_vlan_tlv *)
314286a2265eSRasesh Mody 	    ecore_iov_search_list_tlvs(p_hwfn, p_mbx->req_virt, tlv);
314322d07d93SRasesh Mody 	if (!p_accept_any_vlan)
314422d07d93SRasesh Mody 		return;
314586a2265eSRasesh Mody 
314686a2265eSRasesh Mody 	p_data->accept_any_vlan = p_accept_any_vlan->accept_any_vlan;
314786a2265eSRasesh Mody 	p_data->update_accept_any_vlan_flg =
314886a2265eSRasesh Mody 			p_accept_any_vlan->update_accept_any_vlan_flg;
314986a2265eSRasesh Mody 	*tlvs_mask |= 1 << ECORE_IOV_VP_UPDATE_ACCEPT_ANY_VLAN;
315086a2265eSRasesh Mody }
315186a2265eSRasesh Mody 
315286a2265eSRasesh Mody 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)315386a2265eSRasesh Mody ecore_iov_vp_update_rss_param(struct ecore_hwfn *p_hwfn,
315486a2265eSRasesh Mody 			      struct ecore_vf_info *vf,
315586a2265eSRasesh Mody 			      struct ecore_sp_vport_update_params *p_data,
315686a2265eSRasesh Mody 			      struct ecore_rss_params *p_rss,
315769d7ba88SRasesh Mody 			      struct ecore_iov_vf_mbx *p_mbx,
315869d7ba88SRasesh Mody 			      u16 *tlvs_mask, u16 *tlvs_accepted)
315986a2265eSRasesh Mody {
316086a2265eSRasesh Mody 	struct vfpf_vport_update_rss_tlv *p_rss_tlv;
316186a2265eSRasesh Mody 	u16 tlv = CHANNEL_TLV_VPORT_UPDATE_RSS;
316269d7ba88SRasesh Mody 	bool b_reject = false;
316322d07d93SRasesh Mody 	u16 table_size;
316469d7ba88SRasesh Mody 	u16 i, q_idx;
316586a2265eSRasesh Mody 
316686a2265eSRasesh Mody 	p_rss_tlv = (struct vfpf_vport_update_rss_tlv *)
316786a2265eSRasesh Mody 	    ecore_iov_search_list_tlvs(p_hwfn, p_mbx->req_virt, tlv);
316822d07d93SRasesh Mody 	if (!p_rss_tlv) {
316922d07d93SRasesh Mody 		p_data->rss_params = OSAL_NULL;
317022d07d93SRasesh Mody 		return;
317122d07d93SRasesh Mody 	}
317222d07d93SRasesh Mody 
317386a2265eSRasesh Mody 	OSAL_MEMSET(p_rss, 0, sizeof(struct ecore_rss_params));
317486a2265eSRasesh Mody 
317586a2265eSRasesh Mody 	p_rss->update_rss_config =
317686a2265eSRasesh Mody 	    !!(p_rss_tlv->update_rss_flags &
317786a2265eSRasesh Mody 		VFPF_UPDATE_RSS_CONFIG_FLAG);
317886a2265eSRasesh Mody 	p_rss->update_rss_capabilities =
317986a2265eSRasesh Mody 	    !!(p_rss_tlv->update_rss_flags &
318086a2265eSRasesh Mody 		VFPF_UPDATE_RSS_CAPS_FLAG);
318186a2265eSRasesh Mody 	p_rss->update_rss_ind_table =
318286a2265eSRasesh Mody 	    !!(p_rss_tlv->update_rss_flags &
318386a2265eSRasesh Mody 		VFPF_UPDATE_RSS_IND_TABLE_FLAG);
318486a2265eSRasesh Mody 	p_rss->update_rss_key =
318522d07d93SRasesh Mody 	    !!(p_rss_tlv->update_rss_flags &
318622d07d93SRasesh Mody 		VFPF_UPDATE_RSS_KEY_FLAG);
318786a2265eSRasesh Mody 
318886a2265eSRasesh Mody 	p_rss->rss_enable = p_rss_tlv->rss_enable;
318935da9596SRasesh Mody 	p_rss->rss_eng_id = vf->rss_eng_id;
319086a2265eSRasesh Mody 	p_rss->rss_caps = p_rss_tlv->rss_caps;
319186a2265eSRasesh Mody 	p_rss->rss_table_size_log = p_rss_tlv->rss_table_size_log;
319286a2265eSRasesh Mody 	OSAL_MEMCPY(p_rss->rss_key, p_rss_tlv->rss_key,
319386a2265eSRasesh Mody 		    sizeof(p_rss->rss_key));
319486a2265eSRasesh Mody 
319522d07d93SRasesh Mody 	table_size = OSAL_MIN_T(u16, OSAL_ARRAY_SIZE(p_rss->rss_ind_table),
319686a2265eSRasesh Mody 				(1 << p_rss_tlv->rss_table_size_log));
319786a2265eSRasesh Mody 
319886a2265eSRasesh Mody 	for (i = 0; i < table_size; i++) {
3199eb8e81adSRasesh Mody 		struct ecore_queue_cid *p_cid;
3200eb8e81adSRasesh Mody 
320169d7ba88SRasesh Mody 		q_idx = p_rss_tlv->rss_ind_table[i];
3202eb8e81adSRasesh Mody 		if (!ecore_iov_validate_rxq(p_hwfn, vf, q_idx,
3203eb8e81adSRasesh Mody 					    ECORE_IOV_VALIDATE_Q_ENABLE)) {
320469d7ba88SRasesh Mody 			DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
320569d7ba88SRasesh Mody 				   "VF[%d]: Omitting RSS due to wrong queue %04x\n",
320669d7ba88SRasesh Mody 				   vf->relative_vf_id, q_idx);
320769d7ba88SRasesh Mody 			b_reject = true;
320869d7ba88SRasesh Mody 			goto out;
320969d7ba88SRasesh Mody 		}
321022d07d93SRasesh Mody 
321130ecf673SRasesh Mody 		p_cid = ecore_iov_get_vf_rx_queue_cid(&vf->vf_queues[q_idx]);
3212eb8e81adSRasesh Mody 		p_rss->rss_ind_table[i] = p_cid;
321386a2265eSRasesh Mody 	}
321486a2265eSRasesh Mody 
321586a2265eSRasesh Mody 	p_data->rss_params = p_rss;
321669d7ba88SRasesh Mody out:
321786a2265eSRasesh Mody 	*tlvs_mask |= 1 << ECORE_IOV_VP_UPDATE_RSS;
321869d7ba88SRasesh Mody 	if (!b_reject)
321969d7ba88SRasesh Mody 		*tlvs_accepted |= 1 << ECORE_IOV_VP_UPDATE_RSS;
322086a2265eSRasesh Mody }
322186a2265eSRasesh Mody 
322286a2265eSRasesh Mody 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)322386a2265eSRasesh Mody ecore_iov_vp_update_sge_tpa_param(struct ecore_hwfn *p_hwfn,
322486a2265eSRasesh Mody 				  struct ecore_sp_vport_update_params *p_data,
322586a2265eSRasesh Mody 				  struct ecore_sge_tpa_params *p_sge_tpa,
322686a2265eSRasesh Mody 				  struct ecore_iov_vf_mbx *p_mbx,
322786a2265eSRasesh Mody 				  u16 *tlvs_mask)
322886a2265eSRasesh Mody {
322986a2265eSRasesh Mody 	struct vfpf_vport_update_sge_tpa_tlv *p_sge_tpa_tlv;
323086a2265eSRasesh Mody 	u16 tlv = CHANNEL_TLV_VPORT_UPDATE_SGE_TPA;
323186a2265eSRasesh Mody 
323286a2265eSRasesh Mody 	p_sge_tpa_tlv = (struct vfpf_vport_update_sge_tpa_tlv *)
323386a2265eSRasesh Mody 	    ecore_iov_search_list_tlvs(p_hwfn, p_mbx->req_virt, tlv);
323486a2265eSRasesh Mody 
323586a2265eSRasesh Mody 	if (!p_sge_tpa_tlv) {
323686a2265eSRasesh Mody 		p_data->sge_tpa_params = OSAL_NULL;
323786a2265eSRasesh Mody 		return;
323886a2265eSRasesh Mody 	}
323986a2265eSRasesh Mody 
324086a2265eSRasesh Mody 	OSAL_MEMSET(p_sge_tpa, 0, sizeof(struct ecore_sge_tpa_params));
324186a2265eSRasesh Mody 
324286a2265eSRasesh Mody 	p_sge_tpa->update_tpa_en_flg =
324386a2265eSRasesh Mody 	    !!(p_sge_tpa_tlv->update_sge_tpa_flags & VFPF_UPDATE_TPA_EN_FLAG);
324486a2265eSRasesh Mody 	p_sge_tpa->update_tpa_param_flg =
324586a2265eSRasesh Mody 	    !!(p_sge_tpa_tlv->update_sge_tpa_flags &
324686a2265eSRasesh Mody 		VFPF_UPDATE_TPA_PARAM_FLAG);
324786a2265eSRasesh Mody 
324886a2265eSRasesh Mody 	p_sge_tpa->tpa_ipv4_en_flg =
324986a2265eSRasesh Mody 	    !!(p_sge_tpa_tlv->sge_tpa_flags & VFPF_TPA_IPV4_EN_FLAG);
325086a2265eSRasesh Mody 	p_sge_tpa->tpa_ipv6_en_flg =
325186a2265eSRasesh Mody 	    !!(p_sge_tpa_tlv->sge_tpa_flags & VFPF_TPA_IPV6_EN_FLAG);
325286a2265eSRasesh Mody 	p_sge_tpa->tpa_pkt_split_flg =
325386a2265eSRasesh Mody 	    !!(p_sge_tpa_tlv->sge_tpa_flags & VFPF_TPA_PKT_SPLIT_FLAG);
325486a2265eSRasesh Mody 	p_sge_tpa->tpa_hdr_data_split_flg =
325586a2265eSRasesh Mody 	    !!(p_sge_tpa_tlv->sge_tpa_flags & VFPF_TPA_HDR_DATA_SPLIT_FLAG);
325686a2265eSRasesh Mody 	p_sge_tpa->tpa_gro_consistent_flg =
325786a2265eSRasesh Mody 	    !!(p_sge_tpa_tlv->sge_tpa_flags & VFPF_TPA_GRO_CONSIST_FLAG);
325886a2265eSRasesh Mody 
325986a2265eSRasesh Mody 	p_sge_tpa->tpa_max_aggs_num = p_sge_tpa_tlv->tpa_max_aggs_num;
326086a2265eSRasesh Mody 	p_sge_tpa->tpa_max_size = p_sge_tpa_tlv->tpa_max_size;
326186a2265eSRasesh Mody 	p_sge_tpa->tpa_min_size_to_start = p_sge_tpa_tlv->tpa_min_size_to_start;
326286a2265eSRasesh Mody 	p_sge_tpa->tpa_min_size_to_cont = p_sge_tpa_tlv->tpa_min_size_to_cont;
326386a2265eSRasesh Mody 	p_sge_tpa->max_buffers_per_cqe = p_sge_tpa_tlv->max_buffers_per_cqe;
326486a2265eSRasesh Mody 
326586a2265eSRasesh Mody 	p_data->sge_tpa_params = p_sge_tpa;
326686a2265eSRasesh Mody 
326786a2265eSRasesh Mody 	*tlvs_mask |= 1 << ECORE_IOV_VP_UPDATE_SGE_TPA;
326886a2265eSRasesh Mody }
326986a2265eSRasesh Mody 
ecore_iov_vf_mbx_vport_update(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * vf)327086a2265eSRasesh Mody static void ecore_iov_vf_mbx_vport_update(struct ecore_hwfn *p_hwfn,
327186a2265eSRasesh Mody 					  struct ecore_ptt *p_ptt,
327286a2265eSRasesh Mody 					  struct ecore_vf_info *vf)
327386a2265eSRasesh Mody {
327469d7ba88SRasesh Mody 	struct ecore_rss_params *p_rss_params = OSAL_NULL;
327586a2265eSRasesh Mody 	struct ecore_sp_vport_update_params params;
327686a2265eSRasesh Mody 	struct ecore_iov_vf_mbx *mbx = &vf->vf_mbx;
327786a2265eSRasesh Mody 	struct ecore_sge_tpa_params sge_tpa_params;
327822d07d93SRasesh Mody 	u16 tlvs_mask = 0, tlvs_accepted = 0;
327986a2265eSRasesh Mody 	u8 status = PFVF_STATUS_SUCCESS;
328086a2265eSRasesh Mody 	u16 length;
328122d07d93SRasesh Mody 	enum _ecore_status_t rc;
328222d07d93SRasesh Mody 
328322d07d93SRasesh Mody 	/* Valiate PF can send such a request */
328422d07d93SRasesh Mody 	if (!vf->vport_instance) {
328522d07d93SRasesh Mody 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
328622d07d93SRasesh Mody 			   "No VPORT instance available for VF[%d],"
328722d07d93SRasesh Mody 			   " failing vport update\n",
328822d07d93SRasesh Mody 			   vf->abs_vf_id);
328922d07d93SRasesh Mody 		status = PFVF_STATUS_FAILURE;
329022d07d93SRasesh Mody 		goto out;
329122d07d93SRasesh Mody 	}
329286a2265eSRasesh Mody 
3293a261b214SRasesh Mody 	p_rss_params = OSAL_VZALLOC(p_hwfn->p_dev, sizeof(*p_rss_params));
329469d7ba88SRasesh Mody 	if (p_rss_params == OSAL_NULL) {
329569d7ba88SRasesh Mody 		status = PFVF_STATUS_FAILURE;
329669d7ba88SRasesh Mody 		goto out;
329769d7ba88SRasesh Mody 	}
329869d7ba88SRasesh Mody 
329986a2265eSRasesh Mody 	OSAL_MEMSET(&params, 0, sizeof(params));
330086a2265eSRasesh Mody 	params.opaque_fid = vf->opaque_fid;
330186a2265eSRasesh Mody 	params.vport_id = vf->vport_id;
330286a2265eSRasesh Mody 	params.rss_params = OSAL_NULL;
330386a2265eSRasesh Mody 
330486a2265eSRasesh Mody 	/* Search for extended tlvs list and update values
330586a2265eSRasesh Mody 	 * from VF in struct ecore_sp_vport_update_params.
330686a2265eSRasesh Mody 	 */
330786a2265eSRasesh Mody 	ecore_iov_vp_update_act_param(p_hwfn, &params, mbx, &tlvs_mask);
330886a2265eSRasesh Mody 	ecore_iov_vp_update_vlan_param(p_hwfn, &params, vf, mbx, &tlvs_mask);
330986a2265eSRasesh Mody 	ecore_iov_vp_update_tx_switch(p_hwfn, &params, mbx, &tlvs_mask);
331086a2265eSRasesh Mody 	ecore_iov_vp_update_mcast_bin_param(p_hwfn, &params, mbx, &tlvs_mask);
331186a2265eSRasesh Mody 	ecore_iov_vp_update_accept_flag(p_hwfn, &params, mbx, &tlvs_mask);
331286a2265eSRasesh Mody 	ecore_iov_vp_update_accept_any_vlan(p_hwfn, &params, mbx, &tlvs_mask);
331330ecf673SRasesh Mody 	ecore_iov_vp_update_sge_tpa_param(p_hwfn, &params,
331486a2265eSRasesh Mody 					  &sge_tpa_params, mbx, &tlvs_mask);
331586a2265eSRasesh Mody 
331669d7ba88SRasesh Mody 	tlvs_accepted = tlvs_mask;
331769d7ba88SRasesh Mody 
331869d7ba88SRasesh Mody 	/* Some of the extended TLVs need to be validated first; In that case,
331969d7ba88SRasesh Mody 	 * they can update the mask without updating the accepted [so that
332069d7ba88SRasesh Mody 	 * PF could communicate to VF it has rejected request].
332169d7ba88SRasesh Mody 	 */
332269d7ba88SRasesh Mody 	ecore_iov_vp_update_rss_param(p_hwfn, vf, &params, p_rss_params,
332369d7ba88SRasesh Mody 				      mbx, &tlvs_mask, &tlvs_accepted);
332469d7ba88SRasesh Mody 
332586a2265eSRasesh Mody 	/* Just log a message if there is no single extended tlv in buffer.
332686a2265eSRasesh Mody 	 * When all features of vport update ramrod would be requested by VF
332786a2265eSRasesh Mody 	 * as extended TLVs in buffer then an error can be returned in response
332886a2265eSRasesh Mody 	 * if there is no extended TLV present in buffer.
332986a2265eSRasesh Mody 	 */
333086a2265eSRasesh Mody 	if (OSAL_IOV_VF_VPORT_UPDATE(p_hwfn, vf->relative_vf_id,
333186a2265eSRasesh Mody 				     &params, &tlvs_accepted) !=
333286a2265eSRasesh Mody 	    ECORE_SUCCESS) {
333386a2265eSRasesh Mody 		tlvs_accepted = 0;
333486a2265eSRasesh Mody 		status = PFVF_STATUS_NOT_SUPPORTED;
333586a2265eSRasesh Mody 		goto out;
333686a2265eSRasesh Mody 	}
333786a2265eSRasesh Mody 
333886a2265eSRasesh Mody 	if (!tlvs_accepted) {
333986a2265eSRasesh Mody 		if (tlvs_mask)
334086a2265eSRasesh Mody 			DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
334122d07d93SRasesh Mody 				   "Upper-layer prevents said VF"
334222d07d93SRasesh Mody 				   " configuration\n");
334386a2265eSRasesh Mody 		else
334449f4b9dcSRasesh Mody 			DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
334586a2265eSRasesh Mody 				   "No feature tlvs found for vport update\n");
334686a2265eSRasesh Mody 		status = PFVF_STATUS_NOT_SUPPORTED;
334786a2265eSRasesh Mody 		goto out;
334886a2265eSRasesh Mody 	}
334986a2265eSRasesh Mody 
335086a2265eSRasesh Mody 	rc = ecore_sp_vport_update(p_hwfn, &params, ECORE_SPQ_MODE_EBLOCK,
335186a2265eSRasesh Mody 				   OSAL_NULL);
335286a2265eSRasesh Mody 
335386a2265eSRasesh Mody 	if (rc)
335486a2265eSRasesh Mody 		status = PFVF_STATUS_FAILURE;
335586a2265eSRasesh Mody 
335686a2265eSRasesh Mody out:
335769d7ba88SRasesh Mody 	OSAL_VFREE(p_hwfn->p_dev, p_rss_params);
335886a2265eSRasesh Mody 	length = ecore_iov_prep_vp_update_resp_tlvs(p_hwfn, vf, mbx, status,
335986a2265eSRasesh Mody 						    tlvs_mask, tlvs_accepted);
336086a2265eSRasesh Mody 	ecore_iov_send_response(p_hwfn, p_ptt, vf, length, status);
336186a2265eSRasesh Mody }
336286a2265eSRasesh Mody 
336386a2265eSRasesh Mody static enum _ecore_status_t
ecore_iov_vf_update_vlan_shadow(struct ecore_hwfn * p_hwfn,struct ecore_vf_info * p_vf,struct ecore_filter_ucast * p_params)336422d07d93SRasesh Mody ecore_iov_vf_update_vlan_shadow(struct ecore_hwfn *p_hwfn,
336586a2265eSRasesh Mody 				struct ecore_vf_info *p_vf,
336686a2265eSRasesh Mody 				struct ecore_filter_ucast *p_params)
336786a2265eSRasesh Mody {
336886a2265eSRasesh Mody 	int i;
336986a2265eSRasesh Mody 
337086a2265eSRasesh Mody 	/* First remove entries and then add new ones */
337186a2265eSRasesh Mody 	if (p_params->opcode == ECORE_FILTER_REMOVE) {
337286a2265eSRasesh Mody 		for (i = 0; i < ECORE_ETH_VF_NUM_VLAN_FILTERS + 1; i++)
337386a2265eSRasesh Mody 			if (p_vf->shadow_config.vlans[i].used &&
337486a2265eSRasesh Mody 			    p_vf->shadow_config.vlans[i].vid ==
337586a2265eSRasesh Mody 			    p_params->vlan) {
337686a2265eSRasesh Mody 				p_vf->shadow_config.vlans[i].used = false;
337786a2265eSRasesh Mody 				break;
337886a2265eSRasesh Mody 			}
337986a2265eSRasesh Mody 		if (i == ECORE_ETH_VF_NUM_VLAN_FILTERS + 1) {
338086a2265eSRasesh Mody 			DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
338122d07d93SRasesh Mody 				   "VF [%d] - Tries to remove a non-existing"
338222d07d93SRasesh Mody 				   " vlan\n",
338386a2265eSRasesh Mody 				   p_vf->relative_vf_id);
338486a2265eSRasesh Mody 			return ECORE_INVAL;
338586a2265eSRasesh Mody 		}
338686a2265eSRasesh Mody 	} else if (p_params->opcode == ECORE_FILTER_REPLACE ||
338786a2265eSRasesh Mody 		   p_params->opcode == ECORE_FILTER_FLUSH) {
338886a2265eSRasesh Mody 		for (i = 0; i < ECORE_ETH_VF_NUM_VLAN_FILTERS + 1; i++)
338986a2265eSRasesh Mody 			p_vf->shadow_config.vlans[i].used = false;
339086a2265eSRasesh Mody 	}
339186a2265eSRasesh Mody 
339286a2265eSRasesh Mody 	/* In forced mode, we're willing to remove entries - but we don't add
339386a2265eSRasesh Mody 	 * new ones.
339486a2265eSRasesh Mody 	 */
339586a2265eSRasesh Mody 	if (p_vf->bulletin.p_virt->valid_bitmap & (1 << VLAN_ADDR_FORCED))
339686a2265eSRasesh Mody 		return ECORE_SUCCESS;
339786a2265eSRasesh Mody 
339886a2265eSRasesh Mody 	if (p_params->opcode == ECORE_FILTER_ADD ||
339986a2265eSRasesh Mody 	    p_params->opcode == ECORE_FILTER_REPLACE) {
340022d07d93SRasesh Mody 		for (i = 0; i < ECORE_ETH_VF_NUM_VLAN_FILTERS + 1; i++) {
340122d07d93SRasesh Mody 			if (p_vf->shadow_config.vlans[i].used)
340222d07d93SRasesh Mody 				continue;
340322d07d93SRasesh Mody 
340486a2265eSRasesh Mody 			p_vf->shadow_config.vlans[i].used = true;
340522d07d93SRasesh Mody 			p_vf->shadow_config.vlans[i].vid = p_params->vlan;
340686a2265eSRasesh Mody 			break;
340786a2265eSRasesh Mody 		}
340822d07d93SRasesh Mody 
340986a2265eSRasesh Mody 		if (i == ECORE_ETH_VF_NUM_VLAN_FILTERS + 1) {
341086a2265eSRasesh Mody 			DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
341122d07d93SRasesh Mody 				   "VF [%d] - Tries to configure more than %d"
341222d07d93SRasesh Mody 				   " vlan filters\n",
341386a2265eSRasesh Mody 				   p_vf->relative_vf_id,
341486a2265eSRasesh Mody 				   ECORE_ETH_VF_NUM_VLAN_FILTERS + 1);
341586a2265eSRasesh Mody 			return ECORE_INVAL;
341686a2265eSRasesh Mody 		}
341786a2265eSRasesh Mody 	}
341886a2265eSRasesh Mody 
341986a2265eSRasesh Mody 	return ECORE_SUCCESS;
342086a2265eSRasesh Mody }
342186a2265eSRasesh Mody 
342222d07d93SRasesh Mody static enum _ecore_status_t
ecore_iov_vf_update_mac_shadow(struct ecore_hwfn * p_hwfn,struct ecore_vf_info * p_vf,struct ecore_filter_ucast * p_params)342322d07d93SRasesh Mody ecore_iov_vf_update_mac_shadow(struct ecore_hwfn *p_hwfn,
342422d07d93SRasesh Mody 			       struct ecore_vf_info *p_vf,
342522d07d93SRasesh Mody 			       struct ecore_filter_ucast *p_params)
342622d07d93SRasesh Mody {
342722d07d93SRasesh Mody 	char empty_mac[ETH_ALEN];
342822d07d93SRasesh Mody 	int i;
342922d07d93SRasesh Mody 
343022d07d93SRasesh Mody 	OSAL_MEM_ZERO(empty_mac, ETH_ALEN);
343122d07d93SRasesh Mody 
343222d07d93SRasesh Mody 	/* If we're in forced-mode, we don't allow any change */
343322d07d93SRasesh Mody 	/* TODO - this would change if we were ever to implement logic for
343422d07d93SRasesh Mody 	 * removing a forced MAC altogether [in which case, like for vlans,
343522d07d93SRasesh Mody 	 * we should be able to re-trace previous configuration.
343622d07d93SRasesh Mody 	 */
343722d07d93SRasesh Mody 	if (p_vf->bulletin.p_virt->valid_bitmap & (1 << MAC_ADDR_FORCED))
343822d07d93SRasesh Mody 		return ECORE_SUCCESS;
343922d07d93SRasesh Mody 
34402cf7a0faSShahed Shaikh 	/* Since we don't have the implementation of the logic for removing
34412cf7a0faSShahed Shaikh 	 * a forced MAC and restoring shadow MAC, let's not worry about
34422cf7a0faSShahed Shaikh 	 * processing shadow copies of MAC as long as VF trust mode is ON,
34432cf7a0faSShahed Shaikh 	 * to keep things simple.
34442cf7a0faSShahed Shaikh 	 */
34452cf7a0faSShahed Shaikh 	if (p_hwfn->pf_params.eth_pf_params.allow_vf_mac_change ||
34462cf7a0faSShahed Shaikh 	    p_vf->p_vf_info.is_trusted_configured)
34472cf7a0faSShahed Shaikh 		return ECORE_SUCCESS;
34482cf7a0faSShahed Shaikh 
344922d07d93SRasesh Mody 	/* First remove entries and then add new ones */
345022d07d93SRasesh Mody 	if (p_params->opcode == ECORE_FILTER_REMOVE) {
345122d07d93SRasesh Mody 		for (i = 0; i < ECORE_ETH_VF_NUM_MAC_FILTERS; i++) {
345222d07d93SRasesh Mody 			if (!OSAL_MEMCMP(p_vf->shadow_config.macs[i],
345322d07d93SRasesh Mody 					 p_params->mac, ETH_ALEN)) {
345422d07d93SRasesh Mody 				OSAL_MEM_ZERO(p_vf->shadow_config.macs[i],
345522d07d93SRasesh Mody 					      ETH_ALEN);
345622d07d93SRasesh Mody 				break;
345722d07d93SRasesh Mody 			}
345822d07d93SRasesh Mody 		}
345922d07d93SRasesh Mody 
346022d07d93SRasesh Mody 		if (i == ECORE_ETH_VF_NUM_MAC_FILTERS) {
346122d07d93SRasesh Mody 			DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
346222d07d93SRasesh Mody 				   "MAC isn't configured\n");
346322d07d93SRasesh Mody 			return ECORE_INVAL;
346422d07d93SRasesh Mody 		}
346522d07d93SRasesh Mody 	} else if (p_params->opcode == ECORE_FILTER_REPLACE ||
346622d07d93SRasesh Mody 		   p_params->opcode == ECORE_FILTER_FLUSH) {
346722d07d93SRasesh Mody 		for (i = 0; i < ECORE_ETH_VF_NUM_MAC_FILTERS; i++)
346822d07d93SRasesh Mody 			OSAL_MEM_ZERO(p_vf->shadow_config.macs[i], ETH_ALEN);
346922d07d93SRasesh Mody 	}
347022d07d93SRasesh Mody 
347122d07d93SRasesh Mody 	/* List the new MAC address */
347222d07d93SRasesh Mody 	if (p_params->opcode != ECORE_FILTER_ADD &&
347322d07d93SRasesh Mody 	    p_params->opcode != ECORE_FILTER_REPLACE)
347422d07d93SRasesh Mody 		return ECORE_SUCCESS;
347522d07d93SRasesh Mody 
347622d07d93SRasesh Mody 	for (i = 0; i < ECORE_ETH_VF_NUM_MAC_FILTERS; i++) {
347722d07d93SRasesh Mody 		if (!OSAL_MEMCMP(p_vf->shadow_config.macs[i],
347822d07d93SRasesh Mody 				 empty_mac, ETH_ALEN)) {
347922d07d93SRasesh Mody 			OSAL_MEMCPY(p_vf->shadow_config.macs[i],
348022d07d93SRasesh Mody 				    p_params->mac, ETH_ALEN);
348122d07d93SRasesh Mody 			DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
348222d07d93SRasesh Mody 				   "Added MAC at %d entry in shadow\n", i);
348322d07d93SRasesh Mody 			break;
348422d07d93SRasesh Mody 		}
348522d07d93SRasesh Mody 	}
348622d07d93SRasesh Mody 
348722d07d93SRasesh Mody 	if (i == ECORE_ETH_VF_NUM_MAC_FILTERS) {
348822d07d93SRasesh Mody 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
348922d07d93SRasesh Mody 			   "No available place for MAC\n");
349022d07d93SRasesh Mody 		return ECORE_INVAL;
349122d07d93SRasesh Mody 	}
349222d07d93SRasesh Mody 
349322d07d93SRasesh Mody 	return ECORE_SUCCESS;
349422d07d93SRasesh Mody }
349522d07d93SRasesh Mody 
349622d07d93SRasesh Mody 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)349722d07d93SRasesh Mody ecore_iov_vf_update_unicast_shadow(struct ecore_hwfn *p_hwfn,
349822d07d93SRasesh Mody 				   struct ecore_vf_info *p_vf,
349922d07d93SRasesh Mody 				   struct ecore_filter_ucast *p_params)
350022d07d93SRasesh Mody {
350122d07d93SRasesh Mody 	enum _ecore_status_t rc = ECORE_SUCCESS;
350222d07d93SRasesh Mody 
350322d07d93SRasesh Mody 	if (p_params->type == ECORE_FILTER_MAC) {
350422d07d93SRasesh Mody 		rc = ecore_iov_vf_update_mac_shadow(p_hwfn, p_vf, p_params);
350522d07d93SRasesh Mody 		if (rc != ECORE_SUCCESS)
350622d07d93SRasesh Mody 			return rc;
350722d07d93SRasesh Mody 	}
350822d07d93SRasesh Mody 
350922d07d93SRasesh Mody 	if (p_params->type == ECORE_FILTER_VLAN)
351022d07d93SRasesh Mody 		rc = ecore_iov_vf_update_vlan_shadow(p_hwfn, p_vf, p_params);
351122d07d93SRasesh Mody 
351222d07d93SRasesh Mody 	return rc;
351322d07d93SRasesh Mody }
351422d07d93SRasesh Mody 
ecore_iov_vf_mbx_ucast_filter(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * vf)351586a2265eSRasesh Mody static void ecore_iov_vf_mbx_ucast_filter(struct ecore_hwfn *p_hwfn,
351686a2265eSRasesh Mody 					  struct ecore_ptt *p_ptt,
351786a2265eSRasesh Mody 					  struct ecore_vf_info *vf)
351886a2265eSRasesh Mody {
351986a2265eSRasesh Mody 	struct ecore_bulletin_content *p_bulletin = vf->bulletin.p_virt;
352022d07d93SRasesh Mody 	struct ecore_iov_vf_mbx *mbx = &vf->vf_mbx;
352122d07d93SRasesh Mody 	struct vfpf_ucast_filter_tlv *req;
352286a2265eSRasesh Mody 	u8 status = PFVF_STATUS_SUCCESS;
352322d07d93SRasesh Mody 	struct ecore_filter_ucast params;
352486a2265eSRasesh Mody 	enum _ecore_status_t rc;
352586a2265eSRasesh Mody 
352686a2265eSRasesh Mody 	/* Prepare the unicast filter params */
352786a2265eSRasesh Mody 	OSAL_MEMSET(&params, 0, sizeof(struct ecore_filter_ucast));
352822d07d93SRasesh Mody 	req = &mbx->req_virt->ucast_filter;
352986a2265eSRasesh Mody 	params.opcode = (enum ecore_filter_opcode)req->opcode;
353086a2265eSRasesh Mody 	params.type = (enum ecore_filter_ucast_type)req->type;
353186a2265eSRasesh Mody 
353286a2265eSRasesh Mody 	/* @@@TBD - We might need logic on HV side in determining this */
353386a2265eSRasesh Mody 	params.is_rx_filter = 1;
353486a2265eSRasesh Mody 	params.is_tx_filter = 1;
353586a2265eSRasesh Mody 	params.vport_to_remove_from = vf->vport_id;
353686a2265eSRasesh Mody 	params.vport_to_add_to = vf->vport_id;
353786a2265eSRasesh Mody 	OSAL_MEMCPY(params.mac, req->mac, ETH_ALEN);
353886a2265eSRasesh Mody 	params.vlan = req->vlan;
353986a2265eSRasesh Mody 
354086a2265eSRasesh Mody 	DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
354122d07d93SRasesh Mody 		   "VF[%d]: opcode 0x%02x type 0x%02x [%s %s] [vport 0x%02x]"
3542*c2c4f87bSAman Deep Singh 		   " MAC " RTE_ETHER_ADDR_PRT_FMT ", vlan 0x%04x\n",
354386a2265eSRasesh Mody 		   vf->abs_vf_id, params.opcode, params.type,
354486a2265eSRasesh Mody 		   params.is_rx_filter ? "RX" : "",
354586a2265eSRasesh Mody 		   params.is_tx_filter ? "TX" : "",
354686a2265eSRasesh Mody 		   params.vport_to_add_to,
354786a2265eSRasesh Mody 		   params.mac[0], params.mac[1], params.mac[2],
354886a2265eSRasesh Mody 		   params.mac[3], params.mac[4], params.mac[5], params.vlan);
354986a2265eSRasesh Mody 
355086a2265eSRasesh Mody 	if (!vf->vport_instance) {
355186a2265eSRasesh Mody 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
355222d07d93SRasesh Mody 			   "No VPORT instance available for VF[%d],"
355322d07d93SRasesh Mody 			   " failing ucast MAC configuration\n",
355486a2265eSRasesh Mody 			   vf->abs_vf_id);
355586a2265eSRasesh Mody 		status = PFVF_STATUS_FAILURE;
355686a2265eSRasesh Mody 		goto out;
355786a2265eSRasesh Mody 	}
355886a2265eSRasesh Mody 
3559da4ff1c3SRasesh Mody 	/* Update shadow copy of the VF configuration. In case shadow indicates
3560da4ff1c3SRasesh Mody 	 * the action should be blocked return success to VF to imitate the
3561da4ff1c3SRasesh Mody 	 * firmware behaviour in such case.
3562da4ff1c3SRasesh Mody 	 */
356386a2265eSRasesh Mody 	if (ecore_iov_vf_update_unicast_shadow(p_hwfn, vf, &params) !=
3564da4ff1c3SRasesh Mody 	    ECORE_SUCCESS)
356586a2265eSRasesh Mody 		goto out;
356686a2265eSRasesh Mody 
356786a2265eSRasesh Mody 	/* Determine if the unicast filtering is acceptible by PF */
356886a2265eSRasesh Mody 	if ((p_bulletin->valid_bitmap & (1 << VLAN_ADDR_FORCED)) &&
356986a2265eSRasesh Mody 	    (params.type == ECORE_FILTER_VLAN ||
357086a2265eSRasesh Mody 	     params.type == ECORE_FILTER_MAC_VLAN)) {
357186a2265eSRasesh Mody 		/* Once VLAN is forced or PVID is set, do not allow
357286a2265eSRasesh Mody 		 * to add/replace any further VLANs.
357386a2265eSRasesh Mody 		 */
357486a2265eSRasesh Mody 		if (params.opcode == ECORE_FILTER_ADD ||
357586a2265eSRasesh Mody 		    params.opcode == ECORE_FILTER_REPLACE)
357686a2265eSRasesh Mody 			status = PFVF_STATUS_FORCED;
357786a2265eSRasesh Mody 		goto out;
357886a2265eSRasesh Mody 	}
357986a2265eSRasesh Mody 
358086a2265eSRasesh Mody 	if ((p_bulletin->valid_bitmap & (1 << MAC_ADDR_FORCED)) &&
358186a2265eSRasesh Mody 	    (params.type == ECORE_FILTER_MAC ||
358286a2265eSRasesh Mody 	     params.type == ECORE_FILTER_MAC_VLAN)) {
358386a2265eSRasesh Mody 		if (OSAL_MEMCMP(p_bulletin->mac, params.mac, ETH_ALEN) ||
358486a2265eSRasesh Mody 		    (params.opcode != ECORE_FILTER_ADD &&
358586a2265eSRasesh Mody 		     params.opcode != ECORE_FILTER_REPLACE))
358686a2265eSRasesh Mody 			status = PFVF_STATUS_FORCED;
358786a2265eSRasesh Mody 		goto out;
358886a2265eSRasesh Mody 	}
358986a2265eSRasesh Mody 
359086a2265eSRasesh Mody 	rc = OSAL_IOV_CHK_UCAST(p_hwfn, vf->relative_vf_id, &params);
359186a2265eSRasesh Mody 	if (rc == ECORE_EXISTS) {
359286a2265eSRasesh Mody 		goto out;
359386a2265eSRasesh Mody 	} else if (rc == ECORE_INVAL) {
359486a2265eSRasesh Mody 		status = PFVF_STATUS_FAILURE;
359586a2265eSRasesh Mody 		goto out;
359686a2265eSRasesh Mody 	}
359786a2265eSRasesh Mody 
359886a2265eSRasesh Mody 	rc = ecore_sp_eth_filter_ucast(p_hwfn, vf->opaque_fid, &params,
359986a2265eSRasesh Mody 				       ECORE_SPQ_MODE_CB, OSAL_NULL);
360086a2265eSRasesh Mody 	if (rc)
360186a2265eSRasesh Mody 		status = PFVF_STATUS_FAILURE;
360286a2265eSRasesh Mody 
360386a2265eSRasesh Mody out:
360486a2265eSRasesh Mody 	ecore_iov_prepare_resp(p_hwfn, p_ptt, vf, CHANNEL_TLV_UCAST_FILTER,
360586a2265eSRasesh Mody 			       sizeof(struct pfvf_def_resp_tlv), status);
360686a2265eSRasesh Mody }
360786a2265eSRasesh Mody 
ecore_iov_vf_mbx_int_cleanup(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * vf)360886a2265eSRasesh Mody static void ecore_iov_vf_mbx_int_cleanup(struct ecore_hwfn *p_hwfn,
360986a2265eSRasesh Mody 					 struct ecore_ptt *p_ptt,
361086a2265eSRasesh Mody 					 struct ecore_vf_info *vf)
361186a2265eSRasesh Mody {
361286a2265eSRasesh Mody 	int i;
361386a2265eSRasesh Mody 
361486a2265eSRasesh Mody 	/* Reset the SBs */
361586a2265eSRasesh Mody 	for (i = 0; i < vf->num_sbs; i++)
361686a2265eSRasesh Mody 		ecore_int_igu_init_pure_rt_single(p_hwfn, p_ptt,
361786a2265eSRasesh Mody 						  vf->igu_sbs[i],
361886a2265eSRasesh Mody 						  vf->opaque_fid, false);
361986a2265eSRasesh Mody 
362086a2265eSRasesh Mody 	ecore_iov_prepare_resp(p_hwfn, p_ptt, vf, CHANNEL_TLV_INT_CLEANUP,
362186a2265eSRasesh Mody 			       sizeof(struct pfvf_def_resp_tlv),
362286a2265eSRasesh Mody 			       PFVF_STATUS_SUCCESS);
362386a2265eSRasesh Mody }
362486a2265eSRasesh Mody 
ecore_iov_vf_mbx_close(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * vf)362586a2265eSRasesh Mody static void ecore_iov_vf_mbx_close(struct ecore_hwfn *p_hwfn,
362686a2265eSRasesh Mody 				   struct ecore_ptt *p_ptt,
362786a2265eSRasesh Mody 				   struct ecore_vf_info *vf)
362886a2265eSRasesh Mody {
362986a2265eSRasesh Mody 	u16 length = sizeof(struct pfvf_def_resp_tlv);
363086a2265eSRasesh Mody 	u8 status = PFVF_STATUS_SUCCESS;
363186a2265eSRasesh Mody 
363286a2265eSRasesh Mody 	/* Disable Interrupts for VF */
363322d07d93SRasesh Mody 	ecore_iov_vf_igu_set_int(p_hwfn, p_ptt, vf, 0);
363486a2265eSRasesh Mody 
363586a2265eSRasesh Mody 	/* Reset Permission table */
363622d07d93SRasesh Mody 	ecore_iov_config_perm_table(p_hwfn, p_ptt, vf, 0);
363786a2265eSRasesh Mody 
363886a2265eSRasesh Mody 	ecore_iov_prepare_resp(p_hwfn, p_ptt, vf, CHANNEL_TLV_CLOSE,
363986a2265eSRasesh Mody 			       length, status);
364086a2265eSRasesh Mody }
364186a2265eSRasesh Mody 
ecore_iov_vf_mbx_release(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * p_vf)364286a2265eSRasesh Mody static void ecore_iov_vf_mbx_release(struct ecore_hwfn *p_hwfn,
364386a2265eSRasesh Mody 				     struct ecore_ptt *p_ptt,
364486a2265eSRasesh Mody 				     struct ecore_vf_info *p_vf)
364586a2265eSRasesh Mody {
364686a2265eSRasesh Mody 	u16 length = sizeof(struct pfvf_def_resp_tlv);
364722d07d93SRasesh Mody 	u8 status = PFVF_STATUS_SUCCESS;
364822d07d93SRasesh Mody 	enum _ecore_status_t rc = ECORE_SUCCESS;
364986a2265eSRasesh Mody 
365086a2265eSRasesh Mody 	ecore_iov_vf_cleanup(p_hwfn, p_vf);
365186a2265eSRasesh Mody 
365222d07d93SRasesh Mody 	if (p_vf->state != VF_STOPPED && p_vf->state != VF_FREE) {
365322d07d93SRasesh Mody 		/* Stopping the VF */
365422d07d93SRasesh Mody 		rc = ecore_sp_vf_stop(p_hwfn, p_vf->concrete_fid,
365522d07d93SRasesh Mody 				      p_vf->opaque_fid);
365622d07d93SRasesh Mody 
365722d07d93SRasesh Mody 		if (rc != ECORE_SUCCESS) {
365822d07d93SRasesh Mody 			DP_ERR(p_hwfn, "ecore_sp_vf_stop returned error %d\n",
365922d07d93SRasesh Mody 			       rc);
366022d07d93SRasesh Mody 			status = PFVF_STATUS_FAILURE;
366122d07d93SRasesh Mody 		}
366222d07d93SRasesh Mody 
366322d07d93SRasesh Mody 		p_vf->state = VF_STOPPED;
366422d07d93SRasesh Mody 	}
366522d07d93SRasesh Mody 
366686a2265eSRasesh Mody 	ecore_iov_prepare_resp(p_hwfn, p_ptt, p_vf, CHANNEL_TLV_RELEASE,
366722d07d93SRasesh Mody 			       length, status);
366886a2265eSRasesh Mody }
366986a2265eSRasesh Mody 
ecore_iov_vf_pf_get_coalesce(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * p_vf)3670823a84aaSRasesh Mody static void ecore_iov_vf_pf_get_coalesce(struct ecore_hwfn *p_hwfn,
3671823a84aaSRasesh Mody 					 struct ecore_ptt *p_ptt,
3672823a84aaSRasesh Mody 					 struct ecore_vf_info *p_vf)
3673823a84aaSRasesh Mody {
3674823a84aaSRasesh Mody 	struct ecore_iov_vf_mbx *mbx = &p_vf->vf_mbx;
3675823a84aaSRasesh Mody 	struct pfvf_read_coal_resp_tlv *p_resp;
3676823a84aaSRasesh Mody 	struct vfpf_read_coal_req_tlv *req;
3677823a84aaSRasesh Mody 	u8 status = PFVF_STATUS_FAILURE;
3678823a84aaSRasesh Mody 	struct ecore_vf_queue *p_queue;
3679823a84aaSRasesh Mody 	struct ecore_queue_cid *p_cid;
3680823a84aaSRasesh Mody 	enum _ecore_status_t rc = ECORE_SUCCESS;
3681823a84aaSRasesh Mody 	u16 coal = 0, qid, i;
3682823a84aaSRasesh Mody 	bool b_is_rx;
3683823a84aaSRasesh Mody 
3684823a84aaSRasesh Mody 	mbx->offset = (u8 *)mbx->reply_virt;
3685823a84aaSRasesh Mody 	req = &mbx->req_virt->read_coal_req;
3686823a84aaSRasesh Mody 
3687823a84aaSRasesh Mody 	qid = req->qid;
3688823a84aaSRasesh Mody 	b_is_rx = req->is_rx ? true : false;
3689823a84aaSRasesh Mody 
3690823a84aaSRasesh Mody 	if (b_is_rx) {
3691823a84aaSRasesh Mody 		if (!ecore_iov_validate_rxq(p_hwfn, p_vf, qid,
3692823a84aaSRasesh Mody 					    ECORE_IOV_VALIDATE_Q_ENABLE)) {
3693823a84aaSRasesh Mody 			DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
3694823a84aaSRasesh Mody 				   "VF[%d]: Invalid Rx queue_id = %d\n",
3695823a84aaSRasesh Mody 				   p_vf->abs_vf_id, qid);
3696823a84aaSRasesh Mody 			goto send_resp;
3697823a84aaSRasesh Mody 		}
3698823a84aaSRasesh Mody 
3699823a84aaSRasesh Mody 		p_cid = ecore_iov_get_vf_rx_queue_cid(&p_vf->vf_queues[qid]);
3700823a84aaSRasesh Mody 		rc = ecore_get_rxq_coalesce(p_hwfn, p_ptt, p_cid, &coal);
3701823a84aaSRasesh Mody 		if (rc != ECORE_SUCCESS)
3702823a84aaSRasesh Mody 			goto send_resp;
3703823a84aaSRasesh Mody 	} else {
3704823a84aaSRasesh Mody 		if (!ecore_iov_validate_txq(p_hwfn, p_vf, qid,
3705823a84aaSRasesh Mody 					    ECORE_IOV_VALIDATE_Q_ENABLE)) {
3706823a84aaSRasesh Mody 			DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
3707823a84aaSRasesh Mody 				   "VF[%d]: Invalid Tx queue_id = %d\n",
3708823a84aaSRasesh Mody 				   p_vf->abs_vf_id, qid);
3709823a84aaSRasesh Mody 			goto send_resp;
3710823a84aaSRasesh Mody 		}
3711823a84aaSRasesh Mody 		for (i = 0; i < MAX_QUEUES_PER_QZONE; i++) {
3712823a84aaSRasesh Mody 			p_queue = &p_vf->vf_queues[qid];
3713823a84aaSRasesh Mody 			if ((p_queue->cids[i].p_cid == OSAL_NULL) ||
3714823a84aaSRasesh Mody 			    (!p_queue->cids[i].b_is_tx))
3715823a84aaSRasesh Mody 				continue;
3716823a84aaSRasesh Mody 
3717823a84aaSRasesh Mody 			p_cid = p_queue->cids[i].p_cid;
3718823a84aaSRasesh Mody 
3719823a84aaSRasesh Mody 			rc = ecore_get_txq_coalesce(p_hwfn, p_ptt,
3720823a84aaSRasesh Mody 						    p_cid, &coal);
3721823a84aaSRasesh Mody 			if (rc != ECORE_SUCCESS)
3722823a84aaSRasesh Mody 				goto send_resp;
3723823a84aaSRasesh Mody 			break;
3724823a84aaSRasesh Mody 		}
3725823a84aaSRasesh Mody 	}
3726823a84aaSRasesh Mody 
3727823a84aaSRasesh Mody 	status = PFVF_STATUS_SUCCESS;
3728823a84aaSRasesh Mody 
3729823a84aaSRasesh Mody send_resp:
3730823a84aaSRasesh Mody 	p_resp = ecore_add_tlv(&mbx->offset, CHANNEL_TLV_COALESCE_READ,
3731823a84aaSRasesh Mody 			       sizeof(*p_resp));
3732823a84aaSRasesh Mody 	p_resp->coal = coal;
3733823a84aaSRasesh Mody 
3734823a84aaSRasesh Mody 	ecore_add_tlv(&mbx->offset, CHANNEL_TLV_LIST_END,
3735823a84aaSRasesh Mody 		      sizeof(struct channel_list_end_tlv));
3736823a84aaSRasesh Mody 
3737823a84aaSRasesh Mody 	ecore_iov_send_response(p_hwfn, p_ptt, p_vf, sizeof(*p_resp), status);
3738823a84aaSRasesh Mody }
3739823a84aaSRasesh Mody 
ecore_iov_vf_pf_set_coalesce(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,struct ecore_vf_info * vf)37406b8962e0SRasesh Mody static void ecore_iov_vf_pf_set_coalesce(struct ecore_hwfn *p_hwfn,
37416b8962e0SRasesh Mody 					 struct ecore_ptt *p_ptt,
37426b8962e0SRasesh Mody 					 struct ecore_vf_info *vf)
37436b8962e0SRasesh Mody {
37446b8962e0SRasesh Mody 	struct ecore_iov_vf_mbx *mbx = &vf->vf_mbx;
37456b8962e0SRasesh Mody 	enum _ecore_status_t rc = ECORE_SUCCESS;
37466b8962e0SRasesh Mody 	struct vfpf_update_coalesce *req;
37476b8962e0SRasesh Mody 	u8 status = PFVF_STATUS_FAILURE;
37486b8962e0SRasesh Mody 	struct ecore_queue_cid *p_cid;
37496b8962e0SRasesh Mody 	u16 rx_coal, tx_coal;
37506b8962e0SRasesh Mody 	u16 qid;
37519ed26bc7SRasesh Mody 	u32 i;
37526b8962e0SRasesh Mody 
37536b8962e0SRasesh Mody 	req = &mbx->req_virt->update_coalesce;
37546b8962e0SRasesh Mody 
37556b8962e0SRasesh Mody 	rx_coal = req->rx_coal;
37566b8962e0SRasesh Mody 	tx_coal = req->tx_coal;
37576b8962e0SRasesh Mody 	qid = req->qid;
37586b8962e0SRasesh Mody 
3759eb8e81adSRasesh Mody 	if (!ecore_iov_validate_rxq(p_hwfn, vf, qid,
3760eb8e81adSRasesh Mody 				    ECORE_IOV_VALIDATE_Q_ENABLE) &&
3761eb8e81adSRasesh Mody 	    rx_coal) {
37626b8962e0SRasesh Mody 		DP_ERR(p_hwfn, "VF[%d]: Invalid Rx queue_id = %d\n",
37636b8962e0SRasesh Mody 		       vf->abs_vf_id, qid);
37646b8962e0SRasesh Mody 		goto out;
37656b8962e0SRasesh Mody 	}
37666b8962e0SRasesh Mody 
3767eb8e81adSRasesh Mody 	if (!ecore_iov_validate_txq(p_hwfn, vf, qid,
3768eb8e81adSRasesh Mody 				    ECORE_IOV_VALIDATE_Q_ENABLE) &&
3769eb8e81adSRasesh Mody 	    tx_coal) {
37706b8962e0SRasesh Mody 		DP_ERR(p_hwfn, "VF[%d]: Invalid Tx queue_id = %d\n",
37716b8962e0SRasesh Mody 		       vf->abs_vf_id, qid);
37726b8962e0SRasesh Mody 		goto out;
37736b8962e0SRasesh Mody 	}
37746b8962e0SRasesh Mody 
37756b8962e0SRasesh Mody 	DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
37766b8962e0SRasesh Mody 		   "VF[%d]: Setting coalesce for VF rx_coal = %d, tx_coal = %d at queue = %d\n",
37776b8962e0SRasesh Mody 		   vf->abs_vf_id, rx_coal, tx_coal, qid);
3778eb8e81adSRasesh Mody 
37796b8962e0SRasesh Mody 	if (rx_coal) {
378030ecf673SRasesh Mody 		p_cid = ecore_iov_get_vf_rx_queue_cid(&vf->vf_queues[qid]);
3781eb8e81adSRasesh Mody 
37826b8962e0SRasesh Mody 		rc = ecore_set_rxq_coalesce(p_hwfn, p_ptt, rx_coal, p_cid);
37836b8962e0SRasesh Mody 		if (rc != ECORE_SUCCESS) {
37846b8962e0SRasesh Mody 			DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
37856b8962e0SRasesh Mody 				   "VF[%d]: Unable to set rx queue = %d coalesce\n",
37866b8962e0SRasesh Mody 				   vf->abs_vf_id, vf->vf_queues[qid].fw_rx_qid);
37876b8962e0SRasesh Mody 			goto out;
37886b8962e0SRasesh Mody 		}
3789be973769SRasesh Mody 		vf->rx_coal = rx_coal;
37906b8962e0SRasesh Mody 	}
3791eb8e81adSRasesh Mody 
3792eb8e81adSRasesh Mody 	/* TODO - in future, it might be possible to pass this in a per-cid
3793eb8e81adSRasesh Mody 	 * granularity. For now, do this for all Tx queues.
3794eb8e81adSRasesh Mody 	 */
37956b8962e0SRasesh Mody 	if (tx_coal) {
3796eb8e81adSRasesh Mody 		struct ecore_vf_queue *p_queue = &vf->vf_queues[qid];
3797eb8e81adSRasesh Mody 
3798eb8e81adSRasesh Mody 		for (i = 0; i < MAX_QUEUES_PER_QZONE; i++) {
3799eb8e81adSRasesh Mody 			if (p_queue->cids[i].p_cid == OSAL_NULL)
3800eb8e81adSRasesh Mody 				continue;
3801eb8e81adSRasesh Mody 
3802eb8e81adSRasesh Mody 			if (!p_queue->cids[i].b_is_tx)
3803eb8e81adSRasesh Mody 				continue;
3804eb8e81adSRasesh Mody 
3805eb8e81adSRasesh Mody 			rc = ecore_set_txq_coalesce(p_hwfn, p_ptt, tx_coal,
3806eb8e81adSRasesh Mody 						    p_queue->cids[i].p_cid);
38076b8962e0SRasesh Mody 			if (rc != ECORE_SUCCESS) {
38086b8962e0SRasesh Mody 				DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
3809eb8e81adSRasesh Mody 					   "VF[%d]: Unable to set tx queue coalesce\n",
3810eb8e81adSRasesh Mody 					   vf->abs_vf_id);
38116b8962e0SRasesh Mody 				goto out;
38126b8962e0SRasesh Mody 			}
38136b8962e0SRasesh Mody 		}
3814be973769SRasesh Mody 		vf->tx_coal = tx_coal;
3815eb8e81adSRasesh Mody 	}
38166b8962e0SRasesh Mody 
38176b8962e0SRasesh Mody 	status = PFVF_STATUS_SUCCESS;
38186b8962e0SRasesh Mody out:
38196b8962e0SRasesh Mody 	ecore_iov_prepare_resp(p_hwfn, p_ptt, vf, CHANNEL_TLV_COALESCE_UPDATE,
38206b8962e0SRasesh Mody 			       sizeof(struct pfvf_def_resp_tlv), status);
38216b8962e0SRasesh Mody }
38226b8962e0SRasesh Mody 
3823be973769SRasesh Mody 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)3824be973769SRasesh Mody ecore_iov_pf_configure_vf_queue_coalesce(struct ecore_hwfn *p_hwfn,
3825be973769SRasesh Mody 					 u16 rx_coal, u16 tx_coal,
3826be973769SRasesh Mody 					 u16 vf_id, u16 qid)
3827be973769SRasesh Mody {
3828be973769SRasesh Mody 	struct ecore_queue_cid *p_cid;
3829be973769SRasesh Mody 	struct ecore_vf_info *vf;
3830be973769SRasesh Mody 	struct ecore_ptt *p_ptt;
38319ed26bc7SRasesh Mody 	int rc = 0;
38329ed26bc7SRasesh Mody 	u32 i;
3833be973769SRasesh Mody 
3834be973769SRasesh Mody 	if (!ecore_iov_is_valid_vfid(p_hwfn, vf_id, true, true)) {
3835be973769SRasesh Mody 		DP_NOTICE(p_hwfn, true,
3836be973769SRasesh Mody 			  "VF[%d] - Can not set coalescing: VF is not active\n",
3837be973769SRasesh Mody 			  vf_id);
3838be973769SRasesh Mody 		return ECORE_INVAL;
3839be973769SRasesh Mody 	}
3840be973769SRasesh Mody 
3841be973769SRasesh Mody 	vf = &p_hwfn->pf_iov_info->vfs_array[vf_id];
3842be973769SRasesh Mody 	p_ptt = ecore_ptt_acquire(p_hwfn);
3843be973769SRasesh Mody 	if (!p_ptt)
3844be973769SRasesh Mody 		return ECORE_AGAIN;
3845be973769SRasesh Mody 
3846be973769SRasesh Mody 	if (!ecore_iov_validate_rxq(p_hwfn, vf, qid,
3847be973769SRasesh Mody 				    ECORE_IOV_VALIDATE_Q_ENABLE) &&
3848be973769SRasesh Mody 	    rx_coal) {
3849be973769SRasesh Mody 		DP_ERR(p_hwfn, "VF[%d]: Invalid Rx queue_id = %d\n",
3850be973769SRasesh Mody 		       vf->abs_vf_id, qid);
3851be973769SRasesh Mody 		goto out;
3852be973769SRasesh Mody 	}
3853be973769SRasesh Mody 
3854be973769SRasesh Mody 	if (!ecore_iov_validate_txq(p_hwfn, vf, qid,
3855be973769SRasesh Mody 				    ECORE_IOV_VALIDATE_Q_ENABLE) &&
3856be973769SRasesh Mody 	    tx_coal) {
3857be973769SRasesh Mody 		DP_ERR(p_hwfn, "VF[%d]: Invalid Tx queue_id = %d\n",
3858be973769SRasesh Mody 		       vf->abs_vf_id, qid);
3859be973769SRasesh Mody 		goto out;
3860be973769SRasesh Mody 	}
3861be973769SRasesh Mody 
3862be973769SRasesh Mody 	DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
3863be973769SRasesh Mody 		   "VF[%d]: Setting coalesce for VF rx_coal = %d, tx_coal = %d at queue = %d\n",
3864be973769SRasesh Mody 		   vf->abs_vf_id, rx_coal, tx_coal, qid);
3865be973769SRasesh Mody 
3866be973769SRasesh Mody 	if (rx_coal) {
386730ecf673SRasesh Mody 		p_cid = ecore_iov_get_vf_rx_queue_cid(&vf->vf_queues[qid]);
3868be973769SRasesh Mody 
3869be973769SRasesh Mody 		rc = ecore_set_rxq_coalesce(p_hwfn, p_ptt, rx_coal, p_cid);
3870be973769SRasesh Mody 		if (rc != ECORE_SUCCESS) {
3871be973769SRasesh Mody 			DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
3872be973769SRasesh Mody 				   "VF[%d]: Unable to set rx queue = %d coalesce\n",
3873be973769SRasesh Mody 				   vf->abs_vf_id, vf->vf_queues[qid].fw_rx_qid);
3874be973769SRasesh Mody 			goto out;
3875be973769SRasesh Mody 		}
3876be973769SRasesh Mody 		vf->rx_coal = rx_coal;
3877be973769SRasesh Mody 	}
3878be973769SRasesh Mody 
3879be973769SRasesh Mody 	/* TODO - in future, it might be possible to pass this in a per-cid
3880be973769SRasesh Mody 	 * granularity. For now, do this for all Tx queues.
3881be973769SRasesh Mody 	 */
3882be973769SRasesh Mody 	if (tx_coal) {
3883be973769SRasesh Mody 		struct ecore_vf_queue *p_queue = &vf->vf_queues[qid];
3884be973769SRasesh Mody 
3885be973769SRasesh Mody 		for (i = 0; i < MAX_QUEUES_PER_QZONE; i++) {
3886be973769SRasesh Mody 			if (p_queue->cids[i].p_cid == OSAL_NULL)
3887be973769SRasesh Mody 				continue;
3888be973769SRasesh Mody 
3889be973769SRasesh Mody 			if (!p_queue->cids[i].b_is_tx)
3890be973769SRasesh Mody 				continue;
3891be973769SRasesh Mody 
3892be973769SRasesh Mody 			rc = ecore_set_txq_coalesce(p_hwfn, p_ptt, tx_coal,
3893be973769SRasesh Mody 						    p_queue->cids[i].p_cid);
3894be973769SRasesh Mody 			if (rc != ECORE_SUCCESS) {
3895be973769SRasesh Mody 				DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
3896be973769SRasesh Mody 					   "VF[%d]: Unable to set tx queue coalesce\n",
3897be973769SRasesh Mody 					   vf->abs_vf_id);
3898be973769SRasesh Mody 				goto out;
3899be973769SRasesh Mody 			}
3900be973769SRasesh Mody 		}
3901be973769SRasesh Mody 		vf->tx_coal = tx_coal;
3902be973769SRasesh Mody 	}
3903be973769SRasesh Mody 
3904be973769SRasesh Mody out:
3905be973769SRasesh Mody 	ecore_ptt_release(p_hwfn, p_ptt);
3906be973769SRasesh Mody 
3907be973769SRasesh Mody 	return rc;
3908be973769SRasesh Mody }
3909be973769SRasesh Mody 
391086a2265eSRasesh Mody 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)391186a2265eSRasesh Mody ecore_iov_vf_flr_poll_dorq(struct ecore_hwfn *p_hwfn,
391286a2265eSRasesh Mody 			   struct ecore_vf_info *p_vf, struct ecore_ptt *p_ptt)
391386a2265eSRasesh Mody {
391486a2265eSRasesh Mody 	int cnt;
391586a2265eSRasesh Mody 	u32 val;
391686a2265eSRasesh Mody 
391786a2265eSRasesh Mody 	ecore_fid_pretend(p_hwfn, p_ptt, (u16)p_vf->concrete_fid);
391886a2265eSRasesh Mody 
391986a2265eSRasesh Mody 	for (cnt = 0; cnt < 50; cnt++) {
392086a2265eSRasesh Mody 		val = ecore_rd(p_hwfn, p_ptt, DORQ_REG_VF_USAGE_CNT);
392186a2265eSRasesh Mody 		if (!val)
392286a2265eSRasesh Mody 			break;
392386a2265eSRasesh Mody 		OSAL_MSLEEP(20);
392486a2265eSRasesh Mody 	}
392586a2265eSRasesh Mody 	ecore_fid_pretend(p_hwfn, p_ptt, (u16)p_hwfn->hw_info.concrete_fid);
392686a2265eSRasesh Mody 
392786a2265eSRasesh Mody 	if (cnt == 50) {
392886a2265eSRasesh Mody 		DP_ERR(p_hwfn,
392986a2265eSRasesh Mody 		       "VF[%d] - dorq failed to cleanup [usage 0x%08x]\n",
393086a2265eSRasesh Mody 		       p_vf->abs_vf_id, val);
393186a2265eSRasesh Mody 		return ECORE_TIMEOUT;
393286a2265eSRasesh Mody 	}
393386a2265eSRasesh Mody 
393486a2265eSRasesh Mody 	return ECORE_SUCCESS;
393586a2265eSRasesh Mody }
393686a2265eSRasesh Mody 
39373b307c55SRasesh Mody #define MAX_NUM_EXT_VOQS	(MAX_NUM_PORTS * NUM_OF_TCS)
39383b307c55SRasesh Mody 
393986a2265eSRasesh Mody 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)394086a2265eSRasesh Mody ecore_iov_vf_flr_poll_pbf(struct ecore_hwfn *p_hwfn,
394186a2265eSRasesh Mody 			  struct ecore_vf_info *p_vf, struct ecore_ptt *p_ptt)
394286a2265eSRasesh Mody {
39433b307c55SRasesh Mody 	u32 prod, cons[MAX_NUM_EXT_VOQS], distance[MAX_NUM_EXT_VOQS], tmp;
39443b307c55SRasesh Mody 	u8 max_phys_tcs_per_port = p_hwfn->qm_info.max_phys_tcs_per_port;
39453b307c55SRasesh Mody 	u8 max_ports_per_engine = p_hwfn->p_dev->num_ports_in_engine;
39463b307c55SRasesh Mody 	u32 prod_voq0_addr = PBF_REG_NUM_BLOCKS_ALLOCATED_PROD_VOQ0;
39473b307c55SRasesh Mody 	u32 cons_voq0_addr = PBF_REG_NUM_BLOCKS_ALLOCATED_CONS_VOQ0;
39483b307c55SRasesh Mody 	u8 port_id, tc, tc_id = 0, voq = 0;
39493b307c55SRasesh Mody 	int cnt;
395086a2265eSRasesh Mody 
395186a2265eSRasesh Mody 	/* Read initial consumers & producers */
39523b307c55SRasesh Mody 	for (port_id = 0; port_id < max_ports_per_engine; port_id++) {
39533b307c55SRasesh Mody 		/* "max_phys_tcs_per_port" active TCs + 1 pure LB TC */
39543b307c55SRasesh Mody 		for (tc = 0; tc < max_phys_tcs_per_port + 1; tc++) {
39553b307c55SRasesh Mody 			tc_id = (tc < max_phys_tcs_per_port) ?
39563b307c55SRasesh Mody 				tc :
39573b307c55SRasesh Mody 				PURE_LB_TC;
39583b307c55SRasesh Mody 			voq = VOQ(port_id, tc_id, max_phys_tcs_per_port);
39593b307c55SRasesh Mody 			cons[voq] = ecore_rd(p_hwfn, p_ptt,
39603b307c55SRasesh Mody 					     cons_voq0_addr + voq * 0x40);
396186a2265eSRasesh Mody 		prod = ecore_rd(p_hwfn, p_ptt,
39623b307c55SRasesh Mody 					prod_voq0_addr + voq * 0x40);
39633b307c55SRasesh Mody 			distance[voq] = prod - cons[voq];
39643b307c55SRasesh Mody 		}
396586a2265eSRasesh Mody 	}
396686a2265eSRasesh Mody 
396786a2265eSRasesh Mody 	/* Wait for consumers to pass the producers */
39683b307c55SRasesh Mody 	port_id = 0;
39693b307c55SRasesh Mody 	tc = 0;
397086a2265eSRasesh Mody 	for (cnt = 0; cnt < 50; cnt++) {
39713b307c55SRasesh Mody 		for (; port_id < max_ports_per_engine; port_id++) {
39723b307c55SRasesh Mody 			/* "max_phys_tcs_per_port" active TCs + 1 pure LB TC */
39733b307c55SRasesh Mody 			for (; tc < max_phys_tcs_per_port + 1; tc++) {
39743b307c55SRasesh Mody 				tc_id = (tc < max_phys_tcs_per_port) ?
39753b307c55SRasesh Mody 					tc :
39763b307c55SRasesh Mody 					PURE_LB_TC;
39773b307c55SRasesh Mody 				voq = VOQ(port_id, tc_id,
39783b307c55SRasesh Mody 					  max_phys_tcs_per_port);
397986a2265eSRasesh Mody 			tmp = ecore_rd(p_hwfn, p_ptt,
39803b307c55SRasesh Mody 					       cons_voq0_addr + voq * 0x40);
39813b307c55SRasesh Mody 			if (distance[voq] > tmp - cons[voq])
398286a2265eSRasesh Mody 				break;
398386a2265eSRasesh Mody 		}
398486a2265eSRasesh Mody 
39853b307c55SRasesh Mody 			if (tc == max_phys_tcs_per_port + 1)
39863b307c55SRasesh Mody 				tc = 0;
39873b307c55SRasesh Mody 			else
39883b307c55SRasesh Mody 				break;
39893b307c55SRasesh Mody 		}
39903b307c55SRasesh Mody 
39913b307c55SRasesh Mody 		if (port_id == max_ports_per_engine)
399286a2265eSRasesh Mody 			break;
399386a2265eSRasesh Mody 
399486a2265eSRasesh Mody 		OSAL_MSLEEP(20);
399586a2265eSRasesh Mody 	}
399686a2265eSRasesh Mody 
399786a2265eSRasesh Mody 	if (cnt == 50) {
39983b307c55SRasesh Mody 		DP_ERR(p_hwfn,
39993b307c55SRasesh Mody 		       "VF[%d] - pbf polling failed on VOQ %d [port_id %d, tc_id %d]\n",
40003b307c55SRasesh Mody 		       p_vf->abs_vf_id, voq, port_id, tc_id);
400186a2265eSRasesh Mody 		return ECORE_TIMEOUT;
400286a2265eSRasesh Mody 	}
400386a2265eSRasesh Mody 
400486a2265eSRasesh Mody 	return ECORE_SUCCESS;
400586a2265eSRasesh Mody }
400686a2265eSRasesh Mody 
ecore_iov_vf_flr_poll(struct ecore_hwfn * p_hwfn,struct ecore_vf_info * p_vf,struct ecore_ptt * p_ptt)400786a2265eSRasesh Mody static enum _ecore_status_t ecore_iov_vf_flr_poll(struct ecore_hwfn *p_hwfn,
400886a2265eSRasesh Mody 						  struct ecore_vf_info *p_vf,
400986a2265eSRasesh Mody 						  struct ecore_ptt *p_ptt)
401086a2265eSRasesh Mody {
401186a2265eSRasesh Mody 	enum _ecore_status_t rc;
401286a2265eSRasesh Mody 
401386a2265eSRasesh Mody 	/* TODO - add SRC and TM polling once we add storage IOV */
401486a2265eSRasesh Mody 
401586a2265eSRasesh Mody 	rc = ecore_iov_vf_flr_poll_dorq(p_hwfn, p_vf, p_ptt);
401686a2265eSRasesh Mody 	if (rc)
401786a2265eSRasesh Mody 		return rc;
401886a2265eSRasesh Mody 
401986a2265eSRasesh Mody 	rc = ecore_iov_vf_flr_poll_pbf(p_hwfn, p_vf, p_ptt);
402086a2265eSRasesh Mody 	if (rc)
402186a2265eSRasesh Mody 		return rc;
402286a2265eSRasesh Mody 
402386a2265eSRasesh Mody 	return ECORE_SUCCESS;
402486a2265eSRasesh Mody }
402586a2265eSRasesh Mody 
402686a2265eSRasesh Mody 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)402786a2265eSRasesh Mody ecore_iov_execute_vf_flr_cleanup(struct ecore_hwfn *p_hwfn,
402886a2265eSRasesh Mody 				 struct ecore_ptt *p_ptt,
402986a2265eSRasesh Mody 				 u16 rel_vf_id, u32 *ack_vfs)
403086a2265eSRasesh Mody {
403186a2265eSRasesh Mody 	struct ecore_vf_info *p_vf;
403222d07d93SRasesh Mody 	enum _ecore_status_t rc = ECORE_SUCCESS;
403386a2265eSRasesh Mody 
403486a2265eSRasesh Mody 	p_vf = ecore_iov_get_vf_info(p_hwfn, rel_vf_id, false);
403586a2265eSRasesh Mody 	if (!p_vf)
403686a2265eSRasesh Mody 		return ECORE_SUCCESS;
403786a2265eSRasesh Mody 
403886a2265eSRasesh Mody 	if (p_hwfn->pf_iov_info->pending_flr[rel_vf_id / 64] &
403986a2265eSRasesh Mody 	    (1ULL << (rel_vf_id % 64))) {
404086a2265eSRasesh Mody 		u16 vfid = p_vf->abs_vf_id;
404186a2265eSRasesh Mody 
404286a2265eSRasesh Mody 		/* TODO - should we lock channel? */
404386a2265eSRasesh Mody 
404486a2265eSRasesh Mody 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
404586a2265eSRasesh Mody 			   "VF[%d] - Handling FLR\n", vfid);
404686a2265eSRasesh Mody 
404786a2265eSRasesh Mody 		ecore_iov_vf_cleanup(p_hwfn, p_vf);
404886a2265eSRasesh Mody 
404986a2265eSRasesh Mody 		/* If VF isn't active, no need for anything but SW */
405022d07d93SRasesh Mody 		if (!p_vf->b_init)
405186a2265eSRasesh Mody 			goto cleanup;
405286a2265eSRasesh Mody 
405386a2265eSRasesh Mody 		/* TODO - what to do in case of failure? */
405486a2265eSRasesh Mody 		rc = ecore_iov_vf_flr_poll(p_hwfn, p_vf, p_ptt);
405586a2265eSRasesh Mody 		if (rc != ECORE_SUCCESS)
405686a2265eSRasesh Mody 			goto cleanup;
405786a2265eSRasesh Mody 
405886a2265eSRasesh Mody 		rc = ecore_final_cleanup(p_hwfn, p_ptt, vfid, true);
405986a2265eSRasesh Mody 		if (rc) {
406086a2265eSRasesh Mody 			/* TODO - what's now? What a mess.... */
406186a2265eSRasesh Mody 			DP_ERR(p_hwfn, "Failed handle FLR of VF[%d]\n", vfid);
406286a2265eSRasesh Mody 			return rc;
406386a2265eSRasesh Mody 		}
406486a2265eSRasesh Mody 
40658168b63dSRasesh Mody 		/* Workaround to make VF-PF channel ready, as FW
40668168b63dSRasesh Mody 		 * doesn't do that as a part of FLR.
40678168b63dSRasesh Mody 		 */
40688168b63dSRasesh Mody 		REG_WR(p_hwfn,
40698168b63dSRasesh Mody 		       GTT_BAR0_MAP_REG_USDM_RAM +
40708168b63dSRasesh Mody 		       USTORM_VF_PF_CHANNEL_READY_OFFSET(vfid), 1);
40718168b63dSRasesh Mody 
407286a2265eSRasesh Mody 		/* VF_STOPPED has to be set only after final cleanup
407386a2265eSRasesh Mody 		 * but prior to re-enabling the VF.
407486a2265eSRasesh Mody 		 */
407586a2265eSRasesh Mody 		p_vf->state = VF_STOPPED;
407686a2265eSRasesh Mody 
407786a2265eSRasesh Mody 		rc = ecore_iov_enable_vf_access(p_hwfn, p_ptt, p_vf);
407886a2265eSRasesh Mody 		if (rc) {
407986a2265eSRasesh Mody 			/* TODO - again, a mess... */
4080e8cff614SLuca Boccassi 			DP_ERR(p_hwfn, "Failed to re-enable VF[%d] access\n",
408186a2265eSRasesh Mody 			       vfid);
408286a2265eSRasesh Mody 			return rc;
408386a2265eSRasesh Mody 		}
408486a2265eSRasesh Mody cleanup:
408586a2265eSRasesh Mody 		/* Mark VF for ack and clean pending state */
408686a2265eSRasesh Mody 		if (p_vf->state == VF_RESET)
408786a2265eSRasesh Mody 			p_vf->state = VF_STOPPED;
408886a2265eSRasesh Mody 		ack_vfs[vfid / 32] |= (1 << (vfid % 32));
408986a2265eSRasesh Mody 		p_hwfn->pf_iov_info->pending_flr[rel_vf_id / 64] &=
409086a2265eSRasesh Mody 		    ~(1ULL << (rel_vf_id % 64));
40914be18885SRasesh Mody 		p_vf->vf_mbx.b_pending_msg = false;
409286a2265eSRasesh Mody 	}
409386a2265eSRasesh Mody 
409486a2265eSRasesh Mody 	return rc;
409586a2265eSRasesh Mody }
409686a2265eSRasesh Mody 
ecore_iov_vf_flr_cleanup(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)409786a2265eSRasesh Mody enum _ecore_status_t ecore_iov_vf_flr_cleanup(struct ecore_hwfn *p_hwfn,
409886a2265eSRasesh Mody 					      struct ecore_ptt *p_ptt)
409986a2265eSRasesh Mody {
41003b307c55SRasesh Mody 	u32 ack_vfs[EXT_VF_BITMAP_SIZE_IN_DWORDS];
410186a2265eSRasesh Mody 	enum _ecore_status_t rc = ECORE_SUCCESS;
410286a2265eSRasesh Mody 	u16 i;
410386a2265eSRasesh Mody 
41043b307c55SRasesh Mody 	OSAL_MEM_ZERO(ack_vfs, EXT_VF_BITMAP_SIZE_IN_BYTES);
410586a2265eSRasesh Mody 
410622d07d93SRasesh Mody 	/* Since BRB <-> PRS interface can't be tested as part of the flr
410722d07d93SRasesh Mody 	 * polling due to HW limitations, simply sleep a bit. And since
410822d07d93SRasesh Mody 	 * there's no need to wait per-vf, do it before looping.
410922d07d93SRasesh Mody 	 */
411022d07d93SRasesh Mody 	OSAL_MSLEEP(100);
411122d07d93SRasesh Mody 
411222d07d93SRasesh Mody 	for (i = 0; i < p_hwfn->p_dev->p_iov_info->total_vfs; i++)
411386a2265eSRasesh Mody 		ecore_iov_execute_vf_flr_cleanup(p_hwfn, p_ptt, i, ack_vfs);
411486a2265eSRasesh Mody 
411586a2265eSRasesh Mody 	rc = ecore_mcp_ack_vf_flr(p_hwfn, p_ptt, ack_vfs);
411686a2265eSRasesh Mody 	return rc;
411786a2265eSRasesh Mody }
411886a2265eSRasesh Mody 
411986a2265eSRasesh Mody enum _ecore_status_t
ecore_iov_single_vf_flr_cleanup(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u16 rel_vf_id)412086a2265eSRasesh Mody ecore_iov_single_vf_flr_cleanup(struct ecore_hwfn *p_hwfn,
412186a2265eSRasesh Mody 				struct ecore_ptt *p_ptt, u16 rel_vf_id)
412286a2265eSRasesh Mody {
41233b307c55SRasesh Mody 	u32 ack_vfs[EXT_VF_BITMAP_SIZE_IN_DWORDS];
412486a2265eSRasesh Mody 	enum _ecore_status_t rc = ECORE_SUCCESS;
412586a2265eSRasesh Mody 
41263b307c55SRasesh Mody 	OSAL_MEM_ZERO(ack_vfs, EXT_VF_BITMAP_SIZE_IN_BYTES);
412786a2265eSRasesh Mody 
412822d07d93SRasesh Mody 	/* Wait instead of polling the BRB <-> PRS interface */
412922d07d93SRasesh Mody 	OSAL_MSLEEP(100);
413022d07d93SRasesh Mody 
413186a2265eSRasesh Mody 	ecore_iov_execute_vf_flr_cleanup(p_hwfn, p_ptt, rel_vf_id, ack_vfs);
413286a2265eSRasesh Mody 
413386a2265eSRasesh Mody 	rc = ecore_mcp_ack_vf_flr(p_hwfn, p_ptt, ack_vfs);
413486a2265eSRasesh Mody 	return rc;
413586a2265eSRasesh Mody }
413686a2265eSRasesh Mody 
ecore_iov_mark_vf_flr(struct ecore_hwfn * p_hwfn,u32 * p_disabled_vfs)413793fce904SRasesh Mody bool ecore_iov_mark_vf_flr(struct ecore_hwfn *p_hwfn, u32 *p_disabled_vfs)
413886a2265eSRasesh Mody {
413963efb906SRasesh Mody 	bool found = false;
414093fce904SRasesh Mody 	u16 i;
414186a2265eSRasesh Mody 
414286a2265eSRasesh Mody 	DP_VERBOSE(p_hwfn, ECORE_MSG_IOV, "Marking FLR-ed VFs\n");
41433b307c55SRasesh Mody 
41443b307c55SRasesh Mody 	for (i = 0; i < VF_BITMAP_SIZE_IN_DWORDS; i++)
414586a2265eSRasesh Mody 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
414686a2265eSRasesh Mody 			   "[%08x,...,%08x]: %08x\n",
414786a2265eSRasesh Mody 			   i * 32, (i + 1) * 32 - 1, p_disabled_vfs[i]);
414886a2265eSRasesh Mody 
414922d07d93SRasesh Mody 	if (!p_hwfn->p_dev->p_iov_info) {
415022d07d93SRasesh Mody 		DP_NOTICE(p_hwfn, true, "VF flr but no IOV\n");
415193fce904SRasesh Mody 		return false;
415222d07d93SRasesh Mody 	}
415322d07d93SRasesh Mody 
415486a2265eSRasesh Mody 	/* Mark VFs */
415522d07d93SRasesh Mody 	for (i = 0; i < p_hwfn->p_dev->p_iov_info->total_vfs; i++) {
415686a2265eSRasesh Mody 		struct ecore_vf_info *p_vf;
415786a2265eSRasesh Mody 		u8 vfid;
415886a2265eSRasesh Mody 
415986a2265eSRasesh Mody 		p_vf = ecore_iov_get_vf_info(p_hwfn, i, false);
416086a2265eSRasesh Mody 		if (!p_vf)
416186a2265eSRasesh Mody 			continue;
416286a2265eSRasesh Mody 
416386a2265eSRasesh Mody 		vfid = p_vf->abs_vf_id;
416486a2265eSRasesh Mody 		if ((1 << (vfid % 32)) & p_disabled_vfs[vfid / 32]) {
416586a2265eSRasesh Mody 			u64 *p_flr = p_hwfn->pf_iov_info->pending_flr;
416686a2265eSRasesh Mody 			u16 rel_vf_id = p_vf->relative_vf_id;
416786a2265eSRasesh Mody 
416886a2265eSRasesh Mody 			DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
416986a2265eSRasesh Mody 				   "VF[%d] [rel %d] got FLR-ed\n",
417086a2265eSRasesh Mody 				   vfid, rel_vf_id);
417186a2265eSRasesh Mody 
417286a2265eSRasesh Mody 			p_vf->state = VF_RESET;
417386a2265eSRasesh Mody 
417486a2265eSRasesh Mody 			/* No need to lock here, since pending_flr should
417586a2265eSRasesh Mody 			 * only change here and before ACKing MFw. Since
417686a2265eSRasesh Mody 			 * MFW will not trigger an additional attention for
417786a2265eSRasesh Mody 			 * VF flr until ACKs, we're safe.
417886a2265eSRasesh Mody 			 */
417986a2265eSRasesh Mody 			p_flr[rel_vf_id / 64] |= 1ULL << (rel_vf_id % 64);
418093fce904SRasesh Mody 			found = true;
418186a2265eSRasesh Mody 		}
418286a2265eSRasesh Mody 	}
418386a2265eSRasesh Mody 
418486a2265eSRasesh Mody 	return found;
418586a2265eSRasesh Mody }
418686a2265eSRasesh Mody 
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)418786a2265eSRasesh Mody void ecore_iov_get_link(struct ecore_hwfn *p_hwfn,
418886a2265eSRasesh Mody 			u16 vfid,
418986a2265eSRasesh Mody 			struct ecore_mcp_link_params *p_params,
419086a2265eSRasesh Mody 			struct ecore_mcp_link_state *p_link,
419186a2265eSRasesh Mody 			struct ecore_mcp_link_capabilities *p_caps)
419286a2265eSRasesh Mody {
419386a2265eSRasesh Mody 	struct ecore_vf_info *p_vf = ecore_iov_get_vf_info(p_hwfn, vfid, false);
419486a2265eSRasesh Mody 	struct ecore_bulletin_content *p_bulletin;
419586a2265eSRasesh Mody 
419686a2265eSRasesh Mody 	if (!p_vf)
419786a2265eSRasesh Mody 		return;
419886a2265eSRasesh Mody 
419986a2265eSRasesh Mody 	p_bulletin = p_vf->bulletin.p_virt;
420086a2265eSRasesh Mody 
420186a2265eSRasesh Mody 	if (p_params)
420230ecf673SRasesh Mody 		__ecore_vf_get_link_params(p_params, p_bulletin);
420386a2265eSRasesh Mody 	if (p_link)
420430ecf673SRasesh Mody 		__ecore_vf_get_link_state(p_link, p_bulletin);
420586a2265eSRasesh Mody 	if (p_caps)
420630ecf673SRasesh Mody 		__ecore_vf_get_link_caps(p_caps, p_bulletin);
420786a2265eSRasesh Mody }
420886a2265eSRasesh Mody 
ecore_iov_process_mbx_req(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,int vfid)420986a2265eSRasesh Mody void ecore_iov_process_mbx_req(struct ecore_hwfn *p_hwfn,
421086a2265eSRasesh Mody 			       struct ecore_ptt *p_ptt, int vfid)
421186a2265eSRasesh Mody {
421286a2265eSRasesh Mody 	struct ecore_iov_vf_mbx *mbx;
421386a2265eSRasesh Mody 	struct ecore_vf_info *p_vf;
421486a2265eSRasesh Mody 
421586a2265eSRasesh Mody 	p_vf = ecore_iov_get_vf_info(p_hwfn, (u16)vfid, true);
421686a2265eSRasesh Mody 	if (!p_vf)
421786a2265eSRasesh Mody 		return;
421886a2265eSRasesh Mody 
421986a2265eSRasesh Mody 	mbx = &p_vf->vf_mbx;
422086a2265eSRasesh Mody 
422186a2265eSRasesh Mody 	/* ecore_iov_process_mbx_request */
42224be18885SRasesh Mody #ifndef CONFIG_ECORE_SW_CHANNEL
42234be18885SRasesh Mody 	if (!mbx->b_pending_msg) {
42244be18885SRasesh Mody 		DP_NOTICE(p_hwfn, true,
42254be18885SRasesh Mody 			  "VF[%02x]: Trying to process mailbox message when none is pending\n",
42264be18885SRasesh Mody 			  p_vf->abs_vf_id);
42274be18885SRasesh Mody 		return;
42284be18885SRasesh Mody 	}
42294be18885SRasesh Mody 	mbx->b_pending_msg = false;
42304be18885SRasesh Mody #endif
423186a2265eSRasesh Mody 
423286a2265eSRasesh Mody 	mbx->first_tlv = mbx->req_virt->first_tlv;
423386a2265eSRasesh Mody 
42344be18885SRasesh Mody 	DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
42354be18885SRasesh Mody 		   "VF[%02x]: Processing mailbox message [type %04x]\n",
42364be18885SRasesh Mody 		   p_vf->abs_vf_id, mbx->first_tlv.tl.type);
42374be18885SRasesh Mody 
423822d07d93SRasesh Mody 	OSAL_IOV_VF_MSG_TYPE(p_hwfn,
423922d07d93SRasesh Mody 			     p_vf->relative_vf_id,
424022d07d93SRasesh Mody 			     mbx->first_tlv.tl.type);
424122d07d93SRasesh Mody 
424286a2265eSRasesh Mody 	/* Lock the per vf op mutex and note the locker's identity.
424386a2265eSRasesh Mody 	 * The unlock will take place in mbx response.
424486a2265eSRasesh Mody 	 */
424586a2265eSRasesh Mody 	ecore_iov_lock_vf_pf_channel(p_hwfn,
424686a2265eSRasesh Mody 				     p_vf, mbx->first_tlv.tl.type);
424786a2265eSRasesh Mody 
424822d07d93SRasesh Mody 	/* check if tlv type is known */
424947b302d6SRasesh Mody 	if (ecore_iov_tlv_supported(mbx->first_tlv.tl.type) &&
425047b302d6SRasesh Mody 	    !p_vf->b_malicious) {
425186a2265eSRasesh Mody 		/* switch on the opcode */
425286a2265eSRasesh Mody 		switch (mbx->first_tlv.tl.type) {
425386a2265eSRasesh Mody 		case CHANNEL_TLV_ACQUIRE:
425486a2265eSRasesh Mody 			ecore_iov_vf_mbx_acquire(p_hwfn, p_ptt, p_vf);
425586a2265eSRasesh Mody 			break;
425686a2265eSRasesh Mody 		case CHANNEL_TLV_VPORT_START:
425786a2265eSRasesh Mody 			ecore_iov_vf_mbx_start_vport(p_hwfn, p_ptt, p_vf);
425886a2265eSRasesh Mody 			break;
425986a2265eSRasesh Mody 		case CHANNEL_TLV_VPORT_TEARDOWN:
426086a2265eSRasesh Mody 			ecore_iov_vf_mbx_stop_vport(p_hwfn, p_ptt, p_vf);
426186a2265eSRasesh Mody 			break;
426286a2265eSRasesh Mody 		case CHANNEL_TLV_START_RXQ:
426386a2265eSRasesh Mody 			ecore_iov_vf_mbx_start_rxq(p_hwfn, p_ptt, p_vf);
426486a2265eSRasesh Mody 			break;
426586a2265eSRasesh Mody 		case CHANNEL_TLV_START_TXQ:
426686a2265eSRasesh Mody 			ecore_iov_vf_mbx_start_txq(p_hwfn, p_ptt, p_vf);
426786a2265eSRasesh Mody 			break;
426886a2265eSRasesh Mody 		case CHANNEL_TLV_STOP_RXQS:
426986a2265eSRasesh Mody 			ecore_iov_vf_mbx_stop_rxqs(p_hwfn, p_ptt, p_vf);
427086a2265eSRasesh Mody 			break;
427186a2265eSRasesh Mody 		case CHANNEL_TLV_STOP_TXQS:
427286a2265eSRasesh Mody 			ecore_iov_vf_mbx_stop_txqs(p_hwfn, p_ptt, p_vf);
427386a2265eSRasesh Mody 			break;
427486a2265eSRasesh Mody 		case CHANNEL_TLV_UPDATE_RXQ:
427586a2265eSRasesh Mody 			ecore_iov_vf_mbx_update_rxqs(p_hwfn, p_ptt, p_vf);
427686a2265eSRasesh Mody 			break;
427786a2265eSRasesh Mody 		case CHANNEL_TLV_VPORT_UPDATE:
427886a2265eSRasesh Mody 			ecore_iov_vf_mbx_vport_update(p_hwfn, p_ptt, p_vf);
427986a2265eSRasesh Mody 			break;
428086a2265eSRasesh Mody 		case CHANNEL_TLV_UCAST_FILTER:
428186a2265eSRasesh Mody 			ecore_iov_vf_mbx_ucast_filter(p_hwfn, p_ptt, p_vf);
428286a2265eSRasesh Mody 			break;
428386a2265eSRasesh Mody 		case CHANNEL_TLV_CLOSE:
428486a2265eSRasesh Mody 			ecore_iov_vf_mbx_close(p_hwfn, p_ptt, p_vf);
428586a2265eSRasesh Mody 			break;
428686a2265eSRasesh Mody 		case CHANNEL_TLV_INT_CLEANUP:
428786a2265eSRasesh Mody 			ecore_iov_vf_mbx_int_cleanup(p_hwfn, p_ptt, p_vf);
428886a2265eSRasesh Mody 			break;
428986a2265eSRasesh Mody 		case CHANNEL_TLV_RELEASE:
429086a2265eSRasesh Mody 			ecore_iov_vf_mbx_release(p_hwfn, p_ptt, p_vf);
429186a2265eSRasesh Mody 			break;
42920b090fd3SRasesh Mody 		case CHANNEL_TLV_UPDATE_TUNN_PARAM:
42930b090fd3SRasesh Mody 			ecore_iov_vf_mbx_update_tunn_param(p_hwfn, p_ptt, p_vf);
42940b090fd3SRasesh Mody 			break;
42956b8962e0SRasesh Mody 		case CHANNEL_TLV_COALESCE_UPDATE:
42966b8962e0SRasesh Mody 			ecore_iov_vf_pf_set_coalesce(p_hwfn, p_ptt, p_vf);
42976b8962e0SRasesh Mody 			break;
4298823a84aaSRasesh Mody 		case CHANNEL_TLV_COALESCE_READ:
4299823a84aaSRasesh Mody 			ecore_iov_vf_pf_get_coalesce(p_hwfn, p_ptt, p_vf);
4300823a84aaSRasesh Mody 			break;
4301d121a6b5SRasesh Mody 		case CHANNEL_TLV_UPDATE_MTU:
4302d121a6b5SRasesh Mody 			ecore_iov_vf_pf_update_mtu(p_hwfn, p_ptt, p_vf);
4303d121a6b5SRasesh Mody 			break;
430486a2265eSRasesh Mody 		}
430547b302d6SRasesh Mody 	} else if (ecore_iov_tlv_supported(mbx->first_tlv.tl.type)) {
430647b302d6SRasesh Mody 		/* If we've received a message from a VF we consider malicious
430747b302d6SRasesh Mody 		 * we ignore the messasge unless it's one for RELEASE, in which
430847b302d6SRasesh Mody 		 * case we'll let it have the benefit of doubt, allowing the
430947b302d6SRasesh Mody 		 * next loaded driver to start again.
431047b302d6SRasesh Mody 		 */
431147b302d6SRasesh Mody 		if (mbx->first_tlv.tl.type == CHANNEL_TLV_RELEASE) {
431247b302d6SRasesh Mody 			/* TODO - initiate FLR, remove malicious indication */
431347b302d6SRasesh Mody 			DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
431447b302d6SRasesh Mody 				   "VF [%02x] - considered malicious, but wanted to RELEASE. TODO\n",
431547b302d6SRasesh Mody 				   p_vf->abs_vf_id);
431647b302d6SRasesh Mody 		} else {
431747b302d6SRasesh Mody 			DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
431847b302d6SRasesh Mody 				   "VF [%02x] - considered malicious; Ignoring TLV [%04x]\n",
431947b302d6SRasesh Mody 				   p_vf->abs_vf_id, mbx->first_tlv.tl.type);
432047b302d6SRasesh Mody 		}
432147b302d6SRasesh Mody 
432247b302d6SRasesh Mody 		ecore_iov_prepare_resp(p_hwfn, p_ptt, p_vf,
432347b302d6SRasesh Mody 				       mbx->first_tlv.tl.type,
432447b302d6SRasesh Mody 				       sizeof(struct pfvf_def_resp_tlv),
432547b302d6SRasesh Mody 				       PFVF_STATUS_MALICIOUS);
432686a2265eSRasesh Mody 	} else {
432786a2265eSRasesh Mody 		/* unknown TLV - this may belong to a VF driver from the future
432886a2265eSRasesh Mody 		 * - a version written after this PF driver was written, which
432986a2265eSRasesh Mody 		 * supports features unknown as of yet. Too bad since we don't
433086a2265eSRasesh Mody 		 * support them. Or this may be because someone wrote a crappy
433186a2265eSRasesh Mody 		 * VF driver and is sending garbage over the channel.
433286a2265eSRasesh Mody 		 */
433322d07d93SRasesh Mody 		DP_NOTICE(p_hwfn, false,
433422d07d93SRasesh Mody 			  "VF[%02x]: unknown TLV. type %04x length %04x"
433522d07d93SRasesh Mody 			  " padding %08x reply address %lu\n",
433622d07d93SRasesh Mody 			  p_vf->abs_vf_id,
433722d07d93SRasesh Mody 			  mbx->first_tlv.tl.type,
433822d07d93SRasesh Mody 			  mbx->first_tlv.tl.length,
433922d07d93SRasesh Mody 			  mbx->first_tlv.padding,
434022d07d93SRasesh Mody 			  (unsigned long)mbx->first_tlv.reply_address);
434186a2265eSRasesh Mody 
434222d07d93SRasesh Mody 		/* Try replying in case reply address matches the acquisition's
434322d07d93SRasesh Mody 		 * posted address.
434486a2265eSRasesh Mody 		 */
434522d07d93SRasesh Mody 		if (p_vf->acquire.first_tlv.reply_address &&
434622d07d93SRasesh Mody 		    (mbx->first_tlv.reply_address ==
434722d07d93SRasesh Mody 		     p_vf->acquire.first_tlv.reply_address))
434822d07d93SRasesh Mody 			ecore_iov_prepare_resp(p_hwfn, p_ptt, p_vf,
434922d07d93SRasesh Mody 					       mbx->first_tlv.tl.type,
435022d07d93SRasesh Mody 					       sizeof(struct pfvf_def_resp_tlv),
435122d07d93SRasesh Mody 					       PFVF_STATUS_NOT_SUPPORTED);
435222d07d93SRasesh Mody 		else
435322d07d93SRasesh Mody 			DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
435422d07d93SRasesh Mody 				   "VF[%02x]: Can't respond to TLV -"
435522d07d93SRasesh Mody 				   " no valid reply address\n",
435622d07d93SRasesh Mody 				   p_vf->abs_vf_id);
435786a2265eSRasesh Mody 	}
435886a2265eSRasesh Mody 
435922d07d93SRasesh Mody 	ecore_iov_unlock_vf_pf_channel(p_hwfn, p_vf,
436022d07d93SRasesh Mody 				       mbx->first_tlv.tl.type);
436122d07d93SRasesh Mody 
436286a2265eSRasesh Mody #ifdef CONFIG_ECORE_SW_CHANNEL
436386a2265eSRasesh Mody 	mbx->sw_mbx.mbx_state = VF_PF_RESPONSE_READY;
436486a2265eSRasesh Mody 	mbx->sw_mbx.response_offset = 0;
436586a2265eSRasesh Mody #endif
436686a2265eSRasesh Mody }
436786a2265eSRasesh Mody 
ecore_iov_pf_get_pending_events(struct ecore_hwfn * p_hwfn,u64 * events)43684be18885SRasesh Mody void ecore_iov_pf_get_pending_events(struct ecore_hwfn *p_hwfn,
436986a2265eSRasesh Mody 				     u64 *events)
437086a2265eSRasesh Mody {
43714be18885SRasesh Mody 	int i;
437286a2265eSRasesh Mody 
43734be18885SRasesh Mody 	OSAL_MEM_ZERO(events, sizeof(u64) * ECORE_VF_ARRAY_LENGTH);
43744be18885SRasesh Mody 
43754be18885SRasesh Mody 	ecore_for_each_vf(p_hwfn, i) {
43764be18885SRasesh Mody 		struct ecore_vf_info *p_vf;
43774be18885SRasesh Mody 
43784be18885SRasesh Mody 		p_vf = &p_hwfn->pf_iov_info->vfs_array[i];
43794be18885SRasesh Mody 		if (p_vf->vf_mbx.b_pending_msg)
43804be18885SRasesh Mody 			events[i / 64] |= 1ULL << (i % 64);
43814be18885SRasesh Mody 	}
438222d07d93SRasesh Mody }
438322d07d93SRasesh Mody 
438447b302d6SRasesh Mody static struct ecore_vf_info *
ecore_sriov_get_vf_from_absid(struct ecore_hwfn * p_hwfn,u16 abs_vfid)438547b302d6SRasesh Mody ecore_sriov_get_vf_from_absid(struct ecore_hwfn *p_hwfn, u16 abs_vfid)
438647b302d6SRasesh Mody {
438747b302d6SRasesh Mody 	u8 min = (u8)p_hwfn->p_dev->p_iov_info->first_vf_in_pf;
438847b302d6SRasesh Mody 
438947b302d6SRasesh Mody 	if (!_ecore_iov_pf_sanity_check(p_hwfn, (int)abs_vfid - min, false)) {
439047b302d6SRasesh Mody 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
439147b302d6SRasesh Mody 			   "Got indication for VF [abs 0x%08x] that cannot be"
439247b302d6SRasesh Mody 			   " handled by PF\n",
439347b302d6SRasesh Mody 			   abs_vfid);
439447b302d6SRasesh Mody 		return OSAL_NULL;
439547b302d6SRasesh Mody 	}
439647b302d6SRasesh Mody 
439747b302d6SRasesh Mody 	return &p_hwfn->pf_iov_info->vfs_array[(u8)abs_vfid - min];
439847b302d6SRasesh Mody }
439947b302d6SRasesh Mody 
ecore_sriov_vfpf_msg(struct ecore_hwfn * p_hwfn,u16 abs_vfid,struct regpair * vf_msg)440022d07d93SRasesh Mody static enum _ecore_status_t ecore_sriov_vfpf_msg(struct ecore_hwfn *p_hwfn,
440122d07d93SRasesh Mody 						 u16 abs_vfid,
440222d07d93SRasesh Mody 						 struct regpair *vf_msg)
440322d07d93SRasesh Mody {
440447b302d6SRasesh Mody 	struct ecore_vf_info *p_vf = ecore_sriov_get_vf_from_absid(p_hwfn,
440522d07d93SRasesh Mody 								   abs_vfid);
440647b302d6SRasesh Mody 
440747b302d6SRasesh Mody 	if (!p_vf)
440822d07d93SRasesh Mody 		return ECORE_SUCCESS;
440922d07d93SRasesh Mody 
441022d07d93SRasesh Mody 	/* List the physical address of the request so that handler
441122d07d93SRasesh Mody 	 * could later on copy the message from it.
441222d07d93SRasesh Mody 	 */
441322d07d93SRasesh Mody 	p_vf->vf_mbx.pending_req = (((u64)vf_msg->hi) << 32) | vf_msg->lo;
441422d07d93SRasesh Mody 
44154be18885SRasesh Mody 	p_vf->vf_mbx.b_pending_msg = true;
44164be18885SRasesh Mody 
441722d07d93SRasesh Mody 	return OSAL_PF_VF_MSG(p_hwfn, p_vf->relative_vf_id);
441822d07d93SRasesh Mody }
441922d07d93SRasesh Mody 
ecore_sriov_vfpf_malicious(struct ecore_hwfn * p_hwfn,struct malicious_vf_eqe_data * p_data)442047b302d6SRasesh Mody static void ecore_sriov_vfpf_malicious(struct ecore_hwfn *p_hwfn,
442147b302d6SRasesh Mody 				       struct malicious_vf_eqe_data *p_data)
442247b302d6SRasesh Mody {
442347b302d6SRasesh Mody 	struct ecore_vf_info *p_vf;
442447b302d6SRasesh Mody 
442585dfd0c5SRasesh Mody 	p_vf = ecore_sriov_get_vf_from_absid(p_hwfn, p_data->vf_id);
442647b302d6SRasesh Mody 
442747b302d6SRasesh Mody 	if (!p_vf)
442847b302d6SRasesh Mody 		return;
442947b302d6SRasesh Mody 
443085dfd0c5SRasesh Mody 	if (!p_vf->b_malicious) {
443185dfd0c5SRasesh Mody 		DP_NOTICE(p_hwfn, false,
443247b302d6SRasesh Mody 			  "VF [%d] - Malicious behavior [%02x]\n",
443385dfd0c5SRasesh Mody 			  p_vf->abs_vf_id, p_data->err_id);
443447b302d6SRasesh Mody 
443547b302d6SRasesh Mody 		p_vf->b_malicious = true;
443685dfd0c5SRasesh Mody 	} else {
443785dfd0c5SRasesh Mody 		DP_INFO(p_hwfn,
443885dfd0c5SRasesh Mody 			"VF [%d] - Malicious behavior [%02x]\n",
443985dfd0c5SRasesh Mody 			p_vf->abs_vf_id, p_data->err_id);
444085dfd0c5SRasesh Mody 	}
444147b302d6SRasesh Mody 
444247b302d6SRasesh Mody 	OSAL_PF_VF_MALICIOUS(p_hwfn, p_vf->relative_vf_id);
444347b302d6SRasesh Mody }
444447b302d6SRasesh Mody 
ecore_sriov_eqe_event(struct ecore_hwfn * p_hwfn,u8 opcode,__le16 echo,union event_ring_data * data,u8 OSAL_UNUSED fw_return_code)44457f474588SRasesh Mody static enum _ecore_status_t ecore_sriov_eqe_event(struct ecore_hwfn *p_hwfn,
444622d07d93SRasesh Mody 						  u8 opcode,
444722d07d93SRasesh Mody 						  __le16 echo,
44487f474588SRasesh Mody 						  union event_ring_data *data,
44497f474588SRasesh Mody 						  u8 OSAL_UNUSED fw_return_code)
445022d07d93SRasesh Mody {
445122d07d93SRasesh Mody 	switch (opcode) {
445222d07d93SRasesh Mody 	case COMMON_EVENT_VF_PF_CHANNEL:
445322d07d93SRasesh Mody 		return ecore_sriov_vfpf_msg(p_hwfn, OSAL_LE16_TO_CPU(echo),
445422d07d93SRasesh Mody 					    &data->vf_pf_channel.msg_addr);
445522d07d93SRasesh Mody 	case COMMON_EVENT_VF_FLR:
445622d07d93SRasesh Mody 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
445722d07d93SRasesh Mody 			   "VF-FLR is still not supported\n");
445822d07d93SRasesh Mody 		return ECORE_SUCCESS;
445947b302d6SRasesh Mody 	case COMMON_EVENT_MALICIOUS_VF:
446047b302d6SRasesh Mody 		ecore_sriov_vfpf_malicious(p_hwfn, &data->malicious_vf);
446147b302d6SRasesh Mody 		return ECORE_SUCCESS;
446222d07d93SRasesh Mody 	default:
446322d07d93SRasesh Mody 		DP_INFO(p_hwfn->p_dev, "Unknown sriov eqe event 0x%02x\n",
446422d07d93SRasesh Mody 			opcode);
446522d07d93SRasesh Mody 		return ECORE_INVAL;
446622d07d93SRasesh Mody 	}
446722d07d93SRasesh Mody }
446822d07d93SRasesh Mody 
ecore_iov_is_vf_pending_flr(struct ecore_hwfn * p_hwfn,u16 rel_vf_id)446922d07d93SRasesh Mody bool ecore_iov_is_vf_pending_flr(struct ecore_hwfn *p_hwfn, u16 rel_vf_id)
447022d07d93SRasesh Mody {
447122d07d93SRasesh Mody 	return !!(p_hwfn->pf_iov_info->pending_flr[rel_vf_id / 64] &
447222d07d93SRasesh Mody 		   (1ULL << (rel_vf_id % 64)));
447322d07d93SRasesh Mody }
447422d07d93SRasesh Mody 
ecore_iov_get_next_active_vf(struct ecore_hwfn * p_hwfn,u16 rel_vf_id)447522d07d93SRasesh Mody u16 ecore_iov_get_next_active_vf(struct ecore_hwfn *p_hwfn, u16 rel_vf_id)
447622d07d93SRasesh Mody {
447722d07d93SRasesh Mody 	struct ecore_hw_sriov_info *p_iov = p_hwfn->p_dev->p_iov_info;
447822d07d93SRasesh Mody 	u16 i;
447922d07d93SRasesh Mody 
448022d07d93SRasesh Mody 	if (!p_iov)
448122d07d93SRasesh Mody 		goto out;
448222d07d93SRasesh Mody 
448322d07d93SRasesh Mody 	for (i = rel_vf_id; i < p_iov->total_vfs; i++)
448447b302d6SRasesh Mody 		if (ecore_iov_is_valid_vfid(p_hwfn, rel_vf_id, true, false))
448522d07d93SRasesh Mody 			return i;
448622d07d93SRasesh Mody 
448722d07d93SRasesh Mody out:
448852fa735cSRasesh Mody 	return MAX_NUM_VFS_K2;
448986a2265eSRasesh Mody }
449086a2265eSRasesh Mody 
ecore_iov_copy_vf_msg(struct ecore_hwfn * p_hwfn,struct ecore_ptt * ptt,int vfid)449186a2265eSRasesh Mody enum _ecore_status_t ecore_iov_copy_vf_msg(struct ecore_hwfn *p_hwfn,
449286a2265eSRasesh Mody 					   struct ecore_ptt *ptt, int vfid)
449386a2265eSRasesh Mody {
4494ea85629fSRasesh Mody 	struct dmae_params params;
449586a2265eSRasesh Mody 	struct ecore_vf_info *vf_info;
449686a2265eSRasesh Mody 
449786a2265eSRasesh Mody 	vf_info = ecore_iov_get_vf_info(p_hwfn, (u16)vfid, true);
449886a2265eSRasesh Mody 	if (!vf_info)
449986a2265eSRasesh Mody 		return ECORE_INVAL;
450086a2265eSRasesh Mody 
45013b307c55SRasesh Mody 	OSAL_MEMSET(&params, 0, sizeof(params));
4502ea85629fSRasesh Mody 	SET_FIELD(params.flags, DMAE_PARAMS_SRC_VF_VALID, 0x1);
4503ea85629fSRasesh Mody 	SET_FIELD(params.flags, DMAE_PARAMS_COMPLETION_DST, 0x1);
4504ea85629fSRasesh Mody 	params.src_vf_id = vf_info->abs_vf_id;
450586a2265eSRasesh Mody 
450686a2265eSRasesh Mody 	if (ecore_dmae_host2host(p_hwfn, ptt,
450786a2265eSRasesh Mody 				 vf_info->vf_mbx.pending_req,
450886a2265eSRasesh Mody 				 vf_info->vf_mbx.req_phys,
450986a2265eSRasesh Mody 				 sizeof(union vfpf_tlvs) / 4, &params)) {
451086a2265eSRasesh Mody 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
451186a2265eSRasesh Mody 			   "Failed to copy message from VF 0x%02x\n", vfid);
451286a2265eSRasesh Mody 
451386a2265eSRasesh Mody 		return ECORE_IO;
451486a2265eSRasesh Mody 	}
451586a2265eSRasesh Mody 
451686a2265eSRasesh Mody 	return ECORE_SUCCESS;
451786a2265eSRasesh Mody }
451886a2265eSRasesh Mody 
ecore_iov_bulletin_set_forced_mac(struct ecore_hwfn * p_hwfn,u8 * mac,int vfid)451986a2265eSRasesh Mody void ecore_iov_bulletin_set_forced_mac(struct ecore_hwfn *p_hwfn,
452086a2265eSRasesh Mody 				       u8 *mac, int vfid)
452186a2265eSRasesh Mody {
452286a2265eSRasesh Mody 	struct ecore_vf_info *vf_info;
452386a2265eSRasesh Mody 	u64 feature;
452486a2265eSRasesh Mody 
452586a2265eSRasesh Mody 	vf_info = ecore_iov_get_vf_info(p_hwfn, (u16)vfid, true);
452686a2265eSRasesh Mody 	if (!vf_info) {
452786a2265eSRasesh Mody 		DP_NOTICE(p_hwfn->p_dev, true,
452886a2265eSRasesh Mody 			  "Can not set forced MAC, invalid vfid [%d]\n", vfid);
452986a2265eSRasesh Mody 		return;
453086a2265eSRasesh Mody 	}
453147b302d6SRasesh Mody 	if (vf_info->b_malicious) {
453247b302d6SRasesh Mody 		DP_NOTICE(p_hwfn->p_dev, false,
453347b302d6SRasesh Mody 			  "Can't set forced MAC to malicious VF [%d]\n",
453447b302d6SRasesh Mody 			  vfid);
453547b302d6SRasesh Mody 		return;
453647b302d6SRasesh Mody 	}
453786a2265eSRasesh Mody 
45382cf7a0faSShahed Shaikh 	if (p_hwfn->pf_params.eth_pf_params.allow_vf_mac_change ||
45392cf7a0faSShahed Shaikh 	    vf_info->p_vf_info.is_trusted_configured) {
4540d5050d4dSRasesh Mody 		feature = 1 << VFPF_BULLETIN_MAC_ADDR;
45412cf7a0faSShahed Shaikh 		/* Trust mode will disable Forced MAC */
45422cf7a0faSShahed Shaikh 		vf_info->bulletin.p_virt->valid_bitmap &=
45432cf7a0faSShahed Shaikh 			~(1 << MAC_ADDR_FORCED);
45442cf7a0faSShahed Shaikh 	} else {
454586a2265eSRasesh Mody 		feature = 1 << MAC_ADDR_FORCED;
454686a2265eSRasesh Mody 		/* Forced MAC will disable MAC_ADDR */
454786a2265eSRasesh Mody 		vf_info->bulletin.p_virt->valid_bitmap &=
454886a2265eSRasesh Mody 			~(1 << VFPF_BULLETIN_MAC_ADDR);
45492cf7a0faSShahed Shaikh 	}
45502cf7a0faSShahed Shaikh 
45512cf7a0faSShahed Shaikh 	OSAL_MEMCPY(vf_info->bulletin.p_virt->mac,
45522cf7a0faSShahed Shaikh 		    mac, ETH_ALEN);
45532cf7a0faSShahed Shaikh 
45542cf7a0faSShahed Shaikh 	vf_info->bulletin.p_virt->valid_bitmap |= feature;
455586a2265eSRasesh Mody 
455686a2265eSRasesh Mody 	ecore_iov_configure_vport_forced(p_hwfn, vf_info, feature);
455786a2265eSRasesh Mody }
455886a2265eSRasesh Mody 
ecore_iov_bulletin_set_mac(struct ecore_hwfn * p_hwfn,u8 * mac,int vfid)455986a2265eSRasesh Mody enum _ecore_status_t ecore_iov_bulletin_set_mac(struct ecore_hwfn *p_hwfn,
456086a2265eSRasesh Mody 						u8 *mac, int vfid)
456186a2265eSRasesh Mody {
456286a2265eSRasesh Mody 	struct ecore_vf_info *vf_info;
456386a2265eSRasesh Mody 	u64 feature;
456486a2265eSRasesh Mody 
456586a2265eSRasesh Mody 	vf_info = ecore_iov_get_vf_info(p_hwfn, (u16)vfid, true);
456686a2265eSRasesh Mody 	if (!vf_info) {
456786a2265eSRasesh Mody 		DP_NOTICE(p_hwfn->p_dev, true,
456886a2265eSRasesh Mody 			  "Can not set MAC, invalid vfid [%d]\n", vfid);
456986a2265eSRasesh Mody 		return ECORE_INVAL;
457086a2265eSRasesh Mody 	}
457147b302d6SRasesh Mody 	if (vf_info->b_malicious) {
457247b302d6SRasesh Mody 		DP_NOTICE(p_hwfn->p_dev, false,
457347b302d6SRasesh Mody 			  "Can't set MAC to malicious VF [%d]\n",
457447b302d6SRasesh Mody 			  vfid);
457547b302d6SRasesh Mody 		return ECORE_INVAL;
457647b302d6SRasesh Mody 	}
457786a2265eSRasesh Mody 
457886a2265eSRasesh Mody 	if (vf_info->bulletin.p_virt->valid_bitmap & (1 << MAC_ADDR_FORCED)) {
457986a2265eSRasesh Mody 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
458086a2265eSRasesh Mody 			   "Can not set MAC, Forced MAC is configured\n");
458186a2265eSRasesh Mody 		return ECORE_INVAL;
458286a2265eSRasesh Mody 	}
458386a2265eSRasesh Mody 
458486a2265eSRasesh Mody 	feature = 1 << VFPF_BULLETIN_MAC_ADDR;
458586a2265eSRasesh Mody 	OSAL_MEMCPY(vf_info->bulletin.p_virt->mac, mac, ETH_ALEN);
458686a2265eSRasesh Mody 
458786a2265eSRasesh Mody 	vf_info->bulletin.p_virt->valid_bitmap |= feature;
458886a2265eSRasesh Mody 
45892cf7a0faSShahed Shaikh 	if (p_hwfn->pf_params.eth_pf_params.allow_vf_mac_change ||
45902cf7a0faSShahed Shaikh 	    vf_info->p_vf_info.is_trusted_configured)
4591d5050d4dSRasesh Mody 		ecore_iov_configure_vport_forced(p_hwfn, vf_info, feature);
4592d5050d4dSRasesh Mody 
459386a2265eSRasesh Mody 	return ECORE_SUCCESS;
459486a2265eSRasesh Mody }
459586a2265eSRasesh Mody 
4596d5050d4dSRasesh Mody #ifndef LINUX_REMOVE
459786a2265eSRasesh Mody enum _ecore_status_t
ecore_iov_bulletin_set_forced_untagged_default(struct ecore_hwfn * p_hwfn,bool b_untagged_only,int vfid)459886a2265eSRasesh Mody ecore_iov_bulletin_set_forced_untagged_default(struct ecore_hwfn *p_hwfn,
459986a2265eSRasesh Mody 					       bool b_untagged_only, int vfid)
460086a2265eSRasesh Mody {
460186a2265eSRasesh Mody 	struct ecore_vf_info *vf_info;
460286a2265eSRasesh Mody 	u64 feature;
460386a2265eSRasesh Mody 
460486a2265eSRasesh Mody 	vf_info = ecore_iov_get_vf_info(p_hwfn, (u16)vfid, true);
460586a2265eSRasesh Mody 	if (!vf_info) {
460686a2265eSRasesh Mody 		DP_NOTICE(p_hwfn->p_dev, true,
460747b302d6SRasesh Mody 			  "Can not set untagged default, invalid vfid [%d]\n",
460847b302d6SRasesh Mody 			  vfid);
460947b302d6SRasesh Mody 		return ECORE_INVAL;
461047b302d6SRasesh Mody 	}
461147b302d6SRasesh Mody 	if (vf_info->b_malicious) {
461247b302d6SRasesh Mody 		DP_NOTICE(p_hwfn->p_dev, false,
461347b302d6SRasesh Mody 			  "Can't set untagged default to malicious VF [%d]\n",
461447b302d6SRasesh Mody 			  vfid);
461586a2265eSRasesh Mody 		return ECORE_INVAL;
461686a2265eSRasesh Mody 	}
461786a2265eSRasesh Mody 
461886a2265eSRasesh Mody 	/* Since this is configurable only during vport-start, don't take it
461986a2265eSRasesh Mody 	 * if we're past that point.
462086a2265eSRasesh Mody 	 */
462186a2265eSRasesh Mody 	if (vf_info->state == VF_ENABLED) {
462286a2265eSRasesh Mody 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
462322d07d93SRasesh Mody 			   "Can't support untagged change for vfid[%d] -"
462422d07d93SRasesh Mody 			   " VF is already active\n",
462586a2265eSRasesh Mody 			   vfid);
462686a2265eSRasesh Mody 		return ECORE_INVAL;
462786a2265eSRasesh Mody 	}
462886a2265eSRasesh Mody 
462986a2265eSRasesh Mody 	/* Set configuration; This will later be taken into account during the
463086a2265eSRasesh Mody 	 * VF initialization.
463186a2265eSRasesh Mody 	 */
463286a2265eSRasesh Mody 	feature = (1 << VFPF_BULLETIN_UNTAGGED_DEFAULT) |
463386a2265eSRasesh Mody 	    (1 << VFPF_BULLETIN_UNTAGGED_DEFAULT_FORCED);
463486a2265eSRasesh Mody 	vf_info->bulletin.p_virt->valid_bitmap |= feature;
463586a2265eSRasesh Mody 
463686a2265eSRasesh Mody 	vf_info->bulletin.p_virt->default_only_untagged = b_untagged_only ? 1
463786a2265eSRasesh Mody 	    : 0;
463886a2265eSRasesh Mody 
463986a2265eSRasesh Mody 	return ECORE_SUCCESS;
464086a2265eSRasesh Mody }
464186a2265eSRasesh Mody 
ecore_iov_get_vfs_opaque_fid(struct ecore_hwfn * p_hwfn,int vfid,u16 * opaque_fid)464286a2265eSRasesh Mody void ecore_iov_get_vfs_opaque_fid(struct ecore_hwfn *p_hwfn, int vfid,
464386a2265eSRasesh Mody 				  u16 *opaque_fid)
464486a2265eSRasesh Mody {
464586a2265eSRasesh Mody 	struct ecore_vf_info *vf_info;
464686a2265eSRasesh Mody 
464786a2265eSRasesh Mody 	vf_info = ecore_iov_get_vf_info(p_hwfn, (u16)vfid, true);
464886a2265eSRasesh Mody 	if (!vf_info)
464986a2265eSRasesh Mody 		return;
465086a2265eSRasesh Mody 
465186a2265eSRasesh Mody 	*opaque_fid = vf_info->opaque_fid;
465286a2265eSRasesh Mody }
4653d5050d4dSRasesh Mody #endif
465486a2265eSRasesh Mody 
ecore_iov_bulletin_set_forced_vlan(struct ecore_hwfn * p_hwfn,u16 pvid,int vfid)465522d07d93SRasesh Mody void ecore_iov_bulletin_set_forced_vlan(struct ecore_hwfn *p_hwfn,
465622d07d93SRasesh Mody 					u16 pvid, int vfid)
465722d07d93SRasesh Mody {
465822d07d93SRasesh Mody 	struct ecore_vf_info *vf_info;
465922d07d93SRasesh Mody 	u64 feature;
466022d07d93SRasesh Mody 
466122d07d93SRasesh Mody 	vf_info = ecore_iov_get_vf_info(p_hwfn, (u16)vfid, true);
466222d07d93SRasesh Mody 	if (!vf_info) {
466322d07d93SRasesh Mody 		DP_NOTICE(p_hwfn->p_dev, true,
466422d07d93SRasesh Mody 			  "Can not set forced MAC, invalid vfid [%d]\n",
466522d07d93SRasesh Mody 			  vfid);
466622d07d93SRasesh Mody 		return;
466722d07d93SRasesh Mody 	}
466847b302d6SRasesh Mody 	if (vf_info->b_malicious) {
466947b302d6SRasesh Mody 		DP_NOTICE(p_hwfn->p_dev, false,
467047b302d6SRasesh Mody 			  "Can't set forced vlan to malicious VF [%d]\n",
467147b302d6SRasesh Mody 			  vfid);
467247b302d6SRasesh Mody 		return;
467347b302d6SRasesh Mody 	}
467422d07d93SRasesh Mody 
467522d07d93SRasesh Mody 	feature = 1 << VLAN_ADDR_FORCED;
467622d07d93SRasesh Mody 	vf_info->bulletin.p_virt->pvid = pvid;
467722d07d93SRasesh Mody 	if (pvid)
467822d07d93SRasesh Mody 		vf_info->bulletin.p_virt->valid_bitmap |= feature;
467922d07d93SRasesh Mody 	else
468022d07d93SRasesh Mody 		vf_info->bulletin.p_virt->valid_bitmap &= ~feature;
468122d07d93SRasesh Mody 
468222d07d93SRasesh Mody 	ecore_iov_configure_vport_forced(p_hwfn, vf_info, feature);
468322d07d93SRasesh Mody }
468422d07d93SRasesh Mody 
ecore_iov_bulletin_set_udp_ports(struct ecore_hwfn * p_hwfn,int vfid,u16 vxlan_port,u16 geneve_port)46854727343dSRasesh Mody void ecore_iov_bulletin_set_udp_ports(struct ecore_hwfn *p_hwfn,
46864727343dSRasesh Mody 				      int vfid, u16 vxlan_port, u16 geneve_port)
46874727343dSRasesh Mody {
46884727343dSRasesh Mody 	struct ecore_vf_info *vf_info;
46894727343dSRasesh Mody 
46904727343dSRasesh Mody 	vf_info = ecore_iov_get_vf_info(p_hwfn, (u16)vfid, true);
46914727343dSRasesh Mody 	if (!vf_info) {
46924727343dSRasesh Mody 		DP_NOTICE(p_hwfn->p_dev, true,
46934727343dSRasesh Mody 			  "Can not set udp ports, invalid vfid [%d]\n", vfid);
46944727343dSRasesh Mody 		return;
46954727343dSRasesh Mody 	}
46964727343dSRasesh Mody 
46974727343dSRasesh Mody 	if (vf_info->b_malicious) {
46984727343dSRasesh Mody 		DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
46994727343dSRasesh Mody 			   "Can not set udp ports to malicious VF [%d]\n",
47004727343dSRasesh Mody 			   vfid);
47014727343dSRasesh Mody 		return;
47024727343dSRasesh Mody 	}
47034727343dSRasesh Mody 
47044727343dSRasesh Mody 	vf_info->bulletin.p_virt->vxlan_udp_port = vxlan_port;
47054727343dSRasesh Mody 	vf_info->bulletin.p_virt->geneve_udp_port = geneve_port;
47064727343dSRasesh Mody }
47074727343dSRasesh Mody 
ecore_iov_vf_has_vport_instance(struct ecore_hwfn * p_hwfn,int vfid)470886a2265eSRasesh Mody bool ecore_iov_vf_has_vport_instance(struct ecore_hwfn *p_hwfn, int vfid)
470986a2265eSRasesh Mody {
471086a2265eSRasesh Mody 	struct ecore_vf_info *p_vf_info;
471186a2265eSRasesh Mody 
471286a2265eSRasesh Mody 	p_vf_info = ecore_iov_get_vf_info(p_hwfn, (u16)vfid, true);
471386a2265eSRasesh Mody 	if (!p_vf_info)
471486a2265eSRasesh Mody 		return false;
471586a2265eSRasesh Mody 
471686a2265eSRasesh Mody 	return !!p_vf_info->vport_instance;
471786a2265eSRasesh Mody }
471886a2265eSRasesh Mody 
ecore_iov_is_vf_stopped(struct ecore_hwfn * p_hwfn,int vfid)471986a2265eSRasesh Mody bool ecore_iov_is_vf_stopped(struct ecore_hwfn *p_hwfn, int vfid)
472086a2265eSRasesh Mody {
472186a2265eSRasesh Mody 	struct ecore_vf_info *p_vf_info;
472286a2265eSRasesh Mody 
472386a2265eSRasesh Mody 	p_vf_info = ecore_iov_get_vf_info(p_hwfn, (u16)vfid, true);
472422d07d93SRasesh Mody 	if (!p_vf_info)
472522d07d93SRasesh Mody 		return true;
472686a2265eSRasesh Mody 
472786a2265eSRasesh Mody 	return p_vf_info->state == VF_STOPPED;
472886a2265eSRasesh Mody }
472986a2265eSRasesh Mody 
ecore_iov_spoofchk_get(struct ecore_hwfn * p_hwfn,int vfid)473086a2265eSRasesh Mody bool ecore_iov_spoofchk_get(struct ecore_hwfn *p_hwfn, int vfid)
473186a2265eSRasesh Mody {
473286a2265eSRasesh Mody 	struct ecore_vf_info *vf_info;
473386a2265eSRasesh Mody 
473486a2265eSRasesh Mody 	vf_info = ecore_iov_get_vf_info(p_hwfn, (u16)vfid, true);
473586a2265eSRasesh Mody 	if (!vf_info)
473686a2265eSRasesh Mody 		return false;
473786a2265eSRasesh Mody 
473886a2265eSRasesh Mody 	return vf_info->spoof_chk;
473986a2265eSRasesh Mody }
474086a2265eSRasesh Mody 
ecore_iov_spoofchk_set(struct ecore_hwfn * p_hwfn,int vfid,bool val)474186a2265eSRasesh Mody enum _ecore_status_t ecore_iov_spoofchk_set(struct ecore_hwfn *p_hwfn,
474286a2265eSRasesh Mody 					    int vfid, bool val)
474386a2265eSRasesh Mody {
474486a2265eSRasesh Mody 	struct ecore_vf_info *vf;
474522d07d93SRasesh Mody 	enum _ecore_status_t rc = ECORE_INVAL;
474686a2265eSRasesh Mody 
474786a2265eSRasesh Mody 	if (!ecore_iov_pf_sanity_check(p_hwfn, vfid)) {
474886a2265eSRasesh Mody 		DP_NOTICE(p_hwfn, true,
474986a2265eSRasesh Mody 			  "SR-IOV sanity check failed, can't set spoofchk\n");
475086a2265eSRasesh Mody 		goto out;
475186a2265eSRasesh Mody 	}
475286a2265eSRasesh Mody 
475386a2265eSRasesh Mody 	vf = ecore_iov_get_vf_info(p_hwfn, (u16)vfid, true);
475486a2265eSRasesh Mody 	if (!vf)
475586a2265eSRasesh Mody 		goto out;
475686a2265eSRasesh Mody 
475786a2265eSRasesh Mody 	if (!ecore_iov_vf_has_vport_instance(p_hwfn, vfid)) {
475886a2265eSRasesh Mody 		/* After VF VPORT start PF will configure spoof check */
475986a2265eSRasesh Mody 		vf->req_spoofchk_val = val;
476086a2265eSRasesh Mody 		rc = ECORE_SUCCESS;
476186a2265eSRasesh Mody 		goto out;
476286a2265eSRasesh Mody 	}
476386a2265eSRasesh Mody 
476486a2265eSRasesh Mody 	rc = __ecore_iov_spoofchk_set(p_hwfn, vf, val);
476586a2265eSRasesh Mody 
476686a2265eSRasesh Mody out:
476786a2265eSRasesh Mody 	return rc;
476886a2265eSRasesh Mody }
476986a2265eSRasesh Mody 
ecore_iov_vf_chains_per_pf(struct ecore_hwfn * p_hwfn)477086a2265eSRasesh Mody u8 ecore_iov_vf_chains_per_pf(struct ecore_hwfn *p_hwfn)
477186a2265eSRasesh Mody {
477286a2265eSRasesh Mody 	u8 max_chains_per_vf = p_hwfn->hw_info.max_chains_per_vf;
477386a2265eSRasesh Mody 
477486a2265eSRasesh Mody 	max_chains_per_vf = (max_chains_per_vf) ? max_chains_per_vf
477586a2265eSRasesh Mody 	    : ECORE_MAX_VF_CHAINS_PER_PF;
477686a2265eSRasesh Mody 
477786a2265eSRasesh Mody 	return max_chains_per_vf;
477886a2265eSRasesh Mody }
477986a2265eSRasesh Mody 
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)478086a2265eSRasesh Mody void ecore_iov_get_vf_req_virt_mbx_params(struct ecore_hwfn *p_hwfn,
478186a2265eSRasesh Mody 					  u16 rel_vf_id,
478286a2265eSRasesh Mody 					  void **pp_req_virt_addr,
478386a2265eSRasesh Mody 					  u16 *p_req_virt_size)
478486a2265eSRasesh Mody {
478586a2265eSRasesh Mody 	struct ecore_vf_info *vf_info =
478686a2265eSRasesh Mody 	    ecore_iov_get_vf_info(p_hwfn, rel_vf_id, true);
478786a2265eSRasesh Mody 
478886a2265eSRasesh Mody 	if (!vf_info)
478986a2265eSRasesh Mody 		return;
479086a2265eSRasesh Mody 
479186a2265eSRasesh Mody 	if (pp_req_virt_addr)
479286a2265eSRasesh Mody 		*pp_req_virt_addr = vf_info->vf_mbx.req_virt;
479386a2265eSRasesh Mody 
479486a2265eSRasesh Mody 	if (p_req_virt_size)
479586a2265eSRasesh Mody 		*p_req_virt_size = sizeof(*vf_info->vf_mbx.req_virt);
479686a2265eSRasesh Mody }
479786a2265eSRasesh Mody 
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)479886a2265eSRasesh Mody void ecore_iov_get_vf_reply_virt_mbx_params(struct ecore_hwfn *p_hwfn,
479986a2265eSRasesh Mody 					    u16 rel_vf_id,
480086a2265eSRasesh Mody 					    void **pp_reply_virt_addr,
480186a2265eSRasesh Mody 					    u16 *p_reply_virt_size)
480286a2265eSRasesh Mody {
480386a2265eSRasesh Mody 	struct ecore_vf_info *vf_info =
480486a2265eSRasesh Mody 	    ecore_iov_get_vf_info(p_hwfn, rel_vf_id, true);
480586a2265eSRasesh Mody 
480686a2265eSRasesh Mody 	if (!vf_info)
480786a2265eSRasesh Mody 		return;
480886a2265eSRasesh Mody 
480986a2265eSRasesh Mody 	if (pp_reply_virt_addr)
481086a2265eSRasesh Mody 		*pp_reply_virt_addr = vf_info->vf_mbx.reply_virt;
481186a2265eSRasesh Mody 
481286a2265eSRasesh Mody 	if (p_reply_virt_size)
481386a2265eSRasesh Mody 		*p_reply_virt_size = sizeof(*vf_info->vf_mbx.reply_virt);
481486a2265eSRasesh Mody }
481586a2265eSRasesh Mody 
481686a2265eSRasesh Mody #ifdef CONFIG_ECORE_SW_CHANNEL
ecore_iov_get_vf_sw_mbx(struct ecore_hwfn * p_hwfn,u16 rel_vf_id)481786a2265eSRasesh Mody struct ecore_iov_sw_mbx *ecore_iov_get_vf_sw_mbx(struct ecore_hwfn *p_hwfn,
481886a2265eSRasesh Mody 						 u16 rel_vf_id)
481986a2265eSRasesh Mody {
482086a2265eSRasesh Mody 	struct ecore_vf_info *vf_info =
482186a2265eSRasesh Mody 	    ecore_iov_get_vf_info(p_hwfn, rel_vf_id, true);
482286a2265eSRasesh Mody 
482386a2265eSRasesh Mody 	if (!vf_info)
482486a2265eSRasesh Mody 		return OSAL_NULL;
482586a2265eSRasesh Mody 
482686a2265eSRasesh Mody 	return &vf_info->vf_mbx.sw_mbx;
482786a2265eSRasesh Mody }
482886a2265eSRasesh Mody #endif
482986a2265eSRasesh Mody 
ecore_iov_is_valid_vfpf_msg_length(u32 length)483086a2265eSRasesh Mody bool ecore_iov_is_valid_vfpf_msg_length(u32 length)
483186a2265eSRasesh Mody {
483286a2265eSRasesh Mody 	return (length >= sizeof(struct vfpf_first_tlv) &&
483386a2265eSRasesh Mody 		(length <= sizeof(union vfpf_tlvs)));
483486a2265eSRasesh Mody }
483586a2265eSRasesh Mody 
ecore_iov_pfvf_msg_length(void)483686a2265eSRasesh Mody u32 ecore_iov_pfvf_msg_length(void)
483786a2265eSRasesh Mody {
483886a2265eSRasesh Mody 	return sizeof(union pfvf_tlvs);
483986a2265eSRasesh Mody }
484086a2265eSRasesh Mody 
ecore_iov_bulletin_get_mac(struct ecore_hwfn * p_hwfn,u16 rel_vf_id)4841d5050d4dSRasesh Mody u8 *ecore_iov_bulletin_get_mac(struct ecore_hwfn *p_hwfn,
4842d5050d4dSRasesh Mody 				      u16 rel_vf_id)
4843d5050d4dSRasesh Mody {
4844d5050d4dSRasesh Mody 	struct ecore_vf_info *p_vf;
4845d5050d4dSRasesh Mody 
4846d5050d4dSRasesh Mody 	p_vf = ecore_iov_get_vf_info(p_hwfn, rel_vf_id, true);
4847d5050d4dSRasesh Mody 	if (!p_vf || !p_vf->bulletin.p_virt)
4848d5050d4dSRasesh Mody 		return OSAL_NULL;
4849d5050d4dSRasesh Mody 
4850d5050d4dSRasesh Mody 	if (!(p_vf->bulletin.p_virt->valid_bitmap &
4851d5050d4dSRasesh Mody 		(1 << VFPF_BULLETIN_MAC_ADDR)))
4852d5050d4dSRasesh Mody 		return OSAL_NULL;
4853d5050d4dSRasesh Mody 
4854d5050d4dSRasesh Mody 	return p_vf->bulletin.p_virt->mac;
4855d5050d4dSRasesh Mody }
4856d5050d4dSRasesh Mody 
ecore_iov_bulletin_get_forced_mac(struct ecore_hwfn * p_hwfn,u16 rel_vf_id)485786a2265eSRasesh Mody u8 *ecore_iov_bulletin_get_forced_mac(struct ecore_hwfn *p_hwfn, u16 rel_vf_id)
485886a2265eSRasesh Mody {
485986a2265eSRasesh Mody 	struct ecore_vf_info *p_vf;
486086a2265eSRasesh Mody 
486186a2265eSRasesh Mody 	p_vf = ecore_iov_get_vf_info(p_hwfn, rel_vf_id, true);
486286a2265eSRasesh Mody 	if (!p_vf || !p_vf->bulletin.p_virt)
486386a2265eSRasesh Mody 		return OSAL_NULL;
486486a2265eSRasesh Mody 
486586a2265eSRasesh Mody 	if (!(p_vf->bulletin.p_virt->valid_bitmap & (1 << MAC_ADDR_FORCED)))
486686a2265eSRasesh Mody 		return OSAL_NULL;
486786a2265eSRasesh Mody 
486886a2265eSRasesh Mody 	return p_vf->bulletin.p_virt->mac;
486986a2265eSRasesh Mody }
487086a2265eSRasesh Mody 
ecore_iov_bulletin_get_forced_vlan(struct ecore_hwfn * p_hwfn,u16 rel_vf_id)487186a2265eSRasesh Mody u16 ecore_iov_bulletin_get_forced_vlan(struct ecore_hwfn *p_hwfn,
487286a2265eSRasesh Mody 				       u16 rel_vf_id)
487386a2265eSRasesh Mody {
487486a2265eSRasesh Mody 	struct ecore_vf_info *p_vf;
487586a2265eSRasesh Mody 
487686a2265eSRasesh Mody 	p_vf = ecore_iov_get_vf_info(p_hwfn, rel_vf_id, true);
487786a2265eSRasesh Mody 	if (!p_vf || !p_vf->bulletin.p_virt)
487886a2265eSRasesh Mody 		return 0;
487986a2265eSRasesh Mody 
488086a2265eSRasesh Mody 	if (!(p_vf->bulletin.p_virt->valid_bitmap & (1 << VLAN_ADDR_FORCED)))
488186a2265eSRasesh Mody 		return 0;
488286a2265eSRasesh Mody 
488386a2265eSRasesh Mody 	return p_vf->bulletin.p_virt->pvid;
488486a2265eSRasesh Mody }
488586a2265eSRasesh Mody 
ecore_iov_configure_tx_rate(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,int vfid,int val)488686a2265eSRasesh Mody enum _ecore_status_t ecore_iov_configure_tx_rate(struct ecore_hwfn *p_hwfn,
488786a2265eSRasesh Mody 						 struct ecore_ptt *p_ptt,
488886a2265eSRasesh Mody 						 int vfid, int val)
488986a2265eSRasesh Mody {
489086a2265eSRasesh Mody 	struct ecore_vf_info *vf;
489186a2265eSRasesh Mody 	u8 abs_vp_id = 0;
48923b307c55SRasesh Mody 	u16 rl_id;
489322d07d93SRasesh Mody 	enum _ecore_status_t rc;
489486a2265eSRasesh Mody 
489586a2265eSRasesh Mody 	vf = ecore_iov_get_vf_info(p_hwfn, (u16)vfid, true);
489686a2265eSRasesh Mody 
489786a2265eSRasesh Mody 	if (!vf)
489886a2265eSRasesh Mody 		return ECORE_INVAL;
489986a2265eSRasesh Mody 
490086a2265eSRasesh Mody 	rc = ecore_fw_vport(p_hwfn, vf->vport_id, &abs_vp_id);
490186a2265eSRasesh Mody 	if (rc != ECORE_SUCCESS)
490286a2265eSRasesh Mody 		return rc;
490386a2265eSRasesh Mody 
49043b307c55SRasesh Mody 	rl_id = abs_vp_id; /* The "rl_id" is set as the "vport_id" */
49053b307c55SRasesh Mody 	return ecore_init_global_rl(p_hwfn, p_ptt, rl_id, (u32)val);
490686a2265eSRasesh Mody }
490786a2265eSRasesh Mody 
ecore_iov_configure_min_tx_rate(struct ecore_dev * p_dev,int vfid,u32 rate)4908cf84de86SRasesh Mody enum _ecore_status_t ecore_iov_configure_min_tx_rate(struct ecore_dev *p_dev,
4909cf84de86SRasesh Mody 						     int vfid, u32 rate)
4910cf84de86SRasesh Mody {
4911cf84de86SRasesh Mody 	struct ecore_vf_info *vf;
4912cf84de86SRasesh Mody 	int i;
4913cf84de86SRasesh Mody 
4914cf84de86SRasesh Mody 	for_each_hwfn(p_dev, i) {
4915cf84de86SRasesh Mody 		struct ecore_hwfn *p_hwfn = &p_dev->hwfns[i];
4916cf84de86SRasesh Mody 
4917cf84de86SRasesh Mody 		if (!ecore_iov_pf_sanity_check(p_hwfn, vfid)) {
4918cf84de86SRasesh Mody 			DP_NOTICE(p_hwfn, true,
4919cf84de86SRasesh Mody 				  "SR-IOV sanity check failed, can't set min rate\n");
4920cf84de86SRasesh Mody 			return ECORE_INVAL;
4921cf84de86SRasesh Mody 		}
4922cf84de86SRasesh Mody 	}
4923cf84de86SRasesh Mody 
4924cf84de86SRasesh Mody 	vf = ecore_iov_get_vf_info(ECORE_LEADING_HWFN(p_dev), (u16)vfid, true);
4925cf84de86SRasesh Mody 	if (!vf) {
4926cf84de86SRasesh Mody 		DP_NOTICE(p_dev, true,
4927cf84de86SRasesh Mody 			  "Getting vf info failed, can't set min rate\n");
4928cf84de86SRasesh Mody 		return ECORE_INVAL;
4929cf84de86SRasesh Mody 	}
4930cf84de86SRasesh Mody 
4931cf84de86SRasesh Mody 	return ecore_configure_vport_wfq(p_dev, vf->vport_id, rate);
4932cf84de86SRasesh Mody }
4933cf84de86SRasesh Mody 
ecore_iov_get_vf_stats(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,int vfid,struct ecore_eth_stats * p_stats)493486a2265eSRasesh Mody enum _ecore_status_t ecore_iov_get_vf_stats(struct ecore_hwfn *p_hwfn,
493586a2265eSRasesh Mody 					    struct ecore_ptt *p_ptt,
493686a2265eSRasesh Mody 					    int vfid,
493786a2265eSRasesh Mody 					    struct ecore_eth_stats *p_stats)
493886a2265eSRasesh Mody {
493986a2265eSRasesh Mody 	struct ecore_vf_info *vf;
494086a2265eSRasesh Mody 
494186a2265eSRasesh Mody 	vf = ecore_iov_get_vf_info(p_hwfn, (u16)vfid, true);
494286a2265eSRasesh Mody 	if (!vf)
494386a2265eSRasesh Mody 		return ECORE_INVAL;
494486a2265eSRasesh Mody 
494586a2265eSRasesh Mody 	if (vf->state != VF_ENABLED)
494686a2265eSRasesh Mody 		return ECORE_INVAL;
494786a2265eSRasesh Mody 
494886a2265eSRasesh Mody 	__ecore_get_vport_stats(p_hwfn, p_ptt, p_stats,
494986a2265eSRasesh Mody 				vf->abs_vf_id + 0x10, false);
495086a2265eSRasesh Mody 
495186a2265eSRasesh Mody 	return ECORE_SUCCESS;
495286a2265eSRasesh Mody }
495386a2265eSRasesh Mody 
ecore_iov_get_vf_num_rxqs(struct ecore_hwfn * p_hwfn,u16 rel_vf_id)495486a2265eSRasesh Mody u8 ecore_iov_get_vf_num_rxqs(struct ecore_hwfn *p_hwfn, u16 rel_vf_id)
495586a2265eSRasesh Mody {
495686a2265eSRasesh Mody 	struct ecore_vf_info *p_vf;
495786a2265eSRasesh Mody 
495886a2265eSRasesh Mody 	p_vf = ecore_iov_get_vf_info(p_hwfn, rel_vf_id, true);
495986a2265eSRasesh Mody 	if (!p_vf)
496086a2265eSRasesh Mody 		return 0;
496186a2265eSRasesh Mody 
496286a2265eSRasesh Mody 	return p_vf->num_rxqs;
496386a2265eSRasesh Mody }
496486a2265eSRasesh Mody 
ecore_iov_get_vf_num_active_rxqs(struct ecore_hwfn * p_hwfn,u16 rel_vf_id)496586a2265eSRasesh Mody u8 ecore_iov_get_vf_num_active_rxqs(struct ecore_hwfn *p_hwfn, u16 rel_vf_id)
496686a2265eSRasesh Mody {
496786a2265eSRasesh Mody 	struct ecore_vf_info *p_vf;
496886a2265eSRasesh Mody 
496986a2265eSRasesh Mody 	p_vf = ecore_iov_get_vf_info(p_hwfn, rel_vf_id, true);
497086a2265eSRasesh Mody 	if (!p_vf)
497186a2265eSRasesh Mody 		return 0;
497286a2265eSRasesh Mody 
497386a2265eSRasesh Mody 	return p_vf->num_active_rxqs;
497486a2265eSRasesh Mody }
497586a2265eSRasesh Mody 
ecore_iov_get_vf_ctx(struct ecore_hwfn * p_hwfn,u16 rel_vf_id)497686a2265eSRasesh Mody void *ecore_iov_get_vf_ctx(struct ecore_hwfn *p_hwfn, u16 rel_vf_id)
497786a2265eSRasesh Mody {
497886a2265eSRasesh Mody 	struct ecore_vf_info *p_vf;
497986a2265eSRasesh Mody 
498086a2265eSRasesh Mody 	p_vf = ecore_iov_get_vf_info(p_hwfn, rel_vf_id, true);
498186a2265eSRasesh Mody 	if (!p_vf)
498286a2265eSRasesh Mody 		return OSAL_NULL;
498386a2265eSRasesh Mody 
498486a2265eSRasesh Mody 	return p_vf->ctx;
498586a2265eSRasesh Mody }
498686a2265eSRasesh Mody 
ecore_iov_get_vf_num_sbs(struct ecore_hwfn * p_hwfn,u16 rel_vf_id)498786a2265eSRasesh Mody u8 ecore_iov_get_vf_num_sbs(struct ecore_hwfn *p_hwfn, u16 rel_vf_id)
498886a2265eSRasesh Mody {
498986a2265eSRasesh Mody 	struct ecore_vf_info *p_vf;
499086a2265eSRasesh Mody 
499186a2265eSRasesh Mody 	p_vf = ecore_iov_get_vf_info(p_hwfn, rel_vf_id, true);
499286a2265eSRasesh Mody 	if (!p_vf)
499386a2265eSRasesh Mody 		return 0;
499486a2265eSRasesh Mody 
499586a2265eSRasesh Mody 	return p_vf->num_sbs;
499686a2265eSRasesh Mody }
499786a2265eSRasesh Mody 
ecore_iov_is_vf_wait_for_acquire(struct ecore_hwfn * p_hwfn,u16 rel_vf_id)499886a2265eSRasesh Mody bool ecore_iov_is_vf_wait_for_acquire(struct ecore_hwfn *p_hwfn, u16 rel_vf_id)
499986a2265eSRasesh Mody {
500086a2265eSRasesh Mody 	struct ecore_vf_info *p_vf;
500186a2265eSRasesh Mody 
500286a2265eSRasesh Mody 	p_vf = ecore_iov_get_vf_info(p_hwfn, rel_vf_id, true);
500386a2265eSRasesh Mody 	if (!p_vf)
500486a2265eSRasesh Mody 		return false;
500586a2265eSRasesh Mody 
500686a2265eSRasesh Mody 	return (p_vf->state == VF_FREE);
500786a2265eSRasesh Mody }
500886a2265eSRasesh Mody 
ecore_iov_is_vf_acquired_not_initialized(struct ecore_hwfn * p_hwfn,u16 rel_vf_id)500986a2265eSRasesh Mody bool ecore_iov_is_vf_acquired_not_initialized(struct ecore_hwfn *p_hwfn,
501086a2265eSRasesh Mody 					      u16 rel_vf_id)
501186a2265eSRasesh Mody {
501286a2265eSRasesh Mody 	struct ecore_vf_info *p_vf;
501386a2265eSRasesh Mody 
501486a2265eSRasesh Mody 	p_vf = ecore_iov_get_vf_info(p_hwfn, rel_vf_id, true);
501586a2265eSRasesh Mody 	if (!p_vf)
501686a2265eSRasesh Mody 		return false;
501786a2265eSRasesh Mody 
501886a2265eSRasesh Mody 	return (p_vf->state == VF_ACQUIRED);
501986a2265eSRasesh Mody }
502086a2265eSRasesh Mody 
ecore_iov_is_vf_initialized(struct ecore_hwfn * p_hwfn,u16 rel_vf_id)502186a2265eSRasesh Mody bool ecore_iov_is_vf_initialized(struct ecore_hwfn *p_hwfn, u16 rel_vf_id)
502286a2265eSRasesh Mody {
502386a2265eSRasesh Mody 	struct ecore_vf_info *p_vf;
502486a2265eSRasesh Mody 
502586a2265eSRasesh Mody 	p_vf = ecore_iov_get_vf_info(p_hwfn, rel_vf_id, true);
502686a2265eSRasesh Mody 	if (!p_vf)
502786a2265eSRasesh Mody 		return false;
502886a2265eSRasesh Mody 
502986a2265eSRasesh Mody 	return (p_vf->state == VF_ENABLED);
503086a2265eSRasesh Mody }
503186a2265eSRasesh Mody 
ecore_iov_is_vf_started(struct ecore_hwfn * p_hwfn,u16 rel_vf_id)5032869c47d0SRasesh Mody bool ecore_iov_is_vf_started(struct ecore_hwfn *p_hwfn,
5033869c47d0SRasesh Mody 			     u16 rel_vf_id)
5034869c47d0SRasesh Mody {
5035869c47d0SRasesh Mody 	struct ecore_vf_info *p_vf;
5036869c47d0SRasesh Mody 
5037869c47d0SRasesh Mody 	p_vf = ecore_iov_get_vf_info(p_hwfn, rel_vf_id, true);
5038869c47d0SRasesh Mody 	if (!p_vf)
5039869c47d0SRasesh Mody 		return false;
5040869c47d0SRasesh Mody 
5041869c47d0SRasesh Mody 	return (p_vf->state != VF_FREE && p_vf->state != VF_STOPPED);
5042869c47d0SRasesh Mody }
5043869c47d0SRasesh Mody 
5044cf84de86SRasesh Mody int
ecore_iov_get_vf_min_rate(struct ecore_hwfn * p_hwfn,int vfid)504593fce904SRasesh Mody ecore_iov_get_vf_min_rate(struct ecore_hwfn *p_hwfn, int vfid)
504686a2265eSRasesh Mody {
504786a2265eSRasesh Mody 	struct ecore_wfq_data *vf_vp_wfq;
504886a2265eSRasesh Mody 	struct ecore_vf_info *vf_info;
504986a2265eSRasesh Mody 
505086a2265eSRasesh Mody 	vf_info = ecore_iov_get_vf_info(p_hwfn, (u16)vfid, true);
505186a2265eSRasesh Mody 	if (!vf_info)
505286a2265eSRasesh Mody 		return 0;
505386a2265eSRasesh Mody 
505486a2265eSRasesh Mody 	vf_vp_wfq = &p_hwfn->qm_info.wfq_data[vf_info->vport_id];
505586a2265eSRasesh Mody 
505686a2265eSRasesh Mody 	if (vf_vp_wfq->configured)
505786a2265eSRasesh Mody 		return vf_vp_wfq->min_speed;
505886a2265eSRasesh Mody 	else
505986a2265eSRasesh Mody 		return 0;
506086a2265eSRasesh Mody }
506101491d29SRasesh Mody 
506201491d29SRasesh Mody #ifdef CONFIG_ECORE_SW_CHANNEL
ecore_iov_set_vf_hw_channel(struct ecore_hwfn * p_hwfn,int vfid,bool b_is_hw)506301491d29SRasesh Mody void ecore_iov_set_vf_hw_channel(struct ecore_hwfn *p_hwfn, int vfid,
506401491d29SRasesh Mody 				 bool b_is_hw)
506501491d29SRasesh Mody {
506601491d29SRasesh Mody 	struct ecore_vf_info *vf_info;
506701491d29SRasesh Mody 
506801491d29SRasesh Mody 	vf_info = ecore_iov_get_vf_info(p_hwfn, (u16)vfid, true);
506901491d29SRasesh Mody 	if (!vf_info)
507001491d29SRasesh Mody 		return;
507101491d29SRasesh Mody 
507201491d29SRasesh Mody 	vf_info->b_hw_channel = b_is_hw;
507301491d29SRasesh Mody }
507401491d29SRasesh Mody #endif
5075