diff --git a/components/dsc/src/wlan_dsc_vdev.c b/components/dsc/src/wlan_dsc_vdev.c index 9bf30e0fae..afd3c2c0c6 100644 --- a/components/dsc/src/wlan_dsc_vdev.c +++ b/components/dsc/src/wlan_dsc_vdev.c @@ -116,9 +116,10 @@ void dsc_vdev_destroy(struct dsc_vdev **out_vdev) * should be rejected and not queued in the DSC queue. Return QDF_STATUS_E_INVAL * in this case. * - * If there are any psoc transition taking place becasue of ssr or driver - * unload, 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 are any psoc transition taking place because of SSR, then vdev + * trans/op should be rejected and queued in the DSC queue so that it may be + * resumed after the current trans/op is completed. return QDF_STATUS_E_AGAIN + * in this case. * * If there is a psoc transition taking place becasue of psoc idle shutdown, * then the vdev trans/ops should be rejected and queued in the DSC queue so @@ -137,12 +138,17 @@ static QDF_STATUS __dsc_vdev_can_trans(struct dsc_vdev *vdev) if (__dsc_trans_active_or_queued(&vdev->psoc->driver->trans)) return QDF_STATUS_E_INVAL; + if (qdf_is_recovering()) + return QDF_STATUS_E_AGAIN; + if (__dsc_trans_active_or_queued(&vdev->psoc->trans)) { /* psoc idle shutdown(wifi off) needs to be added in DSC queue * to avoid wifi on failure while previous psoc idle shutdown - * is in progress and wifi is turned on. + * is in progress and wifi is turned on. And Wifi On also needs + * to be added to the queue so that it waits for SSR to + * complete. */ - if (qdf_is_driver_unloading() || qdf_is_recovering()) + if (qdf_is_driver_unloading()) return QDF_STATUS_E_INVAL; else return QDF_STATUS_E_AGAIN; diff --git a/components/dsc/test/wlan_dsc_test.c b/components/dsc/test/wlan_dsc_test.c index 3354e0d1c1..20c74d0461 100644 --- a/components/dsc/test/wlan_dsc_test.c +++ b/components/dsc/test/wlan_dsc_test.c @@ -284,8 +284,8 @@ static uint32_t dsc_test_psoc_trans_blocks(void) */ cds_set_recovery_in_progress(true); dsc_for_each_psoc_vdev(psoc, vdev) { - action_expect(vdev, trans, QDF_STATUS_E_INVAL, errors); - action_expect(vdev, op, QDF_STATUS_E_INVAL, errors); + action_expect(vdev, trans, QDF_STATUS_E_AGAIN, errors); + action_expect(vdev, op, QDF_STATUS_E_AGAIN, errors); } cds_set_recovery_in_progress(false); diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index b307dc89c5..a948a73b92 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -6039,8 +6039,15 @@ int wlan_hdd_cfg80211_stop_ap(struct wiphy *wiphy, struct osif_vdev_sync *vdev_sync; errno = osif_vdev_sync_op_start(dev, &vdev_sync); + /* + * The stop_ap can be called in the same context through + * wlan_hdd_del_virtual_intf. As vdev_trans is already taking place as + * part of the del_vitrtual_intf, this vdev_op cannot start. + * Return 0 in case op is not started so that the kernel frees the + * beacon memory properly. + */ if (errno) - return errno; + return 0; errno = __wlan_hdd_cfg80211_stop_ap(wiphy, dev);