Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

K. Y. Srinivasan and committed by
Greg Kroah-Hartman
3372592a 1f6ee4e7

+14 -20
+2 -9
drivers/hv/channel.c
··· 879 879 u32 bufferlen, u32 *buffer_actual_len, u64 *requestid, 880 880 bool raw) 881 881 { 882 - int ret; 883 - bool signal = false; 882 + return hv_ringbuffer_read(channel, buffer, bufferlen, 883 + buffer_actual_len, requestid, raw); 884 884 885 - ret = hv_ringbuffer_read(&channel->inbound, buffer, bufferlen, 886 - buffer_actual_len, requestid, &signal, raw); 887 - 888 - if (signal) 889 - vmbus_setevent(channel); 890 - 891 - return ret; 892 885 } 893 886 894 887 int vmbus_recvpacket(struct vmbus_channel *channel, void *buffer,
+2 -2
drivers/hv/hyperv_vmbus.h
··· 532 532 u32 kv_count, bool lock, 533 533 bool kick_q); 534 534 535 - int hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info, 535 + int hv_ringbuffer_read(struct vmbus_channel *channel, 536 536 void *buffer, u32 buflen, u32 *buffer_actual_len, 537 - u64 *requestid, bool *signal, bool raw); 537 + u64 *requestid, bool raw); 538 538 539 539 void hv_ringbuffer_get_debuginfo(struct hv_ring_buffer_info *ring_info, 540 540 struct hv_ring_buffer_debug_info *debug_info);
+4 -3
drivers/hv/ring_buffer.c
··· 353 353 return 0; 354 354 } 355 355 356 - int hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info, 356 + int hv_ringbuffer_read(struct vmbus_channel *channel, 357 357 void *buffer, u32 buflen, u32 *buffer_actual_len, 358 - u64 *requestid, bool *signal, bool raw) 358 + u64 *requestid, bool raw) 359 359 { 360 360 u32 bytes_avail_toread; 361 361 u32 next_read_location = 0; ··· 364 364 u32 offset; 365 365 u32 packetlen; 366 366 int ret = 0; 367 + struct hv_ring_buffer_info *inring_info = &channel->inbound; 367 368 368 369 if (buflen <= 0) 369 370 return -EINVAL; ··· 422 421 /* Update the read index */ 423 422 hv_set_next_read_location(inring_info, next_read_location); 424 423 425 - *signal = hv_need_to_signal_on_read(inring_info); 424 + hv_signal_on_read(channel); 426 425 427 426 return ret; 428 427 }
+6 -6
include/linux/hyperv.h
··· 1487 1487 * there is room for the producer to send the pending packet. 1488 1488 */ 1489 1489 1490 - static inline bool hv_need_to_signal_on_read(struct hv_ring_buffer_info *rbi) 1490 + static inline void hv_signal_on_read(struct vmbus_channel *channel) 1491 1491 { 1492 1492 u32 cur_write_sz; 1493 1493 u32 pending_sz; 1494 + struct hv_ring_buffer_info *rbi = &channel->inbound; 1494 1495 1495 1496 /* 1496 1497 * Issue a full memory barrier before making the signaling decision. ··· 1509 1508 pending_sz = READ_ONCE(rbi->ring_buffer->pending_send_sz); 1510 1509 /* If the other end is not blocked on write don't bother. */ 1511 1510 if (pending_sz == 0) 1512 - return false; 1511 + return; 1513 1512 1514 1513 cur_write_sz = hv_get_bytes_to_write(rbi); 1515 1514 1516 1515 if (cur_write_sz >= pending_sz) 1517 - return true; 1516 + vmbus_setevent(channel); 1518 1517 1519 - return false; 1518 + return; 1520 1519 } 1521 1520 1522 1521 /* ··· 1588 1587 virt_rmb(); 1589 1588 ring_info->ring_buffer->read_index = ring_info->priv_read_index; 1590 1589 1591 - if (hv_need_to_signal_on_read(ring_info)) 1592 - vmbus_set_event(channel); 1590 + hv_signal_on_read(channel); 1593 1591 } 1594 1592 1595 1593