summaryrefslogtreecommitdiff
path: root/endpoint.c
diff options
context:
space:
mode:
Diffstat (limited to 'endpoint.c')
-rw-r--r--endpoint.c105
1 files changed, 48 insertions, 57 deletions
diff --git a/endpoint.c b/endpoint.c
index 3e879d888f7..36411ad4f89 100644
--- a/endpoint.c
+++ b/endpoint.c
@@ -25,6 +25,7 @@
#include "connection.h"
#include "domain.h"
#include "endpoint.h"
+#include "handle.h"
#include "item.h"
#include "message.h"
#include "policy.h"
@@ -76,6 +77,16 @@ void kdbus_ep_disconnect(struct kdbus_ep *ep)
ep->disconnected = true;
mutex_unlock(&ep->lock);
+ /* disconnect from bus */
+ mutex_lock(&ep->bus->lock);
+ list_del(&ep->bus_entry);
+ mutex_unlock(&ep->bus->lock);
+
+ if (device_is_registered(&ep->dev))
+ device_del(&ep->dev);
+
+ kdbus_minor_set(ep->dev.devt, KDBUS_MINOR_EP, NULL);
+
/* disconnect all connections to this endpoint */
for (;;) {
struct kdbus_conn *conn;
@@ -96,19 +107,6 @@ void kdbus_ep_disconnect(struct kdbus_ep *ep)
kdbus_conn_disconnect(conn, false);
kdbus_conn_unref(conn);
}
-
- /* disconnect from bus */
- mutex_lock(&ep->bus->lock);
- list_del(&ep->bus_entry);
- mutex_unlock(&ep->bus->lock);
-
- if (ep->minor > 0) {
- device_del(&ep->dev);
- mutex_lock(&ep->bus->domain->lock);
- idr_remove(&ep->bus->domain->idr, ep->minor);
- mutex_unlock(&ep->bus->domain->lock);
- ep->minor = 0;
- }
}
static void __kdbus_ep_free(struct device *dev)
@@ -119,6 +117,7 @@ static void __kdbus_ep_free(struct device *dev)
BUG_ON(!list_empty(&ep->conn_list));
kdbus_policy_db_clear(&ep->policy_db);
+ kdbus_minor_free(ep->dev.devt);
kdbus_bus_unref(ep->bus);
kdbus_domain_user_unref(ep->user);
kfree(ep->name);
@@ -134,19 +133,13 @@ struct kdbus_ep *kdbus_ep_unref(struct kdbus_ep *ep)
static struct kdbus_ep *kdbus_ep_find(struct kdbus_bus *bus, const char *name)
{
- struct kdbus_ep *e, *ep = NULL;
-
- mutex_lock(&bus->lock);
- list_for_each_entry(e, &bus->ep_list, bus_entry) {
- if (strcmp(e->name, name) != 0)
- continue;
+ struct kdbus_ep *e;
- ep = kdbus_ep_ref(e);
- break;
- }
- mutex_unlock(&bus->lock);
+ list_for_each_entry(e, &bus->ep_list, bus_entry)
+ if (!strcmp(e->name, name))
+ return e;
- return ep;
+ return NULL;
}
/**
@@ -171,12 +164,6 @@ int kdbus_ep_new(struct kdbus_bus *bus, const char *name,
struct kdbus_ep *e;
int ret;
- e = kdbus_ep_find(bus, name);
- if (e) {
- kdbus_ep_unref(e);
- return -EEXIST;
- }
-
e = kzalloc(sizeof(*e), GFP_KERNEL);
if (!e)
return -ENOMEM;
@@ -201,52 +188,56 @@ int kdbus_ep_new(struct kdbus_bus *bus, const char *name,
goto exit_put;
}
- mutex_lock(&bus->domain->lock);
- /* register minor in our endpoint map */
- ret = idr_alloc(&bus->domain->idr, e, 1, 0, GFP_KERNEL);
- if (ret < 0) {
- if (ret == -ENOSPC)
- ret = -EEXIST;
- mutex_unlock(&bus->domain->lock);
- goto exit_put;
- }
-
- e->minor = ret;
- e->dev.devt = MKDEV(bus->domain->major, e->minor);
- mutex_unlock(&bus->domain->lock);
-
ret = dev_set_name(&e->dev, "%s/%s/%s",
bus->domain->devpath, bus->name, name);
if (ret < 0)
- goto exit_idr;
+ goto exit_put;
- ret = device_add(&e->dev);
+ ret = kdbus_minor_alloc(KDBUS_MINOR_EP, NULL, &e->dev.devt);
if (ret < 0)
- goto exit_idr;
+ goto exit_put;
- /* link into bus */
mutex_lock(&bus->lock);
+
if (bus->disconnected) {
mutex_unlock(&bus->lock);
ret = -ESHUTDOWN;
- goto exit_dev;
+ goto exit_put;
}
- e->id = ++bus->ep_seq_last;
+
+ if (kdbus_ep_find(bus, name)) {
+ mutex_unlock(&bus->lock);
+ ret = -EEXIST;
+ goto exit_put;
+ }
+
e->bus = kdbus_bus_ref(bus);
- e->disconnected = false;
list_add_tail(&e->bus_entry, &bus->ep_list);
+
+ e->id = ++bus->ep_seq_last;
+
+ /*
+ * Same as with domains, we have to mark it enabled _before_ running
+ * device_add() to avoid messing with state after UEVENT_ADD was sent.
+ */
+
+ e->disconnected = false;
+ kdbus_minor_set_ep(e->dev.devt, e);
+
+ ret = device_add(&e->dev);
+
mutex_unlock(&bus->lock);
+ if (ret < 0) {
+ kdbus_ep_disconnect(e);
+ kdbus_ep_unref(e);
+ return ret;
+ }
+
if (ep)
*ep = e;
return 0;
-exit_dev:
- device_del(&e->dev);
-exit_idr:
- mutex_lock(&bus->domain->lock);
- idr_remove(&bus->domain->idr, e->minor);
- mutex_unlock(&bus->domain->lock);
exit_put:
put_device(&e->dev);
return ret;