@@ -22,6 +22,7 @@
#define QRTR_MAX_EPH_SOCKET 0x7fff
#define QRTR_EPH_PORT_RANGE \
XA_LIMIT(QRTR_MIN_EPH_SOCKET, QRTR_MAX_EPH_SOCKET)
+#define QRTR_ENDPOINT_RANGE XA_LIMIT(qrtr_local_nid + 1, INT_MAX)
#define QRTR_PORT_CTRL_LEGACY 0xffff
@@ -109,6 +110,10 @@ static LIST_HEAD(qrtr_all_nodes);
/* lock for qrtr_all_nodes and node reference */
static DEFINE_MUTEX(qrtr_node_lock);
+/* endpoint id allocation management */
+static DEFINE_XARRAY_ALLOC(qrtr_endpoints);
+static u32 next_endpoint_id;
+
/* local port allocation management */
static DEFINE_XARRAY_ALLOC(qrtr_ports);
@@ -585,6 +590,8 @@ static struct sk_buff *qrtr_alloc_ctrl_packet(struct qrtr_ctrl_pkt **pkt,
int qrtr_endpoint_register(struct qrtr_endpoint *ep, unsigned int nid)
{
struct qrtr_node *node;
+ u32 endpoint_id;
+ int rc;
if (!ep || !ep->xmit)
return -EINVAL;
@@ -593,6 +600,13 @@ int qrtr_endpoint_register(struct qrtr_endpoint *ep, unsigned int nid)
if (!node)
return -ENOMEM;
+ rc = xa_alloc_cyclic(&qrtr_endpoints, &endpoint_id, NULL,
+ QRTR_ENDPOINT_RANGE, &next_endpoint_id,
+ GFP_KERNEL);
+
+ if (rc < 0)
+ goto free_node;
+
kref_init(&node->ref);
mutex_init(&node->ep_lock);
skb_queue_head_init(&node->rx_queue);
@@ -608,8 +622,12 @@ int qrtr_endpoint_register(struct qrtr_endpoint *ep, unsigned int nid)
list_add(&node->item, &qrtr_all_nodes);
mutex_unlock(&qrtr_node_lock);
ep->node = node;
+ ep->id = endpoint_id;
return 0;
+free_node:
+ kfree(node);
+ return rc;
}
EXPORT_SYMBOL_GPL(qrtr_endpoint_register);
@@ -628,8 +646,10 @@ void qrtr_endpoint_unregister(struct qrtr_endpoint *ep)
struct sk_buff *skb;
unsigned long flags;
void __rcu **slot;
+ u32 endpoint_id;
mutex_lock(&node->ep_lock);
+ endpoint_id = node->ep->id;
node->ep = NULL;
mutex_unlock(&node->ep_lock);
@@ -656,6 +676,10 @@ void qrtr_endpoint_unregister(struct qrtr_endpoint *ep)
mutex_unlock(&node->qrtr_tx_lock);
qrtr_node_release(node);
+
+ xa_erase(&qrtr_endpoints, endpoint_id);
+
+ ep->id = 0;
ep->node = NULL;
}
EXPORT_SYMBOL_GPL(qrtr_endpoint_unregister);
@@ -21,6 +21,7 @@ struct qrtr_endpoint {
int (*xmit)(struct qrtr_endpoint *ep, struct sk_buff *skb);
/* private: not for endpoint use */
struct qrtr_node *node;
+ u32 id;
};
int qrtr_endpoint_register(struct qrtr_endpoint *ep, unsigned int nid);