Received: from milmhbs1.lsil.com (147.145.21.209) by coscas01.lsi.com
 (172.21.36.60) with Microsoft SMTP Server id 8.1.393.1; Tue, 13 Oct 2009
 09:53:45 -0600
Received: from mail1.lsil.com (mail1.lsil.com [147.145.40.21])	by
 milmhbs1.lsil.com (8.12.11/8.12.11) with ESMTP id n9DFrjBu013181	for
 <andy.sharp@lsi.com>; Tue, 13 Oct 2009 08:53:45 -0700
Received: from psmtp.com (na3sys009amx183.postini.com [74.125.149.164])	by
 mail1.lsil.com (8.12.11/8.12.11) with SMTP id n9DFrh4S012389	for
 <andy.sharp@lsi.com>; Tue, 13 Oct 2009 08:53:43 -0700 (PDT)
Received: from source ([78.24.191.182]) by na3sys009amx183.postini.com
 ([74.125.148.14]) with SMTP;	Tue, 13 Oct 2009 08:53:44 PDT
Received: from localhost.localdomain ([127.0.0.1]:40234 "EHLO
	eddie.linux-mips.org" rhost-flags-OK-OK-OK-FAIL) by ftp.linux-mips.org	with
 ESMTP id S1493189AbZJMPxm (ORCPT <rfc822;andy.sharp@lsi.com>);	Tue, 13 Oct
 2009 17:53:42 +0200
Received: with ECARTIS (v1.0.0; list linux-mips); Tue, 13 Oct 2009 17:53:24
 +0200 (CEST)
Received: from mail3.caviumnetworks.com ([12.108.191.235]:17384 "EHLO
	mail3.caviumnetworks.com" rhost-flags-OK-OK-OK-OK)	by ftp.linux-mips.org with
 ESMTP id S1493188AbZJMPwx (ORCPT	<rfc822;linux-mips@linux-mips.org>); Tue, 13
 Oct 2009 17:52:53 +0200
Received: from caexch01.caveonetworks.com (Not Verified[192.168.16.9]) by
 mail3.caviumnetworks.com with MailMarshal (v6,5,4,7535)	id <B4ad4a23f0000>;
 Tue, 13 Oct 2009 08:52:34 -0700
Received: from caexch01.caveonetworks.com ([192.168.16.9]) by
 caexch01.caveonetworks.com with Microsoft SMTPSVC(6.0.3790.3959);	 Tue, 13
 Oct 2009 08:52:32 -0700
Received: from dd1.caveonetworks.com ([12.108.191.236]) by
 caexch01.caveonetworks.com over TLS secured channel with Microsoft
 SMTPSVC(6.0.3790.3959);	 Tue, 13 Oct 2009 08:52:32 -0700
Received: from dd1.caveonetworks.com (localhost.localdomain [127.0.0.1])	by
 dd1.caveonetworks.com (8.14.2/8.14.2) with ESMTP id n9DFqUe1022084;	Tue, 13
 Oct 2009 08:52:30 -0700
Received: (from ddaney@localhost)	by dd1.caveonetworks.com
 (8.14.2/8.14.2/Submit) id n9DFqUIL022083;	Tue, 13 Oct 2009 08:52:30 -0700
From: David Daney <ddaney@caviumnetworks.com>
To: "linux-mips@linux-mips.org" <linux-mips@linux-mips.org>,
	"ralf@linux-mips.org" <ralf@linux-mips.org>
CC: David Daney <ddaney@caviumnetworks.com>
Sender: "linux-mips-bounce@linux-mips.org" <linux-mips-bounce@linux-mips.org>
Date: Tue, 13 Oct 2009 09:52:29 -0600
Subject: [PATCH 2/2] MIPS: Octeon: Use lockless interrupt controller
 operations when possible.
Thread-Topic: [PATCH 2/2] MIPS: Octeon: Use lockless interrupt controller
 operations when possible.
Thread-Index: AcpMHVh0YV8ztJvmSUS/TXJRMnZJrg==
Message-ID: <1255449149-22054-2-git-send-email-ddaney@caviumnetworks.com>
References: <4AD4A1E9.1080309@caviumnetworks.com>
In-Reply-To: <4AD4A1E9.1080309@caviumnetworks.com>
Accept-Language: en-US
Content-Language: en-US
X-MS-Exchange-Organization-AuthAs: Anonymous
X-MS-Exchange-Organization-AuthSource: coscas01.lsi.com
X-MS-Has-Attach:
X-Auto-Response-Suppress: All
X-MS-TNEF-Correlator:
x-scanned-by: MIMEDefang 2.39
errors-to: linux-mips-bounce@linux-mips.org
x-originalarrivaltime: 13 Oct 2009 15:52:32.0472 (UTC)
 FILETIME=[2CE92580:01CA4C1D]
x-pstn-levels: (S:86.35392/99.90000 CV:99.9000 FC:95.5390 LC:95.5390
 R:95.9108 P:95.9108 M:90.4903 C:99.5902 )
x-pstn-settings: 3 (1.0000:1.0000) s cv gt3 gt2 gt1 r p m c 
x-pstn-addresses: from <ddaney@caviumnetworks.com> [db-null] 
x-pstn-neptune: 0/0/0.00/0
Content-Type: text/plain; charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
MIME-Version: 1.0

Some newer Octeon chips have registers that allow lockless operation
of the interrupt controller.  Take advantage of them.

Signed-off-by: David Daney <ddaney@caviumnetworks.com>
---
 arch/mips/cavium-octeon/octeon-irq.c |  177 ++++++++++++++++++++++++++++++=
+++-
 1 files changed, 172 insertions(+), 5 deletions(-)

diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon=
/octeon-irq.c
index 0bda5c5..865ff7b 100644
--- a/arch/mips/cavium-octeon/octeon-irq.c
+++ b/arch/mips/cavium-octeon/octeon-irq.c
@@ -178,6 +178,50 @@ static void octeon_irq_ciu0_disable(unsigned int irq)
 #endif
 }
=20
+/*
+ * Enable the irq on the current core for chips that have the EN*_W1{S,C}
+ * registers.
+ */
+static void octeon_irq_ciu0_enable_v2(unsigned int irq)
+{
+	int index =3D cvmx_get_core_num() * 2;
+	u64 mask =3D 1ull << (irq - OCTEON_IRQ_WORKQ0);
+
+	cvmx_write_csr(CVMX_CIU_INTX_EN0_W1S(index), mask);
+}
+
+/*
+ * Disable the irq on the current core for chips that have the EN*_W1{S,C}
+ * registers.
+ */
+static void octeon_irq_ciu0_disable_v2(unsigned int irq)
+{
+	int index =3D cvmx_get_core_num() * 2;
+	u64 mask =3D 1ull << (irq - OCTEON_IRQ_WORKQ0);
+
+	cvmx_write_csr(CVMX_CIU_INTX_EN0_W1C(index), mask);
+}
+
+/*
+ * Disable the irq on the all cores for chips that have the EN*_W1{S,C}
+ * registers.
+ */
+static void octeon_irq_ciu0_disable_all_v2(unsigned int irq)
+{
+	u64 mask =3D 1ull << (irq - OCTEON_IRQ_WORKQ0);
+	int index;
+#ifdef CONFIG_SMP
+	int cpu;
+	for_each_online_cpu(cpu) {
+		index =3D cpu_logical_map(cpu) * 2;
+		cvmx_write_csr(CVMX_CIU_INTX_EN0_W1C(index), mask);
+	}
+#else
+	index =3D cvmx_get_core_num() * 2;
+	cvmx_write_csr(CVMX_CIU_INTX_EN0_W1C(index), mask);
+#endif
+}
+
 #ifdef CONFIG_SMP
 static int octeon_irq_ciu0_set_affinity(unsigned int irq, const struct cpu=
mask *dest)
 {
@@ -205,8 +249,42 @@ static int octeon_irq_ciu0_set_affinity(unsigned int i=
rq, const struct cpumask *
=20
 	return 0;
 }
+
+/*
+ * Set affinity for the irq for chips that have the EN*_W1{S,C}
+ * registers.
+ */
+static int octeon_irq_ciu0_set_affinity_v2(unsigned int irq,
+					   const struct cpumask *dest)
+{
+	int cpu;
+	int index;
+	u64 mask =3D 1ull << (irq - OCTEON_IRQ_WORKQ0);
+	for_each_online_cpu(cpu) {
+		index =3D cpu_logical_map(cpu) * 2;
+		if (cpumask_test_cpu(cpu, dest))
+			cvmx_write_csr(CVMX_CIU_INTX_EN0_W1S(index), mask);
+		else
+			cvmx_write_csr(CVMX_CIU_INTX_EN0_W1C(index), mask);
+	}
+	return 0;
+}
 #endif
=20
+/*
+ * Newer octeon chips have support for lockless CIU operation.
+ */
+static struct irq_chip octeon_irq_chip_ciu0_v2 =3D {
+	.name =3D "CIU0",
+	.enable =3D octeon_irq_ciu0_enable_v2,
+	.disable =3D octeon_irq_ciu0_disable_all_v2,
+	.ack =3D octeon_irq_ciu0_disable_v2,
+	.eoi =3D octeon_irq_ciu0_enable_v2,
+#ifdef CONFIG_SMP
+	.set_affinity =3D octeon_irq_ciu0_set_affinity_v2,
+#endif
+};
+
 static struct irq_chip octeon_irq_chip_ciu0 =3D {
 	.name =3D "CIU0",
 	.enable =3D octeon_irq_ciu0_enable,
@@ -296,8 +374,53 @@ static void octeon_irq_ciu1_disable(unsigned int irq)
 #endif
 }
=20
+/*
+ * Enable the irq on the current core for chips that have the EN*_W1{S,C}
+ * registers.
+ */
+static void octeon_irq_ciu1_enable_v2(unsigned int irq)
+{
+	int index =3D cvmx_get_core_num() * 2 + 1;
+	u64 mask =3D 1ull << (irq - OCTEON_IRQ_WDOG0);
+
+	cvmx_write_csr(CVMX_CIU_INTX_EN1_W1S(index), mask);
+}
+
+/*
+ * Disable the irq on the current core for chips that have the EN*_W1{S,C}
+ * registers.
+ */
+static void octeon_irq_ciu1_disable_v2(unsigned int irq)
+{
+	int index =3D cvmx_get_core_num() * 2 + 1;
+	u64 mask =3D 1ull << (irq - OCTEON_IRQ_WDOG0);
+
+	cvmx_write_csr(CVMX_CIU_INTX_EN1_W1C(index), mask);
+}
+
+/*
+ * Disable the irq on the all cores for chips that have the EN*_W1{S,C}
+ * registers.
+ */
+static void octeon_irq_ciu1_disable_all_v2(unsigned int irq)
+{
+	u64 mask =3D 1ull << (irq - OCTEON_IRQ_WDOG0);
+	int index;
 #ifdef CONFIG_SMP
-static int octeon_irq_ciu1_set_affinity(unsigned int irq, const struct cpu=
mask *dest)
+	int cpu;
+	for_each_online_cpu(cpu) {
+		index =3D cpu_logical_map(cpu) * 2 + 1;
+		cvmx_write_csr(CVMX_CIU_INTX_EN1_W1C(index), mask);
+	}
+#else
+	index =3D cvmx_get_core_num() * 2 + 1;
+	cvmx_write_csr(CVMX_CIU_INTX_EN1_W1C(index), mask);
+#endif
+}
+
+#ifdef CONFIG_SMP
+static int octeon_irq_ciu1_set_affinity(unsigned int irq,
+					const struct cpumask *dest)
 {
 	int cpu;
 	unsigned long flags;
@@ -324,8 +447,42 @@ static int octeon_irq_ciu1_set_affinity(unsigned int i=
rq, const struct cpumask *
=20
 	return 0;
 }
+
+/*
+ * Set affinity for the irq for chips that have the EN*_W1{S,C}
+ * registers.
+ */
+static int octeon_irq_ciu1_set_affinity_v2(unsigned int irq,
+					   const struct cpumask *dest)
+{
+	int cpu;
+	int index;
+	u64 mask =3D 1ull << (irq - OCTEON_IRQ_WDOG0);
+	for_each_online_cpu(cpu) {
+		index =3D cpu_logical_map(cpu) * 2 + 1;
+		if (cpumask_test_cpu(cpu, dest))
+			cvmx_write_csr(CVMX_CIU_INTX_EN1_W1S(index), mask);
+		else
+			cvmx_write_csr(CVMX_CIU_INTX_EN1_W1C(index), mask);
+	}
+	return 0;
+}
 #endif
=20
+/*
+ * Newer octeon chips have support for lockless CIU operation.
+ */
+static struct irq_chip octeon_irq_chip_ciu1_v2 =3D {
+	.name =3D "CIU0",
+	.enable =3D octeon_irq_ciu1_enable_v2,
+	.disable =3D octeon_irq_ciu1_disable_all_v2,
+	.ack =3D octeon_irq_ciu1_disable_v2,
+	.eoi =3D octeon_irq_ciu1_enable_v2,
+#ifdef CONFIG_SMP
+	.set_affinity =3D octeon_irq_ciu1_set_affinity_v2,
+#endif
+};
+
 static struct irq_chip octeon_irq_chip_ciu1 =3D {
 	.name =3D "CIU1",
 	.enable =3D octeon_irq_ciu1_enable,
@@ -422,6 +579,8 @@ static struct irq_chip octeon_irq_chip_msi =3D {
 void __init arch_init_irq(void)
 {
 	int irq;
+	struct irq_chip *chip0;
+	struct irq_chip *chip1;
=20
 #ifdef CONFIG_SMP
 	/* Set the default affinity to the boot cpu. */
@@ -432,6 +591,16 @@ void __init arch_init_irq(void)
 	if (NR_IRQS < OCTEON_IRQ_LAST)
 		pr_err("octeon_irq_init: NR_IRQS is set too low\n");
=20
+	if (OCTEON_IS_MODEL(OCTEON_CN58XX_PASS2_X) ||
+	    OCTEON_IS_MODEL(OCTEON_CN56XX_PASS2_X) ||
+	    OCTEON_IS_MODEL(OCTEON_CN52XX_PASS2_X)) {
+		chip0 =3D &octeon_irq_chip_ciu0_v2;
+		chip1 =3D &octeon_irq_chip_ciu1_v2;
+	} else {
+		chip0 =3D &octeon_irq_chip_ciu0;
+		chip1 =3D &octeon_irq_chip_ciu1;
+	}
+
 	/* 0 - 15 reserved for i8259 master and slave controller. */
=20
 	/* 17 - 23 Mips internal */
@@ -442,14 +611,12 @@ void __init arch_init_irq(void)
=20
 	/* 24 - 87 CIU_INT_SUM0 */
 	for (irq =3D OCTEON_IRQ_WORKQ0; irq <=3D OCTEON_IRQ_BOOTDMA; irq++) {
-		set_irq_chip_and_handler(irq, &octeon_irq_chip_ciu0,
-					 handle_percpu_irq);
+		set_irq_chip_and_handler(irq, chip0, handle_percpu_irq);
 	}
=20
 	/* 88 - 151 CIU_INT_SUM1 */
 	for (irq =3D OCTEON_IRQ_WDOG0; irq <=3D OCTEON_IRQ_RESERVED151; irq++) {
-		set_irq_chip_and_handler(irq, &octeon_irq_chip_ciu1,
-					 handle_percpu_irq);
+		set_irq_chip_and_handler(irq, chip1, handle_percpu_irq);
 	}
=20
 #ifdef CONFIG_PCI_MSI
--=20
1.6.0.6


