[Refactor and sync kernel/wifi from Openwrt]
[Description]
Refactor and sync kernel/wifi from Openwrt
[Release-log]
N/A
diff --git a/recipes-kernel/linux-mt76/files/patches/0011-mt76-testmode-use-random-payload-for-tx-packets.patch b/recipes-kernel/linux-mt76/files/patches/0011-mt76-testmode-use-random-payload-for-tx-packets.patch
new file mode 100644
index 0000000..dc04e36
--- /dev/null
+++ b/recipes-kernel/linux-mt76/files/patches/0011-mt76-testmode-use-random-payload-for-tx-packets.patch
@@ -0,0 +1,56 @@
+From 5b712b2ec82bb9e88346b379b5c6645b1fa7d7fe Mon Sep 17 00:00:00 2001
+From: Shayne Chen <shayne.chen@mediatek.com>
+Date: Wed, 6 Jul 2022 21:52:45 +0800
+Subject: [PATCH] mt76: testmode: use random payload for tx packets
+
+Compared to fixed payload packets, random payload packets have better
+measured EVM under the same txpower. Our tests show EVM becomes at least
+3 dB better in test cases with high rate and long tx length, which also
+aligns the testing result of proprietary driver.
+
+Suggested-by: Jm Chen <jm.chen@mediatek.com>
+Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
+---
+ drivers/net/wireless/mediatek/mt76/testmode.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/testmode.c b/testmode.c
+index 4a24f6c9..31439b39 100644
+--- a/testmode.c
++++ b/testmode.c
+@@ -1,5 +1,7 @@
+ // SPDX-License-Identifier: ISC
+ /* Copyright (C) 2020 Felix Fietkau <nbd@nbd.name> */
++
++#include <linux/random.h>
+ #include "mt76.h"
+
+ const struct nla_policy mt76_tm_policy[NUM_MT76_TM_ATTRS] = {
+@@ -124,12 +126,14 @@ int mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len)
+ if (!head)
+ return -ENOMEM;
+
+- hdr = __skb_put_zero(head, head_len);
++ hdr = __skb_put_zero(head, sizeof(*hdr));
+ hdr->frame_control = cpu_to_le16(fc);
+ memcpy(hdr->addr1, td->addr[0], ETH_ALEN);
+ memcpy(hdr->addr2, td->addr[1], ETH_ALEN);
+ memcpy(hdr->addr3, td->addr[2], ETH_ALEN);
+ skb_set_queue_mapping(head, IEEE80211_AC_BE);
++ get_random_bytes(__skb_put(head, head_len - sizeof(*hdr)),
++ head_len - sizeof(*hdr));
+
+ info = IEEE80211_SKB_CB(head);
+ info->flags = IEEE80211_TX_CTL_INJECTED |
+@@ -157,7 +161,7 @@ int mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len)
+ return -ENOMEM;
+ }
+
+- __skb_put_zero(frag, frag_len);
++ get_random_bytes(__skb_put(frag, frag_len), frag_len);
+ head->len += frag->len;
+ head->data_len += frag->len;
+
+--
+2.25.1
+
diff --git a/recipes-kernel/linux-mt76/files/patches/1117-mt76-mt7915-add-vendor-subcmd-EDCCA-ctrl.patch b/recipes-kernel/linux-mt76/files/patches/1117-mt76-mt7915-add-vendor-subcmd-EDCCA-ctrl.patch
new file mode 100644
index 0000000..c25f9b2
--- /dev/null
+++ b/recipes-kernel/linux-mt76/files/patches/1117-mt76-mt7915-add-vendor-subcmd-EDCCA-ctrl.patch
@@ -0,0 +1,245 @@
+From c1e72950b8f7df7c36c64e27613637f88e3c1ba3 Mon Sep 17 00:00:00 2001
+From: Howard Hsu <howard-yh.hsu@mediatek.com>
+Date: Fri, 24 Jun 2022 11:15:45 +0800
+Subject: [PATCH 1117/1117] mt76: mt7915: add vendor subcmd EDCCA ctrl
+
+Change-Id: I92dabf8be9c5a7ecec78f35325bc5645af8d15ab
+---
+ mt76_connac_mcu.h | 1 +
+ mt7915/main.c | 3 +++
+ mt7915/mcu.c | 38 ++++++++++++++++++++++++++++
+ mt7915/mcu.h | 12 +++++++++
+ mt7915/mt7915.h | 2 ++
+ mt7915/vendor.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++
+ mt7915/vendor.h | 19 ++++++++++++++
+ 7 files changed, 138 insertions(+)
+
+diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
+index a0e6fa6e..1747e06d 100644
+--- a/mt76_connac_mcu.h
++++ b/mt76_connac_mcu.h
+@@ -1147,6 +1147,7 @@ enum {
+ MCU_EXT_CMD_SMESH_CTRL = 0xae,
+ MCU_EXT_CMD_RX_STAT_USER_CTRL = 0xb3,
+ MCU_EXT_CMD_CERT_CFG = 0xb7,
++ MCU_EXT_CMD_EDCCA = 0xba,
+ MCU_EXT_CMD_CSI_CTRL = 0xc2,
+ };
+
+diff --git a/mt7915/main.c b/mt7915/main.c
+index 6c97ce78..1dc41ab6 100644
+--- a/mt7915/main.c
++++ b/mt7915/main.c
+@@ -456,6 +456,9 @@ static int mt7915_config(struct ieee80211_hw *hw, u32 changed)
+ mutex_unlock(&dev->mt76.mutex);
+ }
+ #endif
++ ret = mt7915_mcu_set_edcca(phy, EDCCA_CTRL_SET_EN, NULL, 0);
++ if (ret)
++ return ret;
+ ieee80211_stop_queues(hw);
+ ret = mt7915_set_channel(phy);
+ if (ret)
+diff --git a/mt7915/mcu.c b/mt7915/mcu.c
+index 46eef36a..205ecbab 100644
+--- a/mt7915/mcu.c
++++ b/mt7915/mcu.c
+@@ -4217,3 +4217,41 @@ int mt7915_mcu_rf_regval(struct mt7915_dev *dev, u32 regidx, u32 *val, bool set)
+
+ return 0;
+ }
++
++int mt7915_mcu_set_edcca(struct mt7915_phy *phy, int mode, u8 *value,
++ s8 compensation)
++{
++ static const u8 ch_band[] = {
++ [NL80211_BAND_2GHZ] = 0,
++ [NL80211_BAND_5GHZ] = 1,
++ [NL80211_BAND_6GHZ] = 2,
++ };
++ struct mt7915_dev *dev = phy->dev;
++ struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
++ struct {
++ u8 band_idx;
++ u8 cmd_idx;
++ u8 setting[3];
++ bool record_in_fw;
++ u8 region;
++ s8 thres_compensation;
++ } __packed req = {
++ .band_idx = phy->band_idx,
++ .cmd_idx = mode,
++ .record_in_fw = false,
++ .region = dev->mt76.region,
++ .thres_compensation = compensation,
++ };
++
++ if (ch_band[chandef->chan->band] != 2)
++ return 0;
++
++ if (mode == EDCCA_CTRL_SET_EN) {
++ if (!value)
++ req.setting[0] = EDCCA_MODE_AUTO;
++ else
++ req.setting[0] = value[0];
++ }
++
++ return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(EDCCA), &req, sizeof(req), true);
++}
+diff --git a/mt7915/mcu.h b/mt7915/mcu.h
+index 873a8055..72c2cfc6 100644
+--- a/mt7915/mcu.h
++++ b/mt7915/mcu.h
+@@ -785,4 +785,16 @@ enum {
+ };
+ #endif
+
++enum {
++ EDCCA_CTRL_SET_EN = 0,
++ EDCCA_CTRL_SET_THERS,
++ EDCCA_CTRL_GET_EN,
++ EDCCA_CTRL_GET_THERS,
++ EDCCA_CTRL_NUM,
++};
++
++enum {
++ EDCCA_MODE_FORCE_DISABLE,
++ EDCCA_MODE_AUTO,
++};
+ #endif
+diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
+index 0b7f73b3..5c58a29c 100644
+--- a/mt7915/mt7915.h
++++ b/mt7915/mt7915.h
+@@ -718,6 +718,8 @@ void mt7915_vendor_amnt_fill_rx(struct mt7915_phy *phy, struct sk_buff *skb);
+ int mt7915_vendor_amnt_sta_remove(struct mt7915_phy *phy,
+ struct ieee80211_sta *sta);
+ #endif
++int mt7915_mcu_set_edcca(struct mt7915_phy *phy, int mode, u8 *value,
++ s8 compensation);
+
+ #ifdef MTK_DEBUG
+ int mt7915_mtk_init_debugfs(struct mt7915_phy *phy, struct dentry *dir);
+diff --git a/mt7915/vendor.c b/mt7915/vendor.c
+index 77d71e48..5a28a554 100644
+--- a/mt7915/vendor.c
++++ b/mt7915/vendor.c
+@@ -62,6 +62,17 @@ phy_capa_dump_policy[NUM_MTK_VENDOR_ATTRS_PHY_CAPA_DUMP] = {
+ [MTK_VENDOR_ATTR_PHY_CAPA_DUMP_MAX_SUPPORTED_STA] = { .type = NLA_U16 },
+ };
+
++static const struct nla_policy
++edcca_ctrl_policy[NUM_MTK_VENDOR_ATTRS_EDCCA_CTRL] = {
++ [MTK_VENDOR_ATTR_EDCCA_CTRL_MODE] = { .type = NLA_U8 },
++ [MTK_VENDOR_ATTR_EDCCA_CTRL_PRI20_VAL] = { .type = NLA_U8 },
++ [MTK_VENDOR_ATTR_EDCCA_CTRL_SEC20_VAL] = { .type = NLA_U8 },
++ [MTK_VENDOR_ATTR_EDCCA_CTRL_SEC40_VAL] = { .type = NLA_U8 },
++ [MTK_VENDOR_ATTR_EDCCA_CTRL_SEC80_VAL] = { .type = NLA_U8 },
++ [MTK_VENDOR_ATTR_EDCCA_CTRL_COMPENSATE] = { .type = NLA_S8 },
++};
++
++
+ struct csi_null_tone {
+ u8 start;
+ u8 end;
+@@ -1015,6 +1026,47 @@ mt7915_vendor_phy_capa_ctrl_dump(struct wiphy *wiphy, struct wireless_dev *wdev,
+ return len;
+ }
+
++static int mt7915_vendor_edcca_ctrl(struct wiphy *wiphy,
++ struct wireless_dev *wdev,
++ const void *data,
++ int data_len)
++{
++ struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
++ struct mt7915_phy *phy = mt7915_hw_phy(hw);
++ struct nlattr *tb[NUM_MTK_VENDOR_ATTRS_EDCCA_CTRL];
++ int err;
++ u8 edcca_mode;
++ s8 edcca_compensation;
++
++ err = nla_parse(tb, MTK_VENDOR_ATTR_EDCCA_CTRL_MAX, data, data_len,
++ edcca_ctrl_policy, NULL);
++ if (err)
++ return err;
++
++ if (!tb[MTK_VENDOR_ATTR_EDCCA_CTRL_MODE])
++ return -EINVAL;
++
++ edcca_mode = nla_get_u8(tb[MTK_VENDOR_ATTR_EDCCA_CTRL_MODE]);
++ if (edcca_mode == EDCCA_CTRL_SET_EN) {
++ u8 edcca_value[3] = {0};
++ if (!tb[MTK_VENDOR_ATTR_EDCCA_CTRL_PRI20_VAL] ||
++ !tb[MTK_VENDOR_ATTR_EDCCA_CTRL_COMPENSATE]) {
++ return -EINVAL;
++ }
++ edcca_value[0] =
++ nla_get_u8(tb[MTK_VENDOR_ATTR_EDCCA_CTRL_PRI20_VAL]);
++ edcca_compensation =
++ nla_get_s8(tb[MTK_VENDOR_ATTR_EDCCA_CTRL_COMPENSATE]);
++
++ err = mt7915_mcu_set_edcca(phy, edcca_mode, edcca_value,
++ edcca_compensation);
++ if (err)
++ return err;
++ }
++ return 0;
++}
++
++
+ static const struct wiphy_vendor_command mt7915_vendor_commands[] = {
+ {
+ .info = {
+@@ -1083,6 +1135,17 @@ static const struct wiphy_vendor_command mt7915_vendor_commands[] = {
+ .dumpit = mt7915_vendor_phy_capa_ctrl_dump,
+ .policy = phy_capa_ctrl_policy,
+ .maxattr = MTK_VENDOR_ATTR_PHY_CAPA_CTRL_MAX,
++ },
++ {
++ .info = {
++ .vendor_id = MTK_NL80211_VENDOR_ID,
++ .subcmd = MTK_NL80211_VENDOR_SUBCMD_EDCCA_CTRL,
++ },
++ .flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
++ WIPHY_VENDOR_CMD_NEED_RUNNING,
++ .doit = mt7915_vendor_edcca_ctrl,
++ .policy = edcca_ctrl_policy,
++ .maxattr = MTK_VENDOR_ATTR_EDCCA_CTRL_MAX,
+ }
+ };
+
+diff --git a/mt7915/vendor.h b/mt7915/vendor.h
+index 719b851f..83c41bc1 100644
+--- a/mt7915/vendor.h
++++ b/mt7915/vendor.h
+@@ -10,8 +10,27 @@ enum mtk_nl80211_vendor_subcmds {
+ MTK_NL80211_VENDOR_SUBCMD_WIRELESS_CTRL = 0xc4,
+ MTK_NL80211_VENDOR_SUBCMD_HEMU_CTRL = 0xc5,
+ MTK_NL80211_VENDOR_SUBCMD_PHY_CAPA_CTRL = 0xc6,
++ MTK_NL80211_VENDOR_SUBCMD_EDCCA_CTRL = 0xc7,
+ };
+
++
++enum mtk_vendor_attr_edcca_ctrl {
++ MTK_VENDOR_ATTR_EDCCA_THRESHOLD_INVALID = 0,
++
++ MTK_VENDOR_ATTR_EDCCA_CTRL_MODE,
++ MTK_VENDOR_ATTR_EDCCA_CTRL_PRI20_VAL,
++ MTK_VENDOR_ATTR_EDCCA_CTRL_SEC20_VAL,
++ MTK_VENDOR_ATTR_EDCCA_CTRL_SEC40_VAL,
++ MTK_VENDOR_ATTR_EDCCA_CTRL_SEC80_VAL,
++ MTK_VENDOR_ATTR_EDCCA_CTRL_COMPENSATE,
++
++ /* keep last */
++ NUM_MTK_VENDOR_ATTRS_EDCCA_CTRL,
++ MTK_VENDOR_ATTR_EDCCA_CTRL_MAX =
++ NUM_MTK_VENDOR_ATTRS_EDCCA_CTRL - 1
++};
++
++
+ enum mtk_capi_control_changed {
+ CAPI_RFEATURE_CHANGED = BIT(16),
+ CAPI_WIRELESS_CHANGED = BIT(17),
+--
+2.18.0
+
diff --git a/recipes-kernel/linux-mt76/files/patches/3002-mt76-add-wed-rx-support.patch b/recipes-kernel/linux-mt76/files/patches/3002-mt76-add-wed-rx-support.patch
index 5c5a05d..7040ca6 100755
--- a/recipes-kernel/linux-mt76/files/patches/3002-mt76-add-wed-rx-support.patch
+++ b/recipes-kernel/linux-mt76/files/patches/3002-mt76-add-wed-rx-support.patch
@@ -5,10 +5,10 @@
Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com>
---
- dma.c | 219 +++++++++++++++++++++++++++++++++--------
+ dma.c | 248 +++++++++++++++++++++++++++++++++--------
dma.h | 10 ++
mac80211.c | 8 +-
- mt76.h | 24 ++++-
+ mt76.h | 24 +++-
mt7603/dma.c | 2 +-
mt7603/mt7603.h | 2 +-
mt7615/mac.c | 2 +-
@@ -17,7 +17,7 @@
mt76x02.h | 2 +-
mt76x02_txrx.c | 2 +-
mt7915/dma.c | 10 ++
- mt7915/mac.c | 89 ++++++++++++++++-
+ mt7915/mac.c | 101 ++++++++++++++++-
mt7915/mcu.c | 3 +
mt7915/mmio.c | 26 ++++-
mt7915/mt7915.h | 7 +-
@@ -25,13 +25,11 @@
mt7921/mac.c | 2 +-
mt7921/mt7921.h | 4 +-
mt7921/pci_mac.c | 4 +-
- tx.c | 34 +++++++
- 21 files changed, 410 insertions(+), 65 deletions(-)
- mode change 100755 => 100644 mt7915/mac.c
- mode change 100755 => 100644 mt7915/mmio.c
+ tx.c | 34 ++++++
+ 21 files changed, 448 insertions(+), 68 deletions(-)
diff --git a/dma.c b/dma.c
-index 03ee910..094aede 100644
+index 03ee910..e46dbed 100644
--- a/dma.c
+++ b/dma.c
@@ -98,6 +98,63 @@ mt76_put_txwi(struct mt76_dev *dev, struct mt76_txwi_cache *t)
@@ -98,7 +96,29 @@
static void
mt76_free_pending_txwi(struct mt76_dev *dev)
{
-@@ -141,12 +198,15 @@ mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q)
+@@ -112,6 +169,21 @@ mt76_free_pending_txwi(struct mt76_dev *dev)
+ local_bh_enable();
+ }
+
++static void
++mt76_free_pending_rxwi(struct mt76_dev *dev)
++{
++ struct mt76_txwi_cache *r;
++
++ local_bh_disable();
++ while ((r = __mt76_get_rxwi(dev)) != NULL) {
++ if (r->buf)
++ skb_free_frag(r->buf);
++
++ kfree(r);
++ }
++ local_bh_enable();
++}
++
+ static void
+ mt76_dma_sync_idx(struct mt76_dev *dev, struct mt76_queue *q)
+ {
+@@ -141,12 +213,15 @@ mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q)
static int
mt76_dma_add_buf(struct mt76_dev *dev, struct mt76_queue *q,
struct mt76_queue_buf *buf, int nbufs, u32 info,
@@ -115,7 +135,7 @@
if (txwi) {
q->entry[q->head].txwi = DMA_DUMMY_DATA;
-@@ -162,28 +222,42 @@ mt76_dma_add_buf(struct mt76_dev *dev, struct mt76_queue *q,
+@@ -162,28 +237,42 @@ mt76_dma_add_buf(struct mt76_dev *dev, struct mt76_queue *q,
desc = &q->desc[idx];
entry = &q->entry[idx];
@@ -178,7 +198,7 @@
WRITE_ONCE(desc->buf0, cpu_to_le32(buf0));
WRITE_ONCE(desc->buf1, cpu_to_le32(buf1));
WRITE_ONCE(desc->info, cpu_to_le32(info));
-@@ -272,33 +346,63 @@ mt76_dma_tx_cleanup(struct mt76_dev *dev, struct mt76_queue *q, bool flush)
+@@ -272,33 +361,63 @@ mt76_dma_tx_cleanup(struct mt76_dev *dev, struct mt76_queue *q, bool flush)
static void *
mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
@@ -248,7 +268,7 @@
{
int idx = q->tail;
-@@ -314,7 +418,7 @@ mt76_dma_dequeue(struct mt76_dev *dev, struct mt76_queue *q, bool flush,
+@@ -314,7 +433,7 @@ mt76_dma_dequeue(struct mt76_dev *dev, struct mt76_queue *q, bool flush,
q->tail = (q->tail + 1) % q->ndesc;
q->queued--;
@@ -257,7 +277,7 @@
}
static int
-@@ -336,7 +440,7 @@ mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, struct mt76_queue *q,
+@@ -336,7 +455,7 @@ mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, struct mt76_queue *q,
buf.len = skb->len;
spin_lock_bh(&q->lock);
@@ -266,7 +286,7 @@
mt76_dma_kick_queue(dev, q);
spin_unlock_bh(&q->lock);
-@@ -413,7 +517,7 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
+@@ -413,7 +532,7 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
goto unmap;
return mt76_dma_add_buf(dev, q, tx_info.buf, tx_info.nbuf,
@@ -275,15 +295,16 @@
unmap:
for (n--; n > 0; n--)
-@@ -448,6 +552,7 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q)
+@@ -448,6 +567,8 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q)
int frames = 0;
int len = SKB_WITH_OVERHEAD(q->buf_size);
int offset = q->buf_offset;
+ struct mtk_wed_device *wed = &dev->mmio.wed;
++ struct page_frag_cache *rx_page;
if (!q->ndesc)
return 0;
-@@ -456,10 +561,27 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q)
+@@ -456,10 +577,29 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q)
while (q->queued < q->ndesc - 1) {
struct mt76_queue_buf qbuf;
@@ -291,7 +312,9 @@
+ bool skip_alloc = false;
+ struct mt76_txwi_cache *r = NULL;
+
++ rx_page = &q->rx_page;
+ if (mtk_wed_device_active(wed) && type == MT76_WED_Q_RX) {
++ rx_page = &wed->rx_page;
+ r = mt76_get_rxwi(dev);
+ if (!r)
+ return -ENOMEM;
@@ -307,14 +330,14 @@
- if (!buf)
- break;
+ if (!skip_alloc) {
-+ buf = page_frag_alloc(&q->rx_page, q->buf_size, GFP_ATOMIC);
++ buf = page_frag_alloc(rx_page, q->buf_size, GFP_ATOMIC);
+ if (!buf)
+ break;
+ }
addr = dma_map_single(dev->dma_dev, buf, len, DMA_FROM_DEVICE);
if (unlikely(dma_mapping_error(dev->dma_dev, addr))) {
-@@ -470,7 +592,7 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q)
+@@ -470,7 +610,7 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q)
qbuf.addr = addr + offset;
qbuf.len = len - offset;
qbuf.skip_unmap = false;
@@ -323,7 +346,7 @@
frames++;
}
-@@ -516,6 +638,11 @@ mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q)
+@@ -516,6 +656,11 @@ mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q)
if (!ret)
q->wed_regs = wed->txfree_ring.reg_base;
break;
@@ -335,7 +358,7 @@
default:
ret = -EINVAL;
}
-@@ -531,7 +658,8 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
+@@ -531,7 +676,8 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
int idx, int n_desc, int bufsize,
u32 ring_base)
{
@@ -345,7 +368,7 @@
spin_lock_init(&q->lock);
spin_lock_init(&q->cleanup_lock);
-@@ -541,6 +669,11 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
+@@ -541,6 +687,11 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
q->buf_size = bufsize;
q->hw_idx = idx;
@@ -357,7 +380,7 @@
size = q->ndesc * sizeof(struct mt76_desc);
q->desc = dmam_alloc_coherent(dev->dma_dev, size, &q->desc_dma, GFP_KERNEL);
if (!q->desc)
-@@ -573,7 +706,7 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
+@@ -573,7 +724,7 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
spin_lock_bh(&q->lock);
do {
@@ -366,7 +389,7 @@
if (!buf)
break;
-@@ -614,7 +747,7 @@ mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid)
+@@ -614,7 +765,7 @@ mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid)
static void
mt76_add_fragment(struct mt76_dev *dev, struct mt76_queue *q, void *data,
@@ -375,7 +398,7 @@
{
struct sk_buff *skb = q->rx_head;
struct skb_shared_info *shinfo = skb_shinfo(skb);
-@@ -634,7 +767,7 @@ mt76_add_fragment(struct mt76_dev *dev, struct mt76_queue *q, void *data,
+@@ -634,7 +785,7 @@ mt76_add_fragment(struct mt76_dev *dev, struct mt76_queue *q, void *data,
q->rx_head = NULL;
if (nr_frags < ARRAY_SIZE(shinfo->frags))
@@ -384,7 +407,7 @@
else
dev_kfree_skb(skb);
}
-@@ -655,6 +788,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
+@@ -655,6 +806,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
}
while (done < budget) {
@@ -392,7 +415,7 @@
u32 info;
if (check_ddone) {
-@@ -665,10 +799,13 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
+@@ -665,10 +817,13 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
break;
}
@@ -407,7 +430,7 @@
if (q->rx_head)
data_len = q->buf_size;
else
-@@ -681,7 +818,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
+@@ -681,7 +836,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
}
if (q->rx_head) {
@@ -416,7 +439,7 @@
continue;
}
-@@ -708,7 +845,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
+@@ -708,7 +863,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
continue;
}
@@ -425,6 +448,36 @@
continue;
free_frag:
+@@ -785,8 +940,8 @@ EXPORT_SYMBOL_GPL(mt76_dma_attach);
+
+ void mt76_dma_cleanup(struct mt76_dev *dev)
+ {
+- int i;
+-
++ int i, type;
++
+ mt76_worker_disable(&dev->tx_worker);
+ netif_napi_del(&dev->tx_napi);
+
+@@ -801,12 +956,17 @@ void mt76_dma_cleanup(struct mt76_dev *dev)
+
+ mt76_for_each_q_rx(dev, i) {
+ netif_napi_del(&dev->napi[i]);
+- mt76_dma_rx_cleanup(dev, &dev->q_rx[i]);
++ type = FIELD_GET(MT_QFLAG_WED_TYPE, dev->q_rx[i].flags);
++ if (type != MT76_WED_Q_RX)
++ mt76_dma_rx_cleanup(dev, &dev->q_rx[i]);
+ }
+
+ mt76_free_pending_txwi(dev);
++ mt76_free_pending_rxwi(dev);
+
+ if (mtk_wed_device_active(&dev->mmio.wed))
+ mtk_wed_device_detach(&dev->mmio.wed);
++
++ mt76_free_pending_rxwi(dev);
+ }
+ EXPORT_SYMBOL_GPL(mt76_dma_cleanup);
diff --git a/dma.h b/dma.h
index fdf786f..90370d1 100644
--- a/dma.h
@@ -628,7 +681,7 @@
int mt7615_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
diff --git a/mt76_connac_mcu.c b/mt76_connac_mcu.c
-index cd35068..f90a08f 100644
+index cd35068..2454846 100644
--- a/mt76_connac_mcu.c
+++ b/mt76_connac_mcu.c
@@ -1190,6 +1190,7 @@ int mt76_connac_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif *mvif,
@@ -737,9 +790,7 @@
MT_RXQ_ID(MT_RXQ_EXT),
MT7915_RX_RING_SIZE,
diff --git a/mt7915/mac.c b/mt7915/mac.c
-old mode 100755
-new mode 100644
-index bc8da4d..79b7d01
+index bc8da4d..dd87a40 100644
--- a/mt7915/mac.c
+++ b/mt7915/mac.c
@@ -217,7 +217,7 @@ static void mt7915_mac_sta_poll(struct mt7915_dev *dev)
@@ -751,23 +802,32 @@
{
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
struct mt76_phy *mphy = &dev->mt76.phy;
+@@ -234,7 +234,7 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
+ bool unicast, insert_ccmp_hdr = false;
+ u8 remove_pad, amsdu_info;
+ u8 mode = 0, qos_ctl = 0;
+- struct mt7915_sta *msta;
++ struct mt7915_sta *msta = NULL;
+ bool hdr_trans;
+ u16 hdr_gap;
+ u16 seq_ctrl = 0;
@@ -494,6 +494,27 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
#endif
} else {
status->flag |= RX_FLAG_8023;
-+ if (msta || msta->vif) {
++ if (msta && msta->vif) {
+ struct mtk_wed_device *wed;
+ int type;
+
+ wed = &dev->mt76.mmio.wed;
+ type = FIELD_GET(MT_QFLAG_WED_TYPE, dev->mt76.q_rx[q].flags);
+ if ((mtk_wed_device_active(wed) && type == MT76_WED_Q_RX) &&
-+ (info & MT_DMA_INFO_PPE_VLD)){
++ (info & MT_DMA_INFO_PPE_VLD)) {
+ struct ieee80211_vif *vif;
+ u32 hash, reason;
+
+ vif = container_of((void *)msta->vif, struct ieee80211_vif,
-+ drv_priv);
++ drv_priv);
+
+ skb->dev = ieee80211_vif_to_netdev(vif);
+ reason = FIELD_GET(MT_DMA_PPE_CPU_REASON, info);
@@ -779,7 +839,7 @@
}
if (rxv && mode >= MT_PHY_TYPE_HE_SU && !(status->flag & RX_FLAG_8023))
-@@ -840,6 +861,68 @@ u32 mt7915_wed_init_buf(void *ptr, dma_addr_t phys, int token_id)
+@@ -840,6 +861,80 @@ u32 mt7915_wed_init_buf(void *ptr, dma_addr_t phys, int token_id)
return MT_TXD_TXP_BUF_SIZE;
}
@@ -826,6 +886,7 @@
+{
+ struct mt76_txwi_cache *rxwi;
+ struct mt7915_dev *dev;
++ struct page *page;
+ int token;
+
+ dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed);
@@ -835,6 +896,9 @@
+ if(!rxwi)
+ continue;
+
++ if(!rxwi->buf)
++ continue;
++
+ dma_unmap_single(dev->mt76.dma_dev, rxwi->dma_addr,
+ wed->wlan.rx_pkt_size, DMA_FROM_DEVICE);
+ skb_free_frag(rxwi->buf);
@@ -842,13 +906,21 @@
+
+ mt76_put_rxwi(&dev->mt76, rxwi);
+ }
++
++ if (wed->rx_page.va)
++ return;
++
++ page = virt_to_page(wed->rx_page.va);
++ __page_frag_cache_drain(page, wed->rx_page.pagecnt_bias);
++ memset(&wed->rx_page, 0, sizeof(wed->rx_page));
++
+ return;
+}
+
static void
mt7915_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
{
-@@ -1120,7 +1203,7 @@ bool mt7915_rx_check(struct mt76_dev *mdev, void *data, int len)
+@@ -1120,7 +1215,7 @@ bool mt7915_rx_check(struct mt76_dev *mdev, void *data, int len)
}
void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
@@ -857,7 +929,7 @@
{
struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
__le32 *rxd = (__le32 *)skb->data;
-@@ -1154,7 +1237,7 @@ void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
+@@ -1154,7 +1249,7 @@ void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
dev_kfree_skb(skb);
break;
case PKT_TYPE_NORMAL:
@@ -867,7 +939,7 @@
return;
}
diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index 1468c3c..4f64df4 100644
+index 1468c3c..5eace9e 100644
--- a/mt7915/mcu.c
+++ b/mt7915/mcu.c
@@ -1704,6 +1704,7 @@ int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif,
@@ -888,9 +960,7 @@
MCU_EXT_CMD(STA_REC_UPDATE), true);
}
diff --git a/mt7915/mmio.c b/mt7915/mmio.c
-old mode 100755
-new mode 100644
-index b4a3120..08ff556
+index b4a3120..08ff556 100644
--- a/mt7915/mmio.c
+++ b/mt7915/mmio.c
@@ -28,6 +28,9 @@ static const u32 mt7915_reg[] = {
diff --git a/recipes-kernel/linux-mt76/files/patches/patches.inc b/recipes-kernel/linux-mt76/files/patches/patches.inc
index da26649..5297bc1 100644
--- a/recipes-kernel/linux-mt76/files/patches/patches.inc
+++ b/recipes-kernel/linux-mt76/files/patches/patches.inc
@@ -7,6 +7,7 @@
file://0005-mt76-mt7915-drop-undefined-action-frame.patch \
file://0008-mt76-common-RF-CR-idx-require-8-bits.patch \
file://0010-mt76-mt7915-4addr-null-frame-using-fixed-rate-to-suc.patch \
+ file://0011-mt76-testmode-use-random-payload-for-tx-packets.patch \
file://100-Revert-of-net-pass-the-dst-buffer-to-of_get_mac_addr.patch \
file://1001-mt76-mt7915-add-mtk-internal-debug-tools-for-mt76.patch \
file://1002-mt76-mt7915-csi-implement-csi-support.patch \
@@ -22,6 +23,7 @@
file://1114-mt76-airtime-fairness-feature-off-in-mac80211.patch \
file://1115-mt76-mt7915-add-mt7986-and-mt7916-pre-calibration.patch \
file://1116-mt76-mt7915-add-vendor-dump-phy-capa.patch \
+ file://1117-mt76-mt7915-add-vendor-subcmd-EDCCA-ctrl.patch \
file://3001-mt76-add-wed-tx-support.patch \
file://3002-mt76-add-wed-rx-support.patch \
file://3003-mt76-add-fill-receive-path-to-report-wed-idx.patch \
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/pending-5.4/201-extra_optimization.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/pending-5.4/201-extra_optimization.patch
deleted file mode 100644
index c606487..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/pending-5.4/201-extra_optimization.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Subject: Upgrade to Linux 2.6.19
-
-- Includes large parts of the patch from #1021 by dpalffy
-- Includes RB532 NAND driver changes by n0-1
-
-[john@phrozen.org: feix will add this to his upstream queue]
-
-lede-commit: bff468813f78f81e36ebb2a3f4354de7365e640f
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
- Makefile | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
---- a/Makefile
-+++ b/Makefile
-@@ -719,11 +719,11 @@ KBUILD_CFLAGS += $(call cc-disable-warni
- KBUILD_CFLAGS += $(call cc-disable-warning, address-of-packed-member)
-
- ifdef CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE
--KBUILD_CFLAGS += -O2
-+KBUILD_CFLAGS += -O2 $(EXTRA_OPTIMIZATION)
- else ifdef CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE_O3
--KBUILD_CFLAGS += -O3
-+KBUILD_CFLAGS += -O3 $(EXTRA_OPTIMIZATION)
- else ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
--KBUILD_CFLAGS += -Os
-+KBUILD_CFLAGS += -Os -fno-reorder-blocks -fno-tree-ch $(EXTRA_OPTIMIZATION)
- endif
-
- # Tell gcc to never replace conditional load with a non-conditional one
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/pending-5.4/pending-5.4.inc b/recipes-kernel/linux/linux-mediatek-5.4/generic/pending-5.4/pending-5.4.inc
index 1b5f456..8317acf 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/pending-5.4/pending-5.4.inc
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/pending-5.4/pending-5.4.inc
@@ -12,7 +12,6 @@
file://180-net-phy-at803x-add-support-for-AT8032.patch \
file://190-rtc-rs5c372-support_alarms_up_to_1_week.patch \
file://191-rtc-rs5c372-let_the_alarm_to_be_used_as_wakeup_source.patch \
- file://201-extra_optimization.patch \
file://203-kallsyms_uncompressed.patch \
file://205-backtrace_module_info.patch \
file://240-remove-unsane-filenames-from-deps_initramfs-list.patch \
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981-spim-nand-2500wan-gmac2.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981-spim-nand-2500wan-gmac2.dts
index 745606f..396f483 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981-spim-nand-2500wan-gmac2.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981-spim-nand-2500wan-gmac2.dts
@@ -179,6 +179,12 @@
#address-cells = <1>;
#size-cells = <1>;
compatible = "spi-nand";
+ spi-cal-enable;
+ spi-cal-mode = "read-data";
+ spi-cal-datalen = <7>;
+ spi-cal-data = /bits/ 8 <0x53 0x50 0x49 0x4E 0x41 0x4E 0x44>;
+ spi-cal-addrlen = <5>;
+ spi-cal-addr = /bits/ 32 <0x0 0x0 0x0 0x0 0x0>;
reg = <0>;
spi-max-frequency = <52000000>;
spi-tx-buswidth = <4>;
@@ -190,6 +196,18 @@
pinctrl-names = "default";
pinctrl-0 = <&spic_pins>;
status = "disabled";
+
+ slb9670: slb9670@0 {
+ compatible = "infineon,slb9670";
+ reg = <0>; /* CE0 */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ spi-cal-enable;
+ spi-cal-mode = "read-data";
+ spi-cal-datalen = <2>;
+ spi-cal-data = /bits/ 8 <0x00 0x1b>;
+ spi-max-frequency = <20000000>;
+ };
};
&pio {
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981-spim-nor-rfb.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981-spim-nor-rfb.dts
index abd7fd3..47bb702 100755
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981-spim-nor-rfb.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981-spim-nor-rfb.dts
@@ -123,6 +123,13 @@
#address-cells = <1>;
#size-cells = <1>;
compatible = "jedec,spi-nor";
+ spi-cal-enable;
+ spi-cal-mode = "read-data";
+ spi-cal-datalen = <7>;
+ spi-cal-data = /bits/ 8 <
+ 0x53 0x46 0x5F 0x42 0x4F 0x4F 0x54>; /* SF_BOOT */
+ spi-cal-addrlen = <1>;
+ spi-cal-addr = /bits/ 32 <0x0>;
reg = <0>;
spi-max-frequency = <52000000>;
spi-tx-buswidth = <4>;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.c
index 7ba9a01..38d2b53 100755
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.c
@@ -631,38 +631,32 @@
int tx_ring_read(struct seq_file *seq, void *v)
{
+ struct mtk_eth *eth = g_eth;
struct mtk_tx_ring *ring = &g_eth->tx_ring;
- struct mtk_tx_dma *tx_ring;
+ struct mtk_tx_dma_v2 *tx_ring;
int i = 0;
- tx_ring =
- kmalloc(sizeof(struct mtk_tx_dma) * MTK_DMA_SIZE, GFP_KERNEL);
- if (!tx_ring) {
- seq_puts(seq, " allocate temp tx_ring fail.\n");
- return 0;
- }
-
- for (i = 0; i < MTK_DMA_SIZE; i++)
- tx_ring[i] = ring->dma[i];
-
seq_printf(seq, "free count = %d\n", (int)atomic_read(&ring->free_count));
seq_printf(seq, "cpu next free: %d\n", (int)(ring->next_free - ring->dma));
seq_printf(seq, "cpu last free: %d\n", (int)(ring->last_free - ring->dma));
for (i = 0; i < MTK_DMA_SIZE; i++) {
- dma_addr_t tmp = ring->phys + i * sizeof(*tx_ring);
+ dma_addr_t tmp = ring->phys + i * eth->soc->txrx.txd_size;
+
+ tx_ring = ring->dma + i * eth->soc->txrx.txd_size;
seq_printf(seq, "%d (%pad): %08x %08x %08x %08x", i, &tmp,
- *(int *)&tx_ring[i].txd1, *(int *)&tx_ring[i].txd2,
- *(int *)&tx_ring[i].txd3, *(int *)&tx_ring[i].txd4);
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
- seq_printf(seq, " %08x %08x %08x %08x",
- *(int *)&tx_ring[i].txd5, *(int *)&tx_ring[i].txd6,
- *(int *)&tx_ring[i].txd7, *(int *)&tx_ring[i].txd8);
-#endif
+ tx_ring->txd1, tx_ring->txd2,
+ tx_ring->txd3, tx_ring->txd4);
+
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
+ seq_printf(seq, " %08x %08x %08x %08x",
+ tx_ring->txd5, tx_ring->txd6,
+ tx_ring->txd7, tx_ring->txd8);
+ }
+
seq_printf(seq, "\n");
}
- kfree(tx_ring);
return 0;
}
@@ -682,34 +676,27 @@
int hwtx_ring_read(struct seq_file *seq, void *v)
{
struct mtk_eth *eth = g_eth;
- struct mtk_tx_dma *hwtx_ring;
+ struct mtk_tx_dma_v2 *hwtx_ring;
int i = 0;
- hwtx_ring =
- kmalloc(sizeof(struct mtk_tx_dma) * MTK_DMA_SIZE, GFP_KERNEL);
- if (!hwtx_ring) {
- seq_puts(seq, " allocate temp hwtx_ring fail.\n");
- return 0;
- }
-
- for (i = 0; i < MTK_DMA_SIZE; i++)
- hwtx_ring[i] = eth->scratch_ring[i];
-
for (i = 0; i < MTK_DMA_SIZE; i++) {
- dma_addr_t addr = eth->phy_scratch_ring + i * sizeof(*hwtx_ring);
+ dma_addr_t addr = eth->phy_scratch_ring + i * eth->soc->txrx.txd_size;
+
+ hwtx_ring = eth->scratch_ring + i * eth->soc->txrx.txd_size;
seq_printf(seq, "%d (%pad): %08x %08x %08x %08x", i, &addr,
- *(int *)&hwtx_ring[i].txd1, *(int *)&hwtx_ring[i].txd2,
- *(int *)&hwtx_ring[i].txd3, *(int *)&hwtx_ring[i].txd4);
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
- seq_printf(seq, " %08x %08x %08x %08x",
- *(int *)&hwtx_ring[i].txd5, *(int *)&hwtx_ring[i].txd6,
- *(int *)&hwtx_ring[i].txd7, *(int *)&hwtx_ring[i].txd8);
-#endif
+ hwtx_ring->txd1, hwtx_ring->txd2,
+ hwtx_ring->txd3, hwtx_ring->txd4);
+
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
+ seq_printf(seq, " %08x %08x %08x %08x",
+ hwtx_ring->txd5, hwtx_ring->txd6,
+ hwtx_ring->txd7, hwtx_ring->txd8);
+ }
+
seq_printf(seq, "\n");
}
- kfree(hwtx_ring);
return 0;
}
@@ -728,36 +715,29 @@
int rx_ring_read(struct seq_file *seq, void *v)
{
+ struct mtk_eth *eth = g_eth;
struct mtk_rx_ring *ring = &g_eth->rx_ring[0];
- struct mtk_rx_dma *rx_ring;
-
+ struct mtk_rx_dma_v2 *rx_ring;
int i = 0;
- rx_ring =
- kmalloc(sizeof(struct mtk_rx_dma) * MTK_DMA_SIZE, GFP_KERNEL);
- if (!rx_ring) {
- seq_puts(seq, " allocate temp rx_ring fail.\n");
- return 0;
- }
-
- for (i = 0; i < MTK_DMA_SIZE; i++)
- rx_ring[i] = ring->dma[i];
-
seq_printf(seq, "next to read: %d\n",
NEXT_DESP_IDX(ring->calc_idx, MTK_DMA_SIZE));
for (i = 0; i < MTK_DMA_SIZE; i++) {
+ rx_ring = ring->dma + i * eth->soc->txrx.rxd_size;
+
seq_printf(seq, "%d: %08x %08x %08x %08x", i,
- *(int *)&rx_ring[i].rxd1, *(int *)&rx_ring[i].rxd2,
- *(int *)&rx_ring[i].rxd3, *(int *)&rx_ring[i].rxd4);
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
- seq_printf(seq, " %08x %08x %08x %08x",
- *(int *)&rx_ring[i].rxd5, *(int *)&rx_ring[i].rxd6,
- *(int *)&rx_ring[i].rxd7, *(int *)&rx_ring[i].rxd8);
-#endif
+ rx_ring->rxd1, rx_ring->rxd2,
+ rx_ring->rxd3, rx_ring->rxd4);
+
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
+ seq_printf(seq, " %08x %08x %08x %08x",
+ rx_ring->rxd5, rx_ring->rxd6,
+ rx_ring->rxd7, rx_ring->rxd8);
+ }
+
seq_printf(seq, "\n");
}
- kfree(rx_ring);
return 0;
}
@@ -902,17 +882,18 @@
.release = single_release
};
-void hw_lro_stats_update(u32 ring_no, struct mtk_rx_dma *rxd)
+void hw_lro_stats_update(u32 ring_no, struct mtk_rx_dma_v2 *rxd)
{
+ struct mtk_eth *eth = g_eth;
u32 idx, agg_cnt, agg_size;
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
- idx = ring_no - 4;
- agg_cnt = RX_DMA_GET_AGG_CNT_V2(rxd->rxd6);
-#else
- idx = ring_no - 1;
- agg_cnt = RX_DMA_GET_AGG_CNT(rxd->rxd2);
-#endif
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
+ idx = ring_no - 4;
+ agg_cnt = RX_DMA_GET_AGG_CNT_V2(rxd->rxd6);
+ } else {
+ idx = ring_no - 1;
+ agg_cnt = RX_DMA_GET_AGG_CNT(rxd->rxd2);
+ }
agg_size = RX_DMA_GET_PLEN0(rxd->rxd2);
@@ -922,17 +903,18 @@
hw_lro_tot_agg_cnt[idx] += agg_cnt;
}
-void hw_lro_flush_stats_update(u32 ring_no, struct mtk_rx_dma *rxd)
+void hw_lro_flush_stats_update(u32 ring_no, struct mtk_rx_dma_v2 *rxd)
{
+ struct mtk_eth *eth = g_eth;
u32 idx, flush_reason;
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
- idx = ring_no - 4;
- flush_reason = RX_DMA_GET_FLUSH_RSN_V2(rxd->rxd6);
-#else
- idx = ring_no - 1;
- flush_reason = RX_DMA_GET_REV(rxd->rxd2);
-#endif
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
+ idx = ring_no - 4;
+ flush_reason = RX_DMA_GET_FLUSH_RSN_V2(rxd->rxd6);
+ } else {
+ idx = ring_no - 1;
+ flush_reason = RX_DMA_GET_REV(rxd->rxd2);
+ }
if ((flush_reason & 0x7) == MTK_HW_LRO_AGG_FLUSH)
hw_lro_agg_flush_cnt[idx]++;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.h b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.h
index 2113c1f..52bd729 100755
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.h
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.h
@@ -279,7 +279,7 @@
int mtketh_debugfs_init(struct mtk_eth *eth);
void mtketh_debugfs_exit(struct mtk_eth *eth);
int mtk_do_priv_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
-void hw_lro_stats_update(u32 ring_no, struct mtk_rx_dma *rxd);
-void hw_lro_flush_stats_update(u32 ring_no, struct mtk_rx_dma *rxd);
+void hw_lro_stats_update(u32 ring_no, struct mtk_rx_dma_v2 *rxd);
+void hw_lro_flush_stats_update(u32 ring_no, struct mtk_rx_dma_v2 *rxd);
#endif /* MTK_ETH_DBG_H */
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index e6f6cce..9489d1d 100755
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -823,8 +823,8 @@
return buf_size;
}
-static inline bool mtk_rx_get_desc(struct mtk_rx_dma *rxd,
- struct mtk_rx_dma *dma_rxd)
+static bool mtk_rx_get_desc(struct mtk_eth *eth, struct mtk_rx_dma_v2 *rxd,
+ struct mtk_rx_dma_v2 *dma_rxd)
{
rxd->rxd2 = READ_ONCE(dma_rxd->rxd2);
if (!(rxd->rxd2 & RX_DMA_DONE))
@@ -833,16 +833,19 @@
rxd->rxd1 = READ_ONCE(dma_rxd->rxd1);
rxd->rxd3 = READ_ONCE(dma_rxd->rxd3);
rxd->rxd4 = READ_ONCE(dma_rxd->rxd4);
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
- rxd->rxd5 = READ_ONCE(dma_rxd->rxd5);
- rxd->rxd6 = READ_ONCE(dma_rxd->rxd6);
-#endif
+
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
+ rxd->rxd5 = READ_ONCE(dma_rxd->rxd5);
+ rxd->rxd6 = READ_ONCE(dma_rxd->rxd6);
+ }
+
return true;
}
/* the qdma core needs scratch memory to be setup */
static int mtk_init_fq_dma(struct mtk_eth *eth)
{
+ const struct mtk_soc_data *soc = eth->soc;
dma_addr_t phy_ring_tail;
int cnt = MTK_DMA_SIZE;
dma_addr_t dma_addr;
@@ -850,9 +853,9 @@
if (!eth->soc->has_sram) {
eth->scratch_ring = dma_alloc_coherent(eth->dev,
- cnt * sizeof(struct mtk_tx_dma),
+ cnt * soc->txrx.txd_size,
ð->phy_scratch_ring,
- GFP_ATOMIC);
+ GFP_KERNEL);
} else {
eth->scratch_ring = eth->base + MTK_ETH_SRAM_OFFSET;
}
@@ -860,8 +863,7 @@
if (unlikely(!eth->scratch_ring))
return -ENOMEM;
- eth->scratch_head = kcalloc(cnt, MTK_QDMA_PAGE_SIZE,
- GFP_KERNEL);
+ eth->scratch_head = kcalloc(cnt, MTK_QDMA_PAGE_SIZE, GFP_KERNEL);
if (unlikely(!eth->scratch_head))
return -ENOMEM;
@@ -871,26 +873,26 @@
if (unlikely(dma_mapping_error(eth->dev, dma_addr)))
return -ENOMEM;
- phy_ring_tail = eth->phy_scratch_ring +
- (sizeof(struct mtk_tx_dma) * (cnt - 1));
+ phy_ring_tail = eth->phy_scratch_ring + soc->txrx.txd_size * (cnt - 1);
for (i = 0; i < cnt; i++) {
- eth->scratch_ring[i].txd1 =
- (dma_addr + (i * MTK_QDMA_PAGE_SIZE));
+ struct mtk_tx_dma_v2 *txd;
+
+ txd = eth->scratch_ring + i * soc->txrx.txd_size;
+ txd->txd1 = dma_addr + i * MTK_QDMA_PAGE_SIZE;
if (i < cnt - 1)
- eth->scratch_ring[i].txd2 = (eth->phy_scratch_ring +
- ((i + 1) * sizeof(struct mtk_tx_dma)));
- eth->scratch_ring[i].txd3 = TX_DMA_SDL(MTK_QDMA_PAGE_SIZE);
+ txd->txd2 = eth->phy_scratch_ring +
+ (i + 1) * soc->txrx.txd_size;
- eth->scratch_ring[i].txd4 = 0;
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
- if (eth->soc->has_sram && ((sizeof(struct mtk_tx_dma)) > 16)) {
- eth->scratch_ring[i].txd5 = 0;
- eth->scratch_ring[i].txd6 = 0;
- eth->scratch_ring[i].txd7 = 0;
- eth->scratch_ring[i].txd8 = 0;
+ txd->txd3 = TX_DMA_PLEN0(MTK_QDMA_PAGE_SIZE);
+ txd->txd4 = 0;
+
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
+ txd->txd5 = 0;
+ txd->txd6 = 0;
+ txd->txd7 = 0;
+ txd->txd8 = 0;
}
-#endif
}
mtk_w32(eth, eth->phy_scratch_ring, MTK_QDMA_FQ_HEAD);
@@ -903,28 +905,26 @@
static inline void *mtk_qdma_phys_to_virt(struct mtk_tx_ring *ring, u32 desc)
{
- void *ret = ring->dma;
-
- return ret + (desc - ring->phys);
+ return ring->dma + (desc - ring->phys);
}
static inline struct mtk_tx_buf *mtk_desc_to_tx_buf(struct mtk_tx_ring *ring,
- struct mtk_tx_dma *txd)
+ void *txd, u32 txd_size)
{
- int idx = txd - ring->dma;
+ int idx = (txd - ring->dma) / txd_size;
return &ring->buf[idx];
}
static struct mtk_tx_dma *qdma_to_pdma(struct mtk_tx_ring *ring,
- struct mtk_tx_dma *dma)
+ void *dma)
{
return ring->dma_pdma - ring->dma + dma;
}
-static int txd_to_idx(struct mtk_tx_ring *ring, struct mtk_tx_dma *dma)
+static int txd_to_idx(struct mtk_tx_ring *ring, void *dma, u32 txd_size)
{
- return ((void *)dma - (void *)ring->dma) / sizeof(*dma);
+ return (dma - ring->dma) / txd_size;
}
static void mtk_tx_unmap(struct mtk_eth *eth, struct mtk_tx_buf *tx_buf,
@@ -992,20 +992,129 @@
}
}
+static void mtk_tx_set_dma_desc_v1(struct sk_buff *skb, struct net_device *dev, void *txd,
+ struct mtk_tx_dma_desc_info *info)
+{
+ struct mtk_mac *mac = netdev_priv(dev);
+ struct mtk_eth *eth = mac->hw;
+ struct mtk_tx_dma *desc = txd;
+ u32 data;
+
+ WRITE_ONCE(desc->txd1, info->addr);
+
+ data = TX_DMA_SWC | QID_LOW_BITS(info->qid) | TX_DMA_PLEN0(info->size);
+ if (info->last)
+ data |= TX_DMA_LS0;
+ WRITE_ONCE(desc->txd3, data);
+
+ data = (mac->id + 1) << TX_DMA_FPORT_SHIFT; /* forward port */
+ data |= QID_HIGH_BITS(info->qid);
+ if (info->first) {
+ if (info->gso)
+ data |= TX_DMA_TSO;
+ /* tx checksum offload */
+ if (info->csum)
+ data |= TX_DMA_CHKSUM;
+ /* vlan header offload */
+ if (info->vlan)
+ data |= TX_DMA_INS_VLAN | info->vlan_tci;
+ }
+
+#if defined(CONFIG_NET_MEDIATEK_HNAT) || defined(CONFIG_NET_MEDIATEK_HNAT_MODULE)
+ if (HNAT_SKB_CB2(skb)->magic == 0x78681415) {
+ data &= ~(0x7 << TX_DMA_FPORT_SHIFT);
+ data |= 0x4 << TX_DMA_FPORT_SHIFT;
+ }
+
+ trace_printk("[%s] skb_shinfo(skb)->nr_frags=%x HNAT_SKB_CB2(skb)->magic=%x txd4=%x<-----\n",
+ __func__, skb_shinfo(skb)->nr_frags, HNAT_SKB_CB2(skb)->magic, data);
+#endif
+ WRITE_ONCE(desc->txd4, data);
+}
+
+static void mtk_tx_set_dma_desc_v2(struct sk_buff *skb, struct net_device *dev, void *txd,
+ struct mtk_tx_dma_desc_info *info)
+{
+ struct mtk_mac *mac = netdev_priv(dev);
+ struct mtk_eth *eth = mac->hw;
+ struct mtk_tx_dma_v2 *desc = txd;
+ u32 data = 0;
+ u16 qid;
+
+ if(!info->qid && mac->id)
+ qid = MTK_QDMA_GMAC2_QID;
+
+ WRITE_ONCE(desc->txd1, info->addr);
+
+ data = TX_DMA_PLEN0(info->size);
+ if (info->last)
+ data |= TX_DMA_LS0;
+ WRITE_ONCE(desc->txd3, data);
+
+ data = (mac->id + 1) << TX_DMA_FPORT_SHIFT_V2; /* forward port */
+ data |= TX_DMA_SWC_V2 | QID_BITS_V2(qid);
+#if defined(CONFIG_NET_MEDIATEK_HNAT) || defined(CONFIG_NET_MEDIATEK_HNAT_MODULE)
+ if (HNAT_SKB_CB2(skb)->magic == 0x78681415) {
+ data &= ~(0xf << TX_DMA_FPORT_SHIFT_V2);
+ data |= 0x4 << TX_DMA_FPORT_SHIFT_V2;
+ }
+
+ trace_printk("[%s] skb_shinfo(skb)->nr_frags=%x HNAT_SKB_CB2(skb)->magic=%x txd4=%x<-----\n",
+ __func__, skb_shinfo(skb)->nr_frags, HNAT_SKB_CB2(skb)->magic, data);
+#endif
+ WRITE_ONCE(desc->txd4, data);
+
+ data = 0;
+ if (info->first) {
+ if (info->gso)
+ data |= TX_DMA_TSO_V2;
+ /* tx checksum offload */
+ if (info->csum)
+ data |= TX_DMA_CHKSUM_V2;
+ }
+ WRITE_ONCE(desc->txd5, data);
+
+ data = 0;
+ if (info->first && info->vlan)
+ data |= TX_DMA_INS_VLAN_V2 | info->vlan_tci;
+ WRITE_ONCE(desc->txd6, data);
+
+ WRITE_ONCE(desc->txd7, 0);
+ WRITE_ONCE(desc->txd8, 0);
+}
+
+static void mtk_tx_set_dma_desc(struct sk_buff *skb, struct net_device *dev, void *txd,
+ struct mtk_tx_dma_desc_info *info)
+{
+ struct mtk_mac *mac = netdev_priv(dev);
+ struct mtk_eth *eth = mac->hw;
+
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
+ mtk_tx_set_dma_desc_v2(skb, dev, txd, info);
+ else
+ mtk_tx_set_dma_desc_v1(skb, dev, txd, info);
+}
+
static int mtk_tx_map(struct sk_buff *skb, struct net_device *dev,
int tx_num, struct mtk_tx_ring *ring, bool gso)
{
+ struct mtk_tx_dma_desc_info txd_info = {
+ .size = skb_headlen(skb),
+ .qid = skb->mark & MTK_QDMA_TX_MASK,
+ .gso = gso,
+ .csum = skb->ip_summed == CHECKSUM_PARTIAL,
+ .vlan = skb_vlan_tag_present(skb),
+ .vlan_tci = skb_vlan_tag_get(skb),
+ .first = true,
+ .last = !skb_is_nonlinear(skb),
+ };
struct mtk_mac *mac = netdev_priv(dev);
struct mtk_eth *eth = mac->hw;
+ const struct mtk_soc_data *soc = eth->soc;
struct mtk_tx_dma *itxd, *txd;
struct mtk_tx_dma *itxd_pdma, *txd_pdma;
struct mtk_tx_buf *itx_buf, *tx_buf;
- dma_addr_t mapped_addr;
- unsigned int nr_frags;
int i, n_desc = 1;
- u32 txd4 = 0, txd5 = 0, txd6 = 0;
- u32 fport;
- u32 qid = 0;
int k = 0;
itxd = ring->next_free;
@@ -1013,93 +1122,35 @@
if (itxd == ring->last_free)
return -ENOMEM;
- itx_buf = mtk_desc_to_tx_buf(ring, itxd);
+ itx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->txrx.txd_size);
memset(itx_buf, 0, sizeof(*itx_buf));
- mapped_addr = dma_map_single(eth->dev, skb->data,
- skb_headlen(skb), DMA_TO_DEVICE);
- if (unlikely(dma_mapping_error(eth->dev, mapped_addr)))
+ txd_info.addr = dma_map_single(eth->dev, skb->data, txd_info.size,
+ DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(eth->dev, txd_info.addr)))
return -ENOMEM;
+ mtk_tx_set_dma_desc(skb, dev, itxd, &txd_info);
+
- WRITE_ONCE(itxd->txd1, mapped_addr);
itx_buf->flags |= MTK_TX_FLAGS_SINGLE0;
itx_buf->flags |= (!mac->id) ? MTK_TX_FLAGS_FPORT0 :
MTK_TX_FLAGS_FPORT1;
- setup_tx_buf(eth, itx_buf, itxd_pdma, mapped_addr, skb_headlen(skb),
+ setup_tx_buf(eth, itx_buf, itxd_pdma, txd_info.addr, txd_info.size,
k++);
- nr_frags = skb_shinfo(skb)->nr_frags;
-
- qid = skb->mark & (MTK_QDMA_TX_MASK);
-
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
- if(!qid && mac->id)
- qid = MTK_QDMA_GMAC2_QID;
-#endif
-
- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
- /* set the forward port */
- fport = (mac->id + 1) << TX_DMA_FPORT_SHIFT_V2;
- txd4 |= fport;
-
- if (gso)
- txd5 |= TX_DMA_TSO_V2;
-
- /* TX Checksum offload */
- if (skb->ip_summed == CHECKSUM_PARTIAL)
- txd5 |= TX_DMA_CHKSUM_V2;
-
- /* VLAN header offload */
- if (skb_vlan_tag_present(skb))
- txd6 |= TX_DMA_INS_VLAN_V2 | skb_vlan_tag_get(skb);
-
- txd4 = txd4 | TX_DMA_SWC_V2;
- } else {
- /* set the forward port */
- fport = (mac->id + 1) << TX_DMA_FPORT_SHIFT;
- txd4 |= fport;
-
- if (gso)
- txd4 |= TX_DMA_TSO;
-
- /* TX Checksum offload */
- if (skb->ip_summed == CHECKSUM_PARTIAL)
- txd4 |= TX_DMA_CHKSUM;
-
- /* VLAN header offload */
- if (skb_vlan_tag_present(skb))
- txd4 |= TX_DMA_INS_VLAN | skb_vlan_tag_get(skb);
- }
/* TX SG offload */
txd = itxd;
txd_pdma = qdma_to_pdma(ring, txd);
-#if defined(CONFIG_NET_MEDIATEK_HNAT) || defined(CONFIG_NET_MEDIATEK_HNAT_MODULE)
- if (HNAT_SKB_CB2(skb)->magic == 0x78681415) {
- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
- txd4 &= ~(0xf << TX_DMA_FPORT_SHIFT_V2);
- txd4 |= 0x4 << TX_DMA_FPORT_SHIFT_V2;
- } else {
- txd4 &= ~(0x7 << TX_DMA_FPORT_SHIFT);
- txd4 |= 0x4 << TX_DMA_FPORT_SHIFT;
- }
- }
-
- trace_printk("[%s] nr_frags=%x HNAT_SKB_CB2(skb)->magic=%x txd4=%x<-----\n",
- __func__, nr_frags, HNAT_SKB_CB2(skb)->magic, txd4);
-#endif
-
- for (i = 0; i < nr_frags; i++) {
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
unsigned int offset = 0;
int frag_size = skb_frag_size(frag);
while (frag_size) {
- bool last_frag = false;
- unsigned int frag_map_size;
bool new_desc = true;
- if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA) ||
+ if (MTK_HAS_CAPS(soc->caps, MTK_QDMA) ||
(i & 0x1)) {
txd = mtk_qdma_phys_to_virt(ring, txd->txd2);
txd_pdma = qdma_to_pdma(ring, txd);
@@ -1111,35 +1162,20 @@
new_desc = false;
}
+ memset(&txd_info, 0, sizeof(struct mtk_tx_dma_desc_info));
+ txd_info.size = min(frag_size, MTK_TX_DMA_BUF_LEN);
+ txd_info.qid = skb->mark & MTK_QDMA_TX_MASK;
+ txd_info.last = i == skb_shinfo(skb)->nr_frags - 1 &&
+ !(frag_size - txd_info.size);
+ txd_info.addr = skb_frag_dma_map(eth->dev, frag,
+ offset, txd_info.size,
+ DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(eth->dev, txd_info.addr)))
+ goto err_dma;
- frag_map_size = min(frag_size, MTK_TX_DMA_BUF_LEN);
- mapped_addr = skb_frag_dma_map(eth->dev, frag, offset,
- frag_map_size,
- DMA_TO_DEVICE);
- if (unlikely(dma_mapping_error(eth->dev, mapped_addr)))
- goto err_dma;
+ mtk_tx_set_dma_desc(skb, dev, txd, &txd_info);
- if (i == nr_frags - 1 &&
- (frag_size - frag_map_size) == 0)
- last_frag = true;
-
- WRITE_ONCE(txd->txd1, mapped_addr);
-
- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
- WRITE_ONCE(txd->txd3, (TX_DMA_PLEN0(frag_map_size) |
- last_frag * TX_DMA_LS0));
- WRITE_ONCE(txd->txd4, fport | TX_DMA_SWC_V2 |
- QID_BITS_V2(qid));
- } else {
- WRITE_ONCE(txd->txd3,
- (TX_DMA_SWC | QID_LOW_BITS(qid) |
- TX_DMA_PLEN0(frag_map_size) |
- last_frag * TX_DMA_LS0));
- WRITE_ONCE(txd->txd4,
- fport | QID_HIGH_BITS(qid));
- }
-
- tx_buf = mtk_desc_to_tx_buf(ring, txd);
+ tx_buf = mtk_desc_to_tx_buf(ring, txd, soc->txrx.txd_size);
if (new_desc)
memset(tx_buf, 0, sizeof(*tx_buf));
tx_buf->skb = (struct sk_buff *)MTK_DMA_DUMMY_DESC;
@@ -1147,36 +1183,18 @@
tx_buf->flags |= (!mac->id) ? MTK_TX_FLAGS_FPORT0 :
MTK_TX_FLAGS_FPORT1;
- setup_tx_buf(eth, tx_buf, txd_pdma, mapped_addr,
- frag_map_size, k++);
+ setup_tx_buf(eth, tx_buf, txd_pdma, txd_info.addr,
+ txd_info.size, k++);
- frag_size -= frag_map_size;
- offset += frag_map_size;
+ frag_size -= txd_info.size;
+ offset += txd_info.size;
}
}
/* store skb to cleanup */
itx_buf->skb = skb;
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
- WRITE_ONCE(itxd->txd5, txd5);
- WRITE_ONCE(itxd->txd6, txd6);
- WRITE_ONCE(itxd->txd7, 0);
- WRITE_ONCE(itxd->txd8, 0);
-#endif
-
- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
- WRITE_ONCE(itxd->txd4, txd4 | QID_BITS_V2(qid));
- WRITE_ONCE(itxd->txd3, (TX_DMA_PLEN0(skb_headlen(skb)) |
- (!nr_frags * TX_DMA_LS0)));
- } else {
- WRITE_ONCE(itxd->txd4, txd4 | QID_HIGH_BITS(qid));
- WRITE_ONCE(itxd->txd3,
- TX_DMA_SWC | TX_DMA_PLEN0(skb_headlen(skb)) |
- (!nr_frags * TX_DMA_LS0) | QID_LOW_BITS(qid));
- }
-
- if (!MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) {
+ if (!MTK_HAS_CAPS(soc->caps, MTK_QDMA)) {
if (k & 0x1)
txd_pdma->txd2 |= TX_DMA_LS0;
else
@@ -1194,12 +1212,12 @@
*/
wmb();
- if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) {
+ if (MTK_HAS_CAPS(soc->caps, MTK_QDMA)) {
if (netif_xmit_stopped(netdev_get_tx_queue(dev, 0)) ||
!netdev_xmit_more())
mtk_w32(eth, txd->txd2, MTK_QTX_CTX_PTR);
} else {
- int next_idx = NEXT_DESP_IDX(txd_to_idx(ring, txd),
+ int next_idx = NEXT_DESP_IDX(txd_to_idx(ring, txd, soc->txrx.txd_size),
ring->dma_size);
mtk_w32(eth, next_idx, MT7628_TX_CTX_IDX0);
}
@@ -1208,13 +1226,13 @@
err_dma:
do {
- tx_buf = mtk_desc_to_tx_buf(ring, itxd);
+ tx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->txrx.txd_size);
/* unmap dma */
mtk_tx_unmap(eth, tx_buf, false);
itxd->txd3 = TX_DMA_LS0 | TX_DMA_OWNER_CPU;
- if (!MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA))
+ if (!MTK_HAS_CAPS(soc->caps, MTK_QDMA))
itxd_pdma->txd2 = TX_DMA_DESP2_DEF;
itxd = mtk_qdma_phys_to_virt(ring, itxd->txd2);
@@ -1334,12 +1352,15 @@
int idx;
for (i = 0; i < MTK_MAX_RX_RING_NUM; i++) {
+ struct mtk_rx_dma *rxd;
+
if (!IS_NORMAL_RING(i) && !IS_HW_LRO_RING(i))
continue;
ring = ð->rx_ring[i];
idx = NEXT_DESP_IDX(ring->calc_idx, ring->dma_size);
- if (ring->dma[idx].rxd2 & RX_DMA_DONE) {
+ rxd = ring->dma + idx * eth->soc->txrx.rxd_size;
+ if (rxd->rxd2 & RX_DMA_DONE) {
ring->calc_idx_update = true;
return ring;
}
@@ -1373,7 +1394,7 @@
int idx;
struct sk_buff *skb;
u8 *data, *new_data;
- struct mtk_rx_dma *rxd, trxd;
+ struct mtk_rx_dma_v2 *rxd, trxd;
int done = 0;
if (unlikely(!ring))
@@ -1383,7 +1404,7 @@
struct net_device *netdev;
unsigned int pktlen;
dma_addr_t dma_addr;
- int mac;
+ int mac = 0;
if (eth->hwlro)
ring = mtk_get_rx_ring(eth);
@@ -1392,21 +1413,19 @@
goto rx_done;
idx = NEXT_DESP_IDX(ring->calc_idx, ring->dma_size);
- rxd = &ring->dma[idx];
+ rxd = ring->dma + idx * eth->soc->txrx.rxd_size;
data = ring->data[idx];
- if (!mtk_rx_get_desc(&trxd, rxd))
+ if (!mtk_rx_get_desc(eth, &trxd, rxd))
break;
/* find out which mac the packet come from. values start at 1 */
if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628)) {
mac = 0;
} else {
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
- mac = RX_DMA_GET_SPORT(trxd.rxd5) - 1;
+ mac = RX_DMA_GET_SPORT_V2(trxd.rxd5) - 1;
else
-#endif
mac = (trxd.rxd4 & RX_DMA_SPECIAL_TAG) ?
0 : RX_DMA_GET_SPORT(trxd.rxd4) - 1;
}
@@ -1486,11 +1505,9 @@
}
#if defined(CONFIG_NET_MEDIATEK_HNAT) || defined(CONFIG_NET_MEDIATEK_HNAT_MODULE)
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
*(u32 *)(skb->head) = trxd.rxd5;
else
-#endif
*(u32 *)(skb->head) = trxd.rxd4;
skb_hnat_alg(skb) = 0;
@@ -1546,6 +1563,7 @@
static void mtk_poll_tx_qdma(struct mtk_eth *eth, int budget,
unsigned int *done, unsigned int *bytes)
{
+ const struct mtk_soc_data *soc = eth->soc;
struct mtk_tx_ring *ring = ð->tx_ring;
struct mtk_tx_dma *desc;
struct sk_buff *skb;
@@ -1566,7 +1584,7 @@
desc = mtk_qdma_phys_to_virt(ring, desc->txd2);
- tx_buf = mtk_desc_to_tx_buf(ring, desc);
+ tx_buf = mtk_desc_to_tx_buf(ring, desc, soc->txrx.txd_size);
if (tx_buf->flags & MTK_TX_FLAGS_FPORT1)
mac = 1;
@@ -1617,7 +1635,7 @@
mtk_tx_unmap(eth, tx_buf, true);
- desc = &ring->dma[cpu];
+ desc = ring->dma + cpu * eth->soc->txrx.txd_size;
ring->last_free = desc;
atomic_inc(&ring->free_count);
@@ -1738,8 +1756,10 @@
static int mtk_tx_alloc(struct mtk_eth *eth)
{
+ const struct mtk_soc_data *soc = eth->soc;
struct mtk_tx_ring *ring = ð->tx_ring;
- int i, sz = sizeof(*ring->dma);
+ int i, sz = soc->txrx.txd_size;
+ struct mtk_tx_dma_v2 *txd, *pdma_txd;
ring->buf = kcalloc(MTK_DMA_SIZE, sizeof(*ring->buf),
GFP_KERNEL);
@@ -1748,9 +1768,9 @@
if (!eth->soc->has_sram)
ring->dma = dma_alloc_coherent(eth->dev, MTK_DMA_SIZE * sz,
- &ring->phys, GFP_ATOMIC);
+ &ring->phys, GFP_KERNEL);
else {
- ring->dma = eth->scratch_ring + MTK_DMA_SIZE;
+ ring->dma = eth->scratch_ring + MTK_DMA_SIZE * sz;
ring->phys = eth->phy_scratch_ring + MTK_DMA_SIZE * sz;
}
@@ -1761,17 +1781,17 @@
int next = (i + 1) % MTK_DMA_SIZE;
u32 next_ptr = ring->phys + next * sz;
- ring->dma[i].txd2 = next_ptr;
- ring->dma[i].txd3 = TX_DMA_LS0 | TX_DMA_OWNER_CPU;
- ring->dma[i].txd4 = 0;
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
- if (eth->soc->has_sram && ( sz > 16)) {
- ring->dma[i].txd5 = 0;
- ring->dma[i].txd6 = 0;
- ring->dma[i].txd7 = 0;
- ring->dma[i].txd8 = 0;
- }
-#endif
+ txd = ring->dma + i * sz;
+ txd->txd2 = next_ptr;
+ txd->txd3 = TX_DMA_LS0 | TX_DMA_OWNER_CPU;
+ txd->txd4 = 0;
+
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
+ txd->txd5 = 0;
+ txd->txd6 = 0;
+ txd->txd7 = 0;
+ txd->txd8 = 0;
+ }
}
/* On MT7688 (PDMA only) this driver uses the ring->dma structs
@@ -1780,21 +1800,22 @@
*/
if (!MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) {
ring->dma_pdma = dma_alloc_coherent(eth->dev, MTK_DMA_SIZE * sz,
- &ring->phys_pdma,
- GFP_ATOMIC);
+ &ring->phys_pdma, GFP_KERNEL);
if (!ring->dma_pdma)
goto no_tx_mem;
for (i = 0; i < MTK_DMA_SIZE; i++) {
- ring->dma_pdma[i].txd2 = TX_DMA_DESP2_DEF;
- ring->dma_pdma[i].txd4 = 0;
+ pdma_txd = ring->dma_pdma + i *sz;
+
+ pdma_txd->txd2 = TX_DMA_DESP2_DEF;
+ pdma_txd->txd4 = 0;
}
}
ring->dma_size = MTK_DMA_SIZE;
atomic_set(&ring->free_count, MTK_DMA_SIZE - 2);
- ring->next_free = &ring->dma[0];
- ring->last_free = &ring->dma[MTK_DMA_SIZE - 1];
+ ring->next_free = ring->dma;
+ ring->last_free = (void *)txd;
ring->last_free_ptr = (u32)(ring->phys + ((MTK_DMA_SIZE - 1) * sz));
ring->thresh = MAX_SKB_FRAGS;
@@ -1827,6 +1848,7 @@
static void mtk_tx_clean(struct mtk_eth *eth)
{
+ const struct mtk_soc_data *soc = eth->soc;
struct mtk_tx_ring *ring = ð->tx_ring;
int i;
@@ -1839,17 +1861,15 @@
if (!eth->soc->has_sram && ring->dma) {
dma_free_coherent(eth->dev,
- MTK_DMA_SIZE * sizeof(*ring->dma),
- ring->dma,
- ring->phys);
+ MTK_DMA_SIZE * soc->txrx.txd_size,
+ ring->dma, ring->phys);
ring->dma = NULL;
}
if (ring->dma_pdma) {
dma_free_coherent(eth->dev,
- MTK_DMA_SIZE * sizeof(*ring->dma_pdma),
- ring->dma_pdma,
- ring->phys_pdma);
+ MTK_DMA_SIZE * soc->txrx.txd_size,
+ ring->dma_pdma, ring->phys_pdma);
ring->dma_pdma = NULL;
}
}
@@ -1892,43 +1912,46 @@
if ((!eth->soc->has_sram) || (eth->soc->has_sram
&& (rx_flag != MTK_RX_FLAGS_NORMAL)))
ring->dma = dma_alloc_coherent(eth->dev,
- rx_dma_size * sizeof(*ring->dma),
- &ring->phys, GFP_ATOMIC);
+ rx_dma_size * eth->soc->txrx.rxd_size,
+ &ring->phys, GFP_KERNEL);
else {
struct mtk_tx_ring *tx_ring = ð->tx_ring;
- ring->dma = (struct mtk_rx_dma *)(tx_ring->dma +
- MTK_DMA_SIZE * (ring_no + 1));
+ ring->dma = tx_ring->dma + MTK_DMA_SIZE *
+ eth->soc->txrx.rxd_size * (ring_no + 1);
ring->phys = tx_ring->phys + MTK_DMA_SIZE *
- sizeof(*tx_ring->dma) * (ring_no + 1);
+ eth->soc->txrx.rxd_size * (ring_no + 1);
}
if (!ring->dma)
return -ENOMEM;
for (i = 0; i < rx_dma_size; i++) {
+ struct mtk_rx_dma_v2 *rxd;
+
dma_addr_t dma_addr = dma_map_single(eth->dev,
ring->data[i] + NET_SKB_PAD + eth->ip_align,
ring->buf_size,
DMA_FROM_DEVICE);
if (unlikely(dma_mapping_error(eth->dev, dma_addr)))
return -ENOMEM;
- ring->dma[i].rxd1 = (unsigned int)dma_addr;
+
+ rxd = ring->dma + i * eth->soc->txrx.rxd_size;
+ rxd->rxd1 = (unsigned int)dma_addr;
if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628))
- ring->dma[i].rxd2 = RX_DMA_LSO;
+ rxd->rxd2 = RX_DMA_LSO;
else
- ring->dma[i].rxd2 = RX_DMA_PLEN0(ring->buf_size);
+ rxd->rxd2 = RX_DMA_PLEN0(ring->buf_size);
- ring->dma[i].rxd3 = 0;
- ring->dma[i].rxd4 = 0;
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
- if (eth->soc->has_sram && ((sizeof(struct mtk_rx_dma)) > 16)) {
- ring->dma[i].rxd5 = 0;
- ring->dma[i].rxd6 = 0;
- ring->dma[i].rxd7 = 0;
- ring->dma[i].rxd8 = 0;
+ rxd->rxd3 = 0;
+ rxd->rxd4 = 0;
+
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
+ rxd->rxd5 = 0;
+ rxd->rxd6 = 0;
+ rxd->rxd7 = 0;
+ rxd->rxd8 = 0;
}
-#endif
}
ring->dma_size = rx_dma_size;
ring->calc_idx_update = false;
@@ -1963,12 +1986,17 @@
if (ring->data && ring->dma) {
for (i = 0; i < ring->dma_size; i++) {
+ struct mtk_rx_dma *rxd;
+
if (!ring->data[i])
continue;
- if (!ring->dma[i].rxd1)
+
+ rxd = ring->dma + i * eth->soc->txrx.rxd_size;
+ if (!rxd->rxd1)
continue;
+
dma_unmap_single(eth->dev,
- ring->dma[i].rxd1,
+ rxd->rxd1,
ring->buf_size,
DMA_FROM_DEVICE);
skb_free_frag(ring->data[i]);
@@ -1982,7 +2010,7 @@
if (ring->dma) {
dma_free_coherent(eth->dev,
- ring->dma_size * sizeof(*ring->dma),
+ ring->dma_size * eth->soc->txrx.rxd_size,
ring->dma,
ring->phys);
ring->dma = NULL;
@@ -2455,6 +2483,7 @@
static void mtk_dma_free(struct mtk_eth *eth)
{
+ const struct mtk_soc_data *soc = eth->soc;
int i;
for (i = 0; i < MTK_MAC_COUNT; i++)
@@ -2462,9 +2491,8 @@
netdev_reset_queue(eth->netdev[i]);
if ( !eth->soc->has_sram && eth->scratch_ring) {
dma_free_coherent(eth->dev,
- MTK_DMA_SIZE * sizeof(struct mtk_tx_dma),
- eth->scratch_ring,
- eth->phy_scratch_ring);
+ MTK_DMA_SIZE * soc->txrx.txd_size,
+ eth->scratch_ring, eth->phy_scratch_ring);
eth->scratch_ring = NULL;
eth->phy_scratch_ring = 0;
}
@@ -3873,6 +3901,12 @@
.required_clks = MT7623_CLKS_BITMAP,
.required_pctl = true,
.has_sram = false,
+ .txrx = {
+ .txd_size = sizeof(struct mtk_tx_dma),
+ .rxd_size = sizeof(struct mtk_rx_dma),
+ .dma_max_len = MTK_TX_DMA_BUF_LEN,
+ .dma_len_offset = MTK_TX_DMA_BUF_SHIFT,
+ },
};
static const struct mtk_soc_data mt7621_data = {
@@ -3881,6 +3915,12 @@
.required_clks = MT7621_CLKS_BITMAP,
.required_pctl = false,
.has_sram = false,
+ .txrx = {
+ .txd_size = sizeof(struct mtk_tx_dma),
+ .rxd_size = sizeof(struct mtk_rx_dma),
+ .dma_max_len = MTK_TX_DMA_BUF_LEN,
+ .dma_len_offset = MTK_TX_DMA_BUF_SHIFT,
+ },
};
static const struct mtk_soc_data mt7622_data = {
@@ -3890,6 +3930,12 @@
.required_clks = MT7622_CLKS_BITMAP,
.required_pctl = false,
.has_sram = false,
+ .txrx = {
+ .txd_size = sizeof(struct mtk_tx_dma),
+ .rxd_size = sizeof(struct mtk_rx_dma),
+ .dma_max_len = MTK_TX_DMA_BUF_LEN,
+ .dma_len_offset = MTK_TX_DMA_BUF_SHIFT,
+ },
};
static const struct mtk_soc_data mt7623_data = {
@@ -3898,6 +3944,12 @@
.required_clks = MT7623_CLKS_BITMAP,
.required_pctl = true,
.has_sram = false,
+ .txrx = {
+ .txd_size = sizeof(struct mtk_tx_dma),
+ .rxd_size = sizeof(struct mtk_rx_dma),
+ .dma_max_len = MTK_TX_DMA_BUF_LEN,
+ .dma_len_offset = MTK_TX_DMA_BUF_SHIFT,
+ },
};
static const struct mtk_soc_data mt7629_data = {
@@ -3907,6 +3959,12 @@
.required_clks = MT7629_CLKS_BITMAP,
.required_pctl = false,
.has_sram = false,
+ .txrx = {
+ .txd_size = sizeof(struct mtk_tx_dma),
+ .rxd_size = sizeof(struct mtk_rx_dma),
+ .dma_max_len = MTK_TX_DMA_BUF_LEN,
+ .dma_len_offset = MTK_TX_DMA_BUF_SHIFT,
+ },
};
static const struct mtk_soc_data mt7986_data = {
@@ -3916,6 +3974,12 @@
.required_clks = MT7986_CLKS_BITMAP,
.required_pctl = false,
.has_sram = true,
+ .txrx = {
+ .txd_size = sizeof(struct mtk_tx_dma_v2),
+ .rxd_size = sizeof(struct mtk_rx_dma_v2),
+ .dma_max_len = MTK_TX_DMA_BUF_LEN_V2,
+ .dma_len_offset = MTK_TX_DMA_BUF_SHIFT_V2,
+ },
};
static const struct mtk_soc_data mt7981_data = {
@@ -3925,6 +3989,12 @@
.required_clks = MT7981_CLKS_BITMAP,
.required_pctl = false,
.has_sram = true,
+ .txrx = {
+ .txd_size = sizeof(struct mtk_tx_dma_v2),
+ .rxd_size = sizeof(struct mtk_rx_dma_v2),
+ .dma_max_len = MTK_TX_DMA_BUF_LEN_V2,
+ .dma_len_offset = MTK_TX_DMA_BUF_SHIFT_V2,
+ },
};
static const struct mtk_soc_data rt5350_data = {
@@ -3933,6 +4003,12 @@
.required_clks = MT7628_CLKS_BITMAP,
.required_pctl = false,
.has_sram = false,
+ .txrx = {
+ .txd_size = sizeof(struct mtk_tx_dma),
+ .rxd_size = sizeof(struct mtk_rx_dma),
+ .dma_max_len = MTK_TX_DMA_BUF_LEN,
+ .dma_len_offset = MTK_TX_DMA_BUF_SHIFT,
+ },
};
const struct of_device_id of_mtk_match[] = {
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 88f9280..7fa0db8 100755
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -494,25 +494,15 @@
#define TX_DMA_FPORT_MASK_V2 0xf
#define TX_DMA_SWC_V2 BIT(30)
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
-#define MTK_TX_DMA_BUF_LEN 0xffff
-#define MTK_TX_DMA_BUF_SHIFT 8
-#else
#define MTK_TX_DMA_BUF_LEN 0x3fff
+#define MTK_TX_DMA_BUF_LEN_V2 0xffff
#define MTK_TX_DMA_BUF_SHIFT 16
-#endif
+#define MTK_TX_DMA_BUF_SHIFT_V2 8
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
-#define MTK_RX_DMA_BUF_LEN 0xffff
-#define MTK_RX_DMA_BUF_SHIFT 8
-#define RX_DMA_SPORT_SHIFT 26
-#define RX_DMA_SPORT_MASK 0xf
-#else
-#define MTK_RX_DMA_BUF_LEN 0x3fff
-#define MTK_RX_DMA_BUF_SHIFT 16
#define RX_DMA_SPORT_SHIFT 19
+#define RX_DMA_SPORT_SHIFT_V2 26
#define RX_DMA_SPORT_MASK 0x7
-#endif
+#define RX_DMA_SPORT_MASK_V2 0xf
/* QDMA descriptor txd4 */
#define TX_DMA_CHKSUM (0x7 << 29)
@@ -524,10 +514,9 @@
/* QDMA descriptor txd3 */
#define TX_DMA_OWNER_CPU BIT(31)
#define TX_DMA_LS0 BIT(30)
-#define TX_DMA_PLEN0(_x) (((_x) & MTK_TX_DMA_BUF_LEN) << MTK_TX_DMA_BUF_SHIFT)
-#define TX_DMA_PLEN1(_x) ((_x) & MTK_TX_DMA_BUF_LEN)
+#define TX_DMA_PLEN0(_x) (((_x) & eth->soc->txrx.dma_max_len) << eth->soc->txrx.dma_len_offset)
+#define TX_DMA_PLEN1(_x) ((_x) & eth->soc->txrx.dma_max_len)
#define TX_DMA_SWC BIT(14)
-#define TX_DMA_SDL(_x) (TX_DMA_PLEN0(_x))
/* PDMA on MT7628 */
#define TX_DMA_DONE BIT(31)
@@ -537,8 +526,8 @@
/* QDMA descriptor rxd2 */
#define RX_DMA_DONE BIT(31)
#define RX_DMA_LSO BIT(30)
-#define RX_DMA_PLEN0(_x) (((_x) & MTK_RX_DMA_BUF_LEN) << MTK_RX_DMA_BUF_SHIFT)
-#define RX_DMA_GET_PLEN0(_x) (((_x) >> MTK_RX_DMA_BUF_SHIFT) & MTK_RX_DMA_BUF_LEN)
+#define RX_DMA_PLEN0(_x) (((_x) & eth->soc->txrx.dma_max_len) << eth->soc->txrx.dma_len_offset)
+#define RX_DMA_GET_PLEN0(_x) (((_x) >> eth->soc->txrx.dma_len_offset) & eth->soc->txrx.dma_max_len)
#define RX_DMA_GET_AGG_CNT(_x) (((_x) >> 2) & 0xff)
#define RX_DMA_GET_REV(_x) (((_x) >> 10) & 0x1f)
#define RX_DMA_VTAG BIT(15)
@@ -554,6 +543,7 @@
#define RX_DMA_SPECIAL_TAG BIT(22) /* switch header in packet */
#define RX_DMA_GET_SPORT(_x) (((_x) >> RX_DMA_SPORT_SHIFT) & RX_DMA_SPORT_MASK)
+#define RX_DMA_GET_SPORT_V2(_x) (((_x) >> RX_DMA_SPORT_SHIFT_V2) & RX_DMA_SPORT_MASK_V2)
/* PDMA V2 descriptor rxd3 */
#define RX_DMA_VTAG_V2 BIT(0)
@@ -774,12 +764,17 @@
unsigned int rxd2;
unsigned int rxd3;
unsigned int rxd4;
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
+} __packed __aligned(4);
+
+struct mtk_rx_dma_v2 {
+ unsigned int rxd1;
+ unsigned int rxd2;
+ unsigned int rxd3;
+ unsigned int rxd4;
unsigned int rxd5;
unsigned int rxd6;
unsigned int rxd7;
unsigned int rxd8;
-#endif
} __packed __aligned(4);
struct mtk_tx_dma {
@@ -787,12 +782,17 @@
unsigned int txd2;
unsigned int txd3;
unsigned int txd4;
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
+} __packed __aligned(4);
+
+struct mtk_tx_dma_v2 {
+ unsigned int txd1;
+ unsigned int txd2;
+ unsigned int txd3;
+ unsigned int txd4;
unsigned int txd5;
unsigned int txd6;
unsigned int txd7;
unsigned int txd8;
-#endif
} __packed __aligned(4);
struct mtk_eth;
@@ -951,16 +951,16 @@
* are present
*/
struct mtk_tx_ring {
- struct mtk_tx_dma *dma;
+ void *dma;
struct mtk_tx_buf *buf;
dma_addr_t phys;
- struct mtk_tx_dma *next_free;
- struct mtk_tx_dma *last_free;
+ void *next_free;
+ void *last_free;
u32 last_free_ptr;
u16 thresh;
atomic_t free_count;
int dma_size;
- struct mtk_tx_dma *dma_pdma; /* For MT7628/88 PDMA handling */
+ void *dma_pdma; /* For MT7628/88 PDMA handling */
dma_addr_t phys_pdma;
int cpu_idx;
};
@@ -982,7 +982,7 @@
* @ring_no: The index of ring
*/
struct mtk_rx_ring {
- struct mtk_rx_dma *dma;
+ void *dma;
u8 **data;
dma_addr_t phys;
u16 frag_size;
@@ -1143,6 +1143,18 @@
MTK_MUX_U3_GMAC2_TO_QPHY | MTK_U3_COPHY_V2 | \
MTK_NETSYS_V2)
+struct mtk_tx_dma_desc_info {
+ dma_addr_t addr;
+ u32 size;
+ u16 vlan_tci;
+ u16 qid;
+ u8 gso:1;
+ u8 csum:1;
+ u8 vlan:1;
+ u8 first:1;
+ u8 last:1;
+};
+
/* struct mtk_eth_data - This is the structure holding all differences
* among various plaforms
* @ana_rgc3: The offset for register ANA_RGC3 related to
@@ -1153,6 +1165,10 @@
* the target SoC
* @required_pctl A bool value to show whether the SoC requires
* the extra setup for those pins used by GMAC.
+ * @txd_size Tx DMA descriptor size.
+ * @rxd_size Rx DMA descriptor size.
+ * @dma_max_len Max DMA tx/rx buffer length.
+ * @dma_len_offset Tx/Rx DMA length field offset.
*/
struct mtk_soc_data {
u32 ana_rgc3;
@@ -1161,6 +1177,12 @@
bool required_pctl;
netdev_features_t hw_features;
bool has_sram;
+ struct {
+ u32 txd_size;
+ u32 rxd_size;
+ u32 dma_max_len;
+ u32 dma_len_offset;
+ } txrx;
};
/* currently no SoC has more than 2 macs */
@@ -1269,7 +1291,7 @@
struct mtk_rx_ring rx_ring_qdma;
struct napi_struct tx_napi;
struct mtk_napi rx_napi[MTK_RX_NAPI_NUM];
- struct mtk_tx_dma *scratch_ring;
+ void *scratch_ring;
struct mtk_reset_event reset_event;
dma_addr_t phy_scratch_ring;
void *scratch_head;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9990-mt7622-backport-nf-hw-offload-framework-and-ups.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9990-mt7622-backport-nf-hw-offload-framework-and-ups.patch
index 6b40b56..e2cb03b 100755
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9990-mt7622-backport-nf-hw-offload-framework-and-ups.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9990-mt7622-backport-nf-hw-offload-framework-and-ups.patch
@@ -130,35 +130,59 @@
for (i = 0; i < MTK_MAX_DEVS; i++) {
if (!eth->netdev[i])
continue;
-@@ -3781,6 +3801,7 @@ static const struct mtk_soc_data mt2701_data = {
+@@ -3781,12 +3801,13 @@ static const struct mtk_soc_data mt2701_data = {
.required_clks = MT7623_CLKS_BITMAP,
.required_pctl = true,
.has_sram = false,
+ .offload_version = 2,
+ .txrx = {
+ .txd_size = sizeof(struct mtk_tx_dma),
+ .rxd_size = sizeof(struct mtk_rx_dma),
+ .dma_max_len = MTK_TX_DMA_BUF_LEN,
+ .dma_len_offset = MTK_TX_DMA_BUF_SHIFT,
+ },
};
static const struct mtk_soc_data mt7621_data = {
-@@ -3789,6 +3810,7 @@ static const struct mtk_soc_data mt7621_data = {
+@@ -3789,12 +3810,13 @@ static const struct mtk_soc_data mt7621_data = {
.required_clks = MT7621_CLKS_BITMAP,
.required_pctl = false,
.has_sram = false,
+ .offload_version = 2,
+ .txrx = {
+ .txd_size = sizeof(struct mtk_tx_dma),
+ .rxd_size = sizeof(struct mtk_rx_dma),
+ .dma_max_len = MTK_TX_DMA_BUF_LEN,
+ .dma_len_offset = MTK_TX_DMA_BUF_SHIFT,
+ },
};
static const struct mtk_soc_data mt7622_data = {
-@@ -3798,6 +3820,7 @@ static const struct mtk_soc_data mt7622_data = {
+@@ -3798,12 +3820,13 @@ static const struct mtk_soc_data mt7622_data = {
.required_clks = MT7622_CLKS_BITMAP,
.required_pctl = false,
.has_sram = false,
+ .offload_version = 2,
+ .txrx = {
+ .txd_size = sizeof(struct mtk_tx_dma),
+ .rxd_size = sizeof(struct mtk_rx_dma),
+ .dma_max_len = MTK_TX_DMA_BUF_LEN,
+ .dma_len_offset = MTK_TX_DMA_BUF_SHIFT,
+ },
};
static const struct mtk_soc_data mt7623_data = {
-@@ -3806,6 +3829,7 @@ static const struct mtk_soc_data mt7623_data = {
+@@ -3806,12 +3829,13 @@ static const struct mtk_soc_data mt7623_data = {
.required_clks = MT7623_CLKS_BITMAP,
.required_pctl = true,
.has_sram = false,
+ .offload_version = 2,
+ .txrx = {
+ .txd_size = sizeof(struct mtk_tx_dma),
+ .rxd_size = sizeof(struct mtk_rx_dma),
+ .dma_max_len = MTK_TX_DMA_BUF_LEN,
+ .dma_len_offset = MTK_TX_DMA_BUF_SHIFT,
+ },
};
static const struct mtk_soc_data mt7629_data = {
@@ -6114,7 +6138,7 @@
index 000000000..ae1eb2656
--- /dev/null
+++ b/net/netfilter/xt_FLOWOFFLOAD.c
-@@ -0,0 +1,719 @@
+@@ -0,0 +1,728 @@
+/*
+ * Copyright (C) 2018-2021 Felix Fietkau <nbd@nbd.name>
+ *
@@ -6585,17 +6609,24 @@
+ devs[!dir]->ifindex,
+ devs);
+ if (ret)
-+ return ret;
++ goto err_route_dir1;
+
+ if (route->tuple[dir].xmit_type == FLOW_OFFLOAD_XMIT_NEIGH &&
+ route->tuple[!dir].xmit_type == FLOW_OFFLOAD_XMIT_NEIGH) {
-+ if (nf_dev_forward_path(route, ct, dir, devs))
-+ return -1;
-+ if (nf_dev_forward_path(route, ct, !dir, devs))
-+ return -1;
++ if (nf_dev_forward_path(route, ct, dir, devs) ||
++ nf_dev_forward_path(route, ct, !dir, devs)) {
++ ret = -1;
++ goto err_route_dir2;
++ }
+ }
+
+ return 0;
++
++err_route_dir2:
++ dst_release(route->tuple[!dir].dst);
++err_route_dir1:
++ dst_release(route->tuple[dir].dst);
++ return ret;
+}
+
+static unsigned int
@@ -6680,6 +6711,7 @@
+ xt_flowoffload_check_device(table, devs[0]);
+ xt_flowoffload_check_device(table, devs[1]);
+
++ dst_release(route.tuple[dir].dst);
+ dst_release(route.tuple[!dir].dst);
+
+ return XT_CONTINUE;
@@ -6687,6 +6719,7 @@
+err_flow_add:
+ flow_offload_free(flow);
+err_flow_alloc:
++ dst_release(route.tuple[dir].dst);
+ dst_release(route.tuple[!dir].dst);
+err_flow_route:
+ clear_bit(IPS_OFFLOAD_BIT, &ct->status);
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9993-add-wed.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9993-add-wed.patch
index 42a9077..66c497d 100755
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9993-add-wed.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9993-add-wed.patch
@@ -168,7 +168,7 @@
if (!eth->soc->has_sram) {
- eth->scratch_ring = dma_alloc_coherent(eth->dev,
+ eth->scratch_ring = dma_alloc_coherent(eth->dma_dev,
- cnt * sizeof(struct mtk_tx_dma),
+ cnt * soc->txrx.txd_size,
ð->phy_scratch_ring,
GFP_ATOMIC);
@@ -866,10 +869,10 @@ static int mtk_init_fq_dma(struct mtk_eth *eth)
@@ -219,33 +219,33 @@
itx_buf = mtk_desc_to_tx_buf(ring, itxd);
memset(itx_buf, 0, sizeof(*itx_buf));
-- mapped_addr = dma_map_single(eth->dev, skb->data,
-+ mapped_addr = dma_map_single(eth->dma_dev, skb->data,
- skb_headlen(skb), DMA_TO_DEVICE);
-- if (unlikely(dma_mapping_error(eth->dev, mapped_addr)))
-+ if (unlikely(dma_mapping_error(eth->dma_dev, mapped_addr)))
+- txd_info.addr = dma_map_single(eth->dev, skb->data, txd_info.size,
++ txd_info.addr = dma_map_single(eth->dma_dev, skb->data, txd_info.size,
+ DMA_TO_DEVICE);
+- if (unlikely(dma_mapping_error(eth->dev, txd_info.addr)))
++ if (unlikely(dma_mapping_error(eth->dma_dev, txd_info.addr)))
return -ENOMEM;
WRITE_ONCE(itxd->txd1, mapped_addr);
@@ -1114,10 +1117,10 @@ static int mtk_tx_map(struct sk_buff *skb, struct net_device *dev,
-
+ txd_info.qid = skb->mark & MTK_QDMA_TX_MASK;
+ txd_info.last = i == skb_shinfo(skb)->nr_frags - 1 &&
+ !(frag_size - txd_info.size);
+- txd_info.addr = skb_frag_dma_map(eth->dev, frag,
++ txd_info.addr = skb_frag_dma_map(eth->dma_dev, frag,
+ offset, txd_info.size,
+ DMA_TO_DEVICE);
+- if (unlikely(dma_mapping_error(eth->dev, txd_info.addr)))
++ if (unlikely(dma_mapping_error(eth->dma_dev, txd_info.addr)))
+ goto err_dma;
- frag_map_size = min(frag_size, MTK_TX_DMA_BUF_LEN);
-- mapped_addr = skb_frag_dma_map(eth->dev, frag, offset,
-+ mapped_addr = skb_frag_dma_map(eth->dma_dev, frag, offset,
- frag_map_size,
- DMA_TO_DEVICE);
-- if (unlikely(dma_mapping_error(eth->dev, mapped_addr)))
-+ if (unlikely(dma_mapping_error(eth->dma_dev, mapped_addr)))
- goto err_dma;
-
- if (i == nr_frags - 1 &&
+ mtk_tx_set_dma_desc(skb, dev, txd, &txd_info);
@@ -1384,6 +1387,7 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
struct net_device *netdev;
unsigned int pktlen;
dma_addr_t dma_addr;
+ u32 hash, reason;
- int mac;
+ int mac = 0;
if (eth->hwlro)
@@ -1427,18 +1431,18 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
@@ -294,49 +294,48 @@
if (!eth->soc->has_sram)
- ring->dma = dma_alloc_coherent(eth->dev, MTK_DMA_SIZE * sz,
+ ring->dma = dma_alloc_coherent(eth->dma_dev, MTK_DMA_SIZE * sz,
- &ring->phys, GFP_ATOMIC);
+ &ring->phys, GFP_KERNEL);
else {
ring->dma = eth->scratch_ring + MTK_DMA_SIZE;
-@@ -1780,7 +1795,7 @@ static int mtk_tx_alloc(struct mtk_eth *eth)
+@@ -1780,6 +1795,6 @@ static int mtk_tx_alloc(struct mtk_eth *eth)
* descriptors in ring->dma_pdma.
*/
if (!MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) {
- ring->dma_pdma = dma_alloc_coherent(eth->dev, MTK_DMA_SIZE * sz,
+ ring->dma_pdma = dma_alloc_coherent(eth->dma_dev, MTK_DMA_SIZE * sz,
- &ring->phys_pdma,
- GFP_ATOMIC);
+ &ring->phys_pdma, GFP_KERNEL);
if (!ring->dma_pdma)
-@@ -1839,7 +1854,7 @@ static void mtk_tx_clean(struct mtk_eth *eth)
+@@ -1839,6 +1854,6 @@ static void mtk_tx_clean(struct mtk_eth *eth)
}
if (!eth->soc->has_sram && ring->dma) {
- dma_free_coherent(eth->dev,
+ dma_free_coherent(eth->dma_dev,
- MTK_DMA_SIZE * sizeof(*ring->dma),
- ring->dma,
- ring->phys);
-@@ -1847,7 +1862,7 @@ static void mtk_tx_clean(struct mtk_eth *eth)
+ MTK_DMA_SIZE * soc->txrx.txd_size,
+ ring->dma, ring->phys);
+@@ -1847,6 +1862,6 @@ static void mtk_tx_clean(struct mtk_eth *eth)
}
if (ring->dma_pdma) {
- dma_free_coherent(eth->dev,
+ dma_free_coherent(eth->dma_dev,
- MTK_DMA_SIZE * sizeof(*ring->dma_pdma),
- ring->dma_pdma,
- ring->phys_pdma);
+ MTK_DMA_SIZE * soc->txrx.txd_size,
+ ring->dma_pdma, ring->phys_pdma);
@@ -1892,7 +1907,7 @@ static int mtk_rx_alloc(struct mtk_eth *eth, int ring_no, int rx_flag)
if ((!eth->soc->has_sram) || (eth->soc->has_sram
&& (rx_flag != MTK_RX_FLAGS_NORMAL)))
- ring->dma = dma_alloc_coherent(eth->dev,
+ ring->dma = dma_alloc_coherent(eth->dma_dev,
- rx_dma_size * sizeof(*ring->dma),
- &ring->phys, GFP_ATOMIC);
+ rx_dma_size * eth->soc->txrx.rxd_size,
+ &ring->phys, GFP_KERNEL);
else {
-@@ -1907,11 +1922,11 @@ static int mtk_rx_alloc(struct mtk_eth *eth, int ring_no, int rx_flag)
+@@ -1907,13 +1922,13 @@ static int mtk_rx_alloc(struct mtk_eth *eth, int ring_no, int rx_flag)
return -ENOMEM;
for (i = 0; i < rx_dma_size; i++) {
+ struct mtk_rx_dma_v2 *rxd;
+
- dma_addr_t dma_addr = dma_map_single(eth->dev,
+ dma_addr_t dma_addr = dma_map_single(eth->dma_dev,
ring->data[i] + NET_SKB_PAD + eth->ip_align,
@@ -345,15 +344,16 @@
- if (unlikely(dma_mapping_error(eth->dev, dma_addr)))
+ if (unlikely(dma_mapping_error(eth->dma_dev, dma_addr)))
return -ENOMEM;
- ring->dma[i].rxd1 = (unsigned int)dma_addr;
-
-@@ -1968,7 +1983,7 @@ static void mtk_rx_clean(struct mtk_eth *eth, struct mtk_rx_ring *ring, int in_s
+
+ rxd = ring->dma + i * eth->soc->txrx.rxd_size;
+@@ -1968,8 +1983,8 @@ static void mtk_rx_clean(struct mtk_eth *eth, struct mtk_rx_ring *ring, int in_s
+ rxd = ring->dma + i * eth->soc->txrx.rxd_size;
+ if (!rxd->rxd1)
continue;
- if (!ring->dma[i].rxd1)
- continue;
+
- dma_unmap_single(eth->dev,
+ dma_unmap_single(eth->dma_dev,
- ring->dma[i].rxd1,
+ rxd->rxd1,
ring->buf_size,
DMA_FROM_DEVICE);
@@ -1982,7 +1997,7 @@ static void mtk_rx_clean(struct mtk_eth *eth, struct mtk_rx_ring *ring, int in_s
@@ -362,18 +362,17 @@
if (ring->dma) {
- dma_free_coherent(eth->dev,
+ dma_free_coherent(eth->dma_dev,
- ring->dma_size * sizeof(*ring->dma),
+ ring->dma_size * eth->soc->txrx.rxd_size,
ring->dma,
ring->phys);
-@@ -2462,7 +2477,7 @@ static void mtk_dma_free(struct mtk_eth *eth)
+@@ -2462,6 +2477,6 @@ static void mtk_dma_free(struct mtk_eth *eth)
if (eth->netdev[i])
netdev_reset_queue(eth->netdev[i]);
if ( !eth->soc->has_sram && eth->scratch_ring) {
- dma_free_coherent(eth->dev,
+ dma_free_coherent(eth->dma_dev,
- MTK_DMA_SIZE * sizeof(struct mtk_tx_dma),
- eth->scratch_ring,
- eth->phy_scratch_ring);
+ MTK_DMA_SIZE * soc->txrx.txd_size,
+ eth->scratch_ring, eth->phy_scratch_ring);
@@ -2661,7 +2676,7 @@ static int mtk_open(struct net_device *dev)
if (err)
return err;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9994-ethernet-update-ppe-from-mt7622-to-mt7986.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9994-ethernet-update-ppe-from-mt7622-to-mt7986.patch
index c2564ba..6a4766d 100755
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9994-ethernet-update-ppe-from-mt7622-to-mt7986.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9994-ethernet-update-ppe-from-mt7622-to-mt7986.patch
@@ -46,11 +46,17 @@
if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX) {
if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
-@@ -3926,6 +3937,7 @@ static const struct mtk_soc_data mt7986_data = {
+@@ -3926,12 +3937,13 @@ static const struct mtk_soc_data mt7986_data = {
.required_clks = MT7986_CLKS_BITMAP,
.required_pctl = false,
.has_sram = true,
+ .offload_version = 2,
+ .txrx = {
+ .txd_size = sizeof(struct mtk_tx_dma_v2),
+ .rxd_size = sizeof(struct mtk_rx_dma_v2),
+ .dma_max_len = MTK_TX_DMA_BUF_LEN_V2,
+ .dma_len_offset = MTK_TX_DMA_BUF_SHIFT_V2,
+ },
};
static const struct mtk_soc_data mt7981_data = {
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9996-add-wed-tx-support-for-mt7986.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9996-add-wed-tx-support-for-mt7986.patch
index 1ba2c2b..16a2b27 100755
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9996-add-wed-tx-support-for-mt7986.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9996-add-wed-tx-support-for-mt7986.patch
@@ -1252,19 +1252,15 @@
struct mtk_wed_ring tx_ring[MTK_WED_TX_QUEUES];
struct mtk_wed_ring txfree_ring;
-@@ -43,8 +57,19 @@ struct mtk_wed_device {
+@@ -43,8 +57,17 @@ struct mtk_wed_device {
/* filled by driver: */
struct {
struct pci_dev *pci_dev;
--
-- u32 wpdma_phys;
+ void __iomem *base;
+ u32 bus_type;
-+
-+ union {
-+ u32 wpdma_phys;
-+ u32 wpdma_int;
-+ };
+
+ u32 wpdma_phys;
++ u32 wpdma_int;
+ u32 wpdma_mask;
+ u32 wpdma_tx;
+ u32 wpdma_txfree;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9997-add-wed-rx-support-for-mt7896.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9997-add-wed-rx-support-for-mt7896.patch
index bc87d67..3df0ab7 100755
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9997-add-wed-rx-support-for-mt7896.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9997-add-wed-rx-support-for-mt7896.patch
@@ -8,16 +8,16 @@
arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 42 +-
arch/arm64/boot/dts/mediatek/mt7986b.dtsi | 42 +-
drivers/net/ethernet/mediatek/Makefile | 2 +-
- drivers/net/ethernet/mediatek/mtk_wed.c | 544 +++++++++++++++--
- drivers/net/ethernet/mediatek/mtk_wed.h | 50 ++
- drivers/net/ethernet/mediatek/mtk_wed_ccif.c | 121 ++++
+ drivers/net/ethernet/mediatek/mtk_wed.c | 613 ++++++++++++++++--
+ drivers/net/ethernet/mediatek/mtk_wed.h | 51 ++
+ drivers/net/ethernet/mediatek/mtk_wed_ccif.c | 133 ++++
drivers/net/ethernet/mediatek/mtk_wed_ccif.h | 45 ++
.../net/ethernet/mediatek/mtk_wed_debugfs.c | 90 +++
- drivers/net/ethernet/mediatek/mtk_wed_mcu.c | 561 ++++++++++++++++++
+ drivers/net/ethernet/mediatek/mtk_wed_mcu.c | 561 ++++++++++++++++
drivers/net/ethernet/mediatek/mtk_wed_mcu.h | 125 ++++
- drivers/net/ethernet/mediatek/mtk_wed_regs.h | 145 ++++-
- drivers/net/ethernet/mediatek/mtk_wed_wo.c | 548 +++++++++++++++++
- drivers/net/ethernet/mediatek/mtk_wed_wo.h | 334 +++++++++++
+ drivers/net/ethernet/mediatek/mtk_wed_regs.h | 147 ++++-
+ drivers/net/ethernet/mediatek/mtk_wed_wo.c | 588 +++++++++++++++++
+ drivers/net/ethernet/mediatek/mtk_wed_wo.h | 336 ++++++++++
include/linux/soc/mediatek/mtk_wed.h | 63 +-
14 files changed, 2643 insertions(+), 69 deletions(-)
mode change 100644 => 100755 drivers/net/ethernet/mediatek/mtk_wed.c
@@ -171,7 +171,7 @@
resets = <ðsysrst 0>;
reset-names = "wocpu_rst";
diff --git a/drivers/net/ethernet/mediatek/Makefile b/drivers/net/ethernet/mediatek/Makefile
-index 3528f1b3c..0c724a55c 100644
+index 3528f1b..0c724a5 100644
--- a/drivers/net/ethernet/mediatek/Makefile
+++ b/drivers/net/ethernet/mediatek/Makefile
@@ -10,5 +10,5 @@ mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed.o
@@ -182,9 +182,7 @@
+obj-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed_ops.o mtk_wed_wo.o mtk_wed_mcu.o mtk_wed_ccif.o
obj-$(CONFIG_NET_MEDIATEK_HNAT) += mtk_hnat/
diff --git a/drivers/net/ethernet/mediatek/mtk_wed.c b/drivers/net/ethernet/mediatek/mtk_wed.c
-old mode 100644
-new mode 100755
-index 48b0353bb..c4aab12b0
+index 48b0353..4d47b3a 100644
--- a/drivers/net/ethernet/mediatek/mtk_wed.c
+++ b/drivers/net/ethernet/mediatek/mtk_wed.c
@@ -13,11 +13,19 @@
@@ -208,7 +206,7 @@
static struct mtk_wed_hw *hw_list[2];
static DEFINE_MUTEX(hw_lock);
-@@ -51,6 +59,12 @@ wdma_set(struct mtk_wed_device *dev, u32 reg, u32 mask)
+@@ -51,6 +59,56 @@ wdma_set(struct mtk_wed_device *dev, u32 reg, u32 mask)
wdma_m32(dev, reg, 0, mask);
}
@@ -218,10 +216,54 @@
+ wdma_m32(dev, reg, mask, 0);
+}
+
++static u32
++mtk_wdma_read_reset(struct mtk_wed_device *dev)
++{
++ return wdma_r32(dev, MTK_WDMA_GLO_CFG);
++}
++
++static void
++mtk_wdma_rx_reset(struct mtk_wed_device *dev)
++{
++ u32 status;
++ u32 mask = MTK_WDMA_GLO_CFG_RX_DMA_BUSY;
++ int i;
++
++ wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_RX_DMA_EN);
++ if (readx_poll_timeout(mtk_wdma_read_reset, dev, status,
++ !(status & mask), 0, 1000))
++ WARN_ON_ONCE(1);
++
++ for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++)
++ if (!dev->rx_wdma[i].desc) {
++ wdma_w32(dev, MTK_WDMA_RING_RX(i) +
++ MTK_WED_RING_OFS_CPU_IDX, 0);
++ }
++}
++
++static void
++mtk_wdma_tx_reset(struct mtk_wed_device *dev)
++{
++ u32 status;
++ u32 mask = MTK_WDMA_GLO_CFG_TX_DMA_BUSY;
++ int i;
++
++ wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_TX_DMA_EN);
++ if (readx_poll_timeout(mtk_wdma_read_reset, dev, status,
++ !(status & mask), 0, 1000))
++ WARN_ON_ONCE(1);
++
++ for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++)
++ if (!dev->tx_wdma[i].desc) {
++ wdma_w32(dev, MTK_WDMA_RING_TX(i) +
++ MTK_WED_RING_OFS_CPU_IDX, 0);
++ }
++}
++
static u32
mtk_wed_read_reset(struct mtk_wed_device *dev)
{
-@@ -68,6 +82,48 @@ mtk_wed_reset(struct mtk_wed_device *dev, u32 mask)
+@@ -68,6 +126,52 @@ mtk_wed_reset(struct mtk_wed_device *dev, u32 mask)
WARN_ON_ONCE(1);
}
@@ -235,6 +277,10 @@
+ u32 value;
+ unsigned long timeout = jiffies + WOCPU_TIMEOUT;
+
++ mtk_wdma_rx_reset(dev);
++
++ mtk_wed_reset(dev, MTK_WED_RESET_WED);
++
+ mtk_wed_mcu_send_msg(wo, MODULE_ID_WO, WO_CMD_CHANGE_STATE,
+ &state, sizeof(state), false);
+
@@ -270,7 +316,30 @@
static struct mtk_wed_hw *
mtk_wed_assign(struct mtk_wed_device *dev)
{
-@@ -205,6 +261,42 @@ free_pagelist:
+@@ -178,7 +282,7 @@ mtk_wed_free_buffer(struct mtk_wed_device *dev)
+ {
+ struct mtk_wdma_desc *desc = dev->buf_ring.desc;
+ void **page_list = dev->buf_ring.pages;
+- int page_idx;
++ int ring_size, page_idx;
+ int i;
+
+ if (!page_list)
+@@ -187,6 +291,13 @@ mtk_wed_free_buffer(struct mtk_wed_device *dev)
+ if (!desc)
+ goto free_pagelist;
+
++ if (dev->ver == MTK_WED_V1) {
++ ring_size = dev->wlan.nbuf & ~(MTK_WED_BUF_PER_PAGE - 1);
++ } else {
++ ring_size = MTK_WED_VLD_GROUP_SIZE * MTK_WED_PER_GROUP_PKT +
++ MTK_WED_WDMA_RING_SIZE * 2;
++ }
++
+ for (i = 0, page_idx = 0; i < dev->buf_ring.size; i += MTK_WED_BUF_PER_PAGE) {
+ void *page = page_list[page_idx++];
+
+@@ -205,6 +316,42 @@ free_pagelist:
kfree(page_list);
}
@@ -299,21 +368,21 @@
+mtk_wed_free_rx_bm(struct mtk_wed_device *dev)
+{
+ struct mtk_rxbm_desc *desc = dev->rx_buf_ring.desc;
-+ int ring_size =dev->rx_buf_ring.size;
++ int ring_size = dev->rx_buf_ring.size;
+
+ if (!desc)
+ return;
+
+ dev->wlan.release_rx_buf(dev);
+
-+ dma_free_coherent(dev->hw->dev, ring_size * sizeof(*desc),
-+ desc, dev->buf_ring.desc_phys);
++ /* dma_free_coherent(dev->hw->dev, ring_size * sizeof(*desc),
++ desc, dev->buf_ring.desc_phys); */
+}
+
static void
mtk_wed_free_ring(struct mtk_wed_device *dev, struct mtk_wed_ring *ring, int scale)
{
-@@ -226,13 +318,22 @@ mtk_wed_free_tx_rings(struct mtk_wed_device *dev)
+@@ -226,13 +373,22 @@ mtk_wed_free_tx_rings(struct mtk_wed_device *dev)
mtk_wed_free_ring(dev, &dev->tx_wdma[i], dev->ver);
}
@@ -337,7 +406,7 @@
/* wed control cr set */
wed_set(dev, MTK_WED_CTRL,
MTK_WED_CTRL_WDMA_INT_AGENT_EN |
-@@ -251,7 +352,7 @@ mtk_wed_set_int(struct mtk_wed_device *dev, u32 irq_mask)
+@@ -251,7 +407,7 @@ mtk_wed_set_int(struct mtk_wed_device *dev, u32 irq_mask)
wed_set(dev, MTK_WED_WPDMA_INT_CTRL,
MTK_WED_WPDMA_INT_CTRL_SUBRT_ADV);
} else {
@@ -346,7 +415,7 @@
wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_TX,
MTK_WED_WPDMA_INT_CTRL_TX0_DONE_EN |
MTK_WED_WPDMA_INT_CTRL_TX0_DONE_CLR |
-@@ -262,22 +363,30 @@ mtk_wed_set_int(struct mtk_wed_device *dev, u32 irq_mask)
+@@ -262,22 +418,30 @@ mtk_wed_set_int(struct mtk_wed_device *dev, u32 irq_mask)
FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_TX1_DONE_TRIG,
dev->wlan.tx_tbit[1]));
@@ -381,7 +450,7 @@
}
wdma_w32(dev, MTK_WDMA_INT_MASK, wdma_mask);
-@@ -312,6 +421,39 @@ mtk_wed_set_512_support(struct mtk_wed_device *dev, bool en)
+@@ -312,6 +476,39 @@ mtk_wed_set_512_support(struct mtk_wed_device *dev, bool en)
}
}
@@ -421,7 +490,7 @@
static void
mtk_wed_dma_enable(struct mtk_wed_device *dev)
{
-@@ -336,9 +478,14 @@ mtk_wed_dma_enable(struct mtk_wed_device *dev)
+@@ -336,9 +533,14 @@ mtk_wed_dma_enable(struct mtk_wed_device *dev)
wdma_set(dev, MTK_WDMA_GLO_CFG,
MTK_WDMA_GLO_CFG_RX_INFO3_PRERES);
} else {
@@ -436,7 +505,7 @@
wed_set(dev, MTK_WED_WPDMA_GLO_CFG,
MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_PKT_PROC |
MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_CRX_SYNC);
-@@ -346,6 +493,15 @@ mtk_wed_dma_enable(struct mtk_wed_device *dev)
+@@ -346,6 +548,15 @@ mtk_wed_dma_enable(struct mtk_wed_device *dev)
wed_clr(dev, MTK_WED_WPDMA_GLO_CFG,
MTK_WED_WPDMA_GLO_CFG_TX_TKID_KEEP |
MTK_WED_WPDMA_GLO_CFG_TX_DMAD_DW3_PREV);
@@ -452,7 +521,7 @@
}
}
-@@ -363,19 +519,23 @@ mtk_wed_dma_disable(struct mtk_wed_device *dev)
+@@ -363,19 +574,23 @@ mtk_wed_dma_disable(struct mtk_wed_device *dev)
MTK_WED_GLO_CFG_TX_DMA_EN |
MTK_WED_GLO_CFG_RX_DMA_EN);
@@ -480,7 +549,20 @@
}
}
+@@ -384,8 +599,11 @@ mtk_wed_stop(struct mtk_wed_device *dev)
+ {
+ mtk_wed_dma_disable(dev);
+
-@@ -395,6 +555,11 @@ mtk_wed_stop(struct mtk_wed_device *dev)
+- if (dev->ver > MTK_WED_V1)
++ if (dev->ver > MTK_WED_V1) {
+ mtk_wed_set_512_support(dev, false);
++ wed_w32(dev, MTK_WED_EXT_INT_MASK1, 0);
++ wed_w32(dev, MTK_WED_EXT_INT_MASK2, 0);
++ }
+
+ mtk_wed_set_ext_int(dev, false);
+
+@@ -395,6 +613,11 @@ mtk_wed_stop(struct mtk_wed_device *dev)
MTK_WED_CTRL_WED_TX_BM_EN |
MTK_WED_CTRL_WED_TX_FREE_AGENT_EN);
@@ -492,25 +574,27 @@
wed_w32(dev, MTK_WED_WPDMA_INT_TRIGGER, 0);
wed_w32(dev, MTK_WED_WDMA_INT_TRIGGER, 0);
wdma_w32(dev, MTK_WDMA_INT_MASK, 0);
-@@ -416,9 +581,17 @@ mtk_wed_detach(struct mtk_wed_device *dev)
- wdma_w32(dev, MTK_WDMA_RESET_IDX, 0);
+@@ -417,8 +640,19 @@ mtk_wed_detach(struct mtk_wed_device *dev)
mtk_wed_reset(dev, MTK_WED_RESET_WED);
-+ if (dev->ver > MTK_WED_V1)
-+ mtk_wed_wo_reset(dev);
-+
+
+ wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_TX_DMA_EN);
+ wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_TX);
+ wdma_w32(dev, MTK_WDMA_RESET_IDX, 0);
-
++
mtk_wed_free_buffer(dev);
mtk_wed_free_tx_rings(dev);
-+ if (dev->ver > MTK_WED_V1)
++ if (dev->ver > MTK_WED_V1) {
++ mtk_wed_wo_reset(dev);
+ mtk_wed_free_rx_rings(dev);
++ mtk_wed_wo_exit(hw);
++ }
++
++ mtk_wdma_tx_reset(dev);
if (dev->wlan.bus_type == MTK_BUS_TYPE_PCIE) {
wlan_node = dev->wlan.pci_dev->dev.of_node;
-@@ -477,7 +650,6 @@ mtk_wed_bus_init(struct mtk_wed_device *dev)
+@@ -477,7 +711,6 @@ mtk_wed_bus_init(struct mtk_wed_device *dev)
value = wed_r32(dev, MTK_WED_PCIE_CFG_INTM);
value = wed_r32(dev, MTK_WED_PCIE_CFG_BASE);
@@ -518,7 +602,7 @@
wed_w32(dev, MTK_WED_PCIE_INT_TRIGGER, BIT(24));
wed_r32(dev, MTK_WED_PCIE_INT_TRIGGER);
-@@ -501,6 +673,9 @@ mtk_wed_set_wpdma(struct mtk_wed_device *dev)
+@@ -501,6 +734,9 @@ mtk_wed_set_wpdma(struct mtk_wed_device *dev)
wed_w32(dev, MTK_WED_WPDMA_CFG_INT_MASK, dev->wlan.wpdma_mask);
wed_w32(dev, MTK_WED_WPDMA_CFG_TX, dev->wlan.wpdma_tx);
wed_w32(dev, MTK_WED_WPDMA_CFG_TX_FREE, dev->wlan.wpdma_txfree);
@@ -528,12 +612,12 @@
} else {
wed_w32(dev, MTK_WED_WPDMA_CFG_BASE, dev->wlan.wpdma_phys);
}
-@@ -549,24 +722,92 @@ mtk_wed_hw_init_early(struct mtk_wed_device *dev)
+@@ -549,24 +785,92 @@ mtk_wed_hw_init_early(struct mtk_wed_device *dev)
FIELD_PREP(MTK_WED_WDMA_OFST1_RX_CTRL,
MTK_WDMA_RING_RX(0)));
}
+}
-+
+
+static void
+mtk_wed_rx_bm_hw_init(struct mtk_wed_device *dev)
+{
@@ -541,7 +625,7 @@
+ FIELD_PREP(MTK_WED_RX_BM_RX_DMAD_SDL0, dev->wlan.rx_pkt_size));
+
+ wed_w32(dev, MTK_WED_RX_BM_BASE, dev->rx_buf_ring.desc_phys);
-
++
+ wed_w32(dev, MTK_WED_RX_BM_INIT_PTR, MTK_WED_RX_BM_INIT_SW_TAIL |
+ FIELD_PREP(MTK_WED_RX_BM_SW_TAIL, dev->wlan.rx_pkt));
+
@@ -629,13 +713,13 @@
rev_size = size;
thr = 0;
}
-@@ -609,13 +852,48 @@ mtk_wed_hw_init(struct mtk_wed_device *dev)
+@@ -609,13 +913,48 @@ mtk_wed_hw_init(struct mtk_wed_device *dev)
}
static void
-mtk_wed_ring_reset(struct mtk_wdma_desc *desc, int size, int scale)
+mtk_wed_rx_hw_init(struct mtk_wed_device *dev)
- {
++{
+ wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX,
+ MTK_WED_WPDMA_RX_D_RST_CRX_IDX0 |
+ MTK_WED_WPDMA_RX_D_RST_CRX_IDX1 |
@@ -664,7 +748,7 @@
+
+static void
+mtk_wed_ring_reset(struct mtk_wdma_desc *desc, int size, int scale, bool tx)
-+{
+ {
+ __le32 ctrl;
int i;
@@ -680,7 +764,7 @@
desc->buf1 = 0;
desc->info = 0;
desc += scale;
-@@ -674,7 +952,7 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
+@@ -674,7 +1013,7 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
if (!desc)
continue;
@@ -689,7 +773,7 @@
}
if (mtk_wed_poll_busy(dev))
-@@ -729,9 +1007,24 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
+@@ -729,9 +1068,24 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
}
@@ -715,7 +799,7 @@
{
ring->desc = dma_alloc_coherent(dev->hw->dev,
size * sizeof(*ring->desc) * scale,
-@@ -740,17 +1033,18 @@ mtk_wed_ring_alloc(struct mtk_wed_device *dev, struct mtk_wed_ring *ring,
+@@ -740,17 +1094,18 @@ mtk_wed_ring_alloc(struct mtk_wed_device *dev, struct mtk_wed_ring *ring,
return -ENOMEM;
ring->size = size;
@@ -737,7 +821,7 @@
return -ENOMEM;
wdma_w32(dev, MTK_WDMA_RING_RX(idx) + MTK_WED_RING_OFS_BASE,
-@@ -767,22 +1061,143 @@ mtk_wed_wdma_ring_setup(struct mtk_wed_device *dev, int idx, int size)
+@@ -767,22 +1122,143 @@ mtk_wed_wdma_ring_setup(struct mtk_wed_device *dev, int idx, int size)
return 0;
}
@@ -887,7 +971,7 @@
mtk_wed_set_ext_int(dev, true);
if (dev->ver == MTK_WED_V1) {
-@@ -797,6 +1212,19 @@ mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask)
+@@ -797,6 +1273,19 @@ mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask)
val |= BIT(0);
regmap_write(dev->hw->mirror, dev->hw->index * 4, val);
} else {
@@ -907,7 +991,7 @@
mtk_wed_set_512_support(dev, true);
}
-@@ -841,9 +1269,17 @@ mtk_wed_attach(struct mtk_wed_device *dev)
+@@ -841,9 +1330,17 @@ mtk_wed_attach(struct mtk_wed_device *dev)
wed_r32(dev, MTK_WED_REV_ID));
ret = mtk_wed_buffer_alloc(dev);
@@ -928,7 +1012,7 @@
}
mtk_wed_hw_init_early(dev);
-@@ -851,7 +1287,12 @@ mtk_wed_attach(struct mtk_wed_device *dev)
+@@ -851,7 +1348,12 @@ mtk_wed_attach(struct mtk_wed_device *dev)
if (dev->ver == MTK_WED_V1)
regmap_update_bits(hw->hifsys, HIFSYS_DMA_AG_MAP,
BIT(hw->index), 0);
@@ -941,7 +1025,7 @@
out:
mutex_unlock(&hw_lock);
-@@ -877,10 +1318,10 @@ mtk_wed_tx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs)
+@@ -877,10 +1379,10 @@ mtk_wed_tx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs)
BUG_ON(idx > ARRAY_SIZE(dev->tx_ring));
@@ -954,7 +1038,7 @@
return -ENOMEM;
ring->reg_base = MTK_WED_RING_TX(idx);
-@@ -927,6 +1368,35 @@ mtk_wed_txfree_ring_setup(struct mtk_wed_device *dev, void __iomem *regs)
+@@ -927,6 +1429,35 @@ mtk_wed_txfree_ring_setup(struct mtk_wed_device *dev, void __iomem *regs)
return 0;
}
@@ -990,7 +1074,7 @@
static u32
mtk_wed_irq_get(struct mtk_wed_device *dev, u32 mask)
{
-@@ -1014,6 +1484,8 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
+@@ -1014,6 +1545,8 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
.attach = mtk_wed_attach,
.tx_ring_setup = mtk_wed_tx_ring_setup,
.txfree_ring_setup = mtk_wed_txfree_ring_setup,
@@ -999,7 +1083,7 @@
.start = mtk_wed_start,
.stop = mtk_wed_stop,
.reset_dma = mtk_wed_reset_dma,
-@@ -1022,6 +1494,7 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
+@@ -1022,6 +1555,7 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
.irq_get = mtk_wed_irq_get,
.irq_set_mask = mtk_wed_irq_set_mask,
.detach = mtk_wed_detach,
@@ -1008,7 +1092,7 @@
struct device_node *eth_np = eth->dev->of_node;
struct platform_device *pdev;
diff --git a/drivers/net/ethernet/mediatek/mtk_wed.h b/drivers/net/ethernet/mediatek/mtk_wed.h
-index 9b17b7405..ec79b0d42 100644
+index 9b17b74..8ef5253 100644
--- a/drivers/net/ethernet/mediatek/mtk_wed.h
+++ b/drivers/net/ethernet/mediatek/mtk_wed.h
@@ -13,6 +13,7 @@
@@ -1093,11 +1177,12 @@
void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
void __iomem *wdma, u32 wdma_phy, int index);
void mtk_wed_exit(void);
-@@ -146,4 +185,15 @@ static inline void mtk_wed_hw_add_debugfs(struct mtk_wed_hw *hw)
+@@ -146,4 +185,16 @@ static inline void mtk_wed_hw_add_debugfs(struct mtk_wed_hw *hw)
}
#endif
+int wed_wo_hardware_init(struct mtk_wed_wo *wo, irq_handler_t isr);
++void wed_wo_hardware_exit(struct mtk_wed_wo *wo);
+int wed_wo_mcu_init(struct mtk_wed_wo *wo);
+int mtk_wed_exception_init(struct mtk_wed_wo *wo);
+void mtk_wed_mcu_rx_unsolicited_event(struct mtk_wed_wo *wo, struct sk_buff *skb);
@@ -1111,10 +1196,10 @@
#endif
diff --git a/drivers/net/ethernet/mediatek/mtk_wed_ccif.c b/drivers/net/ethernet/mediatek/mtk_wed_ccif.c
new file mode 100644
-index 000000000..732ffc8cf
+index 0000000..22ef337
--- /dev/null
+++ b/drivers/net/ethernet/mediatek/mtk_wed_ccif.c
-@@ -0,0 +1,121 @@
+@@ -0,0 +1,133 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/soc/mediatek/mtk_wed.h>
@@ -1228,17 +1313,29 @@
+ return 0;
+
+free_irq:
-+ devm_free_irq(wo->hw->dev, wo->ccif.irq, wo);
++ free_irq(wo->ccif.irq, wo);
+
+ return ret;
+}
+
-+static void wed_wo_hardware_exit(struct mtk_wed_wo *wo)
++void wed_wo_hardware_exit(struct mtk_wed_wo *wo)
+{
++ wo->drv_ops->set_isr(wo, 0);
++
++ disable_irq(wo->ccif.irq);
++ free_irq(wo->ccif.irq, wo);
++
++ tasklet_disable(&wo->irq_tasklet);
++ netif_napi_del(&wo->napi);
++
++ mtk_wed_wo_q_tx_clean(wo, &wo->q_tx, true);
++ mtk_wed_wo_q_rx_clean(wo, &wo->q_rx);
++ mtk_wed_wo_q_free(wo, &wo->q_tx);
++ mtk_wed_wo_q_free(wo, &wo->q_rx);
+}
diff --git a/drivers/net/ethernet/mediatek/mtk_wed_ccif.h b/drivers/net/ethernet/mediatek/mtk_wed_ccif.h
new file mode 100644
-index 000000000..68ade449c
+index 0000000..68ade44
--- /dev/null
+++ b/drivers/net/ethernet/mediatek/mtk_wed_ccif.h
@@ -0,0 +1,45 @@
@@ -1288,7 +1385,7 @@
+
+#endif
diff --git a/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c b/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c
-index f420f187e..fea7ae2fc 100644
+index f420f18..fea7ae2 100644
--- a/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c
+++ b/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c
@@ -2,6 +2,7 @@
@@ -1430,7 +1527,7 @@
}
diff --git a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c
new file mode 100644
-index 000000000..bd1ab9500
+index 0000000..bd1ab95
--- /dev/null
+++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c
@@ -0,0 +1,561 @@
@@ -1997,7 +2094,7 @@
+
diff --git a/drivers/net/ethernet/mediatek/mtk_wed_mcu.h b/drivers/net/ethernet/mediatek/mtk_wed_mcu.h
new file mode 100644
-index 000000000..6a5ac7672
+index 0000000..6a5ac76
--- /dev/null
+++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.h
@@ -0,0 +1,125 @@
@@ -2127,7 +2224,7 @@
+
+#endif
diff --git a/drivers/net/ethernet/mediatek/mtk_wed_regs.h b/drivers/net/ethernet/mediatek/mtk_wed_regs.h
-index 69f136ed4..e911b5315 100644
+index e107de7..64a2483 100644
--- a/drivers/net/ethernet/mediatek/mtk_wed_regs.h
+++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h
@@ -4,6 +4,8 @@
@@ -2147,7 +2244,7 @@
struct mtk_wdma_desc {
__le32 buf0;
-@@ -37,6 +40,8 @@ struct mtk_wdma_desc {
+@@ -41,6 +44,8 @@ struct mtk_wdma_desc {
#define MTK_WED_RESET_WED_TX_DMA BIT(12)
#define MTK_WED_RESET_WDMA_RX_DRV BIT(17)
#define MTK_WED_RESET_WDMA_INT_AGENT BIT(19)
@@ -2156,7 +2253,7 @@
#define MTK_WED_RESET_WED BIT(31)
#define MTK_WED_CTRL 0x00c
-@@ -48,8 +53,12 @@ struct mtk_wdma_desc {
+@@ -52,8 +57,12 @@ struct mtk_wdma_desc {
#define MTK_WED_CTRL_WED_TX_BM_BUSY BIT(9)
#define MTK_WED_CTRL_WED_TX_FREE_AGENT_EN BIT(10)
#define MTK_WED_CTRL_WED_TX_FREE_AGENT_BUSY BIT(11)
@@ -2171,7 +2268,7 @@
#define MTK_WED_CTRL_FINAL_DIDX_READ BIT(24)
#define MTK_WED_CTRL_ETH_DMAD_FMT BIT(25)
#define MTK_WED_CTRL_MIB_READ_CLEAR BIT(28)
-@@ -64,8 +73,8 @@ struct mtk_wdma_desc {
+@@ -68,8 +77,8 @@ struct mtk_wdma_desc {
#define MTK_WED_EXT_INT_STATUS_TX_TKID_LO_TH BIT(10)
#define MTK_WED_EXT_INT_STATUS_TX_TKID_HI_TH BIT(11)
#endif
@@ -2182,7 +2279,7 @@
#define MTK_WED_EXT_INT_STATUS_RX_DRV_R_RESP_ERR BIT(16)
#define MTK_WED_EXT_INT_STATUS_RX_DRV_W_RESP_ERR BIT(17)
#define MTK_WED_EXT_INT_STATUS_RX_DRV_COHERENT BIT(18)
-@@ -82,8 +91,8 @@ struct mtk_wdma_desc {
+@@ -86,8 +95,8 @@ struct mtk_wdma_desc {
#define MTK_WED_EXT_INT_STATUS_ERROR_MASK (MTK_WED_EXT_INT_STATUS_TF_LEN_ERR | \
MTK_WED_EXT_INT_STATUS_TKID_WO_PYLD | \
MTK_WED_EXT_INT_STATUS_TKID_TITO_INVALID | \
@@ -2193,7 +2290,7 @@
MTK_WED_EXT_INT_STATUS_RX_DRV_R_RESP_ERR | \
MTK_WED_EXT_INT_STATUS_RX_DRV_W_RESP_ERR | \
MTK_WED_EXT_INT_STATUS_RX_DRV_COHERENT | \
-@@ -92,6 +101,8 @@ struct mtk_wdma_desc {
+@@ -96,6 +105,8 @@ struct mtk_wdma_desc {
MTK_WED_EXT_INT_STATUS_TX_DMA_W_RESP_ERR)
#define MTK_WED_EXT_INT_MASK 0x028
@@ -2202,7 +2299,7 @@
#define MTK_WED_STATUS 0x060
#define MTK_WED_STATUS_TX GENMASK(15, 8)
-@@ -179,6 +190,9 @@ struct mtk_wdma_desc {
+@@ -183,6 +194,9 @@ struct mtk_wdma_desc {
#define MTK_WED_RING_RX(_n) (0x400 + (_n) * 0x10)
@@ -2212,7 +2309,7 @@
#define MTK_WED_WPDMA_INT_TRIGGER 0x504
#define MTK_WED_WPDMA_INT_TRIGGER_RX_DONE BIT(1)
#define MTK_WED_WPDMA_INT_TRIGGER_TX_DONE GENMASK(5, 4)
-@@ -235,13 +249,19 @@ struct mtk_wdma_desc {
+@@ -239,13 +253,19 @@ struct mtk_wdma_desc {
#define MTK_WED_WPDMA_INT_CTRL_TX 0x530
#define MTK_WED_WPDMA_INT_CTRL_TX0_DONE_EN BIT(0)
@@ -2233,7 +2330,7 @@
#define MTK_WED_WPDMA_INT_CTRL_TX_FREE 0x538
#define MTK_WED_WPDMA_INT_CTRL_TX_FREE_DONE_EN BIT(0)
-@@ -266,13 +286,43 @@ struct mtk_wdma_desc {
+@@ -270,13 +290,43 @@ struct mtk_wdma_desc {
#define MTK_WED_WPDMA_TX_MIB(_n) (0x5a0 + (_n) * 4)
#define MTK_WED_WPDMA_TX_COHERENT_MIB(_n) (0x5d0 + (_n) * 4)
@@ -2277,7 +2374,7 @@
#define MTK_WED_WDMA_GLO_CFG_RX_DRV_EN BIT(2)
#define MTK_WED_WDMA_GLO_CFG_RX_DRV_BUSY BIT(3)
#define MTK_WED_WDMA_GLO_CFG_BT_SIZE GENMASK(5, 4)
-@@ -316,6 +366,20 @@ struct mtk_wdma_desc {
+@@ -320,6 +370,20 @@ struct mtk_wdma_desc {
#define MTK_WED_WDMA_RX_RECYCLE_MIB(_n) (0xae8 + (_n) * 4)
#define MTK_WED_WDMA_RX_PROCESSED_MIB(_n) (0xaf0 + (_n) * 4)
@@ -2298,7 +2395,17 @@
#define MTK_WED_RING_OFS_BASE 0x00
#define MTK_WED_RING_OFS_COUNT 0x04
#define MTK_WED_RING_OFS_CPU_IDX 0x08
-@@ -355,4 +419,71 @@ struct mtk_wdma_desc {
+@@ -330,7 +394,9 @@ struct mtk_wdma_desc {
+
+ #define MTK_WDMA_GLO_CFG 0x204
+ #define MTK_WDMA_GLO_CFG_TX_DMA_EN BIT(0)
++#define MTK_WDMA_GLO_CFG_TX_DMA_BUSY BIT(1)
+ #define MTK_WDMA_GLO_CFG_RX_DMA_EN BIT(2)
++#define MTK_WDMA_GLO_CFG_RX_DMA_BUSY BIT(3)
+ #define MTK_WDMA_GLO_CFG_RX_INFO3_PRERES BIT(26)
+ #define MTK_WDMA_GLO_CFG_RX_INFO2_PRERES BIT(27)
+ #define MTK_WDMA_GLO_CFG_RX_INFO1_PRERES BIT(28)
+@@ -359,4 +425,71 @@ struct mtk_wdma_desc {
/* DMA channel mapping */
#define HIFSYS_DMA_AG_MAP 0x008
@@ -2372,10 +2479,10 @@
#endif
diff --git a/drivers/net/ethernet/mediatek/mtk_wed_wo.c b/drivers/net/ethernet/mediatek/mtk_wed_wo.c
new file mode 100644
-index 000000000..10618fc1a
+index 0000000..e101f17
--- /dev/null
+++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.c
-@@ -0,0 +1,548 @@
+@@ -0,0 +1,588 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/kernel.h>
@@ -2426,8 +2533,7 @@
+ woccif_w32(wo, q->regs->ring_size, q->ndesc);
+
+ /* wo fw start from 1 */
-+ q->head = woccif_r32(wo, q->regs->dma_idx) + 1;
-+ q->tail = q->head;
++ q->tail = q->head = 1;
+}
+
+static void
@@ -2550,6 +2656,23 @@
+}
+
+static void
++woif_q_free(struct mtk_wed_wo *dev, struct wed_wo_queue *q)
++{
++ int size;
++
++ if (!q)
++ return;
++
++ if (!q->desc)
++ return;
++
++ woccif_w32(dev, q->regs->cpu_idx, 0);
++
++ size = q->ndesc * sizeof(struct wed_wo_desc);
++ dma_free_coherent(dev->hw->dev, size, q->desc, q->desc_dma);
++}
++
++static void
+woif_q_tx_clean(struct mtk_wed_wo *wo, struct wed_wo_queue *q, bool flush)
+{
+ int last;
@@ -2594,11 +2717,6 @@
+ }
+}
+
-+static void
-+woif_q_rx_clean(struct mtk_wed_wo *wo, struct wed_wo_queue *q)
-+{
-+}
-+
+static void *
+woif_q_deq(struct mtk_wed_wo *wo, struct wed_wo_queue *q, bool flush,
+ int *len, u32 *info, bool *more)
@@ -2641,6 +2759,35 @@
+ return buf;
+}
+
++static void
++woif_q_rx_clean(struct mtk_wed_wo *wo, struct wed_wo_queue *q)
++{
++ struct page *page;
++ void *buf;
++ bool more;
++
++ if (!q->ndesc)
++ return;
++
++ spin_lock_bh(&q->lock);
++ do {
++ buf = woif_q_deq(wo, q, true, NULL, NULL, &more);
++ if (!buf)
++ break;
++
++ skb_free_frag(buf);
++ } while (1);
++ spin_unlock_bh(&q->lock);
++
++ if (!q->rx_page.va)
++ return;
++
++ page = virt_to_page(q->rx_page.va);
++ __page_frag_cache_drain(page, q->rx_page.pagecnt_bias);
++ memset(&q->rx_page, 0, sizeof(q->rx_page));
++
++}
++
+static int
+woif_q_init(struct mtk_wed_wo *dev,
+ int (*poll)(struct napi_struct *napi, int budget))
@@ -2740,6 +2887,7 @@
+static const struct wed_wo_queue_ops wo_queue_ops = {
+ .init = woif_q_init,
+ .alloc = woif_q_alloc,
++ .free = woif_q_free,
+ .reset = woif_q_reset,
+ .tx_skb = woif_q_tx_skb,
+ .tx_clean = woif_q_tx_clean,
@@ -2910,26 +3058,25 @@
+
+void mtk_wed_wo_exit(struct mtk_wed_hw *hw)
+{
-+/*
-+#ifdef CONFIG_WED_HW_RRO_SUPPORT
-+ woif_bus_exit(woif);
-+ wo_exception_exit(woif);
-+#endif
-+*/
+ struct mtk_wed_wo *wo = hw->wed_wo;
+
++ wed_wo_hardware_exit(wo);
++
+ if (wo->exp.log) {
+ dma_unmap_single(wo->hw->dev, wo->exp.phys, wo->exp.log_size, DMA_FROM_DEVICE);
+ kfree(wo->exp.log);
+ }
+
++ wo->hw = NULL;
++ memset(wo, 0, sizeof(*wo));
++ kfree(wo);
+}
diff --git a/drivers/net/ethernet/mediatek/mtk_wed_wo.h b/drivers/net/ethernet/mediatek/mtk_wed_wo.h
new file mode 100644
-index 000000000..00b39e779
+index 0000000..d962e3a
--- /dev/null
+++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.h
-@@ -0,0 +1,334 @@
+@@ -0,0 +1,336 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (C) 2021 Felix Fietkau <nbd@nbd.name> */
+
@@ -3159,7 +3306,7 @@
+ int (*alloc)(struct mtk_wed_wo *wo, struct wed_wo_queue *q,
+ int idx, int n_desc, int bufsize,
+ struct wed_wo_queue_regs *regs);
-+
++ void (*free)(struct mtk_wed_wo *wo, struct wed_wo_queue *q);
+ void (*reset)(struct mtk_wed_wo *wo, struct wed_wo_queue *q);
+
+ int (*tx_skb)(struct mtk_wed_wo *wo, struct wed_wo_queue *q,
@@ -3199,7 +3346,8 @@
+
+#define mtk_wed_wo_q_init(wo, ...) (wo)->queue_ops->init((wo), __VA_ARGS__)
+#define mtk_wed_wo_q_alloc(wo, ...) (wo)->queue_ops->alloc((wo), __VA_ARGS__)
-+#define mtk_wed_wo_q_reset(wo, ...) (wo)->queue_ops->init((wo), __VA_ARGS__)
++#define mtk_wed_wo_q_free(wo, ...) (wo)->queue_ops->free((wo), __VA_ARGS__)
++#define mtk_wed_wo_q_reset(wo, ...) (wo)->queue_ops->reset((wo), __VA_ARGS__)
+#define mtk_wed_wo_q_tx_skb(wo, ...) (wo)->queue_ops->tx_skb((wo), __VA_ARGS__)
+#define mtk_wed_wo_q_tx_skb1(wo, ...) (wo)->queue_ops->tx_skb1((wo), __VA_ARGS__)
+#define mtk_wed_wo_q_tx_clean(wo, ...) (wo)->queue_ops->tx_clean((wo), __VA_ARGS__)
@@ -3262,6 +3410,7 @@
+}
+
+int mtk_wed_wo_init(struct mtk_wed_hw *hw);
++void mtk_wed_wo_exit(struct mtk_wed_hw *hw);
+#endif
+
diff --git a/include/linux/soc/mediatek/mtk_wed.h b/include/linux/soc/mediatek/mtk_wed.h
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9998-ethernet-update-ppe-backward-compatible-two-way-hash.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9998-ethernet-update-ppe-backward-compatible-two-way-hash.patch
index d655632..244788d 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9998-ethernet-update-ppe-backward-compatible-two-way-hash.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9998-ethernet-update-ppe-backward-compatible-two-way-hash.patch
@@ -12,52 +12,88 @@
if (!eth->ppe[i]) {
err = -ENOMEM;
goto err_free_dev;
-@@ -3927,6 +3928,7 @@ static const struct mtk_soc_data mt2701_data = {
+@@ -3927,12 +3928,13 @@ static const struct mtk_soc_data mt2701_data = {
.required_clks = MT7623_CLKS_BITMAP,
.required_pctl = true,
.has_sram = false,
+ .hash_way = 2,
.offload_version = 2,
+ .txrx = {
+ .txd_size = sizeof(struct mtk_tx_dma),
+ .rxd_size = sizeof(struct mtk_rx_dma),
+ .dma_max_len = MTK_TX_DMA_BUF_LEN,
+ .dma_len_offset = MTK_TX_DMA_BUF_SHIFT,
+ },
};
-@@ -3936,6 +3938,7 @@ static const struct mtk_soc_data mt7621_data = {
+@@ -3936,12 +3938,13 @@ static const struct mtk_soc_data mt7621_data = {
.required_clks = MT7621_CLKS_BITMAP,
.required_pctl = false,
.has_sram = false,
+ .hash_way = 2,
.offload_version = 2,
+ .txrx = {
+ .txd_size = sizeof(struct mtk_tx_dma),
+ .rxd_size = sizeof(struct mtk_rx_dma),
+ .dma_max_len = MTK_TX_DMA_BUF_LEN,
+ .dma_len_offset = MTK_TX_DMA_BUF_SHIFT,
+ },
};
-@@ -3946,6 +3949,7 @@ static const struct mtk_soc_data mt7622_data = {
+@@ -3946,12 +3949,13 @@ static const struct mtk_soc_data mt7622_data = {
.required_clks = MT7622_CLKS_BITMAP,
.required_pctl = false,
.has_sram = false,
+ .hash_way = 2,
.offload_version = 2,
+ .txrx = {
+ .txd_size = sizeof(struct mtk_tx_dma),
+ .rxd_size = sizeof(struct mtk_rx_dma),
+ .dma_max_len = MTK_TX_DMA_BUF_LEN,
+ .dma_len_offset = MTK_TX_DMA_BUF_SHIFT,
+ },
};
-@@ -3955,6 +3959,7 @@ static const struct mtk_soc_data mt7623_data = {
+@@ -3955,12 +3959,13 @@ static const struct mtk_soc_data mt7623_data = {
.required_clks = MT7623_CLKS_BITMAP,
.required_pctl = true,
.has_sram = false,
+ .hash_way = 2,
.offload_version = 2,
+ .txrx = {
+ .txd_size = sizeof(struct mtk_tx_dma),
+ .rxd_size = sizeof(struct mtk_rx_dma),
+ .dma_max_len = MTK_TX_DMA_BUF_LEN,
+ .dma_len_offset = MTK_TX_DMA_BUF_SHIFT,
+ },
};
-@@ -3974,6 +3979,7 @@ static const struct mtk_soc_data mt7986_data = {
+@@ -3974,12 +3979,13 @@ static const struct mtk_soc_data mt7986_data = {
.required_clks = MT7986_CLKS_BITMAP,
.required_pctl = false,
.has_sram = true,
+ .hash_way = 4,
.offload_version = 2,
+ .txrx = {
+ .txd_size = sizeof(struct mtk_tx_dma_v2),
+ .rxd_size = sizeof(struct mtk_rx_dma_v2),
+ .dma_max_len = MTK_TX_DMA_BUF_LEN_V2,
+ .dma_len_offset = MTK_TX_DMA_BUF_SHIFT_V2,
+ },
};
-@@ -3984,6 +3990,8 @@ static const struct mtk_soc_data mt7981_data = {
+@@ -3984,12 +3990,14 @@ static const struct mtk_soc_data mt7981_data = {
.required_clks = MT7981_CLKS_BITMAP,
.required_pctl = false,
.has_sram = true,
+ .hash_way = 4,
+ .offload_version = 2,
+ .txrx = {
+ .txd_size = sizeof(struct mtk_tx_dma_v2),
+ .rxd_size = sizeof(struct mtk_rx_dma_v2),
+ .dma_max_len = MTK_TX_DMA_BUF_LEN_V2,
+ .dma_len_offset = MTK_TX_DMA_BUF_SHIFT_V2,
+ },
};
static const struct mtk_soc_data rt5350_data = {
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9013-drivers-spi-mt65xx-Move-chip_config-to-driver-priv.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9013-drivers-spi-mt65xx-Move-chip_config-to-driver-priv.patch
new file mode 100644
index 0000000..d64f376
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9013-drivers-spi-mt65xx-Move-chip_config-to-driver-priv.patch
@@ -0,0 +1,142 @@
+From 45ec6dfcc5f48127d5bd440fb615bbf48f3fc9c1 Mon Sep 17 00:00:00 2001
+From: "SkyLake.Huang" <skylake.huang@mediatek.com>
+Date: Thu, 23 Jun 2022 18:29:51 +0800
+Subject: [PATCH] drivers: spi-mt65xx: Move chip_config to driver's private
+ data
+
+Signed-off-by: SkyLake.Huang <skylake.huang@mediatek.com>
+---
+ drivers/spi/spi-mt65xx.c | 31 +++++++++++-------------
+ include/linux/platform_data/spi-mt65xx.h | 17 -------------
+ 2 files changed, 14 insertions(+), 34 deletions(-)
+ delete mode 100644 include/linux/platform_data/spi-mt65xx.h
+
+diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c
+index c19e2d4d7..0afd00891 100644
+--- a/drivers/spi/spi-mt65xx.c
++++ b/drivers/spi/spi-mt65xx.c
+@@ -14,7 +14,6 @@
+ #include <linux/of.h>
+ #include <linux/of_gpio.h>
+ #include <linux/platform_device.h>
+-#include <linux/platform_data/spi-mt65xx.h>
+ #include <linux/pm_runtime.h>
+ #include <linux/spi/spi.h>
+ #include <linux/spi/spi-mem.h>
+@@ -123,6 +122,11 @@ struct mtk_spi_compatible {
+ bool need_ahb_clk;
+ };
+
++struct mtk_spi_config {
++ u32 sample_sel;
++ u32 get_tick_dly;
++};
++
+ struct mtk_spi {
+ void __iomem *base;
+ u32 state;
+@@ -135,6 +139,7 @@ struct mtk_spi {
+ struct scatterlist *tx_sgl, *rx_sgl;
+ u32 tx_sgl_len, rx_sgl_len;
+ const struct mtk_spi_compatible *dev_comp;
++ struct mtk_spi_config dev_config;
+
+ struct completion spimem_done;
+ bool use_spimem;
+@@ -189,15 +194,6 @@ static const struct mtk_spi_compatible mt8183_compat = {
+ .enhance_timing = true,
+ };
+
+-/*
+- * A piece of default chip info unless the platform
+- * supplies it.
+- */
+-static const struct mtk_chip_config mtk_default_chip_info = {
+- .sample_sel = 0,
+- .get_tick_dly = 2,
+-};
+-
+ static const struct of_device_id mtk_spi_of_match[] = {
+ { .compatible = "mediatek,ipm-spi-single",
+ .data = (void *)&ipm_compat_single,
+@@ -255,7 +251,6 @@ static int mtk_spi_hw_init(struct spi_master *master,
+ {
+ u16 cpha, cpol;
+ u32 reg_val;
+- struct mtk_chip_config *chip_config = spi->controller_data;
+ struct mtk_spi *mdata = spi_master_get_devdata(master);
+
+ cpha = spi->mode & SPI_CPHA ? 1 : 0;
+@@ -270,13 +265,13 @@ static int mtk_spi_hw_init(struct spi_master *master,
+
+ reg_val = readl(mdata->base + SPI_CMD_REG);
+ reg_val &= ~SPI_CMD_IPM_GET_TICKDLY_MASK;
+- reg_val |= chip_config->get_tick_dly
++ reg_val |= mdata->dev_config.get_tick_dly
+ << SPI_CMD_IPM_GET_TICKDLY_OFFSET;
+ writel(reg_val, mdata->base + SPI_CMD_REG);
+ } else {
+ reg_val = readl(mdata->base + SPI_CFG1_REG);
+ reg_val &= ~SPI_CFG1_GET_TICKDLY_MASK;
+- reg_val |= chip_config->get_tick_dly
++ reg_val |= mdata->dev_config.get_tick_dly
+ << SPI_CFG1_GET_TICKDLY_OFFSET;
+ writel(reg_val, mdata->base + SPI_CFG1_REG);
+ }
+@@ -326,7 +321,7 @@ static int mtk_spi_hw_init(struct spi_master *master,
+ else
+ reg_val &= ~SPI_CMD_CS_POL;
+
+- if (chip_config->sample_sel)
++ if (mdata->dev_config.sample_sel)
+ reg_val |= SPI_CMD_SAMPLE_SEL;
+ else
+ reg_val &= ~SPI_CMD_SAMPLE_SEL;
+@@ -623,9 +618,6 @@ static int mtk_spi_setup(struct spi_device *spi)
+ {
+ struct mtk_spi *mdata = spi_master_get_devdata(spi->master);
+
+- if (!spi->controller_data)
+- spi->controller_data = (void *)&mtk_default_chip_info;
+-
+ if (mdata->dev_comp->need_pad_sel && gpio_is_valid(spi->cs_gpio))
+ gpio_direction_output(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH));
+
+@@ -1025,6 +1017,11 @@ static int mtk_spi_probe(struct platform_device *pdev)
+ }
+
+ mdata = spi_master_get_devdata(master);
++
++ /* Set device configs to default first. Calibrate it later. */
++ mdata->dev_config.sample_sel = 0;
++ mdata->dev_config.get_tick_dly = 2;
++
+ mdata->dev_comp = of_id->data;
+
+ if (mdata->dev_comp->enhance_timing)
+diff --git a/include/linux/platform_data/spi-mt65xx.h b/include/linux/platform_data/spi-mt65xx.h
+deleted file mode 100644
+index fae9bc15c..000000000
+--- a/include/linux/platform_data/spi-mt65xx.h
++++ /dev/null
+@@ -1,17 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0-only */
+-/*
+- * MTK SPI bus driver definitions
+- *
+- * Copyright (c) 2015 MediaTek Inc.
+- * Author: Leilk Liu <leilk.liu@mediatek.com>
+- */
+-
+-#ifndef ____LINUX_PLATFORM_DATA_SPI_MTK_H
+-#define ____LINUX_PLATFORM_DATA_SPI_MTK_H
+-
+-/* Board specific platform_data */
+-struct mtk_chip_config {
+- u32 sample_sel;
+- u32 get_tick_dly;
+-};
+-#endif
+--
+2.18.0
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9014-drivers-spi-Add-support-for-dynamic-calibration.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9014-drivers-spi-Add-support-for-dynamic-calibration.patch
new file mode 100644
index 0000000..688f33f
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9014-drivers-spi-Add-support-for-dynamic-calibration.patch
@@ -0,0 +1,243 @@
+From a84c53fce4ccd67c147dcbb2dcf4fdeceab05981 Mon Sep 17 00:00:00 2001
+From: "SkyLake.Huang" <skylake.huang@mediatek.com>
+Date: Thu, 23 Jun 2022 18:35:52 +0800
+Subject: [PATCH] drivers: spi: Add support for dynamic calibration
+
+Signed-off-by: SkyLake.Huang <skylake.huang@mediatek.com>
+---
+ drivers/spi/spi.c | 137 ++++++++++++++++++++++++++++++++++++++++
+ include/linux/spi/spi.h | 42 ++++++++++++
+ 2 files changed, 179 insertions(+)
+
+diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
+index e562735a3..d548036b1 100644
+--- a/drivers/spi/spi.c
++++ b/drivers/spi/spi.c
+@@ -1109,6 +1109,70 @@ static int spi_transfer_wait(struct spi_controller *ctlr,
+ return 0;
+ }
+
++int spi_do_calibration(struct spi_controller *ctlr, struct spi_device *spi,
++ int (*cal_read)(void *priv, u32 *addr, int addrlen, u8 *buf, int readlen), void *drv_priv)
++{
++ int datalen = ctlr->cal_rule->datalen;
++ int addrlen = ctlr->cal_rule->addrlen;
++ u8 *buf;
++ int ret;
++ int i;
++ struct list_head *cal_head, *listptr;
++ struct spi_cal_target *target;
++
++ /* Calculate calibration result */
++ int hit_val, total_hit, origin;
++ bool hit;
++
++ /* Make sure we can start calibration */
++ if(!ctlr->cal_target || !ctlr->cal_rule || !ctlr->append_caldata)
++ return 0;
++
++ buf = kzalloc(datalen * sizeof(u8), GFP_KERNEL);
++ if(!buf)
++ return -ENOMEM;
++
++ ret = ctlr->append_caldata(ctlr);
++ if (ret)
++ goto cal_end;
++
++ cal_head = ctlr->cal_target;
++ list_for_each(listptr, cal_head) {
++ target = list_entry(listptr, struct spi_cal_target, list);
++
++ hit = false;
++ hit_val = 0;
++ total_hit = 0;
++ origin = *target->cal_item;
++
++ for(i=target->cal_min; i<=target->cal_max; i+=target->step) {
++ *target->cal_item = i;
++ ret = (*cal_read)(drv_priv, ctlr->cal_rule->addr, addrlen, buf, datalen);
++ if(ret)
++ break;
++ dev_dbg(&spi->dev, "controller cal item value: 0x%x\n", i);
++ if(memcmp(ctlr->cal_rule->match_data, buf, datalen * sizeof(u8)) == 0) {
++ hit = true;
++ hit_val += i;
++ total_hit++;
++ dev_dbg(&spi->dev, "golden data matches data read!\n");
++ }
++ }
++ if(hit) {
++ *target->cal_item = DIV_ROUND_CLOSEST(hit_val, total_hit);
++ dev_info(&spi->dev, "calibration result: 0x%x", *target->cal_item);
++ } else {
++ *target->cal_item = origin;
++ dev_warn(&spi->dev, "calibration failed, fallback to default: 0x%x", origin);
++ }
++ }
++
++cal_end:
++ kfree(buf);
++ return ret? ret: 0;
++}
++EXPORT_SYMBOL_GPL(spi_do_calibration);
++
+ static void _spi_transfer_delay_ns(u32 ns)
+ {
+ if (!ns)
+@@ -1720,6 +1784,75 @@ void spi_flush_queue(struct spi_controller *ctlr)
+ /*-------------------------------------------------------------------------*/
+
+ #if defined(CONFIG_OF)
++static inline void alloc_cal_data(struct list_head **cal_target,
++ struct spi_cal_rule **cal_rule, bool enable)
++{
++ if(enable) {
++ *cal_target = kmalloc(sizeof(struct list_head), GFP_KERNEL);
++ INIT_LIST_HEAD(*cal_target);
++ *cal_rule = kmalloc(sizeof(struct spi_cal_rule), GFP_KERNEL);
++ } else {
++ kfree(*cal_target);
++ kfree(*cal_rule);
++ }
++}
++
++static int of_spi_parse_cal_dt(struct spi_controller *ctlr, struct spi_device *spi,
++ struct device_node *nc)
++{
++ u32 value;
++ int rc;
++ const char *cal_mode;
++
++ rc = of_property_read_bool(nc, "spi-cal-enable");
++ if (rc)
++ alloc_cal_data(&ctlr->cal_target, &ctlr->cal_rule, true);
++ else
++ return 0;
++
++ rc = of_property_read_string(nc, "spi-cal-mode", &cal_mode);
++ if(!rc) {
++ if(strcmp("read-data", cal_mode) == 0){
++ ctlr->cal_rule->mode = SPI_CAL_READ_DATA;
++ } else if(strcmp("read-pp", cal_mode) == 0) {
++ ctlr->cal_rule->mode = SPI_CAL_READ_PP;
++ return 0;
++ } else if(strcmp("read-sfdp", cal_mode) == 0){
++ ctlr->cal_rule->mode = SPI_CAL_READ_SFDP;
++ return 0;
++ }
++ } else
++ goto err;
++
++ ctlr->cal_rule->datalen = 0;
++ rc = of_property_read_u32(nc, "spi-cal-datalen", &value);
++ if(!rc && value > 0) {
++ ctlr->cal_rule->datalen = value;
++
++ ctlr->cal_rule->match_data = kzalloc(value * sizeof(u8), GFP_KERNEL);
++ rc = of_property_read_u8_array(nc, "spi-cal-data",
++ ctlr->cal_rule->match_data, value);
++ if(rc)
++ kfree(ctlr->cal_rule->match_data);
++ }
++
++ rc = of_property_read_u32(nc, "spi-cal-addrlen", &value);
++ if(!rc && value > 0) {
++ ctlr->cal_rule->addrlen = value;
++
++ ctlr->cal_rule->addr = kzalloc(value * sizeof(u32), GFP_KERNEL);
++ rc = of_property_read_u32_array(nc, "spi-cal-addr",
++ ctlr->cal_rule->addr, value);
++ if(rc)
++ kfree(ctlr->cal_rule->addr);
++ }
++ return 0;
++
++err:
++ alloc_cal_data(&ctlr->cal_target, &ctlr->cal_rule, false);
++ return 0;
++}
++
+ static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi,
+ struct device_node *nc)
+ {
+@@ -1841,6 +1974,10 @@ of_register_spi_device(struct spi_controller *ctlr, struct device_node *nc)
+ if (rc)
+ goto err_out;
+
++ rc = of_spi_parse_cal_dt(ctlr, spi, nc);
++ if (rc)
++ goto err_out;
++
+ /* Store a pointer to the node in the device structure */
+ of_node_get(nc);
+ spi->dev.of_node = nc;
+diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
+index 7067f85ce..5330cd9b0 100644
+--- a/include/linux/spi/spi.h
++++ b/include/linux/spi/spi.h
+@@ -264,6 +264,40 @@ struct spi_driver {
+ struct device_driver driver;
+ };
+
++enum {
++ SPI_CAL_READ_DATA = 0,
++ SPI_CAL_READ_PP = 1, /* only for SPI-NAND */
++ SPI_CAL_READ_SFDP = 2, /* only for SPI-NOR */
++};
++
++struct nand_addr {
++ unsigned int lun;
++ unsigned int plane;
++ unsigned int eraseblock;
++ unsigned int page;
++ unsigned int dataoffs;
++};
++
++/**
++ * Read calibration rule from device dts node.
++ * Once calibration result matches the rule, we regard is as success.
++ */
++struct spi_cal_rule {
++ int datalen;
++ u8 *match_data;
++ int addrlen;
++ u32 *addr;
++ int mode;
++};
++
++struct spi_cal_target {
++ u32 *cal_item;
++ int cal_min; /* min of cal_item */
++ int cal_max; /* max of cal_item */
++ int step; /* Increase/decrease cal_item */
++ struct list_head list;
++};
++
+ static inline struct spi_driver *to_spi_driver(struct device_driver *drv)
+ {
+ return drv ? container_of(drv, struct spi_driver, driver) : NULL;
+@@ -606,6 +640,11 @@ struct spi_controller {
+ void *dummy_rx;
+ void *dummy_tx;
+
++ /* For calibration */
++ int (*append_caldata)(struct spi_controller *ctlr);
++ struct list_head *cal_target;
++ struct spi_cal_rule *cal_rule;
++
+ int (*fw_translate_cs)(struct spi_controller *ctlr, unsigned cs);
+ };
+
+@@ -1369,6 +1408,9 @@ spi_register_board_info(struct spi_board_info const *info, unsigned n)
+ { return 0; }
+ #endif
+
++extern int spi_do_calibration(struct spi_controller *ctlr,
++ struct spi_device *spi, int (*cal_read)(void *, u32 *, int, u8 *, int), void *drv_priv);
++
+ /* If you're hotplugging an adapter with devices (parport, usb, etc)
+ * use spi_new_device() to describe each device. You can also call
+ * spi_unregister_device() to start making that device vanish, but
+--
+2.18.0
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9015-drivers-spi-mem-Add-spi-calibration-hook.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9015-drivers-spi-mem-Add-spi-calibration-hook.patch
new file mode 100644
index 0000000..dcea7de
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9015-drivers-spi-mem-Add-spi-calibration-hook.patch
@@ -0,0 +1,48 @@
+From a4f235c3a3c4d25aa6a4417ce64831ca0b38c324 Mon Sep 17 00:00:00 2001
+From: "SkyLake.Huang" <skylake.huang@mediatek.com>
+Date: Thu, 23 Jun 2022 18:37:55 +0800
+Subject: [PATCH] drivers: spi-mem: Add spi calibration hook
+
+Signed-off-by: SkyLake.Huang <skylake.huang@mediatek.com>
+---
+ drivers/spi/spi-mem.c | 8 ++++++++
+ include/linux/spi/spi-mem.h | 4 ++++
+ 2 files changed, 12 insertions(+)
+
+diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c
+index 33115bcfc..b5ab26e9c 100644
+--- a/drivers/spi/spi-mem.c
++++ b/drivers/spi/spi-mem.c
+@@ -383,6 +383,14 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
+ }
+ EXPORT_SYMBOL_GPL(spi_mem_exec_op);
+
++int spi_mem_do_calibration(struct spi_mem *mem,
++ int (*cal_read)(void *priv, u32 *addr, int addrlen, u8 *buf, int readlen),
++ void *priv)
++{
++ return spi_do_calibration(mem->spi->controller, mem->spi, cal_read, priv);
++}
++EXPORT_SYMBOL_GPL(spi_mem_do_calibration);
++
+ /**
+ * spi_mem_get_name() - Return the SPI mem device name to be used by the
+ * upper layer if necessary
+diff --git a/include/linux/spi/spi-mem.h b/include/linux/spi/spi-mem.h
+index af9ff2f0f..e2cde8305 100644
+--- a/include/linux/spi/spi-mem.h
++++ b/include/linux/spi/spi-mem.h
+@@ -332,6 +332,10 @@ bool spi_mem_supports_op(struct spi_mem *mem,
+ int spi_mem_exec_op(struct spi_mem *mem,
+ const struct spi_mem_op *op);
+
++int spi_mem_do_calibration(struct spi_mem *mem,
++ int (*cal_read)(void *, u32 *, int, u8 *, int),
++ void *priv);
++
+ const char *spi_mem_get_name(struct spi_mem *mem);
+
+ struct spi_mem_dirmap_desc *
+--
+2.18.0
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9016-drivers-spi-mt65xx-Add-controller-calibration-parameter.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9016-drivers-spi-mt65xx-Add-controller-calibration-parameter.patch
new file mode 100644
index 0000000..2c51aa9
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9016-drivers-spi-mt65xx-Add-controller-calibration-parameter.patch
@@ -0,0 +1,48 @@
+From ac9ed3898b80a81ce220a682749767ef189094a8 Mon Sep 17 00:00:00 2001
+From: "SkyLake.Huang" <skylake.huang@mediatek.com>
+Date: Thu, 23 Jun 2022 18:39:03 +0800
+Subject: [PATCH] drivers: spi-mt65xx: Add controller's calibration paramter
+
+Signed-off-by: SkyLake.Huang <skylake.huang@mediatek.com>
+---
+ drivers/spi/spi-mt65xx.c | 17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c
+index 0afd00891..1b272d15c 100644
+--- a/drivers/spi/spi-mt65xx.c
++++ b/drivers/spi/spi-mt65xx.c
+@@ -727,6 +727,21 @@ static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id)
+ return IRQ_HANDLED;
+ }
+
++static int mtk_spi_append_caldata(struct spi_controller *ctlr)
++{
++ struct spi_cal_target *cal_target = kmalloc(sizeof(*cal_target), GFP_KERNEL);
++ struct mtk_spi *mdata = spi_master_get_devdata(ctlr);
++
++ cal_target->cal_item = &mdata->dev_config.get_tick_dly;
++ cal_target->cal_min = 0;
++ cal_target->cal_max = 7;
++ cal_target->step = 1;
++
++ list_add(&cal_target->list, ctlr->cal_target);
++
++ return 0;
++}
++
+ static int mtk_spi_mem_adjust_op_size(struct spi_mem *mem,
+ struct spi_mem_op *op)
+ {
+@@ -1009,6 +1024,8 @@ static int mtk_spi_probe(struct platform_device *pdev)
+ master->can_dma = mtk_spi_can_dma;
+ master->setup = mtk_spi_setup;
+
++ master->append_caldata = mtk_spi_append_caldata;
++
+ of_id = of_match_node(mtk_spi_of_match, pdev->dev.of_node);
+ if (!of_id) {
+ dev_err(&pdev->dev, "failed to probe of_node\n");
+--
+2.18.0
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9017-drivers-mtd-spinand-Add-calibration-support-for-spinand.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9017-drivers-mtd-spinand-Add-calibration-support-for-spinand.patch
new file mode 100644
index 0000000..374531b
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9017-drivers-mtd-spinand-Add-calibration-support-for-spinand.patch
@@ -0,0 +1,89 @@
+From 6bd88d34cb5a5cb1d7c544c9f5b430105b000308 Mon Sep 17 00:00:00 2001
+From: "SkyLake.Huang" <skylake.huang@mediatek.com>
+Date: Thu, 23 Jun 2022 18:39:56 +0800
+Subject: [PATCH] drivers: mtd: spinand: Add calibration support for spinand
+
+Signed-off-by: SkyLake.Huang <skylake.huang@mediatek.com>
+---
+ drivers/mtd/nand/spi/core.c | 58 +++++++++++++++++++++++++++++++++++++
+ 1 file changed, 58 insertions(+)
+
+diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
+index 9f5f95ff7..b346c7a8a 100644
+--- a/drivers/mtd/nand/spi/core.c
++++ b/drivers/mtd/nand/spi/core.c
+@@ -789,6 +789,60 @@ static int spinand_manufacturer_match(struct spinand_device *spinand,
+ return -ENOTSUPP;
+ }
+
++int spinand_cal_read(void *priv, u32 *addr, int addrlen, u8 *buf, int readlen) {
++ int ret;
++ u8 status;
++ struct spinand_device *spinand = (struct spinand_device *)priv;
++ struct device *dev = &spinand->spimem->spi->dev;
++
++ typedef struct nand_pos my_pos;
++ my_pos pos;
++ typedef struct nand_page_io_req my_req;
++ my_req req;
++
++ if(addrlen != sizeof(struct nand_addr)/sizeof(unsigned int)) {
++ dev_err(dev, "Must provide correct addr(length) for spinand calibration\n");
++ return -EINVAL;
++ }
++
++ ret = spinand_reset_op(spinand);
++ if (ret)
++ return ret;
++
++ /* We should store our golden data in first target because
++ * we can't switch target at this moment.
++ */
++ pos = (my_pos){
++ .target = 0,
++ .lun = *addr,
++ .plane = *(addr+1),
++ .eraseblock = *(addr+2),
++ .page = *(addr+3),
++ };
++
++ req = (my_req){
++ .pos = pos,
++ .dataoffs = *(addr+4),
++ .datalen = readlen,
++ .databuf.in = buf,
++ .mode = MTD_OPS_AUTO_OOB,
++ };
++
++ ret = spinand_load_page_op(spinand, &req);
++ if (ret)
++ return ret;
++
++ ret = spinand_wait(spinand, &status);
++ if (ret < 0)
++ return ret;
++
++ struct spi_mem_op op = SPINAND_PAGE_READ_FROM_CACHE_OP(
++ false, 0, 1, buf, readlen);
++ ret = spi_mem_exec_op(spinand->spimem, &op);
++
++ return 0;
++}
++
+ static int spinand_id_detect(struct spinand_device *spinand)
+ {
+ u8 *id = spinand->id.data;
+@@ -1004,6 +1058,10 @@ static int spinand_init(struct spinand_device *spinand)
+ if (!spinand->scratchbuf)
+ return -ENOMEM;
+
++ ret = spi_mem_do_calibration(spinand->spimem, spinand_cal_read, spinand);
++ if (ret)
++ dev_err(dev, "Failed to calibrate SPI-NAND (err = %d)\n", ret);
++
+ ret = spinand_detect(spinand);
+ if (ret)
+ goto err_free_bufs;
+--
+2.18.0
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9018-drivers-mtd-spi-nor-Add-calibration-support-for-spi-nor.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9018-drivers-mtd-spi-nor-Add-calibration-support-for-spi-nor.patch
new file mode 100644
index 0000000..023f52e
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9018-drivers-mtd-spi-nor-Add-calibration-support-for-spi-nor.patch
@@ -0,0 +1,48 @@
+From b242e30661dac5c1c127999600029cd5b3f6b458 Mon Sep 17 00:00:00 2001
+From: "SkyLake.Huang" <skylake.huang@mediatek.com>
+Date: Thu, 23 Jun 2022 18:40:59 +0800
+Subject: [PATCH] drivers: mtd: spi-nor: Add calibration support for spi-nor
+
+Signed-off-by: SkyLake.Huang <skylake.huang@mediatek.com>
+---
+ drivers/mtd/spi-nor/spi-nor.c | 17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
+index 945833cbb..38a8948b3 100644
+--- a/drivers/mtd/spi-nor/spi-nor.c
++++ b/drivers/mtd/spi-nor/spi-nor.c
+@@ -4893,6 +4893,20 @@ static void spi_nor_debugfs_init(struct spi_nor *nor,
+ info->id_len, info->id);
+ }
+
++static int spi_nor_cal_read(void *priv, u32 *addr, int addrlen, u8 *buf, int readlen)
++{
++ int ret;
++ struct spi_nor *nor = (struct spi_nor *)priv;
++
++ nor->reg_proto = SNOR_PROTO_1_1_1;
++ nor->read_proto = SNOR_PROTO_1_1_1;
++ nor->read_opcode = SPINOR_OP_READ;
++ nor->addr_width = 3;
++ nor->read_dummy = 0;
++
++ return spi_nor_read_raw(nor, *addr, readlen, buf);
++}
++
+ static const struct flash_info *spi_nor_get_flash_info(struct spi_nor *nor,
+ const char *name)
+ {
+@@ -4967,6 +4981,9 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
+ if (!nor->bouncebuf)
+ return -ENOMEM;
+
++ if(nor->spimem)
++ spi_mem_do_calibration(nor->spimem, spi_nor_cal_read, nor);
++
+ info = spi_nor_get_flash_info(nor, name);
+ if (IS_ERR(info))
+ return PTR_ERR(info);
+--
+2.18.0
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9019-drivers-char-tpm-Add-calibration-example-for-SPI-TPM-module.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9019-drivers-char-tpm-Add-calibration-example-for-SPI-TPM-module.patch
new file mode 100644
index 0000000..8b39b12
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9019-drivers-char-tpm-Add-calibration-example-for-SPI-TPM-module.patch
@@ -0,0 +1,97 @@
+From 6110010f7b88392a3094f2aaec91ee54151cde2a Mon Sep 17 00:00:00 2001
+From: "SkyLake.Huang" <skylake.huang@mediatek.com>
+Date: Thu, 23 Jun 2022 18:43:02 +0800
+Subject: [PATCH] drivers: char: tpm: Add calibration example for SPI TPM
+ module
+
+Signed-off-by: SkyLake.Huang <skylake.huang@mediatek.com>
+---
+ drivers/char/tpm/tpm_tis_core.c | 19 +++++++++++++++++++
+ drivers/char/tpm/tpm_tis_core.h | 2 ++
+ drivers/char/tpm/tpm_tis_spi.c | 7 +++++++
+ 3 files changed, 28 insertions(+)
+
+diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
+index 70f785994..b9898a56d 100644
+--- a/drivers/char/tpm/tpm_tis_core.c
++++ b/drivers/char/tpm/tpm_tis_core.c
+@@ -817,6 +817,21 @@ static const struct tpm_class_ops tpm_tis = {
+ .clk_enable = tpm_tis_clkrun_enable,
+ };
+
++int tpm_tis_cal_read(void *priv, u32 *addr, int addrlen, u8 *buf, int readlen)
++{
++ int rc;
++ u32 vendor;
++
++ rc = tpm_tis_read32((struct tpm_tis_data *)priv, TPM_DID_VID(0), &vendor);
++ if (rc < 0)
++ return -EIO;
++
++ buf[0] = (vendor >> 24) & 0xff;
++ buf[1] = (vendor >> 16) & 0xff;
++
++ return 0;
++}
++
+ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
+ const struct tpm_tis_phy_ops *phy_ops,
+ acpi_handle acpi_dev_handle)
+@@ -864,6 +879,10 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
+ if (chip->ops->clk_enable != NULL)
+ chip->ops->clk_enable(chip, true);
+
++ rc = priv->phy_ops->do_calibration(priv, dev);
++ if (rc)
++ goto out_err;
++
+ if (wait_startup(chip, 0) != 0) {
+ rc = -ENODEV;
+ goto out_err;
+diff --git a/drivers/char/tpm/tpm_tis_core.h b/drivers/char/tpm/tpm_tis_core.h
+index 7337819f5..7bb0bc8b6 100644
+--- a/drivers/char/tpm/tpm_tis_core.h
++++ b/drivers/char/tpm/tpm_tis_core.h
+@@ -106,6 +106,7 @@ struct tpm_tis_phy_ops {
+ int (*read16)(struct tpm_tis_data *data, u32 addr, u16 *result);
+ int (*read32)(struct tpm_tis_data *data, u32 addr, u32 *result);
+ int (*write32)(struct tpm_tis_data *data, u32 addr, u32 src);
++ int (*do_calibration)(struct tpm_tis_data *data, struct device *dev);
+ };
+
+ static inline int tpm_tis_read_bytes(struct tpm_tis_data *data, u32 addr,
+@@ -158,6 +159,7 @@ static inline bool is_bsw(void)
+ }
+
+ void tpm_tis_remove(struct tpm_chip *chip);
++int tpm_tis_cal_read(void *priv, u32 *addr, int addrlen, u8 *buf, int readlen);
+ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
+ const struct tpm_tis_phy_ops *phy_ops,
+ acpi_handle acpi_dev_handle);
+diff --git a/drivers/char/tpm/tpm_tis_spi.c b/drivers/char/tpm/tpm_tis_spi.c
+index 19513e622..3be2d53a5 100644
+--- a/drivers/char/tpm/tpm_tis_spi.c
++++ b/drivers/char/tpm/tpm_tis_spi.c
+@@ -184,12 +184,19 @@ static int tpm_tis_spi_write32(struct tpm_tis_data *data, u32 addr, u32 value)
+ return rc;
+ }
+
++int tpm_tis_spi_do_calibration(struct tpm_tis_data *priv, struct device *dev) {
++ struct spi_device *spi = container_of(dev,
++ struct spi_device, dev);
++ return spi_do_calibration(spi->master, spi, tpm_tis_cal_read, priv);
++}
++
+ static const struct tpm_tis_phy_ops tpm_spi_phy_ops = {
+ .read_bytes = tpm_tis_spi_read_bytes,
+ .write_bytes = tpm_tis_spi_write_bytes,
+ .read16 = tpm_tis_spi_read16,
+ .read32 = tpm_tis_spi_read32,
+ .write32 = tpm_tis_spi_write32,
++ .do_calibration = tpm_tis_spi_do_calibration,
+ };
+
+ static int tpm_tis_spi_probe(struct spi_device *dev)
+--
+2.18.0
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/patches-5.4.inc b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/patches-5.4.inc
index cc42f21..ae8ba9b 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/patches-5.4.inc
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/patches-5.4.inc
@@ -103,4 +103,11 @@
file://9009-Add-spi-runtime-PM-support.patch \
file://9010-iwconfig-wireless-rate-fix.patch;apply=no \
file://9011-Modify-tick_delay-for-spi-work-safety.patch \
+ file://9013-drivers-spi-mt65xx-Move-chip_config-to-driver-priv.patch \
+ file://9014-drivers-spi-Add-support-for-dynamic-calibration.patch \
+ file://9015-drivers-spi-mem-Add-spi-calibration-hook.patch \
+ file://9016-drivers-spi-mt65xx-Add-controller-calibration-parameter.patch \
+ file://9017-drivers-mtd-spinand-Add-calibration-support-for-spinand.patch \
+ file://9018-drivers-mtd-spi-nor-Add-calibration-support-for-spi-nor.patch \
+ file://9019-drivers-char-tpm-Add-calibration-example-for-SPI-TPM-module.patch \
"