Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 39b2d36c authored by Hauke Mehrtens's avatar Hauke Mehrtens Committed by John W. Linville
Browse files

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: default avatarHauke Mehrtens <hauke@hauke-m.de>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 5c1da23b
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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)
+24 −0
Original line number Diff line number Diff line
@@ -739,6 +739,28 @@ static void brcms_ops_flush(struct ieee80211_hw *hw, u32 queues, 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)
+44 −0
Original line number Diff line number Diff line
@@ -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;
+2 −0
Original line number Diff line number Diff line
@@ -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);