11408cc1fSYuval Mintz /* QLogic qed NIC Driver
21408cc1fSYuval Mintz  * Copyright (c) 2015 QLogic Corporation
31408cc1fSYuval Mintz  *
41408cc1fSYuval Mintz  * This software is available under the terms of the GNU General Public License
51408cc1fSYuval Mintz  * (GPL) Version 2, available from the file COPYING in the main directory of
61408cc1fSYuval Mintz  * this source tree.
71408cc1fSYuval Mintz  */
81408cc1fSYuval Mintz 
936558c3dSYuval Mintz #include <linux/crc32.h>
10eff16960SYuval Mintz #include <linux/etherdevice.h>
111408cc1fSYuval Mintz #include "qed.h"
121408cc1fSYuval Mintz #include "qed_sriov.h"
131408cc1fSYuval Mintz #include "qed_vf.h"
141408cc1fSYuval Mintz 
151408cc1fSYuval Mintz static void *qed_vf_pf_prep(struct qed_hwfn *p_hwfn, u16 type, u16 length)
161408cc1fSYuval Mintz {
171408cc1fSYuval Mintz 	struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info;
181408cc1fSYuval Mintz 	void *p_tlv;
191408cc1fSYuval Mintz 
201408cc1fSYuval Mintz 	/* This lock is released when we receive PF's response
211408cc1fSYuval Mintz 	 * in qed_send_msg2pf().
221408cc1fSYuval Mintz 	 * So, qed_vf_pf_prep() and qed_send_msg2pf()
231408cc1fSYuval Mintz 	 * must come in sequence.
241408cc1fSYuval Mintz 	 */
251408cc1fSYuval Mintz 	mutex_lock(&(p_iov->mutex));
261408cc1fSYuval Mintz 
271408cc1fSYuval Mintz 	DP_VERBOSE(p_hwfn,
281408cc1fSYuval Mintz 		   QED_MSG_IOV,
291408cc1fSYuval Mintz 		   "preparing to send 0x%04x tlv over vf pf channel\n",
301408cc1fSYuval Mintz 		   type);
311408cc1fSYuval Mintz 
321408cc1fSYuval Mintz 	/* Reset Requst offset */
331408cc1fSYuval Mintz 	p_iov->offset = (u8 *)p_iov->vf2pf_request;
341408cc1fSYuval Mintz 
351408cc1fSYuval Mintz 	/* Clear mailbox - both request and reply */
361408cc1fSYuval Mintz 	memset(p_iov->vf2pf_request, 0, sizeof(union vfpf_tlvs));
371408cc1fSYuval Mintz 	memset(p_iov->pf2vf_reply, 0, sizeof(union pfvf_tlvs));
381408cc1fSYuval Mintz 
391408cc1fSYuval Mintz 	/* Init type and length */
401408cc1fSYuval Mintz 	p_tlv = qed_add_tlv(p_hwfn, &p_iov->offset, type, length);
411408cc1fSYuval Mintz 
421408cc1fSYuval Mintz 	/* Init first tlv header */
431408cc1fSYuval Mintz 	((struct vfpf_first_tlv *)p_tlv)->reply_address =
441408cc1fSYuval Mintz 	    (u64)p_iov->pf2vf_reply_phys;
451408cc1fSYuval Mintz 
461408cc1fSYuval Mintz 	return p_tlv;
471408cc1fSYuval Mintz }
481408cc1fSYuval Mintz 
49b0bccb69SYuval Mintz static void qed_vf_pf_req_end(struct qed_hwfn *p_hwfn, int req_status)
50b0bccb69SYuval Mintz {
51b0bccb69SYuval Mintz 	union pfvf_tlvs *resp = p_hwfn->vf_iov_info->pf2vf_reply;
52b0bccb69SYuval Mintz 
53b0bccb69SYuval Mintz 	DP_VERBOSE(p_hwfn, QED_MSG_IOV,
54b0bccb69SYuval Mintz 		   "VF request status = 0x%x, PF reply status = 0x%x\n",
55b0bccb69SYuval Mintz 		   req_status, resp->default_resp.hdr.status);
56b0bccb69SYuval Mintz 
57b0bccb69SYuval Mintz 	mutex_unlock(&(p_hwfn->vf_iov_info->mutex));
58b0bccb69SYuval Mintz }
59b0bccb69SYuval Mintz 
601408cc1fSYuval Mintz static int qed_send_msg2pf(struct qed_hwfn *p_hwfn, u8 *done, u32 resp_size)
611408cc1fSYuval Mintz {
621408cc1fSYuval Mintz 	union vfpf_tlvs *p_req = p_hwfn->vf_iov_info->vf2pf_request;
631408cc1fSYuval Mintz 	struct ustorm_trigger_vf_zone trigger;
641408cc1fSYuval Mintz 	struct ustorm_vf_zone *zone_data;
651408cc1fSYuval Mintz 	int rc = 0, time = 100;
661408cc1fSYuval Mintz 
671408cc1fSYuval Mintz 	zone_data = (struct ustorm_vf_zone *)PXP_VF_BAR0_START_USDM_ZONE_B;
681408cc1fSYuval Mintz 
691408cc1fSYuval Mintz 	/* output tlvs list */
701408cc1fSYuval Mintz 	qed_dp_tlv_list(p_hwfn, p_req);
711408cc1fSYuval Mintz 
721408cc1fSYuval Mintz 	/* need to add the END TLV to the message size */
731408cc1fSYuval Mintz 	resp_size += sizeof(struct channel_list_end_tlv);
741408cc1fSYuval Mintz 
751408cc1fSYuval Mintz 	/* Send TLVs over HW channel */
761408cc1fSYuval Mintz 	memset(&trigger, 0, sizeof(struct ustorm_trigger_vf_zone));
771408cc1fSYuval Mintz 	trigger.vf_pf_msg_valid = 1;
781408cc1fSYuval Mintz 
791408cc1fSYuval Mintz 	DP_VERBOSE(p_hwfn,
801408cc1fSYuval Mintz 		   QED_MSG_IOV,
811408cc1fSYuval Mintz 		   "VF -> PF [%02x] message: [%08x, %08x] --> %p, %08x --> %p\n",
821408cc1fSYuval Mintz 		   GET_FIELD(p_hwfn->hw_info.concrete_fid,
831408cc1fSYuval Mintz 			     PXP_CONCRETE_FID_PFID),
841408cc1fSYuval Mintz 		   upper_32_bits(p_hwfn->vf_iov_info->vf2pf_request_phys),
851408cc1fSYuval Mintz 		   lower_32_bits(p_hwfn->vf_iov_info->vf2pf_request_phys),
861408cc1fSYuval Mintz 		   &zone_data->non_trigger.vf_pf_msg_addr,
871408cc1fSYuval Mintz 		   *((u32 *)&trigger), &zone_data->trigger);
881408cc1fSYuval Mintz 
891408cc1fSYuval Mintz 	REG_WR(p_hwfn,
901408cc1fSYuval Mintz 	       (uintptr_t)&zone_data->non_trigger.vf_pf_msg_addr.lo,
911408cc1fSYuval Mintz 	       lower_32_bits(p_hwfn->vf_iov_info->vf2pf_request_phys));
921408cc1fSYuval Mintz 
931408cc1fSYuval Mintz 	REG_WR(p_hwfn,
941408cc1fSYuval Mintz 	       (uintptr_t)&zone_data->non_trigger.vf_pf_msg_addr.hi,
951408cc1fSYuval Mintz 	       upper_32_bits(p_hwfn->vf_iov_info->vf2pf_request_phys));
961408cc1fSYuval Mintz 
971408cc1fSYuval Mintz 	/* The message data must be written first, to prevent trigger before
981408cc1fSYuval Mintz 	 * data is written.
991408cc1fSYuval Mintz 	 */
1001408cc1fSYuval Mintz 	wmb();
1011408cc1fSYuval Mintz 
1021408cc1fSYuval Mintz 	REG_WR(p_hwfn, (uintptr_t)&zone_data->trigger, *((u32 *)&trigger));
1031408cc1fSYuval Mintz 
1041408cc1fSYuval Mintz 	/* When PF would be done with the response, it would write back to the
1051408cc1fSYuval Mintz 	 * `done' address. Poll until then.
1061408cc1fSYuval Mintz 	 */
1071408cc1fSYuval Mintz 	while ((!*done) && time) {
1081408cc1fSYuval Mintz 		msleep(25);
1091408cc1fSYuval Mintz 		time--;
1101408cc1fSYuval Mintz 	}
1111408cc1fSYuval Mintz 
1121408cc1fSYuval Mintz 	if (!*done) {
1131408cc1fSYuval Mintz 		DP_VERBOSE(p_hwfn, QED_MSG_IOV,
1141408cc1fSYuval Mintz 			   "VF <-- PF Timeout [Type %d]\n",
1151408cc1fSYuval Mintz 			   p_req->first_tlv.tl.type);
1161408cc1fSYuval Mintz 		rc = -EBUSY;
1171408cc1fSYuval Mintz 	} else {
1181408cc1fSYuval Mintz 		DP_VERBOSE(p_hwfn, QED_MSG_IOV,
1191408cc1fSYuval Mintz 			   "PF response: %d [Type %d]\n",
1201408cc1fSYuval Mintz 			   *done, p_req->first_tlv.tl.type);
1211408cc1fSYuval Mintz 	}
1221408cc1fSYuval Mintz 
1231408cc1fSYuval Mintz 	return rc;
1241408cc1fSYuval Mintz }
1251408cc1fSYuval Mintz 
1261408cc1fSYuval Mintz #define VF_ACQUIRE_THRESH 3
1271cf2b1a9SYuval Mintz static void qed_vf_pf_acquire_reduce_resc(struct qed_hwfn *p_hwfn,
1281cf2b1a9SYuval Mintz 					  struct vf_pf_resc_request *p_req,
1291cf2b1a9SYuval Mintz 					  struct pf_vf_resc *p_resp)
1301cf2b1a9SYuval Mintz {
1311cf2b1a9SYuval Mintz 	DP_VERBOSE(p_hwfn,
1321cf2b1a9SYuval Mintz 		   QED_MSG_IOV,
1331cf2b1a9SYuval Mintz 		   "PF unwilling to fullill resource request: rxq [%02x/%02x] txq [%02x/%02x] sbs [%02x/%02x] mac [%02x/%02x] vlan [%02x/%02x] mc [%02x/%02x]. Try PF recommended amount\n",
1341cf2b1a9SYuval Mintz 		   p_req->num_rxqs,
1351cf2b1a9SYuval Mintz 		   p_resp->num_rxqs,
1361cf2b1a9SYuval Mintz 		   p_req->num_rxqs,
1371cf2b1a9SYuval Mintz 		   p_resp->num_txqs,
1381cf2b1a9SYuval Mintz 		   p_req->num_sbs,
1391cf2b1a9SYuval Mintz 		   p_resp->num_sbs,
1401cf2b1a9SYuval Mintz 		   p_req->num_mac_filters,
1411cf2b1a9SYuval Mintz 		   p_resp->num_mac_filters,
1421cf2b1a9SYuval Mintz 		   p_req->num_vlan_filters,
1431cf2b1a9SYuval Mintz 		   p_resp->num_vlan_filters,
1441cf2b1a9SYuval Mintz 		   p_req->num_mc_filters, p_resp->num_mc_filters);
1451cf2b1a9SYuval Mintz 
1461cf2b1a9SYuval Mintz 	/* humble our request */
1471cf2b1a9SYuval Mintz 	p_req->num_txqs = p_resp->num_txqs;
1481cf2b1a9SYuval Mintz 	p_req->num_rxqs = p_resp->num_rxqs;
1491cf2b1a9SYuval Mintz 	p_req->num_sbs = p_resp->num_sbs;
1501cf2b1a9SYuval Mintz 	p_req->num_mac_filters = p_resp->num_mac_filters;
1511cf2b1a9SYuval Mintz 	p_req->num_vlan_filters = p_resp->num_vlan_filters;
1521cf2b1a9SYuval Mintz 	p_req->num_mc_filters = p_resp->num_mc_filters;
1531cf2b1a9SYuval Mintz }
1541408cc1fSYuval Mintz 
1551408cc1fSYuval Mintz static int qed_vf_pf_acquire(struct qed_hwfn *p_hwfn)
1561408cc1fSYuval Mintz {
1571408cc1fSYuval Mintz 	struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info;
1581408cc1fSYuval Mintz 	struct pfvf_acquire_resp_tlv *resp = &p_iov->pf2vf_reply->acquire_resp;
1591408cc1fSYuval Mintz 	struct pf_vf_pfdev_info *pfdev_info = &resp->pfdev_info;
1601cf2b1a9SYuval Mintz 	struct vf_pf_resc_request *p_resc;
1611408cc1fSYuval Mintz 	bool resources_acquired = false;
1621408cc1fSYuval Mintz 	struct vfpf_acquire_tlv *req;
1631408cc1fSYuval Mintz 	int rc = 0, attempts = 0;
1641408cc1fSYuval Mintz 
1651408cc1fSYuval Mintz 	/* clear mailbox and prep first tlv */
1661408cc1fSYuval Mintz 	req = qed_vf_pf_prep(p_hwfn, CHANNEL_TLV_ACQUIRE, sizeof(*req));
1671cf2b1a9SYuval Mintz 	p_resc = &req->resc_request;
1681408cc1fSYuval Mintz 
1691408cc1fSYuval Mintz 	/* starting filling the request */
1701408cc1fSYuval Mintz 	req->vfdev_info.opaque_fid = p_hwfn->hw_info.opaque_fid;
1711408cc1fSYuval Mintz 
1721cf2b1a9SYuval Mintz 	p_resc->num_rxqs = QED_MAX_VF_CHAINS_PER_PF;
1731cf2b1a9SYuval Mintz 	p_resc->num_txqs = QED_MAX_VF_CHAINS_PER_PF;
1741cf2b1a9SYuval Mintz 	p_resc->num_sbs = QED_MAX_VF_CHAINS_PER_PF;
1751cf2b1a9SYuval Mintz 	p_resc->num_mac_filters = QED_ETH_VF_NUM_MAC_FILTERS;
1761cf2b1a9SYuval Mintz 	p_resc->num_vlan_filters = QED_ETH_VF_NUM_VLAN_FILTERS;
1771408cc1fSYuval Mintz 
1781408cc1fSYuval Mintz 	req->vfdev_info.os_type = VFPF_ACQUIRE_OS_LINUX;
1791408cc1fSYuval Mintz 	req->vfdev_info.fw_major = FW_MAJOR_VERSION;
1801408cc1fSYuval Mintz 	req->vfdev_info.fw_minor = FW_MINOR_VERSION;
1811408cc1fSYuval Mintz 	req->vfdev_info.fw_revision = FW_REVISION_VERSION;
1821408cc1fSYuval Mintz 	req->vfdev_info.fw_engineering = FW_ENGINEERING_VERSION;
1831fe614d1SYuval Mintz 	req->vfdev_info.eth_fp_hsi_major = ETH_HSI_VER_MAJOR;
1841fe614d1SYuval Mintz 	req->vfdev_info.eth_fp_hsi_minor = ETH_HSI_VER_MINOR;
1851408cc1fSYuval Mintz 
1861408cc1fSYuval Mintz 	/* Fill capability field with any non-deprecated config we support */
1871408cc1fSYuval Mintz 	req->vfdev_info.capabilities |= VFPF_ACQUIRE_CAP_100G;
1881408cc1fSYuval Mintz 
1891408cc1fSYuval Mintz 	/* pf 2 vf bulletin board address */
1901408cc1fSYuval Mintz 	req->bulletin_addr = p_iov->bulletin.phys;
1911408cc1fSYuval Mintz 	req->bulletin_size = p_iov->bulletin.size;
1921408cc1fSYuval Mintz 
1931408cc1fSYuval Mintz 	/* add list termination tlv */
1941408cc1fSYuval Mintz 	qed_add_tlv(p_hwfn, &p_iov->offset,
1951408cc1fSYuval Mintz 		    CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv));
1961408cc1fSYuval Mintz 
1971408cc1fSYuval Mintz 	while (!resources_acquired) {
1981408cc1fSYuval Mintz 		DP_VERBOSE(p_hwfn,
1991408cc1fSYuval Mintz 			   QED_MSG_IOV, "attempting to acquire resources\n");
2001408cc1fSYuval Mintz 
201d8c2c7e3SYuval Mintz 		/* Clear response buffer, as this might be a re-send */
202d8c2c7e3SYuval Mintz 		memset(p_iov->pf2vf_reply, 0, sizeof(union pfvf_tlvs));
203d8c2c7e3SYuval Mintz 
2041408cc1fSYuval Mintz 		/* send acquire request */
2051408cc1fSYuval Mintz 		rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp));
2061408cc1fSYuval Mintz 		if (rc)
2071408cc1fSYuval Mintz 			return rc;
2081408cc1fSYuval Mintz 
2091408cc1fSYuval Mintz 		/* copy acquire response from buffer to p_hwfn */
2101408cc1fSYuval Mintz 		memcpy(&p_iov->acquire_resp, resp, sizeof(p_iov->acquire_resp));
2111408cc1fSYuval Mintz 
2121408cc1fSYuval Mintz 		attempts++;
2131408cc1fSYuval Mintz 
2141408cc1fSYuval Mintz 		if (resp->hdr.status == PFVF_STATUS_SUCCESS) {
2151408cc1fSYuval Mintz 			/* PF agrees to allocate our resources */
2161408cc1fSYuval Mintz 			if (!(resp->pfdev_info.capabilities &
2171408cc1fSYuval Mintz 			      PFVF_ACQUIRE_CAP_POST_FW_OVERRIDE)) {
218d8c2c7e3SYuval Mintz 				/* It's possible legacy PF mistakenly accepted;
219d8c2c7e3SYuval Mintz 				 * but we don't care - simply mark it as
220d8c2c7e3SYuval Mintz 				 * legacy and continue.
221d8c2c7e3SYuval Mintz 				 */
222d8c2c7e3SYuval Mintz 				req->vfdev_info.capabilities |=
223d8c2c7e3SYuval Mintz 				    VFPF_ACQUIRE_CAP_PRE_FP_HSI;
2241408cc1fSYuval Mintz 			}
2251408cc1fSYuval Mintz 			DP_VERBOSE(p_hwfn, QED_MSG_IOV, "resources acquired\n");
2261408cc1fSYuval Mintz 			resources_acquired = true;
2271408cc1fSYuval Mintz 		} else if (resp->hdr.status == PFVF_STATUS_NO_RESOURCE &&
2281408cc1fSYuval Mintz 			   attempts < VF_ACQUIRE_THRESH) {
2291cf2b1a9SYuval Mintz 			qed_vf_pf_acquire_reduce_resc(p_hwfn, p_resc,
2301cf2b1a9SYuval Mintz 						      &resp->resc);
231d8c2c7e3SYuval Mintz 		} else if (resp->hdr.status == PFVF_STATUS_NOT_SUPPORTED) {
232d8c2c7e3SYuval Mintz 			if (pfdev_info->major_fp_hsi &&
2331fe614d1SYuval Mintz 			    (pfdev_info->major_fp_hsi != ETH_HSI_VER_MAJOR)) {
2341fe614d1SYuval Mintz 				DP_NOTICE(p_hwfn,
2351fe614d1SYuval Mintz 					  "PF uses an incompatible fastpath HSI %02x.%02x [VF requires %02x.%02x]. Please change to a VF driver using %02x.xx.\n",
2361fe614d1SYuval Mintz 					  pfdev_info->major_fp_hsi,
2371fe614d1SYuval Mintz 					  pfdev_info->minor_fp_hsi,
2381fe614d1SYuval Mintz 					  ETH_HSI_VER_MAJOR,
239d8c2c7e3SYuval Mintz 					  ETH_HSI_VER_MINOR,
240d8c2c7e3SYuval Mintz 					  pfdev_info->major_fp_hsi);
241d8c2c7e3SYuval Mintz 				rc = -EINVAL;
242d8c2c7e3SYuval Mintz 				goto exit;
243d8c2c7e3SYuval Mintz 			}
244d8c2c7e3SYuval Mintz 
245d8c2c7e3SYuval Mintz 			if (!pfdev_info->major_fp_hsi) {
246d8c2c7e3SYuval Mintz 				if (req->vfdev_info.capabilities &
247d8c2c7e3SYuval Mintz 				    VFPF_ACQUIRE_CAP_PRE_FP_HSI) {
248d8c2c7e3SYuval Mintz 					DP_NOTICE(p_hwfn,
249d8c2c7e3SYuval Mintz 						  "PF uses very old drivers. Please change to a VF driver using no later than 8.8.x.x.\n");
250d8c2c7e3SYuval Mintz 					rc = -EINVAL;
251d8c2c7e3SYuval Mintz 					goto exit;
252d8c2c7e3SYuval Mintz 				} else {
253d8c2c7e3SYuval Mintz 					DP_INFO(p_hwfn,
254d8c2c7e3SYuval Mintz 						"PF is old - try re-acquire to see if it supports FW-version override\n");
255d8c2c7e3SYuval Mintz 					req->vfdev_info.capabilities |=
256d8c2c7e3SYuval Mintz 					    VFPF_ACQUIRE_CAP_PRE_FP_HSI;
257d8c2c7e3SYuval Mintz 					continue;
258d8c2c7e3SYuval Mintz 				}
259d8c2c7e3SYuval Mintz 			}
260d8c2c7e3SYuval Mintz 
261d8c2c7e3SYuval Mintz 			/* If PF/VF are using same Major, PF must have had
262d8c2c7e3SYuval Mintz 			 * it's reasons. Simply fail.
263d8c2c7e3SYuval Mintz 			 */
264d8c2c7e3SYuval Mintz 			DP_NOTICE(p_hwfn, "PF rejected acquisition by VF\n");
265d8c2c7e3SYuval Mintz 			rc = -EINVAL;
266d8c2c7e3SYuval Mintz 			goto exit;
2671408cc1fSYuval Mintz 		} else {
2681408cc1fSYuval Mintz 			DP_ERR(p_hwfn,
2691408cc1fSYuval Mintz 			       "PF returned error %d to VF acquisition request\n",
2701408cc1fSYuval Mintz 			       resp->hdr.status);
271d8c2c7e3SYuval Mintz 			rc = -EAGAIN;
272d8c2c7e3SYuval Mintz 			goto exit;
2731408cc1fSYuval Mintz 		}
2741408cc1fSYuval Mintz 	}
2751408cc1fSYuval Mintz 
276d8c2c7e3SYuval Mintz 	/* Mark the PF as legacy, if needed */
277d8c2c7e3SYuval Mintz 	if (req->vfdev_info.capabilities & VFPF_ACQUIRE_CAP_PRE_FP_HSI)
278d8c2c7e3SYuval Mintz 		p_iov->b_pre_fp_hsi = true;
279d8c2c7e3SYuval Mintz 
2801408cc1fSYuval Mintz 	/* Update bulletin board size with response from PF */
2811408cc1fSYuval Mintz 	p_iov->bulletin.size = resp->bulletin_size;
2821408cc1fSYuval Mintz 
2831408cc1fSYuval Mintz 	/* get HW info */
2841408cc1fSYuval Mintz 	p_hwfn->cdev->type = resp->pfdev_info.dev_type;
2851408cc1fSYuval Mintz 	p_hwfn->cdev->chip_rev = resp->pfdev_info.chip_rev;
2861408cc1fSYuval Mintz 
2871408cc1fSYuval Mintz 	p_hwfn->cdev->chip_num = pfdev_info->chip_num & 0xffff;
2881408cc1fSYuval Mintz 
2891408cc1fSYuval Mintz 	/* Learn of the possibility of CMT */
2901408cc1fSYuval Mintz 	if (IS_LEAD_HWFN(p_hwfn)) {
2911408cc1fSYuval Mintz 		if (resp->pfdev_info.capabilities & PFVF_ACQUIRE_CAP_100G) {
2921408cc1fSYuval Mintz 			DP_NOTICE(p_hwfn, "100g VF\n");
2931408cc1fSYuval Mintz 			p_hwfn->cdev->num_hwfns = 2;
2941408cc1fSYuval Mintz 		}
2951408cc1fSYuval Mintz 	}
2961408cc1fSYuval Mintz 
297d8c2c7e3SYuval Mintz 	if (!p_iov->b_pre_fp_hsi &&
298d8c2c7e3SYuval Mintz 	    ETH_HSI_VER_MINOR &&
2991fe614d1SYuval Mintz 	    (resp->pfdev_info.minor_fp_hsi < ETH_HSI_VER_MINOR)) {
3001fe614d1SYuval Mintz 		DP_INFO(p_hwfn,
3011fe614d1SYuval Mintz 			"PF is using older fastpath HSI; %02x.%02x is configured\n",
3021fe614d1SYuval Mintz 			ETH_HSI_VER_MAJOR, resp->pfdev_info.minor_fp_hsi);
3031fe614d1SYuval Mintz 	}
3041fe614d1SYuval Mintz 
305d8c2c7e3SYuval Mintz exit:
306b0bccb69SYuval Mintz 	qed_vf_pf_req_end(p_hwfn, rc);
307b0bccb69SYuval Mintz 
308d8c2c7e3SYuval Mintz 	return rc;
3091408cc1fSYuval Mintz }
3101408cc1fSYuval Mintz 
3111408cc1fSYuval Mintz int qed_vf_hw_prepare(struct qed_hwfn *p_hwfn)
3121408cc1fSYuval Mintz {
3131408cc1fSYuval Mintz 	struct qed_vf_iov *p_iov;
3141408cc1fSYuval Mintz 	u32 reg;
3151408cc1fSYuval Mintz 
3161408cc1fSYuval Mintz 	/* Set number of hwfns - might be overriden once leading hwfn learns
3171408cc1fSYuval Mintz 	 * actual configuration from PF.
3181408cc1fSYuval Mintz 	 */
3191408cc1fSYuval Mintz 	if (IS_LEAD_HWFN(p_hwfn))
3201408cc1fSYuval Mintz 		p_hwfn->cdev->num_hwfns = 1;
3211408cc1fSYuval Mintz 
3221408cc1fSYuval Mintz 	/* Set the doorbell bar. Assumption: regview is set */
3231408cc1fSYuval Mintz 	p_hwfn->doorbells = (u8 __iomem *)p_hwfn->regview +
3241408cc1fSYuval Mintz 					  PXP_VF_BAR0_START_DQ;
3251408cc1fSYuval Mintz 
3261408cc1fSYuval Mintz 	reg = PXP_VF_BAR0_ME_OPAQUE_ADDRESS;
3271408cc1fSYuval Mintz 	p_hwfn->hw_info.opaque_fid = (u16)REG_RD(p_hwfn, reg);
3281408cc1fSYuval Mintz 
3291408cc1fSYuval Mintz 	reg = PXP_VF_BAR0_ME_CONCRETE_ADDRESS;
3301408cc1fSYuval Mintz 	p_hwfn->hw_info.concrete_fid = REG_RD(p_hwfn, reg);
3311408cc1fSYuval Mintz 
3321408cc1fSYuval Mintz 	/* Allocate vf sriov info */
3331408cc1fSYuval Mintz 	p_iov = kzalloc(sizeof(*p_iov), GFP_KERNEL);
3342591c280SJoe Perches 	if (!p_iov)
3351408cc1fSYuval Mintz 		return -ENOMEM;
3361408cc1fSYuval Mintz 
3371408cc1fSYuval Mintz 	/* Allocate vf2pf msg */
3381408cc1fSYuval Mintz 	p_iov->vf2pf_request = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev,
3391408cc1fSYuval Mintz 						  sizeof(union vfpf_tlvs),
3401408cc1fSYuval Mintz 						  &p_iov->vf2pf_request_phys,
3411408cc1fSYuval Mintz 						  GFP_KERNEL);
3422591c280SJoe Perches 	if (!p_iov->vf2pf_request)
3431408cc1fSYuval Mintz 		goto free_p_iov;
3441408cc1fSYuval Mintz 
3451408cc1fSYuval Mintz 	p_iov->pf2vf_reply = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev,
3461408cc1fSYuval Mintz 						sizeof(union pfvf_tlvs),
3471408cc1fSYuval Mintz 						&p_iov->pf2vf_reply_phys,
3481408cc1fSYuval Mintz 						GFP_KERNEL);
3492591c280SJoe Perches 	if (!p_iov->pf2vf_reply)
3501408cc1fSYuval Mintz 		goto free_vf2pf_request;
3511408cc1fSYuval Mintz 
3521408cc1fSYuval Mintz 	DP_VERBOSE(p_hwfn,
3531408cc1fSYuval Mintz 		   QED_MSG_IOV,
3541408cc1fSYuval Mintz 		   "VF's Request mailbox [%p virt 0x%llx phys], Response mailbox [%p virt 0x%llx phys]\n",
3551408cc1fSYuval Mintz 		   p_iov->vf2pf_request,
3561408cc1fSYuval Mintz 		   (u64) p_iov->vf2pf_request_phys,
3571408cc1fSYuval Mintz 		   p_iov->pf2vf_reply, (u64)p_iov->pf2vf_reply_phys);
3581408cc1fSYuval Mintz 
3591408cc1fSYuval Mintz 	/* Allocate Bulletin board */
3601408cc1fSYuval Mintz 	p_iov->bulletin.size = sizeof(struct qed_bulletin_content);
3611408cc1fSYuval Mintz 	p_iov->bulletin.p_virt = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev,
3621408cc1fSYuval Mintz 						    p_iov->bulletin.size,
3631408cc1fSYuval Mintz 						    &p_iov->bulletin.phys,
3641408cc1fSYuval Mintz 						    GFP_KERNEL);
3651408cc1fSYuval Mintz 	DP_VERBOSE(p_hwfn, QED_MSG_IOV,
3661408cc1fSYuval Mintz 		   "VF's bulletin Board [%p virt 0x%llx phys 0x%08x bytes]\n",
3671408cc1fSYuval Mintz 		   p_iov->bulletin.p_virt,
3681408cc1fSYuval Mintz 		   (u64)p_iov->bulletin.phys, p_iov->bulletin.size);
3691408cc1fSYuval Mintz 
3701408cc1fSYuval Mintz 	mutex_init(&p_iov->mutex);
3711408cc1fSYuval Mintz 
3721408cc1fSYuval Mintz 	p_hwfn->vf_iov_info = p_iov;
3731408cc1fSYuval Mintz 
3741408cc1fSYuval Mintz 	p_hwfn->hw_info.personality = QED_PCI_ETH;
3751408cc1fSYuval Mintz 
3761408cc1fSYuval Mintz 	return qed_vf_pf_acquire(p_hwfn);
3771408cc1fSYuval Mintz 
3781408cc1fSYuval Mintz free_vf2pf_request:
3791408cc1fSYuval Mintz 	dma_free_coherent(&p_hwfn->cdev->pdev->dev,
3801408cc1fSYuval Mintz 			  sizeof(union vfpf_tlvs),
3811408cc1fSYuval Mintz 			  p_iov->vf2pf_request, p_iov->vf2pf_request_phys);
3821408cc1fSYuval Mintz free_p_iov:
3831408cc1fSYuval Mintz 	kfree(p_iov);
3841408cc1fSYuval Mintz 
3851408cc1fSYuval Mintz 	return -ENOMEM;
3861408cc1fSYuval Mintz }
387d8c2c7e3SYuval Mintz #define TSTORM_QZONE_START   PXP_VF_BAR0_START_SDM_ZONE_A
388d8c2c7e3SYuval Mintz #define MSTORM_QZONE_START(dev)   (TSTORM_QZONE_START +	\
389d8c2c7e3SYuval Mintz 				   (TSTORM_QZONE_SIZE * NUM_OF_L2_QUEUES(dev)))
3901408cc1fSYuval Mintz 
391dacd88d6SYuval Mintz int qed_vf_pf_rxq_start(struct qed_hwfn *p_hwfn,
392dacd88d6SYuval Mintz 			u8 rx_qid,
393dacd88d6SYuval Mintz 			u16 sb,
394dacd88d6SYuval Mintz 			u8 sb_index,
395dacd88d6SYuval Mintz 			u16 bd_max_bytes,
396dacd88d6SYuval Mintz 			dma_addr_t bd_chain_phys_addr,
397dacd88d6SYuval Mintz 			dma_addr_t cqe_pbl_addr,
398dacd88d6SYuval Mintz 			u16 cqe_pbl_size, void __iomem **pp_prod)
399dacd88d6SYuval Mintz {
400dacd88d6SYuval Mintz 	struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info;
401dacd88d6SYuval Mintz 	struct pfvf_start_queue_resp_tlv *resp;
402dacd88d6SYuval Mintz 	struct vfpf_start_rxq_tlv *req;
403dacd88d6SYuval Mintz 	int rc;
404dacd88d6SYuval Mintz 
405dacd88d6SYuval Mintz 	/* clear mailbox and prep first tlv */
406dacd88d6SYuval Mintz 	req = qed_vf_pf_prep(p_hwfn, CHANNEL_TLV_START_RXQ, sizeof(*req));
407dacd88d6SYuval Mintz 
408dacd88d6SYuval Mintz 	req->rx_qid = rx_qid;
409dacd88d6SYuval Mintz 	req->cqe_pbl_addr = cqe_pbl_addr;
410dacd88d6SYuval Mintz 	req->cqe_pbl_size = cqe_pbl_size;
411dacd88d6SYuval Mintz 	req->rxq_addr = bd_chain_phys_addr;
412dacd88d6SYuval Mintz 	req->hw_sb = sb;
413dacd88d6SYuval Mintz 	req->sb_index = sb_index;
414dacd88d6SYuval Mintz 	req->bd_max_bytes = bd_max_bytes;
415dacd88d6SYuval Mintz 	req->stat_id = -1;
416dacd88d6SYuval Mintz 
417d8c2c7e3SYuval Mintz 	/* If PF is legacy, we'll need to calculate producers ourselves
418d8c2c7e3SYuval Mintz 	 * as well as clean them.
419d8c2c7e3SYuval Mintz 	 */
420d8c2c7e3SYuval Mintz 	if (pp_prod && p_iov->b_pre_fp_hsi) {
421d8c2c7e3SYuval Mintz 		u8 hw_qid = p_iov->acquire_resp.resc.hw_qid[rx_qid];
422d8c2c7e3SYuval Mintz 		u32 init_prod_val = 0;
423d8c2c7e3SYuval Mintz 
424d8c2c7e3SYuval Mintz 		*pp_prod = (u8 __iomem *)p_hwfn->regview +
425d8c2c7e3SYuval Mintz 					 MSTORM_QZONE_START(p_hwfn->cdev) +
426d8c2c7e3SYuval Mintz 					 hw_qid * MSTORM_QZONE_SIZE;
427d8c2c7e3SYuval Mintz 
428d8c2c7e3SYuval Mintz 		/* Init the rcq, rx bd and rx sge (if valid) producers to 0 */
429d8c2c7e3SYuval Mintz 		__internal_ram_wr(p_hwfn, *pp_prod, sizeof(u32),
430d8c2c7e3SYuval Mintz 				  (u32 *)(&init_prod_val));
431d8c2c7e3SYuval Mintz 	}
432dacd88d6SYuval Mintz 	/* add list termination tlv */
433dacd88d6SYuval Mintz 	qed_add_tlv(p_hwfn, &p_iov->offset,
434dacd88d6SYuval Mintz 		    CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv));
435dacd88d6SYuval Mintz 
436dacd88d6SYuval Mintz 	resp = &p_iov->pf2vf_reply->queue_start;
437dacd88d6SYuval Mintz 	rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp));
438dacd88d6SYuval Mintz 	if (rc)
439b0bccb69SYuval Mintz 		goto exit;
440dacd88d6SYuval Mintz 
441b0bccb69SYuval Mintz 	if (resp->hdr.status != PFVF_STATUS_SUCCESS) {
442b0bccb69SYuval Mintz 		rc = -EINVAL;
443b0bccb69SYuval Mintz 		goto exit;
444b0bccb69SYuval Mintz 	}
445dacd88d6SYuval Mintz 
446dacd88d6SYuval Mintz 	/* Learn the address of the producer from the response */
447d8c2c7e3SYuval Mintz 	if (pp_prod && !p_iov->b_pre_fp_hsi) {
448b21290b7SYuval Mintz 		u32 init_prod_val = 0;
449dacd88d6SYuval Mintz 
450dacd88d6SYuval Mintz 		*pp_prod = (u8 __iomem *)p_hwfn->regview + resp->offset;
451dacd88d6SYuval Mintz 		DP_VERBOSE(p_hwfn, QED_MSG_IOV,
452dacd88d6SYuval Mintz 			   "Rxq[0x%02x]: producer at %p [offset 0x%08x]\n",
453dacd88d6SYuval Mintz 			   rx_qid, *pp_prod, resp->offset);
454dacd88d6SYuval Mintz 
455dacd88d6SYuval Mintz 		/* Init the rcq, rx bd and rx sge (if valid) producers to 0 */
456b21290b7SYuval Mintz 		__internal_ram_wr(p_hwfn, *pp_prod, sizeof(u32),
457dacd88d6SYuval Mintz 				  (u32 *)&init_prod_val);
458dacd88d6SYuval Mintz 	}
459b0bccb69SYuval Mintz exit:
460b0bccb69SYuval Mintz 	qed_vf_pf_req_end(p_hwfn, rc);
461dacd88d6SYuval Mintz 
462dacd88d6SYuval Mintz 	return rc;
463dacd88d6SYuval Mintz }
464dacd88d6SYuval Mintz 
465dacd88d6SYuval Mintz int qed_vf_pf_rxq_stop(struct qed_hwfn *p_hwfn, u16 rx_qid, bool cqe_completion)
466dacd88d6SYuval Mintz {
467dacd88d6SYuval Mintz 	struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info;
468dacd88d6SYuval Mintz 	struct vfpf_stop_rxqs_tlv *req;
469dacd88d6SYuval Mintz 	struct pfvf_def_resp_tlv *resp;
470dacd88d6SYuval Mintz 	int rc;
471dacd88d6SYuval Mintz 
472dacd88d6SYuval Mintz 	/* clear mailbox and prep first tlv */
473dacd88d6SYuval Mintz 	req = qed_vf_pf_prep(p_hwfn, CHANNEL_TLV_STOP_RXQS, sizeof(*req));
474dacd88d6SYuval Mintz 
475dacd88d6SYuval Mintz 	req->rx_qid = rx_qid;
476dacd88d6SYuval Mintz 	req->num_rxqs = 1;
477dacd88d6SYuval Mintz 	req->cqe_completion = cqe_completion;
478dacd88d6SYuval Mintz 
479dacd88d6SYuval Mintz 	/* add list termination tlv */
480dacd88d6SYuval Mintz 	qed_add_tlv(p_hwfn, &p_iov->offset,
481dacd88d6SYuval Mintz 		    CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv));
482dacd88d6SYuval Mintz 
483dacd88d6SYuval Mintz 	resp = &p_iov->pf2vf_reply->default_resp;
484dacd88d6SYuval Mintz 	rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp));
485dacd88d6SYuval Mintz 	if (rc)
486b0bccb69SYuval Mintz 		goto exit;
487dacd88d6SYuval Mintz 
488b0bccb69SYuval Mintz 	if (resp->hdr.status != PFVF_STATUS_SUCCESS) {
489b0bccb69SYuval Mintz 		rc = -EINVAL;
490b0bccb69SYuval Mintz 		goto exit;
491b0bccb69SYuval Mintz 	}
492b0bccb69SYuval Mintz 
493b0bccb69SYuval Mintz exit:
494b0bccb69SYuval Mintz 	qed_vf_pf_req_end(p_hwfn, rc);
495dacd88d6SYuval Mintz 
496dacd88d6SYuval Mintz 	return rc;
497dacd88d6SYuval Mintz }
498dacd88d6SYuval Mintz 
499dacd88d6SYuval Mintz int qed_vf_pf_txq_start(struct qed_hwfn *p_hwfn,
500dacd88d6SYuval Mintz 			u16 tx_queue_id,
501dacd88d6SYuval Mintz 			u16 sb,
502dacd88d6SYuval Mintz 			u8 sb_index,
503dacd88d6SYuval Mintz 			dma_addr_t pbl_addr,
504dacd88d6SYuval Mintz 			u16 pbl_size, void __iomem **pp_doorbell)
505dacd88d6SYuval Mintz {
506dacd88d6SYuval Mintz 	struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info;
5075040acf5SYuval Mintz 	struct pfvf_start_queue_resp_tlv *resp;
508dacd88d6SYuval Mintz 	struct vfpf_start_txq_tlv *req;
509dacd88d6SYuval Mintz 	int rc;
510dacd88d6SYuval Mintz 
511dacd88d6SYuval Mintz 	/* clear mailbox and prep first tlv */
512dacd88d6SYuval Mintz 	req = qed_vf_pf_prep(p_hwfn, CHANNEL_TLV_START_TXQ, sizeof(*req));
513dacd88d6SYuval Mintz 
514dacd88d6SYuval Mintz 	req->tx_qid = tx_queue_id;
515dacd88d6SYuval Mintz 
516dacd88d6SYuval Mintz 	/* Tx */
517dacd88d6SYuval Mintz 	req->pbl_addr = pbl_addr;
518dacd88d6SYuval Mintz 	req->pbl_size = pbl_size;
519dacd88d6SYuval Mintz 	req->hw_sb = sb;
520dacd88d6SYuval Mintz 	req->sb_index = sb_index;
521dacd88d6SYuval Mintz 
522dacd88d6SYuval Mintz 	/* add list termination tlv */
523dacd88d6SYuval Mintz 	qed_add_tlv(p_hwfn, &p_iov->offset,
524dacd88d6SYuval Mintz 		    CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv));
525dacd88d6SYuval Mintz 
5265040acf5SYuval Mintz 	resp = &p_iov->pf2vf_reply->queue_start;
527dacd88d6SYuval Mintz 	rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp));
528dacd88d6SYuval Mintz 	if (rc)
5295040acf5SYuval Mintz 		goto exit;
530dacd88d6SYuval Mintz 
5315040acf5SYuval Mintz 	if (resp->hdr.status != PFVF_STATUS_SUCCESS) {
5325040acf5SYuval Mintz 		rc = -EINVAL;
5335040acf5SYuval Mintz 		goto exit;
5345040acf5SYuval Mintz 	}
535dacd88d6SYuval Mintz 
536dacd88d6SYuval Mintz 	if (pp_doorbell) {
537d8c2c7e3SYuval Mintz 		/* Modern PFs provide the actual offsets, while legacy
538d8c2c7e3SYuval Mintz 		 * provided only the queue id.
539d8c2c7e3SYuval Mintz 		 */
540d8c2c7e3SYuval Mintz 		if (!p_iov->b_pre_fp_hsi) {
541d8c2c7e3SYuval Mintz 			*pp_doorbell = (u8 __iomem *)p_hwfn->doorbells +
542d8c2c7e3SYuval Mintz 						     resp->offset;
543d8c2c7e3SYuval Mintz 		} else {
544d8c2c7e3SYuval Mintz 			u8 cid = p_iov->acquire_resp.resc.cid[tx_queue_id];
545d8c2c7e3SYuval Mintz 			u32 db_addr;
546d8c2c7e3SYuval Mintz 
54751ff1725SRam Amrani 			db_addr = qed_db_addr_vf(cid, DQ_DEMS_LEGACY);
548d8c2c7e3SYuval Mintz 			*pp_doorbell = (u8 __iomem *)p_hwfn->doorbells +
549d8c2c7e3SYuval Mintz 						     db_addr;
550d8c2c7e3SYuval Mintz 		}
551dacd88d6SYuval Mintz 
5525040acf5SYuval Mintz 		DP_VERBOSE(p_hwfn, QED_MSG_IOV,
5535040acf5SYuval Mintz 			   "Txq[0x%02x]: doorbell at %p [offset 0x%08x]\n",
5545040acf5SYuval Mintz 			   tx_queue_id, *pp_doorbell, resp->offset);
555dacd88d6SYuval Mintz 	}
5565040acf5SYuval Mintz exit:
557b0bccb69SYuval Mintz 	qed_vf_pf_req_end(p_hwfn, rc);
558dacd88d6SYuval Mintz 
559dacd88d6SYuval Mintz 	return rc;
560dacd88d6SYuval Mintz }
561dacd88d6SYuval Mintz 
562dacd88d6SYuval Mintz int qed_vf_pf_txq_stop(struct qed_hwfn *p_hwfn, u16 tx_qid)
563dacd88d6SYuval Mintz {
564dacd88d6SYuval Mintz 	struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info;
565dacd88d6SYuval Mintz 	struct vfpf_stop_txqs_tlv *req;
566dacd88d6SYuval Mintz 	struct pfvf_def_resp_tlv *resp;
567dacd88d6SYuval Mintz 	int rc;
568dacd88d6SYuval Mintz 
569dacd88d6SYuval Mintz 	/* clear mailbox and prep first tlv */
570dacd88d6SYuval Mintz 	req = qed_vf_pf_prep(p_hwfn, CHANNEL_TLV_STOP_TXQS, sizeof(*req));
571dacd88d6SYuval Mintz 
572dacd88d6SYuval Mintz 	req->tx_qid = tx_qid;
573dacd88d6SYuval Mintz 	req->num_txqs = 1;
574dacd88d6SYuval Mintz 
575dacd88d6SYuval Mintz 	/* add list termination tlv */
576dacd88d6SYuval Mintz 	qed_add_tlv(p_hwfn, &p_iov->offset,
577dacd88d6SYuval Mintz 		    CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv));
578dacd88d6SYuval Mintz 
579dacd88d6SYuval Mintz 	resp = &p_iov->pf2vf_reply->default_resp;
580dacd88d6SYuval Mintz 	rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp));
581dacd88d6SYuval Mintz 	if (rc)
582b0bccb69SYuval Mintz 		goto exit;
583dacd88d6SYuval Mintz 
584b0bccb69SYuval Mintz 	if (resp->hdr.status != PFVF_STATUS_SUCCESS) {
585b0bccb69SYuval Mintz 		rc = -EINVAL;
586b0bccb69SYuval Mintz 		goto exit;
587b0bccb69SYuval Mintz 	}
588b0bccb69SYuval Mintz 
589b0bccb69SYuval Mintz exit:
590b0bccb69SYuval Mintz 	qed_vf_pf_req_end(p_hwfn, rc);
591dacd88d6SYuval Mintz 
592dacd88d6SYuval Mintz 	return rc;
593dacd88d6SYuval Mintz }
594dacd88d6SYuval Mintz 
595dacd88d6SYuval Mintz int qed_vf_pf_vport_start(struct qed_hwfn *p_hwfn,
596dacd88d6SYuval Mintz 			  u8 vport_id,
597dacd88d6SYuval Mintz 			  u16 mtu,
598dacd88d6SYuval Mintz 			  u8 inner_vlan_removal,
599dacd88d6SYuval Mintz 			  enum qed_tpa_mode tpa_mode,
60008feecd7SYuval Mintz 			  u8 max_buffers_per_cqe, u8 only_untagged)
601dacd88d6SYuval Mintz {
602dacd88d6SYuval Mintz 	struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info;
603dacd88d6SYuval Mintz 	struct vfpf_vport_start_tlv *req;
604dacd88d6SYuval Mintz 	struct pfvf_def_resp_tlv *resp;
605dacd88d6SYuval Mintz 	int rc, i;
606dacd88d6SYuval Mintz 
607dacd88d6SYuval Mintz 	/* clear mailbox and prep first tlv */
608dacd88d6SYuval Mintz 	req = qed_vf_pf_prep(p_hwfn, CHANNEL_TLV_VPORT_START, sizeof(*req));
609dacd88d6SYuval Mintz 
610dacd88d6SYuval Mintz 	req->mtu = mtu;
611dacd88d6SYuval Mintz 	req->vport_id = vport_id;
612dacd88d6SYuval Mintz 	req->inner_vlan_removal = inner_vlan_removal;
613dacd88d6SYuval Mintz 	req->tpa_mode = tpa_mode;
614dacd88d6SYuval Mintz 	req->max_buffers_per_cqe = max_buffers_per_cqe;
61508feecd7SYuval Mintz 	req->only_untagged = only_untagged;
616dacd88d6SYuval Mintz 
617dacd88d6SYuval Mintz 	/* status blocks */
618dacd88d6SYuval Mintz 	for (i = 0; i < p_hwfn->vf_iov_info->acquire_resp.resc.num_sbs; i++)
619dacd88d6SYuval Mintz 		if (p_hwfn->sbs_info[i])
620dacd88d6SYuval Mintz 			req->sb_addr[i] = p_hwfn->sbs_info[i]->sb_phys;
621dacd88d6SYuval Mintz 
622dacd88d6SYuval Mintz 	/* add list termination tlv */
623dacd88d6SYuval Mintz 	qed_add_tlv(p_hwfn, &p_iov->offset,
624dacd88d6SYuval Mintz 		    CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv));
625dacd88d6SYuval Mintz 
626dacd88d6SYuval Mintz 	resp = &p_iov->pf2vf_reply->default_resp;
627dacd88d6SYuval Mintz 	rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp));
628dacd88d6SYuval Mintz 	if (rc)
629b0bccb69SYuval Mintz 		goto exit;
630dacd88d6SYuval Mintz 
631b0bccb69SYuval Mintz 	if (resp->hdr.status != PFVF_STATUS_SUCCESS) {
632b0bccb69SYuval Mintz 		rc = -EINVAL;
633b0bccb69SYuval Mintz 		goto exit;
634b0bccb69SYuval Mintz 	}
635b0bccb69SYuval Mintz 
636b0bccb69SYuval Mintz exit:
637b0bccb69SYuval Mintz 	qed_vf_pf_req_end(p_hwfn, rc);
638dacd88d6SYuval Mintz 
639dacd88d6SYuval Mintz 	return rc;
640dacd88d6SYuval Mintz }
641dacd88d6SYuval Mintz 
642dacd88d6SYuval Mintz int qed_vf_pf_vport_stop(struct qed_hwfn *p_hwfn)
643dacd88d6SYuval Mintz {
644dacd88d6SYuval Mintz 	struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info;
645dacd88d6SYuval Mintz 	struct pfvf_def_resp_tlv *resp = &p_iov->pf2vf_reply->default_resp;
646dacd88d6SYuval Mintz 	int rc;
647dacd88d6SYuval Mintz 
648dacd88d6SYuval Mintz 	/* clear mailbox and prep first tlv */
649dacd88d6SYuval Mintz 	qed_vf_pf_prep(p_hwfn, CHANNEL_TLV_VPORT_TEARDOWN,
650dacd88d6SYuval Mintz 		       sizeof(struct vfpf_first_tlv));
651dacd88d6SYuval Mintz 
652dacd88d6SYuval Mintz 	/* add list termination tlv */
653dacd88d6SYuval Mintz 	qed_add_tlv(p_hwfn, &p_iov->offset,
654dacd88d6SYuval Mintz 		    CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv));
655dacd88d6SYuval Mintz 
656dacd88d6SYuval Mintz 	rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp));
657dacd88d6SYuval Mintz 	if (rc)
658b0bccb69SYuval Mintz 		goto exit;
659dacd88d6SYuval Mintz 
660b0bccb69SYuval Mintz 	if (resp->hdr.status != PFVF_STATUS_SUCCESS) {
661b0bccb69SYuval Mintz 		rc = -EINVAL;
662b0bccb69SYuval Mintz 		goto exit;
663b0bccb69SYuval Mintz 	}
664b0bccb69SYuval Mintz 
665b0bccb69SYuval Mintz exit:
666b0bccb69SYuval Mintz 	qed_vf_pf_req_end(p_hwfn, rc);
667dacd88d6SYuval Mintz 
668dacd88d6SYuval Mintz 	return rc;
669dacd88d6SYuval Mintz }
670dacd88d6SYuval Mintz 
671dacd88d6SYuval Mintz static bool
672dacd88d6SYuval Mintz qed_vf_handle_vp_update_is_needed(struct qed_hwfn *p_hwfn,
673dacd88d6SYuval Mintz 				  struct qed_sp_vport_update_params *p_data,
674dacd88d6SYuval Mintz 				  u16 tlv)
675dacd88d6SYuval Mintz {
676dacd88d6SYuval Mintz 	switch (tlv) {
677dacd88d6SYuval Mintz 	case CHANNEL_TLV_VPORT_UPDATE_ACTIVATE:
678dacd88d6SYuval Mintz 		return !!(p_data->update_vport_active_rx_flg ||
679dacd88d6SYuval Mintz 			  p_data->update_vport_active_tx_flg);
68017b235c1SYuval Mintz 	case CHANNEL_TLV_VPORT_UPDATE_TX_SWITCH:
68117b235c1SYuval Mintz 		return !!p_data->update_tx_switching_flg;
68217b235c1SYuval Mintz 	case CHANNEL_TLV_VPORT_UPDATE_VLAN_STRIP:
68317b235c1SYuval Mintz 		return !!p_data->update_inner_vlan_removal_flg;
68408feecd7SYuval Mintz 	case CHANNEL_TLV_VPORT_UPDATE_ACCEPT_ANY_VLAN:
68508feecd7SYuval Mintz 		return !!p_data->update_accept_any_vlan_flg;
686dacd88d6SYuval Mintz 	case CHANNEL_TLV_VPORT_UPDATE_MCAST:
687dacd88d6SYuval Mintz 		return !!p_data->update_approx_mcast_flg;
688dacd88d6SYuval Mintz 	case CHANNEL_TLV_VPORT_UPDATE_ACCEPT_PARAM:
689dacd88d6SYuval Mintz 		return !!(p_data->accept_flags.update_rx_mode_config ||
690dacd88d6SYuval Mintz 			  p_data->accept_flags.update_tx_mode_config);
691dacd88d6SYuval Mintz 	case CHANNEL_TLV_VPORT_UPDATE_RSS:
692dacd88d6SYuval Mintz 		return !!p_data->rss_params;
69317b235c1SYuval Mintz 	case CHANNEL_TLV_VPORT_UPDATE_SGE_TPA:
69417b235c1SYuval Mintz 		return !!p_data->sge_tpa_params;
695dacd88d6SYuval Mintz 	default:
696dacd88d6SYuval Mintz 		DP_INFO(p_hwfn, "Unexpected vport-update TLV[%d]\n",
697dacd88d6SYuval Mintz 			tlv);
698dacd88d6SYuval Mintz 		return false;
699dacd88d6SYuval Mintz 	}
700dacd88d6SYuval Mintz }
701dacd88d6SYuval Mintz 
702dacd88d6SYuval Mintz static void
703dacd88d6SYuval Mintz qed_vf_handle_vp_update_tlvs_resp(struct qed_hwfn *p_hwfn,
704dacd88d6SYuval Mintz 				  struct qed_sp_vport_update_params *p_data)
705dacd88d6SYuval Mintz {
706dacd88d6SYuval Mintz 	struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info;
707dacd88d6SYuval Mintz 	struct pfvf_def_resp_tlv *p_resp;
708dacd88d6SYuval Mintz 	u16 tlv;
709dacd88d6SYuval Mintz 
710dacd88d6SYuval Mintz 	for (tlv = CHANNEL_TLV_VPORT_UPDATE_ACTIVATE;
711dacd88d6SYuval Mintz 	     tlv < CHANNEL_TLV_VPORT_UPDATE_MAX; tlv++) {
712dacd88d6SYuval Mintz 		if (!qed_vf_handle_vp_update_is_needed(p_hwfn, p_data, tlv))
713dacd88d6SYuval Mintz 			continue;
714dacd88d6SYuval Mintz 
715dacd88d6SYuval Mintz 		p_resp = (struct pfvf_def_resp_tlv *)
716dacd88d6SYuval Mintz 			 qed_iov_search_list_tlvs(p_hwfn, p_iov->pf2vf_reply,
717dacd88d6SYuval Mintz 						  tlv);
718dacd88d6SYuval Mintz 		if (p_resp && p_resp->hdr.status)
719dacd88d6SYuval Mintz 			DP_VERBOSE(p_hwfn, QED_MSG_IOV,
720dacd88d6SYuval Mintz 				   "TLV[%d] Configuration %s\n",
721dacd88d6SYuval Mintz 				   tlv,
722dacd88d6SYuval Mintz 				   (p_resp && p_resp->hdr.status) ? "succeeded"
723dacd88d6SYuval Mintz 								  : "failed");
724dacd88d6SYuval Mintz 	}
725dacd88d6SYuval Mintz }
726dacd88d6SYuval Mintz 
727dacd88d6SYuval Mintz int qed_vf_pf_vport_update(struct qed_hwfn *p_hwfn,
728dacd88d6SYuval Mintz 			   struct qed_sp_vport_update_params *p_params)
729dacd88d6SYuval Mintz {
730dacd88d6SYuval Mintz 	struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info;
731dacd88d6SYuval Mintz 	struct vfpf_vport_update_tlv *req;
732dacd88d6SYuval Mintz 	struct pfvf_def_resp_tlv *resp;
733dacd88d6SYuval Mintz 	u8 update_rx, update_tx;
734dacd88d6SYuval Mintz 	u32 resp_size = 0;
735dacd88d6SYuval Mintz 	u16 size, tlv;
736dacd88d6SYuval Mintz 	int rc;
737dacd88d6SYuval Mintz 
738dacd88d6SYuval Mintz 	resp = &p_iov->pf2vf_reply->default_resp;
739dacd88d6SYuval Mintz 	resp_size = sizeof(*resp);
740dacd88d6SYuval Mintz 
741dacd88d6SYuval Mintz 	update_rx = p_params->update_vport_active_rx_flg;
742dacd88d6SYuval Mintz 	update_tx = p_params->update_vport_active_tx_flg;
743dacd88d6SYuval Mintz 
744dacd88d6SYuval Mintz 	/* clear mailbox and prep header tlv */
745dacd88d6SYuval Mintz 	qed_vf_pf_prep(p_hwfn, CHANNEL_TLV_VPORT_UPDATE, sizeof(*req));
746dacd88d6SYuval Mintz 
747dacd88d6SYuval Mintz 	/* Prepare extended tlvs */
748dacd88d6SYuval Mintz 	if (update_rx || update_tx) {
749dacd88d6SYuval Mintz 		struct vfpf_vport_update_activate_tlv *p_act_tlv;
750dacd88d6SYuval Mintz 
751dacd88d6SYuval Mintz 		size = sizeof(struct vfpf_vport_update_activate_tlv);
752dacd88d6SYuval Mintz 		p_act_tlv = qed_add_tlv(p_hwfn, &p_iov->offset,
753dacd88d6SYuval Mintz 					CHANNEL_TLV_VPORT_UPDATE_ACTIVATE,
754dacd88d6SYuval Mintz 					size);
755dacd88d6SYuval Mintz 		resp_size += sizeof(struct pfvf_def_resp_tlv);
756dacd88d6SYuval Mintz 
757dacd88d6SYuval Mintz 		if (update_rx) {
758dacd88d6SYuval Mintz 			p_act_tlv->update_rx = update_rx;
759dacd88d6SYuval Mintz 			p_act_tlv->active_rx = p_params->vport_active_rx_flg;
760dacd88d6SYuval Mintz 		}
761dacd88d6SYuval Mintz 
762dacd88d6SYuval Mintz 		if (update_tx) {
763dacd88d6SYuval Mintz 			p_act_tlv->update_tx = update_tx;
764dacd88d6SYuval Mintz 			p_act_tlv->active_tx = p_params->vport_active_tx_flg;
765dacd88d6SYuval Mintz 		}
766dacd88d6SYuval Mintz 	}
767dacd88d6SYuval Mintz 
768831bfb0eSYuval Mintz 	if (p_params->update_tx_switching_flg) {
769831bfb0eSYuval Mintz 		struct vfpf_vport_update_tx_switch_tlv *p_tx_switch_tlv;
770831bfb0eSYuval Mintz 
771831bfb0eSYuval Mintz 		size = sizeof(struct vfpf_vport_update_tx_switch_tlv);
772831bfb0eSYuval Mintz 		tlv = CHANNEL_TLV_VPORT_UPDATE_TX_SWITCH;
773831bfb0eSYuval Mintz 		p_tx_switch_tlv = qed_add_tlv(p_hwfn, &p_iov->offset,
774831bfb0eSYuval Mintz 					      tlv, size);
775831bfb0eSYuval Mintz 		resp_size += sizeof(struct pfvf_def_resp_tlv);
776831bfb0eSYuval Mintz 
777831bfb0eSYuval Mintz 		p_tx_switch_tlv->tx_switching = p_params->tx_switching_flg;
778831bfb0eSYuval Mintz 	}
779831bfb0eSYuval Mintz 
780dacd88d6SYuval Mintz 	if (p_params->update_approx_mcast_flg) {
781dacd88d6SYuval Mintz 		struct vfpf_vport_update_mcast_bin_tlv *p_mcast_tlv;
782dacd88d6SYuval Mintz 
783dacd88d6SYuval Mintz 		size = sizeof(struct vfpf_vport_update_mcast_bin_tlv);
784dacd88d6SYuval Mintz 		p_mcast_tlv = qed_add_tlv(p_hwfn, &p_iov->offset,
785dacd88d6SYuval Mintz 					  CHANNEL_TLV_VPORT_UPDATE_MCAST, size);
786dacd88d6SYuval Mintz 		resp_size += sizeof(struct pfvf_def_resp_tlv);
787dacd88d6SYuval Mintz 
788dacd88d6SYuval Mintz 		memcpy(p_mcast_tlv->bins, p_params->bins,
789dacd88d6SYuval Mintz 		       sizeof(unsigned long) * ETH_MULTICAST_MAC_BINS_IN_REGS);
790dacd88d6SYuval Mintz 	}
791dacd88d6SYuval Mintz 
792dacd88d6SYuval Mintz 	update_rx = p_params->accept_flags.update_rx_mode_config;
793dacd88d6SYuval Mintz 	update_tx = p_params->accept_flags.update_tx_mode_config;
794dacd88d6SYuval Mintz 
795dacd88d6SYuval Mintz 	if (update_rx || update_tx) {
796dacd88d6SYuval Mintz 		struct vfpf_vport_update_accept_param_tlv *p_accept_tlv;
797dacd88d6SYuval Mintz 
798dacd88d6SYuval Mintz 		tlv = CHANNEL_TLV_VPORT_UPDATE_ACCEPT_PARAM;
799dacd88d6SYuval Mintz 		size = sizeof(struct vfpf_vport_update_accept_param_tlv);
800dacd88d6SYuval Mintz 		p_accept_tlv = qed_add_tlv(p_hwfn, &p_iov->offset, tlv, size);
801dacd88d6SYuval Mintz 		resp_size += sizeof(struct pfvf_def_resp_tlv);
802dacd88d6SYuval Mintz 
803dacd88d6SYuval Mintz 		if (update_rx) {
804dacd88d6SYuval Mintz 			p_accept_tlv->update_rx_mode = update_rx;
805dacd88d6SYuval Mintz 			p_accept_tlv->rx_accept_filter =
806dacd88d6SYuval Mintz 			    p_params->accept_flags.rx_accept_filter;
807dacd88d6SYuval Mintz 		}
808dacd88d6SYuval Mintz 
809dacd88d6SYuval Mintz 		if (update_tx) {
810dacd88d6SYuval Mintz 			p_accept_tlv->update_tx_mode = update_tx;
811dacd88d6SYuval Mintz 			p_accept_tlv->tx_accept_filter =
812dacd88d6SYuval Mintz 			    p_params->accept_flags.tx_accept_filter;
813dacd88d6SYuval Mintz 		}
814dacd88d6SYuval Mintz 	}
815dacd88d6SYuval Mintz 
816dacd88d6SYuval Mintz 	if (p_params->rss_params) {
817dacd88d6SYuval Mintz 		struct qed_rss_params *rss_params = p_params->rss_params;
818dacd88d6SYuval Mintz 		struct vfpf_vport_update_rss_tlv *p_rss_tlv;
819dacd88d6SYuval Mintz 
820dacd88d6SYuval Mintz 		size = sizeof(struct vfpf_vport_update_rss_tlv);
821dacd88d6SYuval Mintz 		p_rss_tlv = qed_add_tlv(p_hwfn,
822dacd88d6SYuval Mintz 					&p_iov->offset,
823dacd88d6SYuval Mintz 					CHANNEL_TLV_VPORT_UPDATE_RSS, size);
824dacd88d6SYuval Mintz 		resp_size += sizeof(struct pfvf_def_resp_tlv);
825dacd88d6SYuval Mintz 
826dacd88d6SYuval Mintz 		if (rss_params->update_rss_config)
827dacd88d6SYuval Mintz 			p_rss_tlv->update_rss_flags |=
828dacd88d6SYuval Mintz 			    VFPF_UPDATE_RSS_CONFIG_FLAG;
829dacd88d6SYuval Mintz 		if (rss_params->update_rss_capabilities)
830dacd88d6SYuval Mintz 			p_rss_tlv->update_rss_flags |=
831dacd88d6SYuval Mintz 			    VFPF_UPDATE_RSS_CAPS_FLAG;
832dacd88d6SYuval Mintz 		if (rss_params->update_rss_ind_table)
833dacd88d6SYuval Mintz 			p_rss_tlv->update_rss_flags |=
834dacd88d6SYuval Mintz 			    VFPF_UPDATE_RSS_IND_TABLE_FLAG;
835dacd88d6SYuval Mintz 		if (rss_params->update_rss_key)
836dacd88d6SYuval Mintz 			p_rss_tlv->update_rss_flags |= VFPF_UPDATE_RSS_KEY_FLAG;
837dacd88d6SYuval Mintz 
838dacd88d6SYuval Mintz 		p_rss_tlv->rss_enable = rss_params->rss_enable;
839dacd88d6SYuval Mintz 		p_rss_tlv->rss_caps = rss_params->rss_caps;
840dacd88d6SYuval Mintz 		p_rss_tlv->rss_table_size_log = rss_params->rss_table_size_log;
841dacd88d6SYuval Mintz 		memcpy(p_rss_tlv->rss_ind_table, rss_params->rss_ind_table,
842dacd88d6SYuval Mintz 		       sizeof(rss_params->rss_ind_table));
843dacd88d6SYuval Mintz 		memcpy(p_rss_tlv->rss_key, rss_params->rss_key,
844dacd88d6SYuval Mintz 		       sizeof(rss_params->rss_key));
845dacd88d6SYuval Mintz 	}
846dacd88d6SYuval Mintz 
84708feecd7SYuval Mintz 	if (p_params->update_accept_any_vlan_flg) {
84808feecd7SYuval Mintz 		struct vfpf_vport_update_accept_any_vlan_tlv *p_any_vlan_tlv;
84908feecd7SYuval Mintz 
85008feecd7SYuval Mintz 		size = sizeof(struct vfpf_vport_update_accept_any_vlan_tlv);
85108feecd7SYuval Mintz 		tlv = CHANNEL_TLV_VPORT_UPDATE_ACCEPT_ANY_VLAN;
85208feecd7SYuval Mintz 		p_any_vlan_tlv = qed_add_tlv(p_hwfn, &p_iov->offset, tlv, size);
85308feecd7SYuval Mintz 
85408feecd7SYuval Mintz 		resp_size += sizeof(struct pfvf_def_resp_tlv);
85508feecd7SYuval Mintz 		p_any_vlan_tlv->accept_any_vlan = p_params->accept_any_vlan;
85608feecd7SYuval Mintz 		p_any_vlan_tlv->update_accept_any_vlan_flg =
85708feecd7SYuval Mintz 		    p_params->update_accept_any_vlan_flg;
85808feecd7SYuval Mintz 	}
85908feecd7SYuval Mintz 
860dacd88d6SYuval Mintz 	/* add list termination tlv */
861dacd88d6SYuval Mintz 	qed_add_tlv(p_hwfn, &p_iov->offset,
862dacd88d6SYuval Mintz 		    CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv));
863dacd88d6SYuval Mintz 
864dacd88d6SYuval Mintz 	rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, resp_size);
865dacd88d6SYuval Mintz 	if (rc)
866b0bccb69SYuval Mintz 		goto exit;
867dacd88d6SYuval Mintz 
868b0bccb69SYuval Mintz 	if (resp->hdr.status != PFVF_STATUS_SUCCESS) {
869b0bccb69SYuval Mintz 		rc = -EINVAL;
870b0bccb69SYuval Mintz 		goto exit;
871b0bccb69SYuval Mintz 	}
872dacd88d6SYuval Mintz 
873dacd88d6SYuval Mintz 	qed_vf_handle_vp_update_tlvs_resp(p_hwfn, p_params);
874dacd88d6SYuval Mintz 
875b0bccb69SYuval Mintz exit:
876b0bccb69SYuval Mintz 	qed_vf_pf_req_end(p_hwfn, rc);
877b0bccb69SYuval Mintz 
878dacd88d6SYuval Mintz 	return rc;
879dacd88d6SYuval Mintz }
880dacd88d6SYuval Mintz 
8810b55e27dSYuval Mintz int qed_vf_pf_reset(struct qed_hwfn *p_hwfn)
8820b55e27dSYuval Mintz {
8830b55e27dSYuval Mintz 	struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info;
8840b55e27dSYuval Mintz 	struct pfvf_def_resp_tlv *resp;
8850b55e27dSYuval Mintz 	struct vfpf_first_tlv *req;
8860b55e27dSYuval Mintz 	int rc;
8870b55e27dSYuval Mintz 
8880b55e27dSYuval Mintz 	/* clear mailbox and prep first tlv */
8890b55e27dSYuval Mintz 	req = qed_vf_pf_prep(p_hwfn, CHANNEL_TLV_CLOSE, sizeof(*req));
8900b55e27dSYuval Mintz 
8910b55e27dSYuval Mintz 	/* add list termination tlv */
8920b55e27dSYuval Mintz 	qed_add_tlv(p_hwfn, &p_iov->offset,
8930b55e27dSYuval Mintz 		    CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv));
8940b55e27dSYuval Mintz 
8950b55e27dSYuval Mintz 	resp = &p_iov->pf2vf_reply->default_resp;
8960b55e27dSYuval Mintz 	rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp));
8970b55e27dSYuval Mintz 	if (rc)
898b0bccb69SYuval Mintz 		goto exit;
8990b55e27dSYuval Mintz 
900b0bccb69SYuval Mintz 	if (resp->hdr.status != PFVF_STATUS_SUCCESS) {
901b0bccb69SYuval Mintz 		rc = -EAGAIN;
902b0bccb69SYuval Mintz 		goto exit;
903b0bccb69SYuval Mintz 	}
9040b55e27dSYuval Mintz 
9050b55e27dSYuval Mintz 	p_hwfn->b_int_enabled = 0;
9060b55e27dSYuval Mintz 
907b0bccb69SYuval Mintz exit:
908b0bccb69SYuval Mintz 	qed_vf_pf_req_end(p_hwfn, rc);
909b0bccb69SYuval Mintz 
910b0bccb69SYuval Mintz 	return rc;
9110b55e27dSYuval Mintz }
9120b55e27dSYuval Mintz 
9130b55e27dSYuval Mintz int qed_vf_pf_release(struct qed_hwfn *p_hwfn)
9140b55e27dSYuval Mintz {
9150b55e27dSYuval Mintz 	struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info;
9160b55e27dSYuval Mintz 	struct pfvf_def_resp_tlv *resp;
9170b55e27dSYuval Mintz 	struct vfpf_first_tlv *req;
9180b55e27dSYuval Mintz 	u32 size;
9190b55e27dSYuval Mintz 	int rc;
9200b55e27dSYuval Mintz 
9210b55e27dSYuval Mintz 	/* clear mailbox and prep first tlv */
9220b55e27dSYuval Mintz 	req = qed_vf_pf_prep(p_hwfn, CHANNEL_TLV_RELEASE, sizeof(*req));
9230b55e27dSYuval Mintz 
9240b55e27dSYuval Mintz 	/* add list termination tlv */
9250b55e27dSYuval Mintz 	qed_add_tlv(p_hwfn, &p_iov->offset,
9260b55e27dSYuval Mintz 		    CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv));
9270b55e27dSYuval Mintz 
9280b55e27dSYuval Mintz 	resp = &p_iov->pf2vf_reply->default_resp;
9290b55e27dSYuval Mintz 	rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp));
9300b55e27dSYuval Mintz 
9310b55e27dSYuval Mintz 	if (!rc && resp->hdr.status != PFVF_STATUS_SUCCESS)
9320b55e27dSYuval Mintz 		rc = -EAGAIN;
9330b55e27dSYuval Mintz 
934b0bccb69SYuval Mintz 	qed_vf_pf_req_end(p_hwfn, rc);
935b0bccb69SYuval Mintz 
9360b55e27dSYuval Mintz 	p_hwfn->b_int_enabled = 0;
9370b55e27dSYuval Mintz 
9380b55e27dSYuval Mintz 	if (p_iov->vf2pf_request)
9390b55e27dSYuval Mintz 		dma_free_coherent(&p_hwfn->cdev->pdev->dev,
9400b55e27dSYuval Mintz 				  sizeof(union vfpf_tlvs),
9410b55e27dSYuval Mintz 				  p_iov->vf2pf_request,
9420b55e27dSYuval Mintz 				  p_iov->vf2pf_request_phys);
9430b55e27dSYuval Mintz 	if (p_iov->pf2vf_reply)
9440b55e27dSYuval Mintz 		dma_free_coherent(&p_hwfn->cdev->pdev->dev,
9450b55e27dSYuval Mintz 				  sizeof(union pfvf_tlvs),
9460b55e27dSYuval Mintz 				  p_iov->pf2vf_reply, p_iov->pf2vf_reply_phys);
9470b55e27dSYuval Mintz 
9480b55e27dSYuval Mintz 	if (p_iov->bulletin.p_virt) {
9490b55e27dSYuval Mintz 		size = sizeof(struct qed_bulletin_content);
9500b55e27dSYuval Mintz 		dma_free_coherent(&p_hwfn->cdev->pdev->dev,
9510b55e27dSYuval Mintz 				  size,
9520b55e27dSYuval Mintz 				  p_iov->bulletin.p_virt, p_iov->bulletin.phys);
9530b55e27dSYuval Mintz 	}
9540b55e27dSYuval Mintz 
9550b55e27dSYuval Mintz 	kfree(p_hwfn->vf_iov_info);
9560b55e27dSYuval Mintz 	p_hwfn->vf_iov_info = NULL;
9570b55e27dSYuval Mintz 
9580b55e27dSYuval Mintz 	return rc;
9590b55e27dSYuval Mintz }
9600b55e27dSYuval Mintz 
961dacd88d6SYuval Mintz void qed_vf_pf_filter_mcast(struct qed_hwfn *p_hwfn,
962dacd88d6SYuval Mintz 			    struct qed_filter_mcast *p_filter_cmd)
963dacd88d6SYuval Mintz {
964dacd88d6SYuval Mintz 	struct qed_sp_vport_update_params sp_params;
965dacd88d6SYuval Mintz 	int i;
966dacd88d6SYuval Mintz 
967dacd88d6SYuval Mintz 	memset(&sp_params, 0, sizeof(sp_params));
968dacd88d6SYuval Mintz 	sp_params.update_approx_mcast_flg = 1;
969dacd88d6SYuval Mintz 
970dacd88d6SYuval Mintz 	if (p_filter_cmd->opcode == QED_FILTER_ADD) {
971dacd88d6SYuval Mintz 		for (i = 0; i < p_filter_cmd->num_mc_addrs; i++) {
972dacd88d6SYuval Mintz 			u32 bit;
973dacd88d6SYuval Mintz 
974dacd88d6SYuval Mintz 			bit = qed_mcast_bin_from_mac(p_filter_cmd->mac[i]);
975dacd88d6SYuval Mintz 			__set_bit(bit, sp_params.bins);
976dacd88d6SYuval Mintz 		}
977dacd88d6SYuval Mintz 	}
978dacd88d6SYuval Mintz 
979dacd88d6SYuval Mintz 	qed_vf_pf_vport_update(p_hwfn, &sp_params);
980dacd88d6SYuval Mintz }
981dacd88d6SYuval Mintz 
982dacd88d6SYuval Mintz int qed_vf_pf_filter_ucast(struct qed_hwfn *p_hwfn,
983dacd88d6SYuval Mintz 			   struct qed_filter_ucast *p_ucast)
984dacd88d6SYuval Mintz {
985dacd88d6SYuval Mintz 	struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info;
986dacd88d6SYuval Mintz 	struct vfpf_ucast_filter_tlv *req;
987dacd88d6SYuval Mintz 	struct pfvf_def_resp_tlv *resp;
988dacd88d6SYuval Mintz 	int rc;
989dacd88d6SYuval Mintz 
990dacd88d6SYuval Mintz 	/* clear mailbox and prep first tlv */
991dacd88d6SYuval Mintz 	req = qed_vf_pf_prep(p_hwfn, CHANNEL_TLV_UCAST_FILTER, sizeof(*req));
992dacd88d6SYuval Mintz 	req->opcode = (u8) p_ucast->opcode;
993dacd88d6SYuval Mintz 	req->type = (u8) p_ucast->type;
994dacd88d6SYuval Mintz 	memcpy(req->mac, p_ucast->mac, ETH_ALEN);
995dacd88d6SYuval Mintz 	req->vlan = p_ucast->vlan;
996dacd88d6SYuval Mintz 
997dacd88d6SYuval Mintz 	/* add list termination tlv */
998dacd88d6SYuval Mintz 	qed_add_tlv(p_hwfn, &p_iov->offset,
999dacd88d6SYuval Mintz 		    CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv));
1000dacd88d6SYuval Mintz 
1001dacd88d6SYuval Mintz 	resp = &p_iov->pf2vf_reply->default_resp;
1002dacd88d6SYuval Mintz 	rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp));
1003dacd88d6SYuval Mintz 	if (rc)
1004b0bccb69SYuval Mintz 		goto exit;
1005b0bccb69SYuval Mintz 
1006b0bccb69SYuval Mintz 	if (resp->hdr.status != PFVF_STATUS_SUCCESS) {
1007b0bccb69SYuval Mintz 		rc = -EAGAIN;
1008b0bccb69SYuval Mintz 		goto exit;
1009b0bccb69SYuval Mintz 	}
1010b0bccb69SYuval Mintz 
1011b0bccb69SYuval Mintz exit:
1012b0bccb69SYuval Mintz 	qed_vf_pf_req_end(p_hwfn, rc);
1013b0bccb69SYuval Mintz 
1014dacd88d6SYuval Mintz 	return rc;
1015dacd88d6SYuval Mintz }
1016dacd88d6SYuval Mintz 
10170b55e27dSYuval Mintz int qed_vf_pf_int_cleanup(struct qed_hwfn *p_hwfn)
10180b55e27dSYuval Mintz {
10190b55e27dSYuval Mintz 	struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info;
10200b55e27dSYuval Mintz 	struct pfvf_def_resp_tlv *resp = &p_iov->pf2vf_reply->default_resp;
10210b55e27dSYuval Mintz 	int rc;
10220b55e27dSYuval Mintz 
10230b55e27dSYuval Mintz 	/* clear mailbox and prep first tlv */
10240b55e27dSYuval Mintz 	qed_vf_pf_prep(p_hwfn, CHANNEL_TLV_INT_CLEANUP,
10250b55e27dSYuval Mintz 		       sizeof(struct vfpf_first_tlv));
10260b55e27dSYuval Mintz 
10270b55e27dSYuval Mintz 	/* add list termination tlv */
10280b55e27dSYuval Mintz 	qed_add_tlv(p_hwfn, &p_iov->offset,
10290b55e27dSYuval Mintz 		    CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv));
10300b55e27dSYuval Mintz 
10310b55e27dSYuval Mintz 	rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp));
10320b55e27dSYuval Mintz 	if (rc)
1033b0bccb69SYuval Mintz 		goto exit;
1034b0bccb69SYuval Mintz 
1035b0bccb69SYuval Mintz 	if (resp->hdr.status != PFVF_STATUS_SUCCESS) {
1036b0bccb69SYuval Mintz 		rc = -EINVAL;
1037b0bccb69SYuval Mintz 		goto exit;
1038b0bccb69SYuval Mintz 	}
1039b0bccb69SYuval Mintz 
1040b0bccb69SYuval Mintz exit:
1041b0bccb69SYuval Mintz 	qed_vf_pf_req_end(p_hwfn, rc);
1042b0bccb69SYuval Mintz 
10430b55e27dSYuval Mintz 	return rc;
10440b55e27dSYuval Mintz }
10450b55e27dSYuval Mintz 
10461408cc1fSYuval Mintz u16 qed_vf_get_igu_sb_id(struct qed_hwfn *p_hwfn, u16 sb_id)
10471408cc1fSYuval Mintz {
10481408cc1fSYuval Mintz 	struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info;
10491408cc1fSYuval Mintz 
10501408cc1fSYuval Mintz 	if (!p_iov) {
10511408cc1fSYuval Mintz 		DP_NOTICE(p_hwfn, "vf_sriov_info isn't initialized\n");
10521408cc1fSYuval Mintz 		return 0;
10531408cc1fSYuval Mintz 	}
10541408cc1fSYuval Mintz 
10551408cc1fSYuval Mintz 	return p_iov->acquire_resp.resc.hw_sbs[sb_id].hw_sb_id;
10561408cc1fSYuval Mintz }
10571408cc1fSYuval Mintz 
105836558c3dSYuval Mintz int qed_vf_read_bulletin(struct qed_hwfn *p_hwfn, u8 *p_change)
105936558c3dSYuval Mintz {
106036558c3dSYuval Mintz 	struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info;
106136558c3dSYuval Mintz 	struct qed_bulletin_content shadow;
106236558c3dSYuval Mintz 	u32 crc, crc_size;
106336558c3dSYuval Mintz 
106436558c3dSYuval Mintz 	crc_size = sizeof(p_iov->bulletin.p_virt->crc);
106536558c3dSYuval Mintz 	*p_change = 0;
106636558c3dSYuval Mintz 
106736558c3dSYuval Mintz 	/* Need to guarantee PF is not in the middle of writing it */
106836558c3dSYuval Mintz 	memcpy(&shadow, p_iov->bulletin.p_virt, p_iov->bulletin.size);
106936558c3dSYuval Mintz 
107036558c3dSYuval Mintz 	/* If version did not update, no need to do anything */
107136558c3dSYuval Mintz 	if (shadow.version == p_iov->bulletin_shadow.version)
107236558c3dSYuval Mintz 		return 0;
107336558c3dSYuval Mintz 
107436558c3dSYuval Mintz 	/* Verify the bulletin we see is valid */
107536558c3dSYuval Mintz 	crc = crc32(0, (u8 *)&shadow + crc_size,
107636558c3dSYuval Mintz 		    p_iov->bulletin.size - crc_size);
107736558c3dSYuval Mintz 	if (crc != shadow.crc)
107836558c3dSYuval Mintz 		return -EAGAIN;
107936558c3dSYuval Mintz 
108036558c3dSYuval Mintz 	/* Set the shadow bulletin and process it */
108136558c3dSYuval Mintz 	memcpy(&p_iov->bulletin_shadow, &shadow, p_iov->bulletin.size);
108236558c3dSYuval Mintz 
108336558c3dSYuval Mintz 	DP_VERBOSE(p_hwfn, QED_MSG_IOV,
108436558c3dSYuval Mintz 		   "Read a bulletin update %08x\n", shadow.version);
108536558c3dSYuval Mintz 
108636558c3dSYuval Mintz 	*p_change = 1;
108736558c3dSYuval Mintz 
108836558c3dSYuval Mintz 	return 0;
108936558c3dSYuval Mintz }
109036558c3dSYuval Mintz 
109136558c3dSYuval Mintz void __qed_vf_get_link_params(struct qed_hwfn *p_hwfn,
109236558c3dSYuval Mintz 			      struct qed_mcp_link_params *p_params,
109336558c3dSYuval Mintz 			      struct qed_bulletin_content *p_bulletin)
109436558c3dSYuval Mintz {
109536558c3dSYuval Mintz 	memset(p_params, 0, sizeof(*p_params));
109636558c3dSYuval Mintz 
109736558c3dSYuval Mintz 	p_params->speed.autoneg = p_bulletin->req_autoneg;
109836558c3dSYuval Mintz 	p_params->speed.advertised_speeds = p_bulletin->req_adv_speed;
109936558c3dSYuval Mintz 	p_params->speed.forced_speed = p_bulletin->req_forced_speed;
110036558c3dSYuval Mintz 	p_params->pause.autoneg = p_bulletin->req_autoneg_pause;
110136558c3dSYuval Mintz 	p_params->pause.forced_rx = p_bulletin->req_forced_rx;
110236558c3dSYuval Mintz 	p_params->pause.forced_tx = p_bulletin->req_forced_tx;
110336558c3dSYuval Mintz 	p_params->loopback_mode = p_bulletin->req_loopback;
110436558c3dSYuval Mintz }
110536558c3dSYuval Mintz 
110636558c3dSYuval Mintz void qed_vf_get_link_params(struct qed_hwfn *p_hwfn,
110736558c3dSYuval Mintz 			    struct qed_mcp_link_params *params)
110836558c3dSYuval Mintz {
110936558c3dSYuval Mintz 	__qed_vf_get_link_params(p_hwfn, params,
111036558c3dSYuval Mintz 				 &(p_hwfn->vf_iov_info->bulletin_shadow));
111136558c3dSYuval Mintz }
111236558c3dSYuval Mintz 
111336558c3dSYuval Mintz void __qed_vf_get_link_state(struct qed_hwfn *p_hwfn,
111436558c3dSYuval Mintz 			     struct qed_mcp_link_state *p_link,
111536558c3dSYuval Mintz 			     struct qed_bulletin_content *p_bulletin)
111636558c3dSYuval Mintz {
111736558c3dSYuval Mintz 	memset(p_link, 0, sizeof(*p_link));
111836558c3dSYuval Mintz 
111936558c3dSYuval Mintz 	p_link->link_up = p_bulletin->link_up;
112036558c3dSYuval Mintz 	p_link->speed = p_bulletin->speed;
112136558c3dSYuval Mintz 	p_link->full_duplex = p_bulletin->full_duplex;
112236558c3dSYuval Mintz 	p_link->an = p_bulletin->autoneg;
112336558c3dSYuval Mintz 	p_link->an_complete = p_bulletin->autoneg_complete;
112436558c3dSYuval Mintz 	p_link->parallel_detection = p_bulletin->parallel_detection;
112536558c3dSYuval Mintz 	p_link->pfc_enabled = p_bulletin->pfc_enabled;
112636558c3dSYuval Mintz 	p_link->partner_adv_speed = p_bulletin->partner_adv_speed;
112736558c3dSYuval Mintz 	p_link->partner_tx_flow_ctrl_en = p_bulletin->partner_tx_flow_ctrl_en;
112836558c3dSYuval Mintz 	p_link->partner_rx_flow_ctrl_en = p_bulletin->partner_rx_flow_ctrl_en;
112936558c3dSYuval Mintz 	p_link->partner_adv_pause = p_bulletin->partner_adv_pause;
113036558c3dSYuval Mintz 	p_link->sfp_tx_fault = p_bulletin->sfp_tx_fault;
113136558c3dSYuval Mintz }
113236558c3dSYuval Mintz 
113336558c3dSYuval Mintz void qed_vf_get_link_state(struct qed_hwfn *p_hwfn,
113436558c3dSYuval Mintz 			   struct qed_mcp_link_state *link)
113536558c3dSYuval Mintz {
113636558c3dSYuval Mintz 	__qed_vf_get_link_state(p_hwfn, link,
113736558c3dSYuval Mintz 				&(p_hwfn->vf_iov_info->bulletin_shadow));
113836558c3dSYuval Mintz }
113936558c3dSYuval Mintz 
114036558c3dSYuval Mintz void __qed_vf_get_link_caps(struct qed_hwfn *p_hwfn,
114136558c3dSYuval Mintz 			    struct qed_mcp_link_capabilities *p_link_caps,
114236558c3dSYuval Mintz 			    struct qed_bulletin_content *p_bulletin)
114336558c3dSYuval Mintz {
114436558c3dSYuval Mintz 	memset(p_link_caps, 0, sizeof(*p_link_caps));
114536558c3dSYuval Mintz 	p_link_caps->speed_capabilities = p_bulletin->capability_speed;
114636558c3dSYuval Mintz }
114736558c3dSYuval Mintz 
114836558c3dSYuval Mintz void qed_vf_get_link_caps(struct qed_hwfn *p_hwfn,
114936558c3dSYuval Mintz 			  struct qed_mcp_link_capabilities *p_link_caps)
115036558c3dSYuval Mintz {
115136558c3dSYuval Mintz 	__qed_vf_get_link_caps(p_hwfn, p_link_caps,
115236558c3dSYuval Mintz 			       &(p_hwfn->vf_iov_info->bulletin_shadow));
115336558c3dSYuval Mintz }
115436558c3dSYuval Mintz 
11551408cc1fSYuval Mintz void qed_vf_get_num_rxqs(struct qed_hwfn *p_hwfn, u8 *num_rxqs)
11561408cc1fSYuval Mintz {
11571408cc1fSYuval Mintz 	*num_rxqs = p_hwfn->vf_iov_info->acquire_resp.resc.num_rxqs;
11581408cc1fSYuval Mintz }
11591408cc1fSYuval Mintz 
11601408cc1fSYuval Mintz void qed_vf_get_port_mac(struct qed_hwfn *p_hwfn, u8 *port_mac)
11611408cc1fSYuval Mintz {
11621408cc1fSYuval Mintz 	memcpy(port_mac,
11631408cc1fSYuval Mintz 	       p_hwfn->vf_iov_info->acquire_resp.pfdev_info.port_mac, ETH_ALEN);
11641408cc1fSYuval Mintz }
11651408cc1fSYuval Mintz 
11661408cc1fSYuval Mintz void qed_vf_get_num_vlan_filters(struct qed_hwfn *p_hwfn, u8 *num_vlan_filters)
11671408cc1fSYuval Mintz {
11681408cc1fSYuval Mintz 	struct qed_vf_iov *p_vf;
11691408cc1fSYuval Mintz 
11701408cc1fSYuval Mintz 	p_vf = p_hwfn->vf_iov_info;
11711408cc1fSYuval Mintz 	*num_vlan_filters = p_vf->acquire_resp.resc.num_vlan_filters;
11721408cc1fSYuval Mintz }
11731408cc1fSYuval Mintz 
1174b0fca312SMintz, Yuval void qed_vf_get_num_mac_filters(struct qed_hwfn *p_hwfn, u8 *num_mac_filters)
1175b0fca312SMintz, Yuval {
1176b0fca312SMintz, Yuval 	struct qed_vf_iov *p_vf = p_hwfn->vf_iov_info;
1177b0fca312SMintz, Yuval 
1178b0fca312SMintz, Yuval 	*num_mac_filters = p_vf->acquire_resp.resc.num_mac_filters;
1179b0fca312SMintz, Yuval }
1180b0fca312SMintz, Yuval 
1181eff16960SYuval Mintz bool qed_vf_check_mac(struct qed_hwfn *p_hwfn, u8 *mac)
1182eff16960SYuval Mintz {
1183eff16960SYuval Mintz 	struct qed_bulletin_content *bulletin;
1184eff16960SYuval Mintz 
1185eff16960SYuval Mintz 	bulletin = &p_hwfn->vf_iov_info->bulletin_shadow;
1186eff16960SYuval Mintz 	if (!(bulletin->valid_bitmap & (1 << MAC_ADDR_FORCED)))
1187eff16960SYuval Mintz 		return true;
1188eff16960SYuval Mintz 
1189eff16960SYuval Mintz 	/* Forbid VF from changing a MAC enforced by PF */
1190eff16960SYuval Mintz 	if (ether_addr_equal(bulletin->mac, mac))
1191eff16960SYuval Mintz 		return false;
1192eff16960SYuval Mintz 
1193eff16960SYuval Mintz 	return false;
1194eff16960SYuval Mintz }
1195eff16960SYuval Mintz 
1196ba56947aSBaoyou Xie static bool qed_vf_bulletin_get_forced_mac(struct qed_hwfn *hwfn,
1197eff16960SYuval Mintz 					   u8 *dst_mac, u8 *p_is_forced)
1198eff16960SYuval Mintz {
1199eff16960SYuval Mintz 	struct qed_bulletin_content *bulletin;
1200eff16960SYuval Mintz 
1201eff16960SYuval Mintz 	bulletin = &hwfn->vf_iov_info->bulletin_shadow;
1202eff16960SYuval Mintz 
1203eff16960SYuval Mintz 	if (bulletin->valid_bitmap & (1 << MAC_ADDR_FORCED)) {
1204eff16960SYuval Mintz 		if (p_is_forced)
1205eff16960SYuval Mintz 			*p_is_forced = 1;
1206eff16960SYuval Mintz 	} else if (bulletin->valid_bitmap & (1 << VFPF_BULLETIN_MAC_ADDR)) {
1207eff16960SYuval Mintz 		if (p_is_forced)
1208eff16960SYuval Mintz 			*p_is_forced = 0;
1209eff16960SYuval Mintz 	} else {
1210eff16960SYuval Mintz 		return false;
1211eff16960SYuval Mintz 	}
1212eff16960SYuval Mintz 
1213eff16960SYuval Mintz 	ether_addr_copy(dst_mac, bulletin->mac);
1214eff16960SYuval Mintz 
1215eff16960SYuval Mintz 	return true;
1216eff16960SYuval Mintz }
1217eff16960SYuval Mintz 
12181408cc1fSYuval Mintz void qed_vf_get_fw_version(struct qed_hwfn *p_hwfn,
12191408cc1fSYuval Mintz 			   u16 *fw_major, u16 *fw_minor,
12201408cc1fSYuval Mintz 			   u16 *fw_rev, u16 *fw_eng)
12211408cc1fSYuval Mintz {
12221408cc1fSYuval Mintz 	struct pf_vf_pfdev_info *info;
12231408cc1fSYuval Mintz 
12241408cc1fSYuval Mintz 	info = &p_hwfn->vf_iov_info->acquire_resp.pfdev_info;
12251408cc1fSYuval Mintz 
12261408cc1fSYuval Mintz 	*fw_major = info->fw_major;
12271408cc1fSYuval Mintz 	*fw_minor = info->fw_minor;
12281408cc1fSYuval Mintz 	*fw_rev = info->fw_rev;
12291408cc1fSYuval Mintz 	*fw_eng = info->fw_eng;
12301408cc1fSYuval Mintz }
123136558c3dSYuval Mintz 
123236558c3dSYuval Mintz static void qed_handle_bulletin_change(struct qed_hwfn *hwfn)
123336558c3dSYuval Mintz {
1234eff16960SYuval Mintz 	struct qed_eth_cb_ops *ops = hwfn->cdev->protocol_ops.eth;
1235eff16960SYuval Mintz 	u8 mac[ETH_ALEN], is_mac_exist, is_mac_forced;
1236eff16960SYuval Mintz 	void *cookie = hwfn->cdev->ops_cookie;
1237eff16960SYuval Mintz 
1238eff16960SYuval Mintz 	is_mac_exist = qed_vf_bulletin_get_forced_mac(hwfn, mac,
1239eff16960SYuval Mintz 						      &is_mac_forced);
1240c3aaa403SYuval Mintz 	if (is_mac_exist && cookie)
1241c3aaa403SYuval Mintz 		ops->force_mac(cookie, mac, !!is_mac_forced);
1242eff16960SYuval Mintz 
124336558c3dSYuval Mintz 	/* Always update link configuration according to bulletin */
124436558c3dSYuval Mintz 	qed_link_update(hwfn);
124536558c3dSYuval Mintz }
124636558c3dSYuval Mintz 
124736558c3dSYuval Mintz void qed_iov_vf_task(struct work_struct *work)
124836558c3dSYuval Mintz {
124936558c3dSYuval Mintz 	struct qed_hwfn *hwfn = container_of(work, struct qed_hwfn,
125036558c3dSYuval Mintz 					     iov_task.work);
125136558c3dSYuval Mintz 	u8 change = 0;
125236558c3dSYuval Mintz 
125336558c3dSYuval Mintz 	if (test_and_clear_bit(QED_IOV_WQ_STOP_WQ_FLAG, &hwfn->iov_task_flags))
125436558c3dSYuval Mintz 		return;
125536558c3dSYuval Mintz 
125636558c3dSYuval Mintz 	/* Handle bulletin board changes */
125736558c3dSYuval Mintz 	qed_vf_read_bulletin(hwfn, &change);
125836558c3dSYuval Mintz 	if (change)
125936558c3dSYuval Mintz 		qed_handle_bulletin_change(hwfn);
126036558c3dSYuval Mintz 
126136558c3dSYuval Mintz 	/* As VF is polling bulletin board, need to constantly re-schedule */
126236558c3dSYuval Mintz 	queue_delayed_work(hwfn->iov_wq, &hwfn->iov_task, HZ);
126336558c3dSYuval Mintz }
1264