mirror of
https://github.com/torvalds/linux.git
synced 2026-05-25 07:33:19 +02:00
wifi: mt76: mt7996: Enable HW RRO for MT7992 chipset
This is a preliminary patch to enable WED support for MT7992 Kite chipset supported by MT7996 driver. Co-developed-by: Sujuan Chen <sujuan.chen@mediatek.com> Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com> Co-developed-by: Benjamin Lin <benjamin-jw.lin@mediatek.com> Signed-off-by: Benjamin Lin <benjamin-jw.lin@mediatek.com> Signed-off-by: Rex Lu <rex.lu@mediatek.com> Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> Link: https://patch.msgid.link/20250909-mt7996-rro-rework-v5-6-7d66f6eb7795@kernel.org Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
parent
3bc2f02f5c
commit
eedb427eb2
|
|
@ -605,19 +605,21 @@ void mt7996_mac_init(struct mt7996_dev *dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* rro module init */
|
/* rro module init */
|
||||||
if (is_mt7996(&dev->mt76))
|
if (dev->hif2)
|
||||||
mt7996_mcu_set_rro(dev, UNI_RRO_SET_PLATFORM_TYPE, 2);
|
|
||||||
else
|
|
||||||
mt7996_mcu_set_rro(dev, UNI_RRO_SET_PLATFORM_TYPE,
|
mt7996_mcu_set_rro(dev, UNI_RRO_SET_PLATFORM_TYPE,
|
||||||
dev->hif2 ? 7 : 0);
|
is_mt7996(&dev->mt76) ? 2 : 7);
|
||||||
|
else
|
||||||
|
mt7996_mcu_set_rro(dev, UNI_RRO_SET_PLATFORM_TYPE, 0);
|
||||||
|
|
||||||
if (dev->has_rro) {
|
if (dev->has_rro) {
|
||||||
u16 timeout;
|
u16 timeout;
|
||||||
|
|
||||||
timeout = mt76_rr(dev, MT_HW_REV) == MT_HW_REV1 ? 512 : 128;
|
timeout = mt76_rr(dev, MT_HW_REV) == MT_HW_REV1 ? 512 : 128;
|
||||||
mt7996_mcu_set_rro(dev, UNI_RRO_SET_FLUSH_TIMEOUT, timeout);
|
mt7996_mcu_set_rro(dev, UNI_RRO_SET_FLUSH_TIMEOUT, timeout);
|
||||||
mt7996_mcu_set_rro(dev, UNI_RRO_SET_BYPASS_MODE, 1);
|
mt7996_mcu_set_rro(dev, UNI_RRO_SET_BYPASS_MODE,
|
||||||
mt7996_mcu_set_rro(dev, UNI_RRO_SET_TXFREE_PATH, 0);
|
is_mt7996(&dev->mt76) ? 1 : 2);
|
||||||
|
mt7996_mcu_set_rro(dev, UNI_RRO_SET_TXFREE_PATH,
|
||||||
|
!is_mt7996(&dev->mt76));
|
||||||
} else {
|
} else {
|
||||||
mt7996_mcu_set_rro(dev, UNI_RRO_SET_BYPASS_MODE, 3);
|
mt7996_mcu_set_rro(dev, UNI_RRO_SET_BYPASS_MODE, 3);
|
||||||
mt7996_mcu_set_rro(dev, UNI_RRO_SET_TXFREE_PATH, 1);
|
mt7996_mcu_set_rro(dev, UNI_RRO_SET_TXFREE_PATH, 1);
|
||||||
|
|
@ -754,11 +756,95 @@ void mt7996_wfsys_reset(struct mt7996_dev *dev)
|
||||||
msleep(20);
|
msleep(20);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
|
||||||
|
static void mt7996_rro_hw_init(struct mt7996_dev *dev)
|
||||||
|
{
|
||||||
|
struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
|
||||||
|
u32 reg = MT_RRO_ADDR_ELEM_SEG_ADDR0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!dev->has_rro)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (is_mt7992(&dev->mt76)) {
|
||||||
|
/* Set emul 3.0 function */
|
||||||
|
mt76_wr(dev, MT_RRO_3_0_EMU_CONF,
|
||||||
|
MT_RRO_3_0_EMU_CONF_EN_MASK);
|
||||||
|
mt76_wr(dev, MT_RRO_ADDR_ARRAY_BASE0,
|
||||||
|
dev->wed_rro.addr_elem[0].phy_addr);
|
||||||
|
} else {
|
||||||
|
/* TODO: remove line after WM has set */
|
||||||
|
mt76_clear(dev, WF_RRO_AXI_MST_CFG,
|
||||||
|
WF_RRO_AXI_MST_CFG_DIDX_OK);
|
||||||
|
/* setup BA bitmap cache address */
|
||||||
|
mt76_wr(dev, MT_RRO_BA_BITMAP_BASE0,
|
||||||
|
dev->wed_rro.ba_bitmap[0].phy_addr);
|
||||||
|
mt76_wr(dev, MT_RRO_BA_BITMAP_BASE1, 0);
|
||||||
|
mt76_wr(dev, MT_RRO_BA_BITMAP_BASE_EXT0,
|
||||||
|
dev->wed_rro.ba_bitmap[1].phy_addr);
|
||||||
|
mt76_wr(dev, MT_RRO_BA_BITMAP_BASE_EXT1, 0);
|
||||||
|
|
||||||
|
/* Setup Address element address */
|
||||||
|
for (i = 0; i < ARRAY_SIZE(dev->wed_rro.addr_elem); i++) {
|
||||||
|
mt76_wr(dev, reg,
|
||||||
|
dev->wed_rro.addr_elem[i].phy_addr >> 4);
|
||||||
|
reg += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Setup Address element address - separate address
|
||||||
|
* segment mode
|
||||||
|
*/
|
||||||
|
mt76_wr(dev, MT_RRO_ADDR_ARRAY_BASE1,
|
||||||
|
MT_RRO_ADDR_ARRAY_ELEM_ADDR_SEG_MODE);
|
||||||
|
}
|
||||||
|
wed->wlan.ind_cmd.win_size = ffs(MT7996_RRO_WINDOW_MAX_LEN) - 6;
|
||||||
|
if (is_mt7996(&dev->mt76))
|
||||||
|
wed->wlan.ind_cmd.particular_sid = MT7996_RRO_MAX_SESSION;
|
||||||
|
else
|
||||||
|
wed->wlan.ind_cmd.particular_sid = 1;
|
||||||
|
wed->wlan.ind_cmd.particular_se_phys = dev->wed_rro.session.phy_addr;
|
||||||
|
wed->wlan.ind_cmd.se_group_nums = MT7996_RRO_ADDR_ELEM_LEN;
|
||||||
|
wed->wlan.ind_cmd.ack_sn_addr = MT_RRO_ACK_SN_CTRL;
|
||||||
|
|
||||||
|
mt76_wr(dev, MT_RRO_IND_CMD_SIGNATURE_BASE0, 0x15010e00);
|
||||||
|
mt76_set(dev, MT_RRO_IND_CMD_SIGNATURE_BASE1,
|
||||||
|
MT_RRO_IND_CMD_SIGNATURE_BASE1_EN);
|
||||||
|
|
||||||
|
/* particular session configure */
|
||||||
|
/* use max session idx + 1 as particular session id */
|
||||||
|
mt76_wr(dev, MT_RRO_PARTICULAR_CFG0, dev->wed_rro.session.phy_addr);
|
||||||
|
|
||||||
|
if (is_mt7992(&dev->mt76)) {
|
||||||
|
reg = MT_RRO_MSDU_PG_SEG_ADDR0;
|
||||||
|
|
||||||
|
mt76_set(dev, MT_RRO_3_1_GLOBAL_CONFIG,
|
||||||
|
MT_RRO_3_1_GLOBAL_CONFIG_INTERLEAVE_EN);
|
||||||
|
|
||||||
|
/* setup Msdu page address */
|
||||||
|
for (i = 0; i < ARRAY_SIZE(dev->wed_rro.msdu_pg); i++) {
|
||||||
|
mt76_wr(dev, reg,
|
||||||
|
dev->wed_rro.msdu_pg[i].phy_addr >> 4);
|
||||||
|
reg += 4;
|
||||||
|
}
|
||||||
|
mt76_wr(dev, MT_RRO_PARTICULAR_CFG1,
|
||||||
|
MT_RRO_PARTICULAR_CONFG_EN |
|
||||||
|
FIELD_PREP(MT_RRO_PARTICULAR_SID, 1));
|
||||||
|
} else {
|
||||||
|
mt76_wr(dev, MT_RRO_PARTICULAR_CFG1,
|
||||||
|
MT_RRO_PARTICULAR_CONFG_EN |
|
||||||
|
FIELD_PREP(MT_RRO_PARTICULAR_SID,
|
||||||
|
MT7996_RRO_MAX_SESSION));
|
||||||
|
}
|
||||||
|
/* interrupt enable */
|
||||||
|
mt76_wr(dev, MT_RRO_HOST_INT_ENA,
|
||||||
|
MT_RRO_HOST_INT_ENA_HOST_RRO_DONE_ENA);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int mt7996_wed_rro_init(struct mt7996_dev *dev)
|
static int mt7996_wed_rro_init(struct mt7996_dev *dev)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
|
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
|
||||||
struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
|
struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
|
||||||
u32 reg = MT_RRO_ADDR_ELEM_SEG_ADDR0;
|
|
||||||
struct mt7996_wed_rro_addr *addr;
|
struct mt7996_wed_rro_addr *addr;
|
||||||
void *ptr;
|
void *ptr;
|
||||||
int i;
|
int i;
|
||||||
|
|
@ -804,6 +890,20 @@ static int mt7996_wed_rro_init(struct mt7996_dev *dev)
|
||||||
dev->wed_rro.addr_elem[i].phy_addr;
|
dev->wed_rro.addr_elem[i].phy_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(dev->wed_rro.msdu_pg); i++) {
|
||||||
|
ptr = dmam_alloc_coherent(dev->mt76.dma_dev,
|
||||||
|
MT7996_RRO_MSDU_PG_SIZE_PER_CR,
|
||||||
|
&dev->wed_rro.msdu_pg[i].phy_addr,
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!ptr)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
dev->wed_rro.msdu_pg[i].ptr = ptr;
|
||||||
|
|
||||||
|
memset(dev->wed_rro.msdu_pg[i].ptr, 0,
|
||||||
|
MT7996_RRO_MSDU_PG_SIZE_PER_CR);
|
||||||
|
}
|
||||||
|
|
||||||
ptr = dmam_alloc_coherent(dev->mt76.dma_dev,
|
ptr = dmam_alloc_coherent(dev->mt76.dma_dev,
|
||||||
MT7996_RRO_WINDOW_MAX_LEN * sizeof(*addr),
|
MT7996_RRO_WINDOW_MAX_LEN * sizeof(*addr),
|
||||||
&dev->wed_rro.session.phy_addr,
|
&dev->wed_rro.session.phy_addr,
|
||||||
|
|
@ -818,50 +918,8 @@ static int mt7996_wed_rro_init(struct mt7996_dev *dev)
|
||||||
addr++;
|
addr++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* rro hw init */
|
mt7996_rro_hw_init(dev);
|
||||||
/* TODO: remove line after WM has set */
|
|
||||||
mt76_clear(dev, WF_RRO_AXI_MST_CFG, WF_RRO_AXI_MST_CFG_DIDX_OK);
|
|
||||||
|
|
||||||
/* setup BA bitmap cache address */
|
|
||||||
mt76_wr(dev, MT_RRO_BA_BITMAP_BASE0,
|
|
||||||
dev->wed_rro.ba_bitmap[0].phy_addr);
|
|
||||||
mt76_wr(dev, MT_RRO_BA_BITMAP_BASE1, 0);
|
|
||||||
mt76_wr(dev, MT_RRO_BA_BITMAP_BASE_EXT0,
|
|
||||||
dev->wed_rro.ba_bitmap[1].phy_addr);
|
|
||||||
mt76_wr(dev, MT_RRO_BA_BITMAP_BASE_EXT1, 0);
|
|
||||||
|
|
||||||
/* setup Address element address */
|
|
||||||
for (i = 0; i < ARRAY_SIZE(dev->wed_rro.addr_elem); i++) {
|
|
||||||
mt76_wr(dev, reg, dev->wed_rro.addr_elem[i].phy_addr >> 4);
|
|
||||||
reg += 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* setup Address element address - separate address segment mode */
|
|
||||||
mt76_wr(dev, MT_RRO_ADDR_ARRAY_BASE1,
|
|
||||||
MT_RRO_ADDR_ARRAY_ELEM_ADDR_SEG_MODE);
|
|
||||||
|
|
||||||
wed->wlan.ind_cmd.win_size = ffs(MT7996_RRO_WINDOW_MAX_LEN) - 6;
|
|
||||||
wed->wlan.ind_cmd.particular_sid = MT7996_RRO_MAX_SESSION;
|
|
||||||
wed->wlan.ind_cmd.particular_se_phys = dev->wed_rro.session.phy_addr;
|
|
||||||
wed->wlan.ind_cmd.se_group_nums = MT7996_RRO_ADDR_ELEM_LEN;
|
|
||||||
wed->wlan.ind_cmd.ack_sn_addr = MT_RRO_ACK_SN_CTRL;
|
|
||||||
|
|
||||||
mt76_wr(dev, MT_RRO_IND_CMD_SIGNATURE_BASE0, 0x15010e00);
|
|
||||||
mt76_set(dev, MT_RRO_IND_CMD_SIGNATURE_BASE1,
|
|
||||||
MT_RRO_IND_CMD_SIGNATURE_BASE1_EN);
|
|
||||||
|
|
||||||
/* particular session configure */
|
|
||||||
/* use max session idx + 1 as particular session id */
|
|
||||||
mt76_wr(dev, MT_RRO_PARTICULAR_CFG0, dev->wed_rro.session.phy_addr);
|
|
||||||
mt76_wr(dev, MT_RRO_PARTICULAR_CFG1,
|
|
||||||
MT_RRO_PARTICULAR_CONFG_EN |
|
|
||||||
FIELD_PREP(MT_RRO_PARTICULAR_SID, MT7996_RRO_MAX_SESSION));
|
|
||||||
|
|
||||||
/* interrupt enable */
|
|
||||||
mt76_wr(dev, MT_RRO_HOST_INT_ENA,
|
|
||||||
MT_RRO_HOST_INT_ENA_HOST_RRO_DONE_ENA);
|
|
||||||
|
|
||||||
/* rro ind cmd queue init */
|
|
||||||
return mt7996_dma_rro_init(dev);
|
return mt7996_dma_rro_init(dev);
|
||||||
#else
|
#else
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -900,6 +958,16 @@ static void mt7996_wed_rro_free(struct mt7996_dev *dev)
|
||||||
dev->wed_rro.addr_elem[i].phy_addr);
|
dev->wed_rro.addr_elem[i].phy_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(dev->wed_rro.msdu_pg); i++) {
|
||||||
|
if (!dev->wed_rro.msdu_pg[i].ptr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
dmam_free_coherent(dev->mt76.dma_dev,
|
||||||
|
MT7996_RRO_MSDU_PG_SIZE_PER_CR,
|
||||||
|
dev->wed_rro.msdu_pg[i].ptr,
|
||||||
|
dev->wed_rro.msdu_pg[i].phy_addr);
|
||||||
|
}
|
||||||
|
|
||||||
if (!dev->wed_rro.session.ptr)
|
if (!dev->wed_rro.session.ptr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -112,6 +112,7 @@
|
||||||
#define MT7996_CRIT_TEMP 110
|
#define MT7996_CRIT_TEMP 110
|
||||||
#define MT7996_MAX_TEMP 120
|
#define MT7996_MAX_TEMP 120
|
||||||
|
|
||||||
|
#define MT7996_RRO_MSDU_PG_HASH_SIZE 127
|
||||||
#define MT7996_RRO_MAX_SESSION 1024
|
#define MT7996_RRO_MAX_SESSION 1024
|
||||||
#define MT7996_RRO_WINDOW_MAX_LEN 1024
|
#define MT7996_RRO_WINDOW_MAX_LEN 1024
|
||||||
#define MT7996_RRO_ADDR_ELEM_LEN 128
|
#define MT7996_RRO_ADDR_ELEM_LEN 128
|
||||||
|
|
@ -128,6 +129,10 @@
|
||||||
#define MT7996_RX_MSDU_PAGE_SIZE (128 + \
|
#define MT7996_RX_MSDU_PAGE_SIZE (128 + \
|
||||||
SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
|
SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
|
||||||
|
|
||||||
|
/* RRO 3.1 */
|
||||||
|
#define MT7996_RRO_MSDU_PG_CR_CNT 8
|
||||||
|
#define MT7996_RRO_MSDU_PG_SIZE_PER_CR 0x10000
|
||||||
|
|
||||||
struct mt7996_vif;
|
struct mt7996_vif;
|
||||||
struct mt7996_sta;
|
struct mt7996_sta;
|
||||||
struct mt7996_dfs_pulse;
|
struct mt7996_dfs_pulse;
|
||||||
|
|
@ -400,6 +405,10 @@ struct mt7996_dev {
|
||||||
void *ptr;
|
void *ptr;
|
||||||
dma_addr_t phy_addr;
|
dma_addr_t phy_addr;
|
||||||
} session;
|
} session;
|
||||||
|
struct {
|
||||||
|
void *ptr;
|
||||||
|
dma_addr_t phy_addr;
|
||||||
|
} msdu_pg[MT7996_RRO_MSDU_PG_CR_CNT];
|
||||||
|
|
||||||
struct work_struct work;
|
struct work_struct work;
|
||||||
struct list_head poll_list;
|
struct list_head poll_list;
|
||||||
|
|
|
||||||
|
|
@ -88,6 +88,8 @@ enum offs_rev {
|
||||||
#define MT_RRO_BA_BITMAP_BASE1 MT_RRO_TOP(0xC)
|
#define MT_RRO_BA_BITMAP_BASE1 MT_RRO_TOP(0xC)
|
||||||
#define WF_RRO_AXI_MST_CFG MT_RRO_TOP(0xB8)
|
#define WF_RRO_AXI_MST_CFG MT_RRO_TOP(0xB8)
|
||||||
#define WF_RRO_AXI_MST_CFG_DIDX_OK BIT(12)
|
#define WF_RRO_AXI_MST_CFG_DIDX_OK BIT(12)
|
||||||
|
|
||||||
|
#define MT_RRO_ADDR_ARRAY_BASE0 MT_RRO_TOP(0x30)
|
||||||
#define MT_RRO_ADDR_ARRAY_BASE1 MT_RRO_TOP(0x34)
|
#define MT_RRO_ADDR_ARRAY_BASE1 MT_RRO_TOP(0x34)
|
||||||
#define MT_RRO_ADDR_ARRAY_ELEM_ADDR_SEG_MODE BIT(31)
|
#define MT_RRO_ADDR_ARRAY_ELEM_ADDR_SEG_MODE BIT(31)
|
||||||
|
|
||||||
|
|
@ -108,6 +110,14 @@ enum offs_rev {
|
||||||
|
|
||||||
#define MT_RRO_ADDR_ELEM_SEG_ADDR0 MT_RRO_TOP(0x400)
|
#define MT_RRO_ADDR_ELEM_SEG_ADDR0 MT_RRO_TOP(0x400)
|
||||||
|
|
||||||
|
#define MT_RRO_3_0_EMU_CONF MT_RRO_TOP(0x600)
|
||||||
|
#define MT_RRO_3_0_EMU_CONF_EN_MASK BIT(11)
|
||||||
|
|
||||||
|
#define MT_RRO_3_1_GLOBAL_CONFIG MT_RRO_TOP(0x604)
|
||||||
|
#define MT_RRO_3_1_GLOBAL_CONFIG_INTERLEAVE_EN BIT(0)
|
||||||
|
|
||||||
|
#define MT_RRO_MSDU_PG_SEG_ADDR0 MT_RRO_TOP(0x620)
|
||||||
|
|
||||||
#define MT_RRO_ACK_SN_CTRL MT_RRO_TOP(0x50)
|
#define MT_RRO_ACK_SN_CTRL MT_RRO_TOP(0x50)
|
||||||
#define MT_RRO_ACK_SN_CTRL_SN_MASK GENMASK(27, 16)
|
#define MT_RRO_ACK_SN_CTRL_SN_MASK GENMASK(27, 16)
|
||||||
#define MT_RRO_ACK_SN_CTRL_SESSION_MASK GENMASK(11, 0)
|
#define MT_RRO_ACK_SN_CTRL_SESSION_MASK GENMASK(11, 0)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user