@@ -618,6 +618,61 @@ static int do_callback_changes(const struct ddebug_classes_bitmap_param *dcp,
return matches;
}
+/* support for [+-] symbolic-name boolean list */
+static int param_set_dyndbg_class_strings(const char *instr, const struct kernel_param *kp)
+{
+ const struct ddebug_classes_bitmap_param *dcp = kp->arg;
+ unsigned long inbits;
+ int idx_rc, totct = 0;
+ bool wanted;
+ char *cls, *p;
+
+ if (!dcp || !dcp->map) {
+ pr_err("set_dyndbg_classes: no bits=>queries map\n");
+ return -EINVAL;
+ }
+
+ cls = kstrdup(instr, GFP_KERNEL);
+ p = strchr(cls, '\n');
+ if (p)
+ *p = '\0';
+
+ inbits = *dcp->bits;
+ vpr_info("set_dyndbg_class_strings: %s on 0x%lx\n", cls, inbits);
+
+ for (; cls; cls = p) {
+ p = strchr(cls, ',');
+ if (p)
+ *p++ = '\0';
+
+ if (*cls == '-') {
+ wanted = false;
+ cls++;
+ } else {
+ wanted = true;
+ if (*cls == '+')
+ cls++;
+ }
+ idx_rc = match_string(dcp->map->classes, dcp->map->length, cls);
+ if (idx_rc < 0) {
+ pr_err("%s not found for module: %s\n", cls, dcp->map->mod_name);
+ continue;
+ }
+ if (test_bit(idx_rc, &inbits) == wanted) {
+ v3pr_info("no change on %s\n", cls);
+ continue;
+ }
+
+ vpr_info("set_dyndbg_classes: bit %d: %s\n", idx_rc, dcp->map->classes[idx_rc]);
+ inbits ^= BIT(idx_rc);
+ totct += do_callback_changes(dcp, idx_rc, &inbits);
+ }
+ kfree(cls);
+ *dcp->bits = inbits;
+ vpr_info("total matches: %d\n", totct);
+ return 0;
+}
+
/**
* param_set_dyndbg_classes - bits => categories >control setter
* @instr: string echo>d to sysfs
@@ -639,10 +694,9 @@ int param_set_dyndbg_classes(const char *instr, const struct kernel_param *kp)
return -EINVAL;
}
rc = kstrtoul(instr, 0, &inbits);
- if (rc) {
- pr_err("set_dyndbg_classes: expecting bits/integer\n");
- return -EINVAL;
- }
+ if (rc)
+ return param_set_dyndbg_class_strings(instr, kp);
+
vpr_info("set_dyndbg_classes: new 0x%lx current 0x%lx\n", inbits, *dcp->bits);
for (i = 0; i < dcp->map->length; i++) {
@@ -650,6 +704,7 @@ int param_set_dyndbg_classes(const char *instr, const struct kernel_param *kp)
if (test_bit(i, &inbits) == test_bit(i, dcp->bits))
continue;
+ vpr_info("set_dyndbg_classes: bit %d: %s\n", i, dcp->map->classes[i]);
totct += do_callback_changes(dcp, i, &inbits);
}
*dcp->bits = inbits;