extern __printf(2, 3)
 int __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...);
 
+extern int ddebug_dyndbg_module_param_cb(char *param, char *val,
+                                       const char *modname);
+
 struct device;
 
 extern __printf(3, 4)
 
 #else
 
+#include <linux/string.h>
+#include <linux/errno.h>
+
 static inline int ddebug_remove_module(const char *mod)
 {
        return 0;
 }
 
+static inline int ddebug_dyndbg_module_param_cb(char *param, char *val,
+                                               const char *modname)
+{
+       if (strstr(param, "dyndbg")) {
+               pr_warn("dyndbg supported only in "
+                       "CONFIG_DYNAMIC_DEBUG builds\n");
+               return 0; /* allow and ignore */
+       }
+       return -EINVAL;
+}
+
 #define dynamic_pr_debug(fmt, ...)                                     \
        do { if (0) printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); } while (0)
 #define dynamic_dev_dbg(dev, fmt, ...)                                 \
 
 }
 EXPORT_SYMBOL_GPL(ddebug_add_module);
 
+/* handle both dyndbg=".." and $module.dyndbg=".." params at boot */
+static int ddebug_dyndbg_boot_param_cb(char *param, char *val,
+                               const char *unused)
+{
+       const char *modname = NULL;
+       char *sep;
+
+       sep = strchr(param, '.');
+       if (sep) {
+               *sep = '\0';
+               modname = param;
+               param = sep + 1;
+       }
+       if (strcmp(param, "dyndbg"))
+               return 0; /* skip all other params w/o error */
+
+       vpr_info("module: %s %s=\"%s\"\n", modname, param, val);
+
+       ddebug_exec_queries(val ? val : "+p");
+       return 0; /* query failure shouldnt stop module load */
+}
+
+/* handle dyndbg args to modprobe */
+int ddebug_dyndbg_module_param_cb(char *param, char *val, const char *doing)
+{
+       if (strcmp(param, "dyndbg"))
+               return -ENOENT;
+
+       vpr_info("module: %s %s=\"%s\"\n", doing, param, val);
+
+       ddebug_exec_queries((val ? val : "+p"));
+
+       return 0; /* query failure shouldnt stop module load */
+}
+
 static void ddebug_table_free(struct ddebug_table *dt)
 {
        list_del_init(&dt->link);
 {
        struct _ddebug *iter, *iter_start;
        const char *modname = NULL;
+       char *cmdline;
        int ret = 0;
        int n = 0;
 
                /* keep tables even on ddebug_query parse error */
                ret = 0;
        }
+       /* now that ddebug tables are loaded, process all boot args
+        * again to find and activate queries given in dyndbg params.
+        * While this has already been done for known boot params, it
+        * ignored the unknown ones (dyndbg in particular).  Reusing
+        * parse_args avoids ad-hoc parsing.  This will also attempt
+        * to activate queries for not-yet-loaded modules, which is
+        * slightly noisy if verbose, but harmless.
+        */
+       cmdline = kstrdup(saved_command_line, GFP_KERNEL);
+       parse_args("dyndbg params", cmdline, NULL,
+                  0, 0, 0, &ddebug_dyndbg_boot_param_cb);
+       kfree(cmdline);
 
 out_free:
        if (ret)
 }
 /* Allow early initialization for boot messages via boot param */
 arch_initcall(dynamic_debug_init);
+
 /* Debugfs setup must be done later */
 module_init(dynamic_debug_init_debugfs);