diff options
-rw-r--r-- | include/net/bluetooth/l2cap.h | 4 | ||||
-rw-r--r-- | net/bluetooth/l2cap_core.c | 25 |
2 files changed, 28 insertions, 1 deletions
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 278830ef92cd..7b4cc5b98535 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h | |||
@@ -583,6 +583,7 @@ struct l2cap_conn { | |||
583 | 583 | ||
584 | struct list_head chan_l; | 584 | struct list_head chan_l; |
585 | struct mutex chan_lock; | 585 | struct mutex chan_lock; |
586 | struct kref ref; | ||
586 | }; | 587 | }; |
587 | 588 | ||
588 | #define L2CAP_INFO_CL_MTU_REQ_SENT 0x01 | 589 | #define L2CAP_INFO_CL_MTU_REQ_SENT 0x01 |
@@ -813,4 +814,7 @@ void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan, | |||
813 | u8 status); | 814 | u8 status); |
814 | void __l2cap_physical_cfm(struct l2cap_chan *chan, int result); | 815 | void __l2cap_physical_cfm(struct l2cap_chan *chan, int result); |
815 | 816 | ||
817 | void l2cap_conn_get(struct l2cap_conn *conn); | ||
818 | void l2cap_conn_put(struct l2cap_conn *conn); | ||
819 | |||
816 | #endif /* __L2CAP_H */ | 820 | #endif /* __L2CAP_H */ |
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index e09b89be1c4d..be9ad89339cd 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -1486,7 +1486,8 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err) | |||
1486 | } | 1486 | } |
1487 | 1487 | ||
1488 | hcon->l2cap_data = NULL; | 1488 | hcon->l2cap_data = NULL; |
1489 | kfree(conn); | 1489 | conn->hchan = NULL; |
1490 | l2cap_conn_put(conn); | ||
1490 | } | 1491 | } |
1491 | 1492 | ||
1492 | static void security_timeout(struct work_struct *work) | 1493 | static void security_timeout(struct work_struct *work) |
@@ -1520,8 +1521,10 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon) | |||
1520 | return NULL; | 1521 | return NULL; |
1521 | } | 1522 | } |
1522 | 1523 | ||
1524 | kref_init(&conn->ref); | ||
1523 | hcon->l2cap_data = conn; | 1525 | hcon->l2cap_data = conn; |
1524 | conn->hcon = hcon; | 1526 | conn->hcon = hcon; |
1527 | hci_conn_get(conn->hcon); | ||
1525 | conn->hchan = hchan; | 1528 | conn->hchan = hchan; |
1526 | 1529 | ||
1527 | BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan); | 1530 | BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan); |
@@ -1558,6 +1561,26 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon) | |||
1558 | return conn; | 1561 | return conn; |
1559 | } | 1562 | } |
1560 | 1563 | ||
1564 | static void l2cap_conn_free(struct kref *ref) | ||
1565 | { | ||
1566 | struct l2cap_conn *conn = container_of(ref, struct l2cap_conn, ref); | ||
1567 | |||
1568 | hci_conn_put(conn->hcon); | ||
1569 | kfree(conn); | ||
1570 | } | ||
1571 | |||
1572 | void l2cap_conn_get(struct l2cap_conn *conn) | ||
1573 | { | ||
1574 | kref_get(&conn->ref); | ||
1575 | } | ||
1576 | EXPORT_SYMBOL(l2cap_conn_get); | ||
1577 | |||
1578 | void l2cap_conn_put(struct l2cap_conn *conn) | ||
1579 | { | ||
1580 | kref_put(&conn->ref, l2cap_conn_free); | ||
1581 | } | ||
1582 | EXPORT_SYMBOL(l2cap_conn_put); | ||
1583 | |||
1561 | /* ---- Socket interface ---- */ | 1584 | /* ---- Socket interface ---- */ |
1562 | 1585 | ||
1563 | /* Find socket with psm and source / destination bdaddr. | 1586 | /* Find socket with psm and source / destination bdaddr. |