mm/iob: Support negative offset when copyin/out.
Signed-off-by: Zhe Weng <wengzhe@xiaomi.com>
This commit is contained in:
parent
0f35ad29a8
commit
be89bcc044
|
@ -405,7 +405,7 @@ unsigned int iob_get_queue_size(FAR struct iob_queue_s *queue);
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
int iob_copyin(FAR struct iob_s *iob, FAR const uint8_t *src,
|
int iob_copyin(FAR struct iob_s *iob, FAR const uint8_t *src,
|
||||||
unsigned int len, unsigned int offset, bool throttled);
|
unsigned int len, int offset, bool throttled);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: iob_trycopyin
|
* Name: iob_trycopyin
|
||||||
|
@ -418,7 +418,7 @@ int iob_copyin(FAR struct iob_s *iob, FAR const uint8_t *src,
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
int iob_trycopyin(FAR struct iob_s *iob, FAR const uint8_t *src,
|
int iob_trycopyin(FAR struct iob_s *iob, FAR const uint8_t *src,
|
||||||
unsigned int len, unsigned int offset, bool throttled);
|
unsigned int len, int offset, bool throttled);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: iob_copyout
|
* Name: iob_copyout
|
||||||
|
@ -430,7 +430,7 @@ int iob_trycopyin(FAR struct iob_s *iob, FAR const uint8_t *src,
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
int iob_copyout(FAR uint8_t *dest, FAR const struct iob_s *iob,
|
int iob_copyout(FAR uint8_t *dest, FAR const struct iob_s *iob,
|
||||||
unsigned int len, unsigned int offset);
|
unsigned int len, int offset);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: iob_tailroom
|
* Name: iob_tailroom
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static int iob_copyin_internal(FAR struct iob_s *iob, FAR const uint8_t *src,
|
static int iob_copyin_internal(FAR struct iob_s *iob, FAR const uint8_t *src,
|
||||||
unsigned int len, unsigned int offset,
|
unsigned int len, int offset,
|
||||||
bool throttled, bool can_block)
|
bool throttled, bool can_block)
|
||||||
{
|
{
|
||||||
FAR struct iob_s *head = iob;
|
FAR struct iob_s *head = iob;
|
||||||
|
@ -61,23 +61,30 @@ static int iob_copyin_internal(FAR struct iob_s *iob, FAR const uint8_t *src,
|
||||||
unsigned int avail;
|
unsigned int avail;
|
||||||
unsigned int total = len;
|
unsigned int total = len;
|
||||||
|
|
||||||
iobinfo("iob=%p len=%u offset=%u\n", iob, len, offset);
|
iobinfo("iob=%p len=%u offset=%d\n", iob, len, offset);
|
||||||
DEBUGASSERT(iob && src);
|
DEBUGASSERT(iob && src);
|
||||||
|
|
||||||
/* The offset must applied to data that is already in the I/O buffer
|
/* The offset must applied to data that is already in the I/O buffer
|
||||||
* chain
|
* chain
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (offset > iob->io_pktlen)
|
if ((int)(offset - iob->io_pktlen) > 0)
|
||||||
{
|
{
|
||||||
ioberr("ERROR: offset is past the end of data: %u > %u\n",
|
ioberr("ERROR: offset is past the end of data: %d > %u\n",
|
||||||
offset, iob->io_pktlen);
|
offset, iob->io_pktlen);
|
||||||
return -ESPIPE;
|
return -ESPIPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((int)(offset + iob->io_offset) < 0)
|
||||||
|
{
|
||||||
|
ioberr("ERROR: offset is before the start of data: %d < %d\n",
|
||||||
|
offset, -(int)iob->io_offset);
|
||||||
|
return -ESPIPE;
|
||||||
|
}
|
||||||
|
|
||||||
/* Skip to the I/O buffer containing the data offset */
|
/* Skip to the I/O buffer containing the data offset */
|
||||||
|
|
||||||
while (offset > iob->io_len)
|
while ((int)(offset - iob->io_len) > 0)
|
||||||
{
|
{
|
||||||
offset -= iob->io_len;
|
offset -= iob->io_len;
|
||||||
iob = iob->io_flink;
|
iob = iob->io_flink;
|
||||||
|
@ -216,7 +223,7 @@ static int iob_copyin_internal(FAR struct iob_s *iob, FAR const uint8_t *src,
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
int iob_copyin(FAR struct iob_s *iob, FAR const uint8_t *src,
|
int iob_copyin(FAR struct iob_s *iob, FAR const uint8_t *src,
|
||||||
unsigned int len, unsigned int offset, bool throttled)
|
unsigned int len, int offset, bool throttled)
|
||||||
{
|
{
|
||||||
return iob_copyin_internal(iob, src, len, offset, throttled, true);
|
return iob_copyin_internal(iob, src, len, offset, throttled, true);
|
||||||
}
|
}
|
||||||
|
@ -232,7 +239,7 @@ int iob_copyin(FAR struct iob_s *iob, FAR const uint8_t *src,
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
int iob_trycopyin(FAR struct iob_s *iob, FAR const uint8_t *src,
|
int iob_trycopyin(FAR struct iob_s *iob, FAR const uint8_t *src,
|
||||||
unsigned int len, unsigned int offset, bool throttled)
|
unsigned int len, int offset, bool throttled)
|
||||||
{
|
{
|
||||||
return iob_copyin_internal(iob, src, len, offset, throttled, false);
|
return iob_copyin_internal(iob, src, len, offset, throttled, false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,16 +54,25 @@
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
int iob_copyout(FAR uint8_t *dest, FAR const struct iob_s *iob,
|
int iob_copyout(FAR uint8_t *dest, FAR const struct iob_s *iob,
|
||||||
unsigned int len, unsigned int offset)
|
unsigned int len, int offset)
|
||||||
{
|
{
|
||||||
FAR const uint8_t *src;
|
FAR const uint8_t *src;
|
||||||
unsigned int ncopy;
|
unsigned int ncopy;
|
||||||
unsigned int avail;
|
unsigned int avail;
|
||||||
unsigned int remaining;
|
unsigned int remaining;
|
||||||
|
|
||||||
|
/* The offset must applied to data that is in the I/O buffer chain */
|
||||||
|
|
||||||
|
if ((int)(offset + iob->io_offset) < 0)
|
||||||
|
{
|
||||||
|
ioberr("ERROR: offset is before the start of data: %d < %d\n",
|
||||||
|
offset, -(int)iob->io_offset);
|
||||||
|
return -ESPIPE;
|
||||||
|
}
|
||||||
|
|
||||||
/* Skip to the I/O buffer containing the offset */
|
/* Skip to the I/O buffer containing the offset */
|
||||||
|
|
||||||
while (offset >= iob->io_len)
|
while ((int)(offset - iob->io_len) >= 0)
|
||||||
{
|
{
|
||||||
offset -= iob->io_len;
|
offset -= iob->io_len;
|
||||||
iob = iob->io_flink;
|
iob = iob->io_flink;
|
||||||
|
|
|
@ -1004,12 +1004,7 @@ int devif_poll(FAR struct net_driver_s *dev, devif_poll_callback_t callback)
|
||||||
{
|
{
|
||||||
/* Copy iob to flat buffer */
|
/* Copy iob to flat buffer */
|
||||||
|
|
||||||
iob_copyout(buf + llhdrlen,
|
iob_copyout(buf, dev->d_iob, dev->d_len, -llhdrlen);
|
||||||
dev->d_iob, dev->d_len, 0);
|
|
||||||
|
|
||||||
/* Copy l2 header (arp out) */
|
|
||||||
|
|
||||||
memcpy(buf, IPBUF(-llhdrlen), llhdrlen);
|
|
||||||
|
|
||||||
/* Restore flat buffer pointer */
|
/* Restore flat buffer pointer */
|
||||||
|
|
||||||
|
|
|
@ -68,8 +68,6 @@ int netdev_input(FAR struct net_driver_s *dev,
|
||||||
{
|
{
|
||||||
uint16_t llhdrlen = NET_LL_HDRLEN(dev);
|
uint16_t llhdrlen = NET_LL_HDRLEN(dev);
|
||||||
FAR uint8_t *buf = dev->d_buf;
|
FAR uint8_t *buf = dev->d_buf;
|
||||||
unsigned int offset;
|
|
||||||
unsigned int l3l4len;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* Prepare iob buffer */
|
/* Prepare iob buffer */
|
||||||
|
@ -80,32 +78,21 @@ int netdev_input(FAR struct net_driver_s *dev,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy l2 header to gruard area */
|
/* Copy data to iob entry */
|
||||||
|
|
||||||
offset = dev->d_iob->io_offset - llhdrlen;
|
ret = iob_trycopyin(dev->d_iob, buf, dev->d_len, -llhdrlen, false);
|
||||||
memcpy(dev->d_iob->io_data + offset, buf, llhdrlen);
|
if (ret == dev->d_len)
|
||||||
|
|
||||||
/* Copy l3/l4 data to iob entry */
|
|
||||||
|
|
||||||
l3l4len = dev->d_len - llhdrlen;
|
|
||||||
|
|
||||||
ret = iob_trycopyin(dev->d_iob, buf + llhdrlen,
|
|
||||||
l3l4len, 0, false);
|
|
||||||
if (ret == l3l4len)
|
|
||||||
{
|
{
|
||||||
/* Update device buffer to l2 start */
|
/* Update device buffer to l2 start */
|
||||||
|
|
||||||
dev->d_buf = dev->d_iob->io_data + offset;
|
dev->d_buf = NETLLBUF;
|
||||||
|
|
||||||
iob_update_pktlen(dev->d_iob, l3l4len);
|
|
||||||
|
|
||||||
ret = callback(dev);
|
ret = callback(dev);
|
||||||
if (dev->d_iob != NULL && reply)
|
if (dev->d_iob != NULL && reply)
|
||||||
{
|
{
|
||||||
if (ret == OK && dev->d_len > 0)
|
if (ret == OK && dev->d_len > 0)
|
||||||
{
|
{
|
||||||
iob_copyout(buf + llhdrlen, dev->d_iob, dev->d_len, 0);
|
iob_copyout(buf, dev->d_iob, dev->d_len, -llhdrlen);
|
||||||
memcpy(buf, dev->d_iob->io_data + offset, llhdrlen);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue