diff mbox

[RFCv2,bluetooth-next,09/19] bluetooth: introduce l2cap chan priv data

Message ID 20160807143056.3116-10-aar@pengutronix.de (mailing list archive)
State New, archived
Headers show

Commit Message

Alexander Aring Aug. 7, 2016, 2:30 p.m. UTC
This patch adds possibility to add a private data room to the l2cap_chan
structure. This private dataroom will be freed when the l2cap_chan
reference count reach zero. This avoids dealing with separate allocated
data pointer for l2cap_chan "data" attribute.

Signed-off-by: Alexander Aring <aar@pengutronix.de>
---
 include/net/bluetooth/l2cap.h |  4 ++++
 net/bluetooth/l2cap_core.c    | 21 +++++++++++++++++++--
 2 files changed, 23 insertions(+), 2 deletions(-)
diff mbox

Patch

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 8a4d26e..925c78a 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -598,6 +598,9 @@  struct l2cap_chan {
 	void			*data;
 	const struct l2cap_ops	*ops;
 	struct mutex		lock;
+
+	/* must be last */
+	u8 priv[0] __aligned(sizeof(void *));
 };
 
 struct l2cap_ops {
@@ -925,6 +928,7 @@  int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm);
 int l2cap_add_scid(struct l2cap_chan *chan,  __u16 scid);
 
 struct l2cap_chan *l2cap_chan_create(void);
+struct l2cap_chan *l2cap_chan_create_priv(size_t priv_size);
 void l2cap_chan_close(struct l2cap_chan *chan, int reason);
 int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
 		       bdaddr_t *dst, u8 dst_type);
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 2ab8814..cce5d21 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -433,11 +433,11 @@  static void l2cap_chan_timeout(struct work_struct *work)
 	l2cap_chan_put(chan);
 }
 
-struct l2cap_chan *l2cap_chan_create(void)
+static struct l2cap_chan *__l2cap_chan_create(size_t priv_size)
 {
 	struct l2cap_chan *chan;
 
-	chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
+	chan = kzalloc(sizeof(*chan) + priv_size, GFP_ATOMIC);
 	if (!chan)
 		return NULL;
 
@@ -463,8 +463,25 @@  struct l2cap_chan *l2cap_chan_create(void)
 
 	return chan;
 }
+
+struct l2cap_chan *l2cap_chan_create(void)
+{
+	return __l2cap_chan_create(0);
+}
 EXPORT_SYMBOL_GPL(l2cap_chan_create);
 
+struct l2cap_chan *l2cap_chan_create_priv(size_t priv_size)
+{
+	struct l2cap_chan *chan = __l2cap_chan_create(priv_size);
+
+	/* let's point data pointer to private space */
+	if (chan)
+		chan->data = chan->priv;
+
+	return chan;
+}
+EXPORT_SYMBOL_GPL(l2cap_chan_create_priv);
+
 static void l2cap_chan_destroy(struct kref *kref)
 {
 	struct l2cap_chan *chan = container_of(kref, struct l2cap_chan, kref);