summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Kconfig.debug2
-rw-r--r--lib/Makefile5
-rw-r--r--lib/devres.c26
-rw-r--r--lib/div64.c22
-rw-r--r--lib/iomap.c27
-rw-r--r--lib/kobject.c129
-rw-r--r--lib/kobject_uevent.c28
-rw-r--r--lib/kref.c2
-rw-r--r--lib/parser.c10
-rw-r--r--lib/string.c28
-rw-r--r--lib/vsprintf.c26
11 files changed, 198 insertions, 107 deletions
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 3f3e7403dca..79afd00bbe5 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -261,7 +261,7 @@ config LOCKDEP
bool
depends on DEBUG_KERNEL && TRACE_IRQFLAGS_SUPPORT && STACKTRACE_SUPPORT && LOCKDEP_SUPPORT
select STACKTRACE
- select FRAME_POINTER if !X86
+ select FRAME_POINTER if !X86 && !MIPS
select KALLSYMS
select KALLSYMS_ALL
diff --git a/lib/Makefile b/lib/Makefile
index 992a39ef9ff..ae57f357fec 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -4,7 +4,7 @@
lib-y := ctype.o string.o vsprintf.o cmdline.o \
rbtree.o radix-tree.o dump_stack.o \
- idr.o div64.o int_sqrt.o bitmap.o extable.o prio_tree.o \
+ idr.o int_sqrt.o bitmap.o extable.o prio_tree.o \
sha1.o irq_regs.o reciprocal_div.o
lib-$(CONFIG_MMU) += ioremap.o
@@ -12,7 +12,8 @@ lib-$(CONFIG_SMP) += cpumask.o
lib-y += kobject.o kref.o kobject_uevent.o klist.o
-obj-y += sort.o parser.o halfmd4.o debug_locks.o random32.o bust_spinlocks.o
+obj-y += div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \
+ bust_spinlocks.o
ifeq ($(CONFIG_DEBUG_KOBJECT),y)
CFLAGS_kobject.o += -DDEBUG
diff --git a/lib/devres.c b/lib/devres.c
index eb38849aa71..b1d336ce7f3 100644
--- a/lib/devres.c
+++ b/lib/devres.c
@@ -296,5 +296,31 @@ int pcim_iomap_regions(struct pci_dev *pdev, u16 mask, const char *name)
return rc;
}
EXPORT_SYMBOL(pcim_iomap_regions);
+
+/**
+ * pcim_iounmap_regions - Unmap and release PCI BARs
+ * @pdev: PCI device to map IO resources for
+ * @mask: Mask of BARs to unmap and release
+ *
+ * Unamp and release regions specified by @mask.
+ */
+void pcim_iounmap_regions(struct pci_dev *pdev, u16 mask)
+{
+ void __iomem * const *iomap;
+ int i;
+
+ iomap = pcim_iomap_table(pdev);
+ if (!iomap)
+ return;
+
+ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+ if (!(mask & (1 << i)))
+ continue;
+
+ pcim_iounmap(pdev, iomap[i]);
+ pci_release_region(pdev, i);
+ }
+}
+EXPORT_SYMBOL(pcim_iounmap_regions);
#endif
#endif
diff --git a/lib/div64.c b/lib/div64.c
index 365719f8483..b71cf93c529 100644
--- a/lib/div64.c
+++ b/lib/div64.c
@@ -23,7 +23,7 @@
/* Not needed on 64bit architectures */
#if BITS_PER_LONG == 32
-uint32_t __div64_32(uint64_t *n, uint32_t base)
+uint32_t __attribute__((weak)) __div64_32(uint64_t *n, uint32_t base)
{
uint64_t rem = *n;
uint64_t b = base;
@@ -58,4 +58,24 @@ uint32_t __div64_32(uint64_t *n, uint32_t base)
EXPORT_SYMBOL(__div64_32);
+/* 64bit divisor, dividend and result. dynamic precision */
+uint64_t div64_64(uint64_t dividend, uint64_t divisor)
+{
+ uint32_t high, d;
+
+ high = divisor >> 32;
+ if (high) {
+ unsigned int shift = fls(high);
+
+ d = divisor >> shift;
+ dividend >>= shift;
+ } else
+ d = divisor;
+
+ do_div(dividend, d);
+
+ return dividend;
+}
+EXPORT_SYMBOL(div64_64);
+
#endif /* BITS_PER_LONG == 32 */
diff --git a/lib/iomap.c b/lib/iomap.c
index 4d43f37c015..a57d262a5ed 100644
--- a/lib/iomap.c
+++ b/lib/iomap.c
@@ -35,20 +35,28 @@
#define PIO_RESERVED 0x40000UL
#endif
+static void bad_io_access(unsigned long port, const char *access)
+{
+ static int count = 10;
+ if (count) {
+ count--;
+ printk(KERN_ERR "Bad IO access at port %lx (%s)\n", port, access);
+ WARN_ON(1);
+ }
+}
+
/*
* Ugly macros are a way of life.
*/
-#define VERIFY_PIO(port) BUG_ON((port & ~PIO_MASK) != PIO_OFFSET)
-
#define IO_COND(addr, is_pio, is_mmio) do { \
unsigned long port = (unsigned long __force)addr; \
- if (port < PIO_RESERVED) { \
- VERIFY_PIO(port); \
+ if (port >= PIO_RESERVED) { \
+ is_mmio; \
+ } else if (port > PIO_OFFSET) { \
port &= PIO_MASK; \
is_pio; \
- } else { \
- is_mmio; \
- } \
+ } else \
+ bad_io_access(port, #is_pio ); \
} while (0)
#ifndef pio_read16be
@@ -64,22 +72,27 @@
unsigned int fastcall ioread8(void __iomem *addr)
{
IO_COND(addr, return inb(port), return readb(addr));
+ return 0xff;
}
unsigned int fastcall ioread16(void __iomem *addr)
{
IO_COND(addr, return inw(port), return readw(addr));
+ return 0xffff;
}
unsigned int fastcall ioread16be(void __iomem *addr)
{
IO_COND(addr, return pio_read16be(port), return mmio_read16be(addr));
+ return 0xffff;
}
unsigned int fastcall ioread32(void __iomem *addr)
{
IO_COND(addr, return inl(port), return readl(addr));
+ return 0xffffffff;
}
unsigned int fastcall ioread32be(void __iomem *addr)
{
IO_COND(addr, return pio_read32be(port), return mmio_read32be(addr));
+ return 0xffffffff;
}
EXPORT_SYMBOL(ioread8);
EXPORT_SYMBOL(ioread16);
diff --git a/lib/kobject.c b/lib/kobject.c
index 057921c5945..fc5f3f6e732 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -157,7 +157,7 @@ static void unlink(struct kobject * kobj)
}
/**
- * kobject_add - add an object to the hierarchy.
+ * kobject_shadow_add - add an object to the hierarchy.
* @kobj: object.
* @shadow_parent: sysfs directory to add to.
*/
@@ -174,6 +174,7 @@ int kobject_shadow_add(struct kobject * kobj, struct dentry *shadow_parent)
if (!*kobj->k_name) {
pr_debug("kobject attempted to be registered with no name!\n");
WARN_ON(1);
+ kobject_put(kobj);
return -EINVAL;
}
parent = kobject_get(kobj->parent);
@@ -190,8 +191,8 @@ int kobject_shadow_add(struct kobject * kobj, struct dentry *shadow_parent)
list_add_tail(&kobj->entry,&kobj->kset->list);
spin_unlock(&kobj->kset->list_lock);
+ kobj->parent = parent;
}
- kobj->parent = parent;
error = create_dir(kobj, shadow_parent);
if (error) {
@@ -311,13 +312,43 @@ EXPORT_SYMBOL(kobject_set_name);
int kobject_rename(struct kobject * kobj, const char *new_name)
{
int error = 0;
+ const char *devpath = NULL;
+ char *devpath_string = NULL;
+ char *envp[2];
kobj = kobject_get(kobj);
if (!kobj)
return -EINVAL;
if (!kobj->parent)
return -EINVAL;
+
+ devpath = kobject_get_path(kobj, GFP_KERNEL);
+ if (!devpath) {
+ error = -ENOMEM;
+ goto out;
+ }
+ devpath_string = kmalloc(strlen(devpath) + 15, GFP_KERNEL);
+ if (!devpath_string) {
+ error = -ENOMEM;
+ goto out;
+ }
+ sprintf(devpath_string, "DEVPATH_OLD=%s", devpath);
+ envp[0] = devpath_string;
+ envp[1] = NULL;
+ /* 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->dentry, new_name);
+
+ /* This function is mostly/only used for network interface.
+ * Some hotplug package track interfaces by their name and
+ * therefore want to know when the name is changed by the user. */
+ if (!error)
+ kobject_uevent_env(kobj, KOBJ_MOVE, envp);
+
+out:
+ kfree(devpath_string);
+ kfree(devpath);
kobject_put(kobj);
return error;
@@ -488,13 +519,15 @@ static struct kobj_type dir_ktype = {
};
/**
- * kobject_add_dir - add sub directory of object.
+ * kobject_kset_add_dir - add sub directory of object.
+ * @kset: kset the directory is belongs to.
* @parent: object in which a directory is created.
* @name: directory name.
*
* Add a plain directory object as child of given object.
*/
-struct kobject *kobject_add_dir(struct kobject *parent, const char *name)
+struct kobject *kobject_kset_add_dir(struct kset *kset,
+ struct kobject *parent, const char *name)
{
struct kobject *k;
int ret;
@@ -506,13 +539,14 @@ struct kobject *kobject_add_dir(struct kobject *parent, const char *name)
if (!k)
return NULL;
+ k->kset = kset;
k->parent = parent;
k->ktype = &dir_ktype;
kobject_set_name(k, name);
ret = kobject_register(k);
if (ret < 0) {
- printk(KERN_WARNING "kobject_add_dir: "
- "kobject_register error: %d\n", ret);
+ printk(KERN_WARNING "%s: kobject_register error: %d\n",
+ __func__, ret);
kobject_del(k);
return NULL;
}
@@ -521,6 +555,18 @@ struct kobject *kobject_add_dir(struct kobject *parent, const char *name)
}
/**
+ * kobject_add_dir - add sub directory of object.
+ * @parent: object in which a directory is created.
+ * @name: directory name.
+ *
+ * Add a plain directory object as child of given object.
+ */
+struct kobject *kobject_add_dir(struct kobject *parent, const char *name)
+{
+ return kobject_kset_add_dir(NULL, parent, name);
+}
+
+/**
* kset_init - initialize a kset for use
* @k: kset
*/
@@ -536,22 +582,10 @@ void kset_init(struct kset * k)
/**
* kset_add - add a kset object to the hierarchy.
* @k: kset.
- *
- * Simply, this adds the kset's embedded kobject to the
- * hierarchy.
- * We also try to make sure that the kset's embedded kobject
- * has a parent before it is added. We only care if the embedded
- * kobject is not part of a kset itself, since kobject_add()
- * assigns a parent in that case.
- * If that is the case, and the kset has a controlling subsystem,
- * then we set the kset's parent to be said subsystem.
*/
int kset_add(struct kset * k)
{
- if (!k->kobj.parent && !k->kobj.kset && k->subsys)
- k->kobj.parent = &k->subsys->kset.kobj;
-
return kobject_add(&k->kobj);
}
@@ -610,55 +644,28 @@ struct kobject * kset_find_obj(struct kset * kset, const char * name)
return ret;
}
-
-void subsystem_init(struct subsystem * s)
+void subsystem_init(struct kset *s)
{
- init_rwsem(&s->rwsem);
- kset_init(&s->kset);
+ kset_init(s);
}
-/**
- * subsystem_register - register a subsystem.
- * @s: the subsystem we're registering.
- *
- * Once we register the subsystem, we want to make sure that
- * the kset points back to this subsystem for correct usage of
- * the rwsem.
- */
-
-int subsystem_register(struct subsystem * s)
+int subsystem_register(struct kset *s)
{
- int error;
-
- if (!s)
- return -EINVAL;
-
- subsystem_init(s);
- pr_debug("subsystem %s: registering\n",s->kset.kobj.name);
-
- if (!(error = kset_add(&s->kset))) {
- if (!s->kset.subsys)
- s->kset.subsys = s;
- }
- return error;
+ return kset_register(s);
}
-void subsystem_unregister(struct subsystem * s)
+void subsystem_unregister(struct kset *s)
{
- if (!s)
- return;
- pr_debug("subsystem %s: unregistering\n",s->kset.kobj.name);
- kset_unregister(&s->kset);
+ kset_unregister(s);
}
-
/**
* subsystem_create_file - export sysfs attribute file.
* @s: subsystem.
* @a: subsystem attribute descriptor.
*/
-int subsys_create_file(struct subsystem * s, struct subsys_attribute * a)
+int subsys_create_file(struct kset *s, struct subsys_attribute *a)
{
int error = 0;
@@ -666,28 +673,12 @@ int subsys_create_file(struct subsystem * s, struct subsys_attribute * a)
return -EINVAL;
if (subsys_get(s)) {
- error = sysfs_create_file(&s->kset.kobj,&a->attr);
+ error = sysfs_create_file(&s->kobj, &a->attr);
subsys_put(s);
}
return error;
}
-
-/**
- * subsystem_remove_file - remove sysfs attribute file.
- * @s: subsystem.
- * @a: attribute desciptor.
- */
-#if 0
-void subsys_remove_file(struct subsystem * s, struct subsys_attribute * a)
-{
- if (subsys_get(s)) {
- sysfs_remove_file(&s->kset.kobj,&a->attr);
- subsys_put(s);
- }
-}
-#endif /* 0 */
-
EXPORT_SYMBOL(kobject_init);
EXPORT_SYMBOL(kobject_register);
EXPORT_SYMBOL(kobject_unregister);
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c
index 84272ed77f0..12e311dc664 100644
--- a/lib/kobject_uevent.c
+++ b/lib/kobject_uevent.c
@@ -42,10 +42,6 @@ static char *action_to_string(enum kobject_action action)
return "remove";
case KOBJ_CHANGE:
return "change";
- case KOBJ_MOUNT:
- return "mount";
- case KOBJ_UMOUNT:
- return "umount";
case KOBJ_OFFLINE:
return "offline";
case KOBJ_ONLINE:
@@ -95,10 +91,8 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
/* search the kset we belong to */
top_kobj = kobj;
- if (!top_kobj->kset && top_kobj->parent) {
- do {
- top_kobj = top_kobj->parent;
- } 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");
@@ -115,6 +109,16 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
return 0;
}
+ /* originating subsystem */
+ if (uevent_ops && uevent_ops->name)
+ subsystem = uevent_ops->name(kset, kobj);
+ else
+ subsystem = kobject_name(&kset->kobj);
+ if (!subsystem) {
+ pr_debug("unset subsytem caused the event to drop!\n");
+ return 0;
+ }
+
/* environment index */
envp = kzalloc(NUM_ENVP * sizeof (char *), GFP_KERNEL);
if (!envp)
@@ -134,12 +138,6 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
goto exit;
}
- /* originating subsystem */
- if (uevent_ops && uevent_ops->name)
- subsystem = uevent_ops->name(kset, kobj);
- else
- subsystem = kobject_name(&kset->kobj);
-
/* event environemnt for helper process only */
envp[i++] = "HOME=/";
envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
@@ -293,7 +291,7 @@ EXPORT_SYMBOL_GPL(add_uevent_var);
static int __init kobject_uevent_init(void)
{
uevent_sock = netlink_kernel_create(NETLINK_KOBJECT_UEVENT, 1, NULL,
- THIS_MODULE);
+ NULL, THIS_MODULE);
if (!uevent_sock) {
printk(KERN_ERR
diff --git a/lib/kref.c b/lib/kref.c
index 0d07cc31c81..a6dc3ec328e 100644
--- a/lib/kref.c
+++ b/lib/kref.c
@@ -21,6 +21,7 @@
void kref_init(struct kref *kref)
{
atomic_set(&kref->refcount,1);
+ smp_mb();
}
/**
@@ -31,6 +32,7 @@ void kref_get(struct kref *kref)
{
WARN_ON(!atomic_read(&kref->refcount));
atomic_inc(&kref->refcount);
+ smp_mb__after_atomic_inc();
}
/**
diff --git a/lib/parser.c b/lib/parser.c
index 7ad2a48abc5..703c8c13b34 100644
--- a/lib/parser.c
+++ b/lib/parser.c
@@ -22,7 +22,7 @@
* match extremely simple token=arg style patterns. If the pattern is found,
* the location(s) of the arguments will be returned in the @args array.
*/
-static int match_one(char *s, char *p, substring_t args[])
+static int match_one(char *s, const char *p, substring_t args[])
{
char *meta;
int argc = 0;
@@ -43,7 +43,7 @@ static int match_one(char *s, char *p, substring_t args[])
p = meta + 1;
if (isdigit(*p))
- len = simple_strtoul(p, &p, 10);
+ len = simple_strtoul(p, (char **) &p, 10);
else if (*p == '%') {
if (*s++ != '%')
return 0;
@@ -102,7 +102,7 @@ static int match_one(char *s, char *p, substring_t args[])
*/
int match_token(char *s, match_table_t table, substring_t args[])
{
- struct match_token *p;
+ const struct match_token *p;
for (p = table; !match_one(s, p->pattern, args) ; p++)
;
@@ -190,7 +190,7 @@ int match_hex(substring_t *s, int *result)
* &substring_t @s to the c-style string @to. Caller guarantees that @to is
* large enough to hold the characters of @s.
*/
-void match_strcpy(char *to, substring_t *s)
+void match_strcpy(char *to, const substring_t *s)
{
memcpy(to, s->from, s->to - s->from);
to[s->to - s->from] = '\0';
@@ -204,7 +204,7 @@ void match_strcpy(char *to, substring_t *s)
* the &substring_t @s. The caller is responsible for freeing the returned
* string with kfree().
*/
-char *match_strdup(substring_t *s)
+char *match_strdup(const substring_t *s)
{
char *p = kmalloc(s->to - s->from + 1, GFP_KERNEL);
if (p)
diff --git a/lib/string.c b/lib/string.c
index bab440fb0df..5efafed3d6b 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -60,6 +60,34 @@ int strnicmp(const char *s1, const char *s2, size_t len)
EXPORT_SYMBOL(strnicmp);
#endif
+#ifndef __HAVE_ARCH_STRCASECMP
+int strcasecmp(const char *s1, const char *s2)
+{
+ int c1, c2;
+
+ do {
+ c1 = tolower(*s1++);
+ c2 = tolower(*s2++);
+ } while (c1 == c2 && c1 != 0);
+ return c1 - c2;
+}
+EXPORT_SYMBOL(strcasecmp);
+#endif
+
+#ifndef __HAVE_ARCH_STRNCASECMP
+int strncasecmp(const char *s1, const char *s2, size_t n)
+{
+ int c1, c2;
+
+ do {
+ c1 = tolower(*s1++);
+ c2 = tolower(*s2++);
+ } while ((--n > 0) && c1 == c2 && c1 != 0);
+ return c1 - c2;
+}
+EXPORT_SYMBOL(strncasecmp);
+#endif
+
#ifndef __HAVE_ARCH_STRCPY
/**
* strcpy - Copy a %NUL terminated string
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index b025864d2e4..cbab1df150c 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -851,23 +851,35 @@ EXPORT_SYMBOL(sscanf);
/* Simplified asprintf. */
-char *kasprintf(gfp_t gfp, const char *fmt, ...)
+char *kvasprintf(gfp_t gfp, const char *fmt, va_list ap)
{
- va_list ap;
unsigned int len;
char *p;
+ va_list aq;
- va_start(ap, fmt);
- len = vsnprintf(NULL, 0, fmt, ap);
- va_end(ap);
+ va_copy(aq, ap);
+ len = vsnprintf(NULL, 0, fmt, aq);
+ va_end(aq);
p = kmalloc(len+1, gfp);
if (!p)
return NULL;
- va_start(ap, fmt);
+
vsnprintf(p, len+1, fmt, ap);
- va_end(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);