[rdkb][Common][bsp][Refactor and sync kernel from openwrt]
[Description]
8a990d32 [kernel][mt7986][eth][mediatek-ge: Remove Kconfig option to pass build]
18edade5 [kernel][mt7981][mtd][spinand: Add Etron SPI-NAND support]
c79f5ed5 [kernel][mt7988][eth][fix TDMA Tx monitor]
9f3e8d96 [kernel][common][eth][fix missing DMA tx/rx monitor]
6bb9353b [SW framework][common][bsp][add panic write support for nmbm]
3f7796b4 [SW framework][common][snfi][add panic write support for mtk-snand]
adbd59a5 [Kernel][hnat][Fix log print level in foe_clear_entry]
1b4a861d [kernel][mt7988][eth][i2.5Gphy: Add 20230621 version firmware]
f8eec9df [Kernel][hnat][Fix possibly null pointer and memory leak]
891b26c2 [MAC80211][hnat][Fix patch fail issue]
11c3ac54 [Upgrade kernel version from 5.4.236 to 5.4.246]
00d07458 [kernel][common][eth][Add Airoha EN8811H v1.1.3 2.5G PHY firmware bins]
b23de2f3 [kernel][mt7988][eth][mediatek-ge-soc: Fix VCM K failure]
[Release-log]
Change-Id: Ie610fc884cf39d07d3f8625e0d0106af89dfa001
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/430-v6.3-ubi-Fix-failure-attaching-when-vid_hdr-offset-equals.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/430-v6.3-ubi-Fix-failure-attaching-when-vid_hdr-offset-equals.patch
index afb8e5e..e69de29 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/430-v6.3-ubi-Fix-failure-attaching-when-vid_hdr-offset-equals.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/430-v6.3-ubi-Fix-failure-attaching-when-vid_hdr-offset-equals.patch
@@ -1,69 +0,0 @@
-From 1e020e1b96afdecd20680b5b5be2a6ffc3d27628 Mon Sep 17 00:00:00 2001
-From: Zhihao Cheng <chengzhihao1@huawei.com>
-Date: Mon, 6 Mar 2023 09:33:08 +0800
-Subject: [PATCH] ubi: Fix failure attaching when vid_hdr offset equals to
- (sub)page size
-
-Following process will make ubi attaching failed since commit
-1b42b1a36fc946 ("ubi: ensure that VID header offset ... size"):
-
-ID="0xec,0xa1,0x00,0x15" # 128M 128KB 2KB
-modprobe nandsim id_bytes=$ID
-flash_eraseall /dev/mtd0
-modprobe ubi mtd="0,2048" # set vid_hdr offset as 2048 (one page)
-(dmesg):
- ubi0 error: ubi_attach_mtd_dev [ubi]: VID header offset 2048 too large.
- UBI error: cannot attach mtd0
- UBI error: cannot initialize UBI, error -22
-
-Rework original solution, the key point is making sure
-'vid_hdr_shift + UBI_VID_HDR_SIZE < ubi->vid_hdr_alsize',
-so we should check vid_hdr_shift rather not vid_hdr_offset.
-Then, ubi still support (sub)page aligined VID header offset.
-
-Fixes: 1b42b1a36fc946 ("ubi: ensure that VID header offset ... size")
-Signed-off-by: Zhihao Cheng <chengzhihao1@huawei.com>
-Tested-by: Nicolas Schichan <nschichan@freebox.fr>
-Tested-by: Miquel Raynal <miquel.raynal@bootlin.com> # v5.10, v4.19
-Signed-off-by: Richard Weinberger <richard@nod.at>
----
- drivers/mtd/ubi/build.c | 21 +++++++++++++++------
- 1 file changed, 15 insertions(+), 6 deletions(-)
-
---- a/drivers/mtd/ubi/build.c
-+++ b/drivers/mtd/ubi/build.c
-@@ -644,12 +644,6 @@ static int io_init(struct ubi_device *ub
- ubi->ec_hdr_alsize = ALIGN(UBI_EC_HDR_SIZE, ubi->hdrs_min_io_size);
- ubi->vid_hdr_alsize = ALIGN(UBI_VID_HDR_SIZE, ubi->hdrs_min_io_size);
-
-- if (ubi->vid_hdr_offset && ((ubi->vid_hdr_offset + UBI_VID_HDR_SIZE) >
-- ubi->vid_hdr_alsize)) {
-- ubi_err(ubi, "VID header offset %d too large.", ubi->vid_hdr_offset);
-- return -EINVAL;
-- }
--
- dbg_gen("min_io_size %d", ubi->min_io_size);
- dbg_gen("max_write_size %d", ubi->max_write_size);
- dbg_gen("hdrs_min_io_size %d", ubi->hdrs_min_io_size);
-@@ -667,6 +661,21 @@ static int io_init(struct ubi_device *ub
- ubi->vid_hdr_aloffset;
- }
-
-+ /*
-+ * Memory allocation for VID header is ubi->vid_hdr_alsize
-+ * which is described in comments in io.c.
-+ * Make sure VID header shift + UBI_VID_HDR_SIZE not exceeds
-+ * ubi->vid_hdr_alsize, so that all vid header operations
-+ * won't access memory out of bounds.
-+ */
-+ if ((ubi->vid_hdr_shift + UBI_VID_HDR_SIZE) > ubi->vid_hdr_alsize) {
-+ ubi_err(ubi, "Invalid VID header offset %d, VID header shift(%d)"
-+ " + VID header size(%zu) > VID header aligned size(%d).",
-+ ubi->vid_hdr_offset, ubi->vid_hdr_shift,
-+ UBI_VID_HDR_SIZE, ubi->vid_hdr_alsize);
-+ return -EINVAL;
-+ }
-+
- /* Similar for the data offset */
- ubi->leb_start = ubi->vid_hdr_offset + UBI_VID_HDR_SIZE;
- ubi->leb_start = ALIGN(ubi->leb_start, ubi->min_io_size);
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/backport-5.4.inc b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/backport-5.4.inc
index 0ed63ca..c7ea67c 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/backport-5.4.inc
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/backport-5.4.inc
@@ -172,7 +172,7 @@
file://417-v6.2-0001-mtd-core-simplify-a-bit-code-find-partition-matching.patch \
file://417-v6.2-0002-mtd-core-try-to-find-OF-node-for-every-MTD-partition.patch \
file://420-v6.2-mtd-parsers-add-TP-Link-SafeLoader-partitions-table-.patch \
- file://430-v6.3-ubi-Fix-failure-attaching-when-vid_hdr-offset-equals.patch \
+ file://430-v6.3-ubi-Fix-failure-attaching-when-vid_hdr-offset-equals.patch;apply=no \
file://600-v5.12-net-extract-napi-poll-functionality-to-__napi_poll.patch \
file://601-v5.12-net-implement-threaded-able-napi-poll-loop-support.patch \
file://602-v5.12-net-add-sysfs-attribute-to-control-napi-threaded-mod.patch \
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/files-5.4/drivers/mtd/nmbm/nmbm-core.c b/recipes-kernel/linux/linux-mediatek-5.4/generic/files-5.4/drivers/mtd/nmbm/nmbm-core.c
index b80ea42..9dc4a10 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/files-5.4/drivers/mtd/nmbm/nmbm-core.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/files-5.4/drivers/mtd/nmbm/nmbm-core.c
@@ -257,6 +257,37 @@
}
/*
+ * nmbm_panic_write_phys_page - Panic write page with retry
+ * @ni: NMBM instance structure
+ * @addr: linear address where the data will be written to
+ * @data: the main data to be written
+ *
+ * Write a page for at most NMBM_TRY_COUNT times.
+ */
+static bool nmbm_panic_write_phys_page(struct nmbm_instance *ni, uint64_t addr,
+ const void *data)
+{
+ int tries, ret;
+
+ if (ni->lower.flags & NMBM_F_READ_ONLY) {
+ nlog_err(ni, "%s called with NMBM_F_READ_ONLY set\n", addr);
+ return false;
+ }
+
+ for (tries = 0; tries < NMBM_TRY_COUNT; tries++) {
+ ret = ni->lower.panic_write_page(ni->lower.arg, addr, data);
+ if (!ret)
+ return true;
+
+ nmbm_reset_chip(ni);
+ }
+
+ nlog_err(ni, "Panic page write failed at address 0x%08llx\n", addr);
+
+ return false;
+}
+
+/*
* nmbm_erase_phys_block - Erase a block with retry
* @ni: NMBM instance structure
* @addr: Linear address
@@ -2730,6 +2761,56 @@
}
/*
+ * nmbm_panic_write_logic_page - Panic write page based on logic address
+ * @ni: NMBM instance structure
+ * @addr: logic linear address
+ * @data: buffer contains main data. optional.
+ */
+static int nmbm_panic_write_logic_page(struct nmbm_instance *ni, uint64_t addr,
+ const void *data)
+{
+ uint32_t lb, pb, offset;
+ uint64_t paddr;
+ bool success;
+
+ if (!ni->lower.panic_write_page)
+ return -ENOTSUPP;
+
+ /* Extract block address and in-block offset */
+ lb = addr2ba(ni, addr);
+ offset = addr & ni->erasesize_mask;
+
+ /* Map logic block to physical block */
+ pb = ni->block_mapping[lb];
+
+ /* Whether the logic block is good (has valid mapping) */
+ if ((int32_t)pb < 0) {
+ nlog_debug(ni, "Logic block %u is a bad block\n", lb);
+ return -EIO;
+ }
+
+ /* Fail if physical block is marked bad */
+ if (nmbm_get_block_state(ni, pb) == BLOCK_ST_BAD)
+ return -EIO;
+
+ /* Assemble new address */
+ paddr = ba2addr(ni, pb) + offset;
+
+ success = nmbm_panic_write_phys_page(ni, paddr, data);
+ if (success)
+ return 0;
+
+ /*
+ * Do not remap bad block here. Just mark this block in state table.
+ * Remap this block on erasing.
+ */
+ nmbm_set_block_state(ni, pb, BLOCK_ST_NEED_REMAP);
+ nmbm_update_info_table(ni);
+
+ return -EIO;
+}
+
+/*
* nmbm_write_single_page - Write one page based on logic address
* @ni: NMBM instance structure
* @addr: logic linear address
@@ -2759,6 +2840,32 @@
}
/*
+ * nmbm_panic_write_single_page - Panic write one page based on logic address
+ * @ni: NMBM instance structure
+ * @addr: logic linear address
+ * @data: buffer contains main data. optional.
+ */
+int nmbm_panic_write_single_page(struct nmbm_instance *ni, uint64_t addr,
+ const void *data)
+{
+ if (!ni)
+ return -EINVAL;
+
+ /* Sanity check */
+ if (ni->protected || (ni->lower.flags & NMBM_F_READ_ONLY)) {
+ nlog_debug(ni, "Device is forced read-only\n");
+ return -EROFS;
+ }
+
+ if (addr >= ba2addr(ni, ni->data_block_count)) {
+ nlog_err(ni, "Address 0x%llx is invalid\n", addr);
+ return -EINVAL;
+ }
+
+ return nmbm_panic_write_logic_page(ni, addr, data);
+}
+
+/*
* nmbm_write_range - Write data without oob
* @ni: NMBM instance structure
* @addr: logic linear address
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/files-5.4/drivers/mtd/nmbm/nmbm-mtd.c b/recipes-kernel/linux/linux-mediatek-5.4/generic/files-5.4/drivers/mtd/nmbm/nmbm-mtd.c
index a3e9e18..94413a3 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/files-5.4/drivers/mtd/nmbm/nmbm-mtd.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/files-5.4/drivers/mtd/nmbm/nmbm-mtd.c
@@ -141,6 +141,16 @@
return mtd_write_oob(nm->lower, addr, &ops);
}
+static int nmbm_lower_panic_write_page(void *arg, uint64_t addr,
+ const void *buf)
+{
+ struct nmbm_mtd *nm = arg;
+ size_t retlen;
+
+ return mtd_panic_write(nm->lower, addr, nm->lower->writesize, &retlen,
+ buf);
+}
+
static int nmbm_lower_erase_block(void *arg, uint64_t addr)
{
struct nmbm_mtd *nm = arg;
@@ -538,6 +548,44 @@
return ret;
}
+static int nmbm_mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len,
+ size_t *retlen, const u_char *buf)
+{
+ struct nmbm_mtd *nm = container_of(mtd, struct nmbm_mtd, upper);
+ size_t chklen, wrlen = 0;
+ uint32_t col;
+ int ret;
+
+ col = to & nm->lower->writesize_mask;
+ to &= ~nm->lower->writesize_mask;
+
+ while (len) {
+ /* Move data */
+ chklen = nm->lower->writesize - col;
+ if (chklen > len)
+ chklen = len;
+
+ if (chklen < nm->lower->writesize)
+ memset(nm->page_cache, 0xff, nm->lower->writesize);
+ memcpy(nm->page_cache + col, buf + wrlen, chklen);
+
+ len -= chklen;
+ col = 0; /* (col + chklen) % */
+ wrlen += chklen;
+
+ ret = nmbm_panic_write_single_page(nm->ni, to, nm->page_cache);
+ if (ret)
+ break;
+
+ to += nm->lower->writesize;
+ }
+
+ if (retlen)
+ *retlen = wrlen;
+
+ return 0;
+}
+
static int nmbm_mtd_block_isbad(struct mtd_info *mtd, loff_t offs)
{
struct nmbm_mtd *nm = container_of(mtd, struct nmbm_mtd, upper);
@@ -634,6 +682,7 @@
nld.read_page = nmbm_lower_read_page;
nld.write_page = nmbm_lower_write_page;
+ nld.panic_write_page = nmbm_lower_panic_write_page;
nld.erase_block = nmbm_lower_erase_block;
nld.is_bad_block = nmbm_lower_is_bad_block;
nld.mark_bad_block = nmbm_lower_mark_bad_block;
@@ -697,6 +746,7 @@
mtd->_erase = nmbm_mtd_erase;
mtd->_read_oob = nmbm_mtd_read_oob;
mtd->_write_oob = nmbm_mtd_write_oob;
+ mtd->_panic_write = nmbm_mtd_panic_write;
mtd->_block_isbad = nmbm_mtd_block_isbad;
mtd->_block_markbad = nmbm_mtd_block_markbad;
mtd->_reboot = nmbm_mtd_shutdown;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/files-5.4/include/nmbm/nmbm.h b/recipes-kernel/linux/linux-mediatek-5.4/generic/files-5.4/include/nmbm/nmbm.h
index c040098..0f43466 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/files-5.4/include/nmbm/nmbm.h
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/files-5.4/include/nmbm/nmbm.h
@@ -52,6 +52,7 @@
*/
int (*read_page)(void *arg, uint64_t addr, void *buf, void *oob, enum nmbm_oob_mode mode);
int (*write_page)(void *arg, uint64_t addr, const void *buf, const void *oob, enum nmbm_oob_mode mode);
+ int (*panic_write_page)(void *arg, uint64_t addr, const void *buf);
int (*erase_block)(void *arg, uint64_t addr);
int (*is_bad_block)(void *arg, uint64_t addr);
@@ -88,6 +89,8 @@
int nmbm_write_single_page(struct nmbm_instance *ni, uint64_t addr,
const void *data, const void *oob,
enum nmbm_oob_mode mode);
+int nmbm_panic_write_single_page(struct nmbm_instance *ni, uint64_t addr,
+ const void *data);
int nmbm_write_range(struct nmbm_instance *ni, uint64_t addr, size_t size,
const void *data, enum nmbm_oob_mode mode,
size_t *retlen);
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/mtd/mtk-snand/mtk-snand-mtd.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/mtd/mtk-snand/mtk-snand-mtd.c
index 09dc34d..61d75d3 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/mtd/mtk-snand/mtk-snand-mtd.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/mtd/mtk-snand/mtk-snand-mtd.c
@@ -352,6 +352,50 @@
return ret;
}
+static int mtk_snand_mtd_panic_write(struct mtd_info *mtd, loff_t to,
+ size_t len, size_t *retlen,
+ const u_char *buf)
+{
+ struct mtk_snand_mtd *msm = mtd_to_msm(mtd);
+ size_t chklen, wrlen = 0;
+ uint32_t col;
+ int ret;
+
+ /* Disable IRQ and enter poll mode */
+ disable_irq(msm->irq);
+ mtk_snand_control_poll_mode(&msm->pdev, true);
+
+ col = to & mtd->writesize_mask;
+ to &= ~mtd->writesize_mask;
+
+ while (len) {
+ /* Move data */
+ chklen = mtd->writesize - col;
+ if (chklen > len)
+ chklen = len;
+
+ if (chklen < mtd->writesize)
+ memset(msm->page_cache, 0xff, mtd->writesize);
+ memcpy(msm->page_cache + col, buf + wrlen, chklen);
+
+ len -= chklen;
+ col = 0; /* (col + chklen) % */
+ wrlen += chklen;
+
+ ret = mtk_snand_write_page(msm->snf, to, msm->page_cache,
+ NULL, false);
+ if (ret)
+ break;
+
+ to += mtd->writesize;
+ }
+
+ if (retlen)
+ *retlen = wrlen;
+
+ return ret;
+}
+
static int mtk_snand_mtd_block_isbad(struct mtd_info *mtd, loff_t offs)
{
struct mtk_snand_mtd *msm = mtd_to_msm(mtd);
@@ -663,6 +707,7 @@
mtd->_erase = mtk_snand_mtd_erase;
mtd->_read_oob = mtk_snand_mtd_read_oob;
mtd->_write_oob = mtk_snand_mtd_write_oob;
+ mtd->_panic_write = mtk_snand_mtd_panic_write;
mtd->_block_isbad = mtk_snand_mtd_block_isbad;
mtd->_block_markbad = mtk_snand_mtd_block_markbad;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/mtd/mtk-snand/mtk-snand-os.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/mtd/mtk-snand/mtk-snand-os.c
index 0c3ffec..416a6a2 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/mtd/mtk-snand/mtk-snand-os.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/mtd/mtk-snand/mtk-snand-os.c
@@ -46,3 +46,15 @@
return 0;
}
+
+void mtk_snand_control_poll_mode(struct mtk_snand_plat_dev *pdev, bool enable)
+{
+ if (!pdev)
+ return;
+
+ if (pdev->poll_mode != enable)
+ dev_info(pdev->dev, "Poll mode %s\b", enable ? "enabled" :
+ "disabled");
+
+ pdev->poll_mode = enable;
+}
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/mtd/mtk-snand/mtk-snand-os.h b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/mtd/mtk-snand/mtk-snand-os.h
index 223f73f..b392f34 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/mtd/mtk-snand/mtk-snand-os.h
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/mtd/mtk-snand/mtk-snand-os.h
@@ -24,6 +24,7 @@
struct mtk_snand_plat_dev {
struct device *dev;
struct completion done;
+ bool poll_mode;
};
/* Polling helpers */
@@ -102,32 +103,34 @@
/* Interrupt helpers */
static inline void irq_completion_done(struct mtk_snand_plat_dev *pdev)
{
- complete(&pdev->done);
+ if (!pdev->poll_mode)
+ complete(&pdev->done);
}
static inline void irq_completion_init(struct mtk_snand_plat_dev *pdev)
{
- init_completion(&pdev->done);
+ if (!pdev->poll_mode)
+ init_completion(&pdev->done);
}
static inline int irq_completion_wait(struct mtk_snand_plat_dev *pdev,
void __iomem *reg, uint32_t bit,
uint32_t timeout_us)
{
-#if 0
uint32_t val;
-
- return read32_poll_timeout(reg, val, val & bit, 0, timeout_us);
-#else
int ret;
+ if (pdev->poll_mode)
+ return read32_poll_timeout(reg, val, val & bit, 0, timeout_us);
+
ret = wait_for_completion_timeout(&pdev->done,
usecs_to_jiffies(timeout_us));
if (!ret)
return -ETIMEDOUT;
return 0;
-#endif
}
+void mtk_snand_control_poll_mode(struct mtk_snand_plat_dev *pdev, bool enable);
+
#endif /* _MTK_SNAND_OS_H_ */
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 1b5d356..a1db345 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
@@ -1124,6 +1124,24 @@
.release = single_release
};
+static int mtk_rss_set_indr_tbl(struct mtk_eth *eth, int num)
+{
+ struct mtk_rss_params *rss_params = ð->rss_params;
+ u32 i;
+
+ if (num <= 0 || num > MTK_RX_NAPI_NUM)
+ return -EOPNOTSUPP;
+
+ for (i = 0; i < MTK_RSS_MAX_INDIRECTION_TABLE; i++)
+ rss_params->indirection_table[i] = i % num;
+
+ for (i = 0; i < MTK_RSS_MAX_INDIRECTION_TABLE / 16; i++)
+ mtk_w32(eth, mtk_rss_indr_table(rss_params, i),
+ MTK_RSS_INDR_TABLE_DW(i));
+
+ return 0;
+}
+
ssize_t rss_ctrl_write(struct file *file, const char __user *buffer,
size_t count, loff_t *data)
{
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_reset.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_reset.c
index 66b4646..1042685 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_reset.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_reset.c
@@ -431,22 +431,29 @@
u32 mtk_monitor_tdma_tx(struct mtk_eth *eth)
{
static u32 err_cnt_ttx;
+ static u32 pre_ipq10;
static u32 pre_fsm;
u32 err_flag = 0;
u32 cur_fsm = 0;
u32 tx_busy = 0;
+ u32 ipq10;
if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
+ ipq10 = mtk_r32(eth, MTK_PSE_IQ_STA(6)) & 0xFFF;
cur_fsm = (mtk_r32(eth, MTK_FE_CDM6_FSM) & 0x1FFF) != 0;
tx_busy = ((mtk_r32(eth, MTK_TDMA_GLO_CFG) & 0x2) != 0);
- if (cur_fsm == pre_fsm && cur_fsm != 0 && tx_busy) {
+ if (ipq10 && cur_fsm && tx_busy
+ && cur_fsm == pre_fsm
+ && ipq10 == pre_ipq10) {
err_cnt_ttx++;
if (err_cnt_ttx >= 3) {
pr_info("TDMA Tx Info\n");
pr_info("err_cnt = %d", err_cnt_ttx);
- pr_info("CDM6_FSM = %d\n",
- mtk_r32(eth, MTK_FE_CDM6_FSM));
+ pr_info("CDM6_FSM = 0x%x, PRE_CDM6_FSM = 0x%x\n",
+ mtk_r32(eth, MTK_FE_CDM6_FSM), pre_fsm);
+ pr_info("PSE_IQ_P10 = 0x%x, PRE_PSE_IQ_P10 = 0x%x\n",
+ mtk_r32(eth, MTK_PSE_IQ_STA(6)), pre_ipq10);
pr_info("DMA CFG = 0x%x\n",
mtk_r32(eth, MTK_TDMA_GLO_CFG));
pr_info("==============================\n");
@@ -456,6 +463,7 @@
err_cnt_ttx = 0;
pre_fsm = cur_fsm;
+ pre_ipq10 = ipq10;
}
if (err_flag)
@@ -515,7 +523,7 @@
struct mtk_eth *eth = from_timer(eth, t, mtk_dma_monitor_timer);
u32 i = 0, ret = 0;
- for (i = 0; i < 6; i++) {
+ for (i = 0; i < ARRAY_SIZE(mtk_reset_monitor_func); i++) {
ret = (*mtk_reset_monitor_func[i]) (eth);
if ((ret == MTK_FE_START_RESET) ||
(ret == MTK_FE_STOP_TRAFFIC)) {
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 78ac67e..0c94e93 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
@@ -3015,27 +3015,33 @@
return 0;
}
-int mtk_rss_set_indr_tbl(struct mtk_eth *eth, int num)
+u32 mtk_rss_indr_table(struct mtk_rss_params *rss_params, int index)
{
- u32 i, config;
-
- if (num <= 0 || num > MTK_RX_NAPI_NUM)
- return -EOPNOTSUPP;
-
- for (i = 0, config = 0; i < 16; i++) {
- config <<= 2;
- config |= (i % num);
- }
+ u32 val = 0;
+ int i;
- for (i = 0; i < 8; i++)
- mtk_w32(eth, config, MTK_RSS_INDR_TABLE_DW(i));
+ for (i = 16 * index; i < 16 * index + 16; i++)
+ val |= (rss_params->indirection_table[i] << (2 * (i % 16)));
- return 0;
+ return val;
}
static int mtk_rss_init(struct mtk_eth *eth)
{
+ struct mtk_rss_params *rss_params = ð->rss_params;
+ static u8 hash_key[MTK_RSS_HASH_KEYSIZE] = {
+ 0xfa, 0x01, 0xac, 0xbe, 0x3b, 0xb7, 0x42, 0x6a,
+ 0x0c, 0xf2, 0x30, 0x80, 0xa3, 0x2d, 0xcb, 0x77,
+ 0xb4, 0x30, 0x7b, 0xae, 0xcb, 0x2b, 0xca, 0xd0,
+ 0xb0, 0x8f, 0xa3, 0x43, 0x3d, 0x25, 0x67, 0x41,
+ 0xc2, 0x0e, 0x5b, 0x25, 0xda, 0x56, 0x5a, 0x6d};
u32 val;
+ int i;
+
+ memcpy(rss_params->hash_key, hash_key, MTK_RSS_HASH_KEYSIZE);
+
+ for (i = 0; i < MTK_RSS_MAX_INDIRECTION_TABLE; i++)
+ rss_params->indirection_table[i] = i % eth->soc->rss_num;
if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_RX_V2)) {
/* Set RSS rings to PSE modes */
@@ -3062,8 +3068,14 @@
val |= MTK_RSS_IPV6_STATIC_HASH;
mtk_w32(eth, val, MTK_PDMA_RSS_GLO_CFG);
+ /* Hash Key */
+ for (i = 0; i < MTK_RSS_HASH_KEYSIZE / sizeof(u32); i++)
+ mtk_w32(eth, rss_params->hash_key[i], MTK_RSS_HASH_KEY_DW(i));
+
/* Select the size of indirection table */
- mtk_rss_set_indr_tbl(eth, eth->soc->rss_num);
+ for (i = 0; i < MTK_RSS_MAX_INDIRECTION_TABLE / 16; i++)
+ mtk_w32(eth, mtk_rss_indr_table(rss_params, i),
+ MTK_RSS_INDR_TABLE_DW(i));
/* Pause */
val |= MTK_RSS_CFG_REQ;
@@ -4255,6 +4267,8 @@
static int mtk_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
u32 *rule_locs)
{
+ struct mtk_mac *mac = netdev_priv(dev);
+ struct mtk_eth *eth = mac->hw;
int ret = -EOPNOTSUPP;
switch (cmd->cmd) {
@@ -4262,12 +4276,13 @@
if (dev->hw_features & NETIF_F_LRO) {
cmd->data = MTK_MAX_RX_RING_NUM;
ret = 0;
+ } else if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSS)) {
+ cmd->data = eth->soc->rss_num;
+ ret = 0;
}
break;
case ETHTOOL_GRXCLSRLCNT:
if (dev->hw_features & NETIF_F_LRO) {
- struct mtk_mac *mac = netdev_priv(dev);
-
cmd->rule_cnt = mac->hwlro_ip_cnt;
ret = 0;
}
@@ -4308,6 +4323,73 @@
return ret;
}
+static u32 mtk_get_rxfh_key_size(struct net_device *dev)
+{
+ return MTK_RSS_HASH_KEYSIZE;
+}
+
+static u32 mtk_get_rxfh_indir_size(struct net_device *dev)
+{
+ return MTK_RSS_MAX_INDIRECTION_TABLE;
+}
+
+static int mtk_get_rxfh(struct net_device *dev, u32 *indir, u8 *key,
+ u8 *hfunc)
+{
+ struct mtk_mac *mac = netdev_priv(dev);
+ struct mtk_eth *eth = mac->hw;
+ struct mtk_rss_params *rss_params = ð->rss_params;
+ int i;
+
+ if (hfunc)
+ *hfunc = ETH_RSS_HASH_TOP; /* Toeplitz */
+
+ if (key) {
+ memcpy(key, rss_params->hash_key,
+ sizeof(rss_params->hash_key));
+ }
+
+ if (indir) {
+ for (i = 0; i < MTK_RSS_MAX_INDIRECTION_TABLE; i++)
+ indir[i] = rss_params->indirection_table[i];
+ }
+
+ return 0;
+}
+
+static int mtk_set_rxfh(struct net_device *dev, const u32 *indir,
+ const u8 *key, const u8 hfunc)
+{
+ struct mtk_mac *mac = netdev_priv(dev);
+ struct mtk_eth *eth = mac->hw;
+ struct mtk_rss_params *rss_params = ð->rss_params;
+ int i;
+
+ if (hfunc != ETH_RSS_HASH_NO_CHANGE &&
+ hfunc != ETH_RSS_HASH_TOP)
+ return -EOPNOTSUPP;
+
+ if (key) {
+ memcpy(rss_params->hash_key, key,
+ sizeof(rss_params->hash_key));
+
+ for (i = 0; i < MTK_RSS_HASH_KEYSIZE / sizeof(u32); i++)
+ mtk_w32(eth, rss_params->hash_key[i],
+ MTK_RSS_HASH_KEY_DW(i));
+ }
+
+ if (indir) {
+ for (i = 0; i < MTK_RSS_MAX_INDIRECTION_TABLE; i++)
+ rss_params->indirection_table[i] = indir[i];
+
+ for (i = 0; i < MTK_RSS_MAX_INDIRECTION_TABLE / 16; i++)
+ mtk_w32(eth, mtk_rss_indr_table(rss_params, i),
+ MTK_RSS_INDR_TABLE_DW(i));
+ }
+
+ return 0;
+}
+
static void mtk_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam *pause)
{
struct mtk_mac *mac = netdev_priv(dev);
@@ -4381,6 +4463,10 @@
.get_ethtool_stats = mtk_get_ethtool_stats,
.get_rxnfc = mtk_get_rxnfc,
.set_rxnfc = mtk_set_rxnfc,
+ .get_rxfh_key_size = mtk_get_rxfh_key_size,
+ .get_rxfh_indir_size = mtk_get_rxfh_indir_size,
+ .get_rxfh = mtk_get_rxfh,
+ .set_rxfh = mtk_set_rxfh,
.get_pauseparam = mtk_get_pauseparam,
.set_pauseparam = mtk_set_pauseparam,
.get_eee = mtk_get_eee,
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 01e15fe..181c56a 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
@@ -65,6 +65,9 @@
#define MTK_HW_LRO_REPLACE_DELTA 1000
#define MTK_HW_LRO_SDL_REMAIN_ROOM 1522
+#define MTK_RSS_HASH_KEYSIZE 40
+#define MTK_RSS_MAX_INDIRECTION_TABLE 128
+
/* Frame Engine Global Configuration */
#define MTK_FE_GLO_CFG 0x00
#define MTK_FE_LINK_DOWN_P3 BIT(11)
@@ -267,6 +270,8 @@
#define MTK_RSS_CFG_REQ BIT(2)
#define MTK_RSS_IPV6_STATIC_HASH (0x7 << 8)
#define MTK_RSS_IPV4_STATIC_HASH (0x7 << 12)
+#define MTK_RSS_HASH_KEY_DW(x) (MTK_PDMA_RSS_GLO_CFG + 0x20 + \
+ ((x) * 0x4))
#define MTK_RSS_INDR_TABLE_DW(x) (MTK_PDMA_RSS_GLO_CFG + 0x50 + \
((x) * 0x4))
@@ -1325,6 +1330,18 @@
u32 ring_no;
};
+/* struct mtk_rss_params - This is the structure holding parameters
+ for the RSS ring
+ * @hash_key The element is used to record the
+ secret key for the RSS ring
+ * indirection_table The element is used to record the
+ indirection table for the RSS ring
+ */
+struct mtk_rss_params {
+ u32 hash_key[MTK_RSS_HASH_KEYSIZE / sizeof(u32)];
+ u8 indirection_table[MTK_RSS_MAX_INDIRECTION_TABLE];
+};
+
/* struct mtk_napi - This is the structure holding NAPI-related information,
* and a mtk_napi struct is binding to one interrupt group
* @napi: The NAPI struct
@@ -1787,6 +1804,7 @@
struct mtk_rx_ring rx_ring_qdma;
struct napi_struct tx_napi;
struct mtk_napi rx_napi[MTK_RX_NAPI_NUM];
+ struct mtk_rss_params rss_params;
void *scratch_ring;
struct mtk_reset_event reset_event;
dma_addr_t phy_scratch_ring;
@@ -1864,5 +1882,5 @@
int mtk_dump_usxgmii(struct regmap *pmap, char *name, u32 offset, u32 range);
void mtk_eth_set_dma_device(struct mtk_eth *eth, struct device *dma_dev);
-int mtk_rss_set_indr_tbl(struct mtk_eth *eth, int num);
+u32 mtk_rss_indr_table(struct mtk_rss_params *rss_params, int index);
#endif /* MTK_ETH_H */
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
index ac266b7..63315df 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
@@ -297,8 +297,6 @@
*((u16 *)&h_dest[4]) =
swab16(entry->ipv4_hnapt.dmac_lo);
if (strncmp(h_dest, neigh->ha, ETH_ALEN) != 0) {
- pr_info("%s: state=%d\n", __func__,
- neigh->nud_state);
cr_set_field(hnat_priv->ppe_base[i] + PPE_TB_CFG,
SMA, SMA_ONLY_FWD_CPU);
@@ -312,9 +310,13 @@
mod_timer(&hnat_priv->hnat_sma_build_entry_timer,
jiffies + 3 * HZ);
- pr_info("Delete old entry: dip =%pI4\n", &dip);
- pr_info("Old mac= %pM\n", h_dest);
- pr_info("New mac= %pM\n", neigh->ha);
+ if (debug_level >= 7) {
+ pr_info("%s: state=%d\n", __func__,
+ neigh->nud_state);
+ pr_info("Delete old entry: dip =%pI4\n", &dip);
+ pr_info("Old mac= %pM\n", h_dest);
+ pr_info("New mac= %pM\n", neigh->ha);
+ }
}
}
}
@@ -2794,13 +2796,15 @@
mtk_hnat_ipv4_nf_local_out(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state)
{
- struct sk_buff *new_skb;
struct foe_entry *entry;
struct iphdr *iph;
if (!is_magic_tag_valid(skb))
return NF_ACCEPT;
+ if (unlikely(skb_headroom(skb) < FOE_INFO_LEN))
+ return NF_ACCEPT;
+
if (!skb_hnat_is_hashed(skb))
return NF_ACCEPT;
@@ -2810,16 +2814,6 @@
entry = &hnat_priv->foe_table_cpu[skb_hnat_ppe(skb)][skb_hnat_entry(skb)];
- if (unlikely(skb_headroom(skb) < FOE_INFO_LEN)) {
- new_skb = skb_realloc_headroom(skb, FOE_INFO_LEN);
- if (!new_skb) {
- dev_info(hnat_priv->dev, "%s:drop\n", __func__);
- return NF_DROP;
- }
- dev_kfree_skb(skb);
- skb = new_skb;
- }
-
/* Make the flow from local not be bound. */
iph = ip_hdr(skb);
if (iph->protocol == IPPROTO_IPV6) {
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/mediatek-ge-soc.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/mediatek-ge-soc.c
index 489e524..40a5e0f 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/mediatek-ge-soc.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/mediatek-ge-soc.c
@@ -679,7 +679,7 @@
MTK_PHY_DA_RX_PSBN_LP_MASK,
upper_idx << 12 | upper_idx << 8 |
upper_idx << 4 | upper_idx);
- phydev_dbg(phydev, "TX-VCM SW cal result: 0x%x\n", upper_idx);
+ phydev_info(phydev, "TX-VCM SW cal result: 0x%x\n", upper_idx);
} else if (lower_idx == TXRESERVE_MIN && upper_ret == 1 &&
lower_ret == 1) {
ret = 0;
@@ -845,10 +845,6 @@
/* TCT finetune */
phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_TX_FILTER, 0x5);
- /* Disable TX power saving */
- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG7,
- MTK_PHY_DA_AD_BUF_BIAS_LP_MASK, 0x3 << 8);
-
phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
/* ResetSyncOffset = 5 */
__phy_write(phydev, 0x11, 0x500);
@@ -1137,7 +1133,7 @@
mt798x_phy_common_finetune(phydev);
mt798x_phy_eee(phydev);
- return mt798x_phy_calibration(phydev);
+ return 0;
}
static int mt7988_phy_setup_led(struct phy_device *phydev)
@@ -1229,6 +1225,13 @@
return err;
}
+ /* Disable TX power saving at probing to:
+ * 1. Meet common mode compliance test criteria
+ * 2. Make sure that TX-VCM calibration works fine
+ */
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG7,
+ MTK_PHY_DA_AD_BUF_BIAS_LP_MASK, 0x3 << 8);
+
mt7988_phy_setup_led(phydev);
return mt798x_phy_calibration(phydev);
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3007-flow-offload-add-mkhnat-dual-ppe-new-v2.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3007-flow-offload-add-mkhnat-dual-ppe-new-v2.patch
index 954c6e2..ee370b6 100755
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3007-flow-offload-add-mkhnat-dual-ppe-new-v2.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3007-flow-offload-add-mkhnat-dual-ppe-new-v2.patch
@@ -174,7 +174,7 @@
int mtk_eth_setup_tc(struct net_device *dev, enum tc_setup_type type,
void *type_data);
void mtk_eth_set_dma_device(struct mtk_eth *eth, struct device *dma_dev);
- int mtk_rss_set_indr_tbl(struct mtk_eth *eth, int num);
+ u32 mtk_rss_indr_table(struct mtk_rss_params *rss_params, int index);
+
+int mtk_ppe_debugfs_init(struct mtk_eth *eth);
#endif /* MTK_ETH_H */
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7986.cfg b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7986.cfg
index 59aa655..2f3f416 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7986.cfg
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7986.cfg
@@ -302,7 +302,7 @@
CONFIG_MDIO_DEVICE=y
# CONFIG_MEDIATEK_2P5GE_PHY is not set
# CONFIG_MEDIATEK_GE_PHY is not set
-# CONFIG_MEDIATEK_GE_PHY_SOC is not set
+# CONFIG_MEDIATEK_GE_SOC_PHY is not set
CONFIG_MEDIATEK_MT6577_AUXADC=y
CONFIG_MEDIATEK_NETSYS_V2=y
# CONFIG_MEDIATEK_NETSYS_V3 is not set
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7988.cfg b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7988.cfg
index cb07304..d661a18 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7988.cfg
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7988.cfg
@@ -514,3 +514,6 @@
CONFIG_ZLIB_DEFLATE=y
CONFIG_ZLIB_INFLATE=y
CONFIG_ZONE_DMA32=y
+# CONFIG_BPF_KPROBE_OVERRIDE is not set
+# CONFIG_HIST_TRIGGERS is not set
+# CONFIG_FUNCTION_ERROR_INJECTION is not set
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2341-mtd-spinand-Add-support-etron.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2341-mtd-spinand-Add-support-etron.patch
new file mode 100644
index 0000000..68a6f12
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2341-mtd-spinand-Add-support-etron.patch
@@ -0,0 +1,234 @@
+Index: a/drivers/mtd/nand/spi/Makefile
+===================================================================
+--- a/drivers/mtd/nand/spi/Makefile
++++ b/drivers/mtd/nand/spi/Makefile
+@@ -1,3 +1,3 @@
+ # SPDX-License-Identifier: GPL-2.0
+-spinand-objs := core.o gigadevice.o macronix.o micron.o paragon.o toshiba.o winbond.o
++spinand-objs := core.o gigadevice.o macronix.o micron.o paragon.o toshiba.o winbond.o etron.o
+ obj-$(CONFIG_MTD_SPI_NAND) += spinand.o
+Index: a/drivers/mtd/nand/spi/core.c
+===================================================================
+--- a/drivers/mtd/nand/spi/core.c
++++ b/drivers/mtd/nand/spi/core.c
+@@ -754,6 +754,7 @@ static const struct nand_ops spinand_ops
+ };
+
+ static const struct spinand_manufacturer *spinand_manufacturers[] = {
++ &etron_spinand_manufacturer,
+ &gigadevice_spinand_manufacturer,
+ ¯onix_spinand_manufacturer,
+ µn_spinand_manufacturer,
+Index: a/drivers/mtd/nand/spi/etron.c
+===================================================================
+--- /dev/null
++++ b/drivers/mtd/nand/spi/etron.c
+@@ -0,0 +1,196 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright (c) 2020 Etron Technology, Inc.
++ *
++ */
++
++#include <linux/device.h>
++#include <linux/kernel.h>
++#include <linux/mtd/spinand.h>
++
++#define SPINAND_MFR_ETRON 0xD5
++
++#define STATUS_ECC_LIMIT_BITFLIPS (3 << 4)
++
++static SPINAND_OP_VARIANTS(read_cache_variants,
++ SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 1, NULL, 0),
++ SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
++ SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0),
++ SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0),
++ SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
++ SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
++
++static SPINAND_OP_VARIANTS(write_cache_variants,
++ SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),
++ SPINAND_PROG_LOAD(true, 0, NULL, 0));
++
++static SPINAND_OP_VARIANTS(update_cache_variants,
++ SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),
++ SPINAND_PROG_LOAD(false, 0, NULL, 0));
++
++static int etron_ooblayout_ecc(struct mtd_info *mtd, int section,
++ struct mtd_oob_region *region)
++{
++ if (section > 3)
++ return -ERANGE;
++
++ region->offset = (14 * section) + 72;
++ region->length = 14;
++
++ return 0;
++}
++
++static int etron_ooblayout_free(struct mtd_info *mtd, int section,
++ struct mtd_oob_region *region)
++{
++ if (section > 3)
++ return -ERANGE;
++
++ if (section) {
++ region->offset = 18 * section;
++ region->length = 18;
++ } else {
++ /* section 0 has one byte reserved for bad block mark */
++ region->offset = 2;
++ region->length = 16;
++ }
++
++ return 0;
++}
++
++static const struct mtd_ooblayout_ops etron_ooblayout = {
++ .ecc = etron_ooblayout_ecc,
++ .free = etron_ooblayout_free,
++};
++
++static int etron_ecc_get_status(struct spinand_device *spinand,
++ u8 status)
++{
++ switch (status & STATUS_ECC_MASK) {
++ case STATUS_ECC_NO_BITFLIPS:
++ return 0;
++
++ case STATUS_ECC_UNCOR_ERROR:
++ return -EBADMSG;
++
++ case STATUS_ECC_HAS_BITFLIPS:
++ return 1;
++
++ case STATUS_ECC_LIMIT_BITFLIPS:
++ return 3;
++
++
++ default:
++ break;
++ }
++
++ return -EINVAL;
++}
++
++static const struct spinand_info etron_spinand_table[] = {
++ /* EM73C 1Gb 3.3V */
++ SPINAND_INFO("EM73C044VCF",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x25),
++ NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
++ NAND_ECCREQ(4, 512),
++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++ &write_cache_variants,
++ &update_cache_variants),
++ SPINAND_HAS_QE_BIT,
++ SPINAND_ECCINFO(&etron_ooblayout, etron_ecc_get_status)),
++ /* EM7xD 2Gb */
++ SPINAND_INFO("EM73D044VCR",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x41),
++ NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1),
++ NAND_ECCREQ(4, 512),
++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++ &write_cache_variants,
++ &update_cache_variants),
++ SPINAND_HAS_QE_BIT,
++ SPINAND_ECCINFO(&etron_ooblayout, etron_ecc_get_status)),
++ SPINAND_INFO("EM73D044VCO",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x3A),
++ NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
++ NAND_ECCREQ(8, 512),
++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++ &write_cache_variants,
++ &update_cache_variants),
++ SPINAND_HAS_QE_BIT,
++ SPINAND_ECCINFO(&etron_ooblayout, etron_ecc_get_status)),
++ SPINAND_INFO("EM78D044VCM",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x8E),
++ NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
++ NAND_ECCREQ(8, 512),
++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++ &write_cache_variants,
++ &update_cache_variants),
++ SPINAND_HAS_QE_BIT,
++ SPINAND_ECCINFO(&etron_ooblayout, etron_ecc_get_status)),
++ /* EM7xE 4Gb */
++ SPINAND_INFO("EM73E044VCE",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x3B),
++ NAND_MEMORG(1, 2048, 128, 64, 4096, 80, 1, 1, 1),
++ NAND_ECCREQ(8, 512),
++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++ &write_cache_variants,
++ &update_cache_variants),
++ SPINAND_HAS_QE_BIT,
++ SPINAND_ECCINFO(&etron_ooblayout, etron_ecc_get_status)),
++ SPINAND_INFO("EM78E044VCD",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x8F),
++ NAND_MEMORG(1, 2048, 128, 64, 4096, 80, 1, 1, 1),
++ NAND_ECCREQ(8, 512),
++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++ &write_cache_variants,
++ &update_cache_variants),
++ SPINAND_HAS_QE_BIT,
++ SPINAND_ECCINFO(&etron_ooblayout, etron_ecc_get_status)),
++ /* EM7xF044VCA 8Gb */
++ SPINAND_INFO("EM73F044VCA",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x15),
++ NAND_MEMORG(1, 4096, 256, 64, 4096, 80, 1, 1, 1),
++ NAND_ECCREQ(8, 512),
++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++ &write_cache_variants,
++ &update_cache_variants),
++ SPINAND_HAS_QE_BIT,
++ SPINAND_ECCINFO(&etron_ooblayout, etron_ecc_get_status)),
++ SPINAND_INFO("EM78F044VCA",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x8D),
++ NAND_MEMORG(1, 4096, 256, 64, 4096, 80, 1, 1, 1),
++ NAND_ECCREQ(8, 512),
++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++ &write_cache_variants,
++ &update_cache_variants),
++ SPINAND_HAS_QE_BIT,
++ SPINAND_ECCINFO(&etron_ooblayout, etron_ecc_get_status)),
++};
++
++static int etron_spinand_detect(struct spinand_device *spinand)
++{
++ u8 *id = spinand->id.data;
++ int ret;
++
++ if (id[1] != SPINAND_MFR_ETRON)
++ return 0;
++
++ ret = spinand_match_and_init(spinand, etron_spinand_table,
++ ARRAY_SIZE(etron_spinand_table),
++ id[2]);
++ if (ret)
++ return ret;
++
++ return 1;
++}
++
++static const struct spinand_manufacturer_ops etron_spinand_manuf_ops = {
++};
++
++const struct spinand_manufacturer etron_spinand_manufacturer = {
++ .id = SPINAND_MFR_ETRON,
++ .name = "Etron",
++ .chips = etron_spinand_table,
++ .nchips = ARRAY_SIZE(etron_spinand_table),
++ .ops = &etron_spinand_manuf_ops,
++};
++
+Index: a/include/linux/mtd/spinand.h
+===================================================================
+--- a/include/linux/mtd/spinand.h
++++ b/include/linux/mtd/spinand.h
+@@ -238,6 +238,7 @@ struct spinand_manufacturer {
+ };
+
+ /* SPI NAND manufacturers */
++extern const struct spinand_manufacturer etron_spinand_manufacturer;
+ extern const struct spinand_manufacturer gigadevice_spinand_manufacturer;
+ extern const struct spinand_manufacturer macronix_spinand_manufacturer;
+ extern const struct spinand_manufacturer micron_spinand_manufacturer;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2380-fix-dirty-race-between-do_tmpfile.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2380-fix-dirty-race-between-do_tmpfile.patch
index 63943f8..cece259 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2380-fix-dirty-race-between-do_tmpfile.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2380-fix-dirty-race-between-do_tmpfile.patch
@@ -45,7 +45,7 @@
static int do_tmpfile(struct inode *dir, struct dentry *dentry,
umode_t mode, struct inode **whiteout)
{
-@@ -364,7 +390,7 @@ static int do_tmpfile(struct inode *dir, struct dentry *dentry,
+@@ -364,7 +390,7 @@ static int do_tmpfile(struct inode *dir,
struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1,
.dirtied_ino = 1};
struct ubifs_budget_req ino_req = { .dirtied_ino = 1 };
@@ -54,7 +54,7 @@
int err, instantiated = 0;
struct fscrypt_name nm;
-@@ -426,18 +452,18 @@ static int do_tmpfile(struct inode *dir, struct dentry *dentry,
+@@ -426,11 +452,11 @@ static int do_tmpfile(struct inode *dir,
instantiated = 1;
mutex_unlock(&ui->ui_mutex);
@@ -67,7 +67,8 @@
+ unlock_2_inodes(dir, inode);
ubifs_release_budget(c, &req);
-
+ fscrypt_free_filename(&nm);
+@@ -438,7 +464,7 @@ static int do_tmpfile(struct inode *dir,
return 0;
out_cancel:
@@ -76,7 +77,7 @@
out_inode:
make_bad_inode(inode);
if (!instantiated)
-@@ -672,32 +698,6 @@ static int ubifs_dir_release(struct inode *dir, struct file *file)
+@@ -673,32 +699,6 @@ static int ubifs_dir_release(struct inod
return 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 e21e5f5..fc5ecff 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
@@ -88,6 +88,7 @@
file://999-2338-mtd-tests-fix-pagetest-load.patch \
file://999-2339-drivers-mtd-spinand-Add-calibration-support-for-spinand.patch \
file://999-2340-drivers-mtd-spi-nor-Add-calibration-support-for-spi-nor.patch \
+ file://999-2341-mtd-spinand-Add-support-etron.patch \
file://999-2350-nvmem-core-Add-functions-to-make-number-reading-easy.patch \
file://999-2351-nvmem-mtk-efuse-support-minimum-one-byte-access-stri.patch \
file://999-2361-add-spimem-support-to-mtk-spi.patch \
diff --git a/recipes-kernel/linux/linux-mediatek_5.4.bb b/recipes-kernel/linux/linux-mediatek_5.4.bb
index f6e8bc0..a9cfda2 100644
--- a/recipes-kernel/linux/linux-mediatek_5.4.bb
+++ b/recipes-kernel/linux/linux-mediatek_5.4.bb
@@ -9,8 +9,8 @@
KBRANCH ?= "linux-5.4.y"
-LINUX_VERSION ?= "5.4.238"
-SRCREV_machine ?= "6849d8c4a61a93bb3abf2f65c84ec1ebfa9a9fb6"
+LINUX_VERSION ?= "5.4.246"
+SRCREV_machine ?= "f568a20f058fa1e37069cff4aac4187c1650a0e9"
KMETA = "kernel-meta"
SRCREV_meta ?= "feeb59687bc0f054af837a5061f8d413ec7c93e9"