aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVitaly Kuznetsov <vkuznets@redhat.com>2016-06-17 13:45:30 -0400
committerBjorn Helgaas <bhelgaas@google.com>2016-06-17 13:45:30 -0400
commit837d741ea2e6bb23da9cad1667776fc6f0cb67dd (patch)
tree521c6f78c8a7fa98cfb81377d02452d4bcdab1e9
parent60fcdac8136b4275da42d6edf9ddb10439350289 (diff)
PCI: hv: Handle all pending messages in hv_pci_onchannelcallback()
When we have an interrupt from the host we have a bit set in event page indicating there are messages for the particular channel. We need to read them all as we won't get signaled for what was on the queue before we cleared the bit in vmbus_on_event(). This applies to all Hyper-V drivers and the pass-through driver should do the same. I did not meet any bugs; the issue was found by code inspection. We don't have many events going through hv_pci_onchannelcallback(), which explains why nobody reported the issue before. While on it, fix handling non-zero vmbus_recvpacket_raw() return values by dropping out. If the return value is not zero, it is wrong to inspect buffer or bytes_recvd as these may contain invalid data. Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Acked-by: Jake Oshins <jakeo@microsoft.com>
-rw-r--r--drivers/pci/host/pci-hyperv.c7
1 files changed, 5 insertions, 2 deletions
diff --git a/drivers/pci/host/pci-hyperv.c b/drivers/pci/host/pci-hyperv.c
index a68ec4996ed9..7de341d7caaa 100644
--- a/drivers/pci/host/pci-hyperv.c
+++ b/drivers/pci/host/pci-hyperv.c
@@ -1657,12 +1657,16 @@ static void hv_pci_onchannelcallback(void *context)
1657 continue; 1657 continue;
1658 } 1658 }
1659 1659
1660 /* Zero length indicates there are no more packets. */
1661 if (ret || !bytes_recvd)
1662 break;
1663
1660 /* 1664 /*
1661 * All incoming packets must be at least as large as a 1665 * All incoming packets must be at least as large as a
1662 * response. 1666 * response.
1663 */ 1667 */
1664 if (bytes_recvd <= sizeof(struct pci_response)) 1668 if (bytes_recvd <= sizeof(struct pci_response))
1665 break; 1669 continue;
1666 desc = (struct vmpacket_descriptor *)buffer; 1670 desc = (struct vmpacket_descriptor *)buffer;
1667 1671
1668 switch (desc->type) { 1672 switch (desc->type) {
@@ -1724,7 +1728,6 @@ static void hv_pci_onchannelcallback(void *context)
1724 desc->type, req_id, bytes_recvd); 1728 desc->type, req_id, bytes_recvd);
1725 break; 1729 break;
1726 } 1730 }
1727 break;
1728 } 1731 }
1729 1732
1730 kfree(buffer); 1733 kfree(buffer);