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

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
...@@ -101,14 +101,16 @@ int ptp_set_pinfunc(struct ptp_clock *ptp, unsigned int pin, ...@@ -101,14 +101,16 @@ int ptp_set_pinfunc(struct ptp_clock *ptp, unsigned int pin,
return 0; 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; 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_extended *extoff = NULL;
struct ptp_sys_offset_precise precise_offset; struct ptp_sys_offset_precise precise_offset;
struct system_device_crosststamp xtstamp; struct system_device_crosststamp xtstamp;
...@@ -432,9 +434,11 @@ long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg) ...@@ -432,9 +434,11 @@ long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg)
return err; 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); 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) ...@@ -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)) #define EXTTS_BUFSIZE (PTP_BUF_TIMESTAMPS * sizeof(struct ptp_extts_event))
ssize_t ptp_read(struct posix_clock *pc, ssize_t ptp_read(struct posix_clock_context *pccontext, uint rdflags,
uint rdflags, char __user *buf, size_t cnt) 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 timestamp_event_queue *queue = &ptp->tsevq;
struct ptp_extts_event *event; struct ptp_extts_event *event;
unsigned long flags; unsigned long flags;
......
...@@ -117,16 +117,18 @@ extern struct class *ptp_class; ...@@ -117,16 +117,18 @@ extern struct class *ptp_class;
int ptp_set_pinfunc(struct ptp_clock *ptp, unsigned int pin, int ptp_set_pinfunc(struct ptp_clock *ptp, unsigned int pin,
enum ptp_pin_function func, unsigned int chan); enum ptp_pin_function func, unsigned int chan);
long ptp_ioctl(struct posix_clock *pc, long ptp_ioctl(struct posix_clock_context *pccontext, unsigned int cmd,
unsigned int cmd, unsigned long arg); 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, int ptp_release(struct posix_clock_context *pccontext);
uint flags, char __user *buf, size_t cnt);
__poll_t ptp_poll(struct posix_clock *pc, ssize_t ptp_read(struct posix_clock_context *pccontext, uint flags, char __user *buf,
struct file *fp, poll_table *wait); size_t cnt);
__poll_t ptp_poll(struct posix_clock_context *pccontext, struct file *fp,
poll_table *wait);
/* /*
* see ptp_sysfs.c * see ptp_sysfs.c
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/rwsem.h> #include <linux/rwsem.h>
struct posix_clock; struct posix_clock;
struct posix_clock_context;
/** /**
* struct posix_clock_operations - functional interface to the clock * struct posix_clock_operations - functional interface to the clock
...@@ -50,18 +51,18 @@ struct posix_clock_operations { ...@@ -50,18 +51,18 @@ struct posix_clock_operations {
/* /*
* Optional character device methods: * Optional character device methods:
*/ */
long (*ioctl) (struct posix_clock *pc, long (*ioctl)(struct posix_clock_context *pccontext, unsigned int cmd,
unsigned int cmd, unsigned long arg); 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, __poll_t (*poll)(struct posix_clock_context *pccontext, struct file *file,
struct file *file, poll_table *wait); poll_table *wait);
int (*release) (struct posix_clock *pc); int (*release)(struct posix_clock_context *pccontext);
ssize_t (*read) (struct posix_clock *pc, ssize_t (*read)(struct posix_clock_context *pccontext, uint flags,
uint flags, char __user *buf, size_t cnt); char __user *buf, size_t cnt);
}; };
/** /**
...@@ -90,6 +91,24 @@ struct posix_clock { ...@@ -90,6 +91,24 @@ struct posix_clock {
bool zombie; 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 * posix_clock_register() - register a new clock
* @clk: Pointer to the clock. Caller must provide 'ops' field * @clk: Pointer to the clock. Caller must provide 'ops' field
......
...@@ -19,7 +19,8 @@ ...@@ -19,7 +19,8 @@
*/ */
static struct posix_clock *get_posix_clock(struct file *fp) 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); down_read(&clk->rwsem);
...@@ -39,6 +40,7 @@ static void put_posix_clock(struct posix_clock *clk) ...@@ -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, static ssize_t posix_clock_read(struct file *fp, char __user *buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
struct posix_clock_context *pccontext = fp->private_data;
struct posix_clock *clk = get_posix_clock(fp); struct posix_clock *clk = get_posix_clock(fp);
int err = -EINVAL; int err = -EINVAL;
...@@ -46,7 +48,7 @@ static ssize_t posix_clock_read(struct file *fp, char __user *buf, ...@@ -46,7 +48,7 @@ static ssize_t posix_clock_read(struct file *fp, char __user *buf,
return -ENODEV; return -ENODEV;
if (clk->ops.read) 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); put_posix_clock(clk);
...@@ -55,6 +57,7 @@ static ssize_t posix_clock_read(struct file *fp, char __user *buf, ...@@ -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) 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); struct posix_clock *clk = get_posix_clock(fp);
__poll_t result = 0; __poll_t result = 0;
...@@ -62,7 +65,7 @@ static __poll_t posix_clock_poll(struct file *fp, poll_table *wait) ...@@ -62,7 +65,7 @@ static __poll_t posix_clock_poll(struct file *fp, poll_table *wait)
return EPOLLERR; return EPOLLERR;
if (clk->ops.poll) if (clk->ops.poll)
result = clk->ops.poll(clk, fp, wait); result = clk->ops.poll(pccontext, fp, wait);
put_posix_clock(clk); put_posix_clock(clk);
...@@ -72,6 +75,7 @@ static __poll_t posix_clock_poll(struct file *fp, poll_table *wait) ...@@ -72,6 +75,7 @@ static __poll_t posix_clock_poll(struct file *fp, poll_table *wait)
static long posix_clock_ioctl(struct file *fp, static long posix_clock_ioctl(struct file *fp,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
struct posix_clock_context *pccontext = fp->private_data;
struct posix_clock *clk = get_posix_clock(fp); struct posix_clock *clk = get_posix_clock(fp);
int err = -ENOTTY; int err = -ENOTTY;
...@@ -79,7 +83,7 @@ static long posix_clock_ioctl(struct file *fp, ...@@ -79,7 +83,7 @@ static long posix_clock_ioctl(struct file *fp,
return -ENODEV; return -ENODEV;
if (clk->ops.ioctl) if (clk->ops.ioctl)
err = clk->ops.ioctl(clk, cmd, arg); err = clk->ops.ioctl(pccontext, cmd, arg);
put_posix_clock(clk); put_posix_clock(clk);
...@@ -90,6 +94,7 @@ static long posix_clock_ioctl(struct file *fp, ...@@ -90,6 +94,7 @@ static long posix_clock_ioctl(struct file *fp,
static long posix_clock_compat_ioctl(struct file *fp, static long posix_clock_compat_ioctl(struct file *fp,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
struct posix_clock_context *pccontext = fp->private_data;
struct posix_clock *clk = get_posix_clock(fp); struct posix_clock *clk = get_posix_clock(fp);
int err = -ENOTTY; int err = -ENOTTY;
...@@ -97,7 +102,7 @@ static long posix_clock_compat_ioctl(struct file *fp, ...@@ -97,7 +102,7 @@ static long posix_clock_compat_ioctl(struct file *fp,
return -ENODEV; return -ENODEV;
if (clk->ops.ioctl) if (clk->ops.ioctl)
err = clk->ops.ioctl(clk, cmd, arg); err = clk->ops.ioctl(pccontext, cmd, arg);
put_posix_clock(clk); put_posix_clock(clk);
...@@ -110,6 +115,7 @@ static int posix_clock_open(struct inode *inode, struct file *fp) ...@@ -110,6 +115,7 @@ static int posix_clock_open(struct inode *inode, struct file *fp)
int err; int err;
struct posix_clock *clk = struct posix_clock *clk =
container_of(inode->i_cdev, struct posix_clock, cdev); container_of(inode->i_cdev, struct posix_clock, cdev);
struct posix_clock_context *pccontext;
down_read(&clk->rwsem); down_read(&clk->rwsem);
...@@ -117,14 +123,20 @@ static int posix_clock_open(struct inode *inode, struct file *fp) ...@@ -117,14 +123,20 @@ static int posix_clock_open(struct inode *inode, struct file *fp)
err = -ENODEV; err = -ENODEV;
goto out; 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) if (clk->ops.open)
err = clk->ops.open(clk, fp->f_mode); err = clk->ops.open(pccontext, fp->f_mode);
else else
err = 0; err = 0;
if (!err) { if (!err) {
get_device(clk->dev); get_device(clk->dev);
fp->private_data = clk;
} }
out: out:
up_read(&clk->rwsem); up_read(&clk->rwsem);
...@@ -133,14 +145,20 @@ static int posix_clock_open(struct inode *inode, struct file *fp) ...@@ -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) 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; int err = 0;
if (!pccontext)
return -ENODEV;
clk = pccontext->clk;
if (clk->ops.release) if (clk->ops.release)
err = clk->ops.release(clk); err = clk->ops.release(pccontext);
put_device(clk->dev); put_device(clk->dev);
kfree(pccontext);
fp->private_data = NULL; fp->private_data = NULL;
return err; return err;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment