Add debug on wmi call 13 output for testing

Fix wrong pointer dereferentiation

Add debug output for clevo_acpi

Create more flexible clevo_evaluate_method2()
This commit is contained in:
Werner Sembach 2022-07-16 17:08:15 +02:00
parent 42f8a677cf
commit 45a240f5f2
4 changed files with 69 additions and 34 deletions

View file

@ -31,7 +31,7 @@ struct clevo_acpi_driver_data_t {
static struct clevo_acpi_driver_data_t *active_driver_data = NULL; static struct clevo_acpi_driver_data_t *active_driver_data = NULL;
static u32 clevo_acpi_evaluate(struct acpi_device *device, u8 cmd, u32 arg, u32 *result) static u32 clevo_acpi_evaluate(struct acpi_device *device, u8 cmd, u32 arg, union acpi_object **result)
{ {
u32 status; u32 status;
acpi_handle handle; acpi_handle handle;
@ -68,23 +68,17 @@ static u32 clevo_acpi_evaluate(struct acpi_device *device, u8 cmd, u32 arg, u32
if (!out_obj) { if (!out_obj) {
pr_err("failed to evaluate _DSM\n"); pr_err("failed to evaluate _DSM\n");
status = -1; status = -1;
} else { }
if (out_obj->type == ACPI_TYPE_INTEGER) { else {
if (!IS_ERR_OR_NULL(result)) if (!IS_ERR_OR_NULL(result)) {
*result = (u32) out_obj->integer.value; *result = out_obj;
// pr_debug("evaluate _DSM cmd: %0#4x arg: %0#10x\n", cmd, arg);
} else {
pr_err("unknown output from _DSM\n");
status = -ENODATA;
} }
} }
ACPI_FREE(out_obj);
return status; return status;
} }
u32 clevo_acpi_interface_method_call(u8 cmd, u32 arg, u32 *result_value) u32 clevo_acpi_interface_method_call(u8 cmd, u32 arg, union acpi_object **result_value)
{ {
u32 status = 0; u32 status = 0;
@ -139,9 +133,19 @@ static int clevo_acpi_remove(struct acpi_device *device)
void clevo_acpi_notify(struct acpi_device *device, u32 event) void clevo_acpi_notify(struct acpi_device *device, u32 event)
{ {
u32 event_value; u32 event_value;
union acpi_object *out_obj;
u32 status;
// struct clevo_acpi_driver_data_t *clevo_acpi_driver_data; // struct clevo_acpi_driver_data_t *clevo_acpi_driver_data;
clevo_acpi_evaluate(device, 0x01, 0, &event_value); status = clevo_acpi_evaluate(device, 0x01, 0, &out_obj);
if (!status) {
if (out_obj->type == ACPI_TYPE_INTEGER) {
event_value = (u32)out_obj->integer.value;
} else {
pr_err("return type not integer, use clevo_evaluate_method2\n");
}
ACPI_FREE(out_obj);
}
pr_debug("clevo_acpi event: %0#6x, clevo event value: %0#6x\n", event, event_value); pr_debug("clevo_acpi event: %0#6x, clevo event value: %0#6x\n", event, event_value);
// clevo_acpi_driver_data = container_of(&device, struct clevo_acpi_driver_data_t, adev); // clevo_acpi_driver_data = container_of(&device, struct clevo_acpi_driver_data_t, adev);

View file

@ -20,6 +20,7 @@
#define CLEVO_INTERFACES_H #define CLEVO_INTERFACES_H
#include <linux/types.h> #include <linux/types.h>
#include <linux/acpi.h>
#define CLEVO_WMI_EVENT_GUID "ABBC0F6B-8EA1-11D1-00A0-C90629100000" #define CLEVO_WMI_EVENT_GUID "ABBC0F6B-8EA1-11D1-00A0-C90629100000"
#define CLEVO_WMI_EMAIL_GUID "ABBC0F6C-8EA1-11D1-00A0-C90629100000" #define CLEVO_WMI_EMAIL_GUID "ABBC0F6C-8EA1-11D1-00A0-C90629100000"
@ -51,12 +52,13 @@
struct clevo_interface_t { struct clevo_interface_t {
char *string_id; char *string_id;
void (*event_callb)(u32); void (*event_callb)(u32);
u32 (*method_call)(u8, u32, u32*); u32 (*method_call)(u8, u32, union acpi_object **);
}; };
u32 clevo_keyboard_add_interface(struct clevo_interface_t *new_interface); u32 clevo_keyboard_add_interface(struct clevo_interface_t *new_interface);
u32 clevo_keyboard_remove_interface(struct clevo_interface_t *interface); u32 clevo_keyboard_remove_interface(struct clevo_interface_t *interface);
u32 clevo_evaluate_method(u8 cmd, u32 arg, u32 *result); u32 clevo_evaluate_method(u8 cmd, u32 arg, u32 *result);
u32 clevo_evaluate_method2(u8 cmd, u32 arg, union acpi_object **result);
u32 clevo_get_active_interface_id(char **id_str); u32 clevo_get_active_interface_id(char **id_str);
#define MODULE_ALIAS_CLEVO_WMI() \ #define MODULE_ALIAS_CLEVO_WMI() \

View file

@ -307,7 +307,7 @@ static ssize_t show_hasextra_fs(struct device *child,
return sprintf(buffer, "%d\n", kbd_led_state.has_extra); return sprintf(buffer, "%d\n", kbd_led_state.has_extra);
} }
u32 clevo_evaluate_method(u8 cmd, u32 arg, u32 *result) u32 clevo_evaluate_method2(u8 cmd, u32 arg, union acpi_object **result)
{ {
if (IS_ERR_OR_NULL(active_clevo_interface)) { if (IS_ERR_OR_NULL(active_clevo_interface)) {
pr_err("clevo_keyboard: no active interface while attempting cmd %02x arg %08x\n", cmd, arg); pr_err("clevo_keyboard: no active interface while attempting cmd %02x arg %08x\n", cmd, arg);
@ -315,6 +315,30 @@ u32 clevo_evaluate_method(u8 cmd, u32 arg, u32 *result)
} }
return active_clevo_interface->method_call(cmd, arg, result); return active_clevo_interface->method_call(cmd, arg, result);
} }
EXPORT_SYMBOL(clevo_evaluate_method2);
u32 clevo_evaluate_method(u8 cmd, u32 arg, u32 *result)
{
u32 status = 0;
union acpi_object *out_obj;
status = clevo_evaluate_method2(cmd, arg, &out_obj);
if (status) {
return status;
}
else {
if (out_obj->type == ACPI_TYPE_INTEGER) {
if (!IS_ERR_OR_NULL(result))
*result = (u32) out_obj->integer.value;
} else {
pr_err("return type not integer, use clevo_evaluate_method2\n");
status = -ENODATA;
}
ACPI_FREE(out_obj);
}
return status;
}
EXPORT_SYMBOL(clevo_evaluate_method); EXPORT_SYMBOL(clevo_evaluate_method);
u32 clevo_get_active_interface_id(char **id_str) u32 clevo_get_active_interface_id(char **id_str)

View file

@ -23,7 +23,7 @@
#include <linux/version.h> #include <linux/version.h>
#include "clevo_interfaces.h" #include "clevo_interfaces.h"
static int clevo_wmi_evaluate(u32 wmi_method_id, u32 wmi_arg, u32 *result) static int clevo_wmi_evaluate(u32 wmi_method_id, u32 wmi_arg, union acpi_object **result)
{ {
struct acpi_buffer acpi_buffer_in = { (acpi_size)sizeof(wmi_arg), struct acpi_buffer acpi_buffer_in = { (acpi_size)sizeof(wmi_arg),
&wmi_arg }; &wmi_arg };
@ -45,26 +45,17 @@ static int clevo_wmi_evaluate(u32 wmi_method_id, u32 wmi_arg, u32 *result)
if (!acpi_result) { if (!acpi_result) {
pr_err("failed to evaluate WMI method\n"); pr_err("failed to evaluate WMI method\n");
return_status = -1; return_status = -1;
} else { }
if (acpi_result->type == ACPI_TYPE_INTEGER) { else {
if (!IS_ERR_OR_NULL(result)) { if (!IS_ERR_OR_NULL(result)) {
*result = (u32)acpi_result->integer.value; *result = acpi_result;
/*pr_debug(
"evaluate wmi cmd: %0#4x arg: %0#10x\n",
wmi_method_id, wmi_arg);*/
}
} else {
pr_err("unknown output from wmi method\n");
return_status = -EIO;
} }
} }
kfree(acpi_result);
return return_status; return return_status;
} }
u32 clevo_wmi_interface_method_call(u8 cmd, u32 arg, u32 *result_value) u32 clevo_wmi_interface_method_call(u8 cmd, u32 arg, union acpi_object **result_value)
{ {
return clevo_wmi_evaluate(cmd, arg, result_value); return clevo_wmi_evaluate(cmd, arg, result_value);
} }
@ -80,7 +71,8 @@ static int clevo_wmi_probe(struct wmi_device *wdev)
static int clevo_wmi_probe(struct wmi_device *wdev, const void *dummy_context) static int clevo_wmi_probe(struct wmi_device *wdev, const void *dummy_context)
#endif #endif
{ {
u32 status, ret; u32 status;
union acpi_object *out_obj;
pr_debug("clevo_wmi driver probe\n"); pr_debug("clevo_wmi driver probe\n");
@ -96,16 +88,18 @@ static int clevo_wmi_probe(struct wmi_device *wdev, const void *dummy_context)
// Since the WMI GUIDs aren't unique let's (at least) // Since the WMI GUIDs aren't unique let's (at least)
// check the return of some "known existing general" method // check the return of some "known existing general" method
status = clevo_wmi_evaluate(0x52, 0, &ret); status = clevo_wmi_evaluate(0x52, 0, &out_obj);
if (status < 0) { if (status < 0) {
pr_debug("probe: Clevo GUIDs present but method call failed\n"); pr_debug("probe: Clevo GUIDs present but method call failed\n");
return -ENODEV; return -ENODEV;
} }
if (ret == 0xffffffff) { if (out_obj->type != ACPI_TYPE_INTEGER || (out_obj->type == ACPI_TYPE_INTEGER && (u32)out_obj->integer.value == 0xffffffff)) {
pr_debug( pr_debug(
"probe: Clevo GUIDs present but method returned unexpected value\n"); "probe: Clevo GUIDs present but method returned unexpected value\n");
ACPI_FREE(out_obj);
return -ENODEV; return -ENODEV;
} }
ACPI_FREE(out_obj);
// Add this interface // Add this interface
clevo_keyboard_add_interface(&clevo_wmi_interface); clevo_keyboard_add_interface(&clevo_wmi_interface);
@ -131,7 +125,18 @@ static void clevo_wmi_remove(struct wmi_device *wdev)
static void clevo_wmi_notify(struct wmi_device *wdev, union acpi_object *dummy) static void clevo_wmi_notify(struct wmi_device *wdev, union acpi_object *dummy)
{ {
u32 event_value; u32 event_value;
clevo_wmi_evaluate(0x01, 0, &event_value); union acpi_object *out_obj;
u32 status;
status = clevo_wmi_evaluate(0x01, 0, &out_obj);
if (!status) {
if (out_obj->type == ACPI_TYPE_INTEGER) {
event_value = (u32)out_obj->integer.value;
} else {
pr_err("return type not integer, use clevo_evaluate_method2\n");
}
ACPI_FREE(out_obj);
}
pr_debug("clevo_wmi notify\n"); pr_debug("clevo_wmi notify\n");
if (!IS_ERR_OR_NULL(clevo_wmi_interface.event_callb)) { if (!IS_ERR_OR_NULL(clevo_wmi_interface.event_callb)) {
// Execute registered callback // Execute registered callback