Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 369095
b: refs/heads/master
c: af44e25
h: refs/heads/master
i:
  369093: b5e7b18
  369091: afde25a
  369087: 9a10780
v: v3
  • Loading branch information
Hauke Mehrtens authored and John W. Linville committed Mar 27, 2013
1 parent 4c40f00 commit f440484
Show file tree
Hide file tree
Showing 5 changed files with 160 additions and 7 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: ee9794ff49d60bb0f363704c4e03f7eed511ed3b
refs/heads/master: af44e258108058f30d4d4de1f7af0aff88ea3f4b
13 changes: 11 additions & 2 deletions trunk/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2010 Broadcom Corporation
* Copyright (c) 2013 Hauke Mehrtens <hauke@hauke-m.de>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
Expand Down Expand Up @@ -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) */
Expand Down
141 changes: 138 additions & 3 deletions trunk/drivers/net/wireless/brcm80211/brcmsmac/main.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2010 Broadcom Corporation
* Copyright (c) 2013 Hauke Mehrtens <hauke@hauke-m.de>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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.
*/
Expand All @@ -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 */
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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);
Expand Down
7 changes: 6 additions & 1 deletion trunk/drivers/net/wireless/brcm80211/brcmsmac/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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,
Expand Down
4 changes: 4 additions & 0 deletions trunk/drivers/net/wireless/brcm80211/brcmsmac/pub.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_ */

0 comments on commit f440484

Please sign in to comment.