[Xenomai-git] Philippe Gerum : cobalt/corectl: chain config requests to external subsystems
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 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 #include #include +#include #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 #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_
[Xenomai-git] Philippe Gerum : cobalt/corectl: chain config requests to external subsystems
Module: xenomai-3 Branch: next Commit: 609d91cadc7217bc6ad2edb5bf145cad35f6f7eb URL: http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=609d91cadc7217bc6ad2edb5bf145cad35f6f7eb Author: Philippe Gerum 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 #include #include +#include #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 #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_b