From nobody Fri Sep 25 23:09:02 2026 Received: from smtpout-02.galae.net (smtpout-02.galae.net [185.246.84.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 28ACF4C6808 for ; Mon, 7 Sep 2026 12:47:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.84.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788785238; cv=none; b=u1Zyukj2HFJFEAsiKNLG58nrAaikElAmd917ezh7SimKMuq5YL8Be96uA/lEBWAIBM3dvSA90usFwtLehYiJHEnUTrGcfRpUBC2p1mhlBnC6LiJMTiLxVI6OU6MNujiBGIv1z3qFaa+1k9GzBCU/yH1cnGTCzPEoTIXhBAhFY1k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788785238; c=relaxed/simple; bh=UgqDmnOVqopm2mbDfHXbWFiQUAGdMzePQRCHXpsq6lA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=pMV1L+DzxZ4sYXmyazEv2brTyjuihHLIqdZaXP2QCg5JoEXaG2Up5K9EjdVQfHzkjqoMwFn9RMZTkc/PW9f6HF38WCFV8yrCFZK+22POfeRKTz5gjTVRVR0c1axcgdxU0mQjXL7/VZAV/9h8z9XEdqotM+3NUMGYoVdqGlAXZrk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=BnoIMUBO; arc=none smtp.client-ip=185.246.84.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="BnoIMUBO" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-02.galae.net (Postfix) with ESMTPS id 9634E1A1A33; Mon, 7 Sep 2026 12:47:13 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 6ABA960383; Mon, 7 Sep 2026 12:47:13 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 162DE11C79257; Mon, 7 Sep 2026 14:47:07 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1788785228; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=szJ77LlzQz7Ivcsto15zZ6XkZ55IboGYb8ikcqOxE5w=; b=BnoIMUBOeFX08NQhfvjdSrCFStHaTz/lpCPaal1K3WXso7wiTchmZxTqOHHixsAbnryG/F 1c0RjN73scp7p2Ffi2BRj8bNfFCMnXa5nclbgso/CLXLReaQj2wlJy7/7oBgdStF5B3/Xv SPVYMlqBbEhv6dRqH/y+0hBd8AEvZ1Xouj4UWrRPPIN0SLq7yt0QONIOdapXp0uJkhwlRQ ZPVZBUykNPkaZAb1UEPfWsUzZkEcopYAr1nSZd8kL+7oENqjn5RsZzIC95+eprc/vahOzv UDkaiTdKLm3SM7Kd2a10VzgXaKsJA5zySJp1Gea8M+86q50FsSpCgSF4ERkwZw== From: =?utf-8?q?Beno=C3=AEt_Monin?= Date: Mon, 07 Sep 2026 14:46:35 +0200 Subject: [PATCH v3 1/5] irqchip/mips-gic: Fix unbalanced cm_core_lock in for_each_online_cpu_gic() Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260907-sync-gic-counters-v3-1-3d891ddabdaf@bootlin.com> References: <20260907-sync-gic-counters-v3-0-3d891ddabdaf@bootlin.com> In-Reply-To: <20260907-sync-gic-counters-v3-0-3d891ddabdaf@bootlin.com> To: Thomas Bogendoerfer , Daniel Lezcano , Thomas Gleixner , Dragan Mladjenovic , Chao-ying Fu , Aleksandar Rikalo , Paul Burton , Radu Rendec Cc: Vladimir Kondratiev , Tawfik Bayouk , Gregory CLEMENT , =?utf-8?q?Th=C3=A9o_Lebrun?= , Thomas Petazzoni , linux-mips@vger.kernel.org, linux-kernel@vger.kernel.org, =?utf-8?q?Beno=C3=AEt_Monin?= X-Mailer: b4 0.16.0 X-Last-TLS-Session-Version: TLSv1.3 Commit d9e2ed610a60 ("irqchip/mips-gic: Support multi-cluster in for_each_online_cpu_gic()") added a gic_unlock_cluster() call to the macro's loop increment, which unconditionally invokes mips_cm_unlock_other() on multi-cluster systems. However nothing in the loop ever acquires the corresponding mips_cm_lock_other(), so on multi-cluster hardware every invocation of for_each_online_cpu_gic() releases an unheld per-CPU cm_core_lock. With CONFIG_PROVE_LOCKING this triggers a "bad unlock balance detected" warning at boot, e.g. from gic_irq_domain_map() while mapping local interrupts. Only the first occurrence is reported, since the first warning permanently disables lockdep (debug_locks =3D 0); the unbalanced release itself silently persists. Fix this by moving both the acquire and release into __gic_with_next_online_cpu() so they stay balanced. When advancing to a CPU in a remote cluster, lock the CM redirect block for that cluster via mips_cm_lock_other(); when leaving a remote cluster (or finishing the iteration) release it with mips_cm_unlock_other(). Local-cluster CPUs require no locking, so single-cluster systems are unaffected. This also makes the redirect region behave correctly when accessing local register blocks of CPUs in other clusters. Drop the now-unused gic_unlock_cluster() helper and its call from the for_each_online_cpu_gic() increment. Fixes: d9e2ed610a60 ("irqchip/mips-gic: Support multi-cluster in for_each_o= nline_cpu_gic()") Signed-off-by: Beno=C3=AEt Monin --- drivers/irqchip/irq-mips-gic.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c index 19a57c5e2b2e..3b31cbcbed6f 100644 --- a/drivers/irqchip/irq-mips-gic.c +++ b/drivers/irqchip/irq-mips-gic.c @@ -70,6 +70,10 @@ static int __gic_with_next_online_cpu(int prev) { unsigned int cpu; =20 + /* Release the redirect/other region lock to the previous CPU, if any. */ + if (prev >=3D 0) + mips_cm_unlock_other(); + /* Discover the next online CPU */ cpu =3D cpumask_next(prev, cpu_online_mask); =20 @@ -77,23 +81,12 @@ static int __gic_with_next_online_cpu(int prev) if (cpu >=3D nr_cpu_ids) return cpu; =20 - /* - * Move the access lock to the next CPU's GIC local register block. - * - * Set GIC_VL_OTHER. Since the caller holds gic_lock nothing can - * clobber the written value. - */ - write_gic_vl_other(mips_cm_vp_id(cpu)); + /* Lock access to redirect/other region to the next CPU */ + mips_cm_lock_other_cpu(cpu, CM_GCR_Cx_OTHER_BLOCK_LOCAL); =20 return cpu; } =20 -static inline void gic_unlock_cluster(void) -{ - if (mips_cps_multicluster_cpus()) - mips_cm_unlock_other(); -} - /** * for_each_online_cpu_gic() - Iterate over online CPUs, access local regi= sters * @cpu: An integer variable to hold the current CPU number @@ -108,7 +101,6 @@ static inline void gic_unlock_cluster(void) guard(raw_spinlock_irqsave)(gic_lock); \ for ((cpu) =3D __gic_with_next_online_cpu(-1); \ (cpu) < nr_cpu_ids; \ - gic_unlock_cluster(), \ (cpu) =3D __gic_with_next_online_cpu(cpu)) =20 /** --=20 2.55.0 From nobody Fri Sep 25 23:09:02 2026 Received: from smtpout-02.galae.net (smtpout-02.galae.net [185.246.84.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D27184BB5A8; Mon, 7 Sep 2026 12:47:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.84.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788785242; cv=none; b=e3exGaB/DDwVUD1Fvgevpqhys2UmetLfoOQ1d8AtxUwdveQyweOX7fK+Gf6jRLiQv/wCLYncUjBKL6CTx3wZYcSQxRtxyDDASlejAX8FFYkVNmuky95i7qboiSw06R0E5evfjZr1Y+PKFzFBs2+ZrmxrZx5TGujTM0OYnm3wMes= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788785242; c=relaxed/simple; bh=192a+g3Lk5EobTsbKaqEOhatpCAtWFbKjPR8U9VciAU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=H5ZbkpwolkzJUbo9R8n6Ppp2dNlaxzNSRaMDNEzBv+Al2UNiuktAslwQV2ZNSKDLENU+SODTAXypG26HWhdfyJeld7xRpy8cZY5nF13WCquTlP/Wgq/Vr9quSubhx8UR2+TWXetK1IMB2b3jfXRTqpKMYYCpY3TI7Y+TkZlEQvo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=kRkIa+7H; arc=none smtp.client-ip=185.246.84.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="kRkIa+7H" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-02.galae.net (Postfix) with ESMTPS id 4A6201A1A11; Mon, 7 Sep 2026 12:47:19 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 1F9D660383; Mon, 7 Sep 2026 12:47:19 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id BC50111C7AF0B; Mon, 7 Sep 2026 14:47:12 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1788785234; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=cYLeKozbpmiKqKGEp7Foxa6em3HQlD7wzvGKwnQbhwA=; b=kRkIa+7Hg0RxvAjAtOjAyeq5YOEsLmp9YO47b16tgQbhUfmQ9HlSYJh9KjQGRoFqZRm9+X 8arNwakZwed/wnA7ZGOJUiVqq8wdy7K16kJjbmrRR64SMxLYDnVmZ4bcljAPoBXAt7vdXt 5M9LAd/OSWgX0fV1Yuq6qWVREDoumK6ogFIHz9RK3hNNK1eLdK10T+nAOPu0udnRTQIOhD 1sKYrvIBCXBtqCIkAcrySfU9dcR18vm1o6dKpRZZsFSjPYRb+w3X4iEJPXCPZ5JJhaDfiU sXAxwjyLEThkujGirp69X+QeCj65nOPHlx0Z67Av8ysdRNqDP/7+ClVX4yNFwg== From: =?utf-8?q?Beno=C3=AEt_Monin?= Date: Mon, 07 Sep 2026 14:46:36 +0200 Subject: [PATCH v3 2/5] irqchip/mips-gic: Fix recursive acquisition of gic_lock in gic_set_affinity() Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260907-sync-gic-counters-v3-2-3d891ddabdaf@bootlin.com> References: <20260907-sync-gic-counters-v3-0-3d891ddabdaf@bootlin.com> In-Reply-To: <20260907-sync-gic-counters-v3-0-3d891ddabdaf@bootlin.com> To: Thomas Bogendoerfer , Daniel Lezcano , Thomas Gleixner , Dragan Mladjenovic , Chao-ying Fu , Aleksandar Rikalo , Paul Burton , Radu Rendec Cc: Vladimir Kondratiev , Tawfik Bayouk , Gregory CLEMENT , =?utf-8?q?Th=C3=A9o_Lebrun?= , Thomas Petazzoni , linux-mips@vger.kernel.org, linux-kernel@vger.kernel.org, =?utf-8?q?Beno=C3=AEt_Monin?= X-Mailer: b4 0.16.0 X-Last-TLS-Session-Version: TLSv1.3 Commit 322a90638768 ("irqchip/mips-gic: Multi-cluster support") made gic_set_affinity() call gic_set_type() when an interrupt's affinity is moved between clusters. gic_set_type() takes gic_lock with raw_spin_lock_irqsave(), but gic_set_affinity() holds gic_lock at that point, so the same raw spinlock is acquired twice, triggering a deadlock. Split gic_set_type() into a gic_set_type_locked() helper that assumes gic_lock is already held. gic_set_type() takes gic_lock and calls the helper, and gic_set_affinity() calls gic_set_type_locked() directly, since it already holds gic_lock. Fixes: 322a90638768 ("irqchip/mips-gic: Multi-cluster support") Signed-off-by: Beno=C3=AEt Monin --- drivers/irqchip/irq-mips-gic.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c index 3b31cbcbed6f..f2ae60d39d66 100644 --- a/drivers/irqchip/irq-mips-gic.c +++ b/drivers/irqchip/irq-mips-gic.c @@ -297,14 +297,14 @@ static void gic_ack_irq(struct irq_data *d) } } =20 -static int gic_set_type(struct irq_data *d, unsigned int type) +static int gic_set_type_locked(struct irq_data *d, unsigned int type) { unsigned int irq, pol, trig, dual; - unsigned long flags; + + lockdep_assert_held(&gic_lock); =20 irq =3D GIC_HWIRQ_TO_SHARED(d->hwirq); =20 - raw_spin_lock_irqsave(&gic_lock, flags); switch (type & IRQ_TYPE_SENSE_MASK) { case IRQ_TYPE_EDGE_FALLING: pol =3D GIC_POL_FALLING_EDGE; @@ -351,11 +351,16 @@ static int gic_set_type(struct irq_data *d, unsigned = int type) else irq_set_chip_handler_name_locked(d, &gic_level_irq_controller, handle_level_irq, NULL); - raw_spin_unlock_irqrestore(&gic_lock, flags); =20 return 0; } =20 +static int gic_set_type(struct irq_data *d, unsigned int type) +{ + guard(raw_spinlock_irqsave)(&gic_lock); + return gic_set_type_locked(d, type); +} + #ifdef CONFIG_SMP static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpum= ask, bool force) @@ -407,7 +412,7 @@ static int gic_set_affinity(struct irq_data *d, const s= truct cpumask *cpumask, * trigger type in the new cluster. */ if (cl !=3D old_cl) - gic_set_type(d, irqd_get_trigger_type(d)); + gic_set_type_locked(d, irqd_get_trigger_type(d)); =20 /* Route the interrupt to its new VP(E) */ if (gic_irq_lock_cluster(d)) { --=20 2.55.0 From nobody Fri Sep 25 23:09:02 2026 Received: from smtpout-02.galae.net (smtpout-02.galae.net [185.246.84.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 53B534B8DE6; Mon, 7 Sep 2026 12:47:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.84.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788785243; cv=none; b=WVxnXIUhL0j1wgYfX5Pvj7az4kIIOHzfab5/HvrSmcyjwWQIhPLcDXwt8n5xrGIVqHQekTZUDoVnfbqaba2eRcz12EMxXryMYegpA0Vj7BMCJein+DR+wH/5EU+UWlxleZ2C08wpomd3ZlGDcup7TKTGtA3pt4Teoyw3tGV2sRA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788785243; c=relaxed/simple; bh=Wf+QbgdgWkQe3JNnFVvRLyHOwahdjGfq+ZuBa5Qlu6A=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Y9KS39MHzp+iWrKqW5jAgZXBVfYcEVTTRsIb7WMtEdNTu92Wboh2lXPf1QXWeGb2LZowPNuBWnZRJ7ZGUrCw0vkDqg/Z2Z/fbrNXYmUqWJjD3l+K6CsO04CWGBP7+byJTjgbpRru/zFzD/HAs3opFdRYs7jZOaB0w16+2F7W/yM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=JICAoHPi; arc=none smtp.client-ip=185.246.84.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="JICAoHPi" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-02.galae.net (Postfix) with ESMTPS id D05551A1A33; Mon, 7 Sep 2026 12:47:20 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id A468E60383; Mon, 7 Sep 2026 12:47:20 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 793BC11C7AF1D; Mon, 7 Sep 2026 14:47:18 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1788785239; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=ew1QXNv1E3Xm6+feIsK83rNyoslxYmVUO+n/IV7SqNw=; b=JICAoHPiTZ/QblDsUau1a5K5GRNjskhifboDKXYf/KTO86w+aWiYWVSRcYCgnlceDPXDzM bJfnKV3MnNCxgY39soL6Idnx8qc8dv0tXZHAisiH+kAaj3aXHfHGX2/hASpP6lz5q+JrHS 8PFxhgiNMN6h/GSnepEL8AQWcC+ExAOo/OjxgKaelSVZCcx2mL06hbo8VjcZgqpv072MsU CrCNdPatUwjg/UoUoOsQr5ZmA7uuJOQl2EaQVd2oSuY8EjzDRrmK7Uoxqc0MZysHuAQo0W vU65WB/yEuj5SIAZ1wSiIlPob10lNn0aGSQrGXuZ8ZcQ7pbiRwspSrVnvJ7/cw== From: =?utf-8?q?Beno=C3=AEt_Monin?= Date: Mon, 07 Sep 2026 14:46:37 +0200 Subject: [PATCH v3 3/5] irqchip/mips-gic: Enable interrupt when moving affinity across clusters Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260907-sync-gic-counters-v3-3-3d891ddabdaf@bootlin.com> References: <20260907-sync-gic-counters-v3-0-3d891ddabdaf@bootlin.com> In-Reply-To: <20260907-sync-gic-counters-v3-0-3d891ddabdaf@bootlin.com> To: Thomas Bogendoerfer , Daniel Lezcano , Thomas Gleixner , Dragan Mladjenovic , Chao-ying Fu , Aleksandar Rikalo , Paul Burton , Radu Rendec Cc: Vladimir Kondratiev , Tawfik Bayouk , Gregory CLEMENT , =?utf-8?q?Th=C3=A9o_Lebrun?= , Thomas Petazzoni , linux-mips@vger.kernel.org, linux-kernel@vger.kernel.org, =?utf-8?q?Beno=C3=AEt_Monin?= X-Mailer: b4 0.16.0 X-Last-TLS-Session-Version: TLSv1.3 When an interrupt's affinity is moved to a CPU in another cluster, gic_set_affinity() updates the routing (GIC_SH_MAP_VP) and trigger type in the destination cluster, but never touched the interrupt's mask state. The interrupt mask is per-cluster. After such a move the interrupt was left disabled in the destination cluster, so it never fires despite being correctly routed to its new VP. Handle the mask explicitly on a cross-cluster affinity change: in the old cluster, write GIC_SH_RMASK to disable the interrupt while clearing the route so it is no longer delivered. And in the new cluster, set the mask to enable the interrupt along with reconfiguring the trigger type. Fixes: 322a90638768 ("irqchip/mips-gic: Multi-cluster support") Signed-off-by: Beno=C3=AEt Monin --- drivers/irqchip/irq-mips-gic.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c index f2ae60d39d66..4b76a65f12c9 100644 --- a/drivers/irqchip/irq-mips-gic.c +++ b/drivers/irqchip/irq-mips-gic.c @@ -390,14 +390,17 @@ static int gic_set_affinity(struct irq_data *d, const= struct cpumask *cpumask, =20 /* * If we're moving affinity between clusters, stop routing the - * interrupt to any VP(E) in the old cluster. + * interrupt to any VP(E) in the old cluster and disable + * the interrupt in that cluster. */ if (cl !=3D old_cl) { if (gic_irq_lock_cluster(d)) { write_gic_redir_map_vp(irq, 0); + write_gic_redir_rmask(irq); mips_cm_unlock_other(); } else { write_gic_map_vp(irq, 0); + write_gic_rmask(irq); } } =20 @@ -409,10 +412,17 @@ static int gic_set_affinity(struct irq_data *d, const= struct cpumask *cpumask, =20 /* * If we're moving affinity between clusters, configure the interrupt - * trigger type in the new cluster. + * trigger type and enable the interrupt in the new cluster. */ - if (cl !=3D old_cl) + if (cl !=3D old_cl) { gic_set_type_locked(d, irqd_get_trigger_type(d)); + if (gic_irq_lock_cluster(d)) { + write_gic_redir_smask(irq); + mips_cm_unlock_other(); + } else { + write_gic_smask(irq); + } + } =20 /* Route the interrupt to its new VP(E) */ if (gic_irq_lock_cluster(d)) { --=20 2.55.0 From nobody Fri Sep 25 23:09:02 2026 Received: from smtpout-03.galae.net (smtpout-03.galae.net [185.246.85.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CE2CD4CA270; Mon, 7 Sep 2026 12:47:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.85.4 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788785245; cv=none; b=Q34FQHninSN4D/52Wr30GpYEAdykCNLMJrNn4ySxtiL0/beqZdE9p00WNXdjN/i3xJ/U4QsAquduFi8B+g42T11LCpy5R4HGHCmBTmTr8w23aZpYol2U3IKACJKD9e8wre4eJDIFu6UnHYVCUKy2T8U/dhnuuNjuDsTLmaLArv4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788785245; c=relaxed/simple; bh=6rZTytL69j6CpLD/oEagF1g2bjXrp/x/ZC6FmJMqqY4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=jo5qrgQ+Hg82tePdaXYe26sLdVERHE+3zA3dWWv+IfLwuwn/N6JxP6H08rM2qRgpFuiFWAPQcytWRTR2VXR+sY53XrzWLR7RFkXDC5oiVNnClyjKynsnmTNrTTaZOznuwu1jH2bz0wbrzRdTdmoAFTcpona/vGlzG005+8loCzQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=YZn03Icd; arc=none smtp.client-ip=185.246.85.4 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="YZn03Icd" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id 519DC4E41567; Mon, 7 Sep 2026 12:47:22 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 1FA9460383; Mon, 7 Sep 2026 12:47:22 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 1532111C7AF1C; Mon, 7 Sep 2026 14:47:20 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1788785241; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=D2/9j4zuJdpqtP7yhz1/mgU9l6GOdLZAykPvnpy/HEk=; b=YZn03IcdpISlxpt5o6nAxWg4m54ZOD+rhA3On+9B2uQzwEsqjcctFbh6ImCYlJlRFRFgTE faWsW26+C+VzlEXfV2UwOjaOTE+4dJYW8/nhs8cuWWl/Wu9vIjI4RcsZo+ROL8iZ+9ca7G m7R6hQF/UV6Gk6tRrTtjK2UrE3G9h18rRlC9EoGBb+g/6Pn7jW4xuSBY23p7QKuIhORSUD g8sxH7KG9GzPaOzf5LgFfw1oVXq3tL4lrlRvf+udR0A1pVHBkBWcuGCcbI8EeJTbQcDoC4 WH9stkDlkhUsAxtH4CFs4lX924+sQwQCrrao4VhHEDUQ0W6mbzPH//NlC0jSYA== From: =?utf-8?q?Beno=C3=AEt_Monin?= Date: Mon, 07 Sep 2026 14:46:38 +0200 Subject: [PATCH v3 4/5] clocksource: mips-gic-timer: Simplify gic_next_event() for per-cpu timer Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260907-sync-gic-counters-v3-4-3d891ddabdaf@bootlin.com> References: <20260907-sync-gic-counters-v3-0-3d891ddabdaf@bootlin.com> In-Reply-To: <20260907-sync-gic-counters-v3-0-3d891ddabdaf@bootlin.com> To: Thomas Bogendoerfer , Daniel Lezcano , Thomas Gleixner , Dragan Mladjenovic , Chao-ying Fu , Aleksandar Rikalo , Paul Burton , Radu Rendec Cc: Vladimir Kondratiev , Tawfik Bayouk , Gregory CLEMENT , =?utf-8?q?Th=C3=A9o_Lebrun?= , Thomas Petazzoni , linux-mips@vger.kernel.org, linux-kernel@vger.kernel.org, =?utf-8?q?Beno=C3=AEt_Monin?= X-Mailer: b4 0.16.0 X-Last-TLS-Session-Version: TLSv1.3 The GIC clock event device is registered per CPU and is flagged with CLOCK_EVT_FEAT_C3STOP. This guarantees that the set_next_event() callback is always invoked on the CPU of the event. Drop the code path configuring the compare register of another CPU as it is never called and does not correctly handle the case of having multiple clusters, and document this guarantee by adding the CLOCK_EVT_FEAT_PERCPU flag to the clock event device features. Signed-off-by: Beno=C3=AEt Monin --- drivers/clocksource/mips-gic-timer.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/clocksource/mips-gic-timer.c b/drivers/clocksource/mip= s-gic-timer.c index 1501c7db9a8e..cdaf4ba1d509 100644 --- a/drivers/clocksource/mips-gic-timer.c +++ b/drivers/clocksource/mips-gic-timer.c @@ -52,18 +52,13 @@ static u64 notrace gic_read_count(void) =20 static int gic_next_event(unsigned long delta, struct clock_event_device *= evt) { - int cpu =3D cpumask_first(evt->cpumask); u64 cnt; int res; =20 cnt =3D gic_read_count(); cnt +=3D (u64)delta; - if (cpu =3D=3D raw_smp_processor_id()) { - write_gic_vl_compare(cnt); - } else { - write_gic_vl_other(mips_cm_vp_id(cpu)); - write_gic_vo_compare(cnt); - } + write_gic_vl_compare(cnt); + res =3D ((int)(gic_read_count() - cnt) >=3D 0) ? -ETIME : 0; return res; } @@ -82,6 +77,7 @@ static void gic_clockevent_cpu_init(unsigned int cpu, { cd->name =3D "MIPS GIC"; cd->features =3D CLOCK_EVT_FEAT_ONESHOT | + CLOCK_EVT_FEAT_PERCPU | CLOCK_EVT_FEAT_C3STOP; =20 cd->rating =3D 350; --=20 2.55.0 From nobody Fri Sep 25 23:09:02 2026 Received: from smtpout-03.galae.net (smtpout-03.galae.net [185.246.85.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EA9AF4CA78F; Mon, 7 Sep 2026 12:47:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.85.4 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788785247; cv=none; b=outxdI41elaPzuNKRkCH16aUqG4R06a6+2ZijtbBeMmK/cdkvuLFYTxUev2GYJ1CPKYLPHls7xCtieUKoFmziOUCH6TQYF8nHH/VsMVzTt6KC4ERzO4H+nz388eyfzHtm6V6xaDev3F/K0+C7QaYyj8eUCmWABZij3h5jiKhoeg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788785247; c=relaxed/simple; bh=HJe8XfmAy+6cuvPSTFtenI0mNigrcHVtO6ugEMbO7Q8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=PW27Ti6FzGEGV0I8XIrHz5qeEeAthezyXIzFwRg9xASkSFtzeI1wFIK5YsO6y3rXJxtD200Ss09dIAU+pqI9E+NV4dtCjhzh2l3WwmbLJZFDExJZ+UUcvfcPKQaI/EJlQc3fPzIKRo2NiaJDOPG2kCo7f0OpX1ooDfOsR9YD/cA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=Y3/TFEJD; arc=none smtp.client-ip=185.246.85.4 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="Y3/TFEJD" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id 517844E41569; Mon, 7 Sep 2026 12:47:24 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 1FC5960383; Mon, 7 Sep 2026 12:47:24 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 90F9E11C7AF1F; Mon, 7 Sep 2026 14:47:21 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1788785242; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=RTA8Cqgcw1oYnw9byAz6lCL72FCqdK7NKRYgo/TeUsY=; b=Y3/TFEJDM74Fha72snIPF7WEQ2RTnKfjROyNOjuRoNLC2B/6+vFFtZhQJeMCYVBoNRKzcT c8mDRD9jXvH/QMvPNtAp4R4zuP1yUHCSuDN4CcPHzK/CenFaeXx5DellYx8e8JN9tlqudr Z77mlVWIscvm4UGaJ0QtfhFLUD7Kuk50z1Zvs1nDdte3ppNpPBfWDqPyF+KLVOxXRu8xRw BzMPIBS6o3COOWyFr/FklYD/wA+oIEIEMwdHWghOy2K9DvuHgWNuGjN8F7NPAbKxUF4Oxh 6mYztltxEfNbdfEDoDlXqo7LZ1KbAGzABRtVfVGavnbQ2sUKJMTLAN3ePVcNrw== From: =?utf-8?q?Beno=C3=AEt_Monin?= Date: Mon, 07 Sep 2026 14:46:39 +0200 Subject: [PATCH v3 5/5] clocksource: mips-gic-timer: Use local counter on synced multi-cluster systems Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260907-sync-gic-counters-v3-5-3d891ddabdaf@bootlin.com> References: <20260907-sync-gic-counters-v3-0-3d891ddabdaf@bootlin.com> In-Reply-To: <20260907-sync-gic-counters-v3-0-3d891ddabdaf@bootlin.com> To: Thomas Bogendoerfer , Daniel Lezcano , Thomas Gleixner , Dragan Mladjenovic , Chao-ying Fu , Aleksandar Rikalo , Paul Burton , Radu Rendec Cc: Vladimir Kondratiev , Tawfik Bayouk , Gregory CLEMENT , =?utf-8?q?Th=C3=A9o_Lebrun?= , Thomas Petazzoni , linux-mips@vger.kernel.org, linux-kernel@vger.kernel.org, =?utf-8?q?Beno=C3=AEt_Monin?= X-Mailer: b4 0.16.0 X-Last-TLS-Session-Version: TLSv1.3 In a multi-cluster MIPS system there is one GIC per cluster, each with its own independent counter. These counters are not synchronized in hardware and can drift relative to one another, which is why multi- cluster systems currently fall back to gic_hpt_read_multicluster(): every clocksource read is redirected to cluster 0's counter via a cross-cluster register access. Instead, actively synchronize the counter of each secondary cluster to cluster 0's counter as its CPUs come online. When the first CPU of a cluster starts and the GIC counter is stopped, gic_sync_counter_64() is used to align the local counter with cluster 0 on systems using 64-bit CM accesses: - the local counter is stopped, loaded with cluster 0's counter value plus an accumulated offset, and restarted; - the alignment is checked by reading the local counter, cluster 0's counter and the local counter again (t0, t1, t2). If t1 lies between t0 and t2 the two counters are considered in sync; - otherwise the offset is refined by half of the measured error to compensate for the cross-cluster access latency, and the process is retried. After a short delay the alignment is re-checked to confirm the counters have not drifted apart, and only then is the cluster recorded as synchronized in gic_synced_cl_map. Clusters with no cores and cluster 0 itself are marked synchronized up-front. Once every cluster is synchronized, gic_clocksource_promote() switches the clocksource back from gic_hpt_read_multicluster() to the fast local gic_hpt_read(), re-registers it, and re-enables the GIC VDSO clock mode. It also registers the GIC counter as the sched_clock. Systems where synchronization cannot be achieved keep using the safe cross-cluster read path. Since gic_clocksource_promote() calls clocksource_unregister() and clocksource_register_hz() which internally use a mutex, it cannot be called directly from the CPU hotplug STARTING callback because interrupts are disabled. Instead the call is deferred to a workqueue. gic_clocksource_promote() also registers the local GIC counter as the sched clock via sched_clock_register(). This is valid from a non-__init context because sched_clock_register() lost its __init marker in commit 84b1a903aed8 ("time/sched_clock: Export symbol for sched_clock register function"). Note that the clocksource is only promoted once when all clusters are first online and all GIC counters are in sync. It is assumed that even if a cluster is fully powered-off then on later, gic_sync_counter_64() will be able to synchronize it once again. Said differently: there is no support to "demote" the clocksource. On the dual-cluster Mobileye EyeQ6H SoC, this allows four times faster clock_gettime(CLOCK_MONOTONIC) and a much higher precision sched_clock instead of jiffies. Signed-off-by: Beno=C3=AEt Monin --- drivers/clocksource/mips-gic-timer.c | 117 +++++++++++++++++++++++++++++++= ++-- 1 file changed, 112 insertions(+), 5 deletions(-) diff --git a/drivers/clocksource/mips-gic-timer.c b/drivers/clocksource/mip= s-gic-timer.c index cdaf4ba1d509..2d6f69f87fbb 100644 --- a/drivers/clocksource/mips-gic-timer.c +++ b/drivers/clocksource/mips-gic-timer.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -21,6 +22,8 @@ static int gic_timer_irq; static unsigned int gic_frequency; static unsigned int gic_count_width; static bool __read_mostly gic_clock_unstable; +static unsigned long *gic_synced_cl_map; +static struct work_struct gic_promote_work; =20 static void gic_clocksource_unstable(char *reason); =20 @@ -102,10 +105,71 @@ static void gic_update_frequency(void *data) clockevents_update_freq(this_cpu_ptr(&gic_clockevent_device), rate); } =20 +/* Number of iterations to synchronize the local GIC counter */ +#define GIC_SYNC_ITERATIONS 4 + +/* Delay in us to check if the local GIC counter is still in sync with clu= ster 0 */ +#define GIC_SYNC_CHECK_DELAY 100 + +static void gic_sync_counter_64(unsigned int cluster) +{ + unsigned int config =3D read_gic_config(); + u64 t0, t1, t2; + s64 offset =3D 0; + + mips_cm_lock_other(0, 0, 0, CM_GCR_Cx_OTHER_BLOCK_GLOBAL); + + for (int i =3D 0; i < GIC_SYNC_ITERATIONS; i++) { + write_gic_config(config | GIC_CONFIG_COUNTSTOP); + write_gic_counter(read_gic_redir_counter() + offset); + write_gic_config(config & ~GIC_CONFIG_COUNTSTOP); + + t0 =3D read_gic_counter(); + t1 =3D read_gic_redir_counter(); + t2 =3D read_gic_counter(); + + if (time_in_range64(t1, t0, t2)) + break; + + /* + * Compute the offset to apply to the local counter + * so that (t1 - t0) equals (t2 - t1). + */ + offset +=3D (s64)(2 * t1 - t0 - t2) / 2; + } + + mips_cm_unlock_other(); + + if (!time_in_range64(t1, t0, t2)) + return; + + udelay(GIC_SYNC_CHECK_DELAY); + + mips_cm_lock_other(0, 0, 0, CM_GCR_Cx_OTHER_BLOCK_GLOBAL); + t0 =3D read_gic_counter(); + t1 =3D read_gic_redir_counter(); + t2 =3D read_gic_counter(); + mips_cm_unlock_other(); + + /* If so, mark the cluster as synchronized */ + if (time_in_range64(t1, t0, t2) && gic_synced_cl_map) + bitmap_set(gic_synced_cl_map, cluster, 1); +} + static int gic_starting_cpu(unsigned int cpu) { - /* Ensure the GIC counter is running */ - clear_gic_config(GIC_CONFIG_COUNTSTOP); + unsigned int cluster =3D cpu_cluster(&cpu_data[cpu]); + + if (read_gic_config() & GIC_CONFIG_COUNTSTOP) { + clear_gic_config(GIC_CONFIG_COUNTSTOP); + + if (cluster && mips_cm_is64 && !gic_clock_unstable) + gic_sync_counter_64(cluster); + + if (gic_synced_cl_map && + bitmap_full(gic_synced_cl_map, mips_cps_numclusters())) + schedule_work(&gic_promote_work); + } =20 gic_clockevent_cpu_init(cpu, this_cpu_ptr(&gic_clockevent_device)); return 0; @@ -209,8 +273,33 @@ static void gic_clocksource_unstable(char *reason) clocksource_mark_unstable(&gic_clocksource); } =20 +static void gic_clocksource_promote(struct work_struct *work) +{ + if (gic_clock_unstable || gic_clocksource.read =3D=3D &gic_hpt_read) + return; + + if (clocksource_unregister(&gic_clocksource) < 0) + return; + + gic_clocksource.read =3D &gic_hpt_read; +#ifdef CONFIG_GENERIC_GETTIMEOFDAY + gic_clocksource.vdso_clock_mode =3D VDSO_CLOCKMODE_GIC; +#endif + + if (clocksource_register_hz(&gic_clocksource, gic_frequency) < 0) + return; + + if (mips_cm_revision() >=3D CM_REV_CM3 || !IS_ENABLED(CONFIG_CPU_FREQ)) { + sched_clock_register(mips_cm_is64 ? + gic_read_count_64 : gic_read_count_2x32, + gic_count_width, gic_frequency); + } +} + static int __init __gic_clocksource_init(void) { + unsigned int numclusters; + bool synced =3D false; int ret; =20 /* Set clocksource mask. */ @@ -222,14 +311,32 @@ static int __init __gic_clocksource_init(void) =20 /* Calculate a somewhat reasonable rating value. */ if (mips_cm_revision() >=3D CM_REV_CM3 || !IS_ENABLED(CONFIG_CPU_FREQ)) - gic_clocksource.rating =3D 300; /* Good when frequecy is stable */ + gic_clocksource.rating =3D 300; /* Good when frequency is stable */ else gic_clocksource.rating =3D 200; gic_clocksource.rating +=3D clamp(gic_frequency / 10000000, 0, 99); =20 - if (mips_cps_multicluster_cpus()) { + numclusters =3D mips_cps_numclusters(); + if (numclusters > 1) + gic_synced_cl_map =3D bitmap_zalloc(numclusters, GFP_KERNEL); + + /* + * Mark cluster 0 as synchronized (with itself), and all clusters + * without cores since there is no local GIC counter access on those. + */ + if (gic_synced_cl_map) { + bitmap_set(gic_synced_cl_map, 0, 1); + for (unsigned int cl =3D 0; cl < numclusters; cl++) { + if (!mips_cps_numcores(cl)) + bitmap_set(gic_synced_cl_map, cl, 1); + } + synced =3D bitmap_full(gic_synced_cl_map, numclusters); + } + + if (numclusters > 1 && !synced) { gic_clocksource.read =3D &gic_hpt_read_multicluster; gic_clocksource.vdso_clock_mode =3D VDSO_CLOCKMODE_NONE; + INIT_WORK(&gic_promote_work, gic_clocksource_promote); } =20 ret =3D clocksource_register_hz(&gic_clocksource, gic_frequency); @@ -288,7 +395,7 @@ static int __init gic_clocksource_of_init(struct device= _node *node) * change performed by the CPC core clocks divider. */ if ((mips_cm_revision() >=3D CM_REV_CM3 || !IS_ENABLED(CONFIG_CPU_FREQ)) = && - !mips_cps_multicluster_cpus()) { + gic_clocksource.read =3D=3D &gic_hpt_read) { sched_clock_register(mips_cm_is64 ? gic_read_count_64 : gic_read_count_2x32, gic_count_width, gic_frequency); --=20 2.55.0