Skip to content

Commit 0c7e420

Browse files
CV-Bowenarnopo
authored andcommitted
remoteproc_virtio: optimize the remoteproc virtio transport layer
1. Implement the rproc_virtio_create_virtqueues() and rproc_virtio_delete_virtqueues(). 2. Because 1, also modified the rpmsg init. Signed-off-by: Bowen Wang <wangbowen6@xiaomi.com>
1 parent f94dde5 commit 0c7e420

3 files changed

Lines changed: 186 additions & 48 deletions

File tree

lib/include/openamp/rpmsg_virtio.h

Lines changed: 70 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,43 +118,99 @@ __deprecated static inline int deprecated_rpmsg_slave(void)
118118
return RPMSG_REMOTE;
119119
}
120120

121+
/**
122+
* @brief Get rpmsg virtio device role.
123+
*
124+
* @param rvdev Pointer to rpmsg virtio device.
125+
*
126+
* @return RPMSG_REMOTE or RPMSG_HOST
127+
*/
121128
static inline unsigned int
122129
rpmsg_virtio_get_role(struct rpmsg_virtio_device *rvdev)
123130
{
124131
return rvdev->vdev->role;
125132
}
126133

134+
/**
135+
* @brief Set rpmsg virtio device status.
136+
*
137+
* @param rvdev Pointer to rpmsg virtio device.
138+
* @param status Value to be set as rpmsg virtio device status.
139+
*/
127140
static inline void rpmsg_virtio_set_status(struct rpmsg_virtio_device *rvdev,
128141
uint8_t status)
129142
{
130143
rvdev->vdev->func->set_status(rvdev->vdev, status);
131144
}
132145

146+
/**
147+
* @brief Retrieve rpmsg virtio device status.
148+
*
149+
* @param rvdev Pointer to rpmsg virtio device.
150+
*
151+
* @return The rpmsg virtio device status.
152+
*/
133153
static inline uint8_t rpmsg_virtio_get_status(struct rpmsg_virtio_device *rvdev)
134154
{
135155
return rvdev->vdev->func->get_status(rvdev->vdev);
136156
}
137157

158+
/**
159+
* @brief Get the rpmsg virtio device features.
160+
*
161+
* @param rvdev Pointer to the rpmsg virtio device.
162+
*
163+
* @return The features supported by both the rpmsg driver and rpmsg device.
164+
*/
138165
static inline uint32_t
139166
rpmsg_virtio_get_features(struct rpmsg_virtio_device *rvdev)
140167
{
141168
return rvdev->vdev->func->get_features(rvdev->vdev);
142169
}
143170

171+
/**
172+
* @brief Retrieve configuration data from the rpmsg virtio device.
173+
*
174+
* @param rvdev Pointer to the rpmsg virtio device.
175+
* @param offset Offset of the data within the configuration area.
176+
* @param dst Address of the buffer that will hold the data.
177+
* @param length Length of the data to be retrieved.
178+
*/
144179
static inline void
145180
rpmsg_virtio_read_config(struct rpmsg_virtio_device *rvdev,
146181
uint32_t offset, void *dst, int length)
147182
{
148183
rvdev->vdev->func->read_config(rvdev->vdev, offset, dst, length);
149184
}
150185

186+
/**
187+
* @brief Write configuration data to the rpmsg virtio device.
188+
*
189+
* @param rvdev Pointer to the rpmsg virtio device.
190+
* @param offset Offset of the data within the configuration area.
191+
* @param src Address of the buffer that holds the data to write.
192+
* @param length Length of the data to be written.
193+
*
194+
* @return 0 on success, otherwise error code.
195+
*/
151196
static inline void
152197
rpmsg_virtio_write_config(struct rpmsg_virtio_device *rvdev,
153-
uint32_t offset, void *dst, int length)
198+
uint32_t offset, void *src, int length)
154199
{
155-
rvdev->vdev->func->write_config(rvdev->vdev, offset, dst, length);
200+
rvdev->vdev->func->write_config(rvdev->vdev, offset, src, length);
156201
}
157202

203+
/**
204+
* @brief Create the rpmsg virtio device virtqueue.
205+
*
206+
* @param rvdev Pointer to the rpmsg virtio device.
207+
* @param flags Create flag.
208+
* @param nvqs The virtqueue number.
209+
* @param names Virtqueue names.
210+
* @param callbacks Virtqueue callback functions.
211+
*
212+
* @return 0 on success, otherwise error code.
213+
*/
158214
static inline int
159215
rpmsg_virtio_create_virtqueues(struct rpmsg_virtio_device *rvdev,
160216
int flags, unsigned int nvqs,
@@ -166,7 +222,18 @@ rpmsg_virtio_create_virtqueues(struct rpmsg_virtio_device *rvdev,
166222
}
167223

168224
/**
169-
* @brief Get rpmsg virtio Tx buffer size
225+
* @brief Delete the virtqueues created in rpmsg_virtio_create_virtqueues()
226+
*
227+
* @param rvdev Pointer to the rpmsg virtio device
228+
*/
229+
static inline void
230+
rpmsg_virtio_delete_virtqueues(struct rpmsg_virtio_device *rvdev)
231+
{
232+
virtio_delete_virtqueues(rvdev->vdev);
233+
}
234+
235+
/**
236+
* @brief Get rpmsg virtio buffer size
170237
*
171238
* @param rdev Pointer to the rpmsg device
172239
*

lib/remoteproc/remoteproc_virtio.c

Lines changed: 91 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,89 @@
1616
#include <metal/utilities.h>
1717
#include <metal/alloc.h>
1818

19+
static void rproc_virtio_delete_virtqueues(struct virtio_device *vdev)
20+
{
21+
struct virtio_vring_info *vring_info;
22+
unsigned int i;
23+
24+
if (!vdev->vrings_info)
25+
return;
26+
27+
for (i = 0; i < vdev->vrings_num; i++) {
28+
vring_info = &vdev->vrings_info[i];
29+
if (vring_info->vq)
30+
virtqueue_free(vring_info->vq);
31+
}
32+
}
33+
34+
static int rproc_virtio_create_virtqueue(struct virtio_device *vdev,
35+
unsigned int flags,
36+
unsigned int idx,
37+
const char *name,
38+
vq_callback callback)
39+
{
40+
struct virtio_vring_info *vring_info;
41+
struct vring_alloc_info *vring_alloc;
42+
int ret;
43+
(void)flags;
44+
45+
/* Get the vring information */
46+
vring_info = &vdev->vrings_info[idx];
47+
vring_alloc = &vring_info->info;
48+
49+
/* Fail if the virtqueue has already been created */
50+
if (vring_info->vq)
51+
return ERROR_VQUEUE_INVLD_PARAM;
52+
53+
/* Alloc the virtqueue and init it */
54+
vring_info->vq = virtqueue_allocate(vring_alloc->num_descs);
55+
if (!vring_info->vq)
56+
return ERROR_NO_MEM;
57+
58+
#ifndef VIRTIO_DEVICE_ONLY
59+
if (vdev->role == VIRTIO_DEV_DRIVER) {
60+
size_t offset = metal_io_virt_to_offset(vring_info->io, vring_alloc->vaddr);
61+
size_t size = vring_size(vring_alloc->num_descs, vring_alloc->align);
62+
63+
metal_io_block_set(vring_info->io, offset, 0, size);
64+
}
65+
#endif
66+
ret = virtqueue_create(vdev, idx, name, vring_alloc, callback,
67+
vdev->func->notify, vring_info->vq);
68+
if (ret)
69+
return ret;
70+
71+
return 0;
72+
}
73+
74+
static int rproc_virtio_create_virtqueues(struct virtio_device *vdev,
75+
unsigned int flags,
76+
unsigned int nvqs,
77+
const char *names[],
78+
vq_callback callbacks[],
79+
void *callback_args[])
80+
{
81+
unsigned int i;
82+
int ret;
83+
(void)callback_args;
84+
85+
/* Check virtqueue numbers and the vrings_info */
86+
if (nvqs > vdev->vrings_num || !vdev || !vdev->vrings_info)
87+
return ERROR_VQUEUE_INVLD_PARAM;
88+
89+
/* set the notification id for vrings */
90+
for (i = 0; i < nvqs; i++) {
91+
ret = rproc_virtio_create_virtqueue(vdev, flags, i, names[i], callbacks[i]);
92+
if (ret)
93+
goto err;
94+
}
95+
return 0;
96+
97+
err:
98+
rproc_virtio_delete_virtqueues(vdev);
99+
return ret;
100+
}
101+
19102
static void rproc_virtio_virtqueue_notify(struct virtqueue *vq)
20103
{
21104
struct remoteproc_virtio *rpvdev;
@@ -198,6 +281,8 @@ static void rproc_virtio_reset_device(struct virtio_device *vdev)
198281
#endif
199282

200283
static const struct virtio_dispatch remoteproc_virtio_dispatch_funcs = {
284+
.create_virtqueues = rproc_virtio_create_virtqueues,
285+
.delete_virtqueues = rproc_virtio_delete_virtqueues,
201286
.get_status = rproc_virtio_get_status,
202287
.get_features = rproc_virtio_get_features,
203288
.read_config = rproc_virtio_read_config,
@@ -229,46 +314,28 @@ rproc_virtio_create_vdev(unsigned int role, unsigned int notifyid,
229314
struct fw_rsc_vdev *vdev_rsc = rsc;
230315
struct virtio_device *vdev;
231316
unsigned int num_vrings = vdev_rsc->num_of_vrings;
232-
unsigned int i;
233317

234318
rpvdev = metal_allocate_memory(sizeof(*rpvdev));
235319
if (!rpvdev)
236320
return NULL;
237321
vrings_info = metal_allocate_memory(sizeof(*vrings_info) * num_vrings);
238322
if (!vrings_info)
239-
goto err0;
323+
goto err;
240324
memset(rpvdev, 0, sizeof(*rpvdev));
241325
memset(vrings_info, 0, sizeof(*vrings_info) * num_vrings);
242-
vdev = &rpvdev->vdev;
243-
244-
for (i = 0; i < num_vrings; i++) {
245-
struct virtqueue *vq;
246-
#ifndef VIRTIO_DEVICE_ONLY
247-
struct fw_rsc_vdev_vring *vring_rsc;
248-
#endif
249-
unsigned int num_extra_desc = 0;
250-
251-
#ifndef VIRTIO_DEVICE_ONLY
252-
vring_rsc = &vdev_rsc->vring[i];
253-
if (role == VIRTIO_DEV_DRIVER) {
254-
num_extra_desc = vring_rsc->num;
255-
}
256-
#endif
257-
vq = virtqueue_allocate(num_extra_desc);
258-
if (!vq)
259-
goto err1;
260-
vrings_info[i].vq = vq;
261-
}
262326

327+
/* Initialize the remoteproc virtio */
263328
rpvdev->notify = notify;
264329
rpvdev->priv = priv;
265-
vdev->vrings_info = vrings_info;
266330
/* Assuming the shared memory has been mapped and registered if
267331
* necessary
268332
*/
269333
rpvdev->vdev_rsc = vdev_rsc;
270334
rpvdev->vdev_rsc_io = rsc_io;
271335

336+
/* Initialize the virtio device */
337+
vdev = &rpvdev->vdev;
338+
vdev->vrings_info = vrings_info;
272339
vdev->notifyid = notifyid;
273340
vdev->id.device = vdev_rsc->id;
274341
vdev->role = role;
@@ -285,33 +352,18 @@ rproc_virtio_create_vdev(unsigned int role, unsigned int notifyid,
285352
#endif
286353

287354
return &rpvdev->vdev;
288-
289-
err1:
290-
for (i = 0; i < num_vrings; i++) {
291-
if (vrings_info[i].vq)
292-
metal_free_memory(vrings_info[i].vq);
293-
}
294-
metal_free_memory(vrings_info);
295-
err0:
355+
err:
296356
metal_free_memory(rpvdev);
297357
return NULL;
298358
}
299359

300360
void rproc_virtio_remove_vdev(struct virtio_device *vdev)
301361
{
302362
struct remoteproc_virtio *rpvdev;
303-
unsigned int i;
304363

305364
if (!vdev)
306365
return;
307366
rpvdev = metal_container_of(vdev, struct remoteproc_virtio, vdev);
308-
for (i = 0; i < vdev->vrings_num; i++) {
309-
struct virtqueue *vq;
310-
311-
vq = vdev->vrings_info[i].vq;
312-
if (vq)
313-
metal_free_memory(vq);
314-
}
315367
if (vdev->vrings_info)
316368
metal_free_memory(vdev->vrings_info);
317369
metal_free_memory(rpvdev);

lib/rpmsg/rpmsg_virtio.c

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -870,8 +870,6 @@ int rpmsg_init_vdev_with_config(struct rpmsg_virtio_device *rvdev,
870870
vq_names[1] = "tx_vq";
871871
callback[0] = rpmsg_virtio_rx_callback;
872872
callback[1] = rpmsg_virtio_tx_callback;
873-
rvdev->rvq = vdev->vrings_info[0].vq;
874-
rvdev->svq = vdev->vrings_info[1].vq;
875873
}
876874
#endif /*!VIRTIO_DEVICE_ONLY*/
877875

@@ -882,8 +880,6 @@ int rpmsg_init_vdev_with_config(struct rpmsg_virtio_device *rvdev,
882880
vq_names[1] = "rx_vq";
883881
callback[0] = rpmsg_virtio_tx_callback;
884882
callback[1] = rpmsg_virtio_rx_callback;
885-
rvdev->rvq = vdev->vrings_info[1].vq;
886-
rvdev->svq = vdev->vrings_info[0].vq;
887883
}
888884
#endif /*!VIRTIO_DRIVER_ONLY*/
889885
rvdev->shbuf_io = shm_io;
@@ -895,6 +891,21 @@ int rpmsg_init_vdev_with_config(struct rpmsg_virtio_device *rvdev,
895891
if (status != RPMSG_SUCCESS)
896892
return status;
897893

894+
/* Create virtqueue success, assign back the virtqueue */
895+
#ifndef VIRTIO_DEVICE_ONLY
896+
if (role == RPMSG_HOST) {
897+
rvdev->rvq = vdev->vrings_info[0].vq;
898+
rvdev->svq = vdev->vrings_info[1].vq;
899+
}
900+
#endif /*!VIRTIO_DEVICE_ONLY*/
901+
902+
#ifndef VIRTIO_DRIVER_ONLY
903+
if (role == RPMSG_REMOTE) {
904+
rvdev->rvq = vdev->vrings_info[1].vq;
905+
rvdev->svq = vdev->vrings_info[0].vq;
906+
}
907+
#endif /*!VIRTIO_DRIVER_ONLY*/
908+
898909
/*
899910
* Suppress "tx-complete" interrupts
900911
* since send method use busy loop when buffer pool exhaust
@@ -922,7 +933,8 @@ int rpmsg_init_vdev_with_config(struct rpmsg_virtio_device *rvdev,
922933
rvdev->config.r2h_buf_size);
923934

924935
if (!buffer) {
925-
return RPMSG_ERR_NO_BUFF;
936+
status = RPMSG_ERR_NO_BUFF;
937+
goto err;
926938
}
927939

928940
vqbuf.buf = buffer;
@@ -936,7 +948,7 @@ int rpmsg_init_vdev_with_config(struct rpmsg_virtio_device *rvdev,
936948
buffer);
937949

938950
if (status != RPMSG_SUCCESS) {
939-
return status;
951+
goto err;
940952
}
941953
}
942954
}
@@ -960,7 +972,13 @@ int rpmsg_init_vdev_with_config(struct rpmsg_virtio_device *rvdev,
960972
rpmsg_virtio_set_status(rvdev, VIRTIO_CONFIG_STATUS_DRIVER_OK);
961973
#endif /*!VIRTIO_DEVICE_ONLY*/
962974

975+
return RPMSG_SUCCESS;
976+
977+
#ifndef VIRTIO_DEVICE_ONLY
978+
err:
979+
rpmsg_virtio_delete_virtqueues(rvdev);
963980
return status;
981+
#endif /*!VIRTIO_DEVICE_ONLY*/
964982
}
965983

966984
void rpmsg_deinit_vdev(struct rpmsg_virtio_device *rvdev)
@@ -980,6 +998,7 @@ void rpmsg_deinit_vdev(struct rpmsg_virtio_device *rvdev)
980998
rvdev->rvq = 0;
981999
rvdev->svq = 0;
9821000

1001+
rpmsg_virtio_delete_virtqueues(rvdev);
9831002
metal_mutex_deinit(&rdev->lock);
9841003
}
9851004
}

0 commit comments

Comments
 (0)