| @@ -103,15 +103,29 @@ static bool hv_need_to_signal(u32 old_write, struct hv_ring_buffer_info *rbi) · 102 unmodified lines |
| 103 | 103 | * there is room for the producer to send the pending packet. |
| 104 | 104 | */ |
| 105 | 105 | |
| 106 | | −static bool hv_need_to_signal_on_read(u32 prev_write_sz, |
| 107 | | − struct hv_ring_buffer_info *rbi) |
| 106 | +static bool hv_need_to_signal_on_read(struct hv_ring_buffer_info *rbi) |
| 108 | 107 | { |
| 109 | 108 | u32 cur_write_sz; |
| 110 | 109 | u32 r_size; |
| 111 | | − u32 write_loc = rbi->ring_buffer->write_index; |
| 110 | + u32 write_loc; |
| 112 | 111 | u32 read_loc = rbi->ring_buffer->read_index; |
| 113 | | − u32 pending_sz = rbi->ring_buffer->pending_send_sz; |
| 112 | + u32 pending_sz; |
| 114 | 113 | |
| 114 | + /* |
| 115 | + * Issue a full memory barrier before making the signaling decision. |
| 116 | + * Here is the reason for having this barrier: |
| 117 | + * If the reading of the pend_sz (in this function) |
| 118 | + * were to be reordered and read before we commit the new read |
| 119 | + * index (in the calling function) we could |
| 120 | + * have a problem. If the host were to set the pending_sz after we |
| 121 | + * have sampled pending_sz and go to sleep before we commit the |
| 122 | + * read index, we could miss sending the interrupt. Issue a full |
| 123 | + * memory barrier to address this. |
| 124 | + */ |
| 125 | + mb(); |
| 126 | + |
| 127 | + pending_sz = rbi->ring_buffer->pending_send_sz; |
| 128 | + write_loc = rbi->ring_buffer->write_index; |
| 115 | 129 | /* If the other end is not blocked on write don't bother. */ |
| 116 | 130 | if (pending_sz == 0) |
| 117 | 131 | return false; |
| @@ -120,7 +134,7 @@ static bool hv_need_to_signal_on_read(u32 prev_write_sz, · 2 unmodified lines |
| 120 | 134 | cur_write_sz = write_loc >= read_loc ? r_size - (write_loc - read_loc) : |
| 121 | 135 | read_loc - write_loc; |
| 122 | 136 | |
| 123 | | − if ((prev_write_sz < pending_sz) && (cur_write_sz >= pending_sz)) |
| 137 | + if (cur_write_sz >= pending_sz) |
| 124 | 138 | return true; |
| 125 | 139 | |
| 126 | 140 | return false; |
| @@ -455,7 +469,7 @@ int hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info, · 328 unmodified lines |
| 455 | 469 | /* Update the read index */ |
| 456 | 470 | hv_set_next_read_location(inring_info, next_read_location); |
| 457 | 471 | |
| 458 | | − *signal = hv_need_to_signal_on_read(bytes_avail_towrite, inring_info); |
| 472 | + *signal = hv_need_to_signal_on_read(inring_info); |
| 459 | 473 | |
| 460 | 474 | return ret; |
| 461 | 475 | } |