Bluetooth: Controller: Option to ignore Tx ISO Data Packet Seq Num

Kconfig option to turn off ISO Data Packet Sequence Number
use to place the ISO Data in the correct radio event,
instead simply buffer it to next radio event.

Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
This commit is contained in:
Vinayak Kariappa Chettimada 2023-06-08 10:17:33 +05:30 committed by Carles Cufí
commit 61d00467b4
5 changed files with 111 additions and 16 deletions

View file

@ -499,7 +499,8 @@ config BT_CTLR_SCAN_ENABLE_STRICT
config BT_CTLR_ISOAL_SN_STRICT
bool "Enforce Strict Tx ISO Data Sequence Number use"
depends on BT_CTLR_ADV_ISO || BT_CTLR_CONN_ISO
depends on !BT_CTLR_ISOAL_PSN_IGNORE && (BT_CTLR_ADV_ISO || \
BT_CTLR_CONN_ISO)
default y
help
Enforce strict sequencing of released payloads based on the TX SDU's
@ -517,6 +518,12 @@ config BT_CTLR_ISOAL_SN_STRICT
dropped. This will result in better delivery of data to the receiver
but at the cost of creating skews in the received stream of SDUs.
config BT_CTLR_ISOAL_PSN_IGNORE
bool "Ignore Tx ISO Data Packet Sequence Number use"
depends on BT_CTLR_ADV_ISO || BT_CTLR_CONN_ISO
help
Ignore the use of Tx ISO Data Packet Sequence Number.
config BT_CTLR_ZLI
bool "Use Zero Latency IRQs"
depends on ZERO_LATENCY_IRQS

View file

@ -5657,8 +5657,6 @@ int hci_iso_handle(struct net_buf *buf, struct net_buf **evt)
struct bt_hci_iso_data_hdr *iso_data_hdr;
struct isoal_sdu_tx sdu_frag_tx;
struct bt_hci_iso_hdr *iso_hdr;
struct ll_iso_datapath *dp_in;
struct ll_iso_stream_hdr *hdr;
uint32_t *time_stamp;
uint16_t handle;
uint8_t pb_flag;
@ -5668,8 +5666,6 @@ int hci_iso_handle(struct net_buf *buf, struct net_buf **evt)
iso_data_hdr = NULL;
*evt = NULL;
hdr = NULL;
dp_in = NULL;
if (buf->len < sizeof(*iso_hdr)) {
LOG_ERR("No HCI ISO header");
@ -5747,16 +5743,49 @@ int hci_iso_handle(struct net_buf *buf, struct net_buf **evt)
* data path
*/
} else if (IS_CIS_HANDLE(handle)) {
struct ll_conn_iso_stream *cis =
ll_iso_stream_connected_get(handle);
struct ll_conn_iso_stream *cis;
struct ll_conn_iso_group *cig;
struct ll_iso_stream_hdr *hdr;
struct ll_iso_datapath *dp_in;
cis = ll_iso_stream_connected_get(handle);
if (!cis) {
return -EINVAL;
}
struct ll_conn_iso_group *cig = cis->group;
uint8_t event_offset;
cig = cis->group;
hdr = &(cis->hdr);
#if defined(CONFIG_BT_CTLR_ISOAL_PSN_IGNORE)
uint64_t event_count;
uint64_t pkt_seq_num;
/* Catch up local pkt_seq_num with internal pkt_seq_num */
event_count = cis->lll.event_count;
pkt_seq_num = event_count + 1U;
if (!(pb_flag & 0x01) &&
(((pkt_seq_num - cis->pkt_seq_num) &
BIT64_MASK(39)) <= BIT64_MASK(38))) {
cis->pkt_seq_num = pkt_seq_num;
} else {
pkt_seq_num = cis->pkt_seq_num;
}
/* Pre-increment, for next ISO data packet seq num comparison */
if (pb_flag & 0x10) {
cis->pkt_seq_num++;
}
/* Target next event to avoid overlapping with current event */
pkt_seq_num++;
sdu_frag_tx.target_event = pkt_seq_num;
sdu_frag_tx.grp_ref_point =
isoal_get_wrapped_time_us(cig->cig_ref_point,
((pkt_seq_num - event_count) *
cig->iso_interval *
ISO_INT_UNIT_US));
#else /* !CONFIG_BT_CTLR_ISOAL_PSN_IGNORE */
uint8_t event_offset;
/* We must ensure sufficient time for ISO-AL to fragment SDU and
* deliver PDUs to the TX queue. By checking ull_ref_get, we
@ -5780,11 +5809,15 @@ int hci_iso_handle(struct net_buf *buf, struct net_buf **evt)
}
sdu_frag_tx.target_event = cis->lll.event_count + event_offset;
sdu_frag_tx.grp_ref_point = isoal_get_wrapped_time_us(cig->cig_ref_point,
(event_offset * cig->iso_interval *
ISO_INT_UNIT_US));
sdu_frag_tx.grp_ref_point =
isoal_get_wrapped_time_us(cig->cig_ref_point,
(event_offset *
cig->iso_interval *
ISO_INT_UNIT_US));
#endif /* !CONFIG_BT_CTLR_ISOAL_PSN_IGNORE */
/* Get controller's input data path for CIS */
hdr = &(cis->hdr);
dp_in = hdr->datapath_in;
if (!dp_in || dp_in->path_id != BT_HCI_DATAPATH_ID_HCI) {
LOG_ERR("Input data path not set for HCI");
@ -5817,8 +5850,6 @@ int hci_iso_handle(struct net_buf *buf, struct net_buf **evt)
struct ll_adv_iso_set *adv_iso;
struct lll_adv_iso *lll_iso;
uint16_t stream_handle;
uint8_t target_event;
uint8_t event_offset;
uint16_t slen;
/* FIXME: Code only expects header present */
@ -5844,6 +5875,53 @@ int hci_iso_handle(struct net_buf *buf, struct net_buf **evt)
return -EINVAL;
}
lll_iso = &adv_iso->lll;
#if defined(CONFIG_BT_CTLR_ISOAL_PSN_IGNORE)
uint64_t event_count;
uint64_t pkt_seq_num;
/* Catch up local pkt_seq_num with internal pkt_seq_num */
event_count = lll_iso->payload_count / lll_iso->bn;
pkt_seq_num = event_count;
if (!(pb_flag & 0x01) &&
(((pkt_seq_num - stream->pkt_seq_num) &
BIT64_MASK(39)) <= BIT64_MASK(38))) {
stream->pkt_seq_num = pkt_seq_num;
} else {
pkt_seq_num = stream->pkt_seq_num;
}
/* Pre-increment, for next ISO data packet seq num comparison */
if (pb_flag & 0x10) {
stream->pkt_seq_num++;
}
/* Target next event to avoid overlapping with current event */
/* FIXME: Implement ISO Tx ack generation early in done compared
* to currently only in prepare. I.e. to ensure upper
* layer has the number of completed packet before the
* next BIG event, so as to supply new ISO data packets.
* Without which upper layers need extra buffers to
* buffer next ISO data packet.
*
* Enable below increment once early Tx ack is
* implemented.
*
* pkt_seq_num++;
*/
sdu_frag_tx.target_event = pkt_seq_num;
sdu_frag_tx.grp_ref_point =
isoal_get_wrapped_time_us(adv_iso->big_ref_point,
(((pkt_seq_num + 1U) -
event_count) *
lll_iso->iso_interval *
ISO_INT_UNIT_US));
#else /* !CONFIG_BT_CTLR_ISOAL_PSN_IGNORE */
uint8_t target_event;
uint8_t event_offset;
/* Determine the target event and the first event offset after
* datapath setup.
* event_offset mitigates the possibility of first SDU being
@ -5861,7 +5939,6 @@ int hci_iso_handle(struct net_buf *buf, struct net_buf **evt)
* BIG event by incrementing the previous elapsed big_ref_point
* by one additional ISO interval.
*/
lll_iso = &adv_iso->lll;
target_event = lll_iso->payload_count / lll_iso->bn;
event_offset = ull_ref_get(&adv_iso->ull) ? 0U : 1U;
event_offset += lll_iso->latency_prepare;
@ -5872,6 +5949,7 @@ int hci_iso_handle(struct net_buf *buf, struct net_buf **evt)
((event_offset + 1U) *
lll_iso->iso_interval *
ISO_INT_UNIT_US));
#endif /* !CONFIG_BT_CTLR_ISOAL_PSN_IGNORE */
/* Start Fragmentation */
/* FIXME: need to ensure ISO-AL returns proper isoal_status.

View file

@ -883,6 +883,9 @@ uint8_t ull_central_iso_setup(uint16_t cis_handle,
#endif /* !CONFIG_BT_CTLR_JIT_SCHEDULING */
cis->central.instant = instant;
#if defined(CONFIG_BT_CTLR_ISOAL_PSN_IGNORE)
cis->pkt_seq_num = 0U;
#endif /* CONFIG_BT_CTLR_ISOAL_PSN_IGNORE */
cis->lll.event_count = LLL_CONN_ISO_EVENT_COUNT_MAX;
cis->lll.next_subevent = 0U;
cis->lll.sn = 0U;

View file

@ -48,6 +48,10 @@ struct ll_conn_iso_stream {
*/
uint8_t terminate_reason;
uint8_t cis_id;
#if defined(CONFIG_BT_CTLR_ISOAL_PSN_IGNORE)
uint64_t pkt_seq_num:39;
#endif /* CONFIG_BT_CTLR_ISOAL_PSN_IGNORE */
};
struct ll_conn_iso_group {

View file

@ -326,6 +326,9 @@ uint8_t ull_peripheral_iso_setup(struct pdu_data_llctrl_cis_ind *ind,
cis->sync_delay = sys_get_le24(ind->cis_sync_delay);
cis->offset = cis_offset;
memcpy(cis->lll.access_addr, ind->aa, sizeof(ind->aa));
#if defined(CONFIG_BT_CTLR_ISOAL_PSN_IGNORE)
cis->pkt_seq_num = 0U;
#endif /* CONFIG_BT_CTLR_ISOAL_PSN_IGNORE */
cis->lll.event_count = LLL_CONN_ISO_EVENT_COUNT_MAX;
cis->lll.next_subevent = 0U;
cis->lll.sn = 0U;