aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorK. Y. Srinivasan <kys@microsoft.com>2016-11-06 16:14:18 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2016-11-07 04:01:18 -0500
commit3372592a140db69fd63837e81f048ab4abf8111e (patch)
treee98a51a7fcedba1a35564466daf3a59bc0af80b0
parent1f6ee4e7d83586c8b10bd4f2f4346353d04ce884 (diff)
Drivers: hv: vmbus: On the read path cleanup the logic to interrupt the host
Signal the host when we determine the host is to be signaled - on th read path. The currrent code determines the need to signal in the ringbuffer code and actually issues the signal elsewhere. This can result in the host viewing this interrupt as spurious since the host may also poll the channel. Make the necessary adjustments. Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/hv/channel.c11
-rw-r--r--drivers/hv/hyperv_vmbus.h4
-rw-r--r--drivers/hv/ring_buffer.c7
-rw-r--r--include/linux/hyperv.h12
4 files changed, 14 insertions, 20 deletions
diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
index 8a8148f7b842..5fb4c6d9209b 100644
--- a/drivers/hv/channel.c
+++ b/drivers/hv/channel.c
@@ -879,16 +879,9 @@ __vmbus_recvpacket(struct vmbus_channel *channel, void *buffer,
879 u32 bufferlen, u32 *buffer_actual_len, u64 *requestid, 879 u32 bufferlen, u32 *buffer_actual_len, u64 *requestid,
880 bool raw) 880 bool raw)
881{ 881{
882 int ret; 882 return hv_ringbuffer_read(channel, buffer, bufferlen,
883 bool signal = false; 883 buffer_actual_len, requestid, raw);
884
885 ret = hv_ringbuffer_read(&channel->inbound, buffer, bufferlen,
886 buffer_actual_len, requestid, &signal, raw);
887 884
888 if (signal)
889 vmbus_setevent(channel);
890
891 return ret;
892} 885}
893 886
894int vmbus_recvpacket(struct vmbus_channel *channel, void *buffer, 887int vmbus_recvpacket(struct vmbus_channel *channel, void *buffer,
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h
index 2d42ebe2af6c..0675b395ce5c 100644
--- a/drivers/hv/hyperv_vmbus.h
+++ b/drivers/hv/hyperv_vmbus.h
@@ -532,9 +532,9 @@ int hv_ringbuffer_write(struct vmbus_channel *channel,
532 u32 kv_count, bool lock, 532 u32 kv_count, bool lock,
533 bool kick_q); 533 bool kick_q);
534 534
535int hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info, 535int hv_ringbuffer_read(struct vmbus_channel *channel,
536 void *buffer, u32 buflen, u32 *buffer_actual_len, 536 void *buffer, u32 buflen, u32 *buffer_actual_len,
537 u64 *requestid, bool *signal, bool raw); 537 u64 *requestid, bool raw);
538 538
539void hv_ringbuffer_get_debuginfo(struct hv_ring_buffer_info *ring_info, 539void hv_ringbuffer_get_debuginfo(struct hv_ring_buffer_info *ring_info,
540 struct hv_ring_buffer_debug_info *debug_info); 540 struct hv_ring_buffer_debug_info *debug_info);
diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c
index 4af71306d0ff..cd49cb17eb7f 100644
--- a/drivers/hv/ring_buffer.c
+++ b/drivers/hv/ring_buffer.c
@@ -353,9 +353,9 @@ int hv_ringbuffer_write(struct vmbus_channel *channel,
353 return 0; 353 return 0;
354} 354}
355 355
356int hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info, 356int hv_ringbuffer_read(struct vmbus_channel *channel,
357 void *buffer, u32 buflen, u32 *buffer_actual_len, 357 void *buffer, u32 buflen, u32 *buffer_actual_len,
358 u64 *requestid, bool *signal, bool raw) 358 u64 *requestid, bool raw)
359{ 359{
360 u32 bytes_avail_toread; 360 u32 bytes_avail_toread;
361 u32 next_read_location = 0; 361 u32 next_read_location = 0;
@@ -364,6 +364,7 @@ int hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info,
364 u32 offset; 364 u32 offset;
365 u32 packetlen; 365 u32 packetlen;
366 int ret = 0; 366 int ret = 0;
367 struct hv_ring_buffer_info *inring_info = &channel->inbound;
367 368
368 if (buflen <= 0) 369 if (buflen <= 0)
369 return -EINVAL; 370 return -EINVAL;
@@ -421,7 +422,7 @@ int hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info,
421 /* Update the read index */ 422 /* Update the read index */
422 hv_set_next_read_location(inring_info, next_read_location); 423 hv_set_next_read_location(inring_info, next_read_location);
423 424
424 *signal = hv_need_to_signal_on_read(inring_info); 425 hv_signal_on_read(channel);
425 426
426 return ret; 427 return ret;
427} 428}
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index 8cf78ed96747..fdb0a87323f3 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -1487,10 +1487,11 @@ hv_get_ring_buffer(struct hv_ring_buffer_info *ring_info)
1487 * there is room for the producer to send the pending packet. 1487 * there is room for the producer to send the pending packet.
1488 */ 1488 */
1489 1489
1490static inline bool hv_need_to_signal_on_read(struct hv_ring_buffer_info *rbi) 1490static inline void hv_signal_on_read(struct vmbus_channel *channel)
1491{ 1491{
1492 u32 cur_write_sz; 1492 u32 cur_write_sz;
1493 u32 pending_sz; 1493 u32 pending_sz;
1494 struct hv_ring_buffer_info *rbi = &channel->inbound;
1494 1495
1495 /* 1496 /*
1496 * Issue a full memory barrier before making the signaling decision. 1497 * Issue a full memory barrier before making the signaling decision.
@@ -1508,14 +1509,14 @@ static inline bool hv_need_to_signal_on_read(struct hv_ring_buffer_info *rbi)
1508 pending_sz = READ_ONCE(rbi->ring_buffer->pending_send_sz); 1509 pending_sz = READ_ONCE(rbi->ring_buffer->pending_send_sz);
1509 /* If the other end is not blocked on write don't bother. */ 1510 /* If the other end is not blocked on write don't bother. */
1510 if (pending_sz == 0) 1511 if (pending_sz == 0)
1511 return false; 1512 return;
1512 1513
1513 cur_write_sz = hv_get_bytes_to_write(rbi); 1514 cur_write_sz = hv_get_bytes_to_write(rbi);
1514 1515
1515 if (cur_write_sz >= pending_sz) 1516 if (cur_write_sz >= pending_sz)
1516 return true; 1517 vmbus_setevent(channel);
1517 1518
1518 return false; 1519 return;
1519} 1520}
1520 1521
1521/* 1522/*
@@ -1587,8 +1588,7 @@ static inline void commit_rd_index(struct vmbus_channel *channel)
1587 virt_rmb(); 1588 virt_rmb();
1588 ring_info->ring_buffer->read_index = ring_info->priv_read_index; 1589 ring_info->ring_buffer->read_index = ring_info->priv_read_index;
1589 1590
1590 if (hv_need_to_signal_on_read(ring_info)) 1591 hv_signal_on_read(channel);
1591 vmbus_set_event(channel);
1592} 1592}
1593 1593
1594 1594