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:

committed by
Rahul Choudhary

부모
ab8c55ec38
커밋
8713c007bd
@@ -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,
|
||||
|
Reference in New Issue
Block a user