summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-03-21 09:25:15 -0800
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-21 09:25:15 -0800
commit08a4ecee986dd98e86090ff5faac4782b6765aed (patch)
tree74df5de49f38c432a6a18303b0c6d834fd09028f
parentba93c6297b9cfad5a70b5e5ed13c9dbead6601d3 (diff)
parentb3229087c5e08589cea4f5040dab56f7dc11332a (diff)
downloadlinux-3.10-08a4ecee986dd98e86090ff5faac4782b6765aed.tar.gz
linux-3.10-08a4ecee986dd98e86090ff5faac4782b6765aed.tar.bz2
linux-3.10-08a4ecee986dd98e86090ff5faac4782b6765aed.zip
Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/driver-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/gregkh/driver-2.6: (23 commits) [PATCH] sysfs: fix a kobject leak in sysfs_add_link on the error path [PATCH] sysfs: don't export dir symbols [PATCH] get_cpu_sysdev() signedness fix [PATCH] kobject_add_dir [PATCH] debugfs: Add debugfs_create_blob() helper for exporting binary data [PATCH] sysfs: fix problem with duplicate sysfs directories and files [PATCH] Kobject: kobject.h: fix a typo [PATCH] Kobject: provide better warning messages when people do stupid things [PATCH] Driver core: add macros notice(), dev_notice() [PATCH] firmware: fix BUG: in fw_realloc_buffer [PATCH] sysfs: kzalloc conversion [PATCH] fix module sysfs files reference counting [PATCH] add EXPORT_SYMBOL_GPL_FUTURE() to USB subsystem [PATCH] add EXPORT_SYMBOL_GPL_FUTURE() to RCU subsystem [PATCH] add EXPORT_SYMBOL_GPL_FUTURE() [PATCH] Clean up module.c symbol searching logic [PATCH] kobj_map semaphore to mutex conversion [PATCH] kref: avoid an atomic operation in kref_put() [PATCH] handle errors returned by platform_get_irq*() [PATCH] driver core: platform_get_irq*(): return -ENXIO on error ...
-rw-r--r--Documentation/feature-removal-schedule.txt18
-rw-r--r--arch/arm/common/locomo.c2
-rw-r--r--arch/arm/common/sa1111.c2
-rw-r--r--arch/m68knommu/kernel/vmlinux.lds.S10
-rw-r--r--arch/v850/kernel/vmlinux.lds.S8
-rw-r--r--block/genhd.c31
-rw-r--r--drivers/base/cpu.c2
-rw-r--r--drivers/base/firmware_class.c6
-rw-r--r--drivers/base/map.c21
-rw-r--r--drivers/base/platform.c4
-rw-r--r--drivers/char/s3c2410-rtc.c4
-rw-r--r--drivers/char/watchdog/mpcore_wdt.c4
-rw-r--r--drivers/i2c/busses/i2c-iop3xx.c9
-rw-r--r--drivers/i2c/busses/i2c-mpc.c5
-rw-r--r--drivers/i2c/busses/i2c-mv64xxx.c4
-rw-r--r--drivers/ide/mips/au1xxx-ide.c5
-rw-r--r--drivers/mmc/pxamci.c2
-rw-r--r--drivers/net/arm/am79c961a.c4
-rw-r--r--drivers/net/fs_enet/mac-fcc.c2
-rw-r--r--drivers/net/fs_enet/mac-fec.c2
-rw-r--r--drivers/net/fs_enet/mac-scc.c2
-rw-r--r--drivers/net/gianfar.c4
-rw-r--r--drivers/net/smc91x.c4
-rw-r--r--drivers/pcmcia/omap_cf.c2
-rw-r--r--drivers/serial/s3c2410.c2
-rw-r--r--drivers/usb/core/driver.c6
-rw-r--r--drivers/usb/host/ohci-omap.c9
-rw-r--r--drivers/video/epson1355fb.c1
-rw-r--r--drivers/video/sa1100fb.c2
-rw-r--r--drivers/video/vfb.c1
-rw-r--r--fs/char_dev.c17
-rw-r--r--fs/debugfs/file.c46
-rw-r--r--fs/sysfs/dir.c37
-rw-r--r--fs/sysfs/file.c9
-rw-r--r--fs/sysfs/inode.c9
-rw-r--r--fs/sysfs/symlink.c6
-rw-r--r--fs/sysfs/sysfs.h1
-rw-r--r--include/asm-generic/vmlinux.lds.h14
-rw-r--r--include/linux/cpu.h2
-rw-r--r--include/linux/debugfs.h15
-rw-r--r--include/linux/device.h2
-rw-r--r--include/linux/kobj_map.h4
-rw-r--r--include/linux/kobject.h4
-rw-r--r--include/linux/module.h10
-rw-r--r--kernel/ksysfs.c3
-rw-r--r--kernel/module.c199
-rw-r--r--kernel/params.c10
-rw-r--r--kernel/rcupdate.c6
-rw-r--r--lib/kobject.c60
-rw-r--r--lib/kobject_uevent.c2
-rw-r--r--lib/kref.c7
-rw-r--r--scripts/genksyms/keywords.c_shipped91
-rw-r--r--scripts/genksyms/keywords.gperf1
53 files changed, 514 insertions, 219 deletions
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 28a31c5e228..afeaf6218ea 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -196,3 +196,21 @@ Why: Board specific code doesn't build anymore since ~2.6.0 and no
users have complained indicating there is no more need for these
boards. This should really be considered a last call.
Who: Ralf Baechle <ralf@linux-mips.org>
+
+---------------------------
+
+What: USB driver API moves to EXPORT_SYMBOL_GPL
+When: Febuary 2008
+Files: include/linux/usb.h, drivers/usb/core/driver.c
+Why: The USB subsystem has changed a lot over time, and it has been
+ possible to create userspace USB drivers using usbfs/libusb/gadgetfs
+ that operate as fast as the USB bus allows. Because of this, the USB
+ subsystem will not be allowing closed source kernel drivers to
+ register with it, after this grace period is over. If anyone needs
+ any help in converting their closed source drivers over to use the
+ userspace filesystems, please contact the
+ linux-usb-devel@lists.sourceforge.net mailing list, and the developers
+ there will be glad to help you out.
+Who: Greg Kroah-Hartman <gregkh@suse.de>
+
+---------------------------
diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c
index d31b1cb7eea..23609400a8e 100644
--- a/arch/arm/common/locomo.c
+++ b/arch/arm/common/locomo.c
@@ -788,6 +788,8 @@ static int locomo_probe(struct platform_device *dev)
if (!mem)
return -EINVAL;
irq = platform_get_irq(dev, 0);
+ if (irq < 0)
+ return -ENXIO;
return __locomo_probe(&dev->dev, mem, irq);
}
diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c
index 1475089f9b4..93352f6097c 100644
--- a/arch/arm/common/sa1111.c
+++ b/arch/arm/common/sa1111.c
@@ -943,6 +943,8 @@ static int sa1111_probe(struct platform_device *pdev)
if (!mem)
return -EINVAL;
irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return -ENXIO;
return __sa1111_probe(&pdev->dev, mem, irq);
}
diff --git a/arch/m68knommu/kernel/vmlinux.lds.S b/arch/m68knommu/kernel/vmlinux.lds.S
index ac9de2661c0..a331cc90797 100644
--- a/arch/m68knommu/kernel/vmlinux.lds.S
+++ b/arch/m68knommu/kernel/vmlinux.lds.S
@@ -269,6 +269,11 @@ SECTIONS {
*(__ksymtab_gpl)
__stop___ksymtab_gpl = .;
+ /* Kernel symbol table: GPL-future symbols */
+ __start___ksymtab_gpl_future = .;
+ *(__ksymtab_gpl_future)
+ __stop___ksymtab_gpl_future = .;
+
/* Kernel symbol table: Normal symbols */
__start___kcrctab = .;
*(__kcrctab)
@@ -279,6 +284,11 @@ SECTIONS {
*(__kcrctab_gpl)
__stop___kcrctab_gpl = .;
+ /* Kernel symbol table: GPL-future symbols */
+ __start___kcrctab_gpl_future = .;
+ *(__kcrctab_gpl_future)
+ __stop___kcrctab_gpl_future = .;
+
/* Kernel symbol table: strings */
*(__ksymtab_strings)
diff --git a/arch/v850/kernel/vmlinux.lds.S b/arch/v850/kernel/vmlinux.lds.S
index 5be05f47109..5b2ffcc6e2b 100644
--- a/arch/v850/kernel/vmlinux.lds.S
+++ b/arch/v850/kernel/vmlinux.lds.S
@@ -64,6 +64,10 @@
___start___ksymtab_gpl = .; \
*(__ksymtab_gpl) \
___stop___ksymtab_gpl = .; \
+ /* Kernel symbol table: GPL-future symbols */ \
+ ___start___ksymtab_gpl_future = .; \
+ *(__ksymtab_gpl_future) \
+ ___stop___ksymtab_gpl_future = .; \
/* Kernel symbol table: strings */ \
*(__ksymtab_strings) \
/* Kernel symbol table: Normal symbols */ \
@@ -74,6 +78,10 @@
___start___kcrctab_gpl = .; \
*(__kcrctab_gpl) \
___stop___kcrctab_gpl = .; \
+ /* Kernel symbol table: GPL-future symbols */ \
+ ___start___kcrctab_gpl_future = .; \
+ *(__kcrctab_gpl_future) \
+ ___stop___kcrctab_gpl_future = .; \
/* Built-in module parameters */ \
. = ALIGN (4) ; \
___start___param = .; \
diff --git a/block/genhd.c b/block/genhd.c
index db57546a709..64510fd8862 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -15,12 +15,13 @@
#include <linux/kmod.h>
#include <linux/kobj_map.h>
#include <linux/buffer_head.h>
+#include <linux/mutex.h>
#define MAX_PROBE_HASH 255 /* random */
static struct subsystem block_subsys;
-static DECLARE_MUTEX(block_subsys_sem);
+static DEFINE_MUTEX(block_subsys_lock);
/*
* Can be deleted altogether. Later.
@@ -46,7 +47,7 @@ struct blkdev_info {
/*
* iterate over a list of blkdev_info structures. allows
* the major_names array to be iterated over from outside this file
- * must be called with the block_subsys_sem held
+ * must be called with the block_subsys_lock held
*/
void *get_next_blkdev(void *dev)
{
@@ -85,20 +86,20 @@ out:
void *acquire_blkdev_list(void)
{
- down(&block_subsys_sem);
+ mutex_lock(&block_subsys_lock);
return get_next_blkdev(NULL);
}
void release_blkdev_list(void *dev)
{
- up(&block_subsys_sem);
+ mutex_unlock(&block_subsys_lock);
kfree(dev);
}
/*
* Count the number of records in the blkdev_list.
- * must be called with the block_subsys_sem held
+ * must be called with the block_subsys_lock held
*/
int count_blkdev_list(void)
{
@@ -118,7 +119,7 @@ int count_blkdev_list(void)
/*
* extract the major and name values from a blkdev_info struct
* passed in as a void to *dev. Must be called with
- * block_subsys_sem held
+ * block_subsys_lock held
*/
int get_blkdev_info(void *dev, int *major, char **name)
{
@@ -138,7 +139,7 @@ int register_blkdev(unsigned int major, const char *name)
struct blk_major_name **n, *p;
int index, ret = 0;
- down(&block_subsys_sem);
+ mutex_lock(&block_subsys_lock);
/* temporary */
if (major == 0) {
@@ -183,7 +184,7 @@ int register_blkdev(unsigned int major, const char *name)
kfree(p);
}
out:
- up(&block_subsys_sem);
+ mutex_unlock(&block_subsys_lock);
return ret;
}
@@ -197,7 +198,7 @@ int unregister_blkdev(unsigned int major, const char *name)
int index = major_to_index(major);
int ret = 0;
- down(&block_subsys_sem);
+ mutex_lock(&block_subsys_lock);
for (n = &major_names[index]; *n; n = &(*n)->next)
if ((*n)->major == major)
break;
@@ -207,7 +208,7 @@ int unregister_blkdev(unsigned int major, const char *name)
p = *n;
*n = p->next;
}
- up(&block_subsys_sem);
+ mutex_unlock(&block_subsys_lock);
kfree(p);
return ret;
@@ -301,7 +302,7 @@ static void *part_start(struct seq_file *part, loff_t *pos)
struct list_head *p;
loff_t l = *pos;
- down(&block_subsys_sem);
+ mutex_lock(&block_subsys_lock);
list_for_each(p, &block_subsys.kset.list)
if (!l--)
return list_entry(p, struct gendisk, kobj.entry);
@@ -318,7 +319,7 @@ static void *part_next(struct seq_file *part, void *v, loff_t *pos)
static void part_stop(struct seq_file *part, void *v)
{
- up(&block_subsys_sem);
+ mutex_unlock(&block_subsys_lock);
}
static int show_partition(struct seq_file *part, void *v)
@@ -377,7 +378,7 @@ static struct kobject *base_probe(dev_t dev, int *part, void *data)
static int __init genhd_device_init(void)
{
- bdev_map = kobj_map_init(base_probe, &block_subsys_sem);
+ bdev_map = kobj_map_init(base_probe, &block_subsys_lock);
blk_dev_init();
subsystem_register(&block_subsys);
return 0;
@@ -611,7 +612,7 @@ static void *diskstats_start(struct seq_file *part, loff_t *pos)
loff_t k = *pos;
struct list_head *p;
- down(&block_subsys_sem);
+ mutex_lock(&block_subsys_lock);
list_for_each(p, &block_subsys.kset.list)
if (!k--)
return list_entry(p, struct gendisk, kobj.entry);
@@ -628,7 +629,7 @@ static void *diskstats_next(struct seq_file *part, void *v, loff_t *pos)
static void diskstats_stop(struct seq_file *part, void *v)
{
- up(&block_subsys_sem);
+ mutex_unlock(&block_subsys_lock);
}
static int diskstats_show(struct seq_file *s, void *v)
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index 07a7f97e1de..29f3d7504da 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -141,7 +141,7 @@ int __devinit register_cpu(struct cpu *cpu, int num, struct node *root)
return error;
}
-struct sys_device *get_cpu_sysdev(int cpu)
+struct sys_device *get_cpu_sysdev(unsigned cpu)
{
if (cpu < NR_CPUS)
return cpu_sys_devices[cpu];
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index e97e911ebf7..47231820523 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -211,18 +211,20 @@ static int
fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size)
{
u8 *new_data;
+ int new_size = fw_priv->alloc_size;
if (min_size <= fw_priv->alloc_size)
return 0;
- new_data = vmalloc(fw_priv->alloc_size + PAGE_SIZE);
+ new_size = ALIGN(min_size, PAGE_SIZE);
+ new_data = vmalloc(new_size);
if (!new_data) {
printk(KERN_ERR "%s: unable to alloc buffer\n", __FUNCTION__);
/* Make sure that we don't keep incomplete data */
fw_load_abort(fw_priv);
return -ENOMEM;
}
- fw_priv->alloc_size += PAGE_SIZE;
+ fw_priv->alloc_size = new_size;
if (fw_priv->fw->data) {
memcpy(new_data, fw_priv->fw->data, fw_priv->fw->size);
vfree(fw_priv->fw->data);
diff --git a/drivers/base/map.c b/drivers/base/map.c
index b449dae6f0d..e87017f3685 100644
--- a/drivers/base/map.c
+++ b/drivers/base/map.c
@@ -11,6 +11,7 @@
#include <linux/module.h>
#include <linux/slab.h>
+#include <linux/mutex.h>
#include <linux/kdev_t.h>
#include <linux/kobject.h>
#include <linux/kobj_map.h>
@@ -25,7 +26,7 @@ struct kobj_map {
int (*lock)(dev_t, void *);
void *data;
} *probes[255];
- struct semaphore *sem;
+ struct mutex *lock;
};
int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range,
@@ -53,7 +54,7 @@ int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range,
p->range = range;
p->data = data;
}
- down(domain->sem);
+ mutex_lock(domain->lock);
for (i = 0, p -= n; i < n; i++, p++, index++) {
struct probe **s = &domain->probes[index % 255];
while (*s && (*s)->range < range)
@@ -61,7 +62,7 @@ int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range,
p->next = *s;
*s = p;
}
- up(domain->sem);
+ mutex_unlock(domain->lock);
return 0;
}
@@ -75,7 +76,7 @@ void kobj_unmap(struct kobj_map *domain, dev_t dev, unsigned long range)
if (n > 255)
n = 255;
- down(domain->sem);
+ mutex_lock(domain->lock);
for (i = 0; i < n; i++, index++) {
struct probe **s;
for (s = &domain->probes[index % 255]; *s; s = &(*s)->next) {
@@ -88,7 +89,7 @@ void kobj_unmap(struct kobj_map *domain, dev_t dev, unsigned long range)
}
}
}
- up(domain->sem);
+ mutex_unlock(domain->lock);
kfree(found);
}
@@ -99,7 +100,7 @@ struct kobject *kobj_lookup(struct kobj_map *domain, dev_t dev, int *index)
unsigned long best = ~0UL;
retry:
- down(domain->sem);
+ mutex_lock(domain->lock);
for (p = domain->probes[MAJOR(dev) % 255]; p; p = p->next) {
struct kobject *(*probe)(dev_t, int *, void *);
struct module *owner;
@@ -120,7 +121,7 @@ retry:
module_put(owner);
continue;
}
- up(domain->sem);
+ mutex_unlock(domain->lock);
kobj = probe(dev, index, data);
/* Currently ->owner protects _only_ ->probe() itself. */
module_put(owner);
@@ -128,11 +129,11 @@ retry:
return kobj;
goto retry;
}
- up(domain->sem);
+ mutex_unlock(domain->lock);
return NULL;
}
-struct kobj_map *kobj_map_init(kobj_probe_t *base_probe, struct semaphore *sem)
+struct kobj_map *kobj_map_init(kobj_probe_t *base_probe, struct mutex *lock)
{
struct kobj_map *p = kmalloc(sizeof(struct kobj_map), GFP_KERNEL);
struct probe *base = kzalloc(sizeof(*base), GFP_KERNEL);
@@ -149,6 +150,6 @@ struct kobj_map *kobj_map_init(kobj_probe_t *base_probe, struct semaphore *sem)
base->get = base_probe;
for (i = 0; i < 255; i++)
p->probes[i] = base;
- p->sem = sem;
+ p->lock = lock;
return p;
}
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 461554a0251..89b26832132 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -61,7 +61,7 @@ int platform_get_irq(struct platform_device *dev, unsigned int num)
{
struct resource *r = platform_get_resource(dev, IORESOURCE_IRQ, num);
- return r ? r->start : 0;
+ return r ? r->start : -ENXIO;
}
EXPORT_SYMBOL_GPL(platform_get_irq);
@@ -98,7 +98,7 @@ int platform_get_irq_byname(struct platform_device *dev, char *name)
{
struct resource *r = platform_get_resource_byname(dev, IORESOURCE_IRQ, name);
- return r ? r->start : 0;
+ return r ? r->start : -ENXIO;
}
EXPORT_SYMBOL_GPL(platform_get_irq_byname);
diff --git a/drivers/char/s3c2410-rtc.c b/drivers/char/s3c2410-rtc.c
index 2e308657f6f..b0038b19b50 100644
--- a/drivers/char/s3c2410-rtc.c
+++ b/drivers/char/s3c2410-rtc.c
@@ -448,13 +448,13 @@ static int s3c2410_rtc_probe(struct platform_device *pdev)
/* find the IRQs */
s3c2410_rtc_tickno = platform_get_irq(pdev, 1);
- if (s3c2410_rtc_tickno <= 0) {
+ if (s3c2410_rtc_tickno < 0) {
dev_err(&pdev->dev, "no irq for rtc tick\n");
return -ENOENT;
}
s3c2410_rtc_alarmno = platform_get_irq(pdev, 0);
- if (s3c2410_rtc_alarmno <= 0) {
+ if (s3c2410_rtc_alarmno < 0) {
dev_err(&pdev->dev, "no irq for alarm\n");
return -ENOENT;
}
diff --git a/drivers/char/watchdog/mpcore_wdt.c b/drivers/char/watchdog/mpcore_wdt.c
index b4d84348988..2c2c5177320 100644
--- a/drivers/char/watchdog/mpcore_wdt.c
+++ b/drivers/char/watchdog/mpcore_wdt.c
@@ -338,6 +338,10 @@ static int __devinit mpcore_wdt_probe(struct platform_device *dev)
wdt->dev = &dev->dev;
wdt->irq = platform_get_irq(dev, 0);
+ if (wdt->irq < 0) {
+ ret = -ENXIO;
+ goto err_free;
+ }
wdt->base = ioremap(res->start, res->end - res->start + 1);
if (!wdt->base) {
ret = -ENOMEM;
diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c
index 1414851a17b..d00a02fc23e 100644
--- a/drivers/i2c/busses/i2c-iop3xx.c
+++ b/drivers/i2c/busses/i2c-iop3xx.c
@@ -434,7 +434,7 @@ static int
iop3xx_i2c_probe(struct platform_device *pdev)
{
struct resource *res;
- int ret;
+ int ret, irq;
struct i2c_adapter *new_adapter;
struct i2c_algo_iop3xx_data *adapter_data;
@@ -470,7 +470,12 @@ iop3xx_i2c_probe(struct platform_device *pdev)
goto release_region;
}
- ret = request_irq(platform_get_irq(pdev, 0), iop3xx_i2c_irq_handler, 0,
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ ret = -ENXIO;
+ goto unmap;
+ }
+ ret = request_irq(irq, iop3xx_i2c_irq_handler, 0,
pdev->name, adapter_data);
if (ret) {
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index 5ccd338a9dc..2721e4c8184 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -302,6 +302,10 @@ static int fsl_i2c_probe(struct platform_device *pdev)
}
i2c->irq = platform_get_irq(pdev, 0);
+ if (i2c->irq < 0) {
+ result = -ENXIO;
+ goto fail_get_irq;
+ }
i2c->flags = pdata->device_flags;
init_waitqueue_head(&i2c->queue);
@@ -340,6 +344,7 @@ static int fsl_i2c_probe(struct platform_device *pdev)
fail_irq:
iounmap(i2c->base);
fail_map:
+ fail_get_irq:
kfree(i2c);
return result;
};
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
index 22781d84f79..ac5cde1bbd2 100644
--- a/drivers/i2c/busses/i2c-mv64xxx.c
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
@@ -516,6 +516,10 @@ mv64xxx_i2c_probe(struct platform_device *pd)
drv_data->freq_m = pdata->freq_m;
drv_data->freq_n = pdata->freq_n;
drv_data->irq = platform_get_irq(pd, 0);
+ if (drv_data->irq < 0) {
+ rc = -ENXIO;
+ goto exit_unmap_regs;
+ }
drv_data->adapter.id = I2C_HW_MV64XXX;
drv_data->adapter.algo = &mv64xxx_i2c_algo;
drv_data->adapter.owner = THIS_MODULE;
diff --git a/drivers/ide/mips/au1xxx-ide.c b/drivers/ide/mips/au1xxx-ide.c
index 32431dcf5d8..71f27e955d8 100644
--- a/drivers/ide/mips/au1xxx-ide.c
+++ b/drivers/ide/mips/au1xxx-ide.c
@@ -674,6 +674,11 @@ static int au_ide_probe(struct device *dev)
ret = -ENODEV;
goto out;
}
+ if (ahwif->irq < 0) {
+ pr_debug("%s %d: no IRQ\n", DRV_NAME, pdev->id);
+ ret = -ENODEV;
+ goto out;
+ }
if (!request_mem_region (res->start, res->end-res->start, pdev->name)) {
pr_debug("%s: request_mem_region failed\n", DRV_NAME);
diff --git a/drivers/mmc/pxamci.c b/drivers/mmc/pxamci.c
index 285d7d06809..c32fad1ce51 100644
--- a/drivers/mmc/pxamci.c
+++ b/drivers/mmc/pxamci.c
@@ -438,7 +438,7 @@ static int pxamci_probe(struct platform_device *pdev)
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
irq = platform_get_irq(pdev, 0);
- if (!r || irq == NO_IRQ)
+ if (!r || irq < 0)
return -ENXIO;
r = request_mem_region(r->start, SZ_4K, DRIVER_NAME);
diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c
index 53e3afc1b7b..09d5c3f2698 100644
--- a/drivers/net/arm/am79c961a.c
+++ b/drivers/net/arm/am79c961a.c
@@ -696,7 +696,9 @@ static int __init am79c961_probe(struct platform_device *pdev)
dev->base_addr = res->start;
dev->irq = platform_get_irq(pdev, 0);
- ret = -ENODEV;
+ ret = -ENODEV;
+ if (dev->irq < 0)
+ goto nodev;
if (!request_region(dev->base_addr, 0x18, dev->name))
goto nodev;
diff --git a/drivers/net/fs_enet/mac-fcc.c b/drivers/net/fs_enet/mac-fcc.c
index e67b1d06611..95e2bb8dd7b 100644
--- a/drivers/net/fs_enet/mac-fcc.c
+++ b/drivers/net/fs_enet/mac-fcc.c
@@ -118,6 +118,8 @@ static int do_pd_setup(struct fs_enet_private *fep)
/* Fill out IRQ field */
fep->interrupt = platform_get_irq(pdev, 0);
+ if (fep->interrupt < 0)
+ return -EINVAL;
/* Attach the memory for the FCC Parameter RAM */
r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fcc_pram");
diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/fs_enet/mac-fec.c
index 2e8f4446969..3dad69dfdb2 100644
--- a/drivers/net/fs_enet/mac-fec.c
+++ b/drivers/net/fs_enet/mac-fec.c
@@ -144,6 +144,8 @@ static int do_pd_setup(struct fs_enet_private *fep)
/* Fill out IRQ field */
fep->interrupt = platform_get_irq_byname(pdev,"interrupt");
+ if (fep->interrupt < 0)
+ return -EINVAL;
r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
fep->fec.fecp =(void*)r->start;
diff --git a/drivers/net/fs_enet/mac-scc.c b/drivers/net/fs_enet/mac-scc.c
index a3897fda71f..a772b286f96 100644
--- a/drivers/net/fs_enet/mac-scc.c
+++ b/drivers/net/fs_enet/mac-scc.c
@@ -118,6 +118,8 @@ static int do_pd_setup(struct fs_enet_private *fep)
/* Fill out IRQ field */
fep->interrupt = platform_get_irq_byname(pdev, "interrupt");
+ if (fep->interrupt < 0)
+ return -EINVAL;
r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
fep->scc.sccp = (void *)r->start;
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 0e8e3fcde9f..771e25d8c41 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -193,8 +193,12 @@ static int gfar_probe(struct platform_device *pdev)
priv->interruptTransmit = platform_get_irq_byname(pdev, "tx");
priv->interruptReceive = platform_get_irq_byname(pdev, "rx");
priv->interruptError = platform_get_irq_byname(pdev, "error");
+ if (priv->interruptTransmit < 0 || priv->interruptReceive < 0 || priv->interruptError < 0)
+ goto regs_fail;
} else {
priv->interruptTransmit = platform_get_irq(pdev, 0);
+ if (priv->interruptTransmit < 0)
+ goto regs_fail;
}
/* get a pointer to the register memory */
diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c
index 7ec08127c9d..75e9b3b910c 100644
--- a/drivers/net/smc91x.c
+++ b/drivers/net/smc91x.c
@@ -2221,6 +2221,10 @@ static int smc_drv_probe(struct platform_device *pdev)
ndev->dma = (unsigned char)-1;
ndev->irq = platform_get_irq(pdev, 0);
+ if (ndev->irq < 0) {
+ ret = -ENODEV;
+ goto out_free_netdev;
+ }
ret = smc_request_attrib(pdev);
if (ret)
diff --git a/drivers/pcmcia/omap_cf.c b/drivers/pcmcia/omap_cf.c
index 47b5ade95bd..2c23d758439 100644
--- a/drivers/pcmcia/omap_cf.c
+++ b/drivers/pcmcia/omap_cf.c
@@ -218,7 +218,7 @@ static int __init omap_cf_probe(struct device *dev)
/* either CFLASH.IREQ (INT_1610_CF) or some GPIO */
irq = platform_get_irq(pdev, 0);
- if (!irq)
+ if (irq < 0)
return -EINVAL;
cf = kcalloc(1, sizeof *cf, GFP_KERNEL);
diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c
index 7410e093a6b..00d7c0ad8cb 100644
--- a/drivers/serial/s3c2410.c
+++ b/drivers/serial/s3c2410.c
@@ -1066,6 +1066,8 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
port->mapbase = res->start;
port->membase = S3C24XX_VA_UART + (res->start - S3C24XX_PA_UART);
port->irq = platform_get_irq(platdev, 0);
+ if (port->irq < 0)
+ port->irq = 0;
ourport->clk = clk_get(&platdev->dev, "uart");
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index dce9d987f0f..c196f384530 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -378,7 +378,7 @@ const struct usb_device_id *usb_match_id(struct usb_interface *interface,
return NULL;
}
-EXPORT_SYMBOL(usb_match_id);
+EXPORT_SYMBOL_GPL_FUTURE(usb_match_id);
int usb_device_match(struct device *dev, struct device_driver *drv)
{
@@ -446,7 +446,7 @@ int usb_register_driver(struct usb_driver *new_driver, struct module *owner)
return retval;
}
-EXPORT_SYMBOL(usb_register_driver);
+EXPORT_SYMBOL_GPL_FUTURE(usb_register_driver);
/**
* usb_deregister - unregister a USB driver
@@ -469,4 +469,4 @@ void usb_deregister(struct usb_driver *driver)
usbfs_update_special();
}
-EXPORT_SYMBOL(usb_deregister);
+EXPORT_SYMBOL_GPL_FUTURE(usb_deregister);
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
index 3785b3f7df1..ca19abe01c5 100644
--- a/drivers/usb/host/ohci-omap.c
+++ b/drivers/usb/host/ohci-omap.c
@@ -286,7 +286,7 @@ void usb_hcd_omap_remove (struct usb_hcd *, struct platform_device *);
int usb_hcd_omap_probe (const struct hc_driver *driver,
struct platform_device *pdev)
{
- int retval;
+ int retval, irq;
struct usb_hcd *hcd = 0;
struct ohci_hcd *ohci;
@@ -329,7 +329,12 @@ int usb_hcd_omap_probe (const struct hc_driver *driver,
if (retval < 0)
goto err2;
- retval = usb_add_hcd(hcd, platform_get_irq(pdev, 0), SA_INTERRUPT);
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ retval = -ENXIO;
+ goto err2;
+ }
+ retval = usb_add_hcd(hcd, irq, SA_INTERRUPT);
if (retval == 0)
return retval;
diff --git a/drivers/video/epson1355fb.c b/drivers/video/epson1355fb.c
index 3b0e7138344..082759447bf 100644
--- a/drivers/video/epson1355fb.c
+++ b/drivers/video/epson1355fb.c
@@ -607,6 +607,7 @@ static void clearfb16(struct fb_info *info)
static void epson1355fb_platform_release(struct device *device)
{
+ dev_err(device, "This driver is broken, please bug the authors so they will fix it.\n");
}
static int epson1355fb_remove(struct platform_device *dev)
diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c
index 8a893ce7040..d9831fd4234 100644
--- a/drivers/video/sa1100fb.c
+++ b/drivers/video/sa1100fb.c
@@ -1457,7 +1457,7 @@ static int __init sa1100fb_probe(struct platform_device *pdev)
int ret, irq;
irq = platform_get_irq(pdev, 0);
- if (irq <= 0)
+ if (irq < 0)
return -EINVAL;
if (!request_mem_region(0xb0100000, 0x10000, "LCD"))
diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c
index 53208cb5839..77eed1fd994 100644
--- a/drivers/video/vfb.c
+++ b/drivers/video/vfb.c
@@ -401,6 +401,7 @@ static int __init vfb_setup(char *options)
static void vfb_platform_release(struct device *device)
{
// This is called when the reference count goes to zero.
+ dev_err(device, "This driver is broken, please bug the authors so they will fix it.\n");
}
static int __init vfb_probe(struct platform_device *dev)
diff --git a/fs/char_dev.c b/fs/char_dev.c
index 21195c48163..5c36345c9bf 100644
--- a/fs/char_dev.c
+++ b/fs/char_dev.c
@@ -19,6 +19,7 @@
#include <linux/kobject.h>
#include <linux/kobj_map.h>
#include <linux/cdev.h>
+#include <linux/mutex.h>
#ifdef CONFIG_KMOD
#include <linux/kmod.h>
@@ -28,7 +29,7 @@ static struct kobj_map *cdev_map;
#define MAX_PROBE_HASH 255 /* random */
-static DECLARE_MUTEX(chrdevs_lock);
+static DEFINE_MUTEX(chrdevs_lock);
static struct char_device_struct {
struct char_device_struct *next;
@@ -88,13 +89,13 @@ out:
void *acquire_chrdev_list(void)
{
- down(&chrdevs_lock);
+ mutex_lock(&chrdevs_lock);
return get_next_chrdev(NULL);
}
void release_chrdev_list(void *dev)
{
- up(&chrdevs_lock);
+ mutex_unlock(&chrdevs_lock);
kfree(dev);
}
@@ -151,7 +152,7 @@ __register_chrdev_region(unsigned int major, unsigned int baseminor,
memset(cd, 0, sizeof(struct char_device_struct));
- down(&chrdevs_lock);
+ mutex_lock(&chrdevs_lock);
/* temporary */
if (major == 0) {
@@ -186,10 +187,10 @@ __register_chrdev_region(unsigned int major, unsigned int baseminor,
}
cd->next = *cp;
*cp = cd;
- up(&chrdevs_lock);
+ mutex_unlock(&chrdevs_lock);
return cd;
out:
- up(&chrdevs_lock);
+ mutex_unlock(&chrdevs_lock);
kfree(cd);
return ERR_PTR(ret);
}
@@ -200,7 +201,7 @@ __unregister_chrdev_region(unsigned major, unsigned baseminor, int minorct)
struct char_device_struct *cd = NULL, **cp;
int i = major_to_index(major);
- down(&chrdevs_lock);
+ mutex_lock(&chrdevs_lock);
for (cp = &chrdevs[i]; *cp; cp = &(*cp)->next)
if ((*cp)->major == major &&
(*cp)->baseminor == baseminor &&
@@ -210,7 +211,7 @@ __unregister_chrdev_region(unsigned major, unsigned baseminor, int minorct)
cd = *cp;
*cp = cd->next;
}
- up(&chrdevs_lock);
+ mutex_unlock(&chrdevs_lock);
return cd;
}
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index d575452cd9f..40c4fc973fa 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -251,3 +251,49 @@ struct dentry *debugfs_create_bool(const char *name, mode_t mode,
}
EXPORT_SYMBOL_GPL(debugfs_create_bool);
+static ssize_t read_file_blob(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct debugfs_blob_wrapper *blob = file->private_data;
+ return simple_read_from_buffer(user_buf, count, ppos, blob->data,
+ blob->size);
+}
+
+static struct file_operations fops_blob = {
+ .read = read_file_blob,
+ .open = default_open,
+};
+
+/**
+ * debugfs_create_blob - create a file in the debugfs filesystem that is
+ * used to read and write a binary blob.
+ *
+ * @name: a pointer to a string containing the name of the file to create.
+ * @mode: the permission that the file should have
+ * @parent: a pointer to the parent dentry for this file. This should be a
+ * directory dentry if set. If this paramater is NULL, then the
+ * file will be created in the root of the debugfs filesystem.
+ * @blob: a pointer to a struct debugfs_blob_wrapper which contains a pointer
+ * to the blob data and the size of the data.
+ *
+ * This function creates a file in debugfs with the given name that exports
+ * @blob->data as a binary blob. If the @mode variable is so set it can be
+ * read from. Writing is not supported.
+ *
+ * This function will return a pointer to a dentry if it succeeds. This
+ * pointer must be passed to the debugfs_remove() function when the file is
+ * to be removed (no automatic cleanup happens if your module is unloaded,
+ * you are responsible here.) If an error occurs, NULL will be returned.
+ *
+ * If debugfs is not enabled in the kernel, the value -ENODEV will be
+ * returned. It is not wise to check for this value, but rather, check for
+ * NULL or !NULL instead as to eliminate the need for #ifdef in the calling
+ * code.
+ */
+struct dentry *debugfs_create_blob(const char *name, mode_t mode,
+ struct dentry *parent,
+ struct debugfs_blob_wrapper *blob)
+{
+ return debugfs_create_file(name, mode, parent, blob, &fops_blob);
+}
+EXPORT_SYMBOL_GPL(debugfs_create_blob);
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 49bd219275d..9ee95686444 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -50,6 +50,32 @@ static struct sysfs_dirent * sysfs_new_dirent(struct sysfs_dirent * parent_sd,
return sd;
}
+/**
+ *
+ * Return -EEXIST if there is already a sysfs element with the same name for
+ * the same parent.
+ *
+ * called with parent inode's i_mutex held
+ */
+int sysfs_dirent_exist(struct sysfs_dirent *parent_sd,
+ const unsigned char *new)
+{
+ struct sysfs_dirent * sd;
+
+ list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
+ if (sd->s_element) {
+ const unsigned char *existing = sysfs_get_name(sd);
+ if (strcmp(existing, new))
+ continue;
+ else
+ return -EEXIST;
+ }
+ }
+
+ return 0;
+}
+
+
int sysfs_make_dirent(struct sysfs_dirent * parent_sd, struct dentry * dentry,
void * element, umode_t mode, int type)
{
@@ -102,7 +128,11 @@ static int create_dir(struct kobject * k, struct dentry * p,
mutex_lock(&p->d_inode->i_mutex);
*d = lookup_one_len(n, p, strlen(n));
if (!IS_ERR(*d)) {
- error = sysfs_make_dirent(p->d_fsdata, *d, k, mode, SYSFS_DIR);
+ if (sysfs_dirent_exist(p->d_fsdata, n))
+ error = -EEXIST;
+ else
+ error = sysfs_make_dirent(p->d_fsdata, *d, k, mode,
+ SYSFS_DIR);
if (!error) {
error = sysfs_create(*d, mode, init_dir);
if (!error) {
@@ -302,6 +332,7 @@ void sysfs_remove_dir(struct kobject * kobj)
* Drop reference from dget() on entrance.
*/
dput(dentry);
+ kobj->dentry = NULL;
}
int sysfs_rename_dir(struct kobject * kobj, const char *new_name)
@@ -479,7 +510,3 @@ struct file_operations sysfs_dir_operations = {
.read = generic_read_dir,
.readdir = sysfs_readdir,
};
-
-EXPORT_SYMBOL_GPL(sysfs_create_dir);
-EXPORT_SYMBOL_GPL(sysfs_remove_dir);
-EXPORT_SYMBOL_GPL(sysfs_rename_dir);
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index d0e3d849516..5e83e724678 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -301,9 +301,8 @@ static int check_perm(struct inode * inode, struct file * file)
/* No error? Great, allocate a buffer for the file, and store it
* it in file->private_data for easy access.
*/
- buffer = kmalloc(sizeof(struct sysfs_buffer),GFP_KERNEL);
+ buffer = kzalloc(sizeof(struct sysfs_buffer), GFP_KERNEL);
if (buffer) {
- memset(buffer,0,sizeof(struct sysfs_buffer));
init_MUTEX(&buffer->sem);
buffer->needs_read_fill = 1;
buffer->ops = ops;
@@ -362,10 +361,12 @@ int sysfs_add_file(struct dentry * dir, const struct attribute * attr, int type)
{
struct sysfs_dirent * parent_sd = dir->d_fsdata;
umode_t mode = (attr->mode & S_IALLUGO) | S_IFREG;
- int error = 0;
+ int error = -EEXIST;
mutex_lock(&dir->d_inode->i_mutex);
- error = sysfs_make_dirent(parent_sd, NULL, (void *) attr, mode, type);
+ if (!sysfs_dirent_exist(parent_sd, attr->name))
+ error = sysfs_make_dirent(parent_sd, NULL, (void *)attr,
+ mode, type);
mutex_unlock(&dir->d_inode->i_mutex);
return error;
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index 689f7bcfaf3..4c29ac41ac3 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -54,11 +54,10 @@ int sysfs_setattr(struct dentry * dentry, struct iattr * iattr)
if (!sd_iattr) {
/* setting attributes for the first time, allocate now */
- sd_iattr = kmalloc(sizeof(struct iattr), GFP_KERNEL);
+ sd_iattr = kzalloc(sizeof(struct iattr), GFP_KERNEL);
if (!sd_iattr)
return -ENOMEM;
/* assign default attributes */
- memset(sd_iattr, 0, sizeof(struct iattr));
sd_iattr->ia_mode = sd->s_mode;
sd_iattr->ia_uid = 0;
sd_iattr->ia_gid = 0;
@@ -227,12 +226,16 @@ void sysfs_drop_dentry(struct sysfs_dirent * sd, struct dentry * parent)
void sysfs_hash_and_remove(struct dentry * dir, const char * name)
{
struct sysfs_dirent * sd;
- struct sysfs_dirent * parent_sd = dir->d_fsdata;
+ struct sysfs_dirent * parent_sd;
+
+ if (!dir)
+ return;
if (dir->d_inode == NULL)
/* no inode means this hasn't been made visible yet */
return;
+ parent_sd = dir->d_fsdata;
mutex_lock(&dir->d_inode->i_mutex);
list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
if (!sd->s_element)
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c
index e38d6338a20..d2eac3ceed5 100644
--- a/fs/sysfs/symlink.c
+++ b/fs/sysfs/symlink.c
@@ -66,6 +66,7 @@ static int sysfs_add_link(struct dentry * parent, const char * name, struct kobj
if (!error)
return 0;
+ kobject_put(target);
kfree(sl->link_name);
exit2:
kfree(sl);
@@ -82,12 +83,13 @@ exit1:
int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char * name)
{
struct dentry * dentry = kobj->dentry;
- int error = 0;
+ int error = -EEXIST;
BUG_ON(!kobj || !kobj->dentry || !name);
mutex_lock(&dentry->d_inode->i_mutex);
- error = sysfs_add_link(dentry, name, target);
+ if (!sysfs_dirent_exist(dentry->d_fsdata, name))
+ error = sysfs_add_link(dentry, name, target);
mutex_unlock(&dentry->d_inode->i_mutex);
return error;
}
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index 3f8953e0e5d..cf11d5b789d 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -5,6 +5,7 @@ extern kmem_cache_t *sysfs_dir_cachep;
extern struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent *);
extern int sysfs_create(struct dentry *, int mode, int (*init)(struct inode *));
+extern int sysfs_dirent_exist(struct sysfs_dirent *, const unsigned char *);
extern int sysfs_make_dirent(struct sysfs_dirent *, struct dentry *, void *,
umode_t, int);
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 35de20cf8fa..9d11550b481 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -58,6 +58,13 @@
VMLINUX_SYMBOL(__stop___ksymtab_gpl) = .; \
} \
\
+ /* Kernel symbol table: GPL-future-only symbols */ \
+ __ksymtab_gpl_future : AT(ADDR(__ksymtab_gpl_future) - LOAD_OFFSET) { \
+ VMLINUX_SYMBOL(__start___ksymtab_gpl_future) = .; \
+ *(__ksymtab_gpl_future) \
+ VMLINUX_SYMBOL(__stop___ksymtab_gpl_future) = .; \
+ } \
+ \
/* Kernel symbol table: Normal symbols */ \
__kcrctab : AT(ADDR(__kcrctab) - LOAD_OFFSET) { \
VMLINUX_SYMBOL(__start___kcrctab) = .; \
@@ -72,6 +79,13 @@
VMLINUX_SYMBOL(__stop___kcrctab_gpl) = .; \
} \
\
+ /* Kernel symbol table: GPL-future-only symbols */ \
+ __kcrctab_gpl_future : AT(ADDR(__kcrctab_gpl_future) - LOAD_OFFSET) { \
+ VMLINUX_SYMBOL(__start___kcrctab_gpl_future) = .; \
+ *(__kcrctab_gpl_future) \
+ VMLINUX_SYMBOL(__stop___kcrctab_gpl_future) = .; \
+ } \
+ \
/* Kernel symbol table: strings */ \
__ksymtab_strings : AT(ADDR(__ksymtab_strings) - LOAD_OFFSET) { \
*(__ksymtab_strings) \
diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index 0ed1d4853c6..d612b89dce3 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -32,7 +32,7 @@ struct cpu {
};
extern int register_cpu(struct cpu *, int, struct node *);
-extern struct sys_device *get_cpu_sysdev(int cpu);
+extern struct sys_device *get_cpu_sysdev(unsigned cpu);
#ifdef CONFIG_HOTPLUG_CPU
extern void unregister_cpu(struct cpu *, struct node *);
#endif
diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h
index a5fa6a6eede..4b0428e335b 100644
--- a/include/linux/debugfs.h
+++ b/include/linux/debugfs.h
@@ -21,6 +21,11 @@
struct file_operations;
+struct debugfs_blob_wrapper {
+ void *data;
+ unsigned long size;
+};
+
#if defined(CONFIG_DEBUG_FS)
struct dentry *debugfs_create_file(const char *name, mode_t mode,
struct dentry *parent, void *data,
@@ -39,6 +44,9 @@ struct dentry *debugfs_create_u32(const char *name, mode_t mode,
struct dentry *debugfs_create_bool(const char *name, mode_t mode,
struct dentry *parent, u32 *value);
+struct dentry *debugfs_create_blob(const char *name, mode_t mode,
+ struct dentry *parent,
+ struct debugfs_blob_wrapper *blob);
#else
#include <linux/err.h>
@@ -94,6 +102,13 @@ static inline struct dentry *debugfs_create_bool(const char *name, mode_t mode,
return ERR_PTR(-ENODEV);
}
+static inline struct dentry *debugfs_create_blob(const char *name, mode_t mode,
+ struct dentry *parent,
+ struct debugfs_blob_wrapper *blob)
+{
+ return ERR_PTR(-ENODEV);
+}
+
#endif
#endif
diff --git a/include/linux/device.h b/include/linux/device.h
index 58df18d9cd3..5b595fdfb67 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -424,6 +424,8 @@ extern void firmware_unregister(struct subsystem *);
dev_printk(KERN_INFO , dev , format , ## arg)
#define dev_warn(dev, format, arg...) \
dev_printk(KERN_WARNING , dev , format , ## arg)
+#define dev_notice(dev, format, arg...) \
+ dev_printk(KERN_NOTICE , dev , format , ## arg)
/* Create alias, so I can be autoloaded. */
#define MODULE_ALIAS_CHARDEV(major,minor) \
diff --git a/include/linux/kobj_map.h b/include/linux/kobj_map.h
index cbe7d800804..bafe178a381 100644
--- a/include/linux/kobj_map.h
+++ b/include/linux/kobj_map.h
@@ -1,6 +1,6 @@
#ifdef __KERNEL__
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
typedef struct kobject *kobj_probe_t(dev_t, int *, void *);
struct kobj_map;
@@ -9,6 +9,6 @@ int kobj_map(struct kobj_map *, dev_t, unsigned long, struct module *,
kobj_probe_t *, int (*)(dev_t, void *), void *);
void kobj_unmap(struct kobj_map *, dev_t, unsigned long);
struct kobject *kobj_lookup(struct kobj_map *, dev_t, int *);
-struct kobj_map *kobj_map_init(kobj_probe_t *, struct semaphore *);
+struct kobj_map *kobj_map_init(kobj_probe_t *, struct mutex *);
#endif
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index c374b5fa8d3..4cb1214ec29 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -80,6 +80,8 @@ extern void kobject_unregister(struct kobject *);
extern struct kobject * kobject_get(struct kobject *);
extern void kobject_put(struct kobject *);
+extern struct kobject *kobject_add_dir(struct kobject *, const char *);
+
extern char * kobject_get_path(struct kobject *, gfp_t);
struct kobj_type {
@@ -255,7 +257,7 @@ struct subsys_attribute {
extern int subsys_create_file(struct subsystem * , struct subsys_attribute *);
extern void subsys_remove_file(struct subsystem * , struct subsys_attribute *);
-#if defined(CONFIG_HOTPLUG) & defined(CONFIG_NET)
+#if defined(CONFIG_HOTPLUG) && defined(CONFIG_NET)
void kobject_uevent(struct kobject *kobj, enum kobject_action action);
int add_uevent_var(char **envp, int num_envp, int *cur_index,
diff --git a/include/linux/module.h b/include/linux/module.h
index 84d75f3a8ac..70bd843c71c 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -198,6 +198,9 @@ void *__symbol_get_gpl(const char *symbol);
#define EXPORT_SYMBOL_GPL(sym) \
__EXPORT_SYMBOL(sym, "_gpl")
+#define EXPORT_SYMBOL_GPL_FUTURE(sym) \
+ __EXPORT_SYMBOL(sym, "_gpl_future")
+
#endif
struct module_ref
@@ -242,6 +245,7 @@ struct module
/* Sysfs stuff. */
struct module_kobject mkobj;
struct module_param_attrs *param_attrs;
+ struct module_attribute *modinfo_attrs;
const char *version;
const char *srcversion;
@@ -255,6 +259,11 @@ struct module
unsigned int num_gpl_syms;
const unsigned long *gpl_crcs;
+ /* symbols that will be GPL-only in the near future. */
+ const struct kernel_symbol *gpl_future_syms;
+ unsigned int num_gpl_future_syms;
+ const unsigned long *gpl_future_crcs;
+
/* Exception table */
unsigned int num_exentries;
const struct exception_table_entry *extable;
@@ -441,6 +450,7 @@ void module_remove_driver(struct device_driver *);
#else /* !CONFIG_MODULES... */
#define EXPORT_SYMBOL(sym)
#define EXPORT_SYMBOL_GPL(sym)
+#define EXPORT_SYMBOL_GPL_FUTURE(sym)
/* Given an address, look for it in the exception tables. */
static inline const struct exception_table_entry *
diff --git a/kernel/ksysfs.c b/kernel/ksysfs.c
index d5eeae0fa5b..f2690ed7453 100644
--- a/kernel/ksysfs.c
+++ b/kernel/ksysfs.c
@@ -15,9 +15,6 @@
#include <linux/module.h>
#include <linux/init.h>
-u64 uevent_seqnum;
-char uevent_helper[UEVENT_HELPER_PATH_LEN] = "/sbin/hotplug";
-
#define KERNEL_ATTR_RO(_name) \
static struct subsys_attribute _name##_attr = __ATTR_RO(_name)
diff --git a/kernel/module.c b/kernel/module.c
index 5aad477ddc7..77764f22f02 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -126,8 +126,11 @@ extern const struct kernel_symbol __start___ksymtab[];
extern const struct kernel_symbol __stop___ksymtab[];
extern const struct kernel_symbol __start___ksymtab_gpl[];
extern const struct kernel_symbol __stop___ksymtab_gpl[];
+extern const struct kernel_symbol __start___ksymtab_gpl_future[];
+extern const struct kernel_symbol __stop___ksymtab_gpl_future[];
extern const unsigned long __start___kcrctab[];
extern const unsigned long __start___kcrctab_gpl[];
+extern const unsigned long __start___kcrctab_gpl_future[];
#ifndef CONFIG_MODVERSIONS
#define symversion(base, idx) NULL
@@ -135,6 +138,18 @@ extern const unsigned long __start___kcrctab_gpl[];
#define symversion(base, idx) ((base) ? ((base) + (idx)) : NULL)
#endif
+/* lookup symbol in given range of kernel_symbols */
+static const struct kernel_symbol *lookup_symbol(const char *name,
+ const struct kernel_symbol *start,
+ const struct kernel_symbol *stop)
+{
+ const struct kernel_symbol *ks = start;
+ for (; ks < stop; ks++)
+ if (strcmp(ks->name, name) == 0)
+ return ks;
+ return NULL;
+}
+
/* Find a symbol, return value, crc and module which owns it */
static unsigned long __find_symbol(const char *name,
struct module **owner,
@@ -142,40 +157,75 @@ static unsigned long __find_symbol(const char *name,
int gplok)
{
struct module *mod;
- unsigned int i;
+ const struct kernel_symbol *ks;
/* Core kernel first. */
*owner = NULL;
- for (i = 0; __start___ksymtab+i < __stop___ksymtab; i++) {
- if (strcmp(__start___ksymtab[i].name, name) == 0) {
- *crc = symversion(__start___kcrctab, i);
- return __start___ksymtab[i].value;
- }
+ ks = lookup_symbol(name, __start___ksymtab, __stop___ksymtab);
+ if (ks) {
+ *crc = symversion(__start___kcrctab, (ks - __start___ksymtab));
+ return ks->value;
}
if (gplok) {
- for (i = 0; __start___ksymtab_gpl+i<__stop___ksymtab_gpl; i++)
- if (strcmp(__start___ksymtab_gpl[i].name, name) == 0) {
- *crc = symversion(__start___kcrctab_gpl, i);
- return __start___ksymtab_gpl[i].value;
- }
+ ks = lookup_symbol(name, __start___ksymtab_gpl,
+ __stop___ksymtab_gpl);
+ if (ks) {
+ *crc = symversion(__start___kcrctab_gpl,
+ (ks - __start___ksymtab_gpl));
+ return ks->value;
+ }
+ }
+ ks = lookup_symbol(name, __start___ksymtab_gpl_future,
+ __stop___ksymtab_gpl_future);
+ if (ks) {
+ if (!gplok) {
+ printk(KERN_WARNING "Symbol %s is being used "
+ "by a non-GPL module, which will not "
+ "be allowed in the future\n", name);
+ printk(KERN_WARNING "Please see the file "
+ "Documentation/feature-removal-schedule.txt "
+ "in the kernel source tree for more "
+ "details.\n");
+ }
+ *crc = symversion(__start___kcrctab_gpl_future,
+ (ks - __start___ksymtab_gpl_future));
+ return ks->value;
}
/* Now try modules. */
list_for_each_entry(mod, &modules, list) {
*owner = mod;
- for (i = 0; i < mod->num_syms; i++)
- if (strcmp(mod->syms[i].name, name) == 0) {
- *crc = symversion(mod->crcs, i);
- return mod->syms[i].value;
- }
+ ks = lookup_symbol(name, mod->syms, mod->syms + mod->num_syms);
+ if (ks) {
+ *crc = symversion(mod->crcs, (ks - mod->syms));
+ return ks->value;
+ }
if (gplok) {
- for (i = 0; i < mod->num_gpl_syms; i++) {
- if (strcmp(mod->gpl_syms[i].name, name) == 0) {
- *crc = symversion(mod->gpl_crcs, i);
- return mod->gpl_syms[i].value;
- }
+ ks = lookup_symbol(name, mod->gpl_syms,
+ mod->gpl_syms + mod->num_gpl_syms);
+ if (ks) {
+ *crc = symversion(mod->gpl_crcs,
+ (ks - mod->gpl_syms));
+ return ks->value;
+ }
+ }
+ ks = lookup_symbol(name, mod->gpl_future_syms,
+ (mod->gpl_future_syms +
+ mod->num_gpl_future_syms));
+ if (ks) {
+ if (!gplok) {
+ printk(KERN_WARNING "Symbol %s is being used "
+ "by a non-GPL module, which will not "
+ "be allowed in the future\n", name);
+ printk(KERN_WARNING "Please see the file "
+ "Documentation/feature-removal-schedule.txt "
+ "in the kernel source tree for more "
+ "details.\n");
}
+ *crc = symversion(mod->gpl_future_crcs,
+ (ks - mod->gpl_future_syms));
+ return ks->value;
}
}
DEBUGP("Failed to find symbol %s\n", name);
@@ -379,7 +429,6 @@ static inline void percpu_modcopy(void *pcpudst, const void *src,
}
#endif /* CONFIG_SMP */
-#ifdef CONFIG_MODULE_UNLOAD
#define MODINFO_ATTR(field) \
static void setup_modinfo_##field(struct module *mod, const char *s) \
{ \
@@ -411,12 +460,7 @@ static struct module_attribute modinfo_##field = { \
MODINFO_ATTR(version);
MODINFO_ATTR(srcversion);
-static struct module_attribute *modinfo_attrs[] = {
- &modinfo_version,
- &modinfo_srcversion,
- NULL,
-};
-
+#ifdef CONFIG_MODULE_UNLOAD
/* Init the unload section of the module. */
static void module_unload_init(struct module *mod)
{
@@ -731,6 +775,15 @@ static inline void module_unload_init(struct module *mod)
}
#endif /* CONFIG_MODULE_UNLOAD */
+static struct module_attribute *modinfo_attrs[] = {
+ &modinfo_version,
+ &modinfo_srcversion,
+#ifdef CONFIG_MODULE_UNLOAD
+ &refcnt,
+#endif
+ NULL,
+};
+
#ifdef CONFIG_OBSOLETE_MODPARM
/* Bounds checking done below */
static int obsparm_copy_string(const char *val, struct kernel_param *kp)
@@ -1056,37 +1109,28 @@ static inline void remove_sect_attrs(struct module *mod)
}
#endif /* CONFIG_KALLSYMS */
-
-#ifdef CONFIG_MODULE_UNLOAD
-static inline int module_add_refcnt_attr(struct module *mod)
-{
- return sysfs_create_file(&mod->mkobj.kobj, &refcnt.attr);
-}
-static void module_remove_refcnt_attr(struct module *mod)
-{
- return sysfs_remove_file(&mod->mkobj.kobj, &refcnt.attr);
-}
-#else
-static inline int module_add_refcnt_attr(struct module *mod)
-{
- return 0;
-}
-static void module_remove_refcnt_attr(struct module *mod)
-{
-}
-#endif
-
-#ifdef CONFIG_MODULE_UNLOAD
static int module_add_modinfo_attrs(struct module *mod)
{
struct module_attribute *attr;
+ struct module_attribute *temp_attr;
int error = 0;
int i;
+ mod->modinfo_attrs = kzalloc((sizeof(struct module_attribute) *
+ (ARRAY_SIZE(modinfo_attrs) + 1)),
+ GFP_KERNEL);
+ if (!mod->modinfo_attrs)
+ return -ENOMEM;
+
+ temp_attr = mod->modinfo_attrs;
for (i = 0; (attr = modinfo_attrs[i]) && !error; i++) {
if (!attr->test ||
- (attr->test && attr->test(mod)))
- error = sysfs_create_file(&mod->mkobj.kobj,&attr->attr);
+ (attr->test && attr->test(mod))) {
+ memcpy(temp_attr, attr, sizeof(*temp_attr));
+ temp_attr->attr.owner = mod;
+ error = sysfs_create_file(&mod->mkobj.kobj,&temp_attr->attr);
+ ++temp_attr;
+ }
}
return error;
}
@@ -1096,12 +1140,16 @@ static void module_remove_modinfo_attrs(struct module *mod)
struct module_attribute *attr;
int i;
- for (i = 0; (attr = modinfo_attrs[i]); i++) {
+ for (i = 0; (attr = &mod->modinfo_attrs[i]); i++) {
+ /* pick a field to test for end of list */
+ if (!attr->attr.name)
+ break;
sysfs_remove_file(&mod->mkobj.kobj,&attr->attr);
- attr->free(mod);
+ if (attr->free)
+ attr->free(mod);
}
+ kfree(mod->modinfo_attrs);
}
-#endif
static int mod_sysfs_setup(struct module *mod,
struct kernel_param *kparam,
@@ -1119,19 +1167,13 @@ static int mod_sysfs_setup(struct module *mod,
if (err)
goto out;
- err = module_add_refcnt_attr(mod);
- if (err)
- goto out_unreg;
-
err = module_param_sysfs_setup(mod, kparam, num_params);
if (err)
goto out_unreg;
-#ifdef CONFIG_MODULE_UNLOAD
err = module_add_modinfo_attrs(mod);
if (err)
goto out_unreg;
-#endif
return 0;
@@ -1143,10 +1185,7 @@ out:
static void mod_kobject_remove(struct module *mod)
{
-#ifdef CONFIG_MODULE_UNLOAD
module_remove_modinfo_attrs(mod);
-#endif
- module_remove_refcnt_attr(mod);
module_param_sysfs_remove(mod);
kobject_unregister(&mod->mkobj.kobj);
@@ -1424,7 +1463,6 @@ static char *get_modinfo(Elf_Shdr *sechdrs,
return NULL;
}
-#ifdef CONFIG_MODULE_UNLOAD
static void setup_modinfo(struct module *mod, Elf_Shdr *sechdrs,
unsigned int infoindex)
{
@@ -1439,23 +1477,17 @@ static void setup_modinfo(struct module *mod, Elf_Shdr *sechdrs,
attr->attr.name));
}
}
-#endif
#ifdef CONFIG_KALLSYMS
int is_exported(const char *name, const struct module *mod)
{
- unsigned int i;
-
- if (!mod) {
- for (i = 0; __start___ksymtab+i < __stop___ksymtab; i++)
- if (strcmp(__start___ksymtab[i].name, name) == 0)
- return 1;
- return 0;
- }
- for (i = 0; i < mod->num_syms; i++)
- if (strcmp(mod->syms[i].name, name) == 0)
+ if (!mod && lookup_symbol(name, __start___ksymtab, __stop___ksymtab))
+ return 1;
+ else
+ if (lookup_symbol(name, mod->syms, mod->syms + mod->num_syms))
return 1;
- return 0;
+ else
+ return 0;
}
/* As per nm */
@@ -1537,7 +1569,8 @@ static struct module *load_module(void __user *umod,
char *secstrings, *args, *modmagic, *strtab = NULL;
unsigned int i, symindex = 0, strindex = 0, setupindex, exindex,
exportindex, modindex, obsparmindex, infoindex, gplindex,
- crcindex, gplcrcindex, versindex, pcpuindex;
+ crcindex, gplcrcindex, versindex, pcpuindex, gplfutureindex,
+ gplfuturecrcindex;
long arglen;
struct module *mod;
long err = 0;
@@ -1618,8 +1651,10 @@ static struct module *load_module(void __user *umod,
/* Optional sections */
exportindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab");
gplindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_gpl");
+ gplfutureindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_gpl_future");
crcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab");
gplcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_gpl");
+ gplfuturecrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_gpl_future");
setupindex = find_sec(hdr, sechdrs, secstrings, "__param");
exindex = find_sec(hdr, sechdrs, secstrings, "__ex_table");
obsparmindex = find_sec(hdr, sechdrs, secstrings, "__obsparm");
@@ -1755,10 +1790,8 @@ static struct module *load_module(void __user *umod,
if (strcmp(mod->name, "driverloader") == 0)
add_taint(TAINT_PROPRIETARY_MODULE);
-#ifdef CONFIG_MODULE_UNLOAD
/* Set up MODINFO_ATTR fields */
setup_modinfo(mod, sechdrs, infoindex);
-#endif
/* Fix up syms, so that st_value is a pointer to location. */
err = simplify_symbols(sechdrs, symindex, strtab, versindex, pcpuindex,
@@ -1775,10 +1808,16 @@ static struct module *load_module(void __user *umod,
mod->gpl_syms = (void *)sechdrs[gplindex].sh_addr;
if (gplcrcindex)
mod->gpl_crcs = (void *)sechdrs[gplcrcindex].sh_addr;
+ mod->num_gpl_future_syms = sechdrs[gplfutureindex].sh_size /
+ sizeof(*mod->gpl_future_syms);
+ mod->gpl_future_syms = (void *)sechdrs[gplfutureindex].sh_addr;
+ if (gplfuturecrcindex)
+ mod->gpl_future_crcs = (void *)sechdrs[gplfuturecrcindex].sh_addr;
#ifdef CONFIG_MODVERSIONS
if ((mod->num_syms && !crcindex) ||
- (mod->num_gpl_syms && !gplcrcindex)) {
+ (mod->num_gpl_syms && !gplcrcindex) ||
+ (mod->num_gpl_future_syms && !gplfuturecrcindex)) {
printk(KERN_WARNING "%s: No versions for exported symbols."
" Tainting kernel.\n", mod->name);
add_taint(TAINT_FORCED_MODULE);
diff --git a/kernel/params.c b/kernel/params.c
index c76ad25e6a2..a2915058231 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -638,13 +638,8 @@ static ssize_t module_attr_show(struct kobject *kobj,
if (!attribute->show)
return -EIO;
- if (!try_module_get(mk->mod))
- return -ENODEV;
-
ret = attribute->show(attribute, mk->mod, buf);
- module_put(mk->mod);
-
return ret;
}
@@ -662,13 +657,8 @@ static ssize_t module_attr_store(struct kobject *kobj,
if (!attribute->store)
return -EIO;
- if (!try_module_get(mk->mod))
- return -ENODEV;
-
ret = attribute->store(attribute, mk->mod, buf, len);
- module_put(mk->mod);
-
return ret;
}
diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c
index 8cf15a569fc..fedf5e36975 100644
--- a/kernel/rcupdate.c
+++ b/kernel/rcupdate.c
@@ -609,7 +609,7 @@ module_param(qlowmark, int, 0);
module_param(rsinterval, int, 0);
#endif
EXPORT_SYMBOL_GPL(rcu_batches_completed);
-EXPORT_SYMBOL(call_rcu); /* WARNING: GPL-only in April 2006. */
-EXPORT_SYMBOL(call_rcu_bh); /* WARNING: GPL-only in April 2006. */
+EXPORT_SYMBOL_GPL_FUTURE(call_rcu); /* WARNING: GPL-only in April 2006. */
+EXPORT_SYMBOL_GPL_FUTURE(call_rcu_bh); /* WARNING: GPL-only in April 2006. */
EXPORT_SYMBOL_GPL(synchronize_rcu);
-EXPORT_SYMBOL(synchronize_kernel); /* WARNING: GPL-only in April 2006. */
+EXPORT_SYMBOL_GPL_FUTURE(synchronize_kernel); /* WARNING: GPL-only in April 2006. */
diff --git a/lib/kobject.c b/lib/kobject.c
index efe67fa96a7..25204a41a9b 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -194,6 +194,17 @@ int kobject_add(struct kobject * kobj)
unlink(kobj);
if (parent)
kobject_put(parent);
+
+ /* be noisy on error issues */
+ if (error == -EEXIST)
+ printk("kobject_add failed for %s with -EEXIST, "
+ "don't try to register things with the "
+ "same name in the same directory.\n",
+ kobject_name(kobj));
+ else
+ printk("kobject_add failed for %s (%d)\n",
+ kobject_name(kobj), error);
+ dump_stack();
}
return error;
@@ -207,18 +218,13 @@ int kobject_add(struct kobject * kobj)
int kobject_register(struct kobject * kobj)
{
- int error = 0;
+ int error = -EINVAL;
if (kobj) {
kobject_init(kobj);
error = kobject_add(kobj);
- if (error) {
- printk("kobject_register failed for %s (%d)\n",
- kobject_name(kobj),error);
- dump_stack();
- } else
+ if (!error)
kobject_uevent(kobj, KOBJ_ADD);
- } else
- error = -EINVAL;
+ }
return error;
}
@@ -379,6 +385,44 @@ void kobject_put(struct kobject * kobj)
}
+static void dir_release(struct kobject *kobj)
+{
+ kfree(kobj);
+}
+
+static struct kobj_type dir_ktype = {
+ .release = dir_release,
+ .sysfs_ops = NULL,
+ .default_attrs = NULL,
+};
+
+/**
+ * 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)
+{
+ struct kobject *k;
+
+ if (!parent)
+ return NULL;
+
+ k = kzalloc(sizeof(*k), GFP_KERNEL);
+ if (!k)
+ return NULL;
+
+ k->parent = parent;
+ k->ktype = &dir_ktype;
+ kobject_set_name(k, name);
+ kobject_register(k);
+
+ return k;
+}
+EXPORT_SYMBOL_GPL(kobject_add_dir);
+
/**
* kset_init - initialize a kset for use
* @k: kset
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c
index 086a0c6e888..982226daf93 100644
--- a/lib/kobject_uevent.c
+++ b/lib/kobject_uevent.c
@@ -26,6 +26,8 @@
#define NUM_ENVP 32 /* number of env pointers */
#if defined(CONFIG_HOTPLUG) && defined(CONFIG_NET)
+u64 uevent_seqnum;
+char uevent_helper[UEVENT_HELPER_PATH_LEN] = "/sbin/hotplug";
static DEFINE_SPINLOCK(sequence_lock);
static struct sock *uevent_sock;
diff --git a/lib/kref.c b/lib/kref.c
index 0d07cc31c81..4a467faf136 100644
--- a/lib/kref.c
+++ b/lib/kref.c
@@ -52,7 +52,12 @@ int kref_put(struct kref *kref, void (*release)(struct kref *kref))
WARN_ON(release == NULL);
WARN_ON(release == (void (*)(struct kref *))kfree);
- if (atomic_dec_and_test(&kref->refcount)) {
+ /*
+ * if current count is one, we are the last user and can release object
+ * right now, avoiding an atomic operation on 'refcount'
+ */
+ if ((atomic_read(&kref->refcount) == 1) ||
+ (atomic_dec_and_test(&kref->refcount))) {
release(kref);
return 1;
}
diff --git a/scripts/genksyms/keywords.c_shipped b/scripts/genksyms/keywords.c_shipped
index ee4647805c5..d8153f572e4 100644
--- a/scripts/genksyms/keywords.c_shipped
+++ b/scripts/genksyms/keywords.c_shipped
@@ -52,9 +52,9 @@ is_reserved_hash (register const char *str, register unsigned int len)
71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
- 71, 71, 71, 71, 71, 71, 71, 71, 71, 15,
- 71, 71, 71, 71, 71, 71, 15, 71, 71, 71,
- 10, 71, 71, 71, 71, 71, 71, 71, 71, 71,
+ 71, 71, 71, 71, 71, 71, 71, 71, 71, 0,
+ 71, 71, 71, 71, 71, 71, 35, 71, 71, 71,
+ 5, 71, 71, 71, 71, 71, 71, 71, 71, 71,
71, 71, 71, 71, 71, 0, 71, 0, 71, 5,
5, 0, 10, 20, 71, 25, 71, 71, 20, 0,
20, 30, 25, 71, 10, 5, 0, 20, 15, 71,
@@ -84,9 +84,9 @@ is_reserved_word (register const char *str, register unsigned int len)
{
enum
{
- TOTAL_KEYWORDS = 41,
+ TOTAL_KEYWORDS = 42,
MIN_WORD_LENGTH = 3,
- MAX_WORD_LENGTH = 17,
+ MAX_WORD_LENGTH = 24,
MIN_HASH_VALUE = 3,
MAX_HASH_VALUE = 70
};
@@ -94,104 +94,105 @@ is_reserved_word (register const char *str, register unsigned int len)
static const struct resword wordlist[] =
{
{""}, {""}, {""},
-#line 24 "scripts/genksyms/keywords.gperf"
+#line 25 "scripts/genksyms/keywords.gperf"
{"asm", ASM_KEYW},
{""},
-#line 7 "scripts/genksyms/keywords.gperf"
+#line 8 "scripts/genksyms/keywords.gperf"
{"__asm", ASM_KEYW},
{""},
-#line 8 "scripts/genksyms/keywords.gperf"
+#line 9 "scripts/genksyms/keywords.gperf"
{"__asm__", ASM_KEYW},
{""},
-#line 21 "scripts/genksyms/keywords.gperf"
+#line 22 "scripts/genksyms/keywords.gperf"
{"_restrict", RESTRICT_KEYW},
-#line 50 "scripts/genksyms/keywords.gperf"
+#line 51 "scripts/genksyms/keywords.gperf"
{"__typeof__", TYPEOF_KEYW},
-#line 9 "scripts/genksyms/keywords.gperf"
+#line 10 "scripts/genksyms/keywords.gperf"
{"__attribute", ATTRIBUTE_KEYW},
-#line 11 "scripts/genksyms/keywords.gperf"
+#line 12 "scripts/genksyms/keywords.gperf"
{"__const", CONST_KEYW},
-#line 10 "scripts/genksyms/keywords.gperf"
+#line 11 "scripts/genksyms/keywords.gperf"
{"__attribute__", ATTRIBUTE_KEYW},
-#line 12 "scripts/genksyms/keywords.gperf"
+#line 13 "scripts/genksyms/keywords.gperf"
{"__const__", CONST_KEYW},
-#line 16 "scripts/genksyms/keywords.gperf"
+#line 17 "scripts/genksyms/keywords.gperf"
{"__signed__", SIGNED_KEYW},
-#line 42 "scripts/genksyms/keywords.gperf"
+#line 43 "scripts/genksyms/keywords.gperf"
{"static", STATIC_KEYW},
{""},
-#line 15 "scripts/genksyms/keywords.gperf"
+#line 16 "scripts/genksyms/keywords.gperf"
{"__signed", SIGNED_KEYW},
-#line 30 "scripts/genksyms/keywords.gperf"
+#line 31 "scripts/genksyms/keywords.gperf"
{"char", CHAR_KEYW},
{""},
-#line 43 "scripts/genksyms/keywords.gperf"
+#line 44 "scripts/genksyms/keywords.gperf"
{"struct", STRUCT_KEYW},
-#line 22 "scripts/genksyms/keywords.gperf"
- {"__restrict__", RESTRICT_KEYW},
#line 23 "scripts/genksyms/keywords.gperf"
+ {"__restrict__", RESTRICT_KEYW},
+#line 24 "scripts/genksyms/keywords.gperf"
{"restrict", RESTRICT_KEYW},
-#line 33 "scripts/genksyms/keywords.gperf"
+#line 34 "scripts/genksyms/keywords.gperf"
{"enum", ENUM_KEYW},
-#line 17 "scripts/genksyms/keywords.gperf"
+#line 18 "scripts/genksyms/keywords.gperf"
{"__volatile", VOLATILE_KEYW},
-#line 34 "scripts/genksyms/keywords.gperf"
+#line 35 "scripts/genksyms/keywords.gperf"
{"extern", EXTERN_KEYW},
-#line 18 "scripts/genksyms/keywords.gperf"
+#line 19 "scripts/genksyms/keywords.gperf"
{"__volatile__", VOLATILE_KEYW},
-#line 37 "scripts/genksyms/keywords.gperf"
+#line 38 "scripts/genksyms/keywords.gperf"
{"int", INT_KEYW},
- {""},
-#line 31 "scripts/genksyms/keywords.gperf"
- {"const", CONST_KEYW},
+#line 7 "scripts/genksyms/keywords.gperf"
+ {"EXPORT_SYMBOL_GPL_FUTURE", EXPORT_SYMBOL_KEYW},
#line 32 "scripts/genksyms/keywords.gperf"
+ {"const", CONST_KEYW},
+#line 33 "scripts/genksyms/keywords.gperf"
{"double", DOUBLE_KEYW},
{""},
-#line 13 "scripts/genksyms/keywords.gperf"
+#line 14 "scripts/genksyms/keywords.gperf"
{"__inline", INLINE_KEYW},
-#line 29 "scripts/genksyms/keywords.gperf"
+#line 30 "scripts/genksyms/keywords.gperf"
{"auto", AUTO_KEYW},
-#line 14 "scripts/genksyms/keywords.gperf"
+#line 15 "scripts/genksyms/keywords.gperf"
{"__inline__", INLINE_KEYW},
-#line 41 "scripts/genksyms/keywords.gperf"
+#line 42 "scripts/genksyms/keywords.gperf"
{"signed", SIGNED_KEYW},
{""},
-#line 46 "scripts/genksyms/keywords.gperf"
+#line 47 "scripts/genksyms/keywords.gperf"
{"unsigned", UNSIGNED_KEYW},
{""},
-#line 40 "scripts/genksyms/keywords.gperf"
+#line 41 "scripts/genksyms/keywords.gperf"
{"short", SHORT_KEYW},
-#line 49 "scripts/genksyms/keywords.gperf"
+#line 50 "scripts/genksyms/keywords.gperf"
{"typeof", TYPEOF_KEYW},
-#line 44 "scripts/genksyms/keywords.gperf"
+#line 45 "scripts/genksyms/keywords.gperf"
{"typedef", TYPEDEF_KEYW},
-#line 48 "scripts/genksyms/keywords.gperf"
+#line 49 "scripts/genksyms/keywords.gperf"
{"volatile", VOLATILE_KEYW},
{""},
-#line 35 "scripts/genksyms/keywords.gperf"
+#line 36 "scripts/genksyms/keywords.gperf"
{"float", FLOAT_KEYW},
{""}, {""},
-#line 39 "scripts/genksyms/keywords.gperf"
+#line 40 "scripts/genksyms/keywords.gperf"
{"register", REGISTER_KEYW},
-#line 47 "scripts/genksyms/keywords.gperf"
+#line 48 "scripts/genksyms/keywords.gperf"
{"void", VOID_KEYW},
{""},
-#line 36 "scripts/genksyms/keywords.gperf"
+#line 37 "scripts/genksyms/keywords.gperf"
{"inline", INLINE_KEYW},
{""},
#line 5 "scripts/genksyms/keywords.gperf"
{"EXPORT_SYMBOL", EXPORT_SYMBOL_KEYW},
{""},
-#line 20 "scripts/genksyms/keywords.gperf"
+#line 21 "scripts/genksyms/keywords.gperf"
{"_Bool", BOOL_KEYW},
{""},
#line 6 "scripts/genksyms/keywords.gperf"
{"EXPORT_SYMBOL_GPL", EXPORT_SYMBOL_KEYW},
{""}, {""}, {""}, {""}, {""}, {""},
-#line 38 "scripts/genksyms/keywords.gperf"
+#line 39 "scripts/genksyms/keywords.gperf"
{"long", LONG_KEYW},
{""}, {""}, {""}, {""}, {""},
-#line 45 "scripts/genksyms/keywords.gperf"
+#line 46 "scripts/genksyms/keywords.gperf"
{"union", UNION_KEYW}
};
diff --git a/scripts/genksyms/keywords.gperf b/scripts/genksyms/keywords.gperf
index b6bec765996..c75e0c8d8f0 100644
--- a/scripts/genksyms/keywords.gperf
+++ b/scripts/genksyms/keywords.gperf
@@ -4,6 +4,7 @@ struct resword { const char *name; int token; }
%%
EXPORT_SYMBOL, EXPORT_SYMBOL_KEYW
EXPORT_SYMBOL_GPL, EXPORT_SYMBOL_KEYW
+EXPORT_SYMBOL_GPL_FUTURE, EXPORT_SYMBOL_KEYW
__asm, ASM_KEYW
__asm__, ASM_KEYW
__attribute, ATTRIBUTE_KEYW