diff options
-rw-r--r-- | include/net/bluetooth/l2cap.h | 1 | ||||
-rw-r--r-- | net/bluetooth/l2cap_core.c | 12 | ||||
-rw-r--r-- | net/bluetooth/l2cap_sock.c | 8 |
3 files changed, 19 insertions, 2 deletions
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index cedda399f9c0..1558eccb19db 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h | |||
@@ -711,6 +711,7 @@ enum { | |||
711 | FLAG_DEFER_SETUP, | 711 | FLAG_DEFER_SETUP, |
712 | FLAG_LE_CONN_REQ_SENT, | 712 | FLAG_LE_CONN_REQ_SENT, |
713 | FLAG_PENDING_SECURITY, | 713 | FLAG_PENDING_SECURITY, |
714 | FLAG_HOLD_HCI_CONN, | ||
714 | }; | 715 | }; |
715 | 716 | ||
716 | enum { | 717 | enum { |
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 777c41dbfdbe..a6559225bb50 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -546,7 +546,10 @@ void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) | |||
546 | 546 | ||
547 | l2cap_chan_hold(chan); | 547 | l2cap_chan_hold(chan); |
548 | 548 | ||
549 | hci_conn_hold(conn->hcon); | 549 | /* Only keep a reference for fixed channels if they requested it */ |
550 | if (chan->chan_type != L2CAP_CHAN_FIXED || | ||
551 | test_bit(FLAG_HOLD_HCI_CONN, &chan->flags)) | ||
552 | hci_conn_hold(conn->hcon); | ||
550 | 553 | ||
551 | list_add(&chan->list, &conn->chan_l); | 554 | list_add(&chan->list, &conn->chan_l); |
552 | } | 555 | } |
@@ -577,7 +580,12 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err) | |||
577 | 580 | ||
578 | chan->conn = NULL; | 581 | chan->conn = NULL; |
579 | 582 | ||
580 | if (chan->scid != L2CAP_CID_A2MP) | 583 | /* Reference was only held for non-fixed channels or |
584 | * fixed channels that explicitly requested it using the | ||
585 | * FLAG_HOLD_HCI_CONN flag. | ||
586 | */ | ||
587 | if (chan->chan_type != L2CAP_CHAN_FIXED || | ||
588 | test_bit(FLAG_HOLD_HCI_CONN, &chan->flags)) | ||
581 | hci_conn_drop(conn->hcon); | 589 | hci_conn_drop(conn->hcon); |
582 | 590 | ||
583 | if (mgr && mgr->bredr_chan == chan) | 591 | if (mgr && mgr->bredr_chan == chan) |
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index ed06f88e6f10..31f106e61ca2 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c | |||
@@ -146,6 +146,14 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) | |||
146 | case L2CAP_CHAN_RAW: | 146 | case L2CAP_CHAN_RAW: |
147 | chan->sec_level = BT_SECURITY_SDP; | 147 | chan->sec_level = BT_SECURITY_SDP; |
148 | break; | 148 | break; |
149 | case L2CAP_CHAN_FIXED: | ||
150 | /* Fixed channels default to the L2CAP core not holding a | ||
151 | * hci_conn reference for them. For fixed channels mapping to | ||
152 | * L2CAP sockets we do want to hold a reference so set the | ||
153 | * appropriate flag to request it. | ||
154 | */ | ||
155 | set_bit(FLAG_HOLD_HCI_CONN, &chan->flags); | ||
156 | break; | ||
149 | } | 157 | } |
150 | 158 | ||
151 | bacpy(&chan->src, &la.l2_bdaddr); | 159 | bacpy(&chan->src, &la.l2_bdaddr); |