950-0841-gpio_fsm-Rework-the-atomic-vs-non-atomic-split.patch 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. From f0061ffc98c6e027c5774e2a24ceadcfee4167ea Mon Sep 17 00:00:00 2001
  2. From: Phil Elwell <[email protected]>
  3. Date: Tue, 5 Sep 2023 12:01:13 +0100
  4. Subject: [PATCH] gpio_fsm: Rework the atomic-vs-non-atomic split
  5. Partition the code to separate atomic and non-atomic methods so that
  6. none of them have to handle both cases. The result avoids using deferred
  7. work unless necessary, and should be easier to understand.
  8. Signed-off-by: Phil Elwell <[email protected]>
  9. ---
  10. drivers/gpio/gpio-fsm.c | 84 ++++++++++++++++++++---------------------
  11. 1 file changed, 41 insertions(+), 43 deletions(-)
  12. --- a/drivers/gpio/gpio-fsm.c
  13. +++ b/drivers/gpio/gpio-fsm.c
  14. @@ -193,9 +193,6 @@ static void free_symbols(struct symtab_e
  15. }
  16. }
  17. -static void gpio_fsm_go_to_state(struct gpio_fsm *gf,
  18. - struct fsm_state *new_state);
  19. -
  20. static void gpio_fsm_set_soft(struct gpio_fsm *gf,
  21. unsigned int off, int val);
  22. @@ -213,6 +210,7 @@ static void gpio_fsm_enter_state(struct
  23. dev_dbg(gf->dev, "enter_state(%s)\n", state->name);
  24. gf->current_state = state;
  25. + gf->delay_target_state = NULL;
  26. // 1. Apply any listed signals
  27. for (i = 0; i < state->num_signals; i++) {
  28. @@ -271,7 +269,7 @@ static void gpio_fsm_enter_state(struct
  29. dev_info(gf->dev,
  30. "GF_SOFT %d=%d -> %s\n", event->index,
  31. event->value, event->target->name);
  32. - gpio_fsm_go_to_state(gf, event->target);
  33. + gpio_fsm_enter_state(gf, event->target);
  34. return;
  35. }
  36. }
  37. @@ -284,7 +282,7 @@ static void gpio_fsm_enter_state(struct
  38. inp_state->value = event->value;
  39. inp_state->enabled = true;
  40. - value = gpiod_get_value(gf->input_gpios->desc[event->index]);
  41. + value = gpiod_get_value_cansleep(gf->input_gpios->desc[event->index]);
  42. // Clear stale event state
  43. disable_irq(inp_state->irq);
  44. @@ -299,7 +297,7 @@ static void gpio_fsm_enter_state(struct
  45. dev_info(gf->dev,
  46. "GF_IN %d=%d -> %s\n", event->index,
  47. event->value, event->target->name);
  48. - gpio_fsm_go_to_state(gf, event->target);
  49. + gpio_fsm_enter_state(gf, event->target);
  50. return;
  51. }
  52. }
  53. @@ -325,6 +323,33 @@ static void gpio_fsm_go_to_state(struct
  54. dev_dbg(gf->dev, "go_to_state(%s)\n",
  55. new_state ? new_state->name : "<unset>");
  56. + state = gf->current_state;
  57. +
  58. + /* Disable any enabled GPIO IRQs */
  59. + for (i = 0; i < state->num_gpio_events; i++) {
  60. + gp_ev = &state->gpio_events[i];
  61. + inp_state = &gf->input_gpio_states[gp_ev->index];
  62. + if (inp_state->enabled) {
  63. + inp_state->enabled = false;
  64. + irq_set_irq_type(inp_state->irq,
  65. + IRQF_TRIGGER_NONE);
  66. + }
  67. + }
  68. +
  69. + gpio_fsm_enter_state(gf, new_state);
  70. +}
  71. +
  72. +static void gpio_fsm_go_to_state_deferred(struct gpio_fsm *gf,
  73. + struct fsm_state *new_state)
  74. +{
  75. + struct input_gpio_state *inp_state;
  76. + struct gpio_event *gp_ev;
  77. + struct fsm_state *state;
  78. + int i;
  79. +
  80. + dev_dbg(gf->dev, "go_to_state_deferred(%s)\n",
  81. + new_state ? new_state->name : "<unset>");
  82. +
  83. spin_lock(&gf->spinlock);
  84. if (gf->next_state) {
  85. @@ -335,57 +360,31 @@ static void gpio_fsm_go_to_state(struct
  86. gf->next_state = new_state;
  87. state = gf->current_state;
  88. - gf->delay_target_state = NULL;
  89. - if (state) {
  90. - /* Disarm any GPIO IRQs */
  91. - for (i = 0; i < state->num_gpio_events; i++) {
  92. - gp_ev = &state->gpio_events[i];
  93. - inp_state = &gf->input_gpio_states[gp_ev->index];
  94. - inp_state->target = NULL;
  95. - }
  96. + /* Disarm any GPIO IRQs */
  97. + for (i = 0; i < state->num_gpio_events; i++) {
  98. + gp_ev = &state->gpio_events[i];
  99. + inp_state = &gf->input_gpio_states[gp_ev->index];
  100. + inp_state->target = NULL;
  101. }
  102. spin_unlock(&gf->spinlock);
  103. - if (new_state)
  104. - schedule_work(&gf->work);
  105. + schedule_work(&gf->work);
  106. }
  107. static void gpio_fsm_work(struct work_struct *work)
  108. {
  109. - struct input_gpio_state *inp_state;
  110. struct fsm_state *new_state;
  111. - struct fsm_state *state;
  112. - struct gpio_event *gp_ev;
  113. struct gpio_fsm *gf;
  114. - int i;
  115. gf = container_of(work, struct gpio_fsm, work);
  116. spin_lock(&gf->spinlock);
  117. - state = gf->current_state;
  118. new_state = gf->next_state;
  119. - if (!new_state)
  120. - new_state = gf->delay_target_state;
  121. gf->next_state = NULL;
  122. - gf->delay_target_state = NULL;
  123. spin_unlock(&gf->spinlock);
  124. - if (state) {
  125. - /* Disable any enabled GPIO IRQs */
  126. - for (i = 0; i < state->num_gpio_events; i++) {
  127. - gp_ev = &state->gpio_events[i];
  128. - inp_state = &gf->input_gpio_states[gp_ev->index];
  129. - if (inp_state->enabled) {
  130. - inp_state->enabled = false;
  131. - irq_set_irq_type(inp_state->irq,
  132. - IRQF_TRIGGER_NONE);
  133. - }
  134. - }
  135. - }
  136. -
  137. - if (new_state)
  138. - gpio_fsm_enter_state(gf, new_state);
  139. + gpio_fsm_go_to_state(gf, new_state);
  140. }
  141. static irqreturn_t gpio_fsm_gpio_irq_handler(int irq, void *dev_id)
  142. @@ -404,7 +403,7 @@ static irqreturn_t gpio_fsm_gpio_irq_han
  143. if (gf->debug)
  144. dev_info(gf->dev, "GF_IN %d->%d -> %s\n",
  145. inp_state->index, inp_state->value, target->name);
  146. - gpio_fsm_go_to_state(gf, target);
  147. + gpio_fsm_go_to_state_deferred(gf, target);
  148. return IRQ_HANDLED;
  149. }
  150. @@ -416,12 +415,11 @@ static void gpio_fsm_timer(struct timer_
  151. target = gf->delay_target_state;
  152. if (!target)
  153. return;
  154. -
  155. if (gf->debug)
  156. dev_info(gf->dev, "GF_DELAY %d -> %s\n", gf->delay_ms,
  157. target->name);
  158. - gpio_fsm_go_to_state(gf, target);
  159. + gpio_fsm_go_to_state_deferred(gf, target);
  160. }
  161. int gpio_fsm_parse_signals(struct gpio_fsm *gf, struct fsm_state *state,
  162. @@ -1119,7 +1117,7 @@ static int gpio_fsm_probe(struct platfor
  163. if (gf->debug)
  164. dev_info(gf->dev, "Start -> %s\n", gf->start_state->name);
  165. - gpio_fsm_go_to_state(gf, gf->start_state);
  166. + gpio_fsm_enter_state(gf, gf->start_state);
  167. return devm_gpiochip_add_data(dev, &gf->gc, gf);
  168. }