OSDN Git Service

platform/x86: sony-laptop: SNC calls should handle BUFFER types
authorMattia Dongili <malattia@linux.it>
Fri, 8 May 2020 00:14:04 +0000 (09:14 +0900)
committerAndy Shevchenko <andriy.shevchenko@linux.intel.com>
Tue, 12 May 2020 14:27:11 +0000 (17:27 +0300)
After commit 6d232b29cfce ("ACPICA: Dispatcher: always generate buffer
objects for ASL create_field() operator") ACPICA creates buffers even
when new fields are small enough to fit into an integer.
Many SNC calls counted on the old behaviour.
Since sony-laptop already handles the INTEGER/BUFFER case in
sony_nc_buffer_call, switch sony_nc_int_call to use its more generic
function instead.

Fixes: 6d232b29cfce ("ACPICA: Dispatcher: always generate buffer objects for ASL create_field() operator")
Reported-by: Dominik Mierzejewski <dominik@greysector.net>
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=207491
Reported-by: William Bader <williambader@hotmail.com>
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1830150
Signed-off-by: Mattia Dongili <malattia@linux.it>
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
drivers/platform/x86/sony-laptop.c

index 51309f7..6932cd1 100644 (file)
@@ -757,33 +757,6 @@ static union acpi_object *__call_snc_method(acpi_handle handle, char *method,
        return result;
 }
 
-static int sony_nc_int_call(acpi_handle handle, char *name, int *value,
-               int *result)
-{
-       union acpi_object *object = NULL;
-       if (value) {
-               u64 v = *value;
-               object = __call_snc_method(handle, name, &v);
-       } else
-               object = __call_snc_method(handle, name, NULL);
-
-       if (!object)
-               return -EINVAL;
-
-       if (object->type != ACPI_TYPE_INTEGER) {
-               pr_warn("Invalid acpi_object: expected 0x%x got 0x%x\n",
-                               ACPI_TYPE_INTEGER, object->type);
-               kfree(object);
-               return -EINVAL;
-       }
-
-       if (result)
-               *result = object->integer.value;
-
-       kfree(object);
-       return 0;
-}
-
 #define MIN(a, b)      (a > b ? b : a)
 static int sony_nc_buffer_call(acpi_handle handle, char *name, u64 *value,
                void *buffer, size_t buflen)
@@ -795,17 +768,20 @@ static int sony_nc_buffer_call(acpi_handle handle, char *name, u64 *value,
        if (!object)
                return -EINVAL;
 
-       if (object->type == ACPI_TYPE_BUFFER) {
+       if (!buffer) {
+               /* do nothing */
+       } else if (object->type == ACPI_TYPE_BUFFER) {
                len = MIN(buflen, object->buffer.length);
+               memset(buffer, 0, buflen);
                memcpy(buffer, object->buffer.pointer, len);
 
        } else if (object->type == ACPI_TYPE_INTEGER) {
                len = MIN(buflen, sizeof(object->integer.value));
+               memset(buffer, 0, buflen);
                memcpy(buffer, &object->integer.value, len);
 
        } else {
-               pr_warn("Invalid acpi_object: expected 0x%x got 0x%x\n",
-                               ACPI_TYPE_BUFFER, object->type);
+               pr_warn("Unexpected acpi_object: 0x%x\n", object->type);
                ret = -EINVAL;
        }
 
@@ -813,6 +789,23 @@ static int sony_nc_buffer_call(acpi_handle handle, char *name, u64 *value,
        return ret;
 }
 
+static int sony_nc_int_call(acpi_handle handle, char *name, int *value, int
+               *result)
+{
+       int ret;
+
+       if (value) {
+               u64 v = *value;
+
+               ret = sony_nc_buffer_call(handle, name, &v, result,
+                               sizeof(*result));
+       } else {
+               ret =  sony_nc_buffer_call(handle, name, NULL, result,
+                               sizeof(*result));
+       }
+       return ret;
+}
+
 struct sony_nc_handles {
        u16 cap[0x10];
        struct device_attribute devattr;