Skip to content

Commit

Permalink
Merge tag 'mt76-for-kvalo-2023-12-06' of https://github.com/nbd168/wi…
Browse files Browse the repository at this point in the history
…reless

mt76 patches for 6.8

* fixes
* nvmem eeprom improvements
* mt7996 eht improvements
* mt7996 wed support
* mt7996 36-bit DMA support
  • Loading branch information
Kalle Valo committed Dec 12, 2023
2 parents 68d83f0 + 10f2903 commit 3798722
Show file tree
Hide file tree
Showing 57 changed files with 3,266 additions and 743 deletions.
258 changes: 187 additions & 71 deletions drivers/net/wireless/mediatek/mt76/dma.c

Large diffs are not rendered by default.

54 changes: 54 additions & 0 deletions drivers/net/wireless/mediatek/mt76/dma.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,23 @@
#define MT_DMA_CTL_TO_HOST_A BIT(12)
#define MT_DMA_CTL_DROP BIT(14)
#define MT_DMA_CTL_TOKEN GENMASK(31, 16)
#define MT_DMA_CTL_SDP1_H GENMASK(19, 16)
#define MT_DMA_CTL_SDP0_H GENMASK(3, 0)
#define MT_DMA_CTL_WO_DROP BIT(8)

#define MT_DMA_PPE_CPU_REASON GENMASK(15, 11)
#define MT_DMA_PPE_ENTRY GENMASK(30, 16)
#define MT_DMA_INFO_DMA_FRAG BIT(9)
#define MT_DMA_INFO_PPE_VLD BIT(31)

#define MT_DMA_CTL_PN_CHK_FAIL BIT(13)
#define MT_DMA_CTL_VER_MASK BIT(7)

#define MT_DMA_RRO_EN BIT(13)

#define MT_DMA_WED_IND_CMD_CNT 8
#define MT_DMA_WED_IND_REASON GENMASK(15, 12)

#define MT_DMA_HDR_LEN 4
#define MT_RX_INFO_LEN 4
#define MT_FCE_INFO_LEN 4
Expand All @@ -37,6 +48,11 @@ struct mt76_desc {
__le32 info;
} __packed __aligned(4);

struct mt76_wed_rro_desc {
__le32 buf0;
__le32 buf1;
} __packed __aligned(4);

enum mt76_qsel {
MT_QSEL_MGMT,
MT_QSEL_HCCA,
Expand All @@ -54,9 +70,47 @@ enum mt76_mcu_evt_type {
EVT_EVENT_DFS_DETECT_RSP,
};

enum mt76_dma_wed_ind_reason {
MT_DMA_WED_IND_REASON_NORMAL,
MT_DMA_WED_IND_REASON_REPEAT,
MT_DMA_WED_IND_REASON_OLDPKT,
};

int mt76_dma_rx_poll(struct napi_struct *napi, int budget);
void mt76_dma_attach(struct mt76_dev *dev);
void mt76_dma_cleanup(struct mt76_dev *dev);
int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset);
void mt76_dma_wed_reset(struct mt76_dev *dev);

static inline void
mt76_dma_reset_tx_queue(struct mt76_dev *dev, struct mt76_queue *q)
{
dev->queue_ops->reset_q(dev, q);
if (mtk_wed_device_active(&dev->mmio.wed))
mt76_dma_wed_setup(dev, q, true);
}

static inline void
mt76_dma_should_drop_buf(bool *drop, u32 ctrl, u32 buf1, u32 info)
{
if (!drop)
return;

*drop = !!(ctrl & (MT_DMA_CTL_TO_HOST_A | MT_DMA_CTL_DROP));
if (!(ctrl & MT_DMA_CTL_VER_MASK))
return;

switch (FIELD_GET(MT_DMA_WED_IND_REASON, buf1)) {
case MT_DMA_WED_IND_REASON_REPEAT:
*drop = true;
break;
case MT_DMA_WED_IND_REASON_OLDPKT:
*drop = !(info & MT_DMA_INFO_DMA_FRAG);
break;
default:
*drop = !!(ctrl & MT_DMA_CTL_PN_CHK_FAIL);
break;
}
}

#endif
22 changes: 12 additions & 10 deletions drivers/net/wireless/mediatek/mt76/eeprom.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ static int mt76_get_of_eeprom_data(struct mt76_dev *dev, void *eep, int len)
return 0;
}

static int mt76_get_of_epprom_from_mtd(struct mt76_dev *dev, void *eep, int offset, int len)
int mt76_get_of_data_from_mtd(struct mt76_dev *dev, void *eep, int offset, int len)
{
#ifdef CONFIG_MTD
struct device_node *np = dev->dev->of_node;
Expand Down Expand Up @@ -67,7 +67,7 @@ static int mt76_get_of_epprom_from_mtd(struct mt76_dev *dev, void *eep, int offs
goto out_put_node;
}

offset = be32_to_cpup(list);
offset += be32_to_cpup(list);
ret = mtd_read(mtd, offset, len, &retlen, eep);
put_mtd_device(mtd);
if (mtd_is_bitflip(ret))
Expand Down Expand Up @@ -105,16 +105,18 @@ static int mt76_get_of_epprom_from_mtd(struct mt76_dev *dev, void *eep, int offs
return -ENOENT;
#endif
}
EXPORT_SYMBOL_GPL(mt76_get_of_data_from_mtd);

static int mt76_get_of_epprom_from_nvmem(struct mt76_dev *dev, void *eep, int len)
int mt76_get_of_data_from_nvmem(struct mt76_dev *dev, void *eep,
const char *cell_name, int len)
{
struct device_node *np = dev->dev->of_node;
struct nvmem_cell *cell;
const void *data;
size_t retlen;
int ret = 0;

cell = of_nvmem_cell_get(np, "eeprom");
cell = of_nvmem_cell_get(np, cell_name);
if (IS_ERR(cell))
return PTR_ERR(cell);

Expand All @@ -136,8 +138,9 @@ static int mt76_get_of_epprom_from_nvmem(struct mt76_dev *dev, void *eep, int le

return ret;
}
EXPORT_SYMBOL_GPL(mt76_get_of_data_from_nvmem);

int mt76_get_of_eeprom(struct mt76_dev *dev, void *eep, int offset, int len)
static int mt76_get_of_eeprom(struct mt76_dev *dev, void *eep, int len)
{
struct device_node *np = dev->dev->of_node;
int ret;
Expand All @@ -149,13 +152,12 @@ int mt76_get_of_eeprom(struct mt76_dev *dev, void *eep, int offset, int len)
if (!ret)
return 0;

ret = mt76_get_of_epprom_from_mtd(dev, eep, offset, len);
ret = mt76_get_of_data_from_mtd(dev, eep, 0, len);
if (!ret)
return 0;

return mt76_get_of_epprom_from_nvmem(dev, eep, len);
return mt76_get_of_data_from_nvmem(dev, eep, "eeprom", len);
}
EXPORT_SYMBOL_GPL(mt76_get_of_eeprom);

void
mt76_eeprom_override(struct mt76_phy *phy)
Expand Down Expand Up @@ -379,7 +381,7 @@ s8 mt76_get_rate_power_limits(struct mt76_phy *phy,
if (!np)
return target_power;

txs_delta = mt76_get_txs_delta(np, hweight8(phy->antenna_mask));
txs_delta = mt76_get_txs_delta(np, hweight16(phy->chainmask));

val = mt76_get_of_array(np, "rates-cck", &len, ARRAY_SIZE(dest->cck));
mt76_apply_array_limit(dest->cck, ARRAY_SIZE(dest->cck), val,
Expand Down Expand Up @@ -412,6 +414,6 @@ mt76_eeprom_init(struct mt76_dev *dev, int len)
if (!dev->eeprom.data)
return -ENOMEM;

return !mt76_get_of_eeprom(dev, dev->eeprom.data, 0, len);
return !mt76_get_of_eeprom(dev, dev->eeprom.data, len);
}
EXPORT_SYMBOL_GPL(mt76_eeprom_init);
60 changes: 44 additions & 16 deletions drivers/net/wireless/mediatek/mt76/mac80211.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,10 +197,33 @@ static int mt76_led_init(struct mt76_phy *phy)
{
struct mt76_dev *dev = phy->dev;
struct ieee80211_hw *hw = phy->hw;
struct device_node *np = dev->dev->of_node;

if (!phy->leds.cdev.brightness_set && !phy->leds.cdev.blink_set)
return 0;

np = of_get_child_by_name(np, "led");
if (np) {
if (!of_device_is_available(np)) {
of_node_put(np);
dev_info(dev->dev,
"led registration was explicitly disabled by dts\n");
return 0;
}

if (phy == &dev->phy) {
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);
}

snprintf(phy->leds.name, sizeof(phy->leds.name), "mt76-%s",
wiphy_name(hw->wiphy));

Expand All @@ -211,20 +234,8 @@ static int mt76_led_init(struct mt76_phy *phy)
mt76_tpt_blink,
ARRAY_SIZE(mt76_tpt_blink));

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);
}
}
dev_info(dev->dev,
"registering led '%s'\n", phy->leds.name);

return led_classdev_register(dev->dev, &phy->leds.cdev);
}
Expand Down Expand Up @@ -1537,7 +1548,7 @@ int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
int *dbm)
{
struct mt76_phy *phy = hw->priv;
int n_chains = hweight8(phy->antenna_mask);
int n_chains = hweight16(phy->chainmask);
int delta = mt76_tx_power_nss_delta(n_chains);

*dbm = DIV_ROUND_UP(phy->txpower_cur + delta, 2);
Expand Down Expand Up @@ -1725,7 +1736,7 @@ EXPORT_SYMBOL_GPL(mt76_get_antenna);

struct mt76_queue *
mt76_init_queue(struct mt76_dev *dev, int qid, int idx, int n_desc,
int ring_base, u32 flags)
int ring_base, void *wed, u32 flags)
{
struct mt76_queue *hwq;
int err;
Expand All @@ -1735,6 +1746,7 @@ mt76_init_queue(struct mt76_dev *dev, int qid, int idx, int n_desc,
return ERR_PTR(-ENOMEM);

hwq->flags = flags;
hwq->wed = wed;

err = dev->queue_ops->alloc(dev, hwq, idx, n_desc, 0, ring_base);
if (err < 0)
Expand Down Expand Up @@ -1842,3 +1854,19 @@ enum mt76_dfs_state mt76_phy_dfs_state(struct mt76_phy *phy)
return MT_DFS_STATE_ACTIVE;
}
EXPORT_SYMBOL_GPL(mt76_phy_dfs_state);

#ifdef CONFIG_NET_MEDIATEK_SOC_WED
int mt76_net_setup_tc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct net_device *netdev, enum tc_setup_type type,
void *type_data)
{
struct mt76_phy *phy = hw->priv;
struct mtk_wed_device *wed = &phy->dev->mmio.wed;

if (!mtk_wed_device_active(wed))
return -EOPNOTSUPP;

return mtk_wed_device_setup_tc(wed, netdev, type, type_data);
}
EXPORT_SYMBOL_GPL(mt76_net_setup_tc);
#endif /* CONFIG_NET_MEDIATEK_SOC_WED */
108 changes: 108 additions & 0 deletions drivers/net/wireless/mediatek/mt76/mmio.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*/

#include "mt76.h"
#include "dma.h"
#include "trace.h"

static u32 mt76_mmio_rr(struct mt76_dev *dev, u32 offset)
Expand Down Expand Up @@ -84,6 +85,113 @@ void mt76_set_irq_mask(struct mt76_dev *dev, u32 addr,
}
EXPORT_SYMBOL_GPL(mt76_set_irq_mask);

#ifdef CONFIG_NET_MEDIATEK_SOC_WED
void mt76_mmio_wed_release_rx_buf(struct mtk_wed_device *wed)
{
struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed);
int i;

for (i = 0; i < dev->rx_token_size; i++) {
struct mt76_txwi_cache *t;

t = mt76_rx_token_release(dev, i);
if (!t || !t->ptr)
continue;

mt76_put_page_pool_buf(t->ptr, false);
t->ptr = NULL;

mt76_put_rxwi(dev, t);
}

mt76_free_pending_rxwi(dev);
}
EXPORT_SYMBOL_GPL(mt76_mmio_wed_release_rx_buf);

u32 mt76_mmio_wed_init_rx_buf(struct mtk_wed_device *wed, int size)
{
struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed);
struct mtk_wed_bm_desc *desc = wed->rx_buf_ring.desc;
struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN];
int i, len = SKB_WITH_OVERHEAD(q->buf_size);
struct mt76_txwi_cache *t = NULL;

for (i = 0; i < size; i++) {
enum dma_data_direction dir;
dma_addr_t addr;
u32 offset;
int token;
void *buf;

t = mt76_get_rxwi(dev);
if (!t)
goto unmap;

buf = mt76_get_page_pool_buf(q, &offset, q->buf_size);
if (!buf)
goto unmap;

addr = page_pool_get_dma_addr(virt_to_head_page(buf)) + offset;
dir = page_pool_get_dma_dir(q->page_pool);
dma_sync_single_for_device(dev->dma_dev, addr, len, dir);

desc->buf0 = cpu_to_le32(addr);
token = mt76_rx_token_consume(dev, buf, t, addr);
if (token < 0) {
mt76_put_page_pool_buf(buf, false);
goto unmap;
}

token = FIELD_PREP(MT_DMA_CTL_TOKEN, token);
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
token |= FIELD_PREP(MT_DMA_CTL_SDP0_H, addr >> 32);
#endif
desc->token |= cpu_to_le32(token);
desc++;
}

return 0;

unmap:
if (t)
mt76_put_rxwi(dev, t);
mt76_mmio_wed_release_rx_buf(wed);

return -ENOMEM;
}
EXPORT_SYMBOL_GPL(mt76_mmio_wed_init_rx_buf);

int mt76_mmio_wed_offload_enable(struct mtk_wed_device *wed)
{
struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed);

spin_lock_bh(&dev->token_lock);
dev->token_size = wed->wlan.token_start;
spin_unlock_bh(&dev->token_lock);

return !wait_event_timeout(dev->tx_wait, !dev->wed_token_count, HZ);
}
EXPORT_SYMBOL_GPL(mt76_mmio_wed_offload_enable);

void mt76_mmio_wed_offload_disable(struct mtk_wed_device *wed)
{
struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed);

spin_lock_bh(&dev->token_lock);
dev->token_size = dev->drv->token_size;
spin_unlock_bh(&dev->token_lock);
}
EXPORT_SYMBOL_GPL(mt76_mmio_wed_offload_disable);

void mt76_mmio_wed_reset_complete(struct mtk_wed_device *wed)
{
struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed);

complete(&dev->mmio.wed_reset_complete);
}
EXPORT_SYMBOL_GPL(mt76_mmio_wed_reset_complete);
#endif /*CONFIG_NET_MEDIATEK_SOC_WED */

void mt76_mmio_init(struct mt76_dev *dev, void __iomem *regs)
{
static const struct mt76_bus_ops mt76_mmio_ops = {
Expand Down
Loading

0 comments on commit 3798722

Please sign in to comment.