From 51bac7676dd7f283db284455ce6cb0c975e0f001 Mon Sep 17 00:00:00 2001 From: Wu Gao Date: Thu, 5 Mar 2020 15:50:10 +0800 Subject: [PATCH] qcacmn: Add stream file system support Stream file system is wrapper for Relayfs - a Linux specific feature, which provides efficient method to indicate data to user space. It depends on qdf debugfs APIs. This feature is protected with compilation flags WLAN_STREAMFS and WLAN_DEBUGFS. Change-Id: I1401112ece290e6d0560623cf10faaf498ebb1b7 CRs-Fixed: 2635481 --- qdf/inc/qdf_streamfs.h | 207 +++++++++++++++++++++++++++++++++ qdf/linux/src/i_qdf_streamfs.h | 32 +++++ qdf/linux/src/qdf_streamfs.c | 149 ++++++++++++++++++++++++ 3 files changed, 388 insertions(+) create mode 100644 qdf/inc/qdf_streamfs.h create mode 100644 qdf/linux/src/i_qdf_streamfs.h create mode 100644 qdf/linux/src/qdf_streamfs.c diff --git a/qdf/inc/qdf_streamfs.h b/qdf/inc/qdf_streamfs.h new file mode 100644 index 0000000000..f6449cbe47 --- /dev/null +++ b/qdf/inc/qdf_streamfs.h @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2018, 2020 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: qdf_streamfs.h + * This file provides OS abstraction for stream filesystem APIs. + */ + +#ifndef _QDF_STREAMFS_H +#define _QDF_STREAMFS_H + +#include +#include +#include + +typedef __qdf_streamfs_chan_t qdf_streamfs_chan_t; +typedef __qdf_streamfs_chan_buf_t qdf_streamfs_chan_buf_t; + +#ifdef WLAN_STREAMFS +/** + * qdf_streamfs_create_dir() - wrapper to create a debugfs directory + * @name: name of the new directory + * @parent: parent node. If NULL, defaults to base qdf_debugfs_root + * + * Return: dentry structure pointer in case of success, otherwise NULL. + * + */ +static inline qdf_dentry_t qdf_streamfs_create_dir( + const char *name, qdf_dentry_t parent) +{ + return qdf_debugfs_create_dir(name, parent); +} + +/** + * qdf_streamfs_remove_file() - wrapper to remove streamfs file + * @d: streamfs node + * + */ +static inline void qdf_streamfs_remove_file(qdf_dentry_t d) +{ + qdf_debugfs_remove_file(d); +} + +/** + * qdf_debugfs_remove_dir_recursive() - wrapper to remove directory recursively + * @d: debugfs node + * + * This function will recursively remove a directory in streamfs that was + * previously created with a call to qdf_debugfs_create_file() or it's + * variant functions. + */ +static inline void qdf_streamfs_remove_dir_recursive(qdf_dentry_t d) +{ + qdf_debugfs_remove_dir_recursive(d); +} + +/** + * qdf_streamfs_create_file() - Create streamfs chan buffer file + * @name: base name of file to create + * @mode: filemode + * @parent: dentry of parent directory, NULL for root directory + * @buf: pointer to chan buffer + * + * Returns file dentry pointer if successful, NULL otherwise. + */ +qdf_dentry_t qdf_streamfs_create_file(const char *name, uint16_t mode, + qdf_dentry_t parent, + qdf_streamfs_chan_buf_t buf); + +/** + * qdf_streamfs_open() - Create streamfs channel for data trasfer + * @base_filename: base name of files to create, %NULL for buffering only + * @parent: dentry of parent directory, %NULL for root directory + * @subbuf_size: size of sub-buffers + * @n_subbufs: number of sub-buffers + * @private_data: user-defined data + * + * Returns channel pointer if successful, %NULL otherwise. + */ +qdf_streamfs_chan_t qdf_streamfs_open(const char *base_filename, + qdf_dentry_t parent, + size_t subbuf_size, size_t n_subbufs, + void *private_data); + +/** + * qdf_streamfs_close() - Closes all channel buffers and frees the channel. + * @chan: pointer to qdf_streamfs_chan. + * + * Returns NONE + */ +void qdf_streamfs_close(qdf_streamfs_chan_t chan); + +/** + * qdf_streamfs_flush() - Flushes all channel buffers. + * @chan: pointer to qdf_streamfs_chan. + * + * Returns NONE + */ +void qdf_streamfs_flush(qdf_streamfs_chan_t chan); + +/** + * qdf_streamfs_reset() - Reset streamfs channel + * @chan: pointer to qdf_streamfs_chan. + * + * This erases data from all channel buffers and restarting the channel + * in its initial state. The buffers are not freed, so any mappings are + * still in effect. + * + * Returns NONE + */ +void qdf_streamfs_reset(qdf_streamfs_chan_t chan); + +/** + * qdf_streamfs_subbufs_consumed() - update the buffer's sub-buffers-consumed + * count + * @chan: pointer to qdf_streamfs_chan. + * @cpu: the cpu associated with the channel buffer to update + * @subbufs_consumed: number of sub-buffers to add to current buf's count + * + * Returns NONE + */ +void qdf_streamfs_subbufs_consumed(qdf_streamfs_chan_t chan, + unsigned int cpu, + size_t consumed); + +/** + * qdf_streamfs_write() - write data into the channel + * @chan: relay channel + * @data: data to be written + * @length: number of bytes to write + * + * Writes data into the current cpu's channel buffer. + */ +void qdf_streamfs_write(qdf_streamfs_chan_t chan, const void *data, + size_t length); +#else +static inline qdf_dentry_t qdf_streamfs_create_dir( + const char *name, qdf_dentry_t parent) +{ + return NULL; +} + +static inline void qdf_streamfs_remove_file(qdf_dentry_t d) +{ +} + +static inline void qdf_streamfs_remove_dir_recursive(qdf_dentry_t d) +{ +} + +static inline +qdf_dentry_t qdf_streamfs_create_file(const char *name, uint16_t mode, + qdf_dentry_t parent, + qdf_streamfs_chan_buf_t buf) +{ + return NULL; +} + +static inline +qdf_streamfs_chan_t qdf_streamfs_open(const char *base_filename, + qdf_dentry_t parent, + size_t subbuf_size, size_t n_subbufs, + void *private_data) +{ + return NULL; +} + +static inline void qdf_streamfs_close(qdf_streamfs_chan_t chan) +{ +} + +static inline void qdf_streamfs_flush(qdf_streamfs_chan_t chan) +{ +} + +static inline void qdf_streamfs_reset(qdf_streamfs_chan_t chan) +{ +} + +static inline void +qdf_streamfs_subbufs_consumed(qdf_streamfs_chan_t chan, + unsigned int cpu, size_t consumed) +{ +} + +static inline void +qdf_streamfs_write(qdf_streamfs_chan_t chan, const void *data, + size_t length) +{ +} +#endif /* WLAN_STREAMFS */ +#endif /* _QDF_STREAMFS_H */ diff --git a/qdf/linux/src/i_qdf_streamfs.h b/qdf/linux/src/i_qdf_streamfs.h new file mode 100644 index 0000000000..d4b6e2edc1 --- /dev/null +++ b/qdf/linux/src/i_qdf_streamfs.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2020 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: i_qdf_streamfs.h + * Linux specific implementation for stream filesystem APIs. + */ + +#ifndef _I_QDF_STREAMFS_H +#define _I_QDF_STREAMFS_H + +#include + +typedef struct rchan *__qdf_streamfs_chan_t; +typedef struct rchan_buf *__qdf_streamfs_chan_buf_t; + +#endif /* _I_QDF_STREAMFS_H */ diff --git a/qdf/linux/src/qdf_streamfs.c b/qdf/linux/src/qdf_streamfs.c new file mode 100644 index 0000000000..25f58a3323 --- /dev/null +++ b/qdf/linux/src/qdf_streamfs.c @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2018, 2020 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: qdf_streamfs + * This file provides QDF stream file system APIs + */ + +#include +#include +#include +#include + +/** + * qdf_create_buf_file_handler() - Create streamfs buffer file + * @filename: base name of files to create, NULL for buffering only + * @parent: dentry of parent directory, NULL for root directory + * @mode: filemode + * @buf: streamfs channel buf + * @is_global: pointer to set whether this buf file is global or not. + * + * Returns dentry if successful, NULL otherwise. + */ +static qdf_dentry_t +qdf_create_buf_file_handler(const char *filename, qdf_dentry_t parent, + uint16_t mode, qdf_streamfs_chan_buf_t buf, + int32_t *is_global) +{ + qdf_dentry_t buf_file; + *is_global = 1; + buf_file = qdf_streamfs_create_file(filename, mode, parent, buf); + + if (!buf_file) + return NULL; + + return buf_file; +} + +/** + * qdf_remove_buf_file_handler() - Remove streamfs buffer file + * @dentry:dentry + */ +static int qdf_remove_buf_file_handler(qdf_dentry_t dentry) +{ + qdf_streamfs_remove_file(dentry); + + return 0; +} + +static struct rchan_callbacks g_qdf_streamfs_cb = { + .create_buf_file = qdf_create_buf_file_handler, + .remove_buf_file = qdf_remove_buf_file_handler, +}; + +qdf_dentry_t +qdf_streamfs_create_file(const char *name, uint16_t mode, + qdf_dentry_t parent, + qdf_streamfs_chan_buf_t buf) +{ + qdf_dentry_t file = NULL; + + if (!name) + return NULL; + + file = debugfs_create_file(name, mode, + (struct dentry *)parent, + buf, &relay_file_operations); + + return file; +} + +qdf_export_symbol(qdf_streamfs_create_file); + +qdf_streamfs_chan_t +qdf_streamfs_open(const char *base_filename, qdf_dentry_t parent, + size_t subbuf_size, size_t n_subbufs, + void *private_data) +{ + qdf_streamfs_chan_t channel_ptr = NULL; + + channel_ptr = relay_open(base_filename, + (struct dentry *)parent, + subbuf_size, n_subbufs, + &g_qdf_streamfs_cb, + private_data); + + return channel_ptr; +} + +qdf_export_symbol(qdf_streamfs_open); + +void qdf_streamfs_close(qdf_streamfs_chan_t chan) +{ + if (chan) + relay_close(chan); +} + +qdf_export_symbol(qdf_streamfs_close); + +void qdf_streamfs_flush(qdf_streamfs_chan_t chan) +{ + if (chan) + relay_flush(chan); +} + +qdf_export_symbol(qdf_streamfs_flush); + +void qdf_streamfs_reset(qdf_streamfs_chan_t chan) +{ + if (chan) + relay_reset(chan); +} + +qdf_export_symbol(qdf_streamfs_reset); + +void qdf_streamfs_subbufs_consumed(qdf_streamfs_chan_t chan, + unsigned int cpu, + size_t consumed) +{ + if (chan) + relay_subbufs_consumed(chan, cpu, consumed); +} + +qdf_export_symbol(qdf_streamfs_subbufs_consumed); + +void qdf_streamfs_write(qdf_streamfs_chan_t chan, + const void *data, + size_t length) +{ + if (chan) + relay_write(chan, data, length); +} + +qdf_export_symbol(qdf_streamfs_write);