2013-02-24 01:06:42

by Hauke Mehrtens

[permalink] [raw]
Subject: [RFC 00/13] 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 mode support is added in the last patch.

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.

The probe responses are currently send by the ucode based on the
template and by mac80211. I was searching for a switch so disable probe
request forwarding from the ucode to the driver.

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.


Hauke Mehrtens (13):
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: activate AP support

drivers/net/wireless/brcm80211/brcmsmac/d11.h | 1 +
.../net/wireless/brcm80211/brcmsmac/mac80211_if.c | 66 +++-
drivers/net/wireless/brcm80211/brcmsmac/main.c | 340 ++++++++++++++------
drivers/net/wireless/brcm80211/brcmsmac/main.h | 25 +-
drivers/net/wireless/brcm80211/brcmsmac/pub.h | 15 +-
5 files changed, 334 insertions(+), 113 deletions(-)

--
1.7.10.4



2013-02-24 22:31:26

by Hauke Mehrtens

[permalink] [raw]
Subject: Re: [RFC 00/13] brcmsmac: add AP mode

On 02/24/2013 06:22 PM, Johannes Berg wrote:
> On Sun, 2013-02-24 at 12:38 +0100, Hauke Mehrtens wrote:
>
>> Yes this needs some review and more testing, I hope this also works with
>> power saving stations and so on.
>
> I doubt it will. I know it's not really a major thing, but due to the
> way aggregation is handled you definitely need to implement
> "release_buffered_frames". "allow_buffered_frames" might not be
> necessary if the device doesn't track station's powersave mode by
> itself? Not sure how that's supposed to work, too long since I worked on
> Broadcom stuff.

Ok, I have to read how power saving exactly works and look how brcmsmac
currently does aggregation and so on.

>> probe response offload
>
> See also enum nl80211_probe_resp_offload_support_attr; probe response
> offload is a bit tricky because e.g. for WPS you absolutely need
> userspace, not the firmware, to respond. So if the firmware can't tell
> the difference between regular and WPS probe requests, you can't support
> WPS.
>
> If you can, I'd probably just turn off the response offload. It's likely
> not worth the effort. If you wanted to make that turning off conditional
> we'd have to come up with a bunch of new API to let the driver know what
> kind of AP it's running.

Ok, I will turn it off, this driver is mostly used on devices without a
battery, or a big one, so the energy saving by offloading is not needed
and the performance improvement is probably not that big.

Hauke

2013-02-24 15:26:02

by Hauke Mehrtens

[permalink] [raw]
Subject: Re: [RFC 00/13] brcmsmac: add AP mode

On 02/24/2013 12:38 PM, Hauke Mehrtens wrote:
> On 02/24/2013 11:21 AM, Arend Van Spriel wrote:
>> On Sunday, February 24, 2013 2:05 AM, Hauke Mehrtens wrote:
>>> This patch series contains some cleanup patches for brcmsmac and then
>>> adds beacon and probe response template upload.
>>> With these features AP mode support is added in the last patch.
>>
>> Someone was bound to start on this and we are lately too focussed on
>> brcmfmac. We will review the patches and found out whether our test
>> framework can cover AP mode.
>
> Yes this needs some review and more testing, I hope this also works with
> power saving stations and so on.
>
>>> 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:
>>
>> 5GHz is a bit tricky. I will need to find out whether AP mode can work with
>> the current ucode.
>
> Currently brcmsmac completely denies beaconing on 5GHz in channel.c, how
> could that be changed and still compatible with the interpretation of
> the regulation rules by your lawyers?
>
>>> [ 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
>>
>> It generally indicates a hang in the ucode. Are you using the firmware from
>> the linux-firmware repository?
>
> Instead of these error messages I also got a complete system hang when
> compiling a kernel without lock debugging, the difference between this
> result with lock debugging and the hang without lock debugging is
> probably resulted from different timings.
>
> I used the ucode extracted from the proprietary driver, because only
> this ucode works with my BCM4716, this is ucode 666.2 from driver
> 5.100.138. I will try the ucode from linux-firmware today.

I just tried the firmware version 610.812 from linux-firmware and there
I do not get an error message or hang when starting the AP in 5GHz mode,
but my iwl6300 card is unable to find this network.

>>> The probe responses are currently send by the ucode based on the
>>> template and by mac80211. I was searching for a switch so disable probe
>>> request forwarding from the ucode to the driver.
>>
>> I am pretty sure there is. I will look into this and let you know.
>
> That would be nice.
>
>>> 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.
>>
>> Yeah. Basically, a lot of conversions are done at mac80211 interface to keep
>> the low-level driver code similar to the code base it came from. That is the
>> path taken. I would like to see a replacement driver some day that shares more
>> structure definitions with the linux wireless subsystem, but for now that is just
>> me daydreaming ;-)
>
> I saw your code for beaconing and probe response templates, but I mostly
> replaced it with a new version because this architecture was not
> compatible with mac80211. For the Phy code it makes sense and it is
> probably not so hard to stay near your proprietary code base, but I do
> not think this works very well with the rest of the code mostly in main.c.
>
> Hauke
>


2013-02-24 01:06:55

by Hauke Mehrtens

[permalink] [raw]
Subject: [RFC 06/13] 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 | 6 +++---
drivers/net/wireless/brcm80211/brcmsmac/main.h | 2 --
2 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index 95f44b1..3985738c 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
@@ -7373,7 +7373,7 @@ 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)
+ if (wlc->pub->up && bsscfg->type == BRCMS_TYPE_AP)
/* Clear the soft intmask */
wlc->defmacintmask &= ~MI_BCNTPL;
}
@@ -7448,7 +7448,7 @@ 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)
+ if (wlc->pub->up && bsscfg->type == BRCMS_TYPE_AP)
brcms_c_bss_update_probe_resp(wlc, bsscfg, suspend);
}

@@ -7801,7 +7801,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-02-24 17:22:48

by Johannes Berg

[permalink] [raw]
Subject: Re: [RFC 00/13] brcmsmac: add AP mode

On Sun, 2013-02-24 at 12:38 +0100, Hauke Mehrtens wrote:

> Yes this needs some review and more testing, I hope this also works with
> power saving stations and so on.

I doubt it will. I know it's not really a major thing, but due to the
way aggregation is handled you definitely need to implement
"release_buffered_frames". "allow_buffered_frames" might not be
necessary if the device doesn't track station's powersave mode by
itself? Not sure how that's supposed to work, too long since I worked on
Broadcom stuff.


> probe response offload

See also enum nl80211_probe_resp_offload_support_attr; probe response
offload is a bit tricky because e.g. for WPS you absolutely need
userspace, not the firmware, to respond. So if the firmware can't tell
the difference between regular and WPS probe requests, you can't support
WPS.

If you can, I'd probably just turn off the response offload. It's likely
not worth the effort. If you wanted to make that turning off conditional
we'd have to come up with a bunch of new API to let the driver know what
kind of AP it's running.

johannes


2013-02-24 01:06:44

by Hauke Mehrtens

[permalink] [raw]
Subject: [RFC 02/13] 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 ab678ae..577df22 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
@@ -364,9 +364,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 5f455ba..5696257 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-02-24 01:06:50

by Hauke Mehrtens

[permalink] [raw]
Subject: [RFC 05/13] 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 b5b7a8f..95f44b1 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-02-24 15:06:19

by W. Trevor King

[permalink] [raw]
Subject: Re: [RFC 12/13] brcmsmac: add support for probe response template

On Sun, Feb 24, 2013 at 10:39:25AM +0100, Hauke Mehrtens wrote:
> On 02/24/2013 03:30 AM, W. Trevor King wrote:
> > On Sun, Feb 24, 2013 at 02:06:10AM +0100, Hauke Mehrtens wrote:
> >> 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.
> >
> > Should this read "so there are more answers sent to"?
> >
> yes there are more answers then normal send out, but it is normal that
> you send out more than one, at least I have seen it so it is probably
> in the standard. The last part of this patch could applied again to
> not receive probe requests any more:

I was just trying to correct the English ;), not make a deeper
statement about the content. Sorry for my initial ambiguity…

--
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy


Attachments:
(No filename) (1.07 kB)
signature.asc (836.00 B)
OpenPGP digital signature
Download all attachments

2013-02-24 01:07:13

by Hauke Mehrtens

[permalink] [raw]
Subject: [RFC 12/13] 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 3bb0aec..1348d73 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
@@ -538,6 +538,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__,
@@ -1036,6 +1045,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 7c97de8..15bff24 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;
@@ -7526,6 +7465,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)
@@ -7545,30 +7498,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);
@@ -7582,13 +7524,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)
@@ -7596,8 +7536,12 @@ 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 (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,
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-02-24 01:07:05

by Hauke Mehrtens

[permalink] [raw]
Subject: [RFC 11/13] 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 7a76977..3bb0aec 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
@@ -520,6 +520,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 7ed4e8e..7c97de8 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-02-24 01:06:59

by Hauke Mehrtens

[permalink] [raw]
Subject: [RFC 08/13] 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 49a95c4..44dc7ac 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-02-24 09:41:20

by Hauke Mehrtens

[permalink] [raw]
Subject: Re: [RFC 13/13] brcmsmac: activate AP support

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 02/24/2013 03:30 AM, W. Trevor King wrote:
> On Sun, Feb 24, 2013 at 02:06:11AM +0100, Hauke Mehrtens wrote:
>> This activates the AP mode support. … /* Just STA for now */ - if
>> (vif->type != NL80211_IFTYPE_STATION) { + if (vif->type !=
>> NL80211_IFTYPE_STATION && + vif->type != NL80211_IFTYPE_AP)
>> {
>
> The "Just STA" comment can probably go too ;).
Thanks I will change that, the message below also says sta only.

Hauke

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with undefined - http://www.enigmail.net/

iQIcBAEBAgAGBQJRKeA2AAoJEIZ0px9YPRMybA4P/ArfH7aBKoB1q+utXD44cFGB
SoAaDkYmhoyWE/M2ySQ+8IvSQiBXB1e1bs+6pHvf3FCPd2OM5JhOx4ok/Yu3TJWG
Q1SbhWGzFOKd0EqawvNZEAc2vwAsVqBC0+v9ktgLz6+H351Uv+nNEC223B8okHZr
XAgEhFg1ZFJzIkL/SkW9ZfCibdetU5ZBKpe2mw1Vd6jvOVluot6svsJ0m+b4boGK
a3w8CLTTL2N6DYaLahkZd4aNadCzKg6Wsd3gdLxFp3+nFDootgKMxZcHCPcZ+5LM
l+Z7daa2fl91qLv00DfXyeaBhcZyoYHy7P+kTGQf2N2uR1MkuNe7vmkpynQfcLIu
mgEBovx5193I82qN7+UNJnrXF5PQTcb3uktNYXiNXTzYHORp9NMlfH66b3VIX3p9
Ayn2Kxcm5vpao8p+OvAA0uFPE7UjVj3jO2SZ+Qcm3zEBC5/vQbW+XXpoadn5CnHs
uzHg2dAovV0hfUO8I6mtXUankshRMd23mhw8FJnwXmsw2CE82c/UKZqFJBe6cFju
C8KWY3G3GDTGHZ7n1o/4a43jzrnW+FBpMYYV7Deoz7CpqaquT9BELkbrjeYgrR+t
00It1ysQeNIG6tqZtlwhH4ZEjMrKKoOdn6xIwcdm7OSZCndveYFGJ6TkoklPyOro
2KdI/e13NF8y7XQ4PAGS
=oraK
-----END PGP SIGNATURE-----

2013-02-24 01:07:01

by Hauke Mehrtens

[permalink] [raw]
Subject: [RFC 09/13] 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 44dc7ac..b993ddc 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-02-24 11:38:43

by Hauke Mehrtens

[permalink] [raw]
Subject: Re: [RFC 00/13] brcmsmac: add AP mode

On 02/24/2013 11:21 AM, Arend Van Spriel wrote:
> On Sunday, February 24, 2013 2:05 AM, Hauke Mehrtens wrote:
>> This patch series contains some cleanup patches for brcmsmac and then
>> adds beacon and probe response template upload.
>> With these features AP mode support is added in the last patch.
>
> Someone was bound to start on this and we are lately too focussed on
> brcmfmac. We will review the patches and found out whether our test
> framework can cover AP mode.

Yes this needs some review and more testing, I hope this also works with
power saving stations and so on.

>> 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:
>
> 5GHz is a bit tricky. I will need to find out whether AP mode can work with
> the current ucode.

Currently brcmsmac completely denies beaconing on 5GHz in channel.c, how
could that be changed and still compatible with the interpretation of
the regulation rules by your lawyers?

>> [ 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
>
> It generally indicates a hang in the ucode. Are you using the firmware from
> the linux-firmware repository?

Instead of these error messages I also got a complete system hang when
compiling a kernel without lock debugging, the difference between this
result with lock debugging and the hang without lock debugging is
probably resulted from different timings.

I used the ucode extracted from the proprietary driver, because only
this ucode works with my BCM4716, this is ucode 666.2 from driver
5.100.138. I will try the ucode from linux-firmware today.

>> The probe responses are currently send by the ucode based on the
>> template and by mac80211. I was searching for a switch so disable probe
>> request forwarding from the ucode to the driver.
>
> I am pretty sure there is. I will look into this and let you know.

That would be nice.

>> 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.
>
> Yeah. Basically, a lot of conversions are done at mac80211 interface to keep
> the low-level driver code similar to the code base it came from. That is the
> path taken. I would like to see a replacement driver some day that shares more
> structure definitions with the linux wireless subsystem, but for now that is just
> me daydreaming ;-)

I saw your code for beaconing and probe response templates, but I mostly
replaced it with a new version because this architecture was not
compatible with mac80211. For the Phy code it makes sense and it is
probably not so hard to stay near your proprietary code base, but I do
not think this works very well with the rest of the code mostly in main.c.

Hauke

2013-02-24 01:06:47

by Hauke Mehrtens

[permalink] [raw]
Subject: [RFC 03/13] 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 | 21 +++++++--------------
drivers/net/wireless/brcm80211/brcmsmac/main.h | 2 --
2 files changed, 7 insertions(+), 16 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index 5696257..2242ec0 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,7 @@ 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)
/* Clear the soft intmask */
wlc->defmacintmask &= ~MI_BCNTPL;
}
@@ -7461,7 +7454,7 @@ 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)
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-02-24 01:07:17

by Hauke Mehrtens

[permalink] [raw]
Subject: [RFC 13/13] 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 | 9 +++++++--
drivers/net/wireless/brcm80211/brcmsmac/main.c | 15 +++++++++++++++
drivers/net/wireless/brcm80211/brcmsmac/pub.h | 2 ++
3 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
index 1348d73..17880e8 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
@@ -357,7 +357,8 @@ 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) {
+ 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);
@@ -369,6 +370,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;
@@ -1043,7 +1047,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);

hw->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;

diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index 15bff24..d723e15 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 5e6db62..ecff925 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-02-24 09:39:38

by Hauke Mehrtens

[permalink] [raw]
Subject: Re: [RFC 12/13] brcmsmac: add support for probe response template

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 02/24/2013 03:30 AM, W. Trevor King wrote:
> On Sun, Feb 24, 2013 at 02:06:10AM +0100, Hauke Mehrtens wrote:
>> 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.
>
> Should this read "so there are more answers sent to"?
>
yes there are more answers then normal send out, but it is normal that
you send out more than one, at least I have seen it so it is probably
in the standard. The last part of this patch could applied again to
not receive probe requests any more:

http://driverdev.linuxdriverproject.org/pipermail/devel/2011-October/021574.html

Hauke
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with undefined - http://www.enigmail.net/

iQIcBAEBAgAGBQJRKd/JAAoJEIZ0px9YPRMyNa8QAJtd4fqHhJy+uH+yzc5OKezu
z4bHbKidWek6quLJz+34zo8hMMebnVWb+PxtKkbfN3XiRfFvggOuGRqgY73mWe8d
UctlXnnV292h+QBIYr6exrv4WoqFISiGKyvudTS0aHeLLq9S4slVXRYiEkJT9tdW
Lc/ccl9rg9QYAOkZcdJaNDp+MwZ3WA+fJvGXQiVwYKzGoAt6tUZZkZHs3yHQBCe1
rq3nITwXPRxor+3ba/2ws9mIcZAbGSf6eIOxdwC7JSoP2D8QvYU3pUvR9h79NtlB
2EXOo9PuzPnG8cpcFDi44iZGNf9Kjw4eoZ9JjfrbfXNhx7ucf8wjVNehVyPFivr0
PlptGecxs08UnfCQXBH+cpvlMjE+8kj1gxmPRkD0Z+ghgY801bHmbzprd8mOFyYY
TMqOlAUZtJgemPfYko/4ZaYeCZmMF1oFiDOUs3jkodAGU++TI/IG/DD7K5ZtPjBJ
0OzV1lr5YvOBUIXlhQQQYpF1IfIShyhcRwVPA9ZM5HvQHkKRbx8tF7QeqeOcdrn4
1tGg+Zrr9nc0UcS8ropnPRwjqDjCOna7F6aIaLZOm+D5WFX9ieWNbPx21s1Fo4fW
cf7VOvLZ/oWuJ0yrnbGQ/SBq0RvWF4zxSRQqXpZsu8CJnQZdeloq0REIooQK9Tl6
KgjpbASoKSVGBAI0w8RT
=v7yy
-----END PGP SIGNATURE-----

2013-02-24 02:31:22

by W. Trevor King

[permalink] [raw]
Subject: Re: [RFC 13/13] brcmsmac: activate AP support

On Sun, Feb 24, 2013 at 02:06:11AM +0100, Hauke Mehrtens wrote:
> This activates the AP mode support.
> …
> /* Just STA for now */
> - if (vif->type != NL80211_IFTYPE_STATION) {
> + if (vif->type != NL80211_IFTYPE_STATION &&
> + vif->type != NL80211_IFTYPE_AP) {

The "Just STA" comment can probably go too ;).

Cheers,
Trevor

--
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy


Attachments:
(No filename) (488.00 B)
signature.asc (836.00 B)
OpenPGP digital signature
Download all attachments

2013-02-24 01:06:52

by Hauke Mehrtens

[permalink] [raw]
Subject: [RFC 04/13] 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 2242ec0..b5b7a8f 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;
@@ -7494,7 +7489,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-02-24 01:06:41

by Hauke Mehrtens

[permalink] [raw]
Subject: [RFC 01/13] 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 c6451c6..ab678ae 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
@@ -738,6 +738,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,
@@ -754,6 +776,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 8ef02dc..5f455ba 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-02-24 01:06:56

by Hauke Mehrtens

[permalink] [raw]
Subject: [RFC 07/13] 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 3985738c..49a95c4 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-02-24 10:21:54

by Arend van Spriel

[permalink] [raw]
Subject: RE: [RFC 00/13] brcmsmac: add AP mode

On Sunday, February 24, 2013 2:05 AM, Hauke Mehrtens wrote:
> This patch series contains some cleanup patches for brcmsmac and then
> adds beacon and probe response template upload.
> With these features AP mode support is added in the last patch.

Someone was bound to start on this and we are lately too focussed on
brcmfmac. We will review the patches and found out whether our test
framework can cover AP mode.

> 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:

5GHz is a bit tricky. I will need to find out whether AP mode can work with
the current ucode.

> [ 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

It generally indicates a hang in the ucode. Are you using the firmware from
the linux-firmware repository?

> The probe responses are currently send by the ucode based on the
> template and by mac80211. I was searching for a switch so disable probe
> request forwarding from the ucode to the driver.

I am pretty sure there is. I will look into this and let you know.

> 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.

Yeah. Basically, a lot of conversions are done at mac80211 interface to keep
the low-level driver code similar to the code base it came from. That is the
path taken. I would like to see a replacement driver some day that shares more
structure definitions with the linux wireless subsystem, but for now that is just
me daydreaming ;-)

Regards,
Arend

2013-02-24 03:30:41

by W. Trevor King

[permalink] [raw]
Subject: Re: [RFC 12/13] brcmsmac: add support for probe response template

On Sun, Feb 24, 2013 at 02:06:10AM +0100, Hauke Mehrtens wrote:
> 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.

Should this read "so there are more answers sent to"?

--
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy


Attachments:
(No filename) (569.00 B)
signature.asc (836.00 B)
OpenPGP digital signature
Download all attachments

2013-02-24 01:07:11

by Hauke Mehrtens

[permalink] [raw]
Subject: [RFC 10/13] 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 577df22..7a76977 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
@@ -519,9 +520,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 b993ddc..7ed4e8e 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.
*/
@@ -7382,9 +7490,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)
+ 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 */
@@ -7782,6 +7912,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;

@@ -7913,6 +8047,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