Module: xenomai-3
Branch: next
Commit: 609d91cadc7217bc6ad2edb5bf145cad35f6f7eb
URL:    
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=609d91cadc7217bc6ad2edb5bf145cad35f6f7eb

Author: Philippe Gerum <r...@xenomai.org>
Date:   Sun Dec 27 18:02:01 2015 +0100

cobalt/corectl: chain config requests to external subsystems

External subsystems (e.g. RTNet, Analogy) may attach to the generic
corectl() configuration service by registering to the config_notifier
list, using the cobalt_add_config_chain() routine.

Upon a call to corectl(), a configuration request left unprocessed by
the core is posted to the registered handlers in turn, until NOTIFY_OK
or any error is raised.  If a request remains unprocessed, corectl()
eventually returns -EINVAL.

Unlike core configuration requests which may be handled in primary
mode if applicable, the current context is always switched to
secondary mode before subsystem handlers are called.

---

 include/cobalt/kernel/init.h        |    6 +++---
 include/cobalt/kernel/rtdm/cobalt.h |    1 +
 kernel/cobalt/init.c                |   12 ++++++------
 kernel/cobalt/posix/corectl.c       |   36 +++++++++++++++++++++++++++++------
 kernel/cobalt/posix/corectl.h       |   11 +++++++++++
 kernel/cobalt/rtdm/device.c         |    4 ++--
 6 files changed, 53 insertions(+), 17 deletions(-)

diff --git a/include/cobalt/kernel/init.h b/include/cobalt/kernel/init.h
index bdb2bb6..41dd531 100644
--- a/include/cobalt/kernel/init.h
+++ b/include/cobalt/kernel/init.h
@@ -45,10 +45,10 @@ static inline void set_realtime_core_state(enum 
cobalt_run_states state)
        atomic_set(&cobalt_runstate, state);
 }
 
-void cobalt_add_notifier_chain(struct notifier_block *nb);
+void cobalt_add_state_chain(struct notifier_block *nb);
 
-void cobalt_remove_notifier_chain(struct notifier_block *nb);
+void cobalt_remove_state_chain(struct notifier_block *nb);
 
-void cobalt_call_notifier_chain(enum cobalt_run_states newstate);
+void cobalt_call_state_chain(enum cobalt_run_states newstate);
 
 #endif /* !_COBALT_KERNEL_INIT_H_ */
diff --git a/include/cobalt/kernel/rtdm/cobalt.h 
b/include/cobalt/kernel/rtdm/cobalt.h
index a2b268d..d60cfc5 100644
--- a/include/cobalt/kernel/rtdm/cobalt.h
+++ b/include/cobalt/kernel/rtdm/cobalt.h
@@ -28,5 +28,6 @@
 #include <xenomai/posix/clock.h>
 #include <xenomai/posix/event.h>
 #include <xenomai/posix/monitor.h>
+#include <xenomai/posix/corectl.h>
 
 #endif /* !_COBALT_RTDM_COBALT_H */
diff --git a/kernel/cobalt/init.c b/kernel/cobalt/init.c
index cc77b37..0eab3be 100644
--- a/kernel/cobalt/init.c
+++ b/kernel/cobalt/init.c
@@ -104,23 +104,23 @@ EXPORT_SYMBOL_GPL(cobalt_kernel_ppd);
                        "[STOPPED]" : "";                               \
        })
 
-void cobalt_add_notifier_chain(struct notifier_block *nb)
+void cobalt_add_state_chain(struct notifier_block *nb)
 {
        blocking_notifier_chain_register(&state_notifier_list, nb);
 }
-EXPORT_SYMBOL_GPL(cobalt_add_notifier_chain);
+EXPORT_SYMBOL_GPL(cobalt_add_state_chain);
 
-void cobalt_remove_notifier_chain(struct notifier_block *nb)
+void cobalt_remove_state_chain(struct notifier_block *nb)
 {
        blocking_notifier_chain_unregister(&state_notifier_list, nb);
 }
-EXPORT_SYMBOL_GPL(cobalt_remove_notifier_chain);
+EXPORT_SYMBOL_GPL(cobalt_remove_state_chain);
 
-void cobalt_call_notifier_chain(enum cobalt_run_states newstate)
+void cobalt_call_state_chain(enum cobalt_run_states newstate)
 {
        blocking_notifier_call_chain(&state_notifier_list, newstate, NULL);
 }
-EXPORT_SYMBOL_GPL(cobalt_call_notifier_chain);
+EXPORT_SYMBOL_GPL(cobalt_call_state_chain);
 
 static void sys_shutdown(void)
 {
diff --git a/kernel/cobalt/posix/corectl.c b/kernel/cobalt/posix/corectl.c
index f5af386..de8fa5b 100644
--- a/kernel/cobalt/posix/corectl.c
+++ b/kernel/cobalt/posix/corectl.c
@@ -27,11 +27,14 @@
 #include <asm/xenomai/syscall.h>
 #include "corectl.h"
 
-static int get_conf_option(int option, void __user *u_buf, size_t u_bufsz)
+static BLOCKING_NOTIFIER_HEAD(config_notifier_list);
+
+static int do_conf_option(int option, void __user *u_buf, size_t u_bufsz)
 {
+       struct cobalt_config_vector vec;
        int ret, val = 0;
 
-       if (u_bufsz < sizeof(val))
+       if (option <= _CC_COBALT_GET_CORE_STATUS && u_bufsz < sizeof(val))
                return -EINVAL;
 
        switch (option) {
@@ -86,7 +89,16 @@ static int get_conf_option(int option, void __user *u_buf, 
size_t u_bufsz)
                val = realtime_core_state();
                break;
        default:
-               return -EINVAL;
+               if (!ipipe_root_p)
+                       /* Switch to secondary mode first. */
+                       return -ENOSYS;
+               vec.u_buf = u_buf;
+               vec.u_bufsz = u_bufsz;
+               ret = blocking_notifier_call_chain(&config_notifier_list,
+                                                  option, &vec);
+               if (ret == NOTIFY_DONE)
+                       return -EINVAL; /* Nobody cared. */
+               return notifier_to_errno(ret);
        }
 
        ret = cobalt_copy_to_user(u_buf, &val, sizeof(val));
@@ -129,7 +141,7 @@ static int stop_services(const void __user *u_buf, size_t 
u_bufsz)
                        set_realtime_core_state(state);
                        return ret;
                }
-               cobalt_call_notifier_chain(COBALT_STATE_TEARDOWN);
+               cobalt_call_state_chain(COBALT_STATE_TEARDOWN);
                /* Kill lingering RTDM tasks. */
                ret = xnthread_killall(final_grace_period, 0);
                if (ret == -EAGAIN)
@@ -158,7 +170,7 @@ static int start_services(void)
                break;
        case COBALT_STATE_STOPPED:
                xntimer_grab_hardware();
-               cobalt_call_notifier_chain(COBALT_STATE_WARMUP);
+               cobalt_call_state_chain(COBALT_STATE_WARMUP);
                set_realtime_core_state(COBALT_STATE_RUNNING);
                printk(XENO_INFO "services started\n");
                break;
@@ -182,8 +194,20 @@ COBALT_SYSCALL(corectl, probing,
                ret = start_services();
                break;
        default:
-               ret = get_conf_option(request, u_buf, u_bufsz);
+               ret = do_conf_option(request, u_buf, u_bufsz);
        }
        
        return ret;
 }
+
+void cobalt_add_config_chain(struct notifier_block *nb)
+{
+       blocking_notifier_chain_register(&config_notifier_list, nb);
+}
+EXPORT_SYMBOL_GPL(cobalt_add_config_chain);
+
+void cobalt_remove_config_chain(struct notifier_block *nb)
+{
+       blocking_notifier_chain_unregister(&config_notifier_list, nb);
+}
+EXPORT_SYMBOL_GPL(cobalt_remove_config_chain);
diff --git a/kernel/cobalt/posix/corectl.h b/kernel/cobalt/posix/corectl.h
index 79f46ae..b9bcf3b 100644
--- a/kernel/cobalt/posix/corectl.h
+++ b/kernel/cobalt/posix/corectl.h
@@ -18,10 +18,21 @@
 #ifndef _COBALT_POSIX_CORECTL_H
 #define _COBALT_POSIX_CORECTL_H
 
+#include <linux/types.h>
+#include <linux/notifier.h>
 #include <xenomai/posix/syscall.h>
 #include <cobalt/uapi/corectl.h>
 
+struct cobalt_config_vector {
+       void __user *u_buf;
+       size_t u_bufsz;
+};
+
 COBALT_SYSCALL_DECL(corectl,
                    (int request, void __user *u_buf, size_t u_bufsz));
 
+void cobalt_add_config_chain(struct notifier_block *nb);
+
+void cobalt_remove_config_chain(struct notifier_block *nb);
+
 #endif /* !_COBALT_POSIX_CORECTL_H */
diff --git a/kernel/cobalt/rtdm/device.c b/kernel/cobalt/rtdm/device.c
index 0fdfa2d..9c5aeb1 100644
--- a/kernel/cobalt/rtdm/device.c
+++ b/kernel/cobalt/rtdm/device.c
@@ -309,7 +309,7 @@ static int register_driver(struct rtdm_driver *drv)
 done:
        drv->nb_statechange.notifier_call = state_change_notifier;
        drv->nb_statechange.priority = 0;
-       cobalt_add_notifier_chain(&drv->nb_statechange);
+       cobalt_add_state_chain(&drv->nb_statechange);
        drv->profile_info.magic = RTDM_CLASS_MAGIC;
 
        return 0;
@@ -324,7 +324,7 @@ static void unregister_driver(struct rtdm_driver *drv)
 {
        XENO_BUG_ON(COBALT, drv->profile_info.magic != RTDM_CLASS_MAGIC);
 
-       cobalt_remove_notifier_chain(&drv->nb_statechange);
+       cobalt_remove_state_chain(&drv->nb_statechange);
        
        if (drv->device_flags & RTDM_NAMED_DEVICE) {
                cdev_del(&drv->named.cdev);


_______________________________________________
Xenomai-git mailing list
Xenomai-git@xenomai.org
http://xenomai.org/mailman/listinfo/xenomai-git

Reply via email to