1 /* 2 * Copyright (c) International Business Machines Corp., 2001 3 * Copyright (c) 2013 Oracle and/or its affiliates. All Rights Reserved. 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 13 * the GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19 20 /* 21 * HISTORY: 22 * 06/09/2003 Initial creation mridge (at) us.ibm.com 23 * -Ported 24 * updated - 01/09/2005 Updates from Intel to add functionality 25 * 26 * 01/03/2009 Mrton Nmeth <nm127 (at) freemail.hu> 27 * - Updated for Linux kernel 2.6.28 28 */ 29 30 #include <linux/kernel.h> 31 #include <linux/module.h> 32 #include <linux/init.h> 33 #include <linux/types.h> 34 #include <linux/fs.h> 35 #include <linux/blkdev.h> 36 #include <linux/ioctl.h> 37 #include <linux/pm.h> 38 #include <linux/acpi.h> 39 #include <linux/genhd.h> 40 #include <linux/dmi.h> 41 #include <linux/nls.h> 42 43 #include "ltp_acpi.h" 44 45 MODULE_AUTHOR("Martin Ridgeway <mridge (at) us.ibm.com>"); 46 MODULE_AUTHOR("Alexey Kodanev <alexey.kodanev (at) oracle.com>"); 47 MODULE_DESCRIPTION("ACPI LTP Test Driver"); 48 MODULE_LICENSE("GPL"); 49 ACPI_MODULE_NAME("LTP_ACPI") 50 51 #define prk_err(fmt, ...) \ 52 pr_err(ACPI_TEST_NAME ": " fmt "\n", ##__VA_ARGS__) 53 #define prk_alert(fmt, ...) \ 54 pr_alert(ACPI_TEST_NAME ": " fmt "\n", ##__VA_ARGS__) 55 #define prk_info(fmt, ...) \ 56 pr_info(ACPI_TEST_NAME ": " fmt "\n", ##__VA_ARGS__) 57 58 static int acpi_failure(acpi_status status, const char *name) 59 { 60 if (ACPI_FAILURE(status)) { 61 ACPI_EXCEPTION((AE_INFO, status, name)); 62 return 1; 63 } 64 return 0; 65 } 66 67 /* points to the string of the last found object _STR */ 68 static char *str_obj_result; 69 70 /* sysfs device path of the last found device */ 71 static char *sysfs_path; 72 73 /* first found device with _CRS */ 74 static acpi_handle res_handle; 75 76 static acpi_status get_str_object(acpi_handle handle) 77 { 78 int res; 79 acpi_status status; 80 acpi_handle temp = 0; 81 union acpi_object *str_obj; 82 char *buf = NULL; 83 84 struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; 85 86 status = acpi_get_handle(handle, "_STR", &temp); 87 88 if (ACPI_SUCCESS(status) && 89 !acpi_evaluate_object(handle, "_STR", NULL, &buffer)) { 90 91 str_obj = buffer.pointer; 92 93 buf = kmalloc(str_obj->buffer.length / 2, GFP_KERNEL); 94 if (!buf) { 95 kfree(str_obj); 96 return AE_NO_MEMORY; 97 } 98 99 res = utf16s_to_utf8s((wchar_t *)str_obj->buffer.pointer, 100 str_obj->buffer.length, UTF16_LITTLE_ENDIAN, buf, 101 str_obj->buffer.length / 2); 102 103 buf[res] = '\0'; 104 105 kfree(str_obj_result); 106 str_obj_result = buf; 107 kfree(str_obj); 108 } 109 110 return status; 111 } 112 113 static void get_crs_object(acpi_handle handle) 114 { 115 acpi_status status; 116 acpi_handle temp; 117 if (!res_handle) { 118 status = acpi_get_handle(handle, METHOD_NAME__CRS, &temp); 119 if (ACPI_SUCCESS(status)) 120 res_handle = handle; 121 } 122 } 123 124 static void get_sysfs_path(acpi_handle handle) 125 { 126 acpi_status status; 127 struct acpi_device *device; 128 129 kfree(sysfs_path); 130 sysfs_path = NULL; 131 132 status = acpi_bus_get_device(handle, &device); 133 if (ACPI_SUCCESS(status)) 134 sysfs_path = kobject_get_path(&device->dev.kobj, GFP_KERNEL); 135 } 136 137 /* acpi handle of the last visited device */ 138 static acpi_handle start_parent; 139 140 static int acpi_traverse(acpi_handle parent, acpi_handle child) 141 { 142 static char indent[64]; 143 const char * const ind_end = indent + 63; 144 static const char *ind = ind_end; 145 acpi_status status; 146 struct acpi_device_info *dev_info; 147 acpi_handle new_child; 148 149 if (!indent[0]) 150 memset(indent, 0x20, 63); 151 152 while (parent) { 153 status = acpi_get_next_object(ACPI_TYPE_DEVICE, 154 parent, child, &new_child); 155 156 if (ACPI_FAILURE(status)) { 157 ind += 4; 158 159 child = parent; 160 status = acpi_get_parent(child, &parent); 161 162 /* no more devices */ 163 if (ACPI_FAILURE(status)) { 164 start_parent = 0; 165 kfree(str_obj_result); 166 str_obj_result = NULL; 167 return 0; 168 } 169 continue; 170 } 171 172 status = acpi_get_object_info(new_child, &dev_info); 173 if (acpi_failure(status, "acpi_object_info failed")) 174 return 1; 175 176 get_sysfs_path(new_child); 177 178 get_crs_object(new_child); 179 180 if (ind < indent) 181 ind = indent; 182 else if (ind > ind_end) 183 ind = ind_end; 184 185 /* 186 * if we find _STR object we will stop here 187 * and save last visited child 188 */ 189 if (ACPI_SUCCESS(get_str_object(new_child))) { 190 prk_info("%s%4.4s: has '_STR' '%s' path '%s'", 191 ind, (char *)&dev_info->name, str_obj_result, 192 (sysfs_path) ? sysfs_path : "no path"); 193 ind -= 4; 194 start_parent = new_child; 195 kfree(dev_info); 196 return 0; 197 } 198 prk_info("%s%4.4s: path '%s'", ind, (char *)&dev_info->name, 199 (sysfs_path) ? sysfs_path : "no path"); 200 201 ind -= 4; 202 parent = new_child; 203 child = 0; 204 kfree(dev_info); 205 } 206 207 return 0; 208 } 209 210 static int acpi_traverse_from_root(void) 211 { 212 acpi_status status; 213 struct acpi_device_info *dev_info; 214 acpi_handle parent = 0, child = 0; 215 216 if (!start_parent) { 217 status = acpi_get_handle(NULL, ACPI_NS_ROOT_PATH, &parent); 218 if (acpi_failure(status, "acpi_get_handle")) 219 return 1; 220 status = acpi_get_object_info(parent, &dev_info); 221 if (acpi_failure(status, "acpi_object_info failed")) 222 return 1; 223 prk_info("start from %4.4s", (char *)&dev_info->name); 224 } else { 225 /* continue with the last visited child */ 226 parent = start_parent; 227 } 228 229 return acpi_traverse(parent, child); 230 } 231 232 /* first found device with _STR */ 233 static acpi_handle dev_handle; 234 235 static int acpi_init(void) 236 { 237 acpi_status status; 238 acpi_handle parent_handle; 239 240 struct acpi_device_info *dev_info; 241 242 prk_alert("TEST -- acpi_get_handle "); 243 status = acpi_get_handle(NULL, "\\_SB", &parent_handle); 244 if (acpi_failure(status, "acpi_get_handle")) 245 return 1; 246 247 /* get first device on SYS bus, it will be used in other tests */ 248 while (acpi_get_next_object(ACPI_TYPE_DEVICE, 249 parent_handle, 0, &dev_handle) == 0) { 250 parent_handle = dev_handle; 251 } 252 253 status = acpi_get_object_info(dev_handle, &dev_info); 254 if (acpi_failure(status, "acpi_object_info failed")) 255 return 1; 256 257 prk_alert("ACPI object name %4.4s, type %d", (char *)&dev_info->name, 258 dev_info->type); 259 kfree(dev_info); 260 261 prk_alert("TEST -- acpi_get_parent "); 262 status = acpi_get_parent(dev_handle, &parent_handle); 263 return acpi_failure(status, "acpi_get_parent failed"); 264 } 265 266 /* 267 * acpi_bus_notify 268 * --------------- 269 * Callback for all 'system-level' device notifications (values 0x00-0x7F). 270 */ 271 static void acpi_bus_notify(acpi_handle handle, u32 type, void *data) 272 { 273 prk_alert("Register ACPI Bus Notify callback function"); 274 } 275 276 static int acpi_test_notify_handler(void) 277 { 278 acpi_status status; 279 280 prk_alert("TEST -- acpi_install_notify_handler"); 281 282 status = acpi_install_notify_handler(dev_handle, 283 ACPI_SYSTEM_NOTIFY, &acpi_bus_notify, NULL); 284 285 if (ACPI_SUCCESS(status)) { 286 prk_alert("TEST -- acpi_remove_notify_handler"); 287 status = acpi_remove_notify_handler(dev_handle, 288 ACPI_SYSTEM_NOTIFY, &acpi_bus_notify); 289 return acpi_failure(status, "acpi_remove_notify_handler"); 290 } else if (status != AE_ALREADY_EXISTS) { 291 return acpi_failure(status, "acpi_install_notify_handler"); 292 } 293 294 return 0; 295 } 296 297 static u32 ltp_test_power_button_ev_handler(void *context) 298 { 299 prk_alert("ltp_test_power_button_ev_handler"); 300 return 1; 301 } 302 303 static u32 ltp_test_sleep_button_ev_handler(void *context) 304 { 305 prk_alert("ltp_test_sleep_button_ev_handler"); 306 return 1; 307 } 308 309 static int acpi_test_event_handler(void) 310 { 311 int err = 0; 312 acpi_status status; 313 314 prk_alert("TEST -- acpi_install_fixed_event_handler"); 315 status = acpi_install_fixed_event_handler(ACPI_EVENT_POWER_BUTTON, 316 ltp_test_power_button_ev_handler, NULL); 317 318 if (ACPI_SUCCESS(status)) { 319 prk_alert("TEST -- acpi_remove_fixed_event_handler"); 320 status = acpi_remove_fixed_event_handler( 321 ACPI_EVENT_POWER_BUTTON, 322 ltp_test_power_button_ev_handler); 323 err = acpi_failure(status, "remove fixed event handler"); 324 } else if (status != AE_ALREADY_EXISTS) { 325 err = acpi_failure(status, "install fixed event handler"); 326 } 327 328 prk_alert("TEST -- acpi_install_fixed_event_handler"); 329 status = acpi_install_fixed_event_handler(ACPI_EVENT_RTC, 330 ltp_test_sleep_button_ev_handler, NULL); 331 332 if (ACPI_SUCCESS(status)) { 333 prk_alert("TEST -- acpi_remove_fixed_event_handler"); 334 status = acpi_remove_fixed_event_handler( 335 ACPI_EVENT_RTC, 336 ltp_test_sleep_button_ev_handler); 337 err |= acpi_failure(status, "remove fixed event handler"); 338 } else if (status != AE_ALREADY_EXISTS) { 339 err |= acpi_failure(status, "install fixed event handler"); 340 } 341 342 return err; 343 } 344 345 #ifndef ACPI_EC_UDELAY_GLK 346 #define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ 347 #endif 348 349 static int acpi_global_lock(void) 350 { 351 acpi_status status; 352 u32 global_lock = 0; 353 354 prk_alert("TEST -- acpi_acquire_global_lock "); 355 status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &global_lock); 356 if (acpi_failure(status, "acpi_acquire_global_lock")) 357 return 1; 358 359 prk_alert("TEST -- acpi_release_global_lock "); 360 status = acpi_release_global_lock(global_lock); 361 return acpi_failure(status, "acpi_release_global_lock"); 362 } 363 364 static int acpi_test_bus(void) 365 { 366 int state = 0; 367 acpi_status status; 368 acpi_handle bus_handle; 369 struct acpi_device *device; 370 371 status = acpi_get_handle(NULL, "\\_SB", &bus_handle); 372 if (acpi_failure(status, "acpi_get_handle")) 373 return 1; 374 375 prk_alert("TEST -- acpi_bus_get_device"); 376 status = acpi_bus_get_device(bus_handle, &device); 377 if (acpi_failure(status, "acpi_bus_get_device")) 378 return 1; 379 380 prk_alert("TEST -- acpi_bus_update_power "); 381 status = acpi_bus_update_power(device->handle, &state); 382 if (acpi_failure(status, "error reading power state")) 383 return 1; 384 385 prk_info("acpi bus power state is %d", state); 386 return 0; 387 } 388 389 static acpi_status acpi_ec_io_ports(struct acpi_resource *resource, 390 void *context) 391 { 392 return 0; 393 } 394 395 static int acpi_test_resources(void) 396 { 397 int err = 0; 398 acpi_status status; 399 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 400 401 /* skip if we don't find device with _CRC */ 402 if (res_handle == 0) 403 return 0; 404 405 prk_alert("TEST -- acpi_get_current_resources"); 406 status = acpi_get_current_resources(res_handle, &buffer); 407 err = acpi_failure(status, "failed get_current_resources"); 408 409 #ifdef ACPI_FUTURE_USAGE 410 prk_alert("TEST -- acpi_get_possible_resources"); 411 status = acpi_get_possible_resources(res_handle, &buffer); 412 err |= acpi_failure(status, "get_possible_resources"); 413 #endif 414 415 prk_alert("TEST -- acpi_walk_resources "); 416 status = acpi_walk_resources(res_handle, METHOD_NAME__CRS, 417 acpi_ec_io_ports, NULL); 418 err |= acpi_failure(status, "Failed walk_resources"); 419 420 return err; 421 } 422 423 static int acpi_sleep_test(void) 424 { 425 int err = 0; 426 acpi_status status; 427 u32 i; 428 u8 type_a, type_b; 429 prk_alert("TEST -- acpi_get_sleep_type_data "); 430 431 for (i = 0; i < ACPI_S_STATE_COUNT; ++i) { 432 status = acpi_get_sleep_type_data(i, &type_a, &type_b); 433 if (ACPI_SUCCESS(status)) { 434 prk_info("get_sleep_type_data S%d a:%d b:%d", 435 i, type_a, type_b); 436 } else if (status != AE_NOT_FOUND) { 437 err |= 1; 438 } 439 } 440 441 return err; 442 } 443 444 static int acpi_test_register(void) 445 { 446 int i, err = 0; 447 u32 val; 448 acpi_status status; 449 450 prk_alert("TEST -- acpi_read_bit_register"); 451 /* 452 * ACPICA: Remove obsolete Flags parameter. 453 * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git; 454 * a=commitdiff;h=d8c71b6d3b21cf21ad775e1cf6da95bf87bd5ad4 455 * 456 * ACPICA: Rename ACPI bit register access functions 457 * http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/ 458 * commit/?id=50ffba1bd3120b069617455545bc27bcf3cf7579 459 */ 460 for (i = 0; i < ACPI_NUM_BITREG; ++i) { 461 status = acpi_read_bit_register(i, &val); 462 err |= acpi_failure(status, "acpi_read_bit_register"); 463 if (ACPI_SUCCESS(status)) 464 prk_alert("get register: %02x val: %04x", i, val); 465 } 466 467 return err; 468 } 469 470 static acpi_status ltp_get_dev_callback(acpi_handle obj, u32 depth, 471 void *context, void **ret) 472 { 473 char *name = context; 474 char fullname[20]; 475 476 /* 477 * Only SBA shows up in ACPI namespace, so its CSR space 478 * includes both SBA and IOC. Make SBA and IOC show up 479 * separately in PCI space. 480 */ 481 sprintf(fullname, "%s SBA", name); 482 prk_info("get_dev_callback SBA name %s", fullname); 483 sprintf(fullname, "%s IOC", name); 484 prk_info("get_dev_callback IOC name %s", fullname); 485 486 return 0; 487 } 488 489 static int acpi_test_dev_callback(void) 490 { 491 acpi_status status; 492 prk_alert("TEST -- acpi_get_devices "); 493 status = acpi_get_devices(NULL, ltp_get_dev_callback, "LTP0001", NULL); 494 return acpi_failure(status, "acpi_get_devices"); 495 } 496 497 static int current_test_case; 498 static int test_result; 499 500 static void device_release(struct device *dev) 501 { 502 prk_info("device released"); 503 } 504 505 static struct device tdev = { 506 .init_name = ACPI_TEST_NAME, 507 .release = device_release, 508 }; 509 510 /* print test result to sysfs file */ 511 static ssize_t sys_result(struct device *dev, 512 struct device_attribute *attr, char *buf) 513 { 514 return scnprintf(buf, PAGE_SIZE, "%d\n", test_result); 515 } 516 static DEVICE_ATTR(result, S_IRUSR, sys_result, NULL); 517 518 /* print found device description */ 519 static ssize_t sys_str(struct device *dev, 520 struct device_attribute *attr, char *buf) 521 { 522 if (str_obj_result) 523 return scnprintf(buf, PAGE_SIZE, "%s", str_obj_result); 524 else 525 return 0; 526 } 527 static DEVICE_ATTR(str, S_IRUSR, sys_str, NULL); 528 529 /* print found device's sysfs path */ 530 static ssize_t sys_path(struct device *dev, 531 struct device_attribute *attr, char *buf) 532 { 533 if (sysfs_path) 534 return scnprintf(buf, PAGE_SIZE, "%s", sysfs_path); 535 else 536 return 0; 537 } 538 static DEVICE_ATTR(path, S_IRUSR, sys_path, NULL); 539 540 static ssize_t sys_tcase(struct device *dev, 541 struct device_attribute *attr, const char *buf, size_t count) 542 { 543 sscanf(buf, "%d", ¤t_test_case); 544 prk_info("test-case %d", current_test_case); 545 546 switch (current_test_case) { 547 case ACPI_INIT: 548 test_result = acpi_init(); 549 break; 550 case ACPI_TRAVERSE: 551 test_result = acpi_traverse_from_root(); 552 break; 553 case ACPI_NOTIFY_HANDLER: 554 test_result = acpi_test_notify_handler(); 555 break; 556 case ACPI_EVENT_HANDLER: 557 test_result = acpi_test_event_handler(); 558 break; 559 case ACPI_GLOBAL_LOCK: 560 test_result = acpi_global_lock(); 561 break; 562 case ACPI_TEST_BUS: 563 test_result = acpi_test_bus(); 564 break; 565 case ACPI_TEST_RESOURCES: 566 test_result = acpi_test_resources(); 567 break; 568 case ACPI_SLEEP_TEST: 569 test_result = acpi_sleep_test(); 570 break; 571 case ACPI_TEST_REGISTER: 572 test_result = acpi_test_register(); 573 break; 574 case ACPI_TEST_DEV_CALLBACK: 575 test_result = acpi_test_dev_callback(); 576 break; 577 } 578 579 return count; 580 } 581 static DEVICE_ATTR(tcase, S_IWUSR, NULL, sys_tcase); 582 583 int init_module(void) 584 { 585 int err = 0; 586 prk_info("Starting module"); 587 588 err = device_register(&tdev); 589 if (err) { 590 prk_err("Unable to register device"); 591 goto err0; 592 } 593 prk_info("device registered"); 594 595 err = device_create_file(&tdev, &dev_attr_result); 596 if (err) { 597 prk_err("Can't create sysfs file 'result'"); 598 goto err1; 599 } 600 601 err = device_create_file(&tdev, &dev_attr_str); 602 if (err) { 603 prk_err("Can't create sysfs file 'str'"); 604 goto err2; 605 } 606 607 err = device_create_file(&tdev, &dev_attr_tcase); 608 if (err) { 609 prk_err(": Can't create sysfs file 'tc'"); 610 goto err3; 611 } 612 613 err = device_create_file(&tdev, &dev_attr_path); 614 if (err) { 615 prk_err(": Can't create sysfs file 'path'"); 616 goto err4; 617 } 618 619 return 0; 620 621 err4: 622 device_remove_file(&tdev, &dev_attr_tcase); 623 err3: 624 device_remove_file(&tdev, &dev_attr_str); 625 err2: 626 device_remove_file(&tdev, &dev_attr_result); 627 err1: 628 device_unregister(&tdev); 629 err0: 630 return err; 631 } 632 633 void cleanup_module(void) 634 { 635 prk_info("Unloading module\n"); 636 637 kfree(str_obj_result); 638 kfree(sysfs_path); 639 640 device_remove_file(&tdev, &dev_attr_result); 641 device_remove_file(&tdev, &dev_attr_str); 642 device_remove_file(&tdev, &dev_attr_tcase); 643 device_remove_file(&tdev, &dev_attr_path); 644 device_unregister(&tdev); 645 } 646