Commit 1a6f2a75 authored by Dmitry Torokhov's avatar Dmitry Torokhov Committed by Greg Kroah-Hartman

Driver core: allow certain drivers prohibit bind/unbind via sysfs

Platform drivers registered via platform_driver_probe() can be bound
to devices only once, upon registration, because discard their probe()
routines to save memory. Unbinding the driver through sysfs 'unbind'
leaves the device stranded and confuses users so let's not create
bind and unbind attributes for such drivers.
Signed-off-by: default avatarDmitry Torokhov <dtor@mail.ru>
Cc: Éric Piel <eric.piel@tremplin-utc.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 39acbc12
...@@ -689,15 +689,19 @@ int bus_add_driver(struct device_driver *drv) ...@@ -689,15 +689,19 @@ int bus_add_driver(struct device_driver *drv)
printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n", printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n",
__func__, drv->name); __func__, drv->name);
} }
if (!drv->suppress_bind_attrs) {
error = add_bind_files(drv); error = add_bind_files(drv);
if (error) { if (error) {
/* Ditto */ /* Ditto */
printk(KERN_ERR "%s: add_bind_files(%s) failed\n", printk(KERN_ERR "%s: add_bind_files(%s) failed\n",
__func__, drv->name); __func__, drv->name);
} }
}
kobject_uevent(&priv->kobj, KOBJ_ADD); kobject_uevent(&priv->kobj, KOBJ_ADD);
return 0; return 0;
out_unregister: out_unregister:
kfree(drv->p); kfree(drv->p);
drv->p = NULL; drv->p = NULL;
...@@ -720,6 +724,7 @@ void bus_remove_driver(struct device_driver *drv) ...@@ -720,6 +724,7 @@ void bus_remove_driver(struct device_driver *drv)
if (!drv->bus) if (!drv->bus)
return; return;
if (!drv->suppress_bind_attrs)
remove_bind_files(drv); remove_bind_files(drv);
driver_remove_attrs(drv->bus, drv); driver_remove_attrs(drv->bus, drv);
driver_remove_file(drv, &driver_attr_uevent); driver_remove_file(drv, &driver_attr_uevent);
......
...@@ -521,11 +521,15 @@ int __init_or_module platform_driver_probe(struct platform_driver *drv, ...@@ -521,11 +521,15 @@ int __init_or_module platform_driver_probe(struct platform_driver *drv,
{ {
int retval, code; int retval, code;
/* make sure driver won't have bind/unbind attributes */
drv->driver.suppress_bind_attrs = true;
/* temporary section violation during probe() */ /* temporary section violation during probe() */
drv->probe = probe; drv->probe = probe;
retval = code = platform_driver_register(drv); retval = code = platform_driver_register(drv);
/* Fixup that section violation, being paranoid about code scanning /*
* Fixup that section violation, being paranoid about code scanning
* the list of drivers in order to probe new devices. Check to see * the list of drivers in order to probe new devices. Check to see
* if the probe was successful, and make sure any forced probes of * if the probe was successful, and make sure any forced probes of
* new devices fail. * new devices fail.
......
...@@ -126,6 +126,8 @@ struct device_driver { ...@@ -126,6 +126,8 @@ struct device_driver {
struct module *owner; struct module *owner;
const char *mod_name; /* used for built-in modules */ const char *mod_name; /* used for built-in modules */
bool suppress_bind_attrs; /* disables bind/unbind via sysfs */
int (*probe) (struct device *dev); int (*probe) (struct device *dev);
int (*remove) (struct device *dev); int (*remove) (struct device *dev);
void (*shutdown) (struct device *dev); void (*shutdown) (struct device *dev);
......
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