summary refs log tree commit diff
path: root/drivers/pps/pps.c
diff options
context:
space:
mode:
authorAlexander Gordeev <lasaine@lvk.cs.msu.su>2011-01-12 17:00:58 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2011-01-13 08:03:21 -0800
commit717c033669ed3ceaee8df57d4562fafcc1a6267a (patch)
tree892e922c08b5f5eee8fbe7c8e0fdc774db660c67 /drivers/pps/pps.c
parente2c18e49a0d4f822ffc29fb4958943beb1ff08b7 (diff)
downloadlinux-717c033669ed3ceaee8df57d4562fafcc1a6267a.tar.gz
pps: add kernel consumer support
Add an optional feature of PPSAPI, kernel consumer support, which uses the
added hardpps() function.

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/pps.c')
-rw-r--r--drivers/pps/pps.c38
1 files changed, 37 insertions, 1 deletions
diff --git a/drivers/pps/pps.c b/drivers/pps/pps.c
index 9e15cf1da946..2baadd21b7a6 100644
--- a/drivers/pps/pps.c
+++ b/drivers/pps/pps.c
@@ -33,6 +33,8 @@
 #include <linux/pps_kernel.h>
 #include <linux/slab.h>
 
+#include "kc.h"
+
 /*
  * Local variables
  */
@@ -198,9 +200,43 @@ static long pps_cdev_ioctl(struct file *file,
 
 		break;
 	}
+	case PPS_KC_BIND: {
+		struct pps_bind_args bind_args;
+
+		dev_dbg(pps->dev, "PPS_KC_BIND\n");
+
+		/* Check the capabilities */
+		if (!capable(CAP_SYS_TIME))
+			return -EPERM;
+
+		if (copy_from_user(&bind_args, uarg,
+					sizeof(struct pps_bind_args)))
+			return -EFAULT;
+
+		/* Check for supported capabilities */
+		if ((bind_args.edge & ~pps->info.mode) != 0) {
+			dev_err(pps->dev, "unsupported capabilities (%x)\n",
+					bind_args.edge);
+			return -EINVAL;
+		}
+
+		/* Validate parameters roughly */
+		if (bind_args.tsformat != PPS_TSFMT_TSPEC ||
+				(bind_args.edge & ~PPS_CAPTUREBOTH) != 0 ||
+				bind_args.consumer != PPS_KC_HARDPPS) {
+			dev_err(pps->dev, "invalid kernel consumer bind"
+					" parameters (%x)\n", bind_args.edge);
+			return -EINVAL;
+		}
+
+		err = pps_kc_bind(pps, &bind_args);
+		if (err < 0)
+			return err;
+
+		break;
+	}
 	default:
 		return -ENOTTY;
-		break;
 	}
 
 	return 0;