nimble/transport: Add generic IPC transport with flow control

This adds generic IPC transport that should be used as a base for any
transport with LL on separate core. It's similar to HCI H4, but has a
bit different header to simplify processing and supports internal flow
control to make sure LL does not send data that other core does not have
free buffers for.

IPC transport requires memory shared between cores to keep track of
number of available buffers on application core. Application core will
initialize counters to total number of available buffers. Then on each
alloc LL will atomically test and decrease relevan counter and will
allocate buffer only if that counter was non-zero. The counter will be
increased by application core if relevant buffer was freed.
This commit is contained in:
Andrzej Kaczmarek
2022-10-01 20:20:38 +02:00
parent e2f3e92d03
commit e178ff0d9f
10 changed files with 527 additions and 73 deletions
+12 -8
View File
@@ -43,6 +43,9 @@
#include "controller/ble_ll_utils.h"
#include "ble_ll_conn_priv.h"
#include "ble_ll_ctrl_priv.h"
#if MYNEWT_PKG_apache_mynewt_nimble__nimble_transport_common_hci_ipc
#include <nimble/transport/hci_ipc.h>
#endif
#if (BLETEST_THROUGHPUT_TEST == 1)
extern void bletest_completed_pkt(uint16_t handle);
@@ -3548,9 +3551,9 @@ ble_ll_conn_rx_data_pdu(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr)
/* Free buffer */
conn_rx_data_pdu_end:
#if MYNEWT_VAL(BLE_TRANSPORT_INT_FLOW_CTL)
#if MYNEWT_PKG_apache_mynewt_nimble__nimble_transport_common_hci_ipc
if (hdr->rxinfo.flags & BLE_MBUF_HDR_F_CONN_CREDIT_INT) {
ble_transport_int_flow_ctl_put();
hci_ipc_put(HCI_IPC_TYPE_ACL);
}
#endif
@@ -3614,12 +3617,12 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr)
alloc_rxpdu = false;
}
#if MYNEWT_VAL(BLE_TRANSPORT_INT_FLOW_CTL)
/* Do not alloc PDU if there are no free buffers in transport. We'll nak
* this PDU in LL.
#if MYNEWT_PKG_apache_mynewt_nimble__nimble_transport_common_hci_ipc
/* If IPC transport is used, make sure there is buffer available on app side
* for this PDU. We'll just nak in LL if there are no free buffers.
*/
if (alloc_rxpdu && BLE_LL_LLID_IS_DATA(hdr_byte) && (rx_pyld_len > 0)) {
if (ble_transport_int_flow_ctl_get()) {
if (hci_ipc_get(HCI_IPC_TYPE_ACL)) {
rxhdr->rxinfo.flags |= BLE_MBUF_HDR_F_CONN_CREDIT_INT;
} else {
alloc_rxpdu = false;
@@ -3639,8 +3642,9 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr)
if (ble_ll_conn_cth_flow_alloc_credit(connsm)) {
rxhdr->rxinfo.flags |= BLE_MBUF_HDR_F_CONN_CREDIT;
} else {
#if MYNEWT_VAL(BLE_TRANSPORT_INT_FLOW_CTL)
ble_transport_int_flow_ctl_put();
#if MYNEWT_PKG_apache_mynewt_nimble__nimble_transport_common_hci_ipc
/* Need to return app buffer to pool since we won't use it */
hci_ipc_put(HCI_IPC_TYPE_ACL);
#endif
alloc_rxpdu = false;
}
@@ -0,0 +1,98 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef _HCI_IPC_H_
#define _HCI_IPC_H_
#include <stdint.h>
#define HCI_IPC_TYPE_CMD 0x01
#define HCI_IPC_TYPE_ACL 0x02
#define HCI_IPC_TYPE_EVT 0x04
#define HCI_IPC_TYPE_EVT_DISCARDABLE 0x05
#define HCI_IPC_TYPE_EVT_IN_CMD 0x06
struct __attribute__((packed)) hci_ipc_hdr {
uint8_t type;
uint16_t length;
};
struct hci_ipc_sm {
struct hci_ipc_hdr hdr;
uint8_t hdr_len;
uint16_t rem_len;
uint16_t buf_len;
union {
uint8_t *buf;
struct os_mbuf *om;
};
};
struct hci_ipc_shm {
uint16_t n2a_num_acl;
uint16_t n2a_num_evt;
uint16_t n2a_num_evt_disc;
};
void hci_ipc_init(volatile struct hci_ipc_shm *shm, struct hci_ipc_sm *sm);
int hci_ipc_rx(struct hci_ipc_sm *sm, const uint8_t *buf, uint16_t len);
extern void hci_ipc_atomic_put(volatile uint16_t *num);
extern uint16_t hci_ipc_atomic_get(volatile uint16_t *num);
/* Just to optimize static inlines below, do not use directly! */
extern volatile struct hci_ipc_shm *g_ipc_shm;
static inline int
hci_ipc_get(uint8_t type)
{
volatile struct hci_ipc_shm *shm = g_ipc_shm;
switch (type) {
case HCI_IPC_TYPE_ACL:
return hci_ipc_atomic_get(&shm->n2a_num_acl);
case HCI_IPC_TYPE_EVT:
return hci_ipc_atomic_get(&shm->n2a_num_evt);
case HCI_IPC_TYPE_EVT_DISCARDABLE:
return hci_ipc_atomic_get(&shm->n2a_num_evt_disc);
}
return 0;
}
static inline void
hci_ipc_put(uint8_t type)
{
volatile struct hci_ipc_shm *shm = g_ipc_shm;
switch (type) {
case HCI_IPC_TYPE_ACL:
hci_ipc_atomic_put(&shm->n2a_num_acl);
break;
case HCI_IPC_TYPE_EVT:
hci_ipc_atomic_put(&shm->n2a_num_evt);
break;
case HCI_IPC_TYPE_EVT_DISCARDABLE:
hci_ipc_atomic_put(&shm->n2a_num_evt_disc);
break;
}
}
#endif /* _HCI_IPC_H_ */
@@ -1,3 +1,4 @@
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
@@ -16,5 +17,10 @@
# under the License.
#
syscfg.defs:
BLE_TRANSPORT_INT_FLOW_CTL: 1
pkg.name: nimble/transport/common/hci_ipc
pkg.description: Custom HCI IPC protocol
pkg.author: "Apache Mynewt <[email protected]>"
pkg.homepage: "https://mynewt.apache.org/"
pkg.deps:
- nimble
@@ -0,0 +1,219 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include <assert.h>
#include <stdint.h>
#include <string.h>
#include <syscfg/syscfg.h>
#include <os/os.h>
#include <os/os_mbuf.h>
#include <nimble/transport.h>
#include <nimble/transport/hci_ipc.h>
volatile struct hci_ipc_shm *g_ipc_shm;
static void
hci_ipc_alloc(struct hci_ipc_sm *sm)
{
assert(sm->hdr.type);
assert(sm->buf == NULL);
switch (sm->hdr.type) {
#if MYNEWT_VAL(BLE_CONTROLLER)
case HCI_IPC_TYPE_CMD:
sm->buf = ble_transport_alloc_cmd();
break;
#endif
case HCI_IPC_TYPE_ACL:
#if MYNEWT_VAL(BLE_CONTROLLER)
sm->om = ble_transport_alloc_acl_from_hs();
#else
sm->om = ble_transport_alloc_acl_from_ll();
#endif
break;
#if !MYNEWT_VAL(BLE_CONTROLLER)
case HCI_IPC_TYPE_EVT:
sm->buf = ble_transport_alloc_evt(0);
break;
case HCI_IPC_TYPE_EVT_DISCARDABLE:
sm->buf = ble_transport_alloc_evt(1);
break;
case HCI_IPC_TYPE_EVT_IN_CMD:
sm->buf = ble_transport_alloc_cmd();
break;
#endif
default:
assert(0);
break;
}
assert(sm->buf);
sm->rem_len = sm->hdr.length;
sm->buf_len = 0;
}
static bool
hci_ipc_has_hdr(struct hci_ipc_sm *sm)
{
return sm->hdr_len == sizeof(sm->hdr);
}
static void
hci_ipc_frame(struct hci_ipc_sm *sm)
{
assert(sm->hdr.type);
assert(sm->buf);
assert(sm->rem_len == 0);
switch (sm->hdr.type) {
#if MYNEWT_VAL(BLE_CONTROLLER)
case HCI_IPC_TYPE_CMD:
ble_transport_to_ll_cmd(sm->buf);
break;
#endif
case HCI_IPC_TYPE_ACL:
#if MYNEWT_VAL(BLE_CONTROLLER)
ble_transport_to_ll_acl(sm->om);
#else
ble_transport_to_hs_acl(sm->om);
#endif
break;
#if !MYNEWT_VAL(BLE_CONTROLLER)
case HCI_IPC_TYPE_EVT:
case HCI_IPC_TYPE_EVT_DISCARDABLE:
case HCI_IPC_TYPE_EVT_IN_CMD:
ble_transport_to_hs_evt(sm->buf);
break;
#endif
default:
assert(0);
break;
}
sm->hdr.type = 0;
sm->hdr.length = 0;
sm->hdr_len = 0;
sm->buf_len = 0;
sm->rem_len = 0;
sm->buf = NULL;
}
static uint16_t
hci_ipc_copy_to_hdr(struct hci_ipc_sm *sm, const uint8_t *buf, uint16_t len)
{
uint16_t rem_hdr_len;
uint8_t *p;
if (hci_ipc_has_hdr(sm)) {
return 0;
}
rem_hdr_len = sizeof(sm->hdr) - sm->hdr_len;
len = min(len, rem_hdr_len);
p = (void *)&sm->hdr;
memcpy(p + sm->hdr_len, buf, len);
sm->hdr_len += len;
if (hci_ipc_has_hdr(sm)) {
hci_ipc_alloc(sm);
}
return len;
}
static uint16_t
hci_ipc_copy_to_buf(struct hci_ipc_sm *sm, const uint8_t *buf, uint16_t len)
{
int rc;
assert(sm->hdr.type);
assert(sm->buf);
len = min(len, sm->rem_len);
switch (sm->hdr.type) {
#if MYNEWT_VAL(BLE_CONTROLLER)
case HCI_IPC_TYPE_CMD:
#else
case HCI_IPC_TYPE_EVT:
case HCI_IPC_TYPE_EVT_DISCARDABLE:
case HCI_IPC_TYPE_EVT_IN_CMD:
#endif
memcpy(sm->buf + sm->buf_len, buf, len);
break;
case HCI_IPC_TYPE_ACL:
rc = os_mbuf_append(sm->om, buf, len);
assert(rc == 0);
break;
default:
assert(0);
break;
}
sm->rem_len -= len;
sm->buf_len += len;
if (sm->rem_len == 0) {
hci_ipc_frame(sm);
}
return len;
}
int
hci_ipc_rx(struct hci_ipc_sm *sm, const uint8_t *buf, uint16_t len)
{
uint16_t rem_len = len;
uint16_t copy_len;
while (rem_len) {
if (hci_ipc_has_hdr(sm)) {
copy_len = hci_ipc_copy_to_buf(sm, buf, rem_len);
} else {
copy_len = hci_ipc_copy_to_hdr(sm, buf, rem_len);
}
rem_len -= copy_len;
buf += copy_len;
}
return len;
}
void
hci_ipc_init(volatile struct hci_ipc_shm *shm, struct hci_ipc_sm *sm)
{
assert(g_ipc_shm == NULL);
g_ipc_shm = shm;
memset(sm, 0, sizeof(*sm));
#if MYNEWT_VAL(BLE_CONTROLLER)
while (shm->n2a_num_evt_disc == 0) {
/* Wait until app side initializes credits */
}
#else
shm->n2a_num_acl = MYNEWT_VAL(BLE_TRANSPORT_ACL_FROM_LL_COUNT);
shm->n2a_num_evt = MYNEWT_VAL(BLE_TRANSPORT_EVT_COUNT);
shm->n2a_num_evt_disc = MYNEWT_VAL(BLE_TRANSPORT_EVT_DISCARDABLE_COUNT);
#endif
}
@@ -26,6 +26,9 @@ extern "C" {
#include <nimble/transport_impl.h>
#include <nimble/transport/monitor.h>
#if MYNEWT_PKG_apache_mynewt_nimble__nimble_transport_common_hci_ipc
#include <nimble/transport/transport_ipc.h>
#endif
struct os_mbuf;
@@ -0,0 +1,46 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef H_NIMBLE_TRANSPORT_IPC_
#define H_NIMBLE_TRANSPORT_IPC_
#ifdef __cplusplus
extern "C" {
#endif
/* NOTE: These APIs shall only be used by IPC transports */
#define BLE_TRANSPORT_IPC \
MYNEWT_PKG_apache_mynewt_nimble__nimble_transport_common_hci_ipc
#define BLE_TRANSPORT_IPC_ON_HS \
(BLE_TRANSPORT_IPC && !MYNEWT_VAL(BLE_CONTROLLER))
#define BLE_TRANSPORT_IPC_ON_LL \
(BLE_TRANSPORT_IPC && MYNEWT_VAL(BLE_CONTROLLER))
/* Free cmd/evt buffer sent over IPC */
void ble_transport_ipc_free(void *buf);
/* Get IPC type for cmd/evt buffer */
uint8_t ble_transport_ipc_buf_evt_type_get(void *buf);
#ifdef __cplusplus
}
#endif
#endif /* H_NIMBLE_TRANSPORT_IPC_ */
@@ -34,12 +34,6 @@ extern int ble_transport_to_ll_acl_impl(struct os_mbuf *om);
extern int ble_transport_to_hs_evt_impl(void *buf);
extern int ble_transport_to_hs_acl_impl(struct os_mbuf *om);
#if MYNEWT_VAL(BLE_TRANSPORT_INT_FLOW_CTL)
/* To be implemented if transport supports internal flow control between cores */
extern int ble_transport_int_flow_ctl_get(void);
extern void ble_transport_int_flow_ctl_put(void);
#endif
#ifdef __cplusplus
}
#endif
+1 -1
View File
@@ -28,7 +28,7 @@ pkg.keywords:
pkg.deps:
- nimble
- nimble/transport/common/hci_h4
- nimble/transport/common/hci_ipc
- "@apache-mynewt-core/kernel/os"
- "@apache-mynewt-core/hw/drivers/ipc_nrf5340"
+65 -51
View File
@@ -23,7 +23,7 @@
#include <nimble/ble.h>
#include <ipc_nrf5340/ipc_nrf5340.h>
#include <nimble/transport.h>
#include <nimble/transport/hci_h4.h>
#include <nimble/transport/hci_ipc.h>
#if MYNEWT_VAL(BLE_CONTROLLER)
#define IPC_TX_CHANNEL 0
@@ -33,16 +33,19 @@
#define IPC_RX_CHANNEL 0
#endif
static struct hci_h4_sm hci_nrf5340_h4sm;
static struct hci_ipc_sm g_hci_ipc_sm;
static int
nrf5340_ble_hci_acl_tx(struct os_mbuf *om)
{
uint8_t ind = HCI_H4_ACL;
struct hci_ipc_hdr hdr;
struct os_mbuf *x;
int rc;
rc = ipc_nrf5340_write(IPC_TX_CHANNEL, &ind, 1, false);
hdr.type = HCI_IPC_TYPE_ACL;
hdr.length = 4 + get_le16(&om->om_data[2]);
rc = ipc_nrf5340_write(IPC_TX_CHANNEL, &hdr, sizeof(hdr), false);
if (rc == 0) {
x = om;
while (x) {
@@ -59,37 +62,6 @@ nrf5340_ble_hci_acl_tx(struct os_mbuf *om)
return (rc < 0) ? BLE_ERR_MEM_CAPACITY : 0;
}
static int
nrf5340_ble_hci_frame_cb(uint8_t pkt_type, void *data)
{
int rc;
switch (pkt_type) {
#if MYNEWT_VAL(BLE_CONTROLLER)
case HCI_H4_CMD:
rc = ble_transport_to_ll_cmd(data);
break;
#endif
case HCI_H4_ACL:
#if MYNEWT_VAL(BLE_CONTROLLER)
rc = ble_transport_to_ll_acl(data);
#else
rc = ble_transport_to_hs_acl(data);
#endif
break;
#if !MYNEWT_VAL(BLE_CONTROLLER)
case HCI_H4_EVT:
rc = ble_transport_to_hs_evt(data);
break;
#endif
default:
assert(0);
break;
}
return rc;
}
static void
nrf5340_ble_hci_trans_rx(int channel, void *user_data)
{
@@ -98,7 +70,7 @@ nrf5340_ble_hci_trans_rx(int channel, void *user_data)
len = ipc_nrf5340_available_buf(channel, (void **)&buf);
while (len > 0) {
len = hci_h4_sm_rx(&hci_nrf5340_h4sm, buf, len);
len = hci_ipc_rx(&g_hci_ipc_sm, buf, len);
ipc_nrf5340_consume(channel, len);
len = ipc_nrf5340_available_buf(channel, (void **)&buf);
}
@@ -116,17 +88,19 @@ nrf5340_ble_hci_init(void)
int
ble_transport_to_hs_evt_impl(void *buf)
{
uint8_t ind = HCI_H4_EVT;
uint8_t* hci_ev = buf;
int len = 2 + hci_ev[1];
struct hci_ipc_hdr hdr;
uint8_t *hci_ev = buf;
int rc;
rc = ipc_nrf5340_write(IPC_TX_CHANNEL, &ind, 1, false);
hdr.type = ble_transport_ipc_buf_evt_type_get(buf);
hdr.length = 2 + hci_ev[1];
rc = ipc_nrf5340_write(IPC_TX_CHANNEL, &hdr, sizeof(hdr), false);
if (rc == 0) {
rc = ipc_nrf5340_write(IPC_TX_CHANNEL, hci_ev, len, true);
rc = ipc_nrf5340_write(IPC_TX_CHANNEL, hci_ev, hdr.length, true);
}
ble_transport_free(buf);
ble_transport_ipc_free(buf);
return (rc < 0) ? BLE_ERR_MEM_CAPACITY : 0;
}
@@ -140,8 +114,9 @@ ble_transport_to_hs_acl_impl(struct os_mbuf *om)
void
ble_transport_hs_init(void)
{
hci_h4_sm_init(&hci_nrf5340_h4sm, &hci_h4_allocs_from_hs,
nrf5340_ble_hci_frame_cb);
volatile struct hci_ipc_shm *shm = ipc_nrf5340_hci_shm_get();
hci_ipc_init(shm, &g_hci_ipc_sm);
nrf5340_ble_hci_init();
}
#endif /* BLE_CONTROLLER */
@@ -150,17 +125,19 @@ ble_transport_hs_init(void)
int
ble_transport_to_ll_cmd_impl(void *buf)
{
uint8_t ind = HCI_H4_CMD;
struct hci_ipc_hdr hdr;
uint8_t *cmd = buf;
int len = 3 + cmd[2];
int rc;
rc = ipc_nrf5340_write(IPC_TX_CHANNEL, &ind, 1, false);
hdr.type = HCI_IPC_TYPE_CMD;
hdr.length = 3 + cmd[2];
rc = ipc_nrf5340_write(IPC_TX_CHANNEL, &hdr, sizeof(hdr), false);
if (rc == 0) {
rc = ipc_nrf5340_write(IPC_TX_CHANNEL, cmd, len, true);
rc = ipc_nrf5340_write(IPC_TX_CHANNEL, cmd, hdr.length, true);
}
ble_transport_free(buf);
ble_transport_ipc_free(buf);
return (rc < 0) ? BLE_ERR_MEM_CAPACITY : 0;
}
@@ -174,8 +151,45 @@ ble_transport_to_ll_acl_impl(struct os_mbuf *om)
void
ble_transport_ll_init(void)
{
hci_h4_sm_init(&hci_nrf5340_h4sm, &hci_h4_allocs_from_ll,
nrf5340_ble_hci_frame_cb);
volatile struct hci_ipc_shm *shm = ipc_nrf5340_hci_shm_get();
hci_ipc_init(shm, &g_hci_ipc_sm);
nrf5340_ble_hci_init();
}
#endif /* !BLE_CONTROLLER */
uint16_t
hci_ipc_atomic_get(volatile uint16_t *num)
{
int ret;
__asm__ volatile (".syntax unified \n"
"1: ldrexh r1, [%[addr]] \n"
" mov %[ret], r1 \n"
" cmp r1, #0 \n"
" itte ne \n"
" subne r2, r1, #1 \n"
" strexhne r1, r2, [%[addr]] \n"
" clrexeq \n"
" cmp r1, #0 \n"
" bne 1b \n"
: [ret] "=&r" (ret)
: [addr] "r" (num)
: "r1", "r2", "memory");
return ret;
}
void
hci_ipc_atomic_put(volatile uint16_t *num)
{
__asm__ volatile (".syntax unified \n"
"1: ldrexh r1, [%[addr]] \n"
" add r1, r1, #1 \n"
" strexh r2, r1, [%[addr]] \n"
" cmp r2, #0 \n"
" bne 1b \n"
:
: [addr] "r" (num)
: "r1", "r2", "memory");
}
+75 -5
View File
@@ -25,6 +25,9 @@
#include <nimble/ble.h>
#include <nimble/hci_common.h>
#include <nimble/transport.h>
#if BLE_TRANSPORT_IPC
#include <nimble/transport/hci_ipc.h>
#endif
#define OMP_FLAG_FROM_HS (0x01)
#define OMP_FLAG_FROM_LL (0x02)
@@ -79,17 +82,48 @@ ble_transport_alloc_cmd(void)
return os_memblock_get(&pool_cmd);
}
static void *
try_alloc_evt(struct os_mempool *mp)
{
#if BLE_TRANSPORT_IPC_ON_LL
uint8_t type;
#endif
void *buf;
#if BLE_TRANSPORT_IPC_ON_LL
if (mp == &pool_evt) {
type = HCI_IPC_TYPE_EVT;
} else {
type = HCI_IPC_TYPE_EVT_DISCARDABLE;
}
if (!hci_ipc_get(type)) {
return NULL;
}
#endif
buf = os_memblock_get(mp);
#if BLE_TRANSPORT_IPC_ON_LL
if (!buf) {
hci_ipc_put(type);
}
#endif
return buf;
}
void *
ble_transport_alloc_evt(int discardable)
{
void *buf;
if (discardable) {
buf = os_memblock_get(&pool_evt_lo);
buf = try_alloc_evt(&pool_evt_lo);
} else {
buf = os_memblock_get(&pool_evt);
buf = try_alloc_evt(&pool_evt);
if (!buf) {
buf = os_memblock_get(&pool_evt_lo);
buf = try_alloc_evt(&pool_evt_lo);
}
}
@@ -135,6 +169,26 @@ ble_transport_alloc_acl_from_ll(void)
void
ble_transport_free(void *buf)
{
if (os_memblock_from(&pool_cmd, buf)) {
os_memblock_put(&pool_cmd, buf);
} else if (os_memblock_from(&pool_evt, buf)) {
os_memblock_put(&pool_evt, buf);
#if BLE_TRANSPORT_IPC
hci_ipc_put(HCI_IPC_TYPE_EVT);
#endif
} else if (os_memblock_from(&pool_evt_lo, buf)) {
os_memblock_put(&pool_evt_lo, buf);
#if BLE_TRANSPORT_IPC
hci_ipc_put(HCI_IPC_TYPE_EVT_DISCARDABLE);
#endif
} else {
assert(0);
}
}
void
ble_transport_ipc_free(void *buf)
{
if (os_memblock_from(&pool_cmd, buf)) {
os_memblock_put(&pool_cmd, buf);
@@ -172,9 +226,9 @@ ble_transport_acl_put(struct os_mempool_ext *mpe, void *data, void *arg)
err = os_memblock_put_from_cb(&mpe->mpe_mp, data);
}
#if MYNEWT_VAL(BLE_TRANSPORT_INT_FLOW_CTL)
#if BLE_TRANSPORT_IPC_ON_HS
if (from_ll && !err) {
ble_transport_int_flow_ctl_put();
hci_ipc_put(HCI_IPC_TYPE_ACL);
}
#endif
@@ -218,3 +272,19 @@ ble_transport_register_put_acl_from_ll_cb(os_mempool_put_fn (*cb))
return 0;
}
#if BLE_TRANSPORT_IPC
uint8_t
ble_transport_ipc_buf_evt_type_get(void *buf)
{
if (os_memblock_from(&pool_cmd, buf)) {
return HCI_IPC_TYPE_EVT_IN_CMD;
} else if (os_memblock_from(&pool_evt, buf)) {
return HCI_IPC_TYPE_EVT;
} else if (os_memblock_from(&pool_evt_lo, buf)) {
return HCI_IPC_TYPE_EVT_DISCARDABLE;
} else {
assert(0);
}
}
#endif