diff mbox series

[v6,6/8] usb: typec: cros_ec_ucsi: Add netlink

Message ID 20240910101527.603452-7-ukaszb@chromium.org (mailing list archive)
State New
Headers show
Series usb: typec: Implement UCSI driver for ChromeOS | expand

Commit Message

Łukasz Bartosik Sept. 10, 2024, 10:15 a.m. UTC
Add netlink to ChromeOS UCSI driver to allow forwarding
of UCSI messages to userspace for debugging and testing
purposes.

Signed-off-by: Łukasz Bartosik <ukaszb@chromium.org>
---
 MAINTAINERS                                   |  4 +-
 drivers/usb/typec/ucsi/Makefile               |  4 +-
 .../{cros_ec_ucsi.c => cros_ec_ucsi_main.c}   | 66 +++++++++++++-
 drivers/usb/typec/ucsi/cros_ec_ucsi_nl.c      | 87 +++++++++++++++++++
 drivers/usb/typec/ucsi/cros_ec_ucsi_nl.h      | 52 +++++++++++
 5 files changed, 209 insertions(+), 4 deletions(-)
 rename drivers/usb/typec/ucsi/{cros_ec_ucsi.c => cros_ec_ucsi_main.c} (79%)
 create mode 100644 drivers/usb/typec/ucsi/cros_ec_ucsi_nl.c
 create mode 100644 drivers/usb/typec/ucsi/cros_ec_ucsi_nl.h

Comments

kernel test robot Sept. 11, 2024, 2 p.m. UTC | #1
Hi Łukasz,

kernel test robot noticed the following build warnings:

[auto build test WARNING on usb/usb-testing]
[also build test WARNING on usb/usb-next usb/usb-linus lee-mfd/for-mfd-next driver-core/driver-core-testing driver-core/driver-core-next driver-core/driver-core-linus linus/master v6.11-rc7 next-20240910]
[cannot apply to lee-mfd/for-mfd-fixes]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/ukasz-Bartosik/platform-chrome-Update-ChromeOS-EC-header-for-UCSI/20240910-182729
base:   https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git usb-testing
patch link:    https://lore.kernel.org/r/20240910101527.603452-7-ukaszb%40chromium.org
patch subject: [PATCH v6 6/8] usb: typec: cros_ec_ucsi: Add netlink
config: x86_64-randconfig-121-20240911 (https://download.01.org/0day-ci/archive/20240911/202409112121.GHL72j84-lkp@intel.com/config)
compiler: gcc-12 (Debian 12.2.0-14) 12.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240911/202409112121.GHL72j84-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202409112121.GHL72j84-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
>> drivers/usb/typec/ucsi/cros_ec_ucsi_main.c:178:24: sparse: sparse: symbol 'cros_ucsi_ops' was not declared. Should it be static?

vim +/cros_ucsi_ops +178 drivers/usb/typec/ucsi/cros_ec_ucsi_main.c

ef8d61204d9db5 drivers/usb/typec/ucsi/cros_ec_ucsi.c Pavan Holla 2024-09-10  177  
ef8d61204d9db5 drivers/usb/typec/ucsi/cros_ec_ucsi.c Pavan Holla 2024-09-10 @178  struct ucsi_operations cros_ucsi_ops = {
ef8d61204d9db5 drivers/usb/typec/ucsi/cros_ec_ucsi.c Pavan Holla 2024-09-10  179  	.read_version = cros_ucsi_read_version,
ef8d61204d9db5 drivers/usb/typec/ucsi/cros_ec_ucsi.c Pavan Holla 2024-09-10  180  	.read_cci = cros_ucsi_read_cci,
ef8d61204d9db5 drivers/usb/typec/ucsi/cros_ec_ucsi.c Pavan Holla 2024-09-10  181  	.read_message_in = cros_ucsi_read_message_in,
ef8d61204d9db5 drivers/usb/typec/ucsi/cros_ec_ucsi.c Pavan Holla 2024-09-10  182  	.async_control = cros_ucsi_async_control,
ef8d61204d9db5 drivers/usb/typec/ucsi/cros_ec_ucsi.c Pavan Holla 2024-09-10  183  	.sync_control = cros_ucsi_sync_control,
ef8d61204d9db5 drivers/usb/typec/ucsi/cros_ec_ucsi.c Pavan Holla 2024-09-10  184  };
ef8d61204d9db5 drivers/usb/typec/ucsi/cros_ec_ucsi.c Pavan Holla 2024-09-10  185
Heikki Krogerus Sept. 11, 2024, 2:07 p.m. UTC | #2
Hi,

On Tue, Sep 10, 2024 at 10:15:25AM +0000, Łukasz Bartosik wrote:
> Add netlink to ChromeOS UCSI driver to allow forwarding
> of UCSI messages to userspace for debugging and testing
> purposes.

Why does this need to be cros_ec specific?

> Signed-off-by: Łukasz Bartosik <ukaszb@chromium.org>
> ---
>  MAINTAINERS                                   |  4 +-
>  drivers/usb/typec/ucsi/Makefile               |  4 +-
>  .../{cros_ec_ucsi.c => cros_ec_ucsi_main.c}   | 66 +++++++++++++-
>  drivers/usb/typec/ucsi/cros_ec_ucsi_nl.c      | 87 +++++++++++++++++++
>  drivers/usb/typec/ucsi/cros_ec_ucsi_nl.h      | 52 +++++++++++
>  5 files changed, 209 insertions(+), 4 deletions(-)
>  rename drivers/usb/typec/ucsi/{cros_ec_ucsi.c => cros_ec_ucsi_main.c} (79%)
>  create mode 100644 drivers/usb/typec/ucsi/cros_ec_ucsi_nl.c
>  create mode 100644 drivers/usb/typec/ucsi/cros_ec_ucsi_nl.h
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index d084f32208f0..2afb406a24ce 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -5305,7 +5305,9 @@ M:	Abhishek Pandit-Subedi <abhishekpandit@chromium.org>
>  M:	Łukasz Bartosik <ukaszb@chromium.org>
>  L:	chrome-platform@lists.linux.dev
>  S:	Maintained
> -F:	drivers/usb/typec/ucsi/cros_ec_ucsi.c
> +F:	drivers/usb/typec/ucsi/cros_ec_ucsi_main.c
> +F:	drivers/usb/typec/ucsi/cros_ec_ucsi_nl.c
> +F:	drivers/usb/typec/ucsi/cros_ec_ucsi_nl.h
>  F:	drivers/usb/typec/ucsi/cros_ec_ucsi_trace.h
>  
>  CHRONTEL CH7322 CEC DRIVER
> diff --git a/drivers/usb/typec/ucsi/Makefile b/drivers/usb/typec/ucsi/Makefile
> index be98a879104d..82d960394c39 100644
> --- a/drivers/usb/typec/ucsi/Makefile
> +++ b/drivers/usb/typec/ucsi/Makefile
> @@ -21,5 +21,7 @@ obj-$(CONFIG_UCSI_ACPI)			+= ucsi_acpi.o
>  obj-$(CONFIG_UCSI_CCG)			+= ucsi_ccg.o
>  obj-$(CONFIG_UCSI_STM32G0)		+= ucsi_stm32g0.o
>  obj-$(CONFIG_UCSI_PMIC_GLINK)		+= ucsi_glink.o
> -obj-$(CONFIG_CROS_EC_UCSI)		+= cros_ec_ucsi.o
>  obj-$(CONFIG_UCSI_LENOVO_YOGA_C630)	+= ucsi_yoga_c630.o
> +
> +obj-$(CONFIG_CROS_EC_UCSI)		+= cros_ec_ucsi.o
> +cros_ec_ucsi-y				:= cros_ec_ucsi_main.o cros_ec_ucsi_nl.o
> diff --git a/drivers/usb/typec/ucsi/cros_ec_ucsi.c b/drivers/usb/typec/ucsi/cros_ec_ucsi_main.c
> similarity index 79%
> rename from drivers/usb/typec/ucsi/cros_ec_ucsi.c
> rename to drivers/usb/typec/ucsi/cros_ec_ucsi_main.c
> index 70185616ec86..008b61921278 100644
> --- a/drivers/usb/typec/ucsi/cros_ec_ucsi.c
> +++ b/drivers/usb/typec/ucsi/cros_ec_ucsi_main.c
> @@ -19,6 +19,7 @@
>  #define CREATE_TRACE_POINTS
>  #include "ucsi.h"
>  #include "cros_ec_ucsi_trace.h"
> +#include "cros_ec_ucsi_nl.h"
>  
>  /*
>   * Maximum size in bytes of a UCSI message between AP and EC
> @@ -43,6 +44,43 @@ struct cros_ucsi_data {
>  	unsigned long flags;
>  };
>  
> +/*
> + * When set to true the cros_ec_ucsi driver will forward all UCSI messages
> + * exchanged between OPM <-> PPM to userspace through netlink
> + */
> +static bool is_ap_sniffer_en;
> +
> +static ssize_t enable_ap_sniffer_show(struct device *dev,
> +				      struct device_attribute *attr,
> +				      char *buf)
> +{
> +	return sprintf(buf, "%d\n", is_ap_sniffer_en);
> +}
> +
> +static ssize_t enable_ap_sniffer_store(struct device *dev,
> +				       struct device_attribute *attr,
> +				       const char *buf, size_t count)
> +{
> +	u8 value;
> +
> +	if (kstrtou8(buf, 0, &value))
> +		return -EINVAL;
> +
> +	is_ap_sniffer_en = value ? 1 : 0;
> +	return count;
> +}
> +
> +static DEVICE_ATTR_RW(enable_ap_sniffer);
> +
> +static struct attribute *cros_ec_ucsi_attrs[] = {
> +	&dev_attr_enable_ap_sniffer.attr,
> +	NULL
> +};
> +
> +static const struct attribute_group cros_ec_ucsi_attrs_grp = {
> +	.attrs = cros_ec_ucsi_attrs,
> +};

Undocumented sysfs entry.

>  static int cros_ucsi_read(struct ucsi *ucsi, unsigned int offset, void *val,
>  			  size_t val_len)
>  {
> @@ -65,6 +103,9 @@ static int cros_ucsi_read(struct ucsi *ucsi, unsigned int offset, void *val,
>  		return ret;
>  	}
>  
> +	if (is_ap_sniffer_en)
> +		nl_cros_ec_bcast_msg(NL_CROS_EC_TO_PPM, NL_CROS_EC_RD, offset,
> +				     val, val_len);
>  	trace_cros_ec_opm_to_ppm_rd(offset, val, val_len);
>  	return 0;
>  }
> @@ -101,6 +142,9 @@ static int cros_ucsi_async_control(struct ucsi *ucsi, u64 cmd)
>  		return ret;
>  	}
>  
> +	if (is_ap_sniffer_en)
> +		nl_cros_ec_bcast_msg(NL_CROS_EC_TO_PPM, NL_CROS_EC_WR,
> +				     req->offset, (u8 *) &cmd, sizeof(cmd));
>  	trace_cros_ec_opm_to_ppm_wr(req->offset, &cmd, sizeof(cmd));
>  	return 0;
>  }
> @@ -144,6 +188,8 @@ static void cros_ucsi_work(struct work_struct *work)
>  	struct cros_ucsi_data *udata = container_of(work, struct cros_ucsi_data, work);
>  	u32 cci;
>  
> +	if (is_ap_sniffer_en)
> +		nl_cros_ec_bcast_msg(NL_CROS_EC_TO_OPM, 0, 0, NULL, 0);
>  	trace_cros_ec_ppm_to_opm(0);
>  
>  	if (cros_ucsi_read_cci(udata->ucsi, &cci))
> @@ -229,13 +275,29 @@ static int cros_ucsi_probe(struct platform_device *pdev)
>  		return ret;
>  	}
>  
> +	ret = nl_cros_ec_register();
> +	if (ret) {
> +		dev_err(dev, "failed to register netlink: error=%d", ret);
> +		cros_ucsi_destroy(udata);
> +		return ret;
> +	}
> +
> +	ret = sysfs_create_group(&dev->kobj, &cros_ec_ucsi_attrs_grp);
> +	if (ret) {
> +		dev_err(dev, "failed to register sysfs group: error=%d", ret);
> +		cros_ucsi_destroy(udata);
> +		return ret;
> +	}
> +
>  	return 0;
>  }
>  
> -static void cros_ucsi_remove(struct platform_device *dev)
> +static void cros_ucsi_remove(struct platform_device *pdev)
>  {
> -	struct cros_ucsi_data *udata = platform_get_drvdata(dev);
> +	struct cros_ucsi_data *udata = platform_get_drvdata(pdev);

Please merge that change into the patch 3/8.

> +	sysfs_remove_group(&pdev->dev.kobj, &cros_ec_ucsi_attrs_grp);
> +	nl_cros_ec_unregister();
>  	ucsi_unregister(udata->ucsi);
>  	cros_ucsi_destroy(udata);
>  }

thanks,
Łukasz Bartosik Sept. 14, 2024, 10:08 p.m. UTC | #3
On Wed, Sep 11, 2024 at 4:09 PM Heikki Krogerus
<heikki.krogerus@linux.intel.com> wrote:
>
> Hi,
>
> On Tue, Sep 10, 2024 at 10:15:25AM +0000, Łukasz Bartosik wrote:
> > Add netlink to ChromeOS UCSI driver to allow forwarding
> > of UCSI messages to userspace for debugging and testing
> > purposes.
>
> Why does this need to be cros_ec specific?
>

You're right. Netlink does not have to be cros_ec_ucsi specific.
Would you like to have netlink in typec_ucsi ?

> > Signed-off-by: Łukasz Bartosik <ukaszb@chromium.org>
> > ---
> >  MAINTAINERS                                   |  4 +-
> >  drivers/usb/typec/ucsi/Makefile               |  4 +-
> >  .../{cros_ec_ucsi.c => cros_ec_ucsi_main.c}   | 66 +++++++++++++-
> >  drivers/usb/typec/ucsi/cros_ec_ucsi_nl.c      | 87 +++++++++++++++++++
> >  drivers/usb/typec/ucsi/cros_ec_ucsi_nl.h      | 52 +++++++++++
> >  5 files changed, 209 insertions(+), 4 deletions(-)
> >  rename drivers/usb/typec/ucsi/{cros_ec_ucsi.c => cros_ec_ucsi_main.c} (79%)
> >  create mode 100644 drivers/usb/typec/ucsi/cros_ec_ucsi_nl.c
> >  create mode 100644 drivers/usb/typec/ucsi/cros_ec_ucsi_nl.h
> >
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index d084f32208f0..2afb406a24ce 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -5305,7 +5305,9 @@ M:      Abhishek Pandit-Subedi <abhishekpandit@chromium.org>
> >  M:   Łukasz Bartosik <ukaszb@chromium.org>
> >  L:   chrome-platform@lists.linux.dev
> >  S:   Maintained
> > -F:   drivers/usb/typec/ucsi/cros_ec_ucsi.c
> > +F:   drivers/usb/typec/ucsi/cros_ec_ucsi_main.c
> > +F:   drivers/usb/typec/ucsi/cros_ec_ucsi_nl.c
> > +F:   drivers/usb/typec/ucsi/cros_ec_ucsi_nl.h
> >  F:   drivers/usb/typec/ucsi/cros_ec_ucsi_trace.h
> >
> >  CHRONTEL CH7322 CEC DRIVER
> > diff --git a/drivers/usb/typec/ucsi/Makefile b/drivers/usb/typec/ucsi/Makefile
> > index be98a879104d..82d960394c39 100644
> > --- a/drivers/usb/typec/ucsi/Makefile
> > +++ b/drivers/usb/typec/ucsi/Makefile
> > @@ -21,5 +21,7 @@ obj-$(CONFIG_UCSI_ACPI)                     += ucsi_acpi.o
> >  obj-$(CONFIG_UCSI_CCG)                       += ucsi_ccg.o
> >  obj-$(CONFIG_UCSI_STM32G0)           += ucsi_stm32g0.o
> >  obj-$(CONFIG_UCSI_PMIC_GLINK)                += ucsi_glink.o
> > -obj-$(CONFIG_CROS_EC_UCSI)           += cros_ec_ucsi.o
> >  obj-$(CONFIG_UCSI_LENOVO_YOGA_C630)  += ucsi_yoga_c630.o
> > +
> > +obj-$(CONFIG_CROS_EC_UCSI)           += cros_ec_ucsi.o
> > +cros_ec_ucsi-y                               := cros_ec_ucsi_main.o cros_ec_ucsi_nl.o
> > diff --git a/drivers/usb/typec/ucsi/cros_ec_ucsi.c b/drivers/usb/typec/ucsi/cros_ec_ucsi_main.c
> > similarity index 79%
> > rename from drivers/usb/typec/ucsi/cros_ec_ucsi.c
> > rename to drivers/usb/typec/ucsi/cros_ec_ucsi_main.c
> > index 70185616ec86..008b61921278 100644
> > --- a/drivers/usb/typec/ucsi/cros_ec_ucsi.c
> > +++ b/drivers/usb/typec/ucsi/cros_ec_ucsi_main.c
> > @@ -19,6 +19,7 @@
> >  #define CREATE_TRACE_POINTS
> >  #include "ucsi.h"
> >  #include "cros_ec_ucsi_trace.h"
> > +#include "cros_ec_ucsi_nl.h"
> >
> >  /*
> >   * Maximum size in bytes of a UCSI message between AP and EC
> > @@ -43,6 +44,43 @@ struct cros_ucsi_data {
> >       unsigned long flags;
> >  };
> >
> > +/*
> > + * When set to true the cros_ec_ucsi driver will forward all UCSI messages
> > + * exchanged between OPM <-> PPM to userspace through netlink
> > + */
> > +static bool is_ap_sniffer_en;
> > +
> > +static ssize_t enable_ap_sniffer_show(struct device *dev,
> > +                                   struct device_attribute *attr,
> > +                                   char *buf)
> > +{
> > +     return sprintf(buf, "%d\n", is_ap_sniffer_en);
> > +}
> > +
> > +static ssize_t enable_ap_sniffer_store(struct device *dev,
> > +                                    struct device_attribute *attr,
> > +                                    const char *buf, size_t count)
> > +{
> > +     u8 value;
> > +
> > +     if (kstrtou8(buf, 0, &value))
> > +             return -EINVAL;
> > +
> > +     is_ap_sniffer_en = value ? 1 : 0;
> > +     return count;
> > +}
> > +
> > +static DEVICE_ATTR_RW(enable_ap_sniffer);
> > +
> > +static struct attribute *cros_ec_ucsi_attrs[] = {
> > +     &dev_attr_enable_ap_sniffer.attr,
> > +     NULL
> > +};
> > +
> > +static const struct attribute_group cros_ec_ucsi_attrs_grp = {
> > +     .attrs = cros_ec_ucsi_attrs,
> > +};
>
> Undocumented sysfs entry.
>

I will document the new sysfs entry.

> >  static int cros_ucsi_read(struct ucsi *ucsi, unsigned int offset, void *val,
> >                         size_t val_len)
> >  {
> > @@ -65,6 +103,9 @@ static int cros_ucsi_read(struct ucsi *ucsi, unsigned int offset, void *val,
> >               return ret;
> >       }
> >
> > +     if (is_ap_sniffer_en)
> > +             nl_cros_ec_bcast_msg(NL_CROS_EC_TO_PPM, NL_CROS_EC_RD, offset,
> > +                                  val, val_len);
> >       trace_cros_ec_opm_to_ppm_rd(offset, val, val_len);
> >       return 0;
> >  }
> > @@ -101,6 +142,9 @@ static int cros_ucsi_async_control(struct ucsi *ucsi, u64 cmd)
> >               return ret;
> >       }
> >
> > +     if (is_ap_sniffer_en)
> > +             nl_cros_ec_bcast_msg(NL_CROS_EC_TO_PPM, NL_CROS_EC_WR,
> > +                                  req->offset, (u8 *) &cmd, sizeof(cmd));
> >       trace_cros_ec_opm_to_ppm_wr(req->offset, &cmd, sizeof(cmd));
> >       return 0;
> >  }
> > @@ -144,6 +188,8 @@ static void cros_ucsi_work(struct work_struct *work)
> >       struct cros_ucsi_data *udata = container_of(work, struct cros_ucsi_data, work);
> >       u32 cci;
> >
> > +     if (is_ap_sniffer_en)
> > +             nl_cros_ec_bcast_msg(NL_CROS_EC_TO_OPM, 0, 0, NULL, 0);
> >       trace_cros_ec_ppm_to_opm(0);
> >
> >       if (cros_ucsi_read_cci(udata->ucsi, &cci))
> > @@ -229,13 +275,29 @@ static int cros_ucsi_probe(struct platform_device *pdev)
> >               return ret;
> >       }
> >
> > +     ret = nl_cros_ec_register();
> > +     if (ret) {
> > +             dev_err(dev, "failed to register netlink: error=%d", ret);
> > +             cros_ucsi_destroy(udata);
> > +             return ret;
> > +     }
> > +
> > +     ret = sysfs_create_group(&dev->kobj, &cros_ec_ucsi_attrs_grp);
> > +     if (ret) {
> > +             dev_err(dev, "failed to register sysfs group: error=%d", ret);
> > +             cros_ucsi_destroy(udata);
> > +             return ret;
> > +     }
> > +
> >       return 0;
> >  }
> >
> > -static void cros_ucsi_remove(struct platform_device *dev)
> > +static void cros_ucsi_remove(struct platform_device *pdev)
> >  {
> > -     struct cros_ucsi_data *udata = platform_get_drvdata(dev);
> > +     struct cros_ucsi_data *udata = platform_get_drvdata(pdev);
>
> Please merge that change into the patch 3/8.
>

I will merge this change to the"usb: typec: ucsi: Implement ChromeOS
UCSI driver".

Thanks,
Lukasz



> > +     sysfs_remove_group(&pdev->dev.kobj, &cros_ec_ucsi_attrs_grp);
> > +     nl_cros_ec_unregister();
> >       ucsi_unregister(udata->ucsi);
> >       cros_ucsi_destroy(udata);
> >  }
>
> thanks,
>
> --
> heikki
Heikki Krogerus Sept. 19, 2024, 9:38 a.m. UTC | #4
On Sun, Sep 15, 2024 at 12:08:45AM +0200, Łukasz Bartosik wrote:
> On Wed, Sep 11, 2024 at 4:09 PM Heikki Krogerus
> <heikki.krogerus@linux.intel.com> wrote:
> >
> > Hi,
> >
> > On Tue, Sep 10, 2024 at 10:15:25AM +0000, Łukasz Bartosik wrote:
> > > Add netlink to ChromeOS UCSI driver to allow forwarding
> > > of UCSI messages to userspace for debugging and testing
> > > purposes.
> >
> > Why does this need to be cros_ec specific?
> >
> 
> You're right. Netlink does not have to be cros_ec_ucsi specific.
> Would you like to have netlink in typec_ucsi ?

Does it need to be netlink? We would then have tracepoints, the
custom debugfs interface, and this netlink interface.

I think this information could be exposed via trancepoints (unless I'm
missing something).

Br,
Łukasz Bartosik Sept. 19, 2024, 6:03 p.m. UTC | #5
On Thu, Sep 19, 2024 at 11:38 AM Heikki Krogerus
<heikki.krogerus@linux.intel.com> wrote:
>
> On Sun, Sep 15, 2024 at 12:08:45AM +0200, Łukasz Bartosik wrote:
> > On Wed, Sep 11, 2024 at 4:09 PM Heikki Krogerus
> > <heikki.krogerus@linux.intel.com> wrote:
> > >
> > > Hi,
> > >
> > > On Tue, Sep 10, 2024 at 10:15:25AM +0000, Łukasz Bartosik wrote:
> > > > Add netlink to ChromeOS UCSI driver to allow forwarding
> > > > of UCSI messages to userspace for debugging and testing
> > > > purposes.
> > >
> > > Why does this need to be cros_ec specific?
> > >
> >
> > You're right. Netlink does not have to be cros_ec_ucsi specific.
> > Would you like to have netlink in typec_ucsi ?
>
> Does it need to be netlink? We would then have tracepoints, the
> custom debugfs interface, and this netlink interface.
>
> I think this information could be exposed via trancepoints (unless I'm
> missing something).
>

Hi Heikki,

I agree that there is a common area which is covered by both trace
events and netlink.
However netlink also has advantages which IMHO trace events lack. One
of our cases is that
from userspace it is easy to forward the UCSI messages to a Wireshark
with a plugin
which can decode it. Another case is to use UCSI forwarded messages
through netlink
for testing and validation of chromebooks.

How about leaving netlink specific to cros_ec_ucsi driver ? Would you
consent to that ?

Thanks,
Lukasz

> Br,

>
> --
> heikki
Dmitry Baryshkov Sept. 19, 2024, 8 p.m. UTC | #6
On Thu, Sep 19, 2024 at 08:03:37PM GMT, Łukasz Bartosik wrote:
> On Thu, Sep 19, 2024 at 11:38 AM Heikki Krogerus
> <heikki.krogerus@linux.intel.com> wrote:
> >
> > On Sun, Sep 15, 2024 at 12:08:45AM +0200, Łukasz Bartosik wrote:
> > > On Wed, Sep 11, 2024 at 4:09 PM Heikki Krogerus
> > > <heikki.krogerus@linux.intel.com> wrote:
> > > >
> > > > Hi,
> > > >
> > > > On Tue, Sep 10, 2024 at 10:15:25AM +0000, Łukasz Bartosik wrote:
> > > > > Add netlink to ChromeOS UCSI driver to allow forwarding
> > > > > of UCSI messages to userspace for debugging and testing
> > > > > purposes.
> > > >
> > > > Why does this need to be cros_ec specific?
> > > >
> > >
> > > You're right. Netlink does not have to be cros_ec_ucsi specific.
> > > Would you like to have netlink in typec_ucsi ?
> >
> > Does it need to be netlink? We would then have tracepoints, the
> > custom debugfs interface, and this netlink interface.
> >
> > I think this information could be exposed via trancepoints (unless I'm
> > missing something).
> >
> 
> Hi Heikki,
> 
> I agree that there is a common area which is covered by both trace
> events and netlink.
> However netlink also has advantages which IMHO trace events lack. One
> of our cases is that
> from userspace it is easy to forward the UCSI messages to a Wireshark
> with a plugin
> which can decode it. Another case is to use UCSI forwarded messages
> through netlink
> for testing and validation of chromebooks.
> 
> How about leaving netlink specific to cros_ec_ucsi driver ? Would you
> consent to that ?

I think having it specific to cros_ec_ucsi is the worst option out of
three. It should either be generified to work with all UCSI drivers or
go away and be replaced by tracepoints (against, generic to all UCSI
drivers) or some other mechanism (e.g. TCPM has rolling log of
messages).
diff mbox series

Patch

diff --git a/MAINTAINERS b/MAINTAINERS
index d084f32208f0..2afb406a24ce 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5305,7 +5305,9 @@  M:	Abhishek Pandit-Subedi <abhishekpandit@chromium.org>
 M:	Łukasz Bartosik <ukaszb@chromium.org>
 L:	chrome-platform@lists.linux.dev
 S:	Maintained
-F:	drivers/usb/typec/ucsi/cros_ec_ucsi.c
+F:	drivers/usb/typec/ucsi/cros_ec_ucsi_main.c
+F:	drivers/usb/typec/ucsi/cros_ec_ucsi_nl.c
+F:	drivers/usb/typec/ucsi/cros_ec_ucsi_nl.h
 F:	drivers/usb/typec/ucsi/cros_ec_ucsi_trace.h
 
 CHRONTEL CH7322 CEC DRIVER
diff --git a/drivers/usb/typec/ucsi/Makefile b/drivers/usb/typec/ucsi/Makefile
index be98a879104d..82d960394c39 100644
--- a/drivers/usb/typec/ucsi/Makefile
+++ b/drivers/usb/typec/ucsi/Makefile
@@ -21,5 +21,7 @@  obj-$(CONFIG_UCSI_ACPI)			+= ucsi_acpi.o
 obj-$(CONFIG_UCSI_CCG)			+= ucsi_ccg.o
 obj-$(CONFIG_UCSI_STM32G0)		+= ucsi_stm32g0.o
 obj-$(CONFIG_UCSI_PMIC_GLINK)		+= ucsi_glink.o
-obj-$(CONFIG_CROS_EC_UCSI)		+= cros_ec_ucsi.o
 obj-$(CONFIG_UCSI_LENOVO_YOGA_C630)	+= ucsi_yoga_c630.o
+
+obj-$(CONFIG_CROS_EC_UCSI)		+= cros_ec_ucsi.o
+cros_ec_ucsi-y				:= cros_ec_ucsi_main.o cros_ec_ucsi_nl.o
diff --git a/drivers/usb/typec/ucsi/cros_ec_ucsi.c b/drivers/usb/typec/ucsi/cros_ec_ucsi_main.c
similarity index 79%
rename from drivers/usb/typec/ucsi/cros_ec_ucsi.c
rename to drivers/usb/typec/ucsi/cros_ec_ucsi_main.c
index 70185616ec86..008b61921278 100644
--- a/drivers/usb/typec/ucsi/cros_ec_ucsi.c
+++ b/drivers/usb/typec/ucsi/cros_ec_ucsi_main.c
@@ -19,6 +19,7 @@ 
 #define CREATE_TRACE_POINTS
 #include "ucsi.h"
 #include "cros_ec_ucsi_trace.h"
+#include "cros_ec_ucsi_nl.h"
 
 /*
  * Maximum size in bytes of a UCSI message between AP and EC
@@ -43,6 +44,43 @@  struct cros_ucsi_data {
 	unsigned long flags;
 };
 
+/*
+ * When set to true the cros_ec_ucsi driver will forward all UCSI messages
+ * exchanged between OPM <-> PPM to userspace through netlink
+ */
+static bool is_ap_sniffer_en;
+
+static ssize_t enable_ap_sniffer_show(struct device *dev,
+				      struct device_attribute *attr,
+				      char *buf)
+{
+	return sprintf(buf, "%d\n", is_ap_sniffer_en);
+}
+
+static ssize_t enable_ap_sniffer_store(struct device *dev,
+				       struct device_attribute *attr,
+				       const char *buf, size_t count)
+{
+	u8 value;
+
+	if (kstrtou8(buf, 0, &value))
+		return -EINVAL;
+
+	is_ap_sniffer_en = value ? 1 : 0;
+	return count;
+}
+
+static DEVICE_ATTR_RW(enable_ap_sniffer);
+
+static struct attribute *cros_ec_ucsi_attrs[] = {
+	&dev_attr_enable_ap_sniffer.attr,
+	NULL
+};
+
+static const struct attribute_group cros_ec_ucsi_attrs_grp = {
+	.attrs = cros_ec_ucsi_attrs,
+};
+
 static int cros_ucsi_read(struct ucsi *ucsi, unsigned int offset, void *val,
 			  size_t val_len)
 {
@@ -65,6 +103,9 @@  static int cros_ucsi_read(struct ucsi *ucsi, unsigned int offset, void *val,
 		return ret;
 	}
 
+	if (is_ap_sniffer_en)
+		nl_cros_ec_bcast_msg(NL_CROS_EC_TO_PPM, NL_CROS_EC_RD, offset,
+				     val, val_len);
 	trace_cros_ec_opm_to_ppm_rd(offset, val, val_len);
 	return 0;
 }
@@ -101,6 +142,9 @@  static int cros_ucsi_async_control(struct ucsi *ucsi, u64 cmd)
 		return ret;
 	}
 
+	if (is_ap_sniffer_en)
+		nl_cros_ec_bcast_msg(NL_CROS_EC_TO_PPM, NL_CROS_EC_WR,
+				     req->offset, (u8 *) &cmd, sizeof(cmd));
 	trace_cros_ec_opm_to_ppm_wr(req->offset, &cmd, sizeof(cmd));
 	return 0;
 }
@@ -144,6 +188,8 @@  static void cros_ucsi_work(struct work_struct *work)
 	struct cros_ucsi_data *udata = container_of(work, struct cros_ucsi_data, work);
 	u32 cci;
 
+	if (is_ap_sniffer_en)
+		nl_cros_ec_bcast_msg(NL_CROS_EC_TO_OPM, 0, 0, NULL, 0);
 	trace_cros_ec_ppm_to_opm(0);
 
 	if (cros_ucsi_read_cci(udata->ucsi, &cci))
@@ -229,13 +275,29 @@  static int cros_ucsi_probe(struct platform_device *pdev)
 		return ret;
 	}
 
+	ret = nl_cros_ec_register();
+	if (ret) {
+		dev_err(dev, "failed to register netlink: error=%d", ret);
+		cros_ucsi_destroy(udata);
+		return ret;
+	}
+
+	ret = sysfs_create_group(&dev->kobj, &cros_ec_ucsi_attrs_grp);
+	if (ret) {
+		dev_err(dev, "failed to register sysfs group: error=%d", ret);
+		cros_ucsi_destroy(udata);
+		return ret;
+	}
+
 	return 0;
 }
 
-static void cros_ucsi_remove(struct platform_device *dev)
+static void cros_ucsi_remove(struct platform_device *pdev)
 {
-	struct cros_ucsi_data *udata = platform_get_drvdata(dev);
+	struct cros_ucsi_data *udata = platform_get_drvdata(pdev);
 
+	sysfs_remove_group(&pdev->dev.kobj, &cros_ec_ucsi_attrs_grp);
+	nl_cros_ec_unregister();
 	ucsi_unregister(udata->ucsi);
 	cros_ucsi_destroy(udata);
 }
diff --git a/drivers/usb/typec/ucsi/cros_ec_ucsi_nl.c b/drivers/usb/typec/ucsi/cros_ec_ucsi_nl.c
new file mode 100644
index 000000000000..360568044891
--- /dev/null
+++ b/drivers/usb/typec/ucsi/cros_ec_ucsi_nl.c
@@ -0,0 +1,87 @@ 
+// SPDX-License-Identifier: GPL-2.0
+
+#include <net/genetlink.h>
+#include "cros_ec_ucsi_nl.h"
+
+static const struct genl_multicast_group nl_mc_grps[] = {
+	{ .name = NL_CROS_EC_MC_GRP_NAME },
+};
+
+static struct genl_family genl_fam = {
+	.name	  = NL_CROS_EC_NAME,
+	.version  = NL_CROS_EC_VER,
+	.maxattr  = NL_CROS_EC_A_MAX,
+	.mcgrps	  = nl_mc_grps,
+	.n_mcgrps = ARRAY_SIZE(nl_mc_grps),
+};
+
+int nl_cros_ec_register(void)
+{
+	return genl_register_family(&genl_fam);
+}
+
+void nl_cros_ec_unregister(void)
+{
+	genl_unregister_family(&genl_fam);
+}
+
+int nl_cros_ec_bcast_msg(enum nl_cros_ec_msg_dir dir,
+			 enum nl_cros_ec_cmd_type cmd_type,
+			 u16 offset, const u8 *payload, size_t msg_size)
+{
+	struct timespec64 ts;
+	struct sk_buff *skb;
+	int ret = -ENOMEM;
+	void *hdr;
+
+	skb = genlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+	if (!skb)
+		return -ENOMEM;
+
+	hdr = genlmsg_put(skb, 0, 0, &genl_fam, 0, NL_CROS_EC_C_UCSI);
+	if (!hdr)
+		goto free_mem;
+
+	ret = nla_put_u8(skb, NL_CROS_EC_A_SRC, NL_CROS_EC_AP);
+	if (ret)
+		goto cancel;
+
+	ret = nla_put_u8(skb, NL_CROS_EC_A_DIR, dir);
+	if (ret)
+		goto cancel;
+
+	ret = nla_put_u16(skb, NL_CROS_EC_A_OFFSET, offset);
+	if (ret)
+		goto cancel;
+
+	ret = nla_put_u8(skb, NL_CROS_EC_A_CMD_TYPE, cmd_type);
+	if (ret)
+		goto cancel;
+
+	ktime_get_ts64(&ts);
+	ret = nla_put_u32(skb, NL_CROS_EC_A_TSTAMP_SEC, (u32)ts.tv_sec);
+	if (ret)
+		goto cancel;
+
+	ret = nla_put_u32(skb, NL_CROS_EC_A_TSTAMP_USEC,
+			  (u32)(ts.tv_nsec/1000));
+	if (ret)
+		goto cancel;
+
+	ret = nla_put(skb, NL_CROS_EC_A_PAYLOAD, msg_size, payload);
+	if (ret)
+		goto cancel;
+
+	genlmsg_end(skb, hdr);
+
+	ret = genlmsg_multicast(&genl_fam, skb, 0, 0, GFP_KERNEL);
+	if (ret && ret != -ESRCH)
+		goto free_mem;
+
+	return 0;
+cancel:
+	genlmsg_cancel(skb, hdr);
+free_mem:
+	nlmsg_free(skb);
+	return ret;
+}
diff --git a/drivers/usb/typec/ucsi/cros_ec_ucsi_nl.h b/drivers/usb/typec/ucsi/cros_ec_ucsi_nl.h
new file mode 100644
index 000000000000..c6192d8ace56
--- /dev/null
+++ b/drivers/usb/typec/ucsi/cros_ec_ucsi_nl.h
@@ -0,0 +1,52 @@ 
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __DRIVER_USB_TYPEC_CROS_EC_UCSI_NL_H
+#define __DRIVER_USB_TYPEC_CROS_EC_UCSI_NL_H
+
+#define NL_CROS_EC_NAME "cros_ec_ucsi"
+#define NL_CROS_EC_VER 1
+#define NL_CROS_EC_MC_GRP_NAME "cros_ec_ucsi_mc"
+
+/* attributes */
+enum nl_cros_ec_attrs {
+	NL_CROS_EC_A_SRC,
+	NL_CROS_EC_A_DIR,
+	NL_CROS_EC_A_OFFSET,
+	NL_CROS_EC_A_CMD_TYPE,
+	NL_CROS_EC_A_TSTAMP_SEC,
+	NL_CROS_EC_A_TSTAMP_USEC,
+	NL_CROS_EC_A_PAYLOAD,
+	NL_CROS_EC_A_MAX
+};
+
+enum nl_cros_ec_cmds {
+	NL_CROS_EC_C_UCSI,
+	NL_CROS_EC_C_MAX
+};
+
+/* where message was captured - EC or AP */
+enum nl_cros_ec_src {
+	NL_CROS_EC_AP,
+	NL_CROS_EC_EC
+};
+
+/* message destination */
+enum nl_cros_ec_msg_dir {
+	NL_CROS_EC_TO_PPM,
+	NL_CROS_EC_TO_OPM,
+	NL_CROS_EC_TO_LPM
+};
+
+/* command type - read or write */
+enum nl_cros_ec_cmd_type {
+	NL_CROS_EC_RD,
+	NL_CROS_EC_WR
+};
+
+int nl_cros_ec_register(void);
+void nl_cros_ec_unregister(void);
+int nl_cros_ec_bcast_msg(enum nl_cros_ec_msg_dir dir,
+			 enum nl_cros_ec_cmd_type cmd_type,
+			 u16 offset, const u8 *payload, size_t msg_size);
+
+#endif /* __DRIVER_USB_TYPEC_CROS_EC_UCSI_NL_H */