@ -74,58 +74,58 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
static int l2cap_ertm_data_rcv ( struct sock * sk , struct sk_buff * skb ) ;
/* ---- L2CAP channels ---- */
static struct sock * __l2cap_get_chan_by_dcid ( struct l2cap_chan_list * l , u16 cid )
static struct l2cap_chan * __l2cap_get_chan_by_dcid ( struct l2cap_chan_list * l , u16 cid )
{
struct sock * s ;
for ( s = l - > head ; s ; s = l2cap_pi ( s ) - > next_c ) {
if ( l2cap_pi ( s ) - > dcid = = cid )
struct l2cap_chan * c ;
for ( c = l - > head ; c ; c = c - > next_c ) {
if ( l2cap_pi ( c - > sk ) - > dcid = = cid )
break ;
}
return s ;
return c ;
}
static struct sock * __l2cap_get_chan_by_scid ( struct l2cap_chan_list * l , u16 cid )
static struct l2cap_chan * __l2cap_get_chan_by_scid ( struct l2cap_chan_list * l , u16 cid )
{
struct sock * s ;
for ( s = l - > head ; s ; s = l2cap_pi ( s ) - > next_c ) {
if ( l2cap_pi ( s ) - > scid = = cid )
struct l2cap_chan * c ;
for ( c = l - > head ; c ; c = c - > next_c ) {
if ( l2cap_pi ( c - > sk ) - > scid = = cid )
break ;
}
return s ;
return c ;
}
/* Find channel with given SCID.
* Returns locked socket */
static inline struct sock * l2cap_get_chan_by_scid ( struct l2cap_chan_list * l , u16 cid )
static inline struct l2cap_chan * l2cap_get_chan_by_scid ( struct l2cap_chan_list * l , u16 cid )
{
struct sock * s ;
struct l2cap_chan * c ;
read_lock ( & l - > lock ) ;
s = __l2cap_get_chan_by_scid ( l , cid ) ;
if ( s )
bh_lock_sock ( s ) ;
c = __l2cap_get_chan_by_scid ( l , cid ) ;
if ( c )
bh_lock_sock ( c - > sk ) ;
read_unlock ( & l - > lock ) ;
return s ;
return c ;
}
static struct sock * __l2cap_get_chan_by_ident ( struct l2cap_chan_list * l , u8 ident )
static struct l2cap_chan * __l2cap_get_chan_by_ident ( struct l2cap_chan_list * l , u8 ident )
{
struct sock * s ;
for ( s = l - > head ; s ; s = l2cap_pi ( s ) - > next_c ) {
if ( l2cap_pi ( s ) - > ident = = ident )
struct l2cap_chan * c ;
for ( c = l - > head ; c ; c = c - > next_c ) {
if ( l2cap_pi ( c - > sk ) - > ident = = ident )
break ;
}
return s ;
return c ;
}
static inline struct sock * l2cap_get_chan_by_ident ( struct l2cap_chan_list * l , u8 ident )
static inline struct l2cap_chan * l2cap_get_chan_by_ident ( struct l2cap_chan_list * l , u8 ident )
{
struct sock * s ;
struct l2cap_chan * c ;
read_lock ( & l - > lock ) ;
s = __l2cap_get_chan_by_ident ( l , ident ) ;
if ( s )
bh_lock_sock ( s ) ;
c = __l2cap_get_chan_by_ident ( l , ident ) ;
if ( c )
bh_lock_sock ( c - > sk ) ;
read_unlock ( & l - > lock ) ;
return s ;
return c ;
}
static u16 l2cap_alloc_cid ( struct l2cap_chan_list * l )
@ -140,38 +140,52 @@ static u16 l2cap_alloc_cid(struct l2cap_chan_list *l)
return 0 ;
}
static inline void __l2cap_chan_link ( struct l2cap_chan_list * l , struct sock * sk )
static struct l2cap_chan * l2cap_chan_alloc ( struct sock * sk )
{
struct l2cap_chan * chan ;
chan = kzalloc ( sizeof ( * chan ) , GFP_ATOMIC ) ;
if ( ! chan )
return NULL ;
chan - > sk = sk ;
return chan ;
}
static inline void __l2cap_chan_link ( struct l2cap_chan_list * l , struct l2cap_chan * chan )
{
sock_hold ( sk ) ;
sock_hold ( chan - > sk ) ;
if ( l - > head )
l2cap_pi ( l - > head ) - > prev_c = sk ;
l - > head - > prev_c = chan ;
l2cap_pi ( sk ) - > next_c = l - > head ;
l2cap_pi ( sk ) - > prev_c = NULL ;
l - > head = sk ;
chan - > next_c = l - > head ;
chan - > prev_c = NULL ;
l - > head = chan ;
}
static inline void l2cap_chan_unlink ( struct l2cap_chan_list * l , struct sock * sk )
static inline void l2cap_chan_unlink ( struct l2cap_chan_list * l , struct l2cap_chan * chan )
{
struct sock * next = l2cap_pi ( sk ) - > next_c , * prev = l2cap_pi ( sk ) - > prev_c ;
struct l2cap_chan * next = chan - > next_c , * prev = chan - > prev_c ;
write_lock_bh ( & l - > lock ) ;
if ( sk = = l - > head )
if ( chan = = l - > head )
l - > head = next ;
if ( next )
l2cap_pi ( next ) - > prev_c = prev ;
next - > prev_c = prev ;
if ( prev )
l2cap_pi ( prev ) - > next_c = next ;
prev - > next_c = next ;
write_unlock_bh ( & l - > lock ) ;
__sock_put ( sk ) ;
__sock_put ( chan - > sk ) ;
}
static void __l2cap_chan_add ( struct l2cap_conn * conn , struct sock * sk )
static void __l2cap_chan_add ( struct l2cap_conn * conn , struct l2cap_chan * chan )
{
struct l2cap_chan_list * l = & conn - > chan_list ;
struct sock * sk = chan - > sk ;
BT_DBG ( " conn %p, psm 0x%2.2x, dcid 0x%4.4x " , conn ,
l2cap_pi ( sk ) - > psm , l2cap_pi ( sk ) - > dcid ) ;
@ -203,13 +217,14 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk)
l2cap_pi ( sk ) - > omtu = L2CAP_DEFAULT_MTU ;
}
__l2cap_chan_link ( l , sk ) ;
__l2cap_chan_link ( l , chan ) ;
}
/* Delete channel.
* Must be called on the locked socket . */
void l2cap_chan_del ( struct sock * sk , int err )
void l2cap_chan_del ( struct l2cap_chan * chan , int err )
{
struct sock * sk = chan - > sk ;
struct l2cap_conn * conn = l2cap_pi ( sk ) - > conn ;
struct sock * parent = bt_sk ( sk ) - > parent ;
@ -219,7 +234,7 @@ void l2cap_chan_del(struct sock *sk, int err)
if ( conn ) {
/* Unlink from channel list */
l2cap_chan_unlink ( & conn - > chan_list , sk ) ;
l2cap_chan_unlink ( & conn - > chan_list , chan ) ;
l2cap_pi ( sk ) - > conn = NULL ;
hci_conn_put ( conn - > hcon ) ;
}
@ -253,6 +268,8 @@ void l2cap_chan_del(struct sock *sk, int err)
kfree ( l ) ;
}
}
kfree ( chan ) ;
}
static inline u8 l2cap_get_auth_type ( struct sock * sk )
@ -487,7 +504,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
{
struct l2cap_chan_list * l = & conn - > chan_list ;
struct sock_del_list del , * tmp1 , * tmp2 ;
struct sock * sk ;
struct l2cap_chan * chan ;
BT_DBG ( " conn %p " , conn ) ;
@ -495,7 +512,8 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
read_lock ( & l - > lock ) ;
for ( sk = l - > head ; sk ; sk = l2cap_pi ( sk ) - > next_c ) {
for ( chan = l - > head ; chan ; chan = chan - > next_c ) {
struct sock * sk = chan - > sk ;
bh_lock_sock ( sk ) ;
if ( sk - > sk_type ! = SOCK_SEQPACKET & &
@ -622,6 +640,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
{
struct l2cap_chan_list * list = & conn - > chan_list ;
struct sock * parent , * uninitialized_var ( sk ) ;
struct l2cap_chan * chan ;
BT_DBG ( " " ) ;
@ -641,6 +660,12 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
if ( ! sk )
goto clean ;
chan = l2cap_chan_alloc ( sk ) ;
if ( ! chan ) {
l2cap_sock_kill ( sk ) ;
goto clean ;
}
write_lock_bh ( & list - > lock ) ;
hci_conn_hold ( conn - > hcon ) ;
@ -651,7 +676,9 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
bt_accept_enqueue ( parent , sk ) ;
__l2cap_chan_add ( conn , sk ) ;
__l2cap_chan_add ( conn , chan ) ;
l2cap_pi ( sk ) - > chan = chan ;
l2cap_sock_set_timer ( sk , sk - > sk_sndtimeo ) ;
@ -667,7 +694,7 @@ clean:
static void l2cap_conn_ready ( struct l2cap_conn * conn )
{
struct l2cap_chan_list * l = & conn - > chan_list ;
struct sock * sk ;
struct l2cap_chan * chan ;
BT_DBG ( " conn %p " , conn ) ;
@ -676,7 +703,8 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
read_lock ( & l - > lock ) ;
for ( sk = l - > head ; sk ; sk = l2cap_pi ( sk ) - > next_c ) {
for ( chan = l - > head ; chan ; chan = chan - > next_c ) {
struct sock * sk = chan - > sk ;
bh_lock_sock ( sk ) ;
if ( conn - > hcon - > type = = LE_LINK ) {
@ -703,13 +731,14 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
static void l2cap_conn_unreliable ( struct l2cap_conn * conn , int err )
{
struct l2cap_chan_list * l = & conn - > chan_list ;
struct sock * sk ;
struct l2cap_chan * chan ;
BT_DBG ( " conn %p " , conn ) ;
read_lock ( & l - > lock ) ;
for ( sk = l - > head ; sk ; sk = l2cap_pi ( sk ) - > next_c ) {
for ( chan = l - > head ; chan ; chan = chan - > next_c ) {
struct sock * sk = chan - > sk ;
if ( l2cap_pi ( sk ) - > force_reliable )
sk - > sk_err = err ;
}
@ -768,6 +797,7 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
static void l2cap_conn_del ( struct hci_conn * hcon , int err )
{
struct l2cap_conn * conn = hcon - > l2cap_data ;
struct l2cap_chan * chan ;
struct sock * sk ;
if ( ! conn )
@ -778,9 +808,10 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)
kfree_skb ( conn - > rx_skb ) ;
/* Kill channels */
while ( ( sk = conn - > chan_list . head ) ) {
while ( ( chan = conn - > chan_list . head ) ) {
sk = chan - > sk ;
bh_lock_sock ( sk ) ;
l2cap_chan_del ( sk , err ) ;
l2cap_chan_del ( chan , err ) ;
bh_unlock_sock ( sk ) ;
l2cap_sock_kill ( sk ) ;
}
@ -792,11 +823,11 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)
kfree ( conn ) ;
}
static inline void l2cap_chan_add ( struct l2cap_conn * conn , struct sock * sk )
static inline void l2cap_chan_add ( struct l2cap_conn * conn , struct l2cap_chan * chan )
{
struct l2cap_chan_list * l = & conn - > chan_list ;
write_lock_bh ( & l - > lock ) ;
__l2cap_chan_add ( conn , sk ) ;
__l2cap_chan_add ( conn , chan ) ;
write_unlock_bh ( & l - > lock ) ;
}
@ -837,6 +868,7 @@ int l2cap_do_connect(struct sock *sk)
bdaddr_t * src = & bt_sk ( sk ) - > src ;
bdaddr_t * dst = & bt_sk ( sk ) - > dst ;
struct l2cap_conn * conn ;
struct l2cap_chan * chan ;
struct hci_conn * hcon ;
struct hci_dev * hdev ;
__u8 auth_type ;
@ -872,10 +904,19 @@ int l2cap_do_connect(struct sock *sk)
goto done ;
}
chan = l2cap_chan_alloc ( sk ) ;
if ( ! chan ) {
hci_conn_put ( hcon ) ;
err = - ENOMEM ;
goto done ;
}
/* Update source addr of the socket */
bacpy ( src , conn - > src ) ;
l2cap_chan_add ( conn , sk ) ;
l2cap_chan_add ( conn , chan ) ;
l2cap_pi ( sk ) - > chan = chan ;
sk - > sk_state = BT_CONNECT ;
l2cap_sock_set_timer ( sk , sk - > sk_sndtimeo ) ;
@ -1387,12 +1428,13 @@ static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
{
struct l2cap_chan_list * l = & conn - > chan_list ;
struct sk_buff * nskb ;
struct sock * sk ;
struct l2cap_chan * chan ;
BT_DBG ( " conn %p " , conn ) ;
read_lock ( & l - > lock ) ;
for ( sk = l - > head ; sk ; sk = l2cap_pi ( sk ) - > next_c ) {
for ( chan = l - > head ; chan ; chan = chan - > next_c ) {
struct sock * sk = chan - > sk ;
if ( sk - > sk_type ! = SOCK_RAW )
continue ;
@ -1976,6 +2018,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
struct l2cap_chan_list * list = & conn - > chan_list ;
struct l2cap_conn_req * req = ( struct l2cap_conn_req * ) data ;
struct l2cap_conn_rsp rsp ;
struct l2cap_chan * chan ;
struct sock * parent , * sk = NULL ;
int result , status = L2CAP_CS_NO_INFO ;
@ -2013,6 +2056,12 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
if ( ! sk )
goto response ;
chan = l2cap_chan_alloc ( sk ) ;
if ( ! chan ) {
l2cap_sock_kill ( sk ) ;
goto response ;
}
write_lock_bh ( & list - > lock ) ;
/* Check if we already have channel with that dcid */
@ -2033,7 +2082,10 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
bt_accept_enqueue ( parent , sk ) ;
__l2cap_chan_add ( conn , sk ) ;
__l2cap_chan_add ( conn , chan ) ;
l2cap_pi ( sk ) - > chan = chan ;
dcid = l2cap_pi ( sk ) - > scid ;
l2cap_sock_set_timer ( sk , sk - > sk_sndtimeo ) ;
@ -2105,6 +2157,7 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
{
struct l2cap_conn_rsp * rsp = ( struct l2cap_conn_rsp * ) data ;
u16 scid , dcid , result , status ;
struct l2cap_chan * chan ;
struct sock * sk ;
u8 req [ 128 ] ;
@ -2116,15 +2169,17 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
BT_DBG ( " dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x " , dcid , scid , result , status ) ;
if ( scid ) {
sk = l2cap_get_chan_by_scid ( & conn - > chan_list , scid ) ;
if ( ! sk )
chan = l2cap_get_chan_by_scid ( & conn - > chan_list , scid ) ;
if ( ! chan )
return - EFAULT ;
} else {
sk = l2cap_get_chan_by_ident ( & conn - > chan_list , cmd - > ident ) ;
if ( ! sk )
chan = l2cap_get_chan_by_ident ( & conn - > chan_list , cmd - > ident ) ;
if ( ! chan )
return - EFAULT ;
}
sk = chan - > sk ;
switch ( result ) {
case L2CAP_CR_SUCCESS :
sk - > sk_state = BT_CONFIG ;
@ -2155,7 +2210,7 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
break ;
}
l2cap_chan_del ( sk , ECONNREFUSED ) ;
l2cap_chan_del ( chan , ECONNREFUSED ) ;
break ;
}
@ -2179,6 +2234,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
struct l2cap_conf_req * req = ( struct l2cap_conf_req * ) data ;
u16 dcid , flags ;
u8 rsp [ 64 ] ;
struct l2cap_chan * chan ;
struct sock * sk ;
int len ;
@ -2187,10 +2243,12 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
BT_DBG ( " dcid 0x%4.4x flags 0x%2.2x " , dcid , flags ) ;
sk = l2cap_get_chan_by_scid ( & conn - > chan_list , dcid ) ;
if ( ! sk )
chan = l2cap_get_chan_by_scid ( & conn - > chan_list , dcid ) ;
if ( ! chan )
return - ENOENT ;
sk = chan - > sk ;
if ( sk - > sk_state ! = BT_CONFIG ) {
struct l2cap_cmd_rej rej ;
@ -2269,6 +2327,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
{
struct l2cap_conf_rsp * rsp = ( struct l2cap_conf_rsp * ) data ;
u16 scid , flags , result ;
struct l2cap_chan * chan ;
struct sock * sk ;
int len = cmd - > len - sizeof ( * rsp ) ;
@ -2279,10 +2338,12 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
BT_DBG ( " scid 0x%4.4x flags 0x%2.2x result 0x%2.2x " ,
scid , flags , result ) ;
sk = l2cap_get_chan_by_scid ( & conn - > chan_list , scid ) ;
if ( ! sk )
chan = l2cap_get_chan_by_scid ( & conn - > chan_list , scid ) ;
if ( ! chan )
return 0 ;
sk = chan - > sk ;
switch ( result ) {
case L2CAP_CONF_SUCCESS :
l2cap_conf_rfc_get ( sk , rsp - > data , len ) ;
@ -2349,6 +2410,7 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd
struct l2cap_disconn_req * req = ( struct l2cap_disconn_req * ) data ;
struct l2cap_disconn_rsp rsp ;
u16 dcid , scid ;
struct l2cap_chan * chan ;
struct sock * sk ;
scid = __le16_to_cpu ( req - > scid ) ;
@ -2356,10 +2418,12 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd
BT_DBG ( " scid 0x%4.4x dcid 0x%4.4x " , scid , dcid ) ;
sk = l2cap_get_chan_by_scid ( & conn - > chan_list , dcid ) ;
if ( ! sk )
chan = l2cap_get_chan_by_scid ( & conn - > chan_list , dcid ) ;
if ( ! chan )
return 0 ;
sk = chan - > sk ;
rsp . dcid = cpu_to_le16 ( l2cap_pi ( sk ) - > scid ) ;
rsp . scid = cpu_to_le16 ( l2cap_pi ( sk ) - > dcid ) ;
l2cap_send_cmd ( conn , cmd - > ident , L2CAP_DISCONN_RSP , sizeof ( rsp ) , & rsp ) ;
@ -2375,7 +2439,7 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd
return 0 ;
}
l2cap_chan_del ( sk , ECONNRESET ) ;
l2cap_chan_del ( chan , ECONNRESET ) ;
bh_unlock_sock ( sk ) ;
l2cap_sock_kill ( sk ) ;
@ -2386,6 +2450,7 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd
{
struct l2cap_disconn_rsp * rsp = ( struct l2cap_disconn_rsp * ) data ;
u16 dcid , scid ;
struct l2cap_chan * chan ;
struct sock * sk ;
scid = __le16_to_cpu ( rsp - > scid ) ;
@ -2393,10 +2458,12 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd
BT_DBG ( " dcid 0x%4.4x scid 0x%4.4x " , dcid , scid ) ;
sk = l2cap_get_chan_by_scid ( & conn - > chan_list , scid ) ;
if ( ! sk )
chan = l2cap_get_chan_by_scid ( & conn - > chan_list , scid ) ;
if ( ! chan )
return 0 ;
sk = chan - > sk ;
/* don't delete l2cap channel if sk is owned by user */
if ( sock_owned_by_user ( sk ) ) {
sk - > sk_state = BT_DISCONN ;
@ -2406,7 +2473,7 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd
return 0 ;
}
l2cap_chan_del ( sk , 0 ) ;
l2cap_chan_del ( chan , 0 ) ;
bh_unlock_sock ( sk ) ;
l2cap_sock_kill ( sk ) ;
@ -3538,18 +3605,20 @@ drop:
static inline int l2cap_data_channel ( struct l2cap_conn * conn , u16 cid , struct sk_buff * skb )
{
struct l2cap_chan * chan ;
struct sock * sk ;
struct l2cap_pinfo * pi ;
u16 control ;
u8 tx_seq ;
int len ;
sk = l2cap_get_chan_by_scid ( & conn - > chan_list , cid ) ;
if ( ! sk ) {
chan = l2cap_get_chan_by_scid ( & conn - > chan_list , cid ) ;
if ( ! chan ) {
BT_DBG ( " unknown cid 0x%4.4x " , cid ) ;
goto drop ;
}
sk = chan - > sk ;
pi = l2cap_pi ( sk ) ;
BT_DBG ( " sk %p, len %d " , sk , skb - > len ) ;
@ -3788,7 +3857,7 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
{
struct l2cap_chan_list * l ;
struct l2cap_conn * conn = hcon - > l2cap_data ;
struct sock * sk ;
struct l2cap_chan * chan ;
if ( ! conn )
return 0 ;
@ -3799,7 +3868,8 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
read_lock ( & l - > lock ) ;
for ( sk = l - > head ; sk ; sk = l2cap_pi ( sk ) - > next_c ) {
for ( chan = l - > head ; chan ; chan = chan - > next_c ) {
struct sock * sk = chan - > sk ;
bh_lock_sock ( sk ) ;
if ( l2cap_pi ( sk ) - > conf_state & L2CAP_CONF_CONNECT_PEND ) {
@ -3872,7 +3942,7 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl
if ( ! ( flags & ACL_CONT ) ) {
struct l2cap_hdr * hdr ;
struct sock * sk ;
struct l2cap_chan * chan ;
u16 cid ;
int len ;
@ -3910,18 +3980,21 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl
goto drop ;
}
sk = l2cap_get_chan_by_scid ( & conn - > chan_list , cid ) ;
chan = l2cap_get_chan_by_scid ( & conn - > chan_list , cid ) ;
if ( sk & & l2cap_pi ( sk ) - > imtu < len - L2CAP_HDR_SIZE ) {
BT_ERR ( " Frame exceeding recv MTU (len %d, MTU %d) " ,
len , l2cap_pi ( sk ) - > imtu ) ;
bh_unlock_sock ( sk ) ;
l2cap_conn_unreliable ( conn , ECOMM ) ;
goto drop ;
}
if ( chan & & chan - > sk ) {
struct sock * sk = chan - > sk ;
if ( sk )
if ( l2cap_pi ( sk ) - > imtu < len - L2CAP_HDR_SIZE ) {
BT_ERR ( " Frame exceeding recv MTU (len %d, "
" MTU %d) " , len ,
l2cap_pi ( sk ) - > imtu ) ;
bh_unlock_sock ( sk ) ;
l2cap_conn_unreliable ( conn , ECOMM ) ;
goto drop ;
}
bh_unlock_sock ( sk ) ;
}
/* Allocate skb for the complete frame (with header) */
conn - > rx_skb = bt_skb_alloc ( len , GFP_ATOMIC ) ;