brcmfmac: Fix AP interface delete issue
authorPrasanna Kerekoppa <prasanna.kerekoppa@infineon.com>
Thu, 29 Sep 2022 05:06:13 +0000 (00:06 -0500)
committerKalle Valo <kvalo@kernel.org>
Wed, 5 Oct 2022 07:41:45 +0000 (10:41 +0300)
Fixes the ap interface delete issue. Fix is to make sure interface
is created with supported version.
Patch has been verified by creating and deleting AP interface.

Signed-off-by: Prasanna Kerekoppa <prasanna.kerekoppa@infineon.com>
Signed-off-by: Ian Lin <ian.lin@infineon.com>
Signed-off-by: Kalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/20220929050614.31518-4-ian.lin@infineon.com
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c

index e5f0a9e..bf184c0 100644 (file)
@@ -702,24 +702,103 @@ static int brcmf_cfg80211_request_sta_if(struct brcmf_if *ifp, u8 *macaddr)
 
 static int brcmf_cfg80211_request_ap_if(struct brcmf_if *ifp)
 {
+       struct wl_interface_create_v1 iface_v1;
+       struct wl_interface_create_v2 iface_v2;
+       struct wl_interface_create_v3 iface_v3;
+       u32 iface_create_ver;
        struct brcmf_pub *drvr = ifp->drvr;
        struct brcmf_mbss_ssid_le mbss_ssid_le;
        int bsscfgidx;
        int err;
 
-       memset(&mbss_ssid_le, 0, sizeof(mbss_ssid_le));
-       bsscfgidx = brcmf_get_first_free_bsscfgidx(ifp->drvr);
-       if (bsscfgidx < 0)
-               return bsscfgidx;
+       /* interface_create version 1 */
+       memset(&iface_v1, 0, sizeof(iface_v1));
+       iface_v1.ver = WL_INTERFACE_CREATE_VER_1;
+       iface_v1.flags = WL_INTERFACE_CREATE_AP |
+                        WL_INTERFACE_MAC_USE;
 
-       mbss_ssid_le.bsscfgidx = cpu_to_le32(bsscfgidx);
-       mbss_ssid_le.SSID_len = cpu_to_le32(5);
-       sprintf(mbss_ssid_le.SSID, "ssid%d" , bsscfgidx);
+       brcmf_set_vif_sta_macaddr(ifp, iface_v1.mac_addr);
 
-       err = brcmf_fil_bsscfg_data_set(ifp, "bsscfg:ssid", &mbss_ssid_le,
-                                       sizeof(mbss_ssid_le));
-       if (err < 0)
-               bphy_err(drvr, "setting ssid failed %d\n", err);
+       err = brcmf_fil_iovar_data_get(ifp, "interface_create",
+                                      &iface_v1,
+                                      sizeof(iface_v1));
+       if (err) {
+               brcmf_info("failed to create interface(v1), err=%d\n",
+                          err);
+       } else {
+               brcmf_dbg(INFO, "interface created(v1)\n");
+               return 0;
+       }
+
+       /* interface_create version 2 */
+       memset(&iface_v2, 0, sizeof(iface_v2));
+       iface_v2.ver = WL_INTERFACE_CREATE_VER_2;
+       iface_v2.flags = WL_INTERFACE_MAC_USE;
+       iface_v2.iftype = WL_INTERFACE_CREATE_AP;
+
+       brcmf_set_vif_sta_macaddr(ifp, iface_v2.mac_addr);
+
+       err = brcmf_fil_iovar_data_get(ifp, "interface_create",
+                                      &iface_v2,
+                                      sizeof(iface_v2));
+       if (err) {
+               brcmf_info("failed to create interface(v2), err=%d\n",
+                          err);
+       } else {
+               brcmf_dbg(INFO, "interface created(v2)\n");
+               return 0;
+       }
+
+       /* interface_create version 3+ */
+       /* get supported version from firmware side */
+       iface_create_ver = 0;
+       err = brcmf_fil_bsscfg_int_get(ifp, "interface_create",
+                                      &iface_create_ver);
+       if (err) {
+               brcmf_err("fail to get supported version, err=%d\n", err);
+               return -EOPNOTSUPP;
+       }
+
+       switch (iface_create_ver) {
+       case WL_INTERFACE_CREATE_VER_3:
+               memset(&iface_v3, 0, sizeof(iface_v3));
+               iface_v3.ver = WL_INTERFACE_CREATE_VER_3;
+               iface_v3.flags = WL_INTERFACE_MAC_USE;
+               iface_v3.iftype = WL_INTERFACE_CREATE_AP;
+               brcmf_set_vif_sta_macaddr(ifp, iface_v3.mac_addr);
+
+               err = brcmf_fil_iovar_data_get(ifp, "interface_create",
+                                              &iface_v3,
+                                              sizeof(iface_v3));
+
+               if (!err)
+                       brcmf_dbg(INFO, "interface created(v3)\n");
+               break;
+       default:
+               brcmf_err("not support interface create(v%d)\n",
+                         iface_create_ver);
+               err = -EOPNOTSUPP;
+               break;
+       }
+
+       if (err) {
+               brcmf_info("Does not support interface_create (%d)\n",
+                          err);
+               memset(&mbss_ssid_le, 0, sizeof(mbss_ssid_le));
+               bsscfgidx = brcmf_get_first_free_bsscfgidx(ifp->drvr);
+               if (bsscfgidx < 0)
+                       return bsscfgidx;
+
+               mbss_ssid_le.bsscfgidx = cpu_to_le32(bsscfgidx);
+               mbss_ssid_le.SSID_len = cpu_to_le32(5);
+               sprintf(mbss_ssid_le.SSID, "ssid%d", bsscfgidx);
+
+               err = brcmf_fil_bsscfg_data_set(ifp, "bsscfg:ssid", &mbss_ssid_le,
+                                               sizeof(mbss_ssid_le));
+
+               if (err < 0)
+                       bphy_err(drvr, "setting ssid failed %d\n", err);
+       }
 
        return err;
 }