struct driver_attribute *attr)
{
int error;
- if (get_driver(drv)) {
+ if (drv)
error = sysfs_create_file(&drv->p->kobj, &attr->attr);
- put_driver(drv);
- } else
+ else
error = -EINVAL;
return error;
}
void driver_remove_file(struct device_driver *drv,
struct driver_attribute *attr)
{
- if (get_driver(drv)) {
+ if (drv)
sysfs_remove_file(&drv->p->kobj, &attr->attr);
- put_driver(drv);
- }
}
EXPORT_SYMBOL_GPL(driver_remove_file);
/**
* driver_add_kobj - add a kobject below the specified driver
+ * @drv: requesting device driver
+ * @kobj: kobject to add below this driver
+ * @fmt: format string that names the kobject
*
* You really don't want to do this, this is only here due to one looney
* iseries driver, go poke those developers if you are annoyed about
{
va_list args;
char *name;
+ int ret;
va_start(args, fmt);
name = kvasprintf(GFP_KERNEL, fmt, args);
if (!name)
return -ENOMEM;
- return kobject_add(kobj, &drv->p->kobj, "%s", name);
+ ret = kobject_add(kobj, &drv->p->kobj, "%s", name);
+ kfree(name);
+ return ret;
}
EXPORT_SYMBOL_GPL(driver_add_kobj);
int driver_register(struct device_driver *drv)
{
int ret;
+ struct device_driver *other;
if ((drv->bus->probe && drv->probe) ||
(drv->bus->remove && drv->remove) ||
(drv->bus->shutdown && drv->shutdown))
printk(KERN_WARNING "Driver '%s' needs updating - please use "
"bus_type methods\n", drv->name);
+
+ other = driver_find(drv->name, drv->bus);
+ if (other) {
+ put_driver(other);
+ printk(KERN_ERR "Error: Driver '%s' is already registered, "
+ "aborting...\n", drv->name);
+ return -EEXIST;
+ }
+
ret = bus_add_driver(drv);
if (ret)
return ret;