From c3c6dd750e0b8dcee0306b9c5a45708922debbbe Mon Sep 17 00:00:00 2001 From: David Härdeman Date: Sun, 25 Jun 2017 09:31:24 -0300 Subject: [media] media: lirc_dev: remove support for manually specifying minor number MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All users of lirc_register_driver() uses dynamic minor allocation, therefore we can remove the ability to explicitly request a given number. This changes the function prototype of lirc_unregister_driver() to also take a struct lirc_driver pointer as the sole argument. Signed-off-by: David Härdeman Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- include/media/lirc_dev.h | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'include/media/lirc_dev.h') diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h index 86d15a9b6c01..1bb9890744fa 100644 --- a/include/media/lirc_dev.h +++ b/include/media/lirc_dev.h @@ -116,10 +116,8 @@ static inline unsigned int lirc_buffer_write(struct lirc_buffer *buf, * * @name: this string will be used for logs * - * @minor: indicates minor device (/dev/lirc) number for - * registered driver if caller fills it with negative - * value, then the first free minor number will be used - * (if available). + * @minor: the minor device (/dev/lircX) number for a registered + * driver. * * @code_length: length of the remote control key code expressed in bits. * @@ -157,10 +155,12 @@ static inline unsigned int lirc_buffer_write(struct lirc_buffer *buf, * device. * * @owner: the module owning this struct + * + * @irctl: the struct irctl for this LIRC device. */ struct lirc_driver { char name[40]; - int minor; + unsigned int minor; __u32 code_length; unsigned int buffer_size; /* in chunks holding one code each */ __u32 features; @@ -175,19 +175,17 @@ struct lirc_driver { const struct file_operations *fops; struct device *dev; struct module *owner; + struct irctl *irctl; }; /* following functions can be called ONLY from user context * - * returns negative value on error or minor number - * of the registered device if success + * returns negative value on error or zero * contents of the structure pointed by p is copied */ -extern int lirc_register_driver(struct lirc_driver *d); +int lirc_register_driver(struct lirc_driver *d); -/* returns negative value on error or 0 if success -*/ -extern int lirc_unregister_driver(int minor); +void lirc_unregister_driver(struct lirc_driver *d); /* Returns the private data stored in the lirc_driver * associated with the given device file pointer. -- cgit v1.2.3 From 615cd3fe6cccb950b46728120009a1805cce908e Mon Sep 17 00:00:00 2001 From: David Härdeman Date: Sun, 25 Jun 2017 09:31:40 -0300 Subject: [media] media: lirc_dev: make better use of file->private_data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit By making better use of file->private_data in lirc_dev we can avoid digging around in the irctls[] array, thereby simplifying the code. External drivers need to use lirc_get_pdata() instead of mucking around in file->private_data. The newly introduced lirc_init_pdata() function isn't very elegant, but it's a stopgap measure which can be removed once lirc_zilog is converted to rc-core. Signed-off-by: David Härdeman Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/lirc_dev.c | 70 ++++++++++----------------------- drivers/staging/media/lirc/lirc_zilog.c | 53 +++++-------------------- include/media/lirc_dev.h | 3 ++ 3 files changed, 33 insertions(+), 93 deletions(-) (limited to 'include/media/lirc_dev.h') diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c index 057983b8ec53..ffa203eb2045 100644 --- a/drivers/media/rc/lirc_dev.c +++ b/drivers/media/rc/lirc_dev.c @@ -247,36 +247,18 @@ EXPORT_SYMBOL(lirc_unregister_driver); int lirc_dev_fop_open(struct inode *inode, struct file *file) { - struct irctl *ir; + struct irctl *ir = container_of(inode->i_cdev, struct irctl, cdev); int retval; - if (iminor(inode) >= MAX_IRCTL_DEVICES) { - pr_err("open result for %d is -ENODEV\n", iminor(inode)); - return -ENODEV; - } - - if (mutex_lock_interruptible(&lirc_dev_lock)) - return -ERESTARTSYS; - - ir = irctls[iminor(inode)]; - mutex_unlock(&lirc_dev_lock); - - if (!ir) { - retval = -ENODEV; - goto error; - } - dev_dbg(ir->d.dev, LOGHEAD "open called\n", ir->d.name, ir->d.minor); - if (ir->open) { - retval = -EBUSY; - goto error; - } + if (ir->open) + return -EBUSY; if (ir->d.rdev) { retval = rc_open(ir->d.rdev); if (retval) - goto error; + return retval; } if (ir->buf) @@ -284,25 +266,18 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file) ir->open++; + lirc_init_pdata(inode, file); nonseekable_open(inode, file); return 0; - -error: - return retval; } EXPORT_SYMBOL(lirc_dev_fop_open); int lirc_dev_fop_close(struct inode *inode, struct file *file) { - struct irctl *ir = irctls[iminor(inode)]; + struct irctl *ir = file->private_data; int ret; - if (!ir) { - pr_err("called with invalid irctl\n"); - return -EINVAL; - } - ret = mutex_lock_killable(&lirc_dev_lock); WARN_ON(ret); @@ -318,14 +293,9 @@ EXPORT_SYMBOL(lirc_dev_fop_close); unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait) { - struct irctl *ir = irctls[iminor(file_inode(file))]; + struct irctl *ir = file->private_data; unsigned int ret; - if (!ir) { - pr_err("called with invalid irctl\n"); - return POLLERR; - } - if (!ir->attached) return POLLHUP | POLLERR; @@ -348,14 +318,9 @@ EXPORT_SYMBOL(lirc_dev_fop_poll); long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { + struct irctl *ir = file->private_data; __u32 mode; int result = 0; - struct irctl *ir = irctls[iminor(file_inode(file))]; - - if (!ir) { - pr_err("no irctl found!\n"); - return -ENODEV; - } dev_dbg(ir->d.dev, LOGHEAD "ioctl called (0x%x)\n", ir->d.name, ir->d.minor, cmd); @@ -432,16 +397,11 @@ ssize_t lirc_dev_fop_read(struct file *file, size_t length, loff_t *ppos) { - struct irctl *ir = irctls[iminor(file_inode(file))]; + struct irctl *ir = file->private_data; unsigned char *buf; int ret = 0, written = 0; DECLARE_WAITQUEUE(wait, current); - if (!ir) { - pr_err("called with invalid irctl\n"); - return -ENODEV; - } - if (!LIRC_CAN_REC(ir->d.features)) return -EINVAL; @@ -532,9 +492,19 @@ out_unlocked: } EXPORT_SYMBOL(lirc_dev_fop_read); +void lirc_init_pdata(struct inode *inode, struct file *file) +{ + struct irctl *ir = container_of(inode->i_cdev, struct irctl, cdev); + + file->private_data = ir; +} +EXPORT_SYMBOL(lirc_init_pdata); + void *lirc_get_pdata(struct file *file) { - return irctls[iminor(file_inode(file))]->d.data; + struct irctl *ir = file->private_data; + + return ir->d.data; } EXPORT_SYMBOL(lirc_get_pdata); diff --git a/drivers/staging/media/lirc/lirc_zilog.c b/drivers/staging/media/lirc/lirc_zilog.c index efcbfef1980e..c4a4c2f93ae8 100644 --- a/drivers/staging/media/lirc/lirc_zilog.c +++ b/drivers/staging/media/lirc/lirc_zilog.c @@ -879,7 +879,7 @@ out: static ssize_t read(struct file *filep, char __user *outbuf, size_t n, loff_t *ppos) { - struct IR *ir = filep->private_data; + struct IR *ir = lirc_get_pdata(filep); struct IR_rx *rx; struct lirc_buffer *rbuf = ir->l.rbuf; int ret = 0, written = 0, retries = 0; @@ -1089,7 +1089,7 @@ static int send_code(struct IR_tx *tx, unsigned int code, unsigned int key) static ssize_t write(struct file *filep, const char __user *buf, size_t n, loff_t *ppos) { - struct IR *ir = filep->private_data; + struct IR *ir = lirc_get_pdata(filep); struct IR_tx *tx; size_t i; int failures = 0; @@ -1197,7 +1197,7 @@ static ssize_t write(struct file *filep, const char __user *buf, size_t n, /* copied from lirc_dev */ static unsigned int poll(struct file *filep, poll_table *wait) { - struct IR *ir = filep->private_data; + struct IR *ir = lirc_get_pdata(filep); struct IR_rx *rx; struct lirc_buffer *rbuf = ir->l.rbuf; unsigned int ret; @@ -1230,7 +1230,7 @@ static unsigned int poll(struct file *filep, poll_table *wait) static long ioctl(struct file *filep, unsigned int cmd, unsigned long arg) { - struct IR *ir = filep->private_data; + struct IR *ir = lirc_get_pdata(filep); unsigned long __user *uptr = (unsigned long __user *)arg; int result; unsigned long mode, features; @@ -1280,46 +1280,18 @@ static long ioctl(struct file *filep, unsigned int cmd, unsigned long arg) return result; } -static struct IR *get_ir_device_by_minor(unsigned int minor) -{ - struct IR *ir; - struct IR *ret = NULL; - - mutex_lock(&ir_devices_lock); - - if (!list_empty(&ir_devices_list)) { - list_for_each_entry(ir, &ir_devices_list, list) { - if (ir->l.minor == minor) { - ret = get_ir_device(ir, true); - break; - } - } - } - - mutex_unlock(&ir_devices_lock); - return ret; -} - /* - * Open the IR device. Get hold of our IR structure and - * stash it in private_data for the file + * Open the IR device. */ static int open(struct inode *node, struct file *filep) { struct IR *ir; - unsigned int minor = MINOR(node->i_rdev); - - /* find our IR struct */ - ir = get_ir_device_by_minor(minor); - if (!ir) - return -ENODEV; + lirc_init_pdata(node, filep); + ir = lirc_get_pdata(filep); atomic_inc(&ir->open_count); - /* stash our IR struct */ - filep->private_data = ir; - nonseekable_open(node, filep); return 0; } @@ -1327,14 +1299,7 @@ static int open(struct inode *node, struct file *filep) /* Close the IR device */ static int close(struct inode *node, struct file *filep) { - /* find our IR struct */ - struct IR *ir = filep->private_data; - - if (!ir) { - pr_err("ir: %s: no private_data attached to the file!\n", - __func__); - return -ENODEV; - } + struct IR *ir = lirc_get_pdata(filep); atomic_dec(&ir->open_count); @@ -1489,6 +1454,8 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) */ ir->l.rbuf = &ir->rbuf; ir->l.dev = &adap->dev; + /* This will be returned by lirc_get_pdata() */ + ir->l.data = ir; ret = lirc_buffer_init(ir->l.rbuf, ir->l.chunk_size, ir->l.buffer_size); if (ret) diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h index 1bb9890744fa..d07a53232ffc 100644 --- a/include/media/lirc_dev.h +++ b/include/media/lirc_dev.h @@ -187,6 +187,9 @@ int lirc_register_driver(struct lirc_driver *d); void lirc_unregister_driver(struct lirc_driver *d); +/* Must be called in the open fop before lirc_get_pdata() can be used */ +void lirc_init_pdata(struct inode *inode, struct file *file); + /* Returns the private data stored in the lirc_driver * associated with the given device file pointer. */ -- cgit v1.2.3 From b145ef94f63e02c2615ffde61a376b53f3367bc6 Mon Sep 17 00:00:00 2001 From: David Härdeman Date: Sun, 25 Jun 2017 09:31:45 -0300 Subject: [media] media: lirc_dev: make chunk_size and buffer_size mandatory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make setting chunk_size and buffer_size mandatory for drivers which expect lirc_dev to allocate the lirc_buffer (i.e. ir-lirc-codec) and don't set them in lirc-zilog (which creates its own buffer). Also remove an unnecessary copy of chunk_size in struct irctl (the same information is already available from struct lirc_buffer). Signed-off-by: David Härdeman Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/lirc_dev.c | 26 +++++++++++++------------- drivers/staging/media/lirc/lirc_zilog.c | 5 +---- include/media/lirc_dev.h | 9 +++++---- 3 files changed, 19 insertions(+), 21 deletions(-) (limited to 'include/media/lirc_dev.h') diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c index ffa203eb2045..1915ffc52955 100644 --- a/drivers/media/rc/lirc_dev.c +++ b/drivers/media/rc/lirc_dev.c @@ -41,7 +41,6 @@ struct irctl { struct mutex irctl_lock; struct lirc_buffer *buf; bool buf_internal; - unsigned int chunk_size; struct device dev; struct cdev cdev; @@ -74,16 +73,8 @@ static void lirc_release(struct device *ld) static int lirc_allocate_buffer(struct irctl *ir) { int err = 0; - int bytes_in_key; - unsigned int chunk_size; - unsigned int buffer_size; struct lirc_driver *d = &ir->d; - bytes_in_key = BITS_TO_LONGS(d->code_length) + - (d->code_length % 8 ? 1 : 0); - buffer_size = d->buffer_size ? d->buffer_size : BUFLEN / bytes_in_key; - chunk_size = d->chunk_size ? d->chunk_size : bytes_in_key; - if (d->rbuf) { ir->buf = d->rbuf; ir->buf_internal = false; @@ -94,7 +85,7 @@ static int lirc_allocate_buffer(struct irctl *ir) goto out; } - err = lirc_buffer_init(ir->buf, chunk_size, buffer_size); + err = lirc_buffer_init(ir->buf, d->chunk_size, d->buffer_size); if (err) { kfree(ir->buf); ir->buf = NULL; @@ -104,7 +95,6 @@ static int lirc_allocate_buffer(struct irctl *ir) ir->buf_internal = true; d->rbuf = ir->buf; } - ir->chunk_size = ir->buf->chunk_size; out: return err; @@ -131,6 +121,16 @@ int lirc_register_driver(struct lirc_driver *d) return -EINVAL; } + if (!d->rbuf && d->chunk_size < 1) { + pr_err("chunk_size must be set!\n"); + return -EINVAL; + } + + if (!d->rbuf && d->buffer_size < 1) { + pr_err("buffer_size must be set!\n"); + return -EINVAL; + } + if (d->code_length < 1 || d->code_length > (BUFLEN * 8)) { dev_err(d->dev, "code length must be less than %d bits\n", BUFLEN * 8); @@ -407,7 +407,7 @@ ssize_t lirc_dev_fop_read(struct file *file, dev_dbg(ir->d.dev, LOGHEAD "read called\n", ir->d.name, ir->d.minor); - buf = kzalloc(ir->chunk_size, GFP_KERNEL); + buf = kzalloc(ir->buf->chunk_size, GFP_KERNEL); if (!buf) return -ENOMEM; @@ -420,7 +420,7 @@ ssize_t lirc_dev_fop_read(struct file *file, goto out_locked; } - if (length % ir->chunk_size) { + if (length % ir->buf->chunk_size) { ret = -EINVAL; goto out_locked; } diff --git a/drivers/staging/media/lirc/lirc_zilog.c b/drivers/staging/media/lirc/lirc_zilog.c index c4a4c2f93ae8..780b2d9f2f4b 100644 --- a/drivers/staging/media/lirc/lirc_zilog.c +++ b/drivers/staging/media/lirc/lirc_zilog.c @@ -1348,8 +1348,6 @@ static const struct file_operations lirc_fops = { static struct lirc_driver lirc_template = { .name = "lirc_zilog", .code_length = 13, - .buffer_size = BUFLEN / 2, - .chunk_size = 2, .fops = &lirc_fops, .owner = THIS_MODULE, }; @@ -1456,8 +1454,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) ir->l.dev = &adap->dev; /* This will be returned by lirc_get_pdata() */ ir->l.data = ir; - ret = lirc_buffer_init(ir->l.rbuf, - ir->l.chunk_size, ir->l.buffer_size); + ret = lirc_buffer_init(ir->l.rbuf, 2, BUFLEN / 2); if (ret) goto out_put_ir; } diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h index d07a53232ffc..8e3894e2d2c8 100644 --- a/include/media/lirc_dev.h +++ b/include/media/lirc_dev.h @@ -121,13 +121,14 @@ static inline unsigned int lirc_buffer_write(struct lirc_buffer *buf, * * @code_length: length of the remote control key code expressed in bits. * - * @buffer_size: Number of FIFO buffers with @chunk_size size. If zero, - * creates a buffer with BUFLEN size (16 bytes). - * * @features: lirc compatible hardware features, like LIRC_MODE_RAW, * LIRC_CAN\_\*, as defined at include/media/lirc.h. * + * @buffer_size: Number of FIFO buffers with @chunk_size size. + * Only used if @rbuf is NULL. + * * @chunk_size: Size of each FIFO buffer. + * Only used if @rbuf is NULL. * * @data: it may point to any driver data and this pointer will * be passed to all callback functions. @@ -162,9 +163,9 @@ struct lirc_driver { char name[40]; unsigned int minor; __u32 code_length; - unsigned int buffer_size; /* in chunks holding one code each */ __u32 features; + unsigned int buffer_size; /* in chunks holding one code each */ unsigned int chunk_size; void *data; -- cgit v1.2.3 From 46c8f4771154eb0dc21f5f2bc2640a33e8fe1d02 Mon Sep 17 00:00:00 2001 From: David Härdeman Date: Sun, 25 Jun 2017 09:32:05 -0300 Subject: [media] media: lirc_dev: use an IDA instead of an array to keep track of registered devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using the kernel-provided IDA simplifies the code and makes it possible to remove the lirc_dev_lock mutex. Signed-off-by: David Härdeman Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/lirc_dev.c | 36 ++++++++++++------------------------ include/media/lirc_dev.h | 1 - 2 files changed, 12 insertions(+), 25 deletions(-) (limited to 'include/media/lirc_dev.h') diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c index c83fffec0681..a2c5ed0181c1 100644 --- a/drivers/media/rc/lirc_dev.c +++ b/drivers/media/rc/lirc_dev.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -46,10 +47,9 @@ struct irctl { struct cdev cdev; }; -/* This mutex protects the irctls array */ -static DEFINE_MUTEX(lirc_dev_lock); - -static struct irctl *irctls[MAX_IRCTL_DEVICES]; +/* Used to keep track of allocated lirc devices */ +#define LIRC_MAX_DEVICES 256 +static DEFINE_IDA(lirc_ida); /* Only used for sysfs but defined to void otherwise */ static struct class *lirc_class; @@ -69,9 +69,6 @@ static void lirc_release(struct device *ld) { struct irctl *ir = container_of(ld, struct irctl, dev); - mutex_lock(&lirc_dev_lock); - irctls[ir->d.minor] = NULL; - mutex_unlock(&lirc_dev_lock); lirc_free_buffer(ir); kfree(ir); } @@ -109,7 +106,7 @@ out: int lirc_register_driver(struct lirc_driver *d) { struct irctl *ir; - unsigned int minor; + int minor; int err; if (!d) { @@ -171,28 +168,17 @@ int lirc_register_driver(struct lirc_driver *d) d->rbuf = ir->buf; } - mutex_lock(&lirc_dev_lock); - - /* find first free slot for driver */ - for (minor = 0; minor < MAX_IRCTL_DEVICES; minor++) - if (!irctls[minor]) - break; - - if (minor == MAX_IRCTL_DEVICES) { - dev_err(d->dev, "no free slots for drivers!\n"); - mutex_unlock(&lirc_dev_lock); + minor = ida_simple_get(&lirc_ida, 0, LIRC_MAX_DEVICES, GFP_KERNEL); + if (minor < 0) { lirc_free_buffer(ir); kfree(ir); - return -ENOMEM; + return minor; } - irctls[minor] = ir; d->irctl = ir; d->minor = minor; ir->d.minor = minor; - mutex_unlock(&lirc_dev_lock); - device_initialize(&ir->dev); ir->dev.devt = MKDEV(MAJOR(lirc_base_dev), ir->d.minor); ir->dev.class = lirc_class; @@ -206,6 +192,7 @@ int lirc_register_driver(struct lirc_driver *d) err = cdev_device_add(&ir->cdev, &ir->dev); if (err) { + ida_simple_remove(&lirc_ida, minor); put_device(&ir->dev); return err; } @@ -244,6 +231,7 @@ void lirc_unregister_driver(struct lirc_driver *d) mutex_unlock(&ir->mutex); + ida_simple_remove(&lirc_ida, d->minor); put_device(&ir->dev); } EXPORT_SYMBOL(lirc_unregister_driver); @@ -540,7 +528,7 @@ static int __init lirc_dev_init(void) return PTR_ERR(lirc_class); } - retval = alloc_chrdev_region(&lirc_base_dev, 0, MAX_IRCTL_DEVICES, + retval = alloc_chrdev_region(&lirc_base_dev, 0, LIRC_MAX_DEVICES, "BaseRemoteCtl"); if (retval) { class_destroy(lirc_class); @@ -557,7 +545,7 @@ static int __init lirc_dev_init(void) static void __exit lirc_dev_exit(void) { class_destroy(lirc_class); - unregister_chrdev_region(lirc_base_dev, MAX_IRCTL_DEVICES); + unregister_chrdev_region(lirc_base_dev, LIRC_MAX_DEVICES); pr_info("module unloaded\n"); } diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h index 8e3894e2d2c8..51c15c050e85 100644 --- a/include/media/lirc_dev.h +++ b/include/media/lirc_dev.h @@ -9,7 +9,6 @@ #ifndef _LINUX_LIRC_DEV_H #define _LINUX_LIRC_DEV_H -#define MAX_IRCTL_DEVICES 8 #define BUFLEN 16 #include -- cgit v1.2.3 From 5ddc9c098dc3f91243840cec12a2170e9ab9f33a Mon Sep 17 00:00:00 2001 From: David Härdeman Date: Thu, 21 Sep 2017 16:13:34 -0300 Subject: [media] media: rename struct lirc_driver to struct lirc_dev MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is in preparation for the later patches which do away with struct irctl entirely. Signed-off-by: David Härdeman Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/ir-lirc-codec.c | 52 ++++++++++++++++----------------- drivers/media/rc/lirc_dev.c | 12 ++++---- drivers/media/rc/rc-core-priv.h | 2 +- drivers/staging/media/lirc/lirc_zilog.c | 12 ++++---- include/media/lirc_dev.h | 48 +++++++++--------------------- 5 files changed, 52 insertions(+), 74 deletions(-) (limited to 'include/media/lirc_dev.h') diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c index 58bff7a75d5b..2d591168c991 100644 --- a/drivers/media/rc/ir-lirc-codec.c +++ b/drivers/media/rc/ir-lirc-codec.c @@ -35,7 +35,7 @@ static int ir_lirc_decode(struct rc_dev *dev, struct ir_raw_event ev) struct lirc_codec *lirc = &dev->raw->lirc; int sample; - if (!dev->raw->lirc.drv || !dev->raw->lirc.drv->rbuf) + if (!dev->raw->lirc.ldev || !dev->raw->lirc.ldev->rbuf) return -EINVAL; /* Packet start */ @@ -84,8 +84,8 @@ static int ir_lirc_decode(struct rc_dev *dev, struct ir_raw_event ev) (u64)LIRC_VALUE_MASK); gap_sample = LIRC_SPACE(lirc->gap_duration); - lirc_buffer_write(dev->raw->lirc.drv->rbuf, - (unsigned char *) &gap_sample); + lirc_buffer_write(dev->raw->lirc.ldev->rbuf, + (unsigned char *)&gap_sample); lirc->gap = false; } @@ -95,9 +95,9 @@ static int ir_lirc_decode(struct rc_dev *dev, struct ir_raw_event ev) TO_US(ev.duration), TO_STR(ev.pulse)); } - lirc_buffer_write(dev->raw->lirc.drv->rbuf, + lirc_buffer_write(dev->raw->lirc.ldev->rbuf, (unsigned char *) &sample); - wake_up(&dev->raw->lirc.drv->rbuf->wait_poll); + wake_up(&dev->raw->lirc.ldev->rbuf->wait_poll); return 0; } @@ -343,12 +343,12 @@ static const struct file_operations lirc_fops = { static int ir_lirc_register(struct rc_dev *dev) { - struct lirc_driver *drv; + struct lirc_dev *ldev; int rc = -ENOMEM; unsigned long features = 0; - drv = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL); - if (!drv) + ldev = kzalloc(sizeof(*ldev), GFP_KERNEL); + if (!ldev) return rc; if (dev->driver_type != RC_DRIVER_IR_RAW_TX) { @@ -380,29 +380,29 @@ static int ir_lirc_register(struct rc_dev *dev) if (dev->max_timeout) features |= LIRC_CAN_SET_REC_TIMEOUT; - snprintf(drv->name, sizeof(drv->name), "ir-lirc-codec (%s)", + snprintf(ldev->name, sizeof(ldev->name), "ir-lirc-codec (%s)", dev->driver_name); - drv->features = features; - drv->data = &dev->raw->lirc; - drv->rbuf = NULL; - drv->code_length = sizeof(struct ir_raw_event) * 8; - drv->chunk_size = sizeof(int); - drv->buffer_size = LIRCBUF_SIZE; - drv->fops = &lirc_fops; - drv->dev = &dev->dev; - drv->rdev = dev; - drv->owner = THIS_MODULE; - - rc = lirc_register_driver(drv); + ldev->features = features; + ldev->data = &dev->raw->lirc; + ldev->rbuf = NULL; + ldev->code_length = sizeof(struct ir_raw_event) * 8; + ldev->chunk_size = sizeof(int); + ldev->buffer_size = LIRCBUF_SIZE; + ldev->fops = &lirc_fops; + ldev->dev = &dev->dev; + ldev->rdev = dev; + ldev->owner = THIS_MODULE; + + rc = lirc_register_device(ldev); if (rc < 0) goto out; - dev->raw->lirc.drv = drv; + dev->raw->lirc.ldev = ldev; dev->raw->lirc.dev = dev; return 0; out: - kfree(drv); + kfree(ldev); return rc; } @@ -410,9 +410,9 @@ static int ir_lirc_unregister(struct rc_dev *dev) { struct lirc_codec *lirc = &dev->raw->lirc; - lirc_unregister_driver(lirc->drv); - kfree(lirc->drv); - lirc->drv = NULL; + lirc_unregister_device(lirc->ldev); + kfree(lirc->ldev); + lirc->ldev = NULL; return 0; } diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c index a2c5ed0181c1..e381a1c04bea 100644 --- a/drivers/media/rc/lirc_dev.c +++ b/drivers/media/rc/lirc_dev.c @@ -35,7 +35,7 @@ static dev_t lirc_base_dev; struct irctl { - struct lirc_driver d; + struct lirc_dev d; bool attached; int open; @@ -76,7 +76,7 @@ static void lirc_release(struct device *ld) static int lirc_allocate_buffer(struct irctl *ir) { int err = 0; - struct lirc_driver *d = &ir->d; + struct lirc_dev *d = &ir->d; if (d->rbuf) { ir->buf = d->rbuf; @@ -103,7 +103,7 @@ out: return err; } -int lirc_register_driver(struct lirc_driver *d) +int lirc_register_device(struct lirc_dev *d) { struct irctl *ir; int minor; @@ -204,9 +204,9 @@ int lirc_register_driver(struct lirc_driver *d) return 0; } -EXPORT_SYMBOL(lirc_register_driver); +EXPORT_SYMBOL(lirc_register_device); -void lirc_unregister_driver(struct lirc_driver *d) +void lirc_unregister_device(struct lirc_dev *d) { struct irctl *ir; @@ -234,7 +234,7 @@ void lirc_unregister_driver(struct lirc_driver *d) ida_simple_remove(&lirc_ida, d->minor); put_device(&ir->dev); } -EXPORT_SYMBOL(lirc_unregister_driver); +EXPORT_SYMBOL(lirc_unregister_device); int lirc_dev_fop_open(struct inode *inode, struct file *file) { diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h index 7da9c96cb058..ae4dd0c27731 100644 --- a/drivers/media/rc/rc-core-priv.h +++ b/drivers/media/rc/rc-core-priv.h @@ -106,7 +106,7 @@ struct ir_raw_event_ctrl { } mce_kbd; struct lirc_codec { struct rc_dev *dev; - struct lirc_driver *drv; + struct lirc_dev *ldev; int carrier_low; ktime_t gap_start; diff --git a/drivers/staging/media/lirc/lirc_zilog.c b/drivers/staging/media/lirc/lirc_zilog.c index 780b2d9f2f4b..0766e5029bd7 100644 --- a/drivers/staging/media/lirc/lirc_zilog.c +++ b/drivers/staging/media/lirc/lirc_zilog.c @@ -100,7 +100,7 @@ struct IR { struct list_head list; /* FIXME spinlock access to l.features */ - struct lirc_driver l; + struct lirc_dev l; struct lirc_buffer rbuf; struct mutex ir_lock; @@ -183,7 +183,7 @@ static void release_ir_device(struct kref *ref) * ir->open_count == 0 - happens on final close() * ir_lock, tx_ref_lock, rx_ref_lock, all released */ - lirc_unregister_driver(&ir->l); + lirc_unregister_device(&ir->l); if (kfifo_initialized(&ir->rbuf.fifo)) lirc_buffer_free(&ir->rbuf); @@ -1345,7 +1345,7 @@ static const struct file_operations lirc_fops = { .release = close }; -static struct lirc_driver lirc_template = { +static struct lirc_dev lirc_template = { .name = "lirc_zilog", .code_length = 13, .fops = &lirc_fops, @@ -1441,7 +1441,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) spin_lock_init(&ir->rx_ref_lock); /* set lirc_dev stuff */ - memcpy(&ir->l, &lirc_template, sizeof(struct lirc_driver)); + memcpy(&ir->l, &lirc_template, sizeof(struct lirc_dev)); /* * FIXME this is a pointer reference to us, but no refcount. * @@ -1559,10 +1559,10 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) } /* register with lirc */ - ret = lirc_register_driver(&ir->l); + ret = lirc_register_device(&ir->l); if (ret < 0) { dev_err(tx->ir->l.dev, - "%s: lirc_register_driver() failed: %i\n", + "%s: lirc_register_device() failed: %i\n", __func__, ret); goto out_put_xx; } diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h index 51c15c050e85..d16d6e0ef8da 100644 --- a/include/media/lirc_dev.h +++ b/include/media/lirc_dev.h @@ -111,54 +111,32 @@ static inline unsigned int lirc_buffer_write(struct lirc_buffer *buf, } /** - * struct lirc_driver - Defines the parameters on a LIRC driver - * - * @name: this string will be used for logs - * - * @minor: the minor device (/dev/lircX) number for a registered - * driver. - * - * @code_length: length of the remote control key code expressed in bits. + * struct lirc_dev - represents a LIRC device * + * @name: used for logging + * @minor: the minor device (/dev/lircX) number for the device + * @code_length: length of a remote control key code expressed in bits * @features: lirc compatible hardware features, like LIRC_MODE_RAW, * LIRC_CAN\_\*, as defined at include/media/lirc.h. - * * @buffer_size: Number of FIFO buffers with @chunk_size size. * Only used if @rbuf is NULL. - * * @chunk_size: Size of each FIFO buffer. * Only used if @rbuf is NULL. - * - * @data: it may point to any driver data and this pointer will - * be passed to all callback functions. - * + * @data: private per-driver data * @min_timeout: Minimum timeout for record. Valid only if * LIRC_CAN_SET_REC_TIMEOUT is defined. - * * @max_timeout: Maximum timeout for record. Valid only if * LIRC_CAN_SET_REC_TIMEOUT is defined. - * * @rbuf: if not NULL, it will be used as a read buffer, you will * have to write to the buffer by other means, like irq's * (see also lirc_serial.c). - * - * @rdev: Pointed to struct rc_dev associated with the LIRC - * device. - * - * @fops: file_operations for drivers which don't fit the current - * driver model. - * Some ioctl's can be directly handled by lirc_dev if the - * driver's ioctl function is NULL or if it returns - * -ENOIOCTLCMD (see also lirc_serial.c). - * - * @dev: pointer to the struct device associated with the LIRC - * device. - * + * @rdev: &struct rc_dev associated with the device + * @fops: &struct file_operations for the device + * @dev: &struct device assigned to the device * @owner: the module owning this struct - * - * @irctl: the struct irctl for this LIRC device. + * @irctl: &struct irctl assigned to the device */ -struct lirc_driver { +struct lirc_dev { char name[40]; unsigned int minor; __u32 code_length; @@ -183,14 +161,14 @@ struct lirc_driver { * returns negative value on error or zero * contents of the structure pointed by p is copied */ -int lirc_register_driver(struct lirc_driver *d); +int lirc_register_device(struct lirc_dev *d); -void lirc_unregister_driver(struct lirc_driver *d); +void lirc_unregister_device(struct lirc_dev *d); /* Must be called in the open fop before lirc_get_pdata() can be used */ void lirc_init_pdata(struct inode *inode, struct file *file); -/* Returns the private data stored in the lirc_driver +/* Returns the private data stored in the lirc_dev * associated with the given device file pointer. */ void *lirc_get_pdata(struct file *file); -- cgit v1.2.3 From 6ecccc379b7334c02f90a401dafea6fce5c91310 Mon Sep 17 00:00:00 2001 From: David Härdeman Date: Sun, 25 Jun 2017 09:32:15 -0300 Subject: [media] media: lirc_dev: introduce lirc_allocate_device and lirc_free_device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce two new functions so that the API for lirc_dev matches that of the rc-core and input subsystems. This means that lirc_dev structs are managed using the usual four functions: lirc_allocate_device lirc_free_device lirc_register_device lirc_unregister_device The functions are pretty simplistic at this point, later patches will put more flesh on the bones of both. Signed-off-by: David Härdeman Signed-off-by: Sean Young --- drivers/media/rc/ir-lirc-codec.c | 2 +- drivers/media/rc/lirc_dev.c | 13 +++++++++++++ include/media/lirc_dev.h | 9 ++++----- 3 files changed, 18 insertions(+), 6 deletions(-) (limited to 'include/media/lirc_dev.h') diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c index 2d591168c991..d5c155a5a547 100644 --- a/drivers/media/rc/ir-lirc-codec.c +++ b/drivers/media/rc/ir-lirc-codec.c @@ -347,7 +347,7 @@ static int ir_lirc_register(struct rc_dev *dev) int rc = -ENOMEM; unsigned long features = 0; - ldev = kzalloc(sizeof(*ldev), GFP_KERNEL); + ldev = lirc_allocate_device(); if (!ldev) return rc; diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c index e381a1c04bea..a6005f70de5a 100644 --- a/drivers/media/rc/lirc_dev.c +++ b/drivers/media/rc/lirc_dev.c @@ -103,6 +103,19 @@ out: return err; } +struct lirc_dev * +lirc_allocate_device(void) +{ + return kzalloc(sizeof(struct lirc_dev), GFP_KERNEL); +} +EXPORT_SYMBOL(lirc_allocate_device); + +void lirc_free_device(struct lirc_dev *d) +{ + kfree(d); +} +EXPORT_SYMBOL(lirc_free_device); + int lirc_register_device(struct lirc_dev *d) { struct irctl *ir; diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h index d16d6e0ef8da..4b0dc640e142 100644 --- a/include/media/lirc_dev.h +++ b/include/media/lirc_dev.h @@ -156,11 +156,10 @@ struct lirc_dev { struct irctl *irctl; }; -/* following functions can be called ONLY from user context - * - * returns negative value on error or zero - * contents of the structure pointed by p is copied - */ +struct lirc_dev *lirc_allocate_device(void); + +void lirc_free_device(struct lirc_dev *d); + int lirc_register_device(struct lirc_dev *d); void lirc_unregister_device(struct lirc_dev *d); -- cgit v1.2.3 From b15e39379fe8700fe0ec849a5c5ee2b44cd16381 Mon Sep 17 00:00:00 2001 From: David Härdeman Date: Sun, 25 Jun 2017 09:32:36 -0300 Subject: [media] media: lirc_dev: merge struct irctl into struct lirc_dev MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The use of two separate structs (lirc_dev aka lirc_driver and irctl) makes it much harder to follow the proper lifetime of the various structs and necessitates hacks such as keeping a copy of struct lirc_dev inside struct irctl. Merging the two structs means that lirc_dev can properly manage the lifetime of the resulting struct and simplifies the code at the same time. [mchehab@s-opensource.com: fix merge conflict] Signed-off-by: David Härdeman Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/ir-lirc-codec.c | 15 +- drivers/media/rc/lirc_dev.c | 314 ++++++++++++++------------------ drivers/staging/media/lirc/lirc_zilog.c | 20 +- include/media/lirc_dev.h | 26 ++- 4 files changed, 175 insertions(+), 200 deletions(-) (limited to 'include/media/lirc_dev.h') diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c index d5c155a5a547..bd046c41a53a 100644 --- a/drivers/media/rc/ir-lirc-codec.c +++ b/drivers/media/rc/ir-lirc-codec.c @@ -35,7 +35,7 @@ static int ir_lirc_decode(struct rc_dev *dev, struct ir_raw_event ev) struct lirc_codec *lirc = &dev->raw->lirc; int sample; - if (!dev->raw->lirc.ldev || !dev->raw->lirc.ldev->rbuf) + if (!dev->raw->lirc.ldev || !dev->raw->lirc.ldev->buf) return -EINVAL; /* Packet start */ @@ -84,7 +84,7 @@ static int ir_lirc_decode(struct rc_dev *dev, struct ir_raw_event ev) (u64)LIRC_VALUE_MASK); gap_sample = LIRC_SPACE(lirc->gap_duration); - lirc_buffer_write(dev->raw->lirc.ldev->rbuf, + lirc_buffer_write(dev->raw->lirc.ldev->buf, (unsigned char *)&gap_sample); lirc->gap = false; } @@ -95,9 +95,9 @@ static int ir_lirc_decode(struct rc_dev *dev, struct ir_raw_event ev) TO_US(ev.duration), TO_STR(ev.pulse)); } - lirc_buffer_write(dev->raw->lirc.ldev->rbuf, + lirc_buffer_write(dev->raw->lirc.ldev->buf, (unsigned char *) &sample); - wake_up(&dev->raw->lirc.ldev->rbuf->wait_poll); + wake_up(&dev->raw->lirc.ldev->buf->wait_poll); return 0; } @@ -384,12 +384,12 @@ static int ir_lirc_register(struct rc_dev *dev) dev->driver_name); ldev->features = features; ldev->data = &dev->raw->lirc; - ldev->rbuf = NULL; + ldev->buf = NULL; ldev->code_length = sizeof(struct ir_raw_event) * 8; ldev->chunk_size = sizeof(int); ldev->buffer_size = LIRCBUF_SIZE; ldev->fops = &lirc_fops; - ldev->dev = &dev->dev; + ldev->dev.parent = &dev->dev; ldev->rdev = dev; ldev->owner = THIS_MODULE; @@ -402,7 +402,7 @@ static int ir_lirc_register(struct rc_dev *dev) return 0; out: - kfree(ldev); + lirc_free_device(ldev); return rc; } @@ -411,7 +411,6 @@ static int ir_lirc_unregister(struct rc_dev *dev) struct lirc_codec *lirc = &dev->raw->lirc; lirc_unregister_device(lirc->ldev); - kfree(lirc->ldev); lirc->ldev = NULL; return 0; diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c index a6005f70de5a..e9dae8621670 100644 --- a/drivers/media/rc/lirc_dev.c +++ b/drivers/media/rc/lirc_dev.c @@ -34,19 +34,6 @@ static dev_t lirc_base_dev; -struct irctl { - struct lirc_dev d; - bool attached; - int open; - - struct mutex mutex; /* protect from simultaneous accesses */ - struct lirc_buffer *buf; - bool buf_internal; - - struct device dev; - struct cdev cdev; -}; - /* Used to keep track of allocated lirc devices */ #define LIRC_MAX_DEVICES 256 static DEFINE_IDA(lirc_ida); @@ -54,71 +41,74 @@ static DEFINE_IDA(lirc_ida); /* Only used for sysfs but defined to void otherwise */ static struct class *lirc_class; -static void lirc_free_buffer(struct irctl *ir) +static void lirc_release_device(struct device *ld) { - put_device(ir->dev.parent); - - if (ir->buf_internal) { - lirc_buffer_free(ir->buf); - kfree(ir->buf); - ir->buf = NULL; - } -} + struct lirc_dev *d = container_of(ld, struct lirc_dev, dev); -static void lirc_release(struct device *ld) -{ - struct irctl *ir = container_of(ld, struct irctl, dev); + put_device(d->dev.parent); - lirc_free_buffer(ir); - kfree(ir); + if (d->buf_internal) { + lirc_buffer_free(d->buf); + kfree(d->buf); + d->buf = NULL; + } + kfree(d); + module_put(THIS_MODULE); } -static int lirc_allocate_buffer(struct irctl *ir) +static int lirc_allocate_buffer(struct lirc_dev *d) { - int err = 0; - struct lirc_dev *d = &ir->d; + int err; - if (d->rbuf) { - ir->buf = d->rbuf; - ir->buf_internal = false; - } else { - ir->buf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL); - if (!ir->buf) { - err = -ENOMEM; - goto out; - } + if (d->buf) { + d->buf_internal = false; + return 0; + } - err = lirc_buffer_init(ir->buf, d->chunk_size, d->buffer_size); - if (err) { - kfree(ir->buf); - ir->buf = NULL; - goto out; - } + d->buf = kmalloc(sizeof(*d->buf), GFP_KERNEL); + if (!d->buf) + return -ENOMEM; - ir->buf_internal = true; - d->rbuf = ir->buf; + err = lirc_buffer_init(d->buf, d->chunk_size, d->buffer_size); + if (err) { + kfree(d->buf); + d->buf = NULL; + return err; } -out: - return err; + d->buf_internal = true; + return 0; } struct lirc_dev * lirc_allocate_device(void) { - return kzalloc(sizeof(struct lirc_dev), GFP_KERNEL); + struct lirc_dev *d; + + d = kzalloc(sizeof(*d), GFP_KERNEL); + if (d) { + mutex_init(&d->mutex); + device_initialize(&d->dev); + d->dev.class = lirc_class; + d->dev.release = lirc_release_device; + __module_get(THIS_MODULE); + } + + return d; } EXPORT_SYMBOL(lirc_allocate_device); void lirc_free_device(struct lirc_dev *d) { - kfree(d); + if (!d) + return; + + put_device(&d->dev); } EXPORT_SYMBOL(lirc_free_device); int lirc_register_device(struct lirc_dev *d) { - struct irctl *ir; int minor; int err; @@ -127,8 +117,8 @@ int lirc_register_device(struct lirc_dev *d) return -EBADRQC; } - if (!d->dev) { - pr_err("dev pointer not filled in!\n"); + if (!d->dev.parent) { + pr_err("dev parent pointer not filled in!\n"); return -EINVAL; } @@ -137,25 +127,25 @@ int lirc_register_device(struct lirc_dev *d) return -EINVAL; } - if (!d->rbuf && d->chunk_size < 1) { + if (!d->buf && d->chunk_size < 1) { pr_err("chunk_size must be set!\n"); return -EINVAL; } - if (!d->rbuf && d->buffer_size < 1) { + if (!d->buf && d->buffer_size < 1) { pr_err("buffer_size must be set!\n"); return -EINVAL; } if (d->code_length < 1 || d->code_length > (BUFLEN * 8)) { - dev_err(d->dev, "code length must be less than %d bits\n", - BUFLEN * 8); + dev_err(&d->dev, "code length must be less than %d bits\n", + BUFLEN * 8); return -EBADRQC; } - if (!d->rbuf && !(d->fops && d->fops->read && - d->fops->poll && d->fops->unlocked_ioctl)) { - dev_err(d->dev, "undefined read, poll, ioctl\n"); + if (!d->buf && !(d->fops && d->fops->read && + d->fops->poll && d->fops->unlocked_ioctl)) { + dev_err(&d->dev, "undefined read, poll, ioctl\n"); return -EBADRQC; } @@ -165,55 +155,34 @@ int lirc_register_device(struct lirc_dev *d) if (d->features == 0) d->features = LIRC_CAN_REC_LIRCCODE; - ir = kzalloc(sizeof(*ir), GFP_KERNEL); - if (!ir) - return -ENOMEM; - - mutex_init(&ir->mutex); - ir->d = *d; - if (LIRC_CAN_REC(d->features)) { - err = lirc_allocate_buffer(ir); - if (err) { - kfree(ir); + err = lirc_allocate_buffer(d); + if (err) return err; - } - d->rbuf = ir->buf; } minor = ida_simple_get(&lirc_ida, 0, LIRC_MAX_DEVICES, GFP_KERNEL); - if (minor < 0) { - lirc_free_buffer(ir); - kfree(ir); + if (minor < 0) return minor; - } - d->irctl = ir; d->minor = minor; - ir->d.minor = minor; - - device_initialize(&ir->dev); - ir->dev.devt = MKDEV(MAJOR(lirc_base_dev), ir->d.minor); - ir->dev.class = lirc_class; - ir->dev.parent = d->dev; - ir->dev.release = lirc_release; - dev_set_name(&ir->dev, "lirc%d", ir->d.minor); + d->dev.devt = MKDEV(MAJOR(lirc_base_dev), d->minor); + dev_set_name(&d->dev, "lirc%d", d->minor); - cdev_init(&ir->cdev, d->fops); - ir->cdev.owner = ir->d.owner; - ir->attached = true; + cdev_init(&d->cdev, d->fops); + d->cdev.owner = d->owner; + d->attached = true; - err = cdev_device_add(&ir->cdev, &ir->dev); + err = cdev_device_add(&d->cdev, &d->dev); if (err) { ida_simple_remove(&lirc_ida, minor); - put_device(&ir->dev); return err; } - get_device(ir->dev.parent); + get_device(d->dev.parent); - dev_info(ir->d.dev, "lirc_dev: driver %s registered at minor = %d\n", - ir->d.name, ir->d.minor); + dev_info(&d->dev, "lirc_dev: driver %s registered at minor = %d\n", + d->name, d->minor); return 0; } @@ -221,88 +190,83 @@ EXPORT_SYMBOL(lirc_register_device); void lirc_unregister_device(struct lirc_dev *d) { - struct irctl *ir; - - if (!d || !d->irctl) + if (!d) return; - ir = d->irctl; - - dev_dbg(ir->d.dev, "lirc_dev: driver %s unregistered from minor = %d\n", + dev_dbg(&d->dev, "lirc_dev: driver %s unregistered from minor = %d\n", d->name, d->minor); - cdev_device_del(&ir->cdev, &ir->dev); - - mutex_lock(&ir->mutex); + mutex_lock(&d->mutex); - ir->attached = false; - if (ir->open) { - dev_dbg(ir->d.dev, LOGHEAD "releasing opened driver\n", + d->attached = false; + if (d->open) { + dev_dbg(&d->dev, LOGHEAD "releasing opened driver\n", d->name, d->minor); - wake_up_interruptible(&ir->buf->wait_poll); + wake_up_interruptible(&d->buf->wait_poll); } - mutex_unlock(&ir->mutex); + mutex_unlock(&d->mutex); + cdev_device_del(&d->cdev, &d->dev); ida_simple_remove(&lirc_ida, d->minor); - put_device(&ir->dev); + put_device(&d->dev); } EXPORT_SYMBOL(lirc_unregister_device); int lirc_dev_fop_open(struct inode *inode, struct file *file) { - struct irctl *ir = container_of(inode->i_cdev, struct irctl, cdev); + struct lirc_dev *d = container_of(inode->i_cdev, struct lirc_dev, cdev); int retval; - dev_dbg(ir->d.dev, LOGHEAD "open called\n", ir->d.name, ir->d.minor); + dev_dbg(&d->dev, LOGHEAD "open called\n", d->name, d->minor); - retval = mutex_lock_interruptible(&ir->mutex); + retval = mutex_lock_interruptible(&d->mutex); if (retval) return retval; - if (!ir->attached) { + if (!d->attached) { retval = -ENODEV; goto out; } - if (ir->open) { + if (d->open) { retval = -EBUSY; goto out; } - if (ir->d.rdev) { - retval = rc_open(ir->d.rdev); + if (d->rdev) { + retval = rc_open(d->rdev); if (retval) goto out; } - if (ir->buf) - lirc_buffer_clear(ir->buf); + if (d->buf) + lirc_buffer_clear(d->buf); - ir->open++; + d->open++; lirc_init_pdata(inode, file); nonseekable_open(inode, file); - mutex_unlock(&ir->mutex); + mutex_unlock(&d->mutex); return 0; out: - mutex_unlock(&ir->mutex); + mutex_unlock(&d->mutex); return retval; } EXPORT_SYMBOL(lirc_dev_fop_open); int lirc_dev_fop_close(struct inode *inode, struct file *file) { - struct irctl *ir = file->private_data; + struct lirc_dev *d = file->private_data; - mutex_lock(&ir->mutex); + mutex_lock(&d->mutex); - rc_close(ir->d.rdev); - ir->open--; + rc_close(d->rdev); + d->open--; - mutex_unlock(&ir->mutex); + mutex_unlock(&d->mutex); return 0; } @@ -310,24 +274,24 @@ EXPORT_SYMBOL(lirc_dev_fop_close); unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait) { - struct irctl *ir = file->private_data; + struct lirc_dev *d = file->private_data; unsigned int ret; - if (!ir->attached) + if (!d->attached) return POLLHUP | POLLERR; - if (ir->buf) { - poll_wait(file, &ir->buf->wait_poll, wait); + if (d->buf) { + poll_wait(file, &d->buf->wait_poll, wait); - if (lirc_buffer_empty(ir->buf)) + if (lirc_buffer_empty(d->buf)) ret = 0; else ret = POLLIN | POLLRDNORM; - } else + } else { ret = POLLERR; + } - dev_dbg(ir->d.dev, LOGHEAD "poll result = %d\n", - ir->d.name, ir->d.minor, ret); + dev_dbg(&d->dev, LOGHEAD "poll result = %d\n", d->name, d->minor, ret); return ret; } @@ -335,44 +299,44 @@ EXPORT_SYMBOL(lirc_dev_fop_poll); long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - struct irctl *ir = file->private_data; + struct lirc_dev *d = file->private_data; __u32 mode; int result; - dev_dbg(ir->d.dev, LOGHEAD "ioctl called (0x%x)\n", - ir->d.name, ir->d.minor, cmd); + dev_dbg(&d->dev, LOGHEAD "ioctl called (0x%x)\n", + d->name, d->minor, cmd); - result = mutex_lock_interruptible(&ir->mutex); + result = mutex_lock_interruptible(&d->mutex); if (result) return result; - if (!ir->attached) { + if (!d->attached) { result = -ENODEV; goto out; } switch (cmd) { case LIRC_GET_FEATURES: - result = put_user(ir->d.features, (__u32 __user *)arg); + result = put_user(d->features, (__u32 __user *)arg); break; case LIRC_GET_REC_MODE: - if (!LIRC_CAN_REC(ir->d.features)) { + if (!LIRC_CAN_REC(d->features)) { result = -ENOTTY; break; } result = put_user(LIRC_REC2MODE - (ir->d.features & LIRC_CAN_REC_MASK), + (d->features & LIRC_CAN_REC_MASK), (__u32 __user *)arg); break; case LIRC_SET_REC_MODE: - if (!LIRC_CAN_REC(ir->d.features)) { + if (!LIRC_CAN_REC(d->features)) { result = -ENOTTY; break; } result = get_user(mode, (__u32 __user *)arg); - if (!result && !(LIRC_MODE2REC(mode) & ir->d.features)) + if (!result && !(LIRC_MODE2REC(mode) & d->features)) result = -EINVAL; /* * FIXME: We should actually set the mode somehow but @@ -380,32 +344,32 @@ long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) */ break; case LIRC_GET_LENGTH: - result = put_user(ir->d.code_length, (__u32 __user *)arg); + result = put_user(d->code_length, (__u32 __user *)arg); break; case LIRC_GET_MIN_TIMEOUT: - if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) || - ir->d.min_timeout == 0) { + if (!(d->features & LIRC_CAN_SET_REC_TIMEOUT) || + d->min_timeout == 0) { result = -ENOTTY; break; } - result = put_user(ir->d.min_timeout, (__u32 __user *)arg); + result = put_user(d->min_timeout, (__u32 __user *)arg); break; case LIRC_GET_MAX_TIMEOUT: - if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) || - ir->d.max_timeout == 0) { + if (!(d->features & LIRC_CAN_SET_REC_TIMEOUT) || + d->max_timeout == 0) { result = -ENOTTY; break; } - result = put_user(ir->d.max_timeout, (__u32 __user *)arg); + result = put_user(d->max_timeout, (__u32 __user *)arg); break; default: result = -ENOTTY; } out: - mutex_unlock(&ir->mutex); + mutex_unlock(&d->mutex); return result; } EXPORT_SYMBOL(lirc_dev_fop_ioctl); @@ -415,34 +379,34 @@ ssize_t lirc_dev_fop_read(struct file *file, size_t length, loff_t *ppos) { - struct irctl *ir = file->private_data; + struct lirc_dev *d = file->private_data; unsigned char *buf; int ret, written = 0; DECLARE_WAITQUEUE(wait, current); - dev_dbg(ir->d.dev, LOGHEAD "read called\n", ir->d.name, ir->d.minor); - - buf = kzalloc(ir->buf->chunk_size, GFP_KERNEL); + buf = kzalloc(d->buf->chunk_size, GFP_KERNEL); if (!buf) return -ENOMEM; - ret = mutex_lock_interruptible(&ir->mutex); + dev_dbg(&d->dev, LOGHEAD "read called\n", d->name, d->minor); + + ret = mutex_lock_interruptible(&d->mutex); if (ret) { kfree(buf); return ret; } - if (!ir->attached) { + if (!d->attached) { ret = -ENODEV; goto out_locked; } - if (!LIRC_CAN_REC(ir->d.features)) { + if (!LIRC_CAN_REC(d->features)) { ret = -EINVAL; goto out_locked; } - if (length % ir->buf->chunk_size) { + if (length % d->buf->chunk_size) { ret = -EINVAL; goto out_locked; } @@ -452,14 +416,14 @@ ssize_t lirc_dev_fop_read(struct file *file, * to avoid losing scan code (in case when queue is awaken somewhere * between while condition checking and scheduling) */ - add_wait_queue(&ir->buf->wait_poll, &wait); + add_wait_queue(&d->buf->wait_poll, &wait); /* * while we didn't provide 'length' bytes, device is opened in blocking * mode and 'copy_to_user' is happy, wait for data. */ while (written < length && ret == 0) { - if (lirc_buffer_empty(ir->buf)) { + if (lirc_buffer_empty(d->buf)) { /* According to the read(2) man page, 'written' can be * returned as less than 'length', instead of blocking * again, returning -EWOULDBLOCK, or returning @@ -476,36 +440,36 @@ ssize_t lirc_dev_fop_read(struct file *file, break; } - mutex_unlock(&ir->mutex); + mutex_unlock(&d->mutex); set_current_state(TASK_INTERRUPTIBLE); schedule(); set_current_state(TASK_RUNNING); - ret = mutex_lock_interruptible(&ir->mutex); + ret = mutex_lock_interruptible(&d->mutex); if (ret) { - remove_wait_queue(&ir->buf->wait_poll, &wait); + remove_wait_queue(&d->buf->wait_poll, &wait); goto out_unlocked; } - if (!ir->attached) { + if (!d->attached) { ret = -ENODEV; goto out_locked; } } else { - lirc_buffer_read(ir->buf, buf); + lirc_buffer_read(d->buf, buf); ret = copy_to_user((void __user *)buffer+written, buf, - ir->buf->chunk_size); + d->buf->chunk_size); if (!ret) - written += ir->buf->chunk_size; + written += d->buf->chunk_size; else ret = -EFAULT; } } - remove_wait_queue(&ir->buf->wait_poll, &wait); + remove_wait_queue(&d->buf->wait_poll, &wait); out_locked: - mutex_unlock(&ir->mutex); + mutex_unlock(&d->mutex); out_unlocked: kfree(buf); @@ -516,17 +480,17 @@ EXPORT_SYMBOL(lirc_dev_fop_read); void lirc_init_pdata(struct inode *inode, struct file *file) { - struct irctl *ir = container_of(inode->i_cdev, struct irctl, cdev); + struct lirc_dev *d = container_of(inode->i_cdev, struct lirc_dev, cdev); - file->private_data = ir; + file->private_data = d; } EXPORT_SYMBOL(lirc_init_pdata); void *lirc_get_pdata(struct file *file) { - struct irctl *ir = file->private_data; + struct lirc_dev *d = file->private_data; - return ir->d.data; + return d->data; } EXPORT_SYMBOL(lirc_get_pdata); diff --git a/drivers/staging/media/lirc/lirc_zilog.c b/drivers/staging/media/lirc/lirc_zilog.c index 00e8c8f224b7..6bd0717bf76e 100644 --- a/drivers/staging/media/lirc/lirc_zilog.c +++ b/drivers/staging/media/lirc/lirc_zilog.c @@ -184,10 +184,8 @@ static void release_ir_device(struct kref *ref) * ir->open_count == 0 - happens on final close() * ir_lock, tx_ref_lock, rx_ref_lock, all released */ - if (ir->l) { + if (ir->l) lirc_unregister_device(ir->l); - lirc_free_device(ir->l); - } if (kfifo_initialized(&ir->rbuf.fifo)) lirc_buffer_free(&ir->rbuf); @@ -318,7 +316,7 @@ static int add_to_buf(struct IR *ir) int ret; int failures = 0; unsigned char sendbuf[1] = { 0 }; - struct lirc_buffer *rbuf = ir->l->rbuf; + struct lirc_buffer *rbuf = ir->l->buf; struct IR_rx *rx; struct IR_tx *tx; @@ -464,7 +462,7 @@ static int add_to_buf(struct IR *ir) static int lirc_thread(void *arg) { struct IR *ir = arg; - struct lirc_buffer *rbuf = ir->l->rbuf; + struct lirc_buffer *rbuf = ir->l->buf; dev_dbg(ir->dev, "poll thread started\n"); @@ -885,7 +883,7 @@ static ssize_t read(struct file *filep, char __user *outbuf, size_t n, { struct IR *ir = lirc_get_pdata(filep); struct IR_rx *rx; - struct lirc_buffer *rbuf = ir->l->rbuf; + struct lirc_buffer *rbuf = ir->l->buf; int ret = 0, written = 0, retries = 0; unsigned int m; DECLARE_WAITQUEUE(wait, current); @@ -1203,7 +1201,7 @@ static unsigned int poll(struct file *filep, poll_table *wait) { struct IR *ir = lirc_get_pdata(filep); struct IR_rx *rx; - struct lirc_buffer *rbuf = ir->l->rbuf; + struct lirc_buffer *rbuf = ir->l->buf; unsigned int ret; dev_dbg(ir->dev, "%s called\n", __func__); @@ -1449,6 +1447,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) ir->l->code_length = 13; ir->l->fops = &lirc_fops; ir->l->owner = THIS_MODULE; + ir->l->dev.parent = &adap->dev; /* * FIXME this is a pointer reference to us, but no refcount. @@ -1456,13 +1455,12 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) * This OK for now, since lirc_dev currently won't touch this * buffer as we provide our own lirc_fops. * - * Currently our own lirc_fops rely on this ir->l->rbuf pointer + * Currently our own lirc_fops rely on this ir->l->buf pointer */ - ir->l->rbuf = &ir->rbuf; - ir->l->dev = &adap->dev; + ir->l->buf = &ir->rbuf; /* This will be returned by lirc_get_pdata() */ ir->l->data = ir; - ret = lirc_buffer_init(ir->l->rbuf, 2, BUFLEN / 2); + ret = lirc_buffer_init(ir->l->buf, 2, BUFLEN / 2); if (ret) { lirc_free_device(ir->l); ir->l = NULL; diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h index 4b0dc640e142..981dcabd5fd5 100644 --- a/include/media/lirc_dev.h +++ b/include/media/lirc_dev.h @@ -17,6 +17,8 @@ #include #include #include +#include +#include struct lirc_buffer { wait_queue_head_t wait_poll; @@ -127,14 +129,19 @@ static inline unsigned int lirc_buffer_write(struct lirc_buffer *buf, * LIRC_CAN_SET_REC_TIMEOUT is defined. * @max_timeout: Maximum timeout for record. Valid only if * LIRC_CAN_SET_REC_TIMEOUT is defined. - * @rbuf: if not NULL, it will be used as a read buffer, you will + * @buf: if %NULL, lirc_dev will allocate and manage the buffer, + * otherwise allocated by the caller which will * have to write to the buffer by other means, like irq's * (see also lirc_serial.c). + * @buf_internal: whether lirc_dev has allocated the read buffer or not * @rdev: &struct rc_dev associated with the device * @fops: &struct file_operations for the device - * @dev: &struct device assigned to the device * @owner: the module owning this struct - * @irctl: &struct irctl assigned to the device + * @attached: if the device is still live + * @open: open count for the device's chardev + * @mutex: serialises file_operations calls + * @dev: &struct device assigned to the device + * @cdev: &struct cdev assigned to the device */ struct lirc_dev { char name[40]; @@ -144,16 +151,23 @@ struct lirc_dev { unsigned int buffer_size; /* in chunks holding one code each */ unsigned int chunk_size; + struct lirc_buffer *buf; + bool buf_internal; void *data; int min_timeout; int max_timeout; - struct lirc_buffer *rbuf; struct rc_dev *rdev; const struct file_operations *fops; - struct device *dev; struct module *owner; - struct irctl *irctl; + + bool attached; + int open; + + struct mutex mutex; /* protect from simultaneous accesses */ + + struct device dev; + struct cdev cdev; }; struct lirc_dev *lirc_allocate_device(void); -- cgit v1.2.3 From 2265425fd9c512cc9977516b5fe78d03ad9311a7 Mon Sep 17 00:00:00 2001 From: David Härdeman Date: Sun, 25 Jun 2017 08:31:30 -0400 Subject: media: lirc_dev: remove min_timeout and max_timeout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are no users of this functionality (ir-lirc-codec.c has its own implementation and lirc_zilog.c doesn't use it) so remove it. This only affects users of the lirc kapi, not rc-core drivers. Signed-off-by: David Härdeman Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/lirc_dev.c | 18 ------------------ include/media/lirc_dev.h | 6 ------ 2 files changed, 24 deletions(-) (limited to 'include/media/lirc_dev.h') diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c index e9dae8621670..e16d1138ca48 100644 --- a/drivers/media/rc/lirc_dev.c +++ b/drivers/media/rc/lirc_dev.c @@ -346,24 +346,6 @@ long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case LIRC_GET_LENGTH: result = put_user(d->code_length, (__u32 __user *)arg); break; - case LIRC_GET_MIN_TIMEOUT: - if (!(d->features & LIRC_CAN_SET_REC_TIMEOUT) || - d->min_timeout == 0) { - result = -ENOTTY; - break; - } - - result = put_user(d->min_timeout, (__u32 __user *)arg); - break; - case LIRC_GET_MAX_TIMEOUT: - if (!(d->features & LIRC_CAN_SET_REC_TIMEOUT) || - d->max_timeout == 0) { - result = -ENOTTY; - break; - } - - result = put_user(d->max_timeout, (__u32 __user *)arg); - break; default: result = -ENOTTY; } diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h index 981dcabd5fd5..857da67bd931 100644 --- a/include/media/lirc_dev.h +++ b/include/media/lirc_dev.h @@ -125,10 +125,6 @@ static inline unsigned int lirc_buffer_write(struct lirc_buffer *buf, * @chunk_size: Size of each FIFO buffer. * Only used if @rbuf is NULL. * @data: private per-driver data - * @min_timeout: Minimum timeout for record. Valid only if - * LIRC_CAN_SET_REC_TIMEOUT is defined. - * @max_timeout: Maximum timeout for record. Valid only if - * LIRC_CAN_SET_REC_TIMEOUT is defined. * @buf: if %NULL, lirc_dev will allocate and manage the buffer, * otherwise allocated by the caller which will * have to write to the buffer by other means, like irq's @@ -155,8 +151,6 @@ struct lirc_dev { bool buf_internal; void *data; - int min_timeout; - int max_timeout; struct rc_dev *rdev; const struct file_operations *fops; struct module *owner; -- cgit v1.2.3