mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-10 15:10:38 +00:00
first batch of mt76 patches for 5.1
* fixes for mt76x0/mt76x2 * energy detect regulatory compliance fixes * tx status handling fixes * preparation for MT7603 support * channel switch announcement support -----BEGIN PGP SIGNATURE----- Version: GnuPG/MacGPG2 v2 Comment: GPGTools - http://gpgtools.org iEYEABECAAYFAlxHOf4ACgkQ130UHQKnbvUnmwCg1qdMIcAUT28xG2my8VxqelEP BpMAn2uqBD+P+QBIgyXDN3GGF0P+UOWu =exYK -----END PGP SIGNATURE----- Merge tag 'mt76-for-kvalo-2019-01-22' of https://github.com/nbd168/wireless first batch of mt76 patches for 5.1 * fixes for mt76x0/mt76x2 * energy detect regulatory compliance fixes * tx status handling fixes * preparation for MT7603 support * channel switch announcement support
This commit is contained in:
commit
1899405c98
@ -300,7 +300,7 @@ int mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
if (q->queued + (n + 1) / 2 >= q->ndesc - 1)
|
||||
goto unmap;
|
||||
|
||||
return dev->queue_ops->add_buf(dev, q, buf, n, tx_info, skb, t);
|
||||
return mt76_dma_add_buf(dev, q, buf, n, tx_info, skb, t);
|
||||
|
||||
unmap:
|
||||
ret = -ENOMEM;
|
||||
@ -318,7 +318,7 @@ free:
|
||||
EXPORT_SYMBOL_GPL(mt76_dma_tx_queue_skb);
|
||||
|
||||
static int
|
||||
mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q, bool napi)
|
||||
mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q)
|
||||
{
|
||||
dma_addr_t addr;
|
||||
void *buf;
|
||||
@ -392,7 +392,7 @@ mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid)
|
||||
|
||||
mt76_dma_rx_cleanup(dev, q);
|
||||
mt76_dma_sync_idx(dev, q);
|
||||
mt76_dma_rx_fill(dev, q, false);
|
||||
mt76_dma_rx_fill(dev, q);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -417,10 +417,9 @@ mt76_add_fragment(struct mt76_dev *dev, struct mt76_queue *q, void *data,
|
||||
static int
|
||||
mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
|
||||
{
|
||||
int len, data_len, done = 0;
|
||||
struct sk_buff *skb;
|
||||
unsigned char *data;
|
||||
int len;
|
||||
int done = 0;
|
||||
bool more;
|
||||
|
||||
while (done < budget) {
|
||||
@ -430,6 +429,19 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
|
||||
if (!data)
|
||||
break;
|
||||
|
||||
if (q->rx_head)
|
||||
data_len = q->buf_size;
|
||||
else
|
||||
data_len = SKB_WITH_OVERHEAD(q->buf_size);
|
||||
|
||||
if (data_len < len + q->buf_offset) {
|
||||
dev_kfree_skb(q->rx_head);
|
||||
q->rx_head = NULL;
|
||||
|
||||
skb_free_frag(data);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (q->rx_head) {
|
||||
mt76_add_fragment(dev, q, data, len, more);
|
||||
continue;
|
||||
@ -440,12 +452,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
|
||||
skb_free_frag(data);
|
||||
continue;
|
||||
}
|
||||
|
||||
skb_reserve(skb, q->buf_offset);
|
||||
if (skb->tail + len > skb->end) {
|
||||
dev_kfree_skb(skb);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (q == &dev->q_rx[MT_RXQ_MCU]) {
|
||||
u32 *rxfce = (u32 *) skb->cb;
|
||||
@ -463,7 +470,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
|
||||
dev->drv->rx_skb(dev, q - dev->q_rx, skb);
|
||||
}
|
||||
|
||||
mt76_dma_rx_fill(dev, q, true);
|
||||
mt76_dma_rx_fill(dev, q);
|
||||
return done;
|
||||
}
|
||||
|
||||
@ -504,7 +511,7 @@ mt76_dma_init(struct mt76_dev *dev)
|
||||
for (i = 0; i < ARRAY_SIZE(dev->q_rx); i++) {
|
||||
netif_napi_add(&dev->napi_dev, &dev->napi[i], mt76_dma_rx_poll,
|
||||
64);
|
||||
mt76_dma_rx_fill(dev, &dev->q_rx[i], false);
|
||||
mt76_dma_rx_fill(dev, &dev->q_rx[i]);
|
||||
skb_queue_head_init(&dev->rx_skb[i]);
|
||||
napi_enable(&dev->napi[i]);
|
||||
}
|
||||
|
@ -328,6 +328,7 @@ int mt76_register_device(struct mt76_dev *dev, bool vht,
|
||||
ieee80211_hw_set(hw, MFP_CAPABLE);
|
||||
ieee80211_hw_set(hw, AP_LINK_PS);
|
||||
ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS);
|
||||
ieee80211_hw_set(hw, NEEDS_UNIQUE_STA_ADDR);
|
||||
|
||||
wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
|
||||
|
||||
@ -547,7 +548,7 @@ mt76_check_ccmp_pn(struct sk_buff *skb)
|
||||
}
|
||||
|
||||
static void
|
||||
mt76_check_ps(struct mt76_dev *dev, struct sk_buff *skb)
|
||||
mt76_check_sta(struct mt76_dev *dev, struct sk_buff *skb)
|
||||
{
|
||||
struct mt76_rx_status *status = (struct mt76_rx_status *) skb->cb;
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
||||
@ -566,6 +567,11 @@ mt76_check_ps(struct mt76_dev *dev, struct sk_buff *skb)
|
||||
|
||||
sta = container_of((void *) wcid, struct ieee80211_sta, drv_priv);
|
||||
|
||||
if (status->signal <= 0)
|
||||
ewma_signal_add(&wcid->rssi, -status->signal);
|
||||
|
||||
wcid->inactive_count = 0;
|
||||
|
||||
if (!test_bit(MT_WCID_FLAG_CHECK_PS, &wcid->flags))
|
||||
return;
|
||||
|
||||
@ -625,7 +631,7 @@ void mt76_rx_poll_complete(struct mt76_dev *dev, enum mt76_rxq_id q,
|
||||
__skb_queue_head_init(&frames);
|
||||
|
||||
while ((skb = __skb_dequeue(&dev->rx_skb[q])) != NULL) {
|
||||
mt76_check_ps(dev, skb);
|
||||
mt76_check_sta(dev, skb);
|
||||
mt76_rx_aggr_reorder(skb, &frames);
|
||||
}
|
||||
|
||||
@ -659,6 +665,7 @@ mt76_sta_add(struct mt76_dev *dev, struct ieee80211_vif *vif,
|
||||
mt76_txq_init(dev, sta->txq[i]);
|
||||
}
|
||||
|
||||
ewma_signal_init(&wcid->rssi);
|
||||
rcu_assign_pointer(dev->wcid[wcid->idx], wcid);
|
||||
|
||||
out:
|
||||
@ -709,3 +716,60 @@ int mt76_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_sta_state);
|
||||
|
||||
int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
int *dbm)
|
||||
{
|
||||
struct mt76_dev *dev = hw->priv;
|
||||
int n_chains = __sw_hweight8(dev->antenna_mask);
|
||||
|
||||
*dbm = dev->txpower_cur / 2;
|
||||
|
||||
/* convert from per-chain power to combined
|
||||
* output on 2x2 devices
|
||||
*/
|
||||
if (n_chains > 1)
|
||||
*dbm += 3;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_get_txpower);
|
||||
|
||||
static void
|
||||
__mt76_csa_finish(void *priv, u8 *mac, struct ieee80211_vif *vif)
|
||||
{
|
||||
if (vif->csa_active && ieee80211_csa_is_complete(vif))
|
||||
ieee80211_csa_finish(vif);
|
||||
}
|
||||
|
||||
void mt76_csa_finish(struct mt76_dev *dev)
|
||||
{
|
||||
if (!dev->csa_complete)
|
||||
return;
|
||||
|
||||
ieee80211_iterate_active_interfaces_atomic(dev->hw,
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
__mt76_csa_finish, dev);
|
||||
|
||||
dev->csa_complete = 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_csa_finish);
|
||||
|
||||
static void
|
||||
__mt76_csa_check(void *priv, u8 *mac, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct mt76_dev *dev = priv;
|
||||
|
||||
if (!vif->csa_active)
|
||||
return;
|
||||
|
||||
dev->csa_complete |= ieee80211_csa_is_complete(vif);
|
||||
}
|
||||
|
||||
void mt76_csa_check(struct mt76_dev *dev)
|
||||
{
|
||||
ieee80211_iterate_active_interfaces_atomic(dev->hw,
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
__mt76_csa_check, dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_csa_check);
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/leds.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/average.h>
|
||||
#include <net/mac80211.h>
|
||||
#include "util.h"
|
||||
|
||||
@ -174,6 +175,8 @@ enum mt76_wcid_flags {
|
||||
|
||||
#define MT76_N_WCIDS 128
|
||||
|
||||
DECLARE_EWMA(signal, 10, 8);
|
||||
|
||||
struct mt76_wcid {
|
||||
struct mt76_rx_tid __rcu *aggr[IEEE80211_NUM_TIDS];
|
||||
|
||||
@ -181,6 +184,9 @@ struct mt76_wcid {
|
||||
|
||||
unsigned long flags;
|
||||
|
||||
struct ewma_signal rssi;
|
||||
int inactive_count;
|
||||
|
||||
u8 idx;
|
||||
u8 hw_key_idx;
|
||||
|
||||
@ -239,7 +245,9 @@ struct mt76_rx_tid {
|
||||
#define MT_TX_CB_TXS_FAILED BIT(2)
|
||||
|
||||
#define MT_PACKET_ID_MASK GENMASK(7, 0)
|
||||
#define MT_PACKET_ID_NO_ACK MT_PACKET_ID_MASK
|
||||
#define MT_PACKET_ID_NO_ACK 0
|
||||
#define MT_PACKET_ID_NO_SKB 1
|
||||
#define MT_PACKET_ID_FIRST 2
|
||||
|
||||
#define MT_TX_STATUS_SKB_TIMEOUT HZ
|
||||
|
||||
@ -421,6 +429,7 @@ struct mt76_dev {
|
||||
struct mt76_queue q_tx[__MT_TXQ_MAX];
|
||||
struct mt76_queue q_rx[__MT_RXQ_MAX];
|
||||
const struct mt76_queue_ops *queue_ops;
|
||||
int tx_dma_idx[4];
|
||||
|
||||
wait_queue_head_t tx_wait;
|
||||
struct sk_buff_head status_list;
|
||||
@ -454,6 +463,8 @@ struct mt76_dev {
|
||||
bool led_al;
|
||||
u8 led_pin;
|
||||
|
||||
u8 csa_complete;
|
||||
|
||||
u32 rxfilter;
|
||||
|
||||
union {
|
||||
@ -488,7 +499,7 @@ struct mt76_rx_status {
|
||||
u8 rate_idx;
|
||||
u8 nss;
|
||||
u8 band;
|
||||
u8 signal;
|
||||
s8 signal;
|
||||
u8 chains;
|
||||
s8 chain_signal[IEEE80211_MAX_CHAINS];
|
||||
};
|
||||
@ -677,6 +688,14 @@ int mt76_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
|
||||
struct ieee80211_sta *mt76_rx_convert(struct sk_buff *skb);
|
||||
|
||||
int mt76_get_min_avg_rssi(struct mt76_dev *dev);
|
||||
|
||||
int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
int *dbm);
|
||||
|
||||
void mt76_csa_check(struct mt76_dev *dev);
|
||||
void mt76_csa_finish(struct mt76_dev *dev);
|
||||
|
||||
/* internal */
|
||||
void mt76_tx_free(struct mt76_dev *dev);
|
||||
struct mt76_txwi_cache *mt76_get_txwi(struct mt76_dev *dev);
|
||||
|
@ -88,6 +88,7 @@ static const struct mt76_reg_pair mt76x0_mac_reg_table[] = {
|
||||
{ MT_TX_PROT_CFG6, 0xe3f42004 },
|
||||
{ MT_TX_PROT_CFG7, 0xe3f42084 },
|
||||
{ MT_TX_PROT_CFG8, 0xe3f42104 },
|
||||
{ MT_VHT_HT_FBK_CFG1, 0xedcba980 },
|
||||
};
|
||||
|
||||
static const struct mt76_reg_pair mt76x0_bbp_init_tab[] = {
|
||||
|
@ -99,7 +99,7 @@ static const struct ieee80211_ops mt76x0e_ops = {
|
||||
.sta_rate_tbl_update = mt76x02_sta_rate_tbl_update,
|
||||
.wake_tx_queue = mt76_wake_tx_queue,
|
||||
.get_survey = mt76_get_survey,
|
||||
.get_txpower = mt76x02_get_txpower,
|
||||
.get_txpower = mt76_get_txpower,
|
||||
.flush = mt76x0e_flush,
|
||||
.set_tim = mt76x0e_set_tim,
|
||||
.release_buffered_frames = mt76_release_buffered_frames,
|
||||
@ -141,6 +141,15 @@ static int mt76x0e_register_device(struct mt76x02_dev *dev)
|
||||
mt76_clear(dev, 0x110, BIT(9));
|
||||
mt76_set(dev, MT_MAX_LEN_CFG, BIT(13));
|
||||
|
||||
mt76_wr(dev, MT_CH_TIME_CFG,
|
||||
MT_CH_TIME_CFG_TIMER_EN |
|
||||
MT_CH_TIME_CFG_TX_AS_BUSY |
|
||||
MT_CH_TIME_CFG_RX_AS_BUSY |
|
||||
MT_CH_TIME_CFG_NAV_AS_BUSY |
|
||||
MT_CH_TIME_CFG_EIFS_AS_BUSY |
|
||||
MT_CH_CCA_RC_EN |
|
||||
FIELD_PREP(MT_CH_TIME_CFG_CH_TIMER_CLR, 1));
|
||||
|
||||
err = mt76x0_register_device(dev);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
@ -1013,6 +1013,8 @@ int mt76x0_phy_set_channel(struct mt76x02_dev *dev,
|
||||
mt76x0_phy_calibrate(dev, false);
|
||||
mt76x0_phy_set_txpower(dev);
|
||||
|
||||
mt76x02_edcca_init(dev);
|
||||
|
||||
ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work,
|
||||
MT_CALIBRATE_INTERVAL);
|
||||
|
||||
@ -1075,7 +1077,9 @@ mt76x0_phy_update_channel_gain(struct mt76x02_dev *dev)
|
||||
u8 gain_delta;
|
||||
int low_gain;
|
||||
|
||||
dev->cal.avg_rssi_all = mt76x02_phy_get_min_avg_rssi(dev);
|
||||
dev->cal.avg_rssi_all = mt76_get_min_avg_rssi(&dev->mt76);
|
||||
if (!dev->cal.avg_rssi_all)
|
||||
dev->cal.avg_rssi_all = -75;
|
||||
|
||||
low_gain = (dev->cal.avg_rssi_all > mt76x02_get_rssi_gain_thresh(dev)) +
|
||||
(dev->cal.avg_rssi_all > mt76x02_get_low_rssi_gain_thresh(dev));
|
||||
|
@ -155,7 +155,7 @@ static const struct ieee80211_ops mt76x0u_ops = {
|
||||
.sta_rate_tbl_update = mt76x02_sta_rate_tbl_update,
|
||||
.set_rts_threshold = mt76x02_set_rts_threshold,
|
||||
.wake_tx_queue = mt76_wake_tx_queue,
|
||||
.get_txpower = mt76x02_get_txpower,
|
||||
.get_txpower = mt76_get_txpower,
|
||||
};
|
||||
|
||||
static int mt76x0u_register_device(struct mt76x02_dev *dev)
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "mt76x0.h"
|
||||
#include "mcu.h"
|
||||
|
@ -15,8 +15,8 @@
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __MT76X02_UTIL_H
|
||||
#define __MT76X02_UTIL_H
|
||||
#ifndef __MT76x02_H
|
||||
#define __MT76x02_H
|
||||
|
||||
#include <linux/kfifo.h>
|
||||
|
||||
@ -28,6 +28,9 @@
|
||||
|
||||
#define MT_CALIBRATE_INTERVAL HZ
|
||||
|
||||
#define MT_WATCHDOG_TIME (HZ / 10)
|
||||
#define MT_TX_HANG_TH 10
|
||||
|
||||
#define MT_MAX_CHAINS 2
|
||||
struct mt76x02_rx_freq_cal {
|
||||
s8 high_gain[MT_MAX_CHAINS];
|
||||
@ -79,6 +82,7 @@ struct mt76x02_dev {
|
||||
struct tasklet_struct pre_tbtt_tasklet;
|
||||
struct delayed_work cal_work;
|
||||
struct delayed_work mac_work;
|
||||
struct delayed_work wdt_work;
|
||||
|
||||
u32 aggr_stats[32];
|
||||
|
||||
@ -89,6 +93,9 @@ struct mt76x02_dev {
|
||||
u8 tbtt_count;
|
||||
u16 beacon_int;
|
||||
|
||||
u32 tx_hang_reset;
|
||||
u8 tx_hang_check;
|
||||
|
||||
struct mt76x02_calibration cal;
|
||||
|
||||
s8 target_power;
|
||||
@ -101,6 +108,12 @@ struct mt76x02_dev {
|
||||
u8 slottime;
|
||||
|
||||
struct mt76x02_dfs_pattern_detector dfs_pd;
|
||||
|
||||
/* edcca monitor */
|
||||
bool ed_tx_blocked;
|
||||
bool ed_monitor;
|
||||
u8 ed_trigger;
|
||||
u8 ed_silent;
|
||||
};
|
||||
|
||||
extern struct ieee80211_rate mt76x02_rates[12];
|
||||
@ -136,6 +149,7 @@ s8 mt76x02_tx_get_max_txpwr_adj(struct mt76x02_dev *dev,
|
||||
const struct ieee80211_tx_rate *rate);
|
||||
s8 mt76x02_tx_get_txpwr_adj(struct mt76x02_dev *dev, s8 txpwr,
|
||||
s8 max_txpwr_adj);
|
||||
void mt76x02_wdt_work(struct work_struct *work);
|
||||
void mt76x02_tx_set_txpwr_auto(struct mt76x02_dev *dev, s8 txpwr);
|
||||
void mt76x02_set_tx_ackto(struct mt76x02_dev *dev);
|
||||
void mt76x02_set_coverage_class(struct ieee80211_hw *hw,
|
||||
@ -158,8 +172,6 @@ void mt76x02_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
const u8 *mac);
|
||||
void mt76x02_sw_scan_complete(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif);
|
||||
int mt76x02_get_txpower(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif, int *dbm);
|
||||
void mt76x02_sta_ps(struct mt76_dev *dev, struct ieee80211_sta *sta, bool ps);
|
||||
void mt76x02_bss_info_changed(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
@ -224,4 +236,4 @@ mt76x02_rx_get_sta_wcid(struct mt76x02_sta *sta, bool unicast)
|
||||
return &sta->vif->group_wcid;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* __MT76x02_H */
|
||||
|
@ -133,5 +133,7 @@ void mt76x02_init_debugfs(struct mt76x02_dev *dev)
|
||||
read_txpower);
|
||||
|
||||
debugfs_create_devm_seqfile(dev->mt76.dev, "agc", dir, read_agc);
|
||||
|
||||
debugfs_create_u32("tx_hang_reset", 0400, dir, &dev->tx_hang_reset);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x02_init_debugfs);
|
||||
|
@ -881,12 +881,18 @@ mt76x02_dfs_set_domain(struct mt76x02_dev *dev,
|
||||
{
|
||||
struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
|
||||
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
if (dfs_pd->region != region) {
|
||||
tasklet_disable(&dfs_pd->dfs_tasklet);
|
||||
|
||||
dev->ed_monitor = region == NL80211_DFS_ETSI;
|
||||
mt76x02_edcca_init(dev);
|
||||
|
||||
dfs_pd->region = region;
|
||||
mt76x02_dfs_init_params(dev);
|
||||
tasklet_enable(&dfs_pd->dfs_tasklet);
|
||||
}
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
}
|
||||
|
||||
void mt76x02_regd_notifier(struct wiphy *wiphy,
|
||||
|
@ -130,10 +130,8 @@ static __le16
|
||||
mt76x02_mac_tx_rate_val(struct mt76x02_dev *dev,
|
||||
const struct ieee80211_tx_rate *rate, u8 *nss_val)
|
||||
{
|
||||
u8 phy, rate_idx, nss, bw = 0;
|
||||
u16 rateval;
|
||||
u8 phy, rate_idx;
|
||||
u8 nss = 1;
|
||||
u8 bw = 0;
|
||||
|
||||
if (rate->flags & IEEE80211_TX_RC_VHT_MCS) {
|
||||
rate_idx = rate->idx;
|
||||
@ -164,7 +162,7 @@ mt76x02_mac_tx_rate_val(struct mt76x02_dev *dev,
|
||||
|
||||
phy = val >> 8;
|
||||
rate_idx = val & 0xff;
|
||||
bw = 0;
|
||||
nss = 1;
|
||||
}
|
||||
|
||||
rateval = FIELD_PREP(MT_RXWI_RATE_INDEX, rate_idx);
|
||||
@ -435,7 +433,7 @@ void mt76x02_send_tx_status(struct mt76x02_dev *dev,
|
||||
}
|
||||
|
||||
if (wcid) {
|
||||
if (stat->pktid)
|
||||
if (stat->pktid >= MT_PACKET_ID_FIRST)
|
||||
status.skb = mt76_tx_status_skb_get(mdev, wcid,
|
||||
stat->pktid, &list);
|
||||
if (status.skb)
|
||||
@ -478,7 +476,9 @@ out:
|
||||
}
|
||||
|
||||
static int
|
||||
mt76x02_mac_process_rate(struct mt76_rx_status *status, u16 rate)
|
||||
mt76x02_mac_process_rate(struct mt76x02_dev *dev,
|
||||
struct mt76_rx_status *status,
|
||||
u16 rate)
|
||||
{
|
||||
u8 idx = FIELD_GET(MT_RXWI_RATE_INDEX, rate);
|
||||
|
||||
@ -510,11 +510,15 @@ mt76x02_mac_process_rate(struct mt76_rx_status *status, u16 rate)
|
||||
status->encoding = RX_ENC_HT;
|
||||
status->rate_idx = idx;
|
||||
break;
|
||||
case MT_PHY_TYPE_VHT:
|
||||
case MT_PHY_TYPE_VHT: {
|
||||
u8 n_rxstream = dev->mt76.chainmask & 0xf;
|
||||
|
||||
status->encoding = RX_ENC_VHT;
|
||||
status->rate_idx = FIELD_GET(MT_RATE_INDEX_VHT_IDX, idx);
|
||||
status->nss = FIELD_GET(MT_RATE_INDEX_VHT_NSS, idx) + 1;
|
||||
status->nss = min_t(u8, n_rxstream,
|
||||
FIELD_GET(MT_RATE_INDEX_VHT_NSS, idx) + 1);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -644,7 +648,7 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb,
|
||||
|
||||
status->chains = BIT(0);
|
||||
signal = mt76x02_mac_get_rssi(dev, rxwi->rssi[0], 0);
|
||||
for (i = 1; i < nstreams; i++) {
|
||||
for (i = 0; i < nstreams; i++) {
|
||||
status->chains |= BIT(i);
|
||||
status->chain_signal[i] = mt76x02_mac_get_rssi(dev,
|
||||
rxwi->rssi[i],
|
||||
@ -658,12 +662,7 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb,
|
||||
status->tid = FIELD_GET(MT_RXWI_TID, tid_sn);
|
||||
status->seqno = FIELD_GET(MT_RXWI_SN, tid_sn);
|
||||
|
||||
if (sta) {
|
||||
ewma_signal_add(&sta->rssi, status->signal);
|
||||
sta->inactive_count = 0;
|
||||
}
|
||||
|
||||
return mt76x02_mac_process_rate(status, rate);
|
||||
return mt76x02_mac_process_rate(dev, status, rate);
|
||||
}
|
||||
|
||||
void mt76x02_mac_poll_tx_status(struct mt76x02_dev *dev, bool irq)
|
||||
@ -715,7 +714,7 @@ void mt76x02_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue *q,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x02_tx_complete_skb);
|
||||
|
||||
void mt76x02_mac_set_tx_protection(struct mt76x02_dev *dev, u32 val)
|
||||
void mt76x02_mac_set_rts_thresh(struct mt76x02_dev *dev, u32 val)
|
||||
{
|
||||
u32 data = 0;
|
||||
|
||||
@ -729,20 +728,89 @@ void mt76x02_mac_set_tx_protection(struct mt76x02_dev *dev, u32 val)
|
||||
MT_PROT_CFG_CTRL | MT_PROT_CFG_RTS_THRESH, data);
|
||||
mt76_rmw(dev, MT_OFDM_PROT_CFG,
|
||||
MT_PROT_CFG_CTRL | MT_PROT_CFG_RTS_THRESH, data);
|
||||
mt76_rmw(dev, MT_MM20_PROT_CFG,
|
||||
MT_PROT_CFG_CTRL | MT_PROT_CFG_RTS_THRESH, data);
|
||||
mt76_rmw(dev, MT_MM40_PROT_CFG,
|
||||
MT_PROT_CFG_CTRL | MT_PROT_CFG_RTS_THRESH, data);
|
||||
mt76_rmw(dev, MT_GF20_PROT_CFG,
|
||||
MT_PROT_CFG_CTRL | MT_PROT_CFG_RTS_THRESH, data);
|
||||
mt76_rmw(dev, MT_GF40_PROT_CFG,
|
||||
MT_PROT_CFG_CTRL | MT_PROT_CFG_RTS_THRESH, data);
|
||||
mt76_rmw(dev, MT_TX_PROT_CFG6,
|
||||
MT_PROT_CFG_CTRL | MT_PROT_CFG_RTS_THRESH, data);
|
||||
mt76_rmw(dev, MT_TX_PROT_CFG7,
|
||||
MT_PROT_CFG_CTRL | MT_PROT_CFG_RTS_THRESH, data);
|
||||
mt76_rmw(dev, MT_TX_PROT_CFG8,
|
||||
MT_PROT_CFG_CTRL | MT_PROT_CFG_RTS_THRESH, data);
|
||||
}
|
||||
|
||||
void mt76x02_mac_set_tx_protection(struct mt76x02_dev *dev, bool legacy_prot,
|
||||
int ht_mode)
|
||||
{
|
||||
int mode = ht_mode & IEEE80211_HT_OP_MODE_PROTECTION;
|
||||
bool non_gf = !!(ht_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
|
||||
u32 prot[6];
|
||||
u32 vht_prot[3];
|
||||
int i;
|
||||
u16 rts_thr;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(prot); i++) {
|
||||
prot[i] = mt76_rr(dev, MT_CCK_PROT_CFG + i * 4);
|
||||
prot[i] &= ~MT_PROT_CFG_CTRL;
|
||||
if (i >= 2)
|
||||
prot[i] &= ~MT_PROT_CFG_RATE;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(vht_prot); i++) {
|
||||
vht_prot[i] = mt76_rr(dev, MT_TX_PROT_CFG6 + i * 4);
|
||||
vht_prot[i] &= ~(MT_PROT_CFG_CTRL | MT_PROT_CFG_RATE);
|
||||
}
|
||||
|
||||
rts_thr = mt76_get_field(dev, MT_TX_RTS_CFG, MT_TX_RTS_CFG_THRESH);
|
||||
|
||||
if (rts_thr != 0xffff)
|
||||
prot[0] |= MT_PROT_CTRL_RTS_CTS;
|
||||
|
||||
if (legacy_prot) {
|
||||
prot[1] |= MT_PROT_CTRL_CTS2SELF;
|
||||
|
||||
prot[2] |= MT_PROT_RATE_CCK_11;
|
||||
prot[3] |= MT_PROT_RATE_CCK_11;
|
||||
prot[4] |= MT_PROT_RATE_CCK_11;
|
||||
prot[5] |= MT_PROT_RATE_CCK_11;
|
||||
|
||||
vht_prot[0] |= MT_PROT_RATE_CCK_11;
|
||||
vht_prot[1] |= MT_PROT_RATE_CCK_11;
|
||||
vht_prot[2] |= MT_PROT_RATE_CCK_11;
|
||||
} else {
|
||||
if (rts_thr != 0xffff)
|
||||
prot[1] |= MT_PROT_CTRL_RTS_CTS;
|
||||
|
||||
prot[2] |= MT_PROT_RATE_OFDM_24;
|
||||
prot[3] |= MT_PROT_RATE_DUP_OFDM_24;
|
||||
prot[4] |= MT_PROT_RATE_OFDM_24;
|
||||
prot[5] |= MT_PROT_RATE_DUP_OFDM_24;
|
||||
|
||||
vht_prot[0] |= MT_PROT_RATE_OFDM_24;
|
||||
vht_prot[1] |= MT_PROT_RATE_DUP_OFDM_24;
|
||||
vht_prot[2] |= MT_PROT_RATE_SGI_OFDM_24;
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER:
|
||||
case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED:
|
||||
prot[2] |= MT_PROT_CTRL_RTS_CTS;
|
||||
prot[3] |= MT_PROT_CTRL_RTS_CTS;
|
||||
prot[4] |= MT_PROT_CTRL_RTS_CTS;
|
||||
prot[5] |= MT_PROT_CTRL_RTS_CTS;
|
||||
vht_prot[0] |= MT_PROT_CTRL_RTS_CTS;
|
||||
vht_prot[1] |= MT_PROT_CTRL_RTS_CTS;
|
||||
vht_prot[2] |= MT_PROT_CTRL_RTS_CTS;
|
||||
break;
|
||||
case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ:
|
||||
prot[3] |= MT_PROT_CTRL_RTS_CTS;
|
||||
prot[5] |= MT_PROT_CTRL_RTS_CTS;
|
||||
vht_prot[1] |= MT_PROT_CTRL_RTS_CTS;
|
||||
vht_prot[2] |= MT_PROT_CTRL_RTS_CTS;
|
||||
break;
|
||||
}
|
||||
|
||||
if (non_gf) {
|
||||
prot[4] |= MT_PROT_CTRL_RTS_CTS;
|
||||
prot[5] |= MT_PROT_CTRL_RTS_CTS;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(prot); i++)
|
||||
mt76_wr(dev, MT_CCK_PROT_CFG + i * 4, prot[i]);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(vht_prot); i++)
|
||||
mt76_wr(dev, MT_TX_PROT_CFG6 + i * 4, vht_prot[i]);
|
||||
}
|
||||
|
||||
void mt76x02_update_channel(struct mt76_dev *mdev)
|
||||
@ -774,8 +842,90 @@ static void mt76x02_check_mac_err(struct mt76x02_dev *dev)
|
||||
|
||||
mt76_set(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_RESET_CSR);
|
||||
udelay(10);
|
||||
mt76_clear(dev, MT_MAC_SYS_CTRL,
|
||||
MT_MAC_SYS_CTRL_ENABLE_TX | MT_MAC_SYS_CTRL_ENABLE_RX);
|
||||
mt76_wr(dev, MT_MAC_SYS_CTRL,
|
||||
MT_MAC_SYS_CTRL_ENABLE_TX | MT_MAC_SYS_CTRL_ENABLE_RX);
|
||||
}
|
||||
|
||||
static void
|
||||
mt76x02_edcca_tx_enable(struct mt76x02_dev *dev, bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
u32 data;
|
||||
|
||||
mt76_set(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_TX);
|
||||
mt76_set(dev, MT_AUTO_RSP_CFG, MT_AUTO_RSP_EN);
|
||||
/* enable pa-lna */
|
||||
data = mt76_rr(dev, MT_TX_PIN_CFG);
|
||||
data |= MT_TX_PIN_CFG_TXANT |
|
||||
MT_TX_PIN_CFG_RXANT |
|
||||
MT_TX_PIN_RFTR_EN |
|
||||
MT_TX_PIN_TRSW_EN;
|
||||
mt76_wr(dev, MT_TX_PIN_CFG, data);
|
||||
} else {
|
||||
mt76_clear(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_TX);
|
||||
mt76_clear(dev, MT_AUTO_RSP_CFG, MT_AUTO_RSP_EN);
|
||||
/* disable pa-lna */
|
||||
mt76_clear(dev, MT_TX_PIN_CFG, MT_TX_PIN_CFG_TXANT);
|
||||
mt76_clear(dev, MT_TX_PIN_CFG, MT_TX_PIN_CFG_RXANT);
|
||||
}
|
||||
dev->ed_tx_blocked = !enable;
|
||||
}
|
||||
|
||||
void mt76x02_edcca_init(struct mt76x02_dev *dev)
|
||||
{
|
||||
dev->ed_trigger = 0;
|
||||
dev->ed_silent = 0;
|
||||
|
||||
if (dev->ed_monitor) {
|
||||
struct ieee80211_channel *chan = dev->mt76.chandef.chan;
|
||||
u8 ed_th = chan->band == NL80211_BAND_5GHZ ? 0x0e : 0x20;
|
||||
|
||||
mt76_clear(dev, MT_TX_LINK_CFG, MT_TX_CFACK_EN);
|
||||
mt76_set(dev, MT_TXOP_CTRL_CFG, MT_TXOP_ED_CCA_EN);
|
||||
mt76_rmw(dev, MT_BBP(AGC, 2), GENMASK(15, 0),
|
||||
ed_th << 8 | ed_th);
|
||||
if (!is_mt76x2(dev))
|
||||
mt76_set(dev, MT_TXOP_HLDR_ET,
|
||||
MT_TXOP_HLDR_TX40M_BLK_EN);
|
||||
} else {
|
||||
mt76_set(dev, MT_TX_LINK_CFG, MT_TX_CFACK_EN);
|
||||
mt76_clear(dev, MT_TXOP_CTRL_CFG, MT_TXOP_ED_CCA_EN);
|
||||
if (is_mt76x2(dev)) {
|
||||
mt76_wr(dev, MT_BBP(AGC, 2), 0x00007070);
|
||||
} else {
|
||||
mt76_wr(dev, MT_BBP(AGC, 2), 0x003a6464);
|
||||
mt76_clear(dev, MT_TXOP_HLDR_ET,
|
||||
MT_TXOP_HLDR_TX40M_BLK_EN);
|
||||
}
|
||||
}
|
||||
mt76x02_edcca_tx_enable(dev, true);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x02_edcca_init);
|
||||
|
||||
#define MT_EDCCA_TH 90
|
||||
#define MT_EDCCA_BLOCK_TH 2
|
||||
static void mt76x02_edcca_check(struct mt76x02_dev *dev)
|
||||
{
|
||||
u32 val, busy;
|
||||
|
||||
val = mt76_rr(dev, MT_ED_CCA_TIMER);
|
||||
busy = (val * 100) / jiffies_to_usecs(MT_CALIBRATE_INTERVAL);
|
||||
busy = min_t(u32, busy, 100);
|
||||
|
||||
if (busy > MT_EDCCA_TH) {
|
||||
dev->ed_trigger++;
|
||||
dev->ed_silent = 0;
|
||||
} else {
|
||||
dev->ed_silent++;
|
||||
dev->ed_trigger = 0;
|
||||
}
|
||||
|
||||
if (dev->ed_trigger > MT_EDCCA_BLOCK_TH &&
|
||||
!dev->ed_tx_blocked)
|
||||
mt76x02_edcca_tx_enable(dev, false);
|
||||
else if (dev->ed_silent > MT_EDCCA_BLOCK_TH &&
|
||||
dev->ed_tx_blocked)
|
||||
mt76x02_edcca_tx_enable(dev, true);
|
||||
}
|
||||
|
||||
void mt76x02_mac_work(struct work_struct *work)
|
||||
@ -784,6 +934,8 @@ void mt76x02_mac_work(struct work_struct *work)
|
||||
mac_work.work);
|
||||
int i, idx;
|
||||
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
|
||||
mt76x02_update_channel(&dev->mt76);
|
||||
for (i = 0, idx = 0; i < 16; i++) {
|
||||
u32 val = mt76_rr(dev, MT_TX_AGG_CNT(i));
|
||||
@ -792,10 +944,14 @@ void mt76x02_mac_work(struct work_struct *work)
|
||||
dev->aggr_stats[idx++] += val >> 16;
|
||||
}
|
||||
|
||||
/* XXX: check beacon stuck for ap mode */
|
||||
if (!dev->beacon_mask)
|
||||
mt76x02_check_mac_err(dev);
|
||||
|
||||
if (dev->ed_monitor)
|
||||
mt76x02_edcca_check(dev);
|
||||
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
|
||||
mt76_tx_status_check(&dev->mt76, NULL, false);
|
||||
|
||||
ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work,
|
||||
|
@ -18,8 +18,6 @@
|
||||
#ifndef __MT76X02_MAC_H
|
||||
#define __MT76X02_MAC_H
|
||||
|
||||
#include <linux/average.h>
|
||||
|
||||
struct mt76x02_dev;
|
||||
|
||||
struct mt76x02_tx_status {
|
||||
@ -41,8 +39,6 @@ struct mt76x02_vif {
|
||||
u8 idx;
|
||||
};
|
||||
|
||||
DECLARE_EWMA(signal, 10, 8);
|
||||
|
||||
struct mt76x02_sta {
|
||||
struct mt76_wcid wcid; /* must be first */
|
||||
|
||||
@ -50,8 +46,6 @@ struct mt76x02_sta {
|
||||
struct mt76x02_tx_status status;
|
||||
int n_frames;
|
||||
|
||||
struct ewma_signal rssi;
|
||||
int inactive_count;
|
||||
};
|
||||
|
||||
#define MT_RXINFO_BA BIT(0)
|
||||
@ -194,7 +188,9 @@ void mt76x02_send_tx_status(struct mt76x02_dev *dev,
|
||||
struct mt76x02_tx_status *stat, u8 *update);
|
||||
int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb,
|
||||
void *rxi);
|
||||
void mt76x02_mac_set_tx_protection(struct mt76x02_dev *dev, u32 val);
|
||||
void mt76x02_mac_set_tx_protection(struct mt76x02_dev *dev, bool legacy_prot,
|
||||
int ht_mode);
|
||||
void mt76x02_mac_set_rts_thresh(struct mt76x02_dev *dev, u32 val);
|
||||
void mt76x02_mac_setaddr(struct mt76x02_dev *dev, u8 *addr);
|
||||
void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi,
|
||||
struct sk_buff *skb, struct mt76_wcid *wcid,
|
||||
@ -210,4 +206,6 @@ int mt76x02_mac_set_beacon(struct mt76x02_dev *dev, u8 vif_idx,
|
||||
struct sk_buff *skb);
|
||||
void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev, u8 vif_idx,
|
||||
bool val);
|
||||
|
||||
void mt76x02_edcca_init(struct mt76x02_dev *dev);
|
||||
#endif
|
||||
|
@ -116,14 +116,20 @@ static void mt76x02_pre_tbtt_tasklet(unsigned long arg)
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
mt76x02_update_beacon_iter, dev);
|
||||
|
||||
mt76_csa_check(&dev->mt76);
|
||||
|
||||
if (dev->mt76.csa_complete)
|
||||
return;
|
||||
|
||||
do {
|
||||
nframes = skb_queue_len(&data.q);
|
||||
ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev),
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
mt76x02_add_buffered_bc, &data);
|
||||
} while (nframes != skb_queue_len(&data.q));
|
||||
} while (nframes != skb_queue_len(&data.q) &&
|
||||
skb_queue_len(&data.q) < 8);
|
||||
|
||||
if (!nframes)
|
||||
if (!skb_queue_len(&data.q))
|
||||
return;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(data.tail); i++) {
|
||||
@ -308,8 +314,12 @@ irqreturn_t mt76x02_irq_handler(int irq, void *dev_instance)
|
||||
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]);
|
||||
if (intr & MT_INT_TBTT) {
|
||||
if (dev->mt76.csa_complete)
|
||||
mt76_csa_finish(&dev->mt76);
|
||||
else
|
||||
mt76_queue_kick(dev, &dev->mt76.q_tx[MT_TXQ_PSD]);
|
||||
}
|
||||
|
||||
if (intr & MT_INT_TX_STAT) {
|
||||
mt76x02_mac_poll_tx_status(dev, true);
|
||||
@ -384,3 +394,127 @@ void mt76x02_mac_start(struct mt76x02_dev *dev)
|
||||
MT_INT_TX_STAT);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x02_mac_start);
|
||||
|
||||
static bool mt76x02_tx_hang(struct mt76x02_dev *dev)
|
||||
{
|
||||
u32 dma_idx, prev_dma_idx;
|
||||
struct mt76_queue *q;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
q = &dev->mt76.q_tx[i];
|
||||
|
||||
if (!q->queued)
|
||||
continue;
|
||||
|
||||
prev_dma_idx = dev->mt76.tx_dma_idx[i];
|
||||
dma_idx = ioread32(&q->regs->dma_idx);
|
||||
dev->mt76.tx_dma_idx[i] = dma_idx;
|
||||
|
||||
if (prev_dma_idx == dma_idx)
|
||||
break;
|
||||
}
|
||||
|
||||
return i < 4;
|
||||
}
|
||||
|
||||
static void mt76x02_watchdog_reset(struct mt76x02_dev *dev)
|
||||
{
|
||||
u32 mask = dev->mt76.mmio.irqmask;
|
||||
int i;
|
||||
|
||||
ieee80211_stop_queues(dev->mt76.hw);
|
||||
set_bit(MT76_RESET, &dev->mt76.state);
|
||||
|
||||
tasklet_disable(&dev->pre_tbtt_tasklet);
|
||||
tasklet_disable(&dev->tx_tasklet);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dev->mt76.napi); i++)
|
||||
napi_disable(&dev->mt76.napi[i]);
|
||||
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
|
||||
if (dev->beacon_mask)
|
||||
mt76_clear(dev, MT_BEACON_TIME_CFG,
|
||||
MT_BEACON_TIME_CFG_BEACON_TX |
|
||||
MT_BEACON_TIME_CFG_TBTT_EN);
|
||||
|
||||
mt76x02_irq_disable(dev, mask);
|
||||
|
||||
/* perform device reset */
|
||||
mt76_clear(dev, MT_TXOP_CTRL_CFG, MT_TXOP_ED_CCA_EN);
|
||||
mt76_wr(dev, MT_MAC_SYS_CTRL, 0);
|
||||
mt76_clear(dev, MT_WPDMA_GLO_CFG,
|
||||
MT_WPDMA_GLO_CFG_TX_DMA_EN | MT_WPDMA_GLO_CFG_RX_DMA_EN);
|
||||
usleep_range(5000, 10000);
|
||||
mt76_wr(dev, MT_INT_SOURCE_CSR, 0xffffffff);
|
||||
|
||||
/* let fw reset DMA */
|
||||
mt76_set(dev, 0x734, 0x3);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dev->mt76.q_tx); i++)
|
||||
mt76_queue_tx_cleanup(dev, i, true);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dev->mt76.q_rx); i++)
|
||||
mt76_queue_rx_reset(dev, i);
|
||||
|
||||
mt76_wr(dev, MT_MAC_SYS_CTRL,
|
||||
MT_MAC_SYS_CTRL_ENABLE_TX | MT_MAC_SYS_CTRL_ENABLE_RX);
|
||||
mt76_set(dev, MT_WPDMA_GLO_CFG,
|
||||
MT_WPDMA_GLO_CFG_TX_DMA_EN | MT_WPDMA_GLO_CFG_RX_DMA_EN);
|
||||
if (dev->ed_monitor)
|
||||
mt76_set(dev, MT_TXOP_CTRL_CFG, MT_TXOP_ED_CCA_EN);
|
||||
|
||||
if (dev->beacon_mask)
|
||||
mt76_set(dev, MT_BEACON_TIME_CFG,
|
||||
MT_BEACON_TIME_CFG_BEACON_TX |
|
||||
MT_BEACON_TIME_CFG_TBTT_EN);
|
||||
|
||||
mt76x02_irq_enable(dev, mask);
|
||||
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
|
||||
clear_bit(MT76_RESET, &dev->mt76.state);
|
||||
|
||||
tasklet_enable(&dev->tx_tasklet);
|
||||
tasklet_schedule(&dev->tx_tasklet);
|
||||
|
||||
tasklet_enable(&dev->pre_tbtt_tasklet);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dev->mt76.napi); i++) {
|
||||
napi_enable(&dev->mt76.napi[i]);
|
||||
napi_schedule(&dev->mt76.napi[i]);
|
||||
}
|
||||
|
||||
ieee80211_wake_queues(dev->mt76.hw);
|
||||
|
||||
mt76_txq_schedule_all(&dev->mt76);
|
||||
}
|
||||
|
||||
static void mt76x02_check_tx_hang(struct mt76x02_dev *dev)
|
||||
{
|
||||
if (mt76x02_tx_hang(dev)) {
|
||||
if (++dev->tx_hang_check < MT_TX_HANG_TH)
|
||||
return;
|
||||
|
||||
mt76x02_watchdog_reset(dev);
|
||||
|
||||
dev->tx_hang_reset++;
|
||||
dev->tx_hang_check = 0;
|
||||
memset(dev->mt76.tx_dma_idx, 0xff,
|
||||
sizeof(dev->mt76.tx_dma_idx));
|
||||
} else {
|
||||
dev->tx_hang_check = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void mt76x02_wdt_work(struct work_struct *work)
|
||||
{
|
||||
struct mt76x02_dev *dev = container_of(work, struct mt76x02_dev,
|
||||
wdt_work.work);
|
||||
|
||||
mt76x02_check_tx_hang(dev);
|
||||
|
||||
ieee80211_queue_delayed_work(mt76_hw(dev), &dev->wdt_work,
|
||||
MT_WATCHDOG_TIME);
|
||||
}
|
||||
|
@ -132,53 +132,6 @@ void mt76x02_phy_set_txpower(struct mt76x02_dev *dev, int txp_0, int txp_1)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x02_phy_set_txpower);
|
||||
|
||||
int mt76x02_phy_get_min_avg_rssi(struct mt76x02_dev *dev)
|
||||
{
|
||||
struct mt76x02_sta *sta;
|
||||
struct mt76_wcid *wcid;
|
||||
int i, j, min_rssi = 0;
|
||||
s8 cur_rssi;
|
||||
|
||||
local_bh_disable();
|
||||
rcu_read_lock();
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dev->mt76.wcid_mask); i++) {
|
||||
unsigned long mask = dev->mt76.wcid_mask[i];
|
||||
|
||||
if (!mask)
|
||||
continue;
|
||||
|
||||
for (j = i * BITS_PER_LONG; mask; j++, mask >>= 1) {
|
||||
if (!(mask & 1))
|
||||
continue;
|
||||
|
||||
wcid = rcu_dereference(dev->mt76.wcid[j]);
|
||||
if (!wcid)
|
||||
continue;
|
||||
|
||||
sta = container_of(wcid, struct mt76x02_sta, wcid);
|
||||
spin_lock(&dev->mt76.rx_lock);
|
||||
if (sta->inactive_count++ < 5)
|
||||
cur_rssi = ewma_signal_read(&sta->rssi);
|
||||
else
|
||||
cur_rssi = 0;
|
||||
spin_unlock(&dev->mt76.rx_lock);
|
||||
|
||||
if (cur_rssi < min_rssi)
|
||||
min_rssi = cur_rssi;
|
||||
}
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
local_bh_enable();
|
||||
|
||||
if (!min_rssi)
|
||||
return -75;
|
||||
|
||||
return min_rssi;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x02_phy_get_min_avg_rssi);
|
||||
|
||||
void mt76x02_phy_set_bw(struct mt76x02_dev *dev, int width, u8 ctrl)
|
||||
{
|
||||
int core_val, agc_val;
|
||||
|
@ -51,7 +51,6 @@ void mt76x02_limit_rate_power(struct mt76_rate_power *r, int limit);
|
||||
int mt76x02_get_max_rate_power(struct mt76_rate_power *r);
|
||||
void mt76x02_phy_set_rxpath(struct mt76x02_dev *dev);
|
||||
void mt76x02_phy_set_txdac(struct mt76x02_dev *dev);
|
||||
int mt76x02_phy_get_min_avg_rssi(struct mt76x02_dev *dev);
|
||||
void mt76x02_phy_set_bw(struct mt76x02_dev *dev, int width, u8 ctrl);
|
||||
void mt76x02_phy_set_band(struct mt76x02_dev *dev, int band,
|
||||
bool primary_upper);
|
||||
|
@ -230,6 +230,29 @@
|
||||
#define MT_COM_REG2 0x0738
|
||||
#define MT_COM_REG3 0x073C
|
||||
|
||||
#define MT_LED_CTRL 0x0770
|
||||
#define MT_LED_CTRL_REPLAY(_n) BIT(0 + (8 * (_n)))
|
||||
#define MT_LED_CTRL_POLARITY(_n) BIT(1 + (8 * (_n)))
|
||||
#define MT_LED_CTRL_TX_BLINK_MODE(_n) BIT(2 + (8 * (_n)))
|
||||
#define MT_LED_CTRL_KICK(_n) BIT(7 + (8 * (_n)))
|
||||
|
||||
#define MT_LED_TX_BLINK_0 0x0774
|
||||
#define MT_LED_TX_BLINK_1 0x0778
|
||||
|
||||
#define MT_LED_S0_BASE 0x077C
|
||||
#define MT_LED_S0(_n) (MT_LED_S0_BASE + 8 * (_n))
|
||||
#define MT_LED_S1_BASE 0x0780
|
||||
#define MT_LED_S1(_n) (MT_LED_S1_BASE + 8 * (_n))
|
||||
#define MT_LED_STATUS_OFF_MASK GENMASK(31, 24)
|
||||
#define MT_LED_STATUS_OFF(_v) (((_v) << __ffs(MT_LED_STATUS_OFF_MASK)) & \
|
||||
MT_LED_STATUS_OFF_MASK)
|
||||
#define MT_LED_STATUS_ON_MASK GENMASK(23, 16)
|
||||
#define MT_LED_STATUS_ON(_v) (((_v) << __ffs(MT_LED_STATUS_ON_MASK)) & \
|
||||
MT_LED_STATUS_ON_MASK)
|
||||
#define MT_LED_STATUS_DURATION_MASK GENMASK(15, 8)
|
||||
#define MT_LED_STATUS_DURATION(_v) (((_v) << __ffs(MT_LED_STATUS_DURATION_MASK)) & \
|
||||
MT_LED_STATUS_DURATION_MASK)
|
||||
|
||||
#define MT_FCE_PSE_CTRL 0x0800
|
||||
#define MT_FCE_PARAMETERS 0x0804
|
||||
#define MT_FCE_CSO 0x0808
|
||||
@ -318,6 +341,7 @@
|
||||
#define MT_CH_TIME_CFG_NAV_AS_BUSY BIT(3)
|
||||
#define MT_CH_TIME_CFG_EIFS_AS_BUSY BIT(4)
|
||||
#define MT_CH_TIME_CFG_MDRDY_CNT_EN BIT(5)
|
||||
#define MT_CH_CCA_RC_EN BIT(6)
|
||||
#define MT_CH_TIME_CFG_CH_TIMER_CLR GENMASK(9, 8)
|
||||
#define MT_CH_TIME_CFG_MDRDY_CLR GENMASK(11, 10)
|
||||
|
||||
@ -378,6 +402,9 @@
|
||||
#define MT_TX_PWR_CFG_4 0x1324
|
||||
#define MT_TX_PIN_CFG 0x1328
|
||||
#define MT_TX_PIN_CFG_TXANT GENMASK(3, 0)
|
||||
#define MT_TX_PIN_CFG_RXANT GENMASK(11, 8)
|
||||
#define MT_TX_PIN_RFTR_EN BIT(16)
|
||||
#define MT_TX_PIN_TRSW_EN BIT(18)
|
||||
|
||||
#define MT_TX_BAND_CFG 0x132c
|
||||
#define MT_TX_BAND_CFG_UPPER_40M BIT(0)
|
||||
@ -398,6 +425,7 @@
|
||||
#define MT_TXOP_CTRL_CFG 0x1340
|
||||
#define MT_TXOP_TRUN_EN GENMASK(5, 0)
|
||||
#define MT_TXOP_EXT_CCA_DLY GENMASK(15, 8)
|
||||
#define MT_TXOP_ED_CCA_EN BIT(20)
|
||||
|
||||
#define MT_TX_RTS_CFG 0x1344
|
||||
#define MT_TX_RTS_CFG_RETRY_LIMIT GENMASK(7, 0)
|
||||
@ -409,6 +437,7 @@
|
||||
|
||||
#define MT_TX_RETRY_CFG 0x134c
|
||||
#define MT_TX_LINK_CFG 0x1350
|
||||
#define MT_TX_CFACK_EN BIT(12)
|
||||
#define MT_VHT_HT_FBK_CFG0 0x1354
|
||||
#define MT_VHT_HT_FBK_CFG1 0x1358
|
||||
#define MT_LG_FBK_CFG0 0x135c
|
||||
@ -440,9 +469,10 @@
|
||||
#define MT_PROT_TXOP_ALLOW_GF40 BIT(25)
|
||||
#define MT_PROT_RTS_THR_EN BIT(26)
|
||||
#define MT_PROT_RATE_CCK_11 0x0003
|
||||
#define MT_PROT_RATE_OFDM_6 0x4000
|
||||
#define MT_PROT_RATE_OFDM_24 0x4004
|
||||
#define MT_PROT_RATE_DUP_OFDM_24 0x4084
|
||||
#define MT_PROT_RATE_OFDM_6 0x2000
|
||||
#define MT_PROT_RATE_OFDM_24 0x2004
|
||||
#define MT_PROT_RATE_DUP_OFDM_24 0x2084
|
||||
#define MT_PROT_RATE_SGI_OFDM_24 0x2104
|
||||
#define MT_PROT_TXOP_ALLOW_ALL GENMASK(25, 20)
|
||||
#define MT_PROT_TXOP_ALLOW_BW20 (MT_PROT_TXOP_ALLOW_ALL & \
|
||||
~MT_PROT_TXOP_ALLOW_MM40 & \
|
||||
@ -511,6 +541,7 @@
|
||||
#define MT_RX_FILTR_CFG_CTRL_RSV BIT(16)
|
||||
|
||||
#define MT_AUTO_RSP_CFG 0x1404
|
||||
#define MT_AUTO_RSP_EN BIT(0)
|
||||
#define MT_AUTO_RSP_PREAMB_SHORT BIT(4)
|
||||
#define MT_LEGACY_BASIC_RATE 0x1408
|
||||
#define MT_HT_BASIC_RATE 0x140c
|
||||
@ -532,6 +563,7 @@
|
||||
#define MT_PN_PAD_MODE 0x150c
|
||||
|
||||
#define MT_TXOP_HLDR_ET 0x1608
|
||||
#define MT_TXOP_HLDR_TX40M_BLK_EN BIT(1)
|
||||
|
||||
#define MT_PROT_AUTO_TX_CFG 0x1648
|
||||
#define MT_PROT_AUTO_TX_CFG_PROT_PADJ GENMASK(11, 8)
|
||||
|
@ -177,7 +177,7 @@ int mt76x02_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (pid && pid != MT_PACKET_ID_NO_ACK)
|
||||
if (pid >= MT_PACKET_ID_FIRST)
|
||||
qsel = MT_QSEL_MGMT;
|
||||
|
||||
*tx_info = FIELD_PREP(MT_TXD_INFO_QSEL, qsel) |
|
||||
|
@ -87,8 +87,7 @@ int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data,
|
||||
pid = mt76_tx_status_skb_add(mdev, wcid, skb);
|
||||
txwi->pktid = pid;
|
||||
|
||||
if ((pid && pid != MT_PACKET_ID_NO_ACK) ||
|
||||
q2ep(q->hw_idx) == MT_EP_OUT_HCCA)
|
||||
if (pid >= MT_PACKET_ID_FIRST || q2ep(q->hw_idx) == MT_EP_OUT_HCCA)
|
||||
qsel = MT_QSEL_MGMT;
|
||||
else
|
||||
qsel = MT_QSEL_EDCA;
|
||||
|
@ -75,6 +75,58 @@ static const struct ieee80211_iface_combination mt76x02_if_comb[] = {
|
||||
}
|
||||
};
|
||||
|
||||
static void
|
||||
mt76x02_led_set_config(struct mt76_dev *mdev, u8 delay_on,
|
||||
u8 delay_off)
|
||||
{
|
||||
struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev,
|
||||
mt76);
|
||||
u32 val;
|
||||
|
||||
val = MT_LED_STATUS_DURATION(0xff) |
|
||||
MT_LED_STATUS_OFF(delay_off) |
|
||||
MT_LED_STATUS_ON(delay_on);
|
||||
|
||||
mt76_wr(dev, MT_LED_S0(mdev->led_pin), val);
|
||||
mt76_wr(dev, MT_LED_S1(mdev->led_pin), val);
|
||||
|
||||
val = MT_LED_CTRL_REPLAY(mdev->led_pin) |
|
||||
MT_LED_CTRL_KICK(mdev->led_pin);
|
||||
if (mdev->led_al)
|
||||
val |= MT_LED_CTRL_POLARITY(mdev->led_pin);
|
||||
mt76_wr(dev, MT_LED_CTRL, val);
|
||||
}
|
||||
|
||||
static int
|
||||
mt76x02_led_set_blink(struct led_classdev *led_cdev,
|
||||
unsigned long *delay_on,
|
||||
unsigned long *delay_off)
|
||||
{
|
||||
struct mt76_dev *mdev = container_of(led_cdev, struct mt76_dev,
|
||||
led_cdev);
|
||||
u8 delta_on, delta_off;
|
||||
|
||||
delta_off = max_t(u8, *delay_off / 10, 1);
|
||||
delta_on = max_t(u8, *delay_on / 10, 1);
|
||||
|
||||
mt76x02_led_set_config(mdev, delta_on, delta_off);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
mt76x02_led_set_brightness(struct led_classdev *led_cdev,
|
||||
enum led_brightness brightness)
|
||||
{
|
||||
struct mt76_dev *mdev = container_of(led_cdev, struct mt76_dev,
|
||||
led_cdev);
|
||||
|
||||
if (!brightness)
|
||||
mt76x02_led_set_config(mdev, 0, 0xff);
|
||||
else
|
||||
mt76x02_led_set_config(mdev, 0xff, 0);
|
||||
}
|
||||
|
||||
void mt76x02_init_device(struct mt76x02_dev *dev)
|
||||
{
|
||||
struct ieee80211_hw *hw = mt76_hw(dev);
|
||||
@ -93,6 +145,8 @@ void mt76x02_init_device(struct mt76x02_dev *dev)
|
||||
MT_DMA_HDR_LEN;
|
||||
wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
|
||||
} else {
|
||||
INIT_DELAYED_WORK(&dev->wdt_work, mt76x02_wdt_work);
|
||||
|
||||
mt76x02_dfs_init_detector(dev);
|
||||
|
||||
wiphy->reg_notifier = mt76x02_regd_notifier;
|
||||
@ -106,7 +160,16 @@ void mt76x02_init_device(struct mt76x02_dev *dev)
|
||||
#endif
|
||||
BIT(NL80211_IFTYPE_ADHOC);
|
||||
|
||||
wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
|
||||
|
||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
|
||||
|
||||
/* init led callbacks */
|
||||
if (IS_ENABLED(CONFIG_MT76_LEDS)) {
|
||||
dev->mt76.led_cdev.brightness_set =
|
||||
mt76x02_led_set_brightness;
|
||||
dev->mt76.led_cdev.blink_set = mt76x02_led_set_blink;
|
||||
}
|
||||
}
|
||||
|
||||
hw->sta_data_size = sizeof(struct mt76x02_sta);
|
||||
@ -189,8 +252,6 @@ int mt76x02_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
||||
if (vif->type == NL80211_IFTYPE_AP)
|
||||
set_bit(MT_WCID_FLAG_CHECK_PS, &msta->wcid.flags);
|
||||
|
||||
ewma_signal_init(&msta->rssi);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x02_sta_add);
|
||||
@ -463,7 +524,7 @@ int mt76x02_set_rts_threshold(struct ieee80211_hw *hw, u32 val)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
mt76x02_mac_set_tx_protection(dev, val);
|
||||
mt76x02_mac_set_rts_thresh(dev, val);
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
|
||||
return 0;
|
||||
@ -546,24 +607,6 @@ void mt76x02_sw_scan_complete(struct ieee80211_hw *hw,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x02_sw_scan_complete);
|
||||
|
||||
int mt76x02_get_txpower(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif, int *dbm)
|
||||
{
|
||||
struct mt76x02_dev *dev = hw->priv;
|
||||
u8 nstreams = dev->mt76.chainmask & 0xf;
|
||||
|
||||
*dbm = dev->mt76.txpower_cur / 2;
|
||||
|
||||
/* convert from per-chain power to combined
|
||||
* output on 2x2 devices
|
||||
*/
|
||||
if (nstreams > 1)
|
||||
*dbm += 3;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x02_get_txpower);
|
||||
|
||||
void mt76x02_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta,
|
||||
bool ps)
|
||||
{
|
||||
@ -661,6 +704,10 @@ void mt76x02_bss_info_changed(struct ieee80211_hw *hw,
|
||||
tasklet_enable(&dev->pre_tbtt_tasklet);
|
||||
}
|
||||
|
||||
if (changed & BSS_CHANGED_HT || changed & BSS_CHANGED_ERP_CTS_PROT)
|
||||
mt76x02_mac_set_tx_protection(dev, info->use_cts_prot,
|
||||
info->ht_operation_mode);
|
||||
|
||||
if (changed & BSS_CHANGED_BEACON_INT) {
|
||||
mt76_rmw_field(dev, MT_BEACON_TIME_CFG,
|
||||
MT_BEACON_TIME_CFG_INTVAL,
|
||||
|
@ -143,6 +143,7 @@ void mt76_write_mac_initvals(struct mt76x02_dev *dev)
|
||||
{ MT_VHT_HT_FBK_CFG1, 0xedcba980 },
|
||||
{ MT_PROT_AUTO_TX_CFG, 0x00830083 },
|
||||
{ MT_HT_CTRL_CFG, 0x000001ff },
|
||||
{ MT_TX_LINK_CFG, 0x00001020 },
|
||||
};
|
||||
struct mt76_reg_pair prot_vals[] = {
|
||||
{ MT_CCK_PROT_CFG, DEFAULT_PROT_CFG_CCK },
|
||||
|
@ -26,29 +26,6 @@
|
||||
#define MT_MCU_PCIE_REMAP_BASE2 0x0744
|
||||
#define MT_MCU_PCIE_REMAP_BASE3 0x0748
|
||||
|
||||
#define MT_LED_CTRL 0x0770
|
||||
#define MT_LED_CTRL_REPLAY(_n) BIT(0 + (8 * (_n)))
|
||||
#define MT_LED_CTRL_POLARITY(_n) BIT(1 + (8 * (_n)))
|
||||
#define MT_LED_CTRL_TX_BLINK_MODE(_n) BIT(2 + (8 * (_n)))
|
||||
#define MT_LED_CTRL_KICK(_n) BIT(7 + (8 * (_n)))
|
||||
|
||||
#define MT_LED_TX_BLINK_0 0x0774
|
||||
#define MT_LED_TX_BLINK_1 0x0778
|
||||
|
||||
#define MT_LED_S0_BASE 0x077C
|
||||
#define MT_LED_S0(_n) (MT_LED_S0_BASE + 8 * (_n))
|
||||
#define MT_LED_S1_BASE 0x0780
|
||||
#define MT_LED_S1(_n) (MT_LED_S1_BASE + 8 * (_n))
|
||||
#define MT_LED_STATUS_OFF_MASK GENMASK(31, 24)
|
||||
#define MT_LED_STATUS_OFF(_v) (((_v) << __ffs(MT_LED_STATUS_OFF_MASK)) & \
|
||||
MT_LED_STATUS_OFF_MASK)
|
||||
#define MT_LED_STATUS_ON_MASK GENMASK(23, 16)
|
||||
#define MT_LED_STATUS_ON(_v) (((_v) << __ffs(MT_LED_STATUS_ON_MASK)) & \
|
||||
MT_LED_STATUS_ON_MASK)
|
||||
#define MT_LED_STATUS_DURATION_MASK GENMASK(15, 8)
|
||||
#define MT_LED_STATUS_DURATION(_v) (((_v) << __ffs(MT_LED_STATUS_DURATION_MASK)) & \
|
||||
MT_LED_STATUS_DURATION_MASK)
|
||||
|
||||
#define MT_MCU_ROM_PATCH_OFFSET 0x80000
|
||||
#define MT_MCU_ROM_PATCH_ADDR 0x90000
|
||||
|
||||
|
@ -53,7 +53,6 @@ struct mt76x02_dev *mt76x2_alloc_device(struct device *pdev);
|
||||
int mt76x2_register_device(struct mt76x02_dev *dev);
|
||||
|
||||
void mt76x2_phy_power_on(struct mt76x02_dev *dev);
|
||||
int mt76x2_init_hardware(struct mt76x02_dev *dev);
|
||||
void mt76x2_stop_hardware(struct mt76x02_dev *dev);
|
||||
int mt76x2_eeprom_init(struct mt76x02_dev *dev);
|
||||
int mt76x2_apply_calibration_data(struct mt76x02_dev *dev, int channel);
|
||||
|
@ -151,6 +151,7 @@ static int mt76x2_mac_reset(struct mt76x02_dev *dev, bool hard)
|
||||
MT_CH_TIME_CFG_RX_AS_BUSY |
|
||||
MT_CH_TIME_CFG_NAV_AS_BUSY |
|
||||
MT_CH_TIME_CFG_EIFS_AS_BUSY |
|
||||
MT_CH_CCA_RC_EN |
|
||||
FIELD_PREP(MT_CH_TIME_CFG_CH_TIMER_CLR, 1));
|
||||
|
||||
mt76x02_set_tx_ackto(dev);
|
||||
@ -260,7 +261,7 @@ mt76x2_power_on(struct mt76x02_dev *dev)
|
||||
mt76x2_power_on_rf(dev, 1);
|
||||
}
|
||||
|
||||
int mt76x2_init_hardware(struct mt76x02_dev *dev)
|
||||
static int mt76x2_init_hardware(struct mt76x02_dev *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@ -300,6 +301,7 @@ void mt76x2_stop_hardware(struct mt76x02_dev *dev)
|
||||
{
|
||||
cancel_delayed_work_sync(&dev->cal_work);
|
||||
cancel_delayed_work_sync(&dev->mac_work);
|
||||
cancel_delayed_work_sync(&dev->wdt_work);
|
||||
mt76x02_mcu_set_radio_state(dev, false);
|
||||
mt76x2_mac_stop(dev, false);
|
||||
}
|
||||
@ -340,54 +342,6 @@ struct mt76x02_dev *mt76x2_alloc_device(struct device *pdev)
|
||||
return dev;
|
||||
}
|
||||
|
||||
static void mt76x2_led_set_config(struct mt76_dev *mt76, u8 delay_on,
|
||||
u8 delay_off)
|
||||
{
|
||||
struct mt76x02_dev *dev = container_of(mt76, struct mt76x02_dev,
|
||||
mt76);
|
||||
u32 val;
|
||||
|
||||
val = MT_LED_STATUS_DURATION(0xff) |
|
||||
MT_LED_STATUS_OFF(delay_off) |
|
||||
MT_LED_STATUS_ON(delay_on);
|
||||
|
||||
mt76_wr(dev, MT_LED_S0(mt76->led_pin), val);
|
||||
mt76_wr(dev, MT_LED_S1(mt76->led_pin), val);
|
||||
|
||||
val = MT_LED_CTRL_REPLAY(mt76->led_pin) |
|
||||
MT_LED_CTRL_KICK(mt76->led_pin);
|
||||
if (mt76->led_al)
|
||||
val |= MT_LED_CTRL_POLARITY(mt76->led_pin);
|
||||
mt76_wr(dev, MT_LED_CTRL, val);
|
||||
}
|
||||
|
||||
static int mt76x2_led_set_blink(struct led_classdev *led_cdev,
|
||||
unsigned long *delay_on,
|
||||
unsigned long *delay_off)
|
||||
{
|
||||
struct mt76_dev *mt76 = container_of(led_cdev, struct mt76_dev,
|
||||
led_cdev);
|
||||
u8 delta_on, delta_off;
|
||||
|
||||
delta_off = max_t(u8, *delay_off / 10, 1);
|
||||
delta_on = max_t(u8, *delay_on / 10, 1);
|
||||
|
||||
mt76x2_led_set_config(mt76, delta_on, delta_off);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mt76x2_led_set_brightness(struct led_classdev *led_cdev,
|
||||
enum led_brightness brightness)
|
||||
{
|
||||
struct mt76_dev *mt76 = container_of(led_cdev, struct mt76_dev,
|
||||
led_cdev);
|
||||
|
||||
if (!brightness)
|
||||
mt76x2_led_set_config(mt76, 0, 0xff);
|
||||
else
|
||||
mt76x2_led_set_config(mt76, 0xff, 0);
|
||||
}
|
||||
|
||||
int mt76x2_register_device(struct mt76x02_dev *dev)
|
||||
{
|
||||
int ret;
|
||||
@ -402,12 +356,6 @@ int mt76x2_register_device(struct mt76x02_dev *dev)
|
||||
|
||||
mt76x02_config_mac_addr_list(dev);
|
||||
|
||||
/* init led callbacks */
|
||||
if (IS_ENABLED(CONFIG_MT76_LEDS)) {
|
||||
dev->mt76.led_cdev.brightness_set = mt76x2_led_set_brightness;
|
||||
dev->mt76.led_cdev.blink_set = mt76x2_led_set_blink;
|
||||
}
|
||||
|
||||
ret = mt76_register_device(&dev->mt76, true, mt76x02_rates,
|
||||
ARRAY_SIZE(mt76x02_rates));
|
||||
if (ret)
|
||||
|
@ -34,6 +34,8 @@ mt76x2_start(struct ieee80211_hw *hw)
|
||||
|
||||
ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work,
|
||||
MT_CALIBRATE_INTERVAL);
|
||||
ieee80211_queue_delayed_work(mt76_hw(dev), &dev->wdt_work,
|
||||
MT_WATCHDOG_TIME);
|
||||
|
||||
set_bit(MT76_STATE_RUNNING, &dev->mt76.state);
|
||||
|
||||
@ -189,7 +191,7 @@ const struct ieee80211_ops mt76x2_ops = {
|
||||
.sw_scan_complete = mt76x02_sw_scan_complete,
|
||||
.flush = mt76x2_flush,
|
||||
.ampdu_action = mt76x02_ampdu_action,
|
||||
.get_txpower = mt76x02_get_txpower,
|
||||
.get_txpower = mt76_get_txpower,
|
||||
.wake_tx_queue = mt76_wake_tx_queue,
|
||||
.sta_rate_tbl_update = mt76x02_sta_rate_tbl_update,
|
||||
.release_buffered_frames = mt76_release_buffered_frames,
|
||||
|
@ -254,6 +254,8 @@ int mt76x2_phy_set_channel(struct mt76x02_dev *dev,
|
||||
0x38);
|
||||
}
|
||||
|
||||
mt76x02_edcca_init(dev);
|
||||
|
||||
ieee80211_queue_delayed_work(mt76_hw(dev), &dev->cal_work,
|
||||
MT_CALIBRATE_INTERVAL);
|
||||
|
||||
|
@ -284,7 +284,9 @@ void mt76x2_phy_update_channel_gain(struct mt76x02_dev *dev)
|
||||
int low_gain;
|
||||
u32 val;
|
||||
|
||||
dev->cal.avg_rssi_all = mt76x02_phy_get_min_avg_rssi(dev);
|
||||
dev->cal.avg_rssi_all = mt76_get_min_avg_rssi(&dev->mt76);
|
||||
if (!dev->cal.avg_rssi_all)
|
||||
dev->cal.avg_rssi_all = -75;
|
||||
|
||||
low_gain = (dev->cal.avg_rssi_all > mt76x02_get_rssi_gain_thresh(dev)) +
|
||||
(dev->cal.avg_rssi_all > mt76x02_get_low_rssi_gain_thresh(dev));
|
||||
|
@ -138,5 +138,5 @@ const struct ieee80211_ops mt76x2u_ops = {
|
||||
.sw_scan_start = mt76x02_sw_scan,
|
||||
.sw_scan_complete = mt76x02_sw_scan_complete,
|
||||
.sta_rate_tbl_update = mt76x02_sta_rate_tbl_update,
|
||||
.get_txpower = mt76x02_get_txpower,
|
||||
.get_txpower = mt76_get_txpower,
|
||||
};
|
||||
|
@ -39,7 +39,7 @@ static void mt76x2u_mcu_load_ivb(struct mt76x02_dev *dev)
|
||||
static void mt76x2u_mcu_enable_patch(struct mt76x02_dev *dev)
|
||||
{
|
||||
struct mt76_usb *usb = &dev->mt76.usb;
|
||||
const u8 data[] = {
|
||||
static const u8 data[] = {
|
||||
0x6f, 0xfc, 0x08, 0x01,
|
||||
0x20, 0x04, 0x00, 0x00,
|
||||
0x00, 0x09, 0x00,
|
||||
|
@ -170,21 +170,22 @@ mt76_tx_status_skb_add(struct mt76_dev *dev, struct mt76_wcid *wcid,
|
||||
int pid;
|
||||
|
||||
if (!wcid)
|
||||
return 0;
|
||||
return MT_PACKET_ID_NO_ACK;
|
||||
|
||||
if (info->flags & IEEE80211_TX_CTL_NO_ACK)
|
||||
return MT_PACKET_ID_NO_ACK;
|
||||
|
||||
if (!(info->flags & (IEEE80211_TX_CTL_REQ_TX_STATUS |
|
||||
IEEE80211_TX_CTL_RATE_CTRL_PROBE)))
|
||||
return 0;
|
||||
return MT_PACKET_ID_NO_SKB;
|
||||
|
||||
spin_lock_bh(&dev->status_list.lock);
|
||||
|
||||
memset(cb, 0, sizeof(*cb));
|
||||
wcid->packet_id = (wcid->packet_id + 1) & MT_PACKET_ID_MASK;
|
||||
if (!wcid->packet_id || wcid->packet_id == MT_PACKET_ID_NO_ACK)
|
||||
wcid->packet_id = 1;
|
||||
if (wcid->packet_id == MT_PACKET_ID_NO_ACK ||
|
||||
wcid->packet_id == MT_PACKET_ID_NO_SKB)
|
||||
wcid->packet_id = MT_PACKET_ID_FIRST;
|
||||
|
||||
pid = wcid->packet_id;
|
||||
cb->wcid = wcid->idx;
|
||||
@ -330,7 +331,8 @@ mt76_queue_ps_skb(struct mt76_dev *dev, struct ieee80211_sta *sta,
|
||||
|
||||
info->control.flags |= IEEE80211_TX_CTRL_PS_RESPONSE;
|
||||
if (last)
|
||||
info->flags |= IEEE80211_TX_STATUS_EOSP;
|
||||
info->flags |= IEEE80211_TX_STATUS_EOSP |
|
||||
IEEE80211_TX_CTL_REQ_TX_STATUS;
|
||||
|
||||
mt76_skb_set_moredata(skb, !last);
|
||||
dev->queue_ops->tx_queue_skb(dev, hwq, skb, wcid, sta);
|
||||
@ -394,6 +396,11 @@ mt76_txq_send_burst(struct mt76_dev *dev, struct mt76_queue *hwq,
|
||||
bool probe;
|
||||
int idx;
|
||||
|
||||
if (test_bit(MT_WCID_FLAG_PS, &wcid->flags)) {
|
||||
*empty = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
skb = mt76_txq_dequeue(dev, mtxq, false);
|
||||
if (!skb) {
|
||||
*empty = true;
|
||||
|
@ -407,17 +407,15 @@ mt76u_process_rx_entry(struct mt76_dev *dev, struct urb *urb)
|
||||
if (len < 0)
|
||||
return 0;
|
||||
|
||||
data_len = min_t(int, len, urb->sg[0].length - MT_DMA_HDR_LEN);
|
||||
if (MT_DMA_HDR_LEN + data_len > SKB_WITH_OVERHEAD(q->buf_size))
|
||||
return 0;
|
||||
|
||||
skb = build_skb(data, q->buf_size);
|
||||
if (!skb)
|
||||
return 0;
|
||||
|
||||
data_len = min_t(int, len, urb->sg[0].length - MT_DMA_HDR_LEN);
|
||||
skb_reserve(skb, MT_DMA_HDR_LEN);
|
||||
if (skb->tail + data_len > skb->end) {
|
||||
dev_kfree_skb(skb);
|
||||
return 1;
|
||||
}
|
||||
|
||||
__skb_put(skb, data_len);
|
||||
len -= data_len;
|
||||
|
||||
@ -585,6 +583,7 @@ static void mt76u_stop_rx(struct mt76_dev *dev)
|
||||
static void mt76u_tx_tasklet(unsigned long data)
|
||||
{
|
||||
struct mt76_dev *dev = (struct mt76_dev *)data;
|
||||
struct mt76_queue_entry entry;
|
||||
struct mt76u_buf *buf;
|
||||
struct mt76_queue *q;
|
||||
bool wake;
|
||||
@ -599,17 +598,18 @@ static void mt76u_tx_tasklet(unsigned long data)
|
||||
if (!buf->done || !q->queued)
|
||||
break;
|
||||
|
||||
dev->drv->tx_complete_skb(dev, q,
|
||||
&q->entry[q->head],
|
||||
false);
|
||||
|
||||
if (q->entry[q->head].schedule) {
|
||||
q->entry[q->head].schedule = false;
|
||||
q->swq_queued--;
|
||||
}
|
||||
|
||||
entry = q->entry[q->head];
|
||||
q->head = (q->head + 1) % q->ndesc;
|
||||
q->queued--;
|
||||
|
||||
spin_unlock_bh(&q->lock);
|
||||
dev->drv->tx_complete_skb(dev, q, &entry, false);
|
||||
spin_lock_bh(&q->lock);
|
||||
}
|
||||
mt76_txq_schedule(dev, q);
|
||||
wake = i < IEEE80211_NUM_ACS && q->queued < q->ndesc - 8;
|
||||
|
@ -75,4 +75,46 @@ int mt76_wcid_alloc(unsigned long *mask, int size)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_wcid_alloc);
|
||||
|
||||
int mt76_get_min_avg_rssi(struct mt76_dev *dev)
|
||||
{
|
||||
struct mt76_wcid *wcid;
|
||||
int i, j, min_rssi = 0;
|
||||
s8 cur_rssi;
|
||||
|
||||
local_bh_disable();
|
||||
rcu_read_lock();
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dev->wcid_mask); i++) {
|
||||
unsigned long mask = dev->wcid_mask[i];
|
||||
|
||||
if (!mask)
|
||||
continue;
|
||||
|
||||
for (j = i * BITS_PER_LONG; mask; j++, mask >>= 1) {
|
||||
if (!(mask & 1))
|
||||
continue;
|
||||
|
||||
wcid = rcu_dereference(dev->wcid[j]);
|
||||
if (!wcid)
|
||||
continue;
|
||||
|
||||
spin_lock(&dev->rx_lock);
|
||||
if (wcid->inactive_count++ < 5)
|
||||
cur_rssi = -ewma_signal_read(&wcid->rssi);
|
||||
else
|
||||
cur_rssi = 0;
|
||||
spin_unlock(&dev->rx_lock);
|
||||
|
||||
if (cur_rssi < min_rssi)
|
||||
min_rssi = cur_rssi;
|
||||
}
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
local_bh_enable();
|
||||
|
||||
return min_rssi;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_get_min_avg_rssi);
|
||||
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
|
Loading…
x
Reference in New Issue
Block a user