On Thursday 21 September 2017 08:57:09 Mario Limonciello wrote:
> The driver currently uses an SMI interface which grants direct access
> to physical memory to the platform via a pointer.
> 
> Changing this to operate over WMI-ACPI will use an ACPI OperationRegion
> for a buffer of data storage when platform calls are performed.
> 
> This is a safer approach to use in kernel drivers as the platform will
> only have access to that OperationRegion.

In my opinion direct access is safer then using ACPI wrapper for same
functionality.

Anyway, this change would break support for laptops without ACPI-WMI
functionality. IIRC I read in some Dell ACPI-WMI documentation that Dell
SMM via ACPI-WMI is not supported on all machines (probably older
machines) and it is needed to check some vendor bit in DMI data if Dell
SMM ACPI-WMI is really supported.

In linux kernel we do not want to remove support for older machines,
just because machines with new firmware can use also different new
communication method/protocol.

> As a result, this change removes the dependency on this driver on the
> dcdbas kernel module.
> 
> Signed-off-by: Mario Limonciello <[email protected]>
> ---
>  drivers/platform/x86/Kconfig       |  8 ++--
>  drivers/platform/x86/dell-smbios.c | 76 
> ++++++++++++++++++++++++++------------
>  drivers/platform/x86/dell-smbios.h | 11 +++---
>  3 files changed, 63 insertions(+), 32 deletions(-)
> 
> diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
> index 9e52f05daa2e..81d61c0f4ef8 100644
> --- a/drivers/platform/x86/Kconfig
> +++ b/drivers/platform/x86/Kconfig
> @@ -92,13 +92,13 @@ config ASUS_LAPTOP
>         If you have an ACPI-compatible ASUS laptop, say Y or M here.
>  
>  config DELL_SMBIOS
> -     tristate
> -     select DCDBAS
> +     tristate "Dell WMI SMBIOS calling interface"
> +     depends on ACPI_WMI
>       ---help---
>       This module provides common functions for kernel modules using
> -     Dell SMBIOS.
> +     Dell SMBIOS over ACPI-WMI.
>  
> -     If you have a Dell laptop, say Y or M here.
> +     If you have a Dell computer, say Y or M here.
>  
>  config DELL_LAPTOP
>       tristate "Dell Laptop Extras"
> diff --git a/drivers/platform/x86/dell-smbios.c 
> b/drivers/platform/x86/dell-smbios.c
> index e9b1ca07c872..c06262a89169 100644
> --- a/drivers/platform/x86/dell-smbios.c
> +++ b/drivers/platform/x86/dell-smbios.c
> @@ -4,6 +4,7 @@
>   *  Copyright (c) Red Hat <[email protected]>
>   *  Copyright (c) 2014 Gabriele Mazzotta <[email protected]>
>   *  Copyright (c) 2014 Pali Rohár <[email protected]>
> + *  Copyright (c) 2017 Dell Inc.
>   *
>   *  Based on documentation in the libsmbios package:
>   *  Copyright (C) 2005-2014 Dell Inc.
> @@ -18,13 +19,12 @@
>  #include <linux/module.h>
>  #include <linux/dmi.h>
>  #include <linux/err.h>
> -#include <linux/gfp.h>
>  #include <linux/mutex.h>
> -#include <linux/slab.h>
> -#include <linux/io.h>
> -#include "../../firmware/dcdbas.h"
> +#include <linux/wmi.h>
>  #include "dell-smbios.h"
>  
> +#define DELL_WMI_SMBIOS_GUID "A80593CE-A997-11DA-B012-B622A1EF5492"
> +
>  struct calling_interface_structure {
>       struct dmi_header header;
>       u16 cmdIOAddress;
> @@ -76,20 +76,39 @@ void dell_smbios_release_buffer(void)
>  }
>  EXPORT_SYMBOL_GPL(dell_smbios_release_buffer);
>  
> -void dell_smbios_send_request(int class, int select)
> +int run_wmi_smbios_call(struct calling_interface_buffer *buffer)
>  {
> -     struct smi_cmd command;
> +     struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
> +     struct acpi_buffer input;
> +     union acpi_object *obj;
> +     acpi_status status;
> +
> +     input.length = sizeof(struct calling_interface_buffer);
> +     input.pointer = buffer;
> +
> +     status = wmi_evaluate_method(DELL_WMI_SMBIOS_GUID,
> +                                  0, 1, &input, &output);
> +     if (ACPI_FAILURE(status)) {
> +             pr_err("%x/%x [%x,%x,%x,%x] call failed\n",
> +                     buffer->class, buffer->select, buffer->input[0],
> +                     buffer->input[1], buffer->input[2], buffer->input[3]);
> +                     return -EIO;
> +     }
> +     obj = (union acpi_object *)output.pointer;
> +     if (obj->type != ACPI_TYPE_BUFFER) {
> +             pr_err("invalid type : %d\n", obj->type);
> +             return -EIO;
> +     }
> +     memcpy(buffer, obj->buffer.pointer, input.length);
>  
> -     command.magic = SMI_CMD_MAGIC;
> -     command.command_address = da_command_address;
> -     command.command_code = da_command_code;
> -     command.ebx = virt_to_phys(buffer);
> -     command.ecx = 0x42534931;
> +     return 0;
> +}
>  
> +void dell_smbios_send_request(int class, int select)
> +{
>       buffer->class = class;
>       buffer->select = select;
> -
> -     dcdbas_smi_request(&command);
> +     run_wmi_smbios_call(buffer);
>  }
>  EXPORT_SYMBOL_GPL(dell_smbios_send_request);
>  
> @@ -170,7 +189,7 @@ static void __init find_tokens(const struct dmi_header 
> *dm, void *dummy)
>       }
>  }
>  
> -static int __init dell_smbios_init(void)
> +static int dell_smbios_probe(struct wmi_device *wdev)
>  {
>       int ret;
>  
> @@ -181,11 +200,7 @@ static int __init dell_smbios_init(void)
>               return -ENODEV;
>       }
>  
> -     /*
> -      * Allocate buffer below 4GB for SMI data--only 32-bit physical addr
> -      * is passed to SMI handler.
> -      */
> -     buffer = (void *)__get_free_page(GFP_KERNEL | GFP_DMA32);
> +     buffer = (void *)__get_free_page(GFP_KERNEL);
>       if (!buffer) {
>               ret = -ENOMEM;
>               goto fail_buffer;
> @@ -198,17 +213,32 @@ static int __init dell_smbios_init(void)
>       return ret;
>  }
>  
> -static void __exit dell_smbios_exit(void)
> +static int dell_smbios_remove(struct wmi_device *wdev)
>  {
>       kfree(da_tokens);
>       free_page((unsigned long)buffer);
> +     return 0;
>  }
>  
> -subsys_initcall(dell_smbios_init);
> -module_exit(dell_smbios_exit);
> +static const struct wmi_device_id dell_smbios_id_table[] = {
> +     { .guid_string = DELL_WMI_SMBIOS_GUID },
> +     { },
> +};
> +
> +static struct wmi_driver dell_smbios_driver = {
> +     .driver = {
> +             .name = "dell-smbios",
> +     },
> +     .probe = dell_smbios_probe,
> +     .remove = dell_smbios_remove,
> +     .id_table = dell_smbios_id_table,
> +};
> +module_wmi_driver(dell_smbios_driver);
> +
>  
>  MODULE_AUTHOR("Matthew Garrett <[email protected]>");
>  MODULE_AUTHOR("Gabriele Mazzotta <[email protected]>");
>  MODULE_AUTHOR("Pali Rohár <[email protected]>");
> -MODULE_DESCRIPTION("Common functions for kernel modules using Dell SMBIOS");
> +MODULE_AUTHOR("Mario Limonciello <[email protected]>");
> +MODULE_DESCRIPTION("Common functions for kernel modules using Dell SMBIOS 
> over WMI");
>  MODULE_LICENSE("GPL");
> diff --git a/drivers/platform/x86/dell-smbios.h 
> b/drivers/platform/x86/dell-smbios.h
> index 45cbc2292cd3..e1e29697b362 100644
> --- a/drivers/platform/x86/dell-smbios.h
> +++ b/drivers/platform/x86/dell-smbios.h
> @@ -4,6 +4,7 @@
>   *  Copyright (c) Red Hat <[email protected]>
>   *  Copyright (c) 2014 Gabriele Mazzotta <[email protected]>
>   *  Copyright (c) 2014 Pali Rohár <[email protected]>
> + *  Copyright (c) 2017 Dell Inc.
>   *
>   *  Based on documentation in the libsmbios package:
>   *  Copyright (C) 2005-2014 Dell Inc.
> @@ -18,14 +19,14 @@
>  
>  struct notifier_block;
>  
> -/* This structure will be modified by the firmware when we enter
> - * system management mode, hence the volatiles */
> -
>  struct calling_interface_buffer {
>       u16 class;
>       u16 select;
> -     volatile u32 input[4];
> -     volatile u32 output[4];
> +     u32 input[4];
> +     u32 output[4];
> +     u32 argattrib;
> +     u32 blength;
> +     u8 data[4052];
>  } __packed;
>  
>  struct calling_interface_token {

-- 
Pali Rohár
[email protected]

Reply via email to