Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 5 Mar 2017 07:13:29 +0000 (UTC)
From:      Emmanuel Vadot <manu@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r314699 - in head/sys: dev/extres/clk kern sys
Message-ID:  <201703050713.v257DT3s028601@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: manu
Date: Sun Mar  5 07:13:29 2017
New Revision: 314699
URL: https://svnweb.freebsd.org/changeset/base/314699

Log:
  Export a sysctl dev.<clkdom>.<unit>.clocks for each clock domain containing
  all the clocks that they provide.
  Each clocks are exported under the node 'clock.<clkname>' and have the following
  children nodes :
  - frequency
  - parent (The selected parent, if any)
  - parents (The list of parents, if any)
  - childrens (The list of childrens, if any)
  - enable_cnt (The enabled counter)
  
  This give us the possibility to examine clocks at runtime and make graph of
  the clock flow.
  
  Reviewed by:	mmel
  MFC after:	2 month
  Differential Revision:	https://reviews.freebsd.org/D9833

Modified:
  head/sys/dev/extres/clk/clk.c
  head/sys/kern/kern_mib.c
  head/sys/sys/sysctl.h

Modified: head/sys/dev/extres/clk/clk.c
==============================================================================
--- head/sys/dev/extres/clk/clk.c	Sun Mar  5 05:17:36 2017	(r314698)
+++ head/sys/dev/extres/clk/clk.c	Sun Mar  5 07:13:29 2017	(r314699)
@@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/mutex.h>
 #include <sys/limits.h>
 #include <sys/lock.h>
+#include <sys/sbuf.h>
 #include <sys/sysctl.h>
 #include <sys/systm.h>
 #include <sys/sx.h>
@@ -118,6 +119,8 @@ struct clknode {
 
 	/* Cached values. */
 	uint64_t		freq;		/* Actual frequency */
+
+	struct sysctl_ctx_list	sysctl_ctx;
 };
 
 /*
@@ -175,6 +178,15 @@ SX_SYSINIT(clock_topology, &clk_topo_loc
 
 static void clknode_adjust_parent(struct clknode *clknode, int idx);
 
+enum clknode_sysctl_type {
+	CLKNODE_SYSCTL_PARENT,
+	CLKNODE_SYSCTL_PARENTS_LIST,
+	CLKNODE_SYSCTL_CHILDREN_LIST,
+};
+
+static int clknode_sysctl(SYSCTL_HANDLER_ARGS);
+static int clkdom_sysctl(SYSCTL_HANDLER_ARGS);
+
 /*
  * Default clock methods for base class.
  */
@@ -382,6 +394,14 @@ clkdom_create(device_t dev)
 	clkdom->ofw_mapper = clknode_default_ofw_map;
 #endif
 
+	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
+	  SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+	  OID_AUTO, "clocks",
+	  CTLTYPE_STRING | CTLFLAG_RD,
+		    clkdom, 0, clkdom_sysctl,
+		    "A",
+		    "Clock list for the domain");
+
 	return (clkdom);
 }
 
@@ -503,6 +523,7 @@ clknode_create(struct clkdom * clkdom, c
     const struct clknode_init_def *def)
 {
 	struct clknode *clknode;
+	struct sysctl_oid *clknode_oid;
 
 	KASSERT(def->name != NULL, ("clock name is NULL"));
 	KASSERT(def->name[0] != '\0', ("clock name is empty"));
@@ -547,6 +568,42 @@ clknode_create(struct clkdom * clkdom, c
 	clknode->parent_idx = CLKNODE_IDX_NONE;
 	TAILQ_INIT(&clknode->children);
 
+	sysctl_ctx_init(&clknode->sysctl_ctx);
+	clknode_oid = SYSCTL_ADD_NODE(&clknode->sysctl_ctx,
+	    SYSCTL_STATIC_CHILDREN(_clock),
+	    OID_AUTO, clknode->name,
+	    CTLFLAG_RD, 0, "A clock node");
+
+	SYSCTL_ADD_U64(&clknode->sysctl_ctx,
+	    SYSCTL_CHILDREN(clknode_oid),
+	    OID_AUTO, "frequency",
+	    CTLFLAG_RD, &clknode->freq, 0, "The clock frequency");
+	SYSCTL_ADD_PROC(&clknode->sysctl_ctx,
+	    SYSCTL_CHILDREN(clknode_oid),
+	    OID_AUTO, "parent",
+	    CTLTYPE_STRING | CTLFLAG_RD,
+	    clknode, CLKNODE_SYSCTL_PARENT, clknode_sysctl,
+	    "A",
+	    "The clock parent");
+	SYSCTL_ADD_PROC(&clknode->sysctl_ctx,
+	    SYSCTL_CHILDREN(clknode_oid),
+	    OID_AUTO, "parents",
+	    CTLTYPE_STRING | CTLFLAG_RD,
+	    clknode, CLKNODE_SYSCTL_PARENTS_LIST, clknode_sysctl,
+	    "A",
+	    "The clock parents list");
+	SYSCTL_ADD_PROC(&clknode->sysctl_ctx,
+	    SYSCTL_CHILDREN(clknode_oid),
+	    OID_AUTO, "childrens",
+	    CTLTYPE_STRING | CTLFLAG_RD,
+	    clknode, CLKNODE_SYSCTL_CHILDREN_LIST, clknode_sysctl,
+	    "A",
+	    "The clock childrens list");
+	SYSCTL_ADD_INT(&clknode->sysctl_ctx,
+	    SYSCTL_CHILDREN(clknode_oid),
+	    OID_AUTO, "enable_cnt",
+	    CTLFLAG_RD, &clknode->enable_cnt, 0, "The clock enable counter");
+
 	return (clknode);
 }
 
@@ -1385,3 +1442,64 @@ clk_parse_ofw_clk_name(device_t dev, pha
 	return (0);
 }
 #endif
+
+static int
+clkdom_sysctl(SYSCTL_HANDLER_ARGS)
+{
+	struct clkdom *clkdom = arg1;
+	struct clknode *clknode;
+	struct sbuf *sb;
+	int ret;
+
+	sb = sbuf_new_for_sysctl(NULL, NULL, 4096, req);
+	if (sb == NULL)
+		return (ENOMEM);
+
+	CLK_TOPO_SLOCK();
+	TAILQ_FOREACH(clknode, &clkdom->clknode_list, clkdom_link) {
+		sbuf_printf(sb, "%s ", clknode->name);
+	}
+	CLK_TOPO_UNLOCK();
+
+	ret = sbuf_finish(sb);
+	sbuf_delete(sb);
+	return (ret);
+}
+
+static int
+clknode_sysctl(SYSCTL_HANDLER_ARGS)
+{
+	struct clknode *clknode, *children;
+	enum clknode_sysctl_type type = arg2;
+	struct sbuf *sb;
+	const char **parent_names;
+	int ret, i;
+
+	clknode = arg1;
+	sb = sbuf_new_for_sysctl(NULL, NULL, 512, req);
+	if (sb == NULL)
+		return (ENOMEM);
+
+	CLK_TOPO_SLOCK();
+	switch (type) {
+	case CLKNODE_SYSCTL_PARENT:
+		if (clknode->parent)
+			sbuf_printf(sb, "%s", clknode->parent->name);
+		break;
+	case CLKNODE_SYSCTL_PARENTS_LIST:
+		parent_names = clknode_get_parent_names(clknode);
+		for (i = 0; i < clknode->parent_cnt; i++)
+			sbuf_printf(sb, "%s ", parent_names[i]);
+		break;
+	case CLKNODE_SYSCTL_CHILDREN_LIST:
+		TAILQ_FOREACH(children, &(clknode->children), sibling_link) {
+			sbuf_printf(sb, "%s ", children->name);
+		}
+		break;
+	}
+	CLK_TOPO_UNLOCK();
+
+	ret = sbuf_finish(sb);
+	sbuf_delete(sb);
+	return (ret);
+}

Modified: head/sys/kern/kern_mib.c
==============================================================================
--- head/sys/kern/kern_mib.c	Sun Mar  5 05:17:36 2017	(r314698)
+++ head/sys/kern/kern_mib.c	Sun Mar  5 07:13:29 2017	(r314699)
@@ -88,6 +88,11 @@ SYSCTL_ROOT_NODE(OID_AUTO, regression, C
      "Regression test MIB");
 #endif
 
+#ifdef EXT_RESOURCES
+SYSCTL_ROOT_NODE(OID_AUTO, clock, CTLFLAG_RW, 0,
+	"Clocks");
+#endif
+
 SYSCTL_STRING(_kern, OID_AUTO, ident, CTLFLAG_RD|CTLFLAG_MPSAFE,
     kern_ident, 0, "Kernel identifier");
 

Modified: head/sys/sys/sysctl.h
==============================================================================
--- head/sys/sys/sysctl.h	Sun Mar  5 05:17:36 2017	(r314698)
+++ head/sys/sys/sysctl.h	Sun Mar  5 07:13:29 2017	(r314699)
@@ -1004,6 +1004,9 @@ SYSCTL_DECL(_compat);
 SYSCTL_DECL(_regression);
 SYSCTL_DECL(_security);
 SYSCTL_DECL(_security_bsd);
+#ifdef EXT_RESOURCES
+SYSCTL_DECL(_clock);
+#endif
 
 extern char	machine[];
 extern char	osrelease[];



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201703050713.v257DT3s028601>