Merge tag 'platform-drivers-x86-v4.15-2' of git://git.infradead.org/linux-platform...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 24 Nov 2017 07:14:30 +0000 (21:14 -1000)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 24 Nov 2017 07:14:30 +0000 (21:14 -1000)
Pull x86 platform driver fixes from Darren Hart:
 "Fix two issues resulting from the dell-smbios refactoring and
  introduction of the dell-smbios-wmi dispatcher.

  The first ensures a proper error code is returned when kzalloc fails.

  The second avoids an issue in older Dell BIOS implementations which
  would fail if the more complex calls were made by limiting those
  platforms to the simple calls such as those used by the existing
  dell-laptop and dell-wmi drivers, preserving their functionality prior
  to the addition of the dell-smbios-wmi dispatcher"

* tag 'platform-drivers-x86-v4.15-2' of git://git.infradead.org/linux-platform-drivers-x86:
  platform/x86: dell-laptop: fix error return code in dell_init()
  platform/x86: dell-smbios-wmi: Disable userspace interface if missing hotfix

drivers/platform/x86/dell-laptop.c
drivers/platform/x86/dell-smbios-wmi.c
drivers/platform/x86/dell-wmi-descriptor.c
drivers/platform/x86/dell-wmi-descriptor.h

index 2d704361f67284304b17a781ea8b45da617211be..bf897b1832b188c24a92f33fdf74b33b25aeac43 100644 (file)
@@ -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();
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