You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by GitBox <gi...@apache.org> on 2022/09/08 12:50:57 UTC

[GitHub] [incubator-nuttx] CV-Bowen opened a new pull request, #7042: Add rpmsgmtd support

CV-Bowen opened a new pull request, #7042:
URL: https://github.com/apache/incubator-nuttx/pull/7042

   ## Summary
   1. move the find_mtddriver() to fs.h and add close_mtddriver() api, because the rpmsgmtd need  find_mtddriver() to get the mtd device according to the mtd device path, and need close_mtddriver() to release the inode;
   2. add rpmsgmtd support, the local cpu can access the remote cpu mtd device;
   
   ## Impact
   New feature, should be no impact
   
   ## Testing
   test with sim:rpserver and sim:rpproxy
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [incubator-nuttx] CV-Bowen commented on a diff in pull request #7042: Add rpmsgmtd support

Posted by GitBox <gi...@apache.org>.
CV-Bowen commented on code in PR #7042:
URL: https://github.com/apache/incubator-nuttx/pull/7042#discussion_r966048725


##########
drivers/mtd/Kconfig:
##########
@@ -345,6 +345,16 @@ config NULLMTD_ERASESTATE
 
 endif # NULLMTD
 
+config RPMSGMTD

Review Comment:
   Done



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [incubator-nuttx] xiaoxiang781216 commented on a diff in pull request #7042: Add rpmsgmtd support

Posted by GitBox <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #7042:
URL: https://github.com/apache/incubator-nuttx/pull/7042#discussion_r966620717


##########
drivers/mtd/Kconfig:
##########
@@ -345,6 +345,16 @@ config NULLMTD_ERASESTATE
 
 endif # NULLMTD
 
+config RPMSGMTD

Review Comment:
   Yes, BTW, since the file name is rpmsgmtd.c which is more consistent with RPMSGMTD.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [incubator-nuttx] CV-Bowen commented on a diff in pull request #7042: Add rpmsgmtd support

Posted by GitBox <gi...@apache.org>.
CV-Bowen commented on code in PR #7042:
URL: https://github.com/apache/incubator-nuttx/pull/7042#discussion_r966014725


##########
drivers/mtd/rpmsgmtd.c:
##########
@@ -0,0 +1,1135 @@
+/****************************************************************************
+ * drivers/mtd/rpmsgmtd.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <debug.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/mtd/mtd.h>
+#include <nuttx/mutex.h>
+#include <nuttx/rptun/openamp.h>
+
+#include "rpmsgmtd.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct rpmsgmtd_s
+{
+  struct mtd_dev_s      mtd;         /* MTD device */
+  struct rpmsg_endpoint ept;         /* Rpmsg endpoint */
+  FAR const char       *remotecpu;   /* The server cpu name */
+  FAR const char       *remotepath;  /* The device path in the server cpu */
+  sem_t                 wait;        /* Wait sem, used for preventing any
+                                      * opreation until the connection
+                                      * between two cpu established.
+                                      */
+  mutex_t               geoexcl;     /* Get mtd geometry operation mutex */
+  struct mtd_geometry_s geo;         /* MTD geomerty */
+};
+
+/* Rpmsg device cookie used to handle the response from the remote cpu */
+
+struct rpmsgmtd_cookie_s
+{
+  sem_t     sem;     /* Semaphore used fo rpmsg */
+  int       result;  /* The return value of the remote call */
+  FAR void *data;    /* The return data buffer of the remote call */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* The mtd operation functions */
+
+static int     rpmsgmtd_erase(FAR struct mtd_dev_s *dev, off_t startblock,
+                              size_t nblocks);
+static int     rpmsgmtd_get_geometry(FAR struct rpmsgmtd_s *dev);
+static ssize_t rpmsgmtd_bread(FAR struct mtd_dev_s *dev, off_t startblock,
+                              size_t nblocks, FAR uint8_t *buffer);
+static ssize_t rpmsgmtd_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
+                               size_t nblocks, FAR const uint8_t *buffer);
+static ssize_t rpmsgmtd_read(FAR struct mtd_dev_s *dev, off_t offset,
+                             size_t nbytes, FAR uint8_t *buffer);
+#ifdef CONFIG_MTD_BYTE_WRITE
+static ssize_t rpmsgmtd_write(FAR struct mtd_dev_s *dev, off_t offset,
+                              size_t nbytes, FAR const uint8_t *buffer);
+#endif
+static size_t  rpmsgmtd_ioctl_arglen(int cmd);
+static int     rpmsgmtd_ioctl(FAR struct mtd_dev_s *dev, int cmd,
+                              unsigned long arg);
+
+/* Functions for sending data to the remote cpu */
+
+static int     rpmsgmtd_send_recv(FAR struct rpmsgmtd_s *priv,
+                                  uint32_t command, bool copy,
+                                  FAR struct rpmsgmtd_header_s *msg,
+                                  int len, FAR void *data);
+static FAR void *rpmsgmtd_get_tx_payload_buffer(FAR struct rpmsgmtd_s *priv,
+                                                FAR uint32_t *len);
+
+/* Functions handle the responses from the remote cpu */
+
+static int     rpmsgmtd_default_handler(FAR struct rpmsg_endpoint *ept,
+                                        FAR void *data, size_t len,
+                                        uint32_t src, FAR void *priv);
+static int     rpmsgmtd_bread_handler(FAR struct rpmsg_endpoint *ept,
+                                      FAR void *data, size_t len,
+                                      uint32_t src, FAR void *priv);
+static int     rpmsgmtd_read_handler(FAR struct rpmsg_endpoint *ept,
+                                     FAR void *data, size_t len,
+                                     uint32_t src, FAR void *priv);
+static int     rpmsgmtd_ioctl_handler(FAR struct rpmsg_endpoint *ept,
+                                      FAR void *data, size_t len,
+                                      uint32_t src, FAR void *priv);
+
+/* Functions for creating communication with remote cpu */
+
+static void    rpmsgmtd_device_created(struct rpmsg_device *rdev,
+                                       FAR void *priv_);
+static void    rpmsgmtd_device_destroy(struct rpmsg_device *rdev,
+                                       FAR void *priv_);
+static int     rpmsgmtd_ept_cb(FAR struct rpmsg_endpoint *ept,
+                               FAR void *data, size_t len, uint32_t src,
+                               FAR void *priv);
+static void    rpmsgmtd_ns_bound(struct rpmsg_endpoint *ept);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* Rpmsg device response handler table */
+
+static const rpmsg_ept_cb g_rpmsgmtd_handler[] =
+{
+  [RPMSGMTD_ERASE]  = rpmsgmtd_default_handler,
+  [RPMSGMTD_BREAD]  = rpmsgmtd_bread_handler,
+  [RPMSGMTD_BWRITE] = rpmsgmtd_default_handler,
+  [RPMSGMTD_READ]   = rpmsgmtd_read_handler,
+  [RPMSGMTD_WRITE]  = rpmsgmtd_default_handler,
+  [RPMSGMTD_IOCTL]  = rpmsgmtd_ioctl_handler,
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: rpmsgmtd_erase
+ *
+ * Description:
+ *   Rpmsg-mtd erase operation
+ *
+ * Parameters:
+ *   dev        - the mtd device
+ *   startblock - erase start block
+ *   nblocks    - erase block number
+ *
+ * Returned Values:
+ *   OK on success; A negated errno value is returned on any failure.
+ *
+ ****************************************************************************/
+
+static int rpmsgmtd_erase(FAR struct mtd_dev_s *dev, off_t startblock,
+                          size_t nblocks)
+{
+  FAR struct rpmsgmtd_s *priv = (FAR struct rpmsgmtd_s *)dev;
+  struct rpmsgmtd_erase_s msg;
+  int ret;
+
+  /* Sanity checks */
+
+  DEBUGASSERT(priv != NULL);
+
+  msg.startblock = startblock;
+  msg.nblocks    = nblocks;
+  ret = rpmsgmtd_send_recv(priv, RPMSGMTD_ERASE, true, &msg.header,
+                           sizeof(msg), NULL);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: rpmsgmtd_get_geometry
+ *
+ * Description:
+ *   Rpmsg-mtd get the server mtd device geometry
+ *
+ * Parameters:
+ *   dev - the mtd device
+ *
+ * Returned Values:
+ *   OK on success; A negated errno value is returned on any failure.
+ *
+ ****************************************************************************/
+
+static int rpmsgmtd_get_geometry(FAR struct rpmsgmtd_s *dev)
+{
+  int ret;
+
+  ret = nxmutex_lock(&dev->geoexcl);
+  if (ret < 0)
+    {
+      ferr("ERROR: get geo excl mutex failed, ret=%d\n", ret);
+      return ret;
+    }
+
+  if (dev->geo.blocksize != 0)
+    {
+      /* MTD geometry has already got */
+
+      ret = OK;
+      goto out_with_mutex;
+    }
+
+  /* Get the server mtd device geometry */
+
+  ret = rpmsgmtd_ioctl(&dev->mtd, MTDIOC_GEOMETRY,
+                       (unsigned long)&dev->geo);
+  if (ret < 0)
+    {
+      ferr("ERROR: get geometry failed, ret=%d\n", ret);
+      goto out_with_mutex;
+    }
+
+out_with_mutex:
+  nxmutex_unlock(&dev->geoexcl);
+  return ret;
+}
+
+/****************************************************************************
+ * Name: rpmsgmtd_bread
+ *
+ * Description:
+ *   Rpmsg-mtd block read operation
+ *
+ * Parameters:
+ *   dev        - the mtd device
+ *   startblock - read start block
+ *   nblocks    - read block number
+ *   buffer     - read buffer
+ *
+ * Returned Values:
+ *   The positive non-zero number of blocks read on success, 0 on if an
+ *   end-of-file condition, or a negated errno value on any failure.
+ *
+ ****************************************************************************/
+
+static ssize_t rpmsgmtd_bread(FAR struct mtd_dev_s *dev, off_t startblock,
+                              size_t nblocks, FAR uint8_t *buffer)
+{
+  FAR struct rpmsgmtd_s *priv = (FAR struct rpmsgmtd_s *)dev;
+  struct rpmsgmtd_bread_s msg;
+  struct iovec iov;
+  int ret;
+
+  if (buffer == NULL)
+    {
+      return -EINVAL;
+    }
+
+  /* Sanity checks */
+
+  DEBUGASSERT(priv != NULL);
+
+  /* Get the server mtd geometry */
+
+  ret = rpmsgmtd_get_geometry(priv);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  /* In block read, iov_len represent the received block number */
+
+  iov.iov_base = buffer;
+  iov.iov_len  = 0;
+
+  msg.startblock = startblock;
+  msg.nblocks    = nblocks;
+  msg.blocksize  = priv->geo.blocksize;
+
+  ret = rpmsgmtd_send_recv(priv, RPMSGMTD_BREAD, true, &msg.header,
+                           sizeof(msg) - 1, &iov);
+
+  return ret < 0 ? ret : iov.iov_len;
+}
+
+/****************************************************************************
+ * Name: rpmsgmtd_bwrite
+ *
+ * Description:
+ *   Rpmsg-mtd block write operation
+ *
+ * Parameters:
+ *   dev        - the mtd device
+ *   startblock - write start block
+ *   nblocks    - write block number
+ *   buffer     - write buffer
+ *
+ * Returned Values:
+ *   On success, the number of blocks written are returned (zero indicates
+ *   nothing was written).  On any failure, a negated errno value is returned
+ *   (see comments withwrite() for a description of the appropriate errno
+ *   values).
+ *
+ ****************************************************************************/
+
+static ssize_t rpmsgmtd_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
+                               size_t nblocks, FAR const uint8_t *buffer)
+{
+  FAR struct rpmsgmtd_s *priv = (FAR struct rpmsgmtd_s *)dev;
+  FAR struct rpmsgmtd_bwrite_s *msg;
+  struct rpmsgmtd_cookie_s cookie;
+  uint32_t blocksize;
+  uint32_t space;
+  size_t written = 0;
+  int ret;
+
+  if (buffer == NULL)
+    {
+      return -EINVAL;
+    }
+
+  /* Sanity checks */
+
+  DEBUGASSERT(priv != NULL);
+
+  /* Get the server mtd geometry */
+
+  ret = rpmsgmtd_get_geometry(priv);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  /* Perform the rpmsg write */
+
+  memset(&cookie, 0, sizeof(cookie));
+  nxsem_init(&cookie.sem, 0, 0);
+  nxsem_set_protocol(&cookie.sem, SEM_PRIO_NONE);
+
+  blocksize = priv->geo.blocksize;
+  while (written < nblocks)
+    {
+      msg = rpmsgmtd_get_tx_payload_buffer(priv, &space);
+      if (msg == NULL)
+        {
+          ret = -ENOMEM;
+          goto out;
+        }
+
+      DEBUGASSERT(sizeof(*msg) - 1 + blocksize <= space);
+
+      msg->nblocks = (space - sizeof(*msg) + 1) / blocksize;
+      if (msg->nblocks >= nblocks - written)
+        {
+          /* Send complete, set cookie is valid, need ack */
+
+          msg->nblocks = nblocks - written;
+          msg->header.cookie = (uintptr_t)&cookie;
+        }
+      else
+        {
+          /* Not send complete, set cookie invalid, do not need ack */
+
+          msg->header.cookie = 0;
+        }
+
+      msg->header.command = RPMSGMTD_BWRITE;
+      msg->header.result  = -ENXIO;
+      msg->startblock     = startblock;
+      msg->blocksize      = blocksize;
+      memcpy(msg->buf, buffer, msg->nblocks * blocksize);
+
+      buffer     += msg->nblocks * blocksize;
+      startblock += msg->nblocks;
+      written    += msg->nblocks;
+
+      ret = rpmsg_send_nocopy(&priv->ept, msg,
+                              sizeof(*msg) - 1 + msg->nblocks * blocksize);
+      if (ret < 0)
+        {
+          goto out;
+        }
+    }
+
+  ret = rpmsg_wait(&priv->ept, &cookie.sem);
+  if (ret < 0)
+    {
+      goto out;
+    }
+
+  ret = cookie.result;
+
+out:
+  nxsem_destroy(&cookie.sem);
+  return ret < 0 ? ret : nblocks;
+}
+
+/****************************************************************************
+ * Name: rpmsgmtd_read
+ *
+ * Description:
+ *   Rpmsg-mtd read operation
+ *
+ * Parameters:
+ *   dev    - the mtd device
+ *   offset - read offset address in the mtd device
+ *   nbytes - read number in bytes
+ *   buffer - read buffer
+ *
+ * Returned Values:
+ *   The positive non-zero number of bytes read on success, 0 on if an
+ *   end-of-file condition, or a negated errno value on any failure.
+ *
+ ****************************************************************************/
+
+static ssize_t rpmsgmtd_read(FAR struct mtd_dev_s *dev, off_t offset,
+                             size_t nbytes, FAR uint8_t *buffer)
+{
+  FAR struct rpmsgmtd_s *priv = (FAR struct rpmsgmtd_s *)dev;
+  struct rpmsgmtd_read_s msg;
+  struct iovec iov;
+  ssize_t ret;
+
+  if (buffer == NULL)
+    {
+      return -EINVAL;
+    }
+
+  /* Sanity checks */
+
+  DEBUGASSERT(priv != NULL);
+
+  /* Call the host to perform the read */
+
+  iov.iov_base = buffer;
+  iov.iov_len  = 0;
+
+  msg.offset = offset;
+  msg.nbytes = nbytes;
+
+  ret = rpmsgmtd_send_recv(priv, RPMSGMTD_READ, true, &msg.header,
+                           sizeof(msg) - 1, &iov);
+
+  return ret < 0 ? ret : iov.iov_len;
+}
+
+/****************************************************************************
+ * Name: rpmsgmtd_write
+ *
+ * Description:
+ *   Rpmsg-mtd write operation
+ *
+ * Parameters:
+ *   dev    - the mtd device
+ *   offset - write offset address in the mtd device
+ *   nbytes - write number in bytes
+ *   buffer - write buffer
+ *
+ * Returned Values:
+ *   On success, the number of bytes written are returned (zero indicates
+ *   nothing was written).  On any failure, a negated errno value is returned
+ *   (see comments withwrite() for a description of the appropriate errno
+ *   values).
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_MTD_BYTE_WRITE
+static ssize_t rpmsgmtd_write(FAR struct mtd_dev_s *dev, off_t offset,
+                              size_t nbytes, FAR const uint8_t *buffer)
+{
+  FAR struct rpmsgmtd_s *priv = (FAR struct rpmsgmtd_s *)dev;
+  FAR struct rpmsgmtd_write_s *msg;
+  struct rpmsgmtd_cookie_s cookie;
+  uint32_t space;
+  size_t written = 0;
+  int ret;
+
+  if (buffer == NULL)
+    {
+      return -EINVAL;
+    }
+
+  /* Sanity checks */
+
+  DEBUGASSERT(priv != NULL);
+
+  /* Perform the rpmsg write */
+
+  memset(&cookie, 0, sizeof(cookie));
+  nxsem_init(&cookie.sem, 0, 0);
+  nxsem_set_protocol(&cookie.sem, SEM_PRIO_NONE);
+
+  while (written < nbytes)
+    {
+      msg = rpmsgmtd_get_tx_payload_buffer(priv, &space);
+      if (msg == NULL)
+        {
+          ret = -ENOMEM;
+          goto out;
+        }
+
+      space -= sizeof(*msg) - 1;
+      if (space >= nbytes - written)
+        {
+          /* Send complete, set cookie is valid, need ack */
+
+          space = nbytes - written;
+          msg->header.cookie = (uintptr_t)&cookie;
+        }
+      else
+        {
+          /* Not send complete, set cookie invalid, do not need ack */
+
+          msg->header.cookie = 0;
+        }
+
+      msg->header.command = RPMSGMTD_WRITE;
+      msg->header.result  = -ENXIO;
+      msg->offset         = offset;
+      msg->nbytes         = space;
+      memcpy(msg->buf, buffer, space);
+
+      ret = rpmsg_send_nocopy(&priv->ept, msg, sizeof(*msg) - 1 + space);
+      if (ret < 0)
+        {
+          goto out;
+        }
+
+      buffer  += space;
+      offset  += space;
+      written += space;
+    }
+
+  ret = rpmsg_wait(&priv->ept, &cookie.sem);
+  if (ret < 0)
+    {
+      goto out;
+    }
+
+  ret = cookie.result;
+
+out:
+  nxsem_destroy(&cookie.sem);
+  return ret < 0 ? ret : nbytes;
+}
+#endif
+
+/****************************************************************************
+ * Name: rpmsgmtd_ioctl_arglen
+ *
+ * Description:
+ *   Get rpmsg mtd ioctl argument length according to the command
+ *
+ * Parameters:
+ *   cmd - the ioctl command
+ *
+ * Returned Values:
+ *   0        - ioctl command not support
+ *   positive - the argument length
+ *
+ ****************************************************************************/
+
+static size_t rpmsgmtd_ioctl_arglen(int cmd)
+{
+  switch (cmd)
+    {
+      case MTDIOC_GEOMETRY:
+        return sizeof(struct mtd_geometry_s);
+      case MTDIOC_BULKERASE:
+        return 0;
+      case MTDIOC_PROTECT:
+      case MTDIOC_UNPROTECT:
+        return sizeof(struct mtd_protect_s);
+      default:
+        return 0;
+    }
+}
+
+/****************************************************************************
+ * Name: rpmsgmtd_ioctl
+ *
+ * Description:
+ *   Rpmsg-mtd ioctl operation
+ *
+ * Parameters:
+ *   dev - the mtd device
+ *   cmd - the ioctl command
+ *   arg - the ioctl arguments
+ *
+ * Returned Values:
+ *   OK on success; A negated errno value is returned on any failure.
+ *
+ ****************************************************************************/
+
+static int rpmsgmtd_ioctl(FAR struct mtd_dev_s *dev, int cmd,
+                          unsigned long arg)
+{
+  FAR struct rpmsgmtd_s *priv = (FAR struct rpmsgmtd_s *)dev;
+  FAR struct rpmsgmtd_ioctl_s *msg;
+  uint32_t space;
+  size_t arglen;
+  size_t msglen;
+  int ret;
+
+  /* Sanity checks */
+
+  DEBUGASSERT(priv != NULL);
+
+  /* Call our internal routine to perform the ioctl */
+
+  arglen = rpmsgmtd_ioctl_arglen(cmd);
+  msglen = sizeof(*msg) + arglen - 1;
+
+  msg = rpmsgmtd_get_tx_payload_buffer(priv, &space);
+  if (msg == NULL)
+    {
+      return -ENOMEM;
+    }
+
+  msg->request = cmd;
+  msg->arg     = arg;
+  msg->arglen  = arglen;
+
+  if (arglen > 0)
+    {
+      memcpy(msg->buf, (FAR void *)(uintptr_t)arg, arglen);
+    }
+
+  ret = rpmsgmtd_send_recv(priv, RPMSGMTD_IOCTL, false, &msg->header,

Review Comment:
   Done



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [incubator-nuttx] CV-Bowen commented on a diff in pull request #7042: Add rpmsgmtd support

Posted by GitBox <gi...@apache.org>.
CV-Bowen commented on code in PR #7042:
URL: https://github.com/apache/incubator-nuttx/pull/7042#discussion_r966014478


##########
drivers/mtd/rpmsgmtd.c:
##########
@@ -0,0 +1,1135 @@
+/****************************************************************************
+ * drivers/mtd/rpmsgmtd.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <debug.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/mtd/mtd.h>
+#include <nuttx/mutex.h>
+#include <nuttx/rptun/openamp.h>
+
+#include "rpmsgmtd.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct rpmsgmtd_s
+{
+  struct mtd_dev_s      mtd;         /* MTD device */
+  struct rpmsg_endpoint ept;         /* Rpmsg endpoint */
+  FAR const char       *remotecpu;   /* The server cpu name */
+  FAR const char       *remotepath;  /* The device path in the server cpu */
+  sem_t                 wait;        /* Wait sem, used for preventing any
+                                      * opreation until the connection
+                                      * between two cpu established.
+                                      */
+  mutex_t               geoexcl;     /* Get mtd geometry operation mutex */
+  struct mtd_geometry_s geo;         /* MTD geomerty */
+};
+
+/* Rpmsg device cookie used to handle the response from the remote cpu */
+
+struct rpmsgmtd_cookie_s
+{
+  sem_t     sem;     /* Semaphore used fo rpmsg */
+  int       result;  /* The return value of the remote call */
+  FAR void *data;    /* The return data buffer of the remote call */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* The mtd operation functions */
+
+static int     rpmsgmtd_erase(FAR struct mtd_dev_s *dev, off_t startblock,
+                              size_t nblocks);
+static int     rpmsgmtd_get_geometry(FAR struct rpmsgmtd_s *dev);
+static ssize_t rpmsgmtd_bread(FAR struct mtd_dev_s *dev, off_t startblock,
+                              size_t nblocks, FAR uint8_t *buffer);
+static ssize_t rpmsgmtd_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
+                               size_t nblocks, FAR const uint8_t *buffer);
+static ssize_t rpmsgmtd_read(FAR struct mtd_dev_s *dev, off_t offset,
+                             size_t nbytes, FAR uint8_t *buffer);
+#ifdef CONFIG_MTD_BYTE_WRITE
+static ssize_t rpmsgmtd_write(FAR struct mtd_dev_s *dev, off_t offset,
+                              size_t nbytes, FAR const uint8_t *buffer);
+#endif
+static size_t  rpmsgmtd_ioctl_arglen(int cmd);
+static int     rpmsgmtd_ioctl(FAR struct mtd_dev_s *dev, int cmd,
+                              unsigned long arg);
+
+/* Functions for sending data to the remote cpu */
+
+static int     rpmsgmtd_send_recv(FAR struct rpmsgmtd_s *priv,
+                                  uint32_t command, bool copy,
+                                  FAR struct rpmsgmtd_header_s *msg,
+                                  int len, FAR void *data);
+static FAR void *rpmsgmtd_get_tx_payload_buffer(FAR struct rpmsgmtd_s *priv,
+                                                FAR uint32_t *len);
+
+/* Functions handle the responses from the remote cpu */
+
+static int     rpmsgmtd_default_handler(FAR struct rpmsg_endpoint *ept,
+                                        FAR void *data, size_t len,
+                                        uint32_t src, FAR void *priv);
+static int     rpmsgmtd_bread_handler(FAR struct rpmsg_endpoint *ept,
+                                      FAR void *data, size_t len,
+                                      uint32_t src, FAR void *priv);
+static int     rpmsgmtd_read_handler(FAR struct rpmsg_endpoint *ept,
+                                     FAR void *data, size_t len,
+                                     uint32_t src, FAR void *priv);
+static int     rpmsgmtd_ioctl_handler(FAR struct rpmsg_endpoint *ept,
+                                      FAR void *data, size_t len,
+                                      uint32_t src, FAR void *priv);
+
+/* Functions for creating communication with remote cpu */
+
+static void    rpmsgmtd_device_created(struct rpmsg_device *rdev,
+                                       FAR void *priv_);
+static void    rpmsgmtd_device_destroy(struct rpmsg_device *rdev,
+                                       FAR void *priv_);
+static int     rpmsgmtd_ept_cb(FAR struct rpmsg_endpoint *ept,
+                               FAR void *data, size_t len, uint32_t src,
+                               FAR void *priv);
+static void    rpmsgmtd_ns_bound(struct rpmsg_endpoint *ept);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* Rpmsg device response handler table */
+
+static const rpmsg_ept_cb g_rpmsgmtd_handler[] =
+{
+  [RPMSGMTD_ERASE]  = rpmsgmtd_default_handler,
+  [RPMSGMTD_BREAD]  = rpmsgmtd_bread_handler,
+  [RPMSGMTD_BWRITE] = rpmsgmtd_default_handler,
+  [RPMSGMTD_READ]   = rpmsgmtd_read_handler,
+  [RPMSGMTD_WRITE]  = rpmsgmtd_default_handler,
+  [RPMSGMTD_IOCTL]  = rpmsgmtd_ioctl_handler,
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: rpmsgmtd_erase
+ *
+ * Description:
+ *   Rpmsg-mtd erase operation
+ *
+ * Parameters:
+ *   dev        - the mtd device
+ *   startblock - erase start block
+ *   nblocks    - erase block number
+ *
+ * Returned Values:
+ *   OK on success; A negated errno value is returned on any failure.
+ *
+ ****************************************************************************/
+
+static int rpmsgmtd_erase(FAR struct mtd_dev_s *dev, off_t startblock,
+                          size_t nblocks)
+{
+  FAR struct rpmsgmtd_s *priv = (FAR struct rpmsgmtd_s *)dev;
+  struct rpmsgmtd_erase_s msg;
+  int ret;
+
+  /* Sanity checks */
+
+  DEBUGASSERT(priv != NULL);
+
+  msg.startblock = startblock;
+  msg.nblocks    = nblocks;
+  ret = rpmsgmtd_send_recv(priv, RPMSGMTD_ERASE, true, &msg.header,

Review Comment:
   Done



##########
drivers/mtd/rpmsgmtd.c:
##########
@@ -0,0 +1,1135 @@
+/****************************************************************************
+ * drivers/mtd/rpmsgmtd.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <debug.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/mtd/mtd.h>
+#include <nuttx/mutex.h>
+#include <nuttx/rptun/openamp.h>
+
+#include "rpmsgmtd.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct rpmsgmtd_s
+{
+  struct mtd_dev_s      mtd;         /* MTD device */
+  struct rpmsg_endpoint ept;         /* Rpmsg endpoint */
+  FAR const char       *remotecpu;   /* The server cpu name */
+  FAR const char       *remotepath;  /* The device path in the server cpu */
+  sem_t                 wait;        /* Wait sem, used for preventing any
+                                      * opreation until the connection
+                                      * between two cpu established.
+                                      */
+  mutex_t               geoexcl;     /* Get mtd geometry operation mutex */
+  struct mtd_geometry_s geo;         /* MTD geomerty */
+};
+
+/* Rpmsg device cookie used to handle the response from the remote cpu */
+
+struct rpmsgmtd_cookie_s
+{
+  sem_t     sem;     /* Semaphore used fo rpmsg */
+  int       result;  /* The return value of the remote call */
+  FAR void *data;    /* The return data buffer of the remote call */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* The mtd operation functions */
+
+static int     rpmsgmtd_erase(FAR struct mtd_dev_s *dev, off_t startblock,
+                              size_t nblocks);
+static int     rpmsgmtd_get_geometry(FAR struct rpmsgmtd_s *dev);
+static ssize_t rpmsgmtd_bread(FAR struct mtd_dev_s *dev, off_t startblock,
+                              size_t nblocks, FAR uint8_t *buffer);
+static ssize_t rpmsgmtd_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
+                               size_t nblocks, FAR const uint8_t *buffer);
+static ssize_t rpmsgmtd_read(FAR struct mtd_dev_s *dev, off_t offset,
+                             size_t nbytes, FAR uint8_t *buffer);
+#ifdef CONFIG_MTD_BYTE_WRITE
+static ssize_t rpmsgmtd_write(FAR struct mtd_dev_s *dev, off_t offset,
+                              size_t nbytes, FAR const uint8_t *buffer);
+#endif
+static size_t  rpmsgmtd_ioctl_arglen(int cmd);
+static int     rpmsgmtd_ioctl(FAR struct mtd_dev_s *dev, int cmd,
+                              unsigned long arg);
+
+/* Functions for sending data to the remote cpu */
+
+static int     rpmsgmtd_send_recv(FAR struct rpmsgmtd_s *priv,
+                                  uint32_t command, bool copy,
+                                  FAR struct rpmsgmtd_header_s *msg,
+                                  int len, FAR void *data);
+static FAR void *rpmsgmtd_get_tx_payload_buffer(FAR struct rpmsgmtd_s *priv,
+                                                FAR uint32_t *len);
+
+/* Functions handle the responses from the remote cpu */
+
+static int     rpmsgmtd_default_handler(FAR struct rpmsg_endpoint *ept,
+                                        FAR void *data, size_t len,
+                                        uint32_t src, FAR void *priv);
+static int     rpmsgmtd_bread_handler(FAR struct rpmsg_endpoint *ept,
+                                      FAR void *data, size_t len,
+                                      uint32_t src, FAR void *priv);
+static int     rpmsgmtd_read_handler(FAR struct rpmsg_endpoint *ept,
+                                     FAR void *data, size_t len,
+                                     uint32_t src, FAR void *priv);
+static int     rpmsgmtd_ioctl_handler(FAR struct rpmsg_endpoint *ept,
+                                      FAR void *data, size_t len,
+                                      uint32_t src, FAR void *priv);
+
+/* Functions for creating communication with remote cpu */
+
+static void    rpmsgmtd_device_created(struct rpmsg_device *rdev,
+                                       FAR void *priv_);
+static void    rpmsgmtd_device_destroy(struct rpmsg_device *rdev,
+                                       FAR void *priv_);
+static int     rpmsgmtd_ept_cb(FAR struct rpmsg_endpoint *ept,
+                               FAR void *data, size_t len, uint32_t src,
+                               FAR void *priv);
+static void    rpmsgmtd_ns_bound(struct rpmsg_endpoint *ept);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* Rpmsg device response handler table */
+
+static const rpmsg_ept_cb g_rpmsgmtd_handler[] =
+{
+  [RPMSGMTD_ERASE]  = rpmsgmtd_default_handler,
+  [RPMSGMTD_BREAD]  = rpmsgmtd_bread_handler,
+  [RPMSGMTD_BWRITE] = rpmsgmtd_default_handler,
+  [RPMSGMTD_READ]   = rpmsgmtd_read_handler,
+  [RPMSGMTD_WRITE]  = rpmsgmtd_default_handler,
+  [RPMSGMTD_IOCTL]  = rpmsgmtd_ioctl_handler,
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: rpmsgmtd_erase
+ *
+ * Description:
+ *   Rpmsg-mtd erase operation
+ *
+ * Parameters:
+ *   dev        - the mtd device
+ *   startblock - erase start block
+ *   nblocks    - erase block number
+ *
+ * Returned Values:
+ *   OK on success; A negated errno value is returned on any failure.
+ *
+ ****************************************************************************/
+
+static int rpmsgmtd_erase(FAR struct mtd_dev_s *dev, off_t startblock,
+                          size_t nblocks)
+{
+  FAR struct rpmsgmtd_s *priv = (FAR struct rpmsgmtd_s *)dev;
+  struct rpmsgmtd_erase_s msg;
+  int ret;
+
+  /* Sanity checks */
+
+  DEBUGASSERT(priv != NULL);
+
+  msg.startblock = startblock;
+  msg.nblocks    = nblocks;
+  ret = rpmsgmtd_send_recv(priv, RPMSGMTD_ERASE, true, &msg.header,
+                           sizeof(msg), NULL);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: rpmsgmtd_get_geometry
+ *
+ * Description:
+ *   Rpmsg-mtd get the server mtd device geometry
+ *
+ * Parameters:
+ *   dev - the mtd device
+ *
+ * Returned Values:
+ *   OK on success; A negated errno value is returned on any failure.
+ *
+ ****************************************************************************/
+
+static int rpmsgmtd_get_geometry(FAR struct rpmsgmtd_s *dev)
+{
+  int ret;
+
+  ret = nxmutex_lock(&dev->geoexcl);
+  if (ret < 0)
+    {
+      ferr("ERROR: get geo excl mutex failed, ret=%d\n", ret);
+      return ret;
+    }
+
+  if (dev->geo.blocksize != 0)
+    {
+      /* MTD geometry has already got */
+
+      ret = OK;
+      goto out_with_mutex;
+    }
+
+  /* Get the server mtd device geometry */
+
+  ret = rpmsgmtd_ioctl(&dev->mtd, MTDIOC_GEOMETRY,
+                       (unsigned long)&dev->geo);
+  if (ret < 0)
+    {
+      ferr("ERROR: get geometry failed, ret=%d\n", ret);
+      goto out_with_mutex;
+    }
+
+out_with_mutex:
+  nxmutex_unlock(&dev->geoexcl);
+  return ret;
+}
+
+/****************************************************************************
+ * Name: rpmsgmtd_bread
+ *
+ * Description:
+ *   Rpmsg-mtd block read operation
+ *
+ * Parameters:
+ *   dev        - the mtd device
+ *   startblock - read start block
+ *   nblocks    - read block number
+ *   buffer     - read buffer
+ *
+ * Returned Values:
+ *   The positive non-zero number of blocks read on success, 0 on if an
+ *   end-of-file condition, or a negated errno value on any failure.
+ *
+ ****************************************************************************/
+
+static ssize_t rpmsgmtd_bread(FAR struct mtd_dev_s *dev, off_t startblock,
+                              size_t nblocks, FAR uint8_t *buffer)
+{
+  FAR struct rpmsgmtd_s *priv = (FAR struct rpmsgmtd_s *)dev;
+  struct rpmsgmtd_bread_s msg;
+  struct iovec iov;
+  int ret;
+
+  if (buffer == NULL)
+    {
+      return -EINVAL;
+    }
+
+  /* Sanity checks */
+
+  DEBUGASSERT(priv != NULL);
+
+  /* Get the server mtd geometry */
+
+  ret = rpmsgmtd_get_geometry(priv);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  /* In block read, iov_len represent the received block number */
+
+  iov.iov_base = buffer;
+  iov.iov_len  = 0;
+
+  msg.startblock = startblock;
+  msg.nblocks    = nblocks;
+  msg.blocksize  = priv->geo.blocksize;
+
+  ret = rpmsgmtd_send_recv(priv, RPMSGMTD_BREAD, true, &msg.header,
+                           sizeof(msg) - 1, &iov);
+
+  return ret < 0 ? ret : iov.iov_len;
+}
+
+/****************************************************************************
+ * Name: rpmsgmtd_bwrite
+ *
+ * Description:
+ *   Rpmsg-mtd block write operation
+ *
+ * Parameters:
+ *   dev        - the mtd device
+ *   startblock - write start block
+ *   nblocks    - write block number
+ *   buffer     - write buffer
+ *
+ * Returned Values:
+ *   On success, the number of blocks written are returned (zero indicates
+ *   nothing was written).  On any failure, a negated errno value is returned
+ *   (see comments withwrite() for a description of the appropriate errno
+ *   values).
+ *
+ ****************************************************************************/
+
+static ssize_t rpmsgmtd_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
+                               size_t nblocks, FAR const uint8_t *buffer)
+{
+  FAR struct rpmsgmtd_s *priv = (FAR struct rpmsgmtd_s *)dev;
+  FAR struct rpmsgmtd_bwrite_s *msg;
+  struct rpmsgmtd_cookie_s cookie;
+  uint32_t blocksize;
+  uint32_t space;
+  size_t written = 0;
+  int ret;
+
+  if (buffer == NULL)
+    {
+      return -EINVAL;
+    }
+
+  /* Sanity checks */
+
+  DEBUGASSERT(priv != NULL);
+
+  /* Get the server mtd geometry */
+
+  ret = rpmsgmtd_get_geometry(priv);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  /* Perform the rpmsg write */
+
+  memset(&cookie, 0, sizeof(cookie));
+  nxsem_init(&cookie.sem, 0, 0);
+  nxsem_set_protocol(&cookie.sem, SEM_PRIO_NONE);
+
+  blocksize = priv->geo.blocksize;
+  while (written < nblocks)
+    {
+      msg = rpmsgmtd_get_tx_payload_buffer(priv, &space);
+      if (msg == NULL)
+        {
+          ret = -ENOMEM;
+          goto out;
+        }
+
+      DEBUGASSERT(sizeof(*msg) - 1 + blocksize <= space);
+
+      msg->nblocks = (space - sizeof(*msg) + 1) / blocksize;
+      if (msg->nblocks >= nblocks - written)
+        {
+          /* Send complete, set cookie is valid, need ack */
+
+          msg->nblocks = nblocks - written;
+          msg->header.cookie = (uintptr_t)&cookie;
+        }
+      else
+        {
+          /* Not send complete, set cookie invalid, do not need ack */
+
+          msg->header.cookie = 0;
+        }
+
+      msg->header.command = RPMSGMTD_BWRITE;
+      msg->header.result  = -ENXIO;
+      msg->startblock     = startblock;
+      msg->blocksize      = blocksize;
+      memcpy(msg->buf, buffer, msg->nblocks * blocksize);
+
+      buffer     += msg->nblocks * blocksize;
+      startblock += msg->nblocks;
+      written    += msg->nblocks;
+
+      ret = rpmsg_send_nocopy(&priv->ept, msg,
+                              sizeof(*msg) - 1 + msg->nblocks * blocksize);
+      if (ret < 0)
+        {
+          goto out;
+        }
+    }
+
+  ret = rpmsg_wait(&priv->ept, &cookie.sem);
+  if (ret < 0)
+    {
+      goto out;
+    }
+
+  ret = cookie.result;
+
+out:
+  nxsem_destroy(&cookie.sem);
+  return ret < 0 ? ret : nblocks;
+}
+
+/****************************************************************************
+ * Name: rpmsgmtd_read
+ *
+ * Description:
+ *   Rpmsg-mtd read operation
+ *
+ * Parameters:
+ *   dev    - the mtd device
+ *   offset - read offset address in the mtd device
+ *   nbytes - read number in bytes
+ *   buffer - read buffer
+ *
+ * Returned Values:
+ *   The positive non-zero number of bytes read on success, 0 on if an
+ *   end-of-file condition, or a negated errno value on any failure.
+ *
+ ****************************************************************************/
+
+static ssize_t rpmsgmtd_read(FAR struct mtd_dev_s *dev, off_t offset,
+                             size_t nbytes, FAR uint8_t *buffer)
+{
+  FAR struct rpmsgmtd_s *priv = (FAR struct rpmsgmtd_s *)dev;
+  struct rpmsgmtd_read_s msg;
+  struct iovec iov;
+  ssize_t ret;
+
+  if (buffer == NULL)
+    {
+      return -EINVAL;
+    }
+
+  /* Sanity checks */
+
+  DEBUGASSERT(priv != NULL);
+
+  /* Call the host to perform the read */
+
+  iov.iov_base = buffer;
+  iov.iov_len  = 0;
+
+  msg.offset = offset;
+  msg.nbytes = nbytes;
+
+  ret = rpmsgmtd_send_recv(priv, RPMSGMTD_READ, true, &msg.header,
+                           sizeof(msg) - 1, &iov);
+
+  return ret < 0 ? ret : iov.iov_len;
+}
+
+/****************************************************************************
+ * Name: rpmsgmtd_write
+ *
+ * Description:
+ *   Rpmsg-mtd write operation
+ *
+ * Parameters:
+ *   dev    - the mtd device
+ *   offset - write offset address in the mtd device
+ *   nbytes - write number in bytes
+ *   buffer - write buffer
+ *
+ * Returned Values:
+ *   On success, the number of bytes written are returned (zero indicates
+ *   nothing was written).  On any failure, a negated errno value is returned
+ *   (see comments withwrite() for a description of the appropriate errno
+ *   values).
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_MTD_BYTE_WRITE
+static ssize_t rpmsgmtd_write(FAR struct mtd_dev_s *dev, off_t offset,
+                              size_t nbytes, FAR const uint8_t *buffer)
+{
+  FAR struct rpmsgmtd_s *priv = (FAR struct rpmsgmtd_s *)dev;
+  FAR struct rpmsgmtd_write_s *msg;
+  struct rpmsgmtd_cookie_s cookie;
+  uint32_t space;
+  size_t written = 0;
+  int ret;
+
+  if (buffer == NULL)
+    {
+      return -EINVAL;
+    }
+
+  /* Sanity checks */
+
+  DEBUGASSERT(priv != NULL);
+
+  /* Perform the rpmsg write */
+
+  memset(&cookie, 0, sizeof(cookie));
+  nxsem_init(&cookie.sem, 0, 0);
+  nxsem_set_protocol(&cookie.sem, SEM_PRIO_NONE);
+
+  while (written < nbytes)
+    {
+      msg = rpmsgmtd_get_tx_payload_buffer(priv, &space);
+      if (msg == NULL)
+        {
+          ret = -ENOMEM;
+          goto out;
+        }
+
+      space -= sizeof(*msg) - 1;
+      if (space >= nbytes - written)
+        {
+          /* Send complete, set cookie is valid, need ack */
+
+          space = nbytes - written;
+          msg->header.cookie = (uintptr_t)&cookie;
+        }
+      else
+        {
+          /* Not send complete, set cookie invalid, do not need ack */
+
+          msg->header.cookie = 0;
+        }
+
+      msg->header.command = RPMSGMTD_WRITE;
+      msg->header.result  = -ENXIO;
+      msg->offset         = offset;
+      msg->nbytes         = space;
+      memcpy(msg->buf, buffer, space);
+
+      ret = rpmsg_send_nocopy(&priv->ept, msg, sizeof(*msg) - 1 + space);
+      if (ret < 0)
+        {
+          goto out;
+        }
+
+      buffer  += space;
+      offset  += space;
+      written += space;
+    }
+
+  ret = rpmsg_wait(&priv->ept, &cookie.sem);
+  if (ret < 0)
+    {
+      goto out;
+    }
+
+  ret = cookie.result;
+
+out:
+  nxsem_destroy(&cookie.sem);
+  return ret < 0 ? ret : nbytes;
+}
+#endif
+
+/****************************************************************************
+ * Name: rpmsgmtd_ioctl_arglen
+ *
+ * Description:
+ *   Get rpmsg mtd ioctl argument length according to the command
+ *
+ * Parameters:
+ *   cmd - the ioctl command
+ *
+ * Returned Values:
+ *   0        - ioctl command not support
+ *   positive - the argument length
+ *
+ ****************************************************************************/
+
+static size_t rpmsgmtd_ioctl_arglen(int cmd)
+{
+  switch (cmd)
+    {
+      case MTDIOC_GEOMETRY:
+        return sizeof(struct mtd_geometry_s);
+      case MTDIOC_BULKERASE:

Review Comment:
   Done



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [incubator-nuttx] anchao commented on a diff in pull request #7042: Add rpmsgmtd support

Posted by GitBox <gi...@apache.org>.
anchao commented on code in PR #7042:
URL: https://github.com/apache/incubator-nuttx/pull/7042#discussion_r966034349


##########
drivers/mtd/rpmsgmtd.c:
##########
@@ -0,0 +1,1128 @@
+/****************************************************************************
+ * drivers/mtd/rpmsgmtd.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <debug.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/mtd/mtd.h>
+#include <nuttx/mutex.h>
+#include <nuttx/rptun/openamp.h>
+
+#include "rpmsgmtd.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct rpmsgmtd_s
+{
+  struct mtd_dev_s      mtd;         /* MTD device */
+  struct rpmsg_endpoint ept;         /* Rpmsg endpoint */
+  FAR const char       *remotecpu;   /* The server cpu name */
+  FAR const char       *remotepath;  /* The device path in the server cpu */
+  sem_t                 wait;        /* Wait sem, used for preventing any
+                                      * opreation until the connection
+                                      * between two cpu established.
+                                      */
+  mutex_t               geoexcl;     /* Get mtd geometry operation mutex */
+  struct mtd_geometry_s geo;         /* MTD geomerty */
+};
+
+/* Rpmsg device cookie used to handle the response from the remote cpu */
+
+struct rpmsgmtd_cookie_s
+{
+  sem_t     sem;     /* Semaphore used fo rpmsg */
+  int       result;  /* The return value of the remote call */
+  FAR void *data;    /* The return data buffer of the remote call */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* The mtd operation functions */
+
+static int     rpmsgmtd_erase(FAR struct mtd_dev_s *dev, off_t startblock,
+                              size_t nblocks);
+static int     rpmsgmtd_get_geometry(FAR struct rpmsgmtd_s *dev);
+static ssize_t rpmsgmtd_bread(FAR struct mtd_dev_s *dev, off_t startblock,
+                              size_t nblocks, FAR uint8_t *buffer);
+static ssize_t rpmsgmtd_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
+                               size_t nblocks, FAR const uint8_t *buffer);
+static ssize_t rpmsgmtd_read(FAR struct mtd_dev_s *dev, off_t offset,
+                             size_t nbytes, FAR uint8_t *buffer);
+#ifdef CONFIG_MTD_BYTE_WRITE
+static ssize_t rpmsgmtd_write(FAR struct mtd_dev_s *dev, off_t offset,
+                              size_t nbytes, FAR const uint8_t *buffer);
+#endif
+static size_t  rpmsgmtd_ioctl_arglen(int cmd);
+static int     rpmsgmtd_ioctl(FAR struct mtd_dev_s *dev, int cmd,
+                              unsigned long arg);
+
+/* Functions for sending data to the remote cpu */
+
+static int     rpmsgmtd_send_recv(FAR struct rpmsgmtd_s *priv,
+                                  uint32_t command, bool copy,
+                                  FAR struct rpmsgmtd_header_s *msg,
+                                  int len, FAR void *data);
+static FAR void *rpmsgmtd_get_tx_payload_buffer(FAR struct rpmsgmtd_s *priv,
+                                                FAR uint32_t *len);
+
+/* Functions handle the responses from the remote cpu */
+
+static int     rpmsgmtd_default_handler(FAR struct rpmsg_endpoint *ept,
+                                        FAR void *data, size_t len,
+                                        uint32_t src, FAR void *priv);
+static int     rpmsgmtd_bread_handler(FAR struct rpmsg_endpoint *ept,
+                                      FAR void *data, size_t len,
+                                      uint32_t src, FAR void *priv);
+static int     rpmsgmtd_read_handler(FAR struct rpmsg_endpoint *ept,
+                                     FAR void *data, size_t len,
+                                     uint32_t src, FAR void *priv);
+static int     rpmsgmtd_ioctl_handler(FAR struct rpmsg_endpoint *ept,
+                                      FAR void *data, size_t len,
+                                      uint32_t src, FAR void *priv);
+
+/* Functions for creating communication with remote cpu */
+
+static void    rpmsgmtd_device_created(struct rpmsg_device *rdev,
+                                       FAR void *priv_);
+static void    rpmsgmtd_device_destroy(struct rpmsg_device *rdev,
+                                       FAR void *priv_);
+static int     rpmsgmtd_ept_cb(FAR struct rpmsg_endpoint *ept,
+                               FAR void *data, size_t len, uint32_t src,
+                               FAR void *priv);
+static void    rpmsgmtd_ns_bound(struct rpmsg_endpoint *ept);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* Rpmsg device response handler table */
+
+static const rpmsg_ept_cb g_rpmsgmtd_handler[] =
+{
+  [RPMSGMTD_ERASE]  = rpmsgmtd_default_handler,
+  [RPMSGMTD_BREAD]  = rpmsgmtd_bread_handler,
+  [RPMSGMTD_BWRITE] = rpmsgmtd_default_handler,
+  [RPMSGMTD_READ]   = rpmsgmtd_read_handler,
+  [RPMSGMTD_WRITE]  = rpmsgmtd_default_handler,
+  [RPMSGMTD_IOCTL]  = rpmsgmtd_ioctl_handler,
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: rpmsgmtd_erase
+ *
+ * Description:
+ *   Rpmsg-mtd erase operation
+ *
+ * Parameters:
+ *   dev        - the mtd device
+ *   startblock - erase start block
+ *   nblocks    - erase block number
+ *
+ * Returned Values:
+ *   OK on success; A negated errno value is returned on any failure.
+ *
+ ****************************************************************************/
+
+static int rpmsgmtd_erase(FAR struct mtd_dev_s *dev, off_t startblock,
+                          size_t nblocks)
+{
+  FAR struct rpmsgmtd_s *priv = (FAR struct rpmsgmtd_s *)dev;
+  struct rpmsgmtd_erase_s msg;
+
+  /* Sanity checks */
+
+  DEBUGASSERT(priv != NULL);
+
+  msg.startblock = startblock;
+  msg.nblocks    = nblocks;
+
+  return rpmsgmtd_send_recv(priv, RPMSGMTD_ERASE, true, &msg.header,
+                            sizeof(msg), NULL);
+}
+
+/****************************************************************************
+ * Name: rpmsgmtd_get_geometry
+ *
+ * Description:
+ *   Rpmsg-mtd get the server mtd device geometry
+ *
+ * Parameters:
+ *   dev - the mtd device
+ *
+ * Returned Values:
+ *   OK on success; A negated errno value is returned on any failure.
+ *
+ ****************************************************************************/
+
+static int rpmsgmtd_get_geometry(FAR struct rpmsgmtd_s *dev)

Review Comment:
   static int rpmsgmtd_get_geometry(FAR struct rpmsgmtd_s *dev)
   { 
     int ret;
       
     ret = nxmutex_lock(&dev->geoexcl);
     if (ret == OK && dev->geo.blocksize == 0)
       {
         /* Get the server mtd device geometry */
             
         ret = rpmsgmtd_ioctl(&dev->mtd, MTDIOC_GEOMETRY,
                              (unsigned long)&dev->geo);
       }
   
     nxmutex_unlock(&dev->geoexcl);
     return ret;
   }
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [incubator-nuttx] xiaoxiang781216 commented on a diff in pull request #7042: Add rpmsgmtd support

Posted by GitBox <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #7042:
URL: https://github.com/apache/incubator-nuttx/pull/7042#discussion_r966130447


##########
drivers/mtd/Kconfig:
##########
@@ -345,6 +345,16 @@ config NULLMTD_ERASESTATE
 
 endif # NULLMTD
 
+config RPMSGMTD

Review Comment:
   but the suggestion isdifferent from other similar config(e.g. NULLMTD, RAMMTD, FILEMTD).



##########
drivers/mtd/Kconfig:
##########
@@ -345,6 +345,16 @@ config NULLMTD_ERASESTATE
 
 endif # NULLMTD
 
+config RPMSGMTD

Review Comment:
   but the suggestion is different from other similar config(e.g. NULLMTD, RAMMTD, FILEMTD).



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [incubator-nuttx] CV-Bowen commented on a diff in pull request #7042: Add rpmsgmtd support

Posted by GitBox <gi...@apache.org>.
CV-Bowen commented on code in PR #7042:
URL: https://github.com/apache/incubator-nuttx/pull/7042#discussion_r966587439


##########
drivers/mtd/Kconfig:
##########
@@ -345,6 +345,16 @@ config NULLMTD_ERASESTATE
 
 endif # NULLMTD
 
+config RPMSGMTD

Review Comment:
   Both are good for me
   MTD_RPMSG: like MTD_PARTITION, implement an abstract layer upper on an exists mtd device, MTD_RPMSG implement an abstract layer upper on a remote mtd device;
   RPMSGMTD: like RAMMTD, an independent mtd device implementation.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [incubator-nuttx] anchao commented on a diff in pull request #7042: Add rpmsgmtd support

Posted by GitBox <gi...@apache.org>.
anchao commented on code in PR #7042:
URL: https://github.com/apache/incubator-nuttx/pull/7042#discussion_r966004633


##########
drivers/mtd/rpmsgmtd.c:
##########
@@ -0,0 +1,1135 @@
+/****************************************************************************
+ * drivers/mtd/rpmsgmtd.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <debug.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/mtd/mtd.h>
+#include <nuttx/mutex.h>
+#include <nuttx/rptun/openamp.h>
+
+#include "rpmsgmtd.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct rpmsgmtd_s
+{
+  struct mtd_dev_s      mtd;         /* MTD device */
+  struct rpmsg_endpoint ept;         /* Rpmsg endpoint */
+  FAR const char       *remotecpu;   /* The server cpu name */
+  FAR const char       *remotepath;  /* The device path in the server cpu */
+  sem_t                 wait;        /* Wait sem, used for preventing any
+                                      * opreation until the connection
+                                      * between two cpu established.
+                                      */
+  mutex_t               geoexcl;     /* Get mtd geometry operation mutex */
+  struct mtd_geometry_s geo;         /* MTD geomerty */
+};
+
+/* Rpmsg device cookie used to handle the response from the remote cpu */
+
+struct rpmsgmtd_cookie_s
+{
+  sem_t     sem;     /* Semaphore used fo rpmsg */
+  int       result;  /* The return value of the remote call */
+  FAR void *data;    /* The return data buffer of the remote call */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* The mtd operation functions */
+
+static int     rpmsgmtd_erase(FAR struct mtd_dev_s *dev, off_t startblock,
+                              size_t nblocks);
+static int     rpmsgmtd_get_geometry(FAR struct rpmsgmtd_s *dev);
+static ssize_t rpmsgmtd_bread(FAR struct mtd_dev_s *dev, off_t startblock,
+                              size_t nblocks, FAR uint8_t *buffer);
+static ssize_t rpmsgmtd_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
+                               size_t nblocks, FAR const uint8_t *buffer);
+static ssize_t rpmsgmtd_read(FAR struct mtd_dev_s *dev, off_t offset,
+                             size_t nbytes, FAR uint8_t *buffer);
+#ifdef CONFIG_MTD_BYTE_WRITE
+static ssize_t rpmsgmtd_write(FAR struct mtd_dev_s *dev, off_t offset,
+                              size_t nbytes, FAR const uint8_t *buffer);
+#endif
+static size_t  rpmsgmtd_ioctl_arglen(int cmd);
+static int     rpmsgmtd_ioctl(FAR struct mtd_dev_s *dev, int cmd,
+                              unsigned long arg);
+
+/* Functions for sending data to the remote cpu */
+
+static int     rpmsgmtd_send_recv(FAR struct rpmsgmtd_s *priv,
+                                  uint32_t command, bool copy,
+                                  FAR struct rpmsgmtd_header_s *msg,
+                                  int len, FAR void *data);
+static FAR void *rpmsgmtd_get_tx_payload_buffer(FAR struct rpmsgmtd_s *priv,
+                                                FAR uint32_t *len);
+
+/* Functions handle the responses from the remote cpu */
+
+static int     rpmsgmtd_default_handler(FAR struct rpmsg_endpoint *ept,
+                                        FAR void *data, size_t len,
+                                        uint32_t src, FAR void *priv);
+static int     rpmsgmtd_bread_handler(FAR struct rpmsg_endpoint *ept,
+                                      FAR void *data, size_t len,
+                                      uint32_t src, FAR void *priv);
+static int     rpmsgmtd_read_handler(FAR struct rpmsg_endpoint *ept,
+                                     FAR void *data, size_t len,
+                                     uint32_t src, FAR void *priv);
+static int     rpmsgmtd_ioctl_handler(FAR struct rpmsg_endpoint *ept,
+                                      FAR void *data, size_t len,
+                                      uint32_t src, FAR void *priv);
+
+/* Functions for creating communication with remote cpu */
+
+static void    rpmsgmtd_device_created(struct rpmsg_device *rdev,
+                                       FAR void *priv_);
+static void    rpmsgmtd_device_destroy(struct rpmsg_device *rdev,
+                                       FAR void *priv_);
+static int     rpmsgmtd_ept_cb(FAR struct rpmsg_endpoint *ept,
+                               FAR void *data, size_t len, uint32_t src,
+                               FAR void *priv);
+static void    rpmsgmtd_ns_bound(struct rpmsg_endpoint *ept);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* Rpmsg device response handler table */
+
+static const rpmsg_ept_cb g_rpmsgmtd_handler[] =
+{
+  [RPMSGMTD_ERASE]  = rpmsgmtd_default_handler,
+  [RPMSGMTD_BREAD]  = rpmsgmtd_bread_handler,
+  [RPMSGMTD_BWRITE] = rpmsgmtd_default_handler,
+  [RPMSGMTD_READ]   = rpmsgmtd_read_handler,
+  [RPMSGMTD_WRITE]  = rpmsgmtd_default_handler,
+  [RPMSGMTD_IOCTL]  = rpmsgmtd_ioctl_handler,
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: rpmsgmtd_erase
+ *
+ * Description:
+ *   Rpmsg-mtd erase operation
+ *
+ * Parameters:
+ *   dev        - the mtd device
+ *   startblock - erase start block
+ *   nblocks    - erase block number
+ *
+ * Returned Values:
+ *   OK on success; A negated errno value is returned on any failure.
+ *
+ ****************************************************************************/
+
+static int rpmsgmtd_erase(FAR struct mtd_dev_s *dev, off_t startblock,
+                          size_t nblocks)
+{
+  FAR struct rpmsgmtd_s *priv = (FAR struct rpmsgmtd_s *)dev;
+  struct rpmsgmtd_erase_s msg;
+  int ret;
+
+  /* Sanity checks */
+
+  DEBUGASSERT(priv != NULL);
+
+  msg.startblock = startblock;
+  msg.nblocks    = nblocks;
+  ret = rpmsgmtd_send_recv(priv, RPMSGMTD_ERASE, true, &msg.header,
+                           sizeof(msg), NULL);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: rpmsgmtd_get_geometry
+ *
+ * Description:
+ *   Rpmsg-mtd get the server mtd device geometry
+ *
+ * Parameters:
+ *   dev - the mtd device
+ *
+ * Returned Values:
+ *   OK on success; A negated errno value is returned on any failure.
+ *
+ ****************************************************************************/
+
+static int rpmsgmtd_get_geometry(FAR struct rpmsgmtd_s *dev)
+{
+  int ret;
+
+  ret = nxmutex_lock(&dev->geoexcl);
+  if (ret < 0)
+    {
+      ferr("ERROR: get geo excl mutex failed, ret=%d\n", ret);
+      return ret;
+    }
+
+  if (dev->geo.blocksize != 0)
+    {
+      /* MTD geometry has already got */
+
+      ret = OK;
+      goto out_with_mutex;
+    }
+
+  /* Get the server mtd device geometry */
+
+  ret = rpmsgmtd_ioctl(&dev->mtd, MTDIOC_GEOMETRY,
+                       (unsigned long)&dev->geo);
+  if (ret < 0)
+    {
+      ferr("ERROR: get geometry failed, ret=%d\n", ret);
+      goto out_with_mutex;
+    }
+
+out_with_mutex:
+  nxmutex_unlock(&dev->geoexcl);
+  return ret;
+}
+
+/****************************************************************************
+ * Name: rpmsgmtd_bread
+ *
+ * Description:
+ *   Rpmsg-mtd block read operation
+ *
+ * Parameters:
+ *   dev        - the mtd device
+ *   startblock - read start block
+ *   nblocks    - read block number
+ *   buffer     - read buffer
+ *
+ * Returned Values:
+ *   The positive non-zero number of blocks read on success, 0 on if an
+ *   end-of-file condition, or a negated errno value on any failure.
+ *
+ ****************************************************************************/
+
+static ssize_t rpmsgmtd_bread(FAR struct mtd_dev_s *dev, off_t startblock,
+                              size_t nblocks, FAR uint8_t *buffer)
+{
+  FAR struct rpmsgmtd_s *priv = (FAR struct rpmsgmtd_s *)dev;
+  struct rpmsgmtd_bread_s msg;
+  struct iovec iov;
+  int ret;
+
+  if (buffer == NULL)
+    {
+      return -EINVAL;
+    }
+
+  /* Sanity checks */
+
+  DEBUGASSERT(priv != NULL);
+
+  /* Get the server mtd geometry */
+
+  ret = rpmsgmtd_get_geometry(priv);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  /* In block read, iov_len represent the received block number */
+
+  iov.iov_base = buffer;
+  iov.iov_len  = 0;
+
+  msg.startblock = startblock;
+  msg.nblocks    = nblocks;
+  msg.blocksize  = priv->geo.blocksize;
+
+  ret = rpmsgmtd_send_recv(priv, RPMSGMTD_BREAD, true, &msg.header,
+                           sizeof(msg) - 1, &iov);
+
+  return ret < 0 ? ret : iov.iov_len;
+}
+
+/****************************************************************************
+ * Name: rpmsgmtd_bwrite
+ *
+ * Description:
+ *   Rpmsg-mtd block write operation
+ *
+ * Parameters:
+ *   dev        - the mtd device
+ *   startblock - write start block
+ *   nblocks    - write block number
+ *   buffer     - write buffer
+ *
+ * Returned Values:
+ *   On success, the number of blocks written are returned (zero indicates
+ *   nothing was written).  On any failure, a negated errno value is returned
+ *   (see comments withwrite() for a description of the appropriate errno
+ *   values).
+ *
+ ****************************************************************************/
+
+static ssize_t rpmsgmtd_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
+                               size_t nblocks, FAR const uint8_t *buffer)
+{
+  FAR struct rpmsgmtd_s *priv = (FAR struct rpmsgmtd_s *)dev;
+  FAR struct rpmsgmtd_bwrite_s *msg;
+  struct rpmsgmtd_cookie_s cookie;
+  uint32_t blocksize;
+  uint32_t space;
+  size_t written = 0;
+  int ret;
+
+  if (buffer == NULL)
+    {
+      return -EINVAL;
+    }
+
+  /* Sanity checks */
+
+  DEBUGASSERT(priv != NULL);
+
+  /* Get the server mtd geometry */
+
+  ret = rpmsgmtd_get_geometry(priv);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  /* Perform the rpmsg write */
+
+  memset(&cookie, 0, sizeof(cookie));
+  nxsem_init(&cookie.sem, 0, 0);
+  nxsem_set_protocol(&cookie.sem, SEM_PRIO_NONE);
+
+  blocksize = priv->geo.blocksize;
+  while (written < nblocks)
+    {
+      msg = rpmsgmtd_get_tx_payload_buffer(priv, &space);
+      if (msg == NULL)
+        {
+          ret = -ENOMEM;
+          goto out;
+        }
+
+      DEBUGASSERT(sizeof(*msg) - 1 + blocksize <= space);
+
+      msg->nblocks = (space - sizeof(*msg) + 1) / blocksize;
+      if (msg->nblocks >= nblocks - written)
+        {
+          /* Send complete, set cookie is valid, need ack */
+
+          msg->nblocks = nblocks - written;
+          msg->header.cookie = (uintptr_t)&cookie;
+        }
+      else
+        {
+          /* Not send complete, set cookie invalid, do not need ack */
+
+          msg->header.cookie = 0;
+        }
+
+      msg->header.command = RPMSGMTD_BWRITE;
+      msg->header.result  = -ENXIO;
+      msg->startblock     = startblock;
+      msg->blocksize      = blocksize;
+      memcpy(msg->buf, buffer, msg->nblocks * blocksize);
+
+      buffer     += msg->nblocks * blocksize;
+      startblock += msg->nblocks;
+      written    += msg->nblocks;
+
+      ret = rpmsg_send_nocopy(&priv->ept, msg,
+                              sizeof(*msg) - 1 + msg->nblocks * blocksize);
+      if (ret < 0)
+        {
+          goto out;
+        }
+    }
+
+  ret = rpmsg_wait(&priv->ept, &cookie.sem);
+  if (ret < 0)
+    {
+      goto out;
+    }
+
+  ret = cookie.result;
+
+out:
+  nxsem_destroy(&cookie.sem);
+  return ret < 0 ? ret : nblocks;
+}
+
+/****************************************************************************
+ * Name: rpmsgmtd_read
+ *
+ * Description:
+ *   Rpmsg-mtd read operation
+ *
+ * Parameters:
+ *   dev    - the mtd device
+ *   offset - read offset address in the mtd device
+ *   nbytes - read number in bytes
+ *   buffer - read buffer
+ *
+ * Returned Values:
+ *   The positive non-zero number of bytes read on success, 0 on if an
+ *   end-of-file condition, or a negated errno value on any failure.
+ *
+ ****************************************************************************/
+
+static ssize_t rpmsgmtd_read(FAR struct mtd_dev_s *dev, off_t offset,
+                             size_t nbytes, FAR uint8_t *buffer)
+{
+  FAR struct rpmsgmtd_s *priv = (FAR struct rpmsgmtd_s *)dev;
+  struct rpmsgmtd_read_s msg;
+  struct iovec iov;
+  ssize_t ret;
+
+  if (buffer == NULL)
+    {
+      return -EINVAL;
+    }
+
+  /* Sanity checks */
+
+  DEBUGASSERT(priv != NULL);
+
+  /* Call the host to perform the read */
+
+  iov.iov_base = buffer;
+  iov.iov_len  = 0;
+
+  msg.offset = offset;
+  msg.nbytes = nbytes;
+
+  ret = rpmsgmtd_send_recv(priv, RPMSGMTD_READ, true, &msg.header,
+                           sizeof(msg) - 1, &iov);
+
+  return ret < 0 ? ret : iov.iov_len;
+}
+
+/****************************************************************************
+ * Name: rpmsgmtd_write
+ *
+ * Description:
+ *   Rpmsg-mtd write operation
+ *
+ * Parameters:
+ *   dev    - the mtd device
+ *   offset - write offset address in the mtd device
+ *   nbytes - write number in bytes
+ *   buffer - write buffer
+ *
+ * Returned Values:
+ *   On success, the number of bytes written are returned (zero indicates
+ *   nothing was written).  On any failure, a negated errno value is returned
+ *   (see comments withwrite() for a description of the appropriate errno
+ *   values).
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_MTD_BYTE_WRITE
+static ssize_t rpmsgmtd_write(FAR struct mtd_dev_s *dev, off_t offset,
+                              size_t nbytes, FAR const uint8_t *buffer)
+{
+  FAR struct rpmsgmtd_s *priv = (FAR struct rpmsgmtd_s *)dev;
+  FAR struct rpmsgmtd_write_s *msg;
+  struct rpmsgmtd_cookie_s cookie;
+  uint32_t space;
+  size_t written = 0;
+  int ret;
+
+  if (buffer == NULL)
+    {
+      return -EINVAL;
+    }
+
+  /* Sanity checks */
+
+  DEBUGASSERT(priv != NULL);
+
+  /* Perform the rpmsg write */
+
+  memset(&cookie, 0, sizeof(cookie));
+  nxsem_init(&cookie.sem, 0, 0);
+  nxsem_set_protocol(&cookie.sem, SEM_PRIO_NONE);
+
+  while (written < nbytes)
+    {
+      msg = rpmsgmtd_get_tx_payload_buffer(priv, &space);
+      if (msg == NULL)
+        {
+          ret = -ENOMEM;
+          goto out;
+        }
+
+      space -= sizeof(*msg) - 1;
+      if (space >= nbytes - written)
+        {
+          /* Send complete, set cookie is valid, need ack */
+
+          space = nbytes - written;
+          msg->header.cookie = (uintptr_t)&cookie;
+        }
+      else
+        {
+          /* Not send complete, set cookie invalid, do not need ack */
+
+          msg->header.cookie = 0;
+        }
+
+      msg->header.command = RPMSGMTD_WRITE;
+      msg->header.result  = -ENXIO;
+      msg->offset         = offset;
+      msg->nbytes         = space;
+      memcpy(msg->buf, buffer, space);
+
+      ret = rpmsg_send_nocopy(&priv->ept, msg, sizeof(*msg) - 1 + space);
+      if (ret < 0)
+        {
+          goto out;
+        }
+
+      buffer  += space;
+      offset  += space;
+      written += space;
+    }
+
+  ret = rpmsg_wait(&priv->ept, &cookie.sem);
+  if (ret < 0)
+    {
+      goto out;
+    }
+
+  ret = cookie.result;
+
+out:
+  nxsem_destroy(&cookie.sem);
+  return ret < 0 ? ret : nbytes;
+}
+#endif
+
+/****************************************************************************
+ * Name: rpmsgmtd_ioctl_arglen
+ *
+ * Description:
+ *   Get rpmsg mtd ioctl argument length according to the command
+ *
+ * Parameters:
+ *   cmd - the ioctl command
+ *
+ * Returned Values:
+ *   0        - ioctl command not support
+ *   positive - the argument length
+ *
+ ****************************************************************************/
+
+static size_t rpmsgmtd_ioctl_arglen(int cmd)
+{
+  switch (cmd)
+    {
+      case MTDIOC_GEOMETRY:
+        return sizeof(struct mtd_geometry_s);
+      case MTDIOC_BULKERASE:
+        return 0;
+      case MTDIOC_PROTECT:
+      case MTDIOC_UNPROTECT:
+        return sizeof(struct mtd_protect_s);
+      default:
+        return 0;
+    }
+}
+
+/****************************************************************************
+ * Name: rpmsgmtd_ioctl
+ *
+ * Description:
+ *   Rpmsg-mtd ioctl operation
+ *
+ * Parameters:
+ *   dev - the mtd device
+ *   cmd - the ioctl command
+ *   arg - the ioctl arguments
+ *
+ * Returned Values:
+ *   OK on success; A negated errno value is returned on any failure.
+ *
+ ****************************************************************************/
+
+static int rpmsgmtd_ioctl(FAR struct mtd_dev_s *dev, int cmd,
+                          unsigned long arg)
+{
+  FAR struct rpmsgmtd_s *priv = (FAR struct rpmsgmtd_s *)dev;
+  FAR struct rpmsgmtd_ioctl_s *msg;
+  uint32_t space;
+  size_t arglen;
+  size_t msglen;
+  int ret;
+
+  /* Sanity checks */
+
+  DEBUGASSERT(priv != NULL);
+
+  /* Call our internal routine to perform the ioctl */
+
+  arglen = rpmsgmtd_ioctl_arglen(cmd);
+  msglen = sizeof(*msg) + arglen - 1;
+
+  msg = rpmsgmtd_get_tx_payload_buffer(priv, &space);
+  if (msg == NULL)
+    {
+      return -ENOMEM;
+    }
+
+  msg->request = cmd;
+  msg->arg     = arg;
+  msg->arglen  = arglen;
+
+  if (arglen > 0)
+    {
+      memcpy(msg->buf, (FAR void *)(uintptr_t)arg, arglen);
+    }
+
+  ret = rpmsgmtd_send_recv(priv, RPMSGMTD_IOCTL, false, &msg->header,

Review Comment:
   remove ret



##########
drivers/mtd/Kconfig:
##########
@@ -345,6 +345,16 @@ config NULLMTD_ERASESTATE
 
 endif # NULLMTD
 
+config RPMSGMTD

Review Comment:
   MTD_RPMSG ?



##########
drivers/mtd/rpmsgmtd.c:
##########
@@ -0,0 +1,1135 @@
+/****************************************************************************
+ * drivers/mtd/rpmsgmtd.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <debug.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/mtd/mtd.h>
+#include <nuttx/mutex.h>
+#include <nuttx/rptun/openamp.h>
+
+#include "rpmsgmtd.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct rpmsgmtd_s
+{
+  struct mtd_dev_s      mtd;         /* MTD device */
+  struct rpmsg_endpoint ept;         /* Rpmsg endpoint */
+  FAR const char       *remotecpu;   /* The server cpu name */
+  FAR const char       *remotepath;  /* The device path in the server cpu */
+  sem_t                 wait;        /* Wait sem, used for preventing any
+                                      * opreation until the connection
+                                      * between two cpu established.
+                                      */
+  mutex_t               geoexcl;     /* Get mtd geometry operation mutex */
+  struct mtd_geometry_s geo;         /* MTD geomerty */
+};
+
+/* Rpmsg device cookie used to handle the response from the remote cpu */
+
+struct rpmsgmtd_cookie_s
+{
+  sem_t     sem;     /* Semaphore used fo rpmsg */
+  int       result;  /* The return value of the remote call */
+  FAR void *data;    /* The return data buffer of the remote call */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* The mtd operation functions */
+
+static int     rpmsgmtd_erase(FAR struct mtd_dev_s *dev, off_t startblock,
+                              size_t nblocks);
+static int     rpmsgmtd_get_geometry(FAR struct rpmsgmtd_s *dev);
+static ssize_t rpmsgmtd_bread(FAR struct mtd_dev_s *dev, off_t startblock,
+                              size_t nblocks, FAR uint8_t *buffer);
+static ssize_t rpmsgmtd_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
+                               size_t nblocks, FAR const uint8_t *buffer);
+static ssize_t rpmsgmtd_read(FAR struct mtd_dev_s *dev, off_t offset,
+                             size_t nbytes, FAR uint8_t *buffer);
+#ifdef CONFIG_MTD_BYTE_WRITE
+static ssize_t rpmsgmtd_write(FAR struct mtd_dev_s *dev, off_t offset,
+                              size_t nbytes, FAR const uint8_t *buffer);
+#endif
+static size_t  rpmsgmtd_ioctl_arglen(int cmd);
+static int     rpmsgmtd_ioctl(FAR struct mtd_dev_s *dev, int cmd,
+                              unsigned long arg);
+
+/* Functions for sending data to the remote cpu */
+
+static int     rpmsgmtd_send_recv(FAR struct rpmsgmtd_s *priv,
+                                  uint32_t command, bool copy,
+                                  FAR struct rpmsgmtd_header_s *msg,
+                                  int len, FAR void *data);
+static FAR void *rpmsgmtd_get_tx_payload_buffer(FAR struct rpmsgmtd_s *priv,
+                                                FAR uint32_t *len);
+
+/* Functions handle the responses from the remote cpu */
+
+static int     rpmsgmtd_default_handler(FAR struct rpmsg_endpoint *ept,
+                                        FAR void *data, size_t len,
+                                        uint32_t src, FAR void *priv);
+static int     rpmsgmtd_bread_handler(FAR struct rpmsg_endpoint *ept,
+                                      FAR void *data, size_t len,
+                                      uint32_t src, FAR void *priv);
+static int     rpmsgmtd_read_handler(FAR struct rpmsg_endpoint *ept,
+                                     FAR void *data, size_t len,
+                                     uint32_t src, FAR void *priv);
+static int     rpmsgmtd_ioctl_handler(FAR struct rpmsg_endpoint *ept,
+                                      FAR void *data, size_t len,
+                                      uint32_t src, FAR void *priv);
+
+/* Functions for creating communication with remote cpu */
+
+static void    rpmsgmtd_device_created(struct rpmsg_device *rdev,
+                                       FAR void *priv_);
+static void    rpmsgmtd_device_destroy(struct rpmsg_device *rdev,
+                                       FAR void *priv_);
+static int     rpmsgmtd_ept_cb(FAR struct rpmsg_endpoint *ept,
+                               FAR void *data, size_t len, uint32_t src,
+                               FAR void *priv);
+static void    rpmsgmtd_ns_bound(struct rpmsg_endpoint *ept);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* Rpmsg device response handler table */
+
+static const rpmsg_ept_cb g_rpmsgmtd_handler[] =
+{
+  [RPMSGMTD_ERASE]  = rpmsgmtd_default_handler,
+  [RPMSGMTD_BREAD]  = rpmsgmtd_bread_handler,
+  [RPMSGMTD_BWRITE] = rpmsgmtd_default_handler,
+  [RPMSGMTD_READ]   = rpmsgmtd_read_handler,
+  [RPMSGMTD_WRITE]  = rpmsgmtd_default_handler,
+  [RPMSGMTD_IOCTL]  = rpmsgmtd_ioctl_handler,
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: rpmsgmtd_erase
+ *
+ * Description:
+ *   Rpmsg-mtd erase operation
+ *
+ * Parameters:
+ *   dev        - the mtd device
+ *   startblock - erase start block
+ *   nblocks    - erase block number
+ *
+ * Returned Values:
+ *   OK on success; A negated errno value is returned on any failure.
+ *
+ ****************************************************************************/
+
+static int rpmsgmtd_erase(FAR struct mtd_dev_s *dev, off_t startblock,
+                          size_t nblocks)
+{
+  FAR struct rpmsgmtd_s *priv = (FAR struct rpmsgmtd_s *)dev;
+  struct rpmsgmtd_erase_s msg;
+  int ret;
+
+  /* Sanity checks */
+
+  DEBUGASSERT(priv != NULL);
+
+  msg.startblock = startblock;
+  msg.nblocks    = nblocks;
+  ret = rpmsgmtd_send_recv(priv, RPMSGMTD_ERASE, true, &msg.header,
+                           sizeof(msg), NULL);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: rpmsgmtd_get_geometry
+ *
+ * Description:
+ *   Rpmsg-mtd get the server mtd device geometry
+ *
+ * Parameters:
+ *   dev - the mtd device
+ *
+ * Returned Values:
+ *   OK on success; A negated errno value is returned on any failure.
+ *
+ ****************************************************************************/
+
+static int rpmsgmtd_get_geometry(FAR struct rpmsgmtd_s *dev)
+{
+  int ret;
+
+  ret = nxmutex_lock(&dev->geoexcl);
+  if (ret < 0)
+    {
+      ferr("ERROR: get geo excl mutex failed, ret=%d\n", ret);
+      return ret;
+    }
+
+  if (dev->geo.blocksize != 0)
+    {
+      /* MTD geometry has already got */
+
+      ret = OK;
+      goto out_with_mutex;
+    }
+
+  /* Get the server mtd device geometry */
+
+  ret = rpmsgmtd_ioctl(&dev->mtd, MTDIOC_GEOMETRY,
+                       (unsigned long)&dev->geo);
+  if (ret < 0)
+    {
+      ferr("ERROR: get geometry failed, ret=%d\n", ret);
+      goto out_with_mutex;
+    }
+
+out_with_mutex:
+  nxmutex_unlock(&dev->geoexcl);
+  return ret;
+}
+
+/****************************************************************************
+ * Name: rpmsgmtd_bread
+ *
+ * Description:
+ *   Rpmsg-mtd block read operation
+ *
+ * Parameters:
+ *   dev        - the mtd device
+ *   startblock - read start block
+ *   nblocks    - read block number
+ *   buffer     - read buffer
+ *
+ * Returned Values:
+ *   The positive non-zero number of blocks read on success, 0 on if an
+ *   end-of-file condition, or a negated errno value on any failure.
+ *
+ ****************************************************************************/
+
+static ssize_t rpmsgmtd_bread(FAR struct mtd_dev_s *dev, off_t startblock,
+                              size_t nblocks, FAR uint8_t *buffer)
+{
+  FAR struct rpmsgmtd_s *priv = (FAR struct rpmsgmtd_s *)dev;
+  struct rpmsgmtd_bread_s msg;
+  struct iovec iov;
+  int ret;
+
+  if (buffer == NULL)
+    {
+      return -EINVAL;
+    }
+
+  /* Sanity checks */
+
+  DEBUGASSERT(priv != NULL);
+
+  /* Get the server mtd geometry */
+
+  ret = rpmsgmtd_get_geometry(priv);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  /* In block read, iov_len represent the received block number */
+
+  iov.iov_base = buffer;
+  iov.iov_len  = 0;
+
+  msg.startblock = startblock;
+  msg.nblocks    = nblocks;
+  msg.blocksize  = priv->geo.blocksize;
+
+  ret = rpmsgmtd_send_recv(priv, RPMSGMTD_BREAD, true, &msg.header,
+                           sizeof(msg) - 1, &iov);
+
+  return ret < 0 ? ret : iov.iov_len;
+}
+
+/****************************************************************************
+ * Name: rpmsgmtd_bwrite
+ *
+ * Description:
+ *   Rpmsg-mtd block write operation
+ *
+ * Parameters:
+ *   dev        - the mtd device
+ *   startblock - write start block
+ *   nblocks    - write block number
+ *   buffer     - write buffer
+ *
+ * Returned Values:
+ *   On success, the number of blocks written are returned (zero indicates
+ *   nothing was written).  On any failure, a negated errno value is returned
+ *   (see comments withwrite() for a description of the appropriate errno
+ *   values).
+ *
+ ****************************************************************************/
+
+static ssize_t rpmsgmtd_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
+                               size_t nblocks, FAR const uint8_t *buffer)
+{
+  FAR struct rpmsgmtd_s *priv = (FAR struct rpmsgmtd_s *)dev;
+  FAR struct rpmsgmtd_bwrite_s *msg;
+  struct rpmsgmtd_cookie_s cookie;
+  uint32_t blocksize;
+  uint32_t space;
+  size_t written = 0;
+  int ret;
+
+  if (buffer == NULL)
+    {
+      return -EINVAL;
+    }
+
+  /* Sanity checks */
+
+  DEBUGASSERT(priv != NULL);
+
+  /* Get the server mtd geometry */
+
+  ret = rpmsgmtd_get_geometry(priv);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  /* Perform the rpmsg write */
+
+  memset(&cookie, 0, sizeof(cookie));
+  nxsem_init(&cookie.sem, 0, 0);
+  nxsem_set_protocol(&cookie.sem, SEM_PRIO_NONE);
+
+  blocksize = priv->geo.blocksize;
+  while (written < nblocks)
+    {
+      msg = rpmsgmtd_get_tx_payload_buffer(priv, &space);
+      if (msg == NULL)
+        {
+          ret = -ENOMEM;
+          goto out;
+        }
+
+      DEBUGASSERT(sizeof(*msg) - 1 + blocksize <= space);
+
+      msg->nblocks = (space - sizeof(*msg) + 1) / blocksize;
+      if (msg->nblocks >= nblocks - written)
+        {
+          /* Send complete, set cookie is valid, need ack */
+
+          msg->nblocks = nblocks - written;
+          msg->header.cookie = (uintptr_t)&cookie;
+        }
+      else
+        {
+          /* Not send complete, set cookie invalid, do not need ack */
+
+          msg->header.cookie = 0;
+        }
+
+      msg->header.command = RPMSGMTD_BWRITE;
+      msg->header.result  = -ENXIO;
+      msg->startblock     = startblock;
+      msg->blocksize      = blocksize;
+      memcpy(msg->buf, buffer, msg->nblocks * blocksize);
+
+      buffer     += msg->nblocks * blocksize;
+      startblock += msg->nblocks;
+      written    += msg->nblocks;
+
+      ret = rpmsg_send_nocopy(&priv->ept, msg,
+                              sizeof(*msg) - 1 + msg->nblocks * blocksize);
+      if (ret < 0)
+        {
+          goto out;
+        }
+    }
+
+  ret = rpmsg_wait(&priv->ept, &cookie.sem);
+  if (ret < 0)
+    {
+      goto out;
+    }
+
+  ret = cookie.result;
+
+out:
+  nxsem_destroy(&cookie.sem);
+  return ret < 0 ? ret : nblocks;
+}
+
+/****************************************************************************
+ * Name: rpmsgmtd_read
+ *
+ * Description:
+ *   Rpmsg-mtd read operation
+ *
+ * Parameters:
+ *   dev    - the mtd device
+ *   offset - read offset address in the mtd device
+ *   nbytes - read number in bytes
+ *   buffer - read buffer
+ *
+ * Returned Values:
+ *   The positive non-zero number of bytes read on success, 0 on if an
+ *   end-of-file condition, or a negated errno value on any failure.
+ *
+ ****************************************************************************/
+
+static ssize_t rpmsgmtd_read(FAR struct mtd_dev_s *dev, off_t offset,
+                             size_t nbytes, FAR uint8_t *buffer)
+{
+  FAR struct rpmsgmtd_s *priv = (FAR struct rpmsgmtd_s *)dev;
+  struct rpmsgmtd_read_s msg;
+  struct iovec iov;
+  ssize_t ret;
+
+  if (buffer == NULL)
+    {
+      return -EINVAL;
+    }
+
+  /* Sanity checks */
+
+  DEBUGASSERT(priv != NULL);
+
+  /* Call the host to perform the read */
+
+  iov.iov_base = buffer;
+  iov.iov_len  = 0;
+
+  msg.offset = offset;
+  msg.nbytes = nbytes;
+
+  ret = rpmsgmtd_send_recv(priv, RPMSGMTD_READ, true, &msg.header,
+                           sizeof(msg) - 1, &iov);
+
+  return ret < 0 ? ret : iov.iov_len;
+}
+
+/****************************************************************************
+ * Name: rpmsgmtd_write
+ *
+ * Description:
+ *   Rpmsg-mtd write operation
+ *
+ * Parameters:
+ *   dev    - the mtd device
+ *   offset - write offset address in the mtd device
+ *   nbytes - write number in bytes
+ *   buffer - write buffer
+ *
+ * Returned Values:
+ *   On success, the number of bytes written are returned (zero indicates
+ *   nothing was written).  On any failure, a negated errno value is returned
+ *   (see comments withwrite() for a description of the appropriate errno
+ *   values).
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_MTD_BYTE_WRITE
+static ssize_t rpmsgmtd_write(FAR struct mtd_dev_s *dev, off_t offset,
+                              size_t nbytes, FAR const uint8_t *buffer)
+{
+  FAR struct rpmsgmtd_s *priv = (FAR struct rpmsgmtd_s *)dev;
+  FAR struct rpmsgmtd_write_s *msg;
+  struct rpmsgmtd_cookie_s cookie;
+  uint32_t space;
+  size_t written = 0;
+  int ret;
+
+  if (buffer == NULL)
+    {
+      return -EINVAL;
+    }
+
+  /* Sanity checks */
+
+  DEBUGASSERT(priv != NULL);
+
+  /* Perform the rpmsg write */
+
+  memset(&cookie, 0, sizeof(cookie));
+  nxsem_init(&cookie.sem, 0, 0);
+  nxsem_set_protocol(&cookie.sem, SEM_PRIO_NONE);
+
+  while (written < nbytes)
+    {
+      msg = rpmsgmtd_get_tx_payload_buffer(priv, &space);
+      if (msg == NULL)
+        {
+          ret = -ENOMEM;
+          goto out;
+        }
+
+      space -= sizeof(*msg) - 1;
+      if (space >= nbytes - written)
+        {
+          /* Send complete, set cookie is valid, need ack */
+
+          space = nbytes - written;
+          msg->header.cookie = (uintptr_t)&cookie;
+        }
+      else
+        {
+          /* Not send complete, set cookie invalid, do not need ack */
+
+          msg->header.cookie = 0;
+        }
+
+      msg->header.command = RPMSGMTD_WRITE;
+      msg->header.result  = -ENXIO;
+      msg->offset         = offset;
+      msg->nbytes         = space;
+      memcpy(msg->buf, buffer, space);
+
+      ret = rpmsg_send_nocopy(&priv->ept, msg, sizeof(*msg) - 1 + space);
+      if (ret < 0)
+        {
+          goto out;
+        }
+
+      buffer  += space;
+      offset  += space;
+      written += space;
+    }
+
+  ret = rpmsg_wait(&priv->ept, &cookie.sem);
+  if (ret < 0)
+    {
+      goto out;
+    }
+
+  ret = cookie.result;
+
+out:
+  nxsem_destroy(&cookie.sem);
+  return ret < 0 ? ret : nbytes;
+}
+#endif
+
+/****************************************************************************
+ * Name: rpmsgmtd_ioctl_arglen
+ *
+ * Description:
+ *   Get rpmsg mtd ioctl argument length according to the command
+ *
+ * Parameters:
+ *   cmd - the ioctl command
+ *
+ * Returned Values:
+ *   0        - ioctl command not support
+ *   positive - the argument length
+ *
+ ****************************************************************************/
+
+static size_t rpmsgmtd_ioctl_arglen(int cmd)
+{
+  switch (cmd)
+    {
+      case MTDIOC_GEOMETRY:
+        return sizeof(struct mtd_geometry_s);
+      case MTDIOC_BULKERASE:

Review Comment:
   remove



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [incubator-nuttx] CV-Bowen commented on a diff in pull request #7042: Add rpmsgmtd support

Posted by GitBox <gi...@apache.org>.
CV-Bowen commented on code in PR #7042:
URL: https://github.com/apache/incubator-nuttx/pull/7042#discussion_r966668463


##########
drivers/mtd/Kconfig:
##########
@@ -345,6 +345,16 @@ config NULLMTD_ERASESTATE
 
 endif # NULLMTD
 
+config RPMSGMTD

Review Comment:
   Done



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [incubator-nuttx] anchao commented on a diff in pull request #7042: Add rpmsgmtd support

Posted by GitBox <gi...@apache.org>.
anchao commented on code in PR #7042:
URL: https://github.com/apache/incubator-nuttx/pull/7042#discussion_r966003112


##########
drivers/mtd/rpmsgmtd.c:
##########
@@ -0,0 +1,1135 @@
+/****************************************************************************
+ * drivers/mtd/rpmsgmtd.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <debug.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/mtd/mtd.h>
+#include <nuttx/mutex.h>
+#include <nuttx/rptun/openamp.h>
+
+#include "rpmsgmtd.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct rpmsgmtd_s
+{
+  struct mtd_dev_s      mtd;         /* MTD device */
+  struct rpmsg_endpoint ept;         /* Rpmsg endpoint */
+  FAR const char       *remotecpu;   /* The server cpu name */
+  FAR const char       *remotepath;  /* The device path in the server cpu */
+  sem_t                 wait;        /* Wait sem, used for preventing any
+                                      * opreation until the connection
+                                      * between two cpu established.
+                                      */
+  mutex_t               geoexcl;     /* Get mtd geometry operation mutex */
+  struct mtd_geometry_s geo;         /* MTD geomerty */
+};
+
+/* Rpmsg device cookie used to handle the response from the remote cpu */
+
+struct rpmsgmtd_cookie_s
+{
+  sem_t     sem;     /* Semaphore used fo rpmsg */
+  int       result;  /* The return value of the remote call */
+  FAR void *data;    /* The return data buffer of the remote call */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* The mtd operation functions */
+
+static int     rpmsgmtd_erase(FAR struct mtd_dev_s *dev, off_t startblock,
+                              size_t nblocks);
+static int     rpmsgmtd_get_geometry(FAR struct rpmsgmtd_s *dev);
+static ssize_t rpmsgmtd_bread(FAR struct mtd_dev_s *dev, off_t startblock,
+                              size_t nblocks, FAR uint8_t *buffer);
+static ssize_t rpmsgmtd_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
+                               size_t nblocks, FAR const uint8_t *buffer);
+static ssize_t rpmsgmtd_read(FAR struct mtd_dev_s *dev, off_t offset,
+                             size_t nbytes, FAR uint8_t *buffer);
+#ifdef CONFIG_MTD_BYTE_WRITE
+static ssize_t rpmsgmtd_write(FAR struct mtd_dev_s *dev, off_t offset,
+                              size_t nbytes, FAR const uint8_t *buffer);
+#endif
+static size_t  rpmsgmtd_ioctl_arglen(int cmd);
+static int     rpmsgmtd_ioctl(FAR struct mtd_dev_s *dev, int cmd,
+                              unsigned long arg);
+
+/* Functions for sending data to the remote cpu */
+
+static int     rpmsgmtd_send_recv(FAR struct rpmsgmtd_s *priv,
+                                  uint32_t command, bool copy,
+                                  FAR struct rpmsgmtd_header_s *msg,
+                                  int len, FAR void *data);
+static FAR void *rpmsgmtd_get_tx_payload_buffer(FAR struct rpmsgmtd_s *priv,
+                                                FAR uint32_t *len);
+
+/* Functions handle the responses from the remote cpu */
+
+static int     rpmsgmtd_default_handler(FAR struct rpmsg_endpoint *ept,
+                                        FAR void *data, size_t len,
+                                        uint32_t src, FAR void *priv);
+static int     rpmsgmtd_bread_handler(FAR struct rpmsg_endpoint *ept,
+                                      FAR void *data, size_t len,
+                                      uint32_t src, FAR void *priv);
+static int     rpmsgmtd_read_handler(FAR struct rpmsg_endpoint *ept,
+                                     FAR void *data, size_t len,
+                                     uint32_t src, FAR void *priv);
+static int     rpmsgmtd_ioctl_handler(FAR struct rpmsg_endpoint *ept,
+                                      FAR void *data, size_t len,
+                                      uint32_t src, FAR void *priv);
+
+/* Functions for creating communication with remote cpu */
+
+static void    rpmsgmtd_device_created(struct rpmsg_device *rdev,
+                                       FAR void *priv_);
+static void    rpmsgmtd_device_destroy(struct rpmsg_device *rdev,
+                                       FAR void *priv_);
+static int     rpmsgmtd_ept_cb(FAR struct rpmsg_endpoint *ept,
+                               FAR void *data, size_t len, uint32_t src,
+                               FAR void *priv);
+static void    rpmsgmtd_ns_bound(struct rpmsg_endpoint *ept);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* Rpmsg device response handler table */
+
+static const rpmsg_ept_cb g_rpmsgmtd_handler[] =
+{
+  [RPMSGMTD_ERASE]  = rpmsgmtd_default_handler,
+  [RPMSGMTD_BREAD]  = rpmsgmtd_bread_handler,
+  [RPMSGMTD_BWRITE] = rpmsgmtd_default_handler,
+  [RPMSGMTD_READ]   = rpmsgmtd_read_handler,
+  [RPMSGMTD_WRITE]  = rpmsgmtd_default_handler,
+  [RPMSGMTD_IOCTL]  = rpmsgmtd_ioctl_handler,
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: rpmsgmtd_erase
+ *
+ * Description:
+ *   Rpmsg-mtd erase operation
+ *
+ * Parameters:
+ *   dev        - the mtd device
+ *   startblock - erase start block
+ *   nblocks    - erase block number
+ *
+ * Returned Values:
+ *   OK on success; A negated errno value is returned on any failure.
+ *
+ ****************************************************************************/
+
+static int rpmsgmtd_erase(FAR struct mtd_dev_s *dev, off_t startblock,
+                          size_t nblocks)
+{
+  FAR struct rpmsgmtd_s *priv = (FAR struct rpmsgmtd_s *)dev;
+  struct rpmsgmtd_erase_s msg;
+  int ret;
+
+  /* Sanity checks */
+
+  DEBUGASSERT(priv != NULL);
+
+  msg.startblock = startblock;
+  msg.nblocks    = nblocks;
+  ret = rpmsgmtd_send_recv(priv, RPMSGMTD_ERASE, true, &msg.header,

Review Comment:
   remove ret



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [incubator-nuttx] CV-Bowen commented on pull request #7042: Add rpmsgmtd support

Posted by GitBox <gi...@apache.org>.
CV-Bowen commented on PR #7042:
URL: https://github.com/apache/incubator-nuttx/pull/7042#issuecomment-1241617377

   CI failed, refresh the defconfig.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [incubator-nuttx] CV-Bowen commented on a diff in pull request #7042: Add rpmsgmtd support

Posted by GitBox <gi...@apache.org>.
CV-Bowen commented on code in PR #7042:
URL: https://github.com/apache/incubator-nuttx/pull/7042#discussion_r966052938


##########
drivers/mtd/rpmsgmtd.c:
##########
@@ -0,0 +1,1128 @@
+/****************************************************************************
+ * drivers/mtd/rpmsgmtd.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <debug.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/mtd/mtd.h>
+#include <nuttx/mutex.h>
+#include <nuttx/rptun/openamp.h>
+
+#include "rpmsgmtd.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct rpmsgmtd_s
+{
+  struct mtd_dev_s      mtd;         /* MTD device */
+  struct rpmsg_endpoint ept;         /* Rpmsg endpoint */
+  FAR const char       *remotecpu;   /* The server cpu name */
+  FAR const char       *remotepath;  /* The device path in the server cpu */
+  sem_t                 wait;        /* Wait sem, used for preventing any
+                                      * opreation until the connection
+                                      * between two cpu established.
+                                      */
+  mutex_t               geoexcl;     /* Get mtd geometry operation mutex */
+  struct mtd_geometry_s geo;         /* MTD geomerty */
+};
+
+/* Rpmsg device cookie used to handle the response from the remote cpu */
+
+struct rpmsgmtd_cookie_s
+{
+  sem_t     sem;     /* Semaphore used fo rpmsg */
+  int       result;  /* The return value of the remote call */
+  FAR void *data;    /* The return data buffer of the remote call */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* The mtd operation functions */
+
+static int     rpmsgmtd_erase(FAR struct mtd_dev_s *dev, off_t startblock,
+                              size_t nblocks);
+static int     rpmsgmtd_get_geometry(FAR struct rpmsgmtd_s *dev);
+static ssize_t rpmsgmtd_bread(FAR struct mtd_dev_s *dev, off_t startblock,
+                              size_t nblocks, FAR uint8_t *buffer);
+static ssize_t rpmsgmtd_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
+                               size_t nblocks, FAR const uint8_t *buffer);
+static ssize_t rpmsgmtd_read(FAR struct mtd_dev_s *dev, off_t offset,
+                             size_t nbytes, FAR uint8_t *buffer);
+#ifdef CONFIG_MTD_BYTE_WRITE
+static ssize_t rpmsgmtd_write(FAR struct mtd_dev_s *dev, off_t offset,
+                              size_t nbytes, FAR const uint8_t *buffer);
+#endif
+static size_t  rpmsgmtd_ioctl_arglen(int cmd);
+static int     rpmsgmtd_ioctl(FAR struct mtd_dev_s *dev, int cmd,
+                              unsigned long arg);
+
+/* Functions for sending data to the remote cpu */
+
+static int     rpmsgmtd_send_recv(FAR struct rpmsgmtd_s *priv,
+                                  uint32_t command, bool copy,
+                                  FAR struct rpmsgmtd_header_s *msg,
+                                  int len, FAR void *data);
+static FAR void *rpmsgmtd_get_tx_payload_buffer(FAR struct rpmsgmtd_s *priv,
+                                                FAR uint32_t *len);
+
+/* Functions handle the responses from the remote cpu */
+
+static int     rpmsgmtd_default_handler(FAR struct rpmsg_endpoint *ept,
+                                        FAR void *data, size_t len,
+                                        uint32_t src, FAR void *priv);
+static int     rpmsgmtd_bread_handler(FAR struct rpmsg_endpoint *ept,
+                                      FAR void *data, size_t len,
+                                      uint32_t src, FAR void *priv);
+static int     rpmsgmtd_read_handler(FAR struct rpmsg_endpoint *ept,
+                                     FAR void *data, size_t len,
+                                     uint32_t src, FAR void *priv);
+static int     rpmsgmtd_ioctl_handler(FAR struct rpmsg_endpoint *ept,
+                                      FAR void *data, size_t len,
+                                      uint32_t src, FAR void *priv);
+
+/* Functions for creating communication with remote cpu */
+
+static void    rpmsgmtd_device_created(struct rpmsg_device *rdev,
+                                       FAR void *priv_);
+static void    rpmsgmtd_device_destroy(struct rpmsg_device *rdev,
+                                       FAR void *priv_);
+static int     rpmsgmtd_ept_cb(FAR struct rpmsg_endpoint *ept,
+                               FAR void *data, size_t len, uint32_t src,
+                               FAR void *priv);
+static void    rpmsgmtd_ns_bound(struct rpmsg_endpoint *ept);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* Rpmsg device response handler table */
+
+static const rpmsg_ept_cb g_rpmsgmtd_handler[] =
+{
+  [RPMSGMTD_ERASE]  = rpmsgmtd_default_handler,
+  [RPMSGMTD_BREAD]  = rpmsgmtd_bread_handler,
+  [RPMSGMTD_BWRITE] = rpmsgmtd_default_handler,
+  [RPMSGMTD_READ]   = rpmsgmtd_read_handler,
+  [RPMSGMTD_WRITE]  = rpmsgmtd_default_handler,
+  [RPMSGMTD_IOCTL]  = rpmsgmtd_ioctl_handler,
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: rpmsgmtd_erase
+ *
+ * Description:
+ *   Rpmsg-mtd erase operation
+ *
+ * Parameters:
+ *   dev        - the mtd device
+ *   startblock - erase start block
+ *   nblocks    - erase block number
+ *
+ * Returned Values:
+ *   OK on success; A negated errno value is returned on any failure.
+ *
+ ****************************************************************************/
+
+static int rpmsgmtd_erase(FAR struct mtd_dev_s *dev, off_t startblock,
+                          size_t nblocks)
+{
+  FAR struct rpmsgmtd_s *priv = (FAR struct rpmsgmtd_s *)dev;
+  struct rpmsgmtd_erase_s msg;
+
+  /* Sanity checks */
+
+  DEBUGASSERT(priv != NULL);
+
+  msg.startblock = startblock;
+  msg.nblocks    = nblocks;
+
+  return rpmsgmtd_send_recv(priv, RPMSGMTD_ERASE, true, &msg.header,
+                            sizeof(msg), NULL);
+}
+
+/****************************************************************************
+ * Name: rpmsgmtd_get_geometry
+ *
+ * Description:
+ *   Rpmsg-mtd get the server mtd device geometry
+ *
+ * Parameters:
+ *   dev - the mtd device
+ *
+ * Returned Values:
+ *   OK on success; A negated errno value is returned on any failure.
+ *
+ ****************************************************************************/
+
+static int rpmsgmtd_get_geometry(FAR struct rpmsgmtd_s *dev)

Review Comment:
   Done, I modify to
   ```c
   static int rpmsgmtd_get_geometry(FAR struct rpmsgmtd_s *dev)
   {
     int ret;
   
     ret = nxmutex_lock(&dev->geoexcl);
     if (ret < 0)
       {
         return ret;
       }
   
     if (dev->geo.blocksize == 0)
       {
         /* Get the server mtd device geometry */
   
         ret = rpmsgmtd_ioctl(&dev->mtd, MTDIOC_GEOMETRY,
                              (unsigned long)&dev->geo);
       }
   
     nxmutex_unlock(&dev->geoexcl);
     return ret;
   }
   ```
   I think we should not unlock the mutex if mutex has lock failed. 



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [incubator-nuttx] CV-Bowen commented on a diff in pull request #7042: Add rpmsgmtd support

Posted by GitBox <gi...@apache.org>.
CV-Bowen commented on code in PR #7042:
URL: https://github.com/apache/incubator-nuttx/pull/7042#discussion_r966611943


##########
drivers/mtd/Kconfig:
##########
@@ -345,6 +345,16 @@ config NULLMTD_ERASESTATE
 
 endif # NULLMTD
 
+config RPMSGMTD

Review Comment:
   @xiaoxiang781216 @anchao Should i change it back?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [incubator-nuttx] anchao commented on a diff in pull request #7042: Add rpmsgmtd support

Posted by GitBox <gi...@apache.org>.
anchao commented on code in PR #7042:
URL: https://github.com/apache/incubator-nuttx/pull/7042#discussion_r966034349


##########
drivers/mtd/rpmsgmtd.c:
##########
@@ -0,0 +1,1128 @@
+/****************************************************************************
+ * drivers/mtd/rpmsgmtd.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <debug.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/mtd/mtd.h>
+#include <nuttx/mutex.h>
+#include <nuttx/rptun/openamp.h>
+
+#include "rpmsgmtd.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct rpmsgmtd_s
+{
+  struct mtd_dev_s      mtd;         /* MTD device */
+  struct rpmsg_endpoint ept;         /* Rpmsg endpoint */
+  FAR const char       *remotecpu;   /* The server cpu name */
+  FAR const char       *remotepath;  /* The device path in the server cpu */
+  sem_t                 wait;        /* Wait sem, used for preventing any
+                                      * opreation until the connection
+                                      * between two cpu established.
+                                      */
+  mutex_t               geoexcl;     /* Get mtd geometry operation mutex */
+  struct mtd_geometry_s geo;         /* MTD geomerty */
+};
+
+/* Rpmsg device cookie used to handle the response from the remote cpu */
+
+struct rpmsgmtd_cookie_s
+{
+  sem_t     sem;     /* Semaphore used fo rpmsg */
+  int       result;  /* The return value of the remote call */
+  FAR void *data;    /* The return data buffer of the remote call */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* The mtd operation functions */
+
+static int     rpmsgmtd_erase(FAR struct mtd_dev_s *dev, off_t startblock,
+                              size_t nblocks);
+static int     rpmsgmtd_get_geometry(FAR struct rpmsgmtd_s *dev);
+static ssize_t rpmsgmtd_bread(FAR struct mtd_dev_s *dev, off_t startblock,
+                              size_t nblocks, FAR uint8_t *buffer);
+static ssize_t rpmsgmtd_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
+                               size_t nblocks, FAR const uint8_t *buffer);
+static ssize_t rpmsgmtd_read(FAR struct mtd_dev_s *dev, off_t offset,
+                             size_t nbytes, FAR uint8_t *buffer);
+#ifdef CONFIG_MTD_BYTE_WRITE
+static ssize_t rpmsgmtd_write(FAR struct mtd_dev_s *dev, off_t offset,
+                              size_t nbytes, FAR const uint8_t *buffer);
+#endif
+static size_t  rpmsgmtd_ioctl_arglen(int cmd);
+static int     rpmsgmtd_ioctl(FAR struct mtd_dev_s *dev, int cmd,
+                              unsigned long arg);
+
+/* Functions for sending data to the remote cpu */
+
+static int     rpmsgmtd_send_recv(FAR struct rpmsgmtd_s *priv,
+                                  uint32_t command, bool copy,
+                                  FAR struct rpmsgmtd_header_s *msg,
+                                  int len, FAR void *data);
+static FAR void *rpmsgmtd_get_tx_payload_buffer(FAR struct rpmsgmtd_s *priv,
+                                                FAR uint32_t *len);
+
+/* Functions handle the responses from the remote cpu */
+
+static int     rpmsgmtd_default_handler(FAR struct rpmsg_endpoint *ept,
+                                        FAR void *data, size_t len,
+                                        uint32_t src, FAR void *priv);
+static int     rpmsgmtd_bread_handler(FAR struct rpmsg_endpoint *ept,
+                                      FAR void *data, size_t len,
+                                      uint32_t src, FAR void *priv);
+static int     rpmsgmtd_read_handler(FAR struct rpmsg_endpoint *ept,
+                                     FAR void *data, size_t len,
+                                     uint32_t src, FAR void *priv);
+static int     rpmsgmtd_ioctl_handler(FAR struct rpmsg_endpoint *ept,
+                                      FAR void *data, size_t len,
+                                      uint32_t src, FAR void *priv);
+
+/* Functions for creating communication with remote cpu */
+
+static void    rpmsgmtd_device_created(struct rpmsg_device *rdev,
+                                       FAR void *priv_);
+static void    rpmsgmtd_device_destroy(struct rpmsg_device *rdev,
+                                       FAR void *priv_);
+static int     rpmsgmtd_ept_cb(FAR struct rpmsg_endpoint *ept,
+                               FAR void *data, size_t len, uint32_t src,
+                               FAR void *priv);
+static void    rpmsgmtd_ns_bound(struct rpmsg_endpoint *ept);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* Rpmsg device response handler table */
+
+static const rpmsg_ept_cb g_rpmsgmtd_handler[] =
+{
+  [RPMSGMTD_ERASE]  = rpmsgmtd_default_handler,
+  [RPMSGMTD_BREAD]  = rpmsgmtd_bread_handler,
+  [RPMSGMTD_BWRITE] = rpmsgmtd_default_handler,
+  [RPMSGMTD_READ]   = rpmsgmtd_read_handler,
+  [RPMSGMTD_WRITE]  = rpmsgmtd_default_handler,
+  [RPMSGMTD_IOCTL]  = rpmsgmtd_ioctl_handler,
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: rpmsgmtd_erase
+ *
+ * Description:
+ *   Rpmsg-mtd erase operation
+ *
+ * Parameters:
+ *   dev        - the mtd device
+ *   startblock - erase start block
+ *   nblocks    - erase block number
+ *
+ * Returned Values:
+ *   OK on success; A negated errno value is returned on any failure.
+ *
+ ****************************************************************************/
+
+static int rpmsgmtd_erase(FAR struct mtd_dev_s *dev, off_t startblock,
+                          size_t nblocks)
+{
+  FAR struct rpmsgmtd_s *priv = (FAR struct rpmsgmtd_s *)dev;
+  struct rpmsgmtd_erase_s msg;
+
+  /* Sanity checks */
+
+  DEBUGASSERT(priv != NULL);
+
+  msg.startblock = startblock;
+  msg.nblocks    = nblocks;
+
+  return rpmsgmtd_send_recv(priv, RPMSGMTD_ERASE, true, &msg.header,
+                            sizeof(msg), NULL);
+}
+
+/****************************************************************************
+ * Name: rpmsgmtd_get_geometry
+ *
+ * Description:
+ *   Rpmsg-mtd get the server mtd device geometry
+ *
+ * Parameters:
+ *   dev - the mtd device
+ *
+ * Returned Values:
+ *   OK on success; A negated errno value is returned on any failure.
+ *
+ ****************************************************************************/
+
+static int rpmsgmtd_get_geometry(FAR struct rpmsgmtd_s *dev)

Review Comment:
   ```
   static int rpmsgmtd_get_geometry(FAR struct rpmsgmtd_s *dev)
   { 
     int ret;
       
     ret = nxmutex_lock(&dev->geoexcl);
     if (ret == OK && dev->geo.blocksize == 0)
       {
         /* Get the server mtd device geometry */
             
         ret = rpmsgmtd_ioctl(&dev->mtd, MTDIOC_GEOMETRY,
                              (unsigned long)&dev->geo);
       }
   
     nxmutex_unlock(&dev->geoexcl);
     return ret;
   }
   
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [incubator-nuttx] xiaoxiang781216 merged pull request #7042: Add rpmsgmtd support

Posted by GitBox <gi...@apache.org>.
xiaoxiang781216 merged PR #7042:
URL: https://github.com/apache/incubator-nuttx/pull/7042


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org