qcacmn: Lock rx_desc_pool to collect nbufs and delete later

When multi page alloc is activated, spinlock for rx_desc_pool
is being held for more than 2 seconds, resulting in QDF_BUG.
The major proportion of the time period is used in unmapping
the nbufs.
To fix this, lock rx_desc_pool only to collect nbufs from
rx_desc in a list and unmap and free the nbufs after releasing
the lock.

Change-Id: Iff2078a0de56b51712e2f9a7c5ace7a959e2445d
CRs-Fixed: 2779498
This commit is contained in:
Ananya Gupta
2020-09-25 16:17:19 +05:30
committed by snandini
orang tua 0907c4679d
melakukan 218ec1c24e
2 mengubah file dengan 56 tambahan dan 26 penghapusan

Melihat File

@@ -148,22 +148,21 @@ union dp_rx_desc_list_elem_t *dp_rx_desc_find(uint16_t page_id, uint16_t offset,
rx_desc_pool->elem_size * offset;
}
static QDF_STATUS __dp_rx_desc_nbuf_free(struct dp_soc *soc,
struct rx_desc_pool *rx_desc_pool)
static QDF_STATUS dp_rx_desc_nbuf_collect(struct dp_soc *soc,
struct rx_desc_pool *rx_desc_pool,
qdf_nbuf_t *nbuf_unmap_list,
qdf_nbuf_t *nbuf_free_list)
{
uint32_t i, num_desc, page_id, offset, num_desc_per_page;
union dp_rx_desc_list_elem_t *rx_desc_elem;
struct dp_rx_desc *rx_desc;
qdf_nbuf_t nbuf;
if (qdf_unlikely(!(rx_desc_pool->
desc_pages.cacheable_pages))) {
if (qdf_unlikely(!(rx_desc_pool->desc_pages.cacheable_pages))) {
qdf_err("No pages found on this desc pool");
return QDF_STATUS_E_INVAL;
}
num_desc = rx_desc_pool->pool_size;
num_desc_per_page =
rx_desc_pool->desc_pages.num_element_per_page;
num_desc_per_page = rx_desc_pool->desc_pages.num_element_per_page;
for (i = 0; i < num_desc; i++) {
page_id = i / num_desc_per_page;
offset = i % num_desc_per_page;
@@ -171,47 +170,72 @@ static QDF_STATUS __dp_rx_desc_nbuf_free(struct dp_soc *soc,
rx_desc = &rx_desc_elem->rx_desc;
dp_rx_desc_free_dbg_info(rx_desc);
if (rx_desc->in_use) {
nbuf = rx_desc->nbuf;
if (!rx_desc->unmapped) {
dp_ipa_handle_rx_buf_smmu_mapping(
soc, nbuf,
rx_desc_pool->buf_size,
false);
qdf_nbuf_unmap_nbytes_single(
soc->osdev,
rx_desc->nbuf,
QDF_DMA_BIDIRECTIONAL,
rx_desc_pool->buf_size);
DP_RX_HEAD_APPEND(*nbuf_unmap_list,
rx_desc->nbuf);
rx_desc->unmapped = 1;
} else {
DP_RX_HEAD_APPEND(*nbuf_free_list,
rx_desc->nbuf);
}
qdf_nbuf_free(nbuf);
}
}
return QDF_STATUS_SUCCESS;
}
static void dp_rx_desc_nbuf_cleanup(struct dp_soc *soc,
qdf_nbuf_t nbuf_unmap_list,
qdf_nbuf_t nbuf_free_list,
uint16_t buf_size)
{
qdf_nbuf_t nbuf = nbuf_unmap_list;
qdf_nbuf_t next;
while (nbuf) {
next = nbuf->next;
if (dp_ipa_handle_rx_buf_smmu_mapping(soc, nbuf, buf_size,
false))
dp_info_rl("Unable to unmap nbuf: %pK", nbuf);
qdf_nbuf_unmap_nbytes_single(soc->osdev, nbuf,
QDF_DMA_BIDIRECTIONAL, buf_size);
qdf_nbuf_free(nbuf);
nbuf = next;
}
nbuf = nbuf_free_list;
while (nbuf) {
next = nbuf->next;
qdf_nbuf_free(nbuf);
nbuf = next;
}
}
void dp_rx_desc_nbuf_and_pool_free(struct dp_soc *soc, uint32_t pool_id,
struct rx_desc_pool *rx_desc_pool)
{
QDF_STATUS qdf_status;
qdf_nbuf_t nbuf_unmap_list = NULL;
qdf_nbuf_t nbuf_free_list = NULL;
qdf_spin_lock_bh(&rx_desc_pool->lock);
qdf_status = __dp_rx_desc_nbuf_free(soc, rx_desc_pool);
if (QDF_IS_STATUS_SUCCESS(qdf_status))
dp_rx_desc_pool_free(soc, rx_desc_pool);
dp_rx_desc_nbuf_collect(soc, rx_desc_pool,
&nbuf_unmap_list, &nbuf_free_list);
qdf_spin_unlock_bh(&rx_desc_pool->lock);
dp_rx_desc_nbuf_cleanup(soc, nbuf_unmap_list, nbuf_free_list,
rx_desc_pool->buf_size);
qdf_spinlock_destroy(&rx_desc_pool->lock);
}
void dp_rx_desc_nbuf_free(struct dp_soc *soc,
struct rx_desc_pool *rx_desc_pool)
{
qdf_nbuf_t nbuf_unmap_list = NULL;
qdf_nbuf_t nbuf_free_list = NULL;
qdf_spin_lock_bh(&rx_desc_pool->lock);
__dp_rx_desc_nbuf_free(soc, rx_desc_pool);
dp_rx_desc_nbuf_collect(soc, rx_desc_pool,
&nbuf_unmap_list, &nbuf_free_list);
qdf_spin_unlock_bh(&rx_desc_pool->lock);
dp_rx_desc_nbuf_cleanup(soc, nbuf_unmap_list, nbuf_free_list,
rx_desc_pool->buf_size);
}
void dp_rx_desc_pool_free(struct dp_soc *soc,