From 95099d4622f8cb224d94e314c7a8e0df60b13f87 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Sat, 09 Dec 2023 08:38:01 +0000
Subject: [PATCH] enable docker ppp
---
kernel/drivers/media/rc/gpio-ir-recv.c | 63 +++++++++++++++++++++++++++----
1 files changed, 54 insertions(+), 9 deletions(-)
diff --git a/kernel/drivers/media/rc/gpio-ir-recv.c b/kernel/drivers/media/rc/gpio-ir-recv.c
index 3d99b51..22e524b 100644
--- a/kernel/drivers/media/rc/gpio-ir-recv.c
+++ b/kernel/drivers/media/rc/gpio-ir-recv.c
@@ -1,13 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
*/
#include <linux/kernel.h>
@@ -19,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>
@@ -28,16 +22,37 @@
struct rc_dev *rcdev;
struct gpio_desc *gpiod;
int irq;
+ struct device *pmdev;
+ struct pm_qos_request qos;
};
static irqreturn_t gpio_ir_recv_irq(int irq, void *dev_id)
{
int val;
struct gpio_rc_dev *gpio_dev = dev_id;
+ struct device *pmdev = gpio_dev->pmdev;
+
+ /*
+ * For some cpuidle systems, not all:
+ * 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 to interrupt, another is delay introduced by async api.
+ */
+ if (pmdev)
+ pm_runtime_get(pmdev);
val = gpiod_get_value(gpio_dev->gpiod);
if (val >= 0)
ir_raw_event_store_edge(gpio_dev->rcdev, val == 1);
+
+ if (pmdev) {
+ pm_runtime_mark_last_busy(pmdev);
+ pm_runtime_put_autosuspend(pmdev);
+ }
return IRQ_HANDLED;
}
@@ -48,6 +63,7 @@
struct device_node *np = dev->of_node;
struct gpio_rc_dev *gpio_dev;
struct rc_dev *rcdev;
+ u32 period = 0;
int rc;
if (!np)
@@ -98,6 +114,15 @@
return rc;
}
+ of_property_read_u32(np, "linux,autosuspend-period", &period);
+ if (period) {
+ gpio_dev->pmdev = dev;
+ pm_runtime_set_autosuspend_delay(dev, period);
+ pm_runtime_use_autosuspend(dev);
+ pm_runtime_set_suspended(dev);
+ pm_runtime_enable(dev);
+ }
+
platform_set_drvdata(pdev, gpio_dev);
return devm_request_irq(dev, gpio_dev->irq, gpio_ir_recv_irq,
@@ -130,9 +155,29 @@
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
--
Gitblit v1.6.2