static char *kdbus_devnode_control(struct device *dev, umode_t *mode,
kuid_t *uid, kgid_t *gid)
{
- struct kdbus_domain *domain = dev_get_drvdata(dev);
+ struct kdbus_domain *domain = container_of(dev, struct kdbus_domain,
+ dev);
if (mode)
*mode = domain->mode;
*/
struct kdbus_domain *kdbus_domain_ref(struct kdbus_domain *domain)
{
- kref_get(&domain->kref);
+ get_device(&domain->dev);
return domain;
}
mutex_unlock(&domain->parent->lock);
}
- mutex_lock(&kdbus_subsys_lock);
- if (domain->dev) {
- device_unregister(domain->dev);
- domain->dev = NULL;
- }
-
if (domain->major > 0) {
+ mutex_lock(&kdbus_subsys_lock);
+
+ device_del(&domain->dev);
idr_remove(&kdbus_domain_major_idr, domain->major);
unregister_chrdev(domain->major, KBUILD_MODNAME);
domain->major = 0;
+
+ mutex_unlock(&kdbus_subsys_lock);
}
- mutex_unlock(&kdbus_subsys_lock);
/* disconnect all sub-domains */
for (;;) {
}
}
-static void __kdbus_domain_free(struct kref *kref)
+static void __kdbus_domain_free(struct device *dev)
{
- struct kdbus_domain *domain =
- container_of(kref, struct kdbus_domain, kref);
+ struct kdbus_domain *domain = container_of(dev, struct kdbus_domain,
+ dev);
BUG_ON(!domain->disconnected);
BUG_ON(!list_empty(&domain->domain_list));
*/
struct kdbus_domain *kdbus_domain_unref(struct kdbus_domain *domain)
{
- if (!domain)
- return NULL;
-
- kref_put(&domain->kref, __kdbus_domain_free);
+ if (domain)
+ put_device(&domain->dev);
return NULL;
}
if (!d)
return -ENOMEM;
+ d->disconnected = true;
INIT_LIST_HEAD(&d->bus_list);
INIT_LIST_HEAD(&d->domain_list);
- kref_init(&d->kref);
d->mode = mode;
idr_init(&d->idr);
mutex_init(&d->lock);
atomic64_set(&d->msg_seq_last, 0);
idr_init(&d->user_idr);
+ device_initialize(&d->dev);
+ d->dev.bus = &kdbus_subsys;
+ d->dev.type = &kdbus_devtype_control;
+ d->dev.release = __kdbus_domain_free;
+
/* compose name and path of base directory in /dev */
if (!parent) {
/* initial domain */
d->devpath = kstrdup(KBUILD_MODNAME, GFP_KERNEL);
if (!d->devpath) {
ret = -ENOMEM;
- goto exit_free;
+ goto exit_put;
}
mutex_lock(&kdbus_subsys_lock);
if (parent->disconnected) {
mutex_unlock(&parent->lock);
ret = -ESHUTDOWN;
- goto exit_free;
+ goto exit_put;
}
mutex_lock(&kdbus_subsys_lock);
d->name = kstrdup(name, GFP_KERNEL);
if (!d->name) {
- kfree(d->devpath);
ret = -ENOMEM;
goto exit_unlock;
}
/* get dynamic major */
ret = register_chrdev(0, d->devpath, &kdbus_device_ops);
if (ret < 0)
- goto exit_free_devpath;
+ goto exit_unlock;
d->major = ret;
+ d->dev.devt = MKDEV(d->major, 0);
+
+ ret = dev_set_name(&d->dev, "%s/control", d->devpath);
+ if (ret < 0)
+ goto exit_chrdev;
/*
* kdbus_device_ops' dev_t finds the domain in the major map,
/* get id for this domain */
d->id = ++kdbus_domain_seq_last;
- /* register control device for this domain */
- d->dev = kzalloc(sizeof(*d->dev), GFP_KERNEL);
- if (!d->dev) {
- ret = -ENOMEM;
- goto exit_idr;
- }
-
- dev_set_name(d->dev, "%s/control", d->devpath);
- d->dev->bus = &kdbus_subsys;
- d->dev->type = &kdbus_devtype_control;
- d->dev->devt = MKDEV(d->major, 0);
- dev_set_drvdata(d->dev, d);
- ret = device_register(d->dev);
- if (ret < 0) {
- put_device(d->dev);
- d->dev = NULL;
+ ret = device_add(&d->dev);
+ if (ret < 0)
goto exit_idr;
- }
/* link into parent domain */
if (parent) {
list_add_tail(&d->domain_entry, &parent->domain_list);
}
+ d->disconnected = false;
+
mutex_unlock(&kdbus_subsys_lock);
if (parent)
mutex_unlock(&parent->lock);
idr_remove(&kdbus_domain_major_idr, d->major);
exit_chrdev:
unregister_chrdev(d->major, d->devpath);
-exit_free_devpath:
- kfree(d->name);
- kfree(d->devpath);
exit_unlock:
mutex_unlock(&kdbus_subsys_lock);
if (parent)
mutex_unlock(&parent->lock);
-exit_free:
- kfree(d);
+exit_put:
+ put_device(&d->dev);
return ret;
}
#ifndef __KDBUS_DOMAIN_H
#define __KDBUS_DOMAIN_H
+#include <linux/device.h>
#include <linux/hashtable.h>
#include <linux/idr.h>
/**
* struct kdbus_domain - domain for buses
- * @kref: Reference counter
+ * @dev: Underlying device
* @disconnected: Invalidated data
* @name: Name of the domain
* @devpath: /dev base directory path
* @major: Device major number for all nodes
* @mode: Device node access mode
* @idr: Map of endpoint minors to buses
- * @dev: Control device node, minor == 0
* @lock: Domain data lock
* @bus_seq_last: Last used bus id sequence number
* @msg_seq_last: Last used message id sequence number
* file immediately destroys the entire domain.
*/
struct kdbus_domain {
- struct kref kref;
+ struct device dev;
bool disconnected;
const char *name;
const char *devpath;
unsigned int major;
umode_t mode;
struct idr idr;
- struct device *dev;
struct mutex lock;
u64 bus_seq_last;
atomic64_t msg_seq_last;