|
@@ -2064,6 +2064,7 @@ ol_txrx_vdev_attach(struct cdp_pdev *ppdev,
|
|
|
vdev->ll_pause.paused_reason = 0;
|
|
|
vdev->ll_pause.txq.head = vdev->ll_pause.txq.tail = NULL;
|
|
|
vdev->ll_pause.txq.depth = 0;
|
|
|
+ qdf_atomic_init(&vdev->delete.detaching);
|
|
|
qdf_timer_init(pdev->osdev,
|
|
|
&vdev->ll_pause.timer,
|
|
|
ol_tx_vdev_ll_pause_queue_send, vdev,
|
|
@@ -2240,16 +2241,19 @@ ol_txrx_vdev_detach(struct cdp_vdev *pvdev,
|
|
|
ol_txrx_vdev_delete_cb callback, void *context)
|
|
|
{
|
|
|
struct ol_txrx_vdev_t *vdev = (struct ol_txrx_vdev_t *)pvdev;
|
|
|
- struct ol_txrx_pdev_t *pdev = vdev->pdev;
|
|
|
+ struct ol_txrx_pdev_t *pdev;
|
|
|
|
|
|
/* preconditions */
|
|
|
TXRX_ASSERT2(vdev);
|
|
|
+ pdev = vdev->pdev;
|
|
|
+
|
|
|
+ /* prevent anyone from restarting the ll_pause timer again */
|
|
|
+ qdf_atomic_set(&vdev->delete.detaching, 1);
|
|
|
|
|
|
ol_txrx_vdev_tx_queue_free(vdev);
|
|
|
|
|
|
qdf_spin_lock_bh(&vdev->ll_pause.mutex);
|
|
|
qdf_timer_stop(&vdev->ll_pause.timer);
|
|
|
- qdf_timer_free(&vdev->ll_pause.timer);
|
|
|
vdev->ll_pause.is_q_timer_on = false;
|
|
|
while (vdev->ll_pause.txq.head) {
|
|
|
qdf_nbuf_t next = qdf_nbuf_next(vdev->ll_pause.txq.head);
|
|
@@ -2261,6 +2265,12 @@ ol_txrx_vdev_detach(struct cdp_vdev *pvdev,
|
|
|
vdev->ll_pause.txq.head = next;
|
|
|
}
|
|
|
qdf_spin_unlock_bh(&vdev->ll_pause.mutex);
|
|
|
+
|
|
|
+ /* ll_pause timer should be deleted without any locks held, and
|
|
|
+ * no timer function should be executed after this point because
|
|
|
+ * qdf_timer_free is deleting the timer synchronously.
|
|
|
+ */
|
|
|
+ qdf_timer_free(&vdev->ll_pause.timer);
|
|
|
qdf_spinlock_destroy(&vdev->ll_pause.mutex);
|
|
|
|
|
|
qdf_spin_lock_bh(&vdev->flow_control_lock);
|