mei: speed up the power down flow
authorTomas Winkler <tomas.winkler@intel.com>
Tue, 12 Dec 2017 11:27:06 +0000 (13:27 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 13 Dec 2017 13:10:47 +0000 (14:10 +0100)
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 <tomas.winkler@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/misc/mei/bus.c
drivers/misc/mei/hw-me.c
drivers/misc/mei/hw-txe.c
drivers/misc/mei/init.c

index 1ac10cb64d6ed3e7d5ad20c1d5ebb1ec323fa05d..2a5146bdecf185d2e7510254eb44cec2d3782188 100644 (file)
@@ -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 */
index 10dcf4ff99a54fa1f5098febd6196a17d4b89a78..0b21f9ec00f5a2c2e14f642088922491e88f1383 100644 (file)
@@ -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);
index 24e4a4c966068de843e1189009112ebca54a6f78..84197277f26c5a51d8b1b05ec3ba6a59ed4f080f 100644 (file)
@@ -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);
 
index d2f691424dd1b17960d4c49866c3c92a9dde54af..c46f6e99a55efb19fa3477481183d6c3f6f87c2e 100644 (file)
@@ -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;