2013-03-24 00:47:46

by Hauke Mehrtens

[permalink] [raw]
Subject: [PATCH 00/15] brcmsmac: add AP mode

This patch series contains some cleanup patches for brcmsmac and then
adds beacon and probe response template upload.
With these features AP and Ad hoc mode support is added in the last patch.
Probe response sending by ucode is deactivated for now.

Currently AP and Ad hoc mode do not work in the 5GHz band. I do not
know what is wrong there, I have tested this with the firmware from
linux-firmware and with one extracted from a proprietary Broadcom
driver.

Power saving stations could cause some problems as Johannes said, to
make this properly work some more functions have to be implemented, but
I would like to do this later.

When running AP mode in 5GHz band on my BCM43224 I get the following
errors, and I do not see the network with my Intel IWL6300, the
regulation restrictions in channel.c where changed before:

[ 829.608000] brcmsmac bcma1:0: wl0: wlc_suspend_mac_and_wait: waited 83000 uS and MI_MACSSPNDD is still not on.
[ 829.616000] brcmsmac bcma1:0: wl0: psmdebug 0x00ff808d, phydebug 0x0000000d, psm_brc 0x0000
[ 829.624000] brcmsmac bcma1:0: brcms_ops_bss_info_changed: qos enabled: true (implement)
[ 829.864000] brcmsmac bcma1:0: wl0: wlc_suspend_mac_and_wait: waited 83000 uS and MI_MACSSPNDD is still not on.
[ 829.876000] brcmsmac bcma1:0: wl0: psmdebug 0x00ff80d8, phydebug 0x0000000d, psm_brc 0x0000
[ 829.884000] brcmsmac bcma1:0: brcms_ops_bss_info_changed: qos enabled: true (implement)
[ 830.108000] brcmsmac bcma1:0: wl0: wlc_suspend_mac_and_wait: waited 83000 uS and MI_MACSSPNDD is still not on.
[ 830.120000] brcmsmac bcma1:0: wl0: psmdebug 0x00ff8ae6, phydebug 0x0000000d, psm_brc 0x0000
[ 830.128000] brcmsmac bcma1:0: brcms_ops_bss_info_changed: qos enabled: true (implement)
[ 830.240000] brcmsmac bcma1:0: wl0: wlc_suspend_mac_and_wait: waited 83000 uS and MI_MACSSPNDD is still not on.
[ 830.252000] brcmsmac bcma1:0: wl0: psmdebug 0x00ff800d, phydebug 0x0000000d, psm_brc 0x0000
[ 830.292000] brcmsmac bcma1:0: brcms_ops_bss_info_changed: qos enabled: true (implement)


In the 2.4GHz band I get the following phy errors, but the station
still stays connected:

[ 152.196000] brcmsmac bcma0:0: phyerr 0x1, rate 0x37
[ 152.200000] brcmsmac bcma0:0: brcms_c_ampdu_dotxstatus_complete: ampdu tx phy error (0x1)
[ 152.208000] brcmsmac bcma0:0: phyerr 0x1, rate 0x37
[ 152.216000] brcmsmac bcma0:0: brcms_c_ampdu_dotxstatus_complete: ampdu tx phy error (0x1)
[ 152.228000] brcmsmac bcma0:0: phyerr 0x1, rate 0x37
[ 152.232000] brcmsmac bcma0:0: brcms_c_ampdu_dotxstatus_complete: ampdu tx phy error (0x1)
[ 346.644000] brcmsmac bcma0:0: phyerr 0x10, rate 0x6e
[ 346.652000] brcmsmac bcma0:0: brcms_c_ampdu_dotxstatus_complete: ampdu tx phy error (0x10)
[ 349.504000] brcmsmac bcma0:0: phyerr 0x8, rate 0x14
[ 349.508000] brcmsmac bcma0:0: brcms_c_ampdu_dotxstatus_complete: ampdu tx phy error (0x8)
[ 493.524000] brcmsmac bcma0:0: phyerr 0x8, rate 0x37
[ 493.528000] brcmsmac bcma0:0: brcms_c_ampdu_dotxstatus_complete: ampdu tx phy error (0x8)

This was successfully tested on a BCM4716 in 2.4GHz mode, my BCM43224
does not work in 2.4GHz mode, because the sprom is only configured for
5GHz.
I got some positive responses for other people testing this on their
Access Points with OpenWrt and no problem report.

The structure of brcmsmac is pretty complicated, because it copies many
addresses into its own structs and does not use mac80211 structs in
main.c.

This is based on the current version of wireless-testing/master.

Changes since RFC:
* add ad hoc mode support
* deactivate ucode probe response sending by ucode

Hauke Mehrtens (15):
brcmsmac: implement ieee80211_ops get_tsf and set_tsf
brcmsmac: add interface type to brcms_bss_cfg
brcmsmac: remove brcms_bss_cfg->BSS
brcmsmac: remove brcms_bss_cfg->associated
brcmsmac: remove brcms_bss_cfg->enable
brcmsmac: remove brcms_bss_cfg->up
brcmsmac: remove brcms_bss_cfg->cur_etheraddr
brcmsmac: remove brcms_pub->bcmerr
brcmsmac: write beacon period to hardware
brcmsmac: add beacon template support
brcmsmac: react on changing SSID
brcmsmac: add support for probe response template
brcmsmac: deactivate ucode sending probe responses
brcmsmac: activate AP support
brcmsmac: add support for adhoc mode

drivers/net/wireless/brcm80211/brcmsmac/d11.h | 1 +
.../net/wireless/brcm80211/brcmsmac/mac80211_if.c | 85 ++++-
drivers/net/wireless/brcm80211/brcmsmac/main.c | 362 +++++++++++++++-----
drivers/net/wireless/brcm80211/brcmsmac/main.h | 25 +-
drivers/net/wireless/brcm80211/brcmsmac/pub.h | 17 +-
5 files changed, 376 insertions(+), 114 deletions(-)

--
1.7.10.4



2013-03-24 00:48:36

by Hauke Mehrtens

[permalink] [raw]
Subject: [PATCH 13/15] brcmsmac: deactivate ucode sending probe responses

It is possible to configure the ucode to automatically send the probe
responses to the clients after they send a probe request. At least for
WPS the userspace needs to answer the probe requests and we do not know
a way to say to the ucode to just handle the normal probe requests, so
for now no probe requests should be handled by the ucode.

Signed-off-by: Hauke Mehrtens <[email protected]>
---
drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c | 13 ++++++++++++-
drivers/net/wireless/brcm80211/brcmsmac/main.c | 11 +++++++++++
drivers/net/wireless/brcm80211/brcmsmac/pub.h | 1 +
3 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
index d4a51f0..4b3d46a 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
@@ -552,6 +552,12 @@ brcms_ops_bss_info_changed(struct ieee80211_hw *hw,
/* Beaconing should be enabled/disabled (beaconing modes) */
brcms_err(core, "%s: Beacon enabled: %s\n", __func__,
info->enable_beacon ? "true" : "false");
+ if (info->enable_beacon &&
+ hw->wiphy->flags & WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD) {
+ brcms_c_enable_probe_resp(wl->wlc, true);
+ } else {
+ brcms_c_enable_probe_resp(wl->wlc, false);
+ }
}

if (changed & BSS_CHANGED_CQM) {
@@ -1047,7 +1053,12 @@ static int ieee_hw_init(struct ieee80211_hw *hw)
hw->channel_change_time = 7 * 1000;
hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);

- hw->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
+ /*
+ * deactivate sending probe responses by ucude, because this will
+ * cause problems when WPS is used.
+ *
+ * hw->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
+ */

hw->rate_control_algorithm = "minstrel_ht";

diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index 04192ed..63fb9fd 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
@@ -7480,6 +7480,17 @@ void brcms_c_set_new_probe_resp(struct brcms_c_info *wlc,
brcms_c_update_probe_resp(wlc, false);
}

+void brcms_c_enable_probe_resp(struct brcms_c_info *wlc, bool enable)
+{
+ /*
+ * prevent ucode from sending probe responses by setting the timeout
+ * to 1, it can not send it in that time frame.
+ */
+ wlc->prb_resp_timeout = enable ? BRCMS_PRB_RESP_TIMEOUT : 1;
+ brcms_b_write_shm(wlc->hw, M_PRS_MAXTIME, wlc->prb_resp_timeout);
+ /* TODO: if (enable) => also deactivate receiving of probe request */
+}
+
/* Write ssid into shared memory */
static void
brcms_c_shm_ssid_upd(struct brcms_c_info *wlc, struct brcms_bss_cfg *cfg)
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/pub.h b/drivers/net/wireless/brcm80211/brcmsmac/pub.h
index 5e6db62..6fa746e 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/pub.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/pub.h
@@ -338,6 +338,7 @@ extern void brcms_c_set_new_beacon(struct brcms_c_info *wlc,
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_enable_probe_resp(struct brcms_c_info *wlc, bool enable);
extern void brcms_c_set_ssid(struct brcms_c_info *wlc, u8 *ssid,
size_t ssid_len);

--
1.7.10.4


2013-03-24 00:47:51

by Hauke Mehrtens

[permalink] [raw]
Subject: [PATCH 03/15] brcmsmac: remove brcms_bss_cfg->BSS

This was a read only member. The checks using BSS are replaced by
better fitting checks of the new type member.

The change in brcms_c_tbtt() was based on code from b43, in
brcms_c_ps_allowed() the same happens with BSS being true or false,
beaconing and probe responses are just needed in ap mode.

Signed-off-by: Hauke Mehrtens <[email protected]>
---
drivers/net/wireless/brcm80211/brcmsmac/main.c | 23 +++++++++--------------
drivers/net/wireless/brcm80211/brcmsmac/main.h | 2 --
2 files changed, 9 insertions(+), 16 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index 4e420ea..90e6c0d 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
@@ -1069,7 +1069,7 @@ brcms_b_txstatus(struct brcms_hardware *wlc_hw, bool bound, bool *fatal)

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
@@ -3059,16 +3059,8 @@ static bool brcms_c_ps_allowed(struct brcms_c_info *wlc)
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;
}
@@ -5078,8 +5070,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",
@@ -7386,7 +7379,8 @@ void brcms_c_update_beacon(struct brcms_c_info *wlc)
{
struct brcms_bss_cfg *bsscfg = wlc->bsscfg;

- if (bsscfg->up && !bsscfg->BSS)
+ if (bsscfg->up && (bsscfg->type == BRCMS_TYPE_AP ||
+ bsscfg->type == BRCMS_TYPE_ADHOC))
/* Clear the soft intmask */
wlc->defmacintmask &= ~MI_BCNTPL;
}
@@ -7461,7 +7455,8 @@ void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend)
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 ||
+ bsscfg->type == BRCMS_TYPE_ADHOC))
brcms_c_bss_update_probe_resp(wlc, bsscfg, suspend);
}

diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.h b/drivers/net/wireless/brcm80211/brcmsmac/main.h
index dbf027c..0cfe782 100644
--- 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];
--
1.7.10.4


2013-03-24 00:48:38

by Hauke Mehrtens

[permalink] [raw]
Subject: [PATCH 14/15] brcmsmac: activate AP support

This activates the AP mode support.

Signed-off-by: Hauke Mehrtens <[email protected]>
---
drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c | 13 +++++++++----
drivers/net/wireless/brcm80211/brcmsmac/main.c | 15 +++++++++++++++
drivers/net/wireless/brcm80211/brcmsmac/pub.h | 2 ++
3 files changed, 26 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
index 4b3d46a..445de66 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
@@ -357,10 +357,11 @@ brcms_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
struct brcms_info *wl = hw->priv;

- /* Just STA for now */
- if (vif->type != NL80211_IFTYPE_STATION) {
+ /* Just STA and AP for now */
+ 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",
+ "%s: Attempt to add type %d, only STA and AP for now\n",
__func__, vif->type);
return -EOPNOTSUPP;
}
@@ -370,6 +371,9 @@ brcms_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
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;
@@ -1051,7 +1055,8 @@ static int ieee_hw_init(struct ieee80211_hw *hw)

/* 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);

/*
* deactivate sending probe responses by ucude, because this will
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index 63fb9fd..7825202 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
@@ -2174,6 +2174,18 @@ void brcms_c_start_station(struct brcms_c_info *wlc, u8 *addr)
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)
{
@@ -3062,6 +3074,9 @@ static bool brcms_c_ps_allowed(struct brcms_c_info *wlc)
if (wlc->filter_flags & FIF_PROMISC_IN_BSS)
return false;

+ if (wlc->bsscfg->type == BRCMS_TYPE_AP)
+ return false;
+
return true;
}

diff --git a/drivers/net/wireless/brcm80211/brcmsmac/pub.h b/drivers/net/wireless/brcm80211/brcmsmac/pub.h
index 6fa746e..e3bdccf 100644
--- 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(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);
+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,
--
1.7.10.4


2013-03-24 00:48:20

by Hauke Mehrtens

[permalink] [raw]
Subject: [PATCH 09/15] brcmsmac: write beacon period to hardware

Make brcms_c_set_beacon_period() write the beacon period to the
hardware if a new one is set.

Signed-off-by: Hauke Mehrtens <[email protected]>
---
drivers/net/wireless/brcm80211/brcmsmac/main.c | 10 ++++++++++
1 file changed, 10 insertions(+)

diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index 7e19295..4ffb0c6 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
@@ -5551,10 +5551,20 @@ static void brcms_c_time_unlock(struct brcms_c_info *wlc)

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;
}

--
1.7.10.4


2013-03-24 00:47:52

by Hauke Mehrtens

[permalink] [raw]
Subject: [PATCH 02/15] brcmsmac: add interface type to brcms_bss_cfg

This makes it possible to easily check in which mode the device is
currently running. This also adds a function to start station mode.

Signed-off-by: Hauke Mehrtens <[email protected]>
---
drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c | 3 ++-
drivers/net/wireless/brcm80211/brcmsmac/main.c | 6 ++++++
drivers/net/wireless/brcm80211/brcmsmac/main.h | 8 ++++++++
drivers/net/wireless/brcm80211/brcmsmac/pub.h | 1 +
4 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
index 7dac719..5bfaefb 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
@@ -365,9 +365,10 @@ brcms_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
}

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;
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index 60276af..4e420ea 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
@@ -2163,6 +2163,12 @@ void brcms_b_switch_macfreq(struct brcms_hardware *wlc_hw, u8 spurmode)
}
}

+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)
{
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.h b/drivers/net/wireless/brcm80211/brcmsmac/main.h
index fb44774..dbf027c 100644
--- 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;
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/pub.h b/drivers/net/wireless/brcm80211/brcmsmac/pub.h
index 382fb09..aa8580f 100644
--- 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 brcms_c_info *wlc);
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_ */
--
1.7.10.4


2013-03-24 00:48:19

by Hauke Mehrtens

[permalink] [raw]
Subject: [PATCH 08/15] brcmsmac: remove brcms_pub->bcmerr

This was a write only member

Signed-off-by: Hauke Mehrtens <[email protected]>
---
drivers/net/wireless/brcm80211/brcmsmac/main.c | 1 -
drivers/net/wireless/brcm80211/brcmsmac/pub.h | 2 --
2 files changed, 3 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index 056ca2c..7e19295 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
@@ -4325,7 +4325,6 @@ static void brcms_c_info_init(struct brcms_c_info *wlc, int unit)

/* 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)
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/pub.h b/drivers/net/wireless/brcm80211/brcmsmac/pub.h
index aa8580f..9dae59c 100644
--- 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 */
--
1.7.10.4


2013-03-24 00:48:33

by Hauke Mehrtens

[permalink] [raw]
Subject: [PATCH 12/15] brcmsmac: add support for probe response template

The ucode is able to answer probe response by itself. This writes such
a template into the specific memory. Currently the probe requests are
also send to mac80211 so there are more answers send to a requesting
client. We have to make the ucode stop sending probe requests to the
driver.

Signed-off-by: Hauke Mehrtens <[email protected]>
---
.../net/wireless/brcm80211/brcmsmac/mac80211_if.c | 11 ++
drivers/net/wireless/brcm80211/brcmsmac/main.c | 112 +++++---------------
drivers/net/wireless/brcm80211/brcmsmac/main.h | 1 +
drivers/net/wireless/brcm80211/brcmsmac/pub.h | 2 +
4 files changed, 42 insertions(+), 84 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
index 1d0d0f6..d4a51f0 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
@@ -539,6 +539,15 @@ brcms_ops_bss_info_changed(struct ieee80211_hw *hw,
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__,
@@ -1038,6 +1047,8 @@ static int ieee_hw_init(struct ieee80211_hw *hw)
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;
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index cf11d894..04192ed 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
@@ -451,6 +451,8 @@ static void brcms_c_detach_mfree(struct brcms_c_info *wlc)
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);
@@ -7323,69 +7325,6 @@ brcms_c_mod_prb_rsp_rate_table(struct brcms_c_info *wlc, uint frame_len)
}
}

-/* 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, &ether_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;
@@ -7527,6 +7466,20 @@ void brcms_c_set_new_beacon(struct brcms_c_info *wlc, struct sk_buff *beacon,
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)
@@ -7546,30 +7499,19 @@ brcms_c_shm_ssid_upd(struct brcms_c_info *wlc, struct brcms_bss_cfg *cfg)
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);
@@ -7583,13 +7525,11 @@ brcms_c_bss_update_probe_resp(struct brcms_c_info *wlc,
* 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)
@@ -7598,8 +7538,12 @@ void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend)

/* update AP or IBSS probe responses */
if (wlc->pub->up && (bsscfg->type == BRCMS_TYPE_AP ||
- bsscfg->type == BRCMS_TYPE_ADHOC))
- brcms_c_bss_update_probe_resp(wlc, bsscfg, suspend);
+ bsscfg->type == BRCMS_TYPE_ADHOC)) {
+ 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,
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.h b/drivers/net/wireless/brcm80211/brcmsmac/main.h
index 82382da..b5d7a38 100644
--- 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 */
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/pub.h b/drivers/net/wireless/brcm80211/brcmsmac/pub.h
index 6ed0a20..5e6db62 100644
--- 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 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);
+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);

--
1.7.10.4


2013-03-24 00:47:57

by Hauke Mehrtens

[permalink] [raw]
Subject: [PATCH 04/15] brcmsmac: remove brcms_bss_cfg->associated

Replaced the usage with pub->associated.

Signed-off-by: Hauke Mehrtens <[email protected]>
---
drivers/net/wireless/brcm80211/brcmsmac/main.c | 12 +++---------
drivers/net/wireless/brcm80211/brcmsmac/main.h | 2 --
2 files changed, 3 insertions(+), 11 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index 90e6c0d..810b7e2 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
@@ -3049,8 +3049,6 @@ static void brcms_b_antsel_set(struct brcms_hardware *wlc_hw, u32 antsel_avail)
*/
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;
@@ -3059,9 +3057,6 @@ static bool brcms_c_ps_allowed(struct brcms_c_info *wlc)
if (wlc->filter_flags & FIF_PROMISC_IN_BSS)
return false;

- if (cfg->associated)
- return false;
-
return true;
}

@@ -3819,7 +3814,7 @@ static void brcms_c_set_home_chanspec(struct brcms_c_info *wlc, u16 chanspec)
if (wlc->home_chanspec != chanspec) {
wlc->home_chanspec = chanspec;

- if (wlc->bsscfg->associated)
+ if (wlc->pub->associated)
wlc->bsscfg->current_bss->chanspec = chanspec;
}
}
@@ -5433,7 +5428,7 @@ static void brcms_c_ofdm_rateset_war(struct brcms_c_info *wlc)
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];
@@ -5527,7 +5522,7 @@ int brcms_c_set_rateset(struct brcms_c_info *wlc, struct brcm_rateset *rs)
/* 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;
@@ -7496,7 +7491,6 @@ void brcms_c_scan_stop(struct brcms_c_info *wlc)
void brcms_c_associate_upd(struct brcms_c_info *wlc, bool state)
{
wlc->pub->associated = state;
- wlc->bsscfg->associated = state;
}

/*
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.h b/drivers/net/wireless/brcm80211/brcmsmac/main.h
index 0cfe782..96dc2f4 100644
--- 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];
--
1.7.10.4


2013-03-24 00:47:46

by Hauke Mehrtens

[permalink] [raw]
Subject: [PATCH 01/15] brcmsmac: implement ieee80211_ops get_tsf and set_tsf

setting the tsf is needed to start a timer to make beaconing in AP mode
work.

This is based on older versions of brcmsmac and b43.

Signed-off-by: Hauke Mehrtens <[email protected]>
---
drivers/net/wireless/brcm80211/brcmsmac/d11.h | 1 +
.../net/wireless/brcm80211/brcmsmac/mac80211_if.c | 24 +++++++++++
drivers/net/wireless/brcm80211/brcmsmac/main.c | 44 ++++++++++++++++++++
drivers/net/wireless/brcm80211/brcmsmac/pub.h | 2 +
4 files changed, 71 insertions(+)

diff --git a/drivers/net/wireless/brcm80211/brcmsmac/d11.h b/drivers/net/wireless/brcm80211/brcmsmac/d11.h
index 3f659e0..9035cc4 100644
--- 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)
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
index c70cf7b..7dac719 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
@@ -739,6 +739,28 @@ static void brcms_ops_flush(struct ieee80211_hw *hw, bool drop)
"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,
@@ -755,6 +777,8 @@ static const struct ieee80211_ops brcms_ops = {
.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)
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index 0c8e998..60276af 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
@@ -5543,6 +5543,20 @@ int brcms_c_set_rateset(struct brcms_c_info *wlc, struct brcm_rateset *rs)
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)
@@ -7526,6 +7540,36 @@ void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc, u8 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;
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/pub.h b/drivers/net/wireless/brcm80211/brcmsmac/pub.h
index b0f14b7..382fb09 100644
--- 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_override(struct brcms_c_info *wlc,
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);
--
1.7.10.4


2013-03-24 00:48:04

by Hauke Mehrtens

[permalink] [raw]
Subject: [PATCH 05/15] brcmsmac: remove brcms_bss_cfg->enable

This was a read only member.

Signed-off-by: Hauke Mehrtens <[email protected]>
---
drivers/net/wireless/brcm80211/brcmsmac/main.c | 5 ++---
drivers/net/wireless/brcm80211/brcmsmac/main.h | 2 --
2 files changed, 2 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index 810b7e2..ca1c585 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
@@ -5065,9 +5065,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",
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.h b/drivers/net/wireless/brcm80211/brcmsmac/main.h
index 96dc2f4..e2551a7 100644
--- 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];
--
1.7.10.4


2013-03-24 00:48:11

by Hauke Mehrtens

[permalink] [raw]
Subject: [PATCH 06/15] brcmsmac: remove brcms_bss_cfg->up

This was a read only member, replace it with pub->up.

Signed-off-by: Hauke Mehrtens <[email protected]>
---
drivers/net/wireless/brcm80211/brcmsmac/main.c | 10 +++++-----
drivers/net/wireless/brcm80211/brcmsmac/main.h | 2 --
2 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index ca1c585..9af5851 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
@@ -7373,8 +7373,8 @@ void brcms_c_update_beacon(struct brcms_c_info *wlc)
{
struct brcms_bss_cfg *bsscfg = wlc->bsscfg;

- if (bsscfg->up && (bsscfg->type == BRCMS_TYPE_AP ||
- bsscfg->type == BRCMS_TYPE_ADHOC))
+ if (wlc->pub->up && (bsscfg->type == BRCMS_TYPE_AP ||
+ bsscfg->type == BRCMS_TYPE_ADHOC))
/* Clear the soft intmask */
wlc->defmacintmask &= ~MI_BCNTPL;
}
@@ -7449,8 +7449,8 @@ void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend)
struct brcms_bss_cfg *bsscfg = wlc->bsscfg;

/* update AP or IBSS probe responses */
- if (bsscfg->up && (bsscfg->type == BRCMS_TYPE_AP ||
- bsscfg->type == BRCMS_TYPE_ADHOC))
+ if (wlc->pub->up && (bsscfg->type == BRCMS_TYPE_AP ||
+ bsscfg->type == BRCMS_TYPE_ADHOC))
brcms_c_bss_update_probe_resp(wlc, bsscfg, suspend);
}

@@ -7803,7 +7803,7 @@ void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx)
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 */
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.h b/drivers/net/wireless/brcm80211/brcmsmac/main.h
index e2551a7..65818e2 100644
--- 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];
--
1.7.10.4


2013-03-24 00:48:32

by Hauke Mehrtens

[permalink] [raw]
Subject: [PATCH 10/15] brcmsmac: add beacon template support

This makes it possible that a beacon template provided by mac80211 is
written to the hardware for constant beaconing.

This is based on an old version of brcmsmac, on b43 and the spec b43 is
based on.

Signed-off-by: Hauke Mehrtens <[email protected]>
---
.../net/wireless/brcm80211/brcmsmac/mac80211_if.c | 13 +-
drivers/net/wireless/brcm80211/brcmsmac/main.c | 141 +++++++++++++++++++-
drivers/net/wireless/brcm80211/brcmsmac/main.h | 7 +-
drivers/net/wireless/brcm80211/brcmsmac/pub.h | 4 +
4 files changed, 159 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
index 5bfaefb..591e262 100644
--- 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 <[email protected]>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -520,9 +521,17 @@ brcms_ops_bss_info_changed(struct ieee80211_hw *hw,
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) */
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index 4ffb0c6..60dc2c4 100644
--- 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 <[email protected]>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -448,6 +449,8 @@ static void brcms_c_detach_mfree(struct brcms_c_info *wlc)
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);
@@ -4084,10 +4087,14 @@ void brcms_c_wme_setparams(struct brcms_c_info *wlc, u16 aci,
*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)
@@ -7375,6 +7382,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.
*/
@@ -7383,9 +7491,31 @@ void brcms_c_update_beacon(struct brcms_c_info *wlc)
struct brcms_bss_cfg *bsscfg = wlc->bsscfg;

if (wlc->pub->up && (bsscfg->type == BRCMS_TYPE_AP ||
- bsscfg->type == BRCMS_TYPE_ADHOC))
+ bsscfg->type == BRCMS_TYPE_ADHOC)) {
/* 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 */
@@ -7784,6 +7914,10 @@ bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded)
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;

@@ -7920,6 +8054,7 @@ brcms_c_attach(struct brcms_info *wl, struct bcma_device *core, uint unit,
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);
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.h b/drivers/net/wireless/brcm80211/brcmsmac/main.h
index 397cff3..82382da 100644
--- 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(struct brcms_c_info *wlc, bool cts_only,
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,
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/pub.h b/drivers/net/wireless/brcm80211/brcmsmac/pub.h
index 9dae59c..8a3071f 100644
--- 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(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);
+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_ */
--
1.7.10.4


2013-03-24 00:48:41

by Hauke Mehrtens

[permalink] [raw]
Subject: [PATCH 15/15] brcmsmac: add support for adhoc mode

This adds adhoc mode support to brcmsmac.

Signed-off-by: Hauke Mehrtens <[email protected]>
---
drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c | 12 ++++++++----
drivers/net/wireless/brcm80211/brcmsmac/main.c | 11 +++++++++++
drivers/net/wireless/brcm80211/brcmsmac/pub.h | 1 +
3 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
index 445de66..0b3f8d9 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
@@ -357,11 +357,12 @@ brcms_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
struct brcms_info *wl = hw->priv;

- /* Just STA and AP for now */
+ /* Just STA, AP and ADHOC for now */
if (vif->type != NL80211_IFTYPE_STATION &&
- vif->type != NL80211_IFTYPE_AP) {
+ vif->type != NL80211_IFTYPE_AP &&
+ vif->type != NL80211_IFTYPE_ADHOC) {
brcms_err(wl->wlc->hw->d11core,
- "%s: Attempt to add type %d, only STA and AP for now\n",
+ "%s: Attempt to add type %d, only STA, AP and AdHoc for now\n",
__func__, vif->type);
return -EOPNOTSUPP;
}
@@ -374,6 +375,8 @@ brcms_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
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);
+ else if (vif->type == NL80211_IFTYPE_ADHOC)
+ brcms_c_start_adhoc(wl->wlc, vif->addr);
spin_unlock_bh(&wl->lock);

return 0;
@@ -1056,7 +1059,8 @@ static int ieee_hw_init(struct ieee80211_hw *hw)
/* channel change time is dependent on chip and band */
hw->channel_change_time = 7 * 1000;
hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
- BIT(NL80211_IFTYPE_AP);
+ BIT(NL80211_IFTYPE_AP) |
+ BIT(NL80211_IFTYPE_ADHOC);

/*
* deactivate sending probe responses by ucude, because this will
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index 7825202..59d4384 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
@@ -2186,6 +2186,14 @@ void brcms_c_start_ap(struct brcms_c_info *wlc, u8 *addr, const u8 *bssid,
brcms_b_mctrl(wlc->hw, MCTL_AP | MCTL_INFRA, MCTL_AP | MCTL_INFRA);
}

+void brcms_c_start_adhoc(struct brcms_c_info *wlc, u8 *addr)
+{
+ memcpy(wlc->pub->cur_etheraddr, addr, sizeof(wlc->pub->cur_etheraddr));
+ wlc->bsscfg->type = BRCMS_TYPE_ADHOC;
+
+ brcms_b_mctrl(wlc->hw, MCTL_AP | MCTL_INFRA, 0);
+}
+
/* Initialize GPIOs that are controlled by D11 core */
static void brcms_c_gpio_init(struct brcms_c_info *wlc)
{
@@ -3077,6 +3085,9 @@ static bool brcms_c_ps_allowed(struct brcms_c_info *wlc)
if (wlc->bsscfg->type == BRCMS_TYPE_AP)
return false;

+ if (wlc->bsscfg->type == BRCMS_TYPE_ADHOC)
+ return false;
+
return true;
}

diff --git a/drivers/net/wireless/brcm80211/brcmsmac/pub.h b/drivers/net/wireless/brcm80211/brcmsmac/pub.h
index e3bdccf..d36ea5e 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/pub.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/pub.h
@@ -334,6 +334,7 @@ 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_start_adhoc(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,
--
1.7.10.4


2013-03-24 00:48:25

by Hauke Mehrtens

[permalink] [raw]
Subject: [PATCH 11/15] brcmsmac: react on changing SSID

To send the correct probe response the hardware needs to know the SSID
when it changed.

Signed-off-by: Hauke Mehrtens <[email protected]>
---
drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c | 6 ++++++
drivers/net/wireless/brcm80211/brcmsmac/main.c | 9 +++++++++
drivers/net/wireless/brcm80211/brcmsmac/pub.h | 2 ++
3 files changed, 17 insertions(+)

diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
index 591e262..1d0d0f6 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
@@ -521,6 +521,12 @@ brcms_ops_bss_info_changed(struct ieee80211_hw *hw,
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;
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index 60dc2c4..cf11d894 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
@@ -3783,6 +3783,15 @@ static void brcms_c_set_bssid(struct brcms_bss_cfg *bsscfg)
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;
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/pub.h b/drivers/net/wireless/brcm80211/brcmsmac/pub.h
index 8a3071f..6ed0a20 100644
--- 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 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);
+extern void brcms_c_set_ssid(struct brcms_c_info *wlc, u8 *ssid,
+ size_t ssid_len);

#endif /* _BRCM_PUB_H_ */
--
1.7.10.4


2013-03-24 00:48:12

by Hauke Mehrtens

[permalink] [raw]
Subject: [PATCH 07/15] brcmsmac: remove brcms_bss_cfg->cur_etheraddr

use brcms_pub->cur_etheraddr instead

Signed-off-by: Hauke Mehrtens <[email protected]>
---
drivers/net/wireless/brcm80211/brcmsmac/main.c | 4 ++--
drivers/net/wireless/brcm80211/brcmsmac/main.h | 1 -
2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index 9af5851..056ca2c 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
@@ -3764,7 +3764,7 @@ static int brcms_c_set_mac(struct brcms_bss_cfg *bsscfg)
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);

@@ -7355,7 +7355,7 @@ brcms_c_bcn_prb_template(struct brcms_c_info *wlc, u16 type,
/* A1 filled in by MAC for prb resp, broadcast for bcn */
if (type == IEEE80211_STYPE_BEACON)
memcpy(&h->da, &ether_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 */
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.h b/drivers/net/wireless/brcm80211/brcmsmac/main.h
index 65818e2..397cff3 100644
--- 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;
};

--
1.7.10.4


2013-05-28 20:05:32

by Hauke Mehrtens

[permalink] [raw]
Subject: Re: REGRESSION: v3.10-rc1: [PATCH 04/15] brcmsmac: remove brcms_bss_cfg->associated

On 05/19/2013 12:24 PM, Hauke Mehrtens wrote:
> On 05/19/2013 10:21 AM, Arend van Spriel wrote:
>> On 05/18/2013 09:53 PM, Arend van Spriel wrote:
>>> On 03/24/2013 01:45 AM, Hauke Mehrtens wrote:
>>>> Replaced the usage with pub->associated.
>>>>
>>>> Signed-off-by: Hauke Mehrtens <[email protected]>
>>>> ---
>>>> drivers/net/wireless/brcm80211/brcmsmac/main.c | 12 +++---------
>>>> drivers/net/wireless/brcm80211/brcmsmac/main.h | 2 --
>>>> 2 files changed, 3 insertions(+), 11 deletions(-)
>>>
>>> Hi Hauke,
>>>
>>> I had a problem with bcm43224 in STA mode and bisecting it shows this
>>> change as culprit. On laptop I installed kernel with brcmsmac compiled
>>> as module. It comes up and associates during boot, but after logging in
>>> there is no connectivity. Triggering reassoc gives connectivity for some
>>> time, but after a while (1-2 min) it stops.
>>>
>>> I am looking into it. Given the function name below (brcms_c_ps_allowed)
>>> it may be power-save related. I will keep you informed.
>>>
>>> Gr. AvS
>>>
>>>> diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c
>>>> b/drivers/net/wireless/brcm80211/brcmsmac/main.c
>>>> index 90e6c0d..810b7e2 100644
>>>> --- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
>>>> +++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
>>>> @@ -3049,8 +3049,6 @@ static void brcms_b_antsel_set(struct
>>>> brcms_hardware *wlc_hw, u32 antsel_avail)
>>>> */
>>>> 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;
>>>> @@ -3059,9 +3057,6 @@ static bool brcms_c_ps_allowed(struct
>>>> brcms_c_info *wlc)
>>>> if (wlc->filter_flags & FIF_PROMISC_IN_BSS)
>>>> return false;
>>>>
>>>> - if (cfg->associated)
>>>> - return false;
>>>> -
>>
>> wlc->pub->associated and wlc->bsscfg->associated have the same value,
>> which I guess was your motivation to remove it from struct
>> brcms_bss_cfg. So before this patch the function brcms_c_ps_allowed()
>> always returned false. As power-save is a unsupported feature for
>> brcmsmac that was fine, but the removal below changed that behaviour.
>
> The change in the behavior was not intended. I removed
> wlc->bsscfg->associated because it always had the same value as
> wlc->pub->associated. I must have missed that one the if conditions was
> negated. When multi bssid support will be added to brcmsmac this
> complete handling has to be reworked.
>
>> As power-save is not supported this function can be changed to simply
>> return false for now. I will send out a patch for that.
>
> Thanks for making such a patch.

What is the status of the patch? Is there more needed than returning
false in brcms_c_ps_allowed()?
There is also a bugzilla report at [0] and I added patch a [1], feel
free to use it.

Hauke

[0]: https://bugzilla.kernel.org/show_bug.cgi?id=58471
[1]: https://bugzilla.kernel.org/attachment.cgi?id=102741

2013-05-19 08:32:06

by Arend van Spriel

[permalink] [raw]
Subject: Re: REGRESSION: v3.10-rc1: [PATCH 04/15] brcmsmac: remove brcms_bss_cfg->associated

On 05/19/2013 01:34 AM, Jonas Gorski wrote:
> Hauke's change made it possible for the code to return true, which
> looks at a first glance what might have been originally intended here,
> and the bug is somewhere else. But what do I know, I'm no Broadcom
> engineer;-)

Point taken :-) The function seems rather useless in brcmsmac, but I
would like to keep it so we can use internal driver source as reference
when adding power-save support.

Regards,
Arend


2013-05-18 23:35:22

by Jonas Gorski

[permalink] [raw]
Subject: Re: REGRESSION: v3.10-rc1: [PATCH 04/15] brcmsmac: remove brcms_bss_cfg->associated

On Sat, May 18, 2013 at 9:53 PM, Arend van Spriel <[email protected]> wrote:
> On 03/24/2013 01:45 AM, Hauke Mehrtens wrote:
>>
>> Replaced the usage with pub->associated.
>>
>> Signed-off-by: Hauke Mehrtens <[email protected]>
>> ---
>> drivers/net/wireless/brcm80211/brcmsmac/main.c | 12 +++---------
>> drivers/net/wireless/brcm80211/brcmsmac/main.h | 2 --
>> 2 files changed, 3 insertions(+), 11 deletions(-)
>
>
> Hi Hauke,
>
> I had a problem with bcm43224 in STA mode and bisecting it shows this change
> as culprit. On laptop I installed kernel with brcmsmac compiled as module.
> It comes up and associates during boot, but after logging in there is no
> connectivity. Triggering reassoc gives connectivity for some time, but after
> a while (1-2 min) it stops.
>
> I am looking into it. Given the function name below (brcms_c_ps_allowed) it
> may be power-save related. I will keep you informed.

Looking at the (old) code;
static bool brcms_c_ps_allowed(struct brcms_c_info *wlc)
{
return false;
}

should restore the old behavior.

As for this actual old code:
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;

/* disallow PS when one of these meets when not scanning */
if (wlc->filter_flags & FIF_PROMISC_IN_BSS)
return false;

if (cfg->associated)
return false;

return true;
}

The only way to return true here is if wlc->pub->associated == true
and cfg->associated == false, but the only place setting these is/was
brcms_c_associate_upd() which sets both to the same value. Therefore
the code will always return false.

Hauke's change made it possible for the code to return true, which
looks at a first glance what might have been originally intended here,
and the bug is somewhere else. But what do I know, I'm no Broadcom
engineer ;-)


Jonas

2013-05-19 10:25:09

by Hauke Mehrtens

[permalink] [raw]
Subject: Re: REGRESSION: v3.10-rc1: [PATCH 04/15] brcmsmac: remove brcms_bss_cfg->associated

On 05/19/2013 10:21 AM, Arend van Spriel wrote:
> On 05/18/2013 09:53 PM, Arend van Spriel wrote:
>> On 03/24/2013 01:45 AM, Hauke Mehrtens wrote:
>>> Replaced the usage with pub->associated.
>>>
>>> Signed-off-by: Hauke Mehrtens <[email protected]>
>>> ---
>>> drivers/net/wireless/brcm80211/brcmsmac/main.c | 12 +++---------
>>> drivers/net/wireless/brcm80211/brcmsmac/main.h | 2 --
>>> 2 files changed, 3 insertions(+), 11 deletions(-)
>>
>> Hi Hauke,
>>
>> I had a problem with bcm43224 in STA mode and bisecting it shows this
>> change as culprit. On laptop I installed kernel with brcmsmac compiled
>> as module. It comes up and associates during boot, but after logging in
>> there is no connectivity. Triggering reassoc gives connectivity for some
>> time, but after a while (1-2 min) it stops.
>>
>> I am looking into it. Given the function name below (brcms_c_ps_allowed)
>> it may be power-save related. I will keep you informed.
>>
>> Gr. AvS
>>
>>> diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c
>>> b/drivers/net/wireless/brcm80211/brcmsmac/main.c
>>> index 90e6c0d..810b7e2 100644
>>> --- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
>>> +++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
>>> @@ -3049,8 +3049,6 @@ static void brcms_b_antsel_set(struct
>>> brcms_hardware *wlc_hw, u32 antsel_avail)
>>> */
>>> 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;
>>> @@ -3059,9 +3057,6 @@ static bool brcms_c_ps_allowed(struct
>>> brcms_c_info *wlc)
>>> if (wlc->filter_flags & FIF_PROMISC_IN_BSS)
>>> return false;
>>>
>>> - if (cfg->associated)
>>> - return false;
>>> -
>
> wlc->pub->associated and wlc->bsscfg->associated have the same value,
> which I guess was your motivation to remove it from struct
> brcms_bss_cfg. So before this patch the function brcms_c_ps_allowed()
> always returned false. As power-save is a unsupported feature for
> brcmsmac that was fine, but the removal below changed that behaviour.

The change in the behavior was not intended. I removed
wlc->bsscfg->associated because it always had the same value as
wlc->pub->associated. I must have missed that one the if conditions was
negated. When multi bssid support will be added to brcmsmac this
complete handling has to be reworked.

> As power-save is not supported this function can be changed to simply
> return false for now. I will send out a patch for that.

Thanks for making such a patch.

> Regards,
> Arend
>
>>> return true;
>>> }
>>>
>>> @@ -3819,7 +3814,7 @@ static void brcms_c_set_home_chanspec(struct
>>> brcms_c_info *wlc, u16 chanspec)
>>> if (wlc->home_chanspec != chanspec) {
>>> wlc->home_chanspec = chanspec;
>>>
>>> - if (wlc->bsscfg->associated)
>>> + if (wlc->pub->associated)
>>> wlc->bsscfg->current_bss->chanspec = chanspec;
>>> }
>>> }
>>> @@ -5433,7 +5428,7 @@ static void brcms_c_ofdm_rateset_war(struct
>>> brcms_c_info *wlc)
>>> 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];
>>> @@ -5527,7 +5522,7 @@ int brcms_c_set_rateset(struct brcms_c_info
>>> *wlc, struct brcm_rateset *rs)
>>> /* 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;
>>> @@ -7496,7 +7491,6 @@ void brcms_c_scan_stop(struct brcms_c_info *wlc)
>>> void brcms_c_associate_upd(struct brcms_c_info *wlc, bool state)
>>> {
>>> wlc->pub->associated = state;
>>> - wlc->bsscfg->associated = state;
>>> }
>>>
>>> /*
>>> diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.h
>>> b/drivers/net/wireless/brcm80211/brcmsmac/main.h
>>> index 0cfe782..96dc2f4 100644
>>> --- 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];
>>>
>>
>
>


2013-05-18 19:54:04

by Arend van Spriel

[permalink] [raw]
Subject: REGRESSION: v3.10-rc1: [PATCH 04/15] brcmsmac: remove brcms_bss_cfg->associated

On 03/24/2013 01:45 AM, Hauke Mehrtens wrote:
> Replaced the usage with pub->associated.
>
> Signed-off-by: Hauke Mehrtens <[email protected]>
> ---
> drivers/net/wireless/brcm80211/brcmsmac/main.c | 12 +++---------
> drivers/net/wireless/brcm80211/brcmsmac/main.h | 2 --
> 2 files changed, 3 insertions(+), 11 deletions(-)

Hi Hauke,

I had a problem with bcm43224 in STA mode and bisecting it shows this
change as culprit. On laptop I installed kernel with brcmsmac compiled
as module. It comes up and associates during boot, but after logging in
there is no connectivity. Triggering reassoc gives connectivity for some
time, but after a while (1-2 min) it stops.

I am looking into it. Given the function name below (brcms_c_ps_allowed)
it may be power-save related. I will keep you informed.

Gr. AvS

> diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
> index 90e6c0d..810b7e2 100644
> --- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
> +++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
> @@ -3049,8 +3049,6 @@ static void brcms_b_antsel_set(struct brcms_hardware *wlc_hw, u32 antsel_avail)
> */
> 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;
> @@ -3059,9 +3057,6 @@ static bool brcms_c_ps_allowed(struct brcms_c_info *wlc)
> if (wlc->filter_flags & FIF_PROMISC_IN_BSS)
> return false;
>
> - if (cfg->associated)
> - return false;
> -
> return true;
> }
>
> @@ -3819,7 +3814,7 @@ static void brcms_c_set_home_chanspec(struct brcms_c_info *wlc, u16 chanspec)
> if (wlc->home_chanspec != chanspec) {
> wlc->home_chanspec = chanspec;
>
> - if (wlc->bsscfg->associated)
> + if (wlc->pub->associated)
> wlc->bsscfg->current_bss->chanspec = chanspec;
> }
> }
> @@ -5433,7 +5428,7 @@ static void brcms_c_ofdm_rateset_war(struct brcms_c_info *wlc)
> 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];
> @@ -5527,7 +5522,7 @@ int brcms_c_set_rateset(struct brcms_c_info *wlc, struct brcm_rateset *rs)
> /* 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;
> @@ -7496,7 +7491,6 @@ void brcms_c_scan_stop(struct brcms_c_info *wlc)
> void brcms_c_associate_upd(struct brcms_c_info *wlc, bool state)
> {
> wlc->pub->associated = state;
> - wlc->bsscfg->associated = state;
> }
>
> /*
> diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.h b/drivers/net/wireless/brcm80211/brcmsmac/main.h
> index 0cfe782..96dc2f4 100644
> --- 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];
>



2013-05-19 08:21:48

by Arend van Spriel

[permalink] [raw]
Subject: Re: REGRESSION: v3.10-rc1: [PATCH 04/15] brcmsmac: remove brcms_bss_cfg->associated

On 05/18/2013 09:53 PM, Arend van Spriel wrote:
> On 03/24/2013 01:45 AM, Hauke Mehrtens wrote:
>> Replaced the usage with pub->associated.
>>
>> Signed-off-by: Hauke Mehrtens <[email protected]>
>> ---
>> drivers/net/wireless/brcm80211/brcmsmac/main.c | 12 +++---------
>> drivers/net/wireless/brcm80211/brcmsmac/main.h | 2 --
>> 2 files changed, 3 insertions(+), 11 deletions(-)
>
> Hi Hauke,
>
> I had a problem with bcm43224 in STA mode and bisecting it shows this
> change as culprit. On laptop I installed kernel with brcmsmac compiled
> as module. It comes up and associates during boot, but after logging in
> there is no connectivity. Triggering reassoc gives connectivity for some
> time, but after a while (1-2 min) it stops.
>
> I am looking into it. Given the function name below (brcms_c_ps_allowed)
> it may be power-save related. I will keep you informed.
>
> Gr. AvS
>
>> diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c
>> b/drivers/net/wireless/brcm80211/brcmsmac/main.c
>> index 90e6c0d..810b7e2 100644
>> --- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
>> +++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
>> @@ -3049,8 +3049,6 @@ static void brcms_b_antsel_set(struct
>> brcms_hardware *wlc_hw, u32 antsel_avail)
>> */
>> 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;
>> @@ -3059,9 +3057,6 @@ static bool brcms_c_ps_allowed(struct
>> brcms_c_info *wlc)
>> if (wlc->filter_flags & FIF_PROMISC_IN_BSS)
>> return false;
>>
>> - if (cfg->associated)
>> - return false;
>> -

wlc->pub->associated and wlc->bsscfg->associated have the same value,
which I guess was your motivation to remove it from struct
brcms_bss_cfg. So before this patch the function brcms_c_ps_allowed()
always returned false. As power-save is a unsupported feature for
brcmsmac that was fine, but the removal below changed that behaviour.

As power-save is not supported this function can be changed to simply
return false for now. I will send out a patch for that.

Regards,
Arend

>> return true;
>> }
>>
>> @@ -3819,7 +3814,7 @@ static void brcms_c_set_home_chanspec(struct
>> brcms_c_info *wlc, u16 chanspec)
>> if (wlc->home_chanspec != chanspec) {
>> wlc->home_chanspec = chanspec;
>>
>> - if (wlc->bsscfg->associated)
>> + if (wlc->pub->associated)
>> wlc->bsscfg->current_bss->chanspec = chanspec;
>> }
>> }
>> @@ -5433,7 +5428,7 @@ static void brcms_c_ofdm_rateset_war(struct
>> brcms_c_info *wlc)
>> 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];
>> @@ -5527,7 +5522,7 @@ int brcms_c_set_rateset(struct brcms_c_info
>> *wlc, struct brcm_rateset *rs)
>> /* 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;
>> @@ -7496,7 +7491,6 @@ void brcms_c_scan_stop(struct brcms_c_info *wlc)
>> void brcms_c_associate_upd(struct brcms_c_info *wlc, bool state)
>> {
>> wlc->pub->associated = state;
>> - wlc->bsscfg->associated = state;
>> }
>>
>> /*
>> diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.h
>> b/drivers/net/wireless/brcm80211/brcmsmac/main.h
>> index 0cfe782..96dc2f4 100644
>> --- 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];
>>
>



2013-06-12 13:46:46

by Hauke Mehrtens

[permalink] [raw]
Subject: Re: [PATCH 03/15] brcmsmac: remove brcms_bss_cfg->BSS

On 06/06/2013 02:05 PM, Arend van Spriel wrote:
> On 03/24/2013 01:45 AM, Hauke Mehrtens wrote:
>> This was a read only member. The checks using BSS are replaced by
>> better fitting checks of the new type member.
>>
>> The change in brcms_c_tbtt() was based on code from b43, in
>> brcms_c_ps_allowed() the same happens with BSS being true or false,
>> beaconing and probe responses are just needed in ap mode.
>>
>> Signed-off-by: Hauke Mehrtens <[email protected]>
>> ---
>> drivers/net/wireless/brcm80211/brcmsmac/main.c | 23
>> +++++++++--------------
>> drivers/net/wireless/brcm80211/brcmsmac/main.h | 2 --
>> 2 files changed, 9 insertions(+), 16 deletions(-)
>>
>> diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c
>> b/drivers/net/wireless/brcm80211/brcmsmac/main.c
>> index 4e420ea..90e6c0d 100644
>> --- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
>> +++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
>> @@ -1069,7 +1069,7 @@ brcms_b_txstatus(struct brcms_hardware *wlc_hw,
>> bool bound, bool *fatal)
>>
>> 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
>
> Hi Hauke,
>
> Sorry for such a late comment. It seem that the above change is
> incosistent with the changes below. You probably need to change it.

Yes there is something wrong. I got confused with b43 which sets
wlc->qvalid |= MCMD_DIRFRMQVAL; only in adhoc mode and not in ap mode.

I will create a patch and test this.

>> @@ -7386,7 +7379,8 @@ void brcms_c_update_beacon(struct brcms_c_info
>> *wlc)
>> {
>> struct brcms_bss_cfg *bsscfg = wlc->bsscfg;
>>
>> - if (bsscfg->up && !bsscfg->BSS)
>> + if (bsscfg->up && (bsscfg->type == BRCMS_TYPE_AP ||
>> + bsscfg->type == BRCMS_TYPE_ADHOC))
>> /* Clear the soft intmask */
>> wlc->defmacintmask &= ~MI_BCNTPL;
>> }
>> @@ -7461,7 +7455,8 @@ void brcms_c_update_probe_resp(struct
>> brcms_c_info *wlc, bool suspend)
>> 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 ||
>> + bsscfg->type == BRCMS_TYPE_ADHOC))
>> brcms_c_bss_update_probe_resp(wlc, bsscfg, suspend);
>> }
>>
>
>


2013-06-06 12:08:44

by Arend van Spriel

[permalink] [raw]
Subject: Re: [PATCH 03/15] brcmsmac: remove brcms_bss_cfg->BSS

On 03/24/2013 01:45 AM, Hauke Mehrtens wrote:
> This was a read only member. The checks using BSS are replaced by
> better fitting checks of the new type member.
>
> The change in brcms_c_tbtt() was based on code from b43, in
> brcms_c_ps_allowed() the same happens with BSS being true or false,
> beaconing and probe responses are just needed in ap mode.
>
> Signed-off-by: Hauke Mehrtens <[email protected]>
> ---
> drivers/net/wireless/brcm80211/brcmsmac/main.c | 23 +++++++++--------------
> drivers/net/wireless/brcm80211/brcmsmac/main.h | 2 --
> 2 files changed, 9 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
> index 4e420ea..90e6c0d 100644
> --- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
> +++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
> @@ -1069,7 +1069,7 @@ brcms_b_txstatus(struct brcms_hardware *wlc_hw, bool bound, bool *fatal)
>
> 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

Hi Hauke,

Sorry for such a late comment. It seem that the above change is
incosistent with the changes below. You probably need to change it.

Gr. AvS

> @@ -7386,7 +7379,8 @@ void brcms_c_update_beacon(struct brcms_c_info *wlc)
> {
> struct brcms_bss_cfg *bsscfg = wlc->bsscfg;
>
> - if (bsscfg->up && !bsscfg->BSS)
> + if (bsscfg->up && (bsscfg->type == BRCMS_TYPE_AP ||
> + bsscfg->type == BRCMS_TYPE_ADHOC))
> /* Clear the soft intmask */
> wlc->defmacintmask &= ~MI_BCNTPL;
> }
> @@ -7461,7 +7455,8 @@ void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend)
> 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 ||
> + bsscfg->type == BRCMS_TYPE_ADHOC))
> brcms_c_bss_update_probe_resp(wlc, bsscfg, suspend);
> }
>