diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 4a9671eb14e..95be70c9934 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -25,11 +25,6 @@ config DEV_RPMSG_SERVER default n depends on RPTUN -config DEV_RPMSG_NPOLLWAITERS - int "RPMSG Device Max Number of Poll Threads" - default 4 - depends on DEV_RPMSG_SERVER - config DRVR_MKRD bool "RAM disk wrapper (mkrd)" default n diff --git a/drivers/misc/rpmsgdev.c b/drivers/misc/rpmsgdev.c index 75b0bc112dd..9b4536301c2 100644 --- a/drivers/misc/rpmsgdev.c +++ b/drivers/misc/rpmsgdev.c @@ -54,6 +54,11 @@ * Private Types ****************************************************************************/ +struct rpmsgdev_priv_s +{ + uint64_t filep; /* store server file pointer */ +}; + struct rpmsgdev_s { struct rpmsg_endpoint ept; /* Rpmsg endpoint */ @@ -63,10 +68,6 @@ struct rpmsgdev_s * opreation until the connection * between two cpu established. */ - mutex_t excl; /* Exclusive mutex, used to support thread - * safe. - */ - int open_count; /* Device open count */ }; /* Rpmsg device cookie used to handle the response from the remote cpu */ @@ -188,6 +189,7 @@ const struct file_operations g_rpmsgdev_ops = static int rpmsgdev_open(FAR struct file *filep) { FAR struct rpmsgdev_s *dev; + FAR struct rpmsgdev_priv_s *priv; struct rpmsgdev_open_s msg; int ret; @@ -202,33 +204,30 @@ static int rpmsgdev_open(FAR struct file *filep) dev = filep->f_inode->i_private; DEBUGASSERT(dev != NULL); - /* Take the semaphore */ + priv = (FAR struct rpmsgdev_priv_s *)kmm_zalloc(sizeof(*priv)); + if (priv == NULL) + { + return -ENOMEM; + } - ret = nxmutex_lock(&dev->excl); + /* Try to open the device in the remote cpu */ + + msg.flags = filep->f_oflags; + ret = rpmsgdev_send_recv(dev, RPMSGDEV_OPEN, true, &msg.header, + sizeof(msg), NULL); if (ret < 0) { - rpmsgdeverr("semtake error, ret=%d\n", ret); + rpmsgdeverr("open failed, ret=%d\n", ret); + kmm_free(priv); return ret; } - /* Check if this is the first time that the driver has been opened. */ + priv->filep = msg.filep; - if (dev->open_count++ == 0) - { - /* Try to open the file in the host file system */ + /* Attach the private date to the struct file instance */ - msg.flags = filep->f_oflags; + filep->f_priv = priv; - ret = rpmsgdev_send_recv(dev, RPMSGDEV_OPEN, true, &msg.header, - sizeof(msg), NULL); - if (ret < 0) - { - rpmsgdeverr("open failed\n"); - dev->open_count--; - } - } - - nxmutex_unlock(&dev->excl); return ret; } @@ -249,6 +248,7 @@ static int rpmsgdev_open(FAR struct file *filep) static int rpmsgdev_close(FAR struct file *filep) { FAR struct rpmsgdev_s *dev; + FAR struct rpmsgdev_priv_s *priv; struct rpmsgdev_close_s msg; int ret; @@ -258,30 +258,24 @@ static int rpmsgdev_close(FAR struct file *filep) /* Recover our private data from the struct file instance */ - dev = filep->f_inode->i_private; - DEBUGASSERT(dev != NULL); + dev = filep->f_inode->i_private; + priv = filep->f_priv; + DEBUGASSERT(dev != NULL && priv != NULL); - /* Take the semaphore */ + /* Try to close the device in the remote cpu */ - ret = nxmutex_lock(&dev->excl); + msg.filep = priv->filep; + ret = rpmsgdev_send_recv(dev, RPMSGDEV_CLOSE, true, &msg.header, + sizeof(msg), NULL); if (ret < 0) { + rpmsgdeverr("close failed, ret=%d\n", ret); return ret; } - /* There are no more references to the port */ + filep->f_priv = NULL; + kmm_free(priv); - if (--dev->open_count == 0) - { - ret = rpmsgdev_send_recv(dev, RPMSGDEV_CLOSE, true, &msg.header, - sizeof(msg), NULL); - if (ret < 0) - { - dev->open_count++; - } - } - - nxmutex_unlock(&dev->excl); return ret; } @@ -306,6 +300,7 @@ static ssize_t rpmsgdev_read(FAR struct file *filep, FAR char *buffer, size_t buflen) { FAR struct rpmsgdev_s *dev; + FAR struct rpmsgdev_priv_s *priv; struct rpmsgdev_read_s msg; struct iovec read; ssize_t ret; @@ -321,29 +316,21 @@ static ssize_t rpmsgdev_read(FAR struct file *filep, FAR char *buffer, /* Recover our private data from the struct file instance */ - dev = filep->f_inode->i_private; - DEBUGASSERT(dev != NULL); - - /* Take the semaphore */ - - ret = nxmutex_lock(&dev->excl); - if (ret < 0) - { - return ret; - } + dev = filep->f_inode->i_private; + priv = filep->f_priv; + DEBUGASSERT(dev != NULL && priv != NULL); /* Call the host to perform the read */ read.iov_base = buffer; read.iov_len = 0; + msg.filep = priv->filep; msg.count = buflen; ret = rpmsgdev_send_recv(dev, RPMSGDEV_READ, true, &msg.header, sizeof(msg) - 1, &read); - nxmutex_unlock(&dev->excl); - return read.iov_len ? read.iov_len : ret; } @@ -370,6 +357,7 @@ static ssize_t rpmsgdev_write(FAR struct file *filep, const char *buffer, size_t buflen) { FAR struct rpmsgdev_s *dev; + FAR struct rpmsgdev_priv_s *priv; FAR struct rpmsgdev_write_s *msg; struct rpmsgdev_cookie_s cookie; uint32_t space; @@ -385,16 +373,9 @@ static ssize_t rpmsgdev_write(FAR struct file *filep, const char *buffer, /* Recover our private data from the struct file instance */ - dev = filep->f_inode->i_private; - DEBUGASSERT(dev != NULL); - - /* Take the semaphore */ - - ret = nxmutex_lock(&dev->excl); - if (ret < 0) - { - return ret; - } + dev = filep->f_inode->i_private; + priv = filep->f_priv; + DEBUGASSERT(dev != NULL && priv != NULL); /* Perform the rpmsg write */ @@ -428,6 +409,7 @@ static ssize_t rpmsgdev_write(FAR struct file *filep, const char *buffer, msg->header.command = RPMSGDEV_WRITE; msg->header.result = -ENXIO; + msg->filep = priv->filep; msg->count = space; memcpy(msg->buf, buffer + written, space); @@ -450,8 +432,6 @@ static ssize_t rpmsgdev_write(FAR struct file *filep, const char *buffer, out: nxsem_destroy(&cookie.sem); - nxmutex_unlock(&dev->excl); - return ret < 0 ? ret : buflen; } @@ -475,8 +455,8 @@ out: static off_t rpmsgdev_seek(FAR struct file *filep, off_t offset, int whence) { FAR struct rpmsgdev_s *dev; + FAR struct rpmsgdev_priv_s *priv; struct rpmsgdev_lseek_s msg; - off_t ret; /* Sanity checks */ @@ -484,27 +464,18 @@ static off_t rpmsgdev_seek(FAR struct file *filep, off_t offset, int whence) /* Recover our private data from the struct file instance */ - dev = filep->f_inode->i_private; - DEBUGASSERT(dev != NULL); - - /* Take the semaphore */ - - ret = nxmutex_lock(&dev->excl); - if (ret < 0) - { - return ret; - } + dev = filep->f_inode->i_private; + priv = filep->f_priv; + DEBUGASSERT(dev != NULL && priv != NULL); /* Call our internal routine to perform the seek */ + msg.filep = priv->filep; msg.offset = offset; msg.whence = whence; - ret = rpmsgdev_send_recv(dev, RPMSGDEV_LSEEK, true, &msg.header, - sizeof(msg), NULL); - - nxmutex_unlock(&dev->excl); - return ret; + return rpmsgdev_send_recv(dev, RPMSGDEV_LSEEK, true, &msg.header, + sizeof(msg), NULL); } /**************************************************************************** @@ -557,11 +528,11 @@ static size_t rpmsgdev_ioctl_arglen(int cmd) static int rpmsgdev_ioctl(FAR struct file *filep, int cmd, unsigned long arg) { FAR struct rpmsgdev_s *dev; + FAR struct rpmsgdev_priv_s *priv; FAR struct rpmsgdev_ioctl_s *msg; uint32_t space; size_t arglen; size_t msglen; - int ret; /* Sanity checks */ @@ -569,16 +540,9 @@ static int rpmsgdev_ioctl(FAR struct file *filep, int cmd, unsigned long arg) /* Recover our private data from the struct file instance */ - dev = filep->f_inode->i_private; - DEBUGASSERT(dev != NULL); - - /* Take the semaphore */ - - ret = nxmutex_lock(&dev->excl); - if (ret < 0) - { - return ret; - } + dev = filep->f_inode->i_private; + priv = filep->f_priv; + DEBUGASSERT(dev != NULL && priv != NULL); /* Call our internal routine to perform the ioctl */ @@ -588,10 +552,10 @@ static int rpmsgdev_ioctl(FAR struct file *filep, int cmd, unsigned long arg) msg = rpmsgdev_get_tx_payload_buffer(dev, &space); if (msg == NULL) { - nxmutex_unlock(&dev->excl); return -ENOMEM; } + msg->filep = priv->filep; msg->request = cmd; msg->arg = arg; msg->arglen = arglen; @@ -601,11 +565,8 @@ static int rpmsgdev_ioctl(FAR struct file *filep, int cmd, unsigned long arg) memcpy(msg->buf, (FAR void *)(uintptr_t)arg, arglen); } - ret = rpmsgdev_send_recv(dev, RPMSGDEV_IOCTL, false, &msg->header, - msglen, arglen > 0 ? (FAR void *)arg : NULL); - - nxmutex_unlock(&dev->excl); - return ret; + return rpmsgdev_send_recv(dev, RPMSGDEV_IOCTL, false, &msg->header, + msglen, arglen > 0 ? (FAR void *)arg : NULL); } /**************************************************************************** @@ -628,8 +589,8 @@ static int rpmsgdev_poll(FAR struct file *filep, FAR struct pollfd *fds, bool setup) { FAR struct rpmsgdev_s *dev; + FAR struct rpmsgdev_priv_s *priv; struct rpmsgdev_poll_s msg; - int ret; /* Sanity checks */ @@ -637,32 +598,19 @@ static int rpmsgdev_poll(FAR struct file *filep, FAR struct pollfd *fds, /* Recover our private data from the struct file instance */ - dev = filep->f_inode->i_private; - DEBUGASSERT(dev != NULL); - - /* Take the semaphore */ - - ret = nxmutex_lock(&dev->excl); - if (ret < 0) - { - return ret; - } + dev = filep->f_inode->i_private; + priv = filep->f_priv; + DEBUGASSERT(dev != NULL && priv != NULL); /* Setup or teardown the poll */ - msg.events = fds->events; - msg.setup = setup; - msg.fds = (uint64_t)(uintptr_t)fds; + msg.filep = priv->filep; + msg.events = fds->events; + msg.setup = setup; + msg.fds = (uint64_t)(uintptr_t)fds; - ret = rpmsgdev_send_recv(dev, RPMSGDEV_POLL, true, &msg.header, - sizeof(msg), NULL); - if (ret < 0) - { - rpmsgdeverr("Send failed, ret=%d\n", ret); - } - - nxmutex_unlock(&dev->excl); - return ret; + return rpmsgdev_send_recv(dev, RPMSGDEV_POLL, true, &msg.header, + sizeof(msg), NULL); } /**************************************************************************** @@ -1085,8 +1033,6 @@ int rpmsgdev_register(FAR const char *remotecpu, FAR const char *remotepath, dev->remotecpu = remotecpu; dev->remotepath = remotepath; - nxmutex_init(&dev->excl); - nxsem_init(&dev->wait, 0, 0); nxsem_set_protocol(&dev->wait, SEM_PRIO_NONE); @@ -1127,7 +1073,6 @@ fail_with_rpmsg: NULL); fail: - nxmutex_destroy(&dev->excl); nxsem_destroy(&dev->wait); kmm_free(dev); diff --git a/drivers/misc/rpmsgdev.h b/drivers/misc/rpmsgdev.h index a92177f5ab9..2f3ae2a3068 100644 --- a/drivers/misc/rpmsgdev.h +++ b/drivers/misc/rpmsgdev.h @@ -61,17 +61,20 @@ begin_packed_struct struct rpmsgdev_header_s begin_packed_struct struct rpmsgdev_open_s { struct rpmsgdev_header_s header; + uint64_t filep; int32_t flags; } end_packed_struct; begin_packed_struct struct rpmsgdev_close_s { struct rpmsgdev_header_s header; + uint64_t filep; } end_packed_struct; begin_packed_struct struct rpmsgdev_read_s { struct rpmsgdev_header_s header; + uint64_t filep; uint32_t count; char buf[1]; } end_packed_struct; @@ -81,6 +84,7 @@ begin_packed_struct struct rpmsgdev_read_s begin_packed_struct struct rpmsgdev_lseek_s { struct rpmsgdev_header_s header; + uint64_t filep; int32_t whence; int32_t offset; } end_packed_struct; @@ -88,15 +92,17 @@ begin_packed_struct struct rpmsgdev_lseek_s begin_packed_struct struct rpmsgdev_ioctl_s { struct rpmsgdev_header_s header; - int32_t request; + uint64_t filep; uint64_t arg; uint32_t arglen; + int32_t request; char buf[1]; } end_packed_struct; begin_packed_struct struct rpmsgdev_poll_s { struct rpmsgdev_header_s header; + uint64_t filep; uint32_t events; uint32_t setup; uint64_t fds; diff --git a/drivers/misc/rpmsgdev_server.c b/drivers/misc/rpmsgdev_server.c index 20dc0590f83..0e5b214849c 100644 --- a/drivers/misc/rpmsgdev_server.c +++ b/drivers/misc/rpmsgdev_server.c @@ -28,7 +28,9 @@ #include #include +#include #include +#include #include #include #include @@ -43,12 +45,23 @@ * Private Types ****************************************************************************/ +struct rpmsgdev_device_s +{ + struct file file; /* The open file */ + struct pollfd fd; /* The poll fd */ + uint64_t cfd; /* The client poll fd pointer */ + struct list_node node; /* The double-linked list node */ +}; + struct rpmsgdev_server_s { - struct rpmsg_endpoint ept; - struct file file; - struct pollfd fds[CONFIG_DEV_RPMSG_NPOLLWAITERS]; - uint64_t cfds[CONFIG_DEV_RPMSG_NPOLLWAITERS]; + struct rpmsg_endpoint ept; /* Rpmsg end point */ + struct list_node head; /* The double-linked list head of opened + * devices + */ + mutex_t lock; /* The mutex used to protect the list + * operation + */ }; /**************************************************************************** @@ -122,11 +135,31 @@ static int rpmsgdev_open_handler(FAR struct rpmsg_endpoint *ept, { FAR struct rpmsgdev_server_s *server = ept->priv; FAR struct rpmsgdev_open_s *msg = data; + FAR struct rpmsgdev_device_s *dev; - msg->header.result = file_open(&server->file, + dev = kmm_zalloc(sizeof(*dev)); + if (dev == NULL) + { + msg->header.result = -ENOMEM; + goto out; + } + + msg->header.result = file_open(&dev->file, &ept->name[RPMSGDEV_NAME_PREFIX_LEN], msg->flags, 0); + if (msg->header.result < 0) + { + kmm_free(dev); + goto out; + } + msg->filep = (uint64_t)(uintptr_t)&dev->file; + + nxmutex_lock(&server->lock); + list_add_tail(&server->head, &dev->node); + nxmutex_unlock(&server->lock); + +out: return rpmsg_send(ept, msg, sizeof(*msg)); } @@ -140,8 +173,18 @@ static int rpmsgdev_close_handler(FAR struct rpmsg_endpoint *ept, { FAR struct rpmsgdev_server_s *server = ept->priv; FAR struct rpmsgdev_close_s *msg = data; + FAR struct rpmsgdev_device_s *dev = + (FAR struct rpmsgdev_device_s *)(uintptr_t)msg->filep; - msg->header.result = file_close(&server->file); + msg->header.result = file_close(&dev->file); + if (msg->header.result == 0) + { + nxmutex_lock(&server->lock); + list_delete(&dev->node); + nxmutex_unlock(&server->lock); + + kmm_free(dev); + } return rpmsg_send(ept, msg, sizeof(*msg)); } @@ -154,9 +197,9 @@ static int rpmsgdev_read_handler(FAR struct rpmsg_endpoint *ept, FAR void *data, size_t len, uint32_t src, FAR void *priv) { - FAR struct rpmsgdev_server_s *server = ept->priv; FAR struct rpmsgdev_read_s *msg = data; FAR struct rpmsgdev_read_s *rsp; + FAR struct file *filep = (FAR struct file *)(uintptr_t)msg->filep; int ret = -ENOENT; size_t read = 0; uint32_t space; @@ -177,7 +220,7 @@ static int rpmsgdev_read_handler(FAR struct rpmsg_endpoint *ept, space = msg->count - read; } - ret = file_read(&server->file, rsp->buf, space); + ret = file_read(filep, rsp->buf, space); rsp->header.result = ret; rpmsg_send_nocopy(ept, rsp, (ret < 0 ? 0 : ret) + sizeof(*rsp) - 1); @@ -200,14 +243,14 @@ static int rpmsgdev_write_handler(FAR struct rpmsg_endpoint *ept, FAR void *data, size_t len, uint32_t src, FAR void *priv) { - FAR struct rpmsgdev_server_s *server = ept->priv; FAR struct rpmsgdev_write_s *msg = data; + FAR struct file *filep = (FAR struct file *)(uintptr_t)msg->filep; size_t written = 0; int ret = -ENOENT; while (written < msg->count) { - ret = file_write(&server->file, msg->buf + written, + ret = file_write(filep, msg->buf + written, msg->count - written); if (ret <= 0) { @@ -234,10 +277,10 @@ static int rpmsgdev_lseek_handler(FAR struct rpmsg_endpoint *ept, FAR void *data, size_t len, uint32_t src, FAR void *priv) { - FAR struct rpmsgdev_server_s *server = ept->priv; FAR struct rpmsgdev_lseek_s *msg = data; + FAR struct file *filep = (FAR struct file *)(uintptr_t)msg->filep; - msg->header.result = file_seek(&server->file, msg->offset, msg->whence); + msg->header.result = file_seek(filep, msg->offset, msg->whence); return rpmsg_send(ept, msg, len); } @@ -250,10 +293,10 @@ static int rpmsgdev_ioctl_handler(FAR struct rpmsg_endpoint *ept, FAR void *data, size_t len, uint32_t src, FAR void *priv) { - FAR struct rpmsgdev_server_s *server = ept->priv; FAR struct rpmsgdev_ioctl_s *msg = data; + FAR struct file *filep = (FAR struct file *)(uintptr_t)msg->filep; - msg->header.result = file_ioctl(&server->file, msg->request, + msg->header.result = file_ioctl(filep, msg->request, msg->arglen > 0 ? (unsigned long)msg->buf : msg->arg); @@ -267,16 +310,15 @@ static int rpmsgdev_ioctl_handler(FAR struct rpmsg_endpoint *ept, static void rpmsgdev_poll_cb(FAR struct pollfd *fds) { FAR struct rpmsgdev_server_s *server = fds->arg; + FAR struct rpmsgdev_device_s *dev = + container_of(fds, FAR struct rpmsgdev_device_s, fd); FAR struct rpmsgdev_notify_s msg; - int tmp; - DEBUGASSERT(fds != NULL && (uintptr_t)fds >= (uintptr_t)server->fds); - - tmp = fds - server->fds; + DEBUGASSERT(fds != NULL && dev->cfd != 0); msg.header.command = RPMSGDEV_NOTIFY; msg.revents = fds->revents; - msg.fds = server->cfds[tmp]; + msg.fds = dev->cfd; fds->revents = 0; @@ -293,61 +335,34 @@ static int rpmsgdev_poll_handler(FAR struct rpmsg_endpoint *ept, { FAR struct rpmsgdev_server_s *server = ept->priv; FAR struct rpmsgdev_poll_s *msg = data; - FAR struct pollfd *fds = NULL; - int i; + FAR struct rpmsgdev_device_s *dev = + (FAR struct rpmsgdev_device_s *)(uintptr_t)msg->filep; DEBUGASSERT(msg->fds != 0); if (msg->setup) { - for (i = 0; i < CONFIG_DEV_RPMSG_NPOLLWAITERS; i++) - { - if (server->cfds[i] == 0) - { - server->cfds[i] = msg->fds; - break; - } - } + /* Do not allow double setup */ - if (i >= CONFIG_DEV_RPMSG_NPOLLWAITERS) - { - msg->header.result = -EBUSY; - goto out; - } + DEBUGASSERT(dev->cfd == 0); - fds = &server->fds[i]; - fds->events = msg->events; - fds->revents = 0; - fds->cb = rpmsgdev_poll_cb; - fds->arg = server; + dev->cfd = msg->fds; + dev->fd.events = msg->events; + dev->fd.revents = 0; + dev->fd.cb = rpmsgdev_poll_cb; + dev->fd.arg = server; - msg->header.result = file_poll(&server->file, fds, true); + msg->header.result = file_poll(&dev->file, &dev->fd, true); } else { - for (i = 0; i < CONFIG_DEV_RPMSG_NPOLLWAITERS; i++) - { - if (server->cfds[i] == msg->fds) - { - break; - } - } - - if (i >= CONFIG_DEV_RPMSG_NPOLLWAITERS) - { - msg->header.result = -EINVAL; - goto out; - } - - fds = &server->fds[i]; - msg->header.result = file_poll(&server->file, fds, false); + msg->header.result = file_poll(&dev->file, &dev->fd, false); if (msg->header.result == OK) { - server->cfds[i] = 0; + dev->cfd = 0; } } -out: return rpmsg_send(ept, msg, len); } @@ -379,6 +394,8 @@ static void rpmsgdev_ns_bind(FAR struct rpmsg_device *rdev, return; } + list_initialize(&server->head); + nxmutex_init(&server->lock); server->ept.priv = server; ret = rpmsg_create_ept(&server->ept, rdev, name, @@ -397,10 +414,31 @@ static void rpmsgdev_ns_bind(FAR struct rpmsg_device *rdev, static void rpmsgdev_ns_unbind(FAR struct rpmsg_endpoint *ept) { FAR struct rpmsgdev_server_s *server = ept->priv; + FAR struct rpmsgdev_device_s *dev; + FAR struct rpmsgdev_device_s *tmpdev; + + nxmutex_lock(&server->lock); + + list_for_every_entry_safe(&server->head, dev, tmpdev, + struct rpmsgdev_device_s, node) + { + if (dev->cfd != 0) + { + file_poll(&dev->file, &dev->fd, false); + } + + if (dev->file.f_inode != NULL) + { + file_close(&dev->file); + } + + list_delete(&dev->node); + kmm_free(dev); + } + + nxmutex_unlock(&server->lock); - file_close(&server->file); rpmsg_destroy_ept(&server->ept); - kmm_free(server); }