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);
}
}