Bluetooth: Fix returning unacknowledged packets upon disconnection
The core specification says the following about the treatment of unacknowledged packets when a disconnection occurs (page 773 in core spec 4.2): "When the Host receives a Disconnection Complete, Disconnection Physical Link Complete or Disconnection Logical Link Complete event, the Host shall assume that all unacknowledged HCI Data Packets that have been sent to the Controller for the returned Handle have been flushed, and that the corresponding data buffers have been freed. A Primary Controller does not have to notify the Host about this in a Number Of Completed Packets event" This patch adds tracking of unacknowledged packets on a per-connection basis and makes sure the semaphore that counts controller buffers is given back the appropriate amount when a disconnection occurs. Change-Id: I2ff4d12ffa50d4dda5b3e8c75fc75b4c0927e609 Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
This commit is contained in:
parent
4cdcd228a2
commit
4817c96b68
3 changed files with 28 additions and 1 deletions
|
@ -317,6 +317,8 @@ static void conn_tx_fiber(int arg1, int arg2)
|
|||
BT_DBG("passing buf %p len %u to driver\n", buf, buf->len);
|
||||
bt_dev.drv->send(buf);
|
||||
bt_buf_put(buf);
|
||||
|
||||
conn->pending_pkts++;
|
||||
}
|
||||
|
||||
BT_DBG("handle %u disconnected - cleaning up\n", conn->handle);
|
||||
|
@ -326,6 +328,13 @@ static void conn_tx_fiber(int arg1, int arg2)
|
|||
bt_buf_put(buf);
|
||||
}
|
||||
|
||||
/* Return any unacknowledged packets */
|
||||
if (conn->pending_pkts) {
|
||||
while (conn->pending_pkts--) {
|
||||
nano_fiber_sem_give(&bt_dev.le_pkts_sem);
|
||||
}
|
||||
}
|
||||
|
||||
bt_conn_reset_rx_state(conn);
|
||||
|
||||
BT_DBG("handle %u exiting\n", conn->handle);
|
||||
|
|
|
@ -60,6 +60,8 @@ struct bt_conn {
|
|||
bt_addr_le_t init_addr;
|
||||
bt_addr_le_t resp_addr;
|
||||
|
||||
uint8_t pending_pkts;
|
||||
|
||||
uint8_t encrypt;
|
||||
bt_security_t sec_level;
|
||||
bt_security_t required_sec_level;
|
||||
|
|
|
@ -473,14 +473,30 @@ static void hci_num_completed_packets(struct bt_buf *buf)
|
|||
|
||||
for (i = 0; i < num_handles; i++) {
|
||||
uint16_t handle, count;
|
||||
struct bt_conn *conn;
|
||||
|
||||
handle = sys_le16_to_cpu(evt->h[i].handle);
|
||||
count = sys_le16_to_cpu(evt->h[i].count);
|
||||
|
||||
BT_DBG("handle %u count %u\n", handle, count);
|
||||
|
||||
while (count--)
|
||||
conn = bt_conn_lookup_handle(handle);
|
||||
if (conn) {
|
||||
if (conn->pending_pkts >= count) {
|
||||
conn->pending_pkts -= count;
|
||||
} else {
|
||||
BT_ERR("completed packets mismatch: %u > %u\n",
|
||||
count, conn->pending_pkts);
|
||||
conn->pending_pkts = 0;
|
||||
}
|
||||
bt_conn_put(conn);
|
||||
} else {
|
||||
BT_ERR("No matching connection for handle %u", handle);
|
||||
}
|
||||
|
||||
while (count--) {
|
||||
nano_fiber_sem_give(&bt_dev.le_pkts_sem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue