|
@@ -8,6 +8,7 @@
|
|
|
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
|
|
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
|
|
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
|
|
+ * Copyright (C) 2018 Intel Corporation
|
|
|
*
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
* it under the terms of version 2 of the GNU General Public License as
|
|
@@ -33,6 +34,7 @@
|
|
|
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
|
|
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
|
|
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
|
|
+ * Copyright (C) 2018 Intel Corporation
|
|
|
* All rights reserved.
|
|
|
*
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
@@ -66,55 +68,117 @@
|
|
|
#include "debugfs.h"
|
|
|
#include "dbg.h"
|
|
|
|
|
|
-#define FWRT_DEBUGFS_READ_FILE_OPS(name) \
|
|
|
-static ssize_t iwl_dbgfs_##name##_read(struct iwl_fw_runtime *fwrt, \
|
|
|
- char *buf, size_t count, \
|
|
|
- loff_t *ppos); \
|
|
|
+#define FWRT_DEBUGFS_OPEN_WRAPPER(name, buflen, argtype) \
|
|
|
+struct dbgfs_##name##_data { \
|
|
|
+ argtype *arg; \
|
|
|
+ bool read_done; \
|
|
|
+ ssize_t rlen; \
|
|
|
+ char rbuf[buflen]; \
|
|
|
+}; \
|
|
|
+static int _iwl_dbgfs_##name##_open(struct inode *inode, \
|
|
|
+ struct file *file) \
|
|
|
+{ \
|
|
|
+ struct dbgfs_##name##_data *data; \
|
|
|
+ \
|
|
|
+ data = kzalloc(sizeof(*data), GFP_KERNEL); \
|
|
|
+ if (!data) \
|
|
|
+ return -ENOMEM; \
|
|
|
+ \
|
|
|
+ data->read_done = false; \
|
|
|
+ data->arg = inode->i_private; \
|
|
|
+ file->private_data = data; \
|
|
|
+ \
|
|
|
+ return 0; \
|
|
|
+}
|
|
|
+
|
|
|
+#define FWRT_DEBUGFS_READ_WRAPPER(name) \
|
|
|
+static ssize_t _iwl_dbgfs_##name##_read(struct file *file, \
|
|
|
+ char __user *user_buf, \
|
|
|
+ size_t count, loff_t *ppos) \
|
|
|
+{ \
|
|
|
+ struct dbgfs_##name##_data *data = file->private_data; \
|
|
|
+ \
|
|
|
+ if (!data->read_done) { \
|
|
|
+ data->read_done = true; \
|
|
|
+ data->rlen = iwl_dbgfs_##name##_read(data->arg, \
|
|
|
+ sizeof(data->rbuf),\
|
|
|
+ data->rbuf); \
|
|
|
+ } \
|
|
|
+ \
|
|
|
+ if (data->rlen < 0) \
|
|
|
+ return data->rlen; \
|
|
|
+ return simple_read_from_buffer(user_buf, count, ppos, \
|
|
|
+ data->rbuf, data->rlen); \
|
|
|
+}
|
|
|
+
|
|
|
+static int _iwl_dbgfs_release(struct inode *inode, struct file *file)
|
|
|
+{
|
|
|
+ kfree(file->private_data);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+#define _FWRT_DEBUGFS_READ_FILE_OPS(name, buflen, argtype) \
|
|
|
+FWRT_DEBUGFS_OPEN_WRAPPER(name, buflen, argtype) \
|
|
|
+FWRT_DEBUGFS_READ_WRAPPER(name) \
|
|
|
static const struct file_operations iwl_dbgfs_##name##_ops = { \
|
|
|
- .read = iwl_dbgfs_##name##_read, \
|
|
|
- .open = simple_open, \
|
|
|
+ .read = _iwl_dbgfs_##name##_read, \
|
|
|
+ .open = _iwl_dbgfs_##name##_open, \
|
|
|
.llseek = generic_file_llseek, \
|
|
|
+ .release = _iwl_dbgfs_release, \
|
|
|
}
|
|
|
|
|
|
-#define FWRT_DEBUGFS_WRITE_WRAPPER(name, buflen) \
|
|
|
-static ssize_t iwl_dbgfs_##name##_write(struct iwl_fw_runtime *fwrt, \
|
|
|
- char *buf, size_t count, \
|
|
|
- loff_t *ppos); \
|
|
|
+#define FWRT_DEBUGFS_WRITE_WRAPPER(name, buflen, argtype) \
|
|
|
static ssize_t _iwl_dbgfs_##name##_write(struct file *file, \
|
|
|
const char __user *user_buf, \
|
|
|
size_t count, loff_t *ppos) \
|
|
|
{ \
|
|
|
- struct iwl_fw_runtime *fwrt = file->private_data; \
|
|
|
+ argtype *arg = \
|
|
|
+ ((struct dbgfs_##name##_data *)file->private_data)->arg;\
|
|
|
char buf[buflen] = {}; \
|
|
|
size_t buf_size = min(count, sizeof(buf) - 1); \
|
|
|
\
|
|
|
if (copy_from_user(buf, user_buf, buf_size)) \
|
|
|
return -EFAULT; \
|
|
|
\
|
|
|
- return iwl_dbgfs_##name##_write(fwrt, buf, buf_size, ppos); \
|
|
|
+ return iwl_dbgfs_##name##_write(arg, buf, buf_size); \
|
|
|
}
|
|
|
|
|
|
-#define FWRT_DEBUGFS_READ_WRITE_FILE_OPS(name, buflen) \
|
|
|
-FWRT_DEBUGFS_WRITE_WRAPPER(name, buflen) \
|
|
|
+#define _FWRT_DEBUGFS_READ_WRITE_FILE_OPS(name, buflen, argtype) \
|
|
|
+FWRT_DEBUGFS_OPEN_WRAPPER(name, buflen, argtype) \
|
|
|
+FWRT_DEBUGFS_WRITE_WRAPPER(name, buflen, argtype) \
|
|
|
+FWRT_DEBUGFS_READ_WRAPPER(name) \
|
|
|
static const struct file_operations iwl_dbgfs_##name##_ops = { \
|
|
|
.write = _iwl_dbgfs_##name##_write, \
|
|
|
- .read = iwl_dbgfs_##name##_read, \
|
|
|
- .open = simple_open, \
|
|
|
+ .read = _iwl_dbgfs_##name##_read, \
|
|
|
+ .open = _iwl_dbgfs_##name##_open, \
|
|
|
.llseek = generic_file_llseek, \
|
|
|
+ .release = _iwl_dbgfs_release, \
|
|
|
}
|
|
|
|
|
|
-#define FWRT_DEBUGFS_WRITE_FILE_OPS(name, buflen) \
|
|
|
-FWRT_DEBUGFS_WRITE_WRAPPER(name, buflen) \
|
|
|
+#define _FWRT_DEBUGFS_WRITE_FILE_OPS(name, buflen, argtype) \
|
|
|
+FWRT_DEBUGFS_OPEN_WRAPPER(name, buflen, argtype) \
|
|
|
+FWRT_DEBUGFS_WRITE_WRAPPER(name, buflen, argtype) \
|
|
|
static const struct file_operations iwl_dbgfs_##name##_ops = { \
|
|
|
.write = _iwl_dbgfs_##name##_write, \
|
|
|
- .open = simple_open, \
|
|
|
+ .open = _iwl_dbgfs_##name##_open, \
|
|
|
.llseek = generic_file_llseek, \
|
|
|
+ .release = _iwl_dbgfs_release, \
|
|
|
}
|
|
|
|
|
|
+#define FWRT_DEBUGFS_READ_FILE_OPS(name, bufsz) \
|
|
|
+ _FWRT_DEBUGFS_READ_FILE_OPS(name, bufsz, struct iwl_fw_runtime)
|
|
|
+
|
|
|
+#define FWRT_DEBUGFS_WRITE_FILE_OPS(name, bufsz) \
|
|
|
+ _FWRT_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct iwl_fw_runtime)
|
|
|
+
|
|
|
+#define FWRT_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \
|
|
|
+ _FWRT_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct iwl_fw_runtime)
|
|
|
+
|
|
|
#define FWRT_DEBUGFS_ADD_FILE_ALIAS(alias, name, parent, mode) do { \
|
|
|
- if (!debugfs_create_file(alias, mode, parent, fwrt, \
|
|
|
- &iwl_dbgfs_##name##_ops)) \
|
|
|
- goto err; \
|
|
|
+ if (!debugfs_create_file(alias, mode, parent, fwrt, \
|
|
|
+ &iwl_dbgfs_##name##_ops)) \
|
|
|
+ goto err; \
|
|
|
} while (0)
|
|
|
#define FWRT_DEBUGFS_ADD_FILE(name, parent, mode) \
|
|
|
FWRT_DEBUGFS_ADD_FILE_ALIAS(#name, name, parent, mode)
|
|
@@ -173,8 +237,7 @@ void iwl_fw_trigger_timestamp(struct iwl_fw_runtime *fwrt, u32 delay)
|
|
|
}
|
|
|
|
|
|
static ssize_t iwl_dbgfs_timestamp_marker_write(struct iwl_fw_runtime *fwrt,
|
|
|
- char *buf, size_t count,
|
|
|
- loff_t *ppos)
|
|
|
+ char *buf, size_t count)
|
|
|
{
|
|
|
int ret;
|
|
|
u32 delay;
|