aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/sony-laptop.c
diff options
context:
space:
mode:
authormalattia@linux.it <malattia@linux.it>2007-04-09 04:19:05 -0400
committerLen Brown <len.brown@intel.com>2007-04-10 16:01:18 -0400
commit56b8756b3bc8812837a21f3e066dba1b489e071e (patch)
treeb23f0c58d9db882f6be89b7cdf679e6d5139992a /drivers/misc/sony-laptop.c
parent59b19106f3f20487093ea06c8220426147cf7835 (diff)
sony-laptop: Prepare the platform driver for multiple users.
Both the SNC and SPIC device drivers will create attributes and thus there's the need to have an internal usage count to avoid re-registering or de-registering at the wrong time. Signed-off-by: Mattia Dongili <malattia@linux.it> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/misc/sony-laptop.c')
-rw-r--r--drivers/misc/sony-laptop.c212
1 files changed, 112 insertions, 100 deletions
diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c
index e67189a361a2..2d05d5b7e125 100644
--- a/drivers/misc/sony-laptop.c
+++ b/drivers/misc/sony-laptop.c
@@ -54,6 +54,64 @@ module_param(debug, int, 0);
54MODULE_PARM_DESC(debug, "set this to 1 (and RTFM) if you want to help " 54MODULE_PARM_DESC(debug, "set this to 1 (and RTFM) if you want to help "
55 "the development of this driver"); 55 "the development of this driver");
56 56
57/*********** Platform Device ***********/
58
59static atomic_t sony_pf_users = ATOMIC_INIT(0);
60static struct platform_driver sony_pf_driver = {
61 .driver = {
62 .name = "sony-laptop",
63 .owner = THIS_MODULE,
64 }
65};
66static struct platform_device *sony_pf_device;
67
68static int sony_pf_add(void)
69{
70 int ret = 0;
71
72 /* don't run again if already initialized */
73 if (atomic_add_return(1, &sony_pf_users) > 1)
74 return 0;
75
76 ret = platform_driver_register(&sony_pf_driver);
77 if (ret)
78 goto out;
79
80 sony_pf_device = platform_device_alloc("sony-laptop", -1);
81 if (!sony_pf_device) {
82 ret = -ENOMEM;
83 goto out_platform_registered;
84 }
85
86 ret = platform_device_add(sony_pf_device);
87 if (ret)
88 goto out_platform_alloced;
89
90 return 0;
91
92 out_platform_alloced:
93 platform_device_put(sony_pf_device);
94 sony_pf_device = NULL;
95 out_platform_registered:
96 platform_driver_unregister(&sony_pf_driver);
97 out:
98 atomic_dec(&sony_pf_users);
99 return ret;
100}
101
102static void sony_pf_remove(void)
103{
104 /* deregister only after the last user has gone */
105 if (!atomic_dec_and_test(&sony_pf_users))
106 return;
107
108 platform_device_del(sony_pf_device);
109 platform_device_put(sony_pf_device);
110 platform_driver_unregister(&sony_pf_driver);
111}
112
113/*********** SNC (SNY5001) Device ***********/
114
57static ssize_t sony_nc_sysfs_show(struct device *, struct device_attribute *, 115static ssize_t sony_nc_sysfs_show(struct device *, struct device_attribute *,
58 char *); 116 char *);
59static ssize_t sony_nc_sysfs_store(struct device *, struct device_attribute *, 117static ssize_t sony_nc_sysfs_store(struct device *, struct device_attribute *,
@@ -279,104 +337,6 @@ static ssize_t sony_nc_sysfs_store(struct device *dev,
279 return count; 337 return count;
280} 338}
281 339
282/*
283 * Platform device
284 */
285static struct platform_driver sncpf_driver = {
286 .driver = {
287 .name = "sony-laptop",
288 .owner = THIS_MODULE,
289 }
290};
291static struct platform_device *sncpf_device;
292
293static int sony_nc_pf_add(void)
294{
295 acpi_handle handle;
296 struct sony_nc_value *item;
297 int ret = 0;
298
299 ret = platform_driver_register(&sncpf_driver);
300 if (ret)
301 goto out;
302
303 sncpf_device = platform_device_alloc("sony-laptop", -1);
304 if (!sncpf_device) {
305 ret = -ENOMEM;
306 goto out_platform_registered;
307 }
308
309 ret = platform_device_add(sncpf_device);
310 if (ret)
311 goto out_platform_alloced;
312
313 for (item = sony_nc_values; item->name; ++item) {
314
315 if (!debug && item->debug)
316 continue;
317
318 /* find the available acpiget as described in the DSDT */
319 for (; item->acpiget && *item->acpiget; ++item->acpiget) {
320 if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle,
321 *item->acpiget,
322 &handle))) {
323 if (debug)
324 printk(LOG_PFX "Found %s getter: %s\n",
325 item->name, *item->acpiget);
326 item->devattr.attr.mode |= S_IRUGO;
327 break;
328 }
329 }
330
331 /* find the available acpiset as described in the DSDT */
332 for (; item->acpiset && *item->acpiset; ++item->acpiset) {
333 if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle,
334 *item->acpiset,
335 &handle))) {
336 if (debug)
337 printk(LOG_PFX "Found %s setter: %s\n",
338 item->name, *item->acpiset);
339 item->devattr.attr.mode |= S_IWUSR;
340 break;
341 }
342 }
343
344 if (item->devattr.attr.mode != 0) {
345 ret =
346 device_create_file(&sncpf_device->dev,
347 &item->devattr);
348 if (ret)
349 goto out_sysfs;
350 }
351 }
352
353 return 0;
354
355 out_sysfs:
356 for (item = sony_nc_values; item->name; ++item) {
357 device_remove_file(&sncpf_device->dev, &item->devattr);
358 }
359 platform_device_del(sncpf_device);
360 out_platform_alloced:
361 platform_device_put(sncpf_device);
362 out_platform_registered:
363 platform_driver_unregister(&sncpf_driver);
364 out:
365 return ret;
366}
367
368static void sony_nc_pf_remove(void)
369{
370 struct sony_nc_value *item;
371
372 for (item = sony_nc_values; item->name; ++item) {
373 device_remove_file(&sncpf_device->dev, &item->devattr);
374 }
375
376 platform_device_del(sncpf_device);
377 platform_device_put(sncpf_device);
378 platform_driver_unregister(&sncpf_driver);
379}
380 340
381/* 341/*
382 * Backlight device 342 * Backlight device
@@ -455,6 +415,7 @@ static int sony_nc_add(struct acpi_device *device)
455 acpi_status status; 415 acpi_status status;
456 int result = 0; 416 int result = 0;
457 acpi_handle handle; 417 acpi_handle handle;
418 struct sony_nc_value *item;
458 419
459 sony_nc_acpi_device = device; 420 sony_nc_acpi_device = device;
460 421
@@ -497,13 +458,59 @@ static int sony_nc_add(struct acpi_device *device)
497 458
498 } 459 }
499 460
500 if (sony_nc_pf_add()) 461 if (sony_pf_add())
501 goto outbacklight; 462 goto outbacklight;
502 463
464 /* create sony_pf sysfs attributes related to the SNC device */
465 for (item = sony_nc_values; item->name; ++item) {
466
467 if (!debug && item->debug)
468 continue;
469
470 /* find the available acpiget as described in the DSDT */
471 for (; item->acpiget && *item->acpiget; ++item->acpiget) {
472 if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle,
473 *item->acpiget,
474 &handle))) {
475 if (debug)
476 printk(LOG_PFX "Found %s getter: %s\n",
477 item->name, *item->acpiget);
478 item->devattr.attr.mode |= S_IRUGO;
479 break;
480 }
481 }
482
483 /* find the available acpiset as described in the DSDT */
484 for (; item->acpiset && *item->acpiset; ++item->acpiset) {
485 if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle,
486 *item->acpiset,
487 &handle))) {
488 if (debug)
489 printk(LOG_PFX "Found %s setter: %s\n",
490 item->name, *item->acpiset);
491 item->devattr.attr.mode |= S_IWUSR;
492 break;
493 }
494 }
495
496 if (item->devattr.attr.mode != 0) {
497 result =
498 device_create_file(&sony_pf_device->dev,
499 &item->devattr);
500 if (result)
501 goto out_sysfs;
502 }
503 }
504
503 printk(KERN_INFO SONY_NC_DRIVER_NAME " successfully installed\n"); 505 printk(KERN_INFO SONY_NC_DRIVER_NAME " successfully installed\n");
504 506
505 return 0; 507 return 0;
506 508
509 out_sysfs:
510 for (item = sony_nc_values; item->name; ++item) {
511 device_remove_file(&sony_pf_device->dev, &item->devattr);
512 }
513 sony_pf_remove();
507 outbacklight: 514 outbacklight:
508 if (sony_backlight_device) 515 if (sony_backlight_device)
509 backlight_device_unregister(sony_backlight_device); 516 backlight_device_unregister(sony_backlight_device);
@@ -520,6 +527,7 @@ static int sony_nc_add(struct acpi_device *device)
520static int sony_nc_remove(struct acpi_device *device, int type) 527static int sony_nc_remove(struct acpi_device *device, int type)
521{ 528{
522 acpi_status status; 529 acpi_status status;
530 struct sony_nc_value *item;
523 531
524 if (sony_backlight_device) 532 if (sony_backlight_device)
525 backlight_device_unregister(sony_backlight_device); 533 backlight_device_unregister(sony_backlight_device);
@@ -532,7 +540,11 @@ static int sony_nc_remove(struct acpi_device *device, int type)
532 if (ACPI_FAILURE(status)) 540 if (ACPI_FAILURE(status))
533 printk(LOG_PFX "unable to remove notify handler\n"); 541 printk(LOG_PFX "unable to remove notify handler\n");
534 542
535 sony_nc_pf_remove(); 543 for (item = sony_nc_values; item->name; ++item) {
544 device_remove_file(&sony_pf_device->dev, &item->devattr);
545 }
546
547 sony_pf_remove();
536 548
537 printk(KERN_INFO SONY_NC_DRIVER_NAME " successfully removed\n"); 549 printk(KERN_INFO SONY_NC_DRIVER_NAME " successfully removed\n");
538 550