All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mauro Carvalho Chehab <m.chehab@samsung.com>
To: "David Härdeman" <david@hardeman.nu>
Cc: linux-media@vger.kernel.org
Subject: Re: [PATCH 40/49] rc-ir-raw: simplify locking
Date: Fri, 25 Jul 2014 20:08:52 -0300	[thread overview]
Message-ID: <20140725200852.1aa56c69.m.chehab@samsung.com> (raw)
In-Reply-To: <20140403233438.27099.1183.stgit@zeus.muc.hardeman.nu>

Em Fri, 04 Apr 2014 01:34:38 +0200
David Härdeman <david@hardeman.nu> escreveu:

> Simplify and improve the locking in rc-ir-raw by making better use of
> the existing kfifo functionality and by using RCU where possible.

Please rebase.

> 
> Signed-off-by: David Härdeman <david@hardeman.nu>
> ---
>  drivers/media/rc/rc-core-priv.h |    6 +-
>  drivers/media/rc/rc-ir-raw.c    |  124 ++++++++++++++++-----------------------
>  2 files changed, 55 insertions(+), 75 deletions(-)
> 
> diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h
> index 0b32ef8..c3de26b 100644
> --- a/drivers/media/rc/rc-core-priv.h
> +++ b/drivers/media/rc/rc-core-priv.h
> @@ -37,11 +37,13 @@ struct ir_raw_handler {
>  	int (*raw_unregister)(struct rc_dev *dev);
>  };
>  
> +/* max number of pulse/space transitions to buffer */
> +#define RC_MAX_IR_EVENTS	512
> +
>  struct ir_raw_event_ctrl {
>  	struct list_head		list;		/* to keep track of raw clients */
>  	struct task_struct		*thread;
> -	spinlock_t			lock;
> -	struct kfifo_rec_ptr_1		kfifo;		/* fifo for the pulse/space durations */
> +	DECLARE_KFIFO(kfifo, struct ir_raw_event, RC_MAX_IR_EVENTS); /* for pulse/space durations */
>  	ktime_t				last_event;	/* when last event occurred */
>  	enum raw_event_type		last_type;	/* last event type */
>  	struct rc_dev			*dev;		/* pointer to the parent rc_dev */
> diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c
> index 86f5aa7..9631825 100644
> --- a/drivers/media/rc/rc-ir-raw.c
> +++ b/drivers/media/rc/rc-ir-raw.c
> @@ -21,15 +21,12 @@
>  #include <linux/freezer.h>
>  #include "rc-core-priv.h"
>  
> -/* Define the max number of pulse/space transitions to buffer */
> -#define MAX_IR_EVENT_SIZE      512
> -
> -/* Used to keep track of IR raw clients, protected by ir_raw_handler_lock */
> +/* IR raw clients/handlers, writers synchronize with ir_raw_mutex */
> +static DEFINE_MUTEX(ir_raw_mutex);
>  static LIST_HEAD(ir_raw_client_list);
> -
> -/* Used to handle IR raw handler extensions */
> -static DEFINE_MUTEX(ir_raw_handler_lock);
>  static LIST_HEAD(ir_raw_handler_list);
> +
> +/* protocols supported by the currently loaded decoders */
>  static u64 available_protocols;
>  
>  static int ir_raw_event_thread(void *data)
> @@ -37,32 +34,19 @@ static int ir_raw_event_thread(void *data)
>  	struct ir_raw_event ev;
>  	struct ir_raw_handler *handler;
>  	struct ir_raw_event_ctrl *raw = (struct ir_raw_event_ctrl *)data;
> -	int retval;
>  
>  	while (!kthread_should_stop()) {
> -
> -		spin_lock_irq(&raw->lock);
> -		retval = kfifo_len(&raw->kfifo);
> -
> -		if (retval < sizeof(ev)) {
> +		if (kfifo_out(&raw->kfifo, &ev, 1) == 0) {
>  			set_current_state(TASK_INTERRUPTIBLE);
> -
> -			if (kthread_should_stop())
> -				set_current_state(TASK_RUNNING);
> -
> -			spin_unlock_irq(&raw->lock);
>  			schedule();
>  			continue;
>  		}
>  
> -		retval = kfifo_out(&raw->kfifo, &ev, sizeof(ev));
> -		spin_unlock_irq(&raw->lock);
> -
> -		mutex_lock(&ir_raw_handler_lock);
> -		list_for_each_entry(handler, &ir_raw_handler_list, list)
> +		rcu_read_lock();
> +		list_for_each_entry_rcu(handler, &ir_raw_handler_list, list)
>  			handler->decode(raw->dev, ev);
> +		rcu_read_unlock();
>  		raw->prev_ev = ev;
> -		mutex_unlock(&ir_raw_handler_lock);
>  	}
>  
>  	return 0;
> @@ -76,7 +60,8 @@ static int ir_raw_event_thread(void *data)
>   * This routine (which may be called from an interrupt context) stores a
>   * pulse/space duration for the raw ir decoding state machines. Pulses are
>   * signalled as positive values and spaces as negative values. A zero value
> - * will reset the decoding state machines.
> + * will reset the decoding state machines. Drivers are responsible for
> + * synchronizing calls to this function.
>   */
>  int ir_raw_event_store(struct rc_dev *dev, struct ir_raw_event *ev)
>  {
> @@ -86,7 +71,7 @@ int ir_raw_event_store(struct rc_dev *dev, struct ir_raw_event *ev)
>  	IR_dprintk(2, "sample: (%05dus %s)\n",
>  		   TO_US(ev->duration), TO_STR(ev->pulse));
>  
> -	if (kfifo_in(&dev->raw->kfifo, ev, sizeof(*ev)) != sizeof(*ev))
> +	if (kfifo_in(&dev->raw->kfifo, ev, 1) != 1)
>  		return -ENOMEM;
>  
>  	return 0;
> @@ -258,14 +243,8 @@ EXPORT_SYMBOL_GPL(ir_raw_get_tx_event);
>   */
>  void ir_raw_event_handle(struct rc_dev *dev)
>  {
> -	unsigned long flags;
> -
> -	if (!dev->raw)
> -		return;
> -
> -	spin_lock_irqsave(&dev->raw->lock, flags);
> -	wake_up_process(dev->raw->thread);
> -	spin_unlock_irqrestore(&dev->raw->lock, flags);
> +	if (dev->raw)
> +		wake_up_process(dev->raw->thread);
>  }
>  EXPORT_SYMBOL_GPL(ir_raw_event_handle);
>  
> @@ -273,9 +252,9 @@ EXPORT_SYMBOL_GPL(ir_raw_event_handle);
>  static u64 ir_raw_get_allowed_protocols(struct rc_dev *dev)
>  {
>  	u64 protocols;
> -	mutex_lock(&ir_raw_handler_lock);
> +	mutex_lock(&ir_raw_mutex);
>  	protocols = available_protocols;
> -	mutex_unlock(&ir_raw_handler_lock);
> +	mutex_unlock(&ir_raw_mutex);
>  	return protocols;
>  }
>  
> @@ -290,52 +269,49 @@ static int change_protocol(struct rc_dev *dev, u64 *rc_type) {
>  int rc_register_ir_raw_device(struct rc_dev *dev)
>  {
>  	int rc;
> +	struct ir_raw_event_ctrl *raw;
>  	struct ir_raw_handler *handler;
>  
>  	if (!dev)
>  		return -EINVAL;
>  
> -	dev->raw = kzalloc(sizeof(*dev->raw), GFP_KERNEL);
> -	if (!dev->raw)
> +	raw = kzalloc(sizeof(*raw), GFP_KERNEL);
> +	if (!raw)
>  		return -ENOMEM;
>  
> -	dev->raw->dev = dev;
> -	dev->enabled_protocols = ~0;
> -	dev->get_protocols = ir_raw_get_allowed_protocols;
> -	dev->driver_type = RC_DRIVER_IR_RAW;
> -	dev->change_protocol = change_protocol;
> -	spin_lock_init(&dev->raw->lock);
> -	rc = kfifo_alloc(&dev->raw->kfifo,
> -			 sizeof(struct ir_raw_event) * MAX_IR_EVENT_SIZE,
> -			 GFP_KERNEL);
> -	if (rc < 0)
> -		goto out;
> -
> -	dev->raw->thread = kthread_run(ir_raw_event_thread, dev->raw,
> -				       dev_name(&dev->dev));
> +	raw->dev = dev;
> +	INIT_KFIFO(raw->kfifo);
> +	raw->thread = kthread_run(ir_raw_event_thread, dev->raw,
> +				  dev_name(&dev->dev));
>  
> -	if (IS_ERR(dev->raw->thread)) {
> -		rc = PTR_ERR(dev->raw->thread);
> +	if (IS_ERR(raw->thread)) {
> +		rc = PTR_ERR(raw->thread);
>  		goto out;
>  	}
>  
> +	dev->raw = raw;
> +	dev->enabled_protocols = ~0;
> +	dev->get_protocols = ir_raw_get_allowed_protocols;
> +	dev->driver_type = RC_DRIVER_IR_RAW;
> +	dev->change_protocol = change_protocol;
>  	rc = rc_register_device(dev);
>  	if (rc < 0)
>  		goto out_thread;
>  
> -	mutex_lock(&ir_raw_handler_lock);
> -	list_add_tail(&dev->raw->list, &ir_raw_client_list);
> -	list_for_each_entry(handler, &ir_raw_handler_list, list)
> +	mutex_lock(&ir_raw_mutex);
> +	list_add_tail_rcu(&dev->raw->list, &ir_raw_client_list);
> +	list_for_each_entry_rcu(handler, &ir_raw_handler_list, list)
>  		if (handler->raw_register)
>  			handler->raw_register(dev);
> -	mutex_unlock(&ir_raw_handler_lock);
> +	mutex_unlock(&ir_raw_mutex);
> +	synchronize_rcu();
>  
>  	return 0;
>  
>  out_thread:
> -	kthread_stop(dev->raw->thread);
> +	kthread_stop(raw->thread);
>  out:
> -	kfree(dev->raw);
> +	kfree(raw);
>  	dev->raw = NULL;
>  	return rc;
>  }
> @@ -350,14 +326,14 @@ void rc_unregister_ir_raw_device(struct rc_dev *dev)
>  
>  	kthread_stop(dev->raw->thread);
>  
> -	mutex_lock(&ir_raw_handler_lock);
> -	list_del(&dev->raw->list);
> -	list_for_each_entry(handler, &ir_raw_handler_list, list)
> +	mutex_lock(&ir_raw_mutex);
> +	list_del_rcu(&dev->raw->list);
> +	list_for_each_entry_rcu(handler, &ir_raw_handler_list, list)
>  		if (handler->raw_unregister)
>  			handler->raw_unregister(dev);
> -	mutex_unlock(&ir_raw_handler_lock);
> +	mutex_unlock(&ir_raw_mutex);
> +	synchronize_rcu();
>  
> -	kfifo_free(&dev->raw->kfifo);
>  	kfree(dev->raw);
>  	dev->raw = NULL;
>  	rc_unregister_device(dev);
> @@ -372,13 +348,14 @@ int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler)
>  {
>  	struct ir_raw_event_ctrl *raw;
>  
> -	mutex_lock(&ir_raw_handler_lock);
> -	list_add_tail(&ir_raw_handler->list, &ir_raw_handler_list);
> +	mutex_lock(&ir_raw_mutex);
> +	list_add_tail_rcu(&ir_raw_handler->list, &ir_raw_handler_list);
>  	if (ir_raw_handler->raw_register)
> -		list_for_each_entry(raw, &ir_raw_client_list, list)
> +		list_for_each_entry_rcu(raw, &ir_raw_client_list, list)
>  			ir_raw_handler->raw_register(raw->dev);
>  	available_protocols |= ir_raw_handler->protocols;
> -	mutex_unlock(&ir_raw_handler_lock);
> +	mutex_unlock(&ir_raw_mutex);
> +	synchronize_rcu();
>  
>  	return 0;
>  }
> @@ -388,13 +365,14 @@ void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler)
>  {
>  	struct ir_raw_event_ctrl *raw;
>  
> -	mutex_lock(&ir_raw_handler_lock);
> -	list_del(&ir_raw_handler->list);
> +	mutex_lock(&ir_raw_mutex);
> +	list_del_rcu(&ir_raw_handler->list);
>  	if (ir_raw_handler->raw_unregister)
> -		list_for_each_entry(raw, &ir_raw_client_list, list)
> +		list_for_each_entry_rcu(raw, &ir_raw_client_list, list)
>  			ir_raw_handler->raw_unregister(raw->dev);
>  	available_protocols &= ~ir_raw_handler->protocols;
> -	mutex_unlock(&ir_raw_handler_lock);
> +	mutex_unlock(&ir_raw_mutex);
> +	synchronize_rcu();
>  }
>  EXPORT_SYMBOL(ir_raw_handler_unregister);
>  
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

  reply	other threads:[~2014-07-25 23:08 UTC|newest]

Thread overview: 68+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-04-03 23:31 [PATCH 00/49] rc-core: my current patch queue David Härdeman
2014-04-03 23:31 ` [PATCH 01/49] bt8xx: fixup RC5 decoding David Härdeman
2014-04-03 23:31 ` [PATCH 02/49] rc-core: improve ir-kbd-i2c get_key functions David Härdeman
2014-04-03 23:31 ` [PATCH 03/49] rc-core: document the protocol type David Härdeman
2014-04-03 23:31 ` [PATCH 04/49] rc-core: do not change 32bit NEC scancode format for now David Härdeman
2014-04-04 13:18   ` James Hogan
2014-04-03 23:31 ` [PATCH 05/49] rc-core: split dev->s_filter David Härdeman
2014-04-04 13:08   ` James Hogan
2014-04-03 23:31 ` [PATCH 06/49] rc-core: remove generic scancode filter David Härdeman
2014-04-04 13:30   ` James Hogan
2014-04-03 23:31 ` [PATCH 07/49] dib0700: NEC scancode cleanup David Härdeman
2014-04-03 23:31 ` [PATCH 08/49] lmedm04: " David Härdeman
2014-04-03 23:32 ` [PATCH 09/49] saa7134: NEC scancode fix David Härdeman
2014-04-03 23:32 ` [PATCH 10/49] [RFC] rc-core: use the full 32 bits for NEC scancodes David Härdeman
2014-04-03 23:32 ` [PATCH 11/49] [RFC] rc-core: don't throw away protocol information David Härdeman
2014-04-03 23:32 ` [PATCH 12/49] rc-core: simplify sysfs code David Härdeman
2014-04-03 23:32 ` [PATCH 13/49] rc-core: remove protocol arrays David Härdeman
2014-04-03 23:32 ` [PATCH 14/49] rc-core: rename dev->scanmask to dev->scancode_mask David Härdeman
2014-04-03 23:32 ` [PATCH 15/49] rc-core: merge rc5 and streamzap decoders David Härdeman
2014-04-03 23:32 ` [PATCH 16/49] rc-core: use an IDA rather than a bitmap David Härdeman
2014-07-25 22:39   ` Mauro Carvalho Chehab
2014-04-03 23:32 ` [PATCH 17/49] rc-core: add chardev David Härdeman
2014-04-03 23:32 ` [PATCH 18/49] rc-core: allow chardev to be read David Härdeman
2014-04-03 23:32 ` [PATCH 19/49] rc-core: use a kfifo for TX data David Härdeman
2014-04-03 23:32 ` [PATCH 20/49] rc-core: allow chardev to be written David Härdeman
2014-04-03 23:33 ` [PATCH 21/49] rc-core: add ioctl support to the rc chardev David Härdeman
2014-04-03 23:33 ` [PATCH 22/49] rc-core: add an ioctl for getting IR RX settings David Härdeman
2014-04-03 23:33 ` [PATCH 23/49] rc-loopback: add RCIOCGIRRX ioctl support David Härdeman
2014-04-03 23:33 ` [PATCH 24/49] rc-core: add an ioctl for setting IR RX settings David Härdeman
2014-04-03 23:33 ` [PATCH 25/49] rc-loopback: add RCIOCSIRRX ioctl support David Härdeman
2014-04-03 23:33 ` [PATCH 26/49] rc-core: add an ioctl for getting IR TX settings David Härdeman
2014-04-03 23:33 ` [PATCH 27/49] rc-loopback: add RCIOCGIRTX ioctl support David Härdeman
2014-04-03 23:33 ` [PATCH 28/49] rc-core: add an ioctl for setting IR TX settings David Härdeman
2014-04-03 23:33 ` [PATCH 29/49] rc-loopback: add RCIOCSIRTX ioctl support David Härdeman
2014-04-03 23:33 ` [PATCH 30/49] rc-core: leave the internals of rc_dev alone David Härdeman
2014-07-24  1:50   ` Mauro Carvalho Chehab
2014-04-03 23:33 ` [PATCH 31/49] rc-core: split rc-main.c into rc-main.c and rc-keytable.c David Härdeman
2014-07-25 22:44   ` Mauro Carvalho Chehab
2014-04-03 23:33 ` [PATCH 32/49] rc-core: prepare for multiple keytables David Härdeman
2014-07-25 22:52   ` Mauro Carvalho Chehab
2014-04-03 23:34 ` [PATCH 33/49] rc-core: make the keytable of rc_dev an array David Härdeman
2014-04-03 23:34 ` [PATCH 34/49] rc-core: add ioctls for adding/removing keytables from userspace David Härdeman
2014-04-03 23:34 ` [PATCH 35/49] rc-core: remove redundant spinlock David Härdeman
2014-04-03 23:34 ` [PATCH 36/49] rc-core: make keytable RCU-friendly David Härdeman
2014-04-03 23:34 ` [PATCH 37/49] rc-core: allow empty keymaps David Härdeman
2014-07-25 22:58   ` Mauro Carvalho Chehab
2014-04-03 23:34 ` [PATCH 38/49] rc-core: rename ir-raw.c David Härdeman
2014-04-03 23:34 ` [PATCH 39/49] rc-core: make IR raw handling a separate module David Härdeman
2014-07-25 23:04   ` Mauro Carvalho Chehab
2014-04-03 23:34 ` [PATCH 40/49] rc-ir-raw: simplify locking David Härdeman
2014-07-25 23:08   ` Mauro Carvalho Chehab [this message]
2014-04-03 23:34 ` [PATCH 41/49] rc-core: rename mutex David Härdeman
2014-04-10 21:28   ` James Hogan
2014-07-25 23:12   ` Mauro Carvalho Chehab
2014-04-03 23:34 ` [PATCH 42/49] rc-ir-raw: atomic reads of protocols David Härdeman
2014-07-25 23:13   ` Mauro Carvalho Chehab
2014-04-03 23:34 ` [PATCH 43/49] rc-core: fix various sparse warnings David Härdeman
2014-04-03 23:34 ` [PATCH 44/49] rc-core: don't report scancodes via input devices David Härdeman
2014-07-25 23:16   ` Mauro Carvalho Chehab
2014-04-03 23:35 ` [PATCH 45/49] rc-ir-raw: add various rc_events David Härdeman
2014-07-25 23:16   ` Mauro Carvalho Chehab
2014-04-03 23:35 ` [PATCH 46/49] rc-core: use struct rc_event for all rc communication David Härdeman
2014-07-25 23:19   ` Mauro Carvalho Chehab
2014-04-03 23:35 ` [PATCH 47/49] rc-core: add keytable events David Härdeman
2014-04-03 23:35 ` [PATCH 48/49] rc-core: move remaining keytable functions David Härdeman
2014-04-03 23:35 ` [PATCH 49/49] rc-core: make rc-core.h userspace friendly David Härdeman
2014-04-04  2:05 ` [PATCH 00/49] rc-core: my current patch queue Mauro Carvalho Chehab
2014-06-26 20:07 ` David Härdeman

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20140725200852.1aa56c69.m.chehab@samsung.com \
    --to=m.chehab@samsung.com \
    --cc=david@hardeman.nu \
    --cc=linux-media@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.