On Fri, Dec 27, 2024 at 04:41:36AM +0100, Armin Wolf wrote: > Am 21.12.24 um 06:59 schrieb Kurt Borja: > > > Both WMI devices handled by this module specify a distinct interface for > > LED control. Previously this module handled this by dynamically adapting > > arguments passed to wmi_evaluate_method() based on the `interface` > > global variable. > > > > To avoid the use of global variables, and enable the migration to > > non-deprecated WMI methods, let the WMI drivers define upd_led and > > upd_brightness operations, which completely replace > > alienware_update_led() and wmax_brightness(). > > > > Also define alienware_wmi_command(), which serves as a wrapper for > > wmidev_evaluate_method(). This new method is very similar to > > alienware_wmax_command() but is WMI device agnostic. > > > > Signed-off-by: Kurt Borja <kuurtb@xxxxxxxxx> > > --- > > drivers/platform/x86/dell/alienware-wmi.c | 180 ++++++++++++++-------- > > 1 file changed, 118 insertions(+), 62 deletions(-) > > > > diff --git a/drivers/platform/x86/dell/alienware-wmi.c b/drivers/platform/x86/dell/alienware-wmi.c > > index c4ca141d628e..bcf3b2f80dfd 100644 > > --- a/drivers/platform/x86/dell/alienware-wmi.c > > +++ b/drivers/platform/x86/dell/alienware-wmi.c > > @@ -417,12 +417,46 @@ struct alienfx_priv { > > u8 lighting_control_state; > > }; > > > > +struct alienfx_ops { > > + int (*upd_led)(struct alienfx_priv *priv, struct wmi_device *wdev, > > + u8 location); > > + int (*upd_brightness)(struct alienfx_priv *priv, struct wmi_device *wdev, > > + u8 brightness); > > +}; > > + > > struct alienfx_platdata { > > struct wmi_device *wdev; > > + struct alienfx_ops ops; > > }; > > > > static u8 interface; > > > > +static acpi_status alienware_wmi_command(struct wmi_device *wdev, u32 method_id, > > + void *in_args, size_t in_size, u32 *out_data) > > Please return a errno here instead of acpi_status. Ack! > > > +{ > > + struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL}; > > + struct acpi_buffer in = {in_size, in_args}; > > + union acpi_object *obj; > > + acpi_status ret; > > + > > + if (out_data) { > > + ret = wmidev_evaluate_method(wdev, 0, method_id, &in, &out); > > + if (ACPI_FAILURE(ret)) > > + goto out_free_ptr; > > Just return -EIO here as out.pointer will contain no valid data in this case. I wasn't sure of this. Thanks. > > > + > > + obj = (union acpi_object *)out.pointer; > > Unnecessary cast. Ack. > > > + > > + if (obj && obj->type == ACPI_TYPE_INTEGER) > > + *out_data = (u32)obj->integer.value; > > Please move the code for freeing "obj" to this line. Ack. > > > + } else { > > + ret = wmidev_evaluate_method(wdev, 0, method_id, &in, NULL); > > + } > > + > > +out_free_ptr: > > + kfree(out.pointer); > > + return ret; > > +} > > + > > /* > > * Helpers used for zone control > > */ > > @@ -453,46 +487,6 @@ static int parse_rgb(const char *buf, struct color_platform *colors) > > /* > > * Individual RGB zone control > > */ > > -static int alienware_update_led(struct alienfx_priv *priv, u8 location) > > -{ > > - int method_id; > > - acpi_status status; > > - char *guid; > > - struct acpi_buffer input; > > - struct legacy_led_args legacy_args; > > - struct wmax_led_args wmax_basic_args; > > - if (interface == WMAX) { > > - wmax_basic_args.led_mask = 1 << location; > > - wmax_basic_args.colors = priv->colors[location]; > > - wmax_basic_args.state = priv->lighting_control_state; > > - guid = WMAX_CONTROL_GUID; > > - method_id = WMAX_METHOD_ZONE_CONTROL; > > - > > - input.length = sizeof(wmax_basic_args); > > - input.pointer = &wmax_basic_args; > > - } else { > > - legacy_args.colors = priv->colors[location]; > > - legacy_args.brightness = priv->global_brightness; > > - legacy_args.state = 0; > > - if (priv->lighting_control_state == LEGACY_BOOTING || > > - priv->lighting_control_state == LEGACY_SUSPEND) { > > - guid = LEGACY_POWER_CONTROL_GUID; > > - legacy_args.state = priv->lighting_control_state; > > - } else > > - guid = LEGACY_CONTROL_GUID; > > - method_id = location + 1; > > - > > - input.length = sizeof(legacy_args); > > - input.pointer = &legacy_args; > > - } > > - pr_debug("alienware-wmi: guid %s method %d\n", guid, method_id); > > - > > - status = wmi_evaluate_method(guid, 0, method_id, &input, NULL); > > - if (ACPI_FAILURE(status)) > > - pr_err("alienware-wmi: zone set failure: %u\n", status); > > - return ACPI_FAILURE(status); > > -} > > - > > static ssize_t zone_show(struct device *dev, struct device_attribute *attr, > > char *buf, u8 location) > > { > > @@ -510,18 +504,20 @@ static ssize_t zone_show(struct device *dev, struct device_attribute *attr, > > static ssize_t zone_store(struct device *dev, struct device_attribute *attr, > > const char *buf, size_t count, u8 location) > > { > > + struct alienfx_platdata *pdata; > > struct color_platform *colors; > > struct alienfx_priv *priv; > > int ret; > > > > priv = dev_get_drvdata(dev); > > + pdata = dev_get_platdata(dev); > > colors = &priv->colors[location]; > > > > ret = parse_rgb(buf, colors); > > if (ret) > > return ret; > > > > - ret = alienware_update_led(priv, location); > > + ret = pdata->ops.upd_led(priv, pdata->wdev, location); > > > > return ret ? ret : count; > > } > > @@ -628,35 +624,19 @@ static struct attribute_group zone_attribute_group = { > > /* > > * LED Brightness (Global) > > */ > > -static int wmax_brightness(int brightness) > > -{ > > - acpi_status status; > > - struct acpi_buffer input; > > - struct wmax_brightness_args args = { > > - .led_mask = 0xFF, > > - .percentage = brightness, > > - }; > > - input.length = sizeof(args); > > - input.pointer = &args; > > - status = wmi_evaluate_method(WMAX_CONTROL_GUID, 0, > > - WMAX_METHOD_BRIGHTNESS, &input, NULL); > > - if (ACPI_FAILURE(status)) > > - pr_err("alienware-wmi: brightness set failure: %u\n", status); > > - return ACPI_FAILURE(status); > > -} > > - > > static void global_led_set(struct led_classdev *led_cdev, > > enum led_brightness brightness) > > { > > + struct alienfx_platdata *pdata; > > struct alienfx_priv *priv; > > int ret; > > > > priv = container_of(led_cdev, struct alienfx_priv, global_led); > > + pdata = dev_get_platdata(&priv->pdev->dev); > > + > > priv->global_brightness = brightness; > > - if (interface == WMAX) > > - ret = wmax_brightness(brightness); > > - else > > - ret = alienware_update_led(priv, 0); > > + > > + ret = pdata->ops.upd_brightness(priv, pdata->wdev, brightness); > > if (ret) > > pr_err("LED brightness update failed\n"); > > } > > @@ -1224,10 +1204,47 @@ static void alienware_alienfx_exit(struct wmi_device *wdev) > > /* > > * Legacy WMI driver > > */ > > +static int legacy_wmi_update_led(struct alienfx_priv *priv, > > + struct wmi_device *wdev, u8 location) > > +{ > > + struct legacy_led_args legacy_args; > > + struct acpi_buffer input; > > + acpi_status status; > > + > > + legacy_args.colors = priv->colors[location]; > > + legacy_args.brightness = priv->global_brightness; > > + legacy_args.state = priv->lighting_control_state; > > The original code set "legacy_args.state" to "0" if "priv->lighting_control_state" was "LEGACY_RUNNING". > Please keep this behavior. I missed this. Thanks. > > Thanks, > Armin Wolf > > > + > > + input.length = sizeof(legacy_args); > > + input.pointer = &legacy_args; > > + > > + if (legacy_args.state == LEGACY_RUNNING) > > + status = alienware_wmi_command(wdev, location + 1, &legacy_args, > > + sizeof(legacy_args), NULL); > > + else > > + status = wmi_evaluate_method(LEGACY_POWER_CONTROL_GUID, 0, > > + location + 1, &input, NULL); > > + > > + if (ACPI_FAILURE(status)) > > + return -EIO; > > + > > + return 0; > > +} > > + > > +static int legacy_wmi_update_brightness(struct alienfx_priv *priv, > > + struct wmi_device *wdev, u8 brightness) > > +{ > > + return legacy_wmi_update_led(priv, wdev, 0); > > +} > > + > > static int legacy_wmi_probe(struct wmi_device *wdev, const void *context) > > { > > struct alienfx_platdata pdata = { > > .wdev = wdev, > > + .ops = { > > + .upd_led = legacy_wmi_update_led, > > + .upd_brightness = legacy_wmi_update_brightness, > > + }, > > }; > > > > return alienware_alienfx_setup(&pdata); > > @@ -1267,10 +1284,49 @@ static void __exit alienware_legacy_wmi_exit(void) > > /* > > * WMAX WMI driver > > */ > > +static int wmax_wmi_update_led(struct alienfx_priv *priv, > > + struct wmi_device *wdev, u8 location) > > +{ > > + struct wmax_led_args in_args = { > > + .led_mask = 1 << location, > > + .colors = priv->colors[location], > > + .state = priv->lighting_control_state, > > + }; > > + acpi_status status; > > + > > + status = alienware_wmi_command(wdev, WMAX_METHOD_ZONE_CONTROL, > > + &in_args, sizeof(in_args), NULL); > > + if (ACPI_FAILURE(status)) > > + return -EIO; > > + > > + return 0; > > +} > > + > > +static int wmax_wmi_update_brightness(struct alienfx_priv *priv, > > + struct wmi_device *wdev, u8 brightness) > > +{ > > + struct wmax_brightness_args in_args = { > > + .led_mask = 0xFF, > > + .percentage = brightness, > > + }; > > + acpi_status status; > > + > > + status = alienware_wmi_command(wdev, WMAX_METHOD_BRIGHTNESS, &in_args, > > + sizeof(in_args), NULL); > > + if (ACPI_FAILURE(status)) > > + return -EIO; > > + > > + return 0; > > +} > > + > > static int wmax_wmi_probe(struct wmi_device *wdev, const void *context) > > { > > struct alienfx_platdata pdata = { > > .wdev = wdev, > > + .ops = { > > + .upd_led = wmax_wmi_update_led, > > + .upd_brightness = wmax_wmi_update_brightness, > > + }, > > }; > > int ret = 0; > >