Commit a44aa400 authored by Hante Meuleman's avatar Hante Meuleman Committed by John W. Linville

brcmfmac: add multiple BSS support.

This patch adds support for multiple BSS interfaces (AP). In
total three AP configurations can be created. In order to use
multiple BSS firmware needs to support it.
Reviewed-by: default avatarArend Van Spriel <arend@broadcom.com>
Reviewed-by: default avatarPieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: default avatarHante Meuleman <meuleman@broadcom.com>
Signed-off-by: default avatarArend van Spriel <arend@broadcom.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent c4034f43
......@@ -183,6 +183,7 @@ struct vif_saved_ie {
* @pm_block: power-management blocked.
* @list: linked list.
* @mgmt_rx_reg: registered rx mgmt frame types.
* @mbss: Multiple BSS type, set if not first AP (not relevant for P2P).
*/
struct brcmf_cfg80211_vif {
struct brcmf_if *ifp;
......@@ -194,6 +195,7 @@ struct brcmf_cfg80211_vif {
struct vif_saved_ie saved_ie;
struct list_head list;
u16 mgmt_rx_reg;
bool mbss;
};
/* association inform */
......
......@@ -836,7 +836,7 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx,
return ifp;
}
void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx)
static void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx)
{
struct brcmf_if *ifp;
......@@ -869,6 +869,38 @@ void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx)
}
}
void brcmf_remove_interface(struct brcmf_pub *drvr, u32 bssidx)
{
if (drvr->iflist[bssidx]) {
brcmf_fws_del_interface(drvr->iflist[bssidx]);
brcmf_del_if(drvr, bssidx);
}
}
int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr)
{
int ifidx;
int bsscfgidx;
bool available;
int highest;
available = false;
bsscfgidx = 2;
highest = 2;
for (ifidx = 0; ifidx < BRCMF_MAX_IFS; ifidx++) {
if (drvr->iflist[ifidx]) {
if (drvr->iflist[ifidx]->bssidx == bsscfgidx)
bsscfgidx = highest + 1;
else if (drvr->iflist[ifidx]->bssidx > highest)
highest = drvr->iflist[ifidx]->bssidx;
} else {
available = true;
}
}
return available ? bsscfgidx : -ENOMEM;
}
int brcmf_attach(struct device *dev)
{
struct brcmf_pub *drvr = NULL;
......@@ -1033,10 +1065,7 @@ void brcmf_detach(struct device *dev)
/* make sure primary interface removed last */
for (i = BRCMF_MAX_IFS-1; i > -1; i--)
if (drvr->iflist[i]) {
brcmf_fws_del_interface(drvr->iflist[i]);
brcmf_del_if(drvr, i);
}
brcmf_remove_interface(drvr, i);
brcmf_cfg80211_detach(drvr->config);
......
......@@ -175,7 +175,8 @@ char *brcmf_ifname(struct brcmf_pub *drvr, int idx);
int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked);
struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx,
char *name, u8 *mac_addr);
void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx);
void brcmf_remove_interface(struct brcmf_pub *drvr, u32 bssidx);
int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr);
void brcmf_txflowblock_if(struct brcmf_if *ifp,
enum brcmf_netif_stop_reason reason, bool state);
void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, u8 ifidx,
......
......@@ -97,6 +97,28 @@ static void brcmf_feat_iovar_int_get(struct brcmf_if *ifp,
}
}
/**
* brcmf_feat_iovar_int_set() - determine feature through iovar set.
*
* @ifp: interface to query.
* @id: feature id.
* @name: iovar name.
*/
static void brcmf_feat_iovar_int_set(struct brcmf_if *ifp,
enum brcmf_feat_id id, char *name, u32 val)
{
int err;
err = brcmf_fil_iovar_int_set(ifp, name, val);
if (err == 0) {
brcmf_dbg(INFO, "enabling feature: %s\n", brcmf_feat_names[id]);
ifp->drvr->feat_flags |= BIT(id);
} else {
brcmf_dbg(TRACE, "%s feature check failed: %d\n",
brcmf_feat_names[id], err);
}
}
void brcmf_feat_attach(struct brcmf_pub *drvr)
{
struct brcmf_if *ifp = drvr->iflist[0];
......@@ -104,6 +126,7 @@ void brcmf_feat_attach(struct brcmf_pub *drvr)
brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_MCHAN, "mchan");
if (drvr->bus_if->wowl_supported)
brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_WOWL, "wowl");
brcmf_feat_iovar_int_set(ifp, BRCMF_FEAT_MBSS, "mbss", 0);
/* set chip related quirks */
switch (drvr->bus_if->chip) {
......
......@@ -22,6 +22,7 @@
* MCHAN: multi-channel for concurrent P2P.
*/
#define BRCMF_FEAT_LIST \
BRCMF_FEAT_DEF(MBSS) \
BRCMF_FEAT_DEF(MCHAN) \
BRCMF_FEAT_DEF(WOWL)
/*
......
......@@ -221,10 +221,8 @@ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr,
err = brcmf_fweh_call_event_handler(ifp, emsg->event_code, emsg, data);
if (ifp && ifevent->action == BRCMF_E_IF_DEL) {
brcmf_fws_del_interface(ifp);
brcmf_del_if(drvr, ifevent->bssidx);
}
if (ifp && ifevent->action == BRCMF_E_IF_DEL)
brcmf_remove_interface(drvr, ifevent->bssidx);
}
/**
......
......@@ -519,4 +519,10 @@ struct brcmf_fil_wowl_pattern_le {
/* u8 pattern[] - Pattern follows the mask is at 'patternoffset' */
};
struct brcmf_mbss_ssid_le {
__le32 bsscfgidx;
__le32 SSID_len;
unsigned char SSID[32];
};
#endif /* FWIL_TYPES_H_ */
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