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