summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/broadcom
diff options
context:
space:
mode:
authorWright Feng <wright.feng@cypress.com>2022-09-29 00:06:12 -0500
committerKalle Valo <kvalo@kernel.org>2022-10-05 10:41:45 +0300
commit4388827b87d849e51053e098c4e12c707b9fef34 (patch)
treeb1aef9a9c444c97a5c3fcad087ff2efbbbe5ecf1 /drivers/net/wireless/broadcom
parent2b5fb30f8ff55c7d0e8cd6a06c9be1de6129f5a7 (diff)
brcmfmac: support station interface creation version 1, 2 and 3
To create virtual station interface for RSDB and VSDB, we add interface creation version 1, 2 and 3 supports The structures of each version are different and only version 3 and later version are able to get interface creating version from firmware side. The patch has been verified two concurrent stations pings test with interface create version 1: 89342(4359b1)-PCIE: 9.40.100 interface create version 2: 4373a0-sdio: 13.10.271 interface create version 3: 4373a0-sdio: 13.35.48 Signed-off-by: Wright Feng <wright.feng@cypress.com> Signed-off-by: Chi-hsien Lin <chi-hsien.lin@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-3-ian.lin@infineon.com
Diffstat (limited to 'drivers/net/wireless/broadcom')
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c148
1 files changed, 124 insertions, 24 deletions
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
index 6817e745434a..e5f0a9ef2d0f 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -264,17 +264,46 @@ struct parsed_vndr_ies {
struct parsed_vndr_ie_info ie_info[VNDR_IE_PARSE_LIMIT];
};
+#define WL_INTERFACE_CREATE_VER_1 1
+#define WL_INTERFACE_CREATE_VER_2 2
+#define WL_INTERFACE_CREATE_VER_3 3
+#define WL_INTERFACE_CREATE_VER_MAX WL_INTERFACE_CREATE_VER_3
+
#define WL_INTERFACE_MAC_DONT_USE 0x0
#define WL_INTERFACE_MAC_USE 0x2
#define WL_INTERFACE_CREATE_STA 0x0
#define WL_INTERFACE_CREATE_AP 0x1
-struct wl_interface_create {
- u16 ver;
- u32 flags;
- u8 mac_addr[ETH_ALEN];
- u8 pad[13];
+struct wl_interface_create_v1 {
+ u16 ver; /* structure version */
+ u32 flags; /* flags for operation */
+ u8 mac_addr[ETH_ALEN]; /* MAC address */
+ u32 wlc_index; /* optional for wlc index */
+};
+
+struct wl_interface_create_v2 {
+ u16 ver; /* structure version */
+ u8 pad1[2];
+ u32 flags; /* flags for operation */
+ u8 mac_addr[ETH_ALEN]; /* MAC address */
+ u8 iftype; /* type of interface created */
+ u8 pad2;
+ u32 wlc_index; /* optional for wlc index */
+};
+
+struct wl_interface_create_v3 {
+ u16 ver; /* structure version */
+ u16 len; /* length of structure + data */
+ u16 fixed_len; /* length of structure */
+ u8 iftype; /* type of interface created */
+ u8 wlc_index; /* optional for wlc index */
+ u32 flags; /* flags for operation */
+ u8 mac_addr[ETH_ALEN]; /* MAC address */
+ u8 bssid[ETH_ALEN]; /* optional for BSSID */
+ u8 if_index; /* interface index request */
+ u8 pad[3];
+ u8 data[]; /* Optional for specific data */
};
static u8 nl80211_band_to_fwil(enum nl80211_band band)
@@ -564,16 +593,14 @@ static int brcmf_get_first_free_bsscfgidx(struct brcmf_pub *drvr)
return -ENOMEM;
}
-static void brcmf_set_sta_iface_macaddr(struct brcmf_if *ifp,
- struct wl_interface_create *iface)
+static void brcmf_set_vif_sta_macaddr(struct brcmf_if *ifp, u8 *mac_addr)
{
u8 mac_idx = ifp->drvr->sta_mac_idx;
/* set difference MAC address with locally administered bit */
- iface->flags |= WL_INTERFACE_MAC_USE;
- memcpy(iface->mac_addr, ifp->mac_addr, ETH_ALEN);
- iface->mac_addr[0] |= 0x02;
- iface->mac_addr[3] ^= mac_idx ? 0xC0 : 0xA0;
+ memcpy(mac_addr, ifp->mac_addr, ETH_ALEN);
+ mac_addr[0] |= 0x02;
+ mac_addr[3] ^= mac_idx ? 0xC0 : 0xA0;
mac_idx++;
mac_idx = mac_idx % 2;
ifp->drvr->sta_mac_idx = mac_idx;
@@ -581,23 +608,96 @@ static void brcmf_set_sta_iface_macaddr(struct brcmf_if *ifp,
static int brcmf_cfg80211_request_sta_if(struct brcmf_if *ifp, u8 *macaddr)
{
- struct wl_interface_create iface;
+ 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;
int err;
- memset(&iface, 0, sizeof(iface));
+ /* 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_STA |
+ WL_INTERFACE_MAC_USE;
+ if (!is_zero_ether_addr(macaddr))
+ memcpy(iface_v1.mac_addr, macaddr, ETH_ALEN);
+ else
+ brcmf_set_vif_sta_macaddr(ifp, iface_v1.mac_addr);
- iface.ver = 0;
- iface.flags = WL_INTERFACE_CREATE_STA;
- if (!is_zero_ether_addr(macaddr)) {
- /* set MAC address in cfg80211 params */
- memcpy(iface.mac_addr, macaddr, ETH_ALEN);
+ 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_set_sta_iface_macaddr(ifp, &iface);
+ brcmf_dbg(INFO, "interface created(v1)\n");
+ return 0;
}
- err = brcmf_fil_iovar_data_get(ifp, "interface_create", &iface,
- sizeof(iface));
- return err;
+ /* 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_STA;
+ if (!is_zero_ether_addr(macaddr))
+ memcpy(iface_v2.mac_addr, macaddr, ETH_ALEN);
+ else
+ 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_STA;
+ if (!is_zero_ether_addr(macaddr))
+ memcpy(iface_v3.mac_addr, macaddr, ETH_ALEN);
+ else
+ 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("station interface creation failed (%d)\n",
+ err);
+ return -EIO;
+ }
+
+ return 0;
}
static int brcmf_cfg80211_request_ap_if(struct brcmf_if *ifp)
@@ -7060,7 +7160,7 @@ brcmf_txrx_stypes[NUM_NL80211_IFTYPES] = {
*
* p2p, mchan, and mbss:
*
- * #STA <= 1, #P2P-DEV <= 1, #{P2P-CL, P2P-GO} <= 1, channels = 2, 3 total
+ * #STA <= 2, #P2P-DEV <= 1, #{P2P-CL, P2P-GO} <= 1, channels = 2, 3 total
* #STA <= 1, #P2P-DEV <= 1, #AP <= 1, #P2P-CL <= 1, channels = 1, 4 total
* #AP <= 4, matching BI, channels = 1, 4 total
*
@@ -7106,7 +7206,7 @@ static int brcmf_setup_ifmodes(struct wiphy *wiphy, struct brcmf_if *ifp)
goto err;
combo[c].num_different_channels = 1 + (rsdb || (p2p && mchan));
- c0_limits[i].max = 1;
+ c0_limits[i].max = 1 + (p2p && mchan);
c0_limits[i++].types = BIT(NL80211_IFTYPE_STATION);
if (mon_flag) {
c0_limits[i].max = 1;