qcacmn: Deregister IPA handler from pdev during deinit

A htt message arrived after ipa context is freed as part of
deinitialization which was dereferenced by event handler
assigned to pdev->ipa_uc_op_cb, resulting in crash.
To fix this, during deinit pdev->ipa_uc_op_cb is deregistered
and assigned NULL before freeing up ipa context.

Change-Id: I8125cb104a538e88cda93960f7443129fabd850a
CRs-Fixed: 2793295
This commit is contained in:
Ananya Gupta
2020-10-09 21:32:34 +05:30
committed by snandini
parent f1bed41f65
commit 936ca8fe36
5 changed files with 49 additions and 0 deletions

View File

@@ -161,6 +161,28 @@ cdp_ipa_register_op_cb(ol_txrx_soc_handle soc, uint8_t pdev_id,
return QDF_STATUS_SUCCESS;
}
/**
* cdp_ipa_deregister_op_cb() - deregister event handler function pointer
* @soc - data path soc handle
* @pdev_id - device instance id
*
* Deregister event handler function pointer from pdev
*
* return QDF_STATUS_SUCCESS
*/
static inline
void cdp_ipa_deregister_op_cb(ol_txrx_soc_handle soc, uint8_t pdev_id)
{
if (!soc || !soc->ops || !soc->ops->ipa_ops) {
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL,
"%s invalid instance", __func__);
return;
}
if (soc->ops->ipa_ops->ipa_deregister_op_cb)
soc->ops->ipa_ops->ipa_deregister_op_cb(soc, pdev_id);
}
/**
* cdp_ipa_get_stat() - get IPA data path stats from FW
* @soc - data path soc handle

View File

@@ -1555,6 +1555,8 @@ struct cdp_ipa_ops {
void (*ipa_uc_op_cb_type)
(uint8_t *op_msg, void *osif_ctxt),
void *usr_ctxt);
void (*ipa_deregister_op_cb)(struct cdp_soc_t *soc_hdl,
uint8_t pdev_id);
QDF_STATUS (*ipa_get_stat)(struct cdp_soc_t *soc_hdl, uint8_t pdev_id);
qdf_nbuf_t (*ipa_tx_data_frame)(struct cdp_soc_t *soc_hdl,
uint8_t vdev_id, qdf_nbuf_t skb);

View File

@@ -845,6 +845,21 @@ QDF_STATUS dp_ipa_register_op_cb(struct cdp_soc_t *soc_hdl, uint8_t pdev_id,
return QDF_STATUS_SUCCESS;
}
void dp_ipa_deregister_op_cb(struct cdp_soc_t *soc_hdl, uint8_t pdev_id)
{
struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
struct dp_pdev *pdev = dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id);
if (!pdev) {
dp_err("Invalid instance");
return;
}
dp_debug("Deregister OP handler callback");
pdev->ipa_uc_op_cb = NULL;
pdev->usr_ctxt = NULL;
}
QDF_STATUS dp_ipa_get_stat(struct cdp_soc_t *soc_hdl, uint8_t pdev_id)
{
/* TBD */

View File

@@ -95,6 +95,15 @@ QDF_STATUS dp_ipa_op_response(struct cdp_soc_t *soc_hdl, uint8_t pdev_id,
QDF_STATUS dp_ipa_register_op_cb(struct cdp_soc_t *soc_hdl, uint8_t pdev_id,
ipa_uc_op_cb_type op_cb, void *usr_ctxt);
/**
* dp_ipa_register_op_cb() - Deregister OP handler function
* @soc_hdl - data path soc handle
* @pdev_id - device instance id
*
* Return: none
*/
void dp_ipa_deregister_op_cb(struct cdp_soc_t *soc_hdl, uint8_t pdev_id);
/**
* dp_ipa_get_stat() - Get firmware wdi status
* @soc_hdl - data path soc handle

View File

@@ -11419,6 +11419,7 @@ static struct cdp_ipa_ops dp_ops_ipa = {
.ipa_set_doorbell_paddr = dp_ipa_set_doorbell_paddr,
.ipa_op_response = dp_ipa_op_response,
.ipa_register_op_cb = dp_ipa_register_op_cb,
.ipa_deregister_op_cb = dp_ipa_deregister_op_cb,
.ipa_get_stat = dp_ipa_get_stat,
.ipa_tx_data_frame = dp_tx_send_ipa_data_frame,
.ipa_enable_autonomy = dp_ipa_enable_autonomy,