mirror of
https://github.com/Ysurac/openmptcprouter.git
synced 2025-03-09 15:40:20 +00:00
Update 6.12 kernel patches
This commit is contained in:
parent
bdb9b0046f
commit
9d83c70ced
247 changed files with 53301 additions and 589 deletions
|
@ -11,7 +11,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
|
||||
--- a/include/linux/compiler.h
|
||||
+++ b/include/linux/compiler.h
|
||||
@@ -202,6 +202,8 @@ void ftrace_likely_update(struct ftrace_
|
||||
@@ -214,6 +214,8 @@ void ftrace_likely_update(struct ftrace_
|
||||
__v; \
|
||||
})
|
||||
|
||||
|
@ -20,7 +20,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
#endif /* __KERNEL__ */
|
||||
|
||||
/*
|
||||
@@ -243,6 +245,4 @@ static inline void *offset_to_ptr(const
|
||||
@@ -314,6 +316,4 @@ static inline void *offset_to_ptr(const
|
||||
*/
|
||||
#define prevent_tail_call_optimization() mb()
|
||||
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
From 173019b66dcc9d68ad9333aa744dad1e369b5aa8 Mon Sep 17 00:00:00 2001
|
||||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Sun, 9 Jul 2017 00:26:53 +0200
|
||||
Subject: [PATCH 34/34] kernel: add compile fix for linux 4.9 on x86
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
Makefile | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/Makefile
|
||||
+++ b/Makefile
|
||||
@@ -583,7 +583,7 @@ endif
|
||||
# Allows the usage of unstable features in stable compilers.
|
||||
export RUSTC_BOOTSTRAP := 1
|
||||
|
||||
-export ARCH SRCARCH CONFIG_SHELL BASH HOSTCC KBUILD_HOSTCFLAGS CROSS_COMPILE LD CC HOSTPKG_CONFIG
|
||||
+export ARCH SRCARCH SUBARCH CONFIG_SHELL BASH HOSTCC KBUILD_HOSTCFLAGS CROSS_COMPILE LD CC HOSTPKG_CONFIG
|
||||
export RUSTC RUSTDOC RUSTFMT RUSTC_OR_CLIPPY_QUIET RUSTC_OR_CLIPPY BINDGEN
|
||||
export HOSTRUSTC KBUILD_HOSTRUSTFLAGS
|
||||
export CPP AR NM STRIP OBJCOPY OBJDUMP READELF PAHOLE RESOLVE_BTFIDS LEX YACC AWK INSTALLKERNEL
|
|
@ -71,7 +71,7 @@ Signed-off-by: Tobias Wolf <dev-NTEO@vplace.de>
|
|||
|
||||
--- a/mm/mm_init.c
|
||||
+++ b/mm/mm_init.c
|
||||
@@ -1673,7 +1673,7 @@ static void __init alloc_node_mem_map(st
|
||||
@@ -1632,7 +1632,7 @@ static void __init alloc_node_mem_map(st
|
||||
if (pgdat == NODE_DATA(0)) {
|
||||
mem_map = NODE_DATA(0)->node_mem_map;
|
||||
if (page_to_pfn(mem_map) != pgdat->node_start_pfn)
|
||||
|
|
|
@ -8,7 +8,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
|
||||
--- a/fs/jffs2/dir.c
|
||||
+++ b/fs/jffs2/dir.c
|
||||
@@ -617,8 +617,8 @@ static int jffs2_rmdir (struct inode *di
|
||||
@@ -620,8 +620,8 @@ static int jffs2_rmdir (struct inode *di
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
{
|
||||
struct jffs2_inode_info *f, *dir_f;
|
||||
struct jffs2_sb_info *c;
|
||||
@@ -758,7 +758,11 @@ static int jffs2_mknod (struct mnt_idmap
|
||||
@@ -761,7 +761,11 @@ static int jffs2_mknod (struct mnt_idmap
|
||||
mutex_unlock(&dir_f->sem);
|
||||
jffs2_complete_reservation(c);
|
||||
|
||||
|
@ -32,7 +32,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
return 0;
|
||||
|
||||
fail:
|
||||
@@ -766,6 +770,19 @@ static int jffs2_mknod (struct mnt_idmap
|
||||
@@ -769,6 +773,19 @@ static int jffs2_mknod (struct mnt_idmap
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -52,7 +52,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
static int jffs2_rename (struct mnt_idmap *idmap,
|
||||
struct inode *old_dir_i, struct dentry *old_dentry,
|
||||
struct inode *new_dir_i, struct dentry *new_dentry,
|
||||
@@ -777,7 +794,7 @@ static int jffs2_rename (struct mnt_idma
|
||||
@@ -780,7 +797,7 @@ static int jffs2_rename (struct mnt_idma
|
||||
uint8_t type;
|
||||
uint32_t now;
|
||||
|
||||
|
@ -61,7 +61,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
return -EINVAL;
|
||||
|
||||
/* The VFS will check for us and prevent trying to rename a
|
||||
@@ -843,9 +860,14 @@ static int jffs2_rename (struct mnt_idma
|
||||
@@ -846,9 +863,14 @@ static int jffs2_rename (struct mnt_idma
|
||||
if (d_is_dir(old_dentry) && !victim_f)
|
||||
inc_nlink(new_dir_i);
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
|
||||
--- a/fs/jffs2/dir.c
|
||||
+++ b/fs/jffs2/dir.c
|
||||
@@ -791,18 +791,31 @@ static int jffs2_rename (struct mnt_idma
|
||||
@@ -794,18 +794,31 @@ static int jffs2_rename (struct mnt_idma
|
||||
int ret;
|
||||
struct jffs2_sb_info *c = JFFS2_SB_INFO(old_dir_i->i_sb);
|
||||
struct jffs2_inode_info *victim_f = NULL;
|
||||
|
@ -40,7 +40,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
victim_f = JFFS2_INODE_INFO(d_inode(new_dentry));
|
||||
if (d_is_dir(new_dentry)) {
|
||||
struct jffs2_full_dirent *fd;
|
||||
@@ -837,7 +850,7 @@ static int jffs2_rename (struct mnt_idma
|
||||
@@ -840,7 +853,7 @@ static int jffs2_rename (struct mnt_idma
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -49,7 +49,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
/* There was a victim. Kill it off nicely */
|
||||
if (d_is_dir(new_dentry))
|
||||
clear_nlink(d_inode(new_dentry));
|
||||
@@ -863,6 +876,12 @@ static int jffs2_rename (struct mnt_idma
|
||||
@@ -866,6 +879,12 @@ static int jffs2_rename (struct mnt_idma
|
||||
if (flags & RENAME_WHITEOUT)
|
||||
/* Replace with whiteout */
|
||||
ret = jffs2_whiteout(idmap, old_dir_i, old_dentry);
|
||||
|
@ -62,7 +62,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
else
|
||||
/* Unlink the original */
|
||||
ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i),
|
||||
@@ -895,7 +914,7 @@ static int jffs2_rename (struct mnt_idma
|
||||
@@ -898,7 +917,7 @@ static int jffs2_rename (struct mnt_idma
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -70,4 +70,4 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
+ if (d_is_dir(old_dentry) && !(flags & RENAME_EXCHANGE))
|
||||
drop_nlink(old_dir_i);
|
||||
|
||||
old_dir_i->i_mtime = inode_set_ctime_to_ts(old_dir_i, ITIME(now));
|
||||
inode_set_mtime_to_ts(old_dir_i,
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
From: Daniel González Cabanelas <dgcbueu@gmail.com>
|
||||
Subject: [PATCH 2/2] rtc: rs5c372: let the alarm to be used as wakeup source
|
||||
|
||||
Currently there is no use for the interrupts on the rs5c372 RTC and the
|
||||
wakealarm isn't enabled. There are some devices like NASes which use this
|
||||
RTC to wake up from the power off state when the INTR pin is activated by
|
||||
the alarm clock.
|
||||
|
||||
Enable the alarm and let to be used as a wakeup source.
|
||||
|
||||
Tested on a Buffalo LS421DE NAS.
|
||||
|
||||
Signed-off-by: Daniel González Cabanelas <dgcbueu@gmail.com>
|
||||
---
|
||||
drivers/rtc/rtc-rs5c372.c | 16 ++++++++++++++++
|
||||
1 file changed, 16 insertions(+)
|
||||
|
||||
--- a/drivers/rtc/rtc-rs5c372.c
|
||||
+++ b/drivers/rtc/rtc-rs5c372.c
|
||||
@@ -832,6 +832,7 @@ static int rs5c372_probe(struct i2c_clie
|
||||
int err = 0;
|
||||
int smbus_mode = 0;
|
||||
struct rs5c372 *rs5c372;
|
||||
+ bool rs5c372_can_wakeup_device = false;
|
||||
|
||||
dev_dbg(&client->dev, "%s\n", __func__);
|
||||
|
||||
@@ -868,6 +869,12 @@ static int rs5c372_probe(struct i2c_clie
|
||||
rs5c372->type = id->driver_data;
|
||||
}
|
||||
|
||||
+#ifdef CONFIG_OF
|
||||
+ if(of_property_read_bool(client->dev.of_node,
|
||||
+ "wakeup-source"))
|
||||
+ rs5c372_can_wakeup_device = true;
|
||||
+#endif
|
||||
+
|
||||
/* we read registers 0x0f then 0x00-0x0f; skip the first one */
|
||||
rs5c372->regs = &rs5c372->buf[1];
|
||||
rs5c372->smbus = smbus_mode;
|
||||
@@ -901,6 +908,8 @@ static int rs5c372_probe(struct i2c_clie
|
||||
goto exit;
|
||||
}
|
||||
|
||||
+ rs5c372->has_irq = 1;
|
||||
+
|
||||
/* if the oscillator lost power and no other software (like
|
||||
* the bootloader) set it up, do it here.
|
||||
*
|
||||
@@ -927,6 +936,10 @@ static int rs5c372_probe(struct i2c_clie
|
||||
);
|
||||
|
||||
/* REVISIT use client->irq to register alarm irq ... */
|
||||
+ if (rs5c372_can_wakeup_device) {
|
||||
+ device_init_wakeup(&client->dev, true);
|
||||
+ }
|
||||
+
|
||||
rs5c372->rtc = devm_rtc_device_register(&client->dev,
|
||||
rs5c372_driver.driver.name,
|
||||
&rs5c372_rtc_ops, THIS_MODULE);
|
||||
@@ -940,6 +953,10 @@ static int rs5c372_probe(struct i2c_clie
|
||||
if (err)
|
||||
goto exit;
|
||||
|
||||
+ /* the rs5c372 alarm only supports a minute accuracy */
|
||||
+ set_bit(RTC_FEATURE_ALARM_RES_MINUTE, rs5c372->rtc->features);
|
||||
+ clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, rs5c372->rtc->features);
|
||||
+
|
||||
return 0;
|
||||
|
||||
exit:
|
|
@ -11,7 +11,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
|
||||
--- a/lib/vsprintf.c
|
||||
+++ b/lib/vsprintf.c
|
||||
@@ -982,8 +982,10 @@ char *symbol_string(char *buf, char *end
|
||||
@@ -983,8 +983,10 @@ char *symbol_string(char *buf, char *end
|
||||
struct printf_spec spec, const char *fmt)
|
||||
{
|
||||
unsigned long value;
|
||||
|
@ -23,7 +23,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
#endif
|
||||
|
||||
if (fmt[1] == 'R')
|
||||
@@ -1004,8 +1006,14 @@ char *symbol_string(char *buf, char *end
|
||||
@@ -1005,8 +1007,14 @@ char *symbol_string(char *buf, char *end
|
||||
|
||||
return string_nocheck(buf, end, sym, spec);
|
||||
#else
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
From c2deb5ef01a0ef09088832744cbace9e239a6ee0 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Thibaut=20VAR=C3=88NE?= <hacks@slashdirt.org>
|
||||
Date: Sat, 28 Mar 2020 12:11:50 +0100
|
||||
Subject: [PATCH] generic: platform/mikrotik build bits (5.4)
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This patch adds platform/mikrotik kernel build bits
|
||||
|
||||
Signed-off-by: Thibaut VARÈNE <hacks@slashdirt.org>
|
||||
---
|
||||
drivers/platform/Kconfig | 2 ++
|
||||
drivers/platform/Makefile | 1 +
|
||||
2 files changed, 3 insertions(+)
|
||||
|
||||
--- a/drivers/platform/Kconfig
|
||||
+++ b/drivers/platform/Kconfig
|
||||
@@ -18,3 +18,5 @@ source "drivers/platform/surface/Kconfig
|
||||
source "drivers/platform/x86/Kconfig"
|
||||
|
||||
source "drivers/platform/arm64/Kconfig"
|
||||
+
|
||||
+source "drivers/platform/mikrotik/Kconfig"
|
||||
--- a/drivers/platform/Makefile
|
||||
+++ b/drivers/platform/Makefile
|
||||
@@ -13,3 +13,4 @@ obj-$(CONFIG_CHROME_PLATFORMS) += chrome
|
||||
obj-$(CONFIG_CZNIC_PLATFORMS) += cznic/
|
||||
obj-$(CONFIG_SURFACE_PLATFORMS) += surface/
|
||||
obj-$(CONFIG_ARM64_PLATFORM_DEVICES) += arm64/
|
||||
+obj-$(CONFIG_MIKROTIK) += mikrotik/
|
|
@ -9,7 +9,7 @@ Acked-by: Rob Landley <rob@landley.net>
|
|||
---
|
||||
--- a/arch/mips/Kconfig
|
||||
+++ b/arch/mips/Kconfig
|
||||
@@ -1013,9 +1013,6 @@ config FW_ARC
|
||||
@@ -1055,9 +1055,6 @@ config FW_ARC
|
||||
config ARCH_MAY_HAVE_PC_FDC
|
||||
bool
|
||||
|
||||
|
@ -19,7 +19,7 @@ Acked-by: Rob Landley <rob@landley.net>
|
|||
config CEVT_BCM1480
|
||||
bool
|
||||
|
||||
@@ -2996,6 +2993,18 @@ choice
|
||||
@@ -2991,6 +2988,18 @@ choice
|
||||
bool "Extend builtin kernel arguments with bootloader arguments"
|
||||
endchoice
|
||||
|
||||
|
|
|
@ -11,9 +11,9 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
|
||||
--- a/arch/mips/Makefile
|
||||
+++ b/arch/mips/Makefile
|
||||
@@ -163,7 +163,7 @@ cflags-$(CONFIG_CPU_R4300) += -march=r43
|
||||
cflags-$(CONFIG_CPU_R4X00) += -march=r4600 -Wa,--trap
|
||||
cflags-$(CONFIG_CPU_TX49XX) += -march=r4600 -Wa,--trap
|
||||
@@ -153,7 +153,7 @@ cflags-$(CONFIG_CPU_R4300) += $(call cc-
|
||||
cflags-$(CONFIG_CPU_R4X00) += $(call cc-option,-march=r4600,-march=mips3) -Wa,--trap
|
||||
cflags-$(CONFIG_CPU_TX49XX) += $(call cc-option,-march=r4600,-march=mips3) -Wa,--trap
|
||||
cflags-$(CONFIG_CPU_MIPS32_R1) += -march=mips32 -Wa,--trap
|
||||
-cflags-$(CONFIG_CPU_MIPS32_R2) += -march=mips32r2 -Wa,--trap
|
||||
+cflags-$(CONFIG_CPU_MIPS32_R2) += -march=mips32r2 -mtune=34kc -Wa,--trap
|
||||
|
|
|
@ -9,7 +9,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
|
||||
--- a/arch/arm/kernel/module.c
|
||||
+++ b/arch/arm/kernel/module.c
|
||||
@@ -146,6 +146,10 @@ apply_relocate(Elf32_Shdr *sechdrs, cons
|
||||
@@ -112,6 +112,10 @@ apply_relocate(Elf32_Shdr *sechdrs, cons
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,9 +11,9 @@ Signed-off-by: Yousong Zhou <yszhou4tech@gmail.com>
|
|||
|
||||
--- a/arch/mips/kernel/machine_kexec.c
|
||||
+++ b/arch/mips/kernel/machine_kexec.c
|
||||
@@ -9,14 +9,11 @@
|
||||
#include <linux/delay.h>
|
||||
@@ -10,14 +10,11 @@
|
||||
#include <linux/libfdt.h>
|
||||
#include <linux/reboot.h>
|
||||
|
||||
+#include <asm/bootinfo.h>
|
||||
#include <asm/cacheflush.h>
|
||||
|
@ -29,7 +29,7 @@ Signed-off-by: Yousong Zhou <yszhou4tech@gmail.com>
|
|||
|
||||
static unsigned long reboot_code_buffer;
|
||||
|
||||
@@ -30,6 +27,101 @@ void (*_crash_smp_send_stop)(void) = NUL
|
||||
@@ -31,6 +28,101 @@ void (*_crash_smp_send_stop)(void) = NUL
|
||||
void (*_machine_kexec_shutdown)(void) = NULL;
|
||||
void (*_machine_crash_shutdown)(struct pt_regs *regs) = NULL;
|
||||
|
||||
|
@ -131,7 +131,7 @@ Signed-off-by: Yousong Zhou <yszhou4tech@gmail.com>
|
|||
static void kexec_image_info(const struct kimage *kimage)
|
||||
{
|
||||
unsigned long i;
|
||||
@@ -99,6 +191,18 @@ machine_kexec_prepare(struct kimage *kim
|
||||
@@ -100,6 +192,18 @@ machine_kexec_prepare(struct kimage *kim
|
||||
#endif
|
||||
|
||||
kexec_image_info(kimage);
|
||||
|
@ -150,7 +150,7 @@ Signed-off-by: Yousong Zhou <yszhou4tech@gmail.com>
|
|||
|
||||
if (_machine_kexec_prepare)
|
||||
return _machine_kexec_prepare(kimage);
|
||||
@@ -161,7 +265,7 @@ machine_crash_shutdown(struct pt_regs *r
|
||||
@@ -162,7 +266,7 @@ machine_crash_shutdown(struct pt_regs *r
|
||||
void kexec_nonboot_cpu_jump(void)
|
||||
{
|
||||
local_flush_icache_range((unsigned long)relocated_kexec_smp_wait,
|
||||
|
@ -159,7 +159,7 @@ Signed-off-by: Yousong Zhou <yszhou4tech@gmail.com>
|
|||
|
||||
relocated_kexec_smp_wait(NULL);
|
||||
}
|
||||
@@ -199,7 +303,7 @@ void kexec_reboot(void)
|
||||
@@ -200,7 +304,7 @@ void kexec_reboot(void)
|
||||
* machine_kexec() CPU.
|
||||
*/
|
||||
local_flush_icache_range(reboot_code_buffer,
|
||||
|
@ -168,7 +168,7 @@ Signed-off-by: Yousong Zhou <yszhou4tech@gmail.com>
|
|||
|
||||
do_kexec = (void *)reboot_code_buffer;
|
||||
do_kexec();
|
||||
@@ -212,10 +316,12 @@ machine_kexec(struct kimage *image)
|
||||
@@ -213,10 +317,12 @@ machine_kexec(struct kimage *image)
|
||||
unsigned long *ptr;
|
||||
|
||||
reboot_code_buffer =
|
||||
|
@ -182,7 +182,7 @@ Signed-off-by: Yousong Zhou <yszhou4tech@gmail.com>
|
|||
|
||||
if (image->type == KEXEC_TYPE_DEFAULT) {
|
||||
kexec_indirection_page =
|
||||
@@ -223,9 +329,19 @@ machine_kexec(struct kimage *image)
|
||||
@@ -224,9 +330,19 @@ machine_kexec(struct kimage *image)
|
||||
} else {
|
||||
kexec_indirection_page = (unsigned long)&image->head;
|
||||
}
|
||||
|
@ -204,7 +204,7 @@ Signed-off-by: Yousong Zhou <yszhou4tech@gmail.com>
|
|||
|
||||
/*
|
||||
* The generic kexec code builds a page list with physical
|
||||
@@ -256,7 +372,7 @@ machine_kexec(struct kimage *image)
|
||||
@@ -257,7 +373,7 @@ machine_kexec(struct kimage *image)
|
||||
#ifdef CONFIG_SMP
|
||||
/* All secondary cpus now may jump to kexec_wait cycle */
|
||||
relocated_kexec_smp_wait = reboot_code_buffer +
|
||||
|
@ -251,7 +251,7 @@ Signed-off-by: Yousong Zhou <yszhou4tech@gmail.com>
|
|||
PTR_L a0, arg0
|
||||
PTR_L a1, arg1
|
||||
PTR_L a2, arg2
|
||||
@@ -98,7 +99,7 @@ done:
|
||||
@@ -97,7 +98,7 @@ done:
|
||||
#endif
|
||||
/* jump to kexec_start_address */
|
||||
j s1
|
||||
|
@ -260,7 +260,7 @@ Signed-off-by: Yousong Zhou <yszhou4tech@gmail.com>
|
|||
|
||||
#ifdef CONFIG_SMP
|
||||
/*
|
||||
@@ -177,8 +178,15 @@ EXPORT(kexec_indirection_page)
|
||||
@@ -176,8 +177,15 @@ EXPORT(kexec_indirection_page)
|
||||
PTR_WD 0
|
||||
.size kexec_indirection_page, PTRSIZE
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
|
|||
|
||||
--- a/arch/arc/kernel/unaligned.c
|
||||
+++ b/arch/arc/kernel/unaligned.c
|
||||
@@ -202,7 +202,7 @@ int misaligned_fixup(unsigned long addre
|
||||
@@ -203,7 +203,7 @@ int misaligned_fixup(unsigned long addre
|
||||
char buf[TASK_COMM_LEN];
|
||||
|
||||
/* handle user mode only and only if enabled by sysadmin */
|
||||
|
|
|
@ -14,7 +14,7 @@ Signed-off-by: Pawel Dembicki <paweldembicki@gmail.com>
|
|||
|
||||
--- a/arch/powerpc/Kconfig
|
||||
+++ b/arch/powerpc/Kconfig
|
||||
@@ -251,7 +251,7 @@ config PPC
|
||||
@@ -254,7 +254,7 @@ config PPC
|
||||
select HAVE_KERNEL_GZIP
|
||||
select HAVE_KERNEL_LZMA if DEFAULT_UIMAGE
|
||||
select HAVE_KERNEL_LZO if DEFAULT_UIMAGE
|
||||
|
|
|
@ -31,7 +31,7 @@ Signed-off-by: Shiji Yang <yangshiji66@outlook.com>
|
|||
extern void prom_free_prom_memory(void);
|
||||
--- a/arch/mips/kernel/setup.c
|
||||
+++ b/arch/mips/kernel/setup.c
|
||||
@@ -90,21 +90,27 @@ static struct resource bss_resource = {
|
||||
@@ -86,21 +86,27 @@ static struct resource bss_resource = {
|
||||
unsigned long __kaslr_offset __ro_after_init;
|
||||
EXPORT_SYMBOL(__kaslr_offset);
|
||||
|
||||
|
@ -64,7 +64,7 @@ Signed-off-by: Shiji Yang <yangshiji66@outlook.com>
|
|||
}
|
||||
|
||||
pr_debug("Memory: %lluMB of RAM detected at 0x%llx (min: %lluMB, max: %lluMB)\n",
|
||||
@@ -115,6 +121,7 @@ void __init detect_memory_region(phys_ad
|
||||
@@ -111,6 +117,7 @@ void __init detect_memory_region(phys_ad
|
||||
|
||||
memblock_add(start, size);
|
||||
}
|
||||
|
|
|
@ -230,7 +230,7 @@ Subject: [PATCH] mtd: mtdsplit support
|
|||
mtd_add_partition_attrs(child);
|
||||
|
||||
/* Look for subpartitions */
|
||||
@@ -439,31 +584,6 @@ err_del_partitions:
|
||||
@@ -443,31 +588,6 @@ err_del_partitions:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
|||
|
||||
--- a/drivers/mtd/mtdcore.c
|
||||
+++ b/drivers/mtd/mtdcore.c
|
||||
@@ -548,6 +548,29 @@ static int mtd_nvmem_add(struct mtd_info
|
||||
@@ -549,6 +549,29 @@ static int mtd_nvmem_add(struct mtd_info
|
||||
struct device_node *node = mtd_get_of_node(mtd);
|
||||
struct nvmem_config config = {};
|
||||
|
||||
|
|
|
@ -0,0 +1,245 @@
|
|||
From acacdac272927ae1d96e0bca51eb82899671eaea Mon Sep 17 00:00:00 2001
|
||||
From: John Thomson <git@johnthomson.fastmail.com.au>
|
||||
Date: Fri, 25 Dec 2020 18:50:08 +1000
|
||||
Subject: [PATCH] mtd: spi-nor: write support for minor aligned partitions
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Do not prevent writing to mtd partitions where a partition boundary sits
|
||||
on a minor erasesize boundary.
|
||||
This addresses a FIXME that has been present since the start of the
|
||||
linux git history:
|
||||
/* Doesn't start on a boundary of major erase size */
|
||||
/* FIXME: Let it be writable if it is on a boundary of
|
||||
* _minor_ erase size though */
|
||||
|
||||
Allow a uniform erase region spi-nor device to be configured
|
||||
to use the non-uniform erase regions code path for an erase with:
|
||||
CONFIG_MTD_SPI_NOR_USE_VARIABLE_ERASE=y
|
||||
|
||||
On supporting hardware (SECT_4K: majority of current SPI-NOR device)
|
||||
provide the facility for an erase to use the least number
|
||||
of SPI-NOR operations, as well as access to 4K erase without
|
||||
requiring CONFIG_MTD_SPI_NOR_USE_4K_SECTORS
|
||||
|
||||
Introduce erasesize_minor to the mtd struct,
|
||||
the smallest erasesize supported by the device
|
||||
|
||||
On existing devices, this is useful where write support is wanted
|
||||
for data on a 4K partition, such as some u-boot-env partitions,
|
||||
or RouterBoot soft_config, while still netting the performance
|
||||
benefits of using 64K sectors
|
||||
|
||||
Performance:
|
||||
time mtd erase firmware
|
||||
OpenWrt 5.10 ramips MT7621 w25q128jv 0xfc0000 partition length
|
||||
|
||||
Without this patch
|
||||
MTD_SPI_NOR_USE_4K_SECTORS=y |n
|
||||
real 2m 11.66s |0m 50.86s
|
||||
user 0m 0.00s |0m 0.00s
|
||||
sys 1m 56.20s |0m 50.80s
|
||||
|
||||
With this patch
|
||||
MTD_SPI_NOR_USE_VARIABLE_ERASE=n|y |4K_SECTORS=y
|
||||
real 0m 51.68s |0m 50.85s |2m 12.89s
|
||||
user 0m 0.00s |0m 0.00s |0m 0.01s
|
||||
sys 0m 46.94s |0m 50.38s |2m 12.46s
|
||||
|
||||
Signed-off-by: John Thomson <git@johnthomson.fastmail.com.au>
|
||||
Signed-off-by: Thibaut VARÈNE <hacks+kernel@slashdirt.org>
|
||||
|
||||
---
|
||||
|
||||
checkpatch does not like the printk(KERN_WARNING
|
||||
these should be changed separately beforehand?
|
||||
|
||||
Changes v1 -> v2:
|
||||
Added mtdcore sysfs for erasesize_minor
|
||||
Removed finding minor erasesize for variable erase regions device,
|
||||
as untested and no responses regarding it.
|
||||
Moved IF_ENABLED for SPINOR variable erase to guard setting
|
||||
erasesize_minor in spi-nor/core.c
|
||||
Removed setting erasesize to minor where partition boundaries require
|
||||
minor erase to be writable
|
||||
Simplified minor boundary check by relying on minor being a factor of
|
||||
major
|
||||
|
||||
Changes RFC -> v1:
|
||||
Fix uninitialized variable smatch warning
|
||||
Reported-by: kernel test robot <lkp@intel.com>
|
||||
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
|
||||
---
|
||||
drivers/mtd/mtdcore.c | 10 ++++++++++
|
||||
drivers/mtd/mtdpart.c | 35 +++++++++++++++++++++++++----------
|
||||
drivers/mtd/spi-nor/Kconfig | 10 ++++++++++
|
||||
drivers/mtd/spi-nor/core.c | 11 +++++++++--
|
||||
include/linux/mtd/mtd.h | 2 ++
|
||||
5 files changed, 56 insertions(+), 12 deletions(-)
|
||||
|
||||
--- a/drivers/mtd/mtdcore.c
|
||||
+++ b/drivers/mtd/mtdcore.c
|
||||
@@ -199,6 +199,15 @@ static ssize_t mtd_erasesize_show(struct
|
||||
}
|
||||
MTD_DEVICE_ATTR_RO(erasesize);
|
||||
|
||||
+static ssize_t mtd_erasesize_minor_show(struct device *dev,
|
||||
+ struct device_attribute *attr, char *buf)
|
||||
+{
|
||||
+ struct mtd_info *mtd = dev_get_drvdata(dev);
|
||||
+
|
||||
+ return sysfs_emit(buf, "%lu\n", (unsigned long)mtd->erasesize_minor);
|
||||
+}
|
||||
+MTD_DEVICE_ATTR_RO(erasesize_minor);
|
||||
+
|
||||
static ssize_t mtd_writesize_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
@@ -344,6 +353,7 @@ static struct attribute *mtd_attrs[] = {
|
||||
&dev_attr_flags.attr,
|
||||
&dev_attr_size.attr,
|
||||
&dev_attr_erasesize.attr,
|
||||
+ &dev_attr_erasesize_minor.attr,
|
||||
&dev_attr_writesize.attr,
|
||||
&dev_attr_subpagesize.attr,
|
||||
&dev_attr_oobsize.attr,
|
||||
--- a/drivers/mtd/mtdpart.c
|
||||
+++ b/drivers/mtd/mtdpart.c
|
||||
@@ -47,6 +47,7 @@ static struct mtd_info *allocate_partiti
|
||||
struct mtd_info *master = mtd_get_master(parent);
|
||||
int wr_alignment = (parent->flags & MTD_NO_ERASE) ?
|
||||
master->writesize : master->erasesize;
|
||||
+ int wr_alignment_minor = 0;
|
||||
u64 parent_size = mtd_is_partition(parent) ?
|
||||
parent->part.size : parent->size;
|
||||
struct mtd_info *child;
|
||||
@@ -171,6 +172,7 @@ static struct mtd_info *allocate_partiti
|
||||
} else {
|
||||
/* Single erase size */
|
||||
child->erasesize = master->erasesize;
|
||||
+ child->erasesize_minor = master->erasesize_minor;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -178,26 +180,39 @@ static struct mtd_info *allocate_partiti
|
||||
* exposes several regions with different erasesize. Adjust
|
||||
* wr_alignment accordingly.
|
||||
*/
|
||||
- if (!(child->flags & MTD_NO_ERASE))
|
||||
+ if (!(child->flags & MTD_NO_ERASE)) {
|
||||
wr_alignment = child->erasesize;
|
||||
+ wr_alignment_minor = child->erasesize_minor;
|
||||
+ }
|
||||
|
||||
tmp = mtd_get_master_ofs(child, 0);
|
||||
remainder = do_div(tmp, wr_alignment);
|
||||
if ((child->flags & MTD_WRITEABLE) && remainder) {
|
||||
- /* Doesn't start on a boundary of major erase size */
|
||||
- /* FIXME: Let it be writable if it is on a boundary of
|
||||
- * _minor_ erase size though */
|
||||
- child->flags &= ~MTD_WRITEABLE;
|
||||
- printk(KERN_WARNING"mtd: partition \"%s\" doesn't start on an erase/write block boundary -- force read-only\n",
|
||||
- part->name);
|
||||
+ if (wr_alignment_minor) {
|
||||
+ /* rely on minor being a factor of major erasesize */
|
||||
+ tmp = remainder;
|
||||
+ remainder = do_div(tmp, wr_alignment_minor);
|
||||
+ }
|
||||
+ if (remainder) {
|
||||
+ child->flags &= ~MTD_WRITEABLE;
|
||||
+ printk(KERN_WARNING"mtd: partition \"%s\" doesn't start on an erase/write block boundary -- force read-only\n",
|
||||
+ part->name);
|
||||
+ }
|
||||
}
|
||||
|
||||
tmp = mtd_get_master_ofs(child, 0) + child->part.size;
|
||||
remainder = do_div(tmp, wr_alignment);
|
||||
if ((child->flags & MTD_WRITEABLE) && remainder) {
|
||||
- child->flags &= ~MTD_WRITEABLE;
|
||||
- printk(KERN_WARNING"mtd: partition \"%s\" doesn't end on an erase/write block -- force read-only\n",
|
||||
- part->name);
|
||||
+ if (wr_alignment_minor) {
|
||||
+ tmp = remainder;
|
||||
+ remainder = do_div(tmp, wr_alignment_minor);
|
||||
+ }
|
||||
+
|
||||
+ if (remainder) {
|
||||
+ child->flags &= ~MTD_WRITEABLE;
|
||||
+ printk(KERN_WARNING"mtd: partition \"%s\" doesn't end on an erase/write block -- force read-only\n",
|
||||
+ part->name);
|
||||
+ }
|
||||
}
|
||||
|
||||
child->size = child->part.size;
|
||||
--- a/drivers/mtd/spi-nor/Kconfig
|
||||
+++ b/drivers/mtd/spi-nor/Kconfig
|
||||
@@ -10,6 +10,16 @@ menuconfig MTD_SPI_NOR
|
||||
|
||||
if MTD_SPI_NOR
|
||||
|
||||
+config MTD_SPI_NOR_USE_VARIABLE_ERASE
|
||||
+ bool "Disable uniform_erase to allow use of all hardware supported erasesizes"
|
||||
+ depends on !MTD_SPI_NOR_USE_4K_SECTORS
|
||||
+ default n
|
||||
+ help
|
||||
+ Allow mixed use of all hardware supported erasesizes,
|
||||
+ by forcing spi_nor to use the multiple eraseregions code path.
|
||||
+ For example: A 68K erase will use one 64K erase, and one 4K erase
|
||||
+ on supporting hardware.
|
||||
+
|
||||
config MTD_SPI_NOR_USE_4K_SECTORS
|
||||
bool "Use small 4096 B erase sectors"
|
||||
default y
|
||||
--- a/drivers/mtd/spi-nor/core.c
|
||||
+++ b/drivers/mtd/spi-nor/core.c
|
||||
@@ -1158,6 +1158,8 @@ static u8 spi_nor_convert_3to4_erase(u8
|
||||
|
||||
static bool spi_nor_has_uniform_erase(const struct spi_nor *nor)
|
||||
{
|
||||
+ if (IS_ENABLED(CONFIG_MTD_SPI_NOR_USE_VARIABLE_ERASE))
|
||||
+ return false;
|
||||
return !!nor->params->erase_map.uniform_region.erase_mask;
|
||||
}
|
||||
|
||||
@@ -2516,6 +2518,7 @@ static int spi_nor_select_erase(struct s
|
||||
{
|
||||
struct spi_nor_erase_map *map = &nor->params->erase_map;
|
||||
const struct spi_nor_erase_type *erase = NULL;
|
||||
+ const struct spi_nor_erase_type *erase_minor = NULL;
|
||||
struct mtd_info *mtd = &nor->mtd;
|
||||
int i;
|
||||
|
||||
@@ -2542,8 +2545,9 @@ static int spi_nor_select_erase(struct s
|
||||
*/
|
||||
for (i = SNOR_ERASE_TYPE_MAX - 1; i >= 0; i--) {
|
||||
if (map->erase_type[i].size) {
|
||||
- erase = &map->erase_type[i];
|
||||
- break;
|
||||
+ if (!erase)
|
||||
+ erase = &map->erase_type[i];
|
||||
+ erase_minor = &map->erase_type[i];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2551,6 +2555,9 @@ static int spi_nor_select_erase(struct s
|
||||
return -EINVAL;
|
||||
|
||||
mtd->erasesize = erase->size;
|
||||
+ if (IS_ENABLED(CONFIG_MTD_SPI_NOR_USE_VARIABLE_ERASE) &&
|
||||
+ erase_minor && erase_minor->size < erase->size)
|
||||
+ mtd->erasesize_minor = erase_minor->size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
--- a/include/linux/mtd/mtd.h
|
||||
+++ b/include/linux/mtd/mtd.h
|
||||
@@ -245,6 +245,8 @@ struct mtd_info {
|
||||
* information below if they desire
|
||||
*/
|
||||
uint32_t erasesize;
|
||||
+ /* "Minor" (smallest) erase size supported by the whole device */
|
||||
+ uint32_t erasesize_minor;
|
||||
/* Minimal writable flash unit size. In case of NOR flash it is 1 (even
|
||||
* though individual bits can be cleared), in case of NAND flash it is
|
||||
* one NAND page (or half, or one-fourths of it), in case of ECC-ed NOR
|
|
@ -10,7 +10,7 @@ Signed-off-by: Adrian Schmutzler <freifunk@adrianschmutzler.de>
|
|||
|
||||
--- a/drivers/mtd/parsers/Kconfig
|
||||
+++ b/drivers/mtd/parsers/Kconfig
|
||||
@@ -67,6 +67,22 @@ config MTD_CMDLINE_PARTS
|
||||
@@ -62,6 +62,22 @@ config MTD_CMDLINE_PARTS
|
||||
|
||||
If unsure, say 'N'.
|
||||
|
||||
|
@ -35,7 +35,7 @@ Signed-off-by: Adrian Schmutzler <freifunk@adrianschmutzler.de>
|
|||
default y
|
||||
--- a/drivers/mtd/parsers/Makefile
|
||||
+++ b/drivers/mtd/parsers/Makefile
|
||||
@@ -4,6 +4,7 @@ obj-$(CONFIG_MTD_BCM47XX_PARTS) += bcm4
|
||||
@@ -3,6 +3,7 @@ obj-$(CONFIG_MTD_BCM47XX_PARTS) += bcm4
|
||||
obj-$(CONFIG_MTD_BCM63XX_PARTS) += bcm63xxpart.o
|
||||
obj-$(CONFIG_MTD_BRCM_U_BOOT) += brcm_u-boot.o
|
||||
obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o
|
||||
|
|
|
@ -16,7 +16,7 @@ Signed-off-by: Thibaut VARÈNE <hacks@slashdirt.org>
|
|||
|
||||
--- a/drivers/mtd/parsers/Kconfig
|
||||
+++ b/drivers/mtd/parsers/Kconfig
|
||||
@@ -236,3 +236,12 @@ config MTD_SERCOMM_PARTS
|
||||
@@ -231,3 +231,12 @@ config MTD_SERCOMM_PARTS
|
||||
partition map. This partition table contains real partition
|
||||
offsets, which may differ from device to device depending on the
|
||||
number and location of bad blocks on NAND.
|
||||
|
@ -31,7 +31,7 @@ Signed-off-by: Thibaut VARÈNE <hacks@slashdirt.org>
|
|||
+ formatted DTS.
|
||||
--- a/drivers/mtd/parsers/Makefile
|
||||
+++ b/drivers/mtd/parsers/Makefile
|
||||
@@ -17,3 +17,4 @@ obj-$(CONFIG_MTD_SERCOMM_PARTS) += scpa
|
||||
@@ -16,3 +16,4 @@ obj-$(CONFIG_MTD_SERCOMM_PARTS) += scpa
|
||||
obj-$(CONFIG_MTD_SHARPSL_PARTS) += sharpslpart.o
|
||||
obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o
|
||||
obj-$(CONFIG_MTD_QCOMSMEM_PARTS) += qcomsmempart.o
|
||||
|
|
|
@ -0,0 +1,135 @@
|
|||
From patchwork Tue Jul 30 19:25:59 2024
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
X-Patchwork-Submitter: Daniel Golle <daniel@makrotopia.org>
|
||||
X-Patchwork-Id: 13747816
|
||||
Date: Tue, 30 Jul 2024 20:25:59 +0100
|
||||
From: Daniel Golle <daniel@makrotopia.org>
|
||||
To: Rob Herring <robh@kernel.org>, Krzysztof Kozlowski <krzk+dt@kernel.org>,
|
||||
Conor Dooley <conor+dt@kernel.org>, Jens Axboe <axboe@kernel.dk>,
|
||||
Daniel Golle <daniel@makrotopia.org>, Christian Brauner <brauner@kernel.org>,
|
||||
Al Viro <viro@zeniv.linux.org.uk>, Li Lingfeng <lilingfeng3@huawei.com>,
|
||||
Ming Lei <ming.lei@redhat.com>, Christian Heusel <christian@heusel.eu>,
|
||||
=?utf-8?b?UmFmYcWCIE1pxYJlY2tp?= <rafal@milecki.pl>,
|
||||
Felix Fietkau <nbd@nbd.name>, John Crispin <john@phrozen.org>,
|
||||
Chad Monroe <chad.monroe@adtran.com>, Yangyu Chen <cyy@cyyself.name>,
|
||||
Tianling Shen <cnsztl@immortalwrt.org>, Chuanhong Guo <gch981213@gmail.com>,
|
||||
Chen Minqiang <ptpt52@gmail.com>, devicetree@vger.kernel.org,
|
||||
linux-kernel@vger.kernel.org, linux-block@vger.kernel.org
|
||||
Subject: [PATCH v5 2/4] block: partitions: populate fwnode
|
||||
Message-ID:
|
||||
<3051ac090ad3b3e2f5adb6b67c923261ead729a5.1722365899.git.daniel@makrotopia.org>
|
||||
References: <cover.1722365899.git.daniel@makrotopia.org>
|
||||
Precedence: bulk
|
||||
X-Mailing-List: linux-block@vger.kernel.org
|
||||
List-Id: <linux-block.vger.kernel.org>
|
||||
List-Subscribe: <mailto:linux-block+subscribe@vger.kernel.org>
|
||||
List-Unsubscribe: <mailto:linux-block+unsubscribe@vger.kernel.org>
|
||||
MIME-Version: 1.0
|
||||
Content-Disposition: inline
|
||||
In-Reply-To: <cover.1722365899.git.daniel@makrotopia.org>
|
||||
|
||||
Assign matching firmware nodes to block partitions in order to allow
|
||||
them to be referenced e.g. as NVMEM providers.
|
||||
|
||||
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
---
|
||||
block/partitions/core.c | 72 +++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 72 insertions(+)
|
||||
|
||||
--- a/block/partitions/core.c
|
||||
+++ b/block/partitions/core.c
|
||||
@@ -10,6 +10,8 @@
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/raid/detect.h>
|
||||
+#include <linux/property.h>
|
||||
+
|
||||
#include "check.h"
|
||||
|
||||
static int (*const check_part[])(struct parsed_partitions *) = {
|
||||
@@ -284,6 +286,74 @@ static ssize_t whole_disk_show(struct de
|
||||
}
|
||||
static const DEVICE_ATTR(whole_disk, 0444, whole_disk_show, NULL);
|
||||
|
||||
+static bool part_meta_match(const char *attr, const char *member, size_t length)
|
||||
+{
|
||||
+ /* check if length of attr exceeds specified maximum length */
|
||||
+ if (strnlen(attr, length) == length)
|
||||
+ return false;
|
||||
+
|
||||
+ /* return true if strings match */
|
||||
+ return !strncmp(attr, member, length);
|
||||
+}
|
||||
+
|
||||
+static struct fwnode_handle *find_partition_fwnode(struct block_device *bdev)
|
||||
+{
|
||||
+ struct fwnode_handle *fw_parts, *fw_part;
|
||||
+ struct device *ddev = disk_to_dev(bdev->bd_disk);
|
||||
+ const char *partname, *uuid;
|
||||
+ u32 partno;
|
||||
+ bool got_uuid, got_partname, got_partno;
|
||||
+
|
||||
+ fw_parts = device_get_named_child_node(ddev, "partitions");
|
||||
+ if (!fw_parts)
|
||||
+ return NULL;
|
||||
+
|
||||
+ fwnode_for_each_child_node(fw_parts, fw_part) {
|
||||
+ got_uuid = false;
|
||||
+ got_partname = false;
|
||||
+ got_partno = false;
|
||||
+ /*
|
||||
+ * In case 'uuid' is defined in the partitions firmware node
|
||||
+ * require partition meta info being present and the specified
|
||||
+ * uuid to match.
|
||||
+ */
|
||||
+ got_uuid = !fwnode_property_read_string(fw_part, "uuid", &uuid);
|
||||
+ if (got_uuid && (!bdev->bd_meta_info ||
|
||||
+ !part_meta_match(uuid, bdev->bd_meta_info->uuid,
|
||||
+ PARTITION_META_INFO_UUIDLTH)))
|
||||
+ continue;
|
||||
+
|
||||
+ /*
|
||||
+ * In case 'partname' is defined in the partitions firmware node
|
||||
+ * require partition meta info being present and the specified
|
||||
+ * volname to match.
|
||||
+ */
|
||||
+ got_partname = !fwnode_property_read_string(fw_part, "partname",
|
||||
+ &partname);
|
||||
+ if (got_partname && (!bdev->bd_meta_info ||
|
||||
+ !part_meta_match(partname,
|
||||
+ bdev->bd_meta_info->volname,
|
||||
+ PARTITION_META_INFO_VOLNAMELTH)))
|
||||
+ continue;
|
||||
+
|
||||
+ /*
|
||||
+ * In case 'partno' is defined in the partitions firmware node
|
||||
+ * the specified partno needs to match.
|
||||
+ */
|
||||
+ got_partno = !fwnode_property_read_u32(fw_part, "partno", &partno);
|
||||
+ if (got_partno && (atomic_read(&bdev->__bd_flags) & BD_PARTNO) != partno)
|
||||
+ continue;
|
||||
+
|
||||
+ /* Skip if no matching criteria is present in firmware node */
|
||||
+ if (!got_uuid && !got_partname && !got_partno)
|
||||
+ continue;
|
||||
+
|
||||
+ return fw_part;
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Must be called either with open_mutex held, before a disk can be opened or
|
||||
* after all disk users are gone.
|
||||
@@ -358,6 +428,8 @@ static struct block_device *add_partitio
|
||||
goto out_put;
|
||||
}
|
||||
|
||||
+ device_set_node(pdev, find_partition_fwnode(bdev));
|
||||
+
|
||||
/* delay uevent until 'holders' subdir is created */
|
||||
dev_set_uevent_suppress(pdev, 1);
|
||||
err = device_add(pdev);
|
|
@ -1,7 +1,34 @@
|
|||
From e07ace307ce598847074a096f408bec0e3a392ed Mon Sep 17 00:00:00 2001
|
||||
From patchwork Tue Jul 30 19:26:42 2024
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
X-Patchwork-Submitter: Daniel Golle <daniel@makrotopia.org>
|
||||
X-Patchwork-Id: 13747817
|
||||
Date: Tue, 30 Jul 2024 20:26:42 +0100
|
||||
From: Daniel Golle <daniel@makrotopia.org>
|
||||
Date: Thu, 30 May 2024 03:14:34 +0100
|
||||
Subject: [PATCH 3/9] block: add support for notifications
|
||||
To: Rob Herring <robh@kernel.org>, Krzysztof Kozlowski <krzk+dt@kernel.org>,
|
||||
Conor Dooley <conor+dt@kernel.org>, Jens Axboe <axboe@kernel.dk>,
|
||||
Daniel Golle <daniel@makrotopia.org>, Christian Brauner <brauner@kernel.org>,
|
||||
Al Viro <viro@zeniv.linux.org.uk>, Li Lingfeng <lilingfeng3@huawei.com>,
|
||||
Ming Lei <ming.lei@redhat.com>, Christian Heusel <christian@heusel.eu>,
|
||||
=?utf-8?b?UmFmYcWCIE1pxYJlY2tp?= <rafal@milecki.pl>,
|
||||
Felix Fietkau <nbd@nbd.name>, John Crispin <john@phrozen.org>,
|
||||
Chad Monroe <chad.monroe@adtran.com>, Yangyu Chen <cyy@cyyself.name>,
|
||||
Tianling Shen <cnsztl@immortalwrt.org>, Chuanhong Guo <gch981213@gmail.com>,
|
||||
Chen Minqiang <ptpt52@gmail.com>, devicetree@vger.kernel.org,
|
||||
linux-kernel@vger.kernel.org, linux-block@vger.kernel.org
|
||||
Subject: [PATCH v5 3/4] block: add support for notifications
|
||||
Message-ID:
|
||||
<ca0022886e8f211a323a716653a1396a3bc91653.1722365899.git.daniel@makrotopia.org>
|
||||
References: <cover.1722365899.git.daniel@makrotopia.org>
|
||||
Precedence: bulk
|
||||
X-Mailing-List: linux-block@vger.kernel.org
|
||||
List-Id: <linux-block.vger.kernel.org>
|
||||
List-Subscribe: <mailto:linux-block+subscribe@vger.kernel.org>
|
||||
List-Unsubscribe: <mailto:linux-block+unsubscribe@vger.kernel.org>
|
||||
MIME-Version: 1.0
|
||||
Content-Disposition: inline
|
||||
In-Reply-To: <cover.1722365899.git.daniel@makrotopia.org>
|
||||
|
||||
Add notifier block to notify other subsystems about the addition or
|
||||
removal of block devices.
|
||||
|
@ -10,14 +37,14 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|||
---
|
||||
block/Kconfig | 6 +++
|
||||
block/Makefile | 1 +
|
||||
block/blk-notify.c | 88 ++++++++++++++++++++++++++++++++++++++++++
|
||||
include/linux/blkdev.h | 8 ++++
|
||||
4 files changed, 103 insertions(+)
|
||||
block/blk-notify.c | 87 ++++++++++++++++++++++++++++++++++++++++++
|
||||
include/linux/blkdev.h | 11 ++++++
|
||||
4 files changed, 105 insertions(+)
|
||||
create mode 100644 block/blk-notify.c
|
||||
|
||||
--- a/block/Kconfig
|
||||
+++ b/block/Kconfig
|
||||
@@ -208,6 +208,12 @@ config BLK_INLINE_ENCRYPTION_FALLBACK
|
||||
@@ -209,6 +209,12 @@ config BLK_INLINE_ENCRYPTION_FALLBACK
|
||||
by falling back to the kernel crypto API when inline
|
||||
encryption hardware is not present.
|
||||
|
||||
|
@ -32,14 +59,14 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|||
config BLK_MQ_PCI
|
||||
--- a/block/Makefile
|
||||
+++ b/block/Makefile
|
||||
@@ -40,3 +40,4 @@ obj-$(CONFIG_BLK_INLINE_ENCRYPTION) += b
|
||||
@@ -38,3 +38,4 @@ obj-$(CONFIG_BLK_INLINE_ENCRYPTION) += b
|
||||
blk-crypto-sysfs.o
|
||||
obj-$(CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK) += blk-crypto-fallback.o
|
||||
obj-$(CONFIG_BLOCK_HOLDER_DEPRECATED) += holder.o
|
||||
+obj-$(CONFIG_BLOCK_NOTIFIERS) += blk-notify.o
|
||||
--- /dev/null
|
||||
+++ b/block/blk-notify.c
|
||||
@@ -0,0 +1,88 @@
|
||||
@@ -0,0 +1,87 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
+/*
|
||||
+ * Notifiers for addition and removal of block devices
|
||||
|
@ -97,7 +124,6 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|||
+ list_add_tail(&new_blkdev->list, &blk_devices);
|
||||
+ raw_notifier_call_chain(&blk_notifier_list, BLK_DEVICE_ADD, dev);
|
||||
+ mutex_unlock(&blk_notifier_lock);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
|
@ -130,16 +156,19 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|||
+device_initcall(blk_notifications_init);
|
||||
--- a/include/linux/blkdev.h
|
||||
+++ b/include/linux/blkdev.h
|
||||
@@ -1564,4 +1564,12 @@ struct io_comp_batch {
|
||||
@@ -1689,4 +1689,15 @@ static inline bool bdev_can_atomic_write
|
||||
|
||||
#define DEFINE_IO_COMP_BATCH(name) struct io_comp_batch name = { }
|
||||
|
||||
+
|
||||
+#ifdef CONFIG_BLOCK_NOTIFIERS
|
||||
+#define BLK_DEVICE_ADD 1
|
||||
+#define BLK_DEVICE_REMOVE 2
|
||||
+#if defined(CONFIG_BLOCK_NOTIFIERS)
|
||||
+void blk_register_notify(struct notifier_block *nb);
|
||||
+void blk_unregister_notify(struct notifier_block *nb);
|
||||
+#else
|
||||
+static inline void blk_register_notify(struct notifier_block *nb) { };
|
||||
+static inline void blk_unregister_notify(struct notifier_block *nb) { };
|
||||
+#endif
|
||||
+
|
||||
#endif /* _LINUX_BLKDEV_H */
|
||||
|
|
|
@ -1,7 +1,34 @@
|
|||
From f4487fa1cb7e55b3c17a33f41b9c9d66f4f853b7 Mon Sep 17 00:00:00 2001
|
||||
From patchwork Tue Jul 30 19:27:07 2024
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
X-Patchwork-Submitter: Daniel Golle <daniel@makrotopia.org>
|
||||
X-Patchwork-Id: 13747818
|
||||
Date: Tue, 30 Jul 2024 20:27:07 +0100
|
||||
From: Daniel Golle <daniel@makrotopia.org>
|
||||
Date: Thu, 30 May 2024 03:14:49 +0100
|
||||
Subject: [PATCH 4/9] block: add new genhd flag GENHD_FL_NVMEM
|
||||
To: Rob Herring <robh@kernel.org>, Krzysztof Kozlowski <krzk+dt@kernel.org>,
|
||||
Conor Dooley <conor+dt@kernel.org>, Jens Axboe <axboe@kernel.dk>,
|
||||
Daniel Golle <daniel@makrotopia.org>, Christian Brauner <brauner@kernel.org>,
|
||||
Al Viro <viro@zeniv.linux.org.uk>, Li Lingfeng <lilingfeng3@huawei.com>,
|
||||
Ming Lei <ming.lei@redhat.com>, Christian Heusel <christian@heusel.eu>,
|
||||
=?utf-8?b?UmFmYcWCIE1pxYJlY2tp?= <rafal@milecki.pl>,
|
||||
Felix Fietkau <nbd@nbd.name>, John Crispin <john@phrozen.org>,
|
||||
Chad Monroe <chad.monroe@adtran.com>, Yangyu Chen <cyy@cyyself.name>,
|
||||
Tianling Shen <cnsztl@immortalwrt.org>, Chuanhong Guo <gch981213@gmail.com>,
|
||||
Chen Minqiang <ptpt52@gmail.com>, devicetree@vger.kernel.org,
|
||||
linux-kernel@vger.kernel.org, linux-block@vger.kernel.org
|
||||
Subject: [PATCH v5 4/4] block: add new genhd flag GENHD_FL_NVMEM
|
||||
Message-ID:
|
||||
<311ea569c23ce14e2896cd3b069dc494c58c49c2.1722365899.git.daniel@makrotopia.org>
|
||||
References: <cover.1722365899.git.daniel@makrotopia.org>
|
||||
Precedence: bulk
|
||||
X-Mailing-List: linux-block@vger.kernel.org
|
||||
List-Id: <linux-block.vger.kernel.org>
|
||||
List-Subscribe: <mailto:linux-block+subscribe@vger.kernel.org>
|
||||
List-Unsubscribe: <mailto:linux-block+unsubscribe@vger.kernel.org>
|
||||
MIME-Version: 1.0
|
||||
Content-Disposition: inline
|
||||
In-Reply-To: <cover.1722365899.git.daniel@makrotopia.org>
|
||||
|
||||
Add new flag to destinguish block devices which may act as an NVMEM
|
||||
provider.
|
||||
|
@ -13,7 +40,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|||
|
||||
--- a/include/linux/blkdev.h
|
||||
+++ b/include/linux/blkdev.h
|
||||
@@ -80,11 +80,13 @@ struct partition_meta_info {
|
||||
@@ -82,11 +82,13 @@ struct partition_meta_info {
|
||||
* ``GENHD_FL_NO_PART``: partition support is disabled. The kernel will not
|
||||
* scan for partitions from add_disk, and users can't add partitions manually.
|
||||
*
|
||||
|
|
|
@ -12,7 +12,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|||
|
||||
--- a/drivers/mmc/core/bus.c
|
||||
+++ b/drivers/mmc/core/bus.c
|
||||
@@ -364,6 +364,8 @@ int mmc_add_card(struct mmc_card *card)
|
||||
@@ -368,6 +368,8 @@ int mmc_add_card(struct mmc_card *card)
|
||||
|
||||
mmc_add_card_debugfs(card);
|
||||
card->dev.of_node = mmc_of_find_child_device(card->host, 0);
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
From ef3e38fec26901b71975d7e810a2df6b8bd54a8e Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Golle <daniel@makrotopia.org>
|
||||
Date: Thu, 30 May 2024 03:15:36 +0100
|
||||
Subject: [PATCH 8/9] mmc: block: set fwnode of disk devices
|
||||
|
||||
Set fwnode of disk devices to 'block', 'boot0' and 'boot1' subnodes of
|
||||
the mmc-card. This is done in preparation for having the eMMC act as
|
||||
NVMEM provider.
|
||||
|
||||
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
---
|
||||
drivers/mmc/core/block.c | 7 +++++++
|
||||
1 file changed, 7 insertions(+)
|
||||
|
||||
--- a/drivers/mmc/core/block.c
|
||||
+++ b/drivers/mmc/core/block.c
|
||||
@@ -2678,6 +2678,10 @@ static struct mmc_blk_data *mmc_blk_allo
|
||||
if (area_type == MMC_BLK_DATA_AREA_MAIN)
|
||||
dev_set_drvdata(&card->dev, md);
|
||||
disk_fwnode = mmc_blk_get_partitions_node(parent, subname);
|
||||
+ if (!disk_fwnode)
|
||||
+ disk_fwnode = device_get_named_child_node(subname ? md->parent->parent :
|
||||
+ md->parent,
|
||||
+ subname ? subname : "block");
|
||||
ret = add_disk_fwnode(md->parent, md->disk, mmc_disk_attr_groups,
|
||||
disk_fwnode);
|
||||
if (ret)
|
|
@ -12,7 +12,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|||
|
||||
--- a/drivers/mmc/core/block.c
|
||||
+++ b/drivers/mmc/core/block.c
|
||||
@@ -2516,6 +2516,7 @@ static struct mmc_blk_data *mmc_blk_allo
|
||||
@@ -2644,6 +2644,7 @@ static struct mmc_blk_data *mmc_blk_allo
|
||||
md->disk->major = MMC_BLOCK_MAJOR;
|
||||
md->disk->minors = perdev_minors;
|
||||
md->disk->first_minor = devidx * perdev_minors;
|
||||
|
|
|
@ -8,7 +8,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
|
||||
--- a/drivers/mtd/spi-nor/macronix.c
|
||||
+++ b/drivers/mtd/spi-nor/macronix.c
|
||||
@@ -114,6 +114,7 @@ static int macronix_nor_late_init(struct
|
||||
@@ -194,6 +194,7 @@ static int macronix_nor_late_init(struct
|
||||
{
|
||||
if (!nor->params->set_4byte_addr_mode)
|
||||
nor->params->set_4byte_addr_mode = spi_nor_set_4byte_addr_mode_en4b_ex4b;
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
From: Piotr Dymacz <pepe2k@gmail.com>
|
||||
Subject: kernel/mtd: add support for EON EN25Q128
|
||||
|
||||
Signed-off-by: Piotr Dymacz <pepe2k@gmail.com>
|
||||
---
|
||||
drivers/mtd/spi-nor/spi-nor.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/drivers/mtd/spi-nor/eon.c
|
||||
+++ b/drivers/mtd/spi-nor/eon.c
|
||||
@@ -18,6 +18,11 @@ static const struct flash_info eon_nor_p
|
||||
.name = "en25p64",
|
||||
.size = SZ_8M,
|
||||
}, {
|
||||
+ .id = SNOR_ID(0x1c, 0x30, 0x18),
|
||||
+ .name = "en25q128",
|
||||
+ .size = SZ_16M,
|
||||
+ .no_sfdp_flags = SECT_4K,
|
||||
+ }, {
|
||||
.id = SNOR_ID(0x1c, 0x30, 0x14),
|
||||
.name = "en25q80a",
|
||||
.size = SZ_1M,
|
|
@ -0,0 +1,24 @@
|
|||
From: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Subject: kernel/mtd: add support for EON EN25QX128A
|
||||
|
||||
Add support for EON EN25QX128A with no flags as it does
|
||||
support SFDP parsing.
|
||||
|
||||
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
---
|
||||
drivers/mtd/spi-nor/spi-nor.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/drivers/mtd/spi-nor/eon.c
|
||||
+++ b/drivers/mtd/spi-nor/eon.c
|
||||
@@ -23,6 +23,10 @@ static const struct flash_info eon_nor_p
|
||||
.size = SZ_16M,
|
||||
.no_sfdp_flags = SECT_4K,
|
||||
}, {
|
||||
+ .id = SNOR_ID(0x1c, 0x71, 0x18),
|
||||
+ .name = "en25qx128a",
|
||||
+ .size = SZ_16M,
|
||||
+ }, {
|
||||
.id = SNOR_ID(0x1c, 0x30, 0x14),
|
||||
.name = "en25q80a",
|
||||
.size = SZ_1M,
|
|
@ -0,0 +1,84 @@
|
|||
From patchwork Thu Feb 6 17:19:41 2020
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
X-Patchwork-Submitter: Daniel Golle <daniel@makrotopia.org>
|
||||
X-Patchwork-Id: 1234465
|
||||
Date: Thu, 6 Feb 2020 19:19:41 +0200
|
||||
From: Daniel Golle <daniel@makrotopia.org>
|
||||
To: linux-mtd@lists.infradead.org
|
||||
Subject: [PATCH v2] mtd: spi-nor: Add support for xt25f128b chip
|
||||
Message-ID: <20200206171941.GA2398@makrotopia.org>
|
||||
MIME-Version: 1.0
|
||||
Content-Disposition: inline
|
||||
List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-mtd>,
|
||||
<mailto:linux-mtd-request@lists.infradead.org?subject=subscribe>
|
||||
Cc: Eitan Cohen <eitan@neot-semadar.com>, Piotr Dymacz <pepe2k@gmail.com>,
|
||||
Tudor Ambarus <tudor.ambarus@microchip.com>
|
||||
Sender: "linux-mtd" <linux-mtd-bounces@lists.infradead.org>
|
||||
Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org
|
||||
|
||||
Add XT25F128B made by XTX Technology (Shenzhen) Limited.
|
||||
This chip supports dual and quad read and uniform 4K-byte erase.
|
||||
Verified on Teltonika RUT955 which comes with XT25F128B in recent
|
||||
versions of the device.
|
||||
|
||||
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
drivers/mtd/spi-nor/spi-nor.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
--- a/drivers/mtd/spi-nor/Makefile
|
||||
+++ b/drivers/mtd/spi-nor/Makefile
|
||||
@@ -14,6 +14,7 @@ spi-nor-objs += spansion.o
|
||||
spi-nor-objs += sst.o
|
||||
spi-nor-objs += winbond.o
|
||||
spi-nor-objs += xmc.o
|
||||
+spi-nor-objs += xtx.o
|
||||
spi-nor-$(CONFIG_DEBUG_FS) += debugfs.o
|
||||
obj-$(CONFIG_MTD_SPI_NOR) += spi-nor.o
|
||||
|
||||
--- /dev/null
|
||||
+++ b/drivers/mtd/spi-nor/xtx.c
|
||||
@@ -0,0 +1,20 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+#include <linux/mtd/spi-nor.h>
|
||||
+
|
||||
+#include "core.h"
|
||||
+
|
||||
+static const struct flash_info xtx_parts[] = {
|
||||
+ /* XTX Technology (Shenzhen) Limited */
|
||||
+ {
|
||||
+ .id = SNOR_ID(0x0B, 0x40, 0x18),
|
||||
+ .name = "xt25f128b",
|
||||
+ .size = SZ_16M,
|
||||
+ .no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+const struct spi_nor_manufacturer spi_nor_xtx = {
|
||||
+ .name = "xtx",
|
||||
+ .parts = xtx_parts,
|
||||
+ .nparts = ARRAY_SIZE(xtx_parts),
|
||||
+};
|
||||
--- a/drivers/mtd/spi-nor/core.c
|
||||
+++ b/drivers/mtd/spi-nor/core.c
|
||||
@@ -1979,6 +1979,7 @@ static const struct spi_nor_manufacturer
|
||||
&spi_nor_sst,
|
||||
&spi_nor_winbond,
|
||||
&spi_nor_xmc,
|
||||
+ &spi_nor_xtx,
|
||||
};
|
||||
|
||||
static const struct flash_info spi_nor_generic_flash = {
|
||||
--- a/drivers/mtd/spi-nor/core.h
|
||||
+++ b/drivers/mtd/spi-nor/core.h
|
||||
@@ -593,6 +593,7 @@ extern const struct spi_nor_manufacturer
|
||||
extern const struct spi_nor_manufacturer spi_nor_sst;
|
||||
extern const struct spi_nor_manufacturer spi_nor_winbond;
|
||||
extern const struct spi_nor_manufacturer spi_nor_xmc;
|
||||
+extern const struct spi_nor_manufacturer spi_nor_xtx;
|
||||
|
||||
extern const struct attribute_group *spi_nor_sysfs_groups[];
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
From d68b4aa22e8c625685bfad642dd7337948dc0ad1 Mon Sep 17 00:00:00 2001
|
||||
From: Koen Vandeputte <koen.vandeputte@ncentric.com>
|
||||
Date: Mon, 6 Jan 2020 13:07:56 +0100
|
||||
Subject: [PATCH] mtd: spi-nor: add support for Gigadevice GD25D05
|
||||
|
||||
Signed-off-by: Koen Vandeputte <koen.vandeputte@ncentric.com>
|
||||
---
|
||||
drivers/mtd/spi-nor/spi-nor.c | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
--- a/drivers/mtd/spi-nor/gigadevice.c
|
||||
+++ b/drivers/mtd/spi-nor/gigadevice.c
|
||||
@@ -35,6 +35,12 @@ static const struct spi_nor_fixups gd25q
|
||||
|
||||
static const struct flash_info gigadevice_nor_parts[] = {
|
||||
{
|
||||
+ .id = SNOR_ID(0xc8, 0x40, 0x10),
|
||||
+ .name = "gd25q05",
|
||||
+ .size = SZ_64K,
|
||||
+ .flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB,
|
||||
+ .no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
|
||||
+ }, {
|
||||
.id = SNOR_ID(0xc8, 0x40, 0x15),
|
||||
.name = "gd25q16",
|
||||
.size = SZ_2M,
|
|
@ -0,0 +1,25 @@
|
|||
From f8943df3beb0d3f9754bb35320c3a378727175a8 Mon Sep 17 00:00:00 2001
|
||||
From: OpenWrt community <openwrt-devel@lists.openwrt.org>
|
||||
Date: Thu, 14 Jul 2022 08:38:07 +0200
|
||||
Subject: [PATCH] spi-nor/gigadevic: add gd25q512
|
||||
|
||||
---
|
||||
drivers/mtd/spi-nor/gigadevice.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
--- a/drivers/mtd/spi-nor/gigadevice.c
|
||||
+++ b/drivers/mtd/spi-nor/gigadevice.c
|
||||
@@ -71,6 +71,13 @@ static const struct flash_info gigadevic
|
||||
.fixups = &gd25q256_fixups,
|
||||
.fixup_flags = SPI_NOR_4B_OPCODES,
|
||||
}, {
|
||||
+ .id = SNOR_ID(0xc8, 0x40, 0x20),
|
||||
+ .name = "gd25q512",
|
||||
+ .size = SZ_64M,
|
||||
+ .flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB,
|
||||
+ .no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
|
||||
+ .fixup_flags = SPI_NOR_4B_OPCODES,
|
||||
+ }, {
|
||||
.id = SNOR_ID(0xc8, 0x60, 0x16),
|
||||
.name = "gd25lq32",
|
||||
.size = SZ_4M,
|
|
@ -0,0 +1,27 @@
|
|||
From 87363cc0e522de3294ea6ae10fb468d2a8d6fb2f Mon Sep 17 00:00:00 2001
|
||||
From: OpenWrt community <openwrt-devel@lists.openwrt.org>
|
||||
Date: Wed, 13 Jul 2022 12:17:21 +0200
|
||||
Subject: [PATCH] spi-nor/esmt.c: add esmt f25l16pa
|
||||
|
||||
This fixes support for Dongwon T&I DW02-412H which uses F25L16PA(2S)
|
||||
flash.
|
||||
|
||||
---
|
||||
drivers/mtd/spi-nor/esmt.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
--- a/drivers/mtd/spi-nor/esmt.c
|
||||
+++ b/drivers/mtd/spi-nor/esmt.c
|
||||
@@ -10,6 +10,12 @@
|
||||
|
||||
static const struct flash_info esmt_nor_parts[] = {
|
||||
{
|
||||
+ .id = SNOR_ID(0x8c, 0x21, 0x15),
|
||||
+ .name = "f25l16pa-2s",
|
||||
+ .size = SZ_2M,
|
||||
+ .flags = SPI_NOR_HAS_LOCK,
|
||||
+ .no_sfdp_flags = SECT_4K,
|
||||
+ }, {
|
||||
.id = SNOR_ID(0x8c, 0x20, 0x16),
|
||||
.name = "f25l32pa",
|
||||
.size = SZ_4M,
|
|
@ -0,0 +1,27 @@
|
|||
From f6b33d850f7f12555df2fa0e3349b33427bf5890 Mon Sep 17 00:00:00 2001
|
||||
From: OpenWrt community <openwrt-devel@lists.openwrt.org>
|
||||
Date: Wed, 13 Jul 2022 12:19:01 +0200
|
||||
Subject: [PATCH] spi-nor/xmc.c: add xm25qh128c
|
||||
|
||||
The XMC XM25QH128C is a 16MB SPI NOR chip. The patch is verified on
|
||||
Ruijie RG-EW3200GX PRO.
|
||||
Datasheet available at https://www.xmcwh.com/uploads/435/XM25QH128C.pdf
|
||||
|
||||
---
|
||||
drivers/mtd/spi-nor/xmc.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
--- a/drivers/mtd/spi-nor/xmc.c
|
||||
+++ b/drivers/mtd/spi-nor/xmc.c
|
||||
@@ -19,6 +19,11 @@ static const struct flash_info xmc_nor_p
|
||||
.name = "XM25QH128A",
|
||||
.size = SZ_16M,
|
||||
.no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
|
||||
+ }, {
|
||||
+ .id = SNOR_ID(0x20, 0x40, 0x18),
|
||||
+ .name = "XM25QH128C",
|
||||
+ .size = SZ_16M,
|
||||
+ .no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
|
||||
},
|
||||
};
|
||||
|
|
@ -0,0 +1,170 @@
|
|||
From f32085fc0b87049491b07e198d924d738a1a2834 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Danzberger <daniel@dd-wrt.com>
|
||||
Date: Wed, 3 Aug 2022 17:31:03 +0200
|
||||
Subject: [PATCH] mtd: spinand: Add support for Etron EM73D044VCx
|
||||
|
||||
Airoha is a new ARM platform based on Cortex-A53 which has recently been
|
||||
merged into linux-next.
|
||||
|
||||
Due to BootROM limitations on this platform, the Cortex-A53 can't run in
|
||||
Aarch64 mode and code must be compiled for 32-Bit ARM.
|
||||
|
||||
This support is based mostly on those linux-next commits backported
|
||||
for kernel 5.15.
|
||||
|
||||
Patches:
|
||||
1 - platform support = linux-next
|
||||
2 - clock driver = linux-next
|
||||
3 - gpio driver = linux-next
|
||||
4 - linux,usable-memory-range dts support = linux-next
|
||||
5 - mtd spinand driver
|
||||
6 - spi driver
|
||||
7 - pci driver (kconfig only, uses mediatek PCI) = linux-next
|
||||
|
||||
Still missing:
|
||||
- Ethernet driver
|
||||
- Sysupgrade support
|
||||
|
||||
A.t.m there exists one subtarget EN7523 with only one evaluation
|
||||
board.
|
||||
|
||||
The initramfs can be run with the following commands from u-boot:
|
||||
-
|
||||
u-boot> setenv bootfile \
|
||||
openwrt-airoha-airoha_en7523-evb-initramfs-kernel.bin
|
||||
u-boot> tftpboot
|
||||
u-boot> bootm 0x81800000
|
||||
-
|
||||
|
||||
Submitted-by: Daniel Danzberger <daniel@dd-wrt.com>
|
||||
|
||||
--- a/drivers/mtd/nand/spi/Makefile
|
||||
+++ b/drivers/mtd/nand/spi/Makefile
|
||||
@@ -1,4 +1,4 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
-spinand-objs := core.o alliancememory.o ato.o esmt.o foresee.o gigadevice.o macronix.o
|
||||
-spinand-objs += micron.o paragon.o toshiba.o winbond.o xtx.o
|
||||
+spinand-objs := core.o alliancememory.o ato.o esmt.o etron.o foresee.o gigadevice.o
|
||||
+spinand-objs += macronix.o micron.o paragon.o toshiba.o winbond.o xtx.o
|
||||
obj-$(CONFIG_MTD_SPI_NAND) += spinand.o
|
||||
--- a/drivers/mtd/nand/spi/core.c
|
||||
+++ b/drivers/mtd/nand/spi/core.c
|
||||
@@ -1112,6 +1112,7 @@ static const struct spinand_manufacturer
|
||||
&alliancememory_spinand_manufacturer,
|
||||
&ato_spinand_manufacturer,
|
||||
&esmt_c8_spinand_manufacturer,
|
||||
+ &etron_spinand_manufacturer,
|
||||
&foresee_spinand_manufacturer,
|
||||
&gigadevice_spinand_manufacturer,
|
||||
¯onix_spinand_manufacturer,
|
||||
--- /dev/null
|
||||
+++ b/drivers/mtd/nand/spi/etron.c
|
||||
@@ -0,0 +1,98 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+
|
||||
+#include <linux/device.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/mtd/spinand.h>
|
||||
+
|
||||
+#define SPINAND_MFR_ETRON 0xd5
|
||||
+
|
||||
+
|
||||
+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 *oobregion)
|
||||
+{
|
||||
+ if (section)
|
||||
+ return -ERANGE;
|
||||
+
|
||||
+ oobregion->offset = 72;
|
||||
+ oobregion->length = 56;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int etron_ooblayout_free(struct mtd_info *mtd, int section,
|
||||
+ struct mtd_oob_region *oobregion)
|
||||
+{
|
||||
+ if (section)
|
||||
+ return -ERANGE;
|
||||
+
|
||||
+ oobregion->offset = 1;
|
||||
+ oobregion->length = 71;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+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_HAS_BITFLIPS:
|
||||
+ /* Between 1-7 bitflips were corrected */
|
||||
+ return 7;
|
||||
+
|
||||
+ case STATUS_ECC_MASK:
|
||||
+ /* Maximum bitflips were corrected */
|
||||
+ return 8;
|
||||
+
|
||||
+ case STATUS_ECC_UNCOR_ERROR:
|
||||
+ return -EBADMSG;
|
||||
+ }
|
||||
+
|
||||
+ return -EINVAL;
|
||||
+}
|
||||
+
|
||||
+static const struct mtd_ooblayout_ops etron_ooblayout = {
|
||||
+ .ecc = etron_ooblayout_ecc,
|
||||
+ .free = etron_ooblayout_free,
|
||||
+};
|
||||
+
|
||||
+static const struct spinand_info etron_spinand_table[] = {
|
||||
+ SPINAND_INFO("EM73D044VCx",
|
||||
+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x1f),
|
||||
+ // bpc, pagesize, oobsize, pagesperblock, bperlun, maxbadplun, ppl, lpt, #t
|
||||
+ 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)),
|
||||
+};
|
||||
+
|
||||
+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,
|
||||
+};
|
||||
--- a/include/linux/mtd/spinand.h
|
||||
+++ b/include/linux/mtd/spinand.h
|
||||
@@ -263,6 +263,7 @@ struct spinand_manufacturer {
|
||||
extern const struct spinand_manufacturer alliancememory_spinand_manufacturer;
|
||||
extern const struct spinand_manufacturer ato_spinand_manufacturer;
|
||||
extern const struct spinand_manufacturer esmt_c8_spinand_manufacturer;
|
||||
+extern const struct spinand_manufacturer etron_spinand_manufacturer;
|
||||
extern const struct spinand_manufacturer foresee_spinand_manufacturer;
|
||||
extern const struct spinand_manufacturer gigadevice_spinand_manufacturer;
|
||||
extern const struct spinand_manufacturer macronix_spinand_manufacturer;
|
|
@ -0,0 +1,25 @@
|
|||
From: Joe Mullally <jwmullally@gmail.com>
|
||||
Subject: mtd/spi-nor/xmc: add support for XMC XM25QH64C
|
||||
|
||||
The XMC XM25QH64C is a 8MB SPI NOR chip. The patch is verified on TL-WPA8631P v3.
|
||||
Datasheet available at https://www.xmcwh.com/uploads/442/XM25QH64C.pdf
|
||||
|
||||
Signed-off-by: Joe Mullally <jwmullally@gmail.com>
|
||||
---
|
||||
drivers/mtd/spi-nor/xmc.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
--- a/drivers/mtd/spi-nor/xmc.c
|
||||
+++ b/drivers/mtd/spi-nor/xmc.c
|
||||
@@ -15,6 +15,11 @@ static const struct flash_info xmc_nor_p
|
||||
.size = SZ_8M,
|
||||
.no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
|
||||
}, {
|
||||
+ .id = SNOR_ID(0x20, 0x40, 0x17),
|
||||
+ .name = "XM25QH64C",
|
||||
+ .size = SZ_8M,
|
||||
+ .no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
|
||||
+ }, {
|
||||
.id = SNOR_ID(0x20, 0x70, 0x18),
|
||||
.name = "XM25QH128A",
|
||||
.size = SZ_16M,
|
|
@ -8,7 +8,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|||
|
||||
--- a/drivers/mtd/ubi/build.c
|
||||
+++ b/drivers/mtd/ubi/build.c
|
||||
@@ -1258,6 +1258,80 @@ static struct mtd_notifier ubi_mtd_notif
|
||||
@@ -1263,6 +1263,80 @@ static struct mtd_notifier ubi_mtd_notif
|
||||
.remove = ubi_notify_remove,
|
||||
};
|
||||
|
||||
|
@ -89,7 +89,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|||
static int __init ubi_init_attach(void)
|
||||
{
|
||||
int err, i, k;
|
||||
@@ -1308,6 +1382,12 @@ static int __init ubi_init_attach(void)
|
||||
@@ -1314,6 +1388,12 @@ static int __init ubi_init_attach(void)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|||
|
||||
--- a/drivers/mtd/ubi/block.c
|
||||
+++ b/drivers/mtd/ubi/block.c
|
||||
@@ -570,10 +570,47 @@ match_volume_desc(struct ubi_volume_info
|
||||
@@ -575,10 +575,47 @@ match_volume_desc(struct ubi_volume_info
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|||
+ return magic == UBIFS_NODE_MAGIC;
|
||||
+}
|
||||
+
|
||||
+static void __init ubiblock_create_auto_rootfs(struct ubi_volume_info *vi)
|
||||
+static void ubiblock_create_auto_rootfs(struct ubi_volume_info *vi)
|
||||
+{
|
||||
+ int ret, is_ubifs;
|
||||
+ struct ubi_volume_desc *desc;
|
||||
|
@ -56,7 +56,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|||
struct ubiblock_param *p;
|
||||
|
||||
/*
|
||||
@@ -586,6 +623,7 @@ ubiblock_create_from_param(struct ubi_vo
|
||||
@@ -591,6 +628,7 @@ ubiblock_create_from_param(struct ubi_vo
|
||||
if (!match_volume_desc(vi, p->name, p->ubi_num, p->vol_id))
|
||||
continue;
|
||||
|
||||
|
@ -64,7 +64,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|||
ret = ubiblock_create(vi);
|
||||
if (ret) {
|
||||
pr_err(
|
||||
@@ -594,6 +632,10 @@ ubiblock_create_from_param(struct ubi_vo
|
||||
@@ -599,6 +637,10 @@ ubiblock_create_from_param(struct ubi_vo
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|||
|
||||
--- a/init/do_mounts.c
|
||||
+++ b/init/do_mounts.c
|
||||
@@ -248,7 +248,30 @@ retry:
|
||||
@@ -250,7 +250,30 @@ retry:
|
||||
out:
|
||||
put_page(page);
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|||
#ifdef CONFIG_ROOT_NFS
|
||||
|
||||
#define NFSROOT_TIMEOUT_MIN 5
|
||||
@@ -385,6 +408,11 @@ static inline void mount_block_root(char
|
||||
@@ -387,6 +410,11 @@ static inline void mount_block_root(char
|
||||
|
||||
void __init mount_root(char *root_device_name)
|
||||
{
|
||||
|
|
|
@ -16,7 +16,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|||
|
||||
#include "ubi-media.h"
|
||||
#include "ubi.h"
|
||||
@@ -428,6 +429,15 @@ int ubiblock_create(struct ubi_volume_in
|
||||
@@ -431,6 +432,15 @@ int ubiblock_create(struct ubi_volume_in
|
||||
dev_info(disk_to_dev(dev->gd), "created from ubi%d:%d(%s)",
|
||||
dev->ubi_num, dev->vol_id, vi->name);
|
||||
mutex_unlock(&devices_mutex);
|
||||
|
|
|
@ -50,7 +50,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
|
|||
break;
|
||||
--- a/drivers/mtd/ubi/ubi.h
|
||||
+++ b/drivers/mtd/ubi/ubi.h
|
||||
@@ -780,6 +780,7 @@ struct ubi_attach_info {
|
||||
@@ -778,6 +778,7 @@ struct ubi_attach_info {
|
||||
int mean_ec;
|
||||
uint64_t ec_sum;
|
||||
int ec_count;
|
||||
|
|
|
@ -85,7 +85,7 @@ Signed-off-by: Bernhard Frauendienst <kernel@nospam.obeliks.de>
|
|||
+obj-$(CONFIG_MTD_VIRT_CONCAT) += virt_concat.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/mtd/composite/virt_concat.c
|
||||
@@ -0,0 +1,128 @@
|
||||
@@ -0,0 +1,127 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0+
|
||||
+/*
|
||||
+ * Virtual concat MTD device driver
|
||||
|
@ -94,6 +94,7 @@ Signed-off-by: Bernhard Frauendienst <kernel@nospam.obeliks.de>
|
|||
+ * Author: Bernhard Frauendienst, kernel@nospam.obeliks.de
|
||||
+ */
|
||||
+
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/device.h>
|
||||
+#include <linux/mtd/concat.h>
|
||||
|
@ -115,14 +116,14 @@ Signed-off-by: Bernhard Frauendienst <kernel@nospam.obeliks.de>
|
|||
+ struct mtd_info **devices;
|
||||
+};
|
||||
+
|
||||
+static int virt_concat_remove(struct platform_device *pdev)
|
||||
+static void virt_concat_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct of_virt_concat *info;
|
||||
+ int i;
|
||||
+
|
||||
+ info = platform_get_drvdata(pdev);
|
||||
+ if (!info)
|
||||
+ return 0;
|
||||
+ return;
|
||||
+
|
||||
+ // unset data for when this is called after a probe error
|
||||
+ platform_set_drvdata(pdev, NULL);
|
||||
|
@ -136,8 +137,6 @@ Signed-off-by: Bernhard Frauendienst <kernel@nospam.obeliks.de>
|
|||
+ for (i = 0; i < info->num_devices; i++)
|
||||
+ put_mtd_device(info->devices[i]);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int virt_concat_probe(struct platform_device *pdev)
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
From 8bf2ce6ea4ee840b70f55a27f80e1cd308051b13 Mon Sep 17 00:00:00 2001
|
||||
From: Nick Hainke <vincent@systemli.org>
|
||||
Date: Mon, 27 Dec 2021 00:38:13 +0100
|
||||
Subject: [PATCH 1/2] mtd: spi-nor: locking support for MX25L6405D
|
||||
|
||||
Macronix MX25L6405D supports locking with four block-protection bits.
|
||||
Currently, the driver only sets three bits. If the bootloader does not
|
||||
sustain the flash chip in an unlocked state, the flash might be
|
||||
non-writeable. Add the corresponding flag to enable locking support with
|
||||
four bits in the status register.
|
||||
|
||||
Tested on Nanostation M2 XM.
|
||||
|
||||
Similar to commit 7ea40b54e83b ("mtd: spi-nor: enable locking support for
|
||||
MX25L12805D")
|
||||
|
||||
Signed-off-by: David Bauer <mail@david-bauer.net>
|
||||
Signed-off-by: Nick Hainke <vincent@systemli.org>
|
||||
---
|
||||
drivers/mtd/spi-nor/macronix.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/mtd/spi-nor/macronix.c
|
||||
+++ b/drivers/mtd/spi-nor/macronix.c
|
||||
@@ -66,6 +66,7 @@ static const struct flash_info macronix_
|
||||
.id = SNOR_ID(0xc2, 0x20, 0x17),
|
||||
.name = "mx25l6405d",
|
||||
.size = SZ_8M,
|
||||
+ .flags = SPI_NOR_HAS_LOCK | SPI_NOR_4BIT_BP,
|
||||
.no_sfdp_flags = SECT_4K,
|
||||
}, {
|
||||
.id = SNOR_ID(0xc2, 0x20, 0x18),
|
|
@ -20,7 +20,7 @@ Signed-off-by: Nick Hainke <vincent@systemli.org>
|
|||
|
||||
--- a/drivers/mtd/spi-nor/macronix.c
|
||||
+++ b/drivers/mtd/spi-nor/macronix.c
|
||||
@@ -115,6 +115,7 @@ static int macronix_nor_late_init(struct
|
||||
@@ -195,6 +195,7 @@ static int macronix_nor_late_init(struct
|
||||
{
|
||||
if (!nor->params->set_4byte_addr_mode)
|
||||
nor->params->set_4byte_addr_mode = spi_nor_set_4byte_addr_mode_en4b_ex4b;
|
||||
|
|
|
@ -36,7 +36,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|||
|
||||
--- a/MAINTAINERS
|
||||
+++ b/MAINTAINERS
|
||||
@@ -22014,6 +22014,12 @@ F: Documentation/filesystems/ubifs-authe
|
||||
@@ -23658,6 +23658,12 @@ F: Documentation/filesystems/ubifs-authe
|
||||
F: Documentation/filesystems/ubifs.rst
|
||||
F: fs/ubifs/
|
||||
|
||||
|
@ -51,9 +51,9 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|||
L: linux-block@vger.kernel.org
|
||||
--- a/drivers/block/Kconfig
|
||||
+++ b/drivers/block/Kconfig
|
||||
@@ -354,6 +354,18 @@ config VIRTIO_BLK
|
||||
This is the virtual block driver for virtio. It can be used with
|
||||
QEMU based VMMs (like KVM or Xen). Say Y or M.
|
||||
@@ -363,6 +363,18 @@ config BLK_DEV_RUST_NULL
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
+config UIMAGE_FIT_BLK
|
||||
+ bool "uImage.FIT block driver"
|
||||
|
@ -72,7 +72,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|||
depends on INET && BLOCK
|
||||
--- a/drivers/block/Makefile
|
||||
+++ b/drivers/block/Makefile
|
||||
@@ -39,4 +39,6 @@ obj-$(CONFIG_BLK_DEV_NULL_BLK) += null_b
|
||||
@@ -42,4 +42,6 @@ obj-$(CONFIG_BLK_DEV_NULL_BLK) += null_b
|
||||
|
||||
obj-$(CONFIG_BLK_DEV_UBLK) += ublk_drv.o
|
||||
|
||||
|
@ -81,7 +81,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|||
swim_mod-y := swim.o swim_asm.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/block/fitblk.c
|
||||
@@ -0,0 +1,659 @@
|
||||
@@ -0,0 +1,658 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-only
|
||||
+/*
|
||||
+ * uImage.FIT virtual block device driver.
|
||||
|
@ -668,7 +668,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|||
+ (imgmaxsect + MIN_FREE_SECT) < dsectors) {
|
||||
+ add_fit_subimage_device(bdev, slot++, imgmaxsect,
|
||||
+ dsectors - imgmaxsect, false);
|
||||
+ dev_info(dev, "mapped remaing space as /dev/fitrw\n");
|
||||
+ dev_info(dev, "mapped remaining space as /dev/fitrw\n");
|
||||
+ }
|
||||
+
|
||||
+out_bootconf:
|
||||
|
@ -714,7 +714,6 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|||
+ .probe = fitblk_probe,
|
||||
+ .driver = {
|
||||
+ .name = "fitblk",
|
||||
+ .owner = THIS_MODULE,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
|
|
|
@ -13,7 +13,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|||
|
||||
--- a/init/do_mounts.c
|
||||
+++ b/init/do_mounts.c
|
||||
@@ -463,7 +463,8 @@ static dev_t __init parse_root_device(ch
|
||||
@@ -465,7 +465,8 @@ static dev_t __init parse_root_device(ch
|
||||
int error;
|
||||
dev_t dev;
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -17,7 +17,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
#include <net/net_namespace.h>
|
||||
#ifdef CONFIG_SYSCTL
|
||||
#include <linux/sysctl.h>
|
||||
@@ -461,6 +462,58 @@ static int ct_cpu_seq_show(struct seq_fi
|
||||
@@ -458,6 +459,58 @@ static int ct_cpu_seq_show(struct seq_fi
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -76,7 +76,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
static const struct seq_operations ct_cpu_seq_ops = {
|
||||
.start = ct_cpu_seq_start,
|
||||
.next = ct_cpu_seq_next,
|
||||
@@ -474,8 +527,9 @@ static int nf_conntrack_standalone_init_
|
||||
@@ -471,8 +524,9 @@ static int nf_conntrack_standalone_init_
|
||||
kuid_t root_uid;
|
||||
kgid_t root_gid;
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ Link: https://bugzilla.kernel.org/show_bug.cgi?id=109581
|
|||
|
||||
--- a/net/sched/sch_codel.c
|
||||
+++ b/net/sched/sch_codel.c
|
||||
@@ -95,11 +95,17 @@ static struct sk_buff *codel_qdisc_deque
|
||||
@@ -65,11 +65,17 @@ static struct sk_buff *codel_qdisc_deque
|
||||
&q->stats, qdisc_pkt_len, codel_get_enqueue_time,
|
||||
drop_func, dequeue_func);
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
#define PACKET_FANOUT_LB 1
|
||||
--- a/net/packet/af_packet.c
|
||||
+++ b/net/packet/af_packet.c
|
||||
@@ -1864,6 +1864,7 @@ static int packet_rcv_spkt(struct sk_buf
|
||||
@@ -1925,6 +1925,7 @@ static int packet_rcv_spkt(struct sk_buf
|
||||
{
|
||||
struct sock *sk;
|
||||
struct sockaddr_pkt *spkt;
|
||||
|
@ -38,7 +38,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
|
||||
/*
|
||||
* When we registered the protocol we saved the socket in the data
|
||||
@@ -1871,6 +1872,7 @@ static int packet_rcv_spkt(struct sk_buf
|
||||
@@ -1932,6 +1933,7 @@ static int packet_rcv_spkt(struct sk_buf
|
||||
*/
|
||||
|
||||
sk = pt->af_packet_priv;
|
||||
|
@ -46,7 +46,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
|
||||
/*
|
||||
* Yank back the headers [hope the device set this
|
||||
@@ -1883,7 +1885,7 @@ static int packet_rcv_spkt(struct sk_buf
|
||||
@@ -1944,7 +1946,7 @@ static int packet_rcv_spkt(struct sk_buf
|
||||
* so that this procedure is noop.
|
||||
*/
|
||||
|
||||
|
@ -55,9 +55,9 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
goto out;
|
||||
|
||||
if (!net_eq(dev_net(dev), sock_net(sk)))
|
||||
@@ -2129,12 +2131,12 @@ static int packet_rcv(struct sk_buff *sk
|
||||
@@ -2189,12 +2191,12 @@ static int packet_rcv(struct sk_buff *sk
|
||||
int skb_len = skb->len;
|
||||
unsigned int snaplen, res;
|
||||
bool is_drop_n_account = false;
|
||||
|
||||
- if (skb->pkt_type == PACKET_LOOPBACK)
|
||||
- goto drop;
|
||||
|
@ -71,7 +71,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
if (!net_eq(dev_net(dev), sock_net(sk)))
|
||||
goto drop;
|
||||
|
||||
@@ -2261,12 +2263,12 @@ static int tpacket_rcv(struct sk_buff *s
|
||||
@@ -2318,12 +2320,12 @@ static int tpacket_rcv(struct sk_buff *s
|
||||
BUILD_BUG_ON(TPACKET_ALIGN(sizeof(*h.h2)) != 32);
|
||||
BUILD_BUG_ON(TPACKET_ALIGN(sizeof(*h.h3)) != 48);
|
||||
|
||||
|
@ -87,7 +87,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
if (!net_eq(dev_net(dev), sock_net(sk)))
|
||||
goto drop;
|
||||
|
||||
@@ -3385,6 +3387,7 @@ static int packet_create(struct net *net
|
||||
@@ -3444,6 +3446,7 @@ static int packet_create(struct net *net
|
||||
mutex_init(&po->pg_vec_lock);
|
||||
po->rollover = NULL;
|
||||
po->prot_hook.func = packet_rcv;
|
||||
|
@ -95,7 +95,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
|
||||
if (sock->type == SOCK_PACKET)
|
||||
po->prot_hook.func = packet_rcv_spkt;
|
||||
@@ -4034,6 +4037,16 @@ packet_setsockopt(struct socket *sock, i
|
||||
@@ -4111,6 +4114,16 @@ packet_setsockopt(struct socket *sock, i
|
||||
packet_sock_flag_set(po, PACKET_SOCK_QDISC_BYPASS, val);
|
||||
return 0;
|
||||
}
|
||||
|
@ -112,9 +112,9 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
default:
|
||||
return -ENOPROTOOPT;
|
||||
}
|
||||
@@ -4093,6 +4106,13 @@ static int packet_getsockopt(struct sock
|
||||
case PACKET_VNET_HDR_SZ:
|
||||
val = READ_ONCE(po->vnet_hdr_sz);
|
||||
@@ -4173,6 +4186,13 @@ static int packet_getsockopt(struct sock
|
||||
case PACKET_COPY_THRESH:
|
||||
val = READ_ONCE(pkt_sk(sk)->copy_thresh);
|
||||
break;
|
||||
+ case PACKET_RECV_TYPE:
|
||||
+ if (len > sizeof(unsigned int))
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Thu, 22 Aug 2024 18:02:17 +0200
|
||||
Subject: [PATCH] net: bridge: fix switchdev host mdb entry updates
|
||||
|
||||
When a mdb entry is removed, the bridge switchdev code can issue a
|
||||
switchdev_port_obj_del call for a port that was not offloaded.
|
||||
|
||||
This leads to an imbalance in switchdev_port_obj_add/del calls, since
|
||||
br_switchdev_mdb_replay has not been called for the port before.
|
||||
|
||||
This can lead to potential multicast forwarding issues and messages such as:
|
||||
mt7915e 0000:01:00.0 wl1-ap0: Failed to del Host Multicast Database entry
|
||||
(object id=3) with error: -ENOENT (-2).
|
||||
|
||||
Fix this issue by checking the port offload status when iterating over
|
||||
lower devs.
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
|
||||
--- a/net/bridge/br_switchdev.c
|
||||
+++ b/net/bridge/br_switchdev.c
|
||||
@@ -568,10 +568,18 @@ static void br_switchdev_host_mdb(struct
|
||||
struct net_bridge_mdb_entry *mp, int type)
|
||||
{
|
||||
struct net_device *lower_dev;
|
||||
+ struct net_bridge_port *port;
|
||||
struct list_head *iter;
|
||||
|
||||
- netdev_for_each_lower_dev(dev, lower_dev, iter)
|
||||
+ rcu_read_lock();
|
||||
+ netdev_for_each_lower_dev(dev, lower_dev, iter) {
|
||||
+ port = br_port_get_rcu(lower_dev);
|
||||
+ if (!port || !port->offload_count)
|
||||
+ continue;
|
||||
+
|
||||
br_switchdev_host_mdb_one(dev, lower_dev, mp, type);
|
||||
+ }
|
||||
+ rcu_read_unlock();
|
||||
}
|
||||
|
||||
static int
|
|
@ -0,0 +1,38 @@
|
|||
From: "Leon M. Busch-George" <leon@georgemail.eu>
|
||||
Date: Sun, 20 Oct 2024 18:20:14 +0200
|
||||
Subject: [PATCH] net: bridge: switchdev: Don't drop packets between ports with
|
||||
no hwdom
|
||||
|
||||
nbp_switchdev_allowed_egress uses hwdom to determine whether or not a
|
||||
packet has already been forwarded to a hardware domain. For
|
||||
net_bridge_ports that aren't set up to use forward offloading, hwdom is
|
||||
set to 0. When both ingress and egress port have no hwdom,
|
||||
'cb->src_hwdom != p->hwdom' indicates that the packet is already known in
|
||||
the target domain - which it isn't - and the packet is wrongly dropped.
|
||||
|
||||
The error was found on a bridge containing a wifi device and a VLAN
|
||||
tagging device (e.g. eth0.12). With VLAN filtering, this shouldn't happen.
|
||||
|
||||
This patch adds a check for p->hwdom != 0 before comparing hardware
|
||||
domains to restore forwarding between ports with hwdom = 0.
|
||||
|
||||
fwd_hwdoms are only set for ports with offloading enabled, which also
|
||||
implies a valid hwdom, so the check '!test_bit(p->hwdom, &cb->fwd_hwdoms)'
|
||||
doesn't fail in this way (yet - fingers crossed..) and it is left in place.
|
||||
|
||||
Co-developed-by: Felix Fietkau <nbd@nbd.name>
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
Signed-off-by: Leon M. Busch-George <leon@georgemail.eu>
|
||||
---
|
||||
|
||||
--- a/net/bridge/br_switchdev.c
|
||||
+++ b/net/bridge/br_switchdev.c
|
||||
@@ -67,7 +67,7 @@ bool nbp_switchdev_allowed_egress(const
|
||||
struct br_input_skb_cb *cb = BR_INPUT_SKB_CB(skb);
|
||||
|
||||
return !test_bit(p->hwdom, &cb->fwd_hwdoms) &&
|
||||
- (!skb->offload_fwd_mark || cb->src_hwdom != p->hwdom);
|
||||
+ (!skb->offload_fwd_mark || !p->hwdom || cb->src_hwdom != p->hwdom);
|
||||
}
|
||||
|
||||
/* Flags that can be offloaded to hardware */
|
|
@ -9,7 +9,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
|
||||
--- a/include/linux/skbuff.h
|
||||
+++ b/include/linux/skbuff.h
|
||||
@@ -3062,7 +3062,7 @@ static inline int pskb_network_may_pull(
|
||||
@@ -3180,7 +3180,7 @@ static inline int pskb_network_may_pull(
|
||||
* NET_IP_ALIGN(2) + ethernet_header(14) + IP_header(20/40) + ports(8)
|
||||
*/
|
||||
#ifndef NET_SKB_PAD
|
||||
|
|
|
@ -39,8 +39,8 @@ Signed-off-by: Steven Barth <cyrus@openwrt.org>
|
|||
struct in6_addr raddr; /* remote tunnel end-point address */
|
||||
+ struct __ip6_tnl_fmr *fmrs; /* FMRs */
|
||||
|
||||
__be16 i_flags;
|
||||
__be16 o_flags;
|
||||
IP_TUNNEL_DECLARE_FLAGS(i_flags);
|
||||
IP_TUNNEL_DECLARE_FLAGS(o_flags);
|
||||
--- a/include/uapi/linux/if_tunnel.h
|
||||
+++ b/include/uapi/linux/if_tunnel.h
|
||||
@@ -77,10 +77,23 @@ enum {
|
||||
|
@ -79,7 +79,7 @@ Signed-off-by: Steven Barth <cyrus@openwrt.org>
|
|||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
@@ -67,9 +70,9 @@ static bool log_ecn_error = true;
|
||||
@@ -68,9 +71,9 @@ static bool log_ecn_error = true;
|
||||
module_param(log_ecn_error, bool, 0644);
|
||||
MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN");
|
||||
|
||||
|
@ -91,7 +91,7 @@ Signed-off-by: Steven Barth <cyrus@openwrt.org>
|
|||
|
||||
return hash_32(hash, IP6_TUNNEL_HASH_SIZE_SHIFT);
|
||||
}
|
||||
@@ -114,17 +117,33 @@ static struct ip6_tnl *
|
||||
@@ -115,17 +118,33 @@ static struct ip6_tnl *
|
||||
ip6_tnl_lookup(struct net *net, int link,
|
||||
const struct in6_addr *remote, const struct in6_addr *local)
|
||||
{
|
||||
|
@ -127,7 +127,7 @@ Signed-off-by: Steven Barth <cyrus@openwrt.org>
|
|||
if (link == t->parms.link)
|
||||
return t;
|
||||
else
|
||||
@@ -132,7 +151,7 @@ ip6_tnl_lookup(struct net *net, int link
|
||||
@@ -133,7 +152,7 @@ ip6_tnl_lookup(struct net *net, int link
|
||||
}
|
||||
|
||||
memset(&any, 0, sizeof(any));
|
||||
|
@ -136,7 +136,7 @@ Signed-off-by: Steven Barth <cyrus@openwrt.org>
|
|||
for_each_ip6_tunnel_rcu(ip6n->tnls_r_l[hash]) {
|
||||
if (!ipv6_addr_equal(local, &t->parms.laddr) ||
|
||||
!ipv6_addr_any(&t->parms.raddr) ||
|
||||
@@ -145,7 +164,7 @@ ip6_tnl_lookup(struct net *net, int link
|
||||
@@ -146,7 +165,7 @@ ip6_tnl_lookup(struct net *net, int link
|
||||
cand = t;
|
||||
}
|
||||
|
||||
|
@ -145,7 +145,7 @@ Signed-off-by: Steven Barth <cyrus@openwrt.org>
|
|||
for_each_ip6_tunnel_rcu(ip6n->tnls_r_l[hash]) {
|
||||
if (!ipv6_addr_equal(remote, &t->parms.raddr) ||
|
||||
!ipv6_addr_any(&t->parms.laddr) ||
|
||||
@@ -194,7 +213,7 @@ ip6_tnl_bucket(struct ip6_tnl_net *ip6n,
|
||||
@@ -195,7 +214,7 @@ ip6_tnl_bucket(struct ip6_tnl_net *ip6n,
|
||||
|
||||
if (!ipv6_addr_any(remote) || !ipv6_addr_any(local)) {
|
||||
prio = 1;
|
||||
|
@ -167,7 +167,7 @@ Signed-off-by: Steven Barth <cyrus@openwrt.org>
|
|||
if (dev == ip6n->fb_tnl_dev)
|
||||
RCU_INIT_POINTER(ip6n->tnls_wc[0], NULL);
|
||||
else
|
||||
@@ -788,6 +813,107 @@ int ip6_tnl_rcv_ctl(struct ip6_tnl *t,
|
||||
@@ -790,6 +815,107 @@ int ip6_tnl_rcv_ctl(struct ip6_tnl *t,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ip6_tnl_rcv_ctl);
|
||||
|
||||
|
@ -303,7 +303,7 @@ Signed-off-by: Steven Barth <cyrus@openwrt.org>
|
|||
__skb_tunnel_rx(skb, tunnel->dev, tunnel->net);
|
||||
|
||||
err = dscp_ecn_decapsulate(tunnel, ipv6h, skb);
|
||||
@@ -1002,6 +1149,7 @@ static void init_tel_txopt(struct ipv6_t
|
||||
@@ -1004,6 +1151,7 @@ static void init_tel_txopt(struct ipv6_t
|
||||
opt->ops.opt_nflen = 8;
|
||||
}
|
||||
|
||||
|
@ -311,7 +311,7 @@ Signed-off-by: Steven Barth <cyrus@openwrt.org>
|
|||
/**
|
||||
* ip6_tnl_addr_conflict - compare packet addresses to tunnel's own
|
||||
* @t: the outgoing tunnel device
|
||||
@@ -1292,6 +1440,7 @@ ipxip6_tnl_xmit(struct sk_buff *skb, str
|
||||
@@ -1294,6 +1442,7 @@ ipxip6_tnl_xmit(struct sk_buff *skb, str
|
||||
u8 protocol)
|
||||
{
|
||||
struct ip6_tnl *t = netdev_priv(dev);
|
||||
|
@ -319,7 +319,7 @@ Signed-off-by: Steven Barth <cyrus@openwrt.org>
|
|||
struct ipv6hdr *ipv6h;
|
||||
const struct iphdr *iph;
|
||||
int encap_limit = -1;
|
||||
@@ -1391,6 +1540,18 @@ ipxip6_tnl_xmit(struct sk_buff *skb, str
|
||||
@@ -1393,6 +1542,18 @@ ipxip6_tnl_xmit(struct sk_buff *skb, str
|
||||
fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL);
|
||||
dsfield = INET_ECN_encapsulate(dsfield, orig_dsfield);
|
||||
|
||||
|
@ -338,7 +338,7 @@ Signed-off-by: Steven Barth <cyrus@openwrt.org>
|
|||
if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6))
|
||||
return -1;
|
||||
|
||||
@@ -1543,6 +1704,14 @@ ip6_tnl_change(struct ip6_tnl *t, const
|
||||
@@ -1546,6 +1707,14 @@ ip6_tnl_change(struct ip6_tnl *t, const
|
||||
t->parms.link = p->link;
|
||||
t->parms.proto = p->proto;
|
||||
t->parms.fwmark = p->fwmark;
|
||||
|
@ -353,7 +353,7 @@ Signed-off-by: Steven Barth <cyrus@openwrt.org>
|
|||
dst_cache_reset(&t->dst_cache);
|
||||
ip6_tnl_link_config(t);
|
||||
}
|
||||
@@ -1577,6 +1746,7 @@ ip6_tnl_parm_from_user(struct __ip6_tnl_
|
||||
@@ -1580,6 +1749,7 @@ ip6_tnl_parm_from_user(struct __ip6_tnl_
|
||||
p->flowinfo = u->flowinfo;
|
||||
p->link = u->link;
|
||||
p->proto = u->proto;
|
||||
|
@ -361,7 +361,7 @@ Signed-off-by: Steven Barth <cyrus@openwrt.org>
|
|||
memcpy(p->name, u->name, sizeof(u->name));
|
||||
}
|
||||
|
||||
@@ -1964,6 +2134,15 @@ static int ip6_tnl_validate(struct nlatt
|
||||
@@ -1963,6 +2133,15 @@ static int ip6_tnl_validate(struct nlatt
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -377,7 +377,7 @@ Signed-off-by: Steven Barth <cyrus@openwrt.org>
|
|||
static void ip6_tnl_netlink_parms(struct nlattr *data[],
|
||||
struct __ip6_tnl_parm *parms)
|
||||
{
|
||||
@@ -2001,6 +2180,46 @@ static void ip6_tnl_netlink_parms(struct
|
||||
@@ -2000,6 +2179,46 @@ static void ip6_tnl_netlink_parms(struct
|
||||
|
||||
if (data[IFLA_IPTUN_FWMARK])
|
||||
parms->fwmark = nla_get_u32(data[IFLA_IPTUN_FWMARK]);
|
||||
|
@ -424,7 +424,7 @@ Signed-off-by: Steven Barth <cyrus@openwrt.org>
|
|||
}
|
||||
|
||||
static int ip6_tnl_newlink(struct net *src_net, struct net_device *dev,
|
||||
@@ -2084,6 +2303,12 @@ static void ip6_tnl_dellink(struct net_d
|
||||
@@ -2083,6 +2302,12 @@ static void ip6_tnl_dellink(struct net_d
|
||||
|
||||
static size_t ip6_tnl_get_size(const struct net_device *dev)
|
||||
{
|
||||
|
@ -437,7 +437,7 @@ Signed-off-by: Steven Barth <cyrus@openwrt.org>
|
|||
return
|
||||
/* IFLA_IPTUN_LINK */
|
||||
nla_total_size(4) +
|
||||
@@ -2113,6 +2338,24 @@ static size_t ip6_tnl_get_size(const str
|
||||
@@ -2112,6 +2337,24 @@ static size_t ip6_tnl_get_size(const str
|
||||
nla_total_size(0) +
|
||||
/* IFLA_IPTUN_FWMARK */
|
||||
nla_total_size(4) +
|
||||
|
@ -462,7 +462,7 @@ Signed-off-by: Steven Barth <cyrus@openwrt.org>
|
|||
0;
|
||||
}
|
||||
|
||||
@@ -2120,6 +2363,9 @@ static int ip6_tnl_fill_info(struct sk_b
|
||||
@@ -2119,6 +2362,9 @@ static int ip6_tnl_fill_info(struct sk_b
|
||||
{
|
||||
struct ip6_tnl *tunnel = netdev_priv(dev);
|
||||
struct __ip6_tnl_parm *parm = &tunnel->parms;
|
||||
|
@ -472,7 +472,7 @@ Signed-off-by: Steven Barth <cyrus@openwrt.org>
|
|||
|
||||
if (nla_put_u32(skb, IFLA_IPTUN_LINK, parm->link) ||
|
||||
nla_put_in6_addr(skb, IFLA_IPTUN_LOCAL, &parm->laddr) ||
|
||||
@@ -2129,9 +2375,27 @@ static int ip6_tnl_fill_info(struct sk_b
|
||||
@@ -2128,9 +2374,27 @@ static int ip6_tnl_fill_info(struct sk_b
|
||||
nla_put_be32(skb, IFLA_IPTUN_FLOWINFO, parm->flowinfo) ||
|
||||
nla_put_u32(skb, IFLA_IPTUN_FLAGS, parm->flags) ||
|
||||
nla_put_u8(skb, IFLA_IPTUN_PROTO, parm->proto) ||
|
||||
|
@ -501,7 +501,7 @@ Signed-off-by: Steven Barth <cyrus@openwrt.org>
|
|||
if (nla_put_u16(skb, IFLA_IPTUN_ENCAP_TYPE, tunnel->encap.type) ||
|
||||
nla_put_be16(skb, IFLA_IPTUN_ENCAP_SPORT, tunnel->encap.sport) ||
|
||||
nla_put_be16(skb, IFLA_IPTUN_ENCAP_DPORT, tunnel->encap.dport) ||
|
||||
@@ -2171,6 +2435,7 @@ static const struct nla_policy ip6_tnl_p
|
||||
@@ -2170,6 +2434,7 @@ static const struct nla_policy ip6_tnl_p
|
||||
[IFLA_IPTUN_ENCAP_DPORT] = { .type = NLA_U16 },
|
||||
[IFLA_IPTUN_COLLECT_METADATA] = { .type = NLA_FLAG },
|
||||
[IFLA_IPTUN_FWMARK] = { .type = NLA_U32 },
|
||||
|
|
|
@ -30,7 +30,7 @@ Signed-off-by: Jonas Gorski <jogo@openwrt.org>
|
|||
struct fib_rules_ops *fib6_rules_ops;
|
||||
--- a/include/uapi/linux/fib_rules.h
|
||||
+++ b/include/uapi/linux/fib_rules.h
|
||||
@@ -82,6 +82,10 @@ enum {
|
||||
@@ -83,6 +83,10 @@ enum {
|
||||
FR_ACT_BLACKHOLE, /* Drop without notification */
|
||||
FR_ACT_UNREACHABLE, /* Drop with ENETUNREACH */
|
||||
FR_ACT_PROHIBIT, /* Drop with EACCES */
|
||||
|
@ -66,7 +66,7 @@ Signed-off-by: Jonas Gorski <jogo@openwrt.org>
|
|||
static void rt_fibinfo_free(struct rtable __rcu **rtp)
|
||||
--- a/net/ipv4/fib_trie.c
|
||||
+++ b/net/ipv4/fib_trie.c
|
||||
@@ -2783,6 +2783,7 @@ static const char *const rtn_type_names[
|
||||
@@ -2784,6 +2784,7 @@ static const char *const rtn_type_names[
|
||||
[RTN_THROW] = "THROW",
|
||||
[RTN_NAT] = "NAT",
|
||||
[RTN_XRESOLVE] = "XRESOLVE",
|
||||
|
@ -76,7 +76,7 @@ Signed-off-by: Jonas Gorski <jogo@openwrt.org>
|
|||
static inline const char *rtn_type(char *buf, size_t len, unsigned int t)
|
||||
--- a/net/ipv4/ipmr.c
|
||||
+++ b/net/ipv4/ipmr.c
|
||||
@@ -180,6 +180,7 @@ static int ipmr_rule_action(struct fib_r
|
||||
@@ -191,6 +191,7 @@ static int ipmr_rule_action(struct fib_r
|
||||
case FR_ACT_UNREACHABLE:
|
||||
return -ENETUNREACH;
|
||||
case FR_ACT_PROHIBIT:
|
||||
|
@ -86,7 +86,7 @@ Signed-off-by: Jonas Gorski <jogo@openwrt.org>
|
|||
default:
|
||||
--- a/net/ipv6/fib6_rules.c
|
||||
+++ b/net/ipv6/fib6_rules.c
|
||||
@@ -221,6 +221,10 @@ static int __fib6_rule_action(struct fib
|
||||
@@ -222,6 +222,10 @@ static int __fib6_rule_action(struct fib
|
||||
err = -EACCES;
|
||||
rt = net->ipv6.ip6_prohibit_entry;
|
||||
goto discard_pkt;
|
||||
|
@ -99,7 +99,7 @@ Signed-off-by: Jonas Gorski <jogo@openwrt.org>
|
|||
tb_id = fib_rule_get_table(rule, arg);
|
||||
--- a/net/ipv6/ip6mr.c
|
||||
+++ b/net/ipv6/ip6mr.c
|
||||
@@ -170,6 +170,8 @@ static int ip6mr_rule_action(struct fib_
|
||||
@@ -180,6 +180,8 @@ static int ip6mr_rule_action(struct fib_
|
||||
return -ENETUNREACH;
|
||||
case FR_ACT_PROHIBIT:
|
||||
return -EACCES;
|
||||
|
@ -110,7 +110,7 @@ Signed-off-by: Jonas Gorski <jogo@openwrt.org>
|
|||
return -EINVAL;
|
||||
--- a/net/ipv6/route.c
|
||||
+++ b/net/ipv6/route.c
|
||||
@@ -97,6 +97,8 @@ static int ip6_pkt_discard(struct sk_bu
|
||||
@@ -98,6 +98,8 @@ static int ip6_pkt_discard(struct sk_bu
|
||||
static int ip6_pkt_discard_out(struct net *net, struct sock *sk, struct sk_buff *skb);
|
||||
static int ip6_pkt_prohibit(struct sk_buff *skb);
|
||||
static int ip6_pkt_prohibit_out(struct net *net, struct sock *sk, struct sk_buff *skb);
|
||||
|
@ -119,7 +119,7 @@ Signed-off-by: Jonas Gorski <jogo@openwrt.org>
|
|||
static void ip6_link_failure(struct sk_buff *skb);
|
||||
static void ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk,
|
||||
struct sk_buff *skb, u32 mtu,
|
||||
@@ -317,6 +319,18 @@ static const struct rt6_info ip6_prohibi
|
||||
@@ -316,6 +318,18 @@ static const struct rt6_info ip6_prohibi
|
||||
.rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP),
|
||||
};
|
||||
|
||||
|
@ -138,7 +138,7 @@ Signed-off-by: Jonas Gorski <jogo@openwrt.org>
|
|||
static const struct rt6_info ip6_blk_hole_entry_template = {
|
||||
.dst = {
|
||||
.__rcuref = RCUREF_INIT(1),
|
||||
@@ -1037,6 +1051,7 @@ static const int fib6_prop[RTN_MAX + 1]
|
||||
@@ -1051,6 +1065,7 @@ static const int fib6_prop[RTN_MAX + 1]
|
||||
[RTN_BLACKHOLE] = -EINVAL,
|
||||
[RTN_UNREACHABLE] = -EHOSTUNREACH,
|
||||
[RTN_PROHIBIT] = -EACCES,
|
||||
|
@ -146,7 +146,7 @@ Signed-off-by: Jonas Gorski <jogo@openwrt.org>
|
|||
[RTN_THROW] = -EAGAIN,
|
||||
[RTN_NAT] = -EINVAL,
|
||||
[RTN_XRESOLVE] = -EINVAL,
|
||||
@@ -1072,6 +1087,10 @@ static void ip6_rt_init_dst_reject(struc
|
||||
@@ -1086,6 +1101,10 @@ static void ip6_rt_init_dst_reject(struc
|
||||
rt->dst.output = ip6_pkt_prohibit_out;
|
||||
rt->dst.input = ip6_pkt_prohibit;
|
||||
break;
|
||||
|
@ -157,7 +157,7 @@ Signed-off-by: Jonas Gorski <jogo@openwrt.org>
|
|||
case RTN_THROW:
|
||||
case RTN_UNREACHABLE:
|
||||
default:
|
||||
@@ -4539,6 +4558,17 @@ static int ip6_pkt_prohibit_out(struct n
|
||||
@@ -4555,6 +4574,17 @@ static int ip6_pkt_prohibit_out(struct n
|
||||
return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_OUTNOROUTES);
|
||||
}
|
||||
|
||||
|
@ -175,7 +175,7 @@ Signed-off-by: Jonas Gorski <jogo@openwrt.org>
|
|||
/*
|
||||
* Allocate a dst for local (unicast / anycast) address.
|
||||
*/
|
||||
@@ -5030,7 +5060,8 @@ static int rtm_to_fib6_config(struct sk_
|
||||
@@ -5046,7 +5076,8 @@ static int rtm_to_fib6_config(struct sk_
|
||||
if (rtm->rtm_type == RTN_UNREACHABLE ||
|
||||
rtm->rtm_type == RTN_BLACKHOLE ||
|
||||
rtm->rtm_type == RTN_PROHIBIT ||
|
||||
|
@ -185,7 +185,7 @@ Signed-off-by: Jonas Gorski <jogo@openwrt.org>
|
|||
cfg->fc_flags |= RTF_REJECT;
|
||||
|
||||
if (rtm->rtm_type == RTN_LOCAL)
|
||||
@@ -6277,6 +6308,8 @@ static int ip6_route_dev_notify(struct n
|
||||
@@ -6306,6 +6337,8 @@ static int ip6_route_dev_notify(struct n
|
||||
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
|
||||
net->ipv6.ip6_prohibit_entry->dst.dev = dev;
|
||||
net->ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(dev);
|
||||
|
@ -194,7 +194,7 @@ Signed-off-by: Jonas Gorski <jogo@openwrt.org>
|
|||
net->ipv6.ip6_blk_hole_entry->dst.dev = dev;
|
||||
net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev);
|
||||
#endif
|
||||
@@ -6288,6 +6321,7 @@ static int ip6_route_dev_notify(struct n
|
||||
@@ -6317,6 +6350,7 @@ static int ip6_route_dev_notify(struct n
|
||||
in6_dev_put_clear(&net->ipv6.ip6_null_entry->rt6i_idev);
|
||||
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
|
||||
in6_dev_put_clear(&net->ipv6.ip6_prohibit_entry->rt6i_idev);
|
||||
|
@ -202,7 +202,7 @@ Signed-off-by: Jonas Gorski <jogo@openwrt.org>
|
|||
in6_dev_put_clear(&net->ipv6.ip6_blk_hole_entry->rt6i_idev);
|
||||
#endif
|
||||
}
|
||||
@@ -6488,6 +6522,8 @@ static int __net_init ip6_route_net_init
|
||||
@@ -6512,6 +6546,8 @@ static int __net_init ip6_route_net_init
|
||||
|
||||
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
|
||||
net->ipv6.fib6_has_custom_rules = false;
|
||||
|
@ -211,7 +211,7 @@ Signed-off-by: Jonas Gorski <jogo@openwrt.org>
|
|||
net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template,
|
||||
sizeof(*net->ipv6.ip6_prohibit_entry),
|
||||
GFP_KERNEL);
|
||||
@@ -6498,11 +6534,21 @@ static int __net_init ip6_route_net_init
|
||||
@@ -6522,11 +6558,21 @@ static int __net_init ip6_route_net_init
|
||||
ip6_template_metrics, true);
|
||||
INIT_LIST_HEAD(&net->ipv6.ip6_prohibit_entry->dst.rt_uncached);
|
||||
|
||||
|
@ -234,7 +234,7 @@ Signed-off-by: Jonas Gorski <jogo@openwrt.org>
|
|||
net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops;
|
||||
dst_init_metrics(&net->ipv6.ip6_blk_hole_entry->dst,
|
||||
ip6_template_metrics, true);
|
||||
@@ -6529,6 +6575,8 @@ out:
|
||||
@@ -6553,6 +6599,8 @@ out:
|
||||
return ret;
|
||||
|
||||
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
|
||||
|
@ -243,7 +243,7 @@ Signed-off-by: Jonas Gorski <jogo@openwrt.org>
|
|||
out_ip6_prohibit_entry:
|
||||
kfree(net->ipv6.ip6_prohibit_entry);
|
||||
out_ip6_null_entry:
|
||||
@@ -6548,6 +6596,7 @@ static void __net_exit ip6_route_net_exi
|
||||
@@ -6572,6 +6620,7 @@ static void __net_exit ip6_route_net_exi
|
||||
kfree(net->ipv6.ip6_null_entry);
|
||||
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
|
||||
kfree(net->ipv6.ip6_prohibit_entry);
|
||||
|
@ -251,7 +251,7 @@ Signed-off-by: Jonas Gorski <jogo@openwrt.org>
|
|||
kfree(net->ipv6.ip6_blk_hole_entry);
|
||||
#endif
|
||||
dst_entries_destroy(&net->ipv6.ip6_dst_ops);
|
||||
@@ -6631,6 +6680,9 @@ void __init ip6_route_init_special_entri
|
||||
@@ -6655,6 +6704,9 @@ void __init ip6_route_init_special_entri
|
||||
init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
|
||||
init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev;
|
||||
init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
|
||||
|
|
|
@ -17,7 +17,7 @@ Signed-off-by: Jonas Gorski <jogo@openwrt.org>
|
|||
|
||||
--- a/include/uapi/linux/fib_rules.h
|
||||
+++ b/include/uapi/linux/fib_rules.h
|
||||
@@ -89,6 +89,8 @@ enum {
|
||||
@@ -90,6 +90,8 @@ enum {
|
||||
__FR_ACT_MAX,
|
||||
};
|
||||
|
||||
|
@ -28,7 +28,7 @@ Signed-off-by: Jonas Gorski <jogo@openwrt.org>
|
|||
#endif
|
||||
--- a/include/uapi/linux/icmpv6.h
|
||||
+++ b/include/uapi/linux/icmpv6.h
|
||||
@@ -126,6 +126,8 @@ struct icmp6hdr {
|
||||
@@ -127,6 +127,8 @@ struct icmp6hdr {
|
||||
#define ICMPV6_POLICY_FAIL 5
|
||||
#define ICMPV6_REJECT_ROUTE 6
|
||||
|
||||
|
|
|
@ -0,0 +1,129 @@
|
|||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Thu, 15 Aug 2024 21:15:13 +0200
|
||||
Subject: [PATCH] net: remove NETIF_F_GSO_FRAGLIST from NETIF_F_GSO_SOFTWARE
|
||||
|
||||
Several drivers set NETIF_F_GSO_SOFTWARE, but mangle fraglist GRO packets
|
||||
in a way that they can't be properly segmented anymore.
|
||||
In order to properly deal with this, remove fraglist GSO from
|
||||
NETIF_F_GSO_SOFTWARE and switch to NETIF_F_GSO_SOFTWARE_ALL (which includes
|
||||
fraglist GSO) in places where it's safe to add.
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
|
||||
--- a/drivers/net/dummy.c
|
||||
+++ b/drivers/net/dummy.c
|
||||
@@ -111,7 +111,7 @@ static void dummy_setup(struct net_devic
|
||||
dev->priv_flags |= IFF_LIVE_ADDR_CHANGE | IFF_NO_QUEUE;
|
||||
dev->lltx = true;
|
||||
dev->features |= NETIF_F_SG | NETIF_F_FRAGLIST;
|
||||
- dev->features |= NETIF_F_GSO_SOFTWARE;
|
||||
+ dev->features |= NETIF_F_GSO_SOFTWARE_ALL;
|
||||
dev->features |= NETIF_F_HW_CSUM | NETIF_F_HIGHDMA;
|
||||
dev->features |= NETIF_F_GSO_ENCAP_ALL;
|
||||
dev->hw_features |= dev->features;
|
||||
--- a/drivers/net/loopback.c
|
||||
+++ b/drivers/net/loopback.c
|
||||
@@ -174,7 +174,7 @@ static void gen_lo_setup(struct net_devi
|
||||
dev->lltx = true;
|
||||
dev->netns_local = true;
|
||||
netif_keep_dst(dev);
|
||||
- dev->hw_features = NETIF_F_GSO_SOFTWARE;
|
||||
+ dev->hw_features = NETIF_F_GSO_SOFTWARE_ALL;
|
||||
dev->features = NETIF_F_SG | NETIF_F_FRAGLIST
|
||||
| NETIF_F_GSO_SOFTWARE
|
||||
| NETIF_F_HW_CSUM
|
||||
--- a/drivers/net/macvlan.c
|
||||
+++ b/drivers/net/macvlan.c
|
||||
@@ -897,7 +897,7 @@ static int macvlan_hwtstamp_set(struct n
|
||||
static struct lock_class_key macvlan_netdev_addr_lock_key;
|
||||
|
||||
#define ALWAYS_ON_OFFLOADS \
|
||||
- (NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_GSO_SOFTWARE | \
|
||||
+ (NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_GSO_SOFTWARE_ALL | \
|
||||
NETIF_F_GSO_ROBUST | NETIF_F_GSO_ENCAP_ALL)
|
||||
|
||||
#define ALWAYS_ON_FEATURES ALWAYS_ON_OFFLOADS
|
||||
--- a/include/linux/netdev_features.h
|
||||
+++ b/include/linux/netdev_features.h
|
||||
@@ -211,13 +211,14 @@ static inline int find_next_netdev_featu
|
||||
|
||||
/* List of features with software fallbacks. */
|
||||
#define NETIF_F_GSO_SOFTWARE (NETIF_F_ALL_TSO | NETIF_F_GSO_SCTP | \
|
||||
- NETIF_F_GSO_UDP_L4 | NETIF_F_GSO_FRAGLIST)
|
||||
+ NETIF_F_GSO_UDP_L4)
|
||||
+#define NETIF_F_GSO_SOFTWARE_ALL (NETIF_F_GSO_SOFTWARE | NETIF_F_GSO_FRAGLIST)
|
||||
|
||||
/*
|
||||
* If one device supports one of these features, then enable them
|
||||
* for all in netdev_increment_features.
|
||||
*/
|
||||
-#define NETIF_F_ONE_FOR_ALL (NETIF_F_GSO_SOFTWARE | NETIF_F_GSO_ROBUST | \
|
||||
+#define NETIF_F_ONE_FOR_ALL (NETIF_F_GSO_SOFTWARE_ALL | NETIF_F_GSO_ROBUST | \
|
||||
NETIF_F_SG | NETIF_F_HIGHDMA | \
|
||||
NETIF_F_FRAGLIST | NETIF_F_VLAN_CHALLENGED)
|
||||
|
||||
--- a/net/8021q/vlan.h
|
||||
+++ b/net/8021q/vlan.h
|
||||
@@ -108,7 +108,7 @@ static inline netdev_features_t vlan_tnl
|
||||
netdev_features_t ret;
|
||||
|
||||
ret = real_dev->hw_enc_features &
|
||||
- (NETIF_F_CSUM_MASK | NETIF_F_GSO_SOFTWARE |
|
||||
+ (NETIF_F_CSUM_MASK | NETIF_F_GSO_SOFTWARE_ALL |
|
||||
NETIF_F_GSO_ENCAP_ALL);
|
||||
|
||||
if ((ret & NETIF_F_GSO_ENCAP_ALL) && (ret & NETIF_F_CSUM_MASK))
|
||||
--- a/net/8021q/vlan_dev.c
|
||||
+++ b/net/8021q/vlan_dev.c
|
||||
@@ -561,7 +561,7 @@ static int vlan_dev_init(struct net_devi
|
||||
dev->state |= (1 << __LINK_STATE_NOCARRIER);
|
||||
|
||||
dev->hw_features = NETIF_F_HW_CSUM | NETIF_F_SG |
|
||||
- NETIF_F_FRAGLIST | NETIF_F_GSO_SOFTWARE |
|
||||
+ NETIF_F_FRAGLIST | NETIF_F_GSO_SOFTWARE_ALL |
|
||||
NETIF_F_GSO_ENCAP_ALL |
|
||||
NETIF_F_HIGHDMA | NETIF_F_SCTP_CRC |
|
||||
NETIF_F_FCOE_CRC | NETIF_F_FSO;
|
||||
@@ -657,7 +657,7 @@ static netdev_features_t vlan_dev_fix_fe
|
||||
if (lower_features & (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))
|
||||
lower_features |= NETIF_F_HW_CSUM;
|
||||
features = netdev_intersect_features(features, lower_features);
|
||||
- features |= old_features & (NETIF_F_SOFT_FEATURES | NETIF_F_GSO_SOFTWARE);
|
||||
+ features |= old_features & (NETIF_F_SOFT_FEATURES | NETIF_F_GSO_SOFTWARE_ALL);
|
||||
|
||||
return features;
|
||||
}
|
||||
--- a/net/core/sock.c
|
||||
+++ b/net/core/sock.c
|
||||
@@ -2525,7 +2525,7 @@ void sk_setup_caps(struct sock *sk, stru
|
||||
if (sk_is_tcp(sk))
|
||||
sk->sk_route_caps |= NETIF_F_GSO;
|
||||
if (sk->sk_route_caps & NETIF_F_GSO)
|
||||
- sk->sk_route_caps |= NETIF_F_GSO_SOFTWARE;
|
||||
+ sk->sk_route_caps |= NETIF_F_GSO_SOFTWARE_ALL;
|
||||
if (unlikely(sk->sk_gso_disabled))
|
||||
sk->sk_route_caps &= ~NETIF_F_GSO_MASK;
|
||||
if (sk_can_gso(sk)) {
|
||||
--- a/net/mac80211/ieee80211_i.h
|
||||
+++ b/net/mac80211/ieee80211_i.h
|
||||
@@ -2012,7 +2012,7 @@ void ieee80211_color_collision_detection
|
||||
/* interface handling */
|
||||
#define MAC80211_SUPPORTED_FEATURES_TX (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | \
|
||||
NETIF_F_HW_CSUM | NETIF_F_SG | \
|
||||
- NETIF_F_HIGHDMA | NETIF_F_GSO_SOFTWARE | \
|
||||
+ NETIF_F_HIGHDMA | NETIF_F_GSO_SOFTWARE_ALL | \
|
||||
NETIF_F_HW_TC)
|
||||
#define MAC80211_SUPPORTED_FEATURES_RX (NETIF_F_RXCSUM)
|
||||
#define MAC80211_SUPPORTED_FEATURES (MAC80211_SUPPORTED_FEATURES_TX | \
|
||||
--- a/net/openvswitch/vport-internal_dev.c
|
||||
+++ b/net/openvswitch/vport-internal_dev.c
|
||||
@@ -109,7 +109,7 @@ static void do_setup(struct net_device *
|
||||
netdev->rtnl_link_ops = &internal_dev_link_ops;
|
||||
|
||||
netdev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA |
|
||||
- NETIF_F_HW_CSUM | NETIF_F_GSO_SOFTWARE |
|
||||
+ NETIF_F_HW_CSUM | NETIF_F_GSO_SOFTWARE_ALL |
|
||||
NETIF_F_GSO_ENCAP_ALL;
|
||||
|
||||
netdev->vlan_features = netdev->features;
|
|
@ -0,0 +1,110 @@
|
|||
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Thu, 25 Jan 2018 12:58:55 +0100
|
||||
Subject: [PATCH] netfilter: nft_flow_offload: handle netdevice events from
|
||||
nf_flow_table
|
||||
|
||||
Move the code that deals with device events to the core.
|
||||
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
---
|
||||
|
||||
--- a/net/netfilter/nf_flow_table_core.c
|
||||
+++ b/net/netfilter/nf_flow_table_core.c
|
||||
@@ -658,6 +658,23 @@ static struct pernet_operations nf_flow_
|
||||
.exit_batch = nf_flow_table_pernet_exit,
|
||||
};
|
||||
|
||||
+static int nf_flow_table_netdev_event(struct notifier_block *this,
|
||||
+ unsigned long event, void *ptr)
|
||||
+{
|
||||
+ struct net_device *dev = netdev_notifier_info_to_dev(ptr);
|
||||
+
|
||||
+ if (event != NETDEV_DOWN)
|
||||
+ return NOTIFY_DONE;
|
||||
+
|
||||
+ nf_flow_table_cleanup(dev);
|
||||
+
|
||||
+ return NOTIFY_DONE;
|
||||
+}
|
||||
+
|
||||
+static struct notifier_block flow_offload_netdev_notifier = {
|
||||
+ .notifier_call = nf_flow_table_netdev_event,
|
||||
+};
|
||||
+
|
||||
static int __init nf_flow_table_module_init(void)
|
||||
{
|
||||
int ret;
|
||||
@@ -674,9 +691,14 @@ static int __init nf_flow_table_module_i
|
||||
if (ret)
|
||||
goto out_bpf;
|
||||
|
||||
+ ret = register_netdevice_notifier(&flow_offload_netdev_notifier);
|
||||
+ if (ret)
|
||||
+ goto out_offload_init;
|
||||
+
|
||||
return 0;
|
||||
|
||||
out_bpf:
|
||||
+out_offload_init:
|
||||
nf_flow_table_offload_exit();
|
||||
out_offload:
|
||||
unregister_pernet_subsys(&nf_flow_table_net_ops);
|
||||
@@ -685,6 +707,7 @@ out_offload:
|
||||
|
||||
static void __exit nf_flow_table_module_exit(void)
|
||||
{
|
||||
+ unregister_netdevice_notifier(&flow_offload_netdev_notifier);
|
||||
nf_flow_table_offload_exit();
|
||||
unregister_pernet_subsys(&nf_flow_table_net_ops);
|
||||
}
|
||||
--- a/net/netfilter/nft_flow_offload.c
|
||||
+++ b/net/netfilter/nft_flow_offload.c
|
||||
@@ -481,47 +481,14 @@ static struct nft_expr_type nft_flow_off
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
-static int flow_offload_netdev_event(struct notifier_block *this,
|
||||
- unsigned long event, void *ptr)
|
||||
-{
|
||||
- struct net_device *dev = netdev_notifier_info_to_dev(ptr);
|
||||
-
|
||||
- if (event != NETDEV_DOWN)
|
||||
- return NOTIFY_DONE;
|
||||
-
|
||||
- nf_flow_table_cleanup(dev);
|
||||
-
|
||||
- return NOTIFY_DONE;
|
||||
-}
|
||||
-
|
||||
-static struct notifier_block flow_offload_netdev_notifier = {
|
||||
- .notifier_call = flow_offload_netdev_event,
|
||||
-};
|
||||
-
|
||||
static int __init nft_flow_offload_module_init(void)
|
||||
{
|
||||
- int err;
|
||||
-
|
||||
- err = register_netdevice_notifier(&flow_offload_netdev_notifier);
|
||||
- if (err)
|
||||
- goto err;
|
||||
-
|
||||
- err = nft_register_expr(&nft_flow_offload_type);
|
||||
- if (err < 0)
|
||||
- goto register_expr;
|
||||
-
|
||||
- return 0;
|
||||
-
|
||||
-register_expr:
|
||||
- unregister_netdevice_notifier(&flow_offload_netdev_notifier);
|
||||
-err:
|
||||
- return err;
|
||||
+ return nft_register_expr(&nft_flow_offload_type);
|
||||
}
|
||||
|
||||
static void __exit nft_flow_offload_module_exit(void)
|
||||
{
|
||||
nft_unregister_expr(&nft_flow_offload_type);
|
||||
- unregister_netdevice_notifier(&flow_offload_netdev_notifier);
|
||||
}
|
||||
|
||||
module_init(nft_flow_offload_module_init);
|
|
@ -18,7 +18,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
|
||||
--- a/net/netfilter/nf_tables_api.c
|
||||
+++ b/net/netfilter/nf_tables_api.c
|
||||
@@ -8268,7 +8268,7 @@ static int nft_register_flowtable_net_ho
|
||||
@@ -8607,7 +8607,7 @@ static int nft_register_flowtable_net_ho
|
||||
err = flowtable->data.type->setup(&flowtable->data,
|
||||
hook->ops.dev,
|
||||
FLOW_BLOCK_BIND);
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Mon, 21 Mar 2022 20:39:59 +0100
|
||||
Subject: [PATCH] net: ethernet: mtk_eth_soc: enable threaded NAPI
|
||||
|
||||
This can improve performance under load by ensuring that NAPI processing is
|
||||
not pinned on CPU 0.
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
||||
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
||||
@@ -5041,6 +5041,8 @@ static int mtk_probe(struct platform_dev
|
||||
dev_err(eth->dev, "failed to allocated dummy device\n");
|
||||
goto err_unreg_netdev;
|
||||
}
|
||||
+ eth->dummy_dev->threaded = 1;
|
||||
+ strcpy(eth->dummy_dev->name, "mtk_eth");
|
||||
netif_napi_add(eth->dummy_dev, ð->tx_napi, mtk_napi_tx);
|
||||
netif_napi_add(eth->dummy_dev, ð->rx_napi, mtk_napi_rx);
|
||||
|
|
@ -11,7 +11,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
|
|||
|
||||
--- a/drivers/net/phy/phy_device.c
|
||||
+++ b/drivers/net/phy/phy_device.c
|
||||
@@ -1908,6 +1908,9 @@ void phy_detach(struct phy_device *phyde
|
||||
@@ -1986,6 +1986,9 @@ void phy_detach(struct phy_device *phyde
|
||||
if (phydev->devlink)
|
||||
device_link_del(phydev->devlink);
|
||||
|
||||
|
@ -23,7 +23,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
|
|||
sysfs_remove_link(&dev->dev.kobj, "phydev");
|
||||
--- a/include/linux/phy.h
|
||||
+++ b/include/linux/phy.h
|
||||
@@ -976,6 +976,12 @@ struct phy_driver {
|
||||
@@ -999,6 +999,12 @@ struct phy_driver {
|
||||
/** @handle_interrupt: Override default interrupt handling */
|
||||
irqreturn_t (*handle_interrupt)(struct phy_device *phydev);
|
||||
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
From 4e432e530db0056450fbc4a3cee793f16adc39a7 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Golle <daniel@makrotopia.org>
|
||||
Date: Tue, 8 Oct 2024 23:58:41 +0100
|
||||
Subject: [PATCH] net: phy: populate host_interfaces when attaching PHY
|
||||
|
||||
Use bitmask of interfaces supported by the MAC for the PHY to choose
|
||||
from if the declared interface mode is among those using a single pair
|
||||
of SerDes lanes.
|
||||
This will allow 2500Base-T PHYs to switch to SGMII on most hosts, which
|
||||
results in half-duplex being supported in case the MAC supports them.
|
||||
Without this change, 2500Base-T PHYs will always operate in 2500Base-X
|
||||
mode with rate-matching, which is not only wasteful in terms of energy
|
||||
consumption, but also limits the supported interface modes to
|
||||
full-duplex only.
|
||||
|
||||
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
---
|
||||
drivers/net/phy/phylink.c | 21 ++++++++++++++++++++-
|
||||
1 file changed, 20 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/phy/phylink.c
|
||||
+++ b/drivers/net/phy/phylink.c
|
||||
@@ -2086,7 +2086,7 @@ int phylink_fwnode_phy_connect(struct ph
|
||||
{
|
||||
struct fwnode_handle *phy_fwnode;
|
||||
struct phy_device *phy_dev;
|
||||
- int ret;
|
||||
+ int i, ret;
|
||||
|
||||
/* Fixed links and 802.3z are handled without needing a PHY */
|
||||
if (pl->cfg_link_an_mode == MLO_AN_FIXED ||
|
||||
@@ -2116,6 +2116,25 @@ int phylink_fwnode_phy_connect(struct ph
|
||||
if (pl->config->mac_requires_rxc)
|
||||
flags |= PHY_F_RXC_ALWAYS_ON;
|
||||
|
||||
+ /* Assume single-lane SerDes interface modes share the same
|
||||
+ * lanes and allow the PHY to switch to slower also supported modes
|
||||
+ */
|
||||
+ for (i = ARRAY_SIZE(phylink_sfp_interface_preference) - 1; i >= 0; i--) {
|
||||
+ /* skip unsupported modes */
|
||||
+ if (!test_bit(phylink_sfp_interface_preference[i], pl->config->supported_interfaces))
|
||||
+ continue;
|
||||
+
|
||||
+ __set_bit(phylink_sfp_interface_preference[i], phy_dev->host_interfaces);
|
||||
+
|
||||
+ /* skip all faster modes */
|
||||
+ if (phylink_sfp_interface_preference[i] == pl->link_interface)
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (test_bit(pl->link_interface, phylink_sfp_interfaces))
|
||||
+ phy_interface_and(phy_dev->host_interfaces, phylink_sfp_interfaces,
|
||||
+ pl->config->supported_interfaces);
|
||||
+
|
||||
ret = phy_attach_direct(pl->netdev, phy_dev, flags,
|
||||
pl->link_interface);
|
||||
phy_device_free(phy_dev);
|
|
@ -106,7 +106,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
|
||||
--- a/include/uapi/linux/if_link.h
|
||||
+++ b/include/uapi/linux/if_link.h
|
||||
@@ -571,6 +571,7 @@ enum {
|
||||
@@ -1094,6 +1094,7 @@ enum {
|
||||
IFLA_BRPORT_MCAST_MAX_GROUPS,
|
||||
IFLA_BRPORT_NEIGH_VLAN_SUPPRESS,
|
||||
IFLA_BRPORT_BACKUP_NHID,
|
||||
|
@ -152,7 +152,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
(!(p->flags & BR_PORT_LOCKED) || !(p->flags & BR_LEARNING))) {
|
||||
--- a/net/core/rtnetlink.c
|
||||
+++ b/net/core/rtnetlink.c
|
||||
@@ -61,7 +61,7 @@
|
||||
@@ -62,7 +62,7 @@
|
||||
#include "dev.h"
|
||||
|
||||
#define RTNL_MAX_TYPE 50
|
||||
|
@ -161,7 +161,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
|
||||
struct rtnl_link {
|
||||
rtnl_doit_func doit;
|
||||
@@ -4949,7 +4949,9 @@ int ndo_dflt_bridge_getlink(struct sk_bu
|
||||
@@ -5009,7 +5009,9 @@ int ndo_dflt_bridge_getlink(struct sk_bu
|
||||
brport_nla_put_flag(skb, flags, mask,
|
||||
IFLA_BRPORT_MCAST_FLOOD, BR_MCAST_FLOOD) ||
|
||||
brport_nla_put_flag(skb, flags, mask,
|
||||
|
|
|
@ -16,7 +16,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
|||
|
||||
--- a/drivers/net/dsa/qca/qca8k-8xxx.c
|
||||
+++ b/drivers/net/dsa/qca/qca8k-8xxx.c
|
||||
@@ -2012,6 +2012,8 @@ static const struct dsa_switch_ops qca8k
|
||||
@@ -2031,6 +2031,8 @@ static const struct dsa_switch_ops qca8k
|
||||
.port_fdb_add = qca8k_port_fdb_add,
|
||||
.port_fdb_del = qca8k_port_fdb_del,
|
||||
.port_fdb_dump = qca8k_port_fdb_dump,
|
||||
|
@ -27,7 +27,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
|||
.port_mirror_add = qca8k_port_mirror_add,
|
||||
--- a/drivers/net/dsa/qca/qca8k-common.c
|
||||
+++ b/drivers/net/dsa/qca/qca8k-common.c
|
||||
@@ -1215,6 +1215,42 @@ int qca8k_port_lag_leave(struct dsa_swit
|
||||
@@ -1234,6 +1234,42 @@ int qca8k_port_lag_leave(struct dsa_swit
|
||||
return qca8k_lag_refresh_portmap(ds, port, lag, true);
|
||||
}
|
||||
|
||||
|
@ -72,7 +72,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
|||
u32 val;
|
||||
--- a/drivers/net/dsa/qca/qca8k.h
|
||||
+++ b/drivers/net/dsa/qca/qca8k.h
|
||||
@@ -590,5 +590,11 @@ int qca8k_port_lag_join(struct dsa_switc
|
||||
@@ -592,5 +592,11 @@ int qca8k_port_lag_join(struct dsa_switc
|
||||
struct netlink_ext_ack *extack);
|
||||
int qca8k_port_lag_leave(struct dsa_switch *ds, int port,
|
||||
struct dsa_lag lag);
|
||||
|
|
|
@ -14,7 +14,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
|||
|
||||
--- a/drivers/net/dsa/qca/qca8k-8xxx.c
|
||||
+++ b/drivers/net/dsa/qca/qca8k-8xxx.c
|
||||
@@ -1901,15 +1901,12 @@ qca8k_setup(struct dsa_switch *ds)
|
||||
@@ -1913,15 +1913,12 @@ qca8k_setup(struct dsa_switch *ds)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,158 @@
|
|||
From b2d6ebf2f92f8695c83fa6979f4ab579c588df76 Mon Sep 17 00:00:00 2001
|
||||
From: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Date: Tue, 20 Jun 2023 07:57:38 +0200
|
||||
Subject: [PATCH 4/4] net: dsa: qca8k: add support for port_change_master
|
||||
|
||||
Add support for port_change_master to permit assigning an alternative
|
||||
CPU port if the switch have both CPU port connected or create a LAG on
|
||||
both CPU port and assign the LAG as DSA master.
|
||||
|
||||
On port change master request, we check if the master is a LAG.
|
||||
With LAG we compose the cpu_port_mask with the CPU port in the LAG, if
|
||||
master is a simple dsa_port, we derive the index.
|
||||
|
||||
Finally we apply the new cpu_port_mask to the LOOKUP MEMBER to permit
|
||||
the port to receive packet by the new CPU port setup for the port and we
|
||||
refresh the CPU ports LOOKUP MEMBER configuration to reflect the new
|
||||
user port state.
|
||||
|
||||
port_lag_join/leave is updated to refresh the user ports if we detect
|
||||
that the LAG is a DSA master and we have user port using it as a master.
|
||||
|
||||
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
---
|
||||
drivers/net/dsa/qca/qca8k-8xxx.c | 116 ++++++++++++++++++++++++++++++-
|
||||
1 file changed, 114 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/qca/qca8k-8xxx.c
|
||||
+++ b/drivers/net/dsa/qca/qca8k-8xxx.c
|
||||
@@ -1750,6 +1750,117 @@ qca8k_get_tag_protocol(struct dsa_switch
|
||||
return DSA_TAG_PROTO_QCA;
|
||||
}
|
||||
|
||||
+static int qca8k_port_change_master(struct dsa_switch *ds, int port,
|
||||
+ struct net_device *master,
|
||||
+ struct netlink_ext_ack *extack)
|
||||
+{
|
||||
+ struct dsa_switch_tree *dst = ds->dst;
|
||||
+ struct qca8k_priv *priv = ds->priv;
|
||||
+ u8 cpu_port_mask = 0;
|
||||
+ struct dsa_port *dp;
|
||||
+ u32 val;
|
||||
+ int ret;
|
||||
+
|
||||
+ /* With LAG of CPU port, compose the mask for port LOOKUP MEMBER */
|
||||
+ if (netif_is_lag_master(master)) {
|
||||
+ struct dsa_lag *lag;
|
||||
+ int id;
|
||||
+
|
||||
+ id = dsa_lag_id(dst, master);
|
||||
+ lag = dsa_lag_by_id(dst, id);
|
||||
+
|
||||
+ dsa_lag_foreach_port(dp, dst, lag)
|
||||
+ if (dsa_port_is_cpu(dp))
|
||||
+ cpu_port_mask |= BIT(dp->index);
|
||||
+ } else {
|
||||
+ dp = master->dsa_ptr;
|
||||
+ cpu_port_mask |= BIT(dp->index);
|
||||
+ }
|
||||
+
|
||||
+ /* Connect port to new cpu port */
|
||||
+ ret = regmap_read(priv->regmap, QCA8K_PORT_LOOKUP_CTRL(port), &val);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* Reset connected CPU port in port LOOKUP MEMBER */
|
||||
+ val &= ~dsa_cpu_ports(ds);
|
||||
+ /* Assign the new CPU port in port LOOKUP MEMBER */
|
||||
+ val |= cpu_port_mask;
|
||||
+
|
||||
+ ret = regmap_update_bits(priv->regmap, QCA8K_PORT_LOOKUP_CTRL(port),
|
||||
+ QCA8K_PORT_LOOKUP_MEMBER,
|
||||
+ val);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* Refresh CPU port LOOKUP MEMBER with new port */
|
||||
+ dsa_tree_for_each_cpu_port(dp, ds->dst) {
|
||||
+ u32 reg = QCA8K_PORT_LOOKUP_CTRL(dp->index);
|
||||
+
|
||||
+ /* If CPU port in mask assign port, else remove port */
|
||||
+ if (BIT(dp->index) & cpu_port_mask)
|
||||
+ ret = regmap_set_bits(priv->regmap, reg, BIT(port));
|
||||
+ else
|
||||
+ ret = regmap_clear_bits(priv->regmap, reg, BIT(port));
|
||||
+
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int qca8k_port_lag_refresh_user_ports(struct dsa_switch *ds,
|
||||
+ struct dsa_lag lag)
|
||||
+{
|
||||
+ struct net_device *lag_dev = lag.dev;
|
||||
+ struct dsa_port *dp;
|
||||
+ int ret;
|
||||
+
|
||||
+ /* Ignore if LAG is not a DSA master */
|
||||
+ if (!netif_is_lag_master(lag_dev))
|
||||
+ return 0;
|
||||
+
|
||||
+ dsa_switch_for_each_user_port(dp, ds) {
|
||||
+ /* Skip if assigned master is not the LAG */
|
||||
+ if (dsa_port_to_conduit(dp) != lag_dev)
|
||||
+ continue;
|
||||
+
|
||||
+ ret = qca8k_port_change_master(ds, dp->index,
|
||||
+ lag_dev, NULL);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int qca8xxx_port_lag_join(struct dsa_switch *ds, int port,
|
||||
+ struct dsa_lag lag,
|
||||
+ struct netdev_lag_upper_info *info,
|
||||
+ struct netlink_ext_ack *extack)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = qca8k_port_lag_join(ds, port, lag, info, extack);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ return qca8k_port_lag_refresh_user_ports(ds, lag);
|
||||
+}
|
||||
+
|
||||
+static int qca8xxx_port_lag_leave(struct dsa_switch *ds, int port,
|
||||
+ struct dsa_lag lag)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = qca8k_port_lag_leave(ds, port, lag);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ return qca8k_port_lag_refresh_user_ports(ds, lag);
|
||||
+}
|
||||
+
|
||||
static void
|
||||
qca8k_conduit_change(struct dsa_switch *ds, const struct net_device *conduit,
|
||||
bool operational)
|
||||
@@ -2039,8 +2150,9 @@ static const struct dsa_switch_ops qca8k
|
||||
.port_vlan_del = qca8k_port_vlan_del,
|
||||
.phylink_get_caps = qca8k_phylink_get_caps,
|
||||
.get_phy_flags = qca8k_get_phy_flags,
|
||||
- .port_lag_join = qca8k_port_lag_join,
|
||||
- .port_lag_leave = qca8k_port_lag_leave,
|
||||
+ .port_lag_join = qca8xxx_port_lag_join,
|
||||
+ .port_lag_leave = qca8xxx_port_lag_leave,
|
||||
+ .port_change_conduit = qca8k_port_change_master,
|
||||
.conduit_state_change = qca8k_conduit_change,
|
||||
.connect_tag_protocol = qca8k_connect_tag_protocol,
|
||||
};
|
|
@ -20,7 +20,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
|||
|
||||
--- a/drivers/net/dsa/qca/qca8k-8xxx.c
|
||||
+++ b/drivers/net/dsa/qca/qca8k-8xxx.c
|
||||
@@ -2010,6 +2010,12 @@ qca8k_setup(struct dsa_switch *ds)
|
||||
@@ -2022,6 +2022,12 @@ qca8k_setup(struct dsa_switch *ds)
|
||||
dev_err(priv->dev, "failed enabling QCA header mode on port %d", dp->index);
|
||||
return ret;
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
|||
}
|
||||
|
||||
/* Forward all unknown frames to CPU port for Linux processing */
|
||||
@@ -2039,11 +2045,6 @@ qca8k_setup(struct dsa_switch *ds)
|
||||
@@ -2051,11 +2057,6 @@ qca8k_setup(struct dsa_switch *ds)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -45,7 +45,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
|||
/* For port based vlans to work we need to set the
|
||||
* default egress vid
|
||||
*/
|
||||
@@ -2095,6 +2096,9 @@ qca8k_setup(struct dsa_switch *ds)
|
||||
@@ -2107,6 +2108,9 @@ qca8k_setup(struct dsa_switch *ds)
|
||||
/* Set max number of LAGs supported */
|
||||
ds->num_lag_ids = QCA8K_NUM_LAGS;
|
||||
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
From 3b5a603bf66236b956287909556fd7ad4904450c Mon Sep 17 00:00:00 2001
|
||||
From: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Date: Wed, 24 Jan 2024 19:38:01 +0100
|
||||
Subject: [PATCH 3/3] arm64: dts: qcom: ipq8074: add clock-frequency to MDIO
|
||||
node
|
||||
|
||||
Add clock-frequency to MDIO node to set the MDC rate to 6.25Mhz instead
|
||||
of using the default value of 390KHz from MDIO default divider.
|
||||
|
||||
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
---
|
||||
arch/arm64/boot/dts/qcom/ipq8074.dtsi | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
--- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi
|
||||
+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi
|
||||
@@ -275,6 +275,8 @@
|
||||
clocks = <&gcc GCC_MDIO_AHB_CLK>;
|
||||
clock-names = "gcc_mdio_ahb_clk";
|
||||
|
||||
+ clock-frequency = <6250000>;
|
||||
+
|
||||
status = "disabled";
|
||||
};
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
From 85cd45580f5e3b26068cccb7d6173f200e754dc0 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Golle <daniel@makrotopia.org>
|
||||
Date: Sun, 2 Apr 2023 23:56:16 +0100
|
||||
Subject: [PATCH 1/2] net: phy: realtek: use genphy_soft_reset for 2.5G PHYs
|
||||
|
||||
Some vendor bootloaders do weird things with those PHYs which result in
|
||||
link modes being reported wrongly. Start from a clean sheet by resetting
|
||||
the PHY.
|
||||
|
||||
Reported-by: Yevhen Kolomeiko <jarvis2709@gmail.com>
|
||||
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
---
|
||||
drivers/net/phy/realtek.c | 6 ++++++
|
||||
1 file changed, 6 insertions(+)
|
||||
|
||||
--- a/drivers/net/phy/realtek.c
|
||||
+++ b/drivers/net/phy/realtek.c
|
||||
@@ -1375,6 +1375,7 @@ static struct phy_driver realtek_drvs[]
|
||||
}, {
|
||||
.name = "RTL8226 2.5Gbps PHY",
|
||||
.match_phy_device = rtl8226_match_phy_device,
|
||||
+ .soft_reset = genphy_soft_reset,
|
||||
.get_features = rtl822x_get_features,
|
||||
.config_aneg = rtl822x_config_aneg,
|
||||
.read_status = rtl822x_read_status,
|
||||
@@ -1387,6 +1388,7 @@ static struct phy_driver realtek_drvs[]
|
||||
}, {
|
||||
PHY_ID_MATCH_EXACT(0x001cc840),
|
||||
.name = "RTL8226B_RTL8221B 2.5Gbps PHY",
|
||||
+ .soft_reset = genphy_soft_reset,
|
||||
.get_features = rtl822x_get_features,
|
||||
.config_aneg = rtl822x_config_aneg,
|
||||
.config_init = rtl822xb_config_init,
|
||||
@@ -1401,6 +1403,7 @@ static struct phy_driver realtek_drvs[]
|
||||
}, {
|
||||
PHY_ID_MATCH_EXACT(0x001cc838),
|
||||
.name = "RTL8226-CG 2.5Gbps PHY",
|
||||
+ .soft_reset = genphy_soft_reset,
|
||||
.get_features = rtl822x_get_features,
|
||||
.config_aneg = rtl822x_config_aneg,
|
||||
.read_status = rtl822x_read_status,
|
||||
@@ -1411,6 +1414,7 @@ static struct phy_driver realtek_drvs[]
|
||||
}, {
|
||||
PHY_ID_MATCH_EXACT(0x001cc848),
|
||||
.name = "RTL8226B-CG_RTL8221B-CG 2.5Gbps PHY",
|
||||
+ .soft_reset = genphy_soft_reset,
|
||||
.get_features = rtl822x_get_features,
|
||||
.config_aneg = rtl822x_config_aneg,
|
||||
.config_init = rtl822xb_config_init,
|
||||
@@ -1423,6 +1427,7 @@ static struct phy_driver realtek_drvs[]
|
||||
}, {
|
||||
.match_phy_device = rtl8221b_vb_cg_c22_match_phy_device,
|
||||
.name = "RTL8221B-VB-CG 2.5Gbps PHY (C22)",
|
||||
+ .soft_reset = genphy_soft_reset,
|
||||
.get_features = rtl822x_get_features,
|
||||
.config_aneg = rtl822x_config_aneg,
|
||||
.config_init = rtl822xb_config_init,
|
||||
@@ -1435,6 +1440,7 @@ static struct phy_driver realtek_drvs[]
|
||||
}, {
|
||||
.match_phy_device = rtl8221b_vb_cg_c45_match_phy_device,
|
||||
.name = "RTL8221B-VB-CG 2.5Gbps PHY (C45)",
|
||||
+ .soft_reset = genphy_soft_reset,
|
||||
.config_init = rtl822xb_config_init,
|
||||
.get_rate_matching = rtl822xb_get_rate_matching,
|
||||
.get_features = rtl822x_c45_get_features,
|
||||
@@ -1445,6 +1451,7 @@ static struct phy_driver realtek_drvs[]
|
||||
}, {
|
||||
.match_phy_device = rtl8221b_vn_cg_c22_match_phy_device,
|
||||
.name = "RTL8221B-VM-CG 2.5Gbps PHY (C22)",
|
||||
+ .soft_reset = genphy_soft_reset,
|
||||
.get_features = rtl822x_get_features,
|
||||
.config_aneg = rtl822x_config_aneg,
|
||||
.config_init = rtl822xb_config_init,
|
||||
@@ -1457,6 +1464,7 @@ static struct phy_driver realtek_drvs[]
|
||||
}, {
|
||||
.match_phy_device = rtl8221b_vn_cg_c45_match_phy_device,
|
||||
.name = "RTL8221B-VN-CG 2.5Gbps PHY (C45)",
|
||||
+ .soft_reset = genphy_soft_reset,
|
||||
.config_init = rtl822xb_config_init,
|
||||
.get_rate_matching = rtl822xb_get_rate_matching,
|
||||
.get_features = rtl822x_c45_get_features,
|
|
@ -0,0 +1,63 @@
|
|||
From d54ef6aea00e7a6ace439baade6ad0aa38ee4b04 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Golle <daniel@makrotopia.org>
|
||||
Date: Mon, 3 Apr 2023 01:21:57 +0300
|
||||
Subject: [PATCH 287/326] net: phy: realtek: disable SGMII in-band AN for 2.5G
|
||||
PHYs
|
||||
|
||||
MAC drivers don't use SGMII in-band autonegotiation unless told to do so
|
||||
in device tree using 'managed = "in-band-status"'. When using MDIO to
|
||||
access a PHY, in-band-status is unneeded as we have link-status via
|
||||
MDIO. Switch off SGMII in-band autonegotiation using magic values.
|
||||
|
||||
Reported-by: Chen Minqiang <ptpt52@gmail.com>
|
||||
Reported-by: Chukun Pan <amadeus@jmu.edu.cn>
|
||||
Reported-by: Yevhen Kolomeiko <jarvis2709@gmail.com>
|
||||
Tested-by: Yevhen Kolomeiko <jarvis2709@gmail.com>
|
||||
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
---
|
||||
drivers/net/phy/realtek.c | 27 +++++++++++++++++++++++++--
|
||||
1 file changed, 25 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/realtek.c
|
||||
+++ b/drivers/net/phy/realtek.c
|
||||
@@ -814,8 +814,8 @@ static int rtl822x_write_mmd(struct phy_
|
||||
static int rtl822xb_config_init(struct phy_device *phydev)
|
||||
{
|
||||
bool has_2500, has_sgmii;
|
||||
+ int ret, val;
|
||||
u16 mode;
|
||||
- int ret;
|
||||
|
||||
has_2500 = test_bit(PHY_INTERFACE_MODE_2500BASEX,
|
||||
phydev->host_interfaces) ||
|
||||
@@ -865,7 +865,29 @@ static int rtl822xb_config_init(struct p
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
- return phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x6f11, 0x8020);
|
||||
+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x6f11, 0x8020);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* Disable SGMII AN */
|
||||
+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x7588, 0x2);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x7589, 0x71d0);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x7587, 0x3);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, 0x7587,
|
||||
+ val, !(val & BIT(0)), 500, 100000, false);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
static int rtl822xb_get_rate_matching(struct phy_device *phydev,
|
|
@ -18,7 +18,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|||
|
||||
--- a/drivers/net/phy/realtek.c
|
||||
+++ b/drivers/net/phy/realtek.c
|
||||
@@ -765,9 +765,11 @@ static bool rtlgen_supports_2_5gbps(stru
|
||||
@@ -1092,9 +1092,11 @@ static bool rtlgen_supports_2_5gbps(stru
|
||||
{
|
||||
int val;
|
||||
|
||||
|
@ -31,5 +31,5 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|||
+ rtl821x_write_page(phydev, 0);
|
||||
+ mutex_unlock(&phydev->mdio.bus->mdio_lock);
|
||||
|
||||
return val >= 0 && val & RTL_SUPPORTS_2500FULL;
|
||||
return val >= 0 && val & MDIO_PMA_SPEED_2_5G;
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
From 9155098547fb1172d4fa536f3f6bc9d42f59d08c Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Golle <daniel@makrotopia.org>
|
||||
Date: Sat, 22 Apr 2023 03:26:01 +0100
|
||||
Subject: [PATCH] net: phy: realtek: setup ALDPS on RTL822x
|
||||
|
||||
Setup Link Down Power Saving Mode according the DTS property
|
||||
just like for RTL821x 1GE PHYs.
|
||||
|
||||
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
---
|
||||
drivers/net/phy/realtek.c | 11 +++++++++++
|
||||
1 file changed, 11 insertions(+)
|
||||
|
||||
--- a/drivers/net/phy/realtek.c
|
||||
+++ b/drivers/net/phy/realtek.c
|
||||
@@ -80,6 +80,10 @@
|
||||
|
||||
#define RTL822X_VND2_GANLPAR 0xa414
|
||||
|
||||
+#define RTL8221B_PHYCR1 0xa430
|
||||
+#define RTL8221B_PHYCR1_ALDPS_EN BIT(2)
|
||||
+#define RTL8221B_PHYCR1_ALDPS_XTAL_OFF_EN BIT(12)
|
||||
+
|
||||
#define RTL8366RB_POWER_SAVE 0x15
|
||||
#define RTL8366RB_POWER_SAVE_ON BIT(12)
|
||||
|
||||
@@ -1152,6 +1156,25 @@ static int rtl8251b_c45_match_phy_device
|
||||
return rtlgen_is_c45_match(phydev, RTL_8251B, true);
|
||||
}
|
||||
|
||||
+static int rtl822x_probe(struct phy_device *phydev)
|
||||
+{
|
||||
+ struct device *dev = &phydev->mdio.dev;
|
||||
+ int val;
|
||||
+
|
||||
+ val = phy_read_mmd(phydev, MDIO_MMD_VEND1, RTL8221B_PHYCR1);
|
||||
+ if (val < 0)
|
||||
+ return val;
|
||||
+
|
||||
+ if (of_property_read_bool(dev->of_node, "realtek,aldps-enable"))
|
||||
+ val |= RTL8221B_PHYCR1_ALDPS_EN | RTL8221B_PHYCR1_ALDPS_XTAL_OFF_EN;
|
||||
+ else
|
||||
+ val &= ~(RTL8221B_PHYCR1_ALDPS_EN | RTL8221B_PHYCR1_ALDPS_XTAL_OFF_EN);
|
||||
+
|
||||
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, RTL8221B_PHYCR1, val);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int rtlgen_resume(struct phy_device *phydev)
|
||||
{
|
||||
int ret = genphy_resume(phydev);
|
||||
@@ -1427,6 +1450,7 @@ static struct phy_driver realtek_drvs[]
|
||||
}, {
|
||||
PHY_ID_MATCH_EXACT(0x001cc838),
|
||||
.name = "RTL8226-CG 2.5Gbps PHY",
|
||||
+ .probe = rtl822x_probe,
|
||||
.soft_reset = genphy_soft_reset,
|
||||
.get_features = rtl822x_get_features,
|
||||
.config_aneg = rtl822x_config_aneg,
|
||||
@@ -1438,6 +1462,7 @@ static struct phy_driver realtek_drvs[]
|
||||
}, {
|
||||
PHY_ID_MATCH_EXACT(0x001cc848),
|
||||
.name = "RTL8226B-CG_RTL8221B-CG 2.5Gbps PHY",
|
||||
+ .probe = rtl822x_probe,
|
||||
.soft_reset = genphy_soft_reset,
|
||||
.get_features = rtl822x_get_features,
|
||||
.config_aneg = rtl822x_config_aneg,
|
||||
@@ -1451,6 +1476,7 @@ static struct phy_driver realtek_drvs[]
|
||||
}, {
|
||||
.match_phy_device = rtl8221b_vb_cg_c22_match_phy_device,
|
||||
.name = "RTL8221B-VB-CG 2.5Gbps PHY (C22)",
|
||||
+ .probe = rtl822x_probe,
|
||||
.soft_reset = genphy_soft_reset,
|
||||
.get_features = rtl822x_get_features,
|
||||
.config_aneg = rtl822x_config_aneg,
|
||||
@@ -1464,6 +1490,7 @@ static struct phy_driver realtek_drvs[]
|
||||
}, {
|
||||
.match_phy_device = rtl8221b_vb_cg_c45_match_phy_device,
|
||||
.name = "RTL8221B-VB-CG 2.5Gbps PHY (C45)",
|
||||
+ .probe = rtl822x_probe,
|
||||
.soft_reset = genphy_soft_reset,
|
||||
.config_init = rtl822xb_config_init,
|
||||
.get_rate_matching = rtl822xb_get_rate_matching,
|
||||
@@ -1475,6 +1502,7 @@ static struct phy_driver realtek_drvs[]
|
||||
}, {
|
||||
.match_phy_device = rtl8221b_vn_cg_c22_match_phy_device,
|
||||
.name = "RTL8221B-VM-CG 2.5Gbps PHY (C22)",
|
||||
+ .probe = rtl822x_probe,
|
||||
.soft_reset = genphy_soft_reset,
|
||||
.get_features = rtl822x_get_features,
|
||||
.config_aneg = rtl822x_config_aneg,
|
||||
@@ -1488,6 +1516,7 @@ static struct phy_driver realtek_drvs[]
|
||||
}, {
|
||||
.match_phy_device = rtl8221b_vn_cg_c45_match_phy_device,
|
||||
.name = "RTL8221B-VN-CG 2.5Gbps PHY (C45)",
|
||||
+ .probe = rtl822x_probe,
|
||||
.soft_reset = genphy_soft_reset,
|
||||
.config_init = rtl822xb_config_init,
|
||||
.get_rate_matching = rtl822xb_get_rate_matching,
|
|
@ -0,0 +1,52 @@
|
|||
From 0de82310d2b32e78ff79d42c08b1122a6ede3778 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Golle <daniel@makrotopia.org>
|
||||
Date: Sun, 30 Apr 2023 00:15:41 +0100
|
||||
Subject: [PATCH] net: phy: realtek: detect early version of RTL8221B
|
||||
|
||||
Early versions (?) of the RTL8221B PHY cannot be identified in a regular
|
||||
Clause-45 bus scan as the PHY doesn't report the implemented MMDs
|
||||
correctly but returns 0 instead.
|
||||
Implement custom identify function using the PKGID instead of iterating
|
||||
over the implemented MMDs.
|
||||
|
||||
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
[forward-port by @namiltd]
|
||||
Signed-off-by: Mieczyslaw Nalewaj <namiltd@yahoo.com>
|
||||
--- a/drivers/net/phy/realtek.c
|
||||
+++ b/drivers/net/phy/realtek.c
|
||||
@@ -1120,10 +1120,32 @@ static int rtl8226_match_phy_device(stru
|
||||
static int rtlgen_is_c45_match(struct phy_device *phydev, unsigned int id,
|
||||
bool is_c45)
|
||||
{
|
||||
- if (phydev->is_c45)
|
||||
- return is_c45 && (id == phydev->c45_ids.device_ids[1]);
|
||||
- else
|
||||
+ if (phydev->is_c45) {
|
||||
+ u32 rid;
|
||||
+
|
||||
+ if (!is_c45)
|
||||
+ return 0;
|
||||
+
|
||||
+ rid = phydev->c45_ids.device_ids[1];
|
||||
+ if ((rid == 0xffffffff) && phydev->mdio.bus->read_c45) {
|
||||
+ int val;
|
||||
+
|
||||
+ val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PKGID1);
|
||||
+ if (val < 0)
|
||||
+ return 0;
|
||||
+
|
||||
+ rid = val << 16;
|
||||
+ val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PKGID2);
|
||||
+ if (val < 0)
|
||||
+ return 0;
|
||||
+
|
||||
+ rid |= val;
|
||||
+ }
|
||||
+
|
||||
+ return (id == rid);
|
||||
+ } else {
|
||||
return !is_c45 && (id == phydev->phy_id);
|
||||
+ }
|
||||
}
|
||||
|
||||
static int rtl8221b_vb_cg_c22_match_phy_device(struct phy_device *phydev)
|
|
@ -0,0 +1,102 @@
|
|||
From d7943c31d57c11e1a517aa3ce2006fca44866870 Mon Sep 17 00:00:00 2001
|
||||
From: Jianhui Zhao <zhaojh329@gmail.com>
|
||||
Date: Sun, 24 Sep 2023 22:15:00 +0800
|
||||
Subject: [PATCH] net: phy: realtek: add interrupt support for RTL8221B
|
||||
|
||||
This commit introduces interrupt support for RTL8221B.
|
||||
|
||||
Signed-off-by: Jianhui Zhao <zhaojh329@gmail.com>
|
||||
---
|
||||
drivers/net/phy/realtek.c | 47 +++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 47 insertions(+)
|
||||
|
||||
--- a/drivers/net/phy/realtek.c
|
||||
+++ b/drivers/net/phy/realtek.c
|
||||
@@ -1332,6 +1332,51 @@ static irqreturn_t rtl9000a_handle_inter
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
+static int rtl8221b_ack_interrupt(struct phy_device *phydev)
|
||||
+{
|
||||
+ int err;
|
||||
+
|
||||
+ err = phy_read_mmd(phydev, MDIO_MMD_VEND2, 0xa4d4);
|
||||
+
|
||||
+ return (err < 0) ? err : 0;
|
||||
+}
|
||||
+
|
||||
+static int rtl8221b_config_intr(struct phy_device *phydev)
|
||||
+{
|
||||
+ int err;
|
||||
+
|
||||
+ if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
|
||||
+ err = rtl8221b_ack_interrupt(phydev);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ err = phy_write_mmd(phydev, MDIO_MMD_VEND2, 0xa4d2, 0x7ff);
|
||||
+ } else {
|
||||
+ err = phy_write_mmd(phydev, MDIO_MMD_VEND2, 0xa4d2, 0x0);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ err = rtl8221b_ack_interrupt(phydev);
|
||||
+ }
|
||||
+
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+static irqreturn_t rtl8221b_handle_interrupt(struct phy_device *phydev)
|
||||
+{
|
||||
+ int err;
|
||||
+
|
||||
+ err = rtl8221b_ack_interrupt(phydev);
|
||||
+ if (err) {
|
||||
+ phy_error(phydev);
|
||||
+ return IRQ_NONE;
|
||||
+ }
|
||||
+
|
||||
+ phy_trigger_machine(phydev);
|
||||
+
|
||||
+ return IRQ_HANDLED;
|
||||
+}
|
||||
+
|
||||
static struct phy_driver realtek_drvs[] = {
|
||||
{
|
||||
PHY_ID_MATCH_EXACT(0x00008201),
|
||||
@@ -1498,6 +1543,8 @@ static struct phy_driver realtek_drvs[]
|
||||
}, {
|
||||
.match_phy_device = rtl8221b_vb_cg_c22_match_phy_device,
|
||||
.name = "RTL8221B-VB-CG 2.5Gbps PHY (C22)",
|
||||
+ .config_intr = rtl8221b_config_intr,
|
||||
+ .handle_interrupt = rtl8221b_handle_interrupt,
|
||||
.probe = rtl822x_probe,
|
||||
.soft_reset = genphy_soft_reset,
|
||||
.get_features = rtl822x_get_features,
|
||||
@@ -1512,6 +1559,8 @@ static struct phy_driver realtek_drvs[]
|
||||
}, {
|
||||
.match_phy_device = rtl8221b_vb_cg_c45_match_phy_device,
|
||||
.name = "RTL8221B-VB-CG 2.5Gbps PHY (C45)",
|
||||
+ .config_intr = rtl8221b_config_intr,
|
||||
+ .handle_interrupt = rtl8221b_handle_interrupt,
|
||||
.probe = rtl822x_probe,
|
||||
.soft_reset = genphy_soft_reset,
|
||||
.config_init = rtl822xb_config_init,
|
||||
@@ -1524,6 +1573,8 @@ static struct phy_driver realtek_drvs[]
|
||||
}, {
|
||||
.match_phy_device = rtl8221b_vn_cg_c22_match_phy_device,
|
||||
.name = "RTL8221B-VM-CG 2.5Gbps PHY (C22)",
|
||||
+ .config_intr = rtl8221b_config_intr,
|
||||
+ .handle_interrupt = rtl8221b_handle_interrupt,
|
||||
.probe = rtl822x_probe,
|
||||
.soft_reset = genphy_soft_reset,
|
||||
.get_features = rtl822x_get_features,
|
||||
@@ -1538,6 +1589,8 @@ static struct phy_driver realtek_drvs[]
|
||||
}, {
|
||||
.match_phy_device = rtl8221b_vn_cg_c45_match_phy_device,
|
||||
.name = "RTL8221B-VN-CG 2.5Gbps PHY (C45)",
|
||||
+ .config_intr = rtl8221b_config_intr,
|
||||
+ .handle_interrupt = rtl8221b_handle_interrupt,
|
||||
.probe = rtl822x_probe,
|
||||
.soft_reset = genphy_soft_reset,
|
||||
.config_init = rtl822xb_config_init,
|
|
@ -1,106 +0,0 @@
|
|||
From ace6abaa0f9203083fe4c0a6a74da2d96410b625 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Couzens <lynxis@fe80.eu>
|
||||
Date: Sat, 13 Aug 2022 12:49:33 +0200
|
||||
Subject: [PATCH 01/10] net: phy: realtek: rtl8221: allow to configure SERDES
|
||||
mode
|
||||
|
||||
The rtl8221 supports multiple SERDES modes:
|
||||
- SGMII
|
||||
- 2500base-x
|
||||
- HiSGMII
|
||||
|
||||
Further it supports rate adaption on SERDES links to allow
|
||||
slow ethernet speeds (10/100/1000mbit) to work on 2500base-x/HiSGMII
|
||||
links without reducing the SERDES speed.
|
||||
|
||||
When operating without rate adapters the SERDES link will follow the
|
||||
ethernet speed.
|
||||
|
||||
Signed-off-by: Alexander Couzens <lynxis@fe80.eu>
|
||||
---
|
||||
drivers/net/phy/realtek.c | 48 +++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 48 insertions(+)
|
||||
|
||||
--- a/drivers/net/phy/realtek.c
|
||||
+++ b/drivers/net/phy/realtek.c
|
||||
@@ -54,6 +54,15 @@
|
||||
RTL8201F_ISR_LINK)
|
||||
#define RTL8201F_IER 0x13
|
||||
|
||||
+#define RTL8221B_MMD_SERDES_CTRL MDIO_MMD_VEND1
|
||||
+#define RTL8221B_MMD_PHY_CTRL MDIO_MMD_VEND2
|
||||
+#define RTL8221B_SERDES_OPTION 0x697a
|
||||
+#define RTL8221B_SERDES_OPTION_MODE_MASK GENMASK(5, 0)
|
||||
+#define RTL8221B_SERDES_OPTION_MODE_2500BASEX_SGMII 0
|
||||
+#define RTL8221B_SERDES_OPTION_MODE_HISGMII_SGMII 1
|
||||
+#define RTL8221B_SERDES_OPTION_MODE_2500BASEX 2
|
||||
+#define RTL8221B_SERDES_OPTION_MODE_HISGMII 3
|
||||
+
|
||||
#define RTL8366RB_POWER_SAVE 0x15
|
||||
#define RTL8366RB_POWER_SAVE_ON BIT(12)
|
||||
|
||||
@@ -879,6 +888,48 @@ static irqreturn_t rtl9000a_handle_inter
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
+static int rtl8221b_config_init(struct phy_device *phydev)
|
||||
+{
|
||||
+ u16 option_mode;
|
||||
+
|
||||
+ switch (phydev->interface) {
|
||||
+ case PHY_INTERFACE_MODE_2500BASEX:
|
||||
+ if (!phydev->is_c45) {
|
||||
+ option_mode = RTL8221B_SERDES_OPTION_MODE_2500BASEX;
|
||||
+ break;
|
||||
+ }
|
||||
+ fallthrough;
|
||||
+ case PHY_INTERFACE_MODE_SGMII:
|
||||
+ option_mode = RTL8221B_SERDES_OPTION_MODE_2500BASEX_SGMII;
|
||||
+ break;
|
||||
+ default:
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL,
|
||||
+ 0x75f3, 0);
|
||||
+
|
||||
+ phy_modify_mmd_changed(phydev, RTL8221B_MMD_SERDES_CTRL,
|
||||
+ RTL8221B_SERDES_OPTION,
|
||||
+ RTL8221B_SERDES_OPTION_MODE_MASK, option_mode);
|
||||
+ switch (option_mode) {
|
||||
+ case RTL8221B_SERDES_OPTION_MODE_2500BASEX_SGMII:
|
||||
+ case RTL8221B_SERDES_OPTION_MODE_2500BASEX:
|
||||
+ phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, 0x6a04, 0x0503);
|
||||
+ phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, 0x6f10, 0xd455);
|
||||
+ phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, 0x6f11, 0x8020);
|
||||
+ break;
|
||||
+ case RTL8221B_SERDES_OPTION_MODE_HISGMII_SGMII:
|
||||
+ case RTL8221B_SERDES_OPTION_MODE_HISGMII:
|
||||
+ phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, 0x6a04, 0x0503);
|
||||
+ phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, 0x6f10, 0xd433);
|
||||
+ phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, 0x6f11, 0x8020);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static struct phy_driver realtek_drvs[] = {
|
||||
{
|
||||
PHY_ID_MATCH_EXACT(0x00008201),
|
||||
@@ -1033,6 +1084,7 @@ static struct phy_driver realtek_drvs[]
|
||||
PHY_ID_MATCH_EXACT(0x001cc849),
|
||||
.name = "RTL8221B-VB-CG 2.5Gbps PHY",
|
||||
.get_features = rtl822x_get_features,
|
||||
+ .config_init = rtl8221b_config_init,
|
||||
.config_aneg = rtl822x_config_aneg,
|
||||
.read_status = rtl822x_read_status,
|
||||
.suspend = genphy_suspend,
|
||||
@@ -1044,6 +1096,7 @@ static struct phy_driver realtek_drvs[]
|
||||
.name = "RTL8221B-VM-CG 2.5Gbps PHY",
|
||||
.get_features = rtl822x_get_features,
|
||||
.config_aneg = rtl822x_config_aneg,
|
||||
+ .config_init = rtl8221b_config_init,
|
||||
.read_status = rtl822x_read_status,
|
||||
.suspend = genphy_suspend,
|
||||
.resume = rtlgen_resume,
|
|
@ -1,65 +0,0 @@
|
|||
From 85cd45580f5e3b26068cccb7d6173f200e754dc0 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Golle <daniel@makrotopia.org>
|
||||
Date: Sun, 2 Apr 2023 23:56:16 +0100
|
||||
Subject: [PATCH 1/2] net: phy: realtek: use genphy_soft_reset for 2.5G PHYs
|
||||
|
||||
Some vendor bootloaders do weird things with those PHYs which result in
|
||||
link modes being reported wrongly. Start from a clean sheet by resetting
|
||||
the PHY.
|
||||
|
||||
Reported-by: Yevhen Kolomeiko <jarvis2709@gmail.com>
|
||||
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
---
|
||||
drivers/net/phy/realtek.c | 6 ++++++
|
||||
1 file changed, 6 insertions(+)
|
||||
|
||||
--- a/drivers/net/phy/realtek.c
|
||||
+++ b/drivers/net/phy/realtek.c
|
||||
@@ -1070,6 +1070,7 @@ static struct phy_driver realtek_drvs[]
|
||||
.write_page = rtl821x_write_page,
|
||||
.read_mmd = rtl822x_read_mmd,
|
||||
.write_mmd = rtl822x_write_mmd,
|
||||
+ .soft_reset = genphy_soft_reset,
|
||||
}, {
|
||||
PHY_ID_MATCH_EXACT(0x001cc840),
|
||||
.name = "RTL8226B_RTL8221B 2.5Gbps PHY",
|
||||
@@ -1082,6 +1083,7 @@ static struct phy_driver realtek_drvs[]
|
||||
.write_page = rtl821x_write_page,
|
||||
.read_mmd = rtl822x_read_mmd,
|
||||
.write_mmd = rtl822x_write_mmd,
|
||||
+ .soft_reset = genphy_soft_reset,
|
||||
}, {
|
||||
PHY_ID_MATCH_EXACT(0x001cc838),
|
||||
.name = "RTL8226-CG 2.5Gbps PHY",
|
||||
@@ -1092,6 +1094,7 @@ static struct phy_driver realtek_drvs[]
|
||||
.resume = rtlgen_resume,
|
||||
.read_page = rtl821x_read_page,
|
||||
.write_page = rtl821x_write_page,
|
||||
+ .soft_reset = genphy_soft_reset,
|
||||
}, {
|
||||
PHY_ID_MATCH_EXACT(0x001cc848),
|
||||
.name = "RTL8226B-CG_RTL8221B-CG 2.5Gbps PHY",
|
||||
@@ -1102,6 +1105,7 @@ static struct phy_driver realtek_drvs[]
|
||||
.resume = rtlgen_resume,
|
||||
.read_page = rtl821x_read_page,
|
||||
.write_page = rtl821x_write_page,
|
||||
+ .soft_reset = genphy_soft_reset,
|
||||
}, {
|
||||
PHY_ID_MATCH_EXACT(0x001cc849),
|
||||
.name = "RTL8221B-VB-CG 2.5Gbps PHY",
|
||||
@@ -1113,6 +1117,7 @@ static struct phy_driver realtek_drvs[]
|
||||
.resume = rtlgen_resume,
|
||||
.read_page = rtl821x_read_page,
|
||||
.write_page = rtl821x_write_page,
|
||||
+ .soft_reset = genphy_soft_reset,
|
||||
}, {
|
||||
PHY_ID_MATCH_EXACT(0x001cc84a),
|
||||
.name = "RTL8221B-VM-CG 2.5Gbps PHY",
|
||||
@@ -1124,6 +1129,7 @@ static struct phy_driver realtek_drvs[]
|
||||
.resume = rtlgen_resume,
|
||||
.read_page = rtl821x_read_page,
|
||||
.write_page = rtl821x_write_page,
|
||||
+ .soft_reset = genphy_soft_reset,
|
||||
}, {
|
||||
PHY_ID_MATCH_EXACT(0x001cc961),
|
||||
.name = "RTL8366RB Gigabit Ethernet",
|
|
@ -1,43 +0,0 @@
|
|||
From 2b1b8c4c215af7988136401c902338d091d408a1 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Golle <daniel@makrotopia.org>
|
||||
Date: Mon, 3 Apr 2023 01:21:57 +0300
|
||||
Subject: [PATCH 2/2] net: phy: realtek: disable SGMII in-band AN for 2.5G PHYs
|
||||
|
||||
MAC drivers don't use SGMII in-band autonegotiation unless told to do so
|
||||
in device tree using 'managed = "in-band-status"'. When using MDIO to
|
||||
access a PHY, in-band-status is unneeded as we have link-status via
|
||||
MDIO. Switch off SGMII in-band autonegotiation using magic values.
|
||||
|
||||
Reported-by: Chen Minqiang <ptpt52@gmail.com>
|
||||
Reported-by: Chukun Pan <amadeus@jmu.edu.cn>
|
||||
Reported-by: Yevhen Kolomeiko <jarvis2709@gmail.com>
|
||||
Tested-by: Yevhen Kolomeiko <jarvis2709@gmail.com>
|
||||
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
---
|
||||
drivers/net/phy/realtek.c | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
--- a/drivers/net/phy/realtek.c
|
||||
+++ b/drivers/net/phy/realtek.c
|
||||
@@ -913,6 +913,7 @@ static irqreturn_t rtl9000a_handle_inter
|
||||
static int rtl8221b_config_init(struct phy_device *phydev)
|
||||
{
|
||||
u16 option_mode;
|
||||
+ int val;
|
||||
|
||||
switch (phydev->interface) {
|
||||
case PHY_INTERFACE_MODE_2500BASEX:
|
||||
@@ -949,6 +950,13 @@ static int rtl8221b_config_init(struct p
|
||||
break;
|
||||
}
|
||||
|
||||
+ /* Disable SGMII AN */
|
||||
+ phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, 0x7588, 0x2);
|
||||
+ phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, 0x7589, 0x71d0);
|
||||
+ phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, 0x7587, 0x3);
|
||||
+ phy_read_mmd_poll_timeout(phydev, RTL8221B_MMD_SERDES_CTRL, 0x7587,
|
||||
+ val, !(val & BIT(0)), 500, 100000, false);
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
From 7d41a5a8e9c91cc6bb011dd953570738583dd091 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Golle <daniel@makrotopia.org>
|
||||
Date: Wed, 18 Sep 2024 02:01:01 +0100
|
||||
Subject: [PATCH] net: ethernet: mtk_eth_soc: reset all TX queues on DMA free
|
||||
|
||||
The purpose of resetting the TX queue is to reset the
|
||||
byte and packet count as well as to clear the software
|
||||
flow control XOFF bit.
|
||||
|
||||
MediaTek developers pointed out that netdev_reset_queue would only
|
||||
resets queue 0 of the network device.
|
||||
Queues that are not reset may cause unexpected issues.
|
||||
|
||||
Packets may stop being sent after reset and "transmit timeout" log may
|
||||
be displayed.
|
||||
|
||||
Import fix from MediaTek's SDK to resolve this issue.
|
||||
|
||||
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 18 ++++++++++++++----
|
||||
1 file changed, 14 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
||||
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
||||
@@ -3135,11 +3135,19 @@ static int mtk_dma_init(struct mtk_eth *
|
||||
static void mtk_dma_free(struct mtk_eth *eth)
|
||||
{
|
||||
const struct mtk_soc_data *soc = eth->soc;
|
||||
- int i;
|
||||
+ int i, j, txqs = 1;
|
||||
+
|
||||
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA))
|
||||
+ txqs = MTK_QDMA_NUM_QUEUES;
|
||||
+
|
||||
+ for (i = 0; i < MTK_MAX_DEVS; i++) {
|
||||
+ if (!eth->netdev[i])
|
||||
+ continue;
|
||||
+
|
||||
+ for (j = 0; j < txqs; j++)
|
||||
+ netdev_tx_reset_queue(netdev_get_tx_queue(eth->netdev[i], j));
|
||||
+ }
|
||||
|
||||
- for (i = 0; i < MTK_MAX_DEVS; i++)
|
||||
- if (eth->netdev[i])
|
||||
- netdev_reset_queue(eth->netdev[i]);
|
||||
if (!MTK_HAS_CAPS(soc->caps, MTK_SRAM) && eth->scratch_ring) {
|
||||
dma_free_coherent(eth->dma_dev,
|
||||
MTK_QDMA_RING_SIZE * soc->tx.desc_size,
|
|
@ -17,7 +17,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
|||
|
||||
--- a/include/linux/netdevice.h
|
||||
+++ b/include/linux/netdevice.h
|
||||
@@ -2243,7 +2243,7 @@ struct net_device {
|
||||
@@ -2224,7 +2224,7 @@ struct net_device {
|
||||
#if IS_ENABLED(CONFIG_AX25)
|
||||
void *ax25_ptr;
|
||||
#endif
|
||||
|
|
|
@ -11,7 +11,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
|
||||
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
||||
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
||||
@@ -1334,6 +1334,22 @@ struct mtk_mac {
|
||||
@@ -1322,6 +1322,22 @@ struct mtk_mac {
|
||||
/* the struct describing the SoC. these are declared in the soc_xyz.c files */
|
||||
extern const struct of_device_id of_mtk_match[];
|
||||
|
||||
|
@ -34,7 +34,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
static inline bool mtk_is_netsys_v1(struct mtk_eth *eth)
|
||||
{
|
||||
return eth->soc->version == 1;
|
||||
@@ -1348,6 +1364,7 @@ static inline bool mtk_is_netsys_v3_or_g
|
||||
@@ -1336,6 +1352,7 @@ static inline bool mtk_is_netsys_v3_or_g
|
||||
{
|
||||
return eth->soc->version > 2;
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
#include <net/page_pool/helpers.h>
|
||||
|
||||
#include "mtk_eth_soc.h"
|
||||
@@ -1587,12 +1588,28 @@ static void mtk_wake_queue(struct mtk_et
|
||||
@@ -1596,12 +1597,28 @@ static void mtk_wake_queue(struct mtk_et
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,7 +53,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
bool gso = false;
|
||||
int tx_num;
|
||||
|
||||
@@ -1614,6 +1631,18 @@ static netdev_tx_t mtk_start_xmit(struct
|
||||
@@ -1623,6 +1640,18 @@ static netdev_tx_t mtk_start_xmit(struct
|
||||
return NETDEV_TX_BUSY;
|
||||
}
|
||||
|
||||
|
@ -72,7 +72,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
/* TSO: fill MSS info in tcp checksum field */
|
||||
if (skb_is_gso(skb)) {
|
||||
if (skb_cow_head(skb, 0)) {
|
||||
@@ -1629,8 +1658,14 @@ static netdev_tx_t mtk_start_xmit(struct
|
||||
@@ -1638,8 +1667,14 @@ static netdev_tx_t mtk_start_xmit(struct
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
|
||||
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
||||
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
||||
@@ -2129,7 +2129,7 @@ static int mtk_poll_rx(struct napi_struc
|
||||
@@ -2140,7 +2140,7 @@ static int mtk_poll_rx(struct napi_struc
|
||||
if (ret != XDP_PASS)
|
||||
goto skip_rx;
|
||||
|
||||
|
@ -19,7 +19,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
if (unlikely(!skb)) {
|
||||
page_pool_put_full_page(ring->page_pool,
|
||||
page, true);
|
||||
@@ -2167,7 +2167,7 @@ static int mtk_poll_rx(struct napi_struc
|
||||
@@ -2178,7 +2178,7 @@ static int mtk_poll_rx(struct napi_struc
|
||||
dma_unmap_single(eth->dma_dev, ((u64)trxd.rxd1 | addr64),
|
||||
ring->buf_size, DMA_FROM_DEVICE);
|
||||
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
From: Chad Monroe <chad@monroe.io>
|
||||
Date: Mon, 16 Sep 2024 19:29:03 -0700
|
||||
Subject: [PATCH] net: ethernet: mediatek: increase QDMA RESV_BUF size
|
||||
|
||||
Increase QDMA RESV_BUF from 2K to 3K for netsys v2 to match Mediatek SDK[1].
|
||||
This helps reduce the possibility of Ethernet transmit timeouts.
|
||||
|
||||
[1]: https://git01.mediatek.com/plugins/gitiles/openwrt/feeds/mtk-openwrt-feeds/+/19d8456c3051e5f6dabf42fa770916a2126ea4bf
|
||||
|
||||
Signed-off-by: Chad Monroe <chad@monroe.io>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 6 ++++--
|
||||
drivers/net/ethernet/mediatek/mtk_eth_soc.h | 1 +
|
||||
2 files changed, 5 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
||||
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
||||
@@ -271,6 +271,7 @@
|
||||
#define MTK_WCOMP_EN BIT(24)
|
||||
#define MTK_RESV_BUF (0x80 << 16)
|
||||
#define MTK_MUTLI_CNT (0x4 << 12)
|
||||
+#define MTK_RESV_BUF_MASK (0xff << 16)
|
||||
#define MTK_LEAKY_BUCKET_EN BIT(11)
|
||||
|
||||
/* QDMA Flow Control Register */
|
||||
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
||||
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
||||
@@ -3309,12 +3309,14 @@ static int mtk_start_dma(struct mtk_eth
|
||||
MTK_TX_BT_32DWORDS | MTK_NDP_CO_PRO |
|
||||
MTK_RX_2B_OFFSET | MTK_TX_WB_DDONE;
|
||||
|
||||
- if (mtk_is_netsys_v2_or_greater(eth))
|
||||
+ if (mtk_is_netsys_v2_or_greater(eth)) {
|
||||
+ val &= ~MTK_RESV_BUF_MASK;
|
||||
val |= MTK_MUTLI_CNT | MTK_RESV_BUF |
|
||||
MTK_WCOMP_EN | MTK_DMAD_WR_WDONE |
|
||||
MTK_CHK_DDONE_EN | MTK_LEAKY_BUCKET_EN;
|
||||
- else
|
||||
+ } else {
|
||||
val |= MTK_RX_BT_32DWORDS;
|
||||
+ }
|
||||
mtk_w32(eth, val, reg_map->qdma.glo_cfg);
|
||||
|
||||
mtk_w32(eth,
|
|
@ -0,0 +1,903 @@
|
|||
From d5e337e7aecc2e1cc9e96768062610adb95f8f72 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Golle <daniel@makrotopia.org>
|
||||
Date: Tue, 12 Dec 2023 03:51:14 +0000
|
||||
Subject: [PATCH] net: ethernet: mtk_eth_soc: add paths and SerDes modes for
|
||||
MT7988
|
||||
|
||||
MT7988 comes with a built-in 2.5G PHY as well as SerDes lanes to
|
||||
connect external PHYs or transceivers in USXGMII, 10GBase-R, 5GBase-R,
|
||||
2500Base-X, 1000Base-X and Cisco SGMII interface modes.
|
||||
|
||||
Implement support for configuring for the new paths to SerDes interfaces
|
||||
and the internal 2.5G PHY.
|
||||
|
||||
Add USXGMII PCS driver for 10GBase-R, 5GBase-R and USXGMII mode, and
|
||||
setup the new PHYA on MT7988 to access the also still existing old
|
||||
LynxI PCS for 1000Base-X, 2500Base-X and Cisco SGMII PCS interface
|
||||
modes.
|
||||
|
||||
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/mtk_eth_path.c | 122 +++++++-
|
||||
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 292 +++++++++++++++++--
|
||||
drivers/net/ethernet/mediatek/mtk_eth_soc.h | 107 ++++++-
|
||||
3 files changed, 470 insertions(+), 51 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/mtk_eth_path.c
|
||||
+++ b/drivers/net/ethernet/mediatek/mtk_eth_path.c
|
||||
@@ -31,10 +31,20 @@ static const char *mtk_eth_path_name(u64
|
||||
return "gmac2_rgmii";
|
||||
case MTK_ETH_PATH_GMAC2_SGMII:
|
||||
return "gmac2_sgmii";
|
||||
+ case MTK_ETH_PATH_GMAC2_2P5GPHY:
|
||||
+ return "gmac2_2p5gphy";
|
||||
case MTK_ETH_PATH_GMAC2_GEPHY:
|
||||
return "gmac2_gephy";
|
||||
+ case MTK_ETH_PATH_GMAC3_SGMII:
|
||||
+ return "gmac3_sgmii";
|
||||
case MTK_ETH_PATH_GDM1_ESW:
|
||||
return "gdm1_esw";
|
||||
+ case MTK_ETH_PATH_GMAC1_USXGMII:
|
||||
+ return "gmac1_usxgmii";
|
||||
+ case MTK_ETH_PATH_GMAC2_USXGMII:
|
||||
+ return "gmac2_usxgmii";
|
||||
+ case MTK_ETH_PATH_GMAC3_USXGMII:
|
||||
+ return "gmac3_usxgmii";
|
||||
default:
|
||||
return "unknown path";
|
||||
}
|
||||
@@ -127,6 +137,27 @@ static int set_mux_u3_gmac2_to_qphy(stru
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int set_mux_gmac2_to_2p5gphy(struct mtk_eth *eth, u64 path)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ if (path == MTK_ETH_PATH_GMAC2_2P5GPHY) {
|
||||
+ ret = regmap_clear_bits(eth->ethsys, ETHSYS_SYSCFG0, SYSCFG0_SGMII_GMAC2_V2);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* Setup mux to 2p5g PHY */
|
||||
+ ret = regmap_clear_bits(eth->infra, TOP_MISC_NETSYS_PCS_MUX, MUX_G2_USXGMII_SEL);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ dev_dbg(eth->dev, "path %s in %s updated\n",
|
||||
+ mtk_eth_path_name(path), __func__);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int set_mux_gmac1_gmac2_to_sgmii_rgmii(struct mtk_eth *eth, u64 path)
|
||||
{
|
||||
unsigned int val = 0;
|
||||
@@ -165,7 +196,48 @@ static int set_mux_gmac1_gmac2_to_sgmii_
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int set_mux_gmac12_to_gephy_sgmii(struct mtk_eth *eth, u64 path)
|
||||
+static int set_mux_gmac123_to_usxgmii(struct mtk_eth *eth, u64 path)
|
||||
+{
|
||||
+ unsigned int val = 0;
|
||||
+ bool updated = true;
|
||||
+ int mac_id = 0;
|
||||
+
|
||||
+ /* Disable SYSCFG1 SGMII */
|
||||
+ regmap_read(eth->ethsys, ETHSYS_SYSCFG0, &val);
|
||||
+
|
||||
+ switch (path) {
|
||||
+ case MTK_ETH_PATH_GMAC1_USXGMII:
|
||||
+ val &= ~(u32)SYSCFG0_SGMII_GMAC1_V2;
|
||||
+ mac_id = MTK_GMAC1_ID;
|
||||
+ break;
|
||||
+ case MTK_ETH_PATH_GMAC2_USXGMII:
|
||||
+ val &= ~(u32)SYSCFG0_SGMII_GMAC2_V2;
|
||||
+ mac_id = MTK_GMAC2_ID;
|
||||
+ break;
|
||||
+ case MTK_ETH_PATH_GMAC3_USXGMII:
|
||||
+ val &= ~(u32)SYSCFG0_SGMII_GMAC3_V2;
|
||||
+ mac_id = MTK_GMAC3_ID;
|
||||
+ break;
|
||||
+ default:
|
||||
+ updated = false;
|
||||
+ };
|
||||
+
|
||||
+ if (updated) {
|
||||
+ regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0,
|
||||
+ SYSCFG0_SGMII_MASK, val);
|
||||
+
|
||||
+ if (mac_id == MTK_GMAC2_ID)
|
||||
+ regmap_set_bits(eth->infra, TOP_MISC_NETSYS_PCS_MUX,
|
||||
+ MUX_G2_USXGMII_SEL);
|
||||
+ }
|
||||
+
|
||||
+ dev_dbg(eth->dev, "path %s in %s updated = %d\n",
|
||||
+ mtk_eth_path_name(path), __func__, updated);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int set_mux_gmac123_to_gephy_sgmii(struct mtk_eth *eth, u64 path)
|
||||
{
|
||||
unsigned int val = 0;
|
||||
bool updated = true;
|
||||
@@ -182,6 +254,9 @@ static int set_mux_gmac12_to_gephy_sgmii
|
||||
case MTK_ETH_PATH_GMAC2_SGMII:
|
||||
val |= SYSCFG0_SGMII_GMAC2_V2;
|
||||
break;
|
||||
+ case MTK_ETH_PATH_GMAC3_SGMII:
|
||||
+ val |= SYSCFG0_SGMII_GMAC3_V2;
|
||||
+ break;
|
||||
default:
|
||||
updated = false;
|
||||
}
|
||||
@@ -210,13 +285,25 @@ static const struct mtk_eth_muxc mtk_eth
|
||||
.cap_bit = MTK_ETH_MUX_U3_GMAC2_TO_QPHY,
|
||||
.set_path = set_mux_u3_gmac2_to_qphy,
|
||||
}, {
|
||||
+ .name = "mux_gmac2_to_2p5gphy",
|
||||
+ .cap_bit = MTK_ETH_MUX_GMAC2_TO_2P5GPHY,
|
||||
+ .set_path = set_mux_gmac2_to_2p5gphy,
|
||||
+ }, {
|
||||
.name = "mux_gmac1_gmac2_to_sgmii_rgmii",
|
||||
.cap_bit = MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII,
|
||||
.set_path = set_mux_gmac1_gmac2_to_sgmii_rgmii,
|
||||
}, {
|
||||
.name = "mux_gmac12_to_gephy_sgmii",
|
||||
.cap_bit = MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII,
|
||||
- .set_path = set_mux_gmac12_to_gephy_sgmii,
|
||||
+ .set_path = set_mux_gmac123_to_gephy_sgmii,
|
||||
+ }, {
|
||||
+ .name = "mux_gmac123_to_gephy_sgmii",
|
||||
+ .cap_bit = MTK_ETH_MUX_GMAC123_TO_GEPHY_SGMII,
|
||||
+ .set_path = set_mux_gmac123_to_gephy_sgmii,
|
||||
+ }, {
|
||||
+ .name = "mux_gmac123_to_usxgmii",
|
||||
+ .cap_bit = MTK_ETH_MUX_GMAC123_TO_USXGMII,
|
||||
+ .set_path = set_mux_gmac123_to_usxgmii,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -249,12 +336,39 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
+int mtk_gmac_usxgmii_path_setup(struct mtk_eth *eth, int mac_id)
|
||||
+{
|
||||
+ u64 path;
|
||||
+
|
||||
+ path = (mac_id == MTK_GMAC1_ID) ? MTK_ETH_PATH_GMAC1_USXGMII :
|
||||
+ (mac_id == MTK_GMAC2_ID) ? MTK_ETH_PATH_GMAC2_USXGMII :
|
||||
+ MTK_ETH_PATH_GMAC3_USXGMII;
|
||||
+
|
||||
+ /* Setup proper MUXes along the path */
|
||||
+ return mtk_eth_mux_setup(eth, path);
|
||||
+}
|
||||
+
|
||||
int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id)
|
||||
{
|
||||
u64 path;
|
||||
|
||||
- path = (mac_id == 0) ? MTK_ETH_PATH_GMAC1_SGMII :
|
||||
- MTK_ETH_PATH_GMAC2_SGMII;
|
||||
+ path = (mac_id == MTK_GMAC1_ID) ? MTK_ETH_PATH_GMAC1_SGMII :
|
||||
+ (mac_id == MTK_GMAC2_ID) ? MTK_ETH_PATH_GMAC2_SGMII :
|
||||
+ MTK_ETH_PATH_GMAC3_SGMII;
|
||||
+
|
||||
+ /* Setup proper MUXes along the path */
|
||||
+ return mtk_eth_mux_setup(eth, path);
|
||||
+}
|
||||
+
|
||||
+int mtk_gmac_2p5gphy_path_setup(struct mtk_eth *eth, int mac_id)
|
||||
+{
|
||||
+ u64 path = 0;
|
||||
+
|
||||
+ if (mac_id == MTK_GMAC2_ID)
|
||||
+ path = MTK_ETH_PATH_GMAC2_2P5GPHY;
|
||||
+
|
||||
+ if (!path)
|
||||
+ return -EINVAL;
|
||||
|
||||
/* Setup proper MUXes along the path */
|
||||
return mtk_eth_mux_setup(eth, path);
|
||||
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
||||
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
||||
@@ -22,6 +22,8 @@
|
||||
#include <linux/pinctrl/devinfo.h>
|
||||
#include <linux/phylink.h>
|
||||
#include <linux/pcs/pcs-mtk-lynxi.h>
|
||||
+#include <linux/pcs/pcs-mtk-usxgmii.h>
|
||||
+#include <linux/phy/phy.h>
|
||||
#include <linux/jhash.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <net/dsa.h>
|
||||
@@ -270,12 +272,8 @@ static const char * const mtk_clks_sourc
|
||||
"ethwarp_wocpu2",
|
||||
"ethwarp_wocpu1",
|
||||
"ethwarp_wocpu0",
|
||||
- "top_usxgmii0_sel",
|
||||
- "top_usxgmii1_sel",
|
||||
"top_sgm0_sel",
|
||||
"top_sgm1_sel",
|
||||
- "top_xfi_phy0_xtal_sel",
|
||||
- "top_xfi_phy1_xtal_sel",
|
||||
"top_eth_gmii_sel",
|
||||
"top_eth_refck_50m_sel",
|
||||
"top_eth_sys_200m_sel",
|
||||
@@ -518,6 +516,30 @@ static void mtk_setup_bridge_switch(stru
|
||||
MTK_GSW_CFG);
|
||||
}
|
||||
|
||||
+static bool mtk_check_gmac23_idle(struct mtk_mac *mac)
|
||||
+{
|
||||
+ u32 mac_fsm, gdm_fsm;
|
||||
+
|
||||
+ mac_fsm = mtk_r32(mac->hw, MTK_MAC_FSM(mac->id));
|
||||
+
|
||||
+ switch (mac->id) {
|
||||
+ case MTK_GMAC2_ID:
|
||||
+ gdm_fsm = mtk_r32(mac->hw, MTK_FE_GDM2_FSM);
|
||||
+ break;
|
||||
+ case MTK_GMAC3_ID:
|
||||
+ gdm_fsm = mtk_r32(mac->hw, MTK_FE_GDM3_FSM);
|
||||
+ break;
|
||||
+ default:
|
||||
+ return true;
|
||||
+ };
|
||||
+
|
||||
+ if ((mac_fsm & 0xFFFF0000) == 0x01010000 &&
|
||||
+ (gdm_fsm & 0xFFFF0000) == 0x00000000)
|
||||
+ return true;
|
||||
+
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
static struct phylink_pcs *mtk_mac_select_pcs(struct phylink_config *config,
|
||||
phy_interface_t interface)
|
||||
{
|
||||
@@ -526,6 +548,21 @@ static struct phylink_pcs *mtk_mac_selec
|
||||
struct mtk_eth *eth = mac->hw;
|
||||
unsigned int sid;
|
||||
|
||||
+ if (mtk_is_netsys_v3_or_greater(eth)) {
|
||||
+ switch (interface) {
|
||||
+ case PHY_INTERFACE_MODE_1000BASEX:
|
||||
+ case PHY_INTERFACE_MODE_2500BASEX:
|
||||
+ case PHY_INTERFACE_MODE_SGMII:
|
||||
+ return mac->sgmii_pcs;
|
||||
+ case PHY_INTERFACE_MODE_5GBASER:
|
||||
+ case PHY_INTERFACE_MODE_10GBASER:
|
||||
+ case PHY_INTERFACE_MODE_USXGMII:
|
||||
+ return mac->usxgmii_pcs;
|
||||
+ default:
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
if (interface == PHY_INTERFACE_MODE_SGMII ||
|
||||
phy_interface_mode_is_8023z(interface)) {
|
||||
sid = (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_SGMII)) ?
|
||||
@@ -577,7 +614,22 @@ static void mtk_mac_config(struct phylin
|
||||
goto init_err;
|
||||
}
|
||||
break;
|
||||
+ case PHY_INTERFACE_MODE_USXGMII:
|
||||
+ case PHY_INTERFACE_MODE_10GBASER:
|
||||
+ case PHY_INTERFACE_MODE_5GBASER:
|
||||
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_USXGMII)) {
|
||||
+ err = mtk_gmac_usxgmii_path_setup(eth, mac->id);
|
||||
+ if (err)
|
||||
+ goto init_err;
|
||||
+ }
|
||||
+ break;
|
||||
case PHY_INTERFACE_MODE_INTERNAL:
|
||||
+ if (mac->id == MTK_GMAC2_ID &&
|
||||
+ MTK_HAS_CAPS(eth->soc->caps, MTK_2P5GPHY)) {
|
||||
+ err = mtk_gmac_2p5gphy_path_setup(eth, mac->id);
|
||||
+ if (err)
|
||||
+ goto init_err;
|
||||
+ }
|
||||
break;
|
||||
default:
|
||||
goto err_phy;
|
||||
@@ -624,8 +676,6 @@ static void mtk_mac_config(struct phylin
|
||||
val &= ~SYSCFG0_GE_MODE(SYSCFG0_GE_MASK, mac->id);
|
||||
val |= SYSCFG0_GE_MODE(ge_mode, mac->id);
|
||||
regmap_write(eth->ethsys, ETHSYS_SYSCFG0, val);
|
||||
-
|
||||
- mac->interface = state->interface;
|
||||
}
|
||||
|
||||
/* SGMII */
|
||||
@@ -642,21 +692,40 @@ static void mtk_mac_config(struct phylin
|
||||
|
||||
/* Save the syscfg0 value for mac_finish */
|
||||
mac->syscfg0 = val;
|
||||
- } else if (phylink_autoneg_inband(mode)) {
|
||||
+ } else if (state->interface != PHY_INTERFACE_MODE_USXGMII &&
|
||||
+ state->interface != PHY_INTERFACE_MODE_10GBASER &&
|
||||
+ state->interface != PHY_INTERFACE_MODE_5GBASER &&
|
||||
+ phylink_autoneg_inband(mode)) {
|
||||
dev_err(eth->dev,
|
||||
- "In-band mode not supported in non SGMII mode!\n");
|
||||
+ "In-band mode not supported in non-SerDes modes!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Setup gmac */
|
||||
- if (mtk_is_netsys_v3_or_greater(eth) &&
|
||||
- mac->interface == PHY_INTERFACE_MODE_INTERNAL) {
|
||||
- mtk_w32(mac->hw, MTK_GDMA_XGDM_SEL, MTK_GDMA_EG_CTRL(mac->id));
|
||||
- mtk_w32(mac->hw, MAC_MCR_FORCE_LINK_DOWN, MTK_MAC_MCR(mac->id));
|
||||
+ if (mtk_is_netsys_v3_or_greater(eth)) {
|
||||
+ if (mtk_interface_mode_is_xgmii(state->interface)) {
|
||||
+ mtk_w32(mac->hw, MTK_GDMA_XGDM_SEL, MTK_GDMA_EG_CTRL(mac->id));
|
||||
+ mtk_w32(mac->hw, MAC_MCR_FORCE_LINK_DOWN, MTK_MAC_MCR(mac->id));
|
||||
+
|
||||
+ if (mac->id == MTK_GMAC1_ID)
|
||||
+ mtk_setup_bridge_switch(eth);
|
||||
+ } else {
|
||||
+ mtk_w32(eth, 0, MTK_GDMA_EG_CTRL(mac->id));
|
||||
|
||||
- mtk_setup_bridge_switch(eth);
|
||||
+ /* FIXME: In current hardware design, we have to reset FE
|
||||
+ * when swtiching XGDM to GDM. Therefore, here trigger an SER
|
||||
+ * to let GDM go back to the initial state.
|
||||
+ */
|
||||
+ if ((mtk_interface_mode_is_xgmii(mac->interface) ||
|
||||
+ mac->interface == PHY_INTERFACE_MODE_NA) &&
|
||||
+ !mtk_check_gmac23_idle(mac) &&
|
||||
+ !test_bit(MTK_RESETTING, ð->state))
|
||||
+ schedule_work(ð->pending_work);
|
||||
+ }
|
||||
}
|
||||
|
||||
+ mac->interface = state->interface;
|
||||
+
|
||||
return;
|
||||
|
||||
err_phy:
|
||||
@@ -669,6 +738,18 @@ init_err:
|
||||
mac->id, phy_modes(state->interface), err);
|
||||
}
|
||||
|
||||
+static int mtk_mac_prepare(struct phylink_config *config, unsigned int mode,
|
||||
+ phy_interface_t interface)
|
||||
+{
|
||||
+ struct mtk_mac *mac = container_of(config, struct mtk_mac,
|
||||
+ phylink_config);
|
||||
+
|
||||
+ if (mac->pextp && mac->interface != interface)
|
||||
+ phy_reset(mac->pextp);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int mtk_mac_finish(struct phylink_config *config, unsigned int mode,
|
||||
phy_interface_t interface)
|
||||
{
|
||||
@@ -677,6 +758,10 @@ static int mtk_mac_finish(struct phylink
|
||||
struct mtk_eth *eth = mac->hw;
|
||||
u32 mcr_cur, mcr_new;
|
||||
|
||||
+ /* Setup PMA/PMD */
|
||||
+ if (mac->pextp)
|
||||
+ phy_set_mode_ext(mac->pextp, PHY_MODE_ETHERNET, interface);
|
||||
+
|
||||
/* Enable SGMII */
|
||||
if (interface == PHY_INTERFACE_MODE_SGMII ||
|
||||
phy_interface_mode_is_8023z(interface))
|
||||
@@ -701,10 +786,14 @@ static void mtk_mac_link_down(struct phy
|
||||
{
|
||||
struct mtk_mac *mac = container_of(config, struct mtk_mac,
|
||||
phylink_config);
|
||||
- u32 mcr = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id));
|
||||
|
||||
- mcr &= ~(MAC_MCR_TX_EN | MAC_MCR_RX_EN | MAC_MCR_FORCE_LINK);
|
||||
- mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id));
|
||||
+ if (!mtk_interface_mode_is_xgmii(interface)) {
|
||||
+ mtk_m32(mac->hw, MAC_MCR_TX_EN | MAC_MCR_RX_EN | MAC_MCR_FORCE_LINK, 0, MTK_MAC_MCR(mac->id));
|
||||
+ if (mtk_is_netsys_v3_or_greater(mac->hw))
|
||||
+ mtk_m32(mac->hw, MTK_XGMAC_FORCE_LINK(mac->id), 0, MTK_XGMAC_STS(mac->id));
|
||||
+ } else if (mtk_is_netsys_v3_or_greater(mac->hw) && mac->id != MTK_GMAC1_ID) {
|
||||
+ mtk_m32(mac->hw, XMAC_MCR_TRX_DISABLE, XMAC_MCR_TRX_DISABLE, MTK_XMAC_MCR(mac->id));
|
||||
+ }
|
||||
}
|
||||
|
||||
static void mtk_set_queue_speed(struct mtk_eth *eth, unsigned int idx,
|
||||
@@ -776,13 +865,11 @@ static void mtk_set_queue_speed(struct m
|
||||
mtk_w32(eth, val, soc->reg_map->qdma.qtx_sch + ofs);
|
||||
}
|
||||
|
||||
-static void mtk_mac_link_up(struct phylink_config *config,
|
||||
- struct phy_device *phy,
|
||||
- unsigned int mode, phy_interface_t interface,
|
||||
- int speed, int duplex, bool tx_pause, bool rx_pause)
|
||||
+static void mtk_gdm_mac_link_up(struct mtk_mac *mac,
|
||||
+ struct phy_device *phy,
|
||||
+ unsigned int mode, phy_interface_t interface,
|
||||
+ int speed, int duplex, bool tx_pause, bool rx_pause)
|
||||
{
|
||||
- struct mtk_mac *mac = container_of(config, struct mtk_mac,
|
||||
- phylink_config);
|
||||
u32 mcr;
|
||||
|
||||
mcr = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id));
|
||||
@@ -816,9 +903,63 @@ static void mtk_mac_link_up(struct phyli
|
||||
mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id));
|
||||
}
|
||||
|
||||
+static void mtk_xgdm_mac_link_up(struct mtk_mac *mac,
|
||||
+ struct phy_device *phy,
|
||||
+ unsigned int mode, phy_interface_t interface,
|
||||
+ int speed, int duplex, bool tx_pause, bool rx_pause)
|
||||
+{
|
||||
+ u32 mcr, force_link = 0;
|
||||
+
|
||||
+ if (mac->id == MTK_GMAC1_ID)
|
||||
+ return;
|
||||
+
|
||||
+ /* Eliminate the interference(before link-up) caused by PHY noise */
|
||||
+ mtk_m32(mac->hw, XMAC_LOGIC_RST, 0, MTK_XMAC_LOGIC_RST(mac->id));
|
||||
+ mdelay(20);
|
||||
+ mtk_m32(mac->hw, XMAC_GLB_CNTCLR, XMAC_GLB_CNTCLR, MTK_XMAC_CNT_CTRL(mac->id));
|
||||
+
|
||||
+ if (mac->interface == PHY_INTERFACE_MODE_INTERNAL || mac->id == MTK_GMAC3_ID)
|
||||
+ force_link = MTK_XGMAC_FORCE_LINK(mac->id);
|
||||
+
|
||||
+ mtk_m32(mac->hw, MTK_XGMAC_FORCE_LINK(mac->id), force_link, MTK_XGMAC_STS(mac->id));
|
||||
+
|
||||
+ mcr = mtk_r32(mac->hw, MTK_XMAC_MCR(mac->id));
|
||||
+ mcr &= ~(XMAC_MCR_FORCE_TX_FC | XMAC_MCR_FORCE_RX_FC | XMAC_MCR_TRX_DISABLE);
|
||||
+ /* Configure pause modes -
|
||||
+ * phylink will avoid these for half duplex
|
||||
+ */
|
||||
+ if (tx_pause)
|
||||
+ mcr |= XMAC_MCR_FORCE_TX_FC;
|
||||
+ if (rx_pause)
|
||||
+ mcr |= XMAC_MCR_FORCE_RX_FC;
|
||||
+
|
||||
+ mtk_w32(mac->hw, mcr, MTK_XMAC_MCR(mac->id));
|
||||
+}
|
||||
+
|
||||
+static void mtk_mac_link_up(struct phylink_config *config,
|
||||
+ struct phy_device *phy,
|
||||
+ unsigned int mode, phy_interface_t interface,
|
||||
+ int speed, int duplex, bool tx_pause, bool rx_pause)
|
||||
+{
|
||||
+ struct mtk_mac *mac = container_of(config, struct mtk_mac,
|
||||
+ phylink_config);
|
||||
+
|
||||
+ if (mtk_is_netsys_v3_or_greater(mac->hw) && mtk_interface_mode_is_xgmii(interface))
|
||||
+ mtk_xgdm_mac_link_up(mac, phy, mode, interface, speed, duplex,
|
||||
+ tx_pause, rx_pause);
|
||||
+ else
|
||||
+ mtk_gdm_mac_link_up(mac, phy, mode, interface, speed, duplex,
|
||||
+ tx_pause, rx_pause);
|
||||
+
|
||||
+ /* Repeat pextp setup to tune link */
|
||||
+ if (mac->pextp)
|
||||
+ phy_set_mode_ext(mac->pextp, PHY_MODE_ETHERNET, interface);
|
||||
+}
|
||||
+
|
||||
static const struct phylink_mac_ops mtk_phylink_ops = {
|
||||
.mac_select_pcs = mtk_mac_select_pcs,
|
||||
.mac_config = mtk_mac_config,
|
||||
+ .mac_prepare = mtk_mac_prepare,
|
||||
.mac_finish = mtk_mac_finish,
|
||||
.mac_link_down = mtk_mac_link_down,
|
||||
.mac_link_up = mtk_mac_link_up,
|
||||
@@ -3417,6 +3558,9 @@ static int mtk_open(struct net_device *d
|
||||
|
||||
ppe_num = eth->soc->ppe_num;
|
||||
|
||||
+ if (mac->pextp)
|
||||
+ phy_power_on(mac->pextp);
|
||||
+
|
||||
err = phylink_of_phy_connect(mac->phylink, mac->of_node, 0);
|
||||
if (err) {
|
||||
netdev_err(dev, "%s: could not attach PHY: %d\n", __func__,
|
||||
@@ -3567,6 +3711,9 @@ static int mtk_stop(struct net_device *d
|
||||
for (i = 0; i < ARRAY_SIZE(eth->ppe); i++)
|
||||
mtk_ppe_stop(eth->ppe[i]);
|
||||
|
||||
+ if (mac->pextp)
|
||||
+ phy_power_off(mac->pextp);
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -4580,6 +4727,7 @@ static const struct net_device_ops mtk_n
|
||||
static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
|
||||
{
|
||||
const __be32 *_id = of_get_property(np, "reg", NULL);
|
||||
+ struct device_node *pcs_np;
|
||||
phy_interface_t phy_mode;
|
||||
struct phylink *phylink;
|
||||
struct mtk_mac *mac;
|
||||
@@ -4616,16 +4764,41 @@ static int mtk_add_mac(struct mtk_eth *e
|
||||
mac->id = id;
|
||||
mac->hw = eth;
|
||||
mac->of_node = np;
|
||||
+ pcs_np = of_parse_phandle(mac->of_node, "pcs-handle", 0);
|
||||
+ if (pcs_np) {
|
||||
+ mac->sgmii_pcs = mtk_pcs_lynxi_get(eth->dev, pcs_np);
|
||||
+ if (IS_ERR(mac->sgmii_pcs)) {
|
||||
+ if (PTR_ERR(mac->sgmii_pcs) == -EPROBE_DEFER)
|
||||
+ return -EPROBE_DEFER;
|
||||
|
||||
- err = of_get_ethdev_address(mac->of_node, eth->netdev[id]);
|
||||
- if (err == -EPROBE_DEFER)
|
||||
- return err;
|
||||
+ dev_err(eth->dev, "cannot select SGMII PCS, error %ld\n",
|
||||
+ PTR_ERR(mac->sgmii_pcs));
|
||||
+ return PTR_ERR(mac->sgmii_pcs);
|
||||
+ }
|
||||
+ }
|
||||
|
||||
- if (err) {
|
||||
- /* If the mac address is invalid, use random mac address */
|
||||
- eth_hw_addr_random(eth->netdev[id]);
|
||||
- dev_err(eth->dev, "generated random MAC address %pM\n",
|
||||
- eth->netdev[id]->dev_addr);
|
||||
+ pcs_np = of_parse_phandle(mac->of_node, "pcs-handle", 1);
|
||||
+ if (pcs_np) {
|
||||
+ mac->usxgmii_pcs = mtk_usxgmii_pcs_get(eth->dev, pcs_np);
|
||||
+ if (IS_ERR(mac->usxgmii_pcs)) {
|
||||
+ if (PTR_ERR(mac->usxgmii_pcs) == -EPROBE_DEFER)
|
||||
+ return -EPROBE_DEFER;
|
||||
+
|
||||
+ dev_err(eth->dev, "cannot select USXGMII PCS, error %ld\n",
|
||||
+ PTR_ERR(mac->usxgmii_pcs));
|
||||
+ return PTR_ERR(mac->usxgmii_pcs);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (mtk_is_netsys_v3_or_greater(eth) && (mac->sgmii_pcs || mac->usxgmii_pcs)) {
|
||||
+ mac->pextp = devm_of_phy_get(eth->dev, mac->of_node, NULL);
|
||||
+ if (IS_ERR(mac->pextp)) {
|
||||
+ if (PTR_ERR(mac->pextp) != -EPROBE_DEFER)
|
||||
+ dev_err(eth->dev, "cannot get PHY, error %ld\n",
|
||||
+ PTR_ERR(mac->pextp));
|
||||
+
|
||||
+ return PTR_ERR(mac->pextp);
|
||||
+ }
|
||||
}
|
||||
|
||||
memset(mac->hwlro_ip, 0, sizeof(mac->hwlro_ip));
|
||||
@@ -4708,8 +4881,21 @@ static int mtk_add_mac(struct mtk_eth *e
|
||||
phy_interface_zero(mac->phylink_config.supported_interfaces);
|
||||
__set_bit(PHY_INTERFACE_MODE_INTERNAL,
|
||||
mac->phylink_config.supported_interfaces);
|
||||
+ } else if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_USXGMII)) {
|
||||
+ mac->phylink_config.mac_capabilities |= MAC_5000FD | MAC_10000FD;
|
||||
+ __set_bit(PHY_INTERFACE_MODE_5GBASER,
|
||||
+ mac->phylink_config.supported_interfaces);
|
||||
+ __set_bit(PHY_INTERFACE_MODE_10GBASER,
|
||||
+ mac->phylink_config.supported_interfaces);
|
||||
+ __set_bit(PHY_INTERFACE_MODE_USXGMII,
|
||||
+ mac->phylink_config.supported_interfaces);
|
||||
}
|
||||
|
||||
+ if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_2P5GPHY) &&
|
||||
+ id == MTK_GMAC2_ID)
|
||||
+ __set_bit(PHY_INTERFACE_MODE_INTERNAL,
|
||||
+ mac->phylink_config.supported_interfaces);
|
||||
+
|
||||
phylink = phylink_create(&mac->phylink_config,
|
||||
of_fwnode_handle(mac->of_node),
|
||||
phy_mode, &mtk_phylink_ops);
|
||||
@@ -4760,6 +4946,26 @@ free_netdev:
|
||||
return err;
|
||||
}
|
||||
|
||||
+static int mtk_mac_assign_address(struct mtk_eth *eth, int i, bool test_defer_only)
|
||||
+{
|
||||
+ int err = of_get_ethdev_address(eth->mac[i]->of_node, eth->netdev[i]);
|
||||
+
|
||||
+ if (err == -EPROBE_DEFER)
|
||||
+ return err;
|
||||
+
|
||||
+ if (test_defer_only)
|
||||
+ return 0;
|
||||
+
|
||||
+ if (err) {
|
||||
+ /* If the mac address is invalid, use random mac address */
|
||||
+ eth_hw_addr_random(eth->netdev[i]);
|
||||
+ dev_err(eth->dev, "generated random MAC address %pM\n",
|
||||
+ eth->netdev[i]);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
void mtk_eth_set_dma_device(struct mtk_eth *eth, struct device *dma_dev)
|
||||
{
|
||||
struct net_device *dev, *tmp;
|
||||
@@ -4906,7 +5112,8 @@ static int mtk_probe(struct platform_dev
|
||||
regmap_write(cci, 0, 3);
|
||||
}
|
||||
|
||||
- if (MTK_HAS_CAPS(eth->soc->caps, MTK_SGMII)) {
|
||||
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_SGMII) &&
|
||||
+ !mtk_is_netsys_v3_or_greater(eth)) {
|
||||
err = mtk_sgmii_init(eth);
|
||||
|
||||
if (err)
|
||||
@@ -5017,6 +5224,24 @@ static int mtk_probe(struct platform_dev
|
||||
}
|
||||
}
|
||||
|
||||
+ for (i = 0; i < MTK_MAX_DEVS; i++) {
|
||||
+ if (!eth->netdev[i])
|
||||
+ continue;
|
||||
+
|
||||
+ err = mtk_mac_assign_address(eth, i, true);
|
||||
+ if (err)
|
||||
+ goto err_deinit_hw;
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < MTK_MAX_DEVS; i++) {
|
||||
+ if (!eth->netdev[i])
|
||||
+ continue;
|
||||
+
|
||||
+ err = mtk_mac_assign_address(eth, i, false);
|
||||
+ if (err)
|
||||
+ goto err_deinit_hw;
|
||||
+ }
|
||||
+
|
||||
if (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_INT)) {
|
||||
err = devm_request_irq(eth->dev, eth->irq[0],
|
||||
mtk_handle_irq, 0,
|
||||
@@ -5127,6 +5352,11 @@ static void mtk_remove(struct platform_d
|
||||
mtk_stop(eth->netdev[i]);
|
||||
mac = netdev_priv(eth->netdev[i]);
|
||||
phylink_disconnect_phy(mac->phylink);
|
||||
+ if (mac->sgmii_pcs)
|
||||
+ mtk_pcs_lynxi_put(mac->sgmii_pcs);
|
||||
+
|
||||
+ if (mac->usxgmii_pcs)
|
||||
+ mtk_usxgmii_pcs_put(mac->usxgmii_pcs);
|
||||
}
|
||||
|
||||
mtk_wed_exit();
|
||||
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
||||
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <linux/u64_stats_sync.h>
|
||||
#include <linux/refcount.h>
|
||||
#include <linux/phylink.h>
|
||||
+#include <linux/reset.h>
|
||||
#include <linux/rhashtable.h>
|
||||
#include <linux/dim.h>
|
||||
#include <linux/bitfield.h>
|
||||
@@ -505,6 +506,21 @@
|
||||
#define INTF_MODE_RGMII_1000 (TRGMII_MODE | TRGMII_CENTRAL_ALIGNED)
|
||||
#define INTF_MODE_RGMII_10_100 0
|
||||
|
||||
+/* XFI Mac control registers */
|
||||
+#define MTK_XMAC_BASE(x) (0x12000 + (((x) - 1) * 0x1000))
|
||||
+#define MTK_XMAC_MCR(x) (MTK_XMAC_BASE(x))
|
||||
+#define XMAC_MCR_TRX_DISABLE 0xf
|
||||
+#define XMAC_MCR_FORCE_TX_FC BIT(5)
|
||||
+#define XMAC_MCR_FORCE_RX_FC BIT(4)
|
||||
+
|
||||
+/* XFI Mac logic reset registers */
|
||||
+#define MTK_XMAC_LOGIC_RST(x) (MTK_XMAC_BASE(x) + 0x10)
|
||||
+#define XMAC_LOGIC_RST BIT(0)
|
||||
+
|
||||
+/* XFI Mac count global control */
|
||||
+#define MTK_XMAC_CNT_CTRL(x) (MTK_XMAC_BASE(x) + 0x100)
|
||||
+#define XMAC_GLB_CNTCLR BIT(0)
|
||||
+
|
||||
/* GPIO port control registers for GMAC 2*/
|
||||
#define GPIO_OD33_CTRL8 0x4c0
|
||||
#define GPIO_BIAS_CTRL 0xed0
|
||||
@@ -530,6 +546,7 @@
|
||||
#define SYSCFG0_SGMII_GMAC2 ((3 << 8) & SYSCFG0_SGMII_MASK)
|
||||
#define SYSCFG0_SGMII_GMAC1_V2 BIT(9)
|
||||
#define SYSCFG0_SGMII_GMAC2_V2 BIT(8)
|
||||
+#define SYSCFG0_SGMII_GMAC3_V2 BIT(7)
|
||||
|
||||
|
||||
/* ethernet subsystem clock register */
|
||||
@@ -568,6 +585,11 @@
|
||||
#define GEPHY_MAC_SEL BIT(1)
|
||||
|
||||
/* Top misc registers */
|
||||
+#define TOP_MISC_NETSYS_PCS_MUX 0x84
|
||||
+#define NETSYS_PCS_MUX_MASK GENMASK(1, 0)
|
||||
+#define MUX_G2_USXGMII_SEL BIT(1)
|
||||
+#define MUX_HSGMII1_G1_SEL BIT(0)
|
||||
+
|
||||
#define USB_PHY_SWITCH_REG 0x218
|
||||
#define QPHY_SEL_MASK GENMASK(1, 0)
|
||||
#define SGMII_QPHY_SEL 0x2
|
||||
@@ -592,6 +614,8 @@
|
||||
#define MT7628_SDM_RBCNT (MT7628_SDM_OFFSET + 0x10c)
|
||||
#define MT7628_SDM_CS_ERR (MT7628_SDM_OFFSET + 0x110)
|
||||
|
||||
+/* Debug Purpose Register */
|
||||
+#define MTK_PSE_FQFC_CFG 0x100
|
||||
#define MTK_FE_CDM1_FSM 0x220
|
||||
#define MTK_FE_CDM2_FSM 0x224
|
||||
#define MTK_FE_CDM3_FSM 0x238
|
||||
@@ -600,6 +624,11 @@
|
||||
#define MTK_FE_CDM6_FSM 0x328
|
||||
#define MTK_FE_GDM1_FSM 0x228
|
||||
#define MTK_FE_GDM2_FSM 0x22C
|
||||
+#define MTK_FE_GDM3_FSM 0x23C
|
||||
+#define MTK_FE_PSE_FREE 0x240
|
||||
+#define MTK_FE_DROP_FQ 0x244
|
||||
+#define MTK_FE_DROP_FC 0x248
|
||||
+#define MTK_FE_DROP_PPE 0x24C
|
||||
|
||||
#define MTK_MAC_FSM(x) (0x1010C + ((x) * 0x100))
|
||||
|
||||
@@ -932,6 +961,8 @@ enum mkt_eth_capabilities {
|
||||
MTK_RGMII_BIT = 0,
|
||||
MTK_TRGMII_BIT,
|
||||
MTK_SGMII_BIT,
|
||||
+ MTK_USXGMII_BIT,
|
||||
+ MTK_2P5GPHY_BIT,
|
||||
MTK_ESW_BIT,
|
||||
MTK_GEPHY_BIT,
|
||||
MTK_MUX_BIT,
|
||||
@@ -952,8 +983,11 @@ enum mkt_eth_capabilities {
|
||||
MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT,
|
||||
MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY_BIT,
|
||||
MTK_ETH_MUX_U3_GMAC2_TO_QPHY_BIT,
|
||||
+ MTK_ETH_MUX_GMAC2_TO_2P5GPHY_BIT,
|
||||
MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII_BIT,
|
||||
MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII_BIT,
|
||||
+ MTK_ETH_MUX_GMAC123_TO_GEPHY_SGMII_BIT,
|
||||
+ MTK_ETH_MUX_GMAC123_TO_USXGMII_BIT,
|
||||
|
||||
/* PATH BITS */
|
||||
MTK_ETH_PATH_GMAC1_RGMII_BIT,
|
||||
@@ -961,14 +995,21 @@ enum mkt_eth_capabilities {
|
||||
MTK_ETH_PATH_GMAC1_SGMII_BIT,
|
||||
MTK_ETH_PATH_GMAC2_RGMII_BIT,
|
||||
MTK_ETH_PATH_GMAC2_SGMII_BIT,
|
||||
+ MTK_ETH_PATH_GMAC2_2P5GPHY_BIT,
|
||||
MTK_ETH_PATH_GMAC2_GEPHY_BIT,
|
||||
+ MTK_ETH_PATH_GMAC3_SGMII_BIT,
|
||||
MTK_ETH_PATH_GDM1_ESW_BIT,
|
||||
+ MTK_ETH_PATH_GMAC1_USXGMII_BIT,
|
||||
+ MTK_ETH_PATH_GMAC2_USXGMII_BIT,
|
||||
+ MTK_ETH_PATH_GMAC3_USXGMII_BIT,
|
||||
};
|
||||
|
||||
/* Supported hardware group on SoCs */
|
||||
#define MTK_RGMII BIT_ULL(MTK_RGMII_BIT)
|
||||
#define MTK_TRGMII BIT_ULL(MTK_TRGMII_BIT)
|
||||
#define MTK_SGMII BIT_ULL(MTK_SGMII_BIT)
|
||||
+#define MTK_USXGMII BIT_ULL(MTK_USXGMII_BIT)
|
||||
+#define MTK_2P5GPHY BIT_ULL(MTK_2P5GPHY_BIT)
|
||||
#define MTK_ESW BIT_ULL(MTK_ESW_BIT)
|
||||
#define MTK_GEPHY BIT_ULL(MTK_GEPHY_BIT)
|
||||
#define MTK_MUX BIT_ULL(MTK_MUX_BIT)
|
||||
@@ -991,10 +1032,16 @@ enum mkt_eth_capabilities {
|
||||
BIT_ULL(MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY_BIT)
|
||||
#define MTK_ETH_MUX_U3_GMAC2_TO_QPHY \
|
||||
BIT_ULL(MTK_ETH_MUX_U3_GMAC2_TO_QPHY_BIT)
|
||||
+#define MTK_ETH_MUX_GMAC2_TO_2P5GPHY \
|
||||
+ BIT_ULL(MTK_ETH_MUX_GMAC2_TO_2P5GPHY_BIT)
|
||||
#define MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII \
|
||||
BIT_ULL(MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII_BIT)
|
||||
#define MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII \
|
||||
BIT_ULL(MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII_BIT)
|
||||
+#define MTK_ETH_MUX_GMAC123_TO_GEPHY_SGMII \
|
||||
+ BIT_ULL(MTK_ETH_MUX_GMAC123_TO_GEPHY_SGMII_BIT)
|
||||
+#define MTK_ETH_MUX_GMAC123_TO_USXGMII \
|
||||
+ BIT_ULL(MTK_ETH_MUX_GMAC123_TO_USXGMII_BIT)
|
||||
|
||||
/* Supported path present on SoCs */
|
||||
#define MTK_ETH_PATH_GMAC1_RGMII BIT_ULL(MTK_ETH_PATH_GMAC1_RGMII_BIT)
|
||||
@@ -1002,8 +1049,13 @@ enum mkt_eth_capabilities {
|
||||
#define MTK_ETH_PATH_GMAC1_SGMII BIT_ULL(MTK_ETH_PATH_GMAC1_SGMII_BIT)
|
||||
#define MTK_ETH_PATH_GMAC2_RGMII BIT_ULL(MTK_ETH_PATH_GMAC2_RGMII_BIT)
|
||||
#define MTK_ETH_PATH_GMAC2_SGMII BIT_ULL(MTK_ETH_PATH_GMAC2_SGMII_BIT)
|
||||
+#define MTK_ETH_PATH_GMAC2_2P5GPHY BIT_ULL(MTK_ETH_PATH_GMAC2_2P5GPHY_BIT)
|
||||
#define MTK_ETH_PATH_GMAC2_GEPHY BIT_ULL(MTK_ETH_PATH_GMAC2_GEPHY_BIT)
|
||||
+#define MTK_ETH_PATH_GMAC3_SGMII BIT_ULL(MTK_ETH_PATH_GMAC3_SGMII_BIT)
|
||||
#define MTK_ETH_PATH_GDM1_ESW BIT_ULL(MTK_ETH_PATH_GDM1_ESW_BIT)
|
||||
+#define MTK_ETH_PATH_GMAC1_USXGMII BIT_ULL(MTK_ETH_PATH_GMAC1_USXGMII_BIT)
|
||||
+#define MTK_ETH_PATH_GMAC2_USXGMII BIT_ULL(MTK_ETH_PATH_GMAC2_USXGMII_BIT)
|
||||
+#define MTK_ETH_PATH_GMAC3_USXGMII BIT_ULL(MTK_ETH_PATH_GMAC3_USXGMII_BIT)
|
||||
|
||||
#define MTK_GMAC1_RGMII (MTK_ETH_PATH_GMAC1_RGMII | MTK_RGMII)
|
||||
#define MTK_GMAC1_TRGMII (MTK_ETH_PATH_GMAC1_TRGMII | MTK_TRGMII)
|
||||
@@ -1011,7 +1063,12 @@ enum mkt_eth_capabilities {
|
||||
#define MTK_GMAC2_RGMII (MTK_ETH_PATH_GMAC2_RGMII | MTK_RGMII)
|
||||
#define MTK_GMAC2_SGMII (MTK_ETH_PATH_GMAC2_SGMII | MTK_SGMII)
|
||||
#define MTK_GMAC2_GEPHY (MTK_ETH_PATH_GMAC2_GEPHY | MTK_GEPHY)
|
||||
+#define MTK_GMAC2_2P5GPHY (MTK_ETH_PATH_GMAC2_2P5GPHY | MTK_2P5GPHY)
|
||||
+#define MTK_GMAC3_SGMII (MTK_ETH_PATH_GMAC3_SGMII | MTK_SGMII)
|
||||
#define MTK_GDM1_ESW (MTK_ETH_PATH_GDM1_ESW | MTK_ESW)
|
||||
+#define MTK_GMAC1_USXGMII (MTK_ETH_PATH_GMAC1_USXGMII | MTK_USXGMII)
|
||||
+#define MTK_GMAC2_USXGMII (MTK_ETH_PATH_GMAC2_USXGMII | MTK_USXGMII)
|
||||
+#define MTK_GMAC3_USXGMII (MTK_ETH_PATH_GMAC3_USXGMII | MTK_USXGMII)
|
||||
|
||||
/* MUXes present on SoCs */
|
||||
/* 0: GDM1 -> GMAC1, 1: GDM1 -> ESW */
|
||||
@@ -1030,10 +1087,20 @@ enum mkt_eth_capabilities {
|
||||
(MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII | MTK_MUX | \
|
||||
MTK_SHARED_SGMII)
|
||||
|
||||
+/* 2: GMAC2 -> XGMII */
|
||||
+#define MTK_MUX_GMAC2_TO_2P5GPHY \
|
||||
+ (MTK_ETH_MUX_GMAC2_TO_2P5GPHY | MTK_MUX | MTK_INFRA)
|
||||
+
|
||||
/* 0: GMACx -> GEPHY, 1: GMACx -> SGMII where x is 1 or 2 */
|
||||
#define MTK_MUX_GMAC12_TO_GEPHY_SGMII \
|
||||
(MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII | MTK_MUX)
|
||||
|
||||
+#define MTK_MUX_GMAC123_TO_GEPHY_SGMII \
|
||||
+ (MTK_ETH_MUX_GMAC123_TO_GEPHY_SGMII | MTK_MUX)
|
||||
+
|
||||
+#define MTK_MUX_GMAC123_TO_USXGMII \
|
||||
+ (MTK_ETH_MUX_GMAC123_TO_USXGMII | MTK_MUX | MTK_INFRA)
|
||||
+
|
||||
#define MTK_HAS_CAPS(caps, _x) (((caps) & (_x)) == (_x))
|
||||
|
||||
#define MT7621_CAPS (MTK_GMAC1_RGMII | MTK_GMAC1_TRGMII | \
|
||||
@@ -1065,8 +1132,12 @@ enum mkt_eth_capabilities {
|
||||
MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \
|
||||
MTK_RSTCTRL_PPE1 | MTK_SRAM)
|
||||
|
||||
-#define MT7988_CAPS (MTK_36BIT_DMA | MTK_GDM1_ESW | MTK_QDMA | \
|
||||
- MTK_RSTCTRL_PPE1 | MTK_RSTCTRL_PPE2 | MTK_SRAM)
|
||||
+#define MT7988_CAPS (MTK_36BIT_DMA | MTK_GDM1_ESW | MTK_GMAC1_SGMII | \
|
||||
+ MTK_GMAC2_2P5GPHY | MTK_GMAC2_SGMII | MTK_GMAC2_USXGMII | \
|
||||
+ MTK_GMAC3_SGMII | MTK_GMAC3_USXGMII | \
|
||||
+ MTK_MUX_GMAC123_TO_GEPHY_SGMII | \
|
||||
+ MTK_MUX_GMAC123_TO_USXGMII | MTK_MUX_GMAC2_TO_2P5GPHY | \
|
||||
+ MTK_QDMA | MTK_RSTCTRL_PPE1 | MTK_RSTCTRL_PPE2 | MTK_SRAM)
|
||||
|
||||
struct mtk_tx_dma_desc_info {
|
||||
dma_addr_t addr;
|
||||
@@ -1311,6 +1382,9 @@ struct mtk_mac {
|
||||
struct device_node *of_node;
|
||||
struct phylink *phylink;
|
||||
struct phylink_config phylink_config;
|
||||
+ struct phylink_pcs *sgmii_pcs;
|
||||
+ struct phylink_pcs *usxgmii_pcs;
|
||||
+ struct phy *pextp;
|
||||
struct mtk_eth *hw;
|
||||
struct mtk_hw_stats *hw_stats;
|
||||
__be32 hwlro_ip[MTK_MAX_LRO_IP_CNT];
|
||||
@@ -1434,6 +1508,19 @@ static inline u32 mtk_get_ib2_multicast_
|
||||
return MTK_FOE_IB2_MULTICAST;
|
||||
}
|
||||
|
||||
+static inline bool mtk_interface_mode_is_xgmii(phy_interface_t interface)
|
||||
+{
|
||||
+ switch (interface) {
|
||||
+ case PHY_INTERFACE_MODE_INTERNAL:
|
||||
+ case PHY_INTERFACE_MODE_USXGMII:
|
||||
+ case PHY_INTERFACE_MODE_10GBASER:
|
||||
+ case PHY_INTERFACE_MODE_5GBASER:
|
||||
+ return true;
|
||||
+ default:
|
||||
+ return false;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/* read the hardware status register */
|
||||
void mtk_stats_update_mac(struct mtk_mac *mac);
|
||||
|
||||
@@ -1442,8 +1529,10 @@ u32 mtk_r32(struct mtk_eth *eth, unsigne
|
||||
u32 mtk_m32(struct mtk_eth *eth, u32 mask, u32 set, unsigned int reg);
|
||||
|
||||
int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id);
|
||||
+int mtk_gmac_2p5gphy_path_setup(struct mtk_eth *eth, int mac_id);
|
||||
int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id);
|
||||
int mtk_gmac_rgmii_path_setup(struct mtk_eth *eth, int mac_id);
|
||||
+int mtk_gmac_usxgmii_path_setup(struct mtk_eth *eth, int mac_id);
|
||||
|
||||
int mtk_eth_offload_init(struct mtk_eth *eth, u8 id);
|
||||
int mtk_eth_setup_tc(struct net_device *dev, enum tc_setup_type type,
|
|
@ -0,0 +1,369 @@
|
|||
From 4b1a2716299c0e96a698044aebf3f80513509ae7 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Golle <daniel@makrotopia.org>
|
||||
Date: Tue, 12 Dec 2023 03:47:18 +0000
|
||||
Subject: [PATCH 3/5] net: pcs: pcs-mtk-lynxi: add platform driver for MT7988
|
||||
|
||||
Introduce a proper platform MFD driver for the LynxI (H)SGMII PCS which
|
||||
is going to initially be used for the MT7988 SoC.
|
||||
|
||||
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
---
|
||||
drivers/net/pcs/pcs-mtk-lynxi.c | 227 ++++++++++++++++++++++++++++--
|
||||
include/linux/pcs/pcs-mtk-lynxi.h | 11 ++
|
||||
2 files changed, 227 insertions(+), 11 deletions(-)
|
||||
|
||||
--- a/drivers/net/pcs/pcs-mtk-lynxi.c
|
||||
+++ b/drivers/net/pcs/pcs-mtk-lynxi.c
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
// Copyright (c) 2018-2019 MediaTek Inc.
|
||||
-/* A library for MediaTek SGMII circuit
|
||||
+/* A library and platform driver for the MediaTek LynxI SGMII circuit
|
||||
*
|
||||
* Author: Sean Wang <sean.wang@mediatek.com>
|
||||
* Author: Alexander Couzens <lynxis@fe80.eu>
|
||||
@@ -8,11 +8,17 @@
|
||||
*
|
||||
*/
|
||||
|
||||
+#include <linux/clk.h>
|
||||
#include <linux/mdio.h>
|
||||
+#include <linux/mfd/syscon.h>
|
||||
+#include <linux/mutex.h>
|
||||
#include <linux/of.h>
|
||||
+#include <linux/of_platform.h>
|
||||
#include <linux/pcs/pcs-mtk-lynxi.h>
|
||||
#include <linux/phylink.h>
|
||||
+#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
+#include <linux/reset.h>
|
||||
|
||||
/* SGMII subsystem config registers */
|
||||
/* BMCR (low 16) BMSR (high 16) */
|
||||
@@ -65,6 +71,8 @@
|
||||
#define SGMII_PN_SWAP_MASK GENMASK(1, 0)
|
||||
#define SGMII_PN_SWAP_TX_RX (BIT(0) | BIT(1))
|
||||
|
||||
+#define MTK_NETSYS_V3_AMA_RGC3 0x128
|
||||
+
|
||||
/* struct mtk_pcs_lynxi - This structure holds each sgmii regmap andassociated
|
||||
* data
|
||||
* @regmap: The register map pointing at the range used to setup
|
||||
@@ -74,15 +82,29 @@
|
||||
* @interface: Currently configured interface mode
|
||||
* @pcs: Phylink PCS structure
|
||||
* @flags: Flags indicating hardware properties
|
||||
+ * @rstc: Reset controller
|
||||
+ * @sgmii_sel: SGMII Register Clock
|
||||
+ * @sgmii_rx: SGMII RX Clock
|
||||
+ * @sgmii_tx: SGMII TX Clock
|
||||
+ * @node: List node
|
||||
*/
|
||||
struct mtk_pcs_lynxi {
|
||||
struct regmap *regmap;
|
||||
+ struct device *dev;
|
||||
u32 ana_rgc3;
|
||||
phy_interface_t interface;
|
||||
struct phylink_pcs pcs;
|
||||
u32 flags;
|
||||
+ struct reset_control *rstc;
|
||||
+ struct clk *sgmii_sel;
|
||||
+ struct clk *sgmii_rx;
|
||||
+ struct clk *sgmii_tx;
|
||||
+ struct list_head node;
|
||||
};
|
||||
|
||||
+static LIST_HEAD(mtk_pcs_lynxi_instances);
|
||||
+static DEFINE_MUTEX(instance_mutex);
|
||||
+
|
||||
static struct mtk_pcs_lynxi *pcs_to_mtk_pcs_lynxi(struct phylink_pcs *pcs)
|
||||
{
|
||||
return container_of(pcs, struct mtk_pcs_lynxi, pcs);
|
||||
@@ -102,6 +124,17 @@ static void mtk_pcs_lynxi_get_state(stru
|
||||
FIELD_GET(SGMII_LPA, adv));
|
||||
}
|
||||
|
||||
+static void mtk_sgmii_reset(struct mtk_pcs_lynxi *mpcs)
|
||||
+{
|
||||
+ if (!mpcs->rstc)
|
||||
+ return;
|
||||
+
|
||||
+ reset_control_assert(mpcs->rstc);
|
||||
+ udelay(100);
|
||||
+ reset_control_deassert(mpcs->rstc);
|
||||
+ mdelay(1);
|
||||
+}
|
||||
+
|
||||
static int mtk_pcs_lynxi_config(struct phylink_pcs *pcs, unsigned int neg_mode,
|
||||
phy_interface_t interface,
|
||||
const unsigned long *advertising,
|
||||
@@ -147,6 +180,7 @@ static int mtk_pcs_lynxi_config(struct p
|
||||
SGMII_PHYA_PWD);
|
||||
|
||||
/* Reset SGMII PCS state */
|
||||
+ mtk_sgmii_reset(mpcs);
|
||||
regmap_set_bits(mpcs->regmap, SGMSYS_RESERVED_0,
|
||||
SGMII_SW_RESET);
|
||||
|
||||
@@ -233,10 +267,29 @@ static void mtk_pcs_lynxi_link_up(struct
|
||||
}
|
||||
}
|
||||
|
||||
+static int mtk_pcs_lynxi_enable(struct phylink_pcs *pcs)
|
||||
+{
|
||||
+ struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs);
|
||||
+
|
||||
+ if (mpcs->sgmii_tx && mpcs->sgmii_rx) {
|
||||
+ clk_prepare_enable(mpcs->sgmii_rx);
|
||||
+ clk_prepare_enable(mpcs->sgmii_tx);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static void mtk_pcs_lynxi_disable(struct phylink_pcs *pcs)
|
||||
{
|
||||
struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs);
|
||||
|
||||
+ regmap_set_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, SGMII_PHYA_PWD);
|
||||
+
|
||||
+ if (mpcs->sgmii_tx && mpcs->sgmii_rx) {
|
||||
+ clk_disable_unprepare(mpcs->sgmii_tx);
|
||||
+ clk_disable_unprepare(mpcs->sgmii_rx);
|
||||
+ }
|
||||
+
|
||||
mpcs->interface = PHY_INTERFACE_MODE_NA;
|
||||
}
|
||||
|
||||
@@ -246,11 +299,12 @@ static const struct phylink_pcs_ops mtk_
|
||||
.pcs_an_restart = mtk_pcs_lynxi_restart_an,
|
||||
.pcs_link_up = mtk_pcs_lynxi_link_up,
|
||||
.pcs_disable = mtk_pcs_lynxi_disable,
|
||||
+ .pcs_enable = mtk_pcs_lynxi_enable,
|
||||
};
|
||||
|
||||
-struct phylink_pcs *mtk_pcs_lynxi_create(struct device *dev,
|
||||
- struct regmap *regmap, u32 ana_rgc3,
|
||||
- u32 flags)
|
||||
+static struct phylink_pcs *mtk_pcs_lynxi_init(struct device *dev, struct regmap *regmap,
|
||||
+ u32 ana_rgc3, u32 flags,
|
||||
+ struct mtk_pcs_lynxi *prealloc)
|
||||
{
|
||||
struct mtk_pcs_lynxi *mpcs;
|
||||
u32 id, ver;
|
||||
@@ -258,29 +312,33 @@ struct phylink_pcs *mtk_pcs_lynxi_create
|
||||
|
||||
ret = regmap_read(regmap, SGMSYS_PCS_DEVICE_ID, &id);
|
||||
if (ret < 0)
|
||||
- return NULL;
|
||||
+ return ERR_PTR(ret);
|
||||
|
||||
if (id != SGMII_LYNXI_DEV_ID) {
|
||||
dev_err(dev, "unknown PCS device id %08x\n", id);
|
||||
- return NULL;
|
||||
+ return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
ret = regmap_read(regmap, SGMSYS_PCS_SCRATCH, &ver);
|
||||
if (ret < 0)
|
||||
- return NULL;
|
||||
+ return ERR_PTR(ret);
|
||||
|
||||
ver = FIELD_GET(SGMII_DEV_VERSION, ver);
|
||||
if (ver != 0x1) {
|
||||
dev_err(dev, "unknown PCS device version %04x\n", ver);
|
||||
- return NULL;
|
||||
+ return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
dev_dbg(dev, "MediaTek LynxI SGMII PCS (id 0x%08x, ver 0x%04x)\n", id,
|
||||
ver);
|
||||
|
||||
- mpcs = kzalloc(sizeof(*mpcs), GFP_KERNEL);
|
||||
- if (!mpcs)
|
||||
- return NULL;
|
||||
+ if (prealloc) {
|
||||
+ mpcs = prealloc;
|
||||
+ } else {
|
||||
+ mpcs = kzalloc(sizeof(*mpcs), GFP_KERNEL);
|
||||
+ if (!mpcs)
|
||||
+ return ERR_PTR(-ENOMEM);
|
||||
+ };
|
||||
|
||||
mpcs->ana_rgc3 = ana_rgc3;
|
||||
mpcs->regmap = regmap;
|
||||
@@ -291,6 +349,13 @@ struct phylink_pcs *mtk_pcs_lynxi_create
|
||||
mpcs->interface = PHY_INTERFACE_MODE_NA;
|
||||
|
||||
return &mpcs->pcs;
|
||||
+};
|
||||
+
|
||||
+struct phylink_pcs *mtk_pcs_lynxi_create(struct device *dev,
|
||||
+ struct regmap *regmap, u32 ana_rgc3,
|
||||
+ u32 flags)
|
||||
+{
|
||||
+ return mtk_pcs_lynxi_init(dev, regmap, ana_rgc3, flags, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL(mtk_pcs_lynxi_create);
|
||||
|
||||
@@ -303,5 +368,142 @@ void mtk_pcs_lynxi_destroy(struct phylin
|
||||
}
|
||||
EXPORT_SYMBOL(mtk_pcs_lynxi_destroy);
|
||||
|
||||
+static int mtk_pcs_lynxi_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct device *dev = &pdev->dev;
|
||||
+ struct device_node *np = dev->of_node;
|
||||
+ struct mtk_pcs_lynxi *mpcs;
|
||||
+ struct phylink_pcs *pcs;
|
||||
+ struct regmap *regmap;
|
||||
+ u32 flags = 0;
|
||||
+
|
||||
+ mpcs = devm_kzalloc(dev, sizeof(*mpcs), GFP_KERNEL);
|
||||
+ if (!mpcs)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ mpcs->dev = dev;
|
||||
+ regmap = syscon_node_to_regmap(np->parent);
|
||||
+ if (IS_ERR(regmap))
|
||||
+ return PTR_ERR(regmap);
|
||||
+
|
||||
+ if (of_property_read_bool(np->parent, "mediatek,pnswap"))
|
||||
+ flags |= MTK_SGMII_FLAG_PN_SWAP;
|
||||
+
|
||||
+ mpcs->rstc = of_reset_control_get_shared(np->parent, NULL);
|
||||
+ if (IS_ERR(mpcs->rstc))
|
||||
+ return PTR_ERR(mpcs->rstc);
|
||||
+
|
||||
+ reset_control_deassert(mpcs->rstc);
|
||||
+ mpcs->sgmii_sel = devm_clk_get_enabled(dev, "sgmii_sel");
|
||||
+ if (IS_ERR(mpcs->sgmii_sel))
|
||||
+ return PTR_ERR(mpcs->sgmii_sel);
|
||||
+
|
||||
+ mpcs->sgmii_rx = devm_clk_get(dev, "sgmii_rx");
|
||||
+ if (IS_ERR(mpcs->sgmii_rx))
|
||||
+ return PTR_ERR(mpcs->sgmii_rx);
|
||||
+
|
||||
+ mpcs->sgmii_tx = devm_clk_get(dev, "sgmii_tx");
|
||||
+ if (IS_ERR(mpcs->sgmii_tx))
|
||||
+ return PTR_ERR(mpcs->sgmii_tx);
|
||||
+
|
||||
+ pcs = mtk_pcs_lynxi_init(dev, regmap, (uintptr_t)of_device_get_match_data(dev),
|
||||
+ flags, mpcs);
|
||||
+ if (IS_ERR(pcs))
|
||||
+ return PTR_ERR(pcs);
|
||||
+
|
||||
+ regmap_set_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, SGMII_PHYA_PWD);
|
||||
+
|
||||
+ platform_set_drvdata(pdev, mpcs);
|
||||
+
|
||||
+ mutex_lock(&instance_mutex);
|
||||
+ list_add_tail(&mpcs->node, &mtk_pcs_lynxi_instances);
|
||||
+ mutex_unlock(&instance_mutex);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void mtk_pcs_lynxi_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct device *dev = &pdev->dev;
|
||||
+ struct mtk_pcs_lynxi *cur, *tmp;
|
||||
+
|
||||
+ mutex_lock(&instance_mutex);
|
||||
+ list_for_each_entry_safe(cur, tmp, &mtk_pcs_lynxi_instances, node)
|
||||
+ if (cur->dev == dev) {
|
||||
+ list_del(&cur->node);
|
||||
+ kfree(cur);
|
||||
+ break;
|
||||
+ }
|
||||
+ mutex_unlock(&instance_mutex);
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id mtk_pcs_lynxi_of_match[] = {
|
||||
+ { .compatible = "mediatek,mt7988-sgmii", .data = (void *)MTK_NETSYS_V3_AMA_RGC3 },
|
||||
+ { /* sentinel */ },
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, mtk_pcs_lynxi_of_match);
|
||||
+
|
||||
+struct phylink_pcs *mtk_pcs_lynxi_get(struct device *dev, struct device_node *np)
|
||||
+{
|
||||
+ struct platform_device *pdev;
|
||||
+ struct mtk_pcs_lynxi *mpcs;
|
||||
+
|
||||
+ if (!np)
|
||||
+ return NULL;
|
||||
+
|
||||
+ if (!of_device_is_available(np))
|
||||
+ return ERR_PTR(-ENODEV);
|
||||
+
|
||||
+ if (!of_match_node(mtk_pcs_lynxi_of_match, np))
|
||||
+ return ERR_PTR(-EINVAL);
|
||||
+
|
||||
+ pdev = of_find_device_by_node(np);
|
||||
+ if (!pdev || !platform_get_drvdata(pdev)) {
|
||||
+ if (pdev)
|
||||
+ put_device(&pdev->dev);
|
||||
+ return ERR_PTR(-EPROBE_DEFER);
|
||||
+ }
|
||||
+
|
||||
+ mpcs = platform_get_drvdata(pdev);
|
||||
+ device_link_add(dev, mpcs->dev, DL_FLAG_AUTOREMOVE_CONSUMER);
|
||||
+
|
||||
+ return &mpcs->pcs;
|
||||
+}
|
||||
+EXPORT_SYMBOL(mtk_pcs_lynxi_get);
|
||||
+
|
||||
+void mtk_pcs_lynxi_put(struct phylink_pcs *pcs)
|
||||
+{
|
||||
+ struct mtk_pcs_lynxi *cur, *mpcs = NULL;
|
||||
+
|
||||
+ if (!pcs)
|
||||
+ return;
|
||||
+
|
||||
+ mutex_lock(&instance_mutex);
|
||||
+ list_for_each_entry(cur, &mtk_pcs_lynxi_instances, node)
|
||||
+ if (pcs == &cur->pcs) {
|
||||
+ mpcs = cur;
|
||||
+ break;
|
||||
+ }
|
||||
+ mutex_unlock(&instance_mutex);
|
||||
+
|
||||
+ if (WARN_ON(!mpcs))
|
||||
+ return;
|
||||
+
|
||||
+ put_device(mpcs->dev);
|
||||
+}
|
||||
+EXPORT_SYMBOL(mtk_pcs_lynxi_put);
|
||||
+
|
||||
+static struct platform_driver mtk_pcs_lynxi_driver = {
|
||||
+ .driver = {
|
||||
+ .name = "mtk-pcs-lynxi",
|
||||
+ .suppress_bind_attrs = true,
|
||||
+ .of_match_table = mtk_pcs_lynxi_of_match,
|
||||
+ },
|
||||
+ .probe = mtk_pcs_lynxi_probe,
|
||||
+ .remove = mtk_pcs_lynxi_remove,
|
||||
+};
|
||||
+module_platform_driver(mtk_pcs_lynxi_driver);
|
||||
+
|
||||
+MODULE_AUTHOR("Daniel Golle <daniel@makrotopia.org>");
|
||||
MODULE_DESCRIPTION("MediaTek SGMII library for LynxI");
|
||||
MODULE_LICENSE("GPL");
|
||||
--- a/include/linux/pcs/pcs-mtk-lynxi.h
|
||||
+++ b/include/linux/pcs/pcs-mtk-lynxi.h
|
||||
@@ -10,4 +10,15 @@ struct phylink_pcs *mtk_pcs_lynxi_create
|
||||
struct regmap *regmap,
|
||||
u32 ana_rgc3, u32 flags);
|
||||
void mtk_pcs_lynxi_destroy(struct phylink_pcs *pcs);
|
||||
+
|
||||
+#if IS_ENABLED(CONFIG_PCS_MTK_LYNXI)
|
||||
+struct phylink_pcs *mtk_pcs_lynxi_get(struct device *dev, struct device_node *np);
|
||||
+void mtk_pcs_lynxi_put(struct phylink_pcs *pcs);
|
||||
+#else
|
||||
+static inline struct phylink_pcs *mtk_pcs_lynxi_get(struct device *dev, struct device_node *np)
|
||||
+{
|
||||
+ return NULL;
|
||||
+}
|
||||
+static inline void mtk_pcs_lynxi_put(struct phylink_pcs *pcs) { }
|
||||
+#endif /* IS_ENABLED(CONFIG_PCS_MTK_LYNXI) */
|
||||
#endif
|
|
@ -19,7 +19,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|||
|
||||
--- a/MAINTAINERS
|
||||
+++ b/MAINTAINERS
|
||||
@@ -13356,7 +13356,9 @@ M: Daniel Golle <daniel@makrotopia.org>
|
||||
@@ -14419,7 +14419,9 @@ M: Daniel Golle <daniel@makrotopia.org>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/net/pcs/pcs-mtk-lynxi.c
|
||||
|
@ -51,14 +51,14 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|||
depends on OF && (ARCH_RZN1 || COMPILE_TEST)
|
||||
--- a/drivers/net/pcs/Makefile
|
||||
+++ b/drivers/net/pcs/Makefile
|
||||
@@ -7,3 +7,4 @@ obj-$(CONFIG_PCS_XPCS) += pcs_xpcs.o
|
||||
@@ -8,3 +8,4 @@ obj-$(CONFIG_PCS_XPCS) += pcs_xpcs.o
|
||||
obj-$(CONFIG_PCS_LYNX) += pcs-lynx.o
|
||||
obj-$(CONFIG_PCS_MTK_LYNXI) += pcs-mtk-lynxi.o
|
||||
obj-$(CONFIG_PCS_RZN1_MIIC) += pcs-rzn1-miic.o
|
||||
+obj-$(CONFIG_PCS_MTK_USXGMII) += pcs-mtk-usxgmii.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/pcs/pcs-mtk-usxgmii.c
|
||||
@@ -0,0 +1,456 @@
|
||||
@@ -0,0 +1,454 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+/*
|
||||
+ * Copyright (c) 2023 MediaTek Inc.
|
||||
|
@ -429,7 +429,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mtk_usxgmii_remove(struct platform_device *pdev)
|
||||
+static void mtk_usxgmii_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct device *dev = &pdev->dev;
|
||||
+ struct mtk_usxgmii_pcs *cur, *tmp;
|
||||
|
@ -441,8 +441,6 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|||
+ break;
|
||||
+ }
|
||||
+ mutex_unlock(&instance_mutex);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id mtk_usxgmii_of_mtable[] = {
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
From 1be3688b3eaa7ea2d9e19bd29ae6a6a51c121a0b Mon Sep 17 00:00:00 2001
|
||||
From: David Bauer <mail@david-bauer.net>
|
||||
Date: Sat, 16 Nov 2024 22:36:15 +0100
|
||||
Subject: [PATCH] net: phy: broadcom: update dependency condition
|
||||
|
||||
The broadcom PHY driver only has to depend upon PTP_1588_CLOCK_OPTIONAL
|
||||
if NETWORK_PHY_TIMESTAMPING is enabled. The PTP functionality is stubbed
|
||||
in this case.
|
||||
|
||||
Reflect this circumstance in the dependence condition. This allows to
|
||||
build the driver as a built-in module even if PTP is built as a module.
|
||||
|
||||
This is required to include the broadcom PHY module regardless of the
|
||||
built-setting of the PTP subsystem. On ath79 (and probably more)
|
||||
targets with Broadcom PHY, Gigabit operation is currently broken as the
|
||||
PHY driver is only built as a module in case all kernel-packages are
|
||||
built. Due to this circumstance, affected devices fall back to using the
|
||||
generic PHY driver.
|
||||
|
||||
Signed-off-by: David Bauer <mail@david-bauer.net>
|
||||
---
|
||||
drivers/net/phy/Kconfig | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/phy/Kconfig
|
||||
+++ b/drivers/net/phy/Kconfig
|
||||
@@ -139,7 +139,7 @@ config BROADCOM_PHY
|
||||
tristate "Broadcom 54XX PHYs"
|
||||
select BCM_NET_PHYLIB
|
||||
select BCM_NET_PHYPTP if NETWORK_PHY_TIMESTAMPING
|
||||
- depends on PTP_1588_CLOCK_OPTIONAL
|
||||
+ depends on NETWORK_PHY_TIMESTAMPING=n || PTP_1588_CLOCK_OPTIONAL
|
||||
help
|
||||
Currently supports the BCM5411, BCM5421, BCM5461, BCM54616S, BCM5464,
|
||||
BCM5481, BCM54810 and BCM5482 PHYs.
|
|
@ -32,9 +32,9 @@ https://patchwork.kernel.org/project/netdevbpf/patch/20240425023325.15586-3-SkyL
|
|||
|
||||
--- a/drivers/net/phy/air_en8811h.c
|
||||
+++ b/drivers/net/phy/air_en8811h.c
|
||||
@@ -544,6 +544,10 @@ static int air_hw_led_on_set(struct phy_
|
||||
|
||||
changed |= (priv->led[index].rules != 0);
|
||||
@@ -548,6 +548,10 @@ static int air_hw_led_on_set(struct phy_
|
||||
if (!on)
|
||||
priv->led[index].rules = 0;
|
||||
|
||||
+ /* clear netdev trigger rules in case LED_OFF has been set */
|
||||
+ if (!on)
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Subject: [RFC net-next 7/7] net: dsa: mv88e6xxx: Request assisted learning on CPU port
|
||||
Date: Sat, 16 Jan 2021 02:25:15 +0100
|
||||
Archived-At: <https://lore.kernel.org/netdev/20210116012515.3152-8-tobias@waldekranz.com/>
|
||||
|
||||
While the hardware is capable of performing learning on the CPU port,
|
||||
it requires alot of additions to the bridge's forwarding path in order
|
||||
to handle multi-destination traffic correctly.
|
||||
|
||||
Until that is in place, opt for the next best thing and let DSA sync
|
||||
the relevant addresses down to the hardware FDB.
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
drivers/net/dsa/mv88e6xxx/chip.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
@@ -6989,6 +6989,7 @@ static int mv88e6xxx_register_switch(str
|
||||
ds->ops = &mv88e6xxx_switch_ops;
|
||||
ds->ageing_time_min = chip->info->age_time_coeff;
|
||||
ds->ageing_time_max = chip->info->age_time_coeff * U8_MAX;
|
||||
+ ds->assisted_learning_on_cpu_port = true;
|
||||
|
||||
/* Some chips support up to 32, but that requires enabling the
|
||||
* 5-bit port mode, which we do not support. 640k^W16 ought to
|
|
@ -1,30 +0,0 @@
|
|||
From 3f1a227cb071f65f6ecc4db9f399649869735a7c Mon Sep 17 00:00:00 2001
|
||||
From: David Bauer <mail@david-bauer.net>
|
||||
Date: Sat, 17 Feb 2024 22:34:59 +0100
|
||||
Subject: [PATCH] net vxlan: don't learn non-unicast L2 destinations
|
||||
|
||||
This patch avoids learning non-unicast targets in the vxlan FDB.
|
||||
They are non-unicast and thus should be sent to the broadcast-IPv6
|
||||
instead of a unicast address.
|
||||
|
||||
Link: https://lore.kernel.org/netdev/15ee0cc7-9252-466b-8ce7-5225d605dde8@david-bauer.net/
|
||||
Link: https://github.com/freifunk-gluon/gluon/issues/3191
|
||||
|
||||
Signed-off-by: David Bauer <mail@david-bauer.net>
|
||||
---
|
||||
drivers/net/vxlan.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
--- a/drivers/net/vxlan/vxlan_core.c
|
||||
+++ b/drivers/net/vxlan/vxlan_core.c
|
||||
@@ -1446,6 +1446,10 @@ static bool vxlan_snoop(struct net_devic
|
||||
struct vxlan_fdb *f;
|
||||
u32 ifindex = 0;
|
||||
|
||||
+ /* Don't learn broadcast packets */
|
||||
+ if (is_multicast_ether_addr(src_mac) || is_zero_ether_addr(src_mac))
|
||||
+ return false;
|
||||
+
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
if (src_ip->sa.sa_family == AF_INET6 &&
|
||||
(ipv6_addr_type(&src_ip->sin6.sin6_addr) & IPV6_ADDR_LINKLOCAL))
|
|
@ -0,0 +1,31 @@
|
|||
From f992b15965177e2f280fb6f41f292214f9a6f8d5 Mon Sep 17 00:00:00 2001
|
||||
From: Pavan Chebbi <pavan.chebbi@broadcom.com>
|
||||
Date: Tue, 10 Dec 2024 03:28:31 -0800
|
||||
Subject: [PATCH] tg3: Fix DMA allocations on 57766 devices
|
||||
|
||||
The coherent DMA mask of 31b may not be accepted if
|
||||
the DMA mask is configured to use higher memories of
|
||||
64b. Set the DMA mask also to lower 32b for 57766
|
||||
devices.
|
||||
|
||||
Fixes: 614f4d166eee ("tg3: Set coherent DMA mask bits to 31 for BCM57766 chipsets")
|
||||
Reported-By: Rui Salvaterra <rsalvaterra@gmail.com>
|
||||
Signed-off-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
|
||||
---
|
||||
drivers/net/ethernet/broadcom/tg3.c | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/ethernet/broadcom/tg3.c
|
||||
+++ b/drivers/net/ethernet/broadcom/tg3.c
|
||||
@@ -17801,8 +17801,10 @@ static int tg3_init_one(struct pci_dev *
|
||||
} else
|
||||
persist_dma_mask = dma_mask = DMA_BIT_MASK(64);
|
||||
|
||||
- if (tg3_asic_rev(tp) == ASIC_REV_57766)
|
||||
+ if (tg3_asic_rev(tp) == ASIC_REV_57766) {
|
||||
+ dma_mask = DMA_BIT_MASK(32);
|
||||
persist_dma_mask = DMA_BIT_MASK(31);
|
||||
+ }
|
||||
|
||||
/* Configure DMA attributes. */
|
||||
if (dma_mask > DMA_BIT_MASK(32)) {
|
|
@ -70,7 +70,7 @@ v1 -> v2:
|
|||
|
||||
--- a/drivers/gpio/Kconfig
|
||||
+++ b/drivers/gpio/Kconfig
|
||||
@@ -1820,4 +1820,19 @@ config GPIO_SIM
|
||||
@@ -1929,4 +1929,19 @@ config GPIO_VIRTUSER
|
||||
|
||||
endmenu
|
||||
|
||||
|
@ -92,17 +92,17 @@ v1 -> v2:
|
|||
endif
|
||||
--- a/drivers/gpio/Makefile
|
||||
+++ b/drivers/gpio/Makefile
|
||||
@@ -44,6 +44,7 @@ obj-$(CONFIG_GPIO_BD9571MWV) += gpio-bd
|
||||
@@ -45,6 +45,7 @@ obj-$(CONFIG_GPIO_BD9571MWV) += gpio-bd
|
||||
obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o
|
||||
obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o
|
||||
obj-$(CONFIG_GPIO_CADENCE) += gpio-cadence.o
|
||||
+obj-$(CONFIG_GPIO_CASCADE) += gpio-cascade.o
|
||||
obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o
|
||||
obj-$(CONFIG_GPIO_SNPS_CREG) += gpio-creg-snps.o
|
||||
obj-$(CONFIG_GPIO_CRYSTAL_COVE) += gpio-crystalcove.o
|
||||
obj-$(CONFIG_GPIO_CROS_EC) += gpio-cros-ec.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/gpio/gpio-cascade.c
|
||||
@@ -0,0 +1,117 @@
|
||||
@@ -0,0 +1,112 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-only
|
||||
+/*
|
||||
+ * A generic GPIO cascade driver
|
||||
|
@ -141,11 +141,6 @@ v1 -> v2:
|
|||
+ struct gpio_desc *upstream_line;
|
||||
+};
|
||||
+
|
||||
+static struct gpio_cascade *chip_to_cascade(struct gpio_chip *gc)
|
||||
+{
|
||||
+ return container_of(gc, struct gpio_cascade, gpio_chip);
|
||||
+}
|
||||
+
|
||||
+static int gpio_cascade_get_direction(struct gpio_chip *gc, unsigned int offset)
|
||||
+{
|
||||
+ return GPIO_LINE_DIRECTION_IN;
|
||||
|
@ -153,7 +148,7 @@ v1 -> v2:
|
|||
+
|
||||
+static int gpio_cascade_get_value(struct gpio_chip *gc, unsigned int offset)
|
||||
+{
|
||||
+ struct gpio_cascade *cas = chip_to_cascade(gc);
|
||||
+ struct gpio_cascade *cas = gpiochip_get_data(gc);
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = mux_control_select(cas->mux_control, offset);
|
||||
|
@ -199,7 +194,7 @@ v1 -> v2:
|
|||
+ gc->owner = THIS_MODULE;
|
||||
+
|
||||
+ platform_set_drvdata(pdev, cas);
|
||||
+ return devm_gpiochip_add_data(dev, &cas->gpio_chip, NULL);
|
||||
+ return devm_gpiochip_add_data(dev, &cas->gpio_chip, cas);
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id gpio_cascade_id[] = {
|
||||
|
|
|
@ -33,7 +33,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
|||
return 0;
|
||||
--- a/drivers/opp/core.c
|
||||
+++ b/drivers/opp/core.c
|
||||
@@ -902,7 +902,8 @@ static int _set_opp_voltage(struct devic
|
||||
@@ -942,7 +942,8 @@ static int _set_opp_voltage(struct devic
|
||||
|
||||
static int
|
||||
_opp_config_clk_single(struct device *dev, struct opp_table *opp_table,
|
||||
|
@ -43,7 +43,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
|||
{
|
||||
unsigned long *target = data;
|
||||
unsigned long freq;
|
||||
@@ -934,8 +935,8 @@ _opp_config_clk_single(struct device *de
|
||||
@@ -974,8 +975,8 @@ _opp_config_clk_single(struct device *de
|
||||
* the order in which they are present in the array while scaling up.
|
||||
*/
|
||||
int dev_pm_opp_config_clks_simple(struct device *dev,
|
||||
|
@ -54,7 +54,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
|||
{
|
||||
int ret, i;
|
||||
|
||||
@@ -1217,7 +1218,7 @@ static int _set_opp(struct device *dev,
|
||||
@@ -1242,7 +1243,7 @@ static int _set_opp(struct device *dev,
|
||||
}
|
||||
|
||||
if (opp_table->config_clks) {
|
||||
|
@ -63,7 +63,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
|||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
@@ -1292,7 +1293,7 @@ int dev_pm_opp_set_rate(struct device *d
|
||||
@@ -1321,7 +1322,7 @@ int dev_pm_opp_set_rate(struct device *d
|
||||
* equivalent to a clk_set_rate()
|
||||
*/
|
||||
if (!_get_opp_count(opp_table)) {
|
||||
|
@ -74,7 +74,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
|||
}
|
||||
--- a/include/linux/pm_opp.h
|
||||
+++ b/include/linux/pm_opp.h
|
||||
@@ -61,7 +61,8 @@ typedef int (*config_regulators_t)(struc
|
||||
@@ -50,7 +50,8 @@ typedef int (*config_regulators_t)(struc
|
||||
struct dev_pm_opp *old_opp, struct dev_pm_opp *new_opp,
|
||||
struct regulator **regulators, unsigned int count);
|
||||
|
||||
|
@ -84,7 +84,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
|||
struct dev_pm_opp *opp, void *data, bool scaling_down);
|
||||
|
||||
/**
|
||||
@@ -172,8 +173,8 @@ int dev_pm_opp_set_config(struct device
|
||||
@@ -184,8 +185,8 @@ int dev_pm_opp_set_config(struct device
|
||||
int devm_pm_opp_set_config(struct device *dev, struct dev_pm_opp_config *config);
|
||||
void dev_pm_opp_clear_config(int token);
|
||||
int dev_pm_opp_config_clks_simple(struct device *dev,
|
||||
|
@ -95,7 +95,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
|||
|
||||
struct dev_pm_opp *dev_pm_opp_xlate_required_opp(struct opp_table *src_table, struct opp_table *dst_table, struct dev_pm_opp *src_opp);
|
||||
int dev_pm_opp_xlate_performance_state(struct opp_table *src_table, struct opp_table *dst_table, unsigned int pstate);
|
||||
@@ -377,8 +378,8 @@ static inline int devm_pm_opp_set_config
|
||||
@@ -395,8 +396,8 @@ static inline int devm_pm_opp_set_config
|
||||
static inline void dev_pm_opp_clear_config(int token) {}
|
||||
|
||||
static inline int dev_pm_opp_config_clks_simple(struct device *dev,
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
From 0e71cac033bb7689c4dfa2e6814191337ef770f5 Mon Sep 17 00:00:00 2001
|
||||
From: INAGAKI Hiroshi <musashino.open@gmail.com>
|
||||
Date: Thu, 13 Oct 2022 00:51:33 +0900
|
||||
Subject: [PATCH] nvmem: layouts: u-boot-env: align endianness of crc32 values
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This patch fixes crc32 error on Big-Endianness system by conversion of
|
||||
calculated crc32 value.
|
||||
|
||||
Little-Endianness system:
|
||||
|
||||
obtained crc32: Little
|
||||
calculated crc32: Little
|
||||
|
||||
Big-Endianness system:
|
||||
|
||||
obtained crc32: Little
|
||||
calculated crc32: Big
|
||||
|
||||
log (APRESIA ApresiaLightGS120GT-SS, RTL8382M, Big-Endianness):
|
||||
|
||||
[ 8.570000] u_boot_env 18001200.spi:flash@0:partitions:partition@c0000: Invalid calculated CRC32: 0x88cd6f09 (expected: 0x096fcd88)
|
||||
[ 8.580000] u_boot_env: probe of 18001200.spi:flash@0:partitions:partition@c0000 failed with error -22
|
||||
|
||||
Fixes: f955dc1445069 ("nvmem: add driver handling U-Boot environment variables")
|
||||
|
||||
Signed-off-by: INAGAKI Hiroshi <musashino.open@gmail.com>
|
||||
Acked-by: Rafał Miłecki <rafal@milecki.pl>
|
||||
Tested-by: Christian Lamparter <chunkeey@gmail.com>
|
||||
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
---
|
||||
|
||||
--- a/drivers/nvmem/layouts/u-boot-env.c
|
||||
+++ b/drivers/nvmem/layouts/u-boot-env.c
|
||||
@@ -148,7 +148,7 @@ int u_boot_env_parse(struct device *dev,
|
||||
crc32_data_len = dev_size - crc32_data_offset;
|
||||
data_len = dev_size - data_offset;
|
||||
|
||||
- calc = crc32(~0, buf + crc32_data_offset, crc32_data_len) ^ ~0L;
|
||||
+ calc = le32_to_cpu((__le32)crc32(~0, buf + crc32_data_offset, crc32_data_len) ^ ~0L);
|
||||
if (calc != crc32) {
|
||||
dev_err(dev, "Invalid calculated CRC32: 0x%08x (expected: 0x%08x)\n", calc, crc32);
|
||||
err = -EINVAL;
|
|
@ -33,7 +33,7 @@ string.
|
|||
#include <linux/init.h>
|
||||
#include <linux/kref.h>
|
||||
#include <linux/module.h>
|
||||
@@ -779,6 +782,62 @@ static int nvmem_validate_keepouts(struc
|
||||
@@ -797,6 +800,62 @@ static int nvmem_validate_keepouts(struc
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -96,7 +96,7 @@ string.
|
|||
static int nvmem_add_cells_from_dt(struct nvmem_device *nvmem, struct device_node *np)
|
||||
{
|
||||
struct device *dev = &nvmem->dev;
|
||||
@@ -813,6 +872,25 @@ static int nvmem_add_cells_from_dt(struc
|
||||
@@ -836,6 +895,25 @@ static int nvmem_add_cells_from_dt(struc
|
||||
if (nvmem->fixup_dt_cell_info)
|
||||
nvmem->fixup_dt_cell_info(nvmem, &info);
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
|
|||
|
||||
--- a/drivers/pci/Kconfig
|
||||
+++ b/drivers/pci/Kconfig
|
||||
@@ -113,6 +113,13 @@ config XEN_PCIDEV_FRONTEND
|
||||
@@ -118,6 +118,13 @@ config XEN_PCIDEV_FRONTEND
|
||||
The PCI device frontend driver allows the kernel to import arbitrary
|
||||
PCI devices from a PCI backend to support PCI driver domains.
|
||||
|
||||
|
@ -25,7 +25,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
|
|||
|
||||
--- a/drivers/pci/quirks.c
|
||||
+++ b/drivers/pci/quirks.c
|
||||
@@ -300,6 +300,7 @@ static void quirk_mmio_always_on(struct
|
||||
@@ -313,6 +313,7 @@ static void quirk_mmio_always_on(struct
|
||||
DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_ANY_ID, PCI_ANY_ID,
|
||||
PCI_CLASS_BRIDGE_HOST, 8, quirk_mmio_always_on);
|
||||
|
||||
|
@ -33,7 +33,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
|
|||
/*
|
||||
* The Mellanox Tavor device gives false positive parity errors. Disable
|
||||
* parity error reporting.
|
||||
@@ -3488,6 +3489,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_I
|
||||
@@ -3508,6 +3509,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_I
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65f9, quirk_intel_mc_errata);
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65fa, quirk_intel_mc_errata);
|
||||
|
||||
|
@ -42,7 +42,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
|
|||
/*
|
||||
* Ivytown NTB BAR sizes are misreported by the hardware due to an erratum.
|
||||
* To work around this, query the size it should be configured to by the
|
||||
@@ -3513,6 +3516,8 @@ static void quirk_intel_ntb(struct pci_d
|
||||
@@ -3533,6 +3536,8 @@ static void quirk_intel_ntb(struct pci_d
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0e08, quirk_intel_ntb);
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0e0d, quirk_intel_ntb);
|
||||
|
||||
|
@ -51,7 +51,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
|
|||
/*
|
||||
* Some BIOS implementations leave the Intel GPU interrupts enabled, even
|
||||
* though no one is handling them (e.g., if the i915 driver is never
|
||||
@@ -3551,6 +3556,8 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_IN
|
||||
@@ -3571,6 +3576,8 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_IN
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x010a, disable_igfx_irq);
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0152, disable_igfx_irq);
|
||||
|
||||
|
|
145
6.12/target/linux/generic/pending-6.12/834-ledtrig-libata.patch
Normal file
145
6.12/target/linux/generic/pending-6.12/834-ledtrig-libata.patch
Normal file
|
@ -0,0 +1,145 @@
|
|||
From: Daniel Golle <daniel@makrotopia.org>
|
||||
Subject: libata: add ledtrig support
|
||||
|
||||
This adds a LED trigger for each ATA port indicating disk activity.
|
||||
|
||||
As this is needed only on specific platforms (NAS SoCs and such),
|
||||
these platforms should define ARCH_WANTS_LIBATA_LEDS if there
|
||||
are boards with LED(s) intended to indicate ATA disk activity and
|
||||
need the OS to take care of that.
|
||||
In that way, if not selected, LED trigger support not will be
|
||||
included in libata-core and both, codepaths and structures remain
|
||||
untouched.
|
||||
|
||||
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
---
|
||||
drivers/ata/Kconfig | 16 ++++++++++++++++
|
||||
drivers/ata/libata-core.c | 41 +++++++++++++++++++++++++++++++++++++++++
|
||||
include/linux/libata.h | 9 +++++++++
|
||||
3 files changed, 66 insertions(+)
|
||||
|
||||
--- a/drivers/ata/Kconfig
|
||||
+++ b/drivers/ata/Kconfig
|
||||
@@ -67,6 +67,22 @@ config ATA_FORCE
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
+config ARCH_WANT_LIBATA_LEDS
|
||||
+ bool
|
||||
+
|
||||
+config ATA_LEDS
|
||||
+ bool "support ATA port LED triggers"
|
||||
+ depends on ARCH_WANT_LIBATA_LEDS
|
||||
+ select NEW_LEDS
|
||||
+ select LEDS_CLASS
|
||||
+ select LEDS_TRIGGERS
|
||||
+ default y
|
||||
+ help
|
||||
+ This option adds a LED trigger for each registered ATA port.
|
||||
+ It is used to drive disk activity leds connected via GPIO.
|
||||
+
|
||||
+ If unsure, say N.
|
||||
+
|
||||
config ATA_ACPI
|
||||
bool "ATA ACPI Support"
|
||||
depends on ACPI
|
||||
--- a/drivers/ata/libata-core.c
|
||||
+++ b/drivers/ata/libata-core.c
|
||||
@@ -672,6 +672,17 @@ static inline void ata_set_tf_cdl(struct
|
||||
qc->flags |= ATA_QCFLAG_HAS_CDL | ATA_QCFLAG_RESULT_TF;
|
||||
}
|
||||
|
||||
+#ifdef CONFIG_ATA_LEDS
|
||||
+#define LIBATA_BLINK_DELAY 20 /* ms */
|
||||
+static inline void ata_led_act(struct ata_port *ap)
|
||||
+{
|
||||
+ if (unlikely(!ap->ledtrig))
|
||||
+ return;
|
||||
+
|
||||
+ led_trigger_blink_oneshot(ap->ledtrig, LIBATA_BLINK_DELAY, LIBATA_BLINK_DELAY, 0);
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
/**
|
||||
* ata_build_rw_tf - Build ATA taskfile for given read/write request
|
||||
* @qc: Metadata associated with the taskfile to build
|
||||
@@ -4728,6 +4739,9 @@ void __ata_qc_complete(struct ata_queued
|
||||
link->active_tag = ATA_TAG_POISON;
|
||||
ap->nr_active_links--;
|
||||
}
|
||||
+#ifdef CONFIG_ATA_LEDS
|
||||
+ ata_led_act(ap);
|
||||
+#endif
|
||||
|
||||
/* clear exclusive status */
|
||||
if (unlikely(qc->flags & ATA_QCFLAG_CLEAR_EXCL &&
|
||||
@@ -5450,6 +5464,9 @@ struct ata_port *ata_port_alloc(struct a
|
||||
ap->stats.unhandled_irq = 1;
|
||||
ap->stats.idle_irq = 1;
|
||||
#endif
|
||||
+#ifdef CONFIG_ATA_LEDS
|
||||
+ ap->ledtrig = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
|
||||
+#endif
|
||||
ata_sff_port_init(ap);
|
||||
|
||||
return ap;
|
||||
@@ -5464,6 +5481,12 @@ void ata_port_free(struct ata_port *ap)
|
||||
kfree(ap->pmp_link);
|
||||
kfree(ap->slave_link);
|
||||
ida_free(&ata_ida, ap->print_id);
|
||||
+#ifdef CONFIG_ATA_LEDS
|
||||
+ if (ap->ledtrig) {
|
||||
+ led_trigger_unregister(ap->ledtrig);
|
||||
+ kfree(ap->ledtrig);
|
||||
+ };
|
||||
+#endif
|
||||
kfree(ap);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ata_port_free);
|
||||
@@ -5868,7 +5891,23 @@ int ata_host_register(struct ata_host *h
|
||||
WARN_ON(1);
|
||||
return -EINVAL;
|
||||
}
|
||||
+#ifdef CONFIG_ATA_LEDS
|
||||
+ for (i = 0; i < host->n_ports; i++) {
|
||||
+ if (unlikely(!host->ports[i]->ledtrig))
|
||||
+ continue;
|
||||
|
||||
+ snprintf(host->ports[i]->ledtrig_name,
|
||||
+ sizeof(host->ports[i]->ledtrig_name), "ata%u",
|
||||
+ host->ports[i]->print_id);
|
||||
+
|
||||
+ host->ports[i]->ledtrig->name = host->ports[i]->ledtrig_name;
|
||||
+
|
||||
+ if (led_trigger_register(host->ports[i]->ledtrig)) {
|
||||
+ kfree(host->ports[i]->ledtrig);
|
||||
+ host->ports[i]->ledtrig = NULL;
|
||||
+ }
|
||||
+ }
|
||||
+#endif
|
||||
/* Create associated sysfs transport objects */
|
||||
for (i = 0; i < host->n_ports; i++) {
|
||||
rc = ata_tport_add(host->dev,host->ports[i]);
|
||||
--- a/include/linux/libata.h
|
||||
+++ b/include/linux/libata.h
|
||||
@@ -23,6 +23,9 @@
|
||||
#include <linux/cdrom.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/async.h>
|
||||
+#ifdef CONFIG_ATA_LEDS
|
||||
+#include <linux/leds.h>
|
||||
+#endif
|
||||
|
||||
/*
|
||||
* Define if arch has non-standard setup. This is a _PCI_ standard
|
||||
@@ -726,6 +729,10 @@ struct ata_device {
|
||||
union acpi_object *gtf_cache;
|
||||
unsigned int gtf_filter;
|
||||
#endif
|
||||
+#ifdef CONFIG_ATA_LEDS
|
||||
+ struct led_trigger *ledtrig;
|
||||
+ char ledtrig_name[8];
|
||||
+#endif
|
||||
#ifdef CONFIG_SATA_ZPODD
|
||||
void *zpodd;
|
||||
#endif
|
|
@ -33,7 +33,7 @@ Signed-off-by: Marek Behún <kabel@kernel.org>
|
|||
|
||||
--- a/drivers/pci/controller/pci-aardvark.c
|
||||
+++ b/drivers/pci/controller/pci-aardvark.c
|
||||
@@ -277,7 +277,6 @@ struct advk_pcie {
|
||||
@@ -276,7 +276,6 @@ struct advk_pcie {
|
||||
u8 wins_count;
|
||||
struct irq_domain *rp_irq_domain;
|
||||
struct irq_domain *irq_domain;
|
||||
|
@ -41,7 +41,7 @@ Signed-off-by: Marek Behún <kabel@kernel.org>
|
|||
raw_spinlock_t irq_lock;
|
||||
struct irq_domain *msi_domain;
|
||||
struct irq_domain *msi_inner_domain;
|
||||
@@ -1426,14 +1425,19 @@ static void advk_pcie_irq_unmask(struct
|
||||
@@ -1418,14 +1417,19 @@ static void advk_pcie_irq_unmask(struct
|
||||
raw_spin_unlock_irqrestore(&pcie->irq_lock, flags);
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,7 @@ Signed-off-by: Marek Behún <kabel@kernel.org>
|
|||
irq_set_chip_data(virq, pcie);
|
||||
|
||||
return 0;
|
||||
@@ -1492,7 +1496,6 @@ static int advk_pcie_init_irq_domain(str
|
||||
@@ -1485,7 +1489,6 @@ static int advk_pcie_init_irq_domain(str
|
||||
struct device *dev = &pcie->pdev->dev;
|
||||
struct device_node *node = dev->of_node;
|
||||
struct device_node *pcie_intc_node;
|
||||
|
@ -71,7 +71,7 @@ Signed-off-by: Marek Behún <kabel@kernel.org>
|
|||
int ret = 0;
|
||||
|
||||
raw_spin_lock_init(&pcie->irq_lock);
|
||||
@@ -1503,28 +1506,14 @@ static int advk_pcie_init_irq_domain(str
|
||||
@@ -1496,28 +1499,14 @@ static int advk_pcie_init_irq_domain(str
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,8 +26,8 @@ Signed-off-by: Lech Perczak <lech.perczak@gmail.com>
|
|||
|
||||
--- a/arch/arm/boot/dts/nxp/imx/imx7d-pico.dtsi
|
||||
+++ b/arch/arm/boot/dts/nxp/imx/imx7d-pico.dtsi
|
||||
@@ -108,6 +108,14 @@
|
||||
assigned-clock-rates = <0>, <32768>;
|
||||
@@ -116,6 +116,14 @@
|
||||
cpu-supply = <&sw1a_reg>;
|
||||
};
|
||||
|
||||
+&cpu0 {
|
||||
|
|
|
@ -0,0 +1,783 @@
|
|||
From df1357358eec062241bddd2995e7ef0ce86cf45a Mon Sep 17 00:00:00 2001
|
||||
X-Patchwork-Submitter: Corentin Labbe <clabbe@baylibre.com>
|
||||
X-Patchwork-Id: 13656881
|
||||
Message-Id: <20240507131522.3546113-2-clabbe@baylibre.com>
|
||||
X-Mailer: git-send-email 2.25.1
|
||||
In-Reply-To: <20240507131522.3546113-1-clabbe@baylibre.com>
|
||||
References: <20240507131522.3546113-1-clabbe@baylibre.com>
|
||||
Precedence: bulk
|
||||
X-Mailing-List: linux-usb@vger.kernel.org
|
||||
List-Id: <linux-usb.vger.kernel.org>
|
||||
From: Corentin Labbe <clabbe@baylibre.com>
|
||||
Date: Tue, 7 May 2024 13:15:22 +0000
|
||||
Subject: [PATCH v7] usb: serial: add support for CH348
|
||||
|
||||
The CH348 is an USB octo port serial adapter.
|
||||
The device multiplexes all 8 ports in the same pair of Bulk endpoints.
|
||||
Since there is no public datasheet, unfortunately it remains some magic values
|
||||
|
||||
Signed-off-by: Corentin Labbe <clabbe@baylibre.com>
|
||||
Tested-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
|
||||
---
|
||||
drivers/usb/serial/Kconfig | 9 +
|
||||
drivers/usb/serial/Makefile | 1 +
|
||||
drivers/usb/serial/ch348.c | 725 ++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 735 insertions(+)
|
||||
create mode 100644 drivers/usb/serial/ch348.c
|
||||
|
||||
--- a/drivers/usb/serial/Kconfig
|
||||
+++ b/drivers/usb/serial/Kconfig
|
||||
@@ -112,6 +112,15 @@ config USB_SERIAL_CH341
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called ch341.
|
||||
|
||||
+config USB_SERIAL_CH348
|
||||
+ tristate "USB Winchiphead CH348 Octo Port Serial Driver"
|
||||
+ help
|
||||
+ Say Y here if you want to use a Winchiphead CH348 octo port
|
||||
+ USB to serial adapter.
|
||||
+
|
||||
+ To compile this driver as a module, choose M here: the
|
||||
+ module will be called ch348.
|
||||
+
|
||||
config USB_SERIAL_WHITEHEAT
|
||||
tristate "USB ConnectTech WhiteHEAT Serial Driver"
|
||||
select USB_EZUSB_FX2
|
||||
--- a/drivers/usb/serial/Makefile
|
||||
+++ b/drivers/usb/serial/Makefile
|
||||
@@ -15,6 +15,7 @@ obj-$(CONFIG_USB_SERIAL_AIRCABLE) += ai
|
||||
obj-$(CONFIG_USB_SERIAL_ARK3116) += ark3116.o
|
||||
obj-$(CONFIG_USB_SERIAL_BELKIN) += belkin_sa.o
|
||||
obj-$(CONFIG_USB_SERIAL_CH341) += ch341.o
|
||||
+obj-$(CONFIG_USB_SERIAL_CH348) += ch348.o
|
||||
obj-$(CONFIG_USB_SERIAL_CP210X) += cp210x.o
|
||||
obj-$(CONFIG_USB_SERIAL_CYBERJACK) += cyberjack.o
|
||||
obj-$(CONFIG_USB_SERIAL_CYPRESS_M8) += cypress_m8.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/usb/serial/ch348.c
|
||||
@@ -0,0 +1,725 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+/*
|
||||
+ * USB serial driver for USB to Octal UARTs chip ch348.
|
||||
+ *
|
||||
+ * Copyright (C) 2022 Corentin Labbe <clabbe@baylibre.com>
|
||||
+ * With the help of Neil Armstrong <neil.armstrong@linaro.org>
|
||||
+ * and the help of Martin Blumenstingl <martin.blumenstingl@googlemail.com>
|
||||
+ */
|
||||
+
|
||||
+#include <linux/completion.h>
|
||||
+#include <linux/errno.h>
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/mutex.h>
|
||||
+#include <linux/overflow.h>
|
||||
+#include <linux/serial.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/tty.h>
|
||||
+#include <linux/tty_driver.h>
|
||||
+#include <linux/tty_flip.h>
|
||||
+#include <linux/usb.h>
|
||||
+#include <linux/usb/serial.h>
|
||||
+
|
||||
+#define CH348_CMD_TIMEOUT 2000
|
||||
+
|
||||
+#define CH348_CTO_D 0x01
|
||||
+#define CH348_CTO_R 0x02
|
||||
+
|
||||
+#define CH348_CTI_C 0x10
|
||||
+#define CH348_CTI_DSR 0x20
|
||||
+#define CH348_CTI_R 0x40
|
||||
+#define CH348_CTI_DCD 0x80
|
||||
+
|
||||
+#define CH348_LO 0x02
|
||||
+#define CH348_LP 0x04
|
||||
+#define CH348_LF 0x08
|
||||
+#define CH348_LB 0x10
|
||||
+
|
||||
+#define CMD_W_R 0xC0
|
||||
+#define CMD_W_BR 0x80
|
||||
+
|
||||
+#define CMD_WB_E 0x90
|
||||
+#define CMD_RB_E 0xC0
|
||||
+
|
||||
+#define M_NOR 0x00
|
||||
+#define M_HF 0x03
|
||||
+
|
||||
+#define R_MOD 0x97
|
||||
+#define R_IO_D 0x98
|
||||
+#define R_IO_O 0x99
|
||||
+#define R_IO_I 0x9b
|
||||
+#define R_TM_O 0x9c
|
||||
+#define R_INIT 0xa1
|
||||
+
|
||||
+#define R_C1 0x01
|
||||
+#define R_C2 0x02
|
||||
+#define R_C4 0x04
|
||||
+#define R_C5 0x06
|
||||
+
|
||||
+#define R_II_B1 0x06
|
||||
+#define R_II_B2 0x02
|
||||
+#define R_II_B3 0x00
|
||||
+
|
||||
+#define CMD_VER 0x96
|
||||
+
|
||||
+#define CH348_RX_PORT_CHUNK_LENGTH 32
|
||||
+#define CH348_RX_PORT_MAX_LENGTH 30
|
||||
+
|
||||
+struct ch348_rxbuf {
|
||||
+ u8 port;
|
||||
+ u8 length;
|
||||
+ u8 data[CH348_RX_PORT_MAX_LENGTH];
|
||||
+} __packed;
|
||||
+
|
||||
+struct ch348_txbuf {
|
||||
+ u8 port;
|
||||
+ __le16 length;
|
||||
+ u8 data[];
|
||||
+} __packed;
|
||||
+
|
||||
+#define CH348_TX_HDRSIZE offsetof(struct ch348_txbuf, data)
|
||||
+
|
||||
+struct ch348_initbuf {
|
||||
+ u8 cmd;
|
||||
+ u8 reg;
|
||||
+ u8 port;
|
||||
+ __be32 baudrate;
|
||||
+ u8 format;
|
||||
+ u8 paritytype;
|
||||
+ u8 databits;
|
||||
+ u8 rate;
|
||||
+ u8 unknown;
|
||||
+} __packed;
|
||||
+
|
||||
+#define CH348_MAXPORT 8
|
||||
+
|
||||
+/*
|
||||
+ * The CH348 multiplexes rx & tx into a pair of Bulk USB endpoints for
|
||||
+ * the 8 serial ports, and another pair of Bulk USB endpoints to
|
||||
+ * set port settings and receive port status events.
|
||||
+ *
|
||||
+ * The USB serial cores ties every Bulk endpoints pairs to each ports,
|
||||
+ * but in our case it will set port 0 with the rx/tx endpoints
|
||||
+ * and port 1 with the setup/status endpoints.
|
||||
+ *
|
||||
+ * To still take advantage of the generic code, we (re-)initialize
|
||||
+ * the USB serial port structure with the correct USB endpoint
|
||||
+ * for read and write, and write proper process_read_urb()
|
||||
+ * and prepare_write_buffer() to correctly (de-)multiplex data.
|
||||
+ * Also we use a custom write() implementation to wait until the buffer
|
||||
+ * has been fully transmitted to prevent TX buffer overruns.
|
||||
+ */
|
||||
+
|
||||
+/*
|
||||
+ * struct ch348_port - per-port information
|
||||
+ * @uartmode: UART port current mode
|
||||
+ * @write_completion: completion event when the TX buffer has been written out
|
||||
+ */
|
||||
+struct ch348_port {
|
||||
+ u8 uartmode;
|
||||
+ struct completion write_completion;
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ * struct ch348 - main container for all this driver information
|
||||
+ * @udev: pointer to the CH348 USB device
|
||||
+ * @ports: List of per-port information
|
||||
+ * @serial: pointer to the serial structure
|
||||
+ * @write_lock: protect against concurrent writes so we don't lose data
|
||||
+ * @cmd_ep: endpoint number for configure operations
|
||||
+ * @status_urb: URB for status
|
||||
+ * @status_buffer: buffer used by status_urb
|
||||
+ */
|
||||
+struct ch348 {
|
||||
+ struct usb_device *udev;
|
||||
+ struct ch348_port ports[CH348_MAXPORT];
|
||||
+ struct usb_serial *serial;
|
||||
+
|
||||
+ struct mutex write_lock;
|
||||
+
|
||||
+ int cmd_ep;
|
||||
+
|
||||
+ struct urb *status_urb;
|
||||
+ u8 status_buffer[];
|
||||
+};
|
||||
+
|
||||
+struct ch348_magic {
|
||||
+ u8 action;
|
||||
+ u8 reg;
|
||||
+ u8 control;
|
||||
+} __packed;
|
||||
+
|
||||
+struct ch348_status_entry {
|
||||
+ u8 portnum:4;
|
||||
+ u8 unused:4;
|
||||
+ u8 reg_iir;
|
||||
+ union {
|
||||
+ u8 lsr_signal;
|
||||
+ u8 modem_signal;
|
||||
+ u8 init_data[10];
|
||||
+ };
|
||||
+} __packed;
|
||||
+
|
||||
+static void ch348_process_status_urb(struct urb *urb)
|
||||
+{
|
||||
+ struct ch348_status_entry *status_entry;
|
||||
+ struct ch348 *ch348 = urb->context;
|
||||
+ int ret, status = urb->status;
|
||||
+ struct usb_serial_port *port;
|
||||
+ unsigned int i, status_len;
|
||||
+
|
||||
+ switch (status) {
|
||||
+ case 0:
|
||||
+ /* success */
|
||||
+ break;
|
||||
+ case -ECONNRESET:
|
||||
+ case -ENOENT:
|
||||
+ case -ESHUTDOWN:
|
||||
+ /* this urb is terminated, clean up */
|
||||
+ dev_dbg(&urb->dev->dev, "%s - urb shutting down with status: %d\n",
|
||||
+ __func__, status);
|
||||
+ return;
|
||||
+ default:
|
||||
+ dev_err(&urb->dev->dev, "%s - nonzero urb status received: %d\n",
|
||||
+ __func__, status);
|
||||
+ goto exit;
|
||||
+ }
|
||||
+
|
||||
+ if (urb->actual_length < 3) {
|
||||
+ dev_warn(&ch348->udev->dev,
|
||||
+ "Received too short status buffer with %u bytes\n",
|
||||
+ urb->actual_length);
|
||||
+ goto exit;
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < urb->actual_length;) {
|
||||
+ status_entry = urb->transfer_buffer + i;
|
||||
+
|
||||
+ if (status_entry->portnum >= CH348_MAXPORT) {
|
||||
+ dev_warn(&ch348->udev->dev,
|
||||
+ "Invalid port %d in status entry\n",
|
||||
+ status_entry->portnum);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ port = ch348->serial->port[status_entry->portnum];
|
||||
+ status_len = 3;
|
||||
+
|
||||
+ if (!status_entry->reg_iir) {
|
||||
+ dev_dbg(&port->dev, "Ignoring status with zero reg_iir\n");
|
||||
+ } else if (status_entry->reg_iir == R_INIT) {
|
||||
+ status_len = 12;
|
||||
+ } else if ((status_entry->reg_iir & 0x0f) == R_II_B1) {
|
||||
+ if (status_entry->lsr_signal & CH348_LO)
|
||||
+ port->icount.overrun++;
|
||||
+ if (status_entry->lsr_signal & CH348_LP)
|
||||
+ port->icount.parity++;
|
||||
+ if (status_entry->lsr_signal & CH348_LF)
|
||||
+ port->icount.frame++;
|
||||
+ if (status_entry->lsr_signal & CH348_LF)
|
||||
+ port->icount.brk++;
|
||||
+ } else if ((status_entry->reg_iir & 0x0f) == R_II_B2) {
|
||||
+ complete_all(&ch348->ports[status_entry->portnum].write_completion);
|
||||
+ } else {
|
||||
+ dev_warn(&port->dev,
|
||||
+ "Unsupported status with reg_iir 0x%02x\n",
|
||||
+ status_entry->reg_iir);
|
||||
+ }
|
||||
+
|
||||
+ usb_serial_debug_data(&port->dev, __func__, status_len,
|
||||
+ urb->transfer_buffer + i);
|
||||
+
|
||||
+ i += status_len;
|
||||
+ }
|
||||
+
|
||||
+exit:
|
||||
+ ret = usb_submit_urb(urb, GFP_ATOMIC);
|
||||
+ if (ret)
|
||||
+ dev_err(&urb->dev->dev, "%s - usb_submit_urb failed; %d\n",
|
||||
+ __func__, ret);
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Some values came from vendor tree, and we have no meaning for them, this
|
||||
+ * function simply use them.
|
||||
+ */
|
||||
+static int ch348_do_magic(struct ch348 *ch348, int portnum, u8 action, u8 reg, u8 control)
|
||||
+{
|
||||
+ struct ch348_magic *buffer;
|
||||
+ int ret, len;
|
||||
+
|
||||
+ buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
|
||||
+ if (!buffer)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ if (portnum < 4)
|
||||
+ reg += 0x10 * portnum;
|
||||
+ else
|
||||
+ reg += 0x10 * (portnum - 4) + 0x08;
|
||||
+
|
||||
+ buffer->action = action;
|
||||
+ buffer->reg = reg;
|
||||
+ buffer->control = control;
|
||||
+
|
||||
+ ret = usb_bulk_msg(ch348->udev, ch348->cmd_ep, buffer, 3, &len,
|
||||
+ CH348_CMD_TIMEOUT);
|
||||
+ if (ret)
|
||||
+ dev_err(&ch348->udev->dev, "Failed to write magic err=%d\n", ret);
|
||||
+
|
||||
+ kfree(buffer);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int ch348_configure(struct ch348 *ch348, int portnum)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = ch348_do_magic(ch348, portnum, CMD_W_R, R_C2, 0x87);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ return ch348_do_magic(ch348, portnum, CMD_W_R, R_C4, 0x08);
|
||||
+}
|
||||
+
|
||||
+static void ch348_process_read_urb(struct urb *urb)
|
||||
+{
|
||||
+ struct usb_serial_port *port = urb->context;
|
||||
+ struct ch348 *ch348 = usb_get_serial_data(port->serial);
|
||||
+ unsigned int portnum, usblen, i;
|
||||
+ struct ch348_rxbuf *rxb;
|
||||
+
|
||||
+ if (urb->actual_length < 2) {
|
||||
+ dev_dbg(&ch348->udev->dev, "Empty rx buffer\n");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < urb->actual_length; i += CH348_RX_PORT_CHUNK_LENGTH) {
|
||||
+ rxb = urb->transfer_buffer + i;
|
||||
+ portnum = rxb->port;
|
||||
+ if (portnum >= CH348_MAXPORT) {
|
||||
+ dev_dbg(&ch348->udev->dev, "Invalid port %d\n", portnum);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ port = ch348->serial->port[portnum];
|
||||
+
|
||||
+ usblen = rxb->length;
|
||||
+ if (usblen > CH348_RX_PORT_MAX_LENGTH) {
|
||||
+ dev_dbg(&port->dev, "Invalid length %d for port %d\n",
|
||||
+ usblen, portnum);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ tty_insert_flip_string(&port->port, rxb->data, usblen);
|
||||
+ tty_flip_buffer_push(&port->port);
|
||||
+ port->icount.rx += usblen;
|
||||
+ usb_serial_debug_data(&port->dev, __func__, usblen, rxb->data);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int ch348_prepare_write_buffer(struct usb_serial_port *port, void *dest, size_t size)
|
||||
+{
|
||||
+ struct ch348_txbuf *rxt = dest;
|
||||
+ int count;
|
||||
+
|
||||
+ count = kfifo_out_locked(&port->write_fifo, rxt->data,
|
||||
+ size - CH348_TX_HDRSIZE, &port->lock);
|
||||
+
|
||||
+ rxt->port = port->port_number;
|
||||
+ rxt->length = cpu_to_le16(count);
|
||||
+
|
||||
+ return count + CH348_TX_HDRSIZE;
|
||||
+}
|
||||
+
|
||||
+static int ch348_write(struct tty_struct *tty, struct usb_serial_port *port,
|
||||
+ const unsigned char *buf, int count)
|
||||
+{
|
||||
+ struct ch348 *ch348 = usb_get_serial_data(port->serial);
|
||||
+ struct ch348_port *ch348_port = &ch348->ports[port->port_number];
|
||||
+ int ret, max_tx_size;
|
||||
+
|
||||
+ if (tty_get_baud_rate(tty) < 9600 && count >= 128)
|
||||
+ /*
|
||||
+ * Writing larger buffers can take longer than the hardware
|
||||
+ * allows before discarding the write buffer. Limit the
|
||||
+ * transfer size in such cases.
|
||||
+ * These values have been found by empirical testing.
|
||||
+ */
|
||||
+ max_tx_size = 128;
|
||||
+ else
|
||||
+ /*
|
||||
+ * Only ingest as many bytes as we can transfer with one URB at
|
||||
+ * a time. Once an URB has been written we need to wait for the
|
||||
+ * R_II_B2 status event before we are allowed to send more data.
|
||||
+ * If we ingest more data then usb_serial_generic_write() will
|
||||
+ * internally try to process as much data as possible with any
|
||||
+ * number of URBs without giving us the chance to wait in
|
||||
+ * between transfers.
|
||||
+ */
|
||||
+ max_tx_size = port->bulk_out_size - CH348_TX_HDRSIZE;
|
||||
+
|
||||
+ reinit_completion(&ch348_port->write_completion);
|
||||
+
|
||||
+ mutex_lock(&ch348->write_lock);
|
||||
+
|
||||
+ /*
|
||||
+ * For any (remaining) bytes that we did not transfer TTY core will
|
||||
+ * call us again, with the buffer and count adjusted to the remaining
|
||||
+ * data.
|
||||
+ */
|
||||
+ ret = usb_serial_generic_write(tty, port, buf, min(count, max_tx_size));
|
||||
+
|
||||
+ mutex_unlock(&ch348->write_lock);
|
||||
+
|
||||
+ if (ret <= 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ if (!wait_for_completion_interruptible_timeout(&ch348_port->write_completion,
|
||||
+ msecs_to_jiffies(CH348_CMD_TIMEOUT))) {
|
||||
+ dev_err_console(port, "Failed to wait for TX buffer flush\n");
|
||||
+ return -ETIMEDOUT;
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int ch348_set_uartmode(struct ch348 *ch348, int portnum, u8 mode)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ if (ch348->ports[portnum].uartmode == M_NOR && mode == M_HF) {
|
||||
+ ret = ch348_do_magic(ch348, portnum, CMD_W_BR, R_C4, 0x51);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ ch348->ports[portnum].uartmode = M_HF;
|
||||
+ }
|
||||
+
|
||||
+ if (ch348->ports[portnum].uartmode == M_HF && mode == M_NOR) {
|
||||
+ ret = ch348_do_magic(ch348, portnum, CMD_W_BR, R_C4, 0x50);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ ch348->ports[portnum].uartmode = M_NOR;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void ch348_set_termios(struct tty_struct *tty, struct usb_serial_port *port,
|
||||
+ const struct ktermios *termios_old)
|
||||
+{
|
||||
+ struct ch348 *ch348 = usb_get_serial_data(port->serial);
|
||||
+ struct ktermios *termios = &tty->termios;
|
||||
+ int ret, portnum = port->port_number;
|
||||
+ struct ch348_initbuf *buffer;
|
||||
+ speed_t baudrate;
|
||||
+ u8 format;
|
||||
+
|
||||
+ if (termios_old && !tty_termios_hw_change(&tty->termios, termios_old))
|
||||
+ return;
|
||||
+
|
||||
+ buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
|
||||
+ if (!buffer) {
|
||||
+ if (termios_old)
|
||||
+ tty->termios = *termios_old;
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * The datasheet states that only baud rates in range of 1200..6000000
|
||||
+ * are supported. Tests however show that even baud rates as low as 50
|
||||
+ * and as high as 12000000 are working in practice.
|
||||
+ */
|
||||
+ baudrate = clamp(tty_get_baud_rate(tty), 50, 12000000);
|
||||
+
|
||||
+ format = termios->c_cflag & CSTOPB ? 2 : 1;
|
||||
+
|
||||
+ buffer->paritytype = 0;
|
||||
+ if (termios->c_cflag & PARENB) {
|
||||
+ if (termios->c_cflag & PARODD)
|
||||
+ buffer->paritytype += 1;
|
||||
+ else
|
||||
+ buffer->paritytype += 2;
|
||||
+ if (termios->c_cflag & CMSPAR)
|
||||
+ buffer->paritytype += 2;
|
||||
+ }
|
||||
+
|
||||
+ switch (C_CSIZE(tty)) {
|
||||
+ case CS5:
|
||||
+ buffer->databits = 5;
|
||||
+ break;
|
||||
+ case CS6:
|
||||
+ buffer->databits = 6;
|
||||
+ break;
|
||||
+ case CS7:
|
||||
+ buffer->databits = 7;
|
||||
+ break;
|
||||
+ case CS8:
|
||||
+ default:
|
||||
+ buffer->databits = 8;
|
||||
+ break;
|
||||
+ }
|
||||
+ buffer->cmd = CMD_WB_E | (portnum & 0x0F);
|
||||
+ buffer->reg = R_INIT;
|
||||
+ buffer->port = portnum;
|
||||
+ buffer->baudrate = cpu_to_be32(baudrate);
|
||||
+
|
||||
+ if (format == 2)
|
||||
+ buffer->format = 0x02;
|
||||
+ else if (format == 1)
|
||||
+ buffer->format = 0x00;
|
||||
+
|
||||
+ buffer->rate = max_t(speed_t, 5, (10000 * 15 / baudrate) + 1);
|
||||
+
|
||||
+ ret = usb_bulk_msg(ch348->udev, ch348->cmd_ep, buffer,
|
||||
+ sizeof(*buffer), NULL, CH348_CMD_TIMEOUT);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(&ch348->udev->dev, "Failed to change line settings: err=%d\n",
|
||||
+ ret);
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ ret = ch348_do_magic(ch348, portnum, CMD_W_R, R_C1, 0x0F);
|
||||
+ if (ret < 0)
|
||||
+ goto out;
|
||||
+
|
||||
+ if (C_CRTSCTS(tty))
|
||||
+ ret = ch348_set_uartmode(ch348, portnum, M_HF);
|
||||
+ else
|
||||
+ ret = ch348_set_uartmode(ch348, portnum, M_NOR);
|
||||
+
|
||||
+out:
|
||||
+ kfree(buffer);
|
||||
+}
|
||||
+
|
||||
+static int ch348_open(struct tty_struct *tty, struct usb_serial_port *port)
|
||||
+{
|
||||
+ struct ch348 *ch348 = usb_get_serial_data(port->serial);
|
||||
+ int ret;
|
||||
+
|
||||
+ if (tty)
|
||||
+ ch348_set_termios(tty, port, NULL);
|
||||
+
|
||||
+ ret = ch348_configure(ch348, port->port_number);
|
||||
+ if (ret) {
|
||||
+ dev_err(&ch348->udev->dev, "Fail to configure err=%d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ return usb_serial_generic_open(tty, port);
|
||||
+}
|
||||
+
|
||||
+static int ch348_attach(struct usb_serial *serial)
|
||||
+{
|
||||
+ struct usb_endpoint_descriptor *epcmd, *epstatus;
|
||||
+ struct usb_serial_port *port0 = serial->port[1];
|
||||
+ struct usb_device *usb_dev = serial->dev;
|
||||
+ int status_buffer_size, i, ret;
|
||||
+ struct usb_interface *intf;
|
||||
+ struct ch348 *ch348;
|
||||
+
|
||||
+ intf = usb_ifnum_to_if(usb_dev, 0);
|
||||
+ epstatus = &intf->cur_altsetting->endpoint[2].desc;
|
||||
+ epcmd = &intf->cur_altsetting->endpoint[3].desc;
|
||||
+
|
||||
+ status_buffer_size = usb_endpoint_maxp(epstatus);
|
||||
+
|
||||
+ ch348 = kzalloc(struct_size(ch348, status_buffer, status_buffer_size),
|
||||
+ GFP_KERNEL);
|
||||
+ if (!ch348)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ usb_set_serial_data(serial, ch348);
|
||||
+
|
||||
+ ch348->udev = serial->dev;
|
||||
+ ch348->serial = serial;
|
||||
+ mutex_init(&ch348->write_lock);
|
||||
+
|
||||
+ for (i = 0; i < CH348_MAXPORT; i++)
|
||||
+ init_completion(&ch348->ports[i].write_completion);
|
||||
+
|
||||
+ ch348->status_urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||
+ if (!ch348->status_urb) {
|
||||
+ ret = -ENOMEM;
|
||||
+ goto err_free_ch348;
|
||||
+ }
|
||||
+
|
||||
+ usb_fill_bulk_urb(ch348->status_urb, ch348->udev,
|
||||
+ usb_rcvbulkpipe(ch348->udev, epstatus->bEndpointAddress),
|
||||
+ ch348->status_buffer, status_buffer_size,
|
||||
+ ch348_process_status_urb, ch348);
|
||||
+
|
||||
+ ret = usb_submit_urb(ch348->status_urb, GFP_KERNEL);
|
||||
+ if (ret) {
|
||||
+ dev_err(&ch348->udev->dev,
|
||||
+ "%s - failed to submit status/interrupt urb %i\n",
|
||||
+ __func__, ret);
|
||||
+ goto err_free_status_urb;
|
||||
+ }
|
||||
+
|
||||
+ ret = usb_serial_generic_submit_read_urbs(port0, GFP_KERNEL);
|
||||
+ if (ret)
|
||||
+ goto err_kill_status_urb;
|
||||
+
|
||||
+ ch348->cmd_ep = usb_sndbulkpipe(usb_dev, epcmd->bEndpointAddress);
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+err_kill_status_urb:
|
||||
+ usb_kill_urb(ch348->status_urb);
|
||||
+err_free_status_urb:
|
||||
+ usb_free_urb(ch348->status_urb);
|
||||
+err_free_ch348:
|
||||
+ kfree(ch348);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static void ch348_release(struct usb_serial *serial)
|
||||
+{
|
||||
+ struct ch348 *ch348 = usb_get_serial_data(serial);
|
||||
+
|
||||
+ usb_kill_urb(ch348->status_urb);
|
||||
+ usb_free_urb(ch348->status_urb);
|
||||
+
|
||||
+ kfree(ch348);
|
||||
+}
|
||||
+
|
||||
+static void ch348_print_version(struct usb_serial *serial)
|
||||
+{
|
||||
+ u8 *version_buf;
|
||||
+ int ret;
|
||||
+
|
||||
+ version_buf = kzalloc(4, GFP_KERNEL);
|
||||
+ if (!version_buf)
|
||||
+ return;
|
||||
+
|
||||
+ ret = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
|
||||
+ CMD_VER,
|
||||
+ USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
|
||||
+ 0, 0, version_buf, 4, CH348_CMD_TIMEOUT);
|
||||
+ if (ret < 0)
|
||||
+ dev_dbg(&serial->dev->dev, "Failed to read CMD_VER: %d\n", ret);
|
||||
+ else
|
||||
+ dev_info(&serial->dev->dev, "Found WCH CH348%s\n",
|
||||
+ (version_buf[1] & 0x80) ? "Q" : "L");
|
||||
+
|
||||
+ kfree(version_buf);
|
||||
+}
|
||||
+
|
||||
+static int ch348_probe(struct usb_serial *serial, const struct usb_device_id *id)
|
||||
+{
|
||||
+ struct usb_endpoint_descriptor *epread, *epwrite, *epstatus, *epcmd;
|
||||
+ struct usb_device *usb_dev = serial->dev;
|
||||
+ struct usb_interface *intf;
|
||||
+ int ret;
|
||||
+
|
||||
+ intf = usb_ifnum_to_if(usb_dev, 0);
|
||||
+
|
||||
+ ret = usb_find_common_endpoints(intf->cur_altsetting, &epread, &epwrite,
|
||||
+ NULL, NULL);
|
||||
+ if (ret) {
|
||||
+ dev_err(&serial->dev->dev, "Failed to find basic endpoints ret=%d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ epstatus = &intf->cur_altsetting->endpoint[2].desc;
|
||||
+ if (!usb_endpoint_is_bulk_in(epstatus)) {
|
||||
+ dev_err(&serial->dev->dev, "Missing second bulk in (STATUS/INT)\n");
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ epcmd = &intf->cur_altsetting->endpoint[3].desc;
|
||||
+ if (!usb_endpoint_is_bulk_out(epcmd)) {
|
||||
+ dev_err(&serial->dev->dev, "Missing second bulk out (CMD)\n");
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ ch348_print_version(serial);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int ch348_calc_num_ports(struct usb_serial *serial,
|
||||
+ struct usb_serial_endpoints *epds)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 1; i < CH348_MAXPORT; ++i) {
|
||||
+ epds->bulk_out[i] = epds->bulk_out[0];
|
||||
+ epds->bulk_in[i] = epds->bulk_in[0];
|
||||
+ }
|
||||
+
|
||||
+ epds->num_bulk_out = CH348_MAXPORT;
|
||||
+ epds->num_bulk_in = CH348_MAXPORT;
|
||||
+
|
||||
+ return CH348_MAXPORT;
|
||||
+}
|
||||
+
|
||||
+static int ch348_suspend(struct usb_serial *serial, pm_message_t message)
|
||||
+{
|
||||
+ struct ch348 *ch348 = usb_get_serial_data(serial);
|
||||
+
|
||||
+ usb_kill_urb(ch348->status_urb);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int ch348_resume(struct usb_serial *serial)
|
||||
+{
|
||||
+ struct ch348 *ch348 = usb_get_serial_data(serial);
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = usb_submit_urb(ch348->status_urb, GFP_KERNEL);
|
||||
+ if (ret) {
|
||||
+ dev_err(&ch348->udev->dev,
|
||||
+ "%s - failed to submit status/interrupt urb %i\n",
|
||||
+ __func__, ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ ret = usb_serial_generic_resume(serial);
|
||||
+ if (ret)
|
||||
+ usb_kill_urb(ch348->status_urb);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static const struct usb_device_id ch348_ids[] = {
|
||||
+ { USB_DEVICE(0x1a86, 0x55d9), },
|
||||
+ { /* sentinel */ }
|
||||
+};
|
||||
+
|
||||
+MODULE_DEVICE_TABLE(usb, ch348_ids);
|
||||
+
|
||||
+static struct usb_serial_driver ch348_device = {
|
||||
+ .driver = {
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .name = "ch348",
|
||||
+ },
|
||||
+ .id_table = ch348_ids,
|
||||
+ .num_ports = CH348_MAXPORT,
|
||||
+ .num_bulk_in = 1,
|
||||
+ .num_bulk_out = 1,
|
||||
+ .open = ch348_open,
|
||||
+ .set_termios = ch348_set_termios,
|
||||
+ .process_read_urb = ch348_process_read_urb,
|
||||
+ .prepare_write_buffer = ch348_prepare_write_buffer,
|
||||
+ .write = ch348_write,
|
||||
+ .probe = ch348_probe,
|
||||
+ .calc_num_ports = ch348_calc_num_ports,
|
||||
+ .attach = ch348_attach,
|
||||
+ .release = ch348_release,
|
||||
+ .suspend = ch348_suspend,
|
||||
+ .resume = ch348_resume,
|
||||
+};
|
||||
+
|
||||
+static struct usb_serial_driver * const serial_drivers[] = {
|
||||
+ &ch348_device, NULL
|
||||
+};
|
||||
+
|
||||
+module_usb_serial_driver(serial_drivers, ch348_ids);
|
||||
+
|
||||
+MODULE_AUTHOR("Corentin Labbe <clabbe@baylibre.com>");
|
||||
+MODULE_DESCRIPTION("USB CH348 Octo port serial converter driver");
|
||||
+MODULE_LICENSE("GPL");
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue