Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 1/9] irqchip/ls-scfg-msi: fix typo of MSI compatible strings
From: Minghuan Lian @ 2017-01-17  9:32 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484645563-29877-1-git-send-email-Minghuan.Lian@nxp.com>

The patch is to fix typo of the Layerscape SCFG MSI dts compatible
strings. "1" is replaced by "l".

Signed-off-by: Minghuan Lian <Minghuan.Lian@nxp.com>
Acked-by: Rob Herring <robh@kernel.org>
---
v3-v1:
- None

 .../devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt    | 6 +++---
 drivers/irqchip/irq-ls-scfg-msi.c                                   | 6 ++++--
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt b/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
index 9e38949..2755cd1 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
+++ b/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
@@ -4,8 +4,8 @@ Required properties:
 
 - compatible: should be "fsl,<soc-name>-msi" to identify
 	      Layerscape PCIe MSI controller block such as:
-              "fsl,1s1021a-msi"
-              "fsl,1s1043a-msi"
+              "fsl,ls1021a-msi"
+              "fsl,ls1043a-msi"
 - msi-controller: indicates that this is a PCIe MSI controller node
 - reg: physical base address of the controller and length of memory mapped.
 - interrupts: an interrupt to the parent interrupt controller.
@@ -23,7 +23,7 @@ MSI controller node
 Examples:
 
 	msi1: msi-controller at 1571000 {
-		compatible = "fsl,1s1043a-msi";
+		compatible = "fsl,ls1043a-msi";
 		reg = <0x0 0x1571000 0x0 0x8>,
 		msi-controller;
 		interrupts = <0 116 0x4>;
diff --git a/drivers/irqchip/irq-ls-scfg-msi.c b/drivers/irqchip/irq-ls-scfg-msi.c
index 02cca74c..cef67cc 100644
--- a/drivers/irqchip/irq-ls-scfg-msi.c
+++ b/drivers/irqchip/irq-ls-scfg-msi.c
@@ -219,8 +219,10 @@ static int ls_scfg_msi_remove(struct platform_device *pdev)
 }
 
 static const struct of_device_id ls_scfg_msi_id[] = {
-	{ .compatible = "fsl,1s1021a-msi", },
-	{ .compatible = "fsl,1s1043a-msi", },
+	{ .compatible = "fsl,1s1021a-msi", }, /* a typo */
+	{ .compatible = "fsl,1s1043a-msi", }, /* a typo */
+	{ .compatible = "fsl,ls1021a-msi", },
+	{ .compatible = "fsl,ls1043a-msi", },
 	{},
 };
 
-- 
1.9.1

^ permalink raw reply related

* [PATCH v3 2/9] arm: dts: ls1021a: fix typo of MSI compatible string
From: Minghuan Lian @ 2017-01-17  9:32 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484645563-29877-1-git-send-email-Minghuan.Lian@nxp.com>

"1" should be replaced by "l". This is a typo.
The patch is to fix it.

Signed-off-by: Minghuan Lian <Minghuan.Lian@nxp.com>
---
v3-v1:
- None

 arch/arm/boot/dts/ls1021a.dtsi | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/ls1021a.dtsi b/arch/arm/boot/dts/ls1021a.dtsi
index 282d854..6651938 100644
--- a/arch/arm/boot/dts/ls1021a.dtsi
+++ b/arch/arm/boot/dts/ls1021a.dtsi
@@ -122,14 +122,14 @@
 		};
 
 		msi1: msi-controller at 1570e00 {
-			compatible = "fsl,1s1021a-msi";
+			compatible = "fsl,ls1021a-msi";
 			reg = <0x0 0x1570e00 0x0 0x8>;
 			msi-controller;
 			interrupts =  <GIC_SPI 179 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
 		msi2: msi-controller at 1570e08 {
-			compatible = "fsl,1s1021a-msi";
+			compatible = "fsl,ls1021a-msi";
 			reg = <0x0 0x1570e08 0x0 0x8>;
 			msi-controller;
 			interrupts = <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>;
-- 
1.9.1

^ permalink raw reply related

* [PATCH v3 3/9] arm64: dts: ls1043a: fix typo of MSI compatible string
From: Minghuan Lian @ 2017-01-17  9:32 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484645563-29877-1-git-send-email-Minghuan.Lian@nxp.com>

"1" should be replaced by "l". This is a typo.
The patch is to fix it.

Signed-off-by: Minghuan Lian <Minghuan.Lian@nxp.com>
---
v3-v1:
- None

 arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
index ec13a6e..692fc35 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
@@ -589,21 +589,21 @@
 		};
 
 		msi1: msi-controller1 at 1571000 {
-			compatible = "fsl,1s1043a-msi";
+			compatible = "fsl,ls1043a-msi";
 			reg = <0x0 0x1571000 0x0 0x8>;
 			msi-controller;
 			interrupts = <0 116 0x4>;
 		};
 
 		msi2: msi-controller2 at 1572000 {
-			compatible = "fsl,1s1043a-msi";
+			compatible = "fsl,ls1043a-msi";
 			reg = <0x0 0x1572000 0x0 0x8>;
 			msi-controller;
 			interrupts = <0 126 0x4>;
 		};
 
 		msi3: msi-controller3 at 1573000 {
-			compatible = "fsl,1s1043a-msi";
+			compatible = "fsl,ls1043a-msi";
 			reg = <0x0 0x1573000 0x0 0x8>;
 			msi-controller;
 			interrupts = <0 160 0x4>;
-- 
1.9.1

^ permalink raw reply related

* [PATCH v3 4/9] arm: dts: ls1021a: share all MSIs
From: Minghuan Lian @ 2017-01-17  9:32 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484645563-29877-1-git-send-email-Minghuan.Lian@nxp.com>

In order to maximize the use of MSI, a PCIe controller will share
all MSI controllers. The patch changes msi-parent to refer to all
MSI controller dts nodes.

Signed-off-by: Minghuan Lian <Minghuan.Lian@nxp.com>
---
v3-v1:
- None

 arch/arm/boot/dts/ls1021a.dtsi | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/ls1021a.dtsi b/arch/arm/boot/dts/ls1021a.dtsi
index 6651938..1c82024 100644
--- a/arch/arm/boot/dts/ls1021a.dtsi
+++ b/arch/arm/boot/dts/ls1021a.dtsi
@@ -723,7 +723,7 @@
 			bus-range = <0x0 0xff>;
 			ranges = <0x81000000 0x0 0x00000000 0x40 0x00010000 0x0 0x00010000   /* downstream I/O */
 				  0x82000000 0x0 0x40000000 0x40 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
-			msi-parent = <&msi1>;
+			msi-parent = <&msi1>, <&msi2>;
 			#interrupt-cells = <1>;
 			interrupt-map-mask = <0 0 0 7>;
 			interrupt-map = <0000 0 0 1 &gic GIC_SPI 91  IRQ_TYPE_LEVEL_HIGH>,
@@ -746,7 +746,7 @@
 			bus-range = <0x0 0xff>;
 			ranges = <0x81000000 0x0 0x00000000 0x48 0x00010000 0x0 0x00010000   /* downstream I/O */
 				  0x82000000 0x0 0x40000000 0x48 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
-			msi-parent = <&msi2>;
+			msi-parent = <&msi1>, <&msi2>;
 			#interrupt-cells = <1>;
 			interrupt-map-mask = <0 0 0 7>;
 			interrupt-map = <0000 0 0 1 &gic GIC_SPI 92  IRQ_TYPE_LEVEL_HIGH>,
-- 
1.9.1

^ permalink raw reply related

* [PATCH v3 5/9] arm64: dts: ls1043a: share all MSIs
From: Minghuan Lian @ 2017-01-17  9:32 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484645563-29877-1-git-send-email-Minghuan.Lian@nxp.com>

In order to maximize the use of MSI, a PCIe controller will share
all MSI controllers. The patch changes "msi-parent" to refer to all
MSI controller dts nodes.

Signed-off-by: Minghuan Lian <Minghuan.Lian@nxp.com>
---
v3-v1:
- None

 arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
index 692fc35..3947220 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
@@ -625,7 +625,7 @@
 			bus-range = <0x0 0xff>;
 			ranges = <0x81000000 0x0 0x00000000 0x40 0x00010000 0x0 0x00010000   /* downstream I/O */
 				  0x82000000 0x0 0x40000000 0x40 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
-			msi-parent = <&msi1>;
+			msi-parent = <&msi1>, <&msi2>, <&msi3>;
 			#interrupt-cells = <1>;
 			interrupt-map-mask = <0 0 0 7>;
 			interrupt-map = <0000 0 0 1 &gic 0 110 0x4>,
@@ -650,7 +650,7 @@
 			bus-range = <0x0 0xff>;
 			ranges = <0x81000000 0x0 0x00000000 0x48 0x00010000 0x0 0x00010000   /* downstream I/O */
 				  0x82000000 0x0 0x40000000 0x48 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
-			msi-parent = <&msi2>;
+			msi-parent = <&msi1>, <&msi2>, <&msi3>;
 			#interrupt-cells = <1>;
 			interrupt-map-mask = <0 0 0 7>;
 			interrupt-map = <0000 0 0 1 &gic 0 120  0x4>,
@@ -675,7 +675,7 @@
 			bus-range = <0x0 0xff>;
 			ranges = <0x81000000 0x0 0x00000000 0x50 0x00010000 0x0 0x00010000   /* downstream I/O */
 				  0x82000000 0x0 0x40000000 0x50 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
-			msi-parent = <&msi3>;
+			msi-parent = <&msi1>, <&msi2>, <&msi3>;
 			#interrupt-cells = <1>;
 			interrupt-map-mask = <0 0 0 7>;
 			interrupt-map = <0000 0 0 1 &gic 0 154 0x4>,
-- 
1.9.1

^ permalink raw reply related

* [PATCH v3 6/9] arm64: dts: ls1046a: add MSI dts node
From: Minghuan Lian @ 2017-01-17  9:32 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484645563-29877-1-git-send-email-Minghuan.Lian@nxp.com>

LS1046a includes 3 MSI controllers.
Each controller supports 128 interrupts.

Signed-off-by: Minghuan Lian <Minghuan.Lian@nxp.com>
Acked-by: Rob Herring <robh@kernel.org>
---
v3-v2:
- None
v2-v1:
- change whitespace number

 .../interrupt-controller/fsl,ls-scfg-msi.txt       |  1 +
 arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi     | 31 ++++++++++++++++++++++
 2 files changed, 32 insertions(+)

diff --git a/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt b/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
index 2755cd1..dde4552 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
+++ b/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
@@ -6,6 +6,7 @@ Required properties:
 	      Layerscape PCIe MSI controller block such as:
               "fsl,ls1021a-msi"
               "fsl,ls1043a-msi"
+              "fsl,ls1046a-msi"
 - msi-controller: indicates that this is a PCIe MSI controller node
 - reg: physical base address of the controller and length of memory mapped.
 - interrupts: an interrupt to the parent interrupt controller.
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
index 38806ca..49dbafc 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
@@ -511,5 +511,36 @@
 			interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clockgen 4 1>;
 		};
+
+		msi1: msi-controller at 1580000 {
+			compatible = "fsl,ls1046a-msi";
+			msi-controller;
+			reg = <0x0 0x1580000 0x0 0x10000>;
+			interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		msi2: msi-controller at 1590000 {
+			compatible = "fsl,ls1046a-msi";
+			msi-controller;
+			reg = <0x0 0x1590000 0x0 0x10000>;
+			interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		msi3: msi-controller at 15a0000 {
+			compatible = "fsl,ls1046a-msi";
+			msi-controller;
+			reg = <0x0 0x15a0000 0x0 0x10000>;
+			interrupts = <GIC_SPI 160 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
 	};
 };
-- 
1.9.1

^ permalink raw reply related

* [PATCH v3 7/9] irqchip/ls-scfg-msi: add LS1046a MSI support
From: Minghuan Lian @ 2017-01-17  9:32 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484645563-29877-1-git-send-email-Minghuan.Lian@nxp.com>

LS1046a includes 4 MSIRs, each MSIR is assigned a dedicate GIC
SPI interrupt and provides 32 MSI interrupts. Compared to previous
MSI, LS1046a's IBS(interrupt bit select) shift is changed to 2 and
total MSI interrupt number is changed to 128.

The patch adds structure 'ls_scfg_msir' to describe MSIR setting and
'ibs_shift' to store the different value between the SoCs.

Signed-off-by: Minghuan Lian <Minghuan.Lian@nxp.com>
---
v3-v2:
- keep the old misspelled compatible strings
v2-v1:
- MSI dts node change has been merged into the patch 6/9

 drivers/irqchip/irq-ls-scfg-msi.c | 165 ++++++++++++++++++++++++++++++--------
 1 file changed, 130 insertions(+), 35 deletions(-)

diff --git a/drivers/irqchip/irq-ls-scfg-msi.c b/drivers/irqchip/irq-ls-scfg-msi.c
index cef67cc..0b1f34d 100644
--- a/drivers/irqchip/irq-ls-scfg-msi.c
+++ b/drivers/irqchip/irq-ls-scfg-msi.c
@@ -17,13 +17,24 @@
 #include <linux/irq.h>
 #include <linux/irqchip/chained_irq.h>
 #include <linux/irqdomain.h>
+#include <linux/of_irq.h>
 #include <linux/of_pci.h>
 #include <linux/of_platform.h>
 #include <linux/spinlock.h>
 
-#define MSI_MAX_IRQS	32
-#define MSI_IBS_SHIFT	3
-#define MSIR		4
+#define MSI_IRQS_PER_MSIR	32
+#define MSI_MSIR_OFFSET		4
+
+struct ls_scfg_msi_cfg {
+	u32 ibs_shift; /* Shift of interrupt bit select */
+};
+
+struct ls_scfg_msir {
+	struct ls_scfg_msi *msi_data;
+	unsigned int index;
+	unsigned int gic_irq;
+	void __iomem *reg;
+};
 
 struct ls_scfg_msi {
 	spinlock_t		lock;
@@ -32,8 +43,11 @@ struct ls_scfg_msi {
 	struct irq_domain	*msi_domain;
 	void __iomem		*regs;
 	phys_addr_t		msiir_addr;
-	int			irq;
-	DECLARE_BITMAP(used, MSI_MAX_IRQS);
+	struct ls_scfg_msi_cfg	*cfg;
+	u32			msir_num;
+	struct ls_scfg_msir	*msir;
+	u32			irqs_num;
+	unsigned long		*used;
 };
 
 static struct irq_chip ls_scfg_msi_irq_chip = {
@@ -55,7 +69,7 @@ static void ls_scfg_msi_compose_msg(struct irq_data *data, struct msi_msg *msg)
 
 	msg->address_hi = upper_32_bits(msi_data->msiir_addr);
 	msg->address_lo = lower_32_bits(msi_data->msiir_addr);
-	msg->data = data->hwirq << MSI_IBS_SHIFT;
+	msg->data = data->hwirq;
 }
 
 static int ls_scfg_msi_set_affinity(struct irq_data *irq_data,
@@ -81,8 +95,8 @@ static int ls_scfg_msi_domain_irq_alloc(struct irq_domain *domain,
 	WARN_ON(nr_irqs != 1);
 
 	spin_lock(&msi_data->lock);
-	pos = find_first_zero_bit(msi_data->used, MSI_MAX_IRQS);
-	if (pos < MSI_MAX_IRQS)
+	pos = find_first_zero_bit(msi_data->used, msi_data->irqs_num);
+	if (pos < msi_data->irqs_num)
 		__set_bit(pos, msi_data->used);
 	else
 		err = -ENOSPC;
@@ -106,7 +120,7 @@ static void ls_scfg_msi_domain_irq_free(struct irq_domain *domain,
 	int pos;
 
 	pos = d->hwirq;
-	if (pos < 0 || pos >= MSI_MAX_IRQS) {
+	if (pos < 0 || pos >= msi_data->irqs_num) {
 		pr_err("failed to teardown msi. Invalid hwirq %d\n", pos);
 		return;
 	}
@@ -123,15 +137,17 @@ static void ls_scfg_msi_domain_irq_free(struct irq_domain *domain,
 
 static void ls_scfg_msi_irq_handler(struct irq_desc *desc)
 {
-	struct ls_scfg_msi *msi_data = irq_desc_get_handler_data(desc);
+	struct ls_scfg_msir *msir = irq_desc_get_handler_data(desc);
+	struct ls_scfg_msi *msi_data = msir->msi_data;
 	unsigned long val;
-	int pos, virq;
+	int pos, virq, hwirq;
 
 	chained_irq_enter(irq_desc_get_chip(desc), desc);
 
-	val = ioread32be(msi_data->regs + MSIR);
-	for_each_set_bit(pos, &val, MSI_MAX_IRQS) {
-		virq = irq_find_mapping(msi_data->parent, (31 - pos));
+	val = ioread32be(msir->reg);
+	for_each_set_bit(pos, &val, MSI_IRQS_PER_MSIR) {
+		hwirq = ((31 - pos) << msi_data->cfg->ibs_shift) | msir->index;
+		virq = irq_find_mapping(msi_data->parent, hwirq);
 		if (virq)
 			generic_handle_irq(virq);
 	}
@@ -143,7 +159,7 @@ static int ls_scfg_msi_domains_init(struct ls_scfg_msi *msi_data)
 {
 	/* Initialize MSI domain parent */
 	msi_data->parent = irq_domain_add_linear(NULL,
-						 MSI_MAX_IRQS,
+						 msi_data->irqs_num,
 						 &ls_scfg_msi_domain_ops,
 						 msi_data);
 	if (!msi_data->parent) {
@@ -164,16 +180,87 @@ static int ls_scfg_msi_domains_init(struct ls_scfg_msi *msi_data)
 	return 0;
 }
 
+static int ls_scfg_msi_setup_hwirq(struct ls_scfg_msi *msi_data, int index)
+{
+	struct ls_scfg_msir *msir;
+	int virq, i, hwirq;
+
+	virq = platform_get_irq(msi_data->pdev, index);
+	if (virq <= 0)
+		return -ENODEV;
+
+	msir = &msi_data->msir[index];
+	msir->index = index;
+	msir->msi_data = msi_data;
+	msir->gic_irq = virq;
+	msir->reg = msi_data->regs + MSI_MSIR_OFFSET + 4 * index;
+
+	irq_set_chained_handler_and_data(msir->gic_irq,
+					 ls_scfg_msi_irq_handler,
+					 msir);
+
+	/* Release the hwirqs corresponding to this MSIR */
+	for (i = 0; i < MSI_IRQS_PER_MSIR; i++) {
+		hwirq = i << msi_data->cfg->ibs_shift | msir->index;
+		bitmap_clear(msi_data->used, hwirq, 1);
+	}
+
+	return 0;
+}
+
+static int ls_scfg_msi_teardown_hwirq(struct ls_scfg_msir *msir)
+{
+	struct ls_scfg_msi *msi_data = msir->msi_data;
+	int i, hwirq;
+
+	if (msir->gic_irq > 0)
+		irq_set_chained_handler_and_data(msir->gic_irq, NULL, NULL);
+
+	for (i = 0; i < MSI_IRQS_PER_MSIR; i++) {
+		hwirq = i << msi_data->cfg->ibs_shift | msir->index;
+		bitmap_set(msi_data->used, hwirq, 1);
+	}
+
+	return 0;
+}
+
+static struct ls_scfg_msi_cfg ls1021_msi_cfg = {
+	.ibs_shift = 3,
+};
+
+static struct ls_scfg_msi_cfg ls1046_msi_cfg = {
+	.ibs_shift = 2,
+};
+
+static const struct of_device_id ls_scfg_msi_id[] = {
+	/* The following two misspelled compatibles are obsolete */
+	{ .compatible = "fsl,1s1021a-msi", .data = &ls1021_msi_cfg},
+	{ .compatible = "fsl,1s1043a-msi", .data = &ls1021_msi_cfg},
+
+	{ .compatible = "fsl,ls1021a-msi", .data = &ls1021_msi_cfg },
+	{ .compatible = "fsl,ls1043a-msi", .data = &ls1021_msi_cfg },
+	{ .compatible = "fsl,ls1046a-msi", .data = &ls1046_msi_cfg },
+	{},
+};
+MODULE_DEVICE_TABLE(of, ls_scfg_msi_id);
+
 static int ls_scfg_msi_probe(struct platform_device *pdev)
 {
+	const struct of_device_id *match;
 	struct ls_scfg_msi *msi_data;
 	struct resource *res;
-	int ret;
+	int i, ret;
+
+	match = of_match_device(ls_scfg_msi_id, &pdev->dev);
+	if (!match)
+		return -ENODEV;
 
 	msi_data = devm_kzalloc(&pdev->dev, sizeof(*msi_data), GFP_KERNEL);
 	if (!msi_data)
 		return -ENOMEM;
 
+	msi_data->cfg = (struct ls_scfg_msi_cfg *) match->data;
+
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	msi_data->regs = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(msi_data->regs)) {
@@ -182,23 +269,37 @@ static int ls_scfg_msi_probe(struct platform_device *pdev)
 	}
 	msi_data->msiir_addr = res->start;
 
-	msi_data->irq = platform_get_irq(pdev, 0);
-	if (msi_data->irq <= 0) {
-		dev_err(&pdev->dev, "failed to get MSI irq\n");
-		return -ENODEV;
-	}
-
 	msi_data->pdev = pdev;
 	spin_lock_init(&msi_data->lock);
 
+	msi_data->irqs_num = MSI_IRQS_PER_MSIR *
+			     (1 << msi_data->cfg->ibs_shift);
+	msi_data->used = devm_kcalloc(&pdev->dev,
+				    BITS_TO_LONGS(msi_data->irqs_num),
+				    sizeof(*msi_data->used),
+				    GFP_KERNEL);
+	if (!msi_data->used)
+		return -ENOMEM;
+	/*
+	 * Reserve all the hwirqs
+	 * The available hwirqs will be released in ls1_msi_setup_hwirq()
+	 */
+	bitmap_set(msi_data->used, 0, msi_data->irqs_num);
+
+	msi_data->msir_num = of_irq_count(pdev->dev.of_node);
+	msi_data->msir = devm_kcalloc(&pdev->dev, msi_data->msir_num,
+				      sizeof(*msi_data->msir),
+				      GFP_KERNEL);
+	if (!msi_data->msir)
+		return -ENOMEM;
+
+	for (i = 0; i < msi_data->msir_num; i++)
+		ls_scfg_msi_setup_hwirq(msi_data, i);
+
 	ret = ls_scfg_msi_domains_init(msi_data);
 	if (ret)
 		return ret;
 
-	irq_set_chained_handler_and_data(msi_data->irq,
-					 ls_scfg_msi_irq_handler,
-					 msi_data);
-
 	platform_set_drvdata(pdev, msi_data);
 
 	return 0;
@@ -207,8 +308,10 @@ static int ls_scfg_msi_probe(struct platform_device *pdev)
 static int ls_scfg_msi_remove(struct platform_device *pdev)
 {
 	struct ls_scfg_msi *msi_data = platform_get_drvdata(pdev);
+	int i;
 
-	irq_set_chained_handler_and_data(msi_data->irq, NULL, NULL);
+	for (i = 0; i < msi_data->msir_num; i++)
+		ls_scfg_msi_teardown_hwirq(&msi_data->msir[i]);
 
 	irq_domain_remove(msi_data->msi_domain);
 	irq_domain_remove(msi_data->parent);
@@ -218,14 +321,6 @@ static int ls_scfg_msi_remove(struct platform_device *pdev)
 	return 0;
 }
 
-static const struct of_device_id ls_scfg_msi_id[] = {
-	{ .compatible = "fsl,1s1021a-msi", }, /* a typo */
-	{ .compatible = "fsl,1s1043a-msi", }, /* a typo */
-	{ .compatible = "fsl,ls1021a-msi", },
-	{ .compatible = "fsl,ls1043a-msi", },
-	{},
-};
-
 static struct platform_driver ls_scfg_msi_driver = {
 	.driver = {
 		.name = "ls-scfg-msi",
-- 
1.9.1

^ permalink raw reply related

* [PATCH v3 8/9] irqchip/ls-scfg-msi: add LS1043a v1.1 MSI support
From: Minghuan Lian @ 2017-01-17  9:32 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484645563-29877-1-git-send-email-Minghuan.Lian@nxp.com>

A MSI controller of LS1043a v1.0 only includes one MSIR and
is assigned one GIC interrupt. In order to support affinity,
LS1043a v1.1 MSI is assigned 4 MSIRs and 4 GIC interrupts.
But the MSIR has the different offset and only supports 8 MSIs.
The bits between variable bit_start and bit_end in structure
ls_scfg_msir are used to show 8 MSI interrupts. msir_irqs and
msir_base are added to describe the difference of MSI between
LS1043a v1.1 and other SoCs.

Signed-off-by: Minghuan Lian <Minghuan.Lian@nxp.com>
Acked-by: Rob Herring <robh@kernel.org>
---
v3-v1:
- None

 .../interrupt-controller/fsl,ls-scfg-msi.txt       |  1 +
 drivers/irqchip/irq-ls-scfg-msi.c                  | 45 +++++++++++++++++++---
 2 files changed, 40 insertions(+), 6 deletions(-)

diff --git a/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt b/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
index dde4552..49ccabb 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
+++ b/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
@@ -7,6 +7,7 @@ Required properties:
               "fsl,ls1021a-msi"
               "fsl,ls1043a-msi"
               "fsl,ls1046a-msi"
+              "fsl,ls1043a-v1.1-msi"
 - msi-controller: indicates that this is a PCIe MSI controller node
 - reg: physical base address of the controller and length of memory mapped.
 - interrupts: an interrupt to the parent interrupt controller.
diff --git a/drivers/irqchip/irq-ls-scfg-msi.c b/drivers/irqchip/irq-ls-scfg-msi.c
index 0b1f34d..8d57a59 100644
--- a/drivers/irqchip/irq-ls-scfg-msi.c
+++ b/drivers/irqchip/irq-ls-scfg-msi.c
@@ -25,14 +25,21 @@
 #define MSI_IRQS_PER_MSIR	32
 #define MSI_MSIR_OFFSET		4
 
+#define MSI_LS1043V1_1_IRQS_PER_MSIR	8
+#define MSI_LS1043V1_1_MSIR_OFFSET	0x10
+
 struct ls_scfg_msi_cfg {
 	u32 ibs_shift; /* Shift of interrupt bit select */
+	u32 msir_irqs; /* The irq number per MSIR */
+	u32 msir_base; /* The base address of MSIR */
 };
 
 struct ls_scfg_msir {
 	struct ls_scfg_msi *msi_data;
 	unsigned int index;
 	unsigned int gic_irq;
+	unsigned int bit_start;
+	unsigned int bit_end;
 	void __iomem *reg;
 };
 
@@ -140,13 +147,18 @@ static void ls_scfg_msi_irq_handler(struct irq_desc *desc)
 	struct ls_scfg_msir *msir = irq_desc_get_handler_data(desc);
 	struct ls_scfg_msi *msi_data = msir->msi_data;
 	unsigned long val;
-	int pos, virq, hwirq;
+	int pos, size, virq, hwirq;
 
 	chained_irq_enter(irq_desc_get_chip(desc), desc);
 
 	val = ioread32be(msir->reg);
-	for_each_set_bit(pos, &val, MSI_IRQS_PER_MSIR) {
-		hwirq = ((31 - pos) << msi_data->cfg->ibs_shift) | msir->index;
+
+	pos = msir->bit_start;
+	size = msir->bit_end + 1;
+
+	for_each_set_bit_from(pos, &val, size) {
+		hwirq = ((msir->bit_end - pos) << msi_data->cfg->ibs_shift) |
+			msir->index;
 		virq = irq_find_mapping(msi_data->parent, hwirq);
 		if (virq)
 			generic_handle_irq(virq);
@@ -193,14 +205,24 @@ static int ls_scfg_msi_setup_hwirq(struct ls_scfg_msi *msi_data, int index)
 	msir->index = index;
 	msir->msi_data = msi_data;
 	msir->gic_irq = virq;
-	msir->reg = msi_data->regs + MSI_MSIR_OFFSET + 4 * index;
+	msir->reg = msi_data->regs + msi_data->cfg->msir_base + 4 * index;
+
+	if (msi_data->cfg->msir_irqs == MSI_LS1043V1_1_IRQS_PER_MSIR) {
+		msir->bit_start = 32 - ((msir->index + 1) *
+				  MSI_LS1043V1_1_IRQS_PER_MSIR);
+		msir->bit_end = msir->bit_start +
+				MSI_LS1043V1_1_IRQS_PER_MSIR - 1;
+	} else {
+		msir->bit_start = 0;
+		msir->bit_end = msi_data->cfg->msir_irqs - 1;
+	}
 
 	irq_set_chained_handler_and_data(msir->gic_irq,
 					 ls_scfg_msi_irq_handler,
 					 msir);
 
 	/* Release the hwirqs corresponding to this MSIR */
-	for (i = 0; i < MSI_IRQS_PER_MSIR; i++) {
+	for (i = 0; i < msi_data->cfg->msir_irqs; i++) {
 		hwirq = i << msi_data->cfg->ibs_shift | msir->index;
 		bitmap_clear(msi_data->used, hwirq, 1);
 	}
@@ -216,7 +238,7 @@ static int ls_scfg_msi_teardown_hwirq(struct ls_scfg_msir *msir)
 	if (msir->gic_irq > 0)
 		irq_set_chained_handler_and_data(msir->gic_irq, NULL, NULL);
 
-	for (i = 0; i < MSI_IRQS_PER_MSIR; i++) {
+	for (i = 0; i < msi_data->cfg->msir_irqs; i++) {
 		hwirq = i << msi_data->cfg->ibs_shift | msir->index;
 		bitmap_set(msi_data->used, hwirq, 1);
 	}
@@ -226,10 +248,20 @@ static int ls_scfg_msi_teardown_hwirq(struct ls_scfg_msir *msir)
 
 static struct ls_scfg_msi_cfg ls1021_msi_cfg = {
 	.ibs_shift = 3,
+	.msir_irqs = MSI_IRQS_PER_MSIR,
+	.msir_base = MSI_MSIR_OFFSET,
 };
 
 static struct ls_scfg_msi_cfg ls1046_msi_cfg = {
 	.ibs_shift = 2,
+	.msir_irqs = MSI_IRQS_PER_MSIR,
+	.msir_base = MSI_MSIR_OFFSET,
+};
+
+static struct ls_scfg_msi_cfg ls1043_v1_1_msi_cfg = {
+	.ibs_shift = 2,
+	.msir_irqs = MSI_LS1043V1_1_IRQS_PER_MSIR,
+	.msir_base = MSI_LS1043V1_1_MSIR_OFFSET,
 };
 
 static const struct of_device_id ls_scfg_msi_id[] = {
@@ -239,6 +271,7 @@ static int ls_scfg_msi_teardown_hwirq(struct ls_scfg_msir *msir)
 
 	{ .compatible = "fsl,ls1021a-msi", .data = &ls1021_msi_cfg },
 	{ .compatible = "fsl,ls1043a-msi", .data = &ls1021_msi_cfg },
+	{ .compatible = "fsl,ls1043a-v1.1-msi", .data = &ls1043_v1_1_msi_cfg },
 	{ .compatible = "fsl,ls1046a-msi", .data = &ls1046_msi_cfg },
 	{},
 };
-- 
1.9.1

^ permalink raw reply related

* [PATCH v3 9/9] irqchip/ls-scfg-msi: add MSI affinity support
From: Minghuan Lian @ 2017-01-17  9:32 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484645563-29877-1-git-send-email-Minghuan.Lian@nxp.com>

For LS1046a and LS1043a v1.1, the MSI controller has 4 MSIRs and 4 GIC
SPI interrupts which can be associated with different Core.
So we can support affinity to improve the performance.
The MSI message data is a byte for Layerscape MSI.
  7    6   5  4  3  2   1   0
| - |       IBS       |  SRS |
SRS bit0-1 is to select a MSIR which is associated with a CPU.
IBS bit2-6 of ls1046, bit2-4 of ls1043a v1.1 is to select bit of the
MSIR. With affinity, only bits of MSIR0(srs=0 cpu0) are available.
All other bits of the MSIR1-3(cpu1-3) are reserved. The MSI hwirq
always equals bit index of the MSIR0. When changing affinity, MSI
message data will be appended corresponding SRS then MSI will be
moved to the corresponding core.
But in affinity mode, there is only 8 MSI interrupts for a controller
of LS1043a v1.1. It cannot meet the requirement of the some PCIe
devices such as 4 ports Ethernet card. In contrast, without affinity,
all MSIRs can be used for core 0, the MSI interrupts can up to 32.
So the parameter is added to control affinity mode.
"lsmsi=no-affinity" will disable affinity and increase MSI
interrupt number.

Signed-off-by: Minghuan Lian <Minghuan.Lian@nxp.com>
---
v3-v2:
- 1. update the description
- 2. remove unnecessary msir_index checking
v2-v1:
- None

 drivers/irqchip/irq-ls-scfg-msi.c | 68 ++++++++++++++++++++++++++++++++++++---
 1 file changed, 63 insertions(+), 5 deletions(-)

diff --git a/drivers/irqchip/irq-ls-scfg-msi.c b/drivers/irqchip/irq-ls-scfg-msi.c
index 8d57a59..119f4ef 100644
--- a/drivers/irqchip/irq-ls-scfg-msi.c
+++ b/drivers/irqchip/irq-ls-scfg-msi.c
@@ -40,6 +40,7 @@ struct ls_scfg_msir {
 	unsigned int gic_irq;
 	unsigned int bit_start;
 	unsigned int bit_end;
+	unsigned int srs; /* Shared interrupt register select */
 	void __iomem *reg;
 };
 
@@ -70,6 +71,19 @@ struct ls_scfg_msi {
 	.chip	= &ls_scfg_msi_irq_chip,
 };
 
+static int msi_affinity_flag = 1;
+
+static int __init early_parse_ls_scfg_msi(char *p)
+{
+	if (p && strncmp(p, "no-affinity", 11) == 0)
+		msi_affinity_flag = 0;
+	else
+		msi_affinity_flag = 1;
+
+	return 0;
+}
+early_param("lsmsi", early_parse_ls_scfg_msi);
+
 static void ls_scfg_msi_compose_msg(struct irq_data *data, struct msi_msg *msg)
 {
 	struct ls_scfg_msi *msi_data = irq_data_get_irq_chip_data(data);
@@ -77,12 +91,36 @@ static void ls_scfg_msi_compose_msg(struct irq_data *data, struct msi_msg *msg)
 	msg->address_hi = upper_32_bits(msi_data->msiir_addr);
 	msg->address_lo = lower_32_bits(msi_data->msiir_addr);
 	msg->data = data->hwirq;
+
+	if (msi_affinity_flag)
+		msg->data |= cpumask_first(data->common->affinity);
 }
 
 static int ls_scfg_msi_set_affinity(struct irq_data *irq_data,
 				    const struct cpumask *mask, bool force)
 {
-	return -EINVAL;
+	struct ls_scfg_msi *msi_data = irq_data_get_irq_chip_data(irq_data);
+	u32 cpu;
+
+	if (!msi_affinity_flag)
+		return -EINVAL;
+
+	if (!force)
+		cpu = cpumask_any_and(mask, cpu_online_mask);
+	else
+		cpu = cpumask_first(mask);
+
+	if (cpu >= msi_data->msir_num)
+		return -EINVAL;
+
+	if (msi_data->msir[cpu].gic_irq <= 0) {
+		pr_warn("cannot bind the irq to cpu%d\n", cpu);
+		return -EINVAL;
+	}
+
+	cpumask_copy(irq_data->common->affinity, mask);
+
+	return IRQ_SET_MASK_OK;
 }
 
 static struct irq_chip ls_scfg_msi_parent_chip = {
@@ -158,7 +196,7 @@ static void ls_scfg_msi_irq_handler(struct irq_desc *desc)
 
 	for_each_set_bit_from(pos, &val, size) {
 		hwirq = ((msir->bit_end - pos) << msi_data->cfg->ibs_shift) |
-			msir->index;
+			msir->srs;
 		virq = irq_find_mapping(msi_data->parent, hwirq);
 		if (virq)
 			generic_handle_irq(virq);
@@ -221,10 +259,19 @@ static int ls_scfg_msi_setup_hwirq(struct ls_scfg_msi *msi_data, int index)
 					 ls_scfg_msi_irq_handler,
 					 msir);
 
+	if (msi_affinity_flag) {
+		/* Associate MSIR interrupt to the cpu */
+		irq_set_affinity(msir->gic_irq, get_cpu_mask(index));
+		msir->srs = 0; /* This value is determined by the CPU */
+	} else
+		msir->srs = index;
+
 	/* Release the hwirqs corresponding to this MSIR */
-	for (i = 0; i < msi_data->cfg->msir_irqs; i++) {
-		hwirq = i << msi_data->cfg->ibs_shift | msir->index;
-		bitmap_clear(msi_data->used, hwirq, 1);
+	if (!msi_affinity_flag || msir->index == 0) {
+		for (i = 0; i < msi_data->cfg->msir_irqs; i++) {
+			hwirq = i << msi_data->cfg->ibs_shift | msir->index;
+			bitmap_clear(msi_data->used, hwirq, 1);
+		}
 	}
 
 	return 0;
@@ -320,6 +367,17 @@ static int ls_scfg_msi_probe(struct platform_device *pdev)
 	bitmap_set(msi_data->used, 0, msi_data->irqs_num);
 
 	msi_data->msir_num = of_irq_count(pdev->dev.of_node);
+
+	if (msi_affinity_flag) {
+		u32 cpu_num;
+
+		cpu_num = num_possible_cpus();
+		if (msi_data->msir_num >= cpu_num)
+			msi_data->msir_num = cpu_num;
+		else
+			msi_affinity_flag = 0;
+	}
+
 	msi_data->msir = devm_kcalloc(&pdev->dev, msi_data->msir_num,
 				      sizeof(*msi_data->msir),
 				      GFP_KERNEL);
-- 
1.9.1

^ permalink raw reply related

* [PATCH] drm/rockchip: vop: make vop register setting take effect
From: Tomasz Figa @ 2017-01-17  9:32 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <57C3A341.9030302@rock-chips.com>

Hi Mark,

On Mon, Aug 29, 2016 at 11:51 AM, Mark yao <mark.yao@rock-chips.com> wrote:
> On 2016?08?27? 11:39, Chris Zhong wrote:
>>
>> The setting of vop registers need a reg_done writing to take effect.
>> In vop_enable the vop return to work by by restoring registers, but the
>> registers do not take effect immediately, it should a vop_cfg_done
>> after it. The same thing is needed by windows_disabled in
>> vop_crtc_disable.
>>
>> Signed-off-by: Chris Zhong <zyw@rock-chips.com>
>> ---
>>   drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 4 ++++
>>   1 file changed, 4 insertions(+)
>
> Thanks for your fix.
>
> applied to my drm-fixes.

This patch seems to have been lost in action. I don't see it in linux-next.

Best regards,
Tomasz

^ permalink raw reply

* [PATCH 1/2] dt-bindings: gpu: Add Mali Utgard bindings
From: Maxime Ripard @ 2017-01-17  9:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170116184906.r62di7xiil5lae33@kozik-lap>

Hi,

On Mon, Jan 16, 2017 at 08:49:06PM +0200, Krzysztof Kozlowski wrote:
> On Mon, Jan 16, 2017 at 02:24:23PM +0100, Maxime Ripard wrote:
> > The ARM Mali Utgard GPU family is embedded into a number of SoCs from
> > Allwinner, Amlogic, Mediatek or Rockchip.
> > 
> > Add a binding for the GPU of that family.
> > 
> > Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > ---
> >  .../devicetree/bindings/gpu/arm,mali-utgard.txt    | 76 ++++++++++++++++++++++
> >  1 file changed, 76 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/gpu/arm,mali-utgard.txt
> 
> Do you have a driver in kernel which will implement these bindings?

No, but we have bindings for out-of-tree drivers already.

> Defining them for out-of-tree driver does not bring any benefits
> (3rd party driver will not respect them anyway).

You could see it the other way around too. The out-of-tree drivers
don't respect it at the moment because there's no binding to respect.

And at least for us, we definitely plan on doing that.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20170117/a98cc236/attachment.sig>

^ permalink raw reply

* [PATCH] tcb_clksrc: Use 32 bit tcb as sched_clock
From: Mason @ 2017-01-17  9:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170111135059.21318-1-david.engraf@sysgo.com>

On 11/01/2017 14:50, David Engraf wrote:

> Subject: [PATCH] tcb_clksrc: Use 32 bit tcb as sched_clock

I was puzzled by the TCB acronym :-)

Trusted Computing Base
Task Control Block
Transfer Control Block
Test Control Board

In fact, it (probably) stands for Timer Counter Block, which makes
sense for a clksrc patch.

Regards.

^ permalink raw reply

* [PATCH v3] arm64: mm: Fix NOMAP page initialization
From: Robert Richter @ 2017-01-17 10:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170113131500.GS4930@rric.localdomain>

On 13.01.17 14:15:00, Robert Richter wrote:
> On 13.01.17 09:19:04, Will Deacon wrote:
> > On Thu, Jan 12, 2017 at 07:58:25PM +0100, Robert Richter wrote:
> > > On 12.01.17 16:05:36, Will Deacon wrote:
> > > > On Mon, Jan 09, 2017 at 12:53:20PM +0100, Robert Richter wrote:
> > > 
> > > > > Kernel compile times (3 runs each):
> > > > > 
> > > > > pfn_valid_within():
> > > > > 
> > > > > real    6m4.088s
> > > > > user    372m57.607s
> > > > > sys     16m55.158s
> > > > > 
> > > > > real    6m1.532s
> > > > > user    372m48.453s
> > > > > sys     16m50.370s
> > > > > 
> > > > > real    6m4.061s
> > > > > user    373m18.753s
> > > > > sys     16m57.027s
> > > > 
> > > > Did you reboot the machine between each build here, or only when changing
> > > > kernel? If the latter, do you see variations in kernel build time by simply
> > > > rebooting the same Image?
> > > 
> > > I built it in a loop on the shell, so no reboots between builds. Note
> > > that I was building the kernel in /dev/shm to not access harddisks. I
> > > think build times should be comparable then since there is no fs
> > > caching.
> > 
> > I guess I'm really asking what the standard deviation is if you *do* reboot
> > between builds, using the same kernel. It's hard to tell whether the numbers
> > are due to the patches, or just because of noise incurred by the way things
> > happen to initialise.
> 
> Ok, I am going to test this.

See below the data for a test with reboots between every 3 builds (9
builds per kernel). Though some deviation can be seen between reboots
there is a trend.

-Robert



pfn_valid_within(), boot #1:

real	6m0.007s
user	372m55.709s
sys	16m45.962s

real	5m58.718s
user	372m58.852s
sys	16m47.675s

real	5m58.481s
user	372m56.172s
sys	16m46.953s

pfn_valid_within(), Boot #2:

real	6m1.163s
user	372m57.282s
sys	16m52.025s

real	6m0.562s
user	373m4.957s
sys	16m52.847s

real	6m0.030s
user	372m54.710s
sys	16m54.516s

pfn_valid_within(), Boot #3:

real	6m1.784s
user	373m13.379s
sys	16m48.388s

real	5m58.579s
user	373m10.403s
sys	16m47.628s

real	5m59.151s
user	373m0.084s
sys	16m50.634s

early_pfn_valid(), Boot #1:

real	5m59.902s
user	372m57.201s
sys	16m42.157s

real	5m59.510s
user	372m59.762s
sys	16m47.331s

real	5m58.559s
user	372m46.530s
sys	16m49.010s

early_pfn_valid(), Boot #2:

real	6m0.652s
user	373m10.785s
sys	16m25.138s

real	5m58.663s
user	373m4.498s
sys	16m28.262s

real	5m57.675s
user	373m6.174s
sys	16m28.653s

early_pfn_valid(), Boot #3:

real	5m59.680s
user	373m4.007s
sys	16m26.781s

real	5m58.234s
user	372m58.895s
sys	16m26.957s

real	5m58.707s
user	372m40.546s
sys	16m29.345s

^ permalink raw reply

* [RFC PATCH 08/10] arm64/sve: ptrace: Wire up vector length control and reporting
From: Dave Martin @ 2017-01-17 10:03 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170116151156.GI28060@E107787-LIN>

On Mon, Jan 16, 2017 at 03:11:56PM +0000, Yao Qi wrote:
> On 17-01-16 13:32:31, Dave Martin wrote:
> > On Mon, Jan 16, 2017 at 12:20:38PM +0000, Yao Qi wrote:
> > > On 17-01-12 11:26:07, Dave Martin wrote:
> > > > This patch adds support for manipulating a task's vector length at
> > > > runtime via ptrace.
> > > > 
> > > 
> > > I hope kernel doesn't provide such interface to ptracer to change vector
> > > length.
> > 
> > It does, with this patch, beacuse...
> > 
> > > The vector length is sort of a read-only property of thread/process/
> > > program to debugger, unless we really have a clear requirement to modify
> > > vector length in debugging.  I may miss something because I haven't debug
> > > SVE code yet.
> > 
> > ...the vector length is no longer read-only for the task, thanks to
> > the new prctls().
> 
> What I meant "read-only" is that debugger can't change it, while the program
> itself can change it via prctl().

I see.

> > 
> > This does add complexity, but I figured that any programmer's model
> > state that the thread can modify for itself should be modifiable by the
> > debugger, if for no other reason than the user may want to experiment to
> > see what happens.  Without a ptrace interface, it would be necessary
> > to inject a prctl() call into the target, which is possible but awkward.
> 
> We only need such interface if it is useful, see more below.
> 
> Suppose it is useful to change vector length through ptrace, we should align
> ptrace interface to prctl() as much as possible.  Looks that both prctl
> change and ptrace change can go through sve_set_vector_length, easy to keep
> two consistent.
> 
> > 
> > gdb must already re-detect the vector length on stop, since the target
> > could have called the prctl() in the meantime.
> 
> Yes, gdb assumes the vector length may be changed, so it re-detects on
> every stop, but I don't see the need for gdb to change the vector length.
> 
> > 
> > Access via ptrace also allows things like trapping on exec, fork or
> > clone and changing the vector length for the new process or thread
> > before it starts to run.  I'm guessing here, but such a scenario seems
> > legitimate (?)
> > 
> 
> Yes, these cases are valid, but the usefulness is still questionable to
> me.  I just doubt that SVE developers do need to change vector length
> when they are debugging code.  Note that it is not my strong objection
> to this patch, if kernel people believe this is useful, I am fine with
> it.

That's fair.  I'll leave the patch there for now and see if anyone else
has a comment to make, but it could be removed without affecting
anything else.

Are there situations in which injecting a function call into the target
won't work, i.e., where we couldn't do:

set prctl(...)

?

Using the prctl interface this way, it would also be preferable to refer
to the #defines by name.

Cheers
---Dave

^ permalink raw reply

* [PATCH] drm/rockchip: vop: make vop register setting take effect
From: Mark yao @ 2017-01-17 10:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAAFQd5CP8ERvJzchZo0=5gvuUuP+EBiyfhKDkgRYBa8iQYW0Kw@mail.gmail.com>

Hi Tomasz

I had sent to Dave, but maybe something is wrong, it miss.

the patch is on this pull-request:
https://lists.freedesktop.org/archives/dri-devel/2016-September/118505.html

I forgot to double check it, I will resend to Dave soon.

Thanks.

On 2017?01?17? 17:32, Tomasz Figa wrote:
> Hi Mark,
>
> On Mon, Aug 29, 2016 at 11:51 AM, Mark yao <mark.yao@rock-chips.com> wrote:
>> On 2016?08?27? 11:39, Chris Zhong wrote:
>>> The setting of vop registers need a reg_done writing to take effect.
>>> In vop_enable the vop return to work by by restoring registers, but the
>>> registers do not take effect immediately, it should a vop_cfg_done
>>> after it. The same thing is needed by windows_disabled in
>>> vop_crtc_disable.
>>>
>>> Signed-off-by: Chris Zhong <zyw@rock-chips.com>
>>> ---
>>>    drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 4 ++++
>>>    1 file changed, 4 insertions(+)
>> Thanks for your fix.
>>
>> applied to my drm-fixes.
> This patch seems to have been lost in action. I don't see it in linux-next.
>
> Best regards,
> Tomasz
>
>
>


-- 
?ark Yao

^ permalink raw reply

* [PATCH] reset: uniphier: add compatible string for LD11 SD-reset block
From: Philipp Zabel @ 2017-01-17 10:07 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484420686-28911-1-git-send-email-yamada.masahiro@socionext.com>

On Sun, 2017-01-15 at 04:04 +0900, Masahiro Yamada wrote:
> The LD11 SoC is equipped with not only MIO-reset but also SD-reset
> for controlling RST_n pin of the eMMC device.
> 
> Update the binding document and remove unneeded "." from each line
> in itemization.
> 
> Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>

Applied, thank you.

regards
Philipp

> ---
> 
>  .../devicetree/bindings/reset/uniphier-reset.txt   | 47 +++++++++++-----------
>  drivers/reset/reset-uniphier.c                     |  4 ++
>  2 files changed, 28 insertions(+), 23 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/reset/uniphier-reset.txt b/Documentation/devicetree/bindings/reset/uniphier-reset.txt
> index 5020524..83ab0f5 100644
> --- a/Documentation/devicetree/bindings/reset/uniphier-reset.txt
> +++ b/Documentation/devicetree/bindings/reset/uniphier-reset.txt
> @@ -6,14 +6,14 @@ System reset
>  
>  Required properties:
>  - compatible: should be one of the following:
> -    "socionext,uniphier-sld3-reset" - for sLD3 SoC.
> -    "socionext,uniphier-ld4-reset"  - for LD4 SoC.
> -    "socionext,uniphier-pro4-reset" - for Pro4 SoC.
> -    "socionext,uniphier-sld8-reset" - for sLD8 SoC.
> -    "socionext,uniphier-pro5-reset" - for Pro5 SoC.
> -    "socionext,uniphier-pxs2-reset" - for PXs2/LD6b SoC.
> -    "socionext,uniphier-ld11-reset" - for LD11 SoC.
> -    "socionext,uniphier-ld20-reset" - for LD20 SoC.
> +    "socionext,uniphier-sld3-reset" - for sLD3 SoC
> +    "socionext,uniphier-ld4-reset"  - for LD4 SoC
> +    "socionext,uniphier-pro4-reset" - for Pro4 SoC
> +    "socionext,uniphier-sld8-reset" - for sLD8 SoC
> +    "socionext,uniphier-pro5-reset" - for Pro5 SoC
> +    "socionext,uniphier-pxs2-reset" - for PXs2/LD6b SoC
> +    "socionext,uniphier-ld11-reset" - for LD11 SoC
> +    "socionext,uniphier-ld20-reset" - for LD20 SoC
>  - #reset-cells: should be 1.
>  
>  Example:
> @@ -37,14 +37,15 @@ Media I/O (MIO) reset, SD reset
>  
>  Required properties:
>  - compatible: should be one of the following:
> -    "socionext,uniphier-sld3-mio-reset" - for sLD3 SoC.
> -    "socionext,uniphier-ld4-mio-reset"  - for LD4 SoC.
> -    "socionext,uniphier-pro4-mio-reset" - for Pro4 SoC.
> -    "socionext,uniphier-sld8-mio-reset" - for sLD8 SoC.
> -    "socionext,uniphier-pro5-sd-reset"  - for Pro5 SoC.
> -    "socionext,uniphier-pxs2-sd-reset"  - for PXs2/LD6b SoC.
> -    "socionext,uniphier-ld11-mio-reset" - for LD11 SoC.
> -    "socionext,uniphier-ld20-sd-reset"  - for LD20 SoC.
> +    "socionext,uniphier-sld3-mio-reset" - for sLD3 SoC
> +    "socionext,uniphier-ld4-mio-reset"  - for LD4 SoC
> +    "socionext,uniphier-pro4-mio-reset" - for Pro4 SoC
> +    "socionext,uniphier-sld8-mio-reset" - for sLD8 SoC
> +    "socionext,uniphier-pro5-sd-reset"  - for Pro5 SoC
> +    "socionext,uniphier-pxs2-sd-reset"  - for PXs2/LD6b SoC
> +    "socionext,uniphier-ld11-mio-reset" - for LD11 SoC (MIO)
> +    "socionext,uniphier-ld11-sd-reset"  - for LD11 SoC (SD)
> +    "socionext,uniphier-ld20-sd-reset"  - for LD20 SoC
>  - #reset-cells: should be 1.
>  
>  Example:
> @@ -68,13 +69,13 @@ Peripheral reset
>  
>  Required properties:
>  - compatible: should be one of the following:
> -    "socionext,uniphier-ld4-peri-reset"  - for LD4 SoC.
> -    "socionext,uniphier-pro4-peri-reset" - for Pro4 SoC.
> -    "socionext,uniphier-sld8-peri-reset" - for sLD8 SoC.
> -    "socionext,uniphier-pro5-peri-reset" - for Pro5 SoC.
> -    "socionext,uniphier-pxs2-peri-reset" - for PXs2/LD6b SoC.
> -    "socionext,uniphier-ld11-peri-reset" - for LD11 SoC.
> -    "socionext,uniphier-ld20-peri-reset" - for LD20 SoC.
> +    "socionext,uniphier-ld4-peri-reset"  - for LD4 SoC
> +    "socionext,uniphier-pro4-peri-reset" - for Pro4 SoC
> +    "socionext,uniphier-sld8-peri-reset" - for sLD8 SoC
> +    "socionext,uniphier-pro5-peri-reset" - for Pro5 SoC
> +    "socionext,uniphier-pxs2-peri-reset" - for PXs2/LD6b SoC
> +    "socionext,uniphier-ld11-peri-reset" - for LD11 SoC
> +    "socionext,uniphier-ld20-peri-reset" - for LD20 SoC
>  - #reset-cells: should be 1.
>  
>  Example:
> diff --git a/drivers/reset/reset-uniphier.c b/drivers/reset/reset-uniphier.c
> index 968c3ae..9c11be3 100644
> --- a/drivers/reset/reset-uniphier.c
> +++ b/drivers/reset/reset-uniphier.c
> @@ -390,6 +390,10 @@ static const struct of_device_id uniphier_reset_match[] = {
>  		.data = uniphier_sld3_mio_reset_data,
>  	},
>  	{
> +		.compatible = "socionext,uniphier-ld11-sd-reset",
> +		.data = uniphier_pro5_sd_reset_data,
> +	},
> +	{
>  		.compatible = "socionext,uniphier-ld20-sd-reset",
>  		.data = uniphier_pro5_sd_reset_data,
>  	},

^ permalink raw reply

* [GIT PULL] bcm2835-dt-next-2017-01-17
From: Eric Anholt @ 2017-01-17 10:10 UTC (permalink / raw)
  To: linux-arm-kernel

  Linux 4.10-rc1 (2016-12-25 16:13:08 -0800)

are available in the git repository at:

  https://github.com/anholt/linux tags/bcm2835-dt-next-2017-01-17

for you to fetch changes up to 38742ca2b8b21bfc2a2cc24278b58485ff781644:

  ARM: bcm/dt: Enable the VEC IP on all RaspberryPi boards (2017-01-16 21:50:26 +1100)

----------------------------------------------------------------
This pull request brings in the DT changes for VEC (TV-out) on
Raspberry Pi.

----------------------------------------------------------------
Boris Brezillon (2):
      ARM: bcm/dt: Add VEC node in bcm283x.dtsi
      ARM: bcm/dt: Enable the VEC IP on all RaspberryPi boards

 arch/arm/boot/dts/bcm2835-rpi.dtsi | 5 +++++
 arch/arm/boot/dts/bcm283x.dtsi     | 8 ++++++++
 2 files changed, 13 insertions(+)

^ permalink raw reply

* [RFC PATCH 00/33] irqchip: Core support for GICv4
From: Marc Zyngier @ 2017-01-17 10:20 UTC (permalink / raw)
  To: linux-arm-kernel

This series implements the core support for GICv4. And despite its
size, it does exactly *nothing*. What it adds is an infrastructure
that a hypervisor (KVM) can use to route VLPIs to a guest.

>From the bit of documentation that is in patch #32:

WARNING: The blurb below assumes that you understand the
intricacies of GICv3, GICv4, and how a guest's view of a GICv3 gets
translated into GICv4 commands. So it effectively targets at most
two individuals. You know who you are.

The core GICv4 code is designed to *avoid* exposing too much of the
core GIC code (that would in turn leak into the hypervisor code),
and instead provide a hypervisor agnostic interface to the HW (of
course, the astute reader will quickly realize that hypervisor
agnostic actually means KVM-specific - what were you thinking?).

In order to achieve a modicum of isolation, we try to hide most of
the GICv4 "stuff" behind normal irqchip operations:

- Any guest-visible VLPI is backed by a Linux interrupt (and a
  physical LPI which gets deconfigured when the guest maps the
  VLPI). This allows the same DevID/Event pair to be either mapped
  to the LPI (host) or the VLPI (guest).

- Enabling/disabling a VLPI is done by issuing mask/unmask calls.

- Guest INT/CLEAR commands are implemented through
  irq_set_irqchip_state().

- The *bizarre* stuff (mapping/unmapping an interrupt to a VLPI, or
  issuing an INV after changing a priority) gets shoved into the
  irq_set_vcpu_affinity() method. While this is quite horrible
  (let's face it, this is the irqchip version of an ioctl), it
  confines the crap to a single location. And map/unmap really is
  about setting the affinity of a VLPI to a vcpu, so only INV is
  majorly out of place. So there.

But handling VLPIs is only one side of the job of the GICv4
code. The other (darker) side is to take care of the doorbell
interrupts which are delivered when a VLPI targeting a non-running
vcpu is being made pending.

The choice made here is that each vcpu (VPE in old northern GICv4
dialect) gets a single doorbell, no matter how many interrupts are
targeting it. This has a nice property, which is that the interrupt
becomes a handle for the VPE, and that the hypervisor code can
manipulate it through the normal interrupt API:

- VMs (or rather the VM abstraction that matters to the GIC)
  contain an irq domain where each interrupt maps to a VPE. In
  turn, this domain sits on top of the normal LPI allocator, and a
  specially crafted irq_chip implementation.

- mask/unmask do what is expected on the doorbell interrupt.

- irq_set_affinity is used to move a VPE from one redistributor to
  another.

- irq_set_vcpu_affinity once again gets hijacked for the purpose of
  creating a new sub-API, namely scheduling/descheduling a VPE and
  performing INVALL operations.


I'm posting these patches separately from the rest of the KVM work
because:

- they are complicated enough already
- I want to keep the interface as clean as possible
- the KVM device assignment is still in a state of flux

Patches on top of v4.10-rc3.

Marc Zyngier (33):
  irqchip/gic-v3: Add redistributor iterator
  irqchip/gic-v3: Add VLPI/DirectLPI discovery
  irqchip/gic-v3-its: Refactor command encoding
  irqchip/gic-v3-its: Move LPI definitions around
  irqchip/gic-v3-its: Zero command on allocation
  irqchip/gic-v3-its: Add probing for VLPI properties
  irqchip/gic-v3-its: Macro-ize its_send_single_command
  irqchip/gic-v3-its: Implement irq_set_irqchip_state for pending state
  irqchip/gic-v3-its: Split out property table allocation
  irqchip/gic-v4-its: Allow use of indirect VCPU tables
  irqchip/gic-v3-its: Split out pending table allocation
  irqchip/gic-v3-its: Rework LPI freeing
  irqchip/gic-v3-its: Generalize device table allocation
  irqchip/gic-v3-its: Generalize LPI configuration
  irqchip/gic-v4: Add management structure definitions
  irqchip/gic-v3-its: Add GICv4 ITS command definitions
  irqchip/gic-v3-its: Add VLPI configuration hook
  irqchip/gic-v3-its: Add VLPI map/unmap operations
  irqchip/gic-v3-its: Add VLPI configuration handling
  irqchip/gic-v3-its: Add VPE domain infrastructure
  irqchip/gic-v3-its: Add VPE irq domain allocation/teardown
  irqchip/gic-v3-its: Add VPE irq domain [de]activation
  irqchip/gic-v3-its: Add VPENDBASER/VPROPBASER accessors
  irqchip/gic-v3-its: Add VPE scheduling
  irqchip/gic-v3-its: Add VPE invalidation hook
  irqchip/gic-v3-its: Add VPE affinity changes
  irqchip/gic-v3-its: Add VPE interrupt masking
  irqchip/gic-v3-its: Support VPE doorbell invalidation even when
    !DirectLPI
  irqchip/gic-v4: Add per-VM VPE domain creation
  irqchip/gic-v4: Add VPE command interface
  irqchip/gic-v4: Add VLPI configuration interface
  irqchip/gic-v4: Add some basic documentation
  irqchip/gic-v4: Enable low-level GICv4 operations

 arch/arm/include/asm/arch_gicv3.h   |   28 +
 arch/arm64/include/asm/arch_gicv3.h |    5 +
 drivers/irqchip/Makefile            |    2 +-
 drivers/irqchip/irq-gic-v3-its.c    | 1183 +++++++++++++++++++++++++++++++----
 drivers/irqchip/irq-gic-v3.c        |   99 ++-
 drivers/irqchip/irq-gic-v4.c        |  241 +++++++
 include/linux/irqchip/arm-gic-v3.h  |   82 +++
 include/linux/irqchip/arm-gic-v4.h  |  102 +++
 8 files changed, 1602 insertions(+), 140 deletions(-)
 create mode 100644 drivers/irqchip/irq-gic-v4.c
 create mode 100644 include/linux/irqchip/arm-gic-v4.h

-- 
2.1.4

^ permalink raw reply

* [RFC PATCH 01/33] irqchip/gic-v3: Add redistributor iterator
From: Marc Zyngier @ 2017-01-17 10:20 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484648454-21216-1-git-send-email-marc.zyngier@arm.com>

In order to discover the VLPI properties, we need to iterate over
the redistributor regions. As we already have code that does this,
let's factor it out and make it slightly more generic.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/irqchip/irq-gic-v3.c | 77 ++++++++++++++++++++++++++++++++------------
 1 file changed, 56 insertions(+), 21 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index c132f29..5cadec0 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -421,24 +421,15 @@ static void __init gic_dist_init(void)
 		gic_write_irouter(affinity, base + GICD_IROUTER + i * 8);
 }
 
-static int gic_populate_rdist(void)
+static int gic_scan_rdist_properties(int (*fn)(struct redist_region *,
+					       void __iomem *))
 {
-	unsigned long mpidr = cpu_logical_map(smp_processor_id());
-	u64 typer;
-	u32 aff;
+	int ret = 0;
 	int i;
 
-	/*
-	 * Convert affinity to a 32bit value that can be matched to
-	 * GICR_TYPER bits [63:32].
-	 */
-	aff = (MPIDR_AFFINITY_LEVEL(mpidr, 3) << 24 |
-	       MPIDR_AFFINITY_LEVEL(mpidr, 2) << 16 |
-	       MPIDR_AFFINITY_LEVEL(mpidr, 1) << 8 |
-	       MPIDR_AFFINITY_LEVEL(mpidr, 0));
-
 	for (i = 0; i < gic_data.nr_redist_regions; i++) {
 		void __iomem *ptr = gic_data.redist_regions[i].redist_base;
+		u64 typer;
 		u32 reg;
 
 		reg = readl_relaxed(ptr + GICR_PIDR2) & GIC_PIDR2_ARCH_MASK;
@@ -450,14 +441,14 @@ static int gic_populate_rdist(void)
 
 		do {
 			typer = gic_read_typer(ptr + GICR_TYPER);
-			if ((typer >> 32) == aff) {
-				u64 offset = ptr - gic_data.redist_regions[i].redist_base;
-				gic_data_rdist_rd_base() = ptr;
-				gic_data_rdist()->phys_base = gic_data.redist_regions[i].phys_base + offset;
-				pr_info("CPU%d: found redistributor %lx region %d:%pa\n",
-					smp_processor_id(), mpidr, i,
-					&gic_data_rdist()->phys_base);
+			ret = fn(gic_data.redist_regions + i, ptr);
+			switch (ret) {
+			case 0:
 				return 0;
+			case -1:
+				break;
+			default:
+				ret = 0;
 			}
 
 			if (gic_data.redist_regions[i].single_redist)
@@ -473,9 +464,53 @@ static int gic_populate_rdist(void)
 		} while (!(typer & GICR_TYPER_LAST));
 	}
 
+	if (ret == -1)
+		ret = -ENODEV;
+
+	return 0;
+}
+
+static int __gic_populate_rdist(struct redist_region *region, void __iomem *ptr)
+{
+	unsigned long mpidr = cpu_logical_map(smp_processor_id());
+	u64 typer;
+	u32 aff;
+
+	/*
+	 * Convert affinity to a 32bit value that can be matched to
+	 * GICR_TYPER bits [63:32].
+	 */
+	aff = (MPIDR_AFFINITY_LEVEL(mpidr, 3) << 24 |
+	       MPIDR_AFFINITY_LEVEL(mpidr, 2) << 16 |
+	       MPIDR_AFFINITY_LEVEL(mpidr, 1) << 8 |
+	       MPIDR_AFFINITY_LEVEL(mpidr, 0));
+
+	typer = gic_read_typer(ptr + GICR_TYPER);
+	if ((typer >> 32) == aff) {
+		u64 offset = ptr - region->redist_base;
+		gic_data_rdist_rd_base() = ptr;
+		gic_data_rdist()->phys_base = region->phys_base + offset;
+
+		pr_info("CPU%d: found redistributor %lx region %d:%pa\n",
+			smp_processor_id(), mpidr,
+			(int)(region - gic_data.redist_regions),
+			&gic_data_rdist()->phys_base);
+		return 0;
+	}
+
+	/* Try next one */
+	return 1;
+}
+
+static int gic_populate_rdist(void)
+{
+	if (gic_scan_rdist_properties(__gic_populate_rdist) == 0)
+		return 0;
+
 	/* We couldn't even deal with ourselves... */
 	WARN(true, "CPU%d: mpidr %lx has no re-distributor!\n",
-	     smp_processor_id(), mpidr);
+	     smp_processor_id(),
+	     (unsigned long)cpu_logical_map(smp_processor_id()));
 	return -ENODEV;
 }
 
-- 
2.1.4

^ permalink raw reply related

* [RFC PATCH 02/33] irqchip/gic-v3: Add VLPI/DirectLPI discovery
From: Marc Zyngier @ 2017-01-17 10:20 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484648454-21216-1-git-send-email-marc.zyngier@arm.com>

Add helper functions that probe for VLPI and DirectLPI properties.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/irqchip/irq-gic-v3.c       | 22 ++++++++++++++++++++++
 include/linux/irqchip/arm-gic-v3.h |  3 +++
 2 files changed, 25 insertions(+)

diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 5cadec0..8a6de91 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -514,6 +514,24 @@ static int gic_populate_rdist(void)
 	return -ENODEV;
 }
 
+static int __gic_update_vlpi_properties(struct redist_region *region,
+					void __iomem *ptr)
+{
+	u64 typer = gic_read_typer(ptr + GICR_TYPER);
+	gic_data.rdists.has_vlpis &= !!(typer & GICR_TYPER_VLPIS);
+	gic_data.rdists.has_direct_lpi &= !!(typer & GICR_TYPER_DirectLPIS);
+
+	return 1;
+}
+
+static void gic_update_vlpi_properties(void)
+{
+	gic_scan_rdist_properties(__gic_update_vlpi_properties);
+	pr_info("%sVLPI support, %sdirect LPI support\n",
+		!gic_data.rdists.has_vlpis ? "no " : "",
+		!gic_data.rdists.has_direct_lpi ? "no " : "");
+}
+
 static void gic_cpu_sys_reg_init(void)
 {
 	/*
@@ -975,6 +993,8 @@ static int __init gic_init_bases(void __iomem *dist_base,
 	gic_data.domain = irq_domain_create_tree(handle, &gic_irq_domain_ops,
 						 &gic_data);
 	gic_data.rdists.rdist = alloc_percpu(typeof(*gic_data.rdists.rdist));
+	gic_data.rdists.has_vlpis = true;
+	gic_data.rdists.has_direct_lpi = true;
 
 	if (WARN_ON(!gic_data.domain) || WARN_ON(!gic_data.rdists.rdist)) {
 		err = -ENOMEM;
@@ -983,6 +1003,8 @@ static int __init gic_init_bases(void __iomem *dist_base,
 
 	set_handle_irq(gic_handle_irq);
 
+	gic_update_vlpi_properties();
+
 	if (IS_ENABLED(CONFIG_ARM_GIC_V3_ITS) && gic_dist_supports_lpis())
 		its_init(handle, &gic_data.rdists, gic_data.domain);
 
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index e808f8a..b162bfa 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -200,6 +200,7 @@
 
 #define GICR_TYPER_PLPIS		(1U << 0)
 #define GICR_TYPER_VLPIS		(1U << 1)
+#define GICR_TYPER_DirectLPIS		(1U << 3)
 #define GICR_TYPER_LAST			(1U << 4)
 
 #define GIC_V3_REDIST_SIZE		0x20000
@@ -427,6 +428,8 @@ struct rdists {
 	struct page		*prop_page;
 	int			id_bits;
 	u64			flags;
+	bool			has_vlpis;
+	bool			has_direct_lpi;
 };
 
 struct irq_domain;
-- 
2.1.4

^ permalink raw reply related

* [RFC PATCH 03/33] irqchip/gic-v3-its: Refactor command encoding
From: Marc Zyngier @ 2017-01-17 10:20 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484648454-21216-1-git-send-email-marc.zyngier@arm.com>

The way we encode the various ITS command fields is both tedious
and error prone. Let's introduce a helper function that performs
the encoding, and convert the existing encoders to use that
helper.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/irqchip/irq-gic-v3-its.c | 34 ++++++++++++++++------------------
 1 file changed, 16 insertions(+), 18 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 69b040f..49b681e 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -193,58 +193,56 @@ struct its_cmd_block {
 typedef struct its_collection *(*its_cmd_builder_t)(struct its_cmd_block *,
 						    struct its_cmd_desc *);
 
+static void its_mask_encode(u64 *raw_cmd, u64 val, int h, int l)
+{
+	u64 mask = GENMASK_ULL(h, l);
+	*raw_cmd &= ~mask;
+	*raw_cmd |= (val << l) & mask;
+}
+
 static void its_encode_cmd(struct its_cmd_block *cmd, u8 cmd_nr)
 {
-	cmd->raw_cmd[0] &= ~0xffULL;
-	cmd->raw_cmd[0] |= cmd_nr;
+	its_mask_encode(&cmd->raw_cmd[0], cmd_nr, 7, 0);
 }
 
 static void its_encode_devid(struct its_cmd_block *cmd, u32 devid)
 {
-	cmd->raw_cmd[0] &= BIT_ULL(32) - 1;
-	cmd->raw_cmd[0] |= ((u64)devid) << 32;
+	its_mask_encode(&cmd->raw_cmd[0], devid, 63, 32);
 }
 
 static void its_encode_event_id(struct its_cmd_block *cmd, u32 id)
 {
-	cmd->raw_cmd[1] &= ~0xffffffffULL;
-	cmd->raw_cmd[1] |= id;
+	its_mask_encode(&cmd->raw_cmd[1], id, 31, 0);
 }
 
 static void its_encode_phys_id(struct its_cmd_block *cmd, u32 phys_id)
 {
-	cmd->raw_cmd[1] &= 0xffffffffULL;
-	cmd->raw_cmd[1] |= ((u64)phys_id) << 32;
+	its_mask_encode(&cmd->raw_cmd[1], phys_id, 63, 32);
 }
 
 static void its_encode_size(struct its_cmd_block *cmd, u8 size)
 {
-	cmd->raw_cmd[1] &= ~0x1fULL;
-	cmd->raw_cmd[1] |= size & 0x1f;
+	its_mask_encode(&cmd->raw_cmd[1], size, 4, 0);
 }
 
 static void its_encode_itt(struct its_cmd_block *cmd, u64 itt_addr)
 {
-	cmd->raw_cmd[2] &= ~0xffffffffffffULL;
-	cmd->raw_cmd[2] |= itt_addr & 0xffffffffff00ULL;
+	its_mask_encode(&cmd->raw_cmd[2], itt_addr >> 8, 50, 8);
 }
 
 static void its_encode_valid(struct its_cmd_block *cmd, int valid)
 {
-	cmd->raw_cmd[2] &= ~(1ULL << 63);
-	cmd->raw_cmd[2] |= ((u64)!!valid) << 63;
+	its_mask_encode(&cmd->raw_cmd[2], !!valid, 63, 63);
 }
 
 static void its_encode_target(struct its_cmd_block *cmd, u64 target_addr)
 {
-	cmd->raw_cmd[2] &= ~(0xffffffffULL << 16);
-	cmd->raw_cmd[2] |= (target_addr & (0xffffffffULL << 16));
+	its_mask_encode(&cmd->raw_cmd[2], target_addr >> 16, 50, 16);
 }
 
 static void its_encode_collection(struct its_cmd_block *cmd, u16 col)
 {
-	cmd->raw_cmd[2] &= ~0xffffULL;
-	cmd->raw_cmd[2] |= col;
+	its_mask_encode(&cmd->raw_cmd[2], col, 15, 0);
 }
 
 static inline void its_fixup_cmd(struct its_cmd_block *cmd)
-- 
2.1.4

^ permalink raw reply related

* [RFC PATCH 04/33] irqchip/gic-v3-its: Move LPI definitions around
From: Marc Zyngier @ 2017-01-17 10:20 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484648454-21216-1-git-send-email-marc.zyngier@arm.com>

The various LPI definitions are in the middle of the code, and
would be better placed at the beginning, given that we're going
to use some of them much earlier.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/irqchip/irq-gic-v3-its.c | 27 +++++++++++++++------------
 1 file changed, 15 insertions(+), 12 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 49b681e..2ca27f6 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -49,6 +49,21 @@
 #define RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING	(1 << 0)
 
 /*
+ * We allocate 64kB for PROPBASE. That gives us@most 64K LPIs to
+ * deal with (one configuration byte per interrupt). PENDBASE has to
+ * be 64kB aligned (one bit per LPI, plus 8192 bits for SPI/PPI/SGI).
+ */
+#define LPI_PROPBASE_SZ		SZ_64K
+#define LPI_PENDBASE_SZ		(LPI_PROPBASE_SZ / 8 + SZ_1K)
+
+/*
+ * This is how many bits of ID we need, including the useless ones.
+ */
+#define LPI_NRBITS		ilog2(LPI_PROPBASE_SZ + SZ_8K)
+
+#define LPI_PROP_DEFAULT_PRIO	0xa0
+
+/*
  * Collection structure - just an ID, and a redistributor address to
  * ping. We use one per CPU as a bag of interrupts assigned to this
  * CPU.
@@ -779,20 +794,8 @@ static void its_lpi_free(struct event_lpi_map *map)
 	kfree(map->col_map);
 }
 
-/*
- * We allocate 64kB for PROPBASE. That gives us at most 64K LPIs to
- * deal with (one configuration byte per interrupt). PENDBASE has to
- * be 64kB aligned (one bit per LPI, plus 8192 bits for SPI/PPI/SGI).
- */
-#define LPI_PROPBASE_SZ		SZ_64K
-#define LPI_PENDBASE_SZ		(LPI_PROPBASE_SZ / 8 + SZ_1K)
 
-/*
- * This is how many bits of ID we need, including the useless ones.
- */
-#define LPI_NRBITS		ilog2(LPI_PROPBASE_SZ + SZ_8K)
 
-#define LPI_PROP_DEFAULT_PRIO	0xa0
 
 static int __init its_alloc_lpi_tables(void)
 {
-- 
2.1.4

^ permalink raw reply related

* [RFC PATCH 05/33] irqchip/gic-v3-its: Zero command on allocation
From: Marc Zyngier @ 2017-01-17 10:20 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484648454-21216-1-git-send-email-marc.zyngier@arm.com>

When reusing commands from the ring buffer, it would be better
to zero them out, even if the ITS should ignore the unused
fields.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/irqchip/irq-gic-v3-its.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 2ca27f6..9304dd2 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -426,6 +426,12 @@ static struct its_cmd_block *its_allocate_entry(struct its_node *its)
 	if (its->cmd_write == (its->cmd_base + ITS_CMD_QUEUE_NR_ENTRIES))
 		its->cmd_write = its->cmd_base;
 
+	/* Clear command  */
+	cmd->raw_cmd[0] = 0;
+	cmd->raw_cmd[1] = 0;
+	cmd->raw_cmd[2] = 0;
+	cmd->raw_cmd[3] = 0;
+
 	return cmd;
 }
 
-- 
2.1.4

^ permalink raw reply related

* [RFC PATCH 06/33] irqchip/gic-v3-its: Add probing for VLPI properties
From: Marc Zyngier @ 2017-01-17 10:20 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484648454-21216-1-git-send-email-marc.zyngier@arm.com>

Add the probing code for the ITS VLPI support. This includes
configuring the ITS number if not supporting the single VMOVP
command feature.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/irqchip/irq-gic-v3-its.c   | 47 ++++++++++++++++++++++++++++++++++----
 include/linux/irqchip/arm-gic-v3.h |  4 ++++
 2 files changed, 47 insertions(+), 4 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 9304dd2..99f6130 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -103,6 +103,7 @@ struct its_node {
 	u32			ite_size;
 	u32			device_ids;
 	int			numa_node;
+	bool			is_v4;
 };
 
 #define ITS_ITT_ALIGN		SZ_256
@@ -135,6 +136,8 @@ static DEFINE_SPINLOCK(its_lock);
 static struct rdists *gic_rdists;
 static struct irq_domain *its_parent;
 
+static unsigned long its_list_map;
+
 #define gic_data_rdist()		(raw_cpu_ptr(gic_rdists->rdist))
 #define gic_data_rdist_rd_base()	(gic_data_rdist()->rd_base)
 
@@ -1661,8 +1664,8 @@ static int __init its_probe_one(struct resource *res,
 {
 	struct its_node *its;
 	void __iomem *its_base;
-	u32 val;
-	u64 baser, tmp;
+	u32 val, ctlr;
+	u64 baser, tmp, typer;
 	int err;
 
 	its_base = ioremap(res->start, resource_size(res));
@@ -1695,9 +1698,44 @@ static int __init its_probe_one(struct resource *res,
 	raw_spin_lock_init(&its->lock);
 	INIT_LIST_HEAD(&its->entry);
 	INIT_LIST_HEAD(&its->its_device_list);
+	typer = gic_read_typer(its_base + GITS_TYPER);
 	its->base = its_base;
 	its->phys_base = res->start;
-	its->ite_size = ((gic_read_typer(its_base + GITS_TYPER) >> 4) & 0xf) + 1;
+	its->ite_size = ((typer >> 4) & 0xf) + 1;
+	its->is_v4 = !!(typer & GITS_TYPER_VLPIS);
+	if (its->is_v4 && !(typer & GITS_TYPER_VMOVP)) {
+		int its_number;
+
+		its_number = find_first_zero_bit(&its_list_map, 16);
+		if (its_number >= 16) {
+			pr_err("ITS@%pa: No ITSList entry available!\n",
+			       &res->start);
+			err = -EINVAL;
+			goto out_free_its;
+		}
+
+		ctlr = readl_relaxed(its_base + GITS_CTLR);
+		ctlr &= ~GITS_CTLR_ITS_NUMBER;
+		ctlr |= its_number << GITS_CTLR_ITS_NUMBER_SHIFT;
+		writel_relaxed(ctlr, its_base + GITS_CTLR);
+		ctlr = readl_relaxed(its_base + GITS_CTLR);
+		if ((ctlr & GITS_CTLR_ITS_NUMBER) != (its_number << GITS_CTLR_ITS_NUMBER_SHIFT)) {
+			its_number = ctlr & GITS_CTLR_ITS_NUMBER;
+			its_number >>= GITS_CTLR_ITS_NUMBER_SHIFT;
+		}
+
+		if (test_and_set_bit(its_number, &its_list_map)) {
+			pr_err("ITS@%pa: Duplicate ITSList entry %d\n",
+			       &res->start, its_number);
+			err = -EINVAL;
+			goto out_free_its;
+		}
+
+		pr_info("ITS@%pa: Using ITS number %d\n", &res->start, its_number);
+	} else {
+		pr_info("ITS@%pa: Single VMOVP capable\n", &res->start);
+	}
+
 	its->numa_node = numa_node;
 
 	its->cmd_base = kzalloc(ITS_CMD_QUEUE_SZ, GFP_KERNEL);
@@ -1743,7 +1781,8 @@ static int __init its_probe_one(struct resource *res,
 	}
 
 	gits_write_cwriter(0, its->base + GITS_CWRITER);
-	writel_relaxed(GITS_CTLR_ENABLE, its->base + GITS_CTLR);
+	ctlr = readl_relaxed(its->base + GITS_CTLR);
+	writel_relaxed(ctlr | GITS_CTLR_ENABLE, its->base + GITS_CTLR);
 
 	err = its_init_domain(handle, its);
 	if (err)
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index b162bfa..dc7dcc6 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -231,14 +231,18 @@
 #define GITS_TRANSLATER			0x10040
 
 #define GITS_CTLR_ENABLE		(1U << 0)
+#define	GITS_CTLR_ITS_NUMBER_SHIFT	4
+#define	GITS_CTLR_ITS_NUMBER		(0xFU << GITS_CTLR_ITS_NUMBER_SHIFT)
 #define GITS_CTLR_QUIESCENT		(1U << 31)
 
 #define GITS_TYPER_PLPIS		(1UL << 0)
+#define GITS_TYPER_VLPIS		(1UL << 1)
 #define GITS_TYPER_IDBITS_SHIFT		8
 #define GITS_TYPER_DEVBITS_SHIFT	13
 #define GITS_TYPER_DEVBITS(r)		((((r) >> GITS_TYPER_DEVBITS_SHIFT) & 0x1f) + 1)
 #define GITS_TYPER_PTA			(1UL << 19)
 #define GITS_TYPER_HWCOLLCNT_SHIFT	24
+#define GITS_TYPER_VMOVP		(1ULL << 37)
 
 #define GITS_CBASER_VALID			(1ULL << 63)
 #define GITS_CBASER_SHAREABILITY_SHIFT		(10)
-- 
2.1.4

^ permalink raw reply related

* [RFC PATCH 07/33] irqchip/gic-v3-its: Macro-ize its_send_single_command
From: Marc Zyngier @ 2017-01-17 10:20 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484648454-21216-1-git-send-email-marc.zyngier@arm.com>

Most ITS commands do operate on a collection object, and require
a SYNC command to be performed on that collection in order to
guarantee the execution of the first command.

With GICv4 ITS, another set of commands perform similar operations
on a VPE object, and a VSYNC operations must be executed to guarantee
their execution.

Given the similarities (post a command, perform a synchronization
operation on a sync object), it makes sense to reuse the same
mechanism for both class of commands.

Let's start with turning its_send_single_command into a huge macro
that performs the bulk of the work, and a set of helpers that
make this macro useeable for the GICv3 ITS commands.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/irqchip/irq-gic-v3-its.c | 82 ++++++++++++++++++++++------------------
 1 file changed, 45 insertions(+), 37 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 99f6130..520b764 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -484,43 +484,51 @@ static void its_wait_for_range_completion(struct its_node *its,
 	}
 }
 
-static void its_send_single_command(struct its_node *its,
-				    its_cmd_builder_t builder,
-				    struct its_cmd_desc *desc)
-{
-	struct its_cmd_block *cmd, *sync_cmd, *next_cmd;
-	struct its_collection *sync_col;
-	unsigned long flags;
-
-	raw_spin_lock_irqsave(&its->lock, flags);
-
-	cmd = its_allocate_entry(its);
-	if (!cmd) {		/* We're soooooo screewed... */
-		pr_err_ratelimited("ITS can't allocate, dropping command\n");
-		raw_spin_unlock_irqrestore(&its->lock, flags);
-		return;
-	}
-	sync_col = builder(cmd, desc);
-	its_flush_cmd(its, cmd);
-
-	if (sync_col) {
-		sync_cmd = its_allocate_entry(its);
-		if (!sync_cmd) {
-			pr_err_ratelimited("ITS can't SYNC, skipping\n");
-			goto post;
-		}
-		its_encode_cmd(sync_cmd, GITS_CMD_SYNC);
-		its_encode_target(sync_cmd, sync_col->target_address);
-		its_fixup_cmd(sync_cmd);
-		its_flush_cmd(its, sync_cmd);
-	}
-
-post:
-	next_cmd = its_post_commands(its);
-	raw_spin_unlock_irqrestore(&its->lock, flags);
-
-	its_wait_for_range_completion(its, cmd, next_cmd);
-}
+#define __its_send_single_cmd(name, buildtype, synctype, buildfn)	\
+void name(struct its_node *its,						\
+	  buildtype builder,						\
+	  struct its_cmd_desc *desc)					\
+{									\
+	struct its_cmd_block *cmd, *sync_cmd, *next_cmd;		\
+	synctype *sync_obj;						\
+	unsigned long flags;						\
+									\
+	raw_spin_lock_irqsave(&its->lock, flags);			\
+									\
+	cmd = its_allocate_entry(its);					\
+	if (!cmd) {		/* We're soooooo screewed... */		\
+		raw_spin_unlock_irqrestore(&its->lock, flags);		\
+		return;							\
+	}								\
+	sync_obj = builder(cmd, desc);					\
+	its_flush_cmd(its, cmd);					\
+									\
+	if (sync_obj) {							\
+		sync_cmd = its_allocate_entry(its);			\
+		if (!sync_cmd)						\
+			goto post;					\
+									\
+		buildfn(sync_cmd, sync_obj);				\
+		its_fixup_cmd(sync_cmd);				\
+		its_flush_cmd(its, sync_cmd);				\
+	}								\
+									\
+post:									\
+	next_cmd = its_post_commands(its);				\
+	raw_spin_unlock_irqrestore(&its->lock, flags);			\
+									\
+	its_wait_for_range_completion(its, cmd, next_cmd);		\
+}
+
+static void its_build_sync_cmd(struct its_cmd_block *sync_cmd,
+			       struct its_collection *sync_col)
+{
+	its_encode_cmd(sync_cmd, GITS_CMD_SYNC);
+	its_encode_target(sync_cmd, sync_col->target_address);
+}
+
+static __its_send_single_cmd(its_send_single_command, its_cmd_builder_t,
+			     struct its_collection, its_build_sync_cmd)
 
 static void its_send_inv(struct its_device *dev, u32 event_id)
 {
-- 
2.1.4

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox