Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 180ea05b authored by Tomas Winkler's avatar Tomas Winkler Committed by Greg Kroah-Hartman
Browse files

mei: me: add runtime pm framework



Add runtime pm framework for ME devices.
The runtime pm handlers are used to run
me power gating isolation protocol

Signed-off-by: default avatarTomas Winkler <tomas.winkler@intel.com>
Signed-off-by: default avatarAlexander Usyskin <alexander.usyskin@intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent a532bbed
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/mei.h>
#include <linux/pm_runtime.h>

#include "mei_dev.h"
#include "hbm.h"
@@ -742,6 +743,13 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
		dev->pg_event = MEI_PG_EVENT_RECEIVED;
		if (waitqueue_active(&dev->wait_pg))
			wake_up(&dev->wait_pg);
		else
			/*
			* If the driver is not waiting on this then
			* this is HW initiated exit from PG.
			* Start runtime pm resume sequence to exit from PG.
			*/
			pm_request_resume(&dev->pdev->dev);
		break;

	case HOST_CLIENT_PROPERTIES_RES_CMD:
+2 −0
Original line number Diff line number Diff line
@@ -24,6 +24,8 @@
#include "mei_dev.h"
#include "client.h"

#define MEI_ME_RPM_TIMEOUT    500 /* ms */

struct mei_me_hw {
	void __iomem *mem_addr;
	/*
+90 −2
Original line number Diff line number Diff line
@@ -33,6 +33,8 @@
#include <linux/interrupt.h>
#include <linux/miscdevice.h>

#include <linux/pm_runtime.h>

#include <linux/mei.h>

#include "mei_dev.h"
@@ -212,6 +214,9 @@ static int mei_me_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
		goto release_irq;
	}

	pm_runtime_set_autosuspend_delay(&pdev->dev, MEI_ME_RPM_TIMEOUT);
	pm_runtime_use_autosuspend(&pdev->dev);

	err = mei_register(dev);
	if (err)
		goto release_irq;
@@ -220,6 +225,9 @@ static int mei_me_probe(struct pci_dev *pdev, const struct pci_device_id *ent)

	schedule_delayed_work(&dev->timer_work, HZ);

	if (mei_pg_is_enabled(dev))
		pm_runtime_put_noidle(&pdev->dev);

	dev_dbg(&pdev->dev, "initialization successful.\n");

	return 0;
@@ -259,6 +267,9 @@ static void mei_me_remove(struct pci_dev *pdev)
	if (!dev)
		return;

	if (mei_pg_is_enabled(dev))
		pm_runtime_get_noresume(&pdev->dev);

	hw = to_me_hw(dev);


@@ -343,12 +354,89 @@ static int mei_me_pci_resume(struct device *device)

	return 0;
}
#endif /* CONFIG_PM_SLEEP */

#ifdef CONFIG_PM_RUNTIME
static int mei_me_pm_runtime_idle(struct device *device)
{
	struct pci_dev *pdev = to_pci_dev(device);
	struct mei_device *dev;

	dev_dbg(&pdev->dev, "rpm: me: runtime_idle\n");

	dev = pci_get_drvdata(pdev);
	if (!dev)
		return -ENODEV;
	if (mei_write_is_idle(dev))
		pm_schedule_suspend(device, MEI_ME_RPM_TIMEOUT * 2);

	return -EBUSY;
}

static int mei_me_pm_runtime_suspend(struct device *device)
{
	struct pci_dev *pdev = to_pci_dev(device);
	struct mei_device *dev;
	int ret;

	dev_dbg(&pdev->dev, "rpm: me: runtime suspend\n");

	dev = pci_get_drvdata(pdev);
	if (!dev)
		return -ENODEV;

	mutex_lock(&dev->device_lock);

	if (mei_write_is_idle(dev))
		ret = mei_me_pg_set_sync(dev);
	else
		ret = -EAGAIN;

	mutex_unlock(&dev->device_lock);

	dev_dbg(&pdev->dev, "rpm: me: runtime suspend ret=%d\n", ret);

	return ret;
}

static int mei_me_pm_runtime_resume(struct device *device)
{
	struct pci_dev *pdev = to_pci_dev(device);
	struct mei_device *dev;
	int ret;

	dev_dbg(&pdev->dev, "rpm: me: runtime resume\n");

	dev = pci_get_drvdata(pdev);
	if (!dev)
		return -ENODEV;

	mutex_lock(&dev->device_lock);

	ret = mei_me_pg_unset_sync(dev);

	mutex_unlock(&dev->device_lock);

	dev_dbg(&pdev->dev, "rpm: me: runtime resume ret = %d\n", ret);

	return ret;
}
#endif /* CONFIG_PM_RUNTIME */

#ifdef CONFIG_PM
static const struct dev_pm_ops mei_me_pm_ops = {
	SET_SYSTEM_SLEEP_PM_OPS(mei_me_pci_suspend,
				mei_me_pci_resume)
	SET_RUNTIME_PM_OPS(
		mei_me_pm_runtime_suspend,
		mei_me_pm_runtime_resume,
		mei_me_pm_runtime_idle)
};

static SIMPLE_DEV_PM_OPS(mei_me_pm_ops, mei_me_pci_suspend, mei_me_pci_resume);
#define MEI_ME_PM_OPS	(&mei_me_pm_ops)
#else
#define MEI_ME_PM_OPS	NULL
#endif /* CONFIG_PM_SLEEP */
#endif /* CONFIG_PM */
/*
 *  PCI driver structure
 */