int
vmbus_chan_recv(struct vmbus_channel *chan, void *data, int *dlen0,
    uint64_t *xactid)
{
	struct vmbus_chanpkt_hdr pkt;
	int error, dlen, hlen;

	error = vmbus_rxbr_peek(&chan->ch_rxbr, &pkt, sizeof(pkt));
	if (error)
		return error;

	hlen = VMBUS_CHANPKT_GETLEN(pkt.cph_hlen);
	dlen = VMBUS_CHANPKT_GETLEN(pkt.cph_tlen) - hlen;

	if (*dlen0 < dlen) {
		/* Return the size of this packet's data. */
		*dlen0 = dlen;
		return ENOBUFS;
	}

	*xactid = pkt.cph_xactid;
	*dlen0 = dlen;

	/* Skip packet header */
	error = vmbus_rxbr_read(&chan->ch_rxbr, data, dlen, hlen);
	KASSERT(!error, ("vmbus_rxbr_read failed"));

	return 0;
}
int
vmbus_chan_recv_pkt(struct vmbus_channel *chan,
    struct vmbus_chanpkt_hdr *pkt0, int *pktlen0)
{
	struct vmbus_chanpkt_hdr pkt;
	int error, pktlen;

	error = vmbus_rxbr_peek(&chan->ch_rxbr, &pkt, sizeof(pkt));
	if (error)
		return error;

	pktlen = VMBUS_CHANPKT_GETLEN(pkt.cph_tlen);
	if (*pktlen0 < pktlen) {
		/* Return the size of this packet. */
		*pktlen0 = pktlen;
		return ENOBUFS;
	}
	*pktlen0 = pktlen;

	/* Include packet header */
	error = vmbus_rxbr_read(&chan->ch_rxbr, pkt0, pktlen, 0);
	KASSERT(!error, ("vmbus_rxbr_read failed"));

	return 0;
}
示例#3
0
static int vmbus_read_and_signal(struct vmbus_channel *chan,
				 void *data, size_t dlen, size_t skip)
{
	struct vmbus_br *rbr = &chan->rxbr;
	uint32_t write_sz, pending_sz, bytes_read;
	int error;

	/* Record where host was when we started read (for debug) */
	rbr->windex = rbr->vbr->windex;

	/* Read data and skip packet header */
	error = vmbus_rxbr_read(rbr, data, dlen, skip);
	if (error)
		return error;

	/* No need for signaling on older versions */
	if (!rbr->vbr->feature_bits.feat_pending_send_sz)
		return 0;

	/* Make sure reading of pending happens after new read index */
	rte_mb();

	pending_sz = rbr->vbr->pending_send;
	if (!pending_sz)
		return 0;

	rte_smp_rmb();
	write_sz = vmbus_br_availwrite(rbr, rbr->vbr->windex);
	bytes_read = dlen + skip + sizeof(uint64_t);

	/* If there was space before then host was not blocked */
	if (write_sz - bytes_read > pending_sz)
		return 0;

	/* If pending write will not fit */
	if (write_sz <= pending_sz)
		return 0;

	vmbus_set_event(chan->device, chan);
	return 0;
}