diff options
author | Kalle Valo <kvalo@codeaurora.org> | 2018-12-13 16:02:19 +0200 |
---|---|---|
committer | Kalle Valo <kvalo@codeaurora.org> | 2018-12-13 16:02:19 +0200 |
commit | 074b145a05835e9f93a52323a4770b70b4b782fd (patch) | |
tree | cd78bcf438bc5bdcb61ec13e0989497c52a558a8 /drivers/net/wireless/mediatek/mt76/mt76x2 | |
parent | d9bbd6a1a56eccb2b1198b8f2008d622982df0a1 (diff) | |
parent | e28487ea84a9c081c6d8d7da319427f7fcc32ff5 (diff) | |
download | linux-074b145a05835e9f93a52323a4770b70b4b782fd.tar.gz linux-074b145a05835e9f93a52323a4770b70b4b782fd.tar.bz2 linux-074b145a05835e9f93a52323a4770b70b4b782fd.zip |
Merge tag 'mt76-for-kvalo-2018-11-30' of https://github.com/nbd168/wireless
first batch of mt76 patches for 4.21
* use the same firmware for mt76x2e and mt76x2u
* mt76x2 fixes
* mt76x0 fixes
* mt76x0e survey support
* more unification between mt76x2 and mt76x0
* mt76x0e AP mode support
* mt76x0e DFS support
* rework and fix tx status handling for mt76x0 and mt76x2
kvalo: fixed a conflict in drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c
and a build problem in drivers/net/wireless/mediatek/mt76/mt76x02_util.c
Diffstat (limited to 'drivers/net/wireless/mediatek/mt76/mt76x2')
22 files changed, 199 insertions, 1974 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/Makefile b/drivers/net/wireless/mediatek/mt76/mt76x2/Makefile index b71bb1049170..9297b850bbba 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/Makefile +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/Makefile @@ -3,11 +3,11 @@ obj-$(CONFIG_MT76x2E) += mt76x2e.o obj-$(CONFIG_MT76x2U) += mt76x2u.o mt76x2-common-y := \ - eeprom.o mac.o init.o phy.o debugfs.o mcu.o + eeprom.o mac.o init.o phy.o mcu.o mt76x2e-y := \ - pci.o pci_main.o pci_init.o pci_tx.o \ - pci_mac.o pci_mcu.o pci_phy.o pci_dfs.o + pci.o pci_main.o pci_init.o pci_mcu.o \ + pci_phy.o mt76x2u-y := \ usb.o usb_init.o usb_main.o usb_mac.o usb_mcu.o \ diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt76x2/debugfs.c deleted file mode 100644 index e8f8ccc0a5ed..000000000000 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/debugfs.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - * 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 mt76x02_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 int read_txpower(struct seq_file *file, void *data) -{ - struct mt76x02_dev *dev = dev_get_drvdata(file->private); - - seq_printf(file, "Target power: %d\n", dev->target_power); - - mt76_seq_puts_array(file, "Delta", dev->target_power_delta, - ARRAY_SIZE(dev->target_power_delta)); - 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) -{ - struct mt76x02_dev *dev = file->private; - struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; - int i; - - seq_printf(file, "allocated sequences:\t%d\n", - dfs_pd->seq_stats.seq_pool_len); - seq_printf(file, "used sequences:\t\t%d\n", - dfs_pd->seq_stats.seq_len); - seq_puts(file, "\n"); - - 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); - seq_printf(file, " sw pattern detected:\t%d\n", - dfs_pd->stats[i].sw_pattern); - } - - 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, -}; - -static int read_agc(struct seq_file *file, void *data) -{ - struct mt76x02_dev *dev = dev_get_drvdata(file->private); - - seq_printf(file, "avg_rssi: %d\n", dev->cal.avg_rssi_all); - seq_printf(file, "low_gain: %d\n", dev->cal.low_gain); - seq_printf(file, "false_cca: %d\n", dev->cal.false_cca); - seq_printf(file, "agc_gain_adjust: %d\n", dev->cal.agc_gain_adjust); - - return 0; -} - -void mt76x2_init_debugfs(struct mt76x02_dev *dev) -{ - struct dentry *dir; - - dir = mt76_register_debugfs(&dev->mt76); - if (!dir) - return; - - debugfs_create_u8("temperature", 0400, dir, &dev->cal.temp); - debugfs_create_bool("tpc", 0600, dir, &dev->enable_tpc); - - debugfs_create_file("ampdu_stat", 0400, dir, dev, &fops_ampdu_stat); - debugfs_create_file("dfs_stats", 0400, dir, dev, &fops_dfs_stat); - debugfs_create_devm_seqfile(dev->mt76.dev, "txpower", dir, - read_txpower); - - debugfs_create_devm_seqfile(dev->mt76.dev, "agc", dir, read_agc); -} -EXPORT_SYMBOL_GPL(mt76x2_init_debugfs); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/dfs.h b/drivers/net/wireless/mediatek/mt76/mt76x2/dfs.h deleted file mode 100644 index 3cb9d1864286..000000000000 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/dfs.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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 __DFS_H -#define __DFS_H - -void mt76x2_dfs_init_params(struct mt76x02_dev *dev); -void mt76x2_dfs_init_detector(struct mt76x02_dev *dev); -void mt76x2_dfs_adjust_agc(struct mt76x02_dev *dev); -void mt76x2_dfs_set_domain(struct mt76x02_dev *dev, - enum nl80211_dfs_regions region); - -#endif /* __DFS_H */ diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c index f39b622d03f4..6f6998561d9d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c @@ -22,17 +22,6 @@ #define EE_FIELD(_name, _value) [MT_EE_##_name] = (_value) | 1 static int -mt76x2_eeprom_copy(struct mt76x02_dev *dev, enum mt76x02_eeprom_field field, - void *dest, int len) -{ - if (field + len > dev->mt76.eeprom.size) - return -1; - - memcpy(dest, dev->mt76.eeprom.data + field, len); - return 0; -} - -static int mt76x2_eeprom_get_macaddr(struct mt76x02_dev *dev) { void *src = dev->mt76.eeprom.data + MT_EE_MAC_ADDR; @@ -378,7 +367,7 @@ mt76x2_get_power_info_2g(struct mt76x02_dev *dev, else delta_idx = 5; - mt76x2_eeprom_copy(dev, offset, data, sizeof(data)); + mt76x02_eeprom_copy(dev, offset, data, sizeof(data)); t->chain[chain].tssi_slope = data[0]; t->chain[chain].tssi_offset = data[1]; @@ -429,7 +418,7 @@ mt76x2_get_power_info_5g(struct mt76x02_dev *dev, else delta_idx = 4; - mt76x2_eeprom_copy(dev, offset, data, sizeof(data)); + mt76x02_eeprom_copy(dev, offset, data, sizeof(data)); t->chain[chain].tssi_slope = data[0]; t->chain[chain].tssi_offset = data[1]; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/init.c index 3c73fdeaf30f..54a9b5fac787 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/init.c @@ -158,38 +158,6 @@ void mt76_write_mac_initvals(struct mt76x02_dev *dev) } EXPORT_SYMBOL_GPL(mt76_write_mac_initvals); -void mt76x2_init_device(struct mt76x02_dev *dev) -{ - struct ieee80211_hw *hw = mt76_hw(dev); - - hw->queues = 4; - hw->max_rates = 1; - hw->max_report_rates = 7; - hw->max_rate_tries = 1; - hw->extra_tx_headroom = 2; - if (mt76_is_usb(dev)) - hw->extra_tx_headroom += sizeof(struct mt76x02_txwi) + - MT_DMA_HDR_LEN; - - hw->sta_data_size = sizeof(struct mt76x02_sta); - hw->vif_data_size = sizeof(struct mt76x02_vif); - - ieee80211_hw_set(hw, SUPPORTS_HT_CCK_RATES); - ieee80211_hw_set(hw, SUPPORTS_REORDERING_BUFFER); - - dev->mt76.sband_2g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; - dev->mt76.sband_5g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; - - dev->mt76.chainmask = 0x202; - dev->mt76.global_wcid.idx = 255; - dev->mt76.global_wcid.hw_key_idx = -1; - dev->slottime = 9; - - /* init antenna configuration */ - dev->mt76.antenna_mask = 3; -} -EXPORT_SYMBOL_GPL(mt76x2_init_device); - void mt76x2_init_txpower(struct mt76x02_dev *dev, struct ieee80211_supported_band *sband) { diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/mac.h b/drivers/net/wireless/mediatek/mt76/mt76x2/mac.h index a31bd49ae6cb..4c8e20bce920 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/mac.h @@ -26,12 +26,5 @@ struct mt76x02_vif; int mt76x2_mac_start(struct mt76x02_dev *dev); void mt76x2_mac_stop(struct mt76x02_dev *dev, bool force); void mt76x2_mac_resume(struct mt76x02_dev *dev); -void mt76x2_mac_set_bssid(struct mt76x02_dev *dev, u8 idx, const u8 *addr); - -int mt76x2_mac_set_beacon(struct mt76x02_dev *dev, u8 vif_idx, - struct sk_buff *skb); -void mt76x2_mac_set_beacon_enable(struct mt76x02_dev *dev, u8 vif_idx, bool val); - -void mt76x2_mac_work(struct work_struct *work); #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x2/mcu.c index 88bd62cfbdf9..cd3e082f486c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/mcu.c @@ -26,7 +26,6 @@ int mt76x2_mcu_set_channel(struct mt76x02_dev *dev, u8 channel, u8 bw, u8 bw_index, bool scan) { - struct sk_buff *skb; struct { u8 idx; u8 scan; @@ -45,21 +44,19 @@ int mt76x2_mcu_set_channel(struct mt76x02_dev *dev, u8 channel, u8 bw, }; /* first set the channel without the extension channel info */ - skb = mt76_mcu_msg_alloc(dev, &msg, sizeof(msg)); - mt76_mcu_send_msg(dev, skb, CMD_SWITCH_CHANNEL_OP, true); + mt76_mcu_send_msg(dev, CMD_SWITCH_CHANNEL_OP, &msg, sizeof(msg), true); usleep_range(5000, 10000); msg.ext_chan = 0xe0 + bw_index; - skb = mt76_mcu_msg_alloc(dev, &msg, sizeof(msg)); - return mt76_mcu_send_msg(dev, skb, CMD_SWITCH_CHANNEL_OP, true); + return mt76_mcu_send_msg(dev, CMD_SWITCH_CHANNEL_OP, &msg, sizeof(msg), + true); } EXPORT_SYMBOL_GPL(mt76x2_mcu_set_channel); int mt76x2_mcu_load_cr(struct mt76x02_dev *dev, u8 type, u8 temp_level, u8 channel) { - struct sk_buff *skb; struct { u8 cr_mode; u8 temp; @@ -80,15 +77,13 @@ int mt76x2_mcu_load_cr(struct mt76x02_dev *dev, u8 type, u8 temp_level, msg.cfg = cpu_to_le32(val); /* first set the channel without the extension channel info */ - skb = mt76_mcu_msg_alloc(dev, &msg, sizeof(msg)); - return mt76_mcu_send_msg(dev, skb, CMD_LOAD_CR, true); + return mt76_mcu_send_msg(dev, CMD_LOAD_CR, &msg, sizeof(msg), true); } EXPORT_SYMBOL_GPL(mt76x2_mcu_load_cr); int mt76x2_mcu_init_gain(struct mt76x02_dev *dev, u8 channel, u32 gain, bool force) { - struct sk_buff *skb; struct { __le32 channel; __le32 gain_val; @@ -100,15 +95,14 @@ int mt76x2_mcu_init_gain(struct mt76x02_dev *dev, u8 channel, u32 gain, if (force) msg.channel |= cpu_to_le32(BIT(31)); - skb = mt76_mcu_msg_alloc(dev, &msg, sizeof(msg)); - return mt76_mcu_send_msg(dev, skb, CMD_INIT_GAIN_OP, true); + return mt76_mcu_send_msg(dev, CMD_INIT_GAIN_OP, &msg, sizeof(msg), + true); } EXPORT_SYMBOL_GPL(mt76x2_mcu_init_gain); int mt76x2_mcu_tssi_comp(struct mt76x02_dev *dev, struct mt76x2_tssi_comp *tssi_data) { - struct sk_buff *skb; struct { __le32 id; struct mt76x2_tssi_comp data; @@ -117,7 +111,7 @@ int mt76x2_mcu_tssi_comp(struct mt76x02_dev *dev, .data = *tssi_data, }; - skb = mt76_mcu_msg_alloc(dev, &msg, sizeof(msg)); - return mt76_mcu_send_msg(dev, skb, CMD_CALIBRATION_OP, true); + return mt76_mcu_send_msg(dev, CMD_CALIBRATION_OP, &msg, sizeof(msg), + true); } EXPORT_SYMBOL_GPL(mt76x2_mcu_tssi_comp); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h b/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h index ab93125f46de..b259e4b50f1e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h @@ -31,14 +31,8 @@ #define MT7662_ROM_PATCH "mt7662_rom_patch.bin" #define MT7662_EEPROM_SIZE 512 -#define MT7662U_FIRMWARE "mediatek/mt7662u.bin" -#define MT7662U_ROM_PATCH "mediatek/mt7662u_rom_patch.bin" - -#define MT_CALIBRATE_INTERVAL HZ - #include "../mt76x02.h" #include "mac.h" -#include "dfs.h" static inline bool is_mt7612(struct mt76x02_dev *dev) { @@ -57,15 +51,12 @@ extern const struct ieee80211_ops mt76x2_ops; struct mt76x02_dev *mt76x2_alloc_device(struct device *pdev); int mt76x2_register_device(struct mt76x02_dev *dev); -void mt76x2_init_debugfs(struct mt76x02_dev *dev); -void mt76x2_init_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); -void mt76x2_set_tx_ackto(struct mt76x02_dev *dev); void mt76x2_phy_set_antenna(struct mt76x02_dev *dev); int mt76x2_phy_start(struct mt76x02_dev *dev); @@ -82,24 +73,17 @@ int mt76x2_mcu_load_cr(struct mt76x02_dev *dev, u8 type, u8 temp_level, void mt76x2_cleanup(struct mt76x02_dev *dev); -void mt76x2_mac_set_tx_protection(struct mt76x02_dev *dev, u32 val); - -void mt76x2_pre_tbtt_tasklet(unsigned long arg); - -void mt76x2_sta_ps(struct mt76_dev *dev, struct ieee80211_sta *sta, bool ps); - -void mt76x2_update_channel(struct mt76_dev *mdev); - void mt76x2_reset_wlan(struct mt76x02_dev *dev, bool enable); void mt76x2_init_txpower(struct mt76x02_dev *dev, struct ieee80211_supported_band *sband); void mt76_write_mac_initvals(struct mt76x02_dev *dev); -void mt76x2_phy_tssi_compensate(struct mt76x02_dev *dev, bool wait); +void mt76x2_phy_tssi_compensate(struct mt76x02_dev *dev); void mt76x2_phy_set_txpower_regs(struct mt76x02_dev *dev, enum nl80211_band band); void mt76x2_configure_tx_delay(struct mt76x02_dev *dev, enum nl80211_band band, u8 bw); void mt76x2_apply_gain_adj(struct mt76x02_dev *dev); +void mt76x2_phy_update_channel_gain(struct mt76x02_dev *dev); #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2u.h b/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2u.h index 6e932b5010ef..0b0075411b34 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2u.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2u.h @@ -43,11 +43,8 @@ int mt76x2u_mac_stop(struct mt76x02_dev *dev); int mt76x2u_phy_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef); void mt76x2u_phy_calibrate(struct work_struct *work); -void mt76x2u_phy_channel_calibrate(struct mt76x02_dev *dev); void mt76x2u_mcu_complete_urb(struct urb *urb); -int mt76x2u_mcu_set_dynamic_vga(struct mt76x02_dev *dev, u8 channel, bool ap, - bool ext, int rssi, u32 false_cca); int mt76x2u_mcu_init(struct mt76x02_dev *dev); int mt76x2u_mcu_fw_init(struct mt76x02_dev *dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_dfs.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_dfs.c deleted file mode 100644 index b56febae8945..000000000000 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_dfs.c +++ /dev/null @@ -1,878 +0,0 @@ -/* - * 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. - */ - -#include "mt76x2.h" - -#define RADAR_SPEC(m, len, el, eh, wl, wh, \ - w_tolerance, tl, th, t_tolerance, \ - bl, bh, event_exp, power_jmp) \ -{ \ - .mode = m, \ - .avg_len = len, \ - .e_low = el, \ - .e_high = eh, \ - .w_low = wl, \ - .w_high = wh, \ - .w_margin = w_tolerance, \ - .t_low = tl, \ - .t_high = th, \ - .t_margin = t_tolerance, \ - .b_low = bl, \ - .b_high = bh, \ - .event_expiration = event_exp, \ - .pwr_jmp = power_jmp \ -} - -static const struct mt76x02_radar_specs etsi_radar_specs[] = { - /* 20MHz */ - RADAR_SPEC(0, 8, 2, 15, 106, 150, 10, 4900, 100096, 10, 0, - 0x7fffffff, 0x155cc0, 0x19cc), - RADAR_SPEC(0, 40, 4, 59, 96, 380, 150, 4900, 100096, 40, 0, - 0x7fffffff, 0x155cc0, 0x19cc), - RADAR_SPEC(3, 60, 20, 46, 300, 640, 80, 4900, 10100, 80, 0, - 0x7fffffff, 0x155cc0, 0x19dd), - RADAR_SPEC(8, 8, 2, 9, 106, 150, 32, 4900, 296704, 32, 0, - 0x7fffffff, 0x2191c0, 0x15cc), - /* 40MHz */ - RADAR_SPEC(0, 8, 2, 15, 106, 150, 10, 4900, 100096, 10, 0, - 0x7fffffff, 0x155cc0, 0x19cc), - RADAR_SPEC(0, 40, 4, 59, 96, 380, 150, 4900, 100096, 40, 0, - 0x7fffffff, 0x155cc0, 0x19cc), - RADAR_SPEC(3, 60, 20, 46, 300, 640, 80, 4900, 10100, 80, 0, - 0x7fffffff, 0x155cc0, 0x19dd), - RADAR_SPEC(8, 8, 2, 9, 106, 150, 32, 4900, 296704, 32, 0, - 0x7fffffff, 0x2191c0, 0x15cc), - /* 80MHz */ - RADAR_SPEC(0, 8, 2, 15, 106, 150, 10, 4900, 100096, 10, 0, - 0x7fffffff, 0x155cc0, 0x19cc), - RADAR_SPEC(0, 40, 4, 59, 96, 380, 150, 4900, 100096, 40, 0, - 0x7fffffff, 0x155cc0, 0x19cc), - RADAR_SPEC(3, 60, 20, 46, 300, 640, 80, 4900, 10100, 80, 0, - 0x7fffffff, 0x155cc0, 0x19dd), - RADAR_SPEC(8, 8, 2, 9, 106, 150, 32, 4900, 296704, 32, 0, - 0x7fffffff, 0x2191c0, 0x15cc) -}; - -static const struct mt76x02_radar_specs fcc_radar_specs[] = { - /* 20MHz */ - RADAR_SPEC(0, 8, 2, 12, 106, 150, 5, 2900, 80100, 5, 0, - 0x7fffffff, 0xfe808, 0x13dc), - RADAR_SPEC(0, 8, 2, 7, 106, 140, 5, 27600, 27900, 5, 0, - 0x7fffffff, 0xfe808, 0x19dd), - RADAR_SPEC(0, 40, 4, 54, 96, 480, 150, 2900, 80100, 40, 0, - 0x7fffffff, 0xfe808, 0x12cc), - RADAR_SPEC(2, 60, 15, 63, 640, 2080, 32, 19600, 40200, 32, 0, - 0x3938700, 0x57bcf00, 0x1289), - /* 40MHz */ - RADAR_SPEC(0, 8, 2, 12, 106, 150, 5, 2900, 80100, 5, 0, - 0x7fffffff, 0xfe808, 0x13dc), - RADAR_SPEC(0, 8, 2, 7, 106, 140, 5, 27600, 27900, 5, 0, - 0x7fffffff, 0xfe808, 0x19dd), - RADAR_SPEC(0, 40, 4, 54, 96, 480, 150, 2900, 80100, 40, 0, - 0x7fffffff, 0xfe808, 0x12cc), - RADAR_SPEC(2, 60, 15, 63, 640, 2080, 32, 19600, 40200, 32, 0, - 0x3938700, 0x57bcf00, 0x1289), - /* 80MHz */ - RADAR_SPEC(0, 8, 2, 14, 106, 150, 15, 2900, 80100, 15, 0, - 0x7fffffff, 0xfe808, 0x16cc), - RADAR_SPEC(0, 8, 2, 7, 106, 140, 5, 27600, 27900, 5, 0, - 0x7fffffff, 0xfe808, 0x19dd), - RADAR_SPEC(0, 40, 4, 54, 96, 480, 150, 2900, 80100, 40, 0, - 0x7fffffff, 0xfe808, 0x12cc), - RADAR_SPEC(2, 60, 15, 63, 640, 2080, 32, 19600, 40200, 32, 0, - 0x3938700, 0x57bcf00, 0x1289) -}; - -static const struct mt76x02_radar_specs jp_w56_radar_specs[] = { - /* 20MHz */ - RADAR_SPEC(0, 8, 2, 7, 106, 150, 5, 2900, 80100, 5, 0, - 0x7fffffff, 0x14c080, 0x13dc), - RADAR_SPEC(0, 8, 2, 7, 106, 140, 5, 27600, 27900, 5, 0, - 0x7fffffff, 0x14c080, 0x19dd), - RADAR_SPEC(0, 40, 4, 44, 96, 480, 150, 2900, 80100, 40, 0, - 0x7fffffff, 0x14c080, 0x12cc), - RADAR_SPEC(2, 60, 15, 48, 940, 2080, 32, 19600, 40200, 32, 0, - 0x3938700, 0X57bcf00, 0x1289), - /* 40MHz */ - RADAR_SPEC(0, 8, 2, 7, 106, 150, 5, 2900, 80100, 5, 0, - 0x7fffffff, 0x14c080, 0x13dc), - RADAR_SPEC(0, 8, 2, 7, 106, 140, 5, 27600, 27900, 5, 0, - 0x7fffffff, 0x14c080, 0x19dd), - RADAR_SPEC(0, 40, 4, 44, 96, 480, 150, 2900, 80100, 40, 0, - 0x7fffffff, 0x14c080, 0x12cc), - RADAR_SPEC(2, 60, 15, 48, 940, 2080, 32, 19600, 40200, 32, 0, - 0x3938700, 0X57bcf00, 0x1289), - /* 80MHz */ - RADAR_SPEC(0, 8, 2, 9, 106, 150, 15, 2900, 80100, 15, 0, - 0x7fffffff, 0x14c080, 0x16cc), - RADAR_SPEC(0, 8, 2, 7, 106, 140, 5, 27600, 27900, 5, 0, - 0x7fffffff, 0x14c080, 0x19dd), - RADAR_SPEC(0, 40, 4, 44, 96, 480, 150, 2900, 80100, 40, 0, - 0x7fffffff, 0x14c080, 0x12cc), - RADAR_SPEC(2, 60, 15, 48, 940, 2080, 32, 19600, 40200, 32, 0, - 0x3938700, 0X57bcf00, 0x1289) -}; - -static const struct mt76x02_radar_specs jp_w53_radar_specs[] = { - /* 20MHz */ - RADAR_SPEC(0, 8, 2, 9, 106, 150, 20, 28400, 77000, 20, 0, - 0x7fffffff, 0x14c080, 0x16cc), - { 0 }, - RADAR_SPEC(0, 40, 4, 44, 96, 200, 150, 28400, 77000, 60, 0, - 0x7fffffff, 0x14c080, 0x16cc), - { 0 }, - /* 40MHz */ - RADAR_SPEC(0, 8, 2, 9, 106, 150, 20, 28400, 77000, 20, 0, - 0x7fffffff, 0x14c080, 0x16cc), - { 0 }, - RADAR_SPEC(0, 40, 4, 44, 96, 200, 150, 28400, 77000, 60, 0, - 0x7fffffff, 0x14c080, 0x16cc), - { 0 }, - /* 80MHz */ - RADAR_SPEC(0, 8, 2, 9, 106, 150, 20, 28400, 77000, 20, 0, - 0x7fffffff, 0x14c080, 0x16cc), - { 0 }, - RADAR_SPEC(0, 40, 4, 44, 96, 200, 150, 28400, 77000, 60, 0, - 0x7fffffff, 0x14c080, 0x16cc), - { 0 } -}; - -static void -mt76x2_dfs_set_capture_mode_ctrl(struct mt76x02_dev *dev, - u8 enable) -{ - u32 data; - - data = (1 << 1) | enable; - mt76_wr(dev, MT_BBP(DFS, 36), data); -} - -static void mt76x2_dfs_seq_pool_put(struct mt76x02_dev *dev, - struct mt76x02_dfs_sequence *seq) -{ - struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; - - list_add(&seq->head, &dfs_pd->seq_pool); - - dfs_pd->seq_stats.seq_pool_len++; - dfs_pd->seq_stats.seq_len--; -} - -static struct mt76x02_dfs_sequence * -mt76x2_dfs_seq_pool_get(struct mt76x02_dev *dev) -{ - struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; - struct mt76x02_dfs_sequence *seq; - - if (list_empty(&dfs_pd->seq_pool)) { - seq = devm_kzalloc(dev->mt76.dev, sizeof(*seq), GFP_ATOMIC); - } else { - seq = list_first_entry(&dfs_pd->seq_pool, - struct mt76x02_dfs_sequence, - head); - list_del(&seq->head); - dfs_pd->seq_stats.seq_pool_len--; - } - if (seq) - dfs_pd->seq_stats.seq_len++; - - return seq; -} - -static int mt76x2_dfs_get_multiple(int val, int frac, int margin) -{ - int remainder, factor; - - if (!frac) - return 0; - - if (abs(val - frac) <= margin) - return 1; - - factor = val / frac; - remainder = val % frac; - - if (remainder > margin) { - if ((frac - remainder) <= margin) - factor++; - else - factor = 0; - } - return factor; -} - -static void mt76x2_dfs_detector_reset(struct mt76x02_dev *dev) -{ - struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; - struct mt76x02_dfs_sequence *seq, *tmp_seq; - int i; - - /* reset hw detector */ - mt76_wr(dev, MT_BBP(DFS, 1), 0xf); - - /* reset sw detector */ - for (i = 0; i < ARRAY_SIZE(dfs_pd->event_rb); i++) { - dfs_pd->event_rb[i].h_rb = 0; - dfs_pd->event_rb[i].t_rb = 0; - } - - list_for_each_entry_safe(seq, tmp_seq, &dfs_pd->sequences, head) { - list_del_init(&seq->head); - mt76x2_dfs_seq_pool_put(dev, seq); - } -} - -static bool mt76x2_dfs_check_chirp(struct mt76x02_dev *dev) -{ - bool ret = false; - u32 current_ts, delta_ts; - struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; - - current_ts = mt76_rr(dev, MT_PBF_LIFE_TIMER); - delta_ts = current_ts - dfs_pd->chirp_pulse_ts; - dfs_pd->chirp_pulse_ts = current_ts; - - /* 12 sec */ - if (delta_ts <= (12 * (1 << 20))) { - if (++dfs_pd->chirp_pulse_cnt > 8) - ret = true; - } else { - dfs_pd->chirp_pulse_cnt = 1; - } - - return ret; -} - -static void mt76x2_dfs_get_hw_pulse(struct mt76x02_dev *dev, - struct mt76x02_dfs_hw_pulse *pulse) -{ - u32 data; - - /* select channel */ - data = (MT_DFS_CH_EN << 16) | pulse->engine; - mt76_wr(dev, MT_BBP(DFS, 0), data); - - /* reported period */ - pulse->period = mt76_rr(dev, MT_BBP(DFS, 19)); - - /* reported width */ - pulse->w1 = mt76_rr(dev, MT_BBP(DFS, 20)); - pulse->w2 = mt76_rr(dev, MT_BBP(DFS, 23)); - - /* reported burst number */ - pulse->burst = mt76_rr(dev, MT_BBP(DFS, 22)); -} - -static bool mt76x2_dfs_check_hw_pulse(struct mt76x02_dev *dev, - struct mt76x02_dfs_hw_pulse *pulse) -{ - bool ret = false; - - if (!pulse->period || !pulse->w1) - return false; - - switch (dev->dfs_pd.region) { - case NL80211_DFS_FCC: - if (pulse->engine > 3) - break; - - if (pulse->engine == 3) { - ret = mt76x2_dfs_check_chirp(dev); - break; - } - - /* check short pulse*/ - if (pulse->w1 < 120) - ret = (pulse->period >= 2900 && - (pulse->period <= 4700 || - pulse->period >= 6400) && - (pulse->period <= 6800 || - pulse->period >= 10200) && - pulse->period <= 61600); - else if (pulse->w1 < 130) /* 120 - 130 */ - ret = (pulse->period >= 2900 && - pulse->period <= 61600); - else - ret = (pulse->period >= 3500 && - pulse->period <= 10100); - break; - case NL80211_DFS_ETSI: - if (pulse->engine >= 3) - break; - - ret = (pulse->period >= 4900 && - (pulse->period <= 10200 || - pulse->period >= 12400) && - pulse->period <= 100100); - break; - case NL80211_DFS_JP: - if (dev->mt76.chandef.chan->center_freq >= 5250 && - dev->mt76.chandef.chan->center_freq <= 5350) { - /* JPW53 */ - if (pulse->w1 <= 130) - ret = (pulse->period >= 28360 && - (pulse->period <= 28700 || - pulse->period >= 76900) && - pulse->period <= 76940); - break; - } - - if (pulse->engine > 3) - break; - - if (pulse->engine == 3) { - ret = mt76x2_dfs_check_chirp(dev); - break; - } - - /* check short pulse*/ - if (pulse->w1 < 120) - ret = (pulse->period >= 2900 && - (pulse->period <= 4700 || - pulse->period >= 6400) && - (pulse->period <= 6800 || - pulse->period >= 27560) && - (pulse->period <= 27960 || - pulse->period >= 28360) && - (pulse->period <= 28700 || - pulse->period >= 79900) && - pulse->period <= 80100); - else if (pulse->w1 < 130) /* 120 - 130 */ - ret = (pulse->period >= 2900 && - (pulse->period <= 10100 || - pulse->period >= 27560) && - (pulse->period <= 27960 || - pulse->period >= 28360) && - (pulse->period <= 28700 || - pulse->period >= 79900) && - pulse->period <= 80100); - else - ret = (pulse->period >= 3900 && - pulse->period <= 10100); - break; - case NL80211_DFS_UNSET: - default: - return false; - } - - return ret; -} - -static bool mt76x2_dfs_fetch_event(struct mt76x02_dev *dev, - struct mt76x02_dfs_event *event) -{ - u32 data; - - /* 1st: DFS_R37[31]: 0 (engine 0) - 1 (engine 2) - * 2nd: DFS_R37[21:0]: pulse time - * 3rd: DFS_R37[11:0]: pulse width - * 3rd: DFS_R37[25:16]: phase - * 4th: DFS_R37[12:0]: current pwr - * 4th: DFS_R37[21:16]: pwr stable counter - * - * 1st: DFS_R37[31:0] set to 0xffffffff means no event detected - */ - data = mt76_rr(dev, MT_BBP(DFS, 37)); - if (!MT_DFS_CHECK_EVENT(data)) - return false; - - event->engine = MT_DFS_EVENT_ENGINE(data); - data = mt76_rr(dev, MT_BBP(DFS, 37)); - event->ts = MT_DFS_EVENT_TIMESTAMP(data); - data = mt76_rr(dev, MT_BBP(DFS, 37)); - event->width = MT_DFS_EVENT_WIDTH(data); - - return true; -} - -static bool mt76x2_dfs_check_event(struct mt76x02_dev *dev, - struct mt76x02_dfs_event *event) -{ - if (event->engine == 2) { - struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; - struct mt76x02_dfs_event_rb *event_buff = &dfs_pd->event_rb[1]; - u16 last_event_idx; - u32 delta_ts; - - last_event_idx = mt76_decr(event_buff->t_rb, - MT_DFS_EVENT_BUFLEN); - delta_ts = event->ts - event_buff->data[last_event_idx].ts; - if (delta_ts < MT_DFS_EVENT_TIME_MARGIN && - event_buff->data[last_event_idx].width >= 200) - return false; - } - return true; -} - -static void mt76x2_dfs_queue_event(struct mt76x02_dev *dev, - struct mt76x02_dfs_event *event) -{ - struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; - struct mt76x02_dfs_event_rb *event_buff; - - /* add radar event to ring buffer */ - event_buff = event->engine == 2 ? &dfs_pd->event_rb[1] - : &dfs_pd->event_rb[0]; - event_buff->data[event_buff->t_rb] = *event; - event_buff->data[event_buff->t_rb].fetch_ts = jiffies; - - event_buff->t_rb = mt76_incr(event_buff->t_rb, MT_DFS_EVENT_BUFLEN); - if (event_buff->t_rb == event_buff->h_rb) - event_buff->h_rb = mt76_incr(event_buff->h_rb, - MT_DFS_EVENT_BUFLEN); -} - -static int mt76x2_dfs_create_sequence(struct mt76x02_dev *dev, - struct mt76x02_dfs_event *event, - u16 cur_len) -{ - struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; - struct mt76x02_dfs_sw_detector_params *sw_params; - u32 width_delta, with_sum, factor, cur_pri; - struct mt76x02_dfs_sequence seq, *seq_p; - struct mt76x02_dfs_event_rb *event_rb; - struct mt76x02_dfs_event *cur_event; - int i, j, end, pri; - - event_rb = event->engine == 2 ? &dfs_pd->event_rb[1] - : &dfs_pd->event_rb[0]; - - i = mt76_decr(event_rb->t_rb, MT_DFS_EVENT_BUFLEN); - end = mt76_decr(event_rb->h_rb, MT_DFS_EVENT_BUFLEN); - - while (i != end) { - cur_event = &event_rb->data[i]; - with_sum = event->width + cur_event->width; - - sw_params = &dfs_pd->sw_dpd_params; - switch (dev->dfs_pd.region) { - case NL80211_DFS_FCC: - case NL80211_DFS_JP: - if (with_sum < 600) - width_delta = 8; - else - width_delta = with_sum >> 3; - break; - case NL80211_DFS_ETSI: - if (event->engine == 2) - width_delta = with_sum >> 6; - else if (with_sum < 620) - width_delta = 24; - else - width_delta = 8; - break; - case NL80211_DFS_UNSET: - default: - return -EINVAL; - } - - pri = event->ts - cur_event->ts; - if (abs(event->width - cur_event->width) > width_delta || - pri < sw_params->min_pri) - goto next; - - if (pri > sw_params->max_pri) - break; - - seq.pri = event->ts - cur_event->ts; - seq.first_ts = cur_event->ts; - seq.last_ts = event->ts; - seq.engine = event->engine; - seq.count = 2; - - j = mt76_decr(i, MT_DFS_EVENT_BUFLEN); - while (j != end) { - cur_event = &event_rb->data[j]; - cur_pri = event->ts - cur_event->ts; - factor = mt76x2_dfs_get_multiple(cur_pri, seq.pri, - sw_params->pri_margin); - if (factor > 0) { - seq.first_ts = cur_event->ts; - seq.count++; - } - - j = mt76_decr(j, MT_DFS_EVENT_BUFLEN); - } - if (seq.count <= cur_len) - goto next; - - seq_p = mt76x2_dfs_seq_pool_get(dev); - if (!seq_p) - return -ENOMEM; - - *seq_p = seq; - INIT_LIST_HEAD(&seq_p->head); - list_add(&seq_p->head, &dfs_pd->sequences); -next: - i = mt76_decr(i, MT_DFS_EVENT_BUFLEN); - } - return 0; -} - -static u16 mt76x2_dfs_add_event_to_sequence(struct mt76x02_dev *dev, - struct mt76x02_dfs_event *event) -{ - struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; - struct mt76x02_dfs_sw_detector_params *sw_params; - struct mt76x02_dfs_sequence *seq, *tmp_seq; - u16 max_seq_len = 0; - u32 factor, pri; - - sw_params = &dfs_pd->sw_dpd_params; - list_for_each_entry_safe(seq, tmp_seq, &dfs_pd->sequences, head) { - if (event->ts > seq->first_ts + MT_DFS_SEQUENCE_WINDOW) { - list_del_init(&seq->head); - mt76x2_dfs_seq_pool_put(dev, seq); - continue; - } - - if (event->engine != seq->engine) - continue; - - pri = event->ts - seq->last_ts; - factor = mt76x2_dfs_get_multiple(pri, seq->pri, - sw_params->pri_margin); - if (factor > 0) { - seq->last_ts = event->ts; - seq->count++; - max_seq_len = max_t(u16, max_seq_len, seq->count); - } - } - return max_seq_len; -} - -static bool mt76x2_dfs_check_detection(struct mt76x02_dev *dev) -{ - struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; - struct mt76x02_dfs_sequence *seq; - - if (list_empty(&dfs_pd->sequences)) - return false; - - list_for_each_entry(seq, &dfs_pd->sequences, head) { - if (seq->count > MT_DFS_SEQUENCE_TH) { - dfs_pd->stats[seq->engine].sw_pattern++; - return true; - } - } - return false; -} - -static void mt76x2_dfs_add_events(struct mt76x02_dev *dev) -{ - struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; - struct mt76x02_dfs_event event; - int i, seq_len; - - /* disable debug mode */ - mt76x2_dfs_set_capture_mode_ctrl(dev, false); - for (i = 0; i < MT_DFS_EVENT_LOOP; i++) { - if (!mt76x2_dfs_fetch_event(dev, &event)) - break; - - if (dfs_pd->last_event_ts > event.ts) - mt76x2_dfs_detector_reset(dev); - dfs_pd->last_event_ts = event.ts; - - if (!mt76x2_dfs_check_event(dev, &event)) - continue; - - seq_len = mt76x2_dfs_add_event_to_sequence(dev, &event); - mt76x2_dfs_create_sequence(dev, &event, seq_len); - - mt76x2_dfs_queue_event(dev, &event); - } - mt76x2_dfs_set_capture_mode_ctrl(dev, true); -} - -static void mt76x2_dfs_check_event_window(struct mt76x02_dev *dev) -{ - struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; - struct mt76x02_dfs_event_rb *event_buff; - struct mt76x02_dfs_event *event; - int i; - - for (i = 0; i < ARRAY_SIZE(dfs_pd->event_rb); i++) { - event_buff = &dfs_pd->event_rb[i]; - - while (event_buff->h_rb != event_buff->t_rb) { - event = &event_buff->data[event_buff->h_rb]; - - /* sorted list */ - if (time_is_after_jiffies(event->fetch_ts + - MT_DFS_EVENT_WINDOW)) - break; - event_buff->h_rb = mt76_incr(event_buff->h_rb, - MT_DFS_EVENT_BUFLEN); - } - } -} - -static void mt76x2_dfs_tasklet(unsigned long arg) -{ - struct mt76x02_dev *dev = (struct mt76x02_dev *)arg; - struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; - u32 engine_mask; - int i; - - if (test_bit(MT76_SCANNING, &dev->mt76.state)) - goto out; - - if (time_is_before_jiffies(dfs_pd->last_sw_check + - MT_DFS_SW_TIMEOUT)) { - bool radar_detected; - - dfs_pd->last_sw_check = jiffies; - - mt76x2_dfs_add_events(dev); - radar_detected = mt76x2_dfs_check_detection(dev); - if (radar_detected) { - /* sw detector rx radar pattern */ - ieee80211_radar_detected(dev->mt76.hw); - mt76x2_dfs_detector_reset(dev); - - return; - } - mt76x2_dfs_check_event_window(dev); - } - - engine_mask = mt76_rr(dev, MT_BBP(DFS, 1)); - if (!(engine_mask & 0xf)) - goto out; - - for (i = 0; i < MT_DFS_NUM_ENGINES; i++) { - struct mt76x02_dfs_hw_pulse pulse; - - if (!(engine_mask & (1 << i))) - continue; - - pulse.engine = i; - mt76x2_dfs_get_hw_pulse(dev, &pulse); - - if (!mt76x2_dfs_check_hw_pulse(dev, &pulse)) { - dfs_pd->stats[i].hw_pulse_discarded++; - continue; - } - - /* hw detector rx radar pattern */ - dfs_pd->stats[i].hw_pattern++; - ieee80211_radar_detected(dev->mt76.hw); - mt76x2_dfs_detector_reset(dev); - - return; - } - - /* reset hw detector */ - mt76_wr(dev, MT_BBP(DFS, 1), 0xf); - -out: - mt76x02_irq_enable(dev, MT_INT_GPTIMER); -} - -static void mt76x2_dfs_init_sw_detector(struct mt76x02_dev *dev) -{ - struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; - - switch (dev->dfs_pd.region) { - case NL80211_DFS_FCC: - dfs_pd->sw_dpd_params.max_pri = MT_DFS_FCC_MAX_PRI; - dfs_pd->sw_dpd_params.min_pri = MT_DFS_FCC_MIN_PRI; - dfs_pd->sw_dpd_params.pri_margin = MT_DFS_PRI_MARGIN; - break; - case NL80211_DFS_ETSI: - dfs_pd->sw_dpd_params.max_pri = MT_DFS_ETSI_MAX_PRI; - dfs_pd->sw_dpd_params.min_pri = MT_DFS_ETSI_MIN_PRI; - dfs_pd->sw_dpd_params.pri_margin = MT_DFS_PRI_MARGIN << 2; - break; - case NL80211_DFS_JP: - dfs_pd->sw_dpd_params.max_pri = MT_DFS_JP_MAX_PRI; - dfs_pd->sw_dpd_params.min_pri = MT_DFS_JP_MIN_PRI; - dfs_pd->sw_dpd_params.pri_margin = MT_DFS_PRI_MARGIN; - break; - case NL80211_DFS_UNSET: - default: - break; - } -} - -static void mt76x2_dfs_set_bbp_params(struct mt76x02_dev *dev) -{ - const struct mt76x02_radar_specs *radar_specs; - u8 i, shift; - u32 data; - - switch (dev->mt76.chandef.width) { - case NL80211_CHAN_WIDTH_40: - shift = MT_DFS_NUM_ENGINES; - break; - case NL80211_CHAN_WIDTH_80: - shift = 2 * MT_DFS_NUM_ENGINES; - break; - default: - shift = 0; - break; - } - - switch (dev->dfs_pd.region) { - case NL80211_DFS_FCC: - radar_specs = &fcc_radar_specs[shift]; - break; - case NL80211_DFS_ETSI: - radar_specs = &etsi_radar_specs[shift]; - break; - case NL80211_DFS_JP: - if (dev->mt76.chandef.chan->center_freq >= 5250 && - dev->mt76.chandef.chan->center_freq <= 5350) - radar_specs = &jp_w53_radar_specs[shift]; - else - radar_specs = &jp_w56_radar_specs[shift]; - break; - case NL80211_DFS_UNSET: - default: - return; - } - - data = (MT_DFS_VGA_MASK << 16) | - (MT_DFS_PWR_GAIN_OFFSET << 12) | - (MT_DFS_PWR_DOWN_TIME << 8) | - (MT_DFS_SYM_ROUND << 4) | - (MT_DFS_DELTA_DELAY & 0xf); - mt76_wr(dev, MT_BBP(DFS, 2), data); - - data = (MT_DFS_RX_PE_MASK << 16) | MT_DFS_PKT_END_MASK; - mt76_wr(dev, MT_BBP(DFS, 3), data); - - for (i = 0; i < MT_DFS_NUM_ENGINES; i++) { - /* configure engine */ - mt76_wr(dev, MT_BBP(DFS, 0), i); - - /* detection mode + avg_len */ - data = ((radar_specs[i].avg_len & 0x1ff) << 16) | - (radar_specs[i].mode & 0xf); - mt76_wr(dev, MT_BBP(DFS, 4), data); - - /* dfs energy */ - data = ((radar_specs[i].e_high & 0x0fff) << 16) | - (radar_specs[i].e_low & 0x0fff); - mt76_wr(dev, MT_BBP(DFS, 5), data); - - /* dfs period */ - mt76_wr(dev, MT_BBP(DFS, 7), radar_specs[i].t_low); - mt76_wr(dev, MT_BBP(DFS, 9), radar_specs[i].t_high); - - /* dfs burst */ - mt76_wr(dev, MT_BBP(DFS, 11), radar_specs[i].b_low); - mt76_wr(dev, MT_BBP(DFS, 13), radar_specs[i].b_high); - - /* dfs width */ - data = ((radar_specs[i].w_high & 0x0fff) << 16) | - (radar_specs[i].w_low & 0x0fff); - mt76_wr(dev, MT_BBP(DFS, 14), data); - - /* dfs margins */ - data = (radar_specs[i].w_margin << 16) | - radar_specs[i].t_margin; - mt76_wr(dev, MT_BBP(DFS, 15), data); - - /* dfs event expiration */ - mt76_wr(dev, MT_BBP(DFS, 17), radar_specs[i].event_expiration); - - /* dfs pwr adj */ - mt76_wr(dev, MT_BBP(DFS, 30), radar_specs[i].pwr_jmp); - } - - /* reset status */ - mt76_wr(dev, MT_BBP(DFS, 1), 0xf); - mt76_wr(dev, MT_BBP(DFS, 36), 0x3); - - /* enable detection*/ - mt76_wr(dev, MT_BBP(DFS, 0), MT_DFS_CH_EN << 16); - mt76_wr(dev, 0x212c, 0x0c350001); -} - -void mt76x2_dfs_adjust_agc(struct mt76x02_dev *dev) -{ - u32 agc_r8, agc_r4, val_r8, val_r4, dfs_r31; - - agc_r8 = mt76_rr(dev, MT_BBP(AGC, 8)); - agc_r4 = mt76_rr(dev, MT_BBP(AGC, 4)); - - val_r8 = (agc_r8 & 0x00007e00) >> 9; - val_r4 = agc_r4 & ~0x1f000000; - val_r4 += (((val_r8 + 1) >> 1) << 24); - mt76_wr(dev, MT_BBP(AGC, 4), val_r4); - - dfs_r31 = FIELD_GET(MT_BBP_AGC_LNA_HIGH_GAIN, val_r4); - dfs_r31 += val_r8; - dfs_r31 -= (agc_r8 & 0x00000038) >> 3; - dfs_r31 = (dfs_r31 << 16) | 0x00000307; - mt76_wr(dev, MT_BBP(DFS, 31), dfs_r31); - - mt76_wr(dev, MT_BBP(DFS, 32), 0x00040071); -} - -void mt76x2_dfs_init_params(struct mt76x02_dev *dev) -{ - struct cfg80211_chan_def *chandef = &dev->mt76.chandef; - - if ((chandef->chan->flags & IEEE80211_CHAN_RADAR) && - dev->dfs_pd.region != NL80211_DFS_UNSET) { - mt76x2_dfs_init_sw_detector(dev); - mt76x2_dfs_set_bbp_params(dev); - /* enable debug mode */ - mt76x2_dfs_set_capture_mode_ctrl(dev, true); - - mt76x02_irq_enable(dev, MT_INT_GPTIMER); - mt76_rmw_field(dev, MT_INT_TIMER_EN, - MT_INT_TIMER_EN_GP_TIMER_EN, 1); - } else { - /* disable hw detector */ - mt76_wr(dev, MT_BBP(DFS, 0), 0); - /* clear detector status */ - mt76_wr(dev, MT_BBP(DFS, 1), 0xf); - mt76_wr(dev, 0x212c, 0); - - mt76x02_irq_disable(dev, MT_INT_GPTIMER); - mt76_rmw_field(dev, MT_INT_TIMER_EN, - MT_INT_TIMER_EN_GP_TIMER_EN, 0); - } -} - -void mt76x2_dfs_init_detector(struct mt76x02_dev *dev) -{ - struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; - - INIT_LIST_HEAD(&dfs_pd->sequences); - INIT_LIST_HEAD(&dfs_pd->seq_pool); - dfs_pd->region = NL80211_DFS_UNSET; - dfs_pd->last_sw_check = jiffies; - tasklet_init(&dfs_pd->dfs_tasklet, mt76x2_dfs_tasklet, - (unsigned long)dev); -} - -void mt76x2_dfs_set_domain(struct mt76x02_dev *dev, - enum nl80211_dfs_regions region) -{ - struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; - - if (dfs_pd->region != region) { - tasklet_disable(&dfs_pd->dfs_tasklet); - dfs_pd->region = region; - mt76x2_dfs_init_params(dev); - tasklet_enable(&dfs_pd->dfs_tasklet); - } -} - diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c index fd125722d1fb..7f4ea2d00f42 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c @@ -79,7 +79,6 @@ mt76x2_fixup_xtal(struct mt76x02_dev *dev) static int mt76x2_mac_reset(struct mt76x02_dev *dev, bool hard) { - static const u8 null_addr[ETH_ALEN] = {}; const u8 *macaddr = dev->mt76.macaddr; u32 val; int i, k; @@ -123,27 +122,18 @@ static int mt76x2_mac_reset(struct mt76x02_dev *dev, bool hard) mt76_wr(dev, MT_MAC_ADDR_DW0, get_unaligned_le32(macaddr)); mt76_wr(dev, MT_MAC_ADDR_DW1, get_unaligned_le16(macaddr + 4)); - mt76_wr(dev, MT_MAC_BSSID_DW0, get_unaligned_le32(macaddr)); - mt76_wr(dev, MT_MAC_BSSID_DW1, get_unaligned_le16(macaddr + 4) | - FIELD_PREP(MT_MAC_BSSID_DW1_MBSS_MODE, 3) | /* 8 beacons */ - MT_MAC_BSSID_DW1_MBSS_LOCAL_BIT); - - /* Fire a pre-TBTT interrupt 8 ms before TBTT */ - mt76_rmw_field(dev, MT_INT_TIMER_CFG, MT_INT_TIMER_CFG_PRE_TBTT, - 8 << 4); - mt76_rmw_field(dev, MT_INT_TIMER_CFG, MT_INT_TIMER_CFG_GP_TIMER, - MT_DFS_GP_INTERVAL); - mt76_wr(dev, MT_INT_TIMER_EN, 0); - - mt76_wr(dev, MT_BCN_BYPASS_MASK, 0xffff); + mt76x02_init_beacon_config(dev); if (!hard) return 0; for (i = 0; i < 256 / 32; i++) mt76_wr(dev, MT_WCID_DROP_BASE + i * 4, 0); - for (i = 0; i < 256; i++) + for (i = 0; i < 256; i++) { mt76x02_mac_wcid_setup(dev, i, 0, NULL); + mt76_wr(dev, MT_WCID_TX_RATE(i), 0); + mt76_wr(dev, MT_WCID_TX_RATE(i) + 4, 0); + } for (i = 0; i < MT_MAX_VIFS; i++) mt76x02_mac_wcid_setup(dev, MT_VIF_WCID(i), i, NULL); @@ -152,11 +142,6 @@ static int mt76x2_mac_reset(struct mt76x02_dev *dev, bool hard) for (k = 0; k < 4; k++) mt76x02_mac_shared_key_setup(dev, i, k, NULL); - for (i = 0; i < 8; i++) { - mt76x2_mac_set_bssid(dev, i, null_addr); - mt76x2_mac_set_beacon(dev, i, NULL); - } - for (i = 0; i < 16; i++) mt76_rr(dev, MT_TX_STAT_FIFO); @@ -168,9 +153,7 @@ static int mt76x2_mac_reset(struct mt76x02_dev *dev, bool hard) MT_CH_TIME_CFG_EIFS_AS_BUSY | FIELD_PREP(MT_CH_TIME_CFG_CH_TIMER_CLR, 1)); - mt76x02_set_beacon_offsets(dev); - - mt76x2_set_tx_ackto(dev); + mt76x02_set_tx_ackto(dev); return 0; } @@ -277,30 +260,10 @@ mt76x2_power_on(struct mt76x02_dev *dev) mt76x2_power_on_rf(dev, 1); } -void mt76x2_set_tx_ackto(struct mt76x02_dev *dev) -{ - u8 ackto, sifs, slottime = dev->slottime; - - /* As defined by IEEE 802.11-2007 17.3.8.6 */ - slottime += 3 * dev->coverage_class; - mt76_rmw_field(dev, MT_BKOFF_SLOT_CFG, - MT_BKOFF_SLOT_CFG_SLOTTIME, slottime); - - sifs = mt76_get_field(dev, MT_XIFS_TIME_CFG, - MT_XIFS_TIME_CFG_OFDM_SIFS); - - ackto = slottime + sifs; - mt76_rmw_field(dev, MT_TX_TIMEOUT_CFG, - MT_TX_TIMEOUT_CFG_ACKTO, ackto); -} - int mt76x2_init_hardware(struct mt76x02_dev *dev) { int ret; - tasklet_init(&dev->pre_tbtt_tasklet, mt76x2_pre_tbtt_tasklet, - (unsigned long) dev); - mt76x02_dma_disable(dev); mt76x2_reset_wlan(dev, true); mt76x2_power_on(dev); @@ -337,7 +300,7 @@ void mt76x2_stop_hardware(struct mt76x02_dev *dev) { cancel_delayed_work_sync(&dev->cal_work); cancel_delayed_work_sync(&dev->mac_work); - mt76x02_mcu_set_radio_state(dev, false, true); + mt76x02_mcu_set_radio_state(dev, false); mt76x2_mac_stop(dev, false); } @@ -354,12 +317,14 @@ struct mt76x02_dev *mt76x2_alloc_device(struct device *pdev) { static const struct mt76_driver_ops drv_ops = { .txwi_size = sizeof(struct mt76x02_txwi), - .update_survey = mt76x2_update_channel, + .update_survey = mt76x02_update_channel, .tx_prepare_skb = mt76x02_tx_prepare_skb, .tx_complete_skb = mt76x02_tx_complete_skb, .rx_skb = mt76x02_queue_rx_skb, .rx_poll_complete = mt76x02_rx_poll_complete, - .sta_ps = mt76x2_sta_ps, + .sta_ps = mt76x02_sta_ps, + .sta_add = mt76x02_sta_add, + .sta_remove = mt76x02_sta_remove, }; struct mt76x02_dev *dev; struct mt76_dev *mdev; @@ -375,43 +340,6 @@ struct mt76x02_dev *mt76x2_alloc_device(struct device *pdev) return dev; } -static void mt76x2_regd_notifier(struct wiphy *wiphy, - struct regulatory_request *request) -{ - struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); - struct mt76x02_dev *dev = hw->priv; - - mt76x2_dfs_set_domain(dev, request->dfs_region); -} - -static const struct ieee80211_iface_limit if_limits[] = { - { - .max = 1, - .types = BIT(NL80211_IFTYPE_ADHOC) - }, { - .max = 8, - .types = BIT(NL80211_IFTYPE_STATION) | -#ifdef CONFIG_MAC80211_MESH - BIT(NL80211_IFTYPE_MESH_POINT) | -#endif - BIT(NL80211_IFTYPE_AP) - }, -}; - -static const struct ieee80211_iface_combination if_comb[] = { - { - .limits = if_limits, - .n_limits = ARRAY_SIZE(if_limits), - .max_interfaces = 8, - .num_different_channels = 1, - .beacon_int_infra_match = true, - .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | - BIT(NL80211_CHAN_WIDTH_20) | - BIT(NL80211_CHAN_WIDTH_40) | - BIT(NL80211_CHAN_WIDTH_80), - } -}; - static void mt76x2_led_set_config(struct mt76_dev *mt76, u8 delay_on, u8 delay_off) { @@ -462,49 +390,17 @@ static void mt76x2_led_set_brightness(struct led_classdev *led_cdev, int mt76x2_register_device(struct mt76x02_dev *dev) { - struct ieee80211_hw *hw = mt76_hw(dev); - struct wiphy *wiphy = hw->wiphy; - int i, ret; + int ret; INIT_DELAYED_WORK(&dev->cal_work, mt76x2_phy_calibrate); - INIT_DELAYED_WORK(&dev->mac_work, mt76x2_mac_work); - mt76x2_init_device(dev); + mt76x02_init_device(dev); ret = mt76x2_init_hardware(dev); if (ret) return ret; - for (i = 0; i < ARRAY_SIZE(dev->macaddr_list); i++) { - u8 *addr = dev->macaddr_list[i].addr; - - memcpy(addr, dev->mt76.macaddr, ETH_ALEN); - - if (!i) - continue; - - addr[0] |= BIT(1); - addr[0] ^= ((i - 1) << 2); - } - wiphy->addresses = dev->macaddr_list; - wiphy->n_addresses = ARRAY_SIZE(dev->macaddr_list); - - wiphy->iface_combinations = if_comb; - wiphy->n_iface_combinations = ARRAY_SIZE(if_comb); - - wiphy->reg_notifier = mt76x2_regd_notifier; - - wiphy->interface_modes = - BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_AP) | -#ifdef CONFIG_MAC80211_MESH - BIT(NL80211_IFTYPE_MESH_POINT) | -#endif - BIT(NL80211_IFTYPE_ADHOC); - - wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS); - - mt76x2_dfs_init_detector(dev); + mt76x02_config_mac_addr_list(dev); /* init led callbacks */ if (IS_ENABLED(CONFIG_MT76_LEDS)) { @@ -517,7 +413,7 @@ int mt76x2_register_device(struct mt76x02_dev *dev) if (ret) goto fail; - mt76x2_init_debugfs(dev); + mt76x02_init_debugfs(dev); mt76x2_init_txpower(dev, &dev->mt76.sband_2g.sband); mt76x2_init_txpower(dev, &dev->mt76.sband_5g.sband); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_mac.c deleted file mode 100644 index 4b331ed14bb2..000000000000 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_mac.c +++ /dev/null @@ -1,203 +0,0 @@ -/* - * 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 "mcu.h" -#include "eeprom.h" - -void mt76x2_mac_set_bssid(struct mt76x02_dev *dev, u8 idx, const u8 *addr) -{ - idx &= 7; - mt76_wr(dev, MT_MAC_APC_BSSID_L(idx), get_unaligned_le32(addr)); - mt76_rmw_field(dev, MT_MAC_APC_BSSID_H(idx), MT_MAC_APC_BSSID_H_ADDR, - get_unaligned_le16(addr + 4)); -} - -static int -mt76_write_beacon(struct mt76x02_dev *dev, int offset, struct sk_buff *skb) -{ - int beacon_len = mt76x02_beacon_offsets[1] - mt76x02_beacon_offsets[0]; - struct mt76x02_txwi txwi; - - if (WARN_ON_ONCE(beacon_len < skb->len + sizeof(struct mt76x02_txwi))) - return -ENOSPC; - - mt76x02_mac_write_txwi(dev, &txwi, skb, NULL, NULL, skb->len); - - mt76_wr_copy(dev, offset, &txwi, sizeof(txwi)); - offset += sizeof(txwi); - - mt76_wr_copy(dev, offset, skb->data, skb->len); - return 0; -} - -static int -__mt76x2_mac_set_beacon(struct mt76x02_dev *dev, u8 bcn_idx, struct sk_buff *skb) -{ - int beacon_len = mt76x02_beacon_offsets[1] - mt76x02_beacon_offsets[0]; - int beacon_addr = mt76x02_beacon_offsets[bcn_idx]; - int ret = 0; - int i; - - /* Prevent corrupt transmissions during update */ - mt76_set(dev, MT_BCN_BYPASS_MASK, BIT(bcn_idx)); - - if (skb) { - ret = mt76_write_beacon(dev, beacon_addr, skb); - if (!ret) - dev->beacon_data_mask |= BIT(bcn_idx); - } else { - dev->beacon_data_mask &= ~BIT(bcn_idx); - for (i = 0; i < beacon_len; i += 4) - mt76_wr(dev, beacon_addr + i, 0); - } - - mt76_wr(dev, MT_BCN_BYPASS_MASK, 0xff00 | ~dev->beacon_data_mask); - - return ret; -} - -int mt76x2_mac_set_beacon(struct mt76x02_dev *dev, u8 vif_idx, - struct sk_buff *skb) -{ - bool force_update = false; - int bcn_idx = 0; - int i; - - for (i = 0; i < ARRAY_SIZE(dev->beacons); i++) { - if (vif_idx == i) { - force_update = !!dev->beacons[i] ^ !!skb; - - if (dev->beacons[i]) - dev_kfree_skb(dev->beacons[i]); - - dev->beacons[i] = skb; - __mt76x2_mac_set_beacon(dev, bcn_idx, skb); - } else if (force_update && dev->beacons[i]) { - __mt76x2_mac_set_beacon(dev, bcn_idx, dev->beacons[i]); - } - - bcn_idx += !!dev->beacons[i]; - } - - for (i = bcn_idx; i < ARRAY_SIZE(dev->beacons); i++) { - if (!(dev->beacon_data_mask & BIT(i))) - break; - - __mt76x2_mac_set_beacon(dev, i, NULL); - } - - mt76_rmw_field(dev, MT_MAC_BSSID_DW1, MT_MAC_BSSID_DW1_MBEACON_N, - bcn_idx - 1); - return 0; -} - -void mt76x2_mac_set_beacon_enable(struct mt76x02_dev *dev, - u8 vif_idx, bool val) -{ - u8 old_mask = dev->beacon_mask; - bool en; - u32 reg; - - if (val) { - dev->beacon_mask |= BIT(vif_idx); - } else { - dev->beacon_mask &= ~BIT(vif_idx); - mt76x2_mac_set_beacon(dev, vif_idx, NULL); - } - - if (!!old_mask == !!dev->beacon_mask) - return; - - en = dev->beacon_mask; - - mt76_rmw_field(dev, MT_INT_TIMER_EN, MT_INT_TIMER_EN_PRE_TBTT_EN, en); - reg = MT_BEACON_TIME_CFG_BEACON_TX | - MT_BEACON_TIME_CFG_TBTT_EN | - MT_BEACON_TIME_CFG_TIMER_EN; - mt76_rmw(dev, MT_BEACON_TIME_CFG, reg, reg * en); - - if (en) - mt76x02_irq_enable(dev, MT_INT_PRE_TBTT | MT_INT_TBTT); - else - mt76x02_irq_disable(dev, MT_INT_PRE_TBTT | MT_INT_TBTT); -} - -void mt76x2_update_channel(struct mt76_dev *mdev) -{ - struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76); - struct mt76_channel_state *state; - u32 active, busy; - - state = mt76_channel_state(&dev->mt76, dev->mt76.chandef.chan); - - busy = mt76_rr(dev, MT_CH_BUSY); - active = busy + mt76_rr(dev, MT_CH_IDLE); - - spin_lock_bh(&dev->mt76.cc_lock); - state->cc_busy += busy; - state->cc_active += active; - spin_unlock_bh(&dev->mt76.cc_lock); -} - -void mt76x2_mac_work(struct work_struct *work) -{ - struct mt76x02_dev *dev = container_of(work, struct mt76x02_dev, - mac_work.work); - int i, idx; - - mt76x2_update_channel(&dev->mt76); - for (i = 0, idx = 0; i < 16; i++) { - u32 val = mt76_rr(dev, MT_TX_AGG_CNT(i)); - - dev->aggr_stats[idx++] += val & 0xffff; - dev->aggr_stats[idx++] += val >> 16; - } - - ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work, - MT_CALIBRATE_INTERVAL); -} - -void mt76x2_mac_set_tx_protection(struct mt76x02_dev *dev, u32 val) -{ - u32 data = 0; - - if (val != ~0) - data = FIELD_PREP(MT_PROT_CFG_CTRL, 1) | - MT_PROT_CFG_RTS_THRESH; - - mt76_rmw_field(dev, MT_TX_RTS_CFG, MT_TX_RTS_CFG_THRESH, val); - - mt76_rmw(dev, MT_CCK_PROT_CFG, - 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); -} diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c index 3f001bd6806c..b54a32397486 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c @@ -74,7 +74,7 @@ mt76x2_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef) mt76_rr(dev, MT_CH_IDLE); mt76_rr(dev, MT_CH_BUSY); - mt76x2_dfs_init_params(dev); + mt76x02_dfs_init_params(dev); mt76x2_mac_resume(dev); tasklet_enable(&dev->dfs_pd.dfs_tasklet); @@ -128,103 +128,12 @@ mt76x2_config(struct ieee80211_hw *hw, u32 changed) } static void -mt76x2_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_bss_conf *info, u32 changed) -{ - struct mt76x02_dev *dev = hw->priv; - struct mt76x02_vif *mvif = (struct mt76x02_vif *) vif->drv_priv; - - mutex_lock(&dev->mt76.mutex); - - if (changed & BSS_CHANGED_BSSID) - mt76x2_mac_set_bssid(dev, mvif->idx, info->bssid); - - if (changed & BSS_CHANGED_BEACON_INT) { - mt76_rmw_field(dev, MT_BEACON_TIME_CFG, - MT_BEACON_TIME_CFG_INTVAL, - info->beacon_int << 4); - dev->beacon_int = info->beacon_int; - dev->tbtt_count = 0; - } - - if (changed & BSS_CHANGED_BEACON_ENABLED) { - tasklet_disable(&dev->pre_tbtt_tasklet); - mt76x2_mac_set_beacon_enable(dev, mvif->idx, - info->enable_beacon); - tasklet_enable(&dev->pre_tbtt_tasklet); - } - - if (changed & BSS_CHANGED_ERP_SLOT) { - int slottime = info->use_short_slot ? 9 : 20; - - dev->slottime = slottime; - mt76x2_set_tx_ackto(dev); - } - - mutex_unlock(&dev->mt76.mutex); -} - -void -mt76x2_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps) -{ - struct mt76x02_sta *msta = (struct mt76x02_sta *) sta->drv_priv; - struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76); - int idx = msta->wcid.idx; - - mt76_stop_tx_queues(&dev->mt76, sta, true); - mt76x02_mac_wcid_set_drop(dev, idx, ps); -} - -static void -mt76x2_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - const u8 *mac) -{ - struct mt76x02_dev *dev = hw->priv; - - tasklet_disable(&dev->pre_tbtt_tasklet); - set_bit(MT76_SCANNING, &dev->mt76.state); -} - -static void -mt76x2_sw_scan_complete(struct ieee80211_hw *hw, struct ieee80211_vif *vif) -{ - struct mt76x02_dev *dev = hw->priv; - - clear_bit(MT76_SCANNING, &dev->mt76.state); - tasklet_enable(&dev->pre_tbtt_tasklet); -} - -static void mt76x2_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u32 queues, bool drop) { } static int -mt76x2_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int *dbm) -{ - struct mt76x02_dev *dev = hw->priv; - - *dbm = dev->mt76.txpower_cur / 2; - - /* convert from per-chain power to combined output on 2x2 devices */ - *dbm += 3; - - return 0; -} - -static void mt76x2_set_coverage_class(struct ieee80211_hw *hw, - s16 coverage_class) -{ - struct mt76x02_dev *dev = hw->priv; - - mutex_lock(&dev->mt76.mutex); - dev->coverage_class = coverage_class; - mt76x2_set_tx_ackto(dev); - mutex_unlock(&dev->mt76.mutex); -} - -static int mt76x2_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set) { return 0; @@ -264,21 +173,6 @@ static int mt76x2_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, return 0; } -static int -mt76x2_set_rts_threshold(struct ieee80211_hw *hw, u32 val) -{ - struct mt76x02_dev *dev = hw->priv; - - if (val != ~0 && val > 0xffff) - return -EINVAL; - - mutex_lock(&dev->mt76.mutex); - mt76x2_mac_set_tx_protection(dev, val); - mutex_unlock(&dev->mt76.mutex); - - return 0; -} - const struct ieee80211_ops mt76x2_ops = { .tx = mt76x02_tx, .start = mt76x2_start, @@ -287,24 +181,23 @@ const struct ieee80211_ops mt76x2_ops = { .remove_interface = mt76x02_remove_interface, .config = mt76x2_config, .configure_filter = mt76x02_configure_filter, - .bss_info_changed = mt76x2_bss_info_changed, - .sta_add = mt76x02_sta_add, - .sta_remove = mt76x02_sta_remove, + .bss_info_changed = mt76x02_bss_info_changed, + .sta_state = mt76_sta_state, .set_key = mt76x02_set_key, .conf_tx = mt76x02_conf_tx, - .sw_scan_start = mt76x2_sw_scan, - .sw_scan_complete = mt76x2_sw_scan_complete, + .sw_scan_start = mt76x02_sw_scan, + .sw_scan_complete = mt76x02_sw_scan_complete, .flush = mt76x2_flush, .ampdu_action = mt76x02_ampdu_action, - .get_txpower = mt76x2_get_txpower, + .get_txpower = mt76x02_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, - .set_coverage_class = mt76x2_set_coverage_class, + .set_coverage_class = mt76x02_set_coverage_class, .get_survey = mt76_get_survey, .set_tim = mt76x2_set_tim, .set_antenna = mt76x2_set_antenna, .get_antenna = mt76x2_get_antenna, - .set_rts_threshold = mt76x2_set_rts_threshold, + .set_rts_threshold = mt76x02_set_rts_threshold, }; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_mcu.c index d8fa9ba56437..03e24ae7f66c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_mcu.c @@ -168,7 +168,6 @@ error: int mt76x2_mcu_init(struct mt76x02_dev *dev) { static const struct mt76_mcu_ops mt76x2_mcu_ops = { - .mcu_msg_alloc = mt76x02_mcu_msg_alloc, .mcu_send_msg = mt76x02_mcu_msg_send, }; int ret; @@ -183,6 +182,6 @@ int mt76x2_mcu_init(struct mt76x02_dev *dev) if (ret) return ret; - mt76x02_mcu_function_select(dev, Q_SELECT, 1, true); + mt76x02_mcu_function_select(dev, Q_SELECT, 1); return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c index 5bda44540225..da7cd40f56ff 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c @@ -38,7 +38,7 @@ mt76x2_phy_tssi_init_cal(struct mt76x02_dev *dev) if (mt76x02_ext_pa_enabled(dev, chan->band)) flag |= BIT(8); - mt76x02_mcu_calibrate(dev, MCU_CAL_TSSI, flag, true); + mt76x02_mcu_calibrate(dev, MCU_CAL_TSSI, flag); dev->cal.tssi_cal_done = true; return true; } @@ -62,13 +62,13 @@ mt76x2_phy_channel_calibrate(struct mt76x02_dev *dev, bool mac_stopped) mt76x2_mac_stop(dev, false); if (is_5ghz) - mt76x02_mcu_calibrate(dev, MCU_CAL_LC, 0, true); + mt76x02_mcu_calibrate(dev, MCU_CAL_LC, 0); - mt76x02_mcu_calibrate(dev, MCU_CAL_TX_LOFT, is_5ghz, true); - mt76x02_mcu_calibrate(dev, MCU_CAL_TXIQ, is_5ghz, true); - mt76x02_mcu_calibrate(dev, MCU_CAL_RXIQC_FI, is_5ghz, true); - mt76x02_mcu_calibrate(dev, MCU_CAL_TEMP_SENSOR, 0, true); - mt76x02_mcu_calibrate(dev, MCU_CAL_TX_SHAPING, 0, true); + mt76x02_mcu_calibrate(dev, MCU_CAL_TX_LOFT, is_5ghz); + mt76x02_mcu_calibrate(dev, MCU_CAL_TXIQ, is_5ghz); + mt76x02_mcu_calibrate(dev, MCU_CAL_RXIQC_FI, is_5ghz); + mt76x02_mcu_calibrate(dev, MCU_CAL_TEMP_SENSOR, 0); + mt76x02_mcu_calibrate(dev, MCU_CAL_TX_SHAPING, 0); if (!mac_stopped) mt76x2_mac_resume(dev); @@ -124,96 +124,6 @@ void mt76x2_phy_set_antenna(struct mt76x02_dev *dev) mt76_wr(dev, MT_BBP(AGC, 0), val); } -static void -mt76x2_phy_set_gain_val(struct mt76x02_dev *dev) -{ - u32 val; - u8 gain_val[2]; - - gain_val[0] = dev->cal.agc_gain_cur[0] - dev->cal.agc_gain_adjust; - gain_val[1] = dev->cal.agc_gain_cur[1] - dev->cal.agc_gain_adjust; - - if (dev->mt76.chandef.width >= NL80211_CHAN_WIDTH_40) - val = 0x1e42 << 16; - else - val = 0x1836 << 16; - - val |= 0xf8; - - mt76_wr(dev, MT_BBP(AGC, 8), - val | FIELD_PREP(MT_BBP_AGC_GAIN, gain_val[0])); - mt76_wr(dev, MT_BBP(AGC, 9), - val | FIELD_PREP(MT_BBP_AGC_GAIN, gain_val[1])); - - if (dev->mt76.chandef.chan->flags & IEEE80211_CHAN_RADAR) - mt76x2_dfs_adjust_agc(dev); -} - -static void -mt76x2_phy_update_channel_gain(struct mt76x02_dev *dev) -{ - u8 *gain = dev->cal.agc_gain_init; - u8 low_gain_delta, gain_delta; - bool gain_change; - int low_gain; - u32 val; - - dev->cal.avg_rssi_all = mt76x02_phy_get_min_avg_rssi(dev); - - 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)); - - gain_change = (dev->cal.low_gain & 2) ^ (low_gain & 2); - dev->cal.low_gain = low_gain; - - if (!gain_change) { - if (mt76x02_phy_adjust_vga_gain(dev)) - mt76x2_phy_set_gain_val(dev); - return; - } - - if (dev->mt76.chandef.width == NL80211_CHAN_WIDTH_80) { - mt76_wr(dev, MT_BBP(RXO, 14), 0x00560211); - val = mt76_rr(dev, MT_BBP(AGC, 26)) & ~0xf; - if (low_gain == 2) - val |= 0x3; - else - val |= 0x5; - mt76_wr(dev, MT_BBP(AGC, 26), val); - } else { - mt76_wr(dev, MT_BBP(RXO, 14), 0x00560423); - } - - if (mt76x2_has_ext_lna(dev)) - low_gain_delta = 10; - else - low_gain_delta = 14; - - if (low_gain == 2) { - mt76_wr(dev, MT_BBP(RXO, 18), 0xf000a990); - mt76_wr(dev, MT_BBP(AGC, 35), 0x08080808); - mt76_wr(dev, MT_BBP(AGC, 37), 0x08080808); - gain_delta = low_gain_delta; - dev->cal.agc_gain_adjust = 0; - } else { - mt76_wr(dev, MT_BBP(RXO, 18), 0xf000a991); - if (dev->mt76.chandef.width == NL80211_CHAN_WIDTH_80) - mt76_wr(dev, MT_BBP(AGC, 35), 0x10101014); - else - mt76_wr(dev, MT_BBP(AGC, 35), 0x11111116); - mt76_wr(dev, MT_BBP(AGC, 37), 0x2121262C); - gain_delta = 0; - dev->cal.agc_gain_adjust = low_gain_delta; - } - - dev->cal.agc_gain_cur[0] = gain[0] - gain_delta; - dev->cal.agc_gain_cur[1] = gain[1] - gain_delta; - mt76x2_phy_set_gain_val(dev); - - /* clear false CCA counters */ - mt76_rr(dev, MT_RX_STAT_1); -} - int mt76x2_phy_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef) { @@ -313,14 +223,14 @@ int mt76x2_phy_set_channel(struct mt76x02_dev *dev, u8 val = mt76x02_eeprom_get(dev, MT_EE_BT_RCAL_RESULT); if (val != 0xff) - mt76x02_mcu_calibrate(dev, MCU_CAL_R, 0, true); + mt76x02_mcu_calibrate(dev, MCU_CAL_R, 0); } - mt76x02_mcu_calibrate(dev, MCU_CAL_RXDCOC, channel, true); + mt76x02_mcu_calibrate(dev, MCU_CAL_RXDCOC, channel); /* Rx LPF calibration */ if (!dev->cal.init_cal_done) - mt76x02_mcu_calibrate(dev, MCU_CAL_RC, 0, true); + mt76x02_mcu_calibrate(dev, MCU_CAL_RC, 0); dev->cal.init_cal_done = true; @@ -384,7 +294,7 @@ void mt76x2_phy_calibrate(struct work_struct *work) dev = container_of(work, struct mt76x02_dev, cal_work.work); mt76x2_phy_channel_calibrate(dev, false); - mt76x2_phy_tssi_compensate(dev, true); + mt76x2_phy_tssi_compensate(dev); mt76x2_phy_temp_compensate(dev); mt76x2_phy_update_channel_gain(dev); ieee80211_queue_delayed_work(mt76_hw(dev), &dev->cal_work, @@ -395,7 +305,7 @@ int mt76x2_phy_start(struct mt76x02_dev *dev) { int ret; - ret = mt76x02_mcu_set_radio_state(dev, true, true); + ret = mt76x02_mcu_set_radio_state(dev, true); if (ret) return ret; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_tx.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_tx.c deleted file mode 100644 index 3a2ec86d3e88..000000000000 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_tx.c +++ /dev/null @@ -1,142 +0,0 @@ -/* - * 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" - -struct beacon_bc_data { - struct mt76x02_dev *dev; - struct sk_buff_head q; - struct sk_buff *tail[8]; -}; - -static void -mt76x2_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) -{ - struct mt76x02_dev *dev = (struct mt76x02_dev *) priv; - struct mt76x02_vif *mvif = (struct mt76x02_vif *) vif->drv_priv; - struct sk_buff *skb = NULL; - - if (!(dev->beacon_mask & BIT(mvif->idx))) - return; - - skb = ieee80211_beacon_get(mt76_hw(dev), vif); - if (!skb) - return; - - mt76x2_mac_set_beacon(dev, mvif->idx, skb); -} - -static void -mt76x2_add_buffered_bc(void *priv, u8 *mac, struct ieee80211_vif *vif) -{ - struct beacon_bc_data *data = priv; - struct mt76x02_dev *dev = data->dev; - struct mt76x02_vif *mvif = (struct mt76x02_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; -} - -static void -mt76x2_resync_beacon_timer(struct mt76x02_dev *dev) -{ - u32 timer_val = dev->beacon_int << 4; - - dev->tbtt_count++; - - /* - * Beacon timer drifts by 1us every tick, the timer is configured - * in 1/16 TU (64us) units. - */ - if (dev->tbtt_count < 62) - return; - - if (dev->tbtt_count >= 64) { - dev->tbtt_count = 0; - return; - } - - /* - * The updated beacon interval takes effect after two TBTT, because - * at this point the original interval has already been loaded into - * the next TBTT_TIMER value - */ - if (dev->tbtt_count == 62) - timer_val -= 1; - - mt76_rmw_field(dev, MT_BEACON_TIME_CFG, - MT_BEACON_TIME_CFG_INTVAL, timer_val); -} - -void mt76x2_pre_tbtt_tasklet(unsigned long arg) -{ - struct mt76x02_dev *dev = (struct mt76x02_dev *) arg; - struct mt76_queue *q = &dev->mt76.q_tx[MT_TXQ_PSD]; - struct beacon_bc_data data = {}; - struct sk_buff *skb; - int i, nframes; - - mt76x2_resync_beacon_timer(dev); - - data.dev = dev; - __skb_queue_head_init(&data.q); - - ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev), - IEEE80211_IFACE_ITER_RESUME_ALL, - mt76x2_update_beacon_iter, dev); - - do { - nframes = skb_queue_len(&data.q); - ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev), - IEEE80211_IFACE_ITER_RESUME_ALL, - mt76x2_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 mt76x02_vif *mvif = (struct mt76x02_vif *) vif->drv_priv; - - mt76_dma_tx_queue_skb(&dev->mt76, q, skb, &mvif->group_wcid, - NULL); - } - spin_unlock_bh(&q->lock); -} - diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c b/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c index e9fff5b7f125..c9634a774705 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c @@ -210,7 +210,7 @@ void mt76x2_configure_tx_delay(struct mt76x02_dev *dev, } EXPORT_SYMBOL_GPL(mt76x2_configure_tx_delay); -void mt76x2_phy_tssi_compensate(struct mt76x02_dev *dev, bool wait) +void mt76x2_phy_tssi_compensate(struct mt76x02_dev *dev) { struct ieee80211_channel *chan = dev->mt76.chandef.chan; struct mt76x2_tx_power_info txp; @@ -245,8 +245,99 @@ void mt76x2_phy_tssi_compensate(struct mt76x02_dev *dev, bool wait) return; usleep_range(10000, 20000); - mt76x02_mcu_calibrate(dev, MCU_CAL_DPD, chan->hw_value, wait); + mt76x02_mcu_calibrate(dev, MCU_CAL_DPD, chan->hw_value); dev->cal.dpd_cal_done = true; } } EXPORT_SYMBOL_GPL(mt76x2_phy_tssi_compensate); + +static void +mt76x2_phy_set_gain_val(struct mt76x02_dev *dev) +{ + u32 val; + u8 gain_val[2]; + + gain_val[0] = dev->cal.agc_gain_cur[0] - dev->cal.agc_gain_adjust; + gain_val[1] = dev->cal.agc_gain_cur[1] - dev->cal.agc_gain_adjust; + + if (dev->mt76.chandef.width >= NL80211_CHAN_WIDTH_40) + val = 0x1e42 << 16; + else + val = 0x1836 << 16; + + val |= 0xf8; + + mt76_wr(dev, MT_BBP(AGC, 8), + val | FIELD_PREP(MT_BBP_AGC_GAIN, gain_val[0])); + mt76_wr(dev, MT_BBP(AGC, 9), + val | FIELD_PREP(MT_BBP_AGC_GAIN, gain_val[1])); + + if (dev->mt76.chandef.chan->flags & IEEE80211_CHAN_RADAR) + mt76x02_phy_dfs_adjust_agc(dev); +} + +void mt76x2_phy_update_channel_gain(struct mt76x02_dev *dev) +{ + u8 *gain = dev->cal.agc_gain_init; + u8 low_gain_delta, gain_delta; + bool gain_change; + int low_gain; + u32 val; + + dev->cal.avg_rssi_all = mt76x02_phy_get_min_avg_rssi(dev); + + 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)); + + gain_change = dev->cal.low_gain < 0 || + (dev->cal.low_gain & 2) ^ (low_gain & 2); + dev->cal.low_gain = low_gain; + + if (!gain_change) { + if (mt76x02_phy_adjust_vga_gain(dev)) + mt76x2_phy_set_gain_val(dev); + return; + } + + if (dev->mt76.chandef.width == NL80211_CHAN_WIDTH_80) { + mt76_wr(dev, MT_BBP(RXO, 14), 0x00560211); + val = mt76_rr(dev, MT_BBP(AGC, 26)) & ~0xf; + if (low_gain == 2) + val |= 0x3; + else + val |= 0x5; + mt76_wr(dev, MT_BBP(AGC, 26), val); + } else { + mt76_wr(dev, MT_BBP(RXO, 14), 0x00560423); + } + + if (mt76x2_has_ext_lna(dev)) + low_gain_delta = 10; + else + low_gain_delta = 14; + + if (low_gain == 2) { + mt76_wr(dev, MT_BBP(RXO, 18), 0xf000a990); + mt76_wr(dev, MT_BBP(AGC, 35), 0x08080808); + mt76_wr(dev, MT_BBP(AGC, 37), 0x08080808); + gain_delta = low_gain_delta; + dev->cal.agc_gain_adjust = 0; + } else { + mt76_wr(dev, MT_BBP(RXO, 18), 0xf000a991); + if (dev->mt76.chandef.width == NL80211_CHAN_WIDTH_80) + mt76_wr(dev, MT_BBP(AGC, 35), 0x10101014); + else + mt76_wr(dev, MT_BBP(AGC, 35), 0x11111116); + mt76_wr(dev, MT_BBP(AGC, 37), 0x2121262C); + gain_delta = 0; + dev->cal.agc_gain_adjust = low_gain_delta; + } + + dev->cal.agc_gain_cur[0] = gain[0] - gain_delta; + dev->cal.agc_gain_cur[1] = gain[1] - gain_delta; + mt76x2_phy_set_gain_val(dev); + + /* clear false CCA counters */ + mt76_rr(dev, MT_RX_STAT_1); +} +EXPORT_SYMBOL_GPL(mt76x2_phy_update_channel_gain); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c index 57baf8d1c830..4d1788eb3812 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c @@ -131,8 +131,8 @@ err: } MODULE_DEVICE_TABLE(usb, mt76x2u_device_table); -MODULE_FIRMWARE(MT7662U_FIRMWARE); -MODULE_FIRMWARE(MT7662U_ROM_PATCH); +MODULE_FIRMWARE(MT7662_FIRMWARE); +MODULE_FIRMWARE(MT7662_ROM_PATCH); static struct usb_driver mt76x2u_driver = { .name = KBUILD_MODNAME, diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c index 13cce2937573..0be3784f44fb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c @@ -141,6 +141,8 @@ struct mt76x02_dev *mt76x2u_alloc_device(struct device *pdev) .tx_complete_skb = mt76x02u_tx_complete_skb, .tx_status_data = mt76x02_tx_status_data, .rx_skb = mt76x02_queue_rx_skb, + .sta_add = mt76x02_sta_add, + .sta_remove = mt76x02_sta_remove, }; struct mt76x02_dev *dev; struct mt76_dev *mdev; @@ -156,21 +158,9 @@ struct mt76x02_dev *mt76x2u_alloc_device(struct device *pdev) return dev; } -static void mt76x2u_init_beacon_offsets(struct mt76x02_dev *dev) -{ - mt76_wr(dev, MT_BCN_OFFSET(0), 0x18100800); - mt76_wr(dev, MT_BCN_OFFSET(1), 0x38302820); - mt76_wr(dev, MT_BCN_OFFSET(2), 0x58504840); - mt76_wr(dev, MT_BCN_OFFSET(3), 0x78706860); -} - int mt76x2u_init_hardware(struct mt76x02_dev *dev) { - const struct mt76_wcid_addr addr = { - .macaddr = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, - .ba_mask = 0, - }; - int i, err; + int i, k, err; mt76x2_reset_wlan(dev, true); mt76x2u_power_on(dev); @@ -191,9 +181,6 @@ int mt76x2u_init_hardware(struct mt76x02_dev *dev) if (!mt76x02_wait_for_mac(&dev->mt76)) return -ETIMEDOUT; - mt76_wr(dev, MT_HEADER_TRANS_CTRL_REG, 0); - mt76_wr(dev, MT_TSO_CTRL, 0); - mt76x2u_init_dma(dev); err = mt76x2u_mcu_init(dev); @@ -207,21 +194,18 @@ int mt76x2u_init_hardware(struct mt76x02_dev *dev) mt76x02_mac_setaddr(dev, dev->mt76.eeprom.data + MT_EE_MAC_ADDR); dev->mt76.rxfilter = mt76_rr(dev, MT_RX_FILTR_CFG); - mt76x2u_init_beacon_offsets(dev); - if (!mt76x02_wait_for_txrx_idle(&dev->mt76)) return -ETIMEDOUT; /* reset wcid table */ - for (i = 0; i < 254; i++) - mt76_wr_copy(dev, MT_WCID_ADDR(i), &addr, - sizeof(struct mt76_wcid_addr)); + for (i = 0; i < 256; i++) + mt76x02_mac_wcid_setup(dev, i, 0, NULL); /* reset shared key table and pairwise key table */ - for (i = 0; i < 4; i++) - mt76_wr(dev, MT_SKEY_MODE_BASE_0 + 4 * i, 0); - for (i = 0; i < 256; i++) - mt76_wr(dev, MT_WCID_ATTR(i), 1); + for (i = 0; i < 16; i++) { + for (k = 0; k < 4; k++) + mt76x02_mac_shared_key_setup(dev, i, k, NULL); + } mt76_clear(dev, MT_BEACON_TIME_CFG, MT_BEACON_TIME_CFG_TIMER_EN | @@ -245,11 +229,10 @@ int mt76x2u_init_hardware(struct mt76x02_dev *dev) int mt76x2u_register_device(struct mt76x02_dev *dev) { struct ieee80211_hw *hw = mt76_hw(dev); - struct wiphy *wiphy = hw->wiphy; int err; INIT_DELAYED_WORK(&dev->cal_work, mt76x2u_phy_calibrate); - mt76x2_init_device(dev); + mt76x02_init_device(dev); err = mt76x2u_init_eeprom(dev); if (err < 0) @@ -267,8 +250,6 @@ int mt76x2u_register_device(struct mt76x02_dev *dev) if (err < 0) goto fail; - wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); - err = mt76_register_device(&dev->mt76, true, mt76x02_rates, ARRAY_SIZE(mt76x02_rates)); if (err) @@ -282,7 +263,7 @@ int mt76x2u_register_device(struct mt76x02_dev *dev) set_bit(MT76_STATE_INITIALIZED, &dev->mt76.state); - mt76x2_init_debugfs(dev); + mt76x02_init_debugfs(dev); mt76x2_init_txpower(dev, &dev->mt76.sband_2g.sband); mt76x2_init_txpower(dev, &dev->mt76.sband_5g.sband); @@ -297,12 +278,13 @@ void mt76x2u_stop_hw(struct mt76x02_dev *dev) { mt76u_stop_stat_wk(&dev->mt76); cancel_delayed_work_sync(&dev->cal_work); + cancel_delayed_work_sync(&dev->mac_work); mt76x2u_mac_stop(dev); } void mt76x2u_cleanup(struct mt76x02_dev *dev) { - mt76x02_mcu_set_radio_state(dev, false, false); + mt76x02_mcu_set_radio_state(dev, false); mt76x2u_stop_hw(dev); mt76u_queues_deinit(&dev->mt76); mt76u_mcu_deinit(&dev->mt76); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c index 1971a1b00038..2b48cc51a30d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c @@ -27,6 +27,8 @@ static int mt76x2u_start(struct ieee80211_hw *hw) if (ret) goto out; + ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work, + MT_CALIBRATE_INTERVAL); set_bit(MT76_STATE_RUNNING, &dev->mt76.state); out: @@ -48,11 +50,12 @@ static int mt76x2u_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct mt76x02_dev *dev = hw->priv; + unsigned int idx = 8; if (!ether_addr_equal(dev->mt76.macaddr, vif->addr)) mt76x02_mac_setaddr(dev, vif->addr); - mt76x02_vif_init(dev, vif, 0); + mt76x02_vif_init(dev, vif, idx); return 0; } @@ -81,29 +84,6 @@ mt76x2u_set_channel(struct mt76x02_dev *dev, return err; } -static void -mt76x2u_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_bss_conf *info, u32 changed) -{ - struct mt76x02_dev *dev = hw->priv; - - mutex_lock(&dev->mt76.mutex); - - if (changed & BSS_CHANGED_ASSOC) { - mt76x2u_phy_channel_calibrate(dev); - mt76x2_apply_gain_adj(dev); - } - - if (changed & BSS_CHANGED_BSSID) { - mt76_wr(dev, MT_MAC_BSSID_DW0, - get_unaligned_le32(info->bssid)); - mt76_wr(dev, MT_MAC_BSSID_DW1, - get_unaligned_le16(info->bssid + 4)); - } - - mutex_unlock(&dev->mt76.mutex); -} - static int mt76x2u_config(struct ieee80211_hw *hw, u32 changed) { @@ -141,39 +121,22 @@ mt76x2u_config(struct ieee80211_hw *hw, u32 changed) return err; } -static void -mt76x2u_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - const u8 *mac) -{ - struct mt76x02_dev *dev = hw->priv; - - set_bit(MT76_SCANNING, &dev->mt76.state); -} - -static void -mt76x2u_sw_scan_complete(struct ieee80211_hw *hw, struct ieee80211_vif *vif) -{ - struct mt76x02_dev *dev = hw->priv; - - clear_bit(MT76_SCANNING, &dev->mt76.state); -} - const struct ieee80211_ops mt76x2u_ops = { .tx = mt76x02_tx, .start = mt76x2u_start, .stop = mt76x2u_stop, .add_interface = mt76x2u_add_interface, .remove_interface = mt76x02_remove_interface, - .sta_add = mt76x02_sta_add, - .sta_remove = mt76x02_sta_remove, + .sta_state = mt76_sta_state, .set_key = mt76x02_set_key, .ampdu_action = mt76x02_ampdu_action, .config = mt76x2u_config, .wake_tx_queue = mt76_wake_tx_queue, - .bss_info_changed = mt76x2u_bss_info_changed, + .bss_info_changed = mt76x02_bss_info_changed, .configure_filter = mt76x02_configure_filter, .conf_tx = mt76x02_conf_tx, - .sw_scan_start = mt76x2u_sw_scan, - .sw_scan_complete = mt76x2u_sw_scan_complete, + .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, }; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mcu.c index 3f1e558e5e6d..45a95ee3a415 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mcu.c @@ -29,30 +29,6 @@ #define MT76U_MCU_DLM_OFFSET 0x110000 #define MT76U_MCU_ROM_PATCH_OFFSET 0x90000 -int mt76x2u_mcu_set_dynamic_vga(struct mt76x02_dev *dev, u8 channel, bool ap, - bool ext, int rssi, u32 false_cca) -{ - struct { - __le32 channel; - __le32 rssi_val; - __le32 false_cca_val; - } __packed __aligned(4) msg = { - .rssi_val = cpu_to_le32(rssi), - .false_cca_val = cpu_to_le32(false_cca), - }; - struct sk_buff *skb; - u32 val = channel; - - if (ap) - val |= BIT(31); - if (ext) - val |= BIT(30); - msg.channel = cpu_to_le32(val); - - skb = mt76_mcu_msg_alloc(dev, &msg, sizeof(msg)); - return mt76_mcu_send_msg(dev, skb, CMD_DYNC_VGA_OP, true); -} - static void mt76x2u_mcu_load_ivb(struct mt76x02_dev *dev) { mt76u_vendor_request(&dev->mt76, MT_VEND_DEV_MODE, @@ -117,7 +93,7 @@ static int mt76x2u_mcu_load_rom_patch(struct mt76x02_dev *dev) return 0; } - err = request_firmware(&fw, MT7662U_ROM_PATCH, dev->mt76.dev); + err = request_firmware(&fw, MT7662_ROM_PATCH, dev->mt76.dev); if (err < 0) return err; @@ -183,7 +159,7 @@ static int mt76x2u_mcu_load_firmware(struct mt76x02_dev *dev) int err, len, ilm_len, dlm_len; const struct firmware *fw; - err = request_firmware(&fw, MT7662U_FIRMWARE, dev->mt76.dev); + err = request_firmware(&fw, MT7662_FIRMWARE, dev->mt76.dev); if (err < 0) return err; @@ -282,9 +258,9 @@ int mt76x2u_mcu_init(struct mt76x02_dev *dev) { int err; - err = mt76x02_mcu_function_select(dev, Q_SELECT, 1, false); + err = mt76x02_mcu_function_select(dev, Q_SELECT, 1); if (err < 0) return err; - return mt76x02_mcu_set_radio_state(dev, true, false); + return mt76x02_mcu_set_radio_state(dev, true); } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c index ca96ba60510e..11d414d86c68 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c @@ -18,63 +18,35 @@ #include "eeprom.h" #include "../mt76x02_phy.h" -void mt76x2u_phy_channel_calibrate(struct mt76x02_dev *dev) +static void +mt76x2u_phy_channel_calibrate(struct mt76x02_dev *dev, bool mac_stopped) { struct ieee80211_channel *chan = dev->mt76.chandef.chan; bool is_5ghz = chan->band == NL80211_BAND_5GHZ; + if (dev->cal.channel_cal_done) + return; + if (mt76x2_channel_silent(dev)) return; - mt76x2u_mac_stop(dev); + if (!mac_stopped) + mt76x2u_mac_stop(dev); if (is_5ghz) - mt76x02_mcu_calibrate(dev, MCU_CAL_LC, 0, false); - - mt76x02_mcu_calibrate(dev, MCU_CAL_TX_LOFT, is_5ghz, false); - mt76x02_mcu_calibrate(dev, MCU_CAL_TXIQ, is_5ghz, false); - mt76x02_mcu_calibrate(dev, MCU_CAL_RXIQC_FI, is_5ghz, false); - mt76x02_mcu_calibrate(dev, MCU_CAL_TEMP_SENSOR, 0, false); - - mt76x2u_mac_resume(dev); -} + mt76x02_mcu_calibrate(dev, MCU_CAL_LC, 0); -static void -mt76x2u_phy_update_channel_gain(struct mt76x02_dev *dev) -{ - u8 channel = dev->mt76.chandef.chan->hw_value; - int freq, freq1; - u32 false_cca; - - freq = dev->mt76.chandef.chan->center_freq; - freq1 = dev->mt76.chandef.center_freq1; + mt76x02_mcu_calibrate(dev, MCU_CAL_TX_LOFT, is_5ghz); + mt76x02_mcu_calibrate(dev, MCU_CAL_TXIQ, is_5ghz); + mt76x02_mcu_calibrate(dev, MCU_CAL_RXIQC_FI, is_5ghz); + mt76x02_mcu_calibrate(dev, MCU_CAL_TEMP_SENSOR, 0); + mt76x02_mcu_calibrate(dev, MCU_CAL_TX_SHAPING, 0); - switch (dev->mt76.chandef.width) { - case NL80211_CHAN_WIDTH_80: { - int ch_group_index; + if (!mac_stopped) + mt76x2u_mac_resume(dev); + mt76x2_apply_gain_adj(dev); - ch_group_index = (freq - freq1 + 30) / 20; - if (WARN_ON(ch_group_index < 0 || ch_group_index > 3)) - ch_group_index = 0; - channel += 6 - ch_group_index * 4; - break; - } - case NL80211_CHAN_WIDTH_40: - if (freq1 > freq) - channel += 2; - else - channel -= 2; - break; - default: - break; - } - - dev->cal.avg_rssi_all = mt76x02_phy_get_min_avg_rssi(dev); - false_cca = FIELD_GET(MT_RX_STAT_1_CCA_ERRORS, - mt76_rr(dev, MT_RX_STAT_1)); - - mt76x2u_mcu_set_dynamic_vga(dev, channel, false, false, - dev->cal.avg_rssi_all, false_cca); + dev->cal.channel_cal_done = true; } void mt76x2u_phy_calibrate(struct work_struct *work) @@ -82,8 +54,9 @@ void mt76x2u_phy_calibrate(struct work_struct *work) struct mt76x02_dev *dev; dev = container_of(work, struct mt76x02_dev, cal_work.work); - mt76x2_phy_tssi_compensate(dev, false); - mt76x2u_phy_update_channel_gain(dev); + mt76x2u_phy_channel_calibrate(dev, false); + mt76x2_phy_tssi_compensate(dev); + mt76x2_phy_update_channel_gain(dev); ieee80211_queue_delayed_work(mt76_hw(dev), &dev->cal_work, MT_CALIBRATE_INTERVAL); @@ -180,14 +153,14 @@ int mt76x2u_phy_set_channel(struct mt76x02_dev *dev, u8 val = mt76x02_eeprom_get(dev, MT_EE_BT_RCAL_RESULT); if (val != 0xff) - mt76x02_mcu_calibrate(dev, MCU_CAL_R, 0, false); + mt76x02_mcu_calibrate(dev, MCU_CAL_R, 0); } - mt76x02_mcu_calibrate(dev, MCU_CAL_RXDCOC, channel, false); + mt76x02_mcu_calibrate(dev, MCU_CAL_RXDCOC, channel); /* Rx LPF calibration */ if (!dev->cal.init_cal_done) - mt76x02_mcu_calibrate(dev, MCU_CAL_RC, 0, false); + mt76x02_mcu_calibrate(dev, MCU_CAL_RC, 0); dev->cal.init_cal_done = true; mt76_wr(dev, MT_BBP(AGC, 61), 0xff64a4e2); @@ -202,6 +175,9 @@ int mt76x2u_phy_set_channel(struct mt76x02_dev *dev, if (scan) return 0; + mt76x2u_phy_channel_calibrate(dev, true); + mt76x02_init_agc_gain(dev); + if (mt76x2_tssi_enabled(dev)) { /* init default values for temp compensation */ mt76_rmw_field(dev, MT_TX_ALC_CFG_1, MT_TX_ALC_CFG_1_TEMP_COMP, @@ -219,7 +195,7 @@ int mt76x2u_phy_set_channel(struct mt76x02_dev *dev, flag |= BIT(0); if (mt76x02_ext_pa_enabled(dev, chan->band)) flag |= BIT(8); - mt76x02_mcu_calibrate(dev, MCU_CAL_TSSI, flag, false); + mt76x02_mcu_calibrate(dev, MCU_CAL_TSSI, flag); dev->cal.tssi_cal_done = true; } } |