qcacmn: add APIs to iterate the peers at vdev level
Add new APIs to iterate through the vdev peer list by taking the peer reference. A call back has to be passed to these APIs which will be called for every peer in the lisst dp_vdev_iterate_peer() -> iterates through peer_list of vdev dp_pdev_iterate_peer() -> iterates through peer_list of all vdevs in pdev dp_soc_iterate_peer() -> iterates through peer_lists of all vdevs in soc Additonal APIs are added to for itearations where the callback will be called outside the vdev->peer_list_lock, as these APIs have additional memory allocations suggested to use only in case the iteration need to happen outside lock dp_vdev_iterate_peer_lock_safe() dp_pdev_iterate_peer_lock_safe() dp_soc_iterate_peer_lock_safe Change-Id: I24632fe611355cc3e93b7f16d90913d4b8686ca9
This commit is contained in:

کامیت شده توسط
snandini

والد
1322dc7949
کامیت
e2b00339f3
@@ -26,6 +26,10 @@
|
||||
|
||||
#define DP_FW_PEER_STATS_CMP_TIMEOUT_MSEC 5000
|
||||
|
||||
typedef void dp_peer_iter_func(struct dp_soc *soc, struct dp_peer *peer,
|
||||
void *arg);
|
||||
void dp_peer_unref_delete(struct dp_peer *peer, enum dp_peer_mod_id id);
|
||||
|
||||
/**
|
||||
* dp_peer_get_ref() - Returns peer object given the peer id
|
||||
*
|
||||
@@ -51,29 +55,38 @@ QDF_STATUS dp_peer_get_ref(struct dp_soc *soc,
|
||||
}
|
||||
|
||||
/**
|
||||
* __dp_peer_find_by_id() - Returns peer object given the peer id
|
||||
* __dp_peer_get_ref_by_id() - Returns peer object given the peer id
|
||||
*
|
||||
* @soc : core DP soc context
|
||||
* @peer_id : peer id from peer object can be retrieved
|
||||
* @mod_id : module id
|
||||
*
|
||||
* Return: struct dp_peer*: Pointer to DP peer object
|
||||
*/
|
||||
static inline struct dp_peer *
|
||||
__dp_peer_find_by_id(struct dp_soc *soc,
|
||||
uint16_t peer_id)
|
||||
__dp_peer_get_ref_by_id(struct dp_soc *soc,
|
||||
uint16_t peer_id,
|
||||
enum dp_peer_mod_id mod_id)
|
||||
|
||||
{
|
||||
struct dp_peer *peer;
|
||||
|
||||
/* TODO: Hold lock */
|
||||
qdf_spin_lock_bh(&soc->peer_map_lock);
|
||||
peer = (peer_id >= soc->max_peers) ? NULL :
|
||||
soc->peer_id_to_obj_map[peer_id];
|
||||
if (!peer ||
|
||||
(dp_peer_get_ref(soc, peer, mod_id) != QDF_STATUS_SUCCESS)) {
|
||||
qdf_spin_unlock_bh(&soc->peer_map_lock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
qdf_spin_unlock_bh(&soc->peer_map_lock);
|
||||
return peer;
|
||||
}
|
||||
|
||||
/**
|
||||
* dp_peer_get_ref_by_id() - Returns peer object given the peer id
|
||||
* if delete_in_progress in not set for peer
|
||||
* if peer state is active
|
||||
*
|
||||
* @soc : core DP soc context
|
||||
* @peer_id : peer id from peer object can be retrieved
|
||||
@@ -89,7 +102,9 @@ struct dp_peer *dp_peer_get_ref_by_id(struct dp_soc *soc,
|
||||
struct dp_peer *peer;
|
||||
|
||||
qdf_spin_lock_bh(&soc->peer_map_lock);
|
||||
peer = __dp_peer_find_by_id(soc, peer_id);
|
||||
peer = (peer_id >= soc->max_peers) ? NULL :
|
||||
soc->peer_id_to_obj_map[peer_id];
|
||||
|
||||
if (!peer || peer->peer_state >= DP_PEER_STATE_LOGICAL_DELETE ||
|
||||
(dp_peer_get_ref(soc, peer, mod_id) != QDF_STATUS_SUCCESS)) {
|
||||
qdf_spin_unlock_bh(&soc->peer_map_lock);
|
||||
@@ -126,6 +141,275 @@ dp_clear_peer_internal(struct dp_soc *soc, struct dp_peer *peer)
|
||||
dp_rx_flush_rx_cached(peer, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* dp_vdev_iterate_peer() - API to iterate through vdev peer list
|
||||
*
|
||||
* @vdev : DP vdev context
|
||||
* @func : function to be called for each peer
|
||||
* @arg : argument need to be passed to func
|
||||
* @mod_id : module_id
|
||||
*
|
||||
* Return: void
|
||||
*/
|
||||
static inline void
|
||||
dp_vdev_iterate_peer(struct dp_vdev *vdev, dp_peer_iter_func *func, void *arg,
|
||||
enum dp_peer_mod_id mod_id)
|
||||
{
|
||||
struct dp_peer *peer;
|
||||
struct dp_peer *tmp_peer;
|
||||
struct dp_soc *soc = NULL;
|
||||
|
||||
if (!vdev || !vdev->pdev || !vdev->pdev->soc)
|
||||
return;
|
||||
|
||||
soc = vdev->pdev->soc;
|
||||
|
||||
qdf_spin_lock_bh(&vdev->peer_list_lock);
|
||||
TAILQ_FOREACH_SAFE(peer, &vdev->peer_list,
|
||||
peer_list_elem,
|
||||
tmp_peer) {
|
||||
if (dp_peer_get_ref(soc, peer, mod_id) ==
|
||||
QDF_STATUS_SUCCESS) {
|
||||
(*func)(soc, peer, arg);
|
||||
dp_peer_unref_delete(peer, mod_id);
|
||||
}
|
||||
}
|
||||
qdf_spin_unlock_bh(&vdev->peer_list_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* dp_pdev_iterate_peer() - API to iterate through all peers of pdev
|
||||
*
|
||||
* @pdev : DP pdev context
|
||||
* @func : function to be called for each peer
|
||||
* @arg : argument need to be passed to func
|
||||
* @mod_id : module_id
|
||||
*
|
||||
* Return: void
|
||||
*/
|
||||
static inline void
|
||||
dp_pdev_iterate_peer(struct dp_pdev *pdev, dp_peer_iter_func *func, void *arg,
|
||||
enum dp_peer_mod_id mod_id)
|
||||
{
|
||||
struct dp_vdev *vdev;
|
||||
|
||||
if (!pdev)
|
||||
return;
|
||||
|
||||
qdf_spin_lock_bh(&pdev->vdev_list_lock);
|
||||
DP_PDEV_ITERATE_VDEV_LIST(pdev, vdev)
|
||||
dp_vdev_iterate_peer(vdev, func, arg, mod_id);
|
||||
qdf_spin_unlock_bh(&pdev->vdev_list_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* dp_soc_iterate_peer() - API to iterate through all peers of soc
|
||||
*
|
||||
* @soc : DP soc context
|
||||
* @func : function to be called for each peer
|
||||
* @arg : argument need to be passed to func
|
||||
* @mod_id : module_id
|
||||
*
|
||||
* Return: void
|
||||
*/
|
||||
static inline void
|
||||
dp_soc_iterate_peer(struct dp_soc *soc, dp_peer_iter_func *func, void *arg,
|
||||
enum dp_peer_mod_id mod_id)
|
||||
{
|
||||
struct dp_pdev *pdev;
|
||||
int i;
|
||||
|
||||
if (!soc)
|
||||
return;
|
||||
|
||||
for (i = 0; i < MAX_PDEV_CNT && soc->pdev_list[i]; i++) {
|
||||
pdev = soc->pdev_list[i];
|
||||
dp_pdev_iterate_peer(pdev, func, arg, mod_id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* dp_vdev_iterate_peer_lock_safe() - API to iterate through vdev list
|
||||
*
|
||||
* This API will cache the peers in local allocated memory and calls
|
||||
* iterate function outside the lock.
|
||||
*
|
||||
* As this API is allocating new memory it is suggested to use this
|
||||
* only when lock cannot be held
|
||||
*
|
||||
* @vdev : DP vdev context
|
||||
* @func : function to be called for each peer
|
||||
* @arg : argument need to be passed to func
|
||||
* @mod_id : module_id
|
||||
*
|
||||
* Return: void
|
||||
*/
|
||||
static inline void
|
||||
dp_vdev_iterate_peer_lock_safe(struct dp_vdev *vdev,
|
||||
dp_peer_iter_func *func,
|
||||
void *arg,
|
||||
enum dp_peer_mod_id mod_id)
|
||||
{
|
||||
struct dp_peer *peer;
|
||||
struct dp_peer *tmp_peer;
|
||||
struct dp_soc *soc = NULL;
|
||||
struct dp_peer **peer_array = NULL;
|
||||
int i = 0;
|
||||
uint32_t num_peers = 0;
|
||||
|
||||
if (!vdev || !vdev->pdev || !vdev->pdev->soc)
|
||||
return;
|
||||
|
||||
num_peers = vdev->num_peers;
|
||||
|
||||
soc = vdev->pdev->soc;
|
||||
|
||||
peer_array = qdf_mem_malloc(num_peers * sizeof(struct dp_peer *));
|
||||
if (!peer_array)
|
||||
return;
|
||||
|
||||
qdf_spin_lock_bh(&vdev->peer_list_lock);
|
||||
TAILQ_FOREACH_SAFE(peer, &vdev->peer_list,
|
||||
peer_list_elem,
|
||||
tmp_peer) {
|
||||
if (i >= num_peers)
|
||||
break;
|
||||
|
||||
if (dp_peer_get_ref(soc, peer, mod_id) == QDF_STATUS_SUCCESS) {
|
||||
peer_array[i] = peer;
|
||||
i = (i + 1);
|
||||
}
|
||||
}
|
||||
qdf_spin_unlock_bh(&vdev->peer_list_lock);
|
||||
|
||||
for (i = 0; i < num_peers; i++) {
|
||||
peer = peer_array[i];
|
||||
|
||||
if (!peer)
|
||||
continue;
|
||||
|
||||
(*func)(soc, peer, arg);
|
||||
dp_peer_unref_delete(peer, mod_id);
|
||||
}
|
||||
|
||||
qdf_mem_free(peer_array);
|
||||
}
|
||||
|
||||
/**
|
||||
* dp_pdev_iterate_peer_lock_safe() - API to iterate through all peers of pdev
|
||||
*
|
||||
* This API will cache the peers in local allocated memory and calls
|
||||
* iterate function outside the lock.
|
||||
*
|
||||
* As this API is allocating new memory it is suggested to use this
|
||||
* only when lock cannot be held
|
||||
*
|
||||
* @pdev : DP pdev context
|
||||
* @func : function to be called for each peer
|
||||
* @arg : argument need to be passed to func
|
||||
* @mod_id : module_id
|
||||
*
|
||||
* Return: void
|
||||
*/
|
||||
static inline void
|
||||
dp_pdev_iterate_peer_lock_safe(struct dp_pdev *pdev,
|
||||
dp_peer_iter_func *func,
|
||||
void *arg,
|
||||
enum dp_peer_mod_id mod_id)
|
||||
{
|
||||
struct dp_peer *peer;
|
||||
struct dp_peer *tmp_peer;
|
||||
struct dp_soc *soc = NULL;
|
||||
struct dp_vdev *vdev = NULL;
|
||||
struct dp_peer **peer_array[DP_PDEV_MAX_VDEVS] = {0};
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
uint32_t num_peers[DP_PDEV_MAX_VDEVS] = {0};
|
||||
|
||||
if (!pdev || !pdev->soc)
|
||||
return;
|
||||
|
||||
soc = pdev->soc;
|
||||
|
||||
qdf_spin_lock_bh(&pdev->vdev_list_lock);
|
||||
DP_PDEV_ITERATE_VDEV_LIST(pdev, vdev) {
|
||||
num_peers[i] = vdev->num_peers;
|
||||
peer_array[i] = qdf_mem_malloc(num_peers[i] *
|
||||
sizeof(struct dp_peer *));
|
||||
if (!peer_array[i])
|
||||
break;
|
||||
|
||||
qdf_spin_lock_bh(&vdev->peer_list_lock);
|
||||
TAILQ_FOREACH_SAFE(peer, &vdev->peer_list,
|
||||
peer_list_elem,
|
||||
tmp_peer) {
|
||||
if (j >= num_peers[i])
|
||||
break;
|
||||
|
||||
if (dp_peer_get_ref(soc, peer, mod_id) ==
|
||||
QDF_STATUS_SUCCESS) {
|
||||
peer_array[i][j] = peer;
|
||||
|
||||
j = (j + 1);
|
||||
}
|
||||
}
|
||||
qdf_spin_unlock_bh(&vdev->peer_list_lock);
|
||||
i = (i + 1);
|
||||
}
|
||||
qdf_spin_unlock_bh(&pdev->vdev_list_lock);
|
||||
|
||||
for (i = 0; i < DP_PDEV_MAX_VDEVS; i++) {
|
||||
if (!peer_array[i])
|
||||
break;
|
||||
|
||||
for (j = 0; j < num_peers[i]; j++) {
|
||||
peer = peer_array[i][j];
|
||||
|
||||
if (!peer)
|
||||
continue;
|
||||
|
||||
(*func)(soc, peer, arg);
|
||||
dp_peer_unref_delete(peer, mod_id);
|
||||
}
|
||||
|
||||
qdf_mem_free(peer_array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* dp_soc_iterate_peer_lock_safe() - API to iterate through all peers of soc
|
||||
*
|
||||
* This API will cache the peers in local allocated memory and calls
|
||||
* iterate function outside the lock.
|
||||
*
|
||||
* As this API is allocating new memory it is suggested to use this
|
||||
* only when lock cannot be held
|
||||
*
|
||||
* @soc : DP soc context
|
||||
* @func : function to be called for each peer
|
||||
* @arg : argument need to be passed to func
|
||||
* @mod_id : module_id
|
||||
*
|
||||
* Return: void
|
||||
*/
|
||||
static inline void
|
||||
dp_soc_iterate_peer_lock_safe(struct dp_soc *soc,
|
||||
dp_peer_iter_func *func,
|
||||
void *arg,
|
||||
enum dp_peer_mod_id mod_id)
|
||||
{
|
||||
struct dp_pdev *pdev;
|
||||
int i;
|
||||
|
||||
if (!soc)
|
||||
return;
|
||||
|
||||
for (i = 0; i < MAX_PDEV_CNT && soc->pdev_list[i]; i++) {
|
||||
pdev = soc->pdev_list[i];
|
||||
dp_pdev_iterate_peer_lock_safe(pdev, func, arg, mod_id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* dp_peer_update_state() - update dp peer state
|
||||
*
|
||||
|
مرجع در شماره جدید
Block a user