diff options
author | Lv Zheng <lv.zheng@intel.com> | 2015-12-02 21:43:14 -0500 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2015-12-14 18:17:44 -0500 |
commit | 836d0830188a97d5c73e8eb514f346a857c086b9 (patch) | |
tree | c2eb9b87cdf6a5096e8d3bf2d1418717b2023a10 /drivers/acpi/osl.c | |
parent | 37645d6590a49d3009eecdf093599795da2b5b41 (diff) |
ACPI / debugger: Add module support for ACPI debugger
This patch converts AML debugger into a loadable module.
Note that, it implements driver unloading at the level dependent on the
module reference count. Which means if ACPI debugger is being used by a
userspace program, "rmmod acpi_dbg" should result in failure.
Signed-off-by: Lv Zheng <lv.zheng@intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/acpi/osl.c')
-rw-r--r-- | drivers/acpi/osl.c | 207 |
1 files changed, 201 insertions, 6 deletions
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 4c1339819bfc..bb66093b7799 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c | |||
@@ -40,7 +40,6 @@ | |||
40 | #include <linux/list.h> | 40 | #include <linux/list.h> |
41 | #include <linux/jiffies.h> | 41 | #include <linux/jiffies.h> |
42 | #include <linux/semaphore.h> | 42 | #include <linux/semaphore.h> |
43 | #include <linux/acpi_dbg.h> | ||
44 | 43 | ||
45 | #include <asm/io.h> | 44 | #include <asm/io.h> |
46 | #include <asm/uaccess.h> | 45 | #include <asm/uaccess.h> |
@@ -221,6 +220,7 @@ void acpi_os_printf(const char *fmt, ...) | |||
221 | acpi_os_vprintf(fmt, args); | 220 | acpi_os_vprintf(fmt, args); |
222 | va_end(args); | 221 | va_end(args); |
223 | } | 222 | } |
223 | EXPORT_SYMBOL(acpi_os_printf); | ||
224 | 224 | ||
225 | void acpi_os_vprintf(const char *fmt, va_list args) | 225 | void acpi_os_vprintf(const char *fmt, va_list args) |
226 | { | 226 | { |
@@ -235,7 +235,7 @@ void acpi_os_vprintf(const char *fmt, va_list args) | |||
235 | printk(KERN_CONT "%s", buffer); | 235 | printk(KERN_CONT "%s", buffer); |
236 | } | 236 | } |
237 | #else | 237 | #else |
238 | if (acpi_aml_write_log(buffer) < 0) | 238 | if (acpi_debugger_write_log(buffer) < 0) |
239 | printk(KERN_CONT "%s", buffer); | 239 | printk(KERN_CONT "%s", buffer); |
240 | #endif | 240 | #endif |
241 | } | 241 | } |
@@ -1103,6 +1103,200 @@ static void acpi_os_execute_deferred(struct work_struct *work) | |||
1103 | kfree(dpc); | 1103 | kfree(dpc); |
1104 | } | 1104 | } |
1105 | 1105 | ||
1106 | #ifdef CONFIG_ACPI_DEBUGGER | ||
1107 | static struct acpi_debugger acpi_debugger; | ||
1108 | static bool acpi_debugger_initialized; | ||
1109 | |||
1110 | int acpi_register_debugger(struct module *owner, | ||
1111 | const struct acpi_debugger_ops *ops) | ||
1112 | { | ||
1113 | int ret = 0; | ||
1114 | |||
1115 | mutex_lock(&acpi_debugger.lock); | ||
1116 | if (acpi_debugger.ops) { | ||
1117 | ret = -EBUSY; | ||
1118 | goto err_lock; | ||
1119 | } | ||
1120 | |||
1121 | acpi_debugger.owner = owner; | ||
1122 | acpi_debugger.ops = ops; | ||
1123 | |||
1124 | err_lock: | ||
1125 | mutex_unlock(&acpi_debugger.lock); | ||
1126 | return ret; | ||
1127 | } | ||
1128 | EXPORT_SYMBOL(acpi_register_debugger); | ||
1129 | |||
1130 | void acpi_unregister_debugger(const struct acpi_debugger_ops *ops) | ||
1131 | { | ||
1132 | mutex_lock(&acpi_debugger.lock); | ||
1133 | if (ops == acpi_debugger.ops) { | ||
1134 | acpi_debugger.ops = NULL; | ||
1135 | acpi_debugger.owner = NULL; | ||
1136 | } | ||
1137 | mutex_unlock(&acpi_debugger.lock); | ||
1138 | } | ||
1139 | EXPORT_SYMBOL(acpi_unregister_debugger); | ||
1140 | |||
1141 | int acpi_debugger_create_thread(acpi_osd_exec_callback function, void *context) | ||
1142 | { | ||
1143 | int ret; | ||
1144 | int (*func)(acpi_osd_exec_callback, void *); | ||
1145 | struct module *owner; | ||
1146 | |||
1147 | if (!acpi_debugger_initialized) | ||
1148 | return -ENODEV; | ||
1149 | mutex_lock(&acpi_debugger.lock); | ||
1150 | if (!acpi_debugger.ops) { | ||
1151 | ret = -ENODEV; | ||
1152 | goto err_lock; | ||
1153 | } | ||
1154 | if (!try_module_get(acpi_debugger.owner)) { | ||
1155 | ret = -ENODEV; | ||
1156 | goto err_lock; | ||
1157 | } | ||
1158 | func = acpi_debugger.ops->create_thread; | ||
1159 | owner = acpi_debugger.owner; | ||
1160 | mutex_unlock(&acpi_debugger.lock); | ||
1161 | |||
1162 | ret = func(function, context); | ||
1163 | |||
1164 | mutex_lock(&acpi_debugger.lock); | ||
1165 | module_put(owner); | ||
1166 | err_lock: | ||
1167 | mutex_unlock(&acpi_debugger.lock); | ||
1168 | return ret; | ||
1169 | } | ||
1170 | |||
1171 | ssize_t acpi_debugger_write_log(const char *msg) | ||
1172 | { | ||
1173 | ssize_t ret; | ||
1174 | ssize_t (*func)(const char *); | ||
1175 | struct module *owner; | ||
1176 | |||
1177 | if (!acpi_debugger_initialized) | ||
1178 | return -ENODEV; | ||
1179 | mutex_lock(&acpi_debugger.lock); | ||
1180 | if (!acpi_debugger.ops) { | ||
1181 | ret = -ENODEV; | ||
1182 | goto err_lock; | ||
1183 | } | ||
1184 | if (!try_module_get(acpi_debugger.owner)) { | ||
1185 | ret = -ENODEV; | ||
1186 | goto err_lock; | ||
1187 | } | ||
1188 | func = acpi_debugger.ops->write_log; | ||
1189 | owner = acpi_debugger.owner; | ||
1190 | mutex_unlock(&acpi_debugger.lock); | ||
1191 | |||
1192 | ret = func(msg); | ||
1193 | |||
1194 | mutex_lock(&acpi_debugger.lock); | ||
1195 | module_put(owner); | ||
1196 | err_lock: | ||
1197 | mutex_unlock(&acpi_debugger.lock); | ||
1198 | return ret; | ||
1199 | } | ||
1200 | |||
1201 | ssize_t acpi_debugger_read_cmd(char *buffer, size_t buffer_length) | ||
1202 | { | ||
1203 | ssize_t ret; | ||
1204 | ssize_t (*func)(char *, size_t); | ||
1205 | struct module *owner; | ||
1206 | |||
1207 | if (!acpi_debugger_initialized) | ||
1208 | return -ENODEV; | ||
1209 | mutex_lock(&acpi_debugger.lock); | ||
1210 | if (!acpi_debugger.ops) { | ||
1211 | ret = -ENODEV; | ||
1212 | goto err_lock; | ||
1213 | } | ||
1214 | if (!try_module_get(acpi_debugger.owner)) { | ||
1215 | ret = -ENODEV; | ||
1216 | goto err_lock; | ||
1217 | } | ||
1218 | func = acpi_debugger.ops->read_cmd; | ||
1219 | owner = acpi_debugger.owner; | ||
1220 | mutex_unlock(&acpi_debugger.lock); | ||
1221 | |||
1222 | ret = func(buffer, buffer_length); | ||
1223 | |||
1224 | mutex_lock(&acpi_debugger.lock); | ||
1225 | module_put(owner); | ||
1226 | err_lock: | ||
1227 | mutex_unlock(&acpi_debugger.lock); | ||
1228 | return ret; | ||
1229 | } | ||
1230 | |||
1231 | int acpi_debugger_wait_command_ready(void) | ||
1232 | { | ||
1233 | int ret; | ||
1234 | int (*func)(bool, char *, size_t); | ||
1235 | struct module *owner; | ||
1236 | |||
1237 | if (!acpi_debugger_initialized) | ||
1238 | return -ENODEV; | ||
1239 | mutex_lock(&acpi_debugger.lock); | ||
1240 | if (!acpi_debugger.ops) { | ||
1241 | ret = -ENODEV; | ||
1242 | goto err_lock; | ||
1243 | } | ||
1244 | if (!try_module_get(acpi_debugger.owner)) { | ||
1245 | ret = -ENODEV; | ||
1246 | goto err_lock; | ||
1247 | } | ||
1248 | func = acpi_debugger.ops->wait_command_ready; | ||
1249 | owner = acpi_debugger.owner; | ||
1250 | mutex_unlock(&acpi_debugger.lock); | ||
1251 | |||
1252 | ret = func(acpi_gbl_method_executing, | ||
1253 | acpi_gbl_db_line_buf, ACPI_DB_LINE_BUFFER_SIZE); | ||
1254 | |||
1255 | mutex_lock(&acpi_debugger.lock); | ||
1256 | module_put(owner); | ||
1257 | err_lock: | ||
1258 | mutex_unlock(&acpi_debugger.lock); | ||
1259 | return ret; | ||
1260 | } | ||
1261 | |||
1262 | int acpi_debugger_notify_command_complete(void) | ||
1263 | { | ||
1264 | int ret; | ||
1265 | int (*func)(void); | ||
1266 | struct module *owner; | ||
1267 | |||
1268 | if (!acpi_debugger_initialized) | ||
1269 | return -ENODEV; | ||
1270 | mutex_lock(&acpi_debugger.lock); | ||
1271 | if (!acpi_debugger.ops) { | ||
1272 | ret = -ENODEV; | ||
1273 | goto err_lock; | ||
1274 | } | ||
1275 | if (!try_module_get(acpi_debugger.owner)) { | ||
1276 | ret = -ENODEV; | ||
1277 | goto err_lock; | ||
1278 | } | ||
1279 | func = acpi_debugger.ops->notify_command_complete; | ||
1280 | owner = acpi_debugger.owner; | ||
1281 | mutex_unlock(&acpi_debugger.lock); | ||
1282 | |||
1283 | ret = func(); | ||
1284 | |||
1285 | mutex_lock(&acpi_debugger.lock); | ||
1286 | module_put(owner); | ||
1287 | err_lock: | ||
1288 | mutex_unlock(&acpi_debugger.lock); | ||
1289 | return ret; | ||
1290 | } | ||
1291 | |||
1292 | int __init acpi_debugger_init(void) | ||
1293 | { | ||
1294 | mutex_init(&acpi_debugger.lock); | ||
1295 | acpi_debugger_initialized = true; | ||
1296 | return 0; | ||
1297 | } | ||
1298 | #endif | ||
1299 | |||
1106 | /******************************************************************************* | 1300 | /******************************************************************************* |
1107 | * | 1301 | * |
1108 | * FUNCTION: acpi_os_execute | 1302 | * FUNCTION: acpi_os_execute |
@@ -1130,7 +1324,7 @@ acpi_status acpi_os_execute(acpi_execute_type type, | |||
1130 | function, context)); | 1324 | function, context)); |
1131 | 1325 | ||
1132 | if (type == OSL_DEBUGGER_MAIN_THREAD) { | 1326 | if (type == OSL_DEBUGGER_MAIN_THREAD) { |
1133 | ret = acpi_aml_create_thread(function, context); | 1327 | ret = acpi_debugger_create_thread(function, context); |
1134 | if (ret) { | 1328 | if (ret) { |
1135 | pr_err("Call to kthread_create() failed.\n"); | 1329 | pr_err("Call to kthread_create() failed.\n"); |
1136 | status = AE_ERROR; | 1330 | status = AE_ERROR; |
@@ -1380,7 +1574,7 @@ acpi_status acpi_os_get_line(char *buffer, u32 buffer_length, u32 *bytes_read) | |||
1380 | #else | 1574 | #else |
1381 | int ret; | 1575 | int ret; |
1382 | 1576 | ||
1383 | ret = acpi_aml_read_cmd(buffer, buffer_length); | 1577 | ret = acpi_debugger_read_cmd(buffer, buffer_length); |
1384 | if (ret < 0) | 1578 | if (ret < 0) |
1385 | return AE_ERROR; | 1579 | return AE_ERROR; |
1386 | if (bytes_read) | 1580 | if (bytes_read) |
@@ -1389,12 +1583,13 @@ acpi_status acpi_os_get_line(char *buffer, u32 buffer_length, u32 *bytes_read) | |||
1389 | 1583 | ||
1390 | return AE_OK; | 1584 | return AE_OK; |
1391 | } | 1585 | } |
1586 | EXPORT_SYMBOL(acpi_os_get_line); | ||
1392 | 1587 | ||
1393 | acpi_status acpi_os_wait_command_ready(void) | 1588 | acpi_status acpi_os_wait_command_ready(void) |
1394 | { | 1589 | { |
1395 | int ret; | 1590 | int ret; |
1396 | 1591 | ||
1397 | ret = acpi_aml_wait_command_ready(); | 1592 | ret = acpi_debugger_wait_command_ready(); |
1398 | if (ret < 0) | 1593 | if (ret < 0) |
1399 | return AE_ERROR; | 1594 | return AE_ERROR; |
1400 | return AE_OK; | 1595 | return AE_OK; |
@@ -1404,7 +1599,7 @@ acpi_status acpi_os_notify_command_complete(void) | |||
1404 | { | 1599 | { |
1405 | int ret; | 1600 | int ret; |
1406 | 1601 | ||
1407 | ret = acpi_aml_notify_command_complete(); | 1602 | ret = acpi_debugger_notify_command_complete(); |
1408 | if (ret < 0) | 1603 | if (ret < 0) |
1409 | return AE_ERROR; | 1604 | return AE_ERROR; |
1410 | return AE_OK; | 1605 | return AE_OK; |