Date: Wed, 12 Oct 2016 05:09:27 +0000 (UTC) From: Sepherosa Ziehau <sephe@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r307103 - stable/10/sys/dev/hyperv/vmbus Message-ID: <201610120509.u9C59Rjh008401@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: sephe Date: Wed Oct 12 05:09:26 2016 New Revision: 307103 URL: https://svnweb.freebsd.org/changeset/base/307103 Log: 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 Modified: stable/10/sys/dev/hyperv/vmbus/hv_ring_buffer.c stable/10/sys/dev/hyperv/vmbus/vmbus_brvar.h stable/10/sys/dev/hyperv/vmbus/vmbus_chan.c stable/10/sys/dev/hyperv/vmbus/vmbus_chanvar.h Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/dev/hyperv/vmbus/hv_ring_buffer.c ============================================================================== --- stable/10/sys/dev/hyperv/vmbus/hv_ring_buffer.c Wed Oct 12 05:09:22 2016 (r307102) +++ stable/10/sys/dev/hyperv/vmbus/hv_ring_buffer.c Wed Oct 12 05:09:26 2016 (r307103) @@ -37,32 +37,29 @@ __FBSDID("$FreeBSD$"); #include <dev/hyperv/vmbus/vmbus_reg.h> #include <dev/hyperv/vmbus/vmbus_brvar.h> -/* Amount of space to write to */ -#define HV_BYTES_AVAIL_TO_WRITE(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); +/* Amount of space available for write */ +#define VMBUS_BR_WAVAIL(r, w, z) \ + (((w) >= (r)) ? ((z) - ((w) - (r))) : ((r) - (w))) + +/* 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 #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 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 += iov[i].iov_len; + total += sizeof(save_windex); - total_bytes_to_write += sizeof(uint64_t); - - 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; - - mtx_lock_spin(&in_ring_info->ring_lock); + 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); +} - get_ring_buffer_avail_bytes(in_ring_info, &bytesAvailToRead, - &bytesAvailToWrite); +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; - - if (buffer_len <= 0) - return (EINVAL); + uint32_t rindex, br_dsize = rbr->rxbr_dsize; - mtx_lock_spin(&in_ring_info->ring_lock); + KASSERT(dlen + skip > 0, ("invalid dlen %d, offset %u", dlen, skip)); - get_ring_buffer_avail_bytes(in_ring_info, &bytes_avail_to_read, - &bytes_avail_to_write); + mtx_lock_spin(&rbr->rxbr_lock); - /* - * 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 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); -} Modified: stable/10/sys/dev/hyperv/vmbus/vmbus_brvar.h ============================================================================== --- stable/10/sys/dev/hyperv/vmbus/vmbus_brvar.h Wed Oct 12 05:09:22 2016 (r307102) +++ stable/10/sys/dev/hyperv/vmbus/vmbus_brvar.h Wed Oct 12 05:09:26 2016 (r307103) @@ -28,58 +28,66 @@ * $FreeBSD$ */ -#ifndef __HYPERV_PRIV_H__ -#define __HYPERV_PRIV_H__ +#ifndef _VMBUS_BRVAR_H_ +#define _VMBUS_BRVAR_H_ #include <sys/param.h> #include <sys/lock.h> #include <sys/mutex.h> -#include <sys/sema.h> #include <sys/_iovec.h> -#include <dev/hyperv/vmbus/vmbus_chanvar.h> +struct vmbus_br { + struct vmbus_bufring *vbr; + uint32_t vbr_dsize; /* total data size */ +}; + +#define vbr_windex vbr->br_windex +#define vbr_rindex vbr->br_rindex +#define vbr_imask vbr->br_imask +#define vbr_data vbr->br_data + +struct vmbus_rxbr { + struct mtx rxbr_lock; + struct vmbus_br rxbr; +}; + +#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 + +struct vmbus_txbr { + struct mtx txbr_lock; + struct vmbus_br txbr; +}; + +#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 -struct vmbus_softc; - -/* - * Private, VM Bus functions - */ struct sysctl_ctx_list; struct sysctl_oid; -void vmbus_br_sysctl_create(struct sysctl_ctx_list *ctx, - struct sysctl_oid *br_tree, hv_vmbus_ring_buffer_info *br, - const char *name); - -int hv_vmbus_ring_buffer_init( - hv_vmbus_ring_buffer_info *ring_info, - void *buffer, - uint32_t buffer_len); - -void hv_ring_buffer_cleanup( - hv_vmbus_ring_buffer_info *ring_info); - -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); - -int hv_ring_buffer_read( - hv_vmbus_ring_buffer_info *ring_info, - void *buffer, - uint32_t buffer_len, - uint32_t offset); - -void hv_ring_buffer_read_begin( - hv_vmbus_ring_buffer_info *ring_info); - -uint32_t hv_ring_buffer_read_end( - hv_vmbus_ring_buffer_info *ring_info); +void vmbus_br_sysctl_create(struct sysctl_ctx_list *ctx, + struct sysctl_oid *br_tree, struct vmbus_br *br, + const char *name); + +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); + +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_ */ Modified: stable/10/sys/dev/hyperv/vmbus/vmbus_chan.c ============================================================================== --- stable/10/sys/dev/hyperv/vmbus/vmbus_chan.c Wed Oct 12 05:09:22 2016 (r307102) +++ stable/10/sys/dev/hyperv/vmbus/vmbus_chan.c Wed Oct 12 05:09:26 2016 (r307103) @@ -178,11 +178,11 @@ vmbus_chan_sysctl_create(struct vmbus_ch /* * 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 *ch 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_c /* * 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 *ch 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_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_cha 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 *ch 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 *ch *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 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 *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 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_soft 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 *ch /* 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); } Modified: stable/10/sys/dev/hyperv/vmbus/vmbus_chanvar.h ============================================================================== --- stable/10/sys/dev/hyperv/vmbus/vmbus_chanvar.h Wed Oct 12 05:09:22 2016 (r307102) +++ stable/10/sys/dev/hyperv/vmbus/vmbus_chanvar.h Wed Oct 12 05:09:26 2016 (r307103) @@ -39,12 +39,7 @@ #include <dev/hyperv/include/hyperv.h> #include <dev/hyperv/include/hyperv_busdma.h> #include <dev/hyperv/include/vmbus.h> - -typedef struct { - struct vmbus_bufring *ring_buffer; - struct mtx ring_lock; - uint32_t ring_data_size; /* ring_size */ -} hv_vmbus_ring_buffer_info; +#include <dev/hyperv/vmbus/vmbus_brvar.h> 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_ */ /*
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201610120509.u9C59Rjh008401>