xref: /dpdk/drivers/common/sfc_efx/base/rhead_virtio.c (revision 05308e34bf849f4f0c3a23d5b8d6b6bd66ab1a39)
14dda72dbSVijay Srivastava /* SPDX-License-Identifier: BSD-3-Clause
24dda72dbSVijay Srivastava  *
34dda72dbSVijay Srivastava  * Copyright(c) 2020-2021 Xilinx, Inc.
44dda72dbSVijay Srivastava  */
54dda72dbSVijay Srivastava 
64dda72dbSVijay Srivastava #include "efx.h"
74dda72dbSVijay Srivastava #include "efx_impl.h"
84dda72dbSVijay Srivastava 
94dda72dbSVijay Srivastava #if EFSYS_OPT_RIVERHEAD && EFSYS_OPT_VIRTIO
104dda72dbSVijay Srivastava 
114dda72dbSVijay Srivastava /*
124dda72dbSVijay Srivastava  * Get function-local index of the associated VI from the
134dda72dbSVijay Srivastava  * virtqueue number queue 0 is reserved for MCDI
144dda72dbSVijay Srivastava  */
154dda72dbSVijay Srivastava #define EFX_VIRTIO_GET_VI_INDEX(vq_num) (((vq_num) / 2) + 1)
164dda72dbSVijay Srivastava 
174dda72dbSVijay Srivastava 	__checkReturn   efx_rc_t
rhead_virtio_qstart(__in efx_virtio_vq_t * evvp,__in efx_virtio_vq_cfg_t * evvcp,__in_opt efx_virtio_vq_dyncfg_t * evvdp)184dda72dbSVijay Srivastava rhead_virtio_qstart(
194dda72dbSVijay Srivastava 	__in		efx_virtio_vq_t *evvp,
204dda72dbSVijay Srivastava 	__in		efx_virtio_vq_cfg_t *evvcp,
214dda72dbSVijay Srivastava 	__in_opt	efx_virtio_vq_dyncfg_t *evvdp)
224dda72dbSVijay Srivastava 
234dda72dbSVijay Srivastava {
244dda72dbSVijay Srivastava 	efx_nic_t *enp = evvp->evv_enp;
254dda72dbSVijay Srivastava 	efx_mcdi_req_t req;
264dda72dbSVijay Srivastava 	uint32_t vi_index;
274dda72dbSVijay Srivastava 	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_VIRTIO_INIT_QUEUE_REQ_LEN,
284dda72dbSVijay Srivastava 		MC_CMD_VIRTIO_INIT_QUEUE_RESP_LEN);
294dda72dbSVijay Srivastava 	efx_rc_t rc;
304dda72dbSVijay Srivastava 
314dda72dbSVijay Srivastava 	EFX_STATIC_ASSERT(EFX_VIRTIO_VQ_TYPE_NET_RXQ ==
324dda72dbSVijay Srivastava 		MC_CMD_VIRTIO_INIT_QUEUE_REQ_NET_RXQ);
334dda72dbSVijay Srivastava 	EFX_STATIC_ASSERT(EFX_VIRTIO_VQ_TYPE_NET_TXQ ==
344dda72dbSVijay Srivastava 		MC_CMD_VIRTIO_INIT_QUEUE_REQ_NET_TXQ);
354dda72dbSVijay Srivastava 	EFX_STATIC_ASSERT(EFX_VIRTIO_VQ_TYPE_BLOCK ==
364dda72dbSVijay Srivastava 		MC_CMD_VIRTIO_INIT_QUEUE_REQ_BLOCK);
374dda72dbSVijay Srivastava 
384dda72dbSVijay Srivastava 	if (evvcp->evvc_type >= EFX_VIRTIO_VQ_NTYPES) {
394dda72dbSVijay Srivastava 		rc = EINVAL;
404dda72dbSVijay Srivastava 		goto fail1;
414dda72dbSVijay Srivastava 	}
424dda72dbSVijay Srivastava 
434dda72dbSVijay Srivastava 	/* virtqueue size must be power of 2 */
444dda72dbSVijay Srivastava 	if ((!ISP2(evvcp->evvc_vq_size)) ||
454dda72dbSVijay Srivastava 	    (evvcp->evvc_vq_size > EFX_VIRTIO_MAX_VQ_SIZE)) {
464dda72dbSVijay Srivastava 		rc = EINVAL;
474dda72dbSVijay Srivastava 		goto fail2;
484dda72dbSVijay Srivastava 	}
494dda72dbSVijay Srivastava 
504dda72dbSVijay Srivastava 	req.emr_cmd = MC_CMD_VIRTIO_INIT_QUEUE;
514dda72dbSVijay Srivastava 	req.emr_in_buf = payload;
524dda72dbSVijay Srivastava 	req.emr_in_length = MC_CMD_VIRTIO_INIT_QUEUE_REQ_LEN;
534dda72dbSVijay Srivastava 	req.emr_out_buf = payload;
544dda72dbSVijay Srivastava 	req.emr_out_length = MC_CMD_VIRTIO_INIT_QUEUE_RESP_LEN;
554dda72dbSVijay Srivastava 
564dda72dbSVijay Srivastava 	MCDI_IN_SET_BYTE(req, VIRTIO_INIT_QUEUE_REQ_QUEUE_TYPE,
574dda72dbSVijay Srivastava 		evvcp->evvc_type);
584dda72dbSVijay Srivastava 	MCDI_IN_SET_WORD(req, VIRTIO_INIT_QUEUE_REQ_TARGET_VF,
594dda72dbSVijay Srivastava 		evvcp->evvc_target_vf);
604dda72dbSVijay Srivastava 
614dda72dbSVijay Srivastava 	vi_index = EFX_VIRTIO_GET_VI_INDEX(evvcp->evvc_vq_num);
624dda72dbSVijay Srivastava 	MCDI_IN_SET_DWORD(req, VIRTIO_INIT_QUEUE_REQ_INSTANCE, vi_index);
634dda72dbSVijay Srivastava 
644dda72dbSVijay Srivastava 	MCDI_IN_SET_DWORD(req, VIRTIO_INIT_QUEUE_REQ_SIZE,
654dda72dbSVijay Srivastava 		evvcp->evvc_vq_size);
664dda72dbSVijay Srivastava 
674dda72dbSVijay Srivastava 	MCDI_IN_SET_DWORD(req, VIRTIO_INIT_QUEUE_REQ_DESC_TBL_ADDR_LO,
684dda72dbSVijay Srivastava 		evvcp->evvc_desc_tbl_addr & 0xFFFFFFFF);
694dda72dbSVijay Srivastava 	MCDI_IN_SET_DWORD(req, VIRTIO_INIT_QUEUE_REQ_DESC_TBL_ADDR_HI,
704dda72dbSVijay Srivastava 		evvcp->evvc_desc_tbl_addr >> 32);
714dda72dbSVijay Srivastava 
724dda72dbSVijay Srivastava 	MCDI_IN_SET_DWORD(req, VIRTIO_INIT_QUEUE_REQ_AVAIL_RING_ADDR_LO,
734dda72dbSVijay Srivastava 		evvcp->evvc_avail_ring_addr & 0xFFFFFFFF);
744dda72dbSVijay Srivastava 	MCDI_IN_SET_DWORD(req, VIRTIO_INIT_QUEUE_REQ_AVAIL_RING_ADDR_HI,
754dda72dbSVijay Srivastava 		evvcp->evvc_avail_ring_addr >> 32);
764dda72dbSVijay Srivastava 
774dda72dbSVijay Srivastava 	MCDI_IN_SET_DWORD(req, VIRTIO_INIT_QUEUE_REQ_USED_RING_ADDR_LO,
784dda72dbSVijay Srivastava 		evvcp->evvc_used_ring_addr & 0xFFFFFFFF);
794dda72dbSVijay Srivastava 	MCDI_IN_SET_DWORD(req, VIRTIO_INIT_QUEUE_REQ_USED_RING_ADDR_HI,
804dda72dbSVijay Srivastava 		evvcp->evvc_used_ring_addr >> 32);
814dda72dbSVijay Srivastava 
824dda72dbSVijay Srivastava 	if (evvcp->evvc_use_pasid) {
834dda72dbSVijay Srivastava 		MCDI_IN_POPULATE_DWORD_1(req, VIRTIO_INIT_QUEUE_REQ_FLAGS,
844dda72dbSVijay Srivastava 			VIRTIO_INIT_QUEUE_REQ_USE_PASID, 1);
854dda72dbSVijay Srivastava 		MCDI_IN_SET_DWORD(req, VIRTIO_INIT_QUEUE_REQ_PASID,
864dda72dbSVijay Srivastava 			evvcp->evvc_pas_id);
874dda72dbSVijay Srivastava 	}
884dda72dbSVijay Srivastava 
894dda72dbSVijay Srivastava 	MCDI_IN_SET_WORD(req, VIRTIO_INIT_QUEUE_REQ_MSIX_VECTOR,
904dda72dbSVijay Srivastava 		evvcp->evvc_msix_vector);
914dda72dbSVijay Srivastava 
924dda72dbSVijay Srivastava 	MCDI_IN_SET_DWORD(req, VIRTIO_INIT_QUEUE_REQ_FEATURES_LO,
934dda72dbSVijay Srivastava 		evvcp->evcc_features & 0xFFFFFFFF);
944dda72dbSVijay Srivastava 	MCDI_IN_SET_DWORD(req, VIRTIO_INIT_QUEUE_REQ_FEATURES_HI,
954dda72dbSVijay Srivastava 		evvcp->evcc_features >> 32);
964dda72dbSVijay Srivastava 
974dda72dbSVijay Srivastava 	if (evvdp != NULL) {
98*05308e34SAbhimanyu Saini 		MCDI_IN_SET_DWORD(req, VIRTIO_INIT_QUEUE_REQ_INITIAL_AVAIL_IDX,
99*05308e34SAbhimanyu Saini 			evvdp->evvd_vq_avail_idx);
100*05308e34SAbhimanyu Saini 		MCDI_IN_SET_DWORD(req, VIRTIO_INIT_QUEUE_REQ_INITIAL_USED_IDX,
101*05308e34SAbhimanyu Saini 			evvdp->evvd_vq_used_idx);
1024dda72dbSVijay Srivastava 	}
1034dda72dbSVijay Srivastava 
1044dda72dbSVijay Srivastava 	MCDI_IN_SET_DWORD(req, VIRTIO_INIT_QUEUE_REQ_MPORT_SELECTOR,
1054dda72dbSVijay Srivastava 		MAE_MPORT_SELECTOR_ASSIGNED);
1064dda72dbSVijay Srivastava 
1074dda72dbSVijay Srivastava 	efx_mcdi_execute(enp, &req);
1084dda72dbSVijay Srivastava 
1094dda72dbSVijay Srivastava 	if (req.emr_rc != 0) {
1104dda72dbSVijay Srivastava 		rc = req.emr_rc;
11193211a52SAbhimanyu Saini 		goto fail3;
1124dda72dbSVijay Srivastava 	}
1134dda72dbSVijay Srivastava 
1144dda72dbSVijay Srivastava 	evvp->evv_vi_index = vi_index;
1154dda72dbSVijay Srivastava 
1164dda72dbSVijay Srivastava 	return (0);
1174dda72dbSVijay Srivastava 
1184dda72dbSVijay Srivastava fail3:
1194dda72dbSVijay Srivastava 	EFSYS_PROBE(fail3);
1204dda72dbSVijay Srivastava fail2:
1214dda72dbSVijay Srivastava 	EFSYS_PROBE(fail2);
1224dda72dbSVijay Srivastava fail1:
1234dda72dbSVijay Srivastava 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1244dda72dbSVijay Srivastava 
1254dda72dbSVijay Srivastava 	return (rc);
1264dda72dbSVijay Srivastava }
1274dda72dbSVijay Srivastava 
1284dda72dbSVijay Srivastava 	__checkReturn   efx_rc_t
rhead_virtio_qstop(__in efx_virtio_vq_t * evvp,__out_opt efx_virtio_vq_dyncfg_t * evvdp)1294dda72dbSVijay Srivastava rhead_virtio_qstop(
1304dda72dbSVijay Srivastava 	__in		efx_virtio_vq_t *evvp,
1314dda72dbSVijay Srivastava 	__out_opt	efx_virtio_vq_dyncfg_t *evvdp)
1324dda72dbSVijay Srivastava {
1334dda72dbSVijay Srivastava 	efx_mcdi_req_t req;
1344dda72dbSVijay Srivastava 	efx_nic_t *enp = evvp->evv_enp;
1354dda72dbSVijay Srivastava 	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_VIRTIO_FINI_QUEUE_REQ_LEN,
1364dda72dbSVijay Srivastava 		MC_CMD_VIRTIO_FINI_QUEUE_RESP_LEN);
1374dda72dbSVijay Srivastava 	efx_rc_t rc;
1384dda72dbSVijay Srivastava 
1394dda72dbSVijay Srivastava 	req.emr_cmd = MC_CMD_VIRTIO_FINI_QUEUE;
1404dda72dbSVijay Srivastava 	req.emr_in_buf = payload;
1414dda72dbSVijay Srivastava 	req.emr_in_length = MC_CMD_VIRTIO_FINI_QUEUE_REQ_LEN;
1424dda72dbSVijay Srivastava 	req.emr_out_buf = payload;
1434dda72dbSVijay Srivastava 	req.emr_out_length = MC_CMD_VIRTIO_FINI_QUEUE_RESP_LEN;
1444dda72dbSVijay Srivastava 
1454dda72dbSVijay Srivastava 	MCDI_IN_SET_BYTE(req, VIRTIO_FINI_QUEUE_REQ_QUEUE_TYPE, evvp->evv_type);
1464dda72dbSVijay Srivastava 	MCDI_IN_SET_WORD(req, VIRTIO_INIT_QUEUE_REQ_TARGET_VF,
1474dda72dbSVijay Srivastava 		evvp->evv_target_vf);
1484dda72dbSVijay Srivastava 	MCDI_IN_SET_DWORD(req, VIRTIO_INIT_QUEUE_REQ_INSTANCE,
1494dda72dbSVijay Srivastava 		evvp->evv_vi_index);
1504dda72dbSVijay Srivastava 
1514dda72dbSVijay Srivastava 	efx_mcdi_execute(enp, &req);
1524dda72dbSVijay Srivastava 
1534dda72dbSVijay Srivastava 	if (req.emr_rc != 0) {
1544dda72dbSVijay Srivastava 		rc = req.emr_rc;
1554dda72dbSVijay Srivastava 		goto fail1;
1564dda72dbSVijay Srivastava 	}
1574dda72dbSVijay Srivastava 
1584dda72dbSVijay Srivastava 	if (req.emr_out_length_used < MC_CMD_VIRTIO_FINI_QUEUE_RESP_LEN) {
1594dda72dbSVijay Srivastava 		rc = EMSGSIZE;
1604dda72dbSVijay Srivastava 		goto fail2;
1614dda72dbSVijay Srivastava 	}
1624dda72dbSVijay Srivastava 
1634dda72dbSVijay Srivastava 	if (evvdp != NULL) {
164*05308e34SAbhimanyu Saini 		evvdp->evvd_vq_avail_idx =
165*05308e34SAbhimanyu Saini 		    MCDI_OUT_DWORD(req, VIRTIO_FINI_QUEUE_RESP_FINAL_AVAIL_IDX);
166*05308e34SAbhimanyu Saini 		evvdp->evvd_vq_used_idx =
167*05308e34SAbhimanyu Saini 		    MCDI_OUT_DWORD(req, VIRTIO_FINI_QUEUE_RESP_FINAL_USED_IDX);
1684dda72dbSVijay Srivastava 	}
1694dda72dbSVijay Srivastava 
1704dda72dbSVijay Srivastava 	return (0);
1714dda72dbSVijay Srivastava 
1724dda72dbSVijay Srivastava fail2:
1734dda72dbSVijay Srivastava 	EFSYS_PROBE(fail2);
1744dda72dbSVijay Srivastava fail1:
1754dda72dbSVijay Srivastava 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1764dda72dbSVijay Srivastava 
1774dda72dbSVijay Srivastava 	return (rc);
1784dda72dbSVijay Srivastava }
1794dda72dbSVijay Srivastava 
180ec03ce69SVijay Srivastava 	__checkReturn	efx_rc_t
rhead_virtio_get_doorbell_offset(__in efx_virtio_vq_t * evvp,__out uint32_t * offsetp)181ec03ce69SVijay Srivastava rhead_virtio_get_doorbell_offset(
182ec03ce69SVijay Srivastava 	__in		efx_virtio_vq_t *evvp,
183ec03ce69SVijay Srivastava 	__out		uint32_t *offsetp)
184ec03ce69SVijay Srivastava {
185ec03ce69SVijay Srivastava 	efx_nic_t *enp = evvp->evv_enp;
186ec03ce69SVijay Srivastava 	efx_mcdi_req_t req;
187ec03ce69SVijay Srivastava 	uint32_t type;
188ec03ce69SVijay Srivastava 	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_VIRTIO_GET_DOORBELL_OFFSET_REQ_LEN,
189ec03ce69SVijay Srivastava 		MC_CMD_VIRTIO_GET_NET_DOORBELL_OFFSET_RESP_LEN);
190ec03ce69SVijay Srivastava 	efx_rc_t rc;
191ec03ce69SVijay Srivastava 
192ec03ce69SVijay Srivastava 	req.emr_cmd = MC_CMD_VIRTIO_GET_DOORBELL_OFFSET;
193ec03ce69SVijay Srivastava 	req.emr_in_buf = payload;
194ec03ce69SVijay Srivastava 	req.emr_in_length = MC_CMD_VIRTIO_GET_DOORBELL_OFFSET_REQ_LEN;
195ec03ce69SVijay Srivastava 	req.emr_out_buf = payload;
196ec03ce69SVijay Srivastava 	req.emr_out_length = MC_CMD_VIRTIO_GET_NET_DOORBELL_OFFSET_RESP_LEN;
197ec03ce69SVijay Srivastava 
198ec03ce69SVijay Srivastava 	switch (evvp->evv_type) {
199ec03ce69SVijay Srivastava 	case EFX_VIRTIO_VQ_TYPE_NET_RXQ:
200ec03ce69SVijay Srivastava 	case EFX_VIRTIO_VQ_TYPE_NET_TXQ:
201ec03ce69SVijay Srivastava 		type = MC_CMD_VIRTIO_GET_FEATURES_IN_NET;
202ec03ce69SVijay Srivastava 		break;
203ec03ce69SVijay Srivastava 	case EFX_VIRTIO_VQ_TYPE_BLOCK:
204ec03ce69SVijay Srivastava 		type = MC_CMD_VIRTIO_GET_FEATURES_IN_BLOCK;
205ec03ce69SVijay Srivastava 		break;
206ec03ce69SVijay Srivastava 	default:
207ec03ce69SVijay Srivastava 		rc = EINVAL;
208ec03ce69SVijay Srivastava 		goto fail1;
209ec03ce69SVijay Srivastava 	}
210ec03ce69SVijay Srivastava 
211ec03ce69SVijay Srivastava 	MCDI_IN_SET_BYTE(req, VIRTIO_GET_DOORBELL_OFFSET_REQ_DEVICE_ID,
212ec03ce69SVijay Srivastava 		type);
213ec03ce69SVijay Srivastava 	MCDI_IN_SET_WORD(req, VIRTIO_GET_DOORBELL_OFFSET_REQ_TARGET_VF,
214ec03ce69SVijay Srivastava 		evvp->evv_target_vf);
215ec03ce69SVijay Srivastava 	MCDI_IN_SET_DWORD(req, VIRTIO_GET_DOORBELL_OFFSET_REQ_INSTANCE,
216ec03ce69SVijay Srivastava 		evvp->evv_vi_index);
217ec03ce69SVijay Srivastava 
218ec03ce69SVijay Srivastava 	efx_mcdi_execute(enp, &req);
219ec03ce69SVijay Srivastava 
220ec03ce69SVijay Srivastava 	if (req.emr_rc != 0) {
221ec03ce69SVijay Srivastava 		rc = req.emr_rc;
222ec03ce69SVijay Srivastava 		goto fail2;
223ec03ce69SVijay Srivastava 	}
224ec03ce69SVijay Srivastava 
225ec03ce69SVijay Srivastava 	switch (type) {
226ec03ce69SVijay Srivastava 	case MC_CMD_VIRTIO_GET_FEATURES_IN_NET:
227ec03ce69SVijay Srivastava 		if (req.emr_out_length_used <
228ec03ce69SVijay Srivastava 		    MC_CMD_VIRTIO_GET_NET_DOORBELL_OFFSET_RESP_LEN) {
229ec03ce69SVijay Srivastava 			rc = EMSGSIZE;
230ec03ce69SVijay Srivastava 			goto fail3;
231ec03ce69SVijay Srivastava 		}
232ec03ce69SVijay Srivastava 
233ec03ce69SVijay Srivastava 		if (evvp->evv_type == EFX_VIRTIO_VQ_TYPE_NET_RXQ) {
234ec03ce69SVijay Srivastava 			*offsetp = MCDI_OUT_DWORD(req,
235ec03ce69SVijay Srivastava 			    VIRTIO_GET_NET_DOORBELL_OFFSET_RESP_RX_DBL_OFFSET);
236ec03ce69SVijay Srivastava 		} else if (evvp->evv_type == EFX_VIRTIO_VQ_TYPE_NET_TXQ) {
237ec03ce69SVijay Srivastava 			*offsetp = MCDI_OUT_DWORD(req,
238ec03ce69SVijay Srivastava 			    VIRTIO_GET_NET_DOORBELL_OFFSET_RESP_TX_DBL_OFFSET);
239ec03ce69SVijay Srivastava 		}
240ec03ce69SVijay Srivastava 		break;
241ec03ce69SVijay Srivastava 	case MC_CMD_VIRTIO_GET_FEATURES_IN_BLOCK:
242ec03ce69SVijay Srivastava 		if (req.emr_out_length_used <
243ec03ce69SVijay Srivastava 		    MC_CMD_VIRTIO_GET_BLOCK_DOORBELL_OFFSET_RESP_LEN) {
244ec03ce69SVijay Srivastava 			rc = EMSGSIZE;
245ec03ce69SVijay Srivastava 			goto fail4;
246ec03ce69SVijay Srivastava 		}
247ec03ce69SVijay Srivastava 
248ec03ce69SVijay Srivastava 		*offsetp = MCDI_OUT_DWORD(req,
249ec03ce69SVijay Srivastava 			VIRTIO_GET_BLOCK_DOORBELL_OFFSET_RESP_DBL_OFFSET);
250ec03ce69SVijay Srivastava 		break;
251ec03ce69SVijay Srivastava 	default:
252ec03ce69SVijay Srivastava 		EFSYS_ASSERT(0);
253ec03ce69SVijay Srivastava 		rc = EINVAL;
254ec03ce69SVijay Srivastava 		goto fail5;
255ec03ce69SVijay Srivastava 	}
256ec03ce69SVijay Srivastava 
257ec03ce69SVijay Srivastava 	return (0);
258ec03ce69SVijay Srivastava 
259ec03ce69SVijay Srivastava fail5:
260ec03ce69SVijay Srivastava 	EFSYS_PROBE(fail5);
261ec03ce69SVijay Srivastava fail4:
262ec03ce69SVijay Srivastava 	EFSYS_PROBE(fail4);
263ec03ce69SVijay Srivastava fail3:
264ec03ce69SVijay Srivastava 	EFSYS_PROBE(fail3);
265ec03ce69SVijay Srivastava fail2:
266ec03ce69SVijay Srivastava 	EFSYS_PROBE(fail2);
267ec03ce69SVijay Srivastava fail1:
268ec03ce69SVijay Srivastava 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
269ec03ce69SVijay Srivastava 
270ec03ce69SVijay Srivastava 	return (rc);
271ec03ce69SVijay Srivastava }
272ec03ce69SVijay Srivastava 
27346d2b38bSVijay Kumar Srivastava 	__checkReturn	efx_rc_t
rhead_virtio_get_features(__in efx_nic_t * enp,__in efx_virtio_device_type_t type,__out uint64_t * featuresp)27446d2b38bSVijay Kumar Srivastava rhead_virtio_get_features(
27546d2b38bSVijay Kumar Srivastava 	__in		efx_nic_t *enp,
27646d2b38bSVijay Kumar Srivastava 	__in		efx_virtio_device_type_t type,
27746d2b38bSVijay Kumar Srivastava 	__out		uint64_t *featuresp)
27846d2b38bSVijay Kumar Srivastava {
27946d2b38bSVijay Kumar Srivastava 	efx_mcdi_req_t req;
28046d2b38bSVijay Kumar Srivastava 	uint32_t features_lo;
28146d2b38bSVijay Kumar Srivastava 	uint32_t features_hi;
28246d2b38bSVijay Kumar Srivastava 	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_VIRTIO_GET_FEATURES_IN_LEN,
28346d2b38bSVijay Kumar Srivastava 		MC_CMD_VIRTIO_GET_FEATURES_OUT_LEN);
28446d2b38bSVijay Kumar Srivastava 	efx_rc_t rc;
28546d2b38bSVijay Kumar Srivastava 
28646d2b38bSVijay Kumar Srivastava 	EFX_STATIC_ASSERT(EFX_VIRTIO_DEVICE_TYPE_NET ==
28746d2b38bSVijay Kumar Srivastava 		MC_CMD_VIRTIO_GET_FEATURES_IN_NET);
28846d2b38bSVijay Kumar Srivastava 	EFX_STATIC_ASSERT(EFX_VIRTIO_DEVICE_TYPE_BLOCK ==
28946d2b38bSVijay Kumar Srivastava 		MC_CMD_VIRTIO_GET_FEATURES_IN_BLOCK);
29046d2b38bSVijay Kumar Srivastava 
29146d2b38bSVijay Kumar Srivastava 	req.emr_cmd = MC_CMD_VIRTIO_GET_FEATURES;
29246d2b38bSVijay Kumar Srivastava 	req.emr_in_buf = payload;
29346d2b38bSVijay Kumar Srivastava 	req.emr_in_length = MC_CMD_VIRTIO_GET_FEATURES_IN_LEN;
29446d2b38bSVijay Kumar Srivastava 	req.emr_out_buf = payload;
29546d2b38bSVijay Kumar Srivastava 	req.emr_out_length = MC_CMD_VIRTIO_GET_FEATURES_OUT_LEN;
29646d2b38bSVijay Kumar Srivastava 
29746d2b38bSVijay Kumar Srivastava 	MCDI_IN_SET_DWORD(req, VIRTIO_GET_FEATURES_IN_DEVICE_ID, type);
29846d2b38bSVijay Kumar Srivastava 
29946d2b38bSVijay Kumar Srivastava 	efx_mcdi_execute(enp, &req);
30046d2b38bSVijay Kumar Srivastava 
30146d2b38bSVijay Kumar Srivastava 	if (req.emr_rc != 0) {
30246d2b38bSVijay Kumar Srivastava 		rc = req.emr_rc;
30346d2b38bSVijay Kumar Srivastava 		goto fail1;
30446d2b38bSVijay Kumar Srivastava 	}
30546d2b38bSVijay Kumar Srivastava 
30646d2b38bSVijay Kumar Srivastava 	if (req.emr_out_length_used < MC_CMD_VIRTIO_GET_FEATURES_OUT_LEN) {
30746d2b38bSVijay Kumar Srivastava 		rc = EMSGSIZE;
30846d2b38bSVijay Kumar Srivastava 		goto fail2;
30946d2b38bSVijay Kumar Srivastava 	}
31046d2b38bSVijay Kumar Srivastava 
31146d2b38bSVijay Kumar Srivastava 	features_lo = MCDI_OUT_DWORD(req, VIRTIO_GET_FEATURES_OUT_FEATURES_LO);
31246d2b38bSVijay Kumar Srivastava 	features_hi = MCDI_OUT_DWORD(req, VIRTIO_GET_FEATURES_OUT_FEATURES_HI);
31346d2b38bSVijay Kumar Srivastava 	*featuresp = ((uint64_t)features_hi << 32) | features_lo;
31446d2b38bSVijay Kumar Srivastava 
31546d2b38bSVijay Kumar Srivastava 	return (0);
31646d2b38bSVijay Kumar Srivastava 
31746d2b38bSVijay Kumar Srivastava fail2:
31846d2b38bSVijay Kumar Srivastava 	EFSYS_PROBE(fail2);
31946d2b38bSVijay Kumar Srivastava fail1:
32046d2b38bSVijay Kumar Srivastava 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
32146d2b38bSVijay Kumar Srivastava 
32246d2b38bSVijay Kumar Srivastava 	return (rc);
32346d2b38bSVijay Kumar Srivastava }
32446d2b38bSVijay Kumar Srivastava 
325b8a896abSVijay Kumar Srivastava 	__checkReturn	efx_rc_t
rhead_virtio_verify_features(__in efx_nic_t * enp,__in efx_virtio_device_type_t type,__in uint64_t features)326b8a896abSVijay Kumar Srivastava rhead_virtio_verify_features(
327b8a896abSVijay Kumar Srivastava 	__in		efx_nic_t *enp,
328b8a896abSVijay Kumar Srivastava 	__in		efx_virtio_device_type_t type,
329b8a896abSVijay Kumar Srivastava 	__in		uint64_t features)
330b8a896abSVijay Kumar Srivastava {
331b8a896abSVijay Kumar Srivastava 	efx_mcdi_req_t req;
332b8a896abSVijay Kumar Srivastava 	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_VIRTIO_TEST_FEATURES_IN_LEN,
333b8a896abSVijay Kumar Srivastava 		MC_CMD_VIRTIO_TEST_FEATURES_OUT_LEN);
334b8a896abSVijay Kumar Srivastava 	efx_rc_t rc;
335b8a896abSVijay Kumar Srivastava 
336b8a896abSVijay Kumar Srivastava 	EFX_STATIC_ASSERT(EFX_VIRTIO_DEVICE_TYPE_NET ==
337b8a896abSVijay Kumar Srivastava 		MC_CMD_VIRTIO_GET_FEATURES_IN_NET);
338b8a896abSVijay Kumar Srivastava 	EFX_STATIC_ASSERT(EFX_VIRTIO_DEVICE_TYPE_BLOCK ==
339b8a896abSVijay Kumar Srivastava 		MC_CMD_VIRTIO_GET_FEATURES_IN_BLOCK);
340b8a896abSVijay Kumar Srivastava 
341b8a896abSVijay Kumar Srivastava 	req.emr_cmd = MC_CMD_VIRTIO_TEST_FEATURES;
342b8a896abSVijay Kumar Srivastava 	req.emr_in_buf = payload;
343b8a896abSVijay Kumar Srivastava 	req.emr_in_length = MC_CMD_VIRTIO_TEST_FEATURES_IN_LEN;
344b8a896abSVijay Kumar Srivastava 	req.emr_out_buf = payload;
345b8a896abSVijay Kumar Srivastava 	req.emr_out_length = MC_CMD_VIRTIO_TEST_FEATURES_OUT_LEN;
346b8a896abSVijay Kumar Srivastava 
347b8a896abSVijay Kumar Srivastava 	MCDI_IN_SET_DWORD(req, VIRTIO_TEST_FEATURES_IN_DEVICE_ID, type);
348b8a896abSVijay Kumar Srivastava 
349b8a896abSVijay Kumar Srivastava 	MCDI_IN_SET_DWORD(req, VIRTIO_TEST_FEATURES_IN_FEATURES_LO,
350b8a896abSVijay Kumar Srivastava 		features & 0xFFFFFFFF);
351b8a896abSVijay Kumar Srivastava 	MCDI_IN_SET_DWORD(req, VIRTIO_TEST_FEATURES_IN_FEATURES_HI,
352b8a896abSVijay Kumar Srivastava 		((features >> 32) & 0xFFFFFFFF));
353b8a896abSVijay Kumar Srivastava 
354b8a896abSVijay Kumar Srivastava 	efx_mcdi_execute(enp, &req);
355b8a896abSVijay Kumar Srivastava 
356b8a896abSVijay Kumar Srivastava 	if (req.emr_rc != 0) {
357b8a896abSVijay Kumar Srivastava 		rc = req.emr_rc;
358b8a896abSVijay Kumar Srivastava 		goto fail1;
359b8a896abSVijay Kumar Srivastava 	}
360b8a896abSVijay Kumar Srivastava 
361b8a896abSVijay Kumar Srivastava 	return (0);
362b8a896abSVijay Kumar Srivastava 
363b8a896abSVijay Kumar Srivastava fail1:
364b8a896abSVijay Kumar Srivastava 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
365b8a896abSVijay Kumar Srivastava 
366b8a896abSVijay Kumar Srivastava 	return (rc);
367b8a896abSVijay Kumar Srivastava }
368b8a896abSVijay Kumar Srivastava 
3694dda72dbSVijay Srivastava #endif	/* EFSYS_OPT_RIVERHEAD && EFSYS_OPT_VIRTIO */
370