linux/drivers/pps/pps.c
<<
>>
Prefs
   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 int pps_cdev_pps_fetch(struct pps_device *pps, struct pps_fdata *fdata)
  68{
  69        unsigned int ev = pps->last_ev;
  70        int err = 0;
  71
  72        /* Manage the timeout */
  73        if (fdata->timeout.flags & PPS_TIME_INVALID)
  74                err = wait_event_interruptible(pps->queue,
  75                                ev != pps->last_ev);
  76        else {
  77                unsigned long ticks;
  78
  79                dev_dbg(pps->dev, "timeout %lld.%09d\n",
  80                                (long long) fdata->timeout.sec,
  81                                fdata->timeout.nsec);
  82                ticks = fdata->timeout.sec * HZ;
  83                ticks += fdata->timeout.nsec / (NSEC_PER_SEC / HZ);
  84
  85                if (ticks != 0) {
  86                        err = wait_event_interruptible_timeout(
  87                                        pps->queue,
  88                                        ev != pps->last_ev,
  89                                        ticks);
  90                        if (err == 0)
  91                                return -ETIMEDOUT;
  92                }
  93        }
  94
  95        /* Check for pending signals */
  96        if (err == -ERESTARTSYS) {
  97                dev_dbg(pps->dev, "pending signal caught\n");
  98                return -EINTR;
  99        }
 100
 101        return 0;
 102}
 103
 104static long pps_cdev_ioctl(struct file *file,
 105                unsigned int cmd, unsigned long arg)
 106{
 107        struct pps_device *pps = file->private_data;
 108        struct pps_kparams params;
 109        void __user *uarg = (void __user *) arg;
 110        int __user *iuarg = (int __user *) arg;
 111        int err;
 112
 113        switch (cmd) {
 114        case PPS_GETPARAMS:
 115                dev_dbg(pps->dev, "PPS_GETPARAMS\n");
 116
 117                spin_lock_irq(&pps->lock);
 118
 119                /* Get the current parameters */
 120                params = pps->params;
 121
 122                spin_unlock_irq(&pps->lock);
 123
 124                err = copy_to_user(uarg, &params, sizeof(struct pps_kparams));
 125                if (err)
 126                        return -EFAULT;
 127
 128                break;
 129
 130        case PPS_SETPARAMS:
 131                dev_dbg(pps->dev, "PPS_SETPARAMS\n");
 132
 133                /* Check the capabilities */
 134                if (!capable(CAP_SYS_TIME))
 135                        return -EPERM;
 136
 137                err = copy_from_user(&params, uarg, sizeof(struct pps_kparams));
 138                if (err)
 139                        return -EFAULT;
 140                if (!(params.mode & (PPS_CAPTUREASSERT | PPS_CAPTURECLEAR))) {
 141                        dev_dbg(pps->dev, "capture mode unspecified (%x)\n",
 142                                                                params.mode);
 143                        return -EINVAL;
 144                }
 145
 146                /* Check for supported capabilities */
 147                if ((params.mode & ~pps->info.mode) != 0) {
 148                        dev_dbg(pps->dev, "unsupported capabilities (%x)\n",
 149                                                                params.mode);
 150                        return -EINVAL;
 151                }
 152
 153                spin_lock_irq(&pps->lock);
 154
 155                /* Save the new parameters */
 156                pps->params = params;
 157
 158                /* Restore the read only parameters */
 159                if ((params.mode & (PPS_TSFMT_TSPEC | PPS_TSFMT_NTPFP)) == 0) {
 160                        /* section 3.3 of RFC 2783 interpreted */
 161                        dev_dbg(pps->dev, "time format unspecified (%x)\n",
 162                                                                params.mode);
 163                        pps->params.mode |= PPS_TSFMT_TSPEC;
 164                }
 165                if (pps->info.mode & PPS_CANWAIT)
 166                        pps->params.mode |= PPS_CANWAIT;
 167                pps->params.api_version = PPS_API_VERS;
 168
 169                spin_unlock_irq(&pps->lock);
 170
 171                break;
 172
 173        case PPS_GETCAP:
 174                dev_dbg(pps->dev, "PPS_GETCAP\n");
 175
 176                err = put_user(pps->info.mode, iuarg);
 177                if (err)
 178                        return -EFAULT;
 179
 180                break;
 181
 182        case PPS_FETCH: {
 183                struct pps_fdata fdata;
 184
 185                dev_dbg(pps->dev, "PPS_FETCH\n");
 186
 187                err = copy_from_user(&fdata, uarg, sizeof(struct pps_fdata));
 188                if (err)
 189                        return -EFAULT;
 190
 191                err = pps_cdev_pps_fetch(pps, &fdata);
 192                if (err)
 193                        return err;
 194
 195                /* Return the fetched timestamp */
 196                spin_lock_irq(&pps->lock);
 197
 198                fdata.info.assert_sequence = pps->assert_sequence;
 199                fdata.info.clear_sequence = pps->clear_sequence;
 200                fdata.info.assert_tu = pps->assert_tu;
 201                fdata.info.clear_tu = pps->clear_tu;
 202                fdata.info.current_mode = pps->current_mode;
 203
 204                spin_unlock_irq(&pps->lock);
 205
 206                err = copy_to_user(uarg, &fdata, sizeof(struct pps_fdata));
 207                if (err)
 208                        return -EFAULT;
 209
 210                break;
 211        }
 212        case PPS_KC_BIND: {
 213                struct pps_bind_args bind_args;
 214
 215                dev_dbg(pps->dev, "PPS_KC_BIND\n");
 216
 217                /* Check the capabilities */
 218                if (!capable(CAP_SYS_TIME))
 219                        return -EPERM;
 220
 221                if (copy_from_user(&bind_args, uarg,
 222                                        sizeof(struct pps_bind_args)))
 223                        return -EFAULT;
 224
 225                /* Check for supported capabilities */
 226                if ((bind_args.edge & ~pps->info.mode) != 0) {
 227                        dev_err(pps->dev, "unsupported capabilities (%x)\n",
 228                                        bind_args.edge);
 229                        return -EINVAL;
 230                }
 231
 232                /* Validate parameters roughly */
 233                if (bind_args.tsformat != PPS_TSFMT_TSPEC ||
 234                                (bind_args.edge & ~PPS_CAPTUREBOTH) != 0 ||
 235                                bind_args.consumer != PPS_KC_HARDPPS) {
 236                        dev_err(pps->dev, "invalid kernel consumer bind"
 237                                        " parameters (%x)\n", bind_args.edge);
 238                        return -EINVAL;
 239                }
 240
 241                err = pps_kc_bind(pps, &bind_args);
 242                if (err < 0)
 243                        return err;
 244
 245                break;
 246        }
 247        default:
 248                return -ENOTTY;
 249        }
 250
 251        return 0;
 252}
 253
 254#ifdef CONFIG_COMPAT
 255static long pps_cdev_compat_ioctl(struct file *file,
 256                unsigned int cmd, unsigned long arg)
 257{
 258        struct pps_device *pps = file->private_data;
 259        void __user *uarg = (void __user *) arg;
 260
 261        cmd = _IOC(_IOC_DIR(cmd), _IOC_TYPE(cmd), _IOC_NR(cmd), sizeof(void *));
 262
 263        if (cmd == PPS_FETCH) {
 264                struct pps_fdata_compat compat;
 265                struct pps_fdata fdata;
 266                int err;
 267
 268                dev_dbg(pps->dev, "PPS_FETCH\n");
 269
 270                err = copy_from_user(&compat, uarg, sizeof(struct pps_fdata_compat));
 271                if (err)
 272                        return -EFAULT;
 273
 274                memcpy(&fdata.timeout, &compat.timeout,
 275                                        sizeof(struct pps_ktime_compat));
 276
 277                err = pps_cdev_pps_fetch(pps, &fdata);
 278                if (err)
 279                        return err;
 280
 281                /* Return the fetched timestamp */
 282                spin_lock_irq(&pps->lock);
 283
 284                compat.info.assert_sequence = pps->assert_sequence;
 285                compat.info.clear_sequence = pps->clear_sequence;
 286                compat.info.current_mode = pps->current_mode;
 287
 288                memcpy(&compat.info.assert_tu, &pps->assert_tu,
 289                                sizeof(struct pps_ktime_compat));
 290                memcpy(&compat.info.clear_tu, &pps->clear_tu,
 291                                sizeof(struct pps_ktime_compat));
 292
 293                spin_unlock_irq(&pps->lock);
 294
 295                return copy_to_user(uarg, &compat,
 296                                sizeof(struct pps_fdata_compat)) ? -EFAULT : 0;
 297        }
 298
 299        return pps_cdev_ioctl(file, cmd, arg);
 300}
 301#else
 302#define pps_cdev_compat_ioctl   NULL
 303#endif
 304
 305static int pps_cdev_open(struct inode *inode, struct file *file)
 306{
 307        struct pps_device *pps = container_of(inode->i_cdev,
 308                                                struct pps_device, cdev);
 309        file->private_data = pps;
 310        kobject_get(&pps->dev->kobj);
 311        return 0;
 312}
 313
 314static int pps_cdev_release(struct inode *inode, struct file *file)
 315{
 316        struct pps_device *pps = container_of(inode->i_cdev,
 317                                                struct pps_device, cdev);
 318        kobject_put(&pps->dev->kobj);
 319        return 0;
 320}
 321
 322/*
 323 * Char device stuff
 324 */
 325
 326static const struct file_operations pps_cdev_fops = {
 327        .owner          = THIS_MODULE,
 328        .llseek         = no_llseek,
 329        .poll           = pps_cdev_poll,
 330        .fasync         = pps_cdev_fasync,
 331        .compat_ioctl   = pps_cdev_compat_ioctl,
 332        .unlocked_ioctl = pps_cdev_ioctl,
 333        .open           = pps_cdev_open,
 334        .release        = pps_cdev_release,
 335};
 336
 337static void pps_device_destruct(struct device *dev)
 338{
 339        struct pps_device *pps = dev_get_drvdata(dev);
 340
 341        cdev_del(&pps->cdev);
 342
 343        /* Now we can release the ID for re-use */
 344        pr_debug("deallocating pps%d\n", pps->id);
 345        mutex_lock(&pps_idr_lock);
 346        idr_remove(&pps_idr, pps->id);
 347        mutex_unlock(&pps_idr_lock);
 348
 349        kfree(dev);
 350        kfree(pps);
 351}
 352
 353int pps_register_cdev(struct pps_device *pps)
 354{
 355        int err;
 356        dev_t devt;
 357
 358        mutex_lock(&pps_idr_lock);
 359        /*
 360         * Get new ID for the new PPS source.  After idr_alloc() calling
 361         * the new source will be freely available into the kernel.
 362         */
 363        err = idr_alloc(&pps_idr, pps, 0, PPS_MAX_SOURCES, GFP_KERNEL);
 364        if (err < 0) {
 365                if (err == -ENOSPC) {
 366                        pr_err("%s: too many PPS sources in the system\n",
 367                               pps->info.name);
 368                        err = -EBUSY;
 369                }
 370                goto out_unlock;
 371        }
 372        pps->id = err;
 373        mutex_unlock(&pps_idr_lock);
 374
 375        devt = MKDEV(MAJOR(pps_devt), pps->id);
 376
 377        cdev_init(&pps->cdev, &pps_cdev_fops);
 378        pps->cdev.owner = pps->info.owner;
 379
 380        err = cdev_add(&pps->cdev, devt, 1);
 381        if (err) {
 382                pr_err("%s: failed to add char device %d:%d\n",
 383                                pps->info.name, MAJOR(pps_devt), pps->id);
 384                goto free_idr;
 385        }
 386        pps->dev = device_create(pps_class, pps->info.dev, devt, pps,
 387                                                        "pps%d", pps->id);
 388        if (IS_ERR(pps->dev)) {
 389                err = PTR_ERR(pps->dev);
 390                goto del_cdev;
 391        }
 392
 393        /* Override the release function with our own */
 394        pps->dev->release = pps_device_destruct;
 395
 396        pr_debug("source %s got cdev (%d:%d)\n", pps->info.name,
 397                        MAJOR(pps_devt), pps->id);
 398
 399        return 0;
 400
 401del_cdev:
 402        cdev_del(&pps->cdev);
 403
 404free_idr:
 405        mutex_lock(&pps_idr_lock);
 406        idr_remove(&pps_idr, pps->id);
 407out_unlock:
 408        mutex_unlock(&pps_idr_lock);
 409        return err;
 410}
 411
 412void pps_unregister_cdev(struct pps_device *pps)
 413{
 414        pr_debug("unregistering pps%d\n", pps->id);
 415        pps->lookup_cookie = NULL;
 416        device_destroy(pps_class, pps->dev->devt);
 417}
 418
 419/*
 420 * Look up a pps device by magic cookie.
 421 * The cookie is usually a pointer to some enclosing device, but this
 422 * code doesn't care; you should never be dereferencing it.
 423 *
 424 * This is a bit of a kludge that is currently used only by the PPS
 425 * serial line discipline.  It may need to be tweaked when a second user
 426 * is found.
 427 *
 428 * There is no function interface for setting the lookup_cookie field.
 429 * It's initialized to NULL when the pps device is created, and if a
 430 * client wants to use it, just fill it in afterward.
 431 *
 432 * The cookie is automatically set to NULL in pps_unregister_source()
 433 * so that it will not be used again, even if the pps device cannot
 434 * be removed from the idr due to pending references holding the minor
 435 * number in use.
 436 */
 437struct pps_device *pps_lookup_dev(void const *cookie)
 438{
 439        struct pps_device *pps;
 440        unsigned id;
 441
 442        rcu_read_lock();
 443        idr_for_each_entry(&pps_idr, pps, id)
 444                if (cookie == pps->lookup_cookie)
 445                        break;
 446        rcu_read_unlock();
 447        return pps;
 448}
 449EXPORT_SYMBOL(pps_lookup_dev);
 450
 451/*
 452 * Module stuff
 453 */
 454
 455static void __exit pps_exit(void)
 456{
 457        class_destroy(pps_class);
 458        unregister_chrdev_region(pps_devt, PPS_MAX_SOURCES);
 459}
 460
 461static int __init pps_init(void)
 462{
 463        int err;
 464
 465        pps_class = class_create(THIS_MODULE, "pps");
 466        if (IS_ERR(pps_class)) {
 467                pr_err("failed to allocate class\n");
 468                return PTR_ERR(pps_class);
 469        }
 470        pps_class->dev_groups = pps_groups;
 471
 472        err = alloc_chrdev_region(&pps_devt, 0, PPS_MAX_SOURCES, "pps");
 473        if (err < 0) {
 474                pr_err("failed to allocate char device region\n");
 475                goto remove_class;
 476        }
 477
 478        pr_info("LinuxPPS API ver. %d registered\n", PPS_API_VERS);
 479        pr_info("Software ver. %s - Copyright 2005-2007 Rodolfo Giometti "
 480                "<giometti@linux.it>\n", PPS_VERSION);
 481
 482        return 0;
 483
 484remove_class:
 485        class_destroy(pps_class);
 486
 487        return err;
 488}
 489
 490subsys_initcall(pps_init);
 491module_exit(pps_exit);
 492
 493MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>");
 494MODULE_DESCRIPTION("LinuxPPS support (RFC 2783) - ver. " PPS_VERSION);
 495MODULE_LICENSE("GPL");
 496