@@ -363,6 +363,9 @@
__start___dyndbg_classes = .; \
KEEP(*(__dyndbg_classes)) \
__stop___dyndbg_classes = .; \
+ __start___dyndbg_class_refs = .; \
+ KEEP(*(__dyndbg_class_refs)) \
+ __stop___dyndbg_class_refs = .; \
__start___dyndbg = .; \
KEEP(*(__dyndbg)) \
__stop___dyndbg = .; \
@@ -81,8 +81,10 @@ enum ddebug_class_map_type {
};
struct ddebug_class_map {
- struct module *mod;
- const char *mod_name; /* needed for builtins */
+ struct list_head link;
+ struct module *mod; /* NULL for builtins */
+ const char *mod_name;
+ struct ddebug_class_param *dc_parm; /* controlling sysfs node */
const char **class_names;
const int length;
const int base; /* index of 1st .class_id, allows split/shared space */
@@ -99,8 +101,8 @@ struct ddebug_class_map {
* @classes: class-names used to control class'd prdbgs
*/
#define DYNDBG_CLASSMAP_DEFINE(_var, _maptype, _base, ...) \
- static const char *_var##_classnames[] = { __VA_ARGS__ }; \
- static struct ddebug_class_map __aligned(8) __used \
+ const char *_var##_classnames[] = { __VA_ARGS__ }; \
+ struct ddebug_class_map __aligned(8) __used \
__section("__dyndbg_classes") _var = { \
.mod = THIS_MODULE, \
.mod_name = KBUILD_MODNAME, \
@@ -108,24 +110,37 @@ struct ddebug_class_map {
.map_type = _maptype, \
.length = ARRAY_SIZE(_var##_classnames), \
.class_names = _var##_classnames, \
- }
+ }; \
+ EXPORT_SYMBOL(_var)
-/*
- * refer to the classmap instantiated once, by the macro above. This
- * distinguishes the multiple users of drm.debug from the single
- * definition, allowing them to specialize. ATM its a pass-thru, but
- * it should help regularize the admittedly wierd sharing by identical
- * definitions.
+struct ddebug_class_user {
+ char *user_mod_name;
+ struct ddebug_class_map *map;
+};
+/**
+ * DYNDBG_CLASSMAP_USE - Use a classmap DEFINEd in another module.
+ * This lets dyndbg initialize the dependent module's prdbgs from the
+ * other module's controlling sysfs node.
*/
-#define DYNDBG_CLASSMAP_USE(_var, _maptype, _base, ...) \
- DYNDBG_CLASSMAP_DEFINE(_var, _maptype, _base, __VA_ARGS__)
+#define DYNDBG_CLASSMAP_USE(_var, ...) \
+ DYNDBG_CLASSMAP_USE_(_var, __UNIQUE_ID(ddebug_class_user), \
+ __VA_ARGS__)
+#define DYNDBG_CLASSMAP_USE_(_var, _uname, ...) \
+ extern struct ddebug_class_map _var[]; \
+ static struct ddebug_class_user __used \
+ __section("__dyndbg_class_refs") _uname = { \
+ .user_mod_name = KBUILD_MODNAME, \
+ .map = _var, \
+ }
/* encapsulate linker provided built-in (or module) dyndbg data */
struct _ddebug_info {
struct _ddebug *descs;
struct ddebug_class_map *classes;
+ struct ddebug_class_user *class_refs;
unsigned int num_descs;
unsigned int num_classes;
+ unsigned int num_class_refs;
};
struct ddebug_class_param {
@@ -2111,6 +2111,8 @@ static int find_module_sections(struct module *mod, struct load_info *info)
sizeof(*info->dyndbg.descs), &info->dyndbg.num_descs);
info->dyndbg.classes = section_objs(info, "__dyndbg_classes",
sizeof(*info->dyndbg.classes), &info->dyndbg.num_classes);
+ info->dyndbg.class_refs = section_objs(info, "__dyndbg_class_refs",
+ sizeof(*info->dyndbg.class_refs), &info->dyndbg.num_class_refs);
return 0;
}
@@ -43,13 +43,16 @@ extern struct _ddebug __start___dyndbg[];
extern struct _ddebug __stop___dyndbg[];
extern struct ddebug_class_map __start___dyndbg_classes[];
extern struct ddebug_class_map __stop___dyndbg_classes[];
+extern struct ddebug_class_user __start___dyndbg_class_refs[];
+extern struct ddebug_class_user __stop___dyndbg_class_refs[];
struct ddebug_table {
struct list_head link;
const char *mod_name;
struct _ddebug *ddebugs;
struct ddebug_class_map *classes;
- unsigned int num_ddebugs, num_classes;
+ struct ddebug_class_user *class_refs;
+ unsigned int num_ddebugs, num_classes, num_class_refs;
};
struct ddebug_query {
@@ -153,15 +156,23 @@ static struct ddebug_class_map *ddebug_find_valid_class(struct ddebug_table cons
__outvar int *class_id)
{
struct ddebug_class_map *map;
+ struct ddebug_class_user *cli;
int i, idx;
- for (map = dt->classes, i = 0; i < dt->num_classes; i++, map++) {
+ for (i = 0, map = dt->classes; i < dt->num_classes; i++, map++) {
idx = match_string(map->class_names, map->length, class_string);
if (idx >= 0) {
*class_id = idx + map->base;
return map;
}
}
+ for (i = 0, cli = dt->class_refs; i < dt->num_class_refs; i++, cli++) {
+ idx = match_string(cli->map->class_names, cli->map->length, class_string);
+ if (idx >= 0) {
+ *class_id = idx + map->base;
+ return map;
+ }
+ }
*class_id = -ENOENT;
return NULL;
}
@@ -603,7 +614,7 @@ static int ddebug_apply_class_bitmap(const struct ddebug_class_param *dcp,
int matches = 0;
int bi, ct;
- v2pr_info("apply: 0x%lx to: 0x%lx\n", *new_bits, *old_bits);
+ v2pr_info("apply bitmap: 0x%lx to: 0x%lx\n", *new_bits, *old_bits);
for (bi = 0; bi < map->length; bi++) {
if (test_bit(bi, new_bits) == test_bit(bi, old_bits))
@@ -1106,13 +1117,19 @@ static void *ddebug_proc_next(struct seq_file *m, void *p, loff_t *pos)
static const char *ddebug_class_name(struct ddebug_iter *iter, struct _ddebug *dp)
{
- struct ddebug_class_map *map = iter->table->classes;
- int i, nc = iter->table->num_classes;
+ struct ddebug_table *dt = iter->table;
+ struct ddebug_class_map *map;
+ struct ddebug_class_user *cli;
+ int i;
- for (i = 0; i < nc; i++, map++)
+ for (i = 0, map = dt->classes; i < dt->num_classes; i++, map++)
if (class_in_range(dp->class_id, map))
return map->class_names[dp->class_id - map->base];
+ for (i = 0, cli = dt->class_refs; i < dt->num_class_refs; i++, cli++)
+ if (class_in_range(dp->class_id, cli->map))
+ return cli->map->class_names[dp->class_id - map->base];
+
return NULL;
}
@@ -1193,6 +1210,54 @@ static const struct proc_ops proc_fops = {
.proc_write = ddebug_proc_write
};
+static void ddebug_match_attach_kparam(const struct kernel_param *kp,
+ struct ddebug_class_map *cm)
+{
+ struct ddebug_class_param *dcp;
+
+ if (kp->ops != ¶m_ops_dyndbg_classes)
+ return;
+ dcp = (struct ddebug_class_param *)kp->arg;
+
+ if (!strncmp(cm->mod_name, dcp->map->mod_name, strlen(cm->mod_name))) {
+ cm->dc_parm = dcp;
+ v2pr_info("controlling kp: %s.%s\n", cm->mod_name, kp->name);
+ } else
+ v2pr_info("not this: %s %s\n", cm->mod_name, kp->name);
+}
+
+static void ddebug_find_kparam(struct ddebug_class_map *cm)
+{
+ const struct kernel_param *kp;
+ int i;
+
+ if (cm->mod) {
+ v2pr_info("loaded class: module:%s base:%d len:%d ty:%d\n",
+ cm->mod_name, cm->base, cm->length, cm->map_type);
+
+ for (i = 0, kp = cm->mod->kp; i < cm->mod->num_kp; i++, kp++)
+ ddebug_match_attach_kparam(kp, cm);
+ } else {
+ v2pr_info("builtin class: module:%s base:%d len:%d ty:%d\n",
+ cm->mod_name, cm->base, cm->length, cm->map_type);
+
+ for (kp = __start___param; kp < __stop___param; kp++)
+ ddebug_match_attach_kparam(kp, cm);
+ }
+}
+
+static void ddebug_param_load_dependent_class(const struct ddebug_class_user *cli)
+{
+ unsigned long new_bits, old_bits = 0;
+
+ new_bits = *cli->map->dc_parm->bits;
+
+ vpr_info("%s needs %s, 0x%lx\n", cli->user_mod_name,
+ cli->map->mod_name, new_bits);
+
+ ddebug_apply_class_bitmap(cli->map->dc_parm, &new_bits, &old_bits, cli->user_mod_name);
+}
+
static void ddebug_attach_module_classes(struct ddebug_table *dt, struct _ddebug_info *di)
{
struct ddebug_class_map *cm;
@@ -1203,20 +1268,60 @@ static void ddebug_attach_module_classes(struct ddebug_table *dt, struct _ddebug
* the builtin/modular classmap vector/section. Save the start
* and length of the subrange at its edges.
*/
- for (cm = di->classes, i = 0; i < di->num_classes; i++, cm++) {
+ for (i = 0, cm = di->classes; i < di->num_classes; i++, cm++) {
if (!strcmp(cm->mod_name, dt->mod_name)) {
if (!nc) {
- v2pr_info("start subrange, class[%d]: module:%s base:%d len:%d ty:%d\n",
- i, cm->mod_name, cm->base, cm->length, cm->map_type);
dt->classes = cm;
+ v2pr_info("classes start: class[%d]: module:%s base:%d len:%d ty:%d\n",
+ i, cm->mod_name, cm->base, cm->length, cm->map_type);
}
+ ddebug_find_kparam(cm);
nc++;
}
}
- if (nc) {
- dt->num_classes = nc;
+ dt->num_classes = nc;
+ if (nc)
vpr_info("module:%s attached %d classes\n", dt->mod_name, nc);
+}
+
+static void ddebug_attach_client_module_classes(struct ddebug_table *dt, struct _ddebug_info *di)
+{
+ struct ddebug_class_user *cli;
+ int i;
+
+ for (i = 0, cli = di->class_refs; i < di->num_class_refs; i++, cli++) {
+
+ if (!cli) {
+ v2pr_info("NO CLI\n");
+ continue;
+ }
+ if (!cli->map) {
+ v2pr_info("NO CLI map\n");
+ continue;
+ }
+ if (!cli->user_mod_name) {
+ v2pr_info("NO CLI name\n");
+ continue;
+ }
+
+ if (!strcmp(cli->user_mod_name, dt->mod_name)) {
+
+ v2pr_info("class_ref[%d] %s -> %s\n", i,
+ cli->user_mod_name, cli->map->mod_name);
+
+ ddebug_param_load_dependent_class(cli);
+
+ dt->class_refs = cli;
+ /*
+ * allow only 1 ref right now, see if that
+ * works. dont want to deal with vector,len
+ * now, maybe inadequate anyway.
+ */
+ v2pr_info("break on %d/%d\n", i, di->num_class_refs);
+ dt->num_class_refs = 1;
+ break;
+ }
}
}
@@ -1229,7 +1334,8 @@ static int __ddebug_add_module(struct _ddebug_info *di, unsigned int base,
{
struct ddebug_table *dt;
- v3pr_info("add-module: %s.%d sites\n", modname, di->num_descs);
+ v3pr_info("add-module: %s %d sites %d.%d\n", modname, di->num_descs,
+ di->num_classes, di->num_class_refs);
if (!di->num_descs) {
v3pr_info(" skip %s\n", modname);
return 0;
@@ -1252,13 +1358,16 @@ static int __ddebug_add_module(struct _ddebug_info *di, unsigned int base,
INIT_LIST_HEAD(&dt->link);
- if (di->classes && di->num_classes)
+ if (di->num_classes)
ddebug_attach_module_classes(dt, di);
mutex_lock(&ddebug_lock);
list_add_tail(&dt->link, &ddebug_tables);
mutex_unlock(&ddebug_lock);
+ if (di->num_class_refs)
+ ddebug_attach_client_module_classes(dt, di);
+
vpr_info("%3u debug prints in module %s\n", di->num_descs, modname);
return 0;
}
@@ -1384,8 +1493,10 @@ static int __init dynamic_debug_init(void)
struct _ddebug_info di = {
.descs = __start___dyndbg,
.classes = __start___dyndbg_classes,
+ .class_refs = __start___dyndbg_class_refs,
.num_descs = __stop___dyndbg - __start___dyndbg,
.num_classes = __stop___dyndbg_classes - __start___dyndbg_classes,
+ .num_class_refs = __stop___dyndbg_class_refs - __start___dyndbg_class_refs,
};
if (&__start___dyndbg == &__stop___dyndbg) {