Home | History | Annotate | Download | only in acpi
      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", &current_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