lists.openwall.net | lists / announce owl-users owl-dev john-users john-dev passwdqc-users yescrypt popa3d-users / oss-security kernel-hardening musl sabotage tlsify passwords / crypt-dev xvendor / Bugtraq Full-Disclosure linux-kernel linux-netdev linux-ext4 linux-hardening PHC | |
Open Source and information security mailing list archives
| ||
|
Date: Mon, 10 Oct 2022 04:18:00 +0300 From: Vadim Fedorenko <vfedorenko@...ek.ru> To: Jakub Kicinski <kuba@...nel.org>, Jiri Pirko <jiri@...nulli.us>, Arkadiusz Kubalewski <arkadiusz.kubalewski@...el.com> Cc: netdev@...r.kernel.org, linux-arm-kernel@...ts.infradead.org, linux-clk@...r.kernel.org, Vadim Fedorenko <vadfed@...com> Subject: [RFC PATCH v3 2/6] dpll: add netlink events From: Vadim Fedorenko <vadfed@...com> Add netlink interface to enable notification of users about events in DPLL framework. Part of this interface should be used by drivers directly, i.e. lock status changes. Signed-off-by: Vadim Fedorenko <vadfed@...com> --- drivers/dpll/dpll_core.c | 3 + drivers/dpll/dpll_netlink.c | 151 ++++++++++++++++++++++++++++++++++++ drivers/dpll/dpll_netlink.h | 3 + include/linux/dpll.h | 5 ++ 4 files changed, 162 insertions(+) diff --git a/drivers/dpll/dpll_core.c b/drivers/dpll/dpll_core.c index 7fdee145e82c..732165b77e38 100644 --- a/drivers/dpll/dpll_core.c +++ b/drivers/dpll/dpll_core.c @@ -115,6 +115,8 @@ struct dpll_device *dpll_device_alloc(struct dpll_device_ops *ops, const char *n mutex_unlock(&dpll_device_xa_lock); dpll->priv = priv; + dpll_notify_device_create(dpll->id, dev_name(&dpll->dev)); + return dpll; error: @@ -150,6 +152,7 @@ void dpll_device_unregister(struct dpll_device *dpll) mutex_lock(&dpll_device_xa_lock); xa_erase(&dpll_device_xa, dpll->id); + dpll_notify_device_delete(dpll->id); mutex_unlock(&dpll_device_xa_lock); } EXPORT_SYMBOL_GPL(dpll_device_unregister); diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c index 31966e0eec3a..6dc92b5b712e 100644 --- a/drivers/dpll/dpll_netlink.c +++ b/drivers/dpll/dpll_netlink.c @@ -47,6 +47,9 @@ struct param { int dpll_source_type; int dpll_output_id; int dpll_output_type; + int dpll_status; + int dpll_event_group; + const char *dpll_name; }; struct dpll_dump_ctx { @@ -240,6 +243,9 @@ static int dpll_genl_cmd_set_source(struct sk_buff *skb, struct genl_info *info) ret = dpll->ops->set_source_type(dpll, src_id, type); mutex_unlock(&dpll->lock); + if (!ret) + dpll_notify_source_change(dpll->id, src_id, type); + return ret; } @@ -263,6 +269,9 @@ static int dpll_genl_cmd_set_output(struct sk_buff *skb, struct genl_info *info) ret = dpll->ops->set_output_type(dpll, out_id, type); mutex_unlock(&dpll->lock); + if (!ret) + dpll_notify_output_change(dpll->id, out_id, type); + return ret; } @@ -401,6 +410,148 @@ static struct genl_family dpll_gnl_family __ro_after_init = { .pre_doit = dpll_pre_doit, }; +static int dpll_event_device_create(struct param *p) +{ + if (nla_put_u32(p->msg, DPLLA_DEVICE_ID, p->dpll_id) || + nla_put_string(p->msg, DPLLA_DEVICE_NAME, p->dpll_name)) + return -EMSGSIZE; + + return 0; +} + +static int dpll_event_device_delete(struct param *p) +{ + if (nla_put_u32(p->msg, DPLLA_DEVICE_ID, p->dpll_id)) + return -EMSGSIZE; + + return 0; +} + +static int dpll_event_status(struct param *p) +{ + if (nla_put_u32(p->msg, DPLLA_DEVICE_ID, p->dpll_id) || + nla_put_u32(p->msg, DPLLA_LOCK_STATUS, p->dpll_status)) + return -EMSGSIZE; + + return 0; +} + +static int dpll_event_source_change(struct param *p) +{ + if (nla_put_u32(p->msg, DPLLA_DEVICE_ID, p->dpll_id) || + nla_put_u32(p->msg, DPLLA_SOURCE_ID, p->dpll_source_id) || + nla_put_u32(p->msg, DPLLA_SOURCE_TYPE, p->dpll_source_type)) + return -EMSGSIZE; + + return 0; +} + +static int dpll_event_output_change(struct param *p) +{ + if (nla_put_u32(p->msg, DPLLA_DEVICE_ID, p->dpll_id) || + nla_put_u32(p->msg, DPLLA_OUTPUT_ID, p->dpll_output_id) || + nla_put_u32(p->msg, DPLLA_OUTPUT_TYPE, p->dpll_output_type)) + return -EMSGSIZE; + + return 0; +} + +static const cb_t event_cb[] = { + [DPLL_EVENT_DEVICE_CREATE] = dpll_event_device_create, + [DPLL_EVENT_DEVICE_DELETE] = dpll_event_device_delete, + [DPLL_EVENT_STATUS_LOCKED] = dpll_event_status, + [DPLL_EVENT_STATUS_UNLOCKED] = dpll_event_status, + [DPLL_EVENT_SOURCE_CHANGE] = dpll_event_source_change, + [DPLL_EVENT_OUTPUT_CHANGE] = dpll_event_output_change, +}; +/* + * Generic netlink DPLL event encoding + */ +static int dpll_send_event(enum dpll_genl_event event, + struct param *p) +{ + struct sk_buff *msg; + int ret = -EMSGSIZE; + void *hdr; + + msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + if (!msg) + return -ENOMEM; + p->msg = msg; + + hdr = genlmsg_put(msg, 0, 0, &dpll_gnl_family, 0, event); + if (!hdr) + goto out_free_msg; + + ret = event_cb[event](p); + if (ret) + goto out_cancel_msg; + + genlmsg_end(msg, hdr); + + genlmsg_multicast(&dpll_gnl_family, msg, 0, p->dpll_event_group, GFP_KERNEL); + + return 0; + +out_cancel_msg: + genlmsg_cancel(msg, hdr); +out_free_msg: + nlmsg_free(msg); + + return ret; +} + +int dpll_notify_device_create(int dpll_id, const char *name) +{ + struct param p = { .dpll_id = dpll_id, .dpll_name = name, + .dpll_event_group = 0 }; + + return dpll_send_event(DPLL_EVENT_DEVICE_CREATE, &p); +} + +int dpll_notify_device_delete(int dpll_id) +{ + struct param p = { .dpll_id = dpll_id, .dpll_event_group = 0 }; + + return dpll_send_event(DPLL_EVENT_DEVICE_DELETE, &p); +} + +int dpll_notify_status_locked(int dpll_id) +{ + struct param p = { .dpll_id = dpll_id, .dpll_status = 1, + .dpll_event_group = 3 }; + + return dpll_send_event(DPLL_EVENT_STATUS_LOCKED, &p); +} +EXPORT_SYMBOL_GPL(dpll_notify_status_locked); + +int dpll_notify_status_unlocked(int dpll_id) +{ + struct param p = { .dpll_id = dpll_id, .dpll_status = 0, + .dpll_event_group = 3 }; + + return dpll_send_event(DPLL_EVENT_STATUS_UNLOCKED, &p); +} +EXPORT_SYMBOL_GPL(dpll_notify_status_unlocked); + +int dpll_notify_source_change(int dpll_id, int source_id, int source_type) +{ + struct param p = { .dpll_id = dpll_id, .dpll_source_id = source_id, + .dpll_source_type = source_type, .dpll_event_group = 1 }; + + return dpll_send_event(DPLL_EVENT_SOURCE_CHANGE, &p); +} +EXPORT_SYMBOL_GPL(dpll_notify_source_change); + +int dpll_notify_output_change(int dpll_id, int output_id, int output_type) +{ + struct param p = { .dpll_id = dpll_id, .dpll_output_id = output_id, + .dpll_output_type = output_type, .dpll_event_group = 2 }; + + return dpll_send_event(DPLL_EVENT_OUTPUT_CHANGE, &p); +} +EXPORT_SYMBOL_GPL(dpll_notify_output_change); + int __init dpll_netlink_init(void) { return genl_register_family(&dpll_gnl_family); diff --git a/drivers/dpll/dpll_netlink.h b/drivers/dpll/dpll_netlink.h index e2d100f59dd6..5c1d1072e818 100644 --- a/drivers/dpll/dpll_netlink.h +++ b/drivers/dpll/dpll_netlink.h @@ -3,5 +3,8 @@ * Copyright (c) 2021 Meta Platforms, Inc. and affiliates */ +int dpll_notify_device_create(int dpll_id, const char *name); +int dpll_notify_device_delete(int dpll_id); + int __init dpll_netlink_init(void); void dpll_netlink_finish(void); diff --git a/include/linux/dpll.h b/include/linux/dpll.h index 9d49b19d03d9..32558965cd41 100644 --- a/include/linux/dpll.h +++ b/include/linux/dpll.h @@ -26,4 +26,9 @@ void dpll_device_register(struct dpll_device *dpll); void dpll_device_unregister(struct dpll_device *dpll); void dpll_device_free(struct dpll_device *dpll); void *dpll_priv(struct dpll_device *dpll); + +int dpll_notify_status_locked(int dpll_id); +int dpll_notify_status_unlocked(int dpll_id); +int dpll_notify_source_change(int dpll_id, int source_id, int source_type); +int dpll_notify_output_change(int dpll_id, int output_id, int output_type); #endif -- 2.27.0
Powered by blists - more mailing lists