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; }
/* 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; }
/* 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; }