diff options
author | Alexander Gordeev <lasaine@lvk.cs.msu.su> | 2011-01-12 20:00:51 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-13 11:03:19 -0500 |
commit | 5e196d34a776420278e4117b4742cd9d3f2350ed (patch) | |
tree | 86187af6a600876506261758a00c7c42e6037283 | |
parent | 6f4229b51106cbc859e9d8209b22c8a2ec749e64 (diff) |
pps: access pps device by direct pointer
Using device index as a pointer needs some unnecessary work to be done
every time the pointer is needed (in irq handler for example). Using a
direct pointer is much more easy (and safe as well).
Signed-off-by: Alexander Gordeev <lasaine@lvk.cs.msu.su>
Acked-by: Rodolfo Giometti <giometti@linux.it>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | drivers/pps/clients/pps-ktimer.c | 30 | ||||
-rw-r--r-- | drivers/pps/clients/pps-ldisc.c | 41 | ||||
-rw-r--r-- | drivers/pps/kapi.c | 124 | ||||
-rw-r--r-- | drivers/pps/pps.c | 22 | ||||
-rw-r--r-- | include/linux/pps_kernel.h | 23 |
5 files changed, 82 insertions, 158 deletions
diff --git a/drivers/pps/clients/pps-ktimer.c b/drivers/pps/clients/pps-ktimer.c index e1bdd8bc8c9c..966ead188ee2 100644 --- a/drivers/pps/clients/pps-ktimer.c +++ b/drivers/pps/clients/pps-ktimer.c | |||
@@ -31,7 +31,7 @@ | |||
31 | * Global variables | 31 | * Global variables |
32 | */ | 32 | */ |
33 | 33 | ||
34 | static int source; | 34 | static struct pps_device *pps; |
35 | static struct timer_list ktimer; | 35 | static struct timer_list ktimer; |
36 | 36 | ||
37 | /* | 37 | /* |
@@ -47,7 +47,7 @@ static void pps_ktimer_event(unsigned long ptr) | |||
47 | 47 | ||
48 | pr_info("PPS event at %lu\n", jiffies); | 48 | pr_info("PPS event at %lu\n", jiffies); |
49 | 49 | ||
50 | pps_event(source, &ts, PPS_CAPTUREASSERT, NULL); | 50 | pps_event(pps, &ts, PPS_CAPTUREASSERT, NULL); |
51 | 51 | ||
52 | mod_timer(&ktimer, jiffies + HZ); | 52 | mod_timer(&ktimer, jiffies + HZ); |
53 | } | 53 | } |
@@ -56,12 +56,11 @@ static void pps_ktimer_event(unsigned long ptr) | |||
56 | * The echo function | 56 | * The echo function |
57 | */ | 57 | */ |
58 | 58 | ||
59 | static void pps_ktimer_echo(int source, int event, void *data) | 59 | static void pps_ktimer_echo(struct pps_device *pps, int event, void *data) |
60 | { | 60 | { |
61 | pr_info("echo %s %s for source %d\n", | 61 | dev_info(pps->dev, "echo %s %s\n", |
62 | event & PPS_CAPTUREASSERT ? "assert" : "", | 62 | event & PPS_CAPTUREASSERT ? "assert" : "", |
63 | event & PPS_CAPTURECLEAR ? "clear" : "", | 63 | event & PPS_CAPTURECLEAR ? "clear" : ""); |
64 | source); | ||
65 | } | 64 | } |
66 | 65 | ||
67 | /* | 66 | /* |
@@ -84,30 +83,27 @@ static struct pps_source_info pps_ktimer_info = { | |||
84 | 83 | ||
85 | static void __exit pps_ktimer_exit(void) | 84 | static void __exit pps_ktimer_exit(void) |
86 | { | 85 | { |
87 | del_timer_sync(&ktimer); | 86 | dev_info(pps->dev, "ktimer PPS source unregistered\n"); |
88 | pps_unregister_source(source); | ||
89 | 87 | ||
90 | pr_info("ktimer PPS source unregistered\n"); | 88 | del_timer_sync(&ktimer); |
89 | pps_unregister_source(pps); | ||
91 | } | 90 | } |
92 | 91 | ||
93 | static int __init pps_ktimer_init(void) | 92 | static int __init pps_ktimer_init(void) |
94 | { | 93 | { |
95 | int ret; | 94 | pps = pps_register_source(&pps_ktimer_info, |
96 | |||
97 | ret = pps_register_source(&pps_ktimer_info, | ||
98 | PPS_CAPTUREASSERT | PPS_OFFSETASSERT); | 95 | PPS_CAPTUREASSERT | PPS_OFFSETASSERT); |
99 | if (ret < 0) { | 96 | if (pps == NULL) { |
100 | printk(KERN_ERR "cannot register ktimer source\n"); | 97 | printk(KERN_ERR "cannot register ktimer source\n"); |
101 | return ret; | 98 | return -ENOMEM; |
102 | } | 99 | } |
103 | source = ret; | ||
104 | 100 | ||
105 | setup_timer(&ktimer, pps_ktimer_event, 0); | 101 | setup_timer(&ktimer, pps_ktimer_event, 0); |
106 | mod_timer(&ktimer, jiffies + HZ); | 102 | mod_timer(&ktimer, jiffies + HZ); |
107 | 103 | ||
108 | pr_info("ktimer PPS source registered at %d\n", source); | 104 | dev_info(pps->dev, "ktimer PPS source registered\n"); |
109 | 105 | ||
110 | return 0; | 106 | return 0; |
111 | } | 107 | } |
112 | 108 | ||
113 | module_init(pps_ktimer_init); | 109 | module_init(pps_ktimer_init); |
diff --git a/drivers/pps/clients/pps-ldisc.c b/drivers/pps/clients/pps-ldisc.c index 20fc9f7645c8..1517f5498ec0 100644 --- a/drivers/pps/clients/pps-ldisc.c +++ b/drivers/pps/clients/pps-ldisc.c | |||
@@ -29,7 +29,7 @@ | |||
29 | static void pps_tty_dcd_change(struct tty_struct *tty, unsigned int status, | 29 | static void pps_tty_dcd_change(struct tty_struct *tty, unsigned int status, |
30 | struct pps_event_time *ts) | 30 | struct pps_event_time *ts) |
31 | { | 31 | { |
32 | int id = (long)tty->disc_data; | 32 | struct pps_device *pps = (struct pps_device *)tty->disc_data; |
33 | struct pps_event_time __ts; | 33 | struct pps_event_time __ts; |
34 | 34 | ||
35 | /* First of all we get the time stamp... */ | 35 | /* First of all we get the time stamp... */ |
@@ -39,12 +39,14 @@ static void pps_tty_dcd_change(struct tty_struct *tty, unsigned int status, | |||
39 | if (!ts) /* No. Do it ourself! */ | 39 | if (!ts) /* No. Do it ourself! */ |
40 | ts = &__ts; | 40 | ts = &__ts; |
41 | 41 | ||
42 | BUG_ON(pps == NULL); | ||
43 | |||
42 | /* Now do the PPS event report */ | 44 | /* Now do the PPS event report */ |
43 | pps_event(id, ts, status ? PPS_CAPTUREASSERT : PPS_CAPTURECLEAR, | 45 | pps_event(pps, ts, status ? PPS_CAPTUREASSERT : |
44 | NULL); | 46 | PPS_CAPTURECLEAR, NULL); |
45 | 47 | ||
46 | pr_debug("PPS %s at %lu on source #%d\n", | 48 | dev_dbg(pps->dev, "PPS %s at %lu\n", |
47 | status ? "assert" : "clear", jiffies, id); | 49 | status ? "assert" : "clear", jiffies); |
48 | } | 50 | } |
49 | 51 | ||
50 | static int (*alias_n_tty_open)(struct tty_struct *tty); | 52 | static int (*alias_n_tty_open)(struct tty_struct *tty); |
@@ -54,6 +56,7 @@ static int pps_tty_open(struct tty_struct *tty) | |||
54 | struct pps_source_info info; | 56 | struct pps_source_info info; |
55 | struct tty_driver *drv = tty->driver; | 57 | struct tty_driver *drv = tty->driver; |
56 | int index = tty->index + drv->name_base; | 58 | int index = tty->index + drv->name_base; |
59 | struct pps_device *pps; | ||
57 | int ret; | 60 | int ret; |
58 | 61 | ||
59 | info.owner = THIS_MODULE; | 62 | info.owner = THIS_MODULE; |
@@ -64,34 +67,42 @@ static int pps_tty_open(struct tty_struct *tty) | |||
64 | PPS_OFFSETASSERT | PPS_OFFSETCLEAR | \ | 67 | PPS_OFFSETASSERT | PPS_OFFSETCLEAR | \ |
65 | PPS_CANWAIT | PPS_TSFMT_TSPEC; | 68 | PPS_CANWAIT | PPS_TSFMT_TSPEC; |
66 | 69 | ||
67 | ret = pps_register_source(&info, PPS_CAPTUREBOTH | \ | 70 | pps = pps_register_source(&info, PPS_CAPTUREBOTH | \ |
68 | PPS_OFFSETASSERT | PPS_OFFSETCLEAR); | 71 | PPS_OFFSETASSERT | PPS_OFFSETCLEAR); |
69 | if (ret < 0) { | 72 | if (pps == NULL) { |
70 | pr_err("cannot register PPS source \"%s\"\n", info.path); | 73 | pr_err("cannot register PPS source \"%s\"\n", info.path); |
71 | return ret; | 74 | return -ENOMEM; |
72 | } | 75 | } |
73 | tty->disc_data = (void *)(long)ret; | 76 | tty->disc_data = pps; |
74 | 77 | ||
75 | /* Should open N_TTY ldisc too */ | 78 | /* Should open N_TTY ldisc too */ |
76 | ret = alias_n_tty_open(tty); | 79 | ret = alias_n_tty_open(tty); |
77 | if (ret < 0) | 80 | if (ret < 0) { |
78 | pps_unregister_source((long)tty->disc_data); | 81 | pr_err("cannot open tty ldisc \"%s\"\n", info.path); |
82 | goto err_unregister; | ||
83 | } | ||
79 | 84 | ||
80 | pr_info("PPS source #%d \"%s\" added\n", ret, info.path); | 85 | dev_info(pps->dev, "source \"%s\" added\n", info.path); |
81 | 86 | ||
82 | return 0; | 87 | return 0; |
88 | |||
89 | err_unregister: | ||
90 | tty->disc_data = NULL; | ||
91 | pps_unregister_source(pps); | ||
92 | return ret; | ||
83 | } | 93 | } |
84 | 94 | ||
85 | static void (*alias_n_tty_close)(struct tty_struct *tty); | 95 | static void (*alias_n_tty_close)(struct tty_struct *tty); |
86 | 96 | ||
87 | static void pps_tty_close(struct tty_struct *tty) | 97 | static void pps_tty_close(struct tty_struct *tty) |
88 | { | 98 | { |
89 | int id = (long)tty->disc_data; | 99 | struct pps_device *pps = (struct pps_device *)tty->disc_data; |
90 | 100 | ||
91 | pps_unregister_source(id); | ||
92 | alias_n_tty_close(tty); | 101 | alias_n_tty_close(tty); |
93 | 102 | ||
94 | pr_info("PPS source #%d removed\n", id); | 103 | tty->disc_data = NULL; |
104 | dev_info(pps->dev, "removed\n"); | ||
105 | pps_unregister_source(pps); | ||
95 | } | 106 | } |
96 | 107 | ||
97 | static struct tty_ldisc_ops pps_ldisc_ops; | 108 | static struct tty_ldisc_ops pps_ldisc_ops; |
diff --git a/drivers/pps/kapi.c b/drivers/pps/kapi.c index b431d83b824a..98d4012ca595 100644 --- a/drivers/pps/kapi.c +++ b/drivers/pps/kapi.c | |||
@@ -32,11 +32,11 @@ | |||
32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
33 | 33 | ||
34 | /* | 34 | /* |
35 | * Global variables | 35 | * Local variables |
36 | */ | 36 | */ |
37 | 37 | ||
38 | DEFINE_SPINLOCK(pps_idr_lock); | 38 | static DEFINE_SPINLOCK(pps_idr_lock); |
39 | DEFINE_IDR(pps_idr); | 39 | static DEFINE_IDR(pps_idr); |
40 | 40 | ||
41 | /* | 41 | /* |
42 | * Local functions | 42 | * Local functions |
@@ -60,60 +60,6 @@ static void pps_add_offset(struct pps_ktime *ts, struct pps_ktime *offset) | |||
60 | * Exported functions | 60 | * Exported functions |
61 | */ | 61 | */ |
62 | 62 | ||
63 | /* pps_get_source - find a PPS source | ||
64 | * @source: the PPS source ID. | ||
65 | * | ||
66 | * This function is used to find an already registered PPS source into the | ||
67 | * system. | ||
68 | * | ||
69 | * The function returns NULL if found nothing, otherwise it returns a pointer | ||
70 | * to the PPS source data struct (the refcounter is incremented by 1). | ||
71 | */ | ||
72 | |||
73 | struct pps_device *pps_get_source(int source) | ||
74 | { | ||
75 | struct pps_device *pps; | ||
76 | unsigned long flags; | ||
77 | |||
78 | spin_lock_irqsave(&pps_idr_lock, flags); | ||
79 | |||
80 | pps = idr_find(&pps_idr, source); | ||
81 | if (pps != NULL) | ||
82 | atomic_inc(&pps->usage); | ||
83 | |||
84 | spin_unlock_irqrestore(&pps_idr_lock, flags); | ||
85 | |||
86 | return pps; | ||
87 | } | ||
88 | |||
89 | /* pps_put_source - free the PPS source data | ||
90 | * @pps: a pointer to the PPS source. | ||
91 | * | ||
92 | * This function is used to free a PPS data struct if its refcount is 0. | ||
93 | */ | ||
94 | |||
95 | void pps_put_source(struct pps_device *pps) | ||
96 | { | ||
97 | unsigned long flags; | ||
98 | |||
99 | spin_lock_irqsave(&pps_idr_lock, flags); | ||
100 | BUG_ON(atomic_read(&pps->usage) == 0); | ||
101 | |||
102 | if (!atomic_dec_and_test(&pps->usage)) { | ||
103 | pps = NULL; | ||
104 | goto exit; | ||
105 | } | ||
106 | |||
107 | /* No more reference to the PPS source. We can safely remove the | ||
108 | * PPS data struct. | ||
109 | */ | ||
110 | idr_remove(&pps_idr, pps->id); | ||
111 | |||
112 | exit: | ||
113 | spin_unlock_irqrestore(&pps_idr_lock, flags); | ||
114 | kfree(pps); | ||
115 | } | ||
116 | |||
117 | /* pps_register_source - add a PPS source in the system | 63 | /* pps_register_source - add a PPS source in the system |
118 | * @info: the PPS info struct | 64 | * @info: the PPS info struct |
119 | * @default_params: the default PPS parameters of the new source | 65 | * @default_params: the default PPS parameters of the new source |
@@ -122,10 +68,11 @@ exit: | |||
122 | * source is described by info's fields and it will have, as default PPS | 68 | * source is described by info's fields and it will have, as default PPS |
123 | * parameters, the ones specified into default_params. | 69 | * parameters, the ones specified into default_params. |
124 | * | 70 | * |
125 | * The function returns, in case of success, the PPS source ID. | 71 | * The function returns, in case of success, the PPS device. Otherwise NULL. |
126 | */ | 72 | */ |
127 | 73 | ||
128 | int pps_register_source(struct pps_source_info *info, int default_params) | 74 | struct pps_device *pps_register_source(struct pps_source_info *info, |
75 | int default_params) | ||
129 | { | 76 | { |
130 | struct pps_device *pps; | 77 | struct pps_device *pps; |
131 | int id; | 78 | int id; |
@@ -168,7 +115,6 @@ int pps_register_source(struct pps_source_info *info, int default_params) | |||
168 | 115 | ||
169 | init_waitqueue_head(&pps->queue); | 116 | init_waitqueue_head(&pps->queue); |
170 | spin_lock_init(&pps->lock); | 117 | spin_lock_init(&pps->lock); |
171 | atomic_set(&pps->usage, 1); | ||
172 | 118 | ||
173 | /* Get new ID for the new PPS source */ | 119 | /* Get new ID for the new PPS source */ |
174 | if (idr_pre_get(&pps_idr, GFP_KERNEL) == 0) { | 120 | if (idr_pre_get(&pps_idr, GFP_KERNEL) == 0) { |
@@ -211,7 +157,7 @@ int pps_register_source(struct pps_source_info *info, int default_params) | |||
211 | 157 | ||
212 | pr_info("new PPS source %s at ID %d\n", info->name, id); | 158 | pr_info("new PPS source %s at ID %d\n", info->name, id); |
213 | 159 | ||
214 | return id; | 160 | return pps; |
215 | 161 | ||
216 | free_idr: | 162 | free_idr: |
217 | spin_lock_irq(&pps_idr_lock); | 163 | spin_lock_irq(&pps_idr_lock); |
@@ -224,38 +170,33 @@ kfree_pps: | |||
224 | pps_register_source_exit: | 170 | pps_register_source_exit: |
225 | printk(KERN_ERR "pps: %s: unable to register source\n", info->name); | 171 | printk(KERN_ERR "pps: %s: unable to register source\n", info->name); |
226 | 172 | ||
227 | return err; | 173 | return NULL; |
228 | } | 174 | } |
229 | EXPORT_SYMBOL(pps_register_source); | 175 | EXPORT_SYMBOL(pps_register_source); |
230 | 176 | ||
231 | /* pps_unregister_source - remove a PPS source from the system | 177 | /* pps_unregister_source - remove a PPS source from the system |
232 | * @source: the PPS source ID | 178 | * @pps: the PPS source |
233 | * | 179 | * |
234 | * This function is used to remove a previously registered PPS source from | 180 | * This function is used to remove a previously registered PPS source from |
235 | * the system. | 181 | * the system. |
236 | */ | 182 | */ |
237 | 183 | ||
238 | void pps_unregister_source(int source) | 184 | void pps_unregister_source(struct pps_device *pps) |
239 | { | 185 | { |
240 | struct pps_device *pps; | 186 | unsigned int id = pps->id; |
241 | 187 | ||
242 | spin_lock_irq(&pps_idr_lock); | 188 | pps_unregister_cdev(pps); |
243 | pps = idr_find(&pps_idr, source); | ||
244 | 189 | ||
245 | if (!pps) { | 190 | spin_lock_irq(&pps_idr_lock); |
246 | BUG(); | 191 | idr_remove(&pps_idr, pps->id); |
247 | spin_unlock_irq(&pps_idr_lock); | ||
248 | return; | ||
249 | } | ||
250 | spin_unlock_irq(&pps_idr_lock); | 192 | spin_unlock_irq(&pps_idr_lock); |
251 | 193 | ||
252 | pps_unregister_cdev(pps); | 194 | kfree(pps); |
253 | pps_put_source(pps); | ||
254 | } | 195 | } |
255 | EXPORT_SYMBOL(pps_unregister_source); | 196 | EXPORT_SYMBOL(pps_unregister_source); |
256 | 197 | ||
257 | /* pps_event - register a PPS event into the system | 198 | /* pps_event - register a PPS event into the system |
258 | * @source: the PPS source ID | 199 | * @pps: the PPS device |
259 | * @ts: the event timestamp | 200 | * @ts: the event timestamp |
260 | * @event: the event type | 201 | * @event: the event type |
261 | * @data: userdef pointer | 202 | * @data: userdef pointer |
@@ -263,30 +204,24 @@ EXPORT_SYMBOL(pps_unregister_source); | |||
263 | * This function is used by each PPS client in order to register a new | 204 | * This function is used by each PPS client in order to register a new |
264 | * PPS event into the system (it's usually called inside an IRQ handler). | 205 | * PPS event into the system (it's usually called inside an IRQ handler). |
265 | * | 206 | * |
266 | * If an echo function is associated with the PPS source it will be called | 207 | * If an echo function is associated with the PPS device it will be called |
267 | * as: | 208 | * as: |
268 | * pps->info.echo(source, event, data); | 209 | * pps->info.echo(pps, event, data); |
269 | */ | 210 | */ |
270 | 211 | void pps_event(struct pps_device *pps, struct pps_event_time *ts, int event, | |
271 | void pps_event(int source, struct pps_event_time *ts, int event, void *data) | 212 | void *data) |
272 | { | 213 | { |
273 | struct pps_device *pps; | ||
274 | unsigned long flags; | 214 | unsigned long flags; |
275 | int captured = 0; | 215 | int captured = 0; |
276 | struct pps_ktime ts_real; | 216 | struct pps_ktime ts_real; |
277 | 217 | ||
278 | if ((event & (PPS_CAPTUREASSERT | PPS_CAPTURECLEAR)) == 0) { | 218 | if ((event & (PPS_CAPTUREASSERT | PPS_CAPTURECLEAR)) == 0) { |
279 | printk(KERN_ERR "pps: unknown event (%x) for source %d\n", | 219 | dev_err(pps->dev, "unknown event (%x)\n", event); |
280 | event, source); | ||
281 | return; | 220 | return; |
282 | } | 221 | } |
283 | 222 | ||
284 | pps = pps_get_source(source); | 223 | dev_dbg(pps->dev, "PPS event at %ld.%09ld\n", |
285 | if (!pps) | 224 | ts->ts_real.tv_sec, ts->ts_real.tv_nsec); |
286 | return; | ||
287 | |||
288 | pr_debug("PPS event on source %d at %ld.%09ld\n", | ||
289 | pps->id, ts->ts_real.tv_sec, ts->ts_real.tv_nsec); | ||
290 | 225 | ||
291 | timespec_to_pps_ktime(&ts_real, ts->ts_real); | 226 | timespec_to_pps_ktime(&ts_real, ts->ts_real); |
292 | 227 | ||
@@ -294,7 +229,7 @@ void pps_event(int source, struct pps_event_time *ts, int event, void *data) | |||
294 | 229 | ||
295 | /* Must call the echo function? */ | 230 | /* Must call the echo function? */ |
296 | if ((pps->params.mode & (PPS_ECHOASSERT | PPS_ECHOCLEAR))) | 231 | if ((pps->params.mode & (PPS_ECHOASSERT | PPS_ECHOCLEAR))) |
297 | pps->info.echo(source, event, data); | 232 | pps->info.echo(pps, event, data); |
298 | 233 | ||
299 | /* Check the event */ | 234 | /* Check the event */ |
300 | pps->current_mode = pps->params.mode; | 235 | pps->current_mode = pps->params.mode; |
@@ -308,8 +243,8 @@ void pps_event(int source, struct pps_event_time *ts, int event, void *data) | |||
308 | /* Save the time stamp */ | 243 | /* Save the time stamp */ |
309 | pps->assert_tu = ts_real; | 244 | pps->assert_tu = ts_real; |
310 | pps->assert_sequence++; | 245 | pps->assert_sequence++; |
311 | pr_debug("capture assert seq #%u for source %d\n", | 246 | dev_dbg(pps->dev, "capture assert seq #%u\n", |
312 | pps->assert_sequence, source); | 247 | pps->assert_sequence); |
313 | 248 | ||
314 | captured = ~0; | 249 | captured = ~0; |
315 | } | 250 | } |
@@ -323,8 +258,8 @@ void pps_event(int source, struct pps_event_time *ts, int event, void *data) | |||
323 | /* Save the time stamp */ | 258 | /* Save the time stamp */ |
324 | pps->clear_tu = ts_real; | 259 | pps->clear_tu = ts_real; |
325 | pps->clear_sequence++; | 260 | pps->clear_sequence++; |
326 | pr_debug("capture clear seq #%u for source %d\n", | 261 | dev_dbg(pps->dev, "capture clear seq #%u\n", |
327 | pps->clear_sequence, source); | 262 | pps->clear_sequence); |
328 | 263 | ||
329 | captured = ~0; | 264 | captured = ~0; |
330 | } | 265 | } |
@@ -338,8 +273,5 @@ void pps_event(int source, struct pps_event_time *ts, int event, void *data) | |||
338 | } | 273 | } |
339 | 274 | ||
340 | spin_unlock_irqrestore(&pps->lock, flags); | 275 | spin_unlock_irqrestore(&pps->lock, flags); |
341 | |||
342 | /* Now we can release the PPS source for (possible) deregistration */ | ||
343 | pps_put_source(pps); | ||
344 | } | 276 | } |
345 | EXPORT_SYMBOL(pps_event); | 277 | EXPORT_SYMBOL(pps_event); |
diff --git a/drivers/pps/pps.c b/drivers/pps/pps.c index dc7e66cb2762..1922f27a52ac 100644 --- a/drivers/pps/pps.c +++ b/drivers/pps/pps.c | |||
@@ -204,12 +204,6 @@ static int pps_cdev_open(struct inode *inode, struct file *file) | |||
204 | { | 204 | { |
205 | struct pps_device *pps = container_of(inode->i_cdev, | 205 | struct pps_device *pps = container_of(inode->i_cdev, |
206 | struct pps_device, cdev); | 206 | struct pps_device, cdev); |
207 | int found; | ||
208 | |||
209 | found = pps_get_source(pps->id) != 0; | ||
210 | if (!found) | ||
211 | return -ENODEV; | ||
212 | |||
213 | file->private_data = pps; | 207 | file->private_data = pps; |
214 | 208 | ||
215 | return 0; | 209 | return 0; |
@@ -217,11 +211,6 @@ static int pps_cdev_open(struct inode *inode, struct file *file) | |||
217 | 211 | ||
218 | static int pps_cdev_release(struct inode *inode, struct file *file) | 212 | static int pps_cdev_release(struct inode *inode, struct file *file) |
219 | { | 213 | { |
220 | struct pps_device *pps = file->private_data; | ||
221 | |||
222 | /* Free the PPS source and wake up (possible) deregistration */ | ||
223 | pps_put_source(pps); | ||
224 | |||
225 | return 0; | 214 | return 0; |
226 | } | 215 | } |
227 | 216 | ||
@@ -242,22 +231,23 @@ static const struct file_operations pps_cdev_fops = { | |||
242 | int pps_register_cdev(struct pps_device *pps) | 231 | int pps_register_cdev(struct pps_device *pps) |
243 | { | 232 | { |
244 | int err; | 233 | int err; |
234 | dev_t devt; | ||
235 | |||
236 | devt = MKDEV(MAJOR(pps_devt), pps->id); | ||
245 | 237 | ||
246 | pps->devno = MKDEV(MAJOR(pps_devt), pps->id); | ||
247 | cdev_init(&pps->cdev, &pps_cdev_fops); | 238 | cdev_init(&pps->cdev, &pps_cdev_fops); |
248 | pps->cdev.owner = pps->info.owner; | 239 | pps->cdev.owner = pps->info.owner; |
249 | 240 | ||
250 | err = cdev_add(&pps->cdev, pps->devno, 1); | 241 | err = cdev_add(&pps->cdev, devt, 1); |
251 | if (err) { | 242 | if (err) { |
252 | printk(KERN_ERR "pps: %s: failed to add char device %d:%d\n", | 243 | printk(KERN_ERR "pps: %s: failed to add char device %d:%d\n", |
253 | pps->info.name, MAJOR(pps_devt), pps->id); | 244 | pps->info.name, MAJOR(pps_devt), pps->id); |
254 | return err; | 245 | return err; |
255 | } | 246 | } |
256 | pps->dev = device_create(pps_class, pps->info.dev, pps->devno, NULL, | 247 | pps->dev = device_create(pps_class, pps->info.dev, devt, pps, |
257 | "pps%d", pps->id); | 248 | "pps%d", pps->id); |
258 | if (IS_ERR(pps->dev)) | 249 | if (IS_ERR(pps->dev)) |
259 | goto del_cdev; | 250 | goto del_cdev; |
260 | dev_set_drvdata(pps->dev, pps); | ||
261 | 251 | ||
262 | pr_debug("source %s got cdev (%d:%d)\n", pps->info.name, | 252 | pr_debug("source %s got cdev (%d:%d)\n", pps->info.name, |
263 | MAJOR(pps_devt), pps->id); | 253 | MAJOR(pps_devt), pps->id); |
@@ -272,7 +262,7 @@ del_cdev: | |||
272 | 262 | ||
273 | void pps_unregister_cdev(struct pps_device *pps) | 263 | void pps_unregister_cdev(struct pps_device *pps) |
274 | { | 264 | { |
275 | device_destroy(pps_class, pps->devno); | 265 | device_destroy(pps_class, pps->dev->devt); |
276 | cdev_del(&pps->cdev); | 266 | cdev_del(&pps->cdev); |
277 | } | 267 | } |
278 | 268 | ||
diff --git a/include/linux/pps_kernel.h b/include/linux/pps_kernel.h index 32aa6763ca1b..1aedf50088cf 100644 --- a/include/linux/pps_kernel.h +++ b/include/linux/pps_kernel.h | |||
@@ -31,13 +31,16 @@ | |||
31 | * Global defines | 31 | * Global defines |
32 | */ | 32 | */ |
33 | 33 | ||
34 | struct pps_device; | ||
35 | |||
34 | /* The specific PPS source info */ | 36 | /* The specific PPS source info */ |
35 | struct pps_source_info { | 37 | struct pps_source_info { |
36 | char name[PPS_MAX_NAME_LEN]; /* simbolic name */ | 38 | char name[PPS_MAX_NAME_LEN]; /* simbolic name */ |
37 | char path[PPS_MAX_NAME_LEN]; /* path of connected device */ | 39 | char path[PPS_MAX_NAME_LEN]; /* path of connected device */ |
38 | int mode; /* PPS's allowed mode */ | 40 | int mode; /* PPS's allowed mode */ |
39 | 41 | ||
40 | void (*echo)(int source, int event, void *data); /* PPS echo function */ | 42 | void (*echo)(struct pps_device *pps, |
43 | int event, void *data); /* PPS echo function */ | ||
41 | 44 | ||
42 | struct module *owner; | 45 | struct module *owner; |
43 | struct device *dev; | 46 | struct device *dev; |
@@ -65,35 +68,27 @@ struct pps_device { | |||
65 | unsigned int id; /* PPS source unique ID */ | 68 | unsigned int id; /* PPS source unique ID */ |
66 | struct cdev cdev; | 69 | struct cdev cdev; |
67 | struct device *dev; | 70 | struct device *dev; |
68 | int devno; | ||
69 | struct fasync_struct *async_queue; /* fasync method */ | 71 | struct fasync_struct *async_queue; /* fasync method */ |
70 | spinlock_t lock; | 72 | spinlock_t lock; |
71 | |||
72 | atomic_t usage; /* usage count */ | ||
73 | }; | 73 | }; |
74 | 74 | ||
75 | /* | 75 | /* |
76 | * Global variables | 76 | * Global variables |
77 | */ | 77 | */ |
78 | 78 | ||
79 | extern spinlock_t pps_idr_lock; | ||
80 | extern struct idr pps_idr; | ||
81 | |||
82 | extern struct device_attribute pps_attrs[]; | 79 | extern struct device_attribute pps_attrs[]; |
83 | 80 | ||
84 | /* | 81 | /* |
85 | * Exported functions | 82 | * Exported functions |
86 | */ | 83 | */ |
87 | 84 | ||
88 | struct pps_device *pps_get_source(int source); | 85 | extern struct pps_device *pps_register_source( |
89 | extern void pps_put_source(struct pps_device *pps); | 86 | struct pps_source_info *info, int default_params); |
90 | extern int pps_register_source(struct pps_source_info *info, | 87 | extern void pps_unregister_source(struct pps_device *pps); |
91 | int default_params); | ||
92 | extern void pps_unregister_source(int source); | ||
93 | extern int pps_register_cdev(struct pps_device *pps); | 88 | extern int pps_register_cdev(struct pps_device *pps); |
94 | extern void pps_unregister_cdev(struct pps_device *pps); | 89 | extern void pps_unregister_cdev(struct pps_device *pps); |
95 | extern void pps_event(int source, struct pps_event_time *ts, int event, | 90 | extern void pps_event(struct pps_device *pps, |
96 | void *data); | 91 | struct pps_event_time *ts, int event, void *data); |
97 | 92 | ||
98 | static inline void timespec_to_pps_ktime(struct pps_ktime *kt, | 93 | static inline void timespec_to_pps_ktime(struct pps_ktime *kt, |
99 | struct timespec ts) | 94 | struct timespec ts) |