1/*
2 * PPS core file
3 *
4 *
5 * Copyright (C) 2005-2009   Rodolfo Giometti <giometti@linux.it>
6 *
7 *   This program is free software; you can redistribute it and/or modify
8 *   it under the terms of the GNU General Public License as published by
9 *   the Free Software Foundation; either version 2 of the License, or
10 *   (at your option) any later version.
11 *
12 *   This program is distributed in the hope that it will be useful,
13 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 *   GNU General Public License for more details.
16 *
17 *   You should have received a copy of the GNU General Public License
18 *   along with this program; if not, write to the Free Software
19 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
23
24#include <linux/kernel.h>
25#include <linux/module.h>
26#include <linux/init.h>
27#include <linux/sched.h>
28#include <linux/uaccess.h>
29#include <linux/idr.h>
30#include <linux/mutex.h>
31#include <linux/cdev.h>
32#include <linux/poll.h>
33#include <linux/pps_kernel.h>
34#include <linux/slab.h>
35
36#include "kc.h"
37
38/*
39 * Local variables
40 */
41
42static dev_t pps_devt;
43static struct class *pps_class;
44
45static DEFINE_MUTEX(pps_idr_lock);
46static DEFINE_IDR(pps_idr);
47
48/*
49 * Char device methods
50 */
51
52static unsigned int pps_cdev_poll(struct file *file, poll_table *wait)
53{
54	struct pps_device *pps = file->private_data;
55
56	poll_wait(file, &pps->queue, wait);
57
58	return POLLIN | POLLRDNORM;
59}
60
61static int pps_cdev_fasync(int fd, struct file *file, int on)
62{
63	struct pps_device *pps = file->private_data;
64	return fasync_helper(fd, file, on, &pps->async_queue);
65}
66
67static long pps_cdev_ioctl(struct file *file,
68		unsigned int cmd, unsigned long arg)
69{
70	struct pps_device *pps = file->private_data;
71	struct pps_kparams params;
72	void __user *uarg = (void __user *) arg;
73	int __user *iuarg = (int __user *) arg;
74	int err;
75
76	switch (cmd) {
77	case PPS_GETPARAMS:
78		dev_dbg(pps->dev, "PPS_GETPARAMS\n");
79
80		spin_lock_irq(&pps->lock);
81
82		/* Get the current parameters */
83		params = pps->params;
84
85		spin_unlock_irq(&pps->lock);
86
87		err = copy_to_user(uarg, &params, sizeof(struct pps_kparams));
88		if (err)
89			return -EFAULT;
90
91		break;
92
93	case PPS_SETPARAMS:
94		dev_dbg(pps->dev, "PPS_SETPARAMS\n");
95
96		/* Check the capabilities */
97		if (!capable(CAP_SYS_TIME))
98			return -EPERM;
99
100		err = copy_from_user(&params, uarg, sizeof(struct pps_kparams));
101		if (err)
102			return -EFAULT;
103		if (!(params.mode & (PPS_CAPTUREASSERT | PPS_CAPTURECLEAR))) {
104			dev_dbg(pps->dev, "capture mode unspecified (%x)\n",
105								params.mode);
106			return -EINVAL;
107		}
108
109		/* Check for supported capabilities */
110		if ((params.mode & ~pps->info.mode) != 0) {
111			dev_dbg(pps->dev, "unsupported capabilities (%x)\n",
112								params.mode);
113			return -EINVAL;
114		}
115
116		spin_lock_irq(&pps->lock);
117
118		/* Save the new parameters */
119		pps->params = params;
120
121		/* Restore the read only parameters */
122		if ((params.mode & (PPS_TSFMT_TSPEC | PPS_TSFMT_NTPFP)) == 0) {
123			/* section 3.3 of RFC 2783 interpreted */
124			dev_dbg(pps->dev, "time format unspecified (%x)\n",
125								params.mode);
126			pps->params.mode |= PPS_TSFMT_TSPEC;
127		}
128		if (pps->info.mode & PPS_CANWAIT)
129			pps->params.mode |= PPS_CANWAIT;
130		pps->params.api_version = PPS_API_VERS;
131
132		spin_unlock_irq(&pps->lock);
133
134		break;
135
136	case PPS_GETCAP:
137		dev_dbg(pps->dev, "PPS_GETCAP\n");
138
139		err = put_user(pps->info.mode, iuarg);
140		if (err)
141			return -EFAULT;
142
143		break;
144
145	case PPS_FETCH: {
146		struct pps_fdata fdata;
147		unsigned int ev;
148
149		dev_dbg(pps->dev, "PPS_FETCH\n");
150
151		err = copy_from_user(&fdata, uarg, sizeof(struct pps_fdata));
152		if (err)
153			return -EFAULT;
154
155		ev = pps->last_ev;
156
157		/* Manage the timeout */
158		if (fdata.timeout.flags & PPS_TIME_INVALID)
159			err = wait_event_interruptible(pps->queue,
160					ev != pps->last_ev);
161		else {
162			unsigned long ticks;
163
164			dev_dbg(pps->dev, "timeout %lld.%09d\n",
165					(long long) fdata.timeout.sec,
166					fdata.timeout.nsec);
167			ticks = fdata.timeout.sec * HZ;
168			ticks += fdata.timeout.nsec / (NSEC_PER_SEC / HZ);
169
170			if (ticks != 0) {
171				err = wait_event_interruptible_timeout(
172						pps->queue,
173						ev != pps->last_ev,
174						ticks);
175				if (err == 0)
176					return -ETIMEDOUT;
177			}
178		}
179
180		/* Check for pending signals */
181		if (err == -ERESTARTSYS) {
182			dev_dbg(pps->dev, "pending signal caught\n");
183			return -EINTR;
184		}
185
186		/* Return the fetched timestamp */
187		spin_lock_irq(&pps->lock);
188
189		fdata.info.assert_sequence = pps->assert_sequence;
190		fdata.info.clear_sequence = pps->clear_sequence;
191		fdata.info.assert_tu = pps->assert_tu;
192		fdata.info.clear_tu = pps->clear_tu;
193		fdata.info.current_mode = pps->current_mode;
194
195		spin_unlock_irq(&pps->lock);
196
197		err = copy_to_user(uarg, &fdata, sizeof(struct pps_fdata));
198		if (err)
199			return -EFAULT;
200
201		break;
202	}
203	case PPS_KC_BIND: {
204		struct pps_bind_args bind_args;
205
206		dev_dbg(pps->dev, "PPS_KC_BIND\n");
207
208		/* Check the capabilities */
209		if (!capable(CAP_SYS_TIME))
210			return -EPERM;
211
212		if (copy_from_user(&bind_args, uarg,
213					sizeof(struct pps_bind_args)))
214			return -EFAULT;
215
216		/* Check for supported capabilities */
217		if ((bind_args.edge & ~pps->info.mode) != 0) {
218			dev_err(pps->dev, "unsupported capabilities (%x)\n",
219					bind_args.edge);
220			return -EINVAL;
221		}
222
223		/* Validate parameters roughly */
224		if (bind_args.tsformat != PPS_TSFMT_TSPEC ||
225				(bind_args.edge & ~PPS_CAPTUREBOTH) != 0 ||
226				bind_args.consumer != PPS_KC_HARDPPS) {
227			dev_err(pps->dev, "invalid kernel consumer bind"
228					" parameters (%x)\n", bind_args.edge);
229			return -EINVAL;
230		}
231
232		err = pps_kc_bind(pps, &bind_args);
233		if (err < 0)
234			return err;
235
236		break;
237	}
238	default:
239		return -ENOTTY;
240	}
241
242	return 0;
243}
244
245static int pps_cdev_open(struct inode *inode, struct file *file)
246{
247	struct pps_device *pps = container_of(inode->i_cdev,
248						struct pps_device, cdev);
249	file->private_data = pps;
250	kobject_get(&pps->dev->kobj);
251	return 0;
252}
253
254static int pps_cdev_release(struct inode *inode, struct file *file)
255{
256	struct pps_device *pps = container_of(inode->i_cdev,
257						struct pps_device, cdev);
258	kobject_put(&pps->dev->kobj);
259	return 0;
260}
261
262/*
263 * Char device stuff
264 */
265
266static const struct file_operations pps_cdev_fops = {
267	.owner		= THIS_MODULE,
268	.llseek		= no_llseek,
269	.poll		= pps_cdev_poll,
270	.fasync		= pps_cdev_fasync,
271	.unlocked_ioctl	= pps_cdev_ioctl,
272	.open		= pps_cdev_open,
273	.release	= pps_cdev_release,
274};
275
276static void pps_device_destruct(struct device *dev)
277{
278	struct pps_device *pps = dev_get_drvdata(dev);
279
280	cdev_del(&pps->cdev);
281
282	/* Now we can release the ID for re-use */
283	pr_debug("deallocating pps%d\n", pps->id);
284	mutex_lock(&pps_idr_lock);
285	idr_remove(&pps_idr, pps->id);
286	mutex_unlock(&pps_idr_lock);
287
288	kfree(dev);
289	kfree(pps);
290}
291
292int pps_register_cdev(struct pps_device *pps)
293{
294	int err;
295	dev_t devt;
296
297	mutex_lock(&pps_idr_lock);
298	/*
299	 * Get new ID for the new PPS source.  After idr_alloc() calling
300	 * the new source will be freely available into the kernel.
301	 */
302	err = idr_alloc(&pps_idr, pps, 0, PPS_MAX_SOURCES, GFP_KERNEL);
303	if (err < 0) {
304		if (err == -ENOSPC) {
305			pr_err("%s: too many PPS sources in the system\n",
306			       pps->info.name);
307			err = -EBUSY;
308		}
309		goto out_unlock;
310	}
311	pps->id = err;
312	mutex_unlock(&pps_idr_lock);
313
314	devt = MKDEV(MAJOR(pps_devt), pps->id);
315
316	cdev_init(&pps->cdev, &pps_cdev_fops);
317	pps->cdev.owner = pps->info.owner;
318
319	err = cdev_add(&pps->cdev, devt, 1);
320	if (err) {
321		pr_err("%s: failed to add char device %d:%d\n",
322				pps->info.name, MAJOR(pps_devt), pps->id);
323		goto free_idr;
324	}
325	pps->dev = device_create(pps_class, pps->info.dev, devt, pps,
326							"pps%d", pps->id);
327	if (IS_ERR(pps->dev)) {
328		err = PTR_ERR(pps->dev);
329		goto del_cdev;
330	}
331
332	/* Override the release function with our own */
333	pps->dev->release = pps_device_destruct;
334
335	pr_debug("source %s got cdev (%d:%d)\n", pps->info.name,
336			MAJOR(pps_devt), pps->id);
337
338	return 0;
339
340del_cdev:
341	cdev_del(&pps->cdev);
342
343free_idr:
344	mutex_lock(&pps_idr_lock);
345	idr_remove(&pps_idr, pps->id);
346out_unlock:
347	mutex_unlock(&pps_idr_lock);
348	return err;
349}
350
351void pps_unregister_cdev(struct pps_device *pps)
352{
353	pr_debug("unregistering pps%d\n", pps->id);
354	pps->lookup_cookie = NULL;
355	device_destroy(pps_class, pps->dev->devt);
356}
357
358/*
359 * Look up a pps device by magic cookie.
360 * The cookie is usually a pointer to some enclosing device, but this
361 * code doesn't care; you should never be dereferencing it.
362 *
363 * This is a bit of a kludge that is currently used only by the PPS
364 * serial line discipline.  It may need to be tweaked when a second user
365 * is found.
366 *
367 * There is no function interface for setting the lookup_cookie field.
368 * It's initialized to NULL when the pps device is created, and if a
369 * client wants to use it, just fill it in afterward.
370 *
371 * The cookie is automatically set to NULL in pps_unregister_source()
372 * so that it will not be used again, even if the pps device cannot
373 * be removed from the idr due to pending references holding the minor
374 * number in use.
375 */
376struct pps_device *pps_lookup_dev(void const *cookie)
377{
378	struct pps_device *pps;
379	unsigned id;
380
381	rcu_read_lock();
382	idr_for_each_entry(&pps_idr, pps, id)
383		if (cookie == pps->lookup_cookie)
384			break;
385	rcu_read_unlock();
386	return pps;
387}
388EXPORT_SYMBOL(pps_lookup_dev);
389
390/*
391 * Module stuff
392 */
393
394static void __exit pps_exit(void)
395{
396	class_destroy(pps_class);
397	unregister_chrdev_region(pps_devt, PPS_MAX_SOURCES);
398}
399
400static int __init pps_init(void)
401{
402	int err;
403
404	pps_class = class_create(THIS_MODULE, "pps");
405	if (IS_ERR(pps_class)) {
406		pr_err("failed to allocate class\n");
407		return PTR_ERR(pps_class);
408	}
409	pps_class->dev_groups = pps_groups;
410
411	err = alloc_chrdev_region(&pps_devt, 0, PPS_MAX_SOURCES, "pps");
412	if (err < 0) {
413		pr_err("failed to allocate char device region\n");
414		goto remove_class;
415	}
416
417	pr_info("LinuxPPS API ver. %d registered\n", PPS_API_VERS);
418	pr_info("Software ver. %s - Copyright 2005-2007 Rodolfo Giometti "
419		"<giometti@linux.it>\n", PPS_VERSION);
420
421	return 0;
422
423remove_class:
424	class_destroy(pps_class);
425
426	return err;
427}
428
429subsys_initcall(pps_init);
430module_exit(pps_exit);
431
432MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>");
433MODULE_DESCRIPTION("LinuxPPS support (RFC 2783) - ver. " PPS_VERSION);
434MODULE_LICENSE("GPL");
435