PCI: hv: Fix hv_pci_remove() for hot-remove
1. We don't really need such a big on-stack buffer when sending the teardown_packet: vmbus_sendpacket() here only uses sizeof(struct pci_message). 2. In the hot-remove case (PCI_EJECT), after we send PCI_EJECTION_COMPLETE to the host, the host will send a RESCIND_CHANNEL message to us and the host won't access the per-channel ringbuffer any longer, so we needn't send PCI_RESOURCES_RELEASED/PCI_BUS_D0EXIT to the host, and we shouldn't expect the host's completion message of PCI_BUS_D0EXIT, which will never come. 3. We should send PCI_BUS_D0EXIT after hv_send_resources_released(). Signed-off-by: Dexuan Cui <decui@microsoft.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Reviewed-by: Jake Oshins <jakeo@microsoft.com> Acked-by: K. Y. Srinivasan <kys@microsoft.com> CC: Haiyang Zhang <haiyangz@microsoft.com> CC: Vitaly Kuznetsov <vkuznets@redhat.com>
This commit is contained in:
parent
8286e96d95
commit
17978524a6
@ -2266,24 +2266,32 @@ free_bus:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static void hv_pci_bus_exit(struct hv_device *hdev)
|
||||||
* hv_pci_remove() - Remove routine for this VMBus channel
|
|
||||||
* @hdev: VMBus's tracking struct for this root PCI bus
|
|
||||||
*
|
|
||||||
* Return: 0 on success, -errno on failure
|
|
||||||
*/
|
|
||||||
static int hv_pci_remove(struct hv_device *hdev)
|
|
||||||
{
|
{
|
||||||
int ret;
|
struct hv_pcibus_device *hbus = hv_get_drvdata(hdev);
|
||||||
struct hv_pcibus_device *hbus;
|
struct {
|
||||||
union {
|
|
||||||
struct pci_packet teardown_packet;
|
struct pci_packet teardown_packet;
|
||||||
u8 buffer[0x100];
|
u8 buffer[sizeof(struct pci_message)];
|
||||||
} pkt;
|
} pkt;
|
||||||
struct pci_bus_relations relations;
|
struct pci_bus_relations relations;
|
||||||
struct hv_pci_compl comp_pkt;
|
struct hv_pci_compl comp_pkt;
|
||||||
|
int ret;
|
||||||
|
|
||||||
hbus = hv_get_drvdata(hdev);
|
/*
|
||||||
|
* After the host sends the RESCIND_CHANNEL message, it doesn't
|
||||||
|
* access the per-channel ringbuffer any longer.
|
||||||
|
*/
|
||||||
|
if (hdev->channel->rescind)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Delete any children which might still exist. */
|
||||||
|
memset(&relations, 0, sizeof(relations));
|
||||||
|
hv_pci_devices_present(hbus, &relations);
|
||||||
|
|
||||||
|
ret = hv_send_resources_released(hdev);
|
||||||
|
if (ret)
|
||||||
|
dev_err(&hdev->device,
|
||||||
|
"Couldn't send resources released packet(s)\n");
|
||||||
|
|
||||||
memset(&pkt.teardown_packet, 0, sizeof(pkt.teardown_packet));
|
memset(&pkt.teardown_packet, 0, sizeof(pkt.teardown_packet));
|
||||||
init_completion(&comp_pkt.host_event);
|
init_completion(&comp_pkt.host_event);
|
||||||
@ -2298,7 +2306,19 @@ static int hv_pci_remove(struct hv_device *hdev)
|
|||||||
VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
|
VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
wait_for_completion_timeout(&comp_pkt.host_event, 10 * HZ);
|
wait_for_completion_timeout(&comp_pkt.host_event, 10 * HZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hv_pci_remove() - Remove routine for this VMBus channel
|
||||||
|
* @hdev: VMBus's tracking struct for this root PCI bus
|
||||||
|
*
|
||||||
|
* Return: 0 on success, -errno on failure
|
||||||
|
*/
|
||||||
|
static int hv_pci_remove(struct hv_device *hdev)
|
||||||
|
{
|
||||||
|
struct hv_pcibus_device *hbus;
|
||||||
|
|
||||||
|
hbus = hv_get_drvdata(hdev);
|
||||||
if (hbus->state == hv_pcibus_installed) {
|
if (hbus->state == hv_pcibus_installed) {
|
||||||
/* Remove the bus from PCI's point of view. */
|
/* Remove the bus from PCI's point of view. */
|
||||||
pci_lock_rescan_remove();
|
pci_lock_rescan_remove();
|
||||||
@ -2307,17 +2327,10 @@ static int hv_pci_remove(struct hv_device *hdev)
|
|||||||
pci_unlock_rescan_remove();
|
pci_unlock_rescan_remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = hv_send_resources_released(hdev);
|
hv_pci_bus_exit(hdev);
|
||||||
if (ret)
|
|
||||||
dev_err(&hdev->device,
|
|
||||||
"Couldn't send resources released packet(s)\n");
|
|
||||||
|
|
||||||
vmbus_close(hdev->channel);
|
vmbus_close(hdev->channel);
|
||||||
|
|
||||||
/* Delete any children which might still exist. */
|
|
||||||
memset(&relations, 0, sizeof(relations));
|
|
||||||
hv_pci_devices_present(hbus, &relations);
|
|
||||||
|
|
||||||
iounmap(hbus->cfg_addr);
|
iounmap(hbus->cfg_addr);
|
||||||
hv_free_config_window(hbus);
|
hv_free_config_window(hbus);
|
||||||
pci_free_resource_list(&hbus->resources_for_children);
|
pci_free_resource_list(&hbus->resources_for_children);
|
||||||
|
Loading…
Reference in New Issue
Block a user