0043-remoteproc-pru-Fix-and-cleanup-firmware-interrupt-ma.patch 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. From b763cdabc4c54e897400dc3fbfb3f9a795c41a48 Mon Sep 17 00:00:00 2001
  2. From: Suman Anna <s-anna@ti.com>
  3. Date: Wed, 7 Apr 2021 10:56:41 -0500
  4. Subject: [PATCH] remoteproc: pru: Fix and cleanup firmware interrupt mapping
  5. logic
  6. The PRU firmware interrupt mappings are configured and unconfigured in
  7. .start() and .stop() callbacks respectively using the variables 'evt_count'
  8. and a 'mapped_irq' pointer. These variables are modified only during these
  9. callbacks but are not re-initialized/reset properly during unwind or
  10. failure paths. These stale values caused a kernel crash while stopping a
  11. PRU remoteproc running a different firmware with no events on a subsequent
  12. run after a previous run that was running a firmware with events.
  13. Fix this crash by ensuring that the evt_count is 0 and the mapped_irq
  14. pointer is set to NULL in pru_dispose_irq_mapping(). Also, reset these
  15. variables properly during any failures in the .start() callback. While
  16. at this, the pru_dispose_irq_mapping() callsites are all made to look
  17. the same, moving any conditional logic to inside the function.
  18. Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>
  19. Fixes: c75c9fdac66e ("remoteproc: pru: Add support for PRU specific interrupt configuration")
  20. Reported-by: Vignesh Raghavendra <vigneshr@ti.com>
  21. Signed-off-by: Suman Anna <s-anna@ti.com>
  22. Link: https://lore.kernel.org/r/20210407155641.5501-4-s-anna@ti.com
  23. Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
  24. ---
  25. drivers/remoteproc/pru_rproc.c | 22 +++++++++++++++++-----
  26. 1 file changed, 17 insertions(+), 5 deletions(-)
  27. diff --git a/drivers/remoteproc/pru_rproc.c b/drivers/remoteproc/pru_rproc.c
  28. index e0c5fce8bccd..d8597027a93e 100644
  29. --- a/drivers/remoteproc/pru_rproc.c
  30. +++ b/drivers/remoteproc/pru_rproc.c
  31. @@ -266,12 +266,17 @@ static void pru_rproc_create_debug_entries(struct rproc *rproc)
  32. static void pru_dispose_irq_mapping(struct pru_rproc *pru)
  33. {
  34. - while (pru->evt_count--) {
  35. + if (!pru->mapped_irq)
  36. + return;
  37. +
  38. + while (pru->evt_count) {
  39. + pru->evt_count--;
  40. if (pru->mapped_irq[pru->evt_count] > 0)
  41. irq_dispose_mapping(pru->mapped_irq[pru->evt_count]);
  42. }
  43. kfree(pru->mapped_irq);
  44. + pru->mapped_irq = NULL;
  45. }
  46. /*
  47. @@ -307,8 +312,10 @@ static int pru_handle_intrmap(struct rproc *rproc)
  48. pru->evt_count = rsc->num_evts;
  49. pru->mapped_irq = kcalloc(pru->evt_count, sizeof(unsigned int),
  50. GFP_KERNEL);
  51. - if (!pru->mapped_irq)
  52. + if (!pru->mapped_irq) {
  53. + pru->evt_count = 0;
  54. return -ENOMEM;
  55. + }
  56. /*
  57. * parse and fill in system event to interrupt channel and
  58. @@ -317,13 +324,19 @@ static int pru_handle_intrmap(struct rproc *rproc)
  59. * corresponding sibling PRUSS INTC node.
  60. */
  61. parent = of_get_parent(dev_of_node(pru->dev));
  62. - if (!parent)
  63. + if (!parent) {
  64. + kfree(pru->mapped_irq);
  65. + pru->mapped_irq = NULL;
  66. + pru->evt_count = 0;
  67. return -ENODEV;
  68. + }
  69. irq_parent = of_get_child_by_name(parent, "interrupt-controller");
  70. of_node_put(parent);
  71. if (!irq_parent) {
  72. kfree(pru->mapped_irq);
  73. + pru->mapped_irq = NULL;
  74. + pru->evt_count = 0;
  75. return -ENODEV;
  76. }
  77. @@ -398,8 +411,7 @@ static int pru_rproc_stop(struct rproc *rproc)
  78. pru_control_write_reg(pru, PRU_CTRL_CTRL, val);
  79. /* dispose irq mapping - new firmware can provide new mapping */
  80. - if (pru->mapped_irq)
  81. - pru_dispose_irq_mapping(pru);
  82. + pru_dispose_irq_mapping(pru);
  83. return 0;
  84. }