@@ -446,18 +446,23 @@ static void gic_irq_set_prio(struct irq_data *d, u8 prio)
446
446
writeb_relaxed (prio , base + offset + index );
447
447
}
448
448
449
- static u32 gic_get_ppi_index ( struct irq_data * d )
449
+ static u32 __gic_get_ppi_index ( irq_hw_number_t hwirq )
450
450
{
451
- switch (get_intid_range ( d )) {
451
+ switch (__get_intid_range ( hwirq )) {
452
452
case PPI_RANGE :
453
- return d -> hwirq - 16 ;
453
+ return hwirq - 16 ;
454
454
case EPPI_RANGE :
455
- return d -> hwirq - EPPI_BASE_INTID + 16 ;
455
+ return hwirq - EPPI_BASE_INTID + 16 ;
456
456
default :
457
457
unreachable ();
458
458
}
459
459
}
460
460
461
+ static u32 gic_get_ppi_index (struct irq_data * d )
462
+ {
463
+ return __gic_get_ppi_index (d -> hwirq );
464
+ }
465
+
461
466
static int gic_irq_nmi_setup (struct irq_data * d )
462
467
{
463
468
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,
1467
1472
}
1468
1473
}
1469
1474
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
+
1470
1496
static int gic_irq_domain_select (struct irq_domain * d ,
1471
1497
struct irq_fwspec * fwspec ,
1472
1498
enum irq_domain_bus_token bus_token )
1473
1499
{
1500
+ unsigned int type , ret , ppi_idx ;
1501
+ irq_hw_number_t hwirq ;
1502
+
1474
1503
/* Not for us */
1475
1504
if (fwspec -> fwnode != d -> fwnode )
1476
1505
return 0 ;
@@ -1479,16 +1508,19 @@ static int gic_irq_domain_select(struct irq_domain *d,
1479
1508
if (!is_of_node (fwspec -> fwnode ))
1480
1509
return 1 ;
1481
1510
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
+
1482
1518
/*
1483
1519
* If this is a PPI and we have a 4th (non-null) parameter,
1484
1520
* then we need to match the partition domain.
1485
1521
*/
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 ]);
1492
1524
}
1493
1525
1494
1526
static const struct irq_domain_ops gic_irq_domain_ops = {
@@ -1503,7 +1535,9 @@ static int partition_domain_translate(struct irq_domain *d,
1503
1535
unsigned long * hwirq ,
1504
1536
unsigned int * type )
1505
1537
{
1538
+ unsigned long ppi_intid ;
1506
1539
struct device_node * np ;
1540
+ unsigned int ppi_idx ;
1507
1541
int ret ;
1508
1542
1509
1543
if (!gic_data .ppi_descs )
@@ -1513,7 +1547,12 @@ static int partition_domain_translate(struct irq_domain *d,
1513
1547
if (WARN_ON (!np ))
1514
1548
return - EINVAL ;
1515
1549
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 ],
1517
1556
of_node_to_fwnode (np ));
1518
1557
if (ret < 0 )
1519
1558
return ret ;
0 commit comments