diff options
Diffstat (limited to 'drivers/net/wireless/mediatek')
37 files changed, 524 insertions, 422 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/Makefile b/drivers/net/wireless/mediatek/mt76/Makefile index 1a45cb30f39f..fa7a44edd02d 100644 --- a/drivers/net/wireless/mediatek/mt76/Makefile +++ b/drivers/net/wireless/mediatek/mt76/Makefile @@ -4,7 +4,8 @@ obj-$(CONFIG_MT76x02_LIB) += mt76x02-lib.o obj-$(CONFIG_MT76x02_USB) += mt76x02-usb.o mt76-y := \ - mmio.o util.o trace.o dma.o mac80211.o debugfs.o eeprom.o tx.o agg-rx.o + mmio.o util.o trace.o dma.o mac80211.o debugfs.o eeprom.o \ + tx.o agg-rx.o mcu.o mt76-usb-y := usb.o usb_trace.o usb_mcu.o diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index e769c8a555dd..6eedc0ec7661 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -242,6 +242,30 @@ mt76_dma_kick_queue(struct mt76_dev *dev, struct mt76_queue *q) iowrite32(q->head, &q->regs->cpu_idx); } +static int +mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, enum mt76_txq_id qid, + struct sk_buff *skb, u32 tx_info) +{ + struct mt76_queue *q = &dev->q_tx[qid]; + struct mt76_queue_buf buf; + dma_addr_t addr; + + addr = dma_map_single(dev->dev, skb->data, skb->len, + DMA_TO_DEVICE); + if (dma_mapping_error(dev->dev, addr)) + return -ENOMEM; + + buf.addr = addr; + buf.len = skb->len; + + spin_lock_bh(&q->lock); + mt76_dma_add_buf(dev, q, &buf, 1, tx_info, skb, NULL); + mt76_dma_kick_queue(dev, q); + spin_unlock_bh(&q->lock); + + return 0; +} + int mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, struct sk_buff *skb, struct mt76_wcid *wcid, struct ieee80211_sta *sta) @@ -522,17 +546,16 @@ mt76_dma_init(struct mt76_dev *dev) static const struct mt76_queue_ops mt76_dma_ops = { .init = mt76_dma_init, .alloc = mt76_dma_alloc_queue, - .add_buf = mt76_dma_add_buf, + .tx_queue_skb_raw = mt76_dma_tx_queue_skb_raw, .tx_queue_skb = mt76_dma_tx_queue_skb, .tx_cleanup = mt76_dma_tx_cleanup, .rx_reset = mt76_dma_rx_reset, .kick = mt76_dma_kick_queue, }; -int mt76_dma_attach(struct mt76_dev *dev) +void mt76_dma_attach(struct mt76_dev *dev) { dev->queue_ops = &mt76_dma_ops; - return 0; } EXPORT_SYMBOL_GPL(mt76_dma_attach); diff --git a/drivers/net/wireless/mediatek/mt76/dma.h b/drivers/net/wireless/mediatek/mt76/dma.h index 357cc356342d..e3292df5e9b2 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.h +++ b/drivers/net/wireless/mediatek/mt76/dma.h @@ -54,7 +54,7 @@ enum mt76_mcu_evt_type { EVT_EVENT_DFS_DETECT_RSP, }; -int mt76_dma_attach(struct mt76_dev *dev); +void mt76_dma_attach(struct mt76_dev *dev); void mt76_dma_cleanup(struct mt76_dev *dev); #endif diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index ee3b65a14870..82e9f78ef328 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -124,7 +124,7 @@ static void mt76_init_stream_cap(struct mt76_dev *dev, bool vht) { struct ieee80211_sta_ht_cap *ht_cap = &sband->ht_cap; - int i, nstream = __sw_hweight8(dev->antenna_mask); + int i, nstream = hweight8(dev->antenna_mask); struct ieee80211_sta_vht_cap *vht_cap; u16 mcs_map = 0; @@ -269,7 +269,9 @@ mt76_check_sband(struct mt76_dev *dev, int band) } struct mt76_dev * -mt76_alloc_device(unsigned int size, const struct ieee80211_ops *ops) +mt76_alloc_device(struct device *pdev, unsigned int size, + const struct ieee80211_ops *ops, + const struct mt76_driver_ops *drv_ops) { struct ieee80211_hw *hw; struct mt76_dev *dev; @@ -280,6 +282,9 @@ mt76_alloc_device(unsigned int size, const struct ieee80211_ops *ops) dev = hw->priv; dev->hw = hw; + dev->dev = pdev; + dev->drv = drv_ops; + spin_lock_init(&dev->rx_lock); spin_lock_init(&dev->lock); spin_lock_init(&dev->cc_lock); @@ -721,7 +726,7 @@ int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int *dbm) { struct mt76_dev *dev = hw->priv; - int n_chains = __sw_hweight8(dev->antenna_mask); + int n_chains = hweight8(dev->antenna_mask); *dbm = dev->txpower_cur / 2; diff --git a/drivers/net/wireless/mediatek/mt76/mcu.c b/drivers/net/wireless/mediatek/mt76/mcu.c new file mode 100644 index 000000000000..dbb57b593a87 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mcu.c @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2019 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 "mt76.h" + +struct sk_buff * +mt76_mcu_msg_alloc(const void *data, int head_len, + int data_len, int tail_len) +{ + struct sk_buff *skb; + + skb = alloc_skb(head_len + data_len + tail_len, + GFP_KERNEL); + if (!skb) + return NULL; + + skb_reserve(skb, head_len); + if (data && data_len) + skb_put_data(skb, data, data_len); + + return skb; +} +EXPORT_SYMBOL_GPL(mt76_mcu_msg_alloc); + +/* mmio */ +struct sk_buff *mt76_mcu_get_response(struct mt76_dev *dev, + unsigned long expires) +{ + unsigned long timeout; + + if (!time_is_after_jiffies(expires)) + return NULL; + + timeout = expires - jiffies; + wait_event_timeout(dev->mmio.mcu.wait, + !skb_queue_empty(&dev->mmio.mcu.res_q), + timeout); + return skb_dequeue(&dev->mmio.mcu.res_q); +} +EXPORT_SYMBOL_GPL(mt76_mcu_get_response); + +void mt76_mcu_rx_event(struct mt76_dev *dev, struct sk_buff *skb) +{ + skb_queue_tail(&dev->mmio.mcu.res_q, skb); + wake_up(&dev->mmio.mcu.wait); +} +EXPORT_SYMBOL_GPL(mt76_mcu_rx_event); diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 2bb9db4ed80a..f55dc621e060 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -87,6 +87,7 @@ struct mt76u_buf { struct mt76_dev *dev; struct urb *urb; size_t len; + void *buf; bool done; }; @@ -157,6 +158,9 @@ struct mt76_queue_ops { struct sk_buff *skb, struct mt76_wcid *wcid, struct ieee80211_sta *sta); + int (*tx_queue_skb_raw)(struct mt76_dev *dev, enum mt76_txq_id qid, + struct sk_buff *skb, u32 tx_info); + void *(*dequeue)(struct mt76_dev *dev, struct mt76_queue *q, bool flush, int *len, u32 *info, bool *more); @@ -376,6 +380,7 @@ struct mt76_usb { u16 out_max_packet; u8 in_ep[__MT_EP_IN_MAX]; u16 in_max_packet; + bool sg_en; struct mt76u_mcu { struct mutex mutex; @@ -562,7 +567,7 @@ static inline u16 mt76_rev(struct mt76_dev *dev) #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_queue_add_buf(dev, ...) (dev)->mt76.queue_ops->add_buf(&((dev)->mt76), __VA_ARGS__) +#define mt76_tx_queue_skb_raw(dev, ...) (dev)->mt76.queue_ops->tx_queue_skb_raw(&((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__) #define mt76_queue_kick(dev, ...) (dev)->mt76.queue_ops->kick(&((dev)->mt76), __VA_ARGS__) @@ -582,8 +587,9 @@ mt76_channel_state(struct mt76_dev *dev, struct ieee80211_channel *c) return &msband->chan[idx]; } -struct mt76_dev *mt76_alloc_device(unsigned int size, - const struct ieee80211_ops *ops); +struct mt76_dev *mt76_alloc_device(struct device *pdev, unsigned int size, + const struct ieee80211_ops *ops, + const struct mt76_driver_ops *drv_ops); int mt76_register_device(struct mt76_dev *dev, bool vht, struct ieee80211_rate *rates, int n_rates); void mt76_unregister_device(struct mt76_dev *dev); @@ -722,14 +728,17 @@ static inline u8 q2ep(u8 qid) return qid + 1; } -static inline bool mt76u_check_sg(struct mt76_dev *dev) +static inline int +mt76u_bulk_msg(struct mt76_dev *dev, void *data, int len, int timeout) { struct usb_interface *intf = to_usb_interface(dev->dev); struct usb_device *udev = interface_to_usbdev(intf); + struct mt76_usb *usb = &dev->usb; + unsigned int pipe; + int sent; - return (udev->bus->sg_tablesize > 0 && - (udev->bus->no_sg_constraint || - udev->speed == USB_SPEED_WIRELESS)); + pipe = usb_sndbulkpipe(udev, usb->out_ep[MT_EP_OUT_INBAND_CMD]); + return usb_bulk_msg(udev, pipe, data, len, &sent, timeout); } int mt76u_vendor_request(struct mt76_dev *dev, u8 req, @@ -740,7 +749,7 @@ void mt76u_single_wr(struct mt76_dev *dev, const u8 req, int mt76u_init(struct mt76_dev *dev, struct usb_interface *intf); void mt76u_deinit(struct mt76_dev *dev); int mt76u_buf_alloc(struct mt76_dev *dev, struct mt76u_buf *buf, - int nsgs, int len, int sglen, gfp_t gfp); + int len, int data_len, gfp_t gfp); void mt76u_buf_free(struct mt76u_buf *buf); int mt76u_submit_buf(struct mt76_dev *dev, int dir, int index, struct mt76u_buf *buf, gfp_t gfp, @@ -751,6 +760,13 @@ void mt76u_stop_queues(struct mt76_dev *dev); void mt76u_stop_stat_wk(struct mt76_dev *dev); void mt76u_queues_deinit(struct mt76_dev *dev); +struct sk_buff * +mt76_mcu_msg_alloc(const void *data, int head_len, + int data_len, int tail_len); +void mt76_mcu_rx_event(struct mt76_dev *dev, struct sk_buff *skb); +struct sk_buff *mt76_mcu_get_response(struct mt76_dev *dev, + unsigned long expires); + void mt76u_mcu_complete_urb(struct urb *urb); int mt76u_mcu_init_rx(struct mt76_dev *dev); void mt76u_mcu_deinit(struct mt76_dev *dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c index b2cabce1d74d..ab6dfc026acb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c @@ -152,11 +152,11 @@ static s8 mt76x0_get_delta(struct mt76x02_dev *dev) return mt76x02_rate_power_val(val); } -void mt76x0_get_tx_power_per_rate(struct mt76x02_dev *dev) +void mt76x0_get_tx_power_per_rate(struct mt76x02_dev *dev, + struct ieee80211_channel *chan, + struct mt76_rate_power *t) { - struct ieee80211_channel *chan = dev->mt76.chandef.chan; bool is_2ghz = chan->band == NL80211_BAND_2GHZ; - struct mt76_rate_power *t = &dev->mt76.rate_power; u16 val, addr; s8 delta; @@ -189,7 +189,7 @@ void mt76x0_get_tx_power_per_rate(struct mt76x02_dev *dev) addr = is_2ghz ? MT_EE_TX_POWER_BYRATE_BASE + 8 : 0x126; val = mt76x02_eeprom_get(dev, addr); t->ht[4] = t->ht[5] = t->vht[4] = t->vht[5] = s6_to_s8(val); - t->ht[6] = t->vht[6] = s6_to_s8(val >> 8); + t->ht[6] = t->ht[7] = t->vht[6] = t->vht[7] = s6_to_s8(val >> 8); /* ht-vht mcs 1ss 0, 1, 2, 3 stbc */ addr = is_2ghz ? MT_EE_TX_POWER_BYRATE_BASE + 14 : 0xec; @@ -205,14 +205,15 @@ void mt76x0_get_tx_power_per_rate(struct mt76x02_dev *dev) /* vht mcs 8, 9 5GHz */ val = mt76x02_eeprom_get(dev, 0x132); - t->vht[7] = s6_to_s8(val); - t->vht[8] = s6_to_s8(val >> 8); + t->vht[8] = s6_to_s8(val); + t->vht[9] = s6_to_s8(val >> 8); delta = mt76x0_tssi_enabled(dev) ? 0 : mt76x0_get_delta(dev); mt76x02_add_rate_power_offset(t, delta); } -void mt76x0_get_power_info(struct mt76x02_dev *dev, s8 *tp) +void mt76x0_get_power_info(struct mt76x02_dev *dev, + struct ieee80211_channel *chan, s8 *tp) { struct mt76x0_chan_map { u8 chan; @@ -226,7 +227,6 @@ void mt76x0_get_power_info(struct mt76x02_dev *dev, s8 *tp) { 140, 26 }, { 151, 28 }, { 157, 30 }, { 161, 32 }, { 167, 34 }, { 171, 36 }, { 175, 38 }, }; - struct ieee80211_channel *chan = dev->mt76.chandef.chan; u8 offset, addr; int i, idx = 0; u16 data; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.h b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.h index 42b259f90b6d..7f73034a23b1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.h @@ -25,8 +25,11 @@ struct mt76x02_dev; int mt76x0_eeprom_init(struct mt76x02_dev *dev); void mt76x0_read_rx_gain(struct mt76x02_dev *dev); -void mt76x0_get_tx_power_per_rate(struct mt76x02_dev *dev); -void mt76x0_get_power_info(struct mt76x02_dev *dev, s8 *tp); +void mt76x0_get_tx_power_per_rate(struct mt76x02_dev *dev, + struct ieee80211_channel *chan, + struct mt76_rate_power *t); +void mt76x0_get_power_info(struct mt76x02_dev *dev, + struct ieee80211_channel *chan, s8 *tp); static inline s8 s6_to_s8(u32 val) { diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c index 87b575fe1c74..a529ce111c20 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c @@ -18,6 +18,7 @@ #include "eeprom.h" #include "mcu.h" #include "initvals.h" +#include "../mt76x02_phy.h" static void mt76x0_vht_cap_mask(struct ieee80211_supported_band *sband) { @@ -262,27 +263,24 @@ int mt76x0_init_hardware(struct mt76x02_dev *dev) } EXPORT_SYMBOL_GPL(mt76x0_init_hardware); -struct mt76x02_dev * -mt76x0_alloc_device(struct device *pdev, - const struct mt76_driver_ops *drv_ops, - const struct ieee80211_ops *ops) +static void +mt76x0_init_txpower(struct mt76x02_dev *dev, + struct ieee80211_supported_band *sband) { - struct mt76x02_dev *dev; - struct mt76_dev *mdev; - - mdev = mt76_alloc_device(sizeof(*dev), ops); - if (!mdev) - return NULL; + struct ieee80211_channel *chan; + struct mt76_rate_power t; + s8 tp; + int i; - mdev->dev = pdev; - mdev->drv = drv_ops; + for (i = 0; i < sband->n_channels; i++) { + chan = &sband->channels[i]; - dev = container_of(mdev, struct mt76x02_dev, mt76); - mutex_init(&dev->phy_mutex); + mt76x0_get_tx_power_per_rate(dev, chan, &t); + mt76x0_get_power_info(dev, chan, &tp); - return dev; + chan->max_power = (mt76x02_get_max_rate_power(&t) + tp) / 2; + } } -EXPORT_SYMBOL_GPL(mt76x0_alloc_device); int mt76x0_register_device(struct mt76x02_dev *dev) { @@ -296,9 +294,14 @@ int mt76x0_register_device(struct mt76x02_dev *dev) if (ret) return ret; - /* overwrite unsupported features */ - if (dev->mt76.cap.has_5ghz) + if (dev->mt76.cap.has_5ghz) { + /* overwrite unsupported features */ mt76x0_vht_cap_mask(&dev->mt76.sband_5g.sband); + mt76x0_init_txpower(dev, &dev->mt76.sband_5g.sband); + } + + if (dev->mt76.cap.has_2ghz) + mt76x0_init_txpower(dev, &dev->mt76.sband_2g.sband); mt76x02_init_debugfs(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h b/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h index 46629f61673b..51fbd75dff31 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h @@ -50,10 +50,6 @@ static inline bool is_mt7630(struct mt76x02_dev *dev) } /* Init */ -struct mt76x02_dev * -mt76x0_alloc_device(struct device *pdev, - const struct mt76_driver_ops *drv_ops, - const struct ieee80211_ops *ops); int mt76x0_init_hardware(struct mt76x02_dev *dev); int mt76x0_register_device(struct mt76x02_dev *dev); void mt76x0_chip_onoff(struct mt76x02_dev *dev, bool enable, bool reset); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c index 1472c8699b29..f302162036d0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c @@ -30,7 +30,7 @@ static int mt76x0e_start(struct ieee80211_hw *hw) mt76x02_mac_start(dev); mt76x0_phy_calibrate(dev, true); ieee80211_queue_delayed_work(dev->mt76.hw, &dev->mac_work, - MT_CALIBRATE_INTERVAL); + MT_MAC_WORK_INTERVAL); ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work, MT_CALIBRATE_INTERVAL); set_bit(MT76_STATE_RUNNING, &dev->mt76.state); @@ -174,6 +174,7 @@ mt76x0e_probe(struct pci_dev *pdev, const struct pci_device_id *id) .sta_remove = mt76x02_sta_remove, }; struct mt76x02_dev *dev; + struct mt76_dev *mdev; int ret; ret = pcim_enable_device(pdev); @@ -190,16 +191,20 @@ mt76x0e_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (ret) return ret; - dev = mt76x0_alloc_device(&pdev->dev, &drv_ops, &mt76x0e_ops); - if (!dev) + mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), &mt76x0e_ops, + &drv_ops); + if (!mdev) return -ENOMEM; - mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]); + dev = container_of(mdev, struct mt76x02_dev, mt76); + mutex_init(&dev->phy_mutex); + + mt76_mmio_init(mdev, pcim_iomap_table(pdev)[0]); - dev->mt76.rev = mt76_rr(dev, MT_ASIC_VERSION); - dev_info(dev->mt76.dev, "ASIC revision: %08x\n", dev->mt76.rev); + mdev->rev = mt76_rr(dev, MT_ASIC_VERSION); + dev_info(mdev->dev, "ASIC revision: %08x\n", mdev->rev); - ret = devm_request_irq(dev->mt76.dev, pdev->irq, mt76x02_irq_handler, + ret = devm_request_irq(mdev->dev, pdev->irq, mt76x02_irq_handler, IRQF_SHARED, KBUILD_MODNAME, dev); if (ret) goto error; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c index 1117cdc15b04..3467a32f5fda 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c @@ -847,14 +847,15 @@ void mt76x0_phy_set_txpower(struct mt76x02_dev *dev) struct mt76_rate_power *t = &dev->mt76.rate_power; s8 info; - mt76x0_get_tx_power_per_rate(dev); - mt76x0_get_power_info(dev, &info); + mt76x0_get_tx_power_per_rate(dev, dev->mt76.chandef.chan, t); + mt76x0_get_power_info(dev, dev->mt76.chandef.chan, &info); mt76x02_add_rate_power_offset(t, info); mt76x02_limit_rate_power(t, dev->mt76.txpower_conf); dev->mt76.txpower_cur = mt76x02_get_max_rate_power(t); mt76x02_add_rate_power_offset(t, -info); + dev->target_power = info; mt76x02_phy_set_txpower(dev, info, info); } @@ -1006,14 +1007,16 @@ int mt76x0_phy_set_channel(struct mt76x02_dev *dev, /* enable vco */ mt76x0_rf_set(dev, MT_RF(0, 4), BIT(7)); - if (scan) + if (scan) { + mt76x02_edcca_init(dev, false); return 0; + } mt76x02_init_agc_gain(dev); mt76x0_phy_calibrate(dev, false); mt76x0_phy_set_txpower(dev); - mt76x02_edcca_init(dev); + mt76x02_edcca_init(dev, true); ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work, MT_CALIBRATE_INTERVAL); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c index 3987adaaf2bd..da9d05f6074d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c @@ -118,7 +118,7 @@ static int mt76x0u_start(struct ieee80211_hw *hw) mt76x0_phy_calibrate(dev, true); ieee80211_queue_delayed_work(dev->mt76.hw, &dev->mac_work, - MT_CALIBRATE_INTERVAL); + MT_MAC_WORK_INTERVAL); ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work, MT_CALIBRATE_INTERVAL); set_bit(MT76_STATE_RUNNING, &dev->mt76.state); @@ -206,7 +206,7 @@ static int mt76x0u_register_device(struct mt76x02_dev *dev) goto out_err; /* check hw sg support in order to enable AMSDU */ - if (mt76u_check_sg(&dev->mt76)) + if (dev->mt76.usb.sg_en) hw->max_tx_fragments = MT_SG_MAX_SIZE; else hw->max_tx_fragments = 1; @@ -233,14 +233,18 @@ static int mt76x0u_probe(struct usb_interface *usb_intf, }; struct usb_device *usb_dev = interface_to_usbdev(usb_intf); struct mt76x02_dev *dev; + struct mt76_dev *mdev; u32 asic_rev, mac_rev; int ret; - dev = mt76x0_alloc_device(&usb_intf->dev, &drv_ops, - &mt76x0u_ops); - if (!dev) + mdev = mt76_alloc_device(&usb_intf->dev, sizeof(*dev), &mt76x0u_ops, + &drv_ops); + if (!mdev) return -ENOMEM; + dev = container_of(mdev, struct mt76x02_dev, mt76); + mutex_init(&dev->phy_mutex); + /* Quirk for Archer T1U */ if (id->driver_info) dev->no_2ghz = true; @@ -250,27 +254,27 @@ static int mt76x0u_probe(struct usb_interface *usb_intf, usb_set_intfdata(usb_intf, dev); - mt76x02u_init_mcu(&dev->mt76); - ret = mt76u_init(&dev->mt76, usb_intf); + mt76x02u_init_mcu(mdev); + ret = mt76u_init(mdev, usb_intf); if (ret) goto err; /* Disable the HW, otherwise MCU fail to initalize on hot reboot */ mt76x0_chip_onoff(dev, false, false); - if (!mt76x02_wait_for_mac(&dev->mt76)) { + if (!mt76x02_wait_for_mac(mdev)) { ret = -ETIMEDOUT; goto err; } asic_rev = mt76_rr(dev, MT_ASIC_VERSION); mac_rev = mt76_rr(dev, MT_MAC_CSR0); - dev_info(dev->mt76.dev, "ASIC revision: %08x MAC revision: %08x\n", + dev_info(mdev->dev, "ASIC revision: %08x MAC revision: %08x\n", asic_rev, mac_rev); /* Note: vendor driver skips this check for MT76X0U */ if (!(mt76_rr(dev, MT_EFUSE_CTRL) & MT_EFUSE_CTRL_SEL)) - dev_warn(dev->mt76.dev, "Warning: eFUSE not present\n"); + dev_warn(mdev->dev, "Warning: eFUSE not present\n"); ret = mt76x0u_register_device(dev); if (ret < 0) @@ -282,7 +286,7 @@ err: usb_set_intfdata(usb_intf, NULL); usb_put_dev(interface_to_usbdev(usb_intf)); - ieee80211_free_hw(dev->mt76.hw); + ieee80211_free_hw(mdev->hw); return ret; } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c index f391d2d21fbc..4a282761ca58 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c @@ -140,12 +140,6 @@ static int mt76x0u_load_firmware(struct mt76x02_dev *dev) FIELD_PREP(MT_USB_DMA_CFG_RX_BULK_AGG_TOUT, 0x20)); mt76x02u_mcu_fw_reset(dev); usleep_range(5000, 6000); -/* - mt76x0_rmw(dev, MT_PBF_CFG, 0, (MT_PBF_CFG_TX0Q_EN | - MT_PBF_CFG_TX1Q_EN | - MT_PBF_CFG_TX2Q_EN | - MT_PBF_CFG_TX3Q_EN)); -*/ mt76_wr(dev, MT_FCE_PSE_CTRL, 1); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02.h b/drivers/net/wireless/mediatek/mt76/mt76x02.h index 6d96766a6ed3..3464b4ca2ea8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h @@ -27,6 +27,7 @@ #include "mt76x02_dma.h" #define MT_CALIBRATE_INTERVAL HZ +#define MT_MAC_WORK_INTERVAL (HZ / 10) #define MT_WATCHDOG_TIME (HZ / 10) #define MT_TX_HANG_TH 10 @@ -73,6 +74,8 @@ struct mt76x02_dev { struct mutex phy_mutex; + u16 vif_mask; + u8 txdone_seq; DECLARE_KFIFO_PTR(txstatus_fifo, struct mt76x02_tx_status); @@ -114,6 +117,7 @@ struct mt76x02_dev { bool ed_monitor; u8 ed_trigger; u8 ed_silent; + ktime_t ed_time; }; extern struct ieee80211_rate mt76x02_rates[12]; @@ -128,8 +132,7 @@ void mt76x02_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); void mt76x02_config_mac_addr_list(struct mt76x02_dev *dev); -void mt76x02_vif_init(struct mt76x02_dev *dev, struct ieee80211_vif *vif, - unsigned int idx); + int mt76x02_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif); void mt76x02_remove_interface(struct ieee80211_hw *hw, diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c index 19fdcab746a0..e4649103efd4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c @@ -886,7 +886,7 @@ mt76x02_dfs_set_domain(struct mt76x02_dev *dev, tasklet_disable(&dfs_pd->dfs_tasklet); dev->ed_monitor = region == NL80211_DFS_ETSI; - mt76x02_edcca_init(dev); + mt76x02_edcca_init(dev, true); dfs_pd->region = region; mt76x02_dfs_init_params(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index 63fa27d2c404..be2979f34f31 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -291,6 +291,13 @@ void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi, memset(txwi, 0, sizeof(*txwi)); + if (!info->control.hw_key && wcid && wcid->hw_key_idx != 0xff && + ieee80211_has_protected(hdr->frame_control)) { + wcid = NULL; + ieee80211_get_tx_rates(info->control.vif, sta, skb, + info->control.rates, 1); + } + if (wcid) txwi->wcid = wcid->idx; else @@ -307,7 +314,7 @@ void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi, ccmp_pn[6] = pn >> 32; ccmp_pn[7] = pn >> 40; txwi->iv = *((__le32 *)&ccmp_pn[0]); - txwi->eiv = *((__le32 *)&ccmp_pn[1]); + txwi->eiv = *((__le32 *)&ccmp_pn[4]); } spin_lock_bh(&dev->mt76.lock); @@ -548,8 +555,11 @@ mt76x02_mac_process_rate(struct mt76x02_dev *dev, return 0; } -void mt76x02_mac_setaddr(struct mt76x02_dev *dev, u8 *addr) +void mt76x02_mac_setaddr(struct mt76x02_dev *dev, const u8 *addr) { + static const u8 null_addr[ETH_ALEN] = {}; + int i; + ether_addr_copy(dev->mt76.macaddr, addr); if (!is_valid_ether_addr(dev->mt76.macaddr)) { @@ -563,6 +573,16 @@ void mt76x02_mac_setaddr(struct mt76x02_dev *dev, u8 *addr) mt76_wr(dev, MT_MAC_ADDR_DW1, get_unaligned_le16(dev->mt76.macaddr + 4) | FIELD_PREP(MT_MAC_ADDR_DW1_U2ME_MASK, 0xff)); + + mt76_wr(dev, MT_MAC_BSSID_DW0, + get_unaligned_le32(dev->mt76.macaddr)); + mt76_wr(dev, MT_MAC_BSSID_DW1, + get_unaligned_le16(dev->mt76.macaddr + 4) | + FIELD_PREP(MT_MAC_BSSID_DW1_MBSS_MODE, 3) | /* 8 APs + 8 STAs */ + MT_MAC_BSSID_DW1_MBSS_LOCAL_BIT); + + for (i = 0; i < 16; i++) + mt76x02_mac_set_bssid(dev, i, null_addr); } EXPORT_SYMBOL_GPL(mt76x02_mac_setaddr); @@ -588,7 +608,7 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb, u16 rate = le16_to_cpu(rxwi->rate); u16 tid_sn = le16_to_cpu(rxwi->tid_sn); bool unicast = rxwi->rxinfo & cpu_to_le32(MT_RXINFO_UNICAST); - int i, pad_len = 0, nstreams = dev->mt76.chainmask & 0xf; + int pad_len = 0, nstreams = dev->mt76.chainmask & 0xf; s8 signal; u8 pn_len; u8 wcid; @@ -648,12 +668,13 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb, status->chains = BIT(0); signal = mt76x02_mac_get_rssi(dev, rxwi->rssi[0], 0); - for (i = 0; i < nstreams; i++) { - status->chains |= BIT(i); - status->chain_signal[i] = mt76x02_mac_get_rssi(dev, - rxwi->rssi[i], - i); - signal = max_t(s8, signal, status->chain_signal[i]); + status->chain_signal[0] = signal; + if (nstreams > 1) { + status->chains |= BIT(1); + status->chain_signal[1] = mt76x02_mac_get_rssi(dev, + rxwi->rssi[1], + 1); + signal = max_t(s8, signal, status->chain_signal[1]); } status->signal = signal; status->freq = dev->mt76.chandef.chan->center_freq; @@ -871,12 +892,12 @@ mt76x02_edcca_tx_enable(struct mt76x02_dev *dev, bool enable) dev->ed_tx_blocked = !enable; } -void mt76x02_edcca_init(struct mt76x02_dev *dev) +void mt76x02_edcca_init(struct mt76x02_dev *dev, bool enable) { dev->ed_trigger = 0; dev->ed_silent = 0; - if (dev->ed_monitor) { + if (dev->ed_monitor && enable) { struct ieee80211_channel *chan = dev->mt76.chandef.chan; u8 ed_th = chan->band == NL80211_BAND_5GHZ ? 0x0e : 0x20; @@ -899,17 +920,27 @@ void mt76x02_edcca_init(struct mt76x02_dev *dev) } } mt76x02_edcca_tx_enable(dev, true); + + /* clear previous CCA timer value */ + mt76_rr(dev, MT_ED_CCA_TIMER); + dev->ed_time = ktime_get_boottime(); } EXPORT_SYMBOL_GPL(mt76x02_edcca_init); -#define MT_EDCCA_TH 90 +#define MT_EDCCA_TH 92 #define MT_EDCCA_BLOCK_TH 2 static void mt76x02_edcca_check(struct mt76x02_dev *dev) { - u32 val, busy; + ktime_t cur_time; + u32 active, val, busy; + cur_time = ktime_get_boottime(); val = mt76_rr(dev, MT_ED_CCA_TIMER); - busy = (val * 100) / jiffies_to_usecs(MT_CALIBRATE_INTERVAL); + + active = ktime_to_us(ktime_sub(cur_time, dev->ed_time)); + dev->ed_time = cur_time; + + busy = (val * 100) / active; busy = min_t(u32, busy, 100); if (busy > MT_EDCCA_TH) { @@ -955,7 +986,7 @@ void mt76x02_mac_work(struct work_struct *work) mt76_tx_status_check(&dev->mt76, NULL, false); ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work, - MT_CALIBRATE_INTERVAL); + MT_MAC_WORK_INTERVAL); } void mt76x02_mac_set_bssid(struct mt76x02_dev *dev, u8 idx, const u8 *addr) @@ -1047,8 +1078,9 @@ int mt76x02_mac_set_beacon(struct mt76x02_dev *dev, u8 vif_idx, return 0; } -void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev, - u8 vif_idx, bool val) +static void +__mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev, u8 vif_idx, + bool val, struct sk_buff *skb) { u8 old_mask = dev->beacon_mask; bool en; @@ -1056,6 +1088,8 @@ void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev, if (val) { dev->beacon_mask |= BIT(vif_idx); + if (skb) + mt76x02_mac_set_beacon(dev, vif_idx, skb); } else { dev->beacon_mask &= ~BIT(vif_idx); mt76x02_mac_set_beacon(dev, vif_idx, NULL); @@ -1066,14 +1100,34 @@ void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev, 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 (mt76_is_usb(dev)) + return; + + mt76_rmw_field(dev, MT_INT_TIMER_EN, MT_INT_TIMER_EN_PRE_TBTT_EN, 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 mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev, + struct ieee80211_vif *vif, bool val) +{ + u8 vif_idx = ((struct mt76x02_vif *)vif->drv_priv)->idx; + struct sk_buff *skb = NULL; + + if (mt76_is_mmio(dev)) + tasklet_disable(&dev->pre_tbtt_tasklet); + else if (val) + skb = ieee80211_beacon_get(mt76_hw(dev), vif); + + __mt76x02_mac_set_beacon_enable(dev, vif_idx, val, skb); + + if (mt76_is_mmio(dev)) + tasklet_enable(&dev->pre_tbtt_tasklet); +} diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h index 940c07f665cd..6b1f25d2f64c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h @@ -191,7 +191,7 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb, void mt76x02_mac_set_tx_protection(struct mt76x02_dev *dev, bool legacy_prot, int ht_mode); void mt76x02_mac_set_rts_thresh(struct mt76x02_dev *dev, u32 val); -void mt76x02_mac_setaddr(struct mt76x02_dev *dev, u8 *addr); +void mt76x02_mac_setaddr(struct mt76x02_dev *dev, const u8 *addr); void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi, struct sk_buff *skb, struct mt76_wcid *wcid, struct ieee80211_sta *sta, int len); @@ -204,8 +204,8 @@ void mt76x02_mac_work(struct work_struct *work); void mt76x02_mac_set_bssid(struct mt76x02_dev *dev, u8 idx, const u8 *addr); int mt76x02_mac_set_beacon(struct mt76x02_dev *dev, u8 vif_idx, struct sk_buff *skb); -void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev, u8 vif_idx, - bool val); +void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev, + struct ieee80211_vif *vif, bool val); -void mt76x02_edcca_init(struct mt76x02_dev *dev); +void mt76x02_edcca_init(struct mt76x02_dev *dev, bool enable); #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c index b7f4edb729e3..4752c104abf3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c @@ -21,70 +21,13 @@ #include "mt76x02_mcu.h" -static struct sk_buff *mt76x02_mcu_msg_alloc(const void *data, int len) -{ - struct sk_buff *skb; - - skb = alloc_skb(len, GFP_KERNEL); - if (!skb) - return NULL; - memcpy(skb_put(skb, len), data, len); - - return skb; -} - -static struct sk_buff * -mt76x02_mcu_get_response(struct mt76x02_dev *dev, unsigned long expires) -{ - unsigned long timeout; - - if (!time_is_after_jiffies(expires)) - return NULL; - - timeout = expires - jiffies; - wait_event_timeout(dev->mt76.mmio.mcu.wait, - !skb_queue_empty(&dev->mt76.mmio.mcu.res_q), - timeout); - return skb_dequeue(&dev->mt76.mmio.mcu.res_q); -} - -static int -mt76x02_tx_queue_mcu(struct mt76x02_dev *dev, enum mt76_txq_id qid, - struct sk_buff *skb, int cmd, int seq) -{ - struct mt76_queue *q = &dev->mt76.q_tx[qid]; - struct mt76_queue_buf buf; - dma_addr_t addr; - u32 tx_info; - - tx_info = MT_MCU_MSG_TYPE_CMD | - FIELD_PREP(MT_MCU_MSG_CMD_TYPE, cmd) | - FIELD_PREP(MT_MCU_MSG_CMD_SEQ, seq) | - FIELD_PREP(MT_MCU_MSG_PORT, CPU_TX_PORT) | - FIELD_PREP(MT_MCU_MSG_LEN, skb->len); - - addr = dma_map_single(dev->mt76.dev, skb->data, skb->len, - DMA_TO_DEVICE); - if (dma_mapping_error(dev->mt76.dev, addr)) - return -ENOMEM; - - buf.addr = addr; - buf.len = skb->len; - - spin_lock_bh(&q->lock); - mt76_queue_add_buf(dev, q, &buf, 1, tx_info, skb, NULL); - mt76_queue_kick(dev, q); - spin_unlock_bh(&q->lock); - - return 0; -} - int mt76x02_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, int len, bool wait_resp) { struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76); unsigned long expires = jiffies + HZ; struct sk_buff *skb; + u32 tx_info; int ret; u8 seq; @@ -98,7 +41,13 @@ int mt76x02_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, if (!seq) seq = ++mdev->mmio.mcu.msg_seq & 0xf; - ret = mt76x02_tx_queue_mcu(dev, MT_TXQ_MCU, skb, cmd, seq); + tx_info = MT_MCU_MSG_TYPE_CMD | + FIELD_PREP(MT_MCU_MSG_CMD_TYPE, cmd) | + FIELD_PREP(MT_MCU_MSG_CMD_SEQ, seq) | + FIELD_PREP(MT_MCU_MSG_PORT, CPU_TX_PORT) | + FIELD_PREP(MT_MCU_MSG_LEN, skb->len); + + ret = mt76_tx_queue_skb_raw(dev, MT_TXQ_MCU, skb, tx_info); if (ret) goto out; @@ -106,7 +55,7 @@ int mt76x02_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, u32 *rxfce; bool check_seq = false; - skb = mt76x02_mcu_get_response(dev, expires); + skb = mt76_mcu_get_response(&dev->mt76, expires); if (!skb) { dev_err(mdev->dev, "MCU message %d (seq %d) timed out\n", cmd, diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.h index 7e4004120102..a7b0d3e5df1d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.h @@ -96,6 +96,12 @@ struct mt76x02_patch_header { u8 pad[2]; }; +static inline struct sk_buff * +mt76x02_mcu_msg_alloc(const void *data, int len) +{ + return mt76_mcu_msg_alloc(data, 0, len, 0); +} + int mt76x02_mcu_cleanup(struct mt76x02_dev *dev); int mt76x02_mcu_calibrate(struct mt76x02_dev *dev, int type, u32 param); int mt76x02_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c b/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c index a5413a309a0a..94f47248c59f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c @@ -22,7 +22,6 @@ void mt76x02_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, struct sk_buff *skb) { - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct mt76x02_dev *dev = hw->priv; struct ieee80211_vif *vif = info->control.vif; @@ -33,13 +32,7 @@ void mt76x02_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, msta = (struct mt76x02_sta *)control->sta->drv_priv; wcid = &msta->wcid; - /* sw encrypted frames */ - if (!info->control.hw_key && wcid->hw_key_idx != 0xff && - ieee80211_has_protected(hdr->frame_control)) - control->sta = NULL; - } - - if (vif && !control->sta) { + } else if (vif) { struct mt76x02_vif *mvif; mvif = (struct mt76x02_vif *)vif->drv_priv; @@ -58,8 +51,7 @@ void mt76x02_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, if (q == MT_RXQ_MCU) { /* this is used just by mmio code */ - skb_queue_tail(&mdev->mmio.mcu.res_q, skb); - wake_up(&mdev->mmio.mcu.wait); + mt76_mcu_rx_event(&dev->mt76, skb); return; } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c index 098d05e109e7..43f07461c8d3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c @@ -49,7 +49,12 @@ int mt76x02u_skb_dma_info(struct sk_buff *skb, int port, u32 flags) FIELD_PREP(MT_TXD_INFO_DPORT, port) | flags; put_unaligned_le32(info, skb_push(skb, sizeof(info))); + /* Add zero pad of 4 - 7 bytes */ pad = round_up(skb->len, 4) + 4 - skb->len; + + /* First packet of a A-MSDU burst keeps track of the whole burst + * length, need to update lenght of it and the last packet. + */ skb_walk_frags(skb, iter) { last = iter; if (!iter->next) { @@ -59,11 +64,10 @@ int mt76x02u_skb_dma_info(struct sk_buff *skb, int port, u32 flags) } } - if (unlikely(pad)) { - if (skb_pad(last, pad)) - return -ENOMEM; - __skb_put(last, pad); - } + if (skb_pad(last, pad)) + return -ENOMEM; + __skb_put(last, pad); + return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c index 6db789f90269..e469e383cb88 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c @@ -28,21 +28,6 @@ #define MT_TX_CPU_FROM_FCE_CPU_DESC_IDX 0x09a8 -static struct sk_buff * -mt76x02u_mcu_msg_alloc(const void *data, int len) -{ - struct sk_buff *skb; - - skb = alloc_skb(MT_CMD_HDR_LEN + len + 8, GFP_KERNEL); - if (!skb) - return NULL; - - skb_reserve(skb, MT_CMD_HDR_LEN); - skb_put_data(skb, data, len); - - return skb; -} - static void mt76x02u_multiple_mcu_reads(struct mt76_dev *dev, u8 *data, int len) { @@ -78,9 +63,9 @@ static int mt76x02u_mcu_wait_resp(struct mt76_dev *dev, u8 seq) struct mt76_usb *usb = &dev->usb; struct mt76u_buf *buf = &usb->mcu.res; struct urb *urb = buf->urb; + u8 *data = buf->buf; int i, ret; u32 rxfce; - u8 *data; for (i = 0; i < 5; i++) { if (!wait_for_completion_timeout(&usb->mcu.cmpl, @@ -90,7 +75,6 @@ static int mt76x02u_mcu_wait_resp(struct mt76_dev *dev, u8 seq) if (urb->status) return -EIO; - data = sg_virt(&urb->sg[0]); if (usb->mcu.rp) mt76x02u_multiple_mcu_reads(dev, data + 4, urb->actual_length - 8); @@ -121,18 +105,14 @@ static int __mt76x02u_mcu_send_msg(struct mt76_dev *dev, struct sk_buff *skb, int cmd, bool wait_resp) { - struct usb_interface *intf = to_usb_interface(dev->dev); - struct usb_device *udev = interface_to_usbdev(intf); struct mt76_usb *usb = &dev->usb; - unsigned int pipe; - int ret, sent; + int ret; u8 seq = 0; u32 info; if (test_bit(MT76_REMOVED, &dev->state)) return 0; - pipe = usb_sndbulkpipe(udev, usb->out_ep[MT_EP_OUT_INBAND_CMD]); if (wait_resp) { seq = ++usb->mcu.msg_seq & 0xf; if (!seq) @@ -146,7 +126,7 @@ __mt76x02u_mcu_send_msg(struct mt76_dev *dev, struct sk_buff *skb, if (ret) return ret; - ret = usb_bulk_msg(udev, pipe, skb->data, skb->len, &sent, 500); + ret = mt76u_bulk_msg(dev, skb->data, skb->len, 500); if (ret) return ret; @@ -166,7 +146,7 @@ mt76x02u_mcu_send_msg(struct mt76_dev *dev, int cmd, const void *data, struct sk_buff *skb; int err; - skb = mt76x02u_mcu_msg_alloc(data, len); + skb = mt76_mcu_msg_alloc(data, MT_CMD_HDR_LEN, len, 8); if (!skb) return -ENOMEM; @@ -268,14 +248,12 @@ void mt76x02u_mcu_fw_reset(struct mt76x02_dev *dev) EXPORT_SYMBOL_GPL(mt76x02u_mcu_fw_reset); static int -__mt76x02u_mcu_fw_send_data(struct mt76x02_dev *dev, struct mt76u_buf *buf, +__mt76x02u_mcu_fw_send_data(struct mt76x02_dev *dev, u8 *data, const void *fw_data, int len, u32 dst_addr) { - u8 *data = sg_virt(&buf->urb->sg[0]); - DECLARE_COMPLETION_ONSTACK(cmpl); __le32 info; u32 val; - int err; + int err, data_len; info = cpu_to_le32(FIELD_PREP(MT_MCU_MSG_PORT, CPU_TX_PORT) | FIELD_PREP(MT_MCU_MSG_LEN, len) | @@ -291,25 +269,12 @@ __mt76x02u_mcu_fw_send_data(struct mt76x02_dev *dev, struct mt76u_buf *buf, mt76u_single_wr(&dev->mt76, MT_VEND_WRITE_FCE, MT_FCE_DMA_LEN, len << 16); - buf->len = MT_CMD_HDR_LEN + len + sizeof(info); - err = mt76u_submit_buf(&dev->mt76, USB_DIR_OUT, - MT_EP_OUT_INBAND_CMD, - buf, GFP_KERNEL, - mt76u_mcu_complete_urb, &cmpl); - if (err < 0) - return err; - - if (!wait_for_completion_timeout(&cmpl, - msecs_to_jiffies(1000))) { - dev_err(dev->mt76.dev, "firmware upload timed out\n"); - usb_kill_urb(buf->urb); - return -ETIMEDOUT; - } + data_len = MT_CMD_HDR_LEN + len + sizeof(info); - if (mt76u_urb_error(buf->urb)) { - dev_err(dev->mt76.dev, "firmware upload failed: %d\n", - buf->urb->status); - return buf->urb->status; + err = mt76u_bulk_msg(&dev->mt76, data, data_len, 1000); + if (err) { + dev_err(dev->mt76.dev, "firmware upload failed: %d\n", err); + return err; } val = mt76_rr(dev, MT_TX_CPU_FROM_FCE_CPU_DESC_IDX); @@ -322,17 +287,16 @@ __mt76x02u_mcu_fw_send_data(struct mt76x02_dev *dev, struct mt76u_buf *buf, int mt76x02u_mcu_fw_send_data(struct mt76x02_dev *dev, const void *data, int data_len, u32 max_payload, u32 offset) { - int err, len, pos = 0, max_len = max_payload - 8; - struct mt76u_buf buf; + int len, err = 0, pos = 0, max_len = max_payload - 8; + u8 *buf; - err = mt76u_buf_alloc(&dev->mt76, &buf, 1, max_payload, max_payload, - GFP_KERNEL); - if (err < 0) - return err; + buf = kmalloc(max_payload, GFP_KERNEL); + if (!buf) + return -ENOMEM; while (data_len > 0) { len = min_t(int, data_len, max_len); - err = __mt76x02u_mcu_fw_send_data(dev, &buf, data + pos, + err = __mt76x02u_mcu_fw_send_data(dev, buf, data + pos, len, offset + pos); if (err < 0) break; @@ -341,7 +305,7 @@ int mt76x02u_mcu_fw_send_data(struct mt76x02_dev *dev, const void *data, pos += len; usleep_range(5000, 10000); } - mt76u_buf_free(&buf); + kfree(buf); return err; } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c index 062614ad0d51..11b5f664f5b1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c @@ -140,10 +140,16 @@ void mt76x02_init_device(struct mt76x02_dev *dev) hw->max_rate_tries = 1; hw->extra_tx_headroom = 2; + wiphy->interface_modes = + BIT(NL80211_IFTYPE_STATION) | +#ifdef CONFIG_MAC80211_MESH + BIT(NL80211_IFTYPE_MESH_POINT) | +#endif + BIT(NL80211_IFTYPE_ADHOC); + if (mt76_is_usb(dev)) { hw->extra_tx_headroom += sizeof(struct mt76x02_txwi) + MT_DMA_HDR_LEN; - wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); } else { INIT_DELAYED_WORK(&dev->wdt_work, mt76x02_wdt_work); @@ -152,18 +158,9 @@ void mt76x02_init_device(struct mt76x02_dev *dev) wiphy->reg_notifier = mt76x02_regd_notifier; wiphy->iface_combinations = mt76x02_if_comb; wiphy->n_iface_combinations = ARRAY_SIZE(mt76x02_if_comb); - 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->interface_modes |= BIT(NL80211_IFTYPE_AP); wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; - wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS); - /* init led callbacks */ if (IS_ENABLED(CONFIG_MT76_LEDS)) { dev->mt76.led_cdev.brightness_set = @@ -172,6 +169,8 @@ void mt76x02_init_device(struct mt76x02_dev *dev) } } + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS); + hw->sta_data_size = sizeof(struct mt76x02_sta); hw->vif_data_size = sizeof(struct mt76x02_vif); @@ -268,8 +267,9 @@ void mt76x02_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, } EXPORT_SYMBOL_GPL(mt76x02_sta_remove); -void mt76x02_vif_init(struct mt76x02_dev *dev, struct ieee80211_vif *vif, - unsigned int idx) +static void +mt76x02_vif_init(struct mt76x02_dev *dev, struct ieee80211_vif *vif, + unsigned int idx) { struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv; struct mt76_txq *mtxq; @@ -282,7 +282,6 @@ void mt76x02_vif_init(struct mt76x02_dev *dev, struct ieee80211_vif *vif, mt76_txq_init(&dev->mt76, vif->txq); } -EXPORT_SYMBOL_GPL(mt76x02_vif_init); int mt76x02_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) @@ -309,6 +308,15 @@ mt76x02_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) if (vif->type == NL80211_IFTYPE_STATION) idx += 8; + if (dev->vif_mask & BIT(idx)) + return -EBUSY; + + /* Allow to change address in HW if we create first interface. */ + if (!dev->vif_mask && !ether_addr_equal(dev->mt76.macaddr, vif->addr)) + mt76x02_mac_setaddr(dev, vif->addr); + + dev->vif_mask |= BIT(idx); + mt76x02_vif_init(dev, vif, idx); return 0; } @@ -318,8 +326,10 @@ void mt76x02_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct mt76x02_dev *dev = hw->priv; + struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv; mt76_txq_remove(&dev->mt76, vif->txq); + dev->vif_mask &= ~BIT(mvif->idx); } EXPORT_SYMBOL_GPL(mt76x02_remove_interface); @@ -421,7 +431,7 @@ int mt76x02_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, } else { if (idx == wcid->hw_key_idx) { wcid->hw_key_idx = -1; - wcid->sw_iv = true; + wcid->sw_iv = false; } key = NULL; @@ -657,29 +667,26 @@ static void mt76x02_set_beacon_offsets(struct mt76x02_dev *dev) void mt76x02_init_beacon_config(struct mt76x02_dev *dev) { - static const u8 null_addr[ETH_ALEN] = {}; int i; - mt76_wr(dev, MT_MAC_BSSID_DW0, - get_unaligned_le32(dev->mt76.macaddr)); - mt76_wr(dev, MT_MAC_BSSID_DW1, - get_unaligned_le16(dev->mt76.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); + if (mt76_is_mmio(dev)) { + /* 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_clear(dev, MT_BEACON_TIME_CFG, (MT_BEACON_TIME_CFG_TIMER_EN | + MT_BEACON_TIME_CFG_SYNC_MODE | + MT_BEACON_TIME_CFG_TBTT_EN | + MT_BEACON_TIME_CFG_BEACON_TX)); mt76_wr(dev, MT_BCN_BYPASS_MASK, 0xffff); - for (i = 0; i < 8; i++) { - mt76x02_mac_set_bssid(dev, i, null_addr); + for (i = 0; i < 8; i++) mt76x02_mac_set_beacon(dev, i, NULL); - } + mt76x02_set_beacon_offsets(dev); } EXPORT_SYMBOL_GPL(mt76x02_init_beacon_config); @@ -697,12 +704,8 @@ void mt76x02_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_BSSID) mt76x02_mac_set_bssid(dev, mvif->idx, info->bssid); - if (changed & BSS_CHANGED_BEACON_ENABLED) { - tasklet_disable(&dev->pre_tbtt_tasklet); - mt76x02_mac_set_beacon_enable(dev, mvif->idx, - info->enable_beacon); - tasklet_enable(&dev->pre_tbtt_tasklet); - } + if (changed & BSS_CHANGED_BEACON_ENABLED) + mt76x02_mac_set_beacon_enable(dev, vif, info->enable_beacon); if (changed & BSS_CHANGED_HT || changed & BSS_CHANGED_ERP_CTS_PROT) mt76x02_mac_set_tx_protection(dev, info->use_cts_prot, diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h b/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h index 28ec19acf9db..6c619f1c65c9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h @@ -49,7 +49,6 @@ static inline bool mt76x2_channel_silent(struct mt76x02_dev *dev) 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_phy_power_on(struct mt76x02_dev *dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2u.h b/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2u.h index 0b0075411b34..787cdfdf5db5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2u.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2u.h @@ -29,7 +29,6 @@ extern const struct ieee80211_ops mt76x2u_ops; -struct mt76x02_dev *mt76x2u_alloc_device(struct device *pdev); int mt76x2u_register_device(struct mt76x02_dev *dev); int mt76x2u_init_hardware(struct mt76x02_dev *dev); void mt76x2u_cleanup(struct mt76x02_dev *dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c index 92432fe97312..6274655e1f7e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c @@ -30,7 +30,19 @@ static const struct pci_device_id mt76pci_device_table[] = { static int mt76pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { + static const struct mt76_driver_ops drv_ops = { + .txwi_size = sizeof(struct mt76x02_txwi), + .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 = mt76x02_sta_ps, + .sta_add = mt76x02_sta_add, + .sta_remove = mt76x02_sta_remove, + }; struct mt76x02_dev *dev; + struct mt76_dev *mdev; int ret; ret = pcim_enable_device(pdev); @@ -47,17 +59,19 @@ mt76pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (ret) return ret; - dev = mt76x2_alloc_device(&pdev->dev); - if (!dev) + mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), &mt76x2_ops, + &drv_ops); + if (!mdev) return -ENOMEM; - mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]); + dev = container_of(mdev, struct mt76x02_dev, mt76); + mt76_mmio_init(mdev, pcim_iomap_table(pdev)[0]); mt76x2_reset_wlan(dev, false); - dev->mt76.rev = mt76_rr(dev, MT_ASIC_VERSION); - dev_info(dev->mt76.dev, "ASIC revision: %08x\n", dev->mt76.rev); + mdev->rev = mt76_rr(dev, MT_ASIC_VERSION); + dev_info(mdev->dev, "ASIC revision: %08x\n", mdev->rev); - ret = devm_request_irq(dev->mt76.dev, pdev->irq, mt76x02_irq_handler, + ret = devm_request_irq(mdev->dev, pdev->irq, mt76x02_irq_handler, IRQF_SHARED, KBUILD_MODNAME, dev); if (ret) goto error; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c index 4347d5e7a915..d4e3d7c11d74 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c @@ -119,9 +119,7 @@ static int mt76x2_mac_reset(struct mt76x02_dev *dev, bool hard) mt76_wr(dev, MT_MCU_CLOCK_CTL, 0x1401); mt76_clear(dev, MT_FCE_L2_STUFF, MT_FCE_L2_STUFF_WR_MPDU_LEN_EN); - mt76_wr(dev, MT_MAC_ADDR_DW0, get_unaligned_le32(macaddr)); - mt76_wr(dev, MT_MAC_ADDR_DW1, get_unaligned_le16(macaddr + 4)); - + mt76x02_mac_setaddr(dev, macaddr); mt76x02_init_beacon_config(dev); if (!hard) return 0; @@ -315,33 +313,6 @@ void mt76x2_cleanup(struct mt76x02_dev *dev) mt76x02_mcu_cleanup(dev); } -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 = 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 = mt76x02_sta_ps, - .sta_add = mt76x02_sta_add, - .sta_remove = mt76x02_sta_remove, - }; - struct mt76x02_dev *dev; - struct mt76_dev *mdev; - - mdev = mt76_alloc_device(sizeof(*dev), &mt76x2_ops); - if (!mdev) - return NULL; - - dev = container_of(mdev, struct mt76x02_dev, mt76); - mdev->dev = pdev; - mdev->drv = &drv_ops; - - return dev; -} - int mt76x2_register_device(struct mt76x02_dev *dev) { int ret; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c index 06a26a152ba4..878ce92405ed 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c @@ -33,7 +33,7 @@ mt76x2_start(struct ieee80211_hw *hw) goto out; ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work, - MT_CALIBRATE_INTERVAL); + MT_MAC_WORK_INTERVAL); ieee80211_queue_delayed_work(mt76_hw(dev), &dev->wdt_work, MT_WATCHDOG_TIME); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c index 65ed62229a5b..97ec575699d0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c @@ -240,8 +240,10 @@ int mt76x2_phy_set_channel(struct mt76x02_dev *dev, mt76_wr(dev, MT_BBP(AGC, 2), 0x00007070); mt76_wr(dev, MT_TXOP_CTRL_CFG, 0x04101B3F); - if (scan) + if (scan) { + mt76x02_edcca_init(dev, false); return 0; + } mt76x2_phy_channel_calibrate(dev, true); mt76x02_init_agc_gain(dev); @@ -254,7 +256,7 @@ int mt76x2_phy_set_channel(struct mt76x02_dev *dev, 0x38); } - mt76x02_edcca_init(dev); + mt76x02_edcca_init(dev, true); ieee80211_queue_delayed_work(mt76_hw(dev), &dev->cal_work, MT_CALIBRATE_INTERVAL); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c b/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c index e2ee5e498da7..1848e8ab2e21 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c @@ -241,7 +241,7 @@ void mt76x2_phy_tssi_compensate(struct mt76x02_dev *dev) t.offset1 = txp.chain[1].tssi_offset; mt76x2_mcu_tssi_comp(dev, &t); - if (t.pa_mode || dev->cal.dpd_cal_done) + if (t.pa_mode || dev->cal.dpd_cal_done || dev->ed_tx_blocked) return; usleep_range(10000, 20000); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c index 4d1788eb3812..f81a85e96922 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c @@ -36,24 +36,36 @@ static const struct usb_device_id mt76x2u_device_table[] = { static int mt76x2u_probe(struct usb_interface *intf, const struct usb_device_id *id) { + static const struct mt76_driver_ops drv_ops = { + .tx_prepare_skb = mt76x02u_tx_prepare_skb, + .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 usb_device *udev = interface_to_usbdev(intf); struct mt76x02_dev *dev; + struct mt76_dev *mdev; int err; - dev = mt76x2u_alloc_device(&intf->dev); - if (!dev) + mdev = mt76_alloc_device(&intf->dev, sizeof(*dev), &mt76x2u_ops, + &drv_ops); + if (!mdev) return -ENOMEM; + dev = container_of(mdev, struct mt76x02_dev, mt76); + udev = usb_get_dev(udev); usb_reset_device(udev); - mt76x02u_init_mcu(&dev->mt76); - err = mt76u_init(&dev->mt76, intf); + mt76x02u_init_mcu(mdev); + err = mt76u_init(mdev, intf); if (err < 0) goto err; - dev->mt76.rev = mt76_rr(dev, MT_ASIC_VERSION); - dev_info(dev->mt76.dev, "ASIC revision: %08x\n", dev->mt76.rev); + mdev->rev = mt76_rr(dev, MT_ASIC_VERSION); + dev_info(mdev->dev, "ASIC revision: %08x\n", mdev->rev); err = mt76x2u_register_device(dev); if (err < 0) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c index 0be3784f44fb..090aaf71b3ef 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c @@ -134,30 +134,6 @@ static int mt76x2u_init_eeprom(struct mt76x02_dev *dev) return 0; } -struct mt76x02_dev *mt76x2u_alloc_device(struct device *pdev) -{ - static const struct mt76_driver_ops drv_ops = { - .tx_prepare_skb = mt76x02u_tx_prepare_skb, - .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; - - mdev = mt76_alloc_device(sizeof(*dev), &mt76x2u_ops); - if (!mdev) - return NULL; - - dev = container_of(mdev, struct mt76x02_dev, mt76); - mdev->dev = pdev; - mdev->drv = &drv_ops; - - return dev; -} - int mt76x2u_init_hardware(struct mt76x02_dev *dev) { int i, k, err; @@ -207,11 +183,7 @@ int mt76x2u_init_hardware(struct mt76x02_dev *dev) mt76x02_mac_shared_key_setup(dev, i, k, NULL); } - mt76_clear(dev, MT_BEACON_TIME_CFG, - MT_BEACON_TIME_CFG_TIMER_EN | - MT_BEACON_TIME_CFG_SYNC_MODE | - MT_BEACON_TIME_CFG_TBTT_EN | - MT_BEACON_TIME_CFG_BEACON_TX); + mt76x02_init_beacon_config(dev); mt76_rmw(dev, MT_US_CYC_CFG, MT_US_CYC_CNT, 0x1e); mt76_wr(dev, MT_TXOP_CTRL_CFG, 0x583f); @@ -256,7 +228,7 @@ int mt76x2u_register_device(struct mt76x02_dev *dev) goto fail; /* check hw sg support in order to enable AMSDU */ - if (mt76u_check_sg(&dev->mt76)) + if (dev->mt76.usb.sg_en) hw->max_tx_fragments = MT_SG_MAX_SIZE; else hw->max_tx_fragments = 1; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c index 286c7f451090..10633b8de8e8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c @@ -28,7 +28,7 @@ static int mt76x2u_start(struct ieee80211_hw *hw) goto out; ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work, - MT_CALIBRATE_INTERVAL); + MT_MAC_WORK_INTERVAL); set_bit(MT76_STATE_RUNNING, &dev->mt76.state); out: @@ -46,19 +46,6 @@ static void mt76x2u_stop(struct ieee80211_hw *hw) mutex_unlock(&dev->mt76.mutex); } -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, idx); - return 0; -} - static int mt76x2u_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef) @@ -125,7 +112,7 @@ const struct ieee80211_ops mt76x2u_ops = { .tx = mt76x02_tx, .start = mt76x2u_start, .stop = mt76x2u_stop, - .add_interface = mt76x2u_add_interface, + .add_interface = mt76x02_add_interface, .remove_interface = mt76x02_remove_interface, .sta_state = mt76_sta_state, .set_key = mt76x02_set_key, diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c index ef38e8626da9..5a349fe3e576 100644 --- a/drivers/net/wireless/mediatek/mt76/tx.c +++ b/drivers/net/wireless/mediatek/mt76/tx.c @@ -205,9 +205,6 @@ mt76_tx_status_skb_get(struct mt76_dev *dev, struct mt76_wcid *wcid, int pktid, { struct sk_buff *skb, *tmp; - if (pktid == MT_PACKET_ID_NO_ACK) - return NULL; - skb_queue_walk_safe(&dev->status_list, skb, tmp) { struct mt76_tx_cb *cb = mt76_tx_skb_cb(skb); @@ -217,7 +214,7 @@ mt76_tx_status_skb_get(struct mt76_dev *dev, struct mt76_wcid *wcid, int pktid, if (cb->pktid == pktid) return skb; - if (!pktid && + if (pktid >= 0 && !time_after(jiffies, cb->jiffies + MT_TX_STATUS_SKB_TIMEOUT)) continue; diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index 6a2507524c6c..78191968b4fa 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -22,6 +22,10 @@ #define MT_VEND_REQ_MAX_RETRY 10 #define MT_VEND_REQ_TOUT_MS 300 +static bool disable_usb_sg; +module_param_named(disable_usb_sg, disable_usb_sg, bool, 0644); +MODULE_PARM_DESC(disable_usb_sg, "Disable usb scatter-gather support"); + /* should be called with usb_ctrl_mtx locked */ static int __mt76u_vendor_request(struct mt76_dev *dev, u8 req, u8 req_type, u16 val, u16 offset, @@ -241,6 +245,16 @@ mt76u_rd_rp(struct mt76_dev *dev, u32 base, return mt76u_req_rd_rp(dev, base, data, n); } +static bool mt76u_check_sg(struct mt76_dev *dev) +{ + struct usb_interface *intf = to_usb_interface(dev->dev); + struct usb_device *udev = interface_to_usbdev(intf); + + return (!disable_usb_sg && udev->bus->sg_tablesize > 0 && + (udev->bus->no_sg_constraint || + udev->speed == USB_SPEED_WIRELESS)); +} + static int mt76u_set_endpoints(struct usb_interface *intf, struct mt76_usb *usb) @@ -309,8 +323,9 @@ mt76u_fill_rx_sg(struct mt76_dev *dev, struct mt76u_buf *buf, return i ? : -ENOMEM; } -int mt76u_buf_alloc(struct mt76_dev *dev, struct mt76u_buf *buf, - int nsgs, int len, int sglen, gfp_t gfp) +static int +mt76u_buf_alloc_sg(struct mt76_dev *dev, struct mt76u_buf *buf, + int nsgs, int len, int sglen, gfp_t gfp) { buf->urb = usb_alloc_urb(0, gfp); if (!buf->urb) @@ -326,15 +341,42 @@ int mt76u_buf_alloc(struct mt76_dev *dev, struct mt76u_buf *buf, return mt76u_fill_rx_sg(dev, buf, nsgs, len, sglen); } -EXPORT_SYMBOL_GPL(mt76u_buf_alloc); + +int mt76u_buf_alloc(struct mt76_dev *dev, struct mt76u_buf *buf, + int len, int data_len, gfp_t gfp) +{ + struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; + + buf->urb = usb_alloc_urb(0, gfp); + if (!buf->urb) + return -ENOMEM; + + buf->buf = page_frag_alloc(&q->rx_page, len, gfp); + if (!buf->buf) + return -ENOMEM; + + buf->len = data_len; + buf->dev = dev; + + return 0; +} void mt76u_buf_free(struct mt76u_buf *buf) { struct urb *urb = buf->urb; + struct scatterlist *sg; int i; - for (i = 0; i < urb->num_sgs; i++) - skb_free_frag(sg_virt(&urb->sg[i])); + for (i = 0; i < urb->num_sgs; i++) { + sg = &urb->sg[i]; + if (!sg) + continue; + + skb_free_frag(sg_virt(sg)); + } + if (buf->buf) + skb_free_frag(buf->buf); + usb_free_urb(buf->urb); } EXPORT_SYMBOL_GPL(mt76u_buf_free); @@ -345,6 +387,7 @@ int mt76u_submit_buf(struct mt76_dev *dev, int dir, int index, { struct usb_interface *intf = to_usb_interface(dev->dev); struct usb_device *udev = interface_to_usbdev(intf); + u8 *data = buf->urb->num_sgs ? NULL : buf->buf; unsigned int pipe; if (dir == USB_DIR_IN) @@ -352,7 +395,7 @@ int mt76u_submit_buf(struct mt76_dev *dev, int dir, int index, else pipe = usb_sndbulkpipe(udev, dev->usb.out_ep[index]); - usb_fill_bulk_urb(buf->urb, udev, pipe, NULL, buf->len, + usb_fill_bulk_urb(buf->urb, udev, pipe, data, buf->len, complete_fn, context); trace_submit_urb(dev, buf->urb); @@ -393,10 +436,11 @@ static int mt76u_get_rx_entry_len(u8 *data, u32 data_len) } static int -mt76u_process_rx_entry(struct mt76_dev *dev, struct urb *urb) +mt76u_process_rx_entry(struct mt76_dev *dev, struct mt76u_buf *buf) { struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; - u8 *data = sg_virt(&urb->sg[0]); + struct urb *urb = buf->urb; + u8 *data = urb->num_sgs ? sg_virt(&urb->sg[0]) : buf->buf; int data_len, len, nsgs = 1; struct sk_buff *skb; @@ -407,7 +451,8 @@ mt76u_process_rx_entry(struct mt76_dev *dev, struct urb *urb) if (len < 0) return 0; - data_len = min_t(int, len, urb->sg[0].length - MT_DMA_HDR_LEN); + data_len = urb->num_sgs ? urb->sg[0].length : buf->len; + data_len = min_t(int, len, data_len - MT_DMA_HDR_LEN); if (MT_DMA_HDR_LEN + data_len > SKB_WITH_OVERHEAD(q->buf_size)) return 0; @@ -419,7 +464,7 @@ mt76u_process_rx_entry(struct mt76_dev *dev, struct urb *urb) __skb_put(skb, data_len); len -= data_len; - while (len > 0) { + while (len > 0 && urb->num_sgs) { data_len = min_t(int, len, urb->sg[nsgs].length); skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, sg_page(&urb->sg[nsgs]), @@ -447,7 +492,8 @@ static void mt76u_complete_rx(struct urb *urb) case -ENOENT: return; default: - dev_err(dev->dev, "rx urb failed: %d\n", urb->status); + dev_err_ratelimited(dev->dev, "rx urb failed: %d\n", + urb->status); /* fall through */ case 0: break; @@ -464,12 +510,26 @@ out: spin_unlock_irqrestore(&q->lock, flags); } +static int +mt76u_refill_rx(struct mt76_dev *dev, struct mt76_queue *q, + struct mt76u_buf *buf, int nsgs) +{ + if (dev->usb.sg_en) { + return mt76u_fill_rx_sg(dev, buf, nsgs, q->buf_size, + SKB_WITH_OVERHEAD(q->buf_size)); + } else { + buf->buf = page_frag_alloc(&q->rx_page, q->buf_size, + GFP_ATOMIC); + return buf->buf ? 0 : -ENOMEM; + } +} + static void mt76u_rx_tasklet(unsigned long data) { struct mt76_dev *dev = (struct mt76_dev *)data; struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; - int err, nsgs, buf_len = q->buf_size; struct mt76u_buf *buf; + int err, count; rcu_read_lock(); @@ -478,11 +538,9 @@ static void mt76u_rx_tasklet(unsigned long data) if (!buf) break; - nsgs = mt76u_process_rx_entry(dev, buf->urb); - if (nsgs > 0) { - err = mt76u_fill_rx_sg(dev, buf, nsgs, - buf_len, - SKB_WITH_OVERHEAD(buf_len)); + count = mt76u_process_rx_entry(dev, buf); + if (count > 0) { + err = mt76u_refill_rx(dev, q, buf, count); if (err < 0) break; } @@ -520,7 +578,7 @@ EXPORT_SYMBOL_GPL(mt76u_submit_rx_buffers); static int mt76u_alloc_rx(struct mt76_dev *dev) { struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; - int i, err, nsgs; + int i, err; spin_lock_init(&q->rx_page_lock); spin_lock_init(&q->lock); @@ -530,23 +588,22 @@ static int mt76u_alloc_rx(struct mt76_dev *dev) if (!q->entry) return -ENOMEM; - if (mt76u_check_sg(dev)) { - q->buf_size = MT_RX_BUF_SIZE; - nsgs = MT_SG_MAX_SIZE; - } else { - q->buf_size = PAGE_SIZE; - nsgs = 1; - } - - for (i = 0; i < MT_NUM_RX_ENTRIES; i++) { - err = mt76u_buf_alloc(dev, &q->entry[i].ubuf, - nsgs, q->buf_size, - SKB_WITH_OVERHEAD(q->buf_size), - GFP_KERNEL); + q->buf_size = dev->usb.sg_en ? MT_RX_BUF_SIZE : PAGE_SIZE; + q->ndesc = MT_NUM_RX_ENTRIES; + for (i = 0; i < q->ndesc; i++) { + if (dev->usb.sg_en) + err = mt76u_buf_alloc_sg(dev, &q->entry[i].ubuf, + MT_SG_MAX_SIZE, q->buf_size, + SKB_WITH_OVERHEAD(q->buf_size), + GFP_KERNEL); + else + err = mt76u_buf_alloc(dev, &q->entry[i].ubuf, + q->buf_size, + SKB_WITH_OVERHEAD(q->buf_size), + GFP_KERNEL); if (err < 0) return err; } - q->ndesc = MT_NUM_RX_ENTRIES; return mt76u_submit_rx_buffers(dev); } @@ -691,7 +748,7 @@ mt76u_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, { struct usb_interface *intf = to_usb_interface(dev->dev); struct usb_device *udev = interface_to_usbdev(intf); - u8 ep = q2ep(q->hw_idx); + u8 *data = NULL, ep = q2ep(q->hw_idx); struct mt76u_buf *buf; u16 idx = q->tail; unsigned int pipe; @@ -708,12 +765,16 @@ mt76u_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, buf = &q->entry[idx].ubuf; buf->done = false; - err = mt76u_tx_build_sg(skb, buf->urb); - if (err < 0) - return err; + if (dev->usb.sg_en) { + err = mt76u_tx_build_sg(skb, buf->urb); + if (err < 0) + return err; + } else { + data = skb->data; + } pipe = usb_sndbulkpipe(udev, dev->usb.out_ep[ep]); - usb_fill_bulk_urb(buf->urb, udev, pipe, NULL, skb->len, + usb_fill_bulk_urb(buf->urb, udev, pipe, data, skb->len, mt76u_complete_tx, buf); q->tail = (q->tail + 1) % q->ndesc; @@ -749,10 +810,8 @@ static int mt76u_alloc_tx(struct mt76_dev *dev) { struct mt76u_buf *buf; struct mt76_queue *q; - size_t size; int i, j; - size = MT_SG_MAX_SIZE * sizeof(struct scatterlist); for (i = 0; i < IEEE80211_NUM_ACS; i++) { q = &dev->q_tx[i]; spin_lock_init(&q->lock); @@ -774,9 +833,15 @@ static int mt76u_alloc_tx(struct mt76_dev *dev) if (!buf->urb) return -ENOMEM; - buf->urb->sg = devm_kzalloc(dev->dev, size, GFP_KERNEL); - if (!buf->urb->sg) - return -ENOMEM; + if (dev->usb.sg_en) { + size_t size = MT_SG_MAX_SIZE * + sizeof(struct scatterlist); + + buf->urb->sg = devm_kzalloc(dev->dev, size, + GFP_KERNEL); + if (!buf->urb->sg) + return -ENOMEM; + } } } return 0; @@ -838,16 +903,9 @@ int mt76u_alloc_queues(struct mt76_dev *dev) err = mt76u_alloc_rx(dev); if (err < 0) - goto err; - - err = mt76u_alloc_tx(dev); - if (err < 0) - goto err; + return err; - return 0; -err: - mt76u_queues_deinit(dev); - return err; + return mt76u_alloc_tx(dev); } EXPORT_SYMBOL_GPL(mt76u_alloc_queues); @@ -882,6 +940,8 @@ int mt76u_init(struct mt76_dev *dev, dev->bus = &mt76u_ops; dev->queue_ops = &usb_queue_ops; + usb->sg_en = mt76u_check_sg(dev); + return mt76u_set_endpoints(intf, usb); } EXPORT_SYMBOL_GPL(mt76u_init); diff --git a/drivers/net/wireless/mediatek/mt76/usb_mcu.c b/drivers/net/wireless/mediatek/mt76/usb_mcu.c index 036be4163e69..72c8607da4b4 100644 --- a/drivers/net/wireless/mediatek/mt76/usb_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/usb_mcu.c @@ -29,9 +29,8 @@ int mt76u_mcu_init_rx(struct mt76_dev *dev) struct mt76_usb *usb = &dev->usb; int err; - err = mt76u_buf_alloc(dev, &usb->mcu.res, 1, - MCU_RESP_URB_SIZE, MCU_RESP_URB_SIZE, - GFP_KERNEL); + err = mt76u_buf_alloc(dev, &usb->mcu.res, MCU_RESP_URB_SIZE, + MCU_RESP_URB_SIZE, GFP_KERNEL); if (err < 0) return err; @@ -48,9 +47,11 @@ EXPORT_SYMBOL_GPL(mt76u_mcu_init_rx); void mt76u_mcu_deinit(struct mt76_dev *dev) { - struct mt76_usb *usb = &dev->usb; + struct mt76u_buf *buf = &dev->usb.mcu.res; - usb_kill_urb(usb->mcu.res.urb); - mt76u_buf_free(&usb->mcu.res); + if (buf->urb) { + usb_kill_urb(buf->urb); + mt76u_buf_free(buf); + } } EXPORT_SYMBOL_GPL(mt76u_mcu_deinit); |