From 8d52af6795c0480a20272159103976a893603fde Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Tue, 12 Dec 2017 13:27:06 +0200 Subject: mei: speed up the power down flow When mei driver is powering down due to suspend or shutdown it will iterate over the mei client bus and disconnect each client device attached in turn. The power down flow consist of the link rest, which causes all clients get disconnected at once, hence the individual disconnection can be omitted and significantly reduce power down flow. Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/bus.c | 10 ++++++++-- drivers/misc/mei/hw-me.c | 4 +++- drivers/misc/mei/hw-txe.c | 4 +++- drivers/misc/mei/init.c | 4 +++- 4 files changed, 17 insertions(+), 5 deletions(-) (limited to 'drivers/misc/mei') diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c index 1ac10cb64d6e..2a5146bdecf1 100644 --- a/drivers/misc/mei/bus.c +++ b/drivers/misc/mei/bus.c @@ -543,14 +543,20 @@ int mei_cldev_disable(struct mei_cl_device *cldev) mutex_lock(&bus->device_lock); if (!mei_cl_is_connected(cl)) { - dev_dbg(bus->dev, "Already disconnected"); + dev_dbg(bus->dev, "Already disconnected\n"); + err = 0; + goto out; + } + + if (bus->dev_state == MEI_DEV_POWER_DOWN) { + dev_dbg(bus->dev, "Device is powering down don't botther with disconnection\n"); err = 0; goto out; } err = mei_cl_disconnect(cl); if (err < 0) - dev_err(bus->dev, "Could not disconnect from the ME client"); + dev_err(bus->dev, "Could not disconnect from the ME client\n"); out: /* Flush queues and remove any pending read */ diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c index 10dcf4ff99a5..0b21f9ec00f5 100644 --- a/drivers/misc/mei/hw-me.c +++ b/drivers/misc/mei/hw-me.c @@ -1260,7 +1260,9 @@ irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id) if (rets == -ENODATA) break; - if (rets && dev->dev_state != MEI_DEV_RESETTING) { + if (rets && + (dev->dev_state != MEI_DEV_RESETTING || + dev->dev_state != MEI_DEV_POWER_DOWN)) { dev_err(dev->dev, "mei_irq_read_handler ret = %d.\n", rets); schedule_work(&dev->reset_work); diff --git a/drivers/misc/mei/hw-txe.c b/drivers/misc/mei/hw-txe.c index 24e4a4c96606..84197277f26c 100644 --- a/drivers/misc/mei/hw-txe.c +++ b/drivers/misc/mei/hw-txe.c @@ -1127,7 +1127,9 @@ irqreturn_t mei_txe_irq_thread_handler(int irq, void *dev_id) if (test_and_clear_bit(TXE_INTR_OUT_DB_BIT, &hw->intr_cause)) { /* Read from TXE */ rets = mei_irq_read_handler(dev, &cmpl_list, &slots); - if (rets && dev->dev_state != MEI_DEV_RESETTING) { + if (rets && + (dev->dev_state != MEI_DEV_RESETTING || + dev->dev_state != MEI_DEV_POWER_DOWN)) { dev_err(dev->dev, "mei_irq_read_handler ret = %d.\n", rets); diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c index d2f691424dd1..c46f6e99a55e 100644 --- a/drivers/misc/mei/init.c +++ b/drivers/misc/mei/init.c @@ -310,6 +310,9 @@ void mei_stop(struct mei_device *dev) { dev_dbg(dev->dev, "stopping the device.\n"); + mutex_lock(&dev->device_lock); + dev->dev_state = MEI_DEV_POWER_DOWN; + mutex_unlock(&dev->device_lock); mei_cl_bus_remove_devices(dev); mei_cancel_work(dev); @@ -319,7 +322,6 @@ void mei_stop(struct mei_device *dev) mutex_lock(&dev->device_lock); - dev->dev_state = MEI_DEV_POWER_DOWN; mei_reset(dev); /* move device to disabled state unconditionally */ dev->dev_state = MEI_DEV_DISABLED; -- cgit v1.2.3 From 8a943bd283ecbaaab26b184717bd2395af1da1e4 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sat, 16 Dec 2017 23:44:24 +0000 Subject: mei: fix spelling mistake: "botther" -> "bother" Trivial fix to spelling mistake in dev_dbg debug message. Also add in a missing comma. Signed-off-by: Colin Ian King Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/bus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/misc/mei') diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c index 2a5146bdecf1..3e5eabdae8d9 100644 --- a/drivers/misc/mei/bus.c +++ b/drivers/misc/mei/bus.c @@ -549,7 +549,7 @@ int mei_cldev_disable(struct mei_cl_device *cldev) } if (bus->dev_state == MEI_DEV_POWER_DOWN) { - dev_dbg(bus->dev, "Device is powering down don't botther with disconnection\n"); + dev_dbg(bus->dev, "Device is powering down, don't bother with disconnection\n"); err = 0; goto out; } -- cgit v1.2.3 From cc365dcf0e56271bedf3de95f88922abe248e951 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Tue, 2 Jan 2018 12:01:41 +0200 Subject: mei: me: allow runtime pm for platform with D0i3 >From the pci power documentation: "The driver itself should not call pm_runtime_allow(), though. Instead, it should let user space or some platform-specific code do that (user space can do it via sysfs as stated above)..." However, the S0ix residency cannot be reached without MEI device getting into low power state. Hence, for mei devices that support D0i3, it's better to make runtime power management mandatory and not rely on the system integration such as udev rules. This policy cannot be applied globally as some older platforms were found to have broken power management. Cc: v4.13+ Cc: Rafael J. Wysocki Signed-off-by: Tomas Winkler Reviewed-by: Alexander Usyskin Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/pci-me.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/misc/mei') diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c index f4f17552c9b8..4a0ccda4d04b 100644 --- a/drivers/misc/mei/pci-me.c +++ b/drivers/misc/mei/pci-me.c @@ -238,8 +238,11 @@ static int mei_me_probe(struct pci_dev *pdev, const struct pci_device_id *ent) */ mei_me_set_pm_domain(dev); - if (mei_pg_is_enabled(dev)) + if (mei_pg_is_enabled(dev)) { pm_runtime_put_noidle(&pdev->dev); + if (hw->d0i3_supported) + pm_runtime_allow(&pdev->dev); + } dev_dbg(&pdev->dev, "initialization successful.\n"); -- cgit v1.2.3 From 912ed8afd6432f1c7c084ccd752139debc2f7014 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 19 Dec 2017 17:35:30 +0000 Subject: mei: fix incorrect logical operator in if statement The current expression using the || operator is always true because dev->dev_state cannot be equal to two different values at the same time. Fix this by replacing the || with &&. Detected by CoverityScan, CID#1463042 ("Constant expression result") Fixes: 8d52af6795c0 ("mei: speed up the power down flow") Signed-off-by: Colin Ian King Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/hw-me.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/misc/mei') diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c index 0b21f9ec00f5..334ab02e1de2 100644 --- a/drivers/misc/mei/hw-me.c +++ b/drivers/misc/mei/hw-me.c @@ -1261,7 +1261,7 @@ irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id) break; if (rets && - (dev->dev_state != MEI_DEV_RESETTING || + (dev->dev_state != MEI_DEV_RESETTING && dev->dev_state != MEI_DEV_POWER_DOWN)) { dev_err(dev->dev, "mei_irq_read_handler ret = %d.\n", rets); -- cgit v1.2.3 From 16ae30ea17cdd2b67f486c3518592067c8f9cc62 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 6 Jan 2018 12:26:50 +0300 Subject: mei: fix an && vs || typo ->dev_state can't be both MEI_DEV_RESETTING and MEI_DEV_POWER_DOWN at the same time. && was clearing intended here. Fixes: 8d52af6795c0 ("mei: speed up the power down flow") Signed-off-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/hw-txe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/misc/mei') diff --git a/drivers/misc/mei/hw-txe.c b/drivers/misc/mei/hw-txe.c index 84197277f26c..c2c8993e2a51 100644 --- a/drivers/misc/mei/hw-txe.c +++ b/drivers/misc/mei/hw-txe.c @@ -1128,7 +1128,7 @@ irqreturn_t mei_txe_irq_thread_handler(int irq, void *dev_id) /* Read from TXE */ rets = mei_irq_read_handler(dev, &cmpl_list, &slots); if (rets && - (dev->dev_state != MEI_DEV_RESETTING || + (dev->dev_state != MEI_DEV_RESETTING && dev->dev_state != MEI_DEV_POWER_DOWN)) { dev_err(dev->dev, "mei_irq_read_handler ret = %d.\n", rets); -- cgit v1.2.3