diff options
author | Dipen Patel <dipenp@nvidia.com> | 2020-02-24 15:15:53 -0500 |
---|---|---|
committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2020-03-02 23:24:35 -0500 |
commit | 59e15cde9f7bb5b8d824295059d42f41e009a420 (patch) | |
tree | 1a40a733685ea1f40a4b25dd6cae1ede38ba4049 /drivers | |
parent | 00211a27a09795f7b255901025e85112ca14355e (diff) |
drivers: staging: gte_test: Unwind and other issues
There are bugs in test driver as follows:
1) gpio unwind is not done during init
2) No guard against re-registering event, for example, if user issues
echo 1 > gpio_en_dis, it will overwrite existing event descriptor
Also, it has other issues as below:
1) print debug messages correction in init
2) No print messages when timestamp is not available
3) Kconfig has extra blank lines
This CL addresses all above issue.
Bug 2865212
Change-Id: I66f4bd377c4d3557b46ab5828dabad4ee8394454
Signed-off-by: Dipen Patel <dipenp@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2302019
Reviewed-by: Stephen Warren <swarren@nvidia.com>
Reviewed-by: Winnie Hsu <whsu@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
GVS: Gerrit_Virtual_Submit
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/staging/platform/tegra/gte_test/Kconfig | 3 | ||||
-rw-r--r-- | drivers/staging/platform/tegra/gte_test/tegra194_gte_test.c | 76 |
2 files changed, 64 insertions, 15 deletions
diff --git a/drivers/staging/platform/tegra/gte_test/Kconfig b/drivers/staging/platform/tegra/gte_test/Kconfig index 7b4fbf1d2..5130e1638 100644 --- a/drivers/staging/platform/tegra/gte_test/Kconfig +++ b/drivers/staging/platform/tegra/gte_test/Kconfig | |||
@@ -4,5 +4,4 @@ config TEGRA_GTE_TEST | |||
4 | help | 4 | help |
5 | Enable this option for integrated generic timestamping support on | 5 | Enable this option for integrated generic timestamping support on |
6 | NVIDIA Tegra systems-on-chip. The driver supports LIC IRQs and AON | 6 | NVIDIA Tegra systems-on-chip. The driver supports LIC IRQs and AON |
7 | GPIO monitoring for hardware timestamping. | 7 | GPIO monitoring for hardware timestamping. \ No newline at end of file |
8 | |||
diff --git a/drivers/staging/platform/tegra/gte_test/tegra194_gte_test.c b/drivers/staging/platform/tegra/gte_test/tegra194_gte_test.c index bea0df14c..2311aa143 100644 --- a/drivers/staging/platform/tegra/gte_test/tegra194_gte_test.c +++ b/drivers/staging/platform/tegra/gte_test/tegra194_gte_test.c | |||
@@ -83,17 +83,34 @@ static ssize_t store_gpio_en_dis(struct kobject *kobj, | |||
83 | } | 83 | } |
84 | 84 | ||
85 | if (val == 1) { | 85 | if (val == 1) { |
86 | if (gte.data_gpio) { | ||
87 | pr_info("gpio_in is already registered\n"); | ||
88 | ret = -EEXIST; | ||
89 | goto error; | ||
90 | } | ||
86 | gte.data_gpio = tegra_gte_register_event(np, gpio_in); | 91 | gte.data_gpio = tegra_gte_register_event(np, gpio_in); |
87 | if (IS_ERR(gte.data_gpio)) { | 92 | if (IS_ERR(gte.data_gpio)) { |
88 | pr_err("Could not register gpio\n"); | 93 | pr_err("Could not register gpio\n"); |
89 | ret = -EINVAL; | 94 | ret = PTR_ERR(gte.data_gpio); |
95 | gte.data_gpio = NULL; | ||
90 | goto error; | 96 | goto error; |
91 | } | 97 | } |
92 | } else if (val == 0) { | 98 | } else if (val == 0) { |
93 | if (tegra_gte_unregister_event(gte.data_gpio) != 0) { | 99 | if (!gte.data_gpio) { |
100 | pr_info("gpio_in is not registered\n"); | ||
94 | ret = -EINVAL; | 101 | ret = -EINVAL; |
95 | goto error; | 102 | goto error; |
96 | } | 103 | } |
104 | ret = tegra_gte_unregister_event(gte.data_gpio); | ||
105 | if (ret == -EBUSY) { | ||
106 | /* User should retry */ | ||
107 | pr_err("failed to unregister gpio in\n"); | ||
108 | goto error; | ||
109 | } else { /* For anything else set data to null */ | ||
110 | gte.data_gpio = NULL; | ||
111 | if (ret == 0) | ||
112 | ret = count; | ||
113 | } | ||
97 | } else { | 114 | } else { |
98 | ret = -EINVAL; | 115 | ret = -EINVAL; |
99 | } | 116 | } |
@@ -126,17 +143,34 @@ static ssize_t store_lic_irq_en_dis(struct kobject *kobj, | |||
126 | } | 143 | } |
127 | 144 | ||
128 | if (val == 1) { | 145 | if (val == 1) { |
146 | if (gte.data_lic) { | ||
147 | pr_info("lic_irq is already registered\n"); | ||
148 | ret = -EEXIST; | ||
149 | goto error; | ||
150 | } | ||
129 | gte.data_lic = tegra_gte_register_event(np, lic_irq); | 151 | gte.data_lic = tegra_gte_register_event(np, lic_irq); |
130 | if (IS_ERR(gte.data_lic)) { | 152 | if (IS_ERR(gte.data_lic)) { |
131 | pr_err("Could not register lic irq\n"); | 153 | pr_err("Could not register lic irq\n"); |
132 | ret = -EINVAL; | 154 | ret = PTR_ERR(gte.data_lic); |
155 | gte.data_lic = NULL; | ||
133 | goto error; | 156 | goto error; |
134 | } | 157 | } |
135 | } else if (val == 0) { | 158 | } else if (val == 0) { |
136 | if (tegra_gte_unregister_event(gte.data_lic) != 0) { | 159 | if (!gte.data_lic) { |
160 | pr_info("lic_irq is not registered\n"); | ||
137 | ret = -EINVAL; | 161 | ret = -EINVAL; |
138 | goto error; | 162 | goto error; |
139 | } | 163 | } |
164 | ret = tegra_gte_unregister_event(gte.data_lic); | ||
165 | if (ret == -EBUSY) { | ||
166 | /* User should retry */ | ||
167 | pr_err("failed to unregister lic irq\n"); | ||
168 | goto error; | ||
169 | } else { /* For anything else set data to null */ | ||
170 | gte.data_lic = NULL; | ||
171 | if (ret == 0) | ||
172 | ret = count; | ||
173 | } | ||
140 | } else { | 174 | } else { |
141 | ret = -EINVAL; | 175 | ret = -EINVAL; |
142 | } | 176 | } |
@@ -206,8 +240,10 @@ static irqreturn_t tegra_gte_test_gpio_isr(int irq, void *data) | |||
206 | struct tegra_gte_ev_detail hts; | 240 | struct tegra_gte_ev_detail hts; |
207 | struct tegra_gte_test *gte = data; | 241 | struct tegra_gte_test *gte = data; |
208 | 242 | ||
209 | if (tegra_gte_retrieve_event((gte->data_gpio), &hts) != 0) | 243 | if (tegra_gte_retrieve_event((gte->data_gpio), &hts) != 0) { |
244 | pr_info("No timestamp available\n"); | ||
210 | return IRQ_HANDLED; | 245 | return IRQ_HANDLED; |
246 | } | ||
211 | 247 | ||
212 | pr_info("GPIO HW Timestamp: raw %llu, ns %llu\n", | 248 | pr_info("GPIO HW Timestamp: raw %llu, ns %llu\n", |
213 | hts.ts_raw, hts.ts_ns); | 249 | hts.ts_raw, hts.ts_ns); |
@@ -219,10 +255,13 @@ static int __init tegra_gte_test_init(void) | |||
219 | int ret = 0; | 255 | int ret = 0; |
220 | 256 | ||
221 | if (gpio_out == -EINVAL || gpio_in == -EINVAL || lic_irq == EINVAL) { | 257 | if (gpio_out == -EINVAL || gpio_in == -EINVAL || lic_irq == EINVAL) { |
222 | pr_err("Invalid gpio_out, gpio_in, gpiochip_base and irq\n"); | 258 | pr_err("Invalid gpio_out, gpio_in and irq\n"); |
223 | return -EINVAL; | 259 | return -EINVAL; |
224 | } | 260 | } |
225 | 261 | ||
262 | gte.data_lic = NULL; | ||
263 | gte.data_gpio = NULL; | ||
264 | |||
226 | ret = gpio_request(gpio_out, "gte_test_gpio_out"); | 265 | ret = gpio_request(gpio_out, "gte_test_gpio_out"); |
227 | if (ret) { | 266 | if (ret) { |
228 | pr_err("failed request gpio out\n"); | 267 | pr_err("failed request gpio out\n"); |
@@ -232,26 +271,31 @@ static int __init tegra_gte_test_init(void) | |||
232 | ret = gpio_direction_output(gpio_out, 0); | 271 | ret = gpio_direction_output(gpio_out, 0); |
233 | if (ret) { | 272 | if (ret) { |
234 | pr_err("failed to set pin direction\n"); | 273 | pr_err("failed to set pin direction\n"); |
235 | return -EINVAL; | 274 | ret = -EINVAL; |
275 | goto free_gpio_out; | ||
236 | } | 276 | } |
237 | 277 | ||
238 | ret = gpio_request(gpio_in, "gte_test_gpio_in"); | 278 | ret = gpio_request(gpio_in, "gte_test_gpio_in"); |
239 | if (ret) { | 279 | if (ret) { |
240 | pr_err("failed to request gpio in\n"); | 280 | pr_err("failed to request gpio in\n"); |
241 | return -EINVAL; | 281 | ret = -EINVAL; |
282 | goto free_gpio_out; | ||
242 | } | 283 | } |
243 | 284 | ||
244 | ret = gpio_direction_input(gpio_in); | 285 | ret = gpio_direction_input(gpio_in); |
245 | if (ret) { | 286 | if (ret) { |
246 | pr_err("failed to set pin direction\n"); | 287 | pr_err("failed to set pin direction\n"); |
247 | return -EINVAL; | 288 | ret = -EINVAL; |
289 | goto free_gpio_in; | ||
290 | |||
248 | } | 291 | } |
249 | 292 | ||
250 | /* IRQ setup */ | 293 | /* IRQ setup */ |
251 | ret = gpio_to_irq(gpio_in); | 294 | ret = gpio_to_irq(gpio_in); |
252 | if (ret < 0) { | 295 | if (ret < 0) { |
253 | pr_err("failed to map GPIO to IRQ: %d\n", ret); | 296 | pr_err("failed to map GPIO to IRQ: %d\n", ret); |
254 | return -EINVAL; | 297 | ret = -EINVAL; |
298 | goto free_gpio_in; | ||
255 | } | 299 | } |
256 | 300 | ||
257 | gte.gpio_in_irq = ret; | 301 | gte.gpio_in_irq = ret; |
@@ -261,14 +305,15 @@ static int __init tegra_gte_test_init(void) | |||
261 | "tegra_gte_test_isr", >e); | 305 | "tegra_gte_test_isr", >e); |
262 | if (ret) { | 306 | if (ret) { |
263 | pr_err("failed to acquire IRQ\n"); | 307 | pr_err("failed to acquire IRQ\n"); |
264 | return ret; | 308 | ret = -EINVAL; |
309 | goto free_gpio_in; | ||
265 | } | 310 | } |
266 | 311 | ||
267 | ret = tegra_gte_test_sysfs_create(); | 312 | ret = tegra_gte_test_sysfs_create(); |
268 | if (ret != 0) { | 313 | if (ret != 0) { |
269 | pr_err("sysfs creation failed\n"); | 314 | pr_err("sysfs creation failed\n"); |
270 | ret = -EINVAL; | 315 | ret = -EINVAL; |
271 | goto error; | 316 | goto free_irq; |
272 | } | 317 | } |
273 | 318 | ||
274 | setup_timer(>e.timer, gpio_timer_cb, 0); | 319 | setup_timer(>e.timer, gpio_timer_cb, 0); |
@@ -276,8 +321,13 @@ static int __init tegra_gte_test_init(void) | |||
276 | 321 | ||
277 | return 0; | 322 | return 0; |
278 | 323 | ||
279 | error: | 324 | free_irq: |
280 | free_irq(gte.gpio_in_irq, >e); | 325 | free_irq(gte.gpio_in_irq, >e); |
326 | free_gpio_in: | ||
327 | gpio_free(gpio_in); | ||
328 | free_gpio_out: | ||
329 | gpio_free(gpio_out); | ||
330 | |||
281 | return ret; | 331 | return ret; |
282 | } | 332 | } |
283 | 333 | ||