diff options
Diffstat (limited to 'drivers/net/wireless/mediatek/mt76/mac80211.c')
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mac80211.c | 124 |
1 files changed, 100 insertions, 24 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index fc608b369b3c..b117e4467c87 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -4,6 +4,7 @@ */ #include <linux/sched.h> #include <linux/of.h> +#include <net/page_pool.h> #include "mt76.h" #define CHAN2G(_idx, _freq) { \ @@ -192,42 +193,48 @@ static const struct cfg80211_sar_capa mt76_sar_capa = { .freq_ranges = &mt76_sar_freq_ranges[0], }; -static int mt76_led_init(struct mt76_dev *dev) +static int mt76_led_init(struct mt76_phy *phy) { - struct device_node *np = dev->dev->of_node; - struct ieee80211_hw *hw = dev->hw; - int led_pin; + struct mt76_dev *dev = phy->dev; + struct ieee80211_hw *hw = phy->hw; - if (!dev->led_cdev.brightness_set && !dev->led_cdev.blink_set) + if (!phy->leds.cdev.brightness_set && !phy->leds.cdev.blink_set) return 0; - snprintf(dev->led_name, sizeof(dev->led_name), - "mt76-%s", wiphy_name(hw->wiphy)); + snprintf(phy->leds.name, sizeof(phy->leds.name), "mt76-%s", + wiphy_name(hw->wiphy)); - dev->led_cdev.name = dev->led_name; - dev->led_cdev.default_trigger = + phy->leds.cdev.name = phy->leds.name; + phy->leds.cdev.default_trigger = ieee80211_create_tpt_led_trigger(hw, IEEE80211_TPT_LEDTRIG_FL_RADIO, mt76_tpt_blink, ARRAY_SIZE(mt76_tpt_blink)); - np = of_get_child_by_name(np, "led"); - if (np) { - if (!of_property_read_u32(np, "led-sources", &led_pin)) - dev->led_pin = led_pin; - dev->led_al = of_property_read_bool(np, "led-active-low"); - of_node_put(np); + if (phy == &dev->phy) { + struct device_node *np = dev->dev->of_node; + + np = of_get_child_by_name(np, "led"); + if (np) { + int led_pin; + + if (!of_property_read_u32(np, "led-sources", &led_pin)) + phy->leds.pin = led_pin; + phy->leds.al = of_property_read_bool(np, + "led-active-low"); + of_node_put(np); + } } - return led_classdev_register(dev->dev, &dev->led_cdev); + return led_classdev_register(dev->dev, &phy->leds.cdev); } -static void mt76_led_cleanup(struct mt76_dev *dev) +static void mt76_led_cleanup(struct mt76_phy *phy) { - if (!dev->led_cdev.brightness_set && !dev->led_cdev.blink_set) + if (!phy->leds.cdev.brightness_set && !phy->leds.cdev.blink_set) return; - led_classdev_unregister(&dev->led_cdev); + led_classdev_unregister(&phy->leds.cdev); } static void mt76_init_stream_cap(struct mt76_phy *phy, @@ -517,6 +524,12 @@ int mt76_register_phy(struct mt76_phy *phy, bool vht, return ret; } + if (IS_ENABLED(CONFIG_MT76_LEDS)) { + ret = mt76_led_init(phy); + if (ret) + return ret; + } + wiphy_read_of_freq_limits(phy->hw->wiphy); mt76_check_sband(phy, &phy->sband_2g, NL80211_BAND_2GHZ); mt76_check_sband(phy, &phy->sband_5g, NL80211_BAND_5GHZ); @@ -536,12 +549,55 @@ void mt76_unregister_phy(struct mt76_phy *phy) { struct mt76_dev *dev = phy->dev; + if (IS_ENABLED(CONFIG_MT76_LEDS)) + mt76_led_cleanup(phy); mt76_tx_status_check(dev, true); ieee80211_unregister_hw(phy->hw); dev->phys[phy->band_idx] = NULL; } EXPORT_SYMBOL_GPL(mt76_unregister_phy); +int mt76_create_page_pool(struct mt76_dev *dev, struct mt76_queue *q) +{ + struct page_pool_params pp_params = { + .order = 0, + .flags = PP_FLAG_PAGE_FRAG, + .nid = NUMA_NO_NODE, + .dev = dev->dma_dev, + }; + int idx = q - dev->q_rx; + + switch (idx) { + case MT_RXQ_MAIN: + case MT_RXQ_BAND1: + case MT_RXQ_BAND2: + pp_params.pool_size = 256; + break; + default: + pp_params.pool_size = 16; + break; + } + + if (mt76_is_mmio(dev)) { + /* rely on page_pool for DMA mapping */ + pp_params.flags |= PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV; + pp_params.dma_dir = DMA_FROM_DEVICE; + pp_params.max_len = PAGE_SIZE; + pp_params.offset = 0; + } + + q->page_pool = page_pool_create(&pp_params); + if (IS_ERR(q->page_pool)) { + int err = PTR_ERR(q->page_pool); + + q->page_pool = NULL; + return err; + } + + return 0; +} +EXPORT_SYMBOL_GPL(mt76_create_page_pool); + struct mt76_dev * mt76_alloc_device(struct device *pdev, unsigned int size, const struct ieee80211_ops *ops, @@ -653,7 +709,7 @@ int mt76_register_device(struct mt76_dev *dev, bool vht, mt76_check_sband(&dev->phy, &phy->sband_6g, NL80211_BAND_6GHZ); if (IS_ENABLED(CONFIG_MT76_LEDS)) { - ret = mt76_led_init(dev); + ret = mt76_led_init(phy); if (ret) return ret; } @@ -674,7 +730,7 @@ void mt76_unregister_device(struct mt76_dev *dev) struct ieee80211_hw *hw = dev->hw; if (IS_ENABLED(CONFIG_MT76_LEDS)) - mt76_led_cleanup(dev); + mt76_led_cleanup(&dev->phy); mt76_tx_status_check(dev, true); ieee80211_unregister_hw(hw); } @@ -1644,7 +1700,7 @@ u16 mt76_calculate_default_rate(struct mt76_phy *phy, int rateidx) EXPORT_SYMBOL_GPL(mt76_calculate_default_rate); void mt76_ethtool_worker(struct mt76_ethtool_worker_info *wi, - struct mt76_sta_stats *stats) + struct mt76_sta_stats *stats, bool eht) { int i, ei = wi->initial_stat_idx; u64 *data = wi->data; @@ -1660,17 +1716,37 @@ void mt76_ethtool_worker(struct mt76_ethtool_worker_info *wi, data[ei++] += stats->tx_mode[MT_PHY_TYPE_HE_EXT_SU]; data[ei++] += stats->tx_mode[MT_PHY_TYPE_HE_TB]; data[ei++] += stats->tx_mode[MT_PHY_TYPE_HE_MU]; + if (eht) { + data[ei++] += stats->tx_mode[MT_PHY_TYPE_EHT_SU]; + data[ei++] += stats->tx_mode[MT_PHY_TYPE_EHT_TRIG]; + data[ei++] += stats->tx_mode[MT_PHY_TYPE_EHT_MU]; + } - for (i = 0; i < ARRAY_SIZE(stats->tx_bw); i++) + for (i = 0; i < (ARRAY_SIZE(stats->tx_bw) - !eht); i++) data[ei++] += stats->tx_bw[i]; - for (i = 0; i < 12; i++) + for (i = 0; i < (eht ? 14 : 12); i++) data[ei++] += stats->tx_mcs[i]; wi->worker_stat_count = ei - wi->initial_stat_idx; } EXPORT_SYMBOL_GPL(mt76_ethtool_worker); +void mt76_ethtool_page_pool_stats(struct mt76_dev *dev, u64 *data, int *index) +{ +#ifdef CONFIG_PAGE_POOL_STATS + struct page_pool_stats stats = {}; + int i; + + mt76_for_each_q_rx(dev, i) + page_pool_get_stats(dev->q_rx[i].page_pool, &stats); + + page_pool_ethtool_stats_get(data, &stats); + *index += page_pool_ethtool_stats_get_count(); +#endif +} +EXPORT_SYMBOL_GPL(mt76_ethtool_page_pool_stats); + enum mt76_dfs_state mt76_phy_dfs_state(struct mt76_phy *phy) { struct ieee80211_hw *hw = phy->hw; |