|
@@ -382,7 +382,10 @@ struct hv_pcibus_device {
|
|
struct msi_domain_info msi_info;
|
|
struct msi_domain_info msi_info;
|
|
struct msi_controller msi_chip;
|
|
struct msi_controller msi_chip;
|
|
struct irq_domain *irq_domain;
|
|
struct irq_domain *irq_domain;
|
|
|
|
+
|
|
|
|
+ /* hypercall arg, must not cross page boundary */
|
|
struct retarget_msi_interrupt retarget_msi_interrupt_params;
|
|
struct retarget_msi_interrupt retarget_msi_interrupt_params;
|
|
|
|
+
|
|
spinlock_t retarget_msi_interrupt_lock;
|
|
spinlock_t retarget_msi_interrupt_lock;
|
|
};
|
|
};
|
|
|
|
|
|
@@ -2204,7 +2207,13 @@ static int hv_pci_probe(struct hv_device *hdev,
|
|
struct hv_pcibus_device *hbus;
|
|
struct hv_pcibus_device *hbus;
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
- hbus = kzalloc(sizeof(*hbus), GFP_KERNEL);
|
|
|
|
|
|
+ /*
|
|
|
|
+ * hv_pcibus_device contains the hypercall arguments for retargeting in
|
|
|
|
+ * hv_irq_unmask(). Those must not cross a page boundary.
|
|
|
|
+ */
|
|
|
|
+ BUILD_BUG_ON(sizeof(*hbus) > PAGE_SIZE);
|
|
|
|
+
|
|
|
|
+ hbus = (struct hv_pcibus_device *)get_zeroed_page(GFP_KERNEL);
|
|
if (!hbus)
|
|
if (!hbus)
|
|
return -ENOMEM;
|
|
return -ENOMEM;
|
|
hbus->state = hv_pcibus_init;
|
|
hbus->state = hv_pcibus_init;
|
|
@@ -2308,7 +2317,7 @@ free_config:
|
|
close:
|
|
close:
|
|
vmbus_close(hdev->channel);
|
|
vmbus_close(hdev->channel);
|
|
free_bus:
|
|
free_bus:
|
|
- kfree(hbus);
|
|
|
|
|
|
+ free_page((unsigned long)hbus);
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2386,7 +2395,7 @@ static int hv_pci_remove(struct hv_device *hdev)
|
|
irq_domain_free_fwnode(hbus->sysdata.fwnode);
|
|
irq_domain_free_fwnode(hbus->sysdata.fwnode);
|
|
put_hvpcibus(hbus);
|
|
put_hvpcibus(hbus);
|
|
wait_for_completion(&hbus->remove_event);
|
|
wait_for_completion(&hbus->remove_event);
|
|
- kfree(hbus);
|
|
|
|
|
|
+ free_page((unsigned long)hbus);
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|