diff mbox

[v2,11/11] misc: throttler: Add Chrome OS EC throttler

Message ID 20180607181214.30338-12-mka@chromium.org (mailing list archive)
State Not Applicable, archived
Headers show

Commit Message

Matthias Kaehlcke June 7, 2018, 6:12 p.m. UTC
The driver subscribes to throttling events from the Chrome OS
embedded controller and enables/disables system throttling based
on these events.

Signed-off-by: Matthias Kaehlcke <mka@chromium.org>
Reviewed-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
---
Changes in v2:
- added SPDX line instead of license boiler-plate
- use macro to avoid splitting line
- changed variable name for throttler from 'cte' to 'ce_thr'
- formatting fixes
- Kconfig: removed odd dashes around 'help'
- added 'Reviewed-by' tag

Note: I finally decided to keep 'Chrome OS' instead of changing it
to 'ChromeOS'. Both are currently used in the kernel, the latter is
currently more prevalent, however the official name is 'Chrome OS',
so there is no good reason to keep introducing the 'alternative' name.

 drivers/misc/throttler/Kconfig             |  14 +++
 drivers/misc/throttler/Makefile            |   1 +
 drivers/misc/throttler/cros_ec_throttler.c | 116 +++++++++++++++++++++
 3 files changed, 131 insertions(+)
 create mode 100644 drivers/misc/throttler/cros_ec_throttler.c

Comments

Enric Balletbo i Serra June 8, 2018, 2:09 p.m. UTC | #1
Hi Matthias,

On 07/06/18 20:12, Matthias Kaehlcke wrote:
> The driver subscribes to throttling events from the Chrome OS
> embedded controller and enables/disables system throttling based
> on these events.
> 
> Signed-off-by: Matthias Kaehlcke <mka@chromium.org>
> Reviewed-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
> ---
> Changes in v2:
> - added SPDX line instead of license boiler-plate
> - use macro to avoid splitting line
> - changed variable name for throttler from 'cte' to 'ce_thr'
> - formatting fixes
> - Kconfig: removed odd dashes around 'help'
> - added 'Reviewed-by' tag
> 
> Note: I finally decided to keep 'Chrome OS' instead of changing it
> to 'ChromeOS'. Both are currently used in the kernel, the latter is
> currently more prevalent, however the official name is 'Chrome OS',
> so there is no good reason to keep introducing the 'alternative' name.
> 

I am pretty sure that somebody from Google told me the contrary, so

¯\_(ツ)_/¯

Anyway, you will probably know better than me :)

>  drivers/misc/throttler/Kconfig             |  14 +++
>  drivers/misc/throttler/Makefile            |   1 +
>  drivers/misc/throttler/cros_ec_throttler.c | 116 +++++++++++++++++++++
>  3 files changed, 131 insertions(+)
>  create mode 100644 drivers/misc/throttler/cros_ec_throttler.c
> 
> diff --git a/drivers/misc/throttler/Kconfig b/drivers/misc/throttler/Kconfig
> index e561f1df5085..da6fb70b96d9 100644
> --- a/drivers/misc/throttler/Kconfig
> +++ b/drivers/misc/throttler/Kconfig
> @@ -12,3 +12,17 @@ menuconfig THROTTLER
>  	  Note that you also need a event monitor module usually called
>  	  *_throttler.
>  
> +if THROTTLER
> +
> +config CROS_EC_THROTTLER
> +	tristate "Throttler event monitor for the Chrome OS Embedded Controller"
> +	depends on MFD_CROS_EC
> +	help
> +	  This driver adds support to throttle the system in reaction to
> +	  Chrome OS EC events.
> +
> +	  To compile this driver as a module, choose M here: the
> +	  module will be called cros_ec_throttler.
> +
> +endif # THROTTLER
> +
> diff --git a/drivers/misc/throttler/Makefile b/drivers/misc/throttler/Makefile
> index c8d920cee315..d9b2a77dabc9 100644
> --- a/drivers/misc/throttler/Makefile
> +++ b/drivers/misc/throttler/Makefile
> @@ -1 +1,2 @@
>  obj-$(CONFIG_THROTTLER)		+= core.o
> +obj-$(CONFIG_CROS_EC_THROTTLER)	+= cros_ec_throttler.o
> diff --git a/drivers/misc/throttler/cros_ec_throttler.c b/drivers/misc/throttler/cros_ec_throttler.c
> new file mode 100644
> index 000000000000..432135c55600
> --- /dev/null
> +++ b/drivers/misc/throttler/cros_ec_throttler.c
> @@ -0,0 +1,116 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Driver for throttling triggered by events from the Chrome OS Embedded
> + * Controller.
> + *
> + * Copyright (C) 2018 Google, Inc.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/mfd/cros_ec.h>
> +#include <linux/module.h>
> +#include <linux/notifier.h>
> +#include <linux/of.h>
> +#include <linux/of_platform.h>
> +#include <linux/platform_device.h>
> +#include <linux/throttler.h>
> +
> +#define nb_to_ce_thr(nb) container_of(nb, struct cros_ec_throttler, nb)
> +
> +struct cros_ec_throttler {
> +	struct cros_ec_device *ec;
> +	struct throttler *throttler;
> +	struct notifier_block nb;
> +};
> +
> +static int cros_ec_throttler_event(struct notifier_block *nb,
> +	unsigned long queued_during_suspend, void *_notify)
> +{
> +	struct cros_ec_throttler *ce_thr = nb_to_ce_thr(nb);
> +	u32 host_event;
> +
> +	host_event = cros_ec_get_host_event(ce_thr->ec);
> +	if (host_event & EC_HOST_EVENT_MASK(EC_HOST_EVENT_THROTTLE_START)) {
> +		throttler_set_level(ce_thr->throttler, 1);
> +
> +		return NOTIFY_OK;
> +	} else if (host_event &
> +		   EC_HOST_EVENT_MASK(EC_HOST_EVENT_THROTTLE_STOP)) {
> +		throttler_set_level(ce_thr->throttler, 0);
> +
> +		return NOTIFY_OK;
> +	}
> +
> +	return NOTIFY_DONE;
> +}
> +
> +static int cros_ec_throttler_probe(struct platform_device *pdev)
> +{
> +	struct cros_ec_throttler *ce_thr;
> +	struct device *dev = &pdev->dev;
> +	struct device_node *np = pdev->dev.of_node;
> +	int ret;
> +
> +	if (!np) {
> +		/* should never happen */
> +		return -EINVAL;
> +	}
> +
> +	ce_thr = devm_kzalloc(dev, sizeof(*ce_thr), GFP_KERNEL);
> +	if (!ce_thr)
> +		return -ENOMEM;
> +
> +	ce_thr->ec = dev_get_drvdata(pdev->dev.parent);
> +
> +	ce_thr->throttler = throttler_setup(dev);
> +	if (IS_ERR(ce_thr->throttler))
> +		return PTR_ERR(ce_thr->throttler);
> +
> +	dev_set_drvdata(dev, ce_thr);
> +
> +	ce_thr->nb.notifier_call = cros_ec_throttler_event;
> +	ret = blocking_notifier_chain_register(&ce_thr->ec->event_notifier,
> +					       &ce_thr->nb);
> +	if (ret < 0) {
> +		dev_err(dev, "failed to register notifier\n");
> +		throttler_teardown(ce_thr->throttler);
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int cros_ec_throttler_remove(struct platform_device *pdev)
> +{
> +	struct cros_ec_throttler *ce_thr = platform_get_drvdata(pdev);
> +
> +	blocking_notifier_chain_unregister(&ce_thr->ec->event_notifier,
> +					   &ce_thr->nb);
> +
> +	throttler_teardown(ce_thr->throttler);
> +
> +	return 0;
> +}
> +
> +#ifdef CONFIG_OF
> +static const struct of_device_id cros_ec_throttler_of_match[] = {
> +	{ .compatible = "google,cros-ec-throttler" },
> +	{ /* sentinel */ }
> +};
> +MODULE_DEVICE_TABLE(of, cros_ec_throttler_of_match);
> +#endif /* CONFIG_OF */
> +
> +static struct platform_driver cros_ec_throttler_driver = {
> +	.driver = {
> +		.name = "cros-ec-throttler",
> +		.of_match_table = of_match_ptr(cros_ec_throttler_of_match),
> +	},
> +	.probe		= cros_ec_throttler_probe,
> +	.remove		= cros_ec_throttler_remove,
> +};
> +
> +module_platform_driver(cros_ec_throttler_driver);
> +
> +MODULE_LICENSE("GPL");

Something that I learnt recently. To match the SPDX-license tag you should set
this to "GPL v2" [1]

 *	"GPL"				[GNU Public License v2 or later]
 *	"GPL v2"			[GNU Public License v2]

[1] https://elixir.bootlin.com/linux/v4.17/source/include/linux/module.h#L172

> +MODULE_AUTHOR("Matthias Kaehlcke <mka@chromium.org>");
> +MODULE_DESCRIPTION("Chrome OS EC Throttler");
> 

Best regards,
 Enric
Matthias Kaehlcke June 8, 2018, 3:56 p.m. UTC | #2
Hi Enric,

On Fri, Jun 08, 2018 at 04:09:18PM +0200, Enric Balletbo i Serra wrote:

> On 07/06/18 20:12, Matthias Kaehlcke wrote:
> > The driver subscribes to throttling events from the Chrome OS
> > embedded controller and enables/disables system throttling based
> > on these events.
> > 
> > Signed-off-by: Matthias Kaehlcke <mka@chromium.org>
> > Reviewed-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
> > ---
> > Changes in v2:
> > - added SPDX line instead of license boiler-plate
> > - use macro to avoid splitting line
> > - changed variable name for throttler from 'cte' to 'ce_thr'
> > - formatting fixes
> > - Kconfig: removed odd dashes around 'help'
> > - added 'Reviewed-by' tag
> > 
> > Note: I finally decided to keep 'Chrome OS' instead of changing it
> > to 'ChromeOS'. Both are currently used in the kernel, the latter is
> > currently more prevalent, however the official name is 'Chrome OS',
> > so there is no good reason to keep introducing the 'alternative' name.
> > 
> 
> I am pretty sure that somebody from Google told me the contrary, so
> 
> ¯\_(ツ)_/¯
> 
> Anyway, you will probably know better than me :)

The different names in the kernel code indicate that even folks at
Google disagree on this ;-) The name might have evolved over time.

chrome://chrome on a Chromebook names it 'Chrome OS', as do official
pages like https://www.google.com/chromebook/ and
https://www.chromium.org/chromium-os so I think it is better to use
this name.

> > +MODULE_LICENSE("GPL");
> 
> Something that I learnt recently. To match the SPDX-license tag you should set
> this to "GPL v2" [1]
> 
>  *	"GPL"				[GNU Public License v2 or later]
>  *	"GPL v2"			[GNU Public License v2]
> 
> [1] https://elixir.bootlin.com/linux/v4.17/source/include/linux/module.h#L172

Will update in the next revision

Thanks!

Matthias
diff mbox

Patch

diff --git a/drivers/misc/throttler/Kconfig b/drivers/misc/throttler/Kconfig
index e561f1df5085..da6fb70b96d9 100644
--- a/drivers/misc/throttler/Kconfig
+++ b/drivers/misc/throttler/Kconfig
@@ -12,3 +12,17 @@  menuconfig THROTTLER
 	  Note that you also need a event monitor module usually called
 	  *_throttler.
 
+if THROTTLER
+
+config CROS_EC_THROTTLER
+	tristate "Throttler event monitor for the Chrome OS Embedded Controller"
+	depends on MFD_CROS_EC
+	help
+	  This driver adds support to throttle the system in reaction to
+	  Chrome OS EC events.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called cros_ec_throttler.
+
+endif # THROTTLER
+
diff --git a/drivers/misc/throttler/Makefile b/drivers/misc/throttler/Makefile
index c8d920cee315..d9b2a77dabc9 100644
--- a/drivers/misc/throttler/Makefile
+++ b/drivers/misc/throttler/Makefile
@@ -1 +1,2 @@ 
 obj-$(CONFIG_THROTTLER)		+= core.o
+obj-$(CONFIG_CROS_EC_THROTTLER)	+= cros_ec_throttler.o
diff --git a/drivers/misc/throttler/cros_ec_throttler.c b/drivers/misc/throttler/cros_ec_throttler.c
new file mode 100644
index 000000000000..432135c55600
--- /dev/null
+++ b/drivers/misc/throttler/cros_ec_throttler.c
@@ -0,0 +1,116 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver for throttling triggered by events from the Chrome OS Embedded
+ * Controller.
+ *
+ * Copyright (C) 2018 Google, Inc.
+ */
+
+#include <linux/kernel.h>
+#include <linux/mfd/cros_ec.h>
+#include <linux/module.h>
+#include <linux/notifier.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/throttler.h>
+
+#define nb_to_ce_thr(nb) container_of(nb, struct cros_ec_throttler, nb)
+
+struct cros_ec_throttler {
+	struct cros_ec_device *ec;
+	struct throttler *throttler;
+	struct notifier_block nb;
+};
+
+static int cros_ec_throttler_event(struct notifier_block *nb,
+	unsigned long queued_during_suspend, void *_notify)
+{
+	struct cros_ec_throttler *ce_thr = nb_to_ce_thr(nb);
+	u32 host_event;
+
+	host_event = cros_ec_get_host_event(ce_thr->ec);
+	if (host_event & EC_HOST_EVENT_MASK(EC_HOST_EVENT_THROTTLE_START)) {
+		throttler_set_level(ce_thr->throttler, 1);
+
+		return NOTIFY_OK;
+	} else if (host_event &
+		   EC_HOST_EVENT_MASK(EC_HOST_EVENT_THROTTLE_STOP)) {
+		throttler_set_level(ce_thr->throttler, 0);
+
+		return NOTIFY_OK;
+	}
+
+	return NOTIFY_DONE;
+}
+
+static int cros_ec_throttler_probe(struct platform_device *pdev)
+{
+	struct cros_ec_throttler *ce_thr;
+	struct device *dev = &pdev->dev;
+	struct device_node *np = pdev->dev.of_node;
+	int ret;
+
+	if (!np) {
+		/* should never happen */
+		return -EINVAL;
+	}
+
+	ce_thr = devm_kzalloc(dev, sizeof(*ce_thr), GFP_KERNEL);
+	if (!ce_thr)
+		return -ENOMEM;
+
+	ce_thr->ec = dev_get_drvdata(pdev->dev.parent);
+
+	ce_thr->throttler = throttler_setup(dev);
+	if (IS_ERR(ce_thr->throttler))
+		return PTR_ERR(ce_thr->throttler);
+
+	dev_set_drvdata(dev, ce_thr);
+
+	ce_thr->nb.notifier_call = cros_ec_throttler_event;
+	ret = blocking_notifier_chain_register(&ce_thr->ec->event_notifier,
+					       &ce_thr->nb);
+	if (ret < 0) {
+		dev_err(dev, "failed to register notifier\n");
+		throttler_teardown(ce_thr->throttler);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int cros_ec_throttler_remove(struct platform_device *pdev)
+{
+	struct cros_ec_throttler *ce_thr = platform_get_drvdata(pdev);
+
+	blocking_notifier_chain_unregister(&ce_thr->ec->event_notifier,
+					   &ce_thr->nb);
+
+	throttler_teardown(ce_thr->throttler);
+
+	return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id cros_ec_throttler_of_match[] = {
+	{ .compatible = "google,cros-ec-throttler" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, cros_ec_throttler_of_match);
+#endif /* CONFIG_OF */
+
+static struct platform_driver cros_ec_throttler_driver = {
+	.driver = {
+		.name = "cros-ec-throttler",
+		.of_match_table = of_match_ptr(cros_ec_throttler_of_match),
+	},
+	.probe		= cros_ec_throttler_probe,
+	.remove		= cros_ec_throttler_remove,
+};
+
+module_platform_driver(cros_ec_throttler_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Matthias Kaehlcke <mka@chromium.org>");
+MODULE_DESCRIPTION("Chrome OS EC Throttler");