From: Vyacheslav Cherkashin Date: Tue, 6 Dec 2016 15:16:18 +0000 (+0300) Subject: Add setup buffer via debugfs X-Git-Tag: accepted/tizen/3.0/common/20161213.163408^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f4d5f0c8b94f4d1beb29fcc3723cdd4e7afea958;p=platform%2Fkernel%2Fswap-modules.git Add setup buffer via debugfs Change-Id: I01c749ff0e920530e5bc1579acfd901177aa9f82 Signed-off-by: Vyacheslav Cherkashin --- diff --git a/driver/Kbuild b/driver/Kbuild index b3e3030..51f30cc 100644 --- a/driver/Kbuild +++ b/driver/Kbuild @@ -4,7 +4,8 @@ KBUILD_EXTRA_SYMBOLS = $(src)/../buffer/Module.symvers obj-m := swap_driver.o swap_driver-y := swap_driver_module.o \ device_driver.o \ - driver_to_buffer.o + driver_to_buffer.o \ + driver_debugfs.o ifeq ($(CONFIG_CONNECTOR),y) swap_driver-y += us_interaction.o diff --git a/driver/device_driver.c b/driver/device_driver.c index f06b0f1..a19ffbf 100644 --- a/driver/device_driver.c +++ b/driver/device_driver.c @@ -58,9 +58,6 @@ /** SWAP device name as it is in /dev/. */ #define SWAP_DEVICE_NAME "swap_device" -/** Maximum subbuffer size. Used for sanitization checks. */ -#define MAXIMUM_SUBBUFFER_SIZE (64 * 1024) - /* swap_device driver routines */ static ssize_t swap_device_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos); @@ -317,14 +314,21 @@ static long swap_device_ioctl(struct file *filp, unsigned int cmd, if (result) break; - if (initialize_struct.size > MAXIMUM_SUBBUFFER_SIZE) { - print_err("Wrong subbuffer size\n"); - result = -E_SD_WRONG_ARGS; + result = driver_to_buffer_set_size(initialize_struct.size); + if (result < 0) { + print_err("Wrong subbuffer size=%zu\n", + initialize_struct.size); + break; + } + + result = driver_to_buffer_set_count(initialize_struct.count); + if (result < 0) { + print_err("Wrong subbuffer count=%u\n", + initialize_struct.count); break; } - result = driver_to_buffer_initialize(initialize_struct.size, - initialize_struct.count); + result = driver_to_buffer_initialize(); if (result < 0) { print_err("Buffer initialization failed %d\n", result); break; diff --git a/driver/driver_debugfs.c b/driver/driver_debugfs.c new file mode 100644 index 0000000..00d81a0 --- /dev/null +++ b/driver/driver_debugfs.c @@ -0,0 +1,156 @@ +/** + * @author Vyacheslav Cherkashin + * + * @section LICENSE + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * @section COPYRIGHT + * + * Copyright (C) Samsung Electronics, 2016 + * + * @section DESCRIPTION + * + * SWAP debugfs interface definition. + */ + +#include +#include +#include +#include +#include "driver_to_buffer.h" +#include "swap_driver_errors.h" + + +#define WRITER_DBG_PERMS (S_IRUSR | S_IWUSR) /* u+rw */ + + +static int buf_enabled_set(u64 val) +{ + int ret = -EINVAL; + + switch (val) { + case 0: + ret = driver_to_buffer_uninitialize(); + break; + case 1: + ret = driver_to_buffer_initialize(); + break; + } + + return ret; +} + +static u64 buf_enabled_get(void) +{ + return driver_to_buffer_enabled(); +} + +static struct dfs_setget_64 dfs_enabled = { + .set = buf_enabled_set, + .get = buf_enabled_get, +}; + +static int subbuf_size_set(u64 val) +{ + + if (driver_to_buffer_set_size(val) != E_SD_SUCCESS) + return -EINVAL; + + return 0; +} + +static u64 subbuf_size_get(void) +{ + return driver_to_buffer_get_size(); +} + +static struct dfs_setget_64 dfs_subbuf_size = { + .set = subbuf_size_set, + .get = subbuf_size_get, +}; + +static int subbuf_count_set(u64 val) +{ + if (driver_to_buffer_set_count(val) != E_SD_SUCCESS) + return -EINVAL; + + return 0; +} + +static u64 subbuf_count_get(void) +{ + return driver_to_buffer_get_count(); +} + +static struct dfs_setget_64 dfs_subbuf_count = { + .set = subbuf_count_set, + .get = subbuf_count_get, +}; + + +struct dbgfs_data { + const char *name; + struct dfs_setget_64 *setget; +}; + +static struct dbgfs_data dbgfs[] = { + { + .name = "buffer_enabled", + .setget = &dfs_enabled, + }, { + .name = "subbuf_size", + .setget = &dfs_subbuf_size, + }, { + .name = "subbuf_conunt", + .setget = &dfs_subbuf_count, + } +}; + + +static struct dentry *driver_dir; + +void driver_debugfs_uninit(void) +{ + debugfs_remove_recursive(driver_dir); + driver_dir = NULL; +} + +int driver_debugfs_init(void) +{ + int i; + struct dentry *swap_dir, *dentry; + + swap_dir = swap_debugfs_getdir(); + if (swap_dir == NULL) + return -ENOENT; + + driver_dir = debugfs_create_dir("driver", swap_dir); + if (driver_dir == NULL) + return -ENOMEM; + + for (i = 0; i < ARRAY_SIZE(dbgfs); ++i) { + struct dbgfs_data *data = &dbgfs[i]; + dentry = debugfs_create_setget_u64(data->name, WRITER_DBG_PERMS, + driver_dir, data->setget); + if (!dentry) + goto fail; + } + + return 0; +fail: + driver_debugfs_uninit(); + return -ENOMEM; +} diff --git a/driver/driver_debugfs.h b/driver/driver_debugfs.h new file mode 100644 index 0000000..5624d05 --- /dev/null +++ b/driver/driver_debugfs.h @@ -0,0 +1,36 @@ +/** + * @author Vyacheslav Cherkashin + * + * @section LICENSE + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * @section COPYRIGHT + * + * Copyright (C) Samsung Electronics, 2016 + * + * @section DESCRIPTION + * + * SWAP debugfs interface definition. + */ + +#ifndef DRIVER_DEBUGFS_H +#define DRIVER_DEBUGFS_H + + +int driver_debugfs_init(void); +void driver_debugfs_uninit(void); + +#endif // DRIVER_DEBUGFS_H diff --git a/driver/driver_to_buffer.c b/driver/driver_to_buffer.c index 3ddd19c..80683a4 100644 --- a/driver/driver_to_buffer.c +++ b/driver/driver_to_buffer.c @@ -44,6 +44,9 @@ #include "device_driver_to_driver_to_buffer.h" #include "app_manage.h" +/** Maximum subbuffer size. Used for sanitization checks. */ +#define MAXIMUM_SUBBUFFER_SIZE (64 * 1024) + /* Current busy buffer */ static struct swap_subbuffer *busy_buffer; @@ -272,6 +275,64 @@ int driver_to_buffer_buffer_to_read(void) return busy_buffer ? 1 : 0; } +static size_t subbuf_size; +static unsigned int subbuf_count; +static bool buffer_enabled; +static DEFINE_MUTEX(buffer_mtx); + +bool driver_to_buffer_enabled(void) +{ + return buffer_enabled; +} + +enum _swap_driver_errors driver_to_buffer_set_size(size_t size) +{ + enum _swap_driver_errors ret = E_SD_SUCCESS; + + if (!size || size > MAXIMUM_SUBBUFFER_SIZE) + return -E_SD_WRONG_ARGS; + + mutex_lock(&buffer_mtx); + if (buffer_enabled) { + ret = -E_SD_BUFFER_ENABLED; + goto unlock; + } + + subbuf_size = size; +unlock: + mutex_unlock(&buffer_mtx); + return ret; +} + +size_t driver_to_buffer_get_size(void) +{ + return subbuf_size; +} + +enum _swap_driver_errors driver_to_buffer_set_count(unsigned int count) +{ + enum _swap_driver_errors ret = E_SD_SUCCESS; + + if (!count) + return -E_SD_WRONG_ARGS; + + mutex_lock(&buffer_mtx); + if (buffer_enabled) { + ret = -E_SD_BUFFER_ENABLED; + goto unlock; + } + subbuf_count = count; + +unlock: + mutex_unlock(&buffer_mtx); + return ret; +} + +unsigned int driver_to_buffer_get_count(void) +{ + return subbuf_count; +} + /** * @brief Initializes SWAP buffer. * @@ -279,12 +340,12 @@ int driver_to_buffer_buffer_to_read(void) * @param count Count of subbuffers. * @return 0 on success, negative error code on error. */ -int driver_to_buffer_initialize(size_t size, unsigned int count) +int driver_to_buffer_initialize(void) { - int result; + enum _swap_driver_errors result; struct buffer_init_t buf_init = { - .subbuffer_size = size, - .nr_subbuffers = count, + .subbuffer_size = subbuf_size, + .nr_subbuffers = subbuf_count, .subbuffer_full_cb = driver_to_buffer_callback, .lower_threshold = 20, .low_mem_cb = app_manage_pause_apps, @@ -292,13 +353,17 @@ int driver_to_buffer_initialize(size_t size, unsigned int count) .enough_mem_cb = app_manage_cont_apps, }; - if (size == 0 && count == 0) - return -E_SD_WRONG_ARGS; + mutex_lock(&buffer_mtx); + if (buffer_enabled) { + result = -E_SD_BUFFER_ENABLED; + goto unlock; + } result = swap_buffer_init(&buf_init); if (result == -E_SB_NO_MEM_QUEUE_BUSY || result == -E_SB_NO_MEM_BUFFER_STRUCT) { - return -E_SD_NO_MEMORY; + result = -E_SD_NO_MEMORY; + goto unlock; } /* TODO Race condition: buffer can be used in other thread till */ @@ -307,8 +372,12 @@ int driver_to_buffer_initialize(size_t size, unsigned int count) pages_per_buffer = result; busy_buffer = NULL; init_buffers_to_read(); + result = E_SD_SUCCESS; + buffer_enabled = true; - return E_SD_SUCCESS; +unlock: + mutex_unlock(&buffer_mtx); + return result; } /** @@ -320,12 +389,18 @@ int driver_to_buffer_uninitialize(void) { int result; + mutex_lock(&buffer_mtx); + if (!buffer_enabled) { + result = -E_SD_BUFFER_DISABLED; + goto unlock; + } + /* Release occupied buffer */ if (busy_buffer) { result = driver_to_buffer_release(); /* TODO Maybe release anyway */ if (result < 0) - return result; + goto unlock; busy_buffer = NULL; } @@ -338,12 +413,15 @@ int driver_to_buffer_uninitialize(void) result = -E_SD_BUFFER_ERROR; } else { result = E_SD_SUCCESS; + buffer_enabled = false; } /* Reinit driver_to_buffer vars */ init_buffers_to_read(); pages_per_buffer = 0; +unlock: + mutex_unlock(&buffer_mtx); return result; } diff --git a/driver/driver_to_buffer.h b/driver/driver_to_buffer.h index e133ee1..465968f 100644 --- a/driver/driver_to_buffer.h +++ b/driver/driver_to_buffer.h @@ -30,7 +30,21 @@ #ifndef __SWAP_DRIVER_DRIVER_TO_BUFFER__ #define __SWAP_DRIVER_DRIVER_TO_BUFFER__ -int driver_to_buffer_initialize(size_t size, unsigned int count); + +#include + +struct splice_pipe_desc; + + +bool driver_to_buffer_enabled(void); + +enum _swap_driver_errors driver_to_buffer_set_size(size_t size); +size_t driver_to_buffer_get_size(void); + +enum _swap_driver_errors driver_to_buffer_set_count(unsigned int count); +unsigned int driver_to_buffer_get_count(void); + +int driver_to_buffer_initialize(void); int driver_to_buffer_uninitialize(void); ssize_t driver_to_buffer_read(char __user *buf, size_t count); int driver_to_buffer_fill_spd(struct splice_pipe_desc *spd); diff --git a/driver/swap_driver_errors.h b/driver/swap_driver_errors.h index 75294a6..7c6fce2 100644 --- a/driver/swap_driver_errors.h +++ b/driver/swap_driver_errors.h @@ -107,7 +107,15 @@ enum _swap_driver_errors { /** * @brief No daemon pid in us_interaction. */ - E_SD_NO_DAEMON_PID = 17 + E_SD_NO_DAEMON_PID = 17, + /** + * @brief Buffer already enabled + */ + E_SD_BUFFER_ENABLED = 18, + /** + * @brief Buffer already disabled + */ + E_SD_BUFFER_DISABLED = 19, }; #endif /* __SWAP_DRIVER_ERRORS_H__ */ diff --git a/driver/swap_driver_module.c b/driver/swap_driver_module.c index 48c7016..dcb69bb 100644 --- a/driver/swap_driver_module.c +++ b/driver/swap_driver_module.c @@ -32,6 +32,7 @@ #include "driver_defs.h" #include "device_driver.h" #include "us_interaction.h" +#include "driver_debugfs.h" static int fs_init(void) { @@ -45,10 +46,16 @@ static int fs_init(void) if (ret) print_err("Cannot initialize netlink socket\n"); + ret = driver_debugfs_init(); + if (ret) + goto us_int_destroy; + print_msg("Driver module initialized\n"); - return 0; + return ret; +us_int_destroy: + us_interaction_destroy(); dev_init_fail: swap_device_exit(); @@ -57,6 +64,7 @@ dev_init_fail: static void fs_uninit(void) { + driver_debugfs_uninit(); us_interaction_destroy(); swap_device_exit(); print_msg("Driver module uninitialized\n");