diff options
Diffstat (limited to 'include/linux/hyperv.h')
| -rw-r--r-- | include/linux/hyperv.h | 53 |
1 files changed, 25 insertions, 28 deletions
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index cd184bdca58f..42fe43fb0c80 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h | |||
| @@ -696,7 +696,7 @@ enum vmbus_device_type { | |||
| 696 | HV_FCOPY, | 696 | HV_FCOPY, |
| 697 | HV_BACKUP, | 697 | HV_BACKUP, |
| 698 | HV_DM, | 698 | HV_DM, |
| 699 | HV_UNKOWN, | 699 | HV_UNKNOWN, |
| 700 | }; | 700 | }; |
| 701 | 701 | ||
| 702 | struct vmbus_device { | 702 | struct vmbus_device { |
| @@ -1119,6 +1119,12 @@ struct hv_driver { | |||
| 1119 | 1119 | ||
| 1120 | struct device_driver driver; | 1120 | struct device_driver driver; |
| 1121 | 1121 | ||
| 1122 | /* dynamic device GUID's */ | ||
| 1123 | struct { | ||
| 1124 | spinlock_t lock; | ||
| 1125 | struct list_head list; | ||
| 1126 | } dynids; | ||
| 1127 | |||
| 1122 | int (*probe)(struct hv_device *, const struct hv_vmbus_device_id *); | 1128 | int (*probe)(struct hv_device *, const struct hv_vmbus_device_id *); |
| 1123 | int (*remove)(struct hv_device *); | 1129 | int (*remove)(struct hv_device *); |
| 1124 | void (*shutdown)(struct hv_device *); | 1130 | void (*shutdown)(struct hv_device *); |
| @@ -1447,6 +1453,7 @@ void hv_event_tasklet_enable(struct vmbus_channel *channel); | |||
| 1447 | 1453 | ||
| 1448 | void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid); | 1454 | void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid); |
| 1449 | 1455 | ||
| 1456 | void vmbus_setevent(struct vmbus_channel *channel); | ||
| 1450 | /* | 1457 | /* |
| 1451 | * Negotiated version with the Host. | 1458 | * Negotiated version with the Host. |
| 1452 | */ | 1459 | */ |
| @@ -1479,10 +1486,11 @@ hv_get_ring_buffer(struct hv_ring_buffer_info *ring_info) | |||
| 1479 | * there is room for the producer to send the pending packet. | 1486 | * there is room for the producer to send the pending packet. |
| 1480 | */ | 1487 | */ |
| 1481 | 1488 | ||
| 1482 | static inline bool hv_need_to_signal_on_read(struct hv_ring_buffer_info *rbi) | 1489 | static inline void hv_signal_on_read(struct vmbus_channel *channel) |
| 1483 | { | 1490 | { |
| 1484 | u32 cur_write_sz; | 1491 | u32 cur_write_sz; |
| 1485 | u32 pending_sz; | 1492 | u32 pending_sz; |
| 1493 | struct hv_ring_buffer_info *rbi = &channel->inbound; | ||
| 1486 | 1494 | ||
| 1487 | /* | 1495 | /* |
| 1488 | * Issue a full memory barrier before making the signaling decision. | 1496 | * Issue a full memory barrier before making the signaling decision. |
| @@ -1500,14 +1508,14 @@ static inline bool hv_need_to_signal_on_read(struct hv_ring_buffer_info *rbi) | |||
| 1500 | pending_sz = READ_ONCE(rbi->ring_buffer->pending_send_sz); | 1508 | pending_sz = READ_ONCE(rbi->ring_buffer->pending_send_sz); |
| 1501 | /* If the other end is not blocked on write don't bother. */ | 1509 | /* If the other end is not blocked on write don't bother. */ |
| 1502 | if (pending_sz == 0) | 1510 | if (pending_sz == 0) |
| 1503 | return false; | 1511 | return; |
| 1504 | 1512 | ||
| 1505 | cur_write_sz = hv_get_bytes_to_write(rbi); | 1513 | cur_write_sz = hv_get_bytes_to_write(rbi); |
| 1506 | 1514 | ||
| 1507 | if (cur_write_sz >= pending_sz) | 1515 | if (cur_write_sz >= pending_sz) |
| 1508 | return true; | 1516 | vmbus_setevent(channel); |
| 1509 | 1517 | ||
| 1510 | return false; | 1518 | return; |
| 1511 | } | 1519 | } |
| 1512 | 1520 | ||
| 1513 | /* | 1521 | /* |
| @@ -1519,31 +1527,23 @@ static inline struct vmpacket_descriptor * | |||
| 1519 | get_next_pkt_raw(struct vmbus_channel *channel) | 1527 | get_next_pkt_raw(struct vmbus_channel *channel) |
| 1520 | { | 1528 | { |
| 1521 | struct hv_ring_buffer_info *ring_info = &channel->inbound; | 1529 | struct hv_ring_buffer_info *ring_info = &channel->inbound; |
| 1522 | u32 read_loc = ring_info->priv_read_index; | 1530 | u32 priv_read_loc = ring_info->priv_read_index; |
| 1523 | void *ring_buffer = hv_get_ring_buffer(ring_info); | 1531 | void *ring_buffer = hv_get_ring_buffer(ring_info); |
| 1524 | struct vmpacket_descriptor *cur_desc; | ||
| 1525 | u32 packetlen; | ||
| 1526 | u32 dsize = ring_info->ring_datasize; | 1532 | u32 dsize = ring_info->ring_datasize; |
| 1527 | u32 delta = read_loc - ring_info->ring_buffer->read_index; | 1533 | /* |
| 1534 | * delta is the difference between what is available to read and | ||
| 1535 | * what was already consumed in place. We commit read index after | ||
| 1536 | * the whole batch is processed. | ||
| 1537 | */ | ||
| 1538 | u32 delta = priv_read_loc >= ring_info->ring_buffer->read_index ? | ||
| 1539 | priv_read_loc - ring_info->ring_buffer->read_index : | ||
| 1540 | (dsize - ring_info->ring_buffer->read_index) + priv_read_loc; | ||
| 1528 | u32 bytes_avail_toread = (hv_get_bytes_to_read(ring_info) - delta); | 1541 | u32 bytes_avail_toread = (hv_get_bytes_to_read(ring_info) - delta); |
| 1529 | 1542 | ||
| 1530 | if (bytes_avail_toread < sizeof(struct vmpacket_descriptor)) | 1543 | if (bytes_avail_toread < sizeof(struct vmpacket_descriptor)) |
| 1531 | return NULL; | 1544 | return NULL; |
| 1532 | 1545 | ||
| 1533 | if ((read_loc + sizeof(*cur_desc)) > dsize) | 1546 | return ring_buffer + priv_read_loc; |
| 1534 | return NULL; | ||
| 1535 | |||
| 1536 | cur_desc = ring_buffer + read_loc; | ||
| 1537 | packetlen = cur_desc->len8 << 3; | ||
| 1538 | |||
| 1539 | /* | ||
| 1540 | * If the packet under consideration is wrapping around, | ||
| 1541 | * return failure. | ||
| 1542 | */ | ||
| 1543 | if ((read_loc + packetlen + VMBUS_PKT_TRAILER) > (dsize - 1)) | ||
| 1544 | return NULL; | ||
| 1545 | |||
| 1546 | return cur_desc; | ||
| 1547 | } | 1547 | } |
| 1548 | 1548 | ||
| 1549 | /* | 1549 | /* |
| @@ -1555,16 +1555,14 @@ static inline void put_pkt_raw(struct vmbus_channel *channel, | |||
| 1555 | struct vmpacket_descriptor *desc) | 1555 | struct vmpacket_descriptor *desc) |
| 1556 | { | 1556 | { |
| 1557 | struct hv_ring_buffer_info *ring_info = &channel->inbound; | 1557 | struct hv_ring_buffer_info *ring_info = &channel->inbound; |
| 1558 | u32 read_loc = ring_info->priv_read_index; | ||
| 1559 | u32 packetlen = desc->len8 << 3; | 1558 | u32 packetlen = desc->len8 << 3; |
| 1560 | u32 dsize = ring_info->ring_datasize; | 1559 | u32 dsize = ring_info->ring_datasize; |
| 1561 | 1560 | ||
| 1562 | if ((read_loc + packetlen + VMBUS_PKT_TRAILER) > dsize) | ||
| 1563 | BUG(); | ||
| 1564 | /* | 1561 | /* |
| 1565 | * Include the packet trailer. | 1562 | * Include the packet trailer. |
| 1566 | */ | 1563 | */ |
| 1567 | ring_info->priv_read_index += packetlen + VMBUS_PKT_TRAILER; | 1564 | ring_info->priv_read_index += packetlen + VMBUS_PKT_TRAILER; |
| 1565 | ring_info->priv_read_index %= dsize; | ||
| 1568 | } | 1566 | } |
| 1569 | 1567 | ||
| 1570 | /* | 1568 | /* |
| @@ -1589,8 +1587,7 @@ static inline void commit_rd_index(struct vmbus_channel *channel) | |||
| 1589 | virt_rmb(); | 1587 | virt_rmb(); |
| 1590 | ring_info->ring_buffer->read_index = ring_info->priv_read_index; | 1588 | ring_info->ring_buffer->read_index = ring_info->priv_read_index; |
| 1591 | 1589 | ||
| 1592 | if (hv_need_to_signal_on_read(ring_info)) | 1590 | hv_signal_on_read(channel); |
| 1593 | vmbus_set_event(channel); | ||
| 1594 | } | 1591 | } |
| 1595 | 1592 | ||
| 1596 | 1593 | ||
