@@ -724,13 +724,54 @@ static void l2cap_chan_rx_init(struct bt_l2cap_le_chan *chan)
724724 }
725725}
726726
727+ static struct net_buf * l2cap_chan_le_get_tx_buf (struct bt_l2cap_le_chan * ch )
728+ {
729+ struct net_buf * buf ;
730+
731+ /* Return current buffer */
732+ if (ch -> tx_buf ) {
733+ buf = ch -> tx_buf ;
734+ ch -> tx_buf = NULL ;
735+ return buf ;
736+ }
737+
738+ return net_buf_get (& ch -> tx_queue , K_NO_WAIT );
739+ }
740+
741+ static int l2cap_chan_le_send_sdu (struct bt_l2cap_le_chan * ch ,
742+ struct net_buf * * buf , u16_t sent );
743+
744+ static void l2cap_chan_tx_process (struct k_work * work )
745+ {
746+ struct bt_l2cap_le_chan * ch ;
747+ struct net_buf * buf ;
748+
749+ ch = CONTAINER_OF (work , struct bt_l2cap_le_chan , tx_work );
750+
751+ /* Resume tx in case there are buffers in the queue */
752+ while ((buf = l2cap_chan_le_get_tx_buf (ch ))) {
753+ int sent = data_sent (buf )-> len ;
754+
755+ BT_DBG ("buf %p sent %u" , buf , sent );
756+
757+ sent = l2cap_chan_le_send_sdu (ch , & buf , sent );
758+ if (sent < 0 ) {
759+ if (sent == - EAGAIN ) {
760+ ch -> tx_buf = buf ;
761+ }
762+ break ;
763+ }
764+ }
765+ }
766+
727767static void l2cap_chan_tx_init (struct bt_l2cap_le_chan * chan )
728768{
729769 BT_DBG ("chan %p" , chan );
730770
731771 (void )memset (& chan -> tx , 0 , sizeof (chan -> tx ));
732772 k_sem_init (& chan -> tx .credits , 0 , UINT_MAX );
733773 k_fifo_init (& chan -> tx_queue );
774+ k_work_init (& chan -> tx_work , l2cap_chan_tx_process );
734775}
735776
736777static void l2cap_chan_tx_give_credits (struct bt_l2cap_le_chan * chan ,
@@ -1180,7 +1221,15 @@ static struct net_buf *l2cap_chan_create_seg(struct bt_l2cap_le_chan *ch,
11801221 return seg ;
11811222}
11821223
1183- static void l2cap_chan_le_send_resume (struct bt_l2cap_le_chan * ch );
1224+ static void l2cap_chan_tx_resume (struct bt_l2cap_le_chan * ch )
1225+ {
1226+ if (!k_sem_count_get (& ch -> tx .credits ) ||
1227+ (k_fifo_is_empty (& ch -> tx_queue ) && !ch -> tx_buf )) {
1228+ return ;
1229+ }
1230+
1231+ k_work_submit (& ch -> tx_work );
1232+ }
11841233
11851234static void l2cap_chan_sdu_sent (struct bt_conn * conn , void * user_data )
11861235{
@@ -1192,7 +1241,7 @@ static void l2cap_chan_sdu_sent(struct bt_conn *conn, void *user_data)
11921241 chan -> ops -> sent (chan );
11931242 }
11941243
1195- l2cap_chan_le_send_resume (BT_L2CAP_LE_CHAN (chan ));
1244+ l2cap_chan_tx_resume (BT_L2CAP_LE_CHAN (chan ));
11961245}
11971246
11981247static void l2cap_chan_seg_sent (struct bt_conn * conn , void * user_data )
@@ -1201,14 +1250,14 @@ static void l2cap_chan_seg_sent(struct bt_conn *conn, void *user_data)
12011250
12021251 BT_DBG ("conn %p chan %p" , conn , chan );
12031252
1204- l2cap_chan_le_send_resume (BT_L2CAP_LE_CHAN (chan ));
1253+ l2cap_chan_tx_resume (BT_L2CAP_LE_CHAN (chan ));
12051254}
12061255
12071256static int l2cap_chan_le_send (struct bt_l2cap_le_chan * ch , struct net_buf * buf ,
12081257 u16_t sdu_hdr_len )
12091258{
12101259 struct net_buf * seg ;
1211- int len ;
1260+ int len , err ;
12121261
12131262 /* Wait for credits */
12141263 if (k_sem_take (& ch -> tx .credits , K_NO_WAIT )) {
@@ -1224,7 +1273,7 @@ static int l2cap_chan_le_send(struct bt_l2cap_le_chan *ch, struct net_buf *buf,
12241273
12251274 /* Channel may have been disconnected while waiting for a buffer */
12261275 if (!ch -> chan .conn ) {
1227- net_buf_unref (buf );
1276+ net_buf_unref (seg );
12281277 return - ECONNRESET ;
12291278 }
12301279
@@ -1237,11 +1286,22 @@ static int l2cap_chan_le_send(struct bt_l2cap_le_chan *ch, struct net_buf *buf,
12371286 * callback has been set.
12381287 */
12391288 if ((buf == seg || !buf -> len ) && ch -> chan .ops -> sent ) {
1240- bt_l2cap_send_cb (ch -> chan .conn , ch -> tx .cid , seg ,
1241- l2cap_chan_sdu_sent , & ch -> chan );
1289+ err = bt_l2cap_send_cb (ch -> chan .conn , ch -> tx .cid , seg ,
1290+ l2cap_chan_sdu_sent , & ch -> chan );
12421291 } else {
1243- bt_l2cap_send_cb (ch -> chan .conn , ch -> tx .cid , seg ,
1244- l2cap_chan_seg_sent , & ch -> chan );
1292+ err = bt_l2cap_send_cb (ch -> chan .conn , ch -> tx .cid , seg ,
1293+ l2cap_chan_seg_sent , & ch -> chan );
1294+ }
1295+
1296+ if (err ) {
1297+ BT_WARN ("Unable to send seg %d" , err );
1298+ k_sem_give (& ch -> tx .credits );
1299+
1300+ if (err == - ENOBUFS ) {
1301+ return - EAGAIN ;
1302+ }
1303+
1304+ return err ;
12451305 }
12461306
12471307 /* Check if there is no credits left clear output status and notify its
@@ -1314,44 +1374,6 @@ static int l2cap_chan_le_send_sdu(struct bt_l2cap_le_chan *ch,
13141374 return ret ;
13151375}
13161376
1317- static struct net_buf * l2cap_chan_le_get_tx_buf (struct bt_l2cap_le_chan * ch )
1318- {
1319- struct net_buf * buf ;
1320-
1321- /* Return current buffer */
1322- if (ch -> tx_buf ) {
1323- buf = ch -> tx_buf ;
1324- ch -> tx_buf = NULL ;
1325- return buf ;
1326- }
1327-
1328- return net_buf_get (& ch -> tx_queue , K_NO_WAIT );
1329- }
1330-
1331- static void l2cap_chan_le_send_resume (struct bt_l2cap_le_chan * ch )
1332- {
1333- struct net_buf * buf ;
1334-
1335- if (!k_sem_count_get (& ch -> tx .credits )) {
1336- return ;
1337- }
1338-
1339- /* Resume tx in case there are buffers in the queue */
1340- while ((buf = l2cap_chan_le_get_tx_buf (ch ))) {
1341- u16_t sent = data_sent (buf )-> len ;
1342-
1343- BT_DBG ("buf %p sent %u" , buf , sent );
1344-
1345- sent = l2cap_chan_le_send_sdu (ch , & buf , sent );
1346- if (sent < 0 ) {
1347- if (sent == - EAGAIN ) {
1348- ch -> tx_buf = buf ;
1349- }
1350- break ;
1351- }
1352- }
1353- }
1354-
13551377static void le_credits (struct bt_l2cap * l2cap , u8_t ident ,
13561378 struct net_buf * buf )
13571379{
@@ -1390,7 +1412,7 @@ static void le_credits(struct bt_l2cap *l2cap, u8_t ident,
13901412 BT_DBG ("chan %p total credits %u" , ch ,
13911413 k_sem_count_get (& ch -> tx .credits ));
13921414
1393- l2cap_chan_le_send_resume (ch );
1415+ l2cap_chan_tx_resume (ch );
13941416}
13951417
13961418static void reject_cmd (struct bt_l2cap * l2cap , u8_t ident ,
@@ -1491,14 +1513,16 @@ static void l2cap_chan_send_credits(struct bt_l2cap_le_chan *chan,
14911513 credits = chan -> rx .init_credits ;
14921514 }
14931515
1494- l2cap_chan_rx_give_credits (chan , credits );
1495-
14961516 buf = l2cap_create_le_sig_pdu (buf , BT_L2CAP_LE_CREDITS , get_ident (),
14971517 sizeof (* ev ));
14981518 if (!buf ) {
1519+ BT_ERR ("Unable to send credits update" );
1520+ bt_l2cap_chan_disconnect (& chan -> chan );
14991521 return ;
15001522 }
15011523
1524+ l2cap_chan_rx_give_credits (chan , credits );
1525+
15021526 ev = net_buf_add (buf , sizeof (* ev ));
15031527 ev -> cid = sys_cpu_to_le16 (chan -> rx .cid );
15041528 ev -> credits = sys_cpu_to_le16 (credits );
@@ -1919,6 +1943,7 @@ int bt_l2cap_chan_disconnect(struct bt_l2cap_chan *chan)
19191943
19201944int bt_l2cap_chan_send (struct bt_l2cap_chan * chan , struct net_buf * buf )
19211945{
1946+ struct bt_l2cap_le_chan * ch = BT_L2CAP_LE_CHAN (chan );
19221947 int err ;
19231948
19241949 if (!buf ) {
@@ -1936,24 +1961,19 @@ int bt_l2cap_chan_send(struct bt_l2cap_chan *chan, struct net_buf *buf)
19361961 return bt_l2cap_br_chan_send (chan , buf );
19371962 }
19381963
1939- /* Attempt to resume first since there could be data from previous
1940- * packets pending.
1941- */
1942- l2cap_chan_le_send_resume (BT_L2CAP_LE_CHAN (chan ));
1943-
1944- /* Check if there are still pending segments */
1945- if (BT_L2CAP_LE_CHAN (chan )-> tx_buf ) {
1946- /* Queue buffer to be sent later */
1964+ /* Queue if there pending segments left from previous packets */
1965+ if (ch -> tx_buf || !k_fifo_is_empty (& ch -> tx_queue )) {
19471966 data_sent (buf )-> len = 0 ;
1948- net_buf_put (& (BT_L2CAP_LE_CHAN (chan ))-> tx_queue , buf );
1967+ net_buf_put (& ch -> tx_queue , buf );
1968+ k_work_submit (& ch -> tx_work );
19491969 return 0 ;
19501970 }
19511971
1952- err = l2cap_chan_le_send_sdu (BT_L2CAP_LE_CHAN ( chan ) , & buf , 0 );
1972+ err = l2cap_chan_le_send_sdu (ch , & buf , 0 );
19531973 if (err < 0 ) {
19541974 if (err == - EAGAIN && data_sent (buf )-> len ) {
19551975 /* Queue buffer if at least one segment could be sent */
1956- net_buf_put (& ( BT_L2CAP_LE_CHAN ( chan )) -> tx_queue , buf );
1976+ net_buf_put (& ch -> tx_queue , buf );
19571977 return data_sent (buf )-> len ;
19581978 }
19591979 BT_ERR ("failed to send message %d" , err );
0 commit comments