There were changes done to controller code that cause tests to do not build and fail during execution. Changes are related with: - modified code related with extended advertising ADI field handling - added generic double buffer data structure that is used in controller - moved code that was building only when DF is enabled - added EVENTS_PHYEND that is not available in nrfbsim board The PR addresses those issues. Signed-off-by: Piotr Pryga <piotr.pryga@nordicsemi.no>
353 lines
6.7 KiB
C
353 lines
6.7 KiB
C
/*
|
|
* Copyright (c) 2020 Nordic Semiconductor ASA
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <zephyr/types.h>
|
|
|
|
#include <bluetooth/hci.h>
|
|
|
|
#include "hal/cpu_vendor_hal.h"
|
|
#include "hal/ccm.h"
|
|
|
|
#include "util/mem.h"
|
|
#include "util/mfifo.h"
|
|
#include "util/memq.h"
|
|
#include "util/dbuf.h"
|
|
#include "util.h"
|
|
|
|
#include "pdu.h"
|
|
#include "ll.h"
|
|
#include "ll_feat.h"
|
|
#include "ll_settings.h"
|
|
#include "lll.h"
|
|
#include "lll_vendor.h"
|
|
#include "lll/lll_adv_types.h"
|
|
#include "lll_adv.h"
|
|
#include "lll/lll_adv_pdu.h"
|
|
#include "lll_scan.h"
|
|
#include "lll_sync.h"
|
|
#include "lll/lll_df_types.h"
|
|
#include "lll_conn.h"
|
|
|
|
#define EVENT_DONE_MAX 3
|
|
/* Backing storage for elements in mfifo_done */
|
|
static struct {
|
|
void *free;
|
|
uint8_t pool[sizeof(struct node_rx_event_done) * EVENT_DONE_MAX];
|
|
} mem_done;
|
|
|
|
static struct {
|
|
void *free;
|
|
uint8_t pool[sizeof(memq_link_t) * EVENT_DONE_MAX];
|
|
} mem_link_done;
|
|
|
|
#if defined(CONFIG_BT_CTLR_PHY) && defined(CONFIG_BT_CTLR_DATA_LENGTH)
|
|
#define LL_PDU_RX_CNT (3 + 128)
|
|
#else
|
|
#define LL_PDU_RX_CNT (2 + 128)
|
|
#endif
|
|
|
|
#define PDU_RX_CNT (CONFIG_BT_CTLR_RX_BUFFERS + 3)
|
|
#define RX_CNT (PDU_RX_CNT + LL_PDU_RX_CNT)
|
|
|
|
static MFIFO_DEFINE(pdu_rx_free, sizeof(void *), PDU_RX_CNT);
|
|
|
|
#if defined(CONFIG_BT_RX_USER_PDU_LEN)
|
|
#define PDU_RX_USER_PDU_OCTETS_MAX (CONFIG_BT_RX_USER_PDU_LEN)
|
|
#else
|
|
#define PDU_RX_USER_PDU_OCTETS_MAX 0
|
|
#endif
|
|
#define NODE_RX_HEADER_SIZE (offsetof(struct node_rx_pdu, pdu))
|
|
#define NODE_RX_STRUCT_OVERHEAD (NODE_RX_HEADER_SIZE)
|
|
|
|
#define PDU_ADV_SIZE MAX(PDU_AC_LL_SIZE_MAX, \
|
|
(PDU_AC_LL_HEADER_SIZE + LL_EXT_OCTETS_RX_MAX))
|
|
|
|
#define PDU_DATA_SIZE (PDU_DC_LL_HEADER_SIZE + LL_LENGTH_OCTETS_RX_MAX)
|
|
|
|
#define PDU_RX_NODE_POOL_ELEMENT_SIZE \
|
|
MROUND(NODE_RX_STRUCT_OVERHEAD + \
|
|
MAX(MAX(PDU_ADV_SIZE, PDU_DATA_SIZE), PDU_RX_USER_PDU_OCTETS_MAX))
|
|
|
|
/*
|
|
* just a big number
|
|
*/
|
|
#define PDU_RX_POOL_SIZE 16384
|
|
|
|
static struct {
|
|
void *free;
|
|
uint8_t pool[PDU_RX_POOL_SIZE];
|
|
} mem_pdu_rx;
|
|
|
|
/*
|
|
* just a big number
|
|
*/
|
|
#define LINK_RX_POOL_SIZE 16384
|
|
static struct {
|
|
uint8_t quota_pdu; /* Number of un-utilized buffers */
|
|
|
|
void *free;
|
|
uint8_t pool[LINK_RX_POOL_SIZE];
|
|
} mem_link_rx;
|
|
|
|
static MEMQ_DECLARE(ull_rx);
|
|
static MEMQ_DECLARE(ll_rx);
|
|
|
|
#if defined(CONFIG_BT_CONN)
|
|
static MFIFO_DEFINE(ll_pdu_rx_free, sizeof(void *), LL_PDU_RX_CNT);
|
|
#endif /* CONFIG_BT_CONN */
|
|
|
|
#ifdef ZTEST_UNITTEST
|
|
extern sys_slist_t ut_rx_q;
|
|
#else
|
|
sys_slist_t ut_rx_q;
|
|
#endif
|
|
|
|
static inline int init_reset(void);
|
|
static inline void rx_alloc(uint8_t max);
|
|
static inline void ll_rx_link_inc_quota(int8_t delta);
|
|
|
|
void ll_reset(void)
|
|
{
|
|
MFIFO_INIT(ll_pdu_rx_free);
|
|
init_reset();
|
|
}
|
|
|
|
void ll_rx_mem_release(void **node_rx)
|
|
{
|
|
struct node_rx_hdr *rx;
|
|
|
|
rx = *node_rx;
|
|
while (rx) {
|
|
struct node_rx_hdr *rx_free;
|
|
|
|
rx_free = rx;
|
|
rx = rx->next;
|
|
|
|
switch (rx_free->type) {
|
|
case NODE_RX_TYPE_DC_PDU:
|
|
ll_rx_link_inc_quota(1);
|
|
mem_release(rx_free, &mem_pdu_rx.free);
|
|
break;
|
|
default:
|
|
__ASSERT(0, "Tried to release unknown rx node type");
|
|
break;
|
|
}
|
|
}
|
|
|
|
*node_rx = rx;
|
|
|
|
rx_alloc(UINT8_MAX);
|
|
}
|
|
|
|
static inline void ll_rx_link_inc_quota(int8_t delta)
|
|
{
|
|
mem_link_rx.quota_pdu += delta;
|
|
}
|
|
|
|
void *ll_rx_link_alloc(void)
|
|
{
|
|
return mem_acquire(&mem_link_rx.free);
|
|
}
|
|
|
|
void ll_rx_link_release(void *link)
|
|
{
|
|
mem_release(link, &mem_link_rx.free);
|
|
}
|
|
|
|
void *ll_rx_alloc(void)
|
|
{
|
|
return mem_acquire(&mem_pdu_rx.free);
|
|
}
|
|
|
|
void ll_rx_release(void *node_rx)
|
|
{
|
|
mem_release(node_rx, &mem_pdu_rx.free);
|
|
}
|
|
|
|
void ll_rx_put(memq_link_t *link, void *rx)
|
|
{
|
|
sys_slist_append(&ut_rx_q, (sys_snode_t *)rx);
|
|
}
|
|
|
|
void ll_rx_sched(void)
|
|
{
|
|
}
|
|
|
|
void *ll_pdu_rx_alloc_peek(uint8_t count)
|
|
{
|
|
if (count > MFIFO_AVAIL_COUNT_GET(ll_pdu_rx_free)) {
|
|
return NULL;
|
|
}
|
|
|
|
return MFIFO_DEQUEUE_PEEK(ll_pdu_rx_free);
|
|
}
|
|
|
|
void *ll_pdu_rx_alloc(void)
|
|
{
|
|
return MFIFO_DEQUEUE(ll_pdu_rx_free);
|
|
}
|
|
|
|
void ll_tx_ack_put(uint16_t handle, struct node_tx *node)
|
|
{
|
|
}
|
|
|
|
void ull_ticker_status_give(uint32_t status, void *param)
|
|
{
|
|
}
|
|
|
|
uint32_t ull_ticker_status_take(uint32_t ret, uint32_t volatile *ret_cb)
|
|
{
|
|
return *ret_cb;
|
|
}
|
|
|
|
void *ull_disable_mark(void *param)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
void *ull_disable_unmark(void *param)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
void *ull_disable_mark_get(void)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
int ull_ticker_stop_with_mark(uint8_t ticker_handle, void *param, void *lll_disable)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
void *ull_update_mark(void *param)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
void *ull_update_unmark(void *param)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
void *ull_update_mark_get(void)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
int ull_disable(void *lll)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
void ull_rx_put(memq_link_t *link, void *rx)
|
|
{
|
|
}
|
|
|
|
void ull_rx_sched(void)
|
|
{
|
|
}
|
|
|
|
/* Forward declaration */
|
|
struct node_rx_event_done;
|
|
void ull_drift_ticks_get(struct node_rx_event_done *done, uint32_t *ticks_drift_plus,
|
|
uint32_t *ticks_drift_minus)
|
|
{
|
|
}
|
|
|
|
static inline int init_reset(void)
|
|
{
|
|
memq_link_t *link;
|
|
|
|
/* Initialize done pool. */
|
|
mem_init(mem_done.pool, sizeof(struct node_rx_event_done), EVENT_DONE_MAX, &mem_done.free);
|
|
|
|
/* Initialize done link pool. */
|
|
mem_init(mem_link_done.pool, sizeof(memq_link_t), EVENT_DONE_MAX, &mem_link_done.free);
|
|
|
|
/* Initialize rx pool. */
|
|
mem_init(mem_pdu_rx.pool, (PDU_RX_NODE_POOL_ELEMENT_SIZE),
|
|
sizeof(mem_pdu_rx.pool) / (PDU_RX_NODE_POOL_ELEMENT_SIZE), &mem_pdu_rx.free);
|
|
|
|
/* Initialize rx link pool. */
|
|
mem_init(mem_link_rx.pool, sizeof(memq_link_t),
|
|
sizeof(mem_link_rx.pool) / sizeof(memq_link_t), &mem_link_rx.free);
|
|
|
|
/* Acquire a link to initialize ull rx memq */
|
|
link = mem_acquire(&mem_link_rx.free);
|
|
|
|
/* Initialize ull rx memq */
|
|
MEMQ_INIT(ull_rx, link);
|
|
|
|
/* Acquire a link to initialize ll rx memq */
|
|
link = mem_acquire(&mem_link_rx.free);
|
|
|
|
/* Initialize ll rx memq */
|
|
MEMQ_INIT(ll_rx, link);
|
|
|
|
/* Allocate rx free buffers */
|
|
mem_link_rx.quota_pdu = RX_CNT;
|
|
rx_alloc(UINT8_MAX);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static inline void rx_alloc(uint8_t max)
|
|
{
|
|
uint8_t idx;
|
|
|
|
#if defined(CONFIG_BT_CONN)
|
|
while (mem_link_rx.quota_pdu && MFIFO_ENQUEUE_IDX_GET(ll_pdu_rx_free, &idx)) {
|
|
memq_link_t *link;
|
|
struct node_rx_hdr *rx;
|
|
|
|
link = mem_acquire(&mem_link_rx.free);
|
|
if (!link) {
|
|
break;
|
|
}
|
|
|
|
rx = mem_acquire(&mem_pdu_rx.free);
|
|
if (!rx) {
|
|
mem_release(link, &mem_link_rx.free);
|
|
break;
|
|
}
|
|
|
|
link->mem = NULL;
|
|
rx->link = link;
|
|
|
|
MFIFO_BY_IDX_ENQUEUE(ll_pdu_rx_free, idx, rx);
|
|
|
|
ll_rx_link_inc_quota(-1);
|
|
}
|
|
#endif /* CONFIG_BT_CONN */
|
|
|
|
if (max > mem_link_rx.quota_pdu) {
|
|
max = mem_link_rx.quota_pdu;
|
|
}
|
|
|
|
while ((max--) && MFIFO_ENQUEUE_IDX_GET(pdu_rx_free, &idx)) {
|
|
memq_link_t *link;
|
|
struct node_rx_hdr *rx;
|
|
|
|
link = mem_acquire(&mem_link_rx.free);
|
|
if (!link) {
|
|
break;
|
|
}
|
|
|
|
rx = mem_acquire(&mem_pdu_rx.free);
|
|
if (!rx) {
|
|
mem_release(link, &mem_link_rx.free);
|
|
break;
|
|
}
|
|
|
|
rx->link = link;
|
|
|
|
MFIFO_BY_IDX_ENQUEUE(pdu_rx_free, idx, rx);
|
|
|
|
ll_rx_link_inc_quota(-1);
|
|
}
|
|
}
|