diff options
author | Mike Belopuhov <mikeb@cvs.openbsd.org> | 2017-06-14 09:47:38 +0000 |
---|---|---|
committer | Mike Belopuhov <mikeb@cvs.openbsd.org> | 2017-06-14 09:47:38 +0000 |
commit | 1eda2c09bf77908bdfc7984de003c39b7d2de5a3 (patch) | |
tree | 2bba801fbc2be2390012c81b506a2a4ba1d0ea60 /sys/dev/pv/hyperv.c | |
parent | daa4a664fed350336c604364248f1627d118eb96 (diff) |
Add another type of a scatter-gather list operation used by StorVSC
Obtained from FreeBSD.
Diffstat (limited to 'sys/dev/pv/hyperv.c')
-rw-r--r-- | sys/dev/pv/hyperv.c | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/sys/dev/pv/hyperv.c b/sys/dev/pv/hyperv.c index 2d0a38fabc7..f9840e87113 100644 --- a/sys/dev/pv/hyperv.c +++ b/sys/dev/pv/hyperv.c @@ -1403,6 +1403,50 @@ hv_channel_send_sgl(struct hv_channel *ch, struct vmbus_gpa *sgl, } int +hv_channel_send_prpl(struct hv_channel *ch, struct vmbus_gpa_range *prpl, + uint32_t nprp, void *data, uint32_t datalen, uint64_t rid) +{ + struct hv_softc *sc = ch->ch_sc; + struct vmbus_chanpkt_prplist cp; + struct iovec iov[4]; + uint32_t buflen, pktlen, pktlen_aligned; + uint64_t zeropad = 0; + int rv, needsig = 0; + + buflen = sizeof(struct vmbus_gpa_range) * (nprp + 1); + pktlen = sizeof(cp) + datalen + buflen; + pktlen_aligned = roundup(pktlen, sizeof(uint64_t)); + + cp.cp_hdr.cph_type = VMBUS_CHANPKT_TYPE_GPA; + cp.cp_hdr.cph_flags = VMBUS_CHANPKT_FLAG_RC; + VMBUS_CHANPKT_SETLEN(cp.cp_hdr.cph_hlen, sizeof(cp) + buflen); + VMBUS_CHANPKT_SETLEN(cp.cp_hdr.cph_tlen, pktlen_aligned); + cp.cp_hdr.cph_tid = rid; + cp.cp_range_cnt = 1; + cp.cp_rsvd = 0; + + iov[0].iov_base = &cp; + iov[0].iov_len = sizeof(cp); + + iov[1].iov_base = prpl; + iov[1].iov_len = buflen; + + iov[2].iov_base = data; + iov[2].iov_len = datalen; + + iov[3].iov_base = &zeropad; + iov[3].iov_len = pktlen_aligned - pktlen; + + mtx_enter(&ch->ch_wrd.rd_lock); + rv = hv_ring_write(&ch->ch_wrd, iov, 4, &needsig); + mtx_leave(&ch->ch_wrd.rd_lock); + if (rv == 0 && needsig) + hv_channel_setevent(sc, ch); + + return (rv); +} + +int hv_ring_peek(struct hv_ring_data *rrd, void *data, uint32_t datalen) { uint32_t avail; |