mt7603: add initial code to configure beacon timers

Signed-off-by: Felix Fietkau <[email protected]>
This commit is contained in:
Felix Fietkau
2016-02-25 17:23:47 +01:00
parent f6092c88ed
commit e6bc17ac24
7 changed files with 223 additions and 8 deletions
+2 -1
View File
@@ -13,4 +13,5 @@ mt76x2e-y := \
mt7603e-y := \
mt7603_pci.o mt7603_main.o mt7603_init.o mt7603_mcu.o \
mt7603_core.o mt7603_dma.o mt7603_mac.o mt7603_eeprom.o
mt7603_core.o mt7603_dma.o mt7603_mac.o mt7603_eeprom.o \
mt7603_beacon.o
+7
View File
@@ -31,6 +31,8 @@
#define MT_AGG_SIZE_LIMIT(n) ((4 + 2 * (n & 1)) << (n / 2))
#define MT7603_PRE_TBTT_TIME 5000 /* ms */
enum {
MT7603_REV_E1 = 0x00,
MT7603_REV_E2 = 0x10
@@ -114,6 +116,8 @@ struct mt7603_dev {
struct mt7603_mcu mcu;
struct mt76_queue q_rx;
u8 beacon_mask;
struct tasklet_struct tx_tasklet;
struct tasklet_struct pre_tbtt_tasklet;
};
@@ -174,6 +178,7 @@ static inline void mt7603_irq_disable(struct mt7603_dev *dev, u32 mask)
void mt7603_mac_start(struct mt7603_dev *dev);
void mt7603_mac_stop(struct mt7603_dev *dev);
void mt7603_mac_set_timing(struct mt7603_dev *dev);
void mt7603_beacon_set_timer(struct mt7603_dev *dev, int idx, int intval);
int mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb);
void mt7603_mac_add_txs(struct mt7603_dev *dev, void *data);
struct sk_buff *mt7603_mac_status_skb(struct mt7603_dev *dev,
@@ -205,4 +210,6 @@ void mt7603_queue_rx_skb(struct mt76_dev *dev, enum mt76_rxq_id q,
struct sk_buff *skb);
void mt7603_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q);
void mt7603_pre_tbtt_tasklet(unsigned long arg);
#endif
+141
View File
@@ -0,0 +1,141 @@
/*
* Copyright (C) 2016 Felix Fietkau <[email protected]>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "mt7603.h"
struct beacon_bc_data {
struct mt7603_dev *dev;
struct sk_buff_head q;
struct sk_buff *tail[8];
};
static void
mt7603_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
{
struct mt7603_dev *dev = (struct mt7603_dev *) priv;
struct mt7603_vif *mvif = (struct mt7603_vif *) vif->drv_priv;
struct ieee80211_tx_info *info;
struct sk_buff *skb = NULL;
if (!(dev->beacon_mask & BIT(mvif->idx)))
return;
skb = ieee80211_beacon_get(mt76_hw(dev), vif);
if (!skb)
return;
info = IEEE80211_SKB_CB(skb);
info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ;
info->control.vif = vif;
mt76_tx_queue_skb(&dev->mt76, &dev->mt76.q_tx[MT_TXQ_BEACON], skb,
&mvif->sta.wcid, NULL);
}
static void
mt7603_add_buffered_bc(void *priv, u8 *mac, struct ieee80211_vif *vif)
{
struct beacon_bc_data *data = priv;
struct mt7603_dev *dev = data->dev;
struct mt7603_vif *mvif = (struct mt7603_vif *) vif->drv_priv;
struct ieee80211_tx_info *info;
struct sk_buff *skb;
if (!(dev->beacon_mask & BIT(mvif->idx)))
return;
skb = ieee80211_get_buffered_bc(mt76_hw(dev), vif);
if (!skb)
return;
info = IEEE80211_SKB_CB(skb);
info->control.vif = vif;
info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ;
mt76_skb_set_moredata(skb, true);
__skb_queue_tail(&data->q, skb);
data->tail[mvif->idx] = skb;
}
void mt7603_pre_tbtt_tasklet(unsigned long arg)
{
struct mt7603_dev *dev = (struct mt7603_dev *) arg;
struct mt76_queue *q = &dev->mt76.q_tx[MT_TXQ_CAB];
struct beacon_bc_data data = {};
struct sk_buff *skb;
int i, nframes;
data.dev = dev;
__skb_queue_head_init(&data.q);
ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev),
IEEE80211_IFACE_ITER_RESUME_ALL,
mt7603_update_beacon_iter, dev);
do {
nframes = skb_queue_len(&data.q);
ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev),
IEEE80211_IFACE_ITER_RESUME_ALL,
mt7603_add_buffered_bc, &data);
} while (nframes != skb_queue_len(&data.q));
if (!nframes)
return;
for (i = 0; i < ARRAY_SIZE(data.tail); i++) {
if (!data.tail[i])
continue;
mt76_skb_set_moredata(data.tail[i], false);
}
spin_lock_bh(&q->lock);
while ((skb = __skb_dequeue(&data.q)) != NULL) {
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_vif *vif = info->control.vif;
struct mt7603_vif *mvif = (struct mt7603_vif *) vif->drv_priv;
mt76_tx_queue_skb(&dev->mt76, q, skb, &mvif->sta.wcid, NULL);
}
mt76_queue_kick(dev, q);
spin_unlock_bh(&q->lock);
}
void mt7603_beacon_set_timer(struct mt7603_dev *dev, int idx, int intval)
{
u32 pre_tbtt = MT7603_PRE_TBTT_TIME / 64;
if (intval)
dev->beacon_mask |= BIT(idx);
else
dev->beacon_mask &= BIT(idx);
if (!dev->beacon_mask) {
mt7603_irq_disable(dev, MT_INT_PRE_TBTT);
mt76_clear(dev, MT_WF_ARB_SCR, MT_WF_ARB_BCNQ_OPMODE_MASK);
mt76_wr(dev, MT_HW_INT_MASK(3), 0);
return;
}
mt76_wr(dev, MT_TBTT,
MT76_SET(MT_TBTT_PERIOD, intval) | MT_TBTT_CAL_ENABLE);
mt76_wr(dev, MT_TBTT_TIMER_CFG, 0x99); /* start timer */
mt76_rmw_field(dev, MT_WF_ARB_SCR, MT_WF_ARB_BCNQ_OPMODE_MASK,
MT_BCNQ_OPMODE_AP);
mt76_wr(dev, MT_PRE_TBTT, pre_tbtt);
mt76_set(dev, MT_HW_INT_MASK(3), MT_HW_INT3_PRE_TBTT0);
mt76_set(dev, MT_WF_ARB_BCN_START, MT_WF_ARB_BCN_START_BSSn(0));
mt7603_irq_enable(dev, MT_INT_PRE_TBTT);
}
+4 -7
View File
@@ -58,14 +58,11 @@ irqreturn_t mt7603_irq_handler(int irq, void *dev_instance)
napi_schedule(&dev->mt76.napi[1]);
}
#if 0
if (intr & MT_INT_PRE_TBTT)
if (intr & MT_INT_PRE_TBTT) {
u32 hwintr = mt76_rr(dev, MT_HW_INT_STATUS(3));
mt76_wr(dev, MT_HW_INT_STATUS(3), hwintr);
tasklet_schedule(&dev->pre_tbtt_tasklet);
/* send buffered multicast frames now */
if (intr & MT_INT_TBTT)
mt76_queue_kick(dev, &dev->mt76.q_tx[MT_TXQ_PSD]);
#endif
}
return IRQ_HANDLED;
}
+2
View File
@@ -371,6 +371,8 @@ int mt7603_register_device(struct mt7603_dev *dev)
spin_lock_init(&dev->status_lock);
INIT_LIST_HEAD(&dev->status_list);
tasklet_init(&dev->pre_tbtt_tasklet, mt7603_pre_tbtt_tasklet, (unsigned long) dev);
dev->rx_chains = 2;
dev->tx_chains = 2;
dev->slottime = 9;
+7
View File
@@ -223,6 +223,13 @@ mt7603_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
mt7603_mac_set_timing(dev);
}
if (changed & (BSS_CHANGED_BEACON_ENABLED | BSS_CHANGED_BEACON_INT)) {
int beacon_int = !!info->enable_beacon * info->beacon_int;
tasklet_disable(&dev->pre_tbtt_tasklet);
mt7603_beacon_set_timer(dev, mvif->idx, beacon_int);
tasklet_enable(&dev->pre_tbtt_tasklet);
}
mutex_unlock(&dev->mutex);
}
+60
View File
@@ -209,8 +209,20 @@
#define MT_WF_ARB_RQCR_RXV_T_EN BIT(8)
#define MT_WF_ARB_SCR MT_WF_ARB(0x080)
#define MT_WF_ARB_BCNQ_OPMODE_MASK GENMASK(1, 0)
#define MT_WF_ARB_BCNQ_OPMODE_SHIFT(n) (n * 2)
#define MT_WF_ARB_TX_DISABLE BIT(8)
#define MT_WF_ARB_RX_DISABLE BIT(9)
#define MT_WF_ARB_BCNQ_EMPTY_SKIP BIT(28)
#define MT_WF_ARB_TTTT_BTIM_PRIO BIT(29)
#define MT_WF_ARB_TBTT_BCN_PRIO BIT(30)
#define MT_WF_ARB_TBTT_BCAST_PRIO BIT(31)
enum {
MT_BCNQ_OPMODE_STA = 0,
MT_BCNQ_OPMODE_AP = 1,
MT_BCNQ_OPMODE_ADHOC = 2,
};
#define MT_WF_ARB_TX_START_0 MT_WF_ARB(0x100)
#define MT_WF_ARB_TX_START_1 MT_WF_ARB(0x104)
@@ -219,6 +231,32 @@
#define MT_WF_ARB_TX_STOP_0 MT_WF_ARB(0x110)
#define MT_WF_ARB_TX_STOP_1 MT_WF_ARB(0x114)
#define MT_WF_ARB_BCN_START MT_WF_ARB(0x118)
#define MT_WF_ARB_BCN_START_BSSn(n) BIT(0 + (n))
#define MT_WF_ARB_BCN_START_T_PRE_TTTT BIT(10)
#define MT_WF_ARB_BCN_START_T_TTTT BIT(11)
#define MT_WF_ARB_BCN_START_T_PRE_TBTT BIT(12)
#define MT_WF_ARB_BCN_START_T_TBTT BIT(13)
#define MT_WF_ARB_BCN_START_T_SLOT_IDLE BIT(14)
#define MT_WF_ARB_BCN_START_T_TX_START BIT(15)
#define MT_WF_ARB_BCN_START_BSS0n(n) BIT((n) ? 16 + ((n) - 1) : 0)
#define MT_WF_ARB_BCN_FLUSH MT_WF_ARB(0x11c)
#define MT_WF_ARB_BCN_FLUSH_BSSn(n) BIT(0 + (n))
#define MT_WF_ARB_BCN_FLUSH_BSS0n(n) BIT((n) ? 16 + ((n) - 1) : 0)
#define MT_WF_ARB_CAB_START MT_WF_ARB(0x120)
#define MT_WF_ARB_CAB_START_BSSn(n) BIT(0 + (n))
#define MT_WF_ARB_CAB_START_BSS0n(n) BIT((n) ? 16 + ((n) - 1) : 0)
#define MT_WF_ARB_CAB_FLUSH MT_WF_ARB(0x124)
#define MT_WF_ARB_CAB_FLUSH_BSSn(n) BIT(0 + (n))
#define MT_WF_ARB_CAB_FLUSH_BSS0n(n) BIT((n) ? 16 + ((n) - 1) : 0)
#define MT_WF_ARB_CAB_COUNT_0 MT_WF_ARB(0x128)
#define MT_WF_ARB_CAB_COUNT_1 MT_WF_ARB(0x12c)
#define MT_WF_ARB_CAB_COUNT_2 MT_WF_ARB(0x130)
#define MT_WF_TMAC_BASE 0x21600
#define MT_WF_TMAC(ofs) (MT_WF_TMAC_BASE + (ofs))
@@ -349,6 +387,28 @@
#define MT_LPON_BTEIR MT_LPON(0x020)
#define MT_LPON_BTEIR_MBSS_MODE GENMASK(31, 29)
#define MT_PRE_TBTT MT_LPON(0x030)
#define MT_PRE_TBTT_MASK GENMASK(7, 0)
#define MT_PRE_TBTT_SHIFT 8
#define MT_TBTT MT_LPON(0x034)
#define MT_TBTT_PERIOD GENMASK(15, 0)
#define MT_TBTT_DTIM_PERIOD GENMASK(23, 16)
#define MT_TBTT_TBTT_WAKE_PERIOD GENMASK(27, 24)
#define MT_TBTT_DTIM_WAKE_PERIOD GENMASK(30, 28)
#define MT_TBTT_CAL_ENABLE BIT(31)
#define MT_TBTT_TIMER_CFG MT_LPON(0x05c)
#define MT_INT_WAKEUP_BASE 0x24400
#define MT_INT_WAKEUP(n) (MT_INT_WAKEUP_BASE + (n))
#define MT_HW_INT_STATUS(n) MT_INT_WAKEUP(0x3c + (n) * 8)
#define MT_HW_INT_MASK(n) MT_INT_WAKEUP(0x40 + (n) * 8)
#define MT_HW_INT3_TBTT0 BIT(15)
#define MT_HW_INT3_PRE_TBTT0 BIT(31)
#define MT_WTBL1_BASE 0x28000
#define MT_PCIE_REMAP_BASE_1 0x40000