mirror of
https://github.com/outbackdingo/mt76.git
synced 2026-10-24 13:26:48 +00:00
mt7603: add initial code to configure beacon timers
Signed-off-by: Felix Fietkau <[email protected]>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user