Add another type of a scatter-gather list operation used by StorVSC
authormikeb <mikeb@openbsd.org>
Wed, 14 Jun 2017 09:47:37 +0000 (09:47 +0000)
committermikeb <mikeb@openbsd.org>
Wed, 14 Jun 2017 09:47:37 +0000 (09:47 +0000)
Obtained from FreeBSD.

sys/dev/pv/hyperv.c
sys/dev/pv/hypervvar.h

index 2d0a38f..f9840e8 100644 (file)
@@ -1402,6 +1402,50 @@ hv_channel_send_sgl(struct hv_channel *ch, struct vmbus_gpa *sgl,
        return (rv);
 }
 
+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)
 {
index 425431b..3305a44 100644 (file)
@@ -212,6 +212,8 @@ int hv_channel_send(struct hv_channel *, void *, uint32_t, uint64_t,
            int, uint32_t);
 int    hv_channel_send_sgl(struct hv_channel *, struct vmbus_gpa *,
            uint32_t, void *, uint32_t, uint64_t);
+int    hv_channel_send_prpl(struct hv_channel *, struct vmbus_gpa_range *,
+           uint32_t, void *, uint32_t, uint64_t);
 int    hv_channel_recv(struct hv_channel *, void *, uint32_t, uint32_t *,
            uint64_t *, int);