qcacmn: Update the current bss for non-assoc link

wdev->current_bss is not updated for a non-assoc link STA vdevs.
As a result, a WARN_ON error is seen in cfg80211_ch_switch_notify()
when it’s called for non-assoc link.

To resolve this, update the wdev->current_bss for non-assoc links
as part of connection and clean up this as part of disconnection.

Change-Id: I5020200fb927dd72d2e1bf0ed73e7a5750897619
CRs-Fixed: 3618438
This commit is contained in:
Shashikala Prabhu
2023-09-22 21:22:34 +05:30
committed by Rahul Choudhary
부모 ab8c55ec38
커밋 8713c007bd
2개의 변경된 파일181개의 추가작업 그리고 8개의 파일을 삭제

파일 보기

@@ -878,6 +878,121 @@ static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev,
}
#else /* WLAN_FEATURE_11BE_MLO_ADV_FEATURE */
#if (LINUX_VERSION_CODE == KERNEL_VERSION(5, 4, 0))
/**
* osif_update_current_bss() - Wrapper API to call cfg80211_update_current_bss
* @dev: network device
* @bss: bss info
* @rsp: Connection manager connect response
* @vdev: pointer to vdev
*
* This API is used as wrapper to update the current bss param of non-assoc link
* sta vdev.
*
* Context: Any context.
* Return: QDF_STATUS.
*/
static QDF_STATUS osif_update_current_bss(struct net_device *dev,
struct cfg80211_bss *bss,
struct wlan_cm_connect_resp *rsp,
struct wlan_objmgr_vdev *vdev)
{
struct cfg80211_connect_resp_params conn_rsp_params;
enum ieee80211_statuscode status;
int ret;
osif_enter_dev(dev);
qdf_mem_zero(&conn_rsp_params, sizeof(conn_rsp_params));
status = osif_get_connect_status_code(rsp);
conn_rsp_params.status = status;
osif_copy_connected_info(&conn_rsp_params, rsp, bss, vdev);
osif_debug("Connect resp status %d", conn_rsp_params.status);
ret = cfg80211_update_current_bss(dev, &conn_rsp_params, rsp->ssid.ssid,
rsp->ssid.length);
if (ret)
osif_err("cfg80211_update_current_bss failed for psoc:%d pdev:%d vdev:%d",
wlan_vdev_get_psoc_id(vdev),
wlan_objmgr_pdev_get_pdev_id(wlan_vdev_get_pdev(vdev)),
wlan_vdev_get_id(vdev));
return qdf_status_from_os_return(ret);
}
/**
* osif_update_current_bss_for_non_assoc_link_vdevs() - API to update the
* current_bss param of non-assoc link STA vdev.
* @vdev: Pointer to vdev
* @arg: Connection manager connect response
*
* Return: None.
*/
static void osif_update_current_bss_for_non_assoc_link_vdevs(
struct wlan_objmgr_vdev *vdev, void *arg)
{
struct wlan_objmgr_vdev *assoc_vdev;
struct wlan_cm_connect_resp resp = {0};
struct qdf_mac_addr macaddr = {0};
struct vdev_osif_priv *osif_priv = NULL;
struct wlan_cm_connect_resp *assoc_link_rsp;
assoc_link_rsp = (struct wlan_cm_connect_resp *)arg;
if (!assoc_link_rsp) {
osif_err("assoc_link_rsp is null");
return;
}
assoc_vdev = wlan_mlo_get_assoc_link_vdev(vdev);
/* For assoc vdev cfg80211_connect_done() is called to update the
* current bss param. Hence, skip the assoc vdev here.
*/
if (vdev == assoc_vdev)
return;
wlan_vdev_mlme_get_ssid(vdev, resp.ssid.ssid, &resp.ssid.length);
wlan_vdev_get_bss_peer_mac(vdev, &macaddr);
qdf_mem_copy(resp.bssid.bytes, macaddr.bytes, QDF_MAC_ADDR_SIZE);
resp.connect_status = assoc_link_rsp->connect_status;
osif_debug("vdev:%p bssid:" QDF_MAC_ADDR_FMT " ssid.length:%d ssid: " QDF_SSID_FMT,
vdev, QDF_MAC_ADDR_REF(macaddr.bytes), resp.ssid.length,
QDF_SSID_REF(resp.ssid.length, resp.ssid.ssid));
osif_priv = wlan_vdev_get_ospriv(vdev);
osif_update_current_bss(osif_priv->wdev->netdev, NULL, &resp, vdev);
}
/**
* osif_update_current_bss_for_non_assoc_links() - API to update the
* current_bss param of non-assoc link STA vdev.
* @assoc_vdev: Pointer to assoc vdev
* @rsp: Connection manager connect response
*
* Return: None.
*/
static void osif_update_current_bss_for_non_assoc_links(
struct wlan_objmgr_vdev *assoc_vdev,
struct wlan_cm_connect_resp *rsp)
{
mlo_iterate_connected_vdev_list(
assoc_vdev,
osif_update_current_bss_for_non_assoc_link_vdevs,
rsp);
}
#else
static void osif_update_current_bss_for_non_assoc_links(
struct wlan_objmgr_vdev *assoc_vdev,
struct wlan_cm_connect_resp *rsp)
{
}
#endif
static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev,
struct vdev_osif_priv *osif_priv,
struct wlan_cm_connect_resp *rsp)
@@ -915,7 +1030,7 @@ static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev,
return;
qdf_mem_copy(&resp, rsp, sizeof(struct wlan_cm_connect_resp));
tmp_osif_priv = wlan_vdev_get_ospriv(assoc_vdev);
freq = vdev->vdev_mlme.bss_chan->ch_freq;
freq = assoc_vdev->vdev_mlme.bss_chan->ch_freq;
qdf_mem_copy(macaddr.bytes, rsp->bssid.bytes,
QDF_MAC_ADDR_SIZE);
if (QDF_IS_STATUS_SUCCESS(rsp->connect_status)) {
@@ -938,6 +1053,10 @@ static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev,
if (osif_update_connect_results(tmp_osif_priv->wdev->netdev, bss,
&resp, assoc_vdev))
osif_connect_bss(tmp_osif_priv->wdev->netdev, bss, &resp);
if (QDF_IS_STATUS_SUCCESS(rsp->connect_status))
osif_update_current_bss_for_non_assoc_links(assoc_vdev,
rsp);
}
}
#endif /* WLAN_FEATURE_11BE_MLO_ADV_FEATURE */

파일 보기

@@ -146,6 +146,58 @@ osif_cm_indicate_disconnect(struct wlan_objmgr_vdev *vdev,
}
}
#else /* WLAN_FEATURE_11BE_MLO_ADV_FEATURE */
/**
* osif_cm_get_anchor_vdev() - API to get the anchor vdev
* @vdev: Pointer to vdev
*
* Return: If the assoc vdev is available, return it. Otherwise, if the MLD is
* disconnected, return the current vdev. If neither is available, return NULL.
*/
static struct wlan_objmgr_vdev *osif_cm_get_anchor_vdev(
struct wlan_objmgr_vdev *vdev)
{
struct wlan_objmgr_vdev *assoc_vdev = NULL;
assoc_vdev = ucfg_mlo_get_assoc_link_vdev(vdev);
if (assoc_vdev)
return assoc_vdev;
else if (ucfg_mlo_is_mld_disconnected(vdev))
return vdev;
else
return NULL;
}
#if (LINUX_VERSION_CODE == KERNEL_VERSION(5, 4, 0))
/**
* osif_cm_indicate_disconnect_for_non_assoc_link() - Wrapper API to clear
* current bss param of non-assoc link
* @netdev: Pointer to netdev of non-assoc link vdev
* @vdev: Pointer to non-assoc link vdev
*
* Return: None
*/
static void osif_cm_indicate_disconnect_for_non_assoc_link(
struct net_device *netdev,
struct wlan_objmgr_vdev *vdev)
{
int ret;
ret = cfg80211_clear_current_bss(netdev);
if (ret)
osif_err("cfg80211_clear_current_bss failed for psoc:%d pdev:%d vdev:%d",
wlan_vdev_get_psoc_id(vdev),
wlan_objmgr_pdev_get_pdev_id(wlan_vdev_get_pdev(vdev)),
wlan_vdev_get_id(vdev));
}
#else
static void osif_cm_indicate_disconnect_for_non_assoc_link(
struct net_device *netdev,
struct wlan_objmgr_vdev *vdev)
{
}
#endif
void
osif_cm_indicate_disconnect(struct wlan_objmgr_vdev *vdev,
struct net_device *dev,
@@ -155,7 +207,7 @@ osif_cm_indicate_disconnect(struct wlan_objmgr_vdev *vdev,
{
struct net_device *netdev = dev;
struct vdev_osif_priv *osif_priv = NULL;
struct wlan_objmgr_vdev *assoc_vdev = NULL;
struct wlan_objmgr_vdev *anchor_vdev;
if (!wlan_vdev_mlme_is_mlo_vdev(vdev) || (link_id != -1)) {
osif_cm_indicate_disconnect_result(
@@ -164,7 +216,12 @@ osif_cm_indicate_disconnect(struct wlan_objmgr_vdev *vdev,
return;
}
if (ucfg_mlo_is_mld_disconnected(vdev)) {
anchor_vdev = osif_cm_get_anchor_vdev(vdev);
if (vdev != anchor_vdev)
osif_cm_indicate_disconnect_for_non_assoc_link(netdev, vdev);
if (anchor_vdev && ucfg_mlo_is_mld_disconnected(vdev)) {
/**
* Kernel maintains some extra state on the assoc netdev.
* If the assoc vdev exists, send disconnected event on the
@@ -173,11 +230,8 @@ osif_cm_indicate_disconnect(struct wlan_objmgr_vdev *vdev,
* already cleaned up the extra state while processing the
* disconnected event sent as part of the link removal.
*/
assoc_vdev = ucfg_mlo_get_assoc_link_vdev(vdev);
if (assoc_vdev) {
osif_priv = wlan_vdev_get_ospriv(assoc_vdev);
netdev = osif_priv->wdev->netdev;
}
osif_priv = wlan_vdev_get_ospriv(anchor_vdev);
netdev = osif_priv->wdev->netdev;
osif_cm_indicate_disconnect_result(
netdev, reason,