build/patch/kernel/archive/sunxi-5.15/patches.megous/misc-modem-power-Add-blocking-variant-of-sysfs-power-state-upda.patch

164 lines
4.5 KiB
Diff

From 0d7dd2b992c85d554809b34e70a127c25e3362c6 Mon Sep 17 00:00:00 2001
From: Ondrej Jirman <megous@megous.com>
Date: Tue, 8 Sep 2020 02:51:57 +0200
Subject: [PATCH 261/478] misc: modem-power: Add blocking variant of sysfs
power state update function
Makes writing modem powerup scripts easier.
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
drivers/misc/modem-power.c | 77 +++++++++++++++++++++++++-------------
1 file changed, 50 insertions(+), 27 deletions(-)
diff --git a/drivers/misc/modem-power.c b/drivers/misc/modem-power.c
index 5cb4e76c78ef..68aa7ecc6a3a 100644
--- a/drivers/misc/modem-power.c
+++ b/drivers/misc/modem-power.c
@@ -944,14 +944,7 @@ static void mpwr_power_down(struct mpwr_dev* mpwr)
dev_info(dev, "powering down");
- set_bit(MPWR_F_POWER_CHANGE_INPROGRESS, mpwr->flags);
- sysfs_notify(&mpwr->dev->kobj, NULL, "is_busy");
-
ret = mpwr->variant->power_down(mpwr);
-
- clear_bit(MPWR_F_POWER_CHANGE_INPROGRESS, mpwr->flags);
- sysfs_notify(&mpwr->dev->kobj, NULL, "is_busy");
-
if (ret) {
dev_err(dev, "power down failed");
} else {
@@ -978,14 +971,7 @@ static void mpwr_power_up(struct mpwr_dev* mpwr)
dev_info(dev, "powering up");
- set_bit(MPWR_F_POWER_CHANGE_INPROGRESS, mpwr->flags);
- sysfs_notify(&mpwr->dev->kobj, NULL, "is_busy");
-
ret = mpwr->variant->power_up(mpwr);
-
- clear_bit(MPWR_F_POWER_CHANGE_INPROGRESS, mpwr->flags);
- sysfs_notify(&mpwr->dev->kobj, NULL, "is_busy");
-
if (ret) {
dev_err(dev, "power up failed");
} else {
@@ -1099,9 +1085,27 @@ static void mpwr_work_handler(struct work_struct *work)
mutex_unlock(&mpwr->modem_lock);
+ clear_bit(MPWR_F_POWER_CHANGE_INPROGRESS, mpwr->flags);
+ sysfs_notify(&mpwr->dev->kobj, NULL, "is_busy");
+ wake_up(&mpwr->wait);
+
pm_relax(mpwr->dev);
}
+static void mpwr_request_power_change(struct mpwr_dev* mpwr, int request)
+{
+ unsigned long flags;
+
+ set_bit(MPWR_F_POWER_CHANGE_INPROGRESS, mpwr->flags);
+ sysfs_notify(&mpwr->dev->kobj, NULL, "is_busy");
+
+ spin_lock_irqsave(&mpwr->lock, flags);
+ mpwr->last_request = request;
+ spin_unlock_irqrestore(&mpwr->lock, flags);
+
+ queue_work(mpwr->wq, &mpwr->power_work);
+}
+
static irqreturn_t mpwr_gpio_isr(int irq, void *dev_id)
{
struct mpwr_dev *mpwr = dev_id;
@@ -1162,7 +1166,6 @@ static ssize_t powered_store(struct device *dev,
const char *buf, size_t len)
{
struct mpwr_dev *mpwr = platform_get_drvdata(to_platform_device(dev));
- unsigned long flags;
bool status;
int ret;
@@ -1170,11 +1173,35 @@ static ssize_t powered_store(struct device *dev,
if (ret)
return ret;
- spin_lock_irqsave(&mpwr->lock, flags);
- mpwr->last_request = status ? MPWR_REQ_PWUP : MPWR_REQ_PWDN;
- spin_unlock_irqrestore(&mpwr->lock, flags);
+ mpwr_request_power_change(mpwr, status ? MPWR_REQ_PWUP : MPWR_REQ_PWDN);
- queue_work(mpwr->wq, &mpwr->power_work);
+ return len;
+}
+
+static ssize_t powered_blocking_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct mpwr_dev *mpwr = platform_get_drvdata(to_platform_device(dev));
+ bool status;
+ int ret;
+
+ ret = kstrtobool(buf, &status);
+ if (ret)
+ return ret;
+
+ mpwr_request_power_change(mpwr, status ? MPWR_REQ_PWUP : MPWR_REQ_PWDN);
+
+ ret = wait_event_interruptible_timeout(mpwr->wait,
+ !test_bit(MPWR_F_POWER_CHANGE_INPROGRESS, mpwr->flags),
+ msecs_to_jiffies(60000));
+ if (ret <= 0) {
+ dev_err(mpwr->dev, "Power state change timeout\n");
+ return -EIO;
+ }
+
+ if (!!status != !!test_bit(MPWR_F_POWERED, mpwr->flags))
+ return -EIO;
return len;
}
@@ -1260,25 +1287,20 @@ static ssize_t hard_reset_store(struct device *dev,
const char *buf, size_t len)
{
struct mpwr_dev *mpwr = platform_get_drvdata(to_platform_device(dev));
- unsigned long flags;
bool val;
int ret;
ret = kstrtobool(buf, &val);
if (ret)
return ret;
-
- if (val) {
- spin_lock_irqsave(&mpwr->lock, flags);
- mpwr->last_request = MPWR_REQ_RESET;
- spin_unlock_irqrestore(&mpwr->lock, flags);
- queue_work(mpwr->wq, &mpwr->power_work);
- }
+ if (val)
+ mpwr_request_power_change(mpwr, MPWR_REQ_RESET);
return len;
}
static DEVICE_ATTR_RW(powered);
+static DEVICE_ATTR_WO(powered_blocking);
static DEVICE_ATTR_RW(dumb_powerup);
static DEVICE_ATTR_RW(wait_rdy);
static DEVICE_ATTR_RO(killswitched);
@@ -1287,6 +1309,7 @@ static DEVICE_ATTR_WO(hard_reset);
static struct attribute *mpwr_attrs[] = {
&dev_attr_powered.attr,
+ &dev_attr_powered_blocking.attr,
&dev_attr_dumb_powerup.attr,
&dev_attr_wait_rdy.attr,
&dev_attr_killswitched.attr,
--
2.35.3