Skip to content

Commit b230812

Browse files
Sujuan ChenPaolo Abeni
authored andcommitted
net: ethernet: mtk_wed: introduce partial AMSDU offload support for MT7988
Introduce partial AMSDU offload support for MT7988 SoC in order to merge in hw packets belonging to the same AMSDU before passing them to the WLAN nic. Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com> Signed-off-by: Paolo Abeni <pabeni@redhat.com>
1 parent 96ddb4d commit b230812

File tree

8 files changed

+248
-28
lines changed

8 files changed

+248
-28
lines changed

drivers/net/ethernet/mediatek/mtk_ppe.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -425,7 +425,8 @@ int mtk_foe_entry_set_pppoe(struct mtk_eth *eth, struct mtk_foe_entry *entry,
425425
}
426426

427427
int mtk_foe_entry_set_wdma(struct mtk_eth *eth, struct mtk_foe_entry *entry,
428-
int wdma_idx, int txq, int bss, int wcid)
428+
int wdma_idx, int txq, int bss, int wcid,
429+
bool amsdu_en)
429430
{
430431
struct mtk_foe_mac_info *l2 = mtk_foe_entry_l2(eth, entry);
431432
u32 *ib2 = mtk_foe_entry_ib2(eth, entry);
@@ -437,6 +438,7 @@ int mtk_foe_entry_set_wdma(struct mtk_eth *eth, struct mtk_foe_entry *entry,
437438
MTK_FOE_IB2_WDMA_WINFO_V2;
438439
l2->w3info = FIELD_PREP(MTK_FOE_WINFO_WCID_V3, wcid) |
439440
FIELD_PREP(MTK_FOE_WINFO_BSS_V3, bss);
441+
l2->amsdu = FIELD_PREP(MTK_FOE_WINFO_AMSDU_EN, amsdu_en);
440442
break;
441443
case 2:
442444
*ib2 &= ~MTK_FOE_IB2_PORT_MG_V2;

drivers/net/ethernet/mediatek/mtk_ppe.h

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -88,13 +88,13 @@ enum {
8888
#define MTK_FOE_WINFO_BSS_V3 GENMASK(23, 16)
8989
#define MTK_FOE_WINFO_WCID_V3 GENMASK(15, 0)
9090

91-
#define MTK_FOE_WINFO_PAO_USR_INFO GENMASK(15, 0)
92-
#define MTK_FOE_WINFO_PAO_TID GENMASK(19, 16)
93-
#define MTK_FOE_WINFO_PAO_IS_FIXEDRATE BIT(20)
94-
#define MTK_FOE_WINFO_PAO_IS_PRIOR BIT(21)
95-
#define MTK_FOE_WINFO_PAO_IS_SP BIT(22)
96-
#define MTK_FOE_WINFO_PAO_HF BIT(23)
97-
#define MTK_FOE_WINFO_PAO_AMSDU_EN BIT(24)
91+
#define MTK_FOE_WINFO_AMSDU_USR_INFO GENMASK(15, 0)
92+
#define MTK_FOE_WINFO_AMSDU_TID GENMASK(19, 16)
93+
#define MTK_FOE_WINFO_AMSDU_IS_FIXEDRATE BIT(20)
94+
#define MTK_FOE_WINFO_AMSDU_IS_PRIOR BIT(21)
95+
#define MTK_FOE_WINFO_AMSDU_IS_SP BIT(22)
96+
#define MTK_FOE_WINFO_AMSDU_HF BIT(23)
97+
#define MTK_FOE_WINFO_AMSDU_EN BIT(24)
9898

9999
enum {
100100
MTK_FOE_STATE_INVALID,
@@ -123,7 +123,7 @@ struct mtk_foe_mac_info {
123123

124124
/* netsys_v3 */
125125
u32 w3info;
126-
u32 wpao;
126+
u32 amsdu;
127127
};
128128

129129
/* software-only entry type */
@@ -392,7 +392,8 @@ int mtk_foe_entry_set_vlan(struct mtk_eth *eth, struct mtk_foe_entry *entry,
392392
int mtk_foe_entry_set_pppoe(struct mtk_eth *eth, struct mtk_foe_entry *entry,
393393
int sid);
394394
int mtk_foe_entry_set_wdma(struct mtk_eth *eth, struct mtk_foe_entry *entry,
395-
int wdma_idx, int txq, int bss, int wcid);
395+
int wdma_idx, int txq, int bss, int wcid,
396+
bool amsdu_en);
396397
int mtk_foe_entry_set_queue(struct mtk_eth *eth, struct mtk_foe_entry *entry,
397398
unsigned int queue);
398399
int mtk_foe_entry_commit(struct mtk_ppe *ppe, struct mtk_flow_entry *entry);

drivers/net/ethernet/mediatek/mtk_ppe_offload.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ mtk_flow_get_wdma_info(struct net_device *dev, const u8 *addr, struct mtk_wdma_i
111111
info->queue = path->mtk_wdma.queue;
112112
info->bss = path->mtk_wdma.bss;
113113
info->wcid = path->mtk_wdma.wcid;
114+
info->amsdu = path->mtk_wdma.amsdu;
114115

115116
return 0;
116117
}
@@ -192,7 +193,7 @@ mtk_flow_set_output_device(struct mtk_eth *eth, struct mtk_foe_entry *foe,
192193

193194
if (mtk_flow_get_wdma_info(dev, dest_mac, &info) == 0) {
194195
mtk_foe_entry_set_wdma(eth, foe, info.wdma_idx, info.queue,
195-
info.bss, info.wcid);
196+
info.bss, info.wcid, info.amsdu);
196197
if (mtk_is_netsys_v2_or_greater(eth)) {
197198
switch (info.wdma_idx) {
198199
case 0:

drivers/net/ethernet/mediatek/mtk_wed.c

Lines changed: 137 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
#define MTK_WED_RX_PAGE_BUF_PER_PAGE (PAGE_SIZE / 128)
3131
#define MTK_WED_RX_RING_SIZE 1536
3232
#define MTK_WED_RX_PG_BM_CNT 8192
33+
#define MTK_WED_AMSDU_BUF_SIZE (PAGE_SIZE << 4)
34+
#define MTK_WED_AMSDU_NPAGES 32
3335

3436
#define MTK_WED_TX_RING_SIZE 2048
3537
#define MTK_WED_WDMA_RING_SIZE 1024
@@ -173,6 +175,23 @@ mtk_wdma_rx_reset(struct mtk_wed_device *dev)
173175
return ret;
174176
}
175177

178+
static u32
179+
mtk_wed_check_busy(struct mtk_wed_device *dev, u32 reg, u32 mask)
180+
{
181+
return !!(wed_r32(dev, reg) & mask);
182+
}
183+
184+
static int
185+
mtk_wed_poll_busy(struct mtk_wed_device *dev, u32 reg, u32 mask)
186+
{
187+
int sleep = 15000;
188+
int timeout = 100 * sleep;
189+
u32 val;
190+
191+
return read_poll_timeout(mtk_wed_check_busy, val, !val, sleep,
192+
timeout, false, dev, reg, mask);
193+
}
194+
176195
static void
177196
mtk_wdma_tx_reset(struct mtk_wed_device *dev)
178197
{
@@ -335,6 +354,118 @@ mtk_wed_assign(struct mtk_wed_device *dev)
335354
return hw;
336355
}
337356

357+
static int
358+
mtk_wed_amsdu_buffer_alloc(struct mtk_wed_device *dev)
359+
{
360+
struct mtk_wed_hw *hw = dev->hw;
361+
struct mtk_wed_amsdu *wed_amsdu;
362+
int i;
363+
364+
if (!mtk_wed_is_v3_or_greater(hw))
365+
return 0;
366+
367+
wed_amsdu = devm_kcalloc(hw->dev, MTK_WED_AMSDU_NPAGES,
368+
sizeof(*wed_amsdu), GFP_KERNEL);
369+
if (!wed_amsdu)
370+
return -ENOMEM;
371+
372+
for (i = 0; i < MTK_WED_AMSDU_NPAGES; i++) {
373+
void *ptr;
374+
375+
/* each segment is 64K */
376+
ptr = (void *)__get_free_pages(GFP_KERNEL | __GFP_NOWARN |
377+
__GFP_ZERO | __GFP_COMP |
378+
GFP_DMA32,
379+
get_order(MTK_WED_AMSDU_BUF_SIZE));
380+
if (!ptr)
381+
goto error;
382+
383+
wed_amsdu[i].txd = ptr;
384+
wed_amsdu[i].txd_phy = dma_map_single(hw->dev, ptr,
385+
MTK_WED_AMSDU_BUF_SIZE,
386+
DMA_TO_DEVICE);
387+
if (dma_mapping_error(hw->dev, wed_amsdu[i].txd_phy))
388+
goto error;
389+
}
390+
dev->hw->wed_amsdu = wed_amsdu;
391+
392+
return 0;
393+
394+
error:
395+
for (i--; i >= 0; i--)
396+
dma_unmap_single(hw->dev, wed_amsdu[i].txd_phy,
397+
MTK_WED_AMSDU_BUF_SIZE, DMA_TO_DEVICE);
398+
return -ENOMEM;
399+
}
400+
401+
static void
402+
mtk_wed_amsdu_free_buffer(struct mtk_wed_device *dev)
403+
{
404+
struct mtk_wed_amsdu *wed_amsdu = dev->hw->wed_amsdu;
405+
int i;
406+
407+
if (!wed_amsdu)
408+
return;
409+
410+
for (i = 0; i < MTK_WED_AMSDU_NPAGES; i++) {
411+
dma_unmap_single(dev->hw->dev, wed_amsdu[i].txd_phy,
412+
MTK_WED_AMSDU_BUF_SIZE, DMA_TO_DEVICE);
413+
free_pages((unsigned long)wed_amsdu[i].txd,
414+
get_order(MTK_WED_AMSDU_BUF_SIZE));
415+
}
416+
}
417+
418+
static int
419+
mtk_wed_amsdu_init(struct mtk_wed_device *dev)
420+
{
421+
struct mtk_wed_amsdu *wed_amsdu = dev->hw->wed_amsdu;
422+
int i, ret;
423+
424+
if (!wed_amsdu)
425+
return 0;
426+
427+
for (i = 0; i < MTK_WED_AMSDU_NPAGES; i++)
428+
wed_w32(dev, MTK_WED_AMSDU_HIFTXD_BASE_L(i),
429+
wed_amsdu[i].txd_phy);
430+
431+
/* init all sta parameter */
432+
wed_w32(dev, MTK_WED_AMSDU_STA_INFO_INIT, MTK_WED_AMSDU_STA_RMVL |
433+
MTK_WED_AMSDU_STA_WTBL_HDRT_MODE |
434+
FIELD_PREP(MTK_WED_AMSDU_STA_MAX_AMSDU_LEN,
435+
dev->wlan.amsdu_max_len >> 8) |
436+
FIELD_PREP(MTK_WED_AMSDU_STA_MAX_AMSDU_NUM,
437+
dev->wlan.amsdu_max_subframes));
438+
439+
wed_w32(dev, MTK_WED_AMSDU_STA_INFO, MTK_WED_AMSDU_STA_INFO_DO_INIT);
440+
441+
ret = mtk_wed_poll_busy(dev, MTK_WED_AMSDU_STA_INFO,
442+
MTK_WED_AMSDU_STA_INFO_DO_INIT);
443+
if (ret) {
444+
dev_err(dev->hw->dev, "amsdu initialization failed\n");
445+
return ret;
446+
}
447+
448+
/* init partial amsdu offload txd src */
449+
wed_set(dev, MTK_WED_AMSDU_HIFTXD_CFG,
450+
FIELD_PREP(MTK_WED_AMSDU_HIFTXD_SRC, dev->hw->index));
451+
452+
/* init qmem */
453+
wed_set(dev, MTK_WED_AMSDU_PSE, MTK_WED_AMSDU_PSE_RESET);
454+
ret = mtk_wed_poll_busy(dev, MTK_WED_MON_AMSDU_QMEM_STS1, BIT(29));
455+
if (ret) {
456+
pr_info("%s: amsdu qmem initialization failed\n", __func__);
457+
return ret;
458+
}
459+
460+
/* eagle E1 PCIE1 tx ring 22 flow control issue */
461+
if (dev->wlan.id == 0x7991)
462+
wed_clr(dev, MTK_WED_AMSDU_FIFO, MTK_WED_AMSDU_IS_PRIOR0_RING);
463+
464+
wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_TX_AMSDU_EN);
465+
466+
return 0;
467+
}
468+
338469
static int
339470
mtk_wed_tx_buffer_alloc(struct mtk_wed_device *dev)
340471
{
@@ -709,6 +840,7 @@ __mtk_wed_detach(struct mtk_wed_device *dev)
709840

710841
mtk_wdma_rx_reset(dev);
711842
mtk_wed_reset(dev, MTK_WED_RESET_WED);
843+
mtk_wed_amsdu_free_buffer(dev);
712844
mtk_wed_free_tx_buffer(dev);
713845
mtk_wed_free_tx_rings(dev);
714846

@@ -1129,23 +1261,6 @@ mtk_wed_ring_reset(struct mtk_wed_ring *ring, int size, bool tx)
11291261
}
11301262
}
11311263

1132-
static u32
1133-
mtk_wed_check_busy(struct mtk_wed_device *dev, u32 reg, u32 mask)
1134-
{
1135-
return !!(wed_r32(dev, reg) & mask);
1136-
}
1137-
1138-
static int
1139-
mtk_wed_poll_busy(struct mtk_wed_device *dev, u32 reg, u32 mask)
1140-
{
1141-
int sleep = 15000;
1142-
int timeout = 100 * sleep;
1143-
u32 val;
1144-
1145-
return read_poll_timeout(mtk_wed_check_busy, val, !val, sleep,
1146-
timeout, false, dev, reg, mask);
1147-
}
1148-
11491264
static int
11501265
mtk_wed_rx_reset(struct mtk_wed_device *dev)
11511266
{
@@ -1692,6 +1807,7 @@ mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask)
16921807
}
16931808

16941809
mtk_wed_set_512_support(dev, dev->wlan.wcid_512);
1810+
mtk_wed_amsdu_init(dev);
16951811

16961812
mtk_wed_dma_enable(dev);
16971813
dev->running = true;
@@ -1748,6 +1864,10 @@ mtk_wed_attach(struct mtk_wed_device *dev)
17481864
if (ret)
17491865
goto out;
17501866

1867+
ret = mtk_wed_amsdu_buffer_alloc(dev);
1868+
if (ret)
1869+
goto out;
1870+
17511871
if (mtk_wed_get_rx_capa(dev)) {
17521872
ret = mtk_wed_rro_alloc(dev);
17531873
if (ret)

drivers/net/ethernet/mediatek/mtk_wed.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ struct mtk_wed_soc_data {
2525
u32 wdma_desc_size;
2626
};
2727

28+
struct mtk_wed_amsdu {
29+
void *txd;
30+
dma_addr_t txd_phy;
31+
};
32+
2833
struct mtk_wed_hw {
2934
const struct mtk_wed_soc_data *soc;
3035
struct device_node *node;
@@ -38,6 +43,7 @@ struct mtk_wed_hw {
3843
struct dentry *debugfs_dir;
3944
struct mtk_wed_device *wed_dev;
4045
struct mtk_wed_wo *wed_wo;
46+
struct mtk_wed_amsdu *wed_amsdu;
4147
u32 pcie_base;
4248
u32 debugfs_reg;
4349
u32 num_flows;
@@ -52,6 +58,7 @@ struct mtk_wdma_info {
5258
u8 queue;
5359
u16 wcid;
5460
u8 bss;
61+
u8 amsdu;
5562
};
5663

5764
#ifdef CONFIG_NET_MEDIATEK_SOC_WED

drivers/net/ethernet/mediatek/mtk_wed_regs.h

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,82 @@ struct mtk_wdma_desc {
672672
#define MTK_WED_WOCPU_VIEW_MIOD_BASE 0x8000
673673
#define MTK_WED_PCIE_INT_MASK 0x0
674674

675+
#define MTK_WED_AMSDU_FIFO 0x1800
676+
#define MTK_WED_AMSDU_IS_PRIOR0_RING BIT(10)
677+
678+
#define MTK_WED_AMSDU_STA_INFO 0x01810
679+
#define MTK_WED_AMSDU_STA_INFO_DO_INIT BIT(0)
680+
#define MTK_WED_AMSDU_STA_INFO_SET_INIT BIT(1)
681+
682+
#define MTK_WED_AMSDU_STA_INFO_INIT 0x01814
683+
#define MTK_WED_AMSDU_STA_WTBL_HDRT_MODE BIT(0)
684+
#define MTK_WED_AMSDU_STA_RMVL BIT(1)
685+
#define MTK_WED_AMSDU_STA_MAX_AMSDU_LEN GENMASK(7, 2)
686+
#define MTK_WED_AMSDU_STA_MAX_AMSDU_NUM GENMASK(11, 8)
687+
688+
#define MTK_WED_AMSDU_HIFTXD_BASE_L(_n) (0x1980 + (_n) * 0x4)
689+
690+
#define MTK_WED_AMSDU_PSE 0x1910
691+
#define MTK_WED_AMSDU_PSE_RESET BIT(16)
692+
693+
#define MTK_WED_AMSDU_HIFTXD_CFG 0x1968
694+
#define MTK_WED_AMSDU_HIFTXD_SRC GENMASK(16, 15)
695+
696+
#define MTK_WED_MON_AMSDU_FIFO_DMAD 0x1a34
697+
698+
#define MTK_WED_MON_AMSDU_ENG_DMAD(_n) (0x1a80 + (_n) * 0x50)
699+
#define MTK_WED_MON_AMSDU_ENG_QFPL(_n) (0x1a84 + (_n) * 0x50)
700+
#define MTK_WED_MON_AMSDU_ENG_QENI(_n) (0x1a88 + (_n) * 0x50)
701+
#define MTK_WED_MON_AMSDU_ENG_QENO(_n) (0x1a8c + (_n) * 0x50)
702+
#define MTK_WED_MON_AMSDU_ENG_MERG(_n) (0x1a90 + (_n) * 0x50)
703+
704+
#define MTK_WED_MON_AMSDU_ENG_CNT8(_n) (0x1a94 + (_n) * 0x50)
705+
#define MTK_WED_AMSDU_ENG_MAX_QGPP_CNT GENMASK(10, 0)
706+
#define MTK_WED_AMSDU_ENG_MAX_PL_CNT GENMASK(27, 16)
707+
708+
#define MTK_WED_MON_AMSDU_ENG_CNT9(_n) (0x1a98 + (_n) * 0x50)
709+
#define MTK_WED_AMSDU_ENG_CUR_ENTRY GENMASK(10, 0)
710+
#define MTK_WED_AMSDU_ENG_MAX_BUF_MERGED GENMASK(20, 16)
711+
#define MTK_WED_AMSDU_ENG_MAX_MSDU_MERGED GENMASK(28, 24)
712+
713+
#define MTK_WED_MON_AMSDU_QMEM_STS1 0x1e04
714+
715+
#define MTK_WED_MON_AMSDU_QMEM_CNT(_n) (0x1e0c + (_n) * 0x4)
716+
#define MTK_WED_AMSDU_QMEM_FQ_CNT GENMASK(27, 16)
717+
#define MTK_WED_AMSDU_QMEM_SP_QCNT GENMASK(11, 0)
718+
#define MTK_WED_AMSDU_QMEM_TID0_QCNT GENMASK(27, 16)
719+
#define MTK_WED_AMSDU_QMEM_TID1_QCNT GENMASK(11, 0)
720+
#define MTK_WED_AMSDU_QMEM_TID2_QCNT GENMASK(27, 16)
721+
#define MTK_WED_AMSDU_QMEM_TID3_QCNT GENMASK(11, 0)
722+
#define MTK_WED_AMSDU_QMEM_TID4_QCNT GENMASK(27, 16)
723+
#define MTK_WED_AMSDU_QMEM_TID5_QCNT GENMASK(11, 0)
724+
#define MTK_WED_AMSDU_QMEM_TID6_QCNT GENMASK(27, 16)
725+
#define MTK_WED_AMSDU_QMEM_TID7_QCNT GENMASK(11, 0)
726+
727+
#define MTK_WED_MON_AMSDU_QMEM_PTR(_n) (0x1e20 + (_n) * 0x4)
728+
#define MTK_WED_AMSDU_QMEM_FQ_HEAD GENMASK(27, 16)
729+
#define MTK_WED_AMSDU_QMEM_SP_QHEAD GENMASK(11, 0)
730+
#define MTK_WED_AMSDU_QMEM_TID0_QHEAD GENMASK(27, 16)
731+
#define MTK_WED_AMSDU_QMEM_TID1_QHEAD GENMASK(11, 0)
732+
#define MTK_WED_AMSDU_QMEM_TID2_QHEAD GENMASK(27, 16)
733+
#define MTK_WED_AMSDU_QMEM_TID3_QHEAD GENMASK(11, 0)
734+
#define MTK_WED_AMSDU_QMEM_TID4_QHEAD GENMASK(27, 16)
735+
#define MTK_WED_AMSDU_QMEM_TID5_QHEAD GENMASK(11, 0)
736+
#define MTK_WED_AMSDU_QMEM_TID6_QHEAD GENMASK(27, 16)
737+
#define MTK_WED_AMSDU_QMEM_TID7_QHEAD GENMASK(11, 0)
738+
#define MTK_WED_AMSDU_QMEM_FQ_TAIL GENMASK(27, 16)
739+
#define MTK_WED_AMSDU_QMEM_SP_QTAIL GENMASK(11, 0)
740+
#define MTK_WED_AMSDU_QMEM_TID0_QTAIL GENMASK(27, 16)
741+
#define MTK_WED_AMSDU_QMEM_TID1_QTAIL GENMASK(11, 0)
742+
#define MTK_WED_AMSDU_QMEM_TID2_QTAIL GENMASK(27, 16)
743+
#define MTK_WED_AMSDU_QMEM_TID3_QTAIL GENMASK(11, 0)
744+
#define MTK_WED_AMSDU_QMEM_TID4_QTAIL GENMASK(27, 16)
745+
#define MTK_WED_AMSDU_QMEM_TID5_QTAIL GENMASK(11, 0)
746+
#define MTK_WED_AMSDU_QMEM_TID6_QTAIL GENMASK(27, 16)
747+
#define MTK_WED_AMSDU_QMEM_TID7_QTAIL GENMASK(11, 0)
748+
749+
#define MTK_WED_MON_AMSDU_HIFTXD_FETCH_MSDU(_n) (0x1ec4 + (_n) * 0x4)
750+
675751
#define MTK_WED_PCIE_BASE 0x11280000
676752
#define MTK_WED_PCIE_BASE0 0x11300000
677753
#define MTK_WED_PCIE_BASE1 0x11310000

include/linux/netdevice.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -919,6 +919,7 @@ struct net_device_path {
919919
u8 queue;
920920
u16 wcid;
921921
u8 bss;
922+
u8 amsdu;
922923
} mtk_wdma;
923924
};
924925
};

0 commit comments

Comments
 (0)