]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
platform/x86: dell-smbios-wmi: Disable userspace interface if missing hotfix
authorMario Limonciello <mario.limonciello@dell.com>
Fri, 17 Nov 2017 04:13:12 +0000 (22:13 -0600)
committerDarren Hart (VMware) <dvhart@infradead.org>
Mon, 20 Nov 2017 20:38:43 +0000 (12:38 -0800)
The Dell SMBIOS WMI interface will fail for some more complex calls unless
a WMI hotfix has been included.  Most platforms have this fix available in
a maintenance BIOS release.  In the case the driver is loaded on a
platform without this fix, disable the userspace interface.

A hotfix indicator is present in the dell-wmi-descriptor that represents
whether or not more complex calls will work properly.

"Simple" calls such as those used by dell-laptop and dell-wmi will continue
to work properly so dell-smbios-wmi should not be blocked from binding and
being used as the dell-smbios dispatcher.

Suggested-by: Girish Prakash <girish.prakash@dell.com>
Signed-off-by: Mario Limonciello <mario.limonciello@dell.com>
Signed-off-by: Darren Hart (VMware) <dvhart@infradead.org>
drivers/platform/x86/dell-smbios-wmi.c
drivers/platform/x86/dell-wmi-descriptor.c
drivers/platform/x86/dell-wmi-descriptor.h

index 0cab1f9c35afd11d20694efa2e6974d9fac03dd2..609557aa58684375b7534a39e21f9fe9eadd97e6 100644 (file)
@@ -147,7 +147,10 @@ fail_smbios_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);
index 4dfef1f5348117eac79ab732c08087e5ba74df84..072821aa47fc20661c6b59abad5795a4ad98f199 100644 (file)
@@ -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);
index 1e8cb96ffd78ec8778cf394276b474c1533b77a9..a6123a4d06a787238abb80121c66d6aa7b3ff211 100644 (file)
@@ -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