diff options
-rw-r--r-- | drivers/base/class.c | 42 | ||||
-rw-r--r-- | drivers/base/core.c | 31 | ||||
-rw-r--r-- | drivers/pcmcia/hd64465_ss.c | 2 | ||||
-rw-r--r-- | drivers/pcmcia/m32r_cfc.c | 2 | ||||
-rw-r--r-- | drivers/pcmcia/m8xx_pcmcia.c | 2 | ||||
-rw-r--r-- | drivers/pcmcia/omap_cf.c | 2 | ||||
-rw-r--r-- | drivers/pcmcia/rsrc_mgr.c | 2 | ||||
-rw-r--r-- | drivers/pcmcia/vrc4171_card.c | 2 | ||||
-rw-r--r-- | fs/sysfs/sysfs.h | 11 | ||||
-rw-r--r-- | include/linux/device.h | 2 | ||||
-rw-r--r-- | include/linux/kmod.h | 2 | ||||
-rw-r--r-- | include/linux/pm.h | 37 | ||||
-rw-r--r-- | include/linux/sysfs.h | 13 | ||||
-rw-r--r-- | kernel/kmod.c | 120 | ||||
-rw-r--r-- | kernel/module.c | 32 | ||||
-rw-r--r-- | kernel/params.c | 1 | ||||
-rw-r--r-- | kernel/power/main.c | 5 |
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 | ||
843 | int 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 | |||
885 | struct class_device * class_device_get(struct class_device *class_dev) | 843 | struct 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 @@ | |||
1 | struct 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 | ||
2 | extern struct vfsmount * sysfs_mount; | 13 | extern struct vfsmount * sysfs_mount; |
3 | extern struct kmem_cache *sysfs_dir_cachep; | 14 | extern 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 *); | |||
294 | extern int __must_check class_device_add(struct class_device *); | 294 | extern int __must_check class_device_add(struct class_device *); |
295 | extern void class_device_del(struct class_device *); | 295 | extern void class_device_del(struct class_device *); |
296 | 296 | ||
297 | extern int class_device_rename(struct class_device *, char *); | ||
298 | |||
299 | extern struct class_device * class_device_get(struct class_device *); | 297 | extern struct class_device * class_device_get(struct class_device *); |
300 | extern void class_device_put(struct class_device *); | 298 | extern 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. */ |
31 | extern void kmod_sysfs_init(void); | ||
32 | extern int request_module(const char * name, ...) __attribute__ ((format (printf, 1, 2))); | 31 | extern int request_module(const char * name, ...) __attribute__ ((format (printf, 1, 2))); |
33 | #else | 32 | #else |
34 | static inline void kmod_sysfs_init(void) {}; | ||
35 | static inline int request_module(const char * name, ...) { return -ENOSYS; } | 33 | static 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 | */ | ||
123 | struct pm_ops { | 152 | struct 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 | ||
131 | extern 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 | */ | ||
164 | extern void pm_set_ops(struct pm_ops *pm_ops); | ||
132 | extern struct pm_ops *pm_ops; | 165 | extern struct pm_ops *pm_ops; |
133 | extern int pm_suspend(suspend_state_t state); | 166 | extern 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 @@ | |||
17 | struct kobject; | 17 | struct kobject; |
18 | struct module; | 18 | struct module; |
19 | struct nameidata; | 19 | struct nameidata; |
20 | struct dentry; | ||
20 | 21 | ||
21 | struct attribute { | 22 | struct 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 | ||
71 | struct 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 | ||
39 | extern int delete_module(const char *name, unsigned int flags); | ||
40 | |||
41 | extern int max_threads; | 39 | extern int max_threads; |
42 | 40 | ||
43 | static struct workqueue_struct *khelper_wq; | 41 | static 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 | */ |
50 | char modprobe_path[KMOD_PATH_LEN] = "/sbin/modprobe"; | 48 | char modprobe_path[KMOD_PATH_LEN] = "/sbin/modprobe"; |
51 | struct 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); |
125 | out: | ||
126 | return ret; | 111 | return ret; |
127 | } | 112 | } |
128 | EXPORT_SYMBOL(request_module); | 113 | EXPORT_SYMBOL(request_module); |
129 | |||
130 | static 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 | |||
150 | static 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 | ||
156 | static 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 | |||
176 | static 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 | |||
182 | static 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 | |||
189 | static 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 | |||
202 | static 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 | |||
212 | void __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); | ||
231 | out: | ||
232 | return; | ||
233 | } | ||
234 | #endif /* CONFIG_KMOD */ | 114 | #endif /* CONFIG_KMOD */ |
235 | 115 | ||
236 | struct subprocess_info { | 116 | struct 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 | ||
656 | int delete_module(const char *name, unsigned int flags) | 656 | asmlinkage long |
657 | sys_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 | ||
721 | asmlinkage long | ||
722 | sys_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 | |||
736 | static void print_unload_info(struct seq_file *m, struct module *mod) | 730 | static 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 | } |
2429 | EXPORT_SYMBOL(module_remove_driver); | 2429 | EXPORT_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 | } |