aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pps/kapi.c
diff options
context:
space:
mode:
authorAlexander Gordeev <lasaine@lvk.cs.msu.su>2011-01-12 20:00:53 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2011-01-13 11:03:20 -0500
commit083e58666ff5b3c5750d9a5c0560018b03cfb4b2 (patch)
treee0543cd7b2e375ca29c41a560e9ce0899c0f1d4e /drivers/pps/kapi.c
parent7f7cce74105adf714bdc9357da3b6f06e019958c (diff)
pps: move idr stuff to pps.c
Since now idr is only used to manage char device id's and not used in kernel API anymore it should be moved to pps.c. This also makes it possible to release id only at actual device freeing so nobody can register a pps device with the same id while our device is not freed yet. 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>
Diffstat (limited to 'drivers/pps/kapi.c')
-rw-r--r--drivers/pps/kapi.c56
1 files changed, 3 insertions, 53 deletions
diff --git a/drivers/pps/kapi.c b/drivers/pps/kapi.c
index e8847c118ea3..c42d3cb8baa1 100644
--- a/drivers/pps/kapi.c
+++ b/drivers/pps/kapi.c
@@ -27,19 +27,11 @@
27#include <linux/sched.h> 27#include <linux/sched.h>
28#include <linux/time.h> 28#include <linux/time.h>
29#include <linux/spinlock.h> 29#include <linux/spinlock.h>
30#include <linux/idr.h>
31#include <linux/fs.h> 30#include <linux/fs.h>
32#include <linux/pps_kernel.h> 31#include <linux/pps_kernel.h>
33#include <linux/slab.h> 32#include <linux/slab.h>
34 33
35/* 34/*
36 * Local variables
37 */
38
39static DEFINE_SPINLOCK(pps_idr_lock);
40static DEFINE_IDR(pps_idr);
41
42/*
43 * Local functions 35 * Local functions
44 */ 36 */
45 37
@@ -76,7 +68,6 @@ struct pps_device *pps_register_source(struct pps_source_info *info,
76 int default_params) 68 int default_params)
77{ 69{
78 struct pps_device *pps; 70 struct pps_device *pps;
79 int id;
80 int err; 71 int err;
81 72
82 /* Sanity checks */ 73 /* Sanity checks */
@@ -117,54 +108,18 @@ struct pps_device *pps_register_source(struct pps_source_info *info,
117 init_waitqueue_head(&pps->queue); 108 init_waitqueue_head(&pps->queue);
118 spin_lock_init(&pps->lock); 109 spin_lock_init(&pps->lock);
119 110
120 /* Get new ID for the new PPS source */
121 if (idr_pre_get(&pps_idr, GFP_KERNEL) == 0) {
122 err = -ENOMEM;
123 goto kfree_pps;
124 }
125
126 spin_lock_irq(&pps_idr_lock);
127
128 /* Now really allocate the PPS source.
129 * After idr_get_new() calling the new source will be freely available
130 * into the kernel.
131 */
132 err = idr_get_new(&pps_idr, pps, &id);
133 if (err < 0) {
134 spin_unlock_irq(&pps_idr_lock);
135 goto kfree_pps;
136 }
137
138 id = id & MAX_ID_MASK;
139 if (id >= PPS_MAX_SOURCES) {
140 spin_unlock_irq(&pps_idr_lock);
141
142 pr_err("%s: too many PPS sources in the system\n",
143 info->name);
144 err = -EBUSY;
145 goto free_idr;
146 }
147 pps->id = id;
148
149 spin_unlock_irq(&pps_idr_lock);
150
151 /* Create the char device */ 111 /* Create the char device */
152 err = pps_register_cdev(pps); 112 err = pps_register_cdev(pps);
153 if (err < 0) { 113 if (err < 0) {
154 pr_err("%s: unable to create char device\n", 114 pr_err("%s: unable to create char device\n",
155 info->name); 115 info->name);
156 goto free_idr; 116 goto kfree_pps;
157 } 117 }
158 118
159 dev_info(pps->dev, "new PPS source %s\n", info->name); 119 dev_info(pps->dev, "new PPS source %s\n", info->name);
160 120
161 return pps; 121 return pps;
162 122
163free_idr:
164 spin_lock_irq(&pps_idr_lock);
165 idr_remove(&pps_idr, id);
166 spin_unlock_irq(&pps_idr_lock);
167
168kfree_pps: 123kfree_pps:
169 kfree(pps); 124 kfree(pps);
170 125
@@ -184,15 +139,10 @@ EXPORT_SYMBOL(pps_register_source);
184 139
185void pps_unregister_source(struct pps_device *pps) 140void pps_unregister_source(struct pps_device *pps)
186{ 141{
187 unsigned int id = pps->id;
188
189 pps_unregister_cdev(pps); 142 pps_unregister_cdev(pps);
190 143
191 spin_lock_irq(&pps_idr_lock); 144 /* don't have to kfree(pps) here because it will be done on
192 idr_remove(&pps_idr, pps->id); 145 * device destruction */
193 spin_unlock_irq(&pps_idr_lock);
194
195 kfree(pps);
196} 146}
197EXPORT_SYMBOL(pps_unregister_source); 147EXPORT_SYMBOL(pps_unregister_source);
198 148