mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Mike Ximing Chen <mike.ximing.chen@intel.com>
To: linux-kernel@vger.kernel.org
Cc: arnd@arndb.de, gregkh@linuxfoundation.org,
	dan.j.williams@intel.com, pierre-louis.bossart@linux.intel.com,
	netdev@vger.kernel.org, davem@davemloft.net, kuba@kernel.org
Subject: [RFC PATCH v12 08/17] dlb: add runtime power-management support
Date: Tue, 21 Dec 2021 00:50:38 -0600	[thread overview]
Message-ID: <20211221065047.290182-9-mike.ximing.chen@intel.com> (raw)
In-Reply-To: <20211221065047.290182-1-mike.ximing.chen@intel.com>

Implemented a power-management policy of putting the device in D0 when in
use (when there are any open device files or memory mappings, or there are
any virtual devices), and D3Hot otherwise.

Add resume/suspend callbacks; when the device resumes, reset the hardware
to a known good state.

Signed-off-by: Mike Ximing Chen <mike.ximing.chen@intel.com>
---
 drivers/misc/dlb/dlb_main.c   | 98 ++++++++++++++++++++++++++++++++++-
 drivers/misc/dlb/dlb_pf_ops.c |  8 +++
 2 files changed, 105 insertions(+), 1 deletion(-)

diff --git a/drivers/misc/dlb/dlb_main.c b/drivers/misc/dlb/dlb_main.c
index 343bf72dc9c7..4b263e849061 100644
--- a/drivers/misc/dlb/dlb_main.c
+++ b/drivers/misc/dlb/dlb_main.c
@@ -8,6 +8,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/pci.h>
+#include <linux/pm_runtime.h>
 #include <linux/uaccess.h>
 
 #include "dlb_main.h"
@@ -72,12 +73,32 @@ static int dlb_open(struct inode *i, struct file *f)
 	f->private_data = dlb;
 	dlb->f = f;
 
+	/*
+	 * Increment the device's usage count and immediately wake it
+	 * if it was suspended.
+	 */
+	pm_runtime_get_sync(&dlb->pdev->dev);
+
+	return 0;
+}
+
+static int dlb_close(struct inode *i, struct file *f)
+{
+	struct dlb *dlb = f->private_data;
+
+	/*
+	 * Decrement the device's usage count and suspend it when
+	 * the application stops using it.
+	 */
+	pm_runtime_put_sync_suspend(&dlb->pdev->dev);
+
 	return 0;
 }
 
 static const struct file_operations dlb_fops = {
 	.owner   = THIS_MODULE,
 	.open    = dlb_open,
+	.release = dlb_close,
 };
 
 int dlb_init_domain(struct dlb *dlb, u32 domain_id)
@@ -95,6 +116,12 @@ int dlb_init_domain(struct dlb *dlb, u32 domain_id)
 
 	dlb->sched_domains[domain_id] = domain;
 
+	/*
+	 * The matching put is in dlb_free_domain, executed when the domain's
+	 * refcnt reaches zero.
+	 */
+	pm_runtime_get_sync(&dlb->pdev->dev);
+
 	return 0;
 }
 
@@ -119,7 +146,21 @@ static int __dlb_free_domain(struct dlb_domain *domain)
 
 void dlb_free_domain(struct kref *kref)
 {
-	__dlb_free_domain(container_of(kref, struct dlb_domain, refcnt));
+	struct dlb_domain *domain;
+	struct dlb *dlb;
+
+	domain = container_of(kref, struct dlb_domain, refcnt);
+
+	dlb = domain->dlb;
+
+	__dlb_free_domain(domain);
+
+	/*
+	 * Decrement the device's usage count and suspend it when
+	 * the last application stops using it. The matching get is in
+	 * dlb_init_domain.
+	 */
+	pm_runtime_put_sync_suspend(&dlb->pdev->dev);
 }
 
 static int dlb_domain_close(struct inode *i, struct file *f)
@@ -230,6 +271,14 @@ static int dlb_probe(struct pci_dev *pdev, const struct pci_device_id *pdev_id)
 	if (ret)
 		goto init_driver_state_fail;
 
+	/*
+	 * Undo the 'get' operation by the PCI layer during probe and
+	 * (if PF) immediately suspend the device. Since the device is only
+	 * enabled when an application requests it, an autosuspend delay is
+	 * likely not beneficial.
+	 */
+	pm_runtime_put_sync_suspend(&pdev->dev);
+
 	return 0;
 
 init_driver_state_fail:
@@ -254,6 +303,9 @@ static void dlb_remove(struct pci_dev *pdev)
 {
 	struct dlb *dlb = pci_get_drvdata(pdev);
 
+	/* Undo the PM operation in dlb_probe(). */
+	pm_runtime_get_noresume(&pdev->dev);
+
 	dlb_resource_free(&dlb->hw);
 
 	device_destroy(dlb_class, dlb->dev_number);
@@ -265,17 +317,61 @@ static void dlb_remove(struct pci_dev *pdev)
 	mutex_unlock(&dlb_ids_lock);
 }
 
+#ifdef CONFIG_PM
+static void dlb_reset_hardware_state(struct dlb *dlb)
+{
+	dlb_reset_device(dlb->pdev);
+}
+
+static int dlb_runtime_suspend(struct device *dev)
+{
+	/* Return and let the PCI subsystem put the device in D3hot. */
+
+	return 0;
+}
+
+static int dlb_runtime_resume(struct device *dev)
+{
+	struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
+	struct dlb *dlb = pci_get_drvdata(pdev);
+	int ret;
+
+	/*
+	 * The PCI subsystem put the device in D0, but the device may not have
+	 * completed powering up. Wait until the device is ready before
+	 * proceeding.
+	 */
+	ret = dlb_pf_wait_for_device_ready(dlb, pdev);
+	if (ret)
+		return ret;
+
+	/* Now reinitialize the device state. */
+	dlb_reset_hardware_state(dlb);
+
+	return 0;
+}
+#endif
+
 static struct pci_device_id dlb_id_table[] = {
 	{ PCI_DEVICE_DATA(INTEL, DLB_PF, DLB_PF) },
 	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, dlb_id_table);
 
+#ifdef CONFIG_PM
+static const struct dev_pm_ops dlb_pm_ops = {
+	SET_RUNTIME_PM_OPS(dlb_runtime_suspend, dlb_runtime_resume, NULL)
+};
+#endif
+
 static struct pci_driver dlb_pci_driver = {
 	.name		 = "dlb",
 	.id_table	 = dlb_id_table,
 	.probe		 = dlb_probe,
 	.remove		 = dlb_remove,
+#ifdef CONFIG_PM
+	.driver.pm	 = &dlb_pm_ops,
+#endif
 };
 
 static int __init dlb_init_module(void)
diff --git a/drivers/misc/dlb/dlb_pf_ops.c b/drivers/misc/dlb/dlb_pf_ops.c
index 8d179beb9d5b..65213c0475e5 100644
--- a/drivers/misc/dlb/dlb_pf_ops.c
+++ b/drivers/misc/dlb/dlb_pf_ops.c
@@ -2,6 +2,7 @@
 /* Copyright(C) 2016-2020 Intel Corporation. All rights reserved. */
 
 #include <linux/delay.h>
+#include <linux/pm_runtime.h>
 
 #include "dlb_main.h"
 #include "dlb_regs.h"
@@ -43,6 +44,13 @@ int dlb_pf_init_driver_state(struct dlb *dlb)
 {
 	mutex_init(&dlb->resource_mutex);
 
+	/*
+	 * Allow PF runtime power-management (forbidden by default by the PCI
+	 * layer during scan). The driver puts the device into D3hot while
+	 * there are no scheduling domains to service.
+	 */
+	pm_runtime_allow(&dlb->pdev->dev);
+
 	return 0;
 }
 
-- 
2.27.0


  parent reply	other threads:[~2021-12-21  6:50 UTC|newest]

Thread overview: 50+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-12-21  6:50 [RFC PATCH v12 00/17] dlb: introduce DLB device driver Mike Ximing Chen
2021-12-21  6:50 ` [RFC PATCH v12 01/17] dlb: add skeleton for DLB driver Mike Ximing Chen
2021-12-21  7:00   ` Joe Perches
2021-12-21 23:22     ` Chen, Mike Ximing
2021-12-22  2:02       ` Joe Perches
2021-12-21  7:12   ` Greg KH
2021-12-21  8:57     ` Greg KH
2021-12-21 14:25       ` Chen, Mike Ximing
2021-12-21 14:42         ` Chen, Mike Ximing
2021-12-21 15:02           ` Greg KH
2021-12-21 14:05     ` Chen, Mike Ximing
2021-12-21  9:53   ` Andrew Lunn
2021-12-21 20:56     ` Chen, Mike Ximing
2021-12-21 21:39       ` Andrew Lunn
2021-12-21 23:05         ` Chen, Mike Ximing
2021-12-22 21:26           ` Andrew Lunn
2021-12-23  5:15             ` Chen, Mike Ximing
2021-12-23 10:22               ` Andrew Lunn
2021-12-27  0:40                 ` Chen, Mike Ximing
     [not found]             ` <20211222194746.3480dea8@hermes.local>
2021-12-23  5:39               ` Dan Williams
2021-12-21  6:50 ` [RFC PATCH v12 02/17] dlb: initialize DLB device Mike Ximing Chen
2021-12-21  6:50 ` [RFC PATCH v12 03/17] dlb: add resource and device initialization Mike Ximing Chen
2021-12-21  6:50 ` [RFC PATCH v12 04/17] dlb: add configfs interface and scheduling domain directory Mike Ximing Chen
2021-12-21  6:50 ` [RFC PATCH v12 05/17] dlb: add scheduling domain configuration Mike Ximing Chen
2021-12-21  6:50 ` [RFC PATCH v12 06/17] dlb: add domain software reset Mike Ximing Chen
2021-12-21  6:50 ` [RFC PATCH v12 07/17] dlb: add low-level register reset operations Mike Ximing Chen
2021-12-21  6:50 ` Mike Ximing Chen [this message]
2021-12-21  6:50 ` [RFC PATCH v12 09/17] dlb: add queue create, reset, get-depth configfs interface Mike Ximing Chen
2021-12-21  6:50 ` [RFC PATCH v12 10/17] dlb: add register operations for queue management Mike Ximing Chen
2021-12-21  6:50 ` [RFC PATCH v12 11/17] dlb: add configfs interface to configure ports Mike Ximing Chen
2021-12-21  6:50 ` [RFC PATCH v12 12/17] dlb: add register operations for port management Mike Ximing Chen
2021-12-21  6:50 ` [RFC PATCH v12 13/17] dlb: add port mmap support Mike Ximing Chen
2021-12-21  6:50 ` [RFC PATCH v12 14/17] dlb: add start domain configfs attribute Mike Ximing Chen
2021-12-21  6:50 ` [RFC PATCH v12 15/17] dlb: add queue map, unmap, and pending unmap Mike Ximing Chen
2021-12-21  6:50 ` [RFC PATCH v12 16/17] dlb: add static queue map register operations Mike Ximing Chen
2021-12-21  6:50 ` [RFC PATCH v12 17/17] dlb: add basic sysfs interfaces Mike Ximing Chen
2021-12-21  7:20   ` Joe Perches
2021-12-21 23:18     ` Chen, Mike Ximing
2021-12-21  8:56   ` Greg KH
2021-12-21 14:07     ` Chen, Mike Ximing
2021-12-21 23:34   ` Stephen Hemminger
2021-12-22  4:21     ` Chen, Mike Ximing
2021-12-21  7:09 ` [RFC PATCH v12 00/17] dlb: introduce DLB device driver Greg KH
2021-12-21 14:03   ` Chen, Mike Ximing
2021-12-21 14:31     ` Greg KH
2021-12-21 18:44       ` Dan Williams
2021-12-21 19:57         ` Andrew Lunn
2021-12-22  8:01         ` Christoph Hellwig
2021-12-21  9:40 ` Andrew Lunn
2021-12-22  4:37   ` Chen, Mike Ximing

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20211221065047.290182-9-mike.ximing.chen@intel.com \
    --to=mike.ximing.chen@intel.com \
    --cc=arnd@arndb.de \
    --cc=dan.j.williams@intel.com \
    --cc=davem@davemloft.net \
    --cc=gregkh@linuxfoundation.org \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=pierre-louis.bossart@linux.intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®