qcacmn: cdp: Convergence of cdp_flowctl_ops

Currently the cdp apis are given pdev/vdev/peer
handle as its arguments, which is directly
accessed in those APIs. This can cause a
race-condition in access of the respective
handles if it has been deleted in parallel.

Hence as a part of cdp convergence, pass only
the pdev/vdev id or peer mac address, which will be
used to get the respective handles, and hence
avoiding the unwanted access of the handles if
it has been deleted.

Converged flowctl_ops
- flow_pool_map_handler
- flow_pool_unmap_handler
- dump_flow_pool_info
- tx_desc_thresh_reached

CRs-Fixed: 2539812
Change-Id: I084d3878df84778622340e87bddf90acd3e669d6
This commit is contained in:
Rakesh Pillai
2019-06-28 19:11:23 +05:30
committed by nshrivas
parent c4ffad74c3
commit dce01374cd
6 changed files with 67 additions and 47 deletions

View File

@@ -182,16 +182,16 @@ cdp_vdev_attach(ol_txrx_soc_handle soc, struct cdp_pdev *pdev,
#ifdef DP_FLOW_CTL #ifdef DP_FLOW_CTL
/** /**
* cdp_flow_pool_map() - Create flow pool for vdev * cdp_flow_pool_map() - Create flow pool for vdev
* @soc - data path soc handle * @soc: data path soc handle
* @pdev * @pdev_id: id of dp pdev handle
* @vdev_id - vdev_id corresponding to vdev start * @vdev_id: vdev_id corresponding to vdev start
* *
* Create per vdev flow pool. * Create per vdev flow pool.
* *
* return none * return none
*/ */
static inline QDF_STATUS cdp_flow_pool_map(ol_txrx_soc_handle soc, static inline QDF_STATUS cdp_flow_pool_map(ol_txrx_soc_handle soc,
struct cdp_pdev *pdev, uint8_t vdev_id) uint8_t pdev_id, uint8_t vdev_id)
{ {
if (!soc || !soc->ops) { if (!soc || !soc->ops) {
QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG,
@@ -204,21 +204,22 @@ static inline QDF_STATUS cdp_flow_pool_map(ol_txrx_soc_handle soc,
!soc->ops->flowctl_ops->flow_pool_map_handler) !soc->ops->flowctl_ops->flow_pool_map_handler)
return QDF_STATUS_E_INVAL; return QDF_STATUS_E_INVAL;
return soc->ops->flowctl_ops->flow_pool_map_handler(soc, pdev, vdev_id); return soc->ops->flowctl_ops->flow_pool_map_handler(soc, pdev_id,
vdev_id);
} }
/** /**
* cdp_flow_pool_unmap() - Delete flow pool * cdp_flow_pool_unmap() - Delete flow pool
* @soc - data path soc handle * @soc: data path soc handle
* @pdev * @pdev_id: id of dp pdev handle
* @vdev_id - vdev_id corresponding to vdev start * @vdev_id: vdev_id corresponding to vdev start
* *
* Delete flow pool * Delete flow pool
* *
* return none * return none
*/ */
static inline void cdp_flow_pool_unmap(ol_txrx_soc_handle soc, static inline void cdp_flow_pool_unmap(ol_txrx_soc_handle soc,
struct cdp_pdev *pdev, uint8_t vdev_id) uint8_t pdev_id, uint8_t vdev_id)
{ {
if (!soc || !soc->ops) { if (!soc || !soc->ops) {
QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG,
@@ -231,7 +232,7 @@ static inline void cdp_flow_pool_unmap(ol_txrx_soc_handle soc,
!soc->ops->flowctl_ops->flow_pool_unmap_handler) !soc->ops->flowctl_ops->flow_pool_unmap_handler)
return; return;
return soc->ops->flowctl_ops->flow_pool_unmap_handler(soc, pdev, return soc->ops->flowctl_ops->flow_pool_unmap_handler(soc, pdev_id,
vdev_id); vdev_id);
} }
#endif #endif

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved.
* *
* Permission to use, copy, modify, and/or distribute this software for * Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the * any purpose with or without fee is hereby granted, provided that the
@@ -92,8 +92,6 @@ cdp_set_desc_global_pool_size(ol_txrx_soc_handle soc,
static inline void static inline void
cdp_dump_flow_pool_info(struct cdp_soc_t *soc) cdp_dump_flow_pool_info(struct cdp_soc_t *soc)
{ {
void *dp_soc = (void *)soc;
if (!soc || !soc->ops) { if (!soc || !soc->ops) {
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
"%s invalid instance", __func__); "%s invalid instance", __func__);
@@ -105,18 +103,18 @@ cdp_dump_flow_pool_info(struct cdp_soc_t *soc)
!soc->ops->flowctl_ops->dump_flow_pool_info) !soc->ops->flowctl_ops->dump_flow_pool_info)
return; return;
soc->ops->flowctl_ops->dump_flow_pool_info(dp_soc); soc->ops->flowctl_ops->dump_flow_pool_info(soc);
} }
/** /**
* cdp_tx_desc_thresh_reached() - Check if avail tx desc meet threshold * cdp_tx_desc_thresh_reached() - Check if avail tx desc meet threshold
* @soc - data path soc handle * @soc: data path soc handle
* @vdev - dp vdev handle * @vdev_id: vdev_id corresponding to vdev start
* *
* Return: true if threshold is met, false if not * Return: true if threshold is met, false if not
*/ */
static inline bool static inline bool
cdp_tx_desc_thresh_reached(struct cdp_soc_t *soc, struct cdp_vdev *vdev) cdp_tx_desc_thresh_reached(struct cdp_soc_t *soc, uint8_t vdev_id)
{ {
if (!soc || !soc->ops) { if (!soc || !soc->ops) {
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
@@ -129,6 +127,6 @@ cdp_tx_desc_thresh_reached(struct cdp_soc_t *soc, struct cdp_vdev *vdev)
!soc->ops->flowctl_ops->tx_desc_thresh_reached) !soc->ops->flowctl_ops->tx_desc_thresh_reached)
return false; return false;
return soc->ops->flowctl_ops->tx_desc_thresh_reached(vdev); return soc->ops->flowctl_ops->tx_desc_thresh_reached(soc, vdev_id);
} }
#endif /* _CDP_TXRX_FC_V2_H_ */ #endif /* _CDP_TXRX_FC_V2_H_ */

View File

@@ -1233,24 +1233,30 @@ struct cdp_cfg_ops {
/** /**
* struct cdp_flowctl_ops - mcl flow control * struct cdp_flowctl_ops - mcl flow control
* @register_pause_cb: * @flow_pool_map_handler: handler to map flow_id and pool descriptors
* @set_desc_global_pool_size: * @flow_pool_unmap_handler: handler to unmap flow_id and pool descriptors
* @dump_flow_pool_info: * @register_pause_cb: handler to register tx pause callback
* @set_desc_global_pool_size: handler to set global pool size
* @dump_flow_pool_info: handler to dump global and flow pool info
* @tx_desc_thresh_reached: handler to set tx desc threshold
*
* Function pointers for operations related to flow control
*/ */
struct cdp_flowctl_ops { struct cdp_flowctl_ops {
QDF_STATUS (*flow_pool_map_handler)(struct cdp_soc_t *soc, QDF_STATUS (*flow_pool_map_handler)(struct cdp_soc_t *soc,
struct cdp_pdev *pdev, uint8_t pdev_id,
uint8_t vdev_id); uint8_t vdev_id);
void (*flow_pool_unmap_handler)(struct cdp_soc_t *soc, void (*flow_pool_unmap_handler)(struct cdp_soc_t *soc,
struct cdp_pdev *pdev, uint8_t pdev_id,
uint8_t vdev_id); uint8_t vdev_id);
QDF_STATUS (*register_pause_cb)(struct cdp_soc_t *soc, QDF_STATUS (*register_pause_cb)(struct cdp_soc_t *soc,
tx_pause_callback); tx_pause_callback);
void (*set_desc_global_pool_size)(uint32_t num_msdu_desc); void (*set_desc_global_pool_size)(uint32_t num_msdu_desc);
void (*dump_flow_pool_info)(void *); void (*dump_flow_pool_info)(struct cdp_soc_t *soc_hdl);
bool (*tx_desc_thresh_reached)(struct cdp_vdev *vdev); bool (*tx_desc_thresh_reached)(struct cdp_soc_t *soc_hdl,
uint8_t vdev_id);
}; };
/** /**

View File

@@ -1343,7 +1343,7 @@ static inline QDF_STATUS dp_peer_stats_notify(struct dp_pdev *pdev,
#endif /* CONFIG_WIN */ #endif /* CONFIG_WIN */
#ifdef QCA_LL_TX_FLOW_CONTROL_V2 #ifdef QCA_LL_TX_FLOW_CONTROL_V2
void dp_tx_dump_flow_pool_info(void *soc); void dp_tx_dump_flow_pool_info(struct cdp_soc_t *soc_hdl);
int dp_tx_delete_flow_pool(struct dp_soc *soc, struct dp_tx_desc_pool_s *pool, int dp_tx_delete_flow_pool(struct dp_soc *soc, struct dp_tx_desc_pool_s *pool,
bool force); bool force);
#endif /* QCA_LL_TX_FLOW_CONTROL_V2 */ #endif /* QCA_LL_TX_FLOW_CONTROL_V2 */

View File

@@ -23,7 +23,6 @@
#include "dp_tx.h" #include "dp_tx.h"
#include "dp_internal.h" #include "dp_internal.h"
/** /**
* 21 bits cookie * 21 bits cookie
* 2 bits pool id 0 ~ 3, * 2 bits pool id 0 ~ 3,
@@ -97,9 +96,9 @@ void dp_tx_flow_control_deinit(struct dp_soc *);
QDF_STATUS dp_txrx_register_pause_cb(struct cdp_soc_t *soc, QDF_STATUS dp_txrx_register_pause_cb(struct cdp_soc_t *soc,
tx_pause_callback pause_cb); tx_pause_callback pause_cb);
QDF_STATUS dp_tx_flow_pool_map(struct cdp_soc_t *soc, struct cdp_pdev *pdev, QDF_STATUS dp_tx_flow_pool_map(struct cdp_soc_t *soc, uint8_t pdev_id,
uint8_t vdev_id); uint8_t vdev_id);
void dp_tx_flow_pool_unmap(struct cdp_soc_t *soc, struct cdp_pdev *pdev, void dp_tx_flow_pool_unmap(struct cdp_soc_t *handle, uint8_t pdev_id,
uint8_t vdev_id); uint8_t vdev_id);
void dp_tx_clear_flow_pool_stats(struct dp_soc *soc); void dp_tx_clear_flow_pool_stats(struct dp_soc *soc);
struct dp_tx_desc_pool_s *dp_tx_create_flow_pool(struct dp_soc *soc, struct dp_tx_desc_pool_s *dp_tx_create_flow_pool(struct dp_soc *soc,
@@ -489,15 +488,17 @@ out:
#endif /* QCA_AC_BASED_FLOW_CONTROL */ #endif /* QCA_AC_BASED_FLOW_CONTROL */
static inline bool static inline bool
dp_tx_desc_thresh_reached(struct cdp_vdev *vdev) dp_tx_desc_thresh_reached(struct cdp_soc_t *soc_hdl, uint8_t vdev_id)
{ {
struct dp_vdev *dp_vdev = (struct dp_vdev *)vdev; struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
struct dp_vdev *vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc,
vdev_id);
struct dp_tx_desc_pool_s *pool; struct dp_tx_desc_pool_s *pool;
if (!vdev) if (!vdev)
return false; return false;
pool = dp_vdev->pool; pool = vdev->pool;
return dp_tx_is_threshold_reached(pool, pool->avail_desc); return dp_tx_is_threshold_reached(pool, pool->avail_desc);
} }

View File

@@ -173,9 +173,9 @@ dp_tx_flow_pool_dump_threshold(struct dp_tx_desc_pool_s *pool)
* *
* Return: none * Return: none
*/ */
void dp_tx_dump_flow_pool_info(void *ctx) void dp_tx_dump_flow_pool_info(struct cdp_soc_t *soc_hdl)
{ {
struct dp_soc *soc = ctx; struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
struct dp_txrx_pool_stats *pool_stats = &soc->pool_stats; struct dp_txrx_pool_stats *pool_stats = &soc->pool_stats;
struct dp_tx_desc_pool_s *pool = NULL; struct dp_tx_desc_pool_s *pool = NULL;
struct dp_tx_desc_pool_s tmp_pool; struct dp_tx_desc_pool_s tmp_pool;
@@ -357,8 +357,7 @@ static void dp_tx_flow_pool_vdev_map(struct dp_pdev *pdev,
struct dp_vdev *vdev; struct dp_vdev *vdev;
struct dp_soc *soc = pdev->soc; struct dp_soc *soc = pdev->soc;
vdev = (struct dp_vdev *)cdp_get_vdev_from_vdev_id((void *)soc, vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc, vdev_id);
(struct cdp_pdev *)pdev, vdev_id);
if (!vdev) { if (!vdev) {
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
"%s: invalid vdev_id %d", "%s: invalid vdev_id %d",
@@ -387,8 +386,7 @@ static void dp_tx_flow_pool_vdev_unmap(struct dp_pdev *pdev,
struct dp_vdev *vdev; struct dp_vdev *vdev;
struct dp_soc *soc = pdev->soc; struct dp_soc *soc = pdev->soc;
vdev = (struct dp_vdev *)cdp_get_vdev_from_vdev_id((void *)soc, vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc, vdev_id);
(struct cdp_pdev *)pdev, vdev_id);
if (!vdev) { if (!vdev) {
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
"%s: invalid vdev_id %d", "%s: invalid vdev_id %d",
@@ -571,19 +569,35 @@ QDF_STATUS dp_txrx_register_pause_cb(struct cdp_soc_t *handle,
return QDF_STATUS_SUCCESS; return QDF_STATUS_SUCCESS;
} }
QDF_STATUS dp_tx_flow_pool_map(struct cdp_soc_t *handle, struct cdp_pdev *pdev, QDF_STATUS dp_tx_flow_pool_map(struct cdp_soc_t *handle, uint8_t pdev_id,
uint8_t vdev_id) uint8_t vdev_id)
{ {
struct dp_soc *soc = (struct dp_soc *)handle; struct dp_soc *soc = cdp_soc_t_to_dp_soc(handle);
struct dp_pdev *pdev =
dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id);
int tx_ring_size = wlan_cfg_tx_ring_size(soc->wlan_cfg_ctx); int tx_ring_size = wlan_cfg_tx_ring_size(soc->wlan_cfg_ctx);
return (dp_tx_flow_pool_map_handler((struct dp_pdev *)pdev, vdev_id, if (!pdev) {
FLOW_TYPE_VDEV, vdev_id, tx_ring_size)); dp_err("pdev is NULL");
return QDF_STATUS_E_INVAL;
}
return dp_tx_flow_pool_map_handler(pdev, vdev_id, FLOW_TYPE_VDEV,
vdev_id, tx_ring_size);
} }
void dp_tx_flow_pool_unmap(struct cdp_soc_t *soc, struct cdp_pdev *pdev, void dp_tx_flow_pool_unmap(struct cdp_soc_t *handle, uint8_t pdev_id,
uint8_t vdev_id) uint8_t vdev_id)
{ {
return(dp_tx_flow_pool_unmap_handler((struct dp_pdev *)pdev, vdev_id, struct dp_soc *soc = cdp_soc_t_to_dp_soc(handle);
FLOW_TYPE_VDEV, vdev_id)); struct dp_pdev *pdev =
dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id);
if (!pdev) {
dp_err("pdev is NULL");
return;
}
return dp_tx_flow_pool_unmap_handler(pdev, vdev_id,
FLOW_TYPE_VDEV, vdev_id);
} }