Commit 60c69466 authored by Xabier Marquiegui's avatar Xabier Marquiegui Committed by David S. Miller
Browse files

posix-clock: introduce posix_clock_context concept



Add the necessary structure to support custom private-data per
posix-clock user.

The previous implementation of posix-clock assumed all file open
instances need access to the same clock structure on private_data.

The need for individual data structures per file open instance has been
identified when developing support for multiple timestamp event queue
users for ptp_clock.

Signed-off-by: default avatarXabier Marquiegui <reibax@gmail.com>
Suggested-by: default avatarRichard Cochran <richardcochran@gmail.com>
Suggested-by: default avatarVinicius Costa Gomes <vinicius.gomes@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 99620ea0
Loading
Loading
Loading
Loading
+13 −8
Original line number Diff line number Diff line
@@ -101,14 +101,16 @@ int ptp_set_pinfunc(struct ptp_clock *ptp, unsigned int pin,
	return 0;
}

int ptp_open(struct posix_clock *pc, fmode_t fmode)
int ptp_open(struct posix_clock_context *pccontext, fmode_t fmode)
{
	return 0;
}

long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg)
long ptp_ioctl(struct posix_clock_context *pccontext, unsigned int cmd,
	       unsigned long arg)
{
	struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock);
	struct ptp_clock *ptp =
		container_of(pccontext->clk, struct ptp_clock, clock);
	struct ptp_sys_offset_extended *extoff = NULL;
	struct ptp_sys_offset_precise precise_offset;
	struct system_device_crosststamp xtstamp;
@@ -432,9 +434,11 @@ long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg)
	return err;
}

__poll_t ptp_poll(struct posix_clock *pc, struct file *fp, poll_table *wait)
__poll_t ptp_poll(struct posix_clock_context *pccontext, struct file *fp,
		  poll_table *wait)
{
	struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock);
	struct ptp_clock *ptp =
		container_of(pccontext->clk, struct ptp_clock, clock);

	poll_wait(fp, &ptp->tsev_wq, wait);

@@ -443,10 +447,11 @@ __poll_t ptp_poll(struct posix_clock *pc, struct file *fp, poll_table *wait)

#define EXTTS_BUFSIZE (PTP_BUF_TIMESTAMPS * sizeof(struct ptp_extts_event))

ssize_t ptp_read(struct posix_clock *pc,
		 uint rdflags, char __user *buf, size_t cnt)
ssize_t ptp_read(struct posix_clock_context *pccontext, uint rdflags,
		 char __user *buf, size_t cnt)
{
	struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock);
	struct ptp_clock *ptp =
		container_of(pccontext->clk, struct ptp_clock, clock);
	struct timestamp_event_queue *queue = &ptp->tsevq;
	struct ptp_extts_event *event;
	unsigned long flags;
+9 −7
Original line number Diff line number Diff line
@@ -117,16 +117,18 @@ extern struct class *ptp_class;
int ptp_set_pinfunc(struct ptp_clock *ptp, unsigned int pin,
		    enum ptp_pin_function func, unsigned int chan);

long ptp_ioctl(struct posix_clock *pc,
	       unsigned int cmd, unsigned long arg);
long ptp_ioctl(struct posix_clock_context *pccontext, unsigned int cmd,
	       unsigned long arg);

int ptp_open(struct posix_clock *pc, fmode_t fmode);
int ptp_open(struct posix_clock_context *pccontext, fmode_t fmode);

ssize_t ptp_read(struct posix_clock *pc,
		 uint flags, char __user *buf, size_t cnt);
int ptp_release(struct posix_clock_context *pccontext);

__poll_t ptp_poll(struct posix_clock *pc,
	      struct file *fp, poll_table *wait);
ssize_t ptp_read(struct posix_clock_context *pccontext, uint flags, char __user *buf,
		 size_t cnt);

__poll_t ptp_poll(struct posix_clock_context *pccontext, struct file *fp,
		  poll_table *wait);

/*
 * see ptp_sysfs.c
+27 −8
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@
#include <linux/rwsem.h>

struct posix_clock;
struct posix_clock_context;

/**
 * struct posix_clock_operations - functional interface to the clock
@@ -50,18 +51,18 @@ struct posix_clock_operations {
	/*
	 * Optional character device methods:
	 */
	long    (*ioctl)   (struct posix_clock *pc,
			    unsigned int cmd, unsigned long arg);
	long (*ioctl)(struct posix_clock_context *pccontext, unsigned int cmd,
		      unsigned long arg);

	int     (*open)    (struct posix_clock *pc, fmode_t f_mode);
	int (*open)(struct posix_clock_context *pccontext, fmode_t f_mode);

	__poll_t (*poll)   (struct posix_clock *pc,
			    struct file *file, poll_table *wait);
	__poll_t (*poll)(struct posix_clock_context *pccontext, struct file *file,
			 poll_table *wait);

	int     (*release) (struct posix_clock *pc);
	int (*release)(struct posix_clock_context *pccontext);

	ssize_t (*read)    (struct posix_clock *pc,
			    uint flags, char __user *buf, size_t cnt);
	ssize_t (*read)(struct posix_clock_context *pccontext, uint flags,
			char __user *buf, size_t cnt);
};

/**
@@ -90,6 +91,24 @@ struct posix_clock {
	bool zombie;
};

/**
 * struct posix_clock_context - represents clock file operations context
 *
 * @clk:              Pointer to the clock
 * @private_clkdata:  Pointer to user data
 *
 * Drivers should use struct posix_clock_context during specific character
 * device file operation methods to access the posix clock.
 *
 * Drivers can store a private data structure during the open operation
 * if they have specific information that is required in other file
 * operations.
 */
struct posix_clock_context {
	struct posix_clock *clk;
	void *private_clkdata;
};

/**
 * posix_clock_register() - register a new clock
 * @clk:   Pointer to the clock. Caller must provide 'ops' field
+27 −9
Original line number Diff line number Diff line
@@ -19,7 +19,8 @@
 */
static struct posix_clock *get_posix_clock(struct file *fp)
{
	struct posix_clock *clk = fp->private_data;
	struct posix_clock_context *pccontext = fp->private_data;
	struct posix_clock *clk = pccontext->clk;

	down_read(&clk->rwsem);

@@ -39,6 +40,7 @@ static void put_posix_clock(struct posix_clock *clk)
static ssize_t posix_clock_read(struct file *fp, char __user *buf,
				size_t count, loff_t *ppos)
{
	struct posix_clock_context *pccontext = fp->private_data;
	struct posix_clock *clk = get_posix_clock(fp);
	int err = -EINVAL;

@@ -46,7 +48,7 @@ static ssize_t posix_clock_read(struct file *fp, char __user *buf,
		return -ENODEV;

	if (clk->ops.read)
		err = clk->ops.read(clk, fp->f_flags, buf, count);
		err = clk->ops.read(pccontext, fp->f_flags, buf, count);

	put_posix_clock(clk);

@@ -55,6 +57,7 @@ static ssize_t posix_clock_read(struct file *fp, char __user *buf,

static __poll_t posix_clock_poll(struct file *fp, poll_table *wait)
{
	struct posix_clock_context *pccontext = fp->private_data;
	struct posix_clock *clk = get_posix_clock(fp);
	__poll_t result = 0;

@@ -62,7 +65,7 @@ static __poll_t posix_clock_poll(struct file *fp, poll_table *wait)
		return EPOLLERR;

	if (clk->ops.poll)
		result = clk->ops.poll(clk, fp, wait);
		result = clk->ops.poll(pccontext, fp, wait);

	put_posix_clock(clk);

@@ -72,6 +75,7 @@ static __poll_t posix_clock_poll(struct file *fp, poll_table *wait)
static long posix_clock_ioctl(struct file *fp,
			      unsigned int cmd, unsigned long arg)
{
	struct posix_clock_context *pccontext = fp->private_data;
	struct posix_clock *clk = get_posix_clock(fp);
	int err = -ENOTTY;

@@ -79,7 +83,7 @@ static long posix_clock_ioctl(struct file *fp,
		return -ENODEV;

	if (clk->ops.ioctl)
		err = clk->ops.ioctl(clk, cmd, arg);
		err = clk->ops.ioctl(pccontext, cmd, arg);

	put_posix_clock(clk);

@@ -90,6 +94,7 @@ static long posix_clock_ioctl(struct file *fp,
static long posix_clock_compat_ioctl(struct file *fp,
				     unsigned int cmd, unsigned long arg)
{
	struct posix_clock_context *pccontext = fp->private_data;
	struct posix_clock *clk = get_posix_clock(fp);
	int err = -ENOTTY;

@@ -97,7 +102,7 @@ static long posix_clock_compat_ioctl(struct file *fp,
		return -ENODEV;

	if (clk->ops.ioctl)
		err = clk->ops.ioctl(clk, cmd, arg);
		err = clk->ops.ioctl(pccontext, cmd, arg);

	put_posix_clock(clk);

@@ -110,6 +115,7 @@ static int posix_clock_open(struct inode *inode, struct file *fp)
	int err;
	struct posix_clock *clk =
		container_of(inode->i_cdev, struct posix_clock, cdev);
	struct posix_clock_context *pccontext;

	down_read(&clk->rwsem);

@@ -117,14 +123,20 @@ static int posix_clock_open(struct inode *inode, struct file *fp)
		err = -ENODEV;
		goto out;
	}
	pccontext = kzalloc(sizeof(*pccontext), GFP_KERNEL);
	if (!pccontext) {
		err = -ENOMEM;
		goto out;
	}
	pccontext->clk = clk;
	fp->private_data = pccontext;
	if (clk->ops.open)
		err = clk->ops.open(clk, fp->f_mode);
		err = clk->ops.open(pccontext, fp->f_mode);
	else
		err = 0;

	if (!err) {
		get_device(clk->dev);
		fp->private_data = clk;
	}
out:
	up_read(&clk->rwsem);
@@ -133,14 +145,20 @@ static int posix_clock_open(struct inode *inode, struct file *fp)

static int posix_clock_release(struct inode *inode, struct file *fp)
{
	struct posix_clock *clk = fp->private_data;
	struct posix_clock_context *pccontext = fp->private_data;
	struct posix_clock *clk;
	int err = 0;

	if (!pccontext)
		return -ENODEV;
	clk = pccontext->clk;

	if (clk->ops.release)
		err = clk->ops.release(clk);
		err = clk->ops.release(pccontext);

	put_device(clk->dev);

	kfree(pccontext);
	fp->private_data = NULL;

	return err;