From: Suman Anna <hidden> Date: 2021-03-23 22:39:59
Hi,
The following series includes fixes for various different issues
associated with the PRU firmware event/interrupt mapping configuration
logic added in the same commit c75c9fdac66e ("remoteproc: pru: Add
support for PRU specific interrupt configuration"). The fixes are
agnostic of SoC family.
Following is the summary of issues and fixes:
- Patch #1 fixes the interrupt node finding logic to always use the
inherent sibling relationship between a PRU/RTU/Tx_PRU node and its
corresponding PRUSS INTC node. This fixes the firmware event mappings
for cases when the PRU nodes do not have an 'interrupt-parent' property
(this is the norm, the property is neither required nor added in the DT
nodes normally).
- Patch #2 fixes a minor issue with returning a success value to the
caller on a fw event mapping failure.
- Patch #3 fixes a kernel crash due to switching of firmwares between
consecutive runs, the first one with events and the second one without
events. There are no issues when the same firmwares are run or if they
are run in reverse order.
Patches should apply cleanly on top of the current rproc-fixes branch
commit 9afeefcf06fc ("remoteproc: pru: Fix firmware loading crashes on K3 SoCs")
regards
Suman
Suman Anna (3):
remoteproc: pru: Fixup interrupt-parent logic for fw events
remoteproc: pru: Fix wrong success return value for fw events
remoteproc: pru: Fix and cleanup firmware interrupt mapping logic
drivers/remoteproc/pru_rproc.c | 33 +++++++++++++++++++++++++--------
1 file changed, 25 insertions(+), 8 deletions(-)
--
2.30.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
From: Suman Anna <hidden> Date: 2021-03-23 22:39:29
The PRU firmware interrupt mapping logic in pru_handle_intrmap() uses
of_irq_find_parent() with PRU device node to get a handle to the PRUSS
Interrupt Controller at present. This logic however requires that the
PRU nodes always define a interrupt-parent property. This property is
neither a required/defined property as per the PRU remoteproc binding,
nor is relevant from a DT node point of view without any associated
interrupts. The curret logic finds a wrong interrupt controller and
fails to perform proper mapping without any interrupt-parent property
in the PRU nodes.
Fix this logic to always find and use the sibling interrupt controller.
Also, while at this, fix the acquired interrupt controller device node
reference properly.
Fixes: c75c9fdac66e ("remoteproc: pru: Add support for PRU specific interrupt configuration")
Signed-off-by: Suman Anna <redacted>
---
drivers/remoteproc/pru_rproc.c | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
@@ -284,7 +284,7 @@ static int pru_handle_intrmap(struct rproc *rproc)structpru_rproc*pru=rproc->priv;structpru_irq_rsc*rsc=pru->pru_interrupt_map;structirq_fwspecfwspec;-structdevice_node*irq_parent;+structdevice_node*parent,*irq_parent;inti,ret=0;/* not having pru_interrupt_map is not an error */
@@ -312,9 +312,16 @@ static int pru_handle_intrmap(struct rproc *rproc)/**parseandfillinsystemeventtointerruptchanneland-*channel-to-hostmapping+*channel-to-hostmapping.Theinterruptcontrollertobeused+*forthesemappingsforagivenPRUremoteprocisalwaysits+*correspondingsiblingPRUSSINTCnode.*/-irq_parent=of_irq_find_parent(pru->dev->of_node);+parent=of_get_parent(dev_of_node(pru->dev));+if(!parent)+return-ENODEV;++irq_parent=of_get_child_by_name(parent,"interrupt-controller");+of_node_put(parent);if(!irq_parent){kfree(pru->mapped_irq);return-ENODEV;
@@ -337,11 +344,13 @@ static int pru_handle_intrmap(struct rproc *rproc)gotomap_fail;}}+of_node_put(irq_parent);returnret;map_fail:pru_dispose_irq_mapping(pru);+of_node_put(irq_parent);returnret;}
--
2.30.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
On Tue, Mar 23, 2021 at 05:38:37PM -0500, Suman Anna wrote:
quoted hunk
The PRU firmware interrupt mapping logic in pru_handle_intrmap() uses
of_irq_find_parent() with PRU device node to get a handle to the PRUSS
Interrupt Controller at present. This logic however requires that the
PRU nodes always define a interrupt-parent property. This property is
neither a required/defined property as per the PRU remoteproc binding,
nor is relevant from a DT node point of view without any associated
interrupts. The curret logic finds a wrong interrupt controller and
fails to perform proper mapping without any interrupt-parent property
in the PRU nodes.
Fix this logic to always find and use the sibling interrupt controller.
Also, while at this, fix the acquired interrupt controller device node
reference properly.
Fixes: c75c9fdac66e ("remoteproc: pru: Add support for PRU specific interrupt configuration")
Signed-off-by: Suman Anna <redacted>
---
drivers/remoteproc/pru_rproc.c | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
@@ -284,7 +284,7 @@ static int pru_handle_intrmap(struct rproc *rproc)structpru_rproc*pru=rproc->priv;structpru_irq_rsc*rsc=pru->pru_interrupt_map;structirq_fwspecfwspec;-structdevice_node*irq_parent;+structdevice_node*parent,*irq_parent;inti,ret=0;/* not having pru_interrupt_map is not an error */
@@ -312,9 +312,16 @@ static int pru_handle_intrmap(struct rproc *rproc)/**parseandfillinsystemeventtointerruptchanneland-*channel-to-hostmapping+*channel-to-hostmapping.Theinterruptcontrollertobeused+*forthesemappingsforagivenPRUremoteprocisalwaysits+*correspondingsiblingPRUSSINTCnode.*/-irq_parent=of_irq_find_parent(pru->dev->of_node);
If I understand correctly when an interrupt controller node wasn't speficied in
the parent this was unwinding until it found one...
From: Suman Anna <hidden> Date: 2021-04-07 14:43:42
On 4/6/21 6:28 PM, Mathieu Poirier wrote:
On Tue, Mar 23, 2021 at 05:38:37PM -0500, Suman Anna wrote:
quoted
The PRU firmware interrupt mapping logic in pru_handle_intrmap() uses
of_irq_find_parent() with PRU device node to get a handle to the PRUSS
Interrupt Controller at present. This logic however requires that the
PRU nodes always define a interrupt-parent property. This property is
neither a required/defined property as per the PRU remoteproc binding,
nor is relevant from a DT node point of view without any associated
interrupts. The curret logic finds a wrong interrupt controller and
fails to perform proper mapping without any interrupt-parent property
in the PRU nodes.
Fix this logic to always find and use the sibling interrupt controller.
Also, while at this, fix the acquired interrupt controller device node
reference properly.
Fixes: c75c9fdac66e ("remoteproc: pru: Add support for PRU specific interrupt configuration")
Signed-off-by: Suman Anna <redacted>
---
drivers/remoteproc/pru_rproc.c | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
@@ -284,7 +284,7 @@ static int pru_handle_intrmap(struct rproc *rproc)structpru_rproc*pru=rproc->priv;structpru_irq_rsc*rsc=pru->pru_interrupt_map;structirq_fwspecfwspec;-structdevice_node*irq_parent;+structdevice_node*parent,*irq_parent;inti,ret=0;/* not having pru_interrupt_map is not an error */
@@ -312,9 +312,16 @@ static int pru_handle_intrmap(struct rproc *rproc)/**parseandfillinsystemeventtointerruptchanneland-*channel-to-hostmapping+*channel-to-hostmapping.Theinterruptcontrollertobeused+*forthesemappingsforagivenPRUremoteprocisalwaysits+*correspondingsiblingPRUSSINTCnode.*/-irq_parent=of_irq_find_parent(pru->dev->of_node);
If I understand correctly when an interrupt controller node wasn't speficied in
the parent this was unwinding until it found one...
Correct if not specified in each PRU node, and ends up finding the complete
wrong interrupt controller (GIC) as it walks up the tree.
From: Suman Anna <hidden> Date: 2021-03-23 22:39:59
The irq_create_fwspec_mapping() returns a proper virq value on success
and 0 upon any failure. The pru_handle_intrmap() treats this as an error
and disposes all firmware event mappings correctly, but is returning
this incorrect value as is, letting the pru_rproc_start() interpret it
as a success and boot the PRU.
Fix this by returning an error value back upon any such failure. While
at this, revise the error trace to print some meaningful info about the
failed event.
Fixes: c75c9fdac66e ("remoteproc: pru: Add support for PRU specific interrupt configuration")
Signed-off-by: Suman Anna <redacted>
---
drivers/remoteproc/pru_rproc.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
@@ -339,8 +339,10 @@ static int pru_handle_intrmap(struct rproc *rproc)pru->mapped_irq[i]=irq_create_fwspec_mapping(&fwspec);if(!pru->mapped_irq[i]){-dev_err(dev,"failed to get virq\n");-ret=pru->mapped_irq[i];+dev_err(dev,"failed to get virq for fw mapping %d: event %d chnl %d host %d\n",+i,fwspec.param[0],fwspec.param[1],+fwspec.param[2]);+ret=-EINVAL;gotomap_fail;}}
--
2.30.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
On Tue, Mar 23, 2021 at 05:38:38PM -0500, Suman Anna wrote:
The irq_create_fwspec_mapping() returns a proper virq value on success
and 0 upon any failure. The pru_handle_intrmap() treats this as an error
and disposes all firmware event mappings correctly, but is returning
this incorrect value as is, letting the pru_rproc_start() interpret it
as a success and boot the PRU.
Very subtle... I had to look twice to make sure.
Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>
quoted hunk
Fix this by returning an error value back upon any such failure. While
at this, revise the error trace to print some meaningful info about the
failed event.
Fixes: c75c9fdac66e ("remoteproc: pru: Add support for PRU specific interrupt configuration")
Signed-off-by: Suman Anna <redacted>
---
drivers/remoteproc/pru_rproc.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
@@ -339,8 +339,10 @@ static int pru_handle_intrmap(struct rproc *rproc)pru->mapped_irq[i]=irq_create_fwspec_mapping(&fwspec);if(!pru->mapped_irq[i]){-dev_err(dev,"failed to get virq\n");-ret=pru->mapped_irq[i];+dev_err(dev,"failed to get virq for fw mapping %d: event %d chnl %d host %d\n",+i,fwspec.param[0],fwspec.param[1],+fwspec.param[2]);+ret=-EINVAL;gotomap_fail;}}
From: Suman Anna <hidden> Date: 2021-03-23 22:39:59
The PRU firmware interrupt mappings are configured and unconfigured in
.start() and .stop() callbacks respectively using the variables 'evt_count'
and a 'mapped_irq' pointer. These variables are modified only during these
callbacks but are not re-initialized/reset properly during unwind or
failure paths. These stale values caused a kernel crash while stopping a
PRU remoteproc running a different firmware with no events on a subsequent
run after a previous run that was running a firmware with events.
Fix this crash by ensuring that the evt_count is 0 and the mapped_irq
pointer is set to NULL in pru_dispose_irq_mapping(). Also, reset these
variables properly during any failures in the .start() callback. While
at this, the pru_dispose_irq_mapping() callsites are all made to look
the same, moving any conditional logic to inside the function.
Fixes: c75c9fdac66e ("remoteproc: pru: Add support for PRU specific interrupt configuration")
Reported-by: Vignesh Raghavendra <vigneshr@ti.com>
Signed-off-by: Suman Anna <redacted>
---
drivers/remoteproc/pru_rproc.c | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
@@ -324,6 +329,8 @@ static int pru_handle_intrmap(struct rproc *rproc)of_node_put(parent);if(!irq_parent){kfree(pru->mapped_irq);+pru->mapped_irq=NULL;+pru->evt_count=0;return-ENODEV;}
@@ -398,8 +405,7 @@ static int pru_rproc_stop(struct rproc *rproc)pru_control_write_reg(pru,PRU_CTRL_CTRL,val);/* dispose irq mapping - new firmware can provide new mapping */-if(pru->mapped_irq)-pru_dispose_irq_mapping(pru);+pru_dispose_irq_mapping(pru);return0;}
--
2.30.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
On Tue, Mar 23, 2021 at 05:38:39PM -0500, Suman Anna wrote:
quoted hunk
The PRU firmware interrupt mappings are configured and unconfigured in
.start() and .stop() callbacks respectively using the variables 'evt_count'
and a 'mapped_irq' pointer. These variables are modified only during these
callbacks but are not re-initialized/reset properly during unwind or
failure paths. These stale values caused a kernel crash while stopping a
PRU remoteproc running a different firmware with no events on a subsequent
run after a previous run that was running a firmware with events.
Fix this crash by ensuring that the evt_count is 0 and the mapped_irq
pointer is set to NULL in pru_dispose_irq_mapping(). Also, reset these
variables properly during any failures in the .start() callback. While
at this, the pru_dispose_irq_mapping() callsites are all made to look
the same, moving any conditional logic to inside the function.
Fixes: c75c9fdac66e ("remoteproc: pru: Add support for PRU specific interrupt configuration")
Reported-by: Vignesh Raghavendra <vigneshr@ti.com>
Signed-off-by: Suman Anna <redacted>
---
drivers/remoteproc/pru_rproc.c | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
@@ -324,6 +329,8 @@ static int pru_handle_intrmap(struct rproc *rproc)of_node_put(parent);if(!irq_parent){kfree(pru->mapped_irq);+pru->mapped_irq=NULL;+pru->evt_count=0;
Patch 1/3 introduced a check on @parent that doesn't free pru->mapped_irq. I
would also expect that error path to do the same has what is done here. And
looking further up I see the error path for !pru->mapped_irq doesn't set
pru->evt_count to zero.
Thanks,
Mathieu
quoted hunk
return -ENODEV;
}
@@ -398,8 +405,7 @@ static int pru_rproc_stop(struct rproc *rproc) pru_control_write_reg(pru, PRU_CTRL_CTRL, val); /* dispose irq mapping - new firmware can provide new mapping */- if (pru->mapped_irq)- pru_dispose_irq_mapping(pru);+ pru_dispose_irq_mapping(pru); return 0; }
From: Suman Anna <hidden> Date: 2021-04-07 14:35:39
Hi Mathieu,
On 4/6/21 6:47 PM, Mathieu Poirier wrote:
On Tue, Mar 23, 2021 at 05:38:39PM -0500, Suman Anna wrote:
quoted
The PRU firmware interrupt mappings are configured and unconfigured in
.start() and .stop() callbacks respectively using the variables 'evt_count'
and a 'mapped_irq' pointer. These variables are modified only during these
callbacks but are not re-initialized/reset properly during unwind or
failure paths. These stale values caused a kernel crash while stopping a
PRU remoteproc running a different firmware with no events on a subsequent
run after a previous run that was running a firmware with events.
Fix this crash by ensuring that the evt_count is 0 and the mapped_irq
pointer is set to NULL in pru_dispose_irq_mapping(). Also, reset these
variables properly during any failures in the .start() callback. While
at this, the pru_dispose_irq_mapping() callsites are all made to look
the same, moving any conditional logic to inside the function.
Fixes: c75c9fdac66e ("remoteproc: pru: Add support for PRU specific interrupt configuration")
Reported-by: Vignesh Raghavendra <vigneshr@ti.com>
Signed-off-by: Suman Anna <redacted>
---
drivers/remoteproc/pru_rproc.c | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
@@ -324,6 +329,8 @@ static int pru_handle_intrmap(struct rproc *rproc)of_node_put(parent);if(!irq_parent){kfree(pru->mapped_irq);+pru->mapped_irq=NULL;+pru->evt_count=0;
Patch 1/3 introduced a check on @parent that doesn't free pru->mapped_irq. I
would also expect that error path to do the same has what is done here. And
looking further up I see the error path for !pru->mapped_irq doesn't set
pru->evt_count to zero.
Good catch, thank you. I will fix these up in v2.
regards
Suman
Thanks,
Mathieu
quoted
return -ENODEV;
}
@@ -398,8 +405,7 @@ static int pru_rproc_stop(struct rproc *rproc) pru_control_write_reg(pru, PRU_CTRL_CTRL, val); /* dispose irq mapping - new firmware can provide new mapping */- if (pru->mapped_irq)- pru_dispose_irq_mapping(pru);+ pru_dispose_irq_mapping(pru); return 0; }