ACPI: sysfs: evaluate _STR on each sysfs access

The handling of the _STR method is inconsistent with the other method
evaluations. It is the only method which is cached.

The cached value stored in 'struct acpi_device_pnp' has a different
lifetime than the other struct members.

Commit d1efe3c324ea ("ACPI: Add new sysfs interface to export device description")
does not explain this difference.

Evaluating the method every time also removes the necessity to manage
the lifetime of the cached value, which would be a problem when managing
the sysfs attributes through the device core.

Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
Link: https://patch.msgid.link/20240709-acpi-sysfs-groups-v2-2-058ab0667fa8@weissschuh.net
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
Thomas Weißschuh 2024-07-09 22:37:25 +02:00 committed by Rafael J. Wysocki
parent 4bb1e7d027
commit 52831d9bbc
2 changed files with 15 additions and 16 deletions

View File

@ -439,23 +439,33 @@ static ssize_t description_show(struct device *dev,
char *buf) char *buf)
{ {
struct acpi_device *acpi_dev = to_acpi_device(dev); struct acpi_device *acpi_dev = to_acpi_device(dev);
struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
union acpi_object *str_obj;
acpi_status status;
int result; int result;
if (acpi_dev->pnp.str_obj == NULL) status = acpi_evaluate_object_typed(acpi_dev->handle, "_STR",
return 0; NULL, &buffer,
ACPI_TYPE_BUFFER);
if (ACPI_FAILURE(status))
return -EIO;
str_obj = buffer.pointer;
/* /*
* The _STR object contains a Unicode identifier for a device. * The _STR object contains a Unicode identifier for a device.
* We need to convert to utf-8 so it can be displayed. * We need to convert to utf-8 so it can be displayed.
*/ */
result = utf16s_to_utf8s( result = utf16s_to_utf8s(
(wchar_t *)acpi_dev->pnp.str_obj->buffer.pointer, (wchar_t *)str_obj->buffer.pointer,
acpi_dev->pnp.str_obj->buffer.length, str_obj->buffer.length,
UTF16_LITTLE_ENDIAN, buf, UTF16_LITTLE_ENDIAN, buf,
PAGE_SIZE - 1); PAGE_SIZE - 1);
buf[result++] = '\n'; buf[result++] = '\n';
kfree(str_obj);
return result; return result;
} }
static DEVICE_ATTR_RO(description); static DEVICE_ATTR_RO(description);
@ -513,8 +523,6 @@ static DEVICE_ATTR_RO(status);
*/ */
int acpi_device_setup_files(struct acpi_device *dev) int acpi_device_setup_files(struct acpi_device *dev)
{ {
struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
acpi_status status;
int result = 0; int result = 0;
/* /*
@ -540,12 +548,6 @@ int acpi_device_setup_files(struct acpi_device *dev)
* If device has _STR, 'description' file is created * If device has _STR, 'description' file is created
*/ */
if (acpi_has_method(dev->handle, "_STR")) { if (acpi_has_method(dev->handle, "_STR")) {
status = acpi_evaluate_object_typed(dev->handle, "_STR",
NULL, &buffer,
ACPI_TYPE_BUFFER);
if (ACPI_FAILURE(status))
buffer.pointer = NULL;
dev->pnp.str_obj = buffer.pointer;
result = device_create_file(&dev->dev, &dev_attr_description); result = device_create_file(&dev->dev, &dev_attr_description);
if (result) if (result)
goto end; goto end;
@ -618,10 +620,8 @@ void acpi_device_remove_files(struct acpi_device *dev)
/* /*
* If device has _STR, remove 'description' file * If device has _STR, remove 'description' file
*/ */
if (acpi_has_method(dev->handle, "_STR")) { if (acpi_has_method(dev->handle, "_STR"))
kfree(dev->pnp.str_obj);
device_remove_file(&dev->dev, &dev_attr_description); device_remove_file(&dev->dev, &dev_attr_description);
}
/* /*
* If device has _EJ0, remove 'eject' file. * If device has _EJ0, remove 'eject' file.
*/ */

View File

@ -255,7 +255,6 @@ struct acpi_device_pnp {
struct list_head ids; /* _HID and _CIDs */ struct list_head ids; /* _HID and _CIDs */
acpi_device_name device_name; /* Driver-determined */ acpi_device_name device_name; /* Driver-determined */
acpi_device_class device_class; /* " */ acpi_device_class device_class; /* " */
union acpi_object *str_obj; /* unicode string for _STR method */
}; };
#define acpi_device_bid(d) ((d)->pnp.bus_id) #define acpi_device_bid(d) ((d)->pnp.bus_id)