summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Kconfig3
-rw-r--r--lib/Kconfig.debug17
-rw-r--r--lib/Makefile10
-rw-r--r--lib/argv_split.c105
-rw-r--r--lib/fault-inject.c4
-rw-r--r--lib/hexdump.c6
-rw-r--r--lib/idr.c6
-rw-r--r--lib/iomap.c15
-rw-r--r--lib/kasprintf.c44
-rw-r--r--lib/kobject.c135
-rw-r--r--lib/kobject_uevent.c223
-rw-r--r--lib/lzo/lzo1x_compress.c6
-rw-r--r--lib/radix-tree.c2
-rw-r--r--lib/swiotlb.c6
-rw-r--r--lib/vsprintf.c35
-rw-r--r--lib/zlib_inflate/Makefile2
-rw-r--r--lib/zlib_inflate/inffast.c18
-rw-r--r--lib/zlib_inflate/inflate.c8
-rw-r--r--lib/zlib_inflate/inflate_syms.c1
-rw-r--r--lib/zlib_inflate/infutil.c49
20 files changed, 429 insertions, 266 deletions
diff --git a/lib/Kconfig b/lib/Kconfig
index e5c2c514174a..ba3d104994d9 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -138,4 +138,7 @@ config HAS_DMA
depends on !NO_DMA
default y
+config CHECK_SIGNATURE
+ bool
+
endmenu
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 640844024ffd..396c38b3cb69 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -167,7 +167,7 @@ config SLUB_DEBUG_ON
config DEBUG_PREEMPT
bool "Debug preemptible kernel"
- depends on DEBUG_KERNEL && PREEMPT && TRACE_IRQFLAGS_SUPPORT
+ depends on DEBUG_KERNEL && PREEMPT && (TRACE_IRQFLAGS_SUPPORT || PPC64)
default y
help
If you say Y here then the kernel will use a debug variant of the
@@ -283,6 +283,19 @@ config LOCKDEP
select KALLSYMS
select KALLSYMS_ALL
+config LOCK_STAT
+ bool "Lock usage statistics"
+ depends on DEBUG_KERNEL && TRACE_IRQFLAGS_SUPPORT && STACKTRACE_SUPPORT && LOCKDEP_SUPPORT
+ select LOCKDEP
+ select DEBUG_SPINLOCK
+ select DEBUG_MUTEXES
+ select DEBUG_LOCK_ALLOC
+ default n
+ help
+ This feature enables tracking lock contention points
+
+ For more details, see Documentation/lockstat.txt
+
config DEBUG_LOCKDEP
bool "Lock dependency engine debugging"
depends on DEBUG_KERNEL && LOCKDEP
@@ -338,7 +351,7 @@ config DEBUG_HIGHMEM
config DEBUG_BUGVERBOSE
bool "Verbose BUG() reporting (adds 70K)" if DEBUG_KERNEL && EMBEDDED
depends on BUG
- depends on ARM || ARM26 || AVR32 || M32R || M68K || SPARC32 || SPARC64 || FRV || SUPERH || GENERIC_BUG || BFIN
+ depends on ARM || AVR32 || M32R || M68K || SPARC32 || SPARC64 || FRV || SUPERH || GENERIC_BUG || BFIN
default !EMBEDDED
help
Say Y here to make BUG() panics output the file name and line number
diff --git a/lib/Makefile b/lib/Makefile
index da68b2ca0606..6c4ea33bb2cb 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -5,23 +5,25 @@
lib-y := ctype.o string.o vsprintf.o cmdline.o \
rbtree.o radix-tree.o dump_stack.o \
idr.o int_sqrt.o bitmap.o extable.o prio_tree.o \
- sha1.o irq_regs.o reciprocal_div.o
+ sha1.o irq_regs.o reciprocal_div.o argv_split.o
lib-$(CONFIG_MMU) += ioremap.o
lib-$(CONFIG_SMP) += cpumask.o
-lib-y += kobject.o kref.o kobject_uevent.o klist.o
+lib-y += kobject.o kref.o klist.o
obj-y += div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \
- bust_spinlocks.o hexdump.o
+ bust_spinlocks.o hexdump.o kasprintf.o
ifeq ($(CONFIG_DEBUG_KOBJECT),y)
CFLAGS_kobject.o += -DDEBUG
CFLAGS_kobject_uevent.o += -DDEBUG
endif
+lib-$(CONFIG_HOTPLUG) += kobject_uevent.o
obj-$(CONFIG_GENERIC_IOMAP) += iomap.o
-obj-$(CONFIG_HAS_IOMEM) += iomap_copy.o devres.o check_signature.o
+obj-$(CONFIG_HAS_IOMEM) += iomap_copy.o devres.o
+obj-$(CONFIG_CHECK_SIGNATURE) += check_signature.o
obj-$(CONFIG_DEBUG_LOCKING_API_SELFTESTS) += locking-selftest.o
obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock_debug.o
lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
diff --git a/lib/argv_split.c b/lib/argv_split.c
new file mode 100644
index 000000000000..4096ed42f490
--- /dev/null
+++ b/lib/argv_split.c
@@ -0,0 +1,105 @@
+/*
+ * Helper function for splitting a string into an argv-like array.
+ */
+
+#include <linux/kernel.h>
+#include <linux/ctype.h>
+#include <linux/bug.h>
+
+static const char *skip_sep(const char *cp)
+{
+ while (*cp && isspace(*cp))
+ cp++;
+
+ return cp;
+}
+
+static const char *skip_arg(const char *cp)
+{
+ while (*cp && !isspace(*cp))
+ cp++;
+
+ return cp;
+}
+
+static int count_argc(const char *str)
+{
+ int count = 0;
+
+ while (*str) {
+ str = skip_sep(str);
+ if (*str) {
+ count++;
+ str = skip_arg(str);
+ }
+ }
+
+ return count;
+}
+
+/**
+ * argv_free - free an argv
+ * @argv - the argument vector to be freed
+ *
+ * Frees an argv and the strings it points to.
+ */
+void argv_free(char **argv)
+{
+ char **p;
+ for (p = argv; *p; p++)
+ kfree(*p);
+
+ kfree(argv);
+}
+EXPORT_SYMBOL(argv_free);
+
+/**
+ * argv_split - split a string at whitespace, returning an argv
+ * @gfp: the GFP mask used to allocate memory
+ * @str: the string to be split
+ * @argcp: returned argument count
+ *
+ * Returns an array of pointers to strings which are split out from
+ * @str. This is performed by strictly splitting on white-space; no
+ * quote processing is performed. Multiple whitespace characters are
+ * considered to be a single argument separator. The returned array
+ * is always NULL-terminated. Returns NULL on memory allocation
+ * failure.
+ */
+char **argv_split(gfp_t gfp, const char *str, int *argcp)
+{
+ int argc = count_argc(str);
+ char **argv = kzalloc(sizeof(*argv) * (argc+1), gfp);
+ char **argvp;
+
+ if (argv == NULL)
+ goto out;
+
+ *argcp = argc;
+ argvp = argv;
+
+ while (*str) {
+ str = skip_sep(str);
+
+ if (*str) {
+ const char *p = str;
+ char *t;
+
+ str = skip_arg(str);
+
+ t = kstrndup(p, str-p, gfp);
+ if (t == NULL)
+ goto fail;
+ *argvp++ = t;
+ }
+ }
+ *argvp = NULL;
+
+ out:
+ return argv;
+
+ fail:
+ argv_free(argv);
+ return NULL;
+}
+EXPORT_SYMBOL(argv_split);
diff --git a/lib/fault-inject.c b/lib/fault-inject.c
index b18fc2ff9ffe..23985a278bbb 100644
--- a/lib/fault-inject.c
+++ b/lib/fault-inject.c
@@ -139,12 +139,14 @@ static void debugfs_ul_set(void *data, u64 val)
*(unsigned long *)data = val;
}
+#ifdef CONFIG_FAULT_INJECTION_STACKTRACE_FILTER
static void debugfs_ul_set_MAX_STACK_TRACE_DEPTH(void *data, u64 val)
{
*(unsigned long *)data =
val < MAX_STACK_TRACE_DEPTH ?
val : MAX_STACK_TRACE_DEPTH;
}
+#endif /* CONFIG_FAULT_INJECTION_STACKTRACE_FILTER */
static u64 debugfs_ul_get(void *data)
{
@@ -159,6 +161,7 @@ static struct dentry *debugfs_create_ul(const char *name, mode_t mode,
return debugfs_create_file(name, mode, parent, value, &fops_ul);
}
+#ifdef CONFIG_FAULT_INJECTION_STACKTRACE_FILTER
DEFINE_SIMPLE_ATTRIBUTE(fops_ul_MAX_STACK_TRACE_DEPTH, debugfs_ul_get,
debugfs_ul_set_MAX_STACK_TRACE_DEPTH, "%llu\n");
@@ -169,6 +172,7 @@ static struct dentry *debugfs_create_ul_MAX_STACK_TRACE_DEPTH(
return debugfs_create_file(name, mode, parent, value,
&fops_ul_MAX_STACK_TRACE_DEPTH);
}
+#endif /* CONFIG_FAULT_INJECTION_STACKTRACE_FILTER */
static void debugfs_atomic_t_set(void *data, u64 val)
{
diff --git a/lib/hexdump.c b/lib/hexdump.c
index 473f5aed6cae..bd5edaeaa80b 100644
--- a/lib/hexdump.c
+++ b/lib/hexdump.c
@@ -145,9 +145,9 @@ EXPORT_SYMBOL(hex_dump_to_buffer);
*/
void print_hex_dump(const char *level, const char *prefix_str, int prefix_type,
int rowsize, int groupsize,
- void *buf, size_t len, bool ascii)
+ const void *buf, size_t len, bool ascii)
{
- u8 *ptr = buf;
+ const u8 *ptr = buf;
int i, linelen, remaining = len;
unsigned char linebuf[200];
@@ -189,7 +189,7 @@ EXPORT_SYMBOL(print_hex_dump);
* rowsize of 16, groupsize of 1, and ASCII output included.
*/
void print_hex_dump_bytes(const char *prefix_str, int prefix_type,
- void *buf, size_t len)
+ const void *buf, size_t len)
{
print_hex_dump(KERN_DEBUG, prefix_str, prefix_type, 16, 1,
buf, len, 1);
diff --git a/lib/idr.c b/lib/idr.c
index 5ca67b3cfd35..d0f1acdbfa3a 100644
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -405,7 +405,7 @@ EXPORT_SYMBOL(idr_remove);
*/
void idr_remove_all(struct idr *idp)
{
- int n, id, max, error = 0;
+ int n, id, max;
struct idr_layer *p;
struct idr_layer *pa[MAX_LEVEL];
struct idr_layer **paa = &pa[0];
@@ -415,7 +415,7 @@ void idr_remove_all(struct idr *idp)
max = 1 << n;
id = 0;
- while (id < max && !error) {
+ while (id < max) {
while (n > IDR_BITS && p) {
n -= IDR_BITS;
*paa++ = p;
@@ -590,7 +590,7 @@ static int init_id_cache(void)
{
if (!idr_layer_cache)
idr_layer_cache = kmem_cache_create("idr_layer_cache",
- sizeof(struct idr_layer), 0, 0, idr_cache_ctor, NULL);
+ sizeof(struct idr_layer), 0, 0, idr_cache_ctor);
return 0;
}
diff --git a/lib/iomap.c b/lib/iomap.c
index a57d262a5ed9..864f2ec1966e 100644
--- a/lib/iomap.c
+++ b/lib/iomap.c
@@ -240,7 +240,20 @@ void ioport_unmap(void __iomem *addr)
EXPORT_SYMBOL(ioport_map);
EXPORT_SYMBOL(ioport_unmap);
-/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
+/**
+ * pci_iomap - create a virtual mapping cookie for a PCI BAR
+ * @dev: PCI device that owns the BAR
+ * @bar: BAR number
+ * @maxlen: length of the memory to map
+ *
+ * Using this function you will get a __iomem address to your device BAR.
+ * You can access it using ioread*() and iowrite*(). These functions hide
+ * the details if this is a MMIO or PIO address space and will just do what
+ * you expect from them in the correct way.
+ *
+ * @maxlen specifies the maximum length to map. If you want to get access to
+ * the complete BAR without checking for its length first, pass %0 here.
+ * */
void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
{
unsigned long start = pci_resource_start(dev, bar);
diff --git a/lib/kasprintf.c b/lib/kasprintf.c
new file mode 100644
index 000000000000..c5ff1fd10030
--- /dev/null
+++ b/lib/kasprintf.c
@@ -0,0 +1,44 @@
+/*
+ * linux/lib/kasprintf.c
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ */
+
+#include <stdarg.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/string.h>
+
+/* Simplified asprintf. */
+char *kvasprintf(gfp_t gfp, const char *fmt, va_list ap)
+{
+ unsigned int len;
+ char *p;
+ va_list aq;
+
+ va_copy(aq, ap);
+ len = vsnprintf(NULL, 0, fmt, aq);
+ va_end(aq);
+
+ p = kmalloc(len+1, gfp);
+ if (!p)
+ return NULL;
+
+ vsnprintf(p, len+1, fmt, ap);
+
+ return p;
+}
+EXPORT_SYMBOL(kvasprintf);
+
+char *kasprintf(gfp_t gfp, const char *fmt, ...)
+{
+ va_list ap;
+ char *p;
+
+ va_start(ap, fmt);
+ p = kvasprintf(gfp, fmt, ap);
+ va_end(ap);
+
+ return p;
+}
+EXPORT_SYMBOL(kasprintf);
diff --git a/lib/kobject.c b/lib/kobject.c
index 4b08e0ff95c8..03d40360ff1b 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -2,6 +2,8 @@
* kobject.c - library routines for handling generic kernel objects
*
* Copyright (c) 2002-2003 Patrick Mochel <mochel@osdl.org>
+ * Copyright (c) 2006-2007 Greg Kroah-Hartman <greg@kroah.com>
+ * Copyright (c) 2006-2007 Novell Inc.
*
* This file is released under the GPLv2.
*
@@ -44,11 +46,11 @@ static int populate_dir(struct kobject * kobj)
return error;
}
-static int create_dir(struct kobject *kobj, struct sysfs_dirent *shadow_parent)
+static int create_dir(struct kobject * kobj)
{
int error = 0;
if (kobject_name(kobj)) {
- error = sysfs_create_dir(kobj, shadow_parent);
+ error = sysfs_create_dir(kobj);
if (!error) {
if ((error = populate_dir(kobj)))
sysfs_remove_dir(kobj);
@@ -131,7 +133,6 @@ void kobject_init(struct kobject * kobj)
return;
kref_init(&kobj->kref);
INIT_LIST_HEAD(&kobj->entry);
- init_waitqueue_head(&kobj->poll);
kobj->kset = kset_get(kobj->kset);
}
@@ -157,12 +158,11 @@ static void unlink(struct kobject * kobj)
}
/**
- * kobject_shadow_add - add an object to the hierarchy.
+ * kobject_add - add an object to the hierarchy.
* @kobj: object.
- * @shadow_parent: sysfs directory to add to.
*/
-int kobject_shadow_add(struct kobject *kobj, struct sysfs_dirent *shadow_parent)
+int kobject_add(struct kobject * kobj)
{
int error = 0;
struct kobject * parent;
@@ -170,7 +170,7 @@ int kobject_shadow_add(struct kobject *kobj, struct sysfs_dirent *shadow_parent)
if (!(kobj = kobject_get(kobj)))
return -ENOENT;
if (!kobj->k_name)
- kobj->k_name = kobj->name;
+ kobject_set_name(kobj, "NO_NAME");
if (!*kobj->k_name) {
pr_debug("kobject attempted to be registered with no name!\n");
WARN_ON(1);
@@ -181,7 +181,7 @@ int kobject_shadow_add(struct kobject *kobj, struct sysfs_dirent *shadow_parent)
pr_debug("kobject %s: registering. parent: %s, set: %s\n",
kobject_name(kobj), parent ? kobject_name(parent) : "<NULL>",
- kobj->kset ? kobj->kset->kobj.name : "<NULL>" );
+ kobj->kset ? kobject_name(&kobj->kset->kobj) : "<NULL>" );
if (kobj->kset) {
spin_lock(&kobj->kset->list_lock);
@@ -194,7 +194,7 @@ int kobject_shadow_add(struct kobject *kobj, struct sysfs_dirent *shadow_parent)
kobj->parent = parent;
}
- error = create_dir(kobj, shadow_parent);
+ error = create_dir(kobj);
if (error) {
/* unlink does the kobject_put() for us */
unlink(kobj);
@@ -216,16 +216,6 @@ int kobject_shadow_add(struct kobject *kobj, struct sysfs_dirent *shadow_parent)
}
/**
- * kobject_add - add an object to the hierarchy.
- * @kobj: object.
- */
-int kobject_add(struct kobject * kobj)
-{
- return kobject_shadow_add(kobj, NULL);
-}
-
-
-/**
* kobject_register - initialize and add an object.
* @kobj: object in question.
*/
@@ -255,54 +245,50 @@ int kobject_register(struct kobject * kobj)
int kobject_set_name(struct kobject * kobj, const char * fmt, ...)
{
int error = 0;
- int limit = KOBJ_NAME_LEN;
+ int limit;
int need;
va_list args;
- char * name;
+ char *name;
- /*
- * First, try the static array
- */
- va_start(args,fmt);
- need = vsnprintf(kobj->name,limit,fmt,args);
+ /* find out how big a buffer we need */
+ name = kmalloc(1024, GFP_KERNEL);
+ if (!name) {
+ error = -ENOMEM;
+ goto done;
+ }
+ va_start(args, fmt);
+ need = vsnprintf(name, 1024, fmt, args);
va_end(args);
- if (need < limit)
- name = kobj->name;
- else {
- /*
- * Need more space? Allocate it and try again
- */
- limit = need + 1;
- name = kmalloc(limit,GFP_KERNEL);
- if (!name) {
- error = -ENOMEM;
- goto Done;
- }
- va_start(args,fmt);
- need = vsnprintf(name,limit,fmt,args);
- va_end(args);
-
- /* Still? Give up. */
- if (need >= limit) {
- kfree(name);
- error = -EFAULT;
- goto Done;
- }
+ kfree(name);
+
+ /* Allocate the new space and copy the string in */
+ limit = need + 1;
+ name = kmalloc(limit, GFP_KERNEL);
+ if (!name) {
+ error = -ENOMEM;
+ goto done;
+ }
+ va_start(args, fmt);
+ need = vsnprintf(name, limit, fmt, args);
+ va_end(args);
+
+ /* something wrong with the string we copied? */
+ if (need >= limit) {
+ kfree(name);
+ error = -EFAULT;
+ goto done;
}
/* Free the old name, if necessary. */
- if (kobj->k_name && kobj->k_name != kobj->name)
- kfree(kobj->k_name);
+ kfree(kobj->k_name);
/* Now, set the new name */
kobj->k_name = name;
- Done:
+done:
return error;
}
-
EXPORT_SYMBOL(kobject_set_name);
-
/**
* kobject_rename - change the name of an object
* @kobj: object in question.
@@ -338,7 +324,7 @@ int kobject_rename(struct kobject * kobj, const char *new_name)
/* Note : if we want to send the new name alone, not the full path,
* we could probably use kobject_name(kobj); */
- error = sysfs_rename_dir(kobj, kobj->parent->sd, new_name);
+ error = sysfs_rename_dir(kobj, new_name);
/* This function is mostly/only used for network interface.
* Some hotplug package track interfaces by their name and
@@ -355,27 +341,6 @@ out:
}
/**
- * kobject_rename - change the name of an object
- * @kobj: object in question.
- * @new_parent: object's new parent
- * @new_name: object's new name
- */
-
-int kobject_shadow_rename(struct kobject *kobj,
- struct sysfs_dirent *new_parent, const char *new_name)
-{
- int error = 0;
-
- kobj = kobject_get(kobj);
- if (!kobj)
- return -EINVAL;
- error = sysfs_rename_dir(kobj, new_parent, new_name);
- kobject_put(kobj);
-
- return error;
-}
-
-/**
* kobject_move - move object to another parent
* @kobj: object in question.
* @new_parent: object's new parent (can be NULL)
@@ -477,13 +442,16 @@ void kobject_cleanup(struct kobject * kobj)
struct kobj_type * t = get_ktype(kobj);
struct kset * s = kobj->kset;
struct kobject * parent = kobj->parent;
+ const char *name = kobj->k_name;
pr_debug("kobject %s: cleaning up\n",kobject_name(kobj));
- if (kobj->k_name != kobj->name)
- kfree(kobj->k_name);
- kobj->k_name = NULL;
- if (t && t->release)
+ if (t && t->release) {
t->release(kobj);
+ /* If we have a release function, we can guess that this was
+ * not a statically allocated kobject, so we should be safe to
+ * free the name */
+ kfree(name);
+ }
if (s)
kset_put(s);
kobject_put(parent);
@@ -651,11 +619,6 @@ struct kobject * kset_find_obj(struct kset * kset, const char * name)
return ret;
}
-void subsystem_init(struct kset *s)
-{
- kset_init(s);
-}
-
int subsystem_register(struct kset *s)
{
return kset_register(s);
@@ -679,9 +642,9 @@ int subsys_create_file(struct kset *s, struct subsys_attribute *a)
if (!s || !a)
return -EINVAL;
- if (subsys_get(s)) {
+ if (kset_get(s)) {
error = sysfs_create_file(&s->kobj, &a->attr);
- subsys_put(s);
+ kset_put(s);
}
return error;
}
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c
index 12e311dc664c..2e4eae5b0824 100644
--- a/lib/kobject_uevent.c
+++ b/lib/kobject_uevent.c
@@ -22,41 +22,62 @@
#include <linux/kobject.h>
#include <net/sock.h>
-#define BUFFER_SIZE 2048 /* buffer for the variables */
-#define NUM_ENVP 32 /* number of env pointers */
-#if defined(CONFIG_HOTPLUG)
u64 uevent_seqnum;
-char uevent_helper[UEVENT_HELPER_PATH_LEN] = "/sbin/hotplug";
+char uevent_helper[UEVENT_HELPER_PATH_LEN] = CONFIG_UEVENT_HELPER_PATH;
static DEFINE_SPINLOCK(sequence_lock);
#if defined(CONFIG_NET)
static struct sock *uevent_sock;
#endif
-static char *action_to_string(enum kobject_action action)
+/* the strings here must match the enum in include/linux/kobject.h */
+static const char *kobject_actions[] = {
+ [KOBJ_ADD] = "add",
+ [KOBJ_REMOVE] = "remove",
+ [KOBJ_CHANGE] = "change",
+ [KOBJ_MOVE] = "move",
+ [KOBJ_ONLINE] = "online",
+ [KOBJ_OFFLINE] = "offline",
+};
+
+/**
+ * kobject_action_type - translate action string to numeric type
+ *
+ * @buf: buffer containing the action string, newline is ignored
+ * @len: length of buffer
+ * @type: pointer to the location to store the action type
+ *
+ * Returns 0 if the action string was recognized.
+ */
+int kobject_action_type(const char *buf, size_t count,
+ enum kobject_action *type)
{
- switch (action) {
- case KOBJ_ADD:
- return "add";
- case KOBJ_REMOVE:
- return "remove";
- case KOBJ_CHANGE:
- return "change";
- case KOBJ_OFFLINE:
- return "offline";
- case KOBJ_ONLINE:
- return "online";
- case KOBJ_MOVE:
- return "move";
- default:
- return NULL;
+ enum kobject_action action;
+ int ret = -EINVAL;
+
+ if (count && buf[count-1] == '\n')
+ count--;
+
+ if (!count)
+ goto out;
+
+ for (action = 0; action < ARRAY_SIZE(kobject_actions); action++) {
+ if (strncmp(kobject_actions[action], buf, count) != 0)
+ continue;
+ if (kobject_actions[action][count] != '\0')
+ continue;
+ *type = action;
+ ret = 0;
+ break;
}
+out:
+ return ret;
}
/**
* kobject_uevent_env - send an uevent with environmental data
*
- * @action: action that is happening (usually KOBJ_MOVE)
+ * @action: action that is happening
* @kobj: struct kobject that the action is happening to
* @envp_ext: pointer to environmental data
*
@@ -64,36 +85,26 @@ static char *action_to_string(enum kobject_action action)
* corresponding error when it fails.
*/
int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
- char *envp_ext[])
+ char *envp_ext[])
{
- char **envp;
- char *buffer;
- char *scratch;
- const char *action_string;
+ struct kobj_uevent_env *env;
+ const char *action_string = kobject_actions[action];
const char *devpath = NULL;
const char *subsystem;
struct kobject *top_kobj;
struct kset *kset;
struct kset_uevent_ops *uevent_ops;
u64 seq;
- char *seq_buff;
int i = 0;
int retval = 0;
- int j;
pr_debug("%s\n", __FUNCTION__);
- action_string = action_to_string(action);
- if (!action_string) {
- pr_debug("kobject attempted to send uevent without action_string!\n");
- return -EINVAL;
- }
-
/* search the kset we belong to */
top_kobj = kobj;
- while (!top_kobj->kset && top_kobj->parent) {
+ while (!top_kobj->kset && top_kobj->parent)
top_kobj = top_kobj->parent;
- }
+
if (!top_kobj->kset) {
pr_debug("kobject attempted to send uevent without kset!\n");
return -EINVAL;
@@ -102,7 +113,7 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
kset = top_kobj->kset;
uevent_ops = kset->uevent_ops;
- /* skip the event, if the filter returns zero. */
+ /* skip the event, if the filter returns zero. */
if (uevent_ops && uevent_ops->filter)
if (!uevent_ops->filter(kset, kobj)) {
pr_debug("kobject filter function caused the event to drop!\n");
@@ -119,18 +130,11 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
return 0;
}
- /* environment index */
- envp = kzalloc(NUM_ENVP * sizeof (char *), GFP_KERNEL);
- if (!envp)
+ /* environment buffer */
+ env = kzalloc(sizeof(struct kobj_uevent_env), GFP_KERNEL);
+ if (!env)
return -ENOMEM;
- /* environment values */
- buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL);
- if (!buffer) {
- retval = -ENOMEM;
- goto exit;
- }
-
/* complete object path */
devpath = kobject_get_path(kobj, GFP_KERNEL);
if (!devpath) {
@@ -138,29 +142,29 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
goto exit;
}
- /* event environemnt for helper process only */
- envp[i++] = "HOME=/";
- envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
-
/* default keys */
- scratch = buffer;
- envp [i++] = scratch;
- scratch += sprintf(scratch, "ACTION=%s", action_string) + 1;
- envp [i++] = scratch;
- scratch += sprintf (scratch, "DEVPATH=%s", devpath) + 1;
- envp [i++] = scratch;
- scratch += sprintf(scratch, "SUBSYSTEM=%s", subsystem) + 1;
- for (j = 0; envp_ext && envp_ext[j]; j++)
- envp[i++] = envp_ext[j];
- /* just reserve the space, overwrite it after kset call has returned */
- envp[i++] = seq_buff = scratch;
- scratch += strlen("SEQNUM=18446744073709551616") + 1;
+ retval = add_uevent_var(env, "ACTION=%s", action_string);
+ if (retval)
+ goto exit;
+ retval = add_uevent_var(env, "DEVPATH=%s", devpath);
+ if (retval)
+ goto exit;
+ retval = add_uevent_var(env, "SUBSYSTEM=%s", subsystem);
+ if (retval)
+ goto exit;
+
+ /* keys passed in from the caller */
+ if (envp_ext) {
+ for (i = 0; envp_ext[i]; i++) {
+ retval = add_uevent_var(env, envp_ext[i]);
+ if (retval)
+ goto exit;
+ }
+ }
/* let the kset specific function add its stuff */
if (uevent_ops && uevent_ops->uevent) {
- retval = uevent_ops->uevent(kset, kobj,
- &envp[i], NUM_ENVP - i, scratch,
- BUFFER_SIZE - (scratch - buffer));
+ retval = uevent_ops->uevent(kset, kobj, env);
if (retval) {
pr_debug ("%s - uevent() returned %d\n",
__FUNCTION__, retval);
@@ -168,11 +172,13 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
}
}
- /* we will send an event, request a new sequence number */
+ /* we will send an event, so request a new sequence number */
spin_lock(&sequence_lock);
seq = ++uevent_seqnum;
spin_unlock(&sequence_lock);
- sprintf(seq_buff, "SEQNUM=%llu", (unsigned long long)seq);
+ retval = add_uevent_var(env, "SEQNUM=%llu", (unsigned long long)seq);
+ if (retval)
+ goto exit;
#if defined(CONFIG_NET)
/* send netlink message */
@@ -182,17 +188,19 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
/* allocate message with the maximum possible size */
len = strlen(action_string) + strlen(devpath) + 2;
- skb = alloc_skb(len + BUFFER_SIZE, GFP_KERNEL);
+ skb = alloc_skb(len + env->buflen, GFP_KERNEL);
if (skb) {
+ char *scratch;
+
/* add header */
scratch = skb_put(skb, len);
sprintf(scratch, "%s@%s", action_string, devpath);
/* copy keys to our continuous event payload buffer */
- for (i = 2; envp[i]; i++) {
- len = strlen(envp[i]) + 1;
+ for (i = 0; i < env->envp_idx; i++) {
+ len = strlen(env->envp[i]) + 1;
scratch = skb_put(skb, len);
- strcpy(scratch, envp[i]);
+ strcpy(scratch, env->envp[i]);
}
NETLINK_CB(skb).dst_group = 1;
@@ -208,13 +216,19 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
argv [0] = uevent_helper;
argv [1] = (char *)subsystem;
argv [2] = NULL;
- call_usermodehelper (argv[0], argv, envp, 0);
+ retval = add_uevent_var(env, "HOME=/");
+ if (retval)
+ goto exit;
+ retval = add_uevent_var(env, "PATH=/sbin:/bin:/usr/sbin:/usr/bin");
+ if (retval)
+ goto exit;
+
+ call_usermodehelper (argv[0], argv, env->envp, UMH_WAIT_EXEC);
}
exit:
kfree(devpath);
- kfree(buffer);
- kfree(envp);
+ kfree(env);
return retval;
}
@@ -223,7 +237,7 @@ EXPORT_SYMBOL_GPL(kobject_uevent_env);
/**
* kobject_uevent - notify userspace by ending an uevent
*
- * @action: action that is happening (usually KOBJ_ADD and KOBJ_REMOVE)
+ * @action: action that is happening
* @kobj: struct kobject that the action is happening to
*
* Returns 0 if kobject_uevent() is completed with success or the
@@ -237,52 +251,38 @@ int kobject_uevent(struct kobject *kobj, enum kobject_action action)
EXPORT_SYMBOL_GPL(kobject_uevent);
/**
- * add_uevent_var - helper for creating event variables
- * @envp: Pointer to table of environment variables, as passed into
- * uevent() method.
- * @num_envp: Number of environment variable slots available, as
- * passed into uevent() method.
- * @cur_index: Pointer to current index into @envp. It should be
- * initialized to 0 before the first call to add_uevent_var(),
- * and will be incremented on success.
- * @buffer: Pointer to buffer for environment variables, as passed
- * into uevent() method.
- * @buffer_size: Length of @buffer, as passed into uevent() method.
- * @cur_len: Pointer to current length of space used in @buffer.
- * Should be initialized to 0 before the first call to
- * add_uevent_var(), and will be incremented on success.
- * @format: Format for creating environment variable (of the form
- * "XXX=%x") for snprintf().
+ * add_uevent_var - add key value string to the environment buffer
+ * @env: environment buffer structure
+ * @format: printf format for the key=value pair
*
* Returns 0 if environment variable was added successfully or -ENOMEM
* if no space was available.
*/
-int add_uevent_var(char **envp, int num_envp, int *cur_index,
- char *buffer, int buffer_size, int *cur_len,
- const char *format, ...)
+int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...)
{
va_list args;
+ int len;
- /*
- * We check against num_envp - 1 to make sure there is at
- * least one slot left after we return, since kobject_uevent()
- * needs to set the last slot to NULL.
- */
- if (*cur_index >= num_envp - 1)
+ if (env->envp_idx >= ARRAY_SIZE(env->envp)) {
+ printk(KERN_ERR "add_uevent_var: too many keys\n");
+ WARN_ON(1);
return -ENOMEM;
-
- envp[*cur_index] = buffer + *cur_len;
+ }
va_start(args, format);
- *cur_len += vsnprintf(envp[*cur_index],
- max(buffer_size - *cur_len, 0),
- format, args) + 1;
+ len = vsnprintf(&env->buf[env->buflen],
+ sizeof(env->buf) - env->buflen,
+ format, args);
va_end(args);
- if (*cur_len > buffer_size)
+ if (len >= (sizeof(env->buf) - env->buflen)) {
+ printk(KERN_ERR "add_uevent_var: buffer size too small\n");
+ WARN_ON(1);
return -ENOMEM;
+ }
- (*cur_index)++;
+ env->envp[env->envp_idx++] = &env->buf[env->buflen];
+ env->buflen += len + 1;
return 0;
}
EXPORT_SYMBOL_GPL(add_uevent_var);
@@ -290,9 +290,8 @@ EXPORT_SYMBOL_GPL(add_uevent_var);
#if defined(CONFIG_NET)
static int __init kobject_uevent_init(void)
{
- uevent_sock = netlink_kernel_create(NETLINK_KOBJECT_UEVENT, 1, NULL,
- NULL, THIS_MODULE);
-
+ uevent_sock = netlink_kernel_create(&init_net, NETLINK_KOBJECT_UEVENT,
+ 1, NULL, NULL, THIS_MODULE);
if (!uevent_sock) {
printk(KERN_ERR
"kobject_uevent: unable to create netlink socket!\n");
@@ -304,5 +303,3 @@ static int __init kobject_uevent_init(void)
postcore_initcall(kobject_uevent_init);
#endif
-
-#endif /* CONFIG_HOTPLUG */
diff --git a/lib/lzo/lzo1x_compress.c b/lib/lzo/lzo1x_compress.c
index c935f00073e9..a6040990a62e 100644
--- a/lib/lzo/lzo1x_compress.c
+++ b/lib/lzo/lzo1x_compress.c
@@ -32,13 +32,13 @@ _lzo1x_1_do_compress(const unsigned char *in, size_t in_len,
ip += 4;
for (;;) {
- dindex = ((0x21 * DX3(ip, 5, 5, 6)) >> 5) & D_MASK;
+ dindex = ((size_t)(0x21 * DX3(ip, 5, 5, 6)) >> 5) & D_MASK;
m_pos = dict[dindex];
if (m_pos < in)
goto literal;
- if (ip == m_pos || (ip - m_pos) > M4_MAX_OFFSET)
+ if (ip == m_pos || ((size_t)(ip - m_pos) > M4_MAX_OFFSET))
goto literal;
m_off = ip - m_pos;
@@ -51,7 +51,7 @@ _lzo1x_1_do_compress(const unsigned char *in, size_t in_len,
if (m_pos < in)
goto literal;
- if (ip == m_pos || (ip - m_pos) > M4_MAX_OFFSET)
+ if (ip == m_pos || ((size_t)(ip - m_pos) > M4_MAX_OFFSET))
goto literal;
m_off = ip - m_pos;
diff --git a/lib/radix-tree.c b/lib/radix-tree.c
index 9927cca14cb7..514efb200be6 100644
--- a/lib/radix-tree.c
+++ b/lib/radix-tree.c
@@ -1021,7 +1021,7 @@ void __init radix_tree_init(void)
{
radix_tree_node_cachep = kmem_cache_create("radix_tree_node",
sizeof(struct radix_tree_node), 0,
- SLAB_PANIC, radix_tree_node_ctor, NULL);
+ SLAB_PANIC, radix_tree_node_ctor);
radix_tree_init_maxindex();
hotcpu_notifier(radix_tree_callback, 0);
}
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 10c13ad0d82d..30c1400e749e 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -357,7 +357,8 @@ map_single(struct device *hwdev, char *buffer, size_t size, int dir)
* This is needed when we sync the memory. Then we sync the buffer if
* needed.
*/
- io_tlb_orig_addr[index] = buffer;
+ for (i = 0; i < nslots; i++)
+ io_tlb_orig_addr[index+i] = buffer + (i << IO_TLB_SHIFT);
if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL)
memcpy(dma_addr, buffer, size);
@@ -418,6 +419,8 @@ sync_single(struct device *hwdev, char *dma_addr, size_t size,
int index = (dma_addr - io_tlb_start) >> IO_TLB_SHIFT;
char *buffer = io_tlb_orig_addr[index];
+ buffer += ((unsigned long)dma_addr & ((1 << IO_TLB_SHIFT) - 1));
+
switch (target) {
case SYNC_FOR_CPU:
if (likely(dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL))
@@ -494,6 +497,7 @@ void
swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr,
dma_addr_t dma_handle)
{
+ WARN_ON(irqs_disabled());
if (!(vaddr >= (void *)io_tlb_start
&& vaddr < (void *)io_tlb_end))
free_pages((unsigned long) vaddr, get_order(size));
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 6b6734df6d2d..7b481cea54ae 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -978,38 +978,3 @@ int sscanf(const char * buf, const char * fmt, ...)
}
EXPORT_SYMBOL(sscanf);
-
-
-/* Simplified asprintf. */
-char *kvasprintf(gfp_t gfp, const char *fmt, va_list ap)
-{
- unsigned int len;
- char *p;
- va_list aq;
-
- va_copy(aq, ap);
- len = vsnprintf(NULL, 0, fmt, aq);
- va_end(aq);
-
- p = kmalloc(len+1, gfp);
- if (!p)
- return NULL;
-
- vsnprintf(p, len+1, fmt, ap);
-
- return p;
-}
-EXPORT_SYMBOL(kvasprintf);
-
-char *kasprintf(gfp_t gfp, const char *fmt, ...)
-{
- va_list ap;
- char *p;
-
- va_start(ap, fmt);
- p = kvasprintf(gfp, fmt, ap);
- va_end(ap);
-
- return p;
-}
-EXPORT_SYMBOL(kasprintf);
diff --git a/lib/zlib_inflate/Makefile b/lib/zlib_inflate/Makefile
index bf065482fa67..49f8ce5774d2 100644
--- a/lib/zlib_inflate/Makefile
+++ b/lib/zlib_inflate/Makefile
@@ -15,5 +15,5 @@
obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate.o
-zlib_inflate-objs := inffast.o inflate.o \
+zlib_inflate-objs := inffast.o inflate.o infutil.o \
inftrees.o inflate_syms.o
diff --git a/lib/zlib_inflate/inffast.c b/lib/zlib_inflate/inffast.c
index d84560c076d8..8550b0c05d00 100644
--- a/lib/zlib_inflate/inffast.c
+++ b/lib/zlib_inflate/inffast.c
@@ -69,22 +69,22 @@
void inflate_fast(z_streamp strm, unsigned start)
{
struct inflate_state *state;
- unsigned char *in; /* local strm->next_in */
- unsigned char *last; /* while in < last, enough input available */
- unsigned char *out; /* local strm->next_out */
- unsigned char *beg; /* inflate()'s initial strm->next_out */
- unsigned char *end; /* while out < end, enough space available */
+ const unsigned char *in; /* local strm->next_in */
+ const unsigned char *last; /* while in < last, enough input available */
+ unsigned char *out; /* local strm->next_out */
+ unsigned char *beg; /* inflate()'s initial strm->next_out */
+ unsigned char *end; /* while out < end, enough space available */
#ifdef INFLATE_STRICT
unsigned dmax; /* maximum distance from zlib header */
#endif
unsigned wsize; /* window size or zero if not using window */
unsigned whave; /* valid bytes in the window */
unsigned write; /* window write index */
- unsigned char *window; /* allocated sliding window, if wsize != 0 */
+ unsigned char *window; /* allocated sliding window, if wsize != 0 */
unsigned long hold; /* local strm->hold */
unsigned bits; /* local strm->bits */
- code const *lcode; /* local strm->lencode */
- code const *dcode; /* local strm->distcode */
+ code const *lcode; /* local strm->lencode */
+ code const *dcode; /* local strm->distcode */
unsigned lmask; /* mask for first level of length codes */
unsigned dmask; /* mask for first level of distance codes */
code this; /* retrieved table entry */
@@ -92,7 +92,7 @@ void inflate_fast(z_streamp strm, unsigned start)
/* window position, window bytes to copy */
unsigned len; /* match length, unused bytes */
unsigned dist; /* match distance */
- unsigned char *from; /* where to copy match from */
+ unsigned char *from; /* where to copy match from */
/* copy state to local variables */
state = (struct inflate_state *)strm->state;
diff --git a/lib/zlib_inflate/inflate.c b/lib/zlib_inflate/inflate.c
index 7e1e3114a73e..f5ce87b0800e 100644
--- a/lib/zlib_inflate/inflate.c
+++ b/lib/zlib_inflate/inflate.c
@@ -332,14 +332,14 @@ static int zlib_inflateSyncPacket(z_streamp strm)
int zlib_inflate(z_streamp strm, int flush)
{
struct inflate_state *state;
- unsigned char *next; /* next input */
- unsigned char *put; /* next output */
+ const unsigned char *next; /* next input */
+ unsigned char *put; /* next output */
unsigned have, left; /* available input and output */
unsigned long hold; /* bit buffer */
unsigned bits; /* bits in bit buffer */
unsigned in, out; /* save starting available input and output */
unsigned copy; /* number of stored or match bytes to copy */
- unsigned char *from; /* where to copy match bytes from */
+ unsigned char *from; /* where to copy match bytes from */
code this; /* current decoding table entry */
code last; /* parent table entry */
unsigned len; /* length to copy for repeats, bits to drop */
@@ -897,7 +897,7 @@ int zlib_inflateIncomp(z_stream *z)
/* Setup some variables to allow misuse of updateWindow */
z->avail_out = 0;
- z->next_out = z->next_in + z->avail_in;
+ z->next_out = (unsigned char*)z->next_in + z->avail_in;
zlib_updatewindow(z, z->avail_in);
diff --git a/lib/zlib_inflate/inflate_syms.c b/lib/zlib_inflate/inflate_syms.c
index 2061d4f06765..67329fe9907e 100644
--- a/lib/zlib_inflate/inflate_syms.c
+++ b/lib/zlib_inflate/inflate_syms.c
@@ -16,4 +16,5 @@ EXPORT_SYMBOL(zlib_inflateInit2);
EXPORT_SYMBOL(zlib_inflateEnd);
EXPORT_SYMBOL(zlib_inflateReset);
EXPORT_SYMBOL(zlib_inflateIncomp);
+EXPORT_SYMBOL(zlib_inflate_blob);
MODULE_LICENSE("GPL");
diff --git a/lib/zlib_inflate/infutil.c b/lib/zlib_inflate/infutil.c
new file mode 100644
index 000000000000..4824c2cc7a09
--- /dev/null
+++ b/lib/zlib_inflate/infutil.c
@@ -0,0 +1,49 @@
+#include <linux/zutil.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+
+/* Utility function: initialize zlib, unpack binary blob, clean up zlib,
+ * return len or negative error code.
+ */
+int zlib_inflate_blob(void *gunzip_buf, unsigned int sz,
+ const void *buf, unsigned int len)
+{
+ const u8 *zbuf = buf;
+ struct z_stream_s *strm;
+ int rc;
+
+ rc = -ENOMEM;
+ strm = kmalloc(sizeof(*strm), GFP_KERNEL);
+ if (strm == NULL)
+ goto gunzip_nomem1;
+ strm->workspace = kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL);
+ if (strm->workspace == NULL)
+ goto gunzip_nomem2;
+
+ /* gzip header (1f,8b,08... 10 bytes total + possible asciz filename)
+ * expected to be stripped from input
+ */
+ strm->next_in = zbuf;
+ strm->avail_in = len;
+ strm->next_out = gunzip_buf;
+ strm->avail_out = sz;
+
+ rc = zlib_inflateInit2(strm, -MAX_WBITS);
+ if (rc == Z_OK) {
+ rc = zlib_inflate(strm, Z_FINISH);
+ /* after Z_FINISH, only Z_STREAM_END is "we unpacked it all" */
+ if (rc == Z_STREAM_END)
+ rc = sz - strm->avail_out;
+ else
+ rc = -EINVAL;
+ zlib_inflateEnd(strm);
+ } else
+ rc = -EINVAL;
+
+ kfree(strm->workspace);
+gunzip_nomem2:
+ kfree(strm);
+gunzip_nomem1:
+ return rc; /* returns Z_OK (0) if successful */
+}