int
vmbus_chan_send(struct vmbus_channel *chan, uint16_t type, uint16_t flags,
    void *data, int dlen, uint64_t xactid)
{
	struct vmbus_chanpkt pkt;
	int pktlen, pad_pktlen, hlen, error;
	uint64_t pad = 0;
	struct iovec iov[3];
	boolean_t send_evt;

	hlen = sizeof(pkt);
	pktlen = hlen + dlen;
	pad_pktlen = VMBUS_CHANPKT_TOTLEN(pktlen);
	KASSERT(pad_pktlen <= vmbus_txbr_maxpktsz(&chan->ch_txbr),
	    ("invalid packet size %d", pad_pktlen));

	pkt.cp_hdr.cph_type = type;
	pkt.cp_hdr.cph_flags = flags;
	VMBUS_CHANPKT_SETLEN(pkt.cp_hdr.cph_hlen, hlen);
	VMBUS_CHANPKT_SETLEN(pkt.cp_hdr.cph_tlen, pad_pktlen);
	pkt.cp_hdr.cph_xactid = xactid;

	iov[0].iov_base = &pkt;
	iov[0].iov_len = hlen;
	iov[1].iov_base = data;
	iov[1].iov_len = dlen;
	iov[2].iov_base = &pad;
	iov[2].iov_len = pad_pktlen - pktlen;

	error = vmbus_txbr_write(&chan->ch_txbr, iov, 3, &send_evt);
	if (!error && send_evt)
		vmbus_chan_signal_tx(chan);
	return error;
}
Beispiel #2
0
/* Do a scatter/gather send where the descriptor points to data. */
int rte_vmbus_chan_send_sglist(struct vmbus_channel *chan,
			       struct vmbus_gpa sg[], uint32_t sglen,
			       void *data, uint32_t dlen,
			       uint64_t xactid, bool *need_sig)
{
	struct vmbus_chanpkt_sglist pkt;
	unsigned int pktlen, pad_pktlen, hlen;
	bool send_evt = false;
	struct iovec iov[4];
	uint64_t pad = 0;
	int error;

	hlen = offsetof(struct vmbus_chanpkt_sglist, gpa[sglen]);
	pktlen = hlen + dlen;
	pad_pktlen = RTE_ALIGN(pktlen, sizeof(uint64_t));

	pkt.hdr.type = VMBUS_CHANPKT_TYPE_GPA;
	pkt.hdr.flags = VMBUS_CHANPKT_FLAG_RC;
	pkt.hdr.hlen = hlen >> VMBUS_CHANPKT_SIZE_SHIFT;
	pkt.hdr.tlen = pad_pktlen >> VMBUS_CHANPKT_SIZE_SHIFT;
	pkt.hdr.xactid = xactid;
	pkt.rsvd = 0;
	pkt.gpa_cnt = sglen;

	iov[0].iov_base = &pkt;
	iov[0].iov_len = sizeof(pkt);
	iov[1].iov_base = sg;
	iov[1].iov_len = sizeof(struct vmbus_gpa) * sglen;
	iov[2].iov_base = data;
	iov[2].iov_len = dlen;
	iov[3].iov_base = &pad;
	iov[3].iov_len = pad_pktlen - pktlen;

	error = vmbus_txbr_write(&chan->txbr, iov, 4, &send_evt);

	/* if caller is batching, just propagate the status */
	if (need_sig)
		*need_sig |= send_evt;
	else if (error == 0 && send_evt)
		rte_vmbus_chan_signal_tx(chan);
	return error;
}
Beispiel #3
0
/* Do a simple send directly using transmit ring. */
int rte_vmbus_chan_send(struct vmbus_channel *chan, uint16_t type,
			void *data, uint32_t dlen,
			uint64_t xactid, uint32_t flags, bool *need_sig)
{
	struct vmbus_chanpkt pkt;
	unsigned int pktlen, pad_pktlen;
	const uint32_t hlen = sizeof(pkt);
	bool send_evt = false;
	uint64_t pad = 0;
	struct iovec iov[3];
	int error;

	pktlen = hlen + dlen;
	pad_pktlen = RTE_ALIGN(pktlen, sizeof(uint64_t));

	pkt.hdr.type = type;
	pkt.hdr.flags = flags;
	pkt.hdr.hlen = hlen >> VMBUS_CHANPKT_SIZE_SHIFT;
	pkt.hdr.tlen = pad_pktlen >> VMBUS_CHANPKT_SIZE_SHIFT;
	pkt.hdr.xactid = xactid;

	iov[0].iov_base = &pkt;
	iov[0].iov_len = hlen;
	iov[1].iov_base = data;
	iov[1].iov_len = dlen;
	iov[2].iov_base = &pad;
	iov[2].iov_len = pad_pktlen - pktlen;

	error = vmbus_txbr_write(&chan->txbr, iov, 3, &send_evt);

	/*
	 * caller sets need_sig to non-NULL if it will handle
	 * signaling if required later.
	 * if need_sig is NULL, signal now if needed.
	 */
	if (need_sig)
		*need_sig |= send_evt;
	else if (error == 0 && send_evt)
		rte_vmbus_chan_signal_tx(chan);
	return error;
}
int
vmbus_chan_send_prplist(struct vmbus_channel *chan,
    struct vmbus_gpa_range *prp, int prp_cnt, void *data, int dlen,
    uint64_t xactid)
{
	struct vmbus_chanpkt_prplist pkt;
	int pktlen, pad_pktlen, hlen, error;
	struct iovec iov[4];
	boolean_t send_evt;
	uint64_t pad = 0;

	hlen = __offsetof(struct vmbus_chanpkt_prplist,
	    cp_range[0].gpa_page[prp_cnt]);
	pktlen = hlen + dlen;
	pad_pktlen = VMBUS_CHANPKT_TOTLEN(pktlen);
	KASSERT(pad_pktlen <= vmbus_txbr_maxpktsz(&chan->ch_txbr),
	    ("invalid packet size %d", pad_pktlen));

	pkt.cp_hdr.cph_type = VMBUS_CHANPKT_TYPE_GPA;
	pkt.cp_hdr.cph_flags = VMBUS_CHANPKT_FLAG_RC;
	VMBUS_CHANPKT_SETLEN(pkt.cp_hdr.cph_hlen, hlen);
	VMBUS_CHANPKT_SETLEN(pkt.cp_hdr.cph_tlen, pad_pktlen);
	pkt.cp_hdr.cph_xactid = xactid;
	pkt.cp_rsvd = 0;
	pkt.cp_range_cnt = 1;

	iov[0].iov_base = &pkt;
	iov[0].iov_len = sizeof(pkt);
	iov[1].iov_base = prp;
	iov[1].iov_len = __offsetof(struct vmbus_gpa_range, gpa_page[prp_cnt]);
	iov[2].iov_base = data;
	iov[2].iov_len = dlen;
	iov[3].iov_base = &pad;
	iov[3].iov_len = pad_pktlen - pktlen;

	error = vmbus_txbr_write(&chan->ch_txbr, iov, 4, &send_evt);
	if (!error && send_evt)
		vmbus_chan_signal_tx(chan);
	return error;
}