diff options
author | Kalle Valo <kvalo@codeaurora.org> | 2018-10-04 08:35:58 +0300 |
---|---|---|
committer | Kalle Valo <kvalo@codeaurora.org> | 2018-10-04 08:35:58 +0300 |
commit | 9434dca95117c493575ab1bd255d323dabf4184a (patch) | |
tree | cd58ffb1df65b177930bf8132f30317620f6b63c | |
parent | 09afaba1c3cc83f0f29a3f7614dcef086d21cd3a (diff) | |
parent | 5289976ad887deb07c76df7eecf553c264aeebed (diff) |
Merge tag 'mt76-for-kvalo-2018-10-01' of https://github.com/nbd168/wireless
mt76 patches for 4.20
* unify code between mt76x0, mt76x2
* mt76x0 fixes
* tx power configuration fix for 76x2
* more progress on mt76x0e support
* support for getting firmware version via ethtool
* fix for rx buffer allocation regression on usb
* fix for handling powersave responses
* fix for mt76x2 beacon transmission
61 files changed, 2289 insertions, 2131 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/Makefile b/drivers/net/wireless/mediatek/mt76/Makefile index 4d25b5c3b70b..2346a1b768bc 100644 --- a/drivers/net/wireless/mediatek/mt76/Makefile +++ b/drivers/net/wireless/mediatek/mt76/Makefile @@ -15,7 +15,8 @@ mt76-usb-y := usb.o usb_trace.o usb_mcu.o CFLAGS_trace.o := -I$(src) CFLAGS_usb_trace.o := -I$(src) -mt76x02-lib-y := mt76x02_util.o mt76x02_mac.o mt76x02_mcu.o +mt76x02-lib-y := mt76x02_util.o mt76x02_mac.o mt76x02_mcu.o \ + mt76x02_eeprom.o mt76x02_phy.o mt76x02_mmio.o mt76x02-usb-y := mt76x02_usb_mcu.o mt76x02_usb_core.o diff --git a/drivers/net/wireless/mediatek/mt76/debugfs.c b/drivers/net/wireless/mediatek/mt76/debugfs.c index a38d05dea599..a5adf22c3ffa 100644 --- a/drivers/net/wireless/mediatek/mt76/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/debugfs.c @@ -56,6 +56,35 @@ mt76_queues_read(struct seq_file *s, void *data) return 0; } +void mt76_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"); +} +EXPORT_SYMBOL_GPL(mt76_seq_puts_array); + +static int mt76_read_rate_txpower(struct seq_file *s, void *data) +{ + struct mt76_dev *dev = dev_get_drvdata(s->private); + + mt76_seq_puts_array(s, "CCK", dev->rate_power.cck, + ARRAY_SIZE(dev->rate_power.cck)); + mt76_seq_puts_array(s, "OFDM", dev->rate_power.ofdm, + ARRAY_SIZE(dev->rate_power.ofdm)); + mt76_seq_puts_array(s, "STBC", dev->rate_power.stbc, + ARRAY_SIZE(dev->rate_power.stbc)); + mt76_seq_puts_array(s, "HT", dev->rate_power.ht, + ARRAY_SIZE(dev->rate_power.ht)); + mt76_seq_puts_array(s, "VHT", dev->rate_power.vht, + ARRAY_SIZE(dev->rate_power.vht)); + return 0; +} + struct dentry *mt76_register_debugfs(struct mt76_dev *dev) { struct dentry *dir; @@ -72,6 +101,8 @@ struct dentry *mt76_register_debugfs(struct mt76_dev *dev) if (dev->otp.data) debugfs_create_blob("otp", 0400, dir, &dev->otp); debugfs_create_devm_seqfile(dev->dev, "queues", dir, mt76_queues_read); + debugfs_create_devm_seqfile(dev->dev, "rate_txpower", dir, + mt76_read_rate_txpower); return dir; } diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index 639cbafc1d50..2a699e8b79bf 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -550,6 +550,12 @@ mt76_check_ps(struct mt76_dev *dev, struct sk_buff *skb) struct mt76_wcid *wcid = status->wcid; bool ps; + if (ieee80211_is_pspoll(hdr->frame_control) && !wcid) { + sta = ieee80211_find_sta_by_ifaddr(dev->hw, hdr->addr2, NULL); + if (sta) + wcid = status->wcid = (struct mt76_wcid *) sta->drv_priv; + } + if (!wcid || !wcid->sta) return; diff --git a/drivers/net/wireless/mediatek/mt76/mmio.c b/drivers/net/wireless/mediatek/mt76/mmio.c index 2f09f451a9b6..30a5d928e655 100644 --- a/drivers/net/wireless/mediatek/mt76/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mmio.c @@ -46,6 +46,30 @@ static void mt76_mmio_copy(struct mt76_dev *dev, u32 offset, const void *data, __iowrite32_copy(dev->mmio.regs + offset, data, len >> 2); } +static int mt76_mmio_wr_rp(struct mt76_dev *dev, u32 base, + const struct mt76_reg_pair *data, int len) +{ + while (len > 0) { + mt76_mmio_wr(dev, data->reg, data->value); + data++; + len--; + } + + return 0; +} + +static int mt76_mmio_rd_rp(struct mt76_dev *dev, u32 base, + struct mt76_reg_pair *data, int len) +{ + while (len > 0) { + data->value = mt76_mmio_rr(dev, data->reg); + data++; + len--; + } + + return 0; +} + void mt76_mmio_init(struct mt76_dev *dev, void __iomem *regs) { static const struct mt76_bus_ops mt76_mmio_ops = { @@ -53,6 +77,8 @@ void mt76_mmio_init(struct mt76_dev *dev, void __iomem *regs) .rmw = mt76_mmio_rmw, .wr = mt76_mmio_wr, .copy = mt76_mmio_copy, + .wr_rp = mt76_mmio_wr_rp, + .rd_rp = mt76_mmio_rd_rp, }; dev->bus = &mt76_mmio_ops; @@ -60,6 +86,7 @@ void mt76_mmio_init(struct mt76_dev *dev, void __iomem *regs) skb_queue_head_init(&dev->mmio.mcu.res_q); init_waitqueue_head(&dev->mmio.mcu.wait); + spin_lock_init(&dev->mmio.irq_lock); mutex_init(&dev->mmio.mcu.mutex); } EXPORT_SYMBOL_GPL(mt76_mmio_init); diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index dbda49243a10..f2dd4d87e355 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -122,6 +122,7 @@ struct mt76_queue { dma_addr_t desc_dma; struct sk_buff *rx_head; struct page_frag_cache rx_page; + spinlock_t rx_page_lock; }; struct mt76_mcu_ops { @@ -275,6 +276,19 @@ struct mt76_sband { struct mt76_channel_state *chan; }; +struct mt76_rate_power { + union { + struct { + s8 cck[4]; + s8 ofdm[8]; + s8 stbc[10]; + s8 ht[16]; + s8 vht[10]; + }; + s8 all[48]; + }; +}; + /* addr req mask */ #define MT_VEND_TYPE_EEPROM BIT(31) #define MT_VEND_TYPE_CFG BIT(30) @@ -349,6 +363,8 @@ struct mt76_mmio { u32 msg_seq; } mcu; void __iomem *regs; + spinlock_t irq_lock; + u32 irqmask; }; struct mt76_dev { @@ -388,6 +404,7 @@ struct mt76_dev { unsigned long state; u8 antenna_mask; + u16 chainmask; struct mt76_sband sband_2g; struct mt76_sband sband_5g; @@ -395,6 +412,10 @@ struct mt76_dev { struct debugfs_blob_wrapper otp; struct mt76_hw_cap cap; + struct mt76_rate_power rate_power; + int txpower_conf; + int txpower_cur; + u32 debugfs_reg; struct led_classdev led_cdev; @@ -418,18 +439,6 @@ enum mt76_phy_type { MT_PHY_TYPE_VHT, }; -struct mt76_rate_power { - union { - struct { - s8 cck[4]; - s8 ofdm[8]; - s8 ht[16]; - s8 vht[10]; - }; - s8 all[38]; - }; -}; - struct mt76_rx_status { struct mt76_wcid *wcid; @@ -510,8 +519,8 @@ static inline u16 mt76_rev(struct mt76_dev *dev) #define mt76xx_chip(dev) mt76_chip(&((dev)->mt76)) #define mt76xx_rev(dev) mt76_rev(&((dev)->mt76)) -#define mt76_init_queues(dev) (dev)->mt76.queue_ops->init(&((dev)->mt76)) -#define mt76_queue_alloc(dev, ...) (dev)->mt76.queue_ops->alloc(&((dev)->mt76), __VA_ARGS__) +#define __mt76_init_queues(dev) (dev)->queue_ops->init((dev)) +#define __mt76_queue_alloc(dev, ...) (dev)->queue_ops->alloc((dev), __VA_ARGS__) #define mt76_queue_add_buf(dev, ...) (dev)->mt76.queue_ops->add_buf(&((dev)->mt76), __VA_ARGS__) #define mt76_queue_rx_reset(dev, ...) (dev)->mt76.queue_ops->rx_reset(&((dev)->mt76), __VA_ARGS__) #define mt76_queue_tx_cleanup(dev, ...) (dev)->mt76.queue_ops->tx_cleanup(&((dev)->mt76), __VA_ARGS__) @@ -539,6 +548,8 @@ int mt76_register_device(struct mt76_dev *dev, bool vht, void mt76_unregister_device(struct mt76_dev *dev); struct dentry *mt76_register_debugfs(struct mt76_dev *dev); +void mt76_seq_puts_array(struct seq_file *file, const char *str, + s8 *val, int len); int mt76_eeprom_init(struct mt76_dev *dev, int len); void mt76_eeprom_override(struct mt76_dev *dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/Makefile b/drivers/net/wireless/mediatek/mt76/mt76x0/Makefile index 48f7979e36ef..254d94efd24d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/Makefile +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/Makefile @@ -5,8 +5,8 @@ obj-$(CONFIG_MT76x0_COMMON) += mt76x0-common.o mt76x0-common-y := \ init.o main.o trace.o eeprom.o phy.o \ mac.o debugfs.o tx.o -mt76x0u-y := usb.o -mt76x0e-y := pci.o +mt76x0u-y := usb.o usb_mcu.o +mt76x0e-y := pci.o pci_mcu.o # ccflags-y := -DDEBUG CFLAGS_trace.o := -I$(src) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt76x0/debugfs.c index e7a77a886068..ddc1af626b3b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/debugfs.c @@ -19,26 +19,6 @@ #include "eeprom.h" static int -mt76_reg_set(void *data, u64 val) -{ - struct mt76x0_dev *dev = data; - - mt76_wr(dev, dev->debugfs_reg, val); - return 0; -} - -static int -mt76_reg_get(void *data, u64 *val) -{ - struct mt76x0_dev *dev = data; - - *val = mt76_rr(dev, dev->debugfs_reg); - return 0; -} - -DEFINE_SIMPLE_ATTRIBUTE(fops_regval, mt76_reg_get, mt76_reg_set, "0x%08llx\n"); - -static int mt76x0_ampdu_stat_read(struct seq_file *file, void *data) { struct mt76x0_dev *dev = file->private; @@ -95,72 +75,13 @@ static const struct file_operations fops_ampdu_stat = { .release = single_release, }; -static int -mt76x0_eeprom_param_read(struct seq_file *file, void *data) -{ - struct mt76x0_dev *dev = file->private; - int i; - - seq_printf(file, "RF freq offset: %hhx\n", dev->ee->rf_freq_off); - seq_printf(file, "RSSI offset 2GHz: %hhx %hhx\n", - dev->ee->rssi_offset_2ghz[0], dev->ee->rssi_offset_2ghz[1]); - seq_printf(file, "RSSI offset 5GHz: %hhx %hhx %hhx\n", - dev->ee->rssi_offset_5ghz[0], dev->ee->rssi_offset_5ghz[1], - dev->ee->rssi_offset_5ghz[2]); - seq_printf(file, "Temperature offset: %hhx\n", dev->ee->temp_off); - seq_printf(file, "LNA gain 2Ghz: %hhx\n", dev->ee->lna_gain_2ghz); - seq_printf(file, "LNA gain 5Ghz: %hhx %hhx %hhx\n", - dev->ee->lna_gain_5ghz[0], dev->ee->lna_gain_5ghz[1], - dev->ee->lna_gain_5ghz[2]); - seq_printf(file, "Power Amplifier type %hhx\n", dev->ee->pa_type); - seq_printf(file, "Reg channels: %hhu-%hhu\n", dev->ee->reg.start, - dev->ee->reg.start + dev->ee->reg.num - 1); - - seq_puts(file, "Per channel power:\n"); - for (i = 0; i < 58; i++) - seq_printf(file, "\t%d chan:%d pwr:%d\n", i, i, - dev->ee->tx_pwr_per_chan[i]); - - seq_puts(file, "Per rate power 2GHz:\n"); - for (i = 0; i < 5; i++) - seq_printf(file, "\t %d bw20:%d bw40:%d\n", - i, dev->ee->tx_pwr_cfg_2g[i][0], - dev->ee->tx_pwr_cfg_5g[i][1]); - - seq_puts(file, "Per rate power 5GHz:\n"); - for (i = 0; i < 5; i++) - seq_printf(file, "\t %d bw20:%d bw40:%d\n", - i, dev->ee->tx_pwr_cfg_5g[i][0], - dev->ee->tx_pwr_cfg_5g[i][1]); - - return 0; -} - -static int -mt76x0_eeprom_param_open(struct inode *inode, struct file *f) -{ - return single_open(f, mt76x0_eeprom_param_read, inode->i_private); -} - -static const struct file_operations fops_eeprom_param = { - .open = mt76x0_eeprom_param_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - void mt76x0_init_debugfs(struct mt76x0_dev *dev) { struct dentry *dir; - dir = debugfs_create_dir("mt76x0", dev->mt76.hw->wiphy->debugfsdir); + dir = mt76_register_debugfs(&dev->mt76); if (!dir) return; - debugfs_create_u32("regidx", S_IRUSR | S_IWUSR, dir, &dev->debugfs_reg); - debugfs_create_file("regval", S_IRUSR | S_IWUSR, dir, dev, - &fops_regval); debugfs_create_file("ampdu_stat", S_IRUSR, dir, dev, &fops_ampdu_stat); - debugfs_create_file("eeprom_param", S_IRUSR, dir, dev, - &fops_eeprom_param); } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c index 79856bde1632..166a1fd8644e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c @@ -13,6 +13,7 @@ * GNU General Public License for more details. */ +#include <linux/module.h> #include <linux/of.h> #include <linux/mtd/mtd.h> #include <linux/mtd/partitions.h> @@ -20,66 +21,7 @@ #include <asm/unaligned.h> #include "mt76x0.h" #include "eeprom.h" - -static bool -field_valid(u8 val) -{ - return val != 0xff; -} - -static s8 -field_validate(u8 val) -{ - if (!field_valid(val)) - return 0; - - return val; -} - -static inline int -sign_extend(u32 val, unsigned int size) -{ - bool sign = val & BIT(size - 1); - - val &= BIT(size - 1) - 1; - - return sign ? val : -val; -} - -static int -mt76x0_efuse_read(struct mt76x0_dev *dev, u16 addr, u8 *data, - enum mt76x0_eeprom_access_modes mode) -{ - u32 val; - int i; - - val = mt76_rr(dev, MT_EFUSE_CTRL); - val &= ~(MT_EFUSE_CTRL_AIN | - MT_EFUSE_CTRL_MODE); - val |= FIELD_PREP(MT_EFUSE_CTRL_AIN, addr & ~0xf) | - FIELD_PREP(MT_EFUSE_CTRL_MODE, mode) | - MT_EFUSE_CTRL_KICK; - mt76_wr(dev, MT_EFUSE_CTRL, val); - - if (!mt76_poll(dev, MT_EFUSE_CTRL, MT_EFUSE_CTRL_KICK, 0, 1000)) - return -ETIMEDOUT; - - val = mt76_rr(dev, MT_EFUSE_CTRL); - if ((val & MT_EFUSE_CTRL_AOUT) == MT_EFUSE_CTRL_AOUT) { - /* Parts of eeprom not in the usage map (0x80-0xc0,0xf0) - * will not return valid data but it's ok. - */ - memset(data, 0xff, 16); - return 0; - } - - for (i = 0; i < 4; i++) { - val = mt76_rr(dev, MT_EFUSE_DATA(i)); - put_unaligned_le32(val, data + 4 * i); - } - - return 0; -} +#include "../mt76x02_phy.h" #define MT_MAP_READS DIV_ROUND_UP(MT_EFUSE_USAGE_MAP_SIZE, 16) static int @@ -89,12 +31,10 @@ mt76x0_efuse_physical_size_check(struct mt76x0_dev *dev) int ret, i; u32 start = 0, end = 0, cnt_free; - for (i = 0; i < MT_MAP_READS; i++) { - ret = mt76x0_efuse_read(dev, MT_EE_USAGE_MAP_START + i * 16, - data + i * 16, MT_EE_PHYSICAL_READ); - if (ret) - return ret; - } + ret = mt76x02_get_efuse_data(&dev->mt76, MT_EE_USAGE_MAP_START, + data, sizeof(data), MT_EE_PHYSICAL_READ); + if (ret) + return ret; for (i = 0; i < MT_EFUSE_USAGE_MAP_SIZE; i++) if (!data[i]) { @@ -105,345 +45,307 @@ mt76x0_efuse_physical_size_check(struct mt76x0_dev *dev) cnt_free = end - start + 1; if (MT_EFUSE_USAGE_MAP_SIZE - cnt_free < 5) { - dev_err(dev->mt76.dev, "Error: your device needs default EEPROM file and this driver doesn't support it!\n"); + dev_err(dev->mt76.dev, + "driver does not support default EEPROM\n"); return -EINVAL; } return 0; } -static void -mt76x0_set_chip_cap(struct mt76x0_dev *dev, u8 *eeprom) +static void mt76x0_set_chip_cap(struct mt76x0_dev *dev) { - enum mt76x2_board_type { BOARD_TYPE_2GHZ = 1, BOARD_TYPE_5GHZ = 2 }; - u16 nic_conf0 = get_unaligned_le16(eeprom + MT_EE_NIC_CONF_0); - u16 nic_conf1 = get_unaligned_le16(eeprom + MT_EE_NIC_CONF_1); - - dev_dbg(dev->mt76.dev, "NIC_CONF0: %04x NIC_CONF1: %04x\n", nic_conf0, nic_conf1); - - switch (FIELD_GET(MT_EE_NIC_CONF_0_BOARD_TYPE, nic_conf0)) { - case BOARD_TYPE_5GHZ: - dev->mt76.cap.has_5ghz = true; - break; - case BOARD_TYPE_2GHZ: - dev->mt76.cap.has_2ghz = true; - break; - default: - dev->mt76.cap.has_2ghz = true; - dev->mt76.cap.has_5ghz = true; - break; - } + u16 nic_conf0 = mt76x02_eeprom_get(&dev->mt76, MT_EE_NIC_CONF_0); + u16 nic_conf1 = mt76x02_eeprom_get(&dev->mt76, MT_EE_NIC_CONF_1); - dev_dbg(dev->mt76.dev, "Has 2GHZ %d 5GHZ %d\n", + mt76x02_eeprom_parse_hw_cap(&dev->mt76); + dev_dbg(dev->mt76.dev, "2GHz %d 5GHz %d\n", dev->mt76.cap.has_2ghz, dev->mt76.cap.has_5ghz); - if (!field_valid(nic_conf1 & 0xff)) + if (dev->no_2ghz) { + dev->mt76.cap.has_2ghz = false; + dev_dbg(dev->mt76.dev, "mask out 2GHz support\n"); + } + + if (!mt76x02_field_valid(nic_conf1 & 0xff)) nic_conf1 &= 0xff00; if (nic_conf1 & MT_EE_NIC_CONF_1_HW_RF_CTRL) dev_err(dev->mt76.dev, - "Error: this driver does not support HW RF ctrl\n"); + "driver does not support HW RF ctrl\n"); - if (!field_valid(nic_conf0 >> 8)) + if (!mt76x02_field_valid(nic_conf0 >> 8)) return; if (FIELD_GET(MT_EE_NIC_CONF_0_RX_PATH, nic_conf0) > 1 || FIELD_GET(MT_EE_NIC_CONF_0_TX_PATH, nic_conf0) > 1) - dev_err(dev->mt76.dev, - "Error: device has more than 1 RX/TX stream!\n"); - - dev->ee->pa_type = FIELD_GET(MT_EE_NIC_CONF_0_PA_TYPE, nic_conf0); - dev_dbg(dev->mt76.dev, "PA Type %d\n", dev->ee->pa_type); + dev_err(dev->mt76.dev, "invalid tx-rx stream\n"); } -static int -mt76x0_set_macaddr(struct mt76x0_dev *dev, const u8 *eeprom) +static void mt76x0_set_temp_offset(struct mt76x0_dev *dev) { - const void *src = eeprom + MT_EE_MAC_ADDR; - u8 *dst = dev->mt76.macaddr; - - ether_addr_copy(dev->mt76.macaddr, src); + u8 val; - if (!is_valid_ether_addr(dst)) { - eth_random_addr(dst); - dev_info(dev->mt76.dev, - "Invalid MAC address, using random address %pM\n", - dst); - } - - mt76_wr(dev, MT_MAC_ADDR_DW0, get_unaligned_le32(dst)); - mt76_wr(dev, MT_MAC_ADDR_DW1, get_unaligned_le16(dst + 4) | - FIELD_PREP(MT_MAC_ADDR_DW1_U2ME_MASK, 0xff)); - - return 0; -} - -static void -mt76x0_set_temp_offset(struct mt76x0_dev *dev, u8 *eeprom) -{ - u8 temp = eeprom[MT_EE_TEMP_OFFSET]; - - if (field_valid(temp)) - dev->ee->temp_off = sign_extend(temp, 8); + val = mt76x02_eeprom_get(&dev->mt76, MT_EE_2G_TARGET_POWER) >> 8; + if (mt76x02_field_valid(val)) + dev->caldata.temp_offset = mt76x02_sign_extend(val, 8); else - dev->ee->temp_off = -10; + dev->caldata.temp_offset = -10; } -static void -mt76x0_set_country_reg(struct mt76x0_dev *dev, u8 *eeprom) +static void mt76x0_set_freq_offset(struct mt76x0_dev *dev) { - /* Note: - region 31 is not valid for mt76x0 (see rtmp_init.c) - * - comments in rtmp_def.h are incorrect (see rt_channel.c) - */ - static const struct reg_channel_bounds chan_bounds[] = { - /* EEPROM country regions 0 - 7 */ - { 1, 11 }, { 1, 13 }, { 10, 2 }, { 10, 4 }, |