RE: [PATCH] ARCv2: intc: Disable all core interrupts by default

2017-02-09 Thread Yuriy Kolerov
Hi Vineet,

> -Original Message-
> From: Vineet Gupta [mailto:vgu...@synopsys.com]
> Sent: Wednesday, February 08, 2017 7:08 PM
> To: Yuriy Kolerov <yuriy.kole...@synopsys.com>; linux-snps-
> a...@lists.infradead.org
> Cc: alexey.brod...@synopsys.com; linux-ker...@vger.kernel.org;
> marc.zyng...@arm.com
> Subject: Re: [PATCH] ARCv2: intc: Disable all core interrupts by default
> 
> On 02/07/2017 03:04 PM, Yuriy Kolerov wrote:
> > The kernel emits a lot of warnings about unexpected IRQs when an
> > appropriate driver is not presented. It happens because all interrupts
> > in the core controller are enabled by default after reset. It would be
> > wise to keep all interrupts masked by default.
> >
> > Thus disable all local and common interrupts. If CPU consists of only
> > 1 core without IDU then it is necessary to disable all interrupts in
> > the core interrupt controller. If CPU contains IDU it means that there
> > are may be more than 1 cores and common interrupts (>= FIRST_EXT_IRQ)
> > must be disabled in IDU.
> 
> This is not elegant. core intc needs to do same thing to all interrupts coming
> in
> - irrespective of whether they are funneled via IDU or not.
> 
> 
> > Signed-off-by: Yuriy Kolerov <yuriy.kole...@synopsys.com>
> > ---
> >  arch/arc/kernel/intc-arcv2.c | 19 +++
> 
> [snip...]
> 
> > +
> > for (i = NR_EXCEPTIONS; i < irq_bcr.irqs + NR_EXCEPTIONS; i++) {
> > write_aux_reg(AUX_IRQ_SELECT, i);
> > write_aux_reg(AUX_IRQ_PRIORITY, ARCV2_IRQ_DEF_PRIO);
> > +
> > +   /*
> > +* If IDU exists then all common interrupts >= FIRST_EXT_IRQ
> > +* are masked by IDU thus disable only local interrupts (below
> > +* FIRST_EXT_IRQ). Otherwise disable all interrupts.
> > +*/
> > +   if (!mp.idu || i < FIRST_EXT_IRQ)
> > +   write_aux_reg(AUX_IRQ_ENABLE, 0);
> 
> So you seem to assume that anything > FIRST_EXT_IRQ is coming in via IDU
> which may not be case.
> external Interrupts can be wired to core directly - not via IDU
>  - 16 .. 23 are cpu private reserved irq
>  - 24 .. C are common irqs (via IDU)
>  - C + 1 .. N are cpu private external irqs
> 
> so better to disable all irq_bcr.irqs independent of how they are hooked up !

All IRQs >= 24 in ARC are marked as common interrupts and it is reasonable. It 
means that when "enable" or "mask" is called for hwirq < 24 then these 
functions are called on all cores. On the other hand these functions are called 
once only on 1 core for common interrupts. Then we have 3 cases:

1. We have UP and everything is easy. Just disable everything by default. When 
a driver comes up an appropriate IRQ is enable on single core.
2. We have SMP with IDU. We can enable/disable common interrupts in IDU and 
keep core interrupts enabled/unmasked by default. But what happens if a device 
is connected to one of the cores directly (is it even possible on SMP 
systems?)? Device Tree does not contain such information and the kernel does 
not know how it enable external IRQ for the specific core (as far as I know).
3. Assume that all core interrupts on all cores are disabled by default. When 
chained IRQ is created (IDU -> core intc) IDU automatically calls "enable" for 
an appropriate IRQ of core intc. But this "enable" is called only for 1 core so 
it is necessary to find a way to call "enable" on the rest of cores. I have a 
solution which solves this problem using "smp_call_function_single_async" in 
"enable" function of the core intc for IRQs >= 24 but I think that it may be 
overkill for such problem. Anyway I cannot find a solution for the same problem 
in other archs...

> -Vineet
___
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc


[PATCH] ARCv2: intc: Disable all core interrupts by default

2017-02-07 Thread Yuriy Kolerov
The kernel emits a lot of warnings about unexpected IRQs when
an appropriate driver is not presented. It happens because all
interrupts in the core controller are enabled by default after
reset. It would be wise to keep all interrupts masked by default.

Thus disable all local and common interrupts. If CPU consists of
only 1 core without IDU then it is necessary to disable all
interrupts in the core interrupt controller. If CPU contains IDU
it means that there are may be more than 1 cores and common
interrupts (>= FIRST_EXT_IRQ) must be disabled in IDU.

Signed-off-by: Yuriy Kolerov <yuriy.kole...@synopsys.com>
---
 arch/arc/kernel/intc-arcv2.c | 19 +++
 1 file changed, 19 insertions(+)

diff --git a/arch/arc/kernel/intc-arcv2.c b/arch/arc/kernel/intc-arcv2.c
index f928795..ac84d09 100644
--- a/arch/arc/kernel/intc-arcv2.c
+++ b/arch/arc/kernel/intc-arcv2.c
@@ -12,6 +12,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #define NR_EXCEPTIONS  16
@@ -34,6 +35,7 @@ void arc_init_IRQ(void)
 {
unsigned int tmp, irq_prio, i;
struct bcr_irq_arcv2 irq_bcr;
+   struct mcip_bcr mp;
 
struct aux_irq_ctrl {
 #ifdef CONFIG_CPU_BIG_ENDIAN
@@ -75,10 +77,27 @@ void arc_init_IRQ(void)
 * Set a default priority for all available interrupts to prevent
 * switching of register banks if Fast IRQ and multiple register banks
 * are supported by CPU.
+*
+* Disable all local and common interrupts. If CPU consists of only 1
+* core without IDU then it is necessary to disable all interrupts
+* in the core interrupt controller. If CPU contains IDU it means that
+* there are may be more than 1 cores and common interrupts
+* (>= FIRST_EXT_IRQ) must be disabled in IDU.
 */
+
+   READ_BCR(ARC_REG_MCIP_BCR, mp);
+
for (i = NR_EXCEPTIONS; i < irq_bcr.irqs + NR_EXCEPTIONS; i++) {
write_aux_reg(AUX_IRQ_SELECT, i);
write_aux_reg(AUX_IRQ_PRIORITY, ARCV2_IRQ_DEF_PRIO);
+
+   /*
+* If IDU exists then all common interrupts >= FIRST_EXT_IRQ
+* are masked by IDU thus disable only local interrupts (below
+* FIRST_EXT_IRQ). Otherwise disable all interrupts.
+*/
+   if (!mp.idu || i < FIRST_EXT_IRQ)
+   write_aux_reg(AUX_IRQ_ENABLE, 0);
}
 
/* setup status32, don't enable intr yet as kernel doesn't want */
-- 
2.7.4



___
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc


[PATCH 0/2] Delete deprecated parameters in Device Trees

2017-02-01 Thread Yuriy Kolerov
  * Remove support of the second argument in IDU interrupts (it is
deprecated and not used anymore).
  * Remove useless declaration of interrupts list in IDU intc because
it is not used anymore and the kernel can obtain information about
supported interrupts from build registers.
  * Some small clean ups. 

Yuriy Kolerov (2):
  ARCv2: IDU-intc: Delete deprecated parameters in Device Trees
  ARCv2: intc: Delete useless comments in Device Trees

 .../interrupt-controller/snps,archs-idu-intc.txt   | 24 ++
 arch/arc/boot/dts/axc003_idu.dtsi  | 23 +++--
 arch/arc/boot/dts/haps_hs_idu.dts  | 11 ++
 arch/arc/boot/dts/nsim_hs_idu.dts  | 15 ++
 arch/arc/boot/dts/nsimosci_hs_idu.dts  | 21 ---
 arch/arc/boot/dts/vdk_axc003_idu.dtsi  | 13 +++-
 arch/arc/kernel/mcip.c | 17 +--
 7 files changed, 21 insertions(+), 103 deletions(-)

-- 
2.7.4



___
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc


[PATCH 2/2] ARCv2: intc: Delete useless comments in Device Trees

2017-02-01 Thread Yuriy Kolerov
Signed-off-by: Yuriy Kolerov <yuriy.kole...@synopsys.com>
---
 arch/arc/boot/dts/haps_hs_idu.dts | 1 -
 arch/arc/boot/dts/nsimosci_hs_idu.dts | 1 -
 2 files changed, 2 deletions(-)

diff --git a/arch/arc/boot/dts/haps_hs_idu.dts 
b/arch/arc/boot/dts/haps_hs_idu.dts
index 0a857fa..215cddd 100644
--- a/arch/arc/boot/dts/haps_hs_idu.dts
+++ b/arch/arc/boot/dts/haps_hs_idu.dts
@@ -47,7 +47,6 @@
compatible = "snps,archs-intc";
interrupt-controller;
#interrupt-cells = <1>;
-/* interrupts = <16 17 18 19 20 21 22 23 24 25>; */
};
 
idu_intc: idu-interrupt-controller {
diff --git a/arch/arc/boot/dts/nsimosci_hs_idu.dts 
b/arch/arc/boot/dts/nsimosci_hs_idu.dts
index 37be2bb..5052917 100644
--- a/arch/arc/boot/dts/nsimosci_hs_idu.dts
+++ b/arch/arc/boot/dts/nsimosci_hs_idu.dts
@@ -43,7 +43,6 @@
compatible = "snps,archs-intc";
interrupt-controller;
#interrupt-cells = <1>;
-/* interrupts = <16 17 18 19 20 21 22 23 24 25>; */
};
 
idu_intc: idu-interrupt-controller {
-- 
2.7.4



___
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc


[PATCH 1/2] ARCv2: IDU-intc: Delete deprecated parameters in Device Trees

2017-02-01 Thread Yuriy Kolerov
No need for specifying a list of interrupts in the declaration
of IDU interrupt controller anymore since the kernel can obtain
a number of supported interrupts from the build register.

Also delete support of the second parameter for devices which
are connected to IDU because it is not used anywhere.

Signed-off-by: Yuriy Kolerov <yuriy.kole...@synopsys.com>
---
 .../interrupt-controller/snps,archs-idu-intc.txt   | 24 ++
 arch/arc/boot/dts/axc003_idu.dtsi  | 23 +++--
 arch/arc/boot/dts/haps_hs_idu.dts  | 10 ++---
 arch/arc/boot/dts/nsim_hs_idu.dts  | 15 ++
 arch/arc/boot/dts/nsimosci_hs_idu.dts  | 20 --
 arch/arc/boot/dts/vdk_axc003_idu.dtsi  | 13 +++-
 arch/arc/kernel/mcip.c | 17 +--
 7 files changed, 21 insertions(+), 101 deletions(-)

diff --git 
a/Documentation/devicetree/bindings/interrupt-controller/snps,archs-idu-intc.txt
 
b/Documentation/devicetree/bindings/interrupt-controller/snps,archs-idu-intc.txt
index 9446576..8b46a34 100644
--- 
a/Documentation/devicetree/bindings/interrupt-controller/snps,archs-idu-intc.txt
+++ 
b/Documentation/devicetree/bindings/interrupt-controller/snps,archs-idu-intc.txt
@@ -8,15 +8,11 @@ Properties:
 - compatible: "snps,archs-idu-intc"
 - interrupt-controller: This is an interrupt controller.
 - interrupt-parent: 
-- #interrupt-cells: Must be <2>.
-- interrupts: <...> specifies the upstream core irqs
+- #interrupt-cells: Must be <1>.
 
-  First cell specifies the "common" IRQ from peripheral to IDU
-  Second cell specifies the irq distribution mode to cores
- 0=Round Robin; 1=cpu0, 2=cpu1, 4=cpu2, 8=cpu3
-
-  The second cell in interrupts property is deprecated and may be ignored by
-  the kernel.
+  Value of the cell specifies the "common" IRQ from peripheral to IDU. Number N
+  of the particular interrupt line of IDU corresponds to the line N+24 of the
+  core interrupt controller.
 
   intc accessed via the special ARC AUX register interface, hence "reg" 
property
   is not specified.
@@ -32,18 +28,10 @@ Example:
compatible = "snps,archs-idu-intc";
interrupt-controller;
interrupt-parent = <_intc>;
-
-   /*
-* 
-* distribution: 0=RR; 1=cpu0, 2=cpu1, 4=cpu2, 8=cpu3
-*/
-   #interrupt-cells = <2>;
-
-   /* upstream core irqs: downstream these are "COMMON" irq 0,1..  
*/
-   interrupts = <24 25 26 27 28 29 30 31>;
+   #interrupt-cells = <1>;
};
 
some_device: serial@c0fc1000 {
interrupt-parent = <_intc>;
-   interrupts = <0 0>; /* upstream idu IRQ #24, Round Robin */
+   interrupts = <0>;   /* upstream idu IRQ #24 */
};
diff --git a/arch/arc/boot/dts/axc003_idu.dtsi 
b/arch/arc/boot/dts/axc003_idu.dtsi
index 3d6cfa3..695f9fa 100644
--- a/arch/arc/boot/dts/axc003_idu.dtsi
+++ b/arch/arc/boot/dts/axc003_idu.dtsi
@@ -40,18 +40,7 @@
compatible = "snps,archs-idu-intc";
interrupt-controller;
interrupt-parent = <_intc>;
-
-   /*
-* 
-* distribution: 0=RR; 1=cpu0, 2=cpu1, 4=cpu2, 8=cpu3
-*/
-   #interrupt-cells = <2>;
-
-   /*
-* upstream irqs to core intc - downstream these are
-* "COMMON" irq 0,1..
-*/
-   interrupts = <24 25>;
+   #interrupt-cells = <1>;
};
 
/*
@@ -73,12 +62,7 @@
interrupt-controller;
#interrupt-cells = <2>;
interrupt-parent = <_intc>;
-
-   /*
-* cmn irq 1 -> cpu irq 25
-* Distribute to cpu0 only
-*/
-   interrupts = <1 1>;
+   interrupts = <1>;
};
};
 
@@ -119,8 +103,7 @@
reg = < 0xe0012000 0x200 >;
interrupt-controller;
interrupt-parent = <_intc>;
-   interrupts = <0 1>; /* cmn irq 0 -> cpu irq 24
-  distribute to cpu0 only */
+   interrupts = <0>;
};
 
memory {
diff --git a/arch/arc/boot/dts/haps_hs_idu.dts

RE: [PATCH v2 4/4] ARCv2: IRQ: Set a default priority for all core interrupts

2017-02-01 Thread Yuriy Kolerov
Hi Vineet,

> -Original Message-
> From: Vineet Gupta [mailto:vgu...@synopsys.com]
> Sent: Tuesday, January 31, 2017 8:54 PM
> To: Yuriy Kolerov <yuriy.kole...@synopsys.com>; linux-snps-
> a...@lists.infradead.org
> Cc: marc.zyng...@arm.com; alexey.brod...@synopsys.com; linux-
> ker...@vger.kernel.org
> Subject: Re: [PATCH v2 4/4] ARCv2: IRQ: Set a default priority for all core
> interrupts
> 
> On 01/31/2017 03:45 AM, Yuriy Kolerov wrote:
> > After reset all interrupts in the core interrupt controller has the
> > highest priority P0. If the platform supports Fast IRQs and has more
> > than 1 banks of registers then CPU automatically switch banks of
> > registers when P0 interrupt comes.
> >
> > The problem is that the kernel expects that by default switching of
> > banks is not used by all interrupts. It is necessary to set a default
> > nonzero priority for all available interrupts to avoid undefined
> > behaviour.
> >
> > Signed-off-by: Yuriy Kolerov <yuriy.kole...@synopsys.com>
> > ---
> >  arch/arc/kernel/intc-arcv2.c | 12 +++-
> >  1 file changed, 11 insertions(+), 1 deletion(-)
> >
> > diff --git a/arch/arc/kernel/intc-arcv2.c
> > b/arch/arc/kernel/intc-arcv2.c index 31246cc..d4fa4a5 100644
> > --- a/arch/arc/kernel/intc-arcv2.c
> > +++ b/arch/arc/kernel/intc-arcv2.c
> > @@ -22,7 +22,7 @@
> >   */
> >  void arc_init_IRQ(void)
> >  {
> > -   unsigned int tmp, irq_prio;
> > +   unsigned int tmp, irq_prio, i;
> >
> > struct bcr_irq_arcv2 irq_bcr;
> >
> > @@ -62,6 +62,16 @@ void arc_init_IRQ(void)
> > irq_prio + 1, ARCV2_IRQ_DEF_PRIO,
> > irq_bcr.firq ? " FIRQ (not used)":"");
> >
> > +   /*
> > +* Set a default priority for all available interrupts to prevent
> > +* switching of register banks if Fast IRQ and multiple register banks
> > +* are supported by CPU.
> > +*/
> > +   for (i = NR_EXCEPTIONS; i < irq_bcr.irqs + NR_EXCEPTIONS; i++) {
> > +   write_aux_reg(AUX_IRQ_SELECT, i);
> > +   write_aux_reg(AUX_IRQ_PRIORITY, ARCV2_IRQ_DEF_PRIO);
> > +   }
> > +
> 
> This itself is fine. However going forward can we move to the genirq
> irq_cpu_online() etc instead of doing this in our platform per cpu hook ?
> 
> https://www.linux-mips.org/archives/linux-mips/2011-03/msg00115.html

We need to set a default priority for all interrupts for each CPU before 
interrupt controller is configured. In other words it this necessary to 
guaranty a default state of all interrupts before doing something else with 
interrupts. Moreover as I understand irq_cpu_online() is intended to be used 
with virtual IRQs (already allocated interrupts) but the configuration of 
priorities must be done for all hardware interrupts to bring CPU to the default 
state.

> > /* setup status32, don't enable intr yet as kernel doesn't want */
> > tmp = read_aux_reg(ARC_REG_STATUS32);
> > tmp |= STATUS_AD_MASK | (ARCV2_IRQ_DEF_PRIO << 1);
> >


___
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc


[PATCH v2 4/4] ARCv2: IRQ: Set a default priority for all core interrupts

2017-01-31 Thread Yuriy Kolerov
After reset all interrupts in the core interrupt controller has
the highest priority P0. If the platform supports Fast IRQs and
has more than 1 banks of registers then CPU automatically switch
banks of registers when P0 interrupt comes.

The problem is that the kernel expects that by default switching
of banks is not used by all interrupts. It is necessary to set a
default nonzero priority for all available interrupts to avoid
undefined behaviour.

Signed-off-by: Yuriy Kolerov <yuriy.kole...@synopsys.com>
---
 arch/arc/kernel/intc-arcv2.c | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/arch/arc/kernel/intc-arcv2.c b/arch/arc/kernel/intc-arcv2.c
index 31246cc..d4fa4a5 100644
--- a/arch/arc/kernel/intc-arcv2.c
+++ b/arch/arc/kernel/intc-arcv2.c
@@ -22,7 +22,7 @@
  */
 void arc_init_IRQ(void)
 {
-   unsigned int tmp, irq_prio;
+   unsigned int tmp, irq_prio, i;
 
struct bcr_irq_arcv2 irq_bcr;
 
@@ -62,6 +62,16 @@ void arc_init_IRQ(void)
irq_prio + 1, ARCV2_IRQ_DEF_PRIO,
irq_bcr.firq ? " FIRQ (not used)":"");
 
+   /*
+* Set a default priority for all available interrupts to prevent
+* switching of register banks if Fast IRQ and multiple register banks
+* are supported by CPU.
+*/
+   for (i = NR_EXCEPTIONS; i < irq_bcr.irqs + NR_EXCEPTIONS; i++) {
+   write_aux_reg(AUX_IRQ_SELECT, i);
+   write_aux_reg(AUX_IRQ_PRIORITY, ARCV2_IRQ_DEF_PRIO);
+   }
+
/* setup status32, don't enable intr yet as kernel doesn't want */
tmp = read_aux_reg(ARC_REG_STATUS32);
tmp |= STATUS_AD_MASK | (ARCV2_IRQ_DEF_PRIO << 1);
-- 
2.7.4



___
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc


[PATCH v2 0/4] Use build registers for getting numbers of interrupts

2017-01-31 Thread Yuriy Kolerov
A summary:

  * Use build registers for getting numbers of interrupts both for
core interrupt controller and for IDU interrupt controller.
  * Set a default priority for all core interrupt to prevent
unexpected switching of banks of registers.
  * Remove option for setting number of interrupts since it does
not affect a number of interrupts in IRQ domains and breaks
portability since it is impossible to change size of table of
interrupts after linkage.

Change in v2:

  * Squash some commits.
  * Do not move a structure for control register of core intc to
the header since it is used only once.

Yuriy Kolerov (4):
  ARCv2: IRQ: Move structure for build register of core intc to the
header
  ARCv2: IRQ: Remove option for setting number of interrupts
  ARCv2: IRQ: Use build registers for getting numbers of interrupts
  ARCv2: IRQ: Set a default priority for all core interrupts

 arch/arc/Kconfig   | 11 ---
 arch/arc/include/asm/arcregs.h | 11 +++
 arch/arc/include/asm/irq.h | 32 +---
 arch/arc/kernel/entry-arcv2.S  |  3 ++-
 arch/arc/kernel/intc-arcv2.c   | 31 ---
 arch/arc/kernel/mcip.c | 31 +++
 include/soc/arc/mcip.h | 17 +
 7 files changed, 98 insertions(+), 38 deletions(-)

-- 
2.7.4



___
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc


[PATCH v2 1/4] ARCv2: IRQ: Move structure for build register of core intc to the header

2017-01-31 Thread Yuriy Kolerov
Also add new macro ARC_REG_STATUS32 for the address of STATUS32
auxiliary register. It is better to use it instead of magic numbers.

Signed-off-by: Yuriy Kolerov <yuriy.kole...@synopsys.com>
---
 arch/arc/include/asm/arcregs.h | 11 +++
 arch/arc/kernel/intc-arcv2.c   | 10 ++
 2 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/arch/arc/include/asm/arcregs.h b/arch/arc/include/asm/arcregs.h
index f659942..2328244 100644
--- a/arch/arc/include/asm/arcregs.h
+++ b/arch/arc/include/asm/arcregs.h
@@ -38,6 +38,9 @@
 #define ARC_REG_CLUSTER_BCR0xcf
 #define ARC_REG_AUX_ICCM   0x208   /* ICCM Base Addr (ARCv2) */
 
+/* Common for ARCompact and ARCv2 status register */
+#define ARC_REG_STATUS32   0x0A
+
 /* status32 Bits Positions */
 #define STATUS_AE_BIT  5   /* Exception active */
 #define STATUS_DE_BIT  6   /* PC is in delay slot */
@@ -233,6 +236,14 @@ struct bcr_generic {
 #endif
 };
 
+struct bcr_irq_arcv2 {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+   unsigned int pad:3, firq:1, prio:4, exts:8, irqs:8, ver:8;
+#else
+   unsigned int ver:8, irqs:8, exts:8, prio:4, firq:1, pad:3;
+#endif
+};
+
 /*
  ***
  * Generic structures to hold build configuration used at runtime
diff --git a/arch/arc/kernel/intc-arcv2.c b/arch/arc/kernel/intc-arcv2.c
index ecef0fb..9de0665 100644
--- a/arch/arc/kernel/intc-arcv2.c
+++ b/arch/arc/kernel/intc-arcv2.c
@@ -24,13 +24,7 @@ void arc_init_IRQ(void)
 {
unsigned int tmp, irq_prio;
 
-   struct irq_build {
-#ifdef CONFIG_CPU_BIG_ENDIAN
-   unsigned int pad:3, firq:1, prio:4, exts:8, irqs:8, ver:8;
-#else
-   unsigned int ver:8, irqs:8, exts:8, prio:4, firq:1, pad:3;
-#endif
-   } irq_bcr;
+   struct bcr_irq_arcv2 irq_bcr;
 
struct aux_irq_ctrl {
 #ifdef CONFIG_CPU_BIG_ENDIAN
@@ -69,7 +63,7 @@ void arc_init_IRQ(void)
irq_bcr.firq ? " FIRQ (not used)":"");
 
/* setup status32, don't enable intr yet as kernel doesn't want */
-   tmp = read_aux_reg(0xa);
+   tmp = read_aux_reg(ARC_REG_STATUS32);
tmp |= STATUS_AD_MASK | (ARCV2_IRQ_DEF_PRIO << 1);
tmp &= ~STATUS_IE_MASK;
asm volatile("kflag %0  \n"::"r"(tmp));
-- 
2.7.4



___
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc


[PATCH v2 3/4] ARCv2: IRQ: Use build registers for getting numbers of interrupts

2017-01-31 Thread Yuriy Kolerov
This enhancement allows to mask all available common interrupts
in IDU interrupt controller in boot time since the kernel can
discover a number of them from the build register. Also now there
is no need to specify in device tree a list of used core interrupts
by IDU. E.g. before:

idu_intc: idu-interrupt-controller {
compatible = "snps,archs-idu-intc";
interrupt-controller;
interrupt-parent = <_intc>;
#interrupt-cells = <2>;
interrupts = <24 25 26 27 28 29 30 31>;
};

and after:

idu_intc: idu-interrupt-controller {
compatible = "snps,archs-idu-intc";
interrupt-controller;
interrupt-parent = <_intc>;
#interrupt-cells = <2>;
};

Signed-off-by: Yuriy Kolerov <yuriy.kole...@synopsys.com>
---
 arch/arc/include/asm/irq.h   |  4 
 arch/arc/kernel/intc-arcv2.c |  9 +++--
 arch/arc/kernel/mcip.c   | 31 +++
 include/soc/arc/mcip.h   | 17 +
 4 files changed, 47 insertions(+), 14 deletions(-)

diff --git a/arch/arc/include/asm/irq.h b/arch/arc/include/asm/irq.h
index d28499a..1970d78c 100644
--- a/arch/arc/include/asm/irq.h
+++ b/arch/arc/include/asm/irq.h
@@ -18,6 +18,9 @@
  */
 #define NR_CPU_IRQS240
 
+/* A fixed number of exceptions which occupy first interrupt lines */
+#define NR_EXCEPTIONS  16
+
 /*
  * ARCv2 can support 240 interrupts in the core interrupts controllers and
  * 128 interrupts in IDU. Thus 512 virtual IRQs must be enough for most
@@ -28,6 +31,7 @@
 /* Platform Independent IRQs */
 #define IPI_IRQ19
 #define SOFTIRQ_IRQ21
+#define FIRST_EXT_IRQ  24
 
 #else
 
diff --git a/arch/arc/kernel/intc-arcv2.c b/arch/arc/kernel/intc-arcv2.c
index 9de0665..31246cc 100644
--- a/arch/arc/kernel/intc-arcv2.c
+++ b/arch/arc/kernel/intc-arcv2.c
@@ -109,7 +109,7 @@ static int arcv2_irq_map(struct irq_domain *d, unsigned int 
irq,
 * core intc IRQs [16, 23]:
 * Statically assigned always private-per-core (Timers, WDT, IPI, PCT)
 */
-   if (hw < 24) {
+   if (hw < FIRST_EXT_IRQ) {
/*
 * A subsequent request_percpu_irq() fails if percpu_devid is
 * not set. That in turns sets NOAUTOEN, meaning each core needs
@@ -134,11 +134,16 @@ static int __init
 init_onchip_IRQ(struct device_node *intc, struct device_node *parent)
 {
struct irq_domain *root_domain;
+   struct bcr_irq_arcv2 irq_bcr;
+   unsigned int nr_cpu_irqs;
+
+   READ_BCR(ARC_REG_IRQ_BCR, irq_bcr);
+   nr_cpu_irqs = irq_bcr.irqs + NR_EXCEPTIONS;
 
if (parent)
panic("DeviceTree incore intc not a root irq controller\n");
 
-   root_domain = irq_domain_add_linear(intc, NR_CPU_IRQS, _irq_ops, 
NULL);
+   root_domain = irq_domain_add_linear(intc, nr_cpu_irqs, _irq_ops, 
NULL);
if (!root_domain)
panic("root irq domain not avail\n");
 
diff --git a/arch/arc/kernel/mcip.c b/arch/arc/kernel/mcip.c
index 9988b42..45d45fc 100644
--- a/arch/arc/kernel/mcip.c
+++ b/arch/arc/kernel/mcip.c
@@ -157,15 +157,20 @@ static void idu_set_mode(unsigned int cmn_irq, unsigned 
int lvl,
__mcip_cmd_data(CMD_IDU_SET_MODE, cmn_irq, data.word);
 }
 
-static void idu_irq_mask(struct irq_data *data)
+static void idu_irq_mask_raw(irq_hw_number_t hwirq)
 {
unsigned long flags;
 
raw_spin_lock_irqsave(_lock, flags);
-   __mcip_cmd_data(CMD_IDU_SET_MASK, data->hwirq, 1);
+   __mcip_cmd_data(CMD_IDU_SET_MASK, hwirq, 1);
raw_spin_unlock_irqrestore(_lock, flags);
 }
 
+static void idu_irq_mask(struct irq_data *data)
+{
+   idu_irq_mask_raw(data->hwirq);
+}
+
 static void idu_irq_unmask(struct irq_data *data)
 {
unsigned long flags;
@@ -231,14 +236,12 @@ static struct irq_chip idu_irq_chip = {
 
 };
 
-static irq_hw_number_t idu_first_hwirq;
-
 static void idu_cascade_isr(struct irq_desc *desc)
 {
struct irq_domain *idu_domain = irq_desc_get_handler_data(desc);
struct irq_chip *core_chip = irq_desc_get_chip(desc);
irq_hw_number_t core_hwirq = irqd_to_hwirq(irq_desc_get_irq_data(desc));
-   irq_hw_number_t idu_hwirq = core_hwirq - idu_first_hwirq;
+   irq_hw_number_t idu_hwirq = core_hwirq - FIRST_EXT_IRQ;
 
chained_irq_enter(core_chip, desc);
generic_handle_irq(irq_find_mapping(idu_domain, idu_hwirq));
@@ -284,33 +287,37 @@ static int __init
 idu_of_init(struct device_node *intc, struct device_node *parent)
 {
struct irq_domain *domain;
-   /* Read IDU BCR to confirm nr_irqs */
-   int nr_irqs = of_irq_count(intc);
+   int nr_irqs;
int i, virq;
struct mcip_bcr mp;
+   struct mcip_idu_bcr idu_bcr;
 
READ_BCR(ARC_REG_MCIP_BCR, mp);
 
if (!mp.idu)
panic("IDU not detected, but DeviceTree using it"

[PATCH 5/6] ARCv2: IRQ: Use build registers for getting numbers of interrupts

2017-01-27 Thread Yuriy Kolerov
This enhancement allows to mask all available common interrupts
in IDU interrupt controller in boot time since the kernel can
discover a number of them from the build register. Also now there
is no need to specify in device tree a list of used core interrupts
by IDU. E.g. before:

idu_intc: idu-interrupt-controller {
compatible = "snps,archs-idu-intc";
interrupt-controller;
interrupt-parent = <_intc>;
#interrupt-cells = <2>;
interrupts = <24 25 26 27 28 29 30 31>;
};

and after:

idu_intc: idu-interrupt-controller {
compatible = "snps,archs-idu-intc";
interrupt-controller;
interrupt-parent = <_intc>;
#interrupt-cells = <2>;
};

Signed-off-by: Yuriy Kolerov <yuriy.kole...@synopsys.com>
---
 arch/arc/include/asm/irq.h   |  3 +++
 arch/arc/kernel/intc-arcv2.c |  7 ++-
 arch/arc/kernel/mcip.c   | 31 +++
 3 files changed, 28 insertions(+), 13 deletions(-)

diff --git a/arch/arc/include/asm/irq.h b/arch/arc/include/asm/irq.h
index dfa09e3..1970d78c 100644
--- a/arch/arc/include/asm/irq.h
+++ b/arch/arc/include/asm/irq.h
@@ -18,6 +18,9 @@
  */
 #define NR_CPU_IRQS240
 
+/* A fixed number of exceptions which occupy first interrupt lines */
+#define NR_EXCEPTIONS  16
+
 /*
  * ARCv2 can support 240 interrupts in the core interrupts controllers and
  * 128 interrupts in IDU. Thus 512 virtual IRQs must be enough for most
diff --git a/arch/arc/kernel/intc-arcv2.c b/arch/arc/kernel/intc-arcv2.c
index a9a7497..b2a6de4 100644
--- a/arch/arc/kernel/intc-arcv2.c
+++ b/arch/arc/kernel/intc-arcv2.c
@@ -123,11 +123,16 @@ static int __init
 init_onchip_IRQ(struct device_node *intc, struct device_node *parent)
 {
struct irq_domain *root_domain;
+   struct bcr_irq_arcv2 irq_bcr;
+   unsigned int nr_cpu_irqs;
+
+   READ_BCR(ARC_REG_IRQ_BCR, irq_bcr);
+   nr_cpu_irqs = irq_bcr.irqs + NR_EXCEPTIONS;
 
if (parent)
panic("DeviceTree incore intc not a root irq controller\n");
 
-   root_domain = irq_domain_add_linear(intc, NR_CPU_IRQS, _irq_ops, 
NULL);
+   root_domain = irq_domain_add_linear(intc, nr_cpu_irqs, _irq_ops, 
NULL);
if (!root_domain)
panic("root irq domain not avail\n");
 
diff --git a/arch/arc/kernel/mcip.c b/arch/arc/kernel/mcip.c
index 9988b42..45d45fc 100644
--- a/arch/arc/kernel/mcip.c
+++ b/arch/arc/kernel/mcip.c
@@ -157,15 +157,20 @@ static void idu_set_mode(unsigned int cmn_irq, unsigned 
int lvl,
__mcip_cmd_data(CMD_IDU_SET_MODE, cmn_irq, data.word);
 }
 
-static void idu_irq_mask(struct irq_data *data)
+static void idu_irq_mask_raw(irq_hw_number_t hwirq)
 {
unsigned long flags;
 
raw_spin_lock_irqsave(_lock, flags);
-   __mcip_cmd_data(CMD_IDU_SET_MASK, data->hwirq, 1);
+   __mcip_cmd_data(CMD_IDU_SET_MASK, hwirq, 1);
raw_spin_unlock_irqrestore(_lock, flags);
 }
 
+static void idu_irq_mask(struct irq_data *data)
+{
+   idu_irq_mask_raw(data->hwirq);
+}
+
 static void idu_irq_unmask(struct irq_data *data)
 {
unsigned long flags;
@@ -231,14 +236,12 @@ static struct irq_chip idu_irq_chip = {
 
 };
 
-static irq_hw_number_t idu_first_hwirq;
-
 static void idu_cascade_isr(struct irq_desc *desc)
 {
struct irq_domain *idu_domain = irq_desc_get_handler_data(desc);
struct irq_chip *core_chip = irq_desc_get_chip(desc);
irq_hw_number_t core_hwirq = irqd_to_hwirq(irq_desc_get_irq_data(desc));
-   irq_hw_number_t idu_hwirq = core_hwirq - idu_first_hwirq;
+   irq_hw_number_t idu_hwirq = core_hwirq - FIRST_EXT_IRQ;
 
chained_irq_enter(core_chip, desc);
generic_handle_irq(irq_find_mapping(idu_domain, idu_hwirq));
@@ -284,33 +287,37 @@ static int __init
 idu_of_init(struct device_node *intc, struct device_node *parent)
 {
struct irq_domain *domain;
-   /* Read IDU BCR to confirm nr_irqs */
-   int nr_irqs = of_irq_count(intc);
+   int nr_irqs;
int i, virq;
struct mcip_bcr mp;
+   struct mcip_idu_bcr idu_bcr;
 
READ_BCR(ARC_REG_MCIP_BCR, mp);
 
if (!mp.idu)
panic("IDU not detected, but DeviceTree using it");
 
-   pr_info("MCIP: IDU referenced from Devicetree %d irqs\n", nr_irqs);
+   READ_BCR(ARC_REG_MCIP_IDU_BCR, idu_bcr);
+   nr_irqs = mcip_idu_bcr_to_nr_irqs(idu_bcr);
+
+   pr_info("MCIP: IDU supports %u common irqs\n", nr_irqs);
 
domain = irq_domain_add_linear(intc, nr_irqs, _irq_ops, NULL);
 
/* Parent interrupts (core-intc) are already mapped */
 
for (i = 0; i < nr_irqs; i++) {
+   /* Mask all common interrupts by default */
+   idu_irq_mask_raw(i);
+
/*
 * Return parent uplink IRQs (towards core intc) 24,25,.
 * this

[PATCH 6/6] ARCv2: IRQ: Set a default priority for all core interrupts

2017-01-27 Thread Yuriy Kolerov
After reset all interrupts in the core interrupt controller has
the highest priority P0. If the platform supports Fast IRQs and
has more than 1 banks of registers then CPU automatically switch
banks of registers when P0 interrupt comes.

The problem is that the kernel expects that by default switching
of banks is not used by all interrupts. It is necessary to set a
default nonzero priority for all available interrupts to avoid
undefined behaviour.

Signed-off-by: Yuriy Kolerov <yuriy.kole...@synopsys.com>
---
 arch/arc/kernel/intc-arcv2.c | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/arch/arc/kernel/intc-arcv2.c b/arch/arc/kernel/intc-arcv2.c
index b2a6de4..b9d9ce6 100644
--- a/arch/arc/kernel/intc-arcv2.c
+++ b/arch/arc/kernel/intc-arcv2.c
@@ -22,7 +22,7 @@
  */
 void arc_init_IRQ(void)
 {
-   unsigned int tmp, irq_prio;
+   unsigned int tmp, irq_prio, i;
 
struct bcr_irq_arcv2 irq_bcr;
struct aux_irq_ctrl_arcv2 ictrl;
@@ -51,6 +51,16 @@ void arc_init_IRQ(void)
irq_prio + 1, ARCV2_IRQ_DEF_PRIO,
irq_bcr.firq ? " FIRQ (not used)":"");
 
+   /*
+* Set a default priority for all available interrupts to prevent
+* switching of register banks if Fast IRQ and multiple register banks
+* are supported by CPU.
+*/
+   for (i = NR_EXCEPTIONS; i < irq_bcr.irqs + NR_EXCEPTIONS; i++) {
+   write_aux_reg(AUX_IRQ_SELECT, i);
+   write_aux_reg(AUX_IRQ_PRIORITY, ARCV2_IRQ_DEF_PRIO);
+   }
+
/* setup status32, don't enable intr yet as kernel doesn't want */
tmp = read_aux_reg(ARC_REG_STATUS32);
tmp |= STATUS_AD_MASK | (ARCV2_IRQ_DEF_PRIO << 1);
-- 
2.7.4



___
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc


[PATCH 3/6] ARCv2: IRQ: Add macro for the first external interrupt number

2017-01-27 Thread Yuriy Kolerov
Signed-off-by: Yuriy Kolerov <yuriy.kole...@synopsys.com>
---
 arch/arc/include/asm/irq.h   | 1 +
 arch/arc/kernel/intc-arcv2.c | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/arc/include/asm/irq.h b/arch/arc/include/asm/irq.h
index c0fa0d2..e61ad30 100644
--- a/arch/arc/include/asm/irq.h
+++ b/arch/arc/include/asm/irq.h
@@ -16,6 +16,7 @@
 #ifdef CONFIG_ISA_ARCV2
 #define IPI_IRQ19
 #define SOFTIRQ_IRQ21
+#define FIRST_EXT_IRQ  24
 #endif
 
 #include 
diff --git a/arch/arc/kernel/intc-arcv2.c b/arch/arc/kernel/intc-arcv2.c
index 2f31bb1..a9a7497 100644
--- a/arch/arc/kernel/intc-arcv2.c
+++ b/arch/arc/kernel/intc-arcv2.c
@@ -98,7 +98,7 @@ static int arcv2_irq_map(struct irq_domain *d, unsigned int 
irq,
 * core intc IRQs [16, 23]:
 * Statically assigned always private-per-core (Timers, WDT, IPI, PCT)
 */
-   if (hw < 24) {
+   if (hw < FIRST_EXT_IRQ) {
/*
 * A subsequent request_percpu_irq() fails if percpu_devid is
 * not set. That in turns sets NOAUTOEN, meaning each core needs
-- 
2.7.4



___
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc


[PATCH 2/6] ARCv2: MCIP: Add structure for build register of IDU

2017-01-27 Thread Yuriy Kolerov
This structure is necessary for retrieving of supported
number of common interrupts in IDU interrupt controller.

Signed-off-by: Yuriy Kolerov <yuriy.kole...@synopsys.com>
---
 include/soc/arc/mcip.h | 17 +
 1 file changed, 17 insertions(+)

diff --git a/include/soc/arc/mcip.h b/include/soc/arc/mcip.h
index 6902c2a..798c01b 100644
--- a/include/soc/arc/mcip.h
+++ b/include/soc/arc/mcip.h
@@ -14,6 +14,7 @@
 #include 
 
 #define ARC_REG_MCIP_BCR   0x0d0
+#define ARC_REG_MCIP_IDU_BCR   0x0D5
 #define ARC_REG_MCIP_CMD   0x600
 #define ARC_REG_MCIP_WDATA 0x601
 #define ARC_REG_MCIP_READBACK  0x602
@@ -69,6 +70,22 @@ struct mcip_bcr {
 #endif
 };
 
+struct mcip_idu_bcr {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+   unsigned int pad:21, cirqnum:3, ver:8;
+#else
+   unsigned int ver:8, cirqnum:3, pad:21;
+#endif
+};
+
+
+/*
+ * Build register for IDU contains not an actual number of supported common
+ * interrupts but an exponent of 2 which must be multiplied by 4 to
+ * get a number of supported common interrupts.
+ */
+#define mcip_idu_bcr_to_nr_irqs(bcr) (4 * (1 << (bcr).cirqnum))
+
 /*
  * MCIP programming model
  *
-- 
2.7.4



___
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc


[PATCH 4/6] ARCv2: IRQ: Remove option for setting number of interrupts

2017-01-27 Thread Yuriy Kolerov
When you set a value of ARC_NUMBER_OF_INTERRUPTS option
it affects only a size of the interrupts table but macros
for number of virtual interrupts (NR_IRQS) and for number
of hardware interrupts (NR_CPU_IRQS) remain unchanged.
Moreover usage of ARC_NUMBER_OF_INTERRUPTS is bad for
portability since it is not possible to change size
of the interrupts table after linkage.

This patch makes these changes in IRQ subsystem:

  * NR_CPU_IRQS defines a maximum number of hardware interrupts.
  * Remove ARC_NUMBER_OF_INTERRUPTS option and create interrupts
table for all possible hardware interrupts.
  * Increase a maximum number of virtual IRQs to 512. ARCv2 can
support 240 interrupts in the core interrupts controllers
and 128 interrupts in IDU. Thus 512 virtual IRQs must be
enough for most configurations of boards.

Signed-off-by: Yuriy Kolerov <yuriy.kole...@synopsys.com>
---
 arch/arc/Kconfig  | 11 ---
 arch/arc/include/asm/irq.h| 28 +---
 arch/arc/kernel/entry-arcv2.S |  3 ++-
 3 files changed, 27 insertions(+), 15 deletions(-)

diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index 283099c..ba15cb8 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -412,17 +412,6 @@ config ARC_HAS_DIV_REM
bool "Insn: div, divu, rem, remu"
default y
 
-config ARC_NUMBER_OF_INTERRUPTS
-   int "Number of interrupts"
-   range 8 240
-   default 32
-   help
- This defines the number of interrupts on the ARCv2HS core.
- It affects the size of vector table.
- The initial 8 IRQs are fixed (Timer, ICI etc) and although 
configurable
- in hardware, it keep things simple for Linux to assume they are always
- present.
-
 endif  # ISA_ARCV2
 
 endmenu   # "ARC CPU Configuration"
diff --git a/arch/arc/include/asm/irq.h b/arch/arc/include/asm/irq.h
index e61ad30..dfa09e3 100644
--- a/arch/arc/include/asm/irq.h
+++ b/arch/arc/include/asm/irq.h
@@ -9,19 +9,41 @@
 #ifndef __ASM_ARC_IRQ_H
 #define __ASM_ARC_IRQ_H
 
-#define NR_CPU_IRQS32  /* number of interrupt lines of ARC770 CPU */
-#define NR_IRQS128 /* allow some CPU external IRQ handling */
+#ifdef CONFIG_ISA_ARCV2
+
+/*
+ * A maximum number of supported interrupts in the core interrupt controller.
+ * This number is not equal to the maximum interrupt number (256) because
+ * first 16 lines are reserved for exceptions and are not configurable.
+ */
+#define NR_CPU_IRQS240
+
+/*
+ * ARCv2 can support 240 interrupts in the core interrupts controllers and
+ * 128 interrupts in IDU. Thus 512 virtual IRQs must be enough for most
+ * configurations of boards.
+ */
+#define NR_IRQS512
 
 /* Platform Independent IRQs */
-#ifdef CONFIG_ISA_ARCV2
 #define IPI_IRQ19
 #define SOFTIRQ_IRQ21
 #define FIRST_EXT_IRQ  24
+
+#else
+
+#define NR_CPU_IRQS32  /* number of interrupt lines of ARC770 CPU */
+#define NR_IRQS128 /* allow some CPU external IRQ handling */
+
 #endif
 
+#ifndef __ASSEMBLY__
+
 #include 
 #include 
 
 extern void arc_init_IRQ(void);
 
 #endif
+
+#endif
diff --git a/arch/arc/kernel/entry-arcv2.S b/arch/arc/kernel/entry-arcv2.S
index 0b6388a..f22101e 100644
--- a/arch/arc/kernel/entry-arcv2.S
+++ b/arch/arc/kernel/entry-arcv2.S
@@ -13,6 +13,7 @@
 #include 
 #include 
 #include 
+#include 
 
.cpu HS
 
@@ -52,7 +53,7 @@ VECTORhandle_interrupt; unused
 VECTOR handle_interrupt; (23) unused
 # End of fixed IRQs
 
-.rept CONFIG_ARC_NUMBER_OF_INTERRUPTS - 8
+.rept NR_CPU_IRQS - 8
VECTOR  handle_interrupt
 .endr
 
-- 
2.7.4



___
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc


RE: [PATCH v3 3/3] ARCv2: MCIP: Deprecate setting of affinity in Device Tree

2017-01-23 Thread Yuriy Kolerov


> -Original Message-
> From: Vineet Gupta [mailto:vgu...@synopsys.com]
> Sent: Tuesday, January 03, 2017 9:11 PM
> To: Yuriy Kolerov <yuriy.kole...@synopsys.com>; linux-snps-
> a...@lists.infradead.org
> Cc: alexey.brod...@synopsys.com; linux-ker...@vger.kernel.org;
> marc.zyng...@arm.com
> Subject: Re: [PATCH v3 3/3] ARCv2: MCIP: Deprecate setting of affinity in
> Device Tree
> 
> On 12/28/2016 12:47 AM, Yuriy Kolerov wrote:
> > Ignore value of interrupt distribution mode for common interrupts in
> > IDU since setting of affinity using value from Device Tree is
> > deprecated in ARC. Originally it is done in idu_irq_xlate() function
> > and it is semantically wrong and does not guaranty that an affinity
> > value will be set properly. idu_irq_enable() function is better place
> > for initialization of common interrupts.
> >
> > By default send all common interrupts to all available online CPUs.
> 
> Is this a departure from our original idea to route everything only to boot 
> cpu
> ?
> Otherwise this looks OK to me !

I have come to the conclusion that now there is no way to route all interrupts 
to the boot CPU in a right manner. It may be implemented properly in the future.

> -Vineet
> 
> > The affinity of common interrupts in IDU must be set manually since in
> > some cases the kernel will not call irq_set_affinity() by itself:
> >
> >   1. When the kernel is not configured with support of SMP.
> >   2. When the kernel is configured with support of SMP but upper
> >  interrupt controllers does not support setting of the affinity
> >  and cannot propagate it to IDU.
> >
> > Signed-off-by: Yuriy Kolerov <yuriy.kole...@synopsys.com>
> > ---
> >  .../interrupt-controller/snps,archs-idu-intc.txt   |  3 ++
> >  arch/arc/kernel/mcip.c | 52 
> > +-
> >  2 files changed, 25 insertions(+), 30 deletions(-)
> >
> > diff --git
> > a/Documentation/devicetree/bindings/interrupt-controller/snps,archs-id
> > u-intc.txt
> > b/Documentation/devicetree/bindings/interrupt-controller/snps,archs-id
> > u-intc.txt
> > index 0dcb7c7..9446576 100644
> > ---
> > a/Documentation/devicetree/bindings/interrupt-controller/snps,archs-id
> > u-intc.txt
> > +++ b/Documentation/devicetree/bindings/interrupt-controller/snps,arch
> > +++ s-idu-intc.txt
> > @@ -15,6 +15,9 @@ Properties:
> >Second cell specifies the irq distribution mode to cores
> >   0=Round Robin; 1=cpu0, 2=cpu1, 4=cpu2, 8=cpu3
> >
> > +  The second cell in interrupts property is deprecated and may be
> > + ignored by  the kernel.
> > +
> >intc accessed via the special ARC AUX register interface, hence "reg"
> property
> >is not specified.
> >
> > diff --git a/arch/arc/kernel/mcip.c b/arch/arc/kernel/mcip.c index
> > be131b2..d492a3c 100644
> > --- a/arch/arc/kernel/mcip.c
> > +++ b/arch/arc/kernel/mcip.c
> > @@ -175,7 +175,6 @@ static void idu_irq_unmask(struct irq_data *data)
> > raw_spin_unlock_irqrestore(_lock, flags);  }
> >
> > -#ifdef CONFIG_SMP
> >  static int
> >  idu_irq_set_affinity(struct irq_data *data, const struct cpumask
> *cpumask,
> >  bool force)
> > @@ -205,12 +204,27 @@ idu_irq_set_affinity(struct irq_data *data,
> > const struct cpumask *cpumask,
> >
> > return IRQ_SET_MASK_OK;
> >  }
> > -#endif
> > +
> > +static void idu_irq_enable(struct irq_data *data) {
> > +   /*
> > +* By default send all common interrupts to all available online CPUs.
> > +* The affinity of common interrupts in IDU must be set manually
> since
> > +* in some cases the kernel will not call irq_set_affinity() by itself:
> > +*   1. When the kernel is not configured with support of SMP.
> > +*   2. When the kernel is configured with support of SMP but upper
> > +*  interrupt controllers does not support setting of the affinity
> > +*  and cannot propagate it to IDU.
> > +*/
> > +   idu_irq_set_affinity(data, cpu_online_mask, false);
> > +   idu_irq_unmask(data);
> > +}
> >
> >  static struct irq_chip idu_irq_chip = {
> > .name   = "MCIP IDU Intc",
> > .irq_mask   = idu_irq_mask,
> > .irq_unmask = idu_irq_unmask,
> > +   .irq_enable = idu_irq_enable,
> >  #ifdef CONFIG_SMP
> > .irq_set_affinity   = idu_irq_set_affinity,
> >  #endif
> > @@ -243,36 +257,14 @@ static 

[PATCH v3 1/3] ARC: IRQ: Use hwirq instead of virq in mask/unmask

2016-12-28 Thread Yuriy Kolerov
It is necessary to use hwirq instead of virq when you communicate
with an interrupt controller since there is no guaranty that virq
numbers match hwirq numbers.

Signed-off-by: Yuriy Kolerov <yuriy.kole...@synopsys.com>
---
 arch/arc/kernel/intc-arcv2.c   | 6 +++---
 arch/arc/kernel/intc-compact.c | 4 ++--
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/arch/arc/kernel/intc-arcv2.c b/arch/arc/kernel/intc-arcv2.c
index 62b59409..fa171e1 100644
--- a/arch/arc/kernel/intc-arcv2.c
+++ b/arch/arc/kernel/intc-arcv2.c
@@ -79,20 +79,20 @@ void arc_init_IRQ(void)
 
 static void arcv2_irq_mask(struct irq_data *data)
 {
-   write_aux_reg(AUX_IRQ_SELECT, data->irq);
+   write_aux_reg(AUX_IRQ_SELECT, data->hwirq);
write_aux_reg(AUX_IRQ_ENABLE, 0);
 }
 
 static void arcv2_irq_unmask(struct irq_data *data)
 {
-   write_aux_reg(AUX_IRQ_SELECT, data->irq);
+   write_aux_reg(AUX_IRQ_SELECT, data->hwirq);
write_aux_reg(AUX_IRQ_ENABLE, 1);
 }
 
 void arcv2_irq_enable(struct irq_data *data)
 {
/* set default priority */
-   write_aux_reg(AUX_IRQ_SELECT, data->irq);
+   write_aux_reg(AUX_IRQ_SELECT, data->hwirq);
write_aux_reg(AUX_IRQ_PRIORITY, irq_prio);
 
/*
diff --git a/arch/arc/kernel/intc-compact.c b/arch/arc/kernel/intc-compact.c
index ce9deb9..8c1fd5c 100644
--- a/arch/arc/kernel/intc-compact.c
+++ b/arch/arc/kernel/intc-compact.c
@@ -57,7 +57,7 @@ static void arc_irq_mask(struct irq_data *data)
unsigned int ienb;
 
ienb = read_aux_reg(AUX_IENABLE);
-   ienb &= ~(1 << data->irq);
+   ienb &= ~(1 << data->hwirq);
write_aux_reg(AUX_IENABLE, ienb);
 }
 
@@ -66,7 +66,7 @@ static void arc_irq_unmask(struct irq_data *data)
unsigned int ienb;
 
ienb = read_aux_reg(AUX_IENABLE);
-   ienb |= (1 << data->irq);
+   ienb |= (1 << data->hwirq);
write_aux_reg(AUX_IENABLE, ienb);
 }
 
-- 
2.7.4



___
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc


[PATCH v3 2/3] ARCv2: IRQ: Call entry/exit functions for chained handlers in MCIP

2016-12-28 Thread Yuriy Kolerov
It is necessary to call entry/exit functions for parent interrupt
controllers for proper masking/unmasking of interrupt lines.

Signed-off-by: Yuriy Kolerov <yuriy.kole...@synopsys.com>
---
 arch/arc/kernel/mcip.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/arch/arc/kernel/mcip.c b/arch/arc/kernel/mcip.c
index f39142a..be131b2 100644
--- a/arch/arc/kernel/mcip.c
+++ b/arch/arc/kernel/mcip.c
@@ -10,6 +10,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -221,10 +222,13 @@ static irq_hw_number_t idu_first_hwirq;
 static void idu_cascade_isr(struct irq_desc *desc)
 {
struct irq_domain *idu_domain = irq_desc_get_handler_data(desc);
+   struct irq_chip *core_chip = irq_desc_get_chip(desc);
irq_hw_number_t core_hwirq = irqd_to_hwirq(irq_desc_get_irq_data(desc));
irq_hw_number_t idu_hwirq = core_hwirq - idu_first_hwirq;
 
+   chained_irq_enter(core_chip, desc);
generic_handle_irq(irq_find_mapping(idu_domain, idu_hwirq));
+   chained_irq_exit(core_chip, desc);
 }
 
 static int idu_irq_map(struct irq_domain *d, unsigned int virq, 
irq_hw_number_t hwirq)
-- 
2.7.4



___
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc


[PATCH v3 3/3] ARCv2: MCIP: Deprecate setting of affinity in Device Tree

2016-12-28 Thread Yuriy Kolerov
Ignore value of interrupt distribution mode for common interrupts in
IDU since setting of affinity using value from Device Tree is deprecated
in ARC. Originally it is done in idu_irq_xlate() function and it is
semantically wrong and does not guaranty that an affinity value will be
set properly. idu_irq_enable() function is better place for
initialization of common interrupts.

By default send all common interrupts to all available online CPUs.
The affinity of common interrupts in IDU must be set manually since
in some cases the kernel will not call irq_set_affinity() by itself:

  1. When the kernel is not configured with support of SMP.
  2. When the kernel is configured with support of SMP but upper
 interrupt controllers does not support setting of the affinity
 and cannot propagate it to IDU.

Signed-off-by: Yuriy Kolerov <yuriy.kole...@synopsys.com>
---
 .../interrupt-controller/snps,archs-idu-intc.txt   |  3 ++
 arch/arc/kernel/mcip.c | 52 +-
 2 files changed, 25 insertions(+), 30 deletions(-)

diff --git 
a/Documentation/devicetree/bindings/interrupt-controller/snps,archs-idu-intc.txt
 
b/Documentation/devicetree/bindings/interrupt-controller/snps,archs-idu-intc.txt
index 0dcb7c7..9446576 100644
--- 
a/Documentation/devicetree/bindings/interrupt-controller/snps,archs-idu-intc.txt
+++ 
b/Documentation/devicetree/bindings/interrupt-controller/snps,archs-idu-intc.txt
@@ -15,6 +15,9 @@ Properties:
   Second cell specifies the irq distribution mode to cores
  0=Round Robin; 1=cpu0, 2=cpu1, 4=cpu2, 8=cpu3
 
+  The second cell in interrupts property is deprecated and may be ignored by
+  the kernel.
+
   intc accessed via the special ARC AUX register interface, hence "reg" 
property
   is not specified.
 
diff --git a/arch/arc/kernel/mcip.c b/arch/arc/kernel/mcip.c
index be131b2..d492a3c 100644
--- a/arch/arc/kernel/mcip.c
+++ b/arch/arc/kernel/mcip.c
@@ -175,7 +175,6 @@ static void idu_irq_unmask(struct irq_data *data)
raw_spin_unlock_irqrestore(_lock, flags);
 }
 
-#ifdef CONFIG_SMP
 static int
 idu_irq_set_affinity(struct irq_data *data, const struct cpumask *cpumask,
 bool force)
@@ -205,12 +204,27 @@ idu_irq_set_affinity(struct irq_data *data, const struct 
cpumask *cpumask,
 
return IRQ_SET_MASK_OK;
 }
-#endif
+
+static void idu_irq_enable(struct irq_data *data)
+{
+   /*
+* By default send all common interrupts to all available online CPUs.
+* The affinity of common interrupts in IDU must be set manually since
+* in some cases the kernel will not call irq_set_affinity() by itself:
+*   1. When the kernel is not configured with support of SMP.
+*   2. When the kernel is configured with support of SMP but upper
+*  interrupt controllers does not support setting of the affinity
+*  and cannot propagate it to IDU.
+*/
+   idu_irq_set_affinity(data, cpu_online_mask, false);
+   idu_irq_unmask(data);
+}
 
 static struct irq_chip idu_irq_chip = {
.name   = "MCIP IDU Intc",
.irq_mask   = idu_irq_mask,
.irq_unmask = idu_irq_unmask,
+   .irq_enable = idu_irq_enable,
 #ifdef CONFIG_SMP
.irq_set_affinity   = idu_irq_set_affinity,
 #endif
@@ -243,36 +257,14 @@ static int idu_irq_xlate(struct irq_domain *d, struct 
device_node *n,
 const u32 *intspec, unsigned int intsize,
 irq_hw_number_t *out_hwirq, unsigned int *out_type)
 {
-   irq_hw_number_t hwirq = *out_hwirq = intspec[0];
-   int distri = intspec[1];
-   unsigned long flags;
-
+   /*
+* Ignore value of interrupt distribution mode for common interrupts in
+* IDU which resides in intspec[1] since setting an affinity using value
+* from Device Tree is deprecated in ARC.
+*/
+   *out_hwirq = intspec[0];
*out_type = IRQ_TYPE_NONE;
 
-   /* XXX: validate distribution scheme again online cpu mask */
-   if (distri == 0) {
-   /* 0 - Round Robin to all cpus, otherwise 1 bit per core */
-   raw_spin_lock_irqsave(_lock, flags);
-   idu_set_dest(hwirq, BIT(num_online_cpus()) - 1);
-   idu_set_mode(hwirq, IDU_M_TRIG_LEVEL, IDU_M_DISTRI_RR);
-   raw_spin_unlock_irqrestore(_lock, flags);
-   } else {
-   /*
-* DEST based distribution for Level Triggered intr can only
-* have 1 CPU, so generalize it to always contain 1 cpu
-*/
-   int cpu = ffs(distri);
-
-   if (cpu != fls(distri))
-   pr_warn("IDU irq %lx distri mode set to cpu %x\n",
-   hwirq, cpu);
-
-   raw_spin_lock_irqsave(_lock, flags);
-   idu_set_dest(hwirq, cpu)

[PATCH v3 0/3] Fixes for IRQ subsystem

2016-12-28 Thread Yuriy Kolerov
First 2 patches fix potential bugs in IRQ subsystem. The third one
deprecates setting of affinity in Device Tree and moves setting of
the initial value of affinity to irq_enable() function of IRQ chip.

Changes for v3:
 * Remove patch for manual setting of the global variable
   irq_default_affinity to avoid messing with generic code.
 * Fix 2 potential bugs.
 * Use irq_enable() for setting of the initial value for
   affinity in IDU.

Changes for v2:
 * Set the value of irq_default_affinity to the boot CPU. It is
   necessary because if an interrupt controller is connected to
   IDU then set_affinity() is not called for IDU interrupts and
   the real affinity of IDU does not correspond to the value
   in the descriptor of IRQ (irq_default_affinity by default).


Yuriy Kolerov (3):
  ARC: IRQ: Use hwirq instead of virq in mask/unmask
  ARCv2: IRQ: Call entry/exit functions for chained handlers in MCIP
  ARCv2: MCIP: Deprecate setting of affinity in Device Tree

 .../interrupt-controller/snps,archs-idu-intc.txt   |  3 ++
 arch/arc/kernel/intc-arcv2.c   |  6 +--
 arch/arc/kernel/intc-compact.c |  4 +-
 arch/arc/kernel/mcip.c | 56 ++
 4 files changed, 34 insertions(+), 35 deletions(-)

-- 
2.7.4



___
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc


[PATCH v2 1/2] ARC: SMP: Set the default affinity to the boot cpu

2016-12-09 Thread Yuriy Kolerov
By default the kernel sets a value for default affinity which may
not correspond to the real bitmap of potentially online CPUs. E.g.
for ARC HS processors with 2 cores the default value of affinity in
the kernel may be 0xF and it is wrong in this case. This happens
because init_irq_default_affinity() sets all bits in
irq_default_affinity variable by default.

It is better to set the default value of affinity to the boot core
to guarantee that value of irq_default_affinity contains at least
one valid online CPU during the early stage of booting. It is
necessary for proper configuration of affinity for common interrupt.

Signed-off-by: Yuriy Kolerov <yuriy.kole...@synopsys.com>
---
 arch/arc/kernel/irq.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/arch/arc/kernel/irq.c b/arch/arc/kernel/irq.c
index 538b36a..e53bfd5 100644
--- a/arch/arc/kernel/irq.c
+++ b/arch/arc/kernel/irq.c
@@ -20,6 +20,12 @@
  */
 void __init init_IRQ(void)
 {
+#ifdef CONFIG_SMP
+   /* Set the default affinity to the boot cpu. */
+   cpumask_clear(irq_default_affinity);
+   cpumask_set_cpu(smp_processor_id(), irq_default_affinity);
+#endif
+
/*
 * process the entire interrupt tree in one go
 * Any external intc will be setup provided DT chains them
-- 
2.7.4



___
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc


[PATCH v2 2/2] ARCv2: MCIP: Deprecate setting of affinity in Device Tree

2016-12-09 Thread Yuriy Kolerov
Ignore value of interrupt distribution mode for common interrupts in
IDU since setting of affinity using value from Device Tree is deprecated
in ARC. Originally it is done in idu_irq_xlate() function and it is
semantically wrong and does not guaranty that an affinity value will be
set properly. idu_irq_map() function is better place since it is called
once for each IRQ.

The affinity of common interrupts in IDU must be set manually since
in some cases the kernel will not call irq_set_affinity() by itself:

1. When the kernel is not configured with support of SMP.
2. When the kernel is configured with support of SMP but upper
   interrupt controllers does not support setting of the affinity
   and cannot propagate it to IDU.

By default send all common interrupts to the boot CPU. If the kernel
has support of SMP then use irq_default_affinity as the affinity
for IDU common interrupts since it is set to the boot CPU by default.
If the kernel is configured without support of SMP then use
cpu_online_mask since in this case it must always contain a valid
bitmap with only 1 online CPU.

Signed-off-by: Yuriy Kolerov <yuriy.kole...@synopsys.com>
---
 .../interrupt-controller/snps,archs-idu-intc.txt   |  3 ++
 arch/arc/kernel/mcip.c | 60 +++---
 2 files changed, 33 insertions(+), 30 deletions(-)

diff --git 
a/Documentation/devicetree/bindings/interrupt-controller/snps,archs-idu-intc.txt
 
b/Documentation/devicetree/bindings/interrupt-controller/snps,archs-idu-intc.txt
index 0dcb7c7..9446576 100644
--- 
a/Documentation/devicetree/bindings/interrupt-controller/snps,archs-idu-intc.txt
+++ 
b/Documentation/devicetree/bindings/interrupt-controller/snps,archs-idu-intc.txt
@@ -15,6 +15,9 @@ Properties:
   Second cell specifies the irq distribution mode to cores
  0=Round Robin; 1=cpu0, 2=cpu1, 4=cpu2, 8=cpu3
 
+  The second cell in interrupts property is deprecated and may be ignored by
+  the kernel.
+
   intc accessed via the special ARC AUX register interface, hence "reg" 
property
   is not specified.
 
diff --git a/arch/arc/kernel/mcip.c b/arch/arc/kernel/mcip.c
index f39142a..5b36f7b 100644
--- a/arch/arc/kernel/mcip.c
+++ b/arch/arc/kernel/mcip.c
@@ -174,7 +174,6 @@ static void idu_irq_unmask(struct irq_data *data)
raw_spin_unlock_irqrestore(_lock, flags);
 }
 
-#ifdef CONFIG_SMP
 static int
 idu_irq_set_affinity(struct irq_data *data, const struct cpumask *cpumask,
 bool force)
@@ -204,7 +203,6 @@ idu_irq_set_affinity(struct irq_data *data, const struct 
cpumask *cpumask,
 
return IRQ_SET_MASK_OK;
 }
-#endif
 
 static struct irq_chip idu_irq_chip = {
.name   = "MCIP IDU Intc",
@@ -229,9 +227,33 @@ static void idu_cascade_isr(struct irq_desc *desc)
 
 static int idu_irq_map(struct irq_domain *d, unsigned int virq, 
irq_hw_number_t hwirq)
 {
+   struct irq_data *irqd = irq_get_irq_data(virq);
+
irq_set_chip_and_handler(virq, _irq_chip, handle_level_irq);
irq_set_status_flags(virq, IRQ_MOVE_PCNTXT);
 
+   /*
+* The affinity of common interrupts in IDU must be set manually since
+* in some cases the kernel will not call irq_set_affinity() by itself:
+*
+*   1. When the kernel is not configured with support of SMP.
+*   2. When the kernel is configured with support of SMP but upper
+*  interrupt controllers does not support setting of the affinity
+*  and cannot propagate it to IDU.
+*
+* By default send all common interrupts to the boot CPU. If the kernel
+* has support of SMP then use irq_default_affinity as the affinity
+* for IDU common interrupts since it is set to the boot CPU by default.
+* If the kernel is configured without support of SMP then use
+* cpu_online_mask since in this case it must always contain a valid
+* bitmap with only 1 online CPU.
+*/
+#ifdef CONFIG_SMP
+   idu_irq_set_affinity(irqd, irq_default_affinity, false);
+#else
+   idu_irq_set_affinity(irqd, cpu_online_mask, false);
+#endif
+
return 0;
 }
 
@@ -239,36 +261,14 @@ static int idu_irq_xlate(struct irq_domain *d, struct 
device_node *n,
 const u32 *intspec, unsigned int intsize,
 irq_hw_number_t *out_hwirq, unsigned int *out_type)
 {
-   irq_hw_number_t hwirq = *out_hwirq = intspec[0];
-   int distri = intspec[1];
-   unsigned long flags;
-
+   /*
+* Ignore value of interrupt distribution mode for common interrupts in
+* IDU which resides in intspec[1] since setting an affinity using value
+* from Device Tree is deprecated in ARC.
+*/
+   *out_hwirq = intspec[0];
*out_type = IRQ_TYPE_NONE;
 
-   /* XXX: validate distribution scheme again online cpu mask */
-   if (distri == 0) {
-   /* 0 - Round Robi

RE: [RFC] ARC: mm: Restrict definition of pfn_valid() macro for CONFIG_FLATMEM

2016-12-02 Thread Yuriy Kolerov
> -Original Message-
> From: Vineet Gupta [mailto:vgu...@synopsys.com]
> Sent: Wednesday, November 30, 2016 7:55 PM
> To: Yuriy Kolerov <yuriy.kole...@synopsys.com>; Michal Hocko
> <mho...@kernel.org>
> Cc: linux-snps-arc@lists.infradead.org; alexey.brod...@synopsys.com; linux-
> ker...@vger.kernel.org
> Subject: Re: [RFC] ARC: mm: Restrict definition of pfn_valid() macro for
> CONFIG_FLATMEM
> 
> On 11/30/2016 06:21 AM, Yuriy Kolerov wrote:
> >> On Tue 29-11-16 18:29:06, Yuriy Kolerov wrote:
> >>> > > Despite the fact that subtraction of unsigned integers is a
> >>> > > defined behaviour however such operations can lead to unexpected
> >>> > > results. Thus it is better to check both left and right
> >>> > > boundaries to avoid potential bugs as it done in the generic page.h.
> >> >
> >> > Why and which code would use an out of range pfn? Why other arches
> >> > do not need to care?
> > Actually some arches do care about checking of both left and right
> boundaries (e.g. avr32, sparc, etc). The problem is that a value of pfn may be
> calculated incorrectly in some places of the kernel. E.g. not long ago I sent 
> a
> patch which fixes truncation of the most significant byte in pfn/pte in some
> cases (in the kernel with PAE40, however it is not a FLATMEM case). So such
> situations can happens in the most unexpected places.
> >
> 
> So the point is - is this a preventive fix (desired thing) or it being there 
> would
> have helped find the PAE40 bug earlier / easier. Woudl it have prevented the
> kernel crash. If so then this is a nobrainer fix.

This fix can help to find bugs which are related to wrong pfn values and only 
for FLATMEM case (usually when PAE40 is turned off). However I have just 
figured out that it is impossible to pass such bad unsigned pfn value which 
passes pfn_valid() check (usually the kernel passes a value from unsigned long 
variable)... This fix may help in cases when the kernel accidently passes a 
signed long value as pfn to the macro. Frankly speaking there are low chances 
that such thing can ever happen so I'm a little paranoid about it.

> BTW did you try to gauge the code gen impact - this function gets pulled all
> over the place in mm code. So build kernel with and w/o change and do a
> scripts/bloat-o-meter

Report from that script (extra 112 bytes):

add/remove: 0/0 grow/shrink: 9/1 up/down: 122/-10 (112)
function old new   delta
set_zone_contiguous  212 248 +36
__pageblock_pfn_to_page  120 136 +16
vm_insert_pfn_prot   432 444 +12
vm_insert_pfn436 448 +12
kpagecount_read  360 372 +12
reserve_bootmem_region   110 120 +10
memremap 248 256  +8
kpageflags_read  840 848  +8
devm_memremap356 364  +8
pagetypeinfo_show752 742 -10
Total: Before=3785631, After=3785743, chg +0.00%

> -Vineet

___
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc


[RFC] ARC: mm: Restrict definition of pfn_valid() macro for CONFIG_FLATMEM

2016-11-29 Thread Yuriy Kolerov
Despite the fact that subtraction of unsigned integers is a defined
behaviour however such operations can lead to unexpected results. Thus
it is better to check both left and right boundaries to avoid potential
bugs as it done in the generic page.h.

Signed-off-by: Yuriy Kolerov <yuriy.kole...@synopsys.com>
---
 arch/arc/include/asm/page.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arc/include/asm/page.h b/arch/arc/include/asm/page.h
index 296c342..81cfc6c7 100644
--- a/arch/arc/include/asm/page.h
+++ b/arch/arc/include/asm/page.h
@@ -88,7 +88,7 @@ typedef pte_t * pgtable_t;
 #define ARCH_PFN_OFFSETvirt_to_pfn(CONFIG_LINUX_LINK_BASE)
 
 #ifdef CONFIG_FLATMEM
-#define pfn_valid(pfn) (((pfn) - ARCH_PFN_OFFSET) < max_mapnr)
+#define pfn_valid(pfn) ((pfn) >= ARCH_PFN_OFFSET && ((pfn) - 
ARCH_PFN_OFFSET) < max_mapnr)
 #endif
 
 /*
-- 
2.7.4



___
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc


[PATCH] ARC: mm: PAE40: Cast pfn to pte_t in pfn_pte() macro

2016-11-27 Thread Yuriy Kolerov
Originally pfn_pte(pfn, prot) macro had this definition:

__pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot))

The value of pfn (Page Frame Number) is shifted to the left to get the
value of pte (Page Table Entry). Usually a 4-byte value is passed to
this macro as value of pfn. However if Linux is configured with support
of PAE40 then value of pte has 8-byte type because it must contain
additional 8 bits of the physical address. Thus if value of pfn
represents a physical page frame above of 4GB boundary then
shifting of pfn to the left by PAGE_SHIFT wipes most significant
bits of the 40-bit physical address.

As a result all physical addresses above of 4GB boundary in systems
with PAE40 are mapped to virtual address incorrectly. An error may
occur when the kernel tries to unmap such bad pages:

[ECR   ]: 0x00050100 => Invalid Read @ 0x41414144 by insn @ 0x801644c6
[EFA   ]: 0x41414144
[BLINK ]: unmap_page_range+0x134/0x700
[ERET  ]: unmap_page_range+0x17a/0x700
[STAT32]: 0x8008021e : IE K
BTA: 0x801644c6  SP: 0x901a5e84  FP: 0x5ff35de8
LPS: 0x8026462c LPE: 0x80264630 LPC: 0x
r00: 0x8fcc4fc0 r01: 0x2fe68000 r02: 0x41414140
r03: 0x2c05c000 r04: 0x2fe6a000 r05: 0x0009
r06: 0x901b6898 r07: 0x2fe68000 r08: 0x0001
r09: 0x804a807c r10: 0x067e r11: 0x
r12: 0x80164480
Stack Trace:
  unmap_page_range+0x17a/0x700
  unmap_vmas+0x46/0x64
  do_munmap+0x210/0x450
  SyS_munmap+0x2c/0x50
  EV_Trap+0xfc/0x100

So the value of pfn must be casted to pte_t before shifting to
ensure that 40-bit address will not be truncated:

__pte(((pte_t) (pfn) << PAGE_SHIFT) | pgprot_val(prot))

Signed-off-by: Yuriy Kolerov <yuriy.kole...@synopsys.com>
---
 arch/arc/include/asm/pgtable.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/arc/include/asm/pgtable.h b/arch/arc/include/asm/pgtable.h
index 89eeb37..77bc51c 100644
--- a/arch/arc/include/asm/pgtable.h
+++ b/arch/arc/include/asm/pgtable.h
@@ -280,7 +280,8 @@ static inline void pmd_set(pmd_t *pmdp, pte_t *ptep)
 
 #define pte_page(pte)  pfn_to_page(pte_pfn(pte))
 #define mk_pte(page, prot) pfn_pte(page_to_pfn(page), prot)
-#define pfn_pte(pfn, prot) __pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
+#define pfn_pte(pfn, prot) \
+   __pte(((pte_t) (pfn) << PAGE_SHIFT) | pgprot_val(prot))
 
 /* Don't use virt_to_pfn for macros below: could cause truncations for PAE40*/
 #define pte_pfn(pte)   (pte_val(pte) >> PAGE_SHIFT)
-- 
2.7.4



___
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc


RE: [PATCH] ARCv2: MCIP: Deprecate setting of affinity in Device Tree

2016-11-14 Thread Yuriy Kolerov
Hi Marc,

> -Original Message-
> From: Marc Zyngier [mailto:marc.zyng...@arm.com]
> Sent: Friday, November 11, 2016 6:29 PM
> To: Yuriy Kolerov <yuriy.kole...@synopsys.com>; linux-snps-
> a...@lists.infradead.org
> Cc: vineet.gup...@synopsys.com; alexey.brod...@synopsys.com;
> t...@linutronix.de; linux-ker...@vger.kernel.org
> Subject: Re: [PATCH] ARCv2: MCIP: Deprecate setting of affinity in Device
> Tree
> 
> Hi Yuriy,
> 
> On 11/11/16 14:38, Yuriy Kolerov wrote:
> > Ignore value of interrupt distribution mode for common interrupts in
> > IDU since setting of affinity using value from Device Tree is
> > deprecated in ARC. Originally it is done in idu_irq_xlate() function
> > and it is semantically wrong and does not guaranty that an affinity
> > value will be set properly.
> >
> > However it is necessary to set a default affinity value manually for
> > all common interrupts since initially all of them are disabled by IDU
> > (a CPU mask for common interrupts is set to 0 after CPU reset) and in
> > some cases the kernel cannot do it itself after initialization of
> > endpoint devices (e.g. when IRQ chip below of IDU does not support
> > setting of affinity and it cannot propagate an affinity value to IDU).
> >
> > By default send all common interrupts to the first online CPU.
> > Usually it is a boot CPU. If the kernel is built without support of
> > SMP then idu_irq_set_affinity() must be called manually since
> > irq_set_affinity() does nothing in this case.
> >
> > Signed-off-by: Yuriy Kolerov <yuriy.kole...@synopsys.com>
> > ---
> >  .../interrupt-controller/snps,archs-idu-intc.txt   |  3 ++
> >  arch/arc/kernel/mcip.c | 51 
> > +-
> >  2 files changed, 24 insertions(+), 30 deletions(-)
> >
> > diff --git
> > a/Documentation/devicetree/bindings/interrupt-controller/snps,archs-id
> > u-intc.txt
> > b/Documentation/devicetree/bindings/interrupt-controller/snps,archs-id
> > u-intc.txt
> > index 0dcb7c7..0607bab 100644
> > ---
> > a/Documentation/devicetree/bindings/interrupt-controller/snps,archs-id
> > u-intc.txt
> > +++ b/Documentation/devicetree/bindings/interrupt-controller/snps,arch
> > +++ s-idu-intc.txt
> > @@ -15,6 +15,9 @@ Properties:
> >Second cell specifies the irq distribution mode to cores
> >   0=Round Robin; 1=cpu0, 2=cpu1, 4=cpu2, 8=cpu3
> >
> > +  The second cell in interrupts property is deprecated and ignored.
> > + All common  interrupts are sent to the boot CPU core by default.
> > +
> 
> 
> This comment only affects the behaviour of the driver, and not the
> hardware. I'd rather see something along the lines of:
> 
> "The second cell is only a hint, and an operating system is free to ignore 
> it."
> 
> >intc accessed via the special ARC AUX register interface, hence "reg"
> property
> >is not specified.
> >
> > diff --git a/arch/arc/kernel/mcip.c b/arch/arc/kernel/mcip.c index
> > 6d90e4b..f36b8d7 100644
> > --- a/arch/arc/kernel/mcip.c
> > +++ b/arch/arc/kernel/mcip.c
> > @@ -174,7 +174,6 @@ static void idu_irq_unmask(struct irq_data *data)
> > raw_spin_unlock_irqrestore(_lock, flags);  }
> >
> > -#ifdef CONFIG_SMP
> >  static int
> >  idu_irq_set_affinity(struct irq_data *data, const struct cpumask
> *cpumask,
> >  bool force)
> > @@ -204,7 +203,6 @@ idu_irq_set_affinity(struct irq_data *data, const
> > struct cpumask *cpumask,
> >
> > return IRQ_SET_MASK_OK;
> >  }
> > -#endif
> >
> >  static struct irq_chip idu_irq_chip = {
> > .name   = "MCIP IDU Intc",
> > @@ -228,9 +226,24 @@ static void idu_cascade_isr(struct irq_desc
> > *desc)
> >
> >  static int idu_irq_map(struct irq_domain *d, unsigned int virq,
> > irq_hw_number_t hwirq)  {
> > +   cpumask_t affinity;
> > +
> > irq_set_chip_and_handler(virq, _irq_chip, handle_level_irq);
> > irq_set_status_flags(virq, IRQ_MOVE_PCNTXT);
> >
> > +   /* By default send all common interrupts to the first online CPU.
> > +* Usually it is a boot CPU. If the kernel is built without support
> > +* of SMP then idu_irq_set_affinity() must be called manually since
> > +* irq_set_affinity() does nothing in this case.
> > +*/
> > +   cpumask_copy(,
> cpumask_of(cpumask_first(cpu_online_mask)));
> > +
> > +#ifdef CONFIG_SMP
> > +   irq_set_affinity(virq, );
> 
> Ghhha. Please do

[PATCH] ARCv2: MCIP: Deprecate setting of affinity in Device Tree

2016-11-11 Thread Yuriy Kolerov
Ignore value of interrupt distribution mode for common interrupts in
IDU since setting of affinity using value from Device Tree is deprecated
in ARC. Originally it is done in idu_irq_xlate() function and it is
semantically wrong and does not guaranty that an affinity value will be
set properly.

However it is necessary to set a default affinity value manually for all
common interrupts since initially all of them are disabled by IDU (a
CPU mask for common interrupts is set to 0 after CPU reset) and in
some cases the kernel cannot do it itself after initialization of
endpoint devices (e.g. when IRQ chip below of IDU does not support
setting of affinity and it cannot propagate an affinity value to IDU).

By default send all common interrupts to the first online CPU.
Usually it is a boot CPU. If the kernel is built without support
of SMP then idu_irq_set_affinity() must be called manually since
irq_set_affinity() does nothing in this case.

Signed-off-by: Yuriy Kolerov <yuriy.kole...@synopsys.com>
---
 .../interrupt-controller/snps,archs-idu-intc.txt   |  3 ++
 arch/arc/kernel/mcip.c | 51 +-
 2 files changed, 24 insertions(+), 30 deletions(-)

diff --git 
a/Documentation/devicetree/bindings/interrupt-controller/snps,archs-idu-intc.txt
 
b/Documentation/devicetree/bindings/interrupt-controller/snps,archs-idu-intc.txt
index 0dcb7c7..0607bab 100644
--- 
a/Documentation/devicetree/bindings/interrupt-controller/snps,archs-idu-intc.txt
+++ 
b/Documentation/devicetree/bindings/interrupt-controller/snps,archs-idu-intc.txt
@@ -15,6 +15,9 @@ Properties:
   Second cell specifies the irq distribution mode to cores
  0=Round Robin; 1=cpu0, 2=cpu1, 4=cpu2, 8=cpu3
 
+  The second cell in interrupts property is deprecated and ignored. All common
+  interrupts are sent to the boot CPU core by default.
+
   intc accessed via the special ARC AUX register interface, hence "reg" 
property
   is not specified.
 
diff --git a/arch/arc/kernel/mcip.c b/arch/arc/kernel/mcip.c
index 6d90e4b..f36b8d7 100644
--- a/arch/arc/kernel/mcip.c
+++ b/arch/arc/kernel/mcip.c
@@ -174,7 +174,6 @@ static void idu_irq_unmask(struct irq_data *data)
raw_spin_unlock_irqrestore(_lock, flags);
 }
 
-#ifdef CONFIG_SMP
 static int
 idu_irq_set_affinity(struct irq_data *data, const struct cpumask *cpumask,
 bool force)
@@ -204,7 +203,6 @@ idu_irq_set_affinity(struct irq_data *data, const struct 
cpumask *cpumask,
 
return IRQ_SET_MASK_OK;
 }
-#endif
 
 static struct irq_chip idu_irq_chip = {
.name   = "MCIP IDU Intc",
@@ -228,9 +226,24 @@ static void idu_cascade_isr(struct irq_desc *desc)
 
 static int idu_irq_map(struct irq_domain *d, unsigned int virq, 
irq_hw_number_t hwirq)
 {
+   cpumask_t affinity;
+
irq_set_chip_and_handler(virq, _irq_chip, handle_level_irq);
irq_set_status_flags(virq, IRQ_MOVE_PCNTXT);
 
+   /* By default send all common interrupts to the first online CPU.
+* Usually it is a boot CPU. If the kernel is built without support
+* of SMP then idu_irq_set_affinity() must be called manually since
+* irq_set_affinity() does nothing in this case.
+*/
+   cpumask_copy(, cpumask_of(cpumask_first(cpu_online_mask)));
+
+#ifdef CONFIG_SMP
+   irq_set_affinity(virq, );
+#else
+   idu_irq_set_affinity(irq_get_irq_data(virq), , false);
+#endif
+
return 0;
 }
 
@@ -238,36 +251,14 @@ static int idu_irq_xlate(struct irq_domain *d, struct 
device_node *n,
 const u32 *intspec, unsigned int intsize,
 irq_hw_number_t *out_hwirq, unsigned int *out_type)
 {
-   irq_hw_number_t hwirq = *out_hwirq = intspec[0];
-   int distri = intspec[1];
-   unsigned long flags;
-
+   /*
+* Ignore value of interrupt distribution mode for common interrupts in
+* IDU which resides in intspec[1] since setting an affinity using value
+* from Device Tree is deprecated in ARC.
+*/
+   *out_hwirq = intspec[0];
*out_type = IRQ_TYPE_NONE;
 
-   /* XXX: validate distribution scheme again online cpu mask */
-   if (distri == 0) {
-   /* 0 - Round Robin to all cpus, otherwise 1 bit per core */
-   raw_spin_lock_irqsave(_lock, flags);
-   idu_set_dest(hwirq, BIT(num_online_cpus()) - 1);
-   idu_set_mode(hwirq, IDU_M_TRIG_LEVEL, IDU_M_DISTRI_RR);
-   raw_spin_unlock_irqrestore(_lock, flags);
-   } else {
-   /*
-* DEST based distribution for Level Triggered intr can only
-* have 1 CPU, so generalize it to always contain 1 cpu
-*/
-   int cpu = ffs(distri);
-
-   if (cpu != fls(distri))
-   pr_warn("IDU irq %lx distri mode set to cpu %x\n",
-   hwirq, cpu);
-
-

[PATCH v4 1/2] ARC: IRQ: Do not use hwirq as virq and vice versa

2016-11-07 Thread Yuriy Kolerov
At first smp_ipi_irq_setup() takes a cpu number and a hwirq number for
the per core local interrupt line in the root interrupt controller and
registers an appropriate IPI handler per cpu. However this function tries
to bind a handler to the hwirq as virtual IRQ number and it is a wrong
behavior. It is necessary to find a mapping of hwirq in the root IRQ
domain to the actual virq using irq_find_mapping(). Also a declaration
of smp_ipi_irq_setup() is corrected to denote that this function takes
a hardware IRQ number but not a virtual IRQ number.

Also there is one more problem related to usage of IRQ numbers. Multicore
ARC configurations use IDU (Interrupt Distribution Unit) for distributing
of common interrupts. In fact IDU is a interrupt controller on top of
main per core interrupt controller.

All common IRQs are physically and linearly mapped to per core
interrupts. E.g. <0, 1, 2, 3> common IDU interrupts may be mapped to per
core <24, 25, 26, 27> interrupts. An initialization code of IDU
controller (idu_of_init()) creates mappings for all parent interrupts
<24, 25, ...> and sets a chained IDU handler for them. In the same
time idu_of_init() must save the first met parent hwirq (idu_first_irq)
thus in future it is possible to figure out what common hwirq has come
by subtracting of idu_first_irq from the current parent hwirq (see
idu_cascade_isr()).

The problem is that idu_of_init() and idu_cascade_isr() use parent virtual
IRQs as hardware IRQs and perform all the above-described manipulations
on virtual IRQs. But it is wrong and hardware IRQs must be used instead.

Signed-off-by: Yuriy Kolerov <yuriy.kole...@synopsys.com>
---
 arch/arc/include/asm/smp.h |  4 ++--
 arch/arc/kernel/mcip.c | 20 +---
 arch/arc/kernel/smp.c  | 13 +
 3 files changed, 20 insertions(+), 17 deletions(-)

diff --git a/arch/arc/include/asm/smp.h b/arch/arc/include/asm/smp.h
index 89fdd1b..0861007 100644
--- a/arch/arc/include/asm/smp.h
+++ b/arch/arc/include/asm/smp.h
@@ -37,9 +37,9 @@ extern const char *arc_platform_smp_cpuinfo(void);
  * API expected BY platform smp code (FROM arch smp code)
  *
  * smp_ipi_irq_setup:
- * Takes @cpu and @irq to which the arch-common ISR is hooked up
+ * Takes @cpu and @hwirq to which the arch-common ISR is hooked up
  */
-extern int smp_ipi_irq_setup(int cpu, int irq);
+extern int smp_ipi_irq_setup(int cpu, irq_hw_number_t hwirq);
 
 /*
  * struct plat_smp_ops - SMP callbacks provided by platform to ARC SMP
diff --git a/arch/arc/kernel/mcip.c b/arch/arc/kernel/mcip.c
index 72f9179..4f4f04b 100644
--- a/arch/arc/kernel/mcip.c
+++ b/arch/arc/kernel/mcip.c
@@ -219,16 +219,14 @@ static struct irq_chip idu_irq_chip = {
 
 };
 
-static int idu_first_irq;
+static irq_hw_number_t idu_first_hwirq;
 
 static void idu_cascade_isr(struct irq_desc *desc)
 {
-   struct irq_domain *domain = irq_desc_get_handler_data(desc);
-   unsigned int core_irq = irq_desc_get_irq(desc);
-   unsigned int idu_irq;
-
-   idu_irq = core_irq - idu_first_irq;
-   generic_handle_irq(irq_find_mapping(domain, idu_irq));
+   struct irq_domain *idu_domain = irq_desc_get_handler_data(desc);
+   irq_hw_number_t core_hwirq = irqd_to_hwirq(irq_desc_get_irq_data(desc));
+   irq_hw_number_t idu_hwirq = core_hwirq - idu_first_hwirq;
+   generic_handle_irq(irq_find_mapping(idu_domain, idu_hwirq));
 }
 
 static int idu_irq_map(struct irq_domain *d, unsigned int virq, 
irq_hw_number_t hwirq)
@@ -294,7 +292,7 @@ idu_of_init(struct device_node *intc, struct device_node 
*parent)
struct irq_domain *domain;
/* Read IDU BCR to confirm nr_irqs */
int nr_irqs = of_irq_count(intc);
-   int i, irq;
+   int i, virq;
 
if (!idu_detected)
panic("IDU not detected, but DeviceTree using it");
@@ -312,11 +310,11 @@ idu_of_init(struct device_node *intc, struct device_node 
*parent)
 * however we need it to get the parent virq and set IDU handler
 * as first level isr
 */
-   irq = irq_of_parse_and_map(intc, i);
+   virq = irq_of_parse_and_map(intc, i);
if (!i)
-   idu_first_irq = irq;
+   idu_first_hwirq = irqd_to_hwirq(irq_get_irq_data(virq));
 
-   irq_set_chained_handler_and_data(irq, idu_cascade_isr, domain);
+   irq_set_chained_handler_and_data(virq, idu_cascade_isr, domain);
}
 
__mcip_cmd(CMD_IDU_ENABLE, 0);
diff --git a/arch/arc/kernel/smp.c b/arch/arc/kernel/smp.c
index f183cc6..692ca51 100644
--- a/arch/arc/kernel/smp.c
+++ b/arch/arc/kernel/smp.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -351,20 +352,24 @@ irqreturn_t do_IPI(int irq, void *dev_id)
  */
 static DEFINE_PER_CPU(int, ipi_dev);
 
-int smp_ipi_irq_setup(int cpu, int irq)
+int smp_ipi_irq_se

RE: [PATCH v3 2/3] ARCv2: MCIP: Use hwirq instead of virq for resolution of IDU IRQ handlers

2016-11-07 Thread Yuriy Kolerov
Yes, theoretically this may not work with 1/3 and 2/3. I will merge those 
patches.

> -Original Message-
> From: Vineet Gupta [mailto:vgu...@synopsys.com]
> Sent: Tuesday, November 08, 2016 4:59 AM
> To: Yuriy Kolerov <yuriy.kole...@synopsys.com>; linux-snps-
> a...@lists.infradead.org
> Cc: alexey.brod...@synopsys.com; t...@linutronix.de; linux-
> ker...@vger.kernel.org
> Subject: Re: [PATCH v3 2/3] ARCv2: MCIP: Use hwirq instead of virq for
> resolution of IDU IRQ handlers
> 
> On 11/03/2016 05:23 AM, Yuriy Kolerov wrote:
> > Multicore ARC configurations use IDU (Interrupt Distribution Unit) for
> > distributing of common interrupts. In fact IDU is a interrupt
> > controller on top of main per core interrupt controller.
> >
> > All common IRQs are physically and linearly mapped to per core
> > interrupts. E.g. <0, 1, 2, 3> common IDU interrupts may be mapped to
> > per core <24, 25, 26, 27> interrupts. An initialization code of IDU
> > controller (idu_of_init) creates mappings for all parent interrupts
> > <24, 25, ...> and sets a chained IDU handler for them. In the same
> > time idu_of_init must save the first met parent hwirq (idu_first_irq)
> > thus in future it is possible to figure out what common hwirq has come
> > by subtracting of idu_first_irq from the current parent hwirq (see
> > idu_cascade_isr).
> >
> > The problem is that idu_of_init and idu_cascade_isr use parent virtual
> > IRQs as hardware IRQs and perform all the above-described
> > manipulations on virtual IRQs. But it is wrong and hardware IRQs must be
> used instead.
> 
> Is this series bisectable ?
> 
> So if one only applies patch 1/3 (and not 2/3) - as might happen in case of a
> bisect for some arbit problem, will it still work - to me it seems not.
> 
> >
> > Signed-off-by: Yuriy Kolerov <yuriy.kole...@synopsys.com>
> > ---
> >  arch/arc/kernel/mcip.c | 20 +---
> >  1 file changed, 9 insertions(+), 11 deletions(-)
> >
> > diff --git a/arch/arc/kernel/mcip.c b/arch/arc/kernel/mcip.c index
> > 72f9179..4f4f04b 100644
> > --- a/arch/arc/kernel/mcip.c
> > +++ b/arch/arc/kernel/mcip.c
> > @@ -219,16 +219,14 @@ static struct irq_chip idu_irq_chip = {
> >
> >  };
> >
> > -static int idu_first_irq;
> > +static irq_hw_number_t idu_first_hwirq;
> >
> >  static void idu_cascade_isr(struct irq_desc *desc)  {
> > -   struct irq_domain *domain = irq_desc_get_handler_data(desc);
> > -   unsigned int core_irq = irq_desc_get_irq(desc);
> > -   unsigned int idu_irq;
> > -
> > -   idu_irq = core_irq - idu_first_irq;
> > -   generic_handle_irq(irq_find_mapping(domain, idu_irq));
> > +   struct irq_domain *idu_domain = irq_desc_get_handler_data(desc);
> > +   irq_hw_number_t core_hwirq =
> irqd_to_hwirq(irq_desc_get_irq_data(desc));
> > +   irq_hw_number_t idu_hwirq = core_hwirq - idu_first_hwirq;
> > +   generic_handle_irq(irq_find_mapping(idu_domain, idu_hwirq));
> >  }
> >
> >  static int idu_irq_map(struct irq_domain *d, unsigned int virq,
> > irq_hw_number_t hwirq) @@ -294,7 +292,7 @@ idu_of_init(struct
> device_node *intc, struct device_node *parent)
> > struct irq_domain *domain;
> > /* Read IDU BCR to confirm nr_irqs */
> > int nr_irqs = of_irq_count(intc);
> > -   int i, irq;
> > +   int i, virq;
> >
> > if (!idu_detected)
> > panic("IDU not detected, but DeviceTree using it"); @@ -
> 312,11
> > +310,11 @@ idu_of_init(struct device_node *intc, struct device_node
> *parent)
> >  * however we need it to get the parent virq and set IDU
> handler
> >  * as first level isr
> >  */
> > -   irq = irq_of_parse_and_map(intc, i);
> > +   virq = irq_of_parse_and_map(intc, i);
> > if (!i)
> > -   idu_first_irq = irq;
> > +   idu_first_hwirq =
> irqd_to_hwirq(irq_get_irq_data(virq));
> >
> > -   irq_set_chained_handler_and_data(irq, idu_cascade_isr,
> domain);
> > +   irq_set_chained_handler_and_data(virq, idu_cascade_isr,
> domain);
> > }
> >
> > __mcip_cmd(CMD_IDU_ENABLE, 0);
> >


___
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc


[RFC] ARCv2: MCIP: Deprecate setting of affinity in Device Tree

2016-11-04 Thread Yuriy Kolerov
Ignore value of interrupt distribution mode for common interrupts in
IDU since setting an affinity using value from Device Tree is deprecated
in ARC. Originially it is done in idu_irq_xlate function and it is
semantically wrong and does not guaranty that an affinity value will be
set properly.

However it is necessary to set a default affinity value manually for all
common interrupts since initially all of them are disabled by IDU (a
CPU mask for common interrupts is set to 0 after CPU reset) and in
some cases the kernel cannot do it itself after initialization of
endpoint devices (e.g. when IRQ chip below of IDU does not support
setting of affinity and it cannot propagate an affinity value to IDU).

P.S.

Despite the fact that the patch works fine I would like to discuss
few topics which are one way or another related to the original problem.

Despite the fact that this patch works fine it does not work well when
the intc below IDU does not support setting and propagating of affinity
(e.g. GPIO intc in AXS103 configuration which does not implement a function
for setting an affinity). That is why it is necessary to set an affinity
manually for IDU - you cannot be sure that an affinity will be propagated
to IDU properly even with support of hierarchical IRQ domains. But an
affinity *must* be set because IDU common interrupts are disabled by
default (registers which stores cpu masks are zeroes). In this patch
I use this soulution in idu_irq_map() function:

irq_set_affinity(virq, cpu_online_mask);

And there is a second problem. You cannot be sure that all cpus are
online at the moment of calling idu_irq_map() that is why cpu_online_mask
mask is used for setting of the initial affinity. It means that affinity
of all common interrupts is unpredictable after kernel boot (of course it
would be cool to distribute all common interrupts to all available cores
by default).

And the third topic is setting of affinity for AXS103 devices. Devices
in AXS103 are connected to CPU through a chain of GPIO controllers which
funnel all signals to 2 IDU common interrupts. Thus you cannot simply set
an affinity for devices using something like:

echo 2 > /proc/irq/3/...

because 1) GPIO contorrels in AXS103 does not support setting an affinity
and 2) there is a logical explanation for it: if you want to set an affinity
for a device connected to GPIO you produce a side affect by touchin an
affinity for nearby devices.

So if in case of AXS103 you must set an affinity not for devices but for
GPIO controllers which are connected to IDU. Also you must to know a virq
of the common interrupt line in IDU to set an affinity for it. Problem is
that you cannot retrieve this value from /proc/interrupts for AXS103 even
if support of hierarchical domains is implemented: /proc/interrupts does
not show chained virqs and virqs without actions (e.g. all virqs of IDU).

P.S.S.

The question is how to solve all those problems properly.

Signed-off-by: Yuriy Kolerov <yuriy.kole...@synopsys.com>
---
 .../interrupt-controller/snps,archs-idu-intc.txt   |  2 ++
 arch/arc/kernel/mcip.c | 35 +-
 2 files changed, 9 insertions(+), 28 deletions(-)

diff --git 
a/Documentation/devicetree/bindings/interrupt-controller/snps,archs-idu-intc.txt
 
b/Documentation/devicetree/bindings/interrupt-controller/snps,archs-idu-intc.txt
index 0dcb7c7..e967e7f 100644
--- 
a/Documentation/devicetree/bindings/interrupt-controller/snps,archs-idu-intc.txt
+++ 
b/Documentation/devicetree/bindings/interrupt-controller/snps,archs-idu-intc.txt
@@ -15,6 +15,8 @@ Properties:
   Second cell specifies the irq distribution mode to cores
  0=Round Robin; 1=cpu0, 2=cpu1, 4=cpu2, 8=cpu3
 
+  The second cell in interrupts property is deprecated and ignored.
+
   intc accessed via the special ARC AUX register interface, hence "reg" 
property
   is not specified.
 
diff --git a/arch/arc/kernel/mcip.c b/arch/arc/kernel/mcip.c
index 90f9934..2f4b0dc 100644
--- a/arch/arc/kernel/mcip.c
+++ b/arch/arc/kernel/mcip.c
@@ -242,6 +242,7 @@ static int idu_irq_map(struct irq_domain *d, unsigned int 
virq, irq_hw_number_t
 {
irq_set_chip_and_handler(virq, _irq_chip, handle_level_irq);
irq_set_status_flags(virq, IRQ_MOVE_PCNTXT);
+   irq_set_affinity(virq, cpu_online_mask);
 
return 0;
 }
@@ -250,36 +251,14 @@ static int idu_irq_xlate(struct irq_domain *d, struct 
device_node *n,
 const u32 *intspec, unsigned int intsize,
 irq_hw_number_t *out_hwirq, unsigned int *out_type)
 {
-   irq_hw_number_t hwirq = *out_hwirq = intspec[0];
-   int distri = intspec[1];
-   unsigned long flags;
-
+   /*
+* Ignore value of interrupt distribution mode for common interrupts in
+* IDU which resides in intspec[1] since setting an affinity using value
+* from Device Tree is deprecated in ARC.
+*/
+   *ou

[PATCH v3 3/3] ARCv2: MCIP: Use IDU_M_DISTRI_DEST mode if there is only 1 destination core

2016-11-03 Thread Yuriy Kolerov
ARC linux uses 2 distribution modes for common interrupts: round robin
mode (IDU_M_DISTRI_RR) and a simple destination mode (IDU_M_DISTRI_DEST).
The first one is used when more than 1 cores may handle a common interrupt
and the second one is used when only 1 core may handle a common interrupt.

However idu_irq_set_affinity always sets IDU_M_DISTRI_RR for all affinity
values. But there is no sense in setting of such mode if only 1 core must
handle a common interrupt.

Signed-off-by: Yuriy Kolerov <yuriy.kole...@synopsys.com>
---
 arch/arc/kernel/mcip.c | 13 +++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/arch/arc/kernel/mcip.c b/arch/arc/kernel/mcip.c
index 4f4f04b..90f9934 100644
--- a/arch/arc/kernel/mcip.c
+++ b/arch/arc/kernel/mcip.c
@@ -193,6 +193,8 @@ idu_irq_set_affinity(struct irq_data *data, const struct 
cpumask *cpumask,
 {
unsigned long flags;
cpumask_t online;
+   unsigned int destination_bits;
+   unsigned int distribution_mode;
 
/* errout if no online cpu per @cpumask */
if (!cpumask_and(, cpumask, cpu_online_mask))
@@ -200,8 +202,15 @@ idu_irq_set_affinity(struct irq_data *data, const struct 
cpumask *cpumask,
 
raw_spin_lock_irqsave(_lock, flags);
 
-   idu_set_dest(data->hwirq, cpumask_bits()[0]);
-   idu_set_mode(data->hwirq, IDU_M_TRIG_LEVEL, IDU_M_DISTRI_RR);
+   destination_bits = cpumask_bits()[0];
+   idu_set_dest(data->hwirq, destination_bits);
+
+   if (ffs(destination_bits) == fls(destination_bits))
+   distribution_mode = IDU_M_DISTRI_DEST;
+   else
+   distribution_mode = IDU_M_DISTRI_RR;
+
+   idu_set_mode(data->hwirq, IDU_M_TRIG_LEVEL, distribution_mode);
 
raw_spin_unlock_irqrestore(_lock, flags);
 
-- 
2.7.4



___
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc


[PATCH v3 2/3] ARCv2: MCIP: Use hwirq instead of virq for resolution of IDU IRQ handlers

2016-11-03 Thread Yuriy Kolerov
Multicore ARC configurations use IDU (Interrupt Distribution Unit) for
distributing of common interrupts. In fact IDU is a interrupt controller
on top of main per core interrupt controller.

All common IRQs are physically and linearly mapped to per core
interrupts. E.g. <0, 1, 2, 3> common IDU interrupts may be mapped to per
core <24, 25, 26, 27> interrupts. An initialization code of IDU
controller (idu_of_init) creates mappings for all parent interrupts
<24, 25, ...> and sets a chained IDU handler for them. In the same
time idu_of_init must save the first met parent hwirq (idu_first_irq)
thus in future it is possible to figure out what common hwirq has come
by subtracting of idu_first_irq from the current parent hwirq (see
idu_cascade_isr).

The problem is that idu_of_init and idu_cascade_isr use parent virtual
IRQs as hardware IRQs and perform all the above-described manipulations
on virtual IRQs. But it is wrong and hardware IRQs must be used instead.

Signed-off-by: Yuriy Kolerov <yuriy.kole...@synopsys.com>
---
 arch/arc/kernel/mcip.c | 20 +---
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/arch/arc/kernel/mcip.c b/arch/arc/kernel/mcip.c
index 72f9179..4f4f04b 100644
--- a/arch/arc/kernel/mcip.c
+++ b/arch/arc/kernel/mcip.c
@@ -219,16 +219,14 @@ static struct irq_chip idu_irq_chip = {
 
 };
 
-static int idu_first_irq;
+static irq_hw_number_t idu_first_hwirq;
 
 static void idu_cascade_isr(struct irq_desc *desc)
 {
-   struct irq_domain *domain = irq_desc_get_handler_data(desc);
-   unsigned int core_irq = irq_desc_get_irq(desc);
-   unsigned int idu_irq;
-
-   idu_irq = core_irq - idu_first_irq;
-   generic_handle_irq(irq_find_mapping(domain, idu_irq));
+   struct irq_domain *idu_domain = irq_desc_get_handler_data(desc);
+   irq_hw_number_t core_hwirq = irqd_to_hwirq(irq_desc_get_irq_data(desc));
+   irq_hw_number_t idu_hwirq = core_hwirq - idu_first_hwirq;
+   generic_handle_irq(irq_find_mapping(idu_domain, idu_hwirq));
 }
 
 static int idu_irq_map(struct irq_domain *d, unsigned int virq, 
irq_hw_number_t hwirq)
@@ -294,7 +292,7 @@ idu_of_init(struct device_node *intc, struct device_node 
*parent)
struct irq_domain *domain;
/* Read IDU BCR to confirm nr_irqs */
int nr_irqs = of_irq_count(intc);
-   int i, irq;
+   int i, virq;
 
if (!idu_detected)
panic("IDU not detected, but DeviceTree using it");
@@ -312,11 +310,11 @@ idu_of_init(struct device_node *intc, struct device_node 
*parent)
 * however we need it to get the parent virq and set IDU handler
 * as first level isr
 */
-   irq = irq_of_parse_and_map(intc, i);
+   virq = irq_of_parse_and_map(intc, i);
if (!i)
-   idu_first_irq = irq;
+   idu_first_hwirq = irqd_to_hwirq(irq_get_irq_data(virq));
 
-   irq_set_chained_handler_and_data(irq, idu_cascade_isr, domain);
+   irq_set_chained_handler_and_data(virq, idu_cascade_isr, domain);
}
 
__mcip_cmd(CMD_IDU_ENABLE, 0);
-- 
2.7.4



___
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc


RE: [PATCH v2 5/5] ARC: MCIP: Use IDU_M_DISTRI_DEST mode if there is only 1 destination core

2016-10-25 Thread Yuriy Kolerov
> -Original Message-
> From: Vineet Gupta [mailto:vgu...@synopsys.com]
> Sent: Tuesday, October 25, 2016 8:53 PM
> To: Yuriy Kolerov <yuriy.kole...@synopsys.com>; linux-snps-
> a...@lists.infradead.org
> Cc: marc.zyng...@arm.com; vineet.gup...@synopsys.com;
> alexey.brod...@synopsys.com; linux-ker...@vger.kernel.org;
> t...@linutronix.de
> Subject: Re: [PATCH v2 5/5] ARC: MCIP: Use IDU_M_DISTRI_DEST mode if
> there is only 1 destination core
> 
> On 10/24/2016 05:46 AM, Yuriy Kolerov wrote:
> > ARC linux uses 2 distribution modes for common interrupts: round robin
> > mode (IDU_M_DISTRI_RR) and a simple destination mode
> (IDU_M_DISTRI_DEST).
> > The first one is used when more than 1 cores may handle a common
> > interrupt and the second one is used when only 1 core may handle a
> common interrupt.
> >
> > However idu_irq_set_affinity always sets IDU_M_DISTRI_RR for all
> > affinity values. But there is no sense in setting of such mode if only
> > 1 core must handle a common interrupt.
> >
> > Signed-off-by: Yuriy Kolerov <yuriy.kole...@synopsys.com>
> > ---
> >  arch/arc/kernel/mcip.c | 11 +--
> >  1 file changed, 9 insertions(+), 2 deletions(-)
> >
> > diff --git a/arch/arc/kernel/mcip.c b/arch/arc/kernel/mcip.c index
> > 090f0a1..75e6d73 100644
> > --- a/arch/arc/kernel/mcip.c
> > +++ b/arch/arc/kernel/mcip.c
> > @@ -197,6 +197,7 @@ idu_irq_set_affinity(struct irq_data *data, const
> > struct cpumask *cpumask,  {
> > unsigned long flags;
> > cpumask_t online;
> > +   unsigned long dest_bits;
> >
> > /* errout if no online cpu per @cpumask */
> > if (!cpumask_and(, cpumask, cpu_online_mask)) @@ -204,8
> > +205,14 @@ idu_irq_set_affinity(struct irq_data *data, const struct
> > cpumask *cpumask,
> >
> > raw_spin_lock_irqsave(_lock, flags);
> >
> > -   idu_set_dest(data->hwirq, cpumask_bits()[0]);
> > -   idu_set_mode(data->hwirq, IDU_M_TRIG_LEVEL,
> IDU_M_DISTRI_RR);
> > +   dest_bits = cpumask_bits()[0];
> > +   idu_set_dest(data->hwirq, dest_bits);
> > +
> > +   if (ffs(dest_bits) == fls(dest_bits)) {
> > +   idu_set_mode(data->hwirq, IDU_M_TRIG_LEVEL,
> IDU_M_DISTRI_DEST);
> > +   } else {
> > +   idu_set_mode(data->hwirq, IDU_M_TRIG_LEVEL,
> IDU_M_DISTRI_RR);
> > +   }
> 
> Better to use a local variable to assign IDU_M_xxx and then call
> idu_set_mode() outside the if. I know the compiler would do that anyways,
> but that looks simpler to read !

Yep.

> But on the other hand, adding all of this here - isn't there some sort of
> duplication of code now between here and in the idu_irq_xlate() ?
> Do we need the same stuff in 2 places ?

I tried to explain in in [PATCH v2 4/5]. In short I moved logic for setting 
affinity to idu_irq_set_affinity because xlate function is not the best place 
where it must be done (see commit message for that patch).

> >
> > raw_spin_unlock_irqrestore(_lock, flags);
> >
> >


___
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc


[PATCH v2 4/5] ARC: MCIP: Set an initial affinity value in idu_irq_map

2016-10-24 Thread Yuriy Kolerov
Originally an initial distribution mode (its value resides in Device Tree)
for each common interrupt is set in idu_irq_xlate. This leads to the
following problems. idu_irq_xlate may be called several times during parsing
of the Device Tree and it is semantically wrong to configure an initial
distribution mode here. Also a value of affinity (CPUs bitmap) is not saved
to irq_desc structure for the virq - later (after parsing of the DT) kernel
sees that affinity is not set and sets a default value of affinity (all
cores in round robin mode). As a result a value of affinity from Device
Tree is ignored.

To fix it I created a buffer for initial CPUs bitmaps from Device Tree.
In idu_irq_xlate those bitmaps are saved to the buffer. Then affinity
for virq is set manually in idu_irq_map. It works because idu_irq_xlate
is always called before idu_irq_map.

Despite the fact that it works I think that it must be rewritten to
eliminate usage of the buffer and move all logic to idu_irq_map but
I do not know how to do it correctly.

Signed-off-by: Yuriy Kolerov <yuriy.kole...@synopsys.com>
---
 arch/arc/kernel/mcip.c | 15 +++
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/arch/arc/kernel/mcip.c b/arch/arc/kernel/mcip.c
index 51a218c..090f0a1 100644
--- a/arch/arc/kernel/mcip.c
+++ b/arch/arc/kernel/mcip.c
@@ -12,12 +12,15 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
 
 static char smp_cpuinfo_buf[128];
 static int idu_detected;
+static unsigned long idu_cirq_to_dest[CONFIG_ARC_NUMBER_OF_INTERRUPTS];
 
 static DEFINE_RAW_SPINLOCK(mcip_lock);
 
@@ -232,9 +235,15 @@ static void idu_cascade_isr(struct irq_desc *desc)
 
 static int idu_irq_map(struct irq_domain *d, unsigned int virq, 
irq_hw_number_t hwirq)
 {
+   cpumask_t mask;
+
irq_set_chip_and_handler(virq, _irq_chip, handle_level_irq);
irq_set_status_flags(virq, IRQ_MOVE_PCNTXT);
 
+   cpumask_clear();
+   cpumask_bits()[0] |= idu_cirq_to_dest[hwirq];
+   irq_set_affinity(virq, );
+
return 0;
 }
 
@@ -252,8 +261,7 @@ static int idu_irq_xlate(struct irq_domain *d, struct 
device_node *n,
if (distri == 0) {
/* 0 - Round Robin to all cpus, otherwise 1 bit per core */
raw_spin_lock_irqsave(_lock, flags);
-   idu_set_dest(hwirq, BIT(num_online_cpus()) - 1);
-   idu_set_mode(hwirq, IDU_M_TRIG_LEVEL, IDU_M_DISTRI_RR);
+   idu_cirq_to_dest[hwirq] = BIT(num_online_cpus()) - 1;
raw_spin_unlock_irqrestore(_lock, flags);
} else {
/*
@@ -267,8 +275,7 @@ static int idu_irq_xlate(struct irq_domain *d, struct 
device_node *n,
hwirq, cpu);
 
raw_spin_lock_irqsave(_lock, flags);
-   idu_set_dest(hwirq, cpu);
-   idu_set_mode(hwirq, IDU_M_TRIG_LEVEL, IDU_M_DISTRI_DEST);
+   idu_cirq_to_dest[hwirq] = cpu;
raw_spin_unlock_irqrestore(_lock, flags);
}
 
-- 
2.7.4



___
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc


[PATCH v2 3/5] ARC: MCIP: Use hwirq instead of virq for resolution of IDU IRQ handlers

2016-10-24 Thread Yuriy Kolerov
Multicore ARC configurations use IDU (Interrupt Distribution Unit) for
distributing of common interrupts. In fact IDU is a interrupt controller
on top of main per core interrupt controller.

All common IRQs are physically and linearly mapped to per core
interrupts. E.g. <0, 1, 2, 3> common IDU interrupts may be mapped to per
core <24, 25, 26, 27> interrupts. An initialization code of IDU
controller (idu_of_init) creates mappings for all parent interrupts
<24, 25, ...> and sets a chained IDU handler for them. In the same
time idu_of_init must save the first met parent hwirq (idu_first_irq)
thus in future it is possible to figure out what common hwirq has come
by subtracting of idu_first_irq from the current parent hwirq (see
idu_cascade_isr).

The problem is that idu_of_init and idu_cascade_isr use parent virtual
IRQs as hardware IRQs and perform all the above-described manipulations
on virtual IRQs. But it is wrong and hardware IRQs must be used instead.

Signed-off-by: Yuriy Kolerov <yuriy.kole...@synopsys.com>
---
 arch/arc/kernel/mcip.c | 20 +---
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/arch/arc/kernel/mcip.c b/arch/arc/kernel/mcip.c
index 28ff766..51a218c 100644
--- a/arch/arc/kernel/mcip.c
+++ b/arch/arc/kernel/mcip.c
@@ -220,16 +220,14 @@ static struct irq_chip idu_irq_chip = {
 
 };
 
-static int idu_first_irq;
+static irq_hw_number_t idu_first_hwirq;
 
 static void idu_cascade_isr(struct irq_desc *desc)
 {
-   struct irq_domain *domain = irq_desc_get_handler_data(desc);
-   unsigned int core_irq = irq_desc_get_irq(desc);
-   unsigned int idu_irq;
-
-   idu_irq = core_irq - idu_first_irq;
-   generic_handle_irq(irq_find_mapping(domain, idu_irq));
+   struct irq_domain *idu_domain = irq_desc_get_handler_data(desc);
+   irq_hw_number_t core_hwirq = irqd_to_hwirq(irq_desc_get_irq_data(desc));
+   irq_hw_number_t idu_hwirq = core_hwirq - idu_first_hwirq;
+   generic_handle_irq(irq_find_mapping(idu_domain, idu_hwirq));
 }
 
 static int idu_irq_map(struct irq_domain *d, unsigned int virq, 
irq_hw_number_t hwirq)
@@ -295,7 +293,7 @@ idu_of_init(struct device_node *intc, struct device_node 
*parent)
struct irq_domain *domain;
/* Read IDU BCR to confirm nr_irqs */
int nr_irqs = of_irq_count(intc);
-   int i, irq;
+   int i, virq;
 
if (!idu_detected)
panic("IDU not detected, but DeviceTree using it");
@@ -313,11 +311,11 @@ idu_of_init(struct device_node *intc, struct device_node 
*parent)
 * however we need it to get the parent virq and set IDU handler
 * as first level isr
 */
-   irq = irq_of_parse_and_map(intc, i);
+   virq = irq_of_parse_and_map(intc, i);
if (!i)
-   idu_first_irq = irq;
+   idu_first_hwirq = irqd_to_hwirq(irq_get_irq_data(virq));
 
-   irq_set_chained_handler_and_data(irq, idu_cascade_isr, domain);
+   irq_set_chained_handler_and_data(virq, idu_cascade_isr, domain);
}
 
__mcip_cmd(CMD_IDU_ENABLE, 0);
-- 
2.7.4



___
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc


[PATCH v2 2/5] ARC: SMP: Pass virq to smp_ipi_irq_setup instead of hwirq

2016-10-24 Thread Yuriy Kolerov
This function takes a cpu number and a virq number and registers an
appropriate handler per cpu. However smp_ipi_irq_setup is incorrectly
used in several places of ARC platform code - hwirq is passed instead of
virq. There is a code with an example of inccorect usage of smp_ipi_irq_setup:

smp_ipi_irq_setup(cpu, IPI_IRQ);
smp_ipi_irq_setup(cpu, SOFTIRQ_IRQ);

where IPI_IRQ and SOFTIRQ_IRQ are hwirq numbers for per cpu interrupts.
Since smp_ipi_irq_setup must be taken a virq number insdead of a hwirq
number then it is necessary to fix usage of this function this way:

smp_ipi_irq_setup(cpu, irq_find_mapping(NULL, IPI_IRQ));
smp_ipi_irq_setup(cpu, irq_find_mapping(NULL, SOFTIRQ_IRQ));

The idea is to find an appropriate mapping of <domain, hwirq> to virq
by using irq_find_mapping function. NULL value is used as a domain
argument (a default domain) since smp_ipi_irq_setup is used for
registering an IRQ handler for a root interrupt controller (a default
IRQ domain must be used).

Signed-off-by: Yuriy Kolerov <yuriy.kole...@synopsys.com>
---
 arch/arc/kernel/mcip.c| 5 +++--
 arch/arc/plat-eznps/smp.c | 2 +-
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/arch/arc/kernel/mcip.c b/arch/arc/kernel/mcip.c
index 72f9179..28ff766 100644
--- a/arch/arc/kernel/mcip.c
+++ b/arch/arc/kernel/mcip.c
@@ -11,6 +11,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -22,8 +23,8 @@ static DEFINE_RAW_SPINLOCK(mcip_lock);
 
 static void mcip_setup_per_cpu(int cpu)
 {
-   smp_ipi_irq_setup(cpu, IPI_IRQ);
-   smp_ipi_irq_setup(cpu, SOFTIRQ_IRQ);
+   smp_ipi_irq_setup(cpu, irq_find_mapping(NULL, IPI_IRQ));
+   smp_ipi_irq_setup(cpu, irq_find_mapping(NULL, SOFTIRQ_IRQ));
 }
 
 static void mcip_ipi_send(int cpu)
diff --git a/arch/arc/plat-eznps/smp.c b/arch/arc/plat-eznps/smp.c
index 5e901f8..dd996e0 100644
--- a/arch/arc/plat-eznps/smp.c
+++ b/arch/arc/plat-eznps/smp.c
@@ -134,7 +134,7 @@ static void eznps_ipi_send(int cpu)
 
 static void eznps_init_per_cpu(int cpu)
 {
-   smp_ipi_irq_setup(cpu, NPS_IPI_IRQ);
+   smp_ipi_irq_setup(cpu, irq_find_mapping(NULL, NPS_IPI_IRQ));
 
eznps_init_core(cpu);
mtm_enable_core(cpu);
-- 
2.7.4



___
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc


[PATCH 4/5] ARC: MCIP: Set an initial affinity value in idu_irq_map

2016-10-21 Thread Yuriy Kolerov
Originally an initial distribution mode (its value resides in Device Tree)
for each common interrupt is set in idu_irq_xlate. This leads to the
following problems. idu_irq_xlate may be called several times during parsing
of the Device Tree and it is semantically wrong to configure an initial
distribution mode here. Also a value of affinity (CPUs bitmap) is not saved
to irq_desc structure for the virq - later (after parsing of the DT) kernel
sees that affinity is not set and sets a default value of affinity (all
cores in round robin mode). As a result a value of affinity from Device
Tree is ignored.

To fix it I created a buffer for initial CPUs bitmaps from Device Tree.
In idu_irq_xlate those bitmaps are saved to the buffer. Then affinity
for virq is set manually in idu_irq_map. It works because idu_irq_xlate
is always called before idu_irq_map.

Despite the fact that it works I think that it must be rewritten to
eliminate usage of the buffer and move all logic to idu_irq_map but
I do not know how to do it correctly.

Signed-off-by: Yuriy Kolerov <yuriy.kole...@synopsys.com>
---
 arch/arc/kernel/mcip.c | 15 +++
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/arch/arc/kernel/mcip.c b/arch/arc/kernel/mcip.c
index 51a218c..090f0a1 100644
--- a/arch/arc/kernel/mcip.c
+++ b/arch/arc/kernel/mcip.c
@@ -12,12 +12,15 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
 
 static char smp_cpuinfo_buf[128];
 static int idu_detected;
+static unsigned long idu_cirq_to_dest[CONFIG_ARC_NUMBER_OF_INTERRUPTS];
 
 static DEFINE_RAW_SPINLOCK(mcip_lock);
 
@@ -232,9 +235,15 @@ static void idu_cascade_isr(struct irq_desc *desc)
 
 static int idu_irq_map(struct irq_domain *d, unsigned int virq, 
irq_hw_number_t hwirq)
 {
+   cpumask_t mask;
+
irq_set_chip_and_handler(virq, _irq_chip, handle_level_irq);
irq_set_status_flags(virq, IRQ_MOVE_PCNTXT);
 
+   cpumask_clear();
+   cpumask_bits()[0] |= idu_cirq_to_dest[hwirq];
+   irq_set_affinity(virq, );
+
return 0;
 }
 
@@ -252,8 +261,7 @@ static int idu_irq_xlate(struct irq_domain *d, struct 
device_node *n,
if (distri == 0) {
/* 0 - Round Robin to all cpus, otherwise 1 bit per core */
raw_spin_lock_irqsave(_lock, flags);
-   idu_set_dest(hwirq, BIT(num_online_cpus()) - 1);
-   idu_set_mode(hwirq, IDU_M_TRIG_LEVEL, IDU_M_DISTRI_RR);
+   idu_cirq_to_dest[hwirq] = BIT(num_online_cpus()) - 1;
raw_spin_unlock_irqrestore(_lock, flags);
} else {
/*
@@ -267,8 +275,7 @@ static int idu_irq_xlate(struct irq_domain *d, struct 
device_node *n,
hwirq, cpu);
 
raw_spin_lock_irqsave(_lock, flags);
-   idu_set_dest(hwirq, cpu);
-   idu_set_mode(hwirq, IDU_M_TRIG_LEVEL, IDU_M_DISTRI_DEST);
+   idu_cirq_to_dest[hwirq] = cpu;
raw_spin_unlock_irqrestore(_lock, flags);
}
 
-- 
2.7.4



___
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc


[PATCH 2/5] ARC: SMP: Pass virq to smp_ipi_irq_setup instead of hwirq

2016-10-21 Thread Yuriy Kolerov
This function takes a cpu number and a virq number and registers an
appropriate handler per cpu. However smp_ipi_irq_setup is incorrectly
used in several places of ARC platform code - hwirq is passed instead of
virq. There is a code with an example of inccorect usage of smp_ipi_irq_setup:

smp_ipi_irq_setup(cpu, IPI_IRQ);
smp_ipi_irq_setup(cpu, SOFTIRQ_IRQ);

where IPI_IRQ and SOFTIRQ_IRQ are hwirq numbers for per cpu interrupts.
Since smp_ipi_irq_setup must be taken a virq number insdead of a hwirq
number then it is necessary to fix usage of this function this way:

smp_ipi_irq_setup(cpu, irq_find_mapping(NULL, IPI_IRQ));
smp_ipi_irq_setup(cpu, irq_find_mapping(NULL, SOFTIRQ_IRQ));

The idea is to find an appropriate mapping of <domain, hwirq> to virq
by using irq_find_mapping function. NULL value is used as a domain
argument (a default domain) since smp_ipi_irq_setup is used for
registering an IRQ handler for a root interrupt controller (a default
IRQ domain must be used).

Signed-off-by: Yuriy Kolerov <yuriy.kole...@synopsys.com>
---
 arch/arc/kernel/mcip.c| 5 +++--
 arch/arc/plat-eznps/smp.c | 2 +-
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/arch/arc/kernel/mcip.c b/arch/arc/kernel/mcip.c
index 72f9179..28ff766 100644
--- a/arch/arc/kernel/mcip.c
+++ b/arch/arc/kernel/mcip.c
@@ -11,6 +11,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -22,8 +23,8 @@ static DEFINE_RAW_SPINLOCK(mcip_lock);
 
 static void mcip_setup_per_cpu(int cpu)
 {
-   smp_ipi_irq_setup(cpu, IPI_IRQ);
-   smp_ipi_irq_setup(cpu, SOFTIRQ_IRQ);
+   smp_ipi_irq_setup(cpu, irq_find_mapping(NULL, IPI_IRQ));
+   smp_ipi_irq_setup(cpu, irq_find_mapping(NULL, SOFTIRQ_IRQ));
 }
 
 static void mcip_ipi_send(int cpu)
diff --git a/arch/arc/plat-eznps/smp.c b/arch/arc/plat-eznps/smp.c
index 5e901f8..dd996e0 100644
--- a/arch/arc/plat-eznps/smp.c
+++ b/arch/arc/plat-eznps/smp.c
@@ -134,7 +134,7 @@ static void eznps_ipi_send(int cpu)
 
 static void eznps_init_per_cpu(int cpu)
 {
-   smp_ipi_irq_setup(cpu, NPS_IPI_IRQ);
+   smp_ipi_irq_setup(cpu, irq_find_mapping(NULL, NPS_IPI_IRQ));
 
eznps_init_core(cpu);
mtm_enable_core(cpu);
-- 
2.7.4



___
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc


[PATCH 5/5] ARC: MCIP: Use IDU_M_DISTRI_DEST mode if there is only 1 destination core

2016-10-21 Thread Yuriy Kolerov
ARC linux uses 2 distribution modes for common interrupts: round robin
mode (IDU_M_DISTRI_RR) and a simple destination mode (IDU_M_DISTRI_DEST).
The first one is used when more than 1 cores may handle a common interrupt
and the second one is used when only 1 core may handle a common interrupt.

However idu_irq_set_affinity always sets IDU_M_DISTRI_RR for all affinity
values. But there is no sense in setting of such mode if only 1 core must
handle a common interrupt.

Signed-off-by: Yuriy Kolerov <yuriy.kole...@synopsys.com>
---
 arch/arc/kernel/mcip.c | 11 +--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/arch/arc/kernel/mcip.c b/arch/arc/kernel/mcip.c
index 090f0a1..75e6d73 100644
--- a/arch/arc/kernel/mcip.c
+++ b/arch/arc/kernel/mcip.c
@@ -197,6 +197,7 @@ idu_irq_set_affinity(struct irq_data *data, const struct 
cpumask *cpumask,
 {
unsigned long flags;
cpumask_t online;
+   unsigned long dest_bits;
 
/* errout if no online cpu per @cpumask */
if (!cpumask_and(, cpumask, cpu_online_mask))
@@ -204,8 +205,14 @@ idu_irq_set_affinity(struct irq_data *data, const struct 
cpumask *cpumask,
 
raw_spin_lock_irqsave(_lock, flags);
 
-   idu_set_dest(data->hwirq, cpumask_bits()[0]);
-   idu_set_mode(data->hwirq, IDU_M_TRIG_LEVEL, IDU_M_DISTRI_RR);
+   dest_bits = cpumask_bits()[0];
+   idu_set_dest(data->hwirq, dest_bits);
+
+   if (ffs(dest_bits) == fls(dest_bits)) {
+   idu_set_mode(data->hwirq, IDU_M_TRIG_LEVEL, IDU_M_DISTRI_DEST);
+   } else {
+   idu_set_mode(data->hwirq, IDU_M_TRIG_LEVEL, IDU_M_DISTRI_RR);
+   }
 
raw_spin_unlock_irqrestore(_lock, flags);
 
-- 
2.7.4



___
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc


[PATCH 3/5] ARC: MCIP: Use hwirq instead of virq for resolution of IDU IRQ handlers

2016-10-21 Thread Yuriy Kolerov
Multicore ARC configurations use IDU (Interrupt Distribution Unit) for
distributing of common interrupts. In fact IDU is a interrupt controller
on top of main per core interrupt controller.

All common IRQs are physically and linearly mapped to per core
interrupts. E.g. <0, 1, 2, 3> common IDU interrupts may be mapped to per
core <24, 25, 26, 27> interrupts. An initialization code of IDU
controller (idu_of_init) creates mappings for all parent interrupts
<24, 25, ...> and sets a chained IDU handler for them. In the same
time idu_of_init must save the first met parent hwirq (idu_first_irq)
thus in future it is possible to figure out what common hwirq has come
by subtracting of idu_first_irq from the current parent hwirq (see
idu_cascade_isr).

The problem is that idu_of_init and idu_cascade_isr use parent virtual
IRQs as hardware IRQs and perform all the above-described manipulations
on virtual IRQs. But it is wrong and hardware IRQs must be used instead.

Signed-off-by: Yuriy Kolerov <yuriy.kole...@synopsys.com>
---
 arch/arc/kernel/mcip.c | 20 +---
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/arch/arc/kernel/mcip.c b/arch/arc/kernel/mcip.c
index 28ff766..51a218c 100644
--- a/arch/arc/kernel/mcip.c
+++ b/arch/arc/kernel/mcip.c
@@ -220,16 +220,14 @@ static struct irq_chip idu_irq_chip = {
 
 };
 
-static int idu_first_irq;
+static irq_hw_number_t idu_first_hwirq;
 
 static void idu_cascade_isr(struct irq_desc *desc)
 {
-   struct irq_domain *domain = irq_desc_get_handler_data(desc);
-   unsigned int core_irq = irq_desc_get_irq(desc);
-   unsigned int idu_irq;
-
-   idu_irq = core_irq - idu_first_irq;
-   generic_handle_irq(irq_find_mapping(domain, idu_irq));
+   struct irq_domain *idu_domain = irq_desc_get_handler_data(desc);
+   irq_hw_number_t core_hwirq = irqd_to_hwirq(irq_desc_get_irq_data(desc));
+   irq_hw_number_t idu_hwirq = core_hwirq - idu_first_hwirq;
+   generic_handle_irq(irq_find_mapping(idu_domain, idu_hwirq));
 }
 
 static int idu_irq_map(struct irq_domain *d, unsigned int virq, 
irq_hw_number_t hwirq)
@@ -295,7 +293,7 @@ idu_of_init(struct device_node *intc, struct device_node 
*parent)
struct irq_domain *domain;
/* Read IDU BCR to confirm nr_irqs */
int nr_irqs = of_irq_count(intc);
-   int i, irq;
+   int i, virq;
 
if (!idu_detected)
panic("IDU not detected, but DeviceTree using it");
@@ -313,11 +311,11 @@ idu_of_init(struct device_node *intc, struct device_node 
*parent)
 * however we need it to get the parent virq and set IDU handler
 * as first level isr
 */
-   irq = irq_of_parse_and_map(intc, i);
+   virq = irq_of_parse_and_map(intc, i);
if (!i)
-   idu_first_irq = irq;
+   idu_first_hwirq = irqd_to_hwirq(irq_get_irq_data(virq));
 
-   irq_set_chained_handler_and_data(irq, idu_cascade_isr, domain);
+   irq_set_chained_handler_and_data(virq, idu_cascade_isr, domain);
}
 
__mcip_cmd(CMD_IDU_ENABLE, 0);
-- 
2.7.4



___
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc


[PATCH] ARCv2: intc: Use kflag if STATUS32.IE must be reset

2016-09-12 Thread Yuriy Kolerov
In the end of "arc_init_IRQ" STATUS32.IE flag is going to be affected by
"flag" instruction but "flag" never touches IE flag on ARCv2. So "kflag"
instruction must be used instead of "flag".

Signed-off-by: Yuriy Kolerov <yuriy.kole...@synopsys.com>
---
 arch/arc/kernel/intc-arcv2.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arc/kernel/intc-arcv2.c b/arch/arc/kernel/intc-arcv2.c
index 6c24faf..62b59409 100644
--- a/arch/arc/kernel/intc-arcv2.c
+++ b/arch/arc/kernel/intc-arcv2.c
@@ -74,7 +74,7 @@ void arc_init_IRQ(void)
tmp = read_aux_reg(0xa);
tmp |= STATUS_AD_MASK | (irq_prio << 1);
tmp &= ~STATUS_IE_MASK;
-   asm volatile("flag %0   \n"::"r"(tmp));
+   asm volatile("kflag %0  \n"::"r"(tmp));
 }
 
 static void arcv2_irq_mask(struct irq_data *data)
-- 
2.7.4



___
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc


[LTP] [PATCH v2] syscalls/fcntl34: Use flock64 instead of flock

2016-08-16 Thread Yuriy Kolerov

This test uses OFD locks which are supported only by 64-bit ABI.
Thus OFD locks must be used with flock64 structure for sure in this
test. It is necessary because on some 32-bit targets (e.g. 32-bit
uClibc) flock is not mapped to flock64 when _FILE_OFFSET_BITS is not
set to 64.

Signed-off-by: Yuriy Kolerov <yuriy.kole...@synopsys.com>
---
 testcases/kernel/syscalls/fcntl/fcntl34.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/testcases/kernel/syscalls/fcntl/fcntl34.c b/testcases/kernel/syscalls/fcntl/fcntl34.c
index c72951e..2f89dea 100644
--- a/testcases/kernel/syscalls/fcntl/fcntl34.c
+++ b/testcases/kernel/syscalls/fcntl/fcntl34.c
@@ -66,7 +66,7 @@ void *thread_fn_01(void *arg)
 
 	memset(buf, (intptr_t)arg, write_size);
 
-	struct flock lck = {
+	struct flock64 lck = {
 		.l_whence = SEEK_SET,
 		.l_start  = 0,
 		.l_len= 1,
___
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc

RE: Problems with support of file locks for ARC (maybe for other targets too)

2016-08-12 Thread Yuriy Kolerov


> -Original Message-
> From: Vineet Gupta
> Sent: Friday, August 12, 2016 2:39 AM
> To: Yuriy Kolerov <ykole...@synopsys.com>; ucl...@uclibc.org
> Cc: Waldemar Brodkorb <w...@openadk.org>; Alexey Brodkin
> <abrod...@synopsys.com>; Anton Kolesov <akole...@synopsys.com>;
> arcml <linux-snps-arc@lists.infradead.org>
> Subject: Re: Problems with support of file locks for ARC (maybe for other
> targets too)
> 
> On 08/11/2016 09:12 AM, Yuriy Kolerov wrote:
> >
> >>>  Moreover the whole uClibc and every application must be compiled
> >>> with
> >> those macros. Here is my question. Is it acceptable just to compile
> >> toolchain itself using CFLAGS_FOR_TARGET with those macros and don’t
> >> define them manually in each application?
> >>
> >> If you enable LFS support in build system (uClibc or buildroot) these
> >> macros will be automatically defined - no point or need to pass them
> >> as CFLAGS etc - infact that would be wrong IMO.
> > If you enable __UCLIBC_HAS_LFS__ while configuring uClibc then
> _LARGEFILE64_SOURCE and _FILE_OFFSET_BITS=64 will not be defined
> automatically.
> 
> What was I smoking when replying ? You are correct - these macros have to
> be added to each application's makefile or at top level as target C flags.
> 
> > E.g. Buildroot has this generic line in Makefile for packages:
> >
> > TARGET_CPPFLAGS += -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE
> > -D_FILE_OFFSET_BITS=64
> 
> Actually BR dropped support for disabling LFS in 2015 - before that the line
> above used to be guarded by BR2_LARGEFILE.
> 
> > These defines are not placed to config.h or somewhere else. They must be
> defined each time you compile anything. uClibc may be built by Buildroot
> with these flags by default (actually it is not true at least for ARC - 
> Buildroot
> must be fixed but it is not a subject of this discussion). However you must
> define these macros manually when building every application later.
> 
> Right, I stand corrected.
> 
> > I don’t understand this thing - is it possible to compile uClibc with full
> support of LFS (see macros above) and don’t use this feature in applications
> and everything will be ok?
> 
> Indeed this is the case - if you don't build with LFS, xxx64 won't even be
> available to begin with.
> 
> > And is it possible to compile uClibc without _LARGEFILE64_SOURCE and
> _FILE_OFFSET_BITS=64 and compile applications with them and everything
> will be ok?
> 
> This mostly likely won't work as those defines will not be present in headers
> to use in application.

But actually it works... As for now uClibc in Buildroot is built without 
-D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 because uClibc 
does not use global TARGET_CFLAGS. And all other applications (e.g. BusyBox) 
use those flags. Again - all those defines are presented in features.h and must 
be activating just by passing those -D options. I'll try to push a patch to 
Buildroot to force using LFS flags but what frustrates me is that everything 
works somehow together.

> > Right now when we build toolchain for ARC using Buildroot uClibc is
> compiled without them and e.g. BusyBox is compiled with -
> D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
> ...
> 
> Buildroot now assumes LFS to be default (and you can't switch it off) so
> everything including uClibc / Busybox has LFS enabled already.
> 
> >
> >> So you really don't need LFS to be able to use locks - but need to
> >> make sure that for common generic ABI - user struct flock pairs
> >> correctly with kernel struct
> >> flock64 with or w/o LFS.
> 
> But this point remains valid - for our ABI - kernel uses struct flock64 and 
> this
> needs to be binary compatible with uClibc struct flock and struct flock64 (LFS
> only)
> 
> Read the comment in libc/sysdeps/linux/common-generic/bits/stat.h
> 
> -Vineet
___
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc