All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH v3 0/5] Create common DPLL/clock configuration API
@ 2022-10-10  1:17 ` Vadim Fedorenko
  0 siblings, 0 replies; 67+ messages in thread
From: Vadim Fedorenko @ 2022-10-10  1:17 UTC (permalink / raw)
  To: Jakub Kicinski, Jiri Pirko, Arkadiusz Kubalewski
  Cc: netdev, linux-arm-kernel, linux-clk, Vadim Fedorenko, Vadim Fedorenko

Implement common API for clock/DPLL configuration and status reporting.
The API utilises netlink interface as transport for commands and event
notifications. This API aim to extend current pin configuration and
make it flexible and easy to cover special configurations.

v2 -> v3:
 * implement source select mode (Arkadiusz)
 * add documentation
 * implementation improvements (Jakub)
v1 -> v2:
 * implement returning supported input/output types
 * ptp_ocp: follow suggestions from Jonathan
 * add linux-clk mailing list
v0 -> v1:
 * fix code style and errors
 * add linux-arm mailing list

Arkadiusz Kubalewski (2):
  dpll: add support for source selection modes
  dpll: get source/output name

Vadim Fedorenko (3):
  dpll: add netlink events
  dpll: documentation on DPLL subsystem interface
  ptp_ocp: implement DPLL ops

 Documentation/networking/dpll.rst  | 157 +++++++++++++
 Documentation/networking/index.rst |   1 +
 drivers/dpll/dpll_core.c           |   3 +
 drivers/dpll/dpll_netlink.c        | 346 ++++++++++++++++++++++++++++-
 drivers/dpll/dpll_netlink.h        |   5 +
 drivers/ptp/Kconfig                |   1 +
 drivers/ptp/ptp_ocp.c              | 170 +++++++++++---
 include/linux/dpll.h               |  14 ++
 include/uapi/linux/dpll.h          |  26 ++-
 9 files changed, 678 insertions(+), 45 deletions(-)
 create mode 100644 Documentation/networking/dpll.rst

-- 
2.27.0


^ permalink raw reply	[flat|nested] 67+ messages in thread

* [RFC PATCH v3 0/5] Create common DPLL/clock configuration API
@ 2022-10-10  1:17 ` Vadim Fedorenko
  0 siblings, 0 replies; 67+ messages in thread
From: Vadim Fedorenko @ 2022-10-10  1:17 UTC (permalink / raw)
  To: Jakub Kicinski, Jiri Pirko, Arkadiusz Kubalewski
  Cc: netdev, linux-arm-kernel, linux-clk, Vadim Fedorenko, Vadim Fedorenko

Implement common API for clock/DPLL configuration and status reporting.
The API utilises netlink interface as transport for commands and event
notifications. This API aim to extend current pin configuration and
make it flexible and easy to cover special configurations.

v2 -> v3:
 * implement source select mode (Arkadiusz)
 * add documentation
 * implementation improvements (Jakub)
v1 -> v2:
 * implement returning supported input/output types
 * ptp_ocp: follow suggestions from Jonathan
 * add linux-clk mailing list
v0 -> v1:
 * fix code style and errors
 * add linux-arm mailing list

Arkadiusz Kubalewski (2):
  dpll: add support for source selection modes
  dpll: get source/output name

Vadim Fedorenko (3):
  dpll: add netlink events
  dpll: documentation on DPLL subsystem interface
  ptp_ocp: implement DPLL ops

 Documentation/networking/dpll.rst  | 157 +++++++++++++
 Documentation/networking/index.rst |   1 +
 drivers/dpll/dpll_core.c           |   3 +
 drivers/dpll/dpll_netlink.c        | 346 ++++++++++++++++++++++++++++-
 drivers/dpll/dpll_netlink.h        |   5 +
 drivers/ptp/Kconfig                |   1 +
 drivers/ptp/ptp_ocp.c              | 170 +++++++++++---
 include/linux/dpll.h               |  14 ++
 include/uapi/linux/dpll.h          |  26 ++-
 9 files changed, 678 insertions(+), 45 deletions(-)
 create mode 100644 Documentation/networking/dpll.rst

-- 
2.27.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [RFC PATCH v3 1/6] dpll: Add DPLL framework base functions
  2022-10-10  1:17 ` Vadim Fedorenko
@ 2022-10-10  1:17   ` Vadim Fedorenko
  -1 siblings, 0 replies; 67+ messages in thread
From: Vadim Fedorenko @ 2022-10-10  1:17 UTC (permalink / raw)
  To: Jakub Kicinski, Jiri Pirko, Arkadiusz Kubalewski
  Cc: netdev, linux-arm-kernel, linux-clk, Vadim Fedorenko

From: Vadim Fedorenko <vadfed@fb.com>

DPLL framework is used to represent and configure DPLL devices
in systems. Each device that has DPLL and can configure sources
and outputs can use this framework.

Signed-off-by: Vadim Fedorenko <vadfed@fb.com>
Co-developed-by: Jakub Kicinski <kuba@kernel.org>
Co-developed-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
---
 MAINTAINERS                 |   8 +
 drivers/Kconfig             |   2 +
 drivers/Makefile            |   1 +
 drivers/dpll/Kconfig        |   7 +
 drivers/dpll/Makefile       |   7 +
 drivers/dpll/dpll_core.c    | 177 +++++++++++++++
 drivers/dpll/dpll_core.h    |  41 ++++
 drivers/dpll/dpll_netlink.c | 417 ++++++++++++++++++++++++++++++++++++
 drivers/dpll/dpll_netlink.h |   7 +
 include/linux/dpll.h        |  29 +++
 include/uapi/linux/dpll.h   | 101 +++++++++
 11 files changed, 797 insertions(+)
 create mode 100644 drivers/dpll/Kconfig
 create mode 100644 drivers/dpll/Makefile
 create mode 100644 drivers/dpll/dpll_core.c
 create mode 100644 drivers/dpll/dpll_core.h
 create mode 100644 drivers/dpll/dpll_netlink.c
 create mode 100644 drivers/dpll/dpll_netlink.h
 create mode 100644 include/linux/dpll.h
 create mode 100644 include/uapi/linux/dpll.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 9ca84cb5ab4a..e2f4fede937f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6301,6 +6301,14 @@ F:	Documentation/networking/device_drivers/ethernet/freescale/dpaa2/switch-drive
 F:	drivers/net/ethernet/freescale/dpaa2/dpaa2-switch*
 F:	drivers/net/ethernet/freescale/dpaa2/dpsw*
 
+DPLL CLOCK SUBSYSTEM
+M:	Vadim Fedorenko <vadfed@fb.com>
+L:	netdev@vger.kernel.org
+S:	Maintained
+F:	drivers/dpll/*
+F:	include/net/dpll.h
+F:	include/uapi/linux/dpll.h
+
 DRBD DRIVER
 M:	Philipp Reisner <philipp.reisner@linbit.com>
 M:	Lars Ellenberg <lars.ellenberg@linbit.com>
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 19ee995bd0ae..a3e00294a995 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -239,4 +239,6 @@ source "drivers/peci/Kconfig"
 
 source "drivers/hte/Kconfig"
 
+source "drivers/dpll/Kconfig"
+
 endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index 057857258bfd..78a68f1621cc 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -188,3 +188,4 @@ obj-$(CONFIG_COUNTER)		+= counter/
 obj-$(CONFIG_MOST)		+= most/
 obj-$(CONFIG_PECI)		+= peci/
 obj-$(CONFIG_HTE)		+= hte/
+obj-$(CONFIG_DPLL)		+= dpll/
diff --git a/drivers/dpll/Kconfig b/drivers/dpll/Kconfig
new file mode 100644
index 000000000000..a4cae73f20d3
--- /dev/null
+++ b/drivers/dpll/Kconfig
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Generic DPLL drivers configuration
+#
+
+config DPLL
+  bool
diff --git a/drivers/dpll/Makefile b/drivers/dpll/Makefile
new file mode 100644
index 000000000000..0748c80097e4
--- /dev/null
+++ b/drivers/dpll/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for DPLL drivers.
+#
+
+obj-$(CONFIG_DPLL)          += dpll_sys.o
+dpll_sys-y                  += dpll_core.o dpll_netlink.o
diff --git a/drivers/dpll/dpll_core.c b/drivers/dpll/dpll_core.c
new file mode 100644
index 000000000000..7fdee145e82c
--- /dev/null
+++ b/drivers/dpll/dpll_core.c
@@ -0,0 +1,177 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *  dpll_core.c - Generic DPLL Management class support.
+ *
+ *  Copyright (c) 2021 Meta Platforms, Inc. and affiliates
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+
+#include "dpll_core.h"
+
+static DEFINE_MUTEX(dpll_device_xa_lock);
+static DEFINE_XARRAY_FLAGS(dpll_device_xa, XA_FLAGS_ALLOC);
+#define DPLL_REGISTERED XA_MARK_1
+
+#define ASSERT_DPLL_REGISTERED(d)                                           \
+	WARN_ON_ONCE(!xa_get_mark(&dpll_device_xa, (d)->id, DPLL_REGISTERED))
+#define ASSERT_DPLL_NOT_REGISTERED(d)                                      \
+	WARN_ON_ONCE(xa_get_mark(&dpll_device_xa, (d)->id, DPLL_REGISTERED))
+
+
+int for_each_dpll_device(int id, int (*cb)(struct dpll_device *, void *),
+			 void *data)
+{
+	struct dpll_device *dpll;
+	unsigned long index;
+	int ret = 0;
+
+	mutex_lock(&dpll_device_xa_lock);
+	xa_for_each_start(&dpll_device_xa, index, dpll, id) {
+		if (!xa_get_mark(&dpll_device_xa, index, DPLL_REGISTERED))
+			continue;
+		ret = cb(dpll, data);
+		if (ret)
+			break;
+	}
+	mutex_unlock(&dpll_device_xa_lock);
+
+	return ret;
+}
+
+struct dpll_device *dpll_device_get_by_id(int id)
+{
+	struct dpll_device *dpll = NULL;
+
+	if (xa_get_mark(&dpll_device_xa, id, DPLL_REGISTERED))
+		dpll = xa_load(&dpll_device_xa, id);
+	return dpll;
+}
+
+struct dpll_device *dpll_device_get_by_name(const char *name)
+{
+	struct dpll_device *dpll, *ret = NULL;
+	unsigned long index;
+
+	mutex_lock(&dpll_device_xa_lock);
+	xa_for_each_marked(&dpll_device_xa, index, dpll, DPLL_REGISTERED) {
+		if (!strcmp(dev_name(&dpll->dev), name)) {
+			ret = dpll;
+			break;
+		}
+	}
+	mutex_unlock(&dpll_device_xa_lock);
+
+	return ret;
+}
+
+void *dpll_priv(struct dpll_device *dpll)
+{
+	return dpll->priv;
+}
+EXPORT_SYMBOL_GPL(dpll_priv);
+
+static void dpll_device_release(struct device *dev)
+{
+	struct dpll_device *dpll;
+
+	dpll = to_dpll_device(dev);
+
+	dpll_device_unregister(dpll);
+	dpll_device_free(dpll);
+}
+
+static struct class dpll_class = {
+	.name = "dpll",
+	.dev_release = dpll_device_release,
+};
+
+struct dpll_device *dpll_device_alloc(struct dpll_device_ops *ops, const char *name,
+				      int sources_count, int outputs_count, void *priv)
+{
+	struct dpll_device *dpll;
+	int ret;
+
+	dpll = kzalloc(sizeof(*dpll), GFP_KERNEL);
+	if (!dpll)
+		return ERR_PTR(-ENOMEM);
+
+	mutex_init(&dpll->lock);
+	dpll->ops = ops;
+	dpll->dev.class = &dpll_class;
+	dpll->sources_count = sources_count;
+	dpll->outputs_count = outputs_count;
+
+	mutex_lock(&dpll_device_xa_lock);
+	ret = xa_alloc(&dpll_device_xa, &dpll->id, dpll, xa_limit_16b, GFP_KERNEL);
+	if (ret)
+		goto error;
+	dev_set_name(&dpll->dev, "%s%d", name ? name : "dpll", dpll->id);
+	mutex_unlock(&dpll_device_xa_lock);
+	dpll->priv = priv;
+
+	return dpll;
+
+error:
+	mutex_unlock(&dpll_device_xa_lock);
+	kfree(dpll);
+	return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(dpll_device_alloc);
+
+void dpll_device_free(struct dpll_device *dpll)
+{
+	if (!dpll)
+		return;
+
+	mutex_destroy(&dpll->lock);
+	kfree(dpll);
+}
+EXPORT_SYMBOL_GPL(dpll_device_free);
+
+void dpll_device_register(struct dpll_device *dpll)
+{
+	ASSERT_DPLL_NOT_REGISTERED(dpll);
+
+	mutex_lock(&dpll_device_xa_lock);
+	xa_set_mark(&dpll_device_xa, dpll->id, DPLL_REGISTERED);
+	mutex_unlock(&dpll_device_xa_lock);
+}
+EXPORT_SYMBOL_GPL(dpll_device_register);
+
+void dpll_device_unregister(struct dpll_device *dpll)
+{
+	ASSERT_DPLL_REGISTERED(dpll);
+
+	mutex_lock(&dpll_device_xa_lock);
+	xa_erase(&dpll_device_xa, dpll->id);
+	mutex_unlock(&dpll_device_xa_lock);
+}
+EXPORT_SYMBOL_GPL(dpll_device_unregister);
+
+static int __init dpll_init(void)
+{
+	int ret;
+
+	ret = dpll_netlink_init();
+	if (ret)
+		goto error;
+
+	ret = class_register(&dpll_class);
+	if (ret)
+		goto unregister_netlink;
+
+	return 0;
+
+unregister_netlink:
+	dpll_netlink_finish();
+error:
+	mutex_destroy(&dpll_device_xa_lock);
+	return ret;
+}
+subsys_initcall(dpll_init);
diff --git a/drivers/dpll/dpll_core.h b/drivers/dpll/dpll_core.h
new file mode 100644
index 000000000000..4b6fc9eb228f
--- /dev/null
+++ b/drivers/dpll/dpll_core.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *  Copyright (c) 2021 Meta Platforms, Inc. and affiliates
+ */
+
+#ifndef __DPLL_CORE_H__
+#define __DPLL_CORE_H__
+
+#include <linux/dpll.h>
+
+#include "dpll_netlink.h"
+
+/**
+ * struct dpll_device - structure for a DPLL device
+ * @id:		unique id number for each edvice
+ * @dev:	&struct device for this dpll device
+ * @sources_count:	amount of input sources this dpll_device supports
+ * @outputs_count:	amount of outputs this dpll_device supports
+ * @ops:	operations this &dpll_device supports
+ * @lock:	mutex to serialize operations
+ * @priv:	pointer to private information of owner
+ */
+struct dpll_device {
+	int id;
+	struct device dev;
+	int sources_count;
+	int outputs_count;
+	struct dpll_device_ops *ops;
+	struct mutex lock;
+	void *priv;
+};
+
+#define to_dpll_device(_dev) \
+	container_of(_dev, struct dpll_device, dev)
+
+int for_each_dpll_device(int id, int (*cb)(struct dpll_device *, void *),
+			  void *data);
+struct dpll_device *dpll_device_get_by_id(int id);
+struct dpll_device *dpll_device_get_by_name(const char *name);
+void dpll_device_unregister(struct dpll_device *dpll);
+#endif
diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c
new file mode 100644
index 000000000000..31966e0eec3a
--- /dev/null
+++ b/drivers/dpll/dpll_netlink.c
@@ -0,0 +1,417 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Generic netlink for DPLL management framework
+ *
+ * Copyright (c) 2021 Meta Platforms, Inc. and affiliates
+ *
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <net/genetlink.h>
+#include "dpll_core.h"
+
+#include <uapi/linux/dpll.h>
+
+static const struct genl_multicast_group dpll_genl_mcgrps[] = {
+	{ .name = DPLL_CONFIG_DEVICE_GROUP_NAME, },
+	{ .name = DPLL_CONFIG_SOURCE_GROUP_NAME, },
+	{ .name = DPLL_CONFIG_OUTPUT_GROUP_NAME, },
+	{ .name = DPLL_MONITOR_GROUP_NAME,  },
+};
+
+static const struct nla_policy dpll_genl_get_policy[] = {
+	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
+	[DPLLA_DEVICE_NAME]	= { .type = NLA_STRING,
+				    .len = DPLL_NAME_LENGTH },
+	[DPLLA_FLAGS]		= { .type = NLA_U32 },
+};
+
+static const struct nla_policy dpll_genl_set_source_policy[] = {
+	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
+	[DPLLA_SOURCE_ID]	= { .type = NLA_U32 },
+	[DPLLA_SOURCE_TYPE]	= { .type = NLA_U32 },
+};
+
+static const struct nla_policy dpll_genl_set_output_policy[] = {
+	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
+	[DPLLA_OUTPUT_ID]	= { .type = NLA_U32 },
+	[DPLLA_OUTPUT_TYPE]	= { .type = NLA_U32 },
+};
+
+struct param {
+	struct netlink_callback *cb;
+	struct dpll_device *dpll;
+	struct sk_buff *msg;
+	int dpll_id;
+	int dpll_source_id;
+	int dpll_source_type;
+	int dpll_output_id;
+	int dpll_output_type;
+};
+
+struct dpll_dump_ctx {
+	struct dpll_device *dev;
+	int flags;
+	int pos_idx;
+	int pos_src_idx;
+	int pos_out_idx;
+};
+
+typedef int (*cb_t)(struct param *);
+
+static struct genl_family dpll_gnl_family;
+
+static struct dpll_dump_ctx *dpll_dump_context(struct netlink_callback *cb)
+{
+	return (struct dpll_dump_ctx *)cb->ctx;
+}
+
+static int __dpll_cmd_device_dump_one(struct dpll_device *dpll,
+					   struct sk_buff *msg)
+{
+	if (nla_put_u32(msg, DPLLA_DEVICE_ID, dpll->id))
+		return -EMSGSIZE;
+
+	if (nla_put_string(msg, DPLLA_DEVICE_NAME, dev_name(&dpll->dev)))
+		return -EMSGSIZE;
+
+	return 0;
+}
+
+static int __dpll_cmd_dump_sources(struct dpll_device *dpll,
+					   struct sk_buff *msg)
+{
+	struct nlattr *src_attr;
+	int i, ret = 0, type;
+
+	for (i = 0; i < dpll->sources_count; i++) {
+		src_attr = nla_nest_start(msg, DPLLA_SOURCE);
+		if (!src_attr) {
+			ret = -EMSGSIZE;
+			break;
+		}
+		type = dpll->ops->get_source_type(dpll, i);
+		if (nla_put_u32(msg, DPLLA_SOURCE_ID, i) ||
+		    nla_put_u32(msg, DPLLA_SOURCE_TYPE, type)) {
+			nla_nest_cancel(msg, src_attr);
+			ret = -EMSGSIZE;
+			break;
+		}
+		if (dpll->ops->get_source_supported) {
+			for (type = 0; type <= DPLL_TYPE_MAX; type++) {
+				ret = dpll->ops->get_source_supported(dpll, i, type);
+				if (ret && nla_put_u32(msg, DPLLA_SOURCE_SUPPORTED, type)) {
+					ret = -EMSGSIZE;
+					break;
+				}
+			}
+			ret = 0;
+		}
+		nla_nest_end(msg, src_attr);
+	}
+
+	return ret;
+}
+
+static int __dpll_cmd_dump_outputs(struct dpll_device *dpll,
+					   struct sk_buff *msg)
+{
+	struct nlattr *out_attr;
+	int i, ret = 0, type;
+
+	for (i = 0; i < dpll->outputs_count; i++) {
+		out_attr = nla_nest_start(msg, DPLLA_OUTPUT);
+		if (!out_attr) {
+			ret = -EMSGSIZE;
+			break;
+		}
+		type = dpll->ops->get_output_type(dpll, i);
+		if (nla_put_u32(msg, DPLLA_OUTPUT_ID, i) ||
+		    nla_put_u32(msg, DPLLA_OUTPUT_TYPE, type)) {
+			nla_nest_cancel(msg, out_attr);
+			ret = -EMSGSIZE;
+			break;
+		}
+		if (dpll->ops->get_output_supported) {
+			for (type = 0; type <= DPLL_TYPE_MAX; type++) {
+				ret = dpll->ops->get_output_supported(dpll, i, type);
+				if (ret && nla_put_u32(msg, DPLLA_OUTPUT_SUPPORTED, type)) {
+					ret = -EMSGSIZE;
+					break;
+				}
+			}
+			ret = 0;
+		}
+		nla_nest_end(msg, out_attr);
+	}
+
+	return ret;
+}
+
+static int __dpll_cmd_dump_status(struct dpll_device *dpll,
+					   struct sk_buff *msg)
+{
+	int ret;
+
+	if (dpll->ops->get_status) {
+		ret = dpll->ops->get_status(dpll);
+		if (nla_put_u32(msg, DPLLA_STATUS, ret))
+			return -EMSGSIZE;
+	}
+
+	if (dpll->ops->get_temp) {
+		ret = dpll->ops->get_temp(dpll);
+		if (nla_put_u32(msg, DPLLA_TEMP, ret))
+			return -EMSGSIZE;
+	}
+
+	if (dpll->ops->get_lock_status) {
+		ret = dpll->ops->get_lock_status(dpll);
+		if (nla_put_u32(msg, DPLLA_LOCK_STATUS, ret))
+			return -EMSGSIZE;
+	}
+
+	return 0;
+}
+
+static int
+dpll_device_dump_one(struct dpll_device *dpll, struct sk_buff *msg,
+		     u32 portid, u32 seq, int flags)
+{
+	struct nlattr *hdr;
+	int ret;
+
+	hdr = genlmsg_put(msg, portid, seq, &dpll_gnl_family, 0,
+			  DPLL_CMD_DEVICE_GET);
+	if (!hdr)
+		return -EMSGSIZE;
+
+	mutex_lock(&dpll->lock);
+	ret = __dpll_cmd_device_dump_one(dpll, msg);
+	if (ret)
+		goto out_unlock;
+
+	if (flags & DPLL_FLAG_SOURCES && dpll->ops->get_source_type) {
+		ret = __dpll_cmd_dump_sources(dpll, msg);
+		if (ret)
+			goto out_unlock;
+	}
+
+	if (flags & DPLL_FLAG_OUTPUTS && dpll->ops->get_output_type) {
+		ret = __dpll_cmd_dump_outputs(dpll, msg);
+		if (ret)
+			goto out_unlock;
+	}
+
+	if (flags & DPLL_FLAG_STATUS) {
+		ret = __dpll_cmd_dump_status(dpll, msg);
+		if (ret)
+			goto out_unlock;
+	}
+	mutex_unlock(&dpll->lock);
+	genlmsg_end(msg, hdr);
+
+	return 0;
+
+out_unlock:
+	mutex_unlock(&dpll->lock);
+	genlmsg_cancel(msg, hdr);
+
+	return ret;
+}
+
+static int dpll_genl_cmd_set_source(struct sk_buff *skb, struct genl_info *info)
+{
+	struct dpll_device *dpll = info->user_ptr[0];
+	struct nlattr **attrs = info->attrs;
+	int ret = 0, src_id, type;
+
+	if (!attrs[DPLLA_SOURCE_ID] ||
+	    !attrs[DPLLA_SOURCE_TYPE])
+		return -EINVAL;
+
+	if (!dpll->ops->set_source_type)
+		return -EOPNOTSUPP;
+
+	src_id = nla_get_u32(attrs[DPLLA_SOURCE_ID]);
+	type = nla_get_u32(attrs[DPLLA_SOURCE_TYPE]);
+
+	mutex_lock(&dpll->lock);
+	ret = dpll->ops->set_source_type(dpll, src_id, type);
+	mutex_unlock(&dpll->lock);
+
+	return ret;
+}
+
+static int dpll_genl_cmd_set_output(struct sk_buff *skb, struct genl_info *info)
+{
+	struct dpll_device *dpll = info->user_ptr[0];
+	struct nlattr **attrs = info->attrs;
+	int ret = 0, out_id, type;
+
+	if (!attrs[DPLLA_OUTPUT_ID] ||
+	    !attrs[DPLLA_OUTPUT_TYPE])
+		return -EINVAL;
+
+	if (!dpll->ops->set_output_type)
+		return -EOPNOTSUPP;
+
+	out_id = nla_get_u32(attrs[DPLLA_OUTPUT_ID]);
+	type = nla_get_u32(attrs[DPLLA_OUTPUT_TYPE]);
+
+	mutex_lock(&dpll->lock);
+	ret = dpll->ops->set_output_type(dpll, out_id, type);
+	mutex_unlock(&dpll->lock);
+
+	return ret;
+}
+
+static int dpll_device_loop_cb(struct dpll_device *dpll, void *data)
+{
+	struct dpll_dump_ctx *ctx;
+	struct param *p = (struct param *)data;
+
+	ctx = dpll_dump_context(p->cb);
+
+	ctx->pos_idx = dpll->id;
+
+	return dpll_device_dump_one(dpll, p->msg, 0, 0, ctx->flags);
+}
+
+static int
+dpll_cmd_device_dump(struct sk_buff *skb, struct netlink_callback *cb)
+{
+	struct dpll_dump_ctx *ctx = dpll_dump_context(cb);
+	struct param p = { .cb = cb, .msg = skb };
+
+	return for_each_dpll_device(ctx->pos_idx, dpll_device_loop_cb, &p);
+}
+
+static int
+dpll_genl_cmd_device_get_id(struct sk_buff *skb, struct genl_info *info)
+{
+	struct dpll_device *dpll = info->user_ptr[0];
+	struct nlattr **attrs = info->attrs;
+	struct sk_buff *msg;
+	int flags = 0;
+	int ret;
+
+	if (attrs[DPLLA_FLAGS])
+		flags = nla_get_u32(attrs[DPLLA_FLAGS]);
+
+	msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+	if (!msg)
+		return -ENOMEM;
+
+	ret = dpll_device_dump_one(dpll, msg, info->snd_portid, info->snd_seq,
+				   flags);
+	if (ret)
+		goto out_free_msg;
+
+	return genlmsg_reply(msg, info);
+
+out_free_msg:
+	nlmsg_free(msg);
+	return ret;
+
+}
+
+static int dpll_genl_cmd_start(struct netlink_callback *cb)
+{
+	const struct genl_dumpit_info *info = genl_dumpit_info(cb);
+	struct dpll_dump_ctx *ctx = dpll_dump_context(cb);
+
+	ctx->dev = NULL;
+	if (info->attrs[DPLLA_FLAGS])
+		ctx->flags = nla_get_u32(info->attrs[DPLLA_FLAGS]);
+	else
+		ctx->flags = 0;
+	ctx->pos_idx = 0;
+	ctx->pos_src_idx = 0;
+	ctx->pos_out_idx = 0;
+	return 0;
+}
+
+static int dpll_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
+						 struct genl_info *info)
+{
+	struct dpll_device *dpll_id = NULL, *dpll_name = NULL;
+
+	if (!info->attrs[DPLLA_DEVICE_ID] &&
+	    !info->attrs[DPLLA_DEVICE_NAME])
+		return -EINVAL;
+
+	if (info->attrs[DPLLA_DEVICE_ID]) {
+		u32 id = nla_get_u32(info->attrs[DPLLA_DEVICE_ID]);
+
+		dpll_id = dpll_device_get_by_id(id);
+		if (!dpll_id)
+			return -ENODEV;
+		info->user_ptr[0] = dpll_id;
+	}
+	if (info->attrs[DPLLA_DEVICE_NAME]) {
+		const char *name = nla_data(info->attrs[DPLLA_DEVICE_NAME]);
+
+		dpll_name = dpll_device_get_by_name(name);
+		if (!dpll_name)
+			return -ENODEV;
+
+		if (dpll_id && dpll_name != dpll_id)
+			return -EINVAL;
+		info->user_ptr[0] = dpll_name;
+	}
+
+	return 0;
+}
+
+static const struct genl_ops dpll_genl_ops[] = {
+	{
+		.cmd	= DPLL_CMD_DEVICE_GET,
+		.flags  = GENL_UNS_ADMIN_PERM,
+		.start	= dpll_genl_cmd_start,
+		.dumpit	= dpll_cmd_device_dump,
+		.doit	= dpll_genl_cmd_device_get_id,
+		.policy	= dpll_genl_get_policy,
+		.maxattr = ARRAY_SIZE(dpll_genl_get_policy) - 1,
+	},
+	{
+		.cmd	= DPLL_CMD_SET_SOURCE_TYPE,
+		.flags	= GENL_UNS_ADMIN_PERM,
+		.doit	= dpll_genl_cmd_set_source,
+		.policy	= dpll_genl_set_source_policy,
+		.maxattr = ARRAY_SIZE(dpll_genl_set_source_policy) - 1,
+	},
+	{
+		.cmd	= DPLL_CMD_SET_OUTPUT_TYPE,
+		.flags	= GENL_UNS_ADMIN_PERM,
+		.doit	= dpll_genl_cmd_set_output,
+		.policy	= dpll_genl_set_output_policy,
+		.maxattr = ARRAY_SIZE(dpll_genl_set_output_policy) - 1,
+	},
+};
+
+static struct genl_family dpll_gnl_family __ro_after_init = {
+	.hdrsize	= 0,
+	.name		= DPLL_FAMILY_NAME,
+	.version	= DPLL_VERSION,
+	.ops		= dpll_genl_ops,
+	.n_ops		= ARRAY_SIZE(dpll_genl_ops),
+	.mcgrps		= dpll_genl_mcgrps,
+	.n_mcgrps	= ARRAY_SIZE(dpll_genl_mcgrps),
+	.pre_doit	= dpll_pre_doit,
+};
+
+int __init dpll_netlink_init(void)
+{
+	return genl_register_family(&dpll_gnl_family);
+}
+
+void dpll_netlink_finish(void)
+{
+	genl_unregister_family(&dpll_gnl_family);
+}
+
+void __exit dpll_netlink_fini(void)
+{
+	dpll_netlink_finish();
+}
diff --git a/drivers/dpll/dpll_netlink.h b/drivers/dpll/dpll_netlink.h
new file mode 100644
index 000000000000..e2d100f59dd6
--- /dev/null
+++ b/drivers/dpll/dpll_netlink.h
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *  Copyright (c) 2021 Meta Platforms, Inc. and affiliates
+ */
+
+int __init dpll_netlink_init(void);
+void dpll_netlink_finish(void);
diff --git a/include/linux/dpll.h b/include/linux/dpll.h
new file mode 100644
index 000000000000..9d49b19d03d9
--- /dev/null
+++ b/include/linux/dpll.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *  Copyright (c) 2021 Meta Platforms, Inc. and affiliates
+ */
+
+#ifndef __DPLL_H__
+#define __DPLL_H__
+
+struct dpll_device;
+
+struct dpll_device_ops {
+	int (*get_status)(struct dpll_device *dpll);
+	int (*get_temp)(struct dpll_device *dpll);
+	int (*get_lock_status)(struct dpll_device *dpll);
+	int (*get_source_type)(struct dpll_device *dpll, int id);
+	int (*get_source_supported)(struct dpll_device *dpll, int id, int type);
+	int (*get_output_type)(struct dpll_device *dpll, int id);
+	int (*get_output_supported)(struct dpll_device *dpll, int id, int type);
+	int (*set_source_type)(struct dpll_device *dpll, int id, int val);
+	int (*set_output_type)(struct dpll_device *dpll, int id, int val);
+};
+
+struct dpll_device *dpll_device_alloc(struct dpll_device_ops *ops, const char *name,
+				      int sources_count, int outputs_count, void *priv);
+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);
+#endif
diff --git a/include/uapi/linux/dpll.h b/include/uapi/linux/dpll.h
new file mode 100644
index 000000000000..fcbea5a5e4d6
--- /dev/null
+++ b/include/uapi/linux/dpll.h
@@ -0,0 +1,101 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef _UAPI_LINUX_DPLL_H
+#define _UAPI_LINUX_DPLL_H
+
+#define DPLL_NAME_LENGTH	20
+
+/* Adding event notification support elements */
+#define DPLL_FAMILY_NAME		"dpll"
+#define DPLL_VERSION			0x01
+#define DPLL_CONFIG_DEVICE_GROUP_NAME  "config"
+#define DPLL_CONFIG_SOURCE_GROUP_NAME  "source"
+#define DPLL_CONFIG_OUTPUT_GROUP_NAME  "output"
+#define DPLL_MONITOR_GROUP_NAME        "monitor"
+
+#define DPLL_FLAG_SOURCES	1
+#define DPLL_FLAG_OUTPUTS	2
+#define DPLL_FLAG_STATUS	4
+
+/* Attributes of dpll_genl_family */
+enum dpll_genl_attr {
+	DPLLA_UNSPEC,
+	DPLLA_DEVICE_ID,
+	DPLLA_DEVICE_NAME,
+	DPLLA_SOURCE,
+	DPLLA_SOURCE_ID,
+	DPLLA_SOURCE_TYPE,
+	DPLLA_SOURCE_SUPPORTED,
+	DPLLA_OUTPUT,
+	DPLLA_OUTPUT_ID,
+	DPLLA_OUTPUT_TYPE,
+	DPLLA_OUTPUT_SUPPORTED,
+	DPLLA_STATUS,
+	DPLLA_TEMP,
+	DPLLA_LOCK_STATUS,
+	DPLLA_FLAGS,
+
+	__DPLLA_MAX,
+};
+#define DPLLA_MAX (__DPLLA_MAX - 1)
+
+/* DPLL status provides information of device status */
+enum dpll_genl_status {
+	DPLL_STATUS_NONE,
+	DPLL_STATUS_CALIBRATING,
+	DPLL_STATUS_LOCKED,
+
+	__DPLL_STATUS_MAX,
+};
+#define DPLL_STATUS_MAX (__DPLL_STATUS_MAX - 1)
+
+/* DPLL signal types used as source or as output */
+enum dpll_genl_signal_type {
+	DPLL_TYPE_EXT_1PPS,
+	DPLL_TYPE_EXT_10MHZ,
+	DPLL_TYPE_SYNCE_ETH_PORT,
+	DPLL_TYPE_INT_OSCILLATOR,
+	DPLL_TYPE_GNSS,
+
+	__DPLL_TYPE_MAX,
+};
+#define DPLL_TYPE_MAX (__DPLL_TYPE_MAX - 1)
+
+/* DPLL lock status provides information of source used to lock the device */
+enum dpll_genl_lock_status {
+	DPLL_LOCK_STATUS_UNLOCKED,
+	DPLL_LOCK_STATUS_EXT_1PPS,
+	DPLL_LOCK_STATUS_EXT_10MHZ,
+	DPLL_LOCK_STATUS_SYNCE,
+	DPLL_LOCK_STATUS_INT_OSCILLATOR,
+	DPLL_LOCK_STATUS_GNSS,
+
+	__DPLL_LOCK_STATUS_MAX,
+};
+#define DPLL_LOCK_STATUS_MAX (__DPLL_LOCK_STATUS_MAX - 1)
+
+/* Events of dpll_genl_family */
+enum dpll_genl_event {
+	DPLL_EVENT_UNSPEC,
+	DPLL_EVENT_DEVICE_CREATE,		/* DPLL device creation */
+	DPLL_EVENT_DEVICE_DELETE,		/* DPLL device deletion */
+	DPLL_EVENT_STATUS_LOCKED,		/* DPLL device locked to source */
+	DPLL_EVENT_STATUS_UNLOCKED,	/* DPLL device freerun */
+	DPLL_EVENT_SOURCE_CHANGE,		/* DPLL device source changed */
+	DPLL_EVENT_OUTPUT_CHANGE,		/* DPLL device output changed */
+
+	__DPLL_EVENT_MAX,
+};
+#define DPLL_EVENT_MAX (__DPLL_EVENT_MAX - 1)
+
+/* Commands supported by the dpll_genl_family */
+enum dpll_genl_cmd {
+	DPLL_CMD_UNSPEC,
+	DPLL_CMD_DEVICE_GET,	/* List of DPLL devices id */
+	DPLL_CMD_SET_SOURCE_TYPE,	/* Set the DPLL device source type */
+	DPLL_CMD_SET_OUTPUT_TYPE,	/* Set the DPLL device output type */
+
+	__DPLL_CMD_MAX,
+};
+#define DPLL_CMD_MAX (__DPLL_CMD_MAX - 1)
+
+#endif /* _UAPI_LINUX_DPLL_H */
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [RFC PATCH v3 1/6] dpll: Add DPLL framework base functions
@ 2022-10-10  1:17   ` Vadim Fedorenko
  0 siblings, 0 replies; 67+ messages in thread
From: Vadim Fedorenko @ 2022-10-10  1:17 UTC (permalink / raw)
  To: Jakub Kicinski, Jiri Pirko, Arkadiusz Kubalewski
  Cc: netdev, linux-arm-kernel, linux-clk, Vadim Fedorenko

From: Vadim Fedorenko <vadfed@fb.com>

DPLL framework is used to represent and configure DPLL devices
in systems. Each device that has DPLL and can configure sources
and outputs can use this framework.

Signed-off-by: Vadim Fedorenko <vadfed@fb.com>
Co-developed-by: Jakub Kicinski <kuba@kernel.org>
Co-developed-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
---
 MAINTAINERS                 |   8 +
 drivers/Kconfig             |   2 +
 drivers/Makefile            |   1 +
 drivers/dpll/Kconfig        |   7 +
 drivers/dpll/Makefile       |   7 +
 drivers/dpll/dpll_core.c    | 177 +++++++++++++++
 drivers/dpll/dpll_core.h    |  41 ++++
 drivers/dpll/dpll_netlink.c | 417 ++++++++++++++++++++++++++++++++++++
 drivers/dpll/dpll_netlink.h |   7 +
 include/linux/dpll.h        |  29 +++
 include/uapi/linux/dpll.h   | 101 +++++++++
 11 files changed, 797 insertions(+)
 create mode 100644 drivers/dpll/Kconfig
 create mode 100644 drivers/dpll/Makefile
 create mode 100644 drivers/dpll/dpll_core.c
 create mode 100644 drivers/dpll/dpll_core.h
 create mode 100644 drivers/dpll/dpll_netlink.c
 create mode 100644 drivers/dpll/dpll_netlink.h
 create mode 100644 include/linux/dpll.h
 create mode 100644 include/uapi/linux/dpll.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 9ca84cb5ab4a..e2f4fede937f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6301,6 +6301,14 @@ F:	Documentation/networking/device_drivers/ethernet/freescale/dpaa2/switch-drive
 F:	drivers/net/ethernet/freescale/dpaa2/dpaa2-switch*
 F:	drivers/net/ethernet/freescale/dpaa2/dpsw*
 
+DPLL CLOCK SUBSYSTEM
+M:	Vadim Fedorenko <vadfed@fb.com>
+L:	netdev@vger.kernel.org
+S:	Maintained
+F:	drivers/dpll/*
+F:	include/net/dpll.h
+F:	include/uapi/linux/dpll.h
+
 DRBD DRIVER
 M:	Philipp Reisner <philipp.reisner@linbit.com>
 M:	Lars Ellenberg <lars.ellenberg@linbit.com>
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 19ee995bd0ae..a3e00294a995 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -239,4 +239,6 @@ source "drivers/peci/Kconfig"
 
 source "drivers/hte/Kconfig"
 
+source "drivers/dpll/Kconfig"
+
 endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index 057857258bfd..78a68f1621cc 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -188,3 +188,4 @@ obj-$(CONFIG_COUNTER)		+= counter/
 obj-$(CONFIG_MOST)		+= most/
 obj-$(CONFIG_PECI)		+= peci/
 obj-$(CONFIG_HTE)		+= hte/
+obj-$(CONFIG_DPLL)		+= dpll/
diff --git a/drivers/dpll/Kconfig b/drivers/dpll/Kconfig
new file mode 100644
index 000000000000..a4cae73f20d3
--- /dev/null
+++ b/drivers/dpll/Kconfig
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Generic DPLL drivers configuration
+#
+
+config DPLL
+  bool
diff --git a/drivers/dpll/Makefile b/drivers/dpll/Makefile
new file mode 100644
index 000000000000..0748c80097e4
--- /dev/null
+++ b/drivers/dpll/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for DPLL drivers.
+#
+
+obj-$(CONFIG_DPLL)          += dpll_sys.o
+dpll_sys-y                  += dpll_core.o dpll_netlink.o
diff --git a/drivers/dpll/dpll_core.c b/drivers/dpll/dpll_core.c
new file mode 100644
index 000000000000..7fdee145e82c
--- /dev/null
+++ b/drivers/dpll/dpll_core.c
@@ -0,0 +1,177 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *  dpll_core.c - Generic DPLL Management class support.
+ *
+ *  Copyright (c) 2021 Meta Platforms, Inc. and affiliates
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+
+#include "dpll_core.h"
+
+static DEFINE_MUTEX(dpll_device_xa_lock);
+static DEFINE_XARRAY_FLAGS(dpll_device_xa, XA_FLAGS_ALLOC);
+#define DPLL_REGISTERED XA_MARK_1
+
+#define ASSERT_DPLL_REGISTERED(d)                                           \
+	WARN_ON_ONCE(!xa_get_mark(&dpll_device_xa, (d)->id, DPLL_REGISTERED))
+#define ASSERT_DPLL_NOT_REGISTERED(d)                                      \
+	WARN_ON_ONCE(xa_get_mark(&dpll_device_xa, (d)->id, DPLL_REGISTERED))
+
+
+int for_each_dpll_device(int id, int (*cb)(struct dpll_device *, void *),
+			 void *data)
+{
+	struct dpll_device *dpll;
+	unsigned long index;
+	int ret = 0;
+
+	mutex_lock(&dpll_device_xa_lock);
+	xa_for_each_start(&dpll_device_xa, index, dpll, id) {
+		if (!xa_get_mark(&dpll_device_xa, index, DPLL_REGISTERED))
+			continue;
+		ret = cb(dpll, data);
+		if (ret)
+			break;
+	}
+	mutex_unlock(&dpll_device_xa_lock);
+
+	return ret;
+}
+
+struct dpll_device *dpll_device_get_by_id(int id)
+{
+	struct dpll_device *dpll = NULL;
+
+	if (xa_get_mark(&dpll_device_xa, id, DPLL_REGISTERED))
+		dpll = xa_load(&dpll_device_xa, id);
+	return dpll;
+}
+
+struct dpll_device *dpll_device_get_by_name(const char *name)
+{
+	struct dpll_device *dpll, *ret = NULL;
+	unsigned long index;
+
+	mutex_lock(&dpll_device_xa_lock);
+	xa_for_each_marked(&dpll_device_xa, index, dpll, DPLL_REGISTERED) {
+		if (!strcmp(dev_name(&dpll->dev), name)) {
+			ret = dpll;
+			break;
+		}
+	}
+	mutex_unlock(&dpll_device_xa_lock);
+
+	return ret;
+}
+
+void *dpll_priv(struct dpll_device *dpll)
+{
+	return dpll->priv;
+}
+EXPORT_SYMBOL_GPL(dpll_priv);
+
+static void dpll_device_release(struct device *dev)
+{
+	struct dpll_device *dpll;
+
+	dpll = to_dpll_device(dev);
+
+	dpll_device_unregister(dpll);
+	dpll_device_free(dpll);
+}
+
+static struct class dpll_class = {
+	.name = "dpll",
+	.dev_release = dpll_device_release,
+};
+
+struct dpll_device *dpll_device_alloc(struct dpll_device_ops *ops, const char *name,
+				      int sources_count, int outputs_count, void *priv)
+{
+	struct dpll_device *dpll;
+	int ret;
+
+	dpll = kzalloc(sizeof(*dpll), GFP_KERNEL);
+	if (!dpll)
+		return ERR_PTR(-ENOMEM);
+
+	mutex_init(&dpll->lock);
+	dpll->ops = ops;
+	dpll->dev.class = &dpll_class;
+	dpll->sources_count = sources_count;
+	dpll->outputs_count = outputs_count;
+
+	mutex_lock(&dpll_device_xa_lock);
+	ret = xa_alloc(&dpll_device_xa, &dpll->id, dpll, xa_limit_16b, GFP_KERNEL);
+	if (ret)
+		goto error;
+	dev_set_name(&dpll->dev, "%s%d", name ? name : "dpll", dpll->id);
+	mutex_unlock(&dpll_device_xa_lock);
+	dpll->priv = priv;
+
+	return dpll;
+
+error:
+	mutex_unlock(&dpll_device_xa_lock);
+	kfree(dpll);
+	return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(dpll_device_alloc);
+
+void dpll_device_free(struct dpll_device *dpll)
+{
+	if (!dpll)
+		return;
+
+	mutex_destroy(&dpll->lock);
+	kfree(dpll);
+}
+EXPORT_SYMBOL_GPL(dpll_device_free);
+
+void dpll_device_register(struct dpll_device *dpll)
+{
+	ASSERT_DPLL_NOT_REGISTERED(dpll);
+
+	mutex_lock(&dpll_device_xa_lock);
+	xa_set_mark(&dpll_device_xa, dpll->id, DPLL_REGISTERED);
+	mutex_unlock(&dpll_device_xa_lock);
+}
+EXPORT_SYMBOL_GPL(dpll_device_register);
+
+void dpll_device_unregister(struct dpll_device *dpll)
+{
+	ASSERT_DPLL_REGISTERED(dpll);
+
+	mutex_lock(&dpll_device_xa_lock);
+	xa_erase(&dpll_device_xa, dpll->id);
+	mutex_unlock(&dpll_device_xa_lock);
+}
+EXPORT_SYMBOL_GPL(dpll_device_unregister);
+
+static int __init dpll_init(void)
+{
+	int ret;
+
+	ret = dpll_netlink_init();
+	if (ret)
+		goto error;
+
+	ret = class_register(&dpll_class);
+	if (ret)
+		goto unregister_netlink;
+
+	return 0;
+
+unregister_netlink:
+	dpll_netlink_finish();
+error:
+	mutex_destroy(&dpll_device_xa_lock);
+	return ret;
+}
+subsys_initcall(dpll_init);
diff --git a/drivers/dpll/dpll_core.h b/drivers/dpll/dpll_core.h
new file mode 100644
index 000000000000..4b6fc9eb228f
--- /dev/null
+++ b/drivers/dpll/dpll_core.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *  Copyright (c) 2021 Meta Platforms, Inc. and affiliates
+ */
+
+#ifndef __DPLL_CORE_H__
+#define __DPLL_CORE_H__
+
+#include <linux/dpll.h>
+
+#include "dpll_netlink.h"
+
+/**
+ * struct dpll_device - structure for a DPLL device
+ * @id:		unique id number for each edvice
+ * @dev:	&struct device for this dpll device
+ * @sources_count:	amount of input sources this dpll_device supports
+ * @outputs_count:	amount of outputs this dpll_device supports
+ * @ops:	operations this &dpll_device supports
+ * @lock:	mutex to serialize operations
+ * @priv:	pointer to private information of owner
+ */
+struct dpll_device {
+	int id;
+	struct device dev;
+	int sources_count;
+	int outputs_count;
+	struct dpll_device_ops *ops;
+	struct mutex lock;
+	void *priv;
+};
+
+#define to_dpll_device(_dev) \
+	container_of(_dev, struct dpll_device, dev)
+
+int for_each_dpll_device(int id, int (*cb)(struct dpll_device *, void *),
+			  void *data);
+struct dpll_device *dpll_device_get_by_id(int id);
+struct dpll_device *dpll_device_get_by_name(const char *name);
+void dpll_device_unregister(struct dpll_device *dpll);
+#endif
diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c
new file mode 100644
index 000000000000..31966e0eec3a
--- /dev/null
+++ b/drivers/dpll/dpll_netlink.c
@@ -0,0 +1,417 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Generic netlink for DPLL management framework
+ *
+ * Copyright (c) 2021 Meta Platforms, Inc. and affiliates
+ *
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <net/genetlink.h>
+#include "dpll_core.h"
+
+#include <uapi/linux/dpll.h>
+
+static const struct genl_multicast_group dpll_genl_mcgrps[] = {
+	{ .name = DPLL_CONFIG_DEVICE_GROUP_NAME, },
+	{ .name = DPLL_CONFIG_SOURCE_GROUP_NAME, },
+	{ .name = DPLL_CONFIG_OUTPUT_GROUP_NAME, },
+	{ .name = DPLL_MONITOR_GROUP_NAME,  },
+};
+
+static const struct nla_policy dpll_genl_get_policy[] = {
+	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
+	[DPLLA_DEVICE_NAME]	= { .type = NLA_STRING,
+				    .len = DPLL_NAME_LENGTH },
+	[DPLLA_FLAGS]		= { .type = NLA_U32 },
+};
+
+static const struct nla_policy dpll_genl_set_source_policy[] = {
+	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
+	[DPLLA_SOURCE_ID]	= { .type = NLA_U32 },
+	[DPLLA_SOURCE_TYPE]	= { .type = NLA_U32 },
+};
+
+static const struct nla_policy dpll_genl_set_output_policy[] = {
+	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
+	[DPLLA_OUTPUT_ID]	= { .type = NLA_U32 },
+	[DPLLA_OUTPUT_TYPE]	= { .type = NLA_U32 },
+};
+
+struct param {
+	struct netlink_callback *cb;
+	struct dpll_device *dpll;
+	struct sk_buff *msg;
+	int dpll_id;
+	int dpll_source_id;
+	int dpll_source_type;
+	int dpll_output_id;
+	int dpll_output_type;
+};
+
+struct dpll_dump_ctx {
+	struct dpll_device *dev;
+	int flags;
+	int pos_idx;
+	int pos_src_idx;
+	int pos_out_idx;
+};
+
+typedef int (*cb_t)(struct param *);
+
+static struct genl_family dpll_gnl_family;
+
+static struct dpll_dump_ctx *dpll_dump_context(struct netlink_callback *cb)
+{
+	return (struct dpll_dump_ctx *)cb->ctx;
+}
+
+static int __dpll_cmd_device_dump_one(struct dpll_device *dpll,
+					   struct sk_buff *msg)
+{
+	if (nla_put_u32(msg, DPLLA_DEVICE_ID, dpll->id))
+		return -EMSGSIZE;
+
+	if (nla_put_string(msg, DPLLA_DEVICE_NAME, dev_name(&dpll->dev)))
+		return -EMSGSIZE;
+
+	return 0;
+}
+
+static int __dpll_cmd_dump_sources(struct dpll_device *dpll,
+					   struct sk_buff *msg)
+{
+	struct nlattr *src_attr;
+	int i, ret = 0, type;
+
+	for (i = 0; i < dpll->sources_count; i++) {
+		src_attr = nla_nest_start(msg, DPLLA_SOURCE);
+		if (!src_attr) {
+			ret = -EMSGSIZE;
+			break;
+		}
+		type = dpll->ops->get_source_type(dpll, i);
+		if (nla_put_u32(msg, DPLLA_SOURCE_ID, i) ||
+		    nla_put_u32(msg, DPLLA_SOURCE_TYPE, type)) {
+			nla_nest_cancel(msg, src_attr);
+			ret = -EMSGSIZE;
+			break;
+		}
+		if (dpll->ops->get_source_supported) {
+			for (type = 0; type <= DPLL_TYPE_MAX; type++) {
+				ret = dpll->ops->get_source_supported(dpll, i, type);
+				if (ret && nla_put_u32(msg, DPLLA_SOURCE_SUPPORTED, type)) {
+					ret = -EMSGSIZE;
+					break;
+				}
+			}
+			ret = 0;
+		}
+		nla_nest_end(msg, src_attr);
+	}
+
+	return ret;
+}
+
+static int __dpll_cmd_dump_outputs(struct dpll_device *dpll,
+					   struct sk_buff *msg)
+{
+	struct nlattr *out_attr;
+	int i, ret = 0, type;
+
+	for (i = 0; i < dpll->outputs_count; i++) {
+		out_attr = nla_nest_start(msg, DPLLA_OUTPUT);
+		if (!out_attr) {
+			ret = -EMSGSIZE;
+			break;
+		}
+		type = dpll->ops->get_output_type(dpll, i);
+		if (nla_put_u32(msg, DPLLA_OUTPUT_ID, i) ||
+		    nla_put_u32(msg, DPLLA_OUTPUT_TYPE, type)) {
+			nla_nest_cancel(msg, out_attr);
+			ret = -EMSGSIZE;
+			break;
+		}
+		if (dpll->ops->get_output_supported) {
+			for (type = 0; type <= DPLL_TYPE_MAX; type++) {
+				ret = dpll->ops->get_output_supported(dpll, i, type);
+				if (ret && nla_put_u32(msg, DPLLA_OUTPUT_SUPPORTED, type)) {
+					ret = -EMSGSIZE;
+					break;
+				}
+			}
+			ret = 0;
+		}
+		nla_nest_end(msg, out_attr);
+	}
+
+	return ret;
+}
+
+static int __dpll_cmd_dump_status(struct dpll_device *dpll,
+					   struct sk_buff *msg)
+{
+	int ret;
+
+	if (dpll->ops->get_status) {
+		ret = dpll->ops->get_status(dpll);
+		if (nla_put_u32(msg, DPLLA_STATUS, ret))
+			return -EMSGSIZE;
+	}
+
+	if (dpll->ops->get_temp) {
+		ret = dpll->ops->get_temp(dpll);
+		if (nla_put_u32(msg, DPLLA_TEMP, ret))
+			return -EMSGSIZE;
+	}
+
+	if (dpll->ops->get_lock_status) {
+		ret = dpll->ops->get_lock_status(dpll);
+		if (nla_put_u32(msg, DPLLA_LOCK_STATUS, ret))
+			return -EMSGSIZE;
+	}
+
+	return 0;
+}
+
+static int
+dpll_device_dump_one(struct dpll_device *dpll, struct sk_buff *msg,
+		     u32 portid, u32 seq, int flags)
+{
+	struct nlattr *hdr;
+	int ret;
+
+	hdr = genlmsg_put(msg, portid, seq, &dpll_gnl_family, 0,
+			  DPLL_CMD_DEVICE_GET);
+	if (!hdr)
+		return -EMSGSIZE;
+
+	mutex_lock(&dpll->lock);
+	ret = __dpll_cmd_device_dump_one(dpll, msg);
+	if (ret)
+		goto out_unlock;
+
+	if (flags & DPLL_FLAG_SOURCES && dpll->ops->get_source_type) {
+		ret = __dpll_cmd_dump_sources(dpll, msg);
+		if (ret)
+			goto out_unlock;
+	}
+
+	if (flags & DPLL_FLAG_OUTPUTS && dpll->ops->get_output_type) {
+		ret = __dpll_cmd_dump_outputs(dpll, msg);
+		if (ret)
+			goto out_unlock;
+	}
+
+	if (flags & DPLL_FLAG_STATUS) {
+		ret = __dpll_cmd_dump_status(dpll, msg);
+		if (ret)
+			goto out_unlock;
+	}
+	mutex_unlock(&dpll->lock);
+	genlmsg_end(msg, hdr);
+
+	return 0;
+
+out_unlock:
+	mutex_unlock(&dpll->lock);
+	genlmsg_cancel(msg, hdr);
+
+	return ret;
+}
+
+static int dpll_genl_cmd_set_source(struct sk_buff *skb, struct genl_info *info)
+{
+	struct dpll_device *dpll = info->user_ptr[0];
+	struct nlattr **attrs = info->attrs;
+	int ret = 0, src_id, type;
+
+	if (!attrs[DPLLA_SOURCE_ID] ||
+	    !attrs[DPLLA_SOURCE_TYPE])
+		return -EINVAL;
+
+	if (!dpll->ops->set_source_type)
+		return -EOPNOTSUPP;
+
+	src_id = nla_get_u32(attrs[DPLLA_SOURCE_ID]);
+	type = nla_get_u32(attrs[DPLLA_SOURCE_TYPE]);
+
+	mutex_lock(&dpll->lock);
+	ret = dpll->ops->set_source_type(dpll, src_id, type);
+	mutex_unlock(&dpll->lock);
+
+	return ret;
+}
+
+static int dpll_genl_cmd_set_output(struct sk_buff *skb, struct genl_info *info)
+{
+	struct dpll_device *dpll = info->user_ptr[0];
+	struct nlattr **attrs = info->attrs;
+	int ret = 0, out_id, type;
+
+	if (!attrs[DPLLA_OUTPUT_ID] ||
+	    !attrs[DPLLA_OUTPUT_TYPE])
+		return -EINVAL;
+
+	if (!dpll->ops->set_output_type)
+		return -EOPNOTSUPP;
+
+	out_id = nla_get_u32(attrs[DPLLA_OUTPUT_ID]);
+	type = nla_get_u32(attrs[DPLLA_OUTPUT_TYPE]);
+
+	mutex_lock(&dpll->lock);
+	ret = dpll->ops->set_output_type(dpll, out_id, type);
+	mutex_unlock(&dpll->lock);
+
+	return ret;
+}
+
+static int dpll_device_loop_cb(struct dpll_device *dpll, void *data)
+{
+	struct dpll_dump_ctx *ctx;
+	struct param *p = (struct param *)data;
+
+	ctx = dpll_dump_context(p->cb);
+
+	ctx->pos_idx = dpll->id;
+
+	return dpll_device_dump_one(dpll, p->msg, 0, 0, ctx->flags);
+}
+
+static int
+dpll_cmd_device_dump(struct sk_buff *skb, struct netlink_callback *cb)
+{
+	struct dpll_dump_ctx *ctx = dpll_dump_context(cb);
+	struct param p = { .cb = cb, .msg = skb };
+
+	return for_each_dpll_device(ctx->pos_idx, dpll_device_loop_cb, &p);
+}
+
+static int
+dpll_genl_cmd_device_get_id(struct sk_buff *skb, struct genl_info *info)
+{
+	struct dpll_device *dpll = info->user_ptr[0];
+	struct nlattr **attrs = info->attrs;
+	struct sk_buff *msg;
+	int flags = 0;
+	int ret;
+
+	if (attrs[DPLLA_FLAGS])
+		flags = nla_get_u32(attrs[DPLLA_FLAGS]);
+
+	msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+	if (!msg)
+		return -ENOMEM;
+
+	ret = dpll_device_dump_one(dpll, msg, info->snd_portid, info->snd_seq,
+				   flags);
+	if (ret)
+		goto out_free_msg;
+
+	return genlmsg_reply(msg, info);
+
+out_free_msg:
+	nlmsg_free(msg);
+	return ret;
+
+}
+
+static int dpll_genl_cmd_start(struct netlink_callback *cb)
+{
+	const struct genl_dumpit_info *info = genl_dumpit_info(cb);
+	struct dpll_dump_ctx *ctx = dpll_dump_context(cb);
+
+	ctx->dev = NULL;
+	if (info->attrs[DPLLA_FLAGS])
+		ctx->flags = nla_get_u32(info->attrs[DPLLA_FLAGS]);
+	else
+		ctx->flags = 0;
+	ctx->pos_idx = 0;
+	ctx->pos_src_idx = 0;
+	ctx->pos_out_idx = 0;
+	return 0;
+}
+
+static int dpll_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
+						 struct genl_info *info)
+{
+	struct dpll_device *dpll_id = NULL, *dpll_name = NULL;
+
+	if (!info->attrs[DPLLA_DEVICE_ID] &&
+	    !info->attrs[DPLLA_DEVICE_NAME])
+		return -EINVAL;
+
+	if (info->attrs[DPLLA_DEVICE_ID]) {
+		u32 id = nla_get_u32(info->attrs[DPLLA_DEVICE_ID]);
+
+		dpll_id = dpll_device_get_by_id(id);
+		if (!dpll_id)
+			return -ENODEV;
+		info->user_ptr[0] = dpll_id;
+	}
+	if (info->attrs[DPLLA_DEVICE_NAME]) {
+		const char *name = nla_data(info->attrs[DPLLA_DEVICE_NAME]);
+
+		dpll_name = dpll_device_get_by_name(name);
+		if (!dpll_name)
+			return -ENODEV;
+
+		if (dpll_id && dpll_name != dpll_id)
+			return -EINVAL;
+		info->user_ptr[0] = dpll_name;
+	}
+
+	return 0;
+}
+
+static const struct genl_ops dpll_genl_ops[] = {
+	{
+		.cmd	= DPLL_CMD_DEVICE_GET,
+		.flags  = GENL_UNS_ADMIN_PERM,
+		.start	= dpll_genl_cmd_start,
+		.dumpit	= dpll_cmd_device_dump,
+		.doit	= dpll_genl_cmd_device_get_id,
+		.policy	= dpll_genl_get_policy,
+		.maxattr = ARRAY_SIZE(dpll_genl_get_policy) - 1,
+	},
+	{
+		.cmd	= DPLL_CMD_SET_SOURCE_TYPE,
+		.flags	= GENL_UNS_ADMIN_PERM,
+		.doit	= dpll_genl_cmd_set_source,
+		.policy	= dpll_genl_set_source_policy,
+		.maxattr = ARRAY_SIZE(dpll_genl_set_source_policy) - 1,
+	},
+	{
+		.cmd	= DPLL_CMD_SET_OUTPUT_TYPE,
+		.flags	= GENL_UNS_ADMIN_PERM,
+		.doit	= dpll_genl_cmd_set_output,
+		.policy	= dpll_genl_set_output_policy,
+		.maxattr = ARRAY_SIZE(dpll_genl_set_output_policy) - 1,
+	},
+};
+
+static struct genl_family dpll_gnl_family __ro_after_init = {
+	.hdrsize	= 0,
+	.name		= DPLL_FAMILY_NAME,
+	.version	= DPLL_VERSION,
+	.ops		= dpll_genl_ops,
+	.n_ops		= ARRAY_SIZE(dpll_genl_ops),
+	.mcgrps		= dpll_genl_mcgrps,
+	.n_mcgrps	= ARRAY_SIZE(dpll_genl_mcgrps),
+	.pre_doit	= dpll_pre_doit,
+};
+
+int __init dpll_netlink_init(void)
+{
+	return genl_register_family(&dpll_gnl_family);
+}
+
+void dpll_netlink_finish(void)
+{
+	genl_unregister_family(&dpll_gnl_family);
+}
+
+void __exit dpll_netlink_fini(void)
+{
+	dpll_netlink_finish();
+}
diff --git a/drivers/dpll/dpll_netlink.h b/drivers/dpll/dpll_netlink.h
new file mode 100644
index 000000000000..e2d100f59dd6
--- /dev/null
+++ b/drivers/dpll/dpll_netlink.h
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *  Copyright (c) 2021 Meta Platforms, Inc. and affiliates
+ */
+
+int __init dpll_netlink_init(void);
+void dpll_netlink_finish(void);
diff --git a/include/linux/dpll.h b/include/linux/dpll.h
new file mode 100644
index 000000000000..9d49b19d03d9
--- /dev/null
+++ b/include/linux/dpll.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *  Copyright (c) 2021 Meta Platforms, Inc. and affiliates
+ */
+
+#ifndef __DPLL_H__
+#define __DPLL_H__
+
+struct dpll_device;
+
+struct dpll_device_ops {
+	int (*get_status)(struct dpll_device *dpll);
+	int (*get_temp)(struct dpll_device *dpll);
+	int (*get_lock_status)(struct dpll_device *dpll);
+	int (*get_source_type)(struct dpll_device *dpll, int id);
+	int (*get_source_supported)(struct dpll_device *dpll, int id, int type);
+	int (*get_output_type)(struct dpll_device *dpll, int id);
+	int (*get_output_supported)(struct dpll_device *dpll, int id, int type);
+	int (*set_source_type)(struct dpll_device *dpll, int id, int val);
+	int (*set_output_type)(struct dpll_device *dpll, int id, int val);
+};
+
+struct dpll_device *dpll_device_alloc(struct dpll_device_ops *ops, const char *name,
+				      int sources_count, int outputs_count, void *priv);
+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);
+#endif
diff --git a/include/uapi/linux/dpll.h b/include/uapi/linux/dpll.h
new file mode 100644
index 000000000000..fcbea5a5e4d6
--- /dev/null
+++ b/include/uapi/linux/dpll.h
@@ -0,0 +1,101 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef _UAPI_LINUX_DPLL_H
+#define _UAPI_LINUX_DPLL_H
+
+#define DPLL_NAME_LENGTH	20
+
+/* Adding event notification support elements */
+#define DPLL_FAMILY_NAME		"dpll"
+#define DPLL_VERSION			0x01
+#define DPLL_CONFIG_DEVICE_GROUP_NAME  "config"
+#define DPLL_CONFIG_SOURCE_GROUP_NAME  "source"
+#define DPLL_CONFIG_OUTPUT_GROUP_NAME  "output"
+#define DPLL_MONITOR_GROUP_NAME        "monitor"
+
+#define DPLL_FLAG_SOURCES	1
+#define DPLL_FLAG_OUTPUTS	2
+#define DPLL_FLAG_STATUS	4
+
+/* Attributes of dpll_genl_family */
+enum dpll_genl_attr {
+	DPLLA_UNSPEC,
+	DPLLA_DEVICE_ID,
+	DPLLA_DEVICE_NAME,
+	DPLLA_SOURCE,
+	DPLLA_SOURCE_ID,
+	DPLLA_SOURCE_TYPE,
+	DPLLA_SOURCE_SUPPORTED,
+	DPLLA_OUTPUT,
+	DPLLA_OUTPUT_ID,
+	DPLLA_OUTPUT_TYPE,
+	DPLLA_OUTPUT_SUPPORTED,
+	DPLLA_STATUS,
+	DPLLA_TEMP,
+	DPLLA_LOCK_STATUS,
+	DPLLA_FLAGS,
+
+	__DPLLA_MAX,
+};
+#define DPLLA_MAX (__DPLLA_MAX - 1)
+
+/* DPLL status provides information of device status */
+enum dpll_genl_status {
+	DPLL_STATUS_NONE,
+	DPLL_STATUS_CALIBRATING,
+	DPLL_STATUS_LOCKED,
+
+	__DPLL_STATUS_MAX,
+};
+#define DPLL_STATUS_MAX (__DPLL_STATUS_MAX - 1)
+
+/* DPLL signal types used as source or as output */
+enum dpll_genl_signal_type {
+	DPLL_TYPE_EXT_1PPS,
+	DPLL_TYPE_EXT_10MHZ,
+	DPLL_TYPE_SYNCE_ETH_PORT,
+	DPLL_TYPE_INT_OSCILLATOR,
+	DPLL_TYPE_GNSS,
+
+	__DPLL_TYPE_MAX,
+};
+#define DPLL_TYPE_MAX (__DPLL_TYPE_MAX - 1)
+
+/* DPLL lock status provides information of source used to lock the device */
+enum dpll_genl_lock_status {
+	DPLL_LOCK_STATUS_UNLOCKED,
+	DPLL_LOCK_STATUS_EXT_1PPS,
+	DPLL_LOCK_STATUS_EXT_10MHZ,
+	DPLL_LOCK_STATUS_SYNCE,
+	DPLL_LOCK_STATUS_INT_OSCILLATOR,
+	DPLL_LOCK_STATUS_GNSS,
+
+	__DPLL_LOCK_STATUS_MAX,
+};
+#define DPLL_LOCK_STATUS_MAX (__DPLL_LOCK_STATUS_MAX - 1)
+
+/* Events of dpll_genl_family */
+enum dpll_genl_event {
+	DPLL_EVENT_UNSPEC,
+	DPLL_EVENT_DEVICE_CREATE,		/* DPLL device creation */
+	DPLL_EVENT_DEVICE_DELETE,		/* DPLL device deletion */
+	DPLL_EVENT_STATUS_LOCKED,		/* DPLL device locked to source */
+	DPLL_EVENT_STATUS_UNLOCKED,	/* DPLL device freerun */
+	DPLL_EVENT_SOURCE_CHANGE,		/* DPLL device source changed */
+	DPLL_EVENT_OUTPUT_CHANGE,		/* DPLL device output changed */
+
+	__DPLL_EVENT_MAX,
+};
+#define DPLL_EVENT_MAX (__DPLL_EVENT_MAX - 1)
+
+/* Commands supported by the dpll_genl_family */
+enum dpll_genl_cmd {
+	DPLL_CMD_UNSPEC,
+	DPLL_CMD_DEVICE_GET,	/* List of DPLL devices id */
+	DPLL_CMD_SET_SOURCE_TYPE,	/* Set the DPLL device source type */
+	DPLL_CMD_SET_OUTPUT_TYPE,	/* Set the DPLL device output type */
+
+	__DPLL_CMD_MAX,
+};
+#define DPLL_CMD_MAX (__DPLL_CMD_MAX - 1)
+
+#endif /* _UAPI_LINUX_DPLL_H */
-- 
2.27.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [RFC PATCH v3 2/6] dpll: add netlink events
  2022-10-10  1:17 ` Vadim Fedorenko
@ 2022-10-10  1:18   ` Vadim Fedorenko
  -1 siblings, 0 replies; 67+ messages in thread
From: Vadim Fedorenko @ 2022-10-10  1:18 UTC (permalink / raw)
  To: Jakub Kicinski, Jiri Pirko, Arkadiusz Kubalewski
  Cc: netdev, linux-arm-kernel, linux-clk, Vadim Fedorenko

From: Vadim Fedorenko <vadfed@fb.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@fb.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


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [RFC PATCH v3 2/6] dpll: add netlink events
@ 2022-10-10  1:18   ` Vadim Fedorenko
  0 siblings, 0 replies; 67+ messages in thread
From: Vadim Fedorenko @ 2022-10-10  1:18 UTC (permalink / raw)
  To: Jakub Kicinski, Jiri Pirko, Arkadiusz Kubalewski
  Cc: netdev, linux-arm-kernel, linux-clk, Vadim Fedorenko

From: Vadim Fedorenko <vadfed@fb.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@fb.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


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [RFC PATCH v3 3/6] dpll: add support for source selection modes
  2022-10-10  1:17 ` Vadim Fedorenko
@ 2022-10-10  1:18   ` Vadim Fedorenko
  -1 siblings, 0 replies; 67+ messages in thread
From: Vadim Fedorenko @ 2022-10-10  1:18 UTC (permalink / raw)
  To: Jakub Kicinski, Jiri Pirko, Arkadiusz Kubalewski
  Cc: netdev, linux-arm-kernel, linux-clk, Vadim Fedorenko

From: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>

Allow to configure dpll device for different source selection modes.
Allow to configure priority of a sources for autmoatic selection mode.

Signed-off-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
---
 drivers/dpll/dpll_netlink.c | 170 ++++++++++++++++++++++++++++++++++--
 drivers/dpll/dpll_netlink.h |   2 +
 include/linux/dpll.h        |   7 ++
 include/uapi/linux/dpll.h   |  22 ++++-
 4 files changed, 192 insertions(+), 9 deletions(-)

diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c
index 6dc92b5b712e..a5779871537a 100644
--- a/drivers/dpll/dpll_netlink.c
+++ b/drivers/dpll/dpll_netlink.c
@@ -23,6 +23,7 @@ static const struct nla_policy dpll_genl_get_policy[] = {
 	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
 	[DPLLA_DEVICE_NAME]	= { .type = NLA_STRING,
 				    .len = DPLL_NAME_LENGTH },
+	[DPLLA_DEVICE_SRC_SELECT_MODE] = { .type = NLA_U32 },
 	[DPLLA_FLAGS]		= { .type = NLA_U32 },
 };
 
@@ -38,13 +39,26 @@ static const struct nla_policy dpll_genl_set_output_policy[] = {
 	[DPLLA_OUTPUT_TYPE]	= { .type = NLA_U32 },
 };
 
+static const struct nla_policy dpll_genl_set_src_select_mode_policy[] = {
+	[DPLLA_DEVICE_ID]		  = { .type = NLA_U32 },
+	[DPLLA_DEVICE_SRC_SELECT_MODE] = { .type = NLA_U32 },
+};
+
+static const struct nla_policy dpll_genl_set_source_prio_policy[] = {
+	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
+	[DPLLA_SOURCE_ID]	= { .type = NLA_U32 },
+	[DPLLA_SOURCE_PRIO]	= { .type = NLA_U32 },
+};
+
 struct param {
 	struct netlink_callback *cb;
 	struct dpll_device *dpll;
 	struct sk_buff *msg;
 	int dpll_id;
+	int dpll_src_select_mode;
 	int dpll_source_id;
 	int dpll_source_type;
+	int dpll_source_prio;
 	int dpll_output_id;
 	int dpll_output_type;
 	int dpll_status;
@@ -84,8 +98,8 @@ static int __dpll_cmd_device_dump_one(struct dpll_device *dpll,
 static int __dpll_cmd_dump_sources(struct dpll_device *dpll,
 					   struct sk_buff *msg)
 {
+	int i, ret = 0, type, prio;
 	struct nlattr *src_attr;
-	int i, ret = 0, type;
 
 	for (i = 0; i < dpll->sources_count; i++) {
 		src_attr = nla_nest_start(msg, DPLLA_SOURCE);
@@ -110,6 +124,14 @@ static int __dpll_cmd_dump_sources(struct dpll_device *dpll,
 			}
 			ret = 0;
 		}
+		if (dpll->ops->get_source_prio) {
+			prio = dpll->ops->get_source_prio(dpll, i);
+			if (nla_put_u32(msg, DPLLA_SOURCE_PRIO, prio)) {
+				nla_nest_cancel(msg, src_attr);
+				ret = -EMSGSIZE;
+				break;
+			}
+		}
 		nla_nest_end(msg, src_attr);
 	}
 
@@ -154,26 +176,51 @@ static int __dpll_cmd_dump_outputs(struct dpll_device *dpll,
 static int __dpll_cmd_dump_status(struct dpll_device *dpll,
 					   struct sk_buff *msg)
 {
-	int ret;
+	struct dpll_device_ops *ops = dpll->ops;
+	int ret, type, attr;
 
-	if (dpll->ops->get_status) {
-		ret = dpll->ops->get_status(dpll);
+	if (ops->get_status) {
+		ret = ops->get_status(dpll);
 		if (nla_put_u32(msg, DPLLA_STATUS, ret))
 			return -EMSGSIZE;
 	}
 
-	if (dpll->ops->get_temp) {
-		ret = dpll->ops->get_temp(dpll);
+	if (ops->get_temp) {
+		ret = ops->get_temp(dpll);
 		if (nla_put_u32(msg, DPLLA_TEMP, ret))
 			return -EMSGSIZE;
 	}
 
-	if (dpll->ops->get_lock_status) {
-		ret = dpll->ops->get_lock_status(dpll);
+	if (ops->get_lock_status) {
+		ret = ops->get_lock_status(dpll);
 		if (nla_put_u32(msg, DPLLA_LOCK_STATUS, ret))
 			return -EMSGSIZE;
 	}
 
+	if (ops->get_source_select_mode) {
+		ret = ops->get_source_select_mode(dpll);
+		if (nla_put_u32(msg, DPLLA_DEVICE_SRC_SELECT_MODE, ret))
+			return -EMSGSIZE;
+	} else {
+		if (nla_put_u32(msg, DPLLA_DEVICE_SRC_SELECT_MODE,
+				DPLL_SRC_SELECT_FORCED))
+			return -EMSGSIZE;
+	}
+
+	if (ops->get_source_select_mode_supported) {
+		attr = DPLLA_DEVICE_SRC_SELECT_MODE_SUPPORTED;
+		for (type = 0; type <= DPLL_SRC_SELECT_MAX; type++) {
+			ret = ops->get_source_select_mode_supported(dpll,
+								    type);
+			if (ret && nla_put_u32(msg, attr, type))
+				return -EMSGSIZE;
+		}
+	} else {
+		if (nla_put_u32(msg, DPLLA_DEVICE_SRC_SELECT_MODE_SUPPORTED,
+				DPLL_SRC_SELECT_FORCED))
+			return -EMSGSIZE;
+	}
+
 	return 0;
 }
 
@@ -275,6 +322,56 @@ static int dpll_genl_cmd_set_output(struct sk_buff *skb, struct genl_info *info)
 	return ret;
 }
 
+static int dpll_genl_cmd_set_source_prio(struct sk_buff *skb, struct genl_info *info)
+{
+	struct dpll_device *dpll = info->user_ptr[0];
+	struct nlattr **attrs = info->attrs;
+	int ret = 0, src_id, prio;
+
+	if (!attrs[DPLLA_SOURCE_ID] ||
+	    !attrs[DPLLA_SOURCE_PRIO])
+		return -EINVAL;
+
+	if (!dpll->ops->set_source_prio)
+		return -EOPNOTSUPP;
+
+	src_id = nla_get_u32(attrs[DPLLA_SOURCE_ID]);
+	prio = nla_get_u32(attrs[DPLLA_SOURCE_PRIO]);
+
+	mutex_lock(&dpll->lock);
+	ret = dpll->ops->set_source_prio(dpll, src_id, prio);
+	mutex_unlock(&dpll->lock);
+
+	if (!ret)
+		dpll_notify_source_prio_change(dpll->id, src_id, prio);
+
+	return ret;
+}
+
+static int dpll_genl_cmd_set_select_mode(struct sk_buff *skb, struct genl_info *info)
+{
+	struct dpll_device *dpll = info->user_ptr[0];
+	struct nlattr **attrs = info->attrs;
+	int ret = 0, mode;
+
+	if (!attrs[DPLLA_DEVICE_SRC_SELECT_MODE])
+		return -EINVAL;
+
+	if (!dpll->ops->set_source_select_mode)
+		return -EOPNOTSUPP;
+
+	mode = nla_get_u32(attrs[DPLLA_DEVICE_SRC_SELECT_MODE]);
+
+	mutex_lock(&dpll->lock);
+	ret = dpll->ops->set_source_select_mode(dpll, mode);
+	mutex_unlock(&dpll->lock);
+
+	if (!ret)
+		dpll_notify_source_select_mode_change(dpll->id, mode);
+
+	return ret;
+}
+
 static int dpll_device_loop_cb(struct dpll_device *dpll, void *data)
 {
 	struct dpll_dump_ctx *ctx;
@@ -397,6 +494,20 @@ static const struct genl_ops dpll_genl_ops[] = {
 		.policy	= dpll_genl_set_output_policy,
 		.maxattr = ARRAY_SIZE(dpll_genl_set_output_policy) - 1,
 	},
+	{
+		.cmd	= DPLL_CMD_SET_SRC_SELECT_MODE,
+		.flags	= GENL_UNS_ADMIN_PERM,
+		.doit	= dpll_genl_cmd_set_select_mode,
+		.policy	= dpll_genl_set_src_select_mode_policy,
+		.maxattr = ARRAY_SIZE(dpll_genl_set_src_select_mode_policy) - 1,
+	},
+	{
+		.cmd	= DPLL_CMD_SET_SOURCE_PRIO,
+		.flags	= GENL_UNS_ADMIN_PERM,
+		.doit	= dpll_genl_cmd_set_source_prio,
+		.policy	= dpll_genl_set_source_prio_policy,
+		.maxattr = ARRAY_SIZE(dpll_genl_set_source_prio_policy) - 1,
+	},
 };
 
 static struct genl_family dpll_gnl_family __ro_after_init = {
@@ -456,6 +567,26 @@ static int dpll_event_output_change(struct param *p)
 	return 0;
 }
 
+static int dpll_event_source_prio(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_PRIO, p->dpll_source_prio))
+		return -EMSGSIZE;
+
+	return 0;
+}
+
+static int dpll_event_select_mode(struct param *p)
+{
+	if (nla_put_u32(p->msg, DPLLA_DEVICE_ID, p->dpll_id) ||
+	    nla_put_u32(p->msg, DPLLA_DEVICE_SRC_SELECT_MODE,
+		    p->dpll_src_select_mode))
+		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,
@@ -463,7 +594,10 @@ static const cb_t event_cb[] = {
 	[DPLL_EVENT_STATUS_UNLOCKED]	= dpll_event_status,
 	[DPLL_EVENT_SOURCE_CHANGE]	= dpll_event_source_change,
 	[DPLL_EVENT_OUTPUT_CHANGE]	= dpll_event_output_change,
+	[DPLL_EVENT_SOURCE_PRIO]        = dpll_event_source_prio,
+	[DPLL_EVENT_SELECT_MODE]        = dpll_event_select_mode,
 };
+
 /*
  * Generic netlink DPLL event encoding
  */
@@ -552,6 +686,26 @@ int dpll_notify_output_change(int dpll_id, int output_id, int output_type)
 }
 EXPORT_SYMBOL_GPL(dpll_notify_output_change);
 
+int dpll_notify_source_select_mode_change(int dpll_id, int new_mode)
+{
+	struct param p =  { .dpll_id = dpll_id,
+			    .dpll_src_select_mode = new_mode,
+			    .dpll_event_group = 0 };
+
+	return dpll_send_event(DPLL_EVENT_SELECT_MODE, &p);
+}
+EXPORT_SYMBOL_GPL(dpll_notify_source_select_mode_change);
+
+int dpll_notify_source_prio_change(int dpll_id, int source_id, int prio)
+{
+	struct param p =  { .dpll_id = dpll_id, .dpll_source_id = source_id,
+			    .dpll_source_prio = prio,
+			    .dpll_event_group = 1 };
+
+	return dpll_send_event(DPLL_EVENT_SOURCE_PRIO, &p);
+}
+EXPORT_SYMBOL_GPL(dpll_notify_source_prio_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 5c1d1072e818..a4962fa0c8c2 100644
--- a/drivers/dpll/dpll_netlink.h
+++ b/drivers/dpll/dpll_netlink.h
@@ -5,6 +5,8 @@
 
 int dpll_notify_device_create(int dpll_id, const char *name);
 int dpll_notify_device_delete(int dpll_id);
+int dpll_notify_source_prio(int dpll_id, int source_id, int prio);
+int dpll_notify_select_mode(int dpll_id, int mode);
 
 int __init dpll_netlink_init(void);
 void dpll_netlink_finish(void);
diff --git a/include/linux/dpll.h b/include/linux/dpll.h
index 32558965cd41..3fe957a06b90 100644
--- a/include/linux/dpll.h
+++ b/include/linux/dpll.h
@@ -12,12 +12,17 @@ struct dpll_device_ops {
 	int (*get_status)(struct dpll_device *dpll);
 	int (*get_temp)(struct dpll_device *dpll);
 	int (*get_lock_status)(struct dpll_device *dpll);
+	int (*get_source_select_mode)(struct dpll_device *dpll);
+	int (*get_source_select_mode_supported)(struct dpll_device *dpll, int type);
 	int (*get_source_type)(struct dpll_device *dpll, int id);
 	int (*get_source_supported)(struct dpll_device *dpll, int id, int type);
+	int (*get_source_prio)(struct dpll_device *dpll, int id);
 	int (*get_output_type)(struct dpll_device *dpll, int id);
 	int (*get_output_supported)(struct dpll_device *dpll, int id, int type);
 	int (*set_source_type)(struct dpll_device *dpll, int id, int val);
 	int (*set_output_type)(struct dpll_device *dpll, int id, int val);
+	int (*set_source_select_mode)(struct dpll_device *dpll, int mode);
+	int (*set_source_prio)(struct dpll_device *dpll, int id, int prio);
 };
 
 struct dpll_device *dpll_device_alloc(struct dpll_device_ops *ops, const char *name,
@@ -31,4 +36,6 @@ 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);
+int dpll_notify_source_select_mode_change(int dpll_id, int source_select_mode);
+int dpll_notify_source_prio_change(int dpll_id, int source_id, int prio);
 #endif
diff --git a/include/uapi/linux/dpll.h b/include/uapi/linux/dpll.h
index fcbea5a5e4d6..f6b674e5cf01 100644
--- a/include/uapi/linux/dpll.h
+++ b/include/uapi/linux/dpll.h
@@ -21,10 +21,13 @@ enum dpll_genl_attr {
 	DPLLA_UNSPEC,
 	DPLLA_DEVICE_ID,
 	DPLLA_DEVICE_NAME,
+	DPLLA_DEVICE_SRC_SELECT_MODE,
+	DPLLA_DEVICE_SRC_SELECT_MODE_SUPPORTED,
 	DPLLA_SOURCE,
 	DPLLA_SOURCE_ID,
 	DPLLA_SOURCE_TYPE,
 	DPLLA_SOURCE_SUPPORTED,
+	DPLLA_SOURCE_PRIO,
 	DPLLA_OUTPUT,
 	DPLLA_OUTPUT_ID,
 	DPLLA_OUTPUT_TYPE,
@@ -82,6 +85,8 @@ enum dpll_genl_event {
 	DPLL_EVENT_STATUS_UNLOCKED,	/* DPLL device freerun */
 	DPLL_EVENT_SOURCE_CHANGE,		/* DPLL device source changed */
 	DPLL_EVENT_OUTPUT_CHANGE,		/* DPLL device output changed */
+	DPLL_EVENT_SOURCE_PRIO,
+	DPLL_EVENT_SELECT_MODE,
 
 	__DPLL_EVENT_MAX,
 };
@@ -90,12 +95,27 @@ enum dpll_genl_event {
 /* Commands supported by the dpll_genl_family */
 enum dpll_genl_cmd {
 	DPLL_CMD_UNSPEC,
-	DPLL_CMD_DEVICE_GET,	/* List of DPLL devices id */
+	DPLL_CMD_DEVICE_GET,		/* List of DPLL devices id */
 	DPLL_CMD_SET_SOURCE_TYPE,	/* Set the DPLL device source type */
 	DPLL_CMD_SET_OUTPUT_TYPE,	/* Set the DPLL device output type */
+	DPLL_CMD_SET_SRC_SELECT_MODE,/* Set mode for selection of a source */
+	DPLL_CMD_SET_SOURCE_PRIO,	/* Set priority of a source */
 
 	__DPLL_CMD_MAX,
 };
 #define DPLL_CMD_MAX (__DPLL_CMD_MAX - 1)
 
+/* Source select modes of dpll */
+enum dpll_genl_source_select_mode {
+	DPLL_SRC_SELECT_UNSPEC,
+	DPLL_SRC_SELECT_FORCED,   /* Source forced by DPLL_CMD_SET_SOURCE_TYPE */
+	DPLL_SRC_SELECT_AUTOMATIC,/* highest prio, valid source, auto selected by dpll */
+	DPLL_SRC_SELECT_HOLDOVER, /* forced holdover */
+	DPLL_SRC_SELECT_FREERUN,  /* dpll driven on system clk, no holdover available */
+	DPLL_SRC_SELECT_NCO,	     /* Set the DPLL device output type */
+
+	__DPLL_SRC_SELECT_MAX,
+};
+#define DPLL_SRC_SELECT_MAX (__DPLL_SRC_SELECT_MAX - 1)
+
 #endif /* _UAPI_LINUX_DPLL_H */
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [RFC PATCH v3 3/6] dpll: add support for source selection modes
@ 2022-10-10  1:18   ` Vadim Fedorenko
  0 siblings, 0 replies; 67+ messages in thread
From: Vadim Fedorenko @ 2022-10-10  1:18 UTC (permalink / raw)
  To: Jakub Kicinski, Jiri Pirko, Arkadiusz Kubalewski
  Cc: netdev, linux-arm-kernel, linux-clk, Vadim Fedorenko

From: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>

Allow to configure dpll device for different source selection modes.
Allow to configure priority of a sources for autmoatic selection mode.

Signed-off-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
---
 drivers/dpll/dpll_netlink.c | 170 ++++++++++++++++++++++++++++++++++--
 drivers/dpll/dpll_netlink.h |   2 +
 include/linux/dpll.h        |   7 ++
 include/uapi/linux/dpll.h   |  22 ++++-
 4 files changed, 192 insertions(+), 9 deletions(-)

diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c
index 6dc92b5b712e..a5779871537a 100644
--- a/drivers/dpll/dpll_netlink.c
+++ b/drivers/dpll/dpll_netlink.c
@@ -23,6 +23,7 @@ static const struct nla_policy dpll_genl_get_policy[] = {
 	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
 	[DPLLA_DEVICE_NAME]	= { .type = NLA_STRING,
 				    .len = DPLL_NAME_LENGTH },
+	[DPLLA_DEVICE_SRC_SELECT_MODE] = { .type = NLA_U32 },
 	[DPLLA_FLAGS]		= { .type = NLA_U32 },
 };
 
@@ -38,13 +39,26 @@ static const struct nla_policy dpll_genl_set_output_policy[] = {
 	[DPLLA_OUTPUT_TYPE]	= { .type = NLA_U32 },
 };
 
+static const struct nla_policy dpll_genl_set_src_select_mode_policy[] = {
+	[DPLLA_DEVICE_ID]		  = { .type = NLA_U32 },
+	[DPLLA_DEVICE_SRC_SELECT_MODE] = { .type = NLA_U32 },
+};
+
+static const struct nla_policy dpll_genl_set_source_prio_policy[] = {
+	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
+	[DPLLA_SOURCE_ID]	= { .type = NLA_U32 },
+	[DPLLA_SOURCE_PRIO]	= { .type = NLA_U32 },
+};
+
 struct param {
 	struct netlink_callback *cb;
 	struct dpll_device *dpll;
 	struct sk_buff *msg;
 	int dpll_id;
+	int dpll_src_select_mode;
 	int dpll_source_id;
 	int dpll_source_type;
+	int dpll_source_prio;
 	int dpll_output_id;
 	int dpll_output_type;
 	int dpll_status;
@@ -84,8 +98,8 @@ static int __dpll_cmd_device_dump_one(struct dpll_device *dpll,
 static int __dpll_cmd_dump_sources(struct dpll_device *dpll,
 					   struct sk_buff *msg)
 {
+	int i, ret = 0, type, prio;
 	struct nlattr *src_attr;
-	int i, ret = 0, type;
 
 	for (i = 0; i < dpll->sources_count; i++) {
 		src_attr = nla_nest_start(msg, DPLLA_SOURCE);
@@ -110,6 +124,14 @@ static int __dpll_cmd_dump_sources(struct dpll_device *dpll,
 			}
 			ret = 0;
 		}
+		if (dpll->ops->get_source_prio) {
+			prio = dpll->ops->get_source_prio(dpll, i);
+			if (nla_put_u32(msg, DPLLA_SOURCE_PRIO, prio)) {
+				nla_nest_cancel(msg, src_attr);
+				ret = -EMSGSIZE;
+				break;
+			}
+		}
 		nla_nest_end(msg, src_attr);
 	}
 
@@ -154,26 +176,51 @@ static int __dpll_cmd_dump_outputs(struct dpll_device *dpll,
 static int __dpll_cmd_dump_status(struct dpll_device *dpll,
 					   struct sk_buff *msg)
 {
-	int ret;
+	struct dpll_device_ops *ops = dpll->ops;
+	int ret, type, attr;
 
-	if (dpll->ops->get_status) {
-		ret = dpll->ops->get_status(dpll);
+	if (ops->get_status) {
+		ret = ops->get_status(dpll);
 		if (nla_put_u32(msg, DPLLA_STATUS, ret))
 			return -EMSGSIZE;
 	}
 
-	if (dpll->ops->get_temp) {
-		ret = dpll->ops->get_temp(dpll);
+	if (ops->get_temp) {
+		ret = ops->get_temp(dpll);
 		if (nla_put_u32(msg, DPLLA_TEMP, ret))
 			return -EMSGSIZE;
 	}
 
-	if (dpll->ops->get_lock_status) {
-		ret = dpll->ops->get_lock_status(dpll);
+	if (ops->get_lock_status) {
+		ret = ops->get_lock_status(dpll);
 		if (nla_put_u32(msg, DPLLA_LOCK_STATUS, ret))
 			return -EMSGSIZE;
 	}
 
+	if (ops->get_source_select_mode) {
+		ret = ops->get_source_select_mode(dpll);
+		if (nla_put_u32(msg, DPLLA_DEVICE_SRC_SELECT_MODE, ret))
+			return -EMSGSIZE;
+	} else {
+		if (nla_put_u32(msg, DPLLA_DEVICE_SRC_SELECT_MODE,
+				DPLL_SRC_SELECT_FORCED))
+			return -EMSGSIZE;
+	}
+
+	if (ops->get_source_select_mode_supported) {
+		attr = DPLLA_DEVICE_SRC_SELECT_MODE_SUPPORTED;
+		for (type = 0; type <= DPLL_SRC_SELECT_MAX; type++) {
+			ret = ops->get_source_select_mode_supported(dpll,
+								    type);
+			if (ret && nla_put_u32(msg, attr, type))
+				return -EMSGSIZE;
+		}
+	} else {
+		if (nla_put_u32(msg, DPLLA_DEVICE_SRC_SELECT_MODE_SUPPORTED,
+				DPLL_SRC_SELECT_FORCED))
+			return -EMSGSIZE;
+	}
+
 	return 0;
 }
 
@@ -275,6 +322,56 @@ static int dpll_genl_cmd_set_output(struct sk_buff *skb, struct genl_info *info)
 	return ret;
 }
 
+static int dpll_genl_cmd_set_source_prio(struct sk_buff *skb, struct genl_info *info)
+{
+	struct dpll_device *dpll = info->user_ptr[0];
+	struct nlattr **attrs = info->attrs;
+	int ret = 0, src_id, prio;
+
+	if (!attrs[DPLLA_SOURCE_ID] ||
+	    !attrs[DPLLA_SOURCE_PRIO])
+		return -EINVAL;
+
+	if (!dpll->ops->set_source_prio)
+		return -EOPNOTSUPP;
+
+	src_id = nla_get_u32(attrs[DPLLA_SOURCE_ID]);
+	prio = nla_get_u32(attrs[DPLLA_SOURCE_PRIO]);
+
+	mutex_lock(&dpll->lock);
+	ret = dpll->ops->set_source_prio(dpll, src_id, prio);
+	mutex_unlock(&dpll->lock);
+
+	if (!ret)
+		dpll_notify_source_prio_change(dpll->id, src_id, prio);
+
+	return ret;
+}
+
+static int dpll_genl_cmd_set_select_mode(struct sk_buff *skb, struct genl_info *info)
+{
+	struct dpll_device *dpll = info->user_ptr[0];
+	struct nlattr **attrs = info->attrs;
+	int ret = 0, mode;
+
+	if (!attrs[DPLLA_DEVICE_SRC_SELECT_MODE])
+		return -EINVAL;
+
+	if (!dpll->ops->set_source_select_mode)
+		return -EOPNOTSUPP;
+
+	mode = nla_get_u32(attrs[DPLLA_DEVICE_SRC_SELECT_MODE]);
+
+	mutex_lock(&dpll->lock);
+	ret = dpll->ops->set_source_select_mode(dpll, mode);
+	mutex_unlock(&dpll->lock);
+
+	if (!ret)
+		dpll_notify_source_select_mode_change(dpll->id, mode);
+
+	return ret;
+}
+
 static int dpll_device_loop_cb(struct dpll_device *dpll, void *data)
 {
 	struct dpll_dump_ctx *ctx;
@@ -397,6 +494,20 @@ static const struct genl_ops dpll_genl_ops[] = {
 		.policy	= dpll_genl_set_output_policy,
 		.maxattr = ARRAY_SIZE(dpll_genl_set_output_policy) - 1,
 	},
+	{
+		.cmd	= DPLL_CMD_SET_SRC_SELECT_MODE,
+		.flags	= GENL_UNS_ADMIN_PERM,
+		.doit	= dpll_genl_cmd_set_select_mode,
+		.policy	= dpll_genl_set_src_select_mode_policy,
+		.maxattr = ARRAY_SIZE(dpll_genl_set_src_select_mode_policy) - 1,
+	},
+	{
+		.cmd	= DPLL_CMD_SET_SOURCE_PRIO,
+		.flags	= GENL_UNS_ADMIN_PERM,
+		.doit	= dpll_genl_cmd_set_source_prio,
+		.policy	= dpll_genl_set_source_prio_policy,
+		.maxattr = ARRAY_SIZE(dpll_genl_set_source_prio_policy) - 1,
+	},
 };
 
 static struct genl_family dpll_gnl_family __ro_after_init = {
@@ -456,6 +567,26 @@ static int dpll_event_output_change(struct param *p)
 	return 0;
 }
 
+static int dpll_event_source_prio(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_PRIO, p->dpll_source_prio))
+		return -EMSGSIZE;
+
+	return 0;
+}
+
+static int dpll_event_select_mode(struct param *p)
+{
+	if (nla_put_u32(p->msg, DPLLA_DEVICE_ID, p->dpll_id) ||
+	    nla_put_u32(p->msg, DPLLA_DEVICE_SRC_SELECT_MODE,
+		    p->dpll_src_select_mode))
+		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,
@@ -463,7 +594,10 @@ static const cb_t event_cb[] = {
 	[DPLL_EVENT_STATUS_UNLOCKED]	= dpll_event_status,
 	[DPLL_EVENT_SOURCE_CHANGE]	= dpll_event_source_change,
 	[DPLL_EVENT_OUTPUT_CHANGE]	= dpll_event_output_change,
+	[DPLL_EVENT_SOURCE_PRIO]        = dpll_event_source_prio,
+	[DPLL_EVENT_SELECT_MODE]        = dpll_event_select_mode,
 };
+
 /*
  * Generic netlink DPLL event encoding
  */
@@ -552,6 +686,26 @@ int dpll_notify_output_change(int dpll_id, int output_id, int output_type)
 }
 EXPORT_SYMBOL_GPL(dpll_notify_output_change);
 
+int dpll_notify_source_select_mode_change(int dpll_id, int new_mode)
+{
+	struct param p =  { .dpll_id = dpll_id,
+			    .dpll_src_select_mode = new_mode,
+			    .dpll_event_group = 0 };
+
+	return dpll_send_event(DPLL_EVENT_SELECT_MODE, &p);
+}
+EXPORT_SYMBOL_GPL(dpll_notify_source_select_mode_change);
+
+int dpll_notify_source_prio_change(int dpll_id, int source_id, int prio)
+{
+	struct param p =  { .dpll_id = dpll_id, .dpll_source_id = source_id,
+			    .dpll_source_prio = prio,
+			    .dpll_event_group = 1 };
+
+	return dpll_send_event(DPLL_EVENT_SOURCE_PRIO, &p);
+}
+EXPORT_SYMBOL_GPL(dpll_notify_source_prio_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 5c1d1072e818..a4962fa0c8c2 100644
--- a/drivers/dpll/dpll_netlink.h
+++ b/drivers/dpll/dpll_netlink.h
@@ -5,6 +5,8 @@
 
 int dpll_notify_device_create(int dpll_id, const char *name);
 int dpll_notify_device_delete(int dpll_id);
+int dpll_notify_source_prio(int dpll_id, int source_id, int prio);
+int dpll_notify_select_mode(int dpll_id, int mode);
 
 int __init dpll_netlink_init(void);
 void dpll_netlink_finish(void);
diff --git a/include/linux/dpll.h b/include/linux/dpll.h
index 32558965cd41..3fe957a06b90 100644
--- a/include/linux/dpll.h
+++ b/include/linux/dpll.h
@@ -12,12 +12,17 @@ struct dpll_device_ops {
 	int (*get_status)(struct dpll_device *dpll);
 	int (*get_temp)(struct dpll_device *dpll);
 	int (*get_lock_status)(struct dpll_device *dpll);
+	int (*get_source_select_mode)(struct dpll_device *dpll);
+	int (*get_source_select_mode_supported)(struct dpll_device *dpll, int type);
 	int (*get_source_type)(struct dpll_device *dpll, int id);
 	int (*get_source_supported)(struct dpll_device *dpll, int id, int type);
+	int (*get_source_prio)(struct dpll_device *dpll, int id);
 	int (*get_output_type)(struct dpll_device *dpll, int id);
 	int (*get_output_supported)(struct dpll_device *dpll, int id, int type);
 	int (*set_source_type)(struct dpll_device *dpll, int id, int val);
 	int (*set_output_type)(struct dpll_device *dpll, int id, int val);
+	int (*set_source_select_mode)(struct dpll_device *dpll, int mode);
+	int (*set_source_prio)(struct dpll_device *dpll, int id, int prio);
 };
 
 struct dpll_device *dpll_device_alloc(struct dpll_device_ops *ops, const char *name,
@@ -31,4 +36,6 @@ 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);
+int dpll_notify_source_select_mode_change(int dpll_id, int source_select_mode);
+int dpll_notify_source_prio_change(int dpll_id, int source_id, int prio);
 #endif
diff --git a/include/uapi/linux/dpll.h b/include/uapi/linux/dpll.h
index fcbea5a5e4d6..f6b674e5cf01 100644
--- a/include/uapi/linux/dpll.h
+++ b/include/uapi/linux/dpll.h
@@ -21,10 +21,13 @@ enum dpll_genl_attr {
 	DPLLA_UNSPEC,
 	DPLLA_DEVICE_ID,
 	DPLLA_DEVICE_NAME,
+	DPLLA_DEVICE_SRC_SELECT_MODE,
+	DPLLA_DEVICE_SRC_SELECT_MODE_SUPPORTED,
 	DPLLA_SOURCE,
 	DPLLA_SOURCE_ID,
 	DPLLA_SOURCE_TYPE,
 	DPLLA_SOURCE_SUPPORTED,
+	DPLLA_SOURCE_PRIO,
 	DPLLA_OUTPUT,
 	DPLLA_OUTPUT_ID,
 	DPLLA_OUTPUT_TYPE,
@@ -82,6 +85,8 @@ enum dpll_genl_event {
 	DPLL_EVENT_STATUS_UNLOCKED,	/* DPLL device freerun */
 	DPLL_EVENT_SOURCE_CHANGE,		/* DPLL device source changed */
 	DPLL_EVENT_OUTPUT_CHANGE,		/* DPLL device output changed */
+	DPLL_EVENT_SOURCE_PRIO,
+	DPLL_EVENT_SELECT_MODE,
 
 	__DPLL_EVENT_MAX,
 };
@@ -90,12 +95,27 @@ enum dpll_genl_event {
 /* Commands supported by the dpll_genl_family */
 enum dpll_genl_cmd {
 	DPLL_CMD_UNSPEC,
-	DPLL_CMD_DEVICE_GET,	/* List of DPLL devices id */
+	DPLL_CMD_DEVICE_GET,		/* List of DPLL devices id */
 	DPLL_CMD_SET_SOURCE_TYPE,	/* Set the DPLL device source type */
 	DPLL_CMD_SET_OUTPUT_TYPE,	/* Set the DPLL device output type */
+	DPLL_CMD_SET_SRC_SELECT_MODE,/* Set mode for selection of a source */
+	DPLL_CMD_SET_SOURCE_PRIO,	/* Set priority of a source */
 
 	__DPLL_CMD_MAX,
 };
 #define DPLL_CMD_MAX (__DPLL_CMD_MAX - 1)
 
+/* Source select modes of dpll */
+enum dpll_genl_source_select_mode {
+	DPLL_SRC_SELECT_UNSPEC,
+	DPLL_SRC_SELECT_FORCED,   /* Source forced by DPLL_CMD_SET_SOURCE_TYPE */
+	DPLL_SRC_SELECT_AUTOMATIC,/* highest prio, valid source, auto selected by dpll */
+	DPLL_SRC_SELECT_HOLDOVER, /* forced holdover */
+	DPLL_SRC_SELECT_FREERUN,  /* dpll driven on system clk, no holdover available */
+	DPLL_SRC_SELECT_NCO,	     /* Set the DPLL device output type */
+
+	__DPLL_SRC_SELECT_MAX,
+};
+#define DPLL_SRC_SELECT_MAX (__DPLL_SRC_SELECT_MAX - 1)
+
 #endif /* _UAPI_LINUX_DPLL_H */
-- 
2.27.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [RFC PATCH v3 4/6] dpll: get source/output name
  2022-10-10  1:17 ` Vadim Fedorenko
@ 2022-10-10  1:18   ` Vadim Fedorenko
  -1 siblings, 0 replies; 67+ messages in thread
From: Vadim Fedorenko @ 2022-10-10  1:18 UTC (permalink / raw)
  To: Jakub Kicinski, Jiri Pirko, Arkadiusz Kubalewski
  Cc: netdev, linux-arm-kernel, linux-clk, Vadim Fedorenko

From: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>

Dump names of sources and outputs in response to DPLL_CMD_DEVICE_GET dump
request.

Signed-off-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
---
 drivers/dpll/dpll_netlink.c | 24 ++++++++++++++++++++++++
 include/linux/dpll.h        |  2 ++
 include/uapi/linux/dpll.h   |  2 ++
 3 files changed, 28 insertions(+)

diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c
index a5779871537a..e3604c10b59e 100644
--- a/drivers/dpll/dpll_netlink.c
+++ b/drivers/dpll/dpll_netlink.c
@@ -31,12 +31,16 @@ static const struct nla_policy dpll_genl_set_source_policy[] = {
 	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
 	[DPLLA_SOURCE_ID]	= { .type = NLA_U32 },
 	[DPLLA_SOURCE_TYPE]	= { .type = NLA_U32 },
+	[DPLLA_SOURCE_NAME]	= { .type = NLA_STRING,
+				    .len = DPLL_NAME_LENGTH },
 };
 
 static const struct nla_policy dpll_genl_set_output_policy[] = {
 	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
 	[DPLLA_OUTPUT_ID]	= { .type = NLA_U32 },
 	[DPLLA_OUTPUT_TYPE]	= { .type = NLA_U32 },
+	[DPLLA_OUTPUT_NAME]	= { .type = NLA_STRING,
+				    .len = DPLL_NAME_LENGTH },
 };
 
 static const struct nla_policy dpll_genl_set_src_select_mode_policy[] = {
@@ -100,6 +104,7 @@ static int __dpll_cmd_dump_sources(struct dpll_device *dpll,
 {
 	int i, ret = 0, type, prio;
 	struct nlattr *src_attr;
+	const char *name;
 
 	for (i = 0; i < dpll->sources_count; i++) {
 		src_attr = nla_nest_start(msg, DPLLA_SOURCE);
@@ -132,6 +137,15 @@ static int __dpll_cmd_dump_sources(struct dpll_device *dpll,
 				break;
 			}
 		}
+		if (dpll->ops->get_source_name) {
+			name = dpll->ops->get_source_name(dpll, i);
+			if (name && nla_put_string(msg, DPLLA_SOURCE_NAME,
+						   name)) {
+				nla_nest_cancel(msg, src_attr);
+				ret = -EMSGSIZE;
+				break;
+			}
+		}
 		nla_nest_end(msg, src_attr);
 	}
 
@@ -143,6 +157,7 @@ static int __dpll_cmd_dump_outputs(struct dpll_device *dpll,
 {
 	struct nlattr *out_attr;
 	int i, ret = 0, type;
+	const char *name;
 
 	for (i = 0; i < dpll->outputs_count; i++) {
 		out_attr = nla_nest_start(msg, DPLLA_OUTPUT);
@@ -167,6 +182,15 @@ static int __dpll_cmd_dump_outputs(struct dpll_device *dpll,
 			}
 			ret = 0;
 		}
+		if (dpll->ops->get_output_name) {
+			name = dpll->ops->get_output_name(dpll, i);
+			if (name && nla_put_string(msg, DPLLA_OUTPUT_NAME,
+						   name)) {
+				nla_nest_cancel(msg, out_attr);
+				ret = -EMSGSIZE;
+				break;
+			}
+		}
 		nla_nest_end(msg, out_attr);
 	}
 
diff --git a/include/linux/dpll.h b/include/linux/dpll.h
index 3fe957a06b90..2f4964dc28f0 100644
--- a/include/linux/dpll.h
+++ b/include/linux/dpll.h
@@ -23,6 +23,8 @@ struct dpll_device_ops {
 	int (*set_output_type)(struct dpll_device *dpll, int id, int val);
 	int (*set_source_select_mode)(struct dpll_device *dpll, int mode);
 	int (*set_source_prio)(struct dpll_device *dpll, int id, int prio);
+	const char *(*get_source_name)(struct dpll_device *dpll, int id);
+	const char *(*get_output_name)(struct dpll_device *dpll, int id);
 };
 
 struct dpll_device *dpll_device_alloc(struct dpll_device_ops *ops, const char *name,
diff --git a/include/uapi/linux/dpll.h b/include/uapi/linux/dpll.h
index f6b674e5cf01..8782d3425aae 100644
--- a/include/uapi/linux/dpll.h
+++ b/include/uapi/linux/dpll.h
@@ -26,11 +26,13 @@ enum dpll_genl_attr {
 	DPLLA_SOURCE,
 	DPLLA_SOURCE_ID,
 	DPLLA_SOURCE_TYPE,
+	DPLLA_SOURCE_NAME,
 	DPLLA_SOURCE_SUPPORTED,
 	DPLLA_SOURCE_PRIO,
 	DPLLA_OUTPUT,
 	DPLLA_OUTPUT_ID,
 	DPLLA_OUTPUT_TYPE,
+	DPLLA_OUTPUT_NAME,
 	DPLLA_OUTPUT_SUPPORTED,
 	DPLLA_STATUS,
 	DPLLA_TEMP,
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [RFC PATCH v3 4/6] dpll: get source/output name
@ 2022-10-10  1:18   ` Vadim Fedorenko
  0 siblings, 0 replies; 67+ messages in thread
From: Vadim Fedorenko @ 2022-10-10  1:18 UTC (permalink / raw)
  To: Jakub Kicinski, Jiri Pirko, Arkadiusz Kubalewski
  Cc: netdev, linux-arm-kernel, linux-clk, Vadim Fedorenko

From: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>

Dump names of sources and outputs in response to DPLL_CMD_DEVICE_GET dump
request.

Signed-off-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
---
 drivers/dpll/dpll_netlink.c | 24 ++++++++++++++++++++++++
 include/linux/dpll.h        |  2 ++
 include/uapi/linux/dpll.h   |  2 ++
 3 files changed, 28 insertions(+)

diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c
index a5779871537a..e3604c10b59e 100644
--- a/drivers/dpll/dpll_netlink.c
+++ b/drivers/dpll/dpll_netlink.c
@@ -31,12 +31,16 @@ static const struct nla_policy dpll_genl_set_source_policy[] = {
 	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
 	[DPLLA_SOURCE_ID]	= { .type = NLA_U32 },
 	[DPLLA_SOURCE_TYPE]	= { .type = NLA_U32 },
+	[DPLLA_SOURCE_NAME]	= { .type = NLA_STRING,
+				    .len = DPLL_NAME_LENGTH },
 };
 
 static const struct nla_policy dpll_genl_set_output_policy[] = {
 	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
 	[DPLLA_OUTPUT_ID]	= { .type = NLA_U32 },
 	[DPLLA_OUTPUT_TYPE]	= { .type = NLA_U32 },
+	[DPLLA_OUTPUT_NAME]	= { .type = NLA_STRING,
+				    .len = DPLL_NAME_LENGTH },
 };
 
 static const struct nla_policy dpll_genl_set_src_select_mode_policy[] = {
@@ -100,6 +104,7 @@ static int __dpll_cmd_dump_sources(struct dpll_device *dpll,
 {
 	int i, ret = 0, type, prio;
 	struct nlattr *src_attr;
+	const char *name;
 
 	for (i = 0; i < dpll->sources_count; i++) {
 		src_attr = nla_nest_start(msg, DPLLA_SOURCE);
@@ -132,6 +137,15 @@ static int __dpll_cmd_dump_sources(struct dpll_device *dpll,
 				break;
 			}
 		}
+		if (dpll->ops->get_source_name) {
+			name = dpll->ops->get_source_name(dpll, i);
+			if (name && nla_put_string(msg, DPLLA_SOURCE_NAME,
+						   name)) {
+				nla_nest_cancel(msg, src_attr);
+				ret = -EMSGSIZE;
+				break;
+			}
+		}
 		nla_nest_end(msg, src_attr);
 	}
 
@@ -143,6 +157,7 @@ static int __dpll_cmd_dump_outputs(struct dpll_device *dpll,
 {
 	struct nlattr *out_attr;
 	int i, ret = 0, type;
+	const char *name;
 
 	for (i = 0; i < dpll->outputs_count; i++) {
 		out_attr = nla_nest_start(msg, DPLLA_OUTPUT);
@@ -167,6 +182,15 @@ static int __dpll_cmd_dump_outputs(struct dpll_device *dpll,
 			}
 			ret = 0;
 		}
+		if (dpll->ops->get_output_name) {
+			name = dpll->ops->get_output_name(dpll, i);
+			if (name && nla_put_string(msg, DPLLA_OUTPUT_NAME,
+						   name)) {
+				nla_nest_cancel(msg, out_attr);
+				ret = -EMSGSIZE;
+				break;
+			}
+		}
 		nla_nest_end(msg, out_attr);
 	}
 
diff --git a/include/linux/dpll.h b/include/linux/dpll.h
index 3fe957a06b90..2f4964dc28f0 100644
--- a/include/linux/dpll.h
+++ b/include/linux/dpll.h
@@ -23,6 +23,8 @@ struct dpll_device_ops {
 	int (*set_output_type)(struct dpll_device *dpll, int id, int val);
 	int (*set_source_select_mode)(struct dpll_device *dpll, int mode);
 	int (*set_source_prio)(struct dpll_device *dpll, int id, int prio);
+	const char *(*get_source_name)(struct dpll_device *dpll, int id);
+	const char *(*get_output_name)(struct dpll_device *dpll, int id);
 };
 
 struct dpll_device *dpll_device_alloc(struct dpll_device_ops *ops, const char *name,
diff --git a/include/uapi/linux/dpll.h b/include/uapi/linux/dpll.h
index f6b674e5cf01..8782d3425aae 100644
--- a/include/uapi/linux/dpll.h
+++ b/include/uapi/linux/dpll.h
@@ -26,11 +26,13 @@ enum dpll_genl_attr {
 	DPLLA_SOURCE,
 	DPLLA_SOURCE_ID,
 	DPLLA_SOURCE_TYPE,
+	DPLLA_SOURCE_NAME,
 	DPLLA_SOURCE_SUPPORTED,
 	DPLLA_SOURCE_PRIO,
 	DPLLA_OUTPUT,
 	DPLLA_OUTPUT_ID,
 	DPLLA_OUTPUT_TYPE,
+	DPLLA_OUTPUT_NAME,
 	DPLLA_OUTPUT_SUPPORTED,
 	DPLLA_STATUS,
 	DPLLA_TEMP,
-- 
2.27.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [RFC PATCH v3 5/6] dpll: documentation on DPLL subsystem interface
  2022-10-10  1:17 ` Vadim Fedorenko
@ 2022-10-10  1:18   ` Vadim Fedorenko
  -1 siblings, 0 replies; 67+ messages in thread
From: Vadim Fedorenko @ 2022-10-10  1:18 UTC (permalink / raw)
  To: Jakub Kicinski, Jiri Pirko, Arkadiusz Kubalewski
  Cc: netdev, linux-arm-kernel, linux-clk, Vadim Fedorenko

From: Vadim Fedorenko <vadfed@fb.com>

Add documentation explaining common netlink interface to configure DPLL
devices and monitoring events. Common way to implement DPLL device in
a driver is also covered.

Signed-off-by: Vadim Fedorenko <vadfed@fb.com>
---
 Documentation/networking/dpll.rst  | 157 +++++++++++++++++++++++++++++
 Documentation/networking/index.rst |   1 +
 2 files changed, 158 insertions(+)
 create mode 100644 Documentation/networking/dpll.rst

diff --git a/Documentation/networking/dpll.rst b/Documentation/networking/dpll.rst
new file mode 100644
index 000000000000..00c15b19aefb
--- /dev/null
+++ b/Documentation/networking/dpll.rst
@@ -0,0 +1,157 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+===============================
+The Linux kernel DPLL subsystem
+===============================
+
+
+The main purpose of DPLL subsystem is to provide general interface
+to configure devices that use any kind of Digital PLL and could use
+different sources of signal to synchronize to as well as different
+types of outputs. The inputs and outputs could be internal components
+of the device as well as external connections. The main interface is
+NETLINK_GENERIC based protocol with config and monitoring groups of
+commands defined.
+
+Configuration commands group
+============================
+
+Configuration commands are used to get information about registered
+DPLL devices as well as get or set configuration of each used input
+or output. As DPLL device could not be abstract and reflects real
+hardware, there is no way to add new DPLL device via netlink from
+user space and each device should be registered by it's driver.
+
+List of command with possible attributes
+========================================
+
+All constants identifying command types use ``DPLL_CMD_`` prefix and
+suffix according to command purpose. All attributes use ``DPLLA_``
+prefix and suffix according to attribute purpose:
+
+  =====================================  =============================
+  ``DEVICE_GET``                         userspace to get device info
+    ``DEVICE_ID``                        attr internal device index
+    ``DEVICE_NAME``                      attr DPLL device name
+    ``STATUS``                           attr DPLL device status info
+    ``DEVICE_SRC_SELECT_MODE``           attr DPLL source selection
+                                         mode
+    ``DEVICE_SRC_SELECT_MODE_SUPPORTED`` attr supported source
+                                         selection modes
+    ``LOCK_STATUS``                      attr internal frequency-lock
+                                         status
+    ``TEMP``                             attr device temperature
+                                         information
+  ``SET_SOURCE``                         userspace to set
+                                         sources/inputs configuration
+    ``DEVICE_ID``                        attr internal device index
+                                         to configure source pin
+    ``SOURCE_ID``                        attr index of source pin to
+                                         configure
+    ``SOURCE_NAME``                      attr name of source pin to
+                                         configure
+    ``SOURCE_TYPE``                      attr configuration value for
+                                         selected source pin
+  ``SET_OUTPUT``                         userspace to set outputs
+                                         configuration
+    ``DEVICE_ID``                        attr internal device index to
+                                         configure output pin
+    ``OUTPUT_ID``                        attr index of output pin to
+                                         configure
+    ``OUTPUT_NAME``                      attr name of output pin to
+                                         configure
+    ``OUTPUT_TYPE``                      attr configuration value for
+                                         selected output pin
+  ``SET_SRC_SELECT_MODE``                userspace to set source pin
+                                         selection mode
+    ``DEVICE_ID``                        attr internal device index
+    ``DEVICE_SRC_SELECT_MODE``           attr source selection mode
+  ``SET_SOURCE_PRIO``                    userspace to set priority of
+                                         a source pin for automatic
+                                         source selection mode
+    ``DEVICE_ID``                        attr internal device index
+                                         for source pin
+    ``SOURCE_ID``                        attr index of source pin to
+                                         configure
+    ``SOURCE_PRIO``                      attr priority of a source pin
+
+
+The pre-defined enums
+=====================
+
+These enums are used to select type values for source/input and
+output pins:
+
+  ============================= ======================================
+  ``DPLL_TYPE_EXT_1PPS``        External 1PPS source
+  ``DPLL_TYPE_EXT_10MHZ``       External 10MHz source
+  ``DPLL_TYPE_SYNCE_ETH_PORT``  SyncE on Ethernet port
+  ``DPLL_TYPE_INT_OSCILLATOR``  Internal Oscillator (i.e. Holdover
+                                with Atomic Clock as a Source)
+  ``DPLL_TYPE_GNSS``            GNSS 1PPS source
+  ``DPLL_TYPE_CUSTOM``          Custom frequency
+
+Values for monitoring attributes STATUS:
+
+  ============================= ======================================
+  ``DPLL_STATUS_NONE``          No information provided
+  ``DPLL_STATUS_CALIBRATING``   DPLL device is not locked to the
+                                source frequency
+  ``DPLL_STATUS_LOCKED``        DPLL device is locked to the source
+                                frequency
+
+
+Possible DPLL source selection mode values:
+
+  ============================= ======================================
+  ``DPLL_SRC_SELECT_FORCED``    source pin is force-selected by
+                                DPLL_CMD_SET_SOURCE_TYPE
+  ``DPLL_SRC_SELECT_AUTOMATIC`` source pin ise auto selected according
+                                to configured priorities and source
+                                signal validity
+  ``DPLL_SRC_SELECT_HOLDOVER``  force holdover mode of DPLL
+  ``DPLL_SRC_SELECT_FREERUN``   DPLL is driven by supplied system
+                                clock without holdover capabilities
+  ``DPLL_SRC_SELECT_NCO``       similar to FREERUN, with possibility
+                                to numerically control frequency offset
+
+Notifications
+================
+
+DPLL device can provide notifications regarding status changes of the
+device, i.e. lock status changes, source/output type changes or alarms.
+This is the multicast group that is used to notify user-space apps via
+netlink socket:
+
+  ============================== ====================================
+  ``DPLL_EVENT_DEVICE_CREATE``   New DPLL device was created
+  ``DPLL_EVENT_DEVICE_DELETE``   DPLL device was deleted
+  ``DPLL_EVENT_STATUS_LOCKED``   DPLL device has locked to source
+  ``DPLL_EVENT_STATUS_UNLOCKED`` DPLL device is in freerun or
+                                 in calibration mode
+  ``DPLL_EVENT_SOURCE_CHANGE``   DPLL device source changed
+  ``DPLL_EVENT_OUTPUT_CHANGE``   DPLL device output changed
+  ``DPLL_EVENT_SOURCE_PRIO``     DPLL device source priority changed
+  ``DPLL_EVENT_SELECT_MODE``     DPLL device source selection mode
+                                 changed
+
+Device driver implementation
+============================
+
+For device to operate as DPLL subsystem device, it should implement
+set of operations and register device via ``dpll_device_alloc`` and
+``dpll_device_register`` providing desired device name and set of
+supported operations as well as the amount of sources/input pins and
+output pins. If there is no specific name supplied, dpll subsystem
+will use ``dpll%d`` template to create device name. Notifications of
+adding or removing DPLL devices are created within subsystem itself,
+but notifications about configurations changes or alarms should be
+implemented within driver as different ways of confirmation could be
+used. All the interfaces for notification messages could be found in
+``<dpll.h>``, constats and enums are placed in ``<uapi/linux/dpll.h>``
+to be consistent with user-space.
+
+There is no strict requeriment to implement all the operations for
+each device, every operation handler is checked for existence and
+ENOTSUPP is returned in case of absence of specific handler.
+
diff --git a/Documentation/networking/index.rst b/Documentation/networking/index.rst
index 16a153bcc5fe..612d322a3380 100644
--- a/Documentation/networking/index.rst
+++ b/Documentation/networking/index.rst
@@ -16,6 +16,7 @@ Contents:
    device_drivers/index
    dsa/index
    devlink/index
+   dpll
    caif/index
    ethtool-netlink
    ieee802154
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [RFC PATCH v3 5/6] dpll: documentation on DPLL subsystem interface
@ 2022-10-10  1:18   ` Vadim Fedorenko
  0 siblings, 0 replies; 67+ messages in thread
From: Vadim Fedorenko @ 2022-10-10  1:18 UTC (permalink / raw)
  To: Jakub Kicinski, Jiri Pirko, Arkadiusz Kubalewski
  Cc: netdev, linux-arm-kernel, linux-clk, Vadim Fedorenko

From: Vadim Fedorenko <vadfed@fb.com>

Add documentation explaining common netlink interface to configure DPLL
devices and monitoring events. Common way to implement DPLL device in
a driver is also covered.

Signed-off-by: Vadim Fedorenko <vadfed@fb.com>
---
 Documentation/networking/dpll.rst  | 157 +++++++++++++++++++++++++++++
 Documentation/networking/index.rst |   1 +
 2 files changed, 158 insertions(+)
 create mode 100644 Documentation/networking/dpll.rst

diff --git a/Documentation/networking/dpll.rst b/Documentation/networking/dpll.rst
new file mode 100644
index 000000000000..00c15b19aefb
--- /dev/null
+++ b/Documentation/networking/dpll.rst
@@ -0,0 +1,157 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+===============================
+The Linux kernel DPLL subsystem
+===============================
+
+
+The main purpose of DPLL subsystem is to provide general interface
+to configure devices that use any kind of Digital PLL and could use
+different sources of signal to synchronize to as well as different
+types of outputs. The inputs and outputs could be internal components
+of the device as well as external connections. The main interface is
+NETLINK_GENERIC based protocol with config and monitoring groups of
+commands defined.
+
+Configuration commands group
+============================
+
+Configuration commands are used to get information about registered
+DPLL devices as well as get or set configuration of each used input
+or output. As DPLL device could not be abstract and reflects real
+hardware, there is no way to add new DPLL device via netlink from
+user space and each device should be registered by it's driver.
+
+List of command with possible attributes
+========================================
+
+All constants identifying command types use ``DPLL_CMD_`` prefix and
+suffix according to command purpose. All attributes use ``DPLLA_``
+prefix and suffix according to attribute purpose:
+
+  =====================================  =============================
+  ``DEVICE_GET``                         userspace to get device info
+    ``DEVICE_ID``                        attr internal device index
+    ``DEVICE_NAME``                      attr DPLL device name
+    ``STATUS``                           attr DPLL device status info
+    ``DEVICE_SRC_SELECT_MODE``           attr DPLL source selection
+                                         mode
+    ``DEVICE_SRC_SELECT_MODE_SUPPORTED`` attr supported source
+                                         selection modes
+    ``LOCK_STATUS``                      attr internal frequency-lock
+                                         status
+    ``TEMP``                             attr device temperature
+                                         information
+  ``SET_SOURCE``                         userspace to set
+                                         sources/inputs configuration
+    ``DEVICE_ID``                        attr internal device index
+                                         to configure source pin
+    ``SOURCE_ID``                        attr index of source pin to
+                                         configure
+    ``SOURCE_NAME``                      attr name of source pin to
+                                         configure
+    ``SOURCE_TYPE``                      attr configuration value for
+                                         selected source pin
+  ``SET_OUTPUT``                         userspace to set outputs
+                                         configuration
+    ``DEVICE_ID``                        attr internal device index to
+                                         configure output pin
+    ``OUTPUT_ID``                        attr index of output pin to
+                                         configure
+    ``OUTPUT_NAME``                      attr name of output pin to
+                                         configure
+    ``OUTPUT_TYPE``                      attr configuration value for
+                                         selected output pin
+  ``SET_SRC_SELECT_MODE``                userspace to set source pin
+                                         selection mode
+    ``DEVICE_ID``                        attr internal device index
+    ``DEVICE_SRC_SELECT_MODE``           attr source selection mode
+  ``SET_SOURCE_PRIO``                    userspace to set priority of
+                                         a source pin for automatic
+                                         source selection mode
+    ``DEVICE_ID``                        attr internal device index
+                                         for source pin
+    ``SOURCE_ID``                        attr index of source pin to
+                                         configure
+    ``SOURCE_PRIO``                      attr priority of a source pin
+
+
+The pre-defined enums
+=====================
+
+These enums are used to select type values for source/input and
+output pins:
+
+  ============================= ======================================
+  ``DPLL_TYPE_EXT_1PPS``        External 1PPS source
+  ``DPLL_TYPE_EXT_10MHZ``       External 10MHz source
+  ``DPLL_TYPE_SYNCE_ETH_PORT``  SyncE on Ethernet port
+  ``DPLL_TYPE_INT_OSCILLATOR``  Internal Oscillator (i.e. Holdover
+                                with Atomic Clock as a Source)
+  ``DPLL_TYPE_GNSS``            GNSS 1PPS source
+  ``DPLL_TYPE_CUSTOM``          Custom frequency
+
+Values for monitoring attributes STATUS:
+
+  ============================= ======================================
+  ``DPLL_STATUS_NONE``          No information provided
+  ``DPLL_STATUS_CALIBRATING``   DPLL device is not locked to the
+                                source frequency
+  ``DPLL_STATUS_LOCKED``        DPLL device is locked to the source
+                                frequency
+
+
+Possible DPLL source selection mode values:
+
+  ============================= ======================================
+  ``DPLL_SRC_SELECT_FORCED``    source pin is force-selected by
+                                DPLL_CMD_SET_SOURCE_TYPE
+  ``DPLL_SRC_SELECT_AUTOMATIC`` source pin ise auto selected according
+                                to configured priorities and source
+                                signal validity
+  ``DPLL_SRC_SELECT_HOLDOVER``  force holdover mode of DPLL
+  ``DPLL_SRC_SELECT_FREERUN``   DPLL is driven by supplied system
+                                clock without holdover capabilities
+  ``DPLL_SRC_SELECT_NCO``       similar to FREERUN, with possibility
+                                to numerically control frequency offset
+
+Notifications
+================
+
+DPLL device can provide notifications regarding status changes of the
+device, i.e. lock status changes, source/output type changes or alarms.
+This is the multicast group that is used to notify user-space apps via
+netlink socket:
+
+  ============================== ====================================
+  ``DPLL_EVENT_DEVICE_CREATE``   New DPLL device was created
+  ``DPLL_EVENT_DEVICE_DELETE``   DPLL device was deleted
+  ``DPLL_EVENT_STATUS_LOCKED``   DPLL device has locked to source
+  ``DPLL_EVENT_STATUS_UNLOCKED`` DPLL device is in freerun or
+                                 in calibration mode
+  ``DPLL_EVENT_SOURCE_CHANGE``   DPLL device source changed
+  ``DPLL_EVENT_OUTPUT_CHANGE``   DPLL device output changed
+  ``DPLL_EVENT_SOURCE_PRIO``     DPLL device source priority changed
+  ``DPLL_EVENT_SELECT_MODE``     DPLL device source selection mode
+                                 changed
+
+Device driver implementation
+============================
+
+For device to operate as DPLL subsystem device, it should implement
+set of operations and register device via ``dpll_device_alloc`` and
+``dpll_device_register`` providing desired device name and set of
+supported operations as well as the amount of sources/input pins and
+output pins. If there is no specific name supplied, dpll subsystem
+will use ``dpll%d`` template to create device name. Notifications of
+adding or removing DPLL devices are created within subsystem itself,
+but notifications about configurations changes or alarms should be
+implemented within driver as different ways of confirmation could be
+used. All the interfaces for notification messages could be found in
+``<dpll.h>``, constats and enums are placed in ``<uapi/linux/dpll.h>``
+to be consistent with user-space.
+
+There is no strict requeriment to implement all the operations for
+each device, every operation handler is checked for existence and
+ENOTSUPP is returned in case of absence of specific handler.
+
diff --git a/Documentation/networking/index.rst b/Documentation/networking/index.rst
index 16a153bcc5fe..612d322a3380 100644
--- a/Documentation/networking/index.rst
+++ b/Documentation/networking/index.rst
@@ -16,6 +16,7 @@ Contents:
    device_drivers/index
    dsa/index
    devlink/index
+   dpll
    caif/index
    ethtool-netlink
    ieee802154
-- 
2.27.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [RFC PATCH v3 6/6] ptp_ocp: implement DPLL ops
  2022-10-10  1:17 ` Vadim Fedorenko
@ 2022-10-10  1:18   ` Vadim Fedorenko
  -1 siblings, 0 replies; 67+ messages in thread
From: Vadim Fedorenko @ 2022-10-10  1:18 UTC (permalink / raw)
  To: Jakub Kicinski, Jiri Pirko, Arkadiusz Kubalewski
  Cc: netdev, linux-arm-kernel, linux-clk, Vadim Fedorenko

From: Vadim Fedorenko <vadfed@fb.com>

Implement DPLL operations in ptp_ocp driver.

Signed-off-by: Vadim Fedorenko <vadfed@fb.com>
---
 drivers/ptp/Kconfig       |   1 +
 drivers/ptp/ptp_ocp.c     | 170 ++++++++++++++++++++++++++++++--------
 include/uapi/linux/dpll.h |   2 +
 3 files changed, 137 insertions(+), 36 deletions(-)

diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig
index fe4971b65c64..8c4cfabc1bfa 100644
--- a/drivers/ptp/Kconfig
+++ b/drivers/ptp/Kconfig
@@ -177,6 +177,7 @@ config PTP_1588_CLOCK_OCP
 	depends on COMMON_CLK
 	select NET_DEVLINK
 	select CRC16
+	select DPLL
 	help
 	  This driver adds support for an OpenCompute time card.
 
diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c
index d36c3f597f77..a01c0c721802 100644
--- a/drivers/ptp/ptp_ocp.c
+++ b/drivers/ptp/ptp_ocp.c
@@ -21,6 +21,8 @@
 #include <linux/mtd/mtd.h>
 #include <linux/nvmem-consumer.h>
 #include <linux/crc16.h>
+#include <linux/dpll.h>
+#include <uapi/linux/dpll.h>
 
 #define PCI_VENDOR_ID_FACEBOOK			0x1d9b
 #define PCI_DEVICE_ID_FACEBOOK_TIMECARD		0x0400
@@ -336,6 +338,7 @@ struct ptp_ocp {
 	struct ptp_ocp_signal	signal[4];
 	struct ptp_ocp_sma_connector sma[4];
 	const struct ocp_sma_op *sma_op;
+	struct dpll_device *dpll;
 };
 
 #define OCP_REQ_TIMESTAMP	BIT(0)
@@ -660,18 +663,19 @@ static DEFINE_IDR(ptp_ocp_idr);
 struct ocp_selector {
 	const char *name;
 	int value;
+	int dpll_type;
 };
 
 static const struct ocp_selector ptp_ocp_clock[] = {
-	{ .name = "NONE",	.value = 0 },
-	{ .name = "TOD",	.value = 1 },
-	{ .name = "IRIG",	.value = 2 },
-	{ .name = "PPS",	.value = 3 },
-	{ .name = "PTP",	.value = 4 },
-	{ .name = "RTC",	.value = 5 },
-	{ .name = "DCF",	.value = 6 },
-	{ .name = "REGS",	.value = 0xfe },
-	{ .name = "EXT",	.value = 0xff },
+	{ .name = "NONE",	.value = 0,		.dpll_type = 0 },
+	{ .name = "TOD",	.value = 1,		.dpll_type = 0 },
+	{ .name = "IRIG",	.value = 2,		.dpll_type = 0 },
+	{ .name = "PPS",	.value = 3,		.dpll_type = 0 },
+	{ .name = "PTP",	.value = 4,		.dpll_type = 0 },
+	{ .name = "RTC",	.value = 5,		.dpll_type = 0 },
+	{ .name = "DCF",	.value = 6,		.dpll_type = 0 },
+	{ .name = "REGS",	.value = 0xfe,		.dpll_type = 0 },
+	{ .name = "EXT",	.value = 0xff,		.dpll_type = 0 },
 	{ }
 };
 
@@ -680,37 +684,37 @@ static const struct ocp_selector ptp_ocp_clock[] = {
 #define SMA_SELECT_MASK		GENMASK(14, 0)
 
 static const struct ocp_selector ptp_ocp_sma_in[] = {
-	{ .name = "10Mhz",	.value = 0x0000 },
-	{ .name = "PPS1",	.value = 0x0001 },
-	{ .name = "PPS2",	.value = 0x0002 },
-	{ .name = "TS1",	.value = 0x0004 },
-	{ .name = "TS2",	.value = 0x0008 },
-	{ .name = "IRIG",	.value = 0x0010 },
-	{ .name = "DCF",	.value = 0x0020 },
-	{ .name = "TS3",	.value = 0x0040 },
-	{ .name = "TS4",	.value = 0x0080 },
-	{ .name = "FREQ1",	.value = 0x0100 },
-	{ .name = "FREQ2",	.value = 0x0200 },
-	{ .name = "FREQ3",	.value = 0x0400 },
-	{ .name = "FREQ4",	.value = 0x0800 },
-	{ .name = "None",	.value = SMA_DISABLE },
+	{ .name = "10Mhz",	.value = 0x0000,	.dpll_type = DPLL_TYPE_EXT_10MHZ },
+	{ .name = "PPS1",	.value = 0x0001,	.dpll_type = DPLL_TYPE_EXT_1PPS },
+	{ .name = "PPS2",	.value = 0x0002,	.dpll_type = DPLL_TYPE_EXT_1PPS },
+	{ .name = "TS1",	.value = 0x0004,	.dpll_type = DPLL_TYPE_CUSTOM },
+	{ .name = "TS2",	.value = 0x0008,	.dpll_type = DPLL_TYPE_CUSTOM },
+	{ .name = "IRIG",	.value = 0x0010,	.dpll_type = DPLL_TYPE_CUSTOM },
+	{ .name = "DCF",	.value = 0x0020,	.dpll_type = DPLL_TYPE_CUSTOM },
+	{ .name = "TS3",	.value = 0x0040,	.dpll_type = DPLL_TYPE_CUSTOM },
+	{ .name = "TS4",	.value = 0x0080,	.dpll_type = DPLL_TYPE_CUSTOM },
+	{ .name = "FREQ1",	.value = 0x0100,	.dpll_type = DPLL_TYPE_CUSTOM },
+	{ .name = "FREQ2",	.value = 0x0200,	.dpll_type = DPLL_TYPE_CUSTOM },
+	{ .name = "FREQ3",	.value = 0x0400,	.dpll_type = DPLL_TYPE_CUSTOM },
+	{ .name = "FREQ4",	.value = 0x0800,	.dpll_type = DPLL_TYPE_CUSTOM },
+	{ .name = "None",	.value = SMA_DISABLE,	.dpll_type = DPLL_TYPE_NONE },
 	{ }
 };
 
 static const struct ocp_selector ptp_ocp_sma_out[] = {
-	{ .name = "10Mhz",	.value = 0x0000 },
-	{ .name = "PHC",	.value = 0x0001 },
-	{ .name = "MAC",	.value = 0x0002 },
-	{ .name = "GNSS1",	.value = 0x0004 },
-	{ .name = "GNSS2",	.value = 0x0008 },
-	{ .name = "IRIG",	.value = 0x0010 },
-	{ .name = "DCF",	.value = 0x0020 },
-	{ .name = "GEN1",	.value = 0x0040 },
-	{ .name = "GEN2",	.value = 0x0080 },
-	{ .name = "GEN3",	.value = 0x0100 },
-	{ .name = "GEN4",	.value = 0x0200 },
-	{ .name = "GND",	.value = 0x2000 },
-	{ .name = "VCC",	.value = 0x4000 },
+	{ .name = "10Mhz",	.value = 0x0000,	.dpll_type = DPLL_TYPE_EXT_10MHZ },
+	{ .name = "PHC",	.value = 0x0001,	.dpll_type = DPLL_TYPE_INT_OSCILLATOR },
+	{ .name = "MAC",	.value = 0x0002,	.dpll_type = DPLL_TYPE_INT_OSCILLATOR },
+	{ .name = "GNSS1",	.value = 0x0004,	.dpll_type = DPLL_TYPE_GNSS },
+	{ .name = "GNSS2",	.value = 0x0008,	.dpll_type = DPLL_TYPE_GNSS },
+	{ .name = "IRIG",	.value = 0x0010,	.dpll_type = DPLL_TYPE_CUSTOM },
+	{ .name = "DCF",	.value = 0x0020,	.dpll_type = DPLL_TYPE_CUSTOM },
+	{ .name = "GEN1",	.value = 0x0040,	.dpll_type = DPLL_TYPE_CUSTOM },
+	{ .name = "GEN2",	.value = 0x0080,	.dpll_type = DPLL_TYPE_CUSTOM },
+	{ .name = "GEN3",	.value = 0x0100,	.dpll_type = DPLL_TYPE_CUSTOM },
+	{ .name = "GEN4",	.value = 0x0200,	.dpll_type = DPLL_TYPE_CUSTOM },
+	{ .name = "GND",	.value = 0x2000,	.dpll_type = DPLL_TYPE_CUSTOM },
+	{ .name = "VCC",	.value = 0x4000,	.dpll_type = DPLL_TYPE_CUSTOM },
 	{ }
 };
 
@@ -3707,6 +3711,90 @@ ptp_ocp_detach(struct ptp_ocp *bp)
 	device_unregister(&bp->dev);
 }
 
+static int ptp_ocp_dpll_get_status(struct dpll_device *dpll)
+{
+	struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll);
+	int sync;
+
+	sync = ioread32(&bp->reg->status) & OCP_STATUS_IN_SYNC;
+	return sync;
+}
+
+static int ptp_ocp_dpll_get_lock_status(struct dpll_device *dpll)
+{
+	struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll);
+	int sync;
+
+	sync = ioread32(&bp->reg->status) & OCP_STATUS_IN_SYNC;
+	return sync;
+}
+
+static int ptp_ocp_sma_get_dpll_type(struct ptp_ocp *bp, int sma_nr)
+{
+	const struct ocp_selector *tbl;
+	u32 val;
+
+	if (bp->sma[sma_nr].mode == SMA_MODE_IN)
+		tbl = bp->sma_op->tbl[0];
+	else
+		tbl = bp->sma_op->tbl[1];
+
+	val = ptp_ocp_sma_get(bp, sma_nr);
+	return tbl[val].dpll_type;
+}
+
+static int ptp_ocp_dpll_type_supported(struct dpll_device *dpll, int sma, int type, int dir)
+{
+	struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll);
+	const struct ocp_selector *tbl = bp->sma_op->tbl[dir];
+	int i;
+
+	for (i = 0; i < sizeof(*tbl); i++) {
+		if (tbl[i].dpll_type == type)
+			return 1;
+	}
+	return 0;
+}
+
+static int ptp_ocp_dpll_get_source_type(struct dpll_device *dpll, int sma)
+{
+	struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll);
+
+	if (bp->sma[sma].mode != SMA_MODE_IN)
+		return -1;
+
+	return ptp_ocp_sma_get_dpll_type(bp, sma);
+}
+
+static int ptp_ocp_dpll_get_source_supported(struct dpll_device *dpll, int sma, int type)
+{
+	return ptp_ocp_dpll_type_supported(dpll, sma, type, 0);
+}
+
+static int ptp_ocp_dpll_get_output_type(struct dpll_device *dpll, int sma)
+{
+	struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll);
+
+	if (bp->sma[sma].mode != SMA_MODE_OUT)
+		return -1;
+
+	return ptp_ocp_sma_get_dpll_type(bp, sma);
+}
+
+static int ptp_ocp_dpll_get_output_supported(struct dpll_device *dpll, int sma, int type)
+{
+	return ptp_ocp_dpll_type_supported(dpll, sma, type, 1);
+}
+
+static struct dpll_device_ops dpll_ops = {
+	.get_status		= ptp_ocp_dpll_get_status,
+	.get_lock_status	= ptp_ocp_dpll_get_lock_status,
+	.get_source_type	= ptp_ocp_dpll_get_source_type,
+	.get_source_supported	= ptp_ocp_dpll_get_source_supported,
+	.get_output_type	= ptp_ocp_dpll_get_output_type,
+	.get_output_supported	= ptp_ocp_dpll_get_output_supported,
+};
+
 static int
 ptp_ocp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
@@ -3762,6 +3850,14 @@ ptp_ocp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
 	ptp_ocp_info(bp);
 	devlink_register(devlink);
+
+	bp->dpll = dpll_device_alloc(&dpll_ops, "ocp", ARRAY_SIZE(bp->sma), ARRAY_SIZE(bp->sma), bp);
+	if (!bp->dpll) {
+		dev_err(&pdev->dev, "dpll_device_alloc failed\n");
+		return 0;
+	}
+	dpll_device_register(bp->dpll);
+
 	return 0;
 
 out:
@@ -3779,6 +3875,8 @@ ptp_ocp_remove(struct pci_dev *pdev)
 	struct ptp_ocp *bp = pci_get_drvdata(pdev);
 	struct devlink *devlink = priv_to_devlink(bp);
 
+	dpll_device_unregister(bp->dpll);
+	dpll_device_free(bp->dpll);
 	devlink_unregister(devlink);
 	ptp_ocp_detach(bp);
 	pci_disable_device(pdev);
diff --git a/include/uapi/linux/dpll.h b/include/uapi/linux/dpll.h
index 8782d3425aae..59fc6ef81b40 100644
--- a/include/uapi/linux/dpll.h
+++ b/include/uapi/linux/dpll.h
@@ -55,11 +55,13 @@ enum dpll_genl_status {
 
 /* DPLL signal types used as source or as output */
 enum dpll_genl_signal_type {
+	DPLL_TYPE_NONE,
 	DPLL_TYPE_EXT_1PPS,
 	DPLL_TYPE_EXT_10MHZ,
 	DPLL_TYPE_SYNCE_ETH_PORT,
 	DPLL_TYPE_INT_OSCILLATOR,
 	DPLL_TYPE_GNSS,
+	DPLL_TYPE_CUSTOM,
 
 	__DPLL_TYPE_MAX,
 };
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [RFC PATCH v3 6/6] ptp_ocp: implement DPLL ops
@ 2022-10-10  1:18   ` Vadim Fedorenko
  0 siblings, 0 replies; 67+ messages in thread
From: Vadim Fedorenko @ 2022-10-10  1:18 UTC (permalink / raw)
  To: Jakub Kicinski, Jiri Pirko, Arkadiusz Kubalewski
  Cc: netdev, linux-arm-kernel, linux-clk, Vadim Fedorenko

From: Vadim Fedorenko <vadfed@fb.com>

Implement DPLL operations in ptp_ocp driver.

Signed-off-by: Vadim Fedorenko <vadfed@fb.com>
---
 drivers/ptp/Kconfig       |   1 +
 drivers/ptp/ptp_ocp.c     | 170 ++++++++++++++++++++++++++++++--------
 include/uapi/linux/dpll.h |   2 +
 3 files changed, 137 insertions(+), 36 deletions(-)

diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig
index fe4971b65c64..8c4cfabc1bfa 100644
--- a/drivers/ptp/Kconfig
+++ b/drivers/ptp/Kconfig
@@ -177,6 +177,7 @@ config PTP_1588_CLOCK_OCP
 	depends on COMMON_CLK
 	select NET_DEVLINK
 	select CRC16
+	select DPLL
 	help
 	  This driver adds support for an OpenCompute time card.
 
diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c
index d36c3f597f77..a01c0c721802 100644
--- a/drivers/ptp/ptp_ocp.c
+++ b/drivers/ptp/ptp_ocp.c
@@ -21,6 +21,8 @@
 #include <linux/mtd/mtd.h>
 #include <linux/nvmem-consumer.h>
 #include <linux/crc16.h>
+#include <linux/dpll.h>
+#include <uapi/linux/dpll.h>
 
 #define PCI_VENDOR_ID_FACEBOOK			0x1d9b
 #define PCI_DEVICE_ID_FACEBOOK_TIMECARD		0x0400
@@ -336,6 +338,7 @@ struct ptp_ocp {
 	struct ptp_ocp_signal	signal[4];
 	struct ptp_ocp_sma_connector sma[4];
 	const struct ocp_sma_op *sma_op;
+	struct dpll_device *dpll;
 };
 
 #define OCP_REQ_TIMESTAMP	BIT(0)
@@ -660,18 +663,19 @@ static DEFINE_IDR(ptp_ocp_idr);
 struct ocp_selector {
 	const char *name;
 	int value;
+	int dpll_type;
 };
 
 static const struct ocp_selector ptp_ocp_clock[] = {
-	{ .name = "NONE",	.value = 0 },
-	{ .name = "TOD",	.value = 1 },
-	{ .name = "IRIG",	.value = 2 },
-	{ .name = "PPS",	.value = 3 },
-	{ .name = "PTP",	.value = 4 },
-	{ .name = "RTC",	.value = 5 },
-	{ .name = "DCF",	.value = 6 },
-	{ .name = "REGS",	.value = 0xfe },
-	{ .name = "EXT",	.value = 0xff },
+	{ .name = "NONE",	.value = 0,		.dpll_type = 0 },
+	{ .name = "TOD",	.value = 1,		.dpll_type = 0 },
+	{ .name = "IRIG",	.value = 2,		.dpll_type = 0 },
+	{ .name = "PPS",	.value = 3,		.dpll_type = 0 },
+	{ .name = "PTP",	.value = 4,		.dpll_type = 0 },
+	{ .name = "RTC",	.value = 5,		.dpll_type = 0 },
+	{ .name = "DCF",	.value = 6,		.dpll_type = 0 },
+	{ .name = "REGS",	.value = 0xfe,		.dpll_type = 0 },
+	{ .name = "EXT",	.value = 0xff,		.dpll_type = 0 },
 	{ }
 };
 
@@ -680,37 +684,37 @@ static const struct ocp_selector ptp_ocp_clock[] = {
 #define SMA_SELECT_MASK		GENMASK(14, 0)
 
 static const struct ocp_selector ptp_ocp_sma_in[] = {
-	{ .name = "10Mhz",	.value = 0x0000 },
-	{ .name = "PPS1",	.value = 0x0001 },
-	{ .name = "PPS2",	.value = 0x0002 },
-	{ .name = "TS1",	.value = 0x0004 },
-	{ .name = "TS2",	.value = 0x0008 },
-	{ .name = "IRIG",	.value = 0x0010 },
-	{ .name = "DCF",	.value = 0x0020 },
-	{ .name = "TS3",	.value = 0x0040 },
-	{ .name = "TS4",	.value = 0x0080 },
-	{ .name = "FREQ1",	.value = 0x0100 },
-	{ .name = "FREQ2",	.value = 0x0200 },
-	{ .name = "FREQ3",	.value = 0x0400 },
-	{ .name = "FREQ4",	.value = 0x0800 },
-	{ .name = "None",	.value = SMA_DISABLE },
+	{ .name = "10Mhz",	.value = 0x0000,	.dpll_type = DPLL_TYPE_EXT_10MHZ },
+	{ .name = "PPS1",	.value = 0x0001,	.dpll_type = DPLL_TYPE_EXT_1PPS },
+	{ .name = "PPS2",	.value = 0x0002,	.dpll_type = DPLL_TYPE_EXT_1PPS },
+	{ .name = "TS1",	.value = 0x0004,	.dpll_type = DPLL_TYPE_CUSTOM },
+	{ .name = "TS2",	.value = 0x0008,	.dpll_type = DPLL_TYPE_CUSTOM },
+	{ .name = "IRIG",	.value = 0x0010,	.dpll_type = DPLL_TYPE_CUSTOM },
+	{ .name = "DCF",	.value = 0x0020,	.dpll_type = DPLL_TYPE_CUSTOM },
+	{ .name = "TS3",	.value = 0x0040,	.dpll_type = DPLL_TYPE_CUSTOM },
+	{ .name = "TS4",	.value = 0x0080,	.dpll_type = DPLL_TYPE_CUSTOM },
+	{ .name = "FREQ1",	.value = 0x0100,	.dpll_type = DPLL_TYPE_CUSTOM },
+	{ .name = "FREQ2",	.value = 0x0200,	.dpll_type = DPLL_TYPE_CUSTOM },
+	{ .name = "FREQ3",	.value = 0x0400,	.dpll_type = DPLL_TYPE_CUSTOM },
+	{ .name = "FREQ4",	.value = 0x0800,	.dpll_type = DPLL_TYPE_CUSTOM },
+	{ .name = "None",	.value = SMA_DISABLE,	.dpll_type = DPLL_TYPE_NONE },
 	{ }
 };
 
 static const struct ocp_selector ptp_ocp_sma_out[] = {
-	{ .name = "10Mhz",	.value = 0x0000 },
-	{ .name = "PHC",	.value = 0x0001 },
-	{ .name = "MAC",	.value = 0x0002 },
-	{ .name = "GNSS1",	.value = 0x0004 },
-	{ .name = "GNSS2",	.value = 0x0008 },
-	{ .name = "IRIG",	.value = 0x0010 },
-	{ .name = "DCF",	.value = 0x0020 },
-	{ .name = "GEN1",	.value = 0x0040 },
-	{ .name = "GEN2",	.value = 0x0080 },
-	{ .name = "GEN3",	.value = 0x0100 },
-	{ .name = "GEN4",	.value = 0x0200 },
-	{ .name = "GND",	.value = 0x2000 },
-	{ .name = "VCC",	.value = 0x4000 },
+	{ .name = "10Mhz",	.value = 0x0000,	.dpll_type = DPLL_TYPE_EXT_10MHZ },
+	{ .name = "PHC",	.value = 0x0001,	.dpll_type = DPLL_TYPE_INT_OSCILLATOR },
+	{ .name = "MAC",	.value = 0x0002,	.dpll_type = DPLL_TYPE_INT_OSCILLATOR },
+	{ .name = "GNSS1",	.value = 0x0004,	.dpll_type = DPLL_TYPE_GNSS },
+	{ .name = "GNSS2",	.value = 0x0008,	.dpll_type = DPLL_TYPE_GNSS },
+	{ .name = "IRIG",	.value = 0x0010,	.dpll_type = DPLL_TYPE_CUSTOM },
+	{ .name = "DCF",	.value = 0x0020,	.dpll_type = DPLL_TYPE_CUSTOM },
+	{ .name = "GEN1",	.value = 0x0040,	.dpll_type = DPLL_TYPE_CUSTOM },
+	{ .name = "GEN2",	.value = 0x0080,	.dpll_type = DPLL_TYPE_CUSTOM },
+	{ .name = "GEN3",	.value = 0x0100,	.dpll_type = DPLL_TYPE_CUSTOM },
+	{ .name = "GEN4",	.value = 0x0200,	.dpll_type = DPLL_TYPE_CUSTOM },
+	{ .name = "GND",	.value = 0x2000,	.dpll_type = DPLL_TYPE_CUSTOM },
+	{ .name = "VCC",	.value = 0x4000,	.dpll_type = DPLL_TYPE_CUSTOM },
 	{ }
 };
 
@@ -3707,6 +3711,90 @@ ptp_ocp_detach(struct ptp_ocp *bp)
 	device_unregister(&bp->dev);
 }
 
+static int ptp_ocp_dpll_get_status(struct dpll_device *dpll)
+{
+	struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll);
+	int sync;
+
+	sync = ioread32(&bp->reg->status) & OCP_STATUS_IN_SYNC;
+	return sync;
+}
+
+static int ptp_ocp_dpll_get_lock_status(struct dpll_device *dpll)
+{
+	struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll);
+	int sync;
+
+	sync = ioread32(&bp->reg->status) & OCP_STATUS_IN_SYNC;
+	return sync;
+}
+
+static int ptp_ocp_sma_get_dpll_type(struct ptp_ocp *bp, int sma_nr)
+{
+	const struct ocp_selector *tbl;
+	u32 val;
+
+	if (bp->sma[sma_nr].mode == SMA_MODE_IN)
+		tbl = bp->sma_op->tbl[0];
+	else
+		tbl = bp->sma_op->tbl[1];
+
+	val = ptp_ocp_sma_get(bp, sma_nr);
+	return tbl[val].dpll_type;
+}
+
+static int ptp_ocp_dpll_type_supported(struct dpll_device *dpll, int sma, int type, int dir)
+{
+	struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll);
+	const struct ocp_selector *tbl = bp->sma_op->tbl[dir];
+	int i;
+
+	for (i = 0; i < sizeof(*tbl); i++) {
+		if (tbl[i].dpll_type == type)
+			return 1;
+	}
+	return 0;
+}
+
+static int ptp_ocp_dpll_get_source_type(struct dpll_device *dpll, int sma)
+{
+	struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll);
+
+	if (bp->sma[sma].mode != SMA_MODE_IN)
+		return -1;
+
+	return ptp_ocp_sma_get_dpll_type(bp, sma);
+}
+
+static int ptp_ocp_dpll_get_source_supported(struct dpll_device *dpll, int sma, int type)
+{
+	return ptp_ocp_dpll_type_supported(dpll, sma, type, 0);
+}
+
+static int ptp_ocp_dpll_get_output_type(struct dpll_device *dpll, int sma)
+{
+	struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll);
+
+	if (bp->sma[sma].mode != SMA_MODE_OUT)
+		return -1;
+
+	return ptp_ocp_sma_get_dpll_type(bp, sma);
+}
+
+static int ptp_ocp_dpll_get_output_supported(struct dpll_device *dpll, int sma, int type)
+{
+	return ptp_ocp_dpll_type_supported(dpll, sma, type, 1);
+}
+
+static struct dpll_device_ops dpll_ops = {
+	.get_status		= ptp_ocp_dpll_get_status,
+	.get_lock_status	= ptp_ocp_dpll_get_lock_status,
+	.get_source_type	= ptp_ocp_dpll_get_source_type,
+	.get_source_supported	= ptp_ocp_dpll_get_source_supported,
+	.get_output_type	= ptp_ocp_dpll_get_output_type,
+	.get_output_supported	= ptp_ocp_dpll_get_output_supported,
+};
+
 static int
 ptp_ocp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
@@ -3762,6 +3850,14 @@ ptp_ocp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
 	ptp_ocp_info(bp);
 	devlink_register(devlink);
+
+	bp->dpll = dpll_device_alloc(&dpll_ops, "ocp", ARRAY_SIZE(bp->sma), ARRAY_SIZE(bp->sma), bp);
+	if (!bp->dpll) {
+		dev_err(&pdev->dev, "dpll_device_alloc failed\n");
+		return 0;
+	}
+	dpll_device_register(bp->dpll);
+
 	return 0;
 
 out:
@@ -3779,6 +3875,8 @@ ptp_ocp_remove(struct pci_dev *pdev)
 	struct ptp_ocp *bp = pci_get_drvdata(pdev);
 	struct devlink *devlink = priv_to_devlink(bp);
 
+	dpll_device_unregister(bp->dpll);
+	dpll_device_free(bp->dpll);
 	devlink_unregister(devlink);
 	ptp_ocp_detach(bp);
 	pci_disable_device(pdev);
diff --git a/include/uapi/linux/dpll.h b/include/uapi/linux/dpll.h
index 8782d3425aae..59fc6ef81b40 100644
--- a/include/uapi/linux/dpll.h
+++ b/include/uapi/linux/dpll.h
@@ -55,11 +55,13 @@ enum dpll_genl_status {
 
 /* DPLL signal types used as source or as output */
 enum dpll_genl_signal_type {
+	DPLL_TYPE_NONE,
 	DPLL_TYPE_EXT_1PPS,
 	DPLL_TYPE_EXT_10MHZ,
 	DPLL_TYPE_SYNCE_ETH_PORT,
 	DPLL_TYPE_INT_OSCILLATOR,
 	DPLL_TYPE_GNSS,
+	DPLL_TYPE_CUSTOM,
 
 	__DPLL_TYPE_MAX,
 };
-- 
2.27.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 1/6] dpll: Add DPLL framework base functions
  2022-10-10  1:17   ` Vadim Fedorenko
@ 2022-10-10  9:18     ` Jiri Pirko
  -1 siblings, 0 replies; 67+ messages in thread
From: Jiri Pirko @ 2022-10-10  9:18 UTC (permalink / raw)
  To: Vadim Fedorenko
  Cc: Jakub Kicinski, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

Mon, Oct 10, 2022 at 03:17:59AM CEST, vfedorenko@novek.ru wrote:
>From: Vadim Fedorenko <vadfed@fb.com>
>
>DPLL framework is used to represent and configure DPLL devices
>in systems. Each device that has DPLL and can configure sources
>and outputs can use this framework.
>
>Signed-off-by: Vadim Fedorenko <vadfed@fb.com>
>Co-developed-by: Jakub Kicinski <kuba@kernel.org>
>Co-developed-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
>---
> MAINTAINERS                 |   8 +
> drivers/Kconfig             |   2 +
> drivers/Makefile            |   1 +
> drivers/dpll/Kconfig        |   7 +
> drivers/dpll/Makefile       |   7 +
> drivers/dpll/dpll_core.c    | 177 +++++++++++++++
> drivers/dpll/dpll_core.h    |  41 ++++
> drivers/dpll/dpll_netlink.c | 417 ++++++++++++++++++++++++++++++++++++
> drivers/dpll/dpll_netlink.h |   7 +
> include/linux/dpll.h        |  29 +++
> include/uapi/linux/dpll.h   | 101 +++++++++
> 11 files changed, 797 insertions(+)
> create mode 100644 drivers/dpll/Kconfig
> create mode 100644 drivers/dpll/Makefile
> create mode 100644 drivers/dpll/dpll_core.c
> create mode 100644 drivers/dpll/dpll_core.h
> create mode 100644 drivers/dpll/dpll_netlink.c
> create mode 100644 drivers/dpll/dpll_netlink.h
> create mode 100644 include/linux/dpll.h
> create mode 100644 include/uapi/linux/dpll.h
>
>diff --git a/MAINTAINERS b/MAINTAINERS
>index 9ca84cb5ab4a..e2f4fede937f 100644
>--- a/MAINTAINERS
>+++ b/MAINTAINERS
>@@ -6301,6 +6301,14 @@ F:	Documentation/networking/device_drivers/ethernet/freescale/dpaa2/switch-drive
> F:	drivers/net/ethernet/freescale/dpaa2/dpaa2-switch*
> F:	drivers/net/ethernet/freescale/dpaa2/dpsw*
> 
>+DPLL CLOCK SUBSYSTEM
>+M:	Vadim Fedorenko <vadfed@fb.com>
>+L:	netdev@vger.kernel.org
>+S:	Maintained
>+F:	drivers/dpll/*
>+F:	include/net/dpll.h
>+F:	include/uapi/linux/dpll.h
>+
> DRBD DRIVER
> M:	Philipp Reisner <philipp.reisner@linbit.com>
> M:	Lars Ellenberg <lars.ellenberg@linbit.com>
>diff --git a/drivers/Kconfig b/drivers/Kconfig
>index 19ee995bd0ae..a3e00294a995 100644
>--- a/drivers/Kconfig
>+++ b/drivers/Kconfig
>@@ -239,4 +239,6 @@ source "drivers/peci/Kconfig"
> 
> source "drivers/hte/Kconfig"
> 
>+source "drivers/dpll/Kconfig"
>+
> endmenu
>diff --git a/drivers/Makefile b/drivers/Makefile
>index 057857258bfd..78a68f1621cc 100644
>--- a/drivers/Makefile
>+++ b/drivers/Makefile
>@@ -188,3 +188,4 @@ obj-$(CONFIG_COUNTER)		+= counter/
> obj-$(CONFIG_MOST)		+= most/
> obj-$(CONFIG_PECI)		+= peci/
> obj-$(CONFIG_HTE)		+= hte/
>+obj-$(CONFIG_DPLL)		+= dpll/
>diff --git a/drivers/dpll/Kconfig b/drivers/dpll/Kconfig
>new file mode 100644
>index 000000000000..a4cae73f20d3
>--- /dev/null
>+++ b/drivers/dpll/Kconfig
>@@ -0,0 +1,7 @@
>+# SPDX-License-Identifier: GPL-2.0-only
>+#
>+# Generic DPLL drivers configuration
>+#
>+
>+config DPLL
>+  bool
>diff --git a/drivers/dpll/Makefile b/drivers/dpll/Makefile
>new file mode 100644
>index 000000000000..0748c80097e4
>--- /dev/null
>+++ b/drivers/dpll/Makefile
>@@ -0,0 +1,7 @@
>+# SPDX-License-Identifier: GPL-2.0
>+#
>+# Makefile for DPLL drivers.
>+#
>+
>+obj-$(CONFIG_DPLL)          += dpll_sys.o
>+dpll_sys-y                  += dpll_core.o dpll_netlink.o
>diff --git a/drivers/dpll/dpll_core.c b/drivers/dpll/dpll_core.c
>new file mode 100644
>index 000000000000..7fdee145e82c
>--- /dev/null
>+++ b/drivers/dpll/dpll_core.c
>@@ -0,0 +1,177 @@
>+// SPDX-License-Identifier: GPL-2.0
>+/*
>+ *  dpll_core.c - Generic DPLL Management class support.
>+ *
>+ *  Copyright (c) 2021 Meta Platforms, Inc. and affiliates
>+ */
>+
>+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
>+
>+#include <linux/device.h>
>+#include <linux/err.h>
>+#include <linux/slab.h>
>+#include <linux/string.h>
>+
>+#include "dpll_core.h"
>+
>+static DEFINE_MUTEX(dpll_device_xa_lock);
>+static DEFINE_XARRAY_FLAGS(dpll_device_xa, XA_FLAGS_ALLOC);
>+#define DPLL_REGISTERED XA_MARK_1
>+
>+#define ASSERT_DPLL_REGISTERED(d)                                           \
>+	WARN_ON_ONCE(!xa_get_mark(&dpll_device_xa, (d)->id, DPLL_REGISTERED))
>+#define ASSERT_DPLL_NOT_REGISTERED(d)                                      \
>+	WARN_ON_ONCE(xa_get_mark(&dpll_device_xa, (d)->id, DPLL_REGISTERED))
>+
>+
>+int for_each_dpll_device(int id, int (*cb)(struct dpll_device *, void *),
>+			 void *data)

Probably better to avoid this "cb" indirection here.
Perhaps in a similar way devlinks_xa_for_each_registered_get() is done?


>+{
>+	struct dpll_device *dpll;
>+	unsigned long index;
>+	int ret = 0;
>+
>+	mutex_lock(&dpll_device_xa_lock);
>+	xa_for_each_start(&dpll_device_xa, index, dpll, id) {
>+		if (!xa_get_mark(&dpll_device_xa, index, DPLL_REGISTERED))
>+			continue;
>+		ret = cb(dpll, data);
>+		if (ret)
>+			break;
>+	}
>+	mutex_unlock(&dpll_device_xa_lock);
>+
>+	return ret;
>+}
>+
>+struct dpll_device *dpll_device_get_by_id(int id)
>+{
>+	struct dpll_device *dpll = NULL;
>+
>+	if (xa_get_mark(&dpll_device_xa, id, DPLL_REGISTERED))
>+		dpll = xa_load(&dpll_device_xa, id);
>+	return dpll;
>+}
>+
>+struct dpll_device *dpll_device_get_by_name(const char *name)
>+{
>+	struct dpll_device *dpll, *ret = NULL;
>+	unsigned long index;
>+
>+	mutex_lock(&dpll_device_xa_lock);
>+	xa_for_each_marked(&dpll_device_xa, index, dpll, DPLL_REGISTERED) {
>+		if (!strcmp(dev_name(&dpll->dev), name)) {
>+			ret = dpll;
>+			break;
>+		}
>+	}
>+	mutex_unlock(&dpll_device_xa_lock);
>+
>+	return ret;
>+}
>+
>+void *dpll_priv(struct dpll_device *dpll)
>+{
>+	return dpll->priv;
>+}
>+EXPORT_SYMBOL_GPL(dpll_priv);
>+
>+static void dpll_device_release(struct device *dev)
>+{
>+	struct dpll_device *dpll;
>+
>+	dpll = to_dpll_device(dev);
>+
>+	dpll_device_unregister(dpll);
>+	dpll_device_free(dpll);
>+}
>+
>+static struct class dpll_class = {
>+	.name = "dpll",
>+	.dev_release = dpll_device_release,
>+};
>+
>+struct dpll_device *dpll_device_alloc(struct dpll_device_ops *ops, const char *name,
>+				      int sources_count, int outputs_count, void *priv)
>+{
>+	struct dpll_device *dpll;
>+	int ret;
>+
>+	dpll = kzalloc(sizeof(*dpll), GFP_KERNEL);
>+	if (!dpll)
>+		return ERR_PTR(-ENOMEM);
>+
>+	mutex_init(&dpll->lock);
>+	dpll->ops = ops;
>+	dpll->dev.class = &dpll_class;
>+	dpll->sources_count = sources_count;
>+	dpll->outputs_count = outputs_count;
>+
>+	mutex_lock(&dpll_device_xa_lock);
>+	ret = xa_alloc(&dpll_device_xa, &dpll->id, dpll, xa_limit_16b, GFP_KERNEL);
>+	if (ret)
>+		goto error;
>+	dev_set_name(&dpll->dev, "%s%d", name ? name : "dpll", dpll->id);
>+	mutex_unlock(&dpll_device_xa_lock);
>+	dpll->priv = priv;
>+
>+	return dpll;
>+
>+error:
>+	mutex_unlock(&dpll_device_xa_lock);
>+	kfree(dpll);
>+	return ERR_PTR(ret);
>+}
>+EXPORT_SYMBOL_GPL(dpll_device_alloc);
>+
>+void dpll_device_free(struct dpll_device *dpll)
>+{
>+	if (!dpll)
>+		return;
>+
>+	mutex_destroy(&dpll->lock);
>+	kfree(dpll);
>+}
>+EXPORT_SYMBOL_GPL(dpll_device_free);
>+
>+void dpll_device_register(struct dpll_device *dpll)
>+{
>+	ASSERT_DPLL_NOT_REGISTERED(dpll);
>+
>+	mutex_lock(&dpll_device_xa_lock);
>+	xa_set_mark(&dpll_device_xa, dpll->id, DPLL_REGISTERED);
>+	mutex_unlock(&dpll_device_xa_lock);
>+}
>+EXPORT_SYMBOL_GPL(dpll_device_register);
>+
>+void dpll_device_unregister(struct dpll_device *dpll)
>+{
>+	ASSERT_DPLL_REGISTERED(dpll);
>+
>+	mutex_lock(&dpll_device_xa_lock);
>+	xa_erase(&dpll_device_xa, dpll->id);
>+	mutex_unlock(&dpll_device_xa_lock);
>+}
>+EXPORT_SYMBOL_GPL(dpll_device_unregister);
>+
>+static int __init dpll_init(void)
>+{
>+	int ret;
>+
>+	ret = dpll_netlink_init();
>+	if (ret)
>+		goto error;
>+
>+	ret = class_register(&dpll_class);
>+	if (ret)
>+		goto unregister_netlink;
>+
>+	return 0;
>+
>+unregister_netlink:
>+	dpll_netlink_finish();
>+error:
>+	mutex_destroy(&dpll_device_xa_lock);
>+	return ret;
>+}
>+subsys_initcall(dpll_init);
>diff --git a/drivers/dpll/dpll_core.h b/drivers/dpll/dpll_core.h
>new file mode 100644
>index 000000000000..4b6fc9eb228f
>--- /dev/null
>+++ b/drivers/dpll/dpll_core.h
>@@ -0,0 +1,41 @@
>+/* SPDX-License-Identifier: GPL-2.0 */
>+/*
>+ *  Copyright (c) 2021 Meta Platforms, Inc. and affiliates
>+ */
>+
>+#ifndef __DPLL_CORE_H__
>+#define __DPLL_CORE_H__
>+
>+#include <linux/dpll.h>
>+
>+#include "dpll_netlink.h"
>+
>+/**
>+ * struct dpll_device - structure for a DPLL device
>+ * @id:		unique id number for each edvice
>+ * @dev:	&struct device for this dpll device
>+ * @sources_count:	amount of input sources this dpll_device supports
>+ * @outputs_count:	amount of outputs this dpll_device supports
>+ * @ops:	operations this &dpll_device supports
>+ * @lock:	mutex to serialize operations
>+ * @priv:	pointer to private information of owner
>+ */
>+struct dpll_device {
>+	int id;
>+	struct device dev;
>+	int sources_count;
>+	int outputs_count;
>+	struct dpll_device_ops *ops;
>+	struct mutex lock;
>+	void *priv;
>+};
>+
>+#define to_dpll_device(_dev) \
>+	container_of(_dev, struct dpll_device, dev)
>+
>+int for_each_dpll_device(int id, int (*cb)(struct dpll_device *, void *),
>+			  void *data);
>+struct dpll_device *dpll_device_get_by_id(int id);
>+struct dpll_device *dpll_device_get_by_name(const char *name);
>+void dpll_device_unregister(struct dpll_device *dpll);
>+#endif
>diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c
>new file mode 100644
>index 000000000000..31966e0eec3a
>--- /dev/null
>+++ b/drivers/dpll/dpll_netlink.c
>@@ -0,0 +1,417 @@
>+// SPDX-License-Identifier: GPL-2.0
>+/*
>+ * Generic netlink for DPLL management framework
>+ *
>+ * Copyright (c) 2021 Meta Platforms, Inc. and affiliates
>+ *
>+ */
>+#include <linux/module.h>
>+#include <linux/kernel.h>
>+#include <net/genetlink.h>
>+#include "dpll_core.h"
>+
>+#include <uapi/linux/dpll.h>
>+
>+static const struct genl_multicast_group dpll_genl_mcgrps[] = {
>+	{ .name = DPLL_CONFIG_DEVICE_GROUP_NAME, },
>+	{ .name = DPLL_CONFIG_SOURCE_GROUP_NAME, },
>+	{ .name = DPLL_CONFIG_OUTPUT_GROUP_NAME, },
>+	{ .name = DPLL_MONITOR_GROUP_NAME,  },
>+};
>+
>+static const struct nla_policy dpll_genl_get_policy[] = {
>+	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
>+	[DPLLA_DEVICE_NAME]	= { .type = NLA_STRING,
>+				    .len = DPLL_NAME_LENGTH },
>+	[DPLLA_FLAGS]		= { .type = NLA_U32 },
>+};
>+
>+static const struct nla_policy dpll_genl_set_source_policy[] = {
>+	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
>+	[DPLLA_SOURCE_ID]	= { .type = NLA_U32 },
>+	[DPLLA_SOURCE_TYPE]	= { .type = NLA_U32 },
>+};
>+
>+static const struct nla_policy dpll_genl_set_output_policy[] = {
>+	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
>+	[DPLLA_OUTPUT_ID]	= { .type = NLA_U32 },
>+	[DPLLA_OUTPUT_TYPE]	= { .type = NLA_U32 },
>+};
>+
>+struct param {

Namespace prefix please	.


>+	struct netlink_callback *cb;
>+	struct dpll_device *dpll;
>+	struct sk_buff *msg;



>+	int dpll_id;
>+	int dpll_source_id;
>+	int dpll_source_type;
>+	int dpll_output_id;
>+	int dpll_output_type;

I don't see where you use these 5.


>+};
>+
>+struct dpll_dump_ctx {
>+	struct dpll_device *dev;
>+	int flags;
>+	int pos_idx;



>+	int pos_src_idx;
>+	int pos_out_idx;

You don't use these 2.


>+};
>+
>+typedef int (*cb_t)(struct param *);
>+
>+static struct genl_family dpll_gnl_family;
>+
>+static struct dpll_dump_ctx *dpll_dump_context(struct netlink_callback *cb)
>+{
>+	return (struct dpll_dump_ctx *)cb->ctx;
>+}
>+
>+static int __dpll_cmd_device_dump_one(struct dpll_device *dpll,
>+					   struct sk_buff *msg)
>+{
>+	if (nla_put_u32(msg, DPLLA_DEVICE_ID, dpll->id))
>+		return -EMSGSIZE;
>+
>+	if (nla_put_string(msg, DPLLA_DEVICE_NAME, dev_name(&dpll->dev)))
>+		return -EMSGSIZE;
>+
>+	return 0;
>+}
>+
>+static int __dpll_cmd_dump_sources(struct dpll_device *dpll,
>+					   struct sk_buff *msg)
>+{
>+	struct nlattr *src_attr;
>+	int i, ret = 0, type;
>+
>+	for (i = 0; i < dpll->sources_count; i++) {
>+		src_attr = nla_nest_start(msg, DPLLA_SOURCE);
>+		if (!src_attr) {
>+			ret = -EMSGSIZE;
>+			break;
>+		}
>+		type = dpll->ops->get_source_type(dpll, i);
>+		if (nla_put_u32(msg, DPLLA_SOURCE_ID, i) ||
>+		    nla_put_u32(msg, DPLLA_SOURCE_TYPE, type)) {
>+			nla_nest_cancel(msg, src_attr);
>+			ret = -EMSGSIZE;
>+			break;
>+		}
>+		if (dpll->ops->get_source_supported) {
>+			for (type = 0; type <= DPLL_TYPE_MAX; type++) {
>+				ret = dpll->ops->get_source_supported(dpll, i, type);

Okay, this looks weird to me. This implicates that it is possible to
have for example:
source index 0 of type 10 
source index 0 of type 11 
Both possible.

However, from how I understand this, each source if of certain fixed type.
Either it is:
SyncE port
1pps external input (SMA)
10MHZ external input (SMA)
internal oscilator (free-running)
GNSS (GPS)

So for example:
index 0, type: 1pps external input (SMA)
index 1, type: 10MHZ external input (
index 2, type: SyncE port, netdev ifindex: 20
index 3, type: SyncE port, netdev ifindex: 30

So 4 "source" objects, each of different type.
In this case I can imagine that the netlink API might look something
like:
-> DPLL_CMD_SOURCE_GET - dump
     ATTR_DEVICE_ID X

<- DPLL_CMD_SOURCE_GET

     ATTR_DEVICE_ID X
     ATTR_SOURCE_INDEX 0
     ATTR_SOURCE_TYPE EXT_1PPS
     
     ATTR_DEVICE_ID X
     ATTR_SOURCE_INDEX 1
     ATTR_SOURCE_TYPE EXT_10MHZ
     
     ATTR_DEVICE_ID X
     ATTR_SOURCE_INDEX 2
     ATTR_SOURCE_TYPE SYNCE_ETH_PORT
     ATTR_SOURCE_NETDEV_IFINDEX 20

     ATTR_DEVICE_ID X
     ATTR_SOURCE_INDEX 3
     ATTR_SOURCE_TYPE SYNCE_ETH_PORT
     ATTR_SOURCE_NETDEV_IFINDEX 30

You see kernel would dump 4 source objects.



>+				if (ret && nla_put_u32(msg, DPLLA_SOURCE_SUPPORTED, type)) {
>+					ret = -EMSGSIZE;
>+					break;
>+				}
>+			}
>+			ret = 0;
>+		}
>+		nla_nest_end(msg, src_attr);
>+	}
>+
>+	return ret;
>+}
>+
>+static int __dpll_cmd_dump_outputs(struct dpll_device *dpll,
>+					   struct sk_buff *msg)
>+{
>+	struct nlattr *out_attr;
>+	int i, ret = 0, type;
>+
>+	for (i = 0; i < dpll->outputs_count; i++) {
>+		out_attr = nla_nest_start(msg, DPLLA_OUTPUT);
>+		if (!out_attr) {
>+			ret = -EMSGSIZE;
>+			break;
>+		}
>+		type = dpll->ops->get_output_type(dpll, i);
>+		if (nla_put_u32(msg, DPLLA_OUTPUT_ID, i) ||
>+		    nla_put_u32(msg, DPLLA_OUTPUT_TYPE, type)) {
>+			nla_nest_cancel(msg, out_attr);
>+			ret = -EMSGSIZE;
>+			break;
>+		}
>+		if (dpll->ops->get_output_supported) {
>+			for (type = 0; type <= DPLL_TYPE_MAX; type++) {
>+				ret = dpll->ops->get_output_supported(dpll, i, type);
>+				if (ret && nla_put_u32(msg, DPLLA_OUTPUT_SUPPORTED, type)) {

This I believe is similar to sources, see my comment above.

I believe we should have separate commands to GET and SET outputs and
sources. That would make the object separation clear and will also help
event model. See below I suggestion how output netlink API may look
like (comment in header file near enum dpll_genl_cmd definition).


>+					ret = -EMSGSIZE;
>+					break;
>+				}
>+			}
>+			ret = 0;
>+		}
>+		nla_nest_end(msg, out_attr);
>+	}
>+
>+	return ret;
>+}
>+
>+static int __dpll_cmd_dump_status(struct dpll_device *dpll,
>+					   struct sk_buff *msg)
>+{
>+	int ret;
>+
>+	if (dpll->ops->get_status) {
>+		ret = dpll->ops->get_status(dpll);
>+		if (nla_put_u32(msg, DPLLA_STATUS, ret))
>+			return -EMSGSIZE;
>+	}
>+
>+	if (dpll->ops->get_temp) {
>+		ret = dpll->ops->get_temp(dpll);
>+		if (nla_put_u32(msg, DPLLA_TEMP, ret))
>+			return -EMSGSIZE;
>+	}
>+
>+	if (dpll->ops->get_lock_status) {
>+		ret = dpll->ops->get_lock_status(dpll);
>+		if (nla_put_u32(msg, DPLLA_LOCK_STATUS, ret))
>+			return -EMSGSIZE;
>+	}
>+
>+	return 0;
>+}
>+
>+static int
>+dpll_device_dump_one(struct dpll_device *dpll, struct sk_buff *msg,
>+		     u32 portid, u32 seq, int flags)
>+{
>+	struct nlattr *hdr;
>+	int ret;
>+
>+	hdr = genlmsg_put(msg, portid, seq, &dpll_gnl_family, 0,
>+			  DPLL_CMD_DEVICE_GET);
>+	if (!hdr)
>+		return -EMSGSIZE;
>+
>+	mutex_lock(&dpll->lock);
>+	ret = __dpll_cmd_device_dump_one(dpll, msg);
>+	if (ret)
>+		goto out_unlock;
>+
>+	if (flags & DPLL_FLAG_SOURCES && dpll->ops->get_source_type) {
>+		ret = __dpll_cmd_dump_sources(dpll, msg);
>+		if (ret)
>+			goto out_unlock;
>+	}
>+
>+	if (flags & DPLL_FLAG_OUTPUTS && dpll->ops->get_output_type) {
>+		ret = __dpll_cmd_dump_outputs(dpll, msg);
>+		if (ret)
>+			goto out_unlock;
>+	}
>+
>+	if (flags & DPLL_FLAG_STATUS) {
>+		ret = __dpll_cmd_dump_status(dpll, msg);
>+		if (ret)
>+			goto out_unlock;
>+	}
>+	mutex_unlock(&dpll->lock);
>+	genlmsg_end(msg, hdr);
>+
>+	return 0;
>+
>+out_unlock:
>+	mutex_unlock(&dpll->lock);
>+	genlmsg_cancel(msg, hdr);
>+
>+	return ret;
>+}
>+
>+static int dpll_genl_cmd_set_source(struct sk_buff *skb, struct genl_info *info)
>+{
>+	struct dpll_device *dpll = info->user_ptr[0];
>+	struct nlattr **attrs = info->attrs;
>+	int ret = 0, src_id, type;

Enums.

>+
>+	if (!attrs[DPLLA_SOURCE_ID] ||
>+	    !attrs[DPLLA_SOURCE_TYPE])
>+		return -EINVAL;
>+
>+	if (!dpll->ops->set_source_type)
>+		return -EOPNOTSUPP;
>+
>+	src_id = nla_get_u32(attrs[DPLLA_SOURCE_ID]);
>+	type = nla_get_u32(attrs[DPLLA_SOURCE_TYPE]);


This looks odd to me. The user should just pass the index of source to
select. Type should be static, and non-changeable.


>+
>+	mutex_lock(&dpll->lock);
>+	ret = dpll->ops->set_source_type(dpll, src_id, type);
>+	mutex_unlock(&dpll->lock);
>+
>+	return ret;
>+}
>+
>+static int dpll_genl_cmd_set_output(struct sk_buff *skb, struct genl_info *info)
>+{
>+	struct dpll_device *dpll = info->user_ptr[0];
>+	struct nlattr **attrs = info->attrs;
>+	int ret = 0, out_id, type;

Enums.


>+
>+	if (!attrs[DPLLA_OUTPUT_ID] ||
>+	    !attrs[DPLLA_OUTPUT_TYPE])
>+		return -EINVAL;
>+
>+	if (!dpll->ops->set_output_type)
>+		return -EOPNOTSUPP;
>+
>+	out_id = nla_get_u32(attrs[DPLLA_OUTPUT_ID]);
>+	type = nla_get_u32(attrs[DPLLA_OUTPUT_TYPE]);

Same here, passing type here looks wrong.



>+
>+	mutex_lock(&dpll->lock);
>+	ret = dpll->ops->set_output_type(dpll, out_id, type);
>+	mutex_unlock(&dpll->lock);
>+
>+	return ret;
>+}
>+
>+static int dpll_device_loop_cb(struct dpll_device *dpll, void *data)
>+{
>+	struct dpll_dump_ctx *ctx;
>+	struct param *p = (struct param *)data;
>+
>+	ctx = dpll_dump_context(p->cb);
>+
>+	ctx->pos_idx = dpll->id;
>+
>+	return dpll_device_dump_one(dpll, p->msg, 0, 0, ctx->flags);
>+}
>+
>+static int
>+dpll_cmd_device_dump(struct sk_buff *skb, struct netlink_callback *cb)
>+{
>+	struct dpll_dump_ctx *ctx = dpll_dump_context(cb);
>+	struct param p = { .cb = cb, .msg = skb };
>+
>+	return for_each_dpll_device(ctx->pos_idx, dpll_device_loop_cb, &p);
>+}
>+
>+static int
>+dpll_genl_cmd_device_get_id(struct sk_buff *skb, struct genl_info *info)

Just "get", no "id" here.


>+{
>+	struct dpll_device *dpll = info->user_ptr[0];
>+	struct nlattr **attrs = info->attrs;
>+	struct sk_buff *msg;
>+	int flags = 0;
>+	int ret;
>+
>+	if (attrs[DPLLA_FLAGS])
>+		flags = nla_get_u32(attrs[DPLLA_FLAGS]);
>+
>+	msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
>+	if (!msg)
>+		return -ENOMEM;
>+
>+	ret = dpll_device_dump_one(dpll, msg, info->snd_portid, info->snd_seq,
>+				   flags);
>+	if (ret)
>+		goto out_free_msg;
>+
>+	return genlmsg_reply(msg, info);
>+
>+out_free_msg:
>+	nlmsg_free(msg);
>+	return ret;
>+
>+}
>+
>+static int dpll_genl_cmd_start(struct netlink_callback *cb)
>+{
>+	const struct genl_dumpit_info *info = genl_dumpit_info(cb);
>+	struct dpll_dump_ctx *ctx = dpll_dump_context(cb);
>+
>+	ctx->dev = NULL;
>+	if (info->attrs[DPLLA_FLAGS])
>+		ctx->flags = nla_get_u32(info->attrs[DPLLA_FLAGS]);
>+	else
>+		ctx->flags = 0;
>+	ctx->pos_idx = 0;
>+	ctx->pos_src_idx = 0;
>+	ctx->pos_out_idx = 0;
>+	return 0;
>+}
>+
>+static int dpll_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
>+						 struct genl_info *info)
>+{
>+	struct dpll_device *dpll_id = NULL, *dpll_name = NULL;
>+
>+	if (!info->attrs[DPLLA_DEVICE_ID] &&
>+	    !info->attrs[DPLLA_DEVICE_NAME])
>+		return -EINVAL;
>+
>+	if (info->attrs[DPLLA_DEVICE_ID]) {
>+		u32 id = nla_get_u32(info->attrs[DPLLA_DEVICE_ID]);
>+
>+		dpll_id = dpll_device_get_by_id(id);
>+		if (!dpll_id)
>+			return -ENODEV;
>+		info->user_ptr[0] = dpll_id;

struct dpll_device *dpll should be stored here.


>+	}
>+	if (info->attrs[DPLLA_DEVICE_NAME]) {

You define new API, have one clear handle for devices. Either name or
ID. Having both is messy.


>+		const char *name = nla_data(info->attrs[DPLLA_DEVICE_NAME]);
>+
>+		dpll_name = dpll_device_get_by_name(name);
>+		if (!dpll_name)
>+			return -ENODEV;
>+
>+		if (dpll_id && dpll_name != dpll_id)
>+			return -EINVAL;
>+		info->user_ptr[0] = dpll_name;

struct dpll_device *dpll should be stored here.



>+	}
>+
>+	return 0;
>+}
>+
>+static const struct genl_ops dpll_genl_ops[] = {
>+	{
>+		.cmd	= DPLL_CMD_DEVICE_GET,
>+		.flags  = GENL_UNS_ADMIN_PERM,
>+		.start	= dpll_genl_cmd_start,
>+		.dumpit	= dpll_cmd_device_dump,
>+		.doit	= dpll_genl_cmd_device_get_id,
>+		.policy	= dpll_genl_get_policy,
>+		.maxattr = ARRAY_SIZE(dpll_genl_get_policy) - 1,
>+	},
>+	{
>+		.cmd	= DPLL_CMD_SET_SOURCE_TYPE,
>+		.flags	= GENL_UNS_ADMIN_PERM,
>+		.doit	= dpll_genl_cmd_set_source,
>+		.policy	= dpll_genl_set_source_policy,
>+		.maxattr = ARRAY_SIZE(dpll_genl_set_source_policy) - 1,
>+	},
>+	{
>+		.cmd	= DPLL_CMD_SET_OUTPUT_TYPE,
>+		.flags	= GENL_UNS_ADMIN_PERM,
>+		.doit	= dpll_genl_cmd_set_output,
>+		.policy	= dpll_genl_set_output_policy,
>+		.maxattr = ARRAY_SIZE(dpll_genl_set_output_policy) - 1,
>+	},
>+};
>+
>+static struct genl_family dpll_gnl_family __ro_after_init = {
>+	.hdrsize	= 0,
>+	.name		= DPLL_FAMILY_NAME,
>+	.version	= DPLL_VERSION,
>+	.ops		= dpll_genl_ops,
>+	.n_ops		= ARRAY_SIZE(dpll_genl_ops),
>+	.mcgrps		= dpll_genl_mcgrps,
>+	.n_mcgrps	= ARRAY_SIZE(dpll_genl_mcgrps),
>+	.pre_doit	= dpll_pre_doit,

Have  .parallel_ops   = true,
You have dpll->lock, you don't need genl, to protect you.


>+};
>+
>+int __init dpll_netlink_init(void)
>+{
>+	return genl_register_family(&dpll_gnl_family);
>+}
>+
>+void dpll_netlink_finish(void)
>+{
>+	genl_unregister_family(&dpll_gnl_family);
>+}
>+
>+void __exit dpll_netlink_fini(void)
>+{
>+	dpll_netlink_finish();
>+}
>diff --git a/drivers/dpll/dpll_netlink.h b/drivers/dpll/dpll_netlink.h
>new file mode 100644
>index 000000000000..e2d100f59dd6
>--- /dev/null
>+++ b/drivers/dpll/dpll_netlink.h
>@@ -0,0 +1,7 @@
>+/* SPDX-License-Identifier: GPL-2.0 */
>+/*
>+ *  Copyright (c) 2021 Meta Platforms, Inc. and affiliates
>+ */
>+
>+int __init dpll_netlink_init(void);
>+void dpll_netlink_finish(void);
>diff --git a/include/linux/dpll.h b/include/linux/dpll.h
>new file mode 100644
>index 000000000000..9d49b19d03d9
>--- /dev/null
>+++ b/include/linux/dpll.h
>@@ -0,0 +1,29 @@
>+/* SPDX-License-Identifier: GPL-2.0 */
>+/*
>+ *  Copyright (c) 2021 Meta Platforms, Inc. and affiliates
>+ */
>+
>+#ifndef __DPLL_H__
>+#define __DPLL_H__
>+
>+struct dpll_device;
>+
>+struct dpll_device_ops {
>+	int (*get_status)(struct dpll_device *dpll);
>+	int (*get_temp)(struct dpll_device *dpll);
>+	int (*get_lock_status)(struct dpll_device *dpll);
>+	int (*get_source_type)(struct dpll_device *dpll, int id);
>+	int (*get_source_supported)(struct dpll_device *dpll, int id, int type);
>+	int (*get_output_type)(struct dpll_device *dpll, int id);
>+	int (*get_output_supported)(struct dpll_device *dpll, int id, int type);
>+	int (*set_source_type)(struct dpll_device *dpll, int id, int val);
>+	int (*set_output_type)(struct dpll_device *dpll, int id, int val);

All int should be enums, when they are really enums. Makes things much
nicer and easier to see what's what.



>+};
>+
>+struct dpll_device *dpll_device_alloc(struct dpll_device_ops *ops, const char *name,
>+				      int sources_count, int outputs_count, void *priv);
>+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);
>+#endif
>diff --git a/include/uapi/linux/dpll.h b/include/uapi/linux/dpll.h
>new file mode 100644
>index 000000000000..fcbea5a5e4d6
>--- /dev/null
>+++ b/include/uapi/linux/dpll.h
>@@ -0,0 +1,101 @@
>+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
>+#ifndef _UAPI_LINUX_DPLL_H
>+#define _UAPI_LINUX_DPLL_H
>+
>+#define DPLL_NAME_LENGTH	20
>+
>+/* Adding event notification support elements */
>+#define DPLL_FAMILY_NAME		"dpll"
>+#define DPLL_VERSION			0x01
>+#define DPLL_CONFIG_DEVICE_GROUP_NAME  "config"
>+#define DPLL_CONFIG_SOURCE_GROUP_NAME  "source"
>+#define DPLL_CONFIG_OUTPUT_GROUP_NAME  "output"
>+#define DPLL_MONITOR_GROUP_NAME        "monitor"

What is exactly the reason for multiple multicast groups? Why you don't
use one?


>+
>+#define DPLL_FLAG_SOURCES	1
>+#define DPLL_FLAG_OUTPUTS	2
>+#define DPLL_FLAG_STATUS	4

I think it is more common to use either 0x prefix or (1<<X) expression
But I don't think these flags are needed at all, if you have per-object
messages.


>+
>+/* Attributes of dpll_genl_family */
>+enum dpll_genl_attr {

I don't see need for "genl" here.
Also, it is common to have consistency betwee enum name and members name.
For example:

enum dpll_attr {
	DPLL_ATTR_UNSPEC,
	DPLL_ATTR_DEVICE_ID,

	...
}
This applies to all enums in this file.


>+	DPLLA_UNSPEC,
>+	DPLLA_DEVICE_ID,
>+	DPLLA_DEVICE_NAME,
>+	DPLLA_SOURCE,
>+	DPLLA_SOURCE_ID,

"ID" sounds a bit odd. I think "index" would be more suitable.


>+	DPLLA_SOURCE_TYPE,
>+	DPLLA_SOURCE_SUPPORTED,
>+	DPLLA_OUTPUT,
>+	DPLLA_OUTPUT_ID,
>+	DPLLA_OUTPUT_TYPE,
>+	DPLLA_OUTPUT_SUPPORTED,
>+	DPLLA_STATUS,
>+	DPLLA_TEMP,
>+	DPLLA_LOCK_STATUS,
>+	DPLLA_FLAGS,
>+
>+	__DPLLA_MAX,
>+};
>+#define DPLLA_MAX (__DPLLA_MAX - 1)
>+
>+/* DPLL status provides information of device status */
>+enum dpll_genl_status {
>+	DPLL_STATUS_NONE,
>+	DPLL_STATUS_CALIBRATING,
>+	DPLL_STATUS_LOCKED,
>+
>+	__DPLL_STATUS_MAX,
>+};
>+#define DPLL_STATUS_MAX (__DPLL_STATUS_MAX - 1)
>+
>+/* DPLL signal types used as source or as output */
>+enum dpll_genl_signal_type {
>+	DPLL_TYPE_EXT_1PPS,
>+	DPLL_TYPE_EXT_10MHZ,
>+	DPLL_TYPE_SYNCE_ETH_PORT,
>+	DPLL_TYPE_INT_OSCILLATOR,
>+	DPLL_TYPE_GNSS,
>+
>+	__DPLL_TYPE_MAX,
>+};
>+#define DPLL_TYPE_MAX (__DPLL_TYPE_MAX - 1)
>+
>+/* DPLL lock status provides information of source used to lock the device */
>+enum dpll_genl_lock_status {
>+	DPLL_LOCK_STATUS_UNLOCKED,
>+	DPLL_LOCK_STATUS_EXT_1PPS,
>+	DPLL_LOCK_STATUS_EXT_10MHZ,
>+	DPLL_LOCK_STATUS_SYNCE,
>+	DPLL_LOCK_STATUS_INT_OSCILLATOR,
>+	DPLL_LOCK_STATUS_GNSS,

I find it a bit odd and redundant to have lock status here as a separate
enum. You have a souce selected (either autoselected or manualy
selected). Then the status is either:
"UNLOCKED"
"LOCKED"
"HOLDOVER"

Or something similar. The point is, don't have the "source type" as a
part of lock status.


>+
>+	__DPLL_LOCK_STATUS_MAX,
>+};
>+#define DPLL_LOCK_STATUS_MAX (__DPLL_LOCK_STATUS_MAX - 1)
>+
>+/* Events of dpll_genl_family */
>+enum dpll_genl_event {
>+	DPLL_EVENT_UNSPEC,
>+	DPLL_EVENT_DEVICE_CREATE,		/* DPLL device creation */
>+	DPLL_EVENT_DEVICE_DELETE,		/* DPLL device deletion */
>+	DPLL_EVENT_STATUS_LOCKED,		/* DPLL device locked to source */
>+	DPLL_EVENT_STATUS_UNLOCKED,	/* DPLL device freerun */

Again, redundant I belive. There should be one event,
inside the message there should be and ATTR of the lock state.

Also, I believe there are 2 options:
1) follow the existing netlink models and have:
DPLL_EVENT_DEVICE_NEW
  - sent for new device
  - sent for change with device
DPLL_EVENT_DEVICE_DEL
  - sent for removed device
2)
DPLL_EVENT_DEVICE_NEW
  - sent for new device
DPLL_EVENT_DEVICE_DEL
  - sent for removed device
DPLL_EVENT_DEVICE_CHANGE
  - sent for change with device

Bot options work fine I belive. The point is, you don't want to have
"cmd" per one attr change. Changed the device, attrs are passed in one
message.



>+	DPLL_EVENT_SOURCE_CHANGE,		/* DPLL device source changed */

Similar here, source of device changed, should be just one attr in
device message, see above.


>+	DPLL_EVENT_OUTPUT_CHANGE,		/* DPLL device output changed */


>+
>+	__DPLL_EVENT_MAX,
>+};
>+#define DPLL_EVENT_MAX (__DPLL_EVENT_MAX - 1)
>+
>+/* Commands supported by the dpll_genl_family */
>+enum dpll_genl_cmd {
>+	DPLL_CMD_UNSPEC,
>+	DPLL_CMD_DEVICE_GET,	/* List of DPLL devices id */
>+	DPLL_CMD_SET_SOURCE_TYPE,	/* Set the DPLL device source type */

This is confusing, you select "source", not "type".

Please be consistent in naming:
DPLL_CMD_*_GET/SET

Also, to be consistend with other netlink interfaces, we don't need
cmd per action, rather there should be OBJ_GET (can dump) and OBJ_SET
commands, like this:
   
   DPLL_CMD_DEVICE_GET (can dump all present devices)
   	ATTR_SOURCE_SELECT_MODE (current one)
   	ATTR_SOURCE_INDEX (currect one)
   DPLL_CMD_DEVICE_SET
   	ATTR_SOURCE_INDEX (to set)
   DPLL_CMD_DEVICE_SET
   	ATTR_SOURCE_SELECT_MODE (to set)


>+	DPLL_CMD_SET_OUTPUT_TYPE,	/* Set the DPLL device output type */

Similar to what I suggested for "source", we should
enable to select the OUTPUT, the type should be static. Also instead,
I belive we should have a list of outputs and basically just allow
enable/disable individual outputs:
   DPLL_CMD_OUTPUT_GET (can dump the list of available outputs)
	ATTR_ENABLED (or "CONNECTED" or whatever) of type bool
   DPLL_CMD_OUTPUT_SET
	ATTR_ENABLED (or "CONNECTED" or whatever) of type bool

This is suitable for SyncE for example, when you have multiple netdev ports
that are connected as "outputs", you can enable exactly those you you want.
Example:
# To list the available outputs:
-> DPLL_CMD_OUTPUT_GET - dump
     ATTR_DEVICE_ID X

<- DPLL_CMD_OUTPUT_GET
     ATTR_DEVICE_ID X
     ATTR_OUTPUT_INDEX 0
     ATTR_OUTPUT_TYPE SYNCE_ETH_PORT
     ATTR_OUTPUT_NETDEV_IFINDEX 20
     ATTR_OUTPUT_ENABLED 0
     
     ATTR_DEVICE_ID X
     ATTR_OUTPUT_INDEX 1
     ATTR_OUTPUT_TYPE SYNCE_ETH_PORT
     ATTR_OUTPUT_NETDEV_IFINDEX 30
     ATTR_OUTPUT_ENABLED 0

# Now enable output with index 0
-> DPLL_CMD_OUTPUT_SET
     ATTR_DEVICE_ID X
     ATTR_OUTPUT_INDEX 0
     ATTR_OUTPUT_ENABLED 1


>+
>+	__DPLL_CMD_MAX,
>+};
>+#define DPLL_CMD_MAX (__DPLL_CMD_MAX - 1)
>+
>+#endif /* _UAPI_LINUX_DPLL_H */
>-- 
>2.27.0
>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 1/6] dpll: Add DPLL framework base functions
@ 2022-10-10  9:18     ` Jiri Pirko
  0 siblings, 0 replies; 67+ messages in thread
From: Jiri Pirko @ 2022-10-10  9:18 UTC (permalink / raw)
  To: Vadim Fedorenko
  Cc: Jakub Kicinski, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

Mon, Oct 10, 2022 at 03:17:59AM CEST, vfedorenko@novek.ru wrote:
>From: Vadim Fedorenko <vadfed@fb.com>
>
>DPLL framework is used to represent and configure DPLL devices
>in systems. Each device that has DPLL and can configure sources
>and outputs can use this framework.
>
>Signed-off-by: Vadim Fedorenko <vadfed@fb.com>
>Co-developed-by: Jakub Kicinski <kuba@kernel.org>
>Co-developed-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
>---
> MAINTAINERS                 |   8 +
> drivers/Kconfig             |   2 +
> drivers/Makefile            |   1 +
> drivers/dpll/Kconfig        |   7 +
> drivers/dpll/Makefile       |   7 +
> drivers/dpll/dpll_core.c    | 177 +++++++++++++++
> drivers/dpll/dpll_core.h    |  41 ++++
> drivers/dpll/dpll_netlink.c | 417 ++++++++++++++++++++++++++++++++++++
> drivers/dpll/dpll_netlink.h |   7 +
> include/linux/dpll.h        |  29 +++
> include/uapi/linux/dpll.h   | 101 +++++++++
> 11 files changed, 797 insertions(+)
> create mode 100644 drivers/dpll/Kconfig
> create mode 100644 drivers/dpll/Makefile
> create mode 100644 drivers/dpll/dpll_core.c
> create mode 100644 drivers/dpll/dpll_core.h
> create mode 100644 drivers/dpll/dpll_netlink.c
> create mode 100644 drivers/dpll/dpll_netlink.h
> create mode 100644 include/linux/dpll.h
> create mode 100644 include/uapi/linux/dpll.h
>
>diff --git a/MAINTAINERS b/MAINTAINERS
>index 9ca84cb5ab4a..e2f4fede937f 100644
>--- a/MAINTAINERS
>+++ b/MAINTAINERS
>@@ -6301,6 +6301,14 @@ F:	Documentation/networking/device_drivers/ethernet/freescale/dpaa2/switch-drive
> F:	drivers/net/ethernet/freescale/dpaa2/dpaa2-switch*
> F:	drivers/net/ethernet/freescale/dpaa2/dpsw*
> 
>+DPLL CLOCK SUBSYSTEM
>+M:	Vadim Fedorenko <vadfed@fb.com>
>+L:	netdev@vger.kernel.org
>+S:	Maintained
>+F:	drivers/dpll/*
>+F:	include/net/dpll.h
>+F:	include/uapi/linux/dpll.h
>+
> DRBD DRIVER
> M:	Philipp Reisner <philipp.reisner@linbit.com>
> M:	Lars Ellenberg <lars.ellenberg@linbit.com>
>diff --git a/drivers/Kconfig b/drivers/Kconfig
>index 19ee995bd0ae..a3e00294a995 100644
>--- a/drivers/Kconfig
>+++ b/drivers/Kconfig
>@@ -239,4 +239,6 @@ source "drivers/peci/Kconfig"
> 
> source "drivers/hte/Kconfig"
> 
>+source "drivers/dpll/Kconfig"
>+
> endmenu
>diff --git a/drivers/Makefile b/drivers/Makefile
>index 057857258bfd..78a68f1621cc 100644
>--- a/drivers/Makefile
>+++ b/drivers/Makefile
>@@ -188,3 +188,4 @@ obj-$(CONFIG_COUNTER)		+= counter/
> obj-$(CONFIG_MOST)		+= most/
> obj-$(CONFIG_PECI)		+= peci/
> obj-$(CONFIG_HTE)		+= hte/
>+obj-$(CONFIG_DPLL)		+= dpll/
>diff --git a/drivers/dpll/Kconfig b/drivers/dpll/Kconfig
>new file mode 100644
>index 000000000000..a4cae73f20d3
>--- /dev/null
>+++ b/drivers/dpll/Kconfig
>@@ -0,0 +1,7 @@
>+# SPDX-License-Identifier: GPL-2.0-only
>+#
>+# Generic DPLL drivers configuration
>+#
>+
>+config DPLL
>+  bool
>diff --git a/drivers/dpll/Makefile b/drivers/dpll/Makefile
>new file mode 100644
>index 000000000000..0748c80097e4
>--- /dev/null
>+++ b/drivers/dpll/Makefile
>@@ -0,0 +1,7 @@
>+# SPDX-License-Identifier: GPL-2.0
>+#
>+# Makefile for DPLL drivers.
>+#
>+
>+obj-$(CONFIG_DPLL)          += dpll_sys.o
>+dpll_sys-y                  += dpll_core.o dpll_netlink.o
>diff --git a/drivers/dpll/dpll_core.c b/drivers/dpll/dpll_core.c
>new file mode 100644
>index 000000000000..7fdee145e82c
>--- /dev/null
>+++ b/drivers/dpll/dpll_core.c
>@@ -0,0 +1,177 @@
>+// SPDX-License-Identifier: GPL-2.0
>+/*
>+ *  dpll_core.c - Generic DPLL Management class support.
>+ *
>+ *  Copyright (c) 2021 Meta Platforms, Inc. and affiliates
>+ */
>+
>+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
>+
>+#include <linux/device.h>
>+#include <linux/err.h>
>+#include <linux/slab.h>
>+#include <linux/string.h>
>+
>+#include "dpll_core.h"
>+
>+static DEFINE_MUTEX(dpll_device_xa_lock);
>+static DEFINE_XARRAY_FLAGS(dpll_device_xa, XA_FLAGS_ALLOC);
>+#define DPLL_REGISTERED XA_MARK_1
>+
>+#define ASSERT_DPLL_REGISTERED(d)                                           \
>+	WARN_ON_ONCE(!xa_get_mark(&dpll_device_xa, (d)->id, DPLL_REGISTERED))
>+#define ASSERT_DPLL_NOT_REGISTERED(d)                                      \
>+	WARN_ON_ONCE(xa_get_mark(&dpll_device_xa, (d)->id, DPLL_REGISTERED))
>+
>+
>+int for_each_dpll_device(int id, int (*cb)(struct dpll_device *, void *),
>+			 void *data)

Probably better to avoid this "cb" indirection here.
Perhaps in a similar way devlinks_xa_for_each_registered_get() is done?


>+{
>+	struct dpll_device *dpll;
>+	unsigned long index;
>+	int ret = 0;
>+
>+	mutex_lock(&dpll_device_xa_lock);
>+	xa_for_each_start(&dpll_device_xa, index, dpll, id) {
>+		if (!xa_get_mark(&dpll_device_xa, index, DPLL_REGISTERED))
>+			continue;
>+		ret = cb(dpll, data);
>+		if (ret)
>+			break;
>+	}
>+	mutex_unlock(&dpll_device_xa_lock);
>+
>+	return ret;
>+}
>+
>+struct dpll_device *dpll_device_get_by_id(int id)
>+{
>+	struct dpll_device *dpll = NULL;
>+
>+	if (xa_get_mark(&dpll_device_xa, id, DPLL_REGISTERED))
>+		dpll = xa_load(&dpll_device_xa, id);
>+	return dpll;
>+}
>+
>+struct dpll_device *dpll_device_get_by_name(const char *name)
>+{
>+	struct dpll_device *dpll, *ret = NULL;
>+	unsigned long index;
>+
>+	mutex_lock(&dpll_device_xa_lock);
>+	xa_for_each_marked(&dpll_device_xa, index, dpll, DPLL_REGISTERED) {
>+		if (!strcmp(dev_name(&dpll->dev), name)) {
>+			ret = dpll;
>+			break;
>+		}
>+	}
>+	mutex_unlock(&dpll_device_xa_lock);
>+
>+	return ret;
>+}
>+
>+void *dpll_priv(struct dpll_device *dpll)
>+{
>+	return dpll->priv;
>+}
>+EXPORT_SYMBOL_GPL(dpll_priv);
>+
>+static void dpll_device_release(struct device *dev)
>+{
>+	struct dpll_device *dpll;
>+
>+	dpll = to_dpll_device(dev);
>+
>+	dpll_device_unregister(dpll);
>+	dpll_device_free(dpll);
>+}
>+
>+static struct class dpll_class = {
>+	.name = "dpll",
>+	.dev_release = dpll_device_release,
>+};
>+
>+struct dpll_device *dpll_device_alloc(struct dpll_device_ops *ops, const char *name,
>+				      int sources_count, int outputs_count, void *priv)
>+{
>+	struct dpll_device *dpll;
>+	int ret;
>+
>+	dpll = kzalloc(sizeof(*dpll), GFP_KERNEL);
>+	if (!dpll)
>+		return ERR_PTR(-ENOMEM);
>+
>+	mutex_init(&dpll->lock);
>+	dpll->ops = ops;
>+	dpll->dev.class = &dpll_class;
>+	dpll->sources_count = sources_count;
>+	dpll->outputs_count = outputs_count;
>+
>+	mutex_lock(&dpll_device_xa_lock);
>+	ret = xa_alloc(&dpll_device_xa, &dpll->id, dpll, xa_limit_16b, GFP_KERNEL);
>+	if (ret)
>+		goto error;
>+	dev_set_name(&dpll->dev, "%s%d", name ? name : "dpll", dpll->id);
>+	mutex_unlock(&dpll_device_xa_lock);
>+	dpll->priv = priv;
>+
>+	return dpll;
>+
>+error:
>+	mutex_unlock(&dpll_device_xa_lock);
>+	kfree(dpll);
>+	return ERR_PTR(ret);
>+}
>+EXPORT_SYMBOL_GPL(dpll_device_alloc);
>+
>+void dpll_device_free(struct dpll_device *dpll)
>+{
>+	if (!dpll)
>+		return;
>+
>+	mutex_destroy(&dpll->lock);
>+	kfree(dpll);
>+}
>+EXPORT_SYMBOL_GPL(dpll_device_free);
>+
>+void dpll_device_register(struct dpll_device *dpll)
>+{
>+	ASSERT_DPLL_NOT_REGISTERED(dpll);
>+
>+	mutex_lock(&dpll_device_xa_lock);
>+	xa_set_mark(&dpll_device_xa, dpll->id, DPLL_REGISTERED);
>+	mutex_unlock(&dpll_device_xa_lock);
>+}
>+EXPORT_SYMBOL_GPL(dpll_device_register);
>+
>+void dpll_device_unregister(struct dpll_device *dpll)
>+{
>+	ASSERT_DPLL_REGISTERED(dpll);
>+
>+	mutex_lock(&dpll_device_xa_lock);
>+	xa_erase(&dpll_device_xa, dpll->id);
>+	mutex_unlock(&dpll_device_xa_lock);
>+}
>+EXPORT_SYMBOL_GPL(dpll_device_unregister);
>+
>+static int __init dpll_init(void)
>+{
>+	int ret;
>+
>+	ret = dpll_netlink_init();
>+	if (ret)
>+		goto error;
>+
>+	ret = class_register(&dpll_class);
>+	if (ret)
>+		goto unregister_netlink;
>+
>+	return 0;
>+
>+unregister_netlink:
>+	dpll_netlink_finish();
>+error:
>+	mutex_destroy(&dpll_device_xa_lock);
>+	return ret;
>+}
>+subsys_initcall(dpll_init);
>diff --git a/drivers/dpll/dpll_core.h b/drivers/dpll/dpll_core.h
>new file mode 100644
>index 000000000000..4b6fc9eb228f
>--- /dev/null
>+++ b/drivers/dpll/dpll_core.h
>@@ -0,0 +1,41 @@
>+/* SPDX-License-Identifier: GPL-2.0 */
>+/*
>+ *  Copyright (c) 2021 Meta Platforms, Inc. and affiliates
>+ */
>+
>+#ifndef __DPLL_CORE_H__
>+#define __DPLL_CORE_H__
>+
>+#include <linux/dpll.h>
>+
>+#include "dpll_netlink.h"
>+
>+/**
>+ * struct dpll_device - structure for a DPLL device
>+ * @id:		unique id number for each edvice
>+ * @dev:	&struct device for this dpll device
>+ * @sources_count:	amount of input sources this dpll_device supports
>+ * @outputs_count:	amount of outputs this dpll_device supports
>+ * @ops:	operations this &dpll_device supports
>+ * @lock:	mutex to serialize operations
>+ * @priv:	pointer to private information of owner
>+ */
>+struct dpll_device {
>+	int id;
>+	struct device dev;
>+	int sources_count;
>+	int outputs_count;
>+	struct dpll_device_ops *ops;
>+	struct mutex lock;
>+	void *priv;
>+};
>+
>+#define to_dpll_device(_dev) \
>+	container_of(_dev, struct dpll_device, dev)
>+
>+int for_each_dpll_device(int id, int (*cb)(struct dpll_device *, void *),
>+			  void *data);
>+struct dpll_device *dpll_device_get_by_id(int id);
>+struct dpll_device *dpll_device_get_by_name(const char *name);
>+void dpll_device_unregister(struct dpll_device *dpll);
>+#endif
>diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c
>new file mode 100644
>index 000000000000..31966e0eec3a
>--- /dev/null
>+++ b/drivers/dpll/dpll_netlink.c
>@@ -0,0 +1,417 @@
>+// SPDX-License-Identifier: GPL-2.0
>+/*
>+ * Generic netlink for DPLL management framework
>+ *
>+ * Copyright (c) 2021 Meta Platforms, Inc. and affiliates
>+ *
>+ */
>+#include <linux/module.h>
>+#include <linux/kernel.h>
>+#include <net/genetlink.h>
>+#include "dpll_core.h"
>+
>+#include <uapi/linux/dpll.h>
>+
>+static const struct genl_multicast_group dpll_genl_mcgrps[] = {
>+	{ .name = DPLL_CONFIG_DEVICE_GROUP_NAME, },
>+	{ .name = DPLL_CONFIG_SOURCE_GROUP_NAME, },
>+	{ .name = DPLL_CONFIG_OUTPUT_GROUP_NAME, },
>+	{ .name = DPLL_MONITOR_GROUP_NAME,  },
>+};
>+
>+static const struct nla_policy dpll_genl_get_policy[] = {
>+	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
>+	[DPLLA_DEVICE_NAME]	= { .type = NLA_STRING,
>+				    .len = DPLL_NAME_LENGTH },
>+	[DPLLA_FLAGS]		= { .type = NLA_U32 },
>+};
>+
>+static const struct nla_policy dpll_genl_set_source_policy[] = {
>+	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
>+	[DPLLA_SOURCE_ID]	= { .type = NLA_U32 },
>+	[DPLLA_SOURCE_TYPE]	= { .type = NLA_U32 },
>+};
>+
>+static const struct nla_policy dpll_genl_set_output_policy[] = {
>+	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
>+	[DPLLA_OUTPUT_ID]	= { .type = NLA_U32 },
>+	[DPLLA_OUTPUT_TYPE]	= { .type = NLA_U32 },
>+};
>+
>+struct param {

Namespace prefix please	.


>+	struct netlink_callback *cb;
>+	struct dpll_device *dpll;
>+	struct sk_buff *msg;



>+	int dpll_id;
>+	int dpll_source_id;
>+	int dpll_source_type;
>+	int dpll_output_id;
>+	int dpll_output_type;

I don't see where you use these 5.


>+};
>+
>+struct dpll_dump_ctx {
>+	struct dpll_device *dev;
>+	int flags;
>+	int pos_idx;



>+	int pos_src_idx;
>+	int pos_out_idx;

You don't use these 2.


>+};
>+
>+typedef int (*cb_t)(struct param *);
>+
>+static struct genl_family dpll_gnl_family;
>+
>+static struct dpll_dump_ctx *dpll_dump_context(struct netlink_callback *cb)
>+{
>+	return (struct dpll_dump_ctx *)cb->ctx;
>+}
>+
>+static int __dpll_cmd_device_dump_one(struct dpll_device *dpll,
>+					   struct sk_buff *msg)
>+{
>+	if (nla_put_u32(msg, DPLLA_DEVICE_ID, dpll->id))
>+		return -EMSGSIZE;
>+
>+	if (nla_put_string(msg, DPLLA_DEVICE_NAME, dev_name(&dpll->dev)))
>+		return -EMSGSIZE;
>+
>+	return 0;
>+}
>+
>+static int __dpll_cmd_dump_sources(struct dpll_device *dpll,
>+					   struct sk_buff *msg)
>+{
>+	struct nlattr *src_attr;
>+	int i, ret = 0, type;
>+
>+	for (i = 0; i < dpll->sources_count; i++) {
>+		src_attr = nla_nest_start(msg, DPLLA_SOURCE);
>+		if (!src_attr) {
>+			ret = -EMSGSIZE;
>+			break;
>+		}
>+		type = dpll->ops->get_source_type(dpll, i);
>+		if (nla_put_u32(msg, DPLLA_SOURCE_ID, i) ||
>+		    nla_put_u32(msg, DPLLA_SOURCE_TYPE, type)) {
>+			nla_nest_cancel(msg, src_attr);
>+			ret = -EMSGSIZE;
>+			break;
>+		}
>+		if (dpll->ops->get_source_supported) {
>+			for (type = 0; type <= DPLL_TYPE_MAX; type++) {
>+				ret = dpll->ops->get_source_supported(dpll, i, type);

Okay, this looks weird to me. This implicates that it is possible to
have for example:
source index 0 of type 10 
source index 0 of type 11 
Both possible.

However, from how I understand this, each source if of certain fixed type.
Either it is:
SyncE port
1pps external input (SMA)
10MHZ external input (SMA)
internal oscilator (free-running)
GNSS (GPS)

So for example:
index 0, type: 1pps external input (SMA)
index 1, type: 10MHZ external input (
index 2, type: SyncE port, netdev ifindex: 20
index 3, type: SyncE port, netdev ifindex: 30

So 4 "source" objects, each of different type.
In this case I can imagine that the netlink API might look something
like:
-> DPLL_CMD_SOURCE_GET - dump
     ATTR_DEVICE_ID X

<- DPLL_CMD_SOURCE_GET

     ATTR_DEVICE_ID X
     ATTR_SOURCE_INDEX 0
     ATTR_SOURCE_TYPE EXT_1PPS
     
     ATTR_DEVICE_ID X
     ATTR_SOURCE_INDEX 1
     ATTR_SOURCE_TYPE EXT_10MHZ
     
     ATTR_DEVICE_ID X
     ATTR_SOURCE_INDEX 2
     ATTR_SOURCE_TYPE SYNCE_ETH_PORT
     ATTR_SOURCE_NETDEV_IFINDEX 20

     ATTR_DEVICE_ID X
     ATTR_SOURCE_INDEX 3
     ATTR_SOURCE_TYPE SYNCE_ETH_PORT
     ATTR_SOURCE_NETDEV_IFINDEX 30

You see kernel would dump 4 source objects.



>+				if (ret && nla_put_u32(msg, DPLLA_SOURCE_SUPPORTED, type)) {
>+					ret = -EMSGSIZE;
>+					break;
>+				}
>+			}
>+			ret = 0;
>+		}
>+		nla_nest_end(msg, src_attr);
>+	}
>+
>+	return ret;
>+}
>+
>+static int __dpll_cmd_dump_outputs(struct dpll_device *dpll,
>+					   struct sk_buff *msg)
>+{
>+	struct nlattr *out_attr;
>+	int i, ret = 0, type;
>+
>+	for (i = 0; i < dpll->outputs_count; i++) {
>+		out_attr = nla_nest_start(msg, DPLLA_OUTPUT);
>+		if (!out_attr) {
>+			ret = -EMSGSIZE;
>+			break;
>+		}
>+		type = dpll->ops->get_output_type(dpll, i);
>+		if (nla_put_u32(msg, DPLLA_OUTPUT_ID, i) ||
>+		    nla_put_u32(msg, DPLLA_OUTPUT_TYPE, type)) {
>+			nla_nest_cancel(msg, out_attr);
>+			ret = -EMSGSIZE;
>+			break;
>+		}
>+		if (dpll->ops->get_output_supported) {
>+			for (type = 0; type <= DPLL_TYPE_MAX; type++) {
>+				ret = dpll->ops->get_output_supported(dpll, i, type);
>+				if (ret && nla_put_u32(msg, DPLLA_OUTPUT_SUPPORTED, type)) {

This I believe is similar to sources, see my comment above.

I believe we should have separate commands to GET and SET outputs and
sources. That would make the object separation clear and will also help
event model. See below I suggestion how output netlink API may look
like (comment in header file near enum dpll_genl_cmd definition).


>+					ret = -EMSGSIZE;
>+					break;
>+				}
>+			}
>+			ret = 0;
>+		}
>+		nla_nest_end(msg, out_attr);
>+	}
>+
>+	return ret;
>+}
>+
>+static int __dpll_cmd_dump_status(struct dpll_device *dpll,
>+					   struct sk_buff *msg)
>+{
>+	int ret;
>+
>+	if (dpll->ops->get_status) {
>+		ret = dpll->ops->get_status(dpll);
>+		if (nla_put_u32(msg, DPLLA_STATUS, ret))
>+			return -EMSGSIZE;
>+	}
>+
>+	if (dpll->ops->get_temp) {
>+		ret = dpll->ops->get_temp(dpll);
>+		if (nla_put_u32(msg, DPLLA_TEMP, ret))
>+			return -EMSGSIZE;
>+	}
>+
>+	if (dpll->ops->get_lock_status) {
>+		ret = dpll->ops->get_lock_status(dpll);
>+		if (nla_put_u32(msg, DPLLA_LOCK_STATUS, ret))
>+			return -EMSGSIZE;
>+	}
>+
>+	return 0;
>+}
>+
>+static int
>+dpll_device_dump_one(struct dpll_device *dpll, struct sk_buff *msg,
>+		     u32 portid, u32 seq, int flags)
>+{
>+	struct nlattr *hdr;
>+	int ret;
>+
>+	hdr = genlmsg_put(msg, portid, seq, &dpll_gnl_family, 0,
>+			  DPLL_CMD_DEVICE_GET);
>+	if (!hdr)
>+		return -EMSGSIZE;
>+
>+	mutex_lock(&dpll->lock);
>+	ret = __dpll_cmd_device_dump_one(dpll, msg);
>+	if (ret)
>+		goto out_unlock;
>+
>+	if (flags & DPLL_FLAG_SOURCES && dpll->ops->get_source_type) {
>+		ret = __dpll_cmd_dump_sources(dpll, msg);
>+		if (ret)
>+			goto out_unlock;
>+	}
>+
>+	if (flags & DPLL_FLAG_OUTPUTS && dpll->ops->get_output_type) {
>+		ret = __dpll_cmd_dump_outputs(dpll, msg);
>+		if (ret)
>+			goto out_unlock;
>+	}
>+
>+	if (flags & DPLL_FLAG_STATUS) {
>+		ret = __dpll_cmd_dump_status(dpll, msg);
>+		if (ret)
>+			goto out_unlock;
>+	}
>+	mutex_unlock(&dpll->lock);
>+	genlmsg_end(msg, hdr);
>+
>+	return 0;
>+
>+out_unlock:
>+	mutex_unlock(&dpll->lock);
>+	genlmsg_cancel(msg, hdr);
>+
>+	return ret;
>+}
>+
>+static int dpll_genl_cmd_set_source(struct sk_buff *skb, struct genl_info *info)
>+{
>+	struct dpll_device *dpll = info->user_ptr[0];
>+	struct nlattr **attrs = info->attrs;
>+	int ret = 0, src_id, type;

Enums.

>+
>+	if (!attrs[DPLLA_SOURCE_ID] ||
>+	    !attrs[DPLLA_SOURCE_TYPE])
>+		return -EINVAL;
>+
>+	if (!dpll->ops->set_source_type)
>+		return -EOPNOTSUPP;
>+
>+	src_id = nla_get_u32(attrs[DPLLA_SOURCE_ID]);
>+	type = nla_get_u32(attrs[DPLLA_SOURCE_TYPE]);


This looks odd to me. The user should just pass the index of source to
select. Type should be static, and non-changeable.


>+
>+	mutex_lock(&dpll->lock);
>+	ret = dpll->ops->set_source_type(dpll, src_id, type);
>+	mutex_unlock(&dpll->lock);
>+
>+	return ret;
>+}
>+
>+static int dpll_genl_cmd_set_output(struct sk_buff *skb, struct genl_info *info)
>+{
>+	struct dpll_device *dpll = info->user_ptr[0];
>+	struct nlattr **attrs = info->attrs;
>+	int ret = 0, out_id, type;

Enums.


>+
>+	if (!attrs[DPLLA_OUTPUT_ID] ||
>+	    !attrs[DPLLA_OUTPUT_TYPE])
>+		return -EINVAL;
>+
>+	if (!dpll->ops->set_output_type)
>+		return -EOPNOTSUPP;
>+
>+	out_id = nla_get_u32(attrs[DPLLA_OUTPUT_ID]);
>+	type = nla_get_u32(attrs[DPLLA_OUTPUT_TYPE]);

Same here, passing type here looks wrong.



>+
>+	mutex_lock(&dpll->lock);
>+	ret = dpll->ops->set_output_type(dpll, out_id, type);
>+	mutex_unlock(&dpll->lock);
>+
>+	return ret;
>+}
>+
>+static int dpll_device_loop_cb(struct dpll_device *dpll, void *data)
>+{
>+	struct dpll_dump_ctx *ctx;
>+	struct param *p = (struct param *)data;
>+
>+	ctx = dpll_dump_context(p->cb);
>+
>+	ctx->pos_idx = dpll->id;
>+
>+	return dpll_device_dump_one(dpll, p->msg, 0, 0, ctx->flags);
>+}
>+
>+static int
>+dpll_cmd_device_dump(struct sk_buff *skb, struct netlink_callback *cb)
>+{
>+	struct dpll_dump_ctx *ctx = dpll_dump_context(cb);
>+	struct param p = { .cb = cb, .msg = skb };
>+
>+	return for_each_dpll_device(ctx->pos_idx, dpll_device_loop_cb, &p);
>+}
>+
>+static int
>+dpll_genl_cmd_device_get_id(struct sk_buff *skb, struct genl_info *info)

Just "get", no "id" here.


>+{
>+	struct dpll_device *dpll = info->user_ptr[0];
>+	struct nlattr **attrs = info->attrs;
>+	struct sk_buff *msg;
>+	int flags = 0;
>+	int ret;
>+
>+	if (attrs[DPLLA_FLAGS])
>+		flags = nla_get_u32(attrs[DPLLA_FLAGS]);
>+
>+	msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
>+	if (!msg)
>+		return -ENOMEM;
>+
>+	ret = dpll_device_dump_one(dpll, msg, info->snd_portid, info->snd_seq,
>+				   flags);
>+	if (ret)
>+		goto out_free_msg;
>+
>+	return genlmsg_reply(msg, info);
>+
>+out_free_msg:
>+	nlmsg_free(msg);
>+	return ret;
>+
>+}
>+
>+static int dpll_genl_cmd_start(struct netlink_callback *cb)
>+{
>+	const struct genl_dumpit_info *info = genl_dumpit_info(cb);
>+	struct dpll_dump_ctx *ctx = dpll_dump_context(cb);
>+
>+	ctx->dev = NULL;
>+	if (info->attrs[DPLLA_FLAGS])
>+		ctx->flags = nla_get_u32(info->attrs[DPLLA_FLAGS]);
>+	else
>+		ctx->flags = 0;
>+	ctx->pos_idx = 0;
>+	ctx->pos_src_idx = 0;
>+	ctx->pos_out_idx = 0;
>+	return 0;
>+}
>+
>+static int dpll_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
>+						 struct genl_info *info)
>+{
>+	struct dpll_device *dpll_id = NULL, *dpll_name = NULL;
>+
>+	if (!info->attrs[DPLLA_DEVICE_ID] &&
>+	    !info->attrs[DPLLA_DEVICE_NAME])
>+		return -EINVAL;
>+
>+	if (info->attrs[DPLLA_DEVICE_ID]) {
>+		u32 id = nla_get_u32(info->attrs[DPLLA_DEVICE_ID]);
>+
>+		dpll_id = dpll_device_get_by_id(id);
>+		if (!dpll_id)
>+			return -ENODEV;
>+		info->user_ptr[0] = dpll_id;

struct dpll_device *dpll should be stored here.


>+	}
>+	if (info->attrs[DPLLA_DEVICE_NAME]) {

You define new API, have one clear handle for devices. Either name or
ID. Having both is messy.


>+		const char *name = nla_data(info->attrs[DPLLA_DEVICE_NAME]);
>+
>+		dpll_name = dpll_device_get_by_name(name);
>+		if (!dpll_name)
>+			return -ENODEV;
>+
>+		if (dpll_id && dpll_name != dpll_id)
>+			return -EINVAL;
>+		info->user_ptr[0] = dpll_name;

struct dpll_device *dpll should be stored here.



>+	}
>+
>+	return 0;
>+}
>+
>+static const struct genl_ops dpll_genl_ops[] = {
>+	{
>+		.cmd	= DPLL_CMD_DEVICE_GET,
>+		.flags  = GENL_UNS_ADMIN_PERM,
>+		.start	= dpll_genl_cmd_start,
>+		.dumpit	= dpll_cmd_device_dump,
>+		.doit	= dpll_genl_cmd_device_get_id,
>+		.policy	= dpll_genl_get_policy,
>+		.maxattr = ARRAY_SIZE(dpll_genl_get_policy) - 1,
>+	},
>+	{
>+		.cmd	= DPLL_CMD_SET_SOURCE_TYPE,
>+		.flags	= GENL_UNS_ADMIN_PERM,
>+		.doit	= dpll_genl_cmd_set_source,
>+		.policy	= dpll_genl_set_source_policy,
>+		.maxattr = ARRAY_SIZE(dpll_genl_set_source_policy) - 1,
>+	},
>+	{
>+		.cmd	= DPLL_CMD_SET_OUTPUT_TYPE,
>+		.flags	= GENL_UNS_ADMIN_PERM,
>+		.doit	= dpll_genl_cmd_set_output,
>+		.policy	= dpll_genl_set_output_policy,
>+		.maxattr = ARRAY_SIZE(dpll_genl_set_output_policy) - 1,
>+	},
>+};
>+
>+static struct genl_family dpll_gnl_family __ro_after_init = {
>+	.hdrsize	= 0,
>+	.name		= DPLL_FAMILY_NAME,
>+	.version	= DPLL_VERSION,
>+	.ops		= dpll_genl_ops,
>+	.n_ops		= ARRAY_SIZE(dpll_genl_ops),
>+	.mcgrps		= dpll_genl_mcgrps,
>+	.n_mcgrps	= ARRAY_SIZE(dpll_genl_mcgrps),
>+	.pre_doit	= dpll_pre_doit,

Have  .parallel_ops   = true,
You have dpll->lock, you don't need genl, to protect you.


>+};
>+
>+int __init dpll_netlink_init(void)
>+{
>+	return genl_register_family(&dpll_gnl_family);
>+}
>+
>+void dpll_netlink_finish(void)
>+{
>+	genl_unregister_family(&dpll_gnl_family);
>+}
>+
>+void __exit dpll_netlink_fini(void)
>+{
>+	dpll_netlink_finish();
>+}
>diff --git a/drivers/dpll/dpll_netlink.h b/drivers/dpll/dpll_netlink.h
>new file mode 100644
>index 000000000000..e2d100f59dd6
>--- /dev/null
>+++ b/drivers/dpll/dpll_netlink.h
>@@ -0,0 +1,7 @@
>+/* SPDX-License-Identifier: GPL-2.0 */
>+/*
>+ *  Copyright (c) 2021 Meta Platforms, Inc. and affiliates
>+ */
>+
>+int __init dpll_netlink_init(void);
>+void dpll_netlink_finish(void);
>diff --git a/include/linux/dpll.h b/include/linux/dpll.h
>new file mode 100644
>index 000000000000..9d49b19d03d9
>--- /dev/null
>+++ b/include/linux/dpll.h
>@@ -0,0 +1,29 @@
>+/* SPDX-License-Identifier: GPL-2.0 */
>+/*
>+ *  Copyright (c) 2021 Meta Platforms, Inc. and affiliates
>+ */
>+
>+#ifndef __DPLL_H__
>+#define __DPLL_H__
>+
>+struct dpll_device;
>+
>+struct dpll_device_ops {
>+	int (*get_status)(struct dpll_device *dpll);
>+	int (*get_temp)(struct dpll_device *dpll);
>+	int (*get_lock_status)(struct dpll_device *dpll);
>+	int (*get_source_type)(struct dpll_device *dpll, int id);
>+	int (*get_source_supported)(struct dpll_device *dpll, int id, int type);
>+	int (*get_output_type)(struct dpll_device *dpll, int id);
>+	int (*get_output_supported)(struct dpll_device *dpll, int id, int type);
>+	int (*set_source_type)(struct dpll_device *dpll, int id, int val);
>+	int (*set_output_type)(struct dpll_device *dpll, int id, int val);

All int should be enums, when they are really enums. Makes things much
nicer and easier to see what's what.



>+};
>+
>+struct dpll_device *dpll_device_alloc(struct dpll_device_ops *ops, const char *name,
>+				      int sources_count, int outputs_count, void *priv);
>+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);
>+#endif
>diff --git a/include/uapi/linux/dpll.h b/include/uapi/linux/dpll.h
>new file mode 100644
>index 000000000000..fcbea5a5e4d6
>--- /dev/null
>+++ b/include/uapi/linux/dpll.h
>@@ -0,0 +1,101 @@
>+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
>+#ifndef _UAPI_LINUX_DPLL_H
>+#define _UAPI_LINUX_DPLL_H
>+
>+#define DPLL_NAME_LENGTH	20
>+
>+/* Adding event notification support elements */
>+#define DPLL_FAMILY_NAME		"dpll"
>+#define DPLL_VERSION			0x01
>+#define DPLL_CONFIG_DEVICE_GROUP_NAME  "config"
>+#define DPLL_CONFIG_SOURCE_GROUP_NAME  "source"
>+#define DPLL_CONFIG_OUTPUT_GROUP_NAME  "output"
>+#define DPLL_MONITOR_GROUP_NAME        "monitor"

What is exactly the reason for multiple multicast groups? Why you don't
use one?


>+
>+#define DPLL_FLAG_SOURCES	1
>+#define DPLL_FLAG_OUTPUTS	2
>+#define DPLL_FLAG_STATUS	4

I think it is more common to use either 0x prefix or (1<<X) expression
But I don't think these flags are needed at all, if you have per-object
messages.


>+
>+/* Attributes of dpll_genl_family */
>+enum dpll_genl_attr {

I don't see need for "genl" here.
Also, it is common to have consistency betwee enum name and members name.
For example:

enum dpll_attr {
	DPLL_ATTR_UNSPEC,
	DPLL_ATTR_DEVICE_ID,

	...
}
This applies to all enums in this file.


>+	DPLLA_UNSPEC,
>+	DPLLA_DEVICE_ID,
>+	DPLLA_DEVICE_NAME,
>+	DPLLA_SOURCE,
>+	DPLLA_SOURCE_ID,

"ID" sounds a bit odd. I think "index" would be more suitable.


>+	DPLLA_SOURCE_TYPE,
>+	DPLLA_SOURCE_SUPPORTED,
>+	DPLLA_OUTPUT,
>+	DPLLA_OUTPUT_ID,
>+	DPLLA_OUTPUT_TYPE,
>+	DPLLA_OUTPUT_SUPPORTED,
>+	DPLLA_STATUS,
>+	DPLLA_TEMP,
>+	DPLLA_LOCK_STATUS,
>+	DPLLA_FLAGS,
>+
>+	__DPLLA_MAX,
>+};
>+#define DPLLA_MAX (__DPLLA_MAX - 1)
>+
>+/* DPLL status provides information of device status */
>+enum dpll_genl_status {
>+	DPLL_STATUS_NONE,
>+	DPLL_STATUS_CALIBRATING,
>+	DPLL_STATUS_LOCKED,
>+
>+	__DPLL_STATUS_MAX,
>+};
>+#define DPLL_STATUS_MAX (__DPLL_STATUS_MAX - 1)
>+
>+/* DPLL signal types used as source or as output */
>+enum dpll_genl_signal_type {
>+	DPLL_TYPE_EXT_1PPS,
>+	DPLL_TYPE_EXT_10MHZ,
>+	DPLL_TYPE_SYNCE_ETH_PORT,
>+	DPLL_TYPE_INT_OSCILLATOR,
>+	DPLL_TYPE_GNSS,
>+
>+	__DPLL_TYPE_MAX,
>+};
>+#define DPLL_TYPE_MAX (__DPLL_TYPE_MAX - 1)
>+
>+/* DPLL lock status provides information of source used to lock the device */
>+enum dpll_genl_lock_status {
>+	DPLL_LOCK_STATUS_UNLOCKED,
>+	DPLL_LOCK_STATUS_EXT_1PPS,
>+	DPLL_LOCK_STATUS_EXT_10MHZ,
>+	DPLL_LOCK_STATUS_SYNCE,
>+	DPLL_LOCK_STATUS_INT_OSCILLATOR,
>+	DPLL_LOCK_STATUS_GNSS,

I find it a bit odd and redundant to have lock status here as a separate
enum. You have a souce selected (either autoselected or manualy
selected). Then the status is either:
"UNLOCKED"
"LOCKED"
"HOLDOVER"

Or something similar. The point is, don't have the "source type" as a
part of lock status.


>+
>+	__DPLL_LOCK_STATUS_MAX,
>+};
>+#define DPLL_LOCK_STATUS_MAX (__DPLL_LOCK_STATUS_MAX - 1)
>+
>+/* Events of dpll_genl_family */
>+enum dpll_genl_event {
>+	DPLL_EVENT_UNSPEC,
>+	DPLL_EVENT_DEVICE_CREATE,		/* DPLL device creation */
>+	DPLL_EVENT_DEVICE_DELETE,		/* DPLL device deletion */
>+	DPLL_EVENT_STATUS_LOCKED,		/* DPLL device locked to source */
>+	DPLL_EVENT_STATUS_UNLOCKED,	/* DPLL device freerun */

Again, redundant I belive. There should be one event,
inside the message there should be and ATTR of the lock state.

Also, I believe there are 2 options:
1) follow the existing netlink models and have:
DPLL_EVENT_DEVICE_NEW
  - sent for new device
  - sent for change with device
DPLL_EVENT_DEVICE_DEL
  - sent for removed device
2)
DPLL_EVENT_DEVICE_NEW
  - sent for new device
DPLL_EVENT_DEVICE_DEL
  - sent for removed device
DPLL_EVENT_DEVICE_CHANGE
  - sent for change with device

Bot options work fine I belive. The point is, you don't want to have
"cmd" per one attr change. Changed the device, attrs are passed in one
message.



>+	DPLL_EVENT_SOURCE_CHANGE,		/* DPLL device source changed */

Similar here, source of device changed, should be just one attr in
device message, see above.


>+	DPLL_EVENT_OUTPUT_CHANGE,		/* DPLL device output changed */


>+
>+	__DPLL_EVENT_MAX,
>+};
>+#define DPLL_EVENT_MAX (__DPLL_EVENT_MAX - 1)
>+
>+/* Commands supported by the dpll_genl_family */
>+enum dpll_genl_cmd {
>+	DPLL_CMD_UNSPEC,
>+	DPLL_CMD_DEVICE_GET,	/* List of DPLL devices id */
>+	DPLL_CMD_SET_SOURCE_TYPE,	/* Set the DPLL device source type */

This is confusing, you select "source", not "type".

Please be consistent in naming:
DPLL_CMD_*_GET/SET

Also, to be consistend with other netlink interfaces, we don't need
cmd per action, rather there should be OBJ_GET (can dump) and OBJ_SET
commands, like this:
   
   DPLL_CMD_DEVICE_GET (can dump all present devices)
   	ATTR_SOURCE_SELECT_MODE (current one)
   	ATTR_SOURCE_INDEX (currect one)
   DPLL_CMD_DEVICE_SET
   	ATTR_SOURCE_INDEX (to set)
   DPLL_CMD_DEVICE_SET
   	ATTR_SOURCE_SELECT_MODE (to set)


>+	DPLL_CMD_SET_OUTPUT_TYPE,	/* Set the DPLL device output type */

Similar to what I suggested for "source", we should
enable to select the OUTPUT, the type should be static. Also instead,
I belive we should have a list of outputs and basically just allow
enable/disable individual outputs:
   DPLL_CMD_OUTPUT_GET (can dump the list of available outputs)
	ATTR_ENABLED (or "CONNECTED" or whatever) of type bool
   DPLL_CMD_OUTPUT_SET
	ATTR_ENABLED (or "CONNECTED" or whatever) of type bool

This is suitable for SyncE for example, when you have multiple netdev ports
that are connected as "outputs", you can enable exactly those you you want.
Example:
# To list the available outputs:
-> DPLL_CMD_OUTPUT_GET - dump
     ATTR_DEVICE_ID X

<- DPLL_CMD_OUTPUT_GET
     ATTR_DEVICE_ID X
     ATTR_OUTPUT_INDEX 0
     ATTR_OUTPUT_TYPE SYNCE_ETH_PORT
     ATTR_OUTPUT_NETDEV_IFINDEX 20
     ATTR_OUTPUT_ENABLED 0
     
     ATTR_DEVICE_ID X
     ATTR_OUTPUT_INDEX 1
     ATTR_OUTPUT_TYPE SYNCE_ETH_PORT
     ATTR_OUTPUT_NETDEV_IFINDEX 30
     ATTR_OUTPUT_ENABLED 0

# Now enable output with index 0
-> DPLL_CMD_OUTPUT_SET
     ATTR_DEVICE_ID X
     ATTR_OUTPUT_INDEX 0
     ATTR_OUTPUT_ENABLED 1


>+
>+	__DPLL_CMD_MAX,
>+};
>+#define DPLL_CMD_MAX (__DPLL_CMD_MAX - 1)
>+
>+#endif /* _UAPI_LINUX_DPLL_H */
>-- 
>2.27.0
>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 4/6] dpll: get source/output name
  2022-10-10  1:18   ` Vadim Fedorenko
@ 2022-10-10  9:45     ` Jiri Pirko
  -1 siblings, 0 replies; 67+ messages in thread
From: Jiri Pirko @ 2022-10-10  9:45 UTC (permalink / raw)
  To: Vadim Fedorenko
  Cc: Jakub Kicinski, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

Mon, Oct 10, 2022 at 03:18:02AM CEST, vfedorenko@novek.ru wrote:
>From: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
>
>Dump names of sources and outputs in response to DPLL_CMD_DEVICE_GET dump
>request.
>
>Signed-off-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
>---
> drivers/dpll/dpll_netlink.c | 24 ++++++++++++++++++++++++
> include/linux/dpll.h        |  2 ++
> include/uapi/linux/dpll.h   |  2 ++
> 3 files changed, 28 insertions(+)
>
>diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c
>index a5779871537a..e3604c10b59e 100644
>--- a/drivers/dpll/dpll_netlink.c
>+++ b/drivers/dpll/dpll_netlink.c
>@@ -31,12 +31,16 @@ static const struct nla_policy dpll_genl_set_source_policy[] = {
> 	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
> 	[DPLLA_SOURCE_ID]	= { .type = NLA_U32 },
> 	[DPLLA_SOURCE_TYPE]	= { .type = NLA_U32 },
>+	[DPLLA_SOURCE_NAME]	= { .type = NLA_STRING,
>+				    .len = DPLL_NAME_LENGTH },
> };
> 
> static const struct nla_policy dpll_genl_set_output_policy[] = {
> 	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
> 	[DPLLA_OUTPUT_ID]	= { .type = NLA_U32 },
> 	[DPLLA_OUTPUT_TYPE]	= { .type = NLA_U32 },
>+	[DPLLA_OUTPUT_NAME]	= { .type = NLA_STRING,
>+				    .len = DPLL_NAME_LENGTH },
> };
> 
> static const struct nla_policy dpll_genl_set_src_select_mode_policy[] = {
>@@ -100,6 +104,7 @@ static int __dpll_cmd_dump_sources(struct dpll_device *dpll,
> {
> 	int i, ret = 0, type, prio;
> 	struct nlattr *src_attr;
>+	const char *name;
> 
> 	for (i = 0; i < dpll->sources_count; i++) {
> 		src_attr = nla_nest_start(msg, DPLLA_SOURCE);
>@@ -132,6 +137,15 @@ static int __dpll_cmd_dump_sources(struct dpll_device *dpll,
> 				break;
> 			}
> 		}
>+		if (dpll->ops->get_source_name) {
>+			name = dpll->ops->get_source_name(dpll, i);
>+			if (name && nla_put_string(msg, DPLLA_SOURCE_NAME,
>+						   name)) {
>+				nla_nest_cancel(msg, src_attr);
>+				ret = -EMSGSIZE;
>+				break;
>+			}
>+		}
> 		nla_nest_end(msg, src_attr);
> 	}
> 
>@@ -143,6 +157,7 @@ static int __dpll_cmd_dump_outputs(struct dpll_device *dpll,
> {
> 	struct nlattr *out_attr;
> 	int i, ret = 0, type;
>+	const char *name;
> 
> 	for (i = 0; i < dpll->outputs_count; i++) {
> 		out_attr = nla_nest_start(msg, DPLLA_OUTPUT);
>@@ -167,6 +182,15 @@ static int __dpll_cmd_dump_outputs(struct dpll_device *dpll,
> 			}
> 			ret = 0;
> 		}
>+		if (dpll->ops->get_output_name) {
>+			name = dpll->ops->get_output_name(dpll, i);
>+			if (name && nla_put_string(msg, DPLLA_OUTPUT_NAME,
>+						   name)) {
>+				nla_nest_cancel(msg, out_attr);
>+				ret = -EMSGSIZE;
>+				break;
>+			}
>+		}
> 		nla_nest_end(msg, out_attr);
> 	}
> 
>diff --git a/include/linux/dpll.h b/include/linux/dpll.h
>index 3fe957a06b90..2f4964dc28f0 100644
>--- a/include/linux/dpll.h
>+++ b/include/linux/dpll.h
>@@ -23,6 +23,8 @@ struct dpll_device_ops {
> 	int (*set_output_type)(struct dpll_device *dpll, int id, int val);
> 	int (*set_source_select_mode)(struct dpll_device *dpll, int mode);
> 	int (*set_source_prio)(struct dpll_device *dpll, int id, int prio);
>+	const char *(*get_source_name)(struct dpll_device *dpll, int id);
>+	const char *(*get_output_name)(struct dpll_device *dpll, int id);

Hmm, why you exactly need the name for?


> };
> 
> struct dpll_device *dpll_device_alloc(struct dpll_device_ops *ops, const char *name,
>diff --git a/include/uapi/linux/dpll.h b/include/uapi/linux/dpll.h
>index f6b674e5cf01..8782d3425aae 100644
>--- a/include/uapi/linux/dpll.h
>+++ b/include/uapi/linux/dpll.h
>@@ -26,11 +26,13 @@ enum dpll_genl_attr {
> 	DPLLA_SOURCE,
> 	DPLLA_SOURCE_ID,
> 	DPLLA_SOURCE_TYPE,
>+	DPLLA_SOURCE_NAME,
> 	DPLLA_SOURCE_SUPPORTED,
> 	DPLLA_SOURCE_PRIO,
> 	DPLLA_OUTPUT,
> 	DPLLA_OUTPUT_ID,
> 	DPLLA_OUTPUT_TYPE,
>+	DPLLA_OUTPUT_NAME,
> 	DPLLA_OUTPUT_SUPPORTED,
> 	DPLLA_STATUS,
> 	DPLLA_TEMP,
>-- 
>2.27.0
>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 4/6] dpll: get source/output name
@ 2022-10-10  9:45     ` Jiri Pirko
  0 siblings, 0 replies; 67+ messages in thread
From: Jiri Pirko @ 2022-10-10  9:45 UTC (permalink / raw)
  To: Vadim Fedorenko
  Cc: Jakub Kicinski, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

Mon, Oct 10, 2022 at 03:18:02AM CEST, vfedorenko@novek.ru wrote:
>From: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
>
>Dump names of sources and outputs in response to DPLL_CMD_DEVICE_GET dump
>request.
>
>Signed-off-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
>---
> drivers/dpll/dpll_netlink.c | 24 ++++++++++++++++++++++++
> include/linux/dpll.h        |  2 ++
> include/uapi/linux/dpll.h   |  2 ++
> 3 files changed, 28 insertions(+)
>
>diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c
>index a5779871537a..e3604c10b59e 100644
>--- a/drivers/dpll/dpll_netlink.c
>+++ b/drivers/dpll/dpll_netlink.c
>@@ -31,12 +31,16 @@ static const struct nla_policy dpll_genl_set_source_policy[] = {
> 	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
> 	[DPLLA_SOURCE_ID]	= { .type = NLA_U32 },
> 	[DPLLA_SOURCE_TYPE]	= { .type = NLA_U32 },
>+	[DPLLA_SOURCE_NAME]	= { .type = NLA_STRING,
>+				    .len = DPLL_NAME_LENGTH },
> };
> 
> static const struct nla_policy dpll_genl_set_output_policy[] = {
> 	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
> 	[DPLLA_OUTPUT_ID]	= { .type = NLA_U32 },
> 	[DPLLA_OUTPUT_TYPE]	= { .type = NLA_U32 },
>+	[DPLLA_OUTPUT_NAME]	= { .type = NLA_STRING,
>+				    .len = DPLL_NAME_LENGTH },
> };
> 
> static const struct nla_policy dpll_genl_set_src_select_mode_policy[] = {
>@@ -100,6 +104,7 @@ static int __dpll_cmd_dump_sources(struct dpll_device *dpll,
> {
> 	int i, ret = 0, type, prio;
> 	struct nlattr *src_attr;
>+	const char *name;
> 
> 	for (i = 0; i < dpll->sources_count; i++) {
> 		src_attr = nla_nest_start(msg, DPLLA_SOURCE);
>@@ -132,6 +137,15 @@ static int __dpll_cmd_dump_sources(struct dpll_device *dpll,
> 				break;
> 			}
> 		}
>+		if (dpll->ops->get_source_name) {
>+			name = dpll->ops->get_source_name(dpll, i);
>+			if (name && nla_put_string(msg, DPLLA_SOURCE_NAME,
>+						   name)) {
>+				nla_nest_cancel(msg, src_attr);
>+				ret = -EMSGSIZE;
>+				break;
>+			}
>+		}
> 		nla_nest_end(msg, src_attr);
> 	}
> 
>@@ -143,6 +157,7 @@ static int __dpll_cmd_dump_outputs(struct dpll_device *dpll,
> {
> 	struct nlattr *out_attr;
> 	int i, ret = 0, type;
>+	const char *name;
> 
> 	for (i = 0; i < dpll->outputs_count; i++) {
> 		out_attr = nla_nest_start(msg, DPLLA_OUTPUT);
>@@ -167,6 +182,15 @@ static int __dpll_cmd_dump_outputs(struct dpll_device *dpll,
> 			}
> 			ret = 0;
> 		}
>+		if (dpll->ops->get_output_name) {
>+			name = dpll->ops->get_output_name(dpll, i);
>+			if (name && nla_put_string(msg, DPLLA_OUTPUT_NAME,
>+						   name)) {
>+				nla_nest_cancel(msg, out_attr);
>+				ret = -EMSGSIZE;
>+				break;
>+			}
>+		}
> 		nla_nest_end(msg, out_attr);
> 	}
> 
>diff --git a/include/linux/dpll.h b/include/linux/dpll.h
>index 3fe957a06b90..2f4964dc28f0 100644
>--- a/include/linux/dpll.h
>+++ b/include/linux/dpll.h
>@@ -23,6 +23,8 @@ struct dpll_device_ops {
> 	int (*set_output_type)(struct dpll_device *dpll, int id, int val);
> 	int (*set_source_select_mode)(struct dpll_device *dpll, int mode);
> 	int (*set_source_prio)(struct dpll_device *dpll, int id, int prio);
>+	const char *(*get_source_name)(struct dpll_device *dpll, int id);
>+	const char *(*get_output_name)(struct dpll_device *dpll, int id);

Hmm, why you exactly need the name for?


> };
> 
> struct dpll_device *dpll_device_alloc(struct dpll_device_ops *ops, const char *name,
>diff --git a/include/uapi/linux/dpll.h b/include/uapi/linux/dpll.h
>index f6b674e5cf01..8782d3425aae 100644
>--- a/include/uapi/linux/dpll.h
>+++ b/include/uapi/linux/dpll.h
>@@ -26,11 +26,13 @@ enum dpll_genl_attr {
> 	DPLLA_SOURCE,
> 	DPLLA_SOURCE_ID,
> 	DPLLA_SOURCE_TYPE,
>+	DPLLA_SOURCE_NAME,
> 	DPLLA_SOURCE_SUPPORTED,
> 	DPLLA_SOURCE_PRIO,
> 	DPLLA_OUTPUT,
> 	DPLLA_OUTPUT_ID,
> 	DPLLA_OUTPUT_TYPE,
>+	DPLLA_OUTPUT_NAME,
> 	DPLLA_OUTPUT_SUPPORTED,
> 	DPLLA_STATUS,
> 	DPLLA_TEMP,
>-- 
>2.27.0
>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 3/6] dpll: add support for source selection modes
  2022-10-10  1:18   ` Vadim Fedorenko
@ 2022-10-10 14:13     ` Jiri Pirko
  -1 siblings, 0 replies; 67+ messages in thread
From: Jiri Pirko @ 2022-10-10 14:13 UTC (permalink / raw)
  To: Vadim Fedorenko
  Cc: Jakub Kicinski, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

Mon, Oct 10, 2022 at 03:18:01AM CEST, vfedorenko@novek.ru wrote:
>From: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
>
>Allow to configure dpll device for different source selection modes.
>Allow to configure priority of a sources for autmoatic selection mode.
>
>Signed-off-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
>---
> drivers/dpll/dpll_netlink.c | 170 ++++++++++++++++++++++++++++++++++--
> drivers/dpll/dpll_netlink.h |   2 +
> include/linux/dpll.h        |   7 ++
> include/uapi/linux/dpll.h   |  22 ++++-
> 4 files changed, 192 insertions(+), 9 deletions(-)
>
>diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c
>index 6dc92b5b712e..a5779871537a 100644
>--- a/drivers/dpll/dpll_netlink.c
>+++ b/drivers/dpll/dpll_netlink.c
>@@ -23,6 +23,7 @@ static const struct nla_policy dpll_genl_get_policy[] = {
> 	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
> 	[DPLLA_DEVICE_NAME]	= { .type = NLA_STRING,
> 				    .len = DPLL_NAME_LENGTH },
>+	[DPLLA_DEVICE_SRC_SELECT_MODE] = { .type = NLA_U32 },
> 	[DPLLA_FLAGS]		= { .type = NLA_U32 },
> };
> 
>@@ -38,13 +39,26 @@ static const struct nla_policy dpll_genl_set_output_policy[] = {
> 	[DPLLA_OUTPUT_TYPE]	= { .type = NLA_U32 },
> };
> 
>+static const struct nla_policy dpll_genl_set_src_select_mode_policy[] = {
>+	[DPLLA_DEVICE_ID]		  = { .type = NLA_U32 },
>+	[DPLLA_DEVICE_SRC_SELECT_MODE] = { .type = NLA_U32 },
>+};
>+
>+static const struct nla_policy dpll_genl_set_source_prio_policy[] = {
>+	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
>+	[DPLLA_SOURCE_ID]	= { .type = NLA_U32 },
>+	[DPLLA_SOURCE_PRIO]	= { .type = NLA_U32 },
>+};
>+
> struct param {
> 	struct netlink_callback *cb;
> 	struct dpll_device *dpll;
> 	struct sk_buff *msg;
> 	int dpll_id;
>+	int dpll_src_select_mode;
> 	int dpll_source_id;
> 	int dpll_source_type;
>+	int dpll_source_prio;
> 	int dpll_output_id;
> 	int dpll_output_type;
> 	int dpll_status;
>@@ -84,8 +98,8 @@ static int __dpll_cmd_device_dump_one(struct dpll_device *dpll,
> static int __dpll_cmd_dump_sources(struct dpll_device *dpll,
> 					   struct sk_buff *msg)
> {
>+	int i, ret = 0, type, prio;
> 	struct nlattr *src_attr;
>-	int i, ret = 0, type;
> 
> 	for (i = 0; i < dpll->sources_count; i++) {
> 		src_attr = nla_nest_start(msg, DPLLA_SOURCE);
>@@ -110,6 +124,14 @@ static int __dpll_cmd_dump_sources(struct dpll_device *dpll,
> 			}
> 			ret = 0;
> 		}
>+		if (dpll->ops->get_source_prio) {
>+			prio = dpll->ops->get_source_prio(dpll, i);
>+			if (nla_put_u32(msg, DPLLA_SOURCE_PRIO, prio)) {
>+				nla_nest_cancel(msg, src_attr);
>+				ret = -EMSGSIZE;
>+				break;
>+			}
>+		}
> 		nla_nest_end(msg, src_attr);
> 	}
> 
>@@ -154,26 +176,51 @@ static int __dpll_cmd_dump_outputs(struct dpll_device *dpll,
> static int __dpll_cmd_dump_status(struct dpll_device *dpll,
> 					   struct sk_buff *msg)
> {
>-	int ret;
>+	struct dpll_device_ops *ops = dpll->ops;
>+	int ret, type, attr;
> 
>-	if (dpll->ops->get_status) {
>-		ret = dpll->ops->get_status(dpll);
>+	if (ops->get_status) {
>+		ret = ops->get_status(dpll);
> 		if (nla_put_u32(msg, DPLLA_STATUS, ret))
> 			return -EMSGSIZE;
> 	}
> 
>-	if (dpll->ops->get_temp) {
>-		ret = dpll->ops->get_temp(dpll);
>+	if (ops->get_temp) {
>+		ret = ops->get_temp(dpll);
> 		if (nla_put_u32(msg, DPLLA_TEMP, ret))
> 			return -EMSGSIZE;
> 	}
> 
>-	if (dpll->ops->get_lock_status) {
>-		ret = dpll->ops->get_lock_status(dpll);
>+	if (ops->get_lock_status) {
>+		ret = ops->get_lock_status(dpll);
> 		if (nla_put_u32(msg, DPLLA_LOCK_STATUS, ret))
> 			return -EMSGSIZE;
> 	}
> 
>+	if (ops->get_source_select_mode) {
>+		ret = ops->get_source_select_mode(dpll);
>+		if (nla_put_u32(msg, DPLLA_DEVICE_SRC_SELECT_MODE, ret))
>+			return -EMSGSIZE;
>+	} else {
>+		if (nla_put_u32(msg, DPLLA_DEVICE_SRC_SELECT_MODE,
>+				DPLL_SRC_SELECT_FORCED))
>+			return -EMSGSIZE;
>+	}
>+
>+	if (ops->get_source_select_mode_supported) {
>+		attr = DPLLA_DEVICE_SRC_SELECT_MODE_SUPPORTED;
>+		for (type = 0; type <= DPLL_SRC_SELECT_MAX; type++) {
>+			ret = ops->get_source_select_mode_supported(dpll,
>+								    type);
>+			if (ret && nla_put_u32(msg, attr, type))
>+				return -EMSGSIZE;
>+		}
>+	} else {
>+		if (nla_put_u32(msg, DPLLA_DEVICE_SRC_SELECT_MODE_SUPPORTED,
>+				DPLL_SRC_SELECT_FORCED))
>+			return -EMSGSIZE;
>+	}
>+
> 	return 0;
> }
> 
>@@ -275,6 +322,56 @@ static int dpll_genl_cmd_set_output(struct sk_buff *skb, struct genl_info *info)
> 	return ret;
> }
> 
>+static int dpll_genl_cmd_set_source_prio(struct sk_buff *skb, struct genl_info *info)
>+{
>+	struct dpll_device *dpll = info->user_ptr[0];
>+	struct nlattr **attrs = info->attrs;
>+	int ret = 0, src_id, prio;
>+
>+	if (!attrs[DPLLA_SOURCE_ID] ||
>+	    !attrs[DPLLA_SOURCE_PRIO])
>+		return -EINVAL;
>+
>+	if (!dpll->ops->set_source_prio)
>+		return -EOPNOTSUPP;
>+
>+	src_id = nla_get_u32(attrs[DPLLA_SOURCE_ID]);
>+	prio = nla_get_u32(attrs[DPLLA_SOURCE_PRIO]);
>+
>+	mutex_lock(&dpll->lock);
>+	ret = dpll->ops->set_source_prio(dpll, src_id, prio);
>+	mutex_unlock(&dpll->lock);
>+
>+	if (!ret)
>+		dpll_notify_source_prio_change(dpll->id, src_id, prio);
>+
>+	return ret;
>+}
>+
>+static int dpll_genl_cmd_set_select_mode(struct sk_buff *skb, struct genl_info *info)
>+{
>+	struct dpll_device *dpll = info->user_ptr[0];
>+	struct nlattr **attrs = info->attrs;
>+	int ret = 0, mode;
>+
>+	if (!attrs[DPLLA_DEVICE_SRC_SELECT_MODE])
>+		return -EINVAL;
>+
>+	if (!dpll->ops->set_source_select_mode)
>+		return -EOPNOTSUPP;
>+
>+	mode = nla_get_u32(attrs[DPLLA_DEVICE_SRC_SELECT_MODE]);
>+
>+	mutex_lock(&dpll->lock);
>+	ret = dpll->ops->set_source_select_mode(dpll, mode);
>+	mutex_unlock(&dpll->lock);
>+
>+	if (!ret)
>+		dpll_notify_source_select_mode_change(dpll->id, mode);
>+
>+	return ret;
>+}
>+
> static int dpll_device_loop_cb(struct dpll_device *dpll, void *data)
> {
> 	struct dpll_dump_ctx *ctx;
>@@ -397,6 +494,20 @@ static const struct genl_ops dpll_genl_ops[] = {
> 		.policy	= dpll_genl_set_output_policy,
> 		.maxattr = ARRAY_SIZE(dpll_genl_set_output_policy) - 1,
> 	},
>+	{
>+		.cmd	= DPLL_CMD_SET_SRC_SELECT_MODE,
>+		.flags	= GENL_UNS_ADMIN_PERM,
>+		.doit	= dpll_genl_cmd_set_select_mode,
>+		.policy	= dpll_genl_set_src_select_mode_policy,
>+		.maxattr = ARRAY_SIZE(dpll_genl_set_src_select_mode_policy) - 1,
>+	},
>+	{
>+		.cmd	= DPLL_CMD_SET_SOURCE_PRIO,

I don't like the 1 netlink cmd per attr. The commands should be rather
get/set object.


>+		.flags	= GENL_UNS_ADMIN_PERM,
>+		.doit	= dpll_genl_cmd_set_source_prio,
>+		.policy	= dpll_genl_set_source_prio_policy,
>+		.maxattr = ARRAY_SIZE(dpll_genl_set_source_prio_policy) - 1,
>+	},
> };
> 
> static struct genl_family dpll_gnl_family __ro_after_init = {
>@@ -456,6 +567,26 @@ static int dpll_event_output_change(struct param *p)
> 	return 0;
> }
> 
>+static int dpll_event_source_prio(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_PRIO, p->dpll_source_prio))
>+		return -EMSGSIZE;
>+
>+	return 0;
>+}
>+
>+static int dpll_event_select_mode(struct param *p)
>+{
>+	if (nla_put_u32(p->msg, DPLLA_DEVICE_ID, p->dpll_id) ||
>+	    nla_put_u32(p->msg, DPLLA_DEVICE_SRC_SELECT_MODE,
>+		    p->dpll_src_select_mode))
>+		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,
>@@ -463,7 +594,10 @@ static const cb_t event_cb[] = {
> 	[DPLL_EVENT_STATUS_UNLOCKED]	= dpll_event_status,
> 	[DPLL_EVENT_SOURCE_CHANGE]	= dpll_event_source_change,
> 	[DPLL_EVENT_OUTPUT_CHANGE]	= dpll_event_output_change,
>+	[DPLL_EVENT_SOURCE_PRIO]        = dpll_event_source_prio,
>+	[DPLL_EVENT_SELECT_MODE]        = dpll_event_select_mode,
> };
>+
> /*
>  * Generic netlink DPLL event encoding
>  */
>@@ -552,6 +686,26 @@ int dpll_notify_output_change(int dpll_id, int output_id, int output_type)
> }
> EXPORT_SYMBOL_GPL(dpll_notify_output_change);
> 
>+int dpll_notify_source_select_mode_change(int dpll_id, int new_mode)
>+{
>+	struct param p =  { .dpll_id = dpll_id,
>+			    .dpll_src_select_mode = new_mode,
>+			    .dpll_event_group = 0 };
>+
>+	return dpll_send_event(DPLL_EVENT_SELECT_MODE, &p);
>+}
>+EXPORT_SYMBOL_GPL(dpll_notify_source_select_mode_change);
>+
>+int dpll_notify_source_prio_change(int dpll_id, int source_id, int prio)
>+{
>+	struct param p =  { .dpll_id = dpll_id, .dpll_source_id = source_id,
>+			    .dpll_source_prio = prio,
>+			    .dpll_event_group = 1 };
>+
>+	return dpll_send_event(DPLL_EVENT_SOURCE_PRIO, &p);
>+}
>+EXPORT_SYMBOL_GPL(dpll_notify_source_prio_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 5c1d1072e818..a4962fa0c8c2 100644
>--- a/drivers/dpll/dpll_netlink.h
>+++ b/drivers/dpll/dpll_netlink.h
>@@ -5,6 +5,8 @@
> 
> int dpll_notify_device_create(int dpll_id, const char *name);
> int dpll_notify_device_delete(int dpll_id);
>+int dpll_notify_source_prio(int dpll_id, int source_id, int prio);
>+int dpll_notify_select_mode(int dpll_id, int mode);
> 
> int __init dpll_netlink_init(void);
> void dpll_netlink_finish(void);
>diff --git a/include/linux/dpll.h b/include/linux/dpll.h
>index 32558965cd41..3fe957a06b90 100644
>--- a/include/linux/dpll.h
>+++ b/include/linux/dpll.h
>@@ -12,12 +12,17 @@ struct dpll_device_ops {
> 	int (*get_status)(struct dpll_device *dpll);
> 	int (*get_temp)(struct dpll_device *dpll);
> 	int (*get_lock_status)(struct dpll_device *dpll);
>+	int (*get_source_select_mode)(struct dpll_device *dpll);
>+	int (*get_source_select_mode_supported)(struct dpll_device *dpll, int type);
> 	int (*get_source_type)(struct dpll_device *dpll, int id);
> 	int (*get_source_supported)(struct dpll_device *dpll, int id, int type);
>+	int (*get_source_prio)(struct dpll_device *dpll, int id);

I don't thing this is a good model to have 1 ops per object attribute.
Did you consider having driver to "register" a source/output with type and
other attributes?



> 	int (*get_output_type)(struct dpll_device *dpll, int id);
> 	int (*get_output_supported)(struct dpll_device *dpll, int id, int type);
> 	int (*set_source_type)(struct dpll_device *dpll, int id, int val);
> 	int (*set_output_type)(struct dpll_device *dpll, int id, int val);
>+	int (*set_source_select_mode)(struct dpll_device *dpll, int mode);
>+	int (*set_source_prio)(struct dpll_device *dpll, int id, int prio);
> };
> 
> struct dpll_device *dpll_device_alloc(struct dpll_device_ops *ops, const char *name,
>@@ -31,4 +36,6 @@ 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);
>+int dpll_notify_source_select_mode_change(int dpll_id, int source_select_mode);
>+int dpll_notify_source_prio_change(int dpll_id, int source_id, int prio);
> #endif
>diff --git a/include/uapi/linux/dpll.h b/include/uapi/linux/dpll.h
>index fcbea5a5e4d6..f6b674e5cf01 100644
>--- a/include/uapi/linux/dpll.h
>+++ b/include/uapi/linux/dpll.h
>@@ -21,10 +21,13 @@ enum dpll_genl_attr {
> 	DPLLA_UNSPEC,
> 	DPLLA_DEVICE_ID,
> 	DPLLA_DEVICE_NAME,
>+	DPLLA_DEVICE_SRC_SELECT_MODE,
>+	DPLLA_DEVICE_SRC_SELECT_MODE_SUPPORTED,
> 	DPLLA_SOURCE,
> 	DPLLA_SOURCE_ID,
> 	DPLLA_SOURCE_TYPE,
> 	DPLLA_SOURCE_SUPPORTED,
>+	DPLLA_SOURCE_PRIO,
> 	DPLLA_OUTPUT,
> 	DPLLA_OUTPUT_ID,
> 	DPLLA_OUTPUT_TYPE,
>@@ -82,6 +85,8 @@ enum dpll_genl_event {
> 	DPLL_EVENT_STATUS_UNLOCKED,	/* DPLL device freerun */
> 	DPLL_EVENT_SOURCE_CHANGE,		/* DPLL device source changed */
> 	DPLL_EVENT_OUTPUT_CHANGE,		/* DPLL device output changed */
>+	DPLL_EVENT_SOURCE_PRIO,
>+	DPLL_EVENT_SELECT_MODE,
> 
> 	__DPLL_EVENT_MAX,
> };
>@@ -90,12 +95,27 @@ enum dpll_genl_event {
> /* Commands supported by the dpll_genl_family */
> enum dpll_genl_cmd {
> 	DPLL_CMD_UNSPEC,
>-	DPLL_CMD_DEVICE_GET,	/* List of DPLL devices id */
>+	DPLL_CMD_DEVICE_GET,		/* List of DPLL devices id */
> 	DPLL_CMD_SET_SOURCE_TYPE,	/* Set the DPLL device source type */
> 	DPLL_CMD_SET_OUTPUT_TYPE,	/* Set the DPLL device output type */
>+	DPLL_CMD_SET_SRC_SELECT_MODE,/* Set mode for selection of a source */
>+	DPLL_CMD_SET_SOURCE_PRIO,	/* Set priority of a source */
> 
> 	__DPLL_CMD_MAX,
> };
> #define DPLL_CMD_MAX (__DPLL_CMD_MAX - 1)
> 
>+/* Source select modes of dpll */
>+enum dpll_genl_source_select_mode {
>+	DPLL_SRC_SELECT_UNSPEC,

consistency please: "source"/"SOURCE".


>+	DPLL_SRC_SELECT_FORCED,   /* Source forced by DPLL_CMD_SET_SOURCE_TYPE */
>+	DPLL_SRC_SELECT_AUTOMATIC,/* highest prio, valid source, auto selected by dpll */
>+	DPLL_SRC_SELECT_HOLDOVER, /* forced holdover */

I think this is mixing up things a bit. I was under impression this is
to set the mode or souce select. So either user select specific source
by index (not type as you suggest above), or you leave the selection up
to the device (according to prio).

Now holdover is not source select.
Isn't think more like admin state/oper state?
oper state would be the lock status
admin state would be "force-holdover"




>+	DPLL_SRC_SELECT_FREERUN,  /* dpll driven on system clk, no holdover available */
>+	DPLL_SRC_SELECT_NCO,	     /* Set the DPLL device output type */

I don't understand what this "NCO" is, the comment didn't help.


>+
>+	__DPLL_SRC_SELECT_MAX,
>+};
>+#define DPLL_SRC_SELECT_MAX (__DPLL_SRC_SELECT_MAX - 1)
>+
> #endif /* _UAPI_LINUX_DPLL_H */
>-- 
>2.27.0
>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 3/6] dpll: add support for source selection modes
@ 2022-10-10 14:13     ` Jiri Pirko
  0 siblings, 0 replies; 67+ messages in thread
From: Jiri Pirko @ 2022-10-10 14:13 UTC (permalink / raw)
  To: Vadim Fedorenko
  Cc: Jakub Kicinski, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

Mon, Oct 10, 2022 at 03:18:01AM CEST, vfedorenko@novek.ru wrote:
>From: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
>
>Allow to configure dpll device for different source selection modes.
>Allow to configure priority of a sources for autmoatic selection mode.
>
>Signed-off-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
>---
> drivers/dpll/dpll_netlink.c | 170 ++++++++++++++++++++++++++++++++++--
> drivers/dpll/dpll_netlink.h |   2 +
> include/linux/dpll.h        |   7 ++
> include/uapi/linux/dpll.h   |  22 ++++-
> 4 files changed, 192 insertions(+), 9 deletions(-)
>
>diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c
>index 6dc92b5b712e..a5779871537a 100644
>--- a/drivers/dpll/dpll_netlink.c
>+++ b/drivers/dpll/dpll_netlink.c
>@@ -23,6 +23,7 @@ static const struct nla_policy dpll_genl_get_policy[] = {
> 	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
> 	[DPLLA_DEVICE_NAME]	= { .type = NLA_STRING,
> 				    .len = DPLL_NAME_LENGTH },
>+	[DPLLA_DEVICE_SRC_SELECT_MODE] = { .type = NLA_U32 },
> 	[DPLLA_FLAGS]		= { .type = NLA_U32 },
> };
> 
>@@ -38,13 +39,26 @@ static const struct nla_policy dpll_genl_set_output_policy[] = {
> 	[DPLLA_OUTPUT_TYPE]	= { .type = NLA_U32 },
> };
> 
>+static const struct nla_policy dpll_genl_set_src_select_mode_policy[] = {
>+	[DPLLA_DEVICE_ID]		  = { .type = NLA_U32 },
>+	[DPLLA_DEVICE_SRC_SELECT_MODE] = { .type = NLA_U32 },
>+};
>+
>+static const struct nla_policy dpll_genl_set_source_prio_policy[] = {
>+	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
>+	[DPLLA_SOURCE_ID]	= { .type = NLA_U32 },
>+	[DPLLA_SOURCE_PRIO]	= { .type = NLA_U32 },
>+};
>+
> struct param {
> 	struct netlink_callback *cb;
> 	struct dpll_device *dpll;
> 	struct sk_buff *msg;
> 	int dpll_id;
>+	int dpll_src_select_mode;
> 	int dpll_source_id;
> 	int dpll_source_type;
>+	int dpll_source_prio;
> 	int dpll_output_id;
> 	int dpll_output_type;
> 	int dpll_status;
>@@ -84,8 +98,8 @@ static int __dpll_cmd_device_dump_one(struct dpll_device *dpll,
> static int __dpll_cmd_dump_sources(struct dpll_device *dpll,
> 					   struct sk_buff *msg)
> {
>+	int i, ret = 0, type, prio;
> 	struct nlattr *src_attr;
>-	int i, ret = 0, type;
> 
> 	for (i = 0; i < dpll->sources_count; i++) {
> 		src_attr = nla_nest_start(msg, DPLLA_SOURCE);
>@@ -110,6 +124,14 @@ static int __dpll_cmd_dump_sources(struct dpll_device *dpll,
> 			}
> 			ret = 0;
> 		}
>+		if (dpll->ops->get_source_prio) {
>+			prio = dpll->ops->get_source_prio(dpll, i);
>+			if (nla_put_u32(msg, DPLLA_SOURCE_PRIO, prio)) {
>+				nla_nest_cancel(msg, src_attr);
>+				ret = -EMSGSIZE;
>+				break;
>+			}
>+		}
> 		nla_nest_end(msg, src_attr);
> 	}
> 
>@@ -154,26 +176,51 @@ static int __dpll_cmd_dump_outputs(struct dpll_device *dpll,
> static int __dpll_cmd_dump_status(struct dpll_device *dpll,
> 					   struct sk_buff *msg)
> {
>-	int ret;
>+	struct dpll_device_ops *ops = dpll->ops;
>+	int ret, type, attr;
> 
>-	if (dpll->ops->get_status) {
>-		ret = dpll->ops->get_status(dpll);
>+	if (ops->get_status) {
>+		ret = ops->get_status(dpll);
> 		if (nla_put_u32(msg, DPLLA_STATUS, ret))
> 			return -EMSGSIZE;
> 	}
> 
>-	if (dpll->ops->get_temp) {
>-		ret = dpll->ops->get_temp(dpll);
>+	if (ops->get_temp) {
>+		ret = ops->get_temp(dpll);
> 		if (nla_put_u32(msg, DPLLA_TEMP, ret))
> 			return -EMSGSIZE;
> 	}
> 
>-	if (dpll->ops->get_lock_status) {
>-		ret = dpll->ops->get_lock_status(dpll);
>+	if (ops->get_lock_status) {
>+		ret = ops->get_lock_status(dpll);
> 		if (nla_put_u32(msg, DPLLA_LOCK_STATUS, ret))
> 			return -EMSGSIZE;
> 	}
> 
>+	if (ops->get_source_select_mode) {
>+		ret = ops->get_source_select_mode(dpll);
>+		if (nla_put_u32(msg, DPLLA_DEVICE_SRC_SELECT_MODE, ret))
>+			return -EMSGSIZE;
>+	} else {
>+		if (nla_put_u32(msg, DPLLA_DEVICE_SRC_SELECT_MODE,
>+				DPLL_SRC_SELECT_FORCED))
>+			return -EMSGSIZE;
>+	}
>+
>+	if (ops->get_source_select_mode_supported) {
>+		attr = DPLLA_DEVICE_SRC_SELECT_MODE_SUPPORTED;
>+		for (type = 0; type <= DPLL_SRC_SELECT_MAX; type++) {
>+			ret = ops->get_source_select_mode_supported(dpll,
>+								    type);
>+			if (ret && nla_put_u32(msg, attr, type))
>+				return -EMSGSIZE;
>+		}
>+	} else {
>+		if (nla_put_u32(msg, DPLLA_DEVICE_SRC_SELECT_MODE_SUPPORTED,
>+				DPLL_SRC_SELECT_FORCED))
>+			return -EMSGSIZE;
>+	}
>+
> 	return 0;
> }
> 
>@@ -275,6 +322,56 @@ static int dpll_genl_cmd_set_output(struct sk_buff *skb, struct genl_info *info)
> 	return ret;
> }
> 
>+static int dpll_genl_cmd_set_source_prio(struct sk_buff *skb, struct genl_info *info)
>+{
>+	struct dpll_device *dpll = info->user_ptr[0];
>+	struct nlattr **attrs = info->attrs;
>+	int ret = 0, src_id, prio;
>+
>+	if (!attrs[DPLLA_SOURCE_ID] ||
>+	    !attrs[DPLLA_SOURCE_PRIO])
>+		return -EINVAL;
>+
>+	if (!dpll->ops->set_source_prio)
>+		return -EOPNOTSUPP;
>+
>+	src_id = nla_get_u32(attrs[DPLLA_SOURCE_ID]);
>+	prio = nla_get_u32(attrs[DPLLA_SOURCE_PRIO]);
>+
>+	mutex_lock(&dpll->lock);
>+	ret = dpll->ops->set_source_prio(dpll, src_id, prio);
>+	mutex_unlock(&dpll->lock);
>+
>+	if (!ret)
>+		dpll_notify_source_prio_change(dpll->id, src_id, prio);
>+
>+	return ret;
>+}
>+
>+static int dpll_genl_cmd_set_select_mode(struct sk_buff *skb, struct genl_info *info)
>+{
>+	struct dpll_device *dpll = info->user_ptr[0];
>+	struct nlattr **attrs = info->attrs;
>+	int ret = 0, mode;
>+
>+	if (!attrs[DPLLA_DEVICE_SRC_SELECT_MODE])
>+		return -EINVAL;
>+
>+	if (!dpll->ops->set_source_select_mode)
>+		return -EOPNOTSUPP;
>+
>+	mode = nla_get_u32(attrs[DPLLA_DEVICE_SRC_SELECT_MODE]);
>+
>+	mutex_lock(&dpll->lock);
>+	ret = dpll->ops->set_source_select_mode(dpll, mode);
>+	mutex_unlock(&dpll->lock);
>+
>+	if (!ret)
>+		dpll_notify_source_select_mode_change(dpll->id, mode);
>+
>+	return ret;
>+}
>+
> static int dpll_device_loop_cb(struct dpll_device *dpll, void *data)
> {
> 	struct dpll_dump_ctx *ctx;
>@@ -397,6 +494,20 @@ static const struct genl_ops dpll_genl_ops[] = {
> 		.policy	= dpll_genl_set_output_policy,
> 		.maxattr = ARRAY_SIZE(dpll_genl_set_output_policy) - 1,
> 	},
>+	{
>+		.cmd	= DPLL_CMD_SET_SRC_SELECT_MODE,
>+		.flags	= GENL_UNS_ADMIN_PERM,
>+		.doit	= dpll_genl_cmd_set_select_mode,
>+		.policy	= dpll_genl_set_src_select_mode_policy,
>+		.maxattr = ARRAY_SIZE(dpll_genl_set_src_select_mode_policy) - 1,
>+	},
>+	{
>+		.cmd	= DPLL_CMD_SET_SOURCE_PRIO,

I don't like the 1 netlink cmd per attr. The commands should be rather
get/set object.


>+		.flags	= GENL_UNS_ADMIN_PERM,
>+		.doit	= dpll_genl_cmd_set_source_prio,
>+		.policy	= dpll_genl_set_source_prio_policy,
>+		.maxattr = ARRAY_SIZE(dpll_genl_set_source_prio_policy) - 1,
>+	},
> };
> 
> static struct genl_family dpll_gnl_family __ro_after_init = {
>@@ -456,6 +567,26 @@ static int dpll_event_output_change(struct param *p)
> 	return 0;
> }
> 
>+static int dpll_event_source_prio(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_PRIO, p->dpll_source_prio))
>+		return -EMSGSIZE;
>+
>+	return 0;
>+}
>+
>+static int dpll_event_select_mode(struct param *p)
>+{
>+	if (nla_put_u32(p->msg, DPLLA_DEVICE_ID, p->dpll_id) ||
>+	    nla_put_u32(p->msg, DPLLA_DEVICE_SRC_SELECT_MODE,
>+		    p->dpll_src_select_mode))
>+		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,
>@@ -463,7 +594,10 @@ static const cb_t event_cb[] = {
> 	[DPLL_EVENT_STATUS_UNLOCKED]	= dpll_event_status,
> 	[DPLL_EVENT_SOURCE_CHANGE]	= dpll_event_source_change,
> 	[DPLL_EVENT_OUTPUT_CHANGE]	= dpll_event_output_change,
>+	[DPLL_EVENT_SOURCE_PRIO]        = dpll_event_source_prio,
>+	[DPLL_EVENT_SELECT_MODE]        = dpll_event_select_mode,
> };
>+
> /*
>  * Generic netlink DPLL event encoding
>  */
>@@ -552,6 +686,26 @@ int dpll_notify_output_change(int dpll_id, int output_id, int output_type)
> }
> EXPORT_SYMBOL_GPL(dpll_notify_output_change);
> 
>+int dpll_notify_source_select_mode_change(int dpll_id, int new_mode)
>+{
>+	struct param p =  { .dpll_id = dpll_id,
>+			    .dpll_src_select_mode = new_mode,
>+			    .dpll_event_group = 0 };
>+
>+	return dpll_send_event(DPLL_EVENT_SELECT_MODE, &p);
>+}
>+EXPORT_SYMBOL_GPL(dpll_notify_source_select_mode_change);
>+
>+int dpll_notify_source_prio_change(int dpll_id, int source_id, int prio)
>+{
>+	struct param p =  { .dpll_id = dpll_id, .dpll_source_id = source_id,
>+			    .dpll_source_prio = prio,
>+			    .dpll_event_group = 1 };
>+
>+	return dpll_send_event(DPLL_EVENT_SOURCE_PRIO, &p);
>+}
>+EXPORT_SYMBOL_GPL(dpll_notify_source_prio_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 5c1d1072e818..a4962fa0c8c2 100644
>--- a/drivers/dpll/dpll_netlink.h
>+++ b/drivers/dpll/dpll_netlink.h
>@@ -5,6 +5,8 @@
> 
> int dpll_notify_device_create(int dpll_id, const char *name);
> int dpll_notify_device_delete(int dpll_id);
>+int dpll_notify_source_prio(int dpll_id, int source_id, int prio);
>+int dpll_notify_select_mode(int dpll_id, int mode);
> 
> int __init dpll_netlink_init(void);
> void dpll_netlink_finish(void);
>diff --git a/include/linux/dpll.h b/include/linux/dpll.h
>index 32558965cd41..3fe957a06b90 100644
>--- a/include/linux/dpll.h
>+++ b/include/linux/dpll.h
>@@ -12,12 +12,17 @@ struct dpll_device_ops {
> 	int (*get_status)(struct dpll_device *dpll);
> 	int (*get_temp)(struct dpll_device *dpll);
> 	int (*get_lock_status)(struct dpll_device *dpll);
>+	int (*get_source_select_mode)(struct dpll_device *dpll);
>+	int (*get_source_select_mode_supported)(struct dpll_device *dpll, int type);
> 	int (*get_source_type)(struct dpll_device *dpll, int id);
> 	int (*get_source_supported)(struct dpll_device *dpll, int id, int type);
>+	int (*get_source_prio)(struct dpll_device *dpll, int id);

I don't thing this is a good model to have 1 ops per object attribute.
Did you consider having driver to "register" a source/output with type and
other attributes?



> 	int (*get_output_type)(struct dpll_device *dpll, int id);
> 	int (*get_output_supported)(struct dpll_device *dpll, int id, int type);
> 	int (*set_source_type)(struct dpll_device *dpll, int id, int val);
> 	int (*set_output_type)(struct dpll_device *dpll, int id, int val);
>+	int (*set_source_select_mode)(struct dpll_device *dpll, int mode);
>+	int (*set_source_prio)(struct dpll_device *dpll, int id, int prio);
> };
> 
> struct dpll_device *dpll_device_alloc(struct dpll_device_ops *ops, const char *name,
>@@ -31,4 +36,6 @@ 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);
>+int dpll_notify_source_select_mode_change(int dpll_id, int source_select_mode);
>+int dpll_notify_source_prio_change(int dpll_id, int source_id, int prio);
> #endif
>diff --git a/include/uapi/linux/dpll.h b/include/uapi/linux/dpll.h
>index fcbea5a5e4d6..f6b674e5cf01 100644
>--- a/include/uapi/linux/dpll.h
>+++ b/include/uapi/linux/dpll.h
>@@ -21,10 +21,13 @@ enum dpll_genl_attr {
> 	DPLLA_UNSPEC,
> 	DPLLA_DEVICE_ID,
> 	DPLLA_DEVICE_NAME,
>+	DPLLA_DEVICE_SRC_SELECT_MODE,
>+	DPLLA_DEVICE_SRC_SELECT_MODE_SUPPORTED,
> 	DPLLA_SOURCE,
> 	DPLLA_SOURCE_ID,
> 	DPLLA_SOURCE_TYPE,
> 	DPLLA_SOURCE_SUPPORTED,
>+	DPLLA_SOURCE_PRIO,
> 	DPLLA_OUTPUT,
> 	DPLLA_OUTPUT_ID,
> 	DPLLA_OUTPUT_TYPE,
>@@ -82,6 +85,8 @@ enum dpll_genl_event {
> 	DPLL_EVENT_STATUS_UNLOCKED,	/* DPLL device freerun */
> 	DPLL_EVENT_SOURCE_CHANGE,		/* DPLL device source changed */
> 	DPLL_EVENT_OUTPUT_CHANGE,		/* DPLL device output changed */
>+	DPLL_EVENT_SOURCE_PRIO,
>+	DPLL_EVENT_SELECT_MODE,
> 
> 	__DPLL_EVENT_MAX,
> };
>@@ -90,12 +95,27 @@ enum dpll_genl_event {
> /* Commands supported by the dpll_genl_family */
> enum dpll_genl_cmd {
> 	DPLL_CMD_UNSPEC,
>-	DPLL_CMD_DEVICE_GET,	/* List of DPLL devices id */
>+	DPLL_CMD_DEVICE_GET,		/* List of DPLL devices id */
> 	DPLL_CMD_SET_SOURCE_TYPE,	/* Set the DPLL device source type */
> 	DPLL_CMD_SET_OUTPUT_TYPE,	/* Set the DPLL device output type */
>+	DPLL_CMD_SET_SRC_SELECT_MODE,/* Set mode for selection of a source */
>+	DPLL_CMD_SET_SOURCE_PRIO,	/* Set priority of a source */
> 
> 	__DPLL_CMD_MAX,
> };
> #define DPLL_CMD_MAX (__DPLL_CMD_MAX - 1)
> 
>+/* Source select modes of dpll */
>+enum dpll_genl_source_select_mode {
>+	DPLL_SRC_SELECT_UNSPEC,

consistency please: "source"/"SOURCE".


>+	DPLL_SRC_SELECT_FORCED,   /* Source forced by DPLL_CMD_SET_SOURCE_TYPE */
>+	DPLL_SRC_SELECT_AUTOMATIC,/* highest prio, valid source, auto selected by dpll */
>+	DPLL_SRC_SELECT_HOLDOVER, /* forced holdover */

I think this is mixing up things a bit. I was under impression this is
to set the mode or souce select. So either user select specific source
by index (not type as you suggest above), or you leave the selection up
to the device (according to prio).

Now holdover is not source select.
Isn't think more like admin state/oper state?
oper state would be the lock status
admin state would be "force-holdover"




>+	DPLL_SRC_SELECT_FREERUN,  /* dpll driven on system clk, no holdover available */
>+	DPLL_SRC_SELECT_NCO,	     /* Set the DPLL device output type */

I don't understand what this "NCO" is, the comment didn't help.


>+
>+	__DPLL_SRC_SELECT_MAX,
>+};
>+#define DPLL_SRC_SELECT_MAX (__DPLL_SRC_SELECT_MAX - 1)
>+
> #endif /* _UAPI_LINUX_DPLL_H */
>-- 
>2.27.0
>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 6/6] ptp_ocp: implement DPLL ops
  2022-10-10  1:18   ` Vadim Fedorenko
@ 2022-10-10 15:42     ` Jiri Pirko
  -1 siblings, 0 replies; 67+ messages in thread
From: Jiri Pirko @ 2022-10-10 15:42 UTC (permalink / raw)
  To: Vadim Fedorenko
  Cc: Jakub Kicinski, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

Mon, Oct 10, 2022 at 03:18:04AM CEST, vfedorenko@novek.ru wrote:
>From: Vadim Fedorenko <vadfed@fb.com>
>
>Implement DPLL operations in ptp_ocp driver.
>
>Signed-off-by: Vadim Fedorenko <vadfed@fb.com>
>---
> drivers/ptp/Kconfig       |   1 +
> drivers/ptp/ptp_ocp.c     | 170 ++++++++++++++++++++++++++++++--------
> include/uapi/linux/dpll.h |   2 +
> 3 files changed, 137 insertions(+), 36 deletions(-)
>
>diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig
>index fe4971b65c64..8c4cfabc1bfa 100644
>--- a/drivers/ptp/Kconfig
>+++ b/drivers/ptp/Kconfig
>@@ -177,6 +177,7 @@ config PTP_1588_CLOCK_OCP
> 	depends on COMMON_CLK
> 	select NET_DEVLINK
> 	select CRC16
>+	select DPLL
> 	help
> 	  This driver adds support for an OpenCompute time card.
> 
>diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c
>index d36c3f597f77..a01c0c721802 100644
>--- a/drivers/ptp/ptp_ocp.c
>+++ b/drivers/ptp/ptp_ocp.c
>@@ -21,6 +21,8 @@
> #include <linux/mtd/mtd.h>
> #include <linux/nvmem-consumer.h>
> #include <linux/crc16.h>
>+#include <linux/dpll.h>
>+#include <uapi/linux/dpll.h>

This should not be needed to include directly. linux/dpll.h should
include uapi/linux/dpll.h


> 
> #define PCI_VENDOR_ID_FACEBOOK			0x1d9b
> #define PCI_DEVICE_ID_FACEBOOK_TIMECARD		0x0400
>@@ -336,6 +338,7 @@ struct ptp_ocp {
> 	struct ptp_ocp_signal	signal[4];
> 	struct ptp_ocp_sma_connector sma[4];
> 	const struct ocp_sma_op *sma_op;
>+	struct dpll_device *dpll;
> };
> 
> #define OCP_REQ_TIMESTAMP	BIT(0)
>@@ -660,18 +663,19 @@ static DEFINE_IDR(ptp_ocp_idr);
> struct ocp_selector {
> 	const char *name;
> 	int value;
>+	int dpll_type;

Enum?


> };
> 
> static const struct ocp_selector ptp_ocp_clock[] = {
>-	{ .name = "NONE",	.value = 0 },
>-	{ .name = "TOD",	.value = 1 },
>-	{ .name = "IRIG",	.value = 2 },
>-	{ .name = "PPS",	.value = 3 },
>-	{ .name = "PTP",	.value = 4 },
>-	{ .name = "RTC",	.value = 5 },
>-	{ .name = "DCF",	.value = 6 },
>-	{ .name = "REGS",	.value = 0xfe },
>-	{ .name = "EXT",	.value = 0xff },
>+	{ .name = "NONE",	.value = 0,		.dpll_type = 0 },
>+	{ .name = "TOD",	.value = 1,		.dpll_type = 0 },
>+	{ .name = "IRIG",	.value = 2,		.dpll_type = 0 },
>+	{ .name = "PPS",	.value = 3,		.dpll_type = 0 },
>+	{ .name = "PTP",	.value = 4,		.dpll_type = 0 },
>+	{ .name = "RTC",	.value = 5,		.dpll_type = 0 },
>+	{ .name = "DCF",	.value = 6,		.dpll_type = 0 },
>+	{ .name = "REGS",	.value = 0xfe,		.dpll_type = 0 },
>+	{ .name = "EXT",	.value = 0xff,		.dpll_type = 0 },
> 	{ }
> };
> 
>@@ -680,37 +684,37 @@ static const struct ocp_selector ptp_ocp_clock[] = {
> #define SMA_SELECT_MASK		GENMASK(14, 0)
> 
> static const struct ocp_selector ptp_ocp_sma_in[] = {
>-	{ .name = "10Mhz",	.value = 0x0000 },
>-	{ .name = "PPS1",	.value = 0x0001 },
>-	{ .name = "PPS2",	.value = 0x0002 },
>-	{ .name = "TS1",	.value = 0x0004 },
>-	{ .name = "TS2",	.value = 0x0008 },
>-	{ .name = "IRIG",	.value = 0x0010 },
>-	{ .name = "DCF",	.value = 0x0020 },
>-	{ .name = "TS3",	.value = 0x0040 },
>-	{ .name = "TS4",	.value = 0x0080 },
>-	{ .name = "FREQ1",	.value = 0x0100 },
>-	{ .name = "FREQ2",	.value = 0x0200 },
>-	{ .name = "FREQ3",	.value = 0x0400 },
>-	{ .name = "FREQ4",	.value = 0x0800 },
>-	{ .name = "None",	.value = SMA_DISABLE },
>+	{ .name = "10Mhz",	.value = 0x0000,	.dpll_type = DPLL_TYPE_EXT_10MHZ },
>+	{ .name = "PPS1",	.value = 0x0001,	.dpll_type = DPLL_TYPE_EXT_1PPS },
>+	{ .name = "PPS2",	.value = 0x0002,	.dpll_type = DPLL_TYPE_EXT_1PPS },
>+	{ .name = "TS1",	.value = 0x0004,	.dpll_type = DPLL_TYPE_CUSTOM },
>+	{ .name = "TS2",	.value = 0x0008,	.dpll_type = DPLL_TYPE_CUSTOM },
>+	{ .name = "IRIG",	.value = 0x0010,	.dpll_type = DPLL_TYPE_CUSTOM },
>+	{ .name = "DCF",	.value = 0x0020,	.dpll_type = DPLL_TYPE_CUSTOM },
>+	{ .name = "TS3",	.value = 0x0040,	.dpll_type = DPLL_TYPE_CUSTOM },
>+	{ .name = "TS4",	.value = 0x0080,	.dpll_type = DPLL_TYPE_CUSTOM },
>+	{ .name = "FREQ1",	.value = 0x0100,	.dpll_type = DPLL_TYPE_CUSTOM },
>+	{ .name = "FREQ2",	.value = 0x0200,	.dpll_type = DPLL_TYPE_CUSTOM },
>+	{ .name = "FREQ3",	.value = 0x0400,	.dpll_type = DPLL_TYPE_CUSTOM },
>+	{ .name = "FREQ4",	.value = 0x0800,	.dpll_type = DPLL_TYPE_CUSTOM },
>+	{ .name = "None",	.value = SMA_DISABLE,	.dpll_type = DPLL_TYPE_NONE },
> 	{ }
> };
> 
> static const struct ocp_selector ptp_ocp_sma_out[] = {
>-	{ .name = "10Mhz",	.value = 0x0000 },
>-	{ .name = "PHC",	.value = 0x0001 },
>-	{ .name = "MAC",	.value = 0x0002 },
>-	{ .name = "GNSS1",	.value = 0x0004 },
>-	{ .name = "GNSS2",	.value = 0x0008 },
>-	{ .name = "IRIG",	.value = 0x0010 },
>-	{ .name = "DCF",	.value = 0x0020 },
>-	{ .name = "GEN1",	.value = 0x0040 },
>-	{ .name = "GEN2",	.value = 0x0080 },
>-	{ .name = "GEN3",	.value = 0x0100 },
>-	{ .name = "GEN4",	.value = 0x0200 },
>-	{ .name = "GND",	.value = 0x2000 },
>-	{ .name = "VCC",	.value = 0x4000 },
>+	{ .name = "10Mhz",	.value = 0x0000,	.dpll_type = DPLL_TYPE_EXT_10MHZ },
>+	{ .name = "PHC",	.value = 0x0001,	.dpll_type = DPLL_TYPE_INT_OSCILLATOR },
>+	{ .name = "MAC",	.value = 0x0002,	.dpll_type = DPLL_TYPE_INT_OSCILLATOR },
>+	{ .name = "GNSS1",	.value = 0x0004,	.dpll_type = DPLL_TYPE_GNSS },
>+	{ .name = "GNSS2",	.value = 0x0008,	.dpll_type = DPLL_TYPE_GNSS },
>+	{ .name = "IRIG",	.value = 0x0010,	.dpll_type = DPLL_TYPE_CUSTOM },
>+	{ .name = "DCF",	.value = 0x0020,	.dpll_type = DPLL_TYPE_CUSTOM },
>+	{ .name = "GEN1",	.value = 0x0040,	.dpll_type = DPLL_TYPE_CUSTOM },
>+	{ .name = "GEN2",	.value = 0x0080,	.dpll_type = DPLL_TYPE_CUSTOM },
>+	{ .name = "GEN3",	.value = 0x0100,	.dpll_type = DPLL_TYPE_CUSTOM },
>+	{ .name = "GEN4",	.value = 0x0200,	.dpll_type = DPLL_TYPE_CUSTOM },
>+	{ .name = "GND",	.value = 0x2000,	.dpll_type = DPLL_TYPE_CUSTOM },
>+	{ .name = "VCC",	.value = 0x4000,	.dpll_type = DPLL_TYPE_CUSTOM },
> 	{ }
> };
> 
>@@ -3707,6 +3711,90 @@ ptp_ocp_detach(struct ptp_ocp *bp)
> 	device_unregister(&bp->dev);
> }
> 
>+static int ptp_ocp_dpll_get_status(struct dpll_device *dpll)
>+{
>+	struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll);
>+	int sync;
>+
>+	sync = ioread32(&bp->reg->status) & OCP_STATUS_IN_SYNC;
>+	return sync;
>+}
>+
>+static int ptp_ocp_dpll_get_lock_status(struct dpll_device *dpll)
>+{
>+	struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll);
>+	int sync;
>+
>+	sync = ioread32(&bp->reg->status) & OCP_STATUS_IN_SYNC;
>+	return sync;
>+}
>+
>+static int ptp_ocp_sma_get_dpll_type(struct ptp_ocp *bp, int sma_nr)
>+{
>+	const struct ocp_selector *tbl;
>+	u32 val;
>+
>+	if (bp->sma[sma_nr].mode == SMA_MODE_IN)
>+		tbl = bp->sma_op->tbl[0];
>+	else
>+		tbl = bp->sma_op->tbl[1];
>+
>+	val = ptp_ocp_sma_get(bp, sma_nr);
>+	return tbl[val].dpll_type;
>+}
>+
>+static int ptp_ocp_dpll_type_supported(struct dpll_device *dpll, int sma, int type, int dir)
>+{
>+	struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll);
>+	const struct ocp_selector *tbl = bp->sma_op->tbl[dir];
>+	int i;
>+
>+	for (i = 0; i < sizeof(*tbl); i++) {
>+		if (tbl[i].dpll_type == type)
>+			return 1;
>+	}
>+	return 0;
>+}
>+
>+static int ptp_ocp_dpll_get_source_type(struct dpll_device *dpll, int sma)
>+{
>+	struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll);
>+
>+	if (bp->sma[sma].mode != SMA_MODE_IN)
>+		return -1;
>+
>+	return ptp_ocp_sma_get_dpll_type(bp, sma);
>+}
>+
>+static int ptp_ocp_dpll_get_source_supported(struct dpll_device *dpll, int sma, int type)
>+{
>+	return ptp_ocp_dpll_type_supported(dpll, sma, type, 0);
>+}
>+
>+static int ptp_ocp_dpll_get_output_type(struct dpll_device *dpll, int sma)
>+{
>+	struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll);
>+
>+	if (bp->sma[sma].mode != SMA_MODE_OUT)
>+		return -1;
>+
>+	return ptp_ocp_sma_get_dpll_type(bp, sma);
>+}
>+
>+static int ptp_ocp_dpll_get_output_supported(struct dpll_device *dpll, int sma, int type)
>+{
>+	return ptp_ocp_dpll_type_supported(dpll, sma, type, 1);
>+}
>+
>+static struct dpll_device_ops dpll_ops = {

Namespace prefix?


>+	.get_status		= ptp_ocp_dpll_get_status,
>+	.get_lock_status	= ptp_ocp_dpll_get_lock_status,
>+	.get_source_type	= ptp_ocp_dpll_get_source_type,
>+	.get_source_supported	= ptp_ocp_dpll_get_source_supported,
>+	.get_output_type	= ptp_ocp_dpll_get_output_type,
>+	.get_output_supported	= ptp_ocp_dpll_get_output_supported,
>+};
>+
> static int
> ptp_ocp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
> {
>@@ -3762,6 +3850,14 @@ ptp_ocp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
> 
> 	ptp_ocp_info(bp);
> 	devlink_register(devlink);
>+
>+	bp->dpll = dpll_device_alloc(&dpll_ops, "ocp", ARRAY_SIZE(bp->sma), ARRAY_SIZE(bp->sma), bp);
>+	if (!bp->dpll) {

You have to use IS_ERR() macro here.


>+		dev_err(&pdev->dev, "dpll_device_alloc failed\n");
>+		return 0;
>+	}
>+	dpll_device_register(bp->dpll);
>+
> 	return 0;
> 
> out:
>@@ -3779,6 +3875,8 @@ ptp_ocp_remove(struct pci_dev *pdev)
> 	struct ptp_ocp *bp = pci_get_drvdata(pdev);
> 	struct devlink *devlink = priv_to_devlink(bp);
> 
>+	dpll_device_unregister(bp->dpll);
>+	dpll_device_free(bp->dpll);
> 	devlink_unregister(devlink);
> 	ptp_ocp_detach(bp);
> 	pci_disable_device(pdev);
>diff --git a/include/uapi/linux/dpll.h b/include/uapi/linux/dpll.h
>index 8782d3425aae..59fc6ef81b40 100644
>--- a/include/uapi/linux/dpll.h
>+++ b/include/uapi/linux/dpll.h
>@@ -55,11 +55,13 @@ enum dpll_genl_status {
> 
> /* DPLL signal types used as source or as output */
> enum dpll_genl_signal_type {
>+	DPLL_TYPE_NONE,
> 	DPLL_TYPE_EXT_1PPS,
> 	DPLL_TYPE_EXT_10MHZ,
> 	DPLL_TYPE_SYNCE_ETH_PORT,
> 	DPLL_TYPE_INT_OSCILLATOR,
> 	DPLL_TYPE_GNSS,
>+	DPLL_TYPE_CUSTOM,

This hunk should not be here.
I commented this on the previous version. Btw, this is not the only
thing that I previously commented and you ignored. It is annoying to be
honest. Could you please include the requested changes in next patchset
version or comment why you are not do including them. Ignoring is never
good :/


> 
> 	__DPLL_TYPE_MAX,
> };
>-- 
>2.27.0
>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 6/6] ptp_ocp: implement DPLL ops
@ 2022-10-10 15:42     ` Jiri Pirko
  0 siblings, 0 replies; 67+ messages in thread
From: Jiri Pirko @ 2022-10-10 15:42 UTC (permalink / raw)
  To: Vadim Fedorenko
  Cc: Jakub Kicinski, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

Mon, Oct 10, 2022 at 03:18:04AM CEST, vfedorenko@novek.ru wrote:
>From: Vadim Fedorenko <vadfed@fb.com>
>
>Implement DPLL operations in ptp_ocp driver.
>
>Signed-off-by: Vadim Fedorenko <vadfed@fb.com>
>---
> drivers/ptp/Kconfig       |   1 +
> drivers/ptp/ptp_ocp.c     | 170 ++++++++++++++++++++++++++++++--------
> include/uapi/linux/dpll.h |   2 +
> 3 files changed, 137 insertions(+), 36 deletions(-)
>
>diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig
>index fe4971b65c64..8c4cfabc1bfa 100644
>--- a/drivers/ptp/Kconfig
>+++ b/drivers/ptp/Kconfig
>@@ -177,6 +177,7 @@ config PTP_1588_CLOCK_OCP
> 	depends on COMMON_CLK
> 	select NET_DEVLINK
> 	select CRC16
>+	select DPLL
> 	help
> 	  This driver adds support for an OpenCompute time card.
> 
>diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c
>index d36c3f597f77..a01c0c721802 100644
>--- a/drivers/ptp/ptp_ocp.c
>+++ b/drivers/ptp/ptp_ocp.c
>@@ -21,6 +21,8 @@
> #include <linux/mtd/mtd.h>
> #include <linux/nvmem-consumer.h>
> #include <linux/crc16.h>
>+#include <linux/dpll.h>
>+#include <uapi/linux/dpll.h>

This should not be needed to include directly. linux/dpll.h should
include uapi/linux/dpll.h


> 
> #define PCI_VENDOR_ID_FACEBOOK			0x1d9b
> #define PCI_DEVICE_ID_FACEBOOK_TIMECARD		0x0400
>@@ -336,6 +338,7 @@ struct ptp_ocp {
> 	struct ptp_ocp_signal	signal[4];
> 	struct ptp_ocp_sma_connector sma[4];
> 	const struct ocp_sma_op *sma_op;
>+	struct dpll_device *dpll;
> };
> 
> #define OCP_REQ_TIMESTAMP	BIT(0)
>@@ -660,18 +663,19 @@ static DEFINE_IDR(ptp_ocp_idr);
> struct ocp_selector {
> 	const char *name;
> 	int value;
>+	int dpll_type;

Enum?


> };
> 
> static const struct ocp_selector ptp_ocp_clock[] = {
>-	{ .name = "NONE",	.value = 0 },
>-	{ .name = "TOD",	.value = 1 },
>-	{ .name = "IRIG",	.value = 2 },
>-	{ .name = "PPS",	.value = 3 },
>-	{ .name = "PTP",	.value = 4 },
>-	{ .name = "RTC",	.value = 5 },
>-	{ .name = "DCF",	.value = 6 },
>-	{ .name = "REGS",	.value = 0xfe },
>-	{ .name = "EXT",	.value = 0xff },
>+	{ .name = "NONE",	.value = 0,		.dpll_type = 0 },
>+	{ .name = "TOD",	.value = 1,		.dpll_type = 0 },
>+	{ .name = "IRIG",	.value = 2,		.dpll_type = 0 },
>+	{ .name = "PPS",	.value = 3,		.dpll_type = 0 },
>+	{ .name = "PTP",	.value = 4,		.dpll_type = 0 },
>+	{ .name = "RTC",	.value = 5,		.dpll_type = 0 },
>+	{ .name = "DCF",	.value = 6,		.dpll_type = 0 },
>+	{ .name = "REGS",	.value = 0xfe,		.dpll_type = 0 },
>+	{ .name = "EXT",	.value = 0xff,		.dpll_type = 0 },
> 	{ }
> };
> 
>@@ -680,37 +684,37 @@ static const struct ocp_selector ptp_ocp_clock[] = {
> #define SMA_SELECT_MASK		GENMASK(14, 0)
> 
> static const struct ocp_selector ptp_ocp_sma_in[] = {
>-	{ .name = "10Mhz",	.value = 0x0000 },
>-	{ .name = "PPS1",	.value = 0x0001 },
>-	{ .name = "PPS2",	.value = 0x0002 },
>-	{ .name = "TS1",	.value = 0x0004 },
>-	{ .name = "TS2",	.value = 0x0008 },
>-	{ .name = "IRIG",	.value = 0x0010 },
>-	{ .name = "DCF",	.value = 0x0020 },
>-	{ .name = "TS3",	.value = 0x0040 },
>-	{ .name = "TS4",	.value = 0x0080 },
>-	{ .name = "FREQ1",	.value = 0x0100 },
>-	{ .name = "FREQ2",	.value = 0x0200 },
>-	{ .name = "FREQ3",	.value = 0x0400 },
>-	{ .name = "FREQ4",	.value = 0x0800 },
>-	{ .name = "None",	.value = SMA_DISABLE },
>+	{ .name = "10Mhz",	.value = 0x0000,	.dpll_type = DPLL_TYPE_EXT_10MHZ },
>+	{ .name = "PPS1",	.value = 0x0001,	.dpll_type = DPLL_TYPE_EXT_1PPS },
>+	{ .name = "PPS2",	.value = 0x0002,	.dpll_type = DPLL_TYPE_EXT_1PPS },
>+	{ .name = "TS1",	.value = 0x0004,	.dpll_type = DPLL_TYPE_CUSTOM },
>+	{ .name = "TS2",	.value = 0x0008,	.dpll_type = DPLL_TYPE_CUSTOM },
>+	{ .name = "IRIG",	.value = 0x0010,	.dpll_type = DPLL_TYPE_CUSTOM },
>+	{ .name = "DCF",	.value = 0x0020,	.dpll_type = DPLL_TYPE_CUSTOM },
>+	{ .name = "TS3",	.value = 0x0040,	.dpll_type = DPLL_TYPE_CUSTOM },
>+	{ .name = "TS4",	.value = 0x0080,	.dpll_type = DPLL_TYPE_CUSTOM },
>+	{ .name = "FREQ1",	.value = 0x0100,	.dpll_type = DPLL_TYPE_CUSTOM },
>+	{ .name = "FREQ2",	.value = 0x0200,	.dpll_type = DPLL_TYPE_CUSTOM },
>+	{ .name = "FREQ3",	.value = 0x0400,	.dpll_type = DPLL_TYPE_CUSTOM },
>+	{ .name = "FREQ4",	.value = 0x0800,	.dpll_type = DPLL_TYPE_CUSTOM },
>+	{ .name = "None",	.value = SMA_DISABLE,	.dpll_type = DPLL_TYPE_NONE },
> 	{ }
> };
> 
> static const struct ocp_selector ptp_ocp_sma_out[] = {
>-	{ .name = "10Mhz",	.value = 0x0000 },
>-	{ .name = "PHC",	.value = 0x0001 },
>-	{ .name = "MAC",	.value = 0x0002 },
>-	{ .name = "GNSS1",	.value = 0x0004 },
>-	{ .name = "GNSS2",	.value = 0x0008 },
>-	{ .name = "IRIG",	.value = 0x0010 },
>-	{ .name = "DCF",	.value = 0x0020 },
>-	{ .name = "GEN1",	.value = 0x0040 },
>-	{ .name = "GEN2",	.value = 0x0080 },
>-	{ .name = "GEN3",	.value = 0x0100 },
>-	{ .name = "GEN4",	.value = 0x0200 },
>-	{ .name = "GND",	.value = 0x2000 },
>-	{ .name = "VCC",	.value = 0x4000 },
>+	{ .name = "10Mhz",	.value = 0x0000,	.dpll_type = DPLL_TYPE_EXT_10MHZ },
>+	{ .name = "PHC",	.value = 0x0001,	.dpll_type = DPLL_TYPE_INT_OSCILLATOR },
>+	{ .name = "MAC",	.value = 0x0002,	.dpll_type = DPLL_TYPE_INT_OSCILLATOR },
>+	{ .name = "GNSS1",	.value = 0x0004,	.dpll_type = DPLL_TYPE_GNSS },
>+	{ .name = "GNSS2",	.value = 0x0008,	.dpll_type = DPLL_TYPE_GNSS },
>+	{ .name = "IRIG",	.value = 0x0010,	.dpll_type = DPLL_TYPE_CUSTOM },
>+	{ .name = "DCF",	.value = 0x0020,	.dpll_type = DPLL_TYPE_CUSTOM },
>+	{ .name = "GEN1",	.value = 0x0040,	.dpll_type = DPLL_TYPE_CUSTOM },
>+	{ .name = "GEN2",	.value = 0x0080,	.dpll_type = DPLL_TYPE_CUSTOM },
>+	{ .name = "GEN3",	.value = 0x0100,	.dpll_type = DPLL_TYPE_CUSTOM },
>+	{ .name = "GEN4",	.value = 0x0200,	.dpll_type = DPLL_TYPE_CUSTOM },
>+	{ .name = "GND",	.value = 0x2000,	.dpll_type = DPLL_TYPE_CUSTOM },
>+	{ .name = "VCC",	.value = 0x4000,	.dpll_type = DPLL_TYPE_CUSTOM },
> 	{ }
> };
> 
>@@ -3707,6 +3711,90 @@ ptp_ocp_detach(struct ptp_ocp *bp)
> 	device_unregister(&bp->dev);
> }
> 
>+static int ptp_ocp_dpll_get_status(struct dpll_device *dpll)
>+{
>+	struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll);
>+	int sync;
>+
>+	sync = ioread32(&bp->reg->status) & OCP_STATUS_IN_SYNC;
>+	return sync;
>+}
>+
>+static int ptp_ocp_dpll_get_lock_status(struct dpll_device *dpll)
>+{
>+	struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll);
>+	int sync;
>+
>+	sync = ioread32(&bp->reg->status) & OCP_STATUS_IN_SYNC;
>+	return sync;
>+}
>+
>+static int ptp_ocp_sma_get_dpll_type(struct ptp_ocp *bp, int sma_nr)
>+{
>+	const struct ocp_selector *tbl;
>+	u32 val;
>+
>+	if (bp->sma[sma_nr].mode == SMA_MODE_IN)
>+		tbl = bp->sma_op->tbl[0];
>+	else
>+		tbl = bp->sma_op->tbl[1];
>+
>+	val = ptp_ocp_sma_get(bp, sma_nr);
>+	return tbl[val].dpll_type;
>+}
>+
>+static int ptp_ocp_dpll_type_supported(struct dpll_device *dpll, int sma, int type, int dir)
>+{
>+	struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll);
>+	const struct ocp_selector *tbl = bp->sma_op->tbl[dir];
>+	int i;
>+
>+	for (i = 0; i < sizeof(*tbl); i++) {
>+		if (tbl[i].dpll_type == type)
>+			return 1;
>+	}
>+	return 0;
>+}
>+
>+static int ptp_ocp_dpll_get_source_type(struct dpll_device *dpll, int sma)
>+{
>+	struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll);
>+
>+	if (bp->sma[sma].mode != SMA_MODE_IN)
>+		return -1;
>+
>+	return ptp_ocp_sma_get_dpll_type(bp, sma);
>+}
>+
>+static int ptp_ocp_dpll_get_source_supported(struct dpll_device *dpll, int sma, int type)
>+{
>+	return ptp_ocp_dpll_type_supported(dpll, sma, type, 0);
>+}
>+
>+static int ptp_ocp_dpll_get_output_type(struct dpll_device *dpll, int sma)
>+{
>+	struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll);
>+
>+	if (bp->sma[sma].mode != SMA_MODE_OUT)
>+		return -1;
>+
>+	return ptp_ocp_sma_get_dpll_type(bp, sma);
>+}
>+
>+static int ptp_ocp_dpll_get_output_supported(struct dpll_device *dpll, int sma, int type)
>+{
>+	return ptp_ocp_dpll_type_supported(dpll, sma, type, 1);
>+}
>+
>+static struct dpll_device_ops dpll_ops = {

Namespace prefix?


>+	.get_status		= ptp_ocp_dpll_get_status,
>+	.get_lock_status	= ptp_ocp_dpll_get_lock_status,
>+	.get_source_type	= ptp_ocp_dpll_get_source_type,
>+	.get_source_supported	= ptp_ocp_dpll_get_source_supported,
>+	.get_output_type	= ptp_ocp_dpll_get_output_type,
>+	.get_output_supported	= ptp_ocp_dpll_get_output_supported,
>+};
>+
> static int
> ptp_ocp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
> {
>@@ -3762,6 +3850,14 @@ ptp_ocp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
> 
> 	ptp_ocp_info(bp);
> 	devlink_register(devlink);
>+
>+	bp->dpll = dpll_device_alloc(&dpll_ops, "ocp", ARRAY_SIZE(bp->sma), ARRAY_SIZE(bp->sma), bp);
>+	if (!bp->dpll) {

You have to use IS_ERR() macro here.


>+		dev_err(&pdev->dev, "dpll_device_alloc failed\n");
>+		return 0;
>+	}
>+	dpll_device_register(bp->dpll);
>+
> 	return 0;
> 
> out:
>@@ -3779,6 +3875,8 @@ ptp_ocp_remove(struct pci_dev *pdev)
> 	struct ptp_ocp *bp = pci_get_drvdata(pdev);
> 	struct devlink *devlink = priv_to_devlink(bp);
> 
>+	dpll_device_unregister(bp->dpll);
>+	dpll_device_free(bp->dpll);
> 	devlink_unregister(devlink);
> 	ptp_ocp_detach(bp);
> 	pci_disable_device(pdev);
>diff --git a/include/uapi/linux/dpll.h b/include/uapi/linux/dpll.h
>index 8782d3425aae..59fc6ef81b40 100644
>--- a/include/uapi/linux/dpll.h
>+++ b/include/uapi/linux/dpll.h
>@@ -55,11 +55,13 @@ enum dpll_genl_status {
> 
> /* DPLL signal types used as source or as output */
> enum dpll_genl_signal_type {
>+	DPLL_TYPE_NONE,
> 	DPLL_TYPE_EXT_1PPS,
> 	DPLL_TYPE_EXT_10MHZ,
> 	DPLL_TYPE_SYNCE_ETH_PORT,
> 	DPLL_TYPE_INT_OSCILLATOR,
> 	DPLL_TYPE_GNSS,
>+	DPLL_TYPE_CUSTOM,

This hunk should not be here.
I commented this on the previous version. Btw, this is not the only
thing that I previously commented and you ignored. It is annoying to be
honest. Could you please include the requested changes in next patchset
version or comment why you are not do including them. Ignoring is never
good :/


> 
> 	__DPLL_TYPE_MAX,
> };
>-- 
>2.27.0
>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 1/6] dpll: Add DPLL framework base functions
  2022-10-10  9:18     ` Jiri Pirko
@ 2022-10-10 19:54       ` Vadim Fedorenko
  -1 siblings, 0 replies; 67+ messages in thread
From: Vadim Fedorenko @ 2022-10-10 19:54 UTC (permalink / raw)
  To: Jiri Pirko
  Cc: Jakub Kicinski, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

On 10.10.2022 10:18, Jiri Pirko wrote:
> Mon, Oct 10, 2022 at 03:17:59AM CEST, vfedorenko@novek.ru wrote:
>> From: Vadim Fedorenko <vadfed@fb.com>
>>
>> DPLL framework is used to represent and configure DPLL devices
>> in systems. Each device that has DPLL and can configure sources
>> and outputs can use this framework.
>>
>> Signed-off-by: Vadim Fedorenko <vadfed@fb.com>
>> Co-developed-by: Jakub Kicinski <kuba@kernel.org>
>> Co-developed-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
>> ---
>> MAINTAINERS                 |   8 +
>> drivers/Kconfig             |   2 +
>> drivers/Makefile            |   1 +
>> drivers/dpll/Kconfig        |   7 +
>> drivers/dpll/Makefile       |   7 +
>> drivers/dpll/dpll_core.c    | 177 +++++++++++++++
>> drivers/dpll/dpll_core.h    |  41 ++++
>> drivers/dpll/dpll_netlink.c | 417 ++++++++++++++++++++++++++++++++++++
>> drivers/dpll/dpll_netlink.h |   7 +
>> include/linux/dpll.h        |  29 +++
>> include/uapi/linux/dpll.h   | 101 +++++++++
>> 11 files changed, 797 insertions(+)
>> create mode 100644 drivers/dpll/Kconfig
>> create mode 100644 drivers/dpll/Makefile
>> create mode 100644 drivers/dpll/dpll_core.c
>> create mode 100644 drivers/dpll/dpll_core.h
>> create mode 100644 drivers/dpll/dpll_netlink.c
>> create mode 100644 drivers/dpll/dpll_netlink.h
>> create mode 100644 include/linux/dpll.h
>> create mode 100644 include/uapi/linux/dpll.h
>>
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index 9ca84cb5ab4a..e2f4fede937f 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -6301,6 +6301,14 @@ F:	Documentation/networking/device_drivers/ethernet/freescale/dpaa2/switch-drive
>> F:	drivers/net/ethernet/freescale/dpaa2/dpaa2-switch*
>> F:	drivers/net/ethernet/freescale/dpaa2/dpsw*
>>
>> +DPLL CLOCK SUBSYSTEM
>> +M:	Vadim Fedorenko <vadfed@fb.com>
>> +L:	netdev@vger.kernel.org
>> +S:	Maintained
>> +F:	drivers/dpll/*
>> +F:	include/net/dpll.h
>> +F:	include/uapi/linux/dpll.h
>> +
>> DRBD DRIVER
>> M:	Philipp Reisner <philipp.reisner@linbit.com>
>> M:	Lars Ellenberg <lars.ellenberg@linbit.com>
>> diff --git a/drivers/Kconfig b/drivers/Kconfig
>> index 19ee995bd0ae..a3e00294a995 100644
>> --- a/drivers/Kconfig
>> +++ b/drivers/Kconfig
>> @@ -239,4 +239,6 @@ source "drivers/peci/Kconfig"
>>
>> source "drivers/hte/Kconfig"
>>
>> +source "drivers/dpll/Kconfig"
>> +
>> endmenu
>> diff --git a/drivers/Makefile b/drivers/Makefile
>> index 057857258bfd..78a68f1621cc 100644
>> --- a/drivers/Makefile
>> +++ b/drivers/Makefile
>> @@ -188,3 +188,4 @@ obj-$(CONFIG_COUNTER)		+= counter/
>> obj-$(CONFIG_MOST)		+= most/
>> obj-$(CONFIG_PECI)		+= peci/
>> obj-$(CONFIG_HTE)		+= hte/
>> +obj-$(CONFIG_DPLL)		+= dpll/
>> diff --git a/drivers/dpll/Kconfig b/drivers/dpll/Kconfig
>> new file mode 100644
>> index 000000000000..a4cae73f20d3
>> --- /dev/null
>> +++ b/drivers/dpll/Kconfig
>> @@ -0,0 +1,7 @@
>> +# SPDX-License-Identifier: GPL-2.0-only
>> +#
>> +# Generic DPLL drivers configuration
>> +#
>> +
>> +config DPLL
>> +  bool
>> diff --git a/drivers/dpll/Makefile b/drivers/dpll/Makefile
>> new file mode 100644
>> index 000000000000..0748c80097e4
>> --- /dev/null
>> +++ b/drivers/dpll/Makefile
>> @@ -0,0 +1,7 @@
>> +# SPDX-License-Identifier: GPL-2.0
>> +#
>> +# Makefile for DPLL drivers.
>> +#
>> +
>> +obj-$(CONFIG_DPLL)          += dpll_sys.o
>> +dpll_sys-y                  += dpll_core.o dpll_netlink.o
>> diff --git a/drivers/dpll/dpll_core.c b/drivers/dpll/dpll_core.c
>> new file mode 100644
>> index 000000000000..7fdee145e82c
>> --- /dev/null
>> +++ b/drivers/dpll/dpll_core.c
>> @@ -0,0 +1,177 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + *  dpll_core.c - Generic DPLL Management class support.
>> + *
>> + *  Copyright (c) 2021 Meta Platforms, Inc. and affiliates
>> + */
>> +
>> +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
>> +
>> +#include <linux/device.h>
>> +#include <linux/err.h>
>> +#include <linux/slab.h>
>> +#include <linux/string.h>
>> +
>> +#include "dpll_core.h"
>> +
>> +static DEFINE_MUTEX(dpll_device_xa_lock);
>> +static DEFINE_XARRAY_FLAGS(dpll_device_xa, XA_FLAGS_ALLOC);
>> +#define DPLL_REGISTERED XA_MARK_1
>> +
>> +#define ASSERT_DPLL_REGISTERED(d)                                           \
>> +	WARN_ON_ONCE(!xa_get_mark(&dpll_device_xa, (d)->id, DPLL_REGISTERED))
>> +#define ASSERT_DPLL_NOT_REGISTERED(d)                                      \
>> +	WARN_ON_ONCE(xa_get_mark(&dpll_device_xa, (d)->id, DPLL_REGISTERED))
>> +
>> +
>> +int for_each_dpll_device(int id, int (*cb)(struct dpll_device *, void *),
>> +			 void *data)
> 
> Probably better to avoid this "cb" indirection here.
> Perhaps in a similar way devlinks_xa_for_each_registered_get() is done?
>
Thanks for pointing to an example, I will consider avoid indirection.
checkpatch.pl is also complaining about this line, but the same way was used in
some other places that's why I chosed to use it.
> 
>> +{
>> +	struct dpll_device *dpll;
>> +	unsigned long index;
>> +	int ret = 0;
>> +
>> +	mutex_lock(&dpll_device_xa_lock);
>> +	xa_for_each_start(&dpll_device_xa, index, dpll, id) {
>> +		if (!xa_get_mark(&dpll_device_xa, index, DPLL_REGISTERED))
>> +			continue;
>> +		ret = cb(dpll, data);
>> +		if (ret)
>> +			break;
>> +	}
>> +	mutex_unlock(&dpll_device_xa_lock);
>> +
>> +	return ret;
>> +}
>> +
>> +struct dpll_device *dpll_device_get_by_id(int id)
>> +{
>> +	struct dpll_device *dpll = NULL;
>> +
>> +	if (xa_get_mark(&dpll_device_xa, id, DPLL_REGISTERED))
>> +		dpll = xa_load(&dpll_device_xa, id);
>> +	return dpll;
>> +}
>> +
>> +struct dpll_device *dpll_device_get_by_name(const char *name)
>> +{
>> +	struct dpll_device *dpll, *ret = NULL;
>> +	unsigned long index;
>> +
>> +	mutex_lock(&dpll_device_xa_lock);
>> +	xa_for_each_marked(&dpll_device_xa, index, dpll, DPLL_REGISTERED) {
>> +		if (!strcmp(dev_name(&dpll->dev), name)) {
>> +			ret = dpll;
>> +			break;
>> +		}
>> +	}
>> +	mutex_unlock(&dpll_device_xa_lock);
>> +
>> +	return ret;
>> +}
>> +
>> +void *dpll_priv(struct dpll_device *dpll)
>> +{
>> +	return dpll->priv;
>> +}
>> +EXPORT_SYMBOL_GPL(dpll_priv);
>> +
>> +static void dpll_device_release(struct device *dev)
>> +{
>> +	struct dpll_device *dpll;
>> +
>> +	dpll = to_dpll_device(dev);
>> +
>> +	dpll_device_unregister(dpll);
>> +	dpll_device_free(dpll);
>> +}
>> +
>> +static struct class dpll_class = {
>> +	.name = "dpll",
>> +	.dev_release = dpll_device_release,
>> +};
>> +
>> +struct dpll_device *dpll_device_alloc(struct dpll_device_ops *ops, const char *name,
>> +				      int sources_count, int outputs_count, void *priv)
>> +{
>> +	struct dpll_device *dpll;
>> +	int ret;
>> +
>> +	dpll = kzalloc(sizeof(*dpll), GFP_KERNEL);
>> +	if (!dpll)
>> +		return ERR_PTR(-ENOMEM);
>> +
>> +	mutex_init(&dpll->lock);
>> +	dpll->ops = ops;
>> +	dpll->dev.class = &dpll_class;
>> +	dpll->sources_count = sources_count;
>> +	dpll->outputs_count = outputs_count;
>> +
>> +	mutex_lock(&dpll_device_xa_lock);
>> +	ret = xa_alloc(&dpll_device_xa, &dpll->id, dpll, xa_limit_16b, GFP_KERNEL);
>> +	if (ret)
>> +		goto error;
>> +	dev_set_name(&dpll->dev, "%s%d", name ? name : "dpll", dpll->id);
>> +	mutex_unlock(&dpll_device_xa_lock);
>> +	dpll->priv = priv;
>> +
>> +	return dpll;
>> +
>> +error:
>> +	mutex_unlock(&dpll_device_xa_lock);
>> +	kfree(dpll);
>> +	return ERR_PTR(ret);
>> +}
>> +EXPORT_SYMBOL_GPL(dpll_device_alloc);
>> +
>> +void dpll_device_free(struct dpll_device *dpll)
>> +{
>> +	if (!dpll)
>> +		return;
>> +
>> +	mutex_destroy(&dpll->lock);
>> +	kfree(dpll);
>> +}
>> +EXPORT_SYMBOL_GPL(dpll_device_free);
>> +
>> +void dpll_device_register(struct dpll_device *dpll)
>> +{
>> +	ASSERT_DPLL_NOT_REGISTERED(dpll);
>> +
>> +	mutex_lock(&dpll_device_xa_lock);
>> +	xa_set_mark(&dpll_device_xa, dpll->id, DPLL_REGISTERED);
>> +	mutex_unlock(&dpll_device_xa_lock);
>> +}
>> +EXPORT_SYMBOL_GPL(dpll_device_register);
>> +
>> +void dpll_device_unregister(struct dpll_device *dpll)
>> +{
>> +	ASSERT_DPLL_REGISTERED(dpll);
>> +
>> +	mutex_lock(&dpll_device_xa_lock);
>> +	xa_erase(&dpll_device_xa, dpll->id);
>> +	mutex_unlock(&dpll_device_xa_lock);
>> +}
>> +EXPORT_SYMBOL_GPL(dpll_device_unregister);
>> +
>> +static int __init dpll_init(void)
>> +{
>> +	int ret;
>> +
>> +	ret = dpll_netlink_init();
>> +	if (ret)
>> +		goto error;
>> +
>> +	ret = class_register(&dpll_class);
>> +	if (ret)
>> +		goto unregister_netlink;
>> +
>> +	return 0;
>> +
>> +unregister_netlink:
>> +	dpll_netlink_finish();
>> +error:
>> +	mutex_destroy(&dpll_device_xa_lock);
>> +	return ret;
>> +}
>> +subsys_initcall(dpll_init);
>> diff --git a/drivers/dpll/dpll_core.h b/drivers/dpll/dpll_core.h
>> new file mode 100644
>> index 000000000000..4b6fc9eb228f
>> --- /dev/null
>> +++ b/drivers/dpll/dpll_core.h
>> @@ -0,0 +1,41 @@
>> +/* SPDX-License-Identifier: GPL-2.0 */
>> +/*
>> + *  Copyright (c) 2021 Meta Platforms, Inc. and affiliates
>> + */
>> +
>> +#ifndef __DPLL_CORE_H__
>> +#define __DPLL_CORE_H__
>> +
>> +#include <linux/dpll.h>
>> +
>> +#include "dpll_netlink.h"
>> +
>> +/**
>> + * struct dpll_device - structure for a DPLL device
>> + * @id:		unique id number for each edvice
>> + * @dev:	&struct device for this dpll device
>> + * @sources_count:	amount of input sources this dpll_device supports
>> + * @outputs_count:	amount of outputs this dpll_device supports
>> + * @ops:	operations this &dpll_device supports
>> + * @lock:	mutex to serialize operations
>> + * @priv:	pointer to private information of owner
>> + */
>> +struct dpll_device {
>> +	int id;
>> +	struct device dev;
>> +	int sources_count;
>> +	int outputs_count;
>> +	struct dpll_device_ops *ops;
>> +	struct mutex lock;
>> +	void *priv;
>> +};
>> +
>> +#define to_dpll_device(_dev) \
>> +	container_of(_dev, struct dpll_device, dev)
>> +
>> +int for_each_dpll_device(int id, int (*cb)(struct dpll_device *, void *),
>> +			  void *data);
>> +struct dpll_device *dpll_device_get_by_id(int id);
>> +struct dpll_device *dpll_device_get_by_name(const char *name);
>> +void dpll_device_unregister(struct dpll_device *dpll);
>> +#endif
>> diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c
>> new file mode 100644
>> index 000000000000..31966e0eec3a
>> --- /dev/null
>> +++ b/drivers/dpll/dpll_netlink.c
>> @@ -0,0 +1,417 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Generic netlink for DPLL management framework
>> + *
>> + * Copyright (c) 2021 Meta Platforms, Inc. and affiliates
>> + *
>> + */
>> +#include <linux/module.h>
>> +#include <linux/kernel.h>
>> +#include <net/genetlink.h>
>> +#include "dpll_core.h"
>> +
>> +#include <uapi/linux/dpll.h>
>> +
>> +static const struct genl_multicast_group dpll_genl_mcgrps[] = {
>> +	{ .name = DPLL_CONFIG_DEVICE_GROUP_NAME, },
>> +	{ .name = DPLL_CONFIG_SOURCE_GROUP_NAME, },
>> +	{ .name = DPLL_CONFIG_OUTPUT_GROUP_NAME, },
>> +	{ .name = DPLL_MONITOR_GROUP_NAME,  },
>> +};
>> +
>> +static const struct nla_policy dpll_genl_get_policy[] = {
>> +	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
>> +	[DPLLA_DEVICE_NAME]	= { .type = NLA_STRING,
>> +				    .len = DPLL_NAME_LENGTH },
>> +	[DPLLA_FLAGS]		= { .type = NLA_U32 },
>> +};
>> +
>> +static const struct nla_policy dpll_genl_set_source_policy[] = {
>> +	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
>> +	[DPLLA_SOURCE_ID]	= { .type = NLA_U32 },
>> +	[DPLLA_SOURCE_TYPE]	= { .type = NLA_U32 },
>> +};
>> +
>> +static const struct nla_policy dpll_genl_set_output_policy[] = {
>> +	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
>> +	[DPLLA_OUTPUT_ID]	= { .type = NLA_U32 },
>> +	[DPLLA_OUTPUT_TYPE]	= { .type = NLA_U32 },
>> +};
>> +
>> +struct param {
> 
> Namespace prefix please	.
>
Yep, will add.
> 
>> +	struct netlink_callback *cb;
>> +	struct dpll_device *dpll;
>> +	struct sk_buff *msg;
> 
> 
> 
>> +	int dpll_id;
>> +	int dpll_source_id;
>> +	int dpll_source_type;
>> +	int dpll_output_id;
>> +	int dpll_output_type;
> 
> I don't see where you use these 5.
> 
Yep, the implementation was improved, it looks like it's artifacts of the 
previous version.

> 
>> +};
>> +
>> +struct dpll_dump_ctx {
>> +	struct dpll_device *dev;
>> +	int flags;
>> +	int pos_idx;
> 
> 
> 
>> +	int pos_src_idx;
>> +	int pos_out_idx;
> 
> You don't use these 2.
> 

The same again, artifacts.

> 
>> +};
>> +
>> +typedef int (*cb_t)(struct param *);
>> +
>> +static struct genl_family dpll_gnl_family;
>> +
>> +static struct dpll_dump_ctx *dpll_dump_context(struct netlink_callback *cb)
>> +{
>> +	return (struct dpll_dump_ctx *)cb->ctx;
>> +}
>> +
>> +static int __dpll_cmd_device_dump_one(struct dpll_device *dpll,
>> +					   struct sk_buff *msg)
>> +{
>> +	if (nla_put_u32(msg, DPLLA_DEVICE_ID, dpll->id))
>> +		return -EMSGSIZE;
>> +
>> +	if (nla_put_string(msg, DPLLA_DEVICE_NAME, dev_name(&dpll->dev)))
>> +		return -EMSGSIZE;
>> +
>> +	return 0;
>> +}
>> +
>> +static int __dpll_cmd_dump_sources(struct dpll_device *dpll,
>> +					   struct sk_buff *msg)
>> +{
>> +	struct nlattr *src_attr;
>> +	int i, ret = 0, type;
>> +
>> +	for (i = 0; i < dpll->sources_count; i++) {
>> +		src_attr = nla_nest_start(msg, DPLLA_SOURCE);
>> +		if (!src_attr) {
>> +			ret = -EMSGSIZE;
>> +			break;
>> +		}
>> +		type = dpll->ops->get_source_type(dpll, i);
>> +		if (nla_put_u32(msg, DPLLA_SOURCE_ID, i) ||
>> +		    nla_put_u32(msg, DPLLA_SOURCE_TYPE, type)) {
>> +			nla_nest_cancel(msg, src_attr);
>> +			ret = -EMSGSIZE;
>> +			break;
>> +		}
>> +		if (dpll->ops->get_source_supported) {
>> +			for (type = 0; type <= DPLL_TYPE_MAX; type++) {
>> +				ret = dpll->ops->get_source_supported(dpll, i, type);
> 
> Okay, this looks weird to me. This implicates that it is possible to
> have for example:
> source index 0 of type 10
> source index 0 of type 11
> Both possible.
> 
> However, from how I understand this, each source if of certain fixed type.
> Either it is:
> SyncE port
> 1pps external input (SMA)
> 10MHZ external input (SMA)
> internal oscilator (free-running)
> GNSS (GPS)
> 
> So for example:
> index 0, type: 1pps external input (SMA)
> index 1, type: 10MHZ external input (
> index 2, type: SyncE port, netdev ifindex: 20
> index 3, type: SyncE port, netdev ifindex: 30
> 
> So 4 "source" objects, each of different type.
> In this case I can imagine that the netlink API might look something
> like:
> -> DPLL_CMD_SOURCE_GET - dump
>       ATTR_DEVICE_ID X
> 
> <- DPLL_CMD_SOURCE_GET
> 
>       ATTR_DEVICE_ID X
>       ATTR_SOURCE_INDEX 0
>       ATTR_SOURCE_TYPE EXT_1PPS
>       
>       ATTR_DEVICE_ID X
>       ATTR_SOURCE_INDEX 1
>       ATTR_SOURCE_TYPE EXT_10MHZ
>       
>       ATTR_DEVICE_ID X
>       ATTR_SOURCE_INDEX 2
>       ATTR_SOURCE_TYPE SYNCE_ETH_PORT
>       ATTR_SOURCE_NETDEV_IFINDEX 20
> 
>       ATTR_DEVICE_ID X
>       ATTR_SOURCE_INDEX 3
>       ATTR_SOURCE_TYPE SYNCE_ETH_PORT
>       ATTR_SOURCE_NETDEV_IFINDEX 30
> 
> You see kernel would dump 4 source objects.
> 
I see your point. We do have hardware which allows changing type of SMA 
connector, and even the direction, each SMA could be used as input/source or 
output of different signals. But there are limitation, like not all SMAs can 
produce IRIG-B signal or only some of them can be used to get GNSS 1PPS. The 
interface was created to cover such case. I believe we have to improve it to 
cover SyncE configuration better, but I personally don't have SyncE hardware 
ready to test and that's why I have to rely on suggestions from yours or 
Arkadiusz's experience. From what I can see now there is need for special 
attribute to link source to net device, and I'm happy to add it. In case of 
fixed configuration of sources, the device should provide only one type as 
supported and that's it.


> 
> 
>> +				if (ret && nla_put_u32(msg, DPLLA_SOURCE_SUPPORTED, type)) {
>> +					ret = -EMSGSIZE;
>> +					break;
>> +				}
>> +			}
>> +			ret = 0;
>> +		}
>> +		nla_nest_end(msg, src_attr);
>> +	}
>> +
>> +	return ret;
>> +}
>> +
>> +static int __dpll_cmd_dump_outputs(struct dpll_device *dpll,
>> +					   struct sk_buff *msg)
>> +{
>> +	struct nlattr *out_attr;
>> +	int i, ret = 0, type;
>> +
>> +	for (i = 0; i < dpll->outputs_count; i++) {
>> +		out_attr = nla_nest_start(msg, DPLLA_OUTPUT);
>> +		if (!out_attr) {
>> +			ret = -EMSGSIZE;
>> +			break;
>> +		}
>> +		type = dpll->ops->get_output_type(dpll, i);
>> +		if (nla_put_u32(msg, DPLLA_OUTPUT_ID, i) ||
>> +		    nla_put_u32(msg, DPLLA_OUTPUT_TYPE, type)) {
>> +			nla_nest_cancel(msg, out_attr);
>> +			ret = -EMSGSIZE;
>> +			break;
>> +		}
>> +		if (dpll->ops->get_output_supported) {
>> +			for (type = 0; type <= DPLL_TYPE_MAX; type++) {
>> +				ret = dpll->ops->get_output_supported(dpll, i, type);
>> +				if (ret && nla_put_u32(msg, DPLLA_OUTPUT_SUPPORTED, type)) {
> 
> This I believe is similar to sources, see my comment above.
> 
As I said, we have to cover the case when SMAs are flexible to configure.

> I believe we should have separate commands to GET and SET outputs and
> sources. That would make the object separation clear and will also help
> event model. See below I suggestion how output netlink API may look
> like (comment in header file near enum dpll_genl_cmd definition).
> 
> 
>> +					ret = -EMSGSIZE;
>> +					break;
>> +				}
>> +			}
>> +			ret = 0;
>> +		}
>> +		nla_nest_end(msg, out_attr);
>> +	}
>> +
>> +	return ret;
>> +}
>> +
>> +static int __dpll_cmd_dump_status(struct dpll_device *dpll,
>> +					   struct sk_buff *msg)
>> +{
>> +	int ret;
>> +
>> +	if (dpll->ops->get_status) {
>> +		ret = dpll->ops->get_status(dpll);
>> +		if (nla_put_u32(msg, DPLLA_STATUS, ret))
>> +			return -EMSGSIZE;
>> +	}
>> +
>> +	if (dpll->ops->get_temp) {
>> +		ret = dpll->ops->get_temp(dpll);
>> +		if (nla_put_u32(msg, DPLLA_TEMP, ret))
>> +			return -EMSGSIZE;
>> +	}
>> +
>> +	if (dpll->ops->get_lock_status) {
>> +		ret = dpll->ops->get_lock_status(dpll);
>> +		if (nla_put_u32(msg, DPLLA_LOCK_STATUS, ret))
>> +			return -EMSGSIZE;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static int
>> +dpll_device_dump_one(struct dpll_device *dpll, struct sk_buff *msg,
>> +		     u32 portid, u32 seq, int flags)
>> +{
>> +	struct nlattr *hdr;
>> +	int ret;
>> +
>> +	hdr = genlmsg_put(msg, portid, seq, &dpll_gnl_family, 0,
>> +			  DPLL_CMD_DEVICE_GET);
>> +	if (!hdr)
>> +		return -EMSGSIZE;
>> +
>> +	mutex_lock(&dpll->lock);
>> +	ret = __dpll_cmd_device_dump_one(dpll, msg);
>> +	if (ret)
>> +		goto out_unlock;
>> +
>> +	if (flags & DPLL_FLAG_SOURCES && dpll->ops->get_source_type) {
>> +		ret = __dpll_cmd_dump_sources(dpll, msg);
>> +		if (ret)
>> +			goto out_unlock;
>> +	}
>> +
>> +	if (flags & DPLL_FLAG_OUTPUTS && dpll->ops->get_output_type) {
>> +		ret = __dpll_cmd_dump_outputs(dpll, msg);
>> +		if (ret)
>> +			goto out_unlock;
>> +	}
>> +
>> +	if (flags & DPLL_FLAG_STATUS) {
>> +		ret = __dpll_cmd_dump_status(dpll, msg);
>> +		if (ret)
>> +			goto out_unlock;
>> +	}
>> +	mutex_unlock(&dpll->lock);
>> +	genlmsg_end(msg, hdr);
>> +
>> +	return 0;
>> +
>> +out_unlock:
>> +	mutex_unlock(&dpll->lock);
>> +	genlmsg_cancel(msg, hdr);
>> +
>> +	return ret;
>> +}
>> +
>> +static int dpll_genl_cmd_set_source(struct sk_buff *skb, struct genl_info *info)
>> +{
>> +	struct dpll_device *dpll = info->user_ptr[0];
>> +	struct nlattr **attrs = info->attrs;
>> +	int ret = 0, src_id, type;
> 
> Enums.
> 

Sure.

>> +
>> +	if (!attrs[DPLLA_SOURCE_ID] ||
>> +	    !attrs[DPLLA_SOURCE_TYPE])
>> +		return -EINVAL;
>> +
>> +	if (!dpll->ops->set_source_type)
>> +		return -EOPNOTSUPP;
>> +
>> +	src_id = nla_get_u32(attrs[DPLLA_SOURCE_ID]);
>> +	type = nla_get_u32(attrs[DPLLA_SOURCE_TYPE]);
> 
> 
> This looks odd to me. The user should just pass the index of source to
> select. Type should be static, and non-changeable.
> 
> 
>> +
>> +	mutex_lock(&dpll->lock);
>> +	ret = dpll->ops->set_source_type(dpll, src_id, type);
>> +	mutex_unlock(&dpll->lock);
>> +
>> +	return ret;
>> +}
>> +
>> +static int dpll_genl_cmd_set_output(struct sk_buff *skb, struct genl_info *info)
>> +{
>> +	struct dpll_device *dpll = info->user_ptr[0];
>> +	struct nlattr **attrs = info->attrs;
>> +	int ret = 0, out_id, type;
> 
> Enums.
> 
> 
>> +
>> +	if (!attrs[DPLLA_OUTPUT_ID] ||
>> +	    !attrs[DPLLA_OUTPUT_TYPE])
>> +		return -EINVAL;
>> +
>> +	if (!dpll->ops->set_output_type)
>> +		return -EOPNOTSUPP;
>> +
>> +	out_id = nla_get_u32(attrs[DPLLA_OUTPUT_ID]);
>> +	type = nla_get_u32(attrs[DPLLA_OUTPUT_TYPE]);
> 
> Same here, passing type here looks wrong.
> 
> 
> 
>> +
>> +	mutex_lock(&dpll->lock);
>> +	ret = dpll->ops->set_output_type(dpll, out_id, type);
>> +	mutex_unlock(&dpll->lock);
>> +
>> +	return ret;
>> +}
>> +
>> +static int dpll_device_loop_cb(struct dpll_device *dpll, void *data)
>> +{
>> +	struct dpll_dump_ctx *ctx;
>> +	struct param *p = (struct param *)data;
>> +
>> +	ctx = dpll_dump_context(p->cb);
>> +
>> +	ctx->pos_idx = dpll->id;
>> +
>> +	return dpll_device_dump_one(dpll, p->msg, 0, 0, ctx->flags);
>> +}
>> +
>> +static int
>> +dpll_cmd_device_dump(struct sk_buff *skb, struct netlink_callback *cb)
>> +{
>> +	struct dpll_dump_ctx *ctx = dpll_dump_context(cb);
>> +	struct param p = { .cb = cb, .msg = skb };
>> +
>> +	return for_each_dpll_device(ctx->pos_idx, dpll_device_loop_cb, &p);
>> +}
>> +
>> +static int
>> +dpll_genl_cmd_device_get_id(struct sk_buff *skb, struct genl_info *info)
> 
> Just "get", no "id" here.
> 

Got it.

> 
>> +{
>> +	struct dpll_device *dpll = info->user_ptr[0];
>> +	struct nlattr **attrs = info->attrs;
>> +	struct sk_buff *msg;
>> +	int flags = 0;
>> +	int ret;
>> +
>> +	if (attrs[DPLLA_FLAGS])
>> +		flags = nla_get_u32(attrs[DPLLA_FLAGS]);
>> +
>> +	msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
>> +	if (!msg)
>> +		return -ENOMEM;
>> +
>> +	ret = dpll_device_dump_one(dpll, msg, info->snd_portid, info->snd_seq,
>> +				   flags);
>> +	if (ret)
>> +		goto out_free_msg;
>> +
>> +	return genlmsg_reply(msg, info);
>> +
>> +out_free_msg:
>> +	nlmsg_free(msg);
>> +	return ret;
>> +
>> +}
>> +
>> +static int dpll_genl_cmd_start(struct netlink_callback *cb)
>> +{
>> +	const struct genl_dumpit_info *info = genl_dumpit_info(cb);
>> +	struct dpll_dump_ctx *ctx = dpll_dump_context(cb);
>> +
>> +	ctx->dev = NULL;
>> +	if (info->attrs[DPLLA_FLAGS])
>> +		ctx->flags = nla_get_u32(info->attrs[DPLLA_FLAGS]);
>> +	else
>> +		ctx->flags = 0;
>> +	ctx->pos_idx = 0;
>> +	ctx->pos_src_idx = 0;
>> +	ctx->pos_out_idx = 0;
>> +	return 0;
>> +}
>> +
>> +static int dpll_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
>> +						 struct genl_info *info)
>> +{
>> +	struct dpll_device *dpll_id = NULL, *dpll_name = NULL;
>> +
>> +	if (!info->attrs[DPLLA_DEVICE_ID] &&
>> +	    !info->attrs[DPLLA_DEVICE_NAME])
>> +		return -EINVAL;
>> +
>> +	if (info->attrs[DPLLA_DEVICE_ID]) {
>> +		u32 id = nla_get_u32(info->attrs[DPLLA_DEVICE_ID]);
>> +
>> +		dpll_id = dpll_device_get_by_id(id);
>> +		if (!dpll_id)
>> +			return -ENODEV;
>> +		info->user_ptr[0] = dpll_id;
> 
> struct dpll_device *dpll should be stored here.
> 
> 
>> +	}
>> +	if (info->attrs[DPLLA_DEVICE_NAME]) {
> 
> You define new API, have one clear handle for devices. Either name or
> ID. Having both is messy.
>
That was added after the discussion with Jakub and Arkadiusz where we agreed 
that the device could be referenced either by index or by name. The example is 
that userspace app can easily find specific DPLL device if it knows the name 
provided by a driver of that specific device. Without searching through sysfs to 
find index value. Later commands could be executed using index once it's known 
through CMD_GET_DEVICE/ATTR_DEVICE_NAME.
> 
>> +		const char *name = nla_data(info->attrs[DPLLA_DEVICE_NAME]);
>> +
>> +		dpll_name = dpll_device_get_by_name(name);
>> +		if (!dpll_name)
>> +			return -ENODEV;
>> +
>> +		if (dpll_id && dpll_name != dpll_id)
>> +			return -EINVAL;
>> +		info->user_ptr[0] = dpll_name;
> 
> struct dpll_device *dpll should be stored here.
>


Didn't get you, where should we store it?
dpll_name and dpll_id are of type struct dpll_device*,
and they are compared to avoid situation when both index and name are provided, 
but refer to different devices.

> 
> 
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static const struct genl_ops dpll_genl_ops[] = {
>> +	{
>> +		.cmd	= DPLL_CMD_DEVICE_GET,
>> +		.flags  = GENL_UNS_ADMIN_PERM,
>> +		.start	= dpll_genl_cmd_start,
>> +		.dumpit	= dpll_cmd_device_dump,
>> +		.doit	= dpll_genl_cmd_device_get_id,
>> +		.policy	= dpll_genl_get_policy,
>> +		.maxattr = ARRAY_SIZE(dpll_genl_get_policy) - 1,
>> +	},
>> +	{
>> +		.cmd	= DPLL_CMD_SET_SOURCE_TYPE,
>> +		.flags	= GENL_UNS_ADMIN_PERM,
>> +		.doit	= dpll_genl_cmd_set_source,
>> +		.policy	= dpll_genl_set_source_policy,
>> +		.maxattr = ARRAY_SIZE(dpll_genl_set_source_policy) - 1,
>> +	},
>> +	{
>> +		.cmd	= DPLL_CMD_SET_OUTPUT_TYPE,
>> +		.flags	= GENL_UNS_ADMIN_PERM,
>> +		.doit	= dpll_genl_cmd_set_output,
>> +		.policy	= dpll_genl_set_output_policy,
>> +		.maxattr = ARRAY_SIZE(dpll_genl_set_output_policy) - 1,
>> +	},
>> +};
>> +
>> +static struct genl_family dpll_gnl_family __ro_after_init = {
>> +	.hdrsize	= 0,
>> +	.name		= DPLL_FAMILY_NAME,
>> +	.version	= DPLL_VERSION,
>> +	.ops		= dpll_genl_ops,
>> +	.n_ops		= ARRAY_SIZE(dpll_genl_ops),
>> +	.mcgrps		= dpll_genl_mcgrps,
>> +	.n_mcgrps	= ARRAY_SIZE(dpll_genl_mcgrps),
>> +	.pre_doit	= dpll_pre_doit,
> 
> Have  .parallel_ops   = true,
> You have dpll->lock, you don't need genl, to protect you.
>

Yep, sure, thanks!

> 
>> +};
>> +
>> +int __init dpll_netlink_init(void)
>> +{
>> +	return genl_register_family(&dpll_gnl_family);
>> +}
>> +
>> +void dpll_netlink_finish(void)
>> +{
>> +	genl_unregister_family(&dpll_gnl_family);
>> +}
>> +
>> +void __exit dpll_netlink_fini(void)
>> +{
>> +	dpll_netlink_finish();
>> +}
>> diff --git a/drivers/dpll/dpll_netlink.h b/drivers/dpll/dpll_netlink.h
>> new file mode 100644
>> index 000000000000..e2d100f59dd6
>> --- /dev/null
>> +++ b/drivers/dpll/dpll_netlink.h
>> @@ -0,0 +1,7 @@
>> +/* SPDX-License-Identifier: GPL-2.0 */
>> +/*
>> + *  Copyright (c) 2021 Meta Platforms, Inc. and affiliates
>> + */
>> +
>> +int __init dpll_netlink_init(void);
>> +void dpll_netlink_finish(void);
>> diff --git a/include/linux/dpll.h b/include/linux/dpll.h
>> new file mode 100644
>> index 000000000000..9d49b19d03d9
>> --- /dev/null
>> +++ b/include/linux/dpll.h
>> @@ -0,0 +1,29 @@
>> +/* SPDX-License-Identifier: GPL-2.0 */
>> +/*
>> + *  Copyright (c) 2021 Meta Platforms, Inc. and affiliates
>> + */
>> +
>> +#ifndef __DPLL_H__
>> +#define __DPLL_H__
>> +
>> +struct dpll_device;
>> +
>> +struct dpll_device_ops {
>> +	int (*get_status)(struct dpll_device *dpll);
>> +	int (*get_temp)(struct dpll_device *dpll);
>> +	int (*get_lock_status)(struct dpll_device *dpll);
>> +	int (*get_source_type)(struct dpll_device *dpll, int id);
>> +	int (*get_source_supported)(struct dpll_device *dpll, int id, int type);
>> +	int (*get_output_type)(struct dpll_device *dpll, int id);
>> +	int (*get_output_supported)(struct dpll_device *dpll, int id, int type);
>> +	int (*set_source_type)(struct dpll_device *dpll, int id, int val);
>> +	int (*set_output_type)(struct dpll_device *dpll, int id, int val);
> 
> All int should be enums, when they are really enums. Makes things much
> nicer and easier to see what's what.
> 
Yep, will update it.
> 
> 
>> +};
>> +
>> +struct dpll_device *dpll_device_alloc(struct dpll_device_ops *ops, const char *name,
>> +				      int sources_count, int outputs_count, void *priv);
>> +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);
>> +#endif
>> diff --git a/include/uapi/linux/dpll.h b/include/uapi/linux/dpll.h
>> new file mode 100644
>> index 000000000000..fcbea5a5e4d6
>> --- /dev/null
>> +++ b/include/uapi/linux/dpll.h
>> @@ -0,0 +1,101 @@
>> +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
>> +#ifndef _UAPI_LINUX_DPLL_H
>> +#define _UAPI_LINUX_DPLL_H
>> +
>> +#define DPLL_NAME_LENGTH	20
>> +
>> +/* Adding event notification support elements */
>> +#define DPLL_FAMILY_NAME		"dpll"
>> +#define DPLL_VERSION			0x01
>> +#define DPLL_CONFIG_DEVICE_GROUP_NAME  "config"
>> +#define DPLL_CONFIG_SOURCE_GROUP_NAME  "source"
>> +#define DPLL_CONFIG_OUTPUT_GROUP_NAME  "output"
>> +#define DPLL_MONITOR_GROUP_NAME        "monitor"
> 
> What is exactly the reason for multiple multicast groups? Why you don't
> use one?
> 
Yes, I agree, there is no need to use multiple groups and I will remove them in 
the next version.

> 
>> +
>> +#define DPLL_FLAG_SOURCES	1
>> +#define DPLL_FLAG_OUTPUTS	2
>> +#define DPLL_FLAG_STATUS	4
> 
> I think it is more common to use either 0x prefix or (1<<X) expression
> But I don't think these flags are needed at all, if you have per-object
> messages.
> 
> 
>> +
>> +/* Attributes of dpll_genl_family */
>> +enum dpll_genl_attr {
> 
> I don't see need for "genl" here.
> Also, it is common to have consistency betwee enum name and members name.
> For example:
> 
> enum dpll_attr {
> 	DPLL_ATTR_UNSPEC,
> 	DPLL_ATTR_DEVICE_ID,
> 
> 	...
> }
> This applies to all enums in this file.
>
Got it, naming is always hard task. Will update all of them in the next version.

> 
>> +	DPLLA_UNSPEC,
>> +	DPLLA_DEVICE_ID,
>> +	DPLLA_DEVICE_NAME,
>> +	DPLLA_SOURCE,
>> +	DPLLA_SOURCE_ID,
> 
> "ID" sounds a bit odd. I think "index" would be more suitable.
> 
I just wanted to have shorter names to better fit 80 columns per line restrictions.
> 
>> +	DPLLA_SOURCE_TYPE,
>> +	DPLLA_SOURCE_SUPPORTED,
>> +	DPLLA_OUTPUT,
>> +	DPLLA_OUTPUT_ID,
>> +	DPLLA_OUTPUT_TYPE,
>> +	DPLLA_OUTPUT_SUPPORTED,
>> +	DPLLA_STATUS,
>> +	DPLLA_TEMP,
>> +	DPLLA_LOCK_STATUS,
>> +	DPLLA_FLAGS,
>> +
>> +	__DPLLA_MAX,
>> +};
>> +#define DPLLA_MAX (__DPLLA_MAX - 1)
>> +
>> +/* DPLL status provides information of device status */
>> +enum dpll_genl_status {
>> +	DPLL_STATUS_NONE,
>> +	DPLL_STATUS_CALIBRATING,
>> +	DPLL_STATUS_LOCKED,
>> +
>> +	__DPLL_STATUS_MAX,
>> +};
>> +#define DPLL_STATUS_MAX (__DPLL_STATUS_MAX - 1)
>> +
>> +/* DPLL signal types used as source or as output */
>> +enum dpll_genl_signal_type {
>> +	DPLL_TYPE_EXT_1PPS,
>> +	DPLL_TYPE_EXT_10MHZ,
>> +	DPLL_TYPE_SYNCE_ETH_PORT,
>> +	DPLL_TYPE_INT_OSCILLATOR,
>> +	DPLL_TYPE_GNSS,
>> +
>> +	__DPLL_TYPE_MAX,
>> +};
>> +#define DPLL_TYPE_MAX (__DPLL_TYPE_MAX - 1)
>> +
>> +/* DPLL lock status provides information of source used to lock the device */
>> +enum dpll_genl_lock_status {
>> +	DPLL_LOCK_STATUS_UNLOCKED,
>> +	DPLL_LOCK_STATUS_EXT_1PPS,
>> +	DPLL_LOCK_STATUS_EXT_10MHZ,
>> +	DPLL_LOCK_STATUS_SYNCE,
>> +	DPLL_LOCK_STATUS_INT_OSCILLATOR,
>> +	DPLL_LOCK_STATUS_GNSS,
> 
> I find it a bit odd and redundant to have lock status here as a separate
> enum. You have a souce selected (either autoselected or manualy
> selected). Then the status is either:
> "UNLOCKED"
> "LOCKED"
> "HOLDOVER"
> 
> Or something similar. The point is, don't have the "source type" as a
> part of lock status.
> 

Yes, it's a very good idea, I was thinking about the same, but it didn't end up 
in the code.

> 
>> +
>> +	__DPLL_LOCK_STATUS_MAX,
>> +};
>> +#define DPLL_LOCK_STATUS_MAX (__DPLL_LOCK_STATUS_MAX - 1)
>> +
>> +/* Events of dpll_genl_family */
>> +enum dpll_genl_event {
>> +	DPLL_EVENT_UNSPEC,
>> +	DPLL_EVENT_DEVICE_CREATE,		/* DPLL device creation */
>> +	DPLL_EVENT_DEVICE_DELETE,		/* DPLL device deletion */
>> +	DPLL_EVENT_STATUS_LOCKED,		/* DPLL device locked to source */
>> +	DPLL_EVENT_STATUS_UNLOCKED,	/* DPLL device freerun */
> 
> Again, redundant I belive. There should be one event,
> inside the message there should be and ATTR of the lock state.
> 
> Also, I believe there are 2 options:
> 1) follow the existing netlink models and have:
> DPLL_EVENT_DEVICE_NEW
>    - sent for new device
>    - sent for change with device
> DPLL_EVENT_DEVICE_DEL
>    - sent for removed device
> 2)
> DPLL_EVENT_DEVICE_NEW
>    - sent for new device
> DPLL_EVENT_DEVICE_DEL
>    - sent for removed device
> DPLL_EVENT_DEVICE_CHANGE
>    - sent for change with device
> 
> Bot options work fine I belive. The point is, you don't want to have
> "cmd" per one attr change. Changed the device, attrs are passed in one
> message.
>

I will try to change events this way, thanks.

> 
> 
>> +	DPLL_EVENT_SOURCE_CHANGE,		/* DPLL device source changed */
> 
> Similar here, source of device changed, should be just one attr in
> device message, see above.
> 

The WIP right now is going the way to have separate objects representing pins, 
which could be used as source/output or even mux device. And the whole part 
about sources and outputs is going to change. But I'll keep in mind that 
suggestion while implementing this new way.

> 
>> +	DPLL_EVENT_OUTPUT_CHANGE,		/* DPLL device output changed */
> 
> 
>> +
>> +	__DPLL_EVENT_MAX,
>> +};
>> +#define DPLL_EVENT_MAX (__DPLL_EVENT_MAX - 1)
>> +
>> +/* Commands supported by the dpll_genl_family */
>> +enum dpll_genl_cmd {
>> +	DPLL_CMD_UNSPEC,
>> +	DPLL_CMD_DEVICE_GET,	/* List of DPLL devices id */
>> +	DPLL_CMD_SET_SOURCE_TYPE,	/* Set the DPLL device source type */
> 
> This is confusing, you select "source", not "type".

As I said, we can have different types for one source.

> 
> Please be consistent in naming:
> DPLL_CMD_*_GET/SET

Sure

> 
> Also, to be consistend with other netlink interfaces, we don't need
> cmd per action, rather there should be OBJ_GET (can dump) and OBJ_SET
> commands, like this:
>     
>     DPLL_CMD_DEVICE_GET (can dump all present devices)
>     	ATTR_SOURCE_SELECT_MODE (current one)
>     	ATTR_SOURCE_INDEX (currect one)
>     DPLL_CMD_DEVICE_SET
>     	ATTR_SOURCE_INDEX (to set)
>     DPLL_CMD_DEVICE_SET
>     	ATTR_SOURCE_SELECT_MODE (to set)
> 

I believe we have to provide all the possible (or suitable) attributes in SET 
command too, to fully configure the source by one command only, right?

And I also think we have to provide special attribute to show which source is 
actually used to sync to, like ATTR_CONNECTED.

> 
>> +	DPLL_CMD_SET_OUTPUT_TYPE,	/* Set the DPLL device output type */
> 
> Similar to what I suggested for "source", we should
> enable to select the OUTPUT, the type should be static. Also instead,
> I belive we should have a list of outputs and basically just allow
> enable/disable individual outputs:
>     DPLL_CMD_OUTPUT_GET (can dump the list of available outputs)
> 	ATTR_ENABLED (or "CONNECTED" or whatever) of type bool
>     DPLL_CMD_OUTPUT_SET
> 	ATTR_ENABLED (or "CONNECTED" or whatever) of type bool
> 
> This is suitable for SyncE for example, when you have multiple netdev ports
> that are connected as "outputs", you can enable exactly those you you want.
> Example:
> # To list the available outputs:
> -> DPLL_CMD_OUTPUT_GET - dump
>       ATTR_DEVICE_ID X
> 
> <- DPLL_CMD_OUTPUT_GET
>       ATTR_DEVICE_ID X
>       ATTR_OUTPUT_INDEX 0
>       ATTR_OUTPUT_TYPE SYNCE_ETH_PORT
>       ATTR_OUTPUT_NETDEV_IFINDEX 20
>       ATTR_OUTPUT_ENABLED 0
>       
>       ATTR_DEVICE_ID X
>       ATTR_OUTPUT_INDEX 1
>       ATTR_OUTPUT_TYPE SYNCE_ETH_PORT
>       ATTR_OUTPUT_NETDEV_IFINDEX 30
>       ATTR_OUTPUT_ENABLED 0
> 
> # Now enable output with index 0
> -> DPLL_CMD_OUTPUT_SET
>       ATTR_DEVICE_ID X
>       ATTR_OUTPUT_INDEX 0
>       ATTR_OUTPUT_ENABLED 1
> 
Well, in case when we have flexible outputs, we can provide this information as 
special type, like DPLL_TYPE_DISABLED. Having other types configured on the 
output will assume that the OUTPUT is enabled.

> 
>> +
>> +	__DPLL_CMD_MAX,
>> +};
>> +#define DPLL_CMD_MAX (__DPLL_CMD_MAX - 1)
>> +
>> +#endif /* _UAPI_LINUX_DPLL_H */
>> -- 
>> 2.27.0
>>

Thanks for actionable feedback, I hope to prepare new version soon with all the 
comments and suggestions addressed!



^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 1/6] dpll: Add DPLL framework base functions
@ 2022-10-10 19:54       ` Vadim Fedorenko
  0 siblings, 0 replies; 67+ messages in thread
From: Vadim Fedorenko @ 2022-10-10 19:54 UTC (permalink / raw)
  To: Jiri Pirko
  Cc: Jakub Kicinski, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

On 10.10.2022 10:18, Jiri Pirko wrote:
> Mon, Oct 10, 2022 at 03:17:59AM CEST, vfedorenko@novek.ru wrote:
>> From: Vadim Fedorenko <vadfed@fb.com>
>>
>> DPLL framework is used to represent and configure DPLL devices
>> in systems. Each device that has DPLL and can configure sources
>> and outputs can use this framework.
>>
>> Signed-off-by: Vadim Fedorenko <vadfed@fb.com>
>> Co-developed-by: Jakub Kicinski <kuba@kernel.org>
>> Co-developed-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
>> ---
>> MAINTAINERS                 |   8 +
>> drivers/Kconfig             |   2 +
>> drivers/Makefile            |   1 +
>> drivers/dpll/Kconfig        |   7 +
>> drivers/dpll/Makefile       |   7 +
>> drivers/dpll/dpll_core.c    | 177 +++++++++++++++
>> drivers/dpll/dpll_core.h    |  41 ++++
>> drivers/dpll/dpll_netlink.c | 417 ++++++++++++++++++++++++++++++++++++
>> drivers/dpll/dpll_netlink.h |   7 +
>> include/linux/dpll.h        |  29 +++
>> include/uapi/linux/dpll.h   | 101 +++++++++
>> 11 files changed, 797 insertions(+)
>> create mode 100644 drivers/dpll/Kconfig
>> create mode 100644 drivers/dpll/Makefile
>> create mode 100644 drivers/dpll/dpll_core.c
>> create mode 100644 drivers/dpll/dpll_core.h
>> create mode 100644 drivers/dpll/dpll_netlink.c
>> create mode 100644 drivers/dpll/dpll_netlink.h
>> create mode 100644 include/linux/dpll.h
>> create mode 100644 include/uapi/linux/dpll.h
>>
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index 9ca84cb5ab4a..e2f4fede937f 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -6301,6 +6301,14 @@ F:	Documentation/networking/device_drivers/ethernet/freescale/dpaa2/switch-drive
>> F:	drivers/net/ethernet/freescale/dpaa2/dpaa2-switch*
>> F:	drivers/net/ethernet/freescale/dpaa2/dpsw*
>>
>> +DPLL CLOCK SUBSYSTEM
>> +M:	Vadim Fedorenko <vadfed@fb.com>
>> +L:	netdev@vger.kernel.org
>> +S:	Maintained
>> +F:	drivers/dpll/*
>> +F:	include/net/dpll.h
>> +F:	include/uapi/linux/dpll.h
>> +
>> DRBD DRIVER
>> M:	Philipp Reisner <philipp.reisner@linbit.com>
>> M:	Lars Ellenberg <lars.ellenberg@linbit.com>
>> diff --git a/drivers/Kconfig b/drivers/Kconfig
>> index 19ee995bd0ae..a3e00294a995 100644
>> --- a/drivers/Kconfig
>> +++ b/drivers/Kconfig
>> @@ -239,4 +239,6 @@ source "drivers/peci/Kconfig"
>>
>> source "drivers/hte/Kconfig"
>>
>> +source "drivers/dpll/Kconfig"
>> +
>> endmenu
>> diff --git a/drivers/Makefile b/drivers/Makefile
>> index 057857258bfd..78a68f1621cc 100644
>> --- a/drivers/Makefile
>> +++ b/drivers/Makefile
>> @@ -188,3 +188,4 @@ obj-$(CONFIG_COUNTER)		+= counter/
>> obj-$(CONFIG_MOST)		+= most/
>> obj-$(CONFIG_PECI)		+= peci/
>> obj-$(CONFIG_HTE)		+= hte/
>> +obj-$(CONFIG_DPLL)		+= dpll/
>> diff --git a/drivers/dpll/Kconfig b/drivers/dpll/Kconfig
>> new file mode 100644
>> index 000000000000..a4cae73f20d3
>> --- /dev/null
>> +++ b/drivers/dpll/Kconfig
>> @@ -0,0 +1,7 @@
>> +# SPDX-License-Identifier: GPL-2.0-only
>> +#
>> +# Generic DPLL drivers configuration
>> +#
>> +
>> +config DPLL
>> +  bool
>> diff --git a/drivers/dpll/Makefile b/drivers/dpll/Makefile
>> new file mode 100644
>> index 000000000000..0748c80097e4
>> --- /dev/null
>> +++ b/drivers/dpll/Makefile
>> @@ -0,0 +1,7 @@
>> +# SPDX-License-Identifier: GPL-2.0
>> +#
>> +# Makefile for DPLL drivers.
>> +#
>> +
>> +obj-$(CONFIG_DPLL)          += dpll_sys.o
>> +dpll_sys-y                  += dpll_core.o dpll_netlink.o
>> diff --git a/drivers/dpll/dpll_core.c b/drivers/dpll/dpll_core.c
>> new file mode 100644
>> index 000000000000..7fdee145e82c
>> --- /dev/null
>> +++ b/drivers/dpll/dpll_core.c
>> @@ -0,0 +1,177 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + *  dpll_core.c - Generic DPLL Management class support.
>> + *
>> + *  Copyright (c) 2021 Meta Platforms, Inc. and affiliates
>> + */
>> +
>> +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
>> +
>> +#include <linux/device.h>
>> +#include <linux/err.h>
>> +#include <linux/slab.h>
>> +#include <linux/string.h>
>> +
>> +#include "dpll_core.h"
>> +
>> +static DEFINE_MUTEX(dpll_device_xa_lock);
>> +static DEFINE_XARRAY_FLAGS(dpll_device_xa, XA_FLAGS_ALLOC);
>> +#define DPLL_REGISTERED XA_MARK_1
>> +
>> +#define ASSERT_DPLL_REGISTERED(d)                                           \
>> +	WARN_ON_ONCE(!xa_get_mark(&dpll_device_xa, (d)->id, DPLL_REGISTERED))
>> +#define ASSERT_DPLL_NOT_REGISTERED(d)                                      \
>> +	WARN_ON_ONCE(xa_get_mark(&dpll_device_xa, (d)->id, DPLL_REGISTERED))
>> +
>> +
>> +int for_each_dpll_device(int id, int (*cb)(struct dpll_device *, void *),
>> +			 void *data)
> 
> Probably better to avoid this "cb" indirection here.
> Perhaps in a similar way devlinks_xa_for_each_registered_get() is done?
>
Thanks for pointing to an example, I will consider avoid indirection.
checkpatch.pl is also complaining about this line, but the same way was used in
some other places that's why I chosed to use it.
> 
>> +{
>> +	struct dpll_device *dpll;
>> +	unsigned long index;
>> +	int ret = 0;
>> +
>> +	mutex_lock(&dpll_device_xa_lock);
>> +	xa_for_each_start(&dpll_device_xa, index, dpll, id) {
>> +		if (!xa_get_mark(&dpll_device_xa, index, DPLL_REGISTERED))
>> +			continue;
>> +		ret = cb(dpll, data);
>> +		if (ret)
>> +			break;
>> +	}
>> +	mutex_unlock(&dpll_device_xa_lock);
>> +
>> +	return ret;
>> +}
>> +
>> +struct dpll_device *dpll_device_get_by_id(int id)
>> +{
>> +	struct dpll_device *dpll = NULL;
>> +
>> +	if (xa_get_mark(&dpll_device_xa, id, DPLL_REGISTERED))
>> +		dpll = xa_load(&dpll_device_xa, id);
>> +	return dpll;
>> +}
>> +
>> +struct dpll_device *dpll_device_get_by_name(const char *name)
>> +{
>> +	struct dpll_device *dpll, *ret = NULL;
>> +	unsigned long index;
>> +
>> +	mutex_lock(&dpll_device_xa_lock);
>> +	xa_for_each_marked(&dpll_device_xa, index, dpll, DPLL_REGISTERED) {
>> +		if (!strcmp(dev_name(&dpll->dev), name)) {
>> +			ret = dpll;
>> +			break;
>> +		}
>> +	}
>> +	mutex_unlock(&dpll_device_xa_lock);
>> +
>> +	return ret;
>> +}
>> +
>> +void *dpll_priv(struct dpll_device *dpll)
>> +{
>> +	return dpll->priv;
>> +}
>> +EXPORT_SYMBOL_GPL(dpll_priv);
>> +
>> +static void dpll_device_release(struct device *dev)
>> +{
>> +	struct dpll_device *dpll;
>> +
>> +	dpll = to_dpll_device(dev);
>> +
>> +	dpll_device_unregister(dpll);
>> +	dpll_device_free(dpll);
>> +}
>> +
>> +static struct class dpll_class = {
>> +	.name = "dpll",
>> +	.dev_release = dpll_device_release,
>> +};
>> +
>> +struct dpll_device *dpll_device_alloc(struct dpll_device_ops *ops, const char *name,
>> +				      int sources_count, int outputs_count, void *priv)
>> +{
>> +	struct dpll_device *dpll;
>> +	int ret;
>> +
>> +	dpll = kzalloc(sizeof(*dpll), GFP_KERNEL);
>> +	if (!dpll)
>> +		return ERR_PTR(-ENOMEM);
>> +
>> +	mutex_init(&dpll->lock);
>> +	dpll->ops = ops;
>> +	dpll->dev.class = &dpll_class;
>> +	dpll->sources_count = sources_count;
>> +	dpll->outputs_count = outputs_count;
>> +
>> +	mutex_lock(&dpll_device_xa_lock);
>> +	ret = xa_alloc(&dpll_device_xa, &dpll->id, dpll, xa_limit_16b, GFP_KERNEL);
>> +	if (ret)
>> +		goto error;
>> +	dev_set_name(&dpll->dev, "%s%d", name ? name : "dpll", dpll->id);
>> +	mutex_unlock(&dpll_device_xa_lock);
>> +	dpll->priv = priv;
>> +
>> +	return dpll;
>> +
>> +error:
>> +	mutex_unlock(&dpll_device_xa_lock);
>> +	kfree(dpll);
>> +	return ERR_PTR(ret);
>> +}
>> +EXPORT_SYMBOL_GPL(dpll_device_alloc);
>> +
>> +void dpll_device_free(struct dpll_device *dpll)
>> +{
>> +	if (!dpll)
>> +		return;
>> +
>> +	mutex_destroy(&dpll->lock);
>> +	kfree(dpll);
>> +}
>> +EXPORT_SYMBOL_GPL(dpll_device_free);
>> +
>> +void dpll_device_register(struct dpll_device *dpll)
>> +{
>> +	ASSERT_DPLL_NOT_REGISTERED(dpll);
>> +
>> +	mutex_lock(&dpll_device_xa_lock);
>> +	xa_set_mark(&dpll_device_xa, dpll->id, DPLL_REGISTERED);
>> +	mutex_unlock(&dpll_device_xa_lock);
>> +}
>> +EXPORT_SYMBOL_GPL(dpll_device_register);
>> +
>> +void dpll_device_unregister(struct dpll_device *dpll)
>> +{
>> +	ASSERT_DPLL_REGISTERED(dpll);
>> +
>> +	mutex_lock(&dpll_device_xa_lock);
>> +	xa_erase(&dpll_device_xa, dpll->id);
>> +	mutex_unlock(&dpll_device_xa_lock);
>> +}
>> +EXPORT_SYMBOL_GPL(dpll_device_unregister);
>> +
>> +static int __init dpll_init(void)
>> +{
>> +	int ret;
>> +
>> +	ret = dpll_netlink_init();
>> +	if (ret)
>> +		goto error;
>> +
>> +	ret = class_register(&dpll_class);
>> +	if (ret)
>> +		goto unregister_netlink;
>> +
>> +	return 0;
>> +
>> +unregister_netlink:
>> +	dpll_netlink_finish();
>> +error:
>> +	mutex_destroy(&dpll_device_xa_lock);
>> +	return ret;
>> +}
>> +subsys_initcall(dpll_init);
>> diff --git a/drivers/dpll/dpll_core.h b/drivers/dpll/dpll_core.h
>> new file mode 100644
>> index 000000000000..4b6fc9eb228f
>> --- /dev/null
>> +++ b/drivers/dpll/dpll_core.h
>> @@ -0,0 +1,41 @@
>> +/* SPDX-License-Identifier: GPL-2.0 */
>> +/*
>> + *  Copyright (c) 2021 Meta Platforms, Inc. and affiliates
>> + */
>> +
>> +#ifndef __DPLL_CORE_H__
>> +#define __DPLL_CORE_H__
>> +
>> +#include <linux/dpll.h>
>> +
>> +#include "dpll_netlink.h"
>> +
>> +/**
>> + * struct dpll_device - structure for a DPLL device
>> + * @id:		unique id number for each edvice
>> + * @dev:	&struct device for this dpll device
>> + * @sources_count:	amount of input sources this dpll_device supports
>> + * @outputs_count:	amount of outputs this dpll_device supports
>> + * @ops:	operations this &dpll_device supports
>> + * @lock:	mutex to serialize operations
>> + * @priv:	pointer to private information of owner
>> + */
>> +struct dpll_device {
>> +	int id;
>> +	struct device dev;
>> +	int sources_count;
>> +	int outputs_count;
>> +	struct dpll_device_ops *ops;
>> +	struct mutex lock;
>> +	void *priv;
>> +};
>> +
>> +#define to_dpll_device(_dev) \
>> +	container_of(_dev, struct dpll_device, dev)
>> +
>> +int for_each_dpll_device(int id, int (*cb)(struct dpll_device *, void *),
>> +			  void *data);
>> +struct dpll_device *dpll_device_get_by_id(int id);
>> +struct dpll_device *dpll_device_get_by_name(const char *name);
>> +void dpll_device_unregister(struct dpll_device *dpll);
>> +#endif
>> diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c
>> new file mode 100644
>> index 000000000000..31966e0eec3a
>> --- /dev/null
>> +++ b/drivers/dpll/dpll_netlink.c
>> @@ -0,0 +1,417 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Generic netlink for DPLL management framework
>> + *
>> + * Copyright (c) 2021 Meta Platforms, Inc. and affiliates
>> + *
>> + */
>> +#include <linux/module.h>
>> +#include <linux/kernel.h>
>> +#include <net/genetlink.h>
>> +#include "dpll_core.h"
>> +
>> +#include <uapi/linux/dpll.h>
>> +
>> +static const struct genl_multicast_group dpll_genl_mcgrps[] = {
>> +	{ .name = DPLL_CONFIG_DEVICE_GROUP_NAME, },
>> +	{ .name = DPLL_CONFIG_SOURCE_GROUP_NAME, },
>> +	{ .name = DPLL_CONFIG_OUTPUT_GROUP_NAME, },
>> +	{ .name = DPLL_MONITOR_GROUP_NAME,  },
>> +};
>> +
>> +static const struct nla_policy dpll_genl_get_policy[] = {
>> +	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
>> +	[DPLLA_DEVICE_NAME]	= { .type = NLA_STRING,
>> +				    .len = DPLL_NAME_LENGTH },
>> +	[DPLLA_FLAGS]		= { .type = NLA_U32 },
>> +};
>> +
>> +static const struct nla_policy dpll_genl_set_source_policy[] = {
>> +	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
>> +	[DPLLA_SOURCE_ID]	= { .type = NLA_U32 },
>> +	[DPLLA_SOURCE_TYPE]	= { .type = NLA_U32 },
>> +};
>> +
>> +static const struct nla_policy dpll_genl_set_output_policy[] = {
>> +	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
>> +	[DPLLA_OUTPUT_ID]	= { .type = NLA_U32 },
>> +	[DPLLA_OUTPUT_TYPE]	= { .type = NLA_U32 },
>> +};
>> +
>> +struct param {
> 
> Namespace prefix please	.
>
Yep, will add.
> 
>> +	struct netlink_callback *cb;
>> +	struct dpll_device *dpll;
>> +	struct sk_buff *msg;
> 
> 
> 
>> +	int dpll_id;
>> +	int dpll_source_id;
>> +	int dpll_source_type;
>> +	int dpll_output_id;
>> +	int dpll_output_type;
> 
> I don't see where you use these 5.
> 
Yep, the implementation was improved, it looks like it's artifacts of the 
previous version.

> 
>> +};
>> +
>> +struct dpll_dump_ctx {
>> +	struct dpll_device *dev;
>> +	int flags;
>> +	int pos_idx;
> 
> 
> 
>> +	int pos_src_idx;
>> +	int pos_out_idx;
> 
> You don't use these 2.
> 

The same again, artifacts.

> 
>> +};
>> +
>> +typedef int (*cb_t)(struct param *);
>> +
>> +static struct genl_family dpll_gnl_family;
>> +
>> +static struct dpll_dump_ctx *dpll_dump_context(struct netlink_callback *cb)
>> +{
>> +	return (struct dpll_dump_ctx *)cb->ctx;
>> +}
>> +
>> +static int __dpll_cmd_device_dump_one(struct dpll_device *dpll,
>> +					   struct sk_buff *msg)
>> +{
>> +	if (nla_put_u32(msg, DPLLA_DEVICE_ID, dpll->id))
>> +		return -EMSGSIZE;
>> +
>> +	if (nla_put_string(msg, DPLLA_DEVICE_NAME, dev_name(&dpll->dev)))
>> +		return -EMSGSIZE;
>> +
>> +	return 0;
>> +}
>> +
>> +static int __dpll_cmd_dump_sources(struct dpll_device *dpll,
>> +					   struct sk_buff *msg)
>> +{
>> +	struct nlattr *src_attr;
>> +	int i, ret = 0, type;
>> +
>> +	for (i = 0; i < dpll->sources_count; i++) {
>> +		src_attr = nla_nest_start(msg, DPLLA_SOURCE);
>> +		if (!src_attr) {
>> +			ret = -EMSGSIZE;
>> +			break;
>> +		}
>> +		type = dpll->ops->get_source_type(dpll, i);
>> +		if (nla_put_u32(msg, DPLLA_SOURCE_ID, i) ||
>> +		    nla_put_u32(msg, DPLLA_SOURCE_TYPE, type)) {
>> +			nla_nest_cancel(msg, src_attr);
>> +			ret = -EMSGSIZE;
>> +			break;
>> +		}
>> +		if (dpll->ops->get_source_supported) {
>> +			for (type = 0; type <= DPLL_TYPE_MAX; type++) {
>> +				ret = dpll->ops->get_source_supported(dpll, i, type);
> 
> Okay, this looks weird to me. This implicates that it is possible to
> have for example:
> source index 0 of type 10
> source index 0 of type 11
> Both possible.
> 
> However, from how I understand this, each source if of certain fixed type.
> Either it is:
> SyncE port
> 1pps external input (SMA)
> 10MHZ external input (SMA)
> internal oscilator (free-running)
> GNSS (GPS)
> 
> So for example:
> index 0, type: 1pps external input (SMA)
> index 1, type: 10MHZ external input (
> index 2, type: SyncE port, netdev ifindex: 20
> index 3, type: SyncE port, netdev ifindex: 30
> 
> So 4 "source" objects, each of different type.
> In this case I can imagine that the netlink API might look something
> like:
> -> DPLL_CMD_SOURCE_GET - dump
>       ATTR_DEVICE_ID X
> 
> <- DPLL_CMD_SOURCE_GET
> 
>       ATTR_DEVICE_ID X
>       ATTR_SOURCE_INDEX 0
>       ATTR_SOURCE_TYPE EXT_1PPS
>       
>       ATTR_DEVICE_ID X
>       ATTR_SOURCE_INDEX 1
>       ATTR_SOURCE_TYPE EXT_10MHZ
>       
>       ATTR_DEVICE_ID X
>       ATTR_SOURCE_INDEX 2
>       ATTR_SOURCE_TYPE SYNCE_ETH_PORT
>       ATTR_SOURCE_NETDEV_IFINDEX 20
> 
>       ATTR_DEVICE_ID X
>       ATTR_SOURCE_INDEX 3
>       ATTR_SOURCE_TYPE SYNCE_ETH_PORT
>       ATTR_SOURCE_NETDEV_IFINDEX 30
> 
> You see kernel would dump 4 source objects.
> 
I see your point. We do have hardware which allows changing type of SMA 
connector, and even the direction, each SMA could be used as input/source or 
output of different signals. But there are limitation, like not all SMAs can 
produce IRIG-B signal or only some of them can be used to get GNSS 1PPS. The 
interface was created to cover such case. I believe we have to improve it to 
cover SyncE configuration better, but I personally don't have SyncE hardware 
ready to test and that's why I have to rely on suggestions from yours or 
Arkadiusz's experience. From what I can see now there is need for special 
attribute to link source to net device, and I'm happy to add it. In case of 
fixed configuration of sources, the device should provide only one type as 
supported and that's it.


> 
> 
>> +				if (ret && nla_put_u32(msg, DPLLA_SOURCE_SUPPORTED, type)) {
>> +					ret = -EMSGSIZE;
>> +					break;
>> +				}
>> +			}
>> +			ret = 0;
>> +		}
>> +		nla_nest_end(msg, src_attr);
>> +	}
>> +
>> +	return ret;
>> +}
>> +
>> +static int __dpll_cmd_dump_outputs(struct dpll_device *dpll,
>> +					   struct sk_buff *msg)
>> +{
>> +	struct nlattr *out_attr;
>> +	int i, ret = 0, type;
>> +
>> +	for (i = 0; i < dpll->outputs_count; i++) {
>> +		out_attr = nla_nest_start(msg, DPLLA_OUTPUT);
>> +		if (!out_attr) {
>> +			ret = -EMSGSIZE;
>> +			break;
>> +		}
>> +		type = dpll->ops->get_output_type(dpll, i);
>> +		if (nla_put_u32(msg, DPLLA_OUTPUT_ID, i) ||
>> +		    nla_put_u32(msg, DPLLA_OUTPUT_TYPE, type)) {
>> +			nla_nest_cancel(msg, out_attr);
>> +			ret = -EMSGSIZE;
>> +			break;
>> +		}
>> +		if (dpll->ops->get_output_supported) {
>> +			for (type = 0; type <= DPLL_TYPE_MAX; type++) {
>> +				ret = dpll->ops->get_output_supported(dpll, i, type);
>> +				if (ret && nla_put_u32(msg, DPLLA_OUTPUT_SUPPORTED, type)) {
> 
> This I believe is similar to sources, see my comment above.
> 
As I said, we have to cover the case when SMAs are flexible to configure.

> I believe we should have separate commands to GET and SET outputs and
> sources. That would make the object separation clear and will also help
> event model. See below I suggestion how output netlink API may look
> like (comment in header file near enum dpll_genl_cmd definition).
> 
> 
>> +					ret = -EMSGSIZE;
>> +					break;
>> +				}
>> +			}
>> +			ret = 0;
>> +		}
>> +		nla_nest_end(msg, out_attr);
>> +	}
>> +
>> +	return ret;
>> +}
>> +
>> +static int __dpll_cmd_dump_status(struct dpll_device *dpll,
>> +					   struct sk_buff *msg)
>> +{
>> +	int ret;
>> +
>> +	if (dpll->ops->get_status) {
>> +		ret = dpll->ops->get_status(dpll);
>> +		if (nla_put_u32(msg, DPLLA_STATUS, ret))
>> +			return -EMSGSIZE;
>> +	}
>> +
>> +	if (dpll->ops->get_temp) {
>> +		ret = dpll->ops->get_temp(dpll);
>> +		if (nla_put_u32(msg, DPLLA_TEMP, ret))
>> +			return -EMSGSIZE;
>> +	}
>> +
>> +	if (dpll->ops->get_lock_status) {
>> +		ret = dpll->ops->get_lock_status(dpll);
>> +		if (nla_put_u32(msg, DPLLA_LOCK_STATUS, ret))
>> +			return -EMSGSIZE;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static int
>> +dpll_device_dump_one(struct dpll_device *dpll, struct sk_buff *msg,
>> +		     u32 portid, u32 seq, int flags)
>> +{
>> +	struct nlattr *hdr;
>> +	int ret;
>> +
>> +	hdr = genlmsg_put(msg, portid, seq, &dpll_gnl_family, 0,
>> +			  DPLL_CMD_DEVICE_GET);
>> +	if (!hdr)
>> +		return -EMSGSIZE;
>> +
>> +	mutex_lock(&dpll->lock);
>> +	ret = __dpll_cmd_device_dump_one(dpll, msg);
>> +	if (ret)
>> +		goto out_unlock;
>> +
>> +	if (flags & DPLL_FLAG_SOURCES && dpll->ops->get_source_type) {
>> +		ret = __dpll_cmd_dump_sources(dpll, msg);
>> +		if (ret)
>> +			goto out_unlock;
>> +	}
>> +
>> +	if (flags & DPLL_FLAG_OUTPUTS && dpll->ops->get_output_type) {
>> +		ret = __dpll_cmd_dump_outputs(dpll, msg);
>> +		if (ret)
>> +			goto out_unlock;
>> +	}
>> +
>> +	if (flags & DPLL_FLAG_STATUS) {
>> +		ret = __dpll_cmd_dump_status(dpll, msg);
>> +		if (ret)
>> +			goto out_unlock;
>> +	}
>> +	mutex_unlock(&dpll->lock);
>> +	genlmsg_end(msg, hdr);
>> +
>> +	return 0;
>> +
>> +out_unlock:
>> +	mutex_unlock(&dpll->lock);
>> +	genlmsg_cancel(msg, hdr);
>> +
>> +	return ret;
>> +}
>> +
>> +static int dpll_genl_cmd_set_source(struct sk_buff *skb, struct genl_info *info)
>> +{
>> +	struct dpll_device *dpll = info->user_ptr[0];
>> +	struct nlattr **attrs = info->attrs;
>> +	int ret = 0, src_id, type;
> 
> Enums.
> 

Sure.

>> +
>> +	if (!attrs[DPLLA_SOURCE_ID] ||
>> +	    !attrs[DPLLA_SOURCE_TYPE])
>> +		return -EINVAL;
>> +
>> +	if (!dpll->ops->set_source_type)
>> +		return -EOPNOTSUPP;
>> +
>> +	src_id = nla_get_u32(attrs[DPLLA_SOURCE_ID]);
>> +	type = nla_get_u32(attrs[DPLLA_SOURCE_TYPE]);
> 
> 
> This looks odd to me. The user should just pass the index of source to
> select. Type should be static, and non-changeable.
> 
> 
>> +
>> +	mutex_lock(&dpll->lock);
>> +	ret = dpll->ops->set_source_type(dpll, src_id, type);
>> +	mutex_unlock(&dpll->lock);
>> +
>> +	return ret;
>> +}
>> +
>> +static int dpll_genl_cmd_set_output(struct sk_buff *skb, struct genl_info *info)
>> +{
>> +	struct dpll_device *dpll = info->user_ptr[0];
>> +	struct nlattr **attrs = info->attrs;
>> +	int ret = 0, out_id, type;
> 
> Enums.
> 
> 
>> +
>> +	if (!attrs[DPLLA_OUTPUT_ID] ||
>> +	    !attrs[DPLLA_OUTPUT_TYPE])
>> +		return -EINVAL;
>> +
>> +	if (!dpll->ops->set_output_type)
>> +		return -EOPNOTSUPP;
>> +
>> +	out_id = nla_get_u32(attrs[DPLLA_OUTPUT_ID]);
>> +	type = nla_get_u32(attrs[DPLLA_OUTPUT_TYPE]);
> 
> Same here, passing type here looks wrong.
> 
> 
> 
>> +
>> +	mutex_lock(&dpll->lock);
>> +	ret = dpll->ops->set_output_type(dpll, out_id, type);
>> +	mutex_unlock(&dpll->lock);
>> +
>> +	return ret;
>> +}
>> +
>> +static int dpll_device_loop_cb(struct dpll_device *dpll, void *data)
>> +{
>> +	struct dpll_dump_ctx *ctx;
>> +	struct param *p = (struct param *)data;
>> +
>> +	ctx = dpll_dump_context(p->cb);
>> +
>> +	ctx->pos_idx = dpll->id;
>> +
>> +	return dpll_device_dump_one(dpll, p->msg, 0, 0, ctx->flags);
>> +}
>> +
>> +static int
>> +dpll_cmd_device_dump(struct sk_buff *skb, struct netlink_callback *cb)
>> +{
>> +	struct dpll_dump_ctx *ctx = dpll_dump_context(cb);
>> +	struct param p = { .cb = cb, .msg = skb };
>> +
>> +	return for_each_dpll_device(ctx->pos_idx, dpll_device_loop_cb, &p);
>> +}
>> +
>> +static int
>> +dpll_genl_cmd_device_get_id(struct sk_buff *skb, struct genl_info *info)
> 
> Just "get", no "id" here.
> 

Got it.

> 
>> +{
>> +	struct dpll_device *dpll = info->user_ptr[0];
>> +	struct nlattr **attrs = info->attrs;
>> +	struct sk_buff *msg;
>> +	int flags = 0;
>> +	int ret;
>> +
>> +	if (attrs[DPLLA_FLAGS])
>> +		flags = nla_get_u32(attrs[DPLLA_FLAGS]);
>> +
>> +	msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
>> +	if (!msg)
>> +		return -ENOMEM;
>> +
>> +	ret = dpll_device_dump_one(dpll, msg, info->snd_portid, info->snd_seq,
>> +				   flags);
>> +	if (ret)
>> +		goto out_free_msg;
>> +
>> +	return genlmsg_reply(msg, info);
>> +
>> +out_free_msg:
>> +	nlmsg_free(msg);
>> +	return ret;
>> +
>> +}
>> +
>> +static int dpll_genl_cmd_start(struct netlink_callback *cb)
>> +{
>> +	const struct genl_dumpit_info *info = genl_dumpit_info(cb);
>> +	struct dpll_dump_ctx *ctx = dpll_dump_context(cb);
>> +
>> +	ctx->dev = NULL;
>> +	if (info->attrs[DPLLA_FLAGS])
>> +		ctx->flags = nla_get_u32(info->attrs[DPLLA_FLAGS]);
>> +	else
>> +		ctx->flags = 0;
>> +	ctx->pos_idx = 0;
>> +	ctx->pos_src_idx = 0;
>> +	ctx->pos_out_idx = 0;
>> +	return 0;
>> +}
>> +
>> +static int dpll_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
>> +						 struct genl_info *info)
>> +{
>> +	struct dpll_device *dpll_id = NULL, *dpll_name = NULL;
>> +
>> +	if (!info->attrs[DPLLA_DEVICE_ID] &&
>> +	    !info->attrs[DPLLA_DEVICE_NAME])
>> +		return -EINVAL;
>> +
>> +	if (info->attrs[DPLLA_DEVICE_ID]) {
>> +		u32 id = nla_get_u32(info->attrs[DPLLA_DEVICE_ID]);
>> +
>> +		dpll_id = dpll_device_get_by_id(id);
>> +		if (!dpll_id)
>> +			return -ENODEV;
>> +		info->user_ptr[0] = dpll_id;
> 
> struct dpll_device *dpll should be stored here.
> 
> 
>> +	}
>> +	if (info->attrs[DPLLA_DEVICE_NAME]) {
> 
> You define new API, have one clear handle for devices. Either name or
> ID. Having both is messy.
>
That was added after the discussion with Jakub and Arkadiusz where we agreed 
that the device could be referenced either by index or by name. The example is 
that userspace app can easily find specific DPLL device if it knows the name 
provided by a driver of that specific device. Without searching through sysfs to 
find index value. Later commands could be executed using index once it's known 
through CMD_GET_DEVICE/ATTR_DEVICE_NAME.
> 
>> +		const char *name = nla_data(info->attrs[DPLLA_DEVICE_NAME]);
>> +
>> +		dpll_name = dpll_device_get_by_name(name);
>> +		if (!dpll_name)
>> +			return -ENODEV;
>> +
>> +		if (dpll_id && dpll_name != dpll_id)
>> +			return -EINVAL;
>> +		info->user_ptr[0] = dpll_name;
> 
> struct dpll_device *dpll should be stored here.
>


Didn't get you, where should we store it?
dpll_name and dpll_id are of type struct dpll_device*,
and they are compared to avoid situation when both index and name are provided, 
but refer to different devices.

> 
> 
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static const struct genl_ops dpll_genl_ops[] = {
>> +	{
>> +		.cmd	= DPLL_CMD_DEVICE_GET,
>> +		.flags  = GENL_UNS_ADMIN_PERM,
>> +		.start	= dpll_genl_cmd_start,
>> +		.dumpit	= dpll_cmd_device_dump,
>> +		.doit	= dpll_genl_cmd_device_get_id,
>> +		.policy	= dpll_genl_get_policy,
>> +		.maxattr = ARRAY_SIZE(dpll_genl_get_policy) - 1,
>> +	},
>> +	{
>> +		.cmd	= DPLL_CMD_SET_SOURCE_TYPE,
>> +		.flags	= GENL_UNS_ADMIN_PERM,
>> +		.doit	= dpll_genl_cmd_set_source,
>> +		.policy	= dpll_genl_set_source_policy,
>> +		.maxattr = ARRAY_SIZE(dpll_genl_set_source_policy) - 1,
>> +	},
>> +	{
>> +		.cmd	= DPLL_CMD_SET_OUTPUT_TYPE,
>> +		.flags	= GENL_UNS_ADMIN_PERM,
>> +		.doit	= dpll_genl_cmd_set_output,
>> +		.policy	= dpll_genl_set_output_policy,
>> +		.maxattr = ARRAY_SIZE(dpll_genl_set_output_policy) - 1,
>> +	},
>> +};
>> +
>> +static struct genl_family dpll_gnl_family __ro_after_init = {
>> +	.hdrsize	= 0,
>> +	.name		= DPLL_FAMILY_NAME,
>> +	.version	= DPLL_VERSION,
>> +	.ops		= dpll_genl_ops,
>> +	.n_ops		= ARRAY_SIZE(dpll_genl_ops),
>> +	.mcgrps		= dpll_genl_mcgrps,
>> +	.n_mcgrps	= ARRAY_SIZE(dpll_genl_mcgrps),
>> +	.pre_doit	= dpll_pre_doit,
> 
> Have  .parallel_ops   = true,
> You have dpll->lock, you don't need genl, to protect you.
>

Yep, sure, thanks!

> 
>> +};
>> +
>> +int __init dpll_netlink_init(void)
>> +{
>> +	return genl_register_family(&dpll_gnl_family);
>> +}
>> +
>> +void dpll_netlink_finish(void)
>> +{
>> +	genl_unregister_family(&dpll_gnl_family);
>> +}
>> +
>> +void __exit dpll_netlink_fini(void)
>> +{
>> +	dpll_netlink_finish();
>> +}
>> diff --git a/drivers/dpll/dpll_netlink.h b/drivers/dpll/dpll_netlink.h
>> new file mode 100644
>> index 000000000000..e2d100f59dd6
>> --- /dev/null
>> +++ b/drivers/dpll/dpll_netlink.h
>> @@ -0,0 +1,7 @@
>> +/* SPDX-License-Identifier: GPL-2.0 */
>> +/*
>> + *  Copyright (c) 2021 Meta Platforms, Inc. and affiliates
>> + */
>> +
>> +int __init dpll_netlink_init(void);
>> +void dpll_netlink_finish(void);
>> diff --git a/include/linux/dpll.h b/include/linux/dpll.h
>> new file mode 100644
>> index 000000000000..9d49b19d03d9
>> --- /dev/null
>> +++ b/include/linux/dpll.h
>> @@ -0,0 +1,29 @@
>> +/* SPDX-License-Identifier: GPL-2.0 */
>> +/*
>> + *  Copyright (c) 2021 Meta Platforms, Inc. and affiliates
>> + */
>> +
>> +#ifndef __DPLL_H__
>> +#define __DPLL_H__
>> +
>> +struct dpll_device;
>> +
>> +struct dpll_device_ops {
>> +	int (*get_status)(struct dpll_device *dpll);
>> +	int (*get_temp)(struct dpll_device *dpll);
>> +	int (*get_lock_status)(struct dpll_device *dpll);
>> +	int (*get_source_type)(struct dpll_device *dpll, int id);
>> +	int (*get_source_supported)(struct dpll_device *dpll, int id, int type);
>> +	int (*get_output_type)(struct dpll_device *dpll, int id);
>> +	int (*get_output_supported)(struct dpll_device *dpll, int id, int type);
>> +	int (*set_source_type)(struct dpll_device *dpll, int id, int val);
>> +	int (*set_output_type)(struct dpll_device *dpll, int id, int val);
> 
> All int should be enums, when they are really enums. Makes things much
> nicer and easier to see what's what.
> 
Yep, will update it.
> 
> 
>> +};
>> +
>> +struct dpll_device *dpll_device_alloc(struct dpll_device_ops *ops, const char *name,
>> +				      int sources_count, int outputs_count, void *priv);
>> +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);
>> +#endif
>> diff --git a/include/uapi/linux/dpll.h b/include/uapi/linux/dpll.h
>> new file mode 100644
>> index 000000000000..fcbea5a5e4d6
>> --- /dev/null
>> +++ b/include/uapi/linux/dpll.h
>> @@ -0,0 +1,101 @@
>> +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
>> +#ifndef _UAPI_LINUX_DPLL_H
>> +#define _UAPI_LINUX_DPLL_H
>> +
>> +#define DPLL_NAME_LENGTH	20
>> +
>> +/* Adding event notification support elements */
>> +#define DPLL_FAMILY_NAME		"dpll"
>> +#define DPLL_VERSION			0x01
>> +#define DPLL_CONFIG_DEVICE_GROUP_NAME  "config"
>> +#define DPLL_CONFIG_SOURCE_GROUP_NAME  "source"
>> +#define DPLL_CONFIG_OUTPUT_GROUP_NAME  "output"
>> +#define DPLL_MONITOR_GROUP_NAME        "monitor"
> 
> What is exactly the reason for multiple multicast groups? Why you don't
> use one?
> 
Yes, I agree, there is no need to use multiple groups and I will remove them in 
the next version.

> 
>> +
>> +#define DPLL_FLAG_SOURCES	1
>> +#define DPLL_FLAG_OUTPUTS	2
>> +#define DPLL_FLAG_STATUS	4
> 
> I think it is more common to use either 0x prefix or (1<<X) expression
> But I don't think these flags are needed at all, if you have per-object
> messages.
> 
> 
>> +
>> +/* Attributes of dpll_genl_family */
>> +enum dpll_genl_attr {
> 
> I don't see need for "genl" here.
> Also, it is common to have consistency betwee enum name and members name.
> For example:
> 
> enum dpll_attr {
> 	DPLL_ATTR_UNSPEC,
> 	DPLL_ATTR_DEVICE_ID,
> 
> 	...
> }
> This applies to all enums in this file.
>
Got it, naming is always hard task. Will update all of them in the next version.

> 
>> +	DPLLA_UNSPEC,
>> +	DPLLA_DEVICE_ID,
>> +	DPLLA_DEVICE_NAME,
>> +	DPLLA_SOURCE,
>> +	DPLLA_SOURCE_ID,
> 
> "ID" sounds a bit odd. I think "index" would be more suitable.
> 
I just wanted to have shorter names to better fit 80 columns per line restrictions.
> 
>> +	DPLLA_SOURCE_TYPE,
>> +	DPLLA_SOURCE_SUPPORTED,
>> +	DPLLA_OUTPUT,
>> +	DPLLA_OUTPUT_ID,
>> +	DPLLA_OUTPUT_TYPE,
>> +	DPLLA_OUTPUT_SUPPORTED,
>> +	DPLLA_STATUS,
>> +	DPLLA_TEMP,
>> +	DPLLA_LOCK_STATUS,
>> +	DPLLA_FLAGS,
>> +
>> +	__DPLLA_MAX,
>> +};
>> +#define DPLLA_MAX (__DPLLA_MAX - 1)
>> +
>> +/* DPLL status provides information of device status */
>> +enum dpll_genl_status {
>> +	DPLL_STATUS_NONE,
>> +	DPLL_STATUS_CALIBRATING,
>> +	DPLL_STATUS_LOCKED,
>> +
>> +	__DPLL_STATUS_MAX,
>> +};
>> +#define DPLL_STATUS_MAX (__DPLL_STATUS_MAX - 1)
>> +
>> +/* DPLL signal types used as source or as output */
>> +enum dpll_genl_signal_type {
>> +	DPLL_TYPE_EXT_1PPS,
>> +	DPLL_TYPE_EXT_10MHZ,
>> +	DPLL_TYPE_SYNCE_ETH_PORT,
>> +	DPLL_TYPE_INT_OSCILLATOR,
>> +	DPLL_TYPE_GNSS,
>> +
>> +	__DPLL_TYPE_MAX,
>> +};
>> +#define DPLL_TYPE_MAX (__DPLL_TYPE_MAX - 1)
>> +
>> +/* DPLL lock status provides information of source used to lock the device */
>> +enum dpll_genl_lock_status {
>> +	DPLL_LOCK_STATUS_UNLOCKED,
>> +	DPLL_LOCK_STATUS_EXT_1PPS,
>> +	DPLL_LOCK_STATUS_EXT_10MHZ,
>> +	DPLL_LOCK_STATUS_SYNCE,
>> +	DPLL_LOCK_STATUS_INT_OSCILLATOR,
>> +	DPLL_LOCK_STATUS_GNSS,
> 
> I find it a bit odd and redundant to have lock status here as a separate
> enum. You have a souce selected (either autoselected or manualy
> selected). Then the status is either:
> "UNLOCKED"
> "LOCKED"
> "HOLDOVER"
> 
> Or something similar. The point is, don't have the "source type" as a
> part of lock status.
> 

Yes, it's a very good idea, I was thinking about the same, but it didn't end up 
in the code.

> 
>> +
>> +	__DPLL_LOCK_STATUS_MAX,
>> +};
>> +#define DPLL_LOCK_STATUS_MAX (__DPLL_LOCK_STATUS_MAX - 1)
>> +
>> +/* Events of dpll_genl_family */
>> +enum dpll_genl_event {
>> +	DPLL_EVENT_UNSPEC,
>> +	DPLL_EVENT_DEVICE_CREATE,		/* DPLL device creation */
>> +	DPLL_EVENT_DEVICE_DELETE,		/* DPLL device deletion */
>> +	DPLL_EVENT_STATUS_LOCKED,		/* DPLL device locked to source */
>> +	DPLL_EVENT_STATUS_UNLOCKED,	/* DPLL device freerun */
> 
> Again, redundant I belive. There should be one event,
> inside the message there should be and ATTR of the lock state.
> 
> Also, I believe there are 2 options:
> 1) follow the existing netlink models and have:
> DPLL_EVENT_DEVICE_NEW
>    - sent for new device
>    - sent for change with device
> DPLL_EVENT_DEVICE_DEL
>    - sent for removed device
> 2)
> DPLL_EVENT_DEVICE_NEW
>    - sent for new device
> DPLL_EVENT_DEVICE_DEL
>    - sent for removed device
> DPLL_EVENT_DEVICE_CHANGE
>    - sent for change with device
> 
> Bot options work fine I belive. The point is, you don't want to have
> "cmd" per one attr change. Changed the device, attrs are passed in one
> message.
>

I will try to change events this way, thanks.

> 
> 
>> +	DPLL_EVENT_SOURCE_CHANGE,		/* DPLL device source changed */
> 
> Similar here, source of device changed, should be just one attr in
> device message, see above.
> 

The WIP right now is going the way to have separate objects representing pins, 
which could be used as source/output or even mux device. And the whole part 
about sources and outputs is going to change. But I'll keep in mind that 
suggestion while implementing this new way.

> 
>> +	DPLL_EVENT_OUTPUT_CHANGE,		/* DPLL device output changed */
> 
> 
>> +
>> +	__DPLL_EVENT_MAX,
>> +};
>> +#define DPLL_EVENT_MAX (__DPLL_EVENT_MAX - 1)
>> +
>> +/* Commands supported by the dpll_genl_family */
>> +enum dpll_genl_cmd {
>> +	DPLL_CMD_UNSPEC,
>> +	DPLL_CMD_DEVICE_GET,	/* List of DPLL devices id */
>> +	DPLL_CMD_SET_SOURCE_TYPE,	/* Set the DPLL device source type */
> 
> This is confusing, you select "source", not "type".

As I said, we can have different types for one source.

> 
> Please be consistent in naming:
> DPLL_CMD_*_GET/SET

Sure

> 
> Also, to be consistend with other netlink interfaces, we don't need
> cmd per action, rather there should be OBJ_GET (can dump) and OBJ_SET
> commands, like this:
>     
>     DPLL_CMD_DEVICE_GET (can dump all present devices)
>     	ATTR_SOURCE_SELECT_MODE (current one)
>     	ATTR_SOURCE_INDEX (currect one)
>     DPLL_CMD_DEVICE_SET
>     	ATTR_SOURCE_INDEX (to set)
>     DPLL_CMD_DEVICE_SET
>     	ATTR_SOURCE_SELECT_MODE (to set)
> 

I believe we have to provide all the possible (or suitable) attributes in SET 
command too, to fully configure the source by one command only, right?

And I also think we have to provide special attribute to show which source is 
actually used to sync to, like ATTR_CONNECTED.

> 
>> +	DPLL_CMD_SET_OUTPUT_TYPE,	/* Set the DPLL device output type */
> 
> Similar to what I suggested for "source", we should
> enable to select the OUTPUT, the type should be static. Also instead,
> I belive we should have a list of outputs and basically just allow
> enable/disable individual outputs:
>     DPLL_CMD_OUTPUT_GET (can dump the list of available outputs)
> 	ATTR_ENABLED (or "CONNECTED" or whatever) of type bool
>     DPLL_CMD_OUTPUT_SET
> 	ATTR_ENABLED (or "CONNECTED" or whatever) of type bool
> 
> This is suitable for SyncE for example, when you have multiple netdev ports
> that are connected as "outputs", you can enable exactly those you you want.
> Example:
> # To list the available outputs:
> -> DPLL_CMD_OUTPUT_GET - dump
>       ATTR_DEVICE_ID X
> 
> <- DPLL_CMD_OUTPUT_GET
>       ATTR_DEVICE_ID X
>       ATTR_OUTPUT_INDEX 0
>       ATTR_OUTPUT_TYPE SYNCE_ETH_PORT
>       ATTR_OUTPUT_NETDEV_IFINDEX 20
>       ATTR_OUTPUT_ENABLED 0
>       
>       ATTR_DEVICE_ID X
>       ATTR_OUTPUT_INDEX 1
>       ATTR_OUTPUT_TYPE SYNCE_ETH_PORT
>       ATTR_OUTPUT_NETDEV_IFINDEX 30
>       ATTR_OUTPUT_ENABLED 0
> 
> # Now enable output with index 0
> -> DPLL_CMD_OUTPUT_SET
>       ATTR_DEVICE_ID X
>       ATTR_OUTPUT_INDEX 0
>       ATTR_OUTPUT_ENABLED 1
> 
Well, in case when we have flexible outputs, we can provide this information as 
special type, like DPLL_TYPE_DISABLED. Having other types configured on the 
output will assume that the OUTPUT is enabled.

> 
>> +
>> +	__DPLL_CMD_MAX,
>> +};
>> +#define DPLL_CMD_MAX (__DPLL_CMD_MAX - 1)
>> +
>> +#endif /* _UAPI_LINUX_DPLL_H */
>> -- 
>> 2.27.0
>>

Thanks for actionable feedback, I hope to prepare new version soon with all the 
comments and suggestions addressed!



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 4/6] dpll: get source/output name
  2022-10-10  9:45     ` Jiri Pirko
@ 2022-10-10 19:55       ` Vadim Fedorenko
  -1 siblings, 0 replies; 67+ messages in thread
From: Vadim Fedorenko @ 2022-10-10 19:55 UTC (permalink / raw)
  To: Jiri Pirko
  Cc: Jakub Kicinski, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

On 10.10.2022 10:45, Jiri Pirko wrote:
> Mon, Oct 10, 2022 at 03:18:02AM CEST, vfedorenko@novek.ru wrote:
>> From: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
>>
>> Dump names of sources and outputs in response to DPLL_CMD_DEVICE_GET dump
>> request.
>>
>> Signed-off-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
>> ---
>> drivers/dpll/dpll_netlink.c | 24 ++++++++++++++++++++++++
>> include/linux/dpll.h        |  2 ++
>> include/uapi/linux/dpll.h   |  2 ++
>> 3 files changed, 28 insertions(+)
>>
>> diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c
>> index a5779871537a..e3604c10b59e 100644
>> --- a/drivers/dpll/dpll_netlink.c
>> +++ b/drivers/dpll/dpll_netlink.c
>> @@ -31,12 +31,16 @@ static const struct nla_policy dpll_genl_set_source_policy[] = {
>> 	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
>> 	[DPLLA_SOURCE_ID]	= { .type = NLA_U32 },
>> 	[DPLLA_SOURCE_TYPE]	= { .type = NLA_U32 },
>> +	[DPLLA_SOURCE_NAME]	= { .type = NLA_STRING,
>> +				    .len = DPLL_NAME_LENGTH },
>> };
>>
>> static const struct nla_policy dpll_genl_set_output_policy[] = {
>> 	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
>> 	[DPLLA_OUTPUT_ID]	= { .type = NLA_U32 },
>> 	[DPLLA_OUTPUT_TYPE]	= { .type = NLA_U32 },
>> +	[DPLLA_OUTPUT_NAME]	= { .type = NLA_STRING,
>> +				    .len = DPLL_NAME_LENGTH },
>> };
>>
>> static const struct nla_policy dpll_genl_set_src_select_mode_policy[] = {
>> @@ -100,6 +104,7 @@ static int __dpll_cmd_dump_sources(struct dpll_device *dpll,
>> {
>> 	int i, ret = 0, type, prio;
>> 	struct nlattr *src_attr;
>> +	const char *name;
>>
>> 	for (i = 0; i < dpll->sources_count; i++) {
>> 		src_attr = nla_nest_start(msg, DPLLA_SOURCE);
>> @@ -132,6 +137,15 @@ static int __dpll_cmd_dump_sources(struct dpll_device *dpll,
>> 				break;
>> 			}
>> 		}
>> +		if (dpll->ops->get_source_name) {
>> +			name = dpll->ops->get_source_name(dpll, i);
>> +			if (name && nla_put_string(msg, DPLLA_SOURCE_NAME,
>> +						   name)) {
>> +				nla_nest_cancel(msg, src_attr);
>> +				ret = -EMSGSIZE;
>> +				break;
>> +			}
>> +		}
>> 		nla_nest_end(msg, src_attr);
>> 	}
>>
>> @@ -143,6 +157,7 @@ static int __dpll_cmd_dump_outputs(struct dpll_device *dpll,
>> {
>> 	struct nlattr *out_attr;
>> 	int i, ret = 0, type;
>> +	const char *name;
>>
>> 	for (i = 0; i < dpll->outputs_count; i++) {
>> 		out_attr = nla_nest_start(msg, DPLLA_OUTPUT);
>> @@ -167,6 +182,15 @@ static int __dpll_cmd_dump_outputs(struct dpll_device *dpll,
>> 			}
>> 			ret = 0;
>> 		}
>> +		if (dpll->ops->get_output_name) {
>> +			name = dpll->ops->get_output_name(dpll, i);
>> +			if (name && nla_put_string(msg, DPLLA_OUTPUT_NAME,
>> +						   name)) {
>> +				nla_nest_cancel(msg, out_attr);
>> +				ret = -EMSGSIZE;
>> +				break;
>> +			}
>> +		}
>> 		nla_nest_end(msg, out_attr);
>> 	}
>>
>> diff --git a/include/linux/dpll.h b/include/linux/dpll.h
>> index 3fe957a06b90..2f4964dc28f0 100644
>> --- a/include/linux/dpll.h
>> +++ b/include/linux/dpll.h
>> @@ -23,6 +23,8 @@ struct dpll_device_ops {
>> 	int (*set_output_type)(struct dpll_device *dpll, int id, int val);
>> 	int (*set_source_select_mode)(struct dpll_device *dpll, int mode);
>> 	int (*set_source_prio)(struct dpll_device *dpll, int id, int prio);
>> +	const char *(*get_source_name)(struct dpll_device *dpll, int id);
>> +	const char *(*get_output_name)(struct dpll_device *dpll, int id);
> 
> Hmm, why you exactly need the name for?
> 
As with device name, user-space app can use source/output name to easily select 
one using configuration value, for example.
> 
>> };
>>
>> struct dpll_device *dpll_device_alloc(struct dpll_device_ops *ops, const char *name,
>> diff --git a/include/uapi/linux/dpll.h b/include/uapi/linux/dpll.h
>> index f6b674e5cf01..8782d3425aae 100644
>> --- a/include/uapi/linux/dpll.h
>> +++ b/include/uapi/linux/dpll.h
>> @@ -26,11 +26,13 @@ enum dpll_genl_attr {
>> 	DPLLA_SOURCE,
>> 	DPLLA_SOURCE_ID,
>> 	DPLLA_SOURCE_TYPE,
>> +	DPLLA_SOURCE_NAME,
>> 	DPLLA_SOURCE_SUPPORTED,
>> 	DPLLA_SOURCE_PRIO,
>> 	DPLLA_OUTPUT,
>> 	DPLLA_OUTPUT_ID,
>> 	DPLLA_OUTPUT_TYPE,
>> +	DPLLA_OUTPUT_NAME,
>> 	DPLLA_OUTPUT_SUPPORTED,
>> 	DPLLA_STATUS,
>> 	DPLLA_TEMP,
>> -- 
>> 2.27.0
>>


^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 4/6] dpll: get source/output name
@ 2022-10-10 19:55       ` Vadim Fedorenko
  0 siblings, 0 replies; 67+ messages in thread
From: Vadim Fedorenko @ 2022-10-10 19:55 UTC (permalink / raw)
  To: Jiri Pirko
  Cc: Jakub Kicinski, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

On 10.10.2022 10:45, Jiri Pirko wrote:
> Mon, Oct 10, 2022 at 03:18:02AM CEST, vfedorenko@novek.ru wrote:
>> From: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
>>
>> Dump names of sources and outputs in response to DPLL_CMD_DEVICE_GET dump
>> request.
>>
>> Signed-off-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
>> ---
>> drivers/dpll/dpll_netlink.c | 24 ++++++++++++++++++++++++
>> include/linux/dpll.h        |  2 ++
>> include/uapi/linux/dpll.h   |  2 ++
>> 3 files changed, 28 insertions(+)
>>
>> diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c
>> index a5779871537a..e3604c10b59e 100644
>> --- a/drivers/dpll/dpll_netlink.c
>> +++ b/drivers/dpll/dpll_netlink.c
>> @@ -31,12 +31,16 @@ static const struct nla_policy dpll_genl_set_source_policy[] = {
>> 	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
>> 	[DPLLA_SOURCE_ID]	= { .type = NLA_U32 },
>> 	[DPLLA_SOURCE_TYPE]	= { .type = NLA_U32 },
>> +	[DPLLA_SOURCE_NAME]	= { .type = NLA_STRING,
>> +				    .len = DPLL_NAME_LENGTH },
>> };
>>
>> static const struct nla_policy dpll_genl_set_output_policy[] = {
>> 	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
>> 	[DPLLA_OUTPUT_ID]	= { .type = NLA_U32 },
>> 	[DPLLA_OUTPUT_TYPE]	= { .type = NLA_U32 },
>> +	[DPLLA_OUTPUT_NAME]	= { .type = NLA_STRING,
>> +				    .len = DPLL_NAME_LENGTH },
>> };
>>
>> static const struct nla_policy dpll_genl_set_src_select_mode_policy[] = {
>> @@ -100,6 +104,7 @@ static int __dpll_cmd_dump_sources(struct dpll_device *dpll,
>> {
>> 	int i, ret = 0, type, prio;
>> 	struct nlattr *src_attr;
>> +	const char *name;
>>
>> 	for (i = 0; i < dpll->sources_count; i++) {
>> 		src_attr = nla_nest_start(msg, DPLLA_SOURCE);
>> @@ -132,6 +137,15 @@ static int __dpll_cmd_dump_sources(struct dpll_device *dpll,
>> 				break;
>> 			}
>> 		}
>> +		if (dpll->ops->get_source_name) {
>> +			name = dpll->ops->get_source_name(dpll, i);
>> +			if (name && nla_put_string(msg, DPLLA_SOURCE_NAME,
>> +						   name)) {
>> +				nla_nest_cancel(msg, src_attr);
>> +				ret = -EMSGSIZE;
>> +				break;
>> +			}
>> +		}
>> 		nla_nest_end(msg, src_attr);
>> 	}
>>
>> @@ -143,6 +157,7 @@ static int __dpll_cmd_dump_outputs(struct dpll_device *dpll,
>> {
>> 	struct nlattr *out_attr;
>> 	int i, ret = 0, type;
>> +	const char *name;
>>
>> 	for (i = 0; i < dpll->outputs_count; i++) {
>> 		out_attr = nla_nest_start(msg, DPLLA_OUTPUT);
>> @@ -167,6 +182,15 @@ static int __dpll_cmd_dump_outputs(struct dpll_device *dpll,
>> 			}
>> 			ret = 0;
>> 		}
>> +		if (dpll->ops->get_output_name) {
>> +			name = dpll->ops->get_output_name(dpll, i);
>> +			if (name && nla_put_string(msg, DPLLA_OUTPUT_NAME,
>> +						   name)) {
>> +				nla_nest_cancel(msg, out_attr);
>> +				ret = -EMSGSIZE;
>> +				break;
>> +			}
>> +		}
>> 		nla_nest_end(msg, out_attr);
>> 	}
>>
>> diff --git a/include/linux/dpll.h b/include/linux/dpll.h
>> index 3fe957a06b90..2f4964dc28f0 100644
>> --- a/include/linux/dpll.h
>> +++ b/include/linux/dpll.h
>> @@ -23,6 +23,8 @@ struct dpll_device_ops {
>> 	int (*set_output_type)(struct dpll_device *dpll, int id, int val);
>> 	int (*set_source_select_mode)(struct dpll_device *dpll, int mode);
>> 	int (*set_source_prio)(struct dpll_device *dpll, int id, int prio);
>> +	const char *(*get_source_name)(struct dpll_device *dpll, int id);
>> +	const char *(*get_output_name)(struct dpll_device *dpll, int id);
> 
> Hmm, why you exactly need the name for?
> 
As with device name, user-space app can use source/output name to easily select 
one using configuration value, for example.
> 
>> };
>>
>> struct dpll_device *dpll_device_alloc(struct dpll_device_ops *ops, const char *name,
>> diff --git a/include/uapi/linux/dpll.h b/include/uapi/linux/dpll.h
>> index f6b674e5cf01..8782d3425aae 100644
>> --- a/include/uapi/linux/dpll.h
>> +++ b/include/uapi/linux/dpll.h
>> @@ -26,11 +26,13 @@ enum dpll_genl_attr {
>> 	DPLLA_SOURCE,
>> 	DPLLA_SOURCE_ID,
>> 	DPLLA_SOURCE_TYPE,
>> +	DPLLA_SOURCE_NAME,
>> 	DPLLA_SOURCE_SUPPORTED,
>> 	DPLLA_SOURCE_PRIO,
>> 	DPLLA_OUTPUT,
>> 	DPLLA_OUTPUT_ID,
>> 	DPLLA_OUTPUT_TYPE,
>> +	DPLLA_OUTPUT_NAME,
>> 	DPLLA_OUTPUT_SUPPORTED,
>> 	DPLLA_STATUS,
>> 	DPLLA_TEMP,
>> -- 
>> 2.27.0
>>


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 3/6] dpll: add support for source selection modes
  2022-10-10 14:13     ` Jiri Pirko
@ 2022-10-10 20:03       ` Vadim Fedorenko
  -1 siblings, 0 replies; 67+ messages in thread
From: Vadim Fedorenko @ 2022-10-10 20:03 UTC (permalink / raw)
  To: Jiri Pirko
  Cc: Jakub Kicinski, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

On 10.10.2022 15:13, Jiri Pirko wrote:
> Mon, Oct 10, 2022 at 03:18:01AM CEST, vfedorenko@novek.ru wrote:
>> From: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
>>
>> Allow to configure dpll device for different source selection modes.
>> Allow to configure priority of a sources for autmoatic selection mode.
>>
>> Signed-off-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
>> ---
>> drivers/dpll/dpll_netlink.c | 170 ++++++++++++++++++++++++++++++++++--
>> drivers/dpll/dpll_netlink.h |   2 +
>> include/linux/dpll.h        |   7 ++
>> include/uapi/linux/dpll.h   |  22 ++++-
>> 4 files changed, 192 insertions(+), 9 deletions(-)
>>
>> diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c
>> index 6dc92b5b712e..a5779871537a 100644
>> --- a/drivers/dpll/dpll_netlink.c
>> +++ b/drivers/dpll/dpll_netlink.c
>> @@ -23,6 +23,7 @@ static const struct nla_policy dpll_genl_get_policy[] = {
>> 	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
>> 	[DPLLA_DEVICE_NAME]	= { .type = NLA_STRING,
>> 				    .len = DPLL_NAME_LENGTH },
>> +	[DPLLA_DEVICE_SRC_SELECT_MODE] = { .type = NLA_U32 },
>> 	[DPLLA_FLAGS]		= { .type = NLA_U32 },
>> };
>>
>> @@ -38,13 +39,26 @@ static const struct nla_policy dpll_genl_set_output_policy[] = {
>> 	[DPLLA_OUTPUT_TYPE]	= { .type = NLA_U32 },
>> };
>>
>> +static const struct nla_policy dpll_genl_set_src_select_mode_policy[] = {
>> +	[DPLLA_DEVICE_ID]		  = { .type = NLA_U32 },
>> +	[DPLLA_DEVICE_SRC_SELECT_MODE] = { .type = NLA_U32 },
>> +};
>> +
>> +static const struct nla_policy dpll_genl_set_source_prio_policy[] = {
>> +	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
>> +	[DPLLA_SOURCE_ID]	= { .type = NLA_U32 },
>> +	[DPLLA_SOURCE_PRIO]	= { .type = NLA_U32 },
>> +};
>> +
>> struct param {
>> 	struct netlink_callback *cb;
>> 	struct dpll_device *dpll;
>> 	struct sk_buff *msg;
>> 	int dpll_id;
>> +	int dpll_src_select_mode;
>> 	int dpll_source_id;
>> 	int dpll_source_type;
>> +	int dpll_source_prio;
>> 	int dpll_output_id;
>> 	int dpll_output_type;
>> 	int dpll_status;
>> @@ -84,8 +98,8 @@ static int __dpll_cmd_device_dump_one(struct dpll_device *dpll,
>> static int __dpll_cmd_dump_sources(struct dpll_device *dpll,
>> 					   struct sk_buff *msg)
>> {
>> +	int i, ret = 0, type, prio;
>> 	struct nlattr *src_attr;
>> -	int i, ret = 0, type;
>>
>> 	for (i = 0; i < dpll->sources_count; i++) {
>> 		src_attr = nla_nest_start(msg, DPLLA_SOURCE);
>> @@ -110,6 +124,14 @@ static int __dpll_cmd_dump_sources(struct dpll_device *dpll,
>> 			}
>> 			ret = 0;
>> 		}
>> +		if (dpll->ops->get_source_prio) {
>> +			prio = dpll->ops->get_source_prio(dpll, i);
>> +			if (nla_put_u32(msg, DPLLA_SOURCE_PRIO, prio)) {
>> +				nla_nest_cancel(msg, src_attr);
>> +				ret = -EMSGSIZE;
>> +				break;
>> +			}
>> +		}
>> 		nla_nest_end(msg, src_attr);
>> 	}
>>
>> @@ -154,26 +176,51 @@ static int __dpll_cmd_dump_outputs(struct dpll_device *dpll,
>> static int __dpll_cmd_dump_status(struct dpll_device *dpll,
>> 					   struct sk_buff *msg)
>> {
>> -	int ret;
>> +	struct dpll_device_ops *ops = dpll->ops;
>> +	int ret, type, attr;
>>
>> -	if (dpll->ops->get_status) {
>> -		ret = dpll->ops->get_status(dpll);
>> +	if (ops->get_status) {
>> +		ret = ops->get_status(dpll);
>> 		if (nla_put_u32(msg, DPLLA_STATUS, ret))
>> 			return -EMSGSIZE;
>> 	}
>>
>> -	if (dpll->ops->get_temp) {
>> -		ret = dpll->ops->get_temp(dpll);
>> +	if (ops->get_temp) {
>> +		ret = ops->get_temp(dpll);
>> 		if (nla_put_u32(msg, DPLLA_TEMP, ret))
>> 			return -EMSGSIZE;
>> 	}
>>
>> -	if (dpll->ops->get_lock_status) {
>> -		ret = dpll->ops->get_lock_status(dpll);
>> +	if (ops->get_lock_status) {
>> +		ret = ops->get_lock_status(dpll);
>> 		if (nla_put_u32(msg, DPLLA_LOCK_STATUS, ret))
>> 			return -EMSGSIZE;
>> 	}
>>
>> +	if (ops->get_source_select_mode) {
>> +		ret = ops->get_source_select_mode(dpll);
>> +		if (nla_put_u32(msg, DPLLA_DEVICE_SRC_SELECT_MODE, ret))
>> +			return -EMSGSIZE;
>> +	} else {
>> +		if (nla_put_u32(msg, DPLLA_DEVICE_SRC_SELECT_MODE,
>> +				DPLL_SRC_SELECT_FORCED))
>> +			return -EMSGSIZE;
>> +	}
>> +
>> +	if (ops->get_source_select_mode_supported) {
>> +		attr = DPLLA_DEVICE_SRC_SELECT_MODE_SUPPORTED;
>> +		for (type = 0; type <= DPLL_SRC_SELECT_MAX; type++) {
>> +			ret = ops->get_source_select_mode_supported(dpll,
>> +								    type);
>> +			if (ret && nla_put_u32(msg, attr, type))
>> +				return -EMSGSIZE;
>> +		}
>> +	} else {
>> +		if (nla_put_u32(msg, DPLLA_DEVICE_SRC_SELECT_MODE_SUPPORTED,
>> +				DPLL_SRC_SELECT_FORCED))
>> +			return -EMSGSIZE;
>> +	}
>> +
>> 	return 0;
>> }
>>
>> @@ -275,6 +322,56 @@ static int dpll_genl_cmd_set_output(struct sk_buff *skb, struct genl_info *info)
>> 	return ret;
>> }
>>
>> +static int dpll_genl_cmd_set_source_prio(struct sk_buff *skb, struct genl_info *info)
>> +{
>> +	struct dpll_device *dpll = info->user_ptr[0];
>> +	struct nlattr **attrs = info->attrs;
>> +	int ret = 0, src_id, prio;
>> +
>> +	if (!attrs[DPLLA_SOURCE_ID] ||
>> +	    !attrs[DPLLA_SOURCE_PRIO])
>> +		return -EINVAL;
>> +
>> +	if (!dpll->ops->set_source_prio)
>> +		return -EOPNOTSUPP;
>> +
>> +	src_id = nla_get_u32(attrs[DPLLA_SOURCE_ID]);
>> +	prio = nla_get_u32(attrs[DPLLA_SOURCE_PRIO]);
>> +
>> +	mutex_lock(&dpll->lock);
>> +	ret = dpll->ops->set_source_prio(dpll, src_id, prio);
>> +	mutex_unlock(&dpll->lock);
>> +
>> +	if (!ret)
>> +		dpll_notify_source_prio_change(dpll->id, src_id, prio);
>> +
>> +	return ret;
>> +}
>> +
>> +static int dpll_genl_cmd_set_select_mode(struct sk_buff *skb, struct genl_info *info)
>> +{
>> +	struct dpll_device *dpll = info->user_ptr[0];
>> +	struct nlattr **attrs = info->attrs;
>> +	int ret = 0, mode;
>> +
>> +	if (!attrs[DPLLA_DEVICE_SRC_SELECT_MODE])
>> +		return -EINVAL;
>> +
>> +	if (!dpll->ops->set_source_select_mode)
>> +		return -EOPNOTSUPP;
>> +
>> +	mode = nla_get_u32(attrs[DPLLA_DEVICE_SRC_SELECT_MODE]);
>> +
>> +	mutex_lock(&dpll->lock);
>> +	ret = dpll->ops->set_source_select_mode(dpll, mode);
>> +	mutex_unlock(&dpll->lock);
>> +
>> +	if (!ret)
>> +		dpll_notify_source_select_mode_change(dpll->id, mode);
>> +
>> +	return ret;
>> +}
>> +
>> static int dpll_device_loop_cb(struct dpll_device *dpll, void *data)
>> {
>> 	struct dpll_dump_ctx *ctx;
>> @@ -397,6 +494,20 @@ static const struct genl_ops dpll_genl_ops[] = {
>> 		.policy	= dpll_genl_set_output_policy,
>> 		.maxattr = ARRAY_SIZE(dpll_genl_set_output_policy) - 1,
>> 	},
>> +	{
>> +		.cmd	= DPLL_CMD_SET_SRC_SELECT_MODE,
>> +		.flags	= GENL_UNS_ADMIN_PERM,
>> +		.doit	= dpll_genl_cmd_set_select_mode,
>> +		.policy	= dpll_genl_set_src_select_mode_policy,
>> +		.maxattr = ARRAY_SIZE(dpll_genl_set_src_select_mode_policy) - 1,
>> +	},
>> +	{
>> +		.cmd	= DPLL_CMD_SET_SOURCE_PRIO,
> 
> I don't like the 1 netlink cmd per attr. The commands should be rather
> get/set object.
> 
> 
>> +		.flags	= GENL_UNS_ADMIN_PERM,
>> +		.doit	= dpll_genl_cmd_set_source_prio,
>> +		.policy	= dpll_genl_set_source_prio_policy,
>> +		.maxattr = ARRAY_SIZE(dpll_genl_set_source_prio_policy) - 1,
>> +	},
>> };
>>
>> static struct genl_family dpll_gnl_family __ro_after_init = {
>> @@ -456,6 +567,26 @@ static int dpll_event_output_change(struct param *p)
>> 	return 0;
>> }
>>
>> +static int dpll_event_source_prio(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_PRIO, p->dpll_source_prio))
>> +		return -EMSGSIZE;
>> +
>> +	return 0;
>> +}
>> +
>> +static int dpll_event_select_mode(struct param *p)
>> +{
>> +	if (nla_put_u32(p->msg, DPLLA_DEVICE_ID, p->dpll_id) ||
>> +	    nla_put_u32(p->msg, DPLLA_DEVICE_SRC_SELECT_MODE,
>> +		    p->dpll_src_select_mode))
>> +		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,
>> @@ -463,7 +594,10 @@ static const cb_t event_cb[] = {
>> 	[DPLL_EVENT_STATUS_UNLOCKED]	= dpll_event_status,
>> 	[DPLL_EVENT_SOURCE_CHANGE]	= dpll_event_source_change,
>> 	[DPLL_EVENT_OUTPUT_CHANGE]	= dpll_event_output_change,
>> +	[DPLL_EVENT_SOURCE_PRIO]        = dpll_event_source_prio,
>> +	[DPLL_EVENT_SELECT_MODE]        = dpll_event_select_mode,
>> };
>> +
>> /*
>>   * Generic netlink DPLL event encoding
>>   */
>> @@ -552,6 +686,26 @@ int dpll_notify_output_change(int dpll_id, int output_id, int output_type)
>> }
>> EXPORT_SYMBOL_GPL(dpll_notify_output_change);
>>
>> +int dpll_notify_source_select_mode_change(int dpll_id, int new_mode)
>> +{
>> +	struct param p =  { .dpll_id = dpll_id,
>> +			    .dpll_src_select_mode = new_mode,
>> +			    .dpll_event_group = 0 };
>> +
>> +	return dpll_send_event(DPLL_EVENT_SELECT_MODE, &p);
>> +}
>> +EXPORT_SYMBOL_GPL(dpll_notify_source_select_mode_change);
>> +
>> +int dpll_notify_source_prio_change(int dpll_id, int source_id, int prio)
>> +{
>> +	struct param p =  { .dpll_id = dpll_id, .dpll_source_id = source_id,
>> +			    .dpll_source_prio = prio,
>> +			    .dpll_event_group = 1 };
>> +
>> +	return dpll_send_event(DPLL_EVENT_SOURCE_PRIO, &p);
>> +}
>> +EXPORT_SYMBOL_GPL(dpll_notify_source_prio_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 5c1d1072e818..a4962fa0c8c2 100644
>> --- a/drivers/dpll/dpll_netlink.h
>> +++ b/drivers/dpll/dpll_netlink.h
>> @@ -5,6 +5,8 @@
>>
>> int dpll_notify_device_create(int dpll_id, const char *name);
>> int dpll_notify_device_delete(int dpll_id);
>> +int dpll_notify_source_prio(int dpll_id, int source_id, int prio);
>> +int dpll_notify_select_mode(int dpll_id, int mode);
>>
>> int __init dpll_netlink_init(void);
>> void dpll_netlink_finish(void);
>> diff --git a/include/linux/dpll.h b/include/linux/dpll.h
>> index 32558965cd41..3fe957a06b90 100644
>> --- a/include/linux/dpll.h
>> +++ b/include/linux/dpll.h
>> @@ -12,12 +12,17 @@ struct dpll_device_ops {
>> 	int (*get_status)(struct dpll_device *dpll);
>> 	int (*get_temp)(struct dpll_device *dpll);
>> 	int (*get_lock_status)(struct dpll_device *dpll);
>> +	int (*get_source_select_mode)(struct dpll_device *dpll);
>> +	int (*get_source_select_mode_supported)(struct dpll_device *dpll, int type);
>> 	int (*get_source_type)(struct dpll_device *dpll, int id);
>> 	int (*get_source_supported)(struct dpll_device *dpll, int id, int type);
>> +	int (*get_source_prio)(struct dpll_device *dpll, int id);
> 
> I don't thing this is a good model to have 1 ops per object attribute.
> Did you consider having driver to "register" a source/output with type and
> other attributes?
> 
I got your point, and I agree. Will upgrade the interface for the next version.

> 
> 
>> 	int (*get_output_type)(struct dpll_device *dpll, int id);
>> 	int (*get_output_supported)(struct dpll_device *dpll, int id, int type);
>> 	int (*set_source_type)(struct dpll_device *dpll, int id, int val);
>> 	int (*set_output_type)(struct dpll_device *dpll, int id, int val);
>> +	int (*set_source_select_mode)(struct dpll_device *dpll, int mode);
>> +	int (*set_source_prio)(struct dpll_device *dpll, int id, int prio);
>> };
>>
>> struct dpll_device *dpll_device_alloc(struct dpll_device_ops *ops, const char *name,
>> @@ -31,4 +36,6 @@ 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);
>> +int dpll_notify_source_select_mode_change(int dpll_id, int source_select_mode);
>> +int dpll_notify_source_prio_change(int dpll_id, int source_id, int prio);
>> #endif
>> diff --git a/include/uapi/linux/dpll.h b/include/uapi/linux/dpll.h
>> index fcbea5a5e4d6..f6b674e5cf01 100644
>> --- a/include/uapi/linux/dpll.h
>> +++ b/include/uapi/linux/dpll.h
>> @@ -21,10 +21,13 @@ enum dpll_genl_attr {
>> 	DPLLA_UNSPEC,
>> 	DPLLA_DEVICE_ID,
>> 	DPLLA_DEVICE_NAME,
>> +	DPLLA_DEVICE_SRC_SELECT_MODE,
>> +	DPLLA_DEVICE_SRC_SELECT_MODE_SUPPORTED,
>> 	DPLLA_SOURCE,
>> 	DPLLA_SOURCE_ID,
>> 	DPLLA_SOURCE_TYPE,
>> 	DPLLA_SOURCE_SUPPORTED,
>> +	DPLLA_SOURCE_PRIO,
>> 	DPLLA_OUTPUT,
>> 	DPLLA_OUTPUT_ID,
>> 	DPLLA_OUTPUT_TYPE,
>> @@ -82,6 +85,8 @@ enum dpll_genl_event {
>> 	DPLL_EVENT_STATUS_UNLOCKED,	/* DPLL device freerun */
>> 	DPLL_EVENT_SOURCE_CHANGE,		/* DPLL device source changed */
>> 	DPLL_EVENT_OUTPUT_CHANGE,		/* DPLL device output changed */
>> +	DPLL_EVENT_SOURCE_PRIO,
>> +	DPLL_EVENT_SELECT_MODE,
>>
>> 	__DPLL_EVENT_MAX,
>> };
>> @@ -90,12 +95,27 @@ enum dpll_genl_event {
>> /* Commands supported by the dpll_genl_family */
>> enum dpll_genl_cmd {
>> 	DPLL_CMD_UNSPEC,
>> -	DPLL_CMD_DEVICE_GET,	/* List of DPLL devices id */
>> +	DPLL_CMD_DEVICE_GET,		/* List of DPLL devices id */
>> 	DPLL_CMD_SET_SOURCE_TYPE,	/* Set the DPLL device source type */
>> 	DPLL_CMD_SET_OUTPUT_TYPE,	/* Set the DPLL device output type */
>> +	DPLL_CMD_SET_SRC_SELECT_MODE,/* Set mode for selection of a source */
>> +	DPLL_CMD_SET_SOURCE_PRIO,	/* Set priority of a source */
>>
>> 	__DPLL_CMD_MAX,
>> };
>> #define DPLL_CMD_MAX (__DPLL_CMD_MAX - 1)
>>
>> +/* Source select modes of dpll */
>> +enum dpll_genl_source_select_mode {
>> +	DPLL_SRC_SELECT_UNSPEC,
> 
> consistency please: "source"/"SOURCE".

Sure, thanks for pointing.
> 
> 
>> +	DPLL_SRC_SELECT_FORCED,   /* Source forced by DPLL_CMD_SET_SOURCE_TYPE */
>> +	DPLL_SRC_SELECT_AUTOMATIC,/* highest prio, valid source, auto selected by dpll */
>> +	DPLL_SRC_SELECT_HOLDOVER, /* forced holdover */
> 
> I think this is mixing up things a bit. I was under impression this is
> to set the mode or souce select. So either user select specific source
> by index (not type as you suggest above), or you leave the selection up
> to the device (according to prio).
> 
> Now holdover is not source select.
> Isn't think more like admin state/oper state?
> oper state would be the lock status
> admin state would be "force-holdover"

Yeah, I agree. With your comments for the first patch in the series, lock status 
could be changed to provide this kind of information.

> 
>> +	DPLL_SRC_SELECT_FREERUN,  /* dpll driven on system clk, no holdover available */
>> +	DPLL_SRC_SELECT_NCO,	     /* Set the DPLL device output type */
> 
> I don't understand what this "NCO" is, the comment didn't help.
> 
NCO states for numerically controlled frequency offset. The way timecounter is 
used in kernel for different PHCs.

> 
>> +
>> +	__DPLL_SRC_SELECT_MAX,
>> +};
>> +#define DPLL_SRC_SELECT_MAX (__DPLL_SRC_SELECT_MAX - 1)
>> +
>> #endif /* _UAPI_LINUX_DPLL_H */
>> -- 
>> 2.27.0
>>


^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 3/6] dpll: add support for source selection modes
@ 2022-10-10 20:03       ` Vadim Fedorenko
  0 siblings, 0 replies; 67+ messages in thread
From: Vadim Fedorenko @ 2022-10-10 20:03 UTC (permalink / raw)
  To: Jiri Pirko
  Cc: Jakub Kicinski, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

On 10.10.2022 15:13, Jiri Pirko wrote:
> Mon, Oct 10, 2022 at 03:18:01AM CEST, vfedorenko@novek.ru wrote:
>> From: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
>>
>> Allow to configure dpll device for different source selection modes.
>> Allow to configure priority of a sources for autmoatic selection mode.
>>
>> Signed-off-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
>> ---
>> drivers/dpll/dpll_netlink.c | 170 ++++++++++++++++++++++++++++++++++--
>> drivers/dpll/dpll_netlink.h |   2 +
>> include/linux/dpll.h        |   7 ++
>> include/uapi/linux/dpll.h   |  22 ++++-
>> 4 files changed, 192 insertions(+), 9 deletions(-)
>>
>> diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c
>> index 6dc92b5b712e..a5779871537a 100644
>> --- a/drivers/dpll/dpll_netlink.c
>> +++ b/drivers/dpll/dpll_netlink.c
>> @@ -23,6 +23,7 @@ static const struct nla_policy dpll_genl_get_policy[] = {
>> 	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
>> 	[DPLLA_DEVICE_NAME]	= { .type = NLA_STRING,
>> 				    .len = DPLL_NAME_LENGTH },
>> +	[DPLLA_DEVICE_SRC_SELECT_MODE] = { .type = NLA_U32 },
>> 	[DPLLA_FLAGS]		= { .type = NLA_U32 },
>> };
>>
>> @@ -38,13 +39,26 @@ static const struct nla_policy dpll_genl_set_output_policy[] = {
>> 	[DPLLA_OUTPUT_TYPE]	= { .type = NLA_U32 },
>> };
>>
>> +static const struct nla_policy dpll_genl_set_src_select_mode_policy[] = {
>> +	[DPLLA_DEVICE_ID]		  = { .type = NLA_U32 },
>> +	[DPLLA_DEVICE_SRC_SELECT_MODE] = { .type = NLA_U32 },
>> +};
>> +
>> +static const struct nla_policy dpll_genl_set_source_prio_policy[] = {
>> +	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
>> +	[DPLLA_SOURCE_ID]	= { .type = NLA_U32 },
>> +	[DPLLA_SOURCE_PRIO]	= { .type = NLA_U32 },
>> +};
>> +
>> struct param {
>> 	struct netlink_callback *cb;
>> 	struct dpll_device *dpll;
>> 	struct sk_buff *msg;
>> 	int dpll_id;
>> +	int dpll_src_select_mode;
>> 	int dpll_source_id;
>> 	int dpll_source_type;
>> +	int dpll_source_prio;
>> 	int dpll_output_id;
>> 	int dpll_output_type;
>> 	int dpll_status;
>> @@ -84,8 +98,8 @@ static int __dpll_cmd_device_dump_one(struct dpll_device *dpll,
>> static int __dpll_cmd_dump_sources(struct dpll_device *dpll,
>> 					   struct sk_buff *msg)
>> {
>> +	int i, ret = 0, type, prio;
>> 	struct nlattr *src_attr;
>> -	int i, ret = 0, type;
>>
>> 	for (i = 0; i < dpll->sources_count; i++) {
>> 		src_attr = nla_nest_start(msg, DPLLA_SOURCE);
>> @@ -110,6 +124,14 @@ static int __dpll_cmd_dump_sources(struct dpll_device *dpll,
>> 			}
>> 			ret = 0;
>> 		}
>> +		if (dpll->ops->get_source_prio) {
>> +			prio = dpll->ops->get_source_prio(dpll, i);
>> +			if (nla_put_u32(msg, DPLLA_SOURCE_PRIO, prio)) {
>> +				nla_nest_cancel(msg, src_attr);
>> +				ret = -EMSGSIZE;
>> +				break;
>> +			}
>> +		}
>> 		nla_nest_end(msg, src_attr);
>> 	}
>>
>> @@ -154,26 +176,51 @@ static int __dpll_cmd_dump_outputs(struct dpll_device *dpll,
>> static int __dpll_cmd_dump_status(struct dpll_device *dpll,
>> 					   struct sk_buff *msg)
>> {
>> -	int ret;
>> +	struct dpll_device_ops *ops = dpll->ops;
>> +	int ret, type, attr;
>>
>> -	if (dpll->ops->get_status) {
>> -		ret = dpll->ops->get_status(dpll);
>> +	if (ops->get_status) {
>> +		ret = ops->get_status(dpll);
>> 		if (nla_put_u32(msg, DPLLA_STATUS, ret))
>> 			return -EMSGSIZE;
>> 	}
>>
>> -	if (dpll->ops->get_temp) {
>> -		ret = dpll->ops->get_temp(dpll);
>> +	if (ops->get_temp) {
>> +		ret = ops->get_temp(dpll);
>> 		if (nla_put_u32(msg, DPLLA_TEMP, ret))
>> 			return -EMSGSIZE;
>> 	}
>>
>> -	if (dpll->ops->get_lock_status) {
>> -		ret = dpll->ops->get_lock_status(dpll);
>> +	if (ops->get_lock_status) {
>> +		ret = ops->get_lock_status(dpll);
>> 		if (nla_put_u32(msg, DPLLA_LOCK_STATUS, ret))
>> 			return -EMSGSIZE;
>> 	}
>>
>> +	if (ops->get_source_select_mode) {
>> +		ret = ops->get_source_select_mode(dpll);
>> +		if (nla_put_u32(msg, DPLLA_DEVICE_SRC_SELECT_MODE, ret))
>> +			return -EMSGSIZE;
>> +	} else {
>> +		if (nla_put_u32(msg, DPLLA_DEVICE_SRC_SELECT_MODE,
>> +				DPLL_SRC_SELECT_FORCED))
>> +			return -EMSGSIZE;
>> +	}
>> +
>> +	if (ops->get_source_select_mode_supported) {
>> +		attr = DPLLA_DEVICE_SRC_SELECT_MODE_SUPPORTED;
>> +		for (type = 0; type <= DPLL_SRC_SELECT_MAX; type++) {
>> +			ret = ops->get_source_select_mode_supported(dpll,
>> +								    type);
>> +			if (ret && nla_put_u32(msg, attr, type))
>> +				return -EMSGSIZE;
>> +		}
>> +	} else {
>> +		if (nla_put_u32(msg, DPLLA_DEVICE_SRC_SELECT_MODE_SUPPORTED,
>> +				DPLL_SRC_SELECT_FORCED))
>> +			return -EMSGSIZE;
>> +	}
>> +
>> 	return 0;
>> }
>>
>> @@ -275,6 +322,56 @@ static int dpll_genl_cmd_set_output(struct sk_buff *skb, struct genl_info *info)
>> 	return ret;
>> }
>>
>> +static int dpll_genl_cmd_set_source_prio(struct sk_buff *skb, struct genl_info *info)
>> +{
>> +	struct dpll_device *dpll = info->user_ptr[0];
>> +	struct nlattr **attrs = info->attrs;
>> +	int ret = 0, src_id, prio;
>> +
>> +	if (!attrs[DPLLA_SOURCE_ID] ||
>> +	    !attrs[DPLLA_SOURCE_PRIO])
>> +		return -EINVAL;
>> +
>> +	if (!dpll->ops->set_source_prio)
>> +		return -EOPNOTSUPP;
>> +
>> +	src_id = nla_get_u32(attrs[DPLLA_SOURCE_ID]);
>> +	prio = nla_get_u32(attrs[DPLLA_SOURCE_PRIO]);
>> +
>> +	mutex_lock(&dpll->lock);
>> +	ret = dpll->ops->set_source_prio(dpll, src_id, prio);
>> +	mutex_unlock(&dpll->lock);
>> +
>> +	if (!ret)
>> +		dpll_notify_source_prio_change(dpll->id, src_id, prio);
>> +
>> +	return ret;
>> +}
>> +
>> +static int dpll_genl_cmd_set_select_mode(struct sk_buff *skb, struct genl_info *info)
>> +{
>> +	struct dpll_device *dpll = info->user_ptr[0];
>> +	struct nlattr **attrs = info->attrs;
>> +	int ret = 0, mode;
>> +
>> +	if (!attrs[DPLLA_DEVICE_SRC_SELECT_MODE])
>> +		return -EINVAL;
>> +
>> +	if (!dpll->ops->set_source_select_mode)
>> +		return -EOPNOTSUPP;
>> +
>> +	mode = nla_get_u32(attrs[DPLLA_DEVICE_SRC_SELECT_MODE]);
>> +
>> +	mutex_lock(&dpll->lock);
>> +	ret = dpll->ops->set_source_select_mode(dpll, mode);
>> +	mutex_unlock(&dpll->lock);
>> +
>> +	if (!ret)
>> +		dpll_notify_source_select_mode_change(dpll->id, mode);
>> +
>> +	return ret;
>> +}
>> +
>> static int dpll_device_loop_cb(struct dpll_device *dpll, void *data)
>> {
>> 	struct dpll_dump_ctx *ctx;
>> @@ -397,6 +494,20 @@ static const struct genl_ops dpll_genl_ops[] = {
>> 		.policy	= dpll_genl_set_output_policy,
>> 		.maxattr = ARRAY_SIZE(dpll_genl_set_output_policy) - 1,
>> 	},
>> +	{
>> +		.cmd	= DPLL_CMD_SET_SRC_SELECT_MODE,
>> +		.flags	= GENL_UNS_ADMIN_PERM,
>> +		.doit	= dpll_genl_cmd_set_select_mode,
>> +		.policy	= dpll_genl_set_src_select_mode_policy,
>> +		.maxattr = ARRAY_SIZE(dpll_genl_set_src_select_mode_policy) - 1,
>> +	},
>> +	{
>> +		.cmd	= DPLL_CMD_SET_SOURCE_PRIO,
> 
> I don't like the 1 netlink cmd per attr. The commands should be rather
> get/set object.
> 
> 
>> +		.flags	= GENL_UNS_ADMIN_PERM,
>> +		.doit	= dpll_genl_cmd_set_source_prio,
>> +		.policy	= dpll_genl_set_source_prio_policy,
>> +		.maxattr = ARRAY_SIZE(dpll_genl_set_source_prio_policy) - 1,
>> +	},
>> };
>>
>> static struct genl_family dpll_gnl_family __ro_after_init = {
>> @@ -456,6 +567,26 @@ static int dpll_event_output_change(struct param *p)
>> 	return 0;
>> }
>>
>> +static int dpll_event_source_prio(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_PRIO, p->dpll_source_prio))
>> +		return -EMSGSIZE;
>> +
>> +	return 0;
>> +}
>> +
>> +static int dpll_event_select_mode(struct param *p)
>> +{
>> +	if (nla_put_u32(p->msg, DPLLA_DEVICE_ID, p->dpll_id) ||
>> +	    nla_put_u32(p->msg, DPLLA_DEVICE_SRC_SELECT_MODE,
>> +		    p->dpll_src_select_mode))
>> +		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,
>> @@ -463,7 +594,10 @@ static const cb_t event_cb[] = {
>> 	[DPLL_EVENT_STATUS_UNLOCKED]	= dpll_event_status,
>> 	[DPLL_EVENT_SOURCE_CHANGE]	= dpll_event_source_change,
>> 	[DPLL_EVENT_OUTPUT_CHANGE]	= dpll_event_output_change,
>> +	[DPLL_EVENT_SOURCE_PRIO]        = dpll_event_source_prio,
>> +	[DPLL_EVENT_SELECT_MODE]        = dpll_event_select_mode,
>> };
>> +
>> /*
>>   * Generic netlink DPLL event encoding
>>   */
>> @@ -552,6 +686,26 @@ int dpll_notify_output_change(int dpll_id, int output_id, int output_type)
>> }
>> EXPORT_SYMBOL_GPL(dpll_notify_output_change);
>>
>> +int dpll_notify_source_select_mode_change(int dpll_id, int new_mode)
>> +{
>> +	struct param p =  { .dpll_id = dpll_id,
>> +			    .dpll_src_select_mode = new_mode,
>> +			    .dpll_event_group = 0 };
>> +
>> +	return dpll_send_event(DPLL_EVENT_SELECT_MODE, &p);
>> +}
>> +EXPORT_SYMBOL_GPL(dpll_notify_source_select_mode_change);
>> +
>> +int dpll_notify_source_prio_change(int dpll_id, int source_id, int prio)
>> +{
>> +	struct param p =  { .dpll_id = dpll_id, .dpll_source_id = source_id,
>> +			    .dpll_source_prio = prio,
>> +			    .dpll_event_group = 1 };
>> +
>> +	return dpll_send_event(DPLL_EVENT_SOURCE_PRIO, &p);
>> +}
>> +EXPORT_SYMBOL_GPL(dpll_notify_source_prio_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 5c1d1072e818..a4962fa0c8c2 100644
>> --- a/drivers/dpll/dpll_netlink.h
>> +++ b/drivers/dpll/dpll_netlink.h
>> @@ -5,6 +5,8 @@
>>
>> int dpll_notify_device_create(int dpll_id, const char *name);
>> int dpll_notify_device_delete(int dpll_id);
>> +int dpll_notify_source_prio(int dpll_id, int source_id, int prio);
>> +int dpll_notify_select_mode(int dpll_id, int mode);
>>
>> int __init dpll_netlink_init(void);
>> void dpll_netlink_finish(void);
>> diff --git a/include/linux/dpll.h b/include/linux/dpll.h
>> index 32558965cd41..3fe957a06b90 100644
>> --- a/include/linux/dpll.h
>> +++ b/include/linux/dpll.h
>> @@ -12,12 +12,17 @@ struct dpll_device_ops {
>> 	int (*get_status)(struct dpll_device *dpll);
>> 	int (*get_temp)(struct dpll_device *dpll);
>> 	int (*get_lock_status)(struct dpll_device *dpll);
>> +	int (*get_source_select_mode)(struct dpll_device *dpll);
>> +	int (*get_source_select_mode_supported)(struct dpll_device *dpll, int type);
>> 	int (*get_source_type)(struct dpll_device *dpll, int id);
>> 	int (*get_source_supported)(struct dpll_device *dpll, int id, int type);
>> +	int (*get_source_prio)(struct dpll_device *dpll, int id);
> 
> I don't thing this is a good model to have 1 ops per object attribute.
> Did you consider having driver to "register" a source/output with type and
> other attributes?
> 
I got your point, and I agree. Will upgrade the interface for the next version.

> 
> 
>> 	int (*get_output_type)(struct dpll_device *dpll, int id);
>> 	int (*get_output_supported)(struct dpll_device *dpll, int id, int type);
>> 	int (*set_source_type)(struct dpll_device *dpll, int id, int val);
>> 	int (*set_output_type)(struct dpll_device *dpll, int id, int val);
>> +	int (*set_source_select_mode)(struct dpll_device *dpll, int mode);
>> +	int (*set_source_prio)(struct dpll_device *dpll, int id, int prio);
>> };
>>
>> struct dpll_device *dpll_device_alloc(struct dpll_device_ops *ops, const char *name,
>> @@ -31,4 +36,6 @@ 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);
>> +int dpll_notify_source_select_mode_change(int dpll_id, int source_select_mode);
>> +int dpll_notify_source_prio_change(int dpll_id, int source_id, int prio);
>> #endif
>> diff --git a/include/uapi/linux/dpll.h b/include/uapi/linux/dpll.h
>> index fcbea5a5e4d6..f6b674e5cf01 100644
>> --- a/include/uapi/linux/dpll.h
>> +++ b/include/uapi/linux/dpll.h
>> @@ -21,10 +21,13 @@ enum dpll_genl_attr {
>> 	DPLLA_UNSPEC,
>> 	DPLLA_DEVICE_ID,
>> 	DPLLA_DEVICE_NAME,
>> +	DPLLA_DEVICE_SRC_SELECT_MODE,
>> +	DPLLA_DEVICE_SRC_SELECT_MODE_SUPPORTED,
>> 	DPLLA_SOURCE,
>> 	DPLLA_SOURCE_ID,
>> 	DPLLA_SOURCE_TYPE,
>> 	DPLLA_SOURCE_SUPPORTED,
>> +	DPLLA_SOURCE_PRIO,
>> 	DPLLA_OUTPUT,
>> 	DPLLA_OUTPUT_ID,
>> 	DPLLA_OUTPUT_TYPE,
>> @@ -82,6 +85,8 @@ enum dpll_genl_event {
>> 	DPLL_EVENT_STATUS_UNLOCKED,	/* DPLL device freerun */
>> 	DPLL_EVENT_SOURCE_CHANGE,		/* DPLL device source changed */
>> 	DPLL_EVENT_OUTPUT_CHANGE,		/* DPLL device output changed */
>> +	DPLL_EVENT_SOURCE_PRIO,
>> +	DPLL_EVENT_SELECT_MODE,
>>
>> 	__DPLL_EVENT_MAX,
>> };
>> @@ -90,12 +95,27 @@ enum dpll_genl_event {
>> /* Commands supported by the dpll_genl_family */
>> enum dpll_genl_cmd {
>> 	DPLL_CMD_UNSPEC,
>> -	DPLL_CMD_DEVICE_GET,	/* List of DPLL devices id */
>> +	DPLL_CMD_DEVICE_GET,		/* List of DPLL devices id */
>> 	DPLL_CMD_SET_SOURCE_TYPE,	/* Set the DPLL device source type */
>> 	DPLL_CMD_SET_OUTPUT_TYPE,	/* Set the DPLL device output type */
>> +	DPLL_CMD_SET_SRC_SELECT_MODE,/* Set mode for selection of a source */
>> +	DPLL_CMD_SET_SOURCE_PRIO,	/* Set priority of a source */
>>
>> 	__DPLL_CMD_MAX,
>> };
>> #define DPLL_CMD_MAX (__DPLL_CMD_MAX - 1)
>>
>> +/* Source select modes of dpll */
>> +enum dpll_genl_source_select_mode {
>> +	DPLL_SRC_SELECT_UNSPEC,
> 
> consistency please: "source"/"SOURCE".

Sure, thanks for pointing.
> 
> 
>> +	DPLL_SRC_SELECT_FORCED,   /* Source forced by DPLL_CMD_SET_SOURCE_TYPE */
>> +	DPLL_SRC_SELECT_AUTOMATIC,/* highest prio, valid source, auto selected by dpll */
>> +	DPLL_SRC_SELECT_HOLDOVER, /* forced holdover */
> 
> I think this is mixing up things a bit. I was under impression this is
> to set the mode or souce select. So either user select specific source
> by index (not type as you suggest above), or you leave the selection up
> to the device (according to prio).
> 
> Now holdover is not source select.
> Isn't think more like admin state/oper state?
> oper state would be the lock status
> admin state would be "force-holdover"

Yeah, I agree. With your comments for the first patch in the series, lock status 
could be changed to provide this kind of information.

> 
>> +	DPLL_SRC_SELECT_FREERUN,  /* dpll driven on system clk, no holdover available */
>> +	DPLL_SRC_SELECT_NCO,	     /* Set the DPLL device output type */
> 
> I don't understand what this "NCO" is, the comment didn't help.
> 
NCO states for numerically controlled frequency offset. The way timecounter is 
used in kernel for different PHCs.

> 
>> +
>> +	__DPLL_SRC_SELECT_MAX,
>> +};
>> +#define DPLL_SRC_SELECT_MAX (__DPLL_SRC_SELECT_MAX - 1)
>> +
>> #endif /* _UAPI_LINUX_DPLL_H */
>> -- 
>> 2.27.0
>>


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 6/6] ptp_ocp: implement DPLL ops
  2022-10-10 15:42     ` Jiri Pirko
@ 2022-10-10 20:14       ` Vadim Fedorenko
  -1 siblings, 0 replies; 67+ messages in thread
From: Vadim Fedorenko @ 2022-10-10 20:14 UTC (permalink / raw)
  To: Jiri Pirko
  Cc: Jakub Kicinski, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

On 10.10.2022 16:42, Jiri Pirko wrote:
> Mon, Oct 10, 2022 at 03:18:04AM CEST, vfedorenko@novek.ru wrote:
>> From: Vadim Fedorenko <vadfed@fb.com>
>>
>> Implement DPLL operations in ptp_ocp driver.
>>
>> Signed-off-by: Vadim Fedorenko <vadfed@fb.com>
>> ---
>> drivers/ptp/Kconfig       |   1 +
>> drivers/ptp/ptp_ocp.c     | 170 ++++++++++++++++++++++++++++++--------
>> include/uapi/linux/dpll.h |   2 +
>> 3 files changed, 137 insertions(+), 36 deletions(-)
>>
>> diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig
>> index fe4971b65c64..8c4cfabc1bfa 100644
>> --- a/drivers/ptp/Kconfig
>> +++ b/drivers/ptp/Kconfig
>> @@ -177,6 +177,7 @@ config PTP_1588_CLOCK_OCP
>> 	depends on COMMON_CLK
>> 	select NET_DEVLINK
>> 	select CRC16
>> +	select DPLL
>> 	help
>> 	  This driver adds support for an OpenCompute time card.
>>
>> diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c
>> index d36c3f597f77..a01c0c721802 100644
>> --- a/drivers/ptp/ptp_ocp.c
>> +++ b/drivers/ptp/ptp_ocp.c
>> @@ -21,6 +21,8 @@
>> #include <linux/mtd/mtd.h>
>> #include <linux/nvmem-consumer.h>
>> #include <linux/crc16.h>
>> +#include <linux/dpll.h>
>> +#include <uapi/linux/dpll.h>
> 
> This should not be needed to include directly. linux/dpll.h should
> include uapi/linux/dpll.h
> 

Got it, will change

> 
>>
>> #define PCI_VENDOR_ID_FACEBOOK			0x1d9b
>> #define PCI_DEVICE_ID_FACEBOOK_TIMECARD		0x0400
>> @@ -336,6 +338,7 @@ struct ptp_ocp {
>> 	struct ptp_ocp_signal	signal[4];
>> 	struct ptp_ocp_sma_connector sma[4];
>> 	const struct ocp_sma_op *sma_op;
>> +	struct dpll_device *dpll;
>> };
>>
>> #define OCP_REQ_TIMESTAMP	BIT(0)
>> @@ -660,18 +663,19 @@ static DEFINE_IDR(ptp_ocp_idr);
>> struct ocp_selector {
>> 	const char *name;
>> 	int value;
>> +	int dpll_type;
> 
> Enum?

Yes, I got it, will convert enums to actual enums in the series.

> 
> 
>> };
>>
>> static const struct ocp_selector ptp_ocp_clock[] = {
>> -	{ .name = "NONE",	.value = 0 },
>> -	{ .name = "TOD",	.value = 1 },
>> -	{ .name = "IRIG",	.value = 2 },
>> -	{ .name = "PPS",	.value = 3 },
>> -	{ .name = "PTP",	.value = 4 },
>> -	{ .name = "RTC",	.value = 5 },
>> -	{ .name = "DCF",	.value = 6 },
>> -	{ .name = "REGS",	.value = 0xfe },
>> -	{ .name = "EXT",	.value = 0xff },
>> +	{ .name = "NONE",	.value = 0,		.dpll_type = 0 },
>> +	{ .name = "TOD",	.value = 1,		.dpll_type = 0 },
>> +	{ .name = "IRIG",	.value = 2,		.dpll_type = 0 },
>> +	{ .name = "PPS",	.value = 3,		.dpll_type = 0 },
>> +	{ .name = "PTP",	.value = 4,		.dpll_type = 0 },
>> +	{ .name = "RTC",	.value = 5,		.dpll_type = 0 },
>> +	{ .name = "DCF",	.value = 6,		.dpll_type = 0 },
>> +	{ .name = "REGS",	.value = 0xfe,		.dpll_type = 0 },
>> +	{ .name = "EXT",	.value = 0xff,		.dpll_type = 0 },
>> 	{ }
>> };
>>
>> @@ -680,37 +684,37 @@ static const struct ocp_selector ptp_ocp_clock[] = {
>> #define SMA_SELECT_MASK		GENMASK(14, 0)
>>
>> static const struct ocp_selector ptp_ocp_sma_in[] = {
>> -	{ .name = "10Mhz",	.value = 0x0000 },
>> -	{ .name = "PPS1",	.value = 0x0001 },
>> -	{ .name = "PPS2",	.value = 0x0002 },
>> -	{ .name = "TS1",	.value = 0x0004 },
>> -	{ .name = "TS2",	.value = 0x0008 },
>> -	{ .name = "IRIG",	.value = 0x0010 },
>> -	{ .name = "DCF",	.value = 0x0020 },
>> -	{ .name = "TS3",	.value = 0x0040 },
>> -	{ .name = "TS4",	.value = 0x0080 },
>> -	{ .name = "FREQ1",	.value = 0x0100 },
>> -	{ .name = "FREQ2",	.value = 0x0200 },
>> -	{ .name = "FREQ3",	.value = 0x0400 },
>> -	{ .name = "FREQ4",	.value = 0x0800 },
>> -	{ .name = "None",	.value = SMA_DISABLE },
>> +	{ .name = "10Mhz",	.value = 0x0000,	.dpll_type = DPLL_TYPE_EXT_10MHZ },
>> +	{ .name = "PPS1",	.value = 0x0001,	.dpll_type = DPLL_TYPE_EXT_1PPS },
>> +	{ .name = "PPS2",	.value = 0x0002,	.dpll_type = DPLL_TYPE_EXT_1PPS },
>> +	{ .name = "TS1",	.value = 0x0004,	.dpll_type = DPLL_TYPE_CUSTOM },
>> +	{ .name = "TS2",	.value = 0x0008,	.dpll_type = DPLL_TYPE_CUSTOM },
>> +	{ .name = "IRIG",	.value = 0x0010,	.dpll_type = DPLL_TYPE_CUSTOM },
>> +	{ .name = "DCF",	.value = 0x0020,	.dpll_type = DPLL_TYPE_CUSTOM },
>> +	{ .name = "TS3",	.value = 0x0040,	.dpll_type = DPLL_TYPE_CUSTOM },
>> +	{ .name = "TS4",	.value = 0x0080,	.dpll_type = DPLL_TYPE_CUSTOM },
>> +	{ .name = "FREQ1",	.value = 0x0100,	.dpll_type = DPLL_TYPE_CUSTOM },
>> +	{ .name = "FREQ2",	.value = 0x0200,	.dpll_type = DPLL_TYPE_CUSTOM },
>> +	{ .name = "FREQ3",	.value = 0x0400,	.dpll_type = DPLL_TYPE_CUSTOM },
>> +	{ .name = "FREQ4",	.value = 0x0800,	.dpll_type = DPLL_TYPE_CUSTOM },
>> +	{ .name = "None",	.value = SMA_DISABLE,	.dpll_type = DPLL_TYPE_NONE },
>> 	{ }
>> };
>>
>> static const struct ocp_selector ptp_ocp_sma_out[] = {
>> -	{ .name = "10Mhz",	.value = 0x0000 },
>> -	{ .name = "PHC",	.value = 0x0001 },
>> -	{ .name = "MAC",	.value = 0x0002 },
>> -	{ .name = "GNSS1",	.value = 0x0004 },
>> -	{ .name = "GNSS2",	.value = 0x0008 },
>> -	{ .name = "IRIG",	.value = 0x0010 },
>> -	{ .name = "DCF",	.value = 0x0020 },
>> -	{ .name = "GEN1",	.value = 0x0040 },
>> -	{ .name = "GEN2",	.value = 0x0080 },
>> -	{ .name = "GEN3",	.value = 0x0100 },
>> -	{ .name = "GEN4",	.value = 0x0200 },
>> -	{ .name = "GND",	.value = 0x2000 },
>> -	{ .name = "VCC",	.value = 0x4000 },
>> +	{ .name = "10Mhz",	.value = 0x0000,	.dpll_type = DPLL_TYPE_EXT_10MHZ },
>> +	{ .name = "PHC",	.value = 0x0001,	.dpll_type = DPLL_TYPE_INT_OSCILLATOR },
>> +	{ .name = "MAC",	.value = 0x0002,	.dpll_type = DPLL_TYPE_INT_OSCILLATOR },
>> +	{ .name = "GNSS1",	.value = 0x0004,	.dpll_type = DPLL_TYPE_GNSS },
>> +	{ .name = "GNSS2",	.value = 0x0008,	.dpll_type = DPLL_TYPE_GNSS },
>> +	{ .name = "IRIG",	.value = 0x0010,	.dpll_type = DPLL_TYPE_CUSTOM },
>> +	{ .name = "DCF",	.value = 0x0020,	.dpll_type = DPLL_TYPE_CUSTOM },
>> +	{ .name = "GEN1",	.value = 0x0040,	.dpll_type = DPLL_TYPE_CUSTOM },
>> +	{ .name = "GEN2",	.value = 0x0080,	.dpll_type = DPLL_TYPE_CUSTOM },
>> +	{ .name = "GEN3",	.value = 0x0100,	.dpll_type = DPLL_TYPE_CUSTOM },
>> +	{ .name = "GEN4",	.value = 0x0200,	.dpll_type = DPLL_TYPE_CUSTOM },
>> +	{ .name = "GND",	.value = 0x2000,	.dpll_type = DPLL_TYPE_CUSTOM },
>> +	{ .name = "VCC",	.value = 0x4000,	.dpll_type = DPLL_TYPE_CUSTOM },
>> 	{ }
>> };
>>
>> @@ -3707,6 +3711,90 @@ ptp_ocp_detach(struct ptp_ocp *bp)
>> 	device_unregister(&bp->dev);
>> }
>>
>> +static int ptp_ocp_dpll_get_status(struct dpll_device *dpll)
>> +{
>> +	struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll);
>> +	int sync;
>> +
>> +	sync = ioread32(&bp->reg->status) & OCP_STATUS_IN_SYNC;
>> +	return sync;
>> +}
>> +
>> +static int ptp_ocp_dpll_get_lock_status(struct dpll_device *dpll)
>> +{
>> +	struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll);
>> +	int sync;
>> +
>> +	sync = ioread32(&bp->reg->status) & OCP_STATUS_IN_SYNC;
>> +	return sync;
>> +}
>> +
>> +static int ptp_ocp_sma_get_dpll_type(struct ptp_ocp *bp, int sma_nr)
>> +{
>> +	const struct ocp_selector *tbl;
>> +	u32 val;
>> +
>> +	if (bp->sma[sma_nr].mode == SMA_MODE_IN)
>> +		tbl = bp->sma_op->tbl[0];
>> +	else
>> +		tbl = bp->sma_op->tbl[1];
>> +
>> +	val = ptp_ocp_sma_get(bp, sma_nr);
>> +	return tbl[val].dpll_type;
>> +}
>> +
>> +static int ptp_ocp_dpll_type_supported(struct dpll_device *dpll, int sma, int type, int dir)
>> +{
>> +	struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll);
>> +	const struct ocp_selector *tbl = bp->sma_op->tbl[dir];
>> +	int i;
>> +
>> +	for (i = 0; i < sizeof(*tbl); i++) {
>> +		if (tbl[i].dpll_type == type)
>> +			return 1;
>> +	}
>> +	return 0;
>> +}
>> +
>> +static int ptp_ocp_dpll_get_source_type(struct dpll_device *dpll, int sma)
>> +{
>> +	struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll);
>> +
>> +	if (bp->sma[sma].mode != SMA_MODE_IN)
>> +		return -1;
>> +
>> +	return ptp_ocp_sma_get_dpll_type(bp, sma);
>> +}
>> +
>> +static int ptp_ocp_dpll_get_source_supported(struct dpll_device *dpll, int sma, int type)
>> +{
>> +	return ptp_ocp_dpll_type_supported(dpll, sma, type, 0);
>> +}
>> +
>> +static int ptp_ocp_dpll_get_output_type(struct dpll_device *dpll, int sma)
>> +{
>> +	struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll);
>> +
>> +	if (bp->sma[sma].mode != SMA_MODE_OUT)
>> +		return -1;
>> +
>> +	return ptp_ocp_sma_get_dpll_type(bp, sma);
>> +}
>> +
>> +static int ptp_ocp_dpll_get_output_supported(struct dpll_device *dpll, int sma, int type)
>> +{
>> +	return ptp_ocp_dpll_type_supported(dpll, sma, type, 1);
>> +}
>> +
>> +static struct dpll_device_ops dpll_ops = {
> 
> Namespace prefix?

Sure, will add ptp_ocp for consistency.

> 
> 
>> +	.get_status		= ptp_ocp_dpll_get_status,
>> +	.get_lock_status	= ptp_ocp_dpll_get_lock_status,
>> +	.get_source_type	= ptp_ocp_dpll_get_source_type,
>> +	.get_source_supported	= ptp_ocp_dpll_get_source_supported,
>> +	.get_output_type	= ptp_ocp_dpll_get_output_type,
>> +	.get_output_supported	= ptp_ocp_dpll_get_output_supported,
>> +};
>> +
>> static int
>> ptp_ocp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
>> {
>> @@ -3762,6 +3850,14 @@ ptp_ocp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
>>
>> 	ptp_ocp_info(bp);
>> 	devlink_register(devlink);
>> +
>> +	bp->dpll = dpll_device_alloc(&dpll_ops, "ocp", ARRAY_SIZE(bp->sma), ARRAY_SIZE(bp->sma), bp);
>> +	if (!bp->dpll) {
> 
> You have to use IS_ERR() macro here.
> 
Thanks, will change.
> 
>> +		dev_err(&pdev->dev, "dpll_device_alloc failed\n");
>> +		return 0;
>> +	}
>> +	dpll_device_register(bp->dpll);
>> +
>> 	return 0;
>>
>> out:
>> @@ -3779,6 +3875,8 @@ ptp_ocp_remove(struct pci_dev *pdev)
>> 	struct ptp_ocp *bp = pci_get_drvdata(pdev);
>> 	struct devlink *devlink = priv_to_devlink(bp);
>>
>> +	dpll_device_unregister(bp->dpll);
>> +	dpll_device_free(bp->dpll);
>> 	devlink_unregister(devlink);
>> 	ptp_ocp_detach(bp);
>> 	pci_disable_device(pdev);
>> diff --git a/include/uapi/linux/dpll.h b/include/uapi/linux/dpll.h
>> index 8782d3425aae..59fc6ef81b40 100644
>> --- a/include/uapi/linux/dpll.h
>> +++ b/include/uapi/linux/dpll.h
>> @@ -55,11 +55,13 @@ enum dpll_genl_status {
>>
>> /* DPLL signal types used as source or as output */
>> enum dpll_genl_signal_type {
>> +	DPLL_TYPE_NONE,
>> 	DPLL_TYPE_EXT_1PPS,
>> 	DPLL_TYPE_EXT_10MHZ,
>> 	DPLL_TYPE_SYNCE_ETH_PORT,
>> 	DPLL_TYPE_INT_OSCILLATOR,
>> 	DPLL_TYPE_GNSS,
>> +	DPLL_TYPE_CUSTOM,
> 
> This hunk should not be here.
> I commented this on the previous version. Btw, this is not the only
> thing that I previously commented and you ignored. It is annoying to be
> honest. Could you please include the requested changes in next patchset
> version or comment why you are not do including them. Ignoring is never
> good :/
> 
Sorry for that. This version of patchset was issued to add visibility to the 
work done by Arkadiusz and to provide documentation (or at least part of it).
I will definitely address the comments in the next spin.

> 
>>
>> 	__DPLL_TYPE_MAX,
>> };
>> -- 
>> 2.27.0
>>


^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 6/6] ptp_ocp: implement DPLL ops
@ 2022-10-10 20:14       ` Vadim Fedorenko
  0 siblings, 0 replies; 67+ messages in thread
From: Vadim Fedorenko @ 2022-10-10 20:14 UTC (permalink / raw)
  To: Jiri Pirko
  Cc: Jakub Kicinski, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

On 10.10.2022 16:42, Jiri Pirko wrote:
> Mon, Oct 10, 2022 at 03:18:04AM CEST, vfedorenko@novek.ru wrote:
>> From: Vadim Fedorenko <vadfed@fb.com>
>>
>> Implement DPLL operations in ptp_ocp driver.
>>
>> Signed-off-by: Vadim Fedorenko <vadfed@fb.com>
>> ---
>> drivers/ptp/Kconfig       |   1 +
>> drivers/ptp/ptp_ocp.c     | 170 ++++++++++++++++++++++++++++++--------
>> include/uapi/linux/dpll.h |   2 +
>> 3 files changed, 137 insertions(+), 36 deletions(-)
>>
>> diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig
>> index fe4971b65c64..8c4cfabc1bfa 100644
>> --- a/drivers/ptp/Kconfig
>> +++ b/drivers/ptp/Kconfig
>> @@ -177,6 +177,7 @@ config PTP_1588_CLOCK_OCP
>> 	depends on COMMON_CLK
>> 	select NET_DEVLINK
>> 	select CRC16
>> +	select DPLL
>> 	help
>> 	  This driver adds support for an OpenCompute time card.
>>
>> diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c
>> index d36c3f597f77..a01c0c721802 100644
>> --- a/drivers/ptp/ptp_ocp.c
>> +++ b/drivers/ptp/ptp_ocp.c
>> @@ -21,6 +21,8 @@
>> #include <linux/mtd/mtd.h>
>> #include <linux/nvmem-consumer.h>
>> #include <linux/crc16.h>
>> +#include <linux/dpll.h>
>> +#include <uapi/linux/dpll.h>
> 
> This should not be needed to include directly. linux/dpll.h should
> include uapi/linux/dpll.h
> 

Got it, will change

> 
>>
>> #define PCI_VENDOR_ID_FACEBOOK			0x1d9b
>> #define PCI_DEVICE_ID_FACEBOOK_TIMECARD		0x0400
>> @@ -336,6 +338,7 @@ struct ptp_ocp {
>> 	struct ptp_ocp_signal	signal[4];
>> 	struct ptp_ocp_sma_connector sma[4];
>> 	const struct ocp_sma_op *sma_op;
>> +	struct dpll_device *dpll;
>> };
>>
>> #define OCP_REQ_TIMESTAMP	BIT(0)
>> @@ -660,18 +663,19 @@ static DEFINE_IDR(ptp_ocp_idr);
>> struct ocp_selector {
>> 	const char *name;
>> 	int value;
>> +	int dpll_type;
> 
> Enum?

Yes, I got it, will convert enums to actual enums in the series.

> 
> 
>> };
>>
>> static const struct ocp_selector ptp_ocp_clock[] = {
>> -	{ .name = "NONE",	.value = 0 },
>> -	{ .name = "TOD",	.value = 1 },
>> -	{ .name = "IRIG",	.value = 2 },
>> -	{ .name = "PPS",	.value = 3 },
>> -	{ .name = "PTP",	.value = 4 },
>> -	{ .name = "RTC",	.value = 5 },
>> -	{ .name = "DCF",	.value = 6 },
>> -	{ .name = "REGS",	.value = 0xfe },
>> -	{ .name = "EXT",	.value = 0xff },
>> +	{ .name = "NONE",	.value = 0,		.dpll_type = 0 },
>> +	{ .name = "TOD",	.value = 1,		.dpll_type = 0 },
>> +	{ .name = "IRIG",	.value = 2,		.dpll_type = 0 },
>> +	{ .name = "PPS",	.value = 3,		.dpll_type = 0 },
>> +	{ .name = "PTP",	.value = 4,		.dpll_type = 0 },
>> +	{ .name = "RTC",	.value = 5,		.dpll_type = 0 },
>> +	{ .name = "DCF",	.value = 6,		.dpll_type = 0 },
>> +	{ .name = "REGS",	.value = 0xfe,		.dpll_type = 0 },
>> +	{ .name = "EXT",	.value = 0xff,		.dpll_type = 0 },
>> 	{ }
>> };
>>
>> @@ -680,37 +684,37 @@ static const struct ocp_selector ptp_ocp_clock[] = {
>> #define SMA_SELECT_MASK		GENMASK(14, 0)
>>
>> static const struct ocp_selector ptp_ocp_sma_in[] = {
>> -	{ .name = "10Mhz",	.value = 0x0000 },
>> -	{ .name = "PPS1",	.value = 0x0001 },
>> -	{ .name = "PPS2",	.value = 0x0002 },
>> -	{ .name = "TS1",	.value = 0x0004 },
>> -	{ .name = "TS2",	.value = 0x0008 },
>> -	{ .name = "IRIG",	.value = 0x0010 },
>> -	{ .name = "DCF",	.value = 0x0020 },
>> -	{ .name = "TS3",	.value = 0x0040 },
>> -	{ .name = "TS4",	.value = 0x0080 },
>> -	{ .name = "FREQ1",	.value = 0x0100 },
>> -	{ .name = "FREQ2",	.value = 0x0200 },
>> -	{ .name = "FREQ3",	.value = 0x0400 },
>> -	{ .name = "FREQ4",	.value = 0x0800 },
>> -	{ .name = "None",	.value = SMA_DISABLE },
>> +	{ .name = "10Mhz",	.value = 0x0000,	.dpll_type = DPLL_TYPE_EXT_10MHZ },
>> +	{ .name = "PPS1",	.value = 0x0001,	.dpll_type = DPLL_TYPE_EXT_1PPS },
>> +	{ .name = "PPS2",	.value = 0x0002,	.dpll_type = DPLL_TYPE_EXT_1PPS },
>> +	{ .name = "TS1",	.value = 0x0004,	.dpll_type = DPLL_TYPE_CUSTOM },
>> +	{ .name = "TS2",	.value = 0x0008,	.dpll_type = DPLL_TYPE_CUSTOM },
>> +	{ .name = "IRIG",	.value = 0x0010,	.dpll_type = DPLL_TYPE_CUSTOM },
>> +	{ .name = "DCF",	.value = 0x0020,	.dpll_type = DPLL_TYPE_CUSTOM },
>> +	{ .name = "TS3",	.value = 0x0040,	.dpll_type = DPLL_TYPE_CUSTOM },
>> +	{ .name = "TS4",	.value = 0x0080,	.dpll_type = DPLL_TYPE_CUSTOM },
>> +	{ .name = "FREQ1",	.value = 0x0100,	.dpll_type = DPLL_TYPE_CUSTOM },
>> +	{ .name = "FREQ2",	.value = 0x0200,	.dpll_type = DPLL_TYPE_CUSTOM },
>> +	{ .name = "FREQ3",	.value = 0x0400,	.dpll_type = DPLL_TYPE_CUSTOM },
>> +	{ .name = "FREQ4",	.value = 0x0800,	.dpll_type = DPLL_TYPE_CUSTOM },
>> +	{ .name = "None",	.value = SMA_DISABLE,	.dpll_type = DPLL_TYPE_NONE },
>> 	{ }
>> };
>>
>> static const struct ocp_selector ptp_ocp_sma_out[] = {
>> -	{ .name = "10Mhz",	.value = 0x0000 },
>> -	{ .name = "PHC",	.value = 0x0001 },
>> -	{ .name = "MAC",	.value = 0x0002 },
>> -	{ .name = "GNSS1",	.value = 0x0004 },
>> -	{ .name = "GNSS2",	.value = 0x0008 },
>> -	{ .name = "IRIG",	.value = 0x0010 },
>> -	{ .name = "DCF",	.value = 0x0020 },
>> -	{ .name = "GEN1",	.value = 0x0040 },
>> -	{ .name = "GEN2",	.value = 0x0080 },
>> -	{ .name = "GEN3",	.value = 0x0100 },
>> -	{ .name = "GEN4",	.value = 0x0200 },
>> -	{ .name = "GND",	.value = 0x2000 },
>> -	{ .name = "VCC",	.value = 0x4000 },
>> +	{ .name = "10Mhz",	.value = 0x0000,	.dpll_type = DPLL_TYPE_EXT_10MHZ },
>> +	{ .name = "PHC",	.value = 0x0001,	.dpll_type = DPLL_TYPE_INT_OSCILLATOR },
>> +	{ .name = "MAC",	.value = 0x0002,	.dpll_type = DPLL_TYPE_INT_OSCILLATOR },
>> +	{ .name = "GNSS1",	.value = 0x0004,	.dpll_type = DPLL_TYPE_GNSS },
>> +	{ .name = "GNSS2",	.value = 0x0008,	.dpll_type = DPLL_TYPE_GNSS },
>> +	{ .name = "IRIG",	.value = 0x0010,	.dpll_type = DPLL_TYPE_CUSTOM },
>> +	{ .name = "DCF",	.value = 0x0020,	.dpll_type = DPLL_TYPE_CUSTOM },
>> +	{ .name = "GEN1",	.value = 0x0040,	.dpll_type = DPLL_TYPE_CUSTOM },
>> +	{ .name = "GEN2",	.value = 0x0080,	.dpll_type = DPLL_TYPE_CUSTOM },
>> +	{ .name = "GEN3",	.value = 0x0100,	.dpll_type = DPLL_TYPE_CUSTOM },
>> +	{ .name = "GEN4",	.value = 0x0200,	.dpll_type = DPLL_TYPE_CUSTOM },
>> +	{ .name = "GND",	.value = 0x2000,	.dpll_type = DPLL_TYPE_CUSTOM },
>> +	{ .name = "VCC",	.value = 0x4000,	.dpll_type = DPLL_TYPE_CUSTOM },
>> 	{ }
>> };
>>
>> @@ -3707,6 +3711,90 @@ ptp_ocp_detach(struct ptp_ocp *bp)
>> 	device_unregister(&bp->dev);
>> }
>>
>> +static int ptp_ocp_dpll_get_status(struct dpll_device *dpll)
>> +{
>> +	struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll);
>> +	int sync;
>> +
>> +	sync = ioread32(&bp->reg->status) & OCP_STATUS_IN_SYNC;
>> +	return sync;
>> +}
>> +
>> +static int ptp_ocp_dpll_get_lock_status(struct dpll_device *dpll)
>> +{
>> +	struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll);
>> +	int sync;
>> +
>> +	sync = ioread32(&bp->reg->status) & OCP_STATUS_IN_SYNC;
>> +	return sync;
>> +}
>> +
>> +static int ptp_ocp_sma_get_dpll_type(struct ptp_ocp *bp, int sma_nr)
>> +{
>> +	const struct ocp_selector *tbl;
>> +	u32 val;
>> +
>> +	if (bp->sma[sma_nr].mode == SMA_MODE_IN)
>> +		tbl = bp->sma_op->tbl[0];
>> +	else
>> +		tbl = bp->sma_op->tbl[1];
>> +
>> +	val = ptp_ocp_sma_get(bp, sma_nr);
>> +	return tbl[val].dpll_type;
>> +}
>> +
>> +static int ptp_ocp_dpll_type_supported(struct dpll_device *dpll, int sma, int type, int dir)
>> +{
>> +	struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll);
>> +	const struct ocp_selector *tbl = bp->sma_op->tbl[dir];
>> +	int i;
>> +
>> +	for (i = 0; i < sizeof(*tbl); i++) {
>> +		if (tbl[i].dpll_type == type)
>> +			return 1;
>> +	}
>> +	return 0;
>> +}
>> +
>> +static int ptp_ocp_dpll_get_source_type(struct dpll_device *dpll, int sma)
>> +{
>> +	struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll);
>> +
>> +	if (bp->sma[sma].mode != SMA_MODE_IN)
>> +		return -1;
>> +
>> +	return ptp_ocp_sma_get_dpll_type(bp, sma);
>> +}
>> +
>> +static int ptp_ocp_dpll_get_source_supported(struct dpll_device *dpll, int sma, int type)
>> +{
>> +	return ptp_ocp_dpll_type_supported(dpll, sma, type, 0);
>> +}
>> +
>> +static int ptp_ocp_dpll_get_output_type(struct dpll_device *dpll, int sma)
>> +{
>> +	struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll);
>> +
>> +	if (bp->sma[sma].mode != SMA_MODE_OUT)
>> +		return -1;
>> +
>> +	return ptp_ocp_sma_get_dpll_type(bp, sma);
>> +}
>> +
>> +static int ptp_ocp_dpll_get_output_supported(struct dpll_device *dpll, int sma, int type)
>> +{
>> +	return ptp_ocp_dpll_type_supported(dpll, sma, type, 1);
>> +}
>> +
>> +static struct dpll_device_ops dpll_ops = {
> 
> Namespace prefix?

Sure, will add ptp_ocp for consistency.

> 
> 
>> +	.get_status		= ptp_ocp_dpll_get_status,
>> +	.get_lock_status	= ptp_ocp_dpll_get_lock_status,
>> +	.get_source_type	= ptp_ocp_dpll_get_source_type,
>> +	.get_source_supported	= ptp_ocp_dpll_get_source_supported,
>> +	.get_output_type	= ptp_ocp_dpll_get_output_type,
>> +	.get_output_supported	= ptp_ocp_dpll_get_output_supported,
>> +};
>> +
>> static int
>> ptp_ocp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
>> {
>> @@ -3762,6 +3850,14 @@ ptp_ocp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
>>
>> 	ptp_ocp_info(bp);
>> 	devlink_register(devlink);
>> +
>> +	bp->dpll = dpll_device_alloc(&dpll_ops, "ocp", ARRAY_SIZE(bp->sma), ARRAY_SIZE(bp->sma), bp);
>> +	if (!bp->dpll) {
> 
> You have to use IS_ERR() macro here.
> 
Thanks, will change.
> 
>> +		dev_err(&pdev->dev, "dpll_device_alloc failed\n");
>> +		return 0;
>> +	}
>> +	dpll_device_register(bp->dpll);
>> +
>> 	return 0;
>>
>> out:
>> @@ -3779,6 +3875,8 @@ ptp_ocp_remove(struct pci_dev *pdev)
>> 	struct ptp_ocp *bp = pci_get_drvdata(pdev);
>> 	struct devlink *devlink = priv_to_devlink(bp);
>>
>> +	dpll_device_unregister(bp->dpll);
>> +	dpll_device_free(bp->dpll);
>> 	devlink_unregister(devlink);
>> 	ptp_ocp_detach(bp);
>> 	pci_disable_device(pdev);
>> diff --git a/include/uapi/linux/dpll.h b/include/uapi/linux/dpll.h
>> index 8782d3425aae..59fc6ef81b40 100644
>> --- a/include/uapi/linux/dpll.h
>> +++ b/include/uapi/linux/dpll.h
>> @@ -55,11 +55,13 @@ enum dpll_genl_status {
>>
>> /* DPLL signal types used as source or as output */
>> enum dpll_genl_signal_type {
>> +	DPLL_TYPE_NONE,
>> 	DPLL_TYPE_EXT_1PPS,
>> 	DPLL_TYPE_EXT_10MHZ,
>> 	DPLL_TYPE_SYNCE_ETH_PORT,
>> 	DPLL_TYPE_INT_OSCILLATOR,
>> 	DPLL_TYPE_GNSS,
>> +	DPLL_TYPE_CUSTOM,
> 
> This hunk should not be here.
> I commented this on the previous version. Btw, this is not the only
> thing that I previously commented and you ignored. It is annoying to be
> honest. Could you please include the requested changes in next patchset
> version or comment why you are not do including them. Ignoring is never
> good :/
> 
Sorry for that. This version of patchset was issued to add visibility to the 
work done by Arkadiusz and to provide documentation (or at least part of it).
I will definitely address the comments in the next spin.

> 
>>
>> 	__DPLL_TYPE_MAX,
>> };
>> -- 
>> 2.27.0
>>


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 6/6] ptp_ocp: implement DPLL ops
  2022-10-10  1:18   ` Vadim Fedorenko
  (?)
  (?)
@ 2022-10-11  0:30   ` kernel test robot
  -1 siblings, 0 replies; 67+ messages in thread
From: kernel test robot @ 2022-10-11  0:30 UTC (permalink / raw)
  To: Vadim Fedorenko; +Cc: llvm, kbuild-all

[-- Attachment #1: Type: text/plain, Size: 2299 bytes --]

Hi Vadim,

[FYI, it's a private test report for your RFC patch.]
[auto build test WARNING on linus/master]
[also build test WARNING on v6.0 next-20221010]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Vadim-Fedorenko/dpll-Add-DPLL-framework-base-functions/20221010-101813
base:   https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 493ffd6605b2d3d4dc7008ab927dba319f36671f
config: i386-allmodconfig
compiler: clang version 14.0.6 (https://github.com/llvm/llvm-project f28c006a5895fc0e329fe15fead81e37457cb1d1)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/intel-lab-lkp/linux/commit/b2144aa97838913b81a3cc24f0fb11ec7e720f1b
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Vadim-Fedorenko/dpll-Add-DPLL-framework-base-functions/20221010-101813
        git checkout b2144aa97838913b81a3cc24f0fb11ec7e720f1b
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=i386 SHELL=/bin/bash drivers/dpll/ drivers/net/dsa/mv88e6xxx/

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> drivers/dpll/dpll_netlink.c:743:13: warning: no previous prototype for function 'dpll_netlink_fini' [-Wmissing-prototypes]
   void __exit dpll_netlink_fini(void)
               ^
   drivers/dpll/dpll_netlink.c:743:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
   void __exit dpll_netlink_fini(void)
   ^
   static 
   1 warning generated.


vim +/dpll_netlink_fini +743 drivers/dpll/dpll_netlink.c

d175443713fad7 Vadim Fedorenko 2022-10-10  742  
d175443713fad7 Vadim Fedorenko 2022-10-10 @743  void __exit dpll_netlink_fini(void)

-- 
0-DAY CI Kernel Test Service
https://01.org/lkp

[-- Attachment #2: config --]
[-- Type: text/plain, Size: 280014 bytes --]

#
# Automatically generated file; DO NOT EDIT.
# Linux/i386 6.0.0 Kernel Configuration
#
CONFIG_CC_VERSION_TEXT="clang version 14.0.6 (git://gitmirror/llvm_project f28c006a5895fc0e329fe15fead81e37457cb1d1)"
CONFIG_GCC_VERSION=0
CONFIG_CC_IS_CLANG=y
CONFIG_CLANG_VERSION=140006
CONFIG_AS_IS_LLVM=y
CONFIG_AS_VERSION=140006
CONFIG_LD_VERSION=0
CONFIG_LD_IS_LLD=y
CONFIG_LLD_VERSION=140006
CONFIG_RUST_IS_AVAILABLE=y
CONFIG_CC_CAN_LINK=y
CONFIG_CC_CAN_LINK_STATIC=y
CONFIG_CC_HAS_ASM_GOTO_OUTPUT=y
CONFIG_TOOLS_SUPPORT_RELR=y
CONFIG_CC_HAS_ASM_INLINE=y
CONFIG_CC_HAS_NO_PROFILE_FN_ATTR=y
CONFIG_PAHOLE_VERSION=123
CONFIG_CONSTRUCTORS=y
CONFIG_IRQ_WORK=y
CONFIG_BUILDTIME_TABLE_SORT=y
CONFIG_THREAD_INFO_IN_TASK=y

#
# General setup
#
CONFIG_INIT_ENV_ARG_LIMIT=32
# CONFIG_COMPILE_TEST is not set
# CONFIG_WERROR is not set
CONFIG_UAPI_HEADER_TEST=y
CONFIG_LOCALVERSION=""
CONFIG_LOCALVERSION_AUTO=y
CONFIG_BUILD_SALT=""
CONFIG_HAVE_KERNEL_GZIP=y
CONFIG_HAVE_KERNEL_BZIP2=y
CONFIG_HAVE_KERNEL_LZMA=y
CONFIG_HAVE_KERNEL_XZ=y
CONFIG_HAVE_KERNEL_LZO=y
CONFIG_HAVE_KERNEL_LZ4=y
CONFIG_HAVE_KERNEL_ZSTD=y
CONFIG_KERNEL_GZIP=y
# CONFIG_KERNEL_BZIP2 is not set
# CONFIG_KERNEL_LZMA is not set
# CONFIG_KERNEL_XZ is not set
# CONFIG_KERNEL_LZO is not set
# CONFIG_KERNEL_LZ4 is not set
# CONFIG_KERNEL_ZSTD is not set
CONFIG_DEFAULT_INIT=""
CONFIG_DEFAULT_HOSTNAME="(none)"
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
CONFIG_POSIX_MQUEUE_SYSCTL=y
CONFIG_WATCH_QUEUE=y
CONFIG_CROSS_MEMORY_ATTACH=y
CONFIG_USELIB=y
CONFIG_AUDIT=y
CONFIG_HAVE_ARCH_AUDITSYSCALL=y
CONFIG_AUDITSYSCALL=y

#
# IRQ subsystem
#
CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_GENERIC_IRQ_SHOW=y
CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y
CONFIG_GENERIC_PENDING_IRQ=y
CONFIG_GENERIC_IRQ_MIGRATION=y
CONFIG_GENERIC_IRQ_INJECTION=y
CONFIG_HARDIRQS_SW_RESEND=y
CONFIG_GENERIC_IRQ_CHIP=y
CONFIG_IRQ_DOMAIN=y
CONFIG_IRQ_SIM=y
CONFIG_IRQ_DOMAIN_HIERARCHY=y
CONFIG_GENERIC_MSI_IRQ=y
CONFIG_GENERIC_MSI_IRQ_DOMAIN=y
CONFIG_IRQ_MSI_IOMMU=y
CONFIG_GENERIC_IRQ_MATRIX_ALLOCATOR=y
CONFIG_GENERIC_IRQ_RESERVATION_MODE=y
CONFIG_IRQ_FORCED_THREADING=y
CONFIG_SPARSE_IRQ=y
CONFIG_GENERIC_IRQ_DEBUGFS=y
# end of IRQ subsystem

CONFIG_CLOCKSOURCE_WATCHDOG=y
CONFIG_ARCH_CLOCKSOURCE_INIT=y
CONFIG_CLOCKSOURCE_VALIDATE_LAST_CYCLE=y
CONFIG_GENERIC_TIME_VSYSCALL=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST=y
CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_HAVE_POSIX_CPU_TIMERS_TASK_WORK=y
CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y
CONFIG_CONTEXT_TRACKING=y
CONFIG_CONTEXT_TRACKING_IDLE=y

#
# Timers subsystem
#
CONFIG_TICK_ONESHOT=y
CONFIG_NO_HZ_COMMON=y
# CONFIG_HZ_PERIODIC is not set
CONFIG_NO_HZ_IDLE=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_CLOCKSOURCE_WATCHDOG_MAX_SKEW_US=100
# end of Timers subsystem

CONFIG_BPF=y
CONFIG_HAVE_EBPF_JIT=y

#
# BPF subsystem
#
CONFIG_BPF_SYSCALL=y
CONFIG_BPF_JIT=y
CONFIG_BPF_JIT_ALWAYS_ON=y
CONFIG_BPF_JIT_DEFAULT_ON=y
CONFIG_BPF_UNPRIV_DEFAULT_OFF=y
CONFIG_USERMODE_DRIVER=y
# CONFIG_BPF_PRELOAD is not set
# CONFIG_BPF_LSM is not set
# end of BPF subsystem

CONFIG_PREEMPT_VOLUNTARY_BUILD=y
# CONFIG_PREEMPT_NONE is not set
CONFIG_PREEMPT_VOLUNTARY=y
# CONFIG_PREEMPT is not set
CONFIG_PREEMPT_COUNT=y
# CONFIG_PREEMPT_DYNAMIC is not set
CONFIG_SCHED_CORE=y

#
# CPU/Task time and stats accounting
#
CONFIG_TICK_CPU_ACCOUNTING=y
CONFIG_IRQ_TIME_ACCOUNTING=y
CONFIG_HAVE_SCHED_AVG_IRQ=y
CONFIG_BSD_PROCESS_ACCT=y
CONFIG_BSD_PROCESS_ACCT_V3=y
CONFIG_TASKSTATS=y
CONFIG_TASK_DELAY_ACCT=y
CONFIG_TASK_XACCT=y
CONFIG_TASK_IO_ACCOUNTING=y
CONFIG_PSI=y
CONFIG_PSI_DEFAULT_DISABLED=y
# end of CPU/Task time and stats accounting

CONFIG_CPU_ISOLATION=y

#
# RCU Subsystem
#
CONFIG_TREE_RCU=y
CONFIG_RCU_EXPERT=y
CONFIG_SRCU=y
CONFIG_TREE_SRCU=y
CONFIG_TASKS_RCU_GENERIC=y
CONFIG_FORCE_TASKS_RCU=y
CONFIG_TASKS_RCU=y
CONFIG_FORCE_TASKS_RUDE_RCU=y
CONFIG_TASKS_RUDE_RCU=y
CONFIG_FORCE_TASKS_TRACE_RCU=y
CONFIG_TASKS_TRACE_RCU=y
CONFIG_RCU_STALL_COMMON=y
CONFIG_RCU_NEED_SEGCBLIST=y
CONFIG_RCU_FANOUT=32
CONFIG_RCU_FANOUT_LEAF=16
CONFIG_RCU_NOCB_CPU=y
CONFIG_RCU_NOCB_CPU_DEFAULT_ALL=y
CONFIG_TASKS_TRACE_RCU_READ_MB=y
# end of RCU Subsystem

CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_IKHEADERS=m
CONFIG_LOG_BUF_SHIFT=20
CONFIG_LOG_CPU_MAX_BUF_SHIFT=12
CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT=13
CONFIG_PRINTK_INDEX=y
CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y

#
# Scheduler features
#
CONFIG_UCLAMP_TASK=y
CONFIG_UCLAMP_BUCKETS_COUNT=5
# end of Scheduler features

CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH=y
CONFIG_CC_IMPLICIT_FALLTHROUGH="-Wimplicit-fallthrough"
CONFIG_GCC12_NO_ARRAY_BOUNDS=y
CONFIG_CGROUPS=y
CONFIG_PAGE_COUNTER=y
CONFIG_CGROUP_FAVOR_DYNMODS=y
CONFIG_MEMCG=y
CONFIG_MEMCG_SWAP=y
CONFIG_MEMCG_KMEM=y
CONFIG_BLK_CGROUP=y
CONFIG_CGROUP_WRITEBACK=y
CONFIG_CGROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
CONFIG_CFS_BANDWIDTH=y
CONFIG_RT_GROUP_SCHED=y
CONFIG_UCLAMP_TASK_GROUP=y
CONFIG_CGROUP_PIDS=y
CONFIG_CGROUP_RDMA=y
CONFIG_CGROUP_FREEZER=y
CONFIG_CGROUP_HUGETLB=y
CONFIG_CPUSETS=y
CONFIG_PROC_PID_CPUSET=y
CONFIG_CGROUP_DEVICE=y
CONFIG_CGROUP_CPUACCT=y
CONFIG_CGROUP_PERF=y
# CONFIG_CGROUP_BPF is not set
CONFIG_CGROUP_MISC=y
CONFIG_CGROUP_DEBUG=y
CONFIG_SOCK_CGROUP_DATA=y
CONFIG_NAMESPACES=y
CONFIG_UTS_NS=y
CONFIG_TIME_NS=y
CONFIG_IPC_NS=y
CONFIG_USER_NS=y
CONFIG_PID_NS=y
CONFIG_NET_NS=y
CONFIG_CHECKPOINT_RESTORE=y
CONFIG_SCHED_AUTOGROUP=y
# CONFIG_SYSFS_DEPRECATED is not set
CONFIG_RELAY=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_RD_GZIP=y
CONFIG_RD_BZIP2=y
CONFIG_RD_LZMA=y
CONFIG_RD_XZ=y
CONFIG_RD_LZO=y
CONFIG_RD_LZ4=y
CONFIG_RD_ZSTD=y
CONFIG_BOOT_CONFIG=y
CONFIG_BOOT_CONFIG_EMBED=y
CONFIG_BOOT_CONFIG_EMBED_FILE=""
CONFIG_INITRAMFS_PRESERVE_MTIME=y
CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_LD_ORPHAN_WARN=y
CONFIG_SYSCTL=y
CONFIG_HAVE_UID16=y
CONFIG_SYSCTL_EXCEPTION_TRACE=y
CONFIG_HAVE_PCSPKR_PLATFORM=y
CONFIG_EXPERT=y
CONFIG_UID16=y
CONFIG_MULTIUSER=y
CONFIG_SGETMASK_SYSCALL=y
CONFIG_SYSFS_SYSCALL=y
CONFIG_FHANDLE=y
CONFIG_POSIX_TIMERS=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_PCSPKR_PLATFORM=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_FUTEX_PI=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_AIO=y
CONFIG_IO_URING=y
CONFIG_ADVISE_SYSCALLS=y
CONFIG_MEMBARRIER=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
CONFIG_KALLSYMS_BASE_RELATIVE=y
CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y
CONFIG_KCMP=y
CONFIG_RSEQ=y
CONFIG_DEBUG_RSEQ=y
CONFIG_EMBEDDED=y
CONFIG_HAVE_PERF_EVENTS=y
CONFIG_GUEST_PERF_EVENTS=y
CONFIG_PERF_USE_VMALLOC=y
CONFIG_PC104=y

#
# Kernel Performance Events And Counters
#
CONFIG_PERF_EVENTS=y
CONFIG_DEBUG_PERF_USE_VMALLOC=y
# end of Kernel Performance Events And Counters

CONFIG_SYSTEM_DATA_VERIFICATION=y
CONFIG_PROFILING=y
CONFIG_TRACEPOINTS=y
# end of General setup

CONFIG_X86_32=y
CONFIG_FORCE_DYNAMIC_FTRACE=y
CONFIG_X86=y
CONFIG_INSTRUCTION_DECODER=y
CONFIG_OUTPUT_FORMAT="elf32-i386"
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_MMU=y
CONFIG_ARCH_MMAP_RND_BITS_MIN=8
CONFIG_ARCH_MMAP_RND_BITS_MAX=16
CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=8
CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=16
CONFIG_GENERIC_ISA_DMA=y
CONFIG_GENERIC_BUG=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_ARCH_HAS_CPU_RELAX=y
CONFIG_ARCH_HIBERNATION_POSSIBLE=y
CONFIG_ARCH_NR_GPIO=512
CONFIG_ARCH_SUSPEND_POSSIBLE=y
CONFIG_HAVE_INTEL_TXT=y
CONFIG_X86_32_SMP=y
CONFIG_ARCH_SUPPORTS_UPROBES=y
CONFIG_FIX_EARLYCON_MEM=y
CONFIG_PGTABLE_LEVELS=2

#
# Processor type and features
#
CONFIG_SMP=y
CONFIG_X86_FEATURE_NAMES=y
CONFIG_X86_MPPARSE=y
CONFIG_GOLDFISH=y
CONFIG_X86_CPU_RESCTRL=y
CONFIG_X86_BIGSMP=y
CONFIG_X86_EXTENDED_PLATFORM=y
# CONFIG_X86_GOLDFISH is not set
CONFIG_X86_INTEL_MID=y
CONFIG_X86_INTEL_QUARK=y
CONFIG_X86_INTEL_LPSS=y
# CONFIG_X86_AMD_PLATFORM_DEVICE is not set
CONFIG_IOSF_MBI=y
CONFIG_IOSF_MBI_DEBUG=y
CONFIG_X86_RDC321X=y
CONFIG_X86_32_NON_STANDARD=y
CONFIG_X86_SUPPORTS_MEMORY_FAILURE=y
CONFIG_STA2X11=y
CONFIG_X86_32_IRIS=m
# CONFIG_SCHED_OMIT_FRAME_POINTER is not set
CONFIG_HYPERVISOR_GUEST=y
CONFIG_PARAVIRT=y
CONFIG_PARAVIRT_DEBUG=y
CONFIG_PARAVIRT_SPINLOCKS=y
CONFIG_X86_HV_CALLBACK_VECTOR=y
CONFIG_KVM_GUEST=y
CONFIG_ARCH_CPUIDLE_HALTPOLL=y
CONFIG_PVH=y
CONFIG_PARAVIRT_TIME_ACCOUNTING=y
CONFIG_PARAVIRT_CLOCK=y
# CONFIG_M486SX is not set
# CONFIG_M486 is not set
# CONFIG_M586 is not set
# CONFIG_M586TSC is not set
# CONFIG_M586MMX is not set
CONFIG_M686=y
# CONFIG_MPENTIUMII is not set
# CONFIG_MPENTIUMIII is not set
# CONFIG_MPENTIUMM is not set
# CONFIG_MPENTIUM4 is not set
# CONFIG_MK6 is not set
# CONFIG_MK7 is not set
# CONFIG_MK8 is not set
# CONFIG_MCRUSOE is not set
# CONFIG_MEFFICEON is not set
# CONFIG_MWINCHIPC6 is not set
# CONFIG_MWINCHIP3D is not set
# CONFIG_MELAN is not set
# CONFIG_MGEODEGX1 is not set
# CONFIG_MGEODE_LX is not set
# CONFIG_MCYRIXIII is not set
# CONFIG_MVIAC3_2 is not set
# CONFIG_MVIAC7 is not set
# CONFIG_MCORE2 is not set
# CONFIG_MATOM is not set
CONFIG_X86_GENERIC=y
CONFIG_X86_INTERNODE_CACHE_SHIFT=6
CONFIG_X86_L1_CACHE_SHIFT=6
CONFIG_X86_INTEL_USERCOPY=y
CONFIG_X86_USE_PPRO_CHECKSUM=y
CONFIG_X86_TSC=y
CONFIG_X86_CMPXCHG64=y
CONFIG_X86_CMOV=y
CONFIG_X86_MINIMUM_CPU_FAMILY=6
CONFIG_X86_DEBUGCTLMSR=y
CONFIG_IA32_FEAT_CTL=y
CONFIG_X86_VMX_FEATURE_NAMES=y
CONFIG_PROCESSOR_SELECT=y
CONFIG_CPU_SUP_INTEL=y
# CONFIG_CPU_SUP_CYRIX_32 is not set
# CONFIG_CPU_SUP_AMD is not set
# CONFIG_CPU_SUP_HYGON is not set
# CONFIG_CPU_SUP_CENTAUR is not set
CONFIG_CPU_SUP_TRANSMETA_32=y
CONFIG_CPU_SUP_UMC_32=y
# CONFIG_CPU_SUP_ZHAOXIN is not set
CONFIG_CPU_SUP_VORTEX_32=y
CONFIG_HPET_TIMER=y
CONFIG_HPET_EMULATE_RTC=y
CONFIG_DMI=y
CONFIG_BOOT_VESA_SUPPORT=y
CONFIG_NR_CPUS_RANGE_BEGIN=2
CONFIG_NR_CPUS_RANGE_END=64
CONFIG_NR_CPUS_DEFAULT=32
CONFIG_NR_CPUS=32
CONFIG_SCHED_CLUSTER=y
CONFIG_SCHED_SMT=y
CONFIG_SCHED_MC=y
CONFIG_SCHED_MC_PRIO=y
CONFIG_X86_LOCAL_APIC=y
CONFIG_X86_IO_APIC=y
CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS=y
CONFIG_X86_MCE=y
CONFIG_X86_MCELOG_LEGACY=y
CONFIG_X86_MCE_INTEL=y
CONFIG_X86_ANCIENT_MCE=y
CONFIG_X86_MCE_THRESHOLD=y
CONFIG_X86_MCE_INJECT=m

#
# Performance monitoring
#
CONFIG_PERF_EVENTS_INTEL_UNCORE=m
CONFIG_PERF_EVENTS_INTEL_RAPL=m
CONFIG_PERF_EVENTS_INTEL_CSTATE=m
# end of Performance monitoring

CONFIG_X86_LEGACY_VM86=y
CONFIG_VM86=y
CONFIG_X86_16BIT=y
CONFIG_X86_ESPFIX32=y
CONFIG_X86_IOPL_IOPERM=y
CONFIG_TOSHIBA=m
CONFIG_X86_REBOOTFIXUPS=y
CONFIG_MICROCODE=y
CONFIG_MICROCODE_INTEL=y
CONFIG_MICROCODE_LATE_LOADING=y
CONFIG_X86_MSR=m
CONFIG_X86_CPUID=m
# CONFIG_NOHIGHMEM is not set
CONFIG_HIGHMEM4G=y
# CONFIG_HIGHMEM64G is not set
CONFIG_VMSPLIT_3G=y
# CONFIG_VMSPLIT_3G_OPT is not set
# CONFIG_VMSPLIT_2G is not set
# CONFIG_VMSPLIT_2G_OPT is not set
# CONFIG_VMSPLIT_1G is not set
CONFIG_PAGE_OFFSET=0xC0000000
CONFIG_HIGHMEM=y
CONFIG_X86_CPA_STATISTICS=y
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_SPARSEMEM_ENABLE=y
CONFIG_ARCH_SELECT_MEMORY_MODEL=y
CONFIG_ILLEGAL_POINTER_VALUE=0
CONFIG_HIGHPTE=y
CONFIG_X86_CHECK_BIOS_CORRUPTION=y
CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK=y
CONFIG_MTRR=y
CONFIG_MTRR_SANITIZER=y
CONFIG_MTRR_SANITIZER_ENABLE_DEFAULT=0
CONFIG_MTRR_SANITIZER_SPARE_REG_NR_DEFAULT=1
CONFIG_X86_PAT=y
CONFIG_ARCH_USES_PG_UNCACHED=y
CONFIG_X86_UMIP=y
CONFIG_CC_HAS_IBT=y
CONFIG_X86_INTEL_TSX_MODE_OFF=y
# CONFIG_X86_INTEL_TSX_MODE_ON is not set
# CONFIG_X86_INTEL_TSX_MODE_AUTO is not set
CONFIG_EFI=y
CONFIG_EFI_STUB=y
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
CONFIG_SCHED_HRTICK=y
CONFIG_KEXEC=y
CONFIG_CRASH_DUMP=y
CONFIG_KEXEC_JUMP=y
CONFIG_PHYSICAL_START=0x1000000
CONFIG_RELOCATABLE=y
# CONFIG_RANDOMIZE_BASE is not set
CONFIG_X86_NEED_RELOCS=y
CONFIG_PHYSICAL_ALIGN=0x200000
CONFIG_HOTPLUG_CPU=y
CONFIG_BOOTPARAM_HOTPLUG_CPU0=y
CONFIG_DEBUG_HOTPLUG_CPU0=y
CONFIG_COMPAT_VDSO=y
# CONFIG_CMDLINE_BOOL is not set
CONFIG_MODIFY_LDT_SYSCALL=y
CONFIG_STRICT_SIGALTSTACK_SIZE=y
# end of Processor type and features

CONFIG_SPECULATION_MITIGATIONS=y
CONFIG_RETPOLINE=y
CONFIG_ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE=y

#
# Power management and ACPI options
#
CONFIG_ARCH_HIBERNATION_HEADER=y
CONFIG_SUSPEND=y
CONFIG_SUSPEND_FREEZER=y
CONFIG_SUSPEND_SKIP_SYNC=y
CONFIG_HIBERNATE_CALLBACKS=y
CONFIG_HIBERNATION=y
CONFIG_HIBERNATION_SNAPSHOT_DEV=y
CONFIG_PM_STD_PARTITION=""
CONFIG_PM_SLEEP=y
CONFIG_PM_SLEEP_SMP=y
CONFIG_PM_AUTOSLEEP=y
CONFIG_PM_USERSPACE_AUTOSLEEP=y
CONFIG_PM_WAKELOCKS=y
CONFIG_PM_WAKELOCKS_LIMIT=100
CONFIG_PM_WAKELOCKS_GC=y
CONFIG_PM=y
CONFIG_PM_DEBUG=y
CONFIG_PM_ADVANCED_DEBUG=y
# CONFIG_PM_TEST_SUSPEND is not set
CONFIG_PM_SLEEP_DEBUG=y
CONFIG_DPM_WATCHDOG=y
CONFIG_DPM_WATCHDOG_TIMEOUT=120
CONFIG_PM_TRACE=y
CONFIG_PM_TRACE_RTC=y
CONFIG_PM_CLK=y
CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y
CONFIG_ENERGY_MODEL=y
CONFIG_ARCH_SUPPORTS_ACPI=y
CONFIG_ACPI=y
CONFIG_ACPI_LEGACY_TABLES_LOOKUP=y
CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC=y
CONFIG_ACPI_SYSTEM_POWER_STATES_SUPPORT=y
CONFIG_ACPI_TABLE_LIB=y
CONFIG_ACPI_DEBUGGER=y
CONFIG_ACPI_DEBUGGER_USER=m
CONFIG_ACPI_SPCR_TABLE=y
CONFIG_ACPI_SLEEP=y
CONFIG_ACPI_REV_OVERRIDE_POSSIBLE=y
CONFIG_ACPI_EC_DEBUGFS=m
CONFIG_ACPI_AC=m
CONFIG_ACPI_BATTERY=m
CONFIG_ACPI_BUTTON=m
CONFIG_ACPI_TINY_POWER_BUTTON=m
CONFIG_ACPI_TINY_POWER_BUTTON_SIGNAL=38
CONFIG_ACPI_VIDEO=m
CONFIG_ACPI_FAN=m
CONFIG_ACPI_TAD=m
CONFIG_ACPI_DOCK=y
CONFIG_ACPI_CPU_FREQ_PSS=y
CONFIG_ACPI_PROCESSOR_CSTATE=y
CONFIG_ACPI_PROCESSOR_IDLE=y
CONFIG_ACPI_PROCESSOR=y
CONFIG_ACPI_IPMI=m
CONFIG_ACPI_HOTPLUG_CPU=y
CONFIG_ACPI_PROCESSOR_AGGREGATOR=m
CONFIG_ACPI_THERMAL=m
CONFIG_ACPI_PLATFORM_PROFILE=m
CONFIG_ARCH_HAS_ACPI_TABLE_UPGRADE=y
CONFIG_ACPI_TABLE_UPGRADE=y
CONFIG_ACPI_DEBUG=y
CONFIG_ACPI_PCI_SLOT=y
CONFIG_ACPI_CONTAINER=y
CONFIG_ACPI_HOTPLUG_IOAPIC=y
CONFIG_ACPI_SBS=m
CONFIG_ACPI_HED=y
CONFIG_ACPI_CUSTOM_METHOD=m
CONFIG_ACPI_BGRT=y
# CONFIG_ACPI_REDUCED_HARDWARE_ONLY is not set
CONFIG_HAVE_ACPI_APEI=y
CONFIG_HAVE_ACPI_APEI_NMI=y
CONFIG_ACPI_APEI=y
CONFIG_ACPI_APEI_GHES=y
CONFIG_ACPI_APEI_PCIEAER=y
CONFIG_ACPI_APEI_MEMORY_FAILURE=y
CONFIG_ACPI_APEI_EINJ=m
CONFIG_ACPI_APEI_ERST_DEBUG=m
CONFIG_ACPI_DPTF=y
CONFIG_DPTF_POWER=m
CONFIG_DPTF_PCH_FIVR=m
CONFIG_ACPI_WATCHDOG=y
CONFIG_ACPI_EXTLOG=m
CONFIG_ACPI_CONFIGFS=m
CONFIG_ACPI_PCC=y
CONFIG_PMIC_OPREGION=y
CONFIG_XPOWER_PMIC_OPREGION=y
CONFIG_BXT_WC_PMIC_OPREGION=y
CONFIG_TPS68470_PMIC_OPREGION=y
CONFIG_ACPI_VIOT=y
CONFIG_X86_PM_TIMER=y
CONFIG_X86_APM_BOOT=y
CONFIG_APM=m
CONFIG_APM_IGNORE_USER_SUSPEND=y
CONFIG_APM_DO_ENABLE=y
CONFIG_APM_CPU_IDLE=y
CONFIG_APM_DISPLAY_BLANK=y
CONFIG_APM_ALLOW_INTS=y

#
# CPU Frequency scaling
#
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_GOV_ATTR_SET=y
CONFIG_CPU_FREQ_GOV_COMMON=y
CONFIG_CPU_FREQ_STAT=y
# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL=y
CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=m
CONFIG_CPU_FREQ_GOV_USERSPACE=m
CONFIG_CPU_FREQ_GOV_ONDEMAND=m
CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y

#
# CPU frequency scaling drivers
#
CONFIG_CPUFREQ_DT=m
CONFIG_CPUFREQ_DT_PLATDEV=y
CONFIG_X86_INTEL_PSTATE=y
CONFIG_X86_PCC_CPUFREQ=m
# CONFIG_X86_AMD_PSTATE is not set
CONFIG_X86_AMD_PSTATE_UT=m
CONFIG_X86_ACPI_CPUFREQ=m
CONFIG_X86_POWERNOW_K6=m
CONFIG_X86_POWERNOW_K7=m
CONFIG_X86_POWERNOW_K7_ACPI=y
CONFIG_X86_POWERNOW_K8=m
CONFIG_X86_GX_SUSPMOD=m
CONFIG_X86_SPEEDSTEP_CENTRINO=m
CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE=y
CONFIG_X86_SPEEDSTEP_ICH=m
CONFIG_X86_SPEEDSTEP_SMI=m
CONFIG_X86_P4_CLOCKMOD=m
CONFIG_X86_CPUFREQ_NFORCE2=m
CONFIG_X86_LONGRUN=m
CONFIG_X86_LONGHAUL=m
CONFIG_X86_E_POWERSAVER=m

#
# shared options
#
CONFIG_X86_SPEEDSTEP_LIB=m
CONFIG_X86_SPEEDSTEP_RELAXED_CAP_CHECK=y
# end of CPU Frequency scaling

#
# CPU Idle
#
CONFIG_CPU_IDLE=y
CONFIG_CPU_IDLE_GOV_LADDER=y
CONFIG_CPU_IDLE_GOV_MENU=y
CONFIG_CPU_IDLE_GOV_TEO=y
CONFIG_CPU_IDLE_GOV_HALTPOLL=y
CONFIG_HALTPOLL_CPUIDLE=m
# end of CPU Idle

CONFIG_INTEL_IDLE=y
# end of Power management and ACPI options

#
# Bus options (PCI etc.)
#
# CONFIG_PCI_GOBIOS is not set
# CONFIG_PCI_GOMMCONFIG is not set
# CONFIG_PCI_GODIRECT is not set
# CONFIG_PCI_GOOLPC is not set
CONFIG_PCI_GOANY=y
CONFIG_PCI_BIOS=y
CONFIG_PCI_DIRECT=y
CONFIG_PCI_MMCONFIG=y
CONFIG_PCI_OLPC=y
CONFIG_PCI_CNB20LE_QUIRK=y
CONFIG_ISA_BUS=y
CONFIG_ISA_DMA_API=y
CONFIG_ISA=y
CONFIG_SCx200=m
CONFIG_SCx200HR_TIMER=m
CONFIG_OLPC=y
CONFIG_OLPC_XO15_SCI=y
CONFIG_ALIX=y
CONFIG_NET5501=y
CONFIG_GEOS=y
# end of Bus options (PCI etc.)

#
# Binary Emulations
#
CONFIG_COMPAT_32=y
# end of Binary Emulations

CONFIG_HAVE_ATOMIC_IOMAP=y
CONFIG_HAVE_KVM=y
CONFIG_HAVE_KVM_PFNCACHE=y
CONFIG_HAVE_KVM_IRQCHIP=y
CONFIG_HAVE_KVM_IRQFD=y
CONFIG_HAVE_KVM_IRQ_ROUTING=y
CONFIG_HAVE_KVM_DIRTY_RING=y
CONFIG_HAVE_KVM_EVENTFD=y
CONFIG_KVM_MMIO=y
CONFIG_KVM_ASYNC_PF=y
CONFIG_HAVE_KVM_MSI=y
CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT=y
CONFIG_KVM_VFIO=y
CONFIG_KVM_GENERIC_DIRTYLOG_READ_PROTECT=y
CONFIG_HAVE_KVM_IRQ_BYPASS=y
CONFIG_HAVE_KVM_NO_POLL=y
CONFIG_KVM_XFER_TO_GUEST_WORK=y
CONFIG_HAVE_KVM_PM_NOTIFIER=y
CONFIG_VIRTUALIZATION=y
CONFIG_KVM=m
# CONFIG_KVM_WERROR is not set
CONFIG_KVM_INTEL=m
# CONFIG_KVM_AMD is not set
CONFIG_KVM_XEN=y
CONFIG_AS_AVX512=y
CONFIG_AS_SHA1_NI=y
CONFIG_AS_SHA256_NI=y
CONFIG_AS_TPAUSE=y

#
# General architecture-dependent options
#
CONFIG_CRASH_CORE=y
CONFIG_KEXEC_CORE=y
CONFIG_HOTPLUG_SMT=y
CONFIG_GENERIC_ENTRY=y
CONFIG_KPROBES=y
CONFIG_JUMP_LABEL=y
# CONFIG_STATIC_KEYS_SELFTEST is not set
# CONFIG_STATIC_CALL_SELFTEST is not set
CONFIG_OPTPROBES=y
CONFIG_KPROBES_ON_FTRACE=y
CONFIG_UPROBES=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_ARCH_USE_BUILTIN_BSWAP=y
CONFIG_KRETPROBES=y
CONFIG_KRETPROBE_ON_RETHOOK=y
CONFIG_USER_RETURN_NOTIFIER=y
CONFIG_HAVE_IOREMAP_PROT=y
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_OPTPROBES=y
CONFIG_HAVE_KPROBES_ON_FTRACE=y
CONFIG_ARCH_CORRECT_STACKTRACE_ON_KRETPROBE=y
CONFIG_HAVE_FUNCTION_ERROR_INJECTION=y
CONFIG_HAVE_NMI=y
CONFIG_TRACE_IRQFLAGS_SUPPORT=y
CONFIG_TRACE_IRQFLAGS_NMI_SUPPORT=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_DMA_CONTIGUOUS=y
CONFIG_GENERIC_SMP_IDLE_THREAD=y
CONFIG_ARCH_HAS_FORTIFY_SOURCE=y
CONFIG_ARCH_HAS_SET_MEMORY=y
CONFIG_ARCH_HAS_SET_DIRECT_MAP=y
CONFIG_HAVE_ARCH_THREAD_STRUCT_WHITELIST=y
CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT=y
CONFIG_ARCH_WANTS_NO_INSTR=y
CONFIG_ARCH_32BIT_OFF_T=y
CONFIG_HAVE_ASM_MODVERSIONS=y
CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
CONFIG_HAVE_RSEQ=y
CONFIG_HAVE_FUNCTION_ARG_ACCESS_API=y
CONFIG_HAVE_HW_BREAKPOINT=y
CONFIG_HAVE_MIXED_BREAKPOINTS_REGS=y
CONFIG_HAVE_USER_RETURN_NOTIFIER=y
CONFIG_HAVE_PERF_EVENTS_NMI=y
CONFIG_HAVE_HARDLOCKUP_DETECTOR_PERF=y
CONFIG_HAVE_PERF_REGS=y
CONFIG_HAVE_PERF_USER_STACK_DUMP=y
CONFIG_HAVE_ARCH_JUMP_LABEL=y
CONFIG_HAVE_ARCH_JUMP_LABEL_RELATIVE=y
CONFIG_MMU_GATHER_TABLE_FREE=y
CONFIG_MMU_GATHER_RCU_TABLE_FREE=y
CONFIG_MMU_GATHER_MERGE_VMAS=y
CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y
CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y
CONFIG_HAVE_CMPXCHG_LOCAL=y
CONFIG_HAVE_CMPXCHG_DOUBLE=y
CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
CONFIG_HAVE_ARCH_SECCOMP=y
CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
CONFIG_SECCOMP=y
CONFIG_SECCOMP_FILTER=y
CONFIG_SECCOMP_CACHE_DEBUG=y
CONFIG_HAVE_ARCH_STACKLEAK=y
CONFIG_ARCH_SUPPORTS_LTO_CLANG=y
CONFIG_ARCH_SUPPORTS_LTO_CLANG_THIN=y
CONFIG_LTO_NONE=y
CONFIG_HAVE_ARCH_WITHIN_STACK_FRAMES=y
CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
CONFIG_HAVE_MOVE_PUD=y
CONFIG_HAVE_MOVE_PMD=y
CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y
CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y
CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
CONFIG_MODULES_USE_ELF_REL=y
CONFIG_HAVE_SOFTIRQ_ON_OWN_STACK=y
CONFIG_SOFTIRQ_ON_OWN_STACK=y
CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
CONFIG_HAVE_ARCH_MMAP_RND_BITS=y
CONFIG_HAVE_EXIT_THREAD=y
CONFIG_ARCH_MMAP_RND_BITS=8
CONFIG_PAGE_SIZE_LESS_THAN_64KB=y
CONFIG_PAGE_SIZE_LESS_THAN_256KB=y
CONFIG_ISA_BUS_API=y
CONFIG_CLONE_BACKWARDS=y
CONFIG_OLD_SIGSUSPEND3=y
CONFIG_OLD_SIGACTION=y
CONFIG_COMPAT_32BIT_TIME=y
CONFIG_HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET=y
CONFIG_RANDOMIZE_KSTACK_OFFSET=y
CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT=y
CONFIG_ARCH_HAS_STRICT_KERNEL_RWX=y
CONFIG_STRICT_KERNEL_RWX=y
CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y
CONFIG_STRICT_MODULE_RWX=y
CONFIG_HAVE_ARCH_PREL32_RELOCATIONS=y
CONFIG_ARCH_USE_MEMREMAP_PROT=y
CONFIG_LOCK_EVENT_COUNTS=y
CONFIG_ARCH_HAS_MEM_ENCRYPT=y
CONFIG_HAVE_STATIC_CALL=y
CONFIG_HAVE_PREEMPT_DYNAMIC=y
CONFIG_HAVE_PREEMPT_DYNAMIC_CALL=y
CONFIG_ARCH_WANT_LD_ORPHAN_WARN=y
CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
CONFIG_ARCH_SPLIT_ARG64=y
CONFIG_ARCH_HAS_PARANOID_L1D_FLUSH=y
CONFIG_DYNAMIC_SIGFRAME=y

#
# GCOV-based kernel profiling
#
CONFIG_GCOV_KERNEL=y
CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
# CONFIG_GCOV_PROFILE_ALL is not set
# end of GCOV-based kernel profiling

CONFIG_HAVE_GCC_PLUGINS=y
# end of General architecture-dependent options

CONFIG_RT_MUTEXES=y
CONFIG_BASE_SMALL=0
CONFIG_MODULE_SIG_FORMAT=y
CONFIG_MODULES=y
CONFIG_MODULE_FORCE_LOAD=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
CONFIG_MODULE_UNLOAD_TAINT_TRACKING=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_MODULE_SIG=y
CONFIG_MODULE_SIG_FORCE=y
CONFIG_MODULE_SIG_ALL=y
CONFIG_MODULE_SIG_SHA1=y
# CONFIG_MODULE_SIG_SHA224 is not set
# CONFIG_MODULE_SIG_SHA256 is not set
# CONFIG_MODULE_SIG_SHA384 is not set
# CONFIG_MODULE_SIG_SHA512 is not set
CONFIG_MODULE_SIG_HASH="sha1"
CONFIG_MODULE_COMPRESS_NONE=y
# CONFIG_MODULE_COMPRESS_GZIP is not set
# CONFIG_MODULE_COMPRESS_XZ is not set
# CONFIG_MODULE_COMPRESS_ZSTD is not set
CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS=y
CONFIG_MODPROBE_PATH="/sbin/modprobe"
# CONFIG_TRIM_UNUSED_KSYMS is not set
CONFIG_MODULES_TREE_LOOKUP=y
CONFIG_BLOCK=y
CONFIG_BLOCK_LEGACY_AUTOLOAD=y
CONFIG_BLK_RQ_ALLOC_TIME=y
CONFIG_BLK_CGROUP_RWSTAT=y
CONFIG_BLK_DEV_BSG_COMMON=y
CONFIG_BLK_ICQ=y
CONFIG_BLK_DEV_BSGLIB=y
CONFIG_BLK_DEV_INTEGRITY=y
CONFIG_BLK_DEV_INTEGRITY_T10=m
CONFIG_BLK_DEV_ZONED=y
CONFIG_BLK_DEV_THROTTLING=y
CONFIG_BLK_DEV_THROTTLING_LOW=y
CONFIG_BLK_WBT=y
CONFIG_BLK_WBT_MQ=y
CONFIG_BLK_CGROUP_IOLATENCY=y
CONFIG_BLK_CGROUP_FC_APPID=y
CONFIG_BLK_CGROUP_IOCOST=y
CONFIG_BLK_CGROUP_IOPRIO=y
CONFIG_BLK_DEBUG_FS=y
CONFIG_BLK_DEBUG_FS_ZONED=y
CONFIG_BLK_SED_OPAL=y
CONFIG_BLK_INLINE_ENCRYPTION=y
CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y

#
# Partition Types
#
CONFIG_PARTITION_ADVANCED=y
CONFIG_ACORN_PARTITION=y
CONFIG_ACORN_PARTITION_CUMANA=y
CONFIG_ACORN_PARTITION_EESOX=y
CONFIG_ACORN_PARTITION_ICS=y
CONFIG_ACORN_PARTITION_ADFS=y
CONFIG_ACORN_PARTITION_POWERTEC=y
CONFIG_ACORN_PARTITION_RISCIX=y
CONFIG_AIX_PARTITION=y
CONFIG_OSF_PARTITION=y
CONFIG_AMIGA_PARTITION=y
CONFIG_ATARI_PARTITION=y
CONFIG_MAC_PARTITION=y
CONFIG_MSDOS_PARTITION=y
CONFIG_BSD_DISKLABEL=y
CONFIG_MINIX_SUBPARTITION=y
CONFIG_SOLARIS_X86_PARTITION=y
CONFIG_UNIXWARE_DISKLABEL=y
CONFIG_LDM_PARTITION=y
CONFIG_LDM_DEBUG=y
CONFIG_SGI_PARTITION=y
CONFIG_ULTRIX_PARTITION=y
CONFIG_SUN_PARTITION=y
CONFIG_KARMA_PARTITION=y
CONFIG_EFI_PARTITION=y
CONFIG_SYSV68_PARTITION=y
CONFIG_CMDLINE_PARTITION=y
# end of Partition Types

CONFIG_BLK_MQ_PCI=y
CONFIG_BLK_MQ_VIRTIO=y
CONFIG_BLK_MQ_RDMA=y
CONFIG_BLK_PM=y
CONFIG_BLOCK_HOLDER_DEPRECATED=y
CONFIG_BLK_MQ_STACKING=y

#
# IO Schedulers
#
CONFIG_MQ_IOSCHED_DEADLINE=y
CONFIG_MQ_IOSCHED_KYBER=m
CONFIG_IOSCHED_BFQ=m
CONFIG_BFQ_GROUP_IOSCHED=y
CONFIG_BFQ_CGROUP_DEBUG=y
# end of IO Schedulers

CONFIG_PREEMPT_NOTIFIERS=y
CONFIG_PADATA=y
CONFIG_ASN1=y
CONFIG_UNINLINE_SPIN_UNLOCK=y
CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
CONFIG_MUTEX_SPIN_ON_OWNER=y
CONFIG_RWSEM_SPIN_ON_OWNER=y
CONFIG_LOCK_SPIN_ON_OWNER=y
CONFIG_ARCH_USE_QUEUED_SPINLOCKS=y
CONFIG_QUEUED_SPINLOCKS=y
CONFIG_ARCH_USE_QUEUED_RWLOCKS=y
CONFIG_QUEUED_RWLOCKS=y
CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE=y
CONFIG_ARCH_HAS_SYNC_CORE_BEFORE_USERMODE=y
CONFIG_ARCH_HAS_SYSCALL_WRAPPER=y
CONFIG_FREEZER=y

#
# Executable file formats
#
CONFIG_BINFMT_ELF=y
CONFIG_ELFCORE=y
CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
CONFIG_BINFMT_SCRIPT=y
CONFIG_BINFMT_MISC=m
CONFIG_COREDUMP=y
# end of Executable file formats

#
# Memory Management options
#
CONFIG_ZPOOL=y
CONFIG_SWAP=y
CONFIG_ZSWAP=y
CONFIG_ZSWAP_DEFAULT_ON=y
# CONFIG_ZSWAP_COMPRESSOR_DEFAULT_DEFLATE is not set
CONFIG_ZSWAP_COMPRESSOR_DEFAULT_LZO=y
# CONFIG_ZSWAP_COMPRESSOR_DEFAULT_842 is not set
# CONFIG_ZSWAP_COMPRESSOR_DEFAULT_LZ4 is not set
# CONFIG_ZSWAP_COMPRESSOR_DEFAULT_LZ4HC is not set
# CONFIG_ZSWAP_COMPRESSOR_DEFAULT_ZSTD is not set
CONFIG_ZSWAP_COMPRESSOR_DEFAULT="lzo"
CONFIG_ZSWAP_ZPOOL_DEFAULT_ZBUD=y
# CONFIG_ZSWAP_ZPOOL_DEFAULT_Z3FOLD is not set
# CONFIG_ZSWAP_ZPOOL_DEFAULT_ZSMALLOC is not set
CONFIG_ZSWAP_ZPOOL_DEFAULT="zbud"
CONFIG_ZBUD=y
CONFIG_Z3FOLD=m
CONFIG_ZSMALLOC=m
CONFIG_ZSMALLOC_STAT=y

#
# SLAB allocator options
#
# CONFIG_SLAB is not set
CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_SLAB_MERGE_DEFAULT=y
CONFIG_SLAB_FREELIST_RANDOM=y
CONFIG_SLAB_FREELIST_HARDENED=y
CONFIG_SLUB_STATS=y
CONFIG_SLUB_CPU_PARTIAL=y
# end of SLAB allocator options

CONFIG_SHUFFLE_PAGE_ALLOCATOR=y
CONFIG_COMPAT_BRK=y
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_SPARSEMEM_STATIC=y
CONFIG_HAVE_FAST_GUP=y
CONFIG_MEMORY_ISOLATION=y
CONFIG_EXCLUSIVE_SYSTEM_RAM=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MEMORY_BALLOON=y
CONFIG_BALLOON_COMPACTION=y
CONFIG_COMPACTION=y
CONFIG_PAGE_REPORTING=y
CONFIG_MIGRATION=y
CONFIG_CONTIG_ALLOC=y
CONFIG_BOUNCE=y
CONFIG_MMU_NOTIFIER=y
CONFIG_KSM=y
CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
CONFIG_ARCH_SUPPORTS_MEMORY_FAILURE=y
CONFIG_MEMORY_FAILURE=y
CONFIG_HWPOISON_INJECT=m
CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
CONFIG_TRANSPARENT_HUGEPAGE=y
CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y
# CONFIG_TRANSPARENT_HUGEPAGE_MADVISE is not set
CONFIG_READ_ONLY_THP_FOR_FS=y
CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y
CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y
CONFIG_HAVE_SETUP_PER_CPU_AREA=y
CONFIG_FRONTSWAP=y
CONFIG_CMA=y
CONFIG_CMA_DEBUG=y
CONFIG_CMA_DEBUGFS=y
CONFIG_CMA_SYSFS=y
CONFIG_CMA_AREAS=7
CONFIG_GENERIC_EARLY_IOREMAP=y
CONFIG_PAGE_IDLE_FLAG=y
CONFIG_IDLE_PAGE_TRACKING=y
CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y
CONFIG_ARCH_HAS_CURRENT_STACK_POINTER=y
CONFIG_ARCH_HAS_ZONE_DMA_SET=y
CONFIG_ZONE_DMA=y
CONFIG_HMM_MIRROR=y
CONFIG_VMAP_PFN=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_PERCPU_STATS=y
# CONFIG_GUP_TEST is not set
CONFIG_ARCH_HAS_PTE_SPECIAL=y
CONFIG_MAPPING_DIRTY_HELPERS=y
CONFIG_KMAP_LOCAL=y
CONFIG_ANON_VMA_NAME=y
CONFIG_USERFAULTFD=y

#
# Data Access Monitoring
#
CONFIG_DAMON=y
CONFIG_DAMON_VADDR=y
CONFIG_DAMON_PADDR=y
CONFIG_DAMON_SYSFS=y
CONFIG_DAMON_DBGFS=y
CONFIG_DAMON_RECLAIM=y
CONFIG_DAMON_LRU_SORT=y
# end of Data Access Monitoring
# end of Memory Management options

CONFIG_NET=y
CONFIG_NET_INGRESS=y
CONFIG_NET_EGRESS=y
CONFIG_NET_REDIRECT=y
CONFIG_SKB_EXTENSIONS=y

#
# Networking options
#
CONFIG_PACKET=m
CONFIG_PACKET_DIAG=m
CONFIG_UNIX=y
CONFIG_UNIX_SCM=y
CONFIG_AF_UNIX_OOB=y
CONFIG_UNIX_DIAG=m
CONFIG_TLS=m
CONFIG_TLS_DEVICE=y
CONFIG_TLS_TOE=y
CONFIG_XFRM=y
CONFIG_XFRM_OFFLOAD=y
CONFIG_XFRM_ALGO=m
CONFIG_XFRM_USER=m
CONFIG_XFRM_INTERFACE=m
CONFIG_XFRM_SUB_POLICY=y
CONFIG_XFRM_MIGRATE=y
CONFIG_XFRM_STATISTICS=y
CONFIG_XFRM_AH=m
CONFIG_XFRM_ESP=m
CONFIG_XFRM_IPCOMP=m
CONFIG_NET_KEY=m
CONFIG_NET_KEY_MIGRATE=y
CONFIG_XFRM_ESPINTCP=y
CONFIG_SMC=m
CONFIG_SMC_DIAG=m
CONFIG_XDP_SOCKETS=y
CONFIG_XDP_SOCKETS_DIAG=m
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
CONFIG_IP_ADVANCED_ROUTER=y
CONFIG_IP_FIB_TRIE_STATS=y
CONFIG_IP_MULTIPLE_TABLES=y
CONFIG_IP_ROUTE_MULTIPATH=y
CONFIG_IP_ROUTE_VERBOSE=y
CONFIG_IP_ROUTE_CLASSID=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
CONFIG_IP_PNP_BOOTP=y
CONFIG_IP_PNP_RARP=y
CONFIG_NET_IPIP=m
CONFIG_NET_IPGRE_DEMUX=m
CONFIG_NET_IP_TUNNEL=m
CONFIG_NET_IPGRE=m
CONFIG_NET_IPGRE_BROADCAST=y
CONFIG_IP_MROUTE_COMMON=y
CONFIG_IP_MROUTE=y
CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
CONFIG_IP_PIMSM_V1=y
CONFIG_IP_PIMSM_V2=y
CONFIG_SYN_COOKIES=y
CONFIG_NET_IPVTI=m
CONFIG_NET_UDP_TUNNEL=m
CONFIG_NET_FOU=m
CONFIG_NET_FOU_IP_TUNNELS=y
CONFIG_INET_AH=m
CONFIG_INET_ESP=m
CONFIG_INET_ESP_OFFLOAD=m
CONFIG_INET_ESPINTCP=y
CONFIG_INET_IPCOMP=m
CONFIG_INET_XFRM_TUNNEL=m
CONFIG_INET_TUNNEL=m
CONFIG_INET_DIAG=m
CONFIG_INET_TCP_DIAG=m
CONFIG_INET_UDP_DIAG=m
CONFIG_INET_RAW_DIAG=m
CONFIG_INET_DIAG_DESTROY=y
CONFIG_TCP_CONG_ADVANCED=y
CONFIG_TCP_CONG_BIC=m
CONFIG_TCP_CONG_CUBIC=m
CONFIG_TCP_CONG_WESTWOOD=m
CONFIG_TCP_CONG_HTCP=m
CONFIG_TCP_CONG_HSTCP=m
CONFIG_TCP_CONG_HYBLA=m
CONFIG_TCP_CONG_VEGAS=m
CONFIG_TCP_CONG_NV=m
CONFIG_TCP_CONG_SCALABLE=m
CONFIG_TCP_CONG_LP=m
CONFIG_TCP_CONG_VENO=m
CONFIG_TCP_CONG_YEAH=m
CONFIG_TCP_CONG_ILLINOIS=m
CONFIG_TCP_CONG_DCTCP=m
CONFIG_TCP_CONG_CDG=m
CONFIG_TCP_CONG_BBR=m
CONFIG_DEFAULT_RENO=y
CONFIG_DEFAULT_TCP_CONG="reno"
CONFIG_TCP_MD5SIG=y
CONFIG_IPV6=m
CONFIG_IPV6_ROUTER_PREF=y
CONFIG_IPV6_ROUTE_INFO=y
CONFIG_IPV6_OPTIMISTIC_DAD=y
CONFIG_INET6_AH=m
CONFIG_INET6_ESP=m
CONFIG_INET6_ESP_OFFLOAD=m
CONFIG_INET6_ESPINTCP=y
CONFIG_INET6_IPCOMP=m
CONFIG_IPV6_MIP6=m
CONFIG_IPV6_ILA=m
CONFIG_INET6_XFRM_TUNNEL=m
CONFIG_INET6_TUNNEL=m
CONFIG_IPV6_VTI=m
CONFIG_IPV6_SIT=m
CONFIG_IPV6_SIT_6RD=y
CONFIG_IPV6_NDISC_NODETYPE=y
CONFIG_IPV6_TUNNEL=m
CONFIG_IPV6_GRE=m
CONFIG_IPV6_FOU=m
CONFIG_IPV6_FOU_TUNNEL=m
CONFIG_IPV6_MULTIPLE_TABLES=y
CONFIG_IPV6_SUBTREES=y
CONFIG_IPV6_MROUTE=y
CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
CONFIG_IPV6_PIMSM_V2=y
CONFIG_IPV6_SEG6_LWTUNNEL=y
CONFIG_IPV6_SEG6_HMAC=y
CONFIG_IPV6_RPL_LWTUNNEL=y
CONFIG_IPV6_IOAM6_LWTUNNEL=y
CONFIG_NETLABEL=y
CONFIG_MPTCP=y
CONFIG_INET_MPTCP_DIAG=m
CONFIG_NETWORK_SECMARK=y
CONFIG_NET_PTP_CLASSIFY=y
CONFIG_NETWORK_PHY_TIMESTAMPING=y
CONFIG_NETFILTER=y
CONFIG_NETFILTER_ADVANCED=y
CONFIG_BRIDGE_NETFILTER=m

#
# Core Netfilter Configuration
#
CONFIG_NETFILTER_INGRESS=y
CONFIG_NETFILTER_EGRESS=y
CONFIG_NETFILTER_SKIP_EGRESS=y
CONFIG_NETFILTER_NETLINK=m
CONFIG_NETFILTER_FAMILY_BRIDGE=y
CONFIG_NETFILTER_FAMILY_ARP=y
CONFIG_NETFILTER_NETLINK_HOOK=m
CONFIG_NETFILTER_NETLINK_ACCT=m
CONFIG_NETFILTER_NETLINK_QUEUE=m
CONFIG_NETFILTER_NETLINK_LOG=m
CONFIG_NETFILTER_NETLINK_OSF=m
CONFIG_NF_CONNTRACK=m
CONFIG_NF_LOG_SYSLOG=m
CONFIG_NETFILTER_CONNCOUNT=m
CONFIG_NF_CONNTRACK_MARK=y
CONFIG_NF_CONNTRACK_SECMARK=y
CONFIG_NF_CONNTRACK_ZONES=y
CONFIG_NF_CONNTRACK_PROCFS=y
CONFIG_NF_CONNTRACK_EVENTS=y
CONFIG_NF_CONNTRACK_TIMEOUT=y
CONFIG_NF_CONNTRACK_TIMESTAMP=y
CONFIG_NF_CONNTRACK_LABELS=y
CONFIG_NF_CT_PROTO_DCCP=y
CONFIG_NF_CT_PROTO_GRE=y
CONFIG_NF_CT_PROTO_SCTP=y
CONFIG_NF_CT_PROTO_UDPLITE=y
CONFIG_NF_CONNTRACK_AMANDA=m
CONFIG_NF_CONNTRACK_FTP=m
CONFIG_NF_CONNTRACK_H323=m
CONFIG_NF_CONNTRACK_IRC=m
CONFIG_NF_CONNTRACK_BROADCAST=m
CONFIG_NF_CONNTRACK_NETBIOS_NS=m
CONFIG_NF_CONNTRACK_SNMP=m
CONFIG_NF_CONNTRACK_PPTP=m
CONFIG_NF_CONNTRACK_SANE=m
CONFIG_NF_CONNTRACK_SIP=m
CONFIG_NF_CONNTRACK_TFTP=m
CONFIG_NF_CT_NETLINK=m
CONFIG_NF_CT_NETLINK_TIMEOUT=m
CONFIG_NF_CT_NETLINK_HELPER=m
CONFIG_NETFILTER_NETLINK_GLUE_CT=y
CONFIG_NF_NAT=m
CONFIG_NF_NAT_AMANDA=m
CONFIG_NF_NAT_FTP=m
CONFIG_NF_NAT_IRC=m
CONFIG_NF_NAT_SIP=m
CONFIG_NF_NAT_TFTP=m
CONFIG_NF_NAT_REDIRECT=y
CONFIG_NF_NAT_MASQUERADE=y
CONFIG_NETFILTER_SYNPROXY=m
CONFIG_NF_TABLES=m
CONFIG_NF_TABLES_INET=y
CONFIG_NF_TABLES_NETDEV=y
CONFIG_NFT_NUMGEN=m
CONFIG_NFT_CT=m
CONFIG_NFT_FLOW_OFFLOAD=m
CONFIG_NFT_CONNLIMIT=m
CONFIG_NFT_LOG=m
CONFIG_NFT_LIMIT=m
CONFIG_NFT_MASQ=m
CONFIG_NFT_REDIR=m
CONFIG_NFT_NAT=m
CONFIG_NFT_TUNNEL=m
CONFIG_NFT_OBJREF=m
CONFIG_NFT_QUEUE=m
CONFIG_NFT_QUOTA=m
CONFIG_NFT_REJECT=m
CONFIG_NFT_REJECT_INET=m
CONFIG_NFT_COMPAT=m
CONFIG_NFT_HASH=m
CONFIG_NFT_FIB=m
CONFIG_NFT_FIB_INET=m
CONFIG_NFT_XFRM=m
CONFIG_NFT_SOCKET=m
CONFIG_NFT_OSF=m
CONFIG_NFT_TPROXY=m
CONFIG_NFT_SYNPROXY=m
CONFIG_NF_DUP_NETDEV=m
CONFIG_NFT_DUP_NETDEV=m
CONFIG_NFT_FWD_NETDEV=m
CONFIG_NFT_FIB_NETDEV=m
CONFIG_NFT_REJECT_NETDEV=m
CONFIG_NF_FLOW_TABLE_INET=m
CONFIG_NF_FLOW_TABLE=m
CONFIG_NF_FLOW_TABLE_PROCFS=y
CONFIG_NETFILTER_XTABLES=m

#
# Xtables combined modules
#
CONFIG_NETFILTER_XT_MARK=m
CONFIG_NETFILTER_XT_CONNMARK=m
CONFIG_NETFILTER_XT_SET=m

#
# Xtables targets
#
CONFIG_NETFILTER_XT_TARGET_AUDIT=m
CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
CONFIG_NETFILTER_XT_TARGET_CT=m
CONFIG_NETFILTER_XT_TARGET_DSCP=m
CONFIG_NETFILTER_XT_TARGET_HL=m
CONFIG_NETFILTER_XT_TARGET_HMARK=m
CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m
CONFIG_NETFILTER_XT_TARGET_LED=m
CONFIG_NETFILTER_XT_TARGET_LOG=m
CONFIG_NETFILTER_XT_TARGET_MARK=m
CONFIG_NETFILTER_XT_NAT=m
CONFIG_NETFILTER_XT_TARGET_NETMAP=m
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
CONFIG_NETFILTER_XT_TARGET_RATEEST=m
CONFIG_NETFILTER_XT_TARGET_REDIRECT=m
CONFIG_NETFILTER_XT_TARGET_MASQUERADE=m
CONFIG_NETFILTER_XT_TARGET_TEE=m
CONFIG_NETFILTER_XT_TARGET_TPROXY=m
CONFIG_NETFILTER_XT_TARGET_TRACE=m
CONFIG_NETFILTER_XT_TARGET_SECMARK=m
CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m

#
# Xtables matches
#
CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
CONFIG_NETFILTER_XT_MATCH_BPF=m
CONFIG_NETFILTER_XT_MATCH_CGROUP=m
CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
CONFIG_NETFILTER_XT_MATCH_CPU=m
CONFIG_NETFILTER_XT_MATCH_DCCP=m
CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m
CONFIG_NETFILTER_XT_MATCH_DSCP=m
CONFIG_NETFILTER_XT_MATCH_ECN=m
CONFIG_NETFILTER_XT_MATCH_ESP=m
CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
CONFIG_NETFILTER_XT_MATCH_HELPER=m
CONFIG_NETFILTER_XT_MATCH_HL=m
CONFIG_NETFILTER_XT_MATCH_IPCOMP=m
CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
CONFIG_NETFILTER_XT_MATCH_IPVS=m
CONFIG_NETFILTER_XT_MATCH_L2TP=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
CONFIG_NETFILTER_XT_MATCH_MAC=m
CONFIG_NETFILTER_XT_MATCH_MARK=m
CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_NFACCT=m
CONFIG_NETFILTER_XT_MATCH_OSF=m
CONFIG_NETFILTER_XT_MATCH_OWNER=m
CONFIG_NETFILTER_XT_MATCH_POLICY=m
CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_QUOTA=m
CONFIG_NETFILTER_XT_MATCH_RATEEST=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
CONFIG_NETFILTER_XT_MATCH_RECENT=m
CONFIG_NETFILTER_XT_MATCH_SCTP=m
CONFIG_NETFILTER_XT_MATCH_SOCKET=m
CONFIG_NETFILTER_XT_MATCH_STATE=m
CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
CONFIG_NETFILTER_XT_MATCH_STRING=m
CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
CONFIG_NETFILTER_XT_MATCH_TIME=m
CONFIG_NETFILTER_XT_MATCH_U32=m
# end of Core Netfilter Configuration

CONFIG_IP_SET=m
CONFIG_IP_SET_MAX=256
CONFIG_IP_SET_BITMAP_IP=m
CONFIG_IP_SET_BITMAP_IPMAC=m
CONFIG_IP_SET_BITMAP_PORT=m
CONFIG_IP_SET_HASH_IP=m
CONFIG_IP_SET_HASH_IPMARK=m
CONFIG_IP_SET_HASH_IPPORT=m
CONFIG_IP_SET_HASH_IPPORTIP=m
CONFIG_IP_SET_HASH_IPPORTNET=m
CONFIG_IP_SET_HASH_IPMAC=m
CONFIG_IP_SET_HASH_MAC=m
CONFIG_IP_SET_HASH_NETPORTNET=m
CONFIG_IP_SET_HASH_NET=m
CONFIG_IP_SET_HASH_NETNET=m
CONFIG_IP_SET_HASH_NETPORT=m
CONFIG_IP_SET_HASH_NETIFACE=m
CONFIG_IP_SET_LIST_SET=m
CONFIG_IP_VS=m
CONFIG_IP_VS_IPV6=y
CONFIG_IP_VS_DEBUG=y
CONFIG_IP_VS_TAB_BITS=12

#
# IPVS transport protocol load balancing support
#
CONFIG_IP_VS_PROTO_TCP=y
CONFIG_IP_VS_PROTO_UDP=y
CONFIG_IP_VS_PROTO_AH_ESP=y
CONFIG_IP_VS_PROTO_ESP=y
CONFIG_IP_VS_PROTO_AH=y
CONFIG_IP_VS_PROTO_SCTP=y

#
# IPVS scheduler
#
CONFIG_IP_VS_RR=m
CONFIG_IP_VS_WRR=m
CONFIG_IP_VS_LC=m
CONFIG_IP_VS_WLC=m
CONFIG_IP_VS_FO=m
CONFIG_IP_VS_OVF=m
CONFIG_IP_VS_LBLC=m
CONFIG_IP_VS_LBLCR=m
CONFIG_IP_VS_DH=m
CONFIG_IP_VS_SH=m
CONFIG_IP_VS_MH=m
CONFIG_IP_VS_SED=m
CONFIG_IP_VS_NQ=m
CONFIG_IP_VS_TWOS=m

#
# IPVS SH scheduler
#
CONFIG_IP_VS_SH_TAB_BITS=8

#
# IPVS MH scheduler
#
CONFIG_IP_VS_MH_TAB_INDEX=12

#
# IPVS application helper
#
CONFIG_IP_VS_FTP=m
CONFIG_IP_VS_NFCT=y
CONFIG_IP_VS_PE_SIP=m

#
# IP: Netfilter Configuration
#
CONFIG_NF_DEFRAG_IPV4=m
CONFIG_NF_SOCKET_IPV4=m
CONFIG_NF_TPROXY_IPV4=m
CONFIG_NF_TABLES_IPV4=y
CONFIG_NFT_REJECT_IPV4=m
CONFIG_NFT_DUP_IPV4=m
CONFIG_NFT_FIB_IPV4=m
CONFIG_NF_TABLES_ARP=y
CONFIG_NF_DUP_IPV4=m
CONFIG_NF_LOG_ARP=m
CONFIG_NF_LOG_IPV4=m
CONFIG_NF_REJECT_IPV4=m
CONFIG_NF_NAT_SNMP_BASIC=m
CONFIG_NF_NAT_PPTP=m
CONFIG_NF_NAT_H323=m
CONFIG_IP_NF_IPTABLES=m
CONFIG_IP_NF_MATCH_AH=m
CONFIG_IP_NF_MATCH_ECN=m
CONFIG_IP_NF_MATCH_RPFILTER=m
CONFIG_IP_NF_MATCH_TTL=m
CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IP_NF_TARGET_SYNPROXY=m
CONFIG_IP_NF_NAT=m
CONFIG_IP_NF_TARGET_MASQUERADE=m
CONFIG_IP_NF_TARGET_NETMAP=m
CONFIG_IP_NF_TARGET_REDIRECT=m
CONFIG_IP_NF_MANGLE=m
CONFIG_IP_NF_TARGET_CLUSTERIP=m
CONFIG_IP_NF_TARGET_ECN=m
CONFIG_IP_NF_TARGET_TTL=m
CONFIG_IP_NF_RAW=m
CONFIG_IP_NF_SECURITY=m
CONFIG_IP_NF_ARPTABLES=m
CONFIG_IP_NF_ARPFILTER=m
CONFIG_IP_NF_ARP_MANGLE=m
# end of IP: Netfilter Configuration

#
# IPv6: Netfilter Configuration
#
CONFIG_NF_SOCKET_IPV6=m
CONFIG_NF_TPROXY_IPV6=m
CONFIG_NF_TABLES_IPV6=y
CONFIG_NFT_REJECT_IPV6=m
CONFIG_NFT_DUP_IPV6=m
CONFIG_NFT_FIB_IPV6=m
CONFIG_NF_DUP_IPV6=m
CONFIG_NF_REJECT_IPV6=m
CONFIG_NF_LOG_IPV6=m
CONFIG_IP6_NF_IPTABLES=m
CONFIG_IP6_NF_MATCH_AH=m
CONFIG_IP6_NF_MATCH_EUI64=m
CONFIG_IP6_NF_MATCH_FRAG=m
CONFIG_IP6_NF_MATCH_OPTS=m
CONFIG_IP6_NF_MATCH_HL=m
CONFIG_IP6_NF_MATCH_IPV6HEADER=m
CONFIG_IP6_NF_MATCH_MH=m
CONFIG_IP6_NF_MATCH_RPFILTER=m
CONFIG_IP6_NF_MATCH_RT=m
CONFIG_IP6_NF_MATCH_SRH=m
CONFIG_IP6_NF_TARGET_HL=m
CONFIG_IP6_NF_FILTER=m
CONFIG_IP6_NF_TARGET_REJECT=m
CONFIG_IP6_NF_TARGET_SYNPROXY=m
CONFIG_IP6_NF_MANGLE=m
CONFIG_IP6_NF_RAW=m
CONFIG_IP6_NF_SECURITY=m
CONFIG_IP6_NF_NAT=m
CONFIG_IP6_NF_TARGET_MASQUERADE=m
CONFIG_IP6_NF_TARGET_NPT=m
# end of IPv6: Netfilter Configuration

CONFIG_NF_DEFRAG_IPV6=m
CONFIG_NF_TABLES_BRIDGE=m
CONFIG_NFT_BRIDGE_META=m
CONFIG_NFT_BRIDGE_REJECT=m
CONFIG_NF_CONNTRACK_BRIDGE=m
CONFIG_BRIDGE_NF_EBTABLES=m
CONFIG_BRIDGE_EBT_BROUTE=m
CONFIG_BRIDGE_EBT_T_FILTER=m
CONFIG_BRIDGE_EBT_T_NAT=m
CONFIG_BRIDGE_EBT_802_3=m
CONFIG_BRIDGE_EBT_AMONG=m
CONFIG_BRIDGE_EBT_ARP=m
CONFIG_BRIDGE_EBT_IP=m
CONFIG_BRIDGE_EBT_IP6=m
CONFIG_BRIDGE_EBT_LIMIT=m
CONFIG_BRIDGE_EBT_MARK=m
CONFIG_BRIDGE_EBT_PKTTYPE=m
CONFIG_BRIDGE_EBT_STP=m
CONFIG_BRIDGE_EBT_VLAN=m
CONFIG_BRIDGE_EBT_ARPREPLY=m
CONFIG_BRIDGE_EBT_DNAT=m
CONFIG_BRIDGE_EBT_MARK_T=m
CONFIG_BRIDGE_EBT_REDIRECT=m
CONFIG_BRIDGE_EBT_SNAT=m
CONFIG_BRIDGE_EBT_LOG=m
CONFIG_BRIDGE_EBT_NFLOG=m
CONFIG_BPFILTER=y
CONFIG_BPFILTER_UMH=m
CONFIG_IP_DCCP=m
CONFIG_INET_DCCP_DIAG=m

#
# DCCP CCIDs Configuration
#
CONFIG_IP_DCCP_CCID2_DEBUG=y
CONFIG_IP_DCCP_CCID3=y
CONFIG_IP_DCCP_CCID3_DEBUG=y
CONFIG_IP_DCCP_TFRC_LIB=y
CONFIG_IP_DCCP_TFRC_DEBUG=y
# end of DCCP CCIDs Configuration

#
# DCCP Kernel Hacking
#
CONFIG_IP_DCCP_DEBUG=y
# end of DCCP Kernel Hacking

CONFIG_IP_SCTP=m
CONFIG_SCTP_DBG_OBJCNT=y
CONFIG_SCTP_DEFAULT_COOKIE_HMAC_MD5=y
# CONFIG_SCTP_DEFAULT_COOKIE_HMAC_SHA1 is not set
# CONFIG_SCTP_DEFAULT_COOKIE_HMAC_NONE is not set
CONFIG_SCTP_COOKIE_HMAC_MD5=y
CONFIG_SCTP_COOKIE_HMAC_SHA1=y
CONFIG_INET_SCTP_DIAG=m
# CONFIG_RDS is not set
CONFIG_TIPC=m
CONFIG_TIPC_MEDIA_IB=y
CONFIG_TIPC_MEDIA_UDP=y
CONFIG_TIPC_CRYPTO=y
CONFIG_TIPC_DIAG=m
CONFIG_ATM=m
CONFIG_ATM_CLIP=m
CONFIG_ATM_CLIP_NO_ICMP=y
CONFIG_ATM_LANE=m
CONFIG_ATM_MPOA=m
CONFIG_ATM_BR2684=m
CONFIG_ATM_BR2684_IPFILTER=y
CONFIG_L2TP=m
CONFIG_L2TP_DEBUGFS=m
CONFIG_L2TP_V3=y
CONFIG_L2TP_IP=m
CONFIG_L2TP_ETH=m
CONFIG_STP=m
CONFIG_GARP=m
CONFIG_MRP=m
CONFIG_BRIDGE=m
CONFIG_BRIDGE_IGMP_SNOOPING=y
CONFIG_BRIDGE_VLAN_FILTERING=y
CONFIG_BRIDGE_MRP=y
CONFIG_BRIDGE_CFM=y
CONFIG_NET_DSA=m
CONFIG_NET_DSA_TAG_AR9331=m
CONFIG_NET_DSA_TAG_BRCM_COMMON=m
CONFIG_NET_DSA_TAG_BRCM=m
CONFIG_NET_DSA_TAG_BRCM_LEGACY=m
CONFIG_NET_DSA_TAG_BRCM_PREPEND=m
CONFIG_NET_DSA_TAG_HELLCREEK=m
CONFIG_NET_DSA_TAG_GSWIP=m
CONFIG_NET_DSA_TAG_DSA_COMMON=m
CONFIG_NET_DSA_TAG_DSA=m
CONFIG_NET_DSA_TAG_EDSA=m
CONFIG_NET_DSA_TAG_MTK=m
CONFIG_NET_DSA_TAG_KSZ=m
CONFIG_NET_DSA_TAG_OCELOT=m
CONFIG_NET_DSA_TAG_OCELOT_8021Q=m
CONFIG_NET_DSA_TAG_QCA=m
CONFIG_NET_DSA_TAG_RTL4_A=m
CONFIG_NET_DSA_TAG_RTL8_4=m
CONFIG_NET_DSA_TAG_RZN1_A5PSW=m
CONFIG_NET_DSA_TAG_LAN9303=m
CONFIG_NET_DSA_TAG_SJA1105=m
CONFIG_NET_DSA_TAG_TRAILER=m
CONFIG_NET_DSA_TAG_XRS700X=m
CONFIG_VLAN_8021Q=m
CONFIG_VLAN_8021Q_GVRP=y
CONFIG_VLAN_8021Q_MVRP=y
CONFIG_LLC=m
CONFIG_LLC2=m
CONFIG_ATALK=m
CONFIG_DEV_APPLETALK=m
# CONFIG_COPS is not set
CONFIG_IPDDP=m
CONFIG_IPDDP_ENCAP=y
CONFIG_X25=m
CONFIG_LAPB=m
CONFIG_PHONET=m
CONFIG_6LOWPAN=m
CONFIG_6LOWPAN_DEBUGFS=y
CONFIG_6LOWPAN_NHC=m
CONFIG_6LOWPAN_NHC_DEST=m
CONFIG_6LOWPAN_NHC_FRAGMENT=m
CONFIG_6LOWPAN_NHC_HOP=m
CONFIG_6LOWPAN_NHC_IPV6=m
CONFIG_6LOWPAN_NHC_MOBILITY=m
CONFIG_6LOWPAN_NHC_ROUTING=m
CONFIG_6LOWPAN_NHC_UDP=m
CONFIG_6LOWPAN_GHC_EXT_HDR_HOP=m
CONFIG_6LOWPAN_GHC_UDP=m
CONFIG_6LOWPAN_GHC_ICMPV6=m
CONFIG_6LOWPAN_GHC_EXT_HDR_DEST=m
CONFIG_6LOWPAN_GHC_EXT_HDR_FRAG=m
CONFIG_6LOWPAN_GHC_EXT_HDR_ROUTE=m
CONFIG_IEEE802154=m
CONFIG_IEEE802154_NL802154_EXPERIMENTAL=y
CONFIG_IEEE802154_SOCKET=m
CONFIG_IEEE802154_6LOWPAN=m
CONFIG_MAC802154=m
CONFIG_NET_SCHED=y

#
# Queueing/Scheduling
#
CONFIG_NET_SCH_CBQ=m
CONFIG_NET_SCH_HTB=m
CONFIG_NET_SCH_HFSC=m
CONFIG_NET_SCH_ATM=m
CONFIG_NET_SCH_PRIO=m
CONFIG_NET_SCH_MULTIQ=m
CONFIG_NET_SCH_RED=m
CONFIG_NET_SCH_SFB=m
CONFIG_NET_SCH_SFQ=m
CONFIG_NET_SCH_TEQL=m
CONFIG_NET_SCH_TBF=m
CONFIG_NET_SCH_CBS=m
CONFIG_NET_SCH_ETF=m
CONFIG_NET_SCH_TAPRIO=m
CONFIG_NET_SCH_GRED=m
CONFIG_NET_SCH_DSMARK=m
CONFIG_NET_SCH_NETEM=m
CONFIG_NET_SCH_DRR=m
CONFIG_NET_SCH_MQPRIO=m
CONFIG_NET_SCH_SKBPRIO=m
CONFIG_NET_SCH_CHOKE=m
CONFIG_NET_SCH_QFQ=m
CONFIG_NET_SCH_CODEL=m
CONFIG_NET_SCH_FQ_CODEL=m
CONFIG_NET_SCH_CAKE=m
CONFIG_NET_SCH_FQ=m
CONFIG_NET_SCH_HHF=m
CONFIG_NET_SCH_PIE=m
CONFIG_NET_SCH_FQ_PIE=m
CONFIG_NET_SCH_INGRESS=m
CONFIG_NET_SCH_PLUG=m
CONFIG_NET_SCH_ETS=m
CONFIG_NET_SCH_DEFAULT=y
# CONFIG_DEFAULT_FQ is not set
# CONFIG_DEFAULT_CODEL is not set
# CONFIG_DEFAULT_FQ_CODEL is not set
# CONFIG_DEFAULT_FQ_PIE is not set
# CONFIG_DEFAULT_SFQ is not set
CONFIG_DEFAULT_PFIFO_FAST=y
CONFIG_DEFAULT_NET_SCH="pfifo_fast"

#
# Classification
#
CONFIG_NET_CLS=y
CONFIG_NET_CLS_BASIC=m
CONFIG_NET_CLS_TCINDEX=m
CONFIG_NET_CLS_ROUTE4=m
CONFIG_NET_CLS_FW=m
CONFIG_NET_CLS_U32=m
CONFIG_CLS_U32_PERF=y
CONFIG_CLS_U32_MARK=y
CONFIG_NET_CLS_RSVP=m
CONFIG_NET_CLS_RSVP6=m
CONFIG_NET_CLS_FLOW=m
CONFIG_NET_CLS_CGROUP=m
CONFIG_NET_CLS_BPF=m
CONFIG_NET_CLS_FLOWER=m
CONFIG_NET_CLS_MATCHALL=m
CONFIG_NET_EMATCH=y
CONFIG_NET_EMATCH_STACK=32
CONFIG_NET_EMATCH_CMP=m
CONFIG_NET_EMATCH_NBYTE=m
CONFIG_NET_EMATCH_U32=m
CONFIG_NET_EMATCH_META=m
CONFIG_NET_EMATCH_TEXT=m
CONFIG_NET_EMATCH_CANID=m
CONFIG_NET_EMATCH_IPSET=m
CONFIG_NET_EMATCH_IPT=m
CONFIG_NET_CLS_ACT=y
CONFIG_NET_ACT_POLICE=m
CONFIG_NET_ACT_GACT=m
CONFIG_GACT_PROB=y
CONFIG_NET_ACT_MIRRED=m
CONFIG_NET_ACT_SAMPLE=m
CONFIG_NET_ACT_IPT=m
CONFIG_NET_ACT_NAT=m
CONFIG_NET_ACT_PEDIT=m
CONFIG_NET_ACT_SIMP=m
CONFIG_NET_ACT_SKBEDIT=m
CONFIG_NET_ACT_CSUM=m
CONFIG_NET_ACT_MPLS=m
CONFIG_NET_ACT_VLAN=m
CONFIG_NET_ACT_BPF=m
CONFIG_NET_ACT_CONNMARK=m
CONFIG_NET_ACT_CTINFO=m
CONFIG_NET_ACT_SKBMOD=m
CONFIG_NET_ACT_IFE=m
CONFIG_NET_ACT_TUNNEL_KEY=m
CONFIG_NET_ACT_CT=m
CONFIG_NET_ACT_GATE=m
CONFIG_NET_IFE_SKBMARK=m
CONFIG_NET_IFE_SKBPRIO=m
CONFIG_NET_IFE_SKBTCINDEX=m
CONFIG_NET_TC_SKB_EXT=y
CONFIG_NET_SCH_FIFO=y
CONFIG_DCB=y
CONFIG_DNS_RESOLVER=m
CONFIG_BATMAN_ADV=m
CONFIG_BATMAN_ADV_BATMAN_V=y
CONFIG_BATMAN_ADV_BLA=y
CONFIG_BATMAN_ADV_DAT=y
CONFIG_BATMAN_ADV_NC=y
CONFIG_BATMAN_ADV_MCAST=y
CONFIG_BATMAN_ADV_DEBUG=y
CONFIG_BATMAN_ADV_TRACING=y
CONFIG_OPENVSWITCH=m
CONFIG_OPENVSWITCH_GRE=m
CONFIG_OPENVSWITCH_VXLAN=m
CONFIG_OPENVSWITCH_GENEVE=m
CONFIG_VSOCKETS=m
CONFIG_VSOCKETS_DIAG=m
CONFIG_VSOCKETS_LOOPBACK=m
CONFIG_VMWARE_VMCI_VSOCKETS=m
CONFIG_VIRTIO_VSOCKETS=m
CONFIG_VIRTIO_VSOCKETS_COMMON=m
CONFIG_HYPERV_VSOCKETS=m
CONFIG_NETLINK_DIAG=m
CONFIG_MPLS=y
CONFIG_NET_MPLS_GSO=m
CONFIG_MPLS_ROUTING=m
CONFIG_MPLS_IPTUNNEL=m
CONFIG_NET_NSH=m
CONFIG_HSR=m
CONFIG_NET_SWITCHDEV=y
CONFIG_NET_L3_MASTER_DEV=y
CONFIG_QRTR=m
CONFIG_QRTR_SMD=m
CONFIG_QRTR_TUN=m
CONFIG_QRTR_MHI=m
CONFIG_NET_NCSI=y
CONFIG_NCSI_OEM_CMD_GET_MAC=y
CONFIG_NCSI_OEM_CMD_KEEP_PHY=y
CONFIG_PCPU_DEV_REFCNT=y
CONFIG_RPS=y
CONFIG_RFS_ACCEL=y
CONFIG_SOCK_RX_QUEUE_MAPPING=y
CONFIG_XPS=y
CONFIG_CGROUP_NET_PRIO=y
CONFIG_CGROUP_NET_CLASSID=y
CONFIG_NET_RX_BUSY_POLL=y
CONFIG_BQL=y
CONFIG_NET_FLOW_LIMIT=y

#
# Network testing
#
CONFIG_NET_PKTGEN=m
CONFIG_NET_DROP_MONITOR=m
# end of Network testing
# end of Networking options

CONFIG_HAMRADIO=y

#
# Packet Radio protocols
#
CONFIG_AX25=m
CONFIG_AX25_DAMA_SLAVE=y
CONFIG_NETROM=m
CONFIG_ROSE=m

#
# AX.25 network device drivers
#
CONFIG_MKISS=m
CONFIG_6PACK=m
CONFIG_BPQETHER=m
CONFIG_SCC=m
CONFIG_SCC_DELAY=y
CONFIG_SCC_TRXECHO=y
CONFIG_BAYCOM_SER_FDX=m
CONFIG_BAYCOM_SER_HDX=m
CONFIG_BAYCOM_PAR=m
CONFIG_BAYCOM_EPP=m
CONFIG_YAM=m
# end of AX.25 network device drivers

CONFIG_CAN=m
CONFIG_CAN_RAW=m
CONFIG_CAN_BCM=m
CONFIG_CAN_GW=m
CONFIG_CAN_J1939=m
CONFIG_CAN_ISOTP=m
CONFIG_BT=m
CONFIG_BT_BREDR=y
CONFIG_BT_RFCOMM=m
CONFIG_BT_RFCOMM_TTY=y
CONFIG_BT_BNEP=m
CONFIG_BT_BNEP_MC_FILTER=y
CONFIG_BT_BNEP_PROTO_FILTER=y
CONFIG_BT_CMTP=m
CONFIG_BT_HIDP=m
CONFIG_BT_HS=y
CONFIG_BT_LE=y
CONFIG_BT_6LOWPAN=m
CONFIG_BT_LEDS=y
CONFIG_BT_MSFTEXT=y
CONFIG_BT_AOSPEXT=y
CONFIG_BT_DEBUGFS=y
# CONFIG_BT_SELFTEST is not set

#
# Bluetooth device drivers
#
CONFIG_BT_INTEL=m
CONFIG_BT_BCM=m
CONFIG_BT_RTL=m
CONFIG_BT_QCA=m
CONFIG_BT_MTK=m
CONFIG_BT_HCIBTUSB=m
CONFIG_BT_HCIBTUSB_AUTOSUSPEND=y
CONFIG_BT_HCIBTUSB_BCM=y
CONFIG_BT_HCIBTUSB_MTK=y
CONFIG_BT_HCIBTUSB_RTL=y
CONFIG_BT_HCIBTSDIO=m
CONFIG_BT_HCIUART=m
CONFIG_BT_HCIUART_SERDEV=y
CONFIG_BT_HCIUART_H4=y
CONFIG_BT_HCIUART_NOKIA=m
CONFIG_BT_HCIUART_BCSP=y
CONFIG_BT_HCIUART_ATH3K=y
CONFIG_BT_HCIUART_LL=y
CONFIG_BT_HCIUART_3WIRE=y
CONFIG_BT_HCIUART_INTEL=y
CONFIG_BT_HCIUART_RTL=y
CONFIG_BT_HCIUART_QCA=y
CONFIG_BT_HCIUART_AG6XX=y
CONFIG_BT_HCIUART_MRVL=y
CONFIG_BT_HCIBCM203X=m
CONFIG_BT_HCIBPA10X=m
CONFIG_BT_HCIBFUSB=m
CONFIG_BT_HCIDTL1=m
CONFIG_BT_HCIBT3C=m
CONFIG_BT_HCIBLUECARD=m
CONFIG_BT_HCIVHCI=m
CONFIG_BT_MRVL=m
CONFIG_BT_MRVL_SDIO=m
CONFIG_BT_ATH3K=m
CONFIG_BT_MTKSDIO=m
CONFIG_BT_MTKUART=m
CONFIG_BT_HCIRSI=m
CONFIG_BT_VIRTIO=m
# end of Bluetooth device drivers

CONFIG_AF_RXRPC=m
CONFIG_AF_RXRPC_IPV6=y
CONFIG_AF_RXRPC_INJECT_LOSS=y
CONFIG_AF_RXRPC_DEBUG=y
CONFIG_RXKAD=y
CONFIG_AF_KCM=m
CONFIG_STREAM_PARSER=y
CONFIG_MCTP=y
CONFIG_MCTP_FLOWS=y
CONFIG_FIB_RULES=y
CONFIG_WIRELESS=y
CONFIG_WIRELESS_EXT=y
CONFIG_WEXT_CORE=y
CONFIG_WEXT_PROC=y
CONFIG_WEXT_SPY=y
CONFIG_WEXT_PRIV=y
CONFIG_CFG80211=m
CONFIG_NL80211_TESTMODE=y
CONFIG_CFG80211_DEVELOPER_WARNINGS=y
CONFIG_CFG80211_CERTIFICATION_ONUS=y
CONFIG_CFG80211_REQUIRE_SIGNED_REGDB=y
CONFIG_CFG80211_USE_KERNEL_REGDB_KEYS=y
CONFIG_CFG80211_EXTRA_REGDB_KEYDIR=""
CONFIG_CFG80211_REG_CELLULAR_HINTS=y
CONFIG_CFG80211_REG_RELAX_NO_IR=y
CONFIG_CFG80211_DEFAULT_PS=y
CONFIG_CFG80211_DEBUGFS=y
CONFIG_CFG80211_CRDA_SUPPORT=y
CONFIG_CFG80211_WEXT=y
CONFIG_CFG80211_WEXT_EXPORT=y
CONFIG_LIB80211=m
CONFIG_LIB80211_CRYPT_WEP=m
CONFIG_LIB80211_CRYPT_CCMP=m
CONFIG_LIB80211_CRYPT_TKIP=m
CONFIG_LIB80211_DEBUG=y
CONFIG_MAC80211=m
CONFIG_MAC80211_HAS_RC=y
CONFIG_MAC80211_RC_MINSTREL=y
CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y
CONFIG_MAC80211_RC_DEFAULT="minstrel_ht"
CONFIG_MAC80211_MESH=y
CONFIG_MAC80211_LEDS=y
CONFIG_MAC80211_DEBUGFS=y
CONFIG_MAC80211_MESSAGE_TRACING=y
CONFIG_MAC80211_DEBUG_MENU=y
CONFIG_MAC80211_NOINLINE=y
CONFIG_MAC80211_VERBOSE_DEBUG=y
CONFIG_MAC80211_MLME_DEBUG=y
CONFIG_MAC80211_STA_DEBUG=y
CONFIG_MAC80211_HT_DEBUG=y
CONFIG_MAC80211_OCB_DEBUG=y
CONFIG_MAC80211_IBSS_DEBUG=y
CONFIG_MAC80211_PS_DEBUG=y
CONFIG_MAC80211_MPL_DEBUG=y
CONFIG_MAC80211_MPATH_DEBUG=y
CONFIG_MAC80211_MHWMP_DEBUG=y
CONFIG_MAC80211_MESH_SYNC_DEBUG=y
CONFIG_MAC80211_MESH_CSA_DEBUG=y
CONFIG_MAC80211_MESH_PS_DEBUG=y
CONFIG_MAC80211_TDLS_DEBUG=y
CONFIG_MAC80211_DEBUG_COUNTERS=y
CONFIG_MAC80211_STA_HASH_MAX_SIZE=0
CONFIG_RFKILL=m
CONFIG_RFKILL_LEDS=y
CONFIG_RFKILL_INPUT=y
CONFIG_RFKILL_GPIO=m
CONFIG_NET_9P=y
CONFIG_NET_9P_FD=m
CONFIG_NET_9P_VIRTIO=y
CONFIG_NET_9P_RDMA=m
CONFIG_NET_9P_DEBUG=y
CONFIG_CAIF=m
CONFIG_CAIF_DEBUG=y
CONFIG_CAIF_NETDEV=m
CONFIG_CAIF_USB=m
CONFIG_CEPH_LIB=m
CONFIG_CEPH_LIB_PRETTYDEBUG=y
CONFIG_CEPH_LIB_USE_DNS_RESOLVER=y
CONFIG_NFC=m
CONFIG_NFC_DIGITAL=m
CONFIG_NFC_NCI=m
CONFIG_NFC_NCI_SPI=m
CONFIG_NFC_NCI_UART=m
CONFIG_NFC_HCI=m
CONFIG_NFC_SHDLC=y

#
# Near Field Communication (NFC) devices
#
CONFIG_NFC_TRF7970A=m
CONFIG_NFC_MEI_PHY=m
CONFIG_NFC_SIM=m
CONFIG_NFC_PORT100=m
CONFIG_NFC_VIRTUAL_NCI=m
CONFIG_NFC_FDP=m
CONFIG_NFC_FDP_I2C=m
CONFIG_NFC_PN544=m
CONFIG_NFC_PN544_I2C=m
CONFIG_NFC_PN544_MEI=m
CONFIG_NFC_PN533=m
CONFIG_NFC_PN533_USB=m
CONFIG_NFC_PN533_I2C=m
CONFIG_NFC_PN532_UART=m
CONFIG_NFC_MICROREAD=m
CONFIG_NFC_MICROREAD_I2C=m
CONFIG_NFC_MICROREAD_MEI=m
CONFIG_NFC_MRVL=m
CONFIG_NFC_MRVL_USB=m
CONFIG_NFC_MRVL_UART=m
CONFIG_NFC_MRVL_I2C=m
CONFIG_NFC_MRVL_SPI=m
CONFIG_NFC_ST21NFCA=m
CONFIG_NFC_ST21NFCA_I2C=m
CONFIG_NFC_ST_NCI=m
CONFIG_NFC_ST_NCI_I2C=m
CONFIG_NFC_ST_NCI_SPI=m
CONFIG_NFC_NXP_NCI=m
CONFIG_NFC_NXP_NCI_I2C=m
CONFIG_NFC_S3FWRN5=m
CONFIG_NFC_S3FWRN5_I2C=m
CONFIG_NFC_S3FWRN82_UART=m
CONFIG_NFC_ST95HF=m
# end of Near Field Communication (NFC) devices

CONFIG_PSAMPLE=m
CONFIG_NET_IFE=m
CONFIG_LWTUNNEL=y
CONFIG_LWTUNNEL_BPF=y
CONFIG_DST_CACHE=y
CONFIG_GRO_CELLS=y
CONFIG_SOCK_VALIDATE_XMIT=y
CONFIG_NET_SELFTESTS=m
CONFIG_NET_SOCK_MSG=y
CONFIG_NET_DEVLINK=y
CONFIG_PAGE_POOL=y
CONFIG_PAGE_POOL_STATS=y
CONFIG_FAILOVER=m
CONFIG_ETHTOOL_NETLINK=y

#
# Device Drivers
#
CONFIG_HAVE_EISA=y
CONFIG_EISA=y
CONFIG_EISA_VLB_PRIMING=y
CONFIG_EISA_PCI_EISA=y
CONFIG_EISA_VIRTUAL_ROOT=y
CONFIG_EISA_NAMES=y
CONFIG_HAVE_PCI=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
CONFIG_PCIEPORTBUS=y
CONFIG_HOTPLUG_PCI_PCIE=y
CONFIG_PCIEAER=y
CONFIG_PCIEAER_INJECT=m
CONFIG_PCIE_ECRC=y
CONFIG_PCIEASPM=y
CONFIG_PCIEASPM_DEFAULT=y
# CONFIG_PCIEASPM_POWERSAVE is not set
# CONFIG_PCIEASPM_POWER_SUPERSAVE is not set
# CONFIG_PCIEASPM_PERFORMANCE is not set
CONFIG_PCIE_PME=y
CONFIG_PCIE_DPC=y
CONFIG_PCIE_PTM=y
CONFIG_PCIE_EDR=y
CONFIG_PCI_MSI=y
CONFIG_PCI_MSI_IRQ_DOMAIN=y
CONFIG_PCI_QUIRKS=y
# CONFIG_PCI_DEBUG is not set
CONFIG_PCI_REALLOC_ENABLE_AUTO=y
CONFIG_PCI_STUB=m
CONFIG_PCI_PF_STUB=m
CONFIG_PCI_ATS=y
CONFIG_PCI_DOE=y
CONFIG_PCI_ECAM=y
CONFIG_PCI_LOCKLESS_CONFIG=y
CONFIG_PCI_IOV=y
CONFIG_PCI_PRI=y
CONFIG_PCI_PASID=y
CONFIG_PCI_LABEL=y
# CONFIG_PCIE_BUS_TUNE_OFF is not set
CONFIG_PCIE_BUS_DEFAULT=y
# CONFIG_PCIE_BUS_SAFE is not set
# CONFIG_PCIE_BUS_PERFORMANCE is not set
# CONFIG_PCIE_BUS_PEER2PEER is not set
CONFIG_VGA_ARB=y
CONFIG_VGA_ARB_MAX_GPUS=16
CONFIG_HOTPLUG_PCI=y
CONFIG_HOTPLUG_PCI_COMPAQ=m
CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM=y
CONFIG_HOTPLUG_PCI_IBM=m
CONFIG_HOTPLUG_PCI_ACPI=y
CONFIG_HOTPLUG_PCI_ACPI_IBM=m
CONFIG_HOTPLUG_PCI_CPCI=y
CONFIG_HOTPLUG_PCI_CPCI_ZT5550=m
CONFIG_HOTPLUG_PCI_CPCI_GENERIC=m
CONFIG_HOTPLUG_PCI_SHPC=y

#
# PCI controller drivers
#
CONFIG_PCI_FTPCI100=y
CONFIG_PCI_HOST_COMMON=y
CONFIG_PCI_HOST_GENERIC=m
CONFIG_PCIE_XILINX=y
CONFIG_PCIE_MICROCHIP_HOST=y

#
# DesignWare PCI Core Support
#
CONFIG_PCIE_DW=y
CONFIG_PCIE_DW_HOST=y
CONFIG_PCIE_DW_EP=y
CONFIG_PCIE_DW_PLAT=y
CONFIG_PCIE_DW_PLAT_HOST=y
CONFIG_PCIE_DW_PLAT_EP=y
CONFIG_PCIE_INTEL_GW=y
CONFIG_PCI_MESON=m
# end of DesignWare PCI Core Support

#
# Mobiveil PCIe Core Support
#
# end of Mobiveil PCIe Core Support

#
# Cadence PCIe controllers support
#
CONFIG_PCIE_CADENCE=y
CONFIG_PCIE_CADENCE_HOST=y
CONFIG_PCIE_CADENCE_EP=y
CONFIG_PCIE_CADENCE_PLAT=y
CONFIG_PCIE_CADENCE_PLAT_HOST=y
CONFIG_PCIE_CADENCE_PLAT_EP=y
CONFIG_PCI_J721E=y
CONFIG_PCI_J721E_HOST=y
CONFIG_PCI_J721E_EP=y
# end of Cadence PCIe controllers support
# end of PCI controller drivers

#
# PCI Endpoint
#
CONFIG_PCI_ENDPOINT=y
CONFIG_PCI_ENDPOINT_CONFIGFS=y
# CONFIG_PCI_EPF_TEST is not set
CONFIG_PCI_EPF_NTB=m
CONFIG_PCI_EPF_VNTB=m
# end of PCI Endpoint

#
# PCI switch controller drivers
#
CONFIG_PCI_SW_SWITCHTEC=m
# end of PCI switch controller drivers

CONFIG_CXL_BUS=m
CONFIG_CXL_PCI=m
CONFIG_CXL_MEM_RAW_COMMANDS=y
CONFIG_CXL_ACPI=m
CONFIG_CXL_MEM=m
CONFIG_CXL_PORT=m
CONFIG_CXL_SUSPEND=y
CONFIG_PCCARD=m
CONFIG_PCMCIA=m
CONFIG_PCMCIA_LOAD_CIS=y
CONFIG_CARDBUS=y

#
# PC-card bridges
#
CONFIG_YENTA=m
CONFIG_YENTA_O2=y
CONFIG_YENTA_RICOH=y
CONFIG_YENTA_TI=y
CONFIG_YENTA_ENE_TUNE=y
CONFIG_YENTA_TOSHIBA=y
CONFIG_PD6729=m
CONFIG_I82092=m
CONFIG_I82365=m
CONFIG_TCIC=m
CONFIG_PCMCIA_PROBE=y
CONFIG_PCCARD_NONSTATIC=y
CONFIG_RAPIDIO=m
CONFIG_RAPIDIO_TSI721=m
CONFIG_RAPIDIO_DISC_TIMEOUT=30
CONFIG_RAPIDIO_ENABLE_RX_TX_PORTS=y
CONFIG_RAPIDIO_DMA_ENGINE=y
CONFIG_RAPIDIO_DEBUG=y
CONFIG_RAPIDIO_ENUM_BASIC=m
CONFIG_RAPIDIO_CHMAN=m
CONFIG_RAPIDIO_MPORT_CDEV=m

#
# RapidIO Switch drivers
#
CONFIG_RAPIDIO_CPS_XX=m
CONFIG_RAPIDIO_CPS_GEN2=m
CONFIG_RAPIDIO_RXS_GEN3=m
# end of RapidIO Switch drivers

#
# Generic Driver Options
#
CONFIG_AUXILIARY_BUS=y
CONFIG_UEVENT_HELPER=y
CONFIG_UEVENT_HELPER_PATH=""
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_DEVTMPFS_SAFE=y
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y

#
# Firmware loader
#
CONFIG_FW_LOADER=y
CONFIG_FW_LOADER_PAGED_BUF=y
CONFIG_FW_LOADER_SYSFS=y
CONFIG_EXTRA_FIRMWARE=""
CONFIG_FW_LOADER_USER_HELPER=y
CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y
CONFIG_FW_LOADER_COMPRESS=y
CONFIG_FW_LOADER_COMPRESS_XZ=y
CONFIG_FW_LOADER_COMPRESS_ZSTD=y
CONFIG_FW_CACHE=y
CONFIG_FW_UPLOAD=y
# end of Firmware loader

CONFIG_WANT_DEV_COREDUMP=y
CONFIG_ALLOW_DEV_COREDUMP=y
CONFIG_DEV_COREDUMP=y
# CONFIG_DEBUG_DRIVER is not set
CONFIG_DEBUG_DEVRES=y
# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set
# CONFIG_TEST_ASYNC_DRIVER_PROBE is not set
CONFIG_GENERIC_CPU_AUTOPROBE=y
CONFIG_GENERIC_CPU_VULNERABILITIES=y
CONFIG_REGMAP=y
CONFIG_REGMAP_I2C=y
CONFIG_REGMAP_SLIMBUS=m
CONFIG_REGMAP_SPI=y
CONFIG_REGMAP_SPMI=m
CONFIG_REGMAP_W1=m
CONFIG_REGMAP_MMIO=y
CONFIG_REGMAP_IRQ=y
CONFIG_REGMAP_SOUNDWIRE=m
CONFIG_REGMAP_SOUNDWIRE_MBQ=m
CONFIG_REGMAP_SCCB=m
CONFIG_REGMAP_I3C=m
CONFIG_REGMAP_SPI_AVMM=m
CONFIG_DMA_SHARED_BUFFER=y
CONFIG_DMA_FENCE_TRACE=y
# end of Generic Driver Options

#
# Bus devices
#
CONFIG_MOXTET=m
CONFIG_MHI_BUS=m
CONFIG_MHI_BUS_DEBUG=y
CONFIG_MHI_BUS_PCI_GENERIC=m
CONFIG_MHI_BUS_EP=m
# end of Bus devices

CONFIG_CONNECTOR=m

#
# Firmware Drivers
#

#
# ARM System Control and Management Interface Protocol
#
# end of ARM System Control and Management Interface Protocol

CONFIG_EDD=m
CONFIG_EDD_OFF=y
CONFIG_FIRMWARE_MEMMAP=y
CONFIG_DMIID=y
CONFIG_DMI_SYSFS=m
CONFIG_DMI_SCAN_MACHINE_NON_EFI_FALLBACK=y
CONFIG_ISCSI_IBFT_FIND=y
CONFIG_ISCSI_IBFT=m
CONFIG_FW_CFG_SYSFS=m
CONFIG_FW_CFG_SYSFS_CMDLINE=y
CONFIG_SYSFB=y
CONFIG_SYSFB_SIMPLEFB=y
CONFIG_CS_DSP=m
CONFIG_GOOGLE_FIRMWARE=y
CONFIG_GOOGLE_SMI=m
CONFIG_GOOGLE_COREBOOT_TABLE=m
CONFIG_GOOGLE_MEMCONSOLE=m
CONFIG_GOOGLE_MEMCONSOLE_X86_LEGACY=m
CONFIG_GOOGLE_FRAMEBUFFER_COREBOOT=m
CONFIG_GOOGLE_MEMCONSOLE_COREBOOT=m
CONFIG_GOOGLE_VPD=m

#
# EFI (Extensible Firmware Interface) Support
#
CONFIG_EFI_ESRT=y
CONFIG_EFI_VARS_PSTORE=m
CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE=y
CONFIG_EFI_RUNTIME_MAP=y
CONFIG_EFI_FAKE_MEMMAP=y
CONFIG_EFI_MAX_FAKE_MEM=8
CONFIG_EFI_DXE_MEM_ATTRIBUTES=y
CONFIG_EFI_RUNTIME_WRAPPERS=y
CONFIG_EFI_GENERIC_STUB_INITRD_CMDLINE_LOADER=y
CONFIG_EFI_BOOTLOADER_CONTROL=m
CONFIG_EFI_CAPSULE_LOADER=y
CONFIG_EFI_CAPSULE_QUIRK_QUARK_CSH=y
# CONFIG_EFI_TEST is not set
CONFIG_EFI_DEV_PATH_PARSER=y
CONFIG_APPLE_PROPERTIES=y
CONFIG_RESET_ATTACK_MITIGATION=y
CONFIG_EFI_RCI2_TABLE=y
CONFIG_EFI_DISABLE_PCI_DMA=y
CONFIG_EFI_EARLYCON=y
CONFIG_EFI_CUSTOM_SSDT_OVERLAYS=y
CONFIG_EFI_DISABLE_RUNTIME=y
CONFIG_EFI_COCO_SECRET=y
CONFIG_EFI_EMBEDDED_FIRMWARE=y
# end of EFI (Extensible Firmware Interface) Support

CONFIG_UEFI_CPER=y
CONFIG_UEFI_CPER_X86=y

#
# Tegra firmware driver
#
# end of Tegra firmware driver
# end of Firmware Drivers

CONFIG_GNSS=m
CONFIG_GNSS_SERIAL=m
CONFIG_GNSS_MTK_SERIAL=m
CONFIG_GNSS_SIRF_SERIAL=m
CONFIG_GNSS_UBX_SERIAL=m
CONFIG_GNSS_USB=m
CONFIG_MTD=m
# CONFIG_MTD_TESTS is not set

#
# Partition parsers
#
CONFIG_MTD_AR7_PARTS=m
CONFIG_MTD_CMDLINE_PARTS=m
CONFIG_MTD_OF_PARTS=m
CONFIG_MTD_REDBOOT_PARTS=m
CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
CONFIG_MTD_REDBOOT_PARTS_READONLY=y
# end of Partition parsers

#
# User Modules And Translation Layers
#
CONFIG_MTD_BLKDEVS=m
CONFIG_MTD_BLOCK=m
CONFIG_MTD_BLOCK_RO=m

#
# Note that in some cases UBI block is preferred. See MTD_UBI_BLOCK.
#
CONFIG_FTL=m
CONFIG_NFTL=m
CONFIG_NFTL_RW=y
CONFIG_INFTL=m
CONFIG_RFD_FTL=m
CONFIG_SSFDC=m
CONFIG_SM_FTL=m
CONFIG_MTD_OOPS=m
CONFIG_MTD_PSTORE=m
CONFIG_MTD_SWAP=m
CONFIG_MTD_PARTITIONED_MASTER=y

#
# RAM/ROM/Flash chip drivers
#
CONFIG_MTD_CFI=m
CONFIG_MTD_JEDECPROBE=m
CONFIG_MTD_GEN_PROBE=m
CONFIG_MTD_CFI_ADV_OPTIONS=y
CONFIG_MTD_CFI_NOSWAP=y
# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
CONFIG_MTD_CFI_GEOMETRY=y
CONFIG_MTD_MAP_BANK_WIDTH_1=y
CONFIG_MTD_MAP_BANK_WIDTH_2=y
CONFIG_MTD_MAP_BANK_WIDTH_4=y
CONFIG_MTD_MAP_BANK_WIDTH_8=y
CONFIG_MTD_MAP_BANK_WIDTH_16=y
CONFIG_MTD_MAP_BANK_WIDTH_32=y
CONFIG_MTD_CFI_I1=y
CONFIG_MTD_CFI_I2=y
CONFIG_MTD_CFI_I4=y
CONFIG_MTD_CFI_I8=y
CONFIG_MTD_OTP=y
CONFIG_MTD_CFI_INTELEXT=m
CONFIG_MTD_CFI_AMDSTD=m
CONFIG_MTD_CFI_STAA=m
CONFIG_MTD_CFI_UTIL=m
CONFIG_MTD_RAM=m
CONFIG_MTD_ROM=m
CONFIG_MTD_ABSENT=m
# end of RAM/ROM/Flash chip drivers

#
# Mapping drivers for chip access
#
CONFIG_MTD_COMPLEX_MAPPINGS=y
CONFIG_MTD_PHYSMAP=m
CONFIG_MTD_PHYSMAP_COMPAT=y
CONFIG_MTD_PHYSMAP_START=0x8000000
CONFIG_MTD_PHYSMAP_LEN=0
CONFIG_MTD_PHYSMAP_BANKWIDTH=2
CONFIG_MTD_PHYSMAP_OF=y
CONFIG_MTD_PHYSMAP_VERSATILE=y
CONFIG_MTD_PHYSMAP_GEMINI=y
CONFIG_MTD_PHYSMAP_GPIO_ADDR=y
CONFIG_MTD_SBC_GXX=m
CONFIG_MTD_SCx200_DOCFLASH=m
# CONFIG_MTD_AMD76XROM is not set
CONFIG_MTD_ICHXROM=m
CONFIG_MTD_ESB2ROM=m
CONFIG_MTD_CK804XROM=m
CONFIG_MTD_SCB2_FLASH=m
CONFIG_MTD_NETtel=m
CONFIG_MTD_L440GX=m
CONFIG_MTD_PCI=m
CONFIG_MTD_PCMCIA=m
CONFIG_MTD_PCMCIA_ANONYMOUS=y
CONFIG_MTD_INTEL_VR_NOR=m
CONFIG_MTD_PLATRAM=m
# end of Mapping drivers for chip access

#
# Self-contained MTD device drivers
#
CONFIG_MTD_PMC551=m
CONFIG_MTD_PMC551_BUGFIX=y
CONFIG_MTD_PMC551_DEBUG=y
CONFIG_MTD_DATAFLASH=m
CONFIG_MTD_DATAFLASH_WRITE_VERIFY=y
CONFIG_MTD_DATAFLASH_OTP=y
CONFIG_MTD_MCHP23K256=m
CONFIG_MTD_MCHP48L640=m
CONFIG_MTD_SST25L=m
CONFIG_MTD_SLRAM=m
CONFIG_MTD_PHRAM=m
CONFIG_MTD_MTDRAM=m
CONFIG_MTDRAM_TOTAL_SIZE=4096
CONFIG_MTDRAM_ERASE_SIZE=128
CONFIG_MTD_BLOCK2MTD=m

#
# Disk-On-Chip Device Drivers
#
CONFIG_MTD_DOCG3=m
CONFIG_BCH_CONST_M=14
CONFIG_BCH_CONST_T=4
# end of Self-contained MTD device drivers

#
# NAND
#
CONFIG_MTD_NAND_CORE=m
CONFIG_MTD_ONENAND=m
CONFIG_MTD_ONENAND_VERIFY_WRITE=y
CONFIG_MTD_ONENAND_GENERIC=m
CONFIG_MTD_ONENAND_OTP=y
CONFIG_MTD_ONENAND_2X_PROGRAM=y
CONFIG_MTD_RAW_NAND=m

#
# Raw/parallel NAND flash controllers
#
CONFIG_MTD_NAND_DENALI=m
CONFIG_MTD_NAND_DENALI_PCI=m
CONFIG_MTD_NAND_DENALI_DT=m
CONFIG_MTD_NAND_CAFE=m
CONFIG_MTD_NAND_CS553X=m
CONFIG_MTD_NAND_MXIC=m
CONFIG_MTD_NAND_GPIO=m
CONFIG_MTD_NAND_PLATFORM=m
CONFIG_MTD_NAND_CADENCE=m
CONFIG_MTD_NAND_ARASAN=m
CONFIG_MTD_NAND_INTEL_LGM=m

#
# Misc
#
CONFIG_MTD_SM_COMMON=m
CONFIG_MTD_NAND_NANDSIM=m
CONFIG_MTD_NAND_RICOH=m
CONFIG_MTD_NAND_DISKONCHIP=m
CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED=y
CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0
CONFIG_MTD_NAND_DISKONCHIP_PROBE_HIGH=y
CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE=y
CONFIG_MTD_SPI_NAND=m

#
# ECC engine support
#
CONFIG_MTD_NAND_ECC=y
CONFIG_MTD_NAND_ECC_SW_HAMMING=y
CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC=y
CONFIG_MTD_NAND_ECC_SW_BCH=y
CONFIG_MTD_NAND_ECC_MXIC=y
# end of ECC engine support
# end of NAND

#
# LPDDR & LPDDR2 PCM memory drivers
#
CONFIG_MTD_LPDDR=m
CONFIG_MTD_QINFO_PROBE=m
# end of LPDDR & LPDDR2 PCM memory drivers

CONFIG_MTD_SPI_NOR=m
CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y
# CONFIG_MTD_SPI_NOR_SWP_DISABLE is not set
CONFIG_MTD_SPI_NOR_SWP_DISABLE_ON_VOLATILE=y
# CONFIG_MTD_SPI_NOR_SWP_KEEP is not set
CONFIG_MTD_UBI=m
CONFIG_MTD_UBI_WL_THRESHOLD=4096
CONFIG_MTD_UBI_BEB_LIMIT=20
CONFIG_MTD_UBI_FASTMAP=y
CONFIG_MTD_UBI_GLUEBI=m
CONFIG_MTD_UBI_BLOCK=y
CONFIG_MTD_HYPERBUS=m
CONFIG_DTC=y
CONFIG_OF=y
# CONFIG_OF_UNITTEST is not set
CONFIG_OF_FLATTREE=y
CONFIG_OF_EARLY_FLATTREE=y
CONFIG_OF_PROMTREE=y
CONFIG_OF_KOBJ=y
CONFIG_OF_DYNAMIC=y
CONFIG_OF_ADDRESS=y
CONFIG_OF_IRQ=y
CONFIG_OF_RESERVED_MEM=y
CONFIG_OF_RESOLVE=y
CONFIG_OF_OVERLAY=y
CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
CONFIG_PARPORT=m
CONFIG_PARPORT_PC=m
CONFIG_PARPORT_SERIAL=m
CONFIG_PARPORT_PC_FIFO=y
CONFIG_PARPORT_PC_SUPERIO=y
CONFIG_PARPORT_PC_PCMCIA=m
CONFIG_PARPORT_AX88796=m
CONFIG_PARPORT_1284=y
CONFIG_PARPORT_NOT_PC=y
CONFIG_PNP=y
CONFIG_PNP_DEBUG_MESSAGES=y

#
# Protocols
#
CONFIG_ISAPNP=y
CONFIG_PNPBIOS=y
CONFIG_PNPBIOS_PROC_FS=y
CONFIG_PNPACPI=y
CONFIG_BLK_DEV=y
CONFIG_BLK_DEV_NULL_BLK=m
CONFIG_BLK_DEV_NULL_BLK_FAULT_INJECTION=y
CONFIG_BLK_DEV_FD=m
CONFIG_BLK_DEV_FD_RAWCMD=y
CONFIG_CDROM=m
# CONFIG_PARIDE is not set
CONFIG_BLK_DEV_PCIESSD_MTIP32XX=m
CONFIG_ZRAM=m
CONFIG_ZRAM_DEF_COMP_LZORLE=y
# CONFIG_ZRAM_DEF_COMP_ZSTD is not set
# CONFIG_ZRAM_DEF_COMP_LZ4 is not set
# CONFIG_ZRAM_DEF_COMP_LZO is not set
# CONFIG_ZRAM_DEF_COMP_LZ4HC is not set
# CONFIG_ZRAM_DEF_COMP_842 is not set
CONFIG_ZRAM_DEF_COMP="lzo-rle"
CONFIG_ZRAM_WRITEBACK=y
CONFIG_ZRAM_MEMORY_TRACKING=y
CONFIG_BLK_DEV_LOOP=m
CONFIG_BLK_DEV_LOOP_MIN_COUNT=8
CONFIG_BLK_DEV_DRBD=m
CONFIG_DRBD_FAULT_INJECTION=y
CONFIG_BLK_DEV_NBD=m
CONFIG_BLK_DEV_RAM=m
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
CONFIG_CDROM_PKTCDVD_WCACHE=y
CONFIG_ATA_OVER_ETH=m
CONFIG_VIRTIO_BLK=m
CONFIG_BLK_DEV_RBD=m
CONFIG_BLK_DEV_UBLK=m
CONFIG_BLK_DEV_RNBD=y
CONFIG_BLK_DEV_RNBD_CLIENT=m
CONFIG_BLK_DEV_RNBD_SERVER=m

#
# NVME Support
#
CONFIG_NVME_COMMON=m
CONFIG_NVME_CORE=m
CONFIG_BLK_DEV_NVME=m
CONFIG_NVME_MULTIPATH=y
CONFIG_NVME_VERBOSE_ERRORS=y
CONFIG_NVME_HWMON=y
CONFIG_NVME_FABRICS=m
CONFIG_NVME_RDMA=m
CONFIG_NVME_FC=m
CONFIG_NVME_TCP=m
CONFIG_NVME_AUTH=y
CONFIG_NVME_TARGET=m
CONFIG_NVME_TARGET_PASSTHRU=y
CONFIG_NVME_TARGET_LOOP=m
CONFIG_NVME_TARGET_RDMA=m
CONFIG_NVME_TARGET_FC=m
CONFIG_NVME_TARGET_FCLOOP=m
CONFIG_NVME_TARGET_TCP=m
CONFIG_NVME_TARGET_AUTH=y
# end of NVME Support

#
# Misc devices
#
CONFIG_SENSORS_LIS3LV02D=m
CONFIG_AD525X_DPOT=m
CONFIG_AD525X_DPOT_I2C=m
CONFIG_AD525X_DPOT_SPI=m
CONFIG_DUMMY_IRQ=m
CONFIG_IBM_ASM=m
CONFIG_PHANTOM=m
CONFIG_TIFM_CORE=m
CONFIG_TIFM_7XX1=m
CONFIG_ICS932S401=m
CONFIG_ENCLOSURE_SERVICES=m
CONFIG_CS5535_MFGPT=m
CONFIG_CS5535_MFGPT_DEFAULT_IRQ=7
CONFIG_CS5535_CLOCK_EVENT_SRC=m
CONFIG_HI6421V600_IRQ=m
CONFIG_HP_ILO=m
CONFIG_APDS9802ALS=m
CONFIG_ISL29003=m
CONFIG_ISL29020=m
CONFIG_SENSORS_TSL2550=m
CONFIG_SENSORS_BH1770=m
CONFIG_SENSORS_APDS990X=m
CONFIG_HMC6352=m
CONFIG_DS1682=m
CONFIG_VMWARE_BALLOON=m
CONFIG_PCH_PHUB=m
CONFIG_LATTICE_ECP3_CONFIG=m
CONFIG_SRAM=y
CONFIG_DW_XDATA_PCIE=m
# CONFIG_PCI_ENDPOINT_TEST is not set
CONFIG_XILINX_SDFEC=m
CONFIG_MISC_RTSX=m
CONFIG_HISI_HIKEY_USB=m
CONFIG_OPEN_DICE=m
CONFIG_VCPU_STALL_DETECTOR=m
CONFIG_C2PORT=m
CONFIG_C2PORT_DURAMAR_2150=m

#
# EEPROM support
#
CONFIG_EEPROM_AT24=m
CONFIG_EEPROM_AT25=m
CONFIG_EEPROM_LEGACY=m
CONFIG_EEPROM_MAX6875=m
CONFIG_EEPROM_93CX6=m
CONFIG_EEPROM_93XX46=m
CONFIG_EEPROM_IDT_89HPESX=m
CONFIG_EEPROM_EE1004=m
# end of EEPROM support

CONFIG_CB710_CORE=m
CONFIG_CB710_DEBUG=y
CONFIG_CB710_DEBUG_ASSUMPTIONS=y

#
# Texas Instruments shared transport line discipline
#
CONFIG_TI_ST=m
# end of Texas Instruments shared transport line discipline

CONFIG_SENSORS_LIS3_I2C=m
CONFIG_ALTERA_STAPL=m
CONFIG_INTEL_MEI=m
CONFIG_INTEL_MEI_ME=m
CONFIG_INTEL_MEI_TXE=m
CONFIG_INTEL_MEI_GSC=m
CONFIG_INTEL_MEI_HDCP=m
CONFIG_INTEL_MEI_PXP=m
CONFIG_VMWARE_VMCI=m
CONFIG_ECHO=m
CONFIG_BCM_VK=m
CONFIG_BCM_VK_TTY=y
CONFIG_MISC_ALCOR_PCI=m
CONFIG_MISC_RTSX_PCI=m
CONFIG_MISC_RTSX_USB=m
CONFIG_HABANA_AI=m
CONFIG_UACCE=m
CONFIG_PVPANIC=y
CONFIG_PVPANIC_MMIO=m
CONFIG_PVPANIC_PCI=m
CONFIG_GP_PCI1XXXX=m
# end of Misc devices

#
# SCSI device support
#
CONFIG_SCSI_MOD=m
CONFIG_RAID_ATTRS=m
CONFIG_SCSI_COMMON=m
CONFIG_SCSI=m
CONFIG_SCSI_DMA=y
CONFIG_SCSI_NETLINK=y
CONFIG_SCSI_PROC_FS=y

#
# SCSI support type (disk, tape, CD-ROM)
#
CONFIG_BLK_DEV_SD=m
CONFIG_CHR_DEV_ST=m
CONFIG_BLK_DEV_SR=m
CONFIG_CHR_DEV_SG=m
CONFIG_BLK_DEV_BSG=y
CONFIG_CHR_DEV_SCH=m
CONFIG_SCSI_ENCLOSURE=m
CONFIG_SCSI_CONSTANTS=y
CONFIG_SCSI_LOGGING=y
CONFIG_SCSI_SCAN_ASYNC=y

#
# SCSI Transports
#
CONFIG_SCSI_SPI_ATTRS=m
CONFIG_SCSI_FC_ATTRS=m
CONFIG_SCSI_ISCSI_ATTRS=m
CONFIG_SCSI_SAS_ATTRS=m
CONFIG_SCSI_SAS_LIBSAS=m
CONFIG_SCSI_SAS_ATA=y
CONFIG_SCSI_SAS_HOST_SMP=y
CONFIG_SCSI_SRP_ATTRS=m
# end of SCSI Transports

CONFIG_SCSI_LOWLEVEL=y
CONFIG_ISCSI_TCP=m
CONFIG_ISCSI_BOOT_SYSFS=m
CONFIG_SCSI_CXGB3_ISCSI=m
CONFIG_SCSI_CXGB4_ISCSI=m
CONFIG_SCSI_BNX2_ISCSI=m
CONFIG_SCSI_BNX2X_FCOE=m
CONFIG_BE2ISCSI=m
CONFIG_BLK_DEV_3W_XXXX_RAID=m
CONFIG_SCSI_HPSA=m
CONFIG_SCSI_3W_9XXX=m
CONFIG_SCSI_3W_SAS=m
CONFIG_SCSI_ACARD=m
CONFIG_SCSI_AHA152X=m
CONFIG_SCSI_AHA1542=m
CONFIG_SCSI_AHA1740=m
CONFIG_SCSI_AACRAID=m
CONFIG_SCSI_AIC7XXX=m
CONFIG_AIC7XXX_CMDS_PER_DEVICE=32
CONFIG_AIC7XXX_RESET_DELAY_MS=5000
CONFIG_AIC7XXX_DEBUG_ENABLE=y
CONFIG_AIC7XXX_DEBUG_MASK=0
CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
CONFIG_SCSI_AIC79XX=m
CONFIG_AIC79XX_CMDS_PER_DEVICE=32
CONFIG_AIC79XX_RESET_DELAY_MS=5000
CONFIG_AIC79XX_DEBUG_ENABLE=y
CONFIG_AIC79XX_DEBUG_MASK=0
CONFIG_AIC79XX_REG_PRETTY_PRINT=y
CONFIG_SCSI_AIC94XX=m
CONFIG_AIC94XX_DEBUG=y
CONFIG_SCSI_MVSAS=m
CONFIG_SCSI_MVSAS_DEBUG=y
CONFIG_SCSI_MVSAS_TASKLET=y
CONFIG_SCSI_MVUMI=m
CONFIG_SCSI_ADVANSYS=m
CONFIG_SCSI_ARCMSR=m
CONFIG_SCSI_ESAS2R=m
CONFIG_MEGARAID_NEWGEN=y
CONFIG_MEGARAID_MM=m
CONFIG_MEGARAID_MAILBOX=m
CONFIG_MEGARAID_LEGACY=m
CONFIG_MEGARAID_SAS=m
CONFIG_SCSI_MPT3SAS=m
CONFIG_SCSI_MPT2SAS_MAX_SGE=128
CONFIG_SCSI_MPT3SAS_MAX_SGE=128
CONFIG_SCSI_MPT2SAS=m
CONFIG_SCSI_MPI3MR=m
CONFIG_SCSI_SMARTPQI=m
CONFIG_SCSI_HPTIOP=m
CONFIG_SCSI_BUSLOGIC=m
CONFIG_SCSI_FLASHPOINT=y
CONFIG_SCSI_MYRB=m
CONFIG_SCSI_MYRS=m
CONFIG_VMWARE_PVSCSI=m
CONFIG_HYPERV_STORAGE=m
CONFIG_LIBFC=m
CONFIG_LIBFCOE=m
CONFIG_FCOE=m
CONFIG_FCOE_FNIC=m
CONFIG_SCSI_SNIC=m
CONFIG_SCSI_SNIC_DEBUG_FS=y
CONFIG_SCSI_DMX3191D=m
CONFIG_SCSI_FDOMAIN=m
CONFIG_SCSI_FDOMAIN_PCI=m
CONFIG_SCSI_FDOMAIN_ISA=m
CONFIG_SCSI_ISCI=m
CONFIG_SCSI_GENERIC_NCR5380=m
CONFIG_SCSI_IPS=m
CONFIG_SCSI_INITIO=m
CONFIG_SCSI_INIA100=m
CONFIG_SCSI_PPA=m
CONFIG_SCSI_IMM=m
CONFIG_SCSI_IZIP_EPP16=y
CONFIG_SCSI_IZIP_SLOW_CTR=y
CONFIG_SCSI_STEX=m
CONFIG_SCSI_SYM53C8XX_2=m
CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
CONFIG_SCSI_SYM53C8XX_MMIO=y
CONFIG_SCSI_IPR=m
CONFIG_SCSI_IPR_TRACE=y
CONFIG_SCSI_IPR_DUMP=y
CONFIG_SCSI_QLOGIC_FAS=m
CONFIG_SCSI_QLOGIC_1280=m
CONFIG_SCSI_QLA_FC=m
CONFIG_TCM_QLA2XXX=m
CONFIG_TCM_QLA2XXX_DEBUG=y
CONFIG_SCSI_QLA_ISCSI=m
CONFIG_QEDI=m
CONFIG_QEDF=m
CONFIG_SCSI_LPFC=m
CONFIG_SCSI_LPFC_DEBUG_FS=y
CONFIG_SCSI_EFCT=m
CONFIG_SCSI_SIM710=m
CONFIG_SCSI_DC395x=m
CONFIG_SCSI_AM53C974=m
CONFIG_SCSI_NSP32=m
CONFIG_SCSI_WD719X=m
CONFIG_SCSI_DEBUG=m
CONFIG_SCSI_PMCRAID=m
CONFIG_SCSI_PM8001=m
CONFIG_SCSI_BFA_FC=m
CONFIG_SCSI_VIRTIO=m
CONFIG_SCSI_CHELSIO_FCOE=m
CONFIG_SCSI_LOWLEVEL_PCMCIA=y
CONFIG_PCMCIA_AHA152X=m
CONFIG_PCMCIA_FDOMAIN=m
CONFIG_PCMCIA_NINJA_SCSI=m
CONFIG_PCMCIA_QLOGIC=m
CONFIG_PCMCIA_SYM53C500=m
CONFIG_SCSI_DH=y
CONFIG_SCSI_DH_RDAC=m
CONFIG_SCSI_DH_HP_SW=m
CONFIG_SCSI_DH_EMC=m
CONFIG_SCSI_DH_ALUA=m
# end of SCSI device support

CONFIG_ATA=m
CONFIG_SATA_HOST=y
CONFIG_PATA_TIMINGS=y
CONFIG_ATA_VERBOSE_ERROR=y
CONFIG_ATA_FORCE=y
CONFIG_ATA_ACPI=y
CONFIG_SATA_ZPODD=y
CONFIG_SATA_PMP=y

#
# Controllers with non-SFF native interface
#
CONFIG_SATA_AHCI=m
CONFIG_SATA_MOBILE_LPM_POLICY=0
CONFIG_SATA_AHCI_PLATFORM=m
CONFIG_AHCI_DWC=m
CONFIG_AHCI_CEVA=m
CONFIG_AHCI_QORIQ=m
CONFIG_SATA_INIC162X=m
CONFIG_SATA_ACARD_AHCI=m
CONFIG_SATA_SIL24=m
CONFIG_ATA_SFF=y

#
# SFF controllers with custom DMA interface
#
CONFIG_PDC_ADMA=m
CONFIG_SATA_QSTOR=m
CONFIG_SATA_SX4=m
CONFIG_ATA_BMDMA=y

#
# SATA SFF controllers with BMDMA
#
CONFIG_ATA_PIIX=m
CONFIG_SATA_DWC=m
CONFIG_SATA_DWC_OLD_DMA=y
CONFIG_SATA_MV=m
CONFIG_SATA_NV=m
CONFIG_SATA_PROMISE=m
CONFIG_SATA_SIL=m
CONFIG_SATA_SIS=m
CONFIG_SATA_SVW=m
CONFIG_SATA_ULI=m
CONFIG_SATA_VIA=m
CONFIG_SATA_VITESSE=m

#
# PATA SFF controllers with BMDMA
#
CONFIG_PATA_ALI=m
# CONFIG_PATA_AMD is not set
CONFIG_PATA_ARTOP=m
CONFIG_PATA_ATIIXP=m
CONFIG_PATA_ATP867X=m
CONFIG_PATA_CMD64X=m
CONFIG_PATA_CS5520=m
CONFIG_PATA_CS5530=m
CONFIG_PATA_CS5535=m
CONFIG_PATA_CS5536=m
CONFIG_PATA_CYPRESS=m
CONFIG_PATA_EFAR=m
CONFIG_PATA_HPT366=m
CONFIG_PATA_HPT37X=m
CONFIG_PATA_HPT3X2N=m
CONFIG_PATA_HPT3X3=m
CONFIG_PATA_HPT3X3_DMA=y
CONFIG_PATA_IT8213=m
CONFIG_PATA_IT821X=m
CONFIG_PATA_JMICRON=m
CONFIG_PATA_MARVELL=m
CONFIG_PATA_NETCELL=m
CONFIG_PATA_NINJA32=m
CONFIG_PATA_NS87415=m
CONFIG_PATA_OLDPIIX=m
CONFIG_PATA_OPTIDMA=m
CONFIG_PATA_PDC2027X=m
CONFIG_PATA_PDC_OLD=m
CONFIG_PATA_RADISYS=m
CONFIG_PATA_RDC=m
CONFIG_PATA_SC1200=m
CONFIG_PATA_SCH=m
CONFIG_PATA_SERVERWORKS=m
CONFIG_PATA_SIL680=m
CONFIG_PATA_SIS=m
CONFIG_PATA_TOSHIBA=m
CONFIG_PATA_TRIFLEX=m
CONFIG_PATA_VIA=m
CONFIG_PATA_WINBOND=m

#
# PIO-only SFF controllers
#
CONFIG_PATA_CMD640_PCI=m
CONFIG_PATA_ISAPNP=m
CONFIG_PATA_MPIIX=m
CONFIG_PATA_NS87410=m
CONFIG_PATA_OPTI=m
CONFIG_PATA_PCMCIA=m
CONFIG_PATA_PLATFORM=m
CONFIG_PATA_OF_PLATFORM=m
CONFIG_PATA_QDI=m
CONFIG_PATA_RZ1000=m
CONFIG_PATA_WINBOND_VLB=m

#
# Generic fallback / legacy drivers
#
CONFIG_PATA_ACPI=m
CONFIG_ATA_GENERIC=m
CONFIG_PATA_LEGACY=m
CONFIG_MD=y
CONFIG_BLK_DEV_MD=m
CONFIG_MD_LINEAR=m
CONFIG_MD_RAID0=m
CONFIG_MD_RAID1=m
CONFIG_MD_RAID10=m
CONFIG_MD_RAID456=m
CONFIG_MD_MULTIPATH=m
CONFIG_MD_FAULTY=m
CONFIG_MD_CLUSTER=m
CONFIG_BCACHE=m
CONFIG_BCACHE_DEBUG=y
CONFIG_BCACHE_CLOSURES_DEBUG=y
CONFIG_BCACHE_ASYNC_REGISTRATION=y
CONFIG_BLK_DEV_DM_BUILTIN=y
CONFIG_BLK_DEV_DM=m
CONFIG_DM_DEBUG=y
CONFIG_DM_BUFIO=m
CONFIG_DM_DEBUG_BLOCK_MANAGER_LOCKING=y
CONFIG_DM_DEBUG_BLOCK_STACK_TRACING=y
CONFIG_DM_BIO_PRISON=m
CONFIG_DM_PERSISTENT_DATA=m
CONFIG_DM_UNSTRIPED=m
CONFIG_DM_CRYPT=m
CONFIG_DM_SNAPSHOT=m
CONFIG_DM_THIN_PROVISIONING=m
CONFIG_DM_CACHE=m
CONFIG_DM_CACHE_SMQ=m
CONFIG_DM_WRITECACHE=m
CONFIG_DM_ERA=m
CONFIG_DM_CLONE=m
CONFIG_DM_MIRROR=m
CONFIG_DM_LOG_USERSPACE=m
CONFIG_DM_RAID=m
CONFIG_DM_ZERO=m
CONFIG_DM_MULTIPATH=m
CONFIG_DM_MULTIPATH_QL=m
CONFIG_DM_MULTIPATH_ST=m
CONFIG_DM_MULTIPATH_HST=m
CONFIG_DM_MULTIPATH_IOA=m
CONFIG_DM_DELAY=m
CONFIG_DM_DUST=m
CONFIG_DM_UEVENT=y
CONFIG_DM_FLAKEY=m
CONFIG_DM_VERITY=m
CONFIG_DM_VERITY_VERIFY_ROOTHASH_SIG=y
CONFIG_DM_VERITY_VERIFY_ROOTHASH_SIG_SECONDARY_KEYRING=y
CONFIG_DM_VERITY_FEC=y
CONFIG_DM_SWITCH=m
CONFIG_DM_LOG_WRITES=m
CONFIG_DM_INTEGRITY=m
CONFIG_DM_ZONED=m
CONFIG_DM_AUDIT=y
CONFIG_TARGET_CORE=m
CONFIG_TCM_IBLOCK=m
CONFIG_TCM_FILEIO=m
CONFIG_TCM_PSCSI=m
CONFIG_TCM_USER2=m
CONFIG_LOOPBACK_TARGET=m
CONFIG_TCM_FC=m
CONFIG_ISCSI_TARGET=m
CONFIG_ISCSI_TARGET_CXGB4=m
CONFIG_SBP_TARGET=m
CONFIG_FUSION=y
CONFIG_FUSION_SPI=m
CONFIG_FUSION_FC=m
CONFIG_FUSION_SAS=m
CONFIG_FUSION_MAX_SGE=128
CONFIG_FUSION_CTL=m
CONFIG_FUSION_LAN=m
CONFIG_FUSION_LOGGING=y

#
# IEEE 1394 (FireWire) support
#
CONFIG_FIREWIRE=m
CONFIG_FIREWIRE_OHCI=m
CONFIG_FIREWIRE_SBP2=m
CONFIG_FIREWIRE_NET=m
CONFIG_FIREWIRE_NOSY=m
# end of IEEE 1394 (FireWire) support

CONFIG_MACINTOSH_DRIVERS=y
CONFIG_MAC_EMUMOUSEBTN=m
CONFIG_NETDEVICES=y
CONFIG_MII=m
CONFIG_NET_CORE=y
CONFIG_BONDING=m
CONFIG_DUMMY=m
CONFIG_WIREGUARD=m
CONFIG_WIREGUARD_DEBUG=y
CONFIG_EQUALIZER=m
CONFIG_NET_FC=y
CONFIG_IFB=m
CONFIG_NET_TEAM=m
CONFIG_NET_TEAM_MODE_BROADCAST=m
CONFIG_NET_TEAM_MODE_ROUNDROBIN=m
CONFIG_NET_TEAM_MODE_RANDOM=m
CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m
CONFIG_NET_TEAM_MODE_LOADBALANCE=m
CONFIG_MACVLAN=m
CONFIG_MACVTAP=m
CONFIG_IPVLAN_L3S=y
CONFIG_IPVLAN=m
CONFIG_IPVTAP=m
CONFIG_VXLAN=m
CONFIG_GENEVE=m
CONFIG_BAREUDP=m
CONFIG_GTP=m
CONFIG_AMT=m
CONFIG_MACSEC=m
CONFIG_NETCONSOLE=m
CONFIG_NETCONSOLE_DYNAMIC=y
CONFIG_NETPOLL=y
CONFIG_NET_POLL_CONTROLLER=y
CONFIG_NTB_NETDEV=m
CONFIG_RIONET=m
CONFIG_RIONET_TX_SIZE=128
CONFIG_RIONET_RX_SIZE=128
CONFIG_TUN=m
CONFIG_TAP=m
CONFIG_TUN_VNET_CROSS_LE=y
CONFIG_VETH=m
CONFIG_VIRTIO_NET=m
CONFIG_NLMON=m
CONFIG_NET_VRF=m
CONFIG_VSOCKMON=m
CONFIG_MHI_NET=m
CONFIG_SUNGEM_PHY=m
CONFIG_ARCNET=m
CONFIG_ARCNET_1201=m
CONFIG_ARCNET_1051=m
CONFIG_ARCNET_RAW=m
CONFIG_ARCNET_CAP=m
CONFIG_ARCNET_COM90xx=m
CONFIG_ARCNET_COM90xxIO=m
CONFIG_ARCNET_RIM_I=m
CONFIG_ARCNET_COM20020=m
CONFIG_ARCNET_COM20020_ISA=m
CONFIG_ARCNET_COM20020_PCI=m
CONFIG_ARCNET_COM20020_CS=m
CONFIG_ATM_DRIVERS=y
CONFIG_ATM_DUMMY=m
CONFIG_ATM_TCP=m
CONFIG_ATM_LANAI=m
CONFIG_ATM_ENI=m
CONFIG_ATM_ENI_DEBUG=y
CONFIG_ATM_ENI_TUNE_BURST=y
CONFIG_ATM_ENI_BURST_TX_16W=y
CONFIG_ATM_ENI_BURST_TX_8W=y
CONFIG_ATM_ENI_BURST_TX_4W=y
CONFIG_ATM_ENI_BURST_TX_2W=y
CONFIG_ATM_ENI_BURST_RX_16W=y
CONFIG_ATM_ENI_BURST_RX_8W=y
CONFIG_ATM_ENI_BURST_RX_4W=y
CONFIG_ATM_ENI_BURST_RX_2W=y
CONFIG_ATM_NICSTAR=m
CONFIG_ATM_NICSTAR_USE_SUNI=y
CONFIG_ATM_NICSTAR_USE_IDT77105=y
CONFIG_ATM_IDT77252=m
CONFIG_ATM_IDT77252_DEBUG=y
CONFIG_ATM_IDT77252_RCV_ALL=y
CONFIG_ATM_IDT77252_USE_SUNI=y
CONFIG_ATM_IA=m
CONFIG_ATM_IA_DEBUG=y
CONFIG_ATM_FORE200E=m
CONFIG_ATM_FORE200E_USE_TASKLET=y
CONFIG_ATM_FORE200E_TX_RETRY=16
CONFIG_ATM_FORE200E_DEBUG=0
CONFIG_ATM_HE=m
CONFIG_ATM_HE_USE_SUNI=y
CONFIG_ATM_SOLOS=m
CONFIG_CAIF_DRIVERS=y
CONFIG_CAIF_TTY=m
CONFIG_CAIF_VIRTIO=m

#
# Distributed Switch Architecture drivers
#
CONFIG_B53=m
CONFIG_B53_SPI_DRIVER=m
CONFIG_B53_MDIO_DRIVER=m
CONFIG_B53_MMAP_DRIVER=m
CONFIG_B53_SRAB_DRIVER=m
CONFIG_B53_SERDES=m
CONFIG_NET_DSA_BCM_SF2=m
CONFIG_NET_DSA_LOOP=m
CONFIG_NET_DSA_HIRSCHMANN_HELLCREEK=m
CONFIG_NET_DSA_LANTIQ_GSWIP=m
CONFIG_NET_DSA_MT7530=m
CONFIG_NET_DSA_MV88E6060=m
CONFIG_NET_DSA_MICROCHIP_KSZ_COMMON=m
CONFIG_NET_DSA_MICROCHIP_KSZ9477_I2C=m
CONFIG_NET_DSA_MICROCHIP_KSZ_SPI=m
CONFIG_NET_DSA_MICROCHIP_KSZ8863_SMI=m
CONFIG_NET_DSA_MV88E6XXX=m
CONFIG_NET_DSA_MV88E6XXX_PTP=y
CONFIG_NET_DSA_MSCC_SEVILLE=m
CONFIG_NET_DSA_AR9331=m
CONFIG_NET_DSA_QCA8K=m
CONFIG_NET_DSA_SJA1105=m
CONFIG_NET_DSA_SJA1105_PTP=y
CONFIG_NET_DSA_SJA1105_TAS=y
CONFIG_NET_DSA_SJA1105_VL=y
CONFIG_NET_DSA_XRS700X=m
CONFIG_NET_DSA_XRS700X_I2C=m
CONFIG_NET_DSA_XRS700X_MDIO=m
CONFIG_NET_DSA_REALTEK=m
CONFIG_NET_DSA_REALTEK_MDIO=m
CONFIG_NET_DSA_REALTEK_SMI=m
CONFIG_NET_DSA_REALTEK_RTL8365MB=m
CONFIG_NET_DSA_REALTEK_RTL8366RB=m
CONFIG_NET_DSA_SMSC_LAN9303=m
CONFIG_NET_DSA_SMSC_LAN9303_I2C=m
CONFIG_NET_DSA_SMSC_LAN9303_MDIO=m
CONFIG_NET_DSA_VITESSE_VSC73XX=m
CONFIG_NET_DSA_VITESSE_VSC73XX_SPI=m
CONFIG_NET_DSA_VITESSE_VSC73XX_PLATFORM=m
# end of Distributed Switch Architecture drivers

CONFIG_ETHERNET=y
CONFIG_MDIO=m
CONFIG_NET_VENDOR_3COM=y
CONFIG_EL3=m
CONFIG_3C515=m
CONFIG_PCMCIA_3C574=m
CONFIG_PCMCIA_3C589=m
CONFIG_VORTEX=m
CONFIG_TYPHOON=m
CONFIG_NET_VENDOR_ADAPTEC=y
CONFIG_ADAPTEC_STARFIRE=m
CONFIG_NET_VENDOR_AGERE=y
CONFIG_ET131X=m
CONFIG_NET_VENDOR_ALACRITECH=y
CONFIG_SLICOSS=m
CONFIG_NET_VENDOR_ALTEON=y
CONFIG_ACENIC=m
CONFIG_ACENIC_OMIT_TIGON_I=y
CONFIG_ALTERA_TSE=m
CONFIG_NET_VENDOR_AMAZON=y
CONFIG_ENA_ETHERNET=m
# CONFIG_NET_VENDOR_AMD is not set
CONFIG_NET_VENDOR_AQUANTIA=y
CONFIG_AQTION=m
CONFIG_NET_VENDOR_ARC=y
CONFIG_NET_VENDOR_ASIX=y
CONFIG_SPI_AX88796C=m
CONFIG_SPI_AX88796C_COMPRESSION=y
CONFIG_NET_VENDOR_ATHEROS=y
CONFIG_ATL2=m
CONFIG_ATL1=m
CONFIG_ATL1E=m
CONFIG_ATL1C=m
CONFIG_ALX=m
CONFIG_CX_ECAT=m
CONFIG_NET_VENDOR_BROADCOM=y
CONFIG_B44=m
CONFIG_B44_PCI_AUTOSELECT=y
CONFIG_B44_PCICORE_AUTOSELECT=y
CONFIG_B44_PCI=y
CONFIG_BCMGENET=m
CONFIG_BNX2=m
CONFIG_CNIC=m
CONFIG_TIGON3=m
CONFIG_TIGON3_HWMON=y
CONFIG_BNX2X=m
CONFIG_BNX2X_SRIOV=y
CONFIG_SYSTEMPORT=m
CONFIG_BNXT=m
CONFIG_BNXT_SRIOV=y
CONFIG_BNXT_FLOWER_OFFLOAD=y
CONFIG_BNXT_DCB=y
CONFIG_BNXT_HWMON=y
CONFIG_NET_VENDOR_CADENCE=y
CONFIG_MACB=m
CONFIG_MACB_USE_HWSTAMP=y
CONFIG_MACB_PCI=m
CONFIG_NET_VENDOR_CAVIUM=y
CONFIG_NET_VENDOR_CHELSIO=y
CONFIG_CHELSIO_T1=m
CONFIG_CHELSIO_T1_1G=y
CONFIG_CHELSIO_T3=m
CONFIG_CHELSIO_T4=m
CONFIG_CHELSIO_T4_DCB=y
CONFIG_CHELSIO_T4_FCOE=y
CONFIG_CHELSIO_T4VF=m
CONFIG_CHELSIO_LIB=m
CONFIG_CHELSIO_INLINE_CRYPTO=y
CONFIG_CRYPTO_DEV_CHELSIO_TLS=m
CONFIG_CHELSIO_IPSEC_INLINE=m
CONFIG_CHELSIO_TLS_DEVICE=m
CONFIG_NET_VENDOR_CIRRUS=y
# CONFIG_CS89x0_ISA is not set
CONFIG_NET_VENDOR_CISCO=y
CONFIG_ENIC=m
CONFIG_NET_VENDOR_CORTINA=y
CONFIG_GEMINI_ETHERNET=m
CONFIG_NET_VENDOR_DAVICOM=y
CONFIG_DM9051=m
CONFIG_DNET=m
CONFIG_NET_VENDOR_DEC=y
CONFIG_NET_TULIP=y
CONFIG_DE2104X=m
CONFIG_DE2104X_DSL=0
CONFIG_TULIP=m
CONFIG_TULIP_MWI=y
CONFIG_TULIP_MMIO=y
CONFIG_TULIP_NAPI=y
CONFIG_TULIP_NAPI_HW_MITIGATION=y
CONFIG_WINBOND_840=m
CONFIG_DM9102=m
CONFIG_ULI526X=m
CONFIG_PCMCIA_XIRCOM=m
CONFIG_NET_VENDOR_DLINK=y
CONFIG_DL2K=m
CONFIG_SUNDANCE=m
CONFIG_SUNDANCE_MMIO=y
CONFIG_NET_VENDOR_EMULEX=y
CONFIG_BE2NET=m
CONFIG_BE2NET_HWMON=y
CONFIG_BE2NET_BE2=y
CONFIG_BE2NET_BE3=y
CONFIG_BE2NET_LANCER=y
CONFIG_BE2NET_SKYHAWK=y
CONFIG_NET_VENDOR_ENGLEDER=y
CONFIG_TSNEP=m
# CONFIG_TSNEP_SELFTESTS is not set
CONFIG_NET_VENDOR_EZCHIP=y
CONFIG_EZCHIP_NPS_MANAGEMENT_ENET=m
CONFIG_NET_VENDOR_FUJITSU=y
CONFIG_PCMCIA_FMVJ18X=m
CONFIG_NET_VENDOR_FUNGIBLE=y
CONFIG_FUN_CORE=m
CONFIG_FUN_ETH=m
CONFIG_NET_VENDOR_GOOGLE=y
CONFIG_GVE=m
CONFIG_NET_VENDOR_HUAWEI=y
CONFIG_HINIC=m
CONFIG_NET_VENDOR_I825XX=y
CONFIG_NET_VENDOR_INTEL=y
CONFIG_E100=m
CONFIG_E1000=y
CONFIG_E1000E=m
CONFIG_E1000E_HWTS=y
CONFIG_IGB=m
CONFIG_IGB_HWMON=y
CONFIG_IGBVF=m
CONFIG_IXGB=m
CONFIG_IXGBE=m
CONFIG_IXGBE_HWMON=y
CONFIG_IXGBE_DCB=y
CONFIG_IXGBE_IPSEC=y
CONFIG_IXGBEVF=m
CONFIG_IXGBEVF_IPSEC=y
CONFIG_I40E=m
CONFIG_I40E_DCB=y
CONFIG_IAVF=m
CONFIG_I40EVF=m
CONFIG_ICE=m
CONFIG_ICE_SWITCHDEV=y
CONFIG_ICE_HWTS=y
CONFIG_FM10K=m
CONFIG_IGC=m
CONFIG_NET_VENDOR_WANGXUN=y
CONFIG_NGBE=m
CONFIG_TXGBE=m
CONFIG_JME=m
CONFIG_NET_VENDOR_ADI=y
CONFIG_ADIN1110=m
CONFIG_NET_VENDOR_LITEX=y
CONFIG_LITEX_LITEETH=m
CONFIG_NET_VENDOR_MARVELL=y
CONFIG_MVMDIO=m
CONFIG_SKGE=m
CONFIG_SKGE_DEBUG=y
CONFIG_SKGE_GENESIS=y
CONFIG_SKY2=m
CONFIG_SKY2_DEBUG=y
CONFIG_PRESTERA=m
CONFIG_PRESTERA_PCI=m
CONFIG_NET_VENDOR_MELLANOX=y
CONFIG_MLX4_EN=m
CONFIG_MLX4_EN_DCB=y
CONFIG_MLX4_CORE=m
CONFIG_MLX4_DEBUG=y
CONFIG_MLX4_CORE_GEN2=y
CONFIG_MLX5_CORE=m
CONFIG_MLX5_FPGA=y
CONFIG_MLX5_CORE_EN=y
CONFIG_MLX5_EN_ARFS=y
CONFIG_MLX5_EN_RXNFC=y
CONFIG_MLX5_MPFS=y
CONFIG_MLX5_ESWITCH=y
CONFIG_MLX5_BRIDGE=y
CONFIG_MLX5_CLS_ACT=y
CONFIG_MLX5_TC_CT=y
CONFIG_MLX5_TC_SAMPLE=y
CONFIG_MLX5_CORE_EN_DCB=y
CONFIG_MLX5_CORE_IPOIB=y
CONFIG_MLX5_EN_MACSEC=y
CONFIG_MLX5_EN_IPSEC=y
CONFIG_MLX5_EN_TLS=y
CONFIG_MLX5_SW_STEERING=y
CONFIG_MLX5_SF=y
CONFIG_MLX5_SF_MANAGER=y
CONFIG_MLXSW_CORE=m
CONFIG_MLXSW_CORE_HWMON=y
CONFIG_MLXSW_CORE_THERMAL=y
CONFIG_MLXSW_PCI=m
CONFIG_MLXSW_I2C=m
CONFIG_MLXSW_SPECTRUM=m
CONFIG_MLXSW_SPECTRUM_DCB=y
CONFIG_MLXSW_MINIMAL=m
CONFIG_MLXFW=m
CONFIG_NET_VENDOR_MICREL=y
CONFIG_KS8842=m
CONFIG_KS8851=m
CONFIG_KS8851_MLL=m
CONFIG_KSZ884X_PCI=m
CONFIG_NET_VENDOR_MICROCHIP=y
CONFIG_ENC28J60=m
CONFIG_ENC28J60_WRITEVERIFY=y
CONFIG_ENCX24J600=m
CONFIG_LAN743X=m
CONFIG_LAN966X_SWITCH=m
CONFIG_NET_VENDOR_MICROSEMI=y
CONFIG_MSCC_OCELOT_SWITCH_LIB=m
CONFIG_MSCC_OCELOT_SWITCH=m
CONFIG_NET_VENDOR_MICROSOFT=y
CONFIG_NET_VENDOR_MYRI=y
CONFIG_MYRI10GE=m
CONFIG_FEALNX=m
CONFIG_NET_VENDOR_NI=y
CONFIG_NI_XGE_MANAGEMENT_ENET=m
CONFIG_NET_VENDOR_NATSEMI=y
CONFIG_NATSEMI=m
CONFIG_NS83820=m
CONFIG_NET_VENDOR_NETERION=y
CONFIG_S2IO=m
CONFIG_NET_VENDOR_NETRONOME=y
CONFIG_NFP=m
CONFIG_NFP_APP_FLOWER=y
CONFIG_NFP_APP_ABM_NIC=y
CONFIG_NFP_DEBUG=y
CONFIG_NET_VENDOR_8390=y
CONFIG_PCMCIA_AXNET=m
CONFIG_NE2000=m
CONFIG_NE2K_PCI=m
CONFIG_PCMCIA_PCNET=m
CONFIG_ULTRA=m
CONFIG_WD80x3=m
CONFIG_NET_VENDOR_NVIDIA=y
CONFIG_FORCEDETH=m
CONFIG_NET_VENDOR_OKI=y
CONFIG_PCH_GBE=m
CONFIG_ETHOC=m
CONFIG_NET_VENDOR_PACKET_ENGINES=y
CONFIG_HAMACHI=m
CONFIG_YELLOWFIN=m
CONFIG_NET_VENDOR_PENSANDO=y
CONFIG_NET_VENDOR_QLOGIC=y
CONFIG_QLA3XXX=m
CONFIG_QLCNIC=m
CONFIG_QLCNIC_SRIOV=y
CONFIG_QLCNIC_DCB=y
CONFIG_QLCNIC_HWMON=y
CONFIG_NETXEN_NIC=m
CONFIG_QED=m
CONFIG_QED_LL2=y
CONFIG_QED_SRIOV=y
CONFIG_QEDE=m
CONFIG_QED_ISCSI=y
CONFIG_QED_FCOE=y
CONFIG_QED_OOO=y
CONFIG_NET_VENDOR_BROCADE=y
CONFIG_BNA=m
CONFIG_NET_VENDOR_QUALCOMM=y
CONFIG_QCA7000=m
CONFIG_QCA7000_SPI=m
CONFIG_QCA7000_UART=m
CONFIG_QCOM_EMAC=m
CONFIG_RMNET=m
CONFIG_NET_VENDOR_RDC=y
CONFIG_R6040=m
CONFIG_NET_VENDOR_REALTEK=y
CONFIG_ATP=m
CONFIG_8139CP=m
CONFIG_8139TOO=m
CONFIG_8139TOO_PIO=y
CONFIG_8139TOO_TUNE_TWISTER=y
CONFIG_8139TOO_8129=y
CONFIG_8139_OLD_RX_RESET=y
CONFIG_R8169=m
CONFIG_NET_VENDOR_RENESAS=y
CONFIG_NET_VENDOR_ROCKER=y
CONFIG_ROCKER=m
CONFIG_NET_VENDOR_SAMSUNG=y
CONFIG_SXGBE_ETH=m
CONFIG_NET_VENDOR_SEEQ=y
CONFIG_NET_VENDOR_SILAN=y
CONFIG_SC92031=m
CONFIG_NET_VENDOR_SIS=y
CONFIG_SIS900=m
CONFIG_SIS190=m
CONFIG_NET_VENDOR_SOLARFLARE=y
CONFIG_SFC=m
CONFIG_SFC_MTD=y
CONFIG_SFC_MCDI_MON=y
CONFIG_SFC_SRIOV=y
CONFIG_SFC_MCDI_LOGGING=y
CONFIG_SFC_FALCON=m
CONFIG_SFC_FALCON_MTD=y
CONFIG_SFC_SIENA=m
CONFIG_SFC_SIENA_MTD=y
CONFIG_SFC_SIENA_MCDI_MON=y
CONFIG_SFC_SIENA_SRIOV=y
CONFIG_SFC_SIENA_MCDI_LOGGING=y
CONFIG_NET_VENDOR_SMSC=y
CONFIG_SMC9194=m
CONFIG_PCMCIA_SMC91C92=m
CONFIG_EPIC100=m
CONFIG_SMSC911X=m
CONFIG_SMSC9420=m
CONFIG_NET_VENDOR_SOCIONEXT=y
CONFIG_NET_VENDOR_STMICRO=y
CONFIG_STMMAC_ETH=m
# CONFIG_STMMAC_SELFTESTS is not set
CONFIG_STMMAC_PLATFORM=m
CONFIG_DWMAC_DWC_QOS_ETH=m
CONFIG_DWMAC_GENERIC=m
CONFIG_DWMAC_INTEL_PLAT=m
CONFIG_DWMAC_INTEL=m
CONFIG_DWMAC_LOONGSON=m
CONFIG_STMMAC_PCI=m
CONFIG_NET_VENDOR_SUN=y
CONFIG_HAPPYMEAL=m
CONFIG_SUNGEM=m
CONFIG_CASSINI=m
CONFIG_NIU=m
CONFIG_NET_VENDOR_SYNOPSYS=y
CONFIG_DWC_XLGMAC=m
CONFIG_DWC_XLGMAC_PCI=m
CONFIG_NET_VENDOR_TEHUTI=y
CONFIG_TEHUTI=m
CONFIG_NET_VENDOR_TI=y
CONFIG_TI_CPSW_PHY_SEL=y
CONFIG_TLAN=m
CONFIG_NET_VENDOR_VERTEXCOM=y
CONFIG_MSE102X=m
CONFIG_NET_VENDOR_VIA=y
CONFIG_VIA_RHINE=m
CONFIG_VIA_RHINE_MMIO=y
CONFIG_VIA_VELOCITY=m
CONFIG_NET_VENDOR_WIZNET=y
CONFIG_WIZNET_W5100=m
CONFIG_WIZNET_W5300=m
# CONFIG_WIZNET_BUS_DIRECT is not set
# CONFIG_WIZNET_BUS_INDIRECT is not set
CONFIG_WIZNET_BUS_ANY=y
CONFIG_WIZNET_W5100_SPI=m
CONFIG_NET_VENDOR_XILINX=y
CONFIG_XILINX_EMACLITE=m
CONFIG_XILINX_AXI_EMAC=m
CONFIG_XILINX_LL_TEMAC=m
CONFIG_NET_VENDOR_XIRCOM=y
CONFIG_PCMCIA_XIRC2PS=m
CONFIG_FDDI=m
CONFIG_DEFXX=m
CONFIG_SKFP=m
CONFIG_HIPPI=y
CONFIG_ROADRUNNER=m
CONFIG_ROADRUNNER_LARGE_RINGS=y
CONFIG_NET_SB1000=m
CONFIG_PHYLINK=m
CONFIG_PHYLIB=m
CONFIG_SWPHY=y
CONFIG_LED_TRIGGER_PHY=y
CONFIG_FIXED_PHY=m
CONFIG_SFP=m

#
# MII PHY device drivers
#
# CONFIG_AMD_PHY is not set
CONFIG_ADIN_PHY=m
CONFIG_ADIN1100_PHY=m
CONFIG_AQUANTIA_PHY=m
CONFIG_AX88796B_PHY=m
CONFIG_BROADCOM_PHY=m
CONFIG_BCM54140_PHY=m
CONFIG_BCM7XXX_PHY=m
CONFIG_BCM84881_PHY=m
CONFIG_BCM87XX_PHY=m
CONFIG_BCM_NET_PHYLIB=m
CONFIG_BCM_NET_PHYPTP=m
CONFIG_CICADA_PHY=m
CONFIG_CORTINA_PHY=m
CONFIG_DAVICOM_PHY=m
CONFIG_ICPLUS_PHY=m
CONFIG_LXT_PHY=m
CONFIG_INTEL_XWAY_PHY=m
CONFIG_LSI_ET1011C_PHY=m
CONFIG_MARVELL_PHY=m
CONFIG_MARVELL_10G_PHY=m
CONFIG_MARVELL_88X2222_PHY=m
CONFIG_MAXLINEAR_GPHY=m
CONFIG_MEDIATEK_GE_PHY=m
CONFIG_MICREL_PHY=m
CONFIG_MICROCHIP_PHY=m
CONFIG_MICROCHIP_T1_PHY=m
CONFIG_MICROSEMI_PHY=m
CONFIG_MOTORCOMM_PHY=m
CONFIG_NATIONAL_PHY=m
CONFIG_NXP_C45_TJA11XX_PHY=m
CONFIG_NXP_TJA11XX_PHY=m
CONFIG_AT803X_PHY=m
CONFIG_QSEMI_PHY=m
CONFIG_REALTEK_PHY=m
CONFIG_RENESAS_PHY=m
CONFIG_ROCKCHIP_PHY=m
CONFIG_SMSC_PHY=m
CONFIG_STE10XP=m
CONFIG_TERANETICS_PHY=m
CONFIG_DP83822_PHY=m
CONFIG_DP83TC811_PHY=m
CONFIG_DP83848_PHY=m
CONFIG_DP83867_PHY=m
CONFIG_DP83869_PHY=m
CONFIG_DP83TD510_PHY=m
CONFIG_VITESSE_PHY=m
CONFIG_XILINX_GMII2RGMII=m
CONFIG_MICREL_KS8995MA=m
CONFIG_PSE_CONTROLLER=y
CONFIG_PSE_REGULATOR=m
CONFIG_CAN_DEV=m
CONFIG_CAN_VCAN=m
CONFIG_CAN_VXCAN=m
CONFIG_CAN_NETLINK=y
CONFIG_CAN_CALC_BITTIMING=y
CONFIG_CAN_RX_OFFLOAD=y
CONFIG_CAN_CAN327=m
CONFIG_CAN_FLEXCAN=m
CONFIG_CAN_GRCAN=m
CONFIG_CAN_JANZ_ICAN3=m
CONFIG_CAN_KVASER_PCIEFD=m
CONFIG_CAN_SLCAN=m
CONFIG_PCH_CAN=m
CONFIG_CAN_C_CAN=m
CONFIG_CAN_C_CAN_PLATFORM=m
CONFIG_CAN_C_CAN_PCI=m
CONFIG_CAN_CC770=m
CONFIG_CAN_CC770_ISA=m
CONFIG_CAN_CC770_PLATFORM=m
CONFIG_CAN_CTUCANFD=m
CONFIG_CAN_CTUCANFD_PCI=m
CONFIG_CAN_CTUCANFD_PLATFORM=m
CONFIG_CAN_IFI_CANFD=m
CONFIG_CAN_M_CAN=m
CONFIG_CAN_M_CAN_PCI=m
CONFIG_CAN_M_CAN_PLATFORM=m
CONFIG_CAN_M_CAN_TCAN4X5X=m
CONFIG_CAN_PEAK_PCIEFD=m
CONFIG_CAN_SJA1000=m
CONFIG_CAN_EMS_PCI=m
CONFIG_CAN_EMS_PCMCIA=m
CONFIG_CAN_F81601=m
CONFIG_CAN_KVASER_PCI=m
CONFIG_CAN_PEAK_PCI=m
CONFIG_CAN_PEAK_PCIEC=y
CONFIG_CAN_PEAK_PCMCIA=m
CONFIG_CAN_PLX_PCI=m
CONFIG_CAN_SJA1000_ISA=m
CONFIG_CAN_SJA1000_PLATFORM=m
CONFIG_CAN_TSCAN1=m
CONFIG_CAN_SOFTING=m
CONFIG_CAN_SOFTING_CS=m

#
# CAN SPI interfaces
#
CONFIG_CAN_HI311X=m
CONFIG_CAN_MCP251X=m
CONFIG_CAN_MCP251XFD=m
CONFIG_CAN_MCP251XFD_SANITY=y
# end of CAN SPI interfaces

#
# CAN USB interfaces
#
CONFIG_CAN_8DEV_USB=m
CONFIG_CAN_EMS_USB=m
CONFIG_CAN_ESD_USB=m
CONFIG_CAN_ETAS_ES58X=m
CONFIG_CAN_GS_USB=m
CONFIG_CAN_KVASER_USB=m
CONFIG_CAN_MCBA_USB=m
CONFIG_CAN_PEAK_USB=m
CONFIG_CAN_UCAN=m
# end of CAN USB interfaces

# CONFIG_CAN_DEBUG_DEVICES is not set

#
# MCTP Device Drivers
#
CONFIG_MCTP_SERIAL=m
CONFIG_MCTP_TRANSPORT_I2C=m
# end of MCTP Device Drivers

CONFIG_MDIO_DEVICE=m
CONFIG_MDIO_BUS=m
CONFIG_FWNODE_MDIO=m
CONFIG_OF_MDIO=m
CONFIG_ACPI_MDIO=m
CONFIG_MDIO_DEVRES=m
CONFIG_MDIO_BITBANG=m
CONFIG_MDIO_BCM_UNIMAC=m
CONFIG_MDIO_GPIO=m
CONFIG_MDIO_HISI_FEMAC=m
CONFIG_MDIO_I2C=m
CONFIG_MDIO_MVUSB=m
CONFIG_MDIO_MSCC_MIIM=m
CONFIG_MDIO_IPQ4019=m
CONFIG_MDIO_IPQ8064=m

#
# MDIO Multiplexers
#
CONFIG_MDIO_BUS_MUX=m
CONFIG_MDIO_BUS_MUX_GPIO=m
CONFIG_MDIO_BUS_MUX_MULTIPLEXER=m
CONFIG_MDIO_BUS_MUX_MMIOREG=m

#
# PCS device drivers
#
CONFIG_PCS_XPCS=m
CONFIG_PCS_LYNX=m
CONFIG_PCS_ALTERA_TSE=m
# end of PCS device drivers

CONFIG_PLIP=m
CONFIG_PPP=m
CONFIG_PPP_BSDCOMP=m
CONFIG_PPP_DEFLATE=m
CONFIG_PPP_FILTER=y
CONFIG_PPP_MPPE=m
CONFIG_PPP_MULTILINK=y
CONFIG_PPPOATM=m
CONFIG_PPPOE=m
CONFIG_PPTP=m
CONFIG_PPPOL2TP=m
CONFIG_PPP_ASYNC=m
CONFIG_PPP_SYNC_TTY=m
CONFIG_SLIP=m
CONFIG_SLHC=m
CONFIG_SLIP_COMPRESSED=y
CONFIG_SLIP_SMART=y
CONFIG_SLIP_MODE_SLIP6=y

#
# Host-side USB support is needed for USB Network Adapter support
#
CONFIG_USB_NET_DRIVERS=m
CONFIG_USB_CATC=m
CONFIG_USB_KAWETH=m
CONFIG_USB_PEGASUS=m
CONFIG_USB_RTL8150=m
CONFIG_USB_RTL8152=m
CONFIG_USB_LAN78XX=m
CONFIG_USB_USBNET=m
CONFIG_USB_NET_AX8817X=m
CONFIG_USB_NET_AX88179_178A=m
CONFIG_USB_NET_CDCETHER=m
CONFIG_USB_NET_CDC_EEM=m
CONFIG_USB_NET_CDC_NCM=m
CONFIG_USB_NET_HUAWEI_CDC_NCM=m
CONFIG_USB_NET_CDC_MBIM=m
CONFIG_USB_NET_DM9601=m
CONFIG_USB_NET_SR9700=m
CONFIG_USB_NET_SR9800=m
CONFIG_USB_NET_SMSC75XX=m
CONFIG_USB_NET_SMSC95XX=m
CONFIG_USB_NET_GL620A=m
CONFIG_USB_NET_NET1080=m
CONFIG_USB_NET_PLUSB=m
CONFIG_USB_NET_MCS7830=m
CONFIG_USB_NET_RNDIS_HOST=m
CONFIG_USB_NET_CDC_SUBSET_ENABLE=m
CONFIG_USB_NET_CDC_SUBSET=m
CONFIG_USB_ALI_M5632=y
CONFIG_USB_AN2720=y
CONFIG_USB_BELKIN=y
CONFIG_USB_ARMLINUX=y
CONFIG_USB_EPSON2888=y
CONFIG_USB_KC2190=y
CONFIG_USB_NET_ZAURUS=m
CONFIG_USB_NET_CX82310_ETH=m
CONFIG_USB_NET_KALMIA=m
CONFIG_USB_NET_QMI_WWAN=m
CONFIG_USB_HSO=m
CONFIG_USB_NET_INT51X1=m
CONFIG_USB_CDC_PHONET=m
CONFIG_USB_IPHETH=m
CONFIG_USB_SIERRA_NET=m
CONFIG_USB_VL600=m
CONFIG_USB_NET_CH9200=m
CONFIG_USB_NET_AQC111=m
CONFIG_USB_RTL8153_ECM=m
CONFIG_WLAN=y
CONFIG_WLAN_VENDOR_ADMTEK=y
CONFIG_ADM8211=m
CONFIG_ATH_COMMON=m
CONFIG_WLAN_VENDOR_ATH=y
CONFIG_ATH_DEBUG=y
CONFIG_ATH_TRACEPOINTS=y
CONFIG_ATH_REG_DYNAMIC_USER_REG_HINTS=y
CONFIG_ATH_REG_DYNAMIC_USER_CERT_TESTING=y
CONFIG_ATH5K=m
CONFIG_ATH5K_DEBUG=y
CONFIG_ATH5K_TRACER=y
CONFIG_ATH5K_PCI=y
# CONFIG_ATH5K_TEST_CHANNELS is not set
CONFIG_ATH9K_HW=m
CONFIG_ATH9K_COMMON=m
CONFIG_ATH9K_COMMON_DEBUG=y
CONFIG_ATH9K_DFS_DEBUGFS=y
CONFIG_ATH9K_BTCOEX_SUPPORT=y
CONFIG_ATH9K=m
CONFIG_ATH9K_PCI=y
CONFIG_ATH9K_AHB=y
CONFIG_ATH9K_DEBUGFS=y
CONFIG_ATH9K_STATION_STATISTICS=y
CONFIG_ATH9K_TX99=y
CONFIG_ATH9K_DFS_CERTIFIED=y
CONFIG_ATH9K_DYNACK=y
CONFIG_ATH9K_WOW=y
CONFIG_ATH9K_RFKILL=y
CONFIG_ATH9K_CHANNEL_CONTEXT=y
CONFIG_ATH9K_PCOEM=y
CONFIG_ATH9K_PCI_NO_EEPROM=m
CONFIG_ATH9K_HTC=m
CONFIG_ATH9K_HTC_DEBUGFS=y
CONFIG_ATH9K_HWRNG=y
CONFIG_ATH9K_COMMON_SPECTRAL=y
CONFIG_CARL9170=m
CONFIG_CARL9170_LEDS=y
CONFIG_CARL9170_DEBUGFS=y
CONFIG_CARL9170_WPC=y
CONFIG_CARL9170_HWRNG=y
CONFIG_ATH6KL=m
CONFIG_ATH6KL_SDIO=m
CONFIG_ATH6KL_USB=m
CONFIG_ATH6KL_DEBUG=y
CONFIG_ATH6KL_TRACING=y
CONFIG_ATH6KL_REGDOMAIN=y
CONFIG_AR5523=m
CONFIG_WIL6210=m
CONFIG_WIL6210_ISR_COR=y
CONFIG_WIL6210_TRACING=y
CONFIG_WIL6210_DEBUGFS=y
CONFIG_ATH10K=m
CONFIG_ATH10K_CE=y
CONFIG_ATH10K_PCI=m
CONFIG_ATH10K_AHB=y
CONFIG_ATH10K_SDIO=m
CONFIG_ATH10K_USB=m
CONFIG_ATH10K_DEBUG=y
CONFIG_ATH10K_DEBUGFS=y
CONFIG_ATH10K_SPECTRAL=y
CONFIG_ATH10K_TRACING=y
CONFIG_ATH10K_DFS_CERTIFIED=y
CONFIG_WCN36XX=m
CONFIG_WCN36XX_DEBUGFS=y
CONFIG_ATH11K=m
CONFIG_ATH11K_AHB=m
CONFIG_ATH11K_PCI=m
CONFIG_ATH11K_DEBUG=y
CONFIG_ATH11K_DEBUGFS=y
CONFIG_ATH11K_TRACING=y
CONFIG_ATH11K_SPECTRAL=y
CONFIG_WLAN_VENDOR_ATMEL=y
CONFIG_ATMEL=m
CONFIG_PCI_ATMEL=m
CONFIG_PCMCIA_ATMEL=m
CONFIG_AT76C50X_USB=m
CONFIG_WLAN_VENDOR_BROADCOM=y
CONFIG_B43=m
CONFIG_B43_BCMA=y
CONFIG_B43_SSB=y
CONFIG_B43_BUSES_BCMA_AND_SSB=y
# CONFIG_B43_BUSES_BCMA is not set
# CONFIG_B43_BUSES_SSB is not set
CONFIG_B43_PCI_AUTOSELECT=y
CONFIG_B43_PCICORE_AUTOSELECT=y
CONFIG_B43_SDIO=y
CONFIG_B43_BCMA_PIO=y
CONFIG_B43_PIO=y
CONFIG_B43_PHY_G=y
CONFIG_B43_PHY_N=y
CONFIG_B43_PHY_LP=y
CONFIG_B43_PHY_HT=y
CONFIG_B43_LEDS=y
CONFIG_B43_HWRNG=y
CONFIG_B43_DEBUG=y
CONFIG_B43LEGACY=m
CONFIG_B43LEGACY_PCI_AUTOSELECT=y
CONFIG_B43LEGACY_PCICORE_AUTOSELECT=y
CONFIG_B43LEGACY_LEDS=y
CONFIG_B43LEGACY_HWRNG=y
CONFIG_B43LEGACY_DEBUG=y
CONFIG_B43LEGACY_DMA=y
CONFIG_B43LEGACY_PIO=y
CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y
# CONFIG_B43LEGACY_DMA_MODE is not set
# CONFIG_B43LEGACY_PIO_MODE is not set
CONFIG_BRCMUTIL=m
CONFIG_BRCMSMAC=m
CONFIG_BRCMSMAC_LEDS=y
CONFIG_BRCMFMAC=m
CONFIG_BRCMFMAC_PROTO_BCDC=y
CONFIG_BRCMFMAC_PROTO_MSGBUF=y
CONFIG_BRCMFMAC_SDIO=y
CONFIG_BRCMFMAC_USB=y
CONFIG_BRCMFMAC_PCIE=y
CONFIG_BRCM_TRACING=y
CONFIG_BRCMDBG=y
CONFIG_WLAN_VENDOR_CISCO=y
CONFIG_AIRO=m
CONFIG_AIRO_CS=m
CONFIG_WLAN_VENDOR_INTEL=y
CONFIG_IPW2100=m
CONFIG_IPW2100_MONITOR=y
CONFIG_IPW2100_DEBUG=y
CONFIG_IPW2200=m
CONFIG_IPW2200_MONITOR=y
CONFIG_IPW2200_RADIOTAP=y
CONFIG_IPW2200_PROMISCUOUS=y
CONFIG_IPW2200_QOS=y
CONFIG_IPW2200_DEBUG=y
CONFIG_LIBIPW=m
CONFIG_LIBIPW_DEBUG=y
CONFIG_IWLEGACY=m
CONFIG_IWL4965=m
CONFIG_IWL3945=m

#
# iwl3945 / iwl4965 Debugging Options
#
CONFIG_IWLEGACY_DEBUG=y
CONFIG_IWLEGACY_DEBUGFS=y
# end of iwl3945 / iwl4965 Debugging Options

CONFIG_IWLWIFI=m
CONFIG_IWLWIFI_LEDS=y
CONFIG_IWLDVM=m
CONFIG_IWLMVM=m
CONFIG_IWLWIFI_OPMODE_MODULAR=y

#
# Debugging Options
#
CONFIG_IWLWIFI_DEBUG=y
CONFIG_IWLWIFI_DEBUGFS=y
CONFIG_IWLWIFI_DEVICE_TRACING=y
# end of Debugging Options

CONFIG_WLAN_VENDOR_INTERSIL=y
CONFIG_HOSTAP=m
CONFIG_HOSTAP_FIRMWARE=y
CONFIG_HOSTAP_FIRMWARE_NVRAM=y
CONFIG_HOSTAP_PLX=m
CONFIG_HOSTAP_PCI=m
CONFIG_HOSTAP_CS=m
CONFIG_HERMES=m
CONFIG_HERMES_PRISM=y
CONFIG_HERMES_CACHE_FW_ON_INIT=y
CONFIG_PLX_HERMES=m
CONFIG_TMD_HERMES=m
CONFIG_NORTEL_HERMES=m
CONFIG_PCI_HERMES=m
CONFIG_PCMCIA_HERMES=m
CONFIG_PCMCIA_SPECTRUM=m
CONFIG_ORINOCO_USB=m
CONFIG_P54_COMMON=m
CONFIG_P54_USB=m
CONFIG_P54_PCI=m
CONFIG_P54_SPI=m
CONFIG_P54_SPI_DEFAULT_EEPROM=y
CONFIG_P54_LEDS=y
CONFIG_WLAN_VENDOR_MARVELL=y
CONFIG_LIBERTAS=m
CONFIG_LIBERTAS_USB=m
CONFIG_LIBERTAS_CS=m
CONFIG_LIBERTAS_SDIO=m
CONFIG_LIBERTAS_SPI=m
CONFIG_LIBERTAS_DEBUG=y
CONFIG_LIBERTAS_MESH=y
CONFIG_LIBERTAS_THINFIRM=m
CONFIG_LIBERTAS_THINFIRM_DEBUG=y
CONFIG_LIBERTAS_THINFIRM_USB=m
CONFIG_MWIFIEX=m
CONFIG_MWIFIEX_SDIO=m
CONFIG_MWIFIEX_PCIE=m
CONFIG_MWIFIEX_USB=m
CONFIG_MWL8K=m
CONFIG_WLAN_VENDOR_MEDIATEK=y
CONFIG_MT7601U=m
CONFIG_MT76_CORE=m
CONFIG_MT76_LEDS=y
CONFIG_MT76_USB=m
CONFIG_MT76_SDIO=m
CONFIG_MT76x02_LIB=m
CONFIG_MT76x02_USB=m
CONFIG_MT76_CONNAC_LIB=m
CONFIG_MT76x0_COMMON=m
CONFIG_MT76x0U=m
CONFIG_MT76x0E=m
CONFIG_MT76x2_COMMON=m
CONFIG_MT76x2E=m
CONFIG_MT76x2U=m
CONFIG_MT7603E=m
CONFIG_MT7615_COMMON=m
CONFIG_MT7615E=m
CONFIG_MT7663_USB_SDIO_COMMON=m
CONFIG_MT7663U=m
CONFIG_MT7663S=m
CONFIG_MT7915E=m
CONFIG_MT7921_COMMON=m
CONFIG_MT7921E=m
CONFIG_MT7921S=m
CONFIG_MT7921U=m
CONFIG_WLAN_VENDOR_MICROCHIP=y
CONFIG_WILC1000=m
CONFIG_WILC1000_SDIO=m
CONFIG_WILC1000_SPI=m
CONFIG_WILC1000_HW_OOB_INTR=y
CONFIG_WLAN_VENDOR_PURELIFI=y
CONFIG_PLFXLC=m
CONFIG_WLAN_VENDOR_RALINK=y
CONFIG_RT2X00=m
CONFIG_RT2400PCI=m
CONFIG_RT2500PCI=m
CONFIG_RT61PCI=m
CONFIG_RT2800PCI=m
CONFIG_RT2800PCI_RT33XX=y
CONFIG_RT2800PCI_RT35XX=y
CONFIG_RT2800PCI_RT53XX=y
CONFIG_RT2800PCI_RT3290=y
CONFIG_RT2500USB=m
CONFIG_RT73USB=m
CONFIG_RT2800USB=m
CONFIG_RT2800USB_RT33XX=y
CONFIG_RT2800USB_RT35XX=y
CONFIG_RT2800USB_RT3573=y
CONFIG_RT2800USB_RT53XX=y
CONFIG_RT2800USB_RT55XX=y
CONFIG_RT2800USB_UNKNOWN=y
CONFIG_RT2800_LIB=m
CONFIG_RT2800_LIB_MMIO=m
CONFIG_RT2X00_LIB_MMIO=m
CONFIG_RT2X00_LIB_PCI=m
CONFIG_RT2X00_LIB_USB=m
CONFIG_RT2X00_LIB=m
CONFIG_RT2X00_LIB_FIRMWARE=y
CONFIG_RT2X00_LIB_CRYPTO=y
CONFIG_RT2X00_LIB_LEDS=y
CONFIG_RT2X00_LIB_DEBUGFS=y
CONFIG_RT2X00_DEBUG=y
CONFIG_WLAN_VENDOR_REALTEK=y
CONFIG_RTL8180=m
CONFIG_RTL8187=m
CONFIG_RTL8187_LEDS=y
CONFIG_RTL_CARDS=m
CONFIG_RTL8192CE=m
CONFIG_RTL8192SE=m
CONFIG_RTL8192DE=m
CONFIG_RTL8723AE=m
CONFIG_RTL8723BE=m
CONFIG_RTL8188EE=m
CONFIG_RTL8192EE=m
CONFIG_RTL8821AE=m
CONFIG_RTL8192CU=m
CONFIG_RTLWIFI=m
CONFIG_RTLWIFI_PCI=m
CONFIG_RTLWIFI_USB=m
CONFIG_RTLWIFI_DEBUG=y
CONFIG_RTL8192C_COMMON=m
CONFIG_RTL8723_COMMON=m
CONFIG_RTLBTCOEXIST=m
CONFIG_RTL8XXXU=m
CONFIG_RTL8XXXU_UNTESTED=y
CONFIG_RTW88=m
CONFIG_RTW88_CORE=m
CONFIG_RTW88_PCI=m
CONFIG_RTW88_8822B=m
CONFIG_RTW88_8822C=m
CONFIG_RTW88_8723D=m
CONFIG_RTW88_8821C=m
CONFIG_RTW88_8822BE=m
CONFIG_RTW88_8822CE=m
CONFIG_RTW88_8723DE=m
CONFIG_RTW88_8821CE=m
CONFIG_RTW88_DEBUG=y
CONFIG_RTW88_DEBUGFS=y
CONFIG_RTW89=m
CONFIG_RTW89_CORE=m
CONFIG_RTW89_PCI=m
CONFIG_RTW89_8852A=m
CONFIG_RTW89_8852C=m
CONFIG_RTW89_8852AE=m
CONFIG_RTW89_8852CE=m
CONFIG_RTW89_DEBUG=y
CONFIG_RTW89_DEBUGMSG=y
CONFIG_RTW89_DEBUGFS=y
CONFIG_WLAN_VENDOR_RSI=y
CONFIG_RSI_91X=m
CONFIG_RSI_DEBUGFS=y
CONFIG_RSI_SDIO=m
CONFIG_RSI_USB=m
CONFIG_RSI_COEX=y
CONFIG_WLAN_VENDOR_SILABS=y
CONFIG_WFX=m
CONFIG_WLAN_VENDOR_ST=y
CONFIG_CW1200=m
CONFIG_CW1200_WLAN_SDIO=m
CONFIG_CW1200_WLAN_SPI=m
CONFIG_WLAN_VENDOR_TI=y
CONFIG_WL1251=m
CONFIG_WL1251_SPI=m
CONFIG_WL1251_SDIO=m
CONFIG_WL12XX=m
CONFIG_WL18XX=m
CONFIG_WLCORE=m
CONFIG_WLCORE_SPI=m
CONFIG_WLCORE_SDIO=m
CONFIG_WILINK_PLATFORM_DATA=y
CONFIG_WLAN_VENDOR_ZYDAS=y
CONFIG_USB_ZD1201=m
CONFIG_ZD1211RW=m
CONFIG_ZD1211RW_DEBUG=y
CONFIG_WLAN_VENDOR_QUANTENNA=y
CONFIG_QTNFMAC=m
CONFIG_QTNFMAC_PCIE=m
CONFIG_PCMCIA_RAYCS=m
CONFIG_PCMCIA_WL3501=m
CONFIG_MAC80211_HWSIM=m
CONFIG_USB_NET_RNDIS_WLAN=m
CONFIG_VIRT_WIFI=m
CONFIG_WAN=y
CONFIG_HDLC=m
CONFIG_HDLC_RAW=m
CONFIG_HDLC_RAW_ETH=m
CONFIG_HDLC_CISCO=m
CONFIG_HDLC_FR=m
CONFIG_HDLC_PPP=m
CONFIG_HDLC_X25=m
CONFIG_PCI200SYN=m
CONFIG_WANXL=m
CONFIG_PC300TOO=m
CONFIG_N2=m
CONFIG_C101=m
CONFIG_FARSYNC=m
CONFIG_LAPBETHER=m
CONFIG_IEEE802154_DRIVERS=m
CONFIG_IEEE802154_FAKELB=m
CONFIG_IEEE802154_AT86RF230=m
CONFIG_IEEE802154_MRF24J40=m
CONFIG_IEEE802154_CC2520=m
CONFIG_IEEE802154_ATUSB=m
CONFIG_IEEE802154_ADF7242=m
CONFIG_IEEE802154_CA8210=m
CONFIG_IEEE802154_CA8210_DEBUGFS=y
CONFIG_IEEE802154_MCR20A=m
CONFIG_IEEE802154_HWSIM=m

#
# Wireless WAN
#
CONFIG_WWAN=m
CONFIG_WWAN_DEBUGFS=y
CONFIG_WWAN_HWSIM=m
CONFIG_MHI_WWAN_CTRL=m
CONFIG_MHI_WWAN_MBIM=m
CONFIG_RPMSG_WWAN_CTRL=m
CONFIG_IOSM=m
CONFIG_MTK_T7XX=m
# end of Wireless WAN

CONFIG_VMXNET3=m
CONFIG_FUJITSU_ES=m
CONFIG_USB4_NET=m
CONFIG_HYPERV_NET=m
CONFIG_NETDEVSIM=m
CONFIG_NET_FAILOVER=m
CONFIG_NETDEV_LEGACY_INIT=y
CONFIG_ISDN=y
CONFIG_ISDN_CAPI=y
CONFIG_CAPI_TRACE=y
CONFIG_ISDN_CAPI_MIDDLEWARE=y
CONFIG_MISDN=m
CONFIG_MISDN_DSP=m
CONFIG_MISDN_L1OIP=m

#
# mISDN hardware drivers
#
CONFIG_MISDN_HFCPCI=m
CONFIG_MISDN_HFCMULTI=m
CONFIG_MISDN_HFCUSB=m
CONFIG_MISDN_AVMFRITZ=m
CONFIG_MISDN_SPEEDFAX=m
CONFIG_MISDN_INFINEON=m
CONFIG_MISDN_W6692=m
CONFIG_MISDN_NETJET=m
CONFIG_MISDN_HDLC=m
CONFIG_MISDN_IPAC=m
CONFIG_MISDN_ISAR=m

#
# Input device support
#
CONFIG_INPUT=y
CONFIG_INPUT_LEDS=m
CONFIG_INPUT_FF_MEMLESS=m
CONFIG_INPUT_SPARSEKMAP=m
CONFIG_INPUT_MATRIXKMAP=m
CONFIG_INPUT_VIVALDIFMAP=y

#
# Userland interfaces
#
CONFIG_INPUT_MOUSEDEV=m
CONFIG_INPUT_MOUSEDEV_PSAUX=y
CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
CONFIG_INPUT_JOYDEV=m
CONFIG_INPUT_EVDEV=m
CONFIG_INPUT_EVBUG=m

#
# Input Device Drivers
#
CONFIG_INPUT_KEYBOARD=y
CONFIG_KEYBOARD_ADC=m
CONFIG_KEYBOARD_ADP5520=m
CONFIG_KEYBOARD_ADP5588=m
CONFIG_KEYBOARD_ADP5589=m
CONFIG_KEYBOARD_APPLESPI=m
CONFIG_KEYBOARD_ATKBD=y
CONFIG_KEYBOARD_QT1050=m
CONFIG_KEYBOARD_QT1070=m
CONFIG_KEYBOARD_QT2160=m
CONFIG_KEYBOARD_DLINK_DIR685=m
CONFIG_KEYBOARD_LKKBD=m
CONFIG_KEYBOARD_GPIO=m
CONFIG_KEYBOARD_GPIO_POLLED=m
CONFIG_KEYBOARD_TCA6416=m
CONFIG_KEYBOARD_TCA8418=m
CONFIG_KEYBOARD_MATRIX=m
CONFIG_KEYBOARD_LM8323=m
CONFIG_KEYBOARD_LM8333=m
CONFIG_KEYBOARD_MAX7359=m
CONFIG_KEYBOARD_MCS=m
CONFIG_KEYBOARD_MPR121=m
CONFIG_KEYBOARD_NEWTON=m
CONFIG_KEYBOARD_OPENCORES=m
CONFIG_KEYBOARD_SAMSUNG=m
CONFIG_KEYBOARD_GOLDFISH_EVENTS=m
CONFIG_KEYBOARD_STOWAWAY=m
CONFIG_KEYBOARD_SUNKBD=m
CONFIG_KEYBOARD_STMPE=m
CONFIG_KEYBOARD_IQS62X=m
CONFIG_KEYBOARD_OMAP4=m
CONFIG_KEYBOARD_TC3589X=m
CONFIG_KEYBOARD_TM2_TOUCHKEY=m
CONFIG_KEYBOARD_TWL4030=m
CONFIG_KEYBOARD_XTKBD=m
CONFIG_KEYBOARD_CROS_EC=m
CONFIG_KEYBOARD_CAP11XX=m
CONFIG_KEYBOARD_BCM=m
CONFIG_KEYBOARD_MTK_PMIC=m
CONFIG_KEYBOARD_CYPRESS_SF=m
CONFIG_INPUT_MOUSE=y
CONFIG_MOUSE_PS2=m
CONFIG_MOUSE_PS2_ALPS=y
CONFIG_MOUSE_PS2_BYD=y
CONFIG_MOUSE_PS2_LOGIPS2PP=y
CONFIG_MOUSE_PS2_SYNAPTICS=y
CONFIG_MOUSE_PS2_SYNAPTICS_SMBUS=y
CONFIG_MOUSE_PS2_CYPRESS=y
CONFIG_MOUSE_PS2_LIFEBOOK=y
CONFIG_MOUSE_PS2_TRACKPOINT=y
CONFIG_MOUSE_PS2_ELANTECH=y
CONFIG_MOUSE_PS2_ELANTECH_SMBUS=y
CONFIG_MOUSE_PS2_SENTELIC=y
CONFIG_MOUSE_PS2_TOUCHKIT=y
CONFIG_MOUSE_PS2_OLPC=y
CONFIG_MOUSE_PS2_FOCALTECH=y
CONFIG_MOUSE_PS2_VMMOUSE=y
CONFIG_MOUSE_PS2_SMBUS=y
CONFIG_MOUSE_SERIAL=m
CONFIG_MOUSE_APPLETOUCH=m
CONFIG_MOUSE_BCM5974=m
CONFIG_MOUSE_CYAPA=m
CONFIG_MOUSE_ELAN_I2C=m
CONFIG_MOUSE_ELAN_I2C_I2C=y
CONFIG_MOUSE_ELAN_I2C_SMBUS=y
CONFIG_MOUSE_INPORT=m
CONFIG_MOUSE_ATIXL=y
CONFIG_MOUSE_LOGIBM=m
CONFIG_MOUSE_PC110PAD=m
CONFIG_MOUSE_VSXXXAA=m
CONFIG_MOUSE_GPIO=m
CONFIG_MOUSE_SYNAPTICS_I2C=m
CONFIG_MOUSE_SYNAPTICS_USB=m
CONFIG_INPUT_JOYSTICK=y
CONFIG_JOYSTICK_ANALOG=m
CONFIG_JOYSTICK_A3D=m
CONFIG_JOYSTICK_ADC=m
CONFIG_JOYSTICK_ADI=m
CONFIG_JOYSTICK_COBRA=m
CONFIG_JOYSTICK_GF2K=m
CONFIG_JOYSTICK_GRIP=m
CONFIG_JOYSTICK_GRIP_MP=m
CONFIG_JOYSTICK_GUILLEMOT=m
CONFIG_JOYSTICK_INTERACT=m
CONFIG_JOYSTICK_SIDEWINDER=m
CONFIG_JOYSTICK_TMDC=m
CONFIG_JOYSTICK_IFORCE=m
CONFIG_JOYSTICK_IFORCE_USB=m
CONFIG_JOYSTICK_IFORCE_232=m
CONFIG_JOYSTICK_WARRIOR=m
CONFIG_JOYSTICK_MAGELLAN=m
CONFIG_JOYSTICK_SPACEORB=m
CONFIG_JOYSTICK_SPACEBALL=m
CONFIG_JOYSTICK_STINGER=m
CONFIG_JOYSTICK_TWIDJOY=m
CONFIG_JOYSTICK_ZHENHUA=m
CONFIG_JOYSTICK_DB9=m
CONFIG_JOYSTICK_GAMECON=m
CONFIG_JOYSTICK_TURBOGRAFX=m
CONFIG_JOYSTICK_AS5011=m
CONFIG_JOYSTICK_JOYDUMP=m
CONFIG_JOYSTICK_XPAD=m
CONFIG_JOYSTICK_XPAD_FF=y
CONFIG_JOYSTICK_XPAD_LEDS=y
CONFIG_JOYSTICK_WALKERA0701=m
CONFIG_JOYSTICK_PSXPAD_SPI=m
CONFIG_JOYSTICK_PSXPAD_SPI_FF=y
CONFIG_JOYSTICK_PXRC=m
CONFIG_JOYSTICK_QWIIC=m
CONFIG_JOYSTICK_FSIA6B=m
CONFIG_JOYSTICK_SENSEHAT=m
CONFIG_INPUT_TABLET=y
CONFIG_TABLET_USB_ACECAD=m
CONFIG_TABLET_USB_AIPTEK=m
CONFIG_TABLET_USB_HANWANG=m
CONFIG_TABLET_USB_KBTAB=m
CONFIG_TABLET_USB_PEGASUS=m
CONFIG_TABLET_SERIAL_WACOM4=m
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_TOUCHSCREEN_88PM860X=m
CONFIG_TOUCHSCREEN_ADS7846=m
CONFIG_TOUCHSCREEN_AD7877=m
CONFIG_TOUCHSCREEN_AD7879=m
CONFIG_TOUCHSCREEN_AD7879_I2C=m
CONFIG_TOUCHSCREEN_AD7879_SPI=m
CONFIG_TOUCHSCREEN_ADC=m
CONFIG_TOUCHSCREEN_AR1021_I2C=m
CONFIG_TOUCHSCREEN_ATMEL_MXT=m
CONFIG_TOUCHSCREEN_ATMEL_MXT_T37=y
CONFIG_TOUCHSCREEN_AUO_PIXCIR=m
CONFIG_TOUCHSCREEN_BU21013=m
CONFIG_TOUCHSCREEN_BU21029=m
CONFIG_TOUCHSCREEN_CHIPONE_ICN8318=m
CONFIG_TOUCHSCREEN_CHIPONE_ICN8505=m
CONFIG_TOUCHSCREEN_CY8CTMA140=m
CONFIG_TOUCHSCREEN_CY8CTMG110=m
CONFIG_TOUCHSCREEN_CYTTSP_CORE=m
CONFIG_TOUCHSCREEN_CYTTSP_I2C=m
CONFIG_TOUCHSCREEN_CYTTSP_SPI=m
CONFIG_TOUCHSCREEN_CYTTSP4_CORE=m
CONFIG_TOUCHSCREEN_CYTTSP4_I2C=m
CONFIG_TOUCHSCREEN_CYTTSP4_SPI=m
CONFIG_TOUCHSCREEN_DA9034=m
CONFIG_TOUCHSCREEN_DA9052=m
CONFIG_TOUCHSCREEN_DYNAPRO=m
CONFIG_TOUCHSCREEN_HAMPSHIRE=m
CONFIG_TOUCHSCREEN_EETI=m
CONFIG_TOUCHSCREEN_EGALAX=m
CONFIG_TOUCHSCREEN_EGALAX_SERIAL=m
CONFIG_TOUCHSCREEN_EXC3000=m
CONFIG_TOUCHSCREEN_FUJITSU=m
CONFIG_TOUCHSCREEN_GOODIX=m
CONFIG_TOUCHSCREEN_HIDEEP=m
CONFIG_TOUCHSCREEN_HYCON_HY46XX=m
CONFIG_TOUCHSCREEN_ILI210X=m
CONFIG_TOUCHSCREEN_ILITEK=m
CONFIG_TOUCHSCREEN_S6SY761=m
CONFIG_TOUCHSCREEN_GUNZE=m
CONFIG_TOUCHSCREEN_EKTF2127=m
CONFIG_TOUCHSCREEN_ELAN=m
CONFIG_TOUCHSCREEN_ELO=m
CONFIG_TOUCHSCREEN_WACOM_W8001=m
CONFIG_TOUCHSCREEN_WACOM_I2C=m
CONFIG_TOUCHSCREEN_MAX11801=m
CONFIG_TOUCHSCREEN_MCS5000=m
CONFIG_TOUCHSCREEN_MMS114=m
CONFIG_TOUCHSCREEN_MELFAS_MIP4=m
CONFIG_TOUCHSCREEN_MSG2638=m
CONFIG_TOUCHSCREEN_MTOUCH=m
CONFIG_TOUCHSCREEN_IMAGIS=m
CONFIG_TOUCHSCREEN_IMX6UL_TSC=m
CONFIG_TOUCHSCREEN_INEXIO=m
CONFIG_TOUCHSCREEN_MK712=m
CONFIG_TOUCHSCREEN_HTCPEN=m
CONFIG_TOUCHSCREEN_PENMOUNT=m
CONFIG_TOUCHSCREEN_EDT_FT5X06=m
CONFIG_TOUCHSCREEN_TOUCHRIGHT=m
CONFIG_TOUCHSCREEN_TOUCHWIN=m
CONFIG_TOUCHSCREEN_TI_AM335X_TSC=m
CONFIG_TOUCHSCREEN_UCB1400=m
CONFIG_TOUCHSCREEN_PIXCIR=m
CONFIG_TOUCHSCREEN_WDT87XX_I2C=m
CONFIG_TOUCHSCREEN_WM831X=m
CONFIG_TOUCHSCREEN_WM97XX=m
CONFIG_TOUCHSCREEN_WM9705=y
CONFIG_TOUCHSCREEN_WM9712=y
CONFIG_TOUCHSCREEN_WM9713=y
CONFIG_TOUCHSCREEN_USB_COMPOSITE=m
CONFIG_TOUCHSCREEN_MC13783=m
CONFIG_TOUCHSCREEN_USB_EGALAX=y
CONFIG_TOUCHSCREEN_USB_PANJIT=y
CONFIG_TOUCHSCREEN_USB_3M=y
CONFIG_TOUCHSCREEN_USB_ITM=y
CONFIG_TOUCHSCREEN_USB_ETURBO=y
CONFIG_TOUCHSCREEN_USB_GUNZE=y
CONFIG_TOUCHSCREEN_USB_DMC_TSC10=y
CONFIG_TOUCHSCREEN_USB_IRTOUCH=y
CONFIG_TOUCHSCREEN_USB_IDEALTEK=y
CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH=y
CONFIG_TOUCHSCREEN_USB_GOTOP=y
CONFIG_TOUCHSCREEN_USB_JASTEC=y
CONFIG_TOUCHSCREEN_USB_ELO=y
CONFIG_TOUCHSCREEN_USB_E2I=y
CONFIG_TOUCHSCREEN_USB_ZYTRONIC=y
CONFIG_TOUCHSCREEN_USB_ETT_TC45USB=y
CONFIG_TOUCHSCREEN_USB_NEXIO=y
CONFIG_TOUCHSCREEN_USB_EASYTOUCH=y
CONFIG_TOUCHSCREEN_TOUCHIT213=m
CONFIG_TOUCHSCREEN_TSC_SERIO=m
CONFIG_TOUCHSCREEN_TSC200X_CORE=m
CONFIG_TOUCHSCREEN_TSC2004=m
CONFIG_TOUCHSCREEN_TSC2005=m
CONFIG_TOUCHSCREEN_TSC2007=m
CONFIG_TOUCHSCREEN_TSC2007_IIO=y
CONFIG_TOUCHSCREEN_PCAP=m
CONFIG_TOUCHSCREEN_RM_TS=m
CONFIG_TOUCHSCREEN_SILEAD=m
CONFIG_TOUCHSCREEN_SIS_I2C=m
CONFIG_TOUCHSCREEN_ST1232=m
CONFIG_TOUCHSCREEN_STMFTS=m
CONFIG_TOUCHSCREEN_STMPE=m
CONFIG_TOUCHSCREEN_SUR40=m
CONFIG_TOUCHSCREEN_SURFACE3_SPI=m
CONFIG_TOUCHSCREEN_SX8654=m
CONFIG_TOUCHSCREEN_TPS6507X=m
CONFIG_TOUCHSCREEN_ZET6223=m
CONFIG_TOUCHSCREEN_ZFORCE=m
CONFIG_TOUCHSCREEN_COLIBRI_VF50=m
CONFIG_TOUCHSCREEN_ROHM_BU21023=m
CONFIG_TOUCHSCREEN_IQS5XX=m
CONFIG_TOUCHSCREEN_ZINITIX=m
CONFIG_INPUT_MISC=y
CONFIG_INPUT_88PM860X_ONKEY=m
CONFIG_INPUT_88PM80X_ONKEY=m
CONFIG_INPUT_AD714X=m
CONFIG_INPUT_AD714X_I2C=m
CONFIG_INPUT_AD714X_SPI=m
CONFIG_INPUT_ARIZONA_HAPTICS=m
CONFIG_INPUT_ATC260X_ONKEY=m
CONFIG_INPUT_ATMEL_CAPTOUCH=m
CONFIG_INPUT_BMA150=m
CONFIG_INPUT_E3X0_BUTTON=m
CONFIG_INPUT_PCSPKR=m
CONFIG_INPUT_MAX77650_ONKEY=m
CONFIG_INPUT_MAX77693_HAPTIC=m
CONFIG_INPUT_MAX8925_ONKEY=m
CONFIG_INPUT_MAX8997_HAPTIC=m
CONFIG_INPUT_MC13783_PWRBUTTON=m
CONFIG_INPUT_MMA8450=m
CONFIG_INPUT_APANEL=m
CONFIG_INPUT_GPIO_BEEPER=m
CONFIG_INPUT_GPIO_DECODER=m
CONFIG_INPUT_GPIO_VIBRA=m
CONFIG_INPUT_CPCAP_PWRBUTTON=m
CONFIG_INPUT_WISTRON_BTNS=m
CONFIG_INPUT_ATLAS_BTNS=m
CONFIG_INPUT_ATI_REMOTE2=m
CONFIG_INPUT_KEYSPAN_REMOTE=m
CONFIG_INPUT_KXTJ9=m
CONFIG_INPUT_POWERMATE=m
CONFIG_INPUT_YEALINK=m
CONFIG_INPUT_CM109=m
CONFIG_INPUT_REGULATOR_HAPTIC=m
CONFIG_INPUT_RETU_PWRBUTTON=m
CONFIG_INPUT_TPS65218_PWRBUTTON=m
CONFIG_INPUT_AXP20X_PEK=m
CONFIG_INPUT_TWL4030_PWRBUTTON=m
CONFIG_INPUT_TWL4030_VIBRA=m
CONFIG_INPUT_TWL6040_VIBRA=m
CONFIG_INPUT_UINPUT=m
CONFIG_INPUT_PALMAS_PWRBUTTON=m
CONFIG_INPUT_PCF50633_PMU=m
CONFIG_INPUT_PCF8574=m
CONFIG_INPUT_PWM_BEEPER=m
CONFIG_INPUT_PWM_VIBRA=m
CONFIG_INPUT_RK805_PWRKEY=m
CONFIG_INPUT_GPIO_ROTARY_ENCODER=m
CONFIG_INPUT_DA7280_HAPTICS=m
CONFIG_INPUT_DA9052_ONKEY=m
CONFIG_INPUT_DA9055_ONKEY=m
CONFIG_INPUT_DA9063_ONKEY=m
CONFIG_INPUT_WM831X_ON=m
CONFIG_INPUT_PCAP=m
CONFIG_INPUT_ADXL34X=m
CONFIG_INPUT_ADXL34X_I2C=m
CONFIG_INPUT_ADXL34X_SPI=m
CONFIG_INPUT_IMS_PCU=m
CONFIG_INPUT_IQS269A=m
CONFIG_INPUT_IQS626A=m
CONFIG_INPUT_IQS7222=m
CONFIG_INPUT_CMA3000=m
CONFIG_INPUT_CMA3000_I2C=m
CONFIG_INPUT_IDEAPAD_SLIDEBAR=m
CONFIG_INPUT_SOC_BUTTON_ARRAY=m
CONFIG_INPUT_DRV260X_HAPTICS=m
CONFIG_INPUT_DRV2665_HAPTICS=m
CONFIG_INPUT_DRV2667_HAPTICS=m
CONFIG_INPUT_RAVE_SP_PWRBUTTON=m
CONFIG_INPUT_STPMIC1_ONKEY=m
CONFIG_RMI4_CORE=m
CONFIG_RMI4_I2C=m
CONFIG_RMI4_SPI=m
CONFIG_RMI4_SMB=m
CONFIG_RMI4_F03=y
CONFIG_RMI4_F03_SERIO=m
CONFIG_RMI4_2D_SENSOR=y
CONFIG_RMI4_F11=y
CONFIG_RMI4_F12=y
CONFIG_RMI4_F30=y
CONFIG_RMI4_F34=y
CONFIG_RMI4_F3A=y
CONFIG_RMI4_F54=y
CONFIG_RMI4_F55=y

#
# Hardware I/O ports
#
CONFIG_SERIO=y
CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y
CONFIG_SERIO_I8042=y
CONFIG_SERIO_SERPORT=m
CONFIG_SERIO_CT82C710=m
CONFIG_SERIO_PARKBD=m
CONFIG_SERIO_PCIPS2=m
CONFIG_SERIO_LIBPS2=y
CONFIG_SERIO_RAW=m
CONFIG_SERIO_ALTERA_PS2=m
CONFIG_SERIO_PS2MULT=m
CONFIG_SERIO_ARC_PS2=m
CONFIG_SERIO_APBPS2=m
CONFIG_HYPERV_KEYBOARD=m
CONFIG_SERIO_GPIO_PS2=m
CONFIG_USERIO=m
CONFIG_GAMEPORT=m
CONFIG_GAMEPORT_NS558=m
CONFIG_GAMEPORT_L4=m
CONFIG_GAMEPORT_EMU10K1=m
CONFIG_GAMEPORT_FM801=m
# end of Hardware I/O ports
# end of Input device support

#
# Character devices
#
CONFIG_TTY=y
CONFIG_VT=y
CONFIG_CONSOLE_TRANSLATIONS=y
CONFIG_VT_CONSOLE=y
CONFIG_VT_CONSOLE_SLEEP=y
CONFIG_HW_CONSOLE=y
CONFIG_VT_HW_CONSOLE_BINDING=y
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
CONFIG_LDISC_AUTOLOAD=y

#
# Serial drivers
#
CONFIG_SERIAL_EARLYCON=y
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_DEPRECATED_OPTIONS=y
CONFIG_SERIAL_8250_PNP=y
CONFIG_SERIAL_8250_16550A_VARIANTS=y
CONFIG_SERIAL_8250_FINTEK=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_8250_DMA=y
CONFIG_SERIAL_8250_PCI=m
CONFIG_SERIAL_8250_EXAR=m
CONFIG_SERIAL_8250_CS=m
CONFIG_SERIAL_8250_MEN_MCB=m
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
CONFIG_SERIAL_8250_EXTENDED=y
CONFIG_SERIAL_8250_MANY_PORTS=y
CONFIG_SERIAL_8250_FOURPORT=m
CONFIG_SERIAL_8250_ACCENT=m
CONFIG_SERIAL_8250_BOCA=m
CONFIG_SERIAL_8250_EXAR_ST16C554=m
CONFIG_SERIAL_8250_HUB6=m
CONFIG_SERIAL_8250_SHARE_IRQ=y
CONFIG_SERIAL_8250_DETECT_IRQ=y
CONFIG_SERIAL_8250_RSA=y
CONFIG_SERIAL_8250_DWLIB=y
CONFIG_SERIAL_8250_DW=m
CONFIG_SERIAL_8250_RT288X=y
CONFIG_SERIAL_8250_LPSS=m
CONFIG_SERIAL_8250_MID=m
CONFIG_SERIAL_8250_PERICOM=m
CONFIG_SERIAL_OF_PLATFORM=m

#
# Non-8250 serial port support
#
CONFIG_SERIAL_MAX3100=m
CONFIG_SERIAL_MAX310X=m
CONFIG_SERIAL_UARTLITE=m
CONFIG_SERIAL_UARTLITE_NR_UARTS=1
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_SERIAL_JSM=m
CONFIG_SERIAL_SIFIVE=m
CONFIG_SERIAL_LANTIQ=m
CONFIG_SERIAL_SCCNXP=m
CONFIG_SERIAL_SC16IS7XX_CORE=m
CONFIG_SERIAL_SC16IS7XX=m
CONFIG_SERIAL_SC16IS7XX_I2C=y
CONFIG_SERIAL_SC16IS7XX_SPI=y
CONFIG_SERIAL_TIMBERDALE=m
CONFIG_SERIAL_ALTERA_JTAGUART=m
CONFIG_SERIAL_ALTERA_UART=m
CONFIG_SERIAL_ALTERA_UART_MAXPORTS=4
CONFIG_SERIAL_ALTERA_UART_BAUDRATE=115200
CONFIG_SERIAL_PCH_UART=m
CONFIG_SERIAL_XILINX_PS_UART=m
CONFIG_SERIAL_ARC=m
CONFIG_SERIAL_ARC_NR_PORTS=1
CONFIG_SERIAL_RP2=m
CONFIG_SERIAL_RP2_NR_UARTS=32
CONFIG_SERIAL_FSL_LPUART=m
CONFIG_SERIAL_FSL_LPUART_CONSOLE=y
CONFIG_SERIAL_FSL_LINFLEXUART=m
CONFIG_SERIAL_CONEXANT_DIGICOLOR=m
CONFIG_SERIAL_MEN_Z135=m
CONFIG_SERIAL_SPRD=m
CONFIG_SERIAL_LITEUART=m
CONFIG_SERIAL_LITEUART_MAX_PORTS=1
# end of Serial drivers

CONFIG_SERIAL_MCTRL_GPIO=y
CONFIG_SERIAL_NONSTANDARD=y
CONFIG_MOXA_INTELLIO=m
CONFIG_MOXA_SMARTIO=m
CONFIG_SYNCLINK_GT=m
CONFIG_N_HDLC=m
CONFIG_GOLDFISH_TTY=m
CONFIG_N_GSM=m
CONFIG_NOZOMI=m
CONFIG_NULL_TTY=m
CONFIG_HVC_DRIVER=y
CONFIG_RPMSG_TTY=m
CONFIG_SERIAL_DEV_BUS=m
CONFIG_TTY_PRINTK=m
CONFIG_TTY_PRINTK_LEVEL=6
CONFIG_PRINTER=m
CONFIG_LP_CONSOLE=y
CONFIG_PPDEV=m
CONFIG_VIRTIO_CONSOLE=m
CONFIG_IPMI_HANDLER=m
CONFIG_IPMI_DMI_DECODE=y
CONFIG_IPMI_PLAT_DATA=y
CONFIG_IPMI_PANIC_EVENT=y
CONFIG_IPMI_PANIC_STRING=y
CONFIG_IPMI_DEVICE_INTERFACE=m
CONFIG_IPMI_SI=m
CONFIG_IPMI_SSIF=m
CONFIG_IPMI_IPMB=m
CONFIG_IPMI_WATCHDOG=m
CONFIG_IPMI_POWEROFF=m
CONFIG_IPMB_DEVICE_INTERFACE=m
CONFIG_HW_RANDOM=m
CONFIG_HW_RANDOM_TIMERIOMEM=m
CONFIG_HW_RANDOM_INTEL=m
# CONFIG_HW_RANDOM_AMD is not set
CONFIG_HW_RANDOM_BA431=m
CONFIG_HW_RANDOM_GEODE=m
CONFIG_HW_RANDOM_VIA=m
CONFIG_HW_RANDOM_VIRTIO=m
CONFIG_HW_RANDOM_CCTRNG=m
CONFIG_HW_RANDOM_XIPHERA=m
CONFIG_DTLK=m
CONFIG_APPLICOM=m
CONFIG_SONYPI=m

#
# PCMCIA character devices
#
CONFIG_SYNCLINK_CS=m
CONFIG_CARDMAN_4000=m
CONFIG_CARDMAN_4040=m
CONFIG_SCR24X=m
CONFIG_IPWIRELESS=m
# end of PCMCIA character devices

CONFIG_MWAVE=m
CONFIG_SCx200_GPIO=m
CONFIG_PC8736x_GPIO=m
CONFIG_NSC_GPIO=m
CONFIG_DEVMEM=y
CONFIG_NVRAM=m
CONFIG_DEVPORT=y
CONFIG_HPET=y
CONFIG_HPET_MMAP=y
CONFIG_HPET_MMAP_DEFAULT=y
CONFIG_HANGCHECK_TIMER=m
CONFIG_TCG_TPM=y
CONFIG_TCG_TIS_CORE=y
CONFIG_TCG_TIS=y
CONFIG_TCG_TIS_SPI=m
CONFIG_TCG_TIS_SPI_CR50=y
CONFIG_TCG_TIS_I2C=m
CONFIG_TCG_TIS_I2C_CR50=m
CONFIG_TCG_TIS_I2C_ATMEL=m
CONFIG_TCG_TIS_I2C_INFINEON=m
CONFIG_TCG_TIS_I2C_NUVOTON=m
CONFIG_TCG_NSC=m
CONFIG_TCG_ATMEL=m
CONFIG_TCG_INFINEON=m
CONFIG_TCG_CRB=y
CONFIG_TCG_VTPM_PROXY=m
CONFIG_TCG_TIS_ST33ZP24=m
CONFIG_TCG_TIS_ST33ZP24_I2C=m
CONFIG_TCG_TIS_ST33ZP24_SPI=m
CONFIG_TELCLOCK=m
CONFIG_XILLYBUS_CLASS=m
CONFIG_XILLYBUS=m
CONFIG_XILLYBUS_PCIE=m
CONFIG_XILLYBUS_OF=m
CONFIG_XILLYUSB=m
CONFIG_RANDOM_TRUST_CPU=y
CONFIG_RANDOM_TRUST_BOOTLOADER=y
# end of Character devices

#
# I2C support
#
CONFIG_I2C=y
CONFIG_ACPI_I2C_OPREGION=y
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_COMPAT=y
CONFIG_I2C_CHARDEV=m
CONFIG_I2C_MUX=m

#
# Multiplexer I2C Chip support
#
CONFIG_I2C_ARB_GPIO_CHALLENGE=m
CONFIG_I2C_MUX_GPIO=m
CONFIG_I2C_MUX_GPMUX=m
CONFIG_I2C_MUX_LTC4306=m
CONFIG_I2C_MUX_PCA9541=m
CONFIG_I2C_MUX_PCA954x=m
CONFIG_I2C_MUX_PINCTRL=m
CONFIG_I2C_MUX_REG=m
CONFIG_I2C_DEMUX_PINCTRL=m
CONFIG_I2C_MUX_MLXCPLD=m
# end of Multiplexer I2C Chip support

CONFIG_I2C_HELPER_AUTO=y
CONFIG_I2C_SMBUS=m
CONFIG_I2C_ALGOBIT=m
CONFIG_I2C_ALGOPCA=m

#
# I2C Hardware Bus support
#

#
# PC SMBus host controller drivers
#
CONFIG_I2C_CCGX_UCSI=m
CONFIG_I2C_ALI1535=m
CONFIG_I2C_ALI1563=m
CONFIG_I2C_ALI15X3=m
# CONFIG_I2C_AMD756 is not set
# CONFIG_I2C_AMD8111 is not set
# CONFIG_I2C_AMD_MP2 is not set
CONFIG_I2C_I801=m
CONFIG_I2C_ISCH=m
CONFIG_I2C_ISMT=m
CONFIG_I2C_PIIX4=m
CONFIG_I2C_NFORCE2=m
CONFIG_I2C_NFORCE2_S4985=m
CONFIG_I2C_NVIDIA_GPU=m
CONFIG_I2C_SIS5595=m
CONFIG_I2C_SIS630=m
CONFIG_I2C_SIS96X=m
CONFIG_I2C_VIA=m
CONFIG_I2C_VIAPRO=m

#
# ACPI drivers
#
CONFIG_I2C_SCMI=m

#
# I2C system bus drivers (mostly embedded / system-on-chip)
#
CONFIG_I2C_CBUS_GPIO=m
CONFIG_I2C_DESIGNWARE_CORE=m
CONFIG_I2C_DESIGNWARE_SLAVE=y
CONFIG_I2C_DESIGNWARE_PLATFORM=m
# CONFIG_I2C_DESIGNWARE_AMDPSP is not set
CONFIG_I2C_DESIGNWARE_BAYTRAIL=y
CONFIG_I2C_DESIGNWARE_PCI=m
CONFIG_I2C_EG20T=m
CONFIG_I2C_EMEV2=m
CONFIG_I2C_GPIO=m
CONFIG_I2C_GPIO_FAULT_INJECTOR=y
CONFIG_I2C_KEMPLD=m
CONFIG_I2C_OCORES=m
CONFIG_I2C_PCA_PLATFORM=m
CONFIG_I2C_PXA=m
CONFIG_I2C_PXA_PCI=y
CONFIG_I2C_RK3X=m
CONFIG_I2C_SIMTEC=m
CONFIG_I2C_XILINX=m

#
# External I2C/SMBus adapter drivers
#
CONFIG_I2C_DIOLAN_U2C=m
CONFIG_I2C_DLN2=m
CONFIG_I2C_CP2615=m
CONFIG_I2C_PARPORT=m
CONFIG_I2C_PCI1XXXX=m
CONFIG_I2C_ROBOTFUZZ_OSIF=m
CONFIG_I2C_TAOS_EVM=m
CONFIG_I2C_TINY_USB=m
CONFIG_I2C_VIPERBOARD=m

#
# Other I2C/SMBus bus drivers
#
CONFIG_I2C_PCA_ISA=m
CONFIG_I2C_CROS_EC_TUNNEL=m
CONFIG_SCx200_ACB=m
CONFIG_I2C_FSI=m
CONFIG_I2C_VIRTIO=m
# end of I2C Hardware Bus support

CONFIG_I2C_STUB=m
CONFIG_I2C_SLAVE=y
CONFIG_I2C_SLAVE_EEPROM=m
CONFIG_I2C_SLAVE_TESTUNIT=m
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
# end of I2C support

CONFIG_I3C=m
CONFIG_CDNS_I3C_MASTER=m
CONFIG_DW_I3C_MASTER=m
CONFIG_SVC_I3C_MASTER=m
CONFIG_MIPI_I3C_HCI=m
CONFIG_SPI=y
CONFIG_SPI_DEBUG=y
CONFIG_SPI_MASTER=y
CONFIG_SPI_MEM=y

#
# SPI Master Controller Drivers
#
CONFIG_SPI_ALTERA=m
CONFIG_SPI_ALTERA_CORE=m
CONFIG_SPI_ALTERA_DFL=m
CONFIG_SPI_AXI_SPI_ENGINE=m
CONFIG_SPI_BITBANG=m
CONFIG_SPI_BUTTERFLY=m
CONFIG_SPI_CADENCE=m
CONFIG_SPI_CADENCE_QUADSPI=m
CONFIG_SPI_CADENCE_XSPI=m
CONFIG_SPI_DESIGNWARE=m
CONFIG_SPI_DW_DMA=y
CONFIG_SPI_DW_PCI=m
CONFIG_SPI_DW_MMIO=m
CONFIG_SPI_DLN2=m
CONFIG_SPI_FSI=m
CONFIG_SPI_NXP_FLEXSPI=m
CONFIG_SPI_GPIO=m
CONFIG_SPI_INTEL=m
CONFIG_SPI_INTEL_PCI=m
CONFIG_SPI_INTEL_PLATFORM=m
CONFIG_SPI_LM70_LLP=m
CONFIG_SPI_FSL_LIB=m
CONFIG_SPI_FSL_SPI=m
CONFIG_SPI_MICROCHIP_CORE=m
CONFIG_SPI_MICROCHIP_CORE_QSPI=m
CONFIG_SPI_LANTIQ_SSC=m
CONFIG_SPI_OC_TINY=m
CONFIG_SPI_PXA2XX=m
CONFIG_SPI_PXA2XX_PCI=m
CONFIG_SPI_ROCKCHIP=m
CONFIG_SPI_SC18IS602=m
CONFIG_SPI_SIFIVE=m
CONFIG_SPI_MXIC=m
CONFIG_SPI_TOPCLIFF_PCH=m
CONFIG_SPI_XCOMM=m
CONFIG_SPI_XILINX=m
CONFIG_SPI_ZYNQMP_GQSPI=m
# CONFIG_SPI_AMD is not set

#
# SPI Multiplexer support
#
CONFIG_SPI_MUX=m

#
# SPI Protocol Masters
#
CONFIG_SPI_SPIDEV=m
# CONFIG_SPI_LOOPBACK_TEST is not set
CONFIG_SPI_TLE62X0=m
CONFIG_SPI_SLAVE=y
CONFIG_SPI_SLAVE_TIME=m
CONFIG_SPI_SLAVE_SYSTEM_CONTROL=m
CONFIG_SPI_DYNAMIC=y
CONFIG_SPMI=m
CONFIG_SPMI_HISI3670=m
CONFIG_HSI=m
CONFIG_HSI_BOARDINFO=y

#
# HSI controllers
#

#
# HSI clients
#
CONFIG_HSI_CHAR=m
CONFIG_PPS=m
# CONFIG_PPS_DEBUG is not set

#
# PPS clients support
#
CONFIG_PPS_CLIENT_KTIMER=m
CONFIG_PPS_CLIENT_LDISC=m
CONFIG_PPS_CLIENT_PARPORT=m
CONFIG_PPS_CLIENT_GPIO=m

#
# PPS generators support
#

#
# PTP clock support
#
CONFIG_PTP_1588_CLOCK=m
CONFIG_PTP_1588_CLOCK_OPTIONAL=m
CONFIG_DP83640_PHY=m
CONFIG_PTP_1588_CLOCK_INES=m
CONFIG_PTP_1588_CLOCK_PCH=m
CONFIG_PTP_1588_CLOCK_KVM=m
CONFIG_PTP_1588_CLOCK_IDT82P33=m
CONFIG_PTP_1588_CLOCK_IDTCM=m
CONFIG_PTP_1588_CLOCK_VMW=m
CONFIG_PTP_1588_CLOCK_OCP=m
# end of PTP clock support

CONFIG_PINCTRL=y
CONFIG_GENERIC_PINCTRL_GROUPS=y
CONFIG_PINMUX=y
CONFIG_GENERIC_PINMUX_FUNCTIONS=y
CONFIG_PINCONF=y
CONFIG_GENERIC_PINCONF=y
CONFIG_DEBUG_PINCTRL=y
# CONFIG_PINCTRL_AMD is not set
CONFIG_PINCTRL_AS3722=m
CONFIG_PINCTRL_AXP209=m
CONFIG_PINCTRL_DA9062=m
CONFIG_PINCTRL_EQUILIBRIUM=m
CONFIG_PINCTRL_MAX77620=m
CONFIG_PINCTRL_MCP23S08_I2C=m
CONFIG_PINCTRL_MCP23S08_SPI=m
CONFIG_PINCTRL_MCP23S08=m
CONFIG_PINCTRL_MICROCHIP_SGPIO=m
CONFIG_PINCTRL_OCELOT=m
CONFIG_PINCTRL_PALMAS=m
CONFIG_PINCTRL_RK805=m
CONFIG_PINCTRL_SINGLE=m
CONFIG_PINCTRL_STMFX=m
CONFIG_PINCTRL_SX150X=y
CONFIG_PINCTRL_LOCHNAGAR=m
CONFIG_PINCTRL_MADERA=m
CONFIG_PINCTRL_CS47L15=y
CONFIG_PINCTRL_CS47L35=y
CONFIG_PINCTRL_CS47L85=y
CONFIG_PINCTRL_CS47L90=y
CONFIG_PINCTRL_CS47L92=y

#
# Intel pinctrl drivers
#
CONFIG_PINCTRL_BAYTRAIL=y
CONFIG_PINCTRL_CHERRYVIEW=m
CONFIG_PINCTRL_LYNXPOINT=m
CONFIG_PINCTRL_MERRIFIELD=m
CONFIG_PINCTRL_INTEL=y
CONFIG_PINCTRL_ALDERLAKE=m
CONFIG_PINCTRL_BROXTON=m
CONFIG_PINCTRL_CANNONLAKE=m
CONFIG_PINCTRL_CEDARFORK=m
CONFIG_PINCTRL_DENVERTON=m
CONFIG_PINCTRL_ELKHARTLAKE=m
CONFIG_PINCTRL_EMMITSBURG=m
CONFIG_PINCTRL_GEMINILAKE=m
CONFIG_PINCTRL_ICELAKE=m
CONFIG_PINCTRL_JASPERLAKE=m
CONFIG_PINCTRL_LAKEFIELD=m
CONFIG_PINCTRL_LEWISBURG=m
CONFIG_PINCTRL_METEORLAKE=m
CONFIG_PINCTRL_SUNRISEPOINT=m
CONFIG_PINCTRL_TIGERLAKE=m
# end of Intel pinctrl drivers

#
# Renesas pinctrl drivers
#
# end of Renesas pinctrl drivers

CONFIG_GPIOLIB=y
CONFIG_GPIOLIB_FASTPATH_LIMIT=512
CONFIG_OF_GPIO=y
CONFIG_GPIO_ACPI=y
CONFIG_GPIOLIB_IRQCHIP=y
CONFIG_DEBUG_GPIO=y
CONFIG_GPIO_SYSFS=y
CONFIG_GPIO_CDEV=y
CONFIG_GPIO_CDEV_V1=y
CONFIG_GPIO_GENERIC=y
CONFIG_GPIO_MAX730X=m

#
# Memory mapped GPIO drivers
#
CONFIG_GPIO_74XX_MMIO=m
CONFIG_GPIO_ALTERA=m
# CONFIG_GPIO_AMDPT is not set
CONFIG_GPIO_CADENCE=m
CONFIG_GPIO_DWAPB=m
CONFIG_GPIO_EXAR=m
CONFIG_GPIO_FTGPIO010=y
CONFIG_GPIO_GENERIC_PLATFORM=m
CONFIG_GPIO_GRGPIO=m
CONFIG_GPIO_HLWD=m
CONFIG_GPIO_ICH=m
CONFIG_GPIO_LOGICVC=m
CONFIG_GPIO_MB86S7X=m
CONFIG_GPIO_MENZ127=m
CONFIG_GPIO_SIFIVE=y
CONFIG_GPIO_SIOX=m
CONFIG_GPIO_STA2X11=y
CONFIG_GPIO_SYSCON=m
CONFIG_GPIO_VX855=m
CONFIG_GPIO_WCD934X=m
CONFIG_GPIO_XILINX=m
CONFIG_GPIO_AMD_FCH=m
# end of Memory mapped GPIO drivers

#
# Port-mapped I/O GPIO drivers
#
CONFIG_GPIO_I8255=m
CONFIG_GPIO_104_DIO_48E=m
CONFIG_GPIO_104_IDIO_16=m
CONFIG_GPIO_104_IDI_48=m
CONFIG_GPIO_F7188X=m
CONFIG_GPIO_GPIO_MM=m
CONFIG_GPIO_IT87=m
CONFIG_GPIO_SCH=m
CONFIG_GPIO_SCH311X=m
CONFIG_GPIO_WINBOND=m
CONFIG_GPIO_WS16C48=m
# end of Port-mapped I/O GPIO drivers

#
# I2C GPIO expanders
#
# CONFIG_GPIO_ADP5588 is not set
CONFIG_GPIO_ADNP=m
CONFIG_GPIO_GW_PLD=m
CONFIG_GPIO_MAX7300=m
CONFIG_GPIO_MAX732X=m
CONFIG_GPIO_PCA953X=m
CONFIG_GPIO_PCA953X_IRQ=y
CONFIG_GPIO_PCA9570=m
CONFIG_GPIO_PCF857X=m
CONFIG_GPIO_TPIC2810=m
# end of I2C GPIO expanders

#
# MFD GPIO expanders
#
CONFIG_GPIO_ADP5520=m
CONFIG_GPIO_ARIZONA=m
CONFIG_GPIO_BD71815=m
CONFIG_GPIO_BD71828=m
CONFIG_GPIO_BD9571MWV=m
CONFIG_GPIO_CS5535=m
CONFIG_GPIO_DA9052=m
CONFIG_GPIO_DA9055=m
CONFIG_GPIO_DLN2=m
CONFIG_GPIO_JANZ_TTL=m
CONFIG_GPIO_KEMPLD=m
CONFIG_GPIO_LP3943=m
CONFIG_GPIO_LP873X=m
CONFIG_GPIO_LP87565=m
CONFIG_GPIO_MADERA=m
CONFIG_GPIO_MAX77620=m
CONFIG_GPIO_MAX77650=m
CONFIG_GPIO_PALMAS=y
CONFIG_GPIO_RC5T583=y
CONFIG_GPIO_STMPE=y
CONFIG_GPIO_TC3589X=y
CONFIG_GPIO_TIMBERDALE=y
CONFIG_GPIO_TPS65086=m
CONFIG_GPIO_TPS65218=m
CONFIG_GPIO_TPS6586X=y
CONFIG_GPIO_TPS65910=y
CONFIG_GPIO_TPS65912=m
CONFIG_GPIO_TPS68470=m
CONFIG_GPIO_TQMX86=m
CONFIG_GPIO_TWL4030=m
CONFIG_GPIO_TWL6040=m
CONFIG_GPIO_UCB1400=m
CONFIG_GPIO_WHISKEY_COVE=m
CONFIG_GPIO_WM831X=m
CONFIG_GPIO_WM8350=m
CONFIG_GPIO_WM8994=m
# end of MFD GPIO expanders

#
# PCI GPIO expanders
#
# CONFIG_GPIO_AMD8111 is not set
CONFIG_GPIO_MERRIFIELD=m
CONFIG_GPIO_ML_IOH=m
CONFIG_GPIO_PCH=m
CONFIG_GPIO_PCI_IDIO_16=m
CONFIG_GPIO_PCIE_IDIO_24=m
CONFIG_GPIO_RDC321X=m
CONFIG_GPIO_SODAVILLE=y
# end of PCI GPIO expanders

#
# SPI GPIO expanders
#
CONFIG_GPIO_74X164=m
CONFIG_GPIO_MAX3191X=m
CONFIG_GPIO_MAX7301=m
CONFIG_GPIO_MC33880=m
CONFIG_GPIO_PISOSR=m
CONFIG_GPIO_XRA1403=m
CONFIG_GPIO_MOXTET=m
# end of SPI GPIO expanders

#
# USB GPIO expanders
#
CONFIG_GPIO_VIPERBOARD=m
# end of USB GPIO expanders

#
# Virtual GPIO drivers
#
CONFIG_GPIO_AGGREGATOR=m
CONFIG_GPIO_MOCKUP=m
CONFIG_GPIO_VIRTIO=m
CONFIG_GPIO_SIM=m
# end of Virtual GPIO drivers

CONFIG_W1=m
CONFIG_W1_CON=y

#
# 1-wire Bus Masters
#
CONFIG_W1_MASTER_MATROX=m
CONFIG_W1_MASTER_DS2490=m
CONFIG_W1_MASTER_DS2482=m
CONFIG_W1_MASTER_DS1WM=m
CONFIG_W1_MASTER_GPIO=m
CONFIG_W1_MASTER_SGI=m
# end of 1-wire Bus Masters

#
# 1-wire Slaves
#
CONFIG_W1_SLAVE_THERM=m
CONFIG_W1_SLAVE_SMEM=m
CONFIG_W1_SLAVE_DS2405=m
CONFIG_W1_SLAVE_DS2408=m
CONFIG_W1_SLAVE_DS2408_READBACK=y
CONFIG_W1_SLAVE_DS2413=m
CONFIG_W1_SLAVE_DS2406=m
CONFIG_W1_SLAVE_DS2423=m
CONFIG_W1_SLAVE_DS2805=m
CONFIG_W1_SLAVE_DS2430=m
CONFIG_W1_SLAVE_DS2431=m
CONFIG_W1_SLAVE_DS2433=m
CONFIG_W1_SLAVE_DS2433_CRC=y
CONFIG_W1_SLAVE_DS2438=m
CONFIG_W1_SLAVE_DS250X=m
CONFIG_W1_SLAVE_DS2780=m
CONFIG_W1_SLAVE_DS2781=m
CONFIG_W1_SLAVE_DS28E04=m
CONFIG_W1_SLAVE_DS28E17=m
# end of 1-wire Slaves

CONFIG_POWER_RESET=y
CONFIG_POWER_RESET_AS3722=y
CONFIG_POWER_RESET_ATC260X=m
CONFIG_POWER_RESET_GPIO=y
CONFIG_POWER_RESET_GPIO_RESTART=y
# CONFIG_POWER_RESET_LTC2952 is not set
CONFIG_POWER_RESET_MT6323=y
CONFIG_POWER_RESET_REGULATOR=y
CONFIG_POWER_RESET_RESTART=y
CONFIG_POWER_RESET_TPS65086=y
CONFIG_POWER_RESET_SYSCON=y
CONFIG_POWER_RESET_SYSCON_POWEROFF=y
CONFIG_REBOOT_MODE=m
CONFIG_SYSCON_REBOOT_MODE=m
CONFIG_NVMEM_REBOOT_MODE=m
CONFIG_POWER_SUPPLY=y
# CONFIG_POWER_SUPPLY_DEBUG is not set
CONFIG_PDA_POWER=m
CONFIG_GENERIC_ADC_BATTERY=m
CONFIG_IP5XXX_POWER=m
CONFIG_MAX8925_POWER=m
CONFIG_WM831X_BACKUP=m
CONFIG_WM831X_POWER=m
CONFIG_WM8350_POWER=m
# CONFIG_TEST_POWER is not set
CONFIG_BATTERY_88PM860X=m
CONFIG_CHARGER_ADP5061=m
CONFIG_BATTERY_ACT8945A=m
CONFIG_BATTERY_CPCAP=m
CONFIG_BATTERY_CW2015=m
CONFIG_BATTERY_DS2760=m
CONFIG_BATTERY_DS2780=m
CONFIG_BATTERY_DS2781=m
CONFIG_BATTERY_DS2782=m
CONFIG_BATTERY_OLPC=m
CONFIG_BATTERY_SAMSUNG_SDI=y
CONFIG_BATTERY_SBS=m
CONFIG_CHARGER_SBS=m
CONFIG_MANAGER_SBS=m
CONFIG_BATTERY_BQ27XXX=m
CONFIG_BATTERY_BQ27XXX_I2C=m
CONFIG_BATTERY_BQ27XXX_HDQ=m
CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM=y
CONFIG_BATTERY_DA9030=m
CONFIG_BATTERY_DA9052=m
CONFIG_CHARGER_DA9150=m
CONFIG_BATTERY_DA9150=m
CONFIG_CHARGER_AXP20X=m
CONFIG_BATTERY_AXP20X=m
CONFIG_AXP20X_POWER=m
CONFIG_AXP288_CHARGER=m
CONFIG_AXP288_FUEL_GAUGE=m
CONFIG_BATTERY_MAX17040=m
CONFIG_BATTERY_MAX17042=m
CONFIG_BATTERY_MAX1721X=m
CONFIG_BATTERY_TWL4030_MADC=m
CONFIG_CHARGER_88PM860X=m
CONFIG_CHARGER_PCF50633=m
CONFIG_BATTERY_RX51=m
CONFIG_CHARGER_ISP1704=m
CONFIG_CHARGER_MAX8903=m
CONFIG_CHARGER_TWL4030=m
CONFIG_CHARGER_LP8727=m
CONFIG_CHARGER_LP8788=m
CONFIG_CHARGER_GPIO=m
CONFIG_CHARGER_MANAGER=m
CONFIG_CHARGER_LT3651=m
CONFIG_CHARGER_LTC4162L=m
CONFIG_CHARGER_MAX14577=m
CONFIG_CHARGER_DETECTOR_MAX14656=m
CONFIG_CHARGER_MAX77650=m
CONFIG_CHARGER_MAX77693=m
CONFIG_CHARGER_MAX77976=m
CONFIG_CHARGER_MAX8997=m
CONFIG_CHARGER_MAX8998=m
CONFIG_CHARGER_MP2629=m
CONFIG_CHARGER_MT6360=m
CONFIG_CHARGER_MT6370=m
CONFIG_CHARGER_BQ2415X=m
CONFIG_CHARGER_BQ24190=m
CONFIG_CHARGER_BQ24257=m
CONFIG_CHARGER_BQ24735=m
CONFIG_CHARGER_BQ2515X=m
CONFIG_CHARGER_BQ25890=m
CONFIG_CHARGER_BQ25980=m
CONFIG_CHARGER_BQ256XX=m
CONFIG_CHARGER_RK817=m
CONFIG_CHARGER_SMB347=m
CONFIG_CHARGER_TPS65090=m
CONFIG_CHARGER_TPS65217=m
CONFIG_BATTERY_GAUGE_LTC2941=m
CONFIG_BATTERY_GOLDFISH=m
CONFIG_BATTERY_RT5033=m
CONFIG_CHARGER_RT9455=m
CONFIG_CHARGER_CROS_USBPD=m
CONFIG_CHARGER_CROS_PCHG=m
CONFIG_CHARGER_UCS1002=m
CONFIG_CHARGER_BD99954=m
CONFIG_CHARGER_WILCO=m
CONFIG_RN5T618_POWER=m
CONFIG_BATTERY_SURFACE=m
CONFIG_CHARGER_SURFACE=m
CONFIG_BATTERY_UG3105=m
CONFIG_HWMON=m
CONFIG_HWMON_VID=m
CONFIG_HWMON_DEBUG_CHIP=y

#
# Native drivers
#
CONFIG_SENSORS_ABITUGURU=m
CONFIG_SENSORS_ABITUGURU3=m
CONFIG_SENSORS_AD7314=m
CONFIG_SENSORS_AD7414=m
CONFIG_SENSORS_AD7418=m
CONFIG_SENSORS_ADM1025=m
CONFIG_SENSORS_ADM1026=m
CONFIG_SENSORS_ADM1029=m
CONFIG_SENSORS_ADM1031=m
CONFIG_SENSORS_ADM1177=m
CONFIG_SENSORS_ADM9240=m
CONFIG_SENSORS_ADT7X10=m
CONFIG_SENSORS_ADT7310=m
CONFIG_SENSORS_ADT7410=m
CONFIG_SENSORS_ADT7411=m
CONFIG_SENSORS_ADT7462=m
CONFIG_SENSORS_ADT7470=m
CONFIG_SENSORS_ADT7475=m
CONFIG_SENSORS_AHT10=m
CONFIG_SENSORS_AQUACOMPUTER_D5NEXT=m
CONFIG_SENSORS_AS370=m
CONFIG_SENSORS_ASC7621=m
CONFIG_SENSORS_AXI_FAN_CONTROL=m
CONFIG_SENSORS_K8TEMP=m
CONFIG_SENSORS_APPLESMC=m
CONFIG_SENSORS_ASB100=m
CONFIG_SENSORS_ATXP1=m
CONFIG_SENSORS_CORSAIR_CPRO=m
CONFIG_SENSORS_CORSAIR_PSU=m
CONFIG_SENSORS_DRIVETEMP=m
CONFIG_SENSORS_DS620=m
CONFIG_SENSORS_DS1621=m
CONFIG_SENSORS_DELL_SMM=m
CONFIG_I8K=y
CONFIG_SENSORS_DA9052_ADC=m
CONFIG_SENSORS_DA9055=m
CONFIG_SENSORS_I5K_AMB=m
CONFIG_SENSORS_F71805F=m
CONFIG_SENSORS_F71882FG=m
CONFIG_SENSORS_F75375S=m
CONFIG_SENSORS_GSC=m
CONFIG_SENSORS_MC13783_ADC=m
CONFIG_SENSORS_FSCHMD=m
CONFIG_SENSORS_FTSTEUTATES=m
CONFIG_SENSORS_GL518SM=m
CONFIG_SENSORS_GL520SM=m
CONFIG_SENSORS_G760A=m
CONFIG_SENSORS_G762=m
CONFIG_SENSORS_GPIO_FAN=m
CONFIG_SENSORS_HIH6130=m
CONFIG_SENSORS_IBMAEM=m
CONFIG_SENSORS_IBMPEX=m
CONFIG_SENSORS_IIO_HWMON=m
CONFIG_SENSORS_I5500=m
CONFIG_SENSORS_CORETEMP=m
CONFIG_SENSORS_IT87=m
CONFIG_SENSORS_JC42=m
CONFIG_SENSORS_POWR1220=m
CONFIG_SENSORS_LINEAGE=m
CONFIG_SENSORS_LOCHNAGAR=m
CONFIG_SENSORS_LTC2945=m
CONFIG_SENSORS_LTC2947=m
CONFIG_SENSORS_LTC2947_I2C=m
CONFIG_SENSORS_LTC2947_SPI=m
CONFIG_SENSORS_LTC2990=m
CONFIG_SENSORS_LTC2992=m
CONFIG_SENSORS_LTC4151=m
CONFIG_SENSORS_LTC4215=m
CONFIG_SENSORS_LTC4222=m
CONFIG_SENSORS_LTC4245=m
CONFIG_SENSORS_LTC4260=m
CONFIG_SENSORS_LTC4261=m
CONFIG_SENSORS_MAX1111=m
CONFIG_SENSORS_MAX127=m
CONFIG_SENSORS_MAX16065=m
CONFIG_SENSORS_MAX1619=m
CONFIG_SENSORS_MAX1668=m
CONFIG_SENSORS_MAX197=m
CONFIG_SENSORS_MAX31722=m
CONFIG_SENSORS_MAX31730=m
CONFIG_SENSORS_MAX31760=m
CONFIG_SENSORS_MAX6620=m
CONFIG_SENSORS_MAX6621=m
CONFIG_SENSORS_MAX6639=m
CONFIG_SENSORS_MAX6650=m
CONFIG_SENSORS_MAX6697=m
CONFIG_SENSORS_MAX31790=m
CONFIG_SENSORS_MCP3021=m
CONFIG_SENSORS_MLXREG_FAN=m
CONFIG_SENSORS_TC654=m
CONFIG_SENSORS_TPS23861=m
CONFIG_SENSORS_MENF21BMC_HWMON=m
CONFIG_SENSORS_MR75203=m
CONFIG_SENSORS_ADCXX=m
CONFIG_SENSORS_LM63=m
CONFIG_SENSORS_LM70=m
CONFIG_SENSORS_LM73=m
CONFIG_SENSORS_LM75=m
CONFIG_SENSORS_LM77=m
CONFIG_SENSORS_LM78=m
CONFIG_SENSORS_LM80=m
CONFIG_SENSORS_LM83=m
CONFIG_SENSORS_LM85=m
CONFIG_SENSORS_LM87=m
CONFIG_SENSORS_LM90=m
CONFIG_SENSORS_LM92=m
CONFIG_SENSORS_LM93=m
CONFIG_SENSORS_LM95234=m
CONFIG_SENSORS_LM95241=m
CONFIG_SENSORS_LM95245=m
CONFIG_SENSORS_PC87360=m
CONFIG_SENSORS_PC87427=m
CONFIG_SENSORS_NTC_THERMISTOR=m
CONFIG_SENSORS_NCT6683=m
CONFIG_SENSORS_NCT6775_CORE=m
CONFIG_SENSORS_NCT6775=m
CONFIG_SENSORS_NCT6775_I2C=m
CONFIG_SENSORS_NCT7802=m
CONFIG_SENSORS_NCT7904=m
CONFIG_SENSORS_NPCM7XX=m
CONFIG_SENSORS_NZXT_KRAKEN2=m
CONFIG_SENSORS_NZXT_SMART2=m
CONFIG_SENSORS_PCF8591=m
CONFIG_SENSORS_PECI_CPUTEMP=m
CONFIG_SENSORS_PECI_DIMMTEMP=m
CONFIG_SENSORS_PECI=m
CONFIG_PMBUS=m
CONFIG_SENSORS_PMBUS=m
CONFIG_SENSORS_ADM1266=m
CONFIG_SENSORS_ADM1275=m
CONFIG_SENSORS_BEL_PFE=m
CONFIG_SENSORS_BPA_RS600=m
CONFIG_SENSORS_DELTA_AHE50DC_FAN=m
CONFIG_SENSORS_FSP_3Y=m
CONFIG_SENSORS_IBM_CFFPS=m
CONFIG_SENSORS_DPS920AB=m
CONFIG_SENSORS_INSPUR_IPSPS=m
CONFIG_SENSORS_IR35221=m
CONFIG_SENSORS_IR36021=m
CONFIG_SENSORS_IR38064=m
CONFIG_SENSORS_IR38064_REGULATOR=y
CONFIG_SENSORS_IRPS5401=m
CONFIG_SENSORS_ISL68137=m
CONFIG_SENSORS_LM25066=m
CONFIG_SENSORS_LM25066_REGULATOR=y
CONFIG_SENSORS_LT7182S=m
CONFIG_SENSORS_LTC2978=m
CONFIG_SENSORS_LTC2978_REGULATOR=y
CONFIG_SENSORS_LTC3815=m
CONFIG_SENSORS_MAX15301=m
CONFIG_SENSORS_MAX16064=m
CONFIG_SENSORS_MAX16601=m
CONFIG_SENSORS_MAX20730=m
CONFIG_SENSORS_MAX20751=m
CONFIG_SENSORS_MAX31785=m
CONFIG_SENSORS_MAX34440=m
CONFIG_SENSORS_MAX8688=m
CONFIG_SENSORS_MP2888=m
CONFIG_SENSORS_MP2975=m
CONFIG_SENSORS_MP5023=m
CONFIG_SENSORS_PIM4328=m
CONFIG_SENSORS_PLI1209BC=m
CONFIG_SENSORS_PLI1209BC_REGULATOR=y
CONFIG_SENSORS_PM6764TR=m
CONFIG_SENSORS_PXE1610=m
CONFIG_SENSORS_Q54SJ108A2=m
CONFIG_SENSORS_STPDDC60=m
CONFIG_SENSORS_TPS40422=m
CONFIG_SENSORS_TPS53679=m
CONFIG_SENSORS_TPS546D24=m
CONFIG_SENSORS_UCD9000=m
CONFIG_SENSORS_UCD9200=m
CONFIG_SENSORS_XDPE152=m
CONFIG_SENSORS_XDPE122=m
CONFIG_SENSORS_XDPE122_REGULATOR=y
CONFIG_SENSORS_ZL6100=m
CONFIG_SENSORS_PWM_FAN=m
CONFIG_SENSORS_SBTSI=m
CONFIG_SENSORS_SBRMI=m
CONFIG_SENSORS_SHT15=m
CONFIG_SENSORS_SHT21=m
CONFIG_SENSORS_SHT3x=m
CONFIG_SENSORS_SHT4x=m
CONFIG_SENSORS_SHTC1=m
CONFIG_SENSORS_SIS5595=m
CONFIG_SENSORS_SY7636A=m
CONFIG_SENSORS_DME1737=m
CONFIG_SENSORS_EMC1403=m
CONFIG_SENSORS_EMC2103=m
CONFIG_SENSORS_EMC2305=m
CONFIG_SENSORS_EMC6W201=m
CONFIG_SENSORS_SMSC47M1=m
CONFIG_SENSORS_SMSC47M192=m
CONFIG_SENSORS_SMSC47B397=m
CONFIG_SENSORS_SCH56XX_COMMON=m
CONFIG_SENSORS_SCH5627=m
CONFIG_SENSORS_SCH5636=m
CONFIG_SENSORS_STTS751=m
CONFIG_SENSORS_SMM665=m
CONFIG_SENSORS_ADC128D818=m
CONFIG_SENSORS_ADS7828=m
CONFIG_SENSORS_ADS7871=m
CONFIG_SENSORS_AMC6821=m
CONFIG_SENSORS_INA209=m
CONFIG_SENSORS_INA2XX=m
CONFIG_SENSORS_INA238=m
CONFIG_SENSORS_INA3221=m
CONFIG_SENSORS_TC74=m
CONFIG_SENSORS_THMC50=m
CONFIG_SENSORS_TMP102=m
CONFIG_SENSORS_TMP103=m
CONFIG_SENSORS_TMP108=m
CONFIG_SENSORS_TMP401=m
CONFIG_SENSORS_TMP421=m
CONFIG_SENSORS_TMP464=m
CONFIG_SENSORS_TMP513=m
CONFIG_SENSORS_VIA_CPUTEMP=m
CONFIG_SENSORS_VIA686A=m
CONFIG_SENSORS_VT1211=m
CONFIG_SENSORS_VT8231=m
CONFIG_SENSORS_W83773G=m
CONFIG_SENSORS_W83781D=m
CONFIG_SENSORS_W83791D=m
CONFIG_SENSORS_W83792D=m
CONFIG_SENSORS_W83793=m
CONFIG_SENSORS_W83795=m
CONFIG_SENSORS_W83795_FANCTRL=y
CONFIG_SENSORS_W83L785TS=m
CONFIG_SENSORS_W83L786NG=m
CONFIG_SENSORS_W83627HF=m
CONFIG_SENSORS_W83627EHF=m
CONFIG_SENSORS_WM831X=m
CONFIG_SENSORS_WM8350=m
CONFIG_SENSORS_XGENE=m
CONFIG_SENSORS_INTEL_M10_BMC_HWMON=m

#
# ACPI drivers
#
CONFIG_SENSORS_ACPI_POWER=m
CONFIG_SENSORS_ATK0110=m
CONFIG_SENSORS_ASUS_WMI=m
CONFIG_SENSORS_ASUS_EC=m
CONFIG_THERMAL=y
CONFIG_THERMAL_NETLINK=y
CONFIG_THERMAL_STATISTICS=y
CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0
CONFIG_THERMAL_OF=y
CONFIG_THERMAL_WRITABLE_TRIPS=y
CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set
CONFIG_THERMAL_GOV_FAIR_SHARE=y
CONFIG_THERMAL_GOV_STEP_WISE=y
CONFIG_THERMAL_GOV_BANG_BANG=y
CONFIG_THERMAL_GOV_USER_SPACE=y
CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
CONFIG_CPU_THERMAL=y
CONFIG_CPU_FREQ_THERMAL=y
CONFIG_CPU_IDLE_THERMAL=y
CONFIG_DEVFREQ_THERMAL=y
CONFIG_THERMAL_EMULATION=y
CONFIG_THERMAL_MMIO=m
CONFIG_MAX77620_THERMAL=m
CONFIG_DA9062_THERMAL=m

#
# Intel thermal drivers
#
CONFIG_INTEL_POWERCLAMP=m
CONFIG_X86_THERMAL_VECTOR=y
CONFIG_X86_PKG_TEMP_THERMAL=m
CONFIG_INTEL_SOC_DTS_IOSF_CORE=m
CONFIG_INTEL_SOC_DTS_THERMAL=m
CONFIG_INTEL_QUARK_DTS_THERMAL=m

#
# ACPI INT340X thermal drivers
#
# end of ACPI INT340X thermal drivers

CONFIG_INTEL_BXT_PMIC_THERMAL=m
CONFIG_INTEL_PCH_THERMAL=m
CONFIG_INTEL_TCC_COOLING=m
CONFIG_INTEL_MENLOW=m
CONFIG_INTEL_HFI_THERMAL=y
# end of Intel thermal drivers

# CONFIG_TI_SOC_THERMAL is not set
CONFIG_GENERIC_ADC_THERMAL=m
CONFIG_WATCHDOG=y
CONFIG_WATCHDOG_CORE=y
CONFIG_WATCHDOG_NOWAYOUT=y
CONFIG_WATCHDOG_HANDLE_BOOT_ENABLED=y
CONFIG_WATCHDOG_OPEN_TIMEOUT=0
CONFIG_WATCHDOG_SYSFS=y
CONFIG_WATCHDOG_HRTIMER_PRETIMEOUT=y

#
# Watchdog Pretimeout Governors
#
CONFIG_WATCHDOG_PRETIMEOUT_GOV=y
CONFIG_WATCHDOG_PRETIMEOUT_GOV_SEL=m
CONFIG_WATCHDOG_PRETIMEOUT_GOV_NOOP=m
CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC=m
# CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_NOOP is not set
CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_PANIC=y

#
# Watchdog Device Drivers
#
CONFIG_SOFT_WATCHDOG=m
CONFIG_SOFT_WATCHDOG_PRETIMEOUT=y
CONFIG_BD957XMUF_WATCHDOG=m
CONFIG_DA9052_WATCHDOG=m
CONFIG_DA9055_WATCHDOG=m
CONFIG_DA9063_WATCHDOG=m
CONFIG_DA9062_WATCHDOG=m
CONFIG_GPIO_WATCHDOG=m
CONFIG_MENF21BMC_WATCHDOG=m
CONFIG_MENZ069_WATCHDOG=m
CONFIG_WDAT_WDT=m
CONFIG_WM831X_WATCHDOG=m
CONFIG_WM8350_WATCHDOG=m
CONFIG_XILINX_WATCHDOG=m
CONFIG_ZIIRAVE_WATCHDOG=m
CONFIG_RAVE_SP_WATCHDOG=m
CONFIG_MLX_WDT=m
CONFIG_CADENCE_WATCHDOG=m
CONFIG_DW_WATCHDOG=m
CONFIG_RN5T618_WATCHDOG=m
CONFIG_TWL4030_WATCHDOG=m
CONFIG_MAX63XX_WATCHDOG=m
CONFIG_MAX77620_WATCHDOG=m
CONFIG_RETU_WATCHDOG=m
CONFIG_STPMIC1_WATCHDOG=m
CONFIG_ACQUIRE_WDT=m
CONFIG_ADVANTECH_WDT=m
CONFIG_ALIM1535_WDT=m
CONFIG_ALIM7101_WDT=m
CONFIG_EBC_C384_WDT=m
CONFIG_F71808E_WDT=m
# CONFIG_SP5100_TCO is not set
# CONFIG_GEODE_WDT is not set
CONFIG_SBC_FITPC2_WATCHDOG=m
# CONFIG_EUROTECH_WDT is not set
CONFIG_IB700_WDT=m
CONFIG_IBMASR=m
CONFIG_WAFER_WDT=m
CONFIG_I6300ESB_WDT=m
CONFIG_IE6XX_WDT=m
CONFIG_INTEL_MID_WATCHDOG=m
CONFIG_ITCO_WDT=m
CONFIG_ITCO_VENDOR_SUPPORT=y
CONFIG_IT8712F_WDT=m
CONFIG_IT87_WDT=m
CONFIG_HP_WATCHDOG=m
CONFIG_HPWDT_NMI_DECODING=y
CONFIG_KEMPLD_WDT=m
CONFIG_SC1200_WDT=m
CONFIG_SCx200_WDT=m
CONFIG_PC87413_WDT=m
CONFIG_NV_TCO=m
CONFIG_RDC321X_WDT=m
CONFIG_60XX_WDT=m
CONFIG_SBC8360_WDT=m
CONFIG_SBC7240_WDT=m
CONFIG_CPU5_WDT=m
CONFIG_SMSC_SCH311X_WDT=m
CONFIG_SMSC37B787_WDT=m
CONFIG_TQMX86_WDT=m
CONFIG_VIA_WDT=m
CONFIG_W83627HF_WDT=m
CONFIG_W83877F_WDT=m
CONFIG_W83977F_WDT=m
CONFIG_MACHZ_WDT=m
CONFIG_SBC_EPX_C3_WATCHDOG=m
CONFIG_INTEL_MEI_WDT=m
CONFIG_NI903X_WDT=m
CONFIG_NIC7018_WDT=m
CONFIG_SIEMENS_SIMATIC_IPC_WDT=m
CONFIG_MEN_A21_WDT=m

#
# ISA-based Watchdog Cards
#
CONFIG_PCWATCHDOG=m
CONFIG_MIXCOMWD=m
# CONFIG_WDT is not set

#
# PCI-based Watchdog Cards
#
CONFIG_PCIPCWATCHDOG=m
CONFIG_WDTPCI=m

#
# USB-based Watchdog Cards
#
CONFIG_USBPCWATCHDOG=m
CONFIG_SSB_POSSIBLE=y
CONFIG_SSB=m
CONFIG_SSB_SPROM=y
CONFIG_SSB_BLOCKIO=y
CONFIG_SSB_PCIHOST_POSSIBLE=y
CONFIG_SSB_PCIHOST=y
CONFIG_SSB_B43_PCI_BRIDGE=y
CONFIG_SSB_PCMCIAHOST_POSSIBLE=y
CONFIG_SSB_PCMCIAHOST=y
CONFIG_SSB_SDIOHOST_POSSIBLE=y
CONFIG_SSB_SDIOHOST=y
CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y
CONFIG_SSB_DRIVER_PCICORE=y
CONFIG_SSB_DRIVER_GPIO=y
CONFIG_BCMA_POSSIBLE=y
CONFIG_BCMA=m
CONFIG_BCMA_BLOCKIO=y
CONFIG_BCMA_HOST_PCI_POSSIBLE=y
CONFIG_BCMA_HOST_PCI=y
CONFIG_BCMA_HOST_SOC=y
CONFIG_BCMA_DRIVER_PCI=y
CONFIG_BCMA_SFLASH=y
CONFIG_BCMA_DRIVER_GMAC_CMN=y
CONFIG_BCMA_DRIVER_GPIO=y
CONFIG_BCMA_DEBUG=y

#
# Multifunction device drivers
#
CONFIG_MFD_CORE=y
CONFIG_MFD_CS5535=m
CONFIG_MFD_ACT8945A=m
CONFIG_MFD_AS3711=y
CONFIG_MFD_AS3722=m
CONFIG_PMIC_ADP5520=y
CONFIG_MFD_AAT2870_CORE=y
CONFIG_MFD_ATMEL_FLEXCOM=m
CONFIG_MFD_ATMEL_HLCDC=m
CONFIG_MFD_BCM590XX=m
CONFIG_MFD_BD9571MWV=m
CONFIG_MFD_AXP20X=m
CONFIG_MFD_AXP20X_I2C=m
CONFIG_MFD_CROS_EC_DEV=m
CONFIG_MFD_MADERA=m
CONFIG_MFD_MADERA_I2C=m
CONFIG_MFD_MADERA_SPI=m
CONFIG_MFD_CS47L15=y
CONFIG_MFD_CS47L35=y
CONFIG_MFD_CS47L85=y
CONFIG_MFD_CS47L90=y
CONFIG_MFD_CS47L92=y
CONFIG_PMIC_DA903X=y
CONFIG_PMIC_DA9052=y
CONFIG_MFD_DA9052_SPI=y
CONFIG_MFD_DA9052_I2C=y
CONFIG_MFD_DA9055=y
CONFIG_MFD_DA9062=m
CONFIG_MFD_DA9063=m
CONFIG_MFD_DA9150=m
CONFIG_MFD_DLN2=m
CONFIG_MFD_GATEWORKS_GSC=m
CONFIG_MFD_MC13XXX=m
CONFIG_MFD_MC13XXX_SPI=m
CONFIG_MFD_MC13XXX_I2C=m
CONFIG_MFD_MP2629=m
CONFIG_MFD_HI6421_PMIC=m
CONFIG_MFD_HI6421_SPMI=m
CONFIG_HTC_PASIC3=m
CONFIG_HTC_I2CPLD=y
CONFIG_MFD_INTEL_QUARK_I2C_GPIO=m
CONFIG_LPC_ICH=m
CONFIG_LPC_SCH=m
CONFIG_INTEL_SOC_PMIC_BXTWC=m
CONFIG_INTEL_SOC_PMIC_MRFLD=m
CONFIG_MFD_INTEL_LPSS=m
CONFIG_MFD_INTEL_LPSS_ACPI=m
CONFIG_MFD_INTEL_LPSS_PCI=m
CONFIG_MFD_INTEL_PMC_BXT=m
CONFIG_MFD_IQS62X=m
CONFIG_MFD_JANZ_CMODIO=m
CONFIG_MFD_KEMPLD=m
CONFIG_MFD_88PM800=m
CONFIG_MFD_88PM805=m
CONFIG_MFD_88PM860X=y
CONFIG_MFD_MAX14577=m
CONFIG_MFD_MAX77620=y
CONFIG_MFD_MAX77650=m
CONFIG_MFD_MAX77686=m
CONFIG_MFD_MAX77693=m
CONFIG_MFD_MAX77714=m
CONFIG_MFD_MAX77843=y
CONFIG_MFD_MAX8907=m
CONFIG_MFD_MAX8925=y
CONFIG_MFD_MAX8997=y
CONFIG_MFD_MAX8998=y
CONFIG_MFD_MT6360=m
CONFIG_MFD_MT6370=m
CONFIG_MFD_MT6397=m
CONFIG_MFD_MENF21BMC=m
CONFIG_MFD_OCELOT=m
CONFIG_EZX_PCAP=y
CONFIG_MFD_CPCAP=m
CONFIG_MFD_VIPERBOARD=m
CONFIG_MFD_NTXEC=m
CONFIG_MFD_RETU=m
CONFIG_MFD_PCF50633=m
CONFIG_PCF50633_ADC=m
CONFIG_PCF50633_GPIO=m
CONFIG_UCB1400_CORE=m
CONFIG_MFD_SY7636A=m
CONFIG_MFD_RDC321X=m
CONFIG_MFD_RT4831=m
CONFIG_MFD_RT5033=m
CONFIG_MFD_RT5120=m
CONFIG_MFD_RC5T583=y
CONFIG_MFD_RK808=y
CONFIG_MFD_RN5T618=m
CONFIG_MFD_SEC_CORE=m
CONFIG_MFD_SI476X_CORE=m
CONFIG_MFD_SIMPLE_MFD_I2C=m
CONFIG_MFD_SM501=m
CONFIG_MFD_SM501_GPIO=y
CONFIG_MFD_SKY81452=m
CONFIG_MFD_STMPE=y

#
# STMicroelectronics STMPE Interface Drivers
#
CONFIG_STMPE_I2C=y
CONFIG_STMPE_SPI=y
# end of STMicroelectronics STMPE Interface Drivers

CONFIG_MFD_STA2X11=y
CONFIG_MFD_SYSCON=y
CONFIG_MFD_TI_AM335X_TSCADC=m
CONFIG_MFD_LP3943=m
CONFIG_MFD_LP8788=y
CONFIG_MFD_TI_LMU=m
CONFIG_MFD_PALMAS=y
CONFIG_TPS6105X=m
# CONFIG_TPS65010 is not set
CONFIG_TPS6507X=m
CONFIG_MFD_TPS65086=m
CONFIG_MFD_TPS65090=y
CONFIG_MFD_TPS65217=m
CONFIG_MFD_TI_LP873X=m
CONFIG_MFD_TI_LP87565=m
CONFIG_MFD_TPS65218=m
CONFIG_MFD_TPS6586X=y
CONFIG_MFD_TPS65910=y
CONFIG_MFD_TPS65912=m
CONFIG_MFD_TPS65912_I2C=m
CONFIG_MFD_TPS65912_SPI=m
CONFIG_TWL4030_CORE=y
CONFIG_MFD_TWL4030_AUDIO=y
CONFIG_TWL6040_CORE=y
CONFIG_MFD_WL1273_CORE=m
CONFIG_MFD_LM3533=m
CONFIG_MFD_TIMBERDALE=m
CONFIG_MFD_TC3589X=y
CONFIG_MFD_TQMX86=m
CONFIG_MFD_VX855=m
CONFIG_MFD_LOCHNAGAR=y
CONFIG_MFD_ARIZONA=m
CONFIG_MFD_ARIZONA_I2C=m
CONFIG_MFD_ARIZONA_SPI=m
CONFIG_MFD_CS47L24=y
CONFIG_MFD_WM5102=y
CONFIG_MFD_WM5110=y
CONFIG_MFD_WM8997=y
CONFIG_MFD_WM8998=y
CONFIG_MFD_WM8400=y
CONFIG_MFD_WM831X=y
CONFIG_MFD_WM831X_I2C=y
CONFIG_MFD_WM831X_SPI=y
CONFIG_MFD_WM8350=y
CONFIG_MFD_WM8350_I2C=y
CONFIG_MFD_WM8994=m
CONFIG_MFD_ROHM_BD718XX=m
CONFIG_MFD_ROHM_BD71828=m
CONFIG_MFD_ROHM_BD957XMUF=m
CONFIG_MFD_STPMIC1=m
CONFIG_MFD_STMFX=m
CONFIG_MFD_WCD934X=m
CONFIG_MFD_ATC260X=m
CONFIG_MFD_ATC260X_I2C=m
CONFIG_MFD_QCOM_PM8008=m
CONFIG_RAVE_SP_CORE=m
CONFIG_MFD_INTEL_M10_BMC=m
CONFIG_MFD_RSMU_I2C=m
CONFIG_MFD_RSMU_SPI=m
# end of Multifunction device drivers

CONFIG_REGULATOR=y
CONFIG_REGULATOR_DEBUG=y
CONFIG_REGULATOR_FIXED_VOLTAGE=m
CONFIG_REGULATOR_VIRTUAL_CONSUMER=m
CONFIG_REGULATOR_USERSPACE_CONSUMER=m
CONFIG_REGULATOR_88PG86X=m
CONFIG_REGULATOR_88PM800=m
CONFIG_REGULATOR_88PM8607=m
CONFIG_REGULATOR_ACT8865=m
CONFIG_REGULATOR_ACT8945A=m
CONFIG_REGULATOR_AD5398=m
CONFIG_REGULATOR_AAT2870=m
CONFIG_REGULATOR_ARIZONA_LDO1=m
CONFIG_REGULATOR_ARIZONA_MICSUPP=m
CONFIG_REGULATOR_AS3711=m
CONFIG_REGULATOR_AS3722=m
CONFIG_REGULATOR_ATC260X=m
CONFIG_REGULATOR_AXP20X=m
CONFIG_REGULATOR_BCM590XX=m
CONFIG_REGULATOR_BD71815=m
CONFIG_REGULATOR_BD71828=m
CONFIG_REGULATOR_BD718XX=m
CONFIG_REGULATOR_BD9571MWV=m
CONFIG_REGULATOR_BD957XMUF=m
CONFIG_REGULATOR_CPCAP=m
CONFIG_REGULATOR_CROS_EC=m
CONFIG_REGULATOR_DA9052=m
CONFIG_REGULATOR_DA9055=m
CONFIG_REGULATOR_DA9062=m
CONFIG_REGULATOR_DA9063=m
CONFIG_REGULATOR_DA9121=m
CONFIG_REGULATOR_DA9210=m
CONFIG_REGULATOR_DA9211=m
CONFIG_REGULATOR_FAN53555=m
CONFIG_REGULATOR_FAN53880=m
CONFIG_REGULATOR_GPIO=m
CONFIG_REGULATOR_HI6421=m
CONFIG_REGULATOR_HI6421V530=m
CONFIG_REGULATOR_HI6421V600=m
CONFIG_REGULATOR_ISL9305=m
CONFIG_REGULATOR_ISL6271A=m
CONFIG_REGULATOR_LM363X=m
CONFIG_REGULATOR_LOCHNAGAR=m
CONFIG_REGULATOR_LP3971=m
CONFIG_REGULATOR_LP3972=m
CONFIG_REGULATOR_LP872X=m
CONFIG_REGULATOR_LP873X=m
CONFIG_REGULATOR_LP8755=m
CONFIG_REGULATOR_LP87565=m
CONFIG_REGULATOR_LP8788=m
CONFIG_REGULATOR_LTC3589=m
CONFIG_REGULATOR_LTC3676=m
CONFIG_REGULATOR_MAX14577=m
CONFIG_REGULATOR_MAX1586=m
CONFIG_REGULATOR_MAX77620=m
CONFIG_REGULATOR_MAX77650=m
CONFIG_REGULATOR_MAX8649=m
CONFIG_REGULATOR_MAX8660=m
CONFIG_REGULATOR_MAX8893=m
CONFIG_REGULATOR_MAX8907=m
CONFIG_REGULATOR_MAX8925=m
CONFIG_REGULATOR_MAX8952=m
CONFIG_REGULATOR_MAX8973=m
CONFIG_REGULATOR_MAX8997=m
CONFIG_REGULATOR_MAX8998=m
CONFIG_REGULATOR_MAX20086=m
CONFIG_REGULATOR_MAX77686=m
CONFIG_REGULATOR_MAX77693=m
CONFIG_REGULATOR_MAX77802=m
CONFIG_REGULATOR_MAX77826=m
CONFIG_REGULATOR_MC13XXX_CORE=m
CONFIG_REGULATOR_MC13783=m
CONFIG_REGULATOR_MC13892=m
CONFIG_REGULATOR_MCP16502=m
CONFIG_REGULATOR_MP5416=m
CONFIG_REGULATOR_MP8859=m
CONFIG_REGULATOR_MP886X=m
CONFIG_REGULATOR_MPQ7920=m
CONFIG_REGULATOR_MT6311=m
CONFIG_REGULATOR_MT6315=m
CONFIG_REGULATOR_MT6323=m
CONFIG_REGULATOR_MT6331=m
CONFIG_REGULATOR_MT6332=m
CONFIG_REGULATOR_MT6358=m
CONFIG_REGULATOR_MT6359=m
CONFIG_REGULATOR_MT6360=m
CONFIG_REGULATOR_MT6370=m
CONFIG_REGULATOR_MT6397=m
CONFIG_REGULATOR_PALMAS=m
CONFIG_REGULATOR_PCA9450=m
CONFIG_REGULATOR_PCAP=m
CONFIG_REGULATOR_PCF50633=m
CONFIG_REGULATOR_PF8X00=m
CONFIG_REGULATOR_PFUZE100=m
CONFIG_REGULATOR_PV88060=m
CONFIG_REGULATOR_PV88080=m
CONFIG_REGULATOR_PV88090=m
CONFIG_REGULATOR_PWM=m
CONFIG_REGULATOR_QCOM_SPMI=m
CONFIG_REGULATOR_QCOM_USB_VBUS=m
CONFIG_REGULATOR_RASPBERRYPI_TOUCHSCREEN_ATTINY=m
CONFIG_REGULATOR_RC5T583=m
CONFIG_REGULATOR_RK808=m
CONFIG_REGULATOR_RN5T618=m
CONFIG_REGULATOR_ROHM=m
CONFIG_REGULATOR_RT4801=m
CONFIG_REGULATOR_RT4831=m
CONFIG_REGULATOR_RT5033=m
CONFIG_REGULATOR_RT5120=m
CONFIG_REGULATOR_RT5190A=m
CONFIG_REGULATOR_RT5759=m
CONFIG_REGULATOR_RT6160=m
CONFIG_REGULATOR_RT6245=m
CONFIG_REGULATOR_RTQ2134=m
CONFIG_REGULATOR_RTMV20=m
CONFIG_REGULATOR_RTQ6752=m
CONFIG_REGULATOR_S2MPA01=m
CONFIG_REGULATOR_S2MPS11=m
CONFIG_REGULATOR_S5M8767=m
CONFIG_REGULATOR_SKY81452=m
CONFIG_REGULATOR_SLG51000=m
CONFIG_REGULATOR_STPMIC1=m
CONFIG_REGULATOR_SY7636A=m
CONFIG_REGULATOR_SY8106A=m
CONFIG_REGULATOR_SY8824X=m
CONFIG_REGULATOR_SY8827N=m
CONFIG_REGULATOR_TPS51632=m
CONFIG_REGULATOR_TPS6105X=m
CONFIG_REGULATOR_TPS62360=m
CONFIG_REGULATOR_TPS6286X=m
CONFIG_REGULATOR_TPS65023=m
CONFIG_REGULATOR_TPS6507X=m
CONFIG_REGULATOR_TPS65086=m
CONFIG_REGULATOR_TPS65090=m
CONFIG_REGULATOR_TPS65132=m
CONFIG_REGULATOR_TPS65217=m
CONFIG_REGULATOR_TPS65218=m
CONFIG_REGULATOR_TPS6524X=m
CONFIG_REGULATOR_TPS6586X=m
CONFIG_REGULATOR_TPS65910=m
CONFIG_REGULATOR_TPS65912=m
CONFIG_REGULATOR_TPS68470=m
CONFIG_REGULATOR_TWL4030=m
CONFIG_REGULATOR_VCTRL=m
CONFIG_REGULATOR_WM831X=m
CONFIG_REGULATOR_WM8350=m
CONFIG_REGULATOR_WM8400=m
CONFIG_REGULATOR_WM8994=m
CONFIG_REGULATOR_QCOM_LABIBB=m
CONFIG_RC_CORE=m
CONFIG_LIRC=y
CONFIG_RC_MAP=m
CONFIG_RC_DECODERS=y
CONFIG_IR_IMON_DECODER=m
CONFIG_IR_JVC_DECODER=m
CONFIG_IR_MCE_KBD_DECODER=m
CONFIG_IR_NEC_DECODER=m
CONFIG_IR_RC5_DECODER=m
CONFIG_IR_RC6_DECODER=m
CONFIG_IR_RCMM_DECODER=m
CONFIG_IR_SANYO_DECODER=m
CONFIG_IR_SHARP_DECODER=m
CONFIG_IR_SONY_DECODER=m
CONFIG_IR_XMP_DECODER=m
CONFIG_RC_DEVICES=y
CONFIG_IR_ENE=m
CONFIG_IR_FINTEK=m
CONFIG_IR_GPIO_CIR=m
CONFIG_IR_GPIO_TX=m
CONFIG_IR_HIX5HD2=m
CONFIG_IR_IGORPLUGUSB=m
CONFIG_IR_IGUANA=m
CONFIG_IR_IMON=m
CONFIG_IR_IMON_RAW=m
CONFIG_IR_ITE_CIR=m
CONFIG_IR_MCEUSB=m
CONFIG_IR_NUVOTON=m
CONFIG_IR_PWM_TX=m
CONFIG_IR_REDRAT3=m
CONFIG_IR_SERIAL=m
CONFIG_IR_SERIAL_TRANSMITTER=y
CONFIG_IR_SPI=m
CONFIG_IR_STREAMZAP=m
CONFIG_IR_TOY=m
CONFIG_IR_TTUSBIR=m
CONFIG_IR_WINBOND_CIR=m
CONFIG_RC_ATI_REMOTE=m
CONFIG_RC_LOOPBACK=m
CONFIG_RC_XBOX_DVD=m
CONFIG_CEC_CORE=m
CONFIG_CEC_NOTIFIER=y

#
# CEC support
#
CONFIG_MEDIA_CEC_RC=y
CONFIG_MEDIA_CEC_SUPPORT=y
CONFIG_CEC_CH7322=m
CONFIG_CEC_CROS_EC=m
CONFIG_CEC_SECO=m
CONFIG_CEC_SECO_RC=y
CONFIG_USB_PULSE8_CEC=m
CONFIG_USB_RAINSHADOW_CEC=m
# end of CEC support

CONFIG_MEDIA_SUPPORT=m
CONFIG_MEDIA_SUPPORT_FILTER=y
CONFIG_MEDIA_SUBDRV_AUTOSELECT=y

#
# Media device types
#
CONFIG_MEDIA_CAMERA_SUPPORT=y
CONFIG_MEDIA_ANALOG_TV_SUPPORT=y
CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y
CONFIG_MEDIA_RADIO_SUPPORT=y
CONFIG_MEDIA_SDR_SUPPORT=y
CONFIG_MEDIA_PLATFORM_SUPPORT=y
# CONFIG_MEDIA_TEST_SUPPORT is not set
# end of Media device types

CONFIG_VIDEO_DEV=m
CONFIG_MEDIA_CONTROLLER=y
CONFIG_DVB_CORE=m

#
# Video4Linux options
#
CONFIG_VIDEO_V4L2_I2C=y
CONFIG_VIDEO_V4L2_SUBDEV_API=y
CONFIG_VIDEO_ADV_DEBUG=y
CONFIG_VIDEO_FIXED_MINOR_RANGES=y
CONFIG_VIDEO_TUNER=m
CONFIG_V4L2_MEM2MEM_DEV=m
CONFIG_V4L2_FLASH_LED_CLASS=m
CONFIG_V4L2_FWNODE=m
CONFIG_V4L2_ASYNC=m
CONFIG_VIDEOBUF_GEN=m
CONFIG_VIDEOBUF_DMA_SG=m
CONFIG_VIDEOBUF_VMALLOC=m
# end of Video4Linux options

#
# Media controller options
#
CONFIG_MEDIA_CONTROLLER_DVB=y
# end of Media controller options

#
# Digital TV options
#
CONFIG_DVB_MMAP=y
CONFIG_DVB_NET=y
CONFIG_DVB_MAX_ADAPTERS=16
CONFIG_DVB_DYNAMIC_MINORS=y
CONFIG_DVB_DEMUX_SECTION_LOSS_LOG=y
CONFIG_DVB_ULE_DEBUG=y
# end of Digital TV options

#
# Media drivers
#

#
# Drivers filtered as selected at 'Filter media drivers'
#

#
# Media drivers
#
CONFIG_MEDIA_USB_SUPPORT=y

#
# Webcam devices
#
CONFIG_USB_GSPCA=m
CONFIG_USB_GSPCA_BENQ=m
CONFIG_USB_GSPCA_CONEX=m
CONFIG_USB_GSPCA_CPIA1=m
CONFIG_USB_GSPCA_DTCS033=m
CONFIG_USB_GSPCA_ETOMS=m
CONFIG_USB_GSPCA_FINEPIX=m
CONFIG_USB_GSPCA_JEILINJ=m
CONFIG_USB_GSPCA_JL2005BCD=m
CONFIG_USB_GSPCA_KINECT=m
CONFIG_USB_GSPCA_KONICA=m
CONFIG_USB_GSPCA_MARS=m
CONFIG_USB_GSPCA_MR97310A=m
CONFIG_USB_GSPCA_NW80X=m
CONFIG_USB_GSPCA_OV519=m
CONFIG_USB_GSPCA_OV534=m
CONFIG_USB_GSPCA_OV534_9=m
CONFIG_USB_GSPCA_PAC207=m
CONFIG_USB_GSPCA_PAC7302=m
CONFIG_USB_GSPCA_PAC7311=m
CONFIG_USB_GSPCA_SE401=m
CONFIG_USB_GSPCA_SN9C2028=m
CONFIG_USB_GSPCA_SN9C20X=m
CONFIG_USB_GSPCA_SONIXB=m
CONFIG_USB_GSPCA_SONIXJ=m
CONFIG_USB_GSPCA_SPCA1528=m
CONFIG_USB_GSPCA_SPCA500=m
CONFIG_USB_GSPCA_SPCA501=m
CONFIG_USB_GSPCA_SPCA505=m
CONFIG_USB_GSPCA_SPCA506=m
CONFIG_USB_GSPCA_SPCA508=m
CONFIG_USB_GSPCA_SPCA561=m
CONFIG_USB_GSPCA_SQ905=m
CONFIG_USB_GSPCA_SQ905C=m
CONFIG_USB_GSPCA_SQ930X=m
CONFIG_USB_GSPCA_STK014=m
CONFIG_USB_GSPCA_STK1135=m
CONFIG_USB_GSPCA_STV0680=m
CONFIG_USB_GSPCA_SUNPLUS=m
CONFIG_USB_GSPCA_T613=m
CONFIG_USB_GSPCA_TOPRO=m
CONFIG_USB_GSPCA_TOUPTEK=m
CONFIG_USB_GSPCA_TV8532=m
CONFIG_USB_GSPCA_VC032X=m
CONFIG_USB_GSPCA_VICAM=m
CONFIG_USB_GSPCA_XIRLINK_CIT=m
CONFIG_USB_GSPCA_ZC3XX=m
CONFIG_USB_GL860=m
CONFIG_USB_M5602=m
CONFIG_USB_STV06XX=m
CONFIG_USB_PWC=m
CONFIG_USB_PWC_DEBUG=y
CONFIG_USB_PWC_INPUT_EVDEV=y
CONFIG_USB_S2255=m
CONFIG_VIDEO_USBTV=m
CONFIG_USB_VIDEO_CLASS=m
CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y

#
# Analog TV USB devices
#
CONFIG_VIDEO_GO7007=m
CONFIG_VIDEO_GO7007_USB=m
CONFIG_VIDEO_GO7007_LOADER=m
CONFIG_VIDEO_GO7007_USB_S2250_BOARD=m
CONFIG_VIDEO_HDPVR=m
CONFIG_VIDEO_PVRUSB2=m
CONFIG_VIDEO_PVRUSB2_SYSFS=y
CONFIG_VIDEO_PVRUSB2_DVB=y
CONFIG_VIDEO_PVRUSB2_DEBUGIFC=y
CONFIG_VIDEO_STK1160_COMMON=m
CONFIG_VIDEO_STK1160=m

#
# Analog/digital TV USB devices
#
CONFIG_VIDEO_AU0828=m
CONFIG_VIDEO_AU0828_V4L2=y
CONFIG_VIDEO_AU0828_RC=y
CONFIG_VIDEO_CX231XX=m
CONFIG_VIDEO_CX231XX_RC=y
CONFIG_VIDEO_CX231XX_ALSA=m
CONFIG_VIDEO_CX231XX_DVB=m

#
# Digital TV USB devices
#
CONFIG_DVB_AS102=m
CONFIG_DVB_B2C2_FLEXCOP_USB=m
CONFIG_DVB_B2C2_FLEXCOP_USB_DEBUG=y
CONFIG_DVB_USB_V2=m
CONFIG_DVB_USB_AF9015=m
CONFIG_DVB_USB_AF9035=m
CONFIG_DVB_USB_ANYSEE=m
CONFIG_DVB_USB_AU6610=m
CONFIG_DVB_USB_AZ6007=m
CONFIG_DVB_USB_CE6230=m
CONFIG_DVB_USB_DVBSKY=m
CONFIG_DVB_USB_EC168=m
CONFIG_DVB_USB_GL861=m
CONFIG_DVB_USB_LME2510=m
CONFIG_DVB_USB_MXL111SF=m
CONFIG_DVB_USB_RTL28XXU=m
CONFIG_DVB_USB_ZD1301=m
CONFIG_DVB_USB=m
CONFIG_DVB_USB_DEBUG=y
CONFIG_DVB_USB_A800=m
CONFIG_DVB_USB_AF9005=m
CONFIG_DVB_USB_AF9005_REMOTE=m
CONFIG_DVB_USB_AZ6027=m
CONFIG_DVB_USB_CINERGY_T2=m
CONFIG_DVB_USB_CXUSB=m
CONFIG_DVB_USB_CXUSB_ANALOG=y
CONFIG_DVB_USB_DIB0700=m
CONFIG_DVB_USB_DIB3000MC=m
CONFIG_DVB_USB_DIBUSB_MB=m
CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y
CONFIG_DVB_USB_DIBUSB_MC=m
CONFIG_DVB_USB_DIGITV=m
CONFIG_DVB_USB_DTT200U=m
CONFIG_DVB_USB_DTV5100=m
CONFIG_DVB_USB_DW2102=m
CONFIG_DVB_USB_GP8PSK=m
CONFIG_DVB_USB_M920X=m
CONFIG_DVB_USB_NOVA_T_USB2=m
CONFIG_DVB_USB_OPERA1=m
CONFIG_DVB_USB_PCTV452E=m
CONFIG_DVB_USB_TECHNISAT_USB2=m
CONFIG_DVB_USB_TTUSB2=m
CONFIG_DVB_USB_UMT_010=m
CONFIG_DVB_USB_VP702X=m
CONFIG_DVB_USB_VP7045=m
CONFIG_SMS_USB_DRV=m
CONFIG_DVB_TTUSB_BUDGET=m
CONFIG_DVB_TTUSB_DEC=m

#
# Webcam, TV (analog/digital) USB devices
#
CONFIG_VIDEO_EM28XX=m
CONFIG_VIDEO_EM28XX_V4L2=m
CONFIG_VIDEO_EM28XX_ALSA=m
CONFIG_VIDEO_EM28XX_DVB=m
CONFIG_VIDEO_EM28XX_RC=m

#
# Software defined radio USB devices
#
CONFIG_USB_AIRSPY=m
CONFIG_USB_HACKRF=m
CONFIG_USB_MSI2500=m
CONFIG_MEDIA_PCI_SUPPORT=y

#
# Media capture support
#
CONFIG_VIDEO_SOLO6X10=m
CONFIG_STA2X11_VIP=m
CONFIG_VIDEO_TW5864=m
CONFIG_VIDEO_TW68=m
CONFIG_VIDEO_TW686X=m
CONFIG_VIDEO_ZORAN=m
CONFIG_VIDEO_ZORAN_DC30=y
CONFIG_VIDEO_ZORAN_ZR36060=y
CONFIG_VIDEO_ZORAN_BUZ=y
CONFIG_VIDEO_ZORAN_DC10=y
CONFIG_VIDEO_ZORAN_LML33=y
CONFIG_VIDEO_ZORAN_LML33R10=y
CONFIG_VIDEO_ZORAN_AVS6EYES=y

#
# Media capture/analog TV support
#
CONFIG_VIDEO_DT3155=m
CONFIG_VIDEO_IVTV=m
CONFIG_VIDEO_IVTV_ALSA=m
CONFIG_VIDEO_FB_IVTV=m
CONFIG_VIDEO_FB_IVTV_FORCE_PAT=y

#
# Media capture/analog/hybrid TV support
#
CONFIG_VIDEO_BT848=m
CONFIG_DVB_BT8XX=m
CONFIG_VIDEO_CX18=m
CONFIG_VIDEO_CX18_ALSA=m
CONFIG_VIDEO_CX23885=m
CONFIG_MEDIA_ALTERA_CI=m
CONFIG_VIDEO_CX25821=m
CONFIG_VIDEO_CX25821_ALSA=m
CONFIG_VIDEO_CX88=m
CONFIG_VIDEO_CX88_ALSA=m
CONFIG_VIDEO_CX88_BLACKBIRD=m
CONFIG_VIDEO_CX88_DVB=m
CONFIG_VIDEO_CX88_ENABLE_VP3054=y
CONFIG_VIDEO_CX88_VP3054=m
CONFIG_VIDEO_CX88_MPEG=m
CONFIG_VIDEO_SAA7134=m
CONFIG_VIDEO_SAA7134_ALSA=m
CONFIG_VIDEO_SAA7134_RC=y
CONFIG_VIDEO_SAA7134_DVB=m
CONFIG_VIDEO_SAA7134_GO7007=m
CONFIG_VIDEO_SAA7164=m

#
# Media digital TV PCI Adapters
#
CONFIG_DVB_B2C2_FLEXCOP_PCI=m
CONFIG_DVB_B2C2_FLEXCOP_PCI_DEBUG=y
CONFIG_DVB_DDBRIDGE=m
CONFIG_DVB_DDBRIDGE_MSIENABLE=y
CONFIG_DVB_DM1105=m
CONFIG_MANTIS_CORE=m
CONFIG_DVB_MANTIS=m
CONFIG_DVB_HOPPER=m
CONFIG_DVB_NETUP_UNIDVB=m
CONFIG_DVB_NGENE=m
CONFIG_DVB_PLUTO2=m
CONFIG_DVB_PT1=m
CONFIG_DVB_PT3=m
CONFIG_DVB_SMIPCIE=m
CONFIG_VIDEO_IPU3_CIO2=m
CONFIG_CIO2_BRIDGE=y
CONFIG_RADIO_ADAPTERS=m
CONFIG_RADIO_MAXIRADIO=m
CONFIG_RADIO_SAA7706H=m
CONFIG_RADIO_SHARK=m
CONFIG_RADIO_SHARK2=m
CONFIG_RADIO_SI4713=m
CONFIG_RADIO_SI476X=m
CONFIG_RADIO_TEA575X=m
CONFIG_RADIO_TEA5764=m
CONFIG_RADIO_TEF6862=m
CONFIG_RADIO_TIMBERDALE=m
CONFIG_RADIO_WL1273=m
CONFIG_USB_DSBR=m
CONFIG_USB_KEENE=m
CONFIG_USB_MA901=m
CONFIG_USB_MR800=m
CONFIG_USB_RAREMONO=m
CONFIG_RADIO_SI470X=m
CONFIG_USB_SI470X=m
CONFIG_I2C_SI470X=m
CONFIG_USB_SI4713=m
CONFIG_PLATFORM_SI4713=m
CONFIG_I2C_SI4713=m
CONFIG_RADIO_WL128X=m
CONFIG_V4L_RADIO_ISA_DRIVERS=y
CONFIG_RADIO_AZTECH=m
CONFIG_RADIO_CADET=m
CONFIG_RADIO_GEMTEK=m
CONFIG_RADIO_ISA=m
CONFIG_RADIO_MIROPCM20=m
CONFIG_RADIO_RTRACK=m
CONFIG_RADIO_RTRACK2=m
CONFIG_RADIO_SF16FMI=m
CONFIG_RADIO_SF16FMR2=m
CONFIG_RADIO_TERRATEC=m
CONFIG_RADIO_TRUST=m
CONFIG_RADIO_TYPHOON=m
CONFIG_RADIO_ZOLTRIX=m
CONFIG_MEDIA_PLATFORM_DRIVERS=y
CONFIG_V4L_PLATFORM_DRIVERS=y
CONFIG_SDR_PLATFORM_DRIVERS=y
CONFIG_DVB_PLATFORM_DRIVERS=y
CONFIG_V4L_MEM2MEM_DRIVERS=y
CONFIG_VIDEO_MEM2MEM_DEINTERLACE=m
CONFIG_VIDEO_MUX=m

#
# Allegro DVT media platform drivers
#

#
# Amlogic media platform drivers
#

#
# Amphion drivers
#

#
# Aspeed media platform drivers
#
CONFIG_VIDEO_ASPEED=m

#
# Atmel media platform drivers
#

#
# Cadence media platform drivers
#
CONFIG_VIDEO_CADENCE_CSI2RX=m
CONFIG_VIDEO_CADENCE_CSI2TX=m

#
# Chips&Media media platform drivers
#

#
# Intel media platform drivers
#

#
# Marvell media platform drivers
#
CONFIG_VIDEO_CAFE_CCIC=m

#
# Mediatek media platform drivers
#

#
# NVidia media platform drivers
#

#
# NXP media platform drivers
#

#
# Qualcomm media platform drivers
#

#
# Renesas media platform drivers
#

#
# Rockchip media platform drivers
#

#
# Samsung media platform drivers
#

#
# STMicroelectronics media platform drivers
#

#
# Sunxi media platform drivers
#

#
# Texas Instruments drivers
#

#
# Verisilicon media platform drivers
#

#
# VIA media platform drivers
#
CONFIG_VIDEO_VIA_CAMERA=m

#
# Xilinx media platform drivers
#
CONFIG_VIDEO_XILINX=m
CONFIG_VIDEO_XILINX_CSI2RXSS=m
CONFIG_VIDEO_XILINX_TPG=m
CONFIG_VIDEO_XILINX_VTC=m

#
# MMC/SDIO DVB adapters
#
CONFIG_SMS_SDIO_DRV=m

#
# FireWire (IEEE 1394) Adapters
#
CONFIG_DVB_FIREDTV=m
CONFIG_DVB_FIREDTV_INPUT=y
CONFIG_MEDIA_COMMON_OPTIONS=y

#
# common driver options
#
CONFIG_CYPRESS_FIRMWARE=m
CONFIG_TTPCI_EEPROM=m
CONFIG_VIDEO_CX2341X=m
CONFIG_VIDEO_TVEEPROM=m
CONFIG_DVB_B2C2_FLEXCOP=m
CONFIG_DVB_B2C2_FLEXCOP_DEBUG=y
CONFIG_SMS_SIANO_MDTV=m
CONFIG_SMS_SIANO_RC=y
CONFIG_SMS_SIANO_DEBUGFS=y
CONFIG_VIDEOBUF2_CORE=m
CONFIG_VIDEOBUF2_V4L2=m
CONFIG_VIDEOBUF2_MEMOPS=m
CONFIG_VIDEOBUF2_DMA_CONTIG=m
CONFIG_VIDEOBUF2_VMALLOC=m
CONFIG_VIDEOBUF2_DMA_SG=m
CONFIG_VIDEOBUF2_DVB=m
# end of Media drivers

#
# Media ancillary drivers
#
CONFIG_MEDIA_ATTACH=y

#
# IR I2C driver auto-selected by 'Autoselect ancillary drivers'
#
CONFIG_VIDEO_IR_I2C=m

#
# Camera sensor devices
#
CONFIG_VIDEO_APTINA_PLL=m
CONFIG_VIDEO_CCS_PLL=m
CONFIG_VIDEO_AR0521=m
CONFIG_VIDEO_HI556=m
CONFIG_VIDEO_HI846=m
CONFIG_VIDEO_HI847=m
CONFIG_VIDEO_IMX208=m
CONFIG_VIDEO_IMX214=m
CONFIG_VIDEO_IMX219=m
CONFIG_VIDEO_IMX258=m
CONFIG_VIDEO_IMX274=m
CONFIG_VIDEO_IMX290=m
CONFIG_VIDEO_IMX319=m
CONFIG_VIDEO_IMX334=m
CONFIG_VIDEO_IMX335=m
CONFIG_VIDEO_IMX355=m
CONFIG_VIDEO_IMX412=m
CONFIG_VIDEO_MAX9271_LIB=m
CONFIG_VIDEO_MT9M001=m
CONFIG_VIDEO_MT9M032=m
CONFIG_VIDEO_MT9M111=m
CONFIG_VIDEO_MT9P031=m
CONFIG_VIDEO_MT9T001=m
CONFIG_VIDEO_MT9T112=m
CONFIG_VIDEO_MT9V011=m
CONFIG_VIDEO_MT9V032=m
CONFIG_VIDEO_MT9V111=m
CONFIG_VIDEO_NOON010PC30=m
CONFIG_VIDEO_OG01A1B=m
CONFIG_VIDEO_OV02A10=m
CONFIG_VIDEO_OV08D10=m
CONFIG_VIDEO_OV13858=m
CONFIG_VIDEO_OV13B10=m
CONFIG_VIDEO_OV2640=m
CONFIG_VIDEO_OV2659=m
CONFIG_VIDEO_OV2680=m
CONFIG_VIDEO_OV2685=m
CONFIG_VIDEO_OV2740=m
CONFIG_VIDEO_OV5640=m
CONFIG_VIDEO_OV5645=m
CONFIG_VIDEO_OV5647=m
CONFIG_VIDEO_OV5648=m
CONFIG_VIDEO_OV5670=m
CONFIG_VIDEO_OV5675=m
CONFIG_VIDEO_OV5693=m
CONFIG_VIDEO_OV5695=m
CONFIG_VIDEO_OV6650=m
CONFIG_VIDEO_OV7251=m
CONFIG_VIDEO_OV7640=m
CONFIG_VIDEO_OV7670=m
CONFIG_VIDEO_OV772X=m
CONFIG_VIDEO_OV7740=m
CONFIG_VIDEO_OV8856=m
CONFIG_VIDEO_OV8865=m
CONFIG_VIDEO_OV9282=m
CONFIG_VIDEO_OV9640=m
CONFIG_VIDEO_OV9650=m
CONFIG_VIDEO_OV9734=m
CONFIG_VIDEO_RDACM20=m
CONFIG_VIDEO_RDACM21=m
CONFIG_VIDEO_RJ54N1=m
CONFIG_VIDEO_S5C73M3=m
CONFIG_VIDEO_S5K4ECGX=m
CONFIG_VIDEO_S5K5BAF=m
CONFIG_VIDEO_S5K6A3=m
CONFIG_VIDEO_S5K6AA=m
CONFIG_VIDEO_SR030PC30=m
CONFIG_VIDEO_VS6624=m
CONFIG_VIDEO_CCS=m
CONFIG_VIDEO_ET8EK8=m
CONFIG_VIDEO_M5MOLS=m
# end of Camera sensor devices

#
# Lens drivers
#
CONFIG_VIDEO_AD5820=m
CONFIG_VIDEO_AK7375=m
CONFIG_VIDEO_DW9714=m
CONFIG_VIDEO_DW9768=m
CONFIG_VIDEO_DW9807_VCM=m
# end of Lens drivers

#
# Flash devices
#
CONFIG_VIDEO_ADP1653=m
CONFIG_VIDEO_LM3560=m
CONFIG_VIDEO_LM3646=m
# end of Flash devices

#
# Audio decoders, processors and mixers
#
CONFIG_VIDEO_CS3308=m
CONFIG_VIDEO_CS5345=m
CONFIG_VIDEO_CS53L32A=m
CONFIG_VIDEO_MSP3400=m
CONFIG_VIDEO_SONY_BTF_MPX=m
CONFIG_VIDEO_TDA1997X=m
CONFIG_VIDEO_TDA7432=m
CONFIG_VIDEO_TDA9840=m
CONFIG_VIDEO_TEA6415C=m
CONFIG_VIDEO_TEA6420=m
CONFIG_VIDEO_TLV320AIC23B=m
CONFIG_VIDEO_TVAUDIO=m
CONFIG_VIDEO_UDA1342=m
CONFIG_VIDEO_VP27SMPX=m
CONFIG_VIDEO_WM8739=m
CONFIG_VIDEO_WM8775=m
# end of Audio decoders, processors and mixers

#
# RDS decoders
#
CONFIG_VIDEO_SAA6588=m
# end of RDS decoders

#
# Video decoders
#
CONFIG_VIDEO_ADV7180=m
CONFIG_VIDEO_ADV7183=m
CONFIG_VIDEO_ADV748X=m
CONFIG_VIDEO_ADV7604=m
CONFIG_VIDEO_ADV7604_CEC=y
CONFIG_VIDEO_ADV7842=m
CONFIG_VIDEO_ADV7842_CEC=y
CONFIG_VIDEO_BT819=m
CONFIG_VIDEO_BT856=m
CONFIG_VIDEO_BT866=m
CONFIG_VIDEO_ISL7998X=m
CONFIG_VIDEO_KS0127=m
CONFIG_VIDEO_MAX9286=m
CONFIG_VIDEO_ML86V7667=m
CONFIG_VIDEO_SAA7110=m
CONFIG_VIDEO_SAA711X=m
CONFIG_VIDEO_TC358743=m
CONFIG_VIDEO_TC358743_CEC=y
CONFIG_VIDEO_TVP514X=m
CONFIG_VIDEO_TVP5150=m
CONFIG_VIDEO_TVP7002=m
CONFIG_VIDEO_TW2804=m
CONFIG_VIDEO_TW9903=m
CONFIG_VIDEO_TW9906=m
CONFIG_VIDEO_TW9910=m
CONFIG_VIDEO_VPX3220=m

#
# Video and audio decoders
#
CONFIG_VIDEO_SAA717X=m
CONFIG_VIDEO_CX25840=m
# end of Video decoders

#
# Video encoders
#
CONFIG_VIDEO_AD9389B=m
CONFIG_VIDEO_ADV7170=m
CONFIG_VIDEO_ADV7175=m
CONFIG_VIDEO_ADV7343=m
CONFIG_VIDEO_ADV7393=m
CONFIG_VIDEO_AK881X=m
CONFIG_VIDEO_SAA7127=m
CONFIG_VIDEO_SAA7185=m
CONFIG_VIDEO_THS8200=m
# end of Video encoders

#
# Video improvement chips
#
CONFIG_VIDEO_UPD64031A=m
CONFIG_VIDEO_UPD64083=m
# end of Video improvement chips

#
# Audio/Video compression chips
#
CONFIG_VIDEO_SAA6752HS=m
# end of Audio/Video compression chips

#
# SDR tuner chips
#
CONFIG_SDR_MAX2175=m
# end of SDR tuner chips

#
# Miscellaneous helper chips
#
CONFIG_VIDEO_I2C=m
CONFIG_VIDEO_M52790=m
CONFIG_VIDEO_ST_MIPID02=m
CONFIG_VIDEO_THS7303=m
# end of Miscellaneous helper chips

#
# Media SPI Adapters
#
CONFIG_CXD2880_SPI_DRV=m
CONFIG_VIDEO_GS1662=m
# end of Media SPI Adapters

CONFIG_MEDIA_TUNER=m

#
# Customize TV tuners
#
CONFIG_MEDIA_TUNER_E4000=m
CONFIG_MEDIA_TUNER_FC0011=m
CONFIG_MEDIA_TUNER_FC0012=m
CONFIG_MEDIA_TUNER_FC0013=m
CONFIG_MEDIA_TUNER_FC2580=m
CONFIG_MEDIA_TUNER_IT913X=m
CONFIG_MEDIA_TUNER_M88RS6000T=m
CONFIG_MEDIA_TUNER_MAX2165=m
CONFIG_MEDIA_TUNER_MC44S803=m
CONFIG_MEDIA_TUNER_MSI001=m
CONFIG_MEDIA_TUNER_MT2060=m
CONFIG_MEDIA_TUNER_MT2063=m
CONFIG_MEDIA_TUNER_MT20XX=m
CONFIG_MEDIA_TUNER_MT2131=m
CONFIG_MEDIA_TUNER_MT2266=m
CONFIG_MEDIA_TUNER_MXL301RF=m
CONFIG_MEDIA_TUNER_MXL5005S=m
CONFIG_MEDIA_TUNER_MXL5007T=m
CONFIG_MEDIA_TUNER_QM1D1B0004=m
CONFIG_MEDIA_TUNER_QM1D1C0042=m
CONFIG_MEDIA_TUNER_QT1010=m
CONFIG_MEDIA_TUNER_R820T=m
CONFIG_MEDIA_TUNER_SI2157=m
CONFIG_MEDIA_TUNER_SIMPLE=m
CONFIG_MEDIA_TUNER_TDA18212=m
CONFIG_MEDIA_TUNER_TDA18218=m
CONFIG_MEDIA_TUNER_TDA18250=m
CONFIG_MEDIA_TUNER_TDA18271=m
CONFIG_MEDIA_TUNER_TDA827X=m
CONFIG_MEDIA_TUNER_TDA8290=m
CONFIG_MEDIA_TUNER_TDA9887=m
CONFIG_MEDIA_TUNER_TEA5761=m
CONFIG_MEDIA_TUNER_TEA5767=m
CONFIG_MEDIA_TUNER_TUA9001=m
CONFIG_MEDIA_TUNER_XC2028=m
CONFIG_MEDIA_TUNER_XC4000=m
CONFIG_MEDIA_TUNER_XC5000=m
# end of Customize TV tuners

#
# Customise DVB Frontends
#

#
# Multistandard (satellite) frontends
#
CONFIG_DVB_M88DS3103=m
CONFIG_DVB_MXL5XX=m
CONFIG_DVB_STB0899=m
CONFIG_DVB_STB6100=m
CONFIG_DVB_STV090x=m
CONFIG_DVB_STV0910=m
CONFIG_DVB_STV6110x=m
CONFIG_DVB_STV6111=m

#
# Multistandard (cable + terrestrial) frontends
#
CONFIG_DVB_DRXK=m
CONFIG_DVB_MN88472=m
CONFIG_DVB_MN88473=m
CONFIG_DVB_SI2165=m
CONFIG_DVB_TDA18271C2DD=m

#
# DVB-S (satellite) frontends
#
CONFIG_DVB_CX24110=m
CONFIG_DVB_CX24116=m
CONFIG_DVB_CX24117=m
CONFIG_DVB_CX24120=m
CONFIG_DVB_CX24123=m
CONFIG_DVB_DS3000=m
CONFIG_DVB_MB86A16=m
CONFIG_DVB_MT312=m
CONFIG_DVB_S5H1420=m
CONFIG_DVB_SI21XX=m
CONFIG_DVB_STB6000=m
CONFIG_DVB_STV0288=m
CONFIG_DVB_STV0299=m
CONFIG_DVB_STV0900=m
CONFIG_DVB_STV6110=m
CONFIG_DVB_TDA10071=m
CONFIG_DVB_TDA10086=m
CONFIG_DVB_TDA8083=m
CONFIG_DVB_TDA8261=m
CONFIG_DVB_TDA826X=m
CONFIG_DVB_TS2020=m
CONFIG_DVB_TUA6100=m
CONFIG_DVB_TUNER_CX24113=m
CONFIG_DVB_TUNER_ITD1000=m
CONFIG_DVB_VES1X93=m
CONFIG_DVB_ZL10036=m
CONFIG_DVB_ZL10039=m

#
# DVB-T (terrestrial) frontends
#
CONFIG_DVB_AF9013=m
CONFIG_DVB_AS102_FE=m
CONFIG_DVB_CX22700=m
CONFIG_DVB_CX22702=m
CONFIG_DVB_CXD2820R=m
CONFIG_DVB_CXD2841ER=m
CONFIG_DVB_DIB3000MB=m
CONFIG_DVB_DIB3000MC=m
CONFIG_DVB_DIB7000M=m
CONFIG_DVB_DIB7000P=m
CONFIG_DVB_DIB9000=m
CONFIG_DVB_DRXD=m
CONFIG_DVB_EC100=m
CONFIG_DVB_GP8PSK_FE=m
CONFIG_DVB_L64781=m
CONFIG_DVB_MT352=m
CONFIG_DVB_NXT6000=m
CONFIG_DVB_RTL2830=m
CONFIG_DVB_RTL2832=m
CONFIG_DVB_RTL2832_SDR=m
CONFIG_DVB_S5H1432=m
CONFIG_DVB_SI2168=m
CONFIG_DVB_SP887X=m
CONFIG_DVB_STV0367=m
CONFIG_DVB_TDA10048=m
CONFIG_DVB_TDA1004X=m
CONFIG_DVB_ZD1301_DEMOD=m
CONFIG_DVB_ZL10353=m
CONFIG_DVB_CXD2880=m

#
# DVB-C (cable) frontends
#
CONFIG_DVB_STV0297=m
CONFIG_DVB_TDA10021=m
CONFIG_DVB_TDA10023=m
CONFIG_DVB_VES1820=m

#
# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
#
CONFIG_DVB_AU8522=m
CONFIG_DVB_AU8522_DTV=m
CONFIG_DVB_AU8522_V4L=m
CONFIG_DVB_BCM3510=m
CONFIG_DVB_LG2160=m
CONFIG_DVB_LGDT3305=m
CONFIG_DVB_LGDT3306A=m
CONFIG_DVB_LGDT330X=m
CONFIG_DVB_MXL692=m
CONFIG_DVB_NXT200X=m
CONFIG_DVB_OR51132=m
CONFIG_DVB_OR51211=m
CONFIG_DVB_S5H1409=m
CONFIG_DVB_S5H1411=m

#
# ISDB-T (terrestrial) frontends
#
CONFIG_DVB_DIB8000=m
CONFIG_DVB_MB86A20S=m
CONFIG_DVB_S921=m

#
# ISDB-S (satellite) & ISDB-T (terrestrial) frontends
#
CONFIG_DVB_MN88443X=m
CONFIG_DVB_TC90522=m

#
# Digital terrestrial only tuners/PLL
#
CONFIG_DVB_PLL=m
CONFIG_DVB_TUNER_DIB0070=m
CONFIG_DVB_TUNER_DIB0090=m

#
# SEC control devices for DVB-S
#
CONFIG_DVB_A8293=m
CONFIG_DVB_AF9033=m
CONFIG_DVB_ASCOT2E=m
CONFIG_DVB_ATBM8830=m
CONFIG_DVB_HELENE=m
CONFIG_DVB_HORUS3A=m
CONFIG_DVB_ISL6405=m
CONFIG_DVB_ISL6421=m
CONFIG_DVB_ISL6423=m
CONFIG_DVB_IX2505V=m
CONFIG_DVB_LGS8GL5=m
CONFIG_DVB_LGS8GXX=m
CONFIG_DVB_LNBH25=m
CONFIG_DVB_LNBH29=m
CONFIG_DVB_LNBP21=m
CONFIG_DVB_LNBP22=m
CONFIG_DVB_M88RS2000=m
CONFIG_DVB_TDA665x=m
CONFIG_DVB_DRX39XYJ=m

#
# Common Interface (EN50221) controller drivers
#
CONFIG_DVB_CXD2099=m
CONFIG_DVB_SP2=m
# end of Customise DVB Frontends
# end of Media ancillary drivers

#
# Graphics support
#
CONFIG_APERTURE_HELPERS=y
CONFIG_AGP=m
CONFIG_AGP_ALI=m
CONFIG_AGP_ATI=m
# CONFIG_AGP_AMD is not set
CONFIG_AGP_INTEL=m
CONFIG_AGP_NVIDIA=m
CONFIG_AGP_SIS=m
CONFIG_AGP_SWORKS=m
CONFIG_AGP_VIA=m
CONFIG_AGP_EFFICEON=m
CONFIG_INTEL_GTT=m
CONFIG_DRM=m
CONFIG_DRM_MIPI_DBI=m
CONFIG_DRM_MIPI_DSI=y
CONFIG_DRM_USE_DYNAMIC_DEBUG=y
CONFIG_DRM_KMS_HELPER=m
CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS=y
CONFIG_DRM_DEBUG_MODESET_LOCK=y
CONFIG_DRM_FBDEV_EMULATION=y
CONFIG_DRM_FBDEV_OVERALLOC=100
CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM=y
CONFIG_DRM_LOAD_EDID_FIRMWARE=y
CONFIG_DRM_DP_AUX_BUS=m
CONFIG_DRM_DISPLAY_HELPER=m
CONFIG_DRM_DISPLAY_DP_HELPER=y
CONFIG_DRM_DISPLAY_HDCP_HELPER=y
CONFIG_DRM_DISPLAY_HDMI_HELPER=y
CONFIG_DRM_DP_AUX_CHARDEV=y
CONFIG_DRM_DP_CEC=y
CONFIG_DRM_TTM=m
CONFIG_DRM_BUDDY=m
CONFIG_DRM_VRAM_HELPER=m
CONFIG_DRM_TTM_HELPER=m
CONFIG_DRM_GEM_DMA_HELPER=m
CONFIG_DRM_GEM_SHMEM_HELPER=m
CONFIG_DRM_SCHED=m

#
# I2C encoder or helper chips
#
CONFIG_DRM_I2C_CH7006=m
CONFIG_DRM_I2C_SIL164=m
CONFIG_DRM_I2C_NXP_TDA998X=m
CONFIG_DRM_I2C_NXP_TDA9950=m
# end of I2C encoder or helper chips

#
# ARM devices
#
CONFIG_DRM_KOMEDA=m
# end of ARM devices

# CONFIG_DRM_RADEON is not set
# CONFIG_DRM_AMDGPU is not set
# CONFIG_DRM_NOUVEAU is not set
CONFIG_DRM_I915=m
CONFIG_DRM_I915_FORCE_PROBE=""
CONFIG_DRM_I915_CAPTURE_ERROR=y
CONFIG_DRM_I915_COMPRESS_ERROR=y
CONFIG_DRM_I915_USERPTR=y
CONFIG_DRM_I915_PXP=y

#
# drm/i915 Debugging
#
CONFIG_DRM_I915_WERROR=y
# CONFIG_DRM_I915_DEBUG is not set
CONFIG_DRM_I915_DEBUG_MMIO=y
# CONFIG_DRM_I915_DEBUG_GEM is not set
CONFIG_DRM_I915_SW_FENCE_DEBUG_OBJECTS=y
CONFIG_DRM_I915_SW_FENCE_CHECK_DAG=y
CONFIG_DRM_I915_DEBUG_GUC=y
# CONFIG_DRM_I915_SELFTEST is not set
CONFIG_DRM_I915_LOW_LEVEL_TRACEPOINTS=y
CONFIG_DRM_I915_DEBUG_VBLANK_EVADE=y
CONFIG_DRM_I915_DEBUG_RUNTIME_PM=y
# end of drm/i915 Debugging

#
# drm/i915 Profile Guided Optimisation
#
CONFIG_DRM_I915_REQUEST_TIMEOUT=20000
CONFIG_DRM_I915_FENCE_TIMEOUT=10000
CONFIG_DRM_I915_USERFAULT_AUTOSUSPEND=250
CONFIG_DRM_I915_HEARTBEAT_INTERVAL=2500
CONFIG_DRM_I915_PREEMPT_TIMEOUT=640
CONFIG_DRM_I915_MAX_REQUEST_BUSYWAIT=8000
CONFIG_DRM_I915_STOP_TIMEOUT=100
CONFIG_DRM_I915_TIMESLICE_DURATION=1
# end of drm/i915 Profile Guided Optimisation

CONFIG_DRM_VGEM=m
CONFIG_DRM_VKMS=m
CONFIG_DRM_VMWGFX=m
CONFIG_DRM_VMWGFX_FBCON=y
CONFIG_DRM_VMWGFX_MKSSTATS=y
CONFIG_DRM_GMA500=m
CONFIG_DRM_UDL=m
CONFIG_DRM_AST=m
CONFIG_DRM_MGAG200=m
CONFIG_DRM_RCAR_DW_HDMI=m
CONFIG_DRM_RCAR_USE_LVDS=y
CONFIG_DRM_RCAR_MIPI_DSI=m
CONFIG_DRM_QXL=m
CONFIG_DRM_VIRTIO_GPU=m
CONFIG_DRM_PANEL=y

#
# Display Panels
#
CONFIG_DRM_PANEL_ABT_Y030XX067A=m
CONFIG_DRM_PANEL_ARM_VERSATILE=m
CONFIG_DRM_PANEL_ASUS_Z00T_TM5P5_NT35596=m
CONFIG_DRM_PANEL_BOE_BF060Y8M_AJ0=m
CONFIG_DRM_PANEL_BOE_HIMAX8279D=m
CONFIG_DRM_PANEL_BOE_TV101WUM_NL6=m
CONFIG_DRM_PANEL_DSI_CM=m
CONFIG_DRM_PANEL_LVDS=m
CONFIG_DRM_PANEL_SIMPLE=m
CONFIG_DRM_PANEL_EDP=m
CONFIG_DRM_PANEL_EBBG_FT8719=m
CONFIG_DRM_PANEL_ELIDA_KD35T133=m
CONFIG_DRM_PANEL_FEIXIN_K101_IM2BA02=m
CONFIG_DRM_PANEL_FEIYANG_FY07024DI26A30D=m
CONFIG_DRM_PANEL_ILITEK_IL9322=m
CONFIG_DRM_PANEL_ILITEK_ILI9341=m
CONFIG_DRM_PANEL_ILITEK_ILI9881C=m
CONFIG_DRM_PANEL_INNOLUX_EJ030NA=m
CONFIG_DRM_PANEL_INNOLUX_P079ZCA=m
CONFIG_DRM_PANEL_JDI_LT070ME05000=m
CONFIG_DRM_PANEL_JDI_R63452=m
CONFIG_DRM_PANEL_KHADAS_TS050=m
CONFIG_DRM_PANEL_KINGDISPLAY_KD097D04=m
CONFIG_DRM_PANEL_LEADTEK_LTK050H3146W=m
CONFIG_DRM_PANEL_LEADTEK_LTK500HD1829=m
CONFIG_DRM_PANEL_SAMSUNG_LD9040=m
CONFIG_DRM_PANEL_LG_LB035Q02=m
CONFIG_DRM_PANEL_LG_LG4573=m
CONFIG_DRM_PANEL_NEC_NL8048HL11=m
CONFIG_DRM_PANEL_NEWVISION_NV3052C=m
CONFIG_DRM_PANEL_NOVATEK_NT35510=m
CONFIG_DRM_PANEL_NOVATEK_NT35560=m
CONFIG_DRM_PANEL_NOVATEK_NT35950=m
CONFIG_DRM_PANEL_NOVATEK_NT36672A=m
CONFIG_DRM_PANEL_NOVATEK_NT39016=m
CONFIG_DRM_PANEL_MANTIX_MLAF057WE51=m
CONFIG_DRM_PANEL_OLIMEX_LCD_OLINUXINO=m
CONFIG_DRM_PANEL_ORISETECH_OTM8009A=m
CONFIG_DRM_PANEL_OSD_OSD101T2587_53TS=m
CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00=m
CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN=m
CONFIG_DRM_PANEL_RAYDIUM_RM67191=m
CONFIG_DRM_PANEL_RAYDIUM_RM68200=m
CONFIG_DRM_PANEL_RONBO_RB070D30=m
CONFIG_DRM_PANEL_SAMSUNG_ATNA33XC20=m
CONFIG_DRM_PANEL_SAMSUNG_DB7430=m
CONFIG_DRM_PANEL_SAMSUNG_S6D16D0=m
CONFIG_DRM_PANEL_SAMSUNG_S6D27A1=m
CONFIG_DRM_PANEL_SAMSUNG_S6E3HA2=m
CONFIG_DRM_PANEL_SAMSUNG_S6E63J0X03=m
CONFIG_DRM_PANEL_SAMSUNG_S6E63M0=m
CONFIG_DRM_PANEL_SAMSUNG_S6E63M0_SPI=m
CONFIG_DRM_PANEL_SAMSUNG_S6E63M0_DSI=m
CONFIG_DRM_PANEL_SAMSUNG_S6E88A0_AMS452EF01=m
CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0=m
CONFIG_DRM_PANEL_SAMSUNG_SOFEF00=m
CONFIG_DRM_PANEL_SEIKO_43WVF1G=m
CONFIG_DRM_PANEL_SHARP_LQ101R1SX01=m
CONFIG_DRM_PANEL_SHARP_LS037V7DW01=m
CONFIG_DRM_PANEL_SHARP_LS043T1LE01=m
CONFIG_DRM_PANEL_SHARP_LS060T1SX01=m
CONFIG_DRM_PANEL_SITRONIX_ST7701=m
CONFIG_DRM_PANEL_SITRONIX_ST7703=m
CONFIG_DRM_PANEL_SITRONIX_ST7789V=m
CONFIG_DRM_PANEL_SONY_ACX565AKM=m
CONFIG_DRM_PANEL_SONY_TULIP_TRULY_NT35521=m
CONFIG_DRM_PANEL_TDO_TL070WSH30=m
CONFIG_DRM_PANEL_TPO_TD028TTEC1=m
CONFIG_DRM_PANEL_TPO_TD043MTEA1=m
CONFIG_DRM_PANEL_TPO_TPG110=m
CONFIG_DRM_PANEL_TRULY_NT35597_WQXGA=m
CONFIG_DRM_PANEL_VISIONOX_RM69299=m
CONFIG_DRM_PANEL_WIDECHIPS_WS2401=m
CONFIG_DRM_PANEL_XINPENG_XPP055C272=m
# end of Display Panels

CONFIG_DRM_BRIDGE=y
CONFIG_DRM_PANEL_BRIDGE=y

#
# Display Interface Bridges
#
CONFIG_DRM_CDNS_DSI=m
CONFIG_DRM_CHIPONE_ICN6211=m
CONFIG_DRM_CHRONTEL_CH7033=m
CONFIG_DRM_CROS_EC_ANX7688=m
CONFIG_DRM_DISPLAY_CONNECTOR=m
CONFIG_DRM_ITE_IT6505=m
CONFIG_DRM_LONTIUM_LT8912B=m
CONFIG_DRM_LONTIUM_LT9211=m
CONFIG_DRM_LONTIUM_LT9611=m
CONFIG_DRM_LONTIUM_LT9611UXC=m
CONFIG_DRM_ITE_IT66121=m
CONFIG_DRM_LVDS_CODEC=m
CONFIG_DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW=m
CONFIG_DRM_NWL_MIPI_DSI=m
CONFIG_DRM_NXP_PTN3460=m
CONFIG_DRM_PARADE_PS8622=m
CONFIG_DRM_PARADE_PS8640=m
CONFIG_DRM_SIL_SII8620=m
CONFIG_DRM_SII902X=m
CONFIG_DRM_SII9234=m
CONFIG_DRM_SIMPLE_BRIDGE=m
CONFIG_DRM_THINE_THC63LVD1024=m
CONFIG_DRM_TOSHIBA_TC358762=m
CONFIG_DRM_TOSHIBA_TC358764=m
CONFIG_DRM_TOSHIBA_TC358767=m
CONFIG_DRM_TOSHIBA_TC358768=m
CONFIG_DRM_TOSHIBA_TC358775=m
CONFIG_DRM_TI_DLPC3433=m
CONFIG_DRM_TI_TFP410=m
CONFIG_DRM_TI_SN65DSI83=m
CONFIG_DRM_TI_SN65DSI86=m
CONFIG_DRM_TI_TPD12S015=m
CONFIG_DRM_ANALOGIX_ANX6345=m
CONFIG_DRM_ANALOGIX_ANX78XX=m
CONFIG_DRM_ANALOGIX_DP=m
CONFIG_DRM_ANALOGIX_ANX7625=m
CONFIG_DRM_I2C_ADV7511=m
CONFIG_DRM_I2C_ADV7511_AUDIO=y
CONFIG_DRM_I2C_ADV7511_CEC=y
CONFIG_DRM_CDNS_MHDP8546=m
CONFIG_DRM_DW_HDMI=m
CONFIG_DRM_DW_HDMI_AHB_AUDIO=m
CONFIG_DRM_DW_HDMI_I2S_AUDIO=m
CONFIG_DRM_DW_HDMI_GP_AUDIO=m
CONFIG_DRM_DW_HDMI_CEC=m
# end of Display Interface Bridges

CONFIG_DRM_ETNAVIV=m
CONFIG_DRM_ETNAVIV_THERMAL=y
CONFIG_DRM_LOGICVC=m
CONFIG_DRM_MXS=y
CONFIG_DRM_MXSFB=m
CONFIG_DRM_IMX_LCDIF=m
CONFIG_DRM_ARCPGU=m
CONFIG_DRM_BOCHS=m
CONFIG_DRM_CIRRUS_QEMU=m
CONFIG_DRM_GM12U320=m
CONFIG_DRM_PANEL_MIPI_DBI=m
CONFIG_DRM_SIMPLEDRM=m
CONFIG_TINYDRM_HX8357D=m
CONFIG_TINYDRM_ILI9163=m
CONFIG_TINYDRM_ILI9225=m
CONFIG_TINYDRM_ILI9341=m
CONFIG_TINYDRM_ILI9486=m
CONFIG_TINYDRM_MI0283QT=m
CONFIG_TINYDRM_REPAPER=m
CONFIG_TINYDRM_ST7586=m
CONFIG_TINYDRM_ST7735R=m
CONFIG_DRM_VBOXVIDEO=m
CONFIG_DRM_GUD=m
CONFIG_DRM_SSD130X=m
CONFIG_DRM_SSD130X_I2C=m
CONFIG_DRM_SSD130X_SPI=m
CONFIG_DRM_HYPERV=m
CONFIG_DRM_LEGACY=y
CONFIG_DRM_TDFX=m
CONFIG_DRM_R128=m
# CONFIG_DRM_I810 is not set
CONFIG_DRM_MGA=m
CONFIG_DRM_SIS=m
CONFIG_DRM_VIA=m
CONFIG_DRM_SAVAGE=m
CONFIG_DRM_PANEL_ORIENTATION_QUIRKS=m
CONFIG_DRM_NOMODESET=y
CONFIG_DRM_PRIVACY_SCREEN=y

#
# Frame buffer Devices
#
CONFIG_FB_CMDLINE=y
CONFIG_FB_NOTIFY=y
CONFIG_FB=m
CONFIG_FIRMWARE_EDID=y
CONFIG_FB_DDC=m
CONFIG_FB_CFB_FILLRECT=m
CONFIG_FB_CFB_COPYAREA=m
CONFIG_FB_CFB_IMAGEBLIT=m
CONFIG_FB_SYS_FILLRECT=m
CONFIG_FB_SYS_COPYAREA=m
CONFIG_FB_SYS_IMAGEBLIT=m
CONFIG_FB_FOREIGN_ENDIAN=y
CONFIG_FB_BOTH_ENDIAN=y
# CONFIG_FB_BIG_ENDIAN is not set
# CONFIG_FB_LITTLE_ENDIAN is not set
CONFIG_FB_SYS_FOPS=m
CONFIG_FB_DEFERRED_IO=y
CONFIG_FB_HECUBA=m
CONFIG_FB_SVGALIB=m
CONFIG_FB_BACKLIGHT=m
CONFIG_FB_MODE_HELPERS=y
CONFIG_FB_TILEBLITTING=y

#
# Frame buffer hardware drivers
#
CONFIG_FB_CIRRUS=m
CONFIG_FB_PM2=m
CONFIG_FB_PM2_FIFO_DISCONNECT=y
CONFIG_FB_CYBER2000=m
CONFIG_FB_CYBER2000_DDC=y
CONFIG_FB_ARC=m
# CONFIG_FB_VGA16 is not set
CONFIG_FB_UVESA=m
CONFIG_FB_N411=m
CONFIG_FB_HGA=m
CONFIG_FB_OPENCORES=m
CONFIG_FB_S1D13XXX=m
CONFIG_FB_NVIDIA=m
CONFIG_FB_NVIDIA_I2C=y
CONFIG_FB_NVIDIA_DEBUG=y
CONFIG_FB_NVIDIA_BACKLIGHT=y
CONFIG_FB_RIVA=m
CONFIG_FB_RIVA_I2C=y
CONFIG_FB_RIVA_DEBUG=y
CONFIG_FB_RIVA_BACKLIGHT=y
CONFIG_FB_I740=m
CONFIG_FB_I810=m
CONFIG_FB_I810_GTF=y
CONFIG_FB_I810_I2C=y
CONFIG_FB_LE80578=m
CONFIG_FB_CARILLO_RANCH=m
CONFIG_FB_INTEL=m
CONFIG_FB_INTEL_DEBUG=y
CONFIG_FB_INTEL_I2C=y
CONFIG_FB_MATROX=m
CONFIG_FB_MATROX_MILLENIUM=y
CONFIG_FB_MATROX_MYSTIQUE=y
CONFIG_FB_MATROX_G=y
CONFIG_FB_MATROX_I2C=m
CONFIG_FB_MATROX_MAVEN=m
# CONFIG_FB_RADEON is not set
CONFIG_FB_ATY128=m
CONFIG_FB_ATY128_BACKLIGHT=y
CONFIG_FB_ATY=m
CONFIG_FB_ATY_CT=y
CONFIG_FB_ATY_GENERIC_LCD=y
CONFIG_FB_ATY_GX=y
CONFIG_FB_ATY_BACKLIGHT=y
CONFIG_FB_S3=m
CONFIG_FB_S3_DDC=y
CONFIG_FB_SAVAGE=m
CONFIG_FB_SAVAGE_I2C=y
CONFIG_FB_SAVAGE_ACCEL=y
CONFIG_FB_SIS=m
CONFIG_FB_SIS_300=y
CONFIG_FB_SIS_315=y
CONFIG_FB_VIA=m
CONFIG_FB_VIA_DIRECT_PROCFS=y
CONFIG_FB_VIA_X_COMPATIBILITY=y
CONFIG_FB_NEOMAGIC=m
CONFIG_FB_KYRO=m
CONFIG_FB_3DFX=m
CONFIG_FB_3DFX_ACCEL=y
CONFIG_FB_3DFX_I2C=y
CONFIG_FB_VOODOO1=m
CONFIG_FB_VT8623=m
CONFIG_FB_TRIDENT=m
CONFIG_FB_ARK=m
CONFIG_FB_PM3=m
CONFIG_FB_CARMINE=m
CONFIG_FB_CARMINE_DRAM_EVAL=y
# CONFIG_CARMINE_DRAM_CUSTOM is not set
CONFIG_FB_GEODE=y
CONFIG_FB_GEODE_LX=m
CONFIG_FB_GEODE_GX=m
CONFIG_FB_GEODE_GX1=m
CONFIG_FB_SM501=m
CONFIG_FB_SMSCUFX=m
CONFIG_FB_UDL=m
CONFIG_FB_IBM_GXT4500=m
CONFIG_FB_GOLDFISH=m
CONFIG_FB_VIRTUAL=m
CONFIG_FB_METRONOME=m
CONFIG_FB_MB862XX=m
CONFIG_FB_MB862XX_PCI_GDC=y
CONFIG_FB_MB862XX_I2C=y
CONFIG_FB_HYPERV=m
CONFIG_FB_SIMPLE=m
CONFIG_FB_SSD1307=m
CONFIG_FB_SM712=m
# end of Frame buffer Devices

#
# Backlight & LCD device support
#
CONFIG_LCD_CLASS_DEVICE=m
CONFIG_LCD_L4F00242T03=m
CONFIG_LCD_LMS283GF05=m
CONFIG_LCD_LTV350QV=m
CONFIG_LCD_ILI922X=m
CONFIG_LCD_ILI9320=m
CONFIG_LCD_TDO24M=m
CONFIG_LCD_VGG2432A4=m
CONFIG_LCD_PLATFORM=m
CONFIG_LCD_AMS369FG06=m
CONFIG_LCD_LMS501KF03=m
CONFIG_LCD_HX8357=m
CONFIG_LCD_OTM3225A=m
CONFIG_BACKLIGHT_CLASS_DEVICE=m
CONFIG_BACKLIGHT_KTD253=m
CONFIG_BACKLIGHT_LM3533=m
CONFIG_BACKLIGHT_CARILLO_RANCH=m
CONFIG_BACKLIGHT_PWM=m
CONFIG_BACKLIGHT_DA903X=m
CONFIG_BACKLIGHT_DA9052=m
CONFIG_BACKLIGHT_MAX8925=m
CONFIG_BACKLIGHT_MT6370=m
CONFIG_BACKLIGHT_APPLE=m
CONFIG_BACKLIGHT_QCOM_WLED=m
CONFIG_BACKLIGHT_RT4831=m
CONFIG_BACKLIGHT_SAHARA=m
CONFIG_BACKLIGHT_WM831X=m
CONFIG_BACKLIGHT_ADP5520=m
CONFIG_BACKLIGHT_ADP8860=m
CONFIG_BACKLIGHT_ADP8870=m
CONFIG_BACKLIGHT_88PM860X=m
CONFIG_BACKLIGHT_PCF50633=m
CONFIG_BACKLIGHT_AAT2870=m
CONFIG_BACKLIGHT_LM3630A=m
CONFIG_BACKLIGHT_LM3639=m
CONFIG_BACKLIGHT_LP855X=m
CONFIG_BACKLIGHT_LP8788=m
CONFIG_BACKLIGHT_PANDORA=m
CONFIG_BACKLIGHT_SKY81452=m
CONFIG_BACKLIGHT_TPS65217=m
CONFIG_BACKLIGHT_AS3711=m
CONFIG_BACKLIGHT_GPIO=m
CONFIG_BACKLIGHT_LV5207LP=m
CONFIG_BACKLIGHT_BD6107=m
CONFIG_BACKLIGHT_ARCXCNN=m
CONFIG_BACKLIGHT_RAVE_SP=m
CONFIG_BACKLIGHT_LED=m
# end of Backlight & LCD device support

CONFIG_VGASTATE=m
CONFIG_VIDEOMODE_HELPERS=y
CONFIG_HDMI=y

#
# Console display driver support
#
CONFIG_VGA_CONSOLE=y
CONFIG_MDA_CONSOLE=m
CONFIG_DUMMY_CONSOLE=y
CONFIG_DUMMY_CONSOLE_COLUMNS=80
CONFIG_DUMMY_CONSOLE_ROWS=25
CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION=y
CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
# end of Console display driver support

CONFIG_LOGO=y
CONFIG_LOGO_LINUX_MONO=y
CONFIG_LOGO_LINUX_VGA16=y
CONFIG_LOGO_LINUX_CLUT224=y
# end of Graphics support

CONFIG_SOUND=m
CONFIG_SOUND_OSS_CORE=y
CONFIG_SOUND_OSS_CORE_PRECLAIM=y
CONFIG_SND=m
CONFIG_SND_TIMER=m
CONFIG_SND_PCM=m
CONFIG_SND_PCM_ELD=y
CONFIG_SND_PCM_IEC958=y
CONFIG_SND_DMAENGINE_PCM=m
CONFIG_SND_HWDEP=m
CONFIG_SND_SEQ_DEVICE=m
CONFIG_SND_RAWMIDI=m
CONFIG_SND_COMPRESS_OFFLOAD=m
CONFIG_SND_JACK=y
CONFIG_SND_JACK_INPUT_DEV=y
CONFIG_SND_OSSEMUL=y
CONFIG_SND_MIXER_OSS=m
CONFIG_SND_PCM_OSS=m
CONFIG_SND_PCM_OSS_PLUGINS=y
CONFIG_SND_PCM_TIMER=y
CONFIG_SND_HRTIMER=m
CONFIG_SND_DYNAMIC_MINORS=y
CONFIG_SND_MAX_CARDS=32
CONFIG_SND_SUPPORT_OLD_API=y
CONFIG_SND_PROC_FS=y
CONFIG_SND_VERBOSE_PROCFS=y
CONFIG_SND_VERBOSE_PRINTK=y
CONFIG_SND_CTL_FAST_LOOKUP=y
CONFIG_SND_DEBUG=y
CONFIG_SND_DEBUG_VERBOSE=y
CONFIG_SND_PCM_XRUN_DEBUG=y
CONFIG_SND_CTL_INPUT_VALIDATION=y
CONFIG_SND_CTL_DEBUG=y
CONFIG_SND_JACK_INJECTION_DEBUG=y
CONFIG_SND_VMASTER=y
CONFIG_SND_DMA_SGBUF=y
CONFIG_SND_CTL_LED=m
CONFIG_SND_SEQUENCER=m
CONFIG_SND_SEQ_DUMMY=m
CONFIG_SND_SEQUENCER_OSS=m
CONFIG_SND_SEQ_HRTIMER_DEFAULT=y
CONFIG_SND_SEQ_MIDI_EVENT=m
CONFIG_SND_SEQ_MIDI=m
CONFIG_SND_SEQ_MIDI_EMUL=m
CONFIG_SND_SEQ_VIRMIDI=m
CONFIG_SND_MPU401_UART=m
CONFIG_SND_OPL3_LIB=m
CONFIG_SND_OPL4_LIB=m
CONFIG_SND_OPL3_LIB_SEQ=m
CONFIG_SND_OPL4_LIB_SEQ=m
CONFIG_SND_VX_LIB=m
CONFIG_SND_AC97_CODEC=m
CONFIG_SND_DRIVERS=y
CONFIG_SND_PCSP=m
CONFIG_SND_DUMMY=m
CONFIG_SND_ALOOP=m
CONFIG_SND_VIRMIDI=m
CONFIG_SND_MTPAV=m
CONFIG_SND_MTS64=m
CONFIG_SND_SERIAL_U16550=m
CONFIG_SND_SERIAL_GENERIC=m
CONFIG_SND_MPU401=m
CONFIG_SND_PORTMAN2X4=m
CONFIG_SND_AC97_POWER_SAVE=y
CONFIG_SND_AC97_POWER_SAVE_DEFAULT=0
CONFIG_SND_WSS_LIB=m
CONFIG_SND_SB_COMMON=m
CONFIG_SND_SB8_DSP=m
CONFIG_SND_SB16_DSP=m
CONFIG_SND_ISA=y
CONFIG_SND_ADLIB=m
CONFIG_SND_AD1816A=m
CONFIG_SND_AD1848=m
CONFIG_SND_ALS100=m
CONFIG_SND_AZT1605=m
CONFIG_SND_AZT2316=m
CONFIG_SND_AZT2320=m
CONFIG_SND_CMI8328=m
CONFIG_SND_CMI8330=m
CONFIG_SND_CS4231=m
CONFIG_SND_CS4236=m
CONFIG_SND_ES1688=m
CONFIG_SND_ES18XX=m
CONFIG_SND_SC6000=m
CONFIG_SND_GUSCLASSIC=m
CONFIG_SND_GUSEXTREME=m
CONFIG_SND_GUSMAX=m
CONFIG_SND_INTERWAVE=m
CONFIG_SND_INTERWAVE_STB=m
CONFIG_SND_JAZZ16=m
CONFIG_SND_OPL3SA2=m
CONFIG_SND_OPTI92X_AD1848=m
CONFIG_SND_OPTI92X_CS4231=m
CONFIG_SND_OPTI93X=m
CONFIG_SND_MIRO=m
CONFIG_SND_SB8=m
CONFIG_SND_SB16=m
CONFIG_SND_SBAWE=m
CONFIG_SND_SBAWE_SEQ=m
CONFIG_SND_SB16_CSP=y
CONFIG_SND_SSCAPE=m
CONFIG_SND_WAVEFRONT=m
CONFIG_SND_MSND_PINNACLE=m
CONFIG_SND_MSND_CLASSIC=m
CONFIG_SND_PCI=y
CONFIG_SND_AD1889=m
CONFIG_SND_ALS300=m
CONFIG_SND_ALS4000=m
CONFIG_SND_ALI5451=m
CONFIG_SND_ASIHPI=m
CONFIG_SND_ATIIXP=m
CONFIG_SND_ATIIXP_MODEM=m
CONFIG_SND_AU8810=m
CONFIG_SND_AU8820=m
CONFIG_SND_AU8830=m
CONFIG_SND_AW2=m
CONFIG_SND_AZT3328=m
CONFIG_SND_BT87X=m
CONFIG_SND_BT87X_OVERCLOCK=y
CONFIG_SND_CA0106=m
CONFIG_SND_CMIPCI=m
CONFIG_SND_OXYGEN_LIB=m
CONFIG_SND_OXYGEN=m
CONFIG_SND_CS4281=m
CONFIG_SND_CS46XX=m
CONFIG_SND_CS46XX_NEW_DSP=y
CONFIG_SND_CS5530=m
CONFIG_SND_CS5535AUDIO=m
CONFIG_SND_CTXFI=m
CONFIG_SND_DARLA20=m
CONFIG_SND_GINA20=m
CONFIG_SND_LAYLA20=m
CONFIG_SND_DARLA24=m
CONFIG_SND_GINA24=m
CONFIG_SND_LAYLA24=m
CONFIG_SND_MONA=m
CONFIG_SND_MIA=m
CONFIG_SND_ECHO3G=m
CONFIG_SND_INDIGO=m
CONFIG_SND_INDIGOIO=m
CONFIG_SND_INDIGODJ=m
CONFIG_SND_INDIGOIOX=m
CONFIG_SND_INDIGODJX=m
CONFIG_SND_EMU10K1=m
CONFIG_SND_EMU10K1_SEQ=m
CONFIG_SND_EMU10K1X=m
CONFIG_SND_ENS1370=m
CONFIG_SND_ENS1371=m
CONFIG_SND_ES1938=m
CONFIG_SND_ES1968=m
CONFIG_SND_ES1968_INPUT=y
CONFIG_SND_ES1968_RADIO=y
CONFIG_SND_FM801=m
CONFIG_SND_FM801_TEA575X_BOOL=y
CONFIG_SND_HDSP=m
CONFIG_SND_HDSPM=m
CONFIG_SND_ICE1712=m
CONFIG_SND_ICE1724=m
CONFIG_SND_INTEL8X0=m
CONFIG_SND_INTEL8X0M=m
CONFIG_SND_KORG1212=m
CONFIG_SND_LOLA=m
CONFIG_SND_LX6464ES=m
CONFIG_SND_MAESTRO3=m
CONFIG_SND_MAESTRO3_INPUT=y
CONFIG_SND_MIXART=m
CONFIG_SND_NM256=m
CONFIG_SND_PCXHR=m
CONFIG_SND_RIPTIDE=m
CONFIG_SND_RME32=m
CONFIG_SND_RME96=m
CONFIG_SND_RME9652=m
CONFIG_SND_SIS7019=m
CONFIG_SND_SONICVIBES=m
CONFIG_SND_TRIDENT=m
CONFIG_SND_VIA82XX=m
CONFIG_SND_VIA82XX_MODEM=m
CONFIG_SND_VIRTUOSO=m
CONFIG_SND_VX222=m
CONFIG_SND_YMFPCI=m

#
# HD-Audio
#
CONFIG_SND_HDA=m
CONFIG_SND_HDA_GENERIC_LEDS=y
CONFIG_SND_HDA_INTEL=m
CONFIG_SND_HDA_HWDEP=y
CONFIG_SND_HDA_RECONFIG=y
CONFIG_SND_HDA_INPUT_BEEP=y
CONFIG_SND_HDA_INPUT_BEEP_MODE=1
CONFIG_SND_HDA_PATCH_LOADER=y
CONFIG_SND_HDA_SCODEC_CS35L41=m
CONFIG_SND_HDA_CS_DSP_CONTROLS=m
CONFIG_SND_HDA_SCODEC_CS35L41_I2C=m
CONFIG_SND_HDA_SCODEC_CS35L41_SPI=m
CONFIG_SND_HDA_CODEC_REALTEK=m
CONFIG_SND_HDA_CODEC_ANALOG=m
CONFIG_SND_HDA_CODEC_SIGMATEL=m
CONFIG_SND_HDA_CODEC_VIA=m
CONFIG_SND_HDA_CODEC_HDMI=m
CONFIG_SND_HDA_CODEC_CIRRUS=m
CONFIG_SND_HDA_CODEC_CS8409=m
CONFIG_SND_HDA_CODEC_CONEXANT=m
CONFIG_SND_HDA_CODEC_CA0110=m
CONFIG_SND_HDA_CODEC_CA0132=m
CONFIG_SND_HDA_CODEC_CA0132_DSP=y
CONFIG_SND_HDA_CODEC_CMEDIA=m
CONFIG_SND_HDA_CODEC_SI3054=m
CONFIG_SND_HDA_GENERIC=m
CONFIG_SND_HDA_POWER_SAVE_DEFAULT=0
CONFIG_SND_HDA_INTEL_HDMI_SILENT_STREAM=y
# end of HD-Audio

CONFIG_SND_HDA_CORE=m
CONFIG_SND_HDA_DSP_LOADER=y
CONFIG_SND_HDA_COMPONENT=y
CONFIG_SND_HDA_I915=y
CONFIG_SND_HDA_EXT_CORE=m
CONFIG_SND_HDA_PREALLOC_SIZE=0
CONFIG_SND_INTEL_NHLT=y
CONFIG_SND_INTEL_DSP_CONFIG=m
CONFIG_SND_INTEL_SOUNDWIRE_ACPI=m
CONFIG_SND_INTEL_BYT_PREFER_SOF=y
CONFIG_SND_SPI=y
CONFIG_SND_USB=y
CONFIG_SND_USB_AUDIO=m
CONFIG_SND_USB_AUDIO_USE_MEDIA_CONTROLLER=y
CONFIG_SND_USB_UA101=m
CONFIG_SND_USB_USX2Y=m
CONFIG_SND_USB_CAIAQ=m
CONFIG_SND_USB_CAIAQ_INPUT=y
CONFIG_SND_USB_US122L=m
CONFIG_SND_USB_6FIRE=m
CONFIG_SND_USB_HIFACE=m
CONFIG_SND_BCD2000=m
CONFIG_SND_USB_LINE6=m
CONFIG_SND_USB_POD=m
CONFIG_SND_USB_PODHD=m
CONFIG_SND_USB_TONEPORT=m
CONFIG_SND_USB_VARIAX=m
CONFIG_SND_FIREWIRE=y
CONFIG_SND_FIREWIRE_LIB=m
CONFIG_SND_DICE=m
CONFIG_SND_OXFW=m
CONFIG_SND_ISIGHT=m
CONFIG_SND_FIREWORKS=m
CONFIG_SND_BEBOB=m
CONFIG_SND_FIREWIRE_DIGI00X=m
CONFIG_SND_FIREWIRE_TASCAM=m
CONFIG_SND_FIREWIRE_MOTU=m
CONFIG_SND_FIREFACE=m
CONFIG_SND_PCMCIA=y
CONFIG_SND_VXPOCKET=m
CONFIG_SND_PDAUDIOCF=m
CONFIG_SND_SOC=m
CONFIG_SND_SOC_AC97_BUS=y
CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM=y
CONFIG_SND_SOC_COMPRESS=y
CONFIG_SND_SOC_TOPOLOGY=y
CONFIG_SND_SOC_ACPI=m
CONFIG_SND_SOC_ADI=m
CONFIG_SND_SOC_ADI_AXI_I2S=m
CONFIG_SND_SOC_ADI_AXI_SPDIF=m
# CONFIG_SND_SOC_AMD_ACP is not set
CONFIG_SND_SOC_AMD_ACP3x=m
# CONFIG_SND_SOC_AMD_RV_RT5682_MACH is not set
# CONFIG_SND_SOC_AMD_RENOIR is not set
CONFIG_SND_SOC_AMD_ACP5x=m
# CONFIG_SND_SOC_AMD_VANGOGH_MACH is not set
CONFIG_SND_SOC_AMD_ACP6x=m
# CONFIG_SND_SOC_AMD_YC_MACH is not set
# CONFIG_SND_AMD_ACP_CONFIG is not set
# CONFIG_SND_SOC_AMD_ACP_COMMON is not set
CONFIG_SND_SOC_AMD_RPL_ACP6x=m
CONFIG_SND_SOC_AMD_PS=m
CONFIG_SND_SOC_AMD_PS_MACH=m
CONFIG_SND_ATMEL_SOC=m
CONFIG_SND_SOC_MIKROE_PROTO=m
CONFIG_SND_BCM63XX_I2S_WHISTLER=m
CONFIG_SND_DESIGNWARE_I2S=m
CONFIG_SND_DESIGNWARE_PCM=y

#
# SoC Audio for Freescale CPUs
#

#
# Common SoC Audio options for Freescale CPUs:
#
CONFIG_SND_SOC_FSL_ASRC=m
CONFIG_SND_SOC_FSL_SAI=m
CONFIG_SND_SOC_FSL_MQS=m
CONFIG_SND_SOC_FSL_AUDMIX=m
CONFIG_SND_SOC_FSL_SSI=m
CONFIG_SND_SOC_FSL_SPDIF=m
CONFIG_SND_SOC_FSL_ESAI=m
CONFIG_SND_SOC_FSL_MICFIL=m
CONFIG_SND_SOC_FSL_EASRC=m
CONFIG_SND_SOC_FSL_XCVR=m
CONFIG_SND_SOC_FSL_UTILS=m
CONFIG_SND_SOC_FSL_RPMSG=m
CONFIG_SND_SOC_IMX_AUDMUX=m
# end of SoC Audio for Freescale CPUs

CONFIG_SND_I2S_HI6210_I2S=m
CONFIG_SND_SOC_IMG=y
CONFIG_SND_SOC_IMG_I2S_IN=m
CONFIG_SND_SOC_IMG_I2S_OUT=m
CONFIG_SND_SOC_IMG_PARALLEL_OUT=m
CONFIG_SND_SOC_IMG_SPDIF_IN=m
CONFIG_SND_SOC_IMG_SPDIF_OUT=m
CONFIG_SND_SOC_IMG_PISTACHIO_INTERNAL_DAC=m
CONFIG_SND_SOC_INTEL_SST_TOPLEVEL=y
CONFIG_SND_SOC_INTEL_SST=m
CONFIG_SND_SOC_INTEL_CATPT=m
CONFIG_SND_SST_ATOM_HIFI2_PLATFORM=m
CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_PCI=m
CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI=m
CONFIG_SND_SOC_INTEL_SKYLAKE=m
CONFIG_SND_SOC_INTEL_SKL=m
CONFIG_SND_SOC_INTEL_APL=m
CONFIG_SND_SOC_INTEL_KBL=m
CONFIG_SND_SOC_INTEL_GLK=m
CONFIG_SND_SOC_INTEL_CNL=m
CONFIG_SND_SOC_INTEL_CFL=m
CONFIG_SND_SOC_INTEL_CML_H=m
CONFIG_SND_SOC_INTEL_CML_LP=m
CONFIG_SND_SOC_INTEL_SKYLAKE_FAMILY=m
CONFIG_SND_SOC_INTEL_SKYLAKE_SSP_CLK=m
CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC=y
CONFIG_SND_SOC_INTEL_SKYLAKE_COMMON=m
CONFIG_SND_SOC_ACPI_INTEL_MATCH=m
CONFIG_SND_SOC_INTEL_AVS=m

#
# Intel AVS Machine drivers
#

#
# Available DSP configurations
#
CONFIG_SND_SOC_INTEL_AVS_MACH_DA7219=m
CONFIG_SND_SOC_INTEL_AVS_MACH_DMIC=m
CONFIG_SND_SOC_INTEL_AVS_MACH_HDAUDIO=m
CONFIG_SND_SOC_INTEL_AVS_MACH_I2S_TEST=m
CONFIG_SND_SOC_INTEL_AVS_MACH_MAX98357A=m
CONFIG_SND_SOC_INTEL_AVS_MACH_MAX98373=m
CONFIG_SND_SOC_INTEL_AVS_MACH_NAU8825=m
CONFIG_SND_SOC_INTEL_AVS_MACH_RT274=m
CONFIG_SND_SOC_INTEL_AVS_MACH_RT286=m
CONFIG_SND_SOC_INTEL_AVS_MACH_RT298=m
CONFIG_SND_SOC_INTEL_AVS_MACH_RT5682=m
CONFIG_SND_SOC_INTEL_AVS_MACH_SSM4567=m
# end of Intel AVS Machine drivers

CONFIG_SND_SOC_INTEL_MACH=y
CONFIG_SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES=y
CONFIG_SND_SOC_INTEL_HDA_DSP_COMMON=m
CONFIG_SND_SOC_INTEL_SOF_MAXIM_COMMON=m
CONFIG_SND_SOC_INTEL_SOF_REALTEK_COMMON=m
CONFIG_SND_SOC_INTEL_HASWELL_MACH=m
CONFIG_SND_SOC_INTEL_BDW_RT5650_MACH=m
CONFIG_SND_SOC_INTEL_BDW_RT5677_MACH=m
CONFIG_SND_SOC_INTEL_BROADWELL_MACH=m
CONFIG_SND_SOC_INTEL_BYTCR_RT5640_MACH=m
CONFIG_SND_SOC_INTEL_BYTCR_RT5651_MACH=m
CONFIG_SND_SOC_INTEL_BYTCR_WM5102_MACH=m
CONFIG_SND_SOC_INTEL_CHT_BSW_RT5672_MACH=m
CONFIG_SND_SOC_INTEL_CHT_BSW_RT5645_MACH=m
CONFIG_SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH=m
CONFIG_SND_SOC_INTEL_CHT_BSW_NAU8824_MACH=m
CONFIG_SND_SOC_INTEL_BYT_CHT_CX2072X_MACH=m
CONFIG_SND_SOC_INTEL_BYT_CHT_DA7213_MACH=m
CONFIG_SND_SOC_INTEL_BYT_CHT_ES8316_MACH=m
CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH=m
CONFIG_SND_SOC_INTEL_SKL_RT286_MACH=m
CONFIG_SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH=m
CONFIG_SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH=m
CONFIG_SND_SOC_INTEL_DA7219_MAX98357A_GENERIC=m
CONFIG_SND_SOC_INTEL_BXT_DA7219_MAX98357A_COMMON=m
CONFIG_SND_SOC_INTEL_BXT_DA7219_MAX98357A_MACH=m
CONFIG_SND_SOC_INTEL_BXT_RT298_MACH=m
CONFIG_SND_SOC_INTEL_SOF_WM8804_MACH=m
CONFIG_SND_SOC_INTEL_KBL_RT5663_MAX98927_MACH=m
CONFIG_SND_SOC_INTEL_KBL_RT5663_RT5514_MAX98927_MACH=m
CONFIG_SND_SOC_INTEL_KBL_DA7219_MAX98357A_MACH=m
CONFIG_SND_SOC_INTEL_KBL_DA7219_MAX98927_MACH=m
CONFIG_SND_SOC_INTEL_KBL_RT5660_MACH=m
CONFIG_SND_SOC_INTEL_SKL_HDA_DSP_GENERIC_MACH=m
CONFIG_SND_SOC_INTEL_SOF_RT5682_MACH=m
CONFIG_SND_SOC_INTEL_SOF_PCM512x_MACH=m
CONFIG_SND_SOC_INTEL_SOUNDWIRE_SOF_MACH=m
CONFIG_SND_SOC_MTK_BTCVSD=m
CONFIG_SND_SOC_SOF_TOPLEVEL=y
CONFIG_SND_SOC_SOF_PCI_DEV=m
CONFIG_SND_SOC_SOF_PCI=m
CONFIG_SND_SOC_SOF_ACPI=m
CONFIG_SND_SOC_SOF_ACPI_DEV=m
CONFIG_SND_SOC_SOF_OF=m
CONFIG_SND_SOC_SOF_DEBUG_PROBES=m
CONFIG_SND_SOC_SOF_CLIENT=m
CONFIG_SND_SOC_SOF_DEVELOPER_SUPPORT=y
CONFIG_SND_SOC_SOF_FORCE_PROBE_WORKQUEUE=y
CONFIG_SND_SOC_SOF_NOCODEC=m
CONFIG_SND_SOC_SOF_NOCODEC_SUPPORT=y
CONFIG_SND_SOC_SOF_STRICT_ABI_CHECKS=y
CONFIG_SND_SOC_SOF_DEBUG=y
CONFIG_SND_SOC_SOF_FORCE_NOCODEC_MODE=y
CONFIG_SND_SOC_SOF_DEBUG_XRUN_STOP=y
CONFIG_SND_SOC_SOF_DEBUG_VERBOSE_IPC=y
CONFIG_SND_SOC_SOF_DEBUG_FORCE_IPC_POSITION=y
CONFIG_SND_SOC_SOF_DEBUG_ENABLE_DEBUGFS_CACHE=y
CONFIG_SND_SOC_SOF_DEBUG_ENABLE_FIRMWARE_TRACE=y
# CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST is not set
CONFIG_SND_SOC_SOF_DEBUG_IPC_MSG_INJECTOR=m
CONFIG_SND_SOC_SOF_DEBUG_RETAIN_DSP_CONTEXT=y
CONFIG_SND_SOC_SOF=m
CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE=y
CONFIG_SND_SOC_SOF_IPC3=y
CONFIG_SND_SOC_SOF_INTEL_IPC4=y
# CONFIG_SND_SOC_SOF_AMD_TOPLEVEL is not set
CONFIG_SND_SOC_SOF_INTEL_TOPLEVEL=y
CONFIG_SND_SOC_SOF_INTEL_HIFI_EP_IPC=m
CONFIG_SND_SOC_SOF_INTEL_ATOM_HIFI_EP=m
CONFIG_SND_SOC_SOF_INTEL_COMMON=m
CONFIG_SND_SOC_SOF_BAYTRAIL=m
CONFIG_SND_SOC_SOF_BROADWELL=m
CONFIG_SND_SOC_SOF_MERRIFIELD=m
CONFIG_SND_SOC_SOF_INTEL_SKL=m
CONFIG_SND_SOC_SOF_SKYLAKE=m
CONFIG_SND_SOC_SOF_KABYLAKE=m
CONFIG_SND_SOC_SOF_INTEL_APL=m
CONFIG_SND_SOC_SOF_APOLLOLAKE=m
CONFIG_SND_SOC_SOF_GEMINILAKE=m
CONFIG_SND_SOC_SOF_INTEL_CNL=m
CONFIG_SND_SOC_SOF_CANNONLAKE=m
CONFIG_SND_SOC_SOF_COFFEELAKE=m
CONFIG_SND_SOC_SOF_COMETLAKE=m
CONFIG_SND_SOC_SOF_INTEL_ICL=m
CONFIG_SND_SOC_SOF_ICELAKE=m
CONFIG_SND_SOC_SOF_JASPERLAKE=m
CONFIG_SND_SOC_SOF_INTEL_TGL=m
CONFIG_SND_SOC_SOF_TIGERLAKE=m
CONFIG_SND_SOC_SOF_ELKHARTLAKE=m
CONFIG_SND_SOC_SOF_ALDERLAKE=m
CONFIG_SND_SOC_SOF_INTEL_MTL=m
CONFIG_SND_SOC_SOF_METEORLAKE=m
CONFIG_SND_SOC_SOF_HDA_COMMON=m
CONFIG_SND_SOC_SOF_HDA_LINK_BASELINE=m
CONFIG_SND_SOC_SOF_HDA_PROBES=m
CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE_LINK_BASELINE=m
CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE=m
CONFIG_SND_SOC_SOF_XTENSA=m

#
# STMicroelectronics STM32 SOC audio support
#
# end of STMicroelectronics STM32 SOC audio support

CONFIG_SND_SOC_XILINX_I2S=m
CONFIG_SND_SOC_XILINX_AUDIO_FORMATTER=m
CONFIG_SND_SOC_XILINX_SPDIF=m
CONFIG_SND_SOC_XTFPGA_I2S=m
CONFIG_SND_SOC_I2C_AND_SPI=m

#
# CODEC drivers
#
CONFIG_SND_SOC_ARIZONA=m
CONFIG_SND_SOC_WM_ADSP=m
CONFIG_SND_SOC_AC97_CODEC=m
CONFIG_SND_SOC_ADAU_UTILS=m
CONFIG_SND_SOC_ADAU1372=m
CONFIG_SND_SOC_ADAU1372_I2C=m
CONFIG_SND_SOC_ADAU1372_SPI=m
CONFIG_SND_SOC_ADAU1701=m
CONFIG_SND_SOC_ADAU17X1=m
CONFIG_SND_SOC_ADAU1761=m
CONFIG_SND_SOC_ADAU1761_I2C=m
CONFIG_SND_SOC_ADAU1761_SPI=m
CONFIG_SND_SOC_ADAU7002=m
CONFIG_SND_SOC_ADAU7118=m
CONFIG_SND_SOC_ADAU7118_HW=m
CONFIG_SND_SOC_ADAU7118_I2C=m
CONFIG_SND_SOC_AK4104=m
CONFIG_SND_SOC_AK4118=m
CONFIG_SND_SOC_AK4375=m
CONFIG_SND_SOC_AK4458=m
CONFIG_SND_SOC_AK4554=m
CONFIG_SND_SOC_AK4613=m
CONFIG_SND_SOC_AK4642=m
CONFIG_SND_SOC_AK5386=m
CONFIG_SND_SOC_AK5558=m
CONFIG_SND_SOC_ALC5623=m
CONFIG_SND_SOC_AW8738=m
CONFIG_SND_SOC_BD28623=m
CONFIG_SND_SOC_BT_SCO=m
CONFIG_SND_SOC_CPCAP=m
CONFIG_SND_SOC_CROS_EC_CODEC=m
CONFIG_SND_SOC_CS35L32=m
CONFIG_SND_SOC_CS35L33=m
CONFIG_SND_SOC_CS35L34=m
CONFIG_SND_SOC_CS35L35=m
CONFIG_SND_SOC_CS35L36=m
CONFIG_SND_SOC_CS35L41_LIB=m
CONFIG_SND_SOC_CS35L41=m
CONFIG_SND_SOC_CS35L41_SPI=m
CONFIG_SND_SOC_CS35L41_I2C=m
CONFIG_SND_SOC_CS35L45_TABLES=m
CONFIG_SND_SOC_CS35L45=m
CONFIG_SND_SOC_CS35L45_SPI=m
CONFIG_SND_SOC_CS35L45_I2C=m
CONFIG_SND_SOC_CS42L42_CORE=m
CONFIG_SND_SOC_CS42L42=m
CONFIG_SND_SOC_CS42L51=m
CONFIG_SND_SOC_CS42L51_I2C=m
CONFIG_SND_SOC_CS42L52=m
CONFIG_SND_SOC_CS42L56=m
CONFIG_SND_SOC_CS42L73=m
CONFIG_SND_SOC_CS42L83=m
CONFIG_SND_SOC_CS4234=m
CONFIG_SND_SOC_CS4265=m
CONFIG_SND_SOC_CS4270=m
CONFIG_SND_SOC_CS4271=m
CONFIG_SND_SOC_CS4271_I2C=m
CONFIG_SND_SOC_CS4271_SPI=m
CONFIG_SND_SOC_CS42XX8=m
CONFIG_SND_SOC_CS42XX8_I2C=m
CONFIG_SND_SOC_CS43130=m
CONFIG_SND_SOC_CS4341=m
CONFIG_SND_SOC_CS4349=m
CONFIG_SND_SOC_CS53L30=m
CONFIG_SND_SOC_CX2072X=m
CONFIG_SND_SOC_DA7213=m
CONFIG_SND_SOC_DA7219=m
CONFIG_SND_SOC_DMIC=m
CONFIG_SND_SOC_HDMI_CODEC=m
CONFIG_SND_SOC_ES7134=m
CONFIG_SND_SOC_ES7241=m
CONFIG_SND_SOC_ES8316=m
CONFIG_SND_SOC_ES8326=m
CONFIG_SND_SOC_ES8328=m
CONFIG_SND_SOC_ES8328_I2C=m
CONFIG_SND_SOC_ES8328_SPI=m
CONFIG_SND_SOC_GTM601=m
CONFIG_SND_SOC_HDAC_HDMI=m
CONFIG_SND_SOC_HDAC_HDA=m
CONFIG_SND_SOC_HDA=m
CONFIG_SND_SOC_ICS43432=m
CONFIG_SND_SOC_INNO_RK3036=m
CONFIG_SND_SOC_LOCHNAGAR_SC=m
CONFIG_SND_SOC_MAX98088=m
CONFIG_SND_SOC_MAX98090=m
CONFIG_SND_SOC_MAX98357A=m
CONFIG_SND_SOC_MAX98504=m
CONFIG_SND_SOC_MAX9867=m
CONFIG_SND_SOC_MAX98927=m
CONFIG_SND_SOC_MAX98520=m
CONFIG_SND_SOC_MAX98373=m
CONFIG_SND_SOC_MAX98373_I2C=m
CONFIG_SND_SOC_MAX98373_SDW=m
CONFIG_SND_SOC_MAX98390=m
CONFIG_SND_SOC_MAX98396=m
CONFIG_SND_SOC_MAX9860=m
CONFIG_SND_SOC_MSM8916_WCD_ANALOG=m
CONFIG_SND_SOC_MSM8916_WCD_DIGITAL=m
CONFIG_SND_SOC_PCM1681=m
CONFIG_SND_SOC_PCM1789=m
CONFIG_SND_SOC_PCM1789_I2C=m
CONFIG_SND_SOC_PCM179X=m
CONFIG_SND_SOC_PCM179X_I2C=m
CONFIG_SND_SOC_PCM179X_SPI=m
CONFIG_SND_SOC_PCM186X=m
CONFIG_SND_SOC_PCM186X_I2C=m
CONFIG_SND_SOC_PCM186X_SPI=m
CONFIG_SND_SOC_PCM3060=m
CONFIG_SND_SOC_PCM3060_I2C=m
CONFIG_SND_SOC_PCM3060_SPI=m
CONFIG_SND_SOC_PCM3168A=m
CONFIG_SND_SOC_PCM3168A_I2C=m
CONFIG_SND_SOC_PCM3168A_SPI=m
CONFIG_SND_SOC_PCM5102A=m
CONFIG_SND_SOC_PCM512x=m
CONFIG_SND_SOC_PCM512x_I2C=m
CONFIG_SND_SOC_PCM512x_SPI=m
CONFIG_SND_SOC_RK3328=m
CONFIG_SND_SOC_RK817=m
CONFIG_SND_SOC_RL6231=m
CONFIG_SND_SOC_RL6347A=m
CONFIG_SND_SOC_RT274=m
CONFIG_SND_SOC_RT286=m
CONFIG_SND_SOC_RT298=m
CONFIG_SND_SOC_RT1011=m
CONFIG_SND_SOC_RT1015=m
CONFIG_SND_SOC_RT1015P=m
CONFIG_SND_SOC_RT1308=m
CONFIG_SND_SOC_RT1308_SDW=m
CONFIG_SND_SOC_RT1316_SDW=m
CONFIG_SND_SOC_RT5514=m
CONFIG_SND_SOC_RT5514_SPI=m
CONFIG_SND_SOC_RT5616=m
CONFIG_SND_SOC_RT5631=m
CONFIG_SND_SOC_RT5640=m
CONFIG_SND_SOC_RT5645=m
CONFIG_SND_SOC_RT5651=m
CONFIG_SND_SOC_RT5659=m
CONFIG_SND_SOC_RT5660=m
CONFIG_SND_SOC_RT5663=m
CONFIG_SND_SOC_RT5670=m
CONFIG_SND_SOC_RT5677=m
CONFIG_SND_SOC_RT5677_SPI=m
CONFIG_SND_SOC_RT5682=m
CONFIG_SND_SOC_RT5682_I2C=m
CONFIG_SND_SOC_RT5682_SDW=m
CONFIG_SND_SOC_RT5682S=m
CONFIG_SND_SOC_RT700=m
CONFIG_SND_SOC_RT700_SDW=m
CONFIG_SND_SOC_RT711=m
CONFIG_SND_SOC_RT711_SDW=m
CONFIG_SND_SOC_RT711_SDCA_SDW=m
CONFIG_SND_SOC_RT715=m
CONFIG_SND_SOC_RT715_SDW=m
CONFIG_SND_SOC_RT715_SDCA_SDW=m
CONFIG_SND_SOC_RT9120=m
CONFIG_SND_SOC_SDW_MOCKUP=m
CONFIG_SND_SOC_SGTL5000=m
CONFIG_SND_SOC_SI476X=m
CONFIG_SND_SOC_SIGMADSP=m
CONFIG_SND_SOC_SIGMADSP_I2C=m
CONFIG_SND_SOC_SIGMADSP_REGMAP=m
CONFIG_SND_SOC_SIMPLE_AMPLIFIER=m
CONFIG_SND_SOC_SIMPLE_MUX=m
CONFIG_SND_SOC_SPDIF=m
CONFIG_SND_SOC_SRC4XXX_I2C=m
CONFIG_SND_SOC_SRC4XXX=m
CONFIG_SND_SOC_SSM2305=m
CONFIG_SND_SOC_SSM2518=m
CONFIG_SND_SOC_SSM2602=m
CONFIG_SND_SOC_SSM2602_SPI=m
CONFIG_SND_SOC_SSM2602_I2C=m
CONFIG_SND_SOC_SSM4567=m
CONFIG_SND_SOC_STA32X=m
CONFIG_SND_SOC_STA350=m
CONFIG_SND_SOC_STI_SAS=m
CONFIG_SND_SOC_TAS2552=m
CONFIG_SND_SOC_TAS2562=m
CONFIG_SND_SOC_TAS2764=m
CONFIG_SND_SOC_TAS2770=m
CONFIG_SND_SOC_TAS2780=m
CONFIG_SND_SOC_TAS5086=m
CONFIG_SND_SOC_TAS571X=m
CONFIG_SND_SOC_TAS5720=m
CONFIG_SND_SOC_TAS5805M=m
CONFIG_SND_SOC_TAS6424=m
CONFIG_SND_SOC_TDA7419=m
CONFIG_SND_SOC_TFA9879=m
CONFIG_SND_SOC_TFA989X=m
CONFIG_SND_SOC_TLV320ADC3XXX=m
CONFIG_SND_SOC_TLV320AIC23=m
CONFIG_SND_SOC_TLV320AIC23_I2C=m
CONFIG_SND_SOC_TLV320AIC23_SPI=m
CONFIG_SND_SOC_TLV320AIC31XX=m
CONFIG_SND_SOC_TLV320AIC32X4=m
CONFIG_SND_SOC_TLV320AIC32X4_I2C=m
CONFIG_SND_SOC_TLV320AIC32X4_SPI=m
CONFIG_SND_SOC_TLV320AIC3X=m
CONFIG_SND_SOC_TLV320AIC3X_I2C=m
CONFIG_SND_SOC_TLV320AIC3X_SPI=m
CONFIG_SND_SOC_TLV320ADCX140=m
CONFIG_SND_SOC_TS3A227E=m
CONFIG_SND_SOC_TSCS42XX=m
CONFIG_SND_SOC_TSCS454=m
CONFIG_SND_SOC_UDA1334=m
CONFIG_SND_SOC_WCD9335=m
CONFIG_SND_SOC_WCD_MBHC=m
CONFIG_SND_SOC_WCD934X=m
CONFIG_SND_SOC_WCD938X=m
CONFIG_SND_SOC_WCD938X_SDW=m
CONFIG_SND_SOC_WM5102=m
CONFIG_SND_SOC_WM8510=m
CONFIG_SND_SOC_WM8523=m
CONFIG_SND_SOC_WM8524=m
CONFIG_SND_SOC_WM8580=m
CONFIG_SND_SOC_WM8711=m
CONFIG_SND_SOC_WM8728=m
CONFIG_SND_SOC_WM8731=m
CONFIG_SND_SOC_WM8731_I2C=m
CONFIG_SND_SOC_WM8731_SPI=m
CONFIG_SND_SOC_WM8737=m
CONFIG_SND_SOC_WM8741=m
CONFIG_SND_SOC_WM8750=m
CONFIG_SND_SOC_WM8753=m
CONFIG_SND_SOC_WM8770=m
CONFIG_SND_SOC_WM8776=m
CONFIG_SND_SOC_WM8782=m
CONFIG_SND_SOC_WM8804=m
CONFIG_SND_SOC_WM8804_I2C=m
CONFIG_SND_SOC_WM8804_SPI=m
CONFIG_SND_SOC_WM8903=m
CONFIG_SND_SOC_WM8904=m
CONFIG_SND_SOC_WM8940=m
CONFIG_SND_SOC_WM8960=m
CONFIG_SND_SOC_WM8962=m
CONFIG_SND_SOC_WM8974=m
CONFIG_SND_SOC_WM8978=m
CONFIG_SND_SOC_WM8985=m
CONFIG_SND_SOC_WSA881X=m
CONFIG_SND_SOC_WSA883X=m
CONFIG_SND_SOC_ZL38060=m
CONFIG_SND_SOC_MAX9759=m
CONFIG_SND_SOC_MT6351=m
CONFIG_SND_SOC_MT6358=m
CONFIG_SND_SOC_MT6660=m
CONFIG_SND_SOC_NAU8315=m
CONFIG_SND_SOC_NAU8540=m
CONFIG_SND_SOC_NAU8810=m
CONFIG_SND_SOC_NAU8821=m
CONFIG_SND_SOC_NAU8822=m
CONFIG_SND_SOC_NAU8824=m
CONFIG_SND_SOC_NAU8825=m
CONFIG_SND_SOC_TPA6130A2=m
CONFIG_SND_SOC_LPASS_MACRO_COMMON=m
CONFIG_SND_SOC_LPASS_WSA_MACRO=m
CONFIG_SND_SOC_LPASS_VA_MACRO=m
CONFIG_SND_SOC_LPASS_RX_MACRO=m
CONFIG_SND_SOC_LPASS_TX_MACRO=m
# end of CODEC drivers

CONFIG_SND_SIMPLE_CARD_UTILS=m
CONFIG_SND_SIMPLE_CARD=m
CONFIG_SND_AUDIO_GRAPH_CARD=m
CONFIG_SND_AUDIO_GRAPH_CARD2=m
CONFIG_SND_AUDIO_GRAPH_CARD2_CUSTOM_SAMPLE=m
# CONFIG_SND_TEST_COMPONENT is not set
CONFIG_SND_X86=y
CONFIG_HDMI_LPE_AUDIO=m
CONFIG_SND_SYNTH_EMUX=m
CONFIG_SND_VIRTIO=m
CONFIG_AC97_BUS=m

#
# HID support
#
CONFIG_HID=m
CONFIG_HID_BATTERY_STRENGTH=y
CONFIG_HIDRAW=y
CONFIG_UHID=m
CONFIG_HID_GENERIC=m

#
# Special HID drivers
#
CONFIG_HID_A4TECH=m
CONFIG_HID_ACCUTOUCH=m
CONFIG_HID_ACRUX=m
CONFIG_HID_ACRUX_FF=y
CONFIG_HID_APPLE=m
CONFIG_HID_APPLEIR=m
CONFIG_HID_ASUS=m
CONFIG_HID_AUREAL=m
CONFIG_HID_BELKIN=m
CONFIG_HID_BETOP_FF=m
CONFIG_HID_BIGBEN_FF=m
CONFIG_HID_CHERRY=m
CONFIG_HID_CHICONY=m
CONFIG_HID_CORSAIR=m
CONFIG_HID_COUGAR=m
CONFIG_HID_MACALLY=m
CONFIG_HID_PRODIKEYS=m
CONFIG_HID_CMEDIA=m
CONFIG_HID_CP2112=m
CONFIG_HID_CREATIVE_SB0540=m
CONFIG_HID_CYPRESS=m
CONFIG_HID_DRAGONRISE=m
CONFIG_DRAGONRISE_FF=y
CONFIG_HID_EMS_FF=m
CONFIG_HID_ELAN=m
CONFIG_HID_ELECOM=m
CONFIG_HID_ELO=m
CONFIG_HID_EZKEY=m
CONFIG_HID_FT260=m
CONFIG_HID_GEMBIRD=m
CONFIG_HID_GFRM=m
CONFIG_HID_GLORIOUS=m
CONFIG_HID_HOLTEK=m
CONFIG_HOLTEK_FF=y
CONFIG_HID_VIVALDI_COMMON=m
CONFIG_HID_GOOGLE_HAMMER=m
CONFIG_HID_VIVALDI=m
CONFIG_HID_GT683R=m
CONFIG_HID_KEYTOUCH=m
CONFIG_HID_KYE=m
CONFIG_HID_UCLOGIC=m
CONFIG_HID_WALTOP=m
CONFIG_HID_VIEWSONIC=m
CONFIG_HID_VRC2=m
CONFIG_HID_XIAOMI=m
CONFIG_HID_GYRATION=m
CONFIG_HID_ICADE=m
CONFIG_HID_ITE=m
CONFIG_HID_JABRA=m
CONFIG_HID_TWINHAN=m
CONFIG_HID_KENSINGTON=m
CONFIG_HID_LCPOWER=m
CONFIG_HID_LED=m
CONFIG_HID_LENOVO=m
CONFIG_HID_LETSKETCH=m
CONFIG_HID_LOGITECH=m
CONFIG_HID_LOGITECH_DJ=m
CONFIG_HID_LOGITECH_HIDPP=m
CONFIG_LOGITECH_FF=y
CONFIG_LOGIRUMBLEPAD2_FF=y
CONFIG_LOGIG940_FF=y
CONFIG_LOGIWHEELS_FF=y
CONFIG_HID_MAGICMOUSE=m
CONFIG_HID_MALTRON=m
CONFIG_HID_MAYFLASH=m
CONFIG_HID_MEGAWORLD_FF=m
CONFIG_HID_REDRAGON=m
CONFIG_HID_MICROSOFT=m
CONFIG_HID_MONTEREY=m
CONFIG_HID_MULTITOUCH=m
CONFIG_HID_NINTENDO=m
CONFIG_NINTENDO_FF=y
CONFIG_HID_NTI=m
CONFIG_HID_NTRIG=m
CONFIG_HID_ORTEK=m
CONFIG_HID_PANTHERLORD=m
CONFIG_PANTHERLORD_FF=y
CONFIG_HID_PENMOUNT=m
CONFIG_HID_PETALYNX=m
CONFIG_HID_PICOLCD=m
CONFIG_HID_PICOLCD_FB=y
CONFIG_HID_PICOLCD_BACKLIGHT=y
CONFIG_HID_PICOLCD_LCD=y
CONFIG_HID_PICOLCD_LEDS=y
CONFIG_HID_PICOLCD_CIR=y
CONFIG_HID_PLANTRONICS=m
CONFIG_HID_PLAYSTATION=m
CONFIG_PLAYSTATION_FF=y
CONFIG_HID_PXRC=m
CONFIG_HID_RAZER=m
CONFIG_HID_PRIMAX=m
CONFIG_HID_RETRODE=m
CONFIG_HID_ROCCAT=m
CONFIG_HID_SAITEK=m
CONFIG_HID_SAMSUNG=m
CONFIG_HID_SEMITEK=m
CONFIG_HID_SIGMAMICRO=m
CONFIG_HID_SONY=m
CONFIG_SONY_FF=y
CONFIG_HID_SPEEDLINK=m
CONFIG_HID_STEAM=m
CONFIG_HID_STEELSERIES=m
CONFIG_HID_SUNPLUS=m
CONFIG_HID_RMI=m
CONFIG_HID_GREENASIA=m
CONFIG_GREENASIA_FF=y
CONFIG_HID_HYPERV_MOUSE=m
CONFIG_HID_SMARTJOYPLUS=m
CONFIG_SMARTJOYPLUS_FF=y
CONFIG_HID_TIVO=m
CONFIG_HID_TOPSEED=m
CONFIG_HID_TOPRE=m
CONFIG_HID_THINGM=m
CONFIG_HID_THRUSTMASTER=m
CONFIG_THRUSTMASTER_FF=y
CONFIG_HID_UDRAW_PS3=m
CONFIG_HID_U2FZERO=m
CONFIG_HID_WACOM=m
CONFIG_HID_WIIMOTE=m
CONFIG_HID_XINMO=m
CONFIG_HID_ZEROPLUS=m
CONFIG_ZEROPLUS_FF=y
CONFIG_HID_ZYDACRON=m
CONFIG_HID_SENSOR_HUB=m
CONFIG_HID_SENSOR_CUSTOM_SENSOR=m
CONFIG_HID_ALPS=m
CONFIG_HID_MCP2221=m
# end of Special HID drivers

#
# USB HID support
#
CONFIG_USB_HID=m
CONFIG_HID_PID=y
CONFIG_USB_HIDDEV=y

#
# USB HID Boot Protocol drivers
#
CONFIG_USB_KBD=m
CONFIG_USB_MOUSE=m
# end of USB HID Boot Protocol drivers
# end of USB HID support

#
# I2C HID support
#
CONFIG_I2C_HID_ACPI=m
CONFIG_I2C_HID_OF=m
CONFIG_I2C_HID_OF_ELAN=m
CONFIG_I2C_HID_OF_GOODIX=m
# end of I2C HID support

CONFIG_I2C_HID_CORE=m

#
# Surface System Aggregator Module HID support
#
CONFIG_SURFACE_HID=m
CONFIG_SURFACE_KBD=m
# end of Surface System Aggregator Module HID support

CONFIG_SURFACE_HID_CORE=m
# end of HID support

CONFIG_USB_OHCI_LITTLE_ENDIAN=y
CONFIG_USB_SUPPORT=y
CONFIG_USB_COMMON=m
CONFIG_USB_LED_TRIG=y
CONFIG_USB_ULPI_BUS=m
CONFIG_USB_CONN_GPIO=m
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB=m
CONFIG_USB_PCI=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y

#
# Miscellaneous USB options
#
CONFIG_USB_DEFAULT_PERSIST=y
CONFIG_USB_FEW_INIT_RETRIES=y
CONFIG_USB_DYNAMIC_MINORS=y
CONFIG_USB_OTG=y
CONFIG_USB_OTG_PRODUCTLIST=y
CONFIG_USB_OTG_DISABLE_EXTERNAL_HUB=y
CONFIG_USB_OTG_FSM=m
CONFIG_USB_LEDS_TRIGGER_USBPORT=m
CONFIG_USB_AUTOSUSPEND_DELAY=2
CONFIG_USB_MON=m

#
# USB Host Controller Drivers
#
CONFIG_USB_C67X00_HCD=m
CONFIG_USB_XHCI_HCD=m
CONFIG_USB_XHCI_DBGCAP=y
CONFIG_USB_XHCI_PCI=m
CONFIG_USB_XHCI_PCI_RENESAS=m
CONFIG_USB_XHCI_PLATFORM=m
CONFIG_USB_EHCI_HCD=m
CONFIG_USB_EHCI_ROOT_HUB_TT=y
CONFIG_USB_EHCI_TT_NEWSCHED=y
CONFIG_USB_EHCI_PCI=m
CONFIG_USB_EHCI_FSL=m
CONFIG_USB_EHCI_HCD_PLATFORM=m
CONFIG_USB_OXU210HP_HCD=m
CONFIG_USB_ISP116X_HCD=m
CONFIG_USB_FOTG210_HCD=m
CONFIG_USB_MAX3421_HCD=m
CONFIG_USB_OHCI_HCD=m
CONFIG_USB_OHCI_HCD_PCI=m
CONFIG_USB_OHCI_HCD_SSB=y
CONFIG_USB_OHCI_HCD_PLATFORM=m
CONFIG_USB_UHCI_HCD=m
CONFIG_USB_U132_HCD=m
CONFIG_USB_SL811_HCD=m
CONFIG_USB_SL811_HCD_ISO=y
CONFIG_USB_SL811_CS=m
CONFIG_USB_R8A66597_HCD=m
CONFIG_USB_HCD_BCMA=m
CONFIG_USB_HCD_SSB=m
# CONFIG_USB_HCD_TEST_MODE is not set

#
# USB Device Class drivers
#
CONFIG_USB_ACM=m
CONFIG_USB_PRINTER=m
CONFIG_USB_WDM=m
CONFIG_USB_TMC=m

#
# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
#

#
# also be needed; see USB_STORAGE Help for more info
#
CONFIG_USB_STORAGE=m
CONFIG_USB_STORAGE_DEBUG=y
CONFIG_USB_STORAGE_REALTEK=m
CONFIG_REALTEK_AUTOPM=y
CONFIG_USB_STORAGE_DATAFAB=m
CONFIG_USB_STORAGE_FREECOM=m
CONFIG_USB_STORAGE_ISD200=m
CONFIG_USB_STORAGE_USBAT=m
CONFIG_USB_STORAGE_SDDR09=m
CONFIG_USB_STORAGE_SDDR55=m
CONFIG_USB_STORAGE_JUMPSHOT=m
CONFIG_USB_STORAGE_ALAUDA=m
CONFIG_USB_STORAGE_ONETOUCH=m
CONFIG_USB_STORAGE_KARMA=m
CONFIG_USB_STORAGE_CYPRESS_ATACB=m
CONFIG_USB_STORAGE_ENE_UB6250=m
CONFIG_USB_UAS=m

#
# USB Imaging devices
#
CONFIG_USB_MDC800=m
CONFIG_USB_MICROTEK=m
CONFIG_USBIP_CORE=m
CONFIG_USBIP_VHCI_HCD=m
CONFIG_USBIP_VHCI_HC_PORTS=8
CONFIG_USBIP_VHCI_NR_HCS=1
CONFIG_USBIP_HOST=m
CONFIG_USBIP_VUDC=m
CONFIG_USBIP_DEBUG=y
CONFIG_USB_CDNS_SUPPORT=m
CONFIG_USB_CDNS_HOST=y
CONFIG_USB_CDNS3=m
CONFIG_USB_CDNS3_GADGET=y
CONFIG_USB_CDNS3_HOST=y
CONFIG_USB_CDNS3_PCI_WRAP=m
CONFIG_USB_CDNSP_PCI=m
CONFIG_USB_CDNSP_GADGET=y
CONFIG_USB_CDNSP_HOST=y
CONFIG_USB_MUSB_HDRC=m
# CONFIG_USB_MUSB_HOST is not set
# CONFIG_USB_MUSB_GADGET is not set
CONFIG_USB_MUSB_DUAL_ROLE=y

#
# Platform Glue Layer
#

#
# MUSB DMA mode
#
CONFIG_MUSB_PIO_ONLY=y
CONFIG_USB_DWC3=m
CONFIG_USB_DWC3_ULPI=y
# CONFIG_USB_DWC3_HOST is not set
# CONFIG_USB_DWC3_GADGET is not set
CONFIG_USB_DWC3_DUAL_ROLE=y

#
# Platform Glue Driver Support
#
CONFIG_USB_DWC3_PCI=m
CONFIG_USB_DWC3_HAPS=m
CONFIG_USB_DWC3_OF_SIMPLE=m
# CONFIG_USB_DWC2 is not set
CONFIG_USB_CHIPIDEA=m
CONFIG_USB_CHIPIDEA_UDC=y
CONFIG_USB_CHIPIDEA_HOST=y
CONFIG_USB_CHIPIDEA_PCI=m
CONFIG_USB_CHIPIDEA_MSM=m
CONFIG_USB_CHIPIDEA_IMX=m
CONFIG_USB_CHIPIDEA_GENERIC=m
CONFIG_USB_CHIPIDEA_TEGRA=m
CONFIG_USB_ISP1760=m
CONFIG_USB_ISP1760_HCD=y
CONFIG_USB_ISP1761_UDC=y
# CONFIG_USB_ISP1760_HOST_ROLE is not set
# CONFIG_USB_ISP1760_GADGET_ROLE is not set
CONFIG_USB_ISP1760_DUAL_ROLE=y

#
# USB port drivers
#
CONFIG_USB_USS720=m
CONFIG_USB_SERIAL=m
CONFIG_USB_SERIAL_GENERIC=y
CONFIG_USB_SERIAL_SIMPLE=m
CONFIG_USB_SERIAL_AIRCABLE=m
CONFIG_USB_SERIAL_ARK3116=m
CONFIG_USB_SERIAL_BELKIN=m
CONFIG_USB_SERIAL_CH341=m
CONFIG_USB_SERIAL_WHITEHEAT=m
CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
CONFIG_USB_SERIAL_CP210X=m
CONFIG_USB_SERIAL_CYPRESS_M8=m
CONFIG_USB_SERIAL_EMPEG=m
CONFIG_USB_SERIAL_FTDI_SIO=m
CONFIG_USB_SERIAL_VISOR=m
CONFIG_USB_SERIAL_IPAQ=m
CONFIG_USB_SERIAL_IR=m
CONFIG_USB_SERIAL_EDGEPORT=m
CONFIG_USB_SERIAL_EDGEPORT_TI=m
CONFIG_USB_SERIAL_F81232=m
CONFIG_USB_SERIAL_F8153X=m
CONFIG_USB_SERIAL_GARMIN=m
CONFIG_USB_SERIAL_IPW=m
CONFIG_USB_SERIAL_IUU=m
CONFIG_USB_SERIAL_KEYSPAN_PDA=m
CONFIG_USB_SERIAL_KEYSPAN=m
CONFIG_USB_SERIAL_KLSI=m
CONFIG_USB_SERIAL_KOBIL_SCT=m
CONFIG_USB_SERIAL_MCT_U232=m
CONFIG_USB_SERIAL_METRO=m
CONFIG_USB_SERIAL_MOS7720=m
CONFIG_USB_SERIAL_MOS7715_PARPORT=y
CONFIG_USB_SERIAL_MOS7840=m
CONFIG_USB_SERIAL_MXUPORT=m
CONFIG_USB_SERIAL_NAVMAN=m
CONFIG_USB_SERIAL_PL2303=m
CONFIG_USB_SERIAL_OTI6858=m
CONFIG_USB_SERIAL_QCAUX=m
CONFIG_USB_SERIAL_QUALCOMM=m
CONFIG_USB_SERIAL_SPCP8X5=m
CONFIG_USB_SERIAL_SAFE=m
CONFIG_USB_SERIAL_SAFE_PADDED=y
CONFIG_USB_SERIAL_SIERRAWIRELESS=m
CONFIG_USB_SERIAL_SYMBOL=m
CONFIG_USB_SERIAL_TI=m
CONFIG_USB_SERIAL_CYBERJACK=m
CONFIG_USB_SERIAL_WWAN=m
CONFIG_USB_SERIAL_OPTION=m
CONFIG_USB_SERIAL_OMNINET=m
CONFIG_USB_SERIAL_OPTICON=m
CONFIG_USB_SERIAL_XSENS_MT=m
CONFIG_USB_SERIAL_WISHBONE=m
CONFIG_USB_SERIAL_SSU100=m
CONFIG_USB_SERIAL_QT2=m
CONFIG_USB_SERIAL_UPD78F0730=m
CONFIG_USB_SERIAL_XR=m
CONFIG_USB_SERIAL_DEBUG=m

#
# USB Miscellaneous drivers
#
CONFIG_USB_EMI62=m
CONFIG_USB_EMI26=m
CONFIG_USB_ADUTUX=m
CONFIG_USB_SEVSEG=m
CONFIG_USB_LEGOTOWER=m
CONFIG_USB_LCD=m
CONFIG_USB_CYPRESS_CY7C63=m
CONFIG_USB_CYTHERM=m
CONFIG_USB_IDMOUSE=m
CONFIG_USB_FTDI_ELAN=m
CONFIG_USB_APPLEDISPLAY=m
CONFIG_APPLE_MFI_FASTCHARGE=m
CONFIG_USB_SISUSBVGA=m
CONFIG_USB_LD=m
CONFIG_USB_TRANCEVIBRATOR=m
CONFIG_USB_IOWARRIOR=m
# CONFIG_USB_TEST is not set
# CONFIG_USB_EHSET_TEST_FIXTURE is not set
CONFIG_USB_ISIGHTFW=m
CONFIG_USB_YUREX=m
CONFIG_USB_EZUSB_FX2=m
CONFIG_USB_HUB_USB251XB=m
CONFIG_USB_HSIC_USB3503=m
CONFIG_USB_HSIC_USB4604=m
# CONFIG_USB_LINK_LAYER_TEST is not set
CONFIG_USB_CHAOSKEY=m
CONFIG_USB_ONBOARD_HUB=m
CONFIG_USB_ATM=m
CONFIG_USB_SPEEDTOUCH=m
CONFIG_USB_CXACRU=m
CONFIG_USB_UEAGLEATM=m
CONFIG_USB_XUSBATM=m

#
# USB Physical Layer drivers
#
CONFIG_USB_PHY=y
CONFIG_NOP_USB_XCEIV=m
CONFIG_USB_GPIO_VBUS=m
CONFIG_TAHVO_USB=m
CONFIG_TAHVO_USB_HOST_BY_DEFAULT=y
CONFIG_USB_ISP1301=m
# end of USB Physical Layer drivers

CONFIG_USB_GADGET=m
CONFIG_USB_GADGET_DEBUG=y
CONFIG_USB_GADGET_VERBOSE=y
CONFIG_USB_GADGET_DEBUG_FILES=y
CONFIG_USB_GADGET_DEBUG_FS=y
CONFIG_USB_GADGET_VBUS_DRAW=2
CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2
CONFIG_U_SERIAL_CONSOLE=y

#
# USB Peripheral Controller
#
CONFIG_USB_FUSB300=m
CONFIG_USB_FOTG210_UDC=m
CONFIG_USB_GR_UDC=m
CONFIG_USB_R8A66597=m
CONFIG_USB_PXA27X=m
CONFIG_USB_MV_UDC=m
CONFIG_USB_MV_U3D=m
CONFIG_USB_SNP_CORE=m
CONFIG_USB_SNP_UDC_PLAT=m
CONFIG_USB_M66592=m
CONFIG_USB_BDC_UDC=m
# CONFIG_USB_AMD5536UDC is not set
CONFIG_USB_NET2272=m
CONFIG_USB_NET2272_DMA=y
CONFIG_USB_NET2280=m
CONFIG_USB_GOKU=m
CONFIG_USB_EG20T=m
CONFIG_USB_GADGET_XILINX=m
CONFIG_USB_MAX3420_UDC=m
CONFIG_USB_DUMMY_HCD=m
# end of USB Peripheral Controller

CONFIG_USB_LIBCOMPOSITE=m
CONFIG_USB_F_ACM=m
CONFIG_USB_F_SS_LB=m
CONFIG_USB_U_SERIAL=m
CONFIG_USB_U_ETHER=m
CONFIG_USB_U_AUDIO=m
CONFIG_USB_F_SERIAL=m
CONFIG_USB_F_OBEX=m
CONFIG_USB_F_NCM=m
CONFIG_USB_F_ECM=m
CONFIG_USB_F_PHONET=m
CONFIG_USB_F_EEM=m
CONFIG_USB_F_SUBSET=m
CONFIG_USB_F_RNDIS=m
CONFIG_USB_F_MASS_STORAGE=m
CONFIG_USB_F_FS=m
CONFIG_USB_F_UAC1=m
CONFIG_USB_F_UAC1_LEGACY=m
CONFIG_USB_F_UAC2=m
CONFIG_USB_F_UVC=m
CONFIG_USB_F_MIDI=m
CONFIG_USB_F_HID=m
CONFIG_USB_F_PRINTER=m
CONFIG_USB_F_TCM=m
CONFIG_USB_CONFIGFS=m
CONFIG_USB_CONFIGFS_SERIAL=y
CONFIG_USB_CONFIGFS_ACM=y
CONFIG_USB_CONFIGFS_OBEX=y
CONFIG_USB_CONFIGFS_NCM=y
CONFIG_USB_CONFIGFS_ECM=y
CONFIG_USB_CONFIGFS_ECM_SUBSET=y
CONFIG_USB_CONFIGFS_RNDIS=y
CONFIG_USB_CONFIGFS_EEM=y
CONFIG_USB_CONFIGFS_PHONET=y
CONFIG_USB_CONFIGFS_MASS_STORAGE=y
CONFIG_USB_CONFIGFS_F_LB_SS=y
CONFIG_USB_CONFIGFS_F_FS=y
CONFIG_USB_CONFIGFS_F_UAC1=y
CONFIG_USB_CONFIGFS_F_UAC1_LEGACY=y
CONFIG_USB_CONFIGFS_F_UAC2=y
CONFIG_USB_CONFIGFS_F_MIDI=y
CONFIG_USB_CONFIGFS_F_HID=y
CONFIG_USB_CONFIGFS_F_UVC=y
CONFIG_USB_CONFIGFS_F_PRINTER=y
CONFIG_USB_CONFIGFS_F_TCM=y

#
# USB Gadget precomposed configurations
#
CONFIG_USB_ZERO=m
CONFIG_USB_ZERO_HNPTEST=y
CONFIG_USB_AUDIO=m
CONFIG_GADGET_UAC1=y
CONFIG_GADGET_UAC1_LEGACY=y
CONFIG_USB_ETH=m
CONFIG_USB_ETH_RNDIS=y
CONFIG_USB_ETH_EEM=y
CONFIG_USB_G_NCM=m
CONFIG_USB_GADGETFS=m
CONFIG_USB_FUNCTIONFS=m
CONFIG_USB_FUNCTIONFS_ETH=y
CONFIG_USB_FUNCTIONFS_RNDIS=y
CONFIG_USB_FUNCTIONFS_GENERIC=y
CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_GADGET_TARGET=m
CONFIG_USB_G_SERIAL=m
CONFIG_USB_MIDI_GADGET=m
CONFIG_USB_G_PRINTER=m
CONFIG_USB_CDC_COMPOSITE=m
CONFIG_USB_G_NOKIA=m
CONFIG_USB_G_ACM_MS=m
CONFIG_USB_G_MULTI=m
CONFIG_USB_G_MULTI_RNDIS=y
CONFIG_USB_G_MULTI_CDC=y
CONFIG_USB_G_HID=m
CONFIG_USB_G_DBGP=m
# CONFIG_USB_G_DBGP_PRINTK is not set
CONFIG_USB_G_DBGP_SERIAL=y
# CONFIG_USB_G_WEBCAM is not set
CONFIG_USB_RAW_GADGET=m
# end of USB Gadget precomposed configurations

CONFIG_TYPEC=m
CONFIG_TYPEC_TCPM=m
CONFIG_TYPEC_TCPCI=m
CONFIG_TYPEC_RT1711H=m
CONFIG_TYPEC_MT6360=m
CONFIG_TYPEC_TCPCI_MT6370=m
CONFIG_TYPEC_TCPCI_MAXIM=m
CONFIG_TYPEC_FUSB302=m
CONFIG_TYPEC_WCOVE=m
CONFIG_TYPEC_UCSI=m
CONFIG_UCSI_CCG=m
CONFIG_UCSI_ACPI=m
CONFIG_UCSI_STM32G0=m
CONFIG_TYPEC_TPS6598X=m
CONFIG_TYPEC_ANX7411=m
CONFIG_TYPEC_RT1719=m
CONFIG_TYPEC_HD3SS3220=m
CONFIG_TYPEC_STUSB160X=m
CONFIG_TYPEC_WUSB3801=m

#
# USB Type-C Multiplexer/DeMultiplexer Switch support
#
CONFIG_TYPEC_MUX_FSA4480=m
CONFIG_TYPEC_MUX_PI3USB30532=m
CONFIG_TYPEC_MUX_INTEL_PMC=m
# end of USB Type-C Multiplexer/DeMultiplexer Switch support

#
# USB Type-C Alternate Mode drivers
#
CONFIG_TYPEC_DP_ALTMODE=m
CONFIG_TYPEC_NVIDIA_ALTMODE=m
# end of USB Type-C Alternate Mode drivers

CONFIG_USB_ROLE_SWITCH=y
CONFIG_USB_ROLES_INTEL_XHCI=m
CONFIG_MMC=m
CONFIG_PWRSEQ_EMMC=m
CONFIG_PWRSEQ_SD8787=m
CONFIG_PWRSEQ_SIMPLE=m
CONFIG_MMC_BLOCK=m
CONFIG_MMC_BLOCK_MINORS=8
CONFIG_SDIO_UART=m
# CONFIG_MMC_TEST is not set
CONFIG_MMC_CRYPTO=y

#
# MMC/SD/SDIO Host Controller Drivers
#
CONFIG_MMC_DEBUG=y
CONFIG_MMC_SDHCI=m
CONFIG_MMC_SDHCI_IO_ACCESSORS=y
CONFIG_MMC_SDHCI_PCI=m
CONFIG_MMC_RICOH_MMC=y
CONFIG_MMC_SDHCI_ACPI=m
CONFIG_MMC_SDHCI_PLTFM=m
CONFIG_MMC_SDHCI_OF_ARASAN=m
CONFIG_MMC_SDHCI_OF_AT91=m
CONFIG_MMC_SDHCI_OF_DWCMSHC=m
CONFIG_MMC_SDHCI_CADENCE=m
CONFIG_MMC_SDHCI_F_SDH30=m
CONFIG_MMC_SDHCI_MILBEAUT=m
CONFIG_MMC_WBSD=m
CONFIG_MMC_ALCOR=m
CONFIG_MMC_TIFM_SD=m
CONFIG_MMC_SPI=m
CONFIG_MMC_SDRICOH_CS=m
CONFIG_MMC_CB710=m
CONFIG_MMC_VIA_SDMMC=m
CONFIG_MMC_VUB300=m
CONFIG_MMC_USHC=m
CONFIG_MMC_USDHI6ROL0=m
CONFIG_MMC_REALTEK_PCI=m
CONFIG_MMC_REALTEK_USB=m
CONFIG_MMC_CQHCI=m
CONFIG_MMC_HSQ=m
CONFIG_MMC_TOSHIBA_PCI=m
CONFIG_MMC_MTK=m
CONFIG_MMC_SDHCI_XENON=m
CONFIG_MMC_SDHCI_OMAP=m
CONFIG_MMC_SDHCI_AM654=m
CONFIG_MMC_SDHCI_EXTERNAL_DMA=y
CONFIG_MMC_LITEX=m
CONFIG_SCSI_UFSHCD=m
CONFIG_SCSI_UFS_BSG=y
CONFIG_SCSI_UFS_CRYPTO=y
CONFIG_SCSI_UFS_HPB=y
CONFIG_SCSI_UFS_FAULT_INJECTION=y
CONFIG_SCSI_UFS_HWMON=y
CONFIG_SCSI_UFSHCD_PCI=m
CONFIG_SCSI_UFS_DWC_TC_PCI=m
CONFIG_SCSI_UFSHCD_PLATFORM=m
CONFIG_SCSI_UFS_CDNS_PLATFORM=m
CONFIG_SCSI_UFS_DWC_TC_PLATFORM=m
CONFIG_MEMSTICK=m
CONFIG_MEMSTICK_DEBUG=y

#
# MemoryStick drivers
#
CONFIG_MEMSTICK_UNSAFE_RESUME=y
CONFIG_MSPRO_BLOCK=m
CONFIG_MS_BLOCK=m

#
# MemoryStick Host Controller Drivers
#
CONFIG_MEMSTICK_TIFM_MS=m
CONFIG_MEMSTICK_JMICRON_38X=m
CONFIG_MEMSTICK_R592=m
CONFIG_MEMSTICK_REALTEK_PCI=m
CONFIG_MEMSTICK_REALTEK_USB=m
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=m
CONFIG_LEDS_CLASS_FLASH=m
CONFIG_LEDS_CLASS_MULTICOLOR=m
CONFIG_LEDS_BRIGHTNESS_HW_CHANGED=y

#
# LED drivers
#
CONFIG_LEDS_88PM860X=m
CONFIG_LEDS_AN30259A=m
CONFIG_LEDS_APU=m
CONFIG_LEDS_AW2013=m
CONFIG_LEDS_BCM6328=m
CONFIG_LEDS_BCM6358=m
CONFIG_LEDS_CPCAP=m
CONFIG_LEDS_CR0014114=m
CONFIG_LEDS_EL15203000=m
CONFIG_LEDS_LM3530=m
CONFIG_LEDS_LM3532=m
CONFIG_LEDS_LM3533=m
CONFIG_LEDS_LM3642=m
CONFIG_LEDS_LM3692X=m
CONFIG_LEDS_MT6323=m
CONFIG_LEDS_NET48XX=m
CONFIG_LEDS_WRAP=m
CONFIG_LEDS_PCA9532=m
CONFIG_LEDS_PCA9532_GPIO=y
CONFIG_LEDS_GPIO=m
CONFIG_LEDS_LP3944=m
CONFIG_LEDS_LP3952=m
CONFIG_LEDS_LP50XX=m
CONFIG_LEDS_LP55XX_COMMON=m
CONFIG_LEDS_LP5521=m
CONFIG_LEDS_LP5523=m
CONFIG_LEDS_LP5562=m
CONFIG_LEDS_LP8501=m
CONFIG_LEDS_LP8788=m
CONFIG_LEDS_LP8860=m
CONFIG_LEDS_PCA955X=m
CONFIG_LEDS_PCA955X_GPIO=y
CONFIG_LEDS_PCA963X=m
CONFIG_LEDS_WM831X_STATUS=m
CONFIG_LEDS_WM8350=m
CONFIG_LEDS_DA903X=m
CONFIG_LEDS_DA9052=m
CONFIG_LEDS_DAC124S085=m
CONFIG_LEDS_PWM=m
CONFIG_LEDS_REGULATOR=m
CONFIG_LEDS_BD2802=m
CONFIG_LEDS_INTEL_SS4200=m
CONFIG_LEDS_LT3593=m
CONFIG_LEDS_ADP5520=m
CONFIG_LEDS_MC13783=m
CONFIG_LEDS_TCA6507=m
CONFIG_LEDS_TLC591XX=m
CONFIG_LEDS_MAX77650=m
CONFIG_LEDS_MAX8997=m
CONFIG_LEDS_LM355x=m
CONFIG_LEDS_OT200=m
CONFIG_LEDS_MENF21BMC=m
CONFIG_LEDS_IS31FL319X=m
CONFIG_LEDS_IS31FL32XX=m

#
# LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM)
#
CONFIG_LEDS_BLINKM=m
CONFIG_LEDS_MLXCPLD=m
CONFIG_LEDS_MLXREG=m
CONFIG_LEDS_USER=m
CONFIG_LEDS_NIC78BX=m
CONFIG_LEDS_SPI_BYTE=m
CONFIG_LEDS_TI_LMU_COMMON=m
CONFIG_LEDS_LM3697=m
CONFIG_LEDS_LM36274=m
CONFIG_LEDS_TPS6105X=m
CONFIG_LEDS_LGM=m

#
# Flash and Torch LED drivers
#
CONFIG_LEDS_AAT1290=m
CONFIG_LEDS_AS3645A=m
CONFIG_LEDS_KTD2692=m
CONFIG_LEDS_LM3601X=m
CONFIG_LEDS_MAX77693=m
CONFIG_LEDS_MT6360=m
CONFIG_LEDS_RT4505=m
CONFIG_LEDS_RT8515=m
CONFIG_LEDS_SGM3140=m

#
# RGB LED drivers
#
CONFIG_LEDS_PWM_MULTICOLOR=m
CONFIG_LEDS_QCOM_LPG=m

#
# LED Triggers
#
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=m
CONFIG_LEDS_TRIGGER_ONESHOT=m
CONFIG_LEDS_TRIGGER_DISK=y
CONFIG_LEDS_TRIGGER_MTD=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=m
CONFIG_LEDS_TRIGGER_BACKLIGHT=m
CONFIG_LEDS_TRIGGER_CPU=y
CONFIG_LEDS_TRIGGER_ACTIVITY=m
CONFIG_LEDS_TRIGGER_GPIO=m
CONFIG_LEDS_TRIGGER_DEFAULT_ON=m

#
# iptables trigger is under Netfilter config (LED target)
#
CONFIG_LEDS_TRIGGER_TRANSIENT=m
CONFIG_LEDS_TRIGGER_CAMERA=m
CONFIG_LEDS_TRIGGER_PANIC=y
CONFIG_LEDS_TRIGGER_NETDEV=m
CONFIG_LEDS_TRIGGER_PATTERN=m
CONFIG_LEDS_TRIGGER_AUDIO=m
CONFIG_LEDS_TRIGGER_TTY=m

#
# Simple LED drivers
#
CONFIG_LEDS_SIEMENS_SIMATIC_IPC=m
CONFIG_ACCESSIBILITY=y
CONFIG_A11Y_BRAILLE_CONSOLE=y

#
# Speakup console speech
#
CONFIG_SPEAKUP=m
CONFIG_SPEAKUP_SERIALIO=y
CONFIG_SPEAKUP_SYNTH_ACNTSA=m
CONFIG_SPEAKUP_SYNTH_ACNTPC=m
CONFIG_SPEAKUP_SYNTH_APOLLO=m
CONFIG_SPEAKUP_SYNTH_AUDPTR=m
CONFIG_SPEAKUP_SYNTH_BNS=m
CONFIG_SPEAKUP_SYNTH_DECTLK=m
CONFIG_SPEAKUP_SYNTH_DECEXT=m
CONFIG_SPEAKUP_SYNTH_DECPC=m
CONFIG_SPEAKUP_SYNTH_DTLK=m
CONFIG_SPEAKUP_SYNTH_KEYPC=m
CONFIG_SPEAKUP_SYNTH_LTLK=m
CONFIG_SPEAKUP_SYNTH_SOFT=m
CONFIG_SPEAKUP_SYNTH_SPKOUT=m
CONFIG_SPEAKUP_SYNTH_TXPRT=m
CONFIG_SPEAKUP_SYNTH_DUMMY=m
# end of Speakup console speech

CONFIG_INFINIBAND=m
CONFIG_INFINIBAND_USER_MAD=m
CONFIG_INFINIBAND_USER_ACCESS=m
CONFIG_INFINIBAND_USER_MEM=y
CONFIG_INFINIBAND_ON_DEMAND_PAGING=y
CONFIG_INFINIBAND_ADDR_TRANS=y
CONFIG_INFINIBAND_ADDR_TRANS_CONFIGFS=y
CONFIG_INFINIBAND_CXGB4=m
CONFIG_INFINIBAND_IRDMA=m
CONFIG_MLX4_INFINIBAND=m
CONFIG_MLX5_INFINIBAND=m
CONFIG_INFINIBAND_MTHCA=m
CONFIG_INFINIBAND_MTHCA_DEBUG=y
CONFIG_INFINIBAND_OCRDMA=m
CONFIG_INFINIBAND_USNIC=m
CONFIG_INFINIBAND_VMWARE_PVRDMA=m
CONFIG_INFINIBAND_IPOIB=m
CONFIG_INFINIBAND_IPOIB_CM=y
CONFIG_INFINIBAND_IPOIB_DEBUG=y
CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y
CONFIG_INFINIBAND_SRP=m
CONFIG_INFINIBAND_SRPT=m
CONFIG_INFINIBAND_ISER=m
CONFIG_INFINIBAND_ISERT=m
CONFIG_INFINIBAND_RTRS=m
CONFIG_INFINIBAND_RTRS_CLIENT=m
CONFIG_INFINIBAND_RTRS_SERVER=m
CONFIG_EDAC_ATOMIC_SCRUB=y
CONFIG_EDAC_SUPPORT=y
CONFIG_EDAC=m
CONFIG_EDAC_LEGACY_SYSFS=y
CONFIG_EDAC_DEBUG=y
# CONFIG_EDAC_AMD76X is not set
CONFIG_EDAC_E7XXX=m
CONFIG_EDAC_E752X=m
CONFIG_EDAC_I82875P=m
CONFIG_EDAC_I82975X=m
CONFIG_EDAC_I3000=m
CONFIG_EDAC_I3200=m
CONFIG_EDAC_IE31200=m
CONFIG_EDAC_X38=m
CONFIG_EDAC_I5400=m
CONFIG_EDAC_I7CORE=m
CONFIG_EDAC_I82860=m
CONFIG_EDAC_R82600=m
CONFIG_EDAC_I5000=m
CONFIG_EDAC_I5100=m
CONFIG_EDAC_I7300=m
CONFIG_RTC_LIB=y
CONFIG_RTC_MC146818_LIB=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_HCTOSYS=y
CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
CONFIG_RTC_SYSTOHC=y
CONFIG_RTC_SYSTOHC_DEVICE="rtc0"
CONFIG_RTC_DEBUG=y
CONFIG_RTC_NVMEM=y

#
# RTC interfaces
#
CONFIG_RTC_INTF_SYSFS=y
CONFIG_RTC_INTF_PROC=y
CONFIG_RTC_INTF_DEV=y
CONFIG_RTC_INTF_DEV_UIE_EMUL=y
# CONFIG_RTC_DRV_TEST is not set

#
# I2C RTC drivers
#
CONFIG_RTC_DRV_88PM860X=m
CONFIG_RTC_DRV_88PM80X=m
CONFIG_RTC_DRV_ABB5ZES3=m
CONFIG_RTC_DRV_ABEOZ9=m
CONFIG_RTC_DRV_ABX80X=m
CONFIG_RTC_DRV_AS3722=m
CONFIG_RTC_DRV_DS1307=m
CONFIG_RTC_DRV_DS1307_CENTURY=y
CONFIG_RTC_DRV_DS1374=m
CONFIG_RTC_DRV_DS1374_WDT=y
CONFIG_RTC_DRV_DS1672=m
CONFIG_RTC_DRV_HYM8563=m
CONFIG_RTC_DRV_LP8788=m
CONFIG_RTC_DRV_MAX6900=m
CONFIG_RTC_DRV_MAX8907=m
CONFIG_RTC_DRV_MAX8925=m
CONFIG_RTC_DRV_MAX8998=m
CONFIG_RTC_DRV_MAX8997=m
CONFIG_RTC_DRV_MAX77686=m
CONFIG_RTC_DRV_NCT3018Y=m
CONFIG_RTC_DRV_RK808=m
CONFIG_RTC_DRV_RS5C372=m
CONFIG_RTC_DRV_ISL1208=m
CONFIG_RTC_DRV_ISL12022=m
CONFIG_RTC_DRV_ISL12026=m
CONFIG_RTC_DRV_X1205=m
CONFIG_RTC_DRV_PCF8523=m
CONFIG_RTC_DRV_PCF85063=m
CONFIG_RTC_DRV_PCF85363=m
CONFIG_RTC_DRV_PCF8563=m
CONFIG_RTC_DRV_PCF8583=m
CONFIG_RTC_DRV_M41T80=m
CONFIG_RTC_DRV_M41T80_WDT=y
CONFIG_RTC_DRV_BD70528=m
CONFIG_RTC_DRV_BQ32K=m
CONFIG_RTC_DRV_TWL4030=m
CONFIG_RTC_DRV_PALMAS=m
CONFIG_RTC_DRV_TPS6586X=m
CONFIG_RTC_DRV_TPS65910=m
CONFIG_RTC_DRV_RC5T583=m
CONFIG_RTC_DRV_RC5T619=m
CONFIG_RTC_DRV_S35390A=m
CONFIG_RTC_DRV_FM3130=m
CONFIG_RTC_DRV_RX8010=m
CONFIG_RTC_DRV_RX8581=m
CONFIG_RTC_DRV_RX8025=m
CONFIG_RTC_DRV_EM3027=m
CONFIG_RTC_DRV_RV3028=m
CONFIG_RTC_DRV_RV3032=m
CONFIG_RTC_DRV_RV8803=m
CONFIG_RTC_DRV_S5M=m
CONFIG_RTC_DRV_SD3078=m

#
# SPI RTC drivers
#
CONFIG_RTC_DRV_M41T93=m
CONFIG_RTC_DRV_M41T94=m
CONFIG_RTC_DRV_DS1302=m
CONFIG_RTC_DRV_DS1305=m
CONFIG_RTC_DRV_DS1343=m
CONFIG_RTC_DRV_DS1347=m
CONFIG_RTC_DRV_DS1390=m
CONFIG_RTC_DRV_MAX6916=m
CONFIG_RTC_DRV_R9701=m
CONFIG_RTC_DRV_RX4581=m
CONFIG_RTC_DRV_RS5C348=m
CONFIG_RTC_DRV_MAX6902=m
CONFIG_RTC_DRV_PCF2123=m
CONFIG_RTC_DRV_MCP795=m
CONFIG_RTC_I2C_AND_SPI=y

#
# SPI and I2C RTC drivers
#
CONFIG_RTC_DRV_DS3232=m
CONFIG_RTC_DRV_DS3232_HWMON=y
CONFIG_RTC_DRV_PCF2127=m
CONFIG_RTC_DRV_RV3029C2=m
CONFIG_RTC_DRV_RV3029_HWMON=y
CONFIG_RTC_DRV_RX6110=m

#
# Platform RTC drivers
#
CONFIG_RTC_DRV_CMOS=m
CONFIG_RTC_DRV_DS1286=m
CONFIG_RTC_DRV_DS1511=m
CONFIG_RTC_DRV_DS1553=m
CONFIG_RTC_DRV_DS1685_FAMILY=m
CONFIG_RTC_DRV_DS1685=y
# CONFIG_RTC_DRV_DS1689 is not set
# CONFIG_RTC_DRV_DS17285 is not set
# CONFIG_RTC_DRV_DS17485 is not set
# CONFIG_RTC_DRV_DS17885 is not set
CONFIG_RTC_DRV_DS1742=m
CONFIG_RTC_DRV_DS2404=m
CONFIG_RTC_DRV_DA9052=m
CONFIG_RTC_DRV_DA9055=m
CONFIG_RTC_DRV_DA9063=m
CONFIG_RTC_DRV_STK17TA8=m
CONFIG_RTC_DRV_M48T86=m
CONFIG_RTC_DRV_M48T35=m
CONFIG_RTC_DRV_M48T59=m
CONFIG_RTC_DRV_MSM6242=m
CONFIG_RTC_DRV_BQ4802=m
CONFIG_RTC_DRV_RP5C01=m
CONFIG_RTC_DRV_V3020=m
CONFIG_RTC_DRV_WM831X=m
CONFIG_RTC_DRV_WM8350=m
CONFIG_RTC_DRV_PCF50633=m
CONFIG_RTC_DRV_ZYNQMP=m
CONFIG_RTC_DRV_CROS_EC=m
CONFIG_RTC_DRV_NTXEC=m

#
# on-CPU RTC drivers
#
CONFIG_RTC_DRV_CADENCE=m
CONFIG_RTC_DRV_FTRTC010=m
CONFIG_RTC_DRV_PCAP=m
CONFIG_RTC_DRV_MC13XXX=m
CONFIG_RTC_DRV_MT6397=m
CONFIG_RTC_DRV_R7301=m
CONFIG_RTC_DRV_CPCAP=m

#
# HID Sensor RTC drivers
#
CONFIG_RTC_DRV_HID_SENSOR_TIME=m
CONFIG_RTC_DRV_GOLDFISH=m
CONFIG_RTC_DRV_WILCO_EC=m
CONFIG_DMADEVICES=y
CONFIG_DMADEVICES_DEBUG=y
CONFIG_DMADEVICES_VDEBUG=y

#
# DMA Devices
#
CONFIG_DMA_ENGINE=y
CONFIG_DMA_VIRTUAL_CHANNELS=y
CONFIG_DMA_ACPI=y
CONFIG_DMA_OF=y
CONFIG_ALTERA_MSGDMA=m
CONFIG_DW_AXI_DMAC=m
CONFIG_FSL_EDMA=m
CONFIG_INTEL_IDMA64=m
CONFIG_PCH_DMA=m
CONFIG_PLX_DMA=m
CONFIG_TIMB_DMA=m
CONFIG_XILINX_ZYNQMP_DPDMA=m
CONFIG_QCOM_HIDMA_MGMT=m
CONFIG_QCOM_HIDMA=m
CONFIG_DW_DMAC_CORE=m
CONFIG_DW_DMAC=m
CONFIG_DW_DMAC_PCI=m
CONFIG_DW_EDMA=m
CONFIG_DW_EDMA_PCIE=m
CONFIG_HSU_DMA=m
CONFIG_HSU_DMA_PCI=m
CONFIG_SF_PDMA=m
CONFIG_INTEL_LDMA=y

#
# DMA Clients
#
CONFIG_ASYNC_TX_DMA=y
CONFIG_DMATEST=m
CONFIG_DMA_ENGINE_RAID=y

#
# DMABUF options
#
CONFIG_SYNC_FILE=y
CONFIG_SW_SYNC=y
CONFIG_UDMABUF=y
CONFIG_DMABUF_MOVE_NOTIFY=y
CONFIG_DMABUF_DEBUG=y
# CONFIG_DMABUF_SELFTESTS is not set
CONFIG_DMABUF_HEAPS=y
CONFIG_DMABUF_SYSFS_STATS=y
CONFIG_DMABUF_HEAPS_SYSTEM=y
CONFIG_DMABUF_HEAPS_CMA=y
# end of DMABUF options

CONFIG_AUXDISPLAY=y
CONFIG_CHARLCD=m
CONFIG_LINEDISP=m
CONFIG_HD44780_COMMON=m
CONFIG_HD44780=m
CONFIG_KS0108=m
CONFIG_KS0108_PORT=0x378
CONFIG_KS0108_DELAY=2
CONFIG_CFAG12864B=m
CONFIG_CFAG12864B_RATE=20
CONFIG_IMG_ASCII_LCD=m
CONFIG_HT16K33=m
CONFIG_LCD2S=m
CONFIG_PARPORT_PANEL=m
CONFIG_PANEL_PARPORT=0
CONFIG_PANEL_PROFILE=5
CONFIG_PANEL_CHANGE_MESSAGE=y
CONFIG_PANEL_BOOT_MESSAGE=""
# CONFIG_CHARLCD_BL_OFF is not set
# CONFIG_CHARLCD_BL_ON is not set
CONFIG_CHARLCD_BL_FLASH=y
CONFIG_PANEL=m
CONFIG_UIO=m
CONFIG_UIO_CIF=m
CONFIG_UIO_PDRV_GENIRQ=m
CONFIG_UIO_DMEM_GENIRQ=m
CONFIG_UIO_AEC=m
CONFIG_UIO_SERCOS3=m
CONFIG_UIO_PCI_GENERIC=m
CONFIG_UIO_NETX=m
CONFIG_UIO_PRUSS=m
CONFIG_UIO_MF624=m
CONFIG_UIO_HV_GENERIC=m
CONFIG_UIO_DFL=m
CONFIG_VFIO=m
CONFIG_VFIO_IOMMU_TYPE1=m
CONFIG_VFIO_VIRQFD=m
CONFIG_VFIO_NOIOMMU=y
CONFIG_VFIO_PCI_CORE=m
CONFIG_VFIO_PCI_MMAP=y
CONFIG_VFIO_PCI_INTX=y
CONFIG_VFIO_PCI=m
CONFIG_VFIO_PCI_VGA=y
CONFIG_VFIO_PCI_IGD=y
CONFIG_MLX5_VFIO_PCI=m
CONFIG_VFIO_MDEV=m
CONFIG_IRQ_BYPASS_MANAGER=m
CONFIG_VIRT_DRIVERS=y
CONFIG_VMGENID=m
CONFIG_VBOXGUEST=m
CONFIG_NITRO_ENCLAVES=m
CONFIG_VIRTIO_ANCHOR=y
CONFIG_VIRTIO=y
CONFIG_VIRTIO_PCI_LIB=m
CONFIG_VIRTIO_PCI_LIB_LEGACY=m
CONFIG_VIRTIO_MENU=y
CONFIG_VIRTIO_PCI=m
CONFIG_VIRTIO_PCI_LEGACY=y
CONFIG_VIRTIO_VDPA=m
CONFIG_VIRTIO_BALLOON=m
CONFIG_VIRTIO_INPUT=m
CONFIG_VIRTIO_MMIO=m
CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES=y
CONFIG_VIRTIO_DMA_SHARED_BUFFER=m
CONFIG_VDPA=m
CONFIG_VDPA_SIM=m
CONFIG_VDPA_SIM_NET=m
CONFIG_VDPA_SIM_BLOCK=m
CONFIG_VDPA_USER=m
CONFIG_IFCVF=m
CONFIG_MLX5_VDPA=y
CONFIG_MLX5_VDPA_NET=m
CONFIG_VP_VDPA=m
CONFIG_ALIBABA_ENI_VDPA=m
CONFIG_VHOST_IOTLB=m
CONFIG_VHOST_RING=m
CONFIG_VHOST=m
CONFIG_VHOST_MENU=y
CONFIG_VHOST_NET=m
CONFIG_VHOST_SCSI=m
CONFIG_VHOST_VSOCK=m
CONFIG_VHOST_VDPA=m
CONFIG_VHOST_CROSS_ENDIAN_LEGACY=y

#
# Microsoft Hyper-V guest support
#
CONFIG_HYPERV=m
CONFIG_HYPERV_TIMER=y
CONFIG_HYPERV_UTILS=m
CONFIG_HYPERV_BALLOON=m
# end of Microsoft Hyper-V guest support

CONFIG_GREYBUS=m
CONFIG_GREYBUS_ES2=m
CONFIG_COMEDI=m
CONFIG_COMEDI_DEBUG=y
CONFIG_COMEDI_DEFAULT_BUF_SIZE_KB=2048
CONFIG_COMEDI_DEFAULT_BUF_MAXSIZE_KB=20480
CONFIG_COMEDI_MISC_DRIVERS=y
CONFIG_COMEDI_BOND=m
# CONFIG_COMEDI_TEST is not set
CONFIG_COMEDI_PARPORT=m
CONFIG_COMEDI_SSV_DNP=m
CONFIG_COMEDI_ISA_DRIVERS=y
CONFIG_COMEDI_PCL711=m
CONFIG_COMEDI_PCL724=m
CONFIG_COMEDI_PCL726=m
CONFIG_COMEDI_PCL730=m
CONFIG_COMEDI_PCL812=m
CONFIG_COMEDI_PCL816=m
CONFIG_COMEDI_PCL818=m
CONFIG_COMEDI_PCM3724=m
CONFIG_COMEDI_AMPLC_DIO200_ISA=m
CONFIG_COMEDI_AMPLC_PC236_ISA=m
CONFIG_COMEDI_AMPLC_PC263_ISA=m
CONFIG_COMEDI_RTI800=m
CONFIG_COMEDI_RTI802=m
CONFIG_COMEDI_DAC02=m
CONFIG_COMEDI_DAS16M1=m
CONFIG_COMEDI_DAS08_ISA=m
CONFIG_COMEDI_DAS16=m
CONFIG_COMEDI_DAS800=m
CONFIG_COMEDI_DAS1800=m
CONFIG_COMEDI_DAS6402=m
CONFIG_COMEDI_DT2801=m
CONFIG_COMEDI_DT2811=m
CONFIG_COMEDI_DT2814=m
CONFIG_COMEDI_DT2815=m
CONFIG_COMEDI_DT2817=m
CONFIG_COMEDI_DT282X=m
CONFIG_COMEDI_DMM32AT=m
CONFIG_COMEDI_FL512=m
CONFIG_COMEDI_AIO_AIO12_8=m
CONFIG_COMEDI_AIO_IIRO_16=m
CONFIG_COMEDI_II_PCI20KC=m
CONFIG_COMEDI_C6XDIGIO=m
CONFIG_COMEDI_MPC624=m
CONFIG_COMEDI_ADQ12B=m
CONFIG_COMEDI_NI_AT_A2150=m
CONFIG_COMEDI_NI_AT_AO=m
CONFIG_COMEDI_NI_ATMIO=m
CONFIG_COMEDI_NI_ATMIO16D=m
CONFIG_COMEDI_NI_LABPC_ISA=m
CONFIG_COMEDI_PCMAD=m
CONFIG_COMEDI_PCMDA12=m
CONFIG_COMEDI_PCMMIO=m
CONFIG_COMEDI_PCMUIO=m
CONFIG_COMEDI_MULTIQ3=m
CONFIG_COMEDI_S526=m
CONFIG_COMEDI_PCI_DRIVERS=m
CONFIG_COMEDI_8255_PCI=m
CONFIG_COMEDI_ADDI_WATCHDOG=m
CONFIG_COMEDI_ADDI_APCI_1032=m
CONFIG_COMEDI_ADDI_APCI_1500=m
CONFIG_COMEDI_ADDI_APCI_1516=m
CONFIG_COMEDI_ADDI_APCI_1564=m
CONFIG_COMEDI_ADDI_APCI_16XX=m
CONFIG_COMEDI_ADDI_APCI_2032=m
CONFIG_COMEDI_ADDI_APCI_2200=m
CONFIG_COMEDI_ADDI_APCI_3120=m
CONFIG_COMEDI_ADDI_APCI_3501=m
CONFIG_COMEDI_ADDI_APCI_3XXX=m
CONFIG_COMEDI_ADL_PCI6208=m
CONFIG_COMEDI_ADL_PCI7X3X=m
CONFIG_COMEDI_ADL_PCI8164=m
CONFIG_COMEDI_ADL_PCI9111=m
CONFIG_COMEDI_ADL_PCI9118=m
CONFIG_COMEDI_ADV_PCI1710=m
CONFIG_COMEDI_ADV_PCI1720=m
CONFIG_COMEDI_ADV_PCI1723=m
CONFIG_COMEDI_ADV_PCI1724=m
CONFIG_COMEDI_ADV_PCI1760=m
CONFIG_COMEDI_ADV_PCI_DIO=m
CONFIG_COMEDI_AMPLC_DIO200_PCI=m
CONFIG_COMEDI_AMPLC_PC236_PCI=m
CONFIG_COMEDI_AMPLC_PC263_PCI=m
CONFIG_COMEDI_AMPLC_PCI224=m
CONFIG_COMEDI_AMPLC_PCI230=m
CONFIG_COMEDI_CONTEC_PCI_DIO=m
CONFIG_COMEDI_DAS08_PCI=m
CONFIG_COMEDI_DT3000=m
CONFIG_COMEDI_DYNA_PCI10XX=m
CONFIG_COMEDI_GSC_HPDI=m
CONFIG_COMEDI_MF6X4=m
CONFIG_COMEDI_ICP_MULTI=m
CONFIG_COMEDI_DAQBOARD2000=m
CONFIG_COMEDI_JR3_PCI=m
CONFIG_COMEDI_KE_COUNTER=m
CONFIG_COMEDI_CB_PCIDAS64=m
CONFIG_COMEDI_CB_PCIDAS=m
CONFIG_COMEDI_CB_PCIDDA=m
CONFIG_COMEDI_CB_PCIMDAS=m
CONFIG_COMEDI_CB_PCIMDDA=m
CONFIG_COMEDI_ME4000=m
CONFIG_COMEDI_ME_DAQ=m
CONFIG_COMEDI_NI_6527=m
CONFIG_COMEDI_NI_65XX=m
CONFIG_COMEDI_NI_660X=m
CONFIG_COMEDI_NI_670X=m
CONFIG_COMEDI_NI_LABPC_PCI=m
CONFIG_COMEDI_NI_PCIDIO=m
CONFIG_COMEDI_NI_PCIMIO=m
CONFIG_COMEDI_RTD520=m
CONFIG_COMEDI_S626=m
CONFIG_COMEDI_MITE=m
CONFIG_COMEDI_NI_TIOCMD=m
CONFIG_COMEDI_PCMCIA_DRIVERS=m
CONFIG_COMEDI_CB_DAS16_CS=m
CONFIG_COMEDI_DAS08_CS=m
CONFIG_COMEDI_NI_DAQ_700_CS=m
CONFIG_COMEDI_NI_DAQ_DIO24_CS=m
CONFIG_COMEDI_NI_LABPC_CS=m
CONFIG_COMEDI_NI_MIO_CS=m
CONFIG_COMEDI_QUATECH_DAQP_CS=m
CONFIG_COMEDI_USB_DRIVERS=m
CONFIG_COMEDI_DT9812=m
CONFIG_COMEDI_NI_USB6501=m
CONFIG_COMEDI_USBDUX=m
CONFIG_COMEDI_USBDUXFAST=m
CONFIG_COMEDI_USBDUXSIGMA=m
CONFIG_COMEDI_VMK80XX=m
CONFIG_COMEDI_8254=m
CONFIG_COMEDI_8255=m
CONFIG_COMEDI_8255_SA=m
CONFIG_COMEDI_KCOMEDILIB=m
CONFIG_COMEDI_AMPLC_DIO200=m
CONFIG_COMEDI_AMPLC_PC236=m
CONFIG_COMEDI_DAS08=m
CONFIG_COMEDI_ISADMA=m
CONFIG_COMEDI_NI_LABPC=m
CONFIG_COMEDI_NI_LABPC_ISADMA=m
CONFIG_COMEDI_NI_TIO=m
CONFIG_COMEDI_NI_ROUTING=m
# CONFIG_COMEDI_TESTS is not set
CONFIG_STAGING=y
CONFIG_PRISM2_USB=m
CONFIG_RTL8192U=m
CONFIG_RTLLIB=m
CONFIG_RTLLIB_CRYPTO_CCMP=m
CONFIG_RTLLIB_CRYPTO_TKIP=m
CONFIG_RTLLIB_CRYPTO_WEP=m
CONFIG_RTL8192E=m
CONFIG_RTL8723BS=m
CONFIG_R8712U=m
CONFIG_R8188EU=m
CONFIG_RTS5208=m
CONFIG_VT6655=m
CONFIG_VT6656=m

#
# IIO staging drivers
#

#
# Accelerometers
#
CONFIG_ADIS16203=m
CONFIG_ADIS16240=m
# end of Accelerometers

#
# Analog to digital converters
#
CONFIG_AD7816=m
# end of Analog to digital converters

#
# Analog digital bi-direction converters
#
CONFIG_ADT7316=m
CONFIG_ADT7316_SPI=m
CONFIG_ADT7316_I2C=m
# end of Analog digital bi-direction converters

#
# Direct Digital Synthesis
#
CONFIG_AD9832=m
CONFIG_AD9834=m
# end of Direct Digital Synthesis

#
# Network Analyzer, Impedance Converters
#
CONFIG_AD5933=m
# end of Network Analyzer, Impedance Converters

#
# Active energy metering IC
#
CONFIG_ADE7854=m
CONFIG_ADE7854_I2C=m
CONFIG_ADE7854_SPI=m
# end of Active energy metering IC

#
# Resolver to digital converters
#
CONFIG_AD2S1210=m
# end of Resolver to digital converters
# end of IIO staging drivers

CONFIG_FB_SM750=m
CONFIG_STAGING_MEDIA=y
CONFIG_INTEL_ATOMISP=y
CONFIG_VIDEO_ATOMISP=m
CONFIG_VIDEO_ATOMISP_ISP2401=y
CONFIG_VIDEO_ATOMISP_OV2722=m
CONFIG_VIDEO_ATOMISP_GC2235=m
CONFIG_VIDEO_ATOMISP_MSRLIST_HELPER=m
CONFIG_VIDEO_ATOMISP_MT9M114=m
CONFIG_VIDEO_ATOMISP_GC0310=m
CONFIG_VIDEO_ATOMISP_OV2680=m
CONFIG_VIDEO_ATOMISP_OV5693=m
CONFIG_VIDEO_ATOMISP_LM3554=m
CONFIG_VIDEO_IPU3_IMGU=m
CONFIG_VIDEO_MAX96712=m
CONFIG_STAGING_MEDIA_DEPRECATED=y
CONFIG_VIDEO_CPIA2=m
CONFIG_VIDEO_MEYE=m
CONFIG_VIDEO_SAA7146=m
CONFIG_VIDEO_SAA7146_VV=m
CONFIG_DVB_AV7110_IR=y
CONFIG_DVB_AV7110=m
CONFIG_DVB_AV7110_OSD=y
CONFIG_DVB_BUDGET_PATCH=m
CONFIG_DVB_SP8870=m
CONFIG_VIDEO_HEXIUM_GEMINI=m
CONFIG_VIDEO_HEXIUM_ORION=m
CONFIG_VIDEO_MXB=m
CONFIG_DVB_BUDGET_CORE=m
CONFIG_DVB_BUDGET=m
CONFIG_DVB_BUDGET_CI=m
CONFIG_DVB_BUDGET_AV=m
CONFIG_VIDEO_STKWEBCAM=m
CONFIG_VIDEO_TM6000=m
CONFIG_VIDEO_TM6000_ALSA=m
CONFIG_VIDEO_TM6000_DVB=m
CONFIG_USB_ZR364XX=m
CONFIG_STAGING_BOARD=y
CONFIG_LTE_GDM724X=m
CONFIG_FB_TFT=m
CONFIG_FB_TFT_AGM1264K_FL=m
CONFIG_FB_TFT_BD663474=m
CONFIG_FB_TFT_HX8340BN=m
CONFIG_FB_TFT_HX8347D=m
CONFIG_FB_TFT_HX8353D=m
CONFIG_FB_TFT_HX8357D=m
CONFIG_FB_TFT_ILI9163=m
CONFIG_FB_TFT_ILI9320=m
CONFIG_FB_TFT_ILI9325=m
CONFIG_FB_TFT_ILI9340=m
CONFIG_FB_TFT_ILI9341=m
CONFIG_FB_TFT_ILI9481=m
CONFIG_FB_TFT_ILI9486=m
CONFIG_FB_TFT_PCD8544=m
CONFIG_FB_TFT_RA8875=m
CONFIG_FB_TFT_S6D02A1=m
CONFIG_FB_TFT_S6D1121=m
CONFIG_FB_TFT_SEPS525=m
CONFIG_FB_TFT_SH1106=m
CONFIG_FB_TFT_SSD1289=m
CONFIG_FB_TFT_SSD1305=m
CONFIG_FB_TFT_SSD1306=m
CONFIG_FB_TFT_SSD1331=m
CONFIG_FB_TFT_SSD1351=m
CONFIG_FB_TFT_ST7735R=m
CONFIG_FB_TFT_ST7789V=m
CONFIG_FB_TFT_TINYLCD=m
CONFIG_FB_TFT_TLS8204=m
CONFIG_FB_TFT_UC1611=m
CONFIG_FB_TFT_UC1701=m
CONFIG_FB_TFT_UPD161704=m
CONFIG_MOST_COMPONENTS=m
CONFIG_MOST_NET=m
CONFIG_MOST_VIDEO=m
CONFIG_MOST_DIM2=m
CONFIG_MOST_I2C=m
CONFIG_KS7010=m
CONFIG_GREYBUS_AUDIO=m
CONFIG_GREYBUS_AUDIO_APB_CODEC=m
CONFIG_GREYBUS_BOOTROM=m
CONFIG_GREYBUS_FIRMWARE=m
CONFIG_GREYBUS_HID=m
CONFIG_GREYBUS_LIGHT=m
CONFIG_GREYBUS_LOG=m
CONFIG_GREYBUS_LOOPBACK=m
CONFIG_GREYBUS_POWER=m
CONFIG_GREYBUS_RAW=m
CONFIG_GREYBUS_VIBRATOR=m
CONFIG_GREYBUS_BRIDGED_PHY=m
CONFIG_GREYBUS_GPIO=m
CONFIG_GREYBUS_I2C=m
CONFIG_GREYBUS_PWM=m
CONFIG_GREYBUS_SDIO=m
CONFIG_GREYBUS_SPI=m
CONFIG_GREYBUS_UART=m
CONFIG_GREYBUS_USB=m
CONFIG_PI433=m
CONFIG_XIL_AXIS_FIFO=m
CONFIG_FIELDBUS_DEV=m
CONFIG_HMS_ANYBUSS_BUS=m
CONFIG_ARCX_ANYBUS_CONTROLLER=m
CONFIG_HMS_PROFINET=m
CONFIG_QLGE=m
CONFIG_VME_BUS=y

#
# VME Bridge Drivers
#
CONFIG_VME_TSI148=m
CONFIG_VME_FAKE=m

#
# VME Device Drivers
#
CONFIG_VME_USER=m
CONFIG_GOLDFISH_PIPE=m
CONFIG_CHROME_PLATFORMS=y
CONFIG_CHROMEOS_ACPI=m
CONFIG_CHROMEOS_LAPTOP=m
CONFIG_CHROMEOS_PSTORE=m
CONFIG_CHROMEOS_TBMC=m
CONFIG_CROS_EC=m
CONFIG_CROS_EC_I2C=m
CONFIG_CROS_EC_RPMSG=m
CONFIG_CROS_EC_SPI=m
CONFIG_CROS_EC_LPC=m
CONFIG_CROS_EC_PROTO=y
CONFIG_CROS_KBD_LED_BACKLIGHT=m
CONFIG_CROS_EC_CHARDEV=m
CONFIG_CROS_EC_LIGHTBAR=m
CONFIG_CROS_EC_VBC=m
CONFIG_CROS_EC_DEBUGFS=m
CONFIG_CROS_EC_SENSORHUB=m
CONFIG_CROS_EC_SYSFS=m
CONFIG_CROS_EC_TYPEC=m
CONFIG_CROS_USBPD_LOGGER=m
CONFIG_CROS_USBPD_NOTIFY=m
CONFIG_CHROMEOS_PRIVACY_SCREEN=m
CONFIG_CROS_TYPEC_SWITCH=m
CONFIG_WILCO_EC=m
CONFIG_WILCO_EC_DEBUGFS=m
CONFIG_WILCO_EC_EVENTS=m
CONFIG_WILCO_EC_TELEMETRY=m
CONFIG_MELLANOX_PLATFORM=y
CONFIG_MLXREG_HOTPLUG=m
CONFIG_MLXREG_IO=m
CONFIG_MLXREG_LC=m
CONFIG_NVSW_SN2201=m
CONFIG_OLPC_EC=y
CONFIG_SURFACE_PLATFORMS=y
CONFIG_SURFACE3_WMI=m
CONFIG_SURFACE_3_POWER_OPREGION=m
CONFIG_SURFACE_ACPI_NOTIFY=m
CONFIG_SURFACE_AGGREGATOR_CDEV=m
CONFIG_SURFACE_AGGREGATOR_HUB=m
CONFIG_SURFACE_AGGREGATOR_REGISTRY=m
CONFIG_SURFACE_AGGREGATOR_TABLET_SWITCH=m
CONFIG_SURFACE_DTX=m
CONFIG_SURFACE_GPE=m
CONFIG_SURFACE_HOTPLUG=m
CONFIG_SURFACE_PLATFORM_PROFILE=m
CONFIG_SURFACE_PRO3_BUTTON=m
CONFIG_SURFACE_AGGREGATOR=m
CONFIG_SURFACE_AGGREGATOR_BUS=y
CONFIG_SURFACE_AGGREGATOR_ERROR_INJECTION=y
CONFIG_X86_PLATFORM_DEVICES=y
CONFIG_ACPI_WMI=m
CONFIG_WMI_BMOF=m
CONFIG_HUAWEI_WMI=m
CONFIG_MXM_WMI=m
CONFIG_PEAQ_WMI=m
CONFIG_NVIDIA_WMI_EC_BACKLIGHT=m
CONFIG_XIAOMI_WMI=m
CONFIG_GIGABYTE_WMI=m
CONFIG_YOGABOOK_WMI=m
CONFIG_ACERHDF=m
CONFIG_ACER_WIRELESS=m
CONFIG_ACER_WMI=m
CONFIG_AMD_PMF=m
# CONFIG_AMD_PMC is not set
CONFIG_ADV_SWBUTTON=m
CONFIG_APPLE_GMUX=m
CONFIG_ASUS_LAPTOP=m
CONFIG_ASUS_WIRELESS=m
CONFIG_ASUS_WMI=m
CONFIG_ASUS_NB_WMI=m
CONFIG_ASUS_TF103C_DOCK=m
CONFIG_MERAKI_MX100=m
CONFIG_EEEPC_LAPTOP=m
CONFIG_EEEPC_WMI=m
CONFIG_X86_PLATFORM_DRIVERS_DELL=y
CONFIG_ALIENWARE_WMI=m
CONFIG_DCDBAS=m
CONFIG_DELL_LAPTOP=m
CONFIG_DELL_RBU=m
CONFIG_DELL_RBTN=m
CONFIG_DELL_SMBIOS=m
CONFIG_DELL_SMBIOS_WMI=y
CONFIG_DELL_SMBIOS_SMM=y
CONFIG_DELL_SMO8800=m
CONFIG_DELL_WMI=m
CONFIG_DELL_WMI_PRIVACY=y
CONFIG_DELL_WMI_AIO=m
CONFIG_DELL_WMI_DESCRIPTOR=m
CONFIG_DELL_WMI_LED=m
CONFIG_DELL_WMI_SYSMAN=m
CONFIG_AMILO_RFKILL=m
CONFIG_FUJITSU_LAPTOP=m
CONFIG_FUJITSU_TABLET=m
CONFIG_GPD_POCKET_FAN=m
CONFIG_HP_ACCEL=m
CONFIG_WIRELESS_HOTKEY=m
CONFIG_HP_WMI=m
CONFIG_TC1100_WMI=m
CONFIG_IBM_RTL=m
CONFIG_IDEAPAD_LAPTOP=m
CONFIG_SENSORS_HDAPS=m
CONFIG_THINKPAD_ACPI=m
CONFIG_THINKPAD_ACPI_ALSA_SUPPORT=y
CONFIG_THINKPAD_ACPI_DEBUGFACILITIES=y
CONFIG_THINKPAD_ACPI_DEBUG=y
CONFIG_THINKPAD_ACPI_UNSAFE_LEDS=y
CONFIG_THINKPAD_ACPI_VIDEO=y
CONFIG_THINKPAD_ACPI_HOTKEY_POLL=y
CONFIG_THINKPAD_LMI=m
CONFIG_INTEL_ATOMISP2_PDX86=y
CONFIG_INTEL_ATOMISP2_LED=m
CONFIG_INTEL_SAR_INT1092=m
CONFIG_INTEL_SKL_INT3472=m
CONFIG_INTEL_PMC_CORE=m
CONFIG_INTEL_PMT_CLASS=m
CONFIG_INTEL_PMT_TELEMETRY=m
CONFIG_INTEL_PMT_CRASHLOG=m
CONFIG_INTEL_WMI=y
CONFIG_INTEL_WMI_SBL_FW_UPDATE=m
CONFIG_INTEL_WMI_THUNDERBOLT=m
CONFIG_INTEL_HID_EVENT=m
CONFIG_INTEL_VBTN=m
CONFIG_INTEL_INT0002_VGPIO=m
CONFIG_INTEL_OAKTRAIL=m
CONFIG_INTEL_BXTWC_PMIC_TMU=m
CONFIG_INTEL_CHTWC_INT33FE=m
CONFIG_INTEL_MRFLD_PWRBTN=m
CONFIG_INTEL_PUNIT_IPC=m
CONFIG_INTEL_RST=m
CONFIG_INTEL_SMARTCONNECT=m
CONFIG_INTEL_VSEC=m
CONFIG_MSI_LAPTOP=m
CONFIG_MSI_WMI=m
CONFIG_XO15_EBOOK=m
CONFIG_XO1_RFKILL=m
CONFIG_PCENGINES_APU2=m
CONFIG_BARCO_P50_GPIO=m
CONFIG_SAMSUNG_LAPTOP=m
CONFIG_SAMSUNG_Q10=m
CONFIG_ACPI_TOSHIBA=m
CONFIG_TOSHIBA_BT_RFKILL=m
CONFIG_TOSHIBA_HAPS=m
CONFIG_TOSHIBA_WMI=m
CONFIG_ACPI_CMPC=m
CONFIG_COMPAL_LAPTOP=m
CONFIG_LG_LAPTOP=m
CONFIG_PANASONIC_LAPTOP=m
CONFIG_SONY_LAPTOP=m
CONFIG_SONYPI_COMPAT=y
CONFIG_SYSTEM76_ACPI=m
CONFIG_TOPSTAR_LAPTOP=m
CONFIG_SERIAL_MULTI_INSTANTIATE=m
CONFIG_MLX_PLATFORM=m
CONFIG_TOUCHSCREEN_DMI=y
CONFIG_X86_ANDROID_TABLETS=m
CONFIG_FW_ATTR_CLASS=m
CONFIG_INTEL_IMR=y
CONFIG_INTEL_IPS=m
CONFIG_INTEL_SCU_IPC=y
CONFIG_INTEL_SCU=y
CONFIG_INTEL_SCU_PCI=y
CONFIG_INTEL_SCU_PLATFORM=m
CONFIG_INTEL_SCU_WDT=y
CONFIG_INTEL_SCU_IPC_UTIL=m
CONFIG_SIEMENS_SIMATIC_IPC=m
CONFIG_WINMATE_FM07_KEYS=m
CONFIG_P2SB=y
CONFIG_HAVE_CLK=y
CONFIG_HAVE_CLK_PREPARE=y
CONFIG_COMMON_CLK=y
CONFIG_COMMON_CLK_WM831X=m
CONFIG_LMK04832=m
CONFIG_COMMON_CLK_MAX77686=m
CONFIG_COMMON_CLK_MAX9485=m
CONFIG_COMMON_CLK_RK808=m
CONFIG_COMMON_CLK_SI5341=m
CONFIG_COMMON_CLK_SI5351=m
CONFIG_COMMON_CLK_SI514=m
CONFIG_COMMON_CLK_SI544=m
CONFIG_COMMON_CLK_SI570=m
CONFIG_COMMON_CLK_CDCE706=m
CONFIG_COMMON_CLK_TPS68470=m
CONFIG_COMMON_CLK_CDCE925=m
CONFIG_COMMON_CLK_CS2000_CP=m
CONFIG_COMMON_CLK_S2MPS11=m
CONFIG_CLK_TWL6040=m
CONFIG_COMMON_CLK_AXI_CLKGEN=m
CONFIG_COMMON_CLK_LOCHNAGAR=m
CONFIG_COMMON_CLK_PALMAS=m
CONFIG_COMMON_CLK_PWM=m
CONFIG_COMMON_CLK_RS9_PCIE=m
CONFIG_COMMON_CLK_VC5=m
CONFIG_COMMON_CLK_VC7=m
CONFIG_COMMON_CLK_BD718XX=m
CONFIG_COMMON_CLK_FIXED_MMIO=y
CONFIG_CLK_LGM_CGU=y
CONFIG_XILINX_VCU=m
CONFIG_COMMON_CLK_XLNX_CLKWZRD=m
CONFIG_HWSPINLOCK=y

#
# Clock Source drivers
#
CONFIG_TIMER_OF=y
CONFIG_TIMER_PROBE=y
CONFIG_CLKSRC_I8253=y
CONFIG_CLKEVT_I8253=y
CONFIG_I8253_LOCK=y
CONFIG_CLKBLD_I8253=y
CONFIG_DW_APB_TIMER=y
CONFIG_MICROCHIP_PIT64B=y
# end of Clock Source drivers

CONFIG_MAILBOX=y
CONFIG_PLATFORM_MHU=m
CONFIG_PCC=y
CONFIG_ALTERA_MBOX=m
# CONFIG_MAILBOX_TEST is not set
CONFIG_IOMMU_IOVA=y
CONFIG_IOASID=y
CONFIG_IOMMU_API=y
CONFIG_IOMMU_SUPPORT=y

#
# Generic IOMMU Pagetable Support
#
# end of Generic IOMMU Pagetable Support

CONFIG_IOMMU_DEBUGFS=y
# CONFIG_IOMMU_DEFAULT_DMA_STRICT is not set
CONFIG_IOMMU_DEFAULT_DMA_LAZY=y
# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
CONFIG_OF_IOMMU=y
CONFIG_IOMMU_DMA=y
CONFIG_DMAR_TABLE=y
CONFIG_DMAR_PERF=y
CONFIG_DMAR_DEBUG=y
CONFIG_INTEL_IOMMU=y
CONFIG_INTEL_IOMMU_DEBUGFS=y
CONFIG_INTEL_IOMMU_DEFAULT_ON=y
CONFIG_INTEL_IOMMU_FLOPPY_WA=y
CONFIG_INTEL_IOMMU_SCALABLE_MODE_DEFAULT_ON=y
CONFIG_HYPERV_IOMMU=y
CONFIG_VIRTIO_IOMMU=m

#
# Remoteproc drivers
#
CONFIG_REMOTEPROC=y
CONFIG_REMOTEPROC_CDEV=y
# end of Remoteproc drivers

#
# Rpmsg drivers
#
CONFIG_RPMSG=m
CONFIG_RPMSG_CHAR=m
CONFIG_RPMSG_CTRL=m
CONFIG_RPMSG_NS=m
CONFIG_RPMSG_QCOM_GLINK=m
CONFIG_RPMSG_QCOM_GLINK_RPM=m
CONFIG_RPMSG_VIRTIO=m
# end of Rpmsg drivers

CONFIG_SOUNDWIRE=m

#
# SoundWire Devices
#
CONFIG_SOUNDWIRE_CADENCE=m
CONFIG_SOUNDWIRE_INTEL=m
CONFIG_SOUNDWIRE_QCOM=m
CONFIG_SOUNDWIRE_GENERIC_ALLOCATION=m

#
# SOC (System On Chip) specific Drivers
#

#
# Amlogic SoC drivers
#
# end of Amlogic SoC drivers

#
# Broadcom SoC drivers
#
# end of Broadcom SoC drivers

#
# NXP/Freescale QorIQ SoC drivers
#
# end of NXP/Freescale QorIQ SoC drivers

#
# fujitsu SoC drivers
#
# end of fujitsu SoC drivers

#
# i.MX SoC drivers
#
# end of i.MX SoC drivers

#
# Enable LiteX SoC Builder specific drivers
#
CONFIG_LITEX=y
CONFIG_LITEX_SOC_CONTROLLER=m
# end of Enable LiteX SoC Builder specific drivers

#
# Qualcomm SoC drivers
#
CONFIG_QCOM_QMI_HELPERS=m
# end of Qualcomm SoC drivers

CONFIG_SOC_TI=y

#
# Xilinx SoC drivers
#
# end of Xilinx SoC drivers
# end of SOC (System On Chip) specific Drivers

CONFIG_PM_DEVFREQ=y

#
# DEVFREQ Governors
#
CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=m
CONFIG_DEVFREQ_GOV_PERFORMANCE=m
CONFIG_DEVFREQ_GOV_POWERSAVE=m
CONFIG_DEVFREQ_GOV_USERSPACE=m
CONFIG_DEVFREQ_GOV_PASSIVE=m

#
# DEVFREQ Drivers
#
CONFIG_PM_DEVFREQ_EVENT=y
CONFIG_EXTCON=y

#
# Extcon Device Drivers
#
CONFIG_EXTCON_ADC_JACK=m
CONFIG_EXTCON_AXP288=m
CONFIG_EXTCON_FSA9480=m
CONFIG_EXTCON_GPIO=m
CONFIG_EXTCON_INTEL_INT3496=m
CONFIG_EXTCON_INTEL_MRFLD=m
CONFIG_EXTCON_MAX14577=m
CONFIG_EXTCON_MAX3355=m
CONFIG_EXTCON_MAX77693=m
CONFIG_EXTCON_MAX77843=m
CONFIG_EXTCON_MAX8997=m
CONFIG_EXTCON_PALMAS=m
CONFIG_EXTCON_PTN5150=m
CONFIG_EXTCON_RT8973A=m
CONFIG_EXTCON_SM5502=m
CONFIG_EXTCON_USB_GPIO=m
CONFIG_EXTCON_USBC_CROS_EC=m
CONFIG_EXTCON_USBC_TUSB320=m
CONFIG_MEMORY=y
CONFIG_FPGA_DFL_EMIF=m
CONFIG_IIO=m
CONFIG_IIO_BUFFER=y
CONFIG_IIO_BUFFER_CB=m
CONFIG_IIO_BUFFER_DMA=m
CONFIG_IIO_BUFFER_DMAENGINE=m
CONFIG_IIO_BUFFER_HW_CONSUMER=m
CONFIG_IIO_KFIFO_BUF=m
CONFIG_IIO_TRIGGERED_BUFFER=m
CONFIG_IIO_CONFIGFS=m
CONFIG_IIO_TRIGGER=y
CONFIG_IIO_CONSUMERS_PER_TRIGGER=2
CONFIG_IIO_SW_DEVICE=m
CONFIG_IIO_SW_TRIGGER=m
CONFIG_IIO_TRIGGERED_EVENT=m

#
# Accelerometers
#
CONFIG_ADIS16201=m
CONFIG_ADIS16209=m
CONFIG_ADXL313=m
CONFIG_ADXL313_I2C=m
CONFIG_ADXL313_SPI=m
CONFIG_ADXL355=m
CONFIG_ADXL355_I2C=m
CONFIG_ADXL355_SPI=m
CONFIG_ADXL367=m
CONFIG_ADXL367_SPI=m
CONFIG_ADXL367_I2C=m
CONFIG_ADXL372=m
CONFIG_ADXL372_SPI=m
CONFIG_ADXL372_I2C=m
CONFIG_BMA220=m
CONFIG_BMA400=m
CONFIG_BMA400_I2C=m
CONFIG_BMA400_SPI=m
CONFIG_BMC150_ACCEL=m
CONFIG_BMC150_ACCEL_I2C=m
CONFIG_BMC150_ACCEL_SPI=m
CONFIG_BMI088_ACCEL=m
CONFIG_BMI088_ACCEL_SPI=m
CONFIG_DA280=m
CONFIG_DA311=m
CONFIG_DMARD06=m
CONFIG_DMARD09=m
CONFIG_DMARD10=m
CONFIG_FXLS8962AF=m
CONFIG_FXLS8962AF_I2C=m
CONFIG_FXLS8962AF_SPI=m
CONFIG_HID_SENSOR_ACCEL_3D=m
CONFIG_IIO_CROS_EC_ACCEL_LEGACY=m
CONFIG_IIO_ST_ACCEL_3AXIS=m
CONFIG_IIO_ST_ACCEL_I2C_3AXIS=m
CONFIG_IIO_ST_ACCEL_SPI_3AXIS=m
CONFIG_KXSD9=m
CONFIG_KXSD9_SPI=m
CONFIG_KXSD9_I2C=m
CONFIG_KXCJK1013=m
CONFIG_MC3230=m
CONFIG_MMA7455=m
CONFIG_MMA7455_I2C=m
CONFIG_MMA7455_SPI=m
CONFIG_MMA7660=m
CONFIG_MMA8452=m
CONFIG_MMA9551_CORE=m
CONFIG_MMA9551=m
CONFIG_MMA9553=m
CONFIG_MSA311=m
CONFIG_MXC4005=m
CONFIG_MXC6255=m
CONFIG_SCA3000=m
CONFIG_SCA3300=m
CONFIG_STK8312=m
CONFIG_STK8BA50=m
# end of Accelerometers

#
# Analog to digital converters
#
CONFIG_AD_SIGMA_DELTA=m
CONFIG_AD7091R5=m
CONFIG_AD7124=m
CONFIG_AD7192=m
CONFIG_AD7266=m
CONFIG_AD7280=m
CONFIG_AD7291=m
CONFIG_AD7292=m
CONFIG_AD7298=m
CONFIG_AD7476=m
CONFIG_AD7606=m
CONFIG_AD7606_IFACE_PARALLEL=m
CONFIG_AD7606_IFACE_SPI=m
CONFIG_AD7766=m
CONFIG_AD7768_1=m
CONFIG_AD7780=m
CONFIG_AD7791=m
CONFIG_AD7793=m
CONFIG_AD7887=m
CONFIG_AD7923=m
CONFIG_AD7949=m
CONFIG_AD799X=m
CONFIG_AD9467=m
CONFIG_ADI_AXI_ADC=m
CONFIG_AXP20X_ADC=m
CONFIG_AXP288_ADC=m
CONFIG_CC10001_ADC=m
CONFIG_CPCAP_ADC=m
CONFIG_DA9150_GPADC=m
CONFIG_DLN2_ADC=m
CONFIG_ENVELOPE_DETECTOR=m
CONFIG_HI8435=m
CONFIG_HX711=m
CONFIG_INA2XX_ADC=m
CONFIG_INTEL_MRFLD_ADC=m
CONFIG_LP8788_ADC=m
CONFIG_LTC2471=m
CONFIG_LTC2485=m
CONFIG_LTC2496=m
CONFIG_LTC2497=m
CONFIG_MAX1027=m
CONFIG_MAX11100=m
CONFIG_MAX1118=m
CONFIG_MAX11205=m
CONFIG_MAX1241=m
CONFIG_MAX1363=m
CONFIG_MAX9611=m
CONFIG_MCP320X=m
CONFIG_MCP3422=m
CONFIG_MCP3911=m
CONFIG_MEDIATEK_MT6360_ADC=m
CONFIG_MEN_Z188_ADC=m
CONFIG_MP2629_ADC=m
CONFIG_NAU7802=m
CONFIG_PALMAS_GPADC=m
CONFIG_QCOM_VADC_COMMON=m
CONFIG_QCOM_SPMI_IADC=m
CONFIG_QCOM_SPMI_VADC=m
CONFIG_QCOM_SPMI_ADC5=m
CONFIG_RN5T618_ADC=m
CONFIG_RICHTEK_RTQ6056=m
CONFIG_SD_ADC_MODULATOR=m
CONFIG_STMPE_ADC=m
CONFIG_TI_ADC081C=m
CONFIG_TI_ADC0832=m
CONFIG_TI_ADC084S021=m
CONFIG_TI_ADC12138=m
CONFIG_TI_ADC108S102=m
CONFIG_TI_ADC128S052=m
CONFIG_TI_ADC161S626=m
CONFIG_TI_ADS1015=m
CONFIG_TI_ADS7950=m
CONFIG_TI_ADS8344=m
CONFIG_TI_ADS8688=m
CONFIG_TI_ADS124S08=m
CONFIG_TI_ADS131E08=m
CONFIG_TI_AM335X_ADC=m
CONFIG_TI_TLC4541=m
CONFIG_TI_TSC2046=m
CONFIG_TWL4030_MADC=m
CONFIG_TWL6030_GPADC=m
CONFIG_VF610_ADC=m
CONFIG_VIPERBOARD_ADC=m
CONFIG_XILINX_XADC=m
# end of Analog to digital converters

#
# Analog to digital and digital to analog converters
#
CONFIG_AD74413R=m
CONFIG_STX104=m
# end of Analog to digital and digital to analog converters

#
# Analog Front Ends
#
CONFIG_IIO_RESCALE=m
# end of Analog Front Ends

#
# Amplifiers
#
CONFIG_AD8366=m
CONFIG_ADA4250=m
CONFIG_HMC425=m
# end of Amplifiers

#
# Capacitance to digital converters
#
CONFIG_AD7150=m
CONFIG_AD7746=m
# end of Capacitance to digital converters

#
# Chemical Sensors
#
CONFIG_ATLAS_PH_SENSOR=m
CONFIG_ATLAS_EZO_SENSOR=m
CONFIG_BME680=m
CONFIG_BME680_I2C=m
CONFIG_BME680_SPI=m
CONFIG_CCS811=m
CONFIG_IAQCORE=m
CONFIG_PMS7003=m
CONFIG_SCD30_CORE=m
CONFIG_SCD30_I2C=m
CONFIG_SCD30_SERIAL=m
CONFIG_SCD4X=m
CONFIG_SENSIRION_SGP30=m
CONFIG_SENSIRION_SGP40=m
CONFIG_SPS30=m
CONFIG_SPS30_I2C=m
CONFIG_SPS30_SERIAL=m
CONFIG_SENSEAIR_SUNRISE_CO2=m
CONFIG_VZ89X=m
# end of Chemical Sensors

CONFIG_IIO_CROS_EC_SENSORS_CORE=m
CONFIG_IIO_CROS_EC_SENSORS=m
CONFIG_IIO_CROS_EC_SENSORS_LID_ANGLE=m

#
# Hid Sensor IIO Common
#
CONFIG_HID_SENSOR_IIO_COMMON=m
CONFIG_HID_SENSOR_IIO_TRIGGER=m
# end of Hid Sensor IIO Common

CONFIG_IIO_MS_SENSORS_I2C=m

#
# IIO SCMI Sensors
#
# end of IIO SCMI Sensors

#
# SSP Sensor Common
#
CONFIG_IIO_SSP_SENSORS_COMMONS=m
CONFIG_IIO_SSP_SENSORHUB=m
# end of SSP Sensor Common

CONFIG_IIO_ST_SENSORS_I2C=m
CONFIG_IIO_ST_SENSORS_SPI=m
CONFIG_IIO_ST_SENSORS_CORE=m

#
# Digital to analog converters
#
CONFIG_AD3552R=m
CONFIG_AD5064=m
CONFIG_AD5360=m
CONFIG_AD5380=m
CONFIG_AD5421=m
CONFIG_AD5446=m
CONFIG_AD5449=m
CONFIG_AD5592R_BASE=m
CONFIG_AD5592R=m
CONFIG_AD5593R=m
CONFIG_AD5504=m
CONFIG_AD5624R_SPI=m
CONFIG_LTC2688=m
CONFIG_AD5686=m
CONFIG_AD5686_SPI=m
CONFIG_AD5696_I2C=m
CONFIG_AD5755=m
CONFIG_AD5758=m
CONFIG_AD5761=m
CONFIG_AD5764=m
CONFIG_AD5766=m
CONFIG_AD5770R=m
CONFIG_AD5791=m
CONFIG_AD7293=m
CONFIG_AD7303=m
CONFIG_AD8801=m
CONFIG_CIO_DAC=m
CONFIG_DPOT_DAC=m
CONFIG_DS4424=m
CONFIG_LTC1660=m
CONFIG_LTC2632=m
CONFIG_M62332=m
CONFIG_MAX517=m
CONFIG_MAX5821=m
CONFIG_MCP4725=m
CONFIG_MCP4922=m
CONFIG_TI_DAC082S085=m
CONFIG_TI_DAC5571=m
CONFIG_TI_DAC7311=m
CONFIG_TI_DAC7612=m
CONFIG_VF610_DAC=m
# end of Digital to analog converters

#
# IIO dummy driver
#
CONFIG_IIO_DUMMY_EVGEN=m
CONFIG_IIO_SIMPLE_DUMMY=m
CONFIG_IIO_SIMPLE_DUMMY_EVENTS=y
CONFIG_IIO_SIMPLE_DUMMY_BUFFER=y
# end of IIO dummy driver

#
# Filters
#
# end of Filters

#
# Frequency Synthesizers DDS/PLL
#

#
# Clock Generator/Distribution
#
CONFIG_AD9523=m
# end of Clock Generator/Distribution

#
# Phase-Locked Loop (PLL) frequency synthesizers
#
CONFIG_ADF4350=m
CONFIG_ADF4371=m
CONFIG_ADMV1013=m
CONFIG_ADMV4420=m
CONFIG_ADRF6780=m
# end of Phase-Locked Loop (PLL) frequency synthesizers
# end of Frequency Synthesizers DDS/PLL

#
# Digital gyroscope sensors
#
CONFIG_ADIS16080=m
CONFIG_ADIS16130=m
CONFIG_ADIS16136=m
CONFIG_ADIS16260=m
CONFIG_ADXRS290=m
CONFIG_ADXRS450=m
CONFIG_BMG160=m
CONFIG_BMG160_I2C=m
CONFIG_BMG160_SPI=m
CONFIG_FXAS21002C=m
CONFIG_FXAS21002C_I2C=m
CONFIG_FXAS21002C_SPI=m
CONFIG_HID_SENSOR_GYRO_3D=m
CONFIG_MPU3050=m
CONFIG_MPU3050_I2C=m
CONFIG_IIO_ST_GYRO_3AXIS=m
CONFIG_IIO_ST_GYRO_I2C_3AXIS=m
CONFIG_IIO_ST_GYRO_SPI_3AXIS=m
CONFIG_ITG3200=m
# end of Digital gyroscope sensors

#
# Health Sensors
#

#
# Heart Rate Monitors
#
CONFIG_AFE4403=m
CONFIG_AFE4404=m
CONFIG_MAX30100=m
CONFIG_MAX30102=m
# end of Heart Rate Monitors
# end of Health Sensors

#
# Humidity sensors
#
CONFIG_AM2315=m
CONFIG_DHT11=m
CONFIG_HDC100X=m
CONFIG_HDC2010=m
CONFIG_HID_SENSOR_HUMIDITY=m
CONFIG_HTS221=m
CONFIG_HTS221_I2C=m
CONFIG_HTS221_SPI=m
CONFIG_HTU21=m
CONFIG_SI7005=m
CONFIG_SI7020=m
# end of Humidity sensors

#
# Inertial measurement units
#
CONFIG_ADIS16400=m
CONFIG_ADIS16460=m
CONFIG_ADIS16475=m
CONFIG_ADIS16480=m
CONFIG_BMI160=m
CONFIG_BMI160_I2C=m
CONFIG_BMI160_SPI=m
CONFIG_BOSCH_BNO055=m
CONFIG_BOSCH_BNO055_SERIAL=m
CONFIG_BOSCH_BNO055_I2C=m
CONFIG_FXOS8700=m
CONFIG_FXOS8700_I2C=m
CONFIG_FXOS8700_SPI=m
CONFIG_KMX61=m
CONFIG_INV_ICM42600=m
CONFIG_INV_ICM42600_I2C=m
CONFIG_INV_ICM42600_SPI=m
CONFIG_INV_MPU6050_IIO=m
CONFIG_INV_MPU6050_I2C=m
CONFIG_INV_MPU6050_SPI=m
CONFIG_IIO_ST_LSM6DSX=m
CONFIG_IIO_ST_LSM6DSX_I2C=m
CONFIG_IIO_ST_LSM6DSX_SPI=m
CONFIG_IIO_ST_LSM6DSX_I3C=m
CONFIG_IIO_ST_LSM9DS0=m
CONFIG_IIO_ST_LSM9DS0_I2C=m
CONFIG_IIO_ST_LSM9DS0_SPI=m
# end of Inertial measurement units

CONFIG_IIO_ADIS_LIB=m
CONFIG_IIO_ADIS_LIB_BUFFER=y

#
# Light sensors
#
CONFIG_ACPI_ALS=m
CONFIG_ADJD_S311=m
CONFIG_ADUX1020=m
CONFIG_AL3010=m
CONFIG_AL3320A=m
CONFIG_APDS9300=m
CONFIG_APDS9960=m
CONFIG_AS73211=m
CONFIG_BH1750=m
CONFIG_BH1780=m
CONFIG_CM32181=m
CONFIG_CM3232=m
CONFIG_CM3323=m
CONFIG_CM3605=m
CONFIG_CM36651=m
CONFIG_IIO_CROS_EC_LIGHT_PROX=m
CONFIG_GP2AP002=m
CONFIG_GP2AP020A00F=m
CONFIG_IQS621_ALS=m
CONFIG_SENSORS_ISL29018=m
CONFIG_SENSORS_ISL29028=m
CONFIG_ISL29125=m
CONFIG_HID_SENSOR_ALS=m
CONFIG_HID_SENSOR_PROX=m
CONFIG_JSA1212=m
CONFIG_RPR0521=m
CONFIG_SENSORS_LM3533=m
CONFIG_LTR501=m
CONFIG_LTRF216A=m
CONFIG_LV0104CS=m
CONFIG_MAX44000=m
CONFIG_MAX44009=m
CONFIG_NOA1305=m
CONFIG_OPT3001=m
CONFIG_PA12203001=m
CONFIG_SI1133=m
CONFIG_SI1145=m
CONFIG_STK3310=m
CONFIG_ST_UVIS25=m
CONFIG_ST_UVIS25_I2C=m
CONFIG_ST_UVIS25_SPI=m
CONFIG_TCS3414=m
CONFIG_TCS3472=m
CONFIG_SENSORS_TSL2563=m
CONFIG_TSL2583=m
CONFIG_TSL2591=m
CONFIG_TSL2772=m
CONFIG_TSL4531=m
CONFIG_US5182D=m
CONFIG_VCNL4000=m
CONFIG_VCNL4035=m
CONFIG_VEML6030=m
CONFIG_VEML6070=m
CONFIG_VL6180=m
CONFIG_ZOPT2201=m
# end of Light sensors

#
# Magnetometer sensors
#
CONFIG_AK8974=m
CONFIG_AK8975=m
CONFIG_AK09911=m
CONFIG_BMC150_MAGN=m
CONFIG_BMC150_MAGN_I2C=m
CONFIG_BMC150_MAGN_SPI=m
CONFIG_MAG3110=m
CONFIG_HID_SENSOR_MAGNETOMETER_3D=m
CONFIG_MMC35240=m
CONFIG_IIO_ST_MAGN_3AXIS=m
CONFIG_IIO_ST_MAGN_I2C_3AXIS=m
CONFIG_IIO_ST_MAGN_SPI_3AXIS=m
CONFIG_SENSORS_HMC5843=m
CONFIG_SENSORS_HMC5843_I2C=m
CONFIG_SENSORS_HMC5843_SPI=m
CONFIG_SENSORS_RM3100=m
CONFIG_SENSORS_RM3100_I2C=m
CONFIG_SENSORS_RM3100_SPI=m
CONFIG_YAMAHA_YAS530=m
# end of Magnetometer sensors

#
# Multiplexers
#
CONFIG_IIO_MUX=m
# end of Multiplexers

#
# Inclinometer sensors
#
CONFIG_HID_SENSOR_INCLINOMETER_3D=m
CONFIG_HID_SENSOR_DEVICE_ROTATION=m
# end of Inclinometer sensors

#
# Triggers - standalone
#
CONFIG_IIO_HRTIMER_TRIGGER=m
CONFIG_IIO_INTERRUPT_TRIGGER=m
CONFIG_IIO_TIGHTLOOP_TRIGGER=m
CONFIG_IIO_SYSFS_TRIGGER=m
# end of Triggers - standalone

#
# Linear and angular position sensors
#
CONFIG_IQS624_POS=m
CONFIG_HID_SENSOR_CUSTOM_INTEL_HINGE=m
# end of Linear and angular position sensors

#
# Digital potentiometers
#
CONFIG_AD5110=m
CONFIG_AD5272=m
CONFIG_DS1803=m
CONFIG_MAX5432=m
CONFIG_MAX5481=m
CONFIG_MAX5487=m
CONFIG_MCP4018=m
CONFIG_MCP4131=m
CONFIG_MCP4531=m
CONFIG_MCP41010=m
CONFIG_TPL0102=m
# end of Digital potentiometers

#
# Digital potentiostats
#
CONFIG_LMP91000=m
# end of Digital potentiostats

#
# Pressure sensors
#
CONFIG_ABP060MG=m
CONFIG_BMP280=m
CONFIG_BMP280_I2C=m
CONFIG_BMP280_SPI=m
CONFIG_IIO_CROS_EC_BARO=m
CONFIG_DLHL60D=m
CONFIG_DPS310=m
CONFIG_HID_SENSOR_PRESS=m
CONFIG_HP03=m
CONFIG_ICP10100=m
CONFIG_MPL115=m
CONFIG_MPL115_I2C=m
CONFIG_MPL115_SPI=m
CONFIG_MPL3115=m
CONFIG_MS5611=m
CONFIG_MS5611_I2C=m
CONFIG_MS5611_SPI=m
CONFIG_MS5637=m
CONFIG_IIO_ST_PRESS=m
CONFIG_IIO_ST_PRESS_I2C=m
CONFIG_IIO_ST_PRESS_SPI=m
CONFIG_T5403=m
CONFIG_HP206C=m
CONFIG_ZPA2326=m
CONFIG_ZPA2326_I2C=m
CONFIG_ZPA2326_SPI=m
# end of Pressure sensors

#
# Lightning sensors
#
CONFIG_AS3935=m
# end of Lightning sensors

#
# Proximity and distance sensors
#
CONFIG_CROS_EC_MKBP_PROXIMITY=m
CONFIG_ISL29501=m
CONFIG_LIDAR_LITE_V2=m
CONFIG_MB1232=m
CONFIG_PING=m
CONFIG_RFD77402=m
CONFIG_SRF04=m
CONFIG_SX_COMMON=m
CONFIG_SX9310=m
CONFIG_SX9324=m
CONFIG_SX9360=m
CONFIG_SX9500=m
CONFIG_SRF08=m
CONFIG_VCNL3020=m
CONFIG_VL53L0X_I2C=m
# end of Proximity and distance sensors

#
# Resolver to digital converters
#
CONFIG_AD2S90=m
CONFIG_AD2S1200=m
# end of Resolver to digital converters

#
# Temperature sensors
#
CONFIG_IQS620AT_TEMP=m
CONFIG_LTC2983=m
CONFIG_MAXIM_THERMOCOUPLE=m
CONFIG_HID_SENSOR_TEMP=m
CONFIG_MLX90614=m
CONFIG_MLX90632=m
CONFIG_TMP006=m
CONFIG_TMP007=m
CONFIG_TMP117=m
CONFIG_TSYS01=m
CONFIG_TSYS02D=m
CONFIG_MAX31856=m
CONFIG_MAX31865=m
# end of Temperature sensors

CONFIG_NTB=m
CONFIG_NTB_MSI=y
CONFIG_NTB_IDT=m
CONFIG_NTB_EPF=m
CONFIG_NTB_SWITCHTEC=m
CONFIG_NTB_PINGPONG=m
CONFIG_NTB_TOOL=m
CONFIG_NTB_PERF=m
# CONFIG_NTB_MSI_TEST is not set
CONFIG_NTB_TRANSPORT=m
CONFIG_PWM=y
CONFIG_PWM_SYSFS=y
CONFIG_PWM_DEBUG=y
CONFIG_PWM_ATMEL_HLCDC_PWM=m
CONFIG_PWM_ATMEL_TCB=m
CONFIG_PWM_CLK=m
CONFIG_PWM_CROS_EC=m
CONFIG_PWM_DWC=m
CONFIG_PWM_FSL_FTM=m
CONFIG_PWM_INTEL_LGM=m
CONFIG_PWM_IQS620A=m
CONFIG_PWM_LP3943=m
CONFIG_PWM_LPSS=m
CONFIG_PWM_LPSS_PCI=m
CONFIG_PWM_LPSS_PLATFORM=m
CONFIG_PWM_NTXEC=m
CONFIG_PWM_PCA9685=m
CONFIG_PWM_STMPE=y
CONFIG_PWM_TWL=m
CONFIG_PWM_TWL_LED=m
CONFIG_PWM_XILINX=m

#
# IRQ chip support
#
CONFIG_IRQCHIP=y
CONFIG_AL_FIC=y
CONFIG_MADERA_IRQ=m
CONFIG_XILINX_INTC=y
# end of IRQ chip support

CONFIG_IPACK_BUS=m
CONFIG_BOARD_TPCI200=m
CONFIG_SERIAL_IPOCTAL=m
CONFIG_RESET_CONTROLLER=y
CONFIG_RESET_INTEL_GW=y
CONFIG_RESET_SIMPLE=y
CONFIG_RESET_TI_SYSCON=m
CONFIG_RESET_TI_TPS380X=m

#
# PHY Subsystem
#
CONFIG_GENERIC_PHY=y
CONFIG_GENERIC_PHY_MIPI_DPHY=y
CONFIG_USB_LGM_PHY=m
CONFIG_PHY_CAN_TRANSCEIVER=m

#
# PHY drivers for Broadcom platforms
#
CONFIG_BCM_KONA_USB2_PHY=m
# end of PHY drivers for Broadcom platforms

CONFIG_PHY_CADENCE_TORRENT=m
CONFIG_PHY_CADENCE_DPHY=m
CONFIG_PHY_CADENCE_DPHY_RX=m
CONFIG_PHY_CADENCE_SIERRA=m
CONFIG_PHY_CADENCE_SALVO=m
CONFIG_PHY_PXA_28NM_HSIC=m
CONFIG_PHY_PXA_28NM_USB2=m
CONFIG_PHY_LAN966X_SERDES=m
CONFIG_PHY_CPCAP_USB=m
CONFIG_PHY_MAPPHONE_MDM6600=m
CONFIG_PHY_OCELOT_SERDES=m
CONFIG_PHY_QCOM_USB_HS=m
CONFIG_PHY_QCOM_USB_HSIC=m
CONFIG_PHY_TUSB1210=m
CONFIG_PHY_INTEL_LGM_COMBO=y
CONFIG_PHY_INTEL_LGM_EMMC=m
# end of PHY Subsystem

CONFIG_POWERCAP=y
CONFIG_INTEL_RAPL_CORE=m
CONFIG_INTEL_RAPL=m
CONFIG_IDLE_INJECT=y
CONFIG_DTPM=y
CONFIG_DTPM_CPU=y
CONFIG_DTPM_DEVFREQ=y
CONFIG_MCB=m
CONFIG_MCB_PCI=m
CONFIG_MCB_LPC=m

#
# Performance monitor support
#
# end of Performance monitor support

CONFIG_RAS=y
CONFIG_RAS_CEC=y
CONFIG_RAS_CEC_DEBUG=y
CONFIG_USB4=m
CONFIG_USB4_DEBUGFS_WRITE=y
CONFIG_USB4_DEBUGFS_MARGINING=y
# CONFIG_USB4_DMA_TEST is not set

#
# Android
#
CONFIG_ANDROID_BINDER_IPC=y
CONFIG_ANDROID_BINDERFS=y
CONFIG_ANDROID_BINDER_DEVICES="binder,hwbinder,vndbinder"
# CONFIG_ANDROID_BINDER_IPC_SELFTEST is not set
# end of Android

CONFIG_DAX=m
CONFIG_DEV_DAX=m
CONFIG_NVMEM=y
CONFIG_NVMEM_SYSFS=y
CONFIG_NVMEM_RAVE_SP_EEPROM=m
CONFIG_NVMEM_RMEM=m
CONFIG_NVMEM_SPMI_SDAM=m
CONFIG_NVMEM_U_BOOT_ENV=m

#
# HW tracing support
#
CONFIG_STM=m
CONFIG_STM_PROTO_BASIC=m
CONFIG_STM_PROTO_SYS_T=m
CONFIG_STM_DUMMY=m
CONFIG_STM_SOURCE_CONSOLE=m
CONFIG_STM_SOURCE_HEARTBEAT=m
CONFIG_STM_SOURCE_FTRACE=m
CONFIG_INTEL_TH=m
CONFIG_INTEL_TH_PCI=m
CONFIG_INTEL_TH_ACPI=m
CONFIG_INTEL_TH_GTH=m
CONFIG_INTEL_TH_STH=m
CONFIG_INTEL_TH_MSU=m
CONFIG_INTEL_TH_PTI=m
CONFIG_INTEL_TH_DEBUG=y
# end of HW tracing support

CONFIG_FPGA=m
CONFIG_ALTERA_PR_IP_CORE=m
CONFIG_ALTERA_PR_IP_CORE_PLAT=m
CONFIG_FPGA_MGR_ALTERA_PS_SPI=m
CONFIG_FPGA_MGR_ALTERA_CVP=m
CONFIG_FPGA_MGR_XILINX_SPI=m
CONFIG_FPGA_MGR_ICE40_SPI=m
CONFIG_FPGA_MGR_MACHXO2_SPI=m
CONFIG_FPGA_BRIDGE=m
CONFIG_ALTERA_FREEZE_BRIDGE=m
CONFIG_XILINX_PR_DECOUPLER=m
CONFIG_FPGA_REGION=m
CONFIG_OF_FPGA_REGION=m
CONFIG_FPGA_DFL=m
CONFIG_FPGA_DFL_FME=m
CONFIG_FPGA_DFL_FME_MGR=m
CONFIG_FPGA_DFL_FME_BRIDGE=m
CONFIG_FPGA_DFL_FME_REGION=m
CONFIG_FPGA_DFL_AFU=m
CONFIG_FPGA_DFL_NIOS_INTEL_PAC_N3000=m
CONFIG_FPGA_DFL_PCI=m
CONFIG_FPGA_M10_BMC_SEC_UPDATE=m
CONFIG_FPGA_MGR_MICROCHIP_SPI=m
CONFIG_FSI=m
CONFIG_FSI_NEW_DEV_NODE=y
CONFIG_FSI_MASTER_GPIO=m
CONFIG_FSI_MASTER_HUB=m
CONFIG_FSI_MASTER_ASPEED=m
CONFIG_FSI_SCOM=m
CONFIG_FSI_SBEFIFO=m
CONFIG_FSI_OCC=m
CONFIG_MULTIPLEXER=m

#
# Multiplexer drivers
#
CONFIG_MUX_ADG792A=m
CONFIG_MUX_ADGS1408=m
CONFIG_MUX_GPIO=m
CONFIG_MUX_MMIO=m
# end of Multiplexer drivers

CONFIG_PM_OPP=y
CONFIG_SIOX=m
CONFIG_SIOX_BUS_GPIO=m
CONFIG_SLIMBUS=m
CONFIG_SLIM_QCOM_CTRL=m
CONFIG_INTERCONNECT=y
CONFIG_COUNTER=m
CONFIG_104_QUAD_8=m
CONFIG_INTERRUPT_CNT=m
CONFIG_FTM_QUADDEC=m
CONFIG_MICROCHIP_TCB_CAPTURE=m
CONFIG_INTEL_QEP=m
CONFIG_MOST=m
CONFIG_MOST_USB_HDM=m
CONFIG_MOST_CDEV=m
CONFIG_MOST_SND=m
CONFIG_PECI=m
CONFIG_PECI_CPU=m
CONFIG_HTE=y
CONFIG_DPLL=y
# end of Device Drivers

#
# File systems
#
CONFIG_DCACHE_WORD_ACCESS=y
CONFIG_VALIDATE_FS_PARSER=y
CONFIG_FS_IOMAP=y
CONFIG_EXT2_FS=m
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT2_FS_POSIX_ACL=y
CONFIG_EXT2_FS_SECURITY=y
CONFIG_EXT3_FS=m
CONFIG_EXT3_FS_POSIX_ACL=y
CONFIG_EXT3_FS_SECURITY=y
CONFIG_EXT4_FS=m
CONFIG_EXT4_FS_POSIX_ACL=y
CONFIG_EXT4_FS_SECURITY=y
CONFIG_EXT4_DEBUG=y
CONFIG_JBD2=m
CONFIG_JBD2_DEBUG=y
CONFIG_FS_MBCACHE=m
CONFIG_REISERFS_FS=m
CONFIG_REISERFS_CHECK=y
CONFIG_REISERFS_PROC_INFO=y
CONFIG_REISERFS_FS_XATTR=y
CONFIG_REISERFS_FS_POSIX_ACL=y
CONFIG_REISERFS_FS_SECURITY=y
CONFIG_JFS_FS=m
CONFIG_JFS_POSIX_ACL=y
CONFIG_JFS_SECURITY=y
CONFIG_JFS_DEBUG=y
CONFIG_JFS_STATISTICS=y
CONFIG_XFS_FS=m
CONFIG_XFS_SUPPORT_V4=y
CONFIG_XFS_QUOTA=y
CONFIG_XFS_POSIX_ACL=y
CONFIG_XFS_RT=y
CONFIG_XFS_ONLINE_SCRUB=y
CONFIG_XFS_ONLINE_REPAIR=y
CONFIG_XFS_DEBUG=y
CONFIG_XFS_ASSERT_FATAL=y
CONFIG_GFS2_FS=m
CONFIG_GFS2_FS_LOCKING_DLM=y
CONFIG_OCFS2_FS=m
CONFIG_OCFS2_FS_O2CB=m
CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
CONFIG_OCFS2_FS_STATS=y
CONFIG_OCFS2_DEBUG_MASKLOG=y
CONFIG_OCFS2_DEBUG_FS=y
CONFIG_BTRFS_FS=m
CONFIG_BTRFS_FS_POSIX_ACL=y
CONFIG_BTRFS_FS_CHECK_INTEGRITY=y
# CONFIG_BTRFS_FS_RUN_SANITY_TESTS is not set
CONFIG_BTRFS_DEBUG=y
CONFIG_BTRFS_ASSERT=y
CONFIG_BTRFS_FS_REF_VERIFY=y
CONFIG_NILFS2_FS=m
CONFIG_F2FS_FS=m
CONFIG_F2FS_STAT_FS=y
CONFIG_F2FS_FS_XATTR=y
CONFIG_F2FS_FS_POSIX_ACL=y
CONFIG_F2FS_FS_SECURITY=y
CONFIG_F2FS_CHECK_FS=y
CONFIG_F2FS_FAULT_INJECTION=y
CONFIG_F2FS_FS_COMPRESSION=y
CONFIG_F2FS_FS_LZO=y
CONFIG_F2FS_FS_LZORLE=y
CONFIG_F2FS_FS_LZ4=y
CONFIG_F2FS_FS_LZ4HC=y
CONFIG_F2FS_FS_ZSTD=y
CONFIG_F2FS_IOSTAT=y
CONFIG_F2FS_UNFAIR_RWSEM=y
CONFIG_ZONEFS_FS=m
CONFIG_FS_POSIX_ACL=y
CONFIG_EXPORTFS=y
CONFIG_EXPORTFS_BLOCK_OPS=y
CONFIG_FILE_LOCKING=y
CONFIG_FS_ENCRYPTION=y
CONFIG_FS_ENCRYPTION_ALGS=m
CONFIG_FS_ENCRYPTION_INLINE_CRYPT=y
CONFIG_FS_VERITY=y
CONFIG_FS_VERITY_DEBUG=y
CONFIG_FS_VERITY_BUILTIN_SIGNATURES=y
CONFIG_FSNOTIFY=y
CONFIG_DNOTIFY=y
CONFIG_INOTIFY_USER=y
CONFIG_FANOTIFY=y
CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y
CONFIG_QUOTA=y
CONFIG_QUOTA_NETLINK_INTERFACE=y
CONFIG_PRINT_QUOTA_WARNING=y
CONFIG_QUOTA_DEBUG=y
CONFIG_QUOTA_TREE=m
CONFIG_QFMT_V1=m
CONFIG_QFMT_V2=m
CONFIG_QUOTACTL=y
CONFIG_AUTOFS4_FS=m
CONFIG_AUTOFS_FS=m
CONFIG_FUSE_FS=m
CONFIG_CUSE=m
CONFIG_VIRTIO_FS=m
CONFIG_OVERLAY_FS=m
CONFIG_OVERLAY_FS_REDIRECT_DIR=y
CONFIG_OVERLAY_FS_REDIRECT_ALWAYS_FOLLOW=y
CONFIG_OVERLAY_FS_INDEX=y
CONFIG_OVERLAY_FS_METACOPY=y

#
# Caches
#
CONFIG_NETFS_SUPPORT=m
CONFIG_NETFS_STATS=y
CONFIG_FSCACHE=m
CONFIG_FSCACHE_STATS=y
CONFIG_FSCACHE_DEBUG=y
CONFIG_CACHEFILES=m
CONFIG_CACHEFILES_DEBUG=y
CONFIG_CACHEFILES_ERROR_INJECTION=y
CONFIG_CACHEFILES_ONDEMAND=y
# end of Caches

#
# CD-ROM/DVD Filesystems
#
CONFIG_ISO9660_FS=m
CONFIG_JOLIET=y
CONFIG_ZISOFS=y
CONFIG_UDF_FS=m
# end of CD-ROM/DVD Filesystems

#
# DOS/FAT/EXFAT/NT Filesystems
#
CONFIG_FAT_FS=m
CONFIG_MSDOS_FS=m
CONFIG_VFAT_FS=m
CONFIG_FAT_DEFAULT_CODEPAGE=437
CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
CONFIG_FAT_DEFAULT_UTF8=y
CONFIG_EXFAT_FS=m
CONFIG_EXFAT_DEFAULT_IOCHARSET="utf8"
CONFIG_NTFS_FS=m
CONFIG_NTFS_DEBUG=y
CONFIG_NTFS_RW=y
CONFIG_NTFS3_FS=m
CONFIG_NTFS3_LZX_XPRESS=y
CONFIG_NTFS3_FS_POSIX_ACL=y
# end of DOS/FAT/EXFAT/NT Filesystems

#
# Pseudo filesystems
#
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_PROC_VMCORE=y
CONFIG_PROC_VMCORE_DEVICE_DUMP=y
CONFIG_PROC_SYSCTL=y
CONFIG_PROC_PAGE_MONITOR=y
CONFIG_PROC_CHILDREN=y
CONFIG_PROC_PID_ARCH_STATUS=y
CONFIG_PROC_CPU_RESCTRL=y
CONFIG_KERNFS=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
CONFIG_TMPFS_POSIX_ACL=y
CONFIG_TMPFS_XATTR=y
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
CONFIG_MEMFD_CREATE=y
CONFIG_CONFIGFS_FS=y
CONFIG_EFIVAR_FS=m
# end of Pseudo filesystems

CONFIG_MISC_FILESYSTEMS=y
CONFIG_ORANGEFS_FS=m
CONFIG_ADFS_FS=m
CONFIG_ADFS_FS_RW=y
CONFIG_AFFS_FS=m
CONFIG_ECRYPT_FS=m
CONFIG_ECRYPT_FS_MESSAGING=y
CONFIG_HFS_FS=m
CONFIG_HFSPLUS_FS=m
CONFIG_BEFS_FS=m
CONFIG_BEFS_DEBUG=y
CONFIG_BFS_FS=m
CONFIG_EFS_FS=m
CONFIG_JFFS2_FS=m
CONFIG_JFFS2_FS_DEBUG=0
CONFIG_JFFS2_FS_WRITEBUFFER=y
CONFIG_JFFS2_FS_WBUF_VERIFY=y
CONFIG_JFFS2_SUMMARY=y
CONFIG_JFFS2_FS_XATTR=y
CONFIG_JFFS2_FS_POSIX_ACL=y
CONFIG_JFFS2_FS_SECURITY=y
CONFIG_JFFS2_COMPRESSION_OPTIONS=y
CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_LZO=y
CONFIG_JFFS2_RTIME=y
CONFIG_JFFS2_RUBIN=y
# CONFIG_JFFS2_CMODE_NONE is not set
CONFIG_JFFS2_CMODE_PRIORITY=y
# CONFIG_JFFS2_CMODE_SIZE is not set
# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
CONFIG_UBIFS_FS=m
CONFIG_UBIFS_FS_ADVANCED_COMPR=y
CONFIG_UBIFS_FS_LZO=y
CONFIG_UBIFS_FS_ZLIB=y
CONFIG_UBIFS_FS_ZSTD=y
CONFIG_UBIFS_ATIME_SUPPORT=y
CONFIG_UBIFS_FS_XATTR=y
CONFIG_UBIFS_FS_SECURITY=y
CONFIG_UBIFS_FS_AUTHENTICATION=y
CONFIG_CRAMFS=m
CONFIG_CRAMFS_BLOCKDEV=y
CONFIG_CRAMFS_MTD=y
CONFIG_SQUASHFS=m
CONFIG_SQUASHFS_FILE_CACHE=y
# CONFIG_SQUASHFS_FILE_DIRECT is not set
CONFIG_SQUASHFS_DECOMP_SINGLE=y
# CONFIG_SQUASHFS_DECOMP_MULTI is not set
# CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU is not set
CONFIG_SQUASHFS_XATTR=y
CONFIG_SQUASHFS_ZLIB=y
CONFIG_SQUASHFS_LZ4=y
CONFIG_SQUASHFS_LZO=y
CONFIG_SQUASHFS_XZ=y
CONFIG_SQUASHFS_ZSTD=y
CONFIG_SQUASHFS_4K_DEVBLK_SIZE=y
CONFIG_SQUASHFS_EMBEDDED=y
CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
CONFIG_VXFS_FS=m
CONFIG_MINIX_FS=m
CONFIG_OMFS_FS=m
CONFIG_HPFS_FS=m
CONFIG_QNX4FS_FS=m
CONFIG_QNX6FS_FS=m
CONFIG_QNX6FS_DEBUG=y
CONFIG_ROMFS_FS=m
CONFIG_ROMFS_BACKED_BY_BLOCK=y
# CONFIG_ROMFS_BACKED_BY_MTD is not set
# CONFIG_ROMFS_BACKED_BY_BOTH is not set
CONFIG_ROMFS_ON_BLOCK=y
CONFIG_PSTORE=y
CONFIG_PSTORE_DEFAULT_KMSG_BYTES=10240
CONFIG_PSTORE_DEFLATE_COMPRESS=m
CONFIG_PSTORE_LZO_COMPRESS=m
CONFIG_PSTORE_LZ4_COMPRESS=m
CONFIG_PSTORE_LZ4HC_COMPRESS=m
CONFIG_PSTORE_842_COMPRESS=y
CONFIG_PSTORE_ZSTD_COMPRESS=y
CONFIG_PSTORE_COMPRESS=y
CONFIG_PSTORE_DEFLATE_COMPRESS_DEFAULT=y
# CONFIG_PSTORE_LZO_COMPRESS_DEFAULT is not set
# CONFIG_PSTORE_LZ4_COMPRESS_DEFAULT is not set
# CONFIG_PSTORE_LZ4HC_COMPRESS_DEFAULT is not set
# CONFIG_PSTORE_842_COMPRESS_DEFAULT is not set
# CONFIG_PSTORE_ZSTD_COMPRESS_DEFAULT is not set
CONFIG_PSTORE_COMPRESS_DEFAULT="deflate"
CONFIG_PSTORE_CONSOLE=y
CONFIG_PSTORE_PMSG=y
CONFIG_PSTORE_FTRACE=y
CONFIG_PSTORE_RAM=m
CONFIG_PSTORE_ZONE=m
CONFIG_PSTORE_BLK=m
CONFIG_PSTORE_BLK_BLKDEV=""
CONFIG_PSTORE_BLK_KMSG_SIZE=64
CONFIG_PSTORE_BLK_MAX_REASON=2
CONFIG_PSTORE_BLK_PMSG_SIZE=64
CONFIG_PSTORE_BLK_CONSOLE_SIZE=64
CONFIG_PSTORE_BLK_FTRACE_SIZE=64
CONFIG_SYSV_FS=m
CONFIG_UFS_FS=m
CONFIG_UFS_FS_WRITE=y
CONFIG_UFS_DEBUG=y
CONFIG_EROFS_FS=m
CONFIG_EROFS_FS_DEBUG=y
CONFIG_EROFS_FS_XATTR=y
CONFIG_EROFS_FS_POSIX_ACL=y
CONFIG_EROFS_FS_SECURITY=y
CONFIG_EROFS_FS_ZIP=y
CONFIG_EROFS_FS_ZIP_LZMA=y
CONFIG_EROFS_FS_ONDEMAND=y
CONFIG_VBOXSF_FS=m
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V2=m
CONFIG_NFS_V3=y
CONFIG_NFS_V3_ACL=y
CONFIG_NFS_V4=m
CONFIG_NFS_SWAP=y
CONFIG_NFS_V4_1=y
CONFIG_NFS_V4_2=y
CONFIG_PNFS_FILE_LAYOUT=m
CONFIG_PNFS_BLOCK=m
CONFIG_PNFS_FLEXFILE_LAYOUT=m
CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN="kernel.org"
CONFIG_NFS_V4_1_MIGRATION=y
CONFIG_NFS_V4_SECURITY_LABEL=y
# CONFIG_ROOT_NFS is not set
CONFIG_NFS_USE_LEGACY_DNS=y
CONFIG_NFS_DEBUG=y
CONFIG_NFS_DISABLE_UDP_SUPPORT=y
CONFIG_NFS_V4_2_READ_PLUS=y
CONFIG_NFSD=m
CONFIG_NFSD_V2_ACL=y
CONFIG_NFSD_V3_ACL=y
CONFIG_NFSD_V4=y
CONFIG_NFSD_PNFS=y
CONFIG_NFSD_BLOCKLAYOUT=y
CONFIG_NFSD_SCSILAYOUT=y
CONFIG_NFSD_FLEXFILELAYOUT=y
CONFIG_NFSD_V4_2_INTER_SSC=y
CONFIG_NFSD_V4_SECURITY_LABEL=y
CONFIG_GRACE_PERIOD=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
CONFIG_NFS_ACL_SUPPORT=y
CONFIG_NFS_COMMON=y
CONFIG_NFS_V4_2_SSC_HELPER=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=m
CONFIG_SUNRPC_BACKCHANNEL=y
CONFIG_SUNRPC_SWAP=y
CONFIG_RPCSEC_GSS_KRB5=m
CONFIG_SUNRPC_DISABLE_INSECURE_ENCTYPES=y
CONFIG_SUNRPC_DEBUG=y
CONFIG_SUNRPC_XPRT_RDMA=m
CONFIG_CEPH_FS=m
CONFIG_CEPH_FSCACHE=y
CONFIG_CEPH_FS_POSIX_ACL=y
CONFIG_CEPH_FS_SECURITY_LABEL=y
CONFIG_CIFS=m
CONFIG_CIFS_STATS2=y
CONFIG_CIFS_ALLOW_INSECURE_LEGACY=y
CONFIG_CIFS_UPCALL=y
CONFIG_CIFS_XATTR=y
CONFIG_CIFS_POSIX=y
CONFIG_CIFS_DEBUG=y
CONFIG_CIFS_DEBUG2=y
CONFIG_CIFS_DEBUG_DUMP_KEYS=y
CONFIG_CIFS_DFS_UPCALL=y
CONFIG_CIFS_SWN_UPCALL=y
CONFIG_CIFS_SMB_DIRECT=y
CONFIG_CIFS_FSCACHE=y
CONFIG_SMB_SERVER=m
CONFIG_SMB_SERVER_SMBDIRECT=y
CONFIG_SMB_SERVER_CHECK_CAP_NET_ADMIN=y
CONFIG_SMB_SERVER_KERBEROS5=y
CONFIG_SMBFS_COMMON=m
CONFIG_CODA_FS=m
CONFIG_AFS_FS=m
CONFIG_AFS_DEBUG=y
CONFIG_AFS_FSCACHE=y
CONFIG_AFS_DEBUG_CURSOR=y
CONFIG_9P_FS=m
CONFIG_9P_FSCACHE=y
CONFIG_9P_FS_POSIX_ACL=y
CONFIG_9P_FS_SECURITY=y
CONFIG_NLS=y
CONFIG_NLS_DEFAULT="iso8859-1"
CONFIG_NLS_CODEPAGE_437=m
CONFIG_NLS_CODEPAGE_737=m
CONFIG_NLS_CODEPAGE_775=m
CONFIG_NLS_CODEPAGE_850=m
CONFIG_NLS_CODEPAGE_852=m
CONFIG_NLS_CODEPAGE_855=m
CONFIG_NLS_CODEPAGE_857=m
CONFIG_NLS_CODEPAGE_860=m
CONFIG_NLS_CODEPAGE_861=m
CONFIG_NLS_CODEPAGE_862=m
CONFIG_NLS_CODEPAGE_863=m
CONFIG_NLS_CODEPAGE_864=m
CONFIG_NLS_CODEPAGE_865=m
CONFIG_NLS_CODEPAGE_866=m
CONFIG_NLS_CODEPAGE_869=m
CONFIG_NLS_CODEPAGE_936=m
CONFIG_NLS_CODEPAGE_950=m
CONFIG_NLS_CODEPAGE_932=m
CONFIG_NLS_CODEPAGE_949=m
CONFIG_NLS_CODEPAGE_874=m
CONFIG_NLS_ISO8859_8=m
CONFIG_NLS_CODEPAGE_1250=m
CONFIG_NLS_CODEPAGE_1251=m
CONFIG_NLS_ASCII=m
CONFIG_NLS_ISO8859_1=m
CONFIG_NLS_ISO8859_2=m
CONFIG_NLS_ISO8859_3=m
CONFIG_NLS_ISO8859_4=m
CONFIG_NLS_ISO8859_5=m
CONFIG_NLS_ISO8859_6=m
CONFIG_NLS_ISO8859_7=m
CONFIG_NLS_ISO8859_9=m
CONFIG_NLS_ISO8859_13=m
CONFIG_NLS_ISO8859_14=m
CONFIG_NLS_ISO8859_15=m
CONFIG_NLS_KOI8_R=m
CONFIG_NLS_KOI8_U=m
CONFIG_NLS_MAC_ROMAN=m
CONFIG_NLS_MAC_CELTIC=m
CONFIG_NLS_MAC_CENTEURO=m
CONFIG_NLS_MAC_CROATIAN=m
CONFIG_NLS_MAC_CYRILLIC=m
CONFIG_NLS_MAC_GAELIC=m
CONFIG_NLS_MAC_GREEK=m
CONFIG_NLS_MAC_ICELAND=m
CONFIG_NLS_MAC_INUIT=m
CONFIG_NLS_MAC_ROMANIAN=m
CONFIG_NLS_MAC_TURKISH=m
CONFIG_NLS_UTF8=m
CONFIG_DLM=m
CONFIG_DLM_DEPRECATED_API=y
CONFIG_DLM_DEBUG=y
CONFIG_UNICODE=m
# CONFIG_UNICODE_NORMALIZATION_SELFTEST is not set
CONFIG_IO_WQ=y
# end of File systems

#
# Security options
#
CONFIG_KEYS=y
CONFIG_KEYS_REQUEST_CACHE=y
CONFIG_PERSISTENT_KEYRINGS=y
CONFIG_TRUSTED_KEYS=m
CONFIG_TRUSTED_KEYS_TPM=y
CONFIG_ENCRYPTED_KEYS=y
CONFIG_USER_DECRYPTED_DATA=y
CONFIG_KEY_DH_OPERATIONS=y
CONFIG_KEY_NOTIFICATIONS=y
CONFIG_SECURITY_DMESG_RESTRICT=y
CONFIG_SECURITY=y
CONFIG_SECURITY_WRITABLE_HOOKS=y
CONFIG_SECURITYFS=y
CONFIG_SECURITY_NETWORK=y
CONFIG_SECURITY_INFINIBAND=y
CONFIG_SECURITY_NETWORK_XFRM=y
CONFIG_SECURITY_PATH=y
CONFIG_INTEL_TXT=y
CONFIG_LSM_MMAP_MIN_ADDR=65536
CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y
CONFIG_HARDENED_USERCOPY=y
CONFIG_STATIC_USERMODEHELPER=y
CONFIG_STATIC_USERMODEHELPER_PATH="/sbin/usermode-helper"
CONFIG_SECURITY_SELINUX=y
CONFIG_SECURITY_SELINUX_BOOTPARAM=y
CONFIG_SECURITY_SELINUX_DISABLE=y
CONFIG_SECURITY_SELINUX_DEVELOP=y
CONFIG_SECURITY_SELINUX_AVC_STATS=y
CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=0
CONFIG_SECURITY_SELINUX_SIDTAB_HASH_BITS=9
CONFIG_SECURITY_SELINUX_SID2STR_CACHE_SIZE=256
CONFIG_SECURITY_SMACK=y
CONFIG_SECURITY_SMACK_BRINGUP=y
CONFIG_SECURITY_SMACK_NETFILTER=y
CONFIG_SECURITY_SMACK_APPEND_SIGNALS=y
# CONFIG_SECURITY_TOMOYO is not set
CONFIG_SECURITY_APPARMOR=y
CONFIG_SECURITY_APPARMOR_DEBUG=y
CONFIG_SECURITY_APPARMOR_DEBUG_ASSERTS=y
CONFIG_SECURITY_APPARMOR_DEBUG_MESSAGES=y
CONFIG_SECURITY_APPARMOR_INTROSPECT_POLICY=y
CONFIG_SECURITY_APPARMOR_HASH=y
CONFIG_SECURITY_APPARMOR_HASH_DEFAULT=y
CONFIG_SECURITY_APPARMOR_EXPORT_BINARY=y
CONFIG_SECURITY_APPARMOR_PARANOID_LOAD=y
CONFIG_SECURITY_LOADPIN=y
CONFIG_SECURITY_LOADPIN_ENFORCE=y
CONFIG_SECURITY_YAMA=y
CONFIG_SECURITY_SAFESETID=y
CONFIG_SECURITY_LOCKDOWN_LSM=y
CONFIG_SECURITY_LOCKDOWN_LSM_EARLY=y
CONFIG_LOCK_DOWN_KERNEL_FORCE_NONE=y
# CONFIG_LOCK_DOWN_KERNEL_FORCE_INTEGRITY is not set
# CONFIG_LOCK_DOWN_KERNEL_FORCE_CONFIDENTIALITY is not set
CONFIG_SECURITY_LANDLOCK=y
CONFIG_INTEGRITY=y
CONFIG_INTEGRITY_SIGNATURE=y
CONFIG_INTEGRITY_ASYMMETRIC_KEYS=y
CONFIG_INTEGRITY_TRUSTED_KEYRING=y
CONFIG_INTEGRITY_PLATFORM_KEYRING=y
CONFIG_LOAD_UEFI_KEYS=y
CONFIG_INTEGRITY_AUDIT=y
CONFIG_IMA=y
CONFIG_IMA_MEASURE_PCR_IDX=10
CONFIG_IMA_LSM_RULES=y
CONFIG_IMA_NG_TEMPLATE=y
# CONFIG_IMA_SIG_TEMPLATE is not set
CONFIG_IMA_DEFAULT_TEMPLATE="ima-ng"
CONFIG_IMA_DEFAULT_HASH_SHA1=y
# CONFIG_IMA_DEFAULT_HASH_SHA256 is not set
# CONFIG_IMA_DEFAULT_HASH_SHA512 is not set
CONFIG_IMA_DEFAULT_HASH="sha1"
CONFIG_IMA_WRITE_POLICY=y
CONFIG_IMA_READ_POLICY=y
CONFIG_IMA_APPRAISE=y
CONFIG_IMA_ARCH_POLICY=y
CONFIG_IMA_APPRAISE_BUILD_POLICY=y
CONFIG_IMA_APPRAISE_REQUIRE_FIRMWARE_SIGS=y
CONFIG_IMA_APPRAISE_REQUIRE_KEXEC_SIGS=y
# CONFIG_IMA_APPRAISE_REQUIRE_MODULE_SIGS is not set
CONFIG_IMA_APPRAISE_REQUIRE_POLICY_SIGS=y
CONFIG_IMA_APPRAISE_BOOTPARAM=y
CONFIG_IMA_APPRAISE_MODSIG=y
CONFIG_IMA_TRUSTED_KEYRING=y
CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY=y
CONFIG_IMA_BLACKLIST_KEYRING=y
CONFIG_IMA_LOAD_X509=y
CONFIG_IMA_X509_PATH="/etc/keys/x509_ima.der"
CONFIG_IMA_APPRAISE_SIGNED_INIT=y
CONFIG_IMA_MEASURE_ASYMMETRIC_KEYS=y
CONFIG_IMA_QUEUE_EARLY_BOOT_KEYS=y
CONFIG_IMA_SECURE_AND_OR_TRUSTED_BOOT=y
CONFIG_IMA_DISABLE_HTABLE=y
CONFIG_EVM=y
CONFIG_EVM_ATTR_FSUUID=y
CONFIG_EVM_EXTRA_SMACK_XATTRS=y
CONFIG_EVM_ADD_XATTRS=y
CONFIG_EVM_LOAD_X509=y
CONFIG_EVM_X509_PATH="/etc/keys/x509_evm.der"
CONFIG_DEFAULT_SECURITY_SELINUX=y
# CONFIG_DEFAULT_SECURITY_SMACK is not set
# CONFIG_DEFAULT_SECURITY_APPARMOR is not set
# CONFIG_DEFAULT_SECURITY_DAC is not set
CONFIG_LSM="landlock,lockdown,yama,loadpin,safesetid,integrity,selinux,smack,tomoyo,apparmor,bpf"

#
# Kernel hardening options
#

#
# Memory initialization
#
CONFIG_CC_HAS_AUTO_VAR_INIT_PATTERN=y
CONFIG_CC_HAS_AUTO_VAR_INIT_ZERO_ENABLER=y
CONFIG_CC_HAS_AUTO_VAR_INIT_ZERO=y
# CONFIG_INIT_STACK_NONE is not set
CONFIG_INIT_STACK_ALL_PATTERN=y
# CONFIG_INIT_STACK_ALL_ZERO is not set
CONFIG_INIT_ON_ALLOC_DEFAULT_ON=y
CONFIG_INIT_ON_FREE_DEFAULT_ON=y
# end of Memory initialization

CONFIG_RANDSTRUCT_NONE=y
# end of Kernel hardening options
# end of Security options

CONFIG_XOR_BLOCKS=m
CONFIG_ASYNC_CORE=m
CONFIG_ASYNC_MEMCPY=m
CONFIG_ASYNC_XOR=m
CONFIG_ASYNC_PQ=m
CONFIG_ASYNC_RAID6_RECOV=m
CONFIG_CRYPTO=y

#
# Crypto core or helper
#
CONFIG_CRYPTO_ALGAPI=y
CONFIG_CRYPTO_ALGAPI2=y
CONFIG_CRYPTO_AEAD=m
CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_SKCIPHER=y
CONFIG_CRYPTO_SKCIPHER2=y
CONFIG_CRYPTO_HASH=y
CONFIG_CRYPTO_HASH2=y
CONFIG_CRYPTO_RNG=y
CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_RNG_DEFAULT=y
CONFIG_CRYPTO_AKCIPHER2=y
CONFIG_CRYPTO_AKCIPHER=y
CONFIG_CRYPTO_KPP2=y
CONFIG_CRYPTO_KPP=y
CONFIG_CRYPTO_ACOMP2=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_MANAGER2=y
CONFIG_CRYPTO_USER=m
CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
CONFIG_CRYPTO_GF128MUL=m
CONFIG_CRYPTO_NULL=m
CONFIG_CRYPTO_NULL2=y
CONFIG_CRYPTO_PCRYPT=m
CONFIG_CRYPTO_CRYPTD=m
CONFIG_CRYPTO_AUTHENC=m
# CONFIG_CRYPTO_TEST is not set
CONFIG_CRYPTO_SIMD=m
CONFIG_CRYPTO_ENGINE=m

#
# Public-key cryptography
#
CONFIG_CRYPTO_RSA=y
CONFIG_CRYPTO_DH=y
CONFIG_CRYPTO_DH_RFC7919_GROUPS=y
CONFIG_CRYPTO_ECC=m
CONFIG_CRYPTO_ECDH=m
CONFIG_CRYPTO_ECDSA=m
CONFIG_CRYPTO_ECRDSA=m
CONFIG_CRYPTO_SM2=m
CONFIG_CRYPTO_CURVE25519=m

#
# Authenticated Encryption with Associated Data
#
CONFIG_CRYPTO_CCM=m
CONFIG_CRYPTO_GCM=m
CONFIG_CRYPTO_CHACHA20POLY1305=m
CONFIG_CRYPTO_AEGIS128=m
CONFIG_CRYPTO_SEQIV=m
CONFIG_CRYPTO_ECHAINIV=m

#
# Block modes
#
CONFIG_CRYPTO_CBC=y
CONFIG_CRYPTO_CFB=m
CONFIG_CRYPTO_CTR=y
CONFIG_CRYPTO_CTS=m
CONFIG_CRYPTO_ECB=m
CONFIG_CRYPTO_LRW=m
CONFIG_CRYPTO_OFB=m
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_XCTR=m
CONFIG_CRYPTO_XTS=m
CONFIG_CRYPTO_KEYWRAP=m
CONFIG_CRYPTO_NHPOLY1305=m
CONFIG_CRYPTO_ADIANTUM=m
CONFIG_CRYPTO_HCTR2=m
CONFIG_CRYPTO_ESSIV=m

#
# Hash modes
#
CONFIG_CRYPTO_CMAC=m
CONFIG_CRYPTO_HMAC=y
CONFIG_CRYPTO_XCBC=m
CONFIG_CRYPTO_VMAC=m

#
# Digest
#
CONFIG_CRYPTO_CRC32C=m
CONFIG_CRYPTO_CRC32C_INTEL=m
CONFIG_CRYPTO_CRC32=m
CONFIG_CRYPTO_CRC32_PCLMUL=m
CONFIG_CRYPTO_XXHASH=m
CONFIG_CRYPTO_BLAKE2B=m
CONFIG_CRYPTO_CRCT10DIF=m
CONFIG_CRYPTO_CRC64_ROCKSOFT=m
CONFIG_CRYPTO_GHASH=m
CONFIG_CRYPTO_POLYVAL=m
CONFIG_CRYPTO_POLY1305=m
CONFIG_CRYPTO_MD4=m
CONFIG_CRYPTO_MD5=y
CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_RMD160=m
CONFIG_CRYPTO_SHA1=y
CONFIG_CRYPTO_SHA256=y
CONFIG_CRYPTO_SHA512=y
CONFIG_CRYPTO_SHA3=m
CONFIG_CRYPTO_SM3=m
CONFIG_CRYPTO_SM3_GENERIC=m
CONFIG_CRYPTO_STREEBOG=m
CONFIG_CRYPTO_WP512=m

#
# Ciphers
#
CONFIG_CRYPTO_AES=y
CONFIG_CRYPTO_AES_TI=m
CONFIG_CRYPTO_AES_NI_INTEL=m
CONFIG_CRYPTO_ANUBIS=m
CONFIG_CRYPTO_ARC4=m
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_BLOWFISH_COMMON=m
CONFIG_CRYPTO_CAMELLIA=m
CONFIG_CRYPTO_CAST_COMMON=m
CONFIG_CRYPTO_CAST5=m
CONFIG_CRYPTO_CAST6=m
CONFIG_CRYPTO_DES=m
CONFIG_CRYPTO_FCRYPT=m
CONFIG_CRYPTO_KHAZAD=m
CONFIG_CRYPTO_CHACHA20=m
CONFIG_CRYPTO_SEED=m
CONFIG_CRYPTO_ARIA=m
CONFIG_CRYPTO_SERPENT=m
CONFIG_CRYPTO_SERPENT_SSE2_586=m
CONFIG_CRYPTO_SM4=m
CONFIG_CRYPTO_SM4_GENERIC=m
CONFIG_CRYPTO_TEA=m
CONFIG_CRYPTO_TWOFISH=m
CONFIG_CRYPTO_TWOFISH_COMMON=m
CONFIG_CRYPTO_TWOFISH_586=m

#
# Compression
#
CONFIG_CRYPTO_DEFLATE=m
CONFIG_CRYPTO_LZO=y
CONFIG_CRYPTO_842=y
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_LZ4HC=m
CONFIG_CRYPTO_ZSTD=y

#
# Random Number Generation
#
CONFIG_CRYPTO_ANSI_CPRNG=m
CONFIG_CRYPTO_DRBG_MENU=y
CONFIG_CRYPTO_DRBG_HMAC=y
CONFIG_CRYPTO_DRBG_HASH=y
CONFIG_CRYPTO_DRBG_CTR=y
CONFIG_CRYPTO_DRBG=y
CONFIG_CRYPTO_JITTERENTROPY=y
CONFIG_CRYPTO_KDF800108_CTR=y
CONFIG_CRYPTO_USER_API=m
CONFIG_CRYPTO_USER_API_HASH=m
CONFIG_CRYPTO_USER_API_SKCIPHER=m
CONFIG_CRYPTO_USER_API_RNG=m
CONFIG_CRYPTO_USER_API_RNG_CAVP=y
CONFIG_CRYPTO_USER_API_AEAD=m
CONFIG_CRYPTO_USER_API_ENABLE_OBSOLETE=y
CONFIG_CRYPTO_STATS=y
CONFIG_CRYPTO_HASH_INFO=y
CONFIG_CRYPTO_HW=y
CONFIG_CRYPTO_DEV_PADLOCK=m
CONFIG_CRYPTO_DEV_PADLOCK_AES=m
CONFIG_CRYPTO_DEV_PADLOCK_SHA=m
CONFIG_CRYPTO_DEV_GEODE=m
CONFIG_CRYPTO_DEV_HIFN_795X=m
CONFIG_CRYPTO_DEV_HIFN_795X_RNG=y
CONFIG_CRYPTO_DEV_ATMEL_I2C=m
CONFIG_CRYPTO_DEV_ATMEL_ECC=m
CONFIG_CRYPTO_DEV_ATMEL_SHA204A=m
CONFIG_CRYPTO_DEV_CCP=y
CONFIG_CRYPTO_DEV_QAT=m
CONFIG_CRYPTO_DEV_QAT_DH895xCC=m
CONFIG_CRYPTO_DEV_QAT_C3XXX=m
CONFIG_CRYPTO_DEV_QAT_C62X=m
CONFIG_CRYPTO_DEV_QAT_4XXX=m
CONFIG_CRYPTO_DEV_QAT_DH895xCCVF=m
CONFIG_CRYPTO_DEV_QAT_C3XXXVF=m
CONFIG_CRYPTO_DEV_QAT_C62XVF=m
CONFIG_CRYPTO_DEV_CHELSIO=m
CONFIG_CRYPTO_DEV_VIRTIO=m
CONFIG_CRYPTO_DEV_SAFEXCEL=m
CONFIG_CRYPTO_DEV_CCREE=m
CONFIG_CRYPTO_DEV_AMLOGIC_GXL=m
CONFIG_CRYPTO_DEV_AMLOGIC_GXL_DEBUG=y
CONFIG_ASYMMETRIC_KEY_TYPE=y
CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y
CONFIG_X509_CERTIFICATE_PARSER=y
CONFIG_PKCS8_PRIVATE_KEY_PARSER=m
CONFIG_PKCS7_MESSAGE_PARSER=y
# CONFIG_PKCS7_TEST_KEY is not set
CONFIG_SIGNED_PE_FILE_VERIFICATION=y
CONFIG_FIPS_SIGNATURE_SELFTEST=y

#
# Certificates for signature checking
#
CONFIG_MODULE_SIG_KEY="certs/signing_key.pem"
CONFIG_MODULE_SIG_KEY_TYPE_RSA=y
# CONFIG_MODULE_SIG_KEY_TYPE_ECDSA is not set
CONFIG_SYSTEM_TRUSTED_KEYRING=y
CONFIG_SYSTEM_TRUSTED_KEYS=""
CONFIG_SYSTEM_EXTRA_CERTIFICATE=y
CONFIG_SYSTEM_EXTRA_CERTIFICATE_SIZE=4096
CONFIG_SECONDARY_TRUSTED_KEYRING=y
CONFIG_SYSTEM_BLACKLIST_KEYRING=y
CONFIG_SYSTEM_BLACKLIST_HASH_LIST=""
CONFIG_SYSTEM_REVOCATION_LIST=y
CONFIG_SYSTEM_REVOCATION_KEYS=""
CONFIG_SYSTEM_BLACKLIST_AUTH_UPDATE=y
# end of Certificates for signature checking

CONFIG_BINARY_PRINTF=y

#
# Library routines
#
CONFIG_RAID6_PQ=m
CONFIG_RAID6_PQ_BENCHMARK=y
CONFIG_LINEAR_RANGES=y
CONFIG_PACKING=y
CONFIG_BITREVERSE=y
CONFIG_GENERIC_STRNCPY_FROM_USER=y
CONFIG_GENERIC_STRNLEN_USER=y
CONFIG_GENERIC_NET_UTILS=y
CONFIG_CORDIC=m
CONFIG_PRIME_NUMBERS=m
CONFIG_RATIONAL=y
CONFIG_GENERIC_PCI_IOMAP=y
CONFIG_GENERIC_IOMAP=y
CONFIG_ARCH_HAS_FAST_MULTIPLIER=y
CONFIG_ARCH_USE_SYM_ANNOTATIONS=y

#
# Crypto library routines
#
CONFIG_CRYPTO_LIB_AES=y
CONFIG_CRYPTO_LIB_ARC4=m
CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y
CONFIG_CRYPTO_LIB_CHACHA_GENERIC=m
CONFIG_CRYPTO_LIB_CHACHA=m
CONFIG_CRYPTO_LIB_CURVE25519_GENERIC=m
CONFIG_CRYPTO_LIB_CURVE25519=m
CONFIG_CRYPTO_LIB_DES=m
CONFIG_CRYPTO_LIB_POLY1305_RSIZE=1
CONFIG_CRYPTO_LIB_POLY1305_GENERIC=m
CONFIG_CRYPTO_LIB_POLY1305=m
CONFIG_CRYPTO_LIB_CHACHA20POLY1305=m
CONFIG_CRYPTO_LIB_SHA1=y
CONFIG_CRYPTO_LIB_SHA256=y
# end of Crypto library routines

CONFIG_LIB_MEMNEQ=y
CONFIG_CRC_CCITT=m
CONFIG_CRC16=m
CONFIG_CRC_T10DIF=m
CONFIG_CRC64_ROCKSOFT=m
CONFIG_CRC_ITU_T=m
CONFIG_CRC32=y
# CONFIG_CRC32_SELFTEST is not set
CONFIG_CRC32_SLICEBY8=y
# CONFIG_CRC32_SLICEBY4 is not set
# CONFIG_CRC32_SARWATE is not set
# CONFIG_CRC32_BIT is not set
CONFIG_CRC64=m
CONFIG_CRC4=m
CONFIG_CRC7=m
CONFIG_LIBCRC32C=m
CONFIG_CRC8=y
CONFIG_XXHASH=y
CONFIG_AUDIT_GENERIC=y
# CONFIG_RANDOM32_SELFTEST is not set
CONFIG_842_COMPRESS=y
CONFIG_842_DECOMPRESS=y
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
CONFIG_LZO_COMPRESS=y
CONFIG_LZO_DECOMPRESS=y
CONFIG_LZ4_COMPRESS=m
CONFIG_LZ4HC_COMPRESS=m
CONFIG_LZ4_DECOMPRESS=y
CONFIG_ZSTD_COMPRESS=y
CONFIG_ZSTD_DECOMPRESS=y
CONFIG_XZ_DEC=y
CONFIG_XZ_DEC_X86=y
CONFIG_XZ_DEC_POWERPC=y
CONFIG_XZ_DEC_IA64=y
CONFIG_XZ_DEC_ARM=y
CONFIG_XZ_DEC_ARMTHUMB=y
CONFIG_XZ_DEC_SPARC=y
CONFIG_XZ_DEC_MICROLZMA=y
CONFIG_XZ_DEC_BCJ=y
# CONFIG_XZ_DEC_TEST is not set
CONFIG_DECOMPRESS_GZIP=y
CONFIG_DECOMPRESS_BZIP2=y
CONFIG_DECOMPRESS_LZMA=y
CONFIG_DECOMPRESS_XZ=y
CONFIG_DECOMPRESS_LZO=y
CONFIG_DECOMPRESS_LZ4=y
CONFIG_DECOMPRESS_ZSTD=y
CONFIG_GENERIC_ALLOCATOR=y
CONFIG_REED_SOLOMON=m
CONFIG_REED_SOLOMON_ENC8=y
CONFIG_REED_SOLOMON_DEC8=y
CONFIG_REED_SOLOMON_DEC16=y
CONFIG_BCH=m
CONFIG_TEXTSEARCH=y
CONFIG_TEXTSEARCH_KMP=m
CONFIG_TEXTSEARCH_BM=m
CONFIG_TEXTSEARCH_FSM=m
CONFIG_BTREE=y
CONFIG_INTERVAL_TREE=y
CONFIG_XARRAY_MULTI=y
CONFIG_ASSOCIATIVE_ARRAY=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT_MAP=y
CONFIG_HAS_DMA=y
CONFIG_DMA_OPS=y
CONFIG_NEED_SG_DMA_LENGTH=y
CONFIG_NEED_DMA_MAP_STATE=y
CONFIG_DMA_DECLARE_COHERENT=y
CONFIG_SWIOTLB=y
CONFIG_DMA_RESTRICTED_POOL=y
CONFIG_DMA_CMA=y
CONFIG_DMA_PERNUMA_CMA=y

#
# Default contiguous memory area size:
#
CONFIG_CMA_SIZE_MBYTES=0
CONFIG_CMA_SIZE_SEL_MBYTES=y
# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set
# CONFIG_CMA_SIZE_SEL_MIN is not set
# CONFIG_CMA_SIZE_SEL_MAX is not set
CONFIG_CMA_ALIGNMENT=8
# CONFIG_DMA_API_DEBUG is not set
CONFIG_DMA_MAP_BENCHMARK=y
CONFIG_SGL_ALLOC=y
CONFIG_CHECK_SIGNATURE=y
CONFIG_CPUMASK_OFFSTACK=y
CONFIG_CPU_RMAP=y
CONFIG_DQL=y
CONFIG_GLOB=y
# CONFIG_GLOB_SELFTEST is not set
CONFIG_NLATTR=y
CONFIG_LRU_CACHE=m
CONFIG_CLZ_TAB=y
CONFIG_IRQ_POLL=y
CONFIG_MPILIB=y
CONFIG_SIGNATURE=y
CONFIG_DIMLIB=y
CONFIG_LIBFDT=y
CONFIG_OID_REGISTRY=y
CONFIG_UCS2_STRING=y
CONFIG_HAVE_GENERIC_VDSO=y
CONFIG_GENERIC_GETTIMEOFDAY=y
CONFIG_GENERIC_VDSO_32=y
CONFIG_GENERIC_VDSO_TIME_NS=y
CONFIG_FONT_SUPPORT=y
CONFIG_FONTS=y
CONFIG_FONT_8x8=y
CONFIG_FONT_8x16=y
CONFIG_FONT_6x11=y
CONFIG_FONT_7x14=y
CONFIG_FONT_PEARL_8x8=y
CONFIG_FONT_ACORN_8x8=y
CONFIG_FONT_MINI_4x6=y
CONFIG_FONT_6x10=y
CONFIG_FONT_10x18=y
CONFIG_FONT_SUN8x16=y
CONFIG_FONT_SUN12x22=y
CONFIG_FONT_TER16x32=y
CONFIG_FONT_6x8=y
CONFIG_SG_POOL=y
CONFIG_ARCH_STACKWALK=y
CONFIG_STACKDEPOT=y
CONFIG_STACKDEPOT_ALWAYS_INIT=y
CONFIG_REF_TRACKER=y
CONFIG_SBITMAP=y
CONFIG_PARMAN=m
CONFIG_OBJAGG=m
# end of Library routines

CONFIG_PLDMFW=y
CONFIG_ASN1_ENCODER=m
CONFIG_POLYNOMIAL=m

#
# Kernel hacking
#

#
# printk and dmesg options
#
CONFIG_PRINTK_TIME=y
CONFIG_PRINTK_CALLER=y
CONFIG_STACKTRACE_BUILD_ID=y
CONFIG_CONSOLE_LOGLEVEL_DEFAULT=7
CONFIG_CONSOLE_LOGLEVEL_QUIET=4
CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4
CONFIG_BOOT_PRINTK_DELAY=y
CONFIG_DYNAMIC_DEBUG=y
CONFIG_DYNAMIC_DEBUG_CORE=y
CONFIG_SYMBOLIC_ERRNAME=y
CONFIG_DEBUG_BUGVERBOSE=y
# end of printk and dmesg options

CONFIG_DEBUG_KERNEL=y
CONFIG_DEBUG_MISC=y

#
# Compile-time checks and compiler options
#
CONFIG_DEBUG_INFO_NONE=y
# CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT is not set
# CONFIG_DEBUG_INFO_DWARF4 is not set
# CONFIG_DEBUG_INFO_DWARF5 is not set
CONFIG_FRAME_WARN=1024
CONFIG_STRIP_ASM_SYMS=y
CONFIG_HEADERS_INSTALL=y
CONFIG_SECTION_MISMATCH_WARN_ONLY=y
CONFIG_FRAME_POINTER=y
CONFIG_VMLINUX_MAP=y
CONFIG_DEBUG_FORCE_WEAK_PER_CPU=y
# end of Compile-time checks and compiler options

#
# Generic Kernel Debugging Instruments
#
CONFIG_MAGIC_SYSRQ=y
CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1
CONFIG_MAGIC_SYSRQ_SERIAL=y
CONFIG_MAGIC_SYSRQ_SERIAL_SEQUENCE=""
CONFIG_DEBUG_FS=y
CONFIG_DEBUG_FS_ALLOW_ALL=y
# CONFIG_DEBUG_FS_DISALLOW_MOUNT is not set
# CONFIG_DEBUG_FS_ALLOW_NONE is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
CONFIG_ARCH_HAS_UBSAN_SANITIZE_ALL=y
# CONFIG_UBSAN is not set
CONFIG_HAVE_KCSAN_COMPILER=y
# end of Generic Kernel Debugging Instruments

#
# Networking Debugging
#
CONFIG_NET_DEV_REFCNT_TRACKER=y
CONFIG_NET_NS_REFCNT_TRACKER=y
CONFIG_DEBUG_NET=y
# end of Networking Debugging

#
# Memory Debugging
#
CONFIG_PAGE_EXTENSION=y
# CONFIG_DEBUG_PAGEALLOC is not set
CONFIG_SLUB_DEBUG=y
CONFIG_SLUB_DEBUG_ON=y
# CONFIG_PAGE_OWNER is not set
CONFIG_PAGE_POISONING=y
CONFIG_DEBUG_PAGE_REF=y
# CONFIG_DEBUG_RODATA_TEST is not set
CONFIG_ARCH_HAS_DEBUG_WX=y
CONFIG_DEBUG_WX=y
CONFIG_GENERIC_PTDUMP=y
CONFIG_PTDUMP_CORE=y
CONFIG_PTDUMP_DEBUGFS=y
CONFIG_DEBUG_OBJECTS=y
# CONFIG_DEBUG_OBJECTS_SELFTEST is not set
CONFIG_DEBUG_OBJECTS_FREE=y
CONFIG_DEBUG_OBJECTS_TIMERS=y
CONFIG_DEBUG_OBJECTS_WORK=y
CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y
CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1
CONFIG_SHRINKER_DEBUG=y
CONFIG_HAVE_DEBUG_KMEMLEAK=y
# CONFIG_DEBUG_KMEMLEAK is not set
CONFIG_DEBUG_STACK_USAGE=y
CONFIG_SCHED_STACK_END_CHECK=y
CONFIG_ARCH_HAS_DEBUG_VM_PGTABLE=y
CONFIG_DEBUG_VM=y
CONFIG_DEBUG_VM_VMACACHE=y
CONFIG_DEBUG_VM_RB=y
CONFIG_DEBUG_VM_PGFLAGS=y
CONFIG_DEBUG_VM_PGTABLE=y
CONFIG_ARCH_HAS_DEBUG_VIRTUAL=y
CONFIG_DEBUG_VIRTUAL=y
CONFIG_DEBUG_MEMORY_INIT=y
CONFIG_DEBUG_PER_CPU_MAPS=y
CONFIG_DEBUG_KMAP_LOCAL=y
CONFIG_ARCH_SUPPORTS_KMAP_LOCAL_FORCE_MAP=y
CONFIG_DEBUG_KMAP_LOCAL_FORCE_MAP=y
CONFIG_DEBUG_HIGHMEM=y
CONFIG_HAVE_DEBUG_STACKOVERFLOW=y
CONFIG_DEBUG_STACKOVERFLOW=y
CONFIG_CC_HAS_KASAN_GENERIC=y
CONFIG_CC_HAS_KASAN_SW_TAGS=y
CONFIG_CC_HAS_WORKING_NOSANITIZE_ADDRESS=y
CONFIG_HAVE_ARCH_KFENCE=y
# CONFIG_KFENCE is not set
# end of Memory Debugging

CONFIG_DEBUG_SHIRQ=y

#
# Debug Oops, Lockups and Hangs
#
CONFIG_PANIC_ON_OOPS=y
CONFIG_PANIC_ON_OOPS_VALUE=1
CONFIG_PANIC_TIMEOUT=0
CONFIG_LOCKUP_DETECTOR=y
CONFIG_SOFTLOCKUP_DETECTOR=y
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y
CONFIG_HARDLOCKUP_DETECTOR_PERF=y
CONFIG_HARDLOCKUP_DETECTOR=y
CONFIG_BOOTPARAM_HARDLOCKUP_PANIC=y
CONFIG_DETECT_HUNG_TASK=y
CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=480
CONFIG_BOOTPARAM_HUNG_TASK_PANIC=y
CONFIG_WQ_WATCHDOG=y
# CONFIG_TEST_LOCKUP is not set
# end of Debug Oops, Lockups and Hangs

#
# Scheduler Debugging
#
CONFIG_SCHED_DEBUG=y
CONFIG_SCHED_INFO=y
CONFIG_SCHEDSTATS=y
# end of Scheduler Debugging

CONFIG_DEBUG_TIMEKEEPING=y

#
# Lock Debugging (spinlocks, mutexes, etc...)
#
CONFIG_LOCK_DEBUGGING_SUPPORT=y
# CONFIG_PROVE_LOCKING is not set
CONFIG_LOCK_STAT=y
CONFIG_DEBUG_RT_MUTEXES=y
CONFIG_DEBUG_SPINLOCK=y
CONFIG_DEBUG_MUTEXES=y
CONFIG_DEBUG_WW_MUTEX_SLOWPATH=y
CONFIG_DEBUG_RWSEMS=y
CONFIG_DEBUG_LOCK_ALLOC=y
CONFIG_LOCKDEP=y
CONFIG_LOCKDEP_BITS=15
CONFIG_LOCKDEP_CHAINS_BITS=16
CONFIG_LOCKDEP_STACK_TRACE_BITS=19
CONFIG_LOCKDEP_STACK_TRACE_HASH_BITS=14
CONFIG_LOCKDEP_CIRCULAR_QUEUE_BITS=12
# CONFIG_DEBUG_LOCKDEP is not set
CONFIG_DEBUG_ATOMIC_SLEEP=y
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_LOCK_TORTURE_TEST is not set
# CONFIG_WW_MUTEX_SELFTEST is not set
# CONFIG_SCF_TORTURE_TEST is not set
# end of Lock Debugging (spinlocks, mutexes, etc...)

CONFIG_TRACE_IRQFLAGS=y
CONFIG_TRACE_IRQFLAGS_NMI=y
CONFIG_DEBUG_IRQFLAGS=y
CONFIG_STACKTRACE=y
# CONFIG_WARN_ALL_UNSEEDED_RANDOM is not set
# CONFIG_DEBUG_KOBJECT is not set
# CONFIG_DEBUG_KOBJECT_RELEASE is not set

#
# Debug kernel data structures
#
CONFIG_DEBUG_LIST=y
CONFIG_DEBUG_PLIST=y
CONFIG_DEBUG_SG=y
CONFIG_DEBUG_NOTIFIERS=y
CONFIG_BUG_ON_DATA_CORRUPTION=y
# end of Debug kernel data structures

CONFIG_DEBUG_CREDENTIALS=y

#
# RCU Debugging
#
# CONFIG_RCU_SCALE_TEST is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_REF_SCALE_TEST is not set
CONFIG_RCU_CPU_STALL_TIMEOUT=21
CONFIG_RCU_EXP_CPU_STALL_TIMEOUT=0
CONFIG_RCU_TRACE=y
CONFIG_RCU_EQS_DEBUG=y
# end of RCU Debugging

CONFIG_DEBUG_WQ_FORCE_RR_CPU=y
CONFIG_CPU_HOTPLUG_STATE_CONTROL=y
CONFIG_LATENCYTOP=y
CONFIG_USER_STACKTRACE_SUPPORT=y
CONFIG_NOP_TRACER=y
CONFIG_HAVE_RETHOOK=y
CONFIG_RETHOOK=y
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS=y
CONFIG_HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS=y
CONFIG_HAVE_DYNAMIC_FTRACE_NO_PATCHABLE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
CONFIG_HAVE_FENTRY=y
CONFIG_HAVE_C_RECORDMCOUNT=y
CONFIG_HAVE_BUILDTIME_MCOUNT_SORT=y
CONFIG_BUILDTIME_MCOUNT_SORT=y
CONFIG_TRACER_MAX_TRACE=y
CONFIG_TRACE_CLOCK=y
CONFIG_RING_BUFFER=y
CONFIG_EVENT_TRACING=y
CONFIG_CONTEXT_SWITCH_TRACER=y
CONFIG_RING_BUFFER_ALLOW_SWAP=y
CONFIG_PREEMPTIRQ_TRACEPOINTS=y
CONFIG_TRACING=y
CONFIG_GENERIC_TRACER=y
CONFIG_TRACING_SUPPORT=y
CONFIG_FTRACE=y
CONFIG_BOOTTIME_TRACING=y
CONFIG_FUNCTION_TRACER=y
CONFIG_FUNCTION_GRAPH_TRACER=y
CONFIG_DYNAMIC_FTRACE=y
CONFIG_DYNAMIC_FTRACE_WITH_REGS=y
CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS=y
CONFIG_FPROBE=y
CONFIG_FUNCTION_PROFILER=y
CONFIG_STACK_TRACER=y
CONFIG_IRQSOFF_TRACER=y
CONFIG_SCHED_TRACER=y
CONFIG_HWLAT_TRACER=y
CONFIG_OSNOISE_TRACER=y
CONFIG_TIMERLAT_TRACER=y
CONFIG_MMIOTRACE=y
CONFIG_FTRACE_SYSCALLS=y
CONFIG_TRACER_SNAPSHOT=y
CONFIG_TRACER_SNAPSHOT_PER_CPU_SWAP=y
CONFIG_BRANCH_PROFILE_NONE=y
# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
# CONFIG_PROFILE_ALL_BRANCHES is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
CONFIG_KPROBE_EVENTS=y
CONFIG_KPROBE_EVENTS_ON_NOTRACE=y
CONFIG_UPROBE_EVENTS=y
CONFIG_BPF_EVENTS=y
CONFIG_DYNAMIC_EVENTS=y
CONFIG_PROBE_EVENTS=y
CONFIG_BPF_KPROBE_OVERRIDE=y
CONFIG_FTRACE_MCOUNT_RECORD=y
CONFIG_FTRACE_MCOUNT_USE_RECORDMCOUNT=y
CONFIG_TRACING_MAP=y
CONFIG_SYNTH_EVENTS=y
CONFIG_HIST_TRIGGERS=y
CONFIG_TRACE_EVENT_INJECT=y
CONFIG_TRACEPOINT_BENCHMARK=y
CONFIG_RING_BUFFER_BENCHMARK=m
CONFIG_TRACE_EVAL_MAP_FILE=y
CONFIG_FTRACE_RECORD_RECURSION=y
CONFIG_FTRACE_RECORD_RECURSION_SIZE=128
CONFIG_RING_BUFFER_RECORD_RECURSION=y
CONFIG_GCOV_PROFILE_FTRACE=y
# CONFIG_FTRACE_STARTUP_TEST is not set
# CONFIG_FTRACE_SORT_STARTUP_TEST is not set
# CONFIG_RING_BUFFER_STARTUP_TEST is not set
CONFIG_RING_BUFFER_VALIDATE_TIME_DELTAS=y
# CONFIG_MMIOTRACE_TEST is not set
# CONFIG_PREEMPTIRQ_DELAY_TEST is not set
# CONFIG_SYNTH_EVENT_GEN_TEST is not set
# CONFIG_KPROBE_EVENT_GEN_TEST is not set
CONFIG_HIST_TRIGGERS_DEBUG=y
CONFIG_DA_MON_EVENTS=y
CONFIG_DA_MON_EVENTS_ID=y
CONFIG_RV=y
CONFIG_RV_MON_WWNR=y
CONFIG_RV_REACTORS=y
CONFIG_RV_REACT_PRINTK=y
CONFIG_RV_REACT_PANIC=y
CONFIG_PROVIDE_OHCI1394_DMA_INIT=y
CONFIG_SAMPLES=y
CONFIG_SAMPLE_AUXDISPLAY=y
CONFIG_SAMPLE_TRACE_EVENTS=m
CONFIG_SAMPLE_TRACE_CUSTOM_EVENTS=m
CONFIG_SAMPLE_TRACE_PRINTK=m
CONFIG_SAMPLE_TRACE_ARRAY=m
CONFIG_SAMPLE_KOBJECT=m
CONFIG_SAMPLE_KPROBES=m
CONFIG_SAMPLE_KRETPROBES=m
CONFIG_SAMPLE_HW_BREAKPOINT=m
CONFIG_SAMPLE_FPROBE=m
CONFIG_SAMPLE_KFIFO=m
CONFIG_SAMPLE_RPMSG_CLIENT=m
CONFIG_SAMPLE_CONFIGFS=m
CONFIG_SAMPLE_CONNECTOR=m
CONFIG_SAMPLE_FANOTIFY_ERROR=y
CONFIG_SAMPLE_HIDRAW=y
CONFIG_SAMPLE_LANDLOCK=y
CONFIG_SAMPLE_PIDFD=y
CONFIG_SAMPLE_SECCOMP=y
CONFIG_SAMPLE_TIMER=y
CONFIG_SAMPLE_UHID=y
CONFIG_SAMPLE_VFIO_MDEV_MTTY=m
CONFIG_SAMPLE_VFIO_MDEV_MDPY=m
CONFIG_SAMPLE_VFIO_MDEV_MDPY_FB=m
CONFIG_SAMPLE_VFIO_MDEV_MBOCHS=m
CONFIG_SAMPLE_ANDROID_BINDERFS=y
CONFIG_SAMPLE_VFS=y
CONFIG_SAMPLE_INTEL_MEI=y
CONFIG_SAMPLE_WATCHDOG=y
CONFIG_SAMPLE_WATCH_QUEUE=y
CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y
CONFIG_STRICT_DEVMEM=y
CONFIG_IO_STRICT_DEVMEM=y

#
# x86 Debugging
#
CONFIG_EARLY_PRINTK_USB=y
CONFIG_X86_VERBOSE_BOOTUP=y
CONFIG_EARLY_PRINTK=y
CONFIG_EARLY_PRINTK_DBGP=y
CONFIG_EARLY_PRINTK_USB_XDBC=y
CONFIG_EFI_PGT_DUMP=y
CONFIG_DEBUG_TLBFLUSH=y
CONFIG_HAVE_MMIOTRACE_SUPPORT=y
# CONFIG_X86_DECODER_SELFTEST is not set
CONFIG_IO_DELAY_0X80=y
# CONFIG_IO_DELAY_0XED is not set
# CONFIG_IO_DELAY_UDELAY is not set
# CONFIG_IO_DELAY_NONE is not set
CONFIG_DEBUG_BOOT_PARAMS=y
# CONFIG_CPA_DEBUG is not set
CONFIG_DEBUG_ENTRY=y
# CONFIG_DEBUG_NMI_SELFTEST is not set
# CONFIG_DEBUG_IMR_SELFTEST is not set
CONFIG_X86_DEBUG_FPU=y
CONFIG_PUNIT_ATOM_DEBUG=m
CONFIG_UNWINDER_FRAME_POINTER=y
# end of x86 Debugging

#
# Kernel Testing and Coverage
#
# CONFIG_KUNIT is not set
CONFIG_NOTIFIER_ERROR_INJECTION=m
CONFIG_PM_NOTIFIER_ERROR_INJECT=m
CONFIG_OF_RECONFIG_NOTIFIER_ERROR_INJECT=m
CONFIG_NETDEV_NOTIFIER_ERROR_INJECT=m
CONFIG_FUNCTION_ERROR_INJECTION=y
CONFIG_FAULT_INJECTION=y
CONFIG_FAILSLAB=y
CONFIG_FAIL_PAGE_ALLOC=y
CONFIG_FAULT_INJECTION_USERCOPY=y
CONFIG_FAIL_MAKE_REQUEST=y
CONFIG_FAIL_IO_TIMEOUT=y
CONFIG_FAIL_FUTEX=y
CONFIG_FAULT_INJECTION_DEBUG_FS=y
CONFIG_FAIL_FUNCTION=y
CONFIG_FAIL_MMC_REQUEST=y
CONFIG_FAIL_SUNRPC=y
CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y
CONFIG_CC_HAS_SANCOV_TRACE_PC=y
CONFIG_RUNTIME_TESTING_MENU=y
# CONFIG_LKDTM is not set
# CONFIG_TEST_MIN_HEAP is not set
# CONFIG_TEST_DIV64 is not set
# CONFIG_BACKTRACE_SELF_TEST is not set
# CONFIG_TEST_REF_TRACKER is not set
# CONFIG_RBTREE_TEST is not set
# CONFIG_REED_SOLOMON_TEST is not set
# CONFIG_INTERVAL_TREE_TEST is not set
# CONFIG_PERCPU_TEST is not set
# CONFIG_ATOMIC64_SELFTEST is not set
# CONFIG_ASYNC_RAID6_TEST is not set
# CONFIG_TEST_HEXDUMP is not set
# CONFIG_STRING_SELFTEST is not set
# CONFIG_TEST_STRING_HELPERS is not set
# CONFIG_TEST_STRSCPY is not set
# CONFIG_TEST_KSTRTOX is not set
# CONFIG_TEST_PRINTF is not set
# CONFIG_TEST_SCANF is not set
# CONFIG_TEST_BITMAP is not set
# CONFIG_TEST_UUID is not set
# CONFIG_TEST_XARRAY is not set
# CONFIG_TEST_RHASHTABLE is not set
# CONFIG_TEST_SIPHASH is not set
# CONFIG_TEST_IDA is not set
# CONFIG_TEST_PARMAN is not set
# CONFIG_TEST_LKM is not set
# CONFIG_TEST_BITOPS is not set
# CONFIG_TEST_VMALLOC is not set
# CONFIG_TEST_USER_COPY is not set
# CONFIG_TEST_BPF is not set
# CONFIG_TEST_BLACKHOLE_DEV is not set
# CONFIG_FIND_BIT_BENCHMARK is not set
# CONFIG_TEST_FIRMWARE is not set
# CONFIG_TEST_SYSCTL is not set
# CONFIG_TEST_UDELAY is not set
# CONFIG_TEST_STATIC_KEYS is not set
CONFIG_TEST_DYNAMIC_DEBUG=m
# CONFIG_TEST_KMOD is not set
# CONFIG_TEST_DEBUG_VIRTUAL is not set
# CONFIG_TEST_MEMCAT_P is not set
# CONFIG_TEST_OBJAGG is not set
# CONFIG_TEST_MEMINIT is not set
# CONFIG_TEST_FREE_PAGES is not set
# CONFIG_TEST_FPU is not set
# CONFIG_TEST_CLOCKSOURCE_WATCHDOG is not set
CONFIG_ARCH_USE_MEMTEST=y
CONFIG_MEMTEST=y
CONFIG_HYPERV_TESTING=y
# end of Kernel Testing and Coverage

#
# Rust hacking
#
# end of Rust hacking
# end of Kernel hacking

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 4/6] dpll: get source/output name
  2022-10-10 19:55       ` Vadim Fedorenko
@ 2022-10-11  7:28         ` Jiri Pirko
  -1 siblings, 0 replies; 67+ messages in thread
From: Jiri Pirko @ 2022-10-11  7:28 UTC (permalink / raw)
  To: Vadim Fedorenko
  Cc: Jakub Kicinski, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

Mon, Oct 10, 2022 at 09:55:57PM CEST, vfedorenko@novek.ru wrote:
>On 10.10.2022 10:45, Jiri Pirko wrote:
>> Mon, Oct 10, 2022 at 03:18:02AM CEST, vfedorenko@novek.ru wrote:
>> > From: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
>> > 
>> > Dump names of sources and outputs in response to DPLL_CMD_DEVICE_GET dump
>> > request.
>> > 
>> > Signed-off-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
>> > ---
>> > drivers/dpll/dpll_netlink.c | 24 ++++++++++++++++++++++++
>> > include/linux/dpll.h        |  2 ++
>> > include/uapi/linux/dpll.h   |  2 ++
>> > 3 files changed, 28 insertions(+)
>> > 
>> > diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c
>> > index a5779871537a..e3604c10b59e 100644
>> > --- a/drivers/dpll/dpll_netlink.c
>> > +++ b/drivers/dpll/dpll_netlink.c
>> > @@ -31,12 +31,16 @@ static const struct nla_policy dpll_genl_set_source_policy[] = {
>> > 	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
>> > 	[DPLLA_SOURCE_ID]	= { .type = NLA_U32 },
>> > 	[DPLLA_SOURCE_TYPE]	= { .type = NLA_U32 },
>> > +	[DPLLA_SOURCE_NAME]	= { .type = NLA_STRING,
>> > +				    .len = DPLL_NAME_LENGTH },
>> > };
>> > 
>> > static const struct nla_policy dpll_genl_set_output_policy[] = {
>> > 	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
>> > 	[DPLLA_OUTPUT_ID]	= { .type = NLA_U32 },
>> > 	[DPLLA_OUTPUT_TYPE]	= { .type = NLA_U32 },
>> > +	[DPLLA_OUTPUT_NAME]	= { .type = NLA_STRING,
>> > +				    .len = DPLL_NAME_LENGTH },
>> > };
>> > 
>> > static const struct nla_policy dpll_genl_set_src_select_mode_policy[] = {
>> > @@ -100,6 +104,7 @@ static int __dpll_cmd_dump_sources(struct dpll_device *dpll,
>> > {
>> > 	int i, ret = 0, type, prio;
>> > 	struct nlattr *src_attr;
>> > +	const char *name;
>> > 
>> > 	for (i = 0; i < dpll->sources_count; i++) {
>> > 		src_attr = nla_nest_start(msg, DPLLA_SOURCE);
>> > @@ -132,6 +137,15 @@ static int __dpll_cmd_dump_sources(struct dpll_device *dpll,
>> > 				break;
>> > 			}
>> > 		}
>> > +		if (dpll->ops->get_source_name) {
>> > +			name = dpll->ops->get_source_name(dpll, i);
>> > +			if (name && nla_put_string(msg, DPLLA_SOURCE_NAME,
>> > +						   name)) {
>> > +				nla_nest_cancel(msg, src_attr);
>> > +				ret = -EMSGSIZE;
>> > +				break;
>> > +			}
>> > +		}
>> > 		nla_nest_end(msg, src_attr);
>> > 	}
>> > 
>> > @@ -143,6 +157,7 @@ static int __dpll_cmd_dump_outputs(struct dpll_device *dpll,
>> > {
>> > 	struct nlattr *out_attr;
>> > 	int i, ret = 0, type;
>> > +	const char *name;
>> > 
>> > 	for (i = 0; i < dpll->outputs_count; i++) {
>> > 		out_attr = nla_nest_start(msg, DPLLA_OUTPUT);
>> > @@ -167,6 +182,15 @@ static int __dpll_cmd_dump_outputs(struct dpll_device *dpll,
>> > 			}
>> > 			ret = 0;
>> > 		}
>> > +		if (dpll->ops->get_output_name) {
>> > +			name = dpll->ops->get_output_name(dpll, i);
>> > +			if (name && nla_put_string(msg, DPLLA_OUTPUT_NAME,
>> > +						   name)) {
>> > +				nla_nest_cancel(msg, out_attr);
>> > +				ret = -EMSGSIZE;
>> > +				break;
>> > +			}
>> > +		}
>> > 		nla_nest_end(msg, out_attr);
>> > 	}
>> > 
>> > diff --git a/include/linux/dpll.h b/include/linux/dpll.h
>> > index 3fe957a06b90..2f4964dc28f0 100644
>> > --- a/include/linux/dpll.h
>> > +++ b/include/linux/dpll.h
>> > @@ -23,6 +23,8 @@ struct dpll_device_ops {
>> > 	int (*set_output_type)(struct dpll_device *dpll, int id, int val);
>> > 	int (*set_source_select_mode)(struct dpll_device *dpll, int mode);
>> > 	int (*set_source_prio)(struct dpll_device *dpll, int id, int prio);
>> > +	const char *(*get_source_name)(struct dpll_device *dpll, int id);
>> > +	const char *(*get_output_name)(struct dpll_device *dpll, int id);
>> 
>> Hmm, why you exactly need the name for?
>> 
>As with device name, user-space app can use source/output name to easily
>select one using configuration value, for example.

Can you give me some examples? I can't imagine how it can be named
differently than containing the "type string". My point is to avoid
drivers to come up with original names that basically have the same
meaning creating a mess.

Why index (which is predictable and could be used in scripts) isn't
enough?

Or, alternatively, we can leave the "resolve" up to the userspace app.
Example:
index 0
  type 1PPS
index 1
  type 10MHZ
index 2
  type SyncE
  ifindex 20
index 3
  type SyncE
  ifindex 30

Now when user does:
1) dpll X source set index 0
   could be equivalent to
   dpll X source set 1pps
     dpll app would do dump of all sources and if there is only one of
     type 1pps, it will resolve it to index 0 which it is going to send
     via ATTR_INDEX to kernel.
2) dpll X source set index 2
   could be equivalent to
   dpll X source set eth1
     dpll app would use rtnetlink to get ifindex 20 for eth1. Then it
     will do dump of all sources and see if there is SyncE source with
     ifindex 30. This will resolve to index 2 which it is going to send
     via ATTR_INDEX to kernel.

>> 
>> > };
>> > 
>> > struct dpll_device *dpll_device_alloc(struct dpll_device_ops *ops, const char *name,
>> > diff --git a/include/uapi/linux/dpll.h b/include/uapi/linux/dpll.h
>> > index f6b674e5cf01..8782d3425aae 100644
>> > --- a/include/uapi/linux/dpll.h
>> > +++ b/include/uapi/linux/dpll.h
>> > @@ -26,11 +26,13 @@ enum dpll_genl_attr {
>> > 	DPLLA_SOURCE,
>> > 	DPLLA_SOURCE_ID,
>> > 	DPLLA_SOURCE_TYPE,
>> > +	DPLLA_SOURCE_NAME,
>> > 	DPLLA_SOURCE_SUPPORTED,
>> > 	DPLLA_SOURCE_PRIO,
>> > 	DPLLA_OUTPUT,
>> > 	DPLLA_OUTPUT_ID,
>> > 	DPLLA_OUTPUT_TYPE,
>> > +	DPLLA_OUTPUT_NAME,
>> > 	DPLLA_OUTPUT_SUPPORTED,
>> > 	DPLLA_STATUS,
>> > 	DPLLA_TEMP,
>> > -- 
>> > 2.27.0
>> > 
>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 4/6] dpll: get source/output name
@ 2022-10-11  7:28         ` Jiri Pirko
  0 siblings, 0 replies; 67+ messages in thread
From: Jiri Pirko @ 2022-10-11  7:28 UTC (permalink / raw)
  To: Vadim Fedorenko
  Cc: Jakub Kicinski, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

Mon, Oct 10, 2022 at 09:55:57PM CEST, vfedorenko@novek.ru wrote:
>On 10.10.2022 10:45, Jiri Pirko wrote:
>> Mon, Oct 10, 2022 at 03:18:02AM CEST, vfedorenko@novek.ru wrote:
>> > From: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
>> > 
>> > Dump names of sources and outputs in response to DPLL_CMD_DEVICE_GET dump
>> > request.
>> > 
>> > Signed-off-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
>> > ---
>> > drivers/dpll/dpll_netlink.c | 24 ++++++++++++++++++++++++
>> > include/linux/dpll.h        |  2 ++
>> > include/uapi/linux/dpll.h   |  2 ++
>> > 3 files changed, 28 insertions(+)
>> > 
>> > diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c
>> > index a5779871537a..e3604c10b59e 100644
>> > --- a/drivers/dpll/dpll_netlink.c
>> > +++ b/drivers/dpll/dpll_netlink.c
>> > @@ -31,12 +31,16 @@ static const struct nla_policy dpll_genl_set_source_policy[] = {
>> > 	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
>> > 	[DPLLA_SOURCE_ID]	= { .type = NLA_U32 },
>> > 	[DPLLA_SOURCE_TYPE]	= { .type = NLA_U32 },
>> > +	[DPLLA_SOURCE_NAME]	= { .type = NLA_STRING,
>> > +				    .len = DPLL_NAME_LENGTH },
>> > };
>> > 
>> > static const struct nla_policy dpll_genl_set_output_policy[] = {
>> > 	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
>> > 	[DPLLA_OUTPUT_ID]	= { .type = NLA_U32 },
>> > 	[DPLLA_OUTPUT_TYPE]	= { .type = NLA_U32 },
>> > +	[DPLLA_OUTPUT_NAME]	= { .type = NLA_STRING,
>> > +				    .len = DPLL_NAME_LENGTH },
>> > };
>> > 
>> > static const struct nla_policy dpll_genl_set_src_select_mode_policy[] = {
>> > @@ -100,6 +104,7 @@ static int __dpll_cmd_dump_sources(struct dpll_device *dpll,
>> > {
>> > 	int i, ret = 0, type, prio;
>> > 	struct nlattr *src_attr;
>> > +	const char *name;
>> > 
>> > 	for (i = 0; i < dpll->sources_count; i++) {
>> > 		src_attr = nla_nest_start(msg, DPLLA_SOURCE);
>> > @@ -132,6 +137,15 @@ static int __dpll_cmd_dump_sources(struct dpll_device *dpll,
>> > 				break;
>> > 			}
>> > 		}
>> > +		if (dpll->ops->get_source_name) {
>> > +			name = dpll->ops->get_source_name(dpll, i);
>> > +			if (name && nla_put_string(msg, DPLLA_SOURCE_NAME,
>> > +						   name)) {
>> > +				nla_nest_cancel(msg, src_attr);
>> > +				ret = -EMSGSIZE;
>> > +				break;
>> > +			}
>> > +		}
>> > 		nla_nest_end(msg, src_attr);
>> > 	}
>> > 
>> > @@ -143,6 +157,7 @@ static int __dpll_cmd_dump_outputs(struct dpll_device *dpll,
>> > {
>> > 	struct nlattr *out_attr;
>> > 	int i, ret = 0, type;
>> > +	const char *name;
>> > 
>> > 	for (i = 0; i < dpll->outputs_count; i++) {
>> > 		out_attr = nla_nest_start(msg, DPLLA_OUTPUT);
>> > @@ -167,6 +182,15 @@ static int __dpll_cmd_dump_outputs(struct dpll_device *dpll,
>> > 			}
>> > 			ret = 0;
>> > 		}
>> > +		if (dpll->ops->get_output_name) {
>> > +			name = dpll->ops->get_output_name(dpll, i);
>> > +			if (name && nla_put_string(msg, DPLLA_OUTPUT_NAME,
>> > +						   name)) {
>> > +				nla_nest_cancel(msg, out_attr);
>> > +				ret = -EMSGSIZE;
>> > +				break;
>> > +			}
>> > +		}
>> > 		nla_nest_end(msg, out_attr);
>> > 	}
>> > 
>> > diff --git a/include/linux/dpll.h b/include/linux/dpll.h
>> > index 3fe957a06b90..2f4964dc28f0 100644
>> > --- a/include/linux/dpll.h
>> > +++ b/include/linux/dpll.h
>> > @@ -23,6 +23,8 @@ struct dpll_device_ops {
>> > 	int (*set_output_type)(struct dpll_device *dpll, int id, int val);
>> > 	int (*set_source_select_mode)(struct dpll_device *dpll, int mode);
>> > 	int (*set_source_prio)(struct dpll_device *dpll, int id, int prio);
>> > +	const char *(*get_source_name)(struct dpll_device *dpll, int id);
>> > +	const char *(*get_output_name)(struct dpll_device *dpll, int id);
>> 
>> Hmm, why you exactly need the name for?
>> 
>As with device name, user-space app can use source/output name to easily
>select one using configuration value, for example.

Can you give me some examples? I can't imagine how it can be named
differently than containing the "type string". My point is to avoid
drivers to come up with original names that basically have the same
meaning creating a mess.

Why index (which is predictable and could be used in scripts) isn't
enough?

Or, alternatively, we can leave the "resolve" up to the userspace app.
Example:
index 0
  type 1PPS
index 1
  type 10MHZ
index 2
  type SyncE
  ifindex 20
index 3
  type SyncE
  ifindex 30

Now when user does:
1) dpll X source set index 0
   could be equivalent to
   dpll X source set 1pps
     dpll app would do dump of all sources and if there is only one of
     type 1pps, it will resolve it to index 0 which it is going to send
     via ATTR_INDEX to kernel.
2) dpll X source set index 2
   could be equivalent to
   dpll X source set eth1
     dpll app would use rtnetlink to get ifindex 20 for eth1. Then it
     will do dump of all sources and see if there is SyncE source with
     ifindex 30. This will resolve to index 2 which it is going to send
     via ATTR_INDEX to kernel.

>> 
>> > };
>> > 
>> > struct dpll_device *dpll_device_alloc(struct dpll_device_ops *ops, const char *name,
>> > diff --git a/include/uapi/linux/dpll.h b/include/uapi/linux/dpll.h
>> > index f6b674e5cf01..8782d3425aae 100644
>> > --- a/include/uapi/linux/dpll.h
>> > +++ b/include/uapi/linux/dpll.h
>> > @@ -26,11 +26,13 @@ enum dpll_genl_attr {
>> > 	DPLLA_SOURCE,
>> > 	DPLLA_SOURCE_ID,
>> > 	DPLLA_SOURCE_TYPE,
>> > +	DPLLA_SOURCE_NAME,
>> > 	DPLLA_SOURCE_SUPPORTED,
>> > 	DPLLA_SOURCE_PRIO,
>> > 	DPLLA_OUTPUT,
>> > 	DPLLA_OUTPUT_ID,
>> > 	DPLLA_OUTPUT_TYPE,
>> > +	DPLLA_OUTPUT_NAME,
>> > 	DPLLA_OUTPUT_SUPPORTED,
>> > 	DPLLA_STATUS,
>> > 	DPLLA_TEMP,
>> > -- 
>> > 2.27.0
>> > 
>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 6/6] ptp_ocp: implement DPLL ops
  2022-10-10 20:14       ` Vadim Fedorenko
@ 2022-10-11  7:30         ` Jiri Pirko
  -1 siblings, 0 replies; 67+ messages in thread
From: Jiri Pirko @ 2022-10-11  7:30 UTC (permalink / raw)
  To: Vadim Fedorenko
  Cc: Jakub Kicinski, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

Mon, Oct 10, 2022 at 10:14:20PM CEST, vfedorenko@novek.ru wrote:
>On 10.10.2022 16:42, Jiri Pirko wrote:
>> Mon, Oct 10, 2022 at 03:18:04AM CEST, vfedorenko@novek.ru wrote:
>> > From: Vadim Fedorenko <vadfed@fb.com>

[..]


>> 
>> This hunk should not be here.
>> I commented this on the previous version. Btw, this is not the only
>> thing that I previously commented and you ignored. It is annoying to be
>> honest. Could you please include the requested changes in next patchset
>> version or comment why you are not do including them. Ignoring is never
>> good :/
>> 
>Sorry for that. This version of patchset was issued to add visibility to the
>work done by Arkadiusz and to provide documentation (or at least part of it).
>I will definitely address the comments in the next spin.

NP, thanks!

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 6/6] ptp_ocp: implement DPLL ops
@ 2022-10-11  7:30         ` Jiri Pirko
  0 siblings, 0 replies; 67+ messages in thread
From: Jiri Pirko @ 2022-10-11  7:30 UTC (permalink / raw)
  To: Vadim Fedorenko
  Cc: Jakub Kicinski, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

Mon, Oct 10, 2022 at 10:14:20PM CEST, vfedorenko@novek.ru wrote:
>On 10.10.2022 16:42, Jiri Pirko wrote:
>> Mon, Oct 10, 2022 at 03:18:04AM CEST, vfedorenko@novek.ru wrote:
>> > From: Vadim Fedorenko <vadfed@fb.com>

[..]


>> 
>> This hunk should not be here.
>> I commented this on the previous version. Btw, this is not the only
>> thing that I previously commented and you ignored. It is annoying to be
>> honest. Could you please include the requested changes in next patchset
>> version or comment why you are not do including them. Ignoring is never
>> good :/
>> 
>Sorry for that. This version of patchset was issued to add visibility to the
>work done by Arkadiusz and to provide documentation (or at least part of it).
>I will definitely address the comments in the next spin.

NP, thanks!

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 1/6] dpll: Add DPLL framework base functions
  2022-10-10 19:54       ` Vadim Fedorenko
@ 2022-10-11  8:32         ` Jiri Pirko
  -1 siblings, 0 replies; 67+ messages in thread
From: Jiri Pirko @ 2022-10-11  8:32 UTC (permalink / raw)
  To: Vadim Fedorenko
  Cc: Jakub Kicinski, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

Mon, Oct 10, 2022 at 09:54:26PM CEST, vfedorenko@novek.ru wrote:
>On 10.10.2022 10:18, Jiri Pirko wrote:
>> Mon, Oct 10, 2022 at 03:17:59AM CEST, vfedorenko@novek.ru wrote:
>> > From: Vadim Fedorenko <vadfed@fb.com>
>> > 
>> > DPLL framework is used to represent and configure DPLL devices
>> > in systems. Each device that has DPLL and can configure sources
>> > and outputs can use this framework.
>> > 
>> > Signed-off-by: Vadim Fedorenko <vadfed@fb.com>
>> > Co-developed-by: Jakub Kicinski <kuba@kernel.org>
>> > Co-developed-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
>> > ---
>> > MAINTAINERS                 |   8 +
>> > drivers/Kconfig             |   2 +
>> > drivers/Makefile            |   1 +
>> > drivers/dpll/Kconfig        |   7 +
>> > drivers/dpll/Makefile       |   7 +
>> > drivers/dpll/dpll_core.c    | 177 +++++++++++++++
>> > drivers/dpll/dpll_core.h    |  41 ++++
>> > drivers/dpll/dpll_netlink.c | 417 ++++++++++++++++++++++++++++++++++++
>> > drivers/dpll/dpll_netlink.h |   7 +
>> > include/linux/dpll.h        |  29 +++
>> > include/uapi/linux/dpll.h   | 101 +++++++++
>> > 11 files changed, 797 insertions(+)
>> > create mode 100644 drivers/dpll/Kconfig
>> > create mode 100644 drivers/dpll/Makefile
>> > create mode 100644 drivers/dpll/dpll_core.c
>> > create mode 100644 drivers/dpll/dpll_core.h
>> > create mode 100644 drivers/dpll/dpll_netlink.c
>> > create mode 100644 drivers/dpll/dpll_netlink.h
>> > create mode 100644 include/linux/dpll.h
>> > create mode 100644 include/uapi/linux/dpll.h
>> > 
>> > diff --git a/MAINTAINERS b/MAINTAINERS
>> > index 9ca84cb5ab4a..e2f4fede937f 100644
>> > --- a/MAINTAINERS
>> > +++ b/MAINTAINERS
>> > @@ -6301,6 +6301,14 @@ F:	Documentation/networking/device_drivers/ethernet/freescale/dpaa2/switch-drive
>> > F:	drivers/net/ethernet/freescale/dpaa2/dpaa2-switch*
>> > F:	drivers/net/ethernet/freescale/dpaa2/dpsw*
>> > 
>> > +DPLL CLOCK SUBSYSTEM
>> > +M:	Vadim Fedorenko <vadfed@fb.com>
>> > +L:	netdev@vger.kernel.org
>> > +S:	Maintained
>> > +F:	drivers/dpll/*
>> > +F:	include/net/dpll.h
>> > +F:	include/uapi/linux/dpll.h
>> > +
>> > DRBD DRIVER
>> > M:	Philipp Reisner <philipp.reisner@linbit.com>
>> > M:	Lars Ellenberg <lars.ellenberg@linbit.com>
>> > diff --git a/drivers/Kconfig b/drivers/Kconfig
>> > index 19ee995bd0ae..a3e00294a995 100644
>> > --- a/drivers/Kconfig
>> > +++ b/drivers/Kconfig
>> > @@ -239,4 +239,6 @@ source "drivers/peci/Kconfig"
>> > 
>> > source "drivers/hte/Kconfig"
>> > 
>> > +source "drivers/dpll/Kconfig"
>> > +
>> > endmenu
>> > diff --git a/drivers/Makefile b/drivers/Makefile
>> > index 057857258bfd..78a68f1621cc 100644
>> > --- a/drivers/Makefile
>> > +++ b/drivers/Makefile
>> > @@ -188,3 +188,4 @@ obj-$(CONFIG_COUNTER)		+= counter/
>> > obj-$(CONFIG_MOST)		+= most/
>> > obj-$(CONFIG_PECI)		+= peci/
>> > obj-$(CONFIG_HTE)		+= hte/
>> > +obj-$(CONFIG_DPLL)		+= dpll/
>> > diff --git a/drivers/dpll/Kconfig b/drivers/dpll/Kconfig
>> > new file mode 100644
>> > index 000000000000..a4cae73f20d3
>> > --- /dev/null
>> > +++ b/drivers/dpll/Kconfig
>> > @@ -0,0 +1,7 @@
>> > +# SPDX-License-Identifier: GPL-2.0-only
>> > +#
>> > +# Generic DPLL drivers configuration
>> > +#
>> > +
>> > +config DPLL
>> > +  bool
>> > diff --git a/drivers/dpll/Makefile b/drivers/dpll/Makefile
>> > new file mode 100644
>> > index 000000000000..0748c80097e4
>> > --- /dev/null
>> > +++ b/drivers/dpll/Makefile
>> > @@ -0,0 +1,7 @@
>> > +# SPDX-License-Identifier: GPL-2.0
>> > +#
>> > +# Makefile for DPLL drivers.
>> > +#
>> > +
>> > +obj-$(CONFIG_DPLL)          += dpll_sys.o
>> > +dpll_sys-y                  += dpll_core.o dpll_netlink.o
>> > diff --git a/drivers/dpll/dpll_core.c b/drivers/dpll/dpll_core.c
>> > new file mode 100644
>> > index 000000000000..7fdee145e82c
>> > --- /dev/null
>> > +++ b/drivers/dpll/dpll_core.c
>> > @@ -0,0 +1,177 @@
>> > +// SPDX-License-Identifier: GPL-2.0
>> > +/*
>> > + *  dpll_core.c - Generic DPLL Management class support.
>> > + *
>> > + *  Copyright (c) 2021 Meta Platforms, Inc. and affiliates
>> > + */
>> > +
>> > +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
>> > +
>> > +#include <linux/device.h>
>> > +#include <linux/err.h>
>> > +#include <linux/slab.h>
>> > +#include <linux/string.h>
>> > +
>> > +#include "dpll_core.h"
>> > +
>> > +static DEFINE_MUTEX(dpll_device_xa_lock);
>> > +static DEFINE_XARRAY_FLAGS(dpll_device_xa, XA_FLAGS_ALLOC);
>> > +#define DPLL_REGISTERED XA_MARK_1
>> > +
>> > +#define ASSERT_DPLL_REGISTERED(d)                                           \
>> > +	WARN_ON_ONCE(!xa_get_mark(&dpll_device_xa, (d)->id, DPLL_REGISTERED))
>> > +#define ASSERT_DPLL_NOT_REGISTERED(d)                                      \
>> > +	WARN_ON_ONCE(xa_get_mark(&dpll_device_xa, (d)->id, DPLL_REGISTERED))
>> > +
>> > +
>> > +int for_each_dpll_device(int id, int (*cb)(struct dpll_device *, void *),
>> > +			 void *data)
>> 
>> Probably better to avoid this "cb" indirection here.
>> Perhaps in a similar way devlinks_xa_for_each_registered_get() is done?
>> 
>Thanks for pointing to an example, I will consider avoid indirection.
>checkpatch.pl is also complaining about this line, but the same way was used in
>some other places that's why I chosed to use it.

Yeah, that does not necessarily mean it is the best practice :)


>> 
>> > +{
>> > +	struct dpll_device *dpll;
>> > +	unsigned long index;
>> > +	int ret = 0;
>> > +
>> > +	mutex_lock(&dpll_device_xa_lock);
>> > +	xa_for_each_start(&dpll_device_xa, index, dpll, id) {
>> > +		if (!xa_get_mark(&dpll_device_xa, index, DPLL_REGISTERED))
>> > +			continue;
>> > +		ret = cb(dpll, data);
>> > +		if (ret)
>> > +			break;
>> > +	}
>> > +	mutex_unlock(&dpll_device_xa_lock);
>> > +
>> > +	return ret;
>> > +}
>> > +
>> > +struct dpll_device *dpll_device_get_by_id(int id)
>> > +{
>> > +	struct dpll_device *dpll = NULL;
>> > +
>> > +	if (xa_get_mark(&dpll_device_xa, id, DPLL_REGISTERED))
>> > +		dpll = xa_load(&dpll_device_xa, id);
>> > +	return dpll;
>> > +}
>> > +
>> > +struct dpll_device *dpll_device_get_by_name(const char *name)
>> > +{
>> > +	struct dpll_device *dpll, *ret = NULL;
>> > +	unsigned long index;
>> > +
>> > +	mutex_lock(&dpll_device_xa_lock);
>> > +	xa_for_each_marked(&dpll_device_xa, index, dpll, DPLL_REGISTERED) {
>> > +		if (!strcmp(dev_name(&dpll->dev), name)) {
>> > +			ret = dpll;
>> > +			break;
>> > +		}
>> > +	}
>> > +	mutex_unlock(&dpll_device_xa_lock);
>> > +
>> > +	return ret;
>> > +}
>> > +
>> > +void *dpll_priv(struct dpll_device *dpll)
>> > +{
>> > +	return dpll->priv;
>> > +}
>> > +EXPORT_SYMBOL_GPL(dpll_priv);
>> > +
>> > +static void dpll_device_release(struct device *dev)
>> > +{
>> > +	struct dpll_device *dpll;
>> > +
>> > +	dpll = to_dpll_device(dev);
>> > +
>> > +	dpll_device_unregister(dpll);
>> > +	dpll_device_free(dpll);
>> > +}
>> > +
>> > +static struct class dpll_class = {
>> > +	.name = "dpll",
>> > +	.dev_release = dpll_device_release,
>> > +};
>> > +
>> > +struct dpll_device *dpll_device_alloc(struct dpll_device_ops *ops, const char *name,
>> > +				      int sources_count, int outputs_count, void *priv)
>> > +{
>> > +	struct dpll_device *dpll;
>> > +	int ret;
>> > +
>> > +	dpll = kzalloc(sizeof(*dpll), GFP_KERNEL);
>> > +	if (!dpll)
>> > +		return ERR_PTR(-ENOMEM);
>> > +
>> > +	mutex_init(&dpll->lock);
>> > +	dpll->ops = ops;
>> > +	dpll->dev.class = &dpll_class;
>> > +	dpll->sources_count = sources_count;
>> > +	dpll->outputs_count = outputs_count;
>> > +
>> > +	mutex_lock(&dpll_device_xa_lock);
>> > +	ret = xa_alloc(&dpll_device_xa, &dpll->id, dpll, xa_limit_16b, GFP_KERNEL);
>> > +	if (ret)
>> > +		goto error;
>> > +	dev_set_name(&dpll->dev, "%s%d", name ? name : "dpll", dpll->id);
>> > +	mutex_unlock(&dpll_device_xa_lock);
>> > +	dpll->priv = priv;
>> > +
>> > +	return dpll;
>> > +
>> > +error:
>> > +	mutex_unlock(&dpll_device_xa_lock);
>> > +	kfree(dpll);
>> > +	return ERR_PTR(ret);
>> > +}
>> > +EXPORT_SYMBOL_GPL(dpll_device_alloc);
>> > +
>> > +void dpll_device_free(struct dpll_device *dpll)
>> > +{
>> > +	if (!dpll)
>> > +		return;
>> > +
>> > +	mutex_destroy(&dpll->lock);
>> > +	kfree(dpll);
>> > +}
>> > +EXPORT_SYMBOL_GPL(dpll_device_free);
>> > +
>> > +void dpll_device_register(struct dpll_device *dpll)
>> > +{
>> > +	ASSERT_DPLL_NOT_REGISTERED(dpll);
>> > +
>> > +	mutex_lock(&dpll_device_xa_lock);
>> > +	xa_set_mark(&dpll_device_xa, dpll->id, DPLL_REGISTERED);
>> > +	mutex_unlock(&dpll_device_xa_lock);
>> > +}
>> > +EXPORT_SYMBOL_GPL(dpll_device_register);
>> > +
>> > +void dpll_device_unregister(struct dpll_device *dpll)
>> > +{
>> > +	ASSERT_DPLL_REGISTERED(dpll);
>> > +
>> > +	mutex_lock(&dpll_device_xa_lock);
>> > +	xa_erase(&dpll_device_xa, dpll->id);
>> > +	mutex_unlock(&dpll_device_xa_lock);
>> > +}
>> > +EXPORT_SYMBOL_GPL(dpll_device_unregister);
>> > +
>> > +static int __init dpll_init(void)
>> > +{
>> > +	int ret;
>> > +
>> > +	ret = dpll_netlink_init();
>> > +	if (ret)
>> > +		goto error;
>> > +
>> > +	ret = class_register(&dpll_class);
>> > +	if (ret)
>> > +		goto unregister_netlink;
>> > +
>> > +	return 0;
>> > +
>> > +unregister_netlink:
>> > +	dpll_netlink_finish();
>> > +error:
>> > +	mutex_destroy(&dpll_device_xa_lock);
>> > +	return ret;
>> > +}
>> > +subsys_initcall(dpll_init);
>> > diff --git a/drivers/dpll/dpll_core.h b/drivers/dpll/dpll_core.h
>> > new file mode 100644
>> > index 000000000000..4b6fc9eb228f
>> > --- /dev/null
>> > +++ b/drivers/dpll/dpll_core.h
>> > @@ -0,0 +1,41 @@
>> > +/* SPDX-License-Identifier: GPL-2.0 */
>> > +/*
>> > + *  Copyright (c) 2021 Meta Platforms, Inc. and affiliates
>> > + */
>> > +
>> > +#ifndef __DPLL_CORE_H__
>> > +#define __DPLL_CORE_H__
>> > +
>> > +#include <linux/dpll.h>
>> > +
>> > +#include "dpll_netlink.h"
>> > +
>> > +/**
>> > + * struct dpll_device - structure for a DPLL device
>> > + * @id:		unique id number for each edvice
>> > + * @dev:	&struct device for this dpll device
>> > + * @sources_count:	amount of input sources this dpll_device supports
>> > + * @outputs_count:	amount of outputs this dpll_device supports
>> > + * @ops:	operations this &dpll_device supports
>> > + * @lock:	mutex to serialize operations
>> > + * @priv:	pointer to private information of owner
>> > + */
>> > +struct dpll_device {
>> > +	int id;
>> > +	struct device dev;
>> > +	int sources_count;
>> > +	int outputs_count;
>> > +	struct dpll_device_ops *ops;
>> > +	struct mutex lock;
>> > +	void *priv;
>> > +};
>> > +
>> > +#define to_dpll_device(_dev) \
>> > +	container_of(_dev, struct dpll_device, dev)
>> > +
>> > +int for_each_dpll_device(int id, int (*cb)(struct dpll_device *, void *),
>> > +			  void *data);
>> > +struct dpll_device *dpll_device_get_by_id(int id);
>> > +struct dpll_device *dpll_device_get_by_name(const char *name);
>> > +void dpll_device_unregister(struct dpll_device *dpll);
>> > +#endif
>> > diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c
>> > new file mode 100644
>> > index 000000000000..31966e0eec3a
>> > --- /dev/null
>> > +++ b/drivers/dpll/dpll_netlink.c
>> > @@ -0,0 +1,417 @@
>> > +// SPDX-License-Identifier: GPL-2.0
>> > +/*
>> > + * Generic netlink for DPLL management framework
>> > + *
>> > + * Copyright (c) 2021 Meta Platforms, Inc. and affiliates
>> > + *
>> > + */
>> > +#include <linux/module.h>
>> > +#include <linux/kernel.h>
>> > +#include <net/genetlink.h>
>> > +#include "dpll_core.h"
>> > +
>> > +#include <uapi/linux/dpll.h>
>> > +
>> > +static const struct genl_multicast_group dpll_genl_mcgrps[] = {
>> > +	{ .name = DPLL_CONFIG_DEVICE_GROUP_NAME, },
>> > +	{ .name = DPLL_CONFIG_SOURCE_GROUP_NAME, },
>> > +	{ .name = DPLL_CONFIG_OUTPUT_GROUP_NAME, },
>> > +	{ .name = DPLL_MONITOR_GROUP_NAME,  },
>> > +};
>> > +
>> > +static const struct nla_policy dpll_genl_get_policy[] = {
>> > +	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
>> > +	[DPLLA_DEVICE_NAME]	= { .type = NLA_STRING,
>> > +				    .len = DPLL_NAME_LENGTH },
>> > +	[DPLLA_FLAGS]		= { .type = NLA_U32 },
>> > +};
>> > +
>> > +static const struct nla_policy dpll_genl_set_source_policy[] = {
>> > +	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
>> > +	[DPLLA_SOURCE_ID]	= { .type = NLA_U32 },
>> > +	[DPLLA_SOURCE_TYPE]	= { .type = NLA_U32 },
>> > +};
>> > +
>> > +static const struct nla_policy dpll_genl_set_output_policy[] = {
>> > +	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
>> > +	[DPLLA_OUTPUT_ID]	= { .type = NLA_U32 },
>> > +	[DPLLA_OUTPUT_TYPE]	= { .type = NLA_U32 },
>> > +};
>> > +
>> > +struct param {
>> 
>> Namespace prefix please	.
>> 
>Yep, will add.
>> 
>> > +	struct netlink_callback *cb;
>> > +	struct dpll_device *dpll;
>> > +	struct sk_buff *msg;
>> 
>> 
>> 
>> > +	int dpll_id;
>> > +	int dpll_source_id;
>> > +	int dpll_source_type;
>> > +	int dpll_output_id;
>> > +	int dpll_output_type;
>> 
>> I don't see where you use these 5.
>> 
>Yep, the implementation was improved, it looks like it's artifacts of the
>previous version.
>
>> 
>> > +};
>> > +
>> > +struct dpll_dump_ctx {
>> > +	struct dpll_device *dev;
>> > +	int flags;
>> > +	int pos_idx;
>> 
>> 
>> 
>> > +	int pos_src_idx;
>> > +	int pos_out_idx;
>> 
>> You don't use these 2.
>> 
>
>The same again, artifacts.
>
>> 
>> > +};
>> > +
>> > +typedef int (*cb_t)(struct param *);
>> > +
>> > +static struct genl_family dpll_gnl_family;
>> > +
>> > +static struct dpll_dump_ctx *dpll_dump_context(struct netlink_callback *cb)
>> > +{
>> > +	return (struct dpll_dump_ctx *)cb->ctx;
>> > +}
>> > +
>> > +static int __dpll_cmd_device_dump_one(struct dpll_device *dpll,
>> > +					   struct sk_buff *msg)
>> > +{
>> > +	if (nla_put_u32(msg, DPLLA_DEVICE_ID, dpll->id))
>> > +		return -EMSGSIZE;
>> > +
>> > +	if (nla_put_string(msg, DPLLA_DEVICE_NAME, dev_name(&dpll->dev)))
>> > +		return -EMSGSIZE;
>> > +
>> > +	return 0;
>> > +}
>> > +
>> > +static int __dpll_cmd_dump_sources(struct dpll_device *dpll,
>> > +					   struct sk_buff *msg)
>> > +{
>> > +	struct nlattr *src_attr;
>> > +	int i, ret = 0, type;
>> > +
>> > +	for (i = 0; i < dpll->sources_count; i++) {
>> > +		src_attr = nla_nest_start(msg, DPLLA_SOURCE);
>> > +		if (!src_attr) {
>> > +			ret = -EMSGSIZE;
>> > +			break;
>> > +		}
>> > +		type = dpll->ops->get_source_type(dpll, i);
>> > +		if (nla_put_u32(msg, DPLLA_SOURCE_ID, i) ||
>> > +		    nla_put_u32(msg, DPLLA_SOURCE_TYPE, type)) {
>> > +			nla_nest_cancel(msg, src_attr);
>> > +			ret = -EMSGSIZE;
>> > +			break;
>> > +		}
>> > +		if (dpll->ops->get_source_supported) {
>> > +			for (type = 0; type <= DPLL_TYPE_MAX; type++) {
>> > +				ret = dpll->ops->get_source_supported(dpll, i, type);
>> 
>> Okay, this looks weird to me. This implicates that it is possible to
>> have for example:
>> source index 0 of type 10
>> source index 0 of type 11
>> Both possible.
>> 
>> However, from how I understand this, each source if of certain fixed type.
>> Either it is:
>> SyncE port
>> 1pps external input (SMA)
>> 10MHZ external input (SMA)
>> internal oscilator (free-running)
>> GNSS (GPS)
>> 
>> So for example:
>> index 0, type: 1pps external input (SMA)
>> index 1, type: 10MHZ external input (
>> index 2, type: SyncE port, netdev ifindex: 20
>> index 3, type: SyncE port, netdev ifindex: 30
>> 
>> So 4 "source" objects, each of different type.
>> In this case I can imagine that the netlink API might look something
>> like:
>> -> DPLL_CMD_SOURCE_GET - dump
>>       ATTR_DEVICE_ID X
>> 
>> <- DPLL_CMD_SOURCE_GET
>> 
>>       ATTR_DEVICE_ID X
>>       ATTR_SOURCE_INDEX 0
>>       ATTR_SOURCE_TYPE EXT_1PPS
>>       ATTR_DEVICE_ID X
>>       ATTR_SOURCE_INDEX 1
>>       ATTR_SOURCE_TYPE EXT_10MHZ
>>       ATTR_DEVICE_ID X
>>       ATTR_SOURCE_INDEX 2
>>       ATTR_SOURCE_TYPE SYNCE_ETH_PORT
>>       ATTR_SOURCE_NETDEV_IFINDEX 20
>> 
>>       ATTR_DEVICE_ID X
>>       ATTR_SOURCE_INDEX 3
>>       ATTR_SOURCE_TYPE SYNCE_ETH_PORT
>>       ATTR_SOURCE_NETDEV_IFINDEX 30
>> 
>> You see kernel would dump 4 source objects.
>> 
>I see your point. We do have hardware which allows changing type of SMA
>connector, and even the direction, each SMA could be used as input/source or
>output of different signals. But there are limitation, like not all SMAs can
>produce IRIG-B signal or only some of them can be used to get GNSS 1PPS. The

Okay, so that is not the *type* of source, but rather attribute of it.
Example:

$ dpll X show
index 0
  type EXT
  signal 1PPS
  supported_signals
     1PPS 10MHz

$ dpll X set source index 1 signal_type 10MHz
$ dpll X show
index 0
  type EXT
  signal 10MHz
  supported_signals
     1PPS 10MHz

So one source with index 0 of type "EXT" (could be "SMA", does not
matter) supports 1 signal types.


Thinking about this more and to cover the case when one SMA could be
potencially used for input and output. It already occured to me that
source/output are quite similar, have similar/same attributes. What if
they are merged together to say a "pin" object only with extra
PERSONALITY attribute?

Example:

-> DPLL_CMD_PIN_GET - dump
      ATTR_DEVICE_ID X

<- DPLL_CMD_PIN_GET

       ATTR_DEVICE_ID X
       ATTR_PIN_INDEX 0
       ATTR_PIN_TYPE EXT
       ATTR_PIN_SIGNAL 1PPS   (selected signal)
       ATTR_PIN_SUPPORTED_SIGNALS (nest)
         ATTR_PIN_SIGNAL 1PPS
         ATTR_PIN_SIGNAL 10MHZ
       ATTR_PIN_PERSONALITY OUTPUT   (selected personality)
       ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
         ATTR_PIN_PERSONALITY DISCONNECTED
         ATTR_PIN_PERSONALITY INPUT
         ATTR_PIN_PERSONALITY OUTPUT     (note this supports both input and
					  output)

       ATTR_DEVICE_ID X
       ATTR_PIN_INDEX 1
       ATTR_PIN_TYPE EXT
       ATTR_PIN_SIGNAL 10MHz   (selected signal)
       ATTR_PIN_SUPPORTED_SIGNALS (nest)
         ATTR_PIN_SIGNAL 1PPS
         ATTR_PIN_SIGNAL 10MHZ
       ATTR_PIN_PERSONALITY DISCONNECTED   (selected personality - not
					    connected currently)
       ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
         ATTR_PIN_PERSONALITY DISCONNECTED
         ATTR_PIN_PERSONALITY INPUT      (note this supports only input)

       ATTR_DEVICE_ID X
       ATTR_PIN_INDEX 2
       ATTR_PIN_TYPE GNSS
       ATTR_PIN_SIGNAL 1PPS   (selected signal)
       ATTR_PIN_SUPPORTED_SIGNALS (nest)
         ATTR_PIN_SIGNAL 1PPS
       ATTR_PIN_PERSONALITY INPUT   (selected personality - note this is
				     now he selected source, being only
				     pin with INPUT personality)
       ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
         ATTR_PIN_PERSONALITY DISCONNECTED
         ATTR_PIN_PERSONALITY INPUT      (note this supports only input)

       ATTR_DEVICE_ID X
       ATTR_PIN_INDEX 3
       ATTR_PIN_TYPE SYNCE_ETH_PORT
       ATTR_PIN_NETDEV_IFINDEX 20
       ATTR_PIN_PERSONALITY OUTPUT   (selected personality)
       ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
         ATTR_PIN_PERSONALITY DISCONNECTED
         ATTR_PIN_PERSONALITY INPUT
         ATTR_PIN_PERSONALITY OUTPUT     (note this supports both input and
					  output)

       ATTR_DEVICE_ID X
       ATTR_PIN_INDEX 4
       ATTR_PIN_TYPE SYNCE_ETH_PORT
       ATTR_PIN_NETDEV_IFINDEX 30
       ATTR_PIN_PERSONALITY OUTPUT   (selected personality)
       ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
         ATTR_PIN_PERSONALITY DISCONNECTED
         ATTR_PIN_PERSONALITY INPUT
         ATTR_PIN_PERSONALITY OUTPUT     (note this supports both input and
					  output)


This allows the user to actually see the full picture:
1) all input/output pins in a single list, no duplicates
2) each pin if of certain type (ATTR_PIN_TYPE) EXT/GNSS/SYNCE_ETH_PORT
3) the pins that can change signal type contain the selected and list of
   supported signal types (ATTR_PIN_SIGNAL, ATTR_PIN_SUPPORTED_SIGNALS)
4) direction/connection of the pin to the DPLL is exposed over
   ATTR_PIN_PERSONALITY. For each pin, the driver would expose it can
   act as INPUT/OUTPUT and even more, it can indicate the pin can
   disconnect from DPLL entirely (if possible).
5) user can select the source by setting ATTR_PIN_PERSONALITY of certain
   pin to INPUT. Only one pin could be set to INPUT and that is the
   souce of DPLL.
   In case no pin have personality set to INPUT, the DPLL is
   free-running.

This would introduce quite nice flexibility, exposes source/output
capabilities and provides good visilibity of current configuration.


>interface was created to cover such case. I believe we have to improve it to
>cover SyncE configuration better, but I personally don't have SyncE hardware
>ready to test and that's why I have to rely on suggestions from yours or
>Arkadiusz's experience. From what I can see now there is need for special
>attribute to link source to net device, and I'm happy to add it. In case of
>fixed configuration of sources, the device should provide only one type as
>supported and that's it.
>
>
>> 
>> 
>> > +				if (ret && nla_put_u32(msg, DPLLA_SOURCE_SUPPORTED, type)) {
>> > +					ret = -EMSGSIZE;
>> > +					break;
>> > +				}
>> > +			}
>> > +			ret = 0;
>> > +		}
>> > +		nla_nest_end(msg, src_attr);
>> > +	}
>> > +
>> > +	return ret;
>> > +}
>> > +
>> > +static int __dpll_cmd_dump_outputs(struct dpll_device *dpll,
>> > +					   struct sk_buff *msg)
>> > +{
>> > +	struct nlattr *out_attr;
>> > +	int i, ret = 0, type;
>> > +
>> > +	for (i = 0; i < dpll->outputs_count; i++) {
>> > +		out_attr = nla_nest_start(msg, DPLLA_OUTPUT);
>> > +		if (!out_attr) {
>> > +			ret = -EMSGSIZE;
>> > +			break;
>> > +		}
>> > +		type = dpll->ops->get_output_type(dpll, i);
>> > +		if (nla_put_u32(msg, DPLLA_OUTPUT_ID, i) ||
>> > +		    nla_put_u32(msg, DPLLA_OUTPUT_TYPE, type)) {
>> > +			nla_nest_cancel(msg, out_attr);
>> > +			ret = -EMSGSIZE;
>> > +			break;
>> > +		}
>> > +		if (dpll->ops->get_output_supported) {
>> > +			for (type = 0; type <= DPLL_TYPE_MAX; type++) {
>> > +				ret = dpll->ops->get_output_supported(dpll, i, type);
>> > +				if (ret && nla_put_u32(msg, DPLLA_OUTPUT_SUPPORTED, type)) {
>> 
>> This I believe is similar to sources, see my comment above.
>> 
>As I said, we have to cover the case when SMAs are flexible to configure.
>
>> I believe we should have separate commands to GET and SET outputs and
>> sources. That would make the object separation clear and will also help
>> event model. See below I suggestion how output netlink API may look
>> like (comment in header file near enum dpll_genl_cmd definition).
>> 
>> 
>> > +					ret = -EMSGSIZE;
>> > +					break;
>> > +				}
>> > +			}
>> > +			ret = 0;
>> > +		}
>> > +		nla_nest_end(msg, out_attr);
>> > +	}
>> > +
>> > +	return ret;
>> > +}
>> > +
>> > +static int __dpll_cmd_dump_status(struct dpll_device *dpll,
>> > +					   struct sk_buff *msg)
>> > +{
>> > +	int ret;
>> > +
>> > +	if (dpll->ops->get_status) {
>> > +		ret = dpll->ops->get_status(dpll);
>> > +		if (nla_put_u32(msg, DPLLA_STATUS, ret))
>> > +			return -EMSGSIZE;
>> > +	}
>> > +
>> > +	if (dpll->ops->get_temp) {
>> > +		ret = dpll->ops->get_temp(dpll);
>> > +		if (nla_put_u32(msg, DPLLA_TEMP, ret))
>> > +			return -EMSGSIZE;
>> > +	}
>> > +
>> > +	if (dpll->ops->get_lock_status) {
>> > +		ret = dpll->ops->get_lock_status(dpll);
>> > +		if (nla_put_u32(msg, DPLLA_LOCK_STATUS, ret))
>> > +			return -EMSGSIZE;
>> > +	}
>> > +
>> > +	return 0;
>> > +}
>> > +
>> > +static int
>> > +dpll_device_dump_one(struct dpll_device *dpll, struct sk_buff *msg,
>> > +		     u32 portid, u32 seq, int flags)
>> > +{
>> > +	struct nlattr *hdr;
>> > +	int ret;
>> > +
>> > +	hdr = genlmsg_put(msg, portid, seq, &dpll_gnl_family, 0,
>> > +			  DPLL_CMD_DEVICE_GET);
>> > +	if (!hdr)
>> > +		return -EMSGSIZE;
>> > +
>> > +	mutex_lock(&dpll->lock);
>> > +	ret = __dpll_cmd_device_dump_one(dpll, msg);
>> > +	if (ret)
>> > +		goto out_unlock;
>> > +
>> > +	if (flags & DPLL_FLAG_SOURCES && dpll->ops->get_source_type) {
>> > +		ret = __dpll_cmd_dump_sources(dpll, msg);
>> > +		if (ret)
>> > +			goto out_unlock;
>> > +	}
>> > +
>> > +	if (flags & DPLL_FLAG_OUTPUTS && dpll->ops->get_output_type) {
>> > +		ret = __dpll_cmd_dump_outputs(dpll, msg);
>> > +		if (ret)
>> > +			goto out_unlock;
>> > +	}
>> > +
>> > +	if (flags & DPLL_FLAG_STATUS) {
>> > +		ret = __dpll_cmd_dump_status(dpll, msg);
>> > +		if (ret)
>> > +			goto out_unlock;
>> > +	}
>> > +	mutex_unlock(&dpll->lock);
>> > +	genlmsg_end(msg, hdr);
>> > +
>> > +	return 0;
>> > +
>> > +out_unlock:
>> > +	mutex_unlock(&dpll->lock);
>> > +	genlmsg_cancel(msg, hdr);
>> > +
>> > +	return ret;
>> > +}
>> > +
>> > +static int dpll_genl_cmd_set_source(struct sk_buff *skb, struct genl_info *info)
>> > +{
>> > +	struct dpll_device *dpll = info->user_ptr[0];
>> > +	struct nlattr **attrs = info->attrs;
>> > +	int ret = 0, src_id, type;
>> 
>> Enums.
>> 
>
>Sure.
>
>> > +
>> > +	if (!attrs[DPLLA_SOURCE_ID] ||
>> > +	    !attrs[DPLLA_SOURCE_TYPE])
>> > +		return -EINVAL;
>> > +
>> > +	if (!dpll->ops->set_source_type)
>> > +		return -EOPNOTSUPP;
>> > +
>> > +	src_id = nla_get_u32(attrs[DPLLA_SOURCE_ID]);
>> > +	type = nla_get_u32(attrs[DPLLA_SOURCE_TYPE]);
>> 
>> 
>> This looks odd to me. The user should just pass the index of source to
>> select. Type should be static, and non-changeable.
>> 
>> 
>> > +
>> > +	mutex_lock(&dpll->lock);
>> > +	ret = dpll->ops->set_source_type(dpll, src_id, type);
>> > +	mutex_unlock(&dpll->lock);
>> > +
>> > +	return ret;
>> > +}
>> > +
>> > +static int dpll_genl_cmd_set_output(struct sk_buff *skb, struct genl_info *info)
>> > +{
>> > +	struct dpll_device *dpll = info->user_ptr[0];
>> > +	struct nlattr **attrs = info->attrs;
>> > +	int ret = 0, out_id, type;
>> 
>> Enums.
>> 
>> 
>> > +
>> > +	if (!attrs[DPLLA_OUTPUT_ID] ||
>> > +	    !attrs[DPLLA_OUTPUT_TYPE])
>> > +		return -EINVAL;
>> > +
>> > +	if (!dpll->ops->set_output_type)
>> > +		return -EOPNOTSUPP;
>> > +
>> > +	out_id = nla_get_u32(attrs[DPLLA_OUTPUT_ID]);
>> > +	type = nla_get_u32(attrs[DPLLA_OUTPUT_TYPE]);
>> 
>> Same here, passing type here looks wrong.
>> 
>> 
>> 
>> > +
>> > +	mutex_lock(&dpll->lock);
>> > +	ret = dpll->ops->set_output_type(dpll, out_id, type);
>> > +	mutex_unlock(&dpll->lock);
>> > +
>> > +	return ret;
>> > +}
>> > +
>> > +static int dpll_device_loop_cb(struct dpll_device *dpll, void *data)
>> > +{
>> > +	struct dpll_dump_ctx *ctx;
>> > +	struct param *p = (struct param *)data;
>> > +
>> > +	ctx = dpll_dump_context(p->cb);
>> > +
>> > +	ctx->pos_idx = dpll->id;
>> > +
>> > +	return dpll_device_dump_one(dpll, p->msg, 0, 0, ctx->flags);
>> > +}
>> > +
>> > +static int
>> > +dpll_cmd_device_dump(struct sk_buff *skb, struct netlink_callback *cb)
>> > +{
>> > +	struct dpll_dump_ctx *ctx = dpll_dump_context(cb);
>> > +	struct param p = { .cb = cb, .msg = skb };
>> > +
>> > +	return for_each_dpll_device(ctx->pos_idx, dpll_device_loop_cb, &p);
>> > +}
>> > +
>> > +static int
>> > +dpll_genl_cmd_device_get_id(struct sk_buff *skb, struct genl_info *info)
>> 
>> Just "get", no "id" here.
>> 
>
>Got it.
>
>> 
>> > +{
>> > +	struct dpll_device *dpll = info->user_ptr[0];
>> > +	struct nlattr **attrs = info->attrs;
>> > +	struct sk_buff *msg;
>> > +	int flags = 0;
>> > +	int ret;
>> > +
>> > +	if (attrs[DPLLA_FLAGS])
>> > +		flags = nla_get_u32(attrs[DPLLA_FLAGS]);
>> > +
>> > +	msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
>> > +	if (!msg)
>> > +		return -ENOMEM;
>> > +
>> > +	ret = dpll_device_dump_one(dpll, msg, info->snd_portid, info->snd_seq,
>> > +				   flags);
>> > +	if (ret)
>> > +		goto out_free_msg;
>> > +
>> > +	return genlmsg_reply(msg, info);
>> > +
>> > +out_free_msg:
>> > +	nlmsg_free(msg);
>> > +	return ret;
>> > +
>> > +}
>> > +
>> > +static int dpll_genl_cmd_start(struct netlink_callback *cb)
>> > +{
>> > +	const struct genl_dumpit_info *info = genl_dumpit_info(cb);
>> > +	struct dpll_dump_ctx *ctx = dpll_dump_context(cb);
>> > +
>> > +	ctx->dev = NULL;
>> > +	if (info->attrs[DPLLA_FLAGS])
>> > +		ctx->flags = nla_get_u32(info->attrs[DPLLA_FLAGS]);
>> > +	else
>> > +		ctx->flags = 0;
>> > +	ctx->pos_idx = 0;
>> > +	ctx->pos_src_idx = 0;
>> > +	ctx->pos_out_idx = 0;
>> > +	return 0;
>> > +}
>> > +
>> > +static int dpll_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
>> > +						 struct genl_info *info)
>> > +{
>> > +	struct dpll_device *dpll_id = NULL, *dpll_name = NULL;
>> > +
>> > +	if (!info->attrs[DPLLA_DEVICE_ID] &&
>> > +	    !info->attrs[DPLLA_DEVICE_NAME])
>> > +		return -EINVAL;
>> > +
>> > +	if (info->attrs[DPLLA_DEVICE_ID]) {
>> > +		u32 id = nla_get_u32(info->attrs[DPLLA_DEVICE_ID]);
>> > +
>> > +		dpll_id = dpll_device_get_by_id(id);
>> > +		if (!dpll_id)
>> > +			return -ENODEV;
>> > +		info->user_ptr[0] = dpll_id;
>> 
>> struct dpll_device *dpll should be stored here.
>> 
>> 
>> > +	}
>> > +	if (info->attrs[DPLLA_DEVICE_NAME]) {
>> 
>> You define new API, have one clear handle for devices. Either name or
>> ID. Having both is messy.
>> 
>That was added after the discussion with Jakub and Arkadiusz where we agreed
>that the device could be referenced either by index or by name. The example
>is that userspace app can easily find specific DPLL device if it knows the
>name provided by a driver of that specific device. Without searching through
>sysfs to find index value. Later commands could be executed using index once
>it's known through CMD_GET_DEVICE/ATTR_DEVICE_NAME.

What exacly is the name? What is the semantics? How the name is
generated in case of multiple instances of the same driver. What happens
if two drivers use the same name? Is the name predictable (in sense of
"stable over reboots")?


>> 
>> > +		const char *name = nla_data(info->attrs[DPLLA_DEVICE_NAME]);
>> > +
>> > +		dpll_name = dpll_device_get_by_name(name);
>> > +		if (!dpll_name)
>> > +			return -ENODEV;
>> > +
>> > +		if (dpll_id && dpll_name != dpll_id)
>> > +			return -EINVAL;
>> > +		info->user_ptr[0] = dpll_name;
>> 
>> struct dpll_device *dpll should be stored here.
>> 
>
>
>Didn't get you, where should we store it?
>dpll_name and dpll_id are of type struct dpll_device*,

Ah sorry, you confused me with the "name"/"id" suffix. Why you don't
have just one variable called "dpll" instead and have the check for both
attrs being set at the beginning? Also, extack error message would be
nice (not only here).


>and they are compared to avoid situation when both index and name are
>provided, but refer to different devices.
>
>> 
>> 
>> > +	}
>> > +
>> > +	return 0;
>> > +}
>> > +
>> > +static const struct genl_ops dpll_genl_ops[] = {
>> > +	{
>> > +		.cmd	= DPLL_CMD_DEVICE_GET,
>> > +		.flags  = GENL_UNS_ADMIN_PERM,
>> > +		.start	= dpll_genl_cmd_start,
>> > +		.dumpit	= dpll_cmd_device_dump,
>> > +		.doit	= dpll_genl_cmd_device_get_id,
>> > +		.policy	= dpll_genl_get_policy,
>> > +		.maxattr = ARRAY_SIZE(dpll_genl_get_policy) - 1,
>> > +	},
>> > +	{
>> > +		.cmd	= DPLL_CMD_SET_SOURCE_TYPE,
>> > +		.flags	= GENL_UNS_ADMIN_PERM,
>> > +		.doit	= dpll_genl_cmd_set_source,
>> > +		.policy	= dpll_genl_set_source_policy,
>> > +		.maxattr = ARRAY_SIZE(dpll_genl_set_source_policy) - 1,
>> > +	},
>> > +	{
>> > +		.cmd	= DPLL_CMD_SET_OUTPUT_TYPE,
>> > +		.flags	= GENL_UNS_ADMIN_PERM,
>> > +		.doit	= dpll_genl_cmd_set_output,
>> > +		.policy	= dpll_genl_set_output_policy,
>> > +		.maxattr = ARRAY_SIZE(dpll_genl_set_output_policy) - 1,
>> > +	},
>> > +};
>> > +
>> > +static struct genl_family dpll_gnl_family __ro_after_init = {
>> > +	.hdrsize	= 0,
>> > +	.name		= DPLL_FAMILY_NAME,
>> > +	.version	= DPLL_VERSION,
>> > +	.ops		= dpll_genl_ops,
>> > +	.n_ops		= ARRAY_SIZE(dpll_genl_ops),
>> > +	.mcgrps		= dpll_genl_mcgrps,
>> > +	.n_mcgrps	= ARRAY_SIZE(dpll_genl_mcgrps),
>> > +	.pre_doit	= dpll_pre_doit,
>> 
>> Have  .parallel_ops   = true,
>> You have dpll->lock, you don't need genl, to protect you.
>> 
>
>Yep, sure, thanks!
>
>> 
>> > +};
>> > +
>> > +int __init dpll_netlink_init(void)
>> > +{
>> > +	return genl_register_family(&dpll_gnl_family);
>> > +}
>> > +
>> > +void dpll_netlink_finish(void)
>> > +{
>> > +	genl_unregister_family(&dpll_gnl_family);
>> > +}
>> > +
>> > +void __exit dpll_netlink_fini(void)
>> > +{
>> > +	dpll_netlink_finish();
>> > +}
>> > diff --git a/drivers/dpll/dpll_netlink.h b/drivers/dpll/dpll_netlink.h
>> > new file mode 100644
>> > index 000000000000..e2d100f59dd6
>> > --- /dev/null
>> > +++ b/drivers/dpll/dpll_netlink.h
>> > @@ -0,0 +1,7 @@
>> > +/* SPDX-License-Identifier: GPL-2.0 */
>> > +/*
>> > + *  Copyright (c) 2021 Meta Platforms, Inc. and affiliates
>> > + */
>> > +
>> > +int __init dpll_netlink_init(void);
>> > +void dpll_netlink_finish(void);
>> > diff --git a/include/linux/dpll.h b/include/linux/dpll.h
>> > new file mode 100644
>> > index 000000000000..9d49b19d03d9
>> > --- /dev/null
>> > +++ b/include/linux/dpll.h
>> > @@ -0,0 +1,29 @@
>> > +/* SPDX-License-Identifier: GPL-2.0 */
>> > +/*
>> > + *  Copyright (c) 2021 Meta Platforms, Inc. and affiliates
>> > + */
>> > +
>> > +#ifndef __DPLL_H__
>> > +#define __DPLL_H__
>> > +
>> > +struct dpll_device;
>> > +
>> > +struct dpll_device_ops {
>> > +	int (*get_status)(struct dpll_device *dpll);
>> > +	int (*get_temp)(struct dpll_device *dpll);
>> > +	int (*get_lock_status)(struct dpll_device *dpll);
>> > +	int (*get_source_type)(struct dpll_device *dpll, int id);
>> > +	int (*get_source_supported)(struct dpll_device *dpll, int id, int type);
>> > +	int (*get_output_type)(struct dpll_device *dpll, int id);
>> > +	int (*get_output_supported)(struct dpll_device *dpll, int id, int type);
>> > +	int (*set_source_type)(struct dpll_device *dpll, int id, int val);
>> > +	int (*set_output_type)(struct dpll_device *dpll, int id, int val);
>> 
>> All int should be enums, when they are really enums. Makes things much
>> nicer and easier to see what's what.
>> 
>Yep, will update it.
>> 
>> 
>> > +};
>> > +
>> > +struct dpll_device *dpll_device_alloc(struct dpll_device_ops *ops, const char *name,
>> > +				      int sources_count, int outputs_count, void *priv);
>> > +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);
>> > +#endif
>> > diff --git a/include/uapi/linux/dpll.h b/include/uapi/linux/dpll.h
>> > new file mode 100644
>> > index 000000000000..fcbea5a5e4d6
>> > --- /dev/null
>> > +++ b/include/uapi/linux/dpll.h
>> > @@ -0,0 +1,101 @@
>> > +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
>> > +#ifndef _UAPI_LINUX_DPLL_H
>> > +#define _UAPI_LINUX_DPLL_H
>> > +
>> > +#define DPLL_NAME_LENGTH	20
>> > +
>> > +/* Adding event notification support elements */
>> > +#define DPLL_FAMILY_NAME		"dpll"
>> > +#define DPLL_VERSION			0x01
>> > +#define DPLL_CONFIG_DEVICE_GROUP_NAME  "config"
>> > +#define DPLL_CONFIG_SOURCE_GROUP_NAME  "source"
>> > +#define DPLL_CONFIG_OUTPUT_GROUP_NAME  "output"
>> > +#define DPLL_MONITOR_GROUP_NAME        "monitor"
>> 
>> What is exactly the reason for multiple multicast groups? Why you don't
>> use one?
>> 
>Yes, I agree, there is no need to use multiple groups and I will remove them
>in the next version.
>
>> 
>> > +
>> > +#define DPLL_FLAG_SOURCES	1
>> > +#define DPLL_FLAG_OUTPUTS	2
>> > +#define DPLL_FLAG_STATUS	4
>> 
>> I think it is more common to use either 0x prefix or (1<<X) expression
>> But I don't think these flags are needed at all, if you have per-object
>> messages.
>> 
>> 
>> > +
>> > +/* Attributes of dpll_genl_family */
>> > +enum dpll_genl_attr {
>> 
>> I don't see need for "genl" here.
>> Also, it is common to have consistency betwee enum name and members name.
>> For example:
>> 
>> enum dpll_attr {
>> 	DPLL_ATTR_UNSPEC,
>> 	DPLL_ATTR_DEVICE_ID,
>> 
>> 	...
>> }
>> This applies to all enums in this file.
>> 
>Got it, naming is always hard task. Will update all of them in the next version.
>
>> 
>> > +	DPLLA_UNSPEC,
>> > +	DPLLA_DEVICE_ID,
>> > +	DPLLA_DEVICE_NAME,
>> > +	DPLLA_SOURCE,
>> > +	DPLLA_SOURCE_ID,
>> 
>> "ID" sounds a bit odd. I think "index" would be more suitable.
>> 
>I just wanted to have shorter names to better fit 80 columns per line restrictions.

I think that ID has a bit different semantics. If "INDEX" is too long
for you (not sure why), use "IDX" perhaps?


>> 
>> > +	DPLLA_SOURCE_TYPE,
>> > +	DPLLA_SOURCE_SUPPORTED,
>> > +	DPLLA_OUTPUT,
>> > +	DPLLA_OUTPUT_ID,
>> > +	DPLLA_OUTPUT_TYPE,
>> > +	DPLLA_OUTPUT_SUPPORTED,
>> > +	DPLLA_STATUS,
>> > +	DPLLA_TEMP,
>> > +	DPLLA_LOCK_STATUS,
>> > +	DPLLA_FLAGS,
>> > +
>> > +	__DPLLA_MAX,
>> > +};
>> > +#define DPLLA_MAX (__DPLLA_MAX - 1)
>> > +
>> > +/* DPLL status provides information of device status */
>> > +enum dpll_genl_status {
>> > +	DPLL_STATUS_NONE,
>> > +	DPLL_STATUS_CALIBRATING,
>> > +	DPLL_STATUS_LOCKED,
>> > +
>> > +	__DPLL_STATUS_MAX,
>> > +};
>> > +#define DPLL_STATUS_MAX (__DPLL_STATUS_MAX - 1)
>> > +
>> > +/* DPLL signal types used as source or as output */
>> > +enum dpll_genl_signal_type {
>> > +	DPLL_TYPE_EXT_1PPS,
>> > +	DPLL_TYPE_EXT_10MHZ,
>> > +	DPLL_TYPE_SYNCE_ETH_PORT,
>> > +	DPLL_TYPE_INT_OSCILLATOR,
>> > +	DPLL_TYPE_GNSS,
>> > +
>> > +	__DPLL_TYPE_MAX,
>> > +};
>> > +#define DPLL_TYPE_MAX (__DPLL_TYPE_MAX - 1)
>> > +
>> > +/* DPLL lock status provides information of source used to lock the device */
>> > +enum dpll_genl_lock_status {
>> > +	DPLL_LOCK_STATUS_UNLOCKED,
>> > +	DPLL_LOCK_STATUS_EXT_1PPS,
>> > +	DPLL_LOCK_STATUS_EXT_10MHZ,
>> > +	DPLL_LOCK_STATUS_SYNCE,
>> > +	DPLL_LOCK_STATUS_INT_OSCILLATOR,
>> > +	DPLL_LOCK_STATUS_GNSS,
>> 
>> I find it a bit odd and redundant to have lock status here as a separate
>> enum. You have a souce selected (either autoselected or manualy
>> selected). Then the status is either:
>> "UNLOCKED"
>> "LOCKED"
>> "HOLDOVER"
>> 
>> Or something similar. The point is, don't have the "source type" as a
>> part of lock status.
>> 
>
>Yes, it's a very good idea, I was thinking about the same, but it didn't end
>up in the code.
>
>> 
>> > +
>> > +	__DPLL_LOCK_STATUS_MAX,
>> > +};
>> > +#define DPLL_LOCK_STATUS_MAX (__DPLL_LOCK_STATUS_MAX - 1)
>> > +
>> > +/* Events of dpll_genl_family */
>> > +enum dpll_genl_event {
>> > +	DPLL_EVENT_UNSPEC,
>> > +	DPLL_EVENT_DEVICE_CREATE,		/* DPLL device creation */
>> > +	DPLL_EVENT_DEVICE_DELETE,		/* DPLL device deletion */
>> > +	DPLL_EVENT_STATUS_LOCKED,		/* DPLL device locked to source */
>> > +	DPLL_EVENT_STATUS_UNLOCKED,	/* DPLL device freerun */
>> 
>> Again, redundant I belive. There should be one event,
>> inside the message there should be and ATTR of the lock state.
>> 
>> Also, I believe there are 2 options:
>> 1) follow the existing netlink models and have:
>> DPLL_EVENT_DEVICE_NEW
>>    - sent for new device
>>    - sent for change with device
>> DPLL_EVENT_DEVICE_DEL
>>    - sent for removed device
>> 2)
>> DPLL_EVENT_DEVICE_NEW
>>    - sent for new device
>> DPLL_EVENT_DEVICE_DEL
>>    - sent for removed device
>> DPLL_EVENT_DEVICE_CHANGE
>>    - sent for change with device
>> 
>> Bot options work fine I belive. The point is, you don't want to have
>> "cmd" per one attr change. Changed the device, attrs are passed in one
>> message.
>> 
>
>I will try to change events this way, thanks.
>
>> 
>> 
>> > +	DPLL_EVENT_SOURCE_CHANGE,		/* DPLL device source changed */
>> 
>> Similar here, source of device changed, should be just one attr in
>> device message, see above.
>> 
>
>The WIP right now is going the way to have separate objects representing
>pins, which could be used as source/output or even mux device. And the whole
>part about sources and outputs is going to change. But I'll keep in mind that
>suggestion while implementing this new way.

Yeah, see my suggestion about the pins above. Good to hear that we are
in sync.


>
>> 
>> > +	DPLL_EVENT_OUTPUT_CHANGE,		/* DPLL device output changed */
>> 
>> 
>> > +
>> > +	__DPLL_EVENT_MAX,
>> > +};
>> > +#define DPLL_EVENT_MAX (__DPLL_EVENT_MAX - 1)
>> > +
>> > +/* Commands supported by the dpll_genl_family */
>> > +enum dpll_genl_cmd {
>> > +	DPLL_CMD_UNSPEC,
>> > +	DPLL_CMD_DEVICE_GET,	/* List of DPLL devices id */
>> > +	DPLL_CMD_SET_SOURCE_TYPE,	/* Set the DPLL device source type */
>> 
>> This is confusing, you select "source", not "type".
>
>As I said, we can have different types for one source.

Again, see above my comment suggesting to separate TYPE and SIGNAL.



>
>> 
>> Please be consistent in naming:
>> DPLL_CMD_*_GET/SET
>
>Sure
>
>> 
>> Also, to be consistend with other netlink interfaces, we don't need
>> cmd per action, rather there should be OBJ_GET (can dump) and OBJ_SET
>> commands, like this:
>>     DPLL_CMD_DEVICE_GET (can dump all present devices)
>>     	ATTR_SOURCE_SELECT_MODE (current one)
>>     	ATTR_SOURCE_INDEX (currect one)
>>     DPLL_CMD_DEVICE_SET
>>     	ATTR_SOURCE_INDEX (to set)
>>     DPLL_CMD_DEVICE_SET
>>     	ATTR_SOURCE_SELECT_MODE (to set)
>> 
>
>I believe we have to provide all the possible (or suitable) attributes in SET
>command too, to fully configure the source by one command only, right?

Yep.


>
>And I also think we have to provide special attribute to show which source is
>actually used to sync to, like ATTR_CONNECTED.

Either that or it could be exposed by PERSONALITY set to INPUT of one of
the pins. See my suggestion about pin personalities above.


>
>> 
>> > +	DPLL_CMD_SET_OUTPUT_TYPE,	/* Set the DPLL device output type */
>> 
>> Similar to what I suggested for "source", we should
>> enable to select the OUTPUT, the type should be static. Also instead,
>> I belive we should have a list of outputs and basically just allow
>> enable/disable individual outputs:
>>     DPLL_CMD_OUTPUT_GET (can dump the list of available outputs)
>> 	ATTR_ENABLED (or "CONNECTED" or whatever) of type bool
>>     DPLL_CMD_OUTPUT_SET
>> 	ATTR_ENABLED (or "CONNECTED" or whatever) of type bool
>> 
>> This is suitable for SyncE for example, when you have multiple netdev ports
>> that are connected as "outputs", you can enable exactly those you you want.
>> Example:
>> # To list the available outputs:
>> -> DPLL_CMD_OUTPUT_GET - dump
>>       ATTR_DEVICE_ID X
>> 
>> <- DPLL_CMD_OUTPUT_GET
>>       ATTR_DEVICE_ID X
>>       ATTR_OUTPUT_INDEX 0
>>       ATTR_OUTPUT_TYPE SYNCE_ETH_PORT
>>       ATTR_OUTPUT_NETDEV_IFINDEX 20
>>       ATTR_OUTPUT_ENABLED 0
>>       ATTR_DEVICE_ID X
>>       ATTR_OUTPUT_INDEX 1
>>       ATTR_OUTPUT_TYPE SYNCE_ETH_PORT
>>       ATTR_OUTPUT_NETDEV_IFINDEX 30
>>       ATTR_OUTPUT_ENABLED 0
>> 
>> # Now enable output with index 0
>> -> DPLL_CMD_OUTPUT_SET
>>       ATTR_DEVICE_ID X
>>       ATTR_OUTPUT_INDEX 0
>>       ATTR_OUTPUT_ENABLED 1
>> 
>Well, in case when we have flexible outputs, we can provide this information
>as special type, like DPLL_TYPE_DISABLED. Having other types configured on
>the output will assume that the OUTPUT is enabled.

Either that or it could be configureg by setting the pin PERSONALITY
set to DISCONNECTED See my suggestion about pin personalities above.


>
>> 
>> > +
>> > +	__DPLL_CMD_MAX,
>> > +};
>> > +#define DPLL_CMD_MAX (__DPLL_CMD_MAX - 1)
>> > +
>> > +#endif /* _UAPI_LINUX_DPLL_H */
>> > -- 
>> > 2.27.0
>> > 
>
>Thanks for actionable feedback, I hope to prepare new version soon with all
>the comments and suggestions addressed!

Thanks! Looking forward to it!

>
>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 1/6] dpll: Add DPLL framework base functions
@ 2022-10-11  8:32         ` Jiri Pirko
  0 siblings, 0 replies; 67+ messages in thread
From: Jiri Pirko @ 2022-10-11  8:32 UTC (permalink / raw)
  To: Vadim Fedorenko
  Cc: Jakub Kicinski, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

Mon, Oct 10, 2022 at 09:54:26PM CEST, vfedorenko@novek.ru wrote:
>On 10.10.2022 10:18, Jiri Pirko wrote:
>> Mon, Oct 10, 2022 at 03:17:59AM CEST, vfedorenko@novek.ru wrote:
>> > From: Vadim Fedorenko <vadfed@fb.com>
>> > 
>> > DPLL framework is used to represent and configure DPLL devices
>> > in systems. Each device that has DPLL and can configure sources
>> > and outputs can use this framework.
>> > 
>> > Signed-off-by: Vadim Fedorenko <vadfed@fb.com>
>> > Co-developed-by: Jakub Kicinski <kuba@kernel.org>
>> > Co-developed-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
>> > ---
>> > MAINTAINERS                 |   8 +
>> > drivers/Kconfig             |   2 +
>> > drivers/Makefile            |   1 +
>> > drivers/dpll/Kconfig        |   7 +
>> > drivers/dpll/Makefile       |   7 +
>> > drivers/dpll/dpll_core.c    | 177 +++++++++++++++
>> > drivers/dpll/dpll_core.h    |  41 ++++
>> > drivers/dpll/dpll_netlink.c | 417 ++++++++++++++++++++++++++++++++++++
>> > drivers/dpll/dpll_netlink.h |   7 +
>> > include/linux/dpll.h        |  29 +++
>> > include/uapi/linux/dpll.h   | 101 +++++++++
>> > 11 files changed, 797 insertions(+)
>> > create mode 100644 drivers/dpll/Kconfig
>> > create mode 100644 drivers/dpll/Makefile
>> > create mode 100644 drivers/dpll/dpll_core.c
>> > create mode 100644 drivers/dpll/dpll_core.h
>> > create mode 100644 drivers/dpll/dpll_netlink.c
>> > create mode 100644 drivers/dpll/dpll_netlink.h
>> > create mode 100644 include/linux/dpll.h
>> > create mode 100644 include/uapi/linux/dpll.h
>> > 
>> > diff --git a/MAINTAINERS b/MAINTAINERS
>> > index 9ca84cb5ab4a..e2f4fede937f 100644
>> > --- a/MAINTAINERS
>> > +++ b/MAINTAINERS
>> > @@ -6301,6 +6301,14 @@ F:	Documentation/networking/device_drivers/ethernet/freescale/dpaa2/switch-drive
>> > F:	drivers/net/ethernet/freescale/dpaa2/dpaa2-switch*
>> > F:	drivers/net/ethernet/freescale/dpaa2/dpsw*
>> > 
>> > +DPLL CLOCK SUBSYSTEM
>> > +M:	Vadim Fedorenko <vadfed@fb.com>
>> > +L:	netdev@vger.kernel.org
>> > +S:	Maintained
>> > +F:	drivers/dpll/*
>> > +F:	include/net/dpll.h
>> > +F:	include/uapi/linux/dpll.h
>> > +
>> > DRBD DRIVER
>> > M:	Philipp Reisner <philipp.reisner@linbit.com>
>> > M:	Lars Ellenberg <lars.ellenberg@linbit.com>
>> > diff --git a/drivers/Kconfig b/drivers/Kconfig
>> > index 19ee995bd0ae..a3e00294a995 100644
>> > --- a/drivers/Kconfig
>> > +++ b/drivers/Kconfig
>> > @@ -239,4 +239,6 @@ source "drivers/peci/Kconfig"
>> > 
>> > source "drivers/hte/Kconfig"
>> > 
>> > +source "drivers/dpll/Kconfig"
>> > +
>> > endmenu
>> > diff --git a/drivers/Makefile b/drivers/Makefile
>> > index 057857258bfd..78a68f1621cc 100644
>> > --- a/drivers/Makefile
>> > +++ b/drivers/Makefile
>> > @@ -188,3 +188,4 @@ obj-$(CONFIG_COUNTER)		+= counter/
>> > obj-$(CONFIG_MOST)		+= most/
>> > obj-$(CONFIG_PECI)		+= peci/
>> > obj-$(CONFIG_HTE)		+= hte/
>> > +obj-$(CONFIG_DPLL)		+= dpll/
>> > diff --git a/drivers/dpll/Kconfig b/drivers/dpll/Kconfig
>> > new file mode 100644
>> > index 000000000000..a4cae73f20d3
>> > --- /dev/null
>> > +++ b/drivers/dpll/Kconfig
>> > @@ -0,0 +1,7 @@
>> > +# SPDX-License-Identifier: GPL-2.0-only
>> > +#
>> > +# Generic DPLL drivers configuration
>> > +#
>> > +
>> > +config DPLL
>> > +  bool
>> > diff --git a/drivers/dpll/Makefile b/drivers/dpll/Makefile
>> > new file mode 100644
>> > index 000000000000..0748c80097e4
>> > --- /dev/null
>> > +++ b/drivers/dpll/Makefile
>> > @@ -0,0 +1,7 @@
>> > +# SPDX-License-Identifier: GPL-2.0
>> > +#
>> > +# Makefile for DPLL drivers.
>> > +#
>> > +
>> > +obj-$(CONFIG_DPLL)          += dpll_sys.o
>> > +dpll_sys-y                  += dpll_core.o dpll_netlink.o
>> > diff --git a/drivers/dpll/dpll_core.c b/drivers/dpll/dpll_core.c
>> > new file mode 100644
>> > index 000000000000..7fdee145e82c
>> > --- /dev/null
>> > +++ b/drivers/dpll/dpll_core.c
>> > @@ -0,0 +1,177 @@
>> > +// SPDX-License-Identifier: GPL-2.0
>> > +/*
>> > + *  dpll_core.c - Generic DPLL Management class support.
>> > + *
>> > + *  Copyright (c) 2021 Meta Platforms, Inc. and affiliates
>> > + */
>> > +
>> > +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
>> > +
>> > +#include <linux/device.h>
>> > +#include <linux/err.h>
>> > +#include <linux/slab.h>
>> > +#include <linux/string.h>
>> > +
>> > +#include "dpll_core.h"
>> > +
>> > +static DEFINE_MUTEX(dpll_device_xa_lock);
>> > +static DEFINE_XARRAY_FLAGS(dpll_device_xa, XA_FLAGS_ALLOC);
>> > +#define DPLL_REGISTERED XA_MARK_1
>> > +
>> > +#define ASSERT_DPLL_REGISTERED(d)                                           \
>> > +	WARN_ON_ONCE(!xa_get_mark(&dpll_device_xa, (d)->id, DPLL_REGISTERED))
>> > +#define ASSERT_DPLL_NOT_REGISTERED(d)                                      \
>> > +	WARN_ON_ONCE(xa_get_mark(&dpll_device_xa, (d)->id, DPLL_REGISTERED))
>> > +
>> > +
>> > +int for_each_dpll_device(int id, int (*cb)(struct dpll_device *, void *),
>> > +			 void *data)
>> 
>> Probably better to avoid this "cb" indirection here.
>> Perhaps in a similar way devlinks_xa_for_each_registered_get() is done?
>> 
>Thanks for pointing to an example, I will consider avoid indirection.
>checkpatch.pl is also complaining about this line, but the same way was used in
>some other places that's why I chosed to use it.

Yeah, that does not necessarily mean it is the best practice :)


>> 
>> > +{
>> > +	struct dpll_device *dpll;
>> > +	unsigned long index;
>> > +	int ret = 0;
>> > +
>> > +	mutex_lock(&dpll_device_xa_lock);
>> > +	xa_for_each_start(&dpll_device_xa, index, dpll, id) {
>> > +		if (!xa_get_mark(&dpll_device_xa, index, DPLL_REGISTERED))
>> > +			continue;
>> > +		ret = cb(dpll, data);
>> > +		if (ret)
>> > +			break;
>> > +	}
>> > +	mutex_unlock(&dpll_device_xa_lock);
>> > +
>> > +	return ret;
>> > +}
>> > +
>> > +struct dpll_device *dpll_device_get_by_id(int id)
>> > +{
>> > +	struct dpll_device *dpll = NULL;
>> > +
>> > +	if (xa_get_mark(&dpll_device_xa, id, DPLL_REGISTERED))
>> > +		dpll = xa_load(&dpll_device_xa, id);
>> > +	return dpll;
>> > +}
>> > +
>> > +struct dpll_device *dpll_device_get_by_name(const char *name)
>> > +{
>> > +	struct dpll_device *dpll, *ret = NULL;
>> > +	unsigned long index;
>> > +
>> > +	mutex_lock(&dpll_device_xa_lock);
>> > +	xa_for_each_marked(&dpll_device_xa, index, dpll, DPLL_REGISTERED) {
>> > +		if (!strcmp(dev_name(&dpll->dev), name)) {
>> > +			ret = dpll;
>> > +			break;
>> > +		}
>> > +	}
>> > +	mutex_unlock(&dpll_device_xa_lock);
>> > +
>> > +	return ret;
>> > +}
>> > +
>> > +void *dpll_priv(struct dpll_device *dpll)
>> > +{
>> > +	return dpll->priv;
>> > +}
>> > +EXPORT_SYMBOL_GPL(dpll_priv);
>> > +
>> > +static void dpll_device_release(struct device *dev)
>> > +{
>> > +	struct dpll_device *dpll;
>> > +
>> > +	dpll = to_dpll_device(dev);
>> > +
>> > +	dpll_device_unregister(dpll);
>> > +	dpll_device_free(dpll);
>> > +}
>> > +
>> > +static struct class dpll_class = {
>> > +	.name = "dpll",
>> > +	.dev_release = dpll_device_release,
>> > +};
>> > +
>> > +struct dpll_device *dpll_device_alloc(struct dpll_device_ops *ops, const char *name,
>> > +				      int sources_count, int outputs_count, void *priv)
>> > +{
>> > +	struct dpll_device *dpll;
>> > +	int ret;
>> > +
>> > +	dpll = kzalloc(sizeof(*dpll), GFP_KERNEL);
>> > +	if (!dpll)
>> > +		return ERR_PTR(-ENOMEM);
>> > +
>> > +	mutex_init(&dpll->lock);
>> > +	dpll->ops = ops;
>> > +	dpll->dev.class = &dpll_class;
>> > +	dpll->sources_count = sources_count;
>> > +	dpll->outputs_count = outputs_count;
>> > +
>> > +	mutex_lock(&dpll_device_xa_lock);
>> > +	ret = xa_alloc(&dpll_device_xa, &dpll->id, dpll, xa_limit_16b, GFP_KERNEL);
>> > +	if (ret)
>> > +		goto error;
>> > +	dev_set_name(&dpll->dev, "%s%d", name ? name : "dpll", dpll->id);
>> > +	mutex_unlock(&dpll_device_xa_lock);
>> > +	dpll->priv = priv;
>> > +
>> > +	return dpll;
>> > +
>> > +error:
>> > +	mutex_unlock(&dpll_device_xa_lock);
>> > +	kfree(dpll);
>> > +	return ERR_PTR(ret);
>> > +}
>> > +EXPORT_SYMBOL_GPL(dpll_device_alloc);
>> > +
>> > +void dpll_device_free(struct dpll_device *dpll)
>> > +{
>> > +	if (!dpll)
>> > +		return;
>> > +
>> > +	mutex_destroy(&dpll->lock);
>> > +	kfree(dpll);
>> > +}
>> > +EXPORT_SYMBOL_GPL(dpll_device_free);
>> > +
>> > +void dpll_device_register(struct dpll_device *dpll)
>> > +{
>> > +	ASSERT_DPLL_NOT_REGISTERED(dpll);
>> > +
>> > +	mutex_lock(&dpll_device_xa_lock);
>> > +	xa_set_mark(&dpll_device_xa, dpll->id, DPLL_REGISTERED);
>> > +	mutex_unlock(&dpll_device_xa_lock);
>> > +}
>> > +EXPORT_SYMBOL_GPL(dpll_device_register);
>> > +
>> > +void dpll_device_unregister(struct dpll_device *dpll)
>> > +{
>> > +	ASSERT_DPLL_REGISTERED(dpll);
>> > +
>> > +	mutex_lock(&dpll_device_xa_lock);
>> > +	xa_erase(&dpll_device_xa, dpll->id);
>> > +	mutex_unlock(&dpll_device_xa_lock);
>> > +}
>> > +EXPORT_SYMBOL_GPL(dpll_device_unregister);
>> > +
>> > +static int __init dpll_init(void)
>> > +{
>> > +	int ret;
>> > +
>> > +	ret = dpll_netlink_init();
>> > +	if (ret)
>> > +		goto error;
>> > +
>> > +	ret = class_register(&dpll_class);
>> > +	if (ret)
>> > +		goto unregister_netlink;
>> > +
>> > +	return 0;
>> > +
>> > +unregister_netlink:
>> > +	dpll_netlink_finish();
>> > +error:
>> > +	mutex_destroy(&dpll_device_xa_lock);
>> > +	return ret;
>> > +}
>> > +subsys_initcall(dpll_init);
>> > diff --git a/drivers/dpll/dpll_core.h b/drivers/dpll/dpll_core.h
>> > new file mode 100644
>> > index 000000000000..4b6fc9eb228f
>> > --- /dev/null
>> > +++ b/drivers/dpll/dpll_core.h
>> > @@ -0,0 +1,41 @@
>> > +/* SPDX-License-Identifier: GPL-2.0 */
>> > +/*
>> > + *  Copyright (c) 2021 Meta Platforms, Inc. and affiliates
>> > + */
>> > +
>> > +#ifndef __DPLL_CORE_H__
>> > +#define __DPLL_CORE_H__
>> > +
>> > +#include <linux/dpll.h>
>> > +
>> > +#include "dpll_netlink.h"
>> > +
>> > +/**
>> > + * struct dpll_device - structure for a DPLL device
>> > + * @id:		unique id number for each edvice
>> > + * @dev:	&struct device for this dpll device
>> > + * @sources_count:	amount of input sources this dpll_device supports
>> > + * @outputs_count:	amount of outputs this dpll_device supports
>> > + * @ops:	operations this &dpll_device supports
>> > + * @lock:	mutex to serialize operations
>> > + * @priv:	pointer to private information of owner
>> > + */
>> > +struct dpll_device {
>> > +	int id;
>> > +	struct device dev;
>> > +	int sources_count;
>> > +	int outputs_count;
>> > +	struct dpll_device_ops *ops;
>> > +	struct mutex lock;
>> > +	void *priv;
>> > +};
>> > +
>> > +#define to_dpll_device(_dev) \
>> > +	container_of(_dev, struct dpll_device, dev)
>> > +
>> > +int for_each_dpll_device(int id, int (*cb)(struct dpll_device *, void *),
>> > +			  void *data);
>> > +struct dpll_device *dpll_device_get_by_id(int id);
>> > +struct dpll_device *dpll_device_get_by_name(const char *name);
>> > +void dpll_device_unregister(struct dpll_device *dpll);
>> > +#endif
>> > diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c
>> > new file mode 100644
>> > index 000000000000..31966e0eec3a
>> > --- /dev/null
>> > +++ b/drivers/dpll/dpll_netlink.c
>> > @@ -0,0 +1,417 @@
>> > +// SPDX-License-Identifier: GPL-2.0
>> > +/*
>> > + * Generic netlink for DPLL management framework
>> > + *
>> > + * Copyright (c) 2021 Meta Platforms, Inc. and affiliates
>> > + *
>> > + */
>> > +#include <linux/module.h>
>> > +#include <linux/kernel.h>
>> > +#include <net/genetlink.h>
>> > +#include "dpll_core.h"
>> > +
>> > +#include <uapi/linux/dpll.h>
>> > +
>> > +static const struct genl_multicast_group dpll_genl_mcgrps[] = {
>> > +	{ .name = DPLL_CONFIG_DEVICE_GROUP_NAME, },
>> > +	{ .name = DPLL_CONFIG_SOURCE_GROUP_NAME, },
>> > +	{ .name = DPLL_CONFIG_OUTPUT_GROUP_NAME, },
>> > +	{ .name = DPLL_MONITOR_GROUP_NAME,  },
>> > +};
>> > +
>> > +static const struct nla_policy dpll_genl_get_policy[] = {
>> > +	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
>> > +	[DPLLA_DEVICE_NAME]	= { .type = NLA_STRING,
>> > +				    .len = DPLL_NAME_LENGTH },
>> > +	[DPLLA_FLAGS]		= { .type = NLA_U32 },
>> > +};
>> > +
>> > +static const struct nla_policy dpll_genl_set_source_policy[] = {
>> > +	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
>> > +	[DPLLA_SOURCE_ID]	= { .type = NLA_U32 },
>> > +	[DPLLA_SOURCE_TYPE]	= { .type = NLA_U32 },
>> > +};
>> > +
>> > +static const struct nla_policy dpll_genl_set_output_policy[] = {
>> > +	[DPLLA_DEVICE_ID]	= { .type = NLA_U32 },
>> > +	[DPLLA_OUTPUT_ID]	= { .type = NLA_U32 },
>> > +	[DPLLA_OUTPUT_TYPE]	= { .type = NLA_U32 },
>> > +};
>> > +
>> > +struct param {
>> 
>> Namespace prefix please	.
>> 
>Yep, will add.
>> 
>> > +	struct netlink_callback *cb;
>> > +	struct dpll_device *dpll;
>> > +	struct sk_buff *msg;
>> 
>> 
>> 
>> > +	int dpll_id;
>> > +	int dpll_source_id;
>> > +	int dpll_source_type;
>> > +	int dpll_output_id;
>> > +	int dpll_output_type;
>> 
>> I don't see where you use these 5.
>> 
>Yep, the implementation was improved, it looks like it's artifacts of the
>previous version.
>
>> 
>> > +};
>> > +
>> > +struct dpll_dump_ctx {
>> > +	struct dpll_device *dev;
>> > +	int flags;
>> > +	int pos_idx;
>> 
>> 
>> 
>> > +	int pos_src_idx;
>> > +	int pos_out_idx;
>> 
>> You don't use these 2.
>> 
>
>The same again, artifacts.
>
>> 
>> > +};
>> > +
>> > +typedef int (*cb_t)(struct param *);
>> > +
>> > +static struct genl_family dpll_gnl_family;
>> > +
>> > +static struct dpll_dump_ctx *dpll_dump_context(struct netlink_callback *cb)
>> > +{
>> > +	return (struct dpll_dump_ctx *)cb->ctx;
>> > +}
>> > +
>> > +static int __dpll_cmd_device_dump_one(struct dpll_device *dpll,
>> > +					   struct sk_buff *msg)
>> > +{
>> > +	if (nla_put_u32(msg, DPLLA_DEVICE_ID, dpll->id))
>> > +		return -EMSGSIZE;
>> > +
>> > +	if (nla_put_string(msg, DPLLA_DEVICE_NAME, dev_name(&dpll->dev)))
>> > +		return -EMSGSIZE;
>> > +
>> > +	return 0;
>> > +}
>> > +
>> > +static int __dpll_cmd_dump_sources(struct dpll_device *dpll,
>> > +					   struct sk_buff *msg)
>> > +{
>> > +	struct nlattr *src_attr;
>> > +	int i, ret = 0, type;
>> > +
>> > +	for (i = 0; i < dpll->sources_count; i++) {
>> > +		src_attr = nla_nest_start(msg, DPLLA_SOURCE);
>> > +		if (!src_attr) {
>> > +			ret = -EMSGSIZE;
>> > +			break;
>> > +		}
>> > +		type = dpll->ops->get_source_type(dpll, i);
>> > +		if (nla_put_u32(msg, DPLLA_SOURCE_ID, i) ||
>> > +		    nla_put_u32(msg, DPLLA_SOURCE_TYPE, type)) {
>> > +			nla_nest_cancel(msg, src_attr);
>> > +			ret = -EMSGSIZE;
>> > +			break;
>> > +		}
>> > +		if (dpll->ops->get_source_supported) {
>> > +			for (type = 0; type <= DPLL_TYPE_MAX; type++) {
>> > +				ret = dpll->ops->get_source_supported(dpll, i, type);
>> 
>> Okay, this looks weird to me. This implicates that it is possible to
>> have for example:
>> source index 0 of type 10
>> source index 0 of type 11
>> Both possible.
>> 
>> However, from how I understand this, each source if of certain fixed type.
>> Either it is:
>> SyncE port
>> 1pps external input (SMA)
>> 10MHZ external input (SMA)
>> internal oscilator (free-running)
>> GNSS (GPS)
>> 
>> So for example:
>> index 0, type: 1pps external input (SMA)
>> index 1, type: 10MHZ external input (
>> index 2, type: SyncE port, netdev ifindex: 20
>> index 3, type: SyncE port, netdev ifindex: 30
>> 
>> So 4 "source" objects, each of different type.
>> In this case I can imagine that the netlink API might look something
>> like:
>> -> DPLL_CMD_SOURCE_GET - dump
>>       ATTR_DEVICE_ID X
>> 
>> <- DPLL_CMD_SOURCE_GET
>> 
>>       ATTR_DEVICE_ID X
>>       ATTR_SOURCE_INDEX 0
>>       ATTR_SOURCE_TYPE EXT_1PPS
>>       ATTR_DEVICE_ID X
>>       ATTR_SOURCE_INDEX 1
>>       ATTR_SOURCE_TYPE EXT_10MHZ
>>       ATTR_DEVICE_ID X
>>       ATTR_SOURCE_INDEX 2
>>       ATTR_SOURCE_TYPE SYNCE_ETH_PORT
>>       ATTR_SOURCE_NETDEV_IFINDEX 20
>> 
>>       ATTR_DEVICE_ID X
>>       ATTR_SOURCE_INDEX 3
>>       ATTR_SOURCE_TYPE SYNCE_ETH_PORT
>>       ATTR_SOURCE_NETDEV_IFINDEX 30
>> 
>> You see kernel would dump 4 source objects.
>> 
>I see your point. We do have hardware which allows changing type of SMA
>connector, and even the direction, each SMA could be used as input/source or
>output of different signals. But there are limitation, like not all SMAs can
>produce IRIG-B signal or only some of them can be used to get GNSS 1PPS. The

Okay, so that is not the *type* of source, but rather attribute of it.
Example:

$ dpll X show
index 0
  type EXT
  signal 1PPS
  supported_signals
     1PPS 10MHz

$ dpll X set source index 1 signal_type 10MHz
$ dpll X show
index 0
  type EXT
  signal 10MHz
  supported_signals
     1PPS 10MHz

So one source with index 0 of type "EXT" (could be "SMA", does not
matter) supports 1 signal types.


Thinking about this more and to cover the case when one SMA could be
potencially used for input and output. It already occured to me that
source/output are quite similar, have similar/same attributes. What if
they are merged together to say a "pin" object only with extra
PERSONALITY attribute?

Example:

-> DPLL_CMD_PIN_GET - dump
      ATTR_DEVICE_ID X

<- DPLL_CMD_PIN_GET

       ATTR_DEVICE_ID X
       ATTR_PIN_INDEX 0
       ATTR_PIN_TYPE EXT
       ATTR_PIN_SIGNAL 1PPS   (selected signal)
       ATTR_PIN_SUPPORTED_SIGNALS (nest)
         ATTR_PIN_SIGNAL 1PPS
         ATTR_PIN_SIGNAL 10MHZ
       ATTR_PIN_PERSONALITY OUTPUT   (selected personality)
       ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
         ATTR_PIN_PERSONALITY DISCONNECTED
         ATTR_PIN_PERSONALITY INPUT
         ATTR_PIN_PERSONALITY OUTPUT     (note this supports both input and
					  output)

       ATTR_DEVICE_ID X
       ATTR_PIN_INDEX 1
       ATTR_PIN_TYPE EXT
       ATTR_PIN_SIGNAL 10MHz   (selected signal)
       ATTR_PIN_SUPPORTED_SIGNALS (nest)
         ATTR_PIN_SIGNAL 1PPS
         ATTR_PIN_SIGNAL 10MHZ
       ATTR_PIN_PERSONALITY DISCONNECTED   (selected personality - not
					    connected currently)
       ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
         ATTR_PIN_PERSONALITY DISCONNECTED
         ATTR_PIN_PERSONALITY INPUT      (note this supports only input)

       ATTR_DEVICE_ID X
       ATTR_PIN_INDEX 2
       ATTR_PIN_TYPE GNSS
       ATTR_PIN_SIGNAL 1PPS   (selected signal)
       ATTR_PIN_SUPPORTED_SIGNALS (nest)
         ATTR_PIN_SIGNAL 1PPS
       ATTR_PIN_PERSONALITY INPUT   (selected personality - note this is
				     now he selected source, being only
				     pin with INPUT personality)
       ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
         ATTR_PIN_PERSONALITY DISCONNECTED
         ATTR_PIN_PERSONALITY INPUT      (note this supports only input)

       ATTR_DEVICE_ID X
       ATTR_PIN_INDEX 3
       ATTR_PIN_TYPE SYNCE_ETH_PORT
       ATTR_PIN_NETDEV_IFINDEX 20
       ATTR_PIN_PERSONALITY OUTPUT   (selected personality)
       ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
         ATTR_PIN_PERSONALITY DISCONNECTED
         ATTR_PIN_PERSONALITY INPUT
         ATTR_PIN_PERSONALITY OUTPUT     (note this supports both input and
					  output)

       ATTR_DEVICE_ID X
       ATTR_PIN_INDEX 4
       ATTR_PIN_TYPE SYNCE_ETH_PORT
       ATTR_PIN_NETDEV_IFINDEX 30
       ATTR_PIN_PERSONALITY OUTPUT   (selected personality)
       ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
         ATTR_PIN_PERSONALITY DISCONNECTED
         ATTR_PIN_PERSONALITY INPUT
         ATTR_PIN_PERSONALITY OUTPUT     (note this supports both input and
					  output)


This allows the user to actually see the full picture:
1) all input/output pins in a single list, no duplicates
2) each pin if of certain type (ATTR_PIN_TYPE) EXT/GNSS/SYNCE_ETH_PORT
3) the pins that can change signal type contain the selected and list of
   supported signal types (ATTR_PIN_SIGNAL, ATTR_PIN_SUPPORTED_SIGNALS)
4) direction/connection of the pin to the DPLL is exposed over
   ATTR_PIN_PERSONALITY. For each pin, the driver would expose it can
   act as INPUT/OUTPUT and even more, it can indicate the pin can
   disconnect from DPLL entirely (if possible).
5) user can select the source by setting ATTR_PIN_PERSONALITY of certain
   pin to INPUT. Only one pin could be set to INPUT and that is the
   souce of DPLL.
   In case no pin have personality set to INPUT, the DPLL is
   free-running.

This would introduce quite nice flexibility, exposes source/output
capabilities and provides good visilibity of current configuration.


>interface was created to cover such case. I believe we have to improve it to
>cover SyncE configuration better, but I personally don't have SyncE hardware
>ready to test and that's why I have to rely on suggestions from yours or
>Arkadiusz's experience. From what I can see now there is need for special
>attribute to link source to net device, and I'm happy to add it. In case of
>fixed configuration of sources, the device should provide only one type as
>supported and that's it.
>
>
>> 
>> 
>> > +				if (ret && nla_put_u32(msg, DPLLA_SOURCE_SUPPORTED, type)) {
>> > +					ret = -EMSGSIZE;
>> > +					break;
>> > +				}
>> > +			}
>> > +			ret = 0;
>> > +		}
>> > +		nla_nest_end(msg, src_attr);
>> > +	}
>> > +
>> > +	return ret;
>> > +}
>> > +
>> > +static int __dpll_cmd_dump_outputs(struct dpll_device *dpll,
>> > +					   struct sk_buff *msg)
>> > +{
>> > +	struct nlattr *out_attr;
>> > +	int i, ret = 0, type;
>> > +
>> > +	for (i = 0; i < dpll->outputs_count; i++) {
>> > +		out_attr = nla_nest_start(msg, DPLLA_OUTPUT);
>> > +		if (!out_attr) {
>> > +			ret = -EMSGSIZE;
>> > +			break;
>> > +		}
>> > +		type = dpll->ops->get_output_type(dpll, i);
>> > +		if (nla_put_u32(msg, DPLLA_OUTPUT_ID, i) ||
>> > +		    nla_put_u32(msg, DPLLA_OUTPUT_TYPE, type)) {
>> > +			nla_nest_cancel(msg, out_attr);
>> > +			ret = -EMSGSIZE;
>> > +			break;
>> > +		}
>> > +		if (dpll->ops->get_output_supported) {
>> > +			for (type = 0; type <= DPLL_TYPE_MAX; type++) {
>> > +				ret = dpll->ops->get_output_supported(dpll, i, type);
>> > +				if (ret && nla_put_u32(msg, DPLLA_OUTPUT_SUPPORTED, type)) {
>> 
>> This I believe is similar to sources, see my comment above.
>> 
>As I said, we have to cover the case when SMAs are flexible to configure.
>
>> I believe we should have separate commands to GET and SET outputs and
>> sources. That would make the object separation clear and will also help
>> event model. See below I suggestion how output netlink API may look
>> like (comment in header file near enum dpll_genl_cmd definition).
>> 
>> 
>> > +					ret = -EMSGSIZE;
>> > +					break;
>> > +				}
>> > +			}
>> > +			ret = 0;
>> > +		}
>> > +		nla_nest_end(msg, out_attr);
>> > +	}
>> > +
>> > +	return ret;
>> > +}
>> > +
>> > +static int __dpll_cmd_dump_status(struct dpll_device *dpll,
>> > +					   struct sk_buff *msg)
>> > +{
>> > +	int ret;
>> > +
>> > +	if (dpll->ops->get_status) {
>> > +		ret = dpll->ops->get_status(dpll);
>> > +		if (nla_put_u32(msg, DPLLA_STATUS, ret))
>> > +			return -EMSGSIZE;
>> > +	}
>> > +
>> > +	if (dpll->ops->get_temp) {
>> > +		ret = dpll->ops->get_temp(dpll);
>> > +		if (nla_put_u32(msg, DPLLA_TEMP, ret))
>> > +			return -EMSGSIZE;
>> > +	}
>> > +
>> > +	if (dpll->ops->get_lock_status) {
>> > +		ret = dpll->ops->get_lock_status(dpll);
>> > +		if (nla_put_u32(msg, DPLLA_LOCK_STATUS, ret))
>> > +			return -EMSGSIZE;
>> > +	}
>> > +
>> > +	return 0;
>> > +}
>> > +
>> > +static int
>> > +dpll_device_dump_one(struct dpll_device *dpll, struct sk_buff *msg,
>> > +		     u32 portid, u32 seq, int flags)
>> > +{
>> > +	struct nlattr *hdr;
>> > +	int ret;
>> > +
>> > +	hdr = genlmsg_put(msg, portid, seq, &dpll_gnl_family, 0,
>> > +			  DPLL_CMD_DEVICE_GET);
>> > +	if (!hdr)
>> > +		return -EMSGSIZE;
>> > +
>> > +	mutex_lock(&dpll->lock);
>> > +	ret = __dpll_cmd_device_dump_one(dpll, msg);
>> > +	if (ret)
>> > +		goto out_unlock;
>> > +
>> > +	if (flags & DPLL_FLAG_SOURCES && dpll->ops->get_source_type) {
>> > +		ret = __dpll_cmd_dump_sources(dpll, msg);
>> > +		if (ret)
>> > +			goto out_unlock;
>> > +	}
>> > +
>> > +	if (flags & DPLL_FLAG_OUTPUTS && dpll->ops->get_output_type) {
>> > +		ret = __dpll_cmd_dump_outputs(dpll, msg);
>> > +		if (ret)
>> > +			goto out_unlock;
>> > +	}
>> > +
>> > +	if (flags & DPLL_FLAG_STATUS) {
>> > +		ret = __dpll_cmd_dump_status(dpll, msg);
>> > +		if (ret)
>> > +			goto out_unlock;
>> > +	}
>> > +	mutex_unlock(&dpll->lock);
>> > +	genlmsg_end(msg, hdr);
>> > +
>> > +	return 0;
>> > +
>> > +out_unlock:
>> > +	mutex_unlock(&dpll->lock);
>> > +	genlmsg_cancel(msg, hdr);
>> > +
>> > +	return ret;
>> > +}
>> > +
>> > +static int dpll_genl_cmd_set_source(struct sk_buff *skb, struct genl_info *info)
>> > +{
>> > +	struct dpll_device *dpll = info->user_ptr[0];
>> > +	struct nlattr **attrs = info->attrs;
>> > +	int ret = 0, src_id, type;
>> 
>> Enums.
>> 
>
>Sure.
>
>> > +
>> > +	if (!attrs[DPLLA_SOURCE_ID] ||
>> > +	    !attrs[DPLLA_SOURCE_TYPE])
>> > +		return -EINVAL;
>> > +
>> > +	if (!dpll->ops->set_source_type)
>> > +		return -EOPNOTSUPP;
>> > +
>> > +	src_id = nla_get_u32(attrs[DPLLA_SOURCE_ID]);
>> > +	type = nla_get_u32(attrs[DPLLA_SOURCE_TYPE]);
>> 
>> 
>> This looks odd to me. The user should just pass the index of source to
>> select. Type should be static, and non-changeable.
>> 
>> 
>> > +
>> > +	mutex_lock(&dpll->lock);
>> > +	ret = dpll->ops->set_source_type(dpll, src_id, type);
>> > +	mutex_unlock(&dpll->lock);
>> > +
>> > +	return ret;
>> > +}
>> > +
>> > +static int dpll_genl_cmd_set_output(struct sk_buff *skb, struct genl_info *info)
>> > +{
>> > +	struct dpll_device *dpll = info->user_ptr[0];
>> > +	struct nlattr **attrs = info->attrs;
>> > +	int ret = 0, out_id, type;
>> 
>> Enums.
>> 
>> 
>> > +
>> > +	if (!attrs[DPLLA_OUTPUT_ID] ||
>> > +	    !attrs[DPLLA_OUTPUT_TYPE])
>> > +		return -EINVAL;
>> > +
>> > +	if (!dpll->ops->set_output_type)
>> > +		return -EOPNOTSUPP;
>> > +
>> > +	out_id = nla_get_u32(attrs[DPLLA_OUTPUT_ID]);
>> > +	type = nla_get_u32(attrs[DPLLA_OUTPUT_TYPE]);
>> 
>> Same here, passing type here looks wrong.
>> 
>> 
>> 
>> > +
>> > +	mutex_lock(&dpll->lock);
>> > +	ret = dpll->ops->set_output_type(dpll, out_id, type);
>> > +	mutex_unlock(&dpll->lock);
>> > +
>> > +	return ret;
>> > +}
>> > +
>> > +static int dpll_device_loop_cb(struct dpll_device *dpll, void *data)
>> > +{
>> > +	struct dpll_dump_ctx *ctx;
>> > +	struct param *p = (struct param *)data;
>> > +
>> > +	ctx = dpll_dump_context(p->cb);
>> > +
>> > +	ctx->pos_idx = dpll->id;
>> > +
>> > +	return dpll_device_dump_one(dpll, p->msg, 0, 0, ctx->flags);
>> > +}
>> > +
>> > +static int
>> > +dpll_cmd_device_dump(struct sk_buff *skb, struct netlink_callback *cb)
>> > +{
>> > +	struct dpll_dump_ctx *ctx = dpll_dump_context(cb);
>> > +	struct param p = { .cb = cb, .msg = skb };
>> > +
>> > +	return for_each_dpll_device(ctx->pos_idx, dpll_device_loop_cb, &p);
>> > +}
>> > +
>> > +static int
>> > +dpll_genl_cmd_device_get_id(struct sk_buff *skb, struct genl_info *info)
>> 
>> Just "get", no "id" here.
>> 
>
>Got it.
>
>> 
>> > +{
>> > +	struct dpll_device *dpll = info->user_ptr[0];
>> > +	struct nlattr **attrs = info->attrs;
>> > +	struct sk_buff *msg;
>> > +	int flags = 0;
>> > +	int ret;
>> > +
>> > +	if (attrs[DPLLA_FLAGS])
>> > +		flags = nla_get_u32(attrs[DPLLA_FLAGS]);
>> > +
>> > +	msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
>> > +	if (!msg)
>> > +		return -ENOMEM;
>> > +
>> > +	ret = dpll_device_dump_one(dpll, msg, info->snd_portid, info->snd_seq,
>> > +				   flags);
>> > +	if (ret)
>> > +		goto out_free_msg;
>> > +
>> > +	return genlmsg_reply(msg, info);
>> > +
>> > +out_free_msg:
>> > +	nlmsg_free(msg);
>> > +	return ret;
>> > +
>> > +}
>> > +
>> > +static int dpll_genl_cmd_start(struct netlink_callback *cb)
>> > +{
>> > +	const struct genl_dumpit_info *info = genl_dumpit_info(cb);
>> > +	struct dpll_dump_ctx *ctx = dpll_dump_context(cb);
>> > +
>> > +	ctx->dev = NULL;
>> > +	if (info->attrs[DPLLA_FLAGS])
>> > +		ctx->flags = nla_get_u32(info->attrs[DPLLA_FLAGS]);
>> > +	else
>> > +		ctx->flags = 0;
>> > +	ctx->pos_idx = 0;
>> > +	ctx->pos_src_idx = 0;
>> > +	ctx->pos_out_idx = 0;
>> > +	return 0;
>> > +}
>> > +
>> > +static int dpll_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
>> > +						 struct genl_info *info)
>> > +{
>> > +	struct dpll_device *dpll_id = NULL, *dpll_name = NULL;
>> > +
>> > +	if (!info->attrs[DPLLA_DEVICE_ID] &&
>> > +	    !info->attrs[DPLLA_DEVICE_NAME])
>> > +		return -EINVAL;
>> > +
>> > +	if (info->attrs[DPLLA_DEVICE_ID]) {
>> > +		u32 id = nla_get_u32(info->attrs[DPLLA_DEVICE_ID]);
>> > +
>> > +		dpll_id = dpll_device_get_by_id(id);
>> > +		if (!dpll_id)
>> > +			return -ENODEV;
>> > +		info->user_ptr[0] = dpll_id;
>> 
>> struct dpll_device *dpll should be stored here.
>> 
>> 
>> > +	}
>> > +	if (info->attrs[DPLLA_DEVICE_NAME]) {
>> 
>> You define new API, have one clear handle for devices. Either name or
>> ID. Having both is messy.
>> 
>That was added after the discussion with Jakub and Arkadiusz where we agreed
>that the device could be referenced either by index or by name. The example
>is that userspace app can easily find specific DPLL device if it knows the
>name provided by a driver of that specific device. Without searching through
>sysfs to find index value. Later commands could be executed using index once
>it's known through CMD_GET_DEVICE/ATTR_DEVICE_NAME.

What exacly is the name? What is the semantics? How the name is
generated in case of multiple instances of the same driver. What happens
if two drivers use the same name? Is the name predictable (in sense of
"stable over reboots")?


>> 
>> > +		const char *name = nla_data(info->attrs[DPLLA_DEVICE_NAME]);
>> > +
>> > +		dpll_name = dpll_device_get_by_name(name);
>> > +		if (!dpll_name)
>> > +			return -ENODEV;
>> > +
>> > +		if (dpll_id && dpll_name != dpll_id)
>> > +			return -EINVAL;
>> > +		info->user_ptr[0] = dpll_name;
>> 
>> struct dpll_device *dpll should be stored here.
>> 
>
>
>Didn't get you, where should we store it?
>dpll_name and dpll_id are of type struct dpll_device*,

Ah sorry, you confused me with the "name"/"id" suffix. Why you don't
have just one variable called "dpll" instead and have the check for both
attrs being set at the beginning? Also, extack error message would be
nice (not only here).


>and they are compared to avoid situation when both index and name are
>provided, but refer to different devices.
>
>> 
>> 
>> > +	}
>> > +
>> > +	return 0;
>> > +}
>> > +
>> > +static const struct genl_ops dpll_genl_ops[] = {
>> > +	{
>> > +		.cmd	= DPLL_CMD_DEVICE_GET,
>> > +		.flags  = GENL_UNS_ADMIN_PERM,
>> > +		.start	= dpll_genl_cmd_start,
>> > +		.dumpit	= dpll_cmd_device_dump,
>> > +		.doit	= dpll_genl_cmd_device_get_id,
>> > +		.policy	= dpll_genl_get_policy,
>> > +		.maxattr = ARRAY_SIZE(dpll_genl_get_policy) - 1,
>> > +	},
>> > +	{
>> > +		.cmd	= DPLL_CMD_SET_SOURCE_TYPE,
>> > +		.flags	= GENL_UNS_ADMIN_PERM,
>> > +		.doit	= dpll_genl_cmd_set_source,
>> > +		.policy	= dpll_genl_set_source_policy,
>> > +		.maxattr = ARRAY_SIZE(dpll_genl_set_source_policy) - 1,
>> > +	},
>> > +	{
>> > +		.cmd	= DPLL_CMD_SET_OUTPUT_TYPE,
>> > +		.flags	= GENL_UNS_ADMIN_PERM,
>> > +		.doit	= dpll_genl_cmd_set_output,
>> > +		.policy	= dpll_genl_set_output_policy,
>> > +		.maxattr = ARRAY_SIZE(dpll_genl_set_output_policy) - 1,
>> > +	},
>> > +};
>> > +
>> > +static struct genl_family dpll_gnl_family __ro_after_init = {
>> > +	.hdrsize	= 0,
>> > +	.name		= DPLL_FAMILY_NAME,
>> > +	.version	= DPLL_VERSION,
>> > +	.ops		= dpll_genl_ops,
>> > +	.n_ops		= ARRAY_SIZE(dpll_genl_ops),
>> > +	.mcgrps		= dpll_genl_mcgrps,
>> > +	.n_mcgrps	= ARRAY_SIZE(dpll_genl_mcgrps),
>> > +	.pre_doit	= dpll_pre_doit,
>> 
>> Have  .parallel_ops   = true,
>> You have dpll->lock, you don't need genl, to protect you.
>> 
>
>Yep, sure, thanks!
>
>> 
>> > +};
>> > +
>> > +int __init dpll_netlink_init(void)
>> > +{
>> > +	return genl_register_family(&dpll_gnl_family);
>> > +}
>> > +
>> > +void dpll_netlink_finish(void)
>> > +{
>> > +	genl_unregister_family(&dpll_gnl_family);
>> > +}
>> > +
>> > +void __exit dpll_netlink_fini(void)
>> > +{
>> > +	dpll_netlink_finish();
>> > +}
>> > diff --git a/drivers/dpll/dpll_netlink.h b/drivers/dpll/dpll_netlink.h
>> > new file mode 100644
>> > index 000000000000..e2d100f59dd6
>> > --- /dev/null
>> > +++ b/drivers/dpll/dpll_netlink.h
>> > @@ -0,0 +1,7 @@
>> > +/* SPDX-License-Identifier: GPL-2.0 */
>> > +/*
>> > + *  Copyright (c) 2021 Meta Platforms, Inc. and affiliates
>> > + */
>> > +
>> > +int __init dpll_netlink_init(void);
>> > +void dpll_netlink_finish(void);
>> > diff --git a/include/linux/dpll.h b/include/linux/dpll.h
>> > new file mode 100644
>> > index 000000000000..9d49b19d03d9
>> > --- /dev/null
>> > +++ b/include/linux/dpll.h
>> > @@ -0,0 +1,29 @@
>> > +/* SPDX-License-Identifier: GPL-2.0 */
>> > +/*
>> > + *  Copyright (c) 2021 Meta Platforms, Inc. and affiliates
>> > + */
>> > +
>> > +#ifndef __DPLL_H__
>> > +#define __DPLL_H__
>> > +
>> > +struct dpll_device;
>> > +
>> > +struct dpll_device_ops {
>> > +	int (*get_status)(struct dpll_device *dpll);
>> > +	int (*get_temp)(struct dpll_device *dpll);
>> > +	int (*get_lock_status)(struct dpll_device *dpll);
>> > +	int (*get_source_type)(struct dpll_device *dpll, int id);
>> > +	int (*get_source_supported)(struct dpll_device *dpll, int id, int type);
>> > +	int (*get_output_type)(struct dpll_device *dpll, int id);
>> > +	int (*get_output_supported)(struct dpll_device *dpll, int id, int type);
>> > +	int (*set_source_type)(struct dpll_device *dpll, int id, int val);
>> > +	int (*set_output_type)(struct dpll_device *dpll, int id, int val);
>> 
>> All int should be enums, when they are really enums. Makes things much
>> nicer and easier to see what's what.
>> 
>Yep, will update it.
>> 
>> 
>> > +};
>> > +
>> > +struct dpll_device *dpll_device_alloc(struct dpll_device_ops *ops, const char *name,
>> > +				      int sources_count, int outputs_count, void *priv);
>> > +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);
>> > +#endif
>> > diff --git a/include/uapi/linux/dpll.h b/include/uapi/linux/dpll.h
>> > new file mode 100644
>> > index 000000000000..fcbea5a5e4d6
>> > --- /dev/null
>> > +++ b/include/uapi/linux/dpll.h
>> > @@ -0,0 +1,101 @@
>> > +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
>> > +#ifndef _UAPI_LINUX_DPLL_H
>> > +#define _UAPI_LINUX_DPLL_H
>> > +
>> > +#define DPLL_NAME_LENGTH	20
>> > +
>> > +/* Adding event notification support elements */
>> > +#define DPLL_FAMILY_NAME		"dpll"
>> > +#define DPLL_VERSION			0x01
>> > +#define DPLL_CONFIG_DEVICE_GROUP_NAME  "config"
>> > +#define DPLL_CONFIG_SOURCE_GROUP_NAME  "source"
>> > +#define DPLL_CONFIG_OUTPUT_GROUP_NAME  "output"
>> > +#define DPLL_MONITOR_GROUP_NAME        "monitor"
>> 
>> What is exactly the reason for multiple multicast groups? Why you don't
>> use one?
>> 
>Yes, I agree, there is no need to use multiple groups and I will remove them
>in the next version.
>
>> 
>> > +
>> > +#define DPLL_FLAG_SOURCES	1
>> > +#define DPLL_FLAG_OUTPUTS	2
>> > +#define DPLL_FLAG_STATUS	4
>> 
>> I think it is more common to use either 0x prefix or (1<<X) expression
>> But I don't think these flags are needed at all, if you have per-object
>> messages.
>> 
>> 
>> > +
>> > +/* Attributes of dpll_genl_family */
>> > +enum dpll_genl_attr {
>> 
>> I don't see need for "genl" here.
>> Also, it is common to have consistency betwee enum name and members name.
>> For example:
>> 
>> enum dpll_attr {
>> 	DPLL_ATTR_UNSPEC,
>> 	DPLL_ATTR_DEVICE_ID,
>> 
>> 	...
>> }
>> This applies to all enums in this file.
>> 
>Got it, naming is always hard task. Will update all of them in the next version.
>
>> 
>> > +	DPLLA_UNSPEC,
>> > +	DPLLA_DEVICE_ID,
>> > +	DPLLA_DEVICE_NAME,
>> > +	DPLLA_SOURCE,
>> > +	DPLLA_SOURCE_ID,
>> 
>> "ID" sounds a bit odd. I think "index" would be more suitable.
>> 
>I just wanted to have shorter names to better fit 80 columns per line restrictions.

I think that ID has a bit different semantics. If "INDEX" is too long
for you (not sure why), use "IDX" perhaps?


>> 
>> > +	DPLLA_SOURCE_TYPE,
>> > +	DPLLA_SOURCE_SUPPORTED,
>> > +	DPLLA_OUTPUT,
>> > +	DPLLA_OUTPUT_ID,
>> > +	DPLLA_OUTPUT_TYPE,
>> > +	DPLLA_OUTPUT_SUPPORTED,
>> > +	DPLLA_STATUS,
>> > +	DPLLA_TEMP,
>> > +	DPLLA_LOCK_STATUS,
>> > +	DPLLA_FLAGS,
>> > +
>> > +	__DPLLA_MAX,
>> > +};
>> > +#define DPLLA_MAX (__DPLLA_MAX - 1)
>> > +
>> > +/* DPLL status provides information of device status */
>> > +enum dpll_genl_status {
>> > +	DPLL_STATUS_NONE,
>> > +	DPLL_STATUS_CALIBRATING,
>> > +	DPLL_STATUS_LOCKED,
>> > +
>> > +	__DPLL_STATUS_MAX,
>> > +};
>> > +#define DPLL_STATUS_MAX (__DPLL_STATUS_MAX - 1)
>> > +
>> > +/* DPLL signal types used as source or as output */
>> > +enum dpll_genl_signal_type {
>> > +	DPLL_TYPE_EXT_1PPS,
>> > +	DPLL_TYPE_EXT_10MHZ,
>> > +	DPLL_TYPE_SYNCE_ETH_PORT,
>> > +	DPLL_TYPE_INT_OSCILLATOR,
>> > +	DPLL_TYPE_GNSS,
>> > +
>> > +	__DPLL_TYPE_MAX,
>> > +};
>> > +#define DPLL_TYPE_MAX (__DPLL_TYPE_MAX - 1)
>> > +
>> > +/* DPLL lock status provides information of source used to lock the device */
>> > +enum dpll_genl_lock_status {
>> > +	DPLL_LOCK_STATUS_UNLOCKED,
>> > +	DPLL_LOCK_STATUS_EXT_1PPS,
>> > +	DPLL_LOCK_STATUS_EXT_10MHZ,
>> > +	DPLL_LOCK_STATUS_SYNCE,
>> > +	DPLL_LOCK_STATUS_INT_OSCILLATOR,
>> > +	DPLL_LOCK_STATUS_GNSS,
>> 
>> I find it a bit odd and redundant to have lock status here as a separate
>> enum. You have a souce selected (either autoselected or manualy
>> selected). Then the status is either:
>> "UNLOCKED"
>> "LOCKED"
>> "HOLDOVER"
>> 
>> Or something similar. The point is, don't have the "source type" as a
>> part of lock status.
>> 
>
>Yes, it's a very good idea, I was thinking about the same, but it didn't end
>up in the code.
>
>> 
>> > +
>> > +	__DPLL_LOCK_STATUS_MAX,
>> > +};
>> > +#define DPLL_LOCK_STATUS_MAX (__DPLL_LOCK_STATUS_MAX - 1)
>> > +
>> > +/* Events of dpll_genl_family */
>> > +enum dpll_genl_event {
>> > +	DPLL_EVENT_UNSPEC,
>> > +	DPLL_EVENT_DEVICE_CREATE,		/* DPLL device creation */
>> > +	DPLL_EVENT_DEVICE_DELETE,		/* DPLL device deletion */
>> > +	DPLL_EVENT_STATUS_LOCKED,		/* DPLL device locked to source */
>> > +	DPLL_EVENT_STATUS_UNLOCKED,	/* DPLL device freerun */
>> 
>> Again, redundant I belive. There should be one event,
>> inside the message there should be and ATTR of the lock state.
>> 
>> Also, I believe there are 2 options:
>> 1) follow the existing netlink models and have:
>> DPLL_EVENT_DEVICE_NEW
>>    - sent for new device
>>    - sent for change with device
>> DPLL_EVENT_DEVICE_DEL
>>    - sent for removed device
>> 2)
>> DPLL_EVENT_DEVICE_NEW
>>    - sent for new device
>> DPLL_EVENT_DEVICE_DEL
>>    - sent for removed device
>> DPLL_EVENT_DEVICE_CHANGE
>>    - sent for change with device
>> 
>> Bot options work fine I belive. The point is, you don't want to have
>> "cmd" per one attr change. Changed the device, attrs are passed in one
>> message.
>> 
>
>I will try to change events this way, thanks.
>
>> 
>> 
>> > +	DPLL_EVENT_SOURCE_CHANGE,		/* DPLL device source changed */
>> 
>> Similar here, source of device changed, should be just one attr in
>> device message, see above.
>> 
>
>The WIP right now is going the way to have separate objects representing
>pins, which could be used as source/output or even mux device. And the whole
>part about sources and outputs is going to change. But I'll keep in mind that
>suggestion while implementing this new way.

Yeah, see my suggestion about the pins above. Good to hear that we are
in sync.


>
>> 
>> > +	DPLL_EVENT_OUTPUT_CHANGE,		/* DPLL device output changed */
>> 
>> 
>> > +
>> > +	__DPLL_EVENT_MAX,
>> > +};
>> > +#define DPLL_EVENT_MAX (__DPLL_EVENT_MAX - 1)
>> > +
>> > +/* Commands supported by the dpll_genl_family */
>> > +enum dpll_genl_cmd {
>> > +	DPLL_CMD_UNSPEC,
>> > +	DPLL_CMD_DEVICE_GET,	/* List of DPLL devices id */
>> > +	DPLL_CMD_SET_SOURCE_TYPE,	/* Set the DPLL device source type */
>> 
>> This is confusing, you select "source", not "type".
>
>As I said, we can have different types for one source.

Again, see above my comment suggesting to separate TYPE and SIGNAL.



>
>> 
>> Please be consistent in naming:
>> DPLL_CMD_*_GET/SET
>
>Sure
>
>> 
>> Also, to be consistend with other netlink interfaces, we don't need
>> cmd per action, rather there should be OBJ_GET (can dump) and OBJ_SET
>> commands, like this:
>>     DPLL_CMD_DEVICE_GET (can dump all present devices)
>>     	ATTR_SOURCE_SELECT_MODE (current one)
>>     	ATTR_SOURCE_INDEX (currect one)
>>     DPLL_CMD_DEVICE_SET
>>     	ATTR_SOURCE_INDEX (to set)
>>     DPLL_CMD_DEVICE_SET
>>     	ATTR_SOURCE_SELECT_MODE (to set)
>> 
>
>I believe we have to provide all the possible (or suitable) attributes in SET
>command too, to fully configure the source by one command only, right?

Yep.


>
>And I also think we have to provide special attribute to show which source is
>actually used to sync to, like ATTR_CONNECTED.

Either that or it could be exposed by PERSONALITY set to INPUT of one of
the pins. See my suggestion about pin personalities above.


>
>> 
>> > +	DPLL_CMD_SET_OUTPUT_TYPE,	/* Set the DPLL device output type */
>> 
>> Similar to what I suggested for "source", we should
>> enable to select the OUTPUT, the type should be static. Also instead,
>> I belive we should have a list of outputs and basically just allow
>> enable/disable individual outputs:
>>     DPLL_CMD_OUTPUT_GET (can dump the list of available outputs)
>> 	ATTR_ENABLED (or "CONNECTED" or whatever) of type bool
>>     DPLL_CMD_OUTPUT_SET
>> 	ATTR_ENABLED (or "CONNECTED" or whatever) of type bool
>> 
>> This is suitable for SyncE for example, when you have multiple netdev ports
>> that are connected as "outputs", you can enable exactly those you you want.
>> Example:
>> # To list the available outputs:
>> -> DPLL_CMD_OUTPUT_GET - dump
>>       ATTR_DEVICE_ID X
>> 
>> <- DPLL_CMD_OUTPUT_GET
>>       ATTR_DEVICE_ID X
>>       ATTR_OUTPUT_INDEX 0
>>       ATTR_OUTPUT_TYPE SYNCE_ETH_PORT
>>       ATTR_OUTPUT_NETDEV_IFINDEX 20
>>       ATTR_OUTPUT_ENABLED 0
>>       ATTR_DEVICE_ID X
>>       ATTR_OUTPUT_INDEX 1
>>       ATTR_OUTPUT_TYPE SYNCE_ETH_PORT
>>       ATTR_OUTPUT_NETDEV_IFINDEX 30
>>       ATTR_OUTPUT_ENABLED 0
>> 
>> # Now enable output with index 0
>> -> DPLL_CMD_OUTPUT_SET
>>       ATTR_DEVICE_ID X
>>       ATTR_OUTPUT_INDEX 0
>>       ATTR_OUTPUT_ENABLED 1
>> 
>Well, in case when we have flexible outputs, we can provide this information
>as special type, like DPLL_TYPE_DISABLED. Having other types configured on
>the output will assume that the OUTPUT is enabled.

Either that or it could be configureg by setting the pin PERSONALITY
set to DISCONNECTED See my suggestion about pin personalities above.


>
>> 
>> > +
>> > +	__DPLL_CMD_MAX,
>> > +};
>> > +#define DPLL_CMD_MAX (__DPLL_CMD_MAX - 1)
>> > +
>> > +#endif /* _UAPI_LINUX_DPLL_H */
>> > -- 
>> > 2.27.0
>> > 
>
>Thanks for actionable feedback, I hope to prepare new version soon with all
>the comments and suggestions addressed!

Thanks! Looking forward to it!

>
>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 1/6] dpll: Add DPLL framework base functions
  2022-10-11  8:32         ` Jiri Pirko
@ 2022-10-11  8:47           ` Jiri Pirko
  -1 siblings, 0 replies; 67+ messages in thread
From: Jiri Pirko @ 2022-10-11  8:47 UTC (permalink / raw)
  To: Vadim Fedorenko
  Cc: Jakub Kicinski, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

Tue, Oct 11, 2022 at 10:32:22AM CEST, jiri@resnulli.us wrote:
>Mon, Oct 10, 2022 at 09:54:26PM CEST, vfedorenko@novek.ru wrote:
>>On 10.10.2022 10:18, Jiri Pirko wrote:
>>> Mon, Oct 10, 2022 at 03:17:59AM CEST, vfedorenko@novek.ru wrote:
>>> > From: Vadim Fedorenko <vadfed@fb.com>

[...]


>>I see your point. We do have hardware which allows changing type of SMA
>>connector, and even the direction, each SMA could be used as input/source or
>>output of different signals. But there are limitation, like not all SMAs can
>>produce IRIG-B signal or only some of them can be used to get GNSS 1PPS. The
>
>Okay, so that is not the *type* of source, but rather attribute of it.
>Example:
>
>$ dpll X show
>index 0
>  type EXT
>  signal 1PPS
>  supported_signals
>     1PPS 10MHz
>
>$ dpll X set source index 1 signal_type 10MHz
>$ dpll X show
>index 0
>  type EXT
>  signal 10MHz
>  supported_signals
>     1PPS 10MHz
>
>So one source with index 0 of type "EXT" (could be "SMA", does not
>matter) supports 1 signal types.
>
>
>Thinking about this more and to cover the case when one SMA could be
>potencially used for input and output. It already occured to me that
>source/output are quite similar, have similar/same attributes. What if
>they are merged together to say a "pin" object only with extra
>PERSONALITY attribute?
>
>Example:
>
>-> DPLL_CMD_PIN_GET - dump
>      ATTR_DEVICE_ID X
>
><- DPLL_CMD_PIN_GET
>
>       ATTR_DEVICE_ID X
>       ATTR_PIN_INDEX 0
>       ATTR_PIN_TYPE EXT
>       ATTR_PIN_SIGNAL 1PPS   (selected signal)
>       ATTR_PIN_SUPPORTED_SIGNALS (nest)
>         ATTR_PIN_SIGNAL 1PPS
>         ATTR_PIN_SIGNAL 10MHZ
>       ATTR_PIN_PERSONALITY OUTPUT   (selected personality)
>       ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>         ATTR_PIN_PERSONALITY DISCONNECTED
>         ATTR_PIN_PERSONALITY INPUT
>         ATTR_PIN_PERSONALITY OUTPUT     (note this supports both input and
>					  output)
>
>       ATTR_DEVICE_ID X
>       ATTR_PIN_INDEX 1
>       ATTR_PIN_TYPE EXT
>       ATTR_PIN_SIGNAL 10MHz   (selected signal)
>       ATTR_PIN_SUPPORTED_SIGNALS (nest)
>         ATTR_PIN_SIGNAL 1PPS
>         ATTR_PIN_SIGNAL 10MHZ
>       ATTR_PIN_PERSONALITY DISCONNECTED   (selected personality - not
>					    connected currently)
>       ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>         ATTR_PIN_PERSONALITY DISCONNECTED
>         ATTR_PIN_PERSONALITY INPUT      (note this supports only input)
>
>       ATTR_DEVICE_ID X
>       ATTR_PIN_INDEX 2
>       ATTR_PIN_TYPE GNSS
>       ATTR_PIN_SIGNAL 1PPS   (selected signal)
>       ATTR_PIN_SUPPORTED_SIGNALS (nest)
>         ATTR_PIN_SIGNAL 1PPS
>       ATTR_PIN_PERSONALITY INPUT   (selected personality - note this is
>				     now he selected source, being only
>				     pin with INPUT personality)
>       ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>         ATTR_PIN_PERSONALITY DISCONNECTED
>         ATTR_PIN_PERSONALITY INPUT      (note this supports only input)
>
>       ATTR_DEVICE_ID X
>       ATTR_PIN_INDEX 3
>       ATTR_PIN_TYPE SYNCE_ETH_PORT
>       ATTR_PIN_NETDEV_IFINDEX 20
>       ATTR_PIN_PERSONALITY OUTPUT   (selected personality)
>       ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>         ATTR_PIN_PERSONALITY DISCONNECTED
>         ATTR_PIN_PERSONALITY INPUT
>         ATTR_PIN_PERSONALITY OUTPUT     (note this supports both input and
>					  output)
>
>       ATTR_DEVICE_ID X
>       ATTR_PIN_INDEX 4
>       ATTR_PIN_TYPE SYNCE_ETH_PORT
>       ATTR_PIN_NETDEV_IFINDEX 30
>       ATTR_PIN_PERSONALITY OUTPUT   (selected personality)
>       ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>         ATTR_PIN_PERSONALITY DISCONNECTED
>         ATTR_PIN_PERSONALITY INPUT
>         ATTR_PIN_PERSONALITY OUTPUT     (note this supports both input and
>					  output)
>
>
>This allows the user to actually see the full picture:
>1) all input/output pins in a single list, no duplicates
>2) each pin if of certain type (ATTR_PIN_TYPE) EXT/GNSS/SYNCE_ETH_PORT
>3) the pins that can change signal type contain the selected and list of
>   supported signal types (ATTR_PIN_SIGNAL, ATTR_PIN_SUPPORTED_SIGNALS)
>4) direction/connection of the pin to the DPLL is exposed over
>   ATTR_PIN_PERSONALITY. For each pin, the driver would expose it can
>   act as INPUT/OUTPUT and even more, it can indicate the pin can
>   disconnect from DPLL entirely (if possible).
>5) user can select the source by setting ATTR_PIN_PERSONALITY of certain
>   pin to INPUT. Only one pin could be set to INPUT and that is the
>   souce of DPLL.
>   In case no pin have personality set to INPUT, the DPLL is
>   free-running.

Okay, thinking about it some more, I would leave the source select
indepentent from the ATTR_PIN_PERSONALITY and selectable using device
set cmd and separate attribute. It works better even more when consider
autoselect mode.

Well of course only pins with ATTR_PIN_PERSONALITY INPUT could be
selected as source.


>
>This would introduce quite nice flexibility, exposes source/output
>capabilities and provides good visilibity of current configuration.
>
>
>>interface was created to cover such case. I believe we have to improve it to
>>cover SyncE configuration better, but I personally don't have SyncE hardware
>>ready to test and that's why I have to rely on suggestions from yours or
>>Arkadiusz's experience. From what I can see now there is need for special
>>attribute to link source to net device, and I'm happy to add it. In case of
>>fixed configuration of sources, the device should provide only one type as
>>supported and that's it.
>>

[...]

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 1/6] dpll: Add DPLL framework base functions
@ 2022-10-11  8:47           ` Jiri Pirko
  0 siblings, 0 replies; 67+ messages in thread
From: Jiri Pirko @ 2022-10-11  8:47 UTC (permalink / raw)
  To: Vadim Fedorenko
  Cc: Jakub Kicinski, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

Tue, Oct 11, 2022 at 10:32:22AM CEST, jiri@resnulli.us wrote:
>Mon, Oct 10, 2022 at 09:54:26PM CEST, vfedorenko@novek.ru wrote:
>>On 10.10.2022 10:18, Jiri Pirko wrote:
>>> Mon, Oct 10, 2022 at 03:17:59AM CEST, vfedorenko@novek.ru wrote:
>>> > From: Vadim Fedorenko <vadfed@fb.com>

[...]


>>I see your point. We do have hardware which allows changing type of SMA
>>connector, and even the direction, each SMA could be used as input/source or
>>output of different signals. But there are limitation, like not all SMAs can
>>produce IRIG-B signal or only some of them can be used to get GNSS 1PPS. The
>
>Okay, so that is not the *type* of source, but rather attribute of it.
>Example:
>
>$ dpll X show
>index 0
>  type EXT
>  signal 1PPS
>  supported_signals
>     1PPS 10MHz
>
>$ dpll X set source index 1 signal_type 10MHz
>$ dpll X show
>index 0
>  type EXT
>  signal 10MHz
>  supported_signals
>     1PPS 10MHz
>
>So one source with index 0 of type "EXT" (could be "SMA", does not
>matter) supports 1 signal types.
>
>
>Thinking about this more and to cover the case when one SMA could be
>potencially used for input and output. It already occured to me that
>source/output are quite similar, have similar/same attributes. What if
>they are merged together to say a "pin" object only with extra
>PERSONALITY attribute?
>
>Example:
>
>-> DPLL_CMD_PIN_GET - dump
>      ATTR_DEVICE_ID X
>
><- DPLL_CMD_PIN_GET
>
>       ATTR_DEVICE_ID X
>       ATTR_PIN_INDEX 0
>       ATTR_PIN_TYPE EXT
>       ATTR_PIN_SIGNAL 1PPS   (selected signal)
>       ATTR_PIN_SUPPORTED_SIGNALS (nest)
>         ATTR_PIN_SIGNAL 1PPS
>         ATTR_PIN_SIGNAL 10MHZ
>       ATTR_PIN_PERSONALITY OUTPUT   (selected personality)
>       ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>         ATTR_PIN_PERSONALITY DISCONNECTED
>         ATTR_PIN_PERSONALITY INPUT
>         ATTR_PIN_PERSONALITY OUTPUT     (note this supports both input and
>					  output)
>
>       ATTR_DEVICE_ID X
>       ATTR_PIN_INDEX 1
>       ATTR_PIN_TYPE EXT
>       ATTR_PIN_SIGNAL 10MHz   (selected signal)
>       ATTR_PIN_SUPPORTED_SIGNALS (nest)
>         ATTR_PIN_SIGNAL 1PPS
>         ATTR_PIN_SIGNAL 10MHZ
>       ATTR_PIN_PERSONALITY DISCONNECTED   (selected personality - not
>					    connected currently)
>       ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>         ATTR_PIN_PERSONALITY DISCONNECTED
>         ATTR_PIN_PERSONALITY INPUT      (note this supports only input)
>
>       ATTR_DEVICE_ID X
>       ATTR_PIN_INDEX 2
>       ATTR_PIN_TYPE GNSS
>       ATTR_PIN_SIGNAL 1PPS   (selected signal)
>       ATTR_PIN_SUPPORTED_SIGNALS (nest)
>         ATTR_PIN_SIGNAL 1PPS
>       ATTR_PIN_PERSONALITY INPUT   (selected personality - note this is
>				     now he selected source, being only
>				     pin with INPUT personality)
>       ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>         ATTR_PIN_PERSONALITY DISCONNECTED
>         ATTR_PIN_PERSONALITY INPUT      (note this supports only input)
>
>       ATTR_DEVICE_ID X
>       ATTR_PIN_INDEX 3
>       ATTR_PIN_TYPE SYNCE_ETH_PORT
>       ATTR_PIN_NETDEV_IFINDEX 20
>       ATTR_PIN_PERSONALITY OUTPUT   (selected personality)
>       ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>         ATTR_PIN_PERSONALITY DISCONNECTED
>         ATTR_PIN_PERSONALITY INPUT
>         ATTR_PIN_PERSONALITY OUTPUT     (note this supports both input and
>					  output)
>
>       ATTR_DEVICE_ID X
>       ATTR_PIN_INDEX 4
>       ATTR_PIN_TYPE SYNCE_ETH_PORT
>       ATTR_PIN_NETDEV_IFINDEX 30
>       ATTR_PIN_PERSONALITY OUTPUT   (selected personality)
>       ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>         ATTR_PIN_PERSONALITY DISCONNECTED
>         ATTR_PIN_PERSONALITY INPUT
>         ATTR_PIN_PERSONALITY OUTPUT     (note this supports both input and
>					  output)
>
>
>This allows the user to actually see the full picture:
>1) all input/output pins in a single list, no duplicates
>2) each pin if of certain type (ATTR_PIN_TYPE) EXT/GNSS/SYNCE_ETH_PORT
>3) the pins that can change signal type contain the selected and list of
>   supported signal types (ATTR_PIN_SIGNAL, ATTR_PIN_SUPPORTED_SIGNALS)
>4) direction/connection of the pin to the DPLL is exposed over
>   ATTR_PIN_PERSONALITY. For each pin, the driver would expose it can
>   act as INPUT/OUTPUT and even more, it can indicate the pin can
>   disconnect from DPLL entirely (if possible).
>5) user can select the source by setting ATTR_PIN_PERSONALITY of certain
>   pin to INPUT. Only one pin could be set to INPUT and that is the
>   souce of DPLL.
>   In case no pin have personality set to INPUT, the DPLL is
>   free-running.

Okay, thinking about it some more, I would leave the source select
indepentent from the ATTR_PIN_PERSONALITY and selectable using device
set cmd and separate attribute. It works better even more when consider
autoselect mode.

Well of course only pins with ATTR_PIN_PERSONALITY INPUT could be
selected as source.


>
>This would introduce quite nice flexibility, exposes source/output
>capabilities and provides good visilibity of current configuration.
>
>
>>interface was created to cover such case. I believe we have to improve it to
>>cover SyncE configuration better, but I personally don't have SyncE hardware
>>ready to test and that's why I have to rely on suggestions from yours or
>>Arkadiusz's experience. From what I can see now there is need for special
>>attribute to link source to net device, and I'm happy to add it. In case of
>>fixed configuration of sources, the device should provide only one type as
>>supported and that's it.
>>

[...]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 1/6] dpll: Add DPLL framework base functions
  2022-10-11  8:32         ` Jiri Pirko
@ 2022-10-11 21:23           ` Vadim Fedorenko
  -1 siblings, 0 replies; 67+ messages in thread
From: Vadim Fedorenko @ 2022-10-11 21:23 UTC (permalink / raw)
  To: Jiri Pirko
  Cc: Jakub Kicinski, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

On 11.10.2022 09:32, Jiri Pirko wrote:
> Mon, Oct 10, 2022 at 09:54:26PM CEST, vfedorenko@novek.ru wrote:
>> On 10.10.2022 10:18, Jiri Pirko wrote:
>>> Mon, Oct 10, 2022 at 03:17:59AM CEST, vfedorenko@novek.ru wrote:
>>>> From: Vadim Fedorenko <vadfed@fb.com>
>>>>
>>>> DPLL framework is used to represent and configure DPLL devices
>>>> in systems. Each device that has DPLL and can configure sources
>>>> and outputs can use this framework.
>>>>
>>>> Signed-off-by: Vadim Fedorenko <vadfed@fb.com>
>>>> Co-developed-by: Jakub Kicinski <kuba@kernel.org>
>>>> Co-developed-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
>>>> ---

[...]

>>>> +static int __dpll_cmd_device_dump_one(struct dpll_device *dpll,
>>>> +					   struct sk_buff *msg)
>>>> +{
>>>> +	if (nla_put_u32(msg, DPLLA_DEVICE_ID, dpll->id))
>>>> +		return -EMSGSIZE;
>>>> +
>>>> +	if (nla_put_string(msg, DPLLA_DEVICE_NAME, dev_name(&dpll->dev)))
>>>> +		return -EMSGSIZE;
>>>> +
>>>> +	return 0;
>>>> +}
>>>> +
>>>> +static int __dpll_cmd_dump_sources(struct dpll_device *dpll,
>>>> +					   struct sk_buff *msg)
>>>> +{
>>>> +	struct nlattr *src_attr;
>>>> +	int i, ret = 0, type;
>>>> +
>>>> +	for (i = 0; i < dpll->sources_count; i++) {
>>>> +		src_attr = nla_nest_start(msg, DPLLA_SOURCE);
>>>> +		if (!src_attr) {
>>>> +			ret = -EMSGSIZE;
>>>> +			break;
>>>> +		}
>>>> +		type = dpll->ops->get_source_type(dpll, i);
>>>> +		if (nla_put_u32(msg, DPLLA_SOURCE_ID, i) ||
>>>> +		    nla_put_u32(msg, DPLLA_SOURCE_TYPE, type)) {
>>>> +			nla_nest_cancel(msg, src_attr);
>>>> +			ret = -EMSGSIZE;
>>>> +			break;
>>>> +		}
>>>> +		if (dpll->ops->get_source_supported) {
>>>> +			for (type = 0; type <= DPLL_TYPE_MAX; type++) {
>>>> +				ret = dpll->ops->get_source_supported(dpll, i, type);
>>>
>>> Okay, this looks weird to me. This implicates that it is possible to
>>> have for example:
>>> source index 0 of type 10
>>> source index 0 of type 11
>>> Both possible.
>>>
>>> However, from how I understand this, each source if of certain fixed type.
>>> Either it is:
>>> SyncE port
>>> 1pps external input (SMA)
>>> 10MHZ external input (SMA)
>>> internal oscilator (free-running)
>>> GNSS (GPS)
>>>
>>> So for example:
>>> index 0, type: 1pps external input (SMA)
>>> index 1, type: 10MHZ external input (
>>> index 2, type: SyncE port, netdev ifindex: 20
>>> index 3, type: SyncE port, netdev ifindex: 30
>>>
>>> So 4 "source" objects, each of different type.
>>> In this case I can imagine that the netlink API might look something
>>> like:
>>> -> DPLL_CMD_SOURCE_GET - dump
>>>        ATTR_DEVICE_ID X
>>>
>>> <- DPLL_CMD_SOURCE_GET
>>>
>>>        ATTR_DEVICE_ID X
>>>        ATTR_SOURCE_INDEX 0
>>>        ATTR_SOURCE_TYPE EXT_1PPS
>>>        ATTR_DEVICE_ID X
>>>        ATTR_SOURCE_INDEX 1
>>>        ATTR_SOURCE_TYPE EXT_10MHZ
>>>        ATTR_DEVICE_ID X
>>>        ATTR_SOURCE_INDEX 2
>>>        ATTR_SOURCE_TYPE SYNCE_ETH_PORT
>>>        ATTR_SOURCE_NETDEV_IFINDEX 20
>>>
>>>        ATTR_DEVICE_ID X
>>>        ATTR_SOURCE_INDEX 3
>>>        ATTR_SOURCE_TYPE SYNCE_ETH_PORT
>>>        ATTR_SOURCE_NETDEV_IFINDEX 30
>>>
>>> You see kernel would dump 4 source objects.
>>>
>> I see your point. We do have hardware which allows changing type of SMA
>> connector, and even the direction, each SMA could be used as input/source or
>> output of different signals. But there are limitation, like not all SMAs can
>> produce IRIG-B signal or only some of them can be used to get GNSS 1PPS. The
> 
> Okay, so that is not the *type* of source, but rather attribute of it.
> Example:
> 
> $ dpll X show
> index 0
>    type EXT
>    signal 1PPS
>    supported_signals
>       1PPS 10MHz
> 
> $ dpll X set source index 1 signal_type 10MHz
> $ dpll X show
> index 0
>    type EXT
>    signal 10MHz
>    supported_signals
>       1PPS 10MHz
> 
> So one source with index 0 of type "EXT" (could be "SMA", does not
> matter) supports 1 signal types.
> 
> 
> Thinking about this more and to cover the case when one SMA could be
> potencially used for input and output. It already occured to me that
> source/output are quite similar, have similar/same attributes. What if
> they are merged together to say a "pin" object only with extra
> PERSONALITY attribute?
> 
> Example:
> 
> -> DPLL_CMD_PIN_GET - dump
>        ATTR_DEVICE_ID X
> 
> <- DPLL_CMD_PIN_GET
> 
>         ATTR_DEVICE_ID X
>         ATTR_PIN_INDEX 0
>         ATTR_PIN_TYPE EXT
>         ATTR_PIN_SIGNAL 1PPS   (selected signal)
>         ATTR_PIN_SUPPORTED_SIGNALS (nest)
>           ATTR_PIN_SIGNAL 1PPS
>           ATTR_PIN_SIGNAL 10MHZ
>         ATTR_PIN_PERSONALITY OUTPUT   (selected personality)
>         ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>           ATTR_PIN_PERSONALITY DISCONNECTED
>           ATTR_PIN_PERSONALITY INPUT
>           ATTR_PIN_PERSONALITY OUTPUT     (note this supports both input and
> 					  output)
> 
>         ATTR_DEVICE_ID X
>         ATTR_PIN_INDEX 1
>         ATTR_PIN_TYPE EXT
>         ATTR_PIN_SIGNAL 10MHz   (selected signal)
>         ATTR_PIN_SUPPORTED_SIGNALS (nest)
>           ATTR_PIN_SIGNAL 1PPS
>           ATTR_PIN_SIGNAL 10MHZ
>         ATTR_PIN_PERSONALITY DISCONNECTED   (selected personality - not
> 					    connected currently)
>         ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>           ATTR_PIN_PERSONALITY DISCONNECTED
>           ATTR_PIN_PERSONALITY INPUT      (note this supports only input)
> 
>         ATTR_DEVICE_ID X
>         ATTR_PIN_INDEX 2
>         ATTR_PIN_TYPE GNSS
>         ATTR_PIN_SIGNAL 1PPS   (selected signal)
>         ATTR_PIN_SUPPORTED_SIGNALS (nest)
>           ATTR_PIN_SIGNAL 1PPS
>         ATTR_PIN_PERSONALITY INPUT   (selected personality - note this is
> 				     now he selected source, being only
> 				     pin with INPUT personality)
>         ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>           ATTR_PIN_PERSONALITY DISCONNECTED
>           ATTR_PIN_PERSONALITY INPUT      (note this supports only input)
> 
>         ATTR_DEVICE_ID X
>         ATTR_PIN_INDEX 3
>         ATTR_PIN_TYPE SYNCE_ETH_PORT
>         ATTR_PIN_NETDEV_IFINDEX 20
>         ATTR_PIN_PERSONALITY OUTPUT   (selected personality)
>         ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>           ATTR_PIN_PERSONALITY DISCONNECTED
>           ATTR_PIN_PERSONALITY INPUT
>           ATTR_PIN_PERSONALITY OUTPUT     (note this supports both input and
> 					  output)
> 
>         ATTR_DEVICE_ID X
>         ATTR_PIN_INDEX 4
>         ATTR_PIN_TYPE SYNCE_ETH_PORT
>         ATTR_PIN_NETDEV_IFINDEX 30
>         ATTR_PIN_PERSONALITY OUTPUT   (selected personality)
>         ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>           ATTR_PIN_PERSONALITY DISCONNECTED
>           ATTR_PIN_PERSONALITY INPUT
>           ATTR_PIN_PERSONALITY OUTPUT     (note this supports both input and
> 					  output)
> 
> 
> This allows the user to actually see the full picture:
> 1) all input/output pins in a single list, no duplicates
> 2) each pin if of certain type (ATTR_PIN_TYPE) EXT/GNSS/SYNCE_ETH_PORT
> 3) the pins that can change signal type contain the selected and list of
>     supported signal types (ATTR_PIN_SIGNAL, ATTR_PIN_SUPPORTED_SIGNALS)
> 4) direction/connection of the pin to the DPLL is exposed over
>     ATTR_PIN_PERSONALITY. For each pin, the driver would expose it can
>     act as INPUT/OUTPUT and even more, it can indicate the pin can
>     disconnect from DPLL entirely (if possible).
> 5) user can select the source by setting ATTR_PIN_PERSONALITY of certain
>     pin to INPUT. Only one pin could be set to INPUT and that is the
>     souce of DPLL.
>     In case no pin have personality set to INPUT, the DPLL is
>     free-running.
> 
> This would introduce quite nice flexibility, exposes source/output
> capabilities and provides good visilibity of current configuration.
> 

My comments about this part are in the answer to the next message

> 
>> interface was created to cover such case. I believe we have to improve it to
>> cover SyncE configuration better, but I personally don't have SyncE hardware
>> ready to test and that's why I have to rely on suggestions from yours or
>> Arkadiusz's experience. From what I can see now there is need for special
>> attribute to link source to net device, and I'm happy to add it. In case of
>> fixed configuration of sources, the device should provide only one type as
>> supported and that's it.
>>
>>
>>>
>>>
>>>> +				if (ret && nla_put_u32(msg, DPLLA_SOURCE_SUPPORTED, type)) {
>>>> +					ret = -EMSGSIZE;
>>>> +					break;
>>>> +				}
>>>> +			}
>>>> +			ret = 0;
>>>> +		}
>>>> +		nla_nest_end(msg, src_attr);
>>>> +	}
>>>> +
>>>> +	return ret;
>>>> +}
>>>> +
>>>> +static int __dpll_cmd_dump_outputs(struct dpll_device *dpll,
>>>> +					   struct sk_buff *msg)
>>>> +{
>>>> +	struct nlattr *out_attr;
>>>> +	int i, ret = 0, type;
>>>> +
>>>> +	for (i = 0; i < dpll->outputs_count; i++) {
>>>> +		out_attr = nla_nest_start(msg, DPLLA_OUTPUT);
>>>> +		if (!out_attr) {
>>>> +			ret = -EMSGSIZE;
>>>> +			break;
>>>> +		}
>>>> +		type = dpll->ops->get_output_type(dpll, i);
>>>> +		if (nla_put_u32(msg, DPLLA_OUTPUT_ID, i) ||
>>>> +		    nla_put_u32(msg, DPLLA_OUTPUT_TYPE, type)) {
>>>> +			nla_nest_cancel(msg, out_attr);
>>>> +			ret = -EMSGSIZE;
>>>> +			break;
>>>> +		}
>>>> +		if (dpll->ops->get_output_supported) {
>>>> +			for (type = 0; type <= DPLL_TYPE_MAX; type++) {
>>>> +				ret = dpll->ops->get_output_supported(dpll, i, type);
>>>> +				if (ret && nla_put_u32(msg, DPLLA_OUTPUT_SUPPORTED, type)) {
>>>
>>> This I believe is similar to sources, see my comment above.
>>>
>> As I said, we have to cover the case when SMAs are flexible to configure.
>>
>>> I believe we should have separate commands to GET and SET outputs and
>>> sources. That would make the object separation clear and will also help
>>> event model. See below I suggestion how output netlink API may look
>>> like (comment in header file near enum dpll_genl_cmd definition).
>>>
>>>
>>>> +					ret = -EMSGSIZE;
>>>> +					break;
>>>> +				}
>>>> +			}
>>>> +			ret = 0;
>>>> +		}
>>>> +		nla_nest_end(msg, out_attr);
>>>> +	}
>>>> +
>>>> +	return ret;
>>>> +}
>>>> +
>>>> +static int __dpll_cmd_dump_status(struct dpll_device *dpll,
>>>> +					   struct sk_buff *msg)
>>>> +{
>>>> +	int ret;
>>>> +
>>>> +	if (dpll->ops->get_status) {
>>>> +		ret = dpll->ops->get_status(dpll);
>>>> +		if (nla_put_u32(msg, DPLLA_STATUS, ret))
>>>> +			return -EMSGSIZE;
>>>> +	}
>>>> +
>>>> +	if (dpll->ops->get_temp) {
>>>> +		ret = dpll->ops->get_temp(dpll);
>>>> +		if (nla_put_u32(msg, DPLLA_TEMP, ret))
>>>> +			return -EMSGSIZE;
>>>> +	}
>>>> +
>>>> +	if (dpll->ops->get_lock_status) {
>>>> +		ret = dpll->ops->get_lock_status(dpll);
>>>> +		if (nla_put_u32(msg, DPLLA_LOCK_STATUS, ret))
>>>> +			return -EMSGSIZE;
>>>> +	}
>>>> +
>>>> +	return 0;
>>>> +}
>>>> +
>>>> +static int
>>>> +dpll_device_dump_one(struct dpll_device *dpll, struct sk_buff *msg,
>>>> +		     u32 portid, u32 seq, int flags)
>>>> +{
>>>> +	struct nlattr *hdr;
>>>> +	int ret;
>>>> +
>>>> +	hdr = genlmsg_put(msg, portid, seq, &dpll_gnl_family, 0,
>>>> +			  DPLL_CMD_DEVICE_GET);
>>>> +	if (!hdr)
>>>> +		return -EMSGSIZE;
>>>> +
>>>> +	mutex_lock(&dpll->lock);
>>>> +	ret = __dpll_cmd_device_dump_one(dpll, msg);
>>>> +	if (ret)
>>>> +		goto out_unlock;
>>>> +
>>>> +	if (flags & DPLL_FLAG_SOURCES && dpll->ops->get_source_type) {
>>>> +		ret = __dpll_cmd_dump_sources(dpll, msg);
>>>> +		if (ret)
>>>> +			goto out_unlock;
>>>> +	}
>>>> +
>>>> +	if (flags & DPLL_FLAG_OUTPUTS && dpll->ops->get_output_type) {
>>>> +		ret = __dpll_cmd_dump_outputs(dpll, msg);
>>>> +		if (ret)
>>>> +			goto out_unlock;
>>>> +	}
>>>> +
>>>> +	if (flags & DPLL_FLAG_STATUS) {
>>>> +		ret = __dpll_cmd_dump_status(dpll, msg);
>>>> +		if (ret)
>>>> +			goto out_unlock;
>>>> +	}
>>>> +	mutex_unlock(&dpll->lock);
>>>> +	genlmsg_end(msg, hdr);
>>>> +
>>>> +	return 0;
>>>> +
>>>> +out_unlock:
>>>> +	mutex_unlock(&dpll->lock);
>>>> +	genlmsg_cancel(msg, hdr);
>>>> +
>>>> +	return ret;
>>>> +}
>>>> +
>>>> +static int dpll_genl_cmd_set_source(struct sk_buff *skb, struct genl_info *info)
>>>> +{
>>>> +	struct dpll_device *dpll = info->user_ptr[0];
>>>> +	struct nlattr **attrs = info->attrs;
>>>> +	int ret = 0, src_id, type;
>>>
>>> Enums.
>>>
>>
>> Sure.
>>
>>>> +
>>>> +	if (!attrs[DPLLA_SOURCE_ID] ||
>>>> +	    !attrs[DPLLA_SOURCE_TYPE])
>>>> +		return -EINVAL;
>>>> +
>>>> +	if (!dpll->ops->set_source_type)
>>>> +		return -EOPNOTSUPP;
>>>> +
>>>> +	src_id = nla_get_u32(attrs[DPLLA_SOURCE_ID]);
>>>> +	type = nla_get_u32(attrs[DPLLA_SOURCE_TYPE]);
>>>
>>>
>>> This looks odd to me. The user should just pass the index of source to
>>> select. Type should be static, and non-changeable.
>>>
>>>
>>>> +
>>>> +	mutex_lock(&dpll->lock);
>>>> +	ret = dpll->ops->set_source_type(dpll, src_id, type);
>>>> +	mutex_unlock(&dpll->lock);
>>>> +
>>>> +	return ret;
>>>> +}
>>>> +
>>>> +static int dpll_genl_cmd_set_output(struct sk_buff *skb, struct genl_info *info)
>>>> +{
>>>> +	struct dpll_device *dpll = info->user_ptr[0];
>>>> +	struct nlattr **attrs = info->attrs;
>>>> +	int ret = 0, out_id, type;
>>>
>>> Enums.
>>>
>>>
>>>> +
>>>> +	if (!attrs[DPLLA_OUTPUT_ID] ||
>>>> +	    !attrs[DPLLA_OUTPUT_TYPE])
>>>> +		return -EINVAL;
>>>> +
>>>> +	if (!dpll->ops->set_output_type)
>>>> +		return -EOPNOTSUPP;
>>>> +
>>>> +	out_id = nla_get_u32(attrs[DPLLA_OUTPUT_ID]);
>>>> +	type = nla_get_u32(attrs[DPLLA_OUTPUT_TYPE]);
>>>
>>> Same here, passing type here looks wrong.
>>>
>>>
>>>
>>>> +
>>>> +	mutex_lock(&dpll->lock);
>>>> +	ret = dpll->ops->set_output_type(dpll, out_id, type);
>>>> +	mutex_unlock(&dpll->lock);
>>>> +
>>>> +	return ret;
>>>> +}
>>>> +
>>>> +static int dpll_device_loop_cb(struct dpll_device *dpll, void *data)
>>>> +{
>>>> +	struct dpll_dump_ctx *ctx;
>>>> +	struct param *p = (struct param *)data;
>>>> +
>>>> +	ctx = dpll_dump_context(p->cb);
>>>> +
>>>> +	ctx->pos_idx = dpll->id;
>>>> +
>>>> +	return dpll_device_dump_one(dpll, p->msg, 0, 0, ctx->flags);
>>>> +}
>>>> +
>>>> +static int
>>>> +dpll_cmd_device_dump(struct sk_buff *skb, struct netlink_callback *cb)
>>>> +{
>>>> +	struct dpll_dump_ctx *ctx = dpll_dump_context(cb);
>>>> +	struct param p = { .cb = cb, .msg = skb };
>>>> +
>>>> +	return for_each_dpll_device(ctx->pos_idx, dpll_device_loop_cb, &p);
>>>> +}
>>>> +
>>>> +static int
>>>> +dpll_genl_cmd_device_get_id(struct sk_buff *skb, struct genl_info *info)
>>>
>>> Just "get", no "id" here.
>>>
>>
>> Got it.
>>
>>>
>>>> +{
>>>> +	struct dpll_device *dpll = info->user_ptr[0];
>>>> +	struct nlattr **attrs = info->attrs;
>>>> +	struct sk_buff *msg;
>>>> +	int flags = 0;
>>>> +	int ret;
>>>> +
>>>> +	if (attrs[DPLLA_FLAGS])
>>>> +		flags = nla_get_u32(attrs[DPLLA_FLAGS]);
>>>> +
>>>> +	msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
>>>> +	if (!msg)
>>>> +		return -ENOMEM;
>>>> +
>>>> +	ret = dpll_device_dump_one(dpll, msg, info->snd_portid, info->snd_seq,
>>>> +				   flags);
>>>> +	if (ret)
>>>> +		goto out_free_msg;
>>>> +
>>>> +	return genlmsg_reply(msg, info);
>>>> +
>>>> +out_free_msg:
>>>> +	nlmsg_free(msg);
>>>> +	return ret;
>>>> +
>>>> +}
>>>> +
>>>> +static int dpll_genl_cmd_start(struct netlink_callback *cb)
>>>> +{
>>>> +	const struct genl_dumpit_info *info = genl_dumpit_info(cb);
>>>> +	struct dpll_dump_ctx *ctx = dpll_dump_context(cb);
>>>> +
>>>> +	ctx->dev = NULL;
>>>> +	if (info->attrs[DPLLA_FLAGS])
>>>> +		ctx->flags = nla_get_u32(info->attrs[DPLLA_FLAGS]);
>>>> +	else
>>>> +		ctx->flags = 0;
>>>> +	ctx->pos_idx = 0;
>>>> +	ctx->pos_src_idx = 0;
>>>> +	ctx->pos_out_idx = 0;
>>>> +	return 0;
>>>> +}
>>>> +
>>>> +static int dpll_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
>>>> +						 struct genl_info *info)
>>>> +{
>>>> +	struct dpll_device *dpll_id = NULL, *dpll_name = NULL;
>>>> +
>>>> +	if (!info->attrs[DPLLA_DEVICE_ID] &&
>>>> +	    !info->attrs[DPLLA_DEVICE_NAME])
>>>> +		return -EINVAL;
>>>> +
>>>> +	if (info->attrs[DPLLA_DEVICE_ID]) {
>>>> +		u32 id = nla_get_u32(info->attrs[DPLLA_DEVICE_ID]);
>>>> +
>>>> +		dpll_id = dpll_device_get_by_id(id);
>>>> +		if (!dpll_id)
>>>> +			return -ENODEV;
>>>> +		info->user_ptr[0] = dpll_id;
>>>
>>> struct dpll_device *dpll should be stored here.
>>>
>>>
>>>> +	}
>>>> +	if (info->attrs[DPLLA_DEVICE_NAME]) {
>>>
>>> You define new API, have one clear handle for devices. Either name or
>>> ID. Having both is messy.
>>>
>> That was added after the discussion with Jakub and Arkadiusz where we agreed
>> that the device could be referenced either by index or by name. The example
>> is that userspace app can easily find specific DPLL device if it knows the
>> name provided by a driver of that specific device. Without searching through
>> sysfs to find index value. Later commands could be executed using index once
>> it's known through CMD_GET_DEVICE/ATTR_DEVICE_NAME.
> 
> What exacly is the name? What is the semantics? How the name is
> generated in case of multiple instances of the same driver. What happens
> if two drivers use the same name? Is the name predictable (in sense of
> "stable over reboots")?
>

The way we were thinking about name is that driver can provide it's own name 
based on the hardware values, like MAC address or any other unique identifier, 
or the subsystem will use 'dpll%d' template to create the device. In the first 
case names can be predictable and stable over reboots at the same time.

> 
>>>
>>>> +		const char *name = nla_data(info->attrs[DPLLA_DEVICE_NAME]);
>>>> +
>>>> +		dpll_name = dpll_device_get_by_name(name);
>>>> +		if (!dpll_name)
>>>> +			return -ENODEV;
>>>> +
>>>> +		if (dpll_id && dpll_name != dpll_id)
>>>> +			return -EINVAL;
>>>> +		info->user_ptr[0] = dpll_name;
>>>
>>> struct dpll_device *dpll should be stored here.
>>>
>>
>>
>> Didn't get you, where should we store it?
>> dpll_name and dpll_id are of type struct dpll_device*,
> 
> Ah sorry, you confused me with the "name"/"id" suffix. Why you don't
> have just one variable called "dpll" instead and have the check for both
> attrs being set at the beginning? Also, extack error message would be
> nice (not only here).
> 

Yeah, I will re-think that part, it definitely needs improvement.

> 
>> and they are compared to avoid situation when both index and name are
>> provided, but refer to different devices.
>>
>>>
>>>
>>>> +	}
>>>> +
>>>> +	return 0;
>>>> +}
>>>> +
>>>> +static const struct genl_ops dpll_genl_ops[] = {
>>>> +	{
>>>> +		.cmd	= DPLL_CMD_DEVICE_GET,
>>>> +		.flags  = GENL_UNS_ADMIN_PERM,
>>>> +		.start	= dpll_genl_cmd_start,
>>>> +		.dumpit	= dpll_cmd_device_dump,
>>>> +		.doit	= dpll_genl_cmd_device_get_id,
>>>> +		.policy	= dpll_genl_get_policy,
>>>> +		.maxattr = ARRAY_SIZE(dpll_genl_get_policy) - 1,
>>>> +	},
>>>> +	{
>>>> +		.cmd	= DPLL_CMD_SET_SOURCE_TYPE,
>>>> +		.flags	= GENL_UNS_ADMIN_PERM,
>>>> +		.doit	= dpll_genl_cmd_set_source,
>>>> +		.policy	= dpll_genl_set_source_policy,
>>>> +		.maxattr = ARRAY_SIZE(dpll_genl_set_source_policy) - 1,
>>>> +	},
>>>> +	{
>>>> +		.cmd	= DPLL_CMD_SET_OUTPUT_TYPE,
>>>> +		.flags	= GENL_UNS_ADMIN_PERM,
>>>> +		.doit	= dpll_genl_cmd_set_output,
>>>> +		.policy	= dpll_genl_set_output_policy,
>>>> +		.maxattr = ARRAY_SIZE(dpll_genl_set_output_policy) - 1,
>>>> +	},
>>>> +};
>>>> +
>>>> +static struct genl_family dpll_gnl_family __ro_after_init = {
>>>> +	.hdrsize	= 0,
>>>> +	.name		= DPLL_FAMILY_NAME,
>>>> +	.version	= DPLL_VERSION,
>>>> +	.ops		= dpll_genl_ops,
>>>> +	.n_ops		= ARRAY_SIZE(dpll_genl_ops),
>>>> +	.mcgrps		= dpll_genl_mcgrps,
>>>> +	.n_mcgrps	= ARRAY_SIZE(dpll_genl_mcgrps),
>>>> +	.pre_doit	= dpll_pre_doit,
>>>
>>> Have  .parallel_ops   = true,
>>> You have dpll->lock, you don't need genl, to protect you.
>>>
>>
>> Yep, sure, thanks!
>>
>>>
>>>> +};
>>>> +
>>>> +int __init dpll_netlink_init(void)
>>>> +{
>>>> +	return genl_register_family(&dpll_gnl_family);
>>>> +}
>>>> +
>>>> +void dpll_netlink_finish(void)
>>>> +{
>>>> +	genl_unregister_family(&dpll_gnl_family);
>>>> +}
>>>> +
>>>> +void __exit dpll_netlink_fini(void)
>>>> +{
>>>> +	dpll_netlink_finish();
>>>> +}
>>>> diff --git a/drivers/dpll/dpll_netlink.h b/drivers/dpll/dpll_netlink.h
>>>> new file mode 100644
>>>> index 000000000000..e2d100f59dd6
>>>> --- /dev/null
>>>> +++ b/drivers/dpll/dpll_netlink.h
>>>> @@ -0,0 +1,7 @@
>>>> +/* SPDX-License-Identifier: GPL-2.0 */
>>>> +/*
>>>> + *  Copyright (c) 2021 Meta Platforms, Inc. and affiliates
>>>> + */
>>>> +
>>>> +int __init dpll_netlink_init(void);
>>>> +void dpll_netlink_finish(void);
>>>> diff --git a/include/linux/dpll.h b/include/linux/dpll.h
>>>> new file mode 100644
>>>> index 000000000000..9d49b19d03d9
>>>> --- /dev/null
>>>> +++ b/include/linux/dpll.h
>>>> @@ -0,0 +1,29 @@
>>>> +/* SPDX-License-Identifier: GPL-2.0 */
>>>> +/*
>>>> + *  Copyright (c) 2021 Meta Platforms, Inc. and affiliates
>>>> + */
>>>> +
>>>> +#ifndef __DPLL_H__
>>>> +#define __DPLL_H__
>>>> +
>>>> +struct dpll_device;
>>>> +
>>>> +struct dpll_device_ops {
>>>> +	int (*get_status)(struct dpll_device *dpll);
>>>> +	int (*get_temp)(struct dpll_device *dpll);
>>>> +	int (*get_lock_status)(struct dpll_device *dpll);
>>>> +	int (*get_source_type)(struct dpll_device *dpll, int id);
>>>> +	int (*get_source_supported)(struct dpll_device *dpll, int id, int type);
>>>> +	int (*get_output_type)(struct dpll_device *dpll, int id);
>>>> +	int (*get_output_supported)(struct dpll_device *dpll, int id, int type);
>>>> +	int (*set_source_type)(struct dpll_device *dpll, int id, int val);
>>>> +	int (*set_output_type)(struct dpll_device *dpll, int id, int val);
>>>
>>> All int should be enums, when they are really enums. Makes things much
>>> nicer and easier to see what's what.
>>>
>> Yep, will update it.
>>>
>>>
>>>> +};
>>>> +
>>>> +struct dpll_device *dpll_device_alloc(struct dpll_device_ops *ops, const char *name,
>>>> +				      int sources_count, int outputs_count, void *priv);
>>>> +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);
>>>> +#endif
>>>> diff --git a/include/uapi/linux/dpll.h b/include/uapi/linux/dpll.h
>>>> new file mode 100644
>>>> index 000000000000..fcbea5a5e4d6
>>>> --- /dev/null
>>>> +++ b/include/uapi/linux/dpll.h
>>>> @@ -0,0 +1,101 @@
>>>> +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
>>>> +#ifndef _UAPI_LINUX_DPLL_H
>>>> +#define _UAPI_LINUX_DPLL_H
>>>> +
>>>> +#define DPLL_NAME_LENGTH	20
>>>> +
>>>> +/* Adding event notification support elements */
>>>> +#define DPLL_FAMILY_NAME		"dpll"
>>>> +#define DPLL_VERSION			0x01
>>>> +#define DPLL_CONFIG_DEVICE_GROUP_NAME  "config"
>>>> +#define DPLL_CONFIG_SOURCE_GROUP_NAME  "source"
>>>> +#define DPLL_CONFIG_OUTPUT_GROUP_NAME  "output"
>>>> +#define DPLL_MONITOR_GROUP_NAME        "monitor"
>>>
>>> What is exactly the reason for multiple multicast groups? Why you don't
>>> use one?
>>>
>> Yes, I agree, there is no need to use multiple groups and I will remove them
>> in the next version.
>>
>>>
>>>> +
>>>> +#define DPLL_FLAG_SOURCES	1
>>>> +#define DPLL_FLAG_OUTPUTS	2
>>>> +#define DPLL_FLAG_STATUS	4
>>>
>>> I think it is more common to use either 0x prefix or (1<<X) expression
>>> But I don't think these flags are needed at all, if you have per-object
>>> messages.
>>>
>>>
>>>> +
>>>> +/* Attributes of dpll_genl_family */
>>>> +enum dpll_genl_attr {
>>>
>>> I don't see need for "genl" here.
>>> Also, it is common to have consistency betwee enum name and members name.
>>> For example:
>>>
>>> enum dpll_attr {
>>> 	DPLL_ATTR_UNSPEC,
>>> 	DPLL_ATTR_DEVICE_ID,
>>>
>>> 	...
>>> }
>>> This applies to all enums in this file.
>>>
>> Got it, naming is always hard task. Will update all of them in the next version.
>>
>>>
>>>> +	DPLLA_UNSPEC,
>>>> +	DPLLA_DEVICE_ID,
>>>> +	DPLLA_DEVICE_NAME,
>>>> +	DPLLA_SOURCE,
>>>> +	DPLLA_SOURCE_ID,
>>>
>>> "ID" sounds a bit odd. I think "index" would be more suitable.
>>>
>> I just wanted to have shorter names to better fit 80 columns per line restrictions.
> 
> I think that ID has a bit different semantics. If "INDEX" is too long
> for you (not sure why), use "IDX" perhaps?
> 
> 
>>>
>>>> +	DPLLA_SOURCE_TYPE,
>>>> +	DPLLA_SOURCE_SUPPORTED,
>>>> +	DPLLA_OUTPUT,
>>>> +	DPLLA_OUTPUT_ID,
>>>> +	DPLLA_OUTPUT_TYPE,
>>>> +	DPLLA_OUTPUT_SUPPORTED,
>>>> +	DPLLA_STATUS,
>>>> +	DPLLA_TEMP,
>>>> +	DPLLA_LOCK_STATUS,
>>>> +	DPLLA_FLAGS,
>>>> +
>>>> +	__DPLLA_MAX,
>>>> +};
>>>> +#define DPLLA_MAX (__DPLLA_MAX - 1)
>>>> +
>>>> +/* DPLL status provides information of device status */
>>>> +enum dpll_genl_status {
>>>> +	DPLL_STATUS_NONE,
>>>> +	DPLL_STATUS_CALIBRATING,
>>>> +	DPLL_STATUS_LOCKED,
>>>> +
>>>> +	__DPLL_STATUS_MAX,
>>>> +};
>>>> +#define DPLL_STATUS_MAX (__DPLL_STATUS_MAX - 1)
>>>> +
>>>> +/* DPLL signal types used as source or as output */
>>>> +enum dpll_genl_signal_type {
>>>> +	DPLL_TYPE_EXT_1PPS,
>>>> +	DPLL_TYPE_EXT_10MHZ,
>>>> +	DPLL_TYPE_SYNCE_ETH_PORT,
>>>> +	DPLL_TYPE_INT_OSCILLATOR,
>>>> +	DPLL_TYPE_GNSS,
>>>> +
>>>> +	__DPLL_TYPE_MAX,
>>>> +};
>>>> +#define DPLL_TYPE_MAX (__DPLL_TYPE_MAX - 1)
>>>> +
>>>> +/* DPLL lock status provides information of source used to lock the device */
>>>> +enum dpll_genl_lock_status {
>>>> +	DPLL_LOCK_STATUS_UNLOCKED,
>>>> +	DPLL_LOCK_STATUS_EXT_1PPS,
>>>> +	DPLL_LOCK_STATUS_EXT_10MHZ,
>>>> +	DPLL_LOCK_STATUS_SYNCE,
>>>> +	DPLL_LOCK_STATUS_INT_OSCILLATOR,
>>>> +	DPLL_LOCK_STATUS_GNSS,
>>>
>>> I find it a bit odd and redundant to have lock status here as a separate
>>> enum. You have a souce selected (either autoselected or manualy
>>> selected). Then the status is either:
>>> "UNLOCKED"
>>> "LOCKED"
>>> "HOLDOVER"
>>>
>>> Or something similar. The point is, don't have the "source type" as a
>>> part of lock status.
>>>
>>
>> Yes, it's a very good idea, I was thinking about the same, but it didn't end
>> up in the code.
>>
>>>
>>>> +
>>>> +	__DPLL_LOCK_STATUS_MAX,
>>>> +};
>>>> +#define DPLL_LOCK_STATUS_MAX (__DPLL_LOCK_STATUS_MAX - 1)
>>>> +
>>>> +/* Events of dpll_genl_family */
>>>> +enum dpll_genl_event {
>>>> +	DPLL_EVENT_UNSPEC,
>>>> +	DPLL_EVENT_DEVICE_CREATE,		/* DPLL device creation */
>>>> +	DPLL_EVENT_DEVICE_DELETE,		/* DPLL device deletion */
>>>> +	DPLL_EVENT_STATUS_LOCKED,		/* DPLL device locked to source */
>>>> +	DPLL_EVENT_STATUS_UNLOCKED,	/* DPLL device freerun */
>>>
>>> Again, redundant I belive. There should be one event,
>>> inside the message there should be and ATTR of the lock state.
>>>
>>> Also, I believe there are 2 options:
>>> 1) follow the existing netlink models and have:
>>> DPLL_EVENT_DEVICE_NEW
>>>     - sent for new device
>>>     - sent for change with device
>>> DPLL_EVENT_DEVICE_DEL
>>>     - sent for removed device
>>> 2)
>>> DPLL_EVENT_DEVICE_NEW
>>>     - sent for new device
>>> DPLL_EVENT_DEVICE_DEL
>>>     - sent for removed device
>>> DPLL_EVENT_DEVICE_CHANGE
>>>     - sent for change with device
>>>
>>> Bot options work fine I belive. The point is, you don't want to have
>>> "cmd" per one attr change. Changed the device, attrs are passed in one
>>> message.
>>>
>>
>> I will try to change events this way, thanks.
>>
>>>
>>>
>>>> +	DPLL_EVENT_SOURCE_CHANGE,		/* DPLL device source changed */
>>>
>>> Similar here, source of device changed, should be just one attr in
>>> device message, see above.
>>>
>>
>> The WIP right now is going the way to have separate objects representing
>> pins, which could be used as source/output or even mux device. And the whole
>> part about sources and outputs is going to change. But I'll keep in mind that
>> suggestion while implementing this new way.
> 
> Yeah, see my suggestion about the pins above. Good to hear that we are
> in sync.
> 
> 
>>
>>>
>>>> +	DPLL_EVENT_OUTPUT_CHANGE,		/* DPLL device output changed */
>>>
>>>
>>>> +
>>>> +	__DPLL_EVENT_MAX,
>>>> +};
>>>> +#define DPLL_EVENT_MAX (__DPLL_EVENT_MAX - 1)
>>>> +
>>>> +/* Commands supported by the dpll_genl_family */
>>>> +enum dpll_genl_cmd {
>>>> +	DPLL_CMD_UNSPEC,
>>>> +	DPLL_CMD_DEVICE_GET,	/* List of DPLL devices id */
>>>> +	DPLL_CMD_SET_SOURCE_TYPE,	/* Set the DPLL device source type */
>>>
>>> This is confusing, you select "source", not "type".
>>
>> As I said, we can have different types for one source.
> 
> Again, see above my comment suggesting to separate TYPE and SIGNAL.
> 
> 
> 
>>
>>>
>>> Please be consistent in naming:
>>> DPLL_CMD_*_GET/SET
>>
>> Sure
>>
>>>
>>> Also, to be consistend with other netlink interfaces, we don't need
>>> cmd per action, rather there should be OBJ_GET (can dump) and OBJ_SET
>>> commands, like this:
>>>      DPLL_CMD_DEVICE_GET (can dump all present devices)
>>>      	ATTR_SOURCE_SELECT_MODE (current one)
>>>      	ATTR_SOURCE_INDEX (currect one)
>>>      DPLL_CMD_DEVICE_SET
>>>      	ATTR_SOURCE_INDEX (to set)
>>>      DPLL_CMD_DEVICE_SET
>>>      	ATTR_SOURCE_SELECT_MODE (to set)
>>>
>>
>> I believe we have to provide all the possible (or suitable) attributes in SET
>> command too, to fully configure the source by one command only, right?
> 
> Yep.
> 
> 
>>
>> And I also think we have to provide special attribute to show which source is
>> actually used to sync to, like ATTR_CONNECTED.
> 
> Either that or it could be exposed by PERSONALITY set to INPUT of one of
> the pins. See my suggestion about pin personalities above.
> 
> 
>>
>>>
>>>> +	DPLL_CMD_SET_OUTPUT_TYPE,	/* Set the DPLL device output type */
>>>
>>> Similar to what I suggested for "source", we should
>>> enable to select the OUTPUT, the type should be static. Also instead,
>>> I belive we should have a list of outputs and basically just allow
>>> enable/disable individual outputs:
>>>      DPLL_CMD_OUTPUT_GET (can dump the list of available outputs)
>>> 	ATTR_ENABLED (or "CONNECTED" or whatever) of type bool
>>>      DPLL_CMD_OUTPUT_SET
>>> 	ATTR_ENABLED (or "CONNECTED" or whatever) of type bool
>>>
>>> This is suitable for SyncE for example, when you have multiple netdev ports
>>> that are connected as "outputs", you can enable exactly those you you want.
>>> Example:
>>> # To list the available outputs:
>>> -> DPLL_CMD_OUTPUT_GET - dump
>>>        ATTR_DEVICE_ID X
>>>
>>> <- DPLL_CMD_OUTPUT_GET
>>>        ATTR_DEVICE_ID X
>>>        ATTR_OUTPUT_INDEX 0
>>>        ATTR_OUTPUT_TYPE SYNCE_ETH_PORT
>>>        ATTR_OUTPUT_NETDEV_IFINDEX 20
>>>        ATTR_OUTPUT_ENABLED 0
>>>        ATTR_DEVICE_ID X
>>>        ATTR_OUTPUT_INDEX 1
>>>        ATTR_OUTPUT_TYPE SYNCE_ETH_PORT
>>>        ATTR_OUTPUT_NETDEV_IFINDEX 30
>>>        ATTR_OUTPUT_ENABLED 0
>>>
>>> # Now enable output with index 0
>>> -> DPLL_CMD_OUTPUT_SET
>>>        ATTR_DEVICE_ID X
>>>        ATTR_OUTPUT_INDEX 0
>>>        ATTR_OUTPUT_ENABLED 1
>>>
>> Well, in case when we have flexible outputs, we can provide this information
>> as special type, like DPLL_TYPE_DISABLED. Having other types configured on
>> the output will assume that the OUTPUT is enabled.
> 
> Either that or it could be configureg by setting the pin PERSONALITY
> set to DISCONNECTED See my suggestion about pin personalities above.
> 
> 
>>
>>>
>>>> +
>>>> +	__DPLL_CMD_MAX,
>>>> +};
>>>> +#define DPLL_CMD_MAX (__DPLL_CMD_MAX - 1)
>>>> +
>>>> +#endif /* _UAPI_LINUX_DPLL_H */
>>>> -- 
>>>> 2.27.0
>>>>
>>
>> Thanks for actionable feedback, I hope to prepare new version soon with all
>> the comments and suggestions addressed!
> 
> Thanks! Looking forward to it!
> 
>>
>>


^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 1/6] dpll: Add DPLL framework base functions
@ 2022-10-11 21:23           ` Vadim Fedorenko
  0 siblings, 0 replies; 67+ messages in thread
From: Vadim Fedorenko @ 2022-10-11 21:23 UTC (permalink / raw)
  To: Jiri Pirko
  Cc: Jakub Kicinski, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

On 11.10.2022 09:32, Jiri Pirko wrote:
> Mon, Oct 10, 2022 at 09:54:26PM CEST, vfedorenko@novek.ru wrote:
>> On 10.10.2022 10:18, Jiri Pirko wrote:
>>> Mon, Oct 10, 2022 at 03:17:59AM CEST, vfedorenko@novek.ru wrote:
>>>> From: Vadim Fedorenko <vadfed@fb.com>
>>>>
>>>> DPLL framework is used to represent and configure DPLL devices
>>>> in systems. Each device that has DPLL and can configure sources
>>>> and outputs can use this framework.
>>>>
>>>> Signed-off-by: Vadim Fedorenko <vadfed@fb.com>
>>>> Co-developed-by: Jakub Kicinski <kuba@kernel.org>
>>>> Co-developed-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
>>>> ---

[...]

>>>> +static int __dpll_cmd_device_dump_one(struct dpll_device *dpll,
>>>> +					   struct sk_buff *msg)
>>>> +{
>>>> +	if (nla_put_u32(msg, DPLLA_DEVICE_ID, dpll->id))
>>>> +		return -EMSGSIZE;
>>>> +
>>>> +	if (nla_put_string(msg, DPLLA_DEVICE_NAME, dev_name(&dpll->dev)))
>>>> +		return -EMSGSIZE;
>>>> +
>>>> +	return 0;
>>>> +}
>>>> +
>>>> +static int __dpll_cmd_dump_sources(struct dpll_device *dpll,
>>>> +					   struct sk_buff *msg)
>>>> +{
>>>> +	struct nlattr *src_attr;
>>>> +	int i, ret = 0, type;
>>>> +
>>>> +	for (i = 0; i < dpll->sources_count; i++) {
>>>> +		src_attr = nla_nest_start(msg, DPLLA_SOURCE);
>>>> +		if (!src_attr) {
>>>> +			ret = -EMSGSIZE;
>>>> +			break;
>>>> +		}
>>>> +		type = dpll->ops->get_source_type(dpll, i);
>>>> +		if (nla_put_u32(msg, DPLLA_SOURCE_ID, i) ||
>>>> +		    nla_put_u32(msg, DPLLA_SOURCE_TYPE, type)) {
>>>> +			nla_nest_cancel(msg, src_attr);
>>>> +			ret = -EMSGSIZE;
>>>> +			break;
>>>> +		}
>>>> +		if (dpll->ops->get_source_supported) {
>>>> +			for (type = 0; type <= DPLL_TYPE_MAX; type++) {
>>>> +				ret = dpll->ops->get_source_supported(dpll, i, type);
>>>
>>> Okay, this looks weird to me. This implicates that it is possible to
>>> have for example:
>>> source index 0 of type 10
>>> source index 0 of type 11
>>> Both possible.
>>>
>>> However, from how I understand this, each source if of certain fixed type.
>>> Either it is:
>>> SyncE port
>>> 1pps external input (SMA)
>>> 10MHZ external input (SMA)
>>> internal oscilator (free-running)
>>> GNSS (GPS)
>>>
>>> So for example:
>>> index 0, type: 1pps external input (SMA)
>>> index 1, type: 10MHZ external input (
>>> index 2, type: SyncE port, netdev ifindex: 20
>>> index 3, type: SyncE port, netdev ifindex: 30
>>>
>>> So 4 "source" objects, each of different type.
>>> In this case I can imagine that the netlink API might look something
>>> like:
>>> -> DPLL_CMD_SOURCE_GET - dump
>>>        ATTR_DEVICE_ID X
>>>
>>> <- DPLL_CMD_SOURCE_GET
>>>
>>>        ATTR_DEVICE_ID X
>>>        ATTR_SOURCE_INDEX 0
>>>        ATTR_SOURCE_TYPE EXT_1PPS
>>>        ATTR_DEVICE_ID X
>>>        ATTR_SOURCE_INDEX 1
>>>        ATTR_SOURCE_TYPE EXT_10MHZ
>>>        ATTR_DEVICE_ID X
>>>        ATTR_SOURCE_INDEX 2
>>>        ATTR_SOURCE_TYPE SYNCE_ETH_PORT
>>>        ATTR_SOURCE_NETDEV_IFINDEX 20
>>>
>>>        ATTR_DEVICE_ID X
>>>        ATTR_SOURCE_INDEX 3
>>>        ATTR_SOURCE_TYPE SYNCE_ETH_PORT
>>>        ATTR_SOURCE_NETDEV_IFINDEX 30
>>>
>>> You see kernel would dump 4 source objects.
>>>
>> I see your point. We do have hardware which allows changing type of SMA
>> connector, and even the direction, each SMA could be used as input/source or
>> output of different signals. But there are limitation, like not all SMAs can
>> produce IRIG-B signal or only some of them can be used to get GNSS 1PPS. The
> 
> Okay, so that is not the *type* of source, but rather attribute of it.
> Example:
> 
> $ dpll X show
> index 0
>    type EXT
>    signal 1PPS
>    supported_signals
>       1PPS 10MHz
> 
> $ dpll X set source index 1 signal_type 10MHz
> $ dpll X show
> index 0
>    type EXT
>    signal 10MHz
>    supported_signals
>       1PPS 10MHz
> 
> So one source with index 0 of type "EXT" (could be "SMA", does not
> matter) supports 1 signal types.
> 
> 
> Thinking about this more and to cover the case when one SMA could be
> potencially used for input and output. It already occured to me that
> source/output are quite similar, have similar/same attributes. What if
> they are merged together to say a "pin" object only with extra
> PERSONALITY attribute?
> 
> Example:
> 
> -> DPLL_CMD_PIN_GET - dump
>        ATTR_DEVICE_ID X
> 
> <- DPLL_CMD_PIN_GET
> 
>         ATTR_DEVICE_ID X
>         ATTR_PIN_INDEX 0
>         ATTR_PIN_TYPE EXT
>         ATTR_PIN_SIGNAL 1PPS   (selected signal)
>         ATTR_PIN_SUPPORTED_SIGNALS (nest)
>           ATTR_PIN_SIGNAL 1PPS
>           ATTR_PIN_SIGNAL 10MHZ
>         ATTR_PIN_PERSONALITY OUTPUT   (selected personality)
>         ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>           ATTR_PIN_PERSONALITY DISCONNECTED
>           ATTR_PIN_PERSONALITY INPUT
>           ATTR_PIN_PERSONALITY OUTPUT     (note this supports both input and
> 					  output)
> 
>         ATTR_DEVICE_ID X
>         ATTR_PIN_INDEX 1
>         ATTR_PIN_TYPE EXT
>         ATTR_PIN_SIGNAL 10MHz   (selected signal)
>         ATTR_PIN_SUPPORTED_SIGNALS (nest)
>           ATTR_PIN_SIGNAL 1PPS
>           ATTR_PIN_SIGNAL 10MHZ
>         ATTR_PIN_PERSONALITY DISCONNECTED   (selected personality - not
> 					    connected currently)
>         ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>           ATTR_PIN_PERSONALITY DISCONNECTED
>           ATTR_PIN_PERSONALITY INPUT      (note this supports only input)
> 
>         ATTR_DEVICE_ID X
>         ATTR_PIN_INDEX 2
>         ATTR_PIN_TYPE GNSS
>         ATTR_PIN_SIGNAL 1PPS   (selected signal)
>         ATTR_PIN_SUPPORTED_SIGNALS (nest)
>           ATTR_PIN_SIGNAL 1PPS
>         ATTR_PIN_PERSONALITY INPUT   (selected personality - note this is
> 				     now he selected source, being only
> 				     pin with INPUT personality)
>         ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>           ATTR_PIN_PERSONALITY DISCONNECTED
>           ATTR_PIN_PERSONALITY INPUT      (note this supports only input)
> 
>         ATTR_DEVICE_ID X
>         ATTR_PIN_INDEX 3
>         ATTR_PIN_TYPE SYNCE_ETH_PORT
>         ATTR_PIN_NETDEV_IFINDEX 20
>         ATTR_PIN_PERSONALITY OUTPUT   (selected personality)
>         ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>           ATTR_PIN_PERSONALITY DISCONNECTED
>           ATTR_PIN_PERSONALITY INPUT
>           ATTR_PIN_PERSONALITY OUTPUT     (note this supports both input and
> 					  output)
> 
>         ATTR_DEVICE_ID X
>         ATTR_PIN_INDEX 4
>         ATTR_PIN_TYPE SYNCE_ETH_PORT
>         ATTR_PIN_NETDEV_IFINDEX 30
>         ATTR_PIN_PERSONALITY OUTPUT   (selected personality)
>         ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>           ATTR_PIN_PERSONALITY DISCONNECTED
>           ATTR_PIN_PERSONALITY INPUT
>           ATTR_PIN_PERSONALITY OUTPUT     (note this supports both input and
> 					  output)
> 
> 
> This allows the user to actually see the full picture:
> 1) all input/output pins in a single list, no duplicates
> 2) each pin if of certain type (ATTR_PIN_TYPE) EXT/GNSS/SYNCE_ETH_PORT
> 3) the pins that can change signal type contain the selected and list of
>     supported signal types (ATTR_PIN_SIGNAL, ATTR_PIN_SUPPORTED_SIGNALS)
> 4) direction/connection of the pin to the DPLL is exposed over
>     ATTR_PIN_PERSONALITY. For each pin, the driver would expose it can
>     act as INPUT/OUTPUT and even more, it can indicate the pin can
>     disconnect from DPLL entirely (if possible).
> 5) user can select the source by setting ATTR_PIN_PERSONALITY of certain
>     pin to INPUT. Only one pin could be set to INPUT and that is the
>     souce of DPLL.
>     In case no pin have personality set to INPUT, the DPLL is
>     free-running.
> 
> This would introduce quite nice flexibility, exposes source/output
> capabilities and provides good visilibity of current configuration.
> 

My comments about this part are in the answer to the next message

> 
>> interface was created to cover such case. I believe we have to improve it to
>> cover SyncE configuration better, but I personally don't have SyncE hardware
>> ready to test and that's why I have to rely on suggestions from yours or
>> Arkadiusz's experience. From what I can see now there is need for special
>> attribute to link source to net device, and I'm happy to add it. In case of
>> fixed configuration of sources, the device should provide only one type as
>> supported and that's it.
>>
>>
>>>
>>>
>>>> +				if (ret && nla_put_u32(msg, DPLLA_SOURCE_SUPPORTED, type)) {
>>>> +					ret = -EMSGSIZE;
>>>> +					break;
>>>> +				}
>>>> +			}
>>>> +			ret = 0;
>>>> +		}
>>>> +		nla_nest_end(msg, src_attr);
>>>> +	}
>>>> +
>>>> +	return ret;
>>>> +}
>>>> +
>>>> +static int __dpll_cmd_dump_outputs(struct dpll_device *dpll,
>>>> +					   struct sk_buff *msg)
>>>> +{
>>>> +	struct nlattr *out_attr;
>>>> +	int i, ret = 0, type;
>>>> +
>>>> +	for (i = 0; i < dpll->outputs_count; i++) {
>>>> +		out_attr = nla_nest_start(msg, DPLLA_OUTPUT);
>>>> +		if (!out_attr) {
>>>> +			ret = -EMSGSIZE;
>>>> +			break;
>>>> +		}
>>>> +		type = dpll->ops->get_output_type(dpll, i);
>>>> +		if (nla_put_u32(msg, DPLLA_OUTPUT_ID, i) ||
>>>> +		    nla_put_u32(msg, DPLLA_OUTPUT_TYPE, type)) {
>>>> +			nla_nest_cancel(msg, out_attr);
>>>> +			ret = -EMSGSIZE;
>>>> +			break;
>>>> +		}
>>>> +		if (dpll->ops->get_output_supported) {
>>>> +			for (type = 0; type <= DPLL_TYPE_MAX; type++) {
>>>> +				ret = dpll->ops->get_output_supported(dpll, i, type);
>>>> +				if (ret && nla_put_u32(msg, DPLLA_OUTPUT_SUPPORTED, type)) {
>>>
>>> This I believe is similar to sources, see my comment above.
>>>
>> As I said, we have to cover the case when SMAs are flexible to configure.
>>
>>> I believe we should have separate commands to GET and SET outputs and
>>> sources. That would make the object separation clear and will also help
>>> event model. See below I suggestion how output netlink API may look
>>> like (comment in header file near enum dpll_genl_cmd definition).
>>>
>>>
>>>> +					ret = -EMSGSIZE;
>>>> +					break;
>>>> +				}
>>>> +			}
>>>> +			ret = 0;
>>>> +		}
>>>> +		nla_nest_end(msg, out_attr);
>>>> +	}
>>>> +
>>>> +	return ret;
>>>> +}
>>>> +
>>>> +static int __dpll_cmd_dump_status(struct dpll_device *dpll,
>>>> +					   struct sk_buff *msg)
>>>> +{
>>>> +	int ret;
>>>> +
>>>> +	if (dpll->ops->get_status) {
>>>> +		ret = dpll->ops->get_status(dpll);
>>>> +		if (nla_put_u32(msg, DPLLA_STATUS, ret))
>>>> +			return -EMSGSIZE;
>>>> +	}
>>>> +
>>>> +	if (dpll->ops->get_temp) {
>>>> +		ret = dpll->ops->get_temp(dpll);
>>>> +		if (nla_put_u32(msg, DPLLA_TEMP, ret))
>>>> +			return -EMSGSIZE;
>>>> +	}
>>>> +
>>>> +	if (dpll->ops->get_lock_status) {
>>>> +		ret = dpll->ops->get_lock_status(dpll);
>>>> +		if (nla_put_u32(msg, DPLLA_LOCK_STATUS, ret))
>>>> +			return -EMSGSIZE;
>>>> +	}
>>>> +
>>>> +	return 0;
>>>> +}
>>>> +
>>>> +static int
>>>> +dpll_device_dump_one(struct dpll_device *dpll, struct sk_buff *msg,
>>>> +		     u32 portid, u32 seq, int flags)
>>>> +{
>>>> +	struct nlattr *hdr;
>>>> +	int ret;
>>>> +
>>>> +	hdr = genlmsg_put(msg, portid, seq, &dpll_gnl_family, 0,
>>>> +			  DPLL_CMD_DEVICE_GET);
>>>> +	if (!hdr)
>>>> +		return -EMSGSIZE;
>>>> +
>>>> +	mutex_lock(&dpll->lock);
>>>> +	ret = __dpll_cmd_device_dump_one(dpll, msg);
>>>> +	if (ret)
>>>> +		goto out_unlock;
>>>> +
>>>> +	if (flags & DPLL_FLAG_SOURCES && dpll->ops->get_source_type) {
>>>> +		ret = __dpll_cmd_dump_sources(dpll, msg);
>>>> +		if (ret)
>>>> +			goto out_unlock;
>>>> +	}
>>>> +
>>>> +	if (flags & DPLL_FLAG_OUTPUTS && dpll->ops->get_output_type) {
>>>> +		ret = __dpll_cmd_dump_outputs(dpll, msg);
>>>> +		if (ret)
>>>> +			goto out_unlock;
>>>> +	}
>>>> +
>>>> +	if (flags & DPLL_FLAG_STATUS) {
>>>> +		ret = __dpll_cmd_dump_status(dpll, msg);
>>>> +		if (ret)
>>>> +			goto out_unlock;
>>>> +	}
>>>> +	mutex_unlock(&dpll->lock);
>>>> +	genlmsg_end(msg, hdr);
>>>> +
>>>> +	return 0;
>>>> +
>>>> +out_unlock:
>>>> +	mutex_unlock(&dpll->lock);
>>>> +	genlmsg_cancel(msg, hdr);
>>>> +
>>>> +	return ret;
>>>> +}
>>>> +
>>>> +static int dpll_genl_cmd_set_source(struct sk_buff *skb, struct genl_info *info)
>>>> +{
>>>> +	struct dpll_device *dpll = info->user_ptr[0];
>>>> +	struct nlattr **attrs = info->attrs;
>>>> +	int ret = 0, src_id, type;
>>>
>>> Enums.
>>>
>>
>> Sure.
>>
>>>> +
>>>> +	if (!attrs[DPLLA_SOURCE_ID] ||
>>>> +	    !attrs[DPLLA_SOURCE_TYPE])
>>>> +		return -EINVAL;
>>>> +
>>>> +	if (!dpll->ops->set_source_type)
>>>> +		return -EOPNOTSUPP;
>>>> +
>>>> +	src_id = nla_get_u32(attrs[DPLLA_SOURCE_ID]);
>>>> +	type = nla_get_u32(attrs[DPLLA_SOURCE_TYPE]);
>>>
>>>
>>> This looks odd to me. The user should just pass the index of source to
>>> select. Type should be static, and non-changeable.
>>>
>>>
>>>> +
>>>> +	mutex_lock(&dpll->lock);
>>>> +	ret = dpll->ops->set_source_type(dpll, src_id, type);
>>>> +	mutex_unlock(&dpll->lock);
>>>> +
>>>> +	return ret;
>>>> +}
>>>> +
>>>> +static int dpll_genl_cmd_set_output(struct sk_buff *skb, struct genl_info *info)
>>>> +{
>>>> +	struct dpll_device *dpll = info->user_ptr[0];
>>>> +	struct nlattr **attrs = info->attrs;
>>>> +	int ret = 0, out_id, type;
>>>
>>> Enums.
>>>
>>>
>>>> +
>>>> +	if (!attrs[DPLLA_OUTPUT_ID] ||
>>>> +	    !attrs[DPLLA_OUTPUT_TYPE])
>>>> +		return -EINVAL;
>>>> +
>>>> +	if (!dpll->ops->set_output_type)
>>>> +		return -EOPNOTSUPP;
>>>> +
>>>> +	out_id = nla_get_u32(attrs[DPLLA_OUTPUT_ID]);
>>>> +	type = nla_get_u32(attrs[DPLLA_OUTPUT_TYPE]);
>>>
>>> Same here, passing type here looks wrong.
>>>
>>>
>>>
>>>> +
>>>> +	mutex_lock(&dpll->lock);
>>>> +	ret = dpll->ops->set_output_type(dpll, out_id, type);
>>>> +	mutex_unlock(&dpll->lock);
>>>> +
>>>> +	return ret;
>>>> +}
>>>> +
>>>> +static int dpll_device_loop_cb(struct dpll_device *dpll, void *data)
>>>> +{
>>>> +	struct dpll_dump_ctx *ctx;
>>>> +	struct param *p = (struct param *)data;
>>>> +
>>>> +	ctx = dpll_dump_context(p->cb);
>>>> +
>>>> +	ctx->pos_idx = dpll->id;
>>>> +
>>>> +	return dpll_device_dump_one(dpll, p->msg, 0, 0, ctx->flags);
>>>> +}
>>>> +
>>>> +static int
>>>> +dpll_cmd_device_dump(struct sk_buff *skb, struct netlink_callback *cb)
>>>> +{
>>>> +	struct dpll_dump_ctx *ctx = dpll_dump_context(cb);
>>>> +	struct param p = { .cb = cb, .msg = skb };
>>>> +
>>>> +	return for_each_dpll_device(ctx->pos_idx, dpll_device_loop_cb, &p);
>>>> +}
>>>> +
>>>> +static int
>>>> +dpll_genl_cmd_device_get_id(struct sk_buff *skb, struct genl_info *info)
>>>
>>> Just "get", no "id" here.
>>>
>>
>> Got it.
>>
>>>
>>>> +{
>>>> +	struct dpll_device *dpll = info->user_ptr[0];
>>>> +	struct nlattr **attrs = info->attrs;
>>>> +	struct sk_buff *msg;
>>>> +	int flags = 0;
>>>> +	int ret;
>>>> +
>>>> +	if (attrs[DPLLA_FLAGS])
>>>> +		flags = nla_get_u32(attrs[DPLLA_FLAGS]);
>>>> +
>>>> +	msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
>>>> +	if (!msg)
>>>> +		return -ENOMEM;
>>>> +
>>>> +	ret = dpll_device_dump_one(dpll, msg, info->snd_portid, info->snd_seq,
>>>> +				   flags);
>>>> +	if (ret)
>>>> +		goto out_free_msg;
>>>> +
>>>> +	return genlmsg_reply(msg, info);
>>>> +
>>>> +out_free_msg:
>>>> +	nlmsg_free(msg);
>>>> +	return ret;
>>>> +
>>>> +}
>>>> +
>>>> +static int dpll_genl_cmd_start(struct netlink_callback *cb)
>>>> +{
>>>> +	const struct genl_dumpit_info *info = genl_dumpit_info(cb);
>>>> +	struct dpll_dump_ctx *ctx = dpll_dump_context(cb);
>>>> +
>>>> +	ctx->dev = NULL;
>>>> +	if (info->attrs[DPLLA_FLAGS])
>>>> +		ctx->flags = nla_get_u32(info->attrs[DPLLA_FLAGS]);
>>>> +	else
>>>> +		ctx->flags = 0;
>>>> +	ctx->pos_idx = 0;
>>>> +	ctx->pos_src_idx = 0;
>>>> +	ctx->pos_out_idx = 0;
>>>> +	return 0;
>>>> +}
>>>> +
>>>> +static int dpll_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
>>>> +						 struct genl_info *info)
>>>> +{
>>>> +	struct dpll_device *dpll_id = NULL, *dpll_name = NULL;
>>>> +
>>>> +	if (!info->attrs[DPLLA_DEVICE_ID] &&
>>>> +	    !info->attrs[DPLLA_DEVICE_NAME])
>>>> +		return -EINVAL;
>>>> +
>>>> +	if (info->attrs[DPLLA_DEVICE_ID]) {
>>>> +		u32 id = nla_get_u32(info->attrs[DPLLA_DEVICE_ID]);
>>>> +
>>>> +		dpll_id = dpll_device_get_by_id(id);
>>>> +		if (!dpll_id)
>>>> +			return -ENODEV;
>>>> +		info->user_ptr[0] = dpll_id;
>>>
>>> struct dpll_device *dpll should be stored here.
>>>
>>>
>>>> +	}
>>>> +	if (info->attrs[DPLLA_DEVICE_NAME]) {
>>>
>>> You define new API, have one clear handle for devices. Either name or
>>> ID. Having both is messy.
>>>
>> That was added after the discussion with Jakub and Arkadiusz where we agreed
>> that the device could be referenced either by index or by name. The example
>> is that userspace app can easily find specific DPLL device if it knows the
>> name provided by a driver of that specific device. Without searching through
>> sysfs to find index value. Later commands could be executed using index once
>> it's known through CMD_GET_DEVICE/ATTR_DEVICE_NAME.
> 
> What exacly is the name? What is the semantics? How the name is
> generated in case of multiple instances of the same driver. What happens
> if two drivers use the same name? Is the name predictable (in sense of
> "stable over reboots")?
>

The way we were thinking about name is that driver can provide it's own name 
based on the hardware values, like MAC address or any other unique identifier, 
or the subsystem will use 'dpll%d' template to create the device. In the first 
case names can be predictable and stable over reboots at the same time.

> 
>>>
>>>> +		const char *name = nla_data(info->attrs[DPLLA_DEVICE_NAME]);
>>>> +
>>>> +		dpll_name = dpll_device_get_by_name(name);
>>>> +		if (!dpll_name)
>>>> +			return -ENODEV;
>>>> +
>>>> +		if (dpll_id && dpll_name != dpll_id)
>>>> +			return -EINVAL;
>>>> +		info->user_ptr[0] = dpll_name;
>>>
>>> struct dpll_device *dpll should be stored here.
>>>
>>
>>
>> Didn't get you, where should we store it?
>> dpll_name and dpll_id are of type struct dpll_device*,
> 
> Ah sorry, you confused me with the "name"/"id" suffix. Why you don't
> have just one variable called "dpll" instead and have the check for both
> attrs being set at the beginning? Also, extack error message would be
> nice (not only here).
> 

Yeah, I will re-think that part, it definitely needs improvement.

> 
>> and they are compared to avoid situation when both index and name are
>> provided, but refer to different devices.
>>
>>>
>>>
>>>> +	}
>>>> +
>>>> +	return 0;
>>>> +}
>>>> +
>>>> +static const struct genl_ops dpll_genl_ops[] = {
>>>> +	{
>>>> +		.cmd	= DPLL_CMD_DEVICE_GET,
>>>> +		.flags  = GENL_UNS_ADMIN_PERM,
>>>> +		.start	= dpll_genl_cmd_start,
>>>> +		.dumpit	= dpll_cmd_device_dump,
>>>> +		.doit	= dpll_genl_cmd_device_get_id,
>>>> +		.policy	= dpll_genl_get_policy,
>>>> +		.maxattr = ARRAY_SIZE(dpll_genl_get_policy) - 1,
>>>> +	},
>>>> +	{
>>>> +		.cmd	= DPLL_CMD_SET_SOURCE_TYPE,
>>>> +		.flags	= GENL_UNS_ADMIN_PERM,
>>>> +		.doit	= dpll_genl_cmd_set_source,
>>>> +		.policy	= dpll_genl_set_source_policy,
>>>> +		.maxattr = ARRAY_SIZE(dpll_genl_set_source_policy) - 1,
>>>> +	},
>>>> +	{
>>>> +		.cmd	= DPLL_CMD_SET_OUTPUT_TYPE,
>>>> +		.flags	= GENL_UNS_ADMIN_PERM,
>>>> +		.doit	= dpll_genl_cmd_set_output,
>>>> +		.policy	= dpll_genl_set_output_policy,
>>>> +		.maxattr = ARRAY_SIZE(dpll_genl_set_output_policy) - 1,
>>>> +	},
>>>> +};
>>>> +
>>>> +static struct genl_family dpll_gnl_family __ro_after_init = {
>>>> +	.hdrsize	= 0,
>>>> +	.name		= DPLL_FAMILY_NAME,
>>>> +	.version	= DPLL_VERSION,
>>>> +	.ops		= dpll_genl_ops,
>>>> +	.n_ops		= ARRAY_SIZE(dpll_genl_ops),
>>>> +	.mcgrps		= dpll_genl_mcgrps,
>>>> +	.n_mcgrps	= ARRAY_SIZE(dpll_genl_mcgrps),
>>>> +	.pre_doit	= dpll_pre_doit,
>>>
>>> Have  .parallel_ops   = true,
>>> You have dpll->lock, you don't need genl, to protect you.
>>>
>>
>> Yep, sure, thanks!
>>
>>>
>>>> +};
>>>> +
>>>> +int __init dpll_netlink_init(void)
>>>> +{
>>>> +	return genl_register_family(&dpll_gnl_family);
>>>> +}
>>>> +
>>>> +void dpll_netlink_finish(void)
>>>> +{
>>>> +	genl_unregister_family(&dpll_gnl_family);
>>>> +}
>>>> +
>>>> +void __exit dpll_netlink_fini(void)
>>>> +{
>>>> +	dpll_netlink_finish();
>>>> +}
>>>> diff --git a/drivers/dpll/dpll_netlink.h b/drivers/dpll/dpll_netlink.h
>>>> new file mode 100644
>>>> index 000000000000..e2d100f59dd6
>>>> --- /dev/null
>>>> +++ b/drivers/dpll/dpll_netlink.h
>>>> @@ -0,0 +1,7 @@
>>>> +/* SPDX-License-Identifier: GPL-2.0 */
>>>> +/*
>>>> + *  Copyright (c) 2021 Meta Platforms, Inc. and affiliates
>>>> + */
>>>> +
>>>> +int __init dpll_netlink_init(void);
>>>> +void dpll_netlink_finish(void);
>>>> diff --git a/include/linux/dpll.h b/include/linux/dpll.h
>>>> new file mode 100644
>>>> index 000000000000..9d49b19d03d9
>>>> --- /dev/null
>>>> +++ b/include/linux/dpll.h
>>>> @@ -0,0 +1,29 @@
>>>> +/* SPDX-License-Identifier: GPL-2.0 */
>>>> +/*
>>>> + *  Copyright (c) 2021 Meta Platforms, Inc. and affiliates
>>>> + */
>>>> +
>>>> +#ifndef __DPLL_H__
>>>> +#define __DPLL_H__
>>>> +
>>>> +struct dpll_device;
>>>> +
>>>> +struct dpll_device_ops {
>>>> +	int (*get_status)(struct dpll_device *dpll);
>>>> +	int (*get_temp)(struct dpll_device *dpll);
>>>> +	int (*get_lock_status)(struct dpll_device *dpll);
>>>> +	int (*get_source_type)(struct dpll_device *dpll, int id);
>>>> +	int (*get_source_supported)(struct dpll_device *dpll, int id, int type);
>>>> +	int (*get_output_type)(struct dpll_device *dpll, int id);
>>>> +	int (*get_output_supported)(struct dpll_device *dpll, int id, int type);
>>>> +	int (*set_source_type)(struct dpll_device *dpll, int id, int val);
>>>> +	int (*set_output_type)(struct dpll_device *dpll, int id, int val);
>>>
>>> All int should be enums, when they are really enums. Makes things much
>>> nicer and easier to see what's what.
>>>
>> Yep, will update it.
>>>
>>>
>>>> +};
>>>> +
>>>> +struct dpll_device *dpll_device_alloc(struct dpll_device_ops *ops, const char *name,
>>>> +				      int sources_count, int outputs_count, void *priv);
>>>> +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);
>>>> +#endif
>>>> diff --git a/include/uapi/linux/dpll.h b/include/uapi/linux/dpll.h
>>>> new file mode 100644
>>>> index 000000000000..fcbea5a5e4d6
>>>> --- /dev/null
>>>> +++ b/include/uapi/linux/dpll.h
>>>> @@ -0,0 +1,101 @@
>>>> +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
>>>> +#ifndef _UAPI_LINUX_DPLL_H
>>>> +#define _UAPI_LINUX_DPLL_H
>>>> +
>>>> +#define DPLL_NAME_LENGTH	20
>>>> +
>>>> +/* Adding event notification support elements */
>>>> +#define DPLL_FAMILY_NAME		"dpll"
>>>> +#define DPLL_VERSION			0x01
>>>> +#define DPLL_CONFIG_DEVICE_GROUP_NAME  "config"
>>>> +#define DPLL_CONFIG_SOURCE_GROUP_NAME  "source"
>>>> +#define DPLL_CONFIG_OUTPUT_GROUP_NAME  "output"
>>>> +#define DPLL_MONITOR_GROUP_NAME        "monitor"
>>>
>>> What is exactly the reason for multiple multicast groups? Why you don't
>>> use one?
>>>
>> Yes, I agree, there is no need to use multiple groups and I will remove them
>> in the next version.
>>
>>>
>>>> +
>>>> +#define DPLL_FLAG_SOURCES	1
>>>> +#define DPLL_FLAG_OUTPUTS	2
>>>> +#define DPLL_FLAG_STATUS	4
>>>
>>> I think it is more common to use either 0x prefix or (1<<X) expression
>>> But I don't think these flags are needed at all, if you have per-object
>>> messages.
>>>
>>>
>>>> +
>>>> +/* Attributes of dpll_genl_family */
>>>> +enum dpll_genl_attr {
>>>
>>> I don't see need for "genl" here.
>>> Also, it is common to have consistency betwee enum name and members name.
>>> For example:
>>>
>>> enum dpll_attr {
>>> 	DPLL_ATTR_UNSPEC,
>>> 	DPLL_ATTR_DEVICE_ID,
>>>
>>> 	...
>>> }
>>> This applies to all enums in this file.
>>>
>> Got it, naming is always hard task. Will update all of them in the next version.
>>
>>>
>>>> +	DPLLA_UNSPEC,
>>>> +	DPLLA_DEVICE_ID,
>>>> +	DPLLA_DEVICE_NAME,
>>>> +	DPLLA_SOURCE,
>>>> +	DPLLA_SOURCE_ID,
>>>
>>> "ID" sounds a bit odd. I think "index" would be more suitable.
>>>
>> I just wanted to have shorter names to better fit 80 columns per line restrictions.
> 
> I think that ID has a bit different semantics. If "INDEX" is too long
> for you (not sure why), use "IDX" perhaps?
> 
> 
>>>
>>>> +	DPLLA_SOURCE_TYPE,
>>>> +	DPLLA_SOURCE_SUPPORTED,
>>>> +	DPLLA_OUTPUT,
>>>> +	DPLLA_OUTPUT_ID,
>>>> +	DPLLA_OUTPUT_TYPE,
>>>> +	DPLLA_OUTPUT_SUPPORTED,
>>>> +	DPLLA_STATUS,
>>>> +	DPLLA_TEMP,
>>>> +	DPLLA_LOCK_STATUS,
>>>> +	DPLLA_FLAGS,
>>>> +
>>>> +	__DPLLA_MAX,
>>>> +};
>>>> +#define DPLLA_MAX (__DPLLA_MAX - 1)
>>>> +
>>>> +/* DPLL status provides information of device status */
>>>> +enum dpll_genl_status {
>>>> +	DPLL_STATUS_NONE,
>>>> +	DPLL_STATUS_CALIBRATING,
>>>> +	DPLL_STATUS_LOCKED,
>>>> +
>>>> +	__DPLL_STATUS_MAX,
>>>> +};
>>>> +#define DPLL_STATUS_MAX (__DPLL_STATUS_MAX - 1)
>>>> +
>>>> +/* DPLL signal types used as source or as output */
>>>> +enum dpll_genl_signal_type {
>>>> +	DPLL_TYPE_EXT_1PPS,
>>>> +	DPLL_TYPE_EXT_10MHZ,
>>>> +	DPLL_TYPE_SYNCE_ETH_PORT,
>>>> +	DPLL_TYPE_INT_OSCILLATOR,
>>>> +	DPLL_TYPE_GNSS,
>>>> +
>>>> +	__DPLL_TYPE_MAX,
>>>> +};
>>>> +#define DPLL_TYPE_MAX (__DPLL_TYPE_MAX - 1)
>>>> +
>>>> +/* DPLL lock status provides information of source used to lock the device */
>>>> +enum dpll_genl_lock_status {
>>>> +	DPLL_LOCK_STATUS_UNLOCKED,
>>>> +	DPLL_LOCK_STATUS_EXT_1PPS,
>>>> +	DPLL_LOCK_STATUS_EXT_10MHZ,
>>>> +	DPLL_LOCK_STATUS_SYNCE,
>>>> +	DPLL_LOCK_STATUS_INT_OSCILLATOR,
>>>> +	DPLL_LOCK_STATUS_GNSS,
>>>
>>> I find it a bit odd and redundant to have lock status here as a separate
>>> enum. You have a souce selected (either autoselected or manualy
>>> selected). Then the status is either:
>>> "UNLOCKED"
>>> "LOCKED"
>>> "HOLDOVER"
>>>
>>> Or something similar. The point is, don't have the "source type" as a
>>> part of lock status.
>>>
>>
>> Yes, it's a very good idea, I was thinking about the same, but it didn't end
>> up in the code.
>>
>>>
>>>> +
>>>> +	__DPLL_LOCK_STATUS_MAX,
>>>> +};
>>>> +#define DPLL_LOCK_STATUS_MAX (__DPLL_LOCK_STATUS_MAX - 1)
>>>> +
>>>> +/* Events of dpll_genl_family */
>>>> +enum dpll_genl_event {
>>>> +	DPLL_EVENT_UNSPEC,
>>>> +	DPLL_EVENT_DEVICE_CREATE,		/* DPLL device creation */
>>>> +	DPLL_EVENT_DEVICE_DELETE,		/* DPLL device deletion */
>>>> +	DPLL_EVENT_STATUS_LOCKED,		/* DPLL device locked to source */
>>>> +	DPLL_EVENT_STATUS_UNLOCKED,	/* DPLL device freerun */
>>>
>>> Again, redundant I belive. There should be one event,
>>> inside the message there should be and ATTR of the lock state.
>>>
>>> Also, I believe there are 2 options:
>>> 1) follow the existing netlink models and have:
>>> DPLL_EVENT_DEVICE_NEW
>>>     - sent for new device
>>>     - sent for change with device
>>> DPLL_EVENT_DEVICE_DEL
>>>     - sent for removed device
>>> 2)
>>> DPLL_EVENT_DEVICE_NEW
>>>     - sent for new device
>>> DPLL_EVENT_DEVICE_DEL
>>>     - sent for removed device
>>> DPLL_EVENT_DEVICE_CHANGE
>>>     - sent for change with device
>>>
>>> Bot options work fine I belive. The point is, you don't want to have
>>> "cmd" per one attr change. Changed the device, attrs are passed in one
>>> message.
>>>
>>
>> I will try to change events this way, thanks.
>>
>>>
>>>
>>>> +	DPLL_EVENT_SOURCE_CHANGE,		/* DPLL device source changed */
>>>
>>> Similar here, source of device changed, should be just one attr in
>>> device message, see above.
>>>
>>
>> The WIP right now is going the way to have separate objects representing
>> pins, which could be used as source/output or even mux device. And the whole
>> part about sources and outputs is going to change. But I'll keep in mind that
>> suggestion while implementing this new way.
> 
> Yeah, see my suggestion about the pins above. Good to hear that we are
> in sync.
> 
> 
>>
>>>
>>>> +	DPLL_EVENT_OUTPUT_CHANGE,		/* DPLL device output changed */
>>>
>>>
>>>> +
>>>> +	__DPLL_EVENT_MAX,
>>>> +};
>>>> +#define DPLL_EVENT_MAX (__DPLL_EVENT_MAX - 1)
>>>> +
>>>> +/* Commands supported by the dpll_genl_family */
>>>> +enum dpll_genl_cmd {
>>>> +	DPLL_CMD_UNSPEC,
>>>> +	DPLL_CMD_DEVICE_GET,	/* List of DPLL devices id */
>>>> +	DPLL_CMD_SET_SOURCE_TYPE,	/* Set the DPLL device source type */
>>>
>>> This is confusing, you select "source", not "type".
>>
>> As I said, we can have different types for one source.
> 
> Again, see above my comment suggesting to separate TYPE and SIGNAL.
> 
> 
> 
>>
>>>
>>> Please be consistent in naming:
>>> DPLL_CMD_*_GET/SET
>>
>> Sure
>>
>>>
>>> Also, to be consistend with other netlink interfaces, we don't need
>>> cmd per action, rather there should be OBJ_GET (can dump) and OBJ_SET
>>> commands, like this:
>>>      DPLL_CMD_DEVICE_GET (can dump all present devices)
>>>      	ATTR_SOURCE_SELECT_MODE (current one)
>>>      	ATTR_SOURCE_INDEX (currect one)
>>>      DPLL_CMD_DEVICE_SET
>>>      	ATTR_SOURCE_INDEX (to set)
>>>      DPLL_CMD_DEVICE_SET
>>>      	ATTR_SOURCE_SELECT_MODE (to set)
>>>
>>
>> I believe we have to provide all the possible (or suitable) attributes in SET
>> command too, to fully configure the source by one command only, right?
> 
> Yep.
> 
> 
>>
>> And I also think we have to provide special attribute to show which source is
>> actually used to sync to, like ATTR_CONNECTED.
> 
> Either that or it could be exposed by PERSONALITY set to INPUT of one of
> the pins. See my suggestion about pin personalities above.
> 
> 
>>
>>>
>>>> +	DPLL_CMD_SET_OUTPUT_TYPE,	/* Set the DPLL device output type */
>>>
>>> Similar to what I suggested for "source", we should
>>> enable to select the OUTPUT, the type should be static. Also instead,
>>> I belive we should have a list of outputs and basically just allow
>>> enable/disable individual outputs:
>>>      DPLL_CMD_OUTPUT_GET (can dump the list of available outputs)
>>> 	ATTR_ENABLED (or "CONNECTED" or whatever) of type bool
>>>      DPLL_CMD_OUTPUT_SET
>>> 	ATTR_ENABLED (or "CONNECTED" or whatever) of type bool
>>>
>>> This is suitable for SyncE for example, when you have multiple netdev ports
>>> that are connected as "outputs", you can enable exactly those you you want.
>>> Example:
>>> # To list the available outputs:
>>> -> DPLL_CMD_OUTPUT_GET - dump
>>>        ATTR_DEVICE_ID X
>>>
>>> <- DPLL_CMD_OUTPUT_GET
>>>        ATTR_DEVICE_ID X
>>>        ATTR_OUTPUT_INDEX 0
>>>        ATTR_OUTPUT_TYPE SYNCE_ETH_PORT
>>>        ATTR_OUTPUT_NETDEV_IFINDEX 20
>>>        ATTR_OUTPUT_ENABLED 0
>>>        ATTR_DEVICE_ID X
>>>        ATTR_OUTPUT_INDEX 1
>>>        ATTR_OUTPUT_TYPE SYNCE_ETH_PORT
>>>        ATTR_OUTPUT_NETDEV_IFINDEX 30
>>>        ATTR_OUTPUT_ENABLED 0
>>>
>>> # Now enable output with index 0
>>> -> DPLL_CMD_OUTPUT_SET
>>>        ATTR_DEVICE_ID X
>>>        ATTR_OUTPUT_INDEX 0
>>>        ATTR_OUTPUT_ENABLED 1
>>>
>> Well, in case when we have flexible outputs, we can provide this information
>> as special type, like DPLL_TYPE_DISABLED. Having other types configured on
>> the output will assume that the OUTPUT is enabled.
> 
> Either that or it could be configureg by setting the pin PERSONALITY
> set to DISCONNECTED See my suggestion about pin personalities above.
> 
> 
>>
>>>
>>>> +
>>>> +	__DPLL_CMD_MAX,
>>>> +};
>>>> +#define DPLL_CMD_MAX (__DPLL_CMD_MAX - 1)
>>>> +
>>>> +#endif /* _UAPI_LINUX_DPLL_H */
>>>> -- 
>>>> 2.27.0
>>>>
>>
>> Thanks for actionable feedback, I hope to prepare new version soon with all
>> the comments and suggestions addressed!
> 
> Thanks! Looking forward to it!
> 
>>
>>


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 1/6] dpll: Add DPLL framework base functions
  2022-10-11  8:47           ` Jiri Pirko
@ 2022-10-11 21:31             ` Vadim Fedorenko
  -1 siblings, 0 replies; 67+ messages in thread
From: Vadim Fedorenko @ 2022-10-11 21:31 UTC (permalink / raw)
  To: Jiri Pirko
  Cc: Jakub Kicinski, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

On 11.10.2022 09:47, Jiri Pirko wrote:
> Tue, Oct 11, 2022 at 10:32:22AM CEST, jiri@resnulli.us wrote:
>> Mon, Oct 10, 2022 at 09:54:26PM CEST, vfedorenko@novek.ru wrote:
>>> On 10.10.2022 10:18, Jiri Pirko wrote:
>>>> Mon, Oct 10, 2022 at 03:17:59AM CEST, vfedorenko@novek.ru wrote:
>>>>> From: Vadim Fedorenko <vadfed@fb.com>
> 
> [...]
> 
> 
>>> I see your point. We do have hardware which allows changing type of SMA
>>> connector, and even the direction, each SMA could be used as input/source or
>>> output of different signals. But there are limitation, like not all SMAs can
>>> produce IRIG-B signal or only some of them can be used to get GNSS 1PPS. The
>>
>> Okay, so that is not the *type* of source, but rather attribute of it.
>> Example:
>>
>> $ dpll X show
>> index 0
>>   type EXT
>>   signal 1PPS
>>   supported_signals
>>      1PPS 10MHz
>>
>> $ dpll X set source index 1 signal_type 10MHz
>> $ dpll X show
>> index 0
>>   type EXT
>>   signal 10MHz
>>   supported_signals
>>      1PPS 10MHz
>>
>> So one source with index 0 of type "EXT" (could be "SMA", does not
>> matter) supports 1 signal types.
>>
>>
>> Thinking about this more and to cover the case when one SMA could be
>> potencially used for input and output. It already occured to me that
>> source/output are quite similar, have similar/same attributes. What if
>> they are merged together to say a "pin" object only with extra
>> PERSONALITY attribute?
>>
>> Example:
>>
>> -> DPLL_CMD_PIN_GET - dump
>>       ATTR_DEVICE_ID X
>>
>> <- DPLL_CMD_PIN_GET
>>
>>        ATTR_DEVICE_ID X
>>        ATTR_PIN_INDEX 0
>>        ATTR_PIN_TYPE EXT
>>        ATTR_PIN_SIGNAL 1PPS   (selected signal)
>>        ATTR_PIN_SUPPORTED_SIGNALS (nest)
>>          ATTR_PIN_SIGNAL 1PPS
>>          ATTR_PIN_SIGNAL 10MHZ
>>        ATTR_PIN_PERSONALITY OUTPUT   (selected personality)
>>        ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>>          ATTR_PIN_PERSONALITY DISCONNECTED
>>          ATTR_PIN_PERSONALITY INPUT
>>          ATTR_PIN_PERSONALITY OUTPUT     (note this supports both input and
>> 					  output)
>>
>>        ATTR_DEVICE_ID X
>>        ATTR_PIN_INDEX 1
>>        ATTR_PIN_TYPE EXT
>>        ATTR_PIN_SIGNAL 10MHz   (selected signal)
>>        ATTR_PIN_SUPPORTED_SIGNALS (nest)
>>          ATTR_PIN_SIGNAL 1PPS
>>          ATTR_PIN_SIGNAL 10MHZ
>>        ATTR_PIN_PERSONALITY DISCONNECTED   (selected personality - not
>> 					    connected currently)
>>        ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>>          ATTR_PIN_PERSONALITY DISCONNECTED
>>          ATTR_PIN_PERSONALITY INPUT      (note this supports only input)
>>
>>        ATTR_DEVICE_ID X
>>        ATTR_PIN_INDEX 2
>>        ATTR_PIN_TYPE GNSS
>>        ATTR_PIN_SIGNAL 1PPS   (selected signal)
>>        ATTR_PIN_SUPPORTED_SIGNALS (nest)
>>          ATTR_PIN_SIGNAL 1PPS
>>        ATTR_PIN_PERSONALITY INPUT   (selected personality - note this is
>> 				     now he selected source, being only
>> 				     pin with INPUT personality)
>>        ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>>          ATTR_PIN_PERSONALITY DISCONNECTED
>>          ATTR_PIN_PERSONALITY INPUT      (note this supports only input)
>>
>>        ATTR_DEVICE_ID X
>>        ATTR_PIN_INDEX 3
>>        ATTR_PIN_TYPE SYNCE_ETH_PORT
>>        ATTR_PIN_NETDEV_IFINDEX 20
>>        ATTR_PIN_PERSONALITY OUTPUT   (selected personality)
>>        ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>>          ATTR_PIN_PERSONALITY DISCONNECTED
>>          ATTR_PIN_PERSONALITY INPUT
>>          ATTR_PIN_PERSONALITY OUTPUT     (note this supports both input and
>> 					  output)
>>
>>        ATTR_DEVICE_ID X
>>        ATTR_PIN_INDEX 4
>>        ATTR_PIN_TYPE SYNCE_ETH_PORT
>>        ATTR_PIN_NETDEV_IFINDEX 30
>>        ATTR_PIN_PERSONALITY OUTPUT   (selected personality)
>>        ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>>          ATTR_PIN_PERSONALITY DISCONNECTED
>>          ATTR_PIN_PERSONALITY INPUT
>>          ATTR_PIN_PERSONALITY OUTPUT     (note this supports both input and
>> 					  output)
>>
>>
>> This allows the user to actually see the full picture:
>> 1) all input/output pins in a single list, no duplicates
>> 2) each pin if of certain type (ATTR_PIN_TYPE) EXT/GNSS/SYNCE_ETH_PORT
>> 3) the pins that can change signal type contain the selected and list of
>>    supported signal types (ATTR_PIN_SIGNAL, ATTR_PIN_SUPPORTED_SIGNALS)
>> 4) direction/connection of the pin to the DPLL is exposed over
>>    ATTR_PIN_PERSONALITY. For each pin, the driver would expose it can
>>    act as INPUT/OUTPUT and even more, it can indicate the pin can
>>    disconnect from DPLL entirely (if possible).
>> 5) user can select the source by setting ATTR_PIN_PERSONALITY of certain
>>    pin to INPUT. Only one pin could be set to INPUT and that is the
>>    souce of DPLL.
>>    In case no pin have personality set to INPUT, the DPLL is
>>    free-running.
> 
> Okay, thinking about it some more, I would leave the source select
> indepentent from the ATTR_PIN_PERSONALITY and selectable using device
> set cmd and separate attribute. It works better even more when consider
> autoselect mode.
> 
> Well of course only pins with ATTR_PIN_PERSONALITY INPUT could be
> selected as source.
> 

Overall, I agree with this proposal, and as I've already said, the work is going 
exactly the same way - to introduce pin object with separate set of attributes.
I don't really like 'PERSONALITY' naming, I think we have to find a better name. 
It looks like DIRECTION is slightly better. And the CONNECTED/DISCONNECTED 
should be different attribute. And we also need attribute PRIORITY to be able to 
configure (or hint) auto-select mode. There are also special objects called 
muxes, which consist of several inputs and one output, but they cannot 
synthonise signal, only pass one of the inputs to output. We are still in kind 
of discussion whether to have them as separate objects, or extend the amount of 
pins of DPLL device in this case. The problem again in the auto-select mode and 
priorities. It would be great to hear your thoughts about such objects.

>>
>> This would introduce quite nice flexibility, exposes source/output
>> capabilities and provides good visilibity of current configuration.
>>
>>
>>> interface was created to cover such case. I believe we have to improve it to
>>> cover SyncE configuration better, but I personally don't have SyncE hardware
>>> ready to test and that's why I have to rely on suggestions from yours or
>>> Arkadiusz's experience. From what I can see now there is need for special
>>> attribute to link source to net device, and I'm happy to add it. In case of
>>> fixed configuration of sources, the device should provide only one type as
>>> supported and that's it.
>>>
> 
> [...]


^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 1/6] dpll: Add DPLL framework base functions
@ 2022-10-11 21:31             ` Vadim Fedorenko
  0 siblings, 0 replies; 67+ messages in thread
From: Vadim Fedorenko @ 2022-10-11 21:31 UTC (permalink / raw)
  To: Jiri Pirko
  Cc: Jakub Kicinski, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

On 11.10.2022 09:47, Jiri Pirko wrote:
> Tue, Oct 11, 2022 at 10:32:22AM CEST, jiri@resnulli.us wrote:
>> Mon, Oct 10, 2022 at 09:54:26PM CEST, vfedorenko@novek.ru wrote:
>>> On 10.10.2022 10:18, Jiri Pirko wrote:
>>>> Mon, Oct 10, 2022 at 03:17:59AM CEST, vfedorenko@novek.ru wrote:
>>>>> From: Vadim Fedorenko <vadfed@fb.com>
> 
> [...]
> 
> 
>>> I see your point. We do have hardware which allows changing type of SMA
>>> connector, and even the direction, each SMA could be used as input/source or
>>> output of different signals. But there are limitation, like not all SMAs can
>>> produce IRIG-B signal or only some of them can be used to get GNSS 1PPS. The
>>
>> Okay, so that is not the *type* of source, but rather attribute of it.
>> Example:
>>
>> $ dpll X show
>> index 0
>>   type EXT
>>   signal 1PPS
>>   supported_signals
>>      1PPS 10MHz
>>
>> $ dpll X set source index 1 signal_type 10MHz
>> $ dpll X show
>> index 0
>>   type EXT
>>   signal 10MHz
>>   supported_signals
>>      1PPS 10MHz
>>
>> So one source with index 0 of type "EXT" (could be "SMA", does not
>> matter) supports 1 signal types.
>>
>>
>> Thinking about this more and to cover the case when one SMA could be
>> potencially used for input and output. It already occured to me that
>> source/output are quite similar, have similar/same attributes. What if
>> they are merged together to say a "pin" object only with extra
>> PERSONALITY attribute?
>>
>> Example:
>>
>> -> DPLL_CMD_PIN_GET - dump
>>       ATTR_DEVICE_ID X
>>
>> <- DPLL_CMD_PIN_GET
>>
>>        ATTR_DEVICE_ID X
>>        ATTR_PIN_INDEX 0
>>        ATTR_PIN_TYPE EXT
>>        ATTR_PIN_SIGNAL 1PPS   (selected signal)
>>        ATTR_PIN_SUPPORTED_SIGNALS (nest)
>>          ATTR_PIN_SIGNAL 1PPS
>>          ATTR_PIN_SIGNAL 10MHZ
>>        ATTR_PIN_PERSONALITY OUTPUT   (selected personality)
>>        ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>>          ATTR_PIN_PERSONALITY DISCONNECTED
>>          ATTR_PIN_PERSONALITY INPUT
>>          ATTR_PIN_PERSONALITY OUTPUT     (note this supports both input and
>> 					  output)
>>
>>        ATTR_DEVICE_ID X
>>        ATTR_PIN_INDEX 1
>>        ATTR_PIN_TYPE EXT
>>        ATTR_PIN_SIGNAL 10MHz   (selected signal)
>>        ATTR_PIN_SUPPORTED_SIGNALS (nest)
>>          ATTR_PIN_SIGNAL 1PPS
>>          ATTR_PIN_SIGNAL 10MHZ
>>        ATTR_PIN_PERSONALITY DISCONNECTED   (selected personality - not
>> 					    connected currently)
>>        ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>>          ATTR_PIN_PERSONALITY DISCONNECTED
>>          ATTR_PIN_PERSONALITY INPUT      (note this supports only input)
>>
>>        ATTR_DEVICE_ID X
>>        ATTR_PIN_INDEX 2
>>        ATTR_PIN_TYPE GNSS
>>        ATTR_PIN_SIGNAL 1PPS   (selected signal)
>>        ATTR_PIN_SUPPORTED_SIGNALS (nest)
>>          ATTR_PIN_SIGNAL 1PPS
>>        ATTR_PIN_PERSONALITY INPUT   (selected personality - note this is
>> 				     now he selected source, being only
>> 				     pin with INPUT personality)
>>        ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>>          ATTR_PIN_PERSONALITY DISCONNECTED
>>          ATTR_PIN_PERSONALITY INPUT      (note this supports only input)
>>
>>        ATTR_DEVICE_ID X
>>        ATTR_PIN_INDEX 3
>>        ATTR_PIN_TYPE SYNCE_ETH_PORT
>>        ATTR_PIN_NETDEV_IFINDEX 20
>>        ATTR_PIN_PERSONALITY OUTPUT   (selected personality)
>>        ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>>          ATTR_PIN_PERSONALITY DISCONNECTED
>>          ATTR_PIN_PERSONALITY INPUT
>>          ATTR_PIN_PERSONALITY OUTPUT     (note this supports both input and
>> 					  output)
>>
>>        ATTR_DEVICE_ID X
>>        ATTR_PIN_INDEX 4
>>        ATTR_PIN_TYPE SYNCE_ETH_PORT
>>        ATTR_PIN_NETDEV_IFINDEX 30
>>        ATTR_PIN_PERSONALITY OUTPUT   (selected personality)
>>        ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>>          ATTR_PIN_PERSONALITY DISCONNECTED
>>          ATTR_PIN_PERSONALITY INPUT
>>          ATTR_PIN_PERSONALITY OUTPUT     (note this supports both input and
>> 					  output)
>>
>>
>> This allows the user to actually see the full picture:
>> 1) all input/output pins in a single list, no duplicates
>> 2) each pin if of certain type (ATTR_PIN_TYPE) EXT/GNSS/SYNCE_ETH_PORT
>> 3) the pins that can change signal type contain the selected and list of
>>    supported signal types (ATTR_PIN_SIGNAL, ATTR_PIN_SUPPORTED_SIGNALS)
>> 4) direction/connection of the pin to the DPLL is exposed over
>>    ATTR_PIN_PERSONALITY. For each pin, the driver would expose it can
>>    act as INPUT/OUTPUT and even more, it can indicate the pin can
>>    disconnect from DPLL entirely (if possible).
>> 5) user can select the source by setting ATTR_PIN_PERSONALITY of certain
>>    pin to INPUT. Only one pin could be set to INPUT and that is the
>>    souce of DPLL.
>>    In case no pin have personality set to INPUT, the DPLL is
>>    free-running.
> 
> Okay, thinking about it some more, I would leave the source select
> indepentent from the ATTR_PIN_PERSONALITY and selectable using device
> set cmd and separate attribute. It works better even more when consider
> autoselect mode.
> 
> Well of course only pins with ATTR_PIN_PERSONALITY INPUT could be
> selected as source.
> 

Overall, I agree with this proposal, and as I've already said, the work is going 
exactly the same way - to introduce pin object with separate set of attributes.
I don't really like 'PERSONALITY' naming, I think we have to find a better name. 
It looks like DIRECTION is slightly better. And the CONNECTED/DISCONNECTED 
should be different attribute. And we also need attribute PRIORITY to be able to 
configure (or hint) auto-select mode. There are also special objects called 
muxes, which consist of several inputs and one output, but they cannot 
synthonise signal, only pass one of the inputs to output. We are still in kind 
of discussion whether to have them as separate objects, or extend the amount of 
pins of DPLL device in this case. The problem again in the auto-select mode and 
priorities. It would be great to hear your thoughts about such objects.

>>
>> This would introduce quite nice flexibility, exposes source/output
>> capabilities and provides good visilibity of current configuration.
>>
>>
>>> interface was created to cover such case. I believe we have to improve it to
>>> cover SyncE configuration better, but I personally don't have SyncE hardware
>>> ready to test and that's why I have to rely on suggestions from yours or
>>> Arkadiusz's experience. From what I can see now there is need for special
>>> attribute to link source to net device, and I'm happy to add it. In case of
>>> fixed configuration of sources, the device should provide only one type as
>>> supported and that's it.
>>>
> 
> [...]


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 1/6] dpll: Add DPLL framework base functions
  2022-10-11 21:31             ` Vadim Fedorenko
@ 2022-10-12  6:44               ` Jiri Pirko
  -1 siblings, 0 replies; 67+ messages in thread
From: Jiri Pirko @ 2022-10-12  6:44 UTC (permalink / raw)
  To: Vadim Fedorenko
  Cc: Jakub Kicinski, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

Tue, Oct 11, 2022 at 11:31:25PM CEST, vfedorenko@novek.ru wrote:
>On 11.10.2022 09:47, Jiri Pirko wrote:
>> Tue, Oct 11, 2022 at 10:32:22AM CEST, jiri@resnulli.us wrote:
>> > Mon, Oct 10, 2022 at 09:54:26PM CEST, vfedorenko@novek.ru wrote:
>> > > On 10.10.2022 10:18, Jiri Pirko wrote:
>> > > > Mon, Oct 10, 2022 at 03:17:59AM CEST, vfedorenko@novek.ru wrote:
>> > > > > From: Vadim Fedorenko <vadfed@fb.com>
>> 
>> [...]
>> 
>> 
>> > > I see your point. We do have hardware which allows changing type of SMA
>> > > connector, and even the direction, each SMA could be used as input/source or
>> > > output of different signals. But there are limitation, like not all SMAs can
>> > > produce IRIG-B signal or only some of them can be used to get GNSS 1PPS. The
>> > 
>> > Okay, so that is not the *type* of source, but rather attribute of it.
>> > Example:
>> > 
>> > $ dpll X show
>> > index 0
>> >   type EXT
>> >   signal 1PPS
>> >   supported_signals
>> >      1PPS 10MHz
>> > 
>> > $ dpll X set source index 1 signal_type 10MHz
>> > $ dpll X show
>> > index 0
>> >   type EXT
>> >   signal 10MHz
>> >   supported_signals
>> >      1PPS 10MHz
>> > 
>> > So one source with index 0 of type "EXT" (could be "SMA", does not
>> > matter) supports 1 signal types.
>> > 
>> > 
>> > Thinking about this more and to cover the case when one SMA could be
>> > potencially used for input and output. It already occured to me that
>> > source/output are quite similar, have similar/same attributes. What if
>> > they are merged together to say a "pin" object only with extra
>> > PERSONALITY attribute?
>> > 
>> > Example:
>> > 
>> > -> DPLL_CMD_PIN_GET - dump
>> >       ATTR_DEVICE_ID X
>> > 
>> > <- DPLL_CMD_PIN_GET
>> > 
>> >        ATTR_DEVICE_ID X
>> >        ATTR_PIN_INDEX 0
>> >        ATTR_PIN_TYPE EXT
>> >        ATTR_PIN_SIGNAL 1PPS   (selected signal)
>> >        ATTR_PIN_SUPPORTED_SIGNALS (nest)
>> >          ATTR_PIN_SIGNAL 1PPS
>> >          ATTR_PIN_SIGNAL 10MHZ
>> >        ATTR_PIN_PERSONALITY OUTPUT   (selected personality)
>> >        ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>> >          ATTR_PIN_PERSONALITY DISCONNECTED
>> >          ATTR_PIN_PERSONALITY INPUT
>> >          ATTR_PIN_PERSONALITY OUTPUT     (note this supports both input and
>> > 					  output)
>> > 
>> >        ATTR_DEVICE_ID X
>> >        ATTR_PIN_INDEX 1
>> >        ATTR_PIN_TYPE EXT
>> >        ATTR_PIN_SIGNAL 10MHz   (selected signal)
>> >        ATTR_PIN_SUPPORTED_SIGNALS (nest)
>> >          ATTR_PIN_SIGNAL 1PPS
>> >          ATTR_PIN_SIGNAL 10MHZ
>> >        ATTR_PIN_PERSONALITY DISCONNECTED   (selected personality - not
>> > 					    connected currently)
>> >        ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>> >          ATTR_PIN_PERSONALITY DISCONNECTED
>> >          ATTR_PIN_PERSONALITY INPUT      (note this supports only input)
>> > 
>> >        ATTR_DEVICE_ID X
>> >        ATTR_PIN_INDEX 2
>> >        ATTR_PIN_TYPE GNSS
>> >        ATTR_PIN_SIGNAL 1PPS   (selected signal)
>> >        ATTR_PIN_SUPPORTED_SIGNALS (nest)
>> >          ATTR_PIN_SIGNAL 1PPS
>> >        ATTR_PIN_PERSONALITY INPUT   (selected personality - note this is
>> > 				     now he selected source, being only
>> > 				     pin with INPUT personality)
>> >        ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>> >          ATTR_PIN_PERSONALITY DISCONNECTED
>> >          ATTR_PIN_PERSONALITY INPUT      (note this supports only input)
>> > 
>> >        ATTR_DEVICE_ID X
>> >        ATTR_PIN_INDEX 3
>> >        ATTR_PIN_TYPE SYNCE_ETH_PORT
>> >        ATTR_PIN_NETDEV_IFINDEX 20
>> >        ATTR_PIN_PERSONALITY OUTPUT   (selected personality)
>> >        ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>> >          ATTR_PIN_PERSONALITY DISCONNECTED
>> >          ATTR_PIN_PERSONALITY INPUT
>> >          ATTR_PIN_PERSONALITY OUTPUT     (note this supports both input and
>> > 					  output)
>> > 
>> >        ATTR_DEVICE_ID X
>> >        ATTR_PIN_INDEX 4
>> >        ATTR_PIN_TYPE SYNCE_ETH_PORT
>> >        ATTR_PIN_NETDEV_IFINDEX 30
>> >        ATTR_PIN_PERSONALITY OUTPUT   (selected personality)
>> >        ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>> >          ATTR_PIN_PERSONALITY DISCONNECTED
>> >          ATTR_PIN_PERSONALITY INPUT
>> >          ATTR_PIN_PERSONALITY OUTPUT     (note this supports both input and
>> > 					  output)
>> > 
>> > 
>> > This allows the user to actually see the full picture:
>> > 1) all input/output pins in a single list, no duplicates
>> > 2) each pin if of certain type (ATTR_PIN_TYPE) EXT/GNSS/SYNCE_ETH_PORT
>> > 3) the pins that can change signal type contain the selected and list of
>> >    supported signal types (ATTR_PIN_SIGNAL, ATTR_PIN_SUPPORTED_SIGNALS)
>> > 4) direction/connection of the pin to the DPLL is exposed over
>> >    ATTR_PIN_PERSONALITY. For each pin, the driver would expose it can
>> >    act as INPUT/OUTPUT and even more, it can indicate the pin can
>> >    disconnect from DPLL entirely (if possible).
>> > 5) user can select the source by setting ATTR_PIN_PERSONALITY of certain
>> >    pin to INPUT. Only one pin could be set to INPUT and that is the
>> >    souce of DPLL.
>> >    In case no pin have personality set to INPUT, the DPLL is
>> >    free-running.
>> 
>> Okay, thinking about it some more, I would leave the source select
>> indepentent from the ATTR_PIN_PERSONALITY and selectable using device
>> set cmd and separate attribute. It works better even more when consider
>> autoselect mode.
>> 
>> Well of course only pins with ATTR_PIN_PERSONALITY INPUT could be
>> selected as source.
>> 
>
>Overall, I agree with this proposal, and as I've already said, the work is
>going exactly the same way - to introduce pin object with separate set of
>attributes.
>I don't really like 'PERSONALITY' naming, I think we have to find a better
>name. It looks like DIRECTION is slightly better. And the
>CONNECTED/DISCONNECTED should be different attribute. And we also need

Yeah, it is a matter of implementation. I just thought that this is
possible to be done in a single attribute, because when the pin is
disconnected, the direction has no meaning.


>attribute PRIORITY to be able to configure (or hint) auto-select mode. There

Sure, I didn't put the PRIORITY attribute to the example, but I believe
it is very straightforward extension to add it.


>are also special objects called muxes, which consist of several inputs and
>one output, but they cannot synthonise signal, only pass one of the inputs to
>output. We are still in kind of discussion whether to have them as separate
>objects, or extend the amount of pins of DPLL device in this case. The
>problem again in the auto-select mode and priorities. It would be great to
>hear your thoughts about such objects.

Does the mux have any attribute/configuration valuable for the user.
If yes, it might make sense to have it as a separate object. Then we
can have it as a tree of object of type MUX with leaves of PIN.

The question really is, if the user needs to know about muxes and work
with them, or they can be abstracted out by the driver.

Could you elaborate a bit more why auto-select mode and priorities are
problematic with muxes in picture?


>
>> > 
>> > This would introduce quite nice flexibility, exposes source/output
>> > capabilities and provides good visilibity of current configuration.
>> > 
>> > 
>> > > interface was created to cover such case. I believe we have to improve it to
>> > > cover SyncE configuration better, but I personally don't have SyncE hardware
>> > > ready to test and that's why I have to rely on suggestions from yours or
>> > > Arkadiusz's experience. From what I can see now there is need for special
>> > > attribute to link source to net device, and I'm happy to add it. In case of
>> > > fixed configuration of sources, the device should provide only one type as
>> > > supported and that's it.
>> > > 
>> 
>> [...]
>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 1/6] dpll: Add DPLL framework base functions
@ 2022-10-12  6:44               ` Jiri Pirko
  0 siblings, 0 replies; 67+ messages in thread
From: Jiri Pirko @ 2022-10-12  6:44 UTC (permalink / raw)
  To: Vadim Fedorenko
  Cc: Jakub Kicinski, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

Tue, Oct 11, 2022 at 11:31:25PM CEST, vfedorenko@novek.ru wrote:
>On 11.10.2022 09:47, Jiri Pirko wrote:
>> Tue, Oct 11, 2022 at 10:32:22AM CEST, jiri@resnulli.us wrote:
>> > Mon, Oct 10, 2022 at 09:54:26PM CEST, vfedorenko@novek.ru wrote:
>> > > On 10.10.2022 10:18, Jiri Pirko wrote:
>> > > > Mon, Oct 10, 2022 at 03:17:59AM CEST, vfedorenko@novek.ru wrote:
>> > > > > From: Vadim Fedorenko <vadfed@fb.com>
>> 
>> [...]
>> 
>> 
>> > > I see your point. We do have hardware which allows changing type of SMA
>> > > connector, and even the direction, each SMA could be used as input/source or
>> > > output of different signals. But there are limitation, like not all SMAs can
>> > > produce IRIG-B signal or only some of them can be used to get GNSS 1PPS. The
>> > 
>> > Okay, so that is not the *type* of source, but rather attribute of it.
>> > Example:
>> > 
>> > $ dpll X show
>> > index 0
>> >   type EXT
>> >   signal 1PPS
>> >   supported_signals
>> >      1PPS 10MHz
>> > 
>> > $ dpll X set source index 1 signal_type 10MHz
>> > $ dpll X show
>> > index 0
>> >   type EXT
>> >   signal 10MHz
>> >   supported_signals
>> >      1PPS 10MHz
>> > 
>> > So one source with index 0 of type "EXT" (could be "SMA", does not
>> > matter) supports 1 signal types.
>> > 
>> > 
>> > Thinking about this more and to cover the case when one SMA could be
>> > potencially used for input and output. It already occured to me that
>> > source/output are quite similar, have similar/same attributes. What if
>> > they are merged together to say a "pin" object only with extra
>> > PERSONALITY attribute?
>> > 
>> > Example:
>> > 
>> > -> DPLL_CMD_PIN_GET - dump
>> >       ATTR_DEVICE_ID X
>> > 
>> > <- DPLL_CMD_PIN_GET
>> > 
>> >        ATTR_DEVICE_ID X
>> >        ATTR_PIN_INDEX 0
>> >        ATTR_PIN_TYPE EXT
>> >        ATTR_PIN_SIGNAL 1PPS   (selected signal)
>> >        ATTR_PIN_SUPPORTED_SIGNALS (nest)
>> >          ATTR_PIN_SIGNAL 1PPS
>> >          ATTR_PIN_SIGNAL 10MHZ
>> >        ATTR_PIN_PERSONALITY OUTPUT   (selected personality)
>> >        ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>> >          ATTR_PIN_PERSONALITY DISCONNECTED
>> >          ATTR_PIN_PERSONALITY INPUT
>> >          ATTR_PIN_PERSONALITY OUTPUT     (note this supports both input and
>> > 					  output)
>> > 
>> >        ATTR_DEVICE_ID X
>> >        ATTR_PIN_INDEX 1
>> >        ATTR_PIN_TYPE EXT
>> >        ATTR_PIN_SIGNAL 10MHz   (selected signal)
>> >        ATTR_PIN_SUPPORTED_SIGNALS (nest)
>> >          ATTR_PIN_SIGNAL 1PPS
>> >          ATTR_PIN_SIGNAL 10MHZ
>> >        ATTR_PIN_PERSONALITY DISCONNECTED   (selected personality - not
>> > 					    connected currently)
>> >        ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>> >          ATTR_PIN_PERSONALITY DISCONNECTED
>> >          ATTR_PIN_PERSONALITY INPUT      (note this supports only input)
>> > 
>> >        ATTR_DEVICE_ID X
>> >        ATTR_PIN_INDEX 2
>> >        ATTR_PIN_TYPE GNSS
>> >        ATTR_PIN_SIGNAL 1PPS   (selected signal)
>> >        ATTR_PIN_SUPPORTED_SIGNALS (nest)
>> >          ATTR_PIN_SIGNAL 1PPS
>> >        ATTR_PIN_PERSONALITY INPUT   (selected personality - note this is
>> > 				     now he selected source, being only
>> > 				     pin with INPUT personality)
>> >        ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>> >          ATTR_PIN_PERSONALITY DISCONNECTED
>> >          ATTR_PIN_PERSONALITY INPUT      (note this supports only input)
>> > 
>> >        ATTR_DEVICE_ID X
>> >        ATTR_PIN_INDEX 3
>> >        ATTR_PIN_TYPE SYNCE_ETH_PORT
>> >        ATTR_PIN_NETDEV_IFINDEX 20
>> >        ATTR_PIN_PERSONALITY OUTPUT   (selected personality)
>> >        ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>> >          ATTR_PIN_PERSONALITY DISCONNECTED
>> >          ATTR_PIN_PERSONALITY INPUT
>> >          ATTR_PIN_PERSONALITY OUTPUT     (note this supports both input and
>> > 					  output)
>> > 
>> >        ATTR_DEVICE_ID X
>> >        ATTR_PIN_INDEX 4
>> >        ATTR_PIN_TYPE SYNCE_ETH_PORT
>> >        ATTR_PIN_NETDEV_IFINDEX 30
>> >        ATTR_PIN_PERSONALITY OUTPUT   (selected personality)
>> >        ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>> >          ATTR_PIN_PERSONALITY DISCONNECTED
>> >          ATTR_PIN_PERSONALITY INPUT
>> >          ATTR_PIN_PERSONALITY OUTPUT     (note this supports both input and
>> > 					  output)
>> > 
>> > 
>> > This allows the user to actually see the full picture:
>> > 1) all input/output pins in a single list, no duplicates
>> > 2) each pin if of certain type (ATTR_PIN_TYPE) EXT/GNSS/SYNCE_ETH_PORT
>> > 3) the pins that can change signal type contain the selected and list of
>> >    supported signal types (ATTR_PIN_SIGNAL, ATTR_PIN_SUPPORTED_SIGNALS)
>> > 4) direction/connection of the pin to the DPLL is exposed over
>> >    ATTR_PIN_PERSONALITY. For each pin, the driver would expose it can
>> >    act as INPUT/OUTPUT and even more, it can indicate the pin can
>> >    disconnect from DPLL entirely (if possible).
>> > 5) user can select the source by setting ATTR_PIN_PERSONALITY of certain
>> >    pin to INPUT. Only one pin could be set to INPUT and that is the
>> >    souce of DPLL.
>> >    In case no pin have personality set to INPUT, the DPLL is
>> >    free-running.
>> 
>> Okay, thinking about it some more, I would leave the source select
>> indepentent from the ATTR_PIN_PERSONALITY and selectable using device
>> set cmd and separate attribute. It works better even more when consider
>> autoselect mode.
>> 
>> Well of course only pins with ATTR_PIN_PERSONALITY INPUT could be
>> selected as source.
>> 
>
>Overall, I agree with this proposal, and as I've already said, the work is
>going exactly the same way - to introduce pin object with separate set of
>attributes.
>I don't really like 'PERSONALITY' naming, I think we have to find a better
>name. It looks like DIRECTION is slightly better. And the
>CONNECTED/DISCONNECTED should be different attribute. And we also need

Yeah, it is a matter of implementation. I just thought that this is
possible to be done in a single attribute, because when the pin is
disconnected, the direction has no meaning.


>attribute PRIORITY to be able to configure (or hint) auto-select mode. There

Sure, I didn't put the PRIORITY attribute to the example, but I believe
it is very straightforward extension to add it.


>are also special objects called muxes, which consist of several inputs and
>one output, but they cannot synthonise signal, only pass one of the inputs to
>output. We are still in kind of discussion whether to have them as separate
>objects, or extend the amount of pins of DPLL device in this case. The
>problem again in the auto-select mode and priorities. It would be great to
>hear your thoughts about such objects.

Does the mux have any attribute/configuration valuable for the user.
If yes, it might make sense to have it as a separate object. Then we
can have it as a tree of object of type MUX with leaves of PIN.

The question really is, if the user needs to know about muxes and work
with them, or they can be abstracted out by the driver.

Could you elaborate a bit more why auto-select mode and priorities are
problematic with muxes in picture?


>
>> > 
>> > This would introduce quite nice flexibility, exposes source/output
>> > capabilities and provides good visilibity of current configuration.
>> > 
>> > 
>> > > interface was created to cover such case. I believe we have to improve it to
>> > > cover SyncE configuration better, but I personally don't have SyncE hardware
>> > > ready to test and that's why I have to rely on suggestions from yours or
>> > > Arkadiusz's experience. From what I can see now there is need for special
>> > > attribute to link source to net device, and I'm happy to add it. In case of
>> > > fixed configuration of sources, the device should provide only one type as
>> > > supported and that's it.
>> > > 
>> 
>> [...]
>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 1/6] dpll: Add DPLL framework base functions
  2022-10-11 21:23           ` Vadim Fedorenko
@ 2022-10-12 10:44             ` Jiri Pirko
  -1 siblings, 0 replies; 67+ messages in thread
From: Jiri Pirko @ 2022-10-12 10:44 UTC (permalink / raw)
  To: Vadim Fedorenko
  Cc: Jakub Kicinski, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

Tue, Oct 11, 2022 at 11:23:38PM CEST, vfedorenko@novek.ru wrote:
>On 11.10.2022 09:32, Jiri Pirko wrote:
>> Mon, Oct 10, 2022 at 09:54:26PM CEST, vfedorenko@novek.ru wrote:
>> > On 10.10.2022 10:18, Jiri Pirko wrote:
>> > > Mon, Oct 10, 2022 at 03:17:59AM CEST, vfedorenko@novek.ru wrote:
>> > > > From: Vadim Fedorenko <vadfed@fb.com>
>> > > > 
>> > > > DPLL framework is used to represent and configure DPLL devices
>> > > > in systems. Each device that has DPLL and can configure sources
>> > > > and outputs can use this framework.
>> > > > 
>> > > > Signed-off-by: Vadim Fedorenko <vadfed@fb.com>
>> > > > Co-developed-by: Jakub Kicinski <kuba@kernel.org>
>> > > > Co-developed-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
>> > > > ---
>

[...]


>> > > > +static int dpll_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
>> > > > +						 struct genl_info *info)
>> > > > +{
>> > > > +	struct dpll_device *dpll_id = NULL, *dpll_name = NULL;
>> > > > +
>> > > > +	if (!info->attrs[DPLLA_DEVICE_ID] &&
>> > > > +	    !info->attrs[DPLLA_DEVICE_NAME])
>> > > > +		return -EINVAL;
>> > > > +
>> > > > +	if (info->attrs[DPLLA_DEVICE_ID]) {
>> > > > +		u32 id = nla_get_u32(info->attrs[DPLLA_DEVICE_ID]);
>> > > > +
>> > > > +		dpll_id = dpll_device_get_by_id(id);
>> > > > +		if (!dpll_id)
>> > > > +			return -ENODEV;
>> > > > +		info->user_ptr[0] = dpll_id;
>> > > 
>> > > struct dpll_device *dpll should be stored here.
>> > > 
>> > > 
>> > > > +	}
>> > > > +	if (info->attrs[DPLLA_DEVICE_NAME]) {
>> > > 
>> > > You define new API, have one clear handle for devices. Either name or
>> > > ID. Having both is messy.
>> > > 
>> > That was added after the discussion with Jakub and Arkadiusz where we agreed
>> > that the device could be referenced either by index or by name. The example
>> > is that userspace app can easily find specific DPLL device if it knows the
>> > name provided by a driver of that specific device. Without searching through
>> > sysfs to find index value. Later commands could be executed using index once
>> > it's known through CMD_GET_DEVICE/ATTR_DEVICE_NAME.
>> 
>> What exacly is the name? What is the semantics? How the name is
>> generated in case of multiple instances of the same driver. What happens
>> if two drivers use the same name? Is the name predictable (in sense of
>> "stable over reboots")?
>> 
>
>The way we were thinking about name is that driver can provide it's own name
>based on the hardware values, like MAC address or any other unique
>identifier, or the subsystem will use 'dpll%d' template to create the device.
>In the first case names can be predictable and stable over reboots at the
>same time.

Well, I don't think it is in general good idea to allow the drivers such
flexibility in strings directly passed to userspace. From past
experience, it usually end up with mess which is very hard to control.
Therefore, I believe that the driver should pass info in struct of well
defined fields. Like for example THIS_MODULE, and dpll.c can get the
name by module_name()


[...]

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 1/6] dpll: Add DPLL framework base functions
@ 2022-10-12 10:44             ` Jiri Pirko
  0 siblings, 0 replies; 67+ messages in thread
From: Jiri Pirko @ 2022-10-12 10:44 UTC (permalink / raw)
  To: Vadim Fedorenko
  Cc: Jakub Kicinski, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

Tue, Oct 11, 2022 at 11:23:38PM CEST, vfedorenko@novek.ru wrote:
>On 11.10.2022 09:32, Jiri Pirko wrote:
>> Mon, Oct 10, 2022 at 09:54:26PM CEST, vfedorenko@novek.ru wrote:
>> > On 10.10.2022 10:18, Jiri Pirko wrote:
>> > > Mon, Oct 10, 2022 at 03:17:59AM CEST, vfedorenko@novek.ru wrote:
>> > > > From: Vadim Fedorenko <vadfed@fb.com>
>> > > > 
>> > > > DPLL framework is used to represent and configure DPLL devices
>> > > > in systems. Each device that has DPLL and can configure sources
>> > > > and outputs can use this framework.
>> > > > 
>> > > > Signed-off-by: Vadim Fedorenko <vadfed@fb.com>
>> > > > Co-developed-by: Jakub Kicinski <kuba@kernel.org>
>> > > > Co-developed-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
>> > > > ---
>

[...]


>> > > > +static int dpll_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
>> > > > +						 struct genl_info *info)
>> > > > +{
>> > > > +	struct dpll_device *dpll_id = NULL, *dpll_name = NULL;
>> > > > +
>> > > > +	if (!info->attrs[DPLLA_DEVICE_ID] &&
>> > > > +	    !info->attrs[DPLLA_DEVICE_NAME])
>> > > > +		return -EINVAL;
>> > > > +
>> > > > +	if (info->attrs[DPLLA_DEVICE_ID]) {
>> > > > +		u32 id = nla_get_u32(info->attrs[DPLLA_DEVICE_ID]);
>> > > > +
>> > > > +		dpll_id = dpll_device_get_by_id(id);
>> > > > +		if (!dpll_id)
>> > > > +			return -ENODEV;
>> > > > +		info->user_ptr[0] = dpll_id;
>> > > 
>> > > struct dpll_device *dpll should be stored here.
>> > > 
>> > > 
>> > > > +	}
>> > > > +	if (info->attrs[DPLLA_DEVICE_NAME]) {
>> > > 
>> > > You define new API, have one clear handle for devices. Either name or
>> > > ID. Having both is messy.
>> > > 
>> > That was added after the discussion with Jakub and Arkadiusz where we agreed
>> > that the device could be referenced either by index or by name. The example
>> > is that userspace app can easily find specific DPLL device if it knows the
>> > name provided by a driver of that specific device. Without searching through
>> > sysfs to find index value. Later commands could be executed using index once
>> > it's known through CMD_GET_DEVICE/ATTR_DEVICE_NAME.
>> 
>> What exacly is the name? What is the semantics? How the name is
>> generated in case of multiple instances of the same driver. What happens
>> if two drivers use the same name? Is the name predictable (in sense of
>> "stable over reboots")?
>> 
>
>The way we were thinking about name is that driver can provide it's own name
>based on the hardware values, like MAC address or any other unique
>identifier, or the subsystem will use 'dpll%d' template to create the device.
>In the first case names can be predictable and stable over reboots at the
>same time.

Well, I don't think it is in general good idea to allow the drivers such
flexibility in strings directly passed to userspace. From past
experience, it usually end up with mess which is very hard to control.
Therefore, I believe that the driver should pass info in struct of well
defined fields. Like for example THIS_MODULE, and dpll.c can get the
name by module_name()


[...]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 1/6] dpll: Add DPLL framework base functions
  2022-10-10  1:17   ` Vadim Fedorenko
@ 2022-10-12 10:47     ` Jiri Pirko
  -1 siblings, 0 replies; 67+ messages in thread
From: Jiri Pirko @ 2022-10-12 10:47 UTC (permalink / raw)
  To: Vadim Fedorenko
  Cc: Jakub Kicinski, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

Mon, Oct 10, 2022 at 03:17:59AM CEST, vfedorenko@novek.ru wrote:
>From: Vadim Fedorenko <vadfed@fb.com>
>
>DPLL framework is used to represent and configure DPLL devices
>in systems. Each device that has DPLL and can configure sources
>and outputs can use this framework.
>
>Signed-off-by: Vadim Fedorenko <vadfed@fb.com>
>Co-developed-by: Jakub Kicinski <kuba@kernel.org>
>Co-developed-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>


[...]


>+struct dpll_device *dpll_device_alloc(struct dpll_device_ops *ops, const char *name,
>+				      int sources_count, int outputs_count, void *priv)

Having constant array of "pins" would not work for SyncE. For example in
mlxsw driver, netdevs can appear and disappear within the device
lifetime (for example port splits, linecard provision). We need to
register/unregister pins dynamically.

[...]


^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 1/6] dpll: Add DPLL framework base functions
@ 2022-10-12 10:47     ` Jiri Pirko
  0 siblings, 0 replies; 67+ messages in thread
From: Jiri Pirko @ 2022-10-12 10:47 UTC (permalink / raw)
  To: Vadim Fedorenko
  Cc: Jakub Kicinski, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

Mon, Oct 10, 2022 at 03:17:59AM CEST, vfedorenko@novek.ru wrote:
>From: Vadim Fedorenko <vadfed@fb.com>
>
>DPLL framework is used to represent and configure DPLL devices
>in systems. Each device that has DPLL and can configure sources
>and outputs can use this framework.
>
>Signed-off-by: Vadim Fedorenko <vadfed@fb.com>
>Co-developed-by: Jakub Kicinski <kuba@kernel.org>
>Co-developed-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>


[...]


>+struct dpll_device *dpll_device_alloc(struct dpll_device_ops *ops, const char *name,
>+				      int sources_count, int outputs_count, void *priv)

Having constant array of "pins" would not work for SyncE. For example in
mlxsw driver, netdevs can appear and disappear within the device
lifetime (for example port splits, linecard provision). We need to
register/unregister pins dynamically.

[...]


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 6/6] ptp_ocp: implement DPLL ops
  2022-10-10  1:18   ` Vadim Fedorenko
@ 2022-10-12 15:14     ` Jiri Pirko
  -1 siblings, 0 replies; 67+ messages in thread
From: Jiri Pirko @ 2022-10-12 15:14 UTC (permalink / raw)
  To: Vadim Fedorenko
  Cc: Jakub Kicinski, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

Mon, Oct 10, 2022 at 03:18:04AM CEST, vfedorenko@novek.ru wrote:
>From: Vadim Fedorenko <vadfed@fb.com>

[...]

>+static int ptp_ocp_dpll_get_status(struct dpll_device *dpll)
>+{
>+	struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll);

Avoid cast from (void *), not needed. (I also mentioned this in RFCv2).


>+	int sync;
>+
>+	sync = ioread32(&bp->reg->status) & OCP_STATUS_IN_SYNC;
>+	return sync;
>+}
>+

[...]

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 6/6] ptp_ocp: implement DPLL ops
@ 2022-10-12 15:14     ` Jiri Pirko
  0 siblings, 0 replies; 67+ messages in thread
From: Jiri Pirko @ 2022-10-12 15:14 UTC (permalink / raw)
  To: Vadim Fedorenko
  Cc: Jakub Kicinski, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

Mon, Oct 10, 2022 at 03:18:04AM CEST, vfedorenko@novek.ru wrote:
>From: Vadim Fedorenko <vadfed@fb.com>

[...]

>+static int ptp_ocp_dpll_get_status(struct dpll_device *dpll)
>+{
>+	struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll);

Avoid cast from (void *), not needed. (I also mentioned this in RFCv2).


>+	int sync;
>+
>+	sync = ioread32(&bp->reg->status) & OCP_STATUS_IN_SYNC;
>+	return sync;
>+}
>+

[...]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 1/6] dpll: Add DPLL framework base functions
  2022-10-10  1:17   ` Vadim Fedorenko
@ 2022-10-12 16:51     ` Jiri Pirko
  -1 siblings, 0 replies; 67+ messages in thread
From: Jiri Pirko @ 2022-10-12 16:51 UTC (permalink / raw)
  To: Vadim Fedorenko
  Cc: Jakub Kicinski, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

Mon, Oct 10, 2022 at 03:17:59AM CEST, vfedorenko@novek.ru wrote:
>From: Vadim Fedorenko <vadfed@fb.com>
>
>DPLL framework is used to represent and configure DPLL devices
>in systems. Each device that has DPLL and can configure sources
>and outputs can use this framework.
>
>Signed-off-by: Vadim Fedorenko <vadfed@fb.com>
>Co-developed-by: Jakub Kicinski <kuba@kernel.org>
>Co-developed-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
>---

[..]

>+enum dpll_genl_status {
>+	DPLL_STATUS_NONE,
>+	DPLL_STATUS_CALIBRATING,
>+	DPLL_STATUS_LOCKED,
>+
>+	__DPLL_STATUS_MAX,
>+};
>+#define DPLL_STATUS_MAX (__DPLL_STATUS_MAX - 1)
>+

[..]

>+
>+/* DPLL lock status provides information of source used to lock the device */
>+enum dpll_genl_lock_status {
>+	DPLL_LOCK_STATUS_UNLOCKED,
>+	DPLL_LOCK_STATUS_EXT_1PPS,
>+	DPLL_LOCK_STATUS_EXT_10MHZ,
>+	DPLL_LOCK_STATUS_SYNCE,
>+	DPLL_LOCK_STATUS_INT_OSCILLATOR,
>+	DPLL_LOCK_STATUS_GNSS,
>+
>+	__DPLL_LOCK_STATUS_MAX,
>+};
>+#define DPLL_LOCK_STATUS_MAX (__DPLL_LOCK_STATUS_MAX - 1)

In addition to what I wrote in the previous reply where I suggested to
have lock status independent on type or source, I think we should merge
"status" and "lock status" to one attr/enum. Or any reason to have these
separate?


^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 1/6] dpll: Add DPLL framework base functions
@ 2022-10-12 16:51     ` Jiri Pirko
  0 siblings, 0 replies; 67+ messages in thread
From: Jiri Pirko @ 2022-10-12 16:51 UTC (permalink / raw)
  To: Vadim Fedorenko
  Cc: Jakub Kicinski, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

Mon, Oct 10, 2022 at 03:17:59AM CEST, vfedorenko@novek.ru wrote:
>From: Vadim Fedorenko <vadfed@fb.com>
>
>DPLL framework is used to represent and configure DPLL devices
>in systems. Each device that has DPLL and can configure sources
>and outputs can use this framework.
>
>Signed-off-by: Vadim Fedorenko <vadfed@fb.com>
>Co-developed-by: Jakub Kicinski <kuba@kernel.org>
>Co-developed-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
>---

[..]

>+enum dpll_genl_status {
>+	DPLL_STATUS_NONE,
>+	DPLL_STATUS_CALIBRATING,
>+	DPLL_STATUS_LOCKED,
>+
>+	__DPLL_STATUS_MAX,
>+};
>+#define DPLL_STATUS_MAX (__DPLL_STATUS_MAX - 1)
>+

[..]

>+
>+/* DPLL lock status provides information of source used to lock the device */
>+enum dpll_genl_lock_status {
>+	DPLL_LOCK_STATUS_UNLOCKED,
>+	DPLL_LOCK_STATUS_EXT_1PPS,
>+	DPLL_LOCK_STATUS_EXT_10MHZ,
>+	DPLL_LOCK_STATUS_SYNCE,
>+	DPLL_LOCK_STATUS_INT_OSCILLATOR,
>+	DPLL_LOCK_STATUS_GNSS,
>+
>+	__DPLL_LOCK_STATUS_MAX,
>+};
>+#define DPLL_LOCK_STATUS_MAX (__DPLL_LOCK_STATUS_MAX - 1)

In addition to what I wrote in the previous reply where I suggested to
have lock status independent on type or source, I think we should merge
"status" and "lock status" to one attr/enum. Or any reason to have these
separate?


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 1/6] dpll: Add DPLL framework base functions
  2022-10-12  6:44               ` Jiri Pirko
@ 2022-10-12 20:12                 ` Vadim Fedorenko
  -1 siblings, 0 replies; 67+ messages in thread
From: Vadim Fedorenko @ 2022-10-12 20:12 UTC (permalink / raw)
  To: Jiri Pirko
  Cc: Jakub Kicinski, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

On 12.10.2022 07:44, Jiri Pirko wrote:
> Tue, Oct 11, 2022 at 11:31:25PM CEST, vfedorenko@novek.ru wrote:
>> On 11.10.2022 09:47, Jiri Pirko wrote:
>>> Tue, Oct 11, 2022 at 10:32:22AM CEST, jiri@resnulli.us wrote:
>>>> Mon, Oct 10, 2022 at 09:54:26PM CEST, vfedorenko@novek.ru wrote:
>>>>> On 10.10.2022 10:18, Jiri Pirko wrote:
>>>>>> Mon, Oct 10, 2022 at 03:17:59AM CEST, vfedorenko@novek.ru wrote:
>>>>>>> From: Vadim Fedorenko <vadfed@fb.com>
>>>
>>> [...]
>>>
>>>
>>>>> I see your point. We do have hardware which allows changing type of SMA
>>>>> connector, and even the direction, each SMA could be used as input/source or
>>>>> output of different signals. But there are limitation, like not all SMAs can
>>>>> produce IRIG-B signal or only some of them can be used to get GNSS 1PPS. The
>>>>
>>>> Okay, so that is not the *type* of source, but rather attribute of it.
>>>> Example:
>>>>
>>>> $ dpll X show
>>>> index 0
>>>>    type EXT
>>>>    signal 1PPS
>>>>    supported_signals
>>>>       1PPS 10MHz
>>>>
>>>> $ dpll X set source index 1 signal_type 10MHz
>>>> $ dpll X show
>>>> index 0
>>>>    type EXT
>>>>    signal 10MHz
>>>>    supported_signals
>>>>       1PPS 10MHz
>>>>
>>>> So one source with index 0 of type "EXT" (could be "SMA", does not
>>>> matter) supports 1 signal types.
>>>>
>>>>
>>>> Thinking about this more and to cover the case when one SMA could be
>>>> potencially used for input and output. It already occured to me that
>>>> source/output are quite similar, have similar/same attributes. What if
>>>> they are merged together to say a "pin" object only with extra
>>>> PERSONALITY attribute?
>>>>
>>>> Example:
>>>>
>>>> -> DPLL_CMD_PIN_GET - dump
>>>>        ATTR_DEVICE_ID X
>>>>
>>>> <- DPLL_CMD_PIN_GET
>>>>
>>>>         ATTR_DEVICE_ID X
>>>>         ATTR_PIN_INDEX 0
>>>>         ATTR_PIN_TYPE EXT
>>>>         ATTR_PIN_SIGNAL 1PPS   (selected signal)
>>>>         ATTR_PIN_SUPPORTED_SIGNALS (nest)
>>>>           ATTR_PIN_SIGNAL 1PPS
>>>>           ATTR_PIN_SIGNAL 10MHZ
>>>>         ATTR_PIN_PERSONALITY OUTPUT   (selected personality)
>>>>         ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>>>>           ATTR_PIN_PERSONALITY DISCONNECTED
>>>>           ATTR_PIN_PERSONALITY INPUT
>>>>           ATTR_PIN_PERSONALITY OUTPUT     (note this supports both input and
>>>> 					  output)
>>>>
>>>>         ATTR_DEVICE_ID X
>>>>         ATTR_PIN_INDEX 1
>>>>         ATTR_PIN_TYPE EXT
>>>>         ATTR_PIN_SIGNAL 10MHz   (selected signal)
>>>>         ATTR_PIN_SUPPORTED_SIGNALS (nest)
>>>>           ATTR_PIN_SIGNAL 1PPS
>>>>           ATTR_PIN_SIGNAL 10MHZ
>>>>         ATTR_PIN_PERSONALITY DISCONNECTED   (selected personality - not
>>>> 					    connected currently)
>>>>         ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>>>>           ATTR_PIN_PERSONALITY DISCONNECTED
>>>>           ATTR_PIN_PERSONALITY INPUT      (note this supports only input)
>>>>
>>>>         ATTR_DEVICE_ID X
>>>>         ATTR_PIN_INDEX 2
>>>>         ATTR_PIN_TYPE GNSS
>>>>         ATTR_PIN_SIGNAL 1PPS   (selected signal)
>>>>         ATTR_PIN_SUPPORTED_SIGNALS (nest)
>>>>           ATTR_PIN_SIGNAL 1PPS
>>>>         ATTR_PIN_PERSONALITY INPUT   (selected personality - note this is
>>>> 				     now he selected source, being only
>>>> 				     pin with INPUT personality)
>>>>         ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>>>>           ATTR_PIN_PERSONALITY DISCONNECTED
>>>>           ATTR_PIN_PERSONALITY INPUT      (note this supports only input)
>>>>
>>>>         ATTR_DEVICE_ID X
>>>>         ATTR_PIN_INDEX 3
>>>>         ATTR_PIN_TYPE SYNCE_ETH_PORT
>>>>         ATTR_PIN_NETDEV_IFINDEX 20
>>>>         ATTR_PIN_PERSONALITY OUTPUT   (selected personality)
>>>>         ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>>>>           ATTR_PIN_PERSONALITY DISCONNECTED
>>>>           ATTR_PIN_PERSONALITY INPUT
>>>>           ATTR_PIN_PERSONALITY OUTPUT     (note this supports both input and
>>>> 					  output)
>>>>
>>>>         ATTR_DEVICE_ID X
>>>>         ATTR_PIN_INDEX 4
>>>>         ATTR_PIN_TYPE SYNCE_ETH_PORT
>>>>         ATTR_PIN_NETDEV_IFINDEX 30
>>>>         ATTR_PIN_PERSONALITY OUTPUT   (selected personality)
>>>>         ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>>>>           ATTR_PIN_PERSONALITY DISCONNECTED
>>>>           ATTR_PIN_PERSONALITY INPUT
>>>>           ATTR_PIN_PERSONALITY OUTPUT     (note this supports both input and
>>>> 					  output)
>>>>
>>>>
>>>> This allows the user to actually see the full picture:
>>>> 1) all input/output pins in a single list, no duplicates
>>>> 2) each pin if of certain type (ATTR_PIN_TYPE) EXT/GNSS/SYNCE_ETH_PORT
>>>> 3) the pins that can change signal type contain the selected and list of
>>>>     supported signal types (ATTR_PIN_SIGNAL, ATTR_PIN_SUPPORTED_SIGNALS)
>>>> 4) direction/connection of the pin to the DPLL is exposed over
>>>>     ATTR_PIN_PERSONALITY. For each pin, the driver would expose it can
>>>>     act as INPUT/OUTPUT and even more, it can indicate the pin can
>>>>     disconnect from DPLL entirely (if possible).
>>>> 5) user can select the source by setting ATTR_PIN_PERSONALITY of certain
>>>>     pin to INPUT. Only one pin could be set to INPUT and that is the
>>>>     souce of DPLL.
>>>>     In case no pin have personality set to INPUT, the DPLL is
>>>>     free-running.
>>>
>>> Okay, thinking about it some more, I would leave the source select
>>> indepentent from the ATTR_PIN_PERSONALITY and selectable using device
>>> set cmd and separate attribute. It works better even more when consider
>>> autoselect mode.
>>>
>>> Well of course only pins with ATTR_PIN_PERSONALITY INPUT could be
>>> selected as source.
>>>
>>
>> Overall, I agree with this proposal, and as I've already said, the work is
>> going exactly the same way - to introduce pin object with separate set of
>> attributes.
>> I don't really like 'PERSONALITY' naming, I think we have to find a better
>> name. It looks like DIRECTION is slightly better. And the
>> CONNECTED/DISCONNECTED should be different attribute. And we also need
> 
> Yeah, it is a matter of implementation. I just thought that this is
> possible to be done in a single attribute, because when the pin is
> disconnected, the direction has no meaning.
> 
> 
>> attribute PRIORITY to be able to configure (or hint) auto-select mode. There
> 
> Sure, I didn't put the PRIORITY attribute to the example, but I believe
> it is very straightforward extension to add it.
> 
> 
>> are also special objects called muxes, which consist of several inputs and
>> one output, but they cannot synthonise signal, only pass one of the inputs to
>> output. We are still in kind of discussion whether to have them as separate
>> objects, or extend the amount of pins of DPLL device in this case. The
>> problem again in the auto-select mode and priorities. It would be great to
>> hear your thoughts about such objects.
> 
> Does the mux have any attribute/configuration valuable for the user.
> If yes, it might make sense to have it as a separate object. Then we
> can have it as a tree of object of type MUX with leaves of PIN.

Yes, that was the first thought, but implementation details are not great for now.

> The question really is, if the user needs to know about muxes and work
> with them, or they can be abstracted out by the driver.

Both ways will work I believe. It's more like our will to give users full 
picture or hide it somehow with the implementation.
> 
> Could you elaborate a bit more why auto-select mode and priorities are
> problematic with muxes in picture?

AFAIU, some mux devices are not smart enough to make a decision suitable for 
autoselect for the pins they have. In this case the autoselect process is done 
in the DPLL device, which selects mux and not the pin directly. At the same time 
there could be muxes that are smart enough to make a decision, and it will be 
autoselect on top of autoselect (and several more layers) and it doesn't sound 
great to me. I believe Arkadiusz will explain the mux a bit better.

> 
> 
>>
>>>>
>>>> This would introduce quite nice flexibility, exposes source/output
>>>> capabilities and provides good visilibity of current configuration.
>>>>
>>>>
>>>>> interface was created to cover such case. I believe we have to improve it to
>>>>> cover SyncE configuration better, but I personally don't have SyncE hardware
>>>>> ready to test and that's why I have to rely on suggestions from yours or
>>>>> Arkadiusz's experience. From what I can see now there is need for special
>>>>> attribute to link source to net device, and I'm happy to add it. In case of
>>>>> fixed configuration of sources, the device should provide only one type as
>>>>> supported and that's it.
>>>>>
>>>
>>> [...]
>>


^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 1/6] dpll: Add DPLL framework base functions
@ 2022-10-12 20:12                 ` Vadim Fedorenko
  0 siblings, 0 replies; 67+ messages in thread
From: Vadim Fedorenko @ 2022-10-12 20:12 UTC (permalink / raw)
  To: Jiri Pirko
  Cc: Jakub Kicinski, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

On 12.10.2022 07:44, Jiri Pirko wrote:
> Tue, Oct 11, 2022 at 11:31:25PM CEST, vfedorenko@novek.ru wrote:
>> On 11.10.2022 09:47, Jiri Pirko wrote:
>>> Tue, Oct 11, 2022 at 10:32:22AM CEST, jiri@resnulli.us wrote:
>>>> Mon, Oct 10, 2022 at 09:54:26PM CEST, vfedorenko@novek.ru wrote:
>>>>> On 10.10.2022 10:18, Jiri Pirko wrote:
>>>>>> Mon, Oct 10, 2022 at 03:17:59AM CEST, vfedorenko@novek.ru wrote:
>>>>>>> From: Vadim Fedorenko <vadfed@fb.com>
>>>
>>> [...]
>>>
>>>
>>>>> I see your point. We do have hardware which allows changing type of SMA
>>>>> connector, and even the direction, each SMA could be used as input/source or
>>>>> output of different signals. But there are limitation, like not all SMAs can
>>>>> produce IRIG-B signal or only some of them can be used to get GNSS 1PPS. The
>>>>
>>>> Okay, so that is not the *type* of source, but rather attribute of it.
>>>> Example:
>>>>
>>>> $ dpll X show
>>>> index 0
>>>>    type EXT
>>>>    signal 1PPS
>>>>    supported_signals
>>>>       1PPS 10MHz
>>>>
>>>> $ dpll X set source index 1 signal_type 10MHz
>>>> $ dpll X show
>>>> index 0
>>>>    type EXT
>>>>    signal 10MHz
>>>>    supported_signals
>>>>       1PPS 10MHz
>>>>
>>>> So one source with index 0 of type "EXT" (could be "SMA", does not
>>>> matter) supports 1 signal types.
>>>>
>>>>
>>>> Thinking about this more and to cover the case when one SMA could be
>>>> potencially used for input and output. It already occured to me that
>>>> source/output are quite similar, have similar/same attributes. What if
>>>> they are merged together to say a "pin" object only with extra
>>>> PERSONALITY attribute?
>>>>
>>>> Example:
>>>>
>>>> -> DPLL_CMD_PIN_GET - dump
>>>>        ATTR_DEVICE_ID X
>>>>
>>>> <- DPLL_CMD_PIN_GET
>>>>
>>>>         ATTR_DEVICE_ID X
>>>>         ATTR_PIN_INDEX 0
>>>>         ATTR_PIN_TYPE EXT
>>>>         ATTR_PIN_SIGNAL 1PPS   (selected signal)
>>>>         ATTR_PIN_SUPPORTED_SIGNALS (nest)
>>>>           ATTR_PIN_SIGNAL 1PPS
>>>>           ATTR_PIN_SIGNAL 10MHZ
>>>>         ATTR_PIN_PERSONALITY OUTPUT   (selected personality)
>>>>         ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>>>>           ATTR_PIN_PERSONALITY DISCONNECTED
>>>>           ATTR_PIN_PERSONALITY INPUT
>>>>           ATTR_PIN_PERSONALITY OUTPUT     (note this supports both input and
>>>> 					  output)
>>>>
>>>>         ATTR_DEVICE_ID X
>>>>         ATTR_PIN_INDEX 1
>>>>         ATTR_PIN_TYPE EXT
>>>>         ATTR_PIN_SIGNAL 10MHz   (selected signal)
>>>>         ATTR_PIN_SUPPORTED_SIGNALS (nest)
>>>>           ATTR_PIN_SIGNAL 1PPS
>>>>           ATTR_PIN_SIGNAL 10MHZ
>>>>         ATTR_PIN_PERSONALITY DISCONNECTED   (selected personality - not
>>>> 					    connected currently)
>>>>         ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>>>>           ATTR_PIN_PERSONALITY DISCONNECTED
>>>>           ATTR_PIN_PERSONALITY INPUT      (note this supports only input)
>>>>
>>>>         ATTR_DEVICE_ID X
>>>>         ATTR_PIN_INDEX 2
>>>>         ATTR_PIN_TYPE GNSS
>>>>         ATTR_PIN_SIGNAL 1PPS   (selected signal)
>>>>         ATTR_PIN_SUPPORTED_SIGNALS (nest)
>>>>           ATTR_PIN_SIGNAL 1PPS
>>>>         ATTR_PIN_PERSONALITY INPUT   (selected personality - note this is
>>>> 				     now he selected source, being only
>>>> 				     pin with INPUT personality)
>>>>         ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>>>>           ATTR_PIN_PERSONALITY DISCONNECTED
>>>>           ATTR_PIN_PERSONALITY INPUT      (note this supports only input)
>>>>
>>>>         ATTR_DEVICE_ID X
>>>>         ATTR_PIN_INDEX 3
>>>>         ATTR_PIN_TYPE SYNCE_ETH_PORT
>>>>         ATTR_PIN_NETDEV_IFINDEX 20
>>>>         ATTR_PIN_PERSONALITY OUTPUT   (selected personality)
>>>>         ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>>>>           ATTR_PIN_PERSONALITY DISCONNECTED
>>>>           ATTR_PIN_PERSONALITY INPUT
>>>>           ATTR_PIN_PERSONALITY OUTPUT     (note this supports both input and
>>>> 					  output)
>>>>
>>>>         ATTR_DEVICE_ID X
>>>>         ATTR_PIN_INDEX 4
>>>>         ATTR_PIN_TYPE SYNCE_ETH_PORT
>>>>         ATTR_PIN_NETDEV_IFINDEX 30
>>>>         ATTR_PIN_PERSONALITY OUTPUT   (selected personality)
>>>>         ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>>>>           ATTR_PIN_PERSONALITY DISCONNECTED
>>>>           ATTR_PIN_PERSONALITY INPUT
>>>>           ATTR_PIN_PERSONALITY OUTPUT     (note this supports both input and
>>>> 					  output)
>>>>
>>>>
>>>> This allows the user to actually see the full picture:
>>>> 1) all input/output pins in a single list, no duplicates
>>>> 2) each pin if of certain type (ATTR_PIN_TYPE) EXT/GNSS/SYNCE_ETH_PORT
>>>> 3) the pins that can change signal type contain the selected and list of
>>>>     supported signal types (ATTR_PIN_SIGNAL, ATTR_PIN_SUPPORTED_SIGNALS)
>>>> 4) direction/connection of the pin to the DPLL is exposed over
>>>>     ATTR_PIN_PERSONALITY. For each pin, the driver would expose it can
>>>>     act as INPUT/OUTPUT and even more, it can indicate the pin can
>>>>     disconnect from DPLL entirely (if possible).
>>>> 5) user can select the source by setting ATTR_PIN_PERSONALITY of certain
>>>>     pin to INPUT. Only one pin could be set to INPUT and that is the
>>>>     souce of DPLL.
>>>>     In case no pin have personality set to INPUT, the DPLL is
>>>>     free-running.
>>>
>>> Okay, thinking about it some more, I would leave the source select
>>> indepentent from the ATTR_PIN_PERSONALITY and selectable using device
>>> set cmd and separate attribute. It works better even more when consider
>>> autoselect mode.
>>>
>>> Well of course only pins with ATTR_PIN_PERSONALITY INPUT could be
>>> selected as source.
>>>
>>
>> Overall, I agree with this proposal, and as I've already said, the work is
>> going exactly the same way - to introduce pin object with separate set of
>> attributes.
>> I don't really like 'PERSONALITY' naming, I think we have to find a better
>> name. It looks like DIRECTION is slightly better. And the
>> CONNECTED/DISCONNECTED should be different attribute. And we also need
> 
> Yeah, it is a matter of implementation. I just thought that this is
> possible to be done in a single attribute, because when the pin is
> disconnected, the direction has no meaning.
> 
> 
>> attribute PRIORITY to be able to configure (or hint) auto-select mode. There
> 
> Sure, I didn't put the PRIORITY attribute to the example, but I believe
> it is very straightforward extension to add it.
> 
> 
>> are also special objects called muxes, which consist of several inputs and
>> one output, but they cannot synthonise signal, only pass one of the inputs to
>> output. We are still in kind of discussion whether to have them as separate
>> objects, or extend the amount of pins of DPLL device in this case. The
>> problem again in the auto-select mode and priorities. It would be great to
>> hear your thoughts about such objects.
> 
> Does the mux have any attribute/configuration valuable for the user.
> If yes, it might make sense to have it as a separate object. Then we
> can have it as a tree of object of type MUX with leaves of PIN.

Yes, that was the first thought, but implementation details are not great for now.

> The question really is, if the user needs to know about muxes and work
> with them, or they can be abstracted out by the driver.

Both ways will work I believe. It's more like our will to give users full 
picture or hide it somehow with the implementation.
> 
> Could you elaborate a bit more why auto-select mode and priorities are
> problematic with muxes in picture?

AFAIU, some mux devices are not smart enough to make a decision suitable for 
autoselect for the pins they have. In this case the autoselect process is done 
in the DPLL device, which selects mux and not the pin directly. At the same time 
there could be muxes that are smart enough to make a decision, and it will be 
autoselect on top of autoselect (and several more layers) and it doesn't sound 
great to me. I believe Arkadiusz will explain the mux a bit better.

> 
> 
>>
>>>>
>>>> This would introduce quite nice flexibility, exposes source/output
>>>> capabilities and provides good visilibity of current configuration.
>>>>
>>>>
>>>>> interface was created to cover such case. I believe we have to improve it to
>>>>> cover SyncE configuration better, but I personally don't have SyncE hardware
>>>>> ready to test and that's why I have to rely on suggestions from yours or
>>>>> Arkadiusz's experience. From what I can see now there is need for special
>>>>> attribute to link source to net device, and I'm happy to add it. In case of
>>>>> fixed configuration of sources, the device should provide only one type as
>>>>> supported and that's it.
>>>>>
>>>
>>> [...]
>>


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 1/6] dpll: Add DPLL framework base functions
  2022-10-12 10:47     ` Jiri Pirko
@ 2022-10-12 20:15       ` Vadim Fedorenko
  -1 siblings, 0 replies; 67+ messages in thread
From: Vadim Fedorenko @ 2022-10-12 20:15 UTC (permalink / raw)
  To: Jiri Pirko
  Cc: Jakub Kicinski, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

On 12.10.2022 11:47, Jiri Pirko wrote:
> Mon, Oct 10, 2022 at 03:17:59AM CEST, vfedorenko@novek.ru wrote:
>> From: Vadim Fedorenko <vadfed@fb.com>
>>
>> DPLL framework is used to represent and configure DPLL devices
>> in systems. Each device that has DPLL and can configure sources
>> and outputs can use this framework.
>>
>> Signed-off-by: Vadim Fedorenko <vadfed@fb.com>
>> Co-developed-by: Jakub Kicinski <kuba@kernel.org>
>> Co-developed-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
> 
> 
> [...]
> 
> 
>> +struct dpll_device *dpll_device_alloc(struct dpll_device_ops *ops, const char *name,
>> +				      int sources_count, int outputs_count, void *priv)
> 
> Having constant array of "pins" would not work for SyncE. For example in
> mlxsw driver, netdevs can appear and disappear within the device
> lifetime (for example port splits, linecard provision). We need to
> register/unregister pins dynamically.
> 
Yes, I agree, and we are working to implement pin object with dynamic 
attach/detach or reg/unreg functions.

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 1/6] dpll: Add DPLL framework base functions
@ 2022-10-12 20:15       ` Vadim Fedorenko
  0 siblings, 0 replies; 67+ messages in thread
From: Vadim Fedorenko @ 2022-10-12 20:15 UTC (permalink / raw)
  To: Jiri Pirko
  Cc: Jakub Kicinski, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

On 12.10.2022 11:47, Jiri Pirko wrote:
> Mon, Oct 10, 2022 at 03:17:59AM CEST, vfedorenko@novek.ru wrote:
>> From: Vadim Fedorenko <vadfed@fb.com>
>>
>> DPLL framework is used to represent and configure DPLL devices
>> in systems. Each device that has DPLL and can configure sources
>> and outputs can use this framework.
>>
>> Signed-off-by: Vadim Fedorenko <vadfed@fb.com>
>> Co-developed-by: Jakub Kicinski <kuba@kernel.org>
>> Co-developed-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
> 
> 
> [...]
> 
> 
>> +struct dpll_device *dpll_device_alloc(struct dpll_device_ops *ops, const char *name,
>> +				      int sources_count, int outputs_count, void *priv)
> 
> Having constant array of "pins" would not work for SyncE. For example in
> mlxsw driver, netdevs can appear and disappear within the device
> lifetime (for example port splits, linecard provision). We need to
> register/unregister pins dynamically.
> 
Yes, I agree, and we are working to implement pin object with dynamic 
attach/detach or reg/unreg functions.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 1/6] dpll: Add DPLL framework base functions
  2022-10-12 16:51     ` Jiri Pirko
@ 2022-10-12 20:17       ` Vadim Fedorenko
  -1 siblings, 0 replies; 67+ messages in thread
From: Vadim Fedorenko @ 2022-10-12 20:17 UTC (permalink / raw)
  To: Jiri Pirko
  Cc: Jakub Kicinski, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

On 12.10.2022 17:51, Jiri Pirko wrote:
> Mon, Oct 10, 2022 at 03:17:59AM CEST, vfedorenko@novek.ru wrote:
>> From: Vadim Fedorenko <vadfed@fb.com>
>>
>> DPLL framework is used to represent and configure DPLL devices
>> in systems. Each device that has DPLL and can configure sources
>> and outputs can use this framework.
>>
>> Signed-off-by: Vadim Fedorenko <vadfed@fb.com>
>> Co-developed-by: Jakub Kicinski <kuba@kernel.org>
>> Co-developed-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
>> ---
> 
> [..]
> 
>> +enum dpll_genl_status {
>> +	DPLL_STATUS_NONE,
>> +	DPLL_STATUS_CALIBRATING,
>> +	DPLL_STATUS_LOCKED,
>> +
>> +	__DPLL_STATUS_MAX,
>> +};
>> +#define DPLL_STATUS_MAX (__DPLL_STATUS_MAX - 1)
>> +
> 
> [..]
> 
>> +
>> +/* DPLL lock status provides information of source used to lock the device */
>> +enum dpll_genl_lock_status {
>> +	DPLL_LOCK_STATUS_UNLOCKED,
>> +	DPLL_LOCK_STATUS_EXT_1PPS,
>> +	DPLL_LOCK_STATUS_EXT_10MHZ,
>> +	DPLL_LOCK_STATUS_SYNCE,
>> +	DPLL_LOCK_STATUS_INT_OSCILLATOR,
>> +	DPLL_LOCK_STATUS_GNSS,
>> +
>> +	__DPLL_LOCK_STATUS_MAX,
>> +};
>> +#define DPLL_LOCK_STATUS_MAX (__DPLL_LOCK_STATUS_MAX - 1)
> 
> In addition to what I wrote in the previous reply where I suggested to
> have lock status independent on type or source, I think we should merge
> "status" and "lock status" to one attr/enum. Or any reason to have these
> separate?
> 
Yep, agree. No reason to have it separate anymore.


^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 1/6] dpll: Add DPLL framework base functions
@ 2022-10-12 20:17       ` Vadim Fedorenko
  0 siblings, 0 replies; 67+ messages in thread
From: Vadim Fedorenko @ 2022-10-12 20:17 UTC (permalink / raw)
  To: Jiri Pirko
  Cc: Jakub Kicinski, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

On 12.10.2022 17:51, Jiri Pirko wrote:
> Mon, Oct 10, 2022 at 03:17:59AM CEST, vfedorenko@novek.ru wrote:
>> From: Vadim Fedorenko <vadfed@fb.com>
>>
>> DPLL framework is used to represent and configure DPLL devices
>> in systems. Each device that has DPLL and can configure sources
>> and outputs can use this framework.
>>
>> Signed-off-by: Vadim Fedorenko <vadfed@fb.com>
>> Co-developed-by: Jakub Kicinski <kuba@kernel.org>
>> Co-developed-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
>> ---
> 
> [..]
> 
>> +enum dpll_genl_status {
>> +	DPLL_STATUS_NONE,
>> +	DPLL_STATUS_CALIBRATING,
>> +	DPLL_STATUS_LOCKED,
>> +
>> +	__DPLL_STATUS_MAX,
>> +};
>> +#define DPLL_STATUS_MAX (__DPLL_STATUS_MAX - 1)
>> +
> 
> [..]
> 
>> +
>> +/* DPLL lock status provides information of source used to lock the device */
>> +enum dpll_genl_lock_status {
>> +	DPLL_LOCK_STATUS_UNLOCKED,
>> +	DPLL_LOCK_STATUS_EXT_1PPS,
>> +	DPLL_LOCK_STATUS_EXT_10MHZ,
>> +	DPLL_LOCK_STATUS_SYNCE,
>> +	DPLL_LOCK_STATUS_INT_OSCILLATOR,
>> +	DPLL_LOCK_STATUS_GNSS,
>> +
>> +	__DPLL_LOCK_STATUS_MAX,
>> +};
>> +#define DPLL_LOCK_STATUS_MAX (__DPLL_LOCK_STATUS_MAX - 1)
> 
> In addition to what I wrote in the previous reply where I suggested to
> have lock status independent on type or source, I think we should merge
> "status" and "lock status" to one attr/enum. Or any reason to have these
> separate?
> 
Yep, agree. No reason to have it separate anymore.


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 1/6] dpll: Add DPLL framework base functions
  2022-10-12 20:12                 ` Vadim Fedorenko
@ 2022-10-13  6:55                   ` Jiri Pirko
  -1 siblings, 0 replies; 67+ messages in thread
From: Jiri Pirko @ 2022-10-13  6:55 UTC (permalink / raw)
  To: Vadim Fedorenko
  Cc: Jakub Kicinski, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

Wed, Oct 12, 2022 at 10:12:43PM CEST, vfedorenko@novek.ru wrote:
>On 12.10.2022 07:44, Jiri Pirko wrote:
>> Tue, Oct 11, 2022 at 11:31:25PM CEST, vfedorenko@novek.ru wrote:
>> > On 11.10.2022 09:47, Jiri Pirko wrote:
>> > > Tue, Oct 11, 2022 at 10:32:22AM CEST, jiri@resnulli.us wrote:
>> > > > Mon, Oct 10, 2022 at 09:54:26PM CEST, vfedorenko@novek.ru wrote:
>> > > > > On 10.10.2022 10:18, Jiri Pirko wrote:
>> > > > > > Mon, Oct 10, 2022 at 03:17:59AM CEST, vfedorenko@novek.ru wrote:
>> > > > > > > From: Vadim Fedorenko <vadfed@fb.com>
>> > > 
>> > > [...]
>> > > 
>> > > 
>> > > > > I see your point. We do have hardware which allows changing type of SMA
>> > > > > connector, and even the direction, each SMA could be used as input/source or
>> > > > > output of different signals. But there are limitation, like not all SMAs can
>> > > > > produce IRIG-B signal or only some of them can be used to get GNSS 1PPS. The
>> > > > 
>> > > > Okay, so that is not the *type* of source, but rather attribute of it.
>> > > > Example:
>> > > > 
>> > > > $ dpll X show
>> > > > index 0
>> > > >    type EXT
>> > > >    signal 1PPS
>> > > >    supported_signals
>> > > >       1PPS 10MHz
>> > > > 
>> > > > $ dpll X set source index 1 signal_type 10MHz
>> > > > $ dpll X show
>> > > > index 0
>> > > >    type EXT
>> > > >    signal 10MHz
>> > > >    supported_signals
>> > > >       1PPS 10MHz
>> > > > 
>> > > > So one source with index 0 of type "EXT" (could be "SMA", does not
>> > > > matter) supports 1 signal types.
>> > > > 
>> > > > 
>> > > > Thinking about this more and to cover the case when one SMA could be
>> > > > potencially used for input and output. It already occured to me that
>> > > > source/output are quite similar, have similar/same attributes. What if
>> > > > they are merged together to say a "pin" object only with extra
>> > > > PERSONALITY attribute?
>> > > > 
>> > > > Example:
>> > > > 
>> > > > -> DPLL_CMD_PIN_GET - dump
>> > > >        ATTR_DEVICE_ID X
>> > > > 
>> > > > <- DPLL_CMD_PIN_GET
>> > > > 
>> > > >         ATTR_DEVICE_ID X
>> > > >         ATTR_PIN_INDEX 0
>> > > >         ATTR_PIN_TYPE EXT
>> > > >         ATTR_PIN_SIGNAL 1PPS   (selected signal)
>> > > >         ATTR_PIN_SUPPORTED_SIGNALS (nest)
>> > > >           ATTR_PIN_SIGNAL 1PPS
>> > > >           ATTR_PIN_SIGNAL 10MHZ
>> > > >         ATTR_PIN_PERSONALITY OUTPUT   (selected personality)
>> > > >         ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>> > > >           ATTR_PIN_PERSONALITY DISCONNECTED
>> > > >           ATTR_PIN_PERSONALITY INPUT
>> > > >           ATTR_PIN_PERSONALITY OUTPUT     (note this supports both input and
>> > > > 					  output)
>> > > > 
>> > > >         ATTR_DEVICE_ID X
>> > > >         ATTR_PIN_INDEX 1
>> > > >         ATTR_PIN_TYPE EXT
>> > > >         ATTR_PIN_SIGNAL 10MHz   (selected signal)
>> > > >         ATTR_PIN_SUPPORTED_SIGNALS (nest)
>> > > >           ATTR_PIN_SIGNAL 1PPS
>> > > >           ATTR_PIN_SIGNAL 10MHZ
>> > > >         ATTR_PIN_PERSONALITY DISCONNECTED   (selected personality - not
>> > > > 					    connected currently)
>> > > >         ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>> > > >           ATTR_PIN_PERSONALITY DISCONNECTED
>> > > >           ATTR_PIN_PERSONALITY INPUT      (note this supports only input)
>> > > > 
>> > > >         ATTR_DEVICE_ID X
>> > > >         ATTR_PIN_INDEX 2
>> > > >         ATTR_PIN_TYPE GNSS
>> > > >         ATTR_PIN_SIGNAL 1PPS   (selected signal)
>> > > >         ATTR_PIN_SUPPORTED_SIGNALS (nest)
>> > > >           ATTR_PIN_SIGNAL 1PPS
>> > > >         ATTR_PIN_PERSONALITY INPUT   (selected personality - note this is
>> > > > 				     now he selected source, being only
>> > > > 				     pin with INPUT personality)
>> > > >         ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>> > > >           ATTR_PIN_PERSONALITY DISCONNECTED
>> > > >           ATTR_PIN_PERSONALITY INPUT      (note this supports only input)
>> > > > 
>> > > >         ATTR_DEVICE_ID X
>> > > >         ATTR_PIN_INDEX 3
>> > > >         ATTR_PIN_TYPE SYNCE_ETH_PORT
>> > > >         ATTR_PIN_NETDEV_IFINDEX 20
>> > > >         ATTR_PIN_PERSONALITY OUTPUT   (selected personality)
>> > > >         ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>> > > >           ATTR_PIN_PERSONALITY DISCONNECTED
>> > > >           ATTR_PIN_PERSONALITY INPUT
>> > > >           ATTR_PIN_PERSONALITY OUTPUT     (note this supports both input and
>> > > > 					  output)
>> > > > 
>> > > >         ATTR_DEVICE_ID X
>> > > >         ATTR_PIN_INDEX 4
>> > > >         ATTR_PIN_TYPE SYNCE_ETH_PORT
>> > > >         ATTR_PIN_NETDEV_IFINDEX 30
>> > > >         ATTR_PIN_PERSONALITY OUTPUT   (selected personality)
>> > > >         ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>> > > >           ATTR_PIN_PERSONALITY DISCONNECTED
>> > > >           ATTR_PIN_PERSONALITY INPUT
>> > > >           ATTR_PIN_PERSONALITY OUTPUT     (note this supports both input and
>> > > > 					  output)
>> > > > 
>> > > > 
>> > > > This allows the user to actually see the full picture:
>> > > > 1) all input/output pins in a single list, no duplicates
>> > > > 2) each pin if of certain type (ATTR_PIN_TYPE) EXT/GNSS/SYNCE_ETH_PORT
>> > > > 3) the pins that can change signal type contain the selected and list of
>> > > >     supported signal types (ATTR_PIN_SIGNAL, ATTR_PIN_SUPPORTED_SIGNALS)
>> > > > 4) direction/connection of the pin to the DPLL is exposed over
>> > > >     ATTR_PIN_PERSONALITY. For each pin, the driver would expose it can
>> > > >     act as INPUT/OUTPUT and even more, it can indicate the pin can
>> > > >     disconnect from DPLL entirely (if possible).
>> > > > 5) user can select the source by setting ATTR_PIN_PERSONALITY of certain
>> > > >     pin to INPUT. Only one pin could be set to INPUT and that is the
>> > > >     souce of DPLL.
>> > > >     In case no pin have personality set to INPUT, the DPLL is
>> > > >     free-running.
>> > > 
>> > > Okay, thinking about it some more, I would leave the source select
>> > > indepentent from the ATTR_PIN_PERSONALITY and selectable using device
>> > > set cmd and separate attribute. It works better even more when consider
>> > > autoselect mode.
>> > > 
>> > > Well of course only pins with ATTR_PIN_PERSONALITY INPUT could be
>> > > selected as source.
>> > > 
>> > 
>> > Overall, I agree with this proposal, and as I've already said, the work is
>> > going exactly the same way - to introduce pin object with separate set of
>> > attributes.
>> > I don't really like 'PERSONALITY' naming, I think we have to find a better
>> > name. It looks like DIRECTION is slightly better. And the
>> > CONNECTED/DISCONNECTED should be different attribute. And we also need
>> 
>> Yeah, it is a matter of implementation. I just thought that this is
>> possible to be done in a single attribute, because when the pin is
>> disconnected, the direction has no meaning.
>> 
>> 
>> > attribute PRIORITY to be able to configure (or hint) auto-select mode. There
>> 
>> Sure, I didn't put the PRIORITY attribute to the example, but I believe
>> it is very straightforward extension to add it.
>> 
>> 
>> > are also special objects called muxes, which consist of several inputs and
>> > one output, but they cannot synthonise signal, only pass one of the inputs to
>> > output. We are still in kind of discussion whether to have them as separate
>> > objects, or extend the amount of pins of DPLL device in this case. The
>> > problem again in the auto-select mode and priorities. It would be great to
>> > hear your thoughts about such objects.
>> 
>> Does the mux have any attribute/configuration valuable for the user.
>> If yes, it might make sense to have it as a separate object. Then we
>> can have it as a tree of object of type MUX with leaves of PIN.
>
>Yes, that was the first thought, but implementation details are not great for now.
>
>> The question really is, if the user needs to know about muxes and work
>> with them, or they can be abstracted out by the driver.
>
>Both ways will work I believe. It's more like our will to give users full
>picture or hide it somehow with the implementation.
>> 
>> Could you elaborate a bit more why auto-select mode and priorities are
>> problematic with muxes in picture?
>
>AFAIU, some mux devices are not smart enough to make a decision suitable for
>autoselect for the pins they have. In this case the autoselect process is
>done in the DPLL device, which selects mux and not the pin directly. At the
>same time there could be muxes that are smart enough to make a decision, and
>it will be autoselect on top of autoselect (and several more layers) and it
>doesn't sound great to me. I believe Arkadiusz will explain the mux a bit
>better.


From what you write in this reply, I have a feeling that these details
are not really interesting for user to see. So I tend to lean forward to
abstract this out and leave the details to HW/FW/driver.


>
>> 
>> 
>> > 
>> > > > 
>> > > > This would introduce quite nice flexibility, exposes source/output
>> > > > capabilities and provides good visilibity of current configuration.
>> > > > 
>> > > > 
>> > > > > interface was created to cover such case. I believe we have to improve it to
>> > > > > cover SyncE configuration better, but I personally don't have SyncE hardware
>> > > > > ready to test and that's why I have to rely on suggestions from yours or
>> > > > > Arkadiusz's experience. From what I can see now there is need for special
>> > > > > attribute to link source to net device, and I'm happy to add it. In case of
>> > > > > fixed configuration of sources, the device should provide only one type as
>> > > > > supported and that's it.
>> > > > > 
>> > > 
>> > > [...]
>> > 
>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 1/6] dpll: Add DPLL framework base functions
@ 2022-10-13  6:55                   ` Jiri Pirko
  0 siblings, 0 replies; 67+ messages in thread
From: Jiri Pirko @ 2022-10-13  6:55 UTC (permalink / raw)
  To: Vadim Fedorenko
  Cc: Jakub Kicinski, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

Wed, Oct 12, 2022 at 10:12:43PM CEST, vfedorenko@novek.ru wrote:
>On 12.10.2022 07:44, Jiri Pirko wrote:
>> Tue, Oct 11, 2022 at 11:31:25PM CEST, vfedorenko@novek.ru wrote:
>> > On 11.10.2022 09:47, Jiri Pirko wrote:
>> > > Tue, Oct 11, 2022 at 10:32:22AM CEST, jiri@resnulli.us wrote:
>> > > > Mon, Oct 10, 2022 at 09:54:26PM CEST, vfedorenko@novek.ru wrote:
>> > > > > On 10.10.2022 10:18, Jiri Pirko wrote:
>> > > > > > Mon, Oct 10, 2022 at 03:17:59AM CEST, vfedorenko@novek.ru wrote:
>> > > > > > > From: Vadim Fedorenko <vadfed@fb.com>
>> > > 
>> > > [...]
>> > > 
>> > > 
>> > > > > I see your point. We do have hardware which allows changing type of SMA
>> > > > > connector, and even the direction, each SMA could be used as input/source or
>> > > > > output of different signals. But there are limitation, like not all SMAs can
>> > > > > produce IRIG-B signal or only some of them can be used to get GNSS 1PPS. The
>> > > > 
>> > > > Okay, so that is not the *type* of source, but rather attribute of it.
>> > > > Example:
>> > > > 
>> > > > $ dpll X show
>> > > > index 0
>> > > >    type EXT
>> > > >    signal 1PPS
>> > > >    supported_signals
>> > > >       1PPS 10MHz
>> > > > 
>> > > > $ dpll X set source index 1 signal_type 10MHz
>> > > > $ dpll X show
>> > > > index 0
>> > > >    type EXT
>> > > >    signal 10MHz
>> > > >    supported_signals
>> > > >       1PPS 10MHz
>> > > > 
>> > > > So one source with index 0 of type "EXT" (could be "SMA", does not
>> > > > matter) supports 1 signal types.
>> > > > 
>> > > > 
>> > > > Thinking about this more and to cover the case when one SMA could be
>> > > > potencially used for input and output. It already occured to me that
>> > > > source/output are quite similar, have similar/same attributes. What if
>> > > > they are merged together to say a "pin" object only with extra
>> > > > PERSONALITY attribute?
>> > > > 
>> > > > Example:
>> > > > 
>> > > > -> DPLL_CMD_PIN_GET - dump
>> > > >        ATTR_DEVICE_ID X
>> > > > 
>> > > > <- DPLL_CMD_PIN_GET
>> > > > 
>> > > >         ATTR_DEVICE_ID X
>> > > >         ATTR_PIN_INDEX 0
>> > > >         ATTR_PIN_TYPE EXT
>> > > >         ATTR_PIN_SIGNAL 1PPS   (selected signal)
>> > > >         ATTR_PIN_SUPPORTED_SIGNALS (nest)
>> > > >           ATTR_PIN_SIGNAL 1PPS
>> > > >           ATTR_PIN_SIGNAL 10MHZ
>> > > >         ATTR_PIN_PERSONALITY OUTPUT   (selected personality)
>> > > >         ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>> > > >           ATTR_PIN_PERSONALITY DISCONNECTED
>> > > >           ATTR_PIN_PERSONALITY INPUT
>> > > >           ATTR_PIN_PERSONALITY OUTPUT     (note this supports both input and
>> > > > 					  output)
>> > > > 
>> > > >         ATTR_DEVICE_ID X
>> > > >         ATTR_PIN_INDEX 1
>> > > >         ATTR_PIN_TYPE EXT
>> > > >         ATTR_PIN_SIGNAL 10MHz   (selected signal)
>> > > >         ATTR_PIN_SUPPORTED_SIGNALS (nest)
>> > > >           ATTR_PIN_SIGNAL 1PPS
>> > > >           ATTR_PIN_SIGNAL 10MHZ
>> > > >         ATTR_PIN_PERSONALITY DISCONNECTED   (selected personality - not
>> > > > 					    connected currently)
>> > > >         ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>> > > >           ATTR_PIN_PERSONALITY DISCONNECTED
>> > > >           ATTR_PIN_PERSONALITY INPUT      (note this supports only input)
>> > > > 
>> > > >         ATTR_DEVICE_ID X
>> > > >         ATTR_PIN_INDEX 2
>> > > >         ATTR_PIN_TYPE GNSS
>> > > >         ATTR_PIN_SIGNAL 1PPS   (selected signal)
>> > > >         ATTR_PIN_SUPPORTED_SIGNALS (nest)
>> > > >           ATTR_PIN_SIGNAL 1PPS
>> > > >         ATTR_PIN_PERSONALITY INPUT   (selected personality - note this is
>> > > > 				     now he selected source, being only
>> > > > 				     pin with INPUT personality)
>> > > >         ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>> > > >           ATTR_PIN_PERSONALITY DISCONNECTED
>> > > >           ATTR_PIN_PERSONALITY INPUT      (note this supports only input)
>> > > > 
>> > > >         ATTR_DEVICE_ID X
>> > > >         ATTR_PIN_INDEX 3
>> > > >         ATTR_PIN_TYPE SYNCE_ETH_PORT
>> > > >         ATTR_PIN_NETDEV_IFINDEX 20
>> > > >         ATTR_PIN_PERSONALITY OUTPUT   (selected personality)
>> > > >         ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>> > > >           ATTR_PIN_PERSONALITY DISCONNECTED
>> > > >           ATTR_PIN_PERSONALITY INPUT
>> > > >           ATTR_PIN_PERSONALITY OUTPUT     (note this supports both input and
>> > > > 					  output)
>> > > > 
>> > > >         ATTR_DEVICE_ID X
>> > > >         ATTR_PIN_INDEX 4
>> > > >         ATTR_PIN_TYPE SYNCE_ETH_PORT
>> > > >         ATTR_PIN_NETDEV_IFINDEX 30
>> > > >         ATTR_PIN_PERSONALITY OUTPUT   (selected personality)
>> > > >         ATTR_PIN_SUPPORTED_PERSONALITIES (nest)
>> > > >           ATTR_PIN_PERSONALITY DISCONNECTED
>> > > >           ATTR_PIN_PERSONALITY INPUT
>> > > >           ATTR_PIN_PERSONALITY OUTPUT     (note this supports both input and
>> > > > 					  output)
>> > > > 
>> > > > 
>> > > > This allows the user to actually see the full picture:
>> > > > 1) all input/output pins in a single list, no duplicates
>> > > > 2) each pin if of certain type (ATTR_PIN_TYPE) EXT/GNSS/SYNCE_ETH_PORT
>> > > > 3) the pins that can change signal type contain the selected and list of
>> > > >     supported signal types (ATTR_PIN_SIGNAL, ATTR_PIN_SUPPORTED_SIGNALS)
>> > > > 4) direction/connection of the pin to the DPLL is exposed over
>> > > >     ATTR_PIN_PERSONALITY. For each pin, the driver would expose it can
>> > > >     act as INPUT/OUTPUT and even more, it can indicate the pin can
>> > > >     disconnect from DPLL entirely (if possible).
>> > > > 5) user can select the source by setting ATTR_PIN_PERSONALITY of certain
>> > > >     pin to INPUT. Only one pin could be set to INPUT and that is the
>> > > >     souce of DPLL.
>> > > >     In case no pin have personality set to INPUT, the DPLL is
>> > > >     free-running.
>> > > 
>> > > Okay, thinking about it some more, I would leave the source select
>> > > indepentent from the ATTR_PIN_PERSONALITY and selectable using device
>> > > set cmd and separate attribute. It works better even more when consider
>> > > autoselect mode.
>> > > 
>> > > Well of course only pins with ATTR_PIN_PERSONALITY INPUT could be
>> > > selected as source.
>> > > 
>> > 
>> > Overall, I agree with this proposal, and as I've already said, the work is
>> > going exactly the same way - to introduce pin object with separate set of
>> > attributes.
>> > I don't really like 'PERSONALITY' naming, I think we have to find a better
>> > name. It looks like DIRECTION is slightly better. And the
>> > CONNECTED/DISCONNECTED should be different attribute. And we also need
>> 
>> Yeah, it is a matter of implementation. I just thought that this is
>> possible to be done in a single attribute, because when the pin is
>> disconnected, the direction has no meaning.
>> 
>> 
>> > attribute PRIORITY to be able to configure (or hint) auto-select mode. There
>> 
>> Sure, I didn't put the PRIORITY attribute to the example, but I believe
>> it is very straightforward extension to add it.
>> 
>> 
>> > are also special objects called muxes, which consist of several inputs and
>> > one output, but they cannot synthonise signal, only pass one of the inputs to
>> > output. We are still in kind of discussion whether to have them as separate
>> > objects, or extend the amount of pins of DPLL device in this case. The
>> > problem again in the auto-select mode and priorities. It would be great to
>> > hear your thoughts about such objects.
>> 
>> Does the mux have any attribute/configuration valuable for the user.
>> If yes, it might make sense to have it as a separate object. Then we
>> can have it as a tree of object of type MUX with leaves of PIN.
>
>Yes, that was the first thought, but implementation details are not great for now.
>
>> The question really is, if the user needs to know about muxes and work
>> with them, or they can be abstracted out by the driver.
>
>Both ways will work I believe. It's more like our will to give users full
>picture or hide it somehow with the implementation.
>> 
>> Could you elaborate a bit more why auto-select mode and priorities are
>> problematic with muxes in picture?
>
>AFAIU, some mux devices are not smart enough to make a decision suitable for
>autoselect for the pins they have. In this case the autoselect process is
>done in the DPLL device, which selects mux and not the pin directly. At the
>same time there could be muxes that are smart enough to make a decision, and
>it will be autoselect on top of autoselect (and several more layers) and it
>doesn't sound great to me. I believe Arkadiusz will explain the mux a bit
>better.


From what you write in this reply, I have a feeling that these details
are not really interesting for user to see. So I tend to lean forward to
abstract this out and leave the details to HW/FW/driver.


>
>> 
>> 
>> > 
>> > > > 
>> > > > This would introduce quite nice flexibility, exposes source/output
>> > > > capabilities and provides good visilibity of current configuration.
>> > > > 
>> > > > 
>> > > > > interface was created to cover such case. I believe we have to improve it to
>> > > > > cover SyncE configuration better, but I personally don't have SyncE hardware
>> > > > > ready to test and that's why I have to rely on suggestions from yours or
>> > > > > Arkadiusz's experience. From what I can see now there is need for special
>> > > > > attribute to link source to net device, and I'm happy to add it. In case of
>> > > > > fixed configuration of sources, the device should provide only one type as
>> > > > > supported and that's it.
>> > > > > 
>> > > 
>> > > [...]
>> > 
>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 1/6] dpll: Add DPLL framework base functions
  2022-10-12 20:15       ` Vadim Fedorenko
@ 2022-10-13  6:56         ` Jiri Pirko
  -1 siblings, 0 replies; 67+ messages in thread
From: Jiri Pirko @ 2022-10-13  6:56 UTC (permalink / raw)
  To: Vadim Fedorenko
  Cc: Jakub Kicinski, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

Wed, Oct 12, 2022 at 10:15:23PM CEST, vfedorenko@novek.ru wrote:
>On 12.10.2022 11:47, Jiri Pirko wrote:
>> Mon, Oct 10, 2022 at 03:17:59AM CEST, vfedorenko@novek.ru wrote:
>> > From: Vadim Fedorenko <vadfed@fb.com>
>> > 
>> > DPLL framework is used to represent and configure DPLL devices
>> > in systems. Each device that has DPLL and can configure sources
>> > and outputs can use this framework.
>> > 
>> > Signed-off-by: Vadim Fedorenko <vadfed@fb.com>
>> > Co-developed-by: Jakub Kicinski <kuba@kernel.org>
>> > Co-developed-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
>> 
>> 
>> [...]
>> 
>> 
>> > +struct dpll_device *dpll_device_alloc(struct dpll_device_ops *ops, const char *name,
>> > +				      int sources_count, int outputs_count, void *priv)
>> 
>> Having constant array of "pins" would not work for SyncE. For example in
>> mlxsw driver, netdevs can appear and disappear within the device
>> lifetime (for example port splits, linecard provision). We need to
>> register/unregister pins dynamically.
>> 
>Yes, I agree, and we are working to implement pin object with dynamic
>attach/detach or reg/unreg functions.

Awesome. Looking forward to the next patchset version!

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 1/6] dpll: Add DPLL framework base functions
@ 2022-10-13  6:56         ` Jiri Pirko
  0 siblings, 0 replies; 67+ messages in thread
From: Jiri Pirko @ 2022-10-13  6:56 UTC (permalink / raw)
  To: Vadim Fedorenko
  Cc: Jakub Kicinski, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

Wed, Oct 12, 2022 at 10:15:23PM CEST, vfedorenko@novek.ru wrote:
>On 12.10.2022 11:47, Jiri Pirko wrote:
>> Mon, Oct 10, 2022 at 03:17:59AM CEST, vfedorenko@novek.ru wrote:
>> > From: Vadim Fedorenko <vadfed@fb.com>
>> > 
>> > DPLL framework is used to represent and configure DPLL devices
>> > in systems. Each device that has DPLL and can configure sources
>> > and outputs can use this framework.
>> > 
>> > Signed-off-by: Vadim Fedorenko <vadfed@fb.com>
>> > Co-developed-by: Jakub Kicinski <kuba@kernel.org>
>> > Co-developed-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
>> 
>> 
>> [...]
>> 
>> 
>> > +struct dpll_device *dpll_device_alloc(struct dpll_device_ops *ops, const char *name,
>> > +				      int sources_count, int outputs_count, void *priv)
>> 
>> Having constant array of "pins" would not work for SyncE. For example in
>> mlxsw driver, netdevs can appear and disappear within the device
>> lifetime (for example port splits, linecard provision). We need to
>> register/unregister pins dynamically.
>> 
>Yes, I agree, and we are working to implement pin object with dynamic
>attach/detach or reg/unreg functions.

Awesome. Looking forward to the next patchset version!

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 1/6] dpll: Add DPLL framework base functions
  2022-10-13  6:55                   ` Jiri Pirko
@ 2022-10-13 15:17                     ` Jakub Kicinski
  -1 siblings, 0 replies; 67+ messages in thread
From: Jakub Kicinski @ 2022-10-13 15:17 UTC (permalink / raw)
  To: Jiri Pirko
  Cc: Vadim Fedorenko, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

On Thu, 13 Oct 2022 08:55:34 +0200 Jiri Pirko wrote:
>> AFAIU, some mux devices are not smart enough to make a decision suitable for
>> autoselect for the pins they have. In this case the autoselect process is
>> done in the DPLL device, which selects mux and not the pin directly. At the
>> same time there could be muxes that are smart enough to make a decision, and
>> it will be autoselect on top of autoselect (and several more layers) and it
>> doesn't sound great to me. I believe Arkadiusz will explain the mux a bit
>> better.  
> 
> From what you write in this reply, I have a feeling that these details
> are not really interesting for user to see. So I tend to lean forward to
> abstract this out and leave the details to HW/FW/driver.

Are you saying we don't need to model MUXes?  Topology of the signals
imposes restrictions on the supported configuration, it's not something
you can "abstract out in the FW".

My thinking was we can let the user ignore it and have the core figure
out the configuration of the muxes if users asks for a pin behind a mux.
But it's better if the mux is visible so that it's clear which signals
can't be selected simultaneously. (IIRC Arkadiusz may have even had
muxes shared between DPLLs :S)

Anyway, I may just be confused about the state of the series because
most of the points you brought up were already discussed. I guess you
were right that off-list reviews are a bad idea :(

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 1/6] dpll: Add DPLL framework base functions
@ 2022-10-13 15:17                     ` Jakub Kicinski
  0 siblings, 0 replies; 67+ messages in thread
From: Jakub Kicinski @ 2022-10-13 15:17 UTC (permalink / raw)
  To: Jiri Pirko
  Cc: Vadim Fedorenko, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

On Thu, 13 Oct 2022 08:55:34 +0200 Jiri Pirko wrote:
>> AFAIU, some mux devices are not smart enough to make a decision suitable for
>> autoselect for the pins they have. In this case the autoselect process is
>> done in the DPLL device, which selects mux and not the pin directly. At the
>> same time there could be muxes that are smart enough to make a decision, and
>> it will be autoselect on top of autoselect (and several more layers) and it
>> doesn't sound great to me. I believe Arkadiusz will explain the mux a bit
>> better.  
> 
> From what you write in this reply, I have a feeling that these details
> are not really interesting for user to see. So I tend to lean forward to
> abstract this out and leave the details to HW/FW/driver.

Are you saying we don't need to model MUXes?  Topology of the signals
imposes restrictions on the supported configuration, it's not something
you can "abstract out in the FW".

My thinking was we can let the user ignore it and have the core figure
out the configuration of the muxes if users asks for a pin behind a mux.
But it's better if the mux is visible so that it's clear which signals
can't be selected simultaneously. (IIRC Arkadiusz may have even had
muxes shared between DPLLs :S)

Anyway, I may just be confused about the state of the series because
most of the points you brought up were already discussed. I guess you
were right that off-list reviews are a bad idea :(

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 1/6] dpll: Add DPLL framework base functions
  2022-10-13 15:17                     ` Jakub Kicinski
@ 2022-10-14  9:52                       ` Jiri Pirko
  -1 siblings, 0 replies; 67+ messages in thread
From: Jiri Pirko @ 2022-10-14  9:52 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: Vadim Fedorenko, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

Thu, Oct 13, 2022 at 05:17:25PM CEST, kuba@kernel.org wrote:
>On Thu, 13 Oct 2022 08:55:34 +0200 Jiri Pirko wrote:
>>> AFAIU, some mux devices are not smart enough to make a decision suitable for
>>> autoselect for the pins they have. In this case the autoselect process is
>>> done in the DPLL device, which selects mux and not the pin directly. At the
>>> same time there could be muxes that are smart enough to make a decision, and
>>> it will be autoselect on top of autoselect (and several more layers) and it
>>> doesn't sound great to me. I believe Arkadiusz will explain the mux a bit
>>> better.  
>> 
>> From what you write in this reply, I have a feeling that these details
>> are not really interesting for user to see. So I tend to lean forward to
>> abstract this out and leave the details to HW/FW/driver.
>
>Are you saying we don't need to model MUXes?  Topology of the signals
>imposes restrictions on the supported configuration, it's not something
>you can "abstract out in the FW".
>
>My thinking was we can let the user ignore it and have the core figure
>out the configuration of the muxes if users asks for a pin behind a mux.
>But it's better if the mux is visible so that it's clear which signals
>can't be selected simultaneously. (IIRC Arkadiusz may have even had
>muxes shared between DPLLs :S)

Yeah, that sounds fine. My point was, the user does not have to know the
details and muxes could be abstracted out in kernel and below.

Not sure why the mux would need to be visible to user. It it needs to,
sure, lets model it. I have no strong opinion here.


>
>Anyway, I may just be confused about the state of the series because
>most of the points you brought up were already discussed. I guess you
>were right that off-list reviews are a bad idea :(

Yep :/ Let's please move it here to stop the mess.

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [RFC PATCH v3 1/6] dpll: Add DPLL framework base functions
@ 2022-10-14  9:52                       ` Jiri Pirko
  0 siblings, 0 replies; 67+ messages in thread
From: Jiri Pirko @ 2022-10-14  9:52 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: Vadim Fedorenko, Arkadiusz Kubalewski, netdev, linux-arm-kernel,
	linux-clk, Vadim Fedorenko

Thu, Oct 13, 2022 at 05:17:25PM CEST, kuba@kernel.org wrote:
>On Thu, 13 Oct 2022 08:55:34 +0200 Jiri Pirko wrote:
>>> AFAIU, some mux devices are not smart enough to make a decision suitable for
>>> autoselect for the pins they have. In this case the autoselect process is
>>> done in the DPLL device, which selects mux and not the pin directly. At the
>>> same time there could be muxes that are smart enough to make a decision, and
>>> it will be autoselect on top of autoselect (and several more layers) and it
>>> doesn't sound great to me. I believe Arkadiusz will explain the mux a bit
>>> better.  
>> 
>> From what you write in this reply, I have a feeling that these details
>> are not really interesting for user to see. So I tend to lean forward to
>> abstract this out and leave the details to HW/FW/driver.
>
>Are you saying we don't need to model MUXes?  Topology of the signals
>imposes restrictions on the supported configuration, it's not something
>you can "abstract out in the FW".
>
>My thinking was we can let the user ignore it and have the core figure
>out the configuration of the muxes if users asks for a pin behind a mux.
>But it's better if the mux is visible so that it's clear which signals
>can't be selected simultaneously. (IIRC Arkadiusz may have even had
>muxes shared between DPLLs :S)

Yeah, that sounds fine. My point was, the user does not have to know the
details and muxes could be abstracted out in kernel and below.

Not sure why the mux would need to be visible to user. It it needs to,
sure, lets model it. I have no strong opinion here.


>
>Anyway, I may just be confused about the state of the series because
>most of the points you brought up were already discussed. I guess you
>were right that off-list reviews are a bad idea :(

Yep :/ Let's please move it here to stop the mess.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 67+ messages in thread

end of thread, other threads:[~2022-10-14  9:54 UTC | newest]

Thread overview: 67+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-10-10  1:17 [RFC PATCH v3 0/5] Create common DPLL/clock configuration API Vadim Fedorenko
2022-10-10  1:17 ` Vadim Fedorenko
2022-10-10  1:17 ` [RFC PATCH v3 1/6] dpll: Add DPLL framework base functions Vadim Fedorenko
2022-10-10  1:17   ` Vadim Fedorenko
2022-10-10  9:18   ` Jiri Pirko
2022-10-10  9:18     ` Jiri Pirko
2022-10-10 19:54     ` Vadim Fedorenko
2022-10-10 19:54       ` Vadim Fedorenko
2022-10-11  8:32       ` Jiri Pirko
2022-10-11  8:32         ` Jiri Pirko
2022-10-11  8:47         ` Jiri Pirko
2022-10-11  8:47           ` Jiri Pirko
2022-10-11 21:31           ` Vadim Fedorenko
2022-10-11 21:31             ` Vadim Fedorenko
2022-10-12  6:44             ` Jiri Pirko
2022-10-12  6:44               ` Jiri Pirko
2022-10-12 20:12               ` Vadim Fedorenko
2022-10-12 20:12                 ` Vadim Fedorenko
2022-10-13  6:55                 ` Jiri Pirko
2022-10-13  6:55                   ` Jiri Pirko
2022-10-13 15:17                   ` Jakub Kicinski
2022-10-13 15:17                     ` Jakub Kicinski
2022-10-14  9:52                     ` Jiri Pirko
2022-10-14  9:52                       ` Jiri Pirko
2022-10-11 21:23         ` Vadim Fedorenko
2022-10-11 21:23           ` Vadim Fedorenko
2022-10-12 10:44           ` Jiri Pirko
2022-10-12 10:44             ` Jiri Pirko
2022-10-12 10:47   ` Jiri Pirko
2022-10-12 10:47     ` Jiri Pirko
2022-10-12 20:15     ` Vadim Fedorenko
2022-10-12 20:15       ` Vadim Fedorenko
2022-10-13  6:56       ` Jiri Pirko
2022-10-13  6:56         ` Jiri Pirko
2022-10-12 16:51   ` Jiri Pirko
2022-10-12 16:51     ` Jiri Pirko
2022-10-12 20:17     ` Vadim Fedorenko
2022-10-12 20:17       ` Vadim Fedorenko
2022-10-10  1:18 ` [RFC PATCH v3 2/6] dpll: add netlink events Vadim Fedorenko
2022-10-10  1:18   ` Vadim Fedorenko
2022-10-10  1:18 ` [RFC PATCH v3 3/6] dpll: add support for source selection modes Vadim Fedorenko
2022-10-10  1:18   ` Vadim Fedorenko
2022-10-10 14:13   ` Jiri Pirko
2022-10-10 14:13     ` Jiri Pirko
2022-10-10 20:03     ` Vadim Fedorenko
2022-10-10 20:03       ` Vadim Fedorenko
2022-10-10  1:18 ` [RFC PATCH v3 4/6] dpll: get source/output name Vadim Fedorenko
2022-10-10  1:18   ` Vadim Fedorenko
2022-10-10  9:45   ` Jiri Pirko
2022-10-10  9:45     ` Jiri Pirko
2022-10-10 19:55     ` Vadim Fedorenko
2022-10-10 19:55       ` Vadim Fedorenko
2022-10-11  7:28       ` Jiri Pirko
2022-10-11  7:28         ` Jiri Pirko
2022-10-10  1:18 ` [RFC PATCH v3 5/6] dpll: documentation on DPLL subsystem interface Vadim Fedorenko
2022-10-10  1:18   ` Vadim Fedorenko
2022-10-10  1:18 ` [RFC PATCH v3 6/6] ptp_ocp: implement DPLL ops Vadim Fedorenko
2022-10-10  1:18   ` Vadim Fedorenko
2022-10-10 15:42   ` Jiri Pirko
2022-10-10 15:42     ` Jiri Pirko
2022-10-10 20:14     ` Vadim Fedorenko
2022-10-10 20:14       ` Vadim Fedorenko
2022-10-11  7:30       ` Jiri Pirko
2022-10-11  7:30         ` Jiri Pirko
2022-10-11  0:30   ` kernel test robot
2022-10-12 15:14   ` Jiri Pirko
2022-10-12 15:14     ` Jiri Pirko

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.