diff mbox

[v4,05/14] platform/x86: dell-wmi-descriptor: split WMI descriptor into it's own driver

Message ID ff211830e3953c70aa8e0d43614619f1fb423668.1507156392.git.mario.limonciello@dell.com (mailing list archive)
State Changes Requested, archived
Delegated to: Darren Hart
Headers show

Commit Message

Limonciello, Mario Oct. 4, 2017, 10:48 p.m. UTC
All communication on individual GUIDs should occur in separate drivers.
Allowing a driver to communicate with the bus to another GUID is just
a hack that discourages drivers to adopt the bus model.

The information found from the WMI descriptor driver is now exported
for use by other drivers.

Signed-off-by: Mario Limonciello <mario.limonciello@dell.com>
---
 MAINTAINERS                                |   5 +
 drivers/platform/x86/Kconfig               |  12 +++
 drivers/platform/x86/Makefile              |   1 +
 drivers/platform/x86/dell-wmi-descriptor.c | 162 +++++++++++++++++++++++++++++
 drivers/platform/x86/dell-wmi-descriptor.h |  18 ++++
 drivers/platform/x86/dell-wmi.c            |  88 ++--------------
 6 files changed, 205 insertions(+), 81 deletions(-)
 create mode 100644 drivers/platform/x86/dell-wmi-descriptor.c
 create mode 100644 drivers/platform/x86/dell-wmi-descriptor.h

Comments

Darren Hart Oct. 5, 2017, 1:09 a.m. UTC | #1
On Wed, Oct 04, 2017 at 05:48:31PM -0500, Mario Limonciello wrote:
> All communication on individual GUIDs should occur in separate drivers.
> Allowing a driver to communicate with the bus to another GUID is just
> a hack that discourages drivers to adopt the bus model.
> 
> The information found from the WMI descriptor driver is now exported
> for use by other drivers.
> 
> Signed-off-by: Mario Limonciello <mario.limonciello@dell.com>
> ---
>  MAINTAINERS                                |   5 +
>  drivers/platform/x86/Kconfig               |  12 +++
>  drivers/platform/x86/Makefile              |   1 +
>  drivers/platform/x86/dell-wmi-descriptor.c | 162 +++++++++++++++++++++++++++++
>  drivers/platform/x86/dell-wmi-descriptor.h |  18 ++++
>  drivers/platform/x86/dell-wmi.c            |  88 ++--------------
>  6 files changed, 205 insertions(+), 81 deletions(-)
>  create mode 100644 drivers/platform/x86/dell-wmi-descriptor.c
>  create mode 100644 drivers/platform/x86/dell-wmi-descriptor.h
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 08b96f77f618..659dbeec4191 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -4002,6 +4002,11 @@ M:	Pali Rohár <pali.rohar@gmail.com>
>  S:	Maintained
>  F:	drivers/platform/x86/dell-wmi.c
>  
> +DELL WMI DESCRIPTOR DRIVER
> +M:	Mario Limonciello <mario.limonciello@dell.com>
> +S:	Maintained
> +F:	drivers/platform/x86/dell-wmi-descriptor.c
> +
>  DELTA ST MEDIA DRIVER
>  M:	Hugues Fruchet <hugues.fruchet@st.com>
>  L:	linux-media@vger.kernel.org
> diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
> index 1f7959ff055c..bc347c326d87 100644
> --- a/drivers/platform/x86/Kconfig
> +++ b/drivers/platform/x86/Kconfig
> @@ -121,6 +121,7 @@ config DELL_WMI
>  	depends on DMI
>  	depends on INPUT
>  	depends on ACPI_VIDEO || ACPI_VIDEO = n
> +	depends on DELL_WMI_DESCRIPTOR

We have to be careful with the use of "select", but I think in this case it
makes sense.

If you "select DELL_WMI_DESCRIPTOR" here, and maintain depends on
ACPI_WMI (not shown in context here), then...

>  	select DELL_SMBIOS
>  	select INPUT_SPARSEKMAP
>  	---help---
> @@ -129,6 +130,17 @@ config DELL_WMI
>  	  To compile this driver as a module, choose M here: the module will
>  	  be called dell-wmi.
>  
> +config DELL_WMI_DESCRIPTOR
> +	tristate "Dell WMI descriptor"
> +	depends on ACPI_WMI
> +	default ACPI_WMI

This default can be dropped, the dependency will be met if DELL_WMI can
be enabled...

> +	---help---
> +	  Say Y here if you want to be able to read the format of WMI
> +	  communications on some Dell laptops, desktops and IoT gateways.
> +
> +	  To compile this driver as a module, choose M here: the module will
> +	  be called dell-wmi-descriptor.

... and this can be converted to an invisible option and eliminate some
Kconfig clutter.

...


> diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c
> index 1366bccdf275..90d7e8e55e9b 100644
...
> @@ -376,7 +375,11 @@ static void dell_wmi_notify(struct wmi_device *wdev,
>  	 * So to prevent reading garbage from buffer we will process only first
>  	 * one event on devices with WMI interface version 0.
>  	 */
> -	if (priv->interface_version == 0 && buffer_entry < buffer_end)
> +	if (!dell_wmi_get_interface_version(&interface_version)) {

You've introduced a dependency on another module here and haven't
guaranteed that dell-wmi-descriptor will have been loaded prior to this
one.

You'll want to add something like:

#ifdef CONFIG_DELL_WMI_DESCRIPTOR_MODULE
	if (request_module("dell_wmi_descriptor"))
		/* FAIL */
#endif

During init.
Andy Shevchenko Oct. 5, 2017, 5:29 a.m. UTC | #2
On Thu, Oct 5, 2017 at 4:09 AM, Darren Hart <dvhart@infradead.org> wrote:
> On Wed, Oct 04, 2017 at 05:48:31PM -0500, Mario Limonciello wrote:
>> All communication on individual GUIDs should occur in separate drivers.
>> Allowing a driver to communicate with the bus to another GUID is just
>> a hack that discourages drivers to adopt the bus model.
>>
>> The information found from the WMI descriptor driver is now exported
>> for use by other drivers.

> You'll want to add something like:
>
> #ifdef CONFIG_DELL_WMI_DESCRIPTOR_MODULE
>         if (request_module("dell_wmi_descriptor"))
>                 /* FAIL */
> #endif
>
> During init.

I don't think #ifdef is needed.

We may just request module.

But looking in the code it seems that we simple need to select that
module. No request_module will be needed.
Did I miss something?
Andy Shevchenko Oct. 5, 2017, 5:34 a.m. UTC | #3
On Thu, Oct 5, 2017 at 1:48 AM, Mario Limonciello
<mario.limonciello@dell.com> wrote:
> All communication on individual GUIDs should occur in separate drivers.
> Allowing a driver to communicate with the bus to another GUID is just
> a hack that discourages drivers to adopt the bus model.
>
> The information found from the WMI descriptor driver is now exported
> for use by other drivers.

> +       priv = list_first_entry_or_null(&wmi_list,
> +                                       struct descriptor_priv,
> +                                       list);

> +       priv = list_first_entry_or_null(&wmi_list,
> +                                       struct descriptor_priv,
> +                                       list);

static inline ...to_priv(...)
{
 return list_first_entry_...();
}

> +       list_add_tail(&priv->list, &wmi_list);

> +       list_del(&priv->list);

Do these need locking?

> +bool dell_wmi_get_interface_version(u32 *version);
> +bool dell_wmi_get_size(u32 *size);

This might need stubs when module is not selected (when functionality
is optional if it would be the case), otherwise all users should
select it explicitly.
Darren Hart Oct. 5, 2017, 7:11 a.m. UTC | #4
On Thu, Oct 05, 2017 at 08:29:10AM +0300, Andy Shevchenko wrote:
> On Thu, Oct 5, 2017 at 4:09 AM, Darren Hart <dvhart@infradead.org> wrote:
> > On Wed, Oct 04, 2017 at 05:48:31PM -0500, Mario Limonciello wrote:
> >> All communication on individual GUIDs should occur in separate drivers.
> >> Allowing a driver to communicate with the bus to another GUID is just
> >> a hack that discourages drivers to adopt the bus model.
> >>
> >> The information found from the WMI descriptor driver is now exported
> >> for use by other drivers.
> 
> > You'll want to add something like:
> >
> > #ifdef CONFIG_DELL_WMI_DESCRIPTOR_MODULE
> >         if (request_module("dell_wmi_descriptor"))
> >                 /* FAIL */
> > #endif
> >
> > During init.
> 
> I don't think #ifdef is needed.

Without the ifdef, we can't distinguish between request_module failing
to load the module because it isn't available and because it is
built-in.

> 
> We may just request module.
> 
> But looking in the code it seems that we simple need to select that
> module. No request_module will be needed.

The select will ensure the module is built, but there is not guarantee
to module load order. The intent of the above is to ensure the symbols
from the required module are loaded.

> Did I miss something?

Or I did :-) Is there something about this module which ensures
dell_wmi_descriptor is loaded first?
Andy Shevchenko Oct. 5, 2017, 8:47 a.m. UTC | #5
On Thu, Oct 5, 2017 at 10:11 AM, Darren Hart <dvhart@infradead.org> wrote:
> On Thu, Oct 05, 2017 at 08:29:10AM +0300, Andy Shevchenko wrote:
>> On Thu, Oct 5, 2017 at 4:09 AM, Darren Hart <dvhart@infradead.org> wrote:

>> > You'll want to add something like:
>> >
>> > #ifdef CONFIG_DELL_WMI_DESCRIPTOR_MODULE
>> >         if (request_module("dell_wmi_descriptor"))
>> >                 /* FAIL */
>> > #endif
>> >
>> > During init.
>>
>> I don't think #ifdef is needed.
>
> Without the ifdef, we can't distinguish between request_module failing
> to load the module because it isn't available and because it is
> built-in.
>
>>
>> We may just request module.
>>
>> But looking in the code it seems that we simple need to select that
>> module. No request_module will be needed.
>
> The select will ensure the module is built, but there is not guarantee
> to module load order. The intent of the above is to ensure the symbols
> from the required module are loaded.
>
>> Did I miss something?
>
> Or I did :-) Is there something about this module which ensures
> dell_wmi_descriptor is loaded first?

If there is an optional *run-time* dependency we need to use somelike
request_module(). For example, this is the case for idma64
(drivers/dma) vs intel-lpss (drivers/mfd).

If it's mandatory run-time dependency, then we need to add stubs to
the header and select the callee's module in Kconfig.

In case they are both modules, depmod keeps an ordering.

So, the corner case here is when the caller is builtin while callee is module.

This is a bit tricky to add to Kconfig (we also have such cases
between I2C DesignWare and acpi_lpss AFAIR).
Limonciello, Mario Oct. 5, 2017, 1:59 p.m. UTC | #6
> -----Original Message-----

> From: Andy Shevchenko [mailto:andy.shevchenko@gmail.com]

> Sent: Thursday, October 5, 2017 3:48 AM

> To: Darren Hart <dvhart@infradead.org>

> Cc: Limonciello, Mario <Mario_Limonciello@Dell.com>; LKML <linux-

> kernel@vger.kernel.org>; Platform Driver <platform-driver-

> x86@vger.kernel.org>; Andy Lutomirski <luto@kernel.org>;

> quasisec@google.com; Pali Rohár <pali.rohar@gmail.com>; Rafael J. Wysocki

> <rjw@rjwysocki.net>; mjg59@google.com; Christoph Hellwig <hch@lst.de>;

> Greg KH <greg@kroah.com>

> Subject: Re: [PATCH v4 05/14] platform/x86: dell-wmi-descriptor: split WMI

> descriptor into it's own driver

> 

> On Thu, Oct 5, 2017 at 10:11 AM, Darren Hart <dvhart@infradead.org> wrote:

> > On Thu, Oct 05, 2017 at 08:29:10AM +0300, Andy Shevchenko wrote:

> >> On Thu, Oct 5, 2017 at 4:09 AM, Darren Hart <dvhart@infradead.org> wrote:

> 

> >> > You'll want to add something like:

> >> >

> >> > #ifdef CONFIG_DELL_WMI_DESCRIPTOR_MODULE

> >> >         if (request_module("dell_wmi_descriptor"))

> >> >                 /* FAIL */

> >> > #endif

> >> >

> >> > During init.

> >>

> >> I don't think #ifdef is needed.

> >

> > Without the ifdef, we can't distinguish between request_module failing

> > to load the module because it isn't available and because it is

> > built-in.

> >

> >>

> >> We may just request module.

> >>

> >> But looking in the code it seems that we simple need to select that

> >> module. No request_module will be needed.

> >

> > The select will ensure the module is built, but there is not guarantee

> > to module load order. The intent of the above is to ensure the symbols

> > from the required module are loaded.

> >

> >> Did I miss something?

> >

> > Or I did :-) Is there something about this module which ensures

> > dell_wmi_descriptor is loaded first?

> 

> If there is an optional *run-time* dependency we need to use somelike

> request_module(). For example, this is the case for idma64

> (drivers/dma) vs intel-lpss (drivers/mfd).

> 

> If it's mandatory run-time dependency, then we need to add stubs to

> the header and select the callee's module in Kconfig.

> 

> In case they are both modules, depmod keeps an ordering.

> 

> So, the corner case here is when the caller is builtin while callee is module.

> 

> This is a bit tricky to add to Kconfig (we also have such cases

> between I2C DesignWare and acpi_lpss AFAIR).

> 

> --

> With Best Regards,

> Andy Shevchenko


So I believe it should be a mandatory runtime dependency due to needing
the symbol dell_wmi_get_interface_version.  Depmod should be handling
this then no?
Darren Hart Oct. 5, 2017, 2:14 p.m. UTC | #7
On Thu, Oct 05, 2017 at 01:59:36PM +0000, Mario.Limonciello@dell.com wrote:
> > -----Original Message-----
> > From: Andy Shevchenko [mailto:andy.shevchenko@gmail.com]
> > Sent: Thursday, October 5, 2017 3:48 AM
> > To: Darren Hart <dvhart@infradead.org>
> > Cc: Limonciello, Mario <Mario_Limonciello@Dell.com>; LKML <linux-
> > kernel@vger.kernel.org>; Platform Driver <platform-driver-
> > x86@vger.kernel.org>; Andy Lutomirski <luto@kernel.org>;
> > quasisec@google.com; Pali Rohár <pali.rohar@gmail.com>; Rafael J. Wysocki
> > <rjw@rjwysocki.net>; mjg59@google.com; Christoph Hellwig <hch@lst.de>;
> > Greg KH <greg@kroah.com>
> > Subject: Re: [PATCH v4 05/14] platform/x86: dell-wmi-descriptor: split WMI
> > descriptor into it's own driver
> > 
> > On Thu, Oct 5, 2017 at 10:11 AM, Darren Hart <dvhart@infradead.org> wrote:
> > > On Thu, Oct 05, 2017 at 08:29:10AM +0300, Andy Shevchenko wrote:
> > >> On Thu, Oct 5, 2017 at 4:09 AM, Darren Hart <dvhart@infradead.org> wrote:
> > 
> > >> > You'll want to add something like:
> > >> >
> > >> > #ifdef CONFIG_DELL_WMI_DESCRIPTOR_MODULE
> > >> >         if (request_module("dell_wmi_descriptor"))
> > >> >                 /* FAIL */
> > >> > #endif
> > >> >
> > >> > During init.
> > >>
> > >> I don't think #ifdef is needed.
> > >
> > > Without the ifdef, we can't distinguish between request_module failing
> > > to load the module because it isn't available and because it is
> > > built-in.
> > >
> > >>
> > >> We may just request module.
> > >>
> > >> But looking in the code it seems that we simple need to select that
> > >> module. No request_module will be needed.
> > >
> > > The select will ensure the module is built, but there is not guarantee
> > > to module load order. The intent of the above is to ensure the symbols
> > > from the required module are loaded.
> > >
> > >> Did I miss something?
> > >
> > > Or I did :-) Is there something about this module which ensures
> > > dell_wmi_descriptor is loaded first?
> > 
> > If there is an optional *run-time* dependency we need to use somelike
> > request_module(). For example, this is the case for idma64
> > (drivers/dma) vs intel-lpss (drivers/mfd).
> > 
> > If it's mandatory run-time dependency, then we need to add stubs to
> > the header and select the callee's module in Kconfig.
> > 
> > In case they are both modules, depmod keeps an ordering.
> > 
> > So, the corner case here is when the caller is builtin while callee is module.
> > 
> > This is a bit tricky to add to Kconfig (we also have such cases
> > between I2C DesignWare and acpi_lpss AFAIR).
> > 
> > --
> > With Best Regards,
> > Andy Shevchenko
> 
> So I believe it should be a mandatory runtime dependency due to needing
> the symbol dell_wmi_get_interface_version.  Depmod should be handling
> this then no?

This was nagging me all night, and I was thinking the last time I had to
use this it was indeed a runtime dependency. Sorry for the noise on
this.

The kconfig needs to be setup such that dell-wmi-descriptor cannot be a
module if the dependent drivers are modules.
Limonciello, Mario Oct. 5, 2017, 2:47 p.m. UTC | #8
> -----Original Message-----
> From: Darren Hart [mailto:dvhart@infradead.org]
> Sent: Thursday, October 5, 2017 9:15 AM
> To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> Cc: andy.shevchenko@gmail.com; linux-kernel@vger.kernel.org; platform-
> driver-x86@vger.kernel.org; luto@kernel.org; quasisec@google.com;
> pali.rohar@gmail.com; rjw@rjwysocki.net; mjg59@google.com; hch@lst.de;
> greg@kroah.com
> Subject: Re: [PATCH v4 05/14] platform/x86: dell-wmi-descriptor: split WMI
> descriptor into it's own driver
> 
> On Thu, Oct 05, 2017 at 01:59:36PM +0000, Mario.Limonciello@dell.com wrote:
> > > -----Original Message-----
> > > From: Andy Shevchenko [mailto:andy.shevchenko@gmail.com]
> > > Sent: Thursday, October 5, 2017 3:48 AM
> > > To: Darren Hart <dvhart@infradead.org>
> > > Cc: Limonciello, Mario <Mario_Limonciello@Dell.com>; LKML <linux-
> > > kernel@vger.kernel.org>; Platform Driver <platform-driver-
> > > x86@vger.kernel.org>; Andy Lutomirski <luto@kernel.org>;
> > > quasisec@google.com; Pali Rohár <pali.rohar@gmail.com>; Rafael J. Wysocki
> > > <rjw@rjwysocki.net>; mjg59@google.com; Christoph Hellwig <hch@lst.de>;
> > > Greg KH <greg@kroah.com>
> > > Subject: Re: [PATCH v4 05/14] platform/x86: dell-wmi-descriptor: split WMI
> > > descriptor into it's own driver
> > >
> > > On Thu, Oct 5, 2017 at 10:11 AM, Darren Hart <dvhart@infradead.org> wrote:
> > > > On Thu, Oct 05, 2017 at 08:29:10AM +0300, Andy Shevchenko wrote:
> > > >> On Thu, Oct 5, 2017 at 4:09 AM, Darren Hart <dvhart@infradead.org>
> wrote:
> > >
> > > >> > You'll want to add something like:
> > > >> >
> > > >> > #ifdef CONFIG_DELL_WMI_DESCRIPTOR_MODULE
> > > >> >         if (request_module("dell_wmi_descriptor"))
> > > >> >                 /* FAIL */
> > > >> > #endif
> > > >> >
> > > >> > During init.
> > > >>
> > > >> I don't think #ifdef is needed.
> > > >
> > > > Without the ifdef, we can't distinguish between request_module failing
> > > > to load the module because it isn't available and because it is
> > > > built-in.
> > > >
> > > >>
> > > >> We may just request module.
> > > >>
> > > >> But looking in the code it seems that we simple need to select that
> > > >> module. No request_module will be needed.
> > > >
> > > > The select will ensure the module is built, but there is not guarantee
> > > > to module load order. The intent of the above is to ensure the symbols
> > > > from the required module are loaded.
> > > >
> > > >> Did I miss something?
> > > >
> > > > Or I did :-) Is there something about this module which ensures
> > > > dell_wmi_descriptor is loaded first?
> > >
> > > If there is an optional *run-time* dependency we need to use somelike
> > > request_module(). For example, this is the case for idma64
> > > (drivers/dma) vs intel-lpss (drivers/mfd).
> > >
> > > If it's mandatory run-time dependency, then we need to add stubs to
> > > the header and select the callee's module in Kconfig.
> > >
> > > In case they are both modules, depmod keeps an ordering.
> > >
> > > So, the corner case here is when the caller is builtin while callee is module.
> > >
> > > This is a bit tricky to add to Kconfig (we also have such cases
> > > between I2C DesignWare and acpi_lpss AFAIR).
> > >
> > > --
> > > With Best Regards,
> > > Andy Shevchenko
> >
> > So I believe it should be a mandatory runtime dependency due to needing
> > the symbol dell_wmi_get_interface_version.  Depmod should be handling
> > this then no?
> 
> This was nagging me all night, and I was thinking the last time I had to
> use this it was indeed a runtime dependency. Sorry for the noise on
> this.
> 
> The kconfig needs to be setup such that dell-wmi-descriptor cannot be a
> module if the dependent drivers are modules.
> 
> --
> Darren Hart
> VMware Open Source Technology Center

Even if the others are modules shouldn't module ordering from depmod still DTRT?
You still won't be able to load dell-wmi.ko until dell-wmi-descriptor.ko was loaded.
Limonciello, Mario Oct. 5, 2017, 5:04 p.m. UTC | #9
> -----Original Message-----

> From: Andy Shevchenko [mailto:andy.shevchenko@gmail.com]

> Sent: Thursday, October 5, 2017 12:34 AM

> To: Limonciello, Mario <Mario_Limonciello@Dell.com>

> Cc: dvhart@infradead.org; LKML <linux-kernel@vger.kernel.org>; Platform Driver

> <platform-driver-x86@vger.kernel.org>; Andy Lutomirski <luto@kernel.org>;

> quasisec@google.com; Pali Rohár <pali.rohar@gmail.com>; Rafael J. Wysocki

> <rjw@rjwysocki.net>; mjg59@google.com; Christoph Hellwig <hch@lst.de>;

> Greg KH <greg@kroah.com>

> Subject: Re: [PATCH v4 05/14] platform/x86: dell-wmi-descriptor: split WMI

> descriptor into it's own driver

> 

> On Thu, Oct 5, 2017 at 1:48 AM, Mario Limonciello

> <mario.limonciello@dell.com> wrote:

> > All communication on individual GUIDs should occur in separate drivers.

> > Allowing a driver to communicate with the bus to another GUID is just

> > a hack that discourages drivers to adopt the bus model.

> >

> > The information found from the WMI descriptor driver is now exported

> > for use by other drivers.

> 

> > +       priv = list_first_entry_or_null(&wmi_list,

> > +                                       struct descriptor_priv,

> > +                                       list);

> 

> > +       priv = list_first_entry_or_null(&wmi_list,

> > +                                       struct descriptor_priv,

> > +                                       list);

> 

> static inline ...to_priv(...)

> {

>  return list_first_entry_...();

> }

> 

> > +       list_add_tail(&priv->list, &wmi_list);

> 

> > +       list_del(&priv->list);

> 

> Do these need locking?


Yeah this seems like a good idea.  I'll add it in.

> 

> > +bool dell_wmi_get_interface_version(u32 *version);

> > +bool dell_wmi_get_size(u32 *size);

> 

> This might need stubs when module is not selected (when functionality

> is optional if it would be the case), otherwise all users should

> select it explicitly.


Per Darren's other threads I'm adjusting Kconfig to make sure this module
is selected.  It's realistically not optional when using these others.
Darren Hart Oct. 5, 2017, 5:22 p.m. UTC | #10
On Thu, Oct 05, 2017 at 02:47:15PM +0000, Mario.Limonciello@dell.com wrote:
> > >
> > > So I believe it should be a mandatory runtime dependency due to needing
> > > the symbol dell_wmi_get_interface_version.  Depmod should be handling
> > > this then no?
> > 
> > This was nagging me all night, and I was thinking the last time I had to
> > use this it was indeed a runtime dependency. Sorry for the noise on
> > this.
> > 
> > The kconfig needs to be setup such that dell-wmi-descriptor cannot be a
> > module if the dependent drivers are modules.
> > 
> > --
> > Darren Hart
> > VMware Open Source Technology Center
> 
> Even if the others are modules shouldn't module ordering from depmod still DTRT?
> You still won't be able to load dell-wmi.ko until dell-wmi-descriptor.ko was loaded.
> 

I worded that wrong *facepalm*, let me try again...

The kconfig needs to be setup such that dell-wmi-descriptor cannot be a
module if the dependent drivers are built-in.
Limonciello, Mario Oct. 5, 2017, 5:32 p.m. UTC | #11
> -----Original Message-----
> From: Darren Hart [mailto:dvhart@infradead.org]
> Sent: Thursday, October 5, 2017 12:22 PM
> To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> Cc: andy.shevchenko@gmail.com; linux-kernel@vger.kernel.org; platform-
> driver-x86@vger.kernel.org; luto@kernel.org; quasisec@google.com;
> pali.rohar@gmail.com; rjw@rjwysocki.net; mjg59@google.com; hch@lst.de;
> greg@kroah.com
> Subject: Re: [PATCH v4 05/14] platform/x86: dell-wmi-descriptor: split WMI
> descriptor into it's own driver
> 
> On Thu, Oct 05, 2017 at 02:47:15PM +0000, Mario.Limonciello@dell.com wrote:
> > > >
> > > > So I believe it should be a mandatory runtime dependency due to needing
> > > > the symbol dell_wmi_get_interface_version.  Depmod should be handling
> > > > this then no?
> > >
> > > This was nagging me all night, and I was thinking the last time I had to
> > > use this it was indeed a runtime dependency. Sorry for the noise on
> > > this.
> > >
> > > The kconfig needs to be setup such that dell-wmi-descriptor cannot be a
> > > module if the dependent drivers are modules.
> > >
> > > --
> > > Darren Hart
> > > VMware Open Source Technology Center
> >
> > Even if the others are modules shouldn't module ordering from depmod still
> DTRT?
> > You still won't be able to load dell-wmi.ko until dell-wmi-descriptor.ko was
> loaded.
> >
> 
> I worded that wrong *facepalm*, let me try again...
> 
> The kconfig needs to be setup such that dell-wmi-descriptor cannot be a
> module if the dependent drivers are built-in.
> 

OK got it.  I've got Kconfig adjusted for this.  Unlike DELL_SMBIOS, 
DELL_WMI_DESCRIPTOR could still be used on it's own.
diff mbox

Patch

diff --git a/MAINTAINERS b/MAINTAINERS
index 08b96f77f618..659dbeec4191 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4002,6 +4002,11 @@  M:	Pali Rohár <pali.rohar@gmail.com>
 S:	Maintained
 F:	drivers/platform/x86/dell-wmi.c
 
+DELL WMI DESCRIPTOR DRIVER
+M:	Mario Limonciello <mario.limonciello@dell.com>
+S:	Maintained
+F:	drivers/platform/x86/dell-wmi-descriptor.c
+
 DELTA ST MEDIA DRIVER
 M:	Hugues Fruchet <hugues.fruchet@st.com>
 L:	linux-media@vger.kernel.org
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 1f7959ff055c..bc347c326d87 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -121,6 +121,7 @@  config DELL_WMI
 	depends on DMI
 	depends on INPUT
 	depends on ACPI_VIDEO || ACPI_VIDEO = n
+	depends on DELL_WMI_DESCRIPTOR
 	select DELL_SMBIOS
 	select INPUT_SPARSEKMAP
 	---help---
@@ -129,6 +130,17 @@  config DELL_WMI
 	  To compile this driver as a module, choose M here: the module will
 	  be called dell-wmi.
 
+config DELL_WMI_DESCRIPTOR
+	tristate "Dell WMI descriptor"
+	depends on ACPI_WMI
+	default ACPI_WMI
+	---help---
+	  Say Y here if you want to be able to read the format of WMI
+	  communications on some Dell laptops, desktops and IoT gateways.
+
+	  To compile this driver as a module, choose M here: the module will
+	  be called dell-wmi-descriptor.
+
 config DELL_WMI_AIO
 	tristate "WMI Hotkeys for Dell All-In-One series"
 	depends on ACPI_WMI
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index 2b315d0df3b7..8636f5d3424f 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -14,6 +14,7 @@  obj-$(CONFIG_COMPAL_LAPTOP)	+= compal-laptop.o
 obj-$(CONFIG_DELL_SMBIOS)	+= dell-smbios.o
 obj-$(CONFIG_DELL_LAPTOP)	+= dell-laptop.o
 obj-$(CONFIG_DELL_WMI)		+= dell-wmi.o
+obj-$(CONFIG_DELL_WMI_DESCRIPTOR)	+= dell-wmi-descriptor.o
 obj-$(CONFIG_DELL_WMI_AIO)	+= dell-wmi-aio.o
 obj-$(CONFIG_DELL_WMI_LED)	+= dell-wmi-led.o
 obj-$(CONFIG_DELL_SMO8800)	+= dell-smo8800.o
diff --git a/drivers/platform/x86/dell-wmi-descriptor.c b/drivers/platform/x86/dell-wmi-descriptor.c
new file mode 100644
index 000000000000..5c2bdda11916
--- /dev/null
+++ b/drivers/platform/x86/dell-wmi-descriptor.c
@@ -0,0 +1,162 @@ 
+/*
+ * Dell WMI descriptor driver
+ *
+ * Copyright (C) 2017 Dell Inc. All Rights Reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/acpi.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/wmi.h>
+#include "dell-wmi-descriptor.h"
+
+#define DELL_WMI_DESCRIPTOR_GUID "8D9DDCBC-A997-11DA-B012-B622A1EF5492"
+
+struct descriptor_priv {
+	struct list_head list;
+	u32 interface_version;
+	u32 size;
+};
+static LIST_HEAD(wmi_list);
+
+bool dell_wmi_get_interface_version(u32 *version)
+{
+	struct descriptor_priv *priv;
+
+	priv = list_first_entry_or_null(&wmi_list,
+					struct descriptor_priv,
+					list);
+	if (!priv)
+		return false;
+	*version = priv->interface_version;
+	return true;
+}
+EXPORT_SYMBOL_GPL(dell_wmi_get_interface_version);
+
+bool dell_wmi_get_size(u32 *size)
+{
+	struct descriptor_priv *priv;
+
+	priv = list_first_entry_or_null(&wmi_list,
+					struct descriptor_priv,
+					list);
+	if (!priv)
+		return false;
+	*size = priv->size;
+	return true;
+}
+EXPORT_SYMBOL_GPL(dell_wmi_get_size);
+
+/*
+ * Descriptor buffer is 128 byte long and contains:
+ *
+ *       Name             Offset  Length  Value
+ * Vendor Signature          0       4    "DELL"
+ * Object Signature          4       4    " WMI"
+ * WMI Interface Version     8       4    <version>
+ * WMI buffer length        12       4    4096 or 32768
+ */
+static int dell_wmi_descriptor_probe(struct wmi_device *wdev)
+{
+	union acpi_object *obj = NULL;
+	struct descriptor_priv *priv;
+	u32 *buffer;
+	int ret;
+
+	obj = wmidev_block_query(wdev, 0);
+	if (!obj) {
+		dev_err(&wdev->dev, "failed to read Dell WMI descriptor\n");
+		ret = -EIO;
+		goto out;
+	}
+
+	if (obj->type != ACPI_TYPE_BUFFER) {
+		dev_err(&wdev->dev, "Dell descriptor has wrong type\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/* Although it's not technically a failure, this would lead to
+	 * unexpected behavior
+	 */
+	if (obj->buffer.length != 128) {
+		dev_err(&wdev->dev,
+			"Dell descriptor buffer has unexpected length (%d)\n",
+			obj->buffer.length);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	buffer = (u32 *)obj->buffer.pointer;
+
+	if (strncmp(obj->string.pointer, "DELL WMI", 8) != 0) {
+		dev_err(&wdev->dev, "Dell descriptor buffer has invalid signature (%8ph)\n",
+			buffer);
+		ret = -EINVAL;
+		goto out;
+	}
+	if (buffer[2] != 0 && buffer[2] != 1)
+		dev_warn(&wdev->dev, "Dell descriptor buffer has unknown version (%u)\n",
+			buffer[2]);
+
+	if (buffer[3] != 4096 && buffer[3] != 32768)
+		dev_warn(&wdev->dev, "Dell descriptor buffer has unexpected buffer length (%u)\n",
+			buffer[3]);
+
+	priv = devm_kzalloc(&wdev->dev, sizeof(struct descriptor_priv),
+	GFP_KERNEL);
+
+	priv->interface_version = buffer[2];
+	priv->size = buffer[3];
+	ret = 0;
+	dev_set_drvdata(&wdev->dev, priv);
+	list_add_tail(&priv->list, &wmi_list);
+
+	/* remove me */
+	dev_info(&wdev->dev, "Detected Dell WMI interface version %u and buffer size %u\n",
+		priv->interface_version, priv->size);
+
+out:
+	kfree(obj);
+	return ret;
+}
+
+static int dell_wmi_descriptor_remove(struct wmi_device *wdev)
+{
+	struct descriptor_priv *priv = dev_get_drvdata(&wdev->dev);
+
+	list_del(&priv->list);
+	return 0;
+}
+
+static const struct wmi_device_id dell_wmi_descriptor_id_table[] = {
+	{ .guid_string = DELL_WMI_DESCRIPTOR_GUID },
+	{ },
+};
+
+static struct wmi_driver dell_wmi_descriptor_driver = {
+	.driver = {
+		.name = "dell-wmi-descriptor",
+	},
+	.probe = dell_wmi_descriptor_probe,
+	.remove = dell_wmi_descriptor_remove,
+	.id_table = dell_wmi_descriptor_id_table,
+};
+
+module_wmi_driver(dell_wmi_descriptor_driver);
+
+MODULE_ALIAS("wmi:" DELL_WMI_DESCRIPTOR_GUID);
+MODULE_AUTHOR("Mario Limonciello <mario.limonciello@dell.com>");
+MODULE_DESCRIPTION("Dell WMI descriptor driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/platform/x86/dell-wmi-descriptor.h b/drivers/platform/x86/dell-wmi-descriptor.h
new file mode 100644
index 000000000000..3e652c6da034
--- /dev/null
+++ b/drivers/platform/x86/dell-wmi-descriptor.h
@@ -0,0 +1,18 @@ 
+/*
+ *
+ *  Copyright (c) 2017 Dell Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#ifndef _DELL_WMI_DESCRIPTOR_H_
+#define _DELL_WMI_DESCRIPTOR_H_
+
+#include <linux/wmi.h>
+
+bool dell_wmi_get_interface_version(u32 *version);
+bool dell_wmi_get_size(u32 *size);
+
+#endif
diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c
index 1366bccdf275..90d7e8e55e9b 100644
--- a/drivers/platform/x86/dell-wmi.c
+++ b/drivers/platform/x86/dell-wmi.c
@@ -39,6 +39,7 @@ 
 #include <linux/wmi.h>
 #include <acpi/video.h>
 #include "dell-smbios.h"
+#include "dell-wmi-descriptor.h"
 
 MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>");
 MODULE_AUTHOR("Pali Rohár <pali.rohar@gmail.com>");
@@ -46,7 +47,6 @@  MODULE_DESCRIPTION("Dell laptop WMI hotkeys driver");
 MODULE_LICENSE("GPL");
 
 #define DELL_EVENT_GUID "9DBB5994-A997-11DA-B012-B622A1EF5492"
-#define DELL_DESCRIPTOR_GUID "8D9DDCBC-A997-11DA-B012-B622A1EF5492"
 
 static bool wmi_requires_smbios_request;
 
@@ -54,7 +54,6 @@  MODULE_ALIAS("wmi:"DELL_EVENT_GUID);
 
 struct dell_wmi_priv {
 	struct input_dev *input_dev;
-	u32 interface_version;
 };
 
 static int __init dmi_matched(const struct dmi_system_id *dmi)
@@ -347,9 +346,9 @@  static void dell_wmi_process_key(struct wmi_device *wdev, int type, int code)
 static void dell_wmi_notify(struct wmi_device *wdev,
 			    union acpi_object *obj)
 {
-	struct dell_wmi_priv *priv = dev_get_drvdata(&wdev->dev);
 	u16 *buffer_entry, *buffer_end;
 	acpi_size buffer_size;
+	u32 interface_version;
 	int len, i;
 
 	if (obj->type != ACPI_TYPE_BUFFER) {
@@ -376,7 +375,11 @@  static void dell_wmi_notify(struct wmi_device *wdev,
 	 * So to prevent reading garbage from buffer we will process only first
 	 * one event on devices with WMI interface version 0.
 	 */
-	if (priv->interface_version == 0 && buffer_entry < buffer_end)
+	if (!dell_wmi_get_interface_version(&interface_version)) {
+		pr_warn("WMI descriptor driver not ready or unavailable");
+		return;
+	}
+	if (interface_version == 0 && buffer_entry < buffer_end)
 		if (buffer_end > buffer_entry + buffer_entry[0] + 1)
 			buffer_end = buffer_entry + buffer_entry[0] + 1;
 
@@ -617,78 +620,6 @@  static void dell_wmi_input_destroy(struct wmi_device *wdev)
 	input_unregister_device(priv->input_dev);
 }
 
-/*
- * Descriptor buffer is 128 byte long and contains:
- *
- *       Name             Offset  Length  Value
- * Vendor Signature          0       4    "DELL"
- * Object Signature          4       4    " WMI"
- * WMI Interface Version     8       4    <version>
- * WMI buffer length        12       4    4096 or 32768
- */
-static int dell_wmi_check_descriptor_buffer(struct wmi_device *wdev)
-{
-	struct dell_wmi_priv *priv = dev_get_drvdata(&wdev->dev);
-	union acpi_object *obj = NULL;
-	struct wmi_device *desc_dev;
-	u32 *buffer;
-	int ret;
-
-	desc_dev = wmidev_get_other_guid(wdev, DELL_DESCRIPTOR_GUID);
-	if (!desc_dev) {
-		dev_err(&wdev->dev, "Dell WMI descriptor does not exist\n");
-		return -ENODEV;
-	}
-
-	obj = wmidev_block_query(desc_dev, 0);
-	if (!obj) {
-		dev_err(&wdev->dev, "failed to read Dell WMI descriptor\n");
-		ret = -EIO;
-		goto out;
-	}
-
-	if (obj->type != ACPI_TYPE_BUFFER) {
-		dev_err(&wdev->dev, "Dell descriptor has wrong type\n");
-		ret = -EINVAL;
-		goto out;
-	}
-
-	if (obj->buffer.length != 128) {
-		dev_err(&wdev->dev,
-			"Dell descriptor buffer has invalid length (%d)\n",
-			obj->buffer.length);
-		ret = -EINVAL;
-		goto out;
-	}
-
-	buffer = (u32 *)obj->buffer.pointer;
-
-	if (strncmp(obj->string.pointer, "DELL WMI", 8) != 0) {
-		dev_err(&wdev->dev, "Dell descriptor buffer has invalid signature (%8ph)\n",
-			buffer);
-		ret = -EINVAL;
-		goto out;
-	}
-	if (buffer[2] != 0 && buffer[2] != 1)
-		dev_warn(&wdev->dev, "Dell descriptor buffer has unknown version (%u)\n",
-			buffer[2]);
-
-	if (desc_buffer[3] != 4096 && desc_buffer[3] != 32768)
-		dev_warn(&wdev->dev, "Dell descriptor buffer has invalid buffer length (%u)\n",
-			buffer[3]);
-
-	priv->interface_version = buffer[2];
-	ret = 0;
-
-	dev_info(&wdev->dev, "Detected Dell WMI interface version %u\n",
-		priv->interface_version);
-
-out:
-	kfree(obj);
-	put_device(&desc_dev->dev);
-	return ret;
-}
-
 /*
  * According to Dell SMBIOS documentation:
  *
@@ -724,7 +655,6 @@  static int dell_wmi_events_set_enabled(bool enable)
 static int dell_wmi_probe(struct wmi_device *wdev)
 {
 	struct dell_wmi_priv *priv;
-	int err;
 
 	priv = devm_kzalloc(
 		&wdev->dev, sizeof(struct dell_wmi_priv), GFP_KERNEL);
@@ -732,10 +662,6 @@  static int dell_wmi_probe(struct wmi_device *wdev)
 		return -ENOMEM;
 	dev_set_drvdata(&wdev->dev, priv);
 
-	err = dell_wmi_check_descriptor_buffer(wdev);
-	if (err)
-		return err;
-
 	return dell_wmi_input_setup(wdev);
 }