net: qrtr: ns: push adsp service announcements to the modem (FP6 voice)
The DSP firmwares expect the downstream IPC-router flooding model: a
node never sends NEW_LOOKUP for a service hosted on a peer node and
relies on the application processor pushing every NEW_SERVER/DEL_SERVER
to every link. Mainline's name service only broadcasts local servers;
remote servers reach other remote nodes solely via persistent lookups
nobody in the firmware issues.
Observed on the FP6 (SM7635): at boot the modem queries the in-kernel
pd-mapper for 'avs/audio' and receives 'msm/adsp/audio_pd' instance 74,
but never contacts the ADSP's service-registry notifier (svc 66 inst 74,
node 5 port 2) because it was never told that service exists - zero
forwarded modem->adsp packets across a full modem boot with the
forwarding path instrumented. Without the avs/audio-up notification the
modem's Voice Services never creates a vocoder session (empty
placeholder encoder/decoder during live VoLTE calls AND CVD loopback,
journal/calls.md sessions 15/16).
A first version of this patch flooded every remote announcement to every
hello'd node, downstream-style; it wedged the phone within ~20 s of the
DSPs booting, recurring in waves (control packets are exempt from qrtr
flow control, so any echo between routers runs unbounded, and DSP
crash/recovery cycles re-trigger it). Push only the one edge voice
needs instead: ADSP-hosted servers, to the modem, both live (new/del)
and replayed when the modem says HELLO. Any echo is structurally
loop-free: a re-announcement arriving from the modem is pushed to
nobody (target == origin). Pairs with the data-path forwarding carry
0c63174949.
Assisted-by: Claude:claude-fable-5
Signed-off-by: Jorijn van der Graaf <jorijnvdgraaf@catcrafts.net>
This commit is contained in:
parent
ff614d787e
commit
fb5953a877
1 changed files with 82 additions and 0 deletions
|
|
@ -70,6 +70,7 @@ struct qrtr_node {
|
|||
unsigned int id;
|
||||
struct xarray servers;
|
||||
u32 server_count;
|
||||
bool hello;
|
||||
};
|
||||
|
||||
/* Max nodes, server, lookup limits are chosen based on the current platform
|
||||
|
|
@ -212,6 +213,60 @@ static void lookup_notify(struct sockaddr_qrtr *to, struct qrtr_server *srv,
|
|||
pr_err("failed to send lookup notification\n");
|
||||
}
|
||||
|
||||
/* FP6 voice bring-up: the DSP firmwares expect the downstream IPC-router
|
||||
* flooding model - they never send NEW_LOOKUP for services on their peers
|
||||
* and instead rely on the application processor pushing announcements to
|
||||
* every link. The modem's voice stack locates the ADSP's service-registry
|
||||
* notifier this way; without it Voice Services never sees avs/audio come
|
||||
* up and never creates a vocoder session.
|
||||
*
|
||||
* Flooding every announcement to every node wedges the phone within
|
||||
* seconds of the DSPs booting (control packets are exempt from qrtr flow
|
||||
* control, so any echo between routers runs unbounded). Push exactly the
|
||||
* one edge voice needs: ADSP-hosted servers, to the modem, only. Any echo
|
||||
* is structurally loop-free: a re-announcement of an ADSP server arriving
|
||||
* from the modem is pushed to nobody (target == origin).
|
||||
*/
|
||||
#define QRTR_NS_FWD_SRC_NODE 5 /* adsp */
|
||||
#define QRTR_NS_FWD_DST_NODE 0 /* modem */
|
||||
|
||||
/* Runtime kill-switch (qrtr.fp6_ns_push): off by default so a boot is
|
||||
* always calm; flip it on, then restart the modem rproc so its HELLO
|
||||
* triggers the replay.
|
||||
*/
|
||||
static bool fp6_ns_push;
|
||||
module_param(fp6_ns_push, bool, 0644);
|
||||
MODULE_PARM_DESC(fp6_ns_push, "FP6: push adsp service announcements to the modem");
|
||||
|
||||
static void service_announce_remotes(struct qrtr_server *srv,
|
||||
unsigned int origin, bool new)
|
||||
{
|
||||
struct sockaddr_qrtr sq;
|
||||
struct qrtr_node *node;
|
||||
|
||||
if (!fp6_ns_push)
|
||||
return;
|
||||
if (srv->node != QRTR_NS_FWD_SRC_NODE)
|
||||
return;
|
||||
if (origin == QRTR_NS_FWD_DST_NODE ||
|
||||
srv->node == QRTR_NS_FWD_DST_NODE ||
|
||||
qrtr_ns.local_node == QRTR_NS_FWD_DST_NODE)
|
||||
return;
|
||||
|
||||
node = xa_load(&nodes, QRTR_NS_FWD_DST_NODE);
|
||||
if (!node || !node->hello)
|
||||
return;
|
||||
|
||||
sq.sq_family = AF_QIPCRTR;
|
||||
sq.sq_node = QRTR_NS_FWD_DST_NODE;
|
||||
sq.sq_port = QRTR_PORT_CTRL;
|
||||
|
||||
if (new)
|
||||
service_announce_new(&sq, srv);
|
||||
else
|
||||
service_announce_del(&sq, srv);
|
||||
}
|
||||
|
||||
static int announce_servers(struct sockaddr_qrtr *sq)
|
||||
{
|
||||
struct qrtr_server *srv;
|
||||
|
|
@ -234,6 +289,24 @@ static int announce_servers(struct sockaddr_qrtr *sq)
|
|||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* FP6 voice: replay the ADSP's servers to a (re)booting modem (see
|
||||
* service_announce_remotes())
|
||||
*/
|
||||
if (fp6_ns_push && sq->sq_node == QRTR_NS_FWD_DST_NODE) {
|
||||
node = xa_load(&nodes, QRTR_NS_FWD_SRC_NODE);
|
||||
if (!node)
|
||||
return 0;
|
||||
|
||||
xa_for_each(&node->servers, index, srv) {
|
||||
ret = service_announce_new(sq, srv);
|
||||
if (ret < 0 && ret != -ENODEV) {
|
||||
pr_err("failed to announce new service\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -308,6 +381,8 @@ static int server_del(struct qrtr_node *node, unsigned int port, bool bcast)
|
|||
/* Broadcast the removal of local servers */
|
||||
if (srv->node == qrtr_ns.local_node && bcast)
|
||||
service_announce_del(&qrtr_ns.bcast_sq, srv);
|
||||
else if (bcast)
|
||||
service_announce_remotes(srv, srv->node, false);
|
||||
|
||||
/* Announce the service's disappearance to observers */
|
||||
list_for_each(li, &qrtr_ns.lookups) {
|
||||
|
|
@ -352,8 +427,13 @@ static int say_hello(struct sockaddr_qrtr *dest)
|
|||
/* Announce the list of servers registered on the local node */
|
||||
static int ctrl_cmd_hello(struct sockaddr_qrtr *sq)
|
||||
{
|
||||
struct qrtr_node *node;
|
||||
int ret;
|
||||
|
||||
node = node_get(sq->sq_node);
|
||||
if (node)
|
||||
node->hello = true;
|
||||
|
||||
ret = say_hello(sq);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
|
@ -521,6 +601,8 @@ static int ctrl_cmd_new_server(struct sockaddr_qrtr *from,
|
|||
pr_err("failed to announce new service\n");
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
service_announce_remotes(srv, from->sq_node, true);
|
||||
}
|
||||
|
||||
/* Notify any potential lookups about the new server */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue