Skip to content

Commit 53b1356

Browse files
author
Marc Zyngier
committed
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 <[email protected]>
2 parents 00a2b7c + d753f84 commit 53b1356

File tree

1 file changed

+50
-11
lines changed

1 file changed

+50
-11
lines changed

drivers/irqchip/irq-gic-v3.c

Lines changed: 50 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -446,18 +446,23 @@ static void gic_irq_set_prio(struct irq_data *d, u8 prio)
446446
writeb_relaxed(prio, base + offset + index);
447447
}
448448

449-
static u32 gic_get_ppi_index(struct irq_data *d)
449+
static u32 __gic_get_ppi_index(irq_hw_number_t hwirq)
450450
{
451-
switch (get_intid_range(d)) {
451+
switch (__get_intid_range(hwirq)) {
452452
case PPI_RANGE:
453-
return d->hwirq - 16;
453+
return hwirq - 16;
454454
case EPPI_RANGE:
455-
return d->hwirq - EPPI_BASE_INTID + 16;
455+
return hwirq - EPPI_BASE_INTID + 16;
456456
default:
457457
unreachable();
458458
}
459459
}
460460

461+
static u32 gic_get_ppi_index(struct irq_data *d)
462+
{
463+
return __gic_get_ppi_index(d->hwirq);
464+
}
465+
461466
static int gic_irq_nmi_setup(struct irq_data *d)
462467
{
463468
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,
14671472
}
14681473
}
14691474

1475+
static bool fwspec_is_partitioned_ppi(struct irq_fwspec *fwspec,
1476+
irq_hw_number_t hwirq)
1477+
{
1478+
enum gic_intid_range range;
1479+
1480+
if (!gic_data.ppi_descs)
1481+
return false;
1482+
1483+
if (!is_of_node(fwspec->fwnode))
1484+
return false;
1485+
1486+
if (fwspec->param_count < 4 || !fwspec->param[3])
1487+
return false;
1488+
1489+
range = __get_intid_range(hwirq);
1490+
if (range != PPI_RANGE && range != EPPI_RANGE)
1491+
return false;
1492+
1493+
return true;
1494+
}
1495+
14701496
static int gic_irq_domain_select(struct irq_domain *d,
14711497
struct irq_fwspec *fwspec,
14721498
enum irq_domain_bus_token bus_token)
14731499
{
1500+
unsigned int type, ret, ppi_idx;
1501+
irq_hw_number_t hwirq;
1502+
14741503
/* Not for us */
14751504
if (fwspec->fwnode != d->fwnode)
14761505
return 0;
@@ -1479,16 +1508,19 @@ static int gic_irq_domain_select(struct irq_domain *d,
14791508
if (!is_of_node(fwspec->fwnode))
14801509
return 1;
14811510

1511+
ret = gic_irq_domain_translate(d, fwspec, &hwirq, &type);
1512+
if (WARN_ON_ONCE(ret))
1513+
return 0;
1514+
1515+
if (!fwspec_is_partitioned_ppi(fwspec, hwirq))
1516+
return d == gic_data.domain;
1517+
14821518
/*
14831519
* If this is a PPI and we have a 4th (non-null) parameter,
14841520
* then we need to match the partition domain.
14851521
*/
1486-
if (fwspec->param_count >= 4 &&
1487-
fwspec->param[0] == 1 && fwspec->param[3] != 0 &&
1488-
gic_data.ppi_descs)
1489-
return d == partition_get_domain(gic_data.ppi_descs[fwspec->param[1]]);
1490-
1491-
return d == gic_data.domain;
1522+
ppi_idx = __gic_get_ppi_index(hwirq);
1523+
return d == partition_get_domain(gic_data.ppi_descs[ppi_idx]);
14921524
}
14931525

14941526
static const struct irq_domain_ops gic_irq_domain_ops = {
@@ -1503,7 +1535,9 @@ static int partition_domain_translate(struct irq_domain *d,
15031535
unsigned long *hwirq,
15041536
unsigned int *type)
15051537
{
1538+
unsigned long ppi_intid;
15061539
struct device_node *np;
1540+
unsigned int ppi_idx;
15071541
int ret;
15081542

15091543
if (!gic_data.ppi_descs)
@@ -1513,7 +1547,12 @@ static int partition_domain_translate(struct irq_domain *d,
15131547
if (WARN_ON(!np))
15141548
return -EINVAL;
15151549

1516-
ret = partition_translate_id(gic_data.ppi_descs[fwspec->param[1]],
1550+
ret = gic_irq_domain_translate(d, fwspec, &ppi_intid, type);
1551+
if (WARN_ON_ONCE(ret))
1552+
return 0;
1553+
1554+
ppi_idx = __gic_get_ppi_index(ppi_intid);
1555+
ret = partition_translate_id(gic_data.ppi_descs[ppi_idx],
15171556
of_node_to_fwnode(np));
15181557
if (ret < 0)
15191558
return ret;

0 commit comments

Comments
 (0)