From f099e5e180f635c72475b004e772109d60d3eeab Mon Sep 17 00:00:00 2001 From: Nirav Shah Date: Sat, 30 Apr 2016 15:38:31 +0530 Subject: [PATCH] qcacld-3.0: Handle multiple map/unmap handler for same peer_id Handle multiple map/unmap handler from firmware for same peer_id. Firmware sends map/unmap event per copy engine enabled for RX path. CRs-Fixed: 1009289 Change-Id: Id8b0c27920a7aae95ddd4cff26731de85248457e --- core/dp/txrx/ol_txrx_peer_find.c | 20 +++++++++++++++----- core/dp/txrx/ol_txrx_peer_find.h | 4 ++-- core/dp/txrx/ol_txrx_types.h | 7 ++++++- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/core/dp/txrx/ol_txrx_peer_find.c b/core/dp/txrx/ol_txrx_peer_find.c index 9646801fa982..072d2ebe5210 100644 --- a/core/dp/txrx/ol_txrx_peer_find.c +++ b/core/dp/txrx/ol_txrx_peer_find.c @@ -346,7 +346,13 @@ ol_txrx_peer_find_add_id(struct ol_txrx_pdev_t *pdev, if (peer) { /* peer's ref count was already incremented by peer_find_hash_find */ - pdev->peer_id_to_obj_map[peer_id] = peer; + if (!pdev->peer_id_to_obj_map[peer_id].peer) { + pdev->peer_id_to_obj_map[peer_id].peer = peer; + qdf_atomic_init + (&pdev->peer_id_to_obj_map[peer_id].peer_id_ref_cnt); + } + qdf_atomic_inc + (&pdev->peer_id_to_obj_map[peer_id].peer_id_ref_cnt); /* * remove the reference added in ol_txrx_peer_find_hash_find. * the reference for the first peer id is already added in @@ -408,11 +414,15 @@ void ol_rx_peer_unmap_handler(ol_txrx_pdev_handle pdev, uint16_t peer_id) { struct ol_txrx_peer_t *peer; peer = (peer_id == HTT_INVALID_PEER) ? NULL : - pdev->peer_id_to_obj_map[peer_id]; + pdev->peer_id_to_obj_map[peer_id].peer; TXRX_PRINT(TXRX_PRINT_LEVEL_INFO1, "%s: peer %p with ID %d to be unmapped.\n", __func__, peer, peer_id); - pdev->peer_id_to_obj_map[peer_id] = NULL; + + if (qdf_atomic_dec_and_test + (&pdev->peer_id_to_obj_map[peer_id].peer_id_ref_cnt)) { + pdev->peer_id_to_obj_map[peer_id].peer = NULL; + } /* * Currently peer IDs are assigned for vdevs as well as peers. * If the peer ID is for a vdev, then the peer pointer stored @@ -461,11 +471,11 @@ void ol_txrx_peer_find_display(ol_txrx_pdev_handle pdev, int indent) "%*speer map:\n", indent, " "); max_peers = ol_cfg_max_peer_id(pdev->ctrl_pdev) + 1; for (i = 0; i < max_peers; i++) { - if (pdev->peer_id_to_obj_map[i]) { + if (pdev->peer_id_to_obj_map[i].peer) { QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_LOW, "%*sid %d -> %p\n", indent + 4, " ", i, - pdev->peer_id_to_obj_map[i]); + pdev->peer_id_to_obj_map[i].peer); } } QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_LOW, diff --git a/core/dp/txrx/ol_txrx_peer_find.h b/core/dp/txrx/ol_txrx_peer_find.h index e5ec69df7efd..43c2f141aac1 100644 --- a/core/dp/txrx/ol_txrx_peer_find.h +++ b/core/dp/txrx/ol_txrx_peer_find.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2011, 2015-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -63,7 +63,7 @@ struct ol_txrx_peer_t *ol_txrx_peer_find_by_id(struct ol_txrx_pdev_t *pdev, { struct ol_txrx_peer_t *peer; peer = (peer_id > ol_cfg_max_peer_id(pdev->ctrl_pdev)) ? NULL : - pdev->peer_id_to_obj_map[peer_id]; + pdev->peer_id_to_obj_map[peer_id].peer; /* * Currently, peer IDs are assigned to vdevs as well as peers. * If the peer ID is for a vdev, the peer_id_to_obj_map entry diff --git a/core/dp/txrx/ol_txrx_types.h b/core/dp/txrx/ol_txrx_types.h index ff36e192ae6b..a2b3cfd5dae5 100644 --- a/core/dp/txrx/ol_txrx_types.h +++ b/core/dp/txrx/ol_txrx_types.h @@ -386,6 +386,11 @@ struct ol_tx_flow_pool_t { #endif +struct ol_txrx_peer_id_map { + struct ol_txrx_peer_t *peer; + qdf_atomic_t peer_id_ref_cnt; +}; + /* * As depicted in the diagram below, the pdev contains an array of * NUM_EXT_TID ol_tx_active_queues_in_tid_t elements. @@ -504,7 +509,7 @@ struct ol_txrx_pdev_t { TAILQ_HEAD(, ol_txrx_vdev_t) vdev_list; /* peer ID to peer object map (array of pointers to peer objects) */ - struct ol_txrx_peer_t **peer_id_to_obj_map; + struct ol_txrx_peer_id_map *peer_id_to_obj_map; struct { unsigned mask;