diff options
author | Kalle Valo <kvalo@kernel.org> | 2022-12-21 21:21:36 +0300 |
---|---|---|
committer | Kalle Valo <kvalo@kernel.org> | 2022-12-21 21:21:36 +0300 |
commit | 33381618d7edf7e939d86861e445da09d72edcd1 (patch) | |
tree | d166d4a508cd8b76a93eaaa9e1bedc699050016c | |
parent | 117dbeda22ec5ea0918254d03b540ef8b8a64d53 (diff) | |
parent | d878d3dc126db05b075147456644bd2d2ab1fb5e (diff) | |
download | linux-33381618d7edf7e939d86861e445da09d72edcd1.tar.xz |
Merge tag 'mt76-for-kvalo-2022-12-09' of https://github.com/nbd168/wireless
mt76 patches for 6.2
- fixes
- per-PHY LED support
34 files changed, 503 insertions, 274 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/debugfs.c b/drivers/net/wireless/mediatek/mt76/debugfs.c index 11b0b3d62f29..57fbcc83e074 100644 --- a/drivers/net/wireless/mediatek/mt76/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/debugfs.c @@ -112,7 +112,7 @@ mt76_register_debugfs_fops(struct mt76_phy *phy, if (!dir) return NULL; - debugfs_create_u8("led_pin", 0600, dir, &dev->led_pin); + debugfs_create_u8("led_pin", 0600, dir, &phy->leds.pin); debugfs_create_u32("regidx", 0600, dir, &dev->debugfs_reg); debugfs_create_file_unsafe("regval", 0600, dir, dev, fops); debugfs_create_file_unsafe("napi_threaded", 0600, dir, dev, diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index f795548562f5..5d582186ed58 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -212,14 +212,14 @@ mt76_dma_add_buf(struct mt76_dev *dev, struct mt76_queue *q, { struct mt76_queue_entry *entry; struct mt76_desc *desc; - u32 ctrl; int i, idx = -1; + u32 ctrl, next; for (i = 0; i < nbufs; i += 2, buf += 2) { u32 buf0 = buf[0].addr, buf1 = 0; idx = q->head; - q->head = (q->head + 1) % q->ndesc; + next = (q->head + 1) % q->ndesc; desc = &q->desc[idx]; entry = &q->entry[idx]; @@ -234,13 +234,16 @@ mt76_dma_add_buf(struct mt76_dev *dev, struct mt76_queue *q, rx_token = mt76_rx_token_consume(dev, (void *)skb, t, buf[0].addr); + if (rx_token < 0) + return -ENOMEM; + buf1 |= FIELD_PREP(MT_DMA_CTL_TOKEN, rx_token); ctrl = FIELD_PREP(MT_DMA_CTL_SD_LEN0, buf[0].len) | MT_DMA_CTL_TO_HOST; } else { if (txwi) { - q->entry[q->head].txwi = DMA_DUMMY_DATA; - q->entry[q->head].skip_buf0 = true; + q->entry[next].txwi = DMA_DUMMY_DATA; + q->entry[next].skip_buf0 = true; } if (buf[0].skip_unmap) @@ -271,6 +274,7 @@ mt76_dma_add_buf(struct mt76_dev *dev, struct mt76_queue *q, WRITE_ONCE(desc->info, cpu_to_le32(info)); WRITE_ONCE(desc->ctrl, cpu_to_le32(ctrl)); + q->head = next; q->queued++; } @@ -550,23 +554,9 @@ free_skb: return ret; } -static struct page_frag_cache * -mt76_dma_rx_get_frag_cache(struct mt76_dev *dev, struct mt76_queue *q) -{ - struct page_frag_cache *rx_page = &q->rx_page; - -#ifdef CONFIG_NET_MEDIATEK_SOC_WED - if ((q->flags & MT_QFLAG_WED) && - FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_RX) - rx_page = &dev->mmio.wed.rx_buf_ring.rx_page; -#endif - return rx_page; -} - static int mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q) { - struct page_frag_cache *rx_page = mt76_dma_rx_get_frag_cache(dev, q); int len = SKB_WITH_OVERHEAD(q->buf_size); int frames = 0, offset = q->buf_offset; dma_addr_t addr; @@ -588,7 +578,7 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q) break; } - buf = page_frag_alloc(rx_page, q->buf_size, GFP_ATOMIC); + buf = page_frag_alloc(&q->rx_page, q->buf_size, GFP_ATOMIC); if (!buf) break; @@ -601,7 +591,12 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q) qbuf.addr = addr + offset; qbuf.len = len - offset; qbuf.skip_unmap = false; - mt76_dma_add_buf(dev, q, &qbuf, 1, 0, buf, t); + if (mt76_dma_add_buf(dev, q, &qbuf, 1, 0, buf, t) < 0) { + dma_unmap_single(dev->dma_dev, addr, len, + DMA_FROM_DEVICE); + skb_free_frag(buf); + break; + } frames++; } diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index fc608b369b3c..7fe7f68acc24 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -192,42 +192,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 +523,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,6 +548,8 @@ 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; @@ -653,7 +667,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 +688,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); } diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 32a77a0ae9da..1037d23bc4d0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -731,6 +731,13 @@ struct mt76_phy { } rx_amsdu[__MT_RXQ_MAX]; struct mt76_freq_range_power *frp; + + struct { + struct led_classdev cdev; + char name[32]; + bool al; + u8 pin; + } leds; }; struct mt76_dev { @@ -812,11 +819,6 @@ struct mt76_dev { u32 debugfs_reg; - struct led_classdev led_cdev; - char led_name[32]; - bool led_al; - u8 led_pin; - u8 csa_complete; u32 rxfilter; diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/init.c b/drivers/net/wireless/mediatek/mt76/mt7603/init.c index 031d39a48a55..9a2e632d577a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/init.c @@ -330,10 +330,10 @@ static const struct ieee80211_iface_combination if_comb[] = { } }; -static void mt7603_led_set_config(struct mt76_dev *mt76, u8 delay_on, +static void mt7603_led_set_config(struct mt76_phy *mphy, u8 delay_on, u8 delay_off) { - struct mt7603_dev *dev = container_of(mt76, struct mt7603_dev, + struct mt7603_dev *dev = container_of(mphy->dev, struct mt7603_dev, mt76); u32 val, addr; @@ -341,15 +341,15 @@ static void mt7603_led_set_config(struct mt76_dev *mt76, u8 delay_on, FIELD_PREP(MT_LED_STATUS_OFF, delay_off) | FIELD_PREP(MT_LED_STATUS_ON, delay_on); - addr = mt7603_reg_map(dev, MT_LED_STATUS_0(mt76->led_pin)); + addr = mt7603_reg_map(dev, MT_LED_STATUS_0(mphy->leds.pin)); mt76_wr(dev, addr, val); - addr = mt7603_reg_map(dev, MT_LED_STATUS_1(mt76->led_pin)); + addr = mt7603_reg_map(dev, MT_LED_STATUS_1(mphy->leds.pin)); mt76_wr(dev, addr, val); - val = MT_LED_CTRL_REPLAY(mt76->led_pin) | - MT_LED_CTRL_KICK(mt76->led_pin); - if (mt76->led_al) - val |= MT_LED_CTRL_POLARITY(mt76->led_pin); + val = MT_LED_CTRL_REPLAY(mphy->leds.pin) | + MT_LED_CTRL_KICK(mphy->leds.pin); + if (mphy->leds.al) + val |= MT_LED_CTRL_POLARITY(mphy->leds.pin); addr = mt7603_reg_map(dev, MT_LED_CTRL); mt76_wr(dev, addr, val); } @@ -358,27 +358,27 @@ static int mt7603_led_set_blink(struct led_classdev *led_cdev, unsigned long *delay_on, unsigned long *delay_off) { - struct mt76_dev *mt76 = container_of(led_cdev, struct mt76_dev, - led_cdev); + struct mt76_phy *mphy = container_of(led_cdev, struct mt76_phy, + leds.cdev); u8 delta_on, delta_off; delta_off = max_t(u8, *delay_off / 10, 1); delta_on = max_t(u8, *delay_on / 10, 1); - mt7603_led_set_config(mt76, delta_on, delta_off); + mt7603_led_set_config(mphy, delta_on, delta_off); return 0; } static void mt7603_led_set_brightness(struct led_classdev *led_cdev, enum led_brightness brightness) { - struct mt76_dev *mt76 = container_of(led_cdev, struct mt76_dev, - led_cdev); + struct mt76_phy *mphy = container_of(led_cdev, struct mt76_phy, + leds.cdev); if (!brightness) - mt7603_led_set_config(mt76, 0, 0xff); + mt7603_led_set_config(mphy, 0, 0xff); else - mt7603_led_set_config(mt76, 0xff, 0); + mt7603_led_set_config(mphy, 0xff, 0); } static u32 __mt7603_reg_addr(struct mt7603_dev *dev, u32 addr) @@ -535,8 +535,8 @@ int mt7603_register_device(struct mt7603_dev *dev) /* init led callbacks */ if (IS_ENABLED(CONFIG_MT76_LEDS)) { - dev->mt76.led_cdev.brightness_set = mt7603_led_set_brightness; - dev->mt76.led_cdev.blink_set = mt7603_led_set_blink; + dev->mphy.leds.cdev.brightness_set = mt7603_led_set_brightness; + dev->mphy.leds.cdev.blink_set = mt7603_led_set_blink; } wiphy->reg_notifier = mt7603_regd_notifier; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index 07a1fea94f66..5fa6f097ec30 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -443,6 +443,85 @@ mt7615_cap_dbdc_disable(struct mt7615_dev *dev) mt76_set_stream_caps(&dev->mphy, true); } +u32 mt7615_reg_map(struct mt7615_dev *dev, u32 addr) +{ + u32 base, offset; + + if (is_mt7663(&dev->mt76)) { + base = addr & MT7663_MCU_PCIE_REMAP_2_BASE; + offset = addr & MT7663_MCU_PCIE_REMAP_2_OFFSET; + } else { + base = addr & MT_MCU_PCIE_REMAP_2_BASE; + offset = addr & MT_MCU_PCIE_REMAP_2_OFFSET; + } + mt76_wr(dev, MT_MCU_PCIE_REMAP_2, base); + + return MT_PCIE_REMAP_BASE_2 + offset; +} +EXPORT_SYMBOL_GPL(mt7615_reg_map); + +static void +mt7615_led_set_config(struct led_classdev *led_cdev, + u8 delay_on, u8 delay_off) +{ + struct mt7615_dev *dev; + struct mt76_phy *mphy; + u32 val, addr; + u8 index; + + mphy = container_of(led_cdev, struct mt76_phy, leds.cdev); + dev = container_of(mphy->dev, struct mt7615_dev, mt76); + + if (!mt76_connac_pm_ref(mphy, &dev->pm)) + return; + + val = FIELD_PREP(MT_LED_STATUS_DURATION, 0xffff) | + FIELD_PREP(MT_LED_STATUS_OFF, delay_off) | + FIELD_PREP(MT_LED_STATUS_ON, delay_on); + + index = dev->dbdc_support ? mphy->band_idx : mphy->leds.pin; + addr = mt7615_reg_map(dev, MT_LED_STATUS_0(index)); + mt76_wr(dev, addr, val); + addr = mt7615_reg_map(dev, MT_LED_STATUS_1(index)); + mt76_wr(dev, addr, val); + + val = MT_LED_CTRL_REPLAY(index) | MT_LED_CTRL_KICK(index); + if (dev->mphy.leds.al) + val |= MT_LED_CTRL_POLARITY(index); + if (mphy->band_idx) + val |= MT_LED_CTRL_BAND(index); + + addr = mt7615_reg_map(dev, MT_LED_CTRL); + mt76_wr(dev, addr, val); + + mt76_connac_pm_unref(mphy, &dev->pm); +} + +int mt7615_led_set_blink(struct led_classdev *led_cdev, + unsigned long *delay_on, + unsigned long *delay_off) +{ + u8 delta_on, delta_off; + + delta_off = max_t(u8, *delay_off / 10, 1); + delta_on = max_t(u8, *delay_on / 10, 1); + + mt7615_led_set_config(led_cdev, delta_on, delta_off); + + return 0; +} +EXPORT_SYMBOL_GPL(mt7615_led_set_blink); + +void mt7615_led_set_brightness(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + if (!brightness) + mt7615_led_set_config(led_cdev, 0, 0xff); + else + mt7615_led_set_config(led_cdev, 0xff, 0); +} +EXPORT_SYMBOL_GPL(mt7615_led_set_brightness); + int mt7615_register_ext_phy(struct mt7615_dev *dev) { struct mt7615_phy *phy = mt7615_ext_phy(dev); @@ -497,6 +576,12 @@ int mt7615_register_ext_phy(struct mt7615_dev *dev) for (i = 0; i <= MT_TXQ_PSD ; i++) mphy->q_tx[i] = dev->mphy.q_tx[i]; + /* init led callbacks */ + if (IS_ENABLED(CONFIG_MT76_LEDS)) { + mphy->leds.cdev.brightness_set = mt7615_led_set_brightness; + mphy->leds.cdev.blink_set = mt7615_led_set_blink; + } + ret = mt76_register_phy(mphy, true, mt76_rates, ARRAY_SIZE(mt76_rates)); if (ret) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c index a784f9d9e935..83173efb56dc 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c @@ -63,22 +63,6 @@ const u32 mt7663e_reg_map[] = { [MT_EFUSE_ADDR_BASE] = 0x78011000, }; -u32 mt7615_reg_map(struct mt7615_dev *dev, u32 addr) -{ - u32 base, offset; - - if (is_mt7663(&dev->mt76)) { - base = addr & MT7663_MCU_PCIE_REMAP_2_BASE; - offset = addr & MT7663_MCU_PCIE_REMAP_2_OFFSET; - } else { - base = addr & MT_MCU_PCIE_REMAP_2_BASE; - offset = addr & MT_MCU_PCIE_REMAP_2_OFFSET; - } - mt76_wr(dev, MT_MCU_PCIE_REMAP_2, base); - - return MT_PCIE_REMAP_BASE_2 + offset; -} - static void mt7615_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q) { diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 087d4886162e..43591b4c1d9a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -376,6 +376,12 @@ int mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base, int irq, const u32 *map); u32 mt7615_reg_map(struct mt7615_dev *dev, u32 addr); +u32 mt7615_reg_map(struct mt7615_dev *dev, u32 addr); +int mt7615_led_set_blink(struct led_classdev *led_cdev, + unsigned long *delay_on, + unsigned long *delay_off); +void mt7615_led_set_brightness(struct led_classdev *led_cdev, + enum led_brightness brightness); void mt7615_init_device(struct mt7615_dev *dev); int mt7615_register_device(struct mt7615_dev *dev); void mt7615_unregister_device(struct mt7615_dev *dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c b/drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c index 87b4aa52ee0f..0680e002b981 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c @@ -66,64 +66,6 @@ static int mt7615_init_hardware(struct mt7615_dev *dev) return 0; } -static void -mt7615_led_set_config(struct led_classdev *led_cdev, - u8 delay_on, u8 delay_off) -{ - struct mt7615_dev *dev; - struct mt76_dev *mt76; - u32 val, addr; - - mt76 = container_of(led_cdev, struct mt76_dev, led_cdev); - dev = container_of(mt76, struct mt7615_dev, mt76); - - if (!mt76_connac_pm_ref(&dev->mphy, &dev->pm)) - return; - - val = FIELD_PREP(MT_LED_STATUS_DURATION, 0xffff) | - FIELD_PREP(MT_LED_STATUS_OFF, delay_off) | - FIELD_PREP(MT_LED_STATUS_ON, delay_on); - - addr = mt7615_reg_map(dev, MT_LED_STATUS_0(mt76->led_pin)); - mt76_wr(dev, addr, val); - addr = mt7615_reg_map(dev, MT_LED_STATUS_1(mt76->led_pin)); - mt76_wr(dev, addr, val); - - val = MT_LED_CTRL_REPLAY(mt76->led_pin) | - MT_LED_CTRL_KICK(mt76->led_pin); - if (mt76->led_al) - val |= MT_LED_CTRL_POLARITY(mt76->led_pin); - addr = mt7615_reg_map(dev, MT_LED_CTRL); - mt76_wr(dev, addr, val); - - mt76_connac_pm_unref(&dev->mphy, &dev->pm); -} - -static int -mt7615_led_set_blink(struct led_classdev *led_cdev, - unsigned long *delay_on, - unsigned long *delay_off) -{ - u8 delta_on, delta_off; - - delta_off = max_t(u8, *delay_off / 10, 1); - delta_on = max_t(u8, *delay_on / 10, 1); - - mt7615_led_set_config(led_cdev, delta_on, delta_off); - - return 0; -} - -static void -mt7615_led_set_brightness(struct led_classdev *led_cdev, - enum led_brightness brightness) -{ - if (!brightness) - mt7615_led_set_config(led_cdev, 0, 0xff); - else - mt7615_led_set_config(led_cdev, 0xff, 0); -} - int mt7615_register_device(struct mt7615_dev *dev) { int ret; @@ -133,8 +75,8 @@ int mt7615_register_device(struct mt7615_dev *dev) /* init led callbacks */ if (IS_ENABLED(CONFIG_MT76_LEDS)) { - dev->mt76.led_cdev.brightness_set = mt7615_led_set_brightness; - dev->mt76.led_cdev.blink_set = mt7615_led_set_blink; + dev->mphy.leds.cdev.brightness_set = mt7615_led_set_brightness; + dev->mphy.leds.cdev.blink_set = mt7615_led_set_blink; } ret = mt7622_wmac_init(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h index fa1b9b26b399..7cecb22c569e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h @@ -544,6 +544,7 @@ enum mt7615_reg_base { #define MT_LED_CTRL_POLARITY(_n) BIT(1 + (8 * (_n))) #define MT_LED_CTRL_TX_BLINK_MODE(_n) BIT(2 + (8 * (_n))) #define MT_LED_CTRL_TX_MANUAL_BLINK(_n) BIT(3 + (8 * (_n))) +#define MT_LED_CTRL_BAND(_n) BIT(4 + (8 * (_n))) #define MT_LED_CTRL_TX_OVER_BLINK(_n) BIT(5 + (8 * (_n))) #define MT_LED_CTRL_KICK(_n) BIT(7 + (8 * (_n))) diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c index fd60123fb284..c8d0c84e688b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c @@ -930,7 +930,7 @@ int mt76_connac2_reverse_frag0_hdr_trans(struct ieee80211_vif *vif, ether_addr_copy(hdr.addr4, eth_hdr->h_source); break; default: - break; + return -EINVAL; } skb_pull(skb, hdr_offset + sizeof(struct ethhdr) - 2); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c index 6c6c8ada7943..d543ef3de65b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c @@ -642,7 +642,12 @@ mt76x0_phy_get_target_power(struct mt76x02_dev *dev, u8 tx_mode, if (tx_rate > 9) return -EINVAL; - *target_power = cur_power + dev->rate_power.vht[tx_rate]; + *target_power = cur_power; + if (tx_rate > 7) + *target_power += dev->rate_power.vht[tx_rate - 8]; + else + *target_power += dev->rate_power.ht[tx_rate]; + *target_pa_power = mt76x0_phy_get_rf_pa_mode(dev, 1, tx_rate); break; default: diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c index 604ddcc21123..7451a63206a5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c @@ -87,10 +87,9 @@ static const struct ieee80211_iface_combination mt76x02u_if_comb[] = { }; static void -mt76x02_led_set_config(struct mt76_dev *mdev, u8 delay_on, - u8 delay_off) +mt76x02_led_set_config(struct mt76_phy *mphy, u8 delay_on, u8 delay_off) { - struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, + struct mt76x02_dev *dev = container_of(mphy->dev, struct mt76x02_dev, mt76); u32 val; @@ -98,13 +97,13 @@ mt76x02_led_set_config(struct mt76_dev *mdev, u8 delay_on, FIELD_PREP(MT_LED_STATUS_OFF, delay_off) | FIELD_PREP(MT_LED_STATUS_ON, delay_on); - mt76_wr(dev, MT_LED_S0(mdev->led_pin), val); - mt76_wr(dev, MT_LED_S1(mdev->led_pin), val); + mt76_wr(dev, MT_LED_S0(mphy->leds.pin), val); + mt76_wr(dev, MT_LED_S1(mphy->leds.pin), val); - val = MT_LED_CTRL_REPLAY(mdev->led_pin) | - MT_LED_CTRL_KICK(mdev->led_pin); - if (mdev->led_al) - val |= MT_LED_CTRL_POLARITY(mdev->led_pin); + val = MT_LED_CTRL_REPLAY(mphy->leds.pin) | + MT_LED_CTRL_KICK(mphy->leds.pin); + if (mphy->leds.al) + val |= MT_LED_CTRL_POLARITY(mphy->leds.pin); mt76_wr(dev, MT_LED_CTRL, val); } @@ -113,14 +112,14 @@ mt76x02_led_set_blink(struct led_classdev *led_cdev, unsigned long *delay_on, unsigned long *delay_off) { - struct mt76_dev *mdev = container_of(led_cdev, struct mt76_dev, - led_cdev); + struct mt76_phy *mphy = container_of(led_cdev, struct mt76_phy, + leds.cdev); u8 delta_on, delta_off; delta_off = max_t(u8, *delay_off / 10, 1); delta_on = max_t(u8, *delay_on / 10, 1); - mt76x02_led_set_config(mdev, delta_on, delta_off); + mt76x02_led_set_config(mphy, delta_on, delta_off); return 0; } @@ -129,13 +128,13 @@ static void mt76x02_led_set_brightness(struct led_classdev *led_cdev, enum led_brightness brightness) { - struct mt76_dev *mdev = container_of(led_cdev, struct mt76_dev, - led_cdev); + struct mt76_phy *mphy = container_of(led_cdev, struct mt76_phy, + leds.cdev); if (!brightness) - mt76x02_led_set_config(mdev, 0, 0xff); + mt76x02_led_set_config(mphy, 0, 0xff); else - mt76x02_led_set_config(mdev, 0xff, 0); + mt76x02_led_set_config(mphy, 0xff, 0); } int mt76x02_init_device(struct mt76x02_dev *dev) @@ -167,9 +166,9 @@ int mt76x02_init_device(struct mt76x02_dev *dev) /* init led callbacks */ if (IS_ENABLED(CONFIG_MT76_LEDS)) { - dev->mt76.led_cdev.brightness_set = + dev->mphy.leds.cdev.brightness_set = mt76x02_led_set_brightness; - dev->mt76.led_cdev.blink_set = mt76x02_led_set_blink; + dev->mphy.leds.cdev.blink_set = mt76x02_led_set_blink; } } diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c index fb46c2c1784f..5a46813a59ea 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c @@ -811,7 +811,7 @@ mt7915_hw_queue_read(struct seq_file *s, u32 size, if (val & BIT(map[i].index)) continue; - ctrl = BIT(31) | (map[i].pid << 10) | (map[i].qid << 24); + ctrl = BIT(31) | (map[i].pid << 10) | ((u32)map[i].qid << 24); mt76_wr(dev, MT_FL_Q0_CTRL, ctrl); head = mt76_get_field(dev, MT_FL_Q2_CTRL, @@ -996,7 +996,7 @@ mt7915_rate_txpower_get(struct file *file, char __user *user_buf, ret = mt7915_mcu_get_txpower_sku(phy, txpwr, sizeof(txpwr)); if (ret) - return ret; + goto out; /* Txpower propagation path: TMAC -> TXV -> BBP */ len += scnprintf(buf + len, sz - len, @@ -1047,6 +1047,8 @@ mt7915_rate_txpower_get(struct file *file, char __user *user_buf, mt76_get_field(dev, reg, MT_WF_PHY_TPC_POWER)); ret = simple_read_from_buffer(user_buf, count, ppos, buf, len); + +out: kfree(buf); return ret; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c index 59069fb86414..24efa280dd86 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c @@ -110,18 +110,23 @@ static int mt7915_eeprom_load(struct mt7915_dev *dev) } else { u8 free_block_num; u32 block_num, i; + u32 eeprom_blk_size = MT7915_EEPROM_BLOCK_SIZE; - mt7915_mcu_get_eeprom_free_block(dev, &free_block_num); - /* efuse info not enough */ + ret = mt7915_mcu_get_eeprom_free_block(dev, &free_block_num); + if (ret < 0) + return ret; + + /* efuse info isn't enough */ if (free_block_num >= 29) return -EINVAL; /* read eeprom data from efuse */ - block_num = DIV_ROUND_UP(eeprom_size, - MT7915_EEPROM_BLOCK_SIZE); - for (i = 0; i < block_num; i++) - mt7915_mcu_get_eeprom(dev, - i * MT7915_EEPROM_BLOCK_SIZE); + block_num = DIV_ROUND_UP(eeprom_size, eeprom_blk_size); + for (i = 0; i < block_num; i++) { + ret = mt7915_mcu_get_eeprom(dev, i * eeprom_blk_size); + if (ret < 0) + return ret; + } } return mt7915_check_eeprom(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c index c810c31fbd6e..571c94835942 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c @@ -209,30 +209,31 @@ static void mt7915_led_set_config(struct led_classdev *led_cdev, u8 delay_on, u8 delay_off) { struct mt7915_dev *dev; - struct mt76_dev *mt76; + struct mt76_phy *mphy; u32 val; - mt76 = container_of(led_cdev, struct mt76_dev, led_cdev); - dev = container_of(mt76, struct mt7915_dev, mt76); + mphy = container_of(led_cdev, struct mt76_phy, leds.cdev); + dev = container_of(mphy->dev, struct mt7915_dev, mt76); - /* select TX blink mode, 2: only data frames */ - mt76_rmw_field(dev, MT_TMAC_TCR0(0), MT_TMAC_TCR0_TX_BLINK, 2); + /* set PWM mode */ + val = FIELD_PREP(MT_LED_STATUS_DURATION, 0xffff) | + FIELD_PREP(MT_LED_STATUS_OFF, delay_off) | + FIELD_PREP(MT_LED_STATUS_ON, delay_on); + mt76_wr(dev, MT_LED_STATUS_0(mphy->band_idx), val); + mt76_wr(dev, MT_LED_STATUS_1(mphy->band_idx), val); /* enable LED */ - mt76_wr(dev, MT_LED_EN(0), 1); - - /* set LED Tx blink on/off time */ - val = FIELD_PREP(MT_LED_TX_BLINK_ON_MASK, delay_on) | - FIELD_PREP(MT_LED_TX_BLINK_OFF_MASK, delay_off); - mt76_wr(dev, MT_LED_TX_BLINK(0), val); + mt76_wr(dev, MT_LED_EN(mphy->band_idx), 1); /* control LED */ - val = MT_LED_CTRL_BLINK_MODE | MT_LED_CTRL_KICK; - if (dev->mt76.led_al) + val = MT_LED_CTRL_KICK; + if (dev->mphy.leds.al) val |= MT_LED_CTRL_POLARITY; + if (mphy->band_idx) + val |= MT_LED_CTRL_BAND; - mt76_wr(dev, MT_LED_CTRL(0), val); - mt76_clear(dev, MT_LED_CTRL(0), MT_LED_CTRL_KICK); + mt76_wr(dev, MT_LED_CTRL(mphy->band_idx), val); + mt76_clear(dev, MT_LED_CTRL(mphy->band_idx), MT_LED_CTRL_KICK); } static int mt7915_led_set_blink(struct led_classdev *led_cdev, @@ -319,9 +320,10 @@ mt7915_regd_notifier(struct wiphy *wiphy, } static void -mt7915_init_wiphy(struct ieee80211_hw *hw) +mt7915_init_wiphy(struct mt7915_phy *phy) { - struct mt7915_phy *phy = mt7915_hw_phy(hw); + struct mt76_phy *mphy = phy->mt76; + struct ieee80211_hw *hw = mphy->hw; struct mt76_dev *mdev = &phy->dev->mt76; struct wiphy *wiphy = hw->wiphy; struct mt7915_dev *dev = phy->dev; @@ -415,6 +417,12 @@ mt7915_init_wiphy(struct ieee80211_hw *hw) wiphy->available_antennas_rx = phy->mt76->antenna_mask; wiphy->available_antennas_tx = phy->mt76->antenna_mask; + + /* init led callbacks */ + if (IS_ENABLED(CONFIG_MT76_LEDS)) { + mphy->leds.cdev.brightness_set = mt7915_led_set_brightness; + mphy->leds.cdev.blink_set = mt7915_led_set_blink; + } } static void @@ -473,6 +481,72 @@ mt7915_mac_init_band(struct mt7915_dev *dev, u8 band) mt76_rmw(dev, MT_WTBLOFF_TOP_RSCR(band), mask, set); } +static void +mt7915_init_led_mux(struct mt7915_dev *dev) +{ + if (!IS_ENABLED(CONFIG_MT76_LEDS)) + return; + + if (dev->dbdc_support) { + switch (mt76_chip(&dev->mt76)) { + case 0x7915: + mt76_rmw_field(dev, MT_LED_GPIO_MUX2, + GENMASK(11, 8), 4); + mt76_rmw_field(dev, MT_LED_GPIO_MUX3, + GENMASK(11, 8), 4); + break; + case 0x7986: + mt76_rmw_field(dev, MT_LED_GPIO_MUX0, + GENMASK(7, 4), 1); + mt76_rmw_field(dev, MT_LED_GPIO_MUX0, + GENMASK(11, 8), 1); + break; + case 0x7916: + mt76_rmw_field(dev, MT_LED_GPIO_MUX1, + GENMASK(27, 24), 3); + mt76_rmw_field(dev, MT_LED_GPIO_MUX1, + GENMASK(31, 28), 3); + break; + default: + break; + } + } else if (dev->mphy.leds.pin) { + switch (mt76_chip(&dev->mt76)) { + case 0x7915: + mt76_rmw_field(dev, MT_LED_GPIO_MUX3, + GENMASK(11, 8), 4); + break; + case 0x7986: + mt76_rmw_field(dev, MT_LED_GPIO_MUX0, + GENMASK(11, 8), 1); + break; + case 0x7916: + mt76_rmw_field(dev, MT_LED_GPIO_MUX1, + GENMASK(31, 28), 3); + break; + default: + break; + } + } else { + switch (mt76_chip(&dev->mt76)) { + case 0x7915: + mt76_rmw_field(dev, MT_LED_GPIO_MUX2, + GENMASK(11, 8), 4); + break; + case 0x7986: + mt76_rmw_field(dev, MT_LED_GPIO_MUX0, + GENMASK(7, 4), 1); + break; + case 0x7916: + mt76_rmw_field(dev, MT_LED_GPIO_MUX1, + GENMASK(27, 24), 3); + break; + default: + break; + } + } +} + void mt7915_mac_init(struct mt7915_dev *dev) { int i; @@ -497,10 +571,7 @@ void mt7915_mac_init(struct mt7915_dev *dev) for (i = 0; i < 2; i++) mt7915_mac_init_band(dev, i); - if (IS_ENABLED(CONFIG_MT76_LEDS)) { - i = dev->mt76.led_pin ? MT_LED_GPIO_MUX3 : MT_LED_GPIO_MUX2; - mt76_rmw_field(dev, i, MT_LED_GPIO_SEL_MASK, 4); - } + mt7915_init_led_mux(dev); } int mt7915_txbf_init(struct mt7915_dev *dev) @@ -569,7 +640,7 @@ mt7915_register_ext_phy(struct mt7915_dev *dev, struct mt7915_phy *phy) mt76_eeprom_override(mphy); /* init wiphy according to mphy and phy */ - mt7915_init_wiphy(mphy->hw); + mt7915_init_wiphy(phy); ret = mt76_register_phy(mphy, true, mt76_rates, ARRAY_SIZE(mt76_rates)); @@ -1104,7 +1175,6 @@ static void mt7915_stop_hardware(struct mt7915_dev *dev) int mt7915_register_device(struct mt7915_dev *dev) { - struct ieee80211_hw *hw = mt76_hw(dev); struct mt7915_phy *phy2; int ret; @@ -1133,18 +1203,12 @@ int mt7915_register_device(struct mt7915_dev *dev) if (ret) goto free_phy2; - mt7915_init_wiphy(hw); + mt7915_init_wiphy(&dev->phy); #ifdef CONFIG_NL80211_TESTMODE dev->mt76.test_ops = &mt7915_testmode_ops; #endif - /* init led callbacks */ - if (IS_ENABLED(CONFIG_MT76_LEDS)) { - dev->mt76.led_cdev.brightness_set = mt7915_led_set_brightness; - dev->mt76.led_cdev.blink_set = mt7915_led_set_blink; - } - ret = mt76_register_device(&dev->mt76, true, mt76_rates, ARRAY_SIZE(mt76_rates)); if (ret) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c index b2652de082ba..37a3c1f082d9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -232,8 +232,11 @@ mt7915_mcu_rx_csa_notify(struct mt7915_dev *dev, struct sk_buff *skb) c = (struct mt7915_mcu_csa_notify *)skb->data; + if (c->band_idx > MT_BAND1) + return; + if ((c->band_idx && !dev->phy.mt76->band_idx) && - dev->mt76.phys[MT_BAND1]) + dev->mt76.phys[MT_BAND1]) mphy = dev->mt76.phys[MT_BAND1]; ieee80211_iterate_active_interfaces_atomic(mphy->hw, @@ -252,8 +255,11 @@ mt7915_mcu_rx_thermal_notify(struct mt7915_dev *dev, struct sk_buff *skb) if (t->ctrl.ctrl_id != THERMAL_PROTECT_ENABLE) return; + if (t->ctrl.band_idx > MT_BAND1) + return; + if ((t->ctrl.band_idx && !dev->phy.mt76->band_idx) && - dev->mt76.phys[MT_BAND1]) + dev->mt76.phys[MT_BAND1]) mphy = dev->mt76.phys[MT_BAND1]; phy = (struct mt7915_phy *)mphy->priv; @@ -268,8 +274,11 @@ mt7915_mcu_rx_radar_detected(struct mt7915_dev *dev, struct sk_buff *skb) r = (struct mt7915_mcu_rdd_report *)skb->data; + if (r->band_idx > MT_BAND1) + return; + if ((r->band_idx && !dev->phy.mt76->band_idx) && - dev->mt76.phys[MT_BAND1]) + dev->mt76.phys[MT_BAND1]) mphy = dev->mt76.phys[MT_BAND1]; if (r->band_idx == MT_RX_SEL2) @@ -326,7 +335,11 @@ mt7915_mcu_rx_bcc_notify(struct mt7915_dev *dev, struct sk_buff *skb) b = (struct mt7915_mcu_bcc_notify *)skb->data; - if ((b->band_idx && !dev->phy.mt76->band_idx) && dev->mt76.phys[MT_BAND1]) + if (b->band_idx > MT_BAND1) + return; + + if ((b->band_idx && !dev->phy.mt76->band_idx) && + dev->mt76.phys[MT_BAND1]) mphy = dev->mt76.phys[MT_BAND1]; ieee80211_iterate_active_interfaces_atomic(mphy->hw, @@ -2792,8 +2805,9 @@ int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset) int ret; u8 *buf; - ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_QUERY(EFUSE_ACCESS), &req, - sizeof(req), true, &skb); + ret = mt76_mcu_send_and_get_msg(&dev->mt76, + MCU_EXT_QUERY(EFUSE_ACCESS), + &req, sizeof(req), true, &skb); if (ret) return ret; @@ -2818,8 +2832,9 @@ int mt7915_mcu_get_eeprom_free_block(struct mt7915_dev *dev, u8 *block_num) struct sk_buff *skb; int ret; - ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_QUERY(EFUSE_FREE_BLOCK), &req, - sizeof(req), true, &skb); + ret = mt76_mcu_send_and_get_msg(&dev->mt76, + MCU_EXT_QUERY(EFUSE_FREE_BLOCK), + &req, sizeof(req), true, &skb); if (ret) return ret; @@ -2974,38 +2989,42 @@ int mt7915_mcu_apply_tx_dpd(struct mt7915_phy *phy) int mt7915_mcu_get_chan_mib_info(struct mt7915_phy *phy, bool chan_switch) { - /* strict order */ - static const u32 offs[] = { - MIB_NON_WIFI_TIME, - MIB_TX_TIME, - MIB_RX_TIME, - MIB_OBSS_AIRTIME, - MIB_TXOP_INIT_COUNT, - /* v2 */ - MIB_NON_WIFI_TIME_V2, - MIB_TX_TIME_V2, - MIB_RX_TIME_V2, - MIB_OBSS_AIRTIME_V2 - }; struct mt76_channel_state *state = phy->mt76->chan_state; struct mt76_channel_state *state_ts = &phy->state_ts; struct mt7915_dev *dev = phy->dev; struct mt7915_mcu_mib *res, req[5]; struct sk_buff *skb; - int i, ret, start = 0, ofs = 20; + static const u32 *offs; + int i, ret, len, offs_cc; u64 cc_tx; - if (!is_mt7915(&dev->mt76)) { - start = 5; - ofs = 0; + /* strict order */ + if (is_mt7915(&dev->mt76)) { + static const u32 chip_offs[] = { + MIB_NON_WIFI_TIME, + MIB_TX_TIME, + MIB_RX_TIME, + MIB_OBSS_AIRTIME, + MIB_TXOP_INIT_COUNT, + }; + len = ARRAY_SIZE(chip_offs); + offs = chip_offs; + offs_cc = 20; + } else { + static const u32 chip_offs[] = { + MIB_NON_WIFI_TIME_V2, + MIB_TX_TIME_V2, + MIB_RX_TIME_V2, + MIB_OBSS_AIRTIME_V2 + }; + len = ARRAY_SIZE(chip_offs); + offs = chip_offs; + offs_cc = 0; } - for (i = 0; i < 5; i++) { + for (i = 0; i < len; i++) { req[i].band = cpu_to_le32(phy->mt76->band_idx); - req[i].offs = cpu_to_le32(offs[i + start]); - - if (!is_mt7915(&dev->mt76) && i == 3) - break; + req[i].offs = cpu_to_le32(offs[i]); } ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_CMD(GET_MIB_INFO), @@ -3013,7 +3032,7 @@ int mt7915_mcu_get_chan_mib_info(struct mt7915_phy *phy, bool chan_switch) if (ret) return ret; - res = (struct mt7915_mcu_mib *)(skb->data + ofs); + res = (struct mt7915_mcu_mib *)(skb->data + offs_cc); #define __res_u64(s) le64_to_cpu(res[s].data) /* subtract Tx backoff time from Tx duration */ diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c index 0a95c3da241b..1a2e4df8d1b5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c @@ -495,7 +495,7 @@ static u32 __mt7915_reg_addr(struct mt7915_dev *dev, u32 addr) if (dev_is_pci(dev->mt76.dev) && ((addr >= MT_CBTOP1_PHY_START && addr <= MT_CBTOP1_PHY_END) || - (addr >= MT_CBTOP2_PHY_START && addr <= MT_CBTOP2_PHY_END))) + addr >= MT_CBTOP2_PHY_START)) return mt7915_reg_map_l1(dev, addr); /* CONN_INFRA: covert to phyiscal addr and use layer 1 remap */ @@ -594,10 +594,13 @@ static void mt7915_mmio_wed_offload_disable(struct mtk_wed_device *wed) static void mt7915_mmio_wed_release_rx_buf(struct mtk_wed_device *wed) { struct mt7915_dev *dev; - struct page *page; + u32 length; int i; dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed); + length = SKB_DATA_ALIGN(NET_SKB_PAD + wed->wlan.rx_size + + sizeof(struct skb_shared_info)); + for (i = 0; i < dev->mt76.rx_token_size; i++) { struct mt76_txwi_cache *t; @@ -607,18 +610,11 @@ static void mt7915_mmio_wed_release_rx_buf(struct mtk_wed_device *wed) dma_unmap_single(dev->mt76.dma_dev, t->dma_addr, wed->wlan.rx_size, DMA_FROM_DEVICE); - skb_free_frag(t->ptr); + __free_pages(virt_to_page(t->ptr), get_order(length)); t->ptr = NULL; mt76_put_rxwi(&dev->mt76, t); } - - if (!wed->rx_buf_ring.rx_page.va) - return; - - page = virt_to_page(wed->rx_buf_ring.rx_page.va); - __page_frag_cache_drain(page, wed->rx_buf_ring.rx_page.pagecnt_bias); - memset(&wed->rx_buf_ring.rx_page, 0, sizeof(wed->rx_buf_ring.rx_page)); } static u32 mt7915_mmio_wed_init_rx_buf(struct mtk_wed_device *wed, int size) @@ -635,24 +631,32 @@ static u32 mt7915_mmio_wed_init_rx_buf(struct mtk_wed_device *wed, int size) for (i = 0; i < size; i++) { struct mt76_txwi_cache *t = mt76_get_rxwi(&dev->mt76); dma_addr_t phy_addr; + struct page *page; int token; void *ptr; - ptr = page_frag_alloc(&wed->rx_buf_ring.rx_page, length, - GFP_KERNEL); - if (!ptr) + page = __dev_alloc_pages(GFP_KERNEL, get_order(length)); + if (!page) goto unmap; + ptr = page_address(page); phy_addr = dma_map_single(dev->mt76.dma_dev, ptr, wed->wlan.rx_size, DMA_TO_DEVICE); if (unlikely(dma_mapping_error(dev->mt76.dev, phy_addr))) { - skb_free_frag(ptr); + __free_pages(page, get_order(length)); goto unmap; } desc->buf0 = cpu_to_le32(phy_addr); token = mt76_rx_token_consume(&dev->mt76, ptr, t, phy_addr); + if (token < 0) { + dma_unmap_single(dev->mt76.dma_dev, phy_addr, + wed->wlan.rx_size, DMA_TO_DEVICE); + __free_pages(page, get_order(length)); + goto unmap; + } + desc->token |= cpu_to_le32(FIELD_PREP(MT_DMA_CTL_TOKEN, token)); desc++; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/regs.h b/drivers/net/wireless/mediatek/mt76/mt7915/regs.h index aca1b2f1e9e3..c8e478a55081 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/regs.h @@ -803,7 +803,6 @@ enum offs_rev { #define MT_CBTOP1_PHY_START 0x70000000 #define MT_CBTOP1_PHY_END __REG(CBTOP1_PHY_END) #define MT_CBTOP2_PHY_START 0xf0000000 -#define MT_CBTOP2_PHY_END 0xffffffff #define MT_INFRA_MCU_START 0x7c000000 #define MT_INFRA_MCU_END __REG(INFRA_MCU_ADDR_END) #define MT_CONN_INFRA_OFFSET(p) ((p) - MT_INFRA_BASE) @@ -1055,6 +1054,7 @@ enum offs_rev { #define MT_LED_CTRL(_n) MT_LED_PHYS(0x00 + ((_n) * 4)) #define MT_LED_CTRL_KICK BIT(7) +#define MT_LED_CTRL_BAND BIT(4) #define MT_LED_CTRL_BLINK_MODE BIT(2) #define MT_LED_CTRL_POLARITY BIT(1) @@ -1062,11 +1062,18 @@ enum offs_rev { #define MT_LED_TX_BLINK_ON_MASK GENMASK(7, 0) #define MT_LED_TX_BLINK_OFF_MASK GENMASK(15, 8) +#define MT_LED_STATUS_0(_n) MT_LED_PHYS(0x20 + ((_n) * 8)) +#define MT_LED_STATUS_1(_n) MT_LED_PHYS(0x24 + ((_n) * 8)) +#define MT_LED_STATUS_OFF GENMASK(31, 24) +#define MT_LED_STATUS_ON GENMASK(23, 16) +#define MT_LED_STATUS_DURATION GENMASK(15, 0) + #define MT_LED_EN(_n) MT_LED_PHYS(0x40 + ((_n) * 4)) +#define MT_LED_GPIO_MUX0 0x70005050 /* GPIO 1 and GPIO 2 */ +#define MT_LED_GPIO_MUX1 0x70005054 /* GPIO 14 and 15 */ #define MT_LED_GPIO_MUX2 0x70005058 /* GPIO 18 */ -#define MT_LED_GPIO_MUX3 0x7000505C /* GPIO 26 */ -#define MT_LED_GPIO_SEL_MASK GENMASK(11, 8) +#define MT_LED_GPIO_MUX3 0x7000505c /* GPIO 26 */ /* MT TOP */ #define MT_TOP_BASE 0x18060000 diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/soc.c b/drivers/net/wireless/mediatek/mt76/mt7915/soc.c index c06c56a0270d..686c9bbd5929 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/soc.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/soc.c @@ -278,6 +278,7 @@ static int mt7986_wmac_coninfra_setup(struct mt7915_dev *dev) return -EINVAL; rmem = of_reserved_mem_lookup(np); + of_node_put(np); if (!rmem) return -EINVAL; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.c b/drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.c index 47e034a9b003..a98d0fb42d0a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.c @@ -135,6 +135,22 @@ mt7921_asar_acpi_read_mtgs(struct mt7921_dev *dev, u8 **table, u8 version) return ret; } +/* MTFG : Flag Table */ +static int +mt7921_asar_acpi_read_mtfg(struct mt7921_dev *dev, u8 **table) +{ + int len, ret; + + ret = mt7921_acpi_read(dev, MT7921_ACPI_MTFG, table, &len); + if (ret) + return ret; + + if (len < MT7921_ASAR_MIN_FG) + ret = -EINVAL; + + return ret; +} + int mt7921_init_acpi_sar(struct mt7921_dev *dev) { struct mt7921_acpi_sar *asar; @@ -162,6 +178,12 @@ int mt7921_init_acpi_sar(struct mt7921_dev *dev) asar->geo = NULL; } + /* MTFG is optional */ + ret = mt7921_asar_acpi_read_mtfg(dev, (u8 **)&asar->fg); + if (ret) { + devm_kfree(dev->mt76.dev, asar->fg); + asar->fg = NULL; + } dev->phy.acpisar = asar; return 0; @@ -280,3 +302,36 @@ int mt7921_init_acpi_sar_power(struct mt7921_phy *phy, bool set_default) return 0; } + +u8 mt7921_acpi_get_flags(struct mt7921_phy *phy) +{ + struct mt7921_asar_fg *fg; + struct { + u8 acpi_idx; + u8 chip_idx; + } map[] = { + {1, 1}, + {4, 2}, + }; + u8 flags = BIT(0); + int i, j; + + if (!phy->acpisar) + return 0; + + fg = phy->acpisar->fg; + if (!fg) + return flags; + + /* pickup necessary settings per device and + * translate the index of bitmap for chip command. + */ + for (i = 0; i < fg->nr_flag; i++) + for (j = 0; j < ARRAY_SIZE(map); j++) + if (fg->flag[i] == map[j].acpi_idx) { + flags |= BIT(map[j].chip_idx); + break; + } + + return flags; +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.h b/drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.h index 23f86bfae0c0..35268b0890ad 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.h @@ -8,10 +8,12 @@ #define MT7921_ASAR_MAX_DYN 8 #define MT7921_ASAR_MIN_GEO 3 #define MT7921_ASAR_MAX_GEO 8 +#define MT7921_ASAR_MIN_FG 8 #define MT7921_ACPI_MTCL "MTCL" #define MT7921_ACPI_MTDS "MTDS" #define MT7921_ACPI_MTGS "MTGS" +#define MT7921_ACPI_MTFG "MTFG" struct mt7921_asar_dyn_limit { u8 idx; @@ -77,6 +79,15 @@ struct mt7921_asar_cl { u8 cl6g[6]; } __packed; +struct mt7921_asar_fg { + u8 names[4]; + u8 version; + u8 rsvd; + u8 nr_flag; + u8 rsvd1; + u8 flag[0]; +} __packed; + struct mt7921_acpi_sar { u8 ver; union { @@ -88,6 +99,7 @@ struct mt7921_acpi_sar { struct mt7921_asar_geo_v2 *geo_v2; }; struct mt7921_asar_cl *countrylist; + struct mt7921_asar_fg *fg; }; #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c index 542dfd425129..d4b681d7e1d2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c @@ -175,7 +175,7 @@ u8 mt7921_check_offload_capability(struct device *dev, const char *fw_wm) if (!fw || !fw->data || fw->size < sizeof(*hdr)) { dev_err(dev, "Invalid firmware\n"); - return -EINVAL; + goto out; } data = fw->data; @@ -206,6 +206,7 @@ u8 mt7921_check_offload_capability(struct device *dev, const char *fw_wm) data += le16_to_cpu(rel_info->len) + rel_info->pad_len; } +out: release_firmware(fw); return features ? features->data : 0; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c index fb9c0f66cb27..8930b5a4467c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c @@ -1184,13 +1184,15 @@ int __mt7921_mcu_set_clc(struct mt7921_dev *dev, u8 *alpha2, __le16 len; u8 idx; u8 env; - u8 pad1[2]; + u8 acpi_conf; + u8 pad1; u8 alpha2[2]; u8 type[2]; u8 rsvd[64]; } __packed req = { .idx = idx, .env = env_cap, + .acpi_conf = mt7921_acpi_get_flags(&dev->phy), }; int ret, valid_cnt = 0; u8 i, *pos; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index 15d6b7fe1c6c..efff4d43d796 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -554,6 +554,7 @@ int mt7921_mcu_uni_add_beacon_offload(struct mt7921_dev *dev, #ifdef CONFIG_ACPI int mt7921_init_acpi_sar(struct mt7921_dev *dev); int mt7921_init_acpi_sar_power(struct mt7921_phy *phy, bool set_default); +u8 mt7921_acpi_get_flags(struct mt7921_phy *phy); #else static inline int mt7921_init_acpi_sar(struct mt7921_dev *dev) @@ -566,6 +567,12 @@ mt7921_init_acpi_sar_power(struct mt7921_phy *phy, bool set_default) { return 0; } + +static inline u8 +mt7921_acpi_get_flags(struct mt7921_phy *phy) +{ + return 0; +} #endif int mt7921_set_tx_sar_pwr(struct ieee80211_hw *hw, const struct cfg80211_sar_specs *sar); diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c index 2e4a8909b9e8..3d4fbbbcc206 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c @@ -457,7 +457,7 @@ mt7996_hw_queue_read(struct seq_file *s, u32 size, if (val & BIT(map[i].index)) continue; - ctrl = BIT(31) | (map[i].pid << 10) | (map[i].qid << 24); + ctrl = BIT(31) | (map[i].pid << 10) | ((u32)map[i].qid << 24); mt76_wr(dev, MT_FL_Q0_CTRL, ctrl); head = mt76_get_field(dev, MT_FL_Q2_CTRL, @@ -653,8 +653,9 @@ static int mt7996_rf_regval_set(void *data, u64 val) { struct mt7996_dev *dev = data; + u32 val32 = val; - return mt7996_mcu_rf_regval(dev, dev->mt76.debugfs_reg, (u32 *)&val, true); + return mt7996_mcu_rf_regval(dev, dev->mt76.debugfs_reg, &val32, true); } DEFINE_DEBUGFS_ATTRIBUTE(fops_rf_regval, mt7996_rf_regval_get, diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7996/eeprom.c index b9f62bedbc48..5d8e0353627e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/eeprom.c @@ -65,17 +65,23 @@ static int mt7996_eeprom_load(struct mt7996_dev *dev) } else { u8 free_block_num; u32 block_num, i; + u32 eeprom_blk_size = MT7996_EEPROM_BLOCK_SIZE; - /* TODO: check free block event */ - mt7996_mcu_get_eeprom_free_block(dev, &free_block_num); - /* efuse info not enough */ + ret = mt7996_mcu_get_eeprom_free_block(dev, &free_block_num); + if (ret < 0) + return ret; + + /* efuse info isn't enough */ if (free_block_num >= 59) return -EINVAL; /* read eeprom data from efuse */ - block_num = DIV_ROUND_UP(MT7996_EEPROM_SIZE, MT7996_EEPROM_BLOCK_SIZE); - for (i = 0; i < block_num; i++) - mt7996_mcu_get_eeprom(dev, i * MT7996_EEPROM_BLOCK_SIZE); + block_num = DIV_ROUND_UP(MT7996_EEPROM_SIZE, eeprom_blk_size); + for (i = 0; i < block_num; i++) { + ret = mt7996_mcu_get_eeprom(dev, i * eeprom_blk_size); + if (ret < 0) + return ret; + } } return mt7996_check_eeprom(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/init.c b/drivers/net/wireless/mediatek/mt76/mt7996/init.c index 46b290526092..64e8dfd06e9f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/init.c @@ -46,11 +46,11 @@ static void mt7996_led_set_config(struct led_classdev *led_cdev, u8 delay_on, u8 delay_off) { struct mt7996_dev *dev; - struct mt76_dev *mt76; + struct mt76_phy *mphy; u32 val; - mt76 = container_of(led_cdev, struct mt76_dev, led_cdev); - dev = container_of(mt76, struct mt7996_dev, mt76); + mphy = container_of(led_cdev, struct mt76_phy, leds.cdev); + dev = container_of(mphy->dev, struct mt7996_dev, mt76); /* select TX blink mode, 2: only data frames */ mt76_rmw_field(dev, MT_TMAC_TCR0(0), MT_TMAC_TCR0_TX_BLINK, 2); @@ -65,7 +65,7 @@ static void mt7996_led_set_config(struct led_classdev *led_cdev, /* control LED */ val = MT_LED_CTRL_BLINK_MODE | MT_LED_CTRL_KICK; - if (dev->mt76.led_al) + if (mphy->leds.al) val |= MT_LED_CTRL_POLARITY; mt76_wr(dev, MT_LED_CTRL(0), val); @@ -261,7 +261,7 @@ static void mt7996_mac_init(struct mt7996_dev *dev) MT_WTBL_UPDATE_ADM_COUNT_CLEAR); if (IS_ENABLED(CONFIG_MT76_LEDS)) { - i = dev->mt76.led_pin ? MT_LED_GPIO_MUX3 : MT_LED_GPIO_MUX2; + i = dev->mphy.leds.pin ? MT_LED_GPIO_MUX3 : MT_LED_GPIO_MUX2; mt76_rmw_field(dev, i, MT_LED_GPIO_SEL_MASK, 4); } @@ -787,8 +787,8 @@ int mt7996_register_device(struct mt7996_dev *dev) /* init led callbacks */ if (IS_ENABLED(CONFIG_MT76_LEDS)) { - dev->mt76.led_cdev.brightness_set = mt7996_led_set_brightness; - dev->mt76.led_cdev.blink_set = mt7996_led_set_blink; + dev->mphy.leds.cdev.brightness_set = mt7996_led_set_brightness; + dev->mphy.leds.cdev.blink_set = mt7996_led_set_blink; } ret = mt76_register_device(&dev->mt76, true, mt76_rates, diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c index 04e1d10bbd21..a88fc7680b1a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c @@ -335,6 +335,9 @@ mt7996_mcu_rx_radar_detected(struct mt7996_dev *dev, struct sk_buff *skb) r = (struct mt7996_mcu_rdd_report *)skb->data; + if (r->band_idx >= ARRAY_SIZE(dev->mt76.phys)) + return; + mphy = dev->mt76.phys[r->band_idx]; if (!mphy) return; @@ -412,6 +415,9 @@ mt7996_mcu_ie_countdown(struct mt7996_dev *dev, struct sk_buff *skb) struct header *hdr = (struct header *)data; struct tlv *tlv = (struct tlv *)(data + 4); + if (hdr->band >= ARRAY_SIZE(dev->mt76.phys)) + return; + if (hdr->band && dev->mt76.phys[hdr->band]) mphy = dev->mt76.phys[hdr->band]; @@ -903,8 +909,8 @@ mt7996_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta) he = (struct sta_rec_he_v2 *)tlv; for (i = 0; i < 11; i++) { if (i < 6) - he->he_mac_cap[i] = cpu_to_le16(elem->mac_cap_info[i]); - he->he_phy_cap[i] = cpu_to_le16(elem->phy_cap_info[i]); + he->he_mac_cap[i] = elem->mac_cap_info[i]; + he->he_phy_cap[i] = elem->phy_cap_info[i]; } mcs_map = sta->deflink.he_cap.he_mcs_nss_supp; @@ -2921,8 +2927,9 @@ int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset) bool valid; int ret; - ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_WM_UNI_CMD_QUERY(EFUSE_CTRL), &req, - sizeof(req), true, &skb); + ret = mt76_mcu_send_and_get_msg(&dev->mt76, + MCU_WM_UNI_CMD_QUERY(EFUSE_CTRL), + &req, sizeof(req), true, &skb); if (ret) return ret; diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c index 521769eb6b0e..60781d046216 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c @@ -149,7 +149,7 @@ static u32 __mt7996_reg_addr(struct mt7996_dev *dev, u32 addr) if (dev_is_pci(dev->mt76.dev) && ((addr >= MT_CBTOP1_PHY_START && addr <= MT_CBTOP1_PHY_END) || - (addr >= MT_CBTOP2_PHY_START && addr <= MT_CBTOP2_PHY_END))) + addr >= MT_CBTOP2_PHY_START)) return mt7996_reg_map_l1(dev, addr); /* CONN_INFRA: covert to phyiscal addr and use layer 1 remap */ diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/regs.h b/drivers/net/wireless/mediatek/mt76/mt7996/regs.h index 794f61b93a46..42980b97b4d4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/regs.h @@ -463,7 +463,6 @@ enum base_rev { #define MT_CBTOP1_PHY_START 0x70000000 #define MT_CBTOP1_PHY_END 0x77ffffff #define MT_CBTOP2_PHY_START 0xf0000000 -#define MT_CBTOP2_PHY_END 0xffffffff #define MT_INFRA_MCU_START 0x7c000000 #define MT_INFRA_MCU_END 0x7c3fffff diff --git a/drivers/net/wireless/mediatek/mt76/sdio_txrx.c b/drivers/net/wireless/mediatek/mt76/sdio_txrx.c index bfc4de50a4d2..ddd8c0cc744d 100644 --- a/drivers/net/wireless/mediatek/mt76/sdio_txrx.c +++ b/drivers/net/wireless/mediatek/mt76/sdio_txrx.c @@ -254,6 +254,10 @@ static int mt76s_tx_run_queue(struct mt76_dev *dev, struct mt76_queue *q) if (!test_bit(MT76_STATE_MCU_RUNNING, &dev->phy.state)) { __skb_put_zero(e->skb, 4); + err = __skb_grow(e->skb, roundup(e->skb->len, + sdio->func->cur_blksize)); + if (err) + return err; err = __mt76s_xmit_queue(dev, e->skb->data, e->skb->len); if (err) diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c index 24568b98ed9d..1f309d05380a 100644 --- a/drivers/net/wireless/mediatek/mt76/tx.c +++ b/drivers/net/wireless/mediatek/mt76/tx.c @@ -764,11 +764,12 @@ int mt76_rx_token_consume(struct mt76_dev *dev, void *ptr, spin_lock_bh(&dev->rx_token_lock); token = idr_alloc(&dev->rx_token, t, 0, dev->rx_token_size, GFP_ATOMIC); + if (token >= 0) { + t->ptr = ptr; + t->dma_addr = phys; + } spin_unlock_bh(&dev->rx_token_lock); - t->ptr = ptr; - t->dma_addr = phys; - return token; } EXPORT_SYMBOL_GPL(mt76_rx_token_consume); diff --git a/include/linux/soc/mediatek/mtk_wed.h b/include/linux/soc/mediatek/mtk_wed.h index a0746d4aec20..db637a13888d 100644 --- a/include/linux/soc/mediatek/mtk_wed.h +++ b/include/linux/soc/mediatek/mtk_wed.h @@ -103,7 +103,6 @@ struct mtk_wed_device { struct { int size; - struct page_frag_cache rx_page; struct mtk_rxbm_desc *desc; dma_addr_t desc_phys; } rx_buf_ring; |