From: wanghongliang wanghongliang@loongson.cn
LoongArch inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IBENRY CVE: NA
--------------------------------
Signed-off-by: wanghongliang wanghongliang@loongson.cn --- drivers/irqchip/irq-loongson-eiointc.c | 47 +++++++++++++++++++------- 1 file changed, 34 insertions(+), 13 deletions(-)
diff --git a/drivers/irqchip/irq-loongson-eiointc.c b/drivers/irqchip/irq-loongson-eiointc.c index 1c7f97dac83b..b4fbf52c7ef5 100644 --- a/drivers/irqchip/irq-loongson-eiointc.c +++ b/drivers/irqchip/irq-loongson-eiointc.c @@ -44,6 +44,16 @@
#define MAX_EIO_NODES (NR_CPUS / CORES_PER_EIO_NODE)
+typedef struct { DECLARE_BITMAP(bits, MAX_EIO_NODES); } extioi_node_map; + +#define EXTIOI_NODE_MASK_NONE \ +((extioi_node_map) { { \ + [0 ... BITS_TO_LONGS(MAX_EIO_NODES)-1] = 0UL \ +} }) + +extioi_node_map extioi_node_maps = EXTIOI_NODE_MASK_NONE; + + static int nr_pics;
struct eiointc_priv { @@ -79,6 +89,7 @@ static void eiointc_set_irq_route(int pos, unsigned int cpu, unsigned int mnode, int i, node, cpu_node, route_node; unsigned char coremap; uint32_t pos_off, data, data_byte, data_mask; + nodemask_t eio_node_map = *node_map;
pos_off = pos & ~3; data_byte = pos & 3; @@ -90,13 +101,14 @@ static void eiointc_set_irq_route(int pos, unsigned int cpu, unsigned int mnode,
for_each_online_cpu(i) { node = cpu_to_eio_node(i); - if (!node_isset(node, *node_map)) - continue; - - /* EIO node 0 is in charge of inter-node interrupt dispatch */ - route_node = (node == mnode) ? cpu_node : node; - data = ((coremap | (route_node << 4)) << (data_byte * 8)); - csr_any_send(EIOINTC_REG_ROUTE + pos_off, data, data_mask, node * CORES_PER_EIO_NODE); + if (node_isset(node, eio_node_map)) { + node_clear(node, eio_node_map); + /* EIO node 0 is in charge of inter-node interrupt dispatch */ + route_node = (node == mnode) ? cpu_node : node; + data = ((coremap | (route_node << 4)) << (data_byte * 8)); + csr_any_send(EIOINTC_REG_ROUTE + pos_off, data, data_mask, + cpu_logical_map(i)); + } } }
@@ -118,7 +130,7 @@ static void virt_extioi_set_irq_route(int irq, unsigned int cpu)
static int eiointc_set_irq_affinity(struct irq_data *d, const struct cpumask *affinity, bool force) { - unsigned int cpu; + unsigned int cpu, i; unsigned long flags; uint32_t vector, regaddr; struct cpumask intersect_affinity; @@ -143,16 +155,20 @@ static int eiointc_set_irq_affinity(struct irq_data *d, const struct cpumask *af virt_extioi_set_irq_route(vector, cpu); iocsr_write32(EIOINTC_ALL_ENABLE, regaddr); } else { + for_each_online_cpu(i) { + if (cpu_to_eio_node(i) == priv->node) + break; + } /* Mask target vector */ csr_any_send(regaddr, EIOINTC_ALL_ENABLE & (~BIT(vector & 0x1F)), - 0x0, priv->node * CORES_PER_EIO_NODE); + 0x0, cpu_logical_map(i));
/* Set route for target vector */ eiointc_set_irq_route(vector, cpu, priv->node, &priv->node_map);
/* Unmask target vector */ csr_any_send(regaddr, EIOINTC_ALL_ENABLE, - 0x0, priv->node * CORES_PER_EIO_NODE); + 0x0, cpu_logical_map(i)); }
irq_data_update_effective_affinity(d, cpumask_of(cpu)); @@ -187,7 +203,7 @@ static int eiointc_router_init(unsigned int cpu) return -1; }
- if ((cpu_logical_map(cpu) % cores) == 0) { + if (!test_bit(node, (&extioi_node_maps)->bits)) { eiointc_enable();
for (i = 0; i < eiointc_priv[0]->vec_count / 32; i++) { @@ -208,7 +224,9 @@ static int eiointc_router_init(unsigned int cpu) else if (index == 0) bit = BIT(cpu_logical_map(0)); else - bit = (eiointc_priv[index]->node << 4) | 1; + bit = (eiointc_priv[index]->node << 4) | + BIT(cpu_logical_map(smp_processor_id()) % + CORES_PER_EIO_NODE);
data = bit | (bit << 8) | (bit << 16) | (bit << 24); iocsr_write32(data, EIOINTC_REG_ROUTE + i * 4); @@ -217,8 +235,10 @@ static int eiointc_router_init(unsigned int cpu) for (i = 0; i < eiointc_priv[0]->vec_count / 32; i++) { data = 0xffffffff; iocsr_write32(data, EIOINTC_REG_ENABLE + i * 4); - iocsr_write32(data, EIOINTC_REG_BOUNCE + i * 4); + iocsr_write32(0, EIOINTC_REG_BOUNCE + i * 4); } + + set_bit(node, (&extioi_node_maps)->bits); }
return 0; @@ -348,6 +368,7 @@ static int eiointc_suspend(void)
static void eiointc_resume(void) { + extioi_node_maps = EXTIOI_NODE_MASK_NONE; eiointc_router_init(0); }