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