Skip to content

Commit f6bae04

Browse files
t-8chrafaeljw
authored andcommitted
ACPI: sysfs: manage attributes as attribute_group
The current manual attribute management is inconsistent and brittle. Not all return values of device_create_file() are checked and the cleanup logic needs to be kept up to date manually. Moving all attributes into an attribute_group and using the is_visible() callback allows the management of all attributes as a single unit. Signed-off-by: Thomas Weißschuh <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Rafael J. Wysocki <[email protected]>
1 parent 52831d9 commit f6bae04

File tree

1 file changed

+71
-96
lines changed

1 file changed

+71
-96
lines changed

drivers/acpi/device_sysfs.c

Lines changed: 71 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -517,88 +517,97 @@ static ssize_t status_show(struct device *dev, struct device_attribute *attr,
517517
}
518518
static DEVICE_ATTR_RO(status);
519519

520-
/**
521-
* acpi_device_setup_files - Create sysfs attributes of an ACPI device.
522-
* @dev: ACPI device object.
523-
*/
524-
int acpi_device_setup_files(struct acpi_device *dev)
525-
{
526-
int result = 0;
520+
static struct attribute *acpi_attrs[] = {
521+
&dev_attr_path.attr,
522+
&dev_attr_hid.attr,
523+
&dev_attr_modalias.attr,
524+
&dev_attr_description.attr,
525+
&dev_attr_adr.attr,
526+
&dev_attr_uid.attr,
527+
&dev_attr_sun.attr,
528+
&dev_attr_hrv.attr,
529+
&dev_attr_status.attr,
530+
&dev_attr_eject.attr,
531+
&dev_attr_power_state.attr,
532+
&dev_attr_real_power_state.attr,
533+
NULL
534+
};
527535

536+
static bool acpi_show_attr(struct acpi_device *dev, const struct device_attribute *attr)
537+
{
528538
/*
529539
* Devices gotten from FADT don't have a "path" attribute
530540
*/
531-
if (dev->handle) {
532-
result = device_create_file(&dev->dev, &dev_attr_path);
533-
if (result)
534-
goto end;
535-
}
541+
if (attr == &dev_attr_path)
542+
return dev->handle;
536543

537-
if (!list_empty(&dev->pnp.ids)) {
538-
result = device_create_file(&dev->dev, &dev_attr_hid);
539-
if (result)
540-
goto end;
544+
if (attr == &dev_attr_hid || attr == &dev_attr_modalias)
545+
return !list_empty(&dev->pnp.ids);
541546

542-
result = device_create_file(&dev->dev, &dev_attr_modalias);
543-
if (result)
544-
goto end;
545-
}
547+
if (attr == &dev_attr_description)
548+
return acpi_has_method(dev->handle, "_STR");
546549

547-
/*
548-
* If device has _STR, 'description' file is created
549-
*/
550-
if (acpi_has_method(dev->handle, "_STR")) {
551-
result = device_create_file(&dev->dev, &dev_attr_description);
552-
if (result)
553-
goto end;
554-
}
550+
if (attr == &dev_attr_adr)
551+
return dev->pnp.type.bus_address;
555552

556-
if (dev->pnp.type.bus_address)
557-
result = device_create_file(&dev->dev, &dev_attr_adr);
558-
if (acpi_device_uid(dev))
559-
result = device_create_file(&dev->dev, &dev_attr_uid);
553+
if (attr == &dev_attr_uid)
554+
return acpi_device_uid(dev);
560555

561-
if (acpi_has_method(dev->handle, "_SUN")) {
562-
result = device_create_file(&dev->dev, &dev_attr_sun);
563-
if (result)
564-
goto end;
565-
}
556+
if (attr == &dev_attr_sun)
557+
return acpi_has_method(dev->handle, "_SUN");
566558

567-
if (acpi_has_method(dev->handle, "_HRV")) {
568-
result = device_create_file(&dev->dev, &dev_attr_hrv);
569-
if (result)
570-
goto end;
571-
}
559+
if (attr == &dev_attr_hrv)
560+
return acpi_has_method(dev->handle, "_HRV");
572561

573-
if (acpi_has_method(dev->handle, "_STA")) {
574-
result = device_create_file(&dev->dev, &dev_attr_status);
575-
if (result)
576-
goto end;
577-
}
562+
if (attr == &dev_attr_status)
563+
return acpi_has_method(dev->handle, "_STA");
578564

579565
/*
580566
* If device has _EJ0, 'eject' file is created that is used to trigger
581567
* hot-removal function from userland.
582568
*/
583-
if (acpi_has_method(dev->handle, "_EJ0")) {
584-
result = device_create_file(&dev->dev, &dev_attr_eject);
585-
if (result)
586-
return result;
587-
}
569+
if (attr == &dev_attr_eject)
570+
return acpi_has_method(dev->handle, "_EJ0");
588571

589-
if (dev->flags.power_manageable) {
590-
result = device_create_file(&dev->dev, &dev_attr_power_state);
591-
if (result)
592-
return result;
572+
if (attr == &dev_attr_power_state)
573+
return dev->flags.power_manageable;
593574

594-
if (dev->power.flags.power_resources)
595-
result = device_create_file(&dev->dev,
596-
&dev_attr_real_power_state);
597-
}
575+
if (attr == &dev_attr_real_power_state)
576+
return dev->flags.power_manageable && dev->power.flags.power_resources;
577+
578+
dev_warn_once(&dev->dev, "Unexpected attribute: %s\n", attr->attr.name);
579+
return false;
580+
}
581+
582+
static umode_t acpi_attr_is_visible(struct kobject *kobj,
583+
struct attribute *attr,
584+
int attrno)
585+
{
586+
struct acpi_device *dev = to_acpi_device(kobj_to_dev(kobj));
587+
588+
if (acpi_show_attr(dev, container_of(attr, struct device_attribute, attr)))
589+
return attr->mode;
590+
else
591+
return 0;
592+
}
593+
594+
static const struct attribute_group acpi_group = {
595+
.attrs = acpi_attrs,
596+
.is_visible = acpi_attr_is_visible,
597+
};
598+
599+
/**
600+
* acpi_device_setup_files - Create sysfs attributes of an ACPI device.
601+
* @dev: ACPI device object.
602+
*/
603+
int acpi_device_setup_files(struct acpi_device *dev)
604+
{
605+
int result = 0;
606+
607+
result = device_add_group(&dev->dev, &acpi_group);
598608

599609
acpi_expose_nondev_subnodes(&dev->dev.kobj, &dev->data);
600610

601-
end:
602611
return result;
603612
}
604613

@@ -609,39 +618,5 @@ int acpi_device_setup_files(struct acpi_device *dev)
609618
void acpi_device_remove_files(struct acpi_device *dev)
610619
{
611620
acpi_hide_nondev_subnodes(&dev->data);
612-
613-
if (dev->flags.power_manageable) {
614-
device_remove_file(&dev->dev, &dev_attr_power_state);
615-
if (dev->power.flags.power_resources)
616-
device_remove_file(&dev->dev,
617-
&dev_attr_real_power_state);
618-
}
619-
620-
/*
621-
* If device has _STR, remove 'description' file
622-
*/
623-
if (acpi_has_method(dev->handle, "_STR"))
624-
device_remove_file(&dev->dev, &dev_attr_description);
625-
/*
626-
* If device has _EJ0, remove 'eject' file.
627-
*/
628-
if (acpi_has_method(dev->handle, "_EJ0"))
629-
device_remove_file(&dev->dev, &dev_attr_eject);
630-
631-
if (acpi_has_method(dev->handle, "_SUN"))
632-
device_remove_file(&dev->dev, &dev_attr_sun);
633-
634-
if (acpi_has_method(dev->handle, "_HRV"))
635-
device_remove_file(&dev->dev, &dev_attr_hrv);
636-
637-
if (acpi_device_uid(dev))
638-
device_remove_file(&dev->dev, &dev_attr_uid);
639-
if (dev->pnp.type.bus_address)
640-
device_remove_file(&dev->dev, &dev_attr_adr);
641-
device_remove_file(&dev->dev, &dev_attr_modalias);
642-
device_remove_file(&dev->dev, &dev_attr_hid);
643-
if (acpi_has_method(dev->handle, "_STA"))
644-
device_remove_file(&dev->dev, &dev_attr_status);
645-
if (dev->handle)
646-
device_remove_file(&dev->dev, &dev_attr_path);
621+
device_remove_group(&dev->dev, &acpi_group);
647622
}

0 commit comments

Comments
 (0)