From: Sean Young <sean@mess.org>
To: Joakim Zhang <qiangqing.zhang@nxp.com>
Cc: mchehab@kernel.org, linux-media@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-imx@nxp.com
Subject: Re: [PATCH] media: rc: gpio-ir-recv: add QoS support for cpuidle system
Date: Tue, 15 Sep 2020 10:33:42 +0100 [thread overview]
Message-ID: <20200915093342.GA24139@gofer.mess.org> (raw)
In-Reply-To: <20200915150202.24165-1-qiangqing.zhang@nxp.com>
Hi Joakim,
Thanks for your patch, I think it looks good in principle but needs a
few small fixes.
On Tue, Sep 15, 2020 at 11:02:02PM +0800, Joakim Zhang wrote:
> GPIO IR receive is much rely on interrupt response, uneven interrupt
> latency will lead to incorrect timing, so the decoder fails to decode
> it. The issue is particularly acute on systems which supports
> cpuidle, dynamically disable and enable cpuidle can solve this problem
> to a great extent.
This is the first soc to be affected by this problem, and gpio-ir-recv
has been used on my systems. For example, the raspberry pi has cpu idle
enabled and does not suffer from this problem. There are many more; this
driver has been used on many arm devices, which will have cpuidle enabled.
>
> However, there is a downside to this approach, the measurement of header
> on the first frame may incorrect. Test on i.MX8M serials, when enable
> cpuidle, interrupt latency could be about 500us.
>
> With this patch:
> 1. has no side effect on non-cpuidle system.
> 2. latency is still much longer for the first gpio interrupt on cpuidle
> system, so the first frame may not be decoded. Generally, RC would transmit
> multiple frames at once press, we can sacrifice the first frame.
>
> Signed-off-by: Joakim Zhang <qiangqing.zhang@nxp.com>
> ---
> drivers/media/rc/gpio-ir-recv.c | 49 ++++++++++++++++++++++++++++++++-
> 1 file changed, 48 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/media/rc/gpio-ir-recv.c b/drivers/media/rc/gpio-ir-recv.c
> index a20413008c3c..42c942ce98cd 100644
> --- a/drivers/media/rc/gpio-ir-recv.c
> +++ b/drivers/media/rc/gpio-ir-recv.c
> @@ -11,6 +11,8 @@
> #include <linux/of.h>
> #include <linux/of_gpio.h>
> #include <linux/platform_device.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/pm_qos.h>
> #include <linux/irq.h>
> #include <media/rc-core.h>
>
> @@ -20,17 +22,36 @@ struct gpio_rc_dev {
> struct rc_dev *rcdev;
> struct gpio_desc *gpiod;
> int irq;
> + struct pm_qos_request qos;
> };
>
> static irqreturn_t gpio_ir_recv_irq(int irq, void *dev_id)
> {
> - int val;
> + int ret, val;
> struct gpio_rc_dev *gpio_dev = dev_id;
> + struct device *dev = gpio_dev->rcdev->dev.parent;
> +
> + /*
> + * For cpuidle system:
For some cpuidle systems, not all. This is why this feature needs a
device tree option for enabling. Otherwise, it will negatively affect
power usage on e.g. raspberry pi.
> + * Respond to interrupt taking more latency when cpu in idle.
> + * Invoke asynchronous pm runtime get from interrupt context,
> + * this may introduce a millisecond delay to call resume callback,
> + * where to disable cpuilde.
> + *
> + * Two issues lead to fail to decode first frame, one is latency to
> + * respond interupt, another is delay introduced by async api.
> + */
> + ret = pm_runtime_get(dev);
> + if (ret < 0)
> + return IRQ_NONE;
If we end up here, we also abandon sending the IR to rc-core (below). I
don't think it should do that. It should call ir_raw_event_store_edge()
always even if it can't do the pm things.
>
> val = gpiod_get_value(gpio_dev->gpiod);
> if (val >= 0)
> ir_raw_event_store_edge(gpio_dev->rcdev, val == 1);
>
> + pm_runtime_mark_last_busy(dev);
> + pm_runtime_put_autosuspend(dev);
> +
> return IRQ_HANDLED;
> }
>
> @@ -92,6 +113,12 @@ static int gpio_ir_recv_probe(struct platform_device *pdev)
>
> platform_set_drvdata(pdev, gpio_dev);
>
> +
> + pm_runtime_set_autosuspend_delay(dev, (rcdev->timeout / 1000 / 1000));
rcdev->timeout is in microseconds (since very recently), so this is wrong.
Also, the timeout can be changed using the LIRC_SET_REC_TIMEOUT ioctl
(using ir-ctl -t in userspace). The autosuspend delay should be updated
when this happens. This can be done by implementing the s_timeout rcdev
function.
> + pm_runtime_use_autosuspend(dev);
> + pm_runtime_set_suspended(dev);
> + pm_runtime_enable(dev);
> +
> return devm_request_irq(dev, gpio_dev->irq, gpio_ir_recv_irq,
> IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
> "gpio-ir-recv-irq", gpio_dev);
> @@ -122,9 +149,29 @@ static int gpio_ir_recv_resume(struct device *dev)
> return 0;
> }
>
> +static int gpio_ir_recv_runtime_suspend(struct device *dev)
> +{
> + struct gpio_rc_dev *gpio_dev = dev_get_drvdata(dev);
> +
> + cpu_latency_qos_remove_request(&gpio_dev->qos);
> +
> + return 0;
> +}
> +
> +static int gpio_ir_recv_runtime_resume(struct device *dev)
> +{
> + struct gpio_rc_dev *gpio_dev = dev_get_drvdata(dev);
> +
> + cpu_latency_qos_add_request(&gpio_dev->qos, 0);
> +
> + return 0;
> +}
> +
> static const struct dev_pm_ops gpio_ir_recv_pm_ops = {
> .suspend = gpio_ir_recv_suspend,
> .resume = gpio_ir_recv_resume,
> + .runtime_suspend = gpio_ir_recv_runtime_suspend,
> + .runtime_resume = gpio_ir_recv_runtime_resume,
> };
> #endif
>
> --
> 2.17.1
next prev parent reply other threads:[~2020-09-15 9:33 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-09-15 15:02 [PATCH] media: rc: gpio-ir-recv: add QoS support for cpuidle system Joakim Zhang
2020-09-15 9:33 ` Sean Young [this message]
2020-09-15 10:55 ` Joakim Zhang
2020-09-15 20:19 ` Sean Young
2020-09-16 10:22 ` Joakim Zhang
2020-09-16 18:19 ` Sean Young
2020-09-17 9:12 ` Joakim Zhang
2020-09-17 20:43 ` Sean Young
2020-09-18 1:42 ` Joakim Zhang
2020-09-18 8:23 ` Sean Young
2020-09-18 8:56 ` Joakim Zhang
[not found] ` <CAHp75Vftg3GmBsCCrZeXo4eofOYTJ2ii+s64hY5FqZadvX6Bww@mail.gmail.com>
[not found] ` <DB8PR04MB6795840F4C0D938A14D1E3BEE6200@DB8PR04MB6795.eurprd04.prod.outlook.com>
2020-09-15 10:42 ` Andy Shevchenko
-- strict thread matches above, loose matches on Subject: below --
2020-09-15 14:57 Joakim Zhang
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=20200915093342.GA24139@gofer.mess.org \
--to=sean@mess.org \
--cc=linux-imx@nxp.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-media@vger.kernel.org \
--cc=mchehab@kernel.org \
--cc=qiangqing.zhang@nxp.com \
/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.