Loading drivers/virt/haven/hh_irq_lend.c +7 −12 Original line number Diff line number Diff line Loading @@ -141,17 +141,14 @@ int hh_irq_lend(enum hh_irq_label label, enum hh_vm_names name, int ret, virq; unsigned long flags; struct hh_irq_entry *entry; struct irq_data *irq_data; if (label >= HH_IRQ_LABEL_MAX || !on_release) return -EINVAL; entry = &hh_irq_entries[label]; irq_data = irq_get_irq_data(irq); if (!irq_data) if (hh_rm_irq_to_virq(irq, &virq)) return -EINVAL; virq = irq_data->hwirq; spin_lock_irqsave(&hh_irq_lend_lock, flags); if (entry->state != HH_IRQ_STATE_NONE) { Loading Loading @@ -245,17 +242,18 @@ EXPORT_SYMBOL(hh_irq_wait_for_lend); * hh_irq_accept: Register to receive interrupts with a lent vIRQ * @label: vIRQ high-level label * @irq: Linux IRQ# to associate vIRQ with. If don't care, use -1 * @type: IRQ flags to use when allowing RM to choose the IRQ. If irq parameter * is specified, then type is unused. * * Returns the Linux IRQ# that vIRQ was registered to on success. * Returns <0 on error * This function is not thread-safe w.r.t. IRQ lend state. Do not race with * with hh_irq_release or another hh_irq_accept with same label. */ int hh_irq_accept(enum hh_irq_label label, int irq) int hh_irq_accept(enum hh_irq_label label, int irq, int type) { struct hh_irq_entry *entry; const struct irq_data *irq_data; int virq; u32 virq; if (label >= HH_IRQ_LABEL_MAX) return -EINVAL; Loading @@ -266,10 +264,8 @@ int hh_irq_accept(enum hh_irq_label label, int irq) return -EINVAL; if (irq != -1) { irq_data = irq_get_irq_data(irq); if (!irq_data) if (hh_rm_irq_to_virq(irq, &virq)) return -EINVAL; virq = irq_data->hwirq; } else virq = -1; Loading @@ -278,8 +274,7 @@ int hh_irq_accept(enum hh_irq_label label, int irq) return virq; if (irq == -1) irq = hh_rm_virq_to_linux_irq(virq - 32, GIC_SPI, IRQ_TYPE_LEVEL_HIGH); irq = hh_rm_virq_to_irq(virq, type); return irq; } Loading drivers/virt/haven/hh_rm_core.c +47 −7 Original line number Diff line number Diff line Loading @@ -60,6 +60,7 @@ static DEFINE_MUTEX(hh_rm_send_lock); static DEFINE_IDA(hh_rm_free_virq_ida); static struct device_node *hh_rm_intc; static struct irq_domain *hh_rm_irq_domain; static u32 hh_rm_base_virq; SRCU_NOTIFIER_HEAD_STATIC(hh_rm_notifier); Loading Loading @@ -624,19 +625,54 @@ void *hh_rm_call(hh_rm_msgid_t message_id, return ret; } int hh_rm_virq_to_linux_irq(u32 virq, u32 type, u32 trigger) /** * hh_rm_virq_to_irq: Get a Linux IRQ from a Haven-compatible vIRQ * @virq: Haven-compatible vIRQ * @type: IRQ trigger type (IRQ_TYPE_EDGE_RISING) * * Returns the mapped Linux IRQ# at Haven's IRQ domain (i.e. GIC SPI) */ int hh_rm_virq_to_irq(u32 virq, u32 type) { struct irq_fwspec fwspec = {}; if (virq < 32 || virq >= GIC_V3_SPI_MAX) { pr_warn("%s: expecting an SPI from RM, but got GIC IRQ %d\n", __func__, virq); } fwspec.fwnode = of_node_to_fwnode(hh_rm_intc); fwspec.param_count = 3; fwspec.param[0] = type; fwspec.param[1] = virq; fwspec.param[2] = trigger; fwspec.param[0] = GIC_SPI; fwspec.param[1] = virq - 32; fwspec.param[2] = type; return irq_create_fwspec_mapping(&fwspec); } EXPORT_SYMBOL(hh_rm_virq_to_linux_irq); EXPORT_SYMBOL(hh_rm_virq_to_irq); /** * hh_rm_irq_to_virq: Get a Haven-compatible vIRQ from a Linux IRQ * @irq: Linux-assigned IRQ# * @virq: out value where Haven-compatible vIRQ is stored * * Returns 0 upon success, -EINVAL if the Linux IRQ could not be mapped to * a Haven vIRQ (i.e., the IRQ does not correspond to any GIC-level IRQ) */ int hh_rm_irq_to_virq(int irq, u32 *virq) { struct irq_data *irq_data; irq_data = irq_domain_get_irq_data(hh_rm_irq_domain, irq); if (!irq_data) return -EINVAL; if (virq) *virq = irq_data->hwirq; return 0; } EXPORT_SYMBOL(hh_rm_irq_to_virq); static int hh_rm_get_irq(struct hh_vm_get_hyp_res_resp_entry *res_entry) { Loading Loading @@ -673,8 +709,7 @@ static int hh_rm_get_irq(struct hh_vm_get_hyp_res_resp_entry *res_entry) return -EINVAL; } return hh_rm_virq_to_linux_irq(virq - 32, GIC_SPI, IRQ_TYPE_EDGE_RISING); return hh_rm_virq_to_irq(virq, IRQ_TYPE_EDGE_RISING); err: ida_free(&hh_rm_free_virq_ida, virq - 32); Loading Loading @@ -838,6 +873,11 @@ static int hh_rm_drv_probe(struct platform_device *pdev) dev_err(dev, "Failed to get the IRQ parent node\n"); return -ENXIO; } hh_rm_irq_domain = irq_find_host(hh_rm_intc); if (!hh_rm_irq_domain) { dev_err(dev, "Failed to get IRQ domain associated with RM\n"); return -ENXIO; } hh_rm_msgq_desc = hh_msgq_register(HH_MSGQ_LABEL_RM); if (IS_ERR_OR_NULL(hh_rm_msgq_desc)) Loading drivers/virt/haven/hh_rm_drv_private.h +0 −1 Original line number Diff line number Diff line Loading @@ -281,7 +281,6 @@ struct hh_mem_notify_req_payload { /* End Message ID headers */ /* Common function declerations */ int hh_rm_virq_to_linux_irq(u32 virq, u32 type, u32 trigger); int hh_update_vm_prop_table(enum hh_vm_names vm_name, struct hh_vm_property *vm_prop); void *hh_rm_call(hh_rm_msgid_t message_id, Loading drivers/virt/haven/hh_rm_iface.c +0 −1 Original line number Diff line number Diff line Loading @@ -373,7 +373,6 @@ static int hh_rm_vm_irq_release(hh_virq_handle_t virq_handle) return ret; } EXPORT_SYMBOL(hh_rm_vm_irq_release); /** * hh_rm_vm_irq_release_notify: Release IRQ back to a VM and notify that it has Loading include/linux/haven/hh_irq_lend.h +1 −1 Original line number Diff line number Diff line Loading @@ -26,7 +26,7 @@ int hh_irq_reclaim(enum hh_irq_label label); int hh_irq_wait_for_lend(enum hh_irq_label label, enum hh_vm_names name, hh_irq_handle_fn on_lend, void *data); int hh_irq_accept(enum hh_irq_label label, int hw_irq); int hh_irq_accept(enum hh_irq_label label, int irq, int type); int hh_irq_release(enum hh_irq_label label); #endif Loading
drivers/virt/haven/hh_irq_lend.c +7 −12 Original line number Diff line number Diff line Loading @@ -141,17 +141,14 @@ int hh_irq_lend(enum hh_irq_label label, enum hh_vm_names name, int ret, virq; unsigned long flags; struct hh_irq_entry *entry; struct irq_data *irq_data; if (label >= HH_IRQ_LABEL_MAX || !on_release) return -EINVAL; entry = &hh_irq_entries[label]; irq_data = irq_get_irq_data(irq); if (!irq_data) if (hh_rm_irq_to_virq(irq, &virq)) return -EINVAL; virq = irq_data->hwirq; spin_lock_irqsave(&hh_irq_lend_lock, flags); if (entry->state != HH_IRQ_STATE_NONE) { Loading Loading @@ -245,17 +242,18 @@ EXPORT_SYMBOL(hh_irq_wait_for_lend); * hh_irq_accept: Register to receive interrupts with a lent vIRQ * @label: vIRQ high-level label * @irq: Linux IRQ# to associate vIRQ with. If don't care, use -1 * @type: IRQ flags to use when allowing RM to choose the IRQ. If irq parameter * is specified, then type is unused. * * Returns the Linux IRQ# that vIRQ was registered to on success. * Returns <0 on error * This function is not thread-safe w.r.t. IRQ lend state. Do not race with * with hh_irq_release or another hh_irq_accept with same label. */ int hh_irq_accept(enum hh_irq_label label, int irq) int hh_irq_accept(enum hh_irq_label label, int irq, int type) { struct hh_irq_entry *entry; const struct irq_data *irq_data; int virq; u32 virq; if (label >= HH_IRQ_LABEL_MAX) return -EINVAL; Loading @@ -266,10 +264,8 @@ int hh_irq_accept(enum hh_irq_label label, int irq) return -EINVAL; if (irq != -1) { irq_data = irq_get_irq_data(irq); if (!irq_data) if (hh_rm_irq_to_virq(irq, &virq)) return -EINVAL; virq = irq_data->hwirq; } else virq = -1; Loading @@ -278,8 +274,7 @@ int hh_irq_accept(enum hh_irq_label label, int irq) return virq; if (irq == -1) irq = hh_rm_virq_to_linux_irq(virq - 32, GIC_SPI, IRQ_TYPE_LEVEL_HIGH); irq = hh_rm_virq_to_irq(virq, type); return irq; } Loading
drivers/virt/haven/hh_rm_core.c +47 −7 Original line number Diff line number Diff line Loading @@ -60,6 +60,7 @@ static DEFINE_MUTEX(hh_rm_send_lock); static DEFINE_IDA(hh_rm_free_virq_ida); static struct device_node *hh_rm_intc; static struct irq_domain *hh_rm_irq_domain; static u32 hh_rm_base_virq; SRCU_NOTIFIER_HEAD_STATIC(hh_rm_notifier); Loading Loading @@ -624,19 +625,54 @@ void *hh_rm_call(hh_rm_msgid_t message_id, return ret; } int hh_rm_virq_to_linux_irq(u32 virq, u32 type, u32 trigger) /** * hh_rm_virq_to_irq: Get a Linux IRQ from a Haven-compatible vIRQ * @virq: Haven-compatible vIRQ * @type: IRQ trigger type (IRQ_TYPE_EDGE_RISING) * * Returns the mapped Linux IRQ# at Haven's IRQ domain (i.e. GIC SPI) */ int hh_rm_virq_to_irq(u32 virq, u32 type) { struct irq_fwspec fwspec = {}; if (virq < 32 || virq >= GIC_V3_SPI_MAX) { pr_warn("%s: expecting an SPI from RM, but got GIC IRQ %d\n", __func__, virq); } fwspec.fwnode = of_node_to_fwnode(hh_rm_intc); fwspec.param_count = 3; fwspec.param[0] = type; fwspec.param[1] = virq; fwspec.param[2] = trigger; fwspec.param[0] = GIC_SPI; fwspec.param[1] = virq - 32; fwspec.param[2] = type; return irq_create_fwspec_mapping(&fwspec); } EXPORT_SYMBOL(hh_rm_virq_to_linux_irq); EXPORT_SYMBOL(hh_rm_virq_to_irq); /** * hh_rm_irq_to_virq: Get a Haven-compatible vIRQ from a Linux IRQ * @irq: Linux-assigned IRQ# * @virq: out value where Haven-compatible vIRQ is stored * * Returns 0 upon success, -EINVAL if the Linux IRQ could not be mapped to * a Haven vIRQ (i.e., the IRQ does not correspond to any GIC-level IRQ) */ int hh_rm_irq_to_virq(int irq, u32 *virq) { struct irq_data *irq_data; irq_data = irq_domain_get_irq_data(hh_rm_irq_domain, irq); if (!irq_data) return -EINVAL; if (virq) *virq = irq_data->hwirq; return 0; } EXPORT_SYMBOL(hh_rm_irq_to_virq); static int hh_rm_get_irq(struct hh_vm_get_hyp_res_resp_entry *res_entry) { Loading Loading @@ -673,8 +709,7 @@ static int hh_rm_get_irq(struct hh_vm_get_hyp_res_resp_entry *res_entry) return -EINVAL; } return hh_rm_virq_to_linux_irq(virq - 32, GIC_SPI, IRQ_TYPE_EDGE_RISING); return hh_rm_virq_to_irq(virq, IRQ_TYPE_EDGE_RISING); err: ida_free(&hh_rm_free_virq_ida, virq - 32); Loading Loading @@ -838,6 +873,11 @@ static int hh_rm_drv_probe(struct platform_device *pdev) dev_err(dev, "Failed to get the IRQ parent node\n"); return -ENXIO; } hh_rm_irq_domain = irq_find_host(hh_rm_intc); if (!hh_rm_irq_domain) { dev_err(dev, "Failed to get IRQ domain associated with RM\n"); return -ENXIO; } hh_rm_msgq_desc = hh_msgq_register(HH_MSGQ_LABEL_RM); if (IS_ERR_OR_NULL(hh_rm_msgq_desc)) Loading
drivers/virt/haven/hh_rm_drv_private.h +0 −1 Original line number Diff line number Diff line Loading @@ -281,7 +281,6 @@ struct hh_mem_notify_req_payload { /* End Message ID headers */ /* Common function declerations */ int hh_rm_virq_to_linux_irq(u32 virq, u32 type, u32 trigger); int hh_update_vm_prop_table(enum hh_vm_names vm_name, struct hh_vm_property *vm_prop); void *hh_rm_call(hh_rm_msgid_t message_id, Loading
drivers/virt/haven/hh_rm_iface.c +0 −1 Original line number Diff line number Diff line Loading @@ -373,7 +373,6 @@ static int hh_rm_vm_irq_release(hh_virq_handle_t virq_handle) return ret; } EXPORT_SYMBOL(hh_rm_vm_irq_release); /** * hh_rm_vm_irq_release_notify: Release IRQ back to a VM and notify that it has Loading
include/linux/haven/hh_irq_lend.h +1 −1 Original line number Diff line number Diff line Loading @@ -26,7 +26,7 @@ int hh_irq_reclaim(enum hh_irq_label label); int hh_irq_wait_for_lend(enum hh_irq_label label, enum hh_vm_names name, hh_irq_handle_fn on_lend, void *data); int hh_irq_accept(enum hh_irq_label label, int hw_irq); int hh_irq_accept(enum hh_irq_label label, int irq, int type); int hh_irq_release(enum hh_irq_label label); #endif