24
24
/* Time to wait - In multiple of 1 msecs. */
25
25
#define RPMSG_TICKS_PER_INTERVAL 1000
26
26
27
+ /*
28
+ * Get the buffer held counter value.
29
+ * If 0 the buffer can be released
30
+ */
31
+ #define RPMSG_BUF_HELD_COUNTER (rp_hdr ) \
32
+ (((rp_hdr)->reserved & RPMSG_BUF_HELD_MASK) >> RPMSG_BUF_HELD_SHIFT)
33
+
34
+ /* Increase buffer held counter */
35
+ #define RPMSG_BUF_HELD_INC (rp_hdr ) \
36
+ ((rp_hdr)->reserved += 1 << RPMSG_BUF_HELD_SHIFT)
37
+
38
+ /* Decrease buffer held counter */
39
+ #define RPMSG_BUF_HELD_DEC (rp_hdr ) \
40
+ ((rp_hdr)->reserved -= 1 << RPMSG_BUF_HELD_SHIFT)
41
+
42
+ /* Get the buffer index */
43
+ #define RPMSG_BUF_INDEX (rphdr ) \
44
+ ((uint16_t)((rp_hdr)->reserved & ~RPMSG_BUF_HELD_MASK))
45
+
27
46
/**
28
47
* struct vbuff_reclaimer_t - vring buffer recycler
29
48
*
@@ -272,37 +291,70 @@ static int rpmsg_virtio_wait_remote_ready(struct rpmsg_virtio_device *rvdev)
272
291
}
273
292
#endif /*!VIRTIO_DRIVER_ONLY*/
274
293
294
+ /**
295
+ * @internal
296
+ *
297
+ * @brief Check whether rpmsg buffer needs to be released or not
298
+ *
299
+ * @param rp_hdr Pointer to rpmsg buffer header
300
+ *
301
+ * @return true indicates this buffer needs to be released
302
+ */
303
+ static bool rpmsg_virtio_buf_held_dec_test (struct rpmsg_hdr * rp_hdr )
304
+ {
305
+ /* Check the held counter first */
306
+ if (RPMSG_BUF_HELD_COUNTER (rp_hdr ) <= 0 ) {
307
+ metal_err ("unexpected buffer held counter\r\n" );
308
+ return false;
309
+ }
310
+
311
+ /* Decrease the held counter */
312
+ RPMSG_BUF_HELD_DEC (rp_hdr );
313
+
314
+ /* Check whether to release the buffer */
315
+ if (RPMSG_BUF_HELD_COUNTER (rp_hdr ) > 0 )
316
+ return false;
317
+
318
+ return true;
319
+ }
320
+
275
321
static void rpmsg_virtio_hold_rx_buffer (struct rpmsg_device * rdev , void * rxbuf )
276
322
{
277
- struct rpmsg_hdr * rp_hdr ;
323
+ metal_mutex_acquire (& rdev -> lock );
324
+ RPMSG_BUF_HELD_INC (RPMSG_LOCATE_HDR (rxbuf ));
325
+ metal_mutex_release (& rdev -> lock );
326
+ }
278
327
279
- (void )rdev ;
328
+ static bool rpmsg_virtio_release_rx_buffer_nolock (struct rpmsg_virtio_device * rvdev ,
329
+ struct rpmsg_hdr * rp_hdr )
330
+ {
331
+ uint16_t idx ;
332
+ uint32_t len ;
280
333
281
- rp_hdr = RPMSG_LOCATE_HDR (rxbuf );
334
+ /* The reserved field contains buffer index */
335
+ idx = RPMSG_BUF_INDEX (rp_hdr );
336
+ /* Return buffer on virtqueue. */
337
+ len = virtqueue_get_buffer_length (rvdev -> rvq , idx );
338
+ rpmsg_virtio_return_buffer (rvdev , rp_hdr , len , idx );
282
339
283
- /* Set held status to keep buffer */
284
- rp_hdr -> reserved |= RPMSG_BUF_HELD ;
340
+ return true;
285
341
}
286
342
287
343
static void rpmsg_virtio_release_rx_buffer (struct rpmsg_device * rdev ,
288
344
void * rxbuf )
289
345
{
290
346
struct rpmsg_virtio_device * rvdev ;
291
347
struct rpmsg_hdr * rp_hdr ;
292
- uint16_t idx ;
293
- uint32_t len ;
294
348
295
349
rvdev = metal_container_of (rdev , struct rpmsg_virtio_device , rdev );
296
350
rp_hdr = RPMSG_LOCATE_HDR (rxbuf );
297
- /* The reserved field contains buffer index */
298
- idx = (uint16_t )(rp_hdr -> reserved & ~RPMSG_BUF_HELD );
299
351
300
352
metal_mutex_acquire (& rdev -> lock );
301
- /* Return buffer on virtqueue. */
302
- len = virtqueue_get_buffer_length (rvdev -> rvq , idx );
303
- rpmsg_virtio_return_buffer ( rvdev , rp_hdr , len , idx );
304
- /* Tell peer we return some rx buffers */
305
- virtqueue_kick ( rvdev -> rvq );
353
+ if ( rpmsg_virtio_buf_held_dec_test ( rp_hdr )) {
354
+ rpmsg_virtio_release_rx_buffer_nolock (rvdev , rp_hdr );
355
+ /* Tell peer we return some rx buffers */
356
+ virtqueue_kick ( rvdev -> rvq );
357
+ }
306
358
metal_mutex_release (& rdev -> lock );
307
359
}
308
360
@@ -361,6 +413,9 @@ static void *rpmsg_virtio_get_tx_payload_buffer(struct rpmsg_device *rdev,
361
413
/* Store the index into the reserved field to be used when sending */
362
414
rp_hdr -> reserved = idx ;
363
415
416
+ /* Increase the held counter to hold this Tx buffer */
417
+ RPMSG_BUF_HELD_INC (rp_hdr );
418
+
364
419
/* Actual data buffer size is vring buffer size minus header length */
365
420
* len -= sizeof (struct rpmsg_hdr );
366
421
return RPMSG_LOCATE_DATA (rp_hdr );
@@ -424,20 +479,20 @@ static int rpmsg_virtio_release_tx_buffer(struct rpmsg_device *rdev, void *txbuf
424
479
struct rpmsg_hdr * rp_hdr = RPMSG_LOCATE_HDR (txbuf );
425
480
void * vbuff = rp_hdr ; /* only used to avoid warning on the cast of a packed structure */
426
481
struct vbuff_reclaimer_t * r_desc = (struct vbuff_reclaimer_t * )vbuff ;
427
- uint16_t idx ;
428
-
429
- /*
430
- * Reuse the RPMsg buffer to temporary store the vbuff_reclaimer_t structure.
431
- * Stores the index locally before overwriting the RPMsg header.
432
- */
433
- idx = rp_hdr -> reserved ;
434
482
435
483
rvdev = metal_container_of (rdev , struct rpmsg_virtio_device , rdev );
436
484
437
485
metal_mutex_acquire (& rdev -> lock );
438
486
439
- r_desc -> idx = idx ;
440
- metal_list_add_tail (& rvdev -> reclaimer , & r_desc -> node );
487
+ /* Check whether to release the Tx buffer */
488
+ if (rpmsg_virtio_buf_held_dec_test (rp_hdr )) {
489
+ /*
490
+ * Reuse the RPMsg buffer to temporary store the vbuff_reclaimer_t structure.
491
+ * Store the index locally before overwriting the RPMsg header.
492
+ */
493
+ r_desc -> idx = RPMSG_BUF_INDEX (rp_hdr );
494
+ metal_list_add_tail (& rvdev -> reclaimer , & r_desc -> node );
495
+ }
441
496
442
497
metal_mutex_release (& rdev -> lock );
443
498
@@ -534,6 +589,7 @@ static void rpmsg_virtio_rx_callback(struct virtqueue *vq)
534
589
metal_mutex_acquire (& rdev -> lock );
535
590
ept = rpmsg_get_ept_from_addr (rdev , rp_hdr -> dst );
536
591
rpmsg_ept_incref (ept );
592
+ RPMSG_BUF_HELD_INC (rp_hdr );
537
593
metal_mutex_release (& rdev -> lock );
538
594
539
595
if (ept ) {
@@ -553,12 +609,8 @@ static void rpmsg_virtio_rx_callback(struct virtqueue *vq)
553
609
554
610
metal_mutex_acquire (& rdev -> lock );
555
611
rpmsg_ept_decref (ept );
556
-
557
- /* Check whether callback wants to hold buffer */
558
- if (!(rp_hdr -> reserved & RPMSG_BUF_HELD )) {
559
- /* No, return used buffers. */
560
- rpmsg_virtio_return_buffer (rvdev , rp_hdr , len , idx );
561
- }
612
+ if (rpmsg_virtio_buf_held_dec_test (rp_hdr ))
613
+ rpmsg_virtio_release_rx_buffer_nolock (rvdev , rp_hdr );
562
614
563
615
rp_hdr = rpmsg_virtio_get_rx_buffer (rvdev , & len , & idx );
564
616
if (!rp_hdr ) {
0 commit comments