Commit 5fe8252f authored by Linus Torvalds's avatar Linus Torvalds

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:
  sysfs: fix build errors: uevent with CONFIG_SYSFS=n
  pcmcia: some class_device fallout
  Driver core: device_add_attrs() cleanup
  debugfs: Remove misleading comments.
  debugfs: implement symbolic links
  Driver: remove redundant kobject_unregister checks
  kobject: kobj->k_name verification fix
  serial: Add PCMCIA IDs for Quatech DSP-100 dual RS232 adapter.
  Driver core: let request_module() send a /sys/modules/kmod/-uevent
  Driver.h copyright update
parents 460223d2 ef665c1a
...@@ -324,27 +324,25 @@ int bus_for_each_drv(struct bus_type * bus, struct device_driver * start, ...@@ -324,27 +324,25 @@ int bus_for_each_drv(struct bus_type * bus, struct device_driver * start,
return error; return error;
} }
static int device_add_attrs(struct bus_type * bus, struct device * dev) static int device_add_attrs(struct bus_type *bus, struct device *dev)
{ {
int error = 0; int error = 0;
int i; int i;
if (bus->dev_attrs) { if (!bus->dev_attrs)
for (i = 0; attr_name(bus->dev_attrs[i]); i++) { return 0;
error = device_create_file(dev,&bus->dev_attrs[i]);
if (error) for (i = 0; attr_name(bus->dev_attrs[i]); i++) {
goto Err; error = device_create_file(dev,&bus->dev_attrs[i]);
if (error) {
while (--i >= 0)
device_remove_file(dev, &bus->dev_attrs[i]);
break;
} }
} }
Done:
return error; return error;
Err:
while (--i >= 0)
device_remove_file(dev,&bus->dev_attrs[i]);
goto Done;
} }
static void device_remove_attrs(struct bus_type * bus, struct device * dev) static void device_remove_attrs(struct bus_type * bus, struct device * dev)
{ {
int i; int i;
......
...@@ -163,8 +163,7 @@ int class_register(struct class * cls) ...@@ -163,8 +163,7 @@ int class_register(struct class * cls)
void class_unregister(struct class * cls) void class_unregister(struct class * cls)
{ {
pr_debug("device class '%s': unregistering\n", cls->name); pr_debug("device class '%s': unregistering\n", cls->name);
if (cls->virtual_dir) kobject_unregister(cls->virtual_dir);
kobject_unregister(cls->virtual_dir);
remove_class_attrs(cls); remove_class_attrs(cls);
subsystem_unregister(&cls->subsys); subsystem_unregister(&cls->subsys);
} }
......
...@@ -277,7 +277,7 @@ static int __init at91_cf_probe(struct platform_device *pdev) ...@@ -277,7 +277,7 @@ static int __init at91_cf_probe(struct platform_device *pdev)
board->det_pin, board->irq_pin); board->det_pin, board->irq_pin);
cf->socket.owner = THIS_MODULE; cf->socket.owner = THIS_MODULE;
cf->socket.dev.dev = &pdev->dev; cf->socket.dev.parent = &pdev->dev;
cf->socket.ops = &at91_cf_ops; cf->socket.ops = &at91_cf_ops;
cf->socket.resource_ops = &pccard_static_ops; cf->socket.resource_ops = &pccard_static_ops;
cf->socket.features = SS_CAP_PCCARD | SS_CAP_STATIC_MAP cf->socket.features = SS_CAP_PCCARD | SS_CAP_STATIC_MAP
......
...@@ -478,7 +478,7 @@ dump_bits(char **p, const char *prefix, unsigned int val, struct bittbl *bits, i ...@@ -478,7 +478,7 @@ dump_bits(char **p, const char *prefix, unsigned int val, struct bittbl *bits, i
* *
* Returns: the number of characters added to the buffer * Returns: the number of characters added to the buffer
*/ */
static ssize_t show_status(struct device *dev, char *buf) static ssize_t show_status(struct device *dev, struct device_attribute *attr, char *buf)
{ {
struct soc_pcmcia_socket *skt = struct soc_pcmcia_socket *skt =
container_of(dev, struct soc_pcmcia_socket, socket.dev); container_of(dev, struct soc_pcmcia_socket, socket.dev);
...@@ -501,7 +501,7 @@ static ssize_t show_status(struct device *dev, char *buf) ...@@ -501,7 +501,7 @@ static ssize_t show_status(struct device *dev, char *buf)
return p-buf; return p-buf;
} }
static CLASS_DEVICE_ATTR(status, S_IRUGO, show_status, NULL); static DEVICE_ATTR(status, S_IRUGO, show_status, NULL);
static struct pccard_operations soc_common_pcmcia_operations = { static struct pccard_operations soc_common_pcmcia_operations = {
...@@ -660,7 +660,7 @@ int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops ...@@ -660,7 +660,7 @@ int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops
skt->socket.ops = &soc_common_pcmcia_operations; skt->socket.ops = &soc_common_pcmcia_operations;
skt->socket.owner = ops->owner; skt->socket.owner = ops->owner;
skt->socket.dev.dev = dev; skt->socket.dev.parent = dev;
init_timer(&skt->poll_timer); init_timer(&skt->poll_timer);
skt->poll_timer.function = soc_common_pcmcia_poll_event; skt->poll_timer.function = soc_common_pcmcia_poll_event;
...@@ -747,7 +747,7 @@ int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops ...@@ -747,7 +747,7 @@ int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops
add_timer(&skt->poll_timer); add_timer(&skt->poll_timer);
device_create_file(&skt->socket.dev, &device_attr_status); device_create_file(&skt->socket.dev, &dev_attr_status);
} }
dev_set_drvdata(dev, sinfo); dev_set_drvdata(dev, sinfo);
......
...@@ -246,6 +246,10 @@ static const struct serial_quirk quirks[] = { ...@@ -246,6 +246,10 @@ static const struct serial_quirk quirks[] = {
.manfid = MANFID_QUATECH, .manfid = MANFID_QUATECH,
.prodid = PRODID_QUATECH_DUAL_RS232_D1, .prodid = PRODID_QUATECH_DUAL_RS232_D1,
.multi = 2, .multi = 2,
}, {
.manfid = MANFID_QUATECH,
.prodid = PRODID_QUATECH_DUAL_RS232_G,
.multi = 2,
}, { }, {
.manfid = MANFID_QUATECH, .manfid = MANFID_QUATECH,
.prodid = PRODID_QUATECH_QUAD_RS232, .prodid = PRODID_QUATECH_QUAD_RS232,
...@@ -891,6 +895,7 @@ static struct pcmcia_device_id serial_ids[] = { ...@@ -891,6 +895,7 @@ static struct pcmcia_device_id serial_ids[] = {
PCMCIA_DEVICE_PROD_ID12("OEM ", "C288MX ", 0xb572d360, 0xd2385b7a), PCMCIA_DEVICE_PROD_ID12("OEM ", "C288MX ", 0xb572d360, 0xd2385b7a),
PCMCIA_DEVICE_PROD_ID12("PCMCIA ", "C336MX ", 0x99bcafe9, 0xaa25bcab), PCMCIA_DEVICE_PROD_ID12("PCMCIA ", "C336MX ", 0x99bcafe9, 0xaa25bcab),
PCMCIA_DEVICE_PROD_ID12("Quatech Inc", "PCMCIA Dual RS-232 Serial Port Card", 0xc4420b35, 0x92abc92f), PCMCIA_DEVICE_PROD_ID12("Quatech Inc", "PCMCIA Dual RS-232 Serial Port Card", 0xc4420b35, 0x92abc92f),
PCMCIA_DEVICE_PROD_ID12("Quatech Inc", "Dual RS-232 Serial Port PC Card", 0xc4420b35, 0x031a380d),
PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "PCMCIA", "EN2218-LAN/MODEM", 0x281f1c5d, 0x570f348e, "PCMLM28.cis"), PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "PCMCIA", "EN2218-LAN/MODEM", 0x281f1c5d, 0x570f348e, "PCMLM28.cis"),
PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "PCMCIA", "UE2218-LAN/MODEM", 0x281f1c5d, 0x6fdcacee, "PCMLM28.cis"), PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "PCMCIA", "UE2218-LAN/MODEM", 0x281f1c5d, 0x6fdcacee, "PCMLM28.cis"),
PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "PCMLM28.cis"), PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "PCMLM28.cis"),
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/pagemap.h> #include <linux/pagemap.h>
#include <linux/namei.h>
#include <linux/debugfs.h> #include <linux/debugfs.h>
static ssize_t default_read_file(struct file *file, char __user *buf, static ssize_t default_read_file(struct file *file, char __user *buf,
...@@ -44,6 +45,17 @@ const struct file_operations debugfs_file_operations = { ...@@ -44,6 +45,17 @@ const struct file_operations debugfs_file_operations = {
.open = default_open, .open = default_open,
}; };
static void *debugfs_follow_link(struct dentry *dentry, struct nameidata *nd)
{
nd_set_link(nd, dentry->d_inode->i_private);
return NULL;
}
const struct inode_operations debugfs_link_operations = {
.readlink = generic_readlink,
.follow_link = debugfs_follow_link,
};
static void debugfs_u8_set(void *data, u64 val) static void debugfs_u8_set(void *data, u64 val)
{ {
*(u8 *)data = val; *(u8 *)data = val;
......
...@@ -25,11 +25,13 @@ ...@@ -25,11 +25,13 @@
#include <linux/namei.h> #include <linux/namei.h>
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/fsnotify.h> #include <linux/fsnotify.h>
#include <linux/string.h>
#define DEBUGFS_MAGIC 0x64626720 #define DEBUGFS_MAGIC 0x64626720
/* declared over in file.c */ /* declared over in file.c */
extern struct file_operations debugfs_file_operations; extern struct file_operations debugfs_file_operations;
extern struct inode_operations debugfs_link_operations;
static struct vfsmount *debugfs_mount; static struct vfsmount *debugfs_mount;
static int debugfs_mount_count; static int debugfs_mount_count;
...@@ -51,6 +53,9 @@ static struct inode *debugfs_get_inode(struct super_block *sb, int mode, dev_t d ...@@ -51,6 +53,9 @@ static struct inode *debugfs_get_inode(struct super_block *sb, int mode, dev_t d
case S_IFREG: case S_IFREG:
inode->i_fop = &debugfs_file_operations; inode->i_fop = &debugfs_file_operations;
break; break;
case S_IFLNK:
inode->i_op = &debugfs_link_operations;
break;
case S_IFDIR: case S_IFDIR:
inode->i_op = &simple_dir_inode_operations; inode->i_op = &simple_dir_inode_operations;
inode->i_fop = &simple_dir_operations; inode->i_fop = &simple_dir_operations;
...@@ -96,6 +101,12 @@ static int debugfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) ...@@ -96,6 +101,12 @@ static int debugfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
return res; return res;
} }
static int debugfs_link(struct inode *dir, struct dentry *dentry, int mode)
{
mode = (mode & S_IALLUGO) | S_IFLNK;
return debugfs_mknod(dir, dentry, mode, 0);
}
static int debugfs_create(struct inode *dir, struct dentry *dentry, int mode) static int debugfs_create(struct inode *dir, struct dentry *dentry, int mode)
{ {
int res; int res;
...@@ -158,10 +169,17 @@ static int debugfs_create_by_name(const char *name, mode_t mode, ...@@ -158,10 +169,17 @@ static int debugfs_create_by_name(const char *name, mode_t mode,
mutex_lock(&parent->d_inode->i_mutex); mutex_lock(&parent->d_inode->i_mutex);
*dentry = lookup_one_len(name, parent, strlen(name)); *dentry = lookup_one_len(name, parent, strlen(name));
if (!IS_ERR(*dentry)) { if (!IS_ERR(*dentry)) {
if ((mode & S_IFMT) == S_IFDIR) switch (mode & S_IFMT) {
case S_IFDIR:
error = debugfs_mkdir(parent->d_inode, *dentry, mode); error = debugfs_mkdir(parent->d_inode, *dentry, mode);
else break;
case S_IFLNK:
error = debugfs_link(parent->d_inode, *dentry, mode);
break;
default:
error = debugfs_create(parent->d_inode, *dentry, mode); error = debugfs_create(parent->d_inode, *dentry, mode);
break;
}
dput(*dentry); dput(*dentry);
} else } else
error = PTR_ERR(*dentry); error = PTR_ERR(*dentry);
...@@ -194,9 +212,7 @@ static int debugfs_create_by_name(const char *name, mode_t mode, ...@@ -194,9 +212,7 @@ static int debugfs_create_by_name(const char *name, mode_t mode,
* you are responsible here.) If an error occurs, %NULL will be returned. * 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 * 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 * returned.
* %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling
* code.
*/ */
struct dentry *debugfs_create_file(const char *name, mode_t mode, struct dentry *debugfs_create_file(const char *name, mode_t mode,
struct dentry *parent, void *data, struct dentry *parent, void *data,
...@@ -246,9 +262,7 @@ EXPORT_SYMBOL_GPL(debugfs_create_file); ...@@ -246,9 +262,7 @@ EXPORT_SYMBOL_GPL(debugfs_create_file);
* you are responsible here.) If an error occurs, %NULL will be returned. * 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 * 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 * returned.
* %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling
* code.
*/ */
struct dentry *debugfs_create_dir(const char *name, struct dentry *parent) struct dentry *debugfs_create_dir(const char *name, struct dentry *parent)
{ {
...@@ -258,6 +272,47 @@ struct dentry *debugfs_create_dir(const char *name, struct dentry *parent) ...@@ -258,6 +272,47 @@ struct dentry *debugfs_create_dir(const char *name, struct dentry *parent)
} }
EXPORT_SYMBOL_GPL(debugfs_create_dir); EXPORT_SYMBOL_GPL(debugfs_create_dir);
/**
* debugfs_create_symlink- create a symbolic link in the debugfs filesystem
* @name: a pointer to a string containing the name of the symbolic link to
* create.
* @parent: a pointer to the parent dentry for this symbolic link. This
* should be a directory dentry if set. If this paramater is NULL,
* then the symbolic link will be created in the root of the debugfs
* filesystem.
* @target: a pointer to a string containing the path to the target of the
* symbolic link.
*
* This function creates a symbolic link with the given name in debugfs that
* links to the given target path.
*
* This function will return a pointer to a dentry if it succeeds. This
* pointer must be passed to the debugfs_remove() function when the symbolic
* link 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.
*/
struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent,
const char *target)
{
struct dentry *result;
char *link;
link = kstrdup(target, GFP_KERNEL);
if (!link)
return NULL;
result = debugfs_create_file(name, S_IFLNK | S_IRWXUGO, parent, link,
NULL);
if (!result)
kfree(link);
return result;
}
EXPORT_SYMBOL_GPL(debugfs_create_symlink);
/** /**
* debugfs_remove - removes a file or directory from the debugfs filesystem * debugfs_remove - removes a file or directory from the debugfs filesystem
* @dentry: a pointer to a the dentry of the file or directory to be * @dentry: a pointer to a the dentry of the file or directory to be
...@@ -287,15 +342,22 @@ void debugfs_remove(struct dentry *dentry) ...@@ -287,15 +342,22 @@ void debugfs_remove(struct dentry *dentry)
if (debugfs_positive(dentry)) { if (debugfs_positive(dentry)) {
if (dentry->d_inode) { if (dentry->d_inode) {
dget(dentry); dget(dentry);
if (S_ISDIR(dentry->d_inode->i_mode)) { switch (dentry->d_inode->i_mode & S_IFMT) {
case S_IFDIR:
ret = simple_rmdir(parent->d_inode, dentry); ret = simple_rmdir(parent->d_inode, dentry);
if (ret) if (ret)
printk(KERN_ERR printk(KERN_ERR
"DebugFS rmdir on %s failed : " "DebugFS rmdir on %s failed : "
"directory not empty.\n", "directory not empty.\n",
dentry->d_name.name); dentry->d_name.name);
} else break;
case S_IFLNK:
kfree(dentry->d_inode->i_private);
/* fall through */
default:
simple_unlink(parent->d_inode, dentry); simple_unlink(parent->d_inode, dentry);
break;
}
if (!ret) if (!ret)
d_delete(dentry); d_delete(dentry);
dput(dentry); dput(dentry);
......
...@@ -358,8 +358,7 @@ void delete_partition(struct gendisk *disk, int part) ...@@ -358,8 +358,7 @@ void delete_partition(struct gendisk *disk, int part)
p->ios[0] = p->ios[1] = 0; p->ios[0] = p->ios[1] = 0;
p->sectors[0] = p->sectors[1] = 0; p->sectors[0] = p->sectors[1] = 0;
sysfs_remove_link(&p->kobj, "subsystem"); sysfs_remove_link(&p->kobj, "subsystem");
if (p->holder_dir) kobject_unregister(p->holder_dir);
kobject_unregister(p->holder_dir);
kobject_uevent(&p->kobj, KOBJ_REMOVE); kobject_uevent(&p->kobj, KOBJ_REMOVE);
kobject_del(&p->kobj); kobject_del(&p->kobj);
kobject_put(&p->kobj); kobject_put(&p->kobj);
...@@ -603,10 +602,8 @@ void del_gendisk(struct gendisk *disk) ...@@ -603,10 +602,8 @@ void del_gendisk(struct gendisk *disk)
disk->stamp = 0; disk->stamp = 0;
kobject_uevent(&disk->kobj, KOBJ_REMOVE); kobject_uevent(&disk->kobj, KOBJ_REMOVE);
if (disk->holder_dir) kobject_unregister(disk->holder_dir);
kobject_unregister(disk->holder_dir); kobject_unregister(disk->slave_dir);
if (disk->slave_dir)
kobject_unregister(disk->slave_dir);
if (disk->driverfs_dev) { if (disk->driverfs_dev) {
char *disk_name = make_block_name(disk); char *disk_name = make_block_name(disk);
sysfs_remove_link(&disk->kobj, "device"); sysfs_remove_link(&disk->kobj, "device");
......
...@@ -33,6 +33,9 @@ struct dentry *debugfs_create_file(const char *name, mode_t mode, ...@@ -33,6 +33,9 @@ struct dentry *debugfs_create_file(const char *name, mode_t mode,
struct dentry *debugfs_create_dir(const char *name, struct dentry *parent); struct dentry *debugfs_create_dir(const char *name, struct dentry *parent);
struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent,
const char *dest);
void debugfs_remove(struct dentry *dentry); void debugfs_remove(struct dentry *dentry);
struct dentry *debugfs_create_u8(const char *name, mode_t mode, struct dentry *debugfs_create_u8(const char *name, mode_t mode,
...@@ -70,6 +73,13 @@ static inline struct dentry *debugfs_create_dir(const char *name, ...@@ -70,6 +73,13 @@ static inline struct dentry *debugfs_create_dir(const char *name,
return ERR_PTR(-ENODEV); return ERR_PTR(-ENODEV);
} }
static inline struct dentry *debugfs_create_symlink(const char *name,
struct dentry *parent,
const char *dest)
{
return ERR_PTR(-ENODEV);
}
static inline void debugfs_remove(struct dentry *dentry) static inline void debugfs_remove(struct dentry *dentry)
{ } { }
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
* device.h - generic, centralized driver model * device.h - generic, centralized driver model
* *
* Copyright (c) 2001-2003 Patrick Mochel <mochel@osdl.org> * Copyright (c) 2001-2003 Patrick Mochel <mochel@osdl.org>
* Copyright (c) 2004-2007 Greg Kroah-Hartman <gregkh@suse.de>
* *
* This file is released under the GPLv2 * This file is released under the GPLv2
* *
......
...@@ -28,8 +28,10 @@ ...@@ -28,8 +28,10 @@
#ifdef CONFIG_KMOD #ifdef CONFIG_KMOD
/* modprobe exit status on success, -ve on error. Return value /* modprobe exit status on success, -ve on error. Return value
* usually useless though. */ * usually useless though. */
extern void kmod_sysfs_init(void);
extern int request_module(const char * name, ...) __attribute__ ((format (printf, 1, 2))); extern int request_module(const char * name, ...) __attribute__ ((format (printf, 1, 2)));
#else #else
static inline void kmod_sysfs_init(void) {};
static inline int request_module(const char * name, ...) { return -ENOSYS; } static inline int request_module(const char * name, ...) { return -ENOSYS; }
#endif #endif
......
...@@ -76,8 +76,6 @@ void sort_extable(struct exception_table_entry *start, ...@@ -76,8 +76,6 @@ void sort_extable(struct exception_table_entry *start,
struct exception_table_entry *finish); struct exception_table_entry *finish);
void sort_main_extable(void); void sort_main_extable(void);
extern struct subsystem module_subsys;
#ifdef MODULE #ifdef MODULE
#define MODULE_GENERIC_TABLE(gtype,name) \ #define MODULE_GENERIC_TABLE(gtype,name) \
extern const struct gtype##_id __mod_##gtype##_table \ extern const struct gtype##_id __mod_##gtype##_table \
...@@ -467,10 +465,6 @@ int unregister_module_notifier(struct notifier_block * nb); ...@@ -467,10 +465,6 @@ int unregister_module_notifier(struct notifier_block * nb);
extern void print_modules(void); extern void print_modules(void);
struct device_driver;
void module_add_driver(struct module *, struct device_driver *);
void module_remove_driver(struct device_driver *);
#else /* !CONFIG_MODULES... */ #else /* !CONFIG_MODULES... */
#define EXPORT_SYMBOL(sym) #define EXPORT_SYMBOL(sym)
#define EXPORT_SYMBOL_GPL(sym) #define EXPORT_SYMBOL_GPL(sym)
...@@ -568,18 +562,59 @@ static inline void print_modules(void) ...@@ -568,18 +562,59 @@ static inline void print_modules(void)
{ {
} }
#endif /* CONFIG_MODULES */
struct device_driver; struct device_driver;
#ifdef CONFIG_SYSFS
struct module; struct module;
static inline void module_add_driver(struct module *module, struct device_driver *driver) extern struct subsystem module_subsys;
int mod_sysfs_init(struct module *mod);
int mod_sysfs_setup(struct module *mod,
struct kernel_param *kparam,
unsigned int num_params);
int module_add_modinfo_attrs(struct module *mod);
void module_remove_modinfo_attrs(struct module *mod);
#else /* !CONFIG_SYSFS */
static inline int mod_sysfs_init(struct module *mod)
{ {
return 0;
} }
static inline void module_remove_driver(struct device_driver *driver) static inline int mod_sysfs_setup(struct module *mod,
struct kernel_param *kparam,
unsigned int num_params)
{ {
return 0;
} }
#endif /* CONFIG_MODULES */ static inline int module_add_modinfo_attrs(struct module *mod)
{
return 0;
}
static inline void module_remove_modinfo_attrs(struct module *mod)
{ }
#endif /* CONFIG_SYSFS */
#if defined(CONFIG_SYSFS) && defined(CONFIG_MODULES)
void module_add_driver(struct module *mod, struct device_driver *drv);
void module_remove_driver(struct device_driver *drv);
#else /* not both CONFIG_SYSFS && CONFIG_MODULES */
static inline void module_add_driver(struct module *mod, struct device_driver *drv)
{ }
static inline void module_remove_driver(struct device_driver *drv)
{ }
#endif
#define symbol_request(x) try_then_request_module(symbol_get(x), "symbol:" #x) #define symbol_request(x) try_then_request_module(symbol_get(x), "symbol:" #x)
......
...@@ -169,10 +169,22 @@ extern int param_get_string(char *buffer, struct kernel_param *kp); ...@@ -169,10 +169,22 @@ extern int param_get_string(char *buffer, struct kernel_param *kp);
struct module; struct module;
#if defined(CONFIG_SYSFS) && defined(CONFIG_MODULES)
extern int module_param_sysfs_setup(struct module *mod, extern int module_param_sysfs_setup(struct module *mod,
struct kernel_param *kparam, struct kernel_param *kparam,
unsigned int num_params); unsigned int num_params);
extern void module_param_sysfs_remove(struct module *mod); extern void module_param_sysfs_remove(struct module *mod);
#else
static inline int module_param_sysfs_setup(struct module *mod,
struct kernel_param *kparam,
unsigned int num_params)
{
return 0;
}
static inline void module_param_sysfs_remove(struct module *mod)
{ }
#endif
#endif /* _LINUX_MODULE_PARAMS_H */ #endif /* _LINUX_MODULE_PARAMS_H */
...@@ -95,6 +95,7 @@ ...@@ -95,6 +95,7 @@
#define PRODID_QUATECH_DUAL_RS232 0x0012 #define PRODID_QUATECH_DUAL_RS232 0x0012
#define PRODID_QUATECH_DUAL_RS232_D1 0x0007 #define PRODID_QUATECH_DUAL_RS232_D1 0x0007
#define PRODID_QUATECH_DUAL_RS232_D2 0x0052 #define PRODID_QUATECH_DUAL_RS232_D2 0x0052
#define PRODID_QUATECH_DUAL_RS232_G 0x004d
#define PRODID_QUATECH_QUAD_RS232 0x001b #define PRODID_QUATECH_QUAD_RS232 0x001b
#define PRODID_QUATECH_DUAL_RS422 0x000e #define PRODID_QUATECH_DUAL_RS422 0x000e
#define PRODID_QUATECH_QUAD_RS422 0x0045 #define PRODID_QUATECH_QUAD_RS422 0x0045
......
...@@ -36,6 +36,8 @@ ...@@ -36,6 +36,8 @@
#include <linux/resource.h> #include <linux/resource.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
extern int delete_module(const char *name, unsigned int flags);
extern int max_threads; extern int max_threads;
static struct workqueue_struct *khelper_wq; static struct workqueue_struct *khelper_wq;
...@@ -46,6 +48,7 @@ static struct workqueue_struct *khelper_wq; ...@@ -46,6 +48,7 @@ static struct workqueue_struct *khelper_wq;
modprobe_path is set via /proc/sys. modprobe_path is set via /proc/sys.
*/ */
char modprobe_path[KMOD_PATH_LEN] = "/sbin/modprobe"; char modprobe_path[KMOD_PATH_LEN] = "/sbin/modprobe";
struct module_kobject kmod_mk;
/** /**
* request_module - try to load a kernel module * request_module - try to load a kernel module
...@@ -75,6 +78,11 @@ int request_module(const char *fmt, ...) ...@@ -75,6 +78,11 @@ int request_module(const char *fmt, ...)
static atomic_t kmod_concurrent = ATOMIC_INIT(0); static atomic_t kmod_concurrent = ATOMIC_INIT(0);
#define MAX_KMOD_CONCURRENT 50 /* Completely arbitrary value - KAO */ #define MAX_KMOD_CONCURRENT 50 /* Completely arbitrary value - KAO */
static int kmod_loop_msg; static int kmod_loop_msg;
char modalias[16 + MODULE_NAME_LEN] = "MODALIAS=";
char *uevent_envp[2] = {
modalias,
NULL
};
va_start(args, fmt); va_start(args, fmt);
ret = vsnprintf(module_name, MODULE_NAME_LEN, fmt, args); ret = vsnprintf(module_name, MODULE_NAME_LEN, fmt, args);
...@@ -82,6 +90,12 @@ int request_module(const char *fmt, ...) ...@@ -82,6 +90,12 @@ int request_module(const char *fmt, ...)
if (ret >= MODULE_NAME_LEN) if (ret >= MODULE_NAME_LEN)
return -ENAMETOOLONG; return -ENAMETOOLONG;
strcpy(&modalias[strlen("MODALIAS=")], module_name);
kobject_uevent_env(&kmod_mk.kobj, KOBJ_CHANGE, uevent_envp);
if (modprobe_path[0] == '\0')
goto out;
/* If modprobe needs a service that is in a module, we get a recursive /* If modprobe needs a service that is in a module, we get a recursive
* loop. Limit the number of running kmod threads to max_threads/2 or * loop. Limit the number of running kmod threads to max_threads/2 or
* MAX_KMOD_CONCURRENT, whichever is the smaller. A cleaner method * MAX_KMOD_CONCURRENT, whichever is the smaller. A cleaner method
...@@ -108,9 +122,115 @@ int request_module(const char *fmt, ...) ...@@ -108,9 +122,115 @@ int request_module(const char *fmt, ...)
ret = call_usermodehelper(modprobe_path, argv, envp, 1); ret = call_usermodehelper(modprobe_path, argv, envp, 1);
atomic_dec(&kmod_concurrent); atomic_dec(&kmod_concurrent);
out:
return ret; return ret;
} }
EXPORT_SYMBOL(request_module); EXPORT_SYMBOL(request_module);
static ssize_t store_mod_request(struct module_attribute *mattr,
struct module *mod,
const char *buffer, size_t count)
{
char name[MODULE_NAME_LEN];
int ret;
if (count < 1 || count+1 > MODULE_NAME_LEN)
return -EINVAL;
memcpy(name, buffer, count);
name[count] = '\0';
if (name[count-1] == '\n')
name[count-1] = '\0';
ret = request_module(name);
if (ret < 0)
return ret;
return count;
}
static struct module_attribute mod_request = {
.attr = { .name = "mod_request", .mode = S_IWUSR, .owner = THIS_MODULE },
.store = store_mod_request,
};
#ifdef CONFIG_MODULE_UNLOAD
static ssize_t store_mod_unload(struct module_attribute *mattr,
struct module *mod,
const char *buffer, size_t count)
{
char name[MODULE_NAME_LEN];
int ret;
if (count < 1 || count+1 > MODULE_NAME_LEN)
return -EINVAL;
memcpy(name, buffer, count);
name[count] = '\0';
if (name[count-1] == '\n')
name[count-1] = '\0';
ret = delete_module(name, O_NONBLOCK);
if (ret < 0)
return ret;
return count;
}
static struct module_attribute mod_unload = {
.attr = { .name = "mod_unload", .mode = S_IWUSR, .owner = THIS_MODULE },
.store = store_mod_unload,
};
#endif
static ssize_t show_mod_request_helper(struct module_attribute *mattr,
struct module *mod,
char *buffer)
{
return sprintf(buffer, "%s\n", modprobe_path);
}
static ssize_t store_mod_request_helper(struct module_attribute *mattr,
struct module *mod,
const char *buffer, size_t count)
{
if (count < 1 || count+1 > KMOD_PATH_LEN)
return -EINVAL;
memcpy(modprobe_path, buffer, count);
modprobe_path[count] = '\0';
if (modprobe_path[count-1] == '\n')
modprobe_path[count-1] = '\0';
return count;
}
static struct module_attribute mod_request_helper = {
.attr = {
.name = "mod_request_helper",
.mode = S_IWUSR | S_IRUGO,
.owner = THIS_MODULE
},
.show = show_mod_request_helper,
.store = store_mod_request_helper,
};
void __init kmod_sysfs_init(void)
{
int ret;
kmod_mk.mod = THIS_MODULE;
kobj_set_kset_s(&kmod_mk, module_subsys);
kobject_set_name(&kmod_mk.kobj, "kmod");
kobject_init(&kmod_mk.kobj);
ret = kobject_add(&kmod_mk.kobj);
if (ret < 0)
goto out;
ret = sysfs_create_file(&kmod_mk.kobj, &mod_request_helper.attr);
ret = sysfs_create_file(&kmod_mk.kobj, &mod_request.attr);
#ifdef CONFIG_MODULE_UNLOAD
ret = sysfs_create_file(&kmod_mk.kobj, &mod_unload.attr);
#endif
kobject_uevent(&kmod_mk.kobj, KOBJ_ADD);
out:
return;
}
#endif /* CONFIG_KMOD */ #endif /* CONFIG_KMOD */
struct subprocess_info { struct subprocess_info {
......
...@@ -653,20 +653,11 @@ static void wait_for_zero_refcount(struct module *mod) ...@@ -653,20 +653,11 @@ static void wait_for_zero_refcount(struct module *mod)
mutex_lock(&module_mutex); mutex_lock(&module_mutex);
} }
asmlinkage long int delete_module(const char *name, unsigned int flags)
sys_delete_module(const char __user *name_user, unsigned int flags)
{ {
struct module *mod; struct module *mod;
char name[MODULE_NAME_LEN];
int ret, forced = 0; int ret, forced = 0;
if (!capable(CAP_SYS_MODULE))
return -EPERM;
if (strncpy_from_user(name, name_user, MODULE_NAME_LEN-1) < 0)
return -EFAULT;
name[MODULE_NAME_LEN-1] = '\0';
if (mutex_lock_interruptible(&module_mutex) != 0) if (mutex_lock_interruptible(&module_mutex) != 0)
return -EINTR; return -EINTR;
...@@ -727,6 +718,21 @@ sys_delete_module(const char __user *name_user, unsigned int flags) ...@@ -727,6 +718,21 @@ sys_delete_module(const char __user *name_user, unsigned int flags)
return ret; return ret;
} }
asmlinkage long
sys_delete_module(const char __user *name_user, unsigned int flags)
{
char name[MODULE_NAME_LEN];
if (!capable(CAP_SYS_MODULE))
return -EPERM;
if (strncpy_from_user(name, name_user, MODULE_NAME_LEN-1) < 0)
return -EFAULT;
name[MODULE_NAME_LEN-1] = '\0';
return delete_module(name, flags);
}
static void print_unload_info(struct seq_file *m, struct module *mod) static void print_unload_info(struct seq_file *m, struct module *mod)
{ {
struct module_use *use; struct module_use *use;
...@@ -1068,7 +1074,8 @@ static inline void remove_sect_attrs(struct module *mod) ...@@ -1068,7 +1074,8 @@ static inline void remove_sect_attrs(struct module *mod)
} }
#endif /* CONFIG_KALLSYMS */ #endif /* CONFIG_KALLSYMS */
static int module_add_modinfo_attrs(struct module *mod) #ifdef CONFIG_SYSFS
int module_add_modinfo_attrs(struct module *mod)
{ {
struct module_attribute *attr; struct module_attribute *attr;
struct module_attribute *temp_attr; struct module_attribute *temp_attr;
...@@ -1094,7 +1101,7 @@ static int module_add_modinfo_attrs(struct module *mod) ...@@ -1094,7 +1101,7 @@ static int module_add_modinfo_attrs(struct module *mod)
return error; return error;
} }
static void module_remove_modinfo_attrs(struct module *mod) void module_remove_modinfo_attrs(struct module *mod)
{ {
struct module_attribute *attr; struct module_attribute *attr;
int i; int i;
...@@ -1109,8 +1116,10 @@ static void module_remove_modinfo_attrs(struct module *mod) ...@@ -1109,8 +1116,10 @@ static void module_remove_modinfo_attrs(struct module *mod)
} }
kfree(mod->modinfo_attrs); kfree(mod->modinfo_attrs);
} }
#endif
static int mod_sysfs_init(struct module *mod) #ifdef CONFIG_SYSFS
int mod_sysfs_init(struct module *mod)
{ {
int err; int err;
...@@ -1133,7 +1142,7 @@ static int mod_sysfs_init(struct module *mod) ...@@ -1133,7 +1142,7 @@ static int mod_sysfs_init(struct module *mod)
return err; return err;
} }
static int mod_sysfs_setup(struct module *mod, int mod_sysfs_setup(struct module *mod,
struct kernel_param *kparam, struct kernel_param *kparam,
unsigned int num_params) unsigned int num_params)
{ {
...@@ -1169,16 +1178,14 @@ static int mod_sysfs_setup(struct module *mod, ...@@ -1169,16 +1178,14 @@ static int mod_sysfs_setup(struct module *mod,
out: out:
return err; return err;
} }
#endif
static void mod_kobject_remove(struct module *mod) static void mod_kobject_remove(struct module *mod)
{ {
module_remove_modinfo_attrs(mod); module_remove_modinfo_attrs(mod);
module_param_sysfs_remove(mod); module_param_sysfs_remove(mod);
if (mod->mkobj.drivers_dir) kobject_unregister(mod->mkobj.drivers_dir);
kobject_unregister(mod->mkobj.drivers_dir); kobject_unregister(mod->holders_dir);
if (mod->holders_dir)
kobject_unregister(mod->holders_dir);
kobject_unregister(&mod->mkobj.kobj); kobject_unregister(&mod->mkobj.kobj);
} }
...@@ -2345,6 +2352,7 @@ void print_modules(void) ...@@ -2345,6 +2352,7 @@ void print_modules(void)
printk("\n"); printk("\n");
} }
#ifdef CONFIG_SYSFS
static char *make_driver_name(struct device_driver *drv) static char *make_driver_name(struct device_driver *drv)
{ {
char *driver_name; char *driver_name;
...@@ -2419,6 +2427,7 @@ void module_remove_driver(struct device_driver *drv) ...@@ -2419,6 +2427,7 @@ void module_remove_driver(struct device_driver *drv)
} }
} }
EXPORT_SYMBOL(module_remove_driver); EXPORT_SYMBOL(module_remove_driver);
#endif
#ifdef CONFIG_MODVERSIONS #ifdef CONFIG_MODVERSIONS
/* Generate the signature for struct module here, too, for modversions. */ /* Generate the signature for struct module here, too, for modversions. */
......
...@@ -30,8 +30,6 @@ ...@@ -30,8 +30,6 @@
#define DEBUGP(fmt, a...) #define DEBUGP(fmt, a...)
#endif #endif
static struct kobj_type module_ktype;
static inline char dash2underscore(char c) static inline char dash2underscore(char c)
{ {
if (c == '-') if (c == '-')
...@@ -391,6 +389,7 @@ struct module_param_attrs ...@@ -391,6 +389,7 @@ struct module_param_attrs
struct param_attribute attrs[0]; struct param_attribute attrs[0];
}; };
#ifdef CONFIG_SYSFS
#define to_param_attr(n) container_of(n, struct param_attribute, mattr); #define to_param_attr(n) container_of(n, struct param_attribute, mattr);
static ssize_t param_attr_show(struct module_attribute *mattr, static ssize_t param_attr_show(struct module_attribute *mattr,
...@@ -426,6 +425,7 @@ static ssize_t param_attr_store(struct module_attribute *mattr, ...@@ -426,6 +425,7 @@ static ssize_t param_attr_store(struct module_attribute *mattr,
return len; return len;
return err; return err;
} }
#endif
#ifdef CONFIG_MODULES #ifdef CONFIG_MODULES
#define __modinit #define __modinit
...@@ -433,6 +433,7 @@ static ssize_t param_attr_store(struct module_attribute *mattr, ...@@ -433,6 +433,7 @@ static ssize_t param_attr_store(struct module_attribute *mattr,
#define __modinit __init #define __modinit __init
#endif #endif
#ifdef CONFIG_SYSFS
/* /*
* param_sysfs_setup - setup sysfs support for one module or KBUILD_MODNAME * param_sysfs_setup - setup sysfs support for one module or KBUILD_MODNAME
* @mk: struct module_kobject (contains parent kobject) * @mk: struct module_kobject (contains parent kobject)
...@@ -500,9 +501,7 @@ param_sysfs_setup(struct module_kobject *mk, ...@@ -500,9 +501,7 @@ param_sysfs_setup(struct module_kobject *mk,
return mp; return mp;
} }
#ifdef CONFIG_MODULES #ifdef CONFIG_MODULES
/* /*
* module_param_sysfs_setup - setup sysfs support for one module * module_param_sysfs_setup - setup sysfs support for one module
* @mod: module * @mod: module
...@@ -625,7 +624,6 @@ static void __init param_sysfs_builtin(void) ...@@ -625,7 +624,6 @@ static void __init param_sysfs_builtin(void)
/* module-related sysfs stuff */ /* module-related sysfs stuff */
#ifdef CONFIG_SYSFS
#define to_module_attr(n) container_of(n, struct module_attribute, attr); #define to_module_attr(n) container_of(n, struct module_attribute, attr);
#define to_module_kobject(n) container_of(n, struct module_kobject, kobj); #define to_module_kobject(n) container_of(n, struct module_kobject, kobj);
...@@ -673,6 +671,8 @@ static struct sysfs_ops module_sysfs_ops = { ...@@ -673,6 +671,8 @@ static struct sysfs_ops module_sysfs_ops = {
.store = module_attr_store, .store = module_attr_store,
}; };
static struct kobj_type module_ktype;
static int uevent_filter(struct kset *kset, struct kobject *kobj) static int uevent_filter(struct kset *kset, struct kobject *kobj)
{ {
struct kobj_type *ktype = get_ktype(kobj); struct kobj_type *ktype = get_ktype(kobj);
...@@ -686,19 +686,12 @@ static struct kset_uevent_ops module_uevent_ops = { ...@@ -686,19 +686,12 @@ static struct kset_uevent_ops module_uevent_ops = {
.filter = uevent_filter, .filter = uevent_filter,
}; };
#else decl_subsys(module, &module_ktype, &module_uevent_ops);
static struct sysfs_ops module_sysfs_ops = {
.show = NULL,
.store = NULL,
};
#endif
static struct kobj_type module_ktype = { static struct kobj_type module_ktype = {
.sysfs_ops = &module_sysfs_ops, .sysfs_ops = &module_sysfs_ops,
}; };
decl_subsys(module, &module_ktype, &module_uevent_ops);
/* /*
* param_sysfs_init - wrapper for built-in params support * param_sysfs_init - wrapper for built-in params support
*/ */
...@@ -714,11 +707,21 @@ static int __init param_sysfs_init(void) ...@@ -714,11 +707,21 @@ static int __init param_sysfs_init(void)
} }
param_sysfs_builtin(); param_sysfs_builtin();
kmod_sysfs_init();
return 0; return 0;
} }
subsys_initcall(param_sysfs_init); subsys_initcall(param_sysfs_init);
#else
#if 0
static struct sysfs_ops module_sysfs_ops = {
.show = NULL,
.store = NULL,
};
#endif
#endif
EXPORT_SYMBOL(param_set_byte); EXPORT_SYMBOL(param_set_byte);
EXPORT_SYMBOL(param_get_byte); EXPORT_SYMBOL(param_get_byte);
EXPORT_SYMBOL(param_set_short); EXPORT_SYMBOL(param_set_short);
......
...@@ -171,7 +171,7 @@ int kobject_shadow_add(struct kobject * kobj, struct dentry *shadow_parent) ...@@ -171,7 +171,7 @@ int kobject_shadow_add(struct kobject * kobj, struct dentry *shadow_parent)
return -ENOENT; return -ENOENT;
if (!kobj->k_name) if (!kobj->k_name)
kobj->k_name = kobj->name; kobj->k_name = kobj->name;
if (!kobj->k_name) { if (!*kobj->k_name) {
pr_debug("kobject attempted to be registered with no name!\n"); pr_debug("kobject attempted to be registered with no name!\n");
WARN_ON(1); WARN_ON(1);
return -EINVAL; return -EINVAL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment