net/iface: Switch fully to a one-pass sending logic in net_if

Now instead of such path:

net_if_send_data -> L2's send -> net_if tx_queue -> net_if_tx -> driver
net_if's send

It will be:

net_if_send_data -> net_if tx_queue -> net_if_tx -> L2's send -> driver
net_if's send

Only Ethernet is adapted, but 15.4 and bt will follow up.
All Ethernet drivers are made compatible with that new scheme also.

Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
This commit is contained in:
Tomasz Bursztyka 2018-06-26 14:51:05 +02:00 committed by Anas Nashif
commit 9464ec3343
12 changed files with 72 additions and 112 deletions

View file

@ -42,9 +42,9 @@ static inline void eth_write(u32_t base_addr, u32_t offset,
sys_write32(val, base_addr + offset);
}
static void eth_rx(struct device *port)
static void eth_rx(struct device *dev)
{
struct eth_runtime *context = port->driver_data;
struct eth_runtime *context = dev->driver_data;
struct net_pkt *pkt;
u32_t frm_len;
int r;
@ -164,10 +164,9 @@ static void eth_tx_data(struct eth_runtime *context, u8_t *data, u16_t len)
* from each fragment's data pointer. This procedure might yield to
* other threads while waiting for the DMA transfer to finish.
*/
static int eth_tx(struct net_if *iface, struct net_pkt *pkt)
static int eth_tx(struct device *dev, struct net_pkt *pkt)
{
struct device *port = net_if_get_device(iface);
struct eth_runtime *context = port->driver_data;
struct eth_runtime *context = dev->driver_data;
/* Ensure we're clear to transmit. */
eth_tx_spin_wait(context);
@ -185,13 +184,12 @@ static int eth_tx(struct net_if *iface, struct net_pkt *pkt)
}
}
net_pkt_unref(pkt);
return 0;
}
static void eth_dw_isr(struct device *port)
static void eth_dw_isr(struct device *dev)
{
struct eth_runtime *context = port->driver_data;
struct eth_runtime *context = dev->driver_data;
#ifdef CONFIG_SHARED_IRQ
u32_t int_status;
@ -205,7 +203,7 @@ static void eth_dw_isr(struct device *port)
return;
}
#endif
eth_rx(port);
eth_rx(dev);
/* Acknowledge the interrupt. */
eth_write(context->base_addr, REG_ADDR_STATUS,
@ -238,9 +236,9 @@ static inline int eth_setup(struct device *dev)
static int eth_initialize_internal(struct net_if *iface)
{
struct device *port = net_if_get_device(iface);
struct eth_runtime *context = port->driver_data;
const struct eth_config *config = port->config->config_info;
struct device *dev = net_if_get_device(iface);
struct eth_runtime *context = dev->driver_data;
const struct eth_config *config = dev->config->config_info;
u32_t base_addr;
context->iface = iface;
@ -317,7 +315,7 @@ static int eth_initialize_internal(struct net_if *iface)
LOG_INF("Enabled 100M full-duplex mode");
config->config_func(port);
config->config_func(dev);
return 0;
}
@ -340,16 +338,16 @@ static enum ethernet_hw_caps eth_dw_get_capabilities(struct device *dev)
static const struct ethernet_api api_funcs = {
.iface_api.init = eth_initialize,
.iface_api.send = eth_tx,
.get_capabilities = eth_dw_get_capabilities,
.send = eth_tx,
};
/* Bindings to the plaform */
#if CONFIG_ETH_DW_0
static void eth_config_0_irq(struct device *port)
static void eth_config_0_irq(struct device *dev)
{
const struct eth_config *config = port->config->config_info;
const struct eth_config *config = dev->config->config_info;
struct device *shared_irq_dev;
#ifdef CONFIG_ETH_DW_0_IRQ_DIRECT
@ -360,8 +358,8 @@ static void eth_config_0_irq(struct device *port)
#elif defined(CONFIG_ETH_DW_0_IRQ_SHARED)
shared_irq_dev = device_get_binding(config->shared_irq_dev_name);
__ASSERT(shared_irq_dev != NULL, "Failed to get eth_dw device binding");
shared_irq_isr_register(shared_irq_dev, (isr_t)eth_dw_isr, port);
shared_irq_enable(shared_irq_dev, port);
shared_irq_isr_register(shared_irq_dev, (isr_t)eth_dw_isr, dev);
shared_irq_enable(shared_irq_dev, dev);
#endif
}

View file

@ -82,19 +82,12 @@ static int e1000_tx(struct e1000_dev *dev, void *data, size_t data_len)
return (dev->tx.sta & TDESC_STA_DD) ? 0 : -EIO;
}
static int e1000_send(struct net_if *iface, struct net_pkt *pkt)
static int e1000_send(struct device *device, struct net_pkt *pkt)
{
struct e1000_dev *dev = net_if_get_device(iface)->driver_data;
struct e1000_dev *dev = device->driver_data;
size_t len = e1000_linearize(pkt, dev->txb, sizeof(dev->txb));
int err = e1000_tx(dev, dev->txb, len);
if (!err) {
net_pkt_unref(pkt);
}
return err;
return e1000_tx(dev, dev->txb, len);
}
static struct net_pkt *e1000_rx(struct e1000_dev *dev)
@ -235,8 +228,8 @@ static struct e1000_dev e1000_dev = {
static const struct ethernet_api e1000_api = {
.iface_api.init = e1000_init,
.iface_api.send = e1000_send,
.get_capabilities = e1000_caps,
.send = e1000_send,
};
NET_DEVICE_INIT(eth_e1000,

View file

@ -405,9 +405,8 @@ static void eth_enc28j60_init_phy(struct device *dev)
}
}
static int eth_enc28j60_tx(struct net_if *iface, struct net_pkt *pkt)
static int eth_enc28j60_tx(struct device *dev, struct net_pkt *pkt)
{
struct device *dev = net_if_get_device(iface);
struct eth_enc28j60_runtime *context = dev->driver_data;
u16_t len = net_pkt_ll_reserve(pkt) + net_pkt_get_len(pkt);
u16_t tx_bufaddr = ENC28J60_TXSTART;
@ -487,8 +486,6 @@ static int eth_enc28j60_tx(struct net_if *iface, struct net_pkt *pkt)
return -EIO;
}
net_pkt_unref(pkt);
LOG_DBG("Tx successful");
return 0;
@ -672,9 +669,9 @@ static void eth_enc28j60_iface_init(struct net_if *iface)
static const struct ethernet_api api_funcs = {
.iface_api.init = eth_enc28j60_iface_init,
.iface_api.send = eth_enc28j60_tx,
.get_capabilities = eth_enc28j60_get_capabilities,
.send = eth_enc28j60_tx,
};
static int eth_enc28j60_init(struct device *dev)

View file

@ -449,9 +449,9 @@ static bool eth_get_ptp_data(struct net_if *iface, struct net_pkt *pkt,
}
#endif /* CONFIG_PTP_CLOCK_MCUX */
static int eth_tx(struct net_if *iface, struct net_pkt *pkt)
static int eth_tx(struct device *dev, struct net_pkt *pkt)
{
struct eth_context *context = net_if_get_device(iface)->driver_data;
struct eth_context *context = dev->driver_data;
const struct net_buf *frag;
u8_t *dst;
status_t status;
@ -501,7 +501,7 @@ static int eth_tx(struct net_if *iface, struct net_pkt *pkt)
total_len);
#if defined(CONFIG_PTP_CLOCK_MCUX)
timestamped_frame = eth_get_ptp_data(iface, pkt, NULL);
timestamped_frame = eth_get_ptp_data(net_pkt_iface(pkt), pkt, NULL);
if (timestamped_frame) {
if (!status) {
ts_tx_pkt[ts_tx_wr] = net_pkt_ref(pkt);
@ -523,8 +523,6 @@ static int eth_tx(struct net_if *iface, struct net_pkt *pkt)
return -1;
}
net_pkt_unref(pkt);
return 0;
}
@ -929,14 +927,12 @@ static struct device *eth_mcux_get_ptp_clock(struct device *dev)
#endif
static const struct ethernet_api api_funcs = {
.iface_api.init = eth_iface_init,
.iface_api.send = eth_tx,
.get_capabilities = eth_mcux_get_capabilities,
.iface_api.init = eth_iface_init,
#if defined(CONFIG_PTP_CLOCK_MCUX)
.get_ptp_clock = eth_mcux_get_ptp_clock,
.get_ptp_clock = eth_mcux_get_ptp_clock,
#endif
.get_capabilities = eth_mcux_get_capabilities,
.send = eth_tx,
};
#if defined(CONFIG_PTP_CLOCK_MCUX)

View file

@ -107,11 +107,6 @@ static struct k_thread rx_thread_data;
/* TODO: support multiple interfaces */
static struct eth_context eth_context_data;
static struct eth_context *get_context(struct net_if *iface)
{
return net_if_get_device(iface)->driver_data;
}
#if defined(CONFIG_NET_GPTP)
static bool need_timestamping(struct gptp_hdr *hdr)
{
@ -205,9 +200,9 @@ static void update_gptp(struct net_if *iface, struct net_pkt *pkt,
#define update_gptp(iface, pkt, send)
#endif /* CONFIG_NET_GPTP */
static int eth_send(struct net_if *iface, struct net_pkt *pkt)
static int eth_send(struct device *dev, struct net_pkt *pkt)
{
struct eth_context *ctx = get_context(iface);
struct eth_context *ctx = dev->driver_data;
struct net_buf *frag;
int count = 0;
int ret;
@ -225,29 +220,27 @@ static int eth_send(struct net_if *iface, struct net_pkt *pkt)
frag = frag->frags;
}
eth_stats_update_bytes_tx(iface, count);
eth_stats_update_pkts_tx(iface);
eth_stats_update_bytes_tx(net_pkt_iface(pkt), count);
eth_stats_update_pkts_tx(net_pkt_iface(pkt));
if (IS_ENABLED(CONFIG_NET_STATISTICS_ETHERNET)) {
if (net_eth_is_addr_broadcast(
&((struct net_eth_hdr *)NET_ETH_HDR(pkt))->dst)) {
eth_stats_update_broadcast_tx(iface);
eth_stats_update_broadcast_tx(net_pkt_iface(pkt));
} else if (net_eth_is_addr_multicast(
&((struct net_eth_hdr *)
NET_ETH_HDR(pkt))->dst)) {
eth_stats_update_multicast_tx(iface);
eth_stats_update_multicast_tx(net_pkt_iface(pkt));
}
}
update_gptp(iface, pkt, true);
update_gptp(net_pkt_iface(pkt), pkt, true);
LOG_DBG("Send pkt %p len %d", pkt, count);
ret = eth_write_data(ctx->dev_fd, ctx->send, count);
if (ret < 0) {
LOG_DBG("Cannot send pkt %p (%d)", pkt, ret);
} else {
net_pkt_unref(pkt);
}
return ret < 0 ? ret : 0;
@ -565,12 +558,12 @@ static int eth_stop_device(struct device *dev)
static const struct ethernet_api eth_if_api = {
.iface_api.init = eth_iface_init,
.iface_api.send = eth_send,
.get_capabilities = eth_posix_native_get_capabilities,
.set_config = set_config,
.start = eth_start_device,
.stop = eth_stop_device,
.send = eth_send,
#if defined(CONFIG_NET_VLAN)
.vlan_setup = vlan_setup,

View file

@ -1290,9 +1290,8 @@ static int priority2queue(enum net_priority priority)
}
#endif
static int eth_tx(struct net_if *iface, struct net_pkt *pkt)
static int eth_tx(struct device *dev, struct net_pkt *pkt)
{
struct device *const dev = net_if_get_device(iface);
const struct eth_sam_dev_cfg *const cfg = DEV_CFG(dev);
struct eth_sam_dev_data *const dev_data = DEV_DATA(dev);
Gmac *gmac = cfg->regs;
@ -1405,6 +1404,9 @@ static int eth_tx(struct net_if *iface, struct net_pkt *pkt)
irq_unlock(key);
/* pkt is internally queued, so it requires to hold a reference */
net_pkt_ref(pkt);
/* Start transmission */
gmac->GMAC_NCR |= GMAC_NCR_TSTART;
@ -1864,11 +1866,11 @@ static struct device *eth_sam_gmac_get_ptp_clock(struct device *dev)
static const struct ethernet_api eth_api = {
.iface_api.init = eth0_iface_init,
.iface_api.send = eth_tx,
.get_capabilities = eth_sam_gmac_get_capabilities,
.set_config = eth_sam_gmac_set_config,
.get_config = eth_sam_gmac_get_config,
.send = eth_tx,
#if defined(CONFIG_PTP_CLOCK_SAM_GMAC)
.get_ptp_clock = eth_sam_gmac_get_ptp_clock,

View file

@ -54,10 +54,9 @@ static inline void disable_mcast_filter(ETH_HandleTypeDef *heth)
heth->Instance->MACFFR = tmp;
}
static int eth_tx(struct net_if *iface, struct net_pkt *pkt)
static int eth_tx(struct device *dev, struct net_pkt *pkt)
{
struct device *dev;
struct eth_stm32_hal_dev_data *dev_data;
struct eth_stm32_hal_dev_data *dev_data = DEV_DATA(dev);
ETH_HandleTypeDef *heth;
u8_t *dma_buffer;
int res;
@ -65,13 +64,8 @@ static int eth_tx(struct net_if *iface, struct net_pkt *pkt)
u16_t total_len;
__IO ETH_DMADescTypeDef *dma_tx_desc;
__ASSERT_NO_MSG(iface != NULL);
__ASSERT_NO_MSG(pkt != NULL);
__ASSERT_NO_MSG(pkt->frags != NULL);
dev = net_if_get_device(iface);
dev_data = DEV_DATA(dev);
__ASSERT_NO_MSG(dev != NULL);
__ASSERT_NO_MSG(dev_data != NULL);
@ -122,8 +116,6 @@ static int eth_tx(struct net_if *iface, struct net_pkt *pkt)
goto error;
}
net_pkt_unref(pkt);
res = 0;
error:
k_mutex_unlock(&dev_data->tx_mutex);
@ -387,9 +379,9 @@ static enum ethernet_hw_caps eth_stm32_hal_get_capabilities(struct device *dev)
static const struct ethernet_api eth_api = {
.iface_api.init = eth_iface_init,
.iface_api.send = eth_tx,
.get_capabilities = eth_stm32_hal_get_capabilities,
.send = eth_tx,
};
static struct device DEVICE_NAME_GET(eth0_stm32_hal);

View file

@ -538,8 +538,6 @@ static inline bool net_eth_get_vlan_status(struct net_if *iface)
}
#endif /* CONFIG_NET_VLAN */
int net_eth_send(struct net_if *iface, struct net_pkt *pkt);
/**
* @brief Inform ethernet L2 driver that ethernet carrier is detected.
* This happens when cable is connected.

View file

@ -49,8 +49,9 @@ struct net_l2 {
* This function is used by net core to push a packet to lower layer
* (interface's L2), which in turn might work on the packet relevantly.
* (adding proper header etc...)
* Returns a negative error code, or the number of bytes sent otherwise.
*/
enum net_verdict (*send)(struct net_if *iface, struct net_pkt *pkt);
int (*send)(struct net_if *iface, struct net_pkt *pkt);
/**
* This function is used to get the amount of bytes the net core should

View file

@ -148,7 +148,6 @@ static inline void net_context_send_cb(struct net_context *context,
static bool net_if_tx(struct net_if *iface, struct net_pkt *pkt)
{
const struct net_if_api *api = net_if_get_device(iface)->driver_api;
struct net_linkaddr *dst;
struct net_context *context;
void *context_token;
@ -170,7 +169,7 @@ static bool net_if_tx(struct net_if *iface, struct net_pkt *pkt)
net_pkt_set_queued(pkt, false);
}
status = api->send(iface, pkt);
status = net_if_l2(iface)->send(iface, pkt);
} else {
/* Drop packet if interface is not up */
NET_WARN("iface %p is down", iface);
@ -184,7 +183,7 @@ static bool net_if_tx(struct net_if *iface, struct net_pkt *pkt)
net_pkt_unref(pkt);
} else {
net_stats_update_bytes_sent(iface, pkt->total_pkt_len);
net_stats_update_bytes_sent(iface, status);
}
if (context) {
@ -252,8 +251,8 @@ enum net_verdict net_if_send_data(struct net_if *iface, struct net_pkt *pkt)
{
struct net_context *context = net_pkt_context(pkt);
struct net_linkaddr *dst = net_pkt_lladdr_dst(pkt);
enum net_verdict verdict = NET_OK;
void *token = net_pkt_token(pkt);
enum net_verdict verdict;
int status = -EIO;
if (!atomic_test_bit(iface->if_dev->flags, NET_IF_UP)) {
@ -280,7 +279,7 @@ enum net_verdict net_if_send_data(struct net_if *iface, struct net_pkt *pkt)
* additional checks, so let the packet through.
*/
if (net_if_l2(iface) == &NET_L2_GET_NAME(DUMMY)) {
goto send;
goto done;
}
#endif
@ -297,14 +296,8 @@ enum net_verdict net_if_send_data(struct net_if *iface, struct net_pkt *pkt)
}
#endif
#if defined(CONFIG_NET_LOOPBACK)
send:
#endif
verdict = net_if_l2(iface)->send(iface, pkt);
done:
/* The L2 send() function can return
* NET_OK in which case packet was sent successfully. In this case
/* NET_OK in which case packet has checked successfully. In this case
* the net_context callback is called after successful delivery in
* net_if_tx_thread().
*
@ -315,15 +308,19 @@ done:
* This can happen for example if we need to do IPv6 ND to figure
* out link layer address.
*/
if (context && verdict == NET_DROP) {
NET_DBG("Calling context send cb %p token %p verdict %d",
context, token, verdict);
if (verdict == NET_DROP) {
if (context) {
NET_DBG("Calling ctx send cb %p token %p verdict %d",
context, token, verdict);
net_context_send_cb(context, token, status);
}
net_context_send_cb(context, token, status);
}
if (verdict == NET_DROP && dst->addr) {
net_if_call_link_cb(iface, dst, status);
if (dst->addr) {
net_if_call_link_cb(iface, dst, status);
}
} else if (verdict == NET_OK) {
/* Packet is ready to be sent by L2, let's queue */
net_if_queue_tx(iface, pkt);
}
return verdict;

View file

@ -464,15 +464,7 @@ static struct net_buf *ethernet_fill_header(struct ethernet_context *ctx,
return hdr_frag;
}
static enum net_verdict ethernet_send(struct net_if *iface,
struct net_pkt *pkt)
{
net_if_queue_tx(iface, pkt);
return NET_OK;
}
int net_eth_send(struct net_if *iface, struct net_pkt *pkt)
static int ethernet_send(struct net_if *iface, struct net_pkt *pkt)
{
const struct ethernet_api *api = net_if_get_device(iface)->driver_api;
struct ethernet_context *ctx = net_if_l2_data(iface);
@ -538,6 +530,7 @@ int net_eth_send(struct net_if *iface, struct net_pkt *pkt)
ret = api->send(net_if_get_device(iface), pkt);
if (!ret) {
ret = net_pkt_get_len(pkt);
net_pkt_unref(pkt);
}

View file

@ -36,10 +36,12 @@ static struct __netusb {
static u8_t interface_data[300];
#endif
static int netusb_send(struct net_if *iface, struct net_pkt *pkt)
static int netusb_send(struct device *dev, struct net_pkt *pkt)
{
int ret;
ARG_UNUSED(dev);
LOG_DBG("Send pkt, len %u", net_pkt_get_len(pkt));
if (!netusb_enabled()) {
@ -52,7 +54,6 @@ static int netusb_send(struct net_if *iface, struct net_pkt *pkt)
return ret;
}
net_pkt_unref(pkt);
return 0;
}
@ -222,11 +223,10 @@ static void netusb_init(struct net_if *iface)
}
static const struct ethernet_api netusb_api_funcs = {
.iface_api = {
.init = netusb_init,
.send = netusb_send,
},
.iface_api.init = netusb_init,
.get_capabilities = NULL,
.send = netusb_send,
};
static int netusb_init_dev(struct device *dev)