pps: Add pps_lookup_dev() function
The PPS serial line discipline wants to attach a PPS device to a tty without changing the tty code to add a struct pps_device * pointer. Since the number of PPS devices in a typical system is generally very low (n=1 is by far the most common), it's practical to search the entire list of allocated pps devices. (We capture the timestamp before the lookup, so the timing isn't affected.) It is a bit ugly that this function, which is part of the in-kernel PPS API, has to be in pps.c as opposed to kapi,c, but that's not something that affects users. Signed-off-by: George Spelvin <linux@horizon.com> Acked-by: Rodolfo Giometti <giometti@enneenne.com> Cc: stable <stable@vger.kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:

committed by
Greg Kroah-Hartman

parent
6d53c3b71d
commit
513b032c98
@@ -352,10 +352,43 @@ free_idr:
|
|||||||
|
|
||||||
void pps_unregister_cdev(struct pps_device *pps)
|
void pps_unregister_cdev(struct pps_device *pps)
|
||||||
{
|
{
|
||||||
|
pps->lookup_cookie = NULL;
|
||||||
device_destroy(pps_class, pps->dev->devt);
|
device_destroy(pps_class, pps->dev->devt);
|
||||||
cdev_del(&pps->cdev);
|
cdev_del(&pps->cdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Look up a pps device by magic cookie.
|
||||||
|
* The cookie is usually a pointer to some enclosing device, but this
|
||||||
|
* code doesn't care; you should never be dereferencing it.
|
||||||
|
*
|
||||||
|
* This is a bit of a kludge that is currently used only by the PPS
|
||||||
|
* serial line discipline. It may need to be tweaked when a second user
|
||||||
|
* is found.
|
||||||
|
*
|
||||||
|
* There is no function interface for setting the lookup_cookie field.
|
||||||
|
* It's initialized to NULL when the pps device is created, and if a
|
||||||
|
* client wants to use it, just fill it in afterward.
|
||||||
|
*
|
||||||
|
* The cookie is automatically set to NULL in pps_unregister_source()
|
||||||
|
* so that it will not be used again, even if the pps device cannot
|
||||||
|
* be removed from the idr due to pending references holding the minor
|
||||||
|
* number in use.
|
||||||
|
*/
|
||||||
|
struct pps_device *pps_lookup_dev(void const *cookie)
|
||||||
|
{
|
||||||
|
struct pps_device *pps;
|
||||||
|
unsigned id;
|
||||||
|
|
||||||
|
rcu_read_lock();
|
||||||
|
idr_for_each_entry(&pps_idr, pps, id)
|
||||||
|
if (cookie == pps->lookup_cookie)
|
||||||
|
break;
|
||||||
|
rcu_read_unlock();
|
||||||
|
return pps;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(pps_lookup_dev);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Module stuff
|
* Module stuff
|
||||||
*/
|
*/
|
||||||
|
@@ -43,7 +43,7 @@ struct pps_source_info {
|
|||||||
int event, void *data); /* PPS echo function */
|
int event, void *data); /* PPS echo function */
|
||||||
|
|
||||||
struct module *owner;
|
struct module *owner;
|
||||||
struct device *dev;
|
struct device *dev; /* Parent device for device_create */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pps_event_time {
|
struct pps_event_time {
|
||||||
@@ -69,6 +69,7 @@ struct pps_device {
|
|||||||
wait_queue_head_t queue; /* PPS event queue */
|
wait_queue_head_t queue; /* PPS event queue */
|
||||||
|
|
||||||
unsigned int id; /* PPS source unique ID */
|
unsigned int id; /* PPS source unique ID */
|
||||||
|
void const *lookup_cookie; /* pps_lookup_dev only */
|
||||||
struct cdev cdev;
|
struct cdev cdev;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
struct fasync_struct *async_queue; /* fasync method */
|
struct fasync_struct *async_queue; /* fasync method */
|
||||||
@@ -81,6 +82,16 @@ struct pps_device {
|
|||||||
|
|
||||||
extern struct device_attribute pps_attrs[];
|
extern struct device_attribute pps_attrs[];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Internal functions.
|
||||||
|
*
|
||||||
|
* These are not actually part of the exported API, but this is a
|
||||||
|
* convenient header file to put them in.
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern int pps_register_cdev(struct pps_device *pps);
|
||||||
|
extern void pps_unregister_cdev(struct pps_device *pps);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Exported functions
|
* Exported functions
|
||||||
*/
|
*/
|
||||||
@@ -88,10 +99,10 @@ extern struct device_attribute pps_attrs[];
|
|||||||
extern struct pps_device *pps_register_source(
|
extern struct pps_device *pps_register_source(
|
||||||
struct pps_source_info *info, int default_params);
|
struct pps_source_info *info, int default_params);
|
||||||
extern void pps_unregister_source(struct pps_device *pps);
|
extern void pps_unregister_source(struct pps_device *pps);
|
||||||
extern int pps_register_cdev(struct pps_device *pps);
|
|
||||||
extern void pps_unregister_cdev(struct pps_device *pps);
|
|
||||||
extern void pps_event(struct pps_device *pps,
|
extern void pps_event(struct pps_device *pps,
|
||||||
struct pps_event_time *ts, int event, void *data);
|
struct pps_event_time *ts, int event, void *data);
|
||||||
|
/* Look up a pps device by magic cookie */
|
||||||
|
struct pps_device *pps_lookup_dev(void const *cookie);
|
||||||
|
|
||||||
static inline void timespec_to_pps_ktime(struct pps_ktime *kt,
|
static inline void timespec_to_pps_ktime(struct pps_ktime *kt,
|
||||||
struct timespec ts)
|
struct timespec ts)
|
||||||
|
Reference in New Issue
Block a user