aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pps/kapi.c
diff options
context:
space:
mode:
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