Commit 7bc04215 authored by Felix Fietkau's avatar Felix Fietkau Committed by Kalle Valo

mt76: add driver code for MT76x2e

MT76x2e is a 2x2 PCIe 802.11ac chipset by MediaTek. This driver has full
support for AP, station, ad-hoc, mesh and monitor mode.
Signed-off-by: default avatarFelix Fietkau <nbd@nbd.name>
Signed-off-by: default avatarLorenzo Bianconi <lorenzo.bianconi83@gmail.com>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
parent 17f1de56
......@@ -11,4 +11,5 @@ config WLAN_VENDOR_MEDIATEK
if WLAN_VENDOR_MEDIATEK
source "drivers/net/wireless/mediatek/mt7601u/Kconfig"
source "drivers/net/wireless/mediatek/mt76/Kconfig"
endif # WLAN_VENDOR_MEDIATEK
obj-$(CONFIG_MT7601U) += mt7601u/
obj-$(CONFIG_MT76_CORE) += mt76/
config MT76_CORE
tristate
config MT76x2E
tristate "MediaTek MT76x2E (PCIe) support"
select MT76_CORE
depends on MAC80211
depends on PCI
---help---
This adds support for MT7612/MT7602/MT7662-based wireless PCIe devices.
obj-$(CONFIG_MT76_CORE) += mt76.o
obj-$(CONFIG_MT76x2E) += mt76x2e.o
mt76-y := \
mmio.o util.o trace.o dma.o mac80211.o debugfs.o eeprom.o tx.o
CFLAGS_trace.o := -I$(src)
mt76x2e-y := \
mt76x2_pci.o mt76x2_dma.o \
mt76x2_main.o mt76x2_init.o mt76x2_debugfs.o mt76x2_tx.o \
mt76x2_core.o mt76x2_mac.o mt76x2_eeprom.o mt76x2_mcu.o mt76x2_phy.o \
mt76x2_dfs.o mt76x2_trace.o
CFLAGS_mt76x2_trace.o := -I$(src)
/*
* Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef __MT76x2_H
#define __MT76x2_H
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/spinlock.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/mutex.h>
#include <linux/bitops.h>
#include <linux/kfifo.h>
#define MT7662_FIRMWARE "mt7662.bin"
#define MT7662_ROM_PATCH "mt7662_rom_patch.bin"
#define MT7662_EEPROM_SIZE 512
#define MT76x2_RX_RING_SIZE 256
#define MT_RX_HEADROOM 32
#define MT_MAX_CHAINS 2
#define MT_CALIBRATE_INTERVAL HZ
#include "mt76.h"
#include "mt76x2_regs.h"
#include "mt76x2_mac.h"
#include "mt76x2_dfs.h"
struct mt76x2_mcu {
struct mutex mutex;
wait_queue_head_t wait;
struct sk_buff_head res_q;
u32 msg_seq;
};
struct mt76x2_rx_freq_cal {
s8 high_gain[MT_MAX_CHAINS];
s8 rssi_offset[MT_MAX_CHAINS];
s8 lna_gain;
u32 mcu_gain;
};
struct mt76x2_calibration {
struct mt76x2_rx_freq_cal rx;
u8 agc_gain_init[MT_MAX_CHAINS];
u8 agc_gain_cur[MT_MAX_CHAINS];
int avg_rssi[MT_MAX_CHAINS];
int avg_rssi_all;
s8 agc_gain_adjust;
s8 low_gain;
u8 temp;
bool init_cal_done;
bool tssi_cal_done;
bool tssi_comp_pending;
bool dpd_cal_done;
bool channel_cal_done;
};
struct mt76x2_dev {
struct mt76_dev mt76; /* must be first */
struct mac_address macaddr_list[8];
struct mutex mutex;
const u16 *beacon_offsets;
unsigned long wcid_mask[128 / BITS_PER_LONG];
int txpower_conf;
int txpower_cur;
u8 txdone_seq;
DECLARE_KFIFO_PTR(txstatus_fifo, struct mt76x2_tx_status);
struct mt76x2_mcu mcu;
struct sk_buff *rx_head;
struct tasklet_struct tx_tasklet;
struct tasklet_struct pre_tbtt_tasklet;
struct delayed_work cal_work;
struct delayed_work mac_work;
u32 aggr_stats[32];
struct mt76_wcid global_wcid;
struct mt76_wcid __rcu *wcid[128];
spinlock_t irq_lock;
u32 irqmask;
struct sk_buff *beacons[8];
u8 beacon_mask;
u8 beacon_data_mask;
u32 rev;
u32 rxfilter;
u16 chainmask;
struct mt76x2_calibration cal;
s8 target_power;
s8 target_power_delta[2];
struct mt76_rate_power rate_power;
bool enable_tpc;
u8 coverage_class;
u8 slottime;
struct mt76x2_dfs_pattern_detector dfs_pd;
};
struct mt76x2_vif {
u8 idx;
struct mt76_wcid group_wcid;
};
struct mt76x2_sta {
struct mt76_wcid wcid; /* must be first */
struct mt76x2_tx_status status;
int n_frames;
};
static inline bool is_mt7612(struct mt76x2_dev *dev)
{
return (dev->rev >> 16) == 0x7612;
}
void mt76x2_set_irq_mask(struct mt76x2_dev *dev, u32 clear, u32 set);
static inline void mt76x2_irq_enable(struct mt76x2_dev *dev, u32 mask)
{
mt76x2_set_irq_mask(dev, 0, mask);
}
static inline void mt76x2_irq_disable(struct mt76x2_dev *dev, u32 mask)
{
mt76x2_set_irq_mask(dev, mask, 0);
}
extern const struct ieee80211_ops mt76x2_ops;
struct mt76x2_dev *mt76x2_alloc_device(struct device *pdev);
int mt76x2_register_device(struct mt76x2_dev *dev);
void mt76x2_init_debugfs(struct mt76x2_dev *dev);
irqreturn_t mt76x2_irq_handler(int irq, void *dev_instance);
void mt76x2_phy_power_on(struct mt76x2_dev *dev);
int mt76x2_init_hardware(struct mt76x2_dev *dev);
void mt76x2_stop_hardware(struct mt76x2_dev *dev);
int mt76x2_eeprom_init(struct mt76x2_dev *dev);
int mt76x2_apply_calibration_data(struct mt76x2_dev *dev, int channel);
void mt76x2_set_tx_ackto(struct mt76x2_dev *dev);
int mt76x2_phy_start(struct mt76x2_dev *dev);
int mt76x2_phy_set_channel(struct mt76x2_dev *dev,
struct cfg80211_chan_def *chandef);
int mt76x2_phy_get_rssi(struct mt76x2_dev *dev, s8 rssi, int chain);
void mt76x2_phy_calibrate(struct work_struct *work);
void mt76x2_phy_set_txpower(struct mt76x2_dev *dev);
int mt76x2_mcu_init(struct mt76x2_dev *dev);
int mt76x2_mcu_set_channel(struct mt76x2_dev *dev, u8 channel, u8 bw,
u8 bw_index, bool scan);
int mt76x2_mcu_set_radio_state(struct mt76x2_dev *dev, bool on);
int mt76x2_mcu_load_cr(struct mt76x2_dev *dev, u8 type, u8 temp_level,
u8 channel);
int mt76x2_mcu_cleanup(struct mt76x2_dev *dev);
int mt76x2_dma_init(struct mt76x2_dev *dev);
void mt76x2_dma_cleanup(struct mt76x2_dev *dev);
void mt76x2_cleanup(struct mt76x2_dev *dev);
int mt76x2_tx_queue_mcu(struct mt76x2_dev *dev, enum mt76_txq_id qid,
struct sk_buff *skb, int cmd, int seq);
void mt76x2_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
struct sk_buff *skb);
void mt76x2_tx_complete(struct mt76x2_dev *dev, struct sk_buff *skb);
int mt76x2_tx_prepare_skb(struct mt76_dev *mdev, void *txwi,
struct sk_buff *skb, struct mt76_queue *q,
struct mt76_wcid *wcid, struct ieee80211_sta *sta,
u32 *tx_info);
void mt76x2_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue *q,
struct mt76_queue_entry *e, bool flush);
void mt76x2_pre_tbtt_tasklet(unsigned long arg);
void mt76x2_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q);
void mt76x2_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
struct sk_buff *skb);
void mt76x2_update_channel(struct mt76_dev *mdev);
s8 mt76x2_tx_get_max_txpwr_adj(struct mt76x2_dev *dev,
const struct ieee80211_tx_rate *rate);
s8 mt76x2_tx_get_txpwr_adj(struct mt76x2_dev *dev, s8 txpwr, s8 max_txpwr_adj);
void mt76x2_tx_set_txpwr_auto(struct mt76x2_dev *dev, s8 txpwr);
#endif
/*
* Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/delay.h>
#include "mt76x2.h"
#include "mt76x2_trace.h"
void mt76x2_set_irq_mask(struct mt76x2_dev *dev, u32 clear, u32 set)
{
unsigned long flags;
spin_lock_irqsave(&dev->irq_lock, flags);
dev->irqmask &= ~clear;
dev->irqmask |= set;
mt76_wr(dev, MT_INT_MASK_CSR, dev->irqmask);
spin_unlock_irqrestore(&dev->irq_lock, flags);
}
void mt76x2_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q)
{
struct mt76x2_dev *dev = container_of(mdev, struct mt76x2_dev, mt76);
mt76x2_irq_enable(dev, MT_INT_RX_DONE(q));
}
irqreturn_t mt76x2_irq_handler(int irq, void *dev_instance)
{
struct mt76x2_dev *dev = dev_instance;
u32 intr;
intr = mt76_rr(dev, MT_INT_SOURCE_CSR);
mt76_wr(dev, MT_INT_SOURCE_CSR, intr);
if (!test_bit(MT76_STATE_INITIALIZED, &dev->mt76.state))
return IRQ_NONE;
trace_dev_irq(dev, intr, dev->irqmask);
intr &= dev->irqmask;
if (intr & MT_INT_TX_DONE_ALL) {
mt76x2_irq_disable(dev, MT_INT_TX_DONE_ALL);
tasklet_schedule(&dev->tx_tasklet);
}
if (intr & MT_INT_RX_DONE(0)) {
mt76x2_irq_disable(dev, MT_INT_RX_DONE(0));
napi_schedule(&dev->mt76.napi[0]);
}
if (intr & MT_INT_RX_DONE(1)) {
mt76x2_irq_disable(dev, MT_INT_RX_DONE(1));
napi_schedule(&dev->mt76.napi[1]);
}
if (intr & MT_INT_PRE_TBTT)
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_TX_STAT) {
mt76x2_mac_poll_tx_status(dev, true);
tasklet_schedule(&dev->tx_tasklet);
}
if (intr & MT_INT_GPTIMER) {
mt76x2_irq_disable(dev, MT_INT_GPTIMER);
tasklet_schedule(&dev->dfs_pd.dfs_tasklet);
}
return IRQ_HANDLED;
}
/*
* Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/debugfs.h>
#include "mt76x2.h"
static int
mt76x2_ampdu_stat_read(struct seq_file *file, void *data)
{
struct mt76x2_dev *dev = file->private;
int i, j;
for (i = 0; i < 4; i++) {
seq_puts(file, "Length: ");
for (j = 0; j < 8; j++)
seq_printf(file, "%8d | ", i * 8 + j + 1);
seq_puts(file, "\n");
seq_puts(file, "Count: ");
for (j = 0; j < 8; j++)
seq_printf(file, "%8d | ", dev->aggr_stats[i * 8 + j]);
seq_puts(file, "\n");
seq_puts(file, "--------");
for (j = 0; j < 8; j++)
seq_puts(file, "-----------");
seq_puts(file, "\n");
}
return 0;
}
static int
mt76x2_ampdu_stat_open(struct inode *inode, struct file *f)
{
return single_open(f, mt76x2_ampdu_stat_read, inode->i_private);
}
static void
seq_puts_array(struct seq_file *file, const char *str, s8 *val, int len)
{
int i;
seq_printf(file, "%10s:", str);
for (i = 0; i < len; i++)
seq_printf(file, " %2d", val[i]);
seq_puts(file, "\n");
}
static int read_txpower(struct seq_file *file, void *data)
{
struct mt76x2_dev *dev = dev_get_drvdata(file->private);
seq_printf(file, "Target power: %d\n", dev->target_power);
seq_puts_array(file, "Delta", dev->target_power_delta,
ARRAY_SIZE(dev->target_power_delta));
seq_puts_array(file, "CCK", dev->rate_power.cck,
ARRAY_SIZE(dev->rate_power.cck));
seq_puts_array(file, "OFDM", dev->rate_power.ofdm,
ARRAY_SIZE(dev->rate_power.ofdm));
seq_puts_array(file, "HT", dev->rate_power.ht,
ARRAY_SIZE(dev->rate_power.ht));
seq_puts_array(file, "VHT", dev->rate_power.vht,
ARRAY_SIZE(dev->rate_power.vht));
return 0;
}
static const struct file_operations fops_ampdu_stat = {
.open = mt76x2_ampdu_stat_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int
mt76x2_dfs_stat_read(struct seq_file *file, void *data)
{
int i;
struct mt76x2_dev *dev = file->private;
struct mt76x2_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
for (i = 0; i < MT_DFS_NUM_ENGINES; i++) {
seq_printf(file, "engine: %d\n", i);
seq_printf(file, " hw pattern detected:\t%d\n",
dfs_pd->stats[i].hw_pattern);
seq_printf(file, " hw pulse discarded:\t%d\n",
dfs_pd->stats[i].hw_pulse_discarded);
}
return 0;
}
static int
mt76x2_dfs_stat_open(struct inode *inode, struct file *f)
{
return single_open(f, mt76x2_dfs_stat_read, inode->i_private);
}
static const struct file_operations fops_dfs_stat = {
.open = mt76x2_dfs_stat_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
void mt76x2_init_debugfs(struct mt76x2_dev *dev)
{
struct dentry *dir;
dir = mt76_register_debugfs(&dev->mt76);
if (!dir)
return;
debugfs_create_u8("temperature", S_IRUSR, dir, &dev->cal.temp);
debugfs_create_bool("tpc", S_IRUSR | S_IWUSR, dir, &dev->enable_tpc);
debugfs_create_file("ampdu_stat", S_IRUSR, dir, dev, &fops_ampdu_stat);
debugfs_create_file("dfs_stats", S_IRUSR, dir, dev, &fops_dfs_stat);
debugfs_create_devm_seqfile(dev->mt76.dev, "txpower", dir,
read_txpower);
}
This diff is collapsed.
/*
* Copyright (C) 2016 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef __MT76x2_DFS_H
#define __MT76x2_DFS_H
#include <linux/types.h>
#include <linux/nl80211.h>
#define MT_DFS_GP_INTERVAL (10 << 4) /* 64 us unit */
#define MT_DFS_NUM_ENGINES 4
/* bbp params */
#define MT_DFS_SYM_ROUND 0
#define MT_DFS_DELTA_DELAY 2
#define MT_DFS_VGA_MASK 0
#define MT_DFS_PWR_GAIN_OFFSET 3
#define MT_DFS_PWR_DOWN_TIME 0xf
#define MT_DFS_RX_PE_MASK 0xff
#define MT_DFS_PKT_END_MASK 0
#define MT_DFS_CH_EN 0xf
struct mt76x2_radar_specs {
u8 mode;
u16 avg_len;
u16 e_low;
u16 e_high;
u16 w_low;
u16 w_high;
u16 w_margin;
u32 t_low;
u32 t_high;
u16 t_margin;
u32 b_low;
u32 b_high;
u32 event_expiration;
u16 pwr_jmp;
};
struct mt76x2_dfs_hw_pulse {
u8 engine;
u32 period;
u32 w1;
u32 w2;
u32 burst;
};
struct mt76x2_dfs_engine_stats {
u32 hw_pattern;
u32 hw_pulse_discarded;
};
struct mt76x2_dfs_pattern_detector {
enum nl80211_dfs_regions region;
u8 chirp_pulse_cnt;
u32 chirp_pulse_ts;
struct mt76x2_dfs_engine_stats stats[MT_DFS_NUM_ENGINES];
struct tasklet_struct dfs_tasklet;
};
void mt76x2_dfs_init_params(struct mt76x2_dev *dev);
void mt76x2_dfs_init_detector(struct mt76x2_dev *dev);
void mt76x2_dfs_adjust_agc(struct mt76x2_dev *dev);
#endif /* __MT76x2_DFS_H */
/*
* Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "mt76x2.h"
#include "mt76x2_dma.h"
int
mt76x2_tx_queue_mcu(struct mt76x2_dev *dev, enum mt76_txq_id qid,
struct sk_buff *skb, int cmd, int seq)
{
struct mt76_queue *q = &dev->mt76.q_tx[qid];
struct mt76_queue_buf buf;
dma_addr_t addr;
u32 tx_info;
tx_info = MT_MCU_MSG_TYPE_CMD |
FIELD_PREP(MT_MCU_MSG_CMD_TYPE, cmd) |
FIELD_PREP(MT_MCU_MSG_CMD_SEQ, seq) |
FIELD_PREP(MT_MCU_MSG_PORT, CPU_TX_PORT) |
FIELD_PREP(MT_MCU_MSG_LEN, skb->len);
addr = dma_map_single(dev->mt76.dev, skb->data, skb->len,
DMA_TO_DEVICE);
if (dma_mapping_error(dev->mt76.dev, addr))
return -ENOMEM;
buf.addr = addr;
buf.len = skb->len;
spin_lock_bh(&q->lock);
mt76_queue_add_buf(dev, q, &buf, 1, tx_info, skb, NULL);
mt76_queue_kick(dev, q);
spin_unlock_bh(&q->lock);
return 0;
}
static int
mt76x2_init_tx_queue(struct mt76x2_dev *dev, struct mt76_queue *q,
int idx, int n_desc)
{
int ret;
q->regs = dev->mt76.regs + MT_TX_RING_BASE + idx * MT_RING_SIZE;
q->ndesc = n_desc;
ret = mt76_queue_alloc(dev, q);
if (ret)
return ret;
mt76x2_irq_enable(dev, MT_INT_TX_DONE(idx));
return 0;
}
void mt76x2_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
struct sk_buff *skb)
{
struct mt76x2_dev *dev = container_of(mdev, struct mt76x2_dev, mt76);
void *rxwi = skb->data;
if (q == MT_RXQ_MCU) {
skb_queue_tail(&dev->mcu.res_q, skb);
wake_up(&dev->mcu.wait);
return;
}
skb_pull(skb, sizeof(struct mt76x2_rxwi));
if (mt76x2_mac_process_rx(dev, skb, rxwi)) {
dev_kfree_skb(skb);
return;
}
mt76_rx(&dev->mt76, q, skb);
}
static int
mt76x2_init_rx_queue(struct mt76x2_dev *dev, struct mt76_queue *q,
int idx, int n_desc, int bufsize)
{
int ret;
q->regs = dev->mt76.regs + MT_RX_RING_BASE + idx * MT_RING_SIZE;
q->ndesc = n_desc;
q->buf_size = bufsize;
ret = mt76_queue_alloc(dev, q);
if (ret)
return ret;
mt76x2_irq_enable(dev, MT_INT_RX_DONE(idx));
return 0;
}
static void
mt76x2_tx_tasklet(unsigned long data)
{
struct mt76x2_dev *dev = (struct mt76x2_dev *) data;
int i;
mt76x2_mac_process_tx_status_fifo(dev);
for (i = MT_TXQ_MCU; i >= 0; i--)
mt76_queue_tx_cleanup(dev, i, false);
mt76x2_mac_poll_tx_status(dev, false);
mt76x2_irq_enable(dev, MT_INT_TX_DONE_ALL);
}
int mt76x2_dma_init(struct mt76x2_dev *dev)
{
static const u8 wmm_queue_map[] = {
[IEEE80211_AC_BE] = 0,
[IEEE80211_AC_BK] = 1,
[IEEE80211_AC_VI] = 2,
[IEEE80211_AC_VO] = 3,
};
int ret;
int i;
struct mt76_txwi_cache __maybe_unused *t;
struct mt76_queue *q;
BUILD_BUG_ON(sizeof(t->txwi) < sizeof(struct mt76x2_txwi));
BUILD_BUG_ON(sizeof(struct mt76x2_rxwi) > MT_RX_HEADROOM);
mt76_dma_attach(&dev->mt76);
init_waitqueue_head(&dev->mcu.wait);
skb_queue_head_init(&dev->mcu.res_q);
tasklet_init(&dev->tx_tasklet, mt76x2_tx_tasklet, (unsigned long) dev);
mt76_wr(dev, MT_WPDMA_RST_IDX, ~0);
for (i = 0; i < ARRAY_SIZE(wmm_queue_map); i++) {
ret = mt76x2_init_tx_queue(dev, &dev->mt76.q_tx[i],
wmm_queue_map[i], MT_TX_RING_SIZE);
if (ret)
return ret;
}
ret = mt76x2_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_PSD],
MT_TX_HW_QUEUE_MGMT, MT_TX_RING_SIZE);
if (ret)
return ret;
ret = mt76x2_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_MCU],
MT_TX_HW_QUEUE_MCU, MT_MCU_RING_SIZE);
if (ret)
return ret;
ret = mt76x2_init_rx_queue(dev, &dev->mt76.q_rx[MT_RXQ_MCU], 1,
MT_MCU_RING_SIZE, MT_RX_BUF_SIZE);
if (ret)
return ret;
q = &dev->mt76.q_rx[MT_RXQ_MAIN];
q->buf_offset = MT_RX_HEADROOM - sizeof(struct mt76x2_rxwi);
ret = mt76x2_init_rx_queue(dev, q, 0, MT76x2_RX_RING_SIZE, MT_RX_BUF_SIZE);
if (ret)
return ret;
return mt76_init_queues(dev);
}
void mt76x2_dma_cleanup(struct mt76x2_dev *dev)
{
tasklet_kill(&dev->tx_tasklet);
mt76_dma_cleanup(&dev->mt76);
}
/*
* Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef __MT76x2_DMA_H
#define __MT76x2_DMA_H
#include "dma.h"
#define MT_TXD_INFO_LEN GENMASK(13, 0)
#define MT_TXD_INFO_NEXT_VLD BIT(16)
#define MT_TXD_INFO_TX_BURST BIT(17)
#define MT_TXD_INFO_80211 BIT(19)
#define MT_TXD_INFO_TSO BIT(20)
#define MT_TXD_INFO_CSO BIT(21)
#define MT_TXD_INFO_WIV BIT(24)
#define MT_TXD_INFO_QSEL GENMASK(26, 25)
#define MT_TXD_INFO_TCO BIT(29)
#define MT_TXD_INFO_UCO BIT(30)
#define MT_TXD_INFO_ICO BIT(31)
#define MT_RX_FCE_INFO_LEN GENMASK(13, 0)
#define MT_RX_FCE_INFO_SELF_GEN BIT(15)
#define MT_RX_FCE_INFO_CMD_SEQ GENMASK(19, 16)
#define MT_RX_FCE_INFO_EVT_TYPE GENMASK(23, 20)
#define MT_RX_FCE_INFO_PCIE_INTR BIT(24)
#define MT_RX_FCE_INFO_QSEL GENMASK(26, 25)
#define MT_RX_FCE_INFO_D_PORT GENMASK(29, 27)
#define MT_RX_FCE_INFO_TYPE GENMASK(31, 30)
/* MCU request message header */
#define MT_MCU_MSG_LEN GENMASK(15, 0)
#define MT_MCU_MSG_CMD_SEQ GENMASK(19, 16)
#define MT_MCU_MSG_CMD_TYPE GENMASK(26, 20)
#define MT_MCU_MSG_PORT GENMASK(29, 27)
#define MT_MCU_MSG_TYPE GENMASK(31, 30)
#define MT_MCU_MSG_TYPE_CMD BIT(30)
enum mt76x2_qsel {
MT_QSEL_MGMT,
MT_QSEL_HCCA,
MT_QSEL_EDCA,
MT_QSEL_EDCA_2,
};
enum dma_msg_port {
WLAN_PORT,
CPU_RX_PORT,
CPU_TX_PORT,
HOST_PORT,
VIRTUAL_CPU_RX_PORT,
VIRTUAL_CPU_TX_PORT,
DISCARD,
};
#endif
This diff is collapsed.
/*
* Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef __MT76x2_EEPROM_H
#define __MT76x2_EEPROM_H
#include "mt76x2.h"
enum mt76x2_eeprom_field {
MT_EE_CHIP_ID = 0x000,
MT_EE_VERSION = 0x002,
MT_EE_MAC_ADDR = 0x004,
MT_EE_PCI_ID = 0x00A,
MT_EE_NIC_CONF_0 = 0x034,
MT_EE_NIC_CONF_1 = 0x036,
MT_EE_NIC_CONF_2 = 0x042,
MT_EE_XTAL_TRIM_1 = 0x03a,
MT_EE_XTAL_TRIM_2 = 0x09e,
MT_EE_LNA_GAIN = 0x044,
MT_EE_RSSI_OFFSET_2G_0 = 0x046,
MT_EE_RSSI_OFFSET_2G_1 = 0x048,
MT_EE_RSSI_OFFSET_5G_0 = 0x04a,
MT_EE_RSSI_OFFSET_5G_1 = 0x04c,
MT_EE_TX_POWER_DELTA_BW40 = 0x050,
MT_EE_TX_POWER_DELTA_BW80 = 0x052,
MT_EE_TX_POWER_EXT_PA_5G = 0x054,
MT_EE_TX_POWER_0_START_2G = 0x056,
MT_EE_TX_POWER_1_START_2G = 0x05c,
/* used as byte arrays */
#define MT_TX_POWER_GROUP_SIZE_5G 5
#define MT_TX_POWER_GROUPS_5G 6
MT_EE_TX_POWER_0_START_5G = 0x062,
MT_EE_TX_POWER_0_GRP3_TX_POWER_DELTA = 0x074,
MT_EE_TX_POWER_0_GRP4_TSSI_SLOPE = 0x076,
MT_EE_TX_POWER_1_START_5G = 0x080,
MT_EE_TX_POWER_CCK = 0x0a0,
MT_EE_TX_POWER_OFDM_2G_6M = 0x0a2,
MT_EE_TX_POWER_OFDM_2G_24M = 0x0a4,
MT_EE_TX_POWER_OFDM_5G_6M = 0x0b2,
MT_EE_TX_POWER_OFDM_5G_24M = 0x0b4,
MT_EE_TX_POWER_HT_MCS0 = 0x0a6,
MT_EE_TX_POWER_HT_MCS4 = 0x0a8,
MT_EE_TX_POWER_HT_MCS8 = 0x0aa,
MT_EE_TX_POWER_HT_MCS12 = 0x0ac,
MT_EE_TX_POWER_VHT_MCS0 = 0x0ba,
MT_EE_TX_POWER_VHT_MCS4 = 0x0bc,
MT_EE_TX_POWER_VHT_MCS8 = 0x0be,
MT_EE_RF_TEMP_COMP_SLOPE_5G = 0x0f2,
MT_EE_RF_TEMP_COMP_SLOPE_2G = 0x0f4,
MT_EE_RF_2G_TSSI_OFF_TXPOWER = 0x0f6,
MT_EE_RF_2G_RX_HIGH_GAIN = 0x0f8,
MT_EE_RF_5G_GRP0_1_RX_HIGH_GAIN = 0x0fa,
MT_EE_RF_5G_GRP2_3_RX_HIGH_GAIN = 0x0fc,
MT_EE_RF_5G_GRP4_5_RX_HIGH_GAIN = 0x0fe,
MT_EE_BT_RCAL_RESULT = 0x138,
MT_EE_BT_VCDL_CALIBRATION = 0x13c,
MT_EE_BT_PMUCFG = 0x13e,
__MT_EE_MAX
};
#define MT_EE_NIC_CONF_0_PA_INT_2G BIT(8)
#define MT_EE_NIC_CONF_0_PA_INT_5G BIT(9)
#define MT_EE_NIC_CONF_0_BOARD_TYPE GENMASK(13, 12)
#define MT_EE_NIC_CONF_1_TEMP_TX_ALC BIT(1)
#define MT_EE_NIC_CONF_1_LNA_EXT_2G BIT(2)
#define MT_EE_NIC_CONF_1_LNA_EXT_5G BIT(3)
#define MT_EE_NIC_CONF_1_TX_ALC_EN BIT(13)
#define MT_EE_NIC_CONF_2_RX_STREAM GENMASK(3, 0)
#define MT_EE_NIC_CONF_2_TX_STREAM GENMASK(7, 4)
#define MT_EE_NIC_CONF_2_HW_ANTDIV BIT(8)
#define MT_EE_NIC_CONF_2_XTAL_OPTION GENMASK(10, 9)
#define MT_EE_NIC_CONF_2_TEMP_DISABLE BIT(11)
#define MT_EE_NIC_CONF_2_COEX_METHOD GENMASK(15, 13)
enum mt76x2_board_type {
BOARD_TYPE_2GHZ = 1,
BOARD_TYPE_5GHZ = 2,
};
enum mt76x2_cal_channel_group {
MT_CH_5G_JAPAN,
MT_CH_5G_UNII_1,
MT_CH_5G_UNII_2,
MT_CH_5G_UNII_2E_1,
MT_CH_5G_UNII_2E_2,
MT_CH_5G_UNII_3,
__MT_CH_MAX
};
struct mt76x2_tx_power_info {
u8 target_power;
s8 delta_bw40;
s8 delta_bw80;
struct {
s8 tssi_slope;
s8 tssi_offset;
s8 target_power;
s8 delta;
} chain[MT_MAX_CHAINS];
};
struct mt76x2_temp_comp {
u8 temp_25_ref;
int lower_bound; /* J */
int upper_bound; /* J */
unsigned int high_slope; /* J / dB */
unsigned int low_slope; /* J / dB */
};
static inline int
mt76x2_eeprom_get(struct mt76x2_dev *dev, enum mt76x2_eeprom_field field)
{
if ((field & 1) || field >= __MT_EE_MAX)
return -1;
return get_unaligned_le16(dev->mt76.eeprom.data + field);
}
void mt76x2_get_rate_power(struct mt76x2_dev *dev, struct mt76_rate_power *t);
void mt76x2_get_power_info(struct mt76x2_dev *dev,
struct mt76x2_tx_power_info *t);
int mt76x2_get_temp_comp(struct mt76x2_dev *dev, struct mt76x2_temp_comp *t);
bool mt76x2_ext_pa_enabled(struct mt76x2_dev *dev, enum nl80211_band band);
void mt76x2_read_rx_gain(struct mt76x2_dev *dev);
static inline bool
mt76x2_temp_tx_alc_enabled(struct mt76x2_dev *dev)
{
return mt76x2_eeprom_get(dev, MT_EE_NIC_CONF_1) &
MT_EE_NIC_CONF_1_TEMP_TX_ALC;
}
static inline bool
mt76x2_tssi_enabled(struct mt76x2_dev *dev)
{
return !mt76x2_temp_tx_alc_enabled(dev) &&
(mt76x2_eeprom_get(dev, MT_EE_NIC_CONF_1) &
MT_EE_NIC_CONF_1_TX_ALC_EN);
}
static inline bool
mt76x2_has_ext_lna(struct mt76x2_dev *dev)
{
u32 val = mt76x2_eeprom_get(dev, MT_EE_NIC_CONF_1);
if (dev->mt76.chandef.chan->band == NL80211_BAND_2GHZ)
return val & MT_EE_NIC_CONF_1_LNA_EXT_2G;
else
return val & MT_EE_NIC_CONF_1_LNA_EXT_5G;
}
#endif
This diff is collapsed.
This diff is collapsed.
/*
* Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef __MT76x2_MAC_H
#define __MT76x2_MAC_H
#include "mt76.h"
struct mt76x2_dev;
struct mt76x2_sta;
struct mt76x2_vif;
struct mt76x2_txwi;
struct mt76x2_tx_status {
u8 valid:1;
u8 success:1;
u8 aggr:1;
u8 ack_req:1;
u8 wcid;
u8 pktid;
u8 retry;
u16 rate;
} __packed __aligned(2);
struct mt76x2_tx_info {
unsigned long jiffies;
u8 tries;
u8 wcid;
u8 pktid;
u8 retry;
};
struct mt76x2_rxwi {
__le32 rxinfo;
__le32 ctl;
__le16 tid_sn;
__le16 rate;
u8 rssi[4];
__le32 bbp_rxinfo[4];
};
#define MT_RXINFO_BA BIT(0)
#define MT_RXINFO_DATA BIT(1)
#define MT_RXINFO_NULL BIT(2)
#define MT_RXINFO_FRAG BIT(3)
#define MT_RXINFO_UNICAST BIT(4)
#define MT_RXINFO_MULTICAST BIT(5)
#define MT_RXINFO_BROADCAST BIT(6)
#define MT_RXINFO_MYBSS BIT(7)
#define MT_RXINFO_CRCERR BIT(8)
#define MT_RXINFO_ICVERR BIT(9)
#define MT_RXINFO_MICERR BIT(10)
#define MT_RXINFO_AMSDU BIT(11)
#define MT_RXINFO_HTC BIT(12)
#define MT_RXINFO_RSSI BIT(13)
#define MT_RXINFO_L2PAD BIT(14)
#define MT_RXINFO_AMPDU BIT(15)
#define MT_RXINFO_DECRYPT BIT(16)
#define MT_RXINFO_BSSIDX3 BIT(17)
#define MT_RXINFO_WAPI_KEY BIT(18)
#define MT_RXINFO_PN_LEN GENMASK(21, 19)
#define MT_RXINFO_SW_FTYPE0 BIT(22)
#define MT_RXINFO_SW_FTYPE1 BIT(23)
#define MT_RXINFO_PROBE_RESP BIT(24)
#define MT_RXINFO_BEACON BIT(25)
#define MT_RXINFO_DISASSOC BIT(26)
#define MT_RXINFO_DEAUTH BIT(27)
#define MT_RXINFO_ACTION BIT(28)
#define MT_RXINFO_TCP_SUM_ERR BIT(30)
#define MT_RXINFO_IP_SUM_ERR BIT(31)
#define MT_RXWI_CTL_WCID GENMASK(7, 0)
#define MT_RXWI_CTL_KEY_IDX GENMASK(9, 8)
#define MT_RXWI_CTL_BSS_IDX GENMASK(12, 10)
#define MT_RXWI_CTL_UDF GENMASK(15, 13)
#define MT_RXWI_CTL_MPDU_LEN GENMASK(29, 16)
#define MT_RXWI_CTL_EOF BIT(31)
#define MT_RXWI_TID GENMASK(3, 0)
#define MT_RXWI_SN GENMASK(15, 4)
#define MT_RXWI_RATE_INDEX GENMASK(5, 0)
#define MT_RXWI_RATE_LDPC BIT(6)
#define MT_RXWI_RATE_BW GENMASK(8, 7)
#define MT_RXWI_RATE_SGI BIT(9)
#define MT_RXWI_RATE_STBC BIT(10)
#define MT_RXWI_RATE_LDPC_EXSYM BIT(11)
#define MT_RXWI_RATE_PHY GENMASK(15, 13)
#define MT_RATE_INDEX_VHT_IDX GENMASK(3, 0)
#define MT_RATE_INDEX_VHT_NSS GENMASK(5, 4)
#define MT_TX_PWR_ADJ GENMASK(3, 0)
enum mt76x2_phy_bandwidth {
MT_PHY_BW_20,
MT_PHY_BW_40,
MT_PHY_BW_80,
};
#define MT_TXWI_FLAGS_FRAG BIT(0)
#define MT_TXWI_FLAGS_MMPS BIT(1)
#define MT_TXWI_FLAGS_CFACK BIT(2)
#define MT_TXWI_FLAGS_TS BIT(3)
#define MT_TXWI_FLAGS_AMPDU BIT(4)
#define MT_TXWI_FLAGS_MPDU_DENSITY GENMASK(7, 5)
#define MT_TXWI_FLAGS_TXOP GENMASK(9, 8)
#define MT_TXWI_FLAGS_NDPS BIT(10)
#define MT_TXWI_FLAGS_RTSBWSIG BIT(11)
#define MT_TXWI_FLAGS_NDP_BW GENMASK(13, 12)
#define MT_TXWI_FLAGS_SOUND BIT(14)
#define MT_TXWI_FLAGS_TX_RATE_LUT BIT(15)
#define MT_TXWI_ACK_CTL_REQ BIT(0)
#define MT_TXWI_ACK_CTL_NSEQ BIT(1)
#define MT_TXWI_ACK_CTL_BA_WINDOW GENMASK(7, 2)
#define MT_TXWI_PKTID_PROBE BIT(7)
struct mt76x2_txwi {
__le16 flags;
__le16 rate;
u8 ack_ctl;
u8 wcid;
__le16 len_ctl;
__le32 iv;
__le32 eiv;
u8 aid;
u8 txstream;
u8 ctl2;
u8 pktid;
} __packed __aligned(4);
static inline struct mt76x2_tx_info *
mt76x2_skb_tx_info(struct sk_buff *skb)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
return (void *) info->status.status_driver_data;
}
int mt76x2_mac_reset(struct mt76x2_dev *dev, bool hard);
int mt76x2_mac_start(struct mt76x2_dev *dev);
void mt76x2_mac_stop(struct mt76x2_dev *dev, bool force);
void mt76x2_mac_resume(struct mt76x2_dev *dev);
void mt76x2_mac_set_bssid(struct mt76x2_dev *dev, u8 idx, const u8 *addr);
int mt76x2_mac_process_rx(struct mt76x2_dev *dev, struct sk_buff *skb,
void *rxi);
void mt76x2_mac_write_txwi(struct mt76x2_dev *dev, struct mt76x2_txwi *txwi,
struct sk_buff *skb, struct mt76_wcid *wcid,
struct ieee80211_sta *sta);
void mt76x2_mac_wcid_setup(struct mt76x2_dev *dev, u8 idx, u8 vif_idx, u8 *mac);
int mt76x2_mac_wcid_set_key(struct mt76x2_dev *dev, u8 idx,
struct ieee80211_key_conf *key);
void mt76x2_mac_wcid_set_rate(struct mt76x2_dev *dev, struct mt76_wcid *wcid,
const struct ieee80211_tx_rate *rate);
void mt76x2_mac_wcid_set_drop(struct mt76x2_dev *dev, u8 idx, bool drop);
int mt76x2_mac_shared_key_setup(struct mt76x2_dev *dev, u8 vif_idx, u8 key_idx,
struct ieee80211_key_conf *key);
int mt76x2_mac_set_beacon(struct mt76x2_dev *dev, u8 vif_idx,
struct sk_buff *skb);
void mt76x2_mac_set_beacon_enable(struct mt76x2_dev *dev, u8 vif_idx, bool val);
void mt76x2_mac_poll_tx_status(struct mt76x2_dev *dev, bool irq);
void mt76x2_mac_process_tx_status_fifo(struct mt76x2_dev *dev);
void mt76x2_mac_work(struct work_struct *work);
#endif
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
* Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/module.h>
#ifndef __CHECKER__
#define CREATE_TRACE_POINTS
#include "mt76x2_trace.h"
#endif
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment