mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-11 07:03:09 -04:00
Merge "haven: irq: Support lending from other domains"
This commit is contained in:
commit
6d688f0472
6 changed files with 69 additions and 22 deletions
|
|
@ -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) {
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
@ -624,19 +625,54 @@ out:
|
|||
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)
|
||||
{
|
||||
|
|
@ -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);
|
||||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -183,6 +183,9 @@ int hh_rm_register_notifier(struct notifier_block *nb);
|
|||
int hh_rm_unregister_notifier(struct notifier_block *nb);
|
||||
|
||||
/* Client APIs for IRQ management */
|
||||
int hh_rm_virq_to_irq(u32 virq, u32 type);
|
||||
int hh_rm_irq_to_virq(int irq, u32 *virq);
|
||||
|
||||
int hh_rm_vm_irq_accept(hh_virq_handle_t virq_handle, int virq);
|
||||
int hh_rm_vm_irq_lend_notify(hh_vmid_t vmid, int virq, int label,
|
||||
hh_virq_handle_t *virq_handle);
|
||||
|
|
@ -227,6 +230,7 @@ int hh_rm_mem_lend(u8 mem_type, u8 flags, hh_label_t label,
|
|||
int hh_rm_mem_notify(hh_memparcel_handle_t handle, u8 flags,
|
||||
hh_label_t mem_info_tag,
|
||||
struct hh_notify_vmid_desc *vmid_desc);
|
||||
|
||||
#else
|
||||
/* RM client register notifications APIs */
|
||||
static inline int hh_rm_register_notifier(struct notifier_block *nb)
|
||||
|
|
@ -240,6 +244,16 @@ static inline int hh_rm_unregister_notifier(struct notifier_block *nb)
|
|||
}
|
||||
|
||||
/* Client APIs for IRQ management */
|
||||
static inline int hh_rm_virq_to_irq(u32 virq)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int hh_rm_irq_to_virq(int irq, u32 *virq)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int hh_rm_vm_irq_accept(hh_virq_handle_t virq_handle, int virq)
|
||||
{
|
||||
return -EINVAL;
|
||||
|
|
|
|||
Loading…
Reference in a new issue