@@ -111,23 +111,28 @@ static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn,
111
111
}
112
112
113
113
/* Find channel with given SCID.
114
- * Returns locked channel. */
114
+ * Returns a reference locked channel.
115
+ */
115
116
static struct l2cap_chan * l2cap_get_chan_by_scid (struct l2cap_conn * conn ,
116
117
u16 cid )
117
118
{
118
119
struct l2cap_chan * c ;
119
120
120
121
mutex_lock (& conn -> chan_lock );
121
122
c = __l2cap_get_chan_by_scid (conn , cid );
122
- if (c )
123
- l2cap_chan_lock (c );
123
+ if (c ) {
124
+ /* Only lock if chan reference is not 0 */
125
+ c = l2cap_chan_hold_unless_zero (c );
126
+ if (c )
127
+ l2cap_chan_lock (c );
128
+ }
124
129
mutex_unlock (& conn -> chan_lock );
125
130
126
131
return c ;
127
132
}
128
133
129
134
/* Find channel with given DCID.
130
- * Returns locked channel.
135
+ * Returns a reference locked channel.
131
136
*/
132
137
static struct l2cap_chan * l2cap_get_chan_by_dcid (struct l2cap_conn * conn ,
133
138
u16 cid )
@@ -136,8 +141,12 @@ static struct l2cap_chan *l2cap_get_chan_by_dcid(struct l2cap_conn *conn,
136
141
137
142
mutex_lock (& conn -> chan_lock );
138
143
c = __l2cap_get_chan_by_dcid (conn , cid );
139
- if (c )
140
- l2cap_chan_lock (c );
144
+ if (c ) {
145
+ /* Only lock if chan reference is not 0 */
146
+ c = l2cap_chan_hold_unless_zero (c );
147
+ if (c )
148
+ l2cap_chan_lock (c );
149
+ }
141
150
mutex_unlock (& conn -> chan_lock );
142
151
143
152
return c ;
@@ -162,8 +171,12 @@ static struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn,
162
171
163
172
mutex_lock (& conn -> chan_lock );
164
173
c = __l2cap_get_chan_by_ident (conn , ident );
165
- if (c )
166
- l2cap_chan_lock (c );
174
+ if (c ) {
175
+ /* Only lock if chan reference is not 0 */
176
+ c = l2cap_chan_hold_unless_zero (c );
177
+ if (c )
178
+ l2cap_chan_lock (c );
179
+ }
167
180
mutex_unlock (& conn -> chan_lock );
168
181
169
182
return c ;
@@ -497,6 +510,16 @@ void l2cap_chan_hold(struct l2cap_chan *c)
497
510
kref_get (& c -> kref );
498
511
}
499
512
513
+ struct l2cap_chan * l2cap_chan_hold_unless_zero (struct l2cap_chan * c )
514
+ {
515
+ BT_DBG ("chan %p orig refcnt %u" , c , kref_read (& c -> kref ));
516
+
517
+ if (!kref_get_unless_zero (& c -> kref ))
518
+ return NULL ;
519
+
520
+ return c ;
521
+ }
522
+
500
523
void l2cap_chan_put (struct l2cap_chan * c )
501
524
{
502
525
BT_DBG ("chan %p orig refcnt %u" , c , kref_read (& c -> kref ));
@@ -1968,7 +1991,10 @@ static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
1968
1991
src_match = !bacmp (& c -> src , src );
1969
1992
dst_match = !bacmp (& c -> dst , dst );
1970
1993
if (src_match && dst_match ) {
1971
- l2cap_chan_hold (c );
1994
+ c = l2cap_chan_hold_unless_zero (c );
1995
+ if (!c )
1996
+ continue ;
1997
+
1972
1998
read_unlock (& chan_list_lock );
1973
1999
return c ;
1974
2000
}
@@ -1983,7 +2009,7 @@ static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
1983
2009
}
1984
2010
1985
2011
if (c1 )
1986
- l2cap_chan_hold (c1 );
2012
+ c1 = l2cap_chan_hold_unless_zero (c1 );
1987
2013
1988
2014
read_unlock (& chan_list_lock );
1989
2015
@@ -4463,6 +4489,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn,
4463
4489
4464
4490
unlock :
4465
4491
l2cap_chan_unlock (chan );
4492
+ l2cap_chan_put (chan );
4466
4493
return err ;
4467
4494
}
4468
4495
@@ -4577,6 +4604,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn,
4577
4604
4578
4605
done :
4579
4606
l2cap_chan_unlock (chan );
4607
+ l2cap_chan_put (chan );
4580
4608
return err ;
4581
4609
}
4582
4610
@@ -5304,6 +5332,7 @@ static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
5304
5332
l2cap_send_move_chan_rsp (chan , result );
5305
5333
5306
5334
l2cap_chan_unlock (chan );
5335
+ l2cap_chan_put (chan );
5307
5336
5308
5337
return 0 ;
5309
5338
}
@@ -5396,6 +5425,7 @@ static void l2cap_move_continue(struct l2cap_conn *conn, u16 icid, u16 result)
5396
5425
}
5397
5426
5398
5427
l2cap_chan_unlock (chan );
5428
+ l2cap_chan_put (chan );
5399
5429
}
5400
5430
5401
5431
static void l2cap_move_fail (struct l2cap_conn * conn , u8 ident , u16 icid ,
@@ -5425,6 +5455,7 @@ static void l2cap_move_fail(struct l2cap_conn *conn, u8 ident, u16 icid,
5425
5455
l2cap_send_move_chan_cfm (chan , L2CAP_MC_UNCONFIRMED );
5426
5456
5427
5457
l2cap_chan_unlock (chan );
5458
+ l2cap_chan_put (chan );
5428
5459
}
5429
5460
5430
5461
static int l2cap_move_channel_rsp (struct l2cap_conn * conn ,
@@ -5488,6 +5519,7 @@ static int l2cap_move_channel_confirm(struct l2cap_conn *conn,
5488
5519
l2cap_send_move_chan_cfm_rsp (conn , cmd -> ident , icid );
5489
5520
5490
5521
l2cap_chan_unlock (chan );
5522
+ l2cap_chan_put (chan );
5491
5523
5492
5524
return 0 ;
5493
5525
}
@@ -5523,6 +5555,7 @@ static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
5523
5555
}
5524
5556
5525
5557
l2cap_chan_unlock (chan );
5558
+ l2cap_chan_put (chan );
5526
5559
5527
5560
return 0 ;
5528
5561
}
@@ -5895,12 +5928,11 @@ static inline int l2cap_le_credits(struct l2cap_conn *conn,
5895
5928
if (credits > max_credits ) {
5896
5929
BT_ERR ("LE credits overflow" );
5897
5930
l2cap_send_disconn_req (chan , ECONNRESET );
5898
- l2cap_chan_unlock (chan );
5899
5931
5900
5932
/* Return 0 so that we don't trigger an unnecessary
5901
5933
* command reject packet.
5902
5934
*/
5903
- return 0 ;
5935
+ goto unlock ;
5904
5936
}
5905
5937
5906
5938
chan -> tx_credits += credits ;
@@ -5911,7 +5943,9 @@ static inline int l2cap_le_credits(struct l2cap_conn *conn,
5911
5943
if (chan -> tx_credits )
5912
5944
chan -> ops -> resume (chan );
5913
5945
5946
+ unlock :
5914
5947
l2cap_chan_unlock (chan );
5948
+ l2cap_chan_put (chan );
5915
5949
5916
5950
return 0 ;
5917
5951
}
@@ -7597,6 +7631,7 @@ static void l2cap_data_channel(struct l2cap_conn *conn, u16 cid,
7597
7631
7598
7632
done :
7599
7633
l2cap_chan_unlock (chan );
7634
+ l2cap_chan_put (chan );
7600
7635
}
7601
7636
7602
7637
static void l2cap_conless_channel (struct l2cap_conn * conn , __le16 psm ,
@@ -8085,7 +8120,7 @@ static struct l2cap_chan *l2cap_global_fixed_chan(struct l2cap_chan *c,
8085
8120
if (src_type != c -> src_type )
8086
8121
continue ;
8087
8122
8088
- l2cap_chan_hold (c );
8123
+ c = l2cap_chan_hold_unless_zero (c );
8089
8124
read_unlock (& chan_list_lock );
8090
8125
return c ;
8091
8126
}
0 commit comments