diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index 2d704361f67284304b17a781ea8b45da617211be..bf897b1832b188c24a92f33fdf74b33b25aeac43 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c @@ -2074,8 +2074,10 @@ static int __init dell_init(void) goto fail_platform_device2; buffer = kzalloc(sizeof(struct calling_interface_buffer), GFP_KERNEL); - if (!buffer) + if (!buffer) { + ret = -ENOMEM; goto fail_buffer; + } ret = dell_setup_rfkill(); diff --git a/drivers/platform/x86/dell-smbios-wmi.c b/drivers/platform/x86/dell-smbios-wmi.c index 0cab1f9c35afd11d20694efa2e6974d9fac03dd2..609557aa58684375b7534a39e21f9fe9eadd97e6 100644 --- a/drivers/platform/x86/dell-smbios-wmi.c +++ b/drivers/platform/x86/dell-smbios-wmi.c @@ -147,7 +147,10 @@ static long dell_smbios_wmi_filter(struct wmi_device *wdev, unsigned int cmd, static int dell_smbios_wmi_probe(struct wmi_device *wdev) { + struct wmi_driver *wdriver = + container_of(wdev->dev.driver, struct wmi_driver, driver); struct wmi_smbios_priv *priv; + u32 hotfix; int count; int ret; @@ -164,6 +167,16 @@ static int dell_smbios_wmi_probe(struct wmi_device *wdev) if (!dell_wmi_get_size(&priv->req_buf_size)) return -EPROBE_DEFER; + /* some SMBIOS calls fail unless BIOS contains hotfix */ + if (!dell_wmi_get_hotfix(&hotfix)) + return -EPROBE_DEFER; + if (!hotfix) { + dev_warn(&wdev->dev, + "WMI SMBIOS userspace interface not supported(%u), try upgrading to a newer BIOS\n", + hotfix); + wdriver->filter_callback = NULL; + } + /* add in the length object we will use internally with ioctl */ priv->req_buf_size += sizeof(u64); ret = set_required_buffer_size(wdev, priv->req_buf_size); diff --git a/drivers/platform/x86/dell-wmi-descriptor.c b/drivers/platform/x86/dell-wmi-descriptor.c index 4dfef1f5348117eac79ab732c08087e5ba74df84..072821aa47fc20661c6b59abad5795a4ad98f199 100644 --- a/drivers/platform/x86/dell-wmi-descriptor.c +++ b/drivers/platform/x86/dell-wmi-descriptor.c @@ -27,6 +27,7 @@ struct descriptor_priv { struct list_head list; u32 interface_version; u32 size; + u32 hotfix; }; static int descriptor_valid = -EPROBE_DEFER; static LIST_HEAD(wmi_list); @@ -77,6 +78,24 @@ bool dell_wmi_get_size(u32 *size) } EXPORT_SYMBOL_GPL(dell_wmi_get_size); +bool dell_wmi_get_hotfix(u32 *hotfix) +{ + struct descriptor_priv *priv; + bool ret = false; + + mutex_lock(&list_mutex); + priv = list_first_entry_or_null(&wmi_list, + struct descriptor_priv, + list); + if (priv) { + *hotfix = priv->hotfix; + ret = true; + } + mutex_unlock(&list_mutex); + return ret; +} +EXPORT_SYMBOL_GPL(dell_wmi_get_hotfix); + /* * Descriptor buffer is 128 byte long and contains: * @@ -85,6 +104,7 @@ EXPORT_SYMBOL_GPL(dell_wmi_get_size); * Object Signature 4 4 " WMI" * WMI Interface Version 8 4 <version> * WMI buffer length 12 4 <length> + * WMI hotfix number 16 4 <hotfix> */ static int dell_wmi_descriptor_probe(struct wmi_device *wdev) { @@ -144,15 +164,17 @@ static int dell_wmi_descriptor_probe(struct wmi_device *wdev) priv->interface_version = buffer[2]; priv->size = buffer[3]; + priv->hotfix = buffer[4]; ret = 0; dev_set_drvdata(&wdev->dev, priv); mutex_lock(&list_mutex); list_add_tail(&priv->list, &wmi_list); mutex_unlock(&list_mutex); - dev_dbg(&wdev->dev, "Detected Dell WMI interface version %lu and buffer size %lu\n", + dev_dbg(&wdev->dev, "Detected Dell WMI interface version %lu, buffer size %lu, hotfix %lu\n", (unsigned long) priv->interface_version, - (unsigned long) priv->size); + (unsigned long) priv->size, + (unsigned long) priv->hotfix); out: kfree(obj); diff --git a/drivers/platform/x86/dell-wmi-descriptor.h b/drivers/platform/x86/dell-wmi-descriptor.h index 1e8cb96ffd78ec8778cf394276b474c1533b77a9..a6123a4d06a787238abb80121c66d6aa7b3ff211 100644 --- a/drivers/platform/x86/dell-wmi-descriptor.h +++ b/drivers/platform/x86/dell-wmi-descriptor.h @@ -23,5 +23,6 @@ int dell_wmi_get_descriptor_valid(void); bool dell_wmi_get_interface_version(u32 *version); bool dell_wmi_get_size(u32 *size); +bool dell_wmi_get_hotfix(u32 *hotfix); #endif