From 80917ec16fd22d239fca5b885983b3e7abf7c4de Mon Sep 17 00:00:00 2001 From: Tomasz Bursztyka Date: Tue, 25 Feb 2020 09:42:35 +0100 Subject: [PATCH] net: Add preliminaly support for suspending/resuming a net interface Such state needs to be set _from_ the PM API functions and not the other way round. So if a network device driver does not support such API, it will not be able to set the core net_if on PM state, obviously. Currently, these functions only set/unset NET_IF_SUSPENDED flag. More logic will be added later, to decide whether the net_if can be actually set to suspend mode or not and also to take care of all timers related to the interface. Signed-off-by: Tomasz Bursztyka --- include/net/net_if.h | 25 +++++++++++++++++++++++++ subsys/net/Kconfig | 7 +++++++ subsys/net/ip/net_if.c | 31 ++++++++++++++++++++++++++++++- 3 files changed, 62 insertions(+), 1 deletion(-) diff --git a/include/net/net_if.h b/include/net/net_if.h index c4b90d1b8da..c07379d164e 100644 --- a/include/net/net_if.h +++ b/include/net/net_if.h @@ -194,6 +194,9 @@ enum net_if_flag { */ NET_IF_NO_AUTO_START, + /** Power management specific: interface is being suspended */ + NET_IF_SUSPENDED, + /** @cond INTERNAL_HIDDEN */ /* Total number of flags - must be at the end of the enum */ NET_IF_NUM_FLAGS @@ -2129,6 +2132,28 @@ static inline bool net_if_are_pending_tx_packets(struct net_if *iface) #endif } +#ifdef CONFIG_NET_POWER_MANAGEMENT + +/** + * @brief Suspend a network interface from a power management perspective + * + * @param iface Pointer to network interface + * + * @return 0 on success, or -EALREADY/-EBUSY as possible errors. + */ +int net_if_suspend(struct net_if *iface); + +/** + * @brief Resume a network interface from a power management perspective + * + * @param iface Pointer to network interface + * + * @return 0 on success, or -EALREADY as a possible error. + */ +int net_if_resume(struct net_if *iface); + +#endif /* CONFIG_NET_POWER_MANAGEMENT */ + /** @cond INTERNAL_HIDDEN */ struct net_if_api { void (*init)(struct net_if *iface); diff --git a/subsys/net/Kconfig b/subsys/net/Kconfig index acbe27ba796..e0fde627eca 100644 --- a/subsys/net/Kconfig +++ b/subsys/net/Kconfig @@ -73,6 +73,13 @@ config NETWORKING if NETWORKING +# Such option should not be configured manually but by device drivers +# which supports PM properly. +config NET_POWER_MANAGEMENT + bool + default n + depends on DEVICE_POWER_MANAGEMENT + source "subsys/net/Kconfig.hostname" source "subsys/net/l2/Kconfig" diff --git a/subsys/net/ip/net_if.c b/subsys/net/ip/net_if.c index d54c7aac78f..c3afc166bdb 100644 --- a/subsys/net/ip/net_if.c +++ b/subsys/net/ip/net_if.c @@ -347,7 +347,8 @@ enum net_verdict net_if_send_data(struct net_if *iface, struct net_pkt *pkt) enum net_verdict verdict = NET_OK; int status = -EIO; - if (!net_if_flag_is_set(iface, NET_IF_UP)) { + if (!net_if_flag_is_set(iface, NET_IF_UP) || + net_if_flag_is_set(iface, NET_IF_SUSPENDED)) { /* Drop packet if interface is not up */ NET_WARN("iface %p is down", iface); verdict = NET_DROP; @@ -3623,6 +3624,34 @@ bool net_if_is_promisc(struct net_if *iface) return net_if_flag_is_set(iface, NET_IF_PROMISC); } +#ifdef CONFIG_NET_POWER_MANAGEMENT + +int net_if_suspend(struct net_if *iface) +{ + if (net_if_are_pending_tx_packets(iface)) { + return -EBUSY; + } + + if (net_if_flag_test_and_set(iface, NET_IF_SUSPENDED)) { + return -EALREADY; + } + + return 0; +} + +int net_if_resume(struct net_if *iface) +{ + if (!net_if_flag_is_set(iface, NET_IF_SUSPENDED)) { + return -EALREADY; + } + + net_if_flag_clear(iface, NET_IF_SUSPENDED); + + return 0; +} + +#endif /* CONFIG_NET_POWER_MANAGEMENT */ + #if defined(CONFIG_NET_PKT_TIMESTAMP_THREAD) static void net_tx_ts_thread(void) {