Commit 4388827b authored by Wright Feng's avatar Wright Feng Committed by Kalle Valo

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: default avatarWright Feng <wright.feng@cypress.com>
Signed-off-by: default avatarChi-hsien Lin <chi-hsien.lin@infineon.com>
Signed-off-by: default avatarIan Lin <ian.lin@infineon.com>
Signed-off-by: default avatarKalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/20220929050614.31518-3-ian.lin@infineon.com
parent 2b5fb30f
......@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment