Re: [PATCH] drivers: watchdog: Add ChromeOS EC watchdog

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Krzysztof,

Please find the answers below.

On Wed, Jan 17, 2024 at 4:27 PM Krzysztof Kozlowski <krzk@xxxxxxxxxx> wrote:
>
> On 17/01/2024 11:24, Lukasz Majczak wrote:
> > This adds EC-based watchdog support for ChromeOS
> > based devices equipped with embedded controller (EC).
> >
> > Signed-off-by: Lukasz Majczak <lma@xxxxxxxxxxxx>
> > ---
> >  MAINTAINERS                                   |   6 +
> >  drivers/mfd/cros_ec_dev.c                     |   9 +
> >  drivers/watchdog/Kconfig                      |  15 +
> >  drivers/watchdog/Makefile                     |   3 +
> >  drivers/watchdog/cros_ec_wdt.c                | 303 ++++++++++++++++++
> >  .../linux/platform_data/cros_ec_commands.h    |  78 ++---
> >  6 files changed, 370 insertions(+), 44 deletions(-)
> >  create mode 100644 drivers/watchdog/cros_ec_wdt.c
> >
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index 391bbb855cbe..55cd626a525f 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -4952,6 +4952,12 @@ R:     Sami Kyöstilä <skyostil@xxxxxxxxxxxx>
> >  S:   Maintained
> >  F:   drivers/platform/chrome/cros_hps_i2c.c
> >
> > +CHROMEOS EC WATCHDOG
> > +M:   Lukasz Majczak <lma@xxxxxxxxxxxx>
> > +L:   chrome-platform@xxxxxxxxxxxxxxx
> > +S:   Maintained
> > +F:   drivers/watchdog/cros_ec_wdt.c
> > +
> >  CHRONTEL CH7322 CEC DRIVER
> >  M:   Joe Tessler <jrt@xxxxxxxxxx>
> >  L:   linux-media@xxxxxxxxxxxxxxx
> > diff --git a/drivers/mfd/cros_ec_dev.c b/drivers/mfd/cros_ec_dev.c
> > index 79d393b602bf..60fe831cf30a 100644
> > --- a/drivers/mfd/cros_ec_dev.c
> > +++ b/drivers/mfd/cros_ec_dev.c
> > @@ -91,6 +91,10 @@ static const struct mfd_cell cros_usbpd_notify_cells[] = {
> >       { .name = "cros-usbpd-notify", },
> >  };
> >
> > +static const struct mfd_cell cros_ec_wdt_cells[] = {
> > +     { .name = "cros-ec-wdt-drv", }
> > +};
> > +
> >  static const struct cros_feature_to_cells cros_subdevices[] = {
> >       {
> >               .id             = EC_FEATURE_CEC,
> > @@ -107,6 +111,11 @@ static const struct cros_feature_to_cells cros_subdevices[] = {
> >               .mfd_cells      = cros_usbpd_charger_cells,
> >               .num_cells      = ARRAY_SIZE(cros_usbpd_charger_cells),
> >       },
> > +     {
> > +             .id             = EC_FEATURE_HANG_DETECT,
> > +             .mfd_cells      = cros_ec_wdt_cells,
> > +             .num_cells      = ARRAY_SIZE(cros_ec_wdt_cells),
> > +     },
> >  };
> >
> >  static const struct mfd_cell cros_ec_platform_cells[] = {
> > diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> > index 7d22051b15a2..1da4be661be8 100644
> > --- a/drivers/watchdog/Kconfig
> > +++ b/drivers/watchdog/Kconfig
> > @@ -2251,4 +2251,19 @@ config KEEMBAY_WATCHDOG
> >         To compile this driver as a module, choose M here: the
> >         module will be called keembay_wdt.
> >
> > +#
> > +# ChromeOS EC-based Watchdog
> > +#
>
> Drop comment, useless, copies what's below.

ACK

>
> > +
> > +config CROS_EC_WATCHDOG
> > +     tristate "ChromeOS EC-based watchdog driver"
> > +     select WATCHDOG_CORE
> > +     depends on CROS_EC
> > +     help
> > +       This is the watchdog driver for ChromeOS devices equipped with EC.
> > +       The EC watchdog - when enabled - expects to be kicked within a given
> > +       time (default set to 30 seconds) otherwise it will simple reboot
> > +       the AP. Priori to that it can also send an event (configurable timeout)
> > +       about upcoming reboot.
>
> Instead you could say what will be the name of the module.
>

ACK

> > +
> >  endif # WATCHDOG
> > diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
> > index 7cbc34514ec1..8295c209ddb0 100644
> > --- a/drivers/watchdog/Makefile
> > +++ b/drivers/watchdog/Makefile
> > @@ -234,3 +234,6 @@ obj-$(CONFIG_MENZ069_WATCHDOG) += menz69_wdt.o
> >  obj-$(CONFIG_RAVE_SP_WATCHDOG) += rave-sp-wdt.o
> >  obj-$(CONFIG_STPMIC1_WATCHDOG) += stpmic1_wdt.o
> >  obj-$(CONFIG_SL28CPLD_WATCHDOG) += sl28cpld_wdt.o
> > +
> > +# Cros EC watchdog
>
> Drop comment.
>
> Also, are you sure you placed it in appropriate place, not just at the
> end of both files?
>

ACK, I will find a better place for above (both in Makefile and
Kconfig) and will try to keep alphabetic order.

> > +obj-$(CONFIG_CROS_EC_WATCHDOG) += cros_ec_wdt.o
> > diff --git a/drivers/watchdog/cros_ec_wdt.c b/drivers/watchdog/cros_ec_wdt.c
> > new file mode 100644
> > index 000000000000..b461c0613269
> > --- /dev/null
> > +++ b/drivers/watchdog/cros_ec_wdt.c
> > @@ -0,0 +1,303 @@
> > +// SPDX-License-Identifier: GPL-2.0-or-later
> > +
> > +#include <linux/slab.h>
> > +#include <linux/err.h>
> > +#include <linux/of_device.h>
> > +#include <linux/kernel.h>
> > +#include <linux/module.h>
> > +#include <linux/platform_data/cros_ec_commands.h>
> > +#include <linux/platform_data/cros_ec_proto.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/watchdog.h>
> > +#include <linux/uaccess.h>
> > +
> > +#define CROS_EC_WATCHDOG_DEFAULT_TIME 30 /* seconds */
> > +
> > +#define DEV_NAME "cros-ec-wdt-dev"
>
> Drop unused defines.

ACK

>
> > +#define DRV_NAME "cros-ec-wdt-drv"
> > +
> > +static int cros_ec_wdt_ping(struct watchdog_device *wdd);
> > +static int cros_ec_wdt_start(struct watchdog_device *wdd);
> > +static int cros_ec_wdt_stop(struct watchdog_device *wdd);
> > +static int cros_ec_wdt_set_timeout(struct watchdog_device *wdd, unsigned int t);
> > +
>
> ...
>
> > +
> > +static int cros_ec_wdt_probe(struct platform_device *pdev)
> > +{
> > +     struct device *dev = &pdev->dev;
> > +     /* We need to get a reference to cros_ec_devices
> > +      * (provides communication layer) which is a parent of
> > +      * the cros-ec-dev (our parent)
> > +      */
> > +     struct cros_ec_device *cros_ec = dev_get_drvdata(dev->parent->parent);
> > +     int ret = 0;
> > +     uint32_t bootstatus;
> > +
> > +     if (!cros_ec) {
> > +             ret = -ENODEV;
> > +             dev_err_probe(dev, ret, "There is no coresponding EC device!");
>
> Syntax is return dev_err_probe
>

ACK

> > +             return ret;
> > +     }
> > +
> > +     cros_ec_wdd.parent = &pdev->dev;
> > +     wd_data.cros_ec = cros_ec;
> > +     wd_data.wdd = &cros_ec_wdd;
> > +     wd_data.start_on_resume = false;
> > +     wd_data.keepalive_on = false;
> > +     wd_data.wdd->timeout = CROS_EC_WATCHDOG_DEFAULT_TIME;
> > +
> > +     watchdog_stop_on_reboot(&cros_ec_wdd);
> > +     watchdog_stop_on_unregister(&cros_ec_wdd);
> > +     watchdog_set_drvdata(&cros_ec_wdd, &wd_data);
> > +     platform_set_drvdata(pdev, &wd_data);
> > +
> > +     /* Get current AP boot status */
> > +     ret = cros_ec_wdt_send_hang_detect(&wd_data, EC_HANG_DETECT_CMD_GET_STATUS, 0,
> > +                                        &bootstatus);
> > +     if (ret < 0) {
> > +             dev_err_probe(dev, ret, "Couldn't get AP boot status from EC");
>
> Syntax is return dev_err_probe

ACK

>
> > +             return ret;
> > +     }
> > +
> > +     /*
> > +      * If bootstatus is not EC_HANG_DETECT_AP_BOOT_NORMAL
> > +      * it mens EC has rebooted the AP due to watchdog timeout.
> > +      * Lets translate it to watchdog core status code.
> > +      */
> > +     if (bootstatus != EC_HANG_DETECT_AP_BOOT_NORMAL)
> > +             wd_data.wdd->bootstatus = WDIOF_CARDRESET;
> > +
> > +     ret = watchdog_register_device(&cros_ec_wdd);
> > +     if (ret < 0)
> > +             dev_err_probe(dev, ret, "Couldn't get AP boot status from EC");
>
> Syntax is return dev_err_probe
>

ACK

> > +
> > +     return ret;
>
> return 0
>

ACK

> > +}
> > +
> > +static int cros_ec_wdt_remove(struct platform_device *pdev)
> > +{
> > +     struct cros_ec_wdt_data *wd_data = platform_get_drvdata(pdev);
> > +
> > +     watchdog_unregister_device(wd_data->wdd);
> > +
> > +     return 0;
> > +}
> > +
> > +static void cros_ec_wdt_shutdown(struct platform_device *pdev)
> > +{
> > +     struct device *dev = &pdev->dev;
> > +     struct cros_ec_wdt_data *wd_data = platform_get_drvdata(pdev);
> > +     int ret;
> > +
> > +     /*
> > +      * Clean only bootstatus flag.
> > +      * EC wdt is are already stopped by watchdog framework.
> > +      */
> > +     ret = cros_ec_wdt_send_hang_detect(wd_data,
> > +                                        EC_HANG_DETECT_CMD_CLEAR_STATUS, 0, NULL);
> > +     if (ret < 0)
> > +             dev_err(dev, "%s failed (%d)", __func__, ret);
> > +
> > +     watchdog_unregister_device(wd_data->wdd);
> > +}
> > +
> > +static int __maybe_unused cros_ec_wdt_suspend(struct platform_device *pdev, pm_message_t state)
> > +{
> > +     struct device *dev = &pdev->dev;
> > +     struct cros_ec_wdt_data *wd_data = platform_get_drvdata(pdev);
> > +     int ret;
> > +
> > +     if (watchdog_active(wd_data->wdd)) {
> > +             ret = cros_ec_wdt_send_hang_detect(wd_data,
> > +                                                EC_HANG_DETECT_CMD_CANCEL, 0, NULL);
> > +             if (ret < 0)
> > +                     dev_err(dev, "%s failed (%d)", __func__, ret);
> > +             wd_data->start_on_resume = true;
> > +     }
> > +
> > +     return 0;
> > +}
> > +
> > +static int __maybe_unused cros_ec_wdt_resume(struct platform_device *pdev)
> > +{
> > +     struct device *dev = &pdev->dev;
> > +     struct cros_ec_wdt_data *wd_data = platform_get_drvdata(pdev);
> > +     int ret;
> > +
> > +     /* start_on_resume is only set if watchdog was active
> > +      * when device was going to sleep
> > +      */
> > +     if (wd_data->start_on_resume) {
> > +             /* On resume we just need to setup a EC watchdog the same way as
>
> Use comment style from Linux coding style.
>

ACK

> > +              * in cros_ec_wdt_start(). When userspace resumes from suspend
> > +              * the watchdog app should just start petting the watchdog again.
> > +              */
> > +             ret = cros_ec_wdt_start(wd_data->wdd);
> > +             if (ret < 0)
> > +                     dev_err(dev, "%s failed (%d)", __func__, ret);
>
> That's not really helpful. This applies everywhere. You have all over
> the place debugging prints with __func__. This is not useful pattern.
> Print something useful, not function name.
>

ACK, I will revisit the logs messages (both the meanings and log levels)

> > +
> > +             wd_data->start_on_resume = false;
> > +     }
> > +
> > +     return 0;
> > +}
> > +
> > +static struct platform_driver cros_ec_wdt_driver = {
> > +     .probe          = cros_ec_wdt_probe,
> > +     .remove         = cros_ec_wdt_remove,
> > +     .shutdown       = cros_ec_wdt_shutdown,
> > +     .suspend        = pm_ptr(cros_ec_wdt_suspend),
> > +     .resume         = pm_ptr(cros_ec_wdt_resume),
> > +     .driver         = {
> > +             .name   = DRV_NAME,
> > +     },
> > +};
> > +
> > +module_platform_driver(cros_ec_wdt_driver);
> > +
> > +MODULE_ALIAS("platform:" DRV_NAME);
>
> You should not need MODULE_ALIAS() in normal cases. If you need it,
> usually it means your device ID table is wrong (e.g. misses either
> entries or MODULE_DEVICE_TABLE()). MODULE_ALIAS() is not a substitute
> for incomplete ID table.
>
>

ACK, I will use MODULE_DEVICE_TABLE().

> > +MODULE_DESCRIPTION("Cros EC Watchdog Device Driver");
> > +MODULE_LICENSE("GPL");
> > diff --git a/include/linux/platform_data/cros_ec_commands.h b/include/linux/platform_data/cros_ec_commands.h
> > index 7dae17b62a4d..35a7a2d32819 100644
> > --- a/include/linux/platform_data/cros_ec_commands.h
> > +++ b/include/linux/platform_data/cros_ec_commands.h
> > @@ -3961,60 +3961,50 @@ struct ec_response_i2c_passthru {
> >  } __ec_align1;
> >
> >  /*****************************************************************************/
> > -/* Power button hang detect */
> > -
> > +/* AP hang detect */
>
> I don't understand how this change is related to the new driver. This
> entire hunk is confusing.
>

Yes, that updates the API and definition for embedded controller (EC).
It should go in the separate patch.

>
> Best regards,
> Krzysztof
>

Best regards,
Lukasz





[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux