/* waitqueue for log readers */ static DECLARE_WAIT_QUEUE_HEAD(cros_ec_debugfs_log_wq);
/** * struct cros_ec_debugfs - EC debugging information. * * @ec: EC device this debugfs information belongs to * @dir: dentry for debugfs files * @log_buffer: circular buffer for console log information * @read_msg: preallocated EC command and buffer to read console log * @log_mutex: mutex to protect circular buffer * @log_poll_work: recurring task to poll EC for new console log data * @panicinfo_blob: panicinfo debugfs blob * @notifier_panic: notifier_block to let kernel to flush buffered log * when EC panic
*/ struct cros_ec_debugfs { struct cros_ec_dev *ec; struct dentry *dir; /* EC log */ struct circ_buf log_buffer; struct cros_ec_command *read_msg; struct mutex log_mutex; struct delayed_work log_poll_work; /* EC panicinfo */ struct debugfs_blob_wrapper panicinfo_blob; struct notifier_block notifier_panic;
};
/* * We need to make sure that the EC log buffer on the UART is large enough, * so that it is unlikely enough to overlow within log_poll_period_ms.
*/ staticvoid cros_ec_console_log_work(struct work_struct *__work)
{ struct cros_ec_debugfs *debug_info =
container_of(to_delayed_work(__work), struct cros_ec_debugfs,
log_poll_work); struct cros_ec_dev *ec = debug_info->ec; struct circ_buf *cb = &debug_info->log_buffer; struct cros_ec_command snapshot_msg = {
.command = EC_CMD_CONSOLE_SNAPSHOT + ec->cmd_offset,
};
struct ec_params_console_read_v1 *read_params =
(struct ec_params_console_read_v1 *)debug_info->read_msg->data;
uint8_t *ec_buffer = (uint8_t *)debug_info->read_msg->data; int idx; int buf_space; int ret;
ret = cros_ec_cmd_xfer_status(ec->ec_dev, &snapshot_msg); if (ret < 0) goto resched;
/* Loop until we have read everything, or there's an error. */
mutex_lock(&debug_info->log_mutex);
buf_space = CIRC_SPACE(cb->head, cb->tail, LOG_SIZE);
while (1) { if (!buf_space) {
dev_info_once(ec->dev, "Some logs may have been dropped...\n"); break;
}
memset(read_params, '\0', sizeof(*read_params));
read_params->subcmd = CONSOLE_READ_RECENT;
ret = cros_ec_cmd_xfer_status(ec->ec_dev,
debug_info->read_msg); if (ret < 0) break;
/* If the buffer is empty, we're done here. */ if (ret == 0 || ec_buffer[0] == '\0') break;
while (!CIRC_CNT(cb->head, cb->tail, LOG_SIZE)) { if (file->f_flags & O_NONBLOCK) {
ret = -EAGAIN; goto error;
}
mutex_unlock(&debug_info->log_mutex);
ret = wait_event_interruptible(cros_ec_debugfs_log_wq,
CIRC_CNT(cb->head, cb->tail, LOG_SIZE)); if (ret < 0) return ret;
mutex_lock(&debug_info->log_mutex);
}
/* Only copy until the end of the circular buffer, and let userspace * retry to get the rest of the data.
*/
ret = min_t(size_t, CIRC_CNT_TO_END(cb->head, cb->tail, LOG_SIZE),
count);
if (copy_to_user(buf, cb->buf + cb->tail, ret)) {
ret = -EFAULT; goto error;
}
/* * Read status from all PD ports until failure, typically caused * by attempting to read status on a port that doesn't exist.
*/ for (i = 0; i < EC_USB_PD_MAX_PORTS; ++i) {
params->port = i;
params->role = 0;
params->mux = 0;
params->swap = 0;
if (cros_ec_cmd_xfer_status(ec_dev, msg) < 0) break;
p += scnprintf(p, sizeof(read_buf) + read_buf - p, "p%d: %s en:%.2x role:%.2x pol:%.2x\n", i,
resp->state, resp->enabled, resp->role,
resp->polarity);
}
return simple_read_from_buffer(user_buf, count, ppos,
read_buf, p - read_buf);
}
ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg) >= 0 &&
response->version_mask & EC_VER_MASK(1);
kfree(msg);
return ret;
}
staticint cros_ec_create_console_log(struct cros_ec_debugfs *debug_info)
{ struct cros_ec_dev *ec = debug_info->ec; char *buf; int read_params_size; int read_response_size;
/* * If the console log feature is not supported return silently and * don't create the console_log entry.
*/ if (!ec_read_version_supported(ec)) return 0;
buf = devm_kzalloc(ec->dev, LOG_SIZE, GFP_KERNEL); if (!buf) return -ENOMEM;
/* * Returns the size of the panicinfo data fetched from the EC
*/ staticint cros_ec_get_panicinfo(struct cros_ec_device *ec_dev, uint8_t *data, int data_size)
{ int ret; struct cros_ec_command *msg;
if (debug_info->log_buffer.buf) { /* Force log poll work to run immediately */
mod_delayed_work(debug_info->log_poll_work.wq, &debug_info->log_poll_work, 0); /* Block until log poll work finishes */
flush_delayed_work(&debug_info->log_poll_work);
}
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Debug logs for ChromeOS EC");
Messung V0.5
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.18Bemerkung:
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.