summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHimanshu Agarwal <himanaga@qti.qualcomm.com>2016-03-13 02:49:32 +0530
committerAnjaneedevi Kapparapu <akappa@codeaurora.org>2016-04-22 10:23:13 +0530
commit89c770ddd30c4fa0dcfd5bdf61c5191eb811bfb4 (patch)
tree854e6340651593eb0b4335aaf4739594f1c1b123
parent527d683f55c6295817123421d4f0e1ac6d3abc28 (diff)
qcacld-2.0: Update netif queue timestamp to avoid watchdog
Update netif queue timestamp while stopping queues to avoid NETDEV watchdog. Change-Id: Ie0c0af1fc585992f5f89c4c29006d4bafce390c3 CRs-Fixed: 988801
-rw-r--r--CORE/CLD_TXRX/TLSHIM/tl_shim.c19
-rw-r--r--CORE/CLD_TXRX/TLSHIM/tl_shim.h3
-rw-r--r--CORE/CLD_TXRX/TXRX/ol_tx.h4
-rw-r--r--CORE/CLD_TXRX/TXRX/ol_tx_queue.c2
-rw-r--r--CORE/CLD_TXRX/TXRX/ol_txrx.c29
-rw-r--r--CORE/CLD_TXRX/TXRX/ol_txrx.h5
-rw-r--r--CORE/CLD_TXRX/TXRX/ol_txrx_types.h3
-rw-r--r--CORE/HDD/inc/wlan_hdd_main.h5
-rw-r--r--CORE/HDD/inc/wlan_hdd_tx_rx.h4
-rw-r--r--CORE/HDD/src/wlan_hdd_hostapd.c2
-rw-r--r--CORE/HDD/src/wlan_hdd_main.c2
-rw-r--r--CORE/HDD/src/wlan_hdd_softap_tx_rx.c17
-rw-r--r--CORE/HDD/src/wlan_hdd_tx_rx.c101
13 files changed, 185 insertions, 11 deletions
diff --git a/CORE/CLD_TXRX/TLSHIM/tl_shim.c b/CORE/CLD_TXRX/TLSHIM/tl_shim.c
index 801d7c9decdc..2ccc71f0ca6d 100644
--- a/CORE/CLD_TXRX/TLSHIM/tl_shim.c
+++ b/CORE/CLD_TXRX/TLSHIM/tl_shim.c
@@ -43,6 +43,7 @@
#include "vos_utils.h"
#include "wdi_out.h"
#include "ol_rx_fwd.h"
+#include "ol_txrx.h"
#define TLSHIM_PEER_AUTHORIZE_WAIT 50
@@ -2665,3 +2666,21 @@ uint64_t tlshim_get_fwd_to_tx_packet_count(uint8_t session_id)
{
return ol_rx_get_fwd_to_tx_packet_count(session_id);
}
+
+/*
+ * tlshim_get_ll_queue_pause_bitmap() - to obtain ll queue pause bitmap and
+ * last pause timestamp
+ * @session_id: vdev id
+ * @pause_bitmap: pointer to return ll queue pause bitmap
+ * @pause_timestamp: pointer to return pause timestamp to calling func.
+ *
+ * Return: status -> A_OK - for success, A_ERROR for failure
+ *
+ */
+A_STATUS tlshim_get_ll_queue_pause_bitmap(uint8_t session_id,
+ uint8_t *pause_bitmap, adf_os_time_t *pause_timestamp)
+{
+ return ol_txrx_get_ll_queue_pause_bitmap(session_id,
+ pause_bitmap, pause_timestamp);
+}
+
diff --git a/CORE/CLD_TXRX/TLSHIM/tl_shim.h b/CORE/CLD_TXRX/TLSHIM/tl_shim.h
index 5114b58bd33a..9a0c9ef03389 100644
--- a/CORE/CLD_TXRX/TLSHIM/tl_shim.h
+++ b/CORE/CLD_TXRX/TLSHIM/tl_shim.h
@@ -127,6 +127,9 @@ int tlshim_mgmt_roam_event_ind(void *context, u_int32_t vdev_id);
void *tl_shim_get_vdev_by_addr(void *vos_context, uint8_t *mac_addr);
void *tl_shim_get_vdev_by_sta_id(void *vos_context, uint8_t sta_id);
uint64_t tlshim_get_fwd_to_tx_packet_count(uint8_t session_id);
+int tlshim_get_ll_queue_pause_bitmap(uint8_t session_id,
+ uint8_t *pause_bitmap, __adf_time_t *pause_timestamp);
+
#ifdef QCA_SUPPORT_TXRX_VDEV_PAUSE_LL
void tl_shim_set_peer_authorized_event(void *vos_ctx, v_U8_t session_id);
diff --git a/CORE/CLD_TXRX/TXRX/ol_tx.h b/CORE/CLD_TXRX/TXRX/ol_tx.h
index 65275eb0ea64..4b0280cfcfbe 100644
--- a/CORE/CLD_TXRX/TXRX/ol_tx.h
+++ b/CORE/CLD_TXRX/TXRX/ol_tx.h
@@ -125,4 +125,8 @@ ol_tx_pdev_ll_pause_queue_send_all(struct ol_txrx_pdev_t *pdev);
struct ol_txrx_vdev_t *
ol_txrx_get_vdev_from_vdev_id(uint8_t vdev_id);
+ol_txrx_vdev_handle
+ol_txrx_get_vdev_from_vdev_id(uint8_t vdev_id);
+
#endif /* _OL_TX__H_ */
+
diff --git a/CORE/CLD_TXRX/TXRX/ol_tx_queue.c b/CORE/CLD_TXRX/TXRX/ol_tx_queue.c
index b3dba2e31397..6e1d47d66d51 100644
--- a/CORE/CLD_TXRX/TXRX/ol_tx_queue.c
+++ b/CORE/CLD_TXRX/TXRX/ol_tx_queue.c
@@ -1052,6 +1052,8 @@ ol_txrx_vdev_pause(ol_txrx_vdev_handle vdev, u_int32_t reason)
} else {
adf_os_spin_lock_bh(&vdev->ll_pause.mutex);
vdev->ll_pause.paused_reason |= reason;
+ vdev->ll_pause.pause_timestamp =
+ adf_os_gettimestamp();
vdev->ll_pause.q_pause_cnt++;
vdev->ll_pause.is_q_paused = TRUE;
adf_os_spin_unlock_bh(&vdev->ll_pause.mutex);
diff --git a/CORE/CLD_TXRX/TXRX/ol_txrx.c b/CORE/CLD_TXRX/TXRX/ol_txrx.c
index 280d6e62e29e..f0b2394070b9 100644
--- a/CORE/CLD_TXRX/TXRX/ol_txrx.c
+++ b/CORE/CLD_TXRX/TXRX/ol_txrx.c
@@ -1081,6 +1081,7 @@ ol_txrx_vdev_attach(
adf_os_spinlock_init(&vdev->ll_pause.mutex);
vdev->ll_pause.paused_reason = 0;
+ vdev->ll_pause.pause_timestamp = 0;
#if defined(CONFIG_HL_SUPPORT)
vdev->hl_paused_reason = 0;
#endif
@@ -2762,3 +2763,31 @@ void ol_txrx_clear_stats(struct ol_txrx_pdev_t *pdev, uint16_t value)
}
}
+/*
+ * ol_txrx_get_ll_queue_pause_bitmap() - to obtain ll queue pause bitmap and
+ * last pause timestamp
+ * @vdev_id: vdev id
+ * @pause_bitmap: pointer to return ll queue pause bitmap
+ * @pause_timestamp: pointer to return pause timestamp to calling func.
+ *
+ * Return: status -> A_OK - for success, A_ERROR for failure
+ *
+ */
+A_STATUS ol_txrx_get_ll_queue_pause_bitmap(uint8_t vdev_id,
+ uint8_t *pause_bitmap, adf_os_time_t *pause_timestamp)
+{
+ ol_txrx_vdev_handle vdev = NULL;
+
+ vdev = (ol_txrx_vdev_handle) ol_txrx_get_vdev_from_vdev_id(vdev_id);
+ if (!vdev) {
+ TXRX_PRINT(TXRX_PRINT_LEVEL_ERR,
+ "%s: vdev handle is NULL for vdev id %d",
+ __func__, vdev_id);
+ return A_ERROR;
+ }
+
+ *pause_timestamp = vdev->ll_pause.pause_timestamp;
+ *pause_bitmap = vdev->ll_pause.paused_reason;
+ return A_OK;
+}
+
diff --git a/CORE/CLD_TXRX/TXRX/ol_txrx.h b/CORE/CLD_TXRX/TXRX/ol_txrx.h
index 95cfd1689486..2c45b8879ab9 100644
--- a/CORE/CLD_TXRX/TXRX/ol_txrx.h
+++ b/CORE/CLD_TXRX/TXRX/ol_txrx.h
@@ -59,4 +59,9 @@ ol_tx_desc_pool_size_hl(ol_pdev_handle ctrl_pdev);
#ifdef CONFIG_TX_DESC_HI_PRIO_RESERVE
#define TXRX_HL_TX_DESC_HI_PRIO_RESERVED 20
#endif
+
+A_STATUS
+ol_txrx_get_ll_queue_pause_bitmap(uint8_t vdev_id,
+ uint8_t *pause_bitmap, adf_os_time_t *pause_timestamp);
+
#endif /* _OL_TXRX__H_ */
diff --git a/CORE/CLD_TXRX/TXRX/ol_txrx_types.h b/CORE/CLD_TXRX/TXRX/ol_txrx_types.h
index 32ebe320f7eb..b1a1798ed85e 100644
--- a/CORE/CLD_TXRX/TXRX/ol_txrx_types.h
+++ b/CORE/CLD_TXRX/TXRX/ol_txrx_types.h
@@ -919,7 +919,8 @@ struct ol_txrx_vdev_t {
adf_nbuf_t tail;
int depth;
} txq;
- u_int32_t paused_reason;
+ uint32_t paused_reason;
+ uint64_t pause_timestamp;
adf_os_spinlock_t mutex;
adf_os_timer_t timer;
int max_q_depth;
diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h
index d6b9ebfca9db..c038b7dbff45 100644
--- a/CORE/HDD/inc/wlan_hdd_main.h
+++ b/CORE/HDD/inc/wlan_hdd_main.h
@@ -1141,6 +1141,11 @@ struct hdd_adapter_s
#endif
uint8_t addr_filter_pattern;
+ /* to store the time of last bug report generated in HDD */
+ uint64_t last_tx_jiffies;
+ /* stores how many times timeout happens since last bug report generation */
+ uint8_t bug_report_count;
+
v_BOOL_t higherDtimTransition;
v_BOOL_t survey_idx;
diff --git a/CORE/HDD/inc/wlan_hdd_tx_rx.h b/CORE/HDD/inc/wlan_hdd_tx_rx.h
index 02d0507ba3be..9e46f119190d 100644
--- a/CORE/HDD/inc/wlan_hdd_tx_rx.h
+++ b/CORE/HDD/inc/wlan_hdd_tx_rx.h
@@ -78,6 +78,8 @@
#define HDD_ETH_HEADER_LEN 14
+#define HDD_BUG_REPORT_MIN_COUNT 3
+#define HDD_BUG_REPORT_MIN_TIME 300000 /* 5 minutes */
/*---------------------------------------------------------------------------
Type declarations
-------------------------------------------------------------------------*/
@@ -270,6 +272,8 @@ static inline void wlan_hdd_log_eapol(struct sk_buff *skb,
VOS_STATUS hdd_mon_rx_packet_cbk(v_VOID_t *vos_ctx, adf_nbuf_t rx_buf,
uint8_t sta_id);
+void wlan_display_tx_timeout_stats(hdd_adapter_t *adapter);
+
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(hdd_adapter_t *adapter,
diff --git a/CORE/HDD/src/wlan_hdd_hostapd.c b/CORE/HDD/src/wlan_hdd_hostapd.c
index 32b8d2013ccd..af22e5d91f19 100644
--- a/CORE/HDD/src/wlan_hdd_hostapd.c
+++ b/CORE/HDD/src/wlan_hdd_hostapd.c
@@ -7133,6 +7133,8 @@ hdd_adapter_t* hdd_wlan_create_ap_dev(hdd_context_t *pHddCtx,
SET_NETDEV_DEV(pWlanHostapdDev, pHddCtx->parent_dev);
spin_lock_init(&pHostapdAdapter->pause_map_lock);
+ pHostapdAdapter->last_tx_jiffies = jiffies;
+ pHostapdAdapter->bug_report_count = 0;
}
return pHostapdAdapter;
}
diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c
index fdd0ca492b71..2944b6ac054a 100644
--- a/CORE/HDD/src/wlan_hdd_main.c
+++ b/CORE/HDD/src/wlan_hdd_main.c
@@ -10138,6 +10138,8 @@ static hdd_adapter_t* hdd_alloc_station_adapter(hdd_context_t *pHddCtx,
hdd_wmm_init( pAdapter );
hdd_adapter_runtime_suspend_init(pAdapter);
spin_lock_init(&pAdapter->pause_map_lock);
+ pAdapter->last_tx_jiffies = jiffies;
+ pAdapter->bug_report_count = 0;
}
return pAdapter;
diff --git a/CORE/HDD/src/wlan_hdd_softap_tx_rx.c b/CORE/HDD/src/wlan_hdd_softap_tx_rx.c
index abe473dcc31c..0b4077c49474 100644
--- a/CORE/HDD/src/wlan_hdd_softap_tx_rx.c
+++ b/CORE/HDD/src/wlan_hdd_softap_tx_rx.c
@@ -464,11 +464,11 @@ static void __hdd_softap_tx_timeout(struct net_device *dev)
{
hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
hdd_context_t *hdd_ctx;
+ struct netdev_queue *txq;
+ int i = 0;
DPTRACE(adf_dp_trace(NULL, ADF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT,
NULL, 0));
- VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
- "%s: Transmission timeout occurred", __func__);
hdd_ctx = WLAN_HDD_GET_CTX(adapter);
if (hdd_ctx->isLogpInProgress) {
@@ -483,6 +483,19 @@ static void __hdd_softap_tx_timeout(struct net_device *dev)
* case of disassociation it is ok to ignore this. But if associated, we have
* do possible recovery here.
*/
+
+ VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
+ "%s: Transmission timeout occurred jiffies %lu trans_start %lu",
+ __func__, jiffies, dev->trans_start);
+
+ for (i = 0; i < NUM_TX_QUEUES; i++) {
+ txq = netdev_get_tx_queue(dev, i);
+ VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA,
+ VOS_TRACE_LEVEL_ERROR,
+ "Queue%d status: %d txq->trans_start %lu",
+ i, netif_tx_queue_stopped(txq), txq->trans_start);
+ }
+ wlan_display_tx_timeout_stats(adapter);
}
/**
diff --git a/CORE/HDD/src/wlan_hdd_tx_rx.c b/CORE/HDD/src/wlan_hdd_tx_rx.c
index 6896ae502df7..09cbd4b1039f 100644
--- a/CORE/HDD/src/wlan_hdd_tx_rx.c
+++ b/CORE/HDD/src/wlan_hdd_tx_rx.c
@@ -774,6 +774,64 @@ VOS_STATUS hdd_get_peer_sta_id(hdd_station_ctx_t *sta_ctx,
}
/**
+ * wlan_display_tx_timeout_stats() - HDD tx timeout stats display handler
+ * @adapter: hdd adapter
+ *
+ * Function called by tx timeout handler to display the stats when timeout
+ * occurs during trabsmission.
+ *
+ * Return: none
+ */
+void wlan_display_tx_timeout_stats(hdd_adapter_t *adapter)
+{
+ hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+ uint8_t pause_bitmap = 0;
+ vos_time_t pause_timestamp = 0;
+ A_STATUS status;
+
+ VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
+ "carrier state: %d", netif_carrier_ok(adapter->dev));
+
+ /* to display the neif queue pause/unpause history */
+ wlan_hdd_display_netif_queue_history(hdd_ctx);
+
+ /* to display the count of packets at diferent layers */
+ adf_nbuf_tx_desc_count_display();
+
+ /* printing last 100 records from DPTRACE */
+ adf_dp_trace_dump_all(100);
+
+ /* to print the pause bitmap of local ll queues */
+ status = tlshim_get_ll_queue_pause_bitmap(adapter->sessionId,
+ &pause_bitmap, &pause_timestamp);
+ if (status != A_OK)
+ hddLog(LOGE, FL("vdev is NULL for vdev id %d"),
+ adapter->sessionId);
+ else
+ hddLog(LOGE,
+ FL("LL vdev queues pause bitmap: %d, last pause timestamp %lu"),
+ pause_bitmap, pause_timestamp);
+
+ /*
+ * To invoke the bug report to flush driver as well as fw logs
+ * when timeout happens. It happens when it has been more
+ * than 5 minutes and the timeout has happened at least 3 times
+ * since the last generation of bug report.
+ */
+ adapter->bug_report_count++;
+ if (adapter->bug_report_count >= HDD_BUG_REPORT_MIN_COUNT &&
+ (jiffies_to_msecs(jiffies - adapter->last_tx_jiffies) >=
+ HDD_BUG_REPORT_MIN_TIME)) {
+ adapter->bug_report_count = 0;
+ adapter->last_tx_jiffies = jiffies;
+ vos_flush_logs(WLAN_LOG_TYPE_FATAL,
+ WLAN_LOG_INDICATOR_HOST_DRIVER,
+ WLAN_LOG_REASON_HDD_TIME_OUT,
+ true);
+ }
+}
+
+/**
* __hdd_tx_timeout() - HDD tx timeout handler
* @dev: pointer to net_device structure
*
@@ -816,12 +874,10 @@ static void __hdd_tx_timeout(struct net_device *dev)
for (i = 0; i < NUM_TX_QUEUES; i++) {
txq = netdev_get_tx_queue(dev, i);
- hddLog(LOG1, FL("Queue%d status: %d txq->trans_start %lu"),
+ hddLog(LOGE, FL("Queue%d status: %d txq->trans_start %lu"),
i, netif_tx_queue_stopped(txq), txq->trans_start);
}
-
- VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
- "carrier state: %d", netif_carrier_ok(dev));
+ wlan_display_tx_timeout_stats(pAdapter);
}
/**
@@ -1458,6 +1514,27 @@ static void wlan_hdd_update_queue_oper_stats(hdd_adapter_t *adapter,
}
/**
+ * wlan_hdd_update_txq_timestamp() - update txq timestamp
+ * @dev: net device
+ *
+ * Return: none
+ */
+static void wlan_hdd_update_txq_timestamp(struct net_device *dev)
+{
+ struct netdev_queue *txq;
+ int i;
+ bool unlock;
+
+ for (i = 0; i < NUM_TX_QUEUES; i++) {
+ txq = netdev_get_tx_queue(dev, i);
+ unlock = __netif_tx_trylock(txq);
+ txq_trans_update(txq);
+ if (unlock == true)
+ __netif_tx_unlock(txq);
+ }
+}
+
+/**
* wlan_hdd_netif_queue_control() - Use for netif_queue related actions
* @adapter: adapter handle
* @action: action type
@@ -1489,8 +1566,10 @@ void wlan_hdd_netif_queue_control(hdd_adapter_t *adapter,
case WLAN_STOP_ALL_NETIF_QUEUE:
spin_lock_bh(&adapter->pause_map_lock);
- if (!adapter->pause_map)
+ if (!adapter->pause_map) {
netif_tx_stop_all_queues(adapter->dev);
+ wlan_hdd_update_txq_timestamp(adapter->dev);
+ }
adapter->pause_map |= (1 << reason);
spin_unlock_bh(&adapter->pause_map_lock);
break;
@@ -1513,8 +1592,10 @@ void wlan_hdd_netif_queue_control(hdd_adapter_t *adapter,
case WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER:
spin_lock_bh(&adapter->pause_map_lock);
- if (!adapter->pause_map)
+ if (!adapter->pause_map) {
netif_tx_stop_all_queues(adapter->dev);
+ wlan_hdd_update_txq_timestamp(adapter->dev);
+ }
adapter->pause_map |= (1 << reason);
netif_carrier_off(adapter->dev);
spin_unlock_bh(&adapter->pause_map_lock);
@@ -1531,16 +1612,20 @@ void wlan_hdd_netif_queue_control(hdd_adapter_t *adapter,
case WLAN_NETIF_TX_DISABLE:
spin_lock_bh(&adapter->pause_map_lock);
- if (!adapter->pause_map)
+ if (!adapter->pause_map) {
netif_tx_disable(adapter->dev);
+ wlan_hdd_update_txq_timestamp(adapter->dev);
+ }
adapter->pause_map |= (1 << reason);
spin_unlock_bh(&adapter->pause_map_lock);
break;
case WLAN_NETIF_TX_DISABLE_N_CARRIER:
spin_lock_bh(&adapter->pause_map_lock);
- if (!adapter->pause_map)
+ if (!adapter->pause_map) {
netif_tx_disable(adapter->dev);
+ wlan_hdd_update_txq_timestamp(adapter->dev);
+ }
adapter->pause_map |= (1 << reason);
netif_carrier_off(adapter->dev);
spin_unlock_bh(&adapter->pause_map_lock);