Skip to content

Commit b4927bd

Browse files
andrea-parriliuw
authored andcommitted
PCI: hv: Fix synchronization between channel callback and hv_pci_bus_exit()
[ Similarly to commit a765ed4 ("PCI: hv: Fix synchronization between channel callback and hv_compose_msi_msg()"): ] The (on-stack) teardown packet becomes invalid once the completion timeout in hv_pci_bus_exit() has expired and hv_pci_bus_exit() has returned. Prevent the channel callback from accessing the invalid packet by removing the ID associated to such packet from the VMbus requestor in hv_pci_bus_exit(). Signed-off-by: Andrea Parri (Microsoft) <parri.andrea@gmail.com> Reviewed-by: Michael Kelley <mikelley@microsoft.com> Acked-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> Link: https://lore.kernel.org/r/20220511223207.3386-3-parri.andrea@gmail.com Signed-off-by: Wei Liu <wei.liu@kernel.org>
1 parent 9937fa6 commit b4927bd

1 file changed

Lines changed: 19 additions & 7 deletions

File tree

drivers/pci/controller/pci-hyperv.c

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3664,20 +3664,22 @@ static int hv_pci_probe(struct hv_device *hdev,
36643664
static int hv_pci_bus_exit(struct hv_device *hdev, bool keep_devs)
36653665
{
36663666
struct hv_pcibus_device *hbus = hv_get_drvdata(hdev);
3667+
struct vmbus_channel *chan = hdev->channel;
36673668
struct {
36683669
struct pci_packet teardown_packet;
36693670
u8 buffer[sizeof(struct pci_message)];
36703671
} pkt;
36713672
struct hv_pci_compl comp_pkt;
36723673
struct hv_pci_dev *hpdev, *tmp;
36733674
unsigned long flags;
3675+
u64 trans_id;
36743676
int ret;
36753677

36763678
/*
36773679
* After the host sends the RESCIND_CHANNEL message, it doesn't
36783680
* access the per-channel ringbuffer any longer.
36793681
*/
3680-
if (hdev->channel->rescind)
3682+
if (chan->rescind)
36813683
return 0;
36823684

36833685
if (!keep_devs) {
@@ -3714,16 +3716,26 @@ static int hv_pci_bus_exit(struct hv_device *hdev, bool keep_devs)
37143716
pkt.teardown_packet.compl_ctxt = &comp_pkt;
37153717
pkt.teardown_packet.message[0].type = PCI_BUS_D0EXIT;
37163718

3717-
ret = vmbus_sendpacket(hdev->channel, &pkt.teardown_packet.message,
3718-
sizeof(struct pci_message),
3719-
(unsigned long)&pkt.teardown_packet,
3720-
VM_PKT_DATA_INBAND,
3721-
VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
3719+
ret = vmbus_sendpacket_getid(chan, &pkt.teardown_packet.message,
3720+
sizeof(struct pci_message),
3721+
(unsigned long)&pkt.teardown_packet,
3722+
&trans_id, VM_PKT_DATA_INBAND,
3723+
VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
37223724
if (ret)
37233725
return ret;
37243726

3725-
if (wait_for_completion_timeout(&comp_pkt.host_event, 10 * HZ) == 0)
3727+
if (wait_for_completion_timeout(&comp_pkt.host_event, 10 * HZ) == 0) {
3728+
/*
3729+
* The completion packet on the stack becomes invalid after
3730+
* 'return'; remove the ID from the VMbus requestor if the
3731+
* identifier is still mapped to/associated with the packet.
3732+
*
3733+
* Cf. hv_pci_onchannelcallback().
3734+
*/
3735+
vmbus_request_addr_match(chan, trans_id,
3736+
(unsigned long)&pkt.teardown_packet);
37263737
return -ETIMEDOUT;
3738+
}
37273739

37283740
return 0;
37293741
}

0 commit comments

Comments
 (0)