CV-Bowen opened a new pull request, #21593:
URL: https://github.com/apache/nuttx/pull/21593
## Summary
Dispatch rpmsg_virtio rx in the rx interrupt and run `RPMSG_PRIO_RT`
endpoints there. Follow-up of apache/nuttx#21381, which prepared the rx
path (exported the open-amp rx helpers, installed the vq callbacks at
init), and of apache/nuttx#21547, which made `rdev->lock` a spinlock so
it can be taken in the interrupt.
- Walk the used ring in the rx interrupt instead of only waking the rx
thread. A message for an `RPMSG_PRIO_RT` endpoint that has finished
its name service handshake is delivered right there; every other
message goes on a ready list and is handled by the rx thread as
before. An RT endpoint still waiting for `NS_CREATE_ACK` keeps going
through the thread, so its first data message cannot overtake the
ACK. The check that drops a message whose length does not fit its
buffer moves with the ring walk.
- Ignore rx interrupts until the vdev is started: the rx callback is
installed through the config, so an interrupt can arrive while
`rpmsg_init_vdev_with_config()` is still running and before
`rvdev->rvq` is set. The initial dispatch in `rpmsg_virtio_start()`
handles what arrived earlier.
An RT endpoint callback runs in interrupt context. It must not block,
including waiting for a tx buffer (`rpmsg_get_tx_payload_buffer(...,
true)` or `rpmsg_send()`); an RT service that needs to reply when no
buffer may be free handles that itself, e.g. with `rpmsg_trysend()` or
by deferring the reply.
## Impact
- Endpoints with the default priority: no change, still called from the
rx thread.
- `RPMSG_PRIO_RT` endpoints (set with `rpmsg_set_priority()`): callback
now runs in the rx interrupt once the endpoint is bound. No in-tree
endpoint uses `RPMSG_PRIO_RT` today.
- No API or Kconfig change.
## Testing
Host: Ubuntu 22.04.5 LTS x86_64, QEMU version 10.2.1, sim: cc (Ubuntu
13.1.0-8ubuntu1~22.04) 13.1.0, qemu-armv8a: aarch64-none-elf-gcc (Arm GNU
Toolchain 12.2.Rel1 (Build arm-12.24)) 12.2.1 20221205
**RT path**: sim:rpserver/rpproxy and qemu-armv8a:rpserver/rpproxy with
a test-only patch (not part of this PR) that sets rpmsg_ping's endpoint
to `RPMSG_PRIO_RT` and logs the first callback in thread and in
interrupt context:
```diff
diff --git a/drivers/rpmsg/rpmsg_ping.c b/drivers/rpmsg/rpmsg_ping.c
index addfb3a239f..8cd057cbbd8 100644
--- a/drivers/rpmsg/rpmsg_ping.c
+++ b/drivers/rpmsg/rpmsg_ping.c
@@ -73,6 +73,14 @@ static int rpmsg_ping_ept_cb(FAR struct rpmsg_endpoint
*ept,
{
FAR struct rpmsg_ping_msg_s *msg = data;
FAR sem_t *sem = (FAR sem_t *)(uintptr_t)msg->cookie;
+ static bool logged[2];
+ int irq = up_interrupt_context();
+
+ if (!logged[irq])
+ {
+ logged[irq] = true;
+ syslog(LOG_INFO, "RTPATH %s in irq=%d\n", ept->name, irq);
+ }
/* Handle the ping response */
@@ -264,9 +272,17 @@ int rpmsg_ping(FAR struct rpmsg_endpoint *ept,
int rpmsg_ping_init(FAR struct rpmsg_device *rdev,
FAR struct rpmsg_endpoint *ept)
{
- return rpmsg_create_ept(ept, rdev, RPMSG_PING_EPT_NAME,
- RPMSG_ADDR_ANY, RPMSG_ADDR_ANY,
- rpmsg_ping_ept_cb, NULL);
+ int ret;
+
+ ret = rpmsg_create_ept(ept, rdev, RPMSG_PING_EPT_NAME,
+ RPMSG_ADDR_ANY, RPMSG_ADDR_ANY,
+ rpmsg_ping_ept_cb, NULL);
+ if (ret >= 0)
+ {
+ rpmsg_set_priority(ept, RPMSG_PRIO_RT);
+ }
+
+ return ret;
}
void rpmsg_ping_deinit(FAR struct rpmsg_endpoint *ept)
```
nsh on each side: `rpmsg ping all 20 1024 3 0` (20 pings of 1024 bytes,
every byte checked by the peer).
| | qemu-armv8a (ivshmem rptun) | sim (rptun from a work queue) |
| --- | --- | --- |
| master + test patch | callback only in thread (`irq=0`); 20/20 | `irq=0`;
20/20 |
| this PR + test patch | first message in thread (`irq=0`, before the
handshake completes), then in the interrupt (`irq=1`); 20/20 | `irq=0`; 20/20 |
sim delivers rptun notifications from a work queue, so there is no
interrupt to run in there; it is listed to show the thread fallback
still works. Logs, qemu-armv8a with this PR:
```
[server] RTPATH rpmsg-ping in irq=0
[server] RTPATH rpmsg-ping in irq=1
[proxy] RTPATH rpmsg-ping in irq=0
[proxy] RTPATH rpmsg-ping in irq=1
```
**Baseline**, without the test patch:
<details><summary>results.md</summary>
Baseline (`test.sh`, cases: baseline.yaml):
- host: Ubuntu 22.04.5 LTS x86_64, QEMU version 10.2.1, sim: cc (Ubuntu
13.1.0-8ubuntu1~22.04) 13.1.0, qemu-armv8a: aarch64-none-elf-gcc (Arm GNU
Toolchain 12.2.Rel1 (Build arm-12.24)) 12.2.1 20221205
- tested: nuttx b1ac3cd9ba7 apps 19a303645
- qemu-armv8a:rpserver qemu-armv8a:rpproxy built with test-only overlay:
disabled LIBC_ENVPATH BINFMT_CHECKEXEC
- sim:rpserver + sim:rpproxy: PASS
- [x] `uname -a` (server)
- [x] `rpmsg dump all` (server)
- [x] `rpmsg ping all 10 1024 3 0` (server)
- [x] `uname -a` (proxy)
- [x] `rpmsg ping all 10 1024 3 0` (proxy)
- [x] `mount -t rpmsgfs -o cpu=server,fs=/proc /sp` (proxy)
- [x] `cat /sp/version` (proxy)
- [x] `rpmsg dump all` (proxy)
- qemu-armv8a:rpserver + qemu-armv8a:rpproxy: PASS
- [x] `uname -a` (server)
- [x] `uname -a` (proxy)
- [x] `rpmsg dump all` (server)
- [x] `rpmsg ping all 10 1024 3 0` (server)
- [x] `rpmsg ping all 10 1024 3 0` (proxy)
- [x] `mount -t rpmsgfs -o cpu=server,fs=/proc /sp` (proxy)
- [x] `cat /sp/version` (proxy)
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]