Index: head/sys/dev/hyperv/vmbus/hv_ring_buffer.c =================================================================== --- head/sys/dev/hyperv/vmbus/hv_ring_buffer.c +++ head/sys/dev/hyperv/vmbus/hv_ring_buffer.c @@ -32,6 +32,7 @@ #include #include "hv_vmbus_priv.h" +#include /* Amount of space to write to */ #define HV_BYTES_AVAIL_TO_WRITE(r, w, z) \ @@ -50,9 +51,9 @@ uint32_t rindex, windex, intr_mask, ravail, wavail; char state[256]; - rindex = br->ring_buffer->read_index; - windex = br->ring_buffer->write_index; - intr_mask = br->ring_buffer->interrupt_mask; + 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; @@ -78,13 +79,13 @@ const hv_vmbus_ring_buffer_info *br = arg1; uint32_t rindex, windex, wavail, state[BR_STATE_MAX]; - rindex = br->ring_buffer->read_index; - windex = br->ring_buffer->write_index; + rindex = br->ring_buffer->br_rindex; + windex = br->ring_buffer->br_windex; wavail = HV_BYTES_AVAIL_TO_WRITE(rindex, windex, br->ring_data_size); state[BR_STATE_RIDX] = rindex; state[BR_STATE_WIDX] = windex; - state[BR_STATE_IMSK] = br->ring_buffer->interrupt_mask; + state[BR_STATE_IMSK] = br->ring_buffer->br_imask; state[BR_STATE_WSPC] = wavail; state[BR_STATE_RSPC] = br->ring_data_size - wavail; @@ -127,8 +128,8 @@ /* * Capture the read/write indices before they changed */ - read_loc = rbi->ring_buffer->read_index; - write_loc = rbi->ring_buffer->write_index; + 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); @@ -141,7 +142,7 @@ static __inline uint32_t get_next_write_location(hv_vmbus_ring_buffer_info *ring_info) { - return ring_info->ring_buffer->write_index; + return ring_info->ring_buffer->br_windex; } /** @@ -151,7 +152,7 @@ set_next_write_location(hv_vmbus_ring_buffer_info *ring_info, uint32_t next_write_location) { - ring_info->ring_buffer->write_index = next_write_location; + ring_info->ring_buffer->br_windex = next_write_location; } /** @@ -160,7 +161,7 @@ static __inline uint32_t get_next_read_location(hv_vmbus_ring_buffer_info *ring_info) { - return ring_info->ring_buffer->read_index; + return ring_info->ring_buffer->br_rindex; } /** @@ -171,7 +172,7 @@ get_next_read_location_with_offset(hv_vmbus_ring_buffer_info *ring_info, uint32_t offset) { - uint32_t next = ring_info->ring_buffer->read_index; + uint32_t next = ring_info->ring_buffer->br_rindex; next += offset; next %= ring_info->ring_data_size; @@ -185,7 +186,7 @@ set_next_read_location(hv_vmbus_ring_buffer_info *ring_info, uint32_t next_read_location) { - ring_info->ring_buffer->read_index = next_read_location; + ring_info->ring_buffer->br_rindex = next_read_location; } /** @@ -194,7 +195,7 @@ static __inline void * get_ring_buffer(hv_vmbus_ring_buffer_info *ring_info) { - return ring_info->ring_buffer->buffer; + return ring_info->ring_buffer->br_data; } /** @@ -212,13 +213,13 @@ static __inline uint64_t get_ring_buffer_indices(hv_vmbus_ring_buffer_info *ring_info) { - return ((uint64_t)ring_info->ring_buffer->write_index) << 32; + return ((uint64_t)ring_info->ring_buffer->br_windex) << 32; } void hv_ring_buffer_read_begin(hv_vmbus_ring_buffer_info *ring_info) { - ring_info->ring_buffer->interrupt_mask = 1; + ring_info->ring_buffer->br_imask = 1; mb(); } @@ -227,7 +228,7 @@ { uint32_t read, write; - ring_info->ring_buffer->interrupt_mask = 0; + ring_info->ring_buffer->br_imask = 0; mb(); /* @@ -259,7 +260,7 @@ hv_vmbus_ring_buffer_info *rbi) { mb(); - if (rbi->ring_buffer->interrupt_mask) + if (rbi->ring_buffer->br_imask) return (FALSE); /* Read memory barrier */ @@ -268,7 +269,7 @@ * 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->read_index) + if (old_write_location == rbi->ring_buffer->br_rindex) return (TRUE); return (FALSE); @@ -284,10 +285,10 @@ memset(ring_info, 0, sizeof(hv_vmbus_ring_buffer_info)); ring_info->ring_buffer = buffer; - ring_info->ring_buffer->read_index = 0; - ring_info->ring_buffer->write_index = 0; + ring_info->ring_buffer->br_rindex = 0; + ring_info->ring_buffer->br_windex = 0; - ring_info->ring_data_size = buffer_len - sizeof(hv_vmbus_ring_buffer); + ring_info->ring_data_size = buffer_len - sizeof(struct vmbus_bufring); mtx_init(&ring_info->ring_lock, "vmbus ring buffer", NULL, MTX_SPIN); return (0); Index: head/sys/dev/hyperv/vmbus/vmbus_chanvar.h =================================================================== --- head/sys/dev/hyperv/vmbus/vmbus_chanvar.h +++ head/sys/dev/hyperv/vmbus/vmbus_chanvar.h @@ -41,31 +41,7 @@ #include typedef struct { - /* - * offset in bytes from the start of ring data below - */ - volatile uint32_t write_index; - /* - * offset in bytes from the start of ring data below - */ - volatile uint32_t read_index; - /* - * NOTE: The interrupt_mask field is used only for channels, but - * vmbus connection also uses this data structure - */ - volatile uint32_t interrupt_mask; - /* pad it to PAGE_SIZE so that data starts on a page */ - uint8_t reserved[4084]; - - /* - * WARNING: Ring data starts here - * !!! DO NOT place any fields below this !!! - */ - uint8_t buffer[0]; /* doubles as interrupt mask */ -} __packed hv_vmbus_ring_buffer; - -typedef struct { - hv_vmbus_ring_buffer* ring_buffer; + struct vmbus_bufring *ring_buffer; struct mtx ring_lock; uint32_t ring_data_size; /* ring_size */ } hv_vmbus_ring_buffer_info; Index: head/sys/dev/hyperv/vmbus/vmbus_reg.h =================================================================== --- head/sys/dev/hyperv/vmbus/vmbus_reg.h +++ head/sys/dev/hyperv/vmbus/vmbus_reg.h @@ -102,6 +102,37 @@ CTASSERT(sizeof(struct vmbus_mnf) == PAGE_SIZE); /* + * Buffer ring + */ +struct vmbus_bufring { + /* + * If br_windex == br_rindex, this bufring is empty; this + * means we can _not_ write data to the bufring, if the + * write is going to make br_windex same as br_rindex. + */ + volatile uint32_t br_windex; + volatile uint32_t br_rindex; + + /* + * Interrupt mask {0,1} + * + * For TX bufring, host set this to 1, when it is processing + * the TX bufring, so that we can safely skip the TX event + * notification to host. + * + * For RX bufring, once this is set to 1 by us, host will not + * further dispatch interrupts to us, even if there are data + * pending on the RX bufring. This effectively disables the + * interrupt of the channel to which this RX bufring is attached. + */ + volatile uint32_t br_imask; + + uint8_t br_rsvd[4084]; + uint8_t br_data[]; +} __packed; +CTASSERT(sizeof(struct vmbus_bufring) == PAGE_SIZE); + +/* * Channel */