qcacmn: Check for tx desc leak or corruption
Tx descriptor is not being freed and put back in tx desc pool for a long time. As a result, system is not going into suspended state. To find this descriptor, during dp_bus_suspend and dp_runtime_suspend, parse through the descriptor pool to check for any descriptors not freed for a long and trigger self recovery when found. Change-Id: Id97c5c8537c9bec922f4e254b5bf094505ee61ff CRs-Fixed: 3109868
这个提交包含在:
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2022 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
|
||||
@@ -93,6 +93,19 @@ do { \
|
||||
#endif /* !QCA_LL_TX_FLOW_CONTROL_V2 */
|
||||
#define MAX_POOL_BUFF_COUNT 10000
|
||||
|
||||
#ifdef DP_TX_TRACKING
|
||||
static inline void dp_tx_desc_set_magic(struct dp_tx_desc_s *tx_desc,
|
||||
uint32_t magic_pattern)
|
||||
{
|
||||
tx_desc->magic = magic_pattern;
|
||||
}
|
||||
#else
|
||||
static inline void dp_tx_desc_set_magic(struct dp_tx_desc_s *tx_desc,
|
||||
uint32_t magic_pattern)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
QDF_STATUS dp_tx_desc_pool_alloc(struct dp_soc *soc, uint8_t pool_id,
|
||||
uint16_t num_elem);
|
||||
QDF_STATUS dp_tx_desc_pool_init(struct dp_soc *soc, uint8_t pool_id,
|
||||
@@ -301,7 +314,8 @@ dp_tx_desc_alloc(struct dp_soc *soc, uint8_t desc_pool_id)
|
||||
tx_desc = dp_tx_get_desc_flow_pool(pool);
|
||||
tx_desc->pool_id = desc_pool_id;
|
||||
tx_desc->flags = DP_TX_DESC_FLAG_ALLOCATED;
|
||||
|
||||
dp_tx_desc_set_magic(tx_desc,
|
||||
DP_TX_MAGIC_PATTERN_INUSE);
|
||||
is_pause = dp_tx_is_threshold_reached(pool,
|
||||
pool->avail_desc);
|
||||
|
||||
@@ -391,6 +405,8 @@ dp_tx_desc_free(struct dp_soc *soc, struct dp_tx_desc_s *tx_desc,
|
||||
tx_desc->vdev_id = DP_INVALID_VDEV_ID;
|
||||
tx_desc->nbuf = NULL;
|
||||
tx_desc->flags = 0;
|
||||
dp_tx_desc_set_magic(tx_desc, DP_TX_MAGIC_PATTERN_FREE);
|
||||
tx_desc->timestamp = 0;
|
||||
dp_tx_put_desc_flow_pool(pool, tx_desc);
|
||||
switch (pool->status) {
|
||||
case FLOW_POOL_ACTIVE_PAUSED:
|
||||
@@ -503,6 +519,8 @@ dp_tx_desc_alloc(struct dp_soc *soc, uint8_t desc_pool_id)
|
||||
tx_desc = dp_tx_get_desc_flow_pool(pool);
|
||||
tx_desc->pool_id = desc_pool_id;
|
||||
tx_desc->flags = DP_TX_DESC_FLAG_ALLOCATED;
|
||||
dp_tx_desc_set_magic(tx_desc,
|
||||
DP_TX_MAGIC_PATTERN_INUSE);
|
||||
if (qdf_unlikely(pool->avail_desc < pool->stop_th)) {
|
||||
pool->status = FLOW_POOL_ACTIVE_PAUSED;
|
||||
qdf_spin_unlock_bh(&pool->flow_pool_lock);
|
||||
@@ -555,6 +573,7 @@ dp_tx_desc_free(struct dp_soc *soc, struct dp_tx_desc_s *tx_desc,
|
||||
tx_desc->vdev_id = DP_INVALID_VDEV_ID;
|
||||
tx_desc->nbuf = NULL;
|
||||
tx_desc->flags = 0;
|
||||
dp_tx_desc_set_magic(tx_desc, DP_TX_MAGIC_PATTERN_FREE);
|
||||
dp_tx_put_desc_flow_pool(pool, tx_desc);
|
||||
switch (pool->status) {
|
||||
case FLOW_POOL_ACTIVE_PAUSED:
|
||||
|
在新工单中引用
屏蔽一个用户