asus-laptop: use attribute group to manage attributes
Instead of registering (and removing) every attribute individually switch to using sysfs attribute group. This makes sure that we properly unwind and do not try to remove non-existent attributes which may not be safe to do in the future. Signed-off-by: Dmitry Torokhov <dtor@mail.ru> Signed-off-by: Matthew Garrett <mjg@redhat.com>
This commit is contained in:
Родитель
209009b2cb
Коммит
ac9b1e5b63
|
@ -1200,81 +1200,69 @@ static void asus_acpi_notify(struct acpi_device *device, u32 event)
|
|||
|
||||
static DEVICE_ATTR(infos, S_IRUGO, show_infos, NULL);
|
||||
static DEVICE_ATTR(wlan, S_IRUGO | S_IWUSR, show_wlan, store_wlan);
|
||||
static DEVICE_ATTR(bluetooth, S_IRUGO | S_IWUSR, show_bluetooth,
|
||||
store_bluetooth);
|
||||
static DEVICE_ATTR(bluetooth, S_IRUGO | S_IWUSR,
|
||||
show_bluetooth, store_bluetooth);
|
||||
static DEVICE_ATTR(display, S_IRUGO | S_IWUSR, show_disp, store_disp);
|
||||
static DEVICE_ATTR(ledd, S_IRUGO | S_IWUSR, show_ledd, store_ledd);
|
||||
static DEVICE_ATTR(ls_level, S_IRUGO | S_IWUSR, show_lslvl, store_lslvl);
|
||||
static DEVICE_ATTR(ls_switch, S_IRUGO | S_IWUSR, show_lssw, store_lssw);
|
||||
static DEVICE_ATTR(gps, S_IRUGO | S_IWUSR, show_gps, store_gps);
|
||||
|
||||
static void asus_sysfs_exit(struct asus_laptop *asus)
|
||||
{
|
||||
struct platform_device *device = asus->platform_device;
|
||||
static struct attribute *asus_attributes[] = {
|
||||
&dev_attr_infos.attr,
|
||||
&dev_attr_wlan.attr,
|
||||
&dev_attr_bluetooth.attr,
|
||||
&dev_attr_display.attr,
|
||||
&dev_attr_ledd.attr,
|
||||
&dev_attr_ls_level.attr,
|
||||
&dev_attr_ls_switch.attr,
|
||||
&dev_attr_gps.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
device_remove_file(&device->dev, &dev_attr_infos);
|
||||
device_remove_file(&device->dev, &dev_attr_wlan);
|
||||
device_remove_file(&device->dev, &dev_attr_bluetooth);
|
||||
device_remove_file(&device->dev, &dev_attr_display);
|
||||
device_remove_file(&device->dev, &dev_attr_ledd);
|
||||
device_remove_file(&device->dev, &dev_attr_ls_switch);
|
||||
device_remove_file(&device->dev, &dev_attr_ls_level);
|
||||
device_remove_file(&device->dev, &dev_attr_gps);
|
||||
static mode_t asus_sysfs_is_visible(struct kobject *kobj,
|
||||
struct attribute *attr,
|
||||
int idx)
|
||||
{
|
||||
struct device *dev = container_of(kobj, struct device, kobj);
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct asus_laptop *asus = platform_get_drvdata(pdev);
|
||||
acpi_handle handle = asus->handle;
|
||||
bool supported;
|
||||
|
||||
if (attr == &dev_attr_wlan.attr) {
|
||||
supported = !acpi_check_handle(handle, METHOD_WLAN, NULL);
|
||||
|
||||
} else if (attr == &dev_attr_bluetooth.attr) {
|
||||
supported = !acpi_check_handle(handle, METHOD_BLUETOOTH, NULL);
|
||||
|
||||
} else if (attr == &dev_attr_display.attr) {
|
||||
supported = !acpi_check_handle(handle, METHOD_SWITCH_DISPLAY, NULL);
|
||||
|
||||
} else if (attr == &dev_attr_ledd.attr) {
|
||||
supported = !acpi_check_handle(handle, METHOD_LEDD, NULL);
|
||||
|
||||
} else if (attr == &dev_attr_ls_switch.attr ||
|
||||
attr == &dev_attr_ls_level.attr) {
|
||||
supported = !acpi_check_handle(handle, METHOD_ALS_CONTROL, NULL) &&
|
||||
!acpi_check_handle(handle, METHOD_ALS_LEVEL, NULL);
|
||||
|
||||
} else if (attr == &dev_attr_gps.attr) {
|
||||
supported = !acpi_check_handle(handle, METHOD_GPS_ON, NULL) &&
|
||||
!acpi_check_handle(handle, METHOD_GPS_OFF, NULL) &&
|
||||
!acpi_check_handle(handle, METHOD_GPS_STATUS, NULL);
|
||||
} else {
|
||||
supported = true;
|
||||
}
|
||||
|
||||
return supported ? attr->mode : 0;
|
||||
}
|
||||
|
||||
static int asus_sysfs_init(struct asus_laptop *asus)
|
||||
{
|
||||
struct platform_device *device = asus->platform_device;
|
||||
int err;
|
||||
|
||||
err = device_create_file(&device->dev, &dev_attr_infos);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (!acpi_check_handle(asus->handle, METHOD_WLAN, NULL)) {
|
||||
err = device_create_file(&device->dev, &dev_attr_wlan);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (!acpi_check_handle(asus->handle, METHOD_BLUETOOTH, NULL)) {
|
||||
err = device_create_file(&device->dev, &dev_attr_bluetooth);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (!acpi_check_handle(asus->handle, METHOD_SWITCH_DISPLAY, NULL)) {
|
||||
err = device_create_file(&device->dev, &dev_attr_display);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (!acpi_check_handle(asus->handle, METHOD_LEDD, NULL)) {
|
||||
err = device_create_file(&device->dev, &dev_attr_ledd);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (!acpi_check_handle(asus->handle, METHOD_ALS_CONTROL, NULL) &&
|
||||
!acpi_check_handle(asus->handle, METHOD_ALS_LEVEL, NULL)) {
|
||||
err = device_create_file(&device->dev, &dev_attr_ls_switch);
|
||||
if (err)
|
||||
return err;
|
||||
err = device_create_file(&device->dev, &dev_attr_ls_level);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (!acpi_check_handle(asus->handle, METHOD_GPS_ON, NULL) &&
|
||||
!acpi_check_handle(asus->handle, METHOD_GPS_OFF, NULL) &&
|
||||
!acpi_check_handle(asus->handle, METHOD_GPS_STATUS, NULL)) {
|
||||
err = device_create_file(&device->dev, &dev_attr_gps);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
static const struct attribute_group asus_attr_group = {
|
||||
.is_visible = asus_sysfs_is_visible,
|
||||
.attrs = asus_attributes,
|
||||
};
|
||||
|
||||
static int asus_platform_init(struct asus_laptop *asus)
|
||||
{
|
||||
|
@ -1289,13 +1277,14 @@ static int asus_platform_init(struct asus_laptop *asus)
|
|||
if (result)
|
||||
goto fail_platform_device;
|
||||
|
||||
result = asus_sysfs_init(asus);
|
||||
result = sysfs_create_group(&asus->platform_device->dev.kobj,
|
||||
&asus_attr_group);
|
||||
if (result)
|
||||
goto fail_sysfs;
|
||||
|
||||
return 0;
|
||||
|
||||
fail_sysfs:
|
||||
asus_sysfs_exit(asus);
|
||||
platform_device_del(asus->platform_device);
|
||||
fail_platform_device:
|
||||
platform_device_put(asus->platform_device);
|
||||
|
@ -1304,7 +1293,7 @@ fail_platform_device:
|
|||
|
||||
static void asus_platform_exit(struct asus_laptop *asus)
|
||||
{
|
||||
asus_sysfs_exit(asus);
|
||||
sysfs_remove_group(&asus->platform_device->dev.kobj, &asus_attr_group);
|
||||
platform_device_unregister(asus->platform_device);
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче