Commit b1b98914 authored by Suman Anna's avatar Suman Anna Committed by Ohad Ben-Cohen

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: default avatarSuman Anna <s-anna@ti.com>
[edit commit message, small code and comment simplification]
Signed-off-by: default avatarOhad Ben-Cohen <ohad@wizery.com>
parent 5d01410f
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
* @svq: tx virtqueue * @svq: tx virtqueue
* @rbufs: kernel address of rx buffers * @rbufs: kernel address of rx buffers
* @sbufs: kernel address of tx buffers * @sbufs: kernel address of tx buffers
* @num_bufs: total number of buffers for rx and tx
* @last_sbuf: index of last tx buffer used * @last_sbuf: index of last tx buffer used
* @bufs_dma: dma base addr of the buffers * @bufs_dma: dma base addr of the buffers
* @tx_lock: protects svq, sbufs and sleepers, to allow concurrent senders. * @tx_lock: protects svq, sbufs and sleepers, to allow concurrent senders.
...@@ -60,6 +61,7 @@ struct virtproc_info { ...@@ -60,6 +61,7 @@ struct virtproc_info {
struct virtio_device *vdev; struct virtio_device *vdev;
struct virtqueue *rvq, *svq; struct virtqueue *rvq, *svq;
void *rbufs, *sbufs; void *rbufs, *sbufs;
unsigned int num_bufs;
int last_sbuf; int last_sbuf;
dma_addr_t bufs_dma; dma_addr_t bufs_dma;
struct mutex tx_lock; struct mutex tx_lock;
...@@ -86,13 +88,14 @@ struct rpmsg_channel_info { ...@@ -86,13 +88,14 @@ struct rpmsg_channel_info {
#define to_rpmsg_driver(d) container_of(d, struct rpmsg_driver, drv) #define to_rpmsg_driver(d) container_of(d, struct rpmsg_driver, drv)
/* /*
* We're allocating 512 buffers of 512 bytes for communications, and then * We're allocating buffers of 512 bytes each for communications. The
* using the first 256 buffers for RX, and the last 256 buffers for TX. * number of buffers will be computed from the number of buffers supported
* by the vring, upto a maximum of 512 buffers (256 in each direction).
* *
* Each buffer will have 16 bytes for the msg header and 496 bytes for * Each buffer will have 16 bytes for the msg header and 496 bytes for
* the payload. * the payload.
* *
* This will require a total space of 256KB for the buffers. * This will utilize a maximum total space of 256KB for the buffers.
* *
* We might also want to add support for user-provided buffers in time. * We might also want to add support for user-provided buffers in time.
* This will allow bigger buffer size flexibility, and can also be used * This will allow bigger buffer size flexibility, and can also be used
...@@ -102,9 +105,8 @@ struct rpmsg_channel_info { ...@@ -102,9 +105,8 @@ struct rpmsg_channel_info {
* can change this without changing anything in the firmware of the remote * can change this without changing anything in the firmware of the remote
* processor. * processor.
*/ */
#define RPMSG_NUM_BUFS (512) #define MAX_RPMSG_NUM_BUFS (512)
#define RPMSG_BUF_SIZE (512) #define RPMSG_BUF_SIZE (512)
#define RPMSG_TOTAL_BUF_SPACE (RPMSG_NUM_BUFS * RPMSG_BUF_SIZE)
/* /*
* Local addresses are dynamically allocated on-demand. * Local addresses are dynamically allocated on-demand.
...@@ -579,7 +581,7 @@ static void *get_a_tx_buf(struct virtproc_info *vrp) ...@@ -579,7 +581,7 @@ static void *get_a_tx_buf(struct virtproc_info *vrp)
* either pick the next unused tx buffer * either pick the next unused tx buffer
* (half of our buffers are used for sending messages) * (half of our buffers are used for sending messages)
*/ */
if (vrp->last_sbuf < RPMSG_NUM_BUFS / 2) if (vrp->last_sbuf < vrp->num_bufs / 2)
ret = vrp->sbufs + RPMSG_BUF_SIZE * vrp->last_sbuf++; ret = vrp->sbufs + RPMSG_BUF_SIZE * vrp->last_sbuf++;
/* or recycle a used one */ /* or recycle a used one */
else else
...@@ -948,6 +950,7 @@ static int rpmsg_probe(struct virtio_device *vdev) ...@@ -948,6 +950,7 @@ static int rpmsg_probe(struct virtio_device *vdev)
struct virtproc_info *vrp; struct virtproc_info *vrp;
void *bufs_va; void *bufs_va;
int err = 0, i; int err = 0, i;
size_t total_buf_space;
vrp = kzalloc(sizeof(*vrp), GFP_KERNEL); vrp = kzalloc(sizeof(*vrp), GFP_KERNEL);
if (!vrp) if (!vrp)
...@@ -968,10 +971,22 @@ static int rpmsg_probe(struct virtio_device *vdev) ...@@ -968,10 +971,22 @@ static int rpmsg_probe(struct virtio_device *vdev)
vrp->rvq = vqs[0]; vrp->rvq = vqs[0];
vrp->svq = vqs[1]; vrp->svq = vqs[1];
/* we expect symmetric tx/rx vrings */
WARN_ON(virtqueue_get_vring_size(vrp->rvq) !=
virtqueue_get_vring_size(vrp->svq));
/* we need less buffers if vrings are small */
if (virtqueue_get_vring_size(vrp->rvq) < MAX_RPMSG_NUM_BUFS / 2)
vrp->num_bufs = virtqueue_get_vring_size(vrp->rvq) * 2;
else
vrp->num_bufs = MAX_RPMSG_NUM_BUFS;
total_buf_space = vrp->num_bufs * RPMSG_BUF_SIZE;
/* allocate coherent memory for the buffers */ /* allocate coherent memory for the buffers */
bufs_va = dma_alloc_coherent(vdev->dev.parent->parent, bufs_va = dma_alloc_coherent(vdev->dev.parent->parent,
RPMSG_TOTAL_BUF_SPACE, total_buf_space, &vrp->bufs_dma,
&vrp->bufs_dma, GFP_KERNEL); GFP_KERNEL);
if (!bufs_va) { if (!bufs_va) {
err = -ENOMEM; err = -ENOMEM;
goto vqs_del; goto vqs_del;
...@@ -984,10 +999,10 @@ static int rpmsg_probe(struct virtio_device *vdev) ...@@ -984,10 +999,10 @@ static int rpmsg_probe(struct virtio_device *vdev)
vrp->rbufs = bufs_va; vrp->rbufs = bufs_va;
/* and half is dedicated for TX */ /* and half is dedicated for TX */
vrp->sbufs = bufs_va + RPMSG_TOTAL_BUF_SPACE / 2; vrp->sbufs = bufs_va + total_buf_space / 2;
/* set up the receive buffers */ /* set up the receive buffers */
for (i = 0; i < RPMSG_NUM_BUFS / 2; i++) { for (i = 0; i < vrp->num_bufs / 2; i++) {
struct scatterlist sg; struct scatterlist sg;
void *cpu_addr = vrp->rbufs + i * RPMSG_BUF_SIZE; void *cpu_addr = vrp->rbufs + i * RPMSG_BUF_SIZE;
...@@ -1023,8 +1038,8 @@ static int rpmsg_probe(struct virtio_device *vdev) ...@@ -1023,8 +1038,8 @@ static int rpmsg_probe(struct virtio_device *vdev)
return 0; return 0;
free_coherent: free_coherent:
dma_free_coherent(vdev->dev.parent->parent, RPMSG_TOTAL_BUF_SPACE, dma_free_coherent(vdev->dev.parent->parent, total_buf_space,
bufs_va, vrp->bufs_dma); bufs_va, vrp->bufs_dma);
vqs_del: vqs_del:
vdev->config->del_vqs(vrp->vdev); vdev->config->del_vqs(vrp->vdev);
free_vrp: free_vrp:
...@@ -1042,6 +1057,7 @@ static int rpmsg_remove_device(struct device *dev, void *data) ...@@ -1042,6 +1057,7 @@ static int rpmsg_remove_device(struct device *dev, void *data)
static void rpmsg_remove(struct virtio_device *vdev) static void rpmsg_remove(struct virtio_device *vdev)
{ {
struct virtproc_info *vrp = vdev->priv; struct virtproc_info *vrp = vdev->priv;
size_t total_buf_space = vrp->num_bufs * RPMSG_BUF_SIZE;
int ret; int ret;
vdev->config->reset(vdev); vdev->config->reset(vdev);
...@@ -1057,8 +1073,8 @@ static void rpmsg_remove(struct virtio_device *vdev) ...@@ -1057,8 +1073,8 @@ static void rpmsg_remove(struct virtio_device *vdev)
vdev->config->del_vqs(vrp->vdev); vdev->config->del_vqs(vrp->vdev);
dma_free_coherent(vdev->dev.parent->parent, RPMSG_TOTAL_BUF_SPACE, dma_free_coherent(vdev->dev.parent->parent, total_buf_space,
vrp->rbufs, vrp->bufs_dma); vrp->rbufs, vrp->bufs_dma);
kfree(vrp); kfree(vrp);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment