diff --git a/include/net/net_if.h b/include/net/net_if.h index b9a98507009..c4b90d1b8da 100644 --- a/include/net/net_if.h +++ b/include/net/net_if.h @@ -469,6 +469,14 @@ struct net_if { /** Network interface instance configuration */ struct net_if_config config; + +#if defined(CONFIG_NET_POWER_MANAGEMENT) + /** Keep track of packets pending in traffic queues. This is + * needed to avoid putting network device driver to sleep if + * there are packets waiting to be sent. + */ + int tx_pending; +#endif } __net_if_align; /** @@ -2101,6 +2109,26 @@ void net_if_unset_promisc(struct net_if *iface); */ bool net_if_is_promisc(struct net_if *iface); +/** + * @brief Check if there are any pending TX network data for a given network + * interface. + * + * @param iface Pointer to network interface + * + * @return True if there are pending TX network packets for this network + * interface, False otherwise. + */ +static inline bool net_if_are_pending_tx_packets(struct net_if *iface) +{ +#if defined(CONFIG_NET_POWER_MANAGEMENT) + return !!iface->tx_pending; +#else + ARG_UNUSED(iface); + + return false; +#endif +} + /** @cond INTERNAL_HIDDEN */ struct net_if_api { void (*init)(struct net_if *iface); diff --git a/subsys/net/ip/net_if.c b/subsys/net/ip/net_if.c index 4f67ea4bdbf..d54c7aac78f 100644 --- a/subsys/net/ip/net_if.c +++ b/subsys/net/ip/net_if.c @@ -260,11 +260,18 @@ static bool net_if_tx(struct net_if *iface, struct net_pkt *pkt) static void process_tx_packet(struct k_work *work) { + struct net_if *iface; struct net_pkt *pkt; pkt = CONTAINER_OF(work, struct net_pkt, work); - net_if_tx(net_pkt_iface(pkt), pkt); + iface = net_pkt_iface(pkt); + + net_if_tx(iface, pkt); + +#if defined(CONFIG_NET_POWER_MANAGEMENT) + iface->tx_pending--; +#endif } void net_if_queue_tx(struct net_if *iface, struct net_pkt *pkt) @@ -282,7 +289,16 @@ void net_if_queue_tx(struct net_if *iface, struct net_pkt *pkt) NET_DBG("TC %d with prio %d pkt %p", tc, prio, pkt); #endif - net_tc_submit_to_tx_queue(tc, pkt); +#if defined(CONFIG_NET_POWER_MANAGEMENT) + iface->tx_pending++; +#endif + + if (!net_tc_submit_to_tx_queue(tc, pkt)) { +#if defined(CONFIG_NET_POWER_MANAGEMENT) + iface->tx_pending-- +#endif + ; + } } void net_if_stats_reset(struct net_if *iface)