src/dpdk/drivers/net/netvsc/hn_rxtx.c
uint32_t hn_process_events(struct hn_data *hv, uint16_t queue_id,
			   uint32_t tx_limit)
{
	struct rte_eth_dev *dev = &rte_eth_devices[hv->port_id];
	struct hn_rx_queue *rxq;
	uint32_t bytes_read = 0;
	uint32_t tx_done = 0;
	int ret = 0;

	rxq = queue_id == 0 ? hv->primary : dev->data->rx_queues[queue_id];

	/*
	 * Since channel is shared between Rx and TX queue need to have a lock
	 * since DPDK does not force same CPU to be used for Rx/Tx.
	 */
	if (unlikely(!rte_spinlock_trylock(&rxq->ring_lock)))
		return 0;

	for (;;) {
		const struct vmbus_chanpkt_hdr *pkt;
		uint32_t len = rxq->event_sz;
		const void *data;

retry:
		ret = rte_vmbus_chan_recv_raw(rxq->chan, rxq->event_buf, &len);
		if (ret == -EAGAIN)
			break;	/* ring is empty */

		if (unlikely(ret == -ENOBUFS)) {
			/* event buffer not large enough to read ring */

			PMD_DRV_LOG(DEBUG,
				    "event buffer expansion (need %u)", len);
			rxq->event_sz = len + len / 4;
			rxq->event_buf = rte_realloc(rxq->event_buf, rxq->event_sz,
						     RTE_CACHE_LINE_SIZE);
			if (rxq->event_buf)
				goto retry;
			/* out of memory, no more events now */
			rxq->event_sz = 0;
			break;
		}

		if (unlikely(ret <= 0)) {
			/* This indicates a failure to communicate (or worse) */
			rte_exit(EXIT_FAILURE,
				 "vmbus ring buffer error: %d", ret);
		}

		bytes_read += ret;
		pkt = (const struct vmbus_chanpkt_hdr *)rxq->event_buf;
		data = (char *)rxq->event_buf + vmbus_chanpkt_getlen(pkt->hlen);

		switch (pkt->type) {
		case VMBUS_CHANPKT_TYPE_COMP:
			++tx_done;
			hn_nvs_handle_comp(dev, queue_id, pkt, data);
			break;

		case VMBUS_CHANPKT_TYPE_RXBUF:
			hn_nvs_handle_rxbuf(dev, hv, rxq, pkt, data);
			break;

		case VMBUS_CHANPKT_TYPE_INBAND:
			hn_nvs_handle_notify(dev, pkt, data);
			break;

		default:
			PMD_DRV_LOG(ERR, "unknown chan pkt %u", pkt->type);
			break;
		}

		if (tx_limit && tx_done >= tx_limit)
			break;
	}

	if (bytes_read > 0)
		rte_vmbus_chan_signal_read(rxq->chan, bytes_read);

	rte_spinlock_unlock(&rxq->ring_lock);

	return tx_done;
}
/*
 * Process pending events on the channel.
 * Called from both Rx queue poll and Tx cleanup
 */
Process pending events on the channel.
Called from both Rx queue poll and Tx cleanup
Process pending events on the channel . Called from both Rx queue poll and Tx cleanup
uint32_t hn_process_events(struct hn_data *hv, uint16_t queue_id,
			   uint32_t tx_limit)
{
	struct rte_eth_dev *dev = &rte_eth_devices[hv->port_id];
	struct hn_rx_queue *rxq;
	uint32_t bytes_read = 0;
	uint32_t tx_done = 0;
	int ret = 0;
	rxq = queue_id == 0 ? hv->primary : dev->data->rx_queues[queue_id];
	if (unlikely(!rte_spinlock_trylock(&rxq->ring_lock)))
		return 0;
	for (;;) {
		const struct vmbus_chanpkt_hdr *pkt;
		uint32_t len = rxq->event_sz;
		const void *data;
retry:
		ret = rte_vmbus_chan_recv_raw(rxq->chan, rxq->event_buf, &len);
		if (ret == -EAGAIN)
			break;	
		if (unlikely(ret == -ENOBUFS)) {
			PMD_DRV_LOG(DEBUG,
				    "event buffer expansion (need %u)", len);
			rxq->event_sz = len + len / 4;
			rxq->event_buf = rte_realloc(rxq->event_buf, rxq->event_sz,
						     RTE_CACHE_LINE_SIZE);
			if (rxq->event_buf)
				goto retry;
			rxq->event_sz = 0;
			break;
		}
		if (unlikely(ret <= 0)) {
			rte_exit(EXIT_FAILURE,
				 "vmbus ring buffer error: %d", ret);
		}
		bytes_read += ret;
		pkt = (const struct vmbus_chanpkt_hdr *)rxq->event_buf;
		data = (char *)rxq->event_buf + vmbus_chanpkt_getlen(pkt->hlen);
		switch (pkt->type) {
		case VMBUS_CHANPKT_TYPE_COMP:
			++tx_done;
			hn_nvs_handle_comp(dev, queue_id, pkt, data);
			break;
		case VMBUS_CHANPKT_TYPE_RXBUF:
			hn_nvs_handle_rxbuf(dev, hv, rxq, pkt, data);
			break;
		case VMBUS_CHANPKT_TYPE_INBAND:
			hn_nvs_handle_notify(dev, pkt, data);
			break;
		default:
			PMD_DRV_LOG(ERR, "unknown chan pkt %u", pkt->type);
			break;
		}
		if (tx_limit && tx_done >= tx_limit)
			break;
	}
	if (bytes_read > 0)
		rte_vmbus_chan_signal_read(rxq->chan, bytes_read);
	rte_spinlock_unlock(&rxq->ring_lock);
	return tx_done;
}
uint32_t hn_process_events ( struct hn_data * hv , uint16_t queue_id , uint32_t tx_limit ) { struct rte_eth_dev * dev = & rte_eth_devices [ hv -> port_id ] ; struct hn_rx_queue * rxq ; uint32_t bytes_read = 0 ; uint32_t tx_done = 0 ; int ret = 0 ; rxq = queue_id == 0 ? hv -> primary : dev -> data -> rx_queues [ queue_id ] ; if ( unlikely ( ! rte_spinlock_trylock ( & rxq -> ring_lock ) ) ) return 0 ; for ( ; ; ) { const struct vmbus_chanpkt_hdr * pkt ; uint32_t len = rxq -> event_sz ; const void * data ; retry : ret = rte_vmbus_chan_recv_raw ( rxq -> chan , rxq -> event_buf , & len ) ; if ( ret == - EAGAIN ) break ; if ( unlikely ( ret == - ENOBUFS ) ) { PMD_DRV_LOG ( DEBUG , " " , len ) ; rxq -> event_sz = len + len / 4 ; rxq -> event_buf = rte_realloc ( rxq -> event_buf , rxq -> event_sz , RTE_CACHE_LINE_SIZE ) ; if ( rxq -> event_buf ) goto retry ; rxq -> event_sz = 0 ; break ; } if ( unlikely ( ret <= 0 ) ) { rte_exit ( EXIT_FAILURE , " " , ret ) ; } bytes_read += ret ; pkt = ( const struct vmbus_chanpkt_hdr * ) rxq -> event_buf ; data = ( char * ) rxq -> event_buf + vmbus_chanpkt_getlen ( pkt -> hlen ) ; switch ( pkt -> type ) { case VMBUS_CHANPKT_TYPE_COMP : ++ tx_done ; hn_nvs_handle_comp ( dev , queue_id , pkt , data ) ; break ; case VMBUS_CHANPKT_TYPE_RXBUF : hn_nvs_handle_rxbuf ( dev , hv , rxq , pkt , data ) ; break ; case VMBUS_CHANPKT_TYPE_INBAND : hn_nvs_handle_notify ( dev , pkt , data ) ; break ; default : PMD_DRV_LOG ( ERR , " " , pkt -> type ) ; break ; } if ( tx_limit && tx_done >= tx_limit ) break ; } if ( bytes_read > 0 ) rte_vmbus_chan_signal_read ( rxq -> chan , bytes_read ) ; rte_spinlock_unlock ( & rxq -> ring_lock ) ; return tx_done ; }
Process pending events on the channel.
Process pending events on the channel .
/*
	 * Since channel is shared between Rx and TX queue need to have a lock
	 * since DPDK does not force same CPU to be used for Rx/Tx.
	 */ /* ring is empty */ /* event buffer not large enough to read ring */ /* out of memory, no more events now */ /* This indicates a failure to communicate (or worse) */