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
/** 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);
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;
--- /dev/null
+/**
+ * @author Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ *
+ * @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 <linux/stat.h>
+#include <linux/errno.h>
+#include <linux/debugfs.h>
+#include <master/swap_debugfs.h>
+#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;
+}
--- /dev/null
+/**
+ * @author Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ *
+ * @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
#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;
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.
*
* @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,
.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 */
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;
}
/**
{
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;
}
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;
}
#ifndef __SWAP_DRIVER_DRIVER_TO_BUFFER__
#define __SWAP_DRIVER_DRIVER_TO_BUFFER__
-int driver_to_buffer_initialize(size_t size, unsigned int count);
+
+#include <linux/types.h>
+
+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);
/**
* @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__ */
#include "driver_defs.h"
#include "device_driver.h"
#include "us_interaction.h"
+#include "driver_debugfs.h"
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();
static void fs_uninit(void)
{
+ driver_debugfs_uninit();
us_interaction_destroy();
swap_device_exit();
print_msg("Driver module uninitialized\n");