From patchwork Wed Aug 28 07:06:02 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bibo Mao X-Patchwork-Id: 13780784 Received: from mail.loongson.cn (mail.loongson.cn [114.242.206.163]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 615191552EB; Wed, 28 Aug 2024 07:06:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=114.242.206.163 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724828769; cv=none; b=ow77S5JQExqs08/HqUKjof5hgva8SLX9HgDDAVc4pd1TfykhC8sMWFdNjjwRxOFG47ua0NaJy9K7oZ8It3fleBxqv6uJ4ssSGZ85wJj54SGHBA4QNK/4F1PyR3YbYQGm9x2xwGQL1uHRjm4T3L3cJWHlRrympyKi3wDI3N4vRbA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724828769; c=relaxed/simple; bh=nizlCHfbuoGImdFJM4bzVM7rc1oIMDc3cMJIQ6PswdM=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=ONPZ8Q0oOOLih4M8h8CCcQrUfINu8qPFXIERraOUQPtn7u271cY/55Uidr/AI8tjHXDLz1uYT9f2KKI32FrimGHACsZOWiy++BKrzAC8AcGnEoara2PUeAavhSKxFV3UsIW/lyNEfQR6EHNUBjOXGvYn18riFA0co5Tls/Npdpo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn; spf=pass smtp.mailfrom=loongson.cn; arc=none smtp.client-ip=114.242.206.163 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=loongson.cn Received: from loongson.cn (unknown [10.2.5.213]) by gateway (Coremail) with SMTP id _____8Bx6elczM5m4nsiAA--.4290S3; Wed, 28 Aug 2024 15:06:04 +0800 (CST) Received: from localhost.localdomain (unknown [10.2.5.213]) by front1 (Coremail) with SMTP id qMiowMCxB2ZbzM5m5UglAA--.2269S3; Wed, 28 Aug 2024 15:06:04 +0800 (CST) From: Bibo Mao To: Huacai Chen , Jianmin Lv Cc: WANG Xuerui , Thomas Gleixner , loongarch@lists.linux.dev, linux-kernel@vger.kernel.org, linux-mips@vger.kernel.org Subject: [RFC v2 1/2] irqchip/loongson-eiointc: Route interrupt parsed from acpi table Date: Wed, 28 Aug 2024 15:06:02 +0800 Message-Id: <20240828070603.3518753-2-maobibo@loongson.cn> X-Mailer: git-send-email 2.39.3 In-Reply-To: <20240828070603.3518753-1-maobibo@loongson.cn> References: <20240828070603.3518753-1-maobibo@loongson.cn> Precedence: bulk X-Mailing-List: linux-mips@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: qMiowMCxB2ZbzM5m5UglAA--.2269S3 X-CM-SenderInfo: xpdruxter6z05rqj20fqof0/ X-Coremail-Antispam: 1Uk129KBjDUn29KB7ZKAUJUUUUU529EdanIXcx71UUUUU7KY7 ZEXasCq-sGcSsGvfJ3UbIjqfuFe4nvWSU5nxnvy29KBjDU0xBIdaVrnUUvcSsGvfC2Kfnx nUUI43ZEXa7xR_UUUUUUUUU== Interrupt controller eiointc routes irq to cpu interface IP0 - IP7, now it is hard-coded that eiointc routes irq to CPU started from IP1. It can be parsed from acpi table, instead hwirq is used for function irq_create_mapping() already, routed interrupt pin must be the same with parent hwirq. Signed-off-by: Bibo Mao --- drivers/irqchip/irq-loongson-eiointc.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/irqchip/irq-loongson-eiointc.c b/drivers/irqchip/irq-loongson-eiointc.c index b1f2080be2be..e9ec63d85ee8 100644 --- a/drivers/irqchip/irq-loongson-eiointc.c +++ b/drivers/irqchip/irq-loongson-eiointc.c @@ -42,6 +42,7 @@ struct eiointc_priv { cpumask_t cpuspan_map; struct fwnode_handle *domain_handle; struct irq_domain *eiointc_domain; + int parent_hwirq; }; static struct eiointc_priv *eiointc_priv[MAX_IO_PICS]; @@ -159,7 +160,12 @@ static int eiointc_router_init(unsigned int cpu) } for (i = 0; i < eiointc_priv[0]->vec_count / 32 / 4; i++) { - bit = BIT(1 + index); /* Route to IP[1 + index] */ + /* + * Route to interrupt pin, using offset minus INT_HWI0 + * Offset 0 means IP0 and so on + * Every 32 vector routing to one interrupt pin + */ + bit = BIT(eiointc_priv[index]->parent_hwirq - INT_HWI0); data = bit | (bit << 8) | (bit << 16) | (bit << 24); iocsr_write32(data, EIOINTC_REG_IPMAP + i * 4); } @@ -424,7 +430,7 @@ int __init eiointc_acpi_init(struct irq_domain *parent, priv->vec_count = VEC_COUNT; priv->node = acpi_eiointc->node; - + priv->parent_hwirq = acpi_eiointc->cascade; parent_irq = irq_create_mapping(parent, acpi_eiointc->cascade); ret = eiointc_init(priv, parent_irq, acpi_eiointc->node_map); @@ -458,6 +464,7 @@ static int __init eiointc_of_init(struct device_node *of_node, { int parent_irq, ret; struct eiointc_priv *priv; + struct irq_data *irq_data; priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) @@ -473,6 +480,12 @@ static int __init eiointc_of_init(struct device_node *of_node, if (ret < 0) goto out_free_priv; + irq_data = irq_get_irq_data(parent_irq); + if (!irq_data) { + ret = -ENODEV; + goto out_free_priv; + } + /* * In particular, the number of devices supported by the LS2K0500 * extended I/O interrupt vector is 128. @@ -484,7 +497,7 @@ static int __init eiointc_of_init(struct device_node *of_node, priv->node = 0; priv->domain_handle = of_node_to_fwnode(of_node); - + priv->parent_hwirq = irqd_to_hwirq(irq_data); ret = eiointc_init(priv, parent_irq, 0); if (ret < 0) goto out_free_priv; From patchwork Wed Aug 28 07:06:03 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bibo Mao X-Patchwork-Id: 13780786 Received: from mail.loongson.cn (mail.loongson.cn [114.242.206.163]) by smtp.subspace.kernel.org (Postfix) with ESMTP id A6D5B158524; Wed, 28 Aug 2024 07:06:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=114.242.206.163 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724828771; cv=none; b=f7CfbtZZQRprAC/GYL0IWU6cO95xocD3+h9B0nyix+TVwrSC7H8hhpBsmcFM1oZefKGNAPmUPXHRj6qUk4qqqcaGLuGnxzJ02KAO3D42Rlirgp9MbiBshOvnGGhHhSHSri6hTD3pEl5HQznn1o6L6bV1Ma3AxmSMJA0TQ9J8rqw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724828771; c=relaxed/simple; bh=Unnar+DNJSX+QG8uYqeEe63Eu0xTKLVIO8iZd6HyRTw=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=pga40vNFadCTFe2aEa68RsokOWCeCfMqtmiS2cwtSOvyUr3uaVgWXhqNz3du/GjPJSq97QoFMS0vp2FxZjEvkHf2gDJ6zW/H3yu074+vd2TQw1G4g0tQrBOEQ8l1amuGtE/5EeH3ClDN2TO6LRhRrolOv5IuCb8AlsPDDgF6RO8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn; spf=pass smtp.mailfrom=loongson.cn; arc=none smtp.client-ip=114.242.206.163 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=loongson.cn Received: from loongson.cn (unknown [10.2.5.213]) by gateway (Coremail) with SMTP id _____8DxOJpezM5m6HsiAA--.32536S3; Wed, 28 Aug 2024 15:06:06 +0800 (CST) Received: from localhost.localdomain (unknown [10.2.5.213]) by front1 (Coremail) with SMTP id qMiowMCxB2ZbzM5m5UglAA--.2269S4; Wed, 28 Aug 2024 15:06:04 +0800 (CST) From: Bibo Mao To: Huacai Chen , Jianmin Lv Cc: WANG Xuerui , Thomas Gleixner , loongarch@lists.linux.dev, linux-kernel@vger.kernel.org, linux-mips@vger.kernel.org Subject: [RFC v2 2/2] irqchip/loongson-eiointc: Add multiple interrupt pin routing support Date: Wed, 28 Aug 2024 15:06:03 +0800 Message-Id: <20240828070603.3518753-3-maobibo@loongson.cn> X-Mailer: git-send-email 2.39.3 In-Reply-To: <20240828070603.3518753-1-maobibo@loongson.cn> References: <20240828070603.3518753-1-maobibo@loongson.cn> Precedence: bulk X-Mailing-List: linux-mips@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: qMiowMCxB2ZbzM5m5UglAA--.2269S4 X-CM-SenderInfo: xpdruxter6z05rqj20fqof0/ X-Coremail-Antispam: 1Uk129KBjDUn29KB7ZKAUJUUUUU529EdanIXcx71UUUUU7KY7 ZEXasCq-sGcSsGvfJ3UbIjqfuFe4nvWSU5nxnvy29KBjDU0xBIdaVrnUUvcSsGvfC2Kfnx nUUI43ZEXa7xR_UUUUUUUUU== Eiointc interrupt controller support 256 interrupt vectors at most, and irq handler gets interrupt status from base register group EIOINTC_REG_ISR plus specific offset. It needs to read register group EIOINTC_REG_ISR four times to get all 256 interrupt vectors status. Eiointc registers including EIOINTC_REG_ISR is software emulated for VMs, there will be VM-exits when accessing eiointc registers. Here one method is introduced so that eiointc interrupt controller can route to different cpu interrupt pins for every 64 interrupt vectors. So irq handler needs read only relative 64 interrupt vector, it reduces VM-exits. Signed-off-by: Bibo Mao --- drivers/irqchip/irq-loongson-eiointc.c | 72 ++++++++++++++++++++++---- 1 file changed, 63 insertions(+), 9 deletions(-) diff --git a/drivers/irqchip/irq-loongson-eiointc.c b/drivers/irqchip/irq-loongson-eiointc.c index e9ec63d85ee8..c6bcb6625e6d 100644 --- a/drivers/irqchip/irq-loongson-eiointc.c +++ b/drivers/irqchip/irq-loongson-eiointc.c @@ -30,11 +30,20 @@ #define VEC_REG_IDX(irq_id) ((irq_id) / VEC_COUNT_PER_REG) #define VEC_REG_BIT(irq_id) ((irq_id) % VEC_COUNT_PER_REG) #define EIOINTC_ALL_ENABLE 0xffffffff +#define EIOINTC_ROUTE_MULTIPLE_IP BIT(0) #define MAX_EIO_NODES (NR_CPUS / CORES_PER_EIO_NODE) static int nr_pics; +struct eiointc_priv; +struct eiointc_ip_route { + struct eiointc_priv *priv; + /* Routed destination IP offset */ + int start; + int end; +}; + struct eiointc_priv { u32 node; u32 vec_count; @@ -43,6 +52,8 @@ struct eiointc_priv { struct fwnode_handle *domain_handle; struct irq_domain *eiointc_domain; int parent_hwirq; + int flags; + struct eiointc_ip_route route_info[4]; }; static struct eiointc_priv *eiointc_priv[MAX_IO_PICS]; @@ -145,12 +156,20 @@ static int eiointc_router_init(unsigned int cpu) uint32_t data; uint32_t node = cpu_to_eio_node(cpu); int index = eiointc_index(node); + int hwirq, mask; if (index < 0) { pr_err("Error: invalid nodemap!\n"); return -1; } + /* Enable cpu interrupt pin routed from eiointc */ + hwirq = eiointc_priv[index]->parent_hwirq; + mask = BIT(hwirq); + if (eiointc_priv[index]->flags & EIOINTC_ROUTE_MULTIPLE_IP) + mask |= BIT(hwirq + 1) | BIT(hwirq + 2) | BIT(hwirq + 3); + set_csr_ecfg(mask); + if ((cpu_logical_map(cpu) % CORES_PER_EIO_NODE) == 0) { eiointc_enable(); @@ -161,12 +180,23 @@ static int eiointc_router_init(unsigned int cpu) for (i = 0; i < eiointc_priv[0]->vec_count / 32 / 4; i++) { /* - * Route to interrupt pin, using offset minus INT_HWI0 - * Offset 0 means IP0 and so on - * Every 32 vector routing to one interrupt pin + * Route to interrupt pin, minus INT_HWI0 as offset + * Offset 0 means IP0 and so on, every 32 vector + * routing to one interrupt pin + * + * If flags is set with EIOINTC_ROUTE_MULTIPLE_IP, + * every 64 vector routes to different consecutive + * IPs, otherwise all vector routes to the same IP */ - bit = BIT(eiointc_priv[index]->parent_hwirq - INT_HWI0); - data = bit | (bit << 8) | (bit << 16) | (bit << 24); + if (eiointc_priv[index]->flags & EIOINTC_ROUTE_MULTIPLE_IP) { + bit = BIT(hwirq++ - INT_HWI0); + data = bit | (bit << 8); + bit = BIT(hwirq++ - INT_HWI0); + data |= (bit << 16) | (bit << 24); + } else { + bit = BIT(hwirq - INT_HWI0); + data = bit | (bit << 8) | (bit << 16) | (bit << 24); + } iocsr_write32(data, EIOINTC_REG_IPMAP + i * 4); } @@ -197,11 +227,18 @@ static void eiointc_irq_dispatch(struct irq_desc *desc) u64 pending; bool handled = false; struct irq_chip *chip = irq_desc_get_chip(desc); - struct eiointc_priv *priv = irq_desc_get_handler_data(desc); + struct eiointc_ip_route *info = irq_desc_get_handler_data(desc); chained_irq_enter(chip, desc); - for (i = 0; i < eiointc_priv[0]->vec_count / VEC_COUNT_PER_REG; i++) { + /* + * If EIOINTC_ROUTE_MULTIPLE_IP is set, every 64 interrupt vectors in + * eiointc interrupt controller routes to different cpu interrupt pins + * + * Every cpu interrupt pin has its own irq handler, it is ok to + * read ISR for these 64 interrupt vectors rather than all vectors + */ + for (i = info->start; i < info->end; i++) { pending = iocsr_read64(EIOINTC_REG_ISR + (i << 3)); /* Skip handling if pending bitmap is zero */ @@ -214,7 +251,7 @@ static void eiointc_irq_dispatch(struct irq_desc *desc) int bit = __ffs(pending); int irq = bit + VEC_COUNT_PER_REG * i; - generic_handle_domain_irq(priv->eiointc_domain, irq); + generic_handle_domain_irq(info->priv->eiointc_domain, irq); pending &= ~BIT(bit); handled = true; } @@ -397,8 +434,25 @@ static int __init eiointc_init(struct eiointc_priv *priv, int parent_irq, } eiointc_priv[nr_pics++] = priv; + if (cpu_has_hypervisor) { + priv->parent_hwirq = INT_HWI0; + for (i = 0; i < priv->vec_count / VEC_COUNT_PER_REG; i++) { + priv->route_info[i].start = priv->parent_hwirq - INT_HWI0 + i; + priv->route_info[i].end = priv->route_info[i].start + 1; + priv->route_info[i].priv = priv; + parent_irq = get_percpu_irq(priv->parent_hwirq + i); + irq_set_chained_handler_and_data(parent_irq, eiointc_irq_dispatch, + &priv->route_info[i]); + } + priv->flags |= EIOINTC_ROUTE_MULTIPLE_IP; + } else { + priv->route_info[0].start = 0; + priv->route_info[0].end = priv->vec_count / VEC_COUNT_PER_REG; + priv->route_info[0].priv = priv; + irq_set_chained_handler_and_data(parent_irq, eiointc_irq_dispatch, + &priv->route_info[0]); + } eiointc_router_init(0); - irq_set_chained_handler_and_data(parent_irq, eiointc_irq_dispatch, priv); if (nr_pics == 1) { register_syscore_ops(&eiointc_syscore_ops);