aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonathan Cameron <jic23@cam.ac.uk>2011-05-18 09:42:11 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2011-05-19 19:15:00 -0400
commit1f785681a87068f123d3e23da13b2c55ab4f93ac (patch)
tree885195dc260626faa37bd1fa8b766fb736b24c1c
parent586d15255dd529be94253b2d4bbb9f40ef680c1a (diff)
staging:iio:trigger sysfs userspace trigger rework.
Awaiting comments on using the nested_irq_trick so that may change. Moves away from platform device to sysfs controlled creation and removal of these triggers. Fix double free of name on trigger allocation failure thanks to Michael Hennerich. Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk> Reviewed-by: Michael Hennerich <michael.hennerich@analog.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/staging/iio/industrialio-trigger.c13
-rw-r--r--drivers/staging/iio/trigger.h1
-rw-r--r--drivers/staging/iio/trigger/iio-trig-sysfs.c170
3 files changed, 149 insertions, 35 deletions
diff --git a/drivers/staging/iio/industrialio-trigger.c b/drivers/staging/iio/industrialio-trigger.c
index dd762f053850..86d026b2ec31 100644
--- a/drivers/staging/iio/industrialio-trigger.c
+++ b/drivers/staging/iio/industrialio-trigger.c
@@ -181,6 +181,19 @@ irqreturn_t iio_trigger_generic_data_rdy_poll(int irq, void *private)
181} 181}
182EXPORT_SYMBOL(iio_trigger_generic_data_rdy_poll); 182EXPORT_SYMBOL(iio_trigger_generic_data_rdy_poll);
183 183
184void iio_trigger_poll_chained(struct iio_trigger *trig, s64 time)
185{
186 int i;
187 if (!trig->use_count) {
188 for (i = 0; i < CONFIG_IIO_CONSUMERS_PER_TRIGGER; i++)
189 if (trig->subirqs[i].enabled) {
190 trig->use_count++;
191 handle_nested_irq(trig->subirq_base + i);
192 }
193 }
194}
195EXPORT_SYMBOL(iio_trigger_poll_chained);
196
184void iio_trigger_notify_done(struct iio_trigger *trig) 197void iio_trigger_notify_done(struct iio_trigger *trig)
185{ 198{
186 trig->use_count--; 199 trig->use_count--;
diff --git a/drivers/staging/iio/trigger.h b/drivers/staging/iio/trigger.h
index e831a8925782..5efa0d50b720 100644
--- a/drivers/staging/iio/trigger.h
+++ b/drivers/staging/iio/trigger.h
@@ -121,6 +121,7 @@ int iio_trigger_dettach_poll_func(struct iio_trigger *trig,
121 * Typically called in relevant hardware interrupt handler. 121 * Typically called in relevant hardware interrupt handler.
122 **/ 122 **/
123void iio_trigger_poll(struct iio_trigger *trig, s64 time); 123void iio_trigger_poll(struct iio_trigger *trig, s64 time);
124void iio_trigger_poll_chained(struct iio_trigger *trig, s64 time);
124void iio_trigger_notify_done(struct iio_trigger *trig); 125void iio_trigger_notify_done(struct iio_trigger *trig);
125 126
126irqreturn_t iio_trigger_generic_data_rdy_poll(int irq, void *private); 127irqreturn_t iio_trigger_generic_data_rdy_poll(int irq, void *private);
diff --git a/drivers/staging/iio/trigger/iio-trig-sysfs.c b/drivers/staging/iio/trigger/iio-trig-sysfs.c
index 127a2a33e4db..6d3dee3fdba8 100644
--- a/drivers/staging/iio/trigger/iio-trig-sysfs.c
+++ b/drivers/staging/iio/trigger/iio-trig-sysfs.c
@@ -9,15 +9,84 @@
9#include <linux/module.h> 9#include <linux/module.h>
10#include <linux/platform_device.h> 10#include <linux/platform_device.h>
11#include <linux/slab.h> 11#include <linux/slab.h>
12#include <linux/list.h>
12 13
13#include "../iio.h" 14#include "../iio.h"
14#include "../trigger.h" 15#include "../trigger.h"
15 16
17struct iio_sysfs_trig {
18 struct iio_trigger *trig;
19 int id;
20 struct list_head l;
21};
22
23static LIST_HEAD(iio_sysfs_trig_list);
24static DEFINE_MUTEX(iio_syfs_trig_list_mut);
25
26static int iio_sysfs_trigger_probe(int id);
27static ssize_t iio_sysfs_trig_add(struct device *dev,
28 struct device_attribute *attr,
29 const char *buf,
30 size_t len)
31{
32 int ret;
33 unsigned long input;
34
35 ret = strict_strtoul(buf, 10, &input);
36 if (ret)
37 return ret;
38 ret = iio_sysfs_trigger_probe(input);
39 if (ret)
40 return ret;
41 return len;
42}
43static DEVICE_ATTR(add_trigger, S_IWUSR, NULL, &iio_sysfs_trig_add);
44
45static int iio_sysfs_trigger_remove(int id);
46static ssize_t iio_sysfs_trig_remove(struct device *dev,
47 struct device_attribute *attr,
48 const char *buf,
49 size_t len)
50{
51 int ret;
52 unsigned long input;
53
54 ret = strict_strtoul(buf, 10, &input);
55 if (ret)
56 return ret;
57 ret = iio_sysfs_trigger_remove(input);
58 if (ret)
59 return ret;
60 return len;
61}
62
63static DEVICE_ATTR(remove_trigger, S_IWUSR, NULL, &iio_sysfs_trig_remove);
64
65static struct attribute *iio_sysfs_trig_attrs[] = {
66 &dev_attr_add_trigger.attr,
67 &dev_attr_remove_trigger.attr,
68 NULL,
69};
70
71static const struct attribute_group iio_sysfs_trig_group = {
72 .attrs = iio_sysfs_trig_attrs,
73};
74
75static const struct attribute_group *iio_sysfs_trig_groups[] = {
76 &iio_sysfs_trig_group,
77 NULL
78};
79
80static struct device iio_sysfs_trig_dev = {
81 .bus = &iio_bus_type,
82 .groups = iio_sysfs_trig_groups,
83};
84
16static ssize_t iio_sysfs_trigger_poll(struct device *dev, 85static ssize_t iio_sysfs_trigger_poll(struct device *dev,
17 struct device_attribute *attr, const char *buf, size_t count) 86 struct device_attribute *attr, const char *buf, size_t count)
18{ 87{
19 struct iio_trigger *trig = dev_get_drvdata(dev); 88 struct iio_trigger *trig = dev_get_drvdata(dev);
20 iio_trigger_poll(trig, 0); 89 iio_trigger_poll_chained(trig, 0);
21 90
22 return count; 91 return count;
23} 92}
@@ -35,70 +104,101 @@ static const struct attribute_group iio_sysfs_trigger_attr_group = {
35 .attrs = iio_sysfs_trigger_attrs, 104 .attrs = iio_sysfs_trigger_attrs,
36}; 105};
37 106
38static int __devinit iio_sysfs_trigger_probe(struct platform_device *pdev) 107static int iio_sysfs_trigger_probe(int id)
39{ 108{
40 struct iio_trigger *trig; 109 struct iio_sysfs_trig *t;
41 int ret; 110 int ret;
111 char *name;
112 bool foundit = false;
113 mutex_lock(&iio_syfs_trig_list_mut);
114 list_for_each_entry(t, &iio_sysfs_trig_list, l)
115 if (id == t->id) {
116 foundit = true;
117 break;
118 }
119 if (foundit) {
120 ret = -EINVAL;
121 goto out1;
122 }
42 123
43 trig = iio_allocate_trigger(); 124 name = kasprintf(GFP_KERNEL, "sysfstrig%d", id);
44 if (!trig) { 125 if (name == NULL) {
45 ret = -ENOMEM; 126 ret = -ENOMEM;
46 goto out1; 127 goto out1;
47 } 128 }
48 129 t = kmalloc(sizeof(*t), GFP_KERNEL);
49 trig->control_attrs = &iio_sysfs_trigger_attr_group; 130 if (t == NULL) {
50 trig->owner = THIS_MODULE;
51 trig->name = kasprintf(GFP_KERNEL, "sysfstrig%d", pdev->id);
52 if (trig->name == NULL) {
53 ret = -ENOMEM; 131 ret = -ENOMEM;
54 goto out2; 132 goto free_name;
133 }
134 t->id = id;
135 t->trig = iio_allocate_trigger_named(name);
136 if (!t->trig) {
137 ret = -ENOMEM;
138 goto free_t;
55 } 139 }
56 140
57 ret = iio_trigger_register(trig); 141 t->trig->control_attrs = &iio_sysfs_trigger_attr_group;
58 if (ret) 142 t->trig->owner = THIS_MODULE;
59 goto out3; 143 t->trig->dev.parent = &iio_sysfs_trig_dev;
60
61 platform_set_drvdata(pdev, trig);
62 144
145 ret = iio_trigger_register(t->trig);
146 if (ret)
147 goto out2;
148 list_add(&t->l, &iio_sysfs_trig_list);
149 __module_get(THIS_MODULE);
150 mutex_unlock(&iio_syfs_trig_list_mut);
63 return 0; 151 return 0;
64out3: 152
65 kfree(trig->name);
66out2: 153out2:
67 iio_put_trigger(trig); 154 iio_put_trigger(t->trig);
155free_t:
156 kfree(t);
157free_name:
158 kfree(name);
68out1: 159out1:
69 160 mutex_unlock(&iio_syfs_trig_list_mut);
70 return ret; 161 return ret;
71} 162}
72 163
73static int __devexit iio_sysfs_trigger_remove(struct platform_device *pdev) 164static int iio_sysfs_trigger_remove(int id)
74{ 165{
75 struct iio_trigger *trig = platform_get_drvdata(pdev); 166 bool foundit = false;
167 struct iio_sysfs_trig *t;
168 mutex_lock(&iio_syfs_trig_list_mut);
169 list_for_each_entry(t, &iio_sysfs_trig_list, l)
170 if (id == t->id) {
171 foundit = true;
172 break;
173 }
174 if (!foundit) {
175 mutex_unlock(&iio_syfs_trig_list_mut);
176 return -EINVAL;
177 }
76 178
77 iio_trigger_unregister(trig); 179 iio_trigger_unregister(t->trig);
78 kfree(trig->name); 180 kfree(t->trig->name);
79 iio_put_trigger(trig); 181 iio_free_trigger(t->trig);
80 182
183 list_del(&t->l);
184 kfree(t);
185 module_put(THIS_MODULE);
186 mutex_unlock(&iio_syfs_trig_list_mut);
81 return 0; 187 return 0;
82} 188}
83 189
84static struct platform_driver iio_sysfs_trigger_driver = {
85 .driver = {
86 .name = "iio_sysfs_trigger",
87 .owner = THIS_MODULE,
88 },
89 .probe = iio_sysfs_trigger_probe,
90 .remove = __devexit_p(iio_sysfs_trigger_remove),
91};
92 190
93static int __init iio_sysfs_trig_init(void) 191static int __init iio_sysfs_trig_init(void)
94{ 192{
95 return platform_driver_register(&iio_sysfs_trigger_driver); 193 device_initialize(&iio_sysfs_trig_dev);
194 dev_set_name(&iio_sysfs_trig_dev, "iio_sysfs_trigger");
195 return device_add(&iio_sysfs_trig_dev);
96} 196}
97module_init(iio_sysfs_trig_init); 197module_init(iio_sysfs_trig_init);
98 198
99static void __exit iio_sysfs_trig_exit(void) 199static void __exit iio_sysfs_trig_exit(void)
100{ 200{
101 platform_driver_unregister(&iio_sysfs_trigger_driver); 201 device_unregister(&iio_sysfs_trig_dev);
102} 202}
103module_exit(iio_sysfs_trig_exit); 203module_exit(iio_sysfs_trig_exit);
104 204