Commit 27cb8823 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'rpmsg-3.19-next' of git://git.kernel.org/pub/scm/linux/kernel/git/ohad/rpmsg

Pull rpmsg update from Ohad Ben-Cohen:
 "A single patch from Suman Anna which makes rpmsg use less buffers when
  small vrings are being used"

* tag 'rpmsg-3.19-next' of git://git.kernel.org/pub/scm/linux/kernel/git/ohad/rpmsg:
  rpmsg: use less buffers when vrings are small
parents 988adfdf b1b98914
...@@ -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