From d297365290944136f5b401cc0495bae063832d73 Mon Sep 17 00:00:00 2001 From: sephe Date: Wed, 12 Oct 2016 05:09:26 +0000 Subject: [PATCH] MFC 303284,303329,303361,303362,303366,303368-303370 303284 hyperv/vmbus: Move bufring info definition to vmbus_brvar.h Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D7282 303329 hyperv/vmbus: Nuke unnecessary accessor functions. Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D7303 303361 hyperv/vmbus: Initialize RX/TX bufring mutex at channel creation time Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D7312 303362 hyperv/vmbus: Use different struct for RX/TX bufring. So that they can use suitable MP synchronization mechanism. While I'm here change the bufring init/read/write function names. Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7313 303366 hyperv/vmbus: Update comment for bufring Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7314 303368 hyperv/vmbus: Cleanup TX bufring write process. Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7315 303369 hyperv/vmbus: Stringent RX bufring data length checks. Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7316 303370 hyperv/vmbus: Cleanup RX bufring read process. Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7317 git-svn-id: svn://svn.freebsd.org/base/stable/10@307103 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f --- sys/dev/hyperv/vmbus/hv_ring_buffer.c | 494 ++++++++++---------------- sys/dev/hyperv/vmbus/vmbus_brvar.h | 86 +++-- sys/dev/hyperv/vmbus/vmbus_chan.c | 38 +- sys/dev/hyperv/vmbus/vmbus_chanvar.h | 11 +- 4 files changed, 262 insertions(+), 367 deletions(-) diff --git a/sys/dev/hyperv/vmbus/hv_ring_buffer.c b/sys/dev/hyperv/vmbus/hv_ring_buffer.c index e26a80dda..95ba553a9 100644 --- a/sys/dev/hyperv/vmbus/hv_ring_buffer.c +++ b/sys/dev/hyperv/vmbus/hv_ring_buffer.c @@ -37,32 +37,29 @@ __FBSDID("$FreeBSD$"); #include #include -/* Amount of space to write to */ -#define HV_BYTES_AVAIL_TO_WRITE(r, w, z) \ - ((w) >= (r)) ? ((z) - ((w) - (r))) : ((r) - (w)) +/* Amount of space available for write */ +#define VMBUS_BR_WAVAIL(r, w, z) \ + (((w) >= (r)) ? ((z) - ((w) - (r))) : ((r) - (w))) -static uint32_t copy_to_ring_buffer(hv_vmbus_ring_buffer_info *ring_info, - uint32_t start_write_offset, const uint8_t *src, - uint32_t src_len); -static uint32_t copy_from_ring_buffer(hv_vmbus_ring_buffer_info *ring_info, - 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) { - const hv_vmbus_ring_buffer_info *br = arg1; - uint32_t rindex, windex, intr_mask, ravail, wavail; + const struct vmbus_br *br = arg1; + uint32_t rindex, windex, imask, ravail, wavail; char state[256]; - rindex = br->ring_buffer->br_rindex; - windex = br->ring_buffer->br_windex; - intr_mask = br->ring_buffer->br_imask; - wavail = HV_BYTES_AVAIL_TO_WRITE(rindex, windex, br->ring_data_size); - ravail = br->ring_data_size - wavail; + rindex = br->vbr_rindex; + windex = br->vbr_windex; + imask = br->vbr_imask; + wavail = VMBUS_BR_WAVAIL(rindex, windex, br->vbr_dsize); + ravail = br->vbr_dsize - wavail; snprintf(state, sizeof(state), - "rindex:%u windex:%u intr_mask:%u ravail:%u wavail:%u", - rindex, windex, intr_mask, ravail, wavail); + "rindex:%u windex:%u imask:%u ravail:%u wavail:%u", + rindex, windex, imask, ravail, wavail); return sysctl_handle_string(oidp, state, sizeof(state), req); } @@ -79,25 +76,25 @@ vmbus_br_sysctl_state_bin(SYSCTL_HANDLER_ARGS) #define BR_STATE_WSPC 4 #define BR_STATE_MAX 5 - const hv_vmbus_ring_buffer_info *br = arg1; + const struct vmbus_br *br = arg1; uint32_t rindex, windex, wavail, state[BR_STATE_MAX]; - rindex = br->ring_buffer->br_rindex; - windex = br->ring_buffer->br_windex; - wavail = HV_BYTES_AVAIL_TO_WRITE(rindex, windex, br->ring_data_size); + rindex = br->vbr_rindex; + windex = br->vbr_windex; + wavail = VMBUS_BR_WAVAIL(rindex, windex, br->vbr_dsize); state[BR_STATE_RIDX] = rindex; state[BR_STATE_WIDX] = windex; - state[BR_STATE_IMSK] = br->ring_buffer->br_imask; + state[BR_STATE_IMSK] = br->vbr_imask; state[BR_STATE_WSPC] = wavail; - state[BR_STATE_RSPC] = br->ring_data_size - wavail; + state[BR_STATE_RSPC] = br->vbr_dsize - wavail; return sysctl_handle_opaque(oidp, state, sizeof(state), req); } void vmbus_br_sysctl_create(struct sysctl_ctx_list *ctx, struct sysctl_oid *br_tree, - hv_vmbus_ring_buffer_info *br, const char *name) + struct vmbus_br *br, const char *name) { struct sysctl_oid *tree; char desc[64]; @@ -118,342 +115,291 @@ vmbus_br_sysctl_create(struct sysctl_ctx_list *ctx, struct sysctl_oid *br_tree, br, 0, vmbus_br_sysctl_state_bin, "IU", desc); } -/** - * @brief Get number of bytes available to read and to write to - * for the specified ring buffer - */ -static __inline void -get_ring_buffer_avail_bytes(hv_vmbus_ring_buffer_info *rbi, uint32_t *read, - uint32_t *write) +void +vmbus_rxbr_intr_mask(struct vmbus_rxbr *rbr) { - uint32_t read_loc, write_loc; - - /* - * Capture the read/write indices before they changed - */ - read_loc = rbi->ring_buffer->br_rindex; - write_loc = rbi->ring_buffer->br_windex; - - *write = HV_BYTES_AVAIL_TO_WRITE(read_loc, write_loc, - rbi->ring_data_size); - *read = rbi->ring_data_size - *write; + rbr->rxbr_imask = 1; + mb(); } -/** - * @brief Get the next write location for the specified ring buffer - */ static __inline uint32_t -get_next_write_location(hv_vmbus_ring_buffer_info *ring_info) +vmbus_rxbr_avail(const struct vmbus_rxbr *rbr) { - return ring_info->ring_buffer->br_windex; -} + uint32_t rindex, windex; -/** - * @brief Set the next write location for the specified ring buffer - */ -static __inline void -set_next_write_location(hv_vmbus_ring_buffer_info *ring_info, - uint32_t next_write_location) -{ - ring_info->ring_buffer->br_windex = next_write_location; -} + /* Get snapshot */ + rindex = rbr->rxbr_rindex; + windex = rbr->rxbr_windex; -/** - * @brief Get the next read location for the specified ring buffer - */ -static __inline uint32_t -get_next_read_location(hv_vmbus_ring_buffer_info *ring_info) -{ - return ring_info->ring_buffer->br_rindex; + return (rbr->rxbr_dsize - + VMBUS_BR_WAVAIL(rindex, windex, rbr->rxbr_dsize)); } -/** - * @brief Get the next read location + offset for the specified ring buffer. - * This allows the caller to skip. - */ -static __inline uint32_t -get_next_read_location_with_offset(hv_vmbus_ring_buffer_info *ring_info, - uint32_t offset) +uint32_t +vmbus_rxbr_intr_unmask(struct vmbus_rxbr *rbr) { - uint32_t next = ring_info->ring_buffer->br_rindex; + rbr->rxbr_imask = 0; + mb(); - next += offset; - next %= ring_info->ring_data_size; - return (next); + /* + * Now check to see if the ring buffer is still empty. + * If it is not, we raced and we need to process new + * incoming channel packets. + */ + return vmbus_rxbr_avail(rbr); } -/** - * @brief Set the next read location for the specified ring buffer - */ -static __inline void -set_next_read_location(hv_vmbus_ring_buffer_info *ring_info, - uint32_t next_read_location) +static void +vmbus_br_setup(struct vmbus_br *br, void *buf, int blen) { - ring_info->ring_buffer->br_rindex = next_read_location; + br->vbr = buf; + br->vbr_dsize = blen - sizeof(struct vmbus_bufring); } -/** - * @brief Get the start of the ring buffer - */ -static __inline void * -get_ring_buffer(hv_vmbus_ring_buffer_info *ring_info) +void +vmbus_rxbr_init(struct vmbus_rxbr *rbr) { - return ring_info->ring_buffer->br_data; + mtx_init(&rbr->rxbr_lock, "vmbus_rxbr", NULL, MTX_SPIN); } -/** - * @brief Get the size of the ring buffer. - */ -static __inline uint32_t -get_ring_buffer_size(hv_vmbus_ring_buffer_info *ring_info) +void +vmbus_rxbr_deinit(struct vmbus_rxbr *rbr) { - return ring_info->ring_data_size; + mtx_destroy(&rbr->rxbr_lock); } -/** - * Get the read and write indices as uint64_t of the specified ring buffer. - */ -static __inline uint64_t -get_ring_buffer_indices(hv_vmbus_ring_buffer_info *ring_info) +void +vmbus_rxbr_setup(struct vmbus_rxbr *rbr, void *buf, int blen) { - return ((uint64_t)ring_info->ring_buffer->br_windex) << 32; + vmbus_br_setup(&rbr->rxbr, buf, blen); } void -hv_ring_buffer_read_begin(hv_vmbus_ring_buffer_info *ring_info) +vmbus_txbr_init(struct vmbus_txbr *tbr) { - ring_info->ring_buffer->br_imask = 1; - mb(); + mtx_init(&tbr->txbr_lock, "vmbus_txbr", NULL, MTX_SPIN); } -uint32_t -hv_ring_buffer_read_end(hv_vmbus_ring_buffer_info *ring_info) +void +vmbus_txbr_deinit(struct vmbus_txbr *tbr) { - uint32_t read, write; - - ring_info->ring_buffer->br_imask = 0; - mb(); + mtx_destroy(&tbr->txbr_lock); +} - /* - * Now check to see if the ring buffer is still empty. - * If it is not, we raced and we need to process new - * incoming messages. - */ - get_ring_buffer_avail_bytes(ring_info, &read, &write); - return (read); +void +vmbus_txbr_setup(struct vmbus_txbr *tbr, void *buf, int blen) +{ + vmbus_br_setup(&tbr->txbr, buf, blen); } /* - * When we write to the ring buffer, check if the host needs to - * be signaled. Here is the details of this protocol: - * - * 1. The host guarantees that while it is draining the - * ring buffer, it will set the interrupt_mask to - * indicate it does not need to be interrupted when - * new data is placed. + * When we write to the ring buffer, check if the host needs to be + * signaled. * - * 2. The host guarantees that it will completely drain - * the ring buffer before exiting the read loop. Further, - * once the ring buffer is empty, it will clear the - * interrupt_mask and re-check to see if new data has - * arrived. + * The contract: + * - The host guarantees that while it is draining the TX bufring, + * it will set the br_imask to indicate it does not need to be + * interrupted when new data are added. + * - The host guarantees that it will completely drain the TX bufring + * before exiting the read loop. Further, once the TX bufring is + * empty, it will clear the br_imask and re-check to see if new + * data have arrived. */ -static boolean_t -hv_ring_buffer_needsig_on_write(uint32_t old_write_location, - hv_vmbus_ring_buffer_info *rbi) +static __inline boolean_t +vmbus_txbr_need_signal(const struct vmbus_txbr *tbr, uint32_t old_windex) { mb(); - if (rbi->ring_buffer->br_imask) + if (tbr->txbr_imask) return (FALSE); + /* XXX only compiler fence is needed */ /* Read memory barrier */ rmb(); + /* * This is the only case we need to signal when the * ring transitions from being empty to non-empty. */ - if (old_write_location == rbi->ring_buffer->br_rindex) + if (old_windex == tbr->txbr_rindex) return (TRUE); return (FALSE); } -/** - * @brief Initialize the ring buffer. - */ -int -hv_vmbus_ring_buffer_init(hv_vmbus_ring_buffer_info *ring_info, void *buffer, - uint32_t buffer_len) +static __inline uint32_t +vmbus_txbr_avail(const struct vmbus_txbr *tbr) { - memset(ring_info, 0, sizeof(hv_vmbus_ring_buffer_info)); - - ring_info->ring_buffer = buffer; - ring_info->ring_buffer->br_rindex = 0; - ring_info->ring_buffer->br_windex = 0; + uint32_t rindex, windex; - ring_info->ring_data_size = buffer_len - sizeof(struct vmbus_bufring); - mtx_init(&ring_info->ring_lock, "vmbus ring buffer", NULL, MTX_SPIN); + /* Get snapshot */ + rindex = tbr->txbr_rindex; + windex = tbr->txbr_windex; - return (0); + return VMBUS_BR_WAVAIL(rindex, windex, tbr->txbr_dsize); } -/** - * @brief Cleanup the ring buffer. - */ -void -hv_ring_buffer_cleanup(hv_vmbus_ring_buffer_info *ring_info) +static __inline uint32_t +vmbus_txbr_copyto(const struct vmbus_txbr *tbr, uint32_t windex, + const void *src0, uint32_t cplen) { - mtx_destroy(&ring_info->ring_lock); + const uint8_t *src = src0; + uint8_t *br_data = tbr->txbr_data; + uint32_t br_dsize = tbr->txbr_dsize; + + if (cplen > br_dsize - windex) { + uint32_t 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); + } + return VMBUS_BR_IDXINC(windex, cplen, br_dsize); } -/** - * @brief Write to the ring buffer. +/* + * Write scattered channel packet to TX bufring. + * + * The offset of this channel packet is written as a 64bits value + * immediately after this channel packet. */ int -hv_ring_buffer_write(hv_vmbus_ring_buffer_info *out_ring_info, - const struct iovec iov[], uint32_t iovlen, boolean_t *need_sig) +vmbus_txbr_write(struct vmbus_txbr *tbr, const struct iovec iov[], int iovlen, + boolean_t *need_sig) { - int i = 0; - uint32_t byte_avail_to_write; - uint32_t byte_avail_to_read; - uint32_t old_write_location; - uint32_t total_bytes_to_write = 0; - volatile uint32_t next_write_location; - uint64_t prev_indices = 0; + uint32_t old_windex, windex, total; + uint64_t save_windex; + int i; + total = 0; for (i = 0; i < iovlen; i++) - total_bytes_to_write += iov[i].iov_len; - - total_bytes_to_write += sizeof(uint64_t); + total += iov[i].iov_len; + total += sizeof(save_windex); - mtx_lock_spin(&out_ring_info->ring_lock); - - get_ring_buffer_avail_bytes(out_ring_info, &byte_avail_to_read, - &byte_avail_to_write); + mtx_lock_spin(&tbr->txbr_lock); /* - * If there is only room for the packet, assume it is full. - * Otherwise, the next time around, we think the ring buffer - * is empty since the read index == write index + * NOTE: + * If this write is going to make br_windex same as br_rindex, + * i.e. the available space for write is same as the write size, + * we can't do it then, since br_windex == br_rindex means that + * the bufring is empty. */ - if (byte_avail_to_write <= total_bytes_to_write) { - mtx_unlock_spin(&out_ring_info->ring_lock); + if (vmbus_txbr_avail(tbr) <= total) { + mtx_unlock_spin(&tbr->txbr_lock); return (EAGAIN); } + /* Save br_windex for later use */ + old_windex = tbr->txbr_windex; + /* - * Write to the ring buffer + * Copy the scattered channel packet to the TX bufring. */ - next_write_location = get_next_write_location(out_ring_info); - - old_write_location = next_write_location; - + windex = old_windex; for (i = 0; i < iovlen; i++) { - next_write_location = copy_to_ring_buffer(out_ring_info, - next_write_location, iov[i].iov_base, iov[i].iov_len); + windex = vmbus_txbr_copyto(tbr, windex, + iov[i].iov_base, iov[i].iov_len); } /* - * Set previous packet start + * Set the offset of the current channel packet. */ - prev_indices = get_ring_buffer_indices(out_ring_info); - - next_write_location = copy_to_ring_buffer(out_ring_info, - next_write_location, (char *)&prev_indices, sizeof(uint64_t)); + save_windex = ((uint64_t)old_windex) << 32; + windex = vmbus_txbr_copyto(tbr, windex, &save_windex, + sizeof(save_windex)); /* + * XXX only compiler fence is needed. * Full memory barrier before upding the write index. */ mb(); /* - * Now, update the write location + * Update the write index _after_ the channel packet + * is copied. */ - set_next_write_location(out_ring_info, next_write_location); + tbr->txbr_windex = windex; - mtx_unlock_spin(&out_ring_info->ring_lock); + mtx_unlock_spin(&tbr->txbr_lock); - *need_sig = hv_ring_buffer_needsig_on_write(old_write_location, - out_ring_info); + *need_sig = vmbus_txbr_need_signal(tbr, old_windex); return (0); } -/** - * @brief Read without advancing the read index. - */ -int -hv_ring_buffer_peek(hv_vmbus_ring_buffer_info *in_ring_info, void *buffer, - uint32_t buffer_len) +static __inline uint32_t +vmbus_rxbr_copyfrom(const struct vmbus_rxbr *rbr, uint32_t rindex, + void *dst0, int cplen) { - uint32_t bytesAvailToWrite; - uint32_t bytesAvailToRead; - uint32_t nextReadLocation = 0; + uint8_t *dst = dst0; + const uint8_t *br_data = rbr->rxbr_data; + uint32_t br_dsize = rbr->rxbr_dsize; - mtx_lock_spin(&in_ring_info->ring_lock); + if (cplen > br_dsize - rindex) { + uint32_t fraglen = br_dsize - rindex; - get_ring_buffer_avail_bytes(in_ring_info, &bytesAvailToRead, - &bytesAvailToWrite); + /* 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) +{ + mtx_lock_spin(&rbr->rxbr_lock); /* - * Make sure there is something to read + * The requested data and the 64bits channel packet + * offset should be there at least. */ - if (bytesAvailToRead < buffer_len) { - mtx_unlock_spin(&in_ring_info->ring_lock); + if (vmbus_rxbr_avail(rbr) < dlen + sizeof(uint64_t)) { + mtx_unlock_spin(&rbr->rxbr_lock); return (EAGAIN); } + vmbus_rxbr_copyfrom(rbr, rbr->rxbr_rindex, data, dlen); - /* - * Convert to byte offset - */ - nextReadLocation = get_next_read_location(in_ring_info); - - nextReadLocation = copy_from_ring_buffer(in_ring_info, - (char *)buffer, buffer_len, nextReadLocation); - - mtx_unlock_spin(&in_ring_info->ring_lock); + mtx_unlock_spin(&rbr->rxbr_lock); return (0); } -/** - * @brief Read and advance the read index. +/* + * NOTE: + * We assume (dlen + skip) == sizeof(channel packet). */ int -hv_ring_buffer_read(hv_vmbus_ring_buffer_info *in_ring_info, void *buffer, - uint32_t buffer_len, uint32_t offset) +vmbus_rxbr_read(struct vmbus_rxbr *rbr, void *data, int dlen, uint32_t skip) { - uint32_t bytes_avail_to_write; - 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; - if (buffer_len <= 0) - return (EINVAL); + KASSERT(dlen + skip > 0, ("invalid dlen %d, offset %u", dlen, skip)); - mtx_lock_spin(&in_ring_info->ring_lock); + mtx_lock_spin(&rbr->rxbr_lock); - get_ring_buffer_avail_bytes(in_ring_info, &bytes_avail_to_read, - &bytes_avail_to_write); - - /* - * Make sure there is something to read - */ - if (bytes_avail_to_read < buffer_len) { - mtx_unlock_spin(&in_ring_info->ring_lock); + if (vmbus_rxbr_avail(rbr) < dlen + skip + sizeof(uint64_t)) { + mtx_unlock_spin(&rbr->rxbr_lock); return (EAGAIN); } - next_read_location = get_next_read_location_with_offset(in_ring_info, - offset); - - next_read_location = copy_from_ring_buffer(in_ring_info, (char *)buffer, - buffer_len, next_read_location); + /* + * Copy channel packet from RX bufring. + */ + rindex = VMBUS_BR_IDXINC(rbr->rxbr_rindex, skip, br_dsize); + rindex = vmbus_rxbr_copyfrom(rbr, rindex, data, dlen); - next_read_location = copy_from_ring_buffer(in_ring_info, - (char *)&prev_indices, sizeof(uint64_t), next_read_location); + /* + * Discard this channel packet's 64bits offset, which is useless to us. + */ + rindex = VMBUS_BR_IDXINC(rindex, sizeof(uint64_t), br_dsize); /* + * XXX only compiler fence is needed. * Make sure all reads are done before we update the read index since * the writer may start writing to the read area once the read index * is updated. @@ -461,67 +407,11 @@ hv_ring_buffer_read(hv_vmbus_ring_buffer_info *in_ring_info, void *buffer, wmb(); /* - * Update the read index + * Update the read index _after_ the channel packet is fetched. */ - set_next_read_location(in_ring_info, next_read_location); + rbr->rxbr_rindex = rindex; - mtx_unlock_spin(&in_ring_info->ring_lock); + mtx_unlock_spin(&rbr->rxbr_lock); return (0); } - -/** - * @brief Helper routine to copy from source to ring buffer. - * - * Assume there is enough room. Handles wrap-around in dest case only! - */ -static uint32_t -copy_to_ring_buffer(hv_vmbus_ring_buffer_info *ring_info, - uint32_t start_write_offset, const uint8_t *src, uint32_t src_len) -{ - char *ring_buffer = get_ring_buffer(ring_info); - uint32_t ring_buffer_size = get_ring_buffer_size(ring_info); - uint32_t fragLen; - - if (src_len > ring_buffer_size - start_write_offset) { - /* wrap-around detected! */ - fragLen = ring_buffer_size - start_write_offset; - memcpy(ring_buffer + start_write_offset, src, fragLen); - memcpy(ring_buffer, src + fragLen, src_len - fragLen); - } else { - memcpy(ring_buffer + start_write_offset, src, src_len); - } - - start_write_offset += src_len; - start_write_offset %= ring_buffer_size; - - return (start_write_offset); -} - -/** - * @brief Helper routine to copy to source from ring buffer. - * - * Assume there is enough room. Handles wrap-around in src case only! - */ -static uint32_t -copy_from_ring_buffer(hv_vmbus_ring_buffer_info *ring_info, char *dest, - uint32_t dest_len, uint32_t start_read_offset) -{ - uint32_t fragLen; - char *ring_buffer = get_ring_buffer(ring_info); - uint32_t ring_buffer_size = get_ring_buffer_size(ring_info); - - 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); -} diff --git a/sys/dev/hyperv/vmbus/vmbus_brvar.h b/sys/dev/hyperv/vmbus/vmbus_brvar.h index b57a96378..892845b0c 100644 --- a/sys/dev/hyperv/vmbus/vmbus_brvar.h +++ b/sys/dev/hyperv/vmbus/vmbus_brvar.h @@ -28,58 +28,66 @@ * $FreeBSD$ */ -#ifndef __HYPERV_PRIV_H__ -#define __HYPERV_PRIV_H__ +#ifndef _VMBUS_BRVAR_H_ +#define _VMBUS_BRVAR_H_ #include #include #include -#include #include -#include +struct vmbus_br { + struct vmbus_bufring *vbr; + uint32_t vbr_dsize; /* total data size */ +}; -struct vmbus_softc; +#define vbr_windex vbr->br_windex +#define vbr_rindex vbr->br_rindex +#define vbr_imask vbr->br_imask +#define vbr_data vbr->br_data -/* - * Private, VM Bus functions - */ -struct sysctl_ctx_list; -struct sysctl_oid; +struct vmbus_rxbr { + struct mtx rxbr_lock; + struct vmbus_br rxbr; +}; -void vmbus_br_sysctl_create(struct sysctl_ctx_list *ctx, - struct sysctl_oid *br_tree, hv_vmbus_ring_buffer_info *br, - const char *name); +#define rxbr_windex rxbr.vbr_windex +#define rxbr_rindex rxbr.vbr_rindex +#define rxbr_imask rxbr.vbr_imask +#define rxbr_data rxbr.vbr_data +#define rxbr_dsize rxbr.vbr_dsize -int hv_vmbus_ring_buffer_init( - hv_vmbus_ring_buffer_info *ring_info, - void *buffer, - uint32_t buffer_len); +struct vmbus_txbr { + struct mtx txbr_lock; + struct vmbus_br txbr; +}; -void hv_ring_buffer_cleanup( - hv_vmbus_ring_buffer_info *ring_info); +#define txbr_windex txbr.vbr_windex +#define txbr_rindex txbr.vbr_rindex +#define txbr_imask txbr.vbr_imask +#define txbr_data txbr.vbr_data +#define txbr_dsize txbr.vbr_dsize -int hv_ring_buffer_write( - hv_vmbus_ring_buffer_info *ring_info, - const struct iovec iov[], - uint32_t iovlen, - boolean_t *need_sig); - -int hv_ring_buffer_peek( - hv_vmbus_ring_buffer_info *ring_info, - void *buffer, - uint32_t buffer_len); +struct sysctl_ctx_list; +struct sysctl_oid; -int hv_ring_buffer_read( - hv_vmbus_ring_buffer_info *ring_info, - void *buffer, - uint32_t buffer_len, - uint32_t offset); +void vmbus_br_sysctl_create(struct sysctl_ctx_list *ctx, + struct sysctl_oid *br_tree, struct vmbus_br *br, + const char *name); -void hv_ring_buffer_read_begin( - hv_vmbus_ring_buffer_info *ring_info); +void vmbus_rxbr_init(struct vmbus_rxbr *rbr); +void vmbus_rxbr_deinit(struct vmbus_rxbr *rbr); +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 skip); +void vmbus_rxbr_intr_mask(struct vmbus_rxbr *rbr); +uint32_t vmbus_rxbr_intr_unmask(struct vmbus_rxbr *rbr); -uint32_t hv_ring_buffer_read_end( - hv_vmbus_ring_buffer_info *ring_info); +void vmbus_txbr_init(struct vmbus_txbr *tbr); +void vmbus_txbr_deinit(struct vmbus_txbr *tbr); +void vmbus_txbr_setup(struct vmbus_txbr *tbr, void *buf, int blen); +int vmbus_txbr_write(struct vmbus_txbr *tbr, + const struct iovec iov[], int iovlen, boolean_t *need_sig); -#endif /* __HYPERV_PRIV_H__ */ +#endif /* _VMBUS_BRVAR_H_ */ diff --git a/sys/dev/hyperv/vmbus/vmbus_chan.c b/sys/dev/hyperv/vmbus/vmbus_chan.c index 44f57cda2..a163d43f4 100644 --- a/sys/dev/hyperv/vmbus/vmbus_chan.c +++ b/sys/dev/hyperv/vmbus/vmbus_chan.c @@ -178,11 +178,11 @@ vmbus_chan_sysctl_create(struct vmbus_channel *chan) /* * Create sysctl tree for RX bufring. */ - vmbus_br_sysctl_create(ctx, br_tree, &chan->ch_rxbr, "rx"); + vmbus_br_sysctl_create(ctx, br_tree, &chan->ch_rxbr.rxbr, "rx"); /* * Create sysctl tree for TX bufring. */ - vmbus_br_sysctl_create(ctx, br_tree, &chan->ch_txbr, "tx"); + vmbus_br_sysctl_create(ctx, br_tree, &chan->ch_txbr.txbr, "tx"); } } @@ -239,9 +239,9 @@ vmbus_chan_open(struct vmbus_channel *chan, int txbr_size, int rxbr_size, chan->ch_bufring = br; /* TX bufring comes first */ - hv_vmbus_ring_buffer_init(&chan->ch_txbr, br, txbr_size); + vmbus_txbr_setup(&chan->ch_txbr, br, txbr_size); /* RX bufring immediately follows TX bufring */ - hv_vmbus_ring_buffer_init(&chan->ch_rxbr, br + txbr_size, rxbr_size); + vmbus_rxbr_setup(&chan->ch_rxbr, br + txbr_size, rxbr_size); /* Create sysctl tree for this channel */ vmbus_chan_sysctl_create(chan); @@ -549,8 +549,6 @@ vmbus_chan_close_internal(struct vmbus_channel *chan) /* * Destroy the TX+RX bufrings. */ - hv_ring_buffer_cleanup(&chan->ch_txbr); - hv_ring_buffer_cleanup(&chan->ch_rxbr); if (chan->ch_bufring != NULL) { hyperv_dmamem_free(&chan->ch_bufring_dma, chan->ch_bufring); chan->ch_bufring = NULL; @@ -620,7 +618,7 @@ vmbus_chan_send(struct vmbus_channel *chan, uint16_t type, uint16_t flags, iov[2].iov_base = &pad; iov[2].iov_len = pad_pktlen - pktlen; - error = hv_ring_buffer_write(&chan->ch_txbr, iov, 3, &send_evt); + error = vmbus_txbr_write(&chan->ch_txbr, iov, 3, &send_evt); if (!error && send_evt) vmbus_chan_signal_tx(chan); return error; @@ -660,7 +658,7 @@ vmbus_chan_send_sglist(struct vmbus_channel *chan, iov[3].iov_base = &pad; iov[3].iov_len = pad_pktlen - pktlen; - error = hv_ring_buffer_write(&chan->ch_txbr, iov, 4, &send_evt); + error = vmbus_txbr_write(&chan->ch_txbr, iov, 4, &send_evt); if (!error && send_evt) vmbus_chan_signal_tx(chan); return error; @@ -702,7 +700,7 @@ vmbus_chan_send_prplist(struct vmbus_channel *chan, iov[3].iov_base = &pad; iov[3].iov_len = pad_pktlen - pktlen; - error = hv_ring_buffer_write(&chan->ch_txbr, iov, 4, &send_evt); + error = vmbus_txbr_write(&chan->ch_txbr, iov, 4, &send_evt); if (!error && send_evt) vmbus_chan_signal_tx(chan); return error; @@ -715,7 +713,7 @@ vmbus_chan_recv(struct vmbus_channel *chan, void *data, int *dlen0, struct vmbus_chanpkt_hdr pkt; int error, dlen, hlen; - error = hv_ring_buffer_peek(&chan->ch_rxbr, &pkt, sizeof(pkt)); + error = vmbus_rxbr_peek(&chan->ch_rxbr, &pkt, sizeof(pkt)); if (error) return error; @@ -732,8 +730,8 @@ vmbus_chan_recv(struct vmbus_channel *chan, void *data, int *dlen0, *dlen0 = dlen; /* Skip packet header */ - error = hv_ring_buffer_read(&chan->ch_rxbr, data, dlen, hlen); - KASSERT(!error, ("hv_ring_buffer_read failed")); + error = vmbus_rxbr_read(&chan->ch_rxbr, data, dlen, hlen); + KASSERT(!error, ("vmbus_rxbr_read failed")); return 0; } @@ -745,7 +743,7 @@ vmbus_chan_recv_pkt(struct vmbus_channel *chan, struct vmbus_chanpkt_hdr pkt; int error, pktlen; - error = hv_ring_buffer_peek(&chan->ch_rxbr, &pkt, sizeof(pkt)); + error = vmbus_rxbr_peek(&chan->ch_rxbr, &pkt, sizeof(pkt)); if (error) return error; @@ -758,8 +756,8 @@ vmbus_chan_recv_pkt(struct vmbus_channel *chan, *pktlen0 = pktlen; /* Include packet header */ - error = hv_ring_buffer_read(&chan->ch_rxbr, pkt0, pktlen, 0); - KASSERT(!error, ("hv_ring_buffer_read failed")); + error = vmbus_rxbr_read(&chan->ch_rxbr, pkt0, pktlen, 0); + KASSERT(!error, ("vmbus_rxbr_read failed")); return 0; } @@ -788,12 +786,12 @@ vmbus_chan_task(void *xchan, int pending __unused) cb(chan, cbarg); - left = hv_ring_buffer_read_end(&chan->ch_rxbr); + left = vmbus_rxbr_intr_unmask(&chan->ch_rxbr); if (left == 0) { /* No more data in RX bufring; done */ break; } - hv_ring_buffer_read_begin(&chan->ch_rxbr); + vmbus_rxbr_intr_mask(&chan->ch_rxbr); } } @@ -835,7 +833,7 @@ vmbus_event_flags_proc(struct vmbus_softc *sc, volatile u_long *event_flags, continue; if (chan->ch_flags & VMBUS_CHAN_FLAG_BATCHREAD) - hv_ring_buffer_read_begin(&chan->ch_rxbr); + vmbus_rxbr_intr_mask(&chan->ch_rxbr); taskqueue_enqueue(chan->ch_tq, &chan->ch_task); } } @@ -914,6 +912,8 @@ vmbus_chan_alloc(struct vmbus_softc *sc) mtx_init(&chan->ch_subchan_lock, "vmbus subchan", NULL, MTX_DEF); TAILQ_INIT(&chan->ch_subchans); TASK_INIT(&chan->ch_detach_task, 0, vmbus_chan_detach_task, chan); + vmbus_rxbr_init(&chan->ch_rxbr); + vmbus_txbr_init(&chan->ch_txbr); return chan; } @@ -926,6 +926,8 @@ vmbus_chan_free(struct vmbus_channel *chan) /* TODO: asset no longer on the vmbus channel list */ hyperv_dmamem_free(&chan->ch_monprm_dma, chan->ch_monprm); mtx_destroy(&chan->ch_subchan_lock); + vmbus_rxbr_deinit(&chan->ch_rxbr); + vmbus_txbr_deinit(&chan->ch_txbr); free(chan, M_DEVBUF); } diff --git a/sys/dev/hyperv/vmbus/vmbus_chanvar.h b/sys/dev/hyperv/vmbus/vmbus_chanvar.h index 593d09d29..3f128b488 100644 --- a/sys/dev/hyperv/vmbus/vmbus_chanvar.h +++ b/sys/dev/hyperv/vmbus/vmbus_chanvar.h @@ -39,12 +39,7 @@ #include #include #include - -typedef struct { - struct vmbus_bufring *ring_buffer; - struct mtx ring_lock; - uint32_t ring_data_size; /* ring_size */ -} hv_vmbus_ring_buffer_info; +#include struct vmbus_channel { /* @@ -57,7 +52,7 @@ struct vmbus_channel { /* * RX bufring; immediately following ch_txbr. */ - hv_vmbus_ring_buffer_info ch_rxbr; + struct vmbus_rxbr ch_rxbr; struct taskqueue *ch_tq; struct task ch_task; @@ -76,7 +71,7 @@ struct vmbus_channel { * TX bufring and following MNF/evtflags do _not_ fit in * one 64B cacheline. */ - hv_vmbus_ring_buffer_info ch_txbr __aligned(CACHE_LINE_SIZE); + struct vmbus_txbr ch_txbr __aligned(CACHE_LINE_SIZE); uint32_t ch_txflags; /* VMBUS_CHAN_TXF_ */ /* -- 2.45.0