This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new 16ea80e53b rndis: support iob offload
16ea80e53b is described below

commit 16ea80e53b3386836ffb86015dbd142e0243cc1c
Author: zhanghongyu <[email protected]>
AuthorDate: Tue Feb 14 17:16:46 2023 +0800

    rndis: support iob offload
    
    Signed-off-by: zhanghongyu <[email protected]>
---
 .../arm/cxd56xx/spresense/configs/rndis/defconfig  |   1 +
 .../cxd56xx/spresense/configs/rndis_smp/defconfig  |   1 +
 .../freedom-k28f/configs/nshsdusb/defconfig        |   1 +
 .../lc823450-xgevk/configs/krndis/defconfig        |   1 +
 .../lc823450-xgevk/configs/rndis/defconfig         |   1 +
 .../stm32/stm32f4discovery/configs/rndis/defconfig |   1 +
 drivers/usbdev/rndis.c                             | 176 ++++++++++++++++-----
 7 files changed, 145 insertions(+), 37 deletions(-)

diff --git a/boards/arm/cxd56xx/spresense/configs/rndis/defconfig 
b/boards/arm/cxd56xx/spresense/configs/rndis/defconfig
index 91ab248d3e..f0a222a822 100644
--- a/boards/arm/cxd56xx/spresense/configs/rndis/defconfig
+++ b/boards/arm/cxd56xx/spresense/configs/rndis/defconfig
@@ -97,6 +97,7 @@ CONFIG_NET_BROADCAST=y
 CONFIG_NET_ETH_PKTSIZE=1514
 CONFIG_NET_ICMP=y
 CONFIG_NET_ICMP_SOCKET=y
+CONFIG_NET_LL_GUARDSIZE=50
 CONFIG_NET_LOOPBACK=y
 CONFIG_NET_PKT=y
 CONFIG_NET_ROUTE=y
diff --git a/boards/arm/cxd56xx/spresense/configs/rndis_smp/defconfig 
b/boards/arm/cxd56xx/spresense/configs/rndis_smp/defconfig
index 83dcb66291..ba138d0bb4 100644
--- a/boards/arm/cxd56xx/spresense/configs/rndis_smp/defconfig
+++ b/boards/arm/cxd56xx/spresense/configs/rndis_smp/defconfig
@@ -97,6 +97,7 @@ CONFIG_NET_BROADCAST=y
 CONFIG_NET_ETH_PKTSIZE=1514
 CONFIG_NET_ICMP=y
 CONFIG_NET_ICMP_SOCKET=y
+CONFIG_NET_LL_GUARDSIZE=50
 CONFIG_NET_LOOPBACK=y
 CONFIG_NET_PKT=y
 CONFIG_NET_ROUTE=y
diff --git a/boards/arm/kinetis/freedom-k28f/configs/nshsdusb/defconfig 
b/boards/arm/kinetis/freedom-k28f/configs/nshsdusb/defconfig
index c356216f41..7cf27d4f0f 100644
--- a/boards/arm/kinetis/freedom-k28f/configs/nshsdusb/defconfig
+++ b/boards/arm/kinetis/freedom-k28f/configs/nshsdusb/defconfig
@@ -52,6 +52,7 @@ CONFIG_NETUTILS_TELNETD=y
 CONFIG_NET_ARP_SEND=y
 CONFIG_NET_BROADCAST=y
 CONFIG_NET_ICMP=y
+CONFIG_NET_LL_GUARDSIZE=50
 CONFIG_NET_LOOPBACK=y
 CONFIG_NET_SOCKOPTS=y
 CONFIG_NET_STATISTICS=y
diff --git a/boards/arm/lc823450/lc823450-xgevk/configs/krndis/defconfig 
b/boards/arm/lc823450/lc823450-xgevk/configs/krndis/defconfig
index 07fa399688..95bc96c44e 100644
--- a/boards/arm/lc823450/lc823450-xgevk/configs/krndis/defconfig
+++ b/boards/arm/lc823450/lc823450-xgevk/configs/krndis/defconfig
@@ -100,6 +100,7 @@ CONFIG_NET_BROADCAST=y
 CONFIG_NET_ETH_PKTSIZE=1500
 CONFIG_NET_ICMP=y
 CONFIG_NET_ICMP_SOCKET=y
+CONFIG_NET_LL_GUARDSIZE=50
 CONFIG_NET_LOOPBACK=y
 CONFIG_NET_PKT=y
 CONFIG_NET_ROUTE=y
diff --git a/boards/arm/lc823450/lc823450-xgevk/configs/rndis/defconfig 
b/boards/arm/lc823450/lc823450-xgevk/configs/rndis/defconfig
index fad049b3e6..a3f3a83399 100644
--- a/boards/arm/lc823450/lc823450-xgevk/configs/rndis/defconfig
+++ b/boards/arm/lc823450/lc823450-xgevk/configs/rndis/defconfig
@@ -97,6 +97,7 @@ CONFIG_NET_BROADCAST=y
 CONFIG_NET_ETH_PKTSIZE=1514
 CONFIG_NET_ICMP=y
 CONFIG_NET_ICMP_SOCKET=y
+CONFIG_NET_LL_GUARDSIZE=50
 CONFIG_NET_LOOPBACK=y
 CONFIG_NET_PKT=y
 CONFIG_NET_ROUTE=y
diff --git a/boards/arm/stm32/stm32f4discovery/configs/rndis/defconfig 
b/boards/arm/stm32/stm32f4discovery/configs/rndis/defconfig
index 0fa2449d30..52c295d8af 100644
--- a/boards/arm/stm32/stm32f4discovery/configs/rndis/defconfig
+++ b/boards/arm/stm32/stm32f4discovery/configs/rndis/defconfig
@@ -53,6 +53,7 @@ CONFIG_NET_ARP_SEND=y
 CONFIG_NET_BROADCAST=y
 CONFIG_NET_ICMP=y
 CONFIG_NET_ICMP_SOCKET=y
+CONFIG_NET_LL_GUARDSIZE=50
 CONFIG_NET_LOOPBACK=y
 CONFIG_NET_STATISTICS=y
 CONFIG_NET_TCP=y
diff --git a/drivers/usbdev/rndis.c b/drivers/usbdev/rndis.c
index de31b6ea3b..765275febb 100644
--- a/drivers/usbdev/rndis.c
+++ b/drivers/usbdev/rndis.c
@@ -70,6 +70,14 @@
   (CONFIG_NET_ETH_PKTSIZE + CONFIG_NET_GUARDSIZE + RNDIS_PACKET_HDR_SIZE)
 #define CONFIG_RNDIS_BULKOUT_REQLEN CONFIG_RNDIS_BULKIN_REQLEN
 
+static_assert(CONFIG_NET_LL_GUARDSIZE >= RNDIS_PACKET_HDR_SIZE + ETH_HDRLEN,
+             "CONFIG_NET_LL_GUARDSIZE cannot be less than ETH_HDRLEN"
+             " + RNDIS_PACKET_HDR_SIZE");
+
+static_assert((CONFIG_NET_LL_GUARDSIZE % 4) == 2,
+             "CONFIG_NET_LL_GUARDSIZE - ETH_HDRLEN "
+             "should be aligned to 4 bytes");
+
 #define RNDIS_NCONFIGS          (1)
 #define RNDIS_CONFIGID          (1)
 #define RNDIS_CONFIGIDNONE      (0)
@@ -108,6 +116,8 @@ struct rndis_req_s
 {
   FAR struct rndis_req_s  *flink;  /* Implements a singly linked list */
   FAR struct usbdev_req_s *req;    /* The contained request */
+  FAR struct iob_s        *iob;    /* IOB offload */
+  FAR uint8_t             *buf;    /* Use malloc buffer when config IOB_LEN < 
CONFIG_RNDIS_BULKIN_REQLEN */
 };
 
 /* This structure describes the internal state of the driver */
@@ -632,6 +642,14 @@ static void rndis_freewrreq(FAR struct rndis_dev_s *priv,
                             FAR struct rndis_req_s *req)
 {
   DEBUGASSERT(req != NULL);
+  if (req->iob)
+    {
+      /* In ep submit case, need release iob chain when write complete */
+
+      iob_free_chain(req->iob);
+      req->iob = NULL;
+    }
+
   sq_addlast((FAR sq_entry_t *)req, &priv->reqlist);
   rndis_submit_rdreq(priv);
 }
@@ -665,11 +683,6 @@ static bool rndis_allocnetreq(FAR struct rndis_dev_s *priv)
     }
 
   priv->net_req = rndis_allocwrreq(priv);
-  if (priv->net_req)
-    {
-      priv->netdev.d_buf = &priv->net_req->req->buf[RNDIS_PACKET_HDR_SIZE];
-      priv->netdev.d_len = CONFIG_NET_ETH_PKTSIZE;
-    }
 
   leave_critical_section(flags);
   return priv->net_req != NULL;
@@ -699,8 +712,6 @@ static void rndis_sendnetreq(FAR struct rndis_dev_s *priv)
   EP_SUBMIT(priv->epbulkin, priv->net_req->req);
 
   priv->net_req            = NULL;
-  priv->netdev.d_buf       = NULL;
-  priv->netdev.d_len       = 0;
   leave_critical_section(flags);
 }
 
@@ -723,12 +734,56 @@ static void rndis_freenetreq(FAR struct rndis_dev_s *priv)
   irqstate_t flags = enter_critical_section();
 
   rndis_freewrreq(priv, priv->net_req);
-  priv->net_req      = NULL;
-  priv->netdev.d_buf = NULL;
-  priv->netdev.d_len = 0;
+  priv->net_req = NULL;
+
   leave_critical_section(flags);
 }
 
+/****************************************************************************
+ * Name: rndis_iob2buf
+ *
+ * Description:
+ *   Map the appropriate location of req iob to buf.
+ *
+ * Input Parameters:
+ *   priv: pointer to RNDIS device driver structure
+ *   req: the request whose buffer we should fill
+ * Assumptions:
+ *   Caller holds the network lock
+ *
+ ****************************************************************************/
+
+static void rndis_iob2buf(FAR struct rndis_dev_s *priv,
+                          FAR struct rndis_req_s *req)
+{
+  uint16_t llhdrlen = NET_LL_HDRLEN(&priv->netdev);
+  uint32_t offset   = CONFIG_NET_LL_GUARDSIZE - llhdrlen -
+                      RNDIS_PACKET_HDR_SIZE;
+
+  /*  ----------------------------------------------------------------
+   *  |<--- CONFIG_NET_LL_GUARDSIZE ---->|<-- io_len/io_pktlen(0) -->|
+   *  ---------------------------------------------------------------|
+   *  |unused | rndis hdr size |llhdrlen |<-- io_len/io_pktlen(0) -->|
+   *  ---------------------------------------------------------------|
+   *  |unused | req->buf(0)                                          |
+   *  ---------------------------------------------------------------|
+   */
+
+  if (req->iob->io_flink == NULL)
+    {
+      req->req->buf = &req->iob->io_data[offset];
+      req->req->len = CONFIG_RNDIS_BULKIN_REQLEN;
+    }
+  else
+    {
+      req->req->buf = req->buf;
+      iob_copyout(&req->req->buf[RNDIS_PACKET_HDR_SIZE], req->iob,
+                  req->iob->io_pktlen + llhdrlen, -llhdrlen);
+      iob_free_chain(req->iob);
+      req->iob = NULL;
+    }
+}
+
 /****************************************************************************
  * Name: rndis_allocrxreq
  *
@@ -748,13 +803,33 @@ static void rndis_freenetreq(FAR struct rndis_dev_s *priv)
 
 static bool rndis_allocrxreq(FAR struct rndis_dev_s *priv)
 {
+  FAR struct iob_s *iob;
+
   if (priv->rx_req != NULL)
     {
       return true;
     }
 
-  priv->rx_req = rndis_allocwrreq(priv);
-  return priv->rx_req != NULL;
+  /* Prepare buffer to receivce data from usb driver */
+
+  iob = iob_tryalloc(false);
+  if (iob == NULL)
+    {
+      return false;
+    }
+
+  iob_reserve(iob, CONFIG_NET_LL_GUARDSIZE);
+
+  if ((priv->rx_req = rndis_allocwrreq(priv)) == NULL)
+    {
+      iob_free_chain(iob);
+      return false;
+    }
+
+  priv->rx_req->iob = iob;
+  rndis_iob2buf(priv, priv->rx_req);
+
+  return true;
 }
 
 /****************************************************************************
@@ -776,10 +851,16 @@ static void rndis_giverxreq(FAR struct rndis_dev_s *priv)
   DEBUGASSERT(priv->rx_req != NULL);
   DEBUGASSERT(priv->net_req == NULL);
 
-  priv->net_req      = priv->rx_req;
-  priv->netdev.d_buf = &priv->net_req->req->buf[RNDIS_PACKET_HDR_SIZE];
-  priv->netdev.d_len = CONFIG_NET_ETH_PKTSIZE;
-  priv->rx_req       = NULL;
+  priv->net_req = priv->rx_req;
+  priv->rx_req  = NULL;
+
+  /* Move iob from net_req to netdev */
+
+  netdev_iob_release(&priv->netdev);
+
+  priv->netdev.d_iob = priv->net_req->iob;
+  priv->netdev.d_len = priv->net_req->iob->io_pktlen;
+  priv->net_req->iob = NULL;
 }
 
 /****************************************************************************
@@ -801,20 +882,23 @@ static void rndis_giverxreq(FAR struct rndis_dev_s *priv)
  ****************************************************************************/
 
 static uint16_t rndis_fillrequest(FAR struct rndis_dev_s *priv,
-                                  FAR struct usbdev_req_s *req)
+                                  FAR struct rndis_req_s *req)
 {
   size_t datalen;
 
-  req->len = 0;
+  req->req->len = 0;
 
   datalen = MIN(priv->netdev.d_len,
                 CONFIG_RNDIS_BULKIN_REQLEN - RNDIS_PACKET_HDR_SIZE);
   if (datalen > 0)
     {
-      /* Send the required headers */
+      /* Move iob from netdev to net_req and send the required headers */
 
+      req->iob = priv->netdev.d_iob;
+      netdev_iob_clear(&priv->netdev);
+      rndis_iob2buf(priv, req);
       FAR struct rndis_packet_msg *msg =
-        (FAR struct rndis_packet_msg *)req->buf;
+        (FAR struct rndis_packet_msg *)req->req->buf;
       memset(msg, 0, RNDIS_PACKET_HDR_SIZE);
 
       msg->msgtype    = RNDIS_PACKET_MSG;
@@ -822,11 +906,11 @@ static uint16_t rndis_fillrequest(FAR struct rndis_dev_s 
*priv,
       msg->dataoffset = RNDIS_PACKET_HDR_SIZE - 8;
       msg->datalen    = datalen;
 
-      req->flags      = USBDEV_REQFLAGS_NULLPKT;
-      req->len        = datalen + RNDIS_PACKET_HDR_SIZE;
+      req->req->flags = USBDEV_REQFLAGS_NULLPKT;
+      req->req->len   = datalen + RNDIS_PACKET_HDR_SIZE;
     }
 
-  return req->len;
+  return req->req->len;
 }
 
 /****************************************************************************
@@ -852,7 +936,9 @@ static void rndis_rxdispatch(FAR void *arg)
   priv->netdev.d_len = priv->current_rx_datagram_size;
   leave_critical_section(flags);
 
-  hdr = (FAR struct eth_hdr_s *)priv->netdev.d_buf;
+  hdr = (FAR struct eth_hdr_s *)
+    &priv->netdev.d_iob->io_data[CONFIG_NET_LL_GUARDSIZE -
+                                 NET_LL_HDRLEN(&priv->netdev)];
 
   /* We only accept IP packets of the configured type and ARP packets */
 
@@ -965,7 +1051,7 @@ static int rndis_transmit(FAR struct rndis_dev_s *priv)
 
   /* Queue the packet */
 
-  rndis_fillrequest(priv, priv->net_req->req);
+  rndis_fillrequest(priv, priv->net_req);
   rndis_sendnetreq(priv);
 
   if (!rndis_allocnetreq(priv))
@@ -1110,9 +1196,10 @@ static inline int rndis_recvpacket(FAR struct 
rndis_dev_s *priv,
               priv->current_rx_datagram_offset = msg->dataoffset + 8;
               if (priv->current_rx_datagram_offset < reqlen)
                 {
-                  memcpy(&priv->rx_req->req->buf[RNDIS_PACKET_HDR_SIZE],
-                         &reqbuf[priv->current_rx_datagram_offset],
-                         reqlen - priv->current_rx_datagram_offset);
+                  iob_trycopyin(priv->rx_req->iob,
+                                &reqbuf[priv->current_rx_datagram_offset],
+                                reqlen - priv->current_rx_datagram_offset,
+                                -NET_LL_HDRLEN(&priv->netdev), false);
                 }
             }
           else
@@ -1136,8 +1223,8 @@ static inline int rndis_recvpacket(FAR struct rndis_dev_s 
*priv,
 
           if ((index + copysize) <= CONFIG_NET_ETH_PKTSIZE)
             {
-              memcpy(&priv->rx_req->req->buf[RNDIS_PACKET_HDR_SIZE + index],
-                     reqbuf, copysize);
+              iob_trycopyin(priv->rx_req->iob, reqbuf, copysize,
+                            priv->rx_req->iob->io_pktlen, false);
             }
           else
             {
@@ -1721,13 +1808,24 @@ static FAR struct usbdev_req_s *usbclass_allocreq(FAR 
struct usbdev_ep_s *ep,
   req = EP_ALLOCREQ(ep);
   if (req != NULL)
     {
+      /* rdreq/epintin_req/ctrlreq use fixed memory
+       * reqcontainer use iob dynamically when needed
+       */
+
       req->len = len;
-      req->buf = EP_ALLOCBUFFER(ep, len);
+      if (len > 0)
+        {
+          req->buf = EP_ALLOCBUFFER(ep, len);
 
-      if (req->buf == NULL)
+          if (req->buf == NULL)
+            {
+              EP_FREEREQ(ep, req);
+              req = NULL;
+            }
+        }
+      else
         {
-          EP_FREEREQ(ep, req);
-          req = NULL;
+          req->buf = NULL;
         }
     }
 
@@ -2109,9 +2207,11 @@ static int usbclass_bind(FAR struct usbdevclass_driver_s 
*driver,
    * size.
    */
 
-  reqlen = 64;
-
-  if (CONFIG_RNDIS_BULKIN_REQLEN > reqlen)
+  if (CONFIG_IOB_BUFSIZE >= CONFIG_RNDIS_BULKIN_REQLEN)
+    {
+      reqlen = 0;
+    }
+  else
     {
       reqlen = CONFIG_RNDIS_BULKIN_REQLEN;
     }
@@ -2128,6 +2228,7 @@ static int usbclass_bind(FAR struct usbdevclass_driver_s 
*driver,
           goto errout;
         }
 
+      reqcontainer->buf           = reqcontainer->req->buf;
       reqcontainer->req->priv     = reqcontainer;
       reqcontainer->req->callback = rndis_wrcomplete;
 
@@ -2269,6 +2370,7 @@ static void usbclass_unbind(FAR struct 
usbdevclass_driver_s *driver,
           reqcontainer = (struct rndis_req_s *)sq_remfirst(&priv->reqlist);
           if (reqcontainer->req != NULL)
             {
+              reqcontainer->req->buf = reqcontainer->buf;
               usbclass_freereq(priv->epbulkin, reqcontainer->req);
             }
         }

Reply via email to