mirror of
https://github.com/apache/nuttx.git
synced 2026-08-01 20:28:58 +00:00
arch/arm/nrf52,nrf53: don't pass HCI messages under the lock
on_hci() ran the host upcall with g_sdc_dev.lock held. On nrf53 this deadlocks the BLE link: the upcall waits for the app core, which cannot answer while bt_hci_send() blocks on the same lock. nrf52 modified for consistency, deadlock is not possible there. Signed-off-by: raiden00pl <raiden00@railab.me> Assisted-by: Claude Code
This commit is contained in:
parent
44299ddfcf
commit
57d384f466
2 changed files with 50 additions and 48 deletions
|
|
@ -181,10 +181,10 @@
|
|||
struct nrf52_sdc_dev_s
|
||||
{
|
||||
uint8_t *mempool; /* Must be 8 bytes aligned */
|
||||
uint8_t msg_buffer[HCI_MSG_BUFFER_MAX_SIZE];
|
||||
|
||||
mutex_t lock;
|
||||
struct work_s work;
|
||||
struct work_s hci_work;
|
||||
};
|
||||
|
||||
begin_packed_struct struct sdc_hci_cmd_vs_zephyr_write_bd_addr_s
|
||||
|
|
@ -308,7 +308,7 @@ static int bt_hci_send(struct bt_driver_s *btdev,
|
|||
{
|
||||
ret = len;
|
||||
|
||||
work_queue(LPWORK, &g_sdc_dev.work, on_hci_worker, NULL, 0);
|
||||
work_queue(LPWORK, &g_sdc_dev.hci_work, on_hci_worker, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -354,22 +354,7 @@ static void low_prio_worker(void *arg)
|
|||
|
||||
static void on_hci_worker(void *arg)
|
||||
{
|
||||
/* We use this worker to force a call to on_hci() right after sending
|
||||
* an HCI command as MPSL/SDC does not always signal the low priority
|
||||
* worker
|
||||
*/
|
||||
|
||||
nxmutex_lock(&g_sdc_dev.lock);
|
||||
on_hci();
|
||||
nxmutex_unlock(&g_sdc_dev.lock);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: on_hci
|
||||
****************************************************************************/
|
||||
|
||||
static void on_hci(void)
|
||||
{
|
||||
uint8_t msg_buffer[HCI_MSG_BUFFER_MAX_SIZE];
|
||||
sdc_hci_msg_type_t type;
|
||||
bool check_again;
|
||||
size_t len;
|
||||
|
|
@ -383,13 +368,16 @@ static void on_hci(void)
|
|||
* buffer and then create an actual bt_buf_s, depending on msg length
|
||||
*/
|
||||
|
||||
ret = sdc_hci_get(g_sdc_dev.msg_buffer, &type);
|
||||
nxmutex_lock(&g_sdc_dev.lock);
|
||||
ret = sdc_hci_get(msg_buffer, &type);
|
||||
nxmutex_unlock(&g_sdc_dev.lock);
|
||||
|
||||
if (ret == 0)
|
||||
{
|
||||
if (type == SDC_HCI_MSG_TYPE_EVT)
|
||||
{
|
||||
struct bt_hci_evt_hdr_s *hdr =
|
||||
(struct bt_hci_evt_hdr_s *)g_sdc_dev.msg_buffer;
|
||||
(struct bt_hci_evt_hdr_s *)msg_buffer;
|
||||
|
||||
len = sizeof(*hdr) + hdr->len;
|
||||
|
||||
|
|
@ -398,7 +386,7 @@ static void on_hci(void)
|
|||
{
|
||||
struct hci_evt_cmd_complete_s *cmd_complete =
|
||||
(struct hci_evt_cmd_complete_s *)
|
||||
(g_sdc_dev.msg_buffer + sizeof(*hdr));
|
||||
(msg_buffer + sizeof(*hdr));
|
||||
uint8_t *status = (uint8_t *)cmd_complete + 3;
|
||||
|
||||
wlinfo("received CMD_COMPLETE from softdevice "
|
||||
|
|
@ -413,14 +401,14 @@ static void on_hci(void)
|
|||
#endif
|
||||
|
||||
bt_netdev_receive(&g_bt_driver, BT_EVT,
|
||||
g_sdc_dev.msg_buffer, len);
|
||||
msg_buffer, len);
|
||||
check_again = true;
|
||||
}
|
||||
|
||||
if (type == SDC_HCI_MSG_TYPE_DATA)
|
||||
{
|
||||
struct bt_hci_acl_hdr_s *hdr =
|
||||
(struct bt_hci_acl_hdr_s *)g_sdc_dev.msg_buffer;
|
||||
(struct bt_hci_acl_hdr_s *)msg_buffer;
|
||||
|
||||
wlinfo("received HCI ACL from softdevice (handle: %d)\n",
|
||||
hdr->handle);
|
||||
|
|
@ -428,7 +416,7 @@ static void on_hci(void)
|
|||
len = sizeof(*hdr) + hdr->len;
|
||||
|
||||
bt_netdev_receive(&g_bt_driver, BT_ACL_IN,
|
||||
g_sdc_dev.msg_buffer, len);
|
||||
msg_buffer, len);
|
||||
check_again = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -436,6 +424,19 @@ static void on_hci(void)
|
|||
while (check_again);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: on_hci
|
||||
*
|
||||
* Description:
|
||||
* SDC message callback.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void on_hci(void)
|
||||
{
|
||||
work_queue(LPWORK, &g_sdc_dev.hci_work, on_hci_worker, NULL, 0);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: swi_isr
|
||||
****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -182,10 +182,10 @@
|
|||
struct nrf53_sdc_dev_s
|
||||
{
|
||||
uint8_t *mempool; /* Must be 8 bytes aligned */
|
||||
uint8_t msg_buffer[HCI_MSG_BUFFER_MAX_SIZE];
|
||||
|
||||
mutex_t lock;
|
||||
struct work_s work;
|
||||
struct work_s hci_work;
|
||||
};
|
||||
|
||||
begin_packed_struct struct sdc_hci_cmd_vs_zephyr_write_bd_addr_s
|
||||
|
|
@ -309,7 +309,7 @@ static int bt_hci_send(struct bt_driver_s *btdev,
|
|||
{
|
||||
ret = len;
|
||||
|
||||
work_queue(LPWORK, &g_sdc_dev.work, on_hci_worker, NULL, 0);
|
||||
work_queue(LPWORK, &g_sdc_dev.hci_work, on_hci_worker, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -355,22 +355,7 @@ static void low_prio_worker(void *arg)
|
|||
|
||||
static void on_hci_worker(void *arg)
|
||||
{
|
||||
/* We use this worker to force a call to on_hci() right after sending
|
||||
* an HCI command as MPSL/SDC does not always signal the low priority
|
||||
* worker
|
||||
*/
|
||||
|
||||
nxmutex_lock(&g_sdc_dev.lock);
|
||||
on_hci();
|
||||
nxmutex_unlock(&g_sdc_dev.lock);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: on_hci
|
||||
****************************************************************************/
|
||||
|
||||
static void on_hci(void)
|
||||
{
|
||||
uint8_t msg_buffer[HCI_MSG_BUFFER_MAX_SIZE];
|
||||
sdc_hci_msg_type_t type;
|
||||
bool check_again;
|
||||
size_t len;
|
||||
|
|
@ -384,13 +369,16 @@ static void on_hci(void)
|
|||
* buffer and then create an actual bt_buf_s, depending on msg length
|
||||
*/
|
||||
|
||||
ret = sdc_hci_get(g_sdc_dev.msg_buffer, &type);
|
||||
nxmutex_lock(&g_sdc_dev.lock);
|
||||
ret = sdc_hci_get(msg_buffer, &type);
|
||||
nxmutex_unlock(&g_sdc_dev.lock);
|
||||
|
||||
if (ret == 0)
|
||||
{
|
||||
if (type == SDC_HCI_MSG_TYPE_EVT)
|
||||
{
|
||||
struct bt_hci_evt_hdr_s *hdr =
|
||||
(struct bt_hci_evt_hdr_s *)g_sdc_dev.msg_buffer;
|
||||
(struct bt_hci_evt_hdr_s *)msg_buffer;
|
||||
|
||||
len = sizeof(*hdr) + hdr->len;
|
||||
|
||||
|
|
@ -399,7 +387,7 @@ static void on_hci(void)
|
|||
{
|
||||
struct hci_evt_cmd_complete_s *cmd_complete =
|
||||
(struct hci_evt_cmd_complete_s *)
|
||||
(g_sdc_dev.msg_buffer + sizeof(*hdr));
|
||||
(msg_buffer + sizeof(*hdr));
|
||||
uint8_t *status = (uint8_t *)cmd_complete + 3;
|
||||
|
||||
wlinfo("received CMD_COMPLETE from softdevice "
|
||||
|
|
@ -414,14 +402,14 @@ static void on_hci(void)
|
|||
#endif
|
||||
|
||||
bt_netdev_receive(&g_bt_driver, BT_EVT,
|
||||
g_sdc_dev.msg_buffer, len);
|
||||
msg_buffer, len);
|
||||
check_again = true;
|
||||
}
|
||||
|
||||
if (type == SDC_HCI_MSG_TYPE_DATA)
|
||||
{
|
||||
struct bt_hci_acl_hdr_s *hdr =
|
||||
(struct bt_hci_acl_hdr_s *)g_sdc_dev.msg_buffer;
|
||||
(struct bt_hci_acl_hdr_s *)msg_buffer;
|
||||
|
||||
wlinfo("received HCI ACL from softdevice (handle: %d)\n",
|
||||
hdr->handle);
|
||||
|
|
@ -429,7 +417,7 @@ static void on_hci(void)
|
|||
len = sizeof(*hdr) + hdr->len;
|
||||
|
||||
bt_netdev_receive(&g_bt_driver, BT_ACL_IN,
|
||||
g_sdc_dev.msg_buffer, len);
|
||||
msg_buffer, len);
|
||||
check_again = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -437,6 +425,19 @@ static void on_hci(void)
|
|||
while (check_again);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: on_hci
|
||||
*
|
||||
* Description:
|
||||
* SDC message callback.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void on_hci(void)
|
||||
{
|
||||
work_queue(LPWORK, &g_sdc_dev.hci_work, on_hci_worker, NULL, 0);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: swi_isr
|
||||
****************************************************************************/
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue