mac80211: brcmsmac: add ap mode support
This does not work very well. I did not got this running in 5GHz mode and it was not very fast. git-svn-id: svn://svn.openwrt.org/openwrt/trunk@35763 3c298f89-4303-0410-b956-a3cf2f4a3e73master
parent
c88549ad2c
commit
575c4cb452
|
@ -0,0 +1,121 @@
|
|||
--- a/drivers/net/wireless/brcm80211/brcmsmac/d11.h
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmsmac/d11.h
|
||||
@@ -457,6 +457,7 @@ struct d11regs {
|
||||
/*== maccontrol register ==*/
|
||||
#define MCTL_GMODE (1U << 31)
|
||||
#define MCTL_DISCARD_PMQ (1 << 30)
|
||||
+#define MCTL_TBTTHOLD (1 << 28)
|
||||
#define MCTL_WAKE (1 << 26)
|
||||
#define MCTL_HPS (1 << 25)
|
||||
#define MCTL_PROMISC (1 << 24)
|
||||
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
|
||||
@@ -741,6 +741,28 @@ static void brcms_ops_flush(struct ieee8
|
||||
"ret=%d\n", jiffies_to_msecs(ret));
|
||||
}
|
||||
|
||||
+static u64 brcms_ops_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||
+{
|
||||
+ struct brcms_info *wl = hw->priv;
|
||||
+ u64 tsf;
|
||||
+
|
||||
+ spin_lock_bh(&wl->lock);
|
||||
+ tsf = brcms_c_tsf_get(wl->wlc);
|
||||
+ spin_unlock_bh(&wl->lock);
|
||||
+
|
||||
+ return tsf;
|
||||
+}
|
||||
+
|
||||
+static void brcms_ops_set_tsf(struct ieee80211_hw *hw,
|
||||
+ struct ieee80211_vif *vif, u64 tsf)
|
||||
+{
|
||||
+ struct brcms_info *wl = hw->priv;
|
||||
+
|
||||
+ spin_lock_bh(&wl->lock);
|
||||
+ brcms_c_tsf_set(wl->wlc, tsf);
|
||||
+ spin_unlock_bh(&wl->lock);
|
||||
+}
|
||||
+
|
||||
static const struct ieee80211_ops brcms_ops = {
|
||||
.tx = brcms_ops_tx,
|
||||
.start = brcms_ops_start,
|
||||
@@ -757,6 +779,8 @@ static const struct ieee80211_ops brcms_
|
||||
.ampdu_action = brcms_ops_ampdu_action,
|
||||
.rfkill_poll = brcms_ops_rfkill_poll,
|
||||
.flush = brcms_ops_flush,
|
||||
+ .get_tsf = brcms_ops_get_tsf,
|
||||
+ .set_tsf = brcms_ops_set_tsf,
|
||||
};
|
||||
|
||||
void brcms_dpc(unsigned long data)
|
||||
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
|
||||
@@ -5545,6 +5545,20 @@ int brcms_c_set_rateset(struct brcms_c_i
|
||||
return bcmerror;
|
||||
}
|
||||
|
||||
+static void brcms_c_time_lock(struct brcms_c_info *wlc)
|
||||
+{
|
||||
+ bcma_set32(wlc->hw->d11core, D11REGOFFS(maccontrol), MCTL_TBTTHOLD);
|
||||
+ /* Commit the write */
|
||||
+ bcma_read32(wlc->hw->d11core, D11REGOFFS(maccontrol));
|
||||
+}
|
||||
+
|
||||
+static void brcms_c_time_unlock(struct brcms_c_info *wlc)
|
||||
+{
|
||||
+ bcma_mask32(wlc->hw->d11core, D11REGOFFS(maccontrol), ~MCTL_TBTTHOLD);
|
||||
+ /* Commit the write */
|
||||
+ bcma_read32(wlc->hw->d11core, D11REGOFFS(maccontrol));
|
||||
+}
|
||||
+
|
||||
int brcms_c_set_beacon_period(struct brcms_c_info *wlc, u16 period)
|
||||
{
|
||||
if (period == 0)
|
||||
@@ -7530,6 +7544,36 @@ void brcms_c_set_beacon_listen_interval(
|
||||
brcms_c_bcn_li_upd(wlc);
|
||||
}
|
||||
|
||||
+u64 brcms_c_tsf_get(struct brcms_c_info *wlc)
|
||||
+{
|
||||
+ u32 tsf_h, tsf_l;
|
||||
+ u64 tsf;
|
||||
+
|
||||
+ brcms_b_read_tsf(wlc->hw, &tsf_l, &tsf_h);
|
||||
+
|
||||
+ tsf = tsf_h;
|
||||
+ tsf <<= 32;
|
||||
+ tsf |= tsf_l;
|
||||
+
|
||||
+ return tsf;
|
||||
+}
|
||||
+
|
||||
+void brcms_c_tsf_set(struct brcms_c_info *wlc, u64 tsf)
|
||||
+{
|
||||
+ u32 tsf_h, tsf_l;
|
||||
+
|
||||
+ brcms_c_time_lock(wlc);
|
||||
+
|
||||
+ tsf_l = tsf;
|
||||
+ tsf_h = (tsf >> 32);
|
||||
+
|
||||
+ /* read the tsf timer low, then high to get an atomic read */
|
||||
+ bcma_write32(wlc->hw->d11core, D11REGOFFS(tsf_timerlow), tsf_l);
|
||||
+ bcma_write32(wlc->hw->d11core, D11REGOFFS(tsf_timerhigh), tsf_h);
|
||||
+
|
||||
+ brcms_c_time_unlock(wlc);
|
||||
+}
|
||||
+
|
||||
int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr)
|
||||
{
|
||||
uint qdbm;
|
||||
--- a/drivers/net/wireless/brcm80211/brcmsmac/pub.h
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmsmac/pub.h
|
||||
@@ -326,6 +326,8 @@ extern void brcms_c_set_shortslot_overri
|
||||
s8 sslot_override);
|
||||
extern void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc,
|
||||
u8 interval);
|
||||
+extern u64 brcms_c_tsf_get(struct brcms_c_info *wlc);
|
||||
+extern void brcms_c_tsf_set(struct brcms_c_info *wlc, u64 tsf);
|
||||
extern int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr);
|
||||
extern int brcms_c_get_tx_power(struct brcms_c_info *wlc);
|
||||
extern bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc);
|
|
@ -0,0 +1,66 @@
|
|||
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
|
||||
@@ -367,9 +367,10 @@ brcms_ops_add_interface(struct ieee80211
|
||||
}
|
||||
|
||||
spin_lock_bh(&wl->lock);
|
||||
- memcpy(wl->pub->cur_etheraddr, vif->addr, sizeof(vif->addr));
|
||||
wl->mute_tx = false;
|
||||
brcms_c_mute(wl->wlc, false);
|
||||
+ if (vif->type == NL80211_IFTYPE_STATION)
|
||||
+ brcms_c_start_station(wl->wlc, vif->addr);
|
||||
spin_unlock_bh(&wl->lock);
|
||||
|
||||
return 0;
|
||||
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
|
||||
@@ -2165,6 +2165,12 @@ void brcms_b_switch_macfreq(struct brcms
|
||||
}
|
||||
}
|
||||
|
||||
+void brcms_c_start_station(struct brcms_c_info *wlc, u8 *addr)
|
||||
+{
|
||||
+ memcpy(wlc->pub->cur_etheraddr, addr, sizeof(wlc->pub->cur_etheraddr));
|
||||
+ wlc->bsscfg->type = BRCMS_TYPE_STATION;
|
||||
+}
|
||||
+
|
||||
/* Initialize GPIOs that are controlled by D11 core */
|
||||
static void brcms_c_gpio_init(struct brcms_c_info *wlc)
|
||||
{
|
||||
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.h
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.h
|
||||
@@ -576,10 +576,17 @@ struct antsel_info {
|
||||
struct brcms_antselcfg antcfg_cur; /* current antenna config (auto) */
|
||||
};
|
||||
|
||||
+enum brcms_bss_type {
|
||||
+ BRCMS_TYPE_STATION,
|
||||
+ BRCMS_TYPE_AP,
|
||||
+ BRCMS_TYPE_ADHOC,
|
||||
+};
|
||||
+
|
||||
/*
|
||||
* BSS configuration state
|
||||
*
|
||||
* wlc: wlc to which this bsscfg belongs to.
|
||||
+ * type: interface type
|
||||
* up: is this configuration up operational
|
||||
* enable: is this configuration enabled
|
||||
* associated: is BSS in ASSOCIATED state
|
||||
@@ -599,6 +606,7 @@ struct antsel_info {
|
||||
*/
|
||||
struct brcms_bss_cfg {
|
||||
struct brcms_c_info *wlc;
|
||||
+ enum brcms_bss_type type;
|
||||
bool up;
|
||||
bool enable;
|
||||
bool associated;
|
||||
--- a/drivers/net/wireless/brcm80211/brcmsmac/pub.h
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmsmac/pub.h
|
||||
@@ -333,5 +333,6 @@ extern int brcms_c_get_tx_power(struct b
|
||||
extern bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc);
|
||||
extern void brcms_c_mute(struct brcms_c_info *wlc, bool on);
|
||||
extern bool brcms_c_tx_flush_completed(struct brcms_c_info *wlc);
|
||||
+extern void brcms_c_start_station(struct brcms_c_info *wlc, u8 *addr);
|
||||
|
||||
#endif /* _BRCM_PUB_H_ */
|
|
@ -0,0 +1,77 @@
|
|||
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
|
||||
@@ -1071,7 +1071,7 @@ brcms_b_txstatus(struct brcms_hardware *
|
||||
|
||||
static void brcms_c_tbtt(struct brcms_c_info *wlc)
|
||||
{
|
||||
- if (!wlc->bsscfg->BSS)
|
||||
+ if (wlc->bsscfg->type == BRCMS_TYPE_ADHOC)
|
||||
/*
|
||||
* DirFrmQ is now valid...defer setting until end
|
||||
* of ATIM window
|
||||
@@ -3061,16 +3061,8 @@ static bool brcms_c_ps_allowed(struct br
|
||||
if (wlc->filter_flags & FIF_PROMISC_IN_BSS)
|
||||
return false;
|
||||
|
||||
- if (cfg->associated) {
|
||||
- /*
|
||||
- * disallow PS when one of the following
|
||||
- * bsscfg specific conditions meets
|
||||
- */
|
||||
- if (!cfg->BSS)
|
||||
- return false;
|
||||
-
|
||||
+ if (cfg->associated)
|
||||
return false;
|
||||
- }
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -5080,8 +5072,9 @@ int brcms_c_up(struct brcms_c_info *wlc)
|
||||
struct brcms_bss_cfg *bsscfg = wlc->bsscfg;
|
||||
mboolset(wlc->pub->radio_disabled,
|
||||
WL_RADIO_HW_DISABLE);
|
||||
-
|
||||
- if (bsscfg->enable && bsscfg->BSS)
|
||||
+ if (bsscfg->enable &&
|
||||
+ (bsscfg->type == BRCMS_TYPE_STATION ||
|
||||
+ bsscfg->type == BRCMS_TYPE_ADHOC))
|
||||
brcms_err(wlc->hw->d11core,
|
||||
"wl%d: up: rfdisable -> "
|
||||
"bsscfg_disable()\n",
|
||||
@@ -7390,7 +7383,7 @@ void brcms_c_update_beacon(struct brcms_
|
||||
{
|
||||
struct brcms_bss_cfg *bsscfg = wlc->bsscfg;
|
||||
|
||||
- if (bsscfg->up && !bsscfg->BSS)
|
||||
+ if (bsscfg->up && bsscfg->type == BRCMS_TYPE_AP)
|
||||
/* Clear the soft intmask */
|
||||
wlc->defmacintmask &= ~MI_BCNTPL;
|
||||
}
|
||||
@@ -7465,7 +7458,7 @@ void brcms_c_update_probe_resp(struct br
|
||||
struct brcms_bss_cfg *bsscfg = wlc->bsscfg;
|
||||
|
||||
/* update AP or IBSS probe responses */
|
||||
- if (bsscfg->up && !bsscfg->BSS)
|
||||
+ if (bsscfg->up && bsscfg->type == BRCMS_TYPE_AP)
|
||||
brcms_c_bss_update_probe_resp(wlc, bsscfg, suspend);
|
||||
}
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.h
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.h
|
||||
@@ -590,7 +590,6 @@ enum brcms_bss_type {
|
||||
* up: is this configuration up operational
|
||||
* enable: is this configuration enabled
|
||||
* associated: is BSS in ASSOCIATED state
|
||||
- * BSS: infraustructure or adhoc
|
||||
* SSID_len: the length of SSID
|
||||
* SSID: SSID string
|
||||
*
|
||||
@@ -610,7 +609,6 @@ struct brcms_bss_cfg {
|
||||
bool up;
|
||||
bool enable;
|
||||
bool associated;
|
||||
- bool BSS;
|
||||
u8 SSID_len;
|
||||
u8 SSID[IEEE80211_MAX_SSID_LEN];
|
||||
u8 BSSID[ETH_ALEN];
|
|
@ -0,0 +1,74 @@
|
|||
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
|
||||
@@ -3051,8 +3051,6 @@ static void brcms_b_antsel_set(struct br
|
||||
*/
|
||||
static bool brcms_c_ps_allowed(struct brcms_c_info *wlc)
|
||||
{
|
||||
- struct brcms_bss_cfg *cfg = wlc->bsscfg;
|
||||
-
|
||||
/* disallow PS when one of the following global conditions meets */
|
||||
if (!wlc->pub->associated)
|
||||
return false;
|
||||
@@ -3061,9 +3059,6 @@ static bool brcms_c_ps_allowed(struct br
|
||||
if (wlc->filter_flags & FIF_PROMISC_IN_BSS)
|
||||
return false;
|
||||
|
||||
- if (cfg->associated)
|
||||
- return false;
|
||||
-
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -3821,7 +3816,7 @@ static void brcms_c_set_home_chanspec(st
|
||||
if (wlc->home_chanspec != chanspec) {
|
||||
wlc->home_chanspec = chanspec;
|
||||
|
||||
- if (wlc->bsscfg->associated)
|
||||
+ if (wlc->pub->associated)
|
||||
wlc->bsscfg->current_bss->chanspec = chanspec;
|
||||
}
|
||||
}
|
||||
@@ -5435,7 +5430,7 @@ static void brcms_c_ofdm_rateset_war(str
|
||||
u8 r;
|
||||
bool war = false;
|
||||
|
||||
- if (wlc->bsscfg->associated)
|
||||
+ if (wlc->pub->associated)
|
||||
r = wlc->bsscfg->current_bss->rateset.rates[0];
|
||||
else
|
||||
r = wlc->default_bss->rateset.rates[0];
|
||||
@@ -5529,7 +5524,7 @@ int brcms_c_set_rateset(struct brcms_c_i
|
||||
/* merge rateset coming in with the current mcsset */
|
||||
if (wlc->pub->_n_enab & SUPPORT_11N) {
|
||||
struct brcms_bss_info *mcsset_bss;
|
||||
- if (wlc->bsscfg->associated)
|
||||
+ if (wlc->pub->associated)
|
||||
mcsset_bss = wlc->bsscfg->current_bss;
|
||||
else
|
||||
mcsset_bss = wlc->default_bss;
|
||||
@@ -7498,7 +7493,6 @@ void brcms_c_scan_stop(struct brcms_c_in
|
||||
void brcms_c_associate_upd(struct brcms_c_info *wlc, bool state)
|
||||
{
|
||||
wlc->pub->associated = state;
|
||||
- wlc->bsscfg->associated = state;
|
||||
}
|
||||
|
||||
/*
|
||||
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.h
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.h
|
||||
@@ -589,7 +589,6 @@ enum brcms_bss_type {
|
||||
* type: interface type
|
||||
* up: is this configuration up operational
|
||||
* enable: is this configuration enabled
|
||||
- * associated: is BSS in ASSOCIATED state
|
||||
* SSID_len: the length of SSID
|
||||
* SSID: SSID string
|
||||
*
|
||||
@@ -608,7 +607,6 @@ struct brcms_bss_cfg {
|
||||
enum brcms_bss_type type;
|
||||
bool up;
|
||||
bool enable;
|
||||
- bool associated;
|
||||
u8 SSID_len;
|
||||
u8 SSID[IEEE80211_MAX_SSID_LEN];
|
||||
u8 BSSID[ETH_ALEN];
|
|
@ -0,0 +1,32 @@
|
|||
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
|
||||
@@ -5067,9 +5067,8 @@ int brcms_c_up(struct brcms_c_info *wlc)
|
||||
struct brcms_bss_cfg *bsscfg = wlc->bsscfg;
|
||||
mboolset(wlc->pub->radio_disabled,
|
||||
WL_RADIO_HW_DISABLE);
|
||||
- if (bsscfg->enable &&
|
||||
- (bsscfg->type == BRCMS_TYPE_STATION ||
|
||||
- bsscfg->type == BRCMS_TYPE_ADHOC))
|
||||
+ if (bsscfg->type == BRCMS_TYPE_STATION ||
|
||||
+ bsscfg->type == BRCMS_TYPE_ADHOC)
|
||||
brcms_err(wlc->hw->d11core,
|
||||
"wl%d: up: rfdisable -> "
|
||||
"bsscfg_disable()\n",
|
||||
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.h
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.h
|
||||
@@ -588,7 +588,6 @@ enum brcms_bss_type {
|
||||
* wlc: wlc to which this bsscfg belongs to.
|
||||
* type: interface type
|
||||
* up: is this configuration up operational
|
||||
- * enable: is this configuration enabled
|
||||
* SSID_len: the length of SSID
|
||||
* SSID: SSID string
|
||||
*
|
||||
@@ -606,7 +605,6 @@ struct brcms_bss_cfg {
|
||||
struct brcms_c_info *wlc;
|
||||
enum brcms_bss_type type;
|
||||
bool up;
|
||||
- bool enable;
|
||||
u8 SSID_len;
|
||||
u8 SSID[IEEE80211_MAX_SSID_LEN];
|
||||
u8 BSSID[ETH_ALEN];
|
|
@ -0,0 +1,47 @@
|
|||
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
|
||||
@@ -7377,7 +7377,7 @@ void brcms_c_update_beacon(struct brcms_
|
||||
{
|
||||
struct brcms_bss_cfg *bsscfg = wlc->bsscfg;
|
||||
|
||||
- if (bsscfg->up && bsscfg->type == BRCMS_TYPE_AP)
|
||||
+ if (wlc->pub->up && bsscfg->type == BRCMS_TYPE_AP)
|
||||
/* Clear the soft intmask */
|
||||
wlc->defmacintmask &= ~MI_BCNTPL;
|
||||
}
|
||||
@@ -7452,7 +7452,7 @@ void brcms_c_update_probe_resp(struct br
|
||||
struct brcms_bss_cfg *bsscfg = wlc->bsscfg;
|
||||
|
||||
/* update AP or IBSS probe responses */
|
||||
- if (bsscfg->up && bsscfg->type == BRCMS_TYPE_AP)
|
||||
+ if (wlc->pub->up && bsscfg->type == BRCMS_TYPE_AP)
|
||||
brcms_c_bss_update_probe_resp(wlc, bsscfg, suspend);
|
||||
}
|
||||
|
||||
@@ -7805,7 +7805,7 @@ void brcms_c_init(struct brcms_c_info *w
|
||||
brcms_c_set_bssid(wlc->bsscfg);
|
||||
|
||||
/* Update tsf_cfprep if associated and up */
|
||||
- if (wlc->pub->associated && wlc->bsscfg->up) {
|
||||
+ if (wlc->pub->associated && wlc->pub->up) {
|
||||
u32 bi;
|
||||
|
||||
/* get beacon period and convert to uS */
|
||||
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.h
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.h
|
||||
@@ -587,7 +587,6 @@ enum brcms_bss_type {
|
||||
*
|
||||
* wlc: wlc to which this bsscfg belongs to.
|
||||
* type: interface type
|
||||
- * up: is this configuration up operational
|
||||
* SSID_len: the length of SSID
|
||||
* SSID: SSID string
|
||||
*
|
||||
@@ -604,7 +603,6 @@ enum brcms_bss_type {
|
||||
struct brcms_bss_cfg {
|
||||
struct brcms_c_info *wlc;
|
||||
enum brcms_bss_type type;
|
||||
- bool up;
|
||||
u8 SSID_len;
|
||||
u8 SSID[IEEE80211_MAX_SSID_LEN];
|
||||
u8 BSSID[ETH_ALEN];
|
|
@ -0,0 +1,30 @@
|
|||
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
|
||||
@@ -3766,7 +3766,7 @@ static int brcms_c_set_mac(struct brcms_
|
||||
struct brcms_c_info *wlc = bsscfg->wlc;
|
||||
|
||||
/* enter the MAC addr into the RXE match registers */
|
||||
- brcms_c_set_addrmatch(wlc, RCM_MAC_OFFSET, bsscfg->cur_etheraddr);
|
||||
+ brcms_c_set_addrmatch(wlc, RCM_MAC_OFFSET, wlc->pub->cur_etheraddr);
|
||||
|
||||
brcms_c_ampdu_macaddr_upd(wlc);
|
||||
|
||||
@@ -7359,7 +7359,7 @@ brcms_c_bcn_prb_template(struct brcms_c_
|
||||
/* A1 filled in by MAC for prb resp, broadcast for bcn */
|
||||
if (type == IEEE80211_STYPE_BEACON)
|
||||
memcpy(&h->da, ðer_bcast, ETH_ALEN);
|
||||
- memcpy(&h->sa, &cfg->cur_etheraddr, ETH_ALEN);
|
||||
+ memcpy(&h->sa, &wlc->pub->cur_etheraddr, ETH_ALEN);
|
||||
memcpy(&h->bssid, &cfg->BSSID, ETH_ALEN);
|
||||
|
||||
/* SEQ filled in by MAC */
|
||||
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.h
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.h
|
||||
@@ -606,7 +606,6 @@ struct brcms_bss_cfg {
|
||||
u8 SSID_len;
|
||||
u8 SSID[IEEE80211_MAX_SSID_LEN];
|
||||
u8 BSSID[ETH_ALEN];
|
||||
- u8 cur_etheraddr[ETH_ALEN];
|
||||
struct brcms_bss_info *current_bss;
|
||||
};
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
|
||||
@@ -4327,7 +4327,6 @@ static void brcms_c_info_init(struct brc
|
||||
|
||||
/* WME QoS mode is Auto by default */
|
||||
wlc->pub->_ampdu = AMPDU_AGG_HOST;
|
||||
- wlc->pub->bcmerror = 0;
|
||||
}
|
||||
|
||||
static uint brcms_c_attach_module(struct brcms_c_info *wlc)
|
||||
--- a/drivers/net/wireless/brcm80211/brcmsmac/pub.h
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmsmac/pub.h
|
||||
@@ -164,8 +164,6 @@ struct brcms_pub {
|
||||
|
||||
u8 cur_etheraddr[ETH_ALEN]; /* our local ethernet address */
|
||||
|
||||
- int bcmerror; /* last bcm error */
|
||||
-
|
||||
u32 radio_disabled; /* bit vector for radio disabled reasons */
|
||||
|
||||
u16 boardrev; /* version # of particular board */
|
|
@ -0,0 +1,23 @@
|
|||
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
|
||||
@@ -5553,10 +5553,20 @@ static void brcms_c_time_unlock(struct b
|
||||
|
||||
int brcms_c_set_beacon_period(struct brcms_c_info *wlc, u16 period)
|
||||
{
|
||||
+ u32 bcnint_us;
|
||||
+
|
||||
if (period == 0)
|
||||
return -EINVAL;
|
||||
|
||||
wlc->default_bss->beacon_period = period;
|
||||
+
|
||||
+ bcnint_us = period << 10;
|
||||
+ brcms_c_time_lock(wlc);
|
||||
+ bcma_write32(wlc->hw->d11core, D11REGOFFS(tsf_cfprep),
|
||||
+ (bcnint_us << CFPREP_CBI_SHIFT));
|
||||
+ bcma_write32(wlc->hw->d11core, D11REGOFFS(tsf_cfpstart), bcnint_us);
|
||||
+ brcms_c_time_unlock(wlc);
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,266 @@
|
|||
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2010 Broadcom Corporation
|
||||
+ * Copyright (c) 2013 Hauke Mehrtens <hauke@hauke-m.de>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@@ -522,9 +523,17 @@ brcms_ops_bss_info_changed(struct ieee80
|
||||
brcms_c_set_addrmatch(wl->wlc, RCM_BSSID_OFFSET, info->bssid);
|
||||
spin_unlock_bh(&wl->lock);
|
||||
}
|
||||
- if (changed & BSS_CHANGED_BEACON)
|
||||
+ if (changed & BSS_CHANGED_BEACON) {
|
||||
/* Beacon data changed, retrieve new beacon (beaconing modes) */
|
||||
- brcms_err(core, "%s: beacon changed\n", __func__);
|
||||
+ struct sk_buff *beacon;
|
||||
+ u16 tim_offset = 0;
|
||||
+
|
||||
+ spin_lock_bh(&wl->lock);
|
||||
+ beacon = ieee80211_beacon_get_tim(hw, vif, &tim_offset, NULL);
|
||||
+ brcms_c_set_new_beacon(wl->wlc, beacon, tim_offset,
|
||||
+ info->dtim_period);
|
||||
+ spin_unlock_bh(&wl->lock);
|
||||
+ }
|
||||
|
||||
if (changed & BSS_CHANGED_BEACON_ENABLED) {
|
||||
/* Beaconing should be enabled/disabled (beaconing modes) */
|
||||
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2010 Broadcom Corporation
|
||||
+ * Copyright (c) 2013 Hauke Mehrtens <hauke@hauke-m.de>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@@ -450,6 +451,8 @@ static void brcms_c_detach_mfree(struct
|
||||
kfree(wlc->corestate);
|
||||
kfree(wlc->hw->bandstate[0]);
|
||||
kfree(wlc->hw);
|
||||
+ if (wlc->beacon)
|
||||
+ dev_kfree_skb_any(wlc->beacon);
|
||||
|
||||
/* free the wlc */
|
||||
kfree(wlc);
|
||||
@@ -4086,10 +4089,14 @@ void brcms_c_wme_setparams(struct brcms_
|
||||
*shm_entry++);
|
||||
}
|
||||
|
||||
- if (suspend) {
|
||||
+ if (suspend)
|
||||
brcms_c_suspend_mac_and_wait(wlc);
|
||||
+
|
||||
+ brcms_c_update_beacon(wlc);
|
||||
+ brcms_c_update_probe_resp(wlc, false);
|
||||
+
|
||||
+ if (suspend)
|
||||
brcms_c_enable_mac(wlc);
|
||||
- }
|
||||
}
|
||||
|
||||
static void brcms_c_edcf_setparams(struct brcms_c_info *wlc, bool suspend)
|
||||
@@ -7379,6 +7386,107 @@ int brcms_c_get_header_len(void)
|
||||
return TXOFF;
|
||||
}
|
||||
|
||||
+static void brcms_c_beacon_write(struct brcms_c_info *wlc,
|
||||
+ struct sk_buff *beacon, u16 tim_offset,
|
||||
+ u16 dtim_period, bool bcn0, bool bcn1)
|
||||
+{
|
||||
+ size_t len;
|
||||
+ struct ieee80211_tx_info *tx_info;
|
||||
+ struct brcms_hardware *wlc_hw = wlc->hw;
|
||||
+ struct ieee80211_hw *ieee_hw = brcms_c_pub(wlc)->ieee_hw;
|
||||
+
|
||||
+ /* Get tx_info */
|
||||
+ tx_info = IEEE80211_SKB_CB(beacon);
|
||||
+
|
||||
+ len = min_t(size_t, beacon->len, BCN_TMPL_LEN);
|
||||
+ wlc->bcn_rspec = ieee80211_get_tx_rate(ieee_hw, tx_info)->hw_value;
|
||||
+
|
||||
+ brcms_c_compute_plcp(wlc, wlc->bcn_rspec,
|
||||
+ len + FCS_LEN - D11_PHY_HDR_LEN, beacon->data);
|
||||
+
|
||||
+ /* "Regular" and 16 MBSS but not for 4 MBSS */
|
||||
+ /* Update the phytxctl for the beacon based on the rspec */
|
||||
+ brcms_c_beacon_phytxctl_txant_upd(wlc, wlc->bcn_rspec);
|
||||
+
|
||||
+ if (bcn0) {
|
||||
+ /* write the probe response into the template region */
|
||||
+ brcms_b_write_template_ram(wlc_hw, T_BCN0_TPL_BASE,
|
||||
+ (len + 3) & ~3, beacon->data);
|
||||
+
|
||||
+ /* write beacon length to SCR */
|
||||
+ brcms_b_write_shm(wlc_hw, M_BCN0_FRM_BYTESZ, (u16) len);
|
||||
+ }
|
||||
+ if (bcn1) {
|
||||
+ /* write the probe response into the template region */
|
||||
+ brcms_b_write_template_ram(wlc_hw, T_BCN1_TPL_BASE,
|
||||
+ (len + 3) & ~3, beacon->data);
|
||||
+
|
||||
+ /* write beacon length to SCR */
|
||||
+ brcms_b_write_shm(wlc_hw, M_BCN1_FRM_BYTESZ, (u16) len);
|
||||
+ }
|
||||
+
|
||||
+ if (tim_offset != 0) {
|
||||
+ brcms_b_write_shm(wlc_hw, M_TIMBPOS_INBEACON,
|
||||
+ tim_offset + D11B_PHY_HDR_LEN);
|
||||
+ brcms_b_write_shm(wlc_hw, M_DOT11_DTIMPERIOD, dtim_period);
|
||||
+ } else {
|
||||
+ brcms_b_write_shm(wlc_hw, M_TIMBPOS_INBEACON,
|
||||
+ len + D11B_PHY_HDR_LEN);
|
||||
+ brcms_b_write_shm(wlc_hw, M_DOT11_DTIMPERIOD, 0);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void brcms_c_update_beacon_hw(struct brcms_c_info *wlc,
|
||||
+ struct sk_buff *beacon, u16 tim_offset,
|
||||
+ u16 dtim_period)
|
||||
+{
|
||||
+ struct brcms_hardware *wlc_hw = wlc->hw;
|
||||
+ struct bcma_device *core = wlc_hw->d11core;
|
||||
+
|
||||
+ /* Hardware beaconing for this config */
|
||||
+ u32 both_valid = MCMD_BCN0VLD | MCMD_BCN1VLD;
|
||||
+
|
||||
+ /* Check if both templates are in use, if so sched. an interrupt
|
||||
+ * that will call back into this routine
|
||||
+ */
|
||||
+ if ((bcma_read32(core, D11REGOFFS(maccommand)) & both_valid) == both_valid)
|
||||
+ /* clear any previous status */
|
||||
+ bcma_write32(core, D11REGOFFS(macintstatus), MI_BCNTPL);
|
||||
+
|
||||
+ if (wlc->beacon_template_virgin) {
|
||||
+ wlc->beacon_template_virgin = false;
|
||||
+ brcms_c_beacon_write(wlc, beacon, tim_offset, dtim_period, true,
|
||||
+ true);
|
||||
+ /* mark beacon0 valid */
|
||||
+ bcma_set32(core, D11REGOFFS(maccommand), MCMD_BCN0VLD);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ /* Check that after scheduling the interrupt both of the
|
||||
+ * templates are still busy. if not clear the int. & remask
|
||||
+ */
|
||||
+ if ((bcma_read32(core, D11REGOFFS(maccommand)) & both_valid) == both_valid) {
|
||||
+ wlc->defmacintmask |= MI_BCNTPL;
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (!(bcma_read32(core, D11REGOFFS(maccommand)) & MCMD_BCN0VLD)) {
|
||||
+ brcms_c_beacon_write(wlc, beacon, tim_offset, dtim_period, true,
|
||||
+ false);
|
||||
+ /* mark beacon0 valid */
|
||||
+ bcma_set32(core, D11REGOFFS(maccommand), MCMD_BCN0VLD);
|
||||
+ return;
|
||||
+ }
|
||||
+ if (!(bcma_read32(core, D11REGOFFS(maccommand)) & MCMD_BCN1VLD)) {
|
||||
+ brcms_c_beacon_write(wlc, beacon, tim_offset, dtim_period,
|
||||
+ false, true);
|
||||
+ /* mark beacon0 valid */
|
||||
+ bcma_set32(core, D11REGOFFS(maccommand), MCMD_BCN1VLD);
|
||||
+ return;
|
||||
+ }
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Update all beacons for the system.
|
||||
*/
|
||||
@@ -7386,9 +7494,31 @@ void brcms_c_update_beacon(struct brcms_
|
||||
{
|
||||
struct brcms_bss_cfg *bsscfg = wlc->bsscfg;
|
||||
|
||||
- if (wlc->pub->up && bsscfg->type == BRCMS_TYPE_AP)
|
||||
+ if (wlc->pub->up && bsscfg->type == BRCMS_TYPE_AP) {
|
||||
/* Clear the soft intmask */
|
||||
wlc->defmacintmask &= ~MI_BCNTPL;
|
||||
+ if (!wlc->beacon)
|
||||
+ return;
|
||||
+ brcms_c_update_beacon_hw(wlc, wlc->beacon,
|
||||
+ wlc->beacon_tim_offset,
|
||||
+ wlc->beacon_dtim_period);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void brcms_c_set_new_beacon(struct brcms_c_info *wlc, struct sk_buff *beacon,
|
||||
+ u16 tim_offset, u16 dtim_period)
|
||||
+{
|
||||
+ if (!beacon)
|
||||
+ return;
|
||||
+ if (wlc->beacon)
|
||||
+ dev_kfree_skb_any(wlc->beacon);
|
||||
+ wlc->beacon = beacon;
|
||||
+
|
||||
+ /* add PLCP */
|
||||
+ skb_push(wlc->beacon, D11_PHY_HDR_LEN);
|
||||
+ wlc->beacon_tim_offset = tim_offset;
|
||||
+ wlc->beacon_dtim_period = dtim_period;
|
||||
+ brcms_c_update_beacon(wlc);
|
||||
}
|
||||
|
||||
/* Write ssid into shared memory */
|
||||
@@ -7786,6 +7916,10 @@ bool brcms_c_dpc(struct brcms_c_info *wl
|
||||
brcms_rfkill_set_hw_state(wlc->wl);
|
||||
}
|
||||
|
||||
+ /* BCN template is available */
|
||||
+ if (macintstatus & MI_BCNTPL)
|
||||
+ brcms_c_update_beacon(wlc);
|
||||
+
|
||||
/* it isn't done and needs to be resched if macintstatus is non-zero */
|
||||
return wlc->macintstatus != 0;
|
||||
|
||||
@@ -7917,6 +8051,7 @@ brcms_c_attach(struct brcms_info *wl, st
|
||||
pub->unit = unit;
|
||||
pub->_piomode = piomode;
|
||||
wlc->bandinit_pending = false;
|
||||
+ wlc->beacon_template_virgin = true;
|
||||
|
||||
/* populate struct brcms_c_info with default values */
|
||||
brcms_c_info_init(wlc, unit);
|
||||
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.h
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.h
|
||||
@@ -492,6 +492,8 @@ struct brcms_c_info {
|
||||
bool radio_monitor;
|
||||
bool going_down;
|
||||
|
||||
+ bool beacon_template_virgin;
|
||||
+
|
||||
struct brcms_timer *wdtimer;
|
||||
struct brcms_timer *radio_timer;
|
||||
|
||||
@@ -561,6 +563,10 @@ struct brcms_c_info {
|
||||
|
||||
struct wiphy *wiphy;
|
||||
struct scb pri_scb;
|
||||
+
|
||||
+ struct sk_buff *beacon;
|
||||
+ u16 beacon_tim_offset;
|
||||
+ u16 beacon_dtim_period;
|
||||
};
|
||||
|
||||
/* antsel module specific state */
|
||||
@@ -630,7 +636,6 @@ extern u16 brcms_c_compute_rtscts_dur(st
|
||||
extern void brcms_c_inval_dma_pkts(struct brcms_hardware *hw,
|
||||
struct ieee80211_sta *sta,
|
||||
void (*dma_callback_fn));
|
||||
-extern void brcms_c_update_beacon(struct brcms_c_info *wlc);
|
||||
extern void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend);
|
||||
extern int brcms_c_set_nmode(struct brcms_c_info *wlc);
|
||||
extern void brcms_c_beacon_phytxctl_txant_upd(struct brcms_c_info *wlc,
|
||||
--- a/drivers/net/wireless/brcm80211/brcmsmac/pub.h
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmsmac/pub.h
|
||||
@@ -332,5 +332,9 @@ extern bool brcms_c_check_radio_disabled
|
||||
extern void brcms_c_mute(struct brcms_c_info *wlc, bool on);
|
||||
extern bool brcms_c_tx_flush_completed(struct brcms_c_info *wlc);
|
||||
extern void brcms_c_start_station(struct brcms_c_info *wlc, u8 *addr);
|
||||
+extern void brcms_c_update_beacon(struct brcms_c_info *wlc);
|
||||
+extern void brcms_c_set_new_beacon(struct brcms_c_info *wlc,
|
||||
+ struct sk_buff *beacon, u16 tim_offset,
|
||||
+ u16 dtim_period);
|
||||
|
||||
#endif /* _BRCM_PUB_H_ */
|
|
@ -0,0 +1,43 @@
|
|||
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
|
||||
@@ -523,6 +523,12 @@ brcms_ops_bss_info_changed(struct ieee80
|
||||
brcms_c_set_addrmatch(wl->wlc, RCM_BSSID_OFFSET, info->bssid);
|
||||
spin_unlock_bh(&wl->lock);
|
||||
}
|
||||
+ if (changed & BSS_CHANGED_SSID) {
|
||||
+ /* BSSID changed, for whatever reason (IBSS and managed mode) */
|
||||
+ spin_lock_bh(&wl->lock);
|
||||
+ brcms_c_set_ssid(wl->wlc, info->ssid, info->ssid_len);
|
||||
+ spin_unlock_bh(&wl->lock);
|
||||
+ }
|
||||
if (changed & BSS_CHANGED_BEACON) {
|
||||
/* Beacon data changed, retrieve new beacon (beaconing modes) */
|
||||
struct sk_buff *beacon;
|
||||
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
|
||||
@@ -3785,6 +3785,15 @@ static void brcms_c_set_bssid(struct brc
|
||||
brcms_c_set_addrmatch(bsscfg->wlc, RCM_BSSID_OFFSET, bsscfg->BSSID);
|
||||
}
|
||||
|
||||
+void brcms_c_set_ssid(struct brcms_c_info *wlc, u8 *ssid, size_t ssid_len)
|
||||
+{
|
||||
+ u8 len = min_t(u8, sizeof(wlc->bsscfg->SSID), ssid_len);
|
||||
+ memset(wlc->bsscfg->SSID, 0, sizeof(wlc->bsscfg->SSID));
|
||||
+
|
||||
+ memcpy(wlc->bsscfg->SSID, ssid, len);
|
||||
+ wlc->bsscfg->SSID_len = len;
|
||||
+}
|
||||
+
|
||||
static void brcms_b_set_shortslot(struct brcms_hardware *wlc_hw, bool shortslot)
|
||||
{
|
||||
wlc_hw->shortslot = shortslot;
|
||||
--- a/drivers/net/wireless/brcm80211/brcmsmac/pub.h
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmsmac/pub.h
|
||||
@@ -336,5 +336,7 @@ extern void brcms_c_update_beacon(struct
|
||||
extern void brcms_c_set_new_beacon(struct brcms_c_info *wlc,
|
||||
struct sk_buff *beacon, u16 tim_offset,
|
||||
u16 dtim_period);
|
||||
+extern void brcms_c_set_ssid(struct brcms_c_info *wlc, u8 *ssid,
|
||||
+ size_t ssid_len);
|
||||
|
||||
#endif /* _BRCM_PUB_H_ */
|
|
@ -0,0 +1,216 @@
|
|||
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
|
||||
@@ -541,6 +541,15 @@ brcms_ops_bss_info_changed(struct ieee80
|
||||
spin_unlock_bh(&wl->lock);
|
||||
}
|
||||
|
||||
+ if (changed & BSS_CHANGED_AP_PROBE_RESP) {
|
||||
+ struct sk_buff *probe_resp;
|
||||
+
|
||||
+ spin_lock_bh(&wl->lock);
|
||||
+ probe_resp = ieee80211_proberesp_get(hw, vif);
|
||||
+ brcms_c_set_new_probe_resp(wl->wlc, probe_resp);
|
||||
+ spin_unlock_bh(&wl->lock);
|
||||
+ }
|
||||
+
|
||||
if (changed & BSS_CHANGED_BEACON_ENABLED) {
|
||||
/* Beaconing should be enabled/disabled (beaconing modes) */
|
||||
brcms_err(core, "%s: Beacon enabled: %s\n", __func__,
|
||||
@@ -1039,6 +1048,8 @@ static int ieee_hw_init(struct ieee80211
|
||||
hw->channel_change_time = 7 * 1000;
|
||||
hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
|
||||
|
||||
+ hw->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
|
||||
+
|
||||
hw->rate_control_algorithm = "minstrel_ht";
|
||||
|
||||
hw->sta_data_size = 0;
|
||||
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
|
||||
@@ -453,6 +453,8 @@ static void brcms_c_detach_mfree(struct
|
||||
kfree(wlc->hw);
|
||||
if (wlc->beacon)
|
||||
dev_kfree_skb_any(wlc->beacon);
|
||||
+ if (wlc->probe_resp)
|
||||
+ dev_kfree_skb_any(wlc->probe_resp);
|
||||
|
||||
/* free the wlc */
|
||||
kfree(wlc);
|
||||
@@ -7327,69 +7329,6 @@ brcms_c_mod_prb_rsp_rate_table(struct br
|
||||
}
|
||||
}
|
||||
|
||||
-/* Max buffering needed for beacon template/prb resp template is 142 bytes.
|
||||
- *
|
||||
- * PLCP header is 6 bytes.
|
||||
- * 802.11 A3 header is 24 bytes.
|
||||
- * Max beacon frame body template length is 112 bytes.
|
||||
- * Max probe resp frame body template length is 110 bytes.
|
||||
- *
|
||||
- * *len on input contains the max length of the packet available.
|
||||
- *
|
||||
- * The *len value is set to the number of bytes in buf used, and starts
|
||||
- * with the PLCP and included up to, but not including, the 4 byte FCS.
|
||||
- */
|
||||
-static void
|
||||
-brcms_c_bcn_prb_template(struct brcms_c_info *wlc, u16 type,
|
||||
- u32 bcn_rspec,
|
||||
- struct brcms_bss_cfg *cfg, u16 *buf, int *len)
|
||||
-{
|
||||
- static const u8 ether_bcast[ETH_ALEN] = {255, 255, 255, 255, 255, 255};
|
||||
- struct cck_phy_hdr *plcp;
|
||||
- struct ieee80211_mgmt *h;
|
||||
- int hdr_len, body_len;
|
||||
-
|
||||
- hdr_len = D11_PHY_HDR_LEN + DOT11_MAC_HDR_LEN;
|
||||
-
|
||||
- /* calc buffer size provided for frame body */
|
||||
- body_len = *len - hdr_len;
|
||||
- /* return actual size */
|
||||
- *len = hdr_len + body_len;
|
||||
-
|
||||
- /* format PHY and MAC headers */
|
||||
- memset(buf, 0, hdr_len);
|
||||
-
|
||||
- plcp = (struct cck_phy_hdr *) buf;
|
||||
-
|
||||
- /*
|
||||
- * PLCP for Probe Response frames are filled in from
|
||||
- * core's rate table
|
||||
- */
|
||||
- if (type == IEEE80211_STYPE_BEACON)
|
||||
- /* fill in PLCP */
|
||||
- brcms_c_compute_plcp(wlc, bcn_rspec,
|
||||
- (DOT11_MAC_HDR_LEN + body_len + FCS_LEN),
|
||||
- (u8 *) plcp);
|
||||
-
|
||||
- /* "Regular" and 16 MBSS but not for 4 MBSS */
|
||||
- /* Update the phytxctl for the beacon based on the rspec */
|
||||
- brcms_c_beacon_phytxctl_txant_upd(wlc, bcn_rspec);
|
||||
-
|
||||
- h = (struct ieee80211_mgmt *)&plcp[1];
|
||||
-
|
||||
- /* fill in 802.11 header */
|
||||
- h->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | type);
|
||||
-
|
||||
- /* DUR is 0 for multicast bcn, or filled in by MAC for prb resp */
|
||||
- /* A1 filled in by MAC for prb resp, broadcast for bcn */
|
||||
- if (type == IEEE80211_STYPE_BEACON)
|
||||
- memcpy(&h->da, ðer_bcast, ETH_ALEN);
|
||||
- memcpy(&h->sa, &wlc->pub->cur_etheraddr, ETH_ALEN);
|
||||
- memcpy(&h->bssid, &cfg->BSSID, ETH_ALEN);
|
||||
-
|
||||
- /* SEQ filled in by MAC */
|
||||
-}
|
||||
-
|
||||
int brcms_c_get_header_len(void)
|
||||
{
|
||||
return TXOFF;
|
||||
@@ -7530,6 +7469,20 @@ void brcms_c_set_new_beacon(struct brcms
|
||||
brcms_c_update_beacon(wlc);
|
||||
}
|
||||
|
||||
+void brcms_c_set_new_probe_resp(struct brcms_c_info *wlc,
|
||||
+ struct sk_buff *probe_resp)
|
||||
+{
|
||||
+ if (!probe_resp)
|
||||
+ return;
|
||||
+ if (wlc->probe_resp)
|
||||
+ dev_kfree_skb_any(wlc->probe_resp);
|
||||
+ wlc->probe_resp = probe_resp;
|
||||
+
|
||||
+ /* add PLCP */
|
||||
+ skb_push(wlc->probe_resp, D11_PHY_HDR_LEN);
|
||||
+ brcms_c_update_probe_resp(wlc, false);
|
||||
+}
|
||||
+
|
||||
/* Write ssid into shared memory */
|
||||
static void
|
||||
brcms_c_shm_ssid_upd(struct brcms_c_info *wlc, struct brcms_bss_cfg *cfg)
|
||||
@@ -7549,30 +7502,19 @@ brcms_c_shm_ssid_upd(struct brcms_c_info
|
||||
static void
|
||||
brcms_c_bss_update_probe_resp(struct brcms_c_info *wlc,
|
||||
struct brcms_bss_cfg *cfg,
|
||||
+ struct sk_buff *probe_resp,
|
||||
bool suspend)
|
||||
{
|
||||
- u16 *prb_resp;
|
||||
- int len = BCN_TMPL_LEN;
|
||||
+ int len;
|
||||
|
||||
- prb_resp = kmalloc(BCN_TMPL_LEN, GFP_ATOMIC);
|
||||
- if (!prb_resp)
|
||||
- return;
|
||||
-
|
||||
- /*
|
||||
- * write the probe response to hardware, or save in
|
||||
- * the config structure
|
||||
- */
|
||||
-
|
||||
- /* create the probe response template */
|
||||
- brcms_c_bcn_prb_template(wlc, IEEE80211_STYPE_PROBE_RESP, 0,
|
||||
- cfg, prb_resp, &len);
|
||||
+ len = min_t(size_t, probe_resp->len, BCN_TMPL_LEN);
|
||||
|
||||
if (suspend)
|
||||
brcms_c_suspend_mac_and_wait(wlc);
|
||||
|
||||
/* write the probe response into the template region */
|
||||
brcms_b_write_template_ram(wlc->hw, T_PRS_TPL_BASE,
|
||||
- (len + 3) & ~3, prb_resp);
|
||||
+ (len + 3) & ~3, probe_resp->data);
|
||||
|
||||
/* write the length of the probe response frame (+PLCP/-FCS) */
|
||||
brcms_b_write_shm(wlc->hw, M_PRB_RESP_FRM_LEN, (u16) len);
|
||||
@@ -7586,13 +7528,11 @@ brcms_c_bss_update_probe_resp(struct brc
|
||||
* PLCP header for the call to brcms_c_mod_prb_rsp_rate_table()
|
||||
* by subtracting the PLCP len and adding the FCS.
|
||||
*/
|
||||
- len += (-D11_PHY_HDR_LEN + FCS_LEN);
|
||||
- brcms_c_mod_prb_rsp_rate_table(wlc, (u16) len);
|
||||
+ brcms_c_mod_prb_rsp_rate_table(wlc,
|
||||
+ (u16)len + FCS_LEN - D11_PHY_HDR_LEN);
|
||||
|
||||
if (suspend)
|
||||
brcms_c_enable_mac(wlc);
|
||||
-
|
||||
- kfree(prb_resp);
|
||||
}
|
||||
|
||||
void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend)
|
||||
@@ -7600,8 +7540,12 @@ void brcms_c_update_probe_resp(struct br
|
||||
struct brcms_bss_cfg *bsscfg = wlc->bsscfg;
|
||||
|
||||
/* update AP or IBSS probe responses */
|
||||
- if (wlc->pub->up && bsscfg->type == BRCMS_TYPE_AP)
|
||||
- brcms_c_bss_update_probe_resp(wlc, bsscfg, suspend);
|
||||
+ if (wlc->pub->up && bsscfg->type == BRCMS_TYPE_AP) {
|
||||
+ if (!wlc->probe_resp)
|
||||
+ return;
|
||||
+ brcms_c_bss_update_probe_resp(wlc, bsscfg, wlc->probe_resp,
|
||||
+ suspend);
|
||||
+ }
|
||||
}
|
||||
|
||||
int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo,
|
||||
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.h
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.h
|
||||
@@ -567,6 +567,7 @@ struct brcms_c_info {
|
||||
struct sk_buff *beacon;
|
||||
u16 beacon_tim_offset;
|
||||
u16 beacon_dtim_period;
|
||||
+ struct sk_buff *probe_resp;
|
||||
};
|
||||
|
||||
/* antsel module specific state */
|
||||
--- a/drivers/net/wireless/brcm80211/brcmsmac/pub.h
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmsmac/pub.h
|
||||
@@ -336,6 +336,8 @@ extern void brcms_c_update_beacon(struct
|
||||
extern void brcms_c_set_new_beacon(struct brcms_c_info *wlc,
|
||||
struct sk_buff *beacon, u16 tim_offset,
|
||||
u16 dtim_period);
|
||||
+extern void brcms_c_set_new_probe_resp(struct brcms_c_info *wlc,
|
||||
+ struct sk_buff *probe_resp);
|
||||
extern void brcms_c_set_ssid(struct brcms_c_info *wlc, u8 *ssid,
|
||||
size_t ssid_len);
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
|
||||
@@ -360,7 +360,8 @@ brcms_ops_add_interface(struct ieee80211
|
||||
struct brcms_info *wl = hw->priv;
|
||||
|
||||
/* Just STA for now */
|
||||
- if (vif->type != NL80211_IFTYPE_STATION) {
|
||||
+ if (vif->type != NL80211_IFTYPE_STATION &&
|
||||
+ vif->type != NL80211_IFTYPE_AP) {
|
||||
brcms_err(wl->wlc->hw->d11core,
|
||||
"%s: Attempt to add type %d, only STA for now\n",
|
||||
__func__, vif->type);
|
||||
@@ -372,6 +373,9 @@ brcms_ops_add_interface(struct ieee80211
|
||||
brcms_c_mute(wl->wlc, false);
|
||||
if (vif->type == NL80211_IFTYPE_STATION)
|
||||
brcms_c_start_station(wl->wlc, vif->addr);
|
||||
+ else if (vif->type == NL80211_IFTYPE_AP)
|
||||
+ brcms_c_start_ap(wl->wlc, vif->addr, vif->bss_conf.bssid,
|
||||
+ vif->bss_conf.ssid, vif->bss_conf.ssid_len);
|
||||
spin_unlock_bh(&wl->lock);
|
||||
|
||||
return 0;
|
||||
@@ -1046,7 +1050,8 @@ static int ieee_hw_init(struct ieee80211
|
||||
|
||||
/* channel change time is dependent on chip and band */
|
||||
hw->channel_change_time = 7 * 1000;
|
||||
- hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
|
||||
+ hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
|
||||
+ BIT(NL80211_IFTYPE_AP);
|
||||
|
||||
hw->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
|
||||
@@ -2176,6 +2176,18 @@ void brcms_c_start_station(struct brcms_
|
||||
wlc->bsscfg->type = BRCMS_TYPE_STATION;
|
||||
}
|
||||
|
||||
+void brcms_c_start_ap(struct brcms_c_info *wlc, u8 *addr, const u8 *bssid,
|
||||
+ u8 *ssid, size_t ssid_len)
|
||||
+{
|
||||
+ brcms_c_set_ssid(wlc, ssid, ssid_len);
|
||||
+
|
||||
+ memcpy(wlc->pub->cur_etheraddr, addr, sizeof(wlc->pub->cur_etheraddr));
|
||||
+ memcpy(wlc->bsscfg->BSSID, bssid, sizeof(wlc->bsscfg->BSSID));
|
||||
+ wlc->bsscfg->type = BRCMS_TYPE_AP;
|
||||
+
|
||||
+ brcms_b_mctrl(wlc->hw, MCTL_AP | MCTL_INFRA, MCTL_AP | MCTL_INFRA);
|
||||
+}
|
||||
+
|
||||
/* Initialize GPIOs that are controlled by D11 core */
|
||||
static void brcms_c_gpio_init(struct brcms_c_info *wlc)
|
||||
{
|
||||
@@ -3064,6 +3076,9 @@ static bool brcms_c_ps_allowed(struct br
|
||||
if (wlc->filter_flags & FIF_PROMISC_IN_BSS)
|
||||
return false;
|
||||
|
||||
+ if (wlc->bsscfg->type == BRCMS_TYPE_AP)
|
||||
+ return false;
|
||||
+
|
||||
return true;
|
||||
}
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmsmac/pub.h
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmsmac/pub.h
|
||||
@@ -332,6 +332,8 @@ extern bool brcms_c_check_radio_disabled
|
||||
extern void brcms_c_mute(struct brcms_c_info *wlc, bool on);
|
||||
extern bool brcms_c_tx_flush_completed(struct brcms_c_info *wlc);
|
||||
extern void brcms_c_start_station(struct brcms_c_info *wlc, u8 *addr);
|
||||
+extern void brcms_c_start_ap(struct brcms_c_info *wlc, u8 *addr,
|
||||
+ const u8 *bssid, u8 *ssid, size_t ssid_len);
|
||||
extern void brcms_c_update_beacon(struct brcms_c_info *wlc);
|
||||
extern void brcms_c_set_new_beacon(struct brcms_c_info *wlc,
|
||||
struct sk_buff *beacon, u16 tim_offset,
|
|
@ -0,0 +1,31 @@
|
|||
--- a/drivers/net/wireless/brcm80211/brcmsmac/channel.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.c
|
||||
@@ -59,23 +59,16 @@
|
||||
|
||||
#define BRCM_2GHZ_2412_2462 REG_RULE(2412-10, 2462+10, 40, 0, 19, 0)
|
||||
#define BRCM_2GHZ_2467_2472 REG_RULE(2467-10, 2472+10, 20, 0, 19, \
|
||||
- NL80211_RRF_PASSIVE_SCAN | \
|
||||
- NL80211_RRF_NO_IBSS)
|
||||
+ 0)
|
||||
|
||||
#define BRCM_5GHZ_5180_5240 REG_RULE(5180-10, 5240+10, 40, 0, 21, \
|
||||
- NL80211_RRF_PASSIVE_SCAN | \
|
||||
- NL80211_RRF_NO_IBSS)
|
||||
+ 0)
|
||||
#define BRCM_5GHZ_5260_5320 REG_RULE(5260-10, 5320+10, 40, 0, 21, \
|
||||
- NL80211_RRF_PASSIVE_SCAN | \
|
||||
- NL80211_RRF_DFS | \
|
||||
- NL80211_RRF_NO_IBSS)
|
||||
+ 0)
|
||||
#define BRCM_5GHZ_5500_5700 REG_RULE(5500-10, 5700+10, 40, 0, 21, \
|
||||
- NL80211_RRF_PASSIVE_SCAN | \
|
||||
- NL80211_RRF_DFS | \
|
||||
- NL80211_RRF_NO_IBSS)
|
||||
+ 0)
|
||||
#define BRCM_5GHZ_5745_5825 REG_RULE(5745-10, 5825+10, 40, 0, 21, \
|
||||
- NL80211_RRF_PASSIVE_SCAN | \
|
||||
- NL80211_RRF_NO_IBSS)
|
||||
+ 0)
|
||||
|
||||
static const struct ieee80211_regdomain brcms_regdom_x2 = {
|
||||
.n_reg_rules = 6,
|
Loading…
Reference in New Issue