linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/3] Start getting rid of the GPIO_NO_WAKE_IRQ
@ 2021-08-19 11:53 Maulik Shah
  2021-08-19 11:53 ` [PATCH v2 1/3] irqdomain: Export irq_domain_disconnect_hierarchy() Maulik Shah
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Maulik Shah @ 2021-08-19 11:53 UTC (permalink / raw)
  To: maz, tglx
  Cc: linux-kernel, linux-arm-msm, linux-gpio, bjorn.andersson,
	linus.walleij, tkjos, lsrao, Maulik Shah

v2:
- Use fix from marc [1] and drop v1 patch 2
- Add new patch for fixes irq_domain_trim_hierarchy()

gpio_to_irq() reports error at irq_domain_trim_hierarchy() for non wakeup
capable GPIOs that do not have dedicated interrupt at GIC.

Since PDC irqchip do not allocate irq at parent GIC domain for such GPIOs
indicate same by using irq_domain_disconnect_hierarchy() for it own domain
and all its parent domains.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git/commit/?h=irq/qcom-pdc-nowake&id=331b2ba388a4a79b5c40b8addf56cbe35099a410
[2] https://patchwork.kernel.org/project/linux-arm-msm/list/?series=532669

Marc Zyngier (1):
  irqchip/qcom-pdc: Start getting rid of the GPIO_NO_WAKE_IRQ

Maulik Shah (2):
  irqdomain: Export irq_domain_disconnect_hierarchy()
  irqdomain: Fix irq_domain_trim_hierarchy()

 drivers/irqchip/qcom-pdc.c | 75 +++++++++++-----------------------------------
 kernel/irq/irqdomain.c     |  6 ++--
 2 files changed, 22 insertions(+), 59 deletions(-)

-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v2 1/3] irqdomain: Export irq_domain_disconnect_hierarchy()
  2021-08-19 11:53 [PATCH v2 0/3] Start getting rid of the GPIO_NO_WAKE_IRQ Maulik Shah
@ 2021-08-19 11:53 ` Maulik Shah
  2021-08-19 11:53 ` [PATCH v2 2/3] irqdomain: Fix irq_domain_trim_hierarchy() Maulik Shah
  2021-08-19 11:53 ` [PATCH v2 3/3] irqchip/qcom-pdc: Start getting rid of the GPIO_NO_WAKE_IRQ Maulik Shah
  2 siblings, 0 replies; 7+ messages in thread
From: Maulik Shah @ 2021-08-19 11:53 UTC (permalink / raw)
  To: maz, tglx
  Cc: linux-kernel, linux-arm-msm, linux-gpio, bjorn.andersson,
	linus.walleij, tkjos, lsrao, Maulik Shah

Export irq_domain_disconnect_hierarchy() so irqchip module drivers
can use it.

Signed-off-by: Maulik Shah <mkshah@codeaurora.org>
---
 kernel/irq/irqdomain.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 0eee481..19e83e9 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -1216,6 +1216,7 @@ int irq_domain_disconnect_hierarchy(struct irq_domain *domain,
 	irqd->chip = ERR_PTR(-ENOTCONN);
 	return 0;
 }
+EXPORT_SYMBOL_GPL(irq_domain_disconnect_hierarchy);
 
 static int irq_domain_trim_hierarchy(unsigned int virq)
 {
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v2 2/3] irqdomain: Fix irq_domain_trim_hierarchy()
  2021-08-19 11:53 [PATCH v2 0/3] Start getting rid of the GPIO_NO_WAKE_IRQ Maulik Shah
  2021-08-19 11:53 ` [PATCH v2 1/3] irqdomain: Export irq_domain_disconnect_hierarchy() Maulik Shah
@ 2021-08-19 11:53 ` Maulik Shah
  2021-08-20 15:54   ` Marc Zyngier
  2021-08-19 11:53 ` [PATCH v2 3/3] irqchip/qcom-pdc: Start getting rid of the GPIO_NO_WAKE_IRQ Maulik Shah
  2 siblings, 1 reply; 7+ messages in thread
From: Maulik Shah @ 2021-08-19 11:53 UTC (permalink / raw)
  To: maz, tglx
  Cc: linux-kernel, linux-arm-msm, linux-gpio, bjorn.andersson,
	linus.walleij, tkjos, lsrao, Maulik Shah

Currently tail marker is moving along with parent domain
irq data. Fix this to initialize only once from where all
parent domain needs trimming.

Also correct the valid irq chip check.

Signed-off-by: Maulik Shah <mkshah@codeaurora.org>
---
 kernel/irq/irqdomain.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 19e83e9..9f6187b 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -1235,7 +1235,7 @@ static int irq_domain_trim_hierarchy(unsigned int virq)
 	 */
 	for (irqd = irq_data->parent_data; irqd; irq_data = irqd, irqd = irqd->parent_data) {
 		/* Can't have a valid irqchip after a trim marker */
-		if (irqd->chip && tail)
+		if (!IS_ERR(irqd->chip) && tail)
 			return -EINVAL;
 
 		/* Can't have an empty irqchip before a trim marker */
@@ -1247,7 +1247,8 @@ static int irq_domain_trim_hierarchy(unsigned int virq)
 			if (PTR_ERR(irqd->chip) != -ENOTCONN)
 				return -EINVAL;
 
-			tail = irq_data;
+			if (!tail)
+				tail = irq_data;
 		}
 	}
 
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v2 3/3] irqchip/qcom-pdc: Start getting rid of the GPIO_NO_WAKE_IRQ
  2021-08-19 11:53 [PATCH v2 0/3] Start getting rid of the GPIO_NO_WAKE_IRQ Maulik Shah
  2021-08-19 11:53 ` [PATCH v2 1/3] irqdomain: Export irq_domain_disconnect_hierarchy() Maulik Shah
  2021-08-19 11:53 ` [PATCH v2 2/3] irqdomain: Fix irq_domain_trim_hierarchy() Maulik Shah
@ 2021-08-19 11:53 ` Maulik Shah
  2021-08-20 15:38   ` Marc Zyngier
  2 siblings, 1 reply; 7+ messages in thread
From: Maulik Shah @ 2021-08-19 11:53 UTC (permalink / raw)
  To: maz, tglx
  Cc: linux-kernel, linux-arm-msm, linux-gpio, bjorn.andersson,
	linus.walleij, tkjos, lsrao, Maulik Shah

From: Marc Zyngier <maz@kernel.org>

gpio_to_irq() reports error at irq_domain_trim_hierarchy() for non
wakeup capable GPIOs that do not have dedicated interrupt at GIC.

Since PDC irqchip do not allocate irq at parent GIC domain for such
GPIOs indicate same by using irq_domain_disconnect_hierarchy() for
PDC and parent GIC domains.

Signed-off-by: Marc Zyngier <maz@kernel.org>
Signed-off-by: Maulik Shah <mkshah@codeaurora.org>
[mkshah: Add loop to disconnect for all parents]
Tested-by: Maulik Shah <mkshah@codeaurora.org>
---
 drivers/irqchip/qcom-pdc.c | 75 +++++++++++-----------------------------------
 1 file changed, 18 insertions(+), 57 deletions(-)

diff --git a/drivers/irqchip/qcom-pdc.c b/drivers/irqchip/qcom-pdc.c
index 32d5920..696afca 100644
--- a/drivers/irqchip/qcom-pdc.c
+++ b/drivers/irqchip/qcom-pdc.c
@@ -53,26 +53,6 @@ static u32 pdc_reg_read(int reg, u32 i)
 	return readl_relaxed(pdc_base + reg + i * sizeof(u32));
 }
 
-static int qcom_pdc_gic_get_irqchip_state(struct irq_data *d,
-					  enum irqchip_irq_state which,
-					  bool *state)
-{
-	if (d->hwirq == GPIO_NO_WAKE_IRQ)
-		return 0;
-
-	return irq_chip_get_parent_state(d, which, state);
-}
-
-static int qcom_pdc_gic_set_irqchip_state(struct irq_data *d,
-					  enum irqchip_irq_state which,
-					  bool value)
-{
-	if (d->hwirq == GPIO_NO_WAKE_IRQ)
-		return 0;
-
-	return irq_chip_set_parent_state(d, which, value);
-}
-
 static void pdc_enable_intr(struct irq_data *d, bool on)
 {
 	int pin_out = d->hwirq;
@@ -91,38 +71,16 @@ static void pdc_enable_intr(struct irq_data *d, bool on)
 
 static void qcom_pdc_gic_disable(struct irq_data *d)
 {
-	if (d->hwirq == GPIO_NO_WAKE_IRQ)
-		return;
-
 	pdc_enable_intr(d, false);
 	irq_chip_disable_parent(d);
 }
 
 static void qcom_pdc_gic_enable(struct irq_data *d)
 {
-	if (d->hwirq == GPIO_NO_WAKE_IRQ)
-		return;
-
 	pdc_enable_intr(d, true);
 	irq_chip_enable_parent(d);
 }
 
-static void qcom_pdc_gic_mask(struct irq_data *d)
-{
-	if (d->hwirq == GPIO_NO_WAKE_IRQ)
-		return;
-
-	irq_chip_mask_parent(d);
-}
-
-static void qcom_pdc_gic_unmask(struct irq_data *d)
-{
-	if (d->hwirq == GPIO_NO_WAKE_IRQ)
-		return;
-
-	irq_chip_unmask_parent(d);
-}
-
 /*
  * GIC does not handle falling edge or active low. To allow falling edge and
  * active low interrupts to be handled at GIC, PDC has an inverter that inverts
@@ -159,14 +117,10 @@ enum pdc_irq_config_bits {
  */
 static int qcom_pdc_gic_set_type(struct irq_data *d, unsigned int type)
 {
-	int pin_out = d->hwirq;
 	enum pdc_irq_config_bits pdc_type;
 	enum pdc_irq_config_bits old_pdc_type;
 	int ret;
 
-	if (pin_out == GPIO_NO_WAKE_IRQ)
-		return 0;
-
 	switch (type) {
 	case IRQ_TYPE_EDGE_RISING:
 		pdc_type = PDC_EDGE_RISING;
@@ -191,8 +145,8 @@ static int qcom_pdc_gic_set_type(struct irq_data *d, unsigned int type)
 		return -EINVAL;
 	}
 
-	old_pdc_type = pdc_reg_read(IRQ_i_CFG, pin_out);
-	pdc_reg_write(IRQ_i_CFG, pin_out, pdc_type);
+	old_pdc_type = pdc_reg_read(IRQ_i_CFG, d->hwirq);
+	pdc_reg_write(IRQ_i_CFG, d->hwirq, pdc_type);
 
 	ret = irq_chip_set_type_parent(d, type);
 	if (ret)
@@ -216,12 +170,12 @@ static int qcom_pdc_gic_set_type(struct irq_data *d, unsigned int type)
 static struct irq_chip qcom_pdc_gic_chip = {
 	.name			= "PDC",
 	.irq_eoi		= irq_chip_eoi_parent,
-	.irq_mask		= qcom_pdc_gic_mask,
-	.irq_unmask		= qcom_pdc_gic_unmask,
+	.irq_mask		= irq_chip_mask_parent,
+	.irq_unmask		= irq_chip_unmask_parent,
 	.irq_disable		= qcom_pdc_gic_disable,
 	.irq_enable		= qcom_pdc_gic_enable,
-	.irq_get_irqchip_state	= qcom_pdc_gic_get_irqchip_state,
-	.irq_set_irqchip_state	= qcom_pdc_gic_set_irqchip_state,
+	.irq_get_irqchip_state	= irq_chip_get_parent_state,
+	.irq_set_irqchip_state	= irq_chip_set_parent_state,
 	.irq_retrigger		= irq_chip_retrigger_hierarchy,
 	.irq_set_type		= qcom_pdc_gic_set_type,
 	.flags			= IRQCHIP_MASK_ON_SUSPEND |
@@ -282,7 +236,7 @@ static int qcom_pdc_alloc(struct irq_domain *domain, unsigned int virq,
 
 	parent_hwirq = get_parent_hwirq(hwirq);
 	if (parent_hwirq == PDC_NO_PARENT_IRQ)
-		return 0;
+		return irq_domain_disconnect_hierarchy(domain->parent, virq);
 
 	if (type & IRQ_TYPE_EDGE_BOTH)
 		type = IRQ_TYPE_EDGE_RISING;
@@ -314,22 +268,29 @@ static int qcom_pdc_gpio_alloc(struct irq_domain *domain, unsigned int virq,
 	irq_hw_number_t hwirq, parent_hwirq;
 	unsigned int type;
 	int ret;
+	struct irq_domain *parent;
 
 	ret = qcom_pdc_translate(domain, fwspec, &hwirq, &type);
 	if (ret)
 		return ret;
 
+	if (hwirq == GPIO_NO_WAKE_IRQ) {
+		for (parent = domain; parent; parent = parent->parent) {
+			ret = irq_domain_disconnect_hierarchy(parent, virq);
+			if (ret)
+				return ret;
+		}
+		return 0;
+	}
+
 	ret = irq_domain_set_hwirq_and_chip(domain, virq, hwirq,
 					    &qcom_pdc_gic_chip, NULL);
 	if (ret)
 		return ret;
 
-	if (hwirq == GPIO_NO_WAKE_IRQ)
-		return 0;
-
 	parent_hwirq = get_parent_hwirq(hwirq);
 	if (parent_hwirq == PDC_NO_PARENT_IRQ)
-		return 0;
+		return irq_domain_disconnect_hierarchy(domain->parent, virq);
 
 	if (type & IRQ_TYPE_EDGE_BOTH)
 		type = IRQ_TYPE_EDGE_RISING;
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH v2 3/3] irqchip/qcom-pdc: Start getting rid of the GPIO_NO_WAKE_IRQ
  2021-08-19 11:53 ` [PATCH v2 3/3] irqchip/qcom-pdc: Start getting rid of the GPIO_NO_WAKE_IRQ Maulik Shah
@ 2021-08-20 15:38   ` Marc Zyngier
  2021-08-23  7:55     ` Maulik Shah
  0 siblings, 1 reply; 7+ messages in thread
From: Marc Zyngier @ 2021-08-20 15:38 UTC (permalink / raw)
  To: Maulik Shah
  Cc: tglx, linux-kernel, linux-arm-msm, linux-gpio, bjorn.andersson,
	linus.walleij, tkjos, lsrao

On Thu, 19 Aug 2021 12:53:13 +0100,
Maulik Shah <mkshah@codeaurora.org> wrote:
> 
> From: Marc Zyngier <maz@kernel.org>
> 
> gpio_to_irq() reports error at irq_domain_trim_hierarchy() for non
> wakeup capable GPIOs that do not have dedicated interrupt at GIC.
> 
> Since PDC irqchip do not allocate irq at parent GIC domain for such
> GPIOs indicate same by using irq_domain_disconnect_hierarchy() for
> PDC and parent GIC domains.
> 
> Signed-off-by: Marc Zyngier <maz@kernel.org>
> Signed-off-by: Maulik Shah <mkshah@codeaurora.org>
> [mkshah: Add loop to disconnect for all parents]
> Tested-by: Maulik Shah <mkshah@codeaurora.org>
> ---
>  drivers/irqchip/qcom-pdc.c | 75 +++++++++++-----------------------------------
>  1 file changed, 18 insertions(+), 57 deletions(-)
> 
> diff --git a/drivers/irqchip/qcom-pdc.c b/drivers/irqchip/qcom-pdc.c
> index 32d5920..696afca 100644
> --- a/drivers/irqchip/qcom-pdc.c
> +++ b/drivers/irqchip/qcom-pdc.c
> @@ -53,26 +53,6 @@ static u32 pdc_reg_read(int reg, u32 i)
>  	return readl_relaxed(pdc_base + reg + i * sizeof(u32));
>  }
>  
> -static int qcom_pdc_gic_get_irqchip_state(struct irq_data *d,
> -					  enum irqchip_irq_state which,
> -					  bool *state)
> -{
> -	if (d->hwirq == GPIO_NO_WAKE_IRQ)
> -		return 0;
> -
> -	return irq_chip_get_parent_state(d, which, state);
> -}
> -
> -static int qcom_pdc_gic_set_irqchip_state(struct irq_data *d,
> -					  enum irqchip_irq_state which,
> -					  bool value)
> -{
> -	if (d->hwirq == GPIO_NO_WAKE_IRQ)
> -		return 0;
> -
> -	return irq_chip_set_parent_state(d, which, value);
> -}
> -
>  static void pdc_enable_intr(struct irq_data *d, bool on)
>  {
>  	int pin_out = d->hwirq;
> @@ -91,38 +71,16 @@ static void pdc_enable_intr(struct irq_data *d, bool on)
>  
>  static void qcom_pdc_gic_disable(struct irq_data *d)
>  {
> -	if (d->hwirq == GPIO_NO_WAKE_IRQ)
> -		return;
> -
>  	pdc_enable_intr(d, false);
>  	irq_chip_disable_parent(d);
>  }
>  
>  static void qcom_pdc_gic_enable(struct irq_data *d)
>  {
> -	if (d->hwirq == GPIO_NO_WAKE_IRQ)
> -		return;
> -
>  	pdc_enable_intr(d, true);
>  	irq_chip_enable_parent(d);
>  }
>  
> -static void qcom_pdc_gic_mask(struct irq_data *d)
> -{
> -	if (d->hwirq == GPIO_NO_WAKE_IRQ)
> -		return;
> -
> -	irq_chip_mask_parent(d);
> -}
> -
> -static void qcom_pdc_gic_unmask(struct irq_data *d)
> -{
> -	if (d->hwirq == GPIO_NO_WAKE_IRQ)
> -		return;
> -
> -	irq_chip_unmask_parent(d);
> -}
> -
>  /*
>   * GIC does not handle falling edge or active low. To allow falling edge and
>   * active low interrupts to be handled at GIC, PDC has an inverter that inverts
> @@ -159,14 +117,10 @@ enum pdc_irq_config_bits {
>   */
>  static int qcom_pdc_gic_set_type(struct irq_data *d, unsigned int type)
>  {
> -	int pin_out = d->hwirq;
>  	enum pdc_irq_config_bits pdc_type;
>  	enum pdc_irq_config_bits old_pdc_type;
>  	int ret;
>  
> -	if (pin_out == GPIO_NO_WAKE_IRQ)
> -		return 0;
> -
>  	switch (type) {
>  	case IRQ_TYPE_EDGE_RISING:
>  		pdc_type = PDC_EDGE_RISING;
> @@ -191,8 +145,8 @@ static int qcom_pdc_gic_set_type(struct irq_data *d, unsigned int type)
>  		return -EINVAL;
>  	}
>  
> -	old_pdc_type = pdc_reg_read(IRQ_i_CFG, pin_out);
> -	pdc_reg_write(IRQ_i_CFG, pin_out, pdc_type);
> +	old_pdc_type = pdc_reg_read(IRQ_i_CFG, d->hwirq);
> +	pdc_reg_write(IRQ_i_CFG, d->hwirq, pdc_type);
>  
>  	ret = irq_chip_set_type_parent(d, type);
>  	if (ret)
> @@ -216,12 +170,12 @@ static int qcom_pdc_gic_set_type(struct irq_data *d, unsigned int type)
>  static struct irq_chip qcom_pdc_gic_chip = {
>  	.name			= "PDC",
>  	.irq_eoi		= irq_chip_eoi_parent,
> -	.irq_mask		= qcom_pdc_gic_mask,
> -	.irq_unmask		= qcom_pdc_gic_unmask,
> +	.irq_mask		= irq_chip_mask_parent,
> +	.irq_unmask		= irq_chip_unmask_parent,
>  	.irq_disable		= qcom_pdc_gic_disable,
>  	.irq_enable		= qcom_pdc_gic_enable,
> -	.irq_get_irqchip_state	= qcom_pdc_gic_get_irqchip_state,
> -	.irq_set_irqchip_state	= qcom_pdc_gic_set_irqchip_state,
> +	.irq_get_irqchip_state	= irq_chip_get_parent_state,
> +	.irq_set_irqchip_state	= irq_chip_set_parent_state,
>  	.irq_retrigger		= irq_chip_retrigger_hierarchy,
>  	.irq_set_type		= qcom_pdc_gic_set_type,
>  	.flags			= IRQCHIP_MASK_ON_SUSPEND |
> @@ -282,7 +236,7 @@ static int qcom_pdc_alloc(struct irq_domain *domain, unsigned int virq,
>  
>  	parent_hwirq = get_parent_hwirq(hwirq);
>  	if (parent_hwirq == PDC_NO_PARENT_IRQ)
> -		return 0;
> +		return irq_domain_disconnect_hierarchy(domain->parent, virq);
>  
>  	if (type & IRQ_TYPE_EDGE_BOTH)
>  		type = IRQ_TYPE_EDGE_RISING;
> @@ -314,22 +268,29 @@ static int qcom_pdc_gpio_alloc(struct irq_domain *domain, unsigned int virq,
>  	irq_hw_number_t hwirq, parent_hwirq;
>  	unsigned int type;
>  	int ret;
> +	struct irq_domain *parent;
>  
>  	ret = qcom_pdc_translate(domain, fwspec, &hwirq, &type);
>  	if (ret)
>  		return ret;
>  
> +	if (hwirq == GPIO_NO_WAKE_IRQ) {
> +		for (parent = domain; parent; parent = parent->parent) {
> +			ret = irq_domain_disconnect_hierarchy(parent, virq);
> +			if (ret)
> +				return ret;
> +		}
> +		return 0;
> +	}
> +

No, this is wrong. Please read the documentation for
irq_domain_disconnect_hierarchy(): the disconnect can only take place
*once* per interrupt, right at the point where you need to terminate
the hierarchy.

irq_domain_trim_hierarchy() should already do the right thing by
iterating over the domains and free the unused irq_data.

	M.

-- 
Without deviation from the norm, progress is not possible.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2 2/3] irqdomain: Fix irq_domain_trim_hierarchy()
  2021-08-19 11:53 ` [PATCH v2 2/3] irqdomain: Fix irq_domain_trim_hierarchy() Maulik Shah
@ 2021-08-20 15:54   ` Marc Zyngier
  0 siblings, 0 replies; 7+ messages in thread
From: Marc Zyngier @ 2021-08-20 15:54 UTC (permalink / raw)
  To: Maulik Shah
  Cc: tglx, linux-kernel, linux-arm-msm, linux-gpio, bjorn.andersson,
	linus.walleij, tkjos, lsrao

On Thu, 19 Aug 2021 12:53:12 +0100,
Maulik Shah <mkshah@codeaurora.org> wrote:
> 
> Currently tail marker is moving along with parent domain
> irq data. Fix this to initialize only once from where all
> parent domain needs trimming.
> 
> Also correct the valid irq chip check.
> 
> Signed-off-by: Maulik Shah <mkshah@codeaurora.org>
> ---
>  kernel/irq/irqdomain.c | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
> index 19e83e9..9f6187b 100644
> --- a/kernel/irq/irqdomain.c
> +++ b/kernel/irq/irqdomain.c
> @@ -1235,7 +1235,7 @@ static int irq_domain_trim_hierarchy(unsigned int virq)
>  	 */
>  	for (irqd = irq_data->parent_data; irqd; irq_data = irqd, irqd = irqd->parent_data) {
>  		/* Can't have a valid irqchip after a trim marker */
> -		if (irqd->chip && tail)
> +		if (!IS_ERR(irqd->chip) && tail)
>  			return -EINVAL;
>  
>  		/* Can't have an empty irqchip before a trim marker */
> @@ -1247,7 +1247,8 @@ static int irq_domain_trim_hierarchy(unsigned int virq)
>  			if (PTR_ERR(irqd->chip) != -ENOTCONN)
>  				return -EINVAL;
>  
> -			tail = irq_data;
> +			if (!tail)
> +				tail = irq_data;
>  		}
>  	}

I think you have the wrong end of the stick. 'tail' represent the
*unique* point in the hierarchy where you can have a trim marker:

(1) If there is a valid irqchip after a trim marker, this is wrong
(2) If there is a trim marker after another trim marker, this is wrong
(3) If there is a NULL irqchip before a trim marker, this is wrong
(4) If there is an error that isn't a trim marker, this is wrong

(1) and (2) are captured by:
		if (irqd->chip && tail)
(3) is captured by:
		if (!irqd->chip && !tail)
(4) is captured by:
		if (IS_ERR(irqd->chip)) {
			/* Only -ENOTCONN is a valid trim marker */
			if (PTR_ERR(irqd->chip) != -ENOTCONN)

The expected usage is that:

- there is a single potential trim marker in the hierarchy
- all the irqd->chip pointers below the marker are NULL
- all the irqd->chip before the marker are neither NULL nor an error

I don't see any bug here.

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2 3/3] irqchip/qcom-pdc: Start getting rid of the GPIO_NO_WAKE_IRQ
  2021-08-20 15:38   ` Marc Zyngier
@ 2021-08-23  7:55     ` Maulik Shah
  0 siblings, 0 replies; 7+ messages in thread
From: Maulik Shah @ 2021-08-23  7:55 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: tglx, linux-kernel, linux-arm-msm, linux-gpio, bjorn.andersson,
	linus.walleij, tkjos, lsrao

Hi,

On 8/20/2021 9:08 PM, Marc Zyngier wrote:
> On Thu, 19 Aug 2021 12:53:13 +0100,
> Maulik Shah <mkshah@codeaurora.org> wrote:
>> From: Marc Zyngier <maz@kernel.org>
>>
>> gpio_to_irq() reports error at irq_domain_trim_hierarchy() for non
>> wakeup capable GPIOs that do not have dedicated interrupt at GIC.
>>
>> Since PDC irqchip do not allocate irq at parent GIC domain for such
>> GPIOs indicate same by using irq_domain_disconnect_hierarchy() for
>> PDC and parent GIC domains.
>>
>> Signed-off-by: Marc Zyngier <maz@kernel.org>
>> Signed-off-by: Maulik Shah <mkshah@codeaurora.org>
>> [mkshah: Add loop to disconnect for all parents]
>> Tested-by: Maulik Shah <mkshah@codeaurora.org>
>> ---
>>   drivers/irqchip/qcom-pdc.c | 75 +++++++++++-----------------------------------
>>   1 file changed, 18 insertions(+), 57 deletions(-)
>>
>> diff --git a/drivers/irqchip/qcom-pdc.c b/drivers/irqchip/qcom-pdc.c
>> index 32d5920..696afca 100644
>> --- a/drivers/irqchip/qcom-pdc.c
>> +++ b/drivers/irqchip/qcom-pdc.c
>> @@ -53,26 +53,6 @@ static u32 pdc_reg_read(int reg, u32 i)
>>   	return readl_relaxed(pdc_base + reg + i * sizeof(u32));
>>   }
>>   
>> -static int qcom_pdc_gic_get_irqchip_state(struct irq_data *d,
>> -					  enum irqchip_irq_state which,
>> -					  bool *state)
>> -{
>> -	if (d->hwirq == GPIO_NO_WAKE_IRQ)
>> -		return 0;
>> -
>> -	return irq_chip_get_parent_state(d, which, state);
>> -}
>> -
>> -static int qcom_pdc_gic_set_irqchip_state(struct irq_data *d,
>> -					  enum irqchip_irq_state which,
>> -					  bool value)
>> -{
>> -	if (d->hwirq == GPIO_NO_WAKE_IRQ)
>> -		return 0;
>> -
>> -	return irq_chip_set_parent_state(d, which, value);
>> -}
>> -
>>   static void pdc_enable_intr(struct irq_data *d, bool on)
>>   {
>>   	int pin_out = d->hwirq;
>> @@ -91,38 +71,16 @@ static void pdc_enable_intr(struct irq_data *d, bool on)
>>   
>>   static void qcom_pdc_gic_disable(struct irq_data *d)
>>   {
>> -	if (d->hwirq == GPIO_NO_WAKE_IRQ)
>> -		return;
>> -
>>   	pdc_enable_intr(d, false);
>>   	irq_chip_disable_parent(d);
>>   }
>>   
>>   static void qcom_pdc_gic_enable(struct irq_data *d)
>>   {
>> -	if (d->hwirq == GPIO_NO_WAKE_IRQ)
>> -		return;
>> -
>>   	pdc_enable_intr(d, true);
>>   	irq_chip_enable_parent(d);
>>   }
>>   
>> -static void qcom_pdc_gic_mask(struct irq_data *d)
>> -{
>> -	if (d->hwirq == GPIO_NO_WAKE_IRQ)
>> -		return;
>> -
>> -	irq_chip_mask_parent(d);
>> -}
>> -
>> -static void qcom_pdc_gic_unmask(struct irq_data *d)
>> -{
>> -	if (d->hwirq == GPIO_NO_WAKE_IRQ)
>> -		return;
>> -
>> -	irq_chip_unmask_parent(d);
>> -}
>> -
>>   /*
>>    * GIC does not handle falling edge or active low. To allow falling edge and
>>    * active low interrupts to be handled at GIC, PDC has an inverter that inverts
>> @@ -159,14 +117,10 @@ enum pdc_irq_config_bits {
>>    */
>>   static int qcom_pdc_gic_set_type(struct irq_data *d, unsigned int type)
>>   {
>> -	int pin_out = d->hwirq;
>>   	enum pdc_irq_config_bits pdc_type;
>>   	enum pdc_irq_config_bits old_pdc_type;
>>   	int ret;
>>   
>> -	if (pin_out == GPIO_NO_WAKE_IRQ)
>> -		return 0;
>> -
>>   	switch (type) {
>>   	case IRQ_TYPE_EDGE_RISING:
>>   		pdc_type = PDC_EDGE_RISING;
>> @@ -191,8 +145,8 @@ static int qcom_pdc_gic_set_type(struct irq_data *d, unsigned int type)
>>   		return -EINVAL;
>>   	}
>>   
>> -	old_pdc_type = pdc_reg_read(IRQ_i_CFG, pin_out);
>> -	pdc_reg_write(IRQ_i_CFG, pin_out, pdc_type);
>> +	old_pdc_type = pdc_reg_read(IRQ_i_CFG, d->hwirq);
>> +	pdc_reg_write(IRQ_i_CFG, d->hwirq, pdc_type);
>>   
>>   	ret = irq_chip_set_type_parent(d, type);
>>   	if (ret)
>> @@ -216,12 +170,12 @@ static int qcom_pdc_gic_set_type(struct irq_data *d, unsigned int type)
>>   static struct irq_chip qcom_pdc_gic_chip = {
>>   	.name			= "PDC",
>>   	.irq_eoi		= irq_chip_eoi_parent,
>> -	.irq_mask		= qcom_pdc_gic_mask,
>> -	.irq_unmask		= qcom_pdc_gic_unmask,
>> +	.irq_mask		= irq_chip_mask_parent,
>> +	.irq_unmask		= irq_chip_unmask_parent,
>>   	.irq_disable		= qcom_pdc_gic_disable,
>>   	.irq_enable		= qcom_pdc_gic_enable,
>> -	.irq_get_irqchip_state	= qcom_pdc_gic_get_irqchip_state,
>> -	.irq_set_irqchip_state	= qcom_pdc_gic_set_irqchip_state,
>> +	.irq_get_irqchip_state	= irq_chip_get_parent_state,
>> +	.irq_set_irqchip_state	= irq_chip_set_parent_state,
>>   	.irq_retrigger		= irq_chip_retrigger_hierarchy,
>>   	.irq_set_type		= qcom_pdc_gic_set_type,
>>   	.flags			= IRQCHIP_MASK_ON_SUSPEND |
>> @@ -282,7 +236,7 @@ static int qcom_pdc_alloc(struct irq_domain *domain, unsigned int virq,
>>   
>>   	parent_hwirq = get_parent_hwirq(hwirq);
>>   	if (parent_hwirq == PDC_NO_PARENT_IRQ)
>> -		return 0;
>> +		return irq_domain_disconnect_hierarchy(domain->parent, virq);
>>   
>>   	if (type & IRQ_TYPE_EDGE_BOTH)
>>   		type = IRQ_TYPE_EDGE_RISING;
>> @@ -314,22 +268,29 @@ static int qcom_pdc_gpio_alloc(struct irq_domain *domain, unsigned int virq,
>>   	irq_hw_number_t hwirq, parent_hwirq;
>>   	unsigned int type;
>>   	int ret;
>> +	struct irq_domain *parent;
>>   
>>   	ret = qcom_pdc_translate(domain, fwspec, &hwirq, &type);
>>   	if (ret)
>>   		return ret;
>>   
>> +	if (hwirq == GPIO_NO_WAKE_IRQ) {
>> +		for (parent = domain; parent; parent = parent->parent) {
>> +			ret = irq_domain_disconnect_hierarchy(parent, virq);
>> +			if (ret)
>> +				return ret;
>> +		}
>> +		return 0;
>> +	}
>> +
> No, this is wrong. Please read the documentation for
> irq_domain_disconnect_hierarchy(): the disconnect can only take place
> *once* per interrupt, right at the point where you need to terminate
> the hierarchy.
>
> irq_domain_trim_hierarchy() should already do the right thing by
> iterating over the domains and free the unused irq_data.
>
> 	M.
Thanks for the review. Seems we need disconnect only once per interrupt.
with this i see patch 2 in this series also of no use since it already 
takes care of removing irq_data for all the parents.

Addressed in v3 series.

Thanks,
Maulik

-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2021-08-23  7:56 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-08-19 11:53 [PATCH v2 0/3] Start getting rid of the GPIO_NO_WAKE_IRQ Maulik Shah
2021-08-19 11:53 ` [PATCH v2 1/3] irqdomain: Export irq_domain_disconnect_hierarchy() Maulik Shah
2021-08-19 11:53 ` [PATCH v2 2/3] irqdomain: Fix irq_domain_trim_hierarchy() Maulik Shah
2021-08-20 15:54   ` Marc Zyngier
2021-08-19 11:53 ` [PATCH v2 3/3] irqchip/qcom-pdc: Start getting rid of the GPIO_NO_WAKE_IRQ Maulik Shah
2021-08-20 15:38   ` Marc Zyngier
2021-08-23  7:55     ` Maulik Shah

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).