From 01428a1131cad8c74341856d01ff1544f2f26a0d Mon Sep 17 00:00:00 2001 From: Ondrej Jirman Date: Tue, 8 Sep 2020 02:51:57 +0200 Subject: [PATCH 178/351] misc: modem-power: Add blocking variant of sysfs power state update function Makes writing modem powerup scripts easier. Signed-off-by: Ondrej Jirman --- 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.34.0