Lines Matching +full:cpu +full:- +full:to +full:- +full:pci
1 // SPDX-License-Identifier: GPL-2.0
4 * Irqdomain for Linux to run as the root partition on Microsoft Hypervisor.
11 #include <linux/pci.h>
14 #include <linux/irqchip/irq-msi-lib.h>
18 int cpu, int vector, struct hv_interrupt_entry *entry) in hv_map_interrupt() argument
32 intr_desc = &input->interrupt_descriptor; in hv_map_interrupt()
34 input->partition_id = hv_current_partition_id; in hv_map_interrupt()
35 input->device_id = device_id.as_uint64; in hv_map_interrupt()
36 intr_desc->interrupt_type = HV_X64_INTERRUPT_TYPE_FIXED; in hv_map_interrupt()
37 intr_desc->vector_count = 1; in hv_map_interrupt()
38 intr_desc->target.vector = vector; in hv_map_interrupt()
41 intr_desc->trigger_mode = HV_INTERRUPT_TRIGGER_MODE_LEVEL; in hv_map_interrupt()
43 intr_desc->trigger_mode = HV_INTERRUPT_TRIGGER_MODE_EDGE; in hv_map_interrupt()
45 intr_desc->target.vp_set.valid_bank_mask = 0; in hv_map_interrupt()
46 intr_desc->target.vp_set.format = HV_GENERIC_SET_SPARSE_4K; in hv_map_interrupt()
47 nr_bank = cpumask_to_vpset(&(intr_desc->target.vp_set), cpumask_of(cpu)); in hv_map_interrupt()
50 pr_err("%s: unable to generate VP set\n", __func__); in hv_map_interrupt()
51 return -EINVAL; in hv_map_interrupt()
53 intr_desc->target.flags = HV_DEVICE_INTERRUPT_TARGET_PROCESSOR_SET; in hv_map_interrupt()
56 * var-sized hypercall, var-size starts after vp_mask (thus in hv_map_interrupt()
64 *entry = output->interrupt_entry; in hv_map_interrupt()
85 intr_entry = &input->interrupt_entry; in hv_unmap_interrupt()
86 input->partition_id = hv_current_partition_id; in hv_unmap_interrupt()
87 input->device_id = id; in hv_unmap_interrupt()
108 u8 bus = PCI_BUS_NUM(rd->rid); in get_rid_cb()
110 if (pdev->bus->number != bus || PCI_BUS_NUM(alias) != bus) { in get_rid_cb()
111 rd->bridge = pdev; in get_rid_cb()
112 rd->rid = alias; in get_rid_cb()
123 .rid = PCI_DEVID(dev->bus->number, dev->devfn) in hv_build_pci_dev_id()
130 dev_id.pci.segment = pci_domain_nr(dev->bus); in hv_build_pci_dev_id()
132 dev_id.pci.bdf.bus = PCI_BUS_NUM(data.rid); in hv_build_pci_dev_id()
133 dev_id.pci.bdf.device = PCI_SLOT(data.rid); in hv_build_pci_dev_id()
134 dev_id.pci.bdf.function = PCI_FUNC(data.rid); in hv_build_pci_dev_id()
135 dev_id.pci.source_shadow = HV_SOURCE_SHADOW_NONE; in hv_build_pci_dev_id()
142 * running in PCI-X mode. in hv_build_pci_dev_id()
144 * To distinguish conventional vs PCI-X bridge, we can check in hv_build_pci_dev_id()
145 * the bridge's PCI-X Secondary Status Register, Secondary Bus in hv_build_pci_dev_id()
146 * Mode and Frequency bits. See PCI Express to PCI/PCI-X Bridge in hv_build_pci_dev_id()
150 * in PCI-X mode. in hv_build_pci_dev_id()
161 /* Non-zero, PCI-X mode */ in hv_build_pci_dev_id()
164 dev_id.pci.source_shadow = HV_SOURCE_SHADOW_BRIDGE_BUS_RANGE; in hv_build_pci_dev_id()
167 dev_id.pci.shadow_bus_range.secondary_bus = sec_bus; in hv_build_pci_dev_id()
169 dev_id.pci.shadow_bus_range.subordinate_bus = sub_bus; in hv_build_pci_dev_id()
178 * hv_map_msi_interrupt() - "Map" the MSI IRQ in the hypervisor.
184 * Return: 0 on success, -errno on failure
194 int cpu; in hv_map_msi_interrupt() local
199 cpu = cpumask_first(irq_data_get_effective_affinity_mask(data)); in hv_map_msi_interrupt()
201 return hv_map_interrupt(device_id, false, cpu, cfg->vector, in hv_map_msi_interrupt()
209 msg->address_hi = 0; in entry_to_msi_msg()
210 msg->address_lo = entry->msi_entry.address.as_uint32; in entry_to_msi_msg()
211 msg->data = entry->msi_entry.data.as_uint32; in entry_to_msi_msg()
231 if (data->chip_data) { in hv_irq_compose_msi_msg()
236 * Microsoft Hypervisor doesn't allow root to change the vector in hv_irq_compose_msi_msg()
240 stored_entry = data->chip_data; in hv_irq_compose_msi_msg()
241 data->chip_data = NULL; in hv_irq_compose_msi_msg()
253 pr_debug("%s: failed to allocate chip data\n", __func__); in hv_irq_compose_msi_msg()
263 data->chip_data = stored_entry; in hv_irq_compose_msi_msg()
264 entry_to_msi_msg(data->chip_data, msg); in hv_irq_compose_msi_msg()
279 if (!irqd->chip_data) { in hv_teardown_msi_irq()
284 old_entry = *(struct hv_interrupt_entry *)irqd->chip_data; in hv_teardown_msi_irq()
287 kfree(irqd->chip_data); in hv_teardown_msi_irq()
288 irqd->chip_data = NULL; in hv_teardown_msi_irq()
294 * IRQ Chip for MSI PCI/PCI-X/PCI-Express Devices,
295 * which implement the MSI or MSI-X Capability Structure.
298 .name = "HV-PCI-MSI",
307 struct irq_chip *chip = info->chip; in hv_init_dev_msi_info()
312 chip->flags |= IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MOVE_DEFERRED; in hv_init_dev_msi_info()
314 info->ops->msi_prepare = pci_msi_prepare; in hv_init_dev_msi_info()
328 .prefix = "HV-",
360 if (!desc || !desc->irq || WARN_ON_ONCE(!dev_is_pci(desc->dev))) in hv_msi_domain_free()
363 hv_teardown_msi_irq(to_pci_dev(desc->dev), irqd); in hv_msi_domain_free()
379 .fwnode = irq_domain_alloc_named_fwnode("HV-PCI-MSI"), in hv_create_pci_msi_domain()
407 int hv_map_ioapic_interrupt(int ioapic_id, bool level, int cpu, int vector, in hv_map_ioapic_interrupt() argument
416 return hv_map_interrupt(device_id, level, cpu, vector, entry); in hv_map_ioapic_interrupt()