2022-09-29 05:20:10

by Ian Lin

[permalink] [raw]
Subject: [PATCH 0/4] brcmfmac: Support multiple station interface series

Support create multiple station interface.
And fix related issues.

Prasanna Kerekoppa (1):
brcmfmac: Fix AP interface delete issue

Ting-Ying Li (1):
brcmfmac: revise SoftAP channel setting

Wright Feng (2):
brcmfmac: add creating station interface support
brcmfmac: support station interface creation version 1, 2 and 3

.../broadcom/brcm80211/brcmfmac/cfg80211.c | 306 ++++++++++++++++--
.../broadcom/brcm80211/brcmfmac/core.h | 1 +
2 files changed, 272 insertions(+), 35 deletions(-)

--
2.25.0


2022-09-29 05:21:19

by Ian Lin

[permalink] [raw]
Subject: [PATCH 1/4] brcmfmac: add creating station interface support

From: Wright Feng <[email protected]>

With RSDB device, it is able to control two station interfaces
concurrently. So we add creating station interface support and
allow user to create it via cfg80211.

Signed-off-by: Wright Feng <[email protected]>
Signed-off-by: Chi-hsien Lin <[email protected]>
Signed-off-by: Ian Lin <[email protected]>
---
.../broadcom/brcm80211/brcmfmac/cfg80211.c | 81 ++++++++++++++++---
.../broadcom/brcm80211/brcmfmac/core.h | 1 +
2 files changed, 70 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
index dfcfb3333369..e352bc6e015c 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -234,6 +234,19 @@ struct parsed_vndr_ies {
struct parsed_vndr_ie_info ie_info[VNDR_IE_PARSE_LIMIT];
};

+#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];
+};
+
static u8 nl80211_band_to_fwil(enum nl80211_band band)
{
switch (band) {
@@ -521,6 +534,42 @@ 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)
+{
+ 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;
+ mac_idx++;
+ mac_idx = mac_idx % 2;
+ ifp->drvr->sta_mac_idx = mac_idx;
+}
+
+static int brcmf_cfg80211_request_sta_if(struct brcmf_if *ifp, u8 *macaddr)
+{
+ struct wl_interface_create iface;
+ int err;
+
+ memset(&iface, 0, sizeof(iface));
+
+ 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);
+ } else {
+ brcmf_set_sta_iface_macaddr(ifp, &iface);
+ }
+
+ err = brcmf_fil_iovar_data_get(ifp, "interface_create", &iface,
+ sizeof(iface));
+ return err;
+}
+
static int brcmf_cfg80211_request_ap_if(struct brcmf_if *ifp)
{
struct brcmf_pub *drvr = ifp->drvr;
@@ -546,15 +595,17 @@ static int brcmf_cfg80211_request_ap_if(struct brcmf_if *ifp)
}

/**
- * brcmf_ap_add_vif() - create a new AP virtual interface for multiple BSS
+ * brcmf_apsta_add_vif() - create a new AP or STA virtual interface
*
* @wiphy: wiphy device of new interface.
* @name: name of the new interface.
- * @params: contains mac address for AP device.
+ * @params: contains mac address for AP or STA device.
+ * @type: interface type.
*/
static
-struct wireless_dev *brcmf_ap_add_vif(struct wiphy *wiphy, const char *name,
- struct vif_params *params)
+struct wireless_dev *brcmf_apsta_add_vif(struct wiphy *wiphy, const char *name,
+ struct vif_params *params,
+ enum nl80211_iftype type)
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
@@ -562,18 +613,24 @@ struct wireless_dev *brcmf_ap_add_vif(struct wiphy *wiphy, const char *name,
struct brcmf_cfg80211_vif *vif;
int err;

+ if (type != NL80211_IFTYPE_STATION && type != NL80211_IFTYPE_AP)
+ return ERR_PTR(-EINVAL);
+
if (brcmf_cfg80211_vif_event_armed(cfg))
return ERR_PTR(-EBUSY);

brcmf_dbg(INFO, "Adding vif \"%s\"\n", name);

- vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_AP);
+ vif = brcmf_alloc_vif(cfg, type);
if (IS_ERR(vif))
return (struct wireless_dev *)vif;

brcmf_cfg80211_arm_vif_event(cfg, vif);

- err = brcmf_cfg80211_request_ap_if(ifp);
+ if (type == NL80211_IFTYPE_STATION)
+ err = brcmf_cfg80211_request_sta_if(ifp, params->macaddr);
+ else
+ err = brcmf_cfg80211_request_ap_if(ifp);
if (err) {
brcmf_cfg80211_arm_vif_event(cfg, NULL);
goto fail;
@@ -720,15 +777,15 @@ static struct wireless_dev *brcmf_cfg80211_add_iface(struct wiphy *wiphy,
}
switch (type) {
case NL80211_IFTYPE_ADHOC:
- case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_AP_VLAN:
case NL80211_IFTYPE_WDS:
case NL80211_IFTYPE_MESH_POINT:
return ERR_PTR(-EOPNOTSUPP);
case NL80211_IFTYPE_MONITOR:
return brcmf_mon_add_vif(wiphy, name);
+ case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_AP:
- wdev = brcmf_ap_add_vif(wiphy, name, params);
+ wdev = brcmf_apsta_add_vif(wiphy, name, params, type);
break;
case NL80211_IFTYPE_P2P_CLIENT:
case NL80211_IFTYPE_P2P_GO:
@@ -848,8 +905,8 @@ s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
return err;
}

-static int brcmf_cfg80211_del_ap_iface(struct wiphy *wiphy,
- struct wireless_dev *wdev)
+static int brcmf_cfg80211_del_apsta_iface(struct wiphy *wiphy,
+ struct wireless_dev *wdev)
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct net_device *ndev = wdev->netdev;
@@ -906,15 +963,15 @@ int brcmf_cfg80211_del_iface(struct wiphy *wiphy, struct wireless_dev *wdev)

switch (wdev->iftype) {
case NL80211_IFTYPE_ADHOC:
- case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_AP_VLAN:
case NL80211_IFTYPE_WDS:
case NL80211_IFTYPE_MESH_POINT:
return -EOPNOTSUPP;
case NL80211_IFTYPE_MONITOR:
return brcmf_mon_del_vif(wiphy, wdev);
+ case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_AP:
- return brcmf_cfg80211_del_ap_iface(wiphy, wdev);
+ return brcmf_cfg80211_del_apsta_iface(wiphy, wdev);
case NL80211_IFTYPE_P2P_CLIENT:
case NL80211_IFTYPE_P2P_GO:
case NL80211_IFTYPE_P2P_DEVICE:
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
index 340346c122d3..2e71b5c2a975 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
@@ -136,6 +136,7 @@ struct brcmf_pub {
struct work_struct bus_reset;

u8 clmver[BRCMF_DCMD_SMLEN];
+ u8 sta_mac_idx;
};

/* forward declarations */
--
2.25.0

2022-09-29 05:22:14

by Ian Lin

[permalink] [raw]
Subject: [PATCH 2/4] brcmfmac: support station interface creation version 1, 2 and 3

From: Wright Feng <[email protected]>

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 <[email protected]>
Signed-off-by: Chi-hsien Lin <[email protected]>
Signed-off-by: Ian Lin <[email protected]>
---
.../broadcom/brcm80211/brcmfmac/cfg80211.c | 148 +++++++++++++++---
1 file 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 e352bc6e015c..2082e255f031 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -234,17 +234,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)
@@ -534,16 +563,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;
@@ -551,23 +578,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)
@@ -7030,7 +7130,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
*
@@ -7076,7 +7176,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;
--
2.25.0

2022-10-05 07:59:38

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH 1/4] brcmfmac: add creating station interface support

Kalle Valo <[email protected]> writes:

> Kalle Valo <[email protected]> writes:
>
>> Ian Lin <[email protected]> wrote:
>>
>>> From: Wright Feng <[email protected]>
>>>
>>> With RSDB device, it is able to control two station interfaces
>>> concurrently. So we add creating station interface support and
>>> allow user to create it via cfg80211.
>>>
>>> Signed-off-by: Wright Feng <[email protected]>
>>> Signed-off-by: Chi-hsien Lin <[email protected]>
>>> Signed-off-by: Ian Lin <[email protected]>
>>
>> 3 patches applied to wireless-next.git, thanks.
>>
>> 2b5fb30f8ff5 brcmfmac: add creating station interface support
>> 4388827b87d8 brcmfmac: support station interface creation version 1, 2 and 3
>> 1562bdef9251 brcmfmac: Fix AP interface delete issue
>
> I didn't notice that "wifi:" prefix was missing, please always add that
> in future patches. More info in the wiki below.

And please stop CCing [email protected], the bounce
messages are really annoying.

<[email protected]>: host smtp2.infineon.com[217.10.52.18] said:
550 #5.1.0 Address rejected. (in reply to RCPT TO command)

--
https://patchwork.kernel.org/project/linux-wireless/list/

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches

2022-10-05 08:00:10

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH 1/4] brcmfmac: add creating station interface support

Ian Lin <[email protected]> wrote:

> From: Wright Feng <[email protected]>
>
> With RSDB device, it is able to control two station interfaces
> concurrently. So we add creating station interface support and
> allow user to create it via cfg80211.
>
> Signed-off-by: Wright Feng <[email protected]>
> Signed-off-by: Chi-hsien Lin <[email protected]>
> Signed-off-by: Ian Lin <[email protected]>

3 patches applied to wireless-next.git, thanks.

2b5fb30f8ff5 brcmfmac: add creating station interface support
4388827b87d8 brcmfmac: support station interface creation version 1, 2 and 3
1562bdef9251 brcmfmac: Fix AP interface delete issue

--
https://patchwork.kernel.org/project/linux-wireless/patch/[email protected]/

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches

2022-10-05 08:03:34

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH 1/4] brcmfmac: add creating station interface support

Kalle Valo <[email protected]> writes:

> Ian Lin <[email protected]> wrote:
>
>> From: Wright Feng <[email protected]>
>>
>> With RSDB device, it is able to control two station interfaces
>> concurrently. So we add creating station interface support and
>> allow user to create it via cfg80211.
>>
>> Signed-off-by: Wright Feng <[email protected]>
>> Signed-off-by: Chi-hsien Lin <[email protected]>
>> Signed-off-by: Ian Lin <[email protected]>
>
> 3 patches applied to wireless-next.git, thanks.
>
> 2b5fb30f8ff5 brcmfmac: add creating station interface support
> 4388827b87d8 brcmfmac: support station interface creation version 1, 2 and 3
> 1562bdef9251 brcmfmac: Fix AP interface delete issue

I didn't notice that "wifi:" prefix was missing, please always add that
in future patches. More info in the wiki below.

--
https://patchwork.kernel.org/project/linux-wireless/list/

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches

2022-10-10 10:18:13

by Arend Van Spriel

[permalink] [raw]
Subject: Re: [PATCH 0/4] brcmfmac: Support multiple station interface series

On 9/29/2022 7:06 AM, Ian Lin wrote:
> Support create multiple station interface.
> And fix related issues.

These patches surely break things for older chips. Also the firmware API
definitions should not be place in cfg80211.c but in fwil_types.h.

Regards,
Arend

> Prasanna Kerekoppa (1):
> brcmfmac: Fix AP interface delete issue
>
> Ting-Ying Li (1):
> brcmfmac: revise SoftAP channel setting
>
> Wright Feng (2):
> brcmfmac: add creating station interface support
> brcmfmac: support station interface creation version 1, 2 and 3
>
> .../broadcom/brcm80211/brcmfmac/cfg80211.c | 306 ++++++++++++++++--
> .../broadcom/brcm80211/brcmfmac/core.h | 1 +
> 2 files changed, 272 insertions(+), 35 deletions(-)
>