Bluetooth: controller: openisa: Fix sanitycheck failures

Fix sanitycheck failures when building
samples/bluetooth/peripheral_hr for rv32m1_vega_ri5cy
platform.

Updates from nRF platform related to 255 byte AD data
support have been directly copied into openisa port to
fix build failures.

Relates to commit c2fc629dd2 ("Bluetooth: controller:
255 byte AD payload support").

Fixes #29967.

Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
This commit is contained in:
Vinayak Kariappa Chettimada 2020-11-13 05:58:04 +05:30 committed by Carles Cufí
commit ef2ece82c0
3 changed files with 322 additions and 45 deletions

View file

@ -18,7 +18,9 @@
#include "hal/ticker.h"
#include "util/util.h"
#include "util/mem.h"
#include "util/memq.h"
#include "util/mfifo.h"
#include "ticker/ticker.h"
@ -75,6 +77,46 @@ static inline bool isr_rx_ci_tgta_check(struct lll_adv *lll,
static inline bool isr_rx_ci_adva_check(struct pdu_adv *adv,
struct pdu_adv *ci);
#if defined(CONFIG_BT_CTLR_ADV_EXT)
#define PAYLOAD_FRAG_COUNT ((CONFIG_BT_CTLR_ADV_DATA_LEN_MAX + \
PDU_AC_PAYLOAD_SIZE_MAX - 1) / \
PDU_AC_PAYLOAD_SIZE_MAX)
#define BT_CTLR_ADV_AUX_SET CONFIG_BT_CTLR_ADV_AUX_SET
#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
#define BT_CTLR_ADV_SYNC_SET CONFIG_BT_CTLR_ADV_SYNC_SET
#else /* !CONFIG_BT_CTLR_ADV_PERIODIC */
#define BT_CTLR_ADV_SYNC_SET 0
#endif /* !CONFIG_BT_CTLR_ADV_PERIODIC */
#else
#define PAYLOAD_FRAG_COUNT 1
#define BT_CTLR_ADV_AUX_SET 0
#define BT_CTLR_ADV_SYNC_SET 0
#endif
#define PDU_MEM_SIZE MROUND(PDU_AC_LL_HEADER_SIZE + \
PDU_AC_PAYLOAD_SIZE_MAX)
#define PDU_MEM_COUNT_MIN (BT_CTLR_ADV_SET + \
(BT_CTLR_ADV_SET * PAYLOAD_FRAG_COUNT) + \
(BT_CTLR_ADV_AUX_SET * PAYLOAD_FRAG_COUNT) + \
(BT_CTLR_ADV_SYNC_SET * PAYLOAD_FRAG_COUNT))
#define PDU_MEM_FIFO_COUNT ((BT_CTLR_ADV_SET * PAYLOAD_FRAG_COUNT * 2) + \
(CONFIG_BT_CTLR_ADV_DATA_BUF_MAX * \
PAYLOAD_FRAG_COUNT))
#define PDU_MEM_COUNT (PDU_MEM_COUNT_MIN + PDU_MEM_FIFO_COUNT)
#define PDU_POOL_SIZE (PDU_MEM_SIZE * PDU_MEM_COUNT)
/* Free AD data PDU buffer pool */
static struct {
void *free;
uint8_t pool[PDU_POOL_SIZE];
} mem_pdu;
/* FIFO to return stale AD data PDU buffers from LLL to thread context */
static MFIFO_DEFINE(pdu_free, sizeof(void *), PDU_MEM_FIFO_COUNT);
/* Semaphore to wakeup thread waiting for free AD data PDU buffers */
static struct k_sem sem_pdu_free;
int lll_adv_init(void)
{
int err;
@ -99,6 +141,166 @@ int lll_adv_reset(void)
return 0;
}
int lll_adv_data_init(struct lll_adv_pdu *pdu)
{
struct pdu_adv *p;
p = mem_acquire(&mem_pdu.free);
if (!p) {
return -ENOMEM;
}
pdu->pdu[0] = (void *)p;
return 0;
}
int lll_adv_data_reset(struct lll_adv_pdu *pdu)
{
/* NOTE: this function is used on HCI reset to mem-zero the structure
* members that otherwise was zero-ed by the architecture
* startup code that zero-ed the .bss section.
* pdu[0] element in the array is not initialized as subsequent
* call to lll_adv_data_init will allocate a PDU buffer and
* assign that.
*/
pdu->first = 0U;
pdu->last = 0U;
pdu->pdu[1] = NULL;
return 0;
}
int lll_adv_data_release(struct lll_adv_pdu *pdu)
{
uint8_t last;
void *p;
last = pdu->last;
p = pdu->pdu[last];
pdu->pdu[last] = NULL;
mem_release(p, &mem_pdu.free);
last++;
if (last == DOUBLE_BUFFER_SIZE) {
last = 0U;
}
p = pdu->pdu[last];
if (p) {
pdu->pdu[last] = NULL;
mem_release(p, &mem_pdu.free);
}
return 0;
}
struct pdu_adv *lll_adv_pdu_alloc(struct lll_adv_pdu *pdu, uint8_t *idx)
{
uint8_t first, last;
struct pdu_adv *p;
int err;
first = pdu->first;
last = pdu->last;
if (first == last) {
last++;
if (last == DOUBLE_BUFFER_SIZE) {
last = 0U;
}
} else {
uint8_t first_latest;
pdu->last = first;
/* FIXME: Ensure that data is synchronized so that an ISR
* vectored, after pdu->last has been updated, does
* access the latest value. __DSB() is used in ARM
* Cortex M4 architectures. Use appropriate
* instructions on other platforms.
*
* cpu_dsb();
*/
first_latest = pdu->first;
if (first_latest != first) {
last++;
if (last == DOUBLE_BUFFER_SIZE) {
last = 0U;
}
}
}
*idx = last;
p = (void *)pdu->pdu[last];
if (p) {
return p;
}
p = MFIFO_DEQUEUE_PEEK(pdu_free);
if (p) {
err = k_sem_take(&sem_pdu_free, K_NO_WAIT);
LL_ASSERT(!err);
MFIFO_DEQUEUE(pdu_free);
pdu->pdu[last] = (void *)p;
return p;
}
p = mem_acquire(&mem_pdu.free);
if (p) {
pdu->pdu[last] = (void *)p;
return p;
}
err = k_sem_take(&sem_pdu_free, K_FOREVER);
LL_ASSERT(!err);
p = MFIFO_DEQUEUE(pdu_free);
LL_ASSERT(p);
pdu->pdu[last] = (void *)p;
return p;
}
struct pdu_adv *lll_adv_pdu_latest_get(struct lll_adv_pdu *pdu,
uint8_t *is_modified)
{
uint8_t first;
first = pdu->first;
if (first != pdu->last) {
uint8_t free_idx;
uint8_t pdu_idx;
void *p;
if (!MFIFO_ENQUEUE_IDX_GET(pdu_free, &free_idx)) {
LL_ASSERT(false);
return NULL;
}
pdu_idx = first;
first += 1U;
if (first == DOUBLE_BUFFER_SIZE) {
first = 0U;
}
pdu->first = first;
*is_modified = 1U;
p = pdu->pdu[pdu_idx];
pdu->pdu[pdu_idx] = NULL;
MFIFO_BY_IDX_ENQUEUE(pdu_free, free_idx, p);
k_sem_give(&sem_pdu_free);
}
return (void *)pdu->pdu[first];
}
void lll_adv_prepare(void *param)
{
struct lll_prepare_param *p = param;

View file

@ -4,13 +4,61 @@
* SPDX-License-Identifier: Apache-2.0
*/
#if defined(CONFIG_BT_CTLR_ADV_SET)
#define BT_CTLR_ADV_SET CONFIG_BT_CTLR_ADV_SET
#else /* CONFIG_BT_CTLR_ADV_SET */
#define BT_CTLR_ADV_SET 1
#endif /* CONFIG_BT_CTLR_ADV_SET */
/* Structure used to double buffer pointers of AD Data PDU buffer.
* The first and last members are used to make modification to AD data to be
* context safe. Thread always appends or updates the buffer pointed to
* the array element indexed by the member last.
* LLL in the ISR context, checks, traverses to the valid pointer indexed
* by the member first, such that the buffer is the latest committed by
* the thread context.
*/
struct lll_adv_pdu {
uint8_t first;
uint8_t last;
/* TODO: use,
* struct pdu_adv *pdu[DOUBLE_BUFFER_SIZE];
*/
uint8_t pdu[DOUBLE_BUFFER_SIZE][PDU_AC_LL_SIZE_MAX];
uint8_t volatile first;
uint8_t last;
uint8_t *pdu[DOUBLE_BUFFER_SIZE];
};
struct lll_adv_aux {
struct lll_hdr hdr;
struct lll_adv *adv;
uint32_t ticks_offset;
struct lll_adv_pdu data;
#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
int8_t tx_pwr_lvl;
#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */
};
struct lll_adv_sync {
struct lll_hdr hdr;
struct lll_adv *adv;
uint8_t access_addr[4];
uint8_t crc_init[3];
uint16_t latency_prepare;
uint16_t latency_event;
uint16_t event_counter;
uint8_t data_chan_map[5];
uint8_t data_chan_count:6;
uint16_t data_chan_id;
uint32_t ticks_offset;
struct lll_adv_pdu data;
#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
int8_t tx_pwr_lvl;
#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */
};
struct lll_adv {
@ -28,7 +76,12 @@ struct lll_adv {
#if defined(CONFIG_BT_CTLR_ADV_EXT)
uint8_t phy_p:3;
#endif /* !CONFIG_BT_CTLR_ADV_EXT */
uint8_t phy_s:3;
#endif /* CONFIG_BT_CTLR_ADV_EXT */
#if defined(CONFIG_BT_CTLR_SCAN_REQ_NOTIFY)
uint8_t scan_req_notify:1;
#endif
#if defined(CONFIG_BT_HCI_MESH_EXT)
uint8_t is_mesh:1;
@ -40,32 +93,32 @@ struct lll_adv {
struct lll_adv_pdu adv_data;
struct lll_adv_pdu scan_rsp;
#if defined(CONFIG_BT_CTLR_ADV_EXT)
struct lll_adv_aux *aux;
#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
struct lll_adv_sync *sync;
#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
#endif /* CONFIG_BT_CTLR_ADV_EXT */
#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
int8_t tx_pwr_lvl;
#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */
#if defined(CONFIG_BT_CTLR_ADV_EXT)
struct node_rx_hdr *node_rx_adv_term;
#endif /* CONFIG_BT_CTLR_ADV_EXT */
};
int lll_adv_init(void);
int lll_adv_reset(void);
int lll_adv_data_init(struct lll_adv_pdu *pdu);
int lll_adv_data_reset(struct lll_adv_pdu *pdu);
int lll_adv_data_release(struct lll_adv_pdu *pdu);
struct pdu_adv *lll_adv_pdu_alloc(struct lll_adv_pdu *pdu, uint8_t *idx);
void lll_adv_prepare(void *param);
static inline struct pdu_adv *lll_adv_pdu_alloc(struct lll_adv_pdu *pdu,
uint8_t *idx)
{
uint8_t last;
if (pdu->first == pdu->last) {
last = pdu->last + 1;
if (last == DOUBLE_BUFFER_SIZE) {
last = 0U;
}
} else {
last = pdu->last;
}
*idx = last;
return (void *)pdu->pdu[last];
}
static inline void lll_adv_pdu_enqueue(struct lll_adv_pdu *pdu, uint8_t idx)
{
pdu->last = idx;
@ -102,4 +155,42 @@ static inline struct pdu_adv *lll_adv_scan_rsp_peek(struct lll_adv *lll)
return (void *)lll->scan_rsp.pdu[lll->scan_rsp.last];
}
#if defined(CONFIG_BT_CTLR_ADV_EXT)
static inline struct pdu_adv *lll_adv_aux_data_alloc(struct lll_adv_aux *lll,
uint8_t *idx)
{
return lll_adv_pdu_alloc(&lll->data, idx);
}
static inline void lll_adv_aux_data_enqueue(struct lll_adv_aux *lll,
uint8_t idx)
{
lll_adv_pdu_enqueue(&lll->data, idx);
}
static inline struct pdu_adv *lll_adv_aux_data_peek(struct lll_adv_aux *lll)
{
return (void *)lll->data.pdu[lll->data.last];
}
#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
static inline struct pdu_adv *lll_adv_sync_data_alloc(struct lll_adv_sync *lll,
uint8_t *idx)
{
return lll_adv_pdu_alloc(&lll->data, idx);
}
static inline void lll_adv_sync_data_enqueue(struct lll_adv_sync *lll,
uint8_t idx)
{
lll_adv_pdu_enqueue(&lll->data, idx);
}
static inline struct pdu_adv *lll_adv_sync_data_peek(struct lll_adv_sync *lll)
{
return (void *)lll->data.pdu[lll->data.last];
}
#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
#endif /* CONFIG_BT_CTLR_ADV_EXT */
extern uint16_t ull_adv_lll_handle_get(struct lll_adv *lll);

View file

@ -4,24 +4,8 @@
* SPDX-License-Identifier: Apache-2.0
*/
static inline struct pdu_adv *lll_adv_pdu_latest_get(struct lll_adv_pdu *pdu,
uint8_t *is_modified)
{
uint8_t first;
first = pdu->first;
if (first != pdu->last) {
first += 1U;
if (first == DOUBLE_BUFFER_SIZE) {
first = 0U;
}
pdu->first = first;
*is_modified = 1U;
}
return (void *)pdu->pdu[first];
}
struct pdu_adv *lll_adv_pdu_latest_get(struct lll_adv_pdu *pdu,
uint8_t *is_modified);
static inline struct pdu_adv *lll_adv_data_latest_get(struct lll_adv *lll,
uint8_t *is_modified)
{