PCI: hv: Fix synchronization between channel callback and hv_pci_bus_exit()
[ Similarly to commit a765ed47e4516 ("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>
This commit is contained in:
parent
9937fa6d1e
commit
b4927bd272
@ -3664,6 +3664,7 @@ free_bus:
|
|||||||
static int hv_pci_bus_exit(struct hv_device *hdev, bool keep_devs)
|
static int hv_pci_bus_exit(struct hv_device *hdev, bool keep_devs)
|
||||||
{
|
{
|
||||||
struct hv_pcibus_device *hbus = hv_get_drvdata(hdev);
|
struct hv_pcibus_device *hbus = hv_get_drvdata(hdev);
|
||||||
|
struct vmbus_channel *chan = hdev->channel;
|
||||||
struct {
|
struct {
|
||||||
struct pci_packet teardown_packet;
|
struct pci_packet teardown_packet;
|
||||||
u8 buffer[sizeof(struct pci_message)];
|
u8 buffer[sizeof(struct pci_message)];
|
||||||
@ -3671,13 +3672,14 @@ static int hv_pci_bus_exit(struct hv_device *hdev, bool keep_devs)
|
|||||||
struct hv_pci_compl comp_pkt;
|
struct hv_pci_compl comp_pkt;
|
||||||
struct hv_pci_dev *hpdev, *tmp;
|
struct hv_pci_dev *hpdev, *tmp;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
u64 trans_id;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* After the host sends the RESCIND_CHANNEL message, it doesn't
|
* After the host sends the RESCIND_CHANNEL message, it doesn't
|
||||||
* access the per-channel ringbuffer any longer.
|
* access the per-channel ringbuffer any longer.
|
||||||
*/
|
*/
|
||||||
if (hdev->channel->rescind)
|
if (chan->rescind)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!keep_devs) {
|
if (!keep_devs) {
|
||||||
@ -3714,16 +3716,26 @@ static int hv_pci_bus_exit(struct hv_device *hdev, bool keep_devs)
|
|||||||
pkt.teardown_packet.compl_ctxt = &comp_pkt;
|
pkt.teardown_packet.compl_ctxt = &comp_pkt;
|
||||||
pkt.teardown_packet.message[0].type = PCI_BUS_D0EXIT;
|
pkt.teardown_packet.message[0].type = PCI_BUS_D0EXIT;
|
||||||
|
|
||||||
ret = vmbus_sendpacket(hdev->channel, &pkt.teardown_packet.message,
|
ret = vmbus_sendpacket_getid(chan, &pkt.teardown_packet.message,
|
||||||
sizeof(struct pci_message),
|
sizeof(struct pci_message),
|
||||||
(unsigned long)&pkt.teardown_packet,
|
(unsigned long)&pkt.teardown_packet,
|
||||||
VM_PKT_DATA_INBAND,
|
&trans_id, VM_PKT_DATA_INBAND,
|
||||||
VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
|
VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (wait_for_completion_timeout(&comp_pkt.host_event, 10 * HZ) == 0)
|
if (wait_for_completion_timeout(&comp_pkt.host_event, 10 * HZ) == 0) {
|
||||||
|
/*
|
||||||
|
* The completion packet on the stack becomes invalid after
|
||||||
|
* 'return'; remove the ID from the VMbus requestor if the
|
||||||
|
* identifier is still mapped to/associated with the packet.
|
||||||
|
*
|
||||||
|
* Cf. hv_pci_onchannelcallback().
|
||||||
|
*/
|
||||||
|
vmbus_request_addr_match(chan, trans_id,
|
||||||
|
(unsigned long)&pkt.teardown_packet);
|
||||||
return -ETIMEDOUT;
|
return -ETIMEDOUT;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user