diff options
author | Jonathan Cameron <jic23@kernel.org> | 2012-04-25 10:54:59 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-04-25 14:11:38 -0400 |
commit | a980e046098b0a40eaff5e4e7fcde6cf035b7c06 (patch) | |
tree | 23375fc2bba39f088974cf621f7abf006d43d087 /drivers/iio/industrialio-trigger.c | |
parent | 06458e277eac2b8761b0a04d3c808d57be281a2e (diff) |
IIO: Move the core files to drivers/iio
Take the core support + the kfifo buffer implentation out of
staging. Whilst we are far from done in improving this subsystem
it is now at a stage where the userspae interfaces (provided by
the core) can be considered stable.
Drivers will follow over a longer time scale.
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/iio/industrialio-trigger.c')
-rw-r--r-- | drivers/iio/industrialio-trigger.c | 509 |
1 files changed, 509 insertions, 0 deletions
diff --git a/drivers/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c new file mode 100644 index 000000000000..03fee2e097ca --- /dev/null +++ b/drivers/iio/industrialio-trigger.c | |||
@@ -0,0 +1,509 @@ | |||
1 | /* The industrial I/O core, trigger handling functions | ||
2 | * | ||
3 | * Copyright (c) 2008 Jonathan Cameron | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License version 2 as published by | ||
7 | * the Free Software Foundation. | ||
8 | */ | ||
9 | |||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/idr.h> | ||
12 | #include <linux/err.h> | ||
13 | #include <linux/device.h> | ||
14 | #include <linux/interrupt.h> | ||
15 | #include <linux/list.h> | ||
16 | #include <linux/slab.h> | ||
17 | |||
18 | #include <linux/iio/iio.h> | ||
19 | #include <linux/iio/trigger.h> | ||
20 | #include "iio_core.h" | ||
21 | #include "iio_core_trigger.h" | ||
22 | #include <linux/iio/trigger_consumer.h> | ||
23 | |||
24 | /* RFC - Question of approach | ||
25 | * Make the common case (single sensor single trigger) | ||
26 | * simple by starting trigger capture from when first sensors | ||
27 | * is added. | ||
28 | * | ||
29 | * Complex simultaneous start requires use of 'hold' functionality | ||
30 | * of the trigger. (not implemented) | ||
31 | * | ||
32 | * Any other suggestions? | ||
33 | */ | ||
34 | |||
35 | static DEFINE_IDA(iio_trigger_ida); | ||
36 | |||
37 | /* Single list of all available triggers */ | ||
38 | static LIST_HEAD(iio_trigger_list); | ||
39 | static DEFINE_MUTEX(iio_trigger_list_lock); | ||
40 | |||
41 | /** | ||
42 | * iio_trigger_read_name() - retrieve useful identifying name | ||
43 | **/ | ||
44 | static ssize_t iio_trigger_read_name(struct device *dev, | ||
45 | struct device_attribute *attr, | ||
46 | char *buf) | ||
47 | { | ||
48 | struct iio_trigger *trig = dev_get_drvdata(dev); | ||
49 | return sprintf(buf, "%s\n", trig->name); | ||
50 | } | ||
51 | |||
52 | static DEVICE_ATTR(name, S_IRUGO, iio_trigger_read_name, NULL); | ||
53 | |||
54 | /** | ||
55 | * iio_trigger_register_sysfs() - create a device for this trigger | ||
56 | * @trig_info: the trigger | ||
57 | * | ||
58 | * Also adds any control attribute registered by the trigger driver | ||
59 | **/ | ||
60 | static int iio_trigger_register_sysfs(struct iio_trigger *trig_info) | ||
61 | { | ||
62 | return sysfs_add_file_to_group(&trig_info->dev.kobj, | ||
63 | &dev_attr_name.attr, | ||
64 | NULL); | ||
65 | } | ||
66 | |||
67 | static void iio_trigger_unregister_sysfs(struct iio_trigger *trig_info) | ||
68 | { | ||
69 | sysfs_remove_file_from_group(&trig_info->dev.kobj, | ||
70 | &dev_attr_name.attr, | ||
71 | NULL); | ||
72 | } | ||
73 | |||
74 | int iio_trigger_register(struct iio_trigger *trig_info) | ||
75 | { | ||
76 | int ret; | ||
77 | |||
78 | trig_info->id = ida_simple_get(&iio_trigger_ida, 0, 0, GFP_KERNEL); | ||
79 | if (trig_info->id < 0) { | ||
80 | ret = trig_info->id; | ||
81 | goto error_ret; | ||
82 | } | ||
83 | /* Set the name used for the sysfs directory etc */ | ||
84 | dev_set_name(&trig_info->dev, "trigger%ld", | ||
85 | (unsigned long) trig_info->id); | ||
86 | |||
87 | ret = device_add(&trig_info->dev); | ||
88 | if (ret) | ||
89 | goto error_unregister_id; | ||
90 | |||
91 | ret = iio_trigger_register_sysfs(trig_info); | ||
92 | if (ret) | ||
93 | goto error_device_del; | ||
94 | |||
95 | /* Add to list of available triggers held by the IIO core */ | ||
96 | mutex_lock(&iio_trigger_list_lock); | ||
97 | list_add_tail(&trig_info->list, &iio_trigger_list); | ||
98 | mutex_unlock(&iio_trigger_list_lock); | ||
99 | |||
100 | return 0; | ||
101 | |||
102 | error_device_del: | ||
103 | device_del(&trig_info->dev); | ||
104 | error_unregister_id: | ||
105 | ida_simple_remove(&iio_trigger_ida, trig_info->id); | ||
106 | error_ret: | ||
107 | return ret; | ||
108 | } | ||
109 | EXPORT_SYMBOL(iio_trigger_register); | ||
110 | |||
111 | void iio_trigger_unregister(struct iio_trigger *trig_info) | ||
112 | { | ||
113 | mutex_lock(&iio_trigger_list_lock); | ||
114 | list_del(&trig_info->list); | ||
115 | mutex_unlock(&iio_trigger_list_lock); | ||
116 | |||
117 | iio_trigger_unregister_sysfs(trig_info); | ||
118 | ida_simple_remove(&iio_trigger_ida, trig_info->id); | ||
119 | /* Possible issue in here */ | ||
120 | device_unregister(&trig_info->dev); | ||
121 | } | ||
122 | EXPORT_SYMBOL(iio_trigger_unregister); | ||
123 | |||
124 | static struct iio_trigger *iio_trigger_find_by_name(const char *name, | ||
125 | size_t len) | ||
126 | { | ||
127 | struct iio_trigger *trig = NULL, *iter; | ||
128 | |||
129 | mutex_lock(&iio_trigger_list_lock); | ||
130 | list_for_each_entry(iter, &iio_trigger_list, list) | ||
131 | if (sysfs_streq(iter->name, name)) { | ||
132 | trig = iter; | ||
133 | break; | ||
134 | } | ||
135 | mutex_unlock(&iio_trigger_list_lock); | ||
136 | |||
137 | return trig; | ||
138 | } | ||
139 | |||
140 | void iio_trigger_poll(struct iio_trigger *trig, s64 time) | ||
141 | { | ||
142 | int i; | ||
143 | if (!trig->use_count) | ||
144 | for (i = 0; i < CONFIG_IIO_CONSUMERS_PER_TRIGGER; i++) | ||
145 | if (trig->subirqs[i].enabled) { | ||
146 | trig->use_count++; | ||
147 | generic_handle_irq(trig->subirq_base + i); | ||
148 | } | ||
149 | } | ||
150 | EXPORT_SYMBOL(iio_trigger_poll); | ||
151 | |||
152 | irqreturn_t iio_trigger_generic_data_rdy_poll(int irq, void *private) | ||
153 | { | ||
154 | iio_trigger_poll(private, iio_get_time_ns()); | ||
155 | return IRQ_HANDLED; | ||
156 | } | ||
157 | EXPORT_SYMBOL(iio_trigger_generic_data_rdy_poll); | ||
158 | |||
159 | void iio_trigger_poll_chained(struct iio_trigger *trig, s64 time) | ||
160 | { | ||
161 | int i; | ||
162 | if (!trig->use_count) | ||
163 | for (i = 0; i < CONFIG_IIO_CONSUMERS_PER_TRIGGER; i++) | ||
164 | if (trig->subirqs[i].enabled) { | ||
165 | trig->use_count++; | ||
166 | handle_nested_irq(trig->subirq_base + i); | ||
167 | } | ||
168 | } | ||
169 | EXPORT_SYMBOL(iio_trigger_poll_chained); | ||
170 | |||
171 | void iio_trigger_notify_done(struct iio_trigger *trig) | ||
172 | { | ||
173 | trig->use_count--; | ||
174 | if (trig->use_count == 0 && trig->ops && trig->ops->try_reenable) | ||
175 | if (trig->ops->try_reenable(trig)) | ||
176 | /* Missed and interrupt so launch new poll now */ | ||
177 | iio_trigger_poll(trig, 0); | ||
178 | } | ||
179 | EXPORT_SYMBOL(iio_trigger_notify_done); | ||
180 | |||
181 | /* Trigger Consumer related functions */ | ||
182 | static int iio_trigger_get_irq(struct iio_trigger *trig) | ||
183 | { | ||
184 | int ret; | ||
185 | mutex_lock(&trig->pool_lock); | ||
186 | ret = bitmap_find_free_region(trig->pool, | ||
187 | CONFIG_IIO_CONSUMERS_PER_TRIGGER, | ||
188 | ilog2(1)); | ||
189 | mutex_unlock(&trig->pool_lock); | ||
190 | if (ret >= 0) | ||
191 | ret += trig->subirq_base; | ||
192 | |||
193 | return ret; | ||
194 | } | ||
195 | |||
196 | static void iio_trigger_put_irq(struct iio_trigger *trig, int irq) | ||
197 | { | ||
198 | mutex_lock(&trig->pool_lock); | ||
199 | clear_bit(irq - trig->subirq_base, trig->pool); | ||
200 | mutex_unlock(&trig->pool_lock); | ||
201 | } | ||
202 | |||
203 | /* Complexity in here. With certain triggers (datardy) an acknowledgement | ||
204 | * may be needed if the pollfuncs do not include the data read for the | ||
205 | * triggering device. | ||
206 | * This is not currently handled. Alternative of not enabling trigger unless | ||
207 | * the relevant function is in there may be the best option. | ||
208 | */ | ||
209 | /* Worth protecting against double additions?*/ | ||
210 | static int iio_trigger_attach_poll_func(struct iio_trigger *trig, | ||
211 | struct iio_poll_func *pf) | ||
212 | { | ||
213 | int ret = 0; | ||
214 | bool notinuse | ||
215 | = bitmap_empty(trig->pool, CONFIG_IIO_CONSUMERS_PER_TRIGGER); | ||
216 | |||
217 | /* Prevent the module being removed whilst attached to a trigger */ | ||
218 | __module_get(pf->indio_dev->info->driver_module); | ||
219 | pf->irq = iio_trigger_get_irq(trig); | ||
220 | ret = request_threaded_irq(pf->irq, pf->h, pf->thread, | ||
221 | pf->type, pf->name, | ||
222 | pf); | ||
223 | if (ret < 0) { | ||
224 | module_put(pf->indio_dev->info->driver_module); | ||
225 | return ret; | ||
226 | } | ||
227 | |||
228 | if (trig->ops && trig->ops->set_trigger_state && notinuse) { | ||
229 | ret = trig->ops->set_trigger_state(trig, true); | ||
230 | if (ret < 0) | ||
231 | module_put(pf->indio_dev->info->driver_module); | ||
232 | } | ||
233 | |||
234 | return ret; | ||
235 | } | ||
236 | |||
237 | static int iio_trigger_dettach_poll_func(struct iio_trigger *trig, | ||
238 | struct iio_poll_func *pf) | ||
239 | { | ||
240 | int ret = 0; | ||
241 | bool no_other_users | ||
242 | = (bitmap_weight(trig->pool, | ||
243 | CONFIG_IIO_CONSUMERS_PER_TRIGGER) | ||
244 | == 1); | ||
245 | if (trig->ops && trig->ops->set_trigger_state && no_other_users) { | ||
246 | ret = trig->ops->set_trigger_state(trig, false); | ||
247 | if (ret) | ||
248 | goto error_ret; | ||
249 | } | ||
250 | iio_trigger_put_irq(trig, pf->irq); | ||
251 | free_irq(pf->irq, pf); | ||
252 | module_put(pf->indio_dev->info->driver_module); | ||
253 | |||
254 | error_ret: | ||
255 | return ret; | ||
256 | } | ||
257 | |||
258 | irqreturn_t iio_pollfunc_store_time(int irq, void *p) | ||
259 | { | ||
260 | struct iio_poll_func *pf = p; | ||
261 | pf->timestamp = iio_get_time_ns(); | ||
262 | return IRQ_WAKE_THREAD; | ||
263 | } | ||
264 | EXPORT_SYMBOL(iio_pollfunc_store_time); | ||
265 | |||
266 | struct iio_poll_func | ||
267 | *iio_alloc_pollfunc(irqreturn_t (*h)(int irq, void *p), | ||
268 | irqreturn_t (*thread)(int irq, void *p), | ||
269 | int type, | ||
270 | struct iio_dev *indio_dev, | ||
271 | const char *fmt, | ||
272 | ...) | ||
273 | { | ||
274 | va_list vargs; | ||
275 | struct iio_poll_func *pf; | ||
276 | |||
277 | pf = kmalloc(sizeof *pf, GFP_KERNEL); | ||
278 | if (pf == NULL) | ||
279 | return NULL; | ||
280 | va_start(vargs, fmt); | ||
281 | pf->name = kvasprintf(GFP_KERNEL, fmt, vargs); | ||
282 | va_end(vargs); | ||
283 | if (pf->name == NULL) { | ||
284 | kfree(pf); | ||
285 | return NULL; | ||
286 | } | ||
287 | pf->h = h; | ||
288 | pf->thread = thread; | ||
289 | pf->type = type; | ||
290 | pf->indio_dev = indio_dev; | ||
291 | |||
292 | return pf; | ||
293 | } | ||
294 | EXPORT_SYMBOL_GPL(iio_alloc_pollfunc); | ||
295 | |||
296 | void iio_dealloc_pollfunc(struct iio_poll_func *pf) | ||
297 | { | ||
298 | kfree(pf->name); | ||
299 | kfree(pf); | ||
300 | } | ||
301 | EXPORT_SYMBOL_GPL(iio_dealloc_pollfunc); | ||
302 | |||
303 | /** | ||
304 | * iio_trigger_read_current() - trigger consumer sysfs query which trigger | ||
305 | * | ||
306 | * For trigger consumers the current_trigger interface allows the trigger | ||
307 | * used by the device to be queried. | ||
308 | **/ | ||
309 | static ssize_t iio_trigger_read_current(struct device *dev, | ||
310 | struct device_attribute *attr, | ||
311 | char *buf) | ||
312 | { | ||
313 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
314 | |||
315 | if (indio_dev->trig) | ||
316 | return sprintf(buf, "%s\n", indio_dev->trig->name); | ||
317 | return 0; | ||
318 | } | ||
319 | |||
320 | /** | ||
321 | * iio_trigger_write_current() trigger consumer sysfs set current trigger | ||
322 | * | ||
323 | * For trigger consumers the current_trigger interface allows the trigger | ||
324 | * used for this device to be specified at run time based on the triggers | ||
325 | * name. | ||
326 | **/ | ||
327 | static ssize_t iio_trigger_write_current(struct device *dev, | ||
328 | struct device_attribute *attr, | ||
329 | const char *buf, | ||
330 | size_t len) | ||
331 | { | ||
332 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
333 | struct iio_trigger *oldtrig = indio_dev->trig; | ||
334 | struct iio_trigger *trig; | ||
335 | int ret; | ||
336 | |||
337 | mutex_lock(&indio_dev->mlock); | ||
338 | if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) { | ||
339 | mutex_unlock(&indio_dev->mlock); | ||
340 | return -EBUSY; | ||
341 | } | ||
342 | mutex_unlock(&indio_dev->mlock); | ||
343 | |||
344 | trig = iio_trigger_find_by_name(buf, len); | ||
345 | if (oldtrig == trig) | ||
346 | return len; | ||
347 | |||
348 | if (trig && indio_dev->info->validate_trigger) { | ||
349 | ret = indio_dev->info->validate_trigger(indio_dev, trig); | ||
350 | if (ret) | ||
351 | return ret; | ||
352 | } | ||
353 | |||
354 | if (trig && trig->ops && trig->ops->validate_device) { | ||
355 | ret = trig->ops->validate_device(trig, indio_dev); | ||
356 | if (ret) | ||
357 | return ret; | ||
358 | } | ||
359 | |||
360 | indio_dev->trig = trig; | ||
361 | |||
362 | if (oldtrig && indio_dev->trig != oldtrig) | ||
363 | iio_put_trigger(oldtrig); | ||
364 | if (indio_dev->trig) | ||
365 | iio_get_trigger(indio_dev->trig); | ||
366 | |||
367 | return len; | ||
368 | } | ||
369 | |||
370 | static DEVICE_ATTR(current_trigger, S_IRUGO | S_IWUSR, | ||
371 | iio_trigger_read_current, | ||
372 | iio_trigger_write_current); | ||
373 | |||
374 | static struct attribute *iio_trigger_consumer_attrs[] = { | ||
375 | &dev_attr_current_trigger.attr, | ||
376 | NULL, | ||
377 | }; | ||
378 | |||
379 | static const struct attribute_group iio_trigger_consumer_attr_group = { | ||
380 | .name = "trigger", | ||
381 | .attrs = iio_trigger_consumer_attrs, | ||
382 | }; | ||
383 | |||
384 | static void iio_trig_release(struct device *device) | ||
385 | { | ||
386 | struct iio_trigger *trig = to_iio_trigger(device); | ||
387 | int i; | ||
388 | |||
389 | if (trig->subirq_base) { | ||
390 | for (i = 0; i < CONFIG_IIO_CONSUMERS_PER_TRIGGER; i++) { | ||
391 | irq_modify_status(trig->subirq_base + i, | ||
392 | IRQ_NOAUTOEN, | ||
393 | IRQ_NOREQUEST | IRQ_NOPROBE); | ||
394 | irq_set_chip(trig->subirq_base + i, | ||
395 | NULL); | ||
396 | irq_set_handler(trig->subirq_base + i, | ||
397 | NULL); | ||
398 | } | ||
399 | |||
400 | irq_free_descs(trig->subirq_base, | ||
401 | CONFIG_IIO_CONSUMERS_PER_TRIGGER); | ||
402 | } | ||
403 | kfree(trig->name); | ||
404 | kfree(trig); | ||
405 | } | ||
406 | |||
407 | static struct device_type iio_trig_type = { | ||
408 | .release = iio_trig_release, | ||
409 | }; | ||
410 | |||
411 | static void iio_trig_subirqmask(struct irq_data *d) | ||
412 | { | ||
413 | struct irq_chip *chip = irq_data_get_irq_chip(d); | ||
414 | struct iio_trigger *trig | ||
415 | = container_of(chip, | ||
416 | struct iio_trigger, subirq_chip); | ||
417 | trig->subirqs[d->irq - trig->subirq_base].enabled = false; | ||
418 | } | ||
419 | |||
420 | static void iio_trig_subirqunmask(struct irq_data *d) | ||
421 | { | ||
422 | struct irq_chip *chip = irq_data_get_irq_chip(d); | ||
423 | struct iio_trigger *trig | ||
424 | = container_of(chip, | ||
425 | struct iio_trigger, subirq_chip); | ||
426 | trig->subirqs[d->irq - trig->subirq_base].enabled = true; | ||
427 | } | ||
428 | |||
429 | struct iio_trigger *iio_allocate_trigger(const char *fmt, ...) | ||
430 | { | ||
431 | va_list vargs; | ||
432 | struct iio_trigger *trig; | ||
433 | trig = kzalloc(sizeof *trig, GFP_KERNEL); | ||
434 | if (trig) { | ||
435 | int i; | ||
436 | trig->dev.type = &iio_trig_type; | ||
437 | trig->dev.bus = &iio_bus_type; | ||
438 | device_initialize(&trig->dev); | ||
439 | dev_set_drvdata(&trig->dev, (void *)trig); | ||
440 | |||
441 | mutex_init(&trig->pool_lock); | ||
442 | trig->subirq_base | ||
443 | = irq_alloc_descs(-1, 0, | ||
444 | CONFIG_IIO_CONSUMERS_PER_TRIGGER, | ||
445 | 0); | ||
446 | if (trig->subirq_base < 0) { | ||
447 | kfree(trig); | ||
448 | return NULL; | ||
449 | } | ||
450 | va_start(vargs, fmt); | ||
451 | trig->name = kvasprintf(GFP_KERNEL, fmt, vargs); | ||
452 | va_end(vargs); | ||
453 | if (trig->name == NULL) { | ||
454 | irq_free_descs(trig->subirq_base, | ||
455 | CONFIG_IIO_CONSUMERS_PER_TRIGGER); | ||
456 | kfree(trig); | ||
457 | return NULL; | ||
458 | } | ||
459 | trig->subirq_chip.name = trig->name; | ||
460 | trig->subirq_chip.irq_mask = &iio_trig_subirqmask; | ||
461 | trig->subirq_chip.irq_unmask = &iio_trig_subirqunmask; | ||
462 | for (i = 0; i < CONFIG_IIO_CONSUMERS_PER_TRIGGER; i++) { | ||
463 | irq_set_chip(trig->subirq_base + i, | ||
464 | &trig->subirq_chip); | ||
465 | irq_set_handler(trig->subirq_base + i, | ||
466 | &handle_simple_irq); | ||
467 | irq_modify_status(trig->subirq_base + i, | ||
468 | IRQ_NOREQUEST | IRQ_NOAUTOEN, | ||
469 | IRQ_NOPROBE); | ||
470 | } | ||
471 | get_device(&trig->dev); | ||
472 | } | ||
473 | return trig; | ||
474 | } | ||
475 | EXPORT_SYMBOL(iio_allocate_trigger); | ||
476 | |||
477 | void iio_free_trigger(struct iio_trigger *trig) | ||
478 | { | ||
479 | if (trig) | ||
480 | put_device(&trig->dev); | ||
481 | } | ||
482 | EXPORT_SYMBOL(iio_free_trigger); | ||
483 | |||
484 | void iio_device_register_trigger_consumer(struct iio_dev *indio_dev) | ||
485 | { | ||
486 | indio_dev->groups[indio_dev->groupcounter++] = | ||
487 | &iio_trigger_consumer_attr_group; | ||
488 | } | ||
489 | |||
490 | void iio_device_unregister_trigger_consumer(struct iio_dev *indio_dev) | ||
491 | { | ||
492 | /* Clean up and associated but not attached triggers references */ | ||
493 | if (indio_dev->trig) | ||
494 | iio_put_trigger(indio_dev->trig); | ||
495 | } | ||
496 | |||
497 | int iio_triggered_buffer_postenable(struct iio_dev *indio_dev) | ||
498 | { | ||
499 | return iio_trigger_attach_poll_func(indio_dev->trig, | ||
500 | indio_dev->pollfunc); | ||
501 | } | ||
502 | EXPORT_SYMBOL(iio_triggered_buffer_postenable); | ||
503 | |||
504 | int iio_triggered_buffer_predisable(struct iio_dev *indio_dev) | ||
505 | { | ||
506 | return iio_trigger_dettach_poll_func(indio_dev->trig, | ||
507 | indio_dev->pollfunc); | ||
508 | } | ||
509 | EXPORT_SYMBOL(iio_triggered_buffer_predisable); | ||