summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomasz Bursztyka <tomasz.bursztyka@linux.intel.com>2017-01-26 14:31:30 +0100
committerJukka Rissanen <jukka.rissanen@linux.intel.com>2017-01-27 12:35:53 +0200
commit83ed3a29be8b1c7636cdd3233c79191277ca517e (patch)
tree6a79a3eafe6af31ec3958cc981c058e94bd01ef0
parent5794d80c10dadfd5149772ce6d84d84c2716be1a (diff)
net/ieee802154: Modify radio TX function signature
The cause for this change is TCP. Until now, the radio strategy driver (ALOHA or CSMA) was providing the actual nbuf, and not the buffer fragment, counting on the fact that the loop was using net_buf_frag_del() which made so, iteration after iteration, buffer framgent to be always buf->frags. The problem with this logic is loosing the fragments that might be still referenced by TCP, in case the whole buffer did not make it so TCP can retry later and so on. Instead, TX now takes the nbuf and the actual frag to send. It could have been working with just a pointer on the data, and the whole length of the frame. But it has been avoided due to possible future devices, that will be smarter and run CSMA directly in the hw, thus it will require to access the whole buffer list through the nbuf. Change-Id: I8d77b1e13b648c0ec3645cb2d55d1910d00381ea Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
-rw-r--r--drivers/ieee802154/ieee802154_cc2520.c32
-rw-r--r--drivers/ieee802154/ieee802154_mcr20a.c17
-rw-r--r--drivers/ieee802154/ieee802154_uart_pipe.c10
-rw-r--r--include/net/ieee802154_radio.h6
-rw-r--r--samples/net/wpan_serial/src/main.c2
-rw-r--r--samples/net/wpanusb/src/wpanusb.c2
-rw-r--r--subsys/net/ip/l2/ieee802154/ieee802154.c2
-rw-r--r--subsys/net/ip/l2/ieee802154/ieee802154_radio_aloha.c7
-rw-r--r--subsys/net/ip/l2/ieee802154/ieee802154_radio_csma_ca.c7
-rw-r--r--subsys/net/ip/l2/ieee802154/ieee802154_radio_utils.h7
-rw-r--r--tests/net/ieee802154/l2/src/ieee802154_fake_driver.c4
11 files changed, 54 insertions, 42 deletions
diff --git a/drivers/ieee802154/ieee802154_cc2520.c b/drivers/ieee802154/ieee802154_cc2520.c
index e1d71bc16..253ee4cc5 100644
--- a/drivers/ieee802154/ieee802154_cc2520.c
+++ b/drivers/ieee802154/ieee802154_cc2520.c
@@ -414,11 +414,10 @@ static inline void setup_gpio_callbacks(struct device *dev)
* TX functions *
***************/
static inline bool write_txfifo_length(struct cc2520_spi *spi,
- struct net_buf *buf)
+ uint8_t len)
{
spi->cmd_buf[0] = CC2520_INS_TXBUF;
- spi->cmd_buf[1] = net_nbuf_ll_reserve(buf) +
- buf->frags->len + CC2520_FCS_LENGTH;
+ spi->cmd_buf[1] = len + CC2520_FCS_LENGTH;
spi_slave_select(spi->dev, spi->slave);
@@ -426,25 +425,22 @@ static inline bool write_txfifo_length(struct cc2520_spi *spi,
}
static inline bool write_txfifo_content(struct cc2520_spi *spi,
- struct net_buf *buf)
+ uint8_t *frame, uint8_t len)
{
uint8_t cmd[128];
cmd[0] = CC2520_INS_TXBUF;
- memcpy(&cmd[1], net_nbuf_ll(buf),
- net_nbuf_ll_reserve(buf) + buf->frags->len);
+ memcpy(&cmd[1], frame, len);
spi_slave_select(spi->dev, spi->slave);
- return (spi_write(spi->dev, cmd, net_nbuf_ll_reserve(buf) +
- buf->frags->len + 1) == 0);
+ return (spi_write(spi->dev, cmd, len + 1) == 0);
}
static inline bool verify_txfifo_status(struct cc2520_context *cc2520,
- struct net_buf *buf)
+ uint8_t len)
{
- if (read_reg_txfifocnt(&cc2520->spi) < (net_nbuf_ll_reserve(buf) +
- buf->frags->len) ||
+ if (read_reg_txfifocnt(&cc2520->spi) < len ||
(read_reg_excflag0(&cc2520->spi) & EXCFLAG0_TX_UNDERFLOW)) {
return false;
}
@@ -816,22 +812,26 @@ error:
return -EIO;
}
-static int cc2520_tx(struct device *dev, struct net_buf *buf)
+static int cc2520_tx(struct device *dev,
+ struct net_buf *buf,
+ struct net_buf *frag)
{
+ uint8_t *frame = frag->data - net_nbuf_ll_reserve(buf);
+ uint8_t len = net_nbuf_ll_reserve(buf) + frag->len;
struct cc2520_context *cc2520 = dev->driver_data;
uint8_t retry = 2;
bool status;
- SYS_LOG_DBG("%p (%u)", buf, net_nbuf_ll_reserve(buf) + buf->frags->len);
+ SYS_LOG_DBG("%p (%u)", frag, len);
if (!write_reg_excflag0(&cc2520->spi, EXCFLAG0_RESET_TX_FLAGS) ||
- !write_txfifo_length(&cc2520->spi, buf) ||
- !write_txfifo_content(&cc2520->spi, buf)) {
+ !write_txfifo_length(&cc2520->spi, len) ||
+ !write_txfifo_content(&cc2520->spi, frame, len)) {
SYS_LOG_ERR("Cannot feed in TX fifo");
goto error;
}
- if (!verify_txfifo_status(cc2520, buf)) {
+ if (!verify_txfifo_status(cc2520, len)) {
SYS_LOG_ERR("Did not write properly into TX FIFO");
goto error;
}
diff --git a/drivers/ieee802154/ieee802154_mcr20a.c b/drivers/ieee802154/ieee802154_mcr20a.c
index a2b7b4cd6..2d150415c 100644
--- a/drivers/ieee802154/ieee802154_mcr20a.c
+++ b/drivers/ieee802154/ieee802154_mcr20a.c
@@ -1072,11 +1072,12 @@ error:
}
static inline bool write_txfifo_content(struct mcr20a_spi *spi,
- struct net_buf *buf)
+ struct net_buf *buf,
+ struct net_buf *frag)
{
uint8_t cmd[2 + MCR20A_PSDU_LENGTH];
- uint8_t payload_len = net_nbuf_ll_reserve(buf) +
- buf->frags->len;
+ uint8_t payload_len = net_nbuf_ll_reserve(buf) + frag->len;
+ uint8_t *payload = frag->data - net_nbuf_ll_reserve(buf);
cmd[0] = MCR20A_BUF_WRITE;
/**
@@ -1090,14 +1091,16 @@ static inline bool write_txfifo_content(struct mcr20a_spi *spi,
SYS_LOG_ERR("Payload too long");
return 0;
}
- memcpy(&cmd[2], net_nbuf_ll(buf), payload_len);
+ memcpy(&cmd[2], payload, payload_len);
spi_slave_select(spi->dev, spi->slave);
return (spi_write(spi->dev, cmd, (2 + payload_len)) == 0);
}
-static int mcr20a_tx(struct device *dev, struct net_buf *buf)
+static int mcr20a_tx(struct device *dev,
+ struct net_buf *buf,
+ struct net_buf *frag)
{
struct mcr20a_context *mcr20a = dev->driver_data;
uint8_t ctrl1;
@@ -1105,7 +1108,7 @@ static int mcr20a_tx(struct device *dev, struct net_buf *buf)
MCR20A_XCVSEQ_TX;
SYS_LOG_DBG("%p (%u)",
- buf, net_nbuf_ll_reserve(buf) + buf->frags->len);
+ frag, net_nbuf_ll_reserve(buf) + frag->len);
if (!mcr20a_mask_irqb(mcr20a, true)) {
goto error;
@@ -1131,7 +1134,7 @@ static int mcr20a_tx(struct device *dev, struct net_buf *buf)
goto error;
}
- if (!write_txfifo_content(&mcr20a->spi, buf)) {
+ if (!write_txfifo_content(&mcr20a->spi, buf, frag)) {
SYS_LOG_ERR("Did not write properly into TX FIFO");
goto error;
}
diff --git a/drivers/ieee802154/ieee802154_uart_pipe.c b/drivers/ieee802154/ieee802154_uart_pipe.c
index ea9aed4d9..6736f4fd0 100644
--- a/drivers/ieee802154/ieee802154_uart_pipe.c
+++ b/drivers/ieee802154/ieee802154_uart_pipe.c
@@ -162,14 +162,16 @@ static int upipe_set_txpower(struct device *dev, int16_t dbm)
return 0;
}
-static int upipe_tx(struct device *dev, struct net_buf *buf)
+static int upipe_tx(struct device *dev,
+ struct net_buf *buf,
+ struct net_buf *frag)
{
- uint8_t len = net_nbuf_ll_reserve(buf) + buf->frags->len;
+ uint8_t *pkt_buf = frag->data - net_nbuf_ll_reserve(buf);
+ uint8_t len = net_nbuf_ll_reserve(buf) + frag->len;
struct upipe_context *upipe = dev->driver_data;
- uint8_t *pkt_buf = net_nbuf_ll(buf);
uint8_t i, data;
- SYS_LOG_DBG("%p (%u)", buf, len);
+ SYS_LOG_DBG("%p (%u)", frag, len);
if (upipe->stopped) {
return -EIO;
diff --git a/include/net/ieee802154_radio.h b/include/net/ieee802154_radio.h
index 9e5e6ab85..ee7966ecc 100644
--- a/include/net/ieee802154_radio.h
+++ b/include/net/ieee802154_radio.h
@@ -42,8 +42,10 @@ struct ieee802154_radio_api {
/** Set TX power level in dbm */
int (*set_txpower)(struct device *dev, int16_t dbm);
- /** Transmit a buffer */
- int (*tx)(struct device *dev, struct net_buf *buf);
+ /** Transmit a buffer fragment */
+ int (*tx)(struct device *dev,
+ struct net_buf *buf,
+ struct net_buf *frag);
/** Start the device */
int (*start)(struct device *dev);
diff --git a/samples/net/wpan_serial/src/main.c b/samples/net/wpan_serial/src/main.c
index e7db90b25..a92e3b973 100644
--- a/samples/net/wpan_serial/src/main.c
+++ b/samples/net/wpan_serial/src/main.c
@@ -314,7 +314,7 @@ static void process_data(struct net_buf *pkt)
}
/* Transmit data through radio */
- ret = radio_api->tx(ieee802154_dev, pkt);
+ ret = radio_api->tx(ieee802154_dev, pkt, buf);
if (ret) {
SYS_LOG_ERR("Error transmit data");
}
diff --git a/samples/net/wpanusb/src/wpanusb.c b/samples/net/wpanusb/src/wpanusb.c
index 17a014252..528d93f2f 100644
--- a/samples/net/wpanusb/src/wpanusb.c
+++ b/samples/net/wpanusb/src/wpanusb.c
@@ -359,7 +359,7 @@ static int tx(struct net_buf *pkt)
SYS_LOG_DBG("len %d seq %u", buf->len, seq);
do {
- ret = radio_api->tx(ieee802154_dev, pkt);
+ ret = radio_api->tx(ieee802154_dev, pkt, buf);
} while (ret && retries--);
if (ret) {
diff --git a/subsys/net/ip/l2/ieee802154/ieee802154.c b/subsys/net/ip/l2/ieee802154/ieee802154.c
index a141ca2b2..d40c85b2f 100644
--- a/subsys/net/ip/l2/ieee802154/ieee802154.c
+++ b/subsys/net/ip/l2/ieee802154/ieee802154.c
@@ -108,7 +108,7 @@ static inline void ieee802154_acknowledge(struct net_if *iface,
net_buf_add(frag, IEEE802154_ACK_PKT_LENGTH);
- radio->tx(iface->dev, buf);
+ radio->tx(iface->dev, buf, frag);
}
net_nbuf_unref(buf);
diff --git a/subsys/net/ip/l2/ieee802154/ieee802154_radio_aloha.c b/subsys/net/ip/l2/ieee802154/ieee802154_radio_aloha.c
index 21125bf37..c519c25e2 100644
--- a/subsys/net/ip/l2/ieee802154/ieee802154_radio_aloha.c
+++ b/subsys/net/ip/l2/ieee802154/ieee802154_radio_aloha.c
@@ -20,7 +20,8 @@
#include "ieee802154_radio_utils.h"
static inline int aloha_tx_fragment(struct net_if *iface,
- struct net_buf *buf)
+ struct net_buf *buf,
+ struct net_buf *frag)
{
uint8_t retries = CONFIG_NET_L2_IEEE802154_RADIO_TX_RETRIES;
struct ieee802154_context *ctx = net_if_l2_data(iface);
@@ -28,12 +29,12 @@ static inline int aloha_tx_fragment(struct net_if *iface,
const struct ieee802154_radio_api *radio = iface->dev->driver_api;
int ret = -EIO;
- NET_DBG("frag %p", buf->frags);
+ NET_DBG("frag %p", frag);
while (retries) {
retries--;
- ret = radio->tx(iface->dev, buf);
+ ret = radio->tx(iface->dev, buf, frag);
if (ret) {
continue;
}
diff --git a/subsys/net/ip/l2/ieee802154/ieee802154_radio_csma_ca.c b/subsys/net/ip/l2/ieee802154/ieee802154_radio_csma_ca.c
index f87264d74..600e88126 100644
--- a/subsys/net/ip/l2/ieee802154/ieee802154_radio_csma_ca.c
+++ b/subsys/net/ip/l2/ieee802154/ieee802154_radio_csma_ca.c
@@ -23,7 +23,8 @@
#include "ieee802154_radio_utils.h"
static inline int csma_ca_tx_fragment(struct net_if *iface,
- struct net_buf *buf)
+ struct net_buf *buf,
+ struct net_buf *frag)
{
const uint8_t max_bo = CONFIG_NET_L2_IEEE802154_RADIO_CSMA_CA_MAX_BO;
const uint8_t max_be = CONFIG_NET_L2_IEEE802154_RADIO_CSMA_CA_MAX_BE;
@@ -35,7 +36,7 @@ static inline int csma_ca_tx_fragment(struct net_if *iface,
uint8_t nb = 0;
int ret = -EIO;
- NET_DBG("frag %p", buf->frags);
+ NET_DBG("frag %p", frag);
loop:
while (retries) {
@@ -60,7 +61,7 @@ loop:
}
}
- ret = radio->tx(iface->dev, buf);
+ ret = radio->tx(iface->dev, buf, frag);
if (ret) {
continue;
}
diff --git a/subsys/net/ip/l2/ieee802154/ieee802154_radio_utils.h b/subsys/net/ip/l2/ieee802154/ieee802154_radio_utils.h
index 766e999d5..e1a9f0e88 100644
--- a/subsys/net/ip/l2/ieee802154/ieee802154_radio_utils.h
+++ b/subsys/net/ip/l2/ieee802154/ieee802154_radio_utils.h
@@ -8,7 +8,8 @@
#define __IEEE802154_RADIO_UTILS_H__
typedef int (ieee802154_radio_tx_frag_t)(struct net_if *iface,
- struct net_buf *buf);
+ struct net_buf *buf,
+ struct net_buf *frag);
static inline bool prepare_for_ack(struct ieee802154_context *ctx,
struct net_buf *buf)
@@ -63,12 +64,12 @@ static inline int tx_buffer_fragments(struct net_if *iface,
frag = buf->frags;
while (frag) {
- ret = tx_func(iface, buf);
+ ret = tx_func(iface, buf, frag);
if (ret) {
break;
}
- frag = net_buf_frag_del(buf, frag);
+ frag = frag->frags;
}
if (!ret) {
diff --git a/tests/net/ieee802154/l2/src/ieee802154_fake_driver.c b/tests/net/ieee802154/l2/src/ieee802154_fake_driver.c
index e395ba018..a65298b16 100644
--- a/tests/net/ieee802154/l2/src/ieee802154_fake_driver.c
+++ b/tests/net/ieee802154/l2/src/ieee802154_fake_driver.c
@@ -75,7 +75,9 @@ static inline void insert_frag_dummy_way(struct net_buf *buf)
}
}
-static int fake_tx(struct device *dev, struct net_buf *buf)
+static int fake_tx(struct device *dev,
+ struct net_buf *buf,
+ struct net_buf *frag)
{
TC_PRINT("Sending buffer %p - length %zu\n",
buf, net_buf_frags_len(buf));