Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add sdb cpu coherency #2

Merged
merged 2 commits into from
Aug 3, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
175 changes: 115 additions & 60 deletions drivers/remoteproc/stm32_rpmsg_sdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <linux/eventfd.h>
#include <linux/of_platform.h>
#include <linux/list.h>
#include <asm/cacheflush.h>

#define RPMSG_SDB_DRIVER_VERSION "1.0"

Expand Down Expand Up @@ -50,17 +51,21 @@ struct rpmsg_sdb_ioctl_set_sync {
#define RPMSG_SDB_IOCTL_SET_EFD _IOW('R', 0x00, struct rpmsg_sdb_ioctl_set_efd *)
#define RPMSG_SDB_IOCTL_GET_DATA_SIZE _IOWR('R', 0x01, struct rpmsg_sdb_ioctl_get_data_size *)
#define RPMSG_SDB_IOCTL_GET_PHYS_ADDR _IOWR('R', 0x02, struct rpmsg_sdb_ioctl_get_phys_addr *)
#define RPMSG_SDB_IOCTL_SET_SYNC _IOW('R', 0x03, struct rpmsg_sdb_ioctl_set_sync *)
#define RPMSG_SDB_IOCTL_SET_SYNC_CPU _IOW('R', 0x03, struct rpmsg_sdb_ioctl_set_sync *)
#define RPMSG_SDB_IOCTL_SET_SYNC_DEV _IOW('R', 0x04, struct rpmsg_sdb_ioctl_set_sync *)
#define RPMSG_SDB_IOCTL_SET_CACHE_FLUSH _IOW('R', 0x05, struct rpmsg_sdb_ioctl_set_sync *)

struct sdb_buf_t {
int index; /* index of buffer */
size_t size; /* buffer size */
size_t writing_size; /* size of data written by copro */
dma_addr_t paddr; /* physical address*/
void *vaddr; /* virtual address */
void *uaddr; /* mapped address for userland */
void *uaddr_start; /* mapped address start for userland */
void *uaddr_end; /* mapped address end for userland */
struct eventfd_ctx *efd_ctx; /* eventfd context */
struct list_head buflist; /* reference in the buffers list */
struct vm_area_struct *vma;
};

struct rpmsg_sdb_t {
Expand All @@ -71,48 +76,50 @@ struct rpmsg_sdb_t {
};

struct device *rpmsg_sdb_dev;
//---------------------------------------------------------------------------------------------------
// Datum - for now disable the internal message channel. We may want this back when DMA is working
//---------------------------------------------------------------------------------------------------

static int rpmsg_sdb_format_txbuf_string(struct sdb_buf_t *buffer, char *bufinfo_str, size_t bufinfo_str_size)
{
return snprintf(bufinfo_str, bufinfo_str_size, "B%dA%08xL%08x", buffer->index, buffer->paddr, buffer->size);
}
// static int rpmsg_sdb_format_txbuf_string(struct sdb_buf_t *buffer, char *bufinfo_str, size_t bufinfo_str_size)
// {
// return snprintf(bufinfo_str, bufinfo_str_size, "B%dA%08xL%08x", buffer->index, buffer->paddr, buffer->size);
// }

static long rpmsg_sdb_decode_rxbuf_string(char *rxbuf_str, int *buffer_id, size_t *size)
{
int ret = 0;
char *sub_str;
long bsize;
long bufid;
const char delimiter[1] = {'L'};
// static long rpmsg_sdb_decode_rxbuf_string(char *rxbuf_str, int *buffer_id, size_t *size)
// {
// int ret = 0;
// char *sub_str;
// long bsize;
// long bufid;
// const char delimiter[1] = {'L'};

//pr_err("%s: rxbuf_str:%s\n", __func__, rxbuf_str);
// //pr_err("%s: rxbuf_str:%s\n", __func__, rxbuf_str);

/* Get first part containing the buffer id */
sub_str = strsep(&rxbuf_str, delimiter);
// /* Get first part containing the buffer id */
// sub_str = strsep(&rxbuf_str, delimiter);

//pr_err("%s: sub_str:%s\n", __func__, sub_str);
// //pr_err("%s: sub_str:%s\n", __func__, sub_str);

/* Save Buffer id and size: template BxLyyyyyyyy*/
ret = kstrtol(&sub_str[1], 10, &bufid);
if (ret < 0) {
pr_err("%s: extract of buffer id failed(%d)", __func__, ret);
goto out;
}
// /* Save Buffer id and size: template BxLyyyyyyyy*/
// ret = kstrtol(&sub_str[1], 10, &bufid);
// if (ret < 0) {
// pr_err("%s: extract of buffer id failed(%d)", __func__, ret);
// goto out;
// }

ret = kstrtol(&rxbuf_str[2], 16, &bsize);
if (ret < 0) {
pr_err("%s: extract of buffer size failed(%d)", __func__, ret);
goto out;
}
// ret = kstrtol(&rxbuf_str[2], 16, &bsize);
// if (ret < 0) {
// pr_err("%s: extract of buffer size failed(%d)", __func__, ret);
// goto out;
// }

*size = (size_t)bsize;
*buffer_id = (int)bufid;
// *size = (size_t)bsize;
// *buffer_id = (int)bufid;

out:
return ret;
}
// out:
// return ret;
// }

// Datum - for now disable the internal message channel. We may want this back when DMA is working
// static int rpmsg_sdb_send_buf_info(struct rpmsg_sdb_t *rpmsg_sdb, struct sdb_buf_t *buffer)
// {
// int count = 0, ret = 0;
Expand Down Expand Up @@ -182,7 +189,7 @@ static int rpmsg_sdb_mmap(struct file *file, struct vm_area_struct *vma)
_buffer = list_last_entry(&_rpmsg_sdb->buffer_list,
struct sdb_buf_t, buflist);

_buffer->uaddr = NULL;
_buffer->uaddr_start = NULL;
_buffer->size = NumPages * PAGE_SIZE;
_buffer->writing_size = -1;
//_buffer->vaddr = dma_alloc_wc(rpmsg_sdb_dev,
Expand All @@ -209,7 +216,9 @@ static int rpmsg_sdb_mmap(struct file *file, struct vm_area_struct *vma)
size, prot))
return -EAGAIN;

_buffer->uaddr = (void *)vma->vm_start;
_buffer->uaddr_start = (void *)vma->vm_start;
_buffer->uaddr_end = (void *)vma->vm_end;
_buffer->vma = vma;

/* Send information to remote proc */
rpmsg_sdb_send_buf_info(_rpmsg_sdb, _buffer);
Expand Down Expand Up @@ -325,15 +334,16 @@ static long rpmsg_sdb_ioctl(struct file *file, unsigned int cmd, unsigned long a
mutex_lock(&_rpmsg_sdb->mutex);

/* Get index from the last buffer in the list */
if (!list_empty(&_rpmsg_sdb->buffer_list)) {
if (!list_empty(&_rpmsg_sdb->buffer_list))
{
lastbuffer = list_last_entry(&_rpmsg_sdb->buffer_list, struct sdb_buf_t, buflist);
idx = lastbuffer->index;
/* increment this index for the next buffer creation*/
idx++;
}

if (copy_from_user(&q_set_efd, (struct rpmsg_sdb_ioctl_set_efd *)argp,
sizeof(struct rpmsg_sdb_ioctl_set_efd))) {
if (copy_from_user(&q_set_efd, (struct rpmsg_sdb_ioctl_set_efd *)argp, sizeof(struct rpmsg_sdb_ioctl_set_efd)))
{
pr_warn("rpmsg_sdb: RPMSG_SDB_IOCTL_GET_DATA_SIZE: copy to user failed.\n");
mutex_unlock(&_rpmsg_sdb->mutex);
return -EFAULT;
Expand All @@ -350,8 +360,8 @@ static long rpmsg_sdb_ioctl(struct file *file, unsigned int cmd, unsigned long a
break;

case RPMSG_SDB_IOCTL_GET_DATA_SIZE:
if (copy_from_user(&q_get_dat_size, (struct rpmsg_sdb_ioctl_get_data_size *)argp,
sizeof(struct rpmsg_sdb_ioctl_get_data_size))) {
if (copy_from_user(&q_get_dat_size, (struct rpmsg_sdb_ioctl_get_data_size *)argp, sizeof(struct rpmsg_sdb_ioctl_get_data_size)))
{
pr_warn("rpmsg_sdb: RPMSG_SDB_IOCTL_GET_DATA_SIZE: copy from user failed.\n");
return -EFAULT;
}
Expand All @@ -362,15 +372,16 @@ static long rpmsg_sdb_ioctl(struct file *file, unsigned int cmd, unsigned long a
list_for_each(pos, &_rpmsg_sdb->buffer_list)
{
datastructureptr = list_entry(pos, struct sdb_buf_t, buflist);
if (datastructureptr->index == idx) {
if (datastructureptr->index == idx)
{
/* Get the writing size*/
q_get_dat_size.size = datastructureptr->writing_size;
break;
}
}

if (copy_to_user((struct rpmsg_sdb_ioctl_get_data_size *)argp, &q_get_dat_size,
sizeof(struct rpmsg_sdb_ioctl_get_data_size))) {
if (copy_to_user((struct rpmsg_sdb_ioctl_get_data_size *)argp, &q_get_dat_size, sizeof(struct rpmsg_sdb_ioctl_get_data_size)))
{
pr_warn("rpmsg_sdb: RPMSG_SDB_IOCTL_GET_DATA_SIZE: copy to user failed.\n");
return -EFAULT;
}
Expand All @@ -380,8 +391,8 @@ static long rpmsg_sdb_ioctl(struct file *file, unsigned int cmd, unsigned long a
break;

case RPMSG_SDB_IOCTL_GET_PHYS_ADDR:
if (copy_from_user(&q_get_phys_addr, (struct rpmsg_sdb_ioctl_get_phys_addr *)argp,
sizeof(struct rpmsg_sdb_ioctl_get_phys_addr))) {
if (copy_from_user(&q_get_phys_addr, (struct rpmsg_sdb_ioctl_get_phys_addr *)argp, sizeof(struct rpmsg_sdb_ioctl_get_phys_addr)))
{
pr_warn("rpmsg_sdb: RPMSG_SDB_IOCTL_GET_PHYS_ADDR: copy from user failed.\n");
return -EFAULT;
}
Expand All @@ -392,25 +403,24 @@ static long rpmsg_sdb_ioctl(struct file *file, unsigned int cmd, unsigned long a
list_for_each(pos, &_rpmsg_sdb->buffer_list)
{
datastructureptr = list_entry(pos, struct sdb_buf_t, buflist);
if (datastructureptr->index == idx) {
if (datastructureptr->index == idx)
{
/* Get the physical address*/
q_get_phys_addr.paddr = (uint32_t)(datastructureptr->paddr);
break;
}
}
if (copy_to_user((struct rpmsg_sdb_ioctl_get_phys_addr *)argp, &q_get_phys_addr,
sizeof(struct rpmsg_sdb_ioctl_get_phys_addr))) {
if (copy_to_user((struct rpmsg_sdb_ioctl_get_phys_addr *)argp, &q_get_phys_addr, sizeof(struct rpmsg_sdb_ioctl_get_phys_addr)))
{
pr_warn("rpmsg_sdb: RPMSG_SDB_IOCTL_GET_PHYS_ADDR: copy to user failed.\n");
return -EFAULT;
}
break;

case RPMSG_SDB_IOCTL_SET_SYNC:
mutex_lock(&_rpmsg_sdb->mutex);
if(copy_from_user(&q_set_sync, (struct rpmsg_sdb_ioctl_set_sync *)argp,
sizeof(struct rpmsg_sdb_ioctl_set_sync))) {
pr_warn("rpmsg_sdb: RPMSG_SDB_IOCTL_SYNC_BUF: copy from user failed.\n");
mutex_unlock(&_rpmsg_sdb->mutex);
case RPMSG_SDB_IOCTL_SET_SYNC_CPU:
if(copy_from_user(&q_set_sync, (struct rpmsg_sdb_ioctl_set_sync *)argp, sizeof(struct rpmsg_sdb_ioctl_set_sync)))
{
pr_warn("rpmsg_sdb: RPMSG_SDB_IOCTL_SYNC_CPU: copy from user failed.\n");
return -EFAULT;
}

Expand All @@ -420,15 +430,60 @@ static long rpmsg_sdb_ioctl(struct file *file, unsigned int cmd, unsigned long a
list_for_each(pos, &_rpmsg_sdb->buffer_list)
{
datastructureptr = list_entry(pos, struct sdb_buf_t, buflist);
if (datastructureptr->index == idx) {
if (datastructureptr->index == idx)
{
/* sync dcache for cpu access */
pr_debug("dma_sync_cpu: idx:%d, paddr:%x, vaddr:%p, writing_size:%d\n", idx, datastructureptr->paddr, datastructureptr->vaddr, datastructureptr->writing_size);
dma_sync_single_for_cpu(rpmsg_sdb_dev, datastructureptr->paddr, datastructureptr->size, DMA_BIDIRECTIONAL);
break;
}
}
break;

case RPMSG_SDB_IOCTL_SET_SYNC_DEV:
if(copy_from_user(&q_set_sync, (struct rpmsg_sdb_ioctl_set_sync *)argp, sizeof(struct rpmsg_sdb_ioctl_set_sync)))
{
pr_warn("rpmsg_sdb: RPMSG_SDB_IOCTL_SYNC_DEV: copy from user failed.\n");
return -EFAULT;
}

/* Get the index of the requested buffer and then look-up in the buffer list*/
idx = q_set_sync.bufferId;

list_for_each(pos, &_rpmsg_sdb->buffer_list)
{
datastructureptr = list_entry(pos, struct sdb_buf_t, buflist);
if (datastructureptr->index == idx)
{
/* sync dcache for device access */
pr_debug("dma_sync_dev: idx:%d, paddr:%x, vaddr:%p, writing_size:%d\n", idx, datastructureptr->paddr, datastructureptr->vaddr, datastructureptr->writing_size);
dma_sync_single_for_device(rpmsg_sdb_dev, datastructureptr->paddr, datastructureptr->size, DMA_BIDIRECTIONAL);
break;
}
}
break;

case RPMSG_SDB_IOCTL_SET_CACHE_FLUSH:
if(copy_from_user(&q_set_sync, (struct rpmsg_sdb_ioctl_set_sync *)argp, sizeof(struct rpmsg_sdb_ioctl_set_sync)))
{
pr_warn("rpmsg_sdb: RPMSG_SDB_IOCTL_SYNC_CPU: copy from user failed.\n");
return -EFAULT;
}

/* Get the index of the requested buffer and then look-up in the buffer list*/
idx = q_set_sync.bufferId;

list_for_each(pos, &_rpmsg_sdb->buffer_list)
{
datastructureptr = list_entry(pos, struct sdb_buf_t, buflist);
if (datastructureptr->index == idx)
{
/* force dcache sync */
pr_debug("dma_sync: idx:%d, paddr:%x, vaddr:%p, writing_size:%d\n", idx, datastructureptr->paddr, datastructureptr->vaddr, datastructureptr->writing_size);
dma_sync_single_for_device(rpmsg_sdb_dev, datastructureptr->paddr,
datastructureptr->size, DMA_BIDIRECTIONAL);
pr_debug("flush_cache_range: idx:%d, paddr:%x, vaddr:%p, writing_size:%d\n", idx, datastructureptr->paddr, datastructureptr->vaddr, datastructureptr->writing_size);
flush_cache_range(datastructureptr->vma, (unsigned long)datastructureptr->uaddr_start, (unsigned long)datastructureptr->uaddr_end);
break;
}
}
mutex_unlock(&_rpmsg_sdb->mutex);
break;

default:
Expand Down