diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-21 00:20:31 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-21 00:20:31 -0400 |
commit | 5af2344013454640e0133bb62e8cf2e30190a472 (patch) | |
tree | 93495d1eb88d7498dac4747a3d28081c09a69a55 /include/linux/hyperv.h | |
parent | 19e36ad292ab24980db64a5ff17973d3118a8fb9 (diff) | |
parent | 725d0123dfff3d7b666cf57f5d29c50addfc99d3 (diff) |
Merge tag 'char-misc-4.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc
Pull char / misc driver updates from Greg KH:
"Here's the big char and misc driver update for 4.7-rc1.
Lots of different tiny driver subsystems have updates here with new
drivers and functionality. Details in the shortlog.
All have been in linux-next with no reported issues for a while"
* tag 'char-misc-4.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (125 commits)
mcb: Delete num_cells variable which is not required
mcb: Fixed bar number assignment for the gdd
mcb: Replace ioremap and request_region with the devm version
mcb: Implement bus->dev.release callback
mcb: export bus information via sysfs
mcb: Correctly initialize the bus's device
mei: bus: call mei_cl_read_start under device lock
coresight: etb10: adjust read pointer only when needed
coresight: configuring ETF in FIFO mode when acting as link
coresight: tmc: implementing TMC-ETF AUX space API
coresight: moving struct cs_buffers to header file
coresight: tmc: keep track of memory width
coresight: tmc: make sysFS and Perf mode mutually exclusive
coresight: tmc: dump system memory content only when needed
coresight: tmc: adding mode of operation for link/sinks
coresight: tmc: getting rid of multiple read access
coresight: tmc: allocating memory when needed
coresight: tmc: making prepare/unprepare functions generic
coresight: tmc: splitting driver in ETB/ETF and ETR components
coresight: tmc: cleaning up header file
...
Diffstat (limited to 'include/linux/hyperv.h')
-rw-r--r-- | include/linux/hyperv.h | 170 |
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 | ||
156 | static 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 | |||
170 | static 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 | 1123 | void vmbus_free_mmio(resource_size_t start, resource_size_t size); | |
1095 | int vmbus_cpu_number_to_vp_number(int cpu_number); | 1124 | int vmbus_cpu_number_to_vp_number(int cpu_number); |
1096 | u64 hv_do_hypercall(u64 control, void *input, void *output); | 1125 | u64 hv_do_hypercall(u64 control, void *input, void *output); |
1097 | 1126 | ||
@@ -1338,4 +1367,143 @@ extern __u32 vmbus_proto_version; | |||
1338 | 1367 | ||
1339 | int vmbus_send_tl_connect_request(const uuid_le *shv_guest_servie_id, | 1368 | int 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); |
1370 | void vmbus_set_event(struct vmbus_channel *channel); | ||
1371 | |||
1372 | /* Get the start of the ring buffer. */ | ||
1373 | static inline void * | ||
1374 | hv_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 | |||
1394 | static 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 | |||
1430 | static inline struct vmpacket_descriptor * | ||
1431 | get_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 | */ | ||
1466 | static 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 | */ | ||
1493 | static 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 */ |