Skip to content

Commit f79a655

Browse files
Jing Liopsiff
authored andcommitted
sw64: irqchip: add support for PINTC on all NUMA nodes
Now, devices located outside NUMA node 0 can also report interrupts to PINTC. Signed-off-by: Jing Li <[email protected]> Reviewed-by: He Sheng <[email protected]> Signed-off-by: Gu Zitao <[email protected]>
1 parent 45422f1 commit f79a655

File tree

2 files changed

+61
-47
lines changed

2 files changed

+61
-47
lines changed

arch/sw_64/include/asm/hw_irq.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ DECLARE_PER_CPU(unsigned long, irq_pmi_count);
99

1010
#define ACTUAL_NR_IRQS nr_irqs
1111

12-
extern struct irq_domain *mcu_irq_domain;
13-
1412
#ifdef CONFIG_PCI_MSI
1513
typedef unsigned int vector_irq_t[PERCPU_MSI_IRQS];
1614
DECLARE_PER_CPU(vector_irq_t, vector_irq);

drivers/irqchip/irq-sunway-pintc.c

Lines changed: 61 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -67,14 +67,16 @@
6767
#define OFFSET_ADR_INT_CONFIG 0x1580UL /* PINTC version >= 2 */
6868
#define OFFSET_DEVINTWK_INTEN 0x1600UL
6969

70-
#define SW_PINTC_MCU_GSI_BASE 64
70+
#define PINTC_GSI_BASE(node) (64 + 512 * (node))
7171

7272
#define INTPU_BASE_V1 0x802a00000000
7373
#define INTPU_SIZE_V1 0x1680
7474

7575
#define MCU_BASE_V1 0x803000000000
7676
#define MCU_SIZE_V1 0x8f00
7777

78+
#define SUNWAY_MAX_NODES 8
79+
7880
DECLARE_PER_CPU(unsigned long, hard_node_id);
7981

8082
struct pintc_chip_data {
@@ -89,13 +91,13 @@ struct pintc_chip_data {
8991
raw_spinlock_t mcu_lock;
9092
};
9193

92-
static struct pintc_chip_data *chip_datas[MAX_NUMNODES];
94+
static struct pintc_chip_data *chip_datas[SUNWAY_MAX_NODES];
9395

9496
static struct pintc_chip_data *pintc_alloc_chip_data(u32 node)
9597
{
9698
struct pintc_chip_data *chip_data;
9799

98-
if (WARN_ON(node >= MAX_NUMNODES))
100+
if (WARN_ON(node >= SUNWAY_MAX_NODES))
99101
return NULL;
100102

101103
chip_data = kzalloc_node(sizeof(struct pintc_chip_data),
@@ -111,7 +113,7 @@ static void pintc_free_chip_data(struct pintc_chip_data *chip_data)
111113
if (!chip_data)
112114
return;
113115

114-
if (WARN_ON((chip_data->node >= MAX_NUMNODES) ||
116+
if (WARN_ON((chip_data->node >= SUNWAY_MAX_NODES) ||
115117
(chip_datas[chip_data->node] != chip_data)))
116118
return;
117119

@@ -285,13 +287,14 @@ static int mcu_irq_set_affinity(struct irq_data *irq_data,
285287
return assign_mcu_irq_config(chip_data, &targets);
286288
}
287289

288-
static struct irq_chip pintc_mcu_chip = {
289-
.name = "MCU-INT",
290-
.irq_enable = mcu_irq_enable,
291-
.irq_disable = mcu_irq_disable,
292-
.irq_mask = mcu_irq_disable,
293-
.irq_unmask = mcu_irq_enable,
294-
.irq_set_affinity = mcu_irq_set_affinity,
290+
static struct irq_chip pintc_mcu_chips[SUNWAY_MAX_NODES] = {
291+
[0 ... SUNWAY_MAX_NODES - 1] = {
292+
.irq_enable = mcu_irq_enable,
293+
.irq_disable = mcu_irq_disable,
294+
.irq_mask = mcu_irq_disable,
295+
.irq_unmask = mcu_irq_enable,
296+
.irq_set_affinity = mcu_irq_set_affinity,
297+
}
295298
};
296299

297300
static struct irq_chip pintc_mcu_vt_chip = {
@@ -303,6 +306,9 @@ static int pintc_mcu_translate(struct irq_domain *domain,
303306
unsigned long *hwirq,
304307
unsigned int *type)
305308
{
309+
struct pintc_chip_data *chip_data = domain->host_data;
310+
u32 node = chip_data->node;
311+
306312
if (WARN_ON(fwspec->param_count < 1))
307313
return -EINVAL;
308314

@@ -315,9 +321,9 @@ static int pintc_mcu_translate(struct irq_domain *domain,
315321

316322
/* ACPI */
317323
if (is_fwnode_irqchip(fwspec->fwnode)) {
318-
if (WARN_ON(fwspec->param[0] < SW_PINTC_MCU_GSI_BASE))
324+
if (WARN_ON(fwspec->param[0] < PINTC_GSI_BASE(node)))
319325
return -EINVAL;
320-
*hwirq = fwspec->param[0] - SW_PINTC_MCU_GSI_BASE;
326+
*hwirq = fwspec->param[0] - PINTC_GSI_BASE(node);
321327
*type = IRQ_TYPE_NONE;
322328
return 0;
323329
}
@@ -376,13 +382,14 @@ static const struct irq_domain_ops pintc_mcu_domain_ops = {
376382
.free = pintc_mcu_free_irqs,
377383
};
378384

379-
struct irq_domain *mcu_irq_domain;
380-
EXPORT_SYMBOL(mcu_irq_domain);
385+
static struct irq_domain *mcu_domains[SUNWAY_MAX_NODES];
381386

382387
static int __init pintc_init_mcu(struct pintc_chip_data *chip_data,
383388
struct fwnode_handle *handle)
384389
{
385390
unsigned int mcu_irq_num = chip_data->mcu_irq_num;
391+
u32 node = chip_data->node;
392+
char *chip_name;
386393

387394
if (chip_data->vt) {
388395
chip_data->mcu_chip = &pintc_mcu_vt_chip;
@@ -392,25 +399,37 @@ static int __init pintc_init_mcu(struct pintc_chip_data *chip_data,
392399
* "irq_domain_create_legacy", we have to call
393400
* "__irq_domain_add" directly.
394401
*/
395-
mcu_irq_domain = __irq_domain_add(handle, mcu_irq_num,
402+
mcu_domains[node] = __irq_domain_add(handle, mcu_irq_num,
396403
mcu_irq_num, 0, &pintc_mcu_domain_ops,
397404
chip_data);
398-
if (mcu_irq_domain)
399-
irq_domain_associate_many(mcu_irq_domain,
405+
if (mcu_domains[node])
406+
irq_domain_associate_many(mcu_domains[node],
400407
0, 0, mcu_irq_num);
401408
} else {
402-
chip_data->mcu_chip = &pintc_mcu_chip;
403-
mcu_irq_domain = irq_domain_create_linear(handle, mcu_irq_num,
409+
chip_data->mcu_chip = &pintc_mcu_chips[node];
410+
411+
chip_name = kzalloc_node(sizeof("MCUX-INT"), GFP_KERNEL, node);
412+
if (!chip_name)
413+
return -ENOMEM;
414+
415+
snprintf(chip_name, sizeof("MCUX-INT"), "MCU%u-INT", node);
416+
chip_data->mcu_chip->name = chip_name;
417+
418+
mcu_domains[node] = irq_domain_create_linear(handle, mcu_irq_num,
404419
&pintc_mcu_domain_ops, chip_data);
420+
405421
/* Mask all interrupts for now */
406422
writeq(0x0, chip_data->mcu_base + OFFSET_MCU_DVC_INT_EN);
407423

408-
/* When building the root domain, move it to a better location */
409-
if (mcu_irq_domain)
424+
if (mcu_domains[node])
410425
pintc_mcu_enable(chip_data->pintc_base);
426+
else {
427+
chip_data->mcu_chip->name = NULL;
428+
kfree(chip_name);
429+
}
411430
}
412431

413-
if (!mcu_irq_domain) {
432+
if (!mcu_domains[node]) {
414433
pr_err("failed to create MCU irq domain\n");
415434
return -ENOMEM;
416435
}
@@ -424,24 +443,24 @@ static int __init pintc_init_mcu(struct pintc_chip_data *chip_data,
424443
return 0;
425444
}
426445

427-
/* Currently, only MCU controller on node 0 is supported */
428446
void handle_dev_int(struct pt_regs *regs)
429447
{
430448
unsigned long stat, val;
431449
unsigned int hwirq;
450+
u32 node = __this_cpu_read(hard_node_id);
432451

433452
/* Disable global irq of MCU due to some hardware reasons */
434-
val = pintc_mcu_disable_and_save(chip_datas[0]);
453+
val = pintc_mcu_disable_and_save(chip_datas[node]);
435454

436-
stat = readq(chip_datas[0]->mcu_base + OFFSET_MCU_DVC_INT);
455+
stat = readq(chip_datas[node]->mcu_base + OFFSET_MCU_DVC_INT);
437456

438457
while (stat) {
439458
hwirq = ffs(stat) - 1;
440-
generic_handle_domain_irq(mcu_irq_domain, hwirq);
459+
generic_handle_domain_irq(mcu_domains[node], hwirq);
441460
stat &= ~(1UL << hwirq);
442461
}
443462

444-
pintc_mcu_restore(chip_datas[0], val);
463+
pintc_mcu_restore(chip_datas[node], val);
445464
}
446465

447466
void handle_fault_int(void)
@@ -487,13 +506,6 @@ void handle_fault_int(void)
487506
static int __init pintc_of_init_mcu(struct pintc_chip_data *chip_data,
488507
struct device_node *pintc)
489508
{
490-
/* Not yet supported */
491-
if (chip_data->node > 0) {
492-
pr_info("MCU version [%u] on node [%u] skipped\n",
493-
chip_data->version, chip_data->node);
494-
return 0;
495-
}
496-
497509
return pintc_init_mcu(chip_data, of_node_to_fwnode(pintc));
498510
}
499511

@@ -608,6 +620,7 @@ enum sw_pintc_sub_type {
608620
static int __init lpc_intc_parse_madt(union acpi_subtable_headers *header,
609621
const unsigned long end)
610622
{
623+
static bool initialized[SUNWAY_MAX_NODES];
611624
struct acpi_madt_sw_lpc_intc *lpc_intc;
612625

613626
lpc_intc = (struct acpi_madt_sw_lpc_intc *)header;
@@ -616,13 +629,22 @@ static int __init lpc_intc_parse_madt(union acpi_subtable_headers *header,
616629
if (lpc_intc->node > 0)
617630
return 0;
618631

632+
if (initialized[lpc_intc->node])
633+
return 0;
634+
635+
/* LPC controller is the child of MCU controller */
636+
if (!mcu_domains[lpc_intc->node])
637+
return 0;
638+
619639
if ((lpc_intc->version == ACPI_MADT_SW_LPC_INTC_VERSION_NONE) ||
620640
(lpc_intc->version >= ACPI_MADT_SW_LPC_INTC_VERSION_RESERVED)) {
621641
pr_err("invalid LPC-INTC version\n");
622642
return -EINVAL;
623643
}
624644

625-
return lpc_intc_acpi_init(mcu_irq_domain, lpc_intc);
645+
initialized[lpc_intc->node] = true;
646+
647+
return lpc_intc_acpi_init(mcu_domains[lpc_intc->node], lpc_intc);
626648
}
627649

628650
static bool __init
@@ -642,22 +664,16 @@ static int __init pintc_acpi_init_mcu(struct pintc_chip_data *chip_data,
642664
struct acpi_madt_sw_sub_pintc *mcu)
643665
{
644666
struct fwnode_handle *handle;
667+
u32 node = chip_data->node;
645668
int ret;
646669

647-
/* Not yet supported */
648-
if (chip_data->node > 0) {
649-
pr_info("MCU version [%u] on node [%u] skipped\n",
650-
chip_data->version, chip_data->node);
651-
return 0;
652-
}
653-
654670
if (!mcu->status) {
655671
pr_info("MCU version [%u] on node [%u] disabled\n",
656672
chip_data->version, chip_data->node);
657673
return 0;
658674
}
659675

660-
if (mcu->gsi_base != SW_PINTC_MCU_GSI_BASE) {
676+
if (mcu->gsi_base != PINTC_GSI_BASE(node)) {
661677
pr_err("invalid MCU GSI\n");
662678
return -EINVAL;
663679
}
@@ -694,7 +710,7 @@ static int __init pintc_acpi_init_mcu(struct pintc_chip_data *chip_data,
694710
return 0;
695711

696712
out_acpi_free_mcu_domain:
697-
irq_domain_remove(mcu_irq_domain);
713+
irq_domain_remove(mcu_domains[node]);
698714
out_acpi_unmap_mcu:
699715
iounmap(chip_data->mcu_base);
700716
out_acpi_free_fwnode:

0 commit comments

Comments
 (0)