diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 64c7437649..a18f659f39 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -1009,7 +1009,7 @@ struct hdd_multicast_addr_list { uint8_t addr[WLAN_HDD_MAX_MC_ADDR_LIST][ETH_ALEN]; }; -#define WLAN_HDD_MAX_HISTORY_ENTRY 10 +#define WLAN_HDD_MAX_HISTORY_ENTRY 25 /** * struct hdd_netif_queue_stats - netif queue operation statistics @@ -1028,12 +1028,14 @@ struct hdd_netif_queue_stats { * @netif_action: action type * @netif_reason: reason type * @pause_map: pause map + * @tx_q_state: state of the netdev TX queues */ struct hdd_netif_queue_history { qdf_time_t time; uint16_t netif_action; uint16_t netif_reason; uint32_t pause_map; + unsigned long tx_q_state[NUM_TX_QUEUES]; }; /** diff --git a/core/hdd/inc/wlan_hdd_tx_rx.h b/core/hdd/inc/wlan_hdd_tx_rx.h index 90c342805a..d78f13b257 100644 --- a/core/hdd/inc/wlan_hdd_tx_rx.h +++ b/core/hdd/inc/wlan_hdd_tx_rx.h @@ -31,6 +31,7 @@ #include #include "cdp_txrx_flow_ctrl_legacy.h" +struct hdd_netif_queue_history; struct hdd_context; #define hdd_dp_alert(params...) QDF_TRACE_FATAL(QDF_MODULE_ID_HDD_DATA, params) @@ -268,6 +269,7 @@ int hdd_get_peer_idx(struct hdd_station_ctx *sta_ctx, const char *hdd_reason_type_to_string(enum netif_reason_type reason); const char *hdd_action_type_to_string(enum netif_action_type action); + void wlan_hdd_netif_queue_control(struct hdd_adapter *adapter, enum netif_action_type action, enum netif_reason_type reason); @@ -375,4 +377,27 @@ hdd_skb_nontso_linearize(struct sk_buff *skb) void hdd_dp_cfg_update(struct wlan_objmgr_psoc *psoc, struct hdd_context *hdd_ctx); +/** + * hdd_print_netdev_txq_status() - print netdev tx queue status + * @dev: Pointer to network device + * + * This function is used to print netdev tx queue status + * + * Return: None + */ +void hdd_print_netdev_txq_status(struct net_device *dev); + +/** + * wlan_hdd_dump_queue_history_state() - Dump hdd queue history states + * @q_hist: pointer to hdd queue history structure + * @buf: buffer where the queue history string is dumped + * @size: size of the buffer + * + * Dump hdd queue history states into a buffer + * + * Return: number of bytes written to the buffer + */ +uint32_t +wlan_hdd_dump_queue_history_state(struct hdd_netif_queue_history *q_hist, + char *buf, uint32_t size); #endif /* end #if !defined(WLAN_HDD_TX_RX_H) */ diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index d6470ad937..d7591ceeb3 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -18634,28 +18634,6 @@ static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason) } } -/** - * hdd_print_netdev_txq_status() - print netdev tx queue status - * @dev: Pointer to network device - * - * This function is used to print netdev tx queue status - * - * Return: none - */ -static void hdd_print_netdev_txq_status(struct net_device *dev) -{ - unsigned int i; - - if (!dev) - return; - - for (i = 0; i < dev->num_tx_queues; i++) { - struct netdev_queue *txq = netdev_get_tx_queue(dev, i); - - hdd_debug("netdev tx queue[%u] state: 0x%lx", i, txq->state); - } -} - /** * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api * @wiphy: Pointer to wiphy diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index aa12edf4c5..f79356d4c2 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -8287,6 +8287,8 @@ hdd_display_netif_queue_history_compact(struct hdd_context *hdd_ctx) qdf_mem_free(comb_log_str); } +/* Max size of a single netdev tx queue state string. e.g. "1: 0x1" */ +#define HDD_NETDEV_TX_Q_STATE_STRLEN 15 /** * wlan_hdd_display_netif_queue_history() - display netif queue history * @hdd_ctx: hdd context @@ -8297,10 +8299,11 @@ void wlan_hdd_display_netif_queue_history(struct hdd_context *hdd_ctx, enum qdf_stats_verbosity_level verb_lvl) { - - struct hdd_adapter *adapter = NULL; int i; + struct hdd_adapter *adapter = NULL; qdf_time_t total, pause, unpause, curr_time, delta; + struct hdd_netif_queue_history *q_hist_ptr; + char q_status_buf[NUM_TX_QUEUES * HDD_NETDEV_TX_Q_STATE_STRLEN] = {0}; if (verb_lvl == QDF_STATS_VERBOSITY_LEVEL_LOW) { hdd_display_netif_queue_history_compact(hdd_ctx); @@ -8308,6 +8311,8 @@ wlan_hdd_display_netif_queue_history(struct hdd_context *hdd_ctx, } hdd_for_each_adapter(hdd_ctx, adapter) { + if (adapter->vdev_id == CDP_INVALID_VDEV_ID) + continue; hdd_nofl_info("Netif queue operation statistics:"); hdd_nofl_info("vdev_id %d device mode %d", adapter->vdev_id, adapter->device_mode); @@ -8345,18 +8350,24 @@ wlan_hdd_display_netif_queue_history(struct hdd_context *hdd_ctx, total_pause_time + pause_delta)); } - hdd_nofl_info("Netif queue operation history:"); - hdd_nofl_info("Total entries: %d current index %d", + hdd_nofl_info("Netif queue operation history: Total entries: %d current index %d(-1) time %u", WLAN_HDD_MAX_HISTORY_ENTRY, - adapter->history_index); + adapter->history_index, + qdf_system_ticks_to_msecs(qdf_system_ticks())); - hdd_nofl_info("index: time: action_type: reason_type: pause_map"); + hdd_nofl_info("%2s%20s%50s%30s%10s %s", + "#", "time(ms)", "action_type", "reason_type", + "pause_map", "netdev-queue-status"); for (i = 0; i < WLAN_HDD_MAX_HISTORY_ENTRY; i++) { /* using hdd_log to avoid printing function name */ if (adapter->queue_oper_history[i].time == 0) continue; - hdd_nofl_info("%d: %u: %s: %s: %x", + q_hist_ptr = &adapter->queue_oper_history[i]; + wlan_hdd_dump_queue_history_state(q_hist_ptr, + q_status_buf, + sizeof(q_status_buf)); + hdd_nofl_info("%2d%20u%50s%30s%10x %s", i, qdf_system_ticks_to_msecs( adapter->queue_oper_history[i].time), hdd_action_type_to_string( @@ -8365,7 +8376,8 @@ wlan_hdd_display_netif_queue_history(struct hdd_context *hdd_ctx, hdd_reason_type_to_string( adapter->queue_oper_history[i]. netif_reason), - adapter->queue_oper_history[i].pause_map); + adapter->queue_oper_history[i].pause_map, + q_status_buf); } } } diff --git a/core/hdd/src/wlan_hdd_tx_rx.c b/core/hdd/src/wlan_hdd_tx_rx.c index 288e84ee9d..162d9558f1 100644 --- a/core/hdd/src/wlan_hdd_tx_rx.c +++ b/core/hdd/src/wlan_hdd_tx_rx.c @@ -2357,6 +2357,47 @@ static void wlan_hdd_update_pause_time(struct hdd_adapter *adapter, } +uint32_t +wlan_hdd_dump_queue_history_state(struct hdd_netif_queue_history *queue_history, + char *buf, uint32_t size) +{ + unsigned int i; + unsigned int index = 0; + + for (i = 0; i < NUM_TX_QUEUES; i++) { + index += qdf_scnprintf(buf + index, + size - index, + "%u:0x%lx ", + i, queue_history->tx_q_state[i]); + } + + return index; +} + +/** + * wlan_hdd_update_queue_history_state() - Save a copy of dev TX queues state + * @adapter: adapter handle + * + * Save netdev TX queues state into adapter queue history. + * + * Return: None + */ +static void +wlan_hdd_update_queue_history_state(struct net_device *dev, + struct hdd_netif_queue_history *q_hist) +{ + unsigned int i = 0; + uint32_t num_tx_queues = 0; + struct netdev_queue *txq = NULL; + + num_tx_queues = qdf_min(dev->num_tx_queues, (uint32_t)NUM_TX_QUEUES); + + for (i = 0; i < num_tx_queues; i++) { + txq = netdev_get_tx_queue(dev, i); + q_hist->tx_q_state[i] = txq->state; + } +} + /** * wlan_hdd_stop_non_priority_queue() - stop non prority queues * @adapter: adapter handle @@ -2402,6 +2443,7 @@ void wlan_hdd_netif_queue_control(struct hdd_adapter *adapter, { uint32_t temp_map; uint8_t index; + struct hdd_netif_queue_history *txq_hist_ptr; if ((!adapter) || (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) || (!adapter->dev)) { @@ -2562,6 +2604,9 @@ void wlan_hdd_netif_queue_control(struct hdd_adapter *adapter, spin_unlock_bh(&adapter->pause_map_lock); break; + case WLAN_NETIF_ACTION_TYPE_NONE: + break; + default: hdd_err("unsupported action %d", action); } @@ -2581,6 +2626,25 @@ void wlan_hdd_netif_queue_control(struct hdd_adapter *adapter, 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; + + txq_hist_ptr = &adapter->queue_oper_history[index]; + + wlan_hdd_update_queue_history_state(adapter->dev, txq_hist_ptr); +} + +void hdd_print_netdev_txq_status(struct net_device *dev) +{ + unsigned int i; + + if (!dev) + return; + + for (i = 0; i < dev->num_tx_queues; i++) { + struct netdev_queue *txq = netdev_get_tx_queue(dev, i); + + hdd_debug("netdev tx queue[%u] state:0x%lx", + i, txq->state); + } } #ifdef FEATURE_MONITOR_MODE_SUPPORT