aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-02-26 14:41:30 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-02-26 14:41:30 -0500
commita7538a7f87826fb5cacc6959f00dfa9fba6f4b15 (patch)
treea0fef9252200a78634f0fa4eaa714c7a40e802b9
parent92320cec611d4ed44a9bd635727d61f6caa669a7 (diff)
parentdfff0a0671baf4e69fc676bf8150635407548288 (diff)
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: Revert "Driver core: let request_module() send a /sys/modules/kmod/-uevent" Driver core: fix error by cleanup up symlinks properly make kernel/kmod.c:kmod_mk static power management: fix struct layout and docs power management: no valid states w/o pm_ops Driver core: more fallout from class_device changes for pcmcia sysfs: move struct sysfs_dirent to private header driver core: refcounting fix Driver core: remove class_device_rename
-rw-r--r--drivers/base/class.c42
-rw-r--r--drivers/base/core.c31
-rw-r--r--drivers/pcmcia/hd64465_ss.c2
-rw-r--r--drivers/pcmcia/m32r_cfc.c2
-rw-r--r--drivers/pcmcia/m8xx_pcmcia.c2
-rw-r--r--drivers/pcmcia/omap_cf.c2
-rw-r--r--drivers/pcmcia/rsrc_mgr.c2
-rw-r--r--drivers/pcmcia/vrc4171_card.c2
-rw-r--r--fs/sysfs/sysfs.h11
-rw-r--r--include/linux/device.h2
-rw-r--r--include/linux/kmod.h2
-rw-r--r--include/linux/pm.h37
-rw-r--r--include/linux/sysfs.h13
-rw-r--r--kernel/kmod.c120
-rw-r--r--kernel/module.c32
-rw-r--r--kernel/params.c1
-rw-r--r--kernel/power/main.c5
17 files changed, 103 insertions, 205 deletions
diff --git a/drivers/base/class.c b/drivers/base/class.c
index 1417e5cd4c6f..d5968128be2b 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -840,48 +840,6 @@ void class_device_destroy(struct class *cls, dev_t devt)
840 class_device_unregister(class_dev); 840 class_device_unregister(class_dev);
841} 841}
842 842
843int class_device_rename(struct class_device *class_dev, char *new_name)
844{
845 int error = 0;
846 char *old_class_name = NULL, *new_class_name = NULL;
847
848 class_dev = class_device_get(class_dev);
849 if (!class_dev)
850 return -EINVAL;
851
852 pr_debug("CLASS: renaming '%s' to '%s'\n", class_dev->class_id,
853 new_name);
854
855#ifdef CONFIG_SYSFS_DEPRECATED
856 if (class_dev->dev)
857 old_class_name = make_class_name(class_dev->class->name,
858 &class_dev->kobj);
859#endif
860
861 strlcpy(class_dev->class_id, new_name, KOBJ_NAME_LEN);
862
863 error = kobject_rename(&class_dev->kobj, new_name);
864
865#ifdef CONFIG_SYSFS_DEPRECATED
866 if (class_dev->dev) {
867 new_class_name = make_class_name(class_dev->class->name,
868 &class_dev->kobj);
869 if (new_class_name)
870 sysfs_create_link(&class_dev->dev->kobj,
871 &class_dev->kobj, new_class_name);
872 if (old_class_name)
873 sysfs_remove_link(&class_dev->dev->kobj,
874 old_class_name);
875 }
876#endif
877 class_device_put(class_dev);
878
879 kfree(old_class_name);
880 kfree(new_class_name);
881
882 return error;
883}
884
885struct class_device * class_device_get(struct class_device *class_dev) 843struct class_device * class_device_get(struct class_device *class_dev)
886{ 844{
887 if (class_dev) 845 if (class_dev)
diff --git a/drivers/base/core.c b/drivers/base/core.c
index d04fd33dcd91..cf2a398aaaa1 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -637,12 +637,41 @@ int device_add(struct device *dev)
637 BUS_NOTIFY_DEL_DEVICE, dev); 637 BUS_NOTIFY_DEL_DEVICE, dev);
638 device_remove_groups(dev); 638 device_remove_groups(dev);
639 GroupError: 639 GroupError:
640 device_remove_attrs(dev); 640 device_remove_attrs(dev);
641 AttrsError: 641 AttrsError:
642 if (dev->devt_attr) { 642 if (dev->devt_attr) {
643 device_remove_file(dev, dev->devt_attr); 643 device_remove_file(dev, dev->devt_attr);
644 kfree(dev->devt_attr); 644 kfree(dev->devt_attr);
645 } 645 }
646
647 if (dev->class) {
648 sysfs_remove_link(&dev->kobj, "subsystem");
649 /* If this is not a "fake" compatible device, remove the
650 * symlink from the class to the device. */
651 if (dev->kobj.parent != &dev->class->subsys.kset.kobj)
652 sysfs_remove_link(&dev->class->subsys.kset.kobj,
653 dev->bus_id);
654#ifdef CONFIG_SYSFS_DEPRECATED
655 if (parent) {
656 char *class_name = make_class_name(dev->class->name,
657 &dev->kobj);
658 if (class_name)
659 sysfs_remove_link(&dev->parent->kobj,
660 class_name);
661 kfree(class_name);
662 sysfs_remove_link(&dev->kobj, "device");
663 }
664#endif
665
666 down(&dev->class->sem);
667 /* notify any interfaces that the device is now gone */
668 list_for_each_entry(class_intf, &dev->class->interfaces, node)
669 if (class_intf->remove_dev)
670 class_intf->remove_dev(dev, class_intf);
671 /* remove the device from the class list */
672 list_del_init(&dev->node);
673 up(&dev->class->sem);
674 }
646 ueventattrError: 675 ueventattrError:
647 device_remove_file(dev, &dev->uevent_attr); 676 device_remove_file(dev, &dev->uevent_attr);
648 attrError: 677 attrError:
diff --git a/drivers/pcmcia/hd64465_ss.c b/drivers/pcmcia/hd64465_ss.c
index caca0dc9d30f..f2e810f53c81 100644
--- a/drivers/pcmcia/hd64465_ss.c
+++ b/drivers/pcmcia/hd64465_ss.c
@@ -907,7 +907,7 @@ static int __init init_hs(void)
907 907
908 for (i=0; i<HS_MAX_SOCKETS; i++) { 908 for (i=0; i<HS_MAX_SOCKETS; i++) {
909 unsigned int ret; 909 unsigned int ret;
910 hs_sockets[i].socket.dev.dev = &hd64465_device.dev; 910 hs_sockets[i].socket.dev.parent = &hd64465_device.dev;
911 hs_sockets[i].number = i; 911 hs_sockets[i].number = i;
912 ret = pcmcia_register_socket(&hs_sockets[i].socket); 912 ret = pcmcia_register_socket(&hs_sockets[i].socket);
913 if (ret && i) 913 if (ret && i)
diff --git a/drivers/pcmcia/m32r_cfc.c b/drivers/pcmcia/m32r_cfc.c
index e4a94108aab9..91da15b5a81e 100644
--- a/drivers/pcmcia/m32r_cfc.c
+++ b/drivers/pcmcia/m32r_cfc.c
@@ -760,7 +760,7 @@ static int __init init_m32r_pcc(void)
760 /* Set up interrupt handler(s) */ 760 /* Set up interrupt handler(s) */
761 761
762 for (i = 0 ; i < pcc_sockets ; i++) { 762 for (i = 0 ; i < pcc_sockets ; i++) {
763 socket[i].socket.dev.dev = &pcc_device.dev; 763 socket[i].socket.dev.parent = &pcc_device.dev;
764 socket[i].socket.ops = &pcc_operations; 764 socket[i].socket.ops = &pcc_operations;
765 socket[i].socket.resource_ops = &pccard_nonstatic_ops; 765 socket[i].socket.resource_ops = &pccard_nonstatic_ops;
766 socket[i].socket.owner = THIS_MODULE; 766 socket[i].socket.owner = THIS_MODULE;
diff --git a/drivers/pcmcia/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c
index d059c9196172..9721ed7bf502 100644
--- a/drivers/pcmcia/m8xx_pcmcia.c
+++ b/drivers/pcmcia/m8xx_pcmcia.c
@@ -1321,7 +1321,7 @@ static int __init m8xx_init(void)
1321 socket[i].socket.ops = &m8xx_services; 1321 socket[i].socket.ops = &m8xx_services;
1322 socket[i].socket.resource_ops = &pccard_iodyn_ops; 1322 socket[i].socket.resource_ops = &pccard_iodyn_ops;
1323 socket[i].socket.cb_dev = NULL; 1323 socket[i].socket.cb_dev = NULL;
1324 socket[i].socket.dev.dev = &m8xx_device.dev; 1324 socket[i].socket.dev.parent = &m8xx_device.dev;
1325 } 1325 }
1326 1326
1327 for (i = 0; i < PCMCIA_SOCKETS_NO; i++) 1327 for (i = 0; i < PCMCIA_SOCKETS_NO; i++)
diff --git a/drivers/pcmcia/omap_cf.c b/drivers/pcmcia/omap_cf.c
index 76f7cbc62a8b..d77f75129f8a 100644
--- a/drivers/pcmcia/omap_cf.c
+++ b/drivers/pcmcia/omap_cf.c
@@ -291,7 +291,7 @@ static int __devinit omap_cf_probe(struct device *dev)
291 omap_cf_present() ? "present" : "(not present)"); 291 omap_cf_present() ? "present" : "(not present)");
292 292
293 cf->socket.owner = THIS_MODULE; 293 cf->socket.owner = THIS_MODULE;
294 cf->socket.dev.dev = dev; 294 cf->socket.dev.parent = dev;
295 cf->socket.ops = &omap_cf_ops; 295 cf->socket.ops = &omap_cf_ops;
296 cf->socket.resource_ops = &pccard_static_ops; 296 cf->socket.resource_ops = &pccard_static_ops;
297 cf->socket.features = SS_CAP_PCCARD | SS_CAP_STATIC_MAP 297 cf->socket.features = SS_CAP_PCCARD | SS_CAP_STATIC_MAP
diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c
index 81dfc2cac2b4..ce2226273aaa 100644
--- a/drivers/pcmcia/rsrc_mgr.c
+++ b/drivers/pcmcia/rsrc_mgr.c
@@ -232,7 +232,7 @@ static struct resource *iodyn_find_io_region(unsigned long base, int num,
232 unsigned long align, struct pcmcia_socket *s) 232 unsigned long align, struct pcmcia_socket *s)
233{ 233{
234 struct resource *res = make_resource(0, num, IORESOURCE_IO, 234 struct resource *res = make_resource(0, num, IORESOURCE_IO,
235 s->dev.class_id); 235 s->dev.bus_id);
236 struct pcmcia_align_data data; 236 struct pcmcia_align_data data;
237 unsigned long min = base; 237 unsigned long min = base;
238 int ret; 238 int ret;
diff --git a/drivers/pcmcia/vrc4171_card.c b/drivers/pcmcia/vrc4171_card.c
index 206e26c91807..eee2f1cb213c 100644
--- a/drivers/pcmcia/vrc4171_card.c
+++ b/drivers/pcmcia/vrc4171_card.c
@@ -596,7 +596,7 @@ static int __devinit vrc4171_add_sockets(void)
596 } 596 }
597 597
598 sprintf(socket->name, "NEC VRC4171 Card Slot %1c", 'A' + slot); 598 sprintf(socket->name, "NEC VRC4171 Card Slot %1c", 'A' + slot);
599 socket->pcmcia_socket.dev.dev = &vrc4171_card_device.dev; 599 socket->pcmcia_socket.dev.parent = &vrc4171_card_device.dev;
600 socket->pcmcia_socket.ops = &vrc4171_pccard_operations; 600 socket->pcmcia_socket.ops = &vrc4171_pccard_operations;
601 socket->pcmcia_socket.owner = THIS_MODULE; 601 socket->pcmcia_socket.owner = THIS_MODULE;
602 602
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index d976b0005549..a77c57e5a6d5 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -1,3 +1,14 @@
1struct sysfs_dirent {
2 atomic_t s_count;
3 struct list_head s_sibling;
4 struct list_head s_children;
5 void * s_element;
6 int s_type;
7 umode_t s_mode;
8 struct dentry * s_dentry;
9 struct iattr * s_iattr;
10 atomic_t s_event;
11};
1 12
2extern struct vfsmount * sysfs_mount; 13extern struct vfsmount * sysfs_mount;
3extern struct kmem_cache *sysfs_dir_cachep; 14extern struct kmem_cache *sysfs_dir_cachep;
diff --git a/include/linux/device.h b/include/linux/device.h
index d1a3a27c3988..39a3199a826d 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -294,8 +294,6 @@ extern void class_device_initialize(struct class_device *);
294extern int __must_check class_device_add(struct class_device *); 294extern int __must_check class_device_add(struct class_device *);
295extern void class_device_del(struct class_device *); 295extern void class_device_del(struct class_device *);
296 296
297extern int class_device_rename(struct class_device *, char *);
298
299extern struct class_device * class_device_get(struct class_device *); 297extern struct class_device * class_device_get(struct class_device *);
300extern void class_device_put(struct class_device *); 298extern void class_device_put(struct class_device *);
301 299
diff --git a/include/linux/kmod.h b/include/linux/kmod.h
index cc8e674ae27a..10f505c8431d 100644
--- a/include/linux/kmod.h
+++ b/include/linux/kmod.h
@@ -28,10 +28,8 @@
28#ifdef CONFIG_KMOD 28#ifdef CONFIG_KMOD
29/* modprobe exit status on success, -ve on error. Return value 29/* modprobe exit status on success, -ve on error. Return value
30 * usually useless though. */ 30 * usually useless though. */
31extern void kmod_sysfs_init(void);
32extern int request_module(const char * name, ...) __attribute__ ((format (printf, 1, 2))); 31extern int request_module(const char * name, ...) __attribute__ ((format (printf, 1, 2)));
33#else 32#else
34static inline void kmod_sysfs_init(void) {};
35static inline int request_module(const char * name, ...) { return -ENOSYS; } 33static inline int request_module(const char * name, ...) { return -ENOSYS; }
36#endif 34#endif
37 35
diff --git a/include/linux/pm.h b/include/linux/pm.h
index 070394e846d0..21db05ac7c0b 100644
--- a/include/linux/pm.h
+++ b/include/linux/pm.h
@@ -120,15 +120,48 @@ typedef int __bitwise suspend_disk_method_t;
120#define PM_DISK_TESTPROC ((__force suspend_disk_method_t) 6) 120#define PM_DISK_TESTPROC ((__force suspend_disk_method_t) 6)
121#define PM_DISK_MAX ((__force suspend_disk_method_t) 7) 121#define PM_DISK_MAX ((__force suspend_disk_method_t) 7)
122 122
123/**
124 * struct pm_ops - Callbacks for managing platform dependent suspend states.
125 * @valid: Callback to determine whether the given state can be entered.
126 * If %CONFIG_SOFTWARE_SUSPEND is set then %PM_SUSPEND_DISK is
127 * always valid and never passed to this call.
128 * If not assigned, all suspend states are advertised as valid
129 * in /sys/power/state (but can still be rejected by prepare or enter.)
130 *
131 * @prepare: Prepare the platform for the given suspend state. Can return a
132 * negative error code if necessary.
133 *
134 * @enter: Enter the given suspend state, must be assigned. Can return a
135 * negative error code if necessary.
136 *
137 * @finish: Called when the system has left the given state and all devices
138 * are resumed. The return value is ignored.
139 *
140 * @pm_disk_mode: Set to the disk method that the user should be able to
141 * configure for suspend-to-disk. Since %PM_DISK_SHUTDOWN,
142 * %PM_DISK_REBOOT, %PM_DISK_TEST and %PM_DISK_TESTPROC
143 * are always allowed, currently only %PM_DISK_PLATFORM
144 * makes sense. If the user then choses %PM_DISK_PLATFORM,
145 * the @prepare call will be called before suspending to disk
146 * (if present), the @enter call should be present and will
147 * be called after all state has been saved and the machine
148 * is ready to be shut down/suspended/..., and the @finish
149 * callback is called after state has been restored. All
150 * these calls are called with %PM_SUSPEND_DISK as the state.
151 */
123struct pm_ops { 152struct pm_ops {
124 suspend_disk_method_t pm_disk_mode;
125 int (*valid)(suspend_state_t state); 153 int (*valid)(suspend_state_t state);
126 int (*prepare)(suspend_state_t state); 154 int (*prepare)(suspend_state_t state);
127 int (*enter)(suspend_state_t state); 155 int (*enter)(suspend_state_t state);
128 int (*finish)(suspend_state_t state); 156 int (*finish)(suspend_state_t state);
157 suspend_disk_method_t pm_disk_mode;
129}; 158};
130 159
131extern void pm_set_ops(struct pm_ops *); 160/**
161 * pm_set_ops - set platform dependent power management ops
162 * @pm_ops: The new power management operations to set.
163 */
164extern void pm_set_ops(struct pm_ops *pm_ops);
132extern struct pm_ops *pm_ops; 165extern struct pm_ops *pm_ops;
133extern int pm_suspend(suspend_state_t state); 166extern int pm_suspend(suspend_state_t state);
134 167
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index f45450b295c0..21805b500aa2 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -17,6 +17,7 @@
17struct kobject; 17struct kobject;
18struct module; 18struct module;
19struct nameidata; 19struct nameidata;
20struct dentry;
20 21
21struct attribute { 22struct attribute {
22 const char * name; 23 const char * name;
@@ -68,18 +69,6 @@ struct sysfs_ops {
68 ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t); 69 ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t);
69}; 70};
70 71
71struct sysfs_dirent {
72 atomic_t s_count;
73 struct list_head s_sibling;
74 struct list_head s_children;
75 void * s_element;
76 int s_type;
77 umode_t s_mode;
78 struct dentry * s_dentry;
79 struct iattr * s_iattr;
80 atomic_t s_event;
81};
82
83#define SYSFS_ROOT 0x0001 72#define SYSFS_ROOT 0x0001
84#define SYSFS_DIR 0x0002 73#define SYSFS_DIR 0x0002
85#define SYSFS_KOBJ_ATTR 0x0004 74#define SYSFS_KOBJ_ATTR 0x0004
diff --git a/kernel/kmod.c b/kernel/kmod.c
index 9f923f8ce6a0..796276141e51 100644
--- a/kernel/kmod.c
+++ b/kernel/kmod.c
@@ -36,8 +36,6 @@
36#include <linux/resource.h> 36#include <linux/resource.h>
37#include <asm/uaccess.h> 37#include <asm/uaccess.h>
38 38
39extern int delete_module(const char *name, unsigned int flags);
40
41extern int max_threads; 39extern int max_threads;
42 40
43static struct workqueue_struct *khelper_wq; 41static struct workqueue_struct *khelper_wq;
@@ -48,7 +46,6 @@ static struct workqueue_struct *khelper_wq;
48 modprobe_path is set via /proc/sys. 46 modprobe_path is set via /proc/sys.
49*/ 47*/
50char modprobe_path[KMOD_PATH_LEN] = "/sbin/modprobe"; 48char modprobe_path[KMOD_PATH_LEN] = "/sbin/modprobe";
51struct module_kobject kmod_mk;
52 49
53/** 50/**
54 * request_module - try to load a kernel module 51 * request_module - try to load a kernel module
@@ -78,11 +75,6 @@ int request_module(const char *fmt, ...)
78 static atomic_t kmod_concurrent = ATOMIC_INIT(0); 75 static atomic_t kmod_concurrent = ATOMIC_INIT(0);
79#define MAX_KMOD_CONCURRENT 50 /* Completely arbitrary value - KAO */ 76#define MAX_KMOD_CONCURRENT 50 /* Completely arbitrary value - KAO */
80 static int kmod_loop_msg; 77 static int kmod_loop_msg;
81 char modalias[16 + MODULE_NAME_LEN] = "MODALIAS=";
82 char *uevent_envp[2] = {
83 modalias,
84 NULL
85 };
86 78
87 va_start(args, fmt); 79 va_start(args, fmt);
88 ret = vsnprintf(module_name, MODULE_NAME_LEN, fmt, args); 80 ret = vsnprintf(module_name, MODULE_NAME_LEN, fmt, args);
@@ -90,12 +82,6 @@ int request_module(const char *fmt, ...)
90 if (ret >= MODULE_NAME_LEN) 82 if (ret >= MODULE_NAME_LEN)
91 return -ENAMETOOLONG; 83 return -ENAMETOOLONG;
92 84
93 strcpy(&modalias[strlen("MODALIAS=")], module_name);
94 kobject_uevent_env(&kmod_mk.kobj, KOBJ_CHANGE, uevent_envp);
95
96 if (modprobe_path[0] == '\0')
97 goto out;
98
99 /* If modprobe needs a service that is in a module, we get a recursive 85 /* If modprobe needs a service that is in a module, we get a recursive
100 * loop. Limit the number of running kmod threads to max_threads/2 or 86 * loop. Limit the number of running kmod threads to max_threads/2 or
101 * MAX_KMOD_CONCURRENT, whichever is the smaller. A cleaner method 87 * MAX_KMOD_CONCURRENT, whichever is the smaller. A cleaner method
@@ -122,115 +108,9 @@ int request_module(const char *fmt, ...)
122 108
123 ret = call_usermodehelper(modprobe_path, argv, envp, 1); 109 ret = call_usermodehelper(modprobe_path, argv, envp, 1);
124 atomic_dec(&kmod_concurrent); 110 atomic_dec(&kmod_concurrent);
125out:
126 return ret; 111 return ret;
127} 112}
128EXPORT_SYMBOL(request_module); 113EXPORT_SYMBOL(request_module);
129
130static ssize_t store_mod_request(struct module_attribute *mattr,
131 struct module *mod,
132 const char *buffer, size_t count)
133{
134 char name[MODULE_NAME_LEN];
135 int ret;
136
137 if (count < 1 || count+1 > MODULE_NAME_LEN)
138 return -EINVAL;
139 memcpy(name, buffer, count);
140 name[count] = '\0';
141 if (name[count-1] == '\n')
142 name[count-1] = '\0';
143
144 ret = request_module(name);
145 if (ret < 0)
146 return ret;
147 return count;
148}
149
150static struct module_attribute mod_request = {
151 .attr = { .name = "mod_request", .mode = S_IWUSR, .owner = THIS_MODULE },
152 .store = store_mod_request,
153};
154
155#ifdef CONFIG_MODULE_UNLOAD
156static ssize_t store_mod_unload(struct module_attribute *mattr,
157 struct module *mod,
158 const char *buffer, size_t count)
159{
160 char name[MODULE_NAME_LEN];
161 int ret;
162
163 if (count < 1 || count+1 > MODULE_NAME_LEN)
164 return -EINVAL;
165 memcpy(name, buffer, count);
166 name[count] = '\0';
167 if (name[count-1] == '\n')
168 name[count-1] = '\0';
169
170 ret = delete_module(name, O_NONBLOCK);
171 if (ret < 0)
172 return ret;
173 return count;
174}
175
176static struct module_attribute mod_unload = {
177 .attr = { .name = "mod_unload", .mode = S_IWUSR, .owner = THIS_MODULE },
178 .store = store_mod_unload,
179};
180#endif
181
182static ssize_t show_mod_request_helper(struct module_attribute *mattr,
183 struct module *mod,
184 char *buffer)
185{
186 return sprintf(buffer, "%s\n", modprobe_path);
187}
188
189static ssize_t store_mod_request_helper(struct module_attribute *mattr,
190 struct module *mod,
191 const char *buffer, size_t count)
192{
193 if (count < 1 || count+1 > KMOD_PATH_LEN)
194 return -EINVAL;
195 memcpy(modprobe_path, buffer, count);
196 modprobe_path[count] = '\0';
197 if (modprobe_path[count-1] == '\n')
198 modprobe_path[count-1] = '\0';
199 return count;
200}
201
202static struct module_attribute mod_request_helper = {
203 .attr = {
204 .name = "mod_request_helper",
205 .mode = S_IWUSR | S_IRUGO,
206 .owner = THIS_MODULE
207 },
208 .show = show_mod_request_helper,
209 .store = store_mod_request_helper,
210};
211
212void __init kmod_sysfs_init(void)
213{
214 int ret;
215
216 kmod_mk.mod = THIS_MODULE;
217 kobj_set_kset_s(&kmod_mk, module_subsys);
218 kobject_set_name(&kmod_mk.kobj, "kmod");
219 kobject_init(&kmod_mk.kobj);
220 ret = kobject_add(&kmod_mk.kobj);
221 if (ret < 0)
222 goto out;
223
224 ret = sysfs_create_file(&kmod_mk.kobj, &mod_request_helper.attr);
225 ret = sysfs_create_file(&kmod_mk.kobj, &mod_request.attr);
226#ifdef CONFIG_MODULE_UNLOAD
227 ret = sysfs_create_file(&kmod_mk.kobj, &mod_unload.attr);
228#endif
229
230 kobject_uevent(&kmod_mk.kobj, KOBJ_ADD);
231out:
232 return;
233}
234#endif /* CONFIG_KMOD */ 114#endif /* CONFIG_KMOD */
235 115
236struct subprocess_info { 116struct subprocess_info {
diff --git a/kernel/module.c b/kernel/module.c
index 8c25b1a04fa6..f77e893e4620 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -653,11 +653,20 @@ static void wait_for_zero_refcount(struct module *mod)
653 mutex_lock(&module_mutex); 653 mutex_lock(&module_mutex);
654} 654}
655 655
656int delete_module(const char *name, unsigned int flags) 656asmlinkage long
657sys_delete_module(const char __user *name_user, unsigned int flags)
657{ 658{
658 struct module *mod; 659 struct module *mod;
660 char name[MODULE_NAME_LEN];
659 int ret, forced = 0; 661 int ret, forced = 0;
660 662
663 if (!capable(CAP_SYS_MODULE))
664 return -EPERM;
665
666 if (strncpy_from_user(name, name_user, MODULE_NAME_LEN-1) < 0)
667 return -EFAULT;
668 name[MODULE_NAME_LEN-1] = '\0';
669
661 if (mutex_lock_interruptible(&module_mutex) != 0) 670 if (mutex_lock_interruptible(&module_mutex) != 0)
662 return -EINTR; 671 return -EINTR;
663 672
@@ -718,21 +727,6 @@ int delete_module(const char *name, unsigned int flags)
718 return ret; 727 return ret;
719} 728}
720 729
721asmlinkage long
722sys_delete_module(const char __user *name_user, unsigned int flags)
723{
724 char name[MODULE_NAME_LEN];
725
726 if (!capable(CAP_SYS_MODULE))
727 return -EPERM;
728
729 if (strncpy_from_user(name, name_user, MODULE_NAME_LEN-1) < 0)
730 return -EFAULT;
731 name[MODULE_NAME_LEN-1] = '\0';
732
733 return delete_module(name, flags);
734}
735
736static void print_unload_info(struct seq_file *m, struct module *mod) 730static void print_unload_info(struct seq_file *m, struct module *mod)
737{ 731{
738 struct module_use *use; 732 struct module_use *use;
@@ -2425,6 +2419,12 @@ void module_remove_driver(struct device_driver *drv)
2425 kfree(driver_name); 2419 kfree(driver_name);
2426 } 2420 }
2427 } 2421 }
2422 /*
2423 * Undo the additional reference we added in module_add_driver()
2424 * via kset_find_obj()
2425 */
2426 if (drv->mod_name)
2427 kobject_put(&drv->kobj);
2428} 2428}
2429EXPORT_SYMBOL(module_remove_driver); 2429EXPORT_SYMBOL(module_remove_driver);
2430#endif 2430#endif
diff --git a/kernel/params.c b/kernel/params.c
index 7a751570b56d..e265b13195b1 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -707,7 +707,6 @@ static int __init param_sysfs_init(void)
707 } 707 }
708 708
709 param_sysfs_builtin(); 709 param_sysfs_builtin();
710 kmod_sysfs_init();
711 710
712 return 0; 711 return 0;
713} 712}
diff --git a/kernel/power/main.c b/kernel/power/main.c
index e1c413120469..a064dfd8877a 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -167,7 +167,10 @@ static inline int valid_state(suspend_state_t state)
167 if (state == PM_SUSPEND_DISK) 167 if (state == PM_SUSPEND_DISK)
168 return 1; 168 return 1;
169 169
170 if (pm_ops && pm_ops->valid && !pm_ops->valid(state)) 170 /* all other states need lowlevel support and need to be
171 * valid to the lowlevel implementation, no valid callback
172 * implies that all are valid. */
173 if (!pm_ops || (pm_ops->valid && !pm_ops->valid(state)))
171 return 0; 174 return 0;
172 return 1; 175 return 1;
173} 176}