diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index e0b279b6f7f8..a129d5903766 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -1451,6 +1452,7 @@ struct hdd_adapter { /* BITMAP indicating pause reason */ uint32_t pause_map; + uint32_t subqueue_pause_map; spinlock_t pause_map_lock; qdf_time_t start_time; qdf_time_t last_time; diff --git a/core/hdd/src/wlan_hdd_tx_rx.c b/core/hdd/src/wlan_hdd_tx_rx.c index d685268e1f7f..645b40897d31 100644 --- a/core/hdd/src/wlan_hdd_tx_rx.c +++ b/core/hdd/src/wlan_hdd_tx_rx.c @@ -2760,6 +2760,7 @@ const char *hdd_action_type_to_string(enum netif_action_type action) CASE_RETURN_STRING(WLAN_NETIF_VO_QUEUE_OFF); CASE_RETURN_STRING(WLAN_NETIF_VI_QUEUE_ON); CASE_RETURN_STRING(WLAN_NETIF_VI_QUEUE_OFF); + CASE_RETURN_STRING(WLAN_NETIF_BE_BK_QUEUE_ON); CASE_RETURN_STRING(WLAN_NETIF_BE_BK_QUEUE_OFF); CASE_RETURN_STRING(WLAN_WAKE_NON_PRIORITY_QUEUE); CASE_RETURN_STRING(WLAN_STOP_NON_PRIORITY_QUEUE); @@ -2790,6 +2791,7 @@ static void wlan_hdd_update_queue_oper_stats(struct hdd_adapter *adapter, case WLAN_START_ALL_NETIF_QUEUE: case WLAN_WAKE_ALL_NETIF_QUEUE: case WLAN_START_ALL_NETIF_QUEUE_N_CARRIER: + case WLAN_NETIF_BE_BK_QUEUE_ON: case WLAN_NETIF_VI_QUEUE_ON: case WLAN_NETIF_VO_QUEUE_ON: case WLAN_NETIF_PRIORITY_QUEUE_ON: @@ -3021,65 +3023,99 @@ void wlan_hdd_netif_queue_control(struct hdd_adapter *adapter, case WLAN_NETIF_PRIORITY_QUEUE_ON: spin_lock_bh(&adapter->pause_map_lock); - temp_map = adapter->pause_map; - adapter->pause_map &= ~(1 << reason); - netif_wake_subqueue(adapter->dev, HDD_LINUX_AC_HI_PRIO); - wlan_hdd_update_pause_time(adapter, temp_map); + if (reason == WLAN_DATA_FLOW_CTRL_PRI) { + temp_map = adapter->subqueue_pause_map; + adapter->subqueue_pause_map &= ~(1 << reason); + } else { + temp_map = adapter->pause_map; + adapter->pause_map &= ~(1 << reason); + } + if (!adapter->pause_map) { + netif_wake_subqueue(adapter->dev, HDD_LINUX_AC_HI_PRIO); + wlan_hdd_update_pause_time(adapter, temp_map); + } spin_unlock_bh(&adapter->pause_map_lock); break; case WLAN_NETIF_PRIORITY_QUEUE_OFF: spin_lock_bh(&adapter->pause_map_lock); - netif_stop_subqueue(adapter->dev, HDD_LINUX_AC_HI_PRIO); - wlan_hdd_update_txq_timestamp(adapter->dev); - wlan_hdd_update_unpause_time(adapter); - adapter->pause_map |= (1 << reason); + if (!adapter->pause_map) { + netif_stop_subqueue(adapter->dev, HDD_LINUX_AC_HI_PRIO); + wlan_hdd_update_txq_timestamp(adapter->dev); + wlan_hdd_update_unpause_time(adapter); + } + if (reason == WLAN_DATA_FLOW_CTRL_PRI) + adapter->subqueue_pause_map |= (1 << reason); + else + adapter->pause_map |= (1 << reason); spin_unlock_bh(&adapter->pause_map_lock); break; case WLAN_NETIF_BE_BK_QUEUE_OFF: spin_lock_bh(&adapter->pause_map_lock); - netif_stop_subqueue(adapter->dev, HDD_LINUX_AC_BK); - netif_stop_subqueue(adapter->dev, HDD_LINUX_AC_BE); - wlan_hdd_update_txq_timestamp(adapter->dev); - wlan_hdd_update_unpause_time(adapter); - adapter->pause_map |= (1 << reason); + if (!adapter->pause_map) { + netif_stop_subqueue(adapter->dev, HDD_LINUX_AC_BK); + netif_stop_subqueue(adapter->dev, HDD_LINUX_AC_BE); + wlan_hdd_update_txq_timestamp(adapter->dev); + wlan_hdd_update_unpause_time(adapter); + } + adapter->subqueue_pause_map |= (1 << reason); + spin_unlock_bh(&adapter->pause_map_lock); + break; + + case WLAN_NETIF_BE_BK_QUEUE_ON: + spin_lock_bh(&adapter->pause_map_lock); + temp_map = adapter->subqueue_pause_map; + adapter->subqueue_pause_map &= ~(1 << reason); + if (!adapter->pause_map) { + netif_wake_subqueue(adapter->dev, HDD_LINUX_AC_BK); + netif_wake_subqueue(adapter->dev, HDD_LINUX_AC_BE); + wlan_hdd_update_pause_time(adapter, temp_map); + } spin_unlock_bh(&adapter->pause_map_lock); break; case WLAN_NETIF_VI_QUEUE_OFF: spin_lock_bh(&adapter->pause_map_lock); - netif_stop_subqueue(adapter->dev, HDD_LINUX_AC_VI); - wlan_hdd_update_txq_timestamp(adapter->dev); - wlan_hdd_update_unpause_time(adapter); - adapter->pause_map |= (1 << reason); + if (!adapter->pause_map) { + netif_stop_subqueue(adapter->dev, HDD_LINUX_AC_VI); + wlan_hdd_update_txq_timestamp(adapter->dev); + wlan_hdd_update_unpause_time(adapter); + } + adapter->subqueue_pause_map |= (1 << reason); spin_unlock_bh(&adapter->pause_map_lock); break; case WLAN_NETIF_VI_QUEUE_ON: spin_lock_bh(&adapter->pause_map_lock); - temp_map = adapter->pause_map; - adapter->pause_map &= ~(1 << reason); - netif_wake_subqueue(adapter->dev, HDD_LINUX_AC_VI); - wlan_hdd_update_pause_time(adapter, temp_map); + temp_map = adapter->subqueue_pause_map; + adapter->subqueue_pause_map &= ~(1 << reason); + if (!adapter->pause_map) { + netif_wake_subqueue(adapter->dev, HDD_LINUX_AC_VI); + wlan_hdd_update_pause_time(adapter, temp_map); + } spin_unlock_bh(&adapter->pause_map_lock); break; case WLAN_NETIF_VO_QUEUE_OFF: spin_lock_bh(&adapter->pause_map_lock); - netif_stop_subqueue(adapter->dev, HDD_LINUX_AC_VO); - wlan_hdd_update_txq_timestamp(adapter->dev); - wlan_hdd_update_unpause_time(adapter); - adapter->pause_map |= (1 << reason); + if (!adapter->pause_map) { + netif_stop_subqueue(adapter->dev, HDD_LINUX_AC_VO); + wlan_hdd_update_txq_timestamp(adapter->dev); + wlan_hdd_update_unpause_time(adapter); + } + adapter->subqueue_pause_map |= (1 << reason); spin_unlock_bh(&adapter->pause_map_lock); break; case WLAN_NETIF_VO_QUEUE_ON: spin_lock_bh(&adapter->pause_map_lock); - temp_map = adapter->pause_map; - adapter->pause_map &= ~(1 << reason); - netif_wake_subqueue(adapter->dev, HDD_LINUX_AC_VO); - wlan_hdd_update_pause_time(adapter, temp_map); + temp_map = adapter->subqueue_pause_map; + adapter->subqueue_pause_map &= ~(1 << reason); + if (!adapter->pause_map) { + netif_wake_subqueue(adapter->dev, HDD_LINUX_AC_VO); + wlan_hdd_update_pause_time(adapter, temp_map); + } spin_unlock_bh(&adapter->pause_map_lock); break; @@ -3161,7 +3197,12 @@ void wlan_hdd_netif_queue_control(struct hdd_adapter *adapter, adapter->queue_oper_history[index].time = qdf_system_ticks(); adapter->queue_oper_history[index].netif_action = action; adapter->queue_oper_history[index].netif_reason = reason; - adapter->queue_oper_history[index].pause_map = adapter->pause_map; + if (reason >= WLAN_DATA_FLOW_CTRL_BE_BK) + adapter->queue_oper_history[index].pause_map = + adapter->subqueue_pause_map; + else + adapter->queue_oper_history[index].pause_map = + adapter->pause_map; txq_hist_ptr = &adapter->queue_oper_history[index];