Commit ac9b1e5b63d5d9829ecf2294f0486ccd270c5db4

Authored by Dmitry Torokhov
Committed by Matthew Garrett
1 parent 209009b2cb

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>

Showing 1 changed file with 50 additions and 61 deletions Side-by-side Diff

drivers/platform/x86/asus-laptop.c
... ... @@ -1200,82 +1200,70 @@
1200 1200  
1201 1201 static DEVICE_ATTR(infos, S_IRUGO, show_infos, NULL);
1202 1202 static DEVICE_ATTR(wlan, S_IRUGO | S_IWUSR, show_wlan, store_wlan);
1203   -static DEVICE_ATTR(bluetooth, S_IRUGO | S_IWUSR, show_bluetooth,
1204   - store_bluetooth);
  1203 +static DEVICE_ATTR(bluetooth, S_IRUGO | S_IWUSR,
  1204 + show_bluetooth, store_bluetooth);
1205 1205 static DEVICE_ATTR(display, S_IRUGO | S_IWUSR, show_disp, store_disp);
1206 1206 static DEVICE_ATTR(ledd, S_IRUGO | S_IWUSR, show_ledd, store_ledd);
1207 1207 static DEVICE_ATTR(ls_level, S_IRUGO | S_IWUSR, show_lslvl, store_lslvl);
1208 1208 static DEVICE_ATTR(ls_switch, S_IRUGO | S_IWUSR, show_lssw, store_lssw);
1209 1209 static DEVICE_ATTR(gps, S_IRUGO | S_IWUSR, show_gps, store_gps);
1210 1210  
1211   -static void asus_sysfs_exit(struct asus_laptop *asus)
1212   -{
1213   - struct platform_device *device = asus->platform_device;
  1211 +static struct attribute *asus_attributes[] = {
  1212 + &dev_attr_infos.attr,
  1213 + &dev_attr_wlan.attr,
  1214 + &dev_attr_bluetooth.attr,
  1215 + &dev_attr_display.attr,
  1216 + &dev_attr_ledd.attr,
  1217 + &dev_attr_ls_level.attr,
  1218 + &dev_attr_ls_switch.attr,
  1219 + &dev_attr_gps.attr,
  1220 + NULL
  1221 +};
1214 1222  
1215   - device_remove_file(&device->dev, &dev_attr_infos);
1216   - device_remove_file(&device->dev, &dev_attr_wlan);
1217   - device_remove_file(&device->dev, &dev_attr_bluetooth);
1218   - device_remove_file(&device->dev, &dev_attr_display);
1219   - device_remove_file(&device->dev, &dev_attr_ledd);
1220   - device_remove_file(&device->dev, &dev_attr_ls_switch);
1221   - device_remove_file(&device->dev, &dev_attr_ls_level);
1222   - device_remove_file(&device->dev, &dev_attr_gps);
1223   -}
1224   -
1225   -static int asus_sysfs_init(struct asus_laptop *asus)
  1223 +static mode_t asus_sysfs_is_visible(struct kobject *kobj,
  1224 + struct attribute *attr,
  1225 + int idx)
1226 1226 {
1227   - struct platform_device *device = asus->platform_device;
1228   - int err;
  1227 + struct device *dev = container_of(kobj, struct device, kobj);
  1228 + struct platform_device *pdev = to_platform_device(dev);
  1229 + struct asus_laptop *asus = platform_get_drvdata(pdev);
  1230 + acpi_handle handle = asus->handle;
  1231 + bool supported;
1229 1232  
1230   - err = device_create_file(&device->dev, &dev_attr_infos);
1231   - if (err)
1232   - return err;
  1233 + if (attr == &dev_attr_wlan.attr) {
  1234 + supported = !acpi_check_handle(handle, METHOD_WLAN, NULL);
1233 1235  
1234   - if (!acpi_check_handle(asus->handle, METHOD_WLAN, NULL)) {
1235   - err = device_create_file(&device->dev, &dev_attr_wlan);
1236   - if (err)
1237   - return err;
1238   - }
  1236 + } else if (attr == &dev_attr_bluetooth.attr) {
  1237 + supported = !acpi_check_handle(handle, METHOD_BLUETOOTH, NULL);
1239 1238  
1240   - if (!acpi_check_handle(asus->handle, METHOD_BLUETOOTH, NULL)) {
1241   - err = device_create_file(&device->dev, &dev_attr_bluetooth);
1242   - if (err)
1243   - return err;
1244   - }
  1239 + } else if (attr == &dev_attr_display.attr) {
  1240 + supported = !acpi_check_handle(handle, METHOD_SWITCH_DISPLAY, NULL);
1245 1241  
1246   - if (!acpi_check_handle(asus->handle, METHOD_SWITCH_DISPLAY, NULL)) {
1247   - err = device_create_file(&device->dev, &dev_attr_display);
1248   - if (err)
1249   - return err;
1250   - }
  1242 + } else if (attr == &dev_attr_ledd.attr) {
  1243 + supported = !acpi_check_handle(handle, METHOD_LEDD, NULL);
1251 1244  
1252   - if (!acpi_check_handle(asus->handle, METHOD_LEDD, NULL)) {
1253   - err = device_create_file(&device->dev, &dev_attr_ledd);
1254   - if (err)
1255   - return err;
1256   - }
  1245 + } else if (attr == &dev_attr_ls_switch.attr ||
  1246 + attr == &dev_attr_ls_level.attr) {
  1247 + supported = !acpi_check_handle(handle, METHOD_ALS_CONTROL, NULL) &&
  1248 + !acpi_check_handle(handle, METHOD_ALS_LEVEL, NULL);
1257 1249  
1258   - if (!acpi_check_handle(asus->handle, METHOD_ALS_CONTROL, NULL) &&
1259   - !acpi_check_handle(asus->handle, METHOD_ALS_LEVEL, NULL)) {
1260   - err = device_create_file(&device->dev, &dev_attr_ls_switch);
1261   - if (err)
1262   - return err;
1263   - err = device_create_file(&device->dev, &dev_attr_ls_level);
1264   - if (err)
1265   - return err;
  1250 + } else if (attr == &dev_attr_gps.attr) {
  1251 + supported = !acpi_check_handle(handle, METHOD_GPS_ON, NULL) &&
  1252 + !acpi_check_handle(handle, METHOD_GPS_OFF, NULL) &&
  1253 + !acpi_check_handle(handle, METHOD_GPS_STATUS, NULL);
  1254 + } else {
  1255 + supported = true;
1266 1256 }
1267 1257  
1268   - if (!acpi_check_handle(asus->handle, METHOD_GPS_ON, NULL) &&
1269   - !acpi_check_handle(asus->handle, METHOD_GPS_OFF, NULL) &&
1270   - !acpi_check_handle(asus->handle, METHOD_GPS_STATUS, NULL)) {
1271   - err = device_create_file(&device->dev, &dev_attr_gps);
1272   - if (err)
1273   - return err;
1274   - }
1275   -
1276   - return err;
  1258 + return supported ? attr->mode : 0;
1277 1259 }
1278 1260  
  1261 +
  1262 +static const struct attribute_group asus_attr_group = {
  1263 + .is_visible = asus_sysfs_is_visible,
  1264 + .attrs = asus_attributes,
  1265 +};
  1266 +
1279 1267 static int asus_platform_init(struct asus_laptop *asus)
1280 1268 {
1281 1269 int result;
1282 1270  
1283 1271  
... ... @@ -1289,13 +1277,14 @@
1289 1277 if (result)
1290 1278 goto fail_platform_device;
1291 1279  
1292   - result = asus_sysfs_init(asus);
  1280 + result = sysfs_create_group(&asus->platform_device->dev.kobj,
  1281 + &asus_attr_group);
1293 1282 if (result)
1294 1283 goto fail_sysfs;
  1284 +
1295 1285 return 0;
1296 1286  
1297 1287 fail_sysfs:
1298   - asus_sysfs_exit(asus);
1299 1288 platform_device_del(asus->platform_device);
1300 1289 fail_platform_device:
1301 1290 platform_device_put(asus->platform_device);
... ... @@ -1304,7 +1293,7 @@
1304 1293  
1305 1294 static void asus_platform_exit(struct asus_laptop *asus)
1306 1295 {
1307   - asus_sysfs_exit(asus);
  1296 + sysfs_remove_group(&asus->platform_device->dev.kobj, &asus_attr_group);
1308 1297 platform_device_unregister(asus->platform_device);
1309 1298 }
1310 1299