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: Xabier Marquiegui <reibax@gmail.com> Suggested-by: Richard Cochran <richardcochran@gmail.com> Suggested-by: Vinicius Costa Gomes <vinicius.gomes@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
99620ea033
commit
60c6946675
4 changed files with 76 additions and 32 deletions
|
@ -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 @@ out:
|
||||||
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)
|
||||||
|
|
||||||
#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;
|
||||||
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 @@
|
||||||
#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 {
|
||||||
/*
|
/*
|
||||||
* 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 {
|
||||||
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 @@
|
||||||
*/
|
*/
|
||||||
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)
|
||||||
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,
|
||||||
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,
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
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)
|
||||||
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)
|
||||||
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 @@ out:
|
||||||
|
|
||||||
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;
|
||||||
|
|
Loading…
Add table
Reference in a new issue