Skip to content
Permalink
Browse files

net: ethernet: Add carrier detection to L2

Add net_eth_carrier_on() and net_eth_carrier_off() functions that
can be called by ethernet device driver when it detects that carrier
is lost or found.

Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
  • Loading branch information...
jukkar authored and nashif committed Jun 4, 2018
1 parent 3122112 commit b93d29df564b8e0baa1c5933792baa979d99c724
Showing with 93 additions and 7 deletions.
  1. +33 −1 include/net/ethernet.h
  2. +60 −6 subsys/net/ip/l2/ethernet/ethernet.c
@@ -164,16 +164,32 @@ struct ethernet_context {
* of network interfaces.
*/
ATOMIC_DEFINE(interfaces, NET_VLAN_MAX_COUNT);
#endif

struct {
/** Carrier ON/OFF handler worker. This is used to create
* network interface UP/DOWN event when ethernet L2 driver
* notices carrier ON/OFF situation. We must not create another
* network management event from inside management handler thus
* we use worker thread to trigger the UP/DOWN event.
*/
struct k_work work;

/** Network interface that is detecting carrier ON/OFF event.
*/
struct net_if *iface;
} carrier_mgmt;

#if defined(CONFIG_NET_VLAN)
/** Flag that tells whether how many VLAN tags are enabled for this
* context. The same information can be dug from the vlan array but
* this saves some time in RX path.
*/
s8_t vlan_enabled;
#endif

/** Is this context already initialized */
bool is_init;
#endif
};

#define ETHERNET_L2_CTX_TYPE struct ethernet_context
@@ -376,6 +392,22 @@ struct net_eth_hdr *net_eth_fill_header(struct ethernet_context *ctx,
u8_t *src,
u8_t *dst);

/**
* @brief Inform ethernet L2 driver that ethernet carrier is detected.
* This happens when cable is connected.
*
* @param iface Network interface
*/
void net_eth_carrier_on(struct net_if *iface);

/**
* @brief Inform ethernet L2 driver that ethernet carrier was lost.
* This happens when cable is disconnected.
*
* @param iface Network interface
*/
void net_eth_carrier_off(struct net_if *iface);

#ifdef __cplusplus
}
#endif
@@ -12,7 +12,9 @@
#include <net/net_core.h>
#include <net/net_l2.h>
#include <net/net_if.h>
#include <net/net_mgmt.h>
#include <net/ethernet.h>
#include <net/ethernet_mgmt.h>
#include <net/arp.h>

#include "net_private.h"
@@ -746,18 +748,72 @@ int net_eth_vlan_disable(struct net_if *iface, u16_t tag)
NET_L2_INIT(ETHERNET_L2, ethernet_recv, ethernet_send, ethernet_reserve,
ethernet_enable);

static void carrier_on(struct k_work *work)
{
struct ethernet_context *ctx = CONTAINER_OF(work,
struct ethernet_context,
carrier_mgmt.work);

NET_DBG("Carrier ON for interface %p", ctx->carrier_mgmt.iface);

ethernet_mgmt_raise_carrier_on_event(ctx->carrier_mgmt.iface);

net_if_up(ctx->carrier_mgmt.iface);
}

static void carrier_off(struct k_work *work)
{
struct ethernet_context *ctx = CONTAINER_OF(work,
struct ethernet_context,
carrier_mgmt.work);

NET_DBG("Carrier OFF for interface %p", ctx->carrier_mgmt.iface);

ethernet_mgmt_raise_carrier_off_event(ctx->carrier_mgmt.iface);

net_if_carrier_down(ctx->carrier_mgmt.iface);
}

static void handle_carrier(struct ethernet_context *ctx,
struct net_if *iface,
k_work_handler_t handler)
{
k_work_init(&ctx->carrier_mgmt.work, handler);

ctx->carrier_mgmt.iface = iface;

k_work_submit(&ctx->carrier_mgmt.work);
}

void net_eth_carrier_on(struct net_if *iface)
{
struct ethernet_context *ctx = net_if_l2_data(iface);

handle_carrier(ctx, iface, carrier_on);
}

void net_eth_carrier_off(struct net_if *iface)
{
struct ethernet_context *ctx = net_if_l2_data(iface);

handle_carrier(ctx, iface, carrier_off);
}

void ethernet_init(struct net_if *iface)
{
#if defined(CONFIG_NET_VLAN)
struct ethernet_context *ctx = net_if_l2_data(iface);

#if defined(CONFIG_NET_VLAN)
int i;
#endif

NET_DBG("Initializing Ethernet L2 %p for iface %p", ctx, iface);

#if defined(CONFIG_NET_VLAN)
if (!(net_eth_get_hw_capabilities(iface) & ETHERNET_HW_VLAN)) {
return;
}

NET_DBG("Initializing Ethernet L2 %p for iface %p", ctx, iface);

for (i = 0; i < CONFIG_NET_VLAN_COUNT; i++) {
if (!ctx->vlan[i].iface) {
NET_DBG("[%d] alloc ctx %p iface %p", i, ctx, iface);
@@ -771,9 +827,7 @@ void ethernet_init(struct net_if *iface)
break;
}
}
#endif

ctx->is_init = true;
#else
ARG_UNUSED(iface);
#endif
}

0 comments on commit b93d29d

Please sign in to comment.
You can’t perform that action at this time.