diff options
author | Long Li <longli@microsoft.com> | 2016-11-08 17:04:38 -0500 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2016-11-29 18:22:43 -0500 |
commit | 0de8ce3ee8e38cc66683438f715c79a2cc69539e (patch) | |
tree | 7defffab1a2a78f999764dcc89424f519dc89038 | |
parent | e74d2ebdda33b3bdd1826b5b92e9aa45bdf92bb3 (diff) |
PCI: hv: Allocate physically contiguous hypercall params buffer
hv_do_hypercall() assumes that we pass a segment from a physically
contiguous buffer. A buffer allocated on the stack may not work if
CONFIG_VMAP_STACK=y is set.
Use kmalloc() to allocate this buffer.
Reported-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Long Li <longli@microsoft.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Acked-by: K. Y. Srinivasan <kys@microsoft.com>
-rw-r--r-- | drivers/pci/host/pci-hyperv.c | 29 |
1 files changed, 19 insertions, 10 deletions
diff --git a/drivers/pci/host/pci-hyperv.c b/drivers/pci/host/pci-hyperv.c index a63c3a4f6c7c..3efcc7bdc5fb 100644 --- a/drivers/pci/host/pci-hyperv.c +++ b/drivers/pci/host/pci-hyperv.c | |||
@@ -378,6 +378,8 @@ struct hv_pcibus_device { | |||
378 | struct msi_domain_info msi_info; | 378 | struct msi_domain_info msi_info; |
379 | struct msi_controller msi_chip; | 379 | struct msi_controller msi_chip; |
380 | struct irq_domain *irq_domain; | 380 | struct irq_domain *irq_domain; |
381 | struct retarget_msi_interrupt retarget_msi_interrupt_params; | ||
382 | spinlock_t retarget_msi_interrupt_lock; | ||
381 | }; | 383 | }; |
382 | 384 | ||
383 | /* | 385 | /* |
@@ -774,34 +776,40 @@ static void hv_irq_unmask(struct irq_data *data) | |||
774 | { | 776 | { |
775 | struct msi_desc *msi_desc = irq_data_get_msi_desc(data); | 777 | struct msi_desc *msi_desc = irq_data_get_msi_desc(data); |
776 | struct irq_cfg *cfg = irqd_cfg(data); | 778 | struct irq_cfg *cfg = irqd_cfg(data); |
777 | struct retarget_msi_interrupt params; | 779 | struct retarget_msi_interrupt *params; |
778 | struct hv_pcibus_device *hbus; | 780 | struct hv_pcibus_device *hbus; |
779 | struct cpumask *dest; | 781 | struct cpumask *dest; |
780 | struct pci_bus *pbus; | 782 | struct pci_bus *pbus; |
781 | struct pci_dev *pdev; | 783 | struct pci_dev *pdev; |
782 | int cpu; | 784 | int cpu; |
785 | unsigned long flags; | ||
783 | 786 | ||
784 | dest = irq_data_get_affinity_mask(data); | 787 | dest = irq_data_get_affinity_mask(data); |
785 | pdev = msi_desc_to_pci_dev(msi_desc); | 788 | pdev = msi_desc_to_pci_dev(msi_desc); |
786 | pbus = pdev->bus; | 789 | pbus = pdev->bus; |
787 | hbus = container_of(pbus->sysdata, struct hv_pcibus_device, sysdata); | 790 | hbus = container_of(pbus->sysdata, struct hv_pcibus_device, sysdata); |
788 | 791 | ||
789 | memset(¶ms, 0, sizeof(params)); | 792 | spin_lock_irqsave(&hbus->retarget_msi_interrupt_lock, flags); |
790 | params.partition_id = HV_PARTITION_ID_SELF; | 793 | |
791 | params.source = 1; /* MSI(-X) */ | 794 | params = &hbus->retarget_msi_interrupt_params; |
792 | params.address = msi_desc->msg.address_lo; | 795 | memset(params, 0, sizeof(*params)); |
793 | params.data = msi_desc->msg.data; | 796 | params->partition_id = HV_PARTITION_ID_SELF; |
794 | params.device_id = (hbus->hdev->dev_instance.b[5] << 24) | | 797 | params->source = 1; /* MSI(-X) */ |
798 | params->address = msi_desc->msg.address_lo; | ||
799 | params->data = msi_desc->msg.data; | ||
800 | params->device_id = (hbus->hdev->dev_instance.b[5] << 24) | | ||
795 | (hbus->hdev->dev_instance.b[4] << 16) | | 801 | (hbus->hdev->dev_instance.b[4] << 16) | |
796 | (hbus->hdev->dev_instance.b[7] << 8) | | 802 | (hbus->hdev->dev_instance.b[7] << 8) | |
797 | (hbus->hdev->dev_instance.b[6] & 0xf8) | | 803 | (hbus->hdev->dev_instance.b[6] & 0xf8) | |
798 | PCI_FUNC(pdev->devfn); | 804 | PCI_FUNC(pdev->devfn); |
799 | params.vector = cfg->vector; | 805 | params->vector = cfg->vector; |
800 | 806 | ||
801 | for_each_cpu_and(cpu, dest, cpu_online_mask) | 807 | for_each_cpu_and(cpu, dest, cpu_online_mask) |
802 | params.vp_mask |= (1ULL << vmbus_cpu_number_to_vp_number(cpu)); | 808 | params->vp_mask |= (1ULL << vmbus_cpu_number_to_vp_number(cpu)); |
809 | |||
810 | hv_do_hypercall(HVCALL_RETARGET_INTERRUPT, params, NULL); | ||
803 | 811 | ||
804 | hv_do_hypercall(HVCALL_RETARGET_INTERRUPT, ¶ms, NULL); | 812 | spin_unlock_irqrestore(&hbus->retarget_msi_interrupt_lock, flags); |
805 | 813 | ||
806 | pci_msi_unmask_irq(data); | 814 | pci_msi_unmask_irq(data); |
807 | } | 815 | } |
@@ -2186,6 +2194,7 @@ static int hv_pci_probe(struct hv_device *hdev, | |||
2186 | INIT_LIST_HEAD(&hbus->resources_for_children); | 2194 | INIT_LIST_HEAD(&hbus->resources_for_children); |
2187 | spin_lock_init(&hbus->config_lock); | 2195 | spin_lock_init(&hbus->config_lock); |
2188 | spin_lock_init(&hbus->device_list_lock); | 2196 | spin_lock_init(&hbus->device_list_lock); |
2197 | spin_lock_init(&hbus->retarget_msi_interrupt_lock); | ||
2189 | sema_init(&hbus->enum_sem, 1); | 2198 | sema_init(&hbus->enum_sem, 1); |
2190 | init_completion(&hbus->remove_event); | 2199 | init_completion(&hbus->remove_event); |
2191 | 2200 | ||