bluez5: deal with missing TX timestamps

There are known controller firmware bugs that cause packet completion
reports, mainly for ISO packets, to be missing.

To avoid getting stuck e.g. in ISO queue flushing, we should consider a
packet completed if sufficient time has passed even if controller (and
kernel) don't report it completed. Take 1 s as conservative timeout, the
expected values are some ms.

These firmware bugs also cause kernel to stop sending packets if too
many are left uncompleted, but we cannot detect that.
This commit is contained in:
Pauli Virtanen 2026-01-11 14:25:23 +02:00
parent 0869be11f8
commit d0309b4e1e
3 changed files with 111 additions and 36 deletions

View file

@ -258,6 +258,7 @@ static void group_on_timeout(struct spa_source *source)
bool resync = false;
bool fail = false;
uint64_t exp;
uint64_t now_realtime;
int res;
if ((res = spa_system_timerfd_read(group->data_system, group->timerfd, &exp)) < 0) {
@ -269,6 +270,8 @@ static void group_on_timeout(struct spa_source *source)
if (!exp)
return;
now_realtime = get_time_ns(group->data_system, CLOCK_REALTIME);
spa_list_for_each(stream, &group->streams, link) {
if (!stream->ready)
goto done;
@ -283,7 +286,7 @@ static void group_on_timeout(struct spa_source *source)
continue;
}
spa_bt_latency_recv_errqueue(&stream->tx_latency, stream->fd, group->log);
spa_bt_latency_recv_errqueue(&stream->tx_latency, stream->fd, now_realtime, group->log);
if (stream->this.need_resync) {
resync = true;
@ -649,6 +652,7 @@ int spa_bt_iso_io_recv_errqueue(struct spa_bt_iso_io *this)
{
struct stream *stream = SPA_CONTAINER_OF(this, struct stream, this);
struct group *group = stream->group;
uint64_t now_realtime;
if (!stream->sink) {
struct stream *s;
@ -661,7 +665,8 @@ int spa_bt_iso_io_recv_errqueue(struct spa_bt_iso_io *this)
}
}
return spa_bt_latency_recv_errqueue(&stream->tx_latency, stream->fd, group->log);
now_realtime = get_time_ns(group->data_system, CLOCK_REALTIME);
return spa_bt_latency_recv_errqueue(&stream->tx_latency, stream->fd, now_realtime, group->log);
}
/**