Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

rpmsg: use less buffers when vrings are small

Adjust the number of rpmsg buffers to rely on the size of the
vring, instead of using the hard coded value of 512 (256 per
direction).

This is needed when small vrings are being used, where 256
buffers are too much to fit in a vring.

While considering the vring size, keep using the 512 hard coded
value as an upper limit to avoid wacky resource tables consuming
unreasonable amount of memory.

NOTE: The number of buffers is already assumed to be symmetrical
in each direction, and that logic is unchanged.

Signed-off-by: Suman Anna <s-anna@ti.com>
[edit commit message, small code and comment simplification]
Signed-off-by: Ohad Ben-Cohen <ohad@wizery.com>

authored by

Suman Anna and committed by
Ohad Ben-Cohen
b1b98914 5d01410f

+30 -14
+30 -14
drivers/rpmsg/virtio_rpmsg_bus.c
··· 41 41 * @svq: tx virtqueue 42 42 * @rbufs: kernel address of rx buffers 43 43 * @sbufs: kernel address of tx buffers 44 + * @num_bufs: total number of buffers for rx and tx 44 45 * @last_sbuf: index of last tx buffer used 45 46 * @bufs_dma: dma base addr of the buffers 46 47 * @tx_lock: protects svq, sbufs and sleepers, to allow concurrent senders. ··· 61 60 struct virtio_device *vdev; 62 61 struct virtqueue *rvq, *svq; 63 62 void *rbufs, *sbufs; 63 + unsigned int num_bufs; 64 64 int last_sbuf; 65 65 dma_addr_t bufs_dma; 66 66 struct mutex tx_lock; ··· 88 86 #define to_rpmsg_driver(d) container_of(d, struct rpmsg_driver, drv) 89 87 90 88 /* 91 - * We're allocating 512 buffers of 512 bytes for communications, and then 92 - * using the first 256 buffers for RX, and the last 256 buffers for TX. 89 + * We're allocating buffers of 512 bytes each for communications. The 90 + * number of buffers will be computed from the number of buffers supported 91 + * by the vring, upto a maximum of 512 buffers (256 in each direction). 93 92 * 94 93 * Each buffer will have 16 bytes for the msg header and 496 bytes for 95 94 * the payload. 96 95 * 97 - * This will require a total space of 256KB for the buffers. 96 + * This will utilize a maximum total space of 256KB for the buffers. 98 97 * 99 98 * We might also want to add support for user-provided buffers in time. 100 99 * This will allow bigger buffer size flexibility, and can also be used ··· 105 102 * can change this without changing anything in the firmware of the remote 106 103 * processor. 107 104 */ 108 - #define RPMSG_NUM_BUFS (512) 105 + #define MAX_RPMSG_NUM_BUFS (512) 109 106 #define RPMSG_BUF_SIZE (512) 110 - #define RPMSG_TOTAL_BUF_SPACE (RPMSG_NUM_BUFS * RPMSG_BUF_SIZE) 111 107 112 108 /* 113 109 * Local addresses are dynamically allocated on-demand. ··· 581 579 * either pick the next unused tx buffer 582 580 * (half of our buffers are used for sending messages) 583 581 */ 584 - if (vrp->last_sbuf < RPMSG_NUM_BUFS / 2) 582 + if (vrp->last_sbuf < vrp->num_bufs / 2) 585 583 ret = vrp->sbufs + RPMSG_BUF_SIZE * vrp->last_sbuf++; 586 584 /* or recycle a used one */ 587 585 else ··· 950 948 struct virtproc_info *vrp; 951 949 void *bufs_va; 952 950 int err = 0, i; 951 + size_t total_buf_space; 953 952 954 953 vrp = kzalloc(sizeof(*vrp), GFP_KERNEL); 955 954 if (!vrp) ··· 971 968 vrp->rvq = vqs[0]; 972 969 vrp->svq = vqs[1]; 973 970 971 + /* we expect symmetric tx/rx vrings */ 972 + WARN_ON(virtqueue_get_vring_size(vrp->rvq) != 973 + virtqueue_get_vring_size(vrp->svq)); 974 + 975 + /* we need less buffers if vrings are small */ 976 + if (virtqueue_get_vring_size(vrp->rvq) < MAX_RPMSG_NUM_BUFS / 2) 977 + vrp->num_bufs = virtqueue_get_vring_size(vrp->rvq) * 2; 978 + else 979 + vrp->num_bufs = MAX_RPMSG_NUM_BUFS; 980 + 981 + total_buf_space = vrp->num_bufs * RPMSG_BUF_SIZE; 982 + 974 983 /* allocate coherent memory for the buffers */ 975 984 bufs_va = dma_alloc_coherent(vdev->dev.parent->parent, 976 - RPMSG_TOTAL_BUF_SPACE, 977 - &vrp->bufs_dma, GFP_KERNEL); 985 + total_buf_space, &vrp->bufs_dma, 986 + GFP_KERNEL); 978 987 if (!bufs_va) { 979 988 err = -ENOMEM; 980 989 goto vqs_del; ··· 999 984 vrp->rbufs = bufs_va; 1000 985 1001 986 /* and half is dedicated for TX */ 1002 - vrp->sbufs = bufs_va + RPMSG_TOTAL_BUF_SPACE / 2; 987 + vrp->sbufs = bufs_va + total_buf_space / 2; 1003 988 1004 989 /* set up the receive buffers */ 1005 - for (i = 0; i < RPMSG_NUM_BUFS / 2; i++) { 990 + for (i = 0; i < vrp->num_bufs / 2; i++) { 1006 991 struct scatterlist sg; 1007 992 void *cpu_addr = vrp->rbufs + i * RPMSG_BUF_SIZE; 1008 993 ··· 1038 1023 return 0; 1039 1024 1040 1025 free_coherent: 1041 - dma_free_coherent(vdev->dev.parent->parent, RPMSG_TOTAL_BUF_SPACE, 1042 - bufs_va, vrp->bufs_dma); 1026 + dma_free_coherent(vdev->dev.parent->parent, total_buf_space, 1027 + bufs_va, vrp->bufs_dma); 1043 1028 vqs_del: 1044 1029 vdev->config->del_vqs(vrp->vdev); 1045 1030 free_vrp: ··· 1057 1042 static void rpmsg_remove(struct virtio_device *vdev) 1058 1043 { 1059 1044 struct virtproc_info *vrp = vdev->priv; 1045 + size_t total_buf_space = vrp->num_bufs * RPMSG_BUF_SIZE; 1060 1046 int ret; 1061 1047 1062 1048 vdev->config->reset(vdev); ··· 1073 1057 1074 1058 vdev->config->del_vqs(vrp->vdev); 1075 1059 1076 - dma_free_coherent(vdev->dev.parent->parent, RPMSG_TOTAL_BUF_SPACE, 1077 - vrp->rbufs, vrp->bufs_dma); 1060 + dma_free_coherent(vdev->dev.parent->parent, total_buf_space, 1061 + vrp->rbufs, vrp->bufs_dma); 1078 1062 1079 1063 kfree(vrp); 1080 1064 }