diff --git a/components/dsc/src/wlan_dsc_psoc.c b/components/dsc/src/wlan_dsc_psoc.c index a5248c4d8c..7acc44a0ac 100644 --- a/components/dsc/src/wlan_dsc_psoc.c +++ b/components/dsc/src/wlan_dsc_psoc.c @@ -126,11 +126,34 @@ static bool __dsc_psoc_trans_active_down_tree(struct dsc_psoc *psoc) #define __dsc_psoc_can_op(psoc) __dsc_psoc_can_trans(psoc) -static bool __dsc_psoc_can_trans(struct dsc_psoc *psoc) +/* + * __dsc_psoc_can_trans() - Returns if the psoc transition can occur or not + * @psoc: The DSC psoc + * + * This function checks if the psoc transition can occur or not by checking if + * any other down the tree/up the tree transition/operation is taking place. + * + * If there are any driver transition taking place, then the psoc trans/ops + * should be rejected and not queued in the DSC queue. Return QDF_STATUS_E_INVAL + * in this case. + * + * If there any psoc or vdev trans/ops is taking place, then the psoc trans/ops + * should be rejected and queued in the DSC queue so that it may be resumed + * after the current trans/ops is completed. Return QDF_STATUS_E_AGAIN in this + * case. + * + * Return: QDF_STATUS_SUCCESS if transition is allowed, error code if not. + */ +static QDF_STATUS __dsc_psoc_can_trans(struct dsc_psoc *psoc) { - return !__dsc_trans_active_or_queued(&psoc->driver->trans) && - !__dsc_trans_active_or_queued(&psoc->trans) && - !__dsc_psoc_trans_active_down_tree(psoc); + if (__dsc_trans_active_or_queued(&psoc->driver->trans)) + return QDF_STATUS_E_INVAL; + + if (__dsc_trans_active_or_queued(&psoc->trans) || + __dsc_psoc_trans_active_down_tree(psoc)) + return QDF_STATUS_E_AGAIN; + + return QDF_STATUS_SUCCESS; } static bool __dsc_psoc_can_trigger(struct dsc_psoc *psoc) @@ -143,8 +166,11 @@ static bool __dsc_psoc_can_trigger(struct dsc_psoc *psoc) static QDF_STATUS __dsc_psoc_trans_start_nolock(struct dsc_psoc *psoc, const char *desc) { - if (!__dsc_psoc_can_trans(psoc)) - return QDF_STATUS_E_AGAIN; + QDF_STATUS status; + + status = __dsc_psoc_can_trans(psoc); + if (QDF_IS_STATUS_ERROR(status)) + return status; return __dsc_trans_start(&psoc->trans, desc); } @@ -194,7 +220,7 @@ __dsc_psoc_trans_start_wait(struct dsc_psoc *psoc, const char *desc) /* try to start without waiting */ status = __dsc_psoc_trans_start_nolock(psoc, desc); - if (QDF_IS_STATUS_SUCCESS(status)) + if (QDF_IS_STATUS_SUCCESS(status) || status == QDF_STATUS_E_INVAL) goto unlock; status = __dsc_trans_queue(&psoc->trans, &tran, desc); @@ -298,10 +324,9 @@ static QDF_STATUS __dsc_psoc_op_start(struct dsc_psoc *psoc, const char *func) __dsc_driver_lock(psoc); - if (!__dsc_psoc_can_op(psoc)) { - status = QDF_STATUS_E_AGAIN; + status = __dsc_psoc_can_op(psoc); + if (QDF_IS_STATUS_ERROR(status)) goto unlock; - } status = __dsc_ops_insert(&psoc->ops, func); @@ -349,9 +374,6 @@ static void __dsc_psoc_wait_for_ops(struct dsc_psoc *psoc) __dsc_driver_lock(psoc); - /* flushing without preventing new ops is almost certainly a bug */ - dsc_assert(!__dsc_psoc_can_op(psoc)); - wait = psoc->ops.count > 0; if (wait) qdf_event_reset(&psoc->ops.event); diff --git a/components/dsc/src/wlan_dsc_vdev.c b/components/dsc/src/wlan_dsc_vdev.c index 462d3e380a..edb9bd91b2 100644 --- a/components/dsc/src/wlan_dsc_vdev.c +++ b/components/dsc/src/wlan_dsc_vdev.c @@ -108,18 +108,44 @@ void dsc_vdev_destroy(struct dsc_vdev **out_vdev) #define __dsc_vdev_can_op(vdev) __dsc_vdev_can_trans(vdev) -static bool __dsc_vdev_can_trans(struct dsc_vdev *vdev) +/* + * __dsc_vdev_can_trans() - Returns if the vdev transition can occur or not + * @vdev: The DSC vdev + * + * This function checks if the vdev transition can occur or not by checking if + * any other down the tree/up the tree transition/operation is taking place. + * + * If there are any driver transition taking place, then the vdev trans/ops + * should be rejected and not queued in the DSC queue. Return QDF_STATUS_E_INVAL + * in this case. + * + * If there any psoc or vdev trans/ops is taking place, then the vdev trans/ops + * should be rejected and queued in the DSC queue so that it may be resumed + * after the current trans/ops is completed. Return QDF_STATUS_E_AGAIN in this + * case. + * + * Return: QDF_STATUS_SUCCESS if transition is allowed, error code if not. + */ +static QDF_STATUS __dsc_vdev_can_trans(struct dsc_vdev *vdev) { - return !__dsc_trans_active_or_queued(&vdev->psoc->driver->trans) && - !__dsc_trans_active_or_queued(&vdev->psoc->trans) && - !__dsc_trans_active_or_queued(&vdev->trans); + if (__dsc_trans_active_or_queued(&vdev->psoc->driver->trans)) + return QDF_STATUS_E_INVAL; + + if (__dsc_trans_active_or_queued(&vdev->psoc->trans) || + __dsc_trans_active_or_queued(&vdev->trans)) + return QDF_STATUS_E_AGAIN; + + return QDF_STATUS_SUCCESS; } static QDF_STATUS __dsc_vdev_trans_start_nolock(struct dsc_vdev *vdev, const char *desc) { - if (!__dsc_vdev_can_trans(vdev)) - return QDF_STATUS_E_AGAIN; + QDF_STATUS status = QDF_STATUS_SUCCESS; + + status = __dsc_vdev_can_trans(vdev); + if (QDF_IS_STATUS_ERROR(status)) + return status; return __dsc_trans_start(&vdev->trans, desc); } @@ -169,7 +195,7 @@ __dsc_vdev_trans_start_wait(struct dsc_vdev *vdev, const char *desc) /* try to start without waiting */ status = __dsc_vdev_trans_start_nolock(vdev, desc); - if (QDF_IS_STATUS_SUCCESS(status)) + if (QDF_IS_STATUS_SUCCESS(status) || status == QDF_STATUS_E_INVAL) goto unlock; status = __dsc_trans_queue(&vdev->trans, &tran, desc); @@ -259,10 +285,9 @@ static QDF_STATUS __dsc_vdev_op_start(struct dsc_vdev *vdev, const char *func) __dsc_driver_lock(vdev); - if (!__dsc_vdev_can_op(vdev)) { - status = QDF_STATUS_E_AGAIN; + status = __dsc_vdev_can_op(vdev); + if (QDF_IS_STATUS_ERROR(status)) goto unlock; - } status = __dsc_ops_insert(&vdev->ops, func); @@ -316,9 +341,6 @@ static void __dsc_vdev_wait_for_ops(struct dsc_vdev *vdev) __dsc_driver_lock(vdev); - /* flushing without preventing new ops is almost certainly a bug */ - dsc_assert(!__dsc_vdev_can_op(vdev)); - wait = vdev->ops.count > 0; if (wait) qdf_event_reset(&vdev->ops.event); diff --git a/components/dsc/test/wlan_dsc_test.c b/components/dsc/test/wlan_dsc_test.c index 3eb54b87a4..0332678906 100644 --- a/components/dsc/test/wlan_dsc_test.c +++ b/components/dsc/test/wlan_dsc_test.c @@ -200,7 +200,6 @@ static uint32_t dsc_test_driver_trans_blocks(void) } /* test */ - /* a driver in transition should cause ... */ action_expect(driver, trans, QDF_STATUS_SUCCESS, errors); @@ -210,13 +209,13 @@ static uint32_t dsc_test_driver_trans_blocks(void) /* ... children psoc trans/ops to fail */ dsc_for_each_driver_psoc(driver, psoc) { - action_expect(psoc, trans, QDF_STATUS_E_AGAIN, errors); - action_expect(psoc, op, QDF_STATUS_E_AGAIN, errors); + action_expect(psoc, trans, QDF_STATUS_E_INVAL, errors); + action_expect(psoc, op, QDF_STATUS_E_INVAL, errors); /* ... grandchildren vdev trans/ops to fail */ dsc_for_each_psoc_vdev(psoc, vdev) { - action_expect(vdev, trans, QDF_STATUS_E_AGAIN, errors); - action_expect(vdev, op, QDF_STATUS_E_AGAIN, errors); + action_expect(vdev, trans, QDF_STATUS_E_INVAL, errors); + action_expect(vdev, op, QDF_STATUS_E_INVAL, errors); } } @@ -251,7 +250,6 @@ static uint32_t dsc_test_psoc_trans_blocks(void) } /* test */ - /* a psoc in transition should cause ... */ psoc = nth_psoc(driver, 1); action_expect(psoc, trans, QDF_STATUS_SUCCESS, errors);