Module: xenomai-3 Branch: stable-3.0.x Commit: eab452191bab1adcb315e38d324723b3a9c33af2 URL: http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=eab452191bab1adcb315e38d324723b3a9c33af2
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