aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/asm-generic/vmlinux.lds.h10
-rw-r--r--include/linux/device.h18
-rw-r--r--include/linux/dynamic_printk.h93
-rw-r--r--include/linux/kernel.h7
-rw-r--r--include/linux/module.h1
-rw-r--r--include/linux/platform_device.h2
-rw-r--r--include/linux/sysfs.h36
7 files changed, 158 insertions, 9 deletions
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 7440a0dcedd..74c5faf26c0 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -268,7 +268,15 @@
CPU_DISCARD(init.data) \
CPU_DISCARD(init.rodata) \
MEM_DISCARD(init.data) \
- MEM_DISCARD(init.rodata)
+ MEM_DISCARD(init.rodata) \
+ /* implement dynamic printk debug */ \
+ VMLINUX_SYMBOL(__start___verbose_strings) = .; \
+ *(__verbose_strings) \
+ VMLINUX_SYMBOL(__stop___verbose_strings) = .; \
+ . = ALIGN(8); \
+ VMLINUX_SYMBOL(__start___verbose) = .; \
+ *(__verbose) \
+ VMLINUX_SYMBOL(__stop___verbose) = .;
#define INIT_TEXT \
*(.init.text) \
diff --git a/include/linux/device.h b/include/linux/device.h
index 246937c9cbc..987f5912720 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -90,6 +90,9 @@ int __must_check bus_for_each_drv(struct bus_type *bus,
struct device_driver *start, void *data,
int (*fn)(struct device_driver *, void *));
+void bus_sort_breadthfirst(struct bus_type *bus,
+ int (*compare)(const struct device *a,
+ const struct device *b));
/*
* Bus notifiers: Get notified of addition/removal of devices
* and binding/unbinding of drivers to devices.
@@ -502,7 +505,6 @@ extern struct device *device_create(struct class *cls, struct device *parent,
dev_t devt, void *drvdata,
const char *fmt, ...)
__attribute__((format(printf, 5, 6)));
-#define device_create_drvdata device_create
extern void device_destroy(struct class *cls, dev_t devt);
/*
@@ -551,7 +553,11 @@ extern const char *dev_driver_string(const struct device *dev);
#define dev_info(dev, format, arg...) \
dev_printk(KERN_INFO , dev , format , ## arg)
-#ifdef DEBUG
+#if defined(CONFIG_DYNAMIC_PRINTK_DEBUG)
+#define dev_dbg(dev, format, ...) do { \
+ dynamic_dev_dbg(dev, format, ##__VA_ARGS__); \
+ } while (0)
+#elif defined(DEBUG)
#define dev_dbg(dev, format, arg...) \
dev_printk(KERN_DEBUG , dev , format , ## arg)
#else
@@ -567,6 +573,14 @@ extern const char *dev_driver_string(const struct device *dev);
({ if (0) dev_printk(KERN_DEBUG, dev, format, ##arg); 0; })
#endif
+/*
+ * dev_WARN() acts like dev_printk(), but with the key difference
+ * of using a WARN/WARN_ON to get the message out, including the
+ * file/line information and a backtrace.
+ */
+#define dev_WARN(dev, format, arg...) \
+ WARN(1, "Device: %s\n" format, dev_driver_string(dev), ## arg);
+
/* Create alias, so I can be autoloaded. */
#define MODULE_ALIAS_CHARDEV(major,minor) \
MODULE_ALIAS("char-major-" __stringify(major) "-" __stringify(minor))
diff --git a/include/linux/dynamic_printk.h b/include/linux/dynamic_printk.h
new file mode 100644
index 00000000000..2d528d00907
--- /dev/null
+++ b/include/linux/dynamic_printk.h
@@ -0,0 +1,93 @@
+#ifndef _DYNAMIC_PRINTK_H
+#define _DYNAMIC_PRINTK_H
+
+#define DYNAMIC_DEBUG_HASH_BITS 6
+#define DEBUG_HASH_TABLE_SIZE (1 << DYNAMIC_DEBUG_HASH_BITS)
+
+#define TYPE_BOOLEAN 1
+
+#define DYNAMIC_ENABLED_ALL 0
+#define DYNAMIC_ENABLED_NONE 1
+#define DYNAMIC_ENABLED_SOME 2
+
+extern int dynamic_enabled;
+
+/* dynamic_printk_enabled, and dynamic_printk_enabled2 are bitmasks in which
+ * bit n is set to 1 if any modname hashes into the bucket n, 0 otherwise. They
+ * use independent hash functions, to reduce the chance of false positives.
+ */
+extern long long dynamic_printk_enabled;
+extern long long dynamic_printk_enabled2;
+
+struct mod_debug {
+ char *modname;
+ char *logical_modname;
+ char *flag_names;
+ int type;
+ int hash;
+ int hash2;
+} __attribute__((aligned(8)));
+
+int register_dynamic_debug_module(char *mod_name, int type, char *share_name,
+ char *flags, int hash, int hash2);
+
+#if defined(CONFIG_DYNAMIC_PRINTK_DEBUG)
+extern int unregister_dynamic_debug_module(char *mod_name);
+extern int __dynamic_dbg_enabled_helper(char *modname, int type,
+ int value, int hash);
+
+#define __dynamic_dbg_enabled(module, type, value, level, hash) ({ \
+ int __ret = 0; \
+ if (unlikely((dynamic_printk_enabled & (1LL << DEBUG_HASH)) && \
+ (dynamic_printk_enabled2 & (1LL << DEBUG_HASH2)))) \
+ __ret = __dynamic_dbg_enabled_helper(module, type, \
+ value, hash);\
+ __ret; })
+
+#define dynamic_pr_debug(fmt, ...) do { \
+ static char mod_name[] \
+ __attribute__((section("__verbose_strings"))) \
+ = KBUILD_MODNAME; \
+ static struct mod_debug descriptor \
+ __used \
+ __attribute__((section("__verbose"), aligned(8))) = \
+ { mod_name, mod_name, NULL, TYPE_BOOLEAN, DEBUG_HASH, DEBUG_HASH2 };\
+ if (__dynamic_dbg_enabled(KBUILD_MODNAME, TYPE_BOOLEAN, \
+ 0, 0, DEBUG_HASH)) \
+ printk(KERN_DEBUG KBUILD_MODNAME ":" fmt, \
+ ##__VA_ARGS__); \
+ } while (0)
+
+#define dynamic_dev_dbg(dev, format, ...) do { \
+ static char mod_name[] \
+ __attribute__((section("__verbose_strings"))) \
+ = KBUILD_MODNAME; \
+ static struct mod_debug descriptor \
+ __used \
+ __attribute__((section("__verbose"), aligned(8))) = \
+ { mod_name, mod_name, NULL, TYPE_BOOLEAN, DEBUG_HASH, DEBUG_HASH2 };\
+ if (__dynamic_dbg_enabled(KBUILD_MODNAME, TYPE_BOOLEAN, \
+ 0, 0, DEBUG_HASH)) \
+ dev_printk(KERN_DEBUG, dev, \
+ KBUILD_MODNAME ": " format, \
+ ##__VA_ARGS__); \
+ } while (0)
+
+#else
+
+static inline int unregister_dynamic_debug_module(const char *mod_name)
+{
+ return 0;
+}
+static inline int __dynamic_dbg_enabled_helper(char *modname, int type,
+ int value, int hash)
+{
+ return 0;
+}
+
+#define __dynamic_dbg_enabled(module, type, value, level, hash) ({ 0; })
+#define dynamic_pr_debug(fmt, ...) do { } while (0)
+#define dynamic_dev_dbg(dev, format, ...) do { } while (0)
+#endif
+
+#endif
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index e971c55f45a..1f3cd8ad052 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -16,6 +16,7 @@
#include <linux/log2.h>
#include <linux/typecheck.h>
#include <linux/ratelimit.h>
+#include <linux/dynamic_printk.h>
#include <asm/byteorder.h>
#include <asm/bug.h>
@@ -304,8 +305,12 @@ static inline char *pack_hex_byte(char *buf, u8 byte)
#define pr_info(fmt, arg...) \
printk(KERN_INFO fmt, ##arg)
-#ifdef DEBUG
/* If you are writing a driver, please use dev_dbg instead */
+#if defined(CONFIG_DYNAMIC_PRINTK_DEBUG)
+#define pr_debug(fmt, ...) do { \
+ dynamic_pr_debug(fmt, ##__VA_ARGS__); \
+ } while (0)
+#elif defined(DEBUG)
#define pr_debug(fmt, arg...) \
printk(KERN_DEBUG fmt, ##arg)
#else
diff --git a/include/linux/module.h b/include/linux/module.h
index 68e09557c95..a41555cbe00 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -345,7 +345,6 @@ struct module
/* Reference counts */
struct module_ref ref[NR_CPUS];
#endif
-
};
#ifndef MODULE_ARCH_INIT
#define MODULE_ARCH_INIT {}
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h
index 95ac21ab3a0..4b8cc6a3247 100644
--- a/include/linux/platform_device.h
+++ b/include/linux/platform_device.h
@@ -37,6 +37,8 @@ extern int platform_add_devices(struct platform_device **, int);
extern struct platform_device *platform_device_register_simple(const char *, int id,
struct resource *, unsigned int);
+extern struct platform_device *platform_device_register_data(struct device *,
+ const char *, int, const void *, size_t);
extern struct platform_device *platform_device_alloc(const char *name, int id);
extern int platform_device_add_resources(struct platform_device *pdev, struct resource *res, unsigned int num);
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index 37fa24152bd..b330e289d71 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -78,6 +78,8 @@ struct sysfs_ops {
ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t);
};
+struct sysfs_dirent;
+
#ifdef CONFIG_SYSFS
int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *),
@@ -117,9 +119,14 @@ int sysfs_add_file_to_group(struct kobject *kobj,
void sysfs_remove_file_from_group(struct kobject *kobj,
const struct attribute *attr, const char *group);
-void sysfs_notify(struct kobject *kobj, char *dir, char *attr);
-
-extern int __must_check sysfs_init(void);
+void sysfs_notify(struct kobject *kobj, const char *dir, const char *attr);
+void sysfs_notify_dirent(struct sysfs_dirent *sd);
+struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd,
+ const unsigned char *name);
+struct sysfs_dirent *sysfs_get(struct sysfs_dirent *sd);
+void sysfs_put(struct sysfs_dirent *sd);
+void sysfs_printk_last_file(void);
+int __must_check sysfs_init(void);
#else /* CONFIG_SYSFS */
@@ -222,7 +229,24 @@ static inline void sysfs_remove_file_from_group(struct kobject *kobj,
{
}
-static inline void sysfs_notify(struct kobject *kobj, char *dir, char *attr)
+static inline void sysfs_notify(struct kobject *kobj, const char *dir,
+ const char *attr)
+{
+}
+static inline void sysfs_notify_dirent(struct sysfs_dirent *sd)
+{
+}
+static inline
+struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd,
+ const unsigned char *name)
+{
+ return NULL;
+}
+static inline struct sysfs_dirent *sysfs_get(struct sysfs_dirent *sd)
+{
+ return NULL;
+}
+static inline void sysfs_put(struct sysfs_dirent *sd)
{
}
@@ -231,6 +255,10 @@ static inline int __must_check sysfs_init(void)
return 0;
}
+static inline void sysfs_printk_last_file(void)
+{
+}
+
#endif /* CONFIG_SYSFS */
#endif /* _SYSFS_H_ */