aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/hyperv.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/linux/hyperv.h')
-rw-r--r--include/linux/hyperv.h170
1 files changed, 169 insertions, 1 deletions
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index aa0fadce9308..b10954a66939 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -126,6 +126,8 @@ struct hv_ring_buffer_info {
126 126
127 u32 ring_datasize; /* < ring_size */ 127 u32 ring_datasize; /* < ring_size */
128 u32 ring_data_startoffset; 128 u32 ring_data_startoffset;
129 u32 priv_write_index;
130 u32 priv_read_index;
129}; 131};
130 132
131/* 133/*
@@ -151,6 +153,33 @@ hv_get_ringbuffer_availbytes(struct hv_ring_buffer_info *rbi,
151 *read = dsize - *write; 153 *read = dsize - *write;
152} 154}
153 155
156static inline u32 hv_get_bytes_to_read(struct hv_ring_buffer_info *rbi)
157{
158 u32 read_loc, write_loc, dsize, read;
159
160 dsize = rbi->ring_datasize;
161 read_loc = rbi->ring_buffer->read_index;
162 write_loc = READ_ONCE(rbi->ring_buffer->write_index);
163
164 read = write_loc >= read_loc ? (write_loc - read_loc) :
165 (dsize - read_loc) + write_loc;
166
167 return read;
168}
169
170static inline u32 hv_get_bytes_to_write(struct hv_ring_buffer_info *rbi)
171{
172 u32 read_loc, write_loc, dsize, write;
173
174 dsize = rbi->ring_datasize;
175 read_loc = READ_ONCE(rbi->ring_buffer->read_index);
176 write_loc = rbi->ring_buffer->write_index;
177
178 write = write_loc >= read_loc ? dsize - (write_loc - read_loc) :
179 read_loc - write_loc;
180 return write;
181}
182
154/* 183/*
155 * VMBUS version is 32 bit entity broken up into 184 * VMBUS version is 32 bit entity broken up into
156 * two 16 bit quantities: major_number. minor_number. 185 * two 16 bit quantities: major_number. minor_number.
@@ -1091,7 +1120,7 @@ int vmbus_allocate_mmio(struct resource **new, struct hv_device *device_obj,
1091 resource_size_t min, resource_size_t max, 1120 resource_size_t min, resource_size_t max,
1092 resource_size_t size, resource_size_t align, 1121 resource_size_t size, resource_size_t align,
1093 bool fb_overlap_ok); 1122 bool fb_overlap_ok);
1094 1123void vmbus_free_mmio(resource_size_t start, resource_size_t size);
1095int vmbus_cpu_number_to_vp_number(int cpu_number); 1124int vmbus_cpu_number_to_vp_number(int cpu_number);
1096u64 hv_do_hypercall(u64 control, void *input, void *output); 1125u64 hv_do_hypercall(u64 control, void *input, void *output);
1097 1126
@@ -1338,4 +1367,143 @@ extern __u32 vmbus_proto_version;
1338 1367
1339int vmbus_send_tl_connect_request(const uuid_le *shv_guest_servie_id, 1368int vmbus_send_tl_connect_request(const uuid_le *shv_guest_servie_id,
1340 const uuid_le *shv_host_servie_id); 1369 const uuid_le *shv_host_servie_id);
1370void vmbus_set_event(struct vmbus_channel *channel);
1371
1372/* Get the start of the ring buffer. */
1373static inline void *
1374hv_get_ring_buffer(struct hv_ring_buffer_info *ring_info)
1375{
1376 return (void *)ring_info->ring_buffer->buffer;
1377}
1378
1379/*
1380 * To optimize the flow management on the send-side,
1381 * when the sender is blocked because of lack of
1382 * sufficient space in the ring buffer, potential the
1383 * consumer of the ring buffer can signal the producer.
1384 * This is controlled by the following parameters:
1385 *
1386 * 1. pending_send_sz: This is the size in bytes that the
1387 * producer is trying to send.
1388 * 2. The feature bit feat_pending_send_sz set to indicate if
1389 * the consumer of the ring will signal when the ring
1390 * state transitions from being full to a state where
1391 * there is room for the producer to send the pending packet.
1392 */
1393
1394static inline bool hv_need_to_signal_on_read(struct hv_ring_buffer_info *rbi)
1395{
1396 u32 cur_write_sz;
1397 u32 pending_sz;
1398
1399 /*
1400 * Issue a full memory barrier before making the signaling decision.
1401 * Here is the reason for having this barrier:
1402 * If the reading of the pend_sz (in this function)
1403 * were to be reordered and read before we commit the new read
1404 * index (in the calling function) we could
1405 * have a problem. If the host were to set the pending_sz after we
1406 * have sampled pending_sz and go to sleep before we commit the
1407 * read index, we could miss sending the interrupt. Issue a full
1408 * memory barrier to address this.
1409 */
1410 virt_mb();
1411
1412 pending_sz = READ_ONCE(rbi->ring_buffer->pending_send_sz);
1413 /* If the other end is not blocked on write don't bother. */
1414 if (pending_sz == 0)
1415 return false;
1416
1417 cur_write_sz = hv_get_bytes_to_write(rbi);
1418
1419 if (cur_write_sz >= pending_sz)
1420 return true;
1421
1422 return false;
1423}
1424
1425/*
1426 * An API to support in-place processing of incoming VMBUS packets.
1427 */
1428#define VMBUS_PKT_TRAILER 8
1429
1430static inline struct vmpacket_descriptor *
1431get_next_pkt_raw(struct vmbus_channel *channel)
1432{
1433 struct hv_ring_buffer_info *ring_info = &channel->inbound;
1434 u32 read_loc = ring_info->priv_read_index;
1435 void *ring_buffer = hv_get_ring_buffer(ring_info);
1436 struct vmpacket_descriptor *cur_desc;
1437 u32 packetlen;
1438 u32 dsize = ring_info->ring_datasize;
1439 u32 delta = read_loc - ring_info->ring_buffer->read_index;
1440 u32 bytes_avail_toread = (hv_get_bytes_to_read(ring_info) - delta);
1441
1442 if (bytes_avail_toread < sizeof(struct vmpacket_descriptor))
1443 return NULL;
1444
1445 if ((read_loc + sizeof(*cur_desc)) > dsize)
1446 return NULL;
1447
1448 cur_desc = ring_buffer + read_loc;
1449 packetlen = cur_desc->len8 << 3;
1450
1451 /*
1452 * If the packet under consideration is wrapping around,
1453 * return failure.
1454 */
1455 if ((read_loc + packetlen + VMBUS_PKT_TRAILER) > (dsize - 1))
1456 return NULL;
1457
1458 return cur_desc;
1459}
1460
1461/*
1462 * A helper function to step through packets "in-place"
1463 * This API is to be called after each successful call
1464 * get_next_pkt_raw().
1465 */
1466static inline void put_pkt_raw(struct vmbus_channel *channel,
1467 struct vmpacket_descriptor *desc)
1468{
1469 struct hv_ring_buffer_info *ring_info = &channel->inbound;
1470 u32 read_loc = ring_info->priv_read_index;
1471 u32 packetlen = desc->len8 << 3;
1472 u32 dsize = ring_info->ring_datasize;
1473
1474 if ((read_loc + packetlen + VMBUS_PKT_TRAILER) > dsize)
1475 BUG();
1476 /*
1477 * Include the packet trailer.
1478 */
1479 ring_info->priv_read_index += packetlen + VMBUS_PKT_TRAILER;
1480}
1481
1482/*
1483 * This call commits the read index and potentially signals the host.
1484 * Here is the pattern for using the "in-place" consumption APIs:
1485 *
1486 * while (get_next_pkt_raw() {
1487 * process the packet "in-place";
1488 * put_pkt_raw();
1489 * }
1490 * if (packets processed in place)
1491 * commit_rd_index();
1492 */
1493static inline void commit_rd_index(struct vmbus_channel *channel)
1494{
1495 struct hv_ring_buffer_info *ring_info = &channel->inbound;
1496 /*
1497 * Make sure all reads are done before we update the read index since
1498 * the writer may start writing to the read area once the read index
1499 * is updated.
1500 */
1501 virt_rmb();
1502 ring_info->ring_buffer->read_index = ring_info->priv_read_index;
1503
1504 if (hv_need_to_signal_on_read(ring_info))
1505 vmbus_set_event(channel);
1506}
1507
1508
1341#endif /* _HYPERV_H */ 1509#endif /* _HYPERV_H */