aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattia Dongili <malattia@linux.it>2011-02-18 21:52:30 -0500
committerMatthew Garrett <mjg@redhat.com>2011-03-28 06:05:26 -0400
commit2a4f0c81adcd1f812a63bc9106be2fd26f437730 (patch)
tree1b06beb94eb06631f0bedca6ac70eb6ec37ff51b
parent3672329c3642033286984313d05f4a5b57bd2da7 (diff)
sony-laptop: cache handles and report them via sysfs
Avoid calling into acpi each time we need to lookup a method handle and report the available handles to ease collection of information when debugging issues. Also move initialization of the platform driver earlier to allow adding files from other setup functions. Signed-off-by: Mattia Dongili <malattia@linux.it> Signed-off-by: Matthew Garrett <mjg@redhat.com>
-rw-r--r--drivers/platform/x86/sony-laptop.c97
1 files changed, 81 insertions, 16 deletions
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c
index 6db1661a5625..516dd22bbb26 100644
--- a/drivers/platform/x86/sony-laptop.c
+++ b/drivers/platform/x86/sony-laptop.c
@@ -727,20 +727,79 @@ static int acpi_callsetfunc(acpi_handle handle, char *name, int value,
727 return -1; 727 return -1;
728} 728}
729 729
730static int sony_find_snc_handle(int handle) 730struct sony_nc_handles {
731 u16 cap[0x10];
732 struct device_attribute devattr;
733};
734
735struct sony_nc_handles *handles;
736
737static ssize_t sony_nc_handles_show(struct device *dev,
738 struct device_attribute *attr, char *buffer)
739{
740 ssize_t len = 0;
741 int i;
742
743 for (i = 0; i < ARRAY_SIZE(handles->cap); i++) {
744 len += snprintf(buffer + len, PAGE_SIZE - len, "0x%.4x ",
745 handles->cap[i]);
746 }
747 len += snprintf(buffer + len, PAGE_SIZE - len, "\n");
748
749 return len;
750}
751
752static int sony_nc_handles_setup(struct platform_device *pd)
731{ 753{
732 int i; 754 int i;
733 int result; 755 int result;
734 756
735 for (i = 0x20; i < 0x30; i++) { 757 handles = kzalloc(sizeof(*handles), GFP_KERNEL);
736 acpi_callsetfunc(sony_nc_acpi_handle, "SN00", i, &result); 758
737 if (result == handle) { 759 sysfs_attr_init(&handles->devattr.attr);
738 dprintk("found handle 0x%.4x (offset: 0x%.2x)\n", 760 handles->devattr.attr.name = "handles";
739 handle, i - 0x20); 761 handles->devattr.attr.mode = S_IRUGO;
740 return i-0x20; 762 handles->devattr.show = sony_nc_handles_show;
763
764 for (i = 0; i < ARRAY_SIZE(handles->cap); i++) {
765 if (!acpi_callsetfunc(sony_nc_acpi_handle,
766 "SN00", i + 0x20, &result)) {
767 dprintk("caching handle 0x%.4x (offset: 0x%.2x)\n",
768 result, i);
769 handles->cap[i] = result;
741 } 770 }
742 } 771 }
743 772
773 /* allow reading capabilities via sysfs */
774 if (device_create_file(&pd->dev, &handles->devattr)) {
775 kfree(handles);
776 handles = NULL;
777 return -1;
778 }
779
780 return 0;
781}
782
783static int sony_nc_handles_cleanup(struct platform_device *pd)
784{
785 if (handles) {
786 device_remove_file(&pd->dev, &handles->devattr);
787 kfree(handles);
788 handles = NULL;
789 }
790 return 0;
791}
792
793static int sony_find_snc_handle(int handle)
794{
795 int i;
796 for (i = 0; i < 0x10; i++) {
797 if (handles->cap[i] == handle) {
798 dprintk("found handle 0x%.4x (offset: 0x%.2x)\n",
799 handle, i);
800 return i;
801 }
802 }
744 dprintk("handle 0x%.4x not found\n", handle); 803 dprintk("handle 0x%.4x not found\n", handle);
745 return -1; 804 return -1;
746} 805}
@@ -1274,6 +1333,10 @@ static int sony_nc_add(struct acpi_device *device)
1274 goto outwalk; 1333 goto outwalk;
1275 } 1334 }
1276 1335
1336 result = sony_pf_add();
1337 if (result)
1338 goto outpresent;
1339
1277 if (debug) { 1340 if (debug) {
1278 status = acpi_walk_namespace(ACPI_TYPE_METHOD, 1341 status = acpi_walk_namespace(ACPI_TYPE_METHOD,
1279 sony_nc_acpi_handle, 1, sony_walk_callback, 1342 sony_nc_acpi_handle, 1, sony_walk_callback,
@@ -1281,7 +1344,7 @@ static int sony_nc_add(struct acpi_device *device)
1281 if (ACPI_FAILURE(status)) { 1344 if (ACPI_FAILURE(status)) {
1282 pr_warn(DRV_PFX "unable to walk acpi resources\n"); 1345 pr_warn(DRV_PFX "unable to walk acpi resources\n");
1283 result = -ENODEV; 1346 result = -ENODEV;
1284 goto outwalk; 1347 goto outpresent;
1285 } 1348 }
1286 } 1349 }
1287 1350
@@ -1294,6 +1357,8 @@ static int sony_nc_add(struct acpi_device *device)
1294 if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00", 1357 if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00",
1295 &handle))) { 1358 &handle))) {
1296 dprintk("Doing SNC setup\n"); 1359 dprintk("Doing SNC setup\n");
1360 if (sony_nc_handles_setup(sony_pf_device))
1361 goto outpresent;
1297 sony_nc_function_setup(device); 1362 sony_nc_function_setup(device);
1298 sony_nc_rfkill_setup(device); 1363 sony_nc_rfkill_setup(device);
1299 } 1364 }
@@ -1302,7 +1367,7 @@ static int sony_nc_add(struct acpi_device *device)
1302 result = sony_laptop_setup_input(device); 1367 result = sony_laptop_setup_input(device);
1303 if (result) { 1368 if (result) {
1304 pr_err(DRV_PFX "Unable to create input devices.\n"); 1369 pr_err(DRV_PFX "Unable to create input devices.\n");
1305 goto outwalk; 1370 goto outsnc;
1306 } 1371 }
1307 1372
1308 if (acpi_video_backlight_support()) { 1373 if (acpi_video_backlight_support()) {
@@ -1330,10 +1395,6 @@ static int sony_nc_add(struct acpi_device *device)
1330 1395
1331 } 1396 }
1332 1397
1333 result = sony_pf_add();
1334 if (result)
1335 goto outbacklight;
1336
1337 /* create sony_pf sysfs attributes related to the SNC device */ 1398 /* create sony_pf sysfs attributes related to the SNC device */
1338 for (item = sony_nc_values; item->name; ++item) { 1399 for (item = sony_nc_values; item->name; ++item) {
1339 1400
@@ -1379,14 +1440,17 @@ static int sony_nc_add(struct acpi_device *device)
1379 for (item = sony_nc_values; item->name; ++item) { 1440 for (item = sony_nc_values; item->name; ++item) {
1380 device_remove_file(&sony_pf_device->dev, &item->devattr); 1441 device_remove_file(&sony_pf_device->dev, &item->devattr);
1381 } 1442 }
1382 sony_pf_remove();
1383
1384 outbacklight:
1385 if (sony_backlight_device) 1443 if (sony_backlight_device)
1386 backlight_device_unregister(sony_backlight_device); 1444 backlight_device_unregister(sony_backlight_device);
1387 1445
1388 sony_laptop_remove_input(); 1446 sony_laptop_remove_input();
1389 1447
1448 outsnc:
1449 sony_nc_handles_cleanup(sony_pf_device);
1450
1451 outpresent:
1452 sony_pf_remove();
1453
1390 outwalk: 1454 outwalk:
1391 sony_nc_rfkill_cleanup(); 1455 sony_nc_rfkill_cleanup();
1392 return result; 1456 return result;
@@ -1405,6 +1469,7 @@ static int sony_nc_remove(struct acpi_device *device, int type)
1405 device_remove_file(&sony_pf_device->dev, &item->devattr); 1469 device_remove_file(&sony_pf_device->dev, &item->devattr);
1406 } 1470 }
1407 1471
1472 sony_nc_handles_cleanup(sony_pf_device);
1408 sony_pf_remove(); 1473 sony_pf_remove();
1409 sony_laptop_remove_input(); 1474 sony_laptop_remove_input();
1410 sony_nc_rfkill_cleanup(); 1475 sony_nc_rfkill_cleanup();