diff options
| author | gbian <gbian@codeaurora.org> | 2017-03-01 18:40:48 +0800 |
|---|---|---|
| committer | qcabuildsw <qcabuildsw@localhost> | 2017-03-04 09:45:43 -0800 |
| commit | ba69fd20745209da8fdf92e2cc0b6c43f80a5c40 (patch) | |
| tree | 87e9fa65becc6d11f8ea12ce155acb1a9617d793 | |
| parent | 22d53bf3045c4d4b96dd2d498c8cdaa25be58a0e (diff) | |
qcacld-3.0: Add vdev checking in the ol_tx_desc_free to avoid crash
qcacld-2.0 to qcacld-3.0 propagation
The ol_tx_desc_free might access the invalid content of vdev referred by tx
desc, since this vdev might be detached in another thread asynchronous.
Go through tx desc pool to set corresponding tx desc's vdev to NULL
when detach this vdev, and add vdev checking in the ol_tx_desc_free to
avoid crash.
Change-Id: I3afa63659e047bbbf008440335fb71c8295ca353
CRs-Fixed: 1087690
| -rw-r--r-- | core/dp/txrx/ol_tx_desc.c | 8 | ||||
| -rw-r--r-- | core/dp/txrx/ol_tx_send.c | 2 | ||||
| -rw-r--r-- | core/dp/txrx/ol_txrx.c | 52 | ||||
| -rw-r--r-- | core/dp/txrx/ol_txrx_types.h | 4 |
4 files changed, 64 insertions, 2 deletions
diff --git a/core/dp/txrx/ol_tx_desc.c b/core/dp/txrx/ol_tx_desc.c index 1e2b48d5c605..519aaea94c67 100644 --- a/core/dp/txrx/ol_tx_desc.c +++ b/core/dp/txrx/ol_tx_desc.c @@ -156,6 +156,8 @@ struct ol_tx_desc_t *ol_tx_desc_alloc(struct ol_txrx_pdev_t *pdev, if (!tx_desc) return NULL; + tx_desc->vdev_id = vdev->vdev_id; + ol_tx_desc_vdev_update(tx_desc, vdev); ol_tx_desc_count_inc(vdev); qdf_atomic_inc(&tx_desc->ref_cnt); @@ -222,6 +224,8 @@ struct ol_tx_desc_t *ol_tx_desc_alloc(struct ol_txrx_pdev_t *pdev, pdev->pool_stats.pkt_drop_no_pool++; } + tx_desc->vdev_id = vdev->vdev_id; + return tx_desc; } @@ -366,6 +370,7 @@ void ol_tx_desc_free(struct ol_txrx_pdev_t *pdev, struct ol_tx_desc_t *tx_desc) ol_tx_put_desc_global_pool(pdev, tx_desc); ol_tx_desc_vdev_rm(tx_desc); + tx_desc->vdev_id = OL_TXRX_INVALID_VDEV_ID; qdf_spin_unlock_bh(&pdev->tx_mutex); } @@ -416,6 +421,9 @@ void ol_tx_desc_free(struct ol_txrx_pdev_t *pdev, struct ol_tx_desc_t *tx_desc) __func__, __LINE__); break; }; + + tx_desc->vdev_id = OL_TXRX_INVALID_VDEV_ID; + qdf_spin_unlock_bh(&pool->flow_pool_lock); } diff --git a/core/dp/txrx/ol_tx_send.c b/core/dp/txrx/ol_tx_send.c index ded02d24da03..6c0db9503186 100644 --- a/core/dp/txrx/ol_tx_send.c +++ b/core/dp/txrx/ol_tx_send.c @@ -643,7 +643,7 @@ void ol_tx_desc_update_group_credit(ol_txrx_pdev_handle pdev, OL_TXQ_GROUP_VDEV_ID_MASK_GET( pdev->txq_grps[i].membership); is_member = OL_TXQ_GROUP_VDEV_ID_BIT_MASK_GET(vdev_id_mask, - tx_desc->vdev->vdev_id); + tx_desc->vdev_id); if (is_member) { ol_txrx_update_group_credit(&pdev->txq_grps[i], credit, absolute); diff --git a/core/dp/txrx/ol_txrx.c b/core/dp/txrx/ol_txrx.c index 3fa99d33e600..8b7ee0e2cebb 100644 --- a/core/dp/txrx/ol_txrx.c +++ b/core/dp/txrx/ol_txrx.c @@ -2104,6 +2104,34 @@ void ol_txrx_set_drop_unenc(ol_txrx_vdev_handle vdev, uint32_t val) vdev->drop_unenc = val; } +#if defined(CONFIG_HL_SUPPORT) + +static void +ol_txrx_tx_desc_reset_vdev(ol_txrx_vdev_handle vdev) +{ + struct ol_txrx_pdev_t *pdev = vdev->pdev; + int i; + struct ol_tx_desc_t *tx_desc; + + qdf_spin_lock_bh(&pdev->tx_mutex); + for (i = 0; i < pdev->tx_desc.pool_size; i++) { + tx_desc = ol_tx_desc_find(pdev, i); + if (tx_desc->vdev == vdev) + tx_desc->vdev = NULL; + } + qdf_spin_unlock_bh(&pdev->tx_mutex); +} + +#else + +static void +ol_txrx_tx_desc_reset_vdev(ol_txrx_vdev_handle vdev) +{ + +} + +#endif + /** * ol_txrx_vdev_detach - Deallocate the specified data virtual * device object. @@ -2196,6 +2224,18 @@ ol_txrx_vdev_detach(ol_txrx_vdev_handle vdev, htt_vdev_detach(pdev->htt_pdev, vdev->vdev_id); /* + * The ol_tx_desc_free might access the invalid content of vdev referred + * by tx desc, since this vdev might be detached in another thread + * asynchronous. + * + * Go through tx desc pool to set corresponding tx desc's vdev to NULL + * when detach this vdev, and add vdev checking in the ol_tx_desc_free + * to avoid crash. + * + */ + ol_txrx_tx_desc_reset_vdev(vdev); + + /* * Doesn't matter if there are outstanding tx frames - * they will be freed once the target sends a tx completion * message for them. @@ -3082,13 +3122,23 @@ int ol_txrx_peer_unref_delete(ol_txrx_peer_handle peer, vdev->delete.callback; void *vdev_delete_context = vdev->delete.context; - /* * Now that there are no references to the peer, * we can release the peer reference lock. */ qdf_spin_unlock_bh(&pdev->peer_ref_mutex); + /* + * The ol_tx_desc_free might access the invalid content of vdev + * referred by tx desc, since this vdev might be detached in + * another thread asynchronous. + * + * Go through tx desc pool to set corresponding tx desc's vdev + * to NULL when detach this vdev, and add vdev checking in the + * ol_tx_desc_free to avoid crash. + * + */ + ol_txrx_tx_desc_reset_vdev(vdev); TXRX_PRINT(TXRX_PRINT_LEVEL_INFO1, "%s: deleting vdev object %p " "(%02x:%02x:%02x:%02x:%02x:%02x)" diff --git a/core/dp/txrx/ol_txrx_types.h b/core/dp/txrx/ol_txrx_types.h index ffafadc67562..5fb4784afeb1 100644 --- a/core/dp/txrx/ol_txrx_types.h +++ b/core/dp/txrx/ol_txrx_types.h @@ -89,6 +89,8 @@ #define TXRX_DATA_HISTROGRAM_GRANULARITY 1000 #define TXRX_DATA_HISTROGRAM_NUM_INTERVALS 100 +#define OL_TXRX_INVALID_VDEV_ID (-1) + struct ol_txrx_pdev_t; struct ol_txrx_vdev_t; struct ol_txrx_peer_t; @@ -189,6 +191,8 @@ struct ol_tx_desc_t { */ uint8_t pkt_type; + u_int8_t vdev_id; + struct ol_txrx_vdev_t *vdev; void *txq; |
