linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/16] lirc_dev spring cleaning
@ 2017-05-01 16:03 David Härdeman
  2017-05-01 16:03 ` [PATCH 01/16] lirc_dev: remove pointless functions David Härdeman
                   ` (15 more replies)
  0 siblings, 16 replies; 28+ messages in thread
From: David Härdeman @ 2017-05-01 16:03 UTC (permalink / raw)
  To: linux-media; +Cc: mchehab, sean

lirc_dev has lots of functionality which is unused and the code isn't exactly
up-to-date with current kernel practices. This patchset removes the unused bits
and also simplifies the locking by moving lirc_dev over to only use
per-device mutexes rather than a big lirc lock in addition to per-device locks.

I think this is about as much as can be done right now before lirc_zilog is
either removed or ported to rc-core.

---

David Härdeman (16):
      lirc_dev: remove pointless functions
      lirc_dev: remove unused set_use_inc/set_use_dec
      lirc_dev: correct error handling
      lirc_dev: remove sampling kthread
      lirc_dev: clarify error handling
      lirc_dev: make fops mandatory
      lirc_dev: merge lirc_register_driver() and lirc_allocate_driver()
      lirc_zilog: remove module parameter minor
      lirc_dev: remove lirc_irctl_init() and lirc_cdev_add()
      lirc_dev: remove superfluous get/put_device() calls
      lirc_dev: remove unused module parameter
      lirc_dev: return POLLHUP and POLLERR when device is gone
      lirc_dev: use an ida instead of a hand-rolled array to keep track of minors
      lirc_dev: cleanup includes
      lirc_dev: remove name from struct lirc_driver
      lirc_dev: cleanup header


 drivers/media/rc/ir-lirc-codec.c        |   23 -
 drivers/media/rc/lirc_dev.c             |  516 ++++++++-----------------------
 drivers/staging/media/lirc/lirc_zilog.c |   33 --
 include/media/lirc_dev.h                |   53 ---
 4 files changed, 149 insertions(+), 476 deletions(-)

--
David Härdeman

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH 01/16] lirc_dev: remove pointless functions
  2017-05-01 16:03 [PATCH 00/16] lirc_dev spring cleaning David Härdeman
@ 2017-05-01 16:03 ` David Härdeman
  2017-05-01 16:03 ` [PATCH 02/16] lirc_dev: remove unused set_use_inc/set_use_dec David Härdeman
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 28+ messages in thread
From: David Härdeman @ 2017-05-01 16:03 UTC (permalink / raw)
  To: linux-media; +Cc: mchehab, sean

drv->set_use_inc and drv->set_use_dec are already optional so we can remove all
dummy functions.

Signed-off-by: David Härdeman <david@hardeman.nu>
---
 drivers/media/rc/ir-lirc-codec.c        |   14 ++------------
 drivers/staging/media/lirc/lirc_zilog.c |   11 -----------
 2 files changed, 2 insertions(+), 23 deletions(-)

diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c
index 8f0669c9894c..fc58745b26b8 100644
--- a/drivers/media/rc/ir-lirc-codec.c
+++ b/drivers/media/rc/ir-lirc-codec.c
@@ -327,16 +327,6 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
 	return ret;
 }
 
-static int ir_lirc_open(void *data)
-{
-	return 0;
-}
-
-static void ir_lirc_close(void *data)
-{
-	return;
-}
-
 static const struct file_operations lirc_fops = {
 	.owner		= THIS_MODULE,
 	.write		= ir_lirc_transmit_ir,
@@ -396,8 +386,8 @@ static int ir_lirc_register(struct rc_dev *dev)
 	drv->features = features;
 	drv->data = &dev->raw->lirc;
 	drv->rbuf = NULL;
-	drv->set_use_inc = &ir_lirc_open;
-	drv->set_use_dec = &ir_lirc_close;
+	drv->set_use_inc = NULL;
+	drv->set_use_dec = NULL;
 	drv->code_length = sizeof(struct ir_raw_event) * 8;
 	drv->chunk_size = sizeof(int);
 	drv->buffer_size = LIRCBUF_SIZE;
diff --git a/drivers/staging/media/lirc/lirc_zilog.c b/drivers/staging/media/lirc/lirc_zilog.c
index e4a533b6beb3..436cf1b6a70a 100644
--- a/drivers/staging/media/lirc/lirc_zilog.c
+++ b/drivers/staging/media/lirc/lirc_zilog.c
@@ -497,15 +497,6 @@ static int lirc_thread(void *arg)
 	return 0;
 }
 
-static int set_use_inc(void *data)
-{
-	return 0;
-}
-
-static void set_use_dec(void *data)
-{
-}
-
 /* safe read of a uint32 (always network byte order) */
 static int read_uint32(unsigned char **data,
 				     unsigned char *endp, unsigned int *val)
@@ -1396,8 +1387,6 @@ static struct lirc_driver lirc_template = {
 	.buffer_size	= BUFLEN / 2,
 	.sample_rate	= 0, /* tell lirc_dev to not start its own kthread */
 	.chunk_size	= 2,
-	.set_use_inc	= set_use_inc,
-	.set_use_dec	= set_use_dec,
 	.fops		= &lirc_fops,
 	.owner		= THIS_MODULE,
 };

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 02/16] lirc_dev: remove unused set_use_inc/set_use_dec
  2017-05-01 16:03 [PATCH 00/16] lirc_dev spring cleaning David Härdeman
  2017-05-01 16:03 ` [PATCH 01/16] lirc_dev: remove pointless functions David Härdeman
@ 2017-05-01 16:03 ` David Härdeman
  2017-05-01 16:03 ` [PATCH 03/16] lirc_dev: correct error handling David Härdeman
                   ` (13 subsequent siblings)
  15 siblings, 0 replies; 28+ messages in thread
From: David Härdeman @ 2017-05-01 16:03 UTC (permalink / raw)
  To: linux-media; +Cc: mchehab, sean

Since there are no users of this functionality, it can be removed altogether.

Signed-off-by: David Härdeman <david@hardeman.nu>
---
 drivers/media/rc/ir-lirc-codec.c |    2 --
 drivers/media/rc/lirc_dev.c      |   24 ++++++------------------
 include/media/lirc_dev.h         |    6 ------
 3 files changed, 6 insertions(+), 26 deletions(-)

diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c
index fc58745b26b8..a30af91710fe 100644
--- a/drivers/media/rc/ir-lirc-codec.c
+++ b/drivers/media/rc/ir-lirc-codec.c
@@ -386,8 +386,6 @@ static int ir_lirc_register(struct rc_dev *dev)
 	drv->features = features;
 	drv->data = &dev->raw->lirc;
 	drv->rbuf = NULL;
-	drv->set_use_inc = NULL;
-	drv->set_use_dec = NULL;
 	drv->code_length = sizeof(struct ir_raw_event) * 8;
 	drv->chunk_size = sizeof(int);
 	drv->buffer_size = LIRCBUF_SIZE;
diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
index 42704552b005..05f600bd6c67 100644
--- a/drivers/media/rc/lirc_dev.c
+++ b/drivers/media/rc/lirc_dev.c
@@ -418,12 +418,6 @@ int lirc_unregister_driver(int minor)
 		wake_up_interruptible(&ir->buf->wait_poll);
 	}
 
-	mutex_lock(&ir->irctl_lock);
-
-	if (ir->d.set_use_dec)
-		ir->d.set_use_dec(ir->d.data);
-
-	mutex_unlock(&ir->irctl_lock);
 	mutex_unlock(&lirc_dev_lock);
 
 	device_del(&ir->dev);
@@ -473,17 +467,13 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file)
 			goto error;
 	}
 
+	if (ir->buf)
+		lirc_buffer_clear(ir->buf);
+
+	if (ir->task)
+		wake_up_process(ir->task);
+
 	ir->open++;
-	if (ir->d.set_use_inc)
-		retval = ir->d.set_use_inc(ir->d.data);
-	if (retval) {
-		ir->open--;
-	} else {
-		if (ir->buf)
-			lirc_buffer_clear(ir->buf);
-		if (ir->task)
-			wake_up_process(ir->task);
-	}
 
 error:
 	nonseekable_open(inode, file);
@@ -508,8 +498,6 @@ int lirc_dev_fop_close(struct inode *inode, struct file *file)
 	rc_close(ir->d.rdev);
 
 	ir->open--;
-	if (ir->d.set_use_dec)
-		ir->d.set_use_dec(ir->d.data);
 	if (!ret)
 		mutex_unlock(&lirc_dev_lock);
 
diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h
index cec7d35602d1..71c1c11950fe 100644
--- a/include/media/lirc_dev.h
+++ b/include/media/lirc_dev.h
@@ -165,10 +165,6 @@ static inline unsigned int lirc_buffer_write(struct lirc_buffer *buf,
  *			have to write to the buffer by other means, like irq's
  *			(see also lirc_serial.c).
  *
- * @set_use_inc:	set_use_inc will be called after device is opened
- *
- * @set_use_dec:	set_use_dec will be called after device is closed
- *
  * @rdev:		Pointed to struct rc_dev associated with the LIRC
  *			device.
  *
@@ -198,8 +194,6 @@ struct lirc_driver {
 	int max_timeout;
 	int (*add_to_buf)(void *data, struct lirc_buffer *buf);
 	struct lirc_buffer *rbuf;
-	int (*set_use_inc)(void *data);
-	void (*set_use_dec)(void *data);
 	struct rc_dev *rdev;
 	const struct file_operations *fops;
 	struct device *dev;

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 03/16] lirc_dev: correct error handling
  2017-05-01 16:03 [PATCH 00/16] lirc_dev spring cleaning David Härdeman
  2017-05-01 16:03 ` [PATCH 01/16] lirc_dev: remove pointless functions David Härdeman
  2017-05-01 16:03 ` [PATCH 02/16] lirc_dev: remove unused set_use_inc/set_use_dec David Härdeman
@ 2017-05-01 16:03 ` David Härdeman
  2017-05-21  8:57   ` Sean Young
  2017-05-01 16:03 ` [PATCH 04/16] lirc_dev: remove sampling kthread David Härdeman
                   ` (12 subsequent siblings)
  15 siblings, 1 reply; 28+ messages in thread
From: David Härdeman @ 2017-05-01 16:03 UTC (permalink / raw)
  To: linux-media; +Cc: mchehab, sean

If an error is generated, nonseekable_open() shouldn't be called.

Signed-off-by: David Härdeman <david@hardeman.nu>
---
 drivers/media/rc/lirc_dev.c |    6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
index 05f600bd6c67..7f13ed479e1c 100644
--- a/drivers/media/rc/lirc_dev.c
+++ b/drivers/media/rc/lirc_dev.c
@@ -431,7 +431,7 @@ EXPORT_SYMBOL(lirc_unregister_driver);
 int lirc_dev_fop_open(struct inode *inode, struct file *file)
 {
 	struct irctl *ir;
-	int retval = 0;
+	int retval;
 
 	if (iminor(inode) >= MAX_IRCTL_DEVICES) {
 		pr_err("open result for %d is -ENODEV\n", iminor(inode));
@@ -475,9 +475,11 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file)
 
 	ir->open++;
 
-error:
 	nonseekable_open(inode, file);
 
+	return 0;
+
+error:
 	return retval;
 }
 EXPORT_SYMBOL(lirc_dev_fop_open);

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 04/16] lirc_dev: remove sampling kthread
  2017-05-01 16:03 [PATCH 00/16] lirc_dev spring cleaning David Härdeman
                   ` (2 preceding siblings ...)
  2017-05-01 16:03 ` [PATCH 03/16] lirc_dev: correct error handling David Härdeman
@ 2017-05-01 16:03 ` David Härdeman
  2017-05-01 16:04 ` [PATCH 05/16] lirc_dev: clarify error handling David Härdeman
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 28+ messages in thread
From: David Härdeman @ 2017-05-01 16:03 UTC (permalink / raw)
  To: linux-media; +Cc: mchehab, sean

There are no drivers which use this functionality.

Signed-off-by: David Härdeman <david@hardeman.nu>
---
 drivers/media/rc/lirc_dev.c             |   94 +------------------------------
 drivers/staging/media/lirc/lirc_zilog.c |    1 
 include/media/lirc_dev.h                |   16 -----
 3 files changed, 2 insertions(+), 109 deletions(-)

diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
index 7f13ed479e1c..5c2b009b6d50 100644
--- a/drivers/media/rc/lirc_dev.c
+++ b/drivers/media/rc/lirc_dev.c
@@ -28,7 +28,6 @@
 #include <linux/mutex.h>
 #include <linux/wait.h>
 #include <linux/unistd.h>
-#include <linux/kthread.h>
 #include <linux/bitops.h>
 #include <linux/device.h>
 #include <linux/cdev.h>
@@ -57,9 +56,6 @@ struct irctl {
 
 	struct device dev;
 	struct cdev cdev;
-
-	struct task_struct *task;
-	long jiffies_to_wait;
 };
 
 static DEFINE_MUTEX(lirc_dev_lock);
@@ -95,59 +91,6 @@ static void lirc_release(struct device *ld)
 	kfree(ir);
 }
 
-/*  helper function
- *  reads key codes from driver and puts them into buffer
- *  returns 0 on success
- */
-static int lirc_add_to_buf(struct irctl *ir)
-{
-	int res;
-	int got_data = -1;
-
-	if (!ir->d.add_to_buf)
-		return 0;
-
-	/*
-	 * service the device as long as it is returning
-	 * data and we have space
-	 */
-	do {
-		got_data++;
-		res = ir->d.add_to_buf(ir->d.data, ir->buf);
-	} while (!res);
-
-	if (res == -ENODEV)
-		kthread_stop(ir->task);
-
-	return got_data ? 0 : res;
-}
-
-/* main function of the polling thread
- */
-static int lirc_thread(void *irctl)
-{
-	struct irctl *ir = irctl;
-
-	do {
-		if (ir->open) {
-			if (ir->jiffies_to_wait) {
-				set_current_state(TASK_INTERRUPTIBLE);
-				schedule_timeout(ir->jiffies_to_wait);
-			}
-			if (kthread_should_stop())
-				break;
-			if (!lirc_add_to_buf(ir))
-				wake_up_interruptible(&ir->buf->wait_poll);
-		} else {
-			set_current_state(TASK_INTERRUPTIBLE);
-			schedule();
-		}
-	} while (!kthread_should_stop());
-
-	return 0;
-}
-
-
 static const struct file_operations lirc_dev_fops = {
 	.owner		= THIS_MODULE,
 	.read		= lirc_dev_fop_read,
@@ -252,18 +195,8 @@ static int lirc_allocate_driver(struct lirc_driver *d)
 		return -EBADRQC;
 	}
 
-	if (d->sample_rate) {
-		if (2 > d->sample_rate || HZ < d->sample_rate) {
-			dev_err(d->dev, "invalid %d sample rate\n",
-							d->sample_rate);
-			return -EBADRQC;
-		}
-		if (!d->add_to_buf) {
-			dev_err(d->dev, "add_to_buf not set\n");
-			return -EBADRQC;
-		}
-	} else if (!d->rbuf && !(d->fops && d->fops->read &&
-				d->fops->poll && d->fops->unlocked_ioctl)) {
+	if (!d->rbuf && !(d->fops && d->fops->read &&
+			  d->fops->poll && d->fops->unlocked_ioctl)) {
 		dev_err(d->dev, "undefined read, poll, ioctl\n");
 		return -EBADRQC;
 	}
@@ -312,22 +245,6 @@ static int lirc_allocate_driver(struct lirc_driver *d)
 	dev_set_name(&ir->dev, "lirc%d", ir->d.minor);
 	device_initialize(&ir->dev);
 
-	if (d->sample_rate) {
-		ir->jiffies_to_wait = HZ / d->sample_rate;
-
-		/* try to fire up polling thread */
-		ir->task = kthread_run(lirc_thread, (void *)ir, "lirc_dev");
-		if (IS_ERR(ir->task)) {
-			dev_err(d->dev, "cannot run thread for minor = %d\n",
-								d->minor);
-			err = -ECHILD;
-			goto out_sysfs;
-		}
-	} else {
-		/* it means - wait for external event in task queue */
-		ir->jiffies_to_wait = 0;
-	}
-
 	err = lirc_cdev_add(ir);
 	if (err)
 		goto out_sysfs;
@@ -404,10 +321,6 @@ int lirc_unregister_driver(int minor)
 		return -ENOENT;
 	}
 
-	/* end up polling thread */
-	if (ir->task)
-		kthread_stop(ir->task);
-
 	dev_dbg(ir->d.dev, "lirc_dev: driver %s unregistered from minor = %d\n",
 		ir->d.name, ir->d.minor);
 
@@ -470,9 +383,6 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file)
 	if (ir->buf)
 		lirc_buffer_clear(ir->buf);
 
-	if (ir->task)
-		wake_up_process(ir->task);
-
 	ir->open++;
 
 	nonseekable_open(inode, file);
diff --git a/drivers/staging/media/lirc/lirc_zilog.c b/drivers/staging/media/lirc/lirc_zilog.c
index 436cf1b6a70a..8d8fd8b164e2 100644
--- a/drivers/staging/media/lirc/lirc_zilog.c
+++ b/drivers/staging/media/lirc/lirc_zilog.c
@@ -1385,7 +1385,6 @@ static struct lirc_driver lirc_template = {
 	.minor		= -1,
 	.code_length	= 13,
 	.buffer_size	= BUFLEN / 2,
-	.sample_rate	= 0, /* tell lirc_dev to not start its own kthread */
 	.chunk_size	= 2,
 	.fops		= &lirc_fops,
 	.owner		= THIS_MODULE,
diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h
index 71c1c11950fe..01649b009922 100644
--- a/include/media/lirc_dev.h
+++ b/include/media/lirc_dev.h
@@ -133,12 +133,6 @@ static inline unsigned int lirc_buffer_write(struct lirc_buffer *buf,
  * @buffer_size:	Number of FIFO buffers with @chunk_size size. If zero,
  *			creates a buffer with BUFLEN size (16 bytes).
  *
- * @sample_rate:	if zero, the device will wait for an event with a new
- *			code to be parsed. Otherwise, specifies the sample
- *			rate for polling. Value should be between 0
- *			and HZ. If equal to HZ, it would mean one polling per
- *			second.
- *
  * @features:		lirc compatible hardware features, like LIRC_MODE_RAW,
  *			LIRC_CAN\_\*, as defined at include/media/lirc.h.
  *
@@ -153,14 +147,6 @@ static inline unsigned int lirc_buffer_write(struct lirc_buffer *buf,
  * @max_timeout:	Maximum timeout for record. Valid only if
  *			LIRC_CAN_SET_REC_TIMEOUT is defined.
  *
- * @add_to_buf:		add_to_buf will be called after specified period of the
- *			time or triggered by the external event, this behavior
- *			depends on value of the sample_rate this function will
- *			be called in user context. This routine should return
- *			0 if data was added to the buffer and -ENODATA if none
- *			was available. This should add some number of bits
- *			evenly divisible by code_length to the buffer.
- *
  * @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).
@@ -184,7 +170,6 @@ struct lirc_driver {
 	int minor;
 	__u32 code_length;
 	unsigned int buffer_size; /* in chunks holding one code each */
-	int sample_rate;
 	__u32 features;
 
 	unsigned int chunk_size;
@@ -192,7 +177,6 @@ struct lirc_driver {
 	void *data;
 	int min_timeout;
 	int max_timeout;
-	int (*add_to_buf)(void *data, struct lirc_buffer *buf);
 	struct lirc_buffer *rbuf;
 	struct rc_dev *rdev;
 	const struct file_operations *fops;

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 05/16] lirc_dev: clarify error handling
  2017-05-01 16:03 [PATCH 00/16] lirc_dev spring cleaning David Härdeman
                   ` (3 preceding siblings ...)
  2017-05-01 16:03 ` [PATCH 04/16] lirc_dev: remove sampling kthread David Härdeman
@ 2017-05-01 16:04 ` David Härdeman
  2017-05-01 16:04 ` [PATCH 06/16] lirc_dev: make fops mandatory David Härdeman
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 28+ messages in thread
From: David Härdeman @ 2017-05-01 16:04 UTC (permalink / raw)
  To: linux-media; +Cc: mchehab, sean

out_sysfs is misleading, sysfs only comes into play after device_add(). Also,
calling device_init() before the rest of struct dev is filled out is clearer.

Signed-off-by: David Härdeman <david@hardeman.nu>
---
 drivers/media/rc/lirc_dev.c |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
index 5c2b009b6d50..fb487c39b834 100644
--- a/drivers/media/rc/lirc_dev.c
+++ b/drivers/media/rc/lirc_dev.c
@@ -238,16 +238,16 @@ static int lirc_allocate_driver(struct lirc_driver *d)
 
 	ir->d = *d;
 
+	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);
-	device_initialize(&ir->dev);
 
 	err = lirc_cdev_add(ir);
 	if (err)
-		goto out_sysfs;
+		goto out_free_dev;
 
 	ir->attached = 1;
 
@@ -264,7 +264,7 @@ static int lirc_allocate_driver(struct lirc_driver *d)
 	return minor;
 out_cdev:
 	cdev_del(&ir->cdev);
-out_sysfs:
+out_free_dev:
 	put_device(&ir->dev);
 out_lock:
 	mutex_unlock(&lirc_dev_lock);

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 06/16] lirc_dev: make fops mandatory
  2017-05-01 16:03 [PATCH 00/16] lirc_dev spring cleaning David Härdeman
                   ` (4 preceding siblings ...)
  2017-05-01 16:04 ` [PATCH 05/16] lirc_dev: clarify error handling David Härdeman
@ 2017-05-01 16:04 ` David Härdeman
  2017-05-01 16:04 ` [PATCH 07/16] lirc_dev: merge lirc_register_driver() and lirc_allocate_driver() David Härdeman
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 28+ messages in thread
From: David Härdeman @ 2017-05-01 16:04 UTC (permalink / raw)
  To: linux-media; +Cc: mchehab, sean

Every caller of lirc_register_driver() passes their own fops and there are no
users of lirc_dev_fop_write() in the kernel tree. Thus we can make fops
mandatory and remove lirc_dev_fop_write().

Signed-off-by: David Härdeman <david@hardeman.nu>
---
 drivers/media/rc/lirc_dev.c |   41 +++++------------------------------------
 include/media/lirc_dev.h    |    3 ---
 2 files changed, 5 insertions(+), 39 deletions(-)

diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
index fb487c39b834..29eecddbd371 100644
--- a/drivers/media/rc/lirc_dev.c
+++ b/drivers/media/rc/lirc_dev.c
@@ -91,17 +91,6 @@ static void lirc_release(struct device *ld)
 	kfree(ir);
 }
 
-static const struct file_operations lirc_dev_fops = {
-	.owner		= THIS_MODULE,
-	.read		= lirc_dev_fop_read,
-	.write		= lirc_dev_fop_write,
-	.poll		= lirc_dev_fop_poll,
-	.unlocked_ioctl	= lirc_dev_fop_ioctl,
-	.open		= lirc_dev_fop_open,
-	.release	= lirc_dev_fop_close,
-	.llseek		= noop_llseek,
-};
-
 static int lirc_cdev_add(struct irctl *ir)
 {
 	struct lirc_driver *d = &ir->d;
@@ -110,13 +99,11 @@ static int lirc_cdev_add(struct irctl *ir)
 
 	cdev = &ir->cdev;
 
-	if (d->fops) {
-		cdev_init(cdev, d->fops);
-		cdev->owner = d->owner;
-	} else {
-		cdev_init(cdev, &lirc_dev_fops);
-		cdev->owner = THIS_MODULE;
-	}
+	if (!d->fops)
+		return -EINVAL;
+
+	cdev_init(cdev, d->fops);
+	cdev->owner = d->owner;
 	retval = kobject_set_name(&cdev->kobj, "lirc%d", d->minor);
 	if (retval)
 		return retval;
@@ -640,24 +627,6 @@ void *lirc_get_pdata(struct file *file)
 EXPORT_SYMBOL(lirc_get_pdata);
 
 
-ssize_t lirc_dev_fop_write(struct file *file, const char __user *buffer,
-			   size_t length, loff_t *ppos)
-{
-	struct irctl *ir = irctls[iminor(file_inode(file))];
-
-	if (!ir) {
-		pr_err("called with invalid irctl\n");
-		return -ENODEV;
-	}
-
-	if (!ir->attached)
-		return -ENODEV;
-
-	return -EINVAL;
-}
-EXPORT_SYMBOL(lirc_dev_fop_write);
-
-
 static int __init lirc_dev_init(void)
 {
 	int retval;
diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h
index 01649b009922..1f327e25a9be 100644
--- a/include/media/lirc_dev.h
+++ b/include/media/lirc_dev.h
@@ -210,7 +210,4 @@ unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait);
 long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
 ssize_t lirc_dev_fop_read(struct file *file, char __user *buffer, size_t length,
 			  loff_t *ppos);
-ssize_t lirc_dev_fop_write(struct file *file, const char __user *buffer,
-			   size_t length, loff_t *ppos);
-
 #endif

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 07/16] lirc_dev: merge lirc_register_driver() and lirc_allocate_driver()
  2017-05-01 16:03 [PATCH 00/16] lirc_dev spring cleaning David Härdeman
                   ` (5 preceding siblings ...)
  2017-05-01 16:04 ` [PATCH 06/16] lirc_dev: make fops mandatory David Härdeman
@ 2017-05-01 16:04 ` David Härdeman
  2017-05-01 16:04 ` [PATCH 08/16] lirc_zilog: remove module parameter minor David Härdeman
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 28+ messages in thread
From: David Härdeman @ 2017-05-01 16:04 UTC (permalink / raw)
  To: linux-media; +Cc: mchehab, sean

Merging the two means that lirc_allocate_buffer() is called before device_add()
and cdev_add() which makes more sense. This also simplifies the locking
slightly because lirc_allocate_buffer() will always be called with lirc_dev_lock
held.

Signed-off-by: David Härdeman <david@hardeman.nu>
---
 drivers/media/rc/lirc_dev.c |   41 +++++++++++++----------------------------
 1 file changed, 13 insertions(+), 28 deletions(-)

diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
index 29eecddbd371..fcc88a09b108 100644
--- a/drivers/media/rc/lirc_dev.c
+++ b/drivers/media/rc/lirc_dev.c
@@ -120,8 +120,6 @@ static int lirc_allocate_buffer(struct irctl *ir)
 	unsigned int buffer_size;
 	struct lirc_driver *d = &ir->d;
 
-	mutex_lock(&lirc_dev_lock);
-
 	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;
@@ -145,16 +143,15 @@ static int lirc_allocate_buffer(struct irctl *ir)
 		}
 
 		ir->buf_internal = true;
+		d->rbuf = ir->buf;
 	}
 	ir->chunk_size = ir->buf->chunk_size;
 
 out:
-	mutex_unlock(&lirc_dev_lock);
-
 	return err;
 }
 
-static int lirc_allocate_driver(struct lirc_driver *d)
+int lirc_register_driver(struct lirc_driver *d)
 {
 	struct irctl *ir;
 	int minor;
@@ -225,6 +222,15 @@ static int lirc_allocate_driver(struct lirc_driver *d)
 
 	ir->d = *d;
 
+	if (LIRC_CAN_REC(d->features)) {
+		err = lirc_allocate_buffer(irctls[minor]);
+		if (err) {
+			kfree(ir);
+			goto out_lock;
+		}
+		d->rbuf = ir->buf;
+	}
+
 	device_initialize(&ir->dev);
 	ir->dev.devt = MKDEV(MAJOR(lirc_base_dev), ir->d.minor);
 	ir->dev.class = lirc_class;
@@ -248,7 +254,9 @@ static int lirc_allocate_driver(struct lirc_driver *d)
 
 	dev_info(ir->d.dev, "lirc_dev: driver %s registered at minor = %d\n",
 		 ir->d.name, ir->d.minor);
+
 	return minor;
+
 out_cdev:
 	cdev_del(&ir->cdev);
 out_free_dev:
@@ -258,29 +266,6 @@ static int lirc_allocate_driver(struct lirc_driver *d)
 
 	return err;
 }
-
-int lirc_register_driver(struct lirc_driver *d)
-{
-	int minor, err = 0;
-
-	minor = lirc_allocate_driver(d);
-	if (minor < 0)
-		return minor;
-
-	if (LIRC_CAN_REC(d->features)) {
-		err = lirc_allocate_buffer(irctls[minor]);
-		if (err)
-			lirc_unregister_driver(minor);
-		else
-			/*
-			 * This is kind of a hack but ir-lirc-codec needs
-			 * access to the buffer that lirc_dev allocated.
-			 */
-			d->rbuf = irctls[minor]->buf;
-	}
-
-	return err ? err : minor;
-}
 EXPORT_SYMBOL(lirc_register_driver);
 
 int lirc_unregister_driver(int minor)

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 08/16] lirc_zilog: remove module parameter minor
  2017-05-01 16:03 [PATCH 00/16] lirc_dev spring cleaning David Härdeman
                   ` (6 preceding siblings ...)
  2017-05-01 16:04 ` [PATCH 07/16] lirc_dev: merge lirc_register_driver() and lirc_allocate_driver() David Härdeman
@ 2017-05-01 16:04 ` David Härdeman
  2017-05-01 16:04 ` [PATCH 09/16] lirc_dev: remove lirc_irctl_init() and lirc_cdev_add() David Härdeman
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 28+ messages in thread
From: David Härdeman @ 2017-05-01 16:04 UTC (permalink / raw)
  To: linux-media; +Cc: mchehab, sean

Remove the "minor" module parameter in preparation for the next patch.

Signed-off-by: David Härdeman <david@hardeman.nu>
---
 drivers/staging/media/lirc/lirc_zilog.c |   16 ++++++----------
 1 file changed, 6 insertions(+), 10 deletions(-)

diff --git a/drivers/staging/media/lirc/lirc_zilog.c b/drivers/staging/media/lirc/lirc_zilog.c
index 8d8fd8b164e2..59e05aa1bc55 100644
--- a/drivers/staging/media/lirc/lirc_zilog.c
+++ b/drivers/staging/media/lirc/lirc_zilog.c
@@ -156,7 +156,6 @@ static struct mutex tx_data_lock;
 /* module parameters */
 static bool debug;	/* debug output */
 static bool tx_only;	/* only handle the IR Tx function */
-static int minor = -1;	/* minor number */
 
 
 /* struct IR reference counting */
@@ -184,10 +183,11 @@ 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.minor >= 0 && ir->l.minor < MAX_IRCTL_DEVICES) {
+	if (ir->l.minor >= 0) {
 		lirc_unregister_driver(ir->l.minor);
-		ir->l.minor = MAX_IRCTL_DEVICES;
+		ir->l.minor = -1;
 	}
+
 	if (kfifo_initialized(&ir->rbuf.fifo))
 		lirc_buffer_free(&ir->rbuf);
 	list_del(&ir->list);
@@ -1597,12 +1597,11 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	}
 
 	/* register with lirc */
-	ir->l.minor = minor; /* module option: user requested minor number */
 	ir->l.minor = lirc_register_driver(&ir->l);
-	if (ir->l.minor < 0 || ir->l.minor >= MAX_IRCTL_DEVICES) {
+	if (ir->l.minor < 0) {
 		dev_err(tx->ir->l.dev,
-			"%s: \"minor\" must be between 0 and %d (%d)!\n",
-			__func__, MAX_IRCTL_DEVICES-1, ir->l.minor);
+			"%s: lirc_register_driver() failed: %i\n",
+			__func__, ir->l.minor);
 		ret = -EBADRQC;
 		goto out_put_xx;
 	}
@@ -1673,9 +1672,6 @@ MODULE_LICENSE("GPL");
 /* for compat with old name, which isn't all that accurate anymore */
 MODULE_ALIAS("lirc_pvr150");
 
-module_param(minor, int, 0444);
-MODULE_PARM_DESC(minor, "Preferred minor device number");
-
 module_param(debug, bool, 0644);
 MODULE_PARM_DESC(debug, "Enable debugging messages");
 

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 09/16] lirc_dev: remove lirc_irctl_init() and lirc_cdev_add()
  2017-05-01 16:03 [PATCH 00/16] lirc_dev spring cleaning David Härdeman
                   ` (7 preceding siblings ...)
  2017-05-01 16:04 ` [PATCH 08/16] lirc_zilog: remove module parameter minor David Härdeman
@ 2017-05-01 16:04 ` David Härdeman
  2017-05-01 16:04 ` [PATCH 10/16] lirc_dev: remove superfluous get/put_device() calls David Härdeman
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 28+ messages in thread
From: David Härdeman @ 2017-05-01 16:04 UTC (permalink / raw)
  To: linux-media; +Cc: mchehab, sean

These two functions only make the logic in lirc_register_driver() harder to
follow.

(Note that almost no other driver calls kobject_set_name() on their cdev so I
simply removed that part).

Signed-off-by: David Härdeman <david@hardeman.nu>
---
 drivers/media/rc/lirc_dev.c |   44 ++++++++++++-------------------------------
 1 file changed, 12 insertions(+), 32 deletions(-)

diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
index fcc88a09b108..574f4dd416b8 100644
--- a/drivers/media/rc/lirc_dev.c
+++ b/drivers/media/rc/lirc_dev.c
@@ -65,15 +65,6 @@ static struct irctl *irctls[MAX_IRCTL_DEVICES];
 /* Only used for sysfs but defined to void otherwise */
 static struct class *lirc_class;
 
-/*  helper function
- *  initializes the irctl structure
- */
-static void lirc_irctl_init(struct irctl *ir)
-{
-	mutex_init(&ir->irctl_lock);
-	ir->d.minor = NOPLUG;
-}
-
 static void lirc_release(struct device *ld)
 {
 	struct irctl *ir = container_of(ld, struct irctl, dev);
@@ -91,27 +82,6 @@ static void lirc_release(struct device *ld)
 	kfree(ir);
 }
 
-static int lirc_cdev_add(struct irctl *ir)
-{
-	struct lirc_driver *d = &ir->d;
-	struct cdev *cdev;
-	int retval;
-
-	cdev = &ir->cdev;
-
-	if (!d->fops)
-		return -EINVAL;
-
-	cdev_init(cdev, d->fops);
-	cdev->owner = d->owner;
-	retval = kobject_set_name(&cdev->kobj, "lirc%d", d->minor);
-	if (retval)
-		return retval;
-
-	cdev->kobj.parent = &ir->dev.kobj;
-	return cdev_add(cdev, ir->dev.devt, 1);
-}
-
 static int lirc_allocate_buffer(struct irctl *ir)
 {
 	int err = 0;
@@ -167,6 +137,11 @@ int lirc_register_driver(struct lirc_driver *d)
 		return -EINVAL;
 	}
 
+	if (!d->fops) {
+		pr_err("fops pointer not filled in!\n");
+		return -EINVAL;
+	}
+
 	if (d->minor >= MAX_IRCTL_DEVICES) {
 		dev_err(d->dev, "minor must be between 0 and %d!\n",
 						MAX_IRCTL_DEVICES - 1);
@@ -210,7 +185,8 @@ int lirc_register_driver(struct lirc_driver *d)
 		err = -ENOMEM;
 		goto out_lock;
 	}
-	lirc_irctl_init(ir);
+
+	mutex_init(&ir->irctl_lock);
 	irctls[minor] = ir;
 	d->minor = minor;
 
@@ -238,7 +214,11 @@ int lirc_register_driver(struct lirc_driver *d)
 	ir->dev.release = lirc_release;
 	dev_set_name(&ir->dev, "lirc%d", ir->d.minor);
 
-	err = lirc_cdev_add(ir);
+	cdev_init(&ir->cdev, d->fops);
+	ir->cdev.owner = ir->d.owner;
+	ir->cdev.kobj.parent = &ir->dev.kobj;
+
+	err = cdev_add(&ir->cdev, ir->dev.devt, 1);
 	if (err)
 		goto out_free_dev;
 

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 10/16] lirc_dev: remove superfluous get/put_device() calls
  2017-05-01 16:03 [PATCH 00/16] lirc_dev spring cleaning David Härdeman
                   ` (8 preceding siblings ...)
  2017-05-01 16:04 ` [PATCH 09/16] lirc_dev: remove lirc_irctl_init() and lirc_cdev_add() David Härdeman
@ 2017-05-01 16:04 ` David Härdeman
  2017-05-01 16:04 ` [PATCH 11/16] lirc_dev: remove unused module parameter David Härdeman
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 28+ messages in thread
From: David Härdeman @ 2017-05-01 16:04 UTC (permalink / raw)
  To: linux-media; +Cc: mchehab, sean

device_add() and friends alredy manage the references to the parent device so
these calls aren't necessary.

Signed-off-by: David Härdeman <david@hardeman.nu>
---
 drivers/media/rc/lirc_dev.c |    4 ----
 1 file changed, 4 deletions(-)

diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
index 574f4dd416b8..34bd3f8bf30d 100644
--- a/drivers/media/rc/lirc_dev.c
+++ b/drivers/media/rc/lirc_dev.c
@@ -69,8 +69,6 @@ static void lirc_release(struct device *ld)
 {
 	struct irctl *ir = container_of(ld, struct irctl, dev);
 
-	put_device(ir->dev.parent);
-
 	if (ir->buf_internal) {
 		lirc_buffer_free(ir->buf);
 		kfree(ir->buf);
@@ -230,8 +228,6 @@ int lirc_register_driver(struct lirc_driver *d)
 
 	mutex_unlock(&lirc_dev_lock);
 
-	get_device(ir->dev.parent);
-
 	dev_info(ir->d.dev, "lirc_dev: driver %s registered at minor = %d\n",
 		 ir->d.name, ir->d.minor);
 

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 11/16] lirc_dev: remove unused module parameter
  2017-05-01 16:03 [PATCH 00/16] lirc_dev spring cleaning David Härdeman
                   ` (9 preceding siblings ...)
  2017-05-01 16:04 ` [PATCH 10/16] lirc_dev: remove superfluous get/put_device() calls David Härdeman
@ 2017-05-01 16:04 ` David Härdeman
  2017-05-01 16:04 ` [PATCH 12/16] lirc_dev: return POLLHUP and POLLERR when device is gone David Härdeman
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 28+ messages in thread
From: David Härdeman @ 2017-05-01 16:04 UTC (permalink / raw)
  To: linux-media; +Cc: mchehab, sean

The "debug" parameter isn't actually used anywhere.

Signed-off-by: David Härdeman <david@hardeman.nu>
---
 drivers/media/rc/lirc_dev.c |    5 -----
 1 file changed, 5 deletions(-)

diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
index 34bd3f8bf30d..57d21201ff93 100644
--- a/drivers/media/rc/lirc_dev.c
+++ b/drivers/media/rc/lirc_dev.c
@@ -36,8 +36,6 @@
 #include <media/lirc.h>
 #include <media/lirc_dev.h>
 
-static bool debug;
-
 #define IRCTL_DEV_NAME	"BaseRemoteCtl"
 #define NOPLUG		-1
 #define LOGHEAD		"lirc_dev (%s[%d]): "
@@ -625,6 +623,3 @@ module_exit(lirc_dev_exit);
 MODULE_DESCRIPTION("LIRC base driver module");
 MODULE_AUTHOR("Artur Lipowski");
 MODULE_LICENSE("GPL");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Enable debugging messages");

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 12/16] lirc_dev: return POLLHUP and POLLERR when device is gone
  2017-05-01 16:03 [PATCH 00/16] lirc_dev spring cleaning David Härdeman
                   ` (10 preceding siblings ...)
  2017-05-01 16:04 ` [PATCH 11/16] lirc_dev: remove unused module parameter David Härdeman
@ 2017-05-01 16:04 ` David Härdeman
  2017-05-01 16:04 ` [PATCH 13/16] lirc_dev: use an ida instead of a hand-rolled array to keep track of minors David Härdeman
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 28+ messages in thread
From: David Härdeman @ 2017-05-01 16:04 UTC (permalink / raw)
  To: linux-media; +Cc: mchehab, sean

Most drivers return both values when the device is gone.

Signed-off-by: David Härdeman <david@hardeman.nu>
---
 drivers/media/rc/lirc_dev.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
index 57d21201ff93..e44e0b23b883 100644
--- a/drivers/media/rc/lirc_dev.c
+++ b/drivers/media/rc/lirc_dev.c
@@ -374,7 +374,7 @@ unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait)
 	}
 
 	if (!ir->attached)
-		return POLLERR;
+		return POLLHUP | POLLERR;
 
 	if (ir->buf) {
 		poll_wait(file, &ir->buf->wait_poll, wait);

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 13/16] lirc_dev: use an ida instead of a hand-rolled array to keep track of minors
  2017-05-01 16:03 [PATCH 00/16] lirc_dev spring cleaning David Härdeman
                   ` (11 preceding siblings ...)
  2017-05-01 16:04 ` [PATCH 12/16] lirc_dev: return POLLHUP and POLLERR when device is gone David Härdeman
@ 2017-05-01 16:04 ` David Härdeman
  2017-05-22 20:09   ` Sean Young
  2017-05-01 16:04 ` [PATCH 14/16] lirc_dev: cleanup includes David Härdeman
                   ` (2 subsequent siblings)
  15 siblings, 1 reply; 28+ messages in thread
From: David Härdeman @ 2017-05-01 16:04 UTC (permalink / raw)
  To: linux-media; +Cc: mchehab, sean

Using the kernel ida facilities, we can avoid a lot of unnecessary code and at the same
time get rid of lirc_dev_lock in favour of per-device locks (the irctls array was used
throughout lirc_dev so this patch necessarily touches a lot of code).

Signed-off-by: David Härdeman <david@hardeman.nu>
---
 drivers/media/rc/ir-lirc-codec.c        |    9 -
 drivers/media/rc/lirc_dev.c             |  258 ++++++++++++-------------------
 drivers/staging/media/lirc/lirc_zilog.c |   16 +-
 include/media/lirc_dev.h                |   14 --
 4 files changed, 115 insertions(+), 182 deletions(-)

diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c
index a30af91710fe..2c1221a61ea1 100644
--- a/drivers/media/rc/ir-lirc-codec.c
+++ b/drivers/media/rc/ir-lirc-codec.c
@@ -382,7 +382,6 @@ static int ir_lirc_register(struct rc_dev *dev)
 
 	snprintf(drv->name, sizeof(drv->name), "ir-lirc-codec (%s)",
 		 dev->driver_name);
-	drv->minor = -1;
 	drv->features = features;
 	drv->data = &dev->raw->lirc;
 	drv->rbuf = NULL;
@@ -394,11 +393,9 @@ static int ir_lirc_register(struct rc_dev *dev)
 	drv->rdev = dev;
 	drv->owner = THIS_MODULE;
 
-	drv->minor = lirc_register_driver(drv);
-	if (drv->minor < 0) {
-		rc = -ENODEV;
+	rc = lirc_register_driver(drv);
+	if (rc < 0)
 		goto out;
-	}
 
 	dev->raw->lirc.drv = drv;
 	dev->raw->lirc.dev = dev;
@@ -413,7 +410,7 @@ static int ir_lirc_unregister(struct rc_dev *dev)
 {
 	struct lirc_codec *lirc = &dev->raw->lirc;
 
-	lirc_unregister_driver(lirc->drv->minor);
+	lirc_unregister_driver(lirc->drv);
 	kfree(lirc->drv);
 	lirc->drv = NULL;
 
diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
index e44e0b23b883..7db7d4c57991 100644
--- a/drivers/media/rc/lirc_dev.c
+++ b/drivers/media/rc/lirc_dev.c
@@ -31,23 +31,35 @@
 #include <linux/bitops.h>
 #include <linux/device.h>
 #include <linux/cdev.h>
+#include <linux/idr.h>
 
 #include <media/rc-core.h>
 #include <media/lirc.h>
 #include <media/lirc_dev.h>
 
 #define IRCTL_DEV_NAME	"BaseRemoteCtl"
-#define NOPLUG		-1
 #define LOGHEAD		"lirc_dev (%s[%d]): "
 
 static dev_t lirc_base_dev;
 
+/**
+ * struct irctl - lirc per-device structure
+ * @d:			internal copy of the &struct lirc_driver for the device
+ * @dead:		if the device has gone away
+ * @users:		the number of users of the lirc chardev (currently limited to 1)
+ * @mutex:		synchronizes open()/close()/ioctl()/etc calls
+ * @buf:		used to store lirc RX data
+ * @buf_internal:	whether @buf was allocated internally or not
+ * @chunk_size:		@buf stores and read() returns data chunks of this size
+ * @dev:		the &struct device for the lirc device
+ * @cdev:		the &struct device for the lirc chardev
+ */
 struct irctl {
 	struct lirc_driver d;
-	int attached;
-	int open;
+	bool dead;
+	unsigned users;
 
-	struct mutex irctl_lock;
+	struct mutex mutex;
 	struct lirc_buffer *buf;
 	bool buf_internal;
 	unsigned int chunk_size;
@@ -56,9 +68,9 @@ struct irctl {
 	struct cdev cdev;
 };
 
-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;
@@ -72,9 +84,6 @@ static void lirc_release(struct device *ld)
 		kfree(ir->buf);
 	}
 
-	mutex_lock(&lirc_dev_lock);
-	irctls[ir->d.minor] = NULL;
-	mutex_unlock(&lirc_dev_lock);
 	kfree(ir);
 }
 
@@ -117,7 +126,18 @@ static int lirc_allocate_buffer(struct irctl *ir)
 	return err;
 }
 
-int lirc_register_driver(struct lirc_driver *d)
+/**
+ * lirc_register_driver() - create a new lirc device by registering a driver
+ * @d: the &struct lirc_driver to register
+ *
+ * This function allocates and registers a lirc device for a given
+ * &lirc_driver. The &lirc_driver structure is updated to contain
+ * information about the allocated device (minor, buffer, etc).
+ *
+ * Return: zero on success or a negative error value.
+ */
+int
+lirc_register_driver(struct lirc_driver *d)
 {
 	struct irctl *ir;
 	int minor;
@@ -138,12 +158,6 @@ int lirc_register_driver(struct lirc_driver *d)
 		return -EINVAL;
 	}
 
-	if (d->minor >= MAX_IRCTL_DEVICES) {
-		dev_err(d->dev, "minor must be between 0 and %d!\n",
-						MAX_IRCTL_DEVICES - 1);
-		return -EBADRQC;
-	}
-
 	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);
@@ -156,49 +170,30 @@ int lirc_register_driver(struct lirc_driver *d)
 		return -EBADRQC;
 	}
 
-	mutex_lock(&lirc_dev_lock);
-
-	minor = d->minor;
+	d->name[sizeof(d->name)-1] = '\0';
+	if (d->features == 0)
+		d->features = LIRC_CAN_REC_LIRCCODE;
 
-	if (minor < 0) {
-		/* 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");
-			err = -ENOMEM;
-			goto out_lock;
-		}
-	} else if (irctls[minor]) {
-		dev_err(d->dev, "minor (%d) just registered!\n", minor);
-		err = -EBUSY;
-		goto out_lock;
-	}
+	minor = ida_simple_get(&lirc_ida, 0, LIRC_MAX_DEVICES, GFP_KERNEL);
+	if (minor < 0)
+		return minor;
+	d->minor = minor;
 
 	ir = kzalloc(sizeof(struct irctl), GFP_KERNEL);
 	if (!ir) {
 		err = -ENOMEM;
-		goto out_lock;
+		goto out_minor;
 	}
 
-	mutex_init(&ir->irctl_lock);
-	irctls[minor] = ir;
-	d->minor = minor;
-
-	/* some safety check 8-) */
-	d->name[sizeof(d->name)-1] = '\0';
-
-	if (d->features == 0)
-		d->features = LIRC_CAN_REC_LIRCCODE;
+	mutex_init(&ir->mutex);
 
 	ir->d = *d;
 
 	if (LIRC_CAN_REC(d->features)) {
-		err = lirc_allocate_buffer(irctls[minor]);
+		err = lirc_allocate_buffer(ir);
 		if (err) {
 			kfree(ir);
-			goto out_lock;
+			goto out_minor;
 		}
 		d->rbuf = ir->buf;
 	}
@@ -218,107 +213,82 @@ int lirc_register_driver(struct lirc_driver *d)
 	if (err)
 		goto out_free_dev;
 
-	ir->attached = 1;
-
 	err = device_add(&ir->dev);
 	if (err)
 		goto out_cdev;
 
-	mutex_unlock(&lirc_dev_lock);
-
 	dev_info(ir->d.dev, "lirc_dev: driver %s registered at minor = %d\n",
 		 ir->d.name, ir->d.minor);
 
-	return minor;
+	d->lirc_internal = ir;
+	return 0;
 
 out_cdev:
 	cdev_del(&ir->cdev);
 out_free_dev:
 	put_device(&ir->dev);
-out_lock:
-	mutex_unlock(&lirc_dev_lock);
+out_minor:
+	ida_simple_remove(&lirc_ida, minor);
 
 	return err;
 }
 EXPORT_SYMBOL(lirc_register_driver);
 
-int lirc_unregister_driver(int minor)
+/**
+ * lirc_unregister_driver() - remove the lirc device for a given driver
+ * @d: the &struct lirc_driver to unregister
+ *
+ * This function unregisters the lirc device for a given &lirc_driver.
+ */
+void
+lirc_unregister_driver(struct lirc_driver *d)
 {
 	struct irctl *ir;
 
-	if (minor < 0 || minor >= MAX_IRCTL_DEVICES) {
-		pr_err("minor (%d) must be between 0 and %d!\n",
-					minor, MAX_IRCTL_DEVICES - 1);
-		return -EBADRQC;
-	}
+	if (!d->lirc_internal)
+		return;
 
-	ir = irctls[minor];
-	if (!ir) {
-		pr_err("failed to get irctl\n");
-		return -ENOENT;
-	}
+	ir = d->lirc_internal;
 
-	mutex_lock(&lirc_dev_lock);
-
-	if (ir->d.minor != minor) {
-		dev_err(ir->d.dev, "lirc_dev: minor %d device not registered\n",
-									minor);
-		mutex_unlock(&lirc_dev_lock);
-		return -ENOENT;
-	}
+	mutex_lock(&ir->mutex);
 
 	dev_dbg(ir->d.dev, "lirc_dev: driver %s unregistered from minor = %d\n",
 		ir->d.name, ir->d.minor);
 
-	ir->attached = 0;
-	if (ir->open) {
+	ir->dead = true;
+	if (ir->users) {
 		dev_dbg(ir->d.dev, LOGHEAD "releasing opened driver\n",
 			ir->d.name, ir->d.minor);
 		wake_up_interruptible(&ir->buf->wait_poll);
 	}
 
-	mutex_unlock(&lirc_dev_lock);
+	mutex_unlock(&ir->mutex);
 
 	device_del(&ir->dev);
 	cdev_del(&ir->cdev);
-	put_device(&ir->dev);
-
-	return 0;
+	ida_simple_remove(&lirc_ida, d->minor);
+	d->minor = -1;
+	d->lirc_internal = NULL;
 }
 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;
+	mutex_lock(&ir->mutex);
 
-	ir = irctls[iminor(inode)];
-	mutex_unlock(&lirc_dev_lock);
-
-	if (!ir) {
-		retval = -ENODEV;
+	if (ir->users) {
+		retval = -EBUSY;
+		mutex_unlock(&ir->mutex);
 		goto error;
 	}
+	ir->users++;
 
-	dev_dbg(ir->d.dev, LOGHEAD "open called\n", ir->d.name, ir->d.minor);
-
-	if (ir->d.minor == NOPLUG) {
-		retval = -ENODEV;
-		goto error;
-	}
+	mutex_unlock(&ir->mutex);
 
-	if (ir->open) {
-		retval = -EBUSY;
-		goto error;
-	}
+	dev_dbg(ir->d.dev, LOGHEAD "open called\n", ir->d.name, ir->d.minor);
 
 	if (ir->d.rdev) {
 		retval = rc_open(ir->d.rdev);
@@ -329,8 +299,7 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file)
 	if (ir->buf)
 		lirc_buffer_clear(ir->buf);
 
-	ir->open++;
-
+	file->private_data = ir;
 	nonseekable_open(inode, file);
 
 	return 0;
@@ -342,22 +311,14 @@ EXPORT_SYMBOL(lirc_dev_fop_open);
 
 int lirc_dev_fop_close(struct inode *inode, struct file *file)
 {
-	struct irctl *ir = irctls[iminor(inode)];
-	int ret;
-
-	if (!ir) {
-		pr_err("called with invalid irctl\n");
-		return -EINVAL;
-	}
+	struct irctl *ir = file->private_data;
 
-	ret = mutex_lock_killable(&lirc_dev_lock);
-	WARN_ON(ret);
+	mutex_lock(&ir->mutex);
 
 	rc_close(ir->d.rdev);
+	ir->users--;
 
-	ir->open--;
-	if (!ret)
-		mutex_unlock(&lirc_dev_lock);
+	mutex_unlock(&ir->mutex);
 
 	return 0;
 }
@@ -365,26 +326,21 @@ 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)
+	if (ir->dead)
 		return POLLHUP | POLLERR;
 
-	if (ir->buf) {
-		poll_wait(file, &ir->buf->wait_poll, wait);
+	if (!ir->buf)
+		return POLLERR;
+
+	poll_wait(file, &ir->buf->wait_poll, wait);
 
-		if (lirc_buffer_empty(ir->buf))
-			ret = 0;
-		else
-			ret = POLLIN | POLLRDNORM;
-	} else
-		ret = POLLERR;
+	if (lirc_buffer_empty(ir->buf))
+		ret = 0;
+	else
+		ret = POLLIN | POLLRDNORM;
 
 	dev_dbg(ir->d.dev, LOGHEAD "poll result = %d\n",
 		ir->d.name, ir->d.minor, ret);
@@ -395,25 +351,20 @@ 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);
 
-	if (ir->d.minor == NOPLUG || !ir->attached) {
+	if (ir->dead) {
 		dev_err(ir->d.dev, LOGHEAD "ioctl result = -ENODEV\n",
 			ir->d.name, ir->d.minor);
 		return -ENODEV;
 	}
 
-	mutex_lock(&ir->irctl_lock);
+	mutex_lock(&ir->mutex);
 
 	switch (cmd) {
 	case LIRC_GET_FEATURES:
@@ -468,7 +419,7 @@ long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 		result = -ENOTTY;
 	}
 
-	mutex_unlock(&ir->irctl_lock);
+	mutex_unlock(&ir->mutex);
 
 	return result;
 }
@@ -479,16 +430,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;
 
@@ -498,11 +444,12 @@ ssize_t lirc_dev_fop_read(struct file *file,
 	if (!buf)
 		return -ENOMEM;
 
-	if (mutex_lock_interruptible(&ir->irctl_lock)) {
+	if (mutex_lock_interruptible(&ir->mutex)) {
 		ret = -ERESTARTSYS;
 		goto out_unlocked;
 	}
-	if (!ir->attached) {
+
+	if (ir->dead) {
 		ret = -ENODEV;
 		goto out_locked;
 	}
@@ -541,18 +488,18 @@ ssize_t lirc_dev_fop_read(struct file *file,
 				break;
 			}
 
-			mutex_unlock(&ir->irctl_lock);
+			mutex_unlock(&ir->mutex);
 			set_current_state(TASK_INTERRUPTIBLE);
 			schedule();
 			set_current_state(TASK_RUNNING);
 
-			if (mutex_lock_interruptible(&ir->irctl_lock)) {
+			if (mutex_lock_interruptible(&ir->mutex)) {
 				ret = -ERESTARTSYS;
 				remove_wait_queue(&ir->buf->wait_poll, &wait);
 				goto out_unlocked;
 			}
 
-			if (!ir->attached) {
+			if (ir->dead) {
 				ret = -ENODEV;
 				goto out_locked;
 			}
@@ -570,7 +517,7 @@ ssize_t lirc_dev_fop_read(struct file *file,
 	remove_wait_queue(&ir->buf->wait_poll, &wait);
 
 out_locked:
-	mutex_unlock(&ir->irctl_lock);
+	mutex_unlock(&ir->mutex);
 
 out_unlocked:
 	kfree(buf);
@@ -581,7 +528,8 @@ EXPORT_SYMBOL(lirc_dev_fop_read);
 
 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);
 
@@ -596,7 +544,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,
 				     IRCTL_DEV_NAME);
 	if (retval) {
 		class_destroy(lirc_class);
@@ -613,7 +561,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/drivers/staging/media/lirc/lirc_zilog.c b/drivers/staging/media/lirc/lirc_zilog.c
index 59e05aa1bc55..ffb70dee4547 100644
--- a/drivers/staging/media/lirc/lirc_zilog.c
+++ b/drivers/staging/media/lirc/lirc_zilog.c
@@ -183,11 +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
 	 */
-	if (ir->l.minor >= 0) {
-		lirc_unregister_driver(ir->l.minor);
-		ir->l.minor = -1;
-	}
-
+	lirc_unregister_driver(&ir->l);
 	if (kfifo_initialized(&ir->rbuf.fifo))
 		lirc_buffer_free(&ir->rbuf);
 	list_del(&ir->list);
@@ -1382,7 +1378,6 @@ static const struct file_operations lirc_fops = {
 
 static struct lirc_driver lirc_template = {
 	.name		= "lirc_zilog",
-	.minor		= -1,
 	.code_length	= 13,
 	.buffer_size	= BUFLEN / 2,
 	.chunk_size	= 2,
@@ -1597,14 +1592,13 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	}
 
 	/* register with lirc */
-	ir->l.minor = lirc_register_driver(&ir->l);
-	if (ir->l.minor < 0) {
+	ret = lirc_register_driver(&ir->l);
+	if (ret < 0) {
 		dev_err(tx->ir->l.dev,
-			"%s: lirc_register_driver() failed: %i\n",
-			__func__, ir->l.minor);
-		ret = -EBADRQC;
+			"%s: lirc_register_driver failed: %i\n", __func__, ret);
 		goto out_put_xx;
 	}
+
 	dev_info(ir->l.dev,
 		 "IR unit on %s (i2c-%d) registered as lirc%d and ready\n",
 		 adap->name, adap->nr, ir->l.minor);
diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h
index 1f327e25a9be..f7629ff116a9 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
 
 #define mod(n, div) ((n) % (div))
@@ -164,6 +163,8 @@ static inline unsigned int lirc_buffer_write(struct lirc_buffer *buf,
  *			device.
  *
  * @owner:		the module owning this struct
+ *
+ * @lirc_internal:	lirc_dev bookkeeping data, don't touch.
  */
 struct lirc_driver {
 	char name[40];
@@ -182,19 +183,12 @@ struct lirc_driver {
 	const struct file_operations *fops;
 	struct device *dev;
 	struct module *owner;
+	void *lirc_internal;
 };
 
-/* following functions can be called ONLY from user context
- *
- * returns negative value on error or minor number
- * of the registered device if success
- * contents of the structure pointed by p is copied
- */
 extern int lirc_register_driver(struct lirc_driver *d);
 
-/* returns negative value on error or 0 if success
-*/
-extern int lirc_unregister_driver(int minor);
+extern void lirc_unregister_driver(struct lirc_driver *d);
 
 /* Returns the private data stored in the lirc_driver
  * associated with the given device file pointer.

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 14/16] lirc_dev: cleanup includes
  2017-05-01 16:03 [PATCH 00/16] lirc_dev spring cleaning David Härdeman
                   ` (12 preceding siblings ...)
  2017-05-01 16:04 ` [PATCH 13/16] lirc_dev: use an ida instead of a hand-rolled array to keep track of minors David Härdeman
@ 2017-05-01 16:04 ` David Härdeman
  2017-05-19 18:21   ` Sean Young
  2017-05-01 16:04 ` [PATCH 15/16] lirc_dev: remove name from struct lirc_driver David Härdeman
  2017-05-01 16:04 ` [PATCH 16/16] lirc_dev: cleanup header David Härdeman
  15 siblings, 1 reply; 28+ messages in thread
From: David Härdeman @ 2017-05-01 16:04 UTC (permalink / raw)
  To: linux-media; +Cc: mchehab, sean

Remove superfluous includes and defines.

Signed-off-by: David Härdeman <david@hardeman.nu>
---
 drivers/media/rc/lirc_dev.c |   12 +-----------
 1 file changed, 1 insertion(+), 11 deletions(-)

diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
index 7db7d4c57991..4ba6c7e2d41b 100644
--- a/drivers/media/rc/lirc_dev.c
+++ b/drivers/media/rc/lirc_dev.c
@@ -15,20 +15,11 @@
  *
  */
 
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
 #include <linux/module.h>
-#include <linux/kernel.h>
 #include <linux/sched/signal.h>
-#include <linux/errno.h>
 #include <linux/ioctl.h>
-#include <linux/fs.h>
 #include <linux/poll.h>
-#include <linux/completion.h>
 #include <linux/mutex.h>
-#include <linux/wait.h>
-#include <linux/unistd.h>
-#include <linux/bitops.h>
 #include <linux/device.h>
 #include <linux/cdev.h>
 #include <linux/idr.h>
@@ -37,7 +28,6 @@
 #include <media/lirc.h>
 #include <media/lirc_dev.h>
 
-#define IRCTL_DEV_NAME	"BaseRemoteCtl"
 #define LOGHEAD		"lirc_dev (%s[%d]): "
 
 static dev_t lirc_base_dev;
@@ -545,7 +535,7 @@ static int __init lirc_dev_init(void)
 	}
 
 	retval = alloc_chrdev_region(&lirc_base_dev, 0, LIRC_MAX_DEVICES,
-				     IRCTL_DEV_NAME);
+				     "BaseRemoteCtl");
 	if (retval) {
 		class_destroy(lirc_class);
 		pr_err("alloc_chrdev_region failed\n");

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 15/16] lirc_dev: remove name from struct lirc_driver
  2017-05-01 16:03 [PATCH 00/16] lirc_dev spring cleaning David Härdeman
                   ` (13 preceding siblings ...)
  2017-05-01 16:04 ` [PATCH 14/16] lirc_dev: cleanup includes David Härdeman
@ 2017-05-01 16:04 ` David Härdeman
  2017-05-02 17:04   ` Sean Young
  2017-05-01 16:04 ` [PATCH 16/16] lirc_dev: cleanup header David Härdeman
  15 siblings, 1 reply; 28+ messages in thread
From: David Härdeman @ 2017-05-01 16:04 UTC (permalink / raw)
  To: linux-media; +Cc: mchehab, sean

The name is only used for a few debug messages and the name of the parent
device as well as the name of the lirc device (e.g. "lirc0") are sufficient
anyway.

Signed-off-by: David Härdeman <david@hardeman.nu>
---
 drivers/media/rc/ir-lirc-codec.c        |    2 --
 drivers/media/rc/lirc_dev.c             |   25 ++++++++-----------------
 drivers/staging/media/lirc/lirc_zilog.c |    1 -
 include/media/lirc_dev.h                |    3 ---
 4 files changed, 8 insertions(+), 23 deletions(-)

diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c
index 2c1221a61ea1..74ce27f92901 100644
--- a/drivers/media/rc/ir-lirc-codec.c
+++ b/drivers/media/rc/ir-lirc-codec.c
@@ -380,8 +380,6 @@ 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)",
-		 dev->driver_name);
 	drv->features = features;
 	drv->data = &dev->raw->lirc;
 	drv->rbuf = NULL;
diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
index 4ba6c7e2d41b..10783ef75a25 100644
--- a/drivers/media/rc/lirc_dev.c
+++ b/drivers/media/rc/lirc_dev.c
@@ -28,8 +28,6 @@
 #include <media/lirc.h>
 #include <media/lirc_dev.h>
 
-#define LOGHEAD		"lirc_dev (%s[%d]): "
-
 static dev_t lirc_base_dev;
 
 /**
@@ -160,7 +158,6 @@ lirc_register_driver(struct lirc_driver *d)
 		return -EBADRQC;
 	}
 
-	d->name[sizeof(d->name)-1] = '\0';
 	if (d->features == 0)
 		d->features = LIRC_CAN_REC_LIRCCODE;
 
@@ -207,8 +204,7 @@ lirc_register_driver(struct lirc_driver *d)
 	if (err)
 		goto out_cdev;
 
-	dev_info(ir->d.dev, "lirc_dev: driver %s registered at minor = %d\n",
-		 ir->d.name, ir->d.minor);
+	dev_info(ir->d.dev, "lirc device registered as lirc%d\n", minor);
 
 	d->lirc_internal = ir;
 	return 0;
@@ -242,13 +238,11 @@ lirc_unregister_driver(struct lirc_driver *d)
 
 	mutex_lock(&ir->mutex);
 
-	dev_dbg(ir->d.dev, "lirc_dev: driver %s unregistered from minor = %d\n",
-		ir->d.name, ir->d.minor);
+	dev_dbg(&ir->dev, "unregistered\n");
 
 	ir->dead = true;
 	if (ir->users) {
-		dev_dbg(ir->d.dev, LOGHEAD "releasing opened driver\n",
-			ir->d.name, ir->d.minor);
+		dev_dbg(&ir->dev, "releasing opened driver\n");
 		wake_up_interruptible(&ir->buf->wait_poll);
 	}
 
@@ -278,7 +272,7 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file)
 
 	mutex_unlock(&ir->mutex);
 
-	dev_dbg(ir->d.dev, LOGHEAD "open called\n", ir->d.name, ir->d.minor);
+	dev_dbg(&ir->dev, "open called\n");
 
 	if (ir->d.rdev) {
 		retval = rc_open(ir->d.rdev);
@@ -332,8 +326,7 @@ unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait)
 	else
 		ret = POLLIN | POLLRDNORM;
 
-	dev_dbg(ir->d.dev, LOGHEAD "poll result = %d\n",
-		ir->d.name, ir->d.minor, ret);
+	dev_dbg(&ir->dev, "poll result = %d\n", ret);
 
 	return ret;
 }
@@ -345,12 +338,10 @@ long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 	__u32 mode;
 	int result = 0;
 
-	dev_dbg(ir->d.dev, LOGHEAD "ioctl called (0x%x)\n",
-		ir->d.name, ir->d.minor, cmd);
+	dev_dbg(&ir->dev, "ioctl called (0x%x)\n", cmd);
 
 	if (ir->dead) {
-		dev_err(ir->d.dev, LOGHEAD "ioctl result = -ENODEV\n",
-			ir->d.name, ir->d.minor);
+		dev_err(&ir->dev, "ioctl result = -ENODEV\n");
 		return -ENODEV;
 	}
 
@@ -428,7 +419,7 @@ ssize_t lirc_dev_fop_read(struct file *file,
 	if (!LIRC_CAN_REC(ir->d.features))
 		return -EINVAL;
 
-	dev_dbg(ir->d.dev, LOGHEAD "read called\n", ir->d.name, ir->d.minor);
+	dev_dbg(&ir->dev, "read called\n");
 
 	buf = kzalloc(ir->chunk_size, GFP_KERNEL);
 	if (!buf)
diff --git a/drivers/staging/media/lirc/lirc_zilog.c b/drivers/staging/media/lirc/lirc_zilog.c
index ffb70dee4547..131d87a04aab 100644
--- a/drivers/staging/media/lirc/lirc_zilog.c
+++ b/drivers/staging/media/lirc/lirc_zilog.c
@@ -1377,7 +1377,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,
diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h
index f7629ff116a9..11f455a34090 100644
--- a/include/media/lirc_dev.h
+++ b/include/media/lirc_dev.h
@@ -120,8 +120,6 @@ 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:		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
@@ -167,7 +165,6 @@ static inline unsigned int lirc_buffer_write(struct lirc_buffer *buf,
  * @lirc_internal:	lirc_dev bookkeeping data, don't touch.
  */
 struct lirc_driver {
-	char name[40];
 	int minor;
 	__u32 code_length;
 	unsigned int buffer_size; /* in chunks holding one code each */

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 16/16] lirc_dev: cleanup header
  2017-05-01 16:03 [PATCH 00/16] lirc_dev spring cleaning David Härdeman
                   ` (14 preceding siblings ...)
  2017-05-01 16:04 ` [PATCH 15/16] lirc_dev: remove name from struct lirc_driver David Härdeman
@ 2017-05-01 16:04 ` David Härdeman
  15 siblings, 0 replies; 28+ messages in thread
From: David Härdeman @ 2017-05-01 16:04 UTC (permalink / raw)
  To: linux-media; +Cc: mchehab, sean

Remove some stuff from lirc_dev.h which is not used anywhere.

Signed-off-by: David Härdeman <david@hardeman.nu>
---
 include/media/lirc_dev.h |   11 ++---------
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h
index 11f455a34090..af738d522dec 100644
--- a/include/media/lirc_dev.h
+++ b/include/media/lirc_dev.h
@@ -9,10 +9,6 @@
 #ifndef _LINUX_LIRC_DEV_H
 #define _LINUX_LIRC_DEV_H
 
-#define BUFLEN            16
-
-#define mod(n, div) ((n) % (div))
-
 #include <linux/slab.h>
 #include <linux/fs.h>
 #include <linux/ioctl.h>
@@ -20,6 +16,8 @@
 #include <linux/kfifo.h>
 #include <media/lirc.h>
 
+#define BUFLEN            16
+
 struct lirc_buffer {
 	wait_queue_head_t wait_poll;
 	spinlock_t fifo_lock;
@@ -89,11 +87,6 @@ static inline int lirc_buffer_empty(struct lirc_buffer *buf)
 	return !lirc_buffer_len(buf);
 }
 
-static inline int lirc_buffer_available(struct lirc_buffer *buf)
-{
-	return buf->size - (lirc_buffer_len(buf) / buf->chunk_size);
-}
-
 static inline unsigned int lirc_buffer_read(struct lirc_buffer *buf,
 					    unsigned char *dest)
 {

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* Re: [PATCH 15/16] lirc_dev: remove name from struct lirc_driver
  2017-05-01 16:04 ` [PATCH 15/16] lirc_dev: remove name from struct lirc_driver David Härdeman
@ 2017-05-02 17:04   ` Sean Young
  2017-05-02 18:41     ` David Härdeman
  0 siblings, 1 reply; 28+ messages in thread
From: Sean Young @ 2017-05-02 17:04 UTC (permalink / raw)
  To: David Härdeman; +Cc: linux-media, mchehab

On Mon, May 01, 2017 at 06:04:52PM +0200, David Härdeman wrote:
> The name is only used for a few debug messages and the name of the parent
> device as well as the name of the lirc device (e.g. "lirc0") are sufficient
> anyway.
> 
> Signed-off-by: David Härdeman <david@hardeman.nu>
> ---
>  drivers/media/rc/ir-lirc-codec.c        |    2 --
>  drivers/media/rc/lirc_dev.c             |   25 ++++++++-----------------
>  drivers/staging/media/lirc/lirc_zilog.c |    1 -
>  include/media/lirc_dev.h                |    3 ---
>  4 files changed, 8 insertions(+), 23 deletions(-)
> 
> diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c
> index 2c1221a61ea1..74ce27f92901 100644
> --- a/drivers/media/rc/ir-lirc-codec.c
> +++ b/drivers/media/rc/ir-lirc-codec.c
> @@ -380,8 +380,6 @@ 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)",
> -		 dev->driver_name);
>  	drv->features = features;
>  	drv->data = &dev->raw->lirc;
>  	drv->rbuf = NULL;
> diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
> index 4ba6c7e2d41b..10783ef75a25 100644
> --- a/drivers/media/rc/lirc_dev.c
> +++ b/drivers/media/rc/lirc_dev.c
> @@ -28,8 +28,6 @@
>  #include <media/lirc.h>
>  #include <media/lirc_dev.h>
>  
> -#define LOGHEAD		"lirc_dev (%s[%d]): "
> -
>  static dev_t lirc_base_dev;
>  
>  /**
> @@ -160,7 +158,6 @@ lirc_register_driver(struct lirc_driver *d)
>  		return -EBADRQC;
>  	}
>  
> -	d->name[sizeof(d->name)-1] = '\0';
>  	if (d->features == 0)
>  		d->features = LIRC_CAN_REC_LIRCCODE;
>  
> @@ -207,8 +204,7 @@ lirc_register_driver(struct lirc_driver *d)
>  	if (err)
>  		goto out_cdev;
>  
> -	dev_info(ir->d.dev, "lirc_dev: driver %s registered at minor = %d\n",
> -		 ir->d.name, ir->d.minor);
> +	dev_info(ir->d.dev, "lirc device registered as lirc%d\n", minor);

I'm not so sure this is a good idea. First of all, the documentation says
you can use "dmesg |grep lirc_dev" to find your lirc devices and you've
just replaced lirc_dev with lirc.

https://linuxtv.org/downloads/v4l-dvb-apis/uapi/rc/lirc-dev-intro.html

It's useful having the driver name in the message. For example, I have
two rc devices connected usually:

[sean@bigcore ~]$ dmesg | grep lirc_dev
[    5.938284] lirc_dev: IR Remote Control driver registered, major 239
[    5.945324] rc rc0: lirc_dev: driver ir-lirc-codec (winbond-cir) registered at minor = 0
[ 5111.830118] rc rc1: lirc_dev: driver ir-lirc-codec (mceusb) registered at minor = 1

With the driver name I know which one is which.

Maybe lirc_driver.name should be a "const char*" so no strcpy is needed
(the ir-lirc-codec does not seem necessary).

Thanks

Sean

>  
>  	d->lirc_internal = ir;
>  	return 0;
> @@ -242,13 +238,11 @@ lirc_unregister_driver(struct lirc_driver *d)
>  
>  	mutex_lock(&ir->mutex);
>  
> -	dev_dbg(ir->d.dev, "lirc_dev: driver %s unregistered from minor = %d\n",
> -		ir->d.name, ir->d.minor);
> +	dev_dbg(&ir->dev, "unregistered\n");
>  
>  	ir->dead = true;
>  	if (ir->users) {
> -		dev_dbg(ir->d.dev, LOGHEAD "releasing opened driver\n",
> -			ir->d.name, ir->d.minor);
> +		dev_dbg(&ir->dev, "releasing opened driver\n");
>  		wake_up_interruptible(&ir->buf->wait_poll);
>  	}
>  
> @@ -278,7 +272,7 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file)
>  
>  	mutex_unlock(&ir->mutex);
>  
> -	dev_dbg(ir->d.dev, LOGHEAD "open called\n", ir->d.name, ir->d.minor);
> +	dev_dbg(&ir->dev, "open called\n");
>  
>  	if (ir->d.rdev) {
>  		retval = rc_open(ir->d.rdev);
> @@ -332,8 +326,7 @@ unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait)
>  	else
>  		ret = POLLIN | POLLRDNORM;
>  
> -	dev_dbg(ir->d.dev, LOGHEAD "poll result = %d\n",
> -		ir->d.name, ir->d.minor, ret);
> +	dev_dbg(&ir->dev, "poll result = %d\n", ret);
>  
>  	return ret;
>  }
> @@ -345,12 +338,10 @@ long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
>  	__u32 mode;
>  	int result = 0;
>  
> -	dev_dbg(ir->d.dev, LOGHEAD "ioctl called (0x%x)\n",
> -		ir->d.name, ir->d.minor, cmd);
> +	dev_dbg(&ir->dev, "ioctl called (0x%x)\n", cmd);
>  
>  	if (ir->dead) {
> -		dev_err(ir->d.dev, LOGHEAD "ioctl result = -ENODEV\n",
> -			ir->d.name, ir->d.minor);
> +		dev_err(&ir->dev, "ioctl result = -ENODEV\n");
>  		return -ENODEV;
>  	}
>  
> @@ -428,7 +419,7 @@ ssize_t lirc_dev_fop_read(struct file *file,
>  	if (!LIRC_CAN_REC(ir->d.features))
>  		return -EINVAL;
>  
> -	dev_dbg(ir->d.dev, LOGHEAD "read called\n", ir->d.name, ir->d.minor);
> +	dev_dbg(&ir->dev, "read called\n");
>  
>  	buf = kzalloc(ir->chunk_size, GFP_KERNEL);
>  	if (!buf)
> diff --git a/drivers/staging/media/lirc/lirc_zilog.c b/drivers/staging/media/lirc/lirc_zilog.c
> index ffb70dee4547..131d87a04aab 100644
> --- a/drivers/staging/media/lirc/lirc_zilog.c
> +++ b/drivers/staging/media/lirc/lirc_zilog.c
> @@ -1377,7 +1377,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,
> diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h
> index f7629ff116a9..11f455a34090 100644
> --- a/include/media/lirc_dev.h
> +++ b/include/media/lirc_dev.h
> @@ -120,8 +120,6 @@ 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:		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
> @@ -167,7 +165,6 @@ static inline unsigned int lirc_buffer_write(struct lirc_buffer *buf,
>   * @lirc_internal:	lirc_dev bookkeeping data, don't touch.
>   */
>  struct lirc_driver {
> -	char name[40];
>  	int minor;
>  	__u32 code_length;
>  	unsigned int buffer_size; /* in chunks holding one code each */

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 15/16] lirc_dev: remove name from struct lirc_driver
  2017-05-02 17:04   ` Sean Young
@ 2017-05-02 18:41     ` David Härdeman
  0 siblings, 0 replies; 28+ messages in thread
From: David Härdeman @ 2017-05-02 18:41 UTC (permalink / raw)
  To: Sean Young; +Cc: linux-media, mchehab

On Tue, May 02, 2017 at 06:04:18PM +0100, Sean Young wrote:
>On Mon, May 01, 2017 at 06:04:52PM +0200, David Härdeman wrote:
>> The name is only used for a few debug messages and the name of the parent
>> device as well as the name of the lirc device (e.g. "lirc0") are sufficient
>> anyway.
>>...
>> @@ -207,8 +204,7 @@ lirc_register_driver(struct lirc_driver *d)
>>  	if (err)
>>  		goto out_cdev;
>>  
>> -	dev_info(ir->d.dev, "lirc_dev: driver %s registered at minor = %d\n",
>> -		 ir->d.name, ir->d.minor);
>> +	dev_info(ir->d.dev, "lirc device registered as lirc%d\n", minor);
>
>I'm not so sure this is a good idea. First of all, the documentation says
>you can use "dmesg |grep lirc_dev" to find your lirc devices and you've
>just replaced lirc_dev with lirc.

Sure, no strong preferences here, you could change the line to say
"lirc_dev device...", or drop the patch.

>https://linuxtv.org/downloads/v4l-dvb-apis/uapi/rc/lirc-dev-intro.html
>
>It's useful having the driver name in the message. For example, I have
>two rc devices connected usually:
>
>[sean@bigcore ~]$ dmesg | grep lirc_dev
>[    5.938284] lirc_dev: IR Remote Control driver registered, major 239
>[    5.945324] rc rc0: lirc_dev: driver ir-lirc-codec (winbond-cir) registered at minor = 0
>[ 5111.830118] rc rc1: lirc_dev: driver ir-lirc-codec (mceusb) registered at minor = 1

winbond-cir....good man :)

How about "dmesg | grep lirc -A2 -B2"?

I don't think the situation is that different from how you'd know which
input dev is allocated to any given rc_dev? With this patch applied the
relevant output will be:

[    0.393494] rc rc0: rc-core loopback device as /devices/virtual/rc/rc0
[    0.394458] input: rc-core loopback device as /devices/virtual/rc/rc0/input2
[    0.395717] rc rc0: lirc device registered as lirc0
[   12.612313] rc rc1: mceusb device as /devices/virtual/rc/rc1
[   12.612768] input: mceusb device as /devices/virtual/rc/rc1/input4
[   12.613112] rc rc1: lirc device registered as lirc1

(and we might want to change the lirc line to include the sysfs path?)

But realistically, how much dmesg grepping are we expecting normal
end-users to be doing?

Anyway, as I said, this patch isn't crucial, and we can revisit printk's
later (I'm looking at the ioctl locking right now and I think an
ir-lirc-codec and lirc_dev merger might be a good idea once the fate of
lirc_zilog has been decided).

>With the driver name I know which one is which.
>
>Maybe lirc_driver.name should be a "const char*" so no strcpy is needed
>(the ir-lirc-codec does not seem necessary).

Not that it really pertains to whether d->name should be kept or not,
but I think that lirc_dev shouldn't copy the lirc_driver struct into an
irctl struct internal copy at all, but just keep a normal pointer. I
haven't gotten around to vetting the (ab)use of the lirc_driver struct
yet though.

Regards,
David

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 14/16] lirc_dev: cleanup includes
  2017-05-01 16:04 ` [PATCH 14/16] lirc_dev: cleanup includes David Härdeman
@ 2017-05-19 18:21   ` Sean Young
  2017-05-21  6:51     ` David Härdeman
  0 siblings, 1 reply; 28+ messages in thread
From: Sean Young @ 2017-05-19 18:21 UTC (permalink / raw)
  To: David Härdeman; +Cc: linux-media, mchehab

On Mon, May 01, 2017 at 06:04:47PM +0200, David Härdeman wrote:
> Remove superfluous includes and defines.
> 
> Signed-off-by: David Härdeman <david@hardeman.nu>
> ---
>  drivers/media/rc/lirc_dev.c |   12 +-----------
>  1 file changed, 1 insertion(+), 11 deletions(-)
> 
> diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
> index 7db7d4c57991..4ba6c7e2d41b 100644
> --- a/drivers/media/rc/lirc_dev.c
> +++ b/drivers/media/rc/lirc_dev.c
> @@ -15,20 +15,11 @@
>   *
>   */
>  
> -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> -
>  #include <linux/module.h>
> -#include <linux/kernel.h>
>  #include <linux/sched/signal.h>
> -#include <linux/errno.h>
>  #include <linux/ioctl.h>
> -#include <linux/fs.h>
>  #include <linux/poll.h>
> -#include <linux/completion.h>
>  #include <linux/mutex.h>
> -#include <linux/wait.h>
> -#include <linux/unistd.h>
> -#include <linux/bitops.h>
>  #include <linux/device.h>
>  #include <linux/cdev.h>
>  #include <linux/idr.h>
> @@ -37,7 +28,6 @@
>  #include <media/lirc.h>
>  #include <media/lirc_dev.h>
>  
> -#define IRCTL_DEV_NAME	"BaseRemoteCtl"
>  #define LOGHEAD		"lirc_dev (%s[%d]): "
>  
>  static dev_t lirc_base_dev;
> @@ -545,7 +535,7 @@ static int __init lirc_dev_init(void)
>  	}
>  
>  	retval = alloc_chrdev_region(&lirc_base_dev, 0, LIRC_MAX_DEVICES,
> -				     IRCTL_DEV_NAME);
> +				     "BaseRemoteCtl");

This has always surprised/annoyed me. Why is this called BaseRemoteCtl? As
far as I know, this is only used for /proc/devices, where it says:

$ grep 239 /proc/devices 
239 BaseRemoteCtl

And not lirc, as you would expect.

Sean

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 14/16] lirc_dev: cleanup includes
  2017-05-19 18:21   ` Sean Young
@ 2017-05-21  6:51     ` David Härdeman
  0 siblings, 0 replies; 28+ messages in thread
From: David Härdeman @ 2017-05-21  6:51 UTC (permalink / raw)
  To: Sean Young; +Cc: linux-media, mchehab

On Fri, May 19, 2017 at 07:21:23PM +0100, Sean Young wrote:
>On Mon, May 01, 2017 at 06:04:47PM +0200, David Härdeman wrote:
>> Remove superfluous includes and defines.
>> 
>> Signed-off-by: David Härdeman <david@hardeman.nu>
>> ---
>>  drivers/media/rc/lirc_dev.c |   12 +-----------
>>  1 file changed, 1 insertion(+), 11 deletions(-)
>> 
>> diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
>> index 7db7d4c57991..4ba6c7e2d41b 100644
>> --- a/drivers/media/rc/lirc_dev.c
>> +++ b/drivers/media/rc/lirc_dev.c
>> @@ -15,20 +15,11 @@
>>   *
>>   */
>>  
>> -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
>> -
>>  #include <linux/module.h>
>> -#include <linux/kernel.h>
>>  #include <linux/sched/signal.h>
>> -#include <linux/errno.h>
>>  #include <linux/ioctl.h>
>> -#include <linux/fs.h>
>>  #include <linux/poll.h>
>> -#include <linux/completion.h>
>>  #include <linux/mutex.h>
>> -#include <linux/wait.h>
>> -#include <linux/unistd.h>
>> -#include <linux/bitops.h>
>>  #include <linux/device.h>
>>  #include <linux/cdev.h>
>>  #include <linux/idr.h>
>> @@ -37,7 +28,6 @@
>>  #include <media/lirc.h>
>>  #include <media/lirc_dev.h>
>>  
>> -#define IRCTL_DEV_NAME	"BaseRemoteCtl"
>>  #define LOGHEAD		"lirc_dev (%s[%d]): "
>>  
>>  static dev_t lirc_base_dev;
>> @@ -545,7 +535,7 @@ static int __init lirc_dev_init(void)
>>  	}
>>  
>>  	retval = alloc_chrdev_region(&lirc_base_dev, 0, LIRC_MAX_DEVICES,
>> -				     IRCTL_DEV_NAME);
>> +				     "BaseRemoteCtl");
>
>This has always surprised/annoyed me. Why is this called BaseRemoteCtl? As
>far as I know, this is only used for /proc/devices, where it says:
>
>$ grep 239 /proc/devices 
>239 BaseRemoteCtl
>
>And not lirc, as you would expect.

Yeah, I also find it a bit of an ugly wart. I didn't dare to change it
though since userspace might rely on "BaseRemoteCtl". For example:
https://build.opensuse.org/package/view_file/openSUSE:12.2/lirc/rc.lirc?expand=1)

-- 
David Härdeman

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 03/16] lirc_dev: correct error handling
  2017-05-01 16:03 ` [PATCH 03/16] lirc_dev: correct error handling David Härdeman
@ 2017-05-21  8:57   ` Sean Young
  2017-05-28  8:23     ` David Härdeman
  0 siblings, 1 reply; 28+ messages in thread
From: Sean Young @ 2017-05-21  8:57 UTC (permalink / raw)
  To: David Härdeman; +Cc: linux-media, mchehab

On Mon, May 01, 2017 at 06:03:51PM +0200, David Härdeman wrote:
> If an error is generated, nonseekable_open() shouldn't be called.

There is no harm in calling nonseekable_open(), so this commit is
misleading.

Sean

> 
> Signed-off-by: David Härdeman <david@hardeman.nu>
> ---
>  drivers/media/rc/lirc_dev.c |    6 ++++--
>  1 file changed, 4 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
> index 05f600bd6c67..7f13ed479e1c 100644
> --- a/drivers/media/rc/lirc_dev.c
> +++ b/drivers/media/rc/lirc_dev.c
> @@ -431,7 +431,7 @@ EXPORT_SYMBOL(lirc_unregister_driver);
>  int lirc_dev_fop_open(struct inode *inode, struct file *file)
>  {
>  	struct irctl *ir;
> -	int retval = 0;
> +	int retval;
>  
>  	if (iminor(inode) >= MAX_IRCTL_DEVICES) {
>  		pr_err("open result for %d is -ENODEV\n", iminor(inode));
> @@ -475,9 +475,11 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file)
>  
>  	ir->open++;
>  
> -error:
>  	nonseekable_open(inode, file);
>  
> +	return 0;
> +
> +error:
>  	return retval;
>  }
>  EXPORT_SYMBOL(lirc_dev_fop_open);

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 13/16] lirc_dev: use an ida instead of a hand-rolled array to keep track of minors
  2017-05-01 16:04 ` [PATCH 13/16] lirc_dev: use an ida instead of a hand-rolled array to keep track of minors David Härdeman
@ 2017-05-22 20:09   ` Sean Young
  2017-05-28  8:26     ` David Härdeman
  0 siblings, 1 reply; 28+ messages in thread
From: Sean Young @ 2017-05-22 20:09 UTC (permalink / raw)
  To: David Härdeman; +Cc: linux-media, mchehab

On Mon, May 01, 2017 at 06:04:42PM +0200, David Härdeman wrote:
> Using the kernel ida facilities, we can avoid a lot of unnecessary code and at the same
> time get rid of lirc_dev_lock in favour of per-device locks (the irctls array was used
> throughout lirc_dev so this patch necessarily touches a lot of code).
> 
> Signed-off-by: David Härdeman <david@hardeman.nu>
> ---
>  drivers/media/rc/ir-lirc-codec.c        |    9 -
>  drivers/media/rc/lirc_dev.c             |  258 ++++++++++++-------------------
>  drivers/staging/media/lirc/lirc_zilog.c |   16 +-
>  include/media/lirc_dev.h                |   14 --
>  4 files changed, 115 insertions(+), 182 deletions(-)
> 
> diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c
> index a30af91710fe..2c1221a61ea1 100644
> --- a/drivers/media/rc/ir-lirc-codec.c
> +++ b/drivers/media/rc/ir-lirc-codec.c
> @@ -382,7 +382,6 @@ static int ir_lirc_register(struct rc_dev *dev)
>  
>  	snprintf(drv->name, sizeof(drv->name), "ir-lirc-codec (%s)",
>  		 dev->driver_name);
> -	drv->minor = -1;
>  	drv->features = features;
>  	drv->data = &dev->raw->lirc;
>  	drv->rbuf = NULL;
> @@ -394,11 +393,9 @@ static int ir_lirc_register(struct rc_dev *dev)
>  	drv->rdev = dev;
>  	drv->owner = THIS_MODULE;
>  
> -	drv->minor = lirc_register_driver(drv);
> -	if (drv->minor < 0) {
> -		rc = -ENODEV;
> +	rc = lirc_register_driver(drv);
> +	if (rc < 0)
>  		goto out;
> -	}
>  
>  	dev->raw->lirc.drv = drv;
>  	dev->raw->lirc.dev = dev;
> @@ -413,7 +410,7 @@ static int ir_lirc_unregister(struct rc_dev *dev)
>  {
>  	struct lirc_codec *lirc = &dev->raw->lirc;
>  
> -	lirc_unregister_driver(lirc->drv->minor);
> +	lirc_unregister_driver(lirc->drv);
>  	kfree(lirc->drv);
>  	lirc->drv = NULL;
>  
> diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
> index e44e0b23b883..7db7d4c57991 100644
> --- a/drivers/media/rc/lirc_dev.c
> +++ b/drivers/media/rc/lirc_dev.c
> @@ -31,23 +31,35 @@
>  #include <linux/bitops.h>
>  #include <linux/device.h>
>  #include <linux/cdev.h>
> +#include <linux/idr.h>
>  
>  #include <media/rc-core.h>
>  #include <media/lirc.h>
>  #include <media/lirc_dev.h>
>  
>  #define IRCTL_DEV_NAME	"BaseRemoteCtl"
> -#define NOPLUG		-1
>  #define LOGHEAD		"lirc_dev (%s[%d]): "
>  
>  static dev_t lirc_base_dev;
>  
> +/**
> + * struct irctl - lirc per-device structure
> + * @d:			internal copy of the &struct lirc_driver for the device
> + * @dead:		if the device has gone away
> + * @users:		the number of users of the lirc chardev (currently limited to 1)
> + * @mutex:		synchronizes open()/close()/ioctl()/etc calls
> + * @buf:		used to store lirc RX data
> + * @buf_internal:	whether @buf was allocated internally or not
> + * @chunk_size:		@buf stores and read() returns data chunks of this size
> + * @dev:		the &struct device for the lirc device
> + * @cdev:		the &struct device for the lirc chardev
> + */
>  struct irctl {
>  	struct lirc_driver d;
> -	int attached;
> -	int open;
> +	bool dead;
> +	unsigned users;
>  
> -	struct mutex irctl_lock;
> +	struct mutex mutex;
>  	struct lirc_buffer *buf;
>  	bool buf_internal;
>  	unsigned int chunk_size;
> @@ -56,9 +68,9 @@ struct irctl {
>  	struct cdev cdev;
>  };
>  
> -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;
> @@ -72,9 +84,6 @@ static void lirc_release(struct device *ld)
>  		kfree(ir->buf);
>  	}
>  
> -	mutex_lock(&lirc_dev_lock);
> -	irctls[ir->d.minor] = NULL;
> -	mutex_unlock(&lirc_dev_lock);
>  	kfree(ir);
>  }
>  
> @@ -117,7 +126,18 @@ static int lirc_allocate_buffer(struct irctl *ir)
>  	return err;
>  }
>  
> -int lirc_register_driver(struct lirc_driver *d)
> +/**
> + * lirc_register_driver() - create a new lirc device by registering a driver
> + * @d: the &struct lirc_driver to register
> + *
> + * This function allocates and registers a lirc device for a given
> + * &lirc_driver. The &lirc_driver structure is updated to contain
> + * information about the allocated device (minor, buffer, etc).
> + *
> + * Return: zero on success or a negative error value.
> + */
> +int
> +lirc_register_driver(struct lirc_driver *d)
>  {
>  	struct irctl *ir;
>  	int minor;
> @@ -138,12 +158,6 @@ int lirc_register_driver(struct lirc_driver *d)
>  		return -EINVAL;
>  	}
>  
> -	if (d->minor >= MAX_IRCTL_DEVICES) {
> -		dev_err(d->dev, "minor must be between 0 and %d!\n",
> -						MAX_IRCTL_DEVICES - 1);
> -		return -EBADRQC;
> -	}
> -
>  	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);
> @@ -156,49 +170,30 @@ int lirc_register_driver(struct lirc_driver *d)
>  		return -EBADRQC;
>  	}
>  
> -	mutex_lock(&lirc_dev_lock);
> -
> -	minor = d->minor;
> +	d->name[sizeof(d->name)-1] = '\0';
> +	if (d->features == 0)
> +		d->features = LIRC_CAN_REC_LIRCCODE;
>  
> -	if (minor < 0) {
> -		/* 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");
> -			err = -ENOMEM;
> -			goto out_lock;
> -		}
> -	} else if (irctls[minor]) {
> -		dev_err(d->dev, "minor (%d) just registered!\n", minor);
> -		err = -EBUSY;
> -		goto out_lock;
> -	}
> +	minor = ida_simple_get(&lirc_ida, 0, LIRC_MAX_DEVICES, GFP_KERNEL);
> +	if (minor < 0)
> +		return minor;
> +	d->minor = minor;
>  
>  	ir = kzalloc(sizeof(struct irctl), GFP_KERNEL);
>  	if (!ir) {
>  		err = -ENOMEM;
> -		goto out_lock;
> +		goto out_minor;
>  	}
>  
> -	mutex_init(&ir->irctl_lock);
> -	irctls[minor] = ir;
> -	d->minor = minor;
> -
> -	/* some safety check 8-) */
> -	d->name[sizeof(d->name)-1] = '\0';
> -
> -	if (d->features == 0)
> -		d->features = LIRC_CAN_REC_LIRCCODE;
> +	mutex_init(&ir->mutex);
>  
>  	ir->d = *d;

Here we copy lirc_driver.

>  
>  	if (LIRC_CAN_REC(d->features)) {
> -		err = lirc_allocate_buffer(irctls[minor]);
> +		err = lirc_allocate_buffer(ir);
>  		if (err) {
>  			kfree(ir);
> -			goto out_lock;
> +			goto out_minor;
>  		}
>  		d->rbuf = ir->buf;
>  	}
> @@ -218,107 +213,82 @@ int lirc_register_driver(struct lirc_driver *d)
>  	if (err)
>  		goto out_free_dev;
>  
> -	ir->attached = 1;
> -
>  	err = device_add(&ir->dev);
>  	if (err)
>  		goto out_cdev;
>  
> -	mutex_unlock(&lirc_dev_lock);
> -
>  	dev_info(ir->d.dev, "lirc_dev: driver %s registered at minor = %d\n",
>  		 ir->d.name, ir->d.minor);
>  
> -	return minor;
> +	d->lirc_internal = ir;

And now a store a pointer to the copy in the original lirc_driver. 

It would be much better to not copy lirc_driver and the lirc_internal
member would be unnecessary.

> +	return 0;
>  
>  out_cdev:
>  	cdev_del(&ir->cdev);
>  out_free_dev:
>  	put_device(&ir->dev);
> -out_lock:
> -	mutex_unlock(&lirc_dev_lock);
> +out_minor:
> +	ida_simple_remove(&lirc_ida, minor);
>  
>  	return err;
>  }
>  EXPORT_SYMBOL(lirc_register_driver);
>  
> -int lirc_unregister_driver(int minor)
> +/**
> + * lirc_unregister_driver() - remove the lirc device for a given driver
> + * @d: the &struct lirc_driver to unregister
> + *
> + * This function unregisters the lirc device for a given &lirc_driver.
> + */
> +void
> +lirc_unregister_driver(struct lirc_driver *d)
>  {
>  	struct irctl *ir;
>  
> -	if (minor < 0 || minor >= MAX_IRCTL_DEVICES) {
> -		pr_err("minor (%d) must be between 0 and %d!\n",
> -					minor, MAX_IRCTL_DEVICES - 1);
> -		return -EBADRQC;
> -	}
> +	if (!d->lirc_internal)
> +		return;
>  
> -	ir = irctls[minor];
> -	if (!ir) {
> -		pr_err("failed to get irctl\n");
> -		return -ENOENT;
> -	}
> +	ir = d->lirc_internal;

This is done to find a our copy again.

> -	mutex_lock(&lirc_dev_lock);
> -
> -	if (ir->d.minor != minor) {
> -		dev_err(ir->d.dev, "lirc_dev: minor %d device not registered\n",
> -									minor);
> -		mutex_unlock(&lirc_dev_lock);
> -		return -ENOENT;
> -	}
> +	mutex_lock(&ir->mutex);
>  
>  	dev_dbg(ir->d.dev, "lirc_dev: driver %s unregistered from minor = %d\n",
>  		ir->d.name, ir->d.minor);
>  
> -	ir->attached = 0;
> -	if (ir->open) {
> +	ir->dead = true;
> +	if (ir->users) {
>  		dev_dbg(ir->d.dev, LOGHEAD "releasing opened driver\n",
>  			ir->d.name, ir->d.minor);
>  		wake_up_interruptible(&ir->buf->wait_poll);
>  	}
>  
> -	mutex_unlock(&lirc_dev_lock);
> +	mutex_unlock(&ir->mutex);
>  
>  	device_del(&ir->dev);
>  	cdev_del(&ir->cdev);
> -	put_device(&ir->dev);
> -
> -	return 0;
> +	ida_simple_remove(&lirc_ida, d->minor);
> +	d->minor = -1;
> +	d->lirc_internal = NULL;
>  }
>  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;
> +	mutex_lock(&ir->mutex);
>  
> -	ir = irctls[iminor(inode)];
> -	mutex_unlock(&lirc_dev_lock);
> -
> -	if (!ir) {
> -		retval = -ENODEV;
> +	if (ir->users) {
> +		retval = -EBUSY;
> +		mutex_unlock(&ir->mutex);
>  		goto error;
>  	}
> +	ir->users++;
>  
> -	dev_dbg(ir->d.dev, LOGHEAD "open called\n", ir->d.name, ir->d.minor);
> -
> -	if (ir->d.minor == NOPLUG) {
> -		retval = -ENODEV;
> -		goto error;
> -	}
> +	mutex_unlock(&ir->mutex);
>  
> -	if (ir->open) {
> -		retval = -EBUSY;
> -		goto error;
> -	}
> +	dev_dbg(ir->d.dev, LOGHEAD "open called\n", ir->d.name, ir->d.minor);
>  
>  	if (ir->d.rdev) {
>  		retval = rc_open(ir->d.rdev);
> @@ -329,8 +299,7 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file)
>  	if (ir->buf)
>  		lirc_buffer_clear(ir->buf);
>  
> -	ir->open++;
> -
> +	file->private_data = ir;
>  	nonseekable_open(inode, file);
>  
>  	return 0;
> @@ -342,22 +311,14 @@ EXPORT_SYMBOL(lirc_dev_fop_open);
>  
>  int lirc_dev_fop_close(struct inode *inode, struct file *file)
>  {
> -	struct irctl *ir = irctls[iminor(inode)];
> -	int ret;
> -
> -	if (!ir) {
> -		pr_err("called with invalid irctl\n");
> -		return -EINVAL;
> -	}
> +	struct irctl *ir = file->private_data;
>  
> -	ret = mutex_lock_killable(&lirc_dev_lock);
> -	WARN_ON(ret);
> +	mutex_lock(&ir->mutex);
>  
>  	rc_close(ir->d.rdev);
> +	ir->users--;
>  
> -	ir->open--;
> -	if (!ret)
> -		mutex_unlock(&lirc_dev_lock);
> +	mutex_unlock(&ir->mutex);
>  
>  	return 0;
>  }
> @@ -365,26 +326,21 @@ 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)
> +	if (ir->dead)
>  		return POLLHUP | POLLERR;
>  
> -	if (ir->buf) {
> -		poll_wait(file, &ir->buf->wait_poll, wait);
> +	if (!ir->buf)
> +		return POLLERR;
> +
> +	poll_wait(file, &ir->buf->wait_poll, wait);
>  
> -		if (lirc_buffer_empty(ir->buf))
> -			ret = 0;
> -		else
> -			ret = POLLIN | POLLRDNORM;
> -	} else
> -		ret = POLLERR;
> +	if (lirc_buffer_empty(ir->buf))
> +		ret = 0;
> +	else
> +		ret = POLLIN | POLLRDNORM;
>  
>  	dev_dbg(ir->d.dev, LOGHEAD "poll result = %d\n",
>  		ir->d.name, ir->d.minor, ret);
> @@ -395,25 +351,20 @@ 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);
>  
> -	if (ir->d.minor == NOPLUG || !ir->attached) {
> +	if (ir->dead) {
>  		dev_err(ir->d.dev, LOGHEAD "ioctl result = -ENODEV\n",
>  			ir->d.name, ir->d.minor);
>  		return -ENODEV;
>  	}
>  
> -	mutex_lock(&ir->irctl_lock);
> +	mutex_lock(&ir->mutex);
>  
>  	switch (cmd) {
>  	case LIRC_GET_FEATURES:
> @@ -468,7 +419,7 @@ long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
>  		result = -ENOTTY;
>  	}
>  
> -	mutex_unlock(&ir->irctl_lock);
> +	mutex_unlock(&ir->mutex);
>  
>  	return result;
>  }
> @@ -479,16 +430,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;
>  
> @@ -498,11 +444,12 @@ ssize_t lirc_dev_fop_read(struct file *file,
>  	if (!buf)
>  		return -ENOMEM;
>  
> -	if (mutex_lock_interruptible(&ir->irctl_lock)) {
> +	if (mutex_lock_interruptible(&ir->mutex)) {
>  		ret = -ERESTARTSYS;
>  		goto out_unlocked;
>  	}
> -	if (!ir->attached) {
> +
> +	if (ir->dead) {
>  		ret = -ENODEV;
>  		goto out_locked;
>  	}
> @@ -541,18 +488,18 @@ ssize_t lirc_dev_fop_read(struct file *file,
>  				break;
>  			}
>  
> -			mutex_unlock(&ir->irctl_lock);
> +			mutex_unlock(&ir->mutex);
>  			set_current_state(TASK_INTERRUPTIBLE);
>  			schedule();
>  			set_current_state(TASK_RUNNING);
>  
> -			if (mutex_lock_interruptible(&ir->irctl_lock)) {
> +			if (mutex_lock_interruptible(&ir->mutex)) {
>  				ret = -ERESTARTSYS;
>  				remove_wait_queue(&ir->buf->wait_poll, &wait);
>  				goto out_unlocked;
>  			}
>  
> -			if (!ir->attached) {
> +			if (ir->dead) {
>  				ret = -ENODEV;
>  				goto out_locked;
>  			}
> @@ -570,7 +517,7 @@ ssize_t lirc_dev_fop_read(struct file *file,
>  	remove_wait_queue(&ir->buf->wait_poll, &wait);
>  
>  out_locked:
> -	mutex_unlock(&ir->irctl_lock);
> +	mutex_unlock(&ir->mutex);
>  
>  out_unlocked:
>  	kfree(buf);
> @@ -581,7 +528,8 @@ EXPORT_SYMBOL(lirc_dev_fop_read);
>  
>  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);
>  
> @@ -596,7 +544,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,
>  				     IRCTL_DEV_NAME);
>  	if (retval) {
>  		class_destroy(lirc_class);
> @@ -613,7 +561,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/drivers/staging/media/lirc/lirc_zilog.c b/drivers/staging/media/lirc/lirc_zilog.c
> index 59e05aa1bc55..ffb70dee4547 100644
> --- a/drivers/staging/media/lirc/lirc_zilog.c
> +++ b/drivers/staging/media/lirc/lirc_zilog.c
> @@ -183,11 +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
>  	 */
> -	if (ir->l.minor >= 0) {
> -		lirc_unregister_driver(ir->l.minor);
> -		ir->l.minor = -1;
> -	}
> -
> +	lirc_unregister_driver(&ir->l);
>  	if (kfifo_initialized(&ir->rbuf.fifo))
>  		lirc_buffer_free(&ir->rbuf);
>  	list_del(&ir->list);
> @@ -1382,7 +1378,6 @@ static const struct file_operations lirc_fops = {
>  
>  static struct lirc_driver lirc_template = {
>  	.name		= "lirc_zilog",
> -	.minor		= -1,
>  	.code_length	= 13,
>  	.buffer_size	= BUFLEN / 2,
>  	.chunk_size	= 2,
> @@ -1597,14 +1592,13 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
>  	}
>  
>  	/* register with lirc */
> -	ir->l.minor = lirc_register_driver(&ir->l);
> -	if (ir->l.minor < 0) {
> +	ret = lirc_register_driver(&ir->l);
> +	if (ret < 0) {
>  		dev_err(tx->ir->l.dev,
> -			"%s: lirc_register_driver() failed: %i\n",
> -			__func__, ir->l.minor);
> -		ret = -EBADRQC;
> +			"%s: lirc_register_driver failed: %i\n", __func__, ret);
>  		goto out_put_xx;
>  	}
> +
>  	dev_info(ir->l.dev,
>  		 "IR unit on %s (i2c-%d) registered as lirc%d and ready\n",
>  		 adap->name, adap->nr, ir->l.minor);
> diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h
> index 1f327e25a9be..f7629ff116a9 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
>  
>  #define mod(n, div) ((n) % (div))
> @@ -164,6 +163,8 @@ static inline unsigned int lirc_buffer_write(struct lirc_buffer *buf,
>   *			device.
>   *
>   * @owner:		the module owning this struct
> + *
> + * @lirc_internal:	lirc_dev bookkeeping data, don't touch.

It's not a great name or comment :)

Otherwise, it's a good idea.


Sean

>   */
>  struct lirc_driver {
>  	char name[40];
> @@ -182,19 +183,12 @@ struct lirc_driver {
>  	const struct file_operations *fops;
>  	struct device *dev;
>  	struct module *owner;
> +	void *lirc_internal;
>  };
>  
> -/* following functions can be called ONLY from user context
> - *
> - * returns negative value on error or minor number
> - * of the registered device if success
> - * contents of the structure pointed by p is copied
> - */
>  extern int lirc_register_driver(struct lirc_driver *d);
>  
> -/* returns negative value on error or 0 if success
> -*/
> -extern int lirc_unregister_driver(int minor);
> +extern void lirc_unregister_driver(struct lirc_driver *d);
>  
>  /* Returns the private data stored in the lirc_driver
>   * associated with the given device file pointer.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 03/16] lirc_dev: correct error handling
  2017-05-21  8:57   ` Sean Young
@ 2017-05-28  8:23     ` David Härdeman
  2017-05-28 15:04       ` Sean Young
  0 siblings, 1 reply; 28+ messages in thread
From: David Härdeman @ 2017-05-28  8:23 UTC (permalink / raw)
  To: Sean Young; +Cc: linux-media, mchehab

On Sun, May 21, 2017 at 09:57:13AM +0100, Sean Young wrote:
>On Mon, May 01, 2017 at 06:03:51PM +0200, David Härdeman wrote:
>> If an error is generated, nonseekable_open() shouldn't be called.
>
>There is no harm in calling nonseekable_open(), so this commit is
>misleading.

I'm not sure why you consider it misleading? If there's an error, the
logic thing to do is to error out immediately and not do any further
work?

>> Signed-off-by: David Härdeman <david@hardeman.nu>
>> ---
>>  drivers/media/rc/lirc_dev.c |    6 ++++--
>>  1 file changed, 4 insertions(+), 2 deletions(-)
>> 
>> diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
>> index 05f600bd6c67..7f13ed479e1c 100644
>> --- a/drivers/media/rc/lirc_dev.c
>> +++ b/drivers/media/rc/lirc_dev.c
>> @@ -431,7 +431,7 @@ EXPORT_SYMBOL(lirc_unregister_driver);
>>  int lirc_dev_fop_open(struct inode *inode, struct file *file)
>>  {
>>  	struct irctl *ir;
>> -	int retval = 0;
>> +	int retval;
>>  
>>  	if (iminor(inode) >= MAX_IRCTL_DEVICES) {
>>  		pr_err("open result for %d is -ENODEV\n", iminor(inode));
>> @@ -475,9 +475,11 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file)
>>  
>>  	ir->open++;
>>  
>> -error:
>>  	nonseekable_open(inode, file);
>>  
>> +	return 0;
>> +
>> +error:
>>  	return retval;
>>  }
>>  EXPORT_SYMBOL(lirc_dev_fop_open);

-- 
David Härdeman

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 13/16] lirc_dev: use an ida instead of a hand-rolled array to keep track of minors
  2017-05-22 20:09   ` Sean Young
@ 2017-05-28  8:26     ` David Härdeman
  2017-05-28 15:08       ` Sean Young
  0 siblings, 1 reply; 28+ messages in thread
From: David Härdeman @ 2017-05-28  8:26 UTC (permalink / raw)
  To: Sean Young; +Cc: linux-media, mchehab

On Mon, May 22, 2017 at 09:09:42PM +0100, Sean Young wrote:
>On Mon, May 01, 2017 at 06:04:42PM +0200, David Härdeman wrote:
>> Using the kernel ida facilities, we can avoid a lot of unnecessary code and at the same
>> time get rid of lirc_dev_lock in favour of per-device locks (the irctls array was used
>> throughout lirc_dev so this patch necessarily touches a lot of code).
>> 
>> Signed-off-by: David Härdeman <david@hardeman.nu>
>> ---
>>  drivers/media/rc/ir-lirc-codec.c        |    9 -
>>  drivers/media/rc/lirc_dev.c             |  258 ++++++++++++-------------------
>>  drivers/staging/media/lirc/lirc_zilog.c |   16 +-
>>  include/media/lirc_dev.h                |   14 --
>>  4 files changed, 115 insertions(+), 182 deletions(-)
>> 
>> diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c
>> index a30af91710fe..2c1221a61ea1 100644
>> --- a/drivers/media/rc/ir-lirc-codec.c
>> +++ b/drivers/media/rc/ir-lirc-codec.c
>> @@ -382,7 +382,6 @@ static int ir_lirc_register(struct rc_dev *dev)
>>  
>>  	snprintf(drv->name, sizeof(drv->name), "ir-lirc-codec (%s)",
>>  		 dev->driver_name);
>> -	drv->minor = -1;
>>  	drv->features = features;
>>  	drv->data = &dev->raw->lirc;
>>  	drv->rbuf = NULL;
>> @@ -394,11 +393,9 @@ static int ir_lirc_register(struct rc_dev *dev)
>>  	drv->rdev = dev;
>>  	drv->owner = THIS_MODULE;
>>  
>> -	drv->minor = lirc_register_driver(drv);
>> -	if (drv->minor < 0) {
>> -		rc = -ENODEV;
>> +	rc = lirc_register_driver(drv);
>> +	if (rc < 0)
>>  		goto out;
>> -	}
>>  
>>  	dev->raw->lirc.drv = drv;
>>  	dev->raw->lirc.dev = dev;
>> @@ -413,7 +410,7 @@ static int ir_lirc_unregister(struct rc_dev *dev)
>>  {
>>  	struct lirc_codec *lirc = &dev->raw->lirc;
>>  
>> -	lirc_unregister_driver(lirc->drv->minor);
>> +	lirc_unregister_driver(lirc->drv);
>>  	kfree(lirc->drv);
>>  	lirc->drv = NULL;
>>  
>> diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
>> index e44e0b23b883..7db7d4c57991 100644
>> --- a/drivers/media/rc/lirc_dev.c
>> +++ b/drivers/media/rc/lirc_dev.c
>> @@ -31,23 +31,35 @@
>>  #include <linux/bitops.h>
>>  #include <linux/device.h>
>>  #include <linux/cdev.h>
>> +#include <linux/idr.h>
>>  
>>  #include <media/rc-core.h>
>>  #include <media/lirc.h>
>>  #include <media/lirc_dev.h>
>>  
>>  #define IRCTL_DEV_NAME	"BaseRemoteCtl"
>> -#define NOPLUG		-1
>>  #define LOGHEAD		"lirc_dev (%s[%d]): "
>>  
>>  static dev_t lirc_base_dev;
>>  
>> +/**
>> + * struct irctl - lirc per-device structure
>> + * @d:			internal copy of the &struct lirc_driver for the device
>> + * @dead:		if the device has gone away
>> + * @users:		the number of users of the lirc chardev (currently limited to 1)
>> + * @mutex:		synchronizes open()/close()/ioctl()/etc calls
>> + * @buf:		used to store lirc RX data
>> + * @buf_internal:	whether @buf was allocated internally or not
>> + * @chunk_size:		@buf stores and read() returns data chunks of this size
>> + * @dev:		the &struct device for the lirc device
>> + * @cdev:		the &struct device for the lirc chardev
>> + */
>>  struct irctl {
>>  	struct lirc_driver d;
>> -	int attached;
>> -	int open;
>> +	bool dead;
>> +	unsigned users;
>>  
>> -	struct mutex irctl_lock;
>> +	struct mutex mutex;
>>  	struct lirc_buffer *buf;
>>  	bool buf_internal;
>>  	unsigned int chunk_size;
>> @@ -56,9 +68,9 @@ struct irctl {
>>  	struct cdev cdev;
>>  };
>>  
>> -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;
>> @@ -72,9 +84,6 @@ static void lirc_release(struct device *ld)
>>  		kfree(ir->buf);
>>  	}
>>  
>> -	mutex_lock(&lirc_dev_lock);
>> -	irctls[ir->d.minor] = NULL;
>> -	mutex_unlock(&lirc_dev_lock);
>>  	kfree(ir);
>>  }
>>  
>> @@ -117,7 +126,18 @@ static int lirc_allocate_buffer(struct irctl *ir)
>>  	return err;
>>  }
>>  
>> -int lirc_register_driver(struct lirc_driver *d)
>> +/**
>> + * lirc_register_driver() - create a new lirc device by registering a driver
>> + * @d: the &struct lirc_driver to register
>> + *
>> + * This function allocates and registers a lirc device for a given
>> + * &lirc_driver. The &lirc_driver structure is updated to contain
>> + * information about the allocated device (minor, buffer, etc).
>> + *
>> + * Return: zero on success or a negative error value.
>> + */
>> +int
>> +lirc_register_driver(struct lirc_driver *d)
>>  {
>>  	struct irctl *ir;
>>  	int minor;
>> @@ -138,12 +158,6 @@ int lirc_register_driver(struct lirc_driver *d)
>>  		return -EINVAL;
>>  	}
>>  
>> -	if (d->minor >= MAX_IRCTL_DEVICES) {
>> -		dev_err(d->dev, "minor must be between 0 and %d!\n",
>> -						MAX_IRCTL_DEVICES - 1);
>> -		return -EBADRQC;
>> -	}
>> -
>>  	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);
>> @@ -156,49 +170,30 @@ int lirc_register_driver(struct lirc_driver *d)
>>  		return -EBADRQC;
>>  	}
>>  
>> -	mutex_lock(&lirc_dev_lock);
>> -
>> -	minor = d->minor;
>> +	d->name[sizeof(d->name)-1] = '\0';
>> +	if (d->features == 0)
>> +		d->features = LIRC_CAN_REC_LIRCCODE;
>>  
>> -	if (minor < 0) {
>> -		/* 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");
>> -			err = -ENOMEM;
>> -			goto out_lock;
>> -		}
>> -	} else if (irctls[minor]) {
>> -		dev_err(d->dev, "minor (%d) just registered!\n", minor);
>> -		err = -EBUSY;
>> -		goto out_lock;
>> -	}
>> +	minor = ida_simple_get(&lirc_ida, 0, LIRC_MAX_DEVICES, GFP_KERNEL);
>> +	if (minor < 0)
>> +		return minor;
>> +	d->minor = minor;
>>  
>>  	ir = kzalloc(sizeof(struct irctl), GFP_KERNEL);
>>  	if (!ir) {
>>  		err = -ENOMEM;
>> -		goto out_lock;
>> +		goto out_minor;
>>  	}
>>  
>> -	mutex_init(&ir->irctl_lock);
>> -	irctls[minor] = ir;
>> -	d->minor = minor;
>> -
>> -	/* some safety check 8-) */
>> -	d->name[sizeof(d->name)-1] = '\0';
>> -
>> -	if (d->features == 0)
>> -		d->features = LIRC_CAN_REC_LIRCCODE;
>> +	mutex_init(&ir->mutex);
>>  
>>  	ir->d = *d;
>
>Here we copy lirc_driver.
>
>>  
>>  	if (LIRC_CAN_REC(d->features)) {
>> -		err = lirc_allocate_buffer(irctls[minor]);
>> +		err = lirc_allocate_buffer(ir);
>>  		if (err) {
>>  			kfree(ir);
>> -			goto out_lock;
>> +			goto out_minor;
>>  		}
>>  		d->rbuf = ir->buf;
>>  	}
>> @@ -218,107 +213,82 @@ int lirc_register_driver(struct lirc_driver *d)
>>  	if (err)
>>  		goto out_free_dev;
>>  
>> -	ir->attached = 1;
>> -
>>  	err = device_add(&ir->dev);
>>  	if (err)
>>  		goto out_cdev;
>>  
>> -	mutex_unlock(&lirc_dev_lock);
>> -
>>  	dev_info(ir->d.dev, "lirc_dev: driver %s registered at minor = %d\n",
>>  		 ir->d.name, ir->d.minor);
>>  
>> -	return minor;
>> +	d->lirc_internal = ir;
>
>And now a store a pointer to the copy in the original lirc_driver. 
>
>It would be much better to not copy lirc_driver and the lirc_internal
>member would be unnecessary.

I know, but this is a more minimal fix. The struct copy is already in
the current code and I'd prefer removing it in a separate patch once the
use of lirc_driver has been vetted.

>> +	return 0;
>>  
>>  out_cdev:
>>  	cdev_del(&ir->cdev);
>>  out_free_dev:
>>  	put_device(&ir->dev);
>> -out_lock:
>> -	mutex_unlock(&lirc_dev_lock);
>> +out_minor:
>> +	ida_simple_remove(&lirc_ida, minor);
>>  
>>  	return err;
>>  }
>>  EXPORT_SYMBOL(lirc_register_driver);
>>  
>> -int lirc_unregister_driver(int minor)
>> +/**
>> + * lirc_unregister_driver() - remove the lirc device for a given driver
>> + * @d: the &struct lirc_driver to unregister
>> + *
>> + * This function unregisters the lirc device for a given &lirc_driver.
>> + */
>> +void
>> +lirc_unregister_driver(struct lirc_driver *d)
>>  {
>>  	struct irctl *ir;
>>  
>> -	if (minor < 0 || minor >= MAX_IRCTL_DEVICES) {
>> -		pr_err("minor (%d) must be between 0 and %d!\n",
>> -					minor, MAX_IRCTL_DEVICES - 1);
>> -		return -EBADRQC;
>> -	}
>> +	if (!d->lirc_internal)
>> +		return;
>>  
>> -	ir = irctls[minor];
>> -	if (!ir) {
>> -		pr_err("failed to get irctl\n");
>> -		return -ENOENT;
>> -	}
>> +	ir = d->lirc_internal;
>
>This is done to find a our copy again.
>
>> -	mutex_lock(&lirc_dev_lock);
>> -
>> -	if (ir->d.minor != minor) {
>> -		dev_err(ir->d.dev, "lirc_dev: minor %d device not registered\n",
>> -									minor);
>> -		mutex_unlock(&lirc_dev_lock);
>> -		return -ENOENT;
>> -	}
>> +	mutex_lock(&ir->mutex);
>>  
>>  	dev_dbg(ir->d.dev, "lirc_dev: driver %s unregistered from minor = %d\n",
>>  		ir->d.name, ir->d.minor);
>>  
>> -	ir->attached = 0;
>> -	if (ir->open) {
>> +	ir->dead = true;
>> +	if (ir->users) {
>>  		dev_dbg(ir->d.dev, LOGHEAD "releasing opened driver\n",
>>  			ir->d.name, ir->d.minor);
>>  		wake_up_interruptible(&ir->buf->wait_poll);
>>  	}
>>  
>> -	mutex_unlock(&lirc_dev_lock);
>> +	mutex_unlock(&ir->mutex);
>>  
>>  	device_del(&ir->dev);
>>  	cdev_del(&ir->cdev);
>> -	put_device(&ir->dev);
>> -
>> -	return 0;
>> +	ida_simple_remove(&lirc_ida, d->minor);
>> +	d->minor = -1;
>> +	d->lirc_internal = NULL;
>>  }
>>  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;
>> +	mutex_lock(&ir->mutex);
>>  
>> -	ir = irctls[iminor(inode)];
>> -	mutex_unlock(&lirc_dev_lock);
>> -
>> -	if (!ir) {
>> -		retval = -ENODEV;
>> +	if (ir->users) {
>> +		retval = -EBUSY;
>> +		mutex_unlock(&ir->mutex);
>>  		goto error;
>>  	}
>> +	ir->users++;
>>  
>> -	dev_dbg(ir->d.dev, LOGHEAD "open called\n", ir->d.name, ir->d.minor);
>> -
>> -	if (ir->d.minor == NOPLUG) {
>> -		retval = -ENODEV;
>> -		goto error;
>> -	}
>> +	mutex_unlock(&ir->mutex);
>>  
>> -	if (ir->open) {
>> -		retval = -EBUSY;
>> -		goto error;
>> -	}
>> +	dev_dbg(ir->d.dev, LOGHEAD "open called\n", ir->d.name, ir->d.minor);
>>  
>>  	if (ir->d.rdev) {
>>  		retval = rc_open(ir->d.rdev);
>> @@ -329,8 +299,7 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file)
>>  	if (ir->buf)
>>  		lirc_buffer_clear(ir->buf);
>>  
>> -	ir->open++;
>> -
>> +	file->private_data = ir;
>>  	nonseekable_open(inode, file);
>>  
>>  	return 0;
>> @@ -342,22 +311,14 @@ EXPORT_SYMBOL(lirc_dev_fop_open);
>>  
>>  int lirc_dev_fop_close(struct inode *inode, struct file *file)
>>  {
>> -	struct irctl *ir = irctls[iminor(inode)];
>> -	int ret;
>> -
>> -	if (!ir) {
>> -		pr_err("called with invalid irctl\n");
>> -		return -EINVAL;
>> -	}
>> +	struct irctl *ir = file->private_data;
>>  
>> -	ret = mutex_lock_killable(&lirc_dev_lock);
>> -	WARN_ON(ret);
>> +	mutex_lock(&ir->mutex);
>>  
>>  	rc_close(ir->d.rdev);
>> +	ir->users--;
>>  
>> -	ir->open--;
>> -	if (!ret)
>> -		mutex_unlock(&lirc_dev_lock);
>> +	mutex_unlock(&ir->mutex);
>>  
>>  	return 0;
>>  }
>> @@ -365,26 +326,21 @@ 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)
>> +	if (ir->dead)
>>  		return POLLHUP | POLLERR;
>>  
>> -	if (ir->buf) {
>> -		poll_wait(file, &ir->buf->wait_poll, wait);
>> +	if (!ir->buf)
>> +		return POLLERR;
>> +
>> +	poll_wait(file, &ir->buf->wait_poll, wait);
>>  
>> -		if (lirc_buffer_empty(ir->buf))
>> -			ret = 0;
>> -		else
>> -			ret = POLLIN | POLLRDNORM;
>> -	} else
>> -		ret = POLLERR;
>> +	if (lirc_buffer_empty(ir->buf))
>> +		ret = 0;
>> +	else
>> +		ret = POLLIN | POLLRDNORM;
>>  
>>  	dev_dbg(ir->d.dev, LOGHEAD "poll result = %d\n",
>>  		ir->d.name, ir->d.minor, ret);
>> @@ -395,25 +351,20 @@ 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);
>>  
>> -	if (ir->d.minor == NOPLUG || !ir->attached) {
>> +	if (ir->dead) {
>>  		dev_err(ir->d.dev, LOGHEAD "ioctl result = -ENODEV\n",
>>  			ir->d.name, ir->d.minor);
>>  		return -ENODEV;
>>  	}
>>  
>> -	mutex_lock(&ir->irctl_lock);
>> +	mutex_lock(&ir->mutex);
>>  
>>  	switch (cmd) {
>>  	case LIRC_GET_FEATURES:
>> @@ -468,7 +419,7 @@ long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
>>  		result = -ENOTTY;
>>  	}
>>  
>> -	mutex_unlock(&ir->irctl_lock);
>> +	mutex_unlock(&ir->mutex);
>>  
>>  	return result;
>>  }
>> @@ -479,16 +430,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;
>>  
>> @@ -498,11 +444,12 @@ ssize_t lirc_dev_fop_read(struct file *file,
>>  	if (!buf)
>>  		return -ENOMEM;
>>  
>> -	if (mutex_lock_interruptible(&ir->irctl_lock)) {
>> +	if (mutex_lock_interruptible(&ir->mutex)) {
>>  		ret = -ERESTARTSYS;
>>  		goto out_unlocked;
>>  	}
>> -	if (!ir->attached) {
>> +
>> +	if (ir->dead) {
>>  		ret = -ENODEV;
>>  		goto out_locked;
>>  	}
>> @@ -541,18 +488,18 @@ ssize_t lirc_dev_fop_read(struct file *file,
>>  				break;
>>  			}
>>  
>> -			mutex_unlock(&ir->irctl_lock);
>> +			mutex_unlock(&ir->mutex);
>>  			set_current_state(TASK_INTERRUPTIBLE);
>>  			schedule();
>>  			set_current_state(TASK_RUNNING);
>>  
>> -			if (mutex_lock_interruptible(&ir->irctl_lock)) {
>> +			if (mutex_lock_interruptible(&ir->mutex)) {
>>  				ret = -ERESTARTSYS;
>>  				remove_wait_queue(&ir->buf->wait_poll, &wait);
>>  				goto out_unlocked;
>>  			}
>>  
>> -			if (!ir->attached) {
>> +			if (ir->dead) {
>>  				ret = -ENODEV;
>>  				goto out_locked;
>>  			}
>> @@ -570,7 +517,7 @@ ssize_t lirc_dev_fop_read(struct file *file,
>>  	remove_wait_queue(&ir->buf->wait_poll, &wait);
>>  
>>  out_locked:
>> -	mutex_unlock(&ir->irctl_lock);
>> +	mutex_unlock(&ir->mutex);
>>  
>>  out_unlocked:
>>  	kfree(buf);
>> @@ -581,7 +528,8 @@ EXPORT_SYMBOL(lirc_dev_fop_read);
>>  
>>  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);
>>  
>> @@ -596,7 +544,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,
>>  				     IRCTL_DEV_NAME);
>>  	if (retval) {
>>  		class_destroy(lirc_class);
>> @@ -613,7 +561,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/drivers/staging/media/lirc/lirc_zilog.c b/drivers/staging/media/lirc/lirc_zilog.c
>> index 59e05aa1bc55..ffb70dee4547 100644
>> --- a/drivers/staging/media/lirc/lirc_zilog.c
>> +++ b/drivers/staging/media/lirc/lirc_zilog.c
>> @@ -183,11 +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
>>  	 */
>> -	if (ir->l.minor >= 0) {
>> -		lirc_unregister_driver(ir->l.minor);
>> -		ir->l.minor = -1;
>> -	}
>> -
>> +	lirc_unregister_driver(&ir->l);
>>  	if (kfifo_initialized(&ir->rbuf.fifo))
>>  		lirc_buffer_free(&ir->rbuf);
>>  	list_del(&ir->list);
>> @@ -1382,7 +1378,6 @@ static const struct file_operations lirc_fops = {
>>  
>>  static struct lirc_driver lirc_template = {
>>  	.name		= "lirc_zilog",
>> -	.minor		= -1,
>>  	.code_length	= 13,
>>  	.buffer_size	= BUFLEN / 2,
>>  	.chunk_size	= 2,
>> @@ -1597,14 +1592,13 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
>>  	}
>>  
>>  	/* register with lirc */
>> -	ir->l.minor = lirc_register_driver(&ir->l);
>> -	if (ir->l.minor < 0) {
>> +	ret = lirc_register_driver(&ir->l);
>> +	if (ret < 0) {
>>  		dev_err(tx->ir->l.dev,
>> -			"%s: lirc_register_driver() failed: %i\n",
>> -			__func__, ir->l.minor);
>> -		ret = -EBADRQC;
>> +			"%s: lirc_register_driver failed: %i\n", __func__, ret);
>>  		goto out_put_xx;
>>  	}
>> +
>>  	dev_info(ir->l.dev,
>>  		 "IR unit on %s (i2c-%d) registered as lirc%d and ready\n",
>>  		 adap->name, adap->nr, ir->l.minor);
>> diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h
>> index 1f327e25a9be..f7629ff116a9 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
>>  
>>  #define mod(n, div) ((n) % (div))
>> @@ -164,6 +163,8 @@ static inline unsigned int lirc_buffer_write(struct lirc_buffer *buf,
>>   *			device.
>>   *
>>   * @owner:		the module owning this struct
>> + *
>> + * @lirc_internal:	lirc_dev bookkeeping data, don't touch.
>
>It's not a great name or comment :)
>
>Otherwise, it's a good idea.
>
>
>Sean
>
>>   */
>>  struct lirc_driver {
>>  	char name[40];
>> @@ -182,19 +183,12 @@ struct lirc_driver {
>>  	const struct file_operations *fops;
>>  	struct device *dev;
>>  	struct module *owner;
>> +	void *lirc_internal;
>>  };
>>  
>> -/* following functions can be called ONLY from user context
>> - *
>> - * returns negative value on error or minor number
>> - * of the registered device if success
>> - * contents of the structure pointed by p is copied
>> - */
>>  extern int lirc_register_driver(struct lirc_driver *d);
>>  
>> -/* returns negative value on error or 0 if success
>> -*/
>> -extern int lirc_unregister_driver(int minor);
>> +extern void lirc_unregister_driver(struct lirc_driver *d);
>>  
>>  /* Returns the private data stored in the lirc_driver
>>   * associated with the given device file pointer.

-- 
David Härdeman

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 03/16] lirc_dev: correct error handling
  2017-05-28  8:23     ` David Härdeman
@ 2017-05-28 15:04       ` Sean Young
  2017-06-17 11:14         ` David Härdeman
  0 siblings, 1 reply; 28+ messages in thread
From: Sean Young @ 2017-05-28 15:04 UTC (permalink / raw)
  To: David Härdeman; +Cc: linux-media, mchehab

On Sun, May 28, 2017 at 10:23:37AM +0200, David Härdeman wrote:
> On Sun, May 21, 2017 at 09:57:13AM +0100, Sean Young wrote:
> >On Mon, May 01, 2017 at 06:03:51PM +0200, David Härdeman wrote:
> >> If an error is generated, nonseekable_open() shouldn't be called.
> >
> >There is no harm in calling nonseekable_open(), so this commit is
> >misleading.
> 
> I'm not sure why you consider it misleading? If there's an error, the
> logic thing to do is to error out immediately and not do any further
> work?

The commit message says that nonseekable_open() should not be called,
suggesting there is a bug which is not the case.


Sean

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 13/16] lirc_dev: use an ida instead of a hand-rolled array to keep track of minors
  2017-05-28  8:26     ` David Härdeman
@ 2017-05-28 15:08       ` Sean Young
  0 siblings, 0 replies; 28+ messages in thread
From: Sean Young @ 2017-05-28 15:08 UTC (permalink / raw)
  To: David Härdeman; +Cc: linux-media, mchehab

On Sun, May 28, 2017 at 10:26:59AM +0200, David Härdeman wrote:
> On Mon, May 22, 2017 at 09:09:42PM +0100, Sean Young wrote:
> >On Mon, May 01, 2017 at 06:04:42PM +0200, David Härdeman wrote:
> >> Using the kernel ida facilities, we can avoid a lot of unnecessary code and at the same
> >> time get rid of lirc_dev_lock in favour of per-device locks (the irctls array was used
> >> throughout lirc_dev so this patch necessarily touches a lot of code).
> >> 
> >> Signed-off-by: David Härdeman <david@hardeman.nu>
> >> ---
> >>  drivers/media/rc/ir-lirc-codec.c        |    9 -
> >>  drivers/media/rc/lirc_dev.c             |  258 ++++++++++++-------------------
> >>  drivers/staging/media/lirc/lirc_zilog.c |   16 +-
> >>  include/media/lirc_dev.h                |   14 --
> >>  4 files changed, 115 insertions(+), 182 deletions(-)
> >> 
> >> diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c
> >> index a30af91710fe..2c1221a61ea1 100644
> >> --- a/drivers/media/rc/ir-lirc-codec.c
> >> +++ b/drivers/media/rc/ir-lirc-codec.c
> >> @@ -382,7 +382,6 @@ static int ir_lirc_register(struct rc_dev *dev)
> >>  
> >>  	snprintf(drv->name, sizeof(drv->name), "ir-lirc-codec (%s)",
> >>  		 dev->driver_name);
> >> -	drv->minor = -1;
> >>  	drv->features = features;
> >>  	drv->data = &dev->raw->lirc;
> >>  	drv->rbuf = NULL;
> >> @@ -394,11 +393,9 @@ static int ir_lirc_register(struct rc_dev *dev)
> >>  	drv->rdev = dev;
> >>  	drv->owner = THIS_MODULE;
> >>  
> >> -	drv->minor = lirc_register_driver(drv);
> >> -	if (drv->minor < 0) {
> >> -		rc = -ENODEV;
> >> +	rc = lirc_register_driver(drv);
> >> +	if (rc < 0)
> >>  		goto out;
> >> -	}
> >>  
> >>  	dev->raw->lirc.drv = drv;
> >>  	dev->raw->lirc.dev = dev;
> >> @@ -413,7 +410,7 @@ static int ir_lirc_unregister(struct rc_dev *dev)
> >>  {
> >>  	struct lirc_codec *lirc = &dev->raw->lirc;
> >>  
> >> -	lirc_unregister_driver(lirc->drv->minor);
> >> +	lirc_unregister_driver(lirc->drv);
> >>  	kfree(lirc->drv);
> >>  	lirc->drv = NULL;
> >>  
> >> diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
> >> index e44e0b23b883..7db7d4c57991 100644
> >> --- a/drivers/media/rc/lirc_dev.c
> >> +++ b/drivers/media/rc/lirc_dev.c
> >> @@ -31,23 +31,35 @@
> >>  #include <linux/bitops.h>
> >>  #include <linux/device.h>
> >>  #include <linux/cdev.h>
> >> +#include <linux/idr.h>
> >>  
> >>  #include <media/rc-core.h>
> >>  #include <media/lirc.h>
> >>  #include <media/lirc_dev.h>
> >>  
> >>  #define IRCTL_DEV_NAME	"BaseRemoteCtl"
> >> -#define NOPLUG		-1
> >>  #define LOGHEAD		"lirc_dev (%s[%d]): "
> >>  
> >>  static dev_t lirc_base_dev;
> >>  
> >> +/**
> >> + * struct irctl - lirc per-device structure
> >> + * @d:			internal copy of the &struct lirc_driver for the device
> >> + * @dead:		if the device has gone away
> >> + * @users:		the number of users of the lirc chardev (currently limited to 1)
> >> + * @mutex:		synchronizes open()/close()/ioctl()/etc calls
> >> + * @buf:		used to store lirc RX data
> >> + * @buf_internal:	whether @buf was allocated internally or not
> >> + * @chunk_size:		@buf stores and read() returns data chunks of this size
> >> + * @dev:		the &struct device for the lirc device
> >> + * @cdev:		the &struct device for the lirc chardev
> >> + */
> >>  struct irctl {
> >>  	struct lirc_driver d;
> >> -	int attached;
> >> -	int open;
> >> +	bool dead;
> >> +	unsigned users;
> >>  
> >> -	struct mutex irctl_lock;
> >> +	struct mutex mutex;
> >>  	struct lirc_buffer *buf;
> >>  	bool buf_internal;
> >>  	unsigned int chunk_size;
> >> @@ -56,9 +68,9 @@ struct irctl {
> >>  	struct cdev cdev;
> >>  };
> >>  
> >> -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;
> >> @@ -72,9 +84,6 @@ static void lirc_release(struct device *ld)
> >>  		kfree(ir->buf);
> >>  	}
> >>  
> >> -	mutex_lock(&lirc_dev_lock);
> >> -	irctls[ir->d.minor] = NULL;
> >> -	mutex_unlock(&lirc_dev_lock);
> >>  	kfree(ir);
> >>  }
> >>  
> >> @@ -117,7 +126,18 @@ static int lirc_allocate_buffer(struct irctl *ir)
> >>  	return err;
> >>  }
> >>  
> >> -int lirc_register_driver(struct lirc_driver *d)
> >> +/**
> >> + * lirc_register_driver() - create a new lirc device by registering a driver
> >> + * @d: the &struct lirc_driver to register
> >> + *
> >> + * This function allocates and registers a lirc device for a given
> >> + * &lirc_driver. The &lirc_driver structure is updated to contain
> >> + * information about the allocated device (minor, buffer, etc).
> >> + *
> >> + * Return: zero on success or a negative error value.
> >> + */
> >> +int
> >> +lirc_register_driver(struct lirc_driver *d)
> >>  {
> >>  	struct irctl *ir;
> >>  	int minor;
> >> @@ -138,12 +158,6 @@ int lirc_register_driver(struct lirc_driver *d)
> >>  		return -EINVAL;
> >>  	}
> >>  
> >> -	if (d->minor >= MAX_IRCTL_DEVICES) {
> >> -		dev_err(d->dev, "minor must be between 0 and %d!\n",
> >> -						MAX_IRCTL_DEVICES - 1);
> >> -		return -EBADRQC;
> >> -	}
> >> -
> >>  	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);
> >> @@ -156,49 +170,30 @@ int lirc_register_driver(struct lirc_driver *d)
> >>  		return -EBADRQC;
> >>  	}
> >>  
> >> -	mutex_lock(&lirc_dev_lock);
> >> -
> >> -	minor = d->minor;
> >> +	d->name[sizeof(d->name)-1] = '\0';
> >> +	if (d->features == 0)
> >> +		d->features = LIRC_CAN_REC_LIRCCODE;
> >>  
> >> -	if (minor < 0) {
> >> -		/* 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");
> >> -			err = -ENOMEM;
> >> -			goto out_lock;
> >> -		}
> >> -	} else if (irctls[minor]) {
> >> -		dev_err(d->dev, "minor (%d) just registered!\n", minor);
> >> -		err = -EBUSY;
> >> -		goto out_lock;
> >> -	}
> >> +	minor = ida_simple_get(&lirc_ida, 0, LIRC_MAX_DEVICES, GFP_KERNEL);
> >> +	if (minor < 0)
> >> +		return minor;
> >> +	d->minor = minor;
> >>  
> >>  	ir = kzalloc(sizeof(struct irctl), GFP_KERNEL);
> >>  	if (!ir) {
> >>  		err = -ENOMEM;
> >> -		goto out_lock;
> >> +		goto out_minor;
> >>  	}
> >>  
> >> -	mutex_init(&ir->irctl_lock);
> >> -	irctls[minor] = ir;
> >> -	d->minor = minor;
> >> -
> >> -	/* some safety check 8-) */
> >> -	d->name[sizeof(d->name)-1] = '\0';
> >> -
> >> -	if (d->features == 0)
> >> -		d->features = LIRC_CAN_REC_LIRCCODE;
> >> +	mutex_init(&ir->mutex);
> >>  
> >>  	ir->d = *d;
> >
> >Here we copy lirc_driver.
> >
> >>  
> >>  	if (LIRC_CAN_REC(d->features)) {
> >> -		err = lirc_allocate_buffer(irctls[minor]);
> >> +		err = lirc_allocate_buffer(ir);
> >>  		if (err) {
> >>  			kfree(ir);
> >> -			goto out_lock;
> >> +			goto out_minor;
> >>  		}
> >>  		d->rbuf = ir->buf;
> >>  	}
> >> @@ -218,107 +213,82 @@ int lirc_register_driver(struct lirc_driver *d)
> >>  	if (err)
> >>  		goto out_free_dev;
> >>  
> >> -	ir->attached = 1;
> >> -
> >>  	err = device_add(&ir->dev);
> >>  	if (err)
> >>  		goto out_cdev;
> >>  
> >> -	mutex_unlock(&lirc_dev_lock);
> >> -
> >>  	dev_info(ir->d.dev, "lirc_dev: driver %s registered at minor = %d\n",
> >>  		 ir->d.name, ir->d.minor);
> >>  
> >> -	return minor;
> >> +	d->lirc_internal = ir;
> >
> >And now a store a pointer to the copy in the original lirc_driver. 
> >
> >It would be much better to not copy lirc_driver and the lirc_internal
> >member would be unnecessary.
> 
> I know, but this is a more minimal fix. The struct copy is already in
> the current code and I'd prefer removing it in a separate patch once the
> use of lirc_driver has been vetted.

Your patch adds the lirc_internal pointer to work around this, which makes
the code even worse than it is.


Sean

> 
> >> +	return 0;
> >>  
> >>  out_cdev:
> >>  	cdev_del(&ir->cdev);
> >>  out_free_dev:
> >>  	put_device(&ir->dev);
> >> -out_lock:
> >> -	mutex_unlock(&lirc_dev_lock);
> >> +out_minor:
> >> +	ida_simple_remove(&lirc_ida, minor);
> >>  
> >>  	return err;
> >>  }
> >>  EXPORT_SYMBOL(lirc_register_driver);
> >>  
> >> -int lirc_unregister_driver(int minor)
> >> +/**
> >> + * lirc_unregister_driver() - remove the lirc device for a given driver
> >> + * @d: the &struct lirc_driver to unregister
> >> + *
> >> + * This function unregisters the lirc device for a given &lirc_driver.
> >> + */
> >> +void
> >> +lirc_unregister_driver(struct lirc_driver *d)
> >>  {
> >>  	struct irctl *ir;
> >>  
> >> -	if (minor < 0 || minor >= MAX_IRCTL_DEVICES) {
> >> -		pr_err("minor (%d) must be between 0 and %d!\n",
> >> -					minor, MAX_IRCTL_DEVICES - 1);
> >> -		return -EBADRQC;
> >> -	}
> >> +	if (!d->lirc_internal)
> >> +		return;
> >>  
> >> -	ir = irctls[minor];
> >> -	if (!ir) {
> >> -		pr_err("failed to get irctl\n");
> >> -		return -ENOENT;
> >> -	}
> >> +	ir = d->lirc_internal;
> >
> >This is done to find a our copy again.
> >
> >> -	mutex_lock(&lirc_dev_lock);
> >> -
> >> -	if (ir->d.minor != minor) {
> >> -		dev_err(ir->d.dev, "lirc_dev: minor %d device not registered\n",
> >> -									minor);
> >> -		mutex_unlock(&lirc_dev_lock);
> >> -		return -ENOENT;
> >> -	}
> >> +	mutex_lock(&ir->mutex);
> >>  
> >>  	dev_dbg(ir->d.dev, "lirc_dev: driver %s unregistered from minor = %d\n",
> >>  		ir->d.name, ir->d.minor);
> >>  
> >> -	ir->attached = 0;
> >> -	if (ir->open) {
> >> +	ir->dead = true;
> >> +	if (ir->users) {
> >>  		dev_dbg(ir->d.dev, LOGHEAD "releasing opened driver\n",
> >>  			ir->d.name, ir->d.minor);
> >>  		wake_up_interruptible(&ir->buf->wait_poll);
> >>  	}
> >>  
> >> -	mutex_unlock(&lirc_dev_lock);
> >> +	mutex_unlock(&ir->mutex);
> >>  
> >>  	device_del(&ir->dev);
> >>  	cdev_del(&ir->cdev);
> >> -	put_device(&ir->dev);
> >> -
> >> -	return 0;
> >> +	ida_simple_remove(&lirc_ida, d->minor);
> >> +	d->minor = -1;
> >> +	d->lirc_internal = NULL;
> >>  }
> >>  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;
> >> +	mutex_lock(&ir->mutex);
> >>  
> >> -	ir = irctls[iminor(inode)];
> >> -	mutex_unlock(&lirc_dev_lock);
> >> -
> >> -	if (!ir) {
> >> -		retval = -ENODEV;
> >> +	if (ir->users) {
> >> +		retval = -EBUSY;
> >> +		mutex_unlock(&ir->mutex);
> >>  		goto error;
> >>  	}
> >> +	ir->users++;
> >>  
> >> -	dev_dbg(ir->d.dev, LOGHEAD "open called\n", ir->d.name, ir->d.minor);
> >> -
> >> -	if (ir->d.minor == NOPLUG) {
> >> -		retval = -ENODEV;
> >> -		goto error;
> >> -	}
> >> +	mutex_unlock(&ir->mutex);
> >>  
> >> -	if (ir->open) {
> >> -		retval = -EBUSY;
> >> -		goto error;
> >> -	}
> >> +	dev_dbg(ir->d.dev, LOGHEAD "open called\n", ir->d.name, ir->d.minor);
> >>  
> >>  	if (ir->d.rdev) {
> >>  		retval = rc_open(ir->d.rdev);
> >> @@ -329,8 +299,7 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file)
> >>  	if (ir->buf)
> >>  		lirc_buffer_clear(ir->buf);
> >>  
> >> -	ir->open++;
> >> -
> >> +	file->private_data = ir;
> >>  	nonseekable_open(inode, file);
> >>  
> >>  	return 0;
> >> @@ -342,22 +311,14 @@ EXPORT_SYMBOL(lirc_dev_fop_open);
> >>  
> >>  int lirc_dev_fop_close(struct inode *inode, struct file *file)
> >>  {
> >> -	struct irctl *ir = irctls[iminor(inode)];
> >> -	int ret;
> >> -
> >> -	if (!ir) {
> >> -		pr_err("called with invalid irctl\n");
> >> -		return -EINVAL;
> >> -	}
> >> +	struct irctl *ir = file->private_data;
> >>  
> >> -	ret = mutex_lock_killable(&lirc_dev_lock);
> >> -	WARN_ON(ret);
> >> +	mutex_lock(&ir->mutex);
> >>  
> >>  	rc_close(ir->d.rdev);
> >> +	ir->users--;
> >>  
> >> -	ir->open--;
> >> -	if (!ret)
> >> -		mutex_unlock(&lirc_dev_lock);
> >> +	mutex_unlock(&ir->mutex);
> >>  
> >>  	return 0;
> >>  }
> >> @@ -365,26 +326,21 @@ 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)
> >> +	if (ir->dead)
> >>  		return POLLHUP | POLLERR;
> >>  
> >> -	if (ir->buf) {
> >> -		poll_wait(file, &ir->buf->wait_poll, wait);
> >> +	if (!ir->buf)
> >> +		return POLLERR;
> >> +
> >> +	poll_wait(file, &ir->buf->wait_poll, wait);
> >>  
> >> -		if (lirc_buffer_empty(ir->buf))
> >> -			ret = 0;
> >> -		else
> >> -			ret = POLLIN | POLLRDNORM;
> >> -	} else
> >> -		ret = POLLERR;
> >> +	if (lirc_buffer_empty(ir->buf))
> >> +		ret = 0;
> >> +	else
> >> +		ret = POLLIN | POLLRDNORM;
> >>  
> >>  	dev_dbg(ir->d.dev, LOGHEAD "poll result = %d\n",
> >>  		ir->d.name, ir->d.minor, ret);
> >> @@ -395,25 +351,20 @@ 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);
> >>  
> >> -	if (ir->d.minor == NOPLUG || !ir->attached) {
> >> +	if (ir->dead) {
> >>  		dev_err(ir->d.dev, LOGHEAD "ioctl result = -ENODEV\n",
> >>  			ir->d.name, ir->d.minor);
> >>  		return -ENODEV;
> >>  	}
> >>  
> >> -	mutex_lock(&ir->irctl_lock);
> >> +	mutex_lock(&ir->mutex);
> >>  
> >>  	switch (cmd) {
> >>  	case LIRC_GET_FEATURES:
> >> @@ -468,7 +419,7 @@ long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
> >>  		result = -ENOTTY;
> >>  	}
> >>  
> >> -	mutex_unlock(&ir->irctl_lock);
> >> +	mutex_unlock(&ir->mutex);
> >>  
> >>  	return result;
> >>  }
> >> @@ -479,16 +430,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;
> >>  
> >> @@ -498,11 +444,12 @@ ssize_t lirc_dev_fop_read(struct file *file,
> >>  	if (!buf)
> >>  		return -ENOMEM;
> >>  
> >> -	if (mutex_lock_interruptible(&ir->irctl_lock)) {
> >> +	if (mutex_lock_interruptible(&ir->mutex)) {
> >>  		ret = -ERESTARTSYS;
> >>  		goto out_unlocked;
> >>  	}
> >> -	if (!ir->attached) {
> >> +
> >> +	if (ir->dead) {
> >>  		ret = -ENODEV;
> >>  		goto out_locked;
> >>  	}
> >> @@ -541,18 +488,18 @@ ssize_t lirc_dev_fop_read(struct file *file,
> >>  				break;
> >>  			}
> >>  
> >> -			mutex_unlock(&ir->irctl_lock);
> >> +			mutex_unlock(&ir->mutex);
> >>  			set_current_state(TASK_INTERRUPTIBLE);
> >>  			schedule();
> >>  			set_current_state(TASK_RUNNING);
> >>  
> >> -			if (mutex_lock_interruptible(&ir->irctl_lock)) {
> >> +			if (mutex_lock_interruptible(&ir->mutex)) {
> >>  				ret = -ERESTARTSYS;
> >>  				remove_wait_queue(&ir->buf->wait_poll, &wait);
> >>  				goto out_unlocked;
> >>  			}
> >>  
> >> -			if (!ir->attached) {
> >> +			if (ir->dead) {
> >>  				ret = -ENODEV;
> >>  				goto out_locked;
> >>  			}
> >> @@ -570,7 +517,7 @@ ssize_t lirc_dev_fop_read(struct file *file,
> >>  	remove_wait_queue(&ir->buf->wait_poll, &wait);
> >>  
> >>  out_locked:
> >> -	mutex_unlock(&ir->irctl_lock);
> >> +	mutex_unlock(&ir->mutex);
> >>  
> >>  out_unlocked:
> >>  	kfree(buf);
> >> @@ -581,7 +528,8 @@ EXPORT_SYMBOL(lirc_dev_fop_read);
> >>  
> >>  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);
> >>  
> >> @@ -596,7 +544,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,
> >>  				     IRCTL_DEV_NAME);
> >>  	if (retval) {
> >>  		class_destroy(lirc_class);
> >> @@ -613,7 +561,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/drivers/staging/media/lirc/lirc_zilog.c b/drivers/staging/media/lirc/lirc_zilog.c
> >> index 59e05aa1bc55..ffb70dee4547 100644
> >> --- a/drivers/staging/media/lirc/lirc_zilog.c
> >> +++ b/drivers/staging/media/lirc/lirc_zilog.c
> >> @@ -183,11 +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
> >>  	 */
> >> -	if (ir->l.minor >= 0) {
> >> -		lirc_unregister_driver(ir->l.minor);
> >> -		ir->l.minor = -1;
> >> -	}
> >> -
> >> +	lirc_unregister_driver(&ir->l);
> >>  	if (kfifo_initialized(&ir->rbuf.fifo))
> >>  		lirc_buffer_free(&ir->rbuf);
> >>  	list_del(&ir->list);
> >> @@ -1382,7 +1378,6 @@ static const struct file_operations lirc_fops = {
> >>  
> >>  static struct lirc_driver lirc_template = {
> >>  	.name		= "lirc_zilog",
> >> -	.minor		= -1,
> >>  	.code_length	= 13,
> >>  	.buffer_size	= BUFLEN / 2,
> >>  	.chunk_size	= 2,
> >> @@ -1597,14 +1592,13 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
> >>  	}
> >>  
> >>  	/* register with lirc */
> >> -	ir->l.minor = lirc_register_driver(&ir->l);
> >> -	if (ir->l.minor < 0) {
> >> +	ret = lirc_register_driver(&ir->l);
> >> +	if (ret < 0) {
> >>  		dev_err(tx->ir->l.dev,
> >> -			"%s: lirc_register_driver() failed: %i\n",
> >> -			__func__, ir->l.minor);
> >> -		ret = -EBADRQC;
> >> +			"%s: lirc_register_driver failed: %i\n", __func__, ret);
> >>  		goto out_put_xx;
> >>  	}
> >> +
> >>  	dev_info(ir->l.dev,
> >>  		 "IR unit on %s (i2c-%d) registered as lirc%d and ready\n",
> >>  		 adap->name, adap->nr, ir->l.minor);
> >> diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h
> >> index 1f327e25a9be..f7629ff116a9 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
> >>  
> >>  #define mod(n, div) ((n) % (div))
> >> @@ -164,6 +163,8 @@ static inline unsigned int lirc_buffer_write(struct lirc_buffer *buf,
> >>   *			device.
> >>   *
> >>   * @owner:		the module owning this struct
> >> + *
> >> + * @lirc_internal:	lirc_dev bookkeeping data, don't touch.
> >
> >It's not a great name or comment :)
> >
> >Otherwise, it's a good idea.
> >
> >
> >Sean
> >
> >>   */
> >>  struct lirc_driver {
> >>  	char name[40];
> >> @@ -182,19 +183,12 @@ struct lirc_driver {
> >>  	const struct file_operations *fops;
> >>  	struct device *dev;
> >>  	struct module *owner;
> >> +	void *lirc_internal;
> >>  };
> >>  
> >> -/* following functions can be called ONLY from user context
> >> - *
> >> - * returns negative value on error or minor number
> >> - * of the registered device if success
> >> - * contents of the structure pointed by p is copied
> >> - */
> >>  extern int lirc_register_driver(struct lirc_driver *d);
> >>  
> >> -/* returns negative value on error or 0 if success
> >> -*/
> >> -extern int lirc_unregister_driver(int minor);
> >> +extern void lirc_unregister_driver(struct lirc_driver *d);
> >>  
> >>  /* Returns the private data stored in the lirc_driver
> >>   * associated with the given device file pointer.
> 
> -- 
> David Härdeman

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 03/16] lirc_dev: correct error handling
  2017-05-28 15:04       ` Sean Young
@ 2017-06-17 11:14         ` David Härdeman
  0 siblings, 0 replies; 28+ messages in thread
From: David Härdeman @ 2017-06-17 11:14 UTC (permalink / raw)
  To: Sean Young; +Cc: linux-media, mchehab

On Sun, May 28, 2017 at 04:04:30PM +0100, Sean Young wrote:
>On Sun, May 28, 2017 at 10:23:37AM +0200, David Härdeman wrote:
>> On Sun, May 21, 2017 at 09:57:13AM +0100, Sean Young wrote:
>> >On Mon, May 01, 2017 at 06:03:51PM +0200, David Härdeman wrote:
>> >> If an error is generated, nonseekable_open() shouldn't be called.
>> >
>> >There is no harm in calling nonseekable_open(), so this commit is
>> >misleading.
>> 
>> I'm not sure why you consider it misleading? If there's an error, the
>> logic thing to do is to error out immediately and not do any further
>> work?
>
>The commit message says that nonseekable_open() should not be called,
>suggesting there is a bug which is not the case.

I'll do another version with an updated commit message then :)

-- 
David Härdeman

^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2017-06-17 11:14 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-05-01 16:03 [PATCH 00/16] lirc_dev spring cleaning David Härdeman
2017-05-01 16:03 ` [PATCH 01/16] lirc_dev: remove pointless functions David Härdeman
2017-05-01 16:03 ` [PATCH 02/16] lirc_dev: remove unused set_use_inc/set_use_dec David Härdeman
2017-05-01 16:03 ` [PATCH 03/16] lirc_dev: correct error handling David Härdeman
2017-05-21  8:57   ` Sean Young
2017-05-28  8:23     ` David Härdeman
2017-05-28 15:04       ` Sean Young
2017-06-17 11:14         ` David Härdeman
2017-05-01 16:03 ` [PATCH 04/16] lirc_dev: remove sampling kthread David Härdeman
2017-05-01 16:04 ` [PATCH 05/16] lirc_dev: clarify error handling David Härdeman
2017-05-01 16:04 ` [PATCH 06/16] lirc_dev: make fops mandatory David Härdeman
2017-05-01 16:04 ` [PATCH 07/16] lirc_dev: merge lirc_register_driver() and lirc_allocate_driver() David Härdeman
2017-05-01 16:04 ` [PATCH 08/16] lirc_zilog: remove module parameter minor David Härdeman
2017-05-01 16:04 ` [PATCH 09/16] lirc_dev: remove lirc_irctl_init() and lirc_cdev_add() David Härdeman
2017-05-01 16:04 ` [PATCH 10/16] lirc_dev: remove superfluous get/put_device() calls David Härdeman
2017-05-01 16:04 ` [PATCH 11/16] lirc_dev: remove unused module parameter David Härdeman
2017-05-01 16:04 ` [PATCH 12/16] lirc_dev: return POLLHUP and POLLERR when device is gone David Härdeman
2017-05-01 16:04 ` [PATCH 13/16] lirc_dev: use an ida instead of a hand-rolled array to keep track of minors David Härdeman
2017-05-22 20:09   ` Sean Young
2017-05-28  8:26     ` David Härdeman
2017-05-28 15:08       ` Sean Young
2017-05-01 16:04 ` [PATCH 14/16] lirc_dev: cleanup includes David Härdeman
2017-05-19 18:21   ` Sean Young
2017-05-21  6:51     ` David Härdeman
2017-05-01 16:04 ` [PATCH 15/16] lirc_dev: remove name from struct lirc_driver David Härdeman
2017-05-02 17:04   ` Sean Young
2017-05-02 18:41     ` David Härdeman
2017-05-01 16:04 ` [PATCH 16/16] lirc_dev: cleanup header David Härdeman

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).