svn commit: r303370 - head/sys/dev/hyperv/vmbus
Sepherosa Ziehau
sephe at FreeBSD.org
Wed Jul 27 07:36:55 UTC 2016
Author: sephe
Date: Wed Jul 27 07:36:54 2016
New Revision: 303370
URL: https://svnweb.freebsd.org/changeset/base/303370
Log:
hyperv/vmbus: Cleanup RX bufring read process.
MFC after: 1 week
Sponsored by: Microsoft
Differential Revision: https://reviews.freebsd.org/D7317
Modified:
head/sys/dev/hyperv/vmbus/hv_ring_buffer.c
head/sys/dev/hyperv/vmbus/vmbus_brvar.h
Modified: head/sys/dev/hyperv/vmbus/hv_ring_buffer.c
==============================================================================
--- head/sys/dev/hyperv/vmbus/hv_ring_buffer.c Wed Jul 27 07:19:06 2016 (r303369)
+++ head/sys/dev/hyperv/vmbus/hv_ring_buffer.c Wed Jul 27 07:36:54 2016 (r303370)
@@ -38,8 +38,8 @@
#define VMBUS_BR_WAVAIL(r, w, z) \
(((w) >= (r)) ? ((z) - ((w) - (r))) : ((r) - (w)))
-static uint32_t copy_from_ring_buffer(const struct vmbus_rxbr *rbr,
- char *dest, uint32_t dest_len, uint32_t start_read_offset);
+/* Increase bufing index */
+#define VMBUS_BR_IDXINC(idx, inc, sz) (((idx) + (inc)) % (sz))
static int
vmbus_br_sysctl_state(SYSCTL_HANDLER_ARGS)
@@ -244,20 +244,15 @@ vmbus_txbr_copyto(const struct vmbus_txb
uint32_t br_dsize = tbr->txbr_dsize;
if (cplen > br_dsize - windex) {
- uint32_t fraglen;
+ uint32_t fraglen = br_dsize - windex;
- /* Wrap-around detected! */
- fraglen = br_dsize - windex;
+ /* Wrap-around detected */
memcpy(br_data + windex, src, fraglen);
memcpy(br_data, src + fraglen, cplen - fraglen);
} else {
memcpy(br_data + windex, src, cplen);
}
-
- windex += cplen;
- windex %= br_dsize;
-
- return windex;
+ return VMBUS_BR_IDXINC(windex, cplen, br_dsize);
}
/*
@@ -331,46 +326,60 @@ vmbus_txbr_write(struct vmbus_txbr *tbr,
return (0);
}
+static __inline uint32_t
+vmbus_rxbr_copyfrom(const struct vmbus_rxbr *rbr, uint32_t rindex,
+ void *dst0, int cplen)
+{
+ uint8_t *dst = dst0;
+ const uint8_t *br_data = rbr->rxbr_data;
+ uint32_t br_dsize = rbr->rxbr_dsize;
+
+ if (cplen > br_dsize - rindex) {
+ uint32_t fraglen = br_dsize - rindex;
+
+ /* Wrap-around detected. */
+ memcpy(dst, br_data + rindex, fraglen);
+ memcpy(dst + fraglen, br_data, cplen - fraglen);
+ } else {
+ memcpy(dst, br_data + rindex, cplen);
+ }
+ return VMBUS_BR_IDXINC(rindex, cplen, br_dsize);
+}
+
int
vmbus_rxbr_peek(struct vmbus_rxbr *rbr, void *data, int dlen)
{
- uint32_t bytesAvailToRead;
- uint32_t nextReadLocation = 0;
-
mtx_lock_spin(&rbr->rxbr_lock);
/*
* The requested data and the 64bits channel packet
* offset should be there at least.
*/
- bytesAvailToRead = vmbus_rxbr_avail(rbr);
- if (bytesAvailToRead < dlen + sizeof(uint64_t)) {
+ if (vmbus_rxbr_avail(rbr) < dlen + sizeof(uint64_t)) {
mtx_unlock_spin(&rbr->rxbr_lock);
return (EAGAIN);
}
-
- nextReadLocation = rbr->rxbr_rindex;
- nextReadLocation = copy_from_ring_buffer(rbr, data, dlen,
- nextReadLocation);
+ vmbus_rxbr_copyfrom(rbr, rbr->rxbr_rindex, data, dlen);
mtx_unlock_spin(&rbr->rxbr_lock);
return (0);
}
+/*
+ * NOTE:
+ * We assume (dlen + skip) == sizeof(channel packet).
+ */
int
-vmbus_rxbr_read(struct vmbus_rxbr *rbr, void *data, int dlen, uint32_t offset)
+vmbus_rxbr_read(struct vmbus_rxbr *rbr, void *data, int dlen, uint32_t skip)
{
- uint32_t bytes_avail_to_read;
- uint32_t next_read_location = 0;
- uint64_t prev_indices = 0;
+ uint32_t rindex, br_dsize = rbr->rxbr_dsize;
- KASSERT(dlen > 0, ("invalid dlen %d", dlen));
+ KASSERT(dlen + skip > 0, ("invalid dlen %d, offset %u", dlen, skip));
mtx_lock_spin(&rbr->rxbr_lock);
- bytes_avail_to_read = vmbus_rxbr_avail(rbr);
- if (bytes_avail_to_read < dlen + offset + sizeof(prev_indices)) {
+ if (vmbus_rxbr_avail(rbr) < dlen + skip + sizeof(uint64_t)) {
mtx_unlock_spin(&rbr->rxbr_lock);
return (EAGAIN);
}
@@ -378,16 +387,13 @@ vmbus_rxbr_read(struct vmbus_rxbr *rbr,
/*
* Copy channel packet from RX bufring.
*/
- next_read_location = (rbr->rxbr_rindex + offset) % rbr->rxbr_dsize;
- next_read_location = copy_from_ring_buffer(rbr, data, dlen,
- next_read_location);
+ rindex = VMBUS_BR_IDXINC(rbr->rxbr_rindex, skip, br_dsize);
+ rindex = vmbus_rxbr_copyfrom(rbr, rindex, data, dlen);
/*
- * Discard this channel packet's start offset, which is useless
- * for us.
+ * Discard this channel packet's 64bits offset, which is useless to us.
*/
- next_read_location = copy_from_ring_buffer(rbr,
- (char *)&prev_indices, sizeof(uint64_t), next_read_location);
+ rindex = VMBUS_BR_IDXINC(rindex, sizeof(uint64_t), br_dsize);
/*
* XXX only compiler fence is needed.
@@ -398,34 +404,11 @@ vmbus_rxbr_read(struct vmbus_rxbr *rbr,
wmb();
/*
- * Update the read index
+ * Update the read index _after_ the channel packet is fetched.
*/
- rbr->rxbr_rindex = next_read_location;
+ rbr->rxbr_rindex = rindex;
mtx_unlock_spin(&rbr->rxbr_lock);
return (0);
}
-
-static uint32_t
-copy_from_ring_buffer(const struct vmbus_rxbr *rbr, char *dest,
- uint32_t dest_len, uint32_t start_read_offset)
-{
- uint32_t fragLen;
- char *ring_buffer = rbr->rxbr_data;
- uint32_t ring_buffer_size = rbr->rxbr_dsize;
-
- if (dest_len > ring_buffer_size - start_read_offset) {
- /* Wrap-around detected at the src */
- fragLen = ring_buffer_size - start_read_offset;
- memcpy(dest, ring_buffer + start_read_offset, fragLen);
- memcpy(dest + fragLen, ring_buffer, dest_len - fragLen);
- } else {
- memcpy(dest, ring_buffer + start_read_offset, dest_len);
- }
-
- start_read_offset += dest_len;
- start_read_offset %= ring_buffer_size;
-
- return (start_read_offset);
-}
Modified: head/sys/dev/hyperv/vmbus/vmbus_brvar.h
==============================================================================
--- head/sys/dev/hyperv/vmbus/vmbus_brvar.h Wed Jul 27 07:19:06 2016 (r303369)
+++ head/sys/dev/hyperv/vmbus/vmbus_brvar.h Wed Jul 27 07:36:54 2016 (r303370)
@@ -80,7 +80,7 @@ void vmbus_rxbr_deinit(struct vmbus_rxb
void vmbus_rxbr_setup(struct vmbus_rxbr *rbr, void *buf, int blen);
int vmbus_rxbr_peek(struct vmbus_rxbr *rbr, void *data, int dlen);
int vmbus_rxbr_read(struct vmbus_rxbr *rbr, void *data, int dlen,
- uint32_t offset);
+ uint32_t skip);
void vmbus_rxbr_intr_mask(struct vmbus_rxbr *rbr);
uint32_t vmbus_rxbr_intr_unmask(struct vmbus_rxbr *rbr);
More information about the svn-src-head
mailing list