[PATCH v1 4/5] platform/x86: ayaneo-ec: Add controller power and modules attributes

Antheas Kapenekakis posted 5 patches 1 month, 2 weeks ago
[PATCH v1 4/5] platform/x86: ayaneo-ec: Add controller power and modules attributes
Posted by Antheas Kapenekakis 1 month, 2 weeks ago
The Ayaneo 3 features hot-swappable controller modules. The ejection
and management is done through HID. However, after ejecting the modules,
the controller needs to be power cycled via the EC to re-initialize.

For this, the EC provides a variable that holds whether the left or
right modules are connected, and a power control register to turn
the controller on or off. After ejecting the modules, the controller
should be turned off. Then, after both modules are reinserted,
the controller may be powered on again to re-initialize.

This patch introduces two new firmware attributes:
 - `controller_modules`: a read-only attribute that indicates whether
   the left and right modules are connected (none, left, right, both).
 - `controller_power`: a read-write attribute that allows the user
   to turn the controller on or off (with 'on'/'off').

Therefore, after ejection is complete, userspace can power off the
controller, then wait until both modules have been reinserted
(`controller_modules` will return 'both') to turn on the controller.

Signed-off-by: Antheas Kapenekakis <lkml@antheas.dev>
---
 drivers/platform/x86/ayaneo-ec.c | 235 ++++++++++++++++++++++++++++++-
 1 file changed, 234 insertions(+), 1 deletion(-)

diff --git a/drivers/platform/x86/ayaneo-ec.c b/drivers/platform/x86/ayaneo-ec.c
index a4bdc6ae7af7..eb7f9ae03b4f 100644
--- a/drivers/platform/x86/ayaneo-ec.c
+++ b/drivers/platform/x86/ayaneo-ec.c
@@ -16,6 +16,10 @@
 #include <linux/platform_device.h>
 #include <acpi/battery.h>
 
+#include "firmware_attributes_class.h"
+
+#define DRIVER_NAME "ayaneo-ec"
+
 #define AYANEO_PWM_ENABLE_REG	 0x4A
 #define AYANEO_PWM_REG		 0x4B
 #define AYANEO_PWM_MODE_AUTO	 0x00
@@ -30,20 +34,60 @@
 #define AYANEO_CHARGE_VAL_AUTO		0xaa
 #define AYANEO_CHARGE_VAL_INHIBIT	0x55
 
+#define AYANEO_POWER_REG	0x2d
+#define AYANEO_POWER_OFF	0xfe
+#define AYANEO_POWER_ON		0xff
+#define AYANEO_MODULE_REG	0x2f
+#define AYANEO_MODULE_LEFT	BIT(0)
+#define AYANEO_MODULE_RIGHT	BIT(1)
+
+enum ayaneo_fw_attr_id {
+	AYANEO_ATTR_CONTROLLER_MODULES,
+	AYANEO_ATTR_CONTROLLER_POWER,
+};
+
+static const char *const ayaneo_fw_attr_name[] = {
+	[AYANEO_ATTR_CONTROLLER_MODULES] = "controller_modules",
+	[AYANEO_ATTR_CONTROLLER_POWER] = "controller_power",
+};
+
+static const char *const ayaneo_fw_attr_desc[] = {
+	[AYANEO_ATTR_CONTROLLER_MODULES] =
+		"Which controller Magic Modules are connected (none, left, right, both)",
+	[AYANEO_ATTR_CONTROLLER_POWER] = "Controller power state (on, off)",
+};
+
+#define AYANEO_ATTR_ENUM_MAX_ATTRS 7
+#define AYANEO_ATTR_LANGUAGE_CODE "en_US.UTF-8"
+
 struct ayaneo_ec_quirk {
 	bool has_fan_control;
 	bool has_charge_control;
+	bool has_magic_modules;
+	bool has_controller_power;
 };
 
 struct ayaneo_ec_platform_data {
 	struct platform_device *pdev;
 	struct ayaneo_ec_quirk *quirks;
 	struct acpi_battery_hook battery_hook;
+	struct device *fw_attrs_dev;
+	struct kset *fw_attrs_kset;
+};
+
+struct ayaneo_fw_attr {
+	struct ayaneo_ec_platform_data *data;
+	enum ayaneo_fw_attr_id fw_attr_id;
+	struct attribute_group attr_group;
+	struct kobj_attribute display_name;
+	struct kobj_attribute current_value;
 };
 
 static const struct ayaneo_ec_quirk ayaneo3 = {
 	.has_fan_control = true,
 	.has_charge_control = true,
+	.has_magic_modules = true,
+	.has_controller_power = true,
 };
 
 static const struct dmi_system_id dmi_table[] = {
@@ -260,6 +304,159 @@ static int ayaneo_remove_battery(struct power_supply *battery,
 	return 0;
 }
 
+static void ayaneo_kset_unregister(void *data)
+{
+	struct kset *kset = data;
+
+	kset_unregister(kset);
+}
+
+static void ayaneo_fw_attrs_dev_unregister(void *data)
+{
+	struct device *fw_attrs_dev = data;
+
+	device_unregister(fw_attrs_dev);
+}
+
+static ssize_t display_name_language_code_show(struct kobject *kobj,
+					       struct kobj_attribute *attr,
+					       char *buf)
+{
+	return sysfs_emit(buf, "%s\n", AYANEO_ATTR_LANGUAGE_CODE);
+}
+
+static struct kobj_attribute fw_attr_display_name_language_code =
+	__ATTR_RO(display_name_language_code);
+
+static ssize_t display_name_show(struct kobject *kobj,
+				 struct kobj_attribute *attr, char *buf)
+{
+	struct ayaneo_fw_attr *fw_attr =
+		container_of(attr, struct ayaneo_fw_attr, display_name);
+
+	return sysfs_emit(buf, "%s\n", ayaneo_fw_attr_desc[fw_attr->fw_attr_id]);
+}
+
+static ssize_t current_value_show(struct kobject *kobj,
+				  struct kobj_attribute *attr, char *buf)
+{
+	struct ayaneo_fw_attr *fw_attr =
+		container_of(attr, struct ayaneo_fw_attr, current_value);
+	bool left, right;
+	char *out;
+	int ret;
+	u8 tmp;
+
+	switch (fw_attr->fw_attr_id) {
+	case AYANEO_ATTR_CONTROLLER_MODULES:
+		ret = ec_read(AYANEO_MODULE_REG, &tmp);
+		if (ret)
+			return ret;
+		left = !(tmp & AYANEO_MODULE_LEFT);
+		right = !(tmp & AYANEO_MODULE_RIGHT);
+
+		if (left && right)
+			out = "both";
+		else if (left)
+			out = "left";
+		else if (right)
+			out = "right";
+		else
+			out = "none";
+
+		return sysfs_emit(buf, "%s\n", out);
+	case AYANEO_ATTR_CONTROLLER_POWER:
+		ret = ec_read(AYANEO_POWER_REG, &tmp);
+		if (ret)
+			return ret;
+
+		if (tmp == AYANEO_POWER_OFF)
+			out = "off";
+		else
+			out = "on";
+
+		return sysfs_emit(buf, "%s\n", out);
+	}
+	return -EINVAL;
+}
+
+static ssize_t current_value_store(struct kobject *kobj,
+				   struct kobj_attribute *attr, const char *buf,
+				   size_t count)
+{
+	struct ayaneo_fw_attr *fw_attr =
+		container_of(attr, struct ayaneo_fw_attr, current_value);
+	int ret;
+
+	switch (fw_attr->fw_attr_id) {
+	case AYANEO_ATTR_CONTROLLER_POWER:
+		if (sysfs_streq(buf, "on"))
+			ret = ec_write(AYANEO_POWER_REG, AYANEO_POWER_ON);
+		else if (sysfs_streq(buf, "off"))
+			ret = ec_write(AYANEO_POWER_REG, AYANEO_POWER_OFF);
+		if (ret)
+			return ret;
+		return count;
+	case AYANEO_ATTR_CONTROLLER_MODULES:
+		return -EINVAL;
+	}
+	return -EINVAL;
+}
+
+static ssize_t type_show(struct kobject *kobj, struct kobj_attribute *attr,
+			 char *buf)
+{
+	return sysfs_emit(buf, "string\n");
+}
+
+static struct kobj_attribute fw_attr_type_string = {
+	.attr = { .name = "type", .mode = 0444 },
+	.show = type_show,
+};
+
+static int ayaneo_fw_attr_init(struct ayaneo_ec_platform_data *data,
+			       const enum ayaneo_fw_attr_id fw_attr_id,
+			       bool read_only)
+{
+	struct ayaneo_fw_attr *fw_attr;
+	struct attribute **attrs;
+	int idx = 0;
+
+	fw_attr = devm_kzalloc(&data->pdev->dev, sizeof(*fw_attr), GFP_KERNEL);
+	if (!fw_attr)
+		return -ENOMEM;
+
+	attrs = devm_kcalloc(&data->pdev->dev, AYANEO_ATTR_ENUM_MAX_ATTRS + 1,
+			     sizeof(*attrs), GFP_KERNEL);
+	if (!attrs)
+		return -ENOMEM;
+
+	fw_attr->data = data;
+	fw_attr->fw_attr_id = fw_attr_id;
+	fw_attr->attr_group.name = ayaneo_fw_attr_name[fw_attr_id];
+	fw_attr->attr_group.attrs = attrs;
+
+	attrs[idx++] = &fw_attr_type_string.attr;
+	attrs[idx++] = &fw_attr_display_name_language_code.attr;
+
+	sysfs_attr_init(&fw_attr->display_name.attr);
+	fw_attr->display_name.attr.name = "display_name";
+	fw_attr->display_name.attr.mode = 0444;
+	fw_attr->display_name.show = display_name_show;
+	attrs[idx++] = &fw_attr->display_name.attr;
+
+	sysfs_attr_init(&fw_attr->current_value.attr);
+	fw_attr->current_value.attr.name = "current_value";
+	fw_attr->current_value.attr.mode = read_only ? 0444 : 0644;
+	fw_attr->current_value.show = current_value_show;
+	fw_attr->current_value.store = current_value_store;
+	attrs[idx++] = &fw_attr->current_value.attr;
+
+	attrs[idx] = NULL;
+	return sysfs_create_group(&data->fw_attrs_kset->kobj,
+				  &fw_attr->attr_group);
+}
+
 static int ayaneo_ec_probe(struct platform_device *pdev)
 {
 	const struct dmi_system_id *dmi_entry;
@@ -295,12 +492,48 @@ static int ayaneo_ec_probe(struct platform_device *pdev)
 			return ret;
 	}
 
+	if (data->quirks->has_magic_modules || data->quirks->has_controller_power) {
+		data->fw_attrs_dev = device_create(&firmware_attributes_class, NULL,
+						MKDEV(0, 0), NULL, "%s",
+						DRIVER_NAME);
+		if (IS_ERR(data->fw_attrs_dev))
+			return PTR_ERR(data->fw_attrs_dev);
+
+		ret = devm_add_action_or_reset(&data->pdev->dev,
+					ayaneo_fw_attrs_dev_unregister,
+					data->fw_attrs_dev);
+		if (ret)
+			return ret;
+
+		data->fw_attrs_kset = kset_create_and_add("attributes", NULL,
+							&data->fw_attrs_dev->kobj);
+		if (!data->fw_attrs_kset)
+			return -ENOMEM;
+
+		ret = devm_add_action_or_reset(&data->pdev->dev, ayaneo_kset_unregister,
+					data->fw_attrs_kset);
+
+		if (data->quirks->has_magic_modules) {
+			ret = ayaneo_fw_attr_init(
+				data, AYANEO_ATTR_CONTROLLER_MODULES, true);
+			if (ret)
+				return ret;
+		}
+
+		if (data->quirks->has_controller_power) {
+			ret = ayaneo_fw_attr_init(
+				data, AYANEO_ATTR_CONTROLLER_POWER, false);
+			if (ret)
+				return ret;
+		}
+	}
+
 	return 0;
 }
 
 static struct platform_driver ayaneo_platform_driver = {
 	.driver = {
-		.name = "ayaneo-ec",
+		.name = DRIVER_NAME,
 	},
 	.probe = ayaneo_ec_probe,
 };
-- 
2.50.1
Re: [PATCH v1 4/5] platform/x86: ayaneo-ec: Add controller power and modules attributes
Posted by Armin Wolf 1 month, 1 week ago
Am 20.08.25 um 18:06 schrieb Antheas Kapenekakis:

> The Ayaneo 3 features hot-swappable controller modules. The ejection
> and management is done through HID. However, after ejecting the modules,
> the controller needs to be power cycled via the EC to re-initialize.
>
> For this, the EC provides a variable that holds whether the left or
> right modules are connected, and a power control register to turn
> the controller on or off. After ejecting the modules, the controller
> should be turned off. Then, after both modules are reinserted,
> the controller may be powered on again to re-initialize.
>
> This patch introduces two new firmware attributes:
>   - `controller_modules`: a read-only attribute that indicates whether
>     the left and right modules are connected (none, left, right, both).
>   - `controller_power`: a read-write attribute that allows the user
>     to turn the controller on or off (with 'on'/'off').
>
> Therefore, after ejection is complete, userspace can power off the
> controller, then wait until both modules have been reinserted
> (`controller_modules` will return 'both') to turn on the controller.

I do not think that those controls should be exposed as firmware attributes,
as they are live values not persistent across power cycles. Better use
sysfs attributes instead.

Thanks,
Armin Wolf

>
> Signed-off-by: Antheas Kapenekakis <lkml@antheas.dev>
> ---
>   drivers/platform/x86/ayaneo-ec.c | 235 ++++++++++++++++++++++++++++++-
>   1 file changed, 234 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/platform/x86/ayaneo-ec.c b/drivers/platform/x86/ayaneo-ec.c
> index a4bdc6ae7af7..eb7f9ae03b4f 100644
> --- a/drivers/platform/x86/ayaneo-ec.c
> +++ b/drivers/platform/x86/ayaneo-ec.c
> @@ -16,6 +16,10 @@
>   #include <linux/platform_device.h>
>   #include <acpi/battery.h>
>   
> +#include "firmware_attributes_class.h"
> +
> +#define DRIVER_NAME "ayaneo-ec"
> +
>   #define AYANEO_PWM_ENABLE_REG	 0x4A
>   #define AYANEO_PWM_REG		 0x4B
>   #define AYANEO_PWM_MODE_AUTO	 0x00
> @@ -30,20 +34,60 @@
>   #define AYANEO_CHARGE_VAL_AUTO		0xaa
>   #define AYANEO_CHARGE_VAL_INHIBIT	0x55
>   
> +#define AYANEO_POWER_REG	0x2d
> +#define AYANEO_POWER_OFF	0xfe
> +#define AYANEO_POWER_ON		0xff
> +#define AYANEO_MODULE_REG	0x2f
> +#define AYANEO_MODULE_LEFT	BIT(0)
> +#define AYANEO_MODULE_RIGHT	BIT(1)
> +
> +enum ayaneo_fw_attr_id {
> +	AYANEO_ATTR_CONTROLLER_MODULES,
> +	AYANEO_ATTR_CONTROLLER_POWER,
> +};
> +
> +static const char *const ayaneo_fw_attr_name[] = {
> +	[AYANEO_ATTR_CONTROLLER_MODULES] = "controller_modules",
> +	[AYANEO_ATTR_CONTROLLER_POWER] = "controller_power",
> +};
> +
> +static const char *const ayaneo_fw_attr_desc[] = {
> +	[AYANEO_ATTR_CONTROLLER_MODULES] =
> +		"Which controller Magic Modules are connected (none, left, right, both)",
> +	[AYANEO_ATTR_CONTROLLER_POWER] = "Controller power state (on, off)",
> +};
> +
> +#define AYANEO_ATTR_ENUM_MAX_ATTRS 7
> +#define AYANEO_ATTR_LANGUAGE_CODE "en_US.UTF-8"
> +
>   struct ayaneo_ec_quirk {
>   	bool has_fan_control;
>   	bool has_charge_control;
> +	bool has_magic_modules;
> +	bool has_controller_power;
>   };
>   
>   struct ayaneo_ec_platform_data {
>   	struct platform_device *pdev;
>   	struct ayaneo_ec_quirk *quirks;
>   	struct acpi_battery_hook battery_hook;
> +	struct device *fw_attrs_dev;
> +	struct kset *fw_attrs_kset;
> +};
> +
> +struct ayaneo_fw_attr {
> +	struct ayaneo_ec_platform_data *data;
> +	enum ayaneo_fw_attr_id fw_attr_id;
> +	struct attribute_group attr_group;
> +	struct kobj_attribute display_name;
> +	struct kobj_attribute current_value;
>   };
>   
>   static const struct ayaneo_ec_quirk ayaneo3 = {
>   	.has_fan_control = true,
>   	.has_charge_control = true,
> +	.has_magic_modules = true,
> +	.has_controller_power = true,
>   };
>   
>   static const struct dmi_system_id dmi_table[] = {
> @@ -260,6 +304,159 @@ static int ayaneo_remove_battery(struct power_supply *battery,
>   	return 0;
>   }
>   
> +static void ayaneo_kset_unregister(void *data)
> +{
> +	struct kset *kset = data;
> +
> +	kset_unregister(kset);
> +}
> +
> +static void ayaneo_fw_attrs_dev_unregister(void *data)
> +{
> +	struct device *fw_attrs_dev = data;
> +
> +	device_unregister(fw_attrs_dev);
> +}
> +
> +static ssize_t display_name_language_code_show(struct kobject *kobj,
> +					       struct kobj_attribute *attr,
> +					       char *buf)
> +{
> +	return sysfs_emit(buf, "%s\n", AYANEO_ATTR_LANGUAGE_CODE);
> +}
> +
> +static struct kobj_attribute fw_attr_display_name_language_code =
> +	__ATTR_RO(display_name_language_code);
> +
> +static ssize_t display_name_show(struct kobject *kobj,
> +				 struct kobj_attribute *attr, char *buf)
> +{
> +	struct ayaneo_fw_attr *fw_attr =
> +		container_of(attr, struct ayaneo_fw_attr, display_name);
> +
> +	return sysfs_emit(buf, "%s\n", ayaneo_fw_attr_desc[fw_attr->fw_attr_id]);
> +}
> +
> +static ssize_t current_value_show(struct kobject *kobj,
> +				  struct kobj_attribute *attr, char *buf)
> +{
> +	struct ayaneo_fw_attr *fw_attr =
> +		container_of(attr, struct ayaneo_fw_attr, current_value);
> +	bool left, right;
> +	char *out;
> +	int ret;
> +	u8 tmp;
> +
> +	switch (fw_attr->fw_attr_id) {
> +	case AYANEO_ATTR_CONTROLLER_MODULES:
> +		ret = ec_read(AYANEO_MODULE_REG, &tmp);
> +		if (ret)
> +			return ret;
> +		left = !(tmp & AYANEO_MODULE_LEFT);
> +		right = !(tmp & AYANEO_MODULE_RIGHT);
> +
> +		if (left && right)
> +			out = "both";
> +		else if (left)
> +			out = "left";
> +		else if (right)
> +			out = "right";
> +		else
> +			out = "none";
> +
> +		return sysfs_emit(buf, "%s\n", out);
> +	case AYANEO_ATTR_CONTROLLER_POWER:
> +		ret = ec_read(AYANEO_POWER_REG, &tmp);
> +		if (ret)
> +			return ret;
> +
> +		if (tmp == AYANEO_POWER_OFF)
> +			out = "off";
> +		else
> +			out = "on";
> +
> +		return sysfs_emit(buf, "%s\n", out);
> +	}
> +	return -EINVAL;
> +}
> +
> +static ssize_t current_value_store(struct kobject *kobj,
> +				   struct kobj_attribute *attr, const char *buf,
> +				   size_t count)
> +{
> +	struct ayaneo_fw_attr *fw_attr =
> +		container_of(attr, struct ayaneo_fw_attr, current_value);
> +	int ret;
> +
> +	switch (fw_attr->fw_attr_id) {
> +	case AYANEO_ATTR_CONTROLLER_POWER:
> +		if (sysfs_streq(buf, "on"))
> +			ret = ec_write(AYANEO_POWER_REG, AYANEO_POWER_ON);
> +		else if (sysfs_streq(buf, "off"))
> +			ret = ec_write(AYANEO_POWER_REG, AYANEO_POWER_OFF);
> +		if (ret)
> +			return ret;
> +		return count;
> +	case AYANEO_ATTR_CONTROLLER_MODULES:
> +		return -EINVAL;
> +	}
> +	return -EINVAL;
> +}
> +
> +static ssize_t type_show(struct kobject *kobj, struct kobj_attribute *attr,
> +			 char *buf)
> +{
> +	return sysfs_emit(buf, "string\n");
> +}
> +
> +static struct kobj_attribute fw_attr_type_string = {
> +	.attr = { .name = "type", .mode = 0444 },
> +	.show = type_show,
> +};
> +
> +static int ayaneo_fw_attr_init(struct ayaneo_ec_platform_data *data,
> +			       const enum ayaneo_fw_attr_id fw_attr_id,
> +			       bool read_only)
> +{
> +	struct ayaneo_fw_attr *fw_attr;
> +	struct attribute **attrs;
> +	int idx = 0;
> +
> +	fw_attr = devm_kzalloc(&data->pdev->dev, sizeof(*fw_attr), GFP_KERNEL);
> +	if (!fw_attr)
> +		return -ENOMEM;
> +
> +	attrs = devm_kcalloc(&data->pdev->dev, AYANEO_ATTR_ENUM_MAX_ATTRS + 1,
> +			     sizeof(*attrs), GFP_KERNEL);
> +	if (!attrs)
> +		return -ENOMEM;
> +
> +	fw_attr->data = data;
> +	fw_attr->fw_attr_id = fw_attr_id;
> +	fw_attr->attr_group.name = ayaneo_fw_attr_name[fw_attr_id];
> +	fw_attr->attr_group.attrs = attrs;
> +
> +	attrs[idx++] = &fw_attr_type_string.attr;
> +	attrs[idx++] = &fw_attr_display_name_language_code.attr;
> +
> +	sysfs_attr_init(&fw_attr->display_name.attr);
> +	fw_attr->display_name.attr.name = "display_name";
> +	fw_attr->display_name.attr.mode = 0444;
> +	fw_attr->display_name.show = display_name_show;
> +	attrs[idx++] = &fw_attr->display_name.attr;
> +
> +	sysfs_attr_init(&fw_attr->current_value.attr);
> +	fw_attr->current_value.attr.name = "current_value";
> +	fw_attr->current_value.attr.mode = read_only ? 0444 : 0644;
> +	fw_attr->current_value.show = current_value_show;
> +	fw_attr->current_value.store = current_value_store;
> +	attrs[idx++] = &fw_attr->current_value.attr;
> +
> +	attrs[idx] = NULL;
> +	return sysfs_create_group(&data->fw_attrs_kset->kobj,
> +				  &fw_attr->attr_group);
> +}
> +
>   static int ayaneo_ec_probe(struct platform_device *pdev)
>   {
>   	const struct dmi_system_id *dmi_entry;
> @@ -295,12 +492,48 @@ static int ayaneo_ec_probe(struct platform_device *pdev)
>   			return ret;
>   	}
>   
> +	if (data->quirks->has_magic_modules || data->quirks->has_controller_power) {
> +		data->fw_attrs_dev = device_create(&firmware_attributes_class, NULL,
> +						MKDEV(0, 0), NULL, "%s",
> +						DRIVER_NAME);
> +		if (IS_ERR(data->fw_attrs_dev))
> +			return PTR_ERR(data->fw_attrs_dev);
> +
> +		ret = devm_add_action_or_reset(&data->pdev->dev,
> +					ayaneo_fw_attrs_dev_unregister,
> +					data->fw_attrs_dev);
> +		if (ret)
> +			return ret;
> +
> +		data->fw_attrs_kset = kset_create_and_add("attributes", NULL,
> +							&data->fw_attrs_dev->kobj);
> +		if (!data->fw_attrs_kset)
> +			return -ENOMEM;
> +
> +		ret = devm_add_action_or_reset(&data->pdev->dev, ayaneo_kset_unregister,
> +					data->fw_attrs_kset);
> +
> +		if (data->quirks->has_magic_modules) {
> +			ret = ayaneo_fw_attr_init(
> +				data, AYANEO_ATTR_CONTROLLER_MODULES, true);
> +			if (ret)
> +				return ret;
> +		}
> +
> +		if (data->quirks->has_controller_power) {
> +			ret = ayaneo_fw_attr_init(
> +				data, AYANEO_ATTR_CONTROLLER_POWER, false);
> +			if (ret)
> +				return ret;
> +		}
> +	}
> +
>   	return 0;
>   }
>   
>   static struct platform_driver ayaneo_platform_driver = {
>   	.driver = {
> -		.name = "ayaneo-ec",
> +		.name = DRIVER_NAME,
>   	},
>   	.probe = ayaneo_ec_probe,
>   };
Re: [PATCH v1 4/5] platform/x86: ayaneo-ec: Add controller power and modules attributes
Posted by kernel test robot 1 month, 1 week ago
Hi Antheas,

kernel test robot noticed the following build errors:

[auto build test ERROR on c17b750b3ad9f45f2b6f7e6f7f4679844244f0b9]

url:    https://github.com/intel-lab-lkp/linux/commits/Antheas-Kapenekakis/platform-x86-ayaneo-ec-Add-Ayaneo-Embedded-Controller-platform-driver/20250821-002525
base:   c17b750b3ad9f45f2b6f7e6f7f4679844244f0b9
patch link:    https://lore.kernel.org/r/20250820160628.99678-5-lkml%40antheas.dev
patch subject: [PATCH v1 4/5] platform/x86: ayaneo-ec: Add controller power and modules attributes
config: i386-allmodconfig (https://download.01.org/0day-ci/archive/20250821/202508211626.9Cxkta6K-lkp@intel.com/config)
compiler: gcc-12 (Debian 12.2.0-14+deb12u1) 12.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250821/202508211626.9Cxkta6K-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202508211626.9Cxkta6K-lkp@intel.com/

All errors (new ones prefixed by >>):

   drivers/platform/x86/ayaneo-ec.c: In function 'ayaneo_ec_probe':
>> drivers/platform/x86/ayaneo-ec.c:497:49: error: implicit declaration of function 'MKDEV' [-Werror=implicit-function-declaration]
     497 |                                                 MKDEV(0, 0), NULL, "%s",
         |                                                 ^~~~~
   cc1: some warnings being treated as errors


vim +/MKDEV +497 drivers/platform/x86/ayaneo-ec.c

   459	
   460	static int ayaneo_ec_probe(struct platform_device *pdev)
   461	{
   462		const struct dmi_system_id *dmi_entry;
   463		struct ayaneo_ec_platform_data *data;
   464		struct device *hwdev;
   465		int ret;
   466	
   467		dmi_entry = dmi_first_match(dmi_table);
   468		if (!dmi_entry)
   469			return -ENODEV;
   470	
   471		data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
   472		if (!data)
   473			return -ENOMEM;
   474	
   475		data->pdev = pdev;
   476		data->quirks = dmi_entry->driver_data;
   477		platform_set_drvdata(pdev, data);
   478	
   479		if (data->quirks->has_fan_control) {
   480			hwdev = devm_hwmon_device_register_with_info(
   481				&pdev->dev, "ayaneo_ec", NULL, &ayaneo_ec_chip_info, NULL);
   482			if (IS_ERR(hwdev))
   483				return PTR_ERR(hwdev);
   484		}
   485	
   486		if (data->quirks->has_charge_control) {
   487			data->battery_hook.add_battery = ayaneo_add_battery;
   488			data->battery_hook.remove_battery = ayaneo_remove_battery;
   489			data->battery_hook.name = "Ayaneo Battery";
   490			ret = devm_battery_hook_register(&pdev->dev, &data->battery_hook);
   491			if (ret)
   492				return ret;
   493		}
   494	
   495		if (data->quirks->has_magic_modules || data->quirks->has_controller_power) {
   496			data->fw_attrs_dev = device_create(&firmware_attributes_class, NULL,
 > 497							MKDEV(0, 0), NULL, "%s",
   498							DRIVER_NAME);
   499			if (IS_ERR(data->fw_attrs_dev))
   500				return PTR_ERR(data->fw_attrs_dev);
   501	
   502			ret = devm_add_action_or_reset(&data->pdev->dev,
   503						ayaneo_fw_attrs_dev_unregister,
   504						data->fw_attrs_dev);
   505			if (ret)
   506				return ret;
   507	
   508			data->fw_attrs_kset = kset_create_and_add("attributes", NULL,
   509								&data->fw_attrs_dev->kobj);
   510			if (!data->fw_attrs_kset)
   511				return -ENOMEM;
   512	
   513			ret = devm_add_action_or_reset(&data->pdev->dev, ayaneo_kset_unregister,
   514						data->fw_attrs_kset);
   515	
   516			if (data->quirks->has_magic_modules) {
   517				ret = ayaneo_fw_attr_init(
   518					data, AYANEO_ATTR_CONTROLLER_MODULES, true);
   519				if (ret)
   520					return ret;
   521			}
   522	
   523			if (data->quirks->has_controller_power) {
   524				ret = ayaneo_fw_attr_init(
   525					data, AYANEO_ATTR_CONTROLLER_POWER, false);
   526				if (ret)
   527					return ret;
   528			}
   529		}
   530	
   531		return 0;
   532	}
   533	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Re: [PATCH v1 4/5] platform/x86: ayaneo-ec: Add controller power and modules attributes
Posted by kernel test robot 1 month, 1 week ago
Hi Antheas,

kernel test robot noticed the following build warnings:

[auto build test WARNING on c17b750b3ad9f45f2b6f7e6f7f4679844244f0b9]

url:    https://github.com/intel-lab-lkp/linux/commits/Antheas-Kapenekakis/platform-x86-ayaneo-ec-Add-Ayaneo-Embedded-Controller-platform-driver/20250821-002525
base:   c17b750b3ad9f45f2b6f7e6f7f4679844244f0b9
patch link:    https://lore.kernel.org/r/20250820160628.99678-5-lkml%40antheas.dev
patch subject: [PATCH v1 4/5] platform/x86: ayaneo-ec: Add controller power and modules attributes
config: x86_64-allyesconfig (https://download.01.org/0day-ci/archive/20250821/202508211640.8MtPueLL-lkp@intel.com/config)
compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250821/202508211640.8MtPueLL-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202508211640.8MtPueLL-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> drivers/platform/x86/ayaneo-ec.c:395:12: warning: variable 'ret' is used uninitialized whenever 'if' condition is false [-Wsometimes-uninitialized]
     395 |                 else if (sysfs_streq(buf, "off"))
         |                          ^~~~~~~~~~~~~~~~~~~~~~~
   drivers/platform/x86/ayaneo-ec.c:397:7: note: uninitialized use occurs here
     397 |                 if (ret)
         |                     ^~~
   drivers/platform/x86/ayaneo-ec.c:395:8: note: remove the 'if' if its condition is always true
     395 |                 else if (sysfs_streq(buf, "off"))
         |                      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
     396 |                         ret = ec_write(AYANEO_POWER_REG, AYANEO_POWER_OFF);
   drivers/platform/x86/ayaneo-ec.c:389:9: note: initialize the variable 'ret' to silence this warning
     389 |         int ret;
         |                ^
         |                 = 0
   1 warning generated.


vim +395 drivers/platform/x86/ayaneo-ec.c

   382	
   383	static ssize_t current_value_store(struct kobject *kobj,
   384					   struct kobj_attribute *attr, const char *buf,
   385					   size_t count)
   386	{
   387		struct ayaneo_fw_attr *fw_attr =
   388			container_of(attr, struct ayaneo_fw_attr, current_value);
   389		int ret;
   390	
   391		switch (fw_attr->fw_attr_id) {
   392		case AYANEO_ATTR_CONTROLLER_POWER:
   393			if (sysfs_streq(buf, "on"))
   394				ret = ec_write(AYANEO_POWER_REG, AYANEO_POWER_ON);
 > 395			else if (sysfs_streq(buf, "off"))
   396				ret = ec_write(AYANEO_POWER_REG, AYANEO_POWER_OFF);
   397			if (ret)
   398				return ret;
   399			return count;
   400		case AYANEO_ATTR_CONTROLLER_MODULES:
   401			return -EINVAL;
   402		}
   403		return -EINVAL;
   404	}
   405	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki