static splice_to_pipe_p_t splice_to_pipe_p;
static splice_grow_spd_p_t splice_grow_spd_p;
-static msg_handler_t msg_handler;
-
/* Device numbers */
static dev_t swap_device_no;
}
+/*
+ * Driver message handler
+ */
+static DECLARE_RWSEM(dmsg_handler_sem);
+static struct driver_msg_handler *dmsg_handler;
+
+static int driver_msg_handler_call(void __user *data)
+{
+ int ret;
+
+ down_read(&dmsg_handler_sem);
+ if (dmsg_handler) {
+ ret = dmsg_handler->handler(data);
+ } else {
+ print_warn("dmsg_handler() is not register\n");
+ ret = -EINVAL;
+ }
+ up_read(&dmsg_handler_sem);
+
+ return ret;
+}
+
+/**
+ * @brief Register message handler.
+ *
+ * @param msg_handler Pointer to message handler.
+ * @return Void.
+ */
+void driver_msg_handler_set(struct driver_msg_handler *msg_handler)
+{
+ down_write(&dmsg_handler_sem);
+ /* unregister dmsg_handler */
+ if (dmsg_handler) {
+ module_put(dmsg_handler->mod);
+ dmsg_handler = NULL;
+ }
+
+ /* register dmsg_handler */
+ if (msg_handler) {
+ BUG_ON(!try_module_get(msg_handler->mod));
+ dmsg_handler = msg_handler;
+ }
+ up_write(&dmsg_handler_sem);
+}
+EXPORT_SYMBOL_GPL(driver_msg_handler_set);
+
+
/**
* @brief We need this realization of splice_shrink_spd() because its desing
* frequently changes in custom kernels.
}
case SWAP_DRIVER_MSG:
{
- if (msg_handler) {
- result = msg_handler((void __user *)arg);
- } else {
- print_warn("msg_handler() is not register\n");
- result = -EINVAL;
- }
+ result = driver_msg_handler_call((void __user *)arg);
break;
}
case SWAP_DRIVER_WAKE_UP:
schedule_work(&w_wake_up);
}
}
-
-/**
- * @brief Registers received message handler.
- *
- * @param mh Pointer to message handler.
- * @return Void.
- */
-void set_msg_handler(msg_handler_t mh)
-{
- msg_handler = mh;
-}
-EXPORT_SYMBOL_GPL(set_msg_handler);
#ifndef __SWAP_DRIVER_DRIVER_TO_MSG__
#define __SWAP_DRIVER_DRIVER_TO_MSG__
-/** Defines type for message handler's pointer. */
-typedef int (*msg_handler_t)(void __user *data);
+#include <linux/compiler.h>
+
+struct module;
+
+struct driver_msg_handler {
+ struct module *mod;
+ int (*handler)(void __user *data);
+};
/* Set the message handler */
-void set_msg_handler(msg_handler_t mh);
+void driver_msg_handler_set(struct driver_msg_handler *msg_handler);
#endif /* __SWAP_DRIVER_DRIVER_TO_MSG__ */
return ret;
}
+static struct driver_msg_handler dmsg_handler = {
+ .mod = THIS_MODULE,
+ .handler = msg_handler,
+};
+
static int reg_msg_handler(void)
{
- set_msg_handler(msg_handler);
+ driver_msg_handler_set(&dmsg_handler);
return 0;
}
static void unreg_msg_handler(void)
{
- set_msg_handler(NULL);
+ driver_msg_handler_set(NULL);
app_list_unreg_all();
}