Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 354979
b: refs/heads/master
c: 98fa8cf
h: refs/heads/master
i:
  354977: 52fd236
  354975: 7095a53
v: v3
  • Loading branch information
K. Y. Srinivasan authored and Greg Kroah-Hartman committed Jan 17, 2013
1 parent 764e29e commit 8295857
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 11 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: f878f3d59ed26f489add852ed6d5c8e5f3bbb1aa
refs/heads/master: 98fa8cf4bcc79cb14de8fd815bbcd00dcbd7b20e
15 changes: 9 additions & 6 deletions trunk/drivers/hv/channel.c
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,7 @@ int vmbus_sendpacket(struct vmbus_channel *channel, const void *buffer,
struct scatterlist bufferlist[3];
u64 aligned_data = 0;
int ret;
bool signal = false;


/* Setup the descriptor */
Expand All @@ -580,9 +581,9 @@ int vmbus_sendpacket(struct vmbus_channel *channel, const void *buffer,
sg_set_buf(&bufferlist[2], &aligned_data,
packetlen_aligned - packetlen);

ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3);
ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3, &signal);

if (ret == 0 && !hv_get_ringbuffer_interrupt_mask(&channel->outbound))
if (ret == 0 && signal)
vmbus_setevent(channel);

return ret;
Expand All @@ -606,6 +607,7 @@ int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel,
u32 packetlen_aligned;
struct scatterlist bufferlist[3];
u64 aligned_data = 0;
bool signal = false;

if (pagecount > MAX_PAGE_BUFFER_COUNT)
return -EINVAL;
Expand Down Expand Up @@ -641,9 +643,9 @@ int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel,
sg_set_buf(&bufferlist[2], &aligned_data,
packetlen_aligned - packetlen);

ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3);
ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3, &signal);

if (ret == 0 && !hv_get_ringbuffer_interrupt_mask(&channel->outbound))
if (ret == 0 && signal)
vmbus_setevent(channel);

return ret;
Expand All @@ -665,6 +667,7 @@ int vmbus_sendpacket_multipagebuffer(struct vmbus_channel *channel,
u32 packetlen_aligned;
struct scatterlist bufferlist[3];
u64 aligned_data = 0;
bool signal = false;
u32 pfncount = NUM_PAGES_SPANNED(multi_pagebuffer->offset,
multi_pagebuffer->len);

Expand Down Expand Up @@ -703,9 +706,9 @@ int vmbus_sendpacket_multipagebuffer(struct vmbus_channel *channel,
sg_set_buf(&bufferlist[2], &aligned_data,
packetlen_aligned - packetlen);

ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3);
ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3, &signal);

if (ret == 0 && !hv_get_ringbuffer_interrupt_mask(&channel->outbound))
if (ret == 0 && signal)
vmbus_setevent(channel);

return ret;
Expand Down
2 changes: 1 addition & 1 deletion trunk/drivers/hv/hyperv_vmbus.h
Original file line number Diff line number Diff line change
Expand Up @@ -555,7 +555,7 @@ void hv_ringbuffer_cleanup(struct hv_ring_buffer_info *ring_info);

int hv_ringbuffer_write(struct hv_ring_buffer_info *ring_info,
struct scatterlist *sglist,
u32 sgcount);
u32 sgcount, bool *signal);

int hv_ringbuffer_peek(struct hv_ring_buffer_info *ring_info, void *buffer,
u32 buflen);
Expand Down
42 changes: 39 additions & 3 deletions trunk/drivers/hv/ring_buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,37 @@ u32 hv_end_read(struct hv_ring_buffer_info *rbi)
return read;
}

/*
* 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.
*
* 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.
*/

static bool hv_need_to_signal(u32 old_write, struct hv_ring_buffer_info *rbi)
{
if (rbi->ring_buffer->interrupt_mask)
return false;

/*
* This is the only case we need to signal when the
* ring transitions from being empty to non-empty.
*/
if (old_write == rbi->ring_buffer->read_index)
return true;

return false;
}


/*
* hv_get_next_write_location()
Expand Down Expand Up @@ -322,7 +353,7 @@ void hv_ringbuffer_cleanup(struct hv_ring_buffer_info *ring_info)
*
*/
int hv_ringbuffer_write(struct hv_ring_buffer_info *outring_info,
struct scatterlist *sglist, u32 sgcount)
struct scatterlist *sglist, u32 sgcount, bool *signal)
{
int i = 0;
u32 bytes_avail_towrite;
Expand All @@ -331,6 +362,7 @@ int hv_ringbuffer_write(struct hv_ring_buffer_info *outring_info,

struct scatterlist *sg;
u32 next_write_location;
u32 old_write;
u64 prev_indices = 0;
unsigned long flags;

Expand Down Expand Up @@ -359,6 +391,8 @@ int hv_ringbuffer_write(struct hv_ring_buffer_info *outring_info,
/* Write to the ring buffer */
next_write_location = hv_get_next_write_location(outring_info);

old_write = next_write_location;

for_each_sg(sglist, sg, sgcount, i)
{
next_write_location = hv_copyto_ringbuffer(outring_info,
Expand All @@ -375,14 +409,16 @@ int hv_ringbuffer_write(struct hv_ring_buffer_info *outring_info,
&prev_indices,
sizeof(u64));

/* Make sure we flush all writes before updating the writeIndex */
smp_wmb();
/* Issue a full memory barrier before updating the write index */
smp_mb();

/* Now, update the write location */
hv_set_next_write_location(outring_info, next_write_location);


spin_unlock_irqrestore(&outring_info->ring_lock, flags);

*signal = hv_need_to_signal(old_write, outring_info);
return 0;
}

Expand Down

0 comments on commit 8295857

Please sign in to comment.