mirror of
https://github.com/torvalds/linux.git
synced 2024-11-30 16:11:38 +00:00
Merge branch irq/gicv3-eppi-partition into irq/irqchip-next
- Add support for partitionned EPPIs, modeled after the existing partitioned PPI support * irq/gicv3-eppi-partition: irqchip/gic-v3: Fix selection of partition domain for EPPIs irqchip/gic-v3: Add __gic_get_ppi_index() to find the PPI number from hwirq Signed-off-by: Marc Zyngier <maz@kernel.org>
This commit is contained in:
commit
53b13565fc
@ -446,18 +446,23 @@ static void gic_irq_set_prio(struct irq_data *d, u8 prio)
|
||||
writeb_relaxed(prio, base + offset + index);
|
||||
}
|
||||
|
||||
static u32 gic_get_ppi_index(struct irq_data *d)
|
||||
static u32 __gic_get_ppi_index(irq_hw_number_t hwirq)
|
||||
{
|
||||
switch (get_intid_range(d)) {
|
||||
switch (__get_intid_range(hwirq)) {
|
||||
case PPI_RANGE:
|
||||
return d->hwirq - 16;
|
||||
return hwirq - 16;
|
||||
case EPPI_RANGE:
|
||||
return d->hwirq - EPPI_BASE_INTID + 16;
|
||||
return hwirq - EPPI_BASE_INTID + 16;
|
||||
default:
|
||||
unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
static u32 gic_get_ppi_index(struct irq_data *d)
|
||||
{
|
||||
return __gic_get_ppi_index(d->hwirq);
|
||||
}
|
||||
|
||||
static int gic_irq_nmi_setup(struct irq_data *d)
|
||||
{
|
||||
struct irq_desc *desc = irq_to_desc(d->irq);
|
||||
@ -1467,10 +1472,34 @@ static void gic_irq_domain_free(struct irq_domain *domain, unsigned int virq,
|
||||
}
|
||||
}
|
||||
|
||||
static bool fwspec_is_partitioned_ppi(struct irq_fwspec *fwspec,
|
||||
irq_hw_number_t hwirq)
|
||||
{
|
||||
enum gic_intid_range range;
|
||||
|
||||
if (!gic_data.ppi_descs)
|
||||
return false;
|
||||
|
||||
if (!is_of_node(fwspec->fwnode))
|
||||
return false;
|
||||
|
||||
if (fwspec->param_count < 4 || !fwspec->param[3])
|
||||
return false;
|
||||
|
||||
range = __get_intid_range(hwirq);
|
||||
if (range != PPI_RANGE && range != EPPI_RANGE)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int gic_irq_domain_select(struct irq_domain *d,
|
||||
struct irq_fwspec *fwspec,
|
||||
enum irq_domain_bus_token bus_token)
|
||||
{
|
||||
unsigned int type, ret, ppi_idx;
|
||||
irq_hw_number_t hwirq;
|
||||
|
||||
/* Not for us */
|
||||
if (fwspec->fwnode != d->fwnode)
|
||||
return 0;
|
||||
@ -1479,16 +1508,19 @@ static int gic_irq_domain_select(struct irq_domain *d,
|
||||
if (!is_of_node(fwspec->fwnode))
|
||||
return 1;
|
||||
|
||||
ret = gic_irq_domain_translate(d, fwspec, &hwirq, &type);
|
||||
if (WARN_ON_ONCE(ret))
|
||||
return 0;
|
||||
|
||||
if (!fwspec_is_partitioned_ppi(fwspec, hwirq))
|
||||
return d == gic_data.domain;
|
||||
|
||||
/*
|
||||
* If this is a PPI and we have a 4th (non-null) parameter,
|
||||
* then we need to match the partition domain.
|
||||
*/
|
||||
if (fwspec->param_count >= 4 &&
|
||||
fwspec->param[0] == 1 && fwspec->param[3] != 0 &&
|
||||
gic_data.ppi_descs)
|
||||
return d == partition_get_domain(gic_data.ppi_descs[fwspec->param[1]]);
|
||||
|
||||
return d == gic_data.domain;
|
||||
ppi_idx = __gic_get_ppi_index(hwirq);
|
||||
return d == partition_get_domain(gic_data.ppi_descs[ppi_idx]);
|
||||
}
|
||||
|
||||
static const struct irq_domain_ops gic_irq_domain_ops = {
|
||||
@ -1503,7 +1535,9 @@ static int partition_domain_translate(struct irq_domain *d,
|
||||
unsigned long *hwirq,
|
||||
unsigned int *type)
|
||||
{
|
||||
unsigned long ppi_intid;
|
||||
struct device_node *np;
|
||||
unsigned int ppi_idx;
|
||||
int ret;
|
||||
|
||||
if (!gic_data.ppi_descs)
|
||||
@ -1513,7 +1547,12 @@ static int partition_domain_translate(struct irq_domain *d,
|
||||
if (WARN_ON(!np))
|
||||
return -EINVAL;
|
||||
|
||||
ret = partition_translate_id(gic_data.ppi_descs[fwspec->param[1]],
|
||||
ret = gic_irq_domain_translate(d, fwspec, &ppi_intid, type);
|
||||
if (WARN_ON_ONCE(ret))
|
||||
return 0;
|
||||
|
||||
ppi_idx = __gic_get_ppi_index(ppi_intid);
|
||||
ret = partition_translate_id(gic_data.ppi_descs[ppi_idx],
|
||||
of_node_to_fwnode(np));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
Loading…
Reference in New Issue
Block a user