Bluetooth: Fix bt_buff lifecycle

Signed-off-by: Brennan Ashton <bashton@brennanashton.com>
This commit is contained in:
Brennan Ashton 2020-12-20 16:57:06 -08:00 committed by Xiang Xiao
parent ec73a4e69c
commit c6947199b2
5 changed files with 90 additions and 36 deletions

View file

@ -120,8 +120,6 @@ static int bthcisock_send(FAR const struct bt_driver_s *dev,
return -1; return -1;
} }
bt_buf_release(buf);
return buf->len; return buf->len;
} }

View file

@ -178,7 +178,7 @@ static int conn_tx_kthread(int argc, FAR char *argv[])
} }
wlinfo("passing buf %p len %u to driver\n", buf, buf->len); wlinfo("passing buf %p len %u to driver\n", buf, buf->len);
g_btdev.btdev->send(g_btdev.btdev, buf); bt_send(g_btdev.btdev, buf);
bt_buf_release(buf); bt_buf_release(buf);
} }

View file

@ -124,30 +124,6 @@ static struct work_s g_hp_work;
* Private Functions * Private Functions
****************************************************************************/ ****************************************************************************/
/****************************************************************************
* Name: bt_send
*
* Description:
* Add the provided buffer 'buf' to the head selected buffer list 'list'
*
* Input Parameters:
* btdev - An instance of the low-level drivers interface structure.
* buf - The buffer to be sent by the driver
*
* Returned Value:
* Zero is returned on success; a negated errno value is returned on any
* failure.
*
****************************************************************************/
static int bt_send(FAR const struct bt_driver_s *btdev,
FAR struct bt_buf_s *buf)
{
/* TODDO: Hook here to notify hci monitor */
return btdev->send(btdev, buf);
}
/**************************************************************************** /****************************************************************************
* Name: bt_enqueue_bufwork * Name: bt_enqueue_bufwork
* *
@ -354,9 +330,17 @@ static void hci_cmd_done(uint16_t opcode, uint8_t status,
return; return;
} }
if (g_btdev.sent_cmd == NULL)
{
wlerr("ERROR: Request cmd missing!\n");
return;
}
if (g_btdev.sent_cmd->u.hci.opcode != opcode) if (g_btdev.sent_cmd->u.hci.opcode != opcode)
{ {
wlerr("ERROR: Unexpected completion of opcode 0x%04x\n", opcode); wlerr("ERROR: Unexpected completion of opcode 0x%04x " \
"expected 0x%04x\n",
opcode, g_btdev.sent_cmd->u.hci.opcode);
return; return;
} }
@ -380,10 +364,8 @@ static void hci_cmd_done(uint16_t opcode, uint8_t status,
nxsem_post(sem); nxsem_post(sem);
} }
else
{ bt_buf_release(sent);
bt_buf_release(sent);
}
} }
static void hci_cmd_complete(FAR struct bt_buf_s *buf) static void hci_cmd_complete(FAR struct bt_buf_s *buf)
@ -1045,12 +1027,13 @@ static int hci_tx_kthread(int argc, FAR char *argv[])
g_btdev.sent_cmd = NULL; g_btdev.sent_cmd = NULL;
} }
g_btdev.sent_cmd = buf; g_btdev.sent_cmd = bt_buf_addref(buf);
wlinfo("Sending command %04x buf %p to driver\n", wlinfo("Sending command %04x buf %p to driver\n",
buf->u.hci.opcode, buf); buf->u.hci.opcode, buf);
btdev->send(btdev, buf); bt_send(btdev, buf);
bt_buf_release(buf);
} }
return EXIT_SUCCESS; /* Can't get here */ return EXIT_SUCCESS; /* Can't get here */
@ -1104,6 +1087,7 @@ static void hci_rx_work(FAR void *arg)
#else #else
g_hci_cb->received(buf, g_hci_cb->context); g_hci_cb->received(buf, g_hci_cb->context);
#endif #endif
bt_buf_release(buf);
} }
} }
@ -1171,6 +1155,7 @@ static void priority_rx_work(FAR void *arg)
g_hci_cb->received(buf, g_hci_cb->context); g_hci_cb->received(buf, g_hci_cb->context);
#endif #endif
bt_buf_release(buf);
} }
} }
@ -1486,6 +1471,36 @@ static void cmd_queue_init(void)
* Public Functions * Public Functions
****************************************************************************/ ****************************************************************************/
/****************************************************************************
* Name: bt_send
*
* Description:
* Send the provided buffer to the bluetooth driver
*
* Input Parameters:
* btdev - An instance of the low-level drivers interface structure.
* buf - The buffer to be sent by the driver
*
* Returned Value:
* Zero is returned on success; a negated errno value is returned on any
* failure.
*
****************************************************************************/
int bt_send(FAR const struct bt_driver_s *btdev,
FAR struct bt_buf_s *buf)
{
int ret;
/* Send to driver */
ret = btdev->send(btdev, buf);
/* TODO: Hook here to notify hci monitor */
return ret;
}
/**************************************************************************** /****************************************************************************
* Name: bt_initialize * Name: bt_initialize
* *
@ -1731,6 +1746,15 @@ int bt_hci_cmd_send(uint16_t opcode, FAR struct bt_buf_s *buf)
return -ENOBUFS; return -ENOBUFS;
} }
} }
else
{
/* We manage the refcount the same for supplied and created
* buffers so increment the supplied count so we can manage
* it as-if we crated it.
*/
bt_buf_addref(buf);
}
wlinfo("opcode %04x len %u\n", opcode, buf->len); wlinfo("opcode %04x len %u\n", opcode, buf->len);
@ -1774,6 +1798,10 @@ int bt_hci_cmd_send_sync(uint16_t opcode, FAR struct bt_buf_s *buf,
return -ENOBUFS; return -ENOBUFS;
} }
} }
else
{
bt_buf_addref(buf);
}
wlinfo("opcode %04x len %u\n", opcode, buf->len); wlinfo("opcode %04x len %u\n", opcode, buf->len);
@ -1850,12 +1878,21 @@ int bt_hci_cmd_send_sync(uint16_t opcode, FAR struct bt_buf_s *buf,
} }
} }
/* Note: if ret < 0 the packet might just be delayed and could still
* be sent. We cannot decrease the ref count since it if it was sent
* it buf could be pointed a completely different request.
*/
if (rsp != NULL) if (rsp != NULL)
{ {
/* If the response is expected provide the sync response */
*rsp = buf->u.hci.sync; *rsp = buf->u.hci.sync;
} }
else if (buf->u.hci.sync != NULL) else if (buf->u.hci.sync != NULL)
{ {
/* If a sync response was given but not requested drop it */
bt_buf_release(buf->u.hci.sync); bt_buf_release(buf->u.hci.sync);
} }

View file

@ -302,6 +302,25 @@ int bt_driver_register(FAR const struct bt_driver_s *btdev);
void bt_driver_unregister(FAR const struct bt_driver_s *btdev); void bt_driver_unregister(FAR const struct bt_driver_s *btdev);
/****************************************************************************
* Name: bt_send
*
* Description:
* Add the provided buffer 'buf' to the head selected buffer list 'list'
*
* Input Parameters:
* btdev - An instance of the low-level drivers interface structure.
* buf - The buffer to be sent by the driver
*
* Returned Value:
* Zero is returned on success; a negated errno value is returned on any
* failure.
*
****************************************************************************/
int bt_send(FAR const struct bt_driver_s *btdev,
FAR struct bt_buf_s *buf);
#ifdef CONFIG_WIRELESS_BLUETOOTH_HOST #ifdef CONFIG_WIRELESS_BLUETOOTH_HOST
/**************************************************************************** /****************************************************************************
* Name: bt_hci_cmd_create * Name: bt_hci_cmd_create

View file

@ -615,7 +615,6 @@ drop:
/* Release our reference on the buffer */ /* Release our reference on the buffer */
bt_buf_release(buf);
net_unlock(); net_unlock();
} }
@ -1222,7 +1221,8 @@ static int btnet_req_hci_data(FAR struct btnet_driver_s *priv,
return -ENOMEM; return -ENOMEM;
} }
g_btdev.btdev->send(g_btdev.btdev, buf); bt_send(g_btdev.btdev, buf);
bt_buf_release(buf);
/* Transfer the frame to the Bluetooth stack. */ /* Transfer the frame to the Bluetooth stack. */