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
This commit is contained in:
parent
2b5fb30f8f
commit
4388827b87
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user