1 | Fix return value checking of eiointc_index where int type | 1 | Fix return value checking of eiointc_index where int type |
---|---|---|---|
2 | is converted uint32_t and check smaller than 0. | 2 | is converted uint32_t and check smaller than 0. |
3 | 3 | ||
4 | Add simple irq route support on system with only one eioi node, | 4 | Add simple irq route support on system with only one eiointc node, |
5 | rather than use anysend method. | 5 | rather than use anysend method. |
6 | 6 | ||
7 | --- | 7 | --- |
8 | Changes in v5: | ||
9 | Modify typo issue. | ||
10 | |||
11 | Changes in v4: | ||
12 | Modify some spell checking problems. | ||
13 | Add Fixes tag. | ||
14 | |||
15 | Changes in v3: | ||
16 | Modify some spell checking problems. | ||
17 | |||
8 | Changes in v2: | 18 | Changes in v2: |
9 | Use the simple irq routing on embeded board like 2K0500 and 2K2000 | 19 | Use the simple irq routing on embeded board like 2K0500 and 2K2000 |
10 | board, since there is only one eio node. | 20 | board, since there is only one eio node. |
11 | 21 | ||
12 | --- | 22 | --- |
13 | Bibo Mao (2): | 23 | Bibo Mao (2): |
14 | irqchip/loongson-eiointc: fix return value checking of eiointc_index | 24 | irqchip/loongson-eiointc: Fix return value checking of eiointc_index |
15 | irqchip/loongson-eiointc: simplify irq route on one eioi-node system | 25 | irqchip/loongson-eiointc: Simplify irq routing on some platforms |
16 | 26 | ||
17 | drivers/irqchip/irq-loongson-eiointc.c | 91 ++++++++++++++++++++++---- | 27 | drivers/irqchip/irq-loongson-eiointc.c | 93 +++++++++++++++++++++++--- |
18 | 1 file changed, 80 insertions(+), 11 deletions(-) | 28 | 1 file changed, 82 insertions(+), 11 deletions(-) |
19 | 29 | ||
20 | base-commit: d528014517f2b0531862c02865b9d4c908019dc4 | ||
21 | -- | 30 | -- |
22 | 2.27.0 | 31 | 2.27.0 | diff view generated by jsdifflib |
1 | return value of function eiointc_index is int, however it is | 1 | Return value of function eiointc_index is int, however it is converted |
---|---|---|---|
2 | converted uint32_t when used. This causes logic problem when | 2 | into uint32_t and then compared smaller than zero. This causes logic |
3 | checking return value. There is eioi initial problem on qemu | 3 | problem. There is eiointc initialization problem on qemu virt-machine |
4 | virt-machine where there is only one eioi node and more than 4 | 4 | where there is only one eiointc node and more than 4 vcpus. Nodemap of |
5 | vcpus, external device intr can only be routed to vcpu 0-3. | 5 | eiointc is 1, and external device intr can only be routed to vcpu 0-3, the |
6 | other vcpus can not response any external device interrupts and only local | ||
7 | processor interrupts like ipi/timer can work. | ||
6 | 8 | ||
9 | Fixes: dd281e1a1a93 ("irqchip: Add Loongson Extended I/O interrupt controller support") | ||
7 | Signed-off-by: Bibo Mao <maobibo@loongson.cn> | 10 | Signed-off-by: Bibo Mao <maobibo@loongson.cn> |
11 | Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> | ||
8 | --- | 12 | --- |
9 | drivers/irqchip/irq-loongson-eiointc.c | 12 +++++++----- | 13 | drivers/irqchip/irq-loongson-eiointc.c | 13 ++++++++----- |
10 | 1 file changed, 7 insertions(+), 5 deletions(-) | 14 | 1 file changed, 8 insertions(+), 5 deletions(-) |
11 | 15 | ||
12 | diff --git a/drivers/irqchip/irq-loongson-eiointc.c b/drivers/irqchip/irq-loongson-eiointc.c | 16 | diff --git a/drivers/irqchip/irq-loongson-eiointc.c b/drivers/irqchip/irq-loongson-eiointc.c |
13 | index XXXXXXX..XXXXXXX 100644 | 17 | index XXXXXXX..XXXXXXX 100644 |
14 | --- a/drivers/irqchip/irq-loongson-eiointc.c | 18 | --- a/drivers/irqchip/irq-loongson-eiointc.c |
15 | +++ b/drivers/irqchip/irq-loongson-eiointc.c | 19 | +++ b/drivers/irqchip/irq-loongson-eiointc.c |
... | ... | ||
23 | - if (index < 0) { | 27 | - if (index < 0) { |
24 | - pr_err("Error: invalid nodemap!\n"); | 28 | - pr_err("Error: invalid nodemap!\n"); |
25 | - return -1; | 29 | - return -1; |
26 | - } | 30 | - } |
27 | + /* | 31 | + /* |
28 | + * qemu virt-machine has only one eio intc and more than four cpus | 32 | + * Qemu virt-machine has only one eiointc and more than four cpus. |
29 | + * irq from eio can only be routed to cpu 0-3 on virt machine | 33 | + * Irq from eiointc can only be routed to cpu 0-3, cpus except 0-3 |
34 | + * need not initialize eiointc on virt-machine | ||
30 | + */ | 35 | + */ |
31 | + if (index < 0) | 36 | + if (index < 0) |
32 | + return 0; | 37 | + return 0; |
33 | 38 | ||
34 | if ((cpu_logical_map(cpu) % CORES_PER_EIO_NODE) == 0) { | 39 | if ((cpu_logical_map(cpu) % CORES_PER_EIO_NODE) == 0) { |
35 | eiointc_enable(); | 40 | eiointc_enable(); |
36 | -- | 41 | -- |
37 | 2.27.0 | 42 | 2.27.0 |
43 | diff view generated by jsdifflib |
1 | Some LoongArch systems has only one eioi node such as 3A5000/2K2000 | 1 | Some LoongArch systems have only one eiointc node such as 3A5000/2K2000 |
---|---|---|---|
2 | and qemu virt machine. If there is only one eioi node, all cpus can | 2 | and qemu virt-machine. If there is only one eiointc node, all cpus can |
3 | access eioi register directly; if there is multiple eioi nodes, cpus | 3 | access eiointc registers directly; if there is multiple eiointc nodes, each |
4 | can only access specified eioi node, so anysend or ipi need be used | 4 | cpu can only access eiointc belonging to specified node group, so anysend |
5 | to configure irq routing. IRQ routing is simple on such system with | 5 | or ipi needs to be used to configure irq routing. IRQ routing is simple on |
6 | one node, hacking method like anysend is not necessary. | 6 | such systems with one node, method like anysend is not necessary. |
7 | 7 | ||
8 | This patch is tested on 3A5000 board and qemu virt machine. | 8 | This patch provides simpile IRQ routing method for systems with one eiointc |
9 | node, and is tested on 3A5000 board and qemu virt-machine. | ||
9 | 10 | ||
10 | Signed-off-by: Bibo Mao <maobibo@loongson.cn> | 11 | Signed-off-by: Bibo Mao <maobibo@loongson.cn> |
11 | --- | 12 | --- |
12 | drivers/irqchip/irq-loongson-eiointc.c | 79 ++++++++++++++++++++++++-- | 13 | drivers/irqchip/irq-loongson-eiointc.c | 80 ++++++++++++++++++++++++-- |
13 | 1 file changed, 73 insertions(+), 6 deletions(-) | 14 | 1 file changed, 74 insertions(+), 6 deletions(-) |
14 | 15 | ||
15 | diff --git a/drivers/irqchip/irq-loongson-eiointc.c b/drivers/irqchip/irq-loongson-eiointc.c | 16 | diff --git a/drivers/irqchip/irq-loongson-eiointc.c b/drivers/irqchip/irq-loongson-eiointc.c |
16 | index XXXXXXX..XXXXXXX 100644 | 17 | index XXXXXXX..XXXXXXX 100644 |
17 | --- a/drivers/irqchip/irq-loongson-eiointc.c | 18 | --- a/drivers/irqchip/irq-loongson-eiointc.c |
18 | +++ b/drivers/irqchip/irq-loongson-eiointc.c | 19 | +++ b/drivers/irqchip/irq-loongson-eiointc.c |
... | ... | ||
39 | + regaddr = EIOINTC_REG_ENABLE + ((vector >> 5) << 2); | 40 | + regaddr = EIOINTC_REG_ENABLE + ((vector >> 5) << 2); |
40 | + data = ~BIT(vector & 0x1F); | 41 | + data = ~BIT(vector & 0x1F); |
41 | + coremap = BIT(cpu_logical_map(cpu) % CORES_PER_EIO_NODE); | 42 | + coremap = BIT(cpu_logical_map(cpu) % CORES_PER_EIO_NODE); |
42 | + | 43 | + |
43 | + /* | 44 | + /* |
44 | + * simplify for only one eio node | 45 | + * simplify for platform with only one eiointc node |
45 | + * access eio registers directly rather than | 46 | + * access eiointc registers directly rather than |
46 | + * use any_send hack method here | 47 | + * use any_send method here |
47 | + */ | 48 | + */ |
48 | + raw_spin_lock_irqsave(&affinity_lock, flags); | 49 | + raw_spin_lock_irqsave(&affinity_lock, flags); |
49 | + iocsr_write32(EIOINTC_ALL_ENABLE & data, regaddr); | 50 | + iocsr_write32(EIOINTC_ALL_ENABLE & data, regaddr); |
50 | + /* | 51 | + /* |
51 | + * get irq route info for continuous 4 vectors | 52 | + * get irq route info for continuous 4 vectors |
... | ... | ||
67 | int i; | 68 | int i; |
68 | @@ -XXX,XX +XXX,XX @@ static struct irq_chip eiointc_irq_chip = { | 69 | @@ -XXX,XX +XXX,XX @@ static struct irq_chip eiointc_irq_chip = { |
69 | .irq_set_affinity = eiointc_set_irq_affinity, | 70 | .irq_set_affinity = eiointc_set_irq_affinity, |
70 | }; | 71 | }; |
71 | 72 | ||
72 | +static struct irq_chip eiointc_irq_chipi_single = { | 73 | +static struct irq_chip eiointc_irq_chip_single = { |
73 | + .name = "EIOINTC-S", | 74 | + .name = "EIOINTC-S", |
74 | + .irq_ack = eiointc_ack_irq, | 75 | + .irq_ack = eiointc_ack_irq, |
75 | + .irq_mask = eiointc_mask_irq, | 76 | + .irq_mask = eiointc_mask_irq, |
76 | + .irq_unmask = eiointc_unmask_irq, | 77 | + .irq_unmask = eiointc_unmask_irq, |
77 | +#ifdef CONFIG_SMP | 78 | +#ifdef CONFIG_SMP |
... | ... | ||
94 | return ret; | 95 | return ret; |
95 | 96 | ||
96 | - for (i = 0; i < nr_irqs; i++) { | 97 | - for (i = 0; i < nr_irqs; i++) { |
97 | - irq_domain_set_info(domain, virq + i, hwirq + i, &eiointc_irq_chip, | 98 | - irq_domain_set_info(domain, virq + i, hwirq + i, &eiointc_irq_chip, |
98 | + /* | 99 | + /* |
99 | + * use simple irq route method for single node eiointc | 100 | + * use simple irq routing method on single eiointc node |
100 | + */ | 101 | + */ |
101 | + if ((nr_pics == 1) && (nodes_weight(priv->node_map) == 1)) | 102 | + if ((nr_pics == 1) && (nodes_weight(priv->node_map) == 1)) |
102 | + chip = &eiointc_irq_chipi_single; | 103 | + chip = &eiointc_irq_chip_single; |
103 | + else | 104 | + else |
104 | + chip = &eiointc_irq_chip; | 105 | + chip = &eiointc_irq_chip; |
105 | + for (i = 0; i < nr_irqs; i++) | 106 | + for (i = 0; i < nr_irqs; i++) |
106 | + irq_domain_set_info(domain, virq + i, hwirq + i, chip, | 107 | + irq_domain_set_info(domain, virq + i, hwirq + i, chip, |
107 | priv, handle_edge_irq, NULL, NULL); | 108 | priv, handle_edge_irq, NULL, NULL); |
... | ... | ||
131 | priv->node = 0; | 132 | priv->node = 0; |
132 | priv->domain_handle = of_node_to_fwnode(of_node); | 133 | priv->domain_handle = of_node_to_fwnode(of_node); |
133 | 134 | ||
134 | - ret = eiointc_init(priv, parent_irq, 0); | 135 | - ret = eiointc_init(priv, parent_irq, 0); |
135 | + /* | 136 | + /* |
136 | + * 2k0500 and 2k2000 has only one eio node | 137 | + * 2k0500 and 2k2000 has only one eiointc node |
137 | + * set nodemap as 1 for simple irq routing | 138 | + * set nodemap as 1 for simple irq routing |
138 | + * what about for future embedded board more than 4 cpus?? | 139 | + * |
140 | + * Fixme: what about future embedded boards with more than 4 cpus? | ||
139 | + * nodemap and node need be added in dts like acpi table | 141 | + * nodemap and node need be added in dts like acpi table |
140 | + */ | 142 | + */ |
141 | + ret = eiointc_init(priv, parent_irq, 1); | 143 | + ret = eiointc_init(priv, parent_irq, 1); |
142 | if (ret < 0) | 144 | if (ret < 0) |
143 | goto out_free_priv; | 145 | goto out_free_priv; |
144 | 146 | ||
145 | -- | 147 | -- |
146 | 2.27.0 | 148 | 2.27.0 | diff view generated by jsdifflib |