Bluetooth: L2CAP: Make bt_l2cap_send_pdu()
This API replaces `bt_l2cap_send()` and `bt_l2cap_send_cb()`. The difference is that it takes the `struct bt_l2cap_le_chan` object directly instead of a connection + CID. We need the channel object in order to put the PDU on the TX queue. It is inefficient to do a search for every PDU when the caller knows the channel object's address and can just pass it down. Signed-off-by: Jonathan Rico <jonathan.rico@nordicsemi.no>
This commit is contained in:
parent
28535fe2f2
commit
38820efd8d
5 changed files with 34 additions and 40 deletions
|
@ -353,7 +353,7 @@ static int chan_send(struct bt_att_chan *chan, struct net_buf *buf)
|
|||
|
||||
data->att_chan = chan;
|
||||
|
||||
err = bt_l2cap_send(chan->att->conn, BT_L2CAP_CID_ATT, buf);
|
||||
err = bt_l2cap_send_pdu(&chan->chan, buf, NULL, NULL);
|
||||
if (err) {
|
||||
if (err == -ENOBUFS) {
|
||||
LOG_ERR("Ran out of TX buffers or contexts.");
|
||||
|
|
|
@ -545,7 +545,10 @@ static struct net_buf *l2cap_create_le_sig_pdu(uint8_t code, uint8_t ident,
|
|||
*/
|
||||
static int l2cap_send_sig(struct bt_conn *conn, struct net_buf *buf)
|
||||
{
|
||||
int err = bt_l2cap_send(conn, BT_L2CAP_CID_LE_SIG, buf);
|
||||
struct bt_l2cap_chan *ch = bt_l2cap_le_lookup_tx_cid(conn, BT_L2CAP_CID_LE_SIG);
|
||||
struct bt_l2cap_le_chan *chan = BT_L2CAP_LE_CHAN(ch);
|
||||
|
||||
int err = bt_l2cap_send_pdu(chan, buf, NULL, NULL);
|
||||
|
||||
if (err) {
|
||||
net_buf_unref(buf);
|
||||
|
@ -771,46 +774,41 @@ static void cancel_data_ready(struct bt_l2cap_le_chan *le_chan)
|
|||
atomic_set(&le_chan->_pdu_ready_lock, 0);
|
||||
}
|
||||
|
||||
int bt_l2cap_send_cb(struct bt_conn *conn, uint16_t cid, struct net_buf *seg,
|
||||
bt_conn_tx_cb_t cb, void *user_data)
|
||||
int bt_l2cap_send_pdu(struct bt_l2cap_le_chan *le_chan, struct net_buf *pdu,
|
||||
bt_conn_tx_cb_t cb, void *user_data)
|
||||
{
|
||||
struct bt_l2cap_hdr *hdr;
|
||||
|
||||
LOG_DBG("conn %p cid %u len %zu", conn, cid, seg->len);
|
||||
LOG_DBG("chan %p len %zu", le_chan, pdu->len);
|
||||
|
||||
hdr = net_buf_push(seg, sizeof(*hdr));
|
||||
hdr->len = sys_cpu_to_le16(seg->len - sizeof(*hdr));
|
||||
hdr->cid = sys_cpu_to_le16(cid);
|
||||
hdr = net_buf_push(pdu, sizeof(*hdr));
|
||||
hdr->len = sys_cpu_to_le16(pdu->len - sizeof(*hdr));
|
||||
hdr->cid = sys_cpu_to_le16(le_chan->tx.cid);
|
||||
|
||||
/* TODO: un-foreach this: ATT, SMP & L2CAP CoC _know_ the channel */
|
||||
struct bt_l2cap_chan *ch = bt_l2cap_le_lookup_tx_cid(conn, cid);
|
||||
|
||||
struct bt_l2cap_le_chan *chan = CONTAINER_OF(ch, struct bt_l2cap_le_chan, chan);
|
||||
|
||||
if (seg->ref != 1) {
|
||||
if (pdu->ref != 1) {
|
||||
/* The host may alter the buf contents when fragmenting. Higher
|
||||
* layers cannot expect the buf contents to stay intact. Extra
|
||||
* refs suggests a silent data corruption would occur if not for
|
||||
* this error.
|
||||
*/
|
||||
LOG_ERR("Expecting 1 ref, got %d", seg->ref);
|
||||
LOG_ERR("Expecting 1 ref, got %d", pdu->ref);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (seg->user_data_size < sizeof(struct closure)) {
|
||||
if (pdu->user_data_size < sizeof(struct closure)) {
|
||||
LOG_DBG("not enough room in user_data %d < %d pool %u",
|
||||
seg->user_data_size,
|
||||
pdu->user_data_size,
|
||||
CONFIG_BT_CONN_TX_USER_DATA_SIZE,
|
||||
seg->pool_id);
|
||||
pdu->pool_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
make_closure(seg->user_data, cb, user_data);
|
||||
make_closure(pdu->user_data, cb, user_data);
|
||||
LOG_DBG("push: cb %p userdata %p", cb, user_data);
|
||||
|
||||
net_buf_put(&chan->_pdu_tx_queue, seg);
|
||||
net_buf_put(&le_chan->_pdu_tx_queue, pdu);
|
||||
|
||||
raise_data_ready(chan); /* tis just a flag */
|
||||
raise_data_ready(le_chan); /* tis just a flag */
|
||||
|
||||
return 0; /* look ma, no failures */
|
||||
}
|
||||
|
@ -2210,8 +2208,7 @@ static int l2cap_chan_le_send_seg(struct bt_l2cap_le_chan *ch, struct net_buf *b
|
|||
* considered lost, as the lower layers are free to re-use it as they
|
||||
* see fit. Reading from it later is obviously a no-no.
|
||||
*/
|
||||
err = bt_l2cap_send_cb(ch->chan.conn, ch->tx.cid, seg,
|
||||
cb, UINT_TO_POINTER(ch->tx.cid));
|
||||
err = bt_l2cap_send_pdu(ch, seg, cb, UINT_TO_POINTER(ch->tx.cid));
|
||||
|
||||
/* The only possible error is enotconn, in that case the data will be discarded anyways */
|
||||
__ASSERT_NO_MSG(!err || err == -ENOTCONN);
|
||||
|
@ -2221,7 +2218,7 @@ static int l2cap_chan_le_send_seg(struct bt_l2cap_le_chan *ch, struct net_buf *b
|
|||
atomic_inc(&ch->tx.credits);
|
||||
|
||||
/* The host takes ownership of the reference in seg when
|
||||
* bt_l2cap_send_cb is successful. The call returned an error,
|
||||
* bt_l2cap_send_pdu is successful. The call returned an error,
|
||||
* so we must get rid of the reference that was taken above.
|
||||
*/
|
||||
LOG_DBG("unref %p (%s)", seg,
|
||||
|
@ -3365,8 +3362,7 @@ int bt_l2cap_chan_send(struct bt_l2cap_chan *chan, struct net_buf *buf)
|
|||
}
|
||||
|
||||
/* Sending over static channels is not supported by this fn. Use
|
||||
* `bt_l2cap_send()` if external to this file, or `l2cap_send` if
|
||||
* internal.
|
||||
* `bt_l2cap_send_pdu()` instead.
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL)) {
|
||||
struct bt_l2cap_le_chan *le_chan = BT_L2CAP_LE_CHAN(chan);
|
||||
|
|
|
@ -214,14 +214,8 @@ struct net_buf *bt_l2cap_create_pdu_timeout(struct net_buf_pool *pool,
|
|||
*
|
||||
* Buffer ownership is transferred to stack in case of success.
|
||||
*/
|
||||
int bt_l2cap_send_cb(struct bt_conn *conn, uint16_t cid, struct net_buf *buf,
|
||||
bt_conn_tx_cb_t cb, void *user_data);
|
||||
|
||||
static inline int bt_l2cap_send(struct bt_conn *conn, uint16_t cid,
|
||||
struct net_buf *buf)
|
||||
{
|
||||
return bt_l2cap_send_cb(conn, cid, buf, NULL, NULL);
|
||||
}
|
||||
int bt_l2cap_send_pdu(struct bt_l2cap_le_chan *le_chan, struct net_buf *pdu,
|
||||
bt_conn_tx_cb_t cb, void *user_data);
|
||||
|
||||
/* Receive a new L2CAP PDU from a connection */
|
||||
void bt_l2cap_recv(struct bt_conn *conn, struct net_buf *buf, bool complete);
|
||||
|
@ -254,4 +248,6 @@ void bt_l2cap_register_ecred_cb(const struct bt_l2cap_ecred_cb *cb);
|
|||
struct bt_l2cap_server *bt_l2cap_server_lookup_psm(uint16_t psm);
|
||||
|
||||
/* Pull data from the L2CAP layer */
|
||||
struct net_buf *l2cap_data_pull(struct bt_conn *conn, size_t amount);
|
||||
struct net_buf *l2cap_data_pull(struct bt_conn *conn,
|
||||
size_t amount,
|
||||
size_t *length);
|
||||
|
|
|
@ -1750,7 +1750,9 @@ static void smp_timeout(struct k_work *work)
|
|||
static void smp_send(struct bt_smp *smp, struct net_buf *buf,
|
||||
bt_conn_tx_cb_t cb, void *user_data)
|
||||
{
|
||||
int err = bt_l2cap_send_cb(smp->chan.chan.conn, BT_L2CAP_CID_SMP, buf, cb, NULL);
|
||||
__ASSERT_NO_MSG(user_data == NULL);
|
||||
|
||||
int err = bt_l2cap_send_pdu(&smp->chan, buf, cb, NULL);
|
||||
|
||||
if (err) {
|
||||
if (err == -ENOBUFS) {
|
||||
|
@ -1805,7 +1807,7 @@ static int smp_error(struct bt_smp *smp, uint8_t reason)
|
|||
rsp->reason = reason;
|
||||
|
||||
/* SMP timer is not restarted for PairingFailed so don't use smp_send */
|
||||
if (bt_l2cap_send(smp->chan.chan.conn, BT_L2CAP_CID_SMP, buf)) {
|
||||
if (bt_l2cap_send_pdu(&smp->chan, buf, NULL, NULL)) {
|
||||
net_buf_unref(buf);
|
||||
}
|
||||
|
||||
|
@ -2824,7 +2826,7 @@ static int smp_send_security_req(struct bt_conn *conn)
|
|||
req->auth_req = get_auth(smp, BT_SMP_AUTH_DEFAULT);
|
||||
|
||||
/* SMP timer is not restarted for SecRequest so don't use smp_send */
|
||||
err = bt_l2cap_send(conn, BT_L2CAP_CID_SMP, req_buf);
|
||||
err = bt_l2cap_send_pdu(&smp->chan, req_buf, NULL, NULL);
|
||||
if (err) {
|
||||
net_buf_unref(req_buf);
|
||||
return err;
|
||||
|
|
|
@ -41,7 +41,7 @@ int bt_smp_sign(struct bt_conn *conn, struct net_buf *buf)
|
|||
|
||||
static int bt_smp_recv(struct bt_l2cap_chan *chan, struct net_buf *req_buf)
|
||||
{
|
||||
struct bt_conn *conn = chan->conn;
|
||||
struct bt_l2cap_le_chan *le_chan = BT_L2CAP_LE_CHAN(chan);
|
||||
struct bt_smp_pairing_fail *rsp;
|
||||
struct bt_smp_hdr *hdr;
|
||||
struct net_buf *buf;
|
||||
|
@ -63,7 +63,7 @@ static int bt_smp_recv(struct bt_l2cap_chan *chan, struct net_buf *req_buf)
|
|||
rsp = net_buf_add(buf, sizeof(*rsp));
|
||||
rsp->reason = BT_SMP_ERR_PAIRING_NOTSUPP;
|
||||
|
||||
if (bt_l2cap_send(conn, BT_L2CAP_CID_SMP, buf)) {
|
||||
if (bt_l2cap_send_pdu(le_chan, buf, NULL, NULL)) {
|
||||
net_buf_unref(buf);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue