Lines Matching +full:poll +full:- +full:retry +full:- +full:count

1 // SPDX-License-Identifier: GPL-2.0+
16 #include <linux/poll.h>
21 #define DRV_NAME "cros-ec-debugfs"
27 #define CIRC_ADD(idx, size, value) (((idx) + (value)) & ((size) - 1))
37 * struct cros_ec_debugfs - EC debugging information.
44 * @log_poll_work: recurring task to poll EC for new console log data
72 struct cros_ec_dev *ec = debug_info->ec; in cros_ec_console_log_work()
73 struct circ_buf *cb = &debug_info->log_buffer; in cros_ec_console_log_work()
75 .command = EC_CMD_CONSOLE_SNAPSHOT + ec->cmd_offset, in cros_ec_console_log_work()
79 (struct ec_params_console_read_v1 *)debug_info->read_msg->data; in cros_ec_console_log_work()
80 uint8_t *ec_buffer = (uint8_t *)debug_info->read_msg->data; in cros_ec_console_log_work()
85 ret = cros_ec_cmd_xfer_status(ec->ec_dev, &snapshot_msg); in cros_ec_console_log_work()
90 mutex_lock(&debug_info->log_mutex); in cros_ec_console_log_work()
91 buf_space = CIRC_SPACE(cb->head, cb->tail, LOG_SIZE); in cros_ec_console_log_work()
95 dev_info_once(ec->dev, in cros_ec_console_log_work()
101 read_params->subcmd = CONSOLE_READ_RECENT; in cros_ec_console_log_work()
102 ret = cros_ec_cmd_xfer_status(ec->ec_dev, in cros_ec_console_log_work()
103 debug_info->read_msg); in cros_ec_console_log_work()
113 cb->buf[cb->head] = ec_buffer[idx]; in cros_ec_console_log_work()
114 cb->head = CIRC_ADD(cb->head, LOG_SIZE, 1); in cros_ec_console_log_work()
116 buf_space--; in cros_ec_console_log_work()
122 mutex_unlock(&debug_info->log_mutex); in cros_ec_console_log_work()
125 schedule_delayed_work(&debug_info->log_poll_work, in cros_ec_console_log_work()
131 file->private_data = inode->i_private; in cros_ec_console_log_open()
137 size_t count, loff_t *ppos) in cros_ec_console_log_read() argument
139 struct cros_ec_debugfs *debug_info = file->private_data; in cros_ec_console_log_read()
140 struct circ_buf *cb = &debug_info->log_buffer; in cros_ec_console_log_read()
143 mutex_lock(&debug_info->log_mutex); in cros_ec_console_log_read()
145 while (!CIRC_CNT(cb->head, cb->tail, LOG_SIZE)) { in cros_ec_console_log_read()
146 if (file->f_flags & O_NONBLOCK) { in cros_ec_console_log_read()
147 ret = -EAGAIN; in cros_ec_console_log_read()
151 mutex_unlock(&debug_info->log_mutex); in cros_ec_console_log_read()
154 CIRC_CNT(cb->head, cb->tail, LOG_SIZE)); in cros_ec_console_log_read()
158 mutex_lock(&debug_info->log_mutex); in cros_ec_console_log_read()
162 * retry to get the rest of the data. in cros_ec_console_log_read()
164 ret = min_t(size_t, CIRC_CNT_TO_END(cb->head, cb->tail, LOG_SIZE), in cros_ec_console_log_read()
165 count); in cros_ec_console_log_read()
167 if (copy_to_user(buf, cb->buf + cb->tail, ret)) { in cros_ec_console_log_read()
168 ret = -EFAULT; in cros_ec_console_log_read()
172 cb->tail = CIRC_ADD(cb->tail, LOG_SIZE, ret); in cros_ec_console_log_read()
175 mutex_unlock(&debug_info->log_mutex); in cros_ec_console_log_read()
182 struct cros_ec_debugfs *debug_info = file->private_data; in cros_ec_console_log_poll()
187 mutex_lock(&debug_info->log_mutex); in cros_ec_console_log_poll()
188 if (CIRC_CNT(debug_info->log_buffer.head, in cros_ec_console_log_poll()
189 debug_info->log_buffer.tail, in cros_ec_console_log_poll()
192 mutex_unlock(&debug_info->log_mutex); in cros_ec_console_log_poll()
204 size_t count, in cros_ec_pdinfo_read() argument
208 struct cros_ec_debugfs *debug_info = file->private_data; in cros_ec_pdinfo_read()
209 struct cros_ec_device *ec_dev = debug_info->ec->ec_dev; in cros_ec_pdinfo_read()
223 params = (struct ec_params_usb_pd_control *)msg->data; in cros_ec_pdinfo_read()
224 resp = (struct ec_response_usb_pd_control_v1 *)msg->data; in cros_ec_pdinfo_read()
226 msg->command = EC_CMD_USB_PD_CONTROL; in cros_ec_pdinfo_read()
227 msg->version = 1; in cros_ec_pdinfo_read()
228 msg->insize = sizeof(*resp); in cros_ec_pdinfo_read()
229 msg->outsize = sizeof(*params); in cros_ec_pdinfo_read()
236 params->port = i; in cros_ec_pdinfo_read()
237 params->role = 0; in cros_ec_pdinfo_read()
238 params->mux = 0; in cros_ec_pdinfo_read()
239 params->swap = 0; in cros_ec_pdinfo_read()
244 p += scnprintf(p, sizeof(read_buf) + read_buf - p, in cros_ec_pdinfo_read()
246 resp->state, resp->enabled, resp->role, in cros_ec_pdinfo_read()
247 resp->polarity); in cros_ec_pdinfo_read()
250 return simple_read_from_buffer(user_buf, count, ppos, in cros_ec_pdinfo_read()
251 read_buf, p - read_buf); in cros_ec_pdinfo_read()
266 if (ret == -EPROTO && msg.cmd.result == EC_RES_INVALID_COMMAND) in cros_ec_uptime_is_supported()
274 size_t count, loff_t *ppos) in cros_ec_uptime_read() argument
276 struct cros_ec_debugfs *debug_info = file->private_data; in cros_ec_uptime_read()
277 struct cros_ec_device *ec_dev = debug_info->ec->ec_dev; in cros_ec_uptime_read()
296 resp->time_since_ec_boot_ms); in cros_ec_uptime_read()
298 return simple_read_from_buffer(user_buf, count, ppos, read_buf, ret); in cros_ec_uptime_read()
305 .poll = cros_ec_console_log_poll,
336 msg->version = 1; in ec_read_version_supported()
337 msg->command = EC_CMD_GET_CMD_VERSIONS + ec->cmd_offset; in ec_read_version_supported()
338 msg->outsize = sizeof(*params); in ec_read_version_supported()
339 msg->insize = sizeof(*response); in ec_read_version_supported()
341 params = (struct ec_params_get_cmd_versions_v1 *)msg->data; in ec_read_version_supported()
342 params->cmd = EC_CMD_CONSOLE_READ; in ec_read_version_supported()
343 response = (struct ec_response_get_cmd_versions *)msg->data; in ec_read_version_supported()
345 ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg) >= 0 && in ec_read_version_supported()
346 response->version_mask & EC_VER_MASK(1); in ec_read_version_supported()
355 struct cros_ec_dev *ec = debug_info->ec; in cros_ec_create_console_log()
367 buf = devm_kzalloc(ec->dev, LOG_SIZE, GFP_KERNEL); in cros_ec_create_console_log()
369 return -ENOMEM; in cros_ec_create_console_log()
372 read_response_size = ec->ec_dev->max_response; in cros_ec_create_console_log()
373 debug_info->read_msg = devm_kzalloc(ec->dev, in cros_ec_create_console_log()
374 sizeof(*debug_info->read_msg) + in cros_ec_create_console_log()
376 if (!debug_info->read_msg) in cros_ec_create_console_log()
377 return -ENOMEM; in cros_ec_create_console_log()
379 debug_info->read_msg->version = 1; in cros_ec_create_console_log()
380 debug_info->read_msg->command = EC_CMD_CONSOLE_READ + ec->cmd_offset; in cros_ec_create_console_log()
381 debug_info->read_msg->outsize = read_params_size; in cros_ec_create_console_log()
382 debug_info->read_msg->insize = read_response_size; in cros_ec_create_console_log()
384 debug_info->log_buffer.buf = buf; in cros_ec_create_console_log()
385 debug_info->log_buffer.head = 0; in cros_ec_create_console_log()
386 debug_info->log_buffer.tail = 0; in cros_ec_create_console_log()
388 mutex_init(&debug_info->log_mutex); in cros_ec_create_console_log()
390 debugfs_create_file("console_log", S_IFREG | 0444, debug_info->dir, in cros_ec_create_console_log()
393 INIT_DELAYED_WORK(&debug_info->log_poll_work, in cros_ec_create_console_log()
395 schedule_delayed_work(&debug_info->log_poll_work, 0); in cros_ec_create_console_log()
402 if (debug_info->log_buffer.buf) { in cros_ec_cleanup_console_log()
403 cancel_delayed_work_sync(&debug_info->log_poll_work); in cros_ec_cleanup_console_log()
404 mutex_destroy(&debug_info->log_mutex); in cros_ec_cleanup_console_log()
417 if (!data || data_size <= 0 || data_size > ec_dev->max_response) in cros_ec_get_panicinfo()
418 return -EINVAL; in cros_ec_get_panicinfo()
422 return -ENOMEM; in cros_ec_get_panicinfo()
424 msg->command = EC_CMD_GET_PANIC_INFO; in cros_ec_get_panicinfo()
425 msg->insize = data_size; in cros_ec_get_panicinfo()
431 memcpy(data, msg->data, data_size); in cros_ec_get_panicinfo()
440 struct cros_ec_device *ec_dev = debug_info->ec->ec_dev; in cros_ec_create_panicinfo()
444 data = devm_kzalloc(debug_info->ec->dev, ec_dev->max_response, in cros_ec_create_panicinfo()
447 return -ENOMEM; in cros_ec_create_panicinfo()
449 ret = cros_ec_get_panicinfo(ec_dev, data, ec_dev->max_response); in cros_ec_create_panicinfo()
459 debug_info->panicinfo_blob.data = data; in cros_ec_create_panicinfo()
460 debug_info->panicinfo_blob.size = ret; in cros_ec_create_panicinfo()
462 debugfs_create_blob("panicinfo", 0444, debug_info->dir, in cros_ec_create_panicinfo()
463 &debug_info->panicinfo_blob); in cros_ec_create_panicinfo()
468 devm_kfree(debug_info->ec->dev, data); in cros_ec_create_panicinfo()
478 if (debug_info->log_buffer.buf) { in cros_ec_debugfs_panic_event()
479 /* Force log poll work to run immediately */ in cros_ec_debugfs_panic_event()
480 mod_delayed_work(debug_info->log_poll_work.wq, &debug_info->log_poll_work, 0); in cros_ec_debugfs_panic_event()
481 /* Block until log poll work finishes */ in cros_ec_debugfs_panic_event()
482 flush_delayed_work(&debug_info->log_poll_work); in cros_ec_debugfs_panic_event()
490 struct cros_ec_dev *ec = dev_get_drvdata(pd->dev.parent); in cros_ec_debugfs_probe()
491 struct cros_ec_platform *ec_platform = dev_get_platdata(ec->dev); in cros_ec_debugfs_probe()
492 const char *name = ec_platform->ec_name; in cros_ec_debugfs_probe()
496 debug_info = devm_kzalloc(ec->dev, sizeof(*debug_info), GFP_KERNEL); in cros_ec_debugfs_probe()
498 return -ENOMEM; in cros_ec_debugfs_probe()
500 debug_info->ec = ec; in cros_ec_debugfs_probe()
501 debug_info->dir = debugfs_create_dir(name, NULL); in cros_ec_debugfs_probe()
511 debugfs_create_file("pdinfo", 0444, debug_info->dir, debug_info, in cros_ec_debugfs_probe()
514 if (cros_ec_uptime_is_supported(ec->ec_dev)) in cros_ec_debugfs_probe()
515 debugfs_create_file("uptime", 0444, debug_info->dir, debug_info, in cros_ec_debugfs_probe()
518 debugfs_create_x32("last_resume_result", 0444, debug_info->dir, in cros_ec_debugfs_probe()
519 &ec->ec_dev->last_resume_result); in cros_ec_debugfs_probe()
521 debugfs_create_u16("suspend_timeout_ms", 0664, debug_info->dir, in cros_ec_debugfs_probe()
522 &ec->ec_dev->suspend_timeout_ms); in cros_ec_debugfs_probe()
524 debug_info->notifier_panic.notifier_call = cros_ec_debugfs_panic_event; in cros_ec_debugfs_probe()
525 ret = blocking_notifier_chain_register(&ec->ec_dev->panic_notifier, in cros_ec_debugfs_probe()
526 &debug_info->notifier_panic); in cros_ec_debugfs_probe()
530 ec->debug_info = debug_info; in cros_ec_debugfs_probe()
532 dev_set_drvdata(&pd->dev, ec); in cros_ec_debugfs_probe()
537 debugfs_remove_recursive(debug_info->dir); in cros_ec_debugfs_probe()
543 struct cros_ec_dev *ec = dev_get_drvdata(pd->dev.parent); in cros_ec_debugfs_remove()
545 debugfs_remove_recursive(ec->debug_info->dir); in cros_ec_debugfs_remove()
546 cros_ec_cleanup_console_log(ec->debug_info); in cros_ec_debugfs_remove()
553 if (ec->debug_info->log_buffer.buf) in cros_ec_debugfs_suspend()
554 cancel_delayed_work_sync(&ec->debug_info->log_poll_work); in cros_ec_debugfs_suspend()
563 if (ec->debug_info->log_buffer.buf) in cros_ec_debugfs_resume()
564 schedule_delayed_work(&ec->debug_info->log_poll_work, 0); in cros_ec_debugfs_resume()