mirror of
https://github.com/coolsnowwolf/lede.git
synced 2025-04-16 04:13:31 +00:00
kernel: bump 5.10 to 5.10.110
This commit is contained in:
parent
4ae5d37ca1
commit
aa0101a649
@ -1,2 +1,2 @@
|
||||
LINUX_VERSION-5.10 = .109
|
||||
LINUX_KERNEL_HASH-5.10.109 = 18fb22ecb249669ea775474aee614dcb0697cab299068074fd9f0bafa32113dc
|
||||
LINUX_VERSION-5.10 = .110
|
||||
LINUX_KERNEL_HASH-5.10.110 = dbef6a06325433481551cb8cfca9254d908d0ae950bc809f3da8ade00c485693
|
||||
|
@ -0,0 +1,27 @@
|
||||
From 1027a42c25cbf8cfc4ade6503c5110aae04866af Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Daniel=20Gonz=C3=A1lez=20Cabanelas?= <dgcbueu@gmail.com>
|
||||
Date: Fri, 16 Oct 2020 20:22:37 +0200
|
||||
Subject: [PATCH] power: reset: linkstation-poweroff: add missing put_device()
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The of_mdio_find_bus() takes a reference to the underlying device
|
||||
structure, we should release that reference using a put_device() call.
|
||||
|
||||
Signed-off-by: Daniel González Cabanelas <dgcbueu@gmail.com>
|
||||
Signed-off-by: Sebastian Reichel <sre@kernel.org>
|
||||
---
|
||||
drivers/power/reset/linkstation-poweroff.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/drivers/power/reset/linkstation-poweroff.c
|
||||
+++ b/drivers/power/reset/linkstation-poweroff.c
|
||||
@@ -113,6 +113,7 @@ static int __init linkstation_poweroff_i
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
phydev = phy_find_first(bus);
|
||||
+ put_device(&bus->dev);
|
||||
if (!phydev)
|
||||
return -EPROBE_DEFER;
|
||||
|
@ -0,0 +1,65 @@
|
||||
From: Johan Almbladh <johan.almbladh@anyfinetworks.com>
|
||||
Date: Tue, 5 Oct 2021 18:54:02 +0200
|
||||
Subject: [PATCH] MIPS: uasm: Enable muhu opcode for MIPS R6
|
||||
|
||||
Enable the 'muhu' instruction, complementing the existing 'mulu', needed
|
||||
to implement a MIPS32 BPF JIT.
|
||||
|
||||
Also fix a typo in the existing definition of 'dmulu'.
|
||||
|
||||
Signed-off-by: Tony Ambardar <Tony.Ambardar@gmail.com>
|
||||
|
||||
This patch is a dependency for my 32-bit MIPS eBPF JIT.
|
||||
|
||||
Signed-off-by: Johan Almbladh <johan.almbladh@anyfinetworks.com>
|
||||
---
|
||||
|
||||
--- a/arch/mips/include/asm/uasm.h
|
||||
+++ b/arch/mips/include/asm/uasm.h
|
||||
@@ -145,6 +145,7 @@ Ip_u1(_mtlo);
|
||||
Ip_u3u1u2(_mul);
|
||||
Ip_u1u2(_multu);
|
||||
Ip_u3u1u2(_mulu);
|
||||
+Ip_u3u1u2(_muhu);
|
||||
Ip_u3u1u2(_nor);
|
||||
Ip_u3u1u2(_or);
|
||||
Ip_u2u1u3(_ori);
|
||||
--- a/arch/mips/mm/uasm-mips.c
|
||||
+++ b/arch/mips/mm/uasm-mips.c
|
||||
@@ -90,7 +90,7 @@ static const struct insn insn_table[insn
|
||||
RS | RT | RD},
|
||||
[insn_dmtc0] = {M(cop0_op, dmtc_op, 0, 0, 0, 0), RT | RD | SET},
|
||||
[insn_dmultu] = {M(spec_op, 0, 0, 0, 0, dmultu_op), RS | RT},
|
||||
- [insn_dmulu] = {M(spec_op, 0, 0, 0, dmult_dmul_op, dmultu_op),
|
||||
+ [insn_dmulu] = {M(spec_op, 0, 0, 0, dmultu_dmulu_op, dmultu_op),
|
||||
RS | RT | RD},
|
||||
[insn_drotr] = {M(spec_op, 1, 0, 0, 0, dsrl_op), RT | RD | RE},
|
||||
[insn_drotr32] = {M(spec_op, 1, 0, 0, 0, dsrl32_op), RT | RD | RE},
|
||||
@@ -150,6 +150,8 @@ static const struct insn insn_table[insn
|
||||
[insn_mtlo] = {M(spec_op, 0, 0, 0, 0, mtlo_op), RS},
|
||||
[insn_mulu] = {M(spec_op, 0, 0, 0, multu_mulu_op, multu_op),
|
||||
RS | RT | RD},
|
||||
+ [insn_muhu] = {M(spec_op, 0, 0, 0, multu_muhu_op, multu_op),
|
||||
+ RS | RT | RD},
|
||||
#ifndef CONFIG_CPU_MIPSR6
|
||||
[insn_mul] = {M(spec2_op, 0, 0, 0, 0, mul_op), RS | RT | RD},
|
||||
#else
|
||||
--- a/arch/mips/mm/uasm.c
|
||||
+++ b/arch/mips/mm/uasm.c
|
||||
@@ -59,7 +59,7 @@ enum opcode {
|
||||
insn_lddir, insn_ldpte, insn_ldx, insn_lh, insn_lhu, insn_ll, insn_lld,
|
||||
insn_lui, insn_lw, insn_lwu, insn_lwx, insn_mfc0, insn_mfhc0, insn_mfhi,
|
||||
insn_mflo, insn_modu, insn_movn, insn_movz, insn_mtc0, insn_mthc0,
|
||||
- insn_mthi, insn_mtlo, insn_mul, insn_multu, insn_mulu, insn_nor,
|
||||
+ insn_mthi, insn_mtlo, insn_mul, insn_multu, insn_mulu, insn_muhu, insn_nor,
|
||||
insn_or, insn_ori, insn_pref, insn_rfe, insn_rotr, insn_sb, insn_sc,
|
||||
insn_scd, insn_seleqz, insn_selnez, insn_sd, insn_sh, insn_sll,
|
||||
insn_sllv, insn_slt, insn_slti, insn_sltiu, insn_sltu, insn_sra,
|
||||
@@ -344,6 +344,7 @@ I_u1(_mtlo)
|
||||
I_u3u1u2(_mul)
|
||||
I_u1u2(_multu)
|
||||
I_u3u1u2(_mulu)
|
||||
+I_u3u1u2(_muhu)
|
||||
I_u3u1u2(_nor)
|
||||
I_u3u1u2(_or)
|
||||
I_u2u1u3(_ori)
|
@ -0,0 +1,31 @@
|
||||
From: Johan Almbladh <johan.almbladh@anyfinetworks.com>
|
||||
Date: Tue, 5 Oct 2021 18:54:03 +0200
|
||||
Subject: [PATCH] mips: uasm: Add workaround for Loongson-2F nop CPU errata
|
||||
|
||||
This patch implements a workaround for the Loongson-2F nop in generated,
|
||||
code, if the existing option CONFIG_CPU_NOP_WORKAROUND is set. Before,
|
||||
the binutils option -mfix-loongson2f-nop was enabled, but no workaround
|
||||
was done when emitting MIPS code. Now, the nop pseudo instruction is
|
||||
emitted as "or ax,ax,zero" instead of the default "sll zero,zero,0". This
|
||||
is consistent with the workaround implemented by binutils.
|
||||
|
||||
Link: https://sourceware.org/legacy-ml/binutils/2009-11/msg00387.html
|
||||
|
||||
Signed-off-by: Johan Almbladh <johan.almbladh@anyfinetworks.com>
|
||||
Reviewed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
|
||||
---
|
||||
|
||||
--- a/arch/mips/include/asm/uasm.h
|
||||
+++ b/arch/mips/include/asm/uasm.h
|
||||
@@ -249,7 +249,11 @@ static inline void uasm_l##lb(struct uas
|
||||
#define uasm_i_bnezl(buf, rs, off) uasm_i_bnel(buf, rs, 0, off)
|
||||
#define uasm_i_ehb(buf) uasm_i_sll(buf, 0, 0, 3)
|
||||
#define uasm_i_move(buf, a, b) UASM_i_ADDU(buf, a, 0, b)
|
||||
+#ifdef CONFIG_CPU_NOP_WORKAROUNDS
|
||||
+#define uasm_i_nop(buf) uasm_i_or(buf, 1, 1, 0)
|
||||
+#else
|
||||
#define uasm_i_nop(buf) uasm_i_sll(buf, 0, 0, 0)
|
||||
+#endif
|
||||
#define uasm_i_ssnop(buf) uasm_i_sll(buf, 0, 0, 1)
|
||||
|
||||
static inline void uasm_i_drotr_safe(u32 **p, unsigned int a1,
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,120 @@
|
||||
From: Johan Almbladh <johan.almbladh@anyfinetworks.com>
|
||||
Date: Tue, 5 Oct 2021 18:54:06 +0200
|
||||
Subject: [PATCH] mips: bpf: Add JIT workarounds for CPU errata
|
||||
|
||||
This patch adds workarounds for the following CPU errata to the MIPS
|
||||
eBPF JIT, if enabled in the kernel configuration.
|
||||
|
||||
- R10000 ll/sc weak ordering
|
||||
- Loongson-3 ll/sc weak ordering
|
||||
- Loongson-2F jump hang
|
||||
|
||||
The Loongson-2F nop errata is implemented in uasm, which the JIT uses,
|
||||
so no additional mitigations are needed for that.
|
||||
|
||||
Signed-off-by: Johan Almbladh <johan.almbladh@anyfinetworks.com>
|
||||
Reviewed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
|
||||
---
|
||||
|
||||
--- a/arch/mips/net/bpf_jit_comp.c
|
||||
+++ b/arch/mips/net/bpf_jit_comp.c
|
||||
@@ -404,6 +404,7 @@ void emit_alu_r(struct jit_context *ctx,
|
||||
/* Atomic read-modify-write (32-bit) */
|
||||
void emit_atomic_r(struct jit_context *ctx, u8 dst, u8 src, s16 off, u8 code)
|
||||
{
|
||||
+ LLSC_sync(ctx);
|
||||
emit(ctx, ll, MIPS_R_T9, off, dst);
|
||||
switch (code) {
|
||||
case BPF_ADD:
|
||||
@@ -420,18 +421,19 @@ void emit_atomic_r(struct jit_context *c
|
||||
break;
|
||||
}
|
||||
emit(ctx, sc, MIPS_R_T8, off, dst);
|
||||
- emit(ctx, beqz, MIPS_R_T8, -16);
|
||||
+ emit(ctx, LLSC_beqz, MIPS_R_T8, -16 - LLSC_offset);
|
||||
emit(ctx, nop); /* Delay slot */
|
||||
}
|
||||
|
||||
/* Atomic compare-and-exchange (32-bit) */
|
||||
void emit_cmpxchg_r(struct jit_context *ctx, u8 dst, u8 src, u8 res, s16 off)
|
||||
{
|
||||
+ LLSC_sync(ctx);
|
||||
emit(ctx, ll, MIPS_R_T9, off, dst);
|
||||
emit(ctx, bne, MIPS_R_T9, res, 12);
|
||||
emit(ctx, move, MIPS_R_T8, src); /* Delay slot */
|
||||
emit(ctx, sc, MIPS_R_T8, off, dst);
|
||||
- emit(ctx, beqz, MIPS_R_T8, -20);
|
||||
+ emit(ctx, LLSC_beqz, MIPS_R_T8, -20 - LLSC_offset);
|
||||
emit(ctx, move, res, MIPS_R_T9); /* Delay slot */
|
||||
clobber_reg(ctx, res);
|
||||
}
|
||||
--- a/arch/mips/net/bpf_jit_comp.h
|
||||
+++ b/arch/mips/net/bpf_jit_comp.h
|
||||
@@ -87,7 +87,7 @@ struct jit_context {
|
||||
};
|
||||
|
||||
/* Emit the instruction if the JIT memory space has been allocated */
|
||||
-#define emit(ctx, func, ...) \
|
||||
+#define __emit(ctx, func, ...) \
|
||||
do { \
|
||||
if ((ctx)->target != NULL) { \
|
||||
u32 *p = &(ctx)->target[ctx->jit_index]; \
|
||||
@@ -95,6 +95,30 @@ do { \
|
||||
} \
|
||||
(ctx)->jit_index++; \
|
||||
} while (0)
|
||||
+#define emit(...) __emit(__VA_ARGS__)
|
||||
+
|
||||
+/* Workaround for R10000 ll/sc errata */
|
||||
+#ifdef CONFIG_WAR_R10000
|
||||
+#define LLSC_beqz beqzl
|
||||
+#else
|
||||
+#define LLSC_beqz beqz
|
||||
+#endif
|
||||
+
|
||||
+/* Workaround for Loongson-3 ll/sc errata */
|
||||
+#ifdef CONFIG_CPU_LOONGSON3_WORKAROUNDS
|
||||
+#define LLSC_sync(ctx) emit(ctx, sync, 0)
|
||||
+#define LLSC_offset 4
|
||||
+#else
|
||||
+#define LLSC_sync(ctx)
|
||||
+#define LLSC_offset 0
|
||||
+#endif
|
||||
+
|
||||
+/* Workaround for Loongson-2F jump errata */
|
||||
+#ifdef CONFIG_CPU_JUMP_WORKAROUNDS
|
||||
+#define JALR_MASK 0xffffffffcfffffffULL
|
||||
+#else
|
||||
+#define JALR_MASK (~0ULL)
|
||||
+#endif
|
||||
|
||||
/*
|
||||
* Mark a BPF register as accessed, it needs to be
|
||||
--- a/arch/mips/net/bpf_jit_comp64.c
|
||||
+++ b/arch/mips/net/bpf_jit_comp64.c
|
||||
@@ -375,6 +375,7 @@ static void emit_atomic_r64(struct jit_c
|
||||
u8 t1 = MIPS_R_T6;
|
||||
u8 t2 = MIPS_R_T7;
|
||||
|
||||
+ LLSC_sync(ctx);
|
||||
emit(ctx, lld, t1, off, dst);
|
||||
switch (code) {
|
||||
case BPF_ADD:
|
||||
@@ -391,7 +392,7 @@ static void emit_atomic_r64(struct jit_c
|
||||
break;
|
||||
}
|
||||
emit(ctx, scd, t2, off, dst);
|
||||
- emit(ctx, beqz, t2, -16);
|
||||
+ emit(ctx, LLSC_beqz, t2, -16 - LLSC_offset);
|
||||
emit(ctx, nop); /* Delay slot */
|
||||
}
|
||||
|
||||
@@ -414,7 +415,7 @@ static int emit_call(struct jit_context
|
||||
push_regs(ctx, ctx->clobbered & JIT_CALLER_REGS, 0, 0);
|
||||
|
||||
/* Emit function call */
|
||||
- emit_mov_i64(ctx, tmp, addr);
|
||||
+ emit_mov_i64(ctx, tmp, addr & JALR_MASK);
|
||||
emit(ctx, jalr, MIPS_R_RA, tmp);
|
||||
emit(ctx, nop); /* Delay slot */
|
||||
|
@ -0,0 +1,61 @@
|
||||
From: Johan Almbladh <johan.almbladh@anyfinetworks.com>
|
||||
Date: Tue, 5 Oct 2021 18:54:07 +0200
|
||||
Subject: [PATCH] mips: bpf: Enable eBPF JITs
|
||||
|
||||
This patch enables the new eBPF JITs for 32-bit and 64-bit MIPS. It also
|
||||
disables the old cBPF JIT to so cBPF programs are converted to use the
|
||||
new JIT.
|
||||
|
||||
Workarounds for R4000 CPU errata are not implemented by the JIT, so the
|
||||
JIT is disabled if any of those workarounds are configured.
|
||||
|
||||
Signed-off-by: Johan Almbladh <johan.almbladh@anyfinetworks.com>
|
||||
---
|
||||
|
||||
--- a/MAINTAINERS
|
||||
+++ b/MAINTAINERS
|
||||
@@ -3294,6 +3294,7 @@ S: Supported
|
||||
F: arch/arm64/net/
|
||||
|
||||
BPF JIT for MIPS (32-BIT AND 64-BIT)
|
||||
+M: Johan Almbladh <johan.almbladh@anyfinetworks.com>
|
||||
M: Paul Burton <paulburton@kernel.org>
|
||||
L: netdev@vger.kernel.org
|
||||
L: bpf@vger.kernel.org
|
||||
--- a/arch/mips/Kconfig
|
||||
+++ b/arch/mips/Kconfig
|
||||
@@ -49,7 +49,6 @@ config MIPS
|
||||
select HAVE_ARCH_TRACEHOOK
|
||||
select HAVE_ARCH_TRANSPARENT_HUGEPAGE if CPU_SUPPORTS_HUGEPAGES
|
||||
select HAVE_ASM_MODVERSIONS
|
||||
- select HAVE_CBPF_JIT if !64BIT && !CPU_MICROMIPS
|
||||
select HAVE_CONTEXT_TRACKING
|
||||
select HAVE_TIF_NOHZ
|
||||
select HAVE_C_RECORDMCOUNT
|
||||
@@ -57,7 +56,10 @@ config MIPS
|
||||
select HAVE_DEBUG_STACKOVERFLOW
|
||||
select HAVE_DMA_CONTIGUOUS
|
||||
select HAVE_DYNAMIC_FTRACE
|
||||
- select HAVE_EBPF_JIT if 64BIT && !CPU_MICROMIPS && TARGET_ISA_REV >= 2
|
||||
+ select HAVE_EBPF_JIT if !CPU_MICROMIPS && \
|
||||
+ !CPU_DADDI_WORKAROUNDS && \
|
||||
+ !CPU_R4000_WORKAROUNDS && \
|
||||
+ !CPU_R4400_WORKAROUNDS
|
||||
select HAVE_EXIT_THREAD
|
||||
select HAVE_FAST_GUP
|
||||
select HAVE_FTRACE_MCOUNT_RECORD
|
||||
--- a/arch/mips/net/Makefile
|
||||
+++ b/arch/mips/net/Makefile
|
||||
@@ -2,9 +2,10 @@
|
||||
# MIPS networking code
|
||||
|
||||
obj-$(CONFIG_MIPS_CBPF_JIT) += bpf_jit.o bpf_jit_asm.o
|
||||
+obj-$(CONFIG_MIPS_EBPF_JIT) += bpf_jit_comp.o
|
||||
|
||||
ifeq ($(CONFIG_32BIT),y)
|
||||
- obj-$(CONFIG_MIPS_EBPF_JIT) += bpf_jit_comp.o bpf_jit_comp32.o
|
||||
+ obj-$(CONFIG_MIPS_EBPF_JIT) += bpf_jit_comp32.o
|
||||
else
|
||||
- obj-$(CONFIG_MIPS_EBPF_JIT) += ebpf_jit.o
|
||||
+ obj-$(CONFIG_MIPS_EBPF_JIT) += bpf_jit_comp64.o
|
||||
endif
|
@ -0,0 +1,387 @@
|
||||
From: Johan Almbladh <johan.almbladh@anyfinetworks.com>
|
||||
Date: Tue, 5 Oct 2021 18:54:08 +0200
|
||||
Subject: [PATCH] mips: bpf: Remove old BPF JIT implementations
|
||||
|
||||
This patch removes the old 32-bit cBPF and 64-bit eBPF JIT implementations.
|
||||
They are replaced by a new eBPF implementation that supports both 32-bit
|
||||
and 64-bit MIPS CPUs.
|
||||
|
||||
Signed-off-by: Johan Almbladh <johan.almbladh@anyfinetworks.com>
|
||||
---
|
||||
delete mode 100644 arch/mips/net/bpf_jit.c
|
||||
delete mode 100644 arch/mips/net/bpf_jit.h
|
||||
delete mode 100644 arch/mips/net/bpf_jit_asm.S
|
||||
delete mode 100644 arch/mips/net/ebpf_jit.c
|
||||
|
||||
--- a/arch/mips/net/bpf_jit.h
|
||||
+++ /dev/null
|
||||
@@ -1,81 +0,0 @@
|
||||
-/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
-/*
|
||||
- * Just-In-Time compiler for BPF filters on MIPS
|
||||
- *
|
||||
- * Copyright (c) 2014 Imagination Technologies Ltd.
|
||||
- * Author: Markos Chandras <markos.chandras@imgtec.com>
|
||||
- */
|
||||
-
|
||||
-#ifndef BPF_JIT_MIPS_OP_H
|
||||
-#define BPF_JIT_MIPS_OP_H
|
||||
-
|
||||
-/* Registers used by JIT */
|
||||
-#define MIPS_R_ZERO 0
|
||||
-#define MIPS_R_V0 2
|
||||
-#define MIPS_R_A0 4
|
||||
-#define MIPS_R_A1 5
|
||||
-#define MIPS_R_T4 12
|
||||
-#define MIPS_R_T5 13
|
||||
-#define MIPS_R_T6 14
|
||||
-#define MIPS_R_T7 15
|
||||
-#define MIPS_R_S0 16
|
||||
-#define MIPS_R_S1 17
|
||||
-#define MIPS_R_S2 18
|
||||
-#define MIPS_R_S3 19
|
||||
-#define MIPS_R_S4 20
|
||||
-#define MIPS_R_S5 21
|
||||
-#define MIPS_R_S6 22
|
||||
-#define MIPS_R_S7 23
|
||||
-#define MIPS_R_SP 29
|
||||
-#define MIPS_R_RA 31
|
||||
-
|
||||
-/* Conditional codes */
|
||||
-#define MIPS_COND_EQ 0x1
|
||||
-#define MIPS_COND_GE (0x1 << 1)
|
||||
-#define MIPS_COND_GT (0x1 << 2)
|
||||
-#define MIPS_COND_NE (0x1 << 3)
|
||||
-#define MIPS_COND_ALL (0x1 << 4)
|
||||
-/* Conditionals on X register or K immediate */
|
||||
-#define MIPS_COND_X (0x1 << 5)
|
||||
-#define MIPS_COND_K (0x1 << 6)
|
||||
-
|
||||
-#define r_ret MIPS_R_V0
|
||||
-
|
||||
-/*
|
||||
- * Use 2 scratch registers to avoid pipeline interlocks.
|
||||
- * There is no overhead during epilogue and prologue since
|
||||
- * any of the $s0-$s6 registers will only be preserved if
|
||||
- * they are going to actually be used.
|
||||
- */
|
||||
-#define r_skb_hl MIPS_R_S0 /* skb header length */
|
||||
-#define r_skb_data MIPS_R_S1 /* skb actual data */
|
||||
-#define r_off MIPS_R_S2
|
||||
-#define r_A MIPS_R_S3
|
||||
-#define r_X MIPS_R_S4
|
||||
-#define r_skb MIPS_R_S5
|
||||
-#define r_M MIPS_R_S6
|
||||
-#define r_skb_len MIPS_R_S7
|
||||
-#define r_s0 MIPS_R_T4 /* scratch reg 1 */
|
||||
-#define r_s1 MIPS_R_T5 /* scratch reg 2 */
|
||||
-#define r_tmp_imm MIPS_R_T6 /* No need to preserve this */
|
||||
-#define r_tmp MIPS_R_T7 /* No need to preserve this */
|
||||
-#define r_zero MIPS_R_ZERO
|
||||
-#define r_sp MIPS_R_SP
|
||||
-#define r_ra MIPS_R_RA
|
||||
-
|
||||
-#ifndef __ASSEMBLY__
|
||||
-
|
||||
-/* Declare ASM helpers */
|
||||
-
|
||||
-#define DECLARE_LOAD_FUNC(func) \
|
||||
- extern u8 func(unsigned long *skb, int offset); \
|
||||
- extern u8 func##_negative(unsigned long *skb, int offset); \
|
||||
- extern u8 func##_positive(unsigned long *skb, int offset)
|
||||
-
|
||||
-DECLARE_LOAD_FUNC(sk_load_word);
|
||||
-DECLARE_LOAD_FUNC(sk_load_half);
|
||||
-DECLARE_LOAD_FUNC(sk_load_byte);
|
||||
-
|
||||
-#endif
|
||||
-
|
||||
-#endif /* BPF_JIT_MIPS_OP_H */
|
||||
--- a/arch/mips/net/bpf_jit_asm.S
|
||||
+++ /dev/null
|
||||
@@ -1,285 +0,0 @@
|
||||
-/*
|
||||
- * bpf_jib_asm.S: Packet/header access helper functions for MIPS/MIPS64 BPF
|
||||
- * compiler.
|
||||
- *
|
||||
- * Copyright (C) 2015 Imagination Technologies Ltd.
|
||||
- * Author: Markos Chandras <markos.chandras@imgtec.com>
|
||||
- *
|
||||
- * This program is free software; you can redistribute it and/or modify it
|
||||
- * under the terms of the GNU General Public License as published by the
|
||||
- * Free Software Foundation; version 2 of the License.
|
||||
- */
|
||||
-
|
||||
-#include <asm/asm.h>
|
||||
-#include <asm/isa-rev.h>
|
||||
-#include <asm/regdef.h>
|
||||
-#include "bpf_jit.h"
|
||||
-
|
||||
-/* ABI
|
||||
- *
|
||||
- * r_skb_hl skb header length
|
||||
- * r_skb_data skb data
|
||||
- * r_off(a1) offset register
|
||||
- * r_A BPF register A
|
||||
- * r_X PF register X
|
||||
- * r_skb(a0) *skb
|
||||
- * r_M *scratch memory
|
||||
- * r_skb_le skb length
|
||||
- * r_s0 Scratch register 0
|
||||
- * r_s1 Scratch register 1
|
||||
- *
|
||||
- * On entry:
|
||||
- * a0: *skb
|
||||
- * a1: offset (imm or imm + X)
|
||||
- *
|
||||
- * All non-BPF-ABI registers are free for use. On return, we only
|
||||
- * care about r_ret. The BPF-ABI registers are assumed to remain
|
||||
- * unmodified during the entire filter operation.
|
||||
- */
|
||||
-
|
||||
-#define skb a0
|
||||
-#define offset a1
|
||||
-#define SKF_LL_OFF (-0x200000) /* Can't include linux/filter.h in assembly */
|
||||
-
|
||||
- /* We know better :) so prevent assembler reordering etc */
|
||||
- .set noreorder
|
||||
-
|
||||
-#define is_offset_negative(TYPE) \
|
||||
- /* If offset is negative we have more work to do */ \
|
||||
- slti t0, offset, 0; \
|
||||
- bgtz t0, bpf_slow_path_##TYPE##_neg; \
|
||||
- /* Be careful what follows in DS. */
|
||||
-
|
||||
-#define is_offset_in_header(SIZE, TYPE) \
|
||||
- /* Reading from header? */ \
|
||||
- addiu $r_s0, $r_skb_hl, -SIZE; \
|
||||
- slt t0, $r_s0, offset; \
|
||||
- bgtz t0, bpf_slow_path_##TYPE; \
|
||||
-
|
||||
-LEAF(sk_load_word)
|
||||
- is_offset_negative(word)
|
||||
-FEXPORT(sk_load_word_positive)
|
||||
- is_offset_in_header(4, word)
|
||||
- /* Offset within header boundaries */
|
||||
- PTR_ADDU t1, $r_skb_data, offset
|
||||
- .set reorder
|
||||
- lw $r_A, 0(t1)
|
||||
- .set noreorder
|
||||
-#ifdef CONFIG_CPU_LITTLE_ENDIAN
|
||||
-# if MIPS_ISA_REV >= 2
|
||||
- wsbh t0, $r_A
|
||||
- rotr $r_A, t0, 16
|
||||
-# else
|
||||
- sll t0, $r_A, 24
|
||||
- srl t1, $r_A, 24
|
||||
- srl t2, $r_A, 8
|
||||
- or t0, t0, t1
|
||||
- andi t2, t2, 0xff00
|
||||
- andi t1, $r_A, 0xff00
|
||||
- or t0, t0, t2
|
||||
- sll t1, t1, 8
|
||||
- or $r_A, t0, t1
|
||||
-# endif
|
||||
-#endif
|
||||
- jr $r_ra
|
||||
- move $r_ret, zero
|
||||
- END(sk_load_word)
|
||||
-
|
||||
-LEAF(sk_load_half)
|
||||
- is_offset_negative(half)
|
||||
-FEXPORT(sk_load_half_positive)
|
||||
- is_offset_in_header(2, half)
|
||||
- /* Offset within header boundaries */
|
||||
- PTR_ADDU t1, $r_skb_data, offset
|
||||
- lhu $r_A, 0(t1)
|
||||
-#ifdef CONFIG_CPU_LITTLE_ENDIAN
|
||||
-# if MIPS_ISA_REV >= 2
|
||||
- wsbh $r_A, $r_A
|
||||
-# else
|
||||
- sll t0, $r_A, 8
|
||||
- srl t1, $r_A, 8
|
||||
- andi t0, t0, 0xff00
|
||||
- or $r_A, t0, t1
|
||||
-# endif
|
||||
-#endif
|
||||
- jr $r_ra
|
||||
- move $r_ret, zero
|
||||
- END(sk_load_half)
|
||||
-
|
||||
-LEAF(sk_load_byte)
|
||||
- is_offset_negative(byte)
|
||||
-FEXPORT(sk_load_byte_positive)
|
||||
- is_offset_in_header(1, byte)
|
||||
- /* Offset within header boundaries */
|
||||
- PTR_ADDU t1, $r_skb_data, offset
|
||||
- lbu $r_A, 0(t1)
|
||||
- jr $r_ra
|
||||
- move $r_ret, zero
|
||||
- END(sk_load_byte)
|
||||
-
|
||||
-/*
|
||||
- * call skb_copy_bits:
|
||||
- * (prototype in linux/skbuff.h)
|
||||
- *
|
||||
- * int skb_copy_bits(sk_buff *skb, int offset, void *to, int len)
|
||||
- *
|
||||
- * o32 mandates we leave 4 spaces for argument registers in case
|
||||
- * the callee needs to use them. Even though we don't care about
|
||||
- * the argument registers ourselves, we need to allocate that space
|
||||
- * to remain ABI compliant since the callee may want to use that space.
|
||||
- * We also allocate 2 more spaces for $r_ra and our return register (*to).
|
||||
- *
|
||||
- * n64 is a bit different. The *caller* will allocate the space to preserve
|
||||
- * the arguments. So in 64-bit kernels, we allocate the 4-arg space for no
|
||||
- * good reason but it does not matter that much really.
|
||||
- *
|
||||
- * (void *to) is returned in r_s0
|
||||
- *
|
||||
- */
|
||||
-#ifdef CONFIG_CPU_LITTLE_ENDIAN
|
||||
-#define DS_OFFSET(SIZE) (4 * SZREG)
|
||||
-#else
|
||||
-#define DS_OFFSET(SIZE) ((4 * SZREG) + (4 - SIZE))
|
||||
-#endif
|
||||
-#define bpf_slow_path_common(SIZE) \
|
||||
- /* Quick check. Are we within reasonable boundaries? */ \
|
||||
- LONG_ADDIU $r_s1, $r_skb_len, -SIZE; \
|
||||
- sltu $r_s0, offset, $r_s1; \
|
||||
- beqz $r_s0, fault; \
|
||||
- /* Load 4th argument in DS */ \
|
||||
- LONG_ADDIU a3, zero, SIZE; \
|
||||
- PTR_ADDIU $r_sp, $r_sp, -(6 * SZREG); \
|
||||
- PTR_LA t0, skb_copy_bits; \
|
||||
- PTR_S $r_ra, (5 * SZREG)($r_sp); \
|
||||
- /* Assign low slot to a2 */ \
|
||||
- PTR_ADDIU a2, $r_sp, DS_OFFSET(SIZE); \
|
||||
- jalr t0; \
|
||||
- /* Reset our destination slot (DS but it's ok) */ \
|
||||
- INT_S zero, (4 * SZREG)($r_sp); \
|
||||
- /* \
|
||||
- * skb_copy_bits returns 0 on success and -EFAULT \
|
||||
- * on error. Our data live in a2. Do not bother with \
|
||||
- * our data if an error has been returned. \
|
||||
- */ \
|
||||
- /* Restore our frame */ \
|
||||
- PTR_L $r_ra, (5 * SZREG)($r_sp); \
|
||||
- INT_L $r_s0, (4 * SZREG)($r_sp); \
|
||||
- bltz v0, fault; \
|
||||
- PTR_ADDIU $r_sp, $r_sp, 6 * SZREG; \
|
||||
- move $r_ret, zero; \
|
||||
-
|
||||
-NESTED(bpf_slow_path_word, (6 * SZREG), $r_sp)
|
||||
- bpf_slow_path_common(4)
|
||||
-#ifdef CONFIG_CPU_LITTLE_ENDIAN
|
||||
-# if MIPS_ISA_REV >= 2
|
||||
- wsbh t0, $r_s0
|
||||
- jr $r_ra
|
||||
- rotr $r_A, t0, 16
|
||||
-# else
|
||||
- sll t0, $r_s0, 24
|
||||
- srl t1, $r_s0, 24
|
||||
- srl t2, $r_s0, 8
|
||||
- or t0, t0, t1
|
||||
- andi t2, t2, 0xff00
|
||||
- andi t1, $r_s0, 0xff00
|
||||
- or t0, t0, t2
|
||||
- sll t1, t1, 8
|
||||
- jr $r_ra
|
||||
- or $r_A, t0, t1
|
||||
-# endif
|
||||
-#else
|
||||
- jr $r_ra
|
||||
- move $r_A, $r_s0
|
||||
-#endif
|
||||
-
|
||||
- END(bpf_slow_path_word)
|
||||
-
|
||||
-NESTED(bpf_slow_path_half, (6 * SZREG), $r_sp)
|
||||
- bpf_slow_path_common(2)
|
||||
-#ifdef CONFIG_CPU_LITTLE_ENDIAN
|
||||
-# if MIPS_ISA_REV >= 2
|
||||
- jr $r_ra
|
||||
- wsbh $r_A, $r_s0
|
||||
-# else
|
||||
- sll t0, $r_s0, 8
|
||||
- andi t1, $r_s0, 0xff00
|
||||
- andi t0, t0, 0xff00
|
||||
- srl t1, t1, 8
|
||||
- jr $r_ra
|
||||
- or $r_A, t0, t1
|
||||
-# endif
|
||||
-#else
|
||||
- jr $r_ra
|
||||
- move $r_A, $r_s0
|
||||
-#endif
|
||||
-
|
||||
- END(bpf_slow_path_half)
|
||||
-
|
||||
-NESTED(bpf_slow_path_byte, (6 * SZREG), $r_sp)
|
||||
- bpf_slow_path_common(1)
|
||||
- jr $r_ra
|
||||
- move $r_A, $r_s0
|
||||
-
|
||||
- END(bpf_slow_path_byte)
|
||||
-
|
||||
-/*
|
||||
- * Negative entry points
|
||||
- */
|
||||
- .macro bpf_is_end_of_data
|
||||
- li t0, SKF_LL_OFF
|
||||
- /* Reading link layer data? */
|
||||
- slt t1, offset, t0
|
||||
- bgtz t1, fault
|
||||
- /* Be careful what follows in DS. */
|
||||
- .endm
|
||||
-/*
|
||||
- * call skb_copy_bits:
|
||||
- * (prototype in linux/filter.h)
|
||||
- *
|
||||
- * void *bpf_internal_load_pointer_neg_helper(const struct sk_buff *skb,
|
||||
- * int k, unsigned int size)
|
||||
- *
|
||||
- * see above (bpf_slow_path_common) for ABI restrictions
|
||||
- */
|
||||
-#define bpf_negative_common(SIZE) \
|
||||
- PTR_ADDIU $r_sp, $r_sp, -(6 * SZREG); \
|
||||
- PTR_LA t0, bpf_internal_load_pointer_neg_helper; \
|
||||
- PTR_S $r_ra, (5 * SZREG)($r_sp); \
|
||||
- jalr t0; \
|
||||
- li a2, SIZE; \
|
||||
- PTR_L $r_ra, (5 * SZREG)($r_sp); \
|
||||
- /* Check return pointer */ \
|
||||
- beqz v0, fault; \
|
||||
- PTR_ADDIU $r_sp, $r_sp, 6 * SZREG; \
|
||||
- /* Preserve our pointer */ \
|
||||
- move $r_s0, v0; \
|
||||
- /* Set return value */ \
|
||||
- move $r_ret, zero; \
|
||||
-
|
||||
-bpf_slow_path_word_neg:
|
||||
- bpf_is_end_of_data
|
||||
-NESTED(sk_load_word_negative, (6 * SZREG), $r_sp)
|
||||
- bpf_negative_common(4)
|
||||
- jr $r_ra
|
||||
- lw $r_A, 0($r_s0)
|
||||
- END(sk_load_word_negative)
|
||||
-
|
||||
-bpf_slow_path_half_neg:
|
||||
- bpf_is_end_of_data
|
||||
-NESTED(sk_load_half_negative, (6 * SZREG), $r_sp)
|
||||
- bpf_negative_common(2)
|
||||
- jr $r_ra
|
||||
- lhu $r_A, 0($r_s0)
|
||||
- END(sk_load_half_negative)
|
||||
-
|
||||
-bpf_slow_path_byte_neg:
|
||||
- bpf_is_end_of_data
|
||||
-NESTED(sk_load_byte_negative, (6 * SZREG), $r_sp)
|
||||
- bpf_negative_common(1)
|
||||
- jr $r_ra
|
||||
- lbu $r_A, 0($r_s0)
|
||||
- END(sk_load_byte_negative)
|
||||
-
|
||||
-fault:
|
||||
- jr $r_ra
|
||||
- addiu $r_ret, zero, 1
|
@ -0,0 +1,52 @@
|
||||
From 02d6fdecb9c38de19065f6bed8d5214556fd061d Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Thu, 4 Nov 2021 16:00:40 +0100
|
||||
Subject: regmap: allow to define reg_update_bits for no bus configuration
|
||||
|
||||
Some device requires a special handling for reg_update_bits and can't use
|
||||
the normal regmap read write logic. An example is when locking is
|
||||
handled by the device and rmw operations requires to do atomic operations.
|
||||
Allow to declare a dedicated function in regmap_config for
|
||||
reg_update_bits in no bus configuration.
|
||||
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Link: https://lore.kernel.org/r/20211104150040.1260-1-ansuelsmth@gmail.com
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
---
|
||||
drivers/base/regmap/regmap.c | 1 +
|
||||
include/linux/regmap.h | 7 +++++++
|
||||
2 files changed, 8 insertions(+)
|
||||
|
||||
--- a/drivers/base/regmap/regmap.c
|
||||
+++ b/drivers/base/regmap/regmap.c
|
||||
@@ -842,6 +842,7 @@ struct regmap *__regmap_init(struct devi
|
||||
if (!bus) {
|
||||
map->reg_read = config->reg_read;
|
||||
map->reg_write = config->reg_write;
|
||||
+ map->reg_update_bits = config->reg_update_bits;
|
||||
|
||||
map->defer_caching = false;
|
||||
goto skip_format_initialization;
|
||||
--- a/include/linux/regmap.h
|
||||
+++ b/include/linux/regmap.h
|
||||
@@ -289,6 +289,11 @@ typedef void (*regmap_unlock)(void *);
|
||||
* read operation on a bus such as SPI, I2C, etc. Most of the
|
||||
* devices do not need this.
|
||||
* @reg_write: Same as above for writing.
|
||||
+ * @reg_update_bits: Optional callback that if filled will be used to perform
|
||||
+ * all the update_bits(rmw) operation. Should only be provided
|
||||
+ * if the function require special handling with lock and reg
|
||||
+ * handling and the operation cannot be represented as a simple
|
||||
+ * update_bits operation on a bus such as SPI, I2C, etc.
|
||||
* @fast_io: Register IO is fast. Use a spinlock instead of a mutex
|
||||
* to perform locking. This field is ignored if custom lock/unlock
|
||||
* functions are used (see fields lock/unlock of struct regmap_config).
|
||||
@@ -366,6 +371,8 @@ struct regmap_config {
|
||||
|
||||
int (*reg_read)(void *context, unsigned int reg, unsigned int *val);
|
||||
int (*reg_write)(void *context, unsigned int reg, unsigned int val);
|
||||
+ int (*reg_update_bits)(void *context, unsigned int reg,
|
||||
+ unsigned int mask, unsigned int val);
|
||||
|
||||
bool fast_io;
|
||||
|
@ -1,152 +0,0 @@
|
||||
From 02591f9febd5f69bb4c266a4abf899c4cf21964f Mon Sep 17 00:00:00 2001
|
||||
From: Dai Ngo <dai.ngo@oracle.com>
|
||||
Date: Thu, 28 Jan 2021 01:42:26 -0500
|
||||
Subject: [PATCH] NFSv4_2: SSC helper should use its own config.
|
||||
|
||||
Currently NFSv4_2 SSC helper, nfs_ssc, incorrectly uses GRACE_PERIOD
|
||||
as its config. Fix by adding new config NFS_V4_2_SSC_HELPER which
|
||||
depends on NFS_V4_2 and is automatically selected when NFSD_V4 is
|
||||
enabled. Also removed the file name from a comment in nfs_ssc.c.
|
||||
|
||||
Signed-off-by: Dai Ngo <dai.ngo@oracle.com>
|
||||
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
|
||||
---
|
||||
fs/Kconfig | 4 ++++
|
||||
fs/nfs/nfs4file.c | 4 ++++
|
||||
fs/nfs/super.c | 12 ++++++++++++
|
||||
fs/nfs_common/Makefile | 2 +-
|
||||
fs/nfs_common/nfs_ssc.c | 2 --
|
||||
fs/nfsd/Kconfig | 1 +
|
||||
6 files changed, 22 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/fs/Kconfig b/fs/Kconfig
|
||||
index aa4c122823018b..a55bda4233bbea 100644
|
||||
--- a/fs/Kconfig
|
||||
+++ b/fs/Kconfig
|
||||
@@ -333,6 +333,10 @@ config NFS_COMMON
|
||||
depends on NFSD || NFS_FS || LOCKD
|
||||
default y
|
||||
|
||||
+config NFS_V4_2_SSC_HELPER
|
||||
+ tristate
|
||||
+ default y if NFS_V4=y || NFS_FS=y
|
||||
+
|
||||
source "net/sunrpc/Kconfig"
|
||||
source "fs/ceph/Kconfig"
|
||||
source "fs/cifs/Kconfig"
|
||||
diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c
|
||||
index 57b3821d975a35..441a2fa073c8f2 100644
|
||||
--- a/fs/nfs/nfs4file.c
|
||||
+++ b/fs/nfs/nfs4file.c
|
||||
@@ -420,7 +420,9 @@ static const struct nfs4_ssc_client_ops nfs4_ssc_clnt_ops_tbl = {
|
||||
*/
|
||||
void nfs42_ssc_register_ops(void)
|
||||
{
|
||||
+#ifdef CONFIG_NFSD_V4
|
||||
nfs42_ssc_register(&nfs4_ssc_clnt_ops_tbl);
|
||||
+#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -431,7 +433,9 @@ void nfs42_ssc_register_ops(void)
|
||||
*/
|
||||
void nfs42_ssc_unregister_ops(void)
|
||||
{
|
||||
+#ifdef CONFIG_NFSD_V4
|
||||
nfs42_ssc_unregister(&nfs4_ssc_clnt_ops_tbl);
|
||||
+#endif
|
||||
}
|
||||
#endif /* CONFIG_NFS_V4_2 */
|
||||
|
||||
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
|
||||
index 4034102010f055..c7a924580eec9c 100644
|
||||
--- a/fs/nfs/super.c
|
||||
+++ b/fs/nfs/super.c
|
||||
@@ -86,9 +86,11 @@ const struct super_operations nfs_sops = {
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(nfs_sops);
|
||||
|
||||
+#ifdef CONFIG_NFS_V4_2
|
||||
static const struct nfs_ssc_client_ops nfs_ssc_clnt_ops_tbl = {
|
||||
.sco_sb_deactive = nfs_sb_deactive,
|
||||
};
|
||||
+#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_NFS_V4)
|
||||
static int __init register_nfs4_fs(void)
|
||||
@@ -111,15 +113,21 @@ static void unregister_nfs4_fs(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
+#ifdef CONFIG_NFS_V4_2
|
||||
static void nfs_ssc_register_ops(void)
|
||||
{
|
||||
+#ifdef CONFIG_NFSD_V4
|
||||
nfs_ssc_register(&nfs_ssc_clnt_ops_tbl);
|
||||
+#endif
|
||||
}
|
||||
|
||||
static void nfs_ssc_unregister_ops(void)
|
||||
{
|
||||
+#ifdef CONFIG_NFSD_V4
|
||||
nfs_ssc_unregister(&nfs_ssc_clnt_ops_tbl);
|
||||
+#endif
|
||||
}
|
||||
+#endif /* CONFIG_NFS_V4_2 */
|
||||
|
||||
static struct shrinker acl_shrinker = {
|
||||
.count_objects = nfs_access_cache_count,
|
||||
@@ -148,7 +156,9 @@ int __init register_nfs_fs(void)
|
||||
ret = register_shrinker(&acl_shrinker);
|
||||
if (ret < 0)
|
||||
goto error_3;
|
||||
+#ifdef CONFIG_NFS_V4_2
|
||||
nfs_ssc_register_ops();
|
||||
+#endif
|
||||
return 0;
|
||||
error_3:
|
||||
nfs_unregister_sysctl();
|
||||
@@ -168,7 +178,9 @@ void __exit unregister_nfs_fs(void)
|
||||
unregister_shrinker(&acl_shrinker);
|
||||
nfs_unregister_sysctl();
|
||||
unregister_nfs4_fs();
|
||||
+#ifdef CONFIG_NFS_V4_2
|
||||
nfs_ssc_unregister_ops();
|
||||
+#endif
|
||||
unregister_filesystem(&nfs_fs_type);
|
||||
}
|
||||
|
||||
diff --git a/fs/nfs_common/Makefile b/fs/nfs_common/Makefile
|
||||
index fa82f5aaa6d95b..119c75ab9fd08e 100644
|
||||
--- a/fs/nfs_common/Makefile
|
||||
+++ b/fs/nfs_common/Makefile
|
||||
@@ -7,4 +7,4 @@ obj-$(CONFIG_NFS_ACL_SUPPORT) += nfs_acl.o
|
||||
nfs_acl-objs := nfsacl.o
|
||||
|
||||
obj-$(CONFIG_GRACE_PERIOD) += grace.o
|
||||
-obj-$(CONFIG_GRACE_PERIOD) += nfs_ssc.o
|
||||
+obj-$(CONFIG_NFS_V4_2_SSC_HELPER) += nfs_ssc.o
|
||||
diff --git a/fs/nfs_common/nfs_ssc.c b/fs/nfs_common/nfs_ssc.c
|
||||
index f43bbb3739134b..7c1509e968c817 100644
|
||||
--- a/fs/nfs_common/nfs_ssc.c
|
||||
+++ b/fs/nfs_common/nfs_ssc.c
|
||||
@@ -1,7 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
- * fs/nfs_common/nfs_ssc_comm.c
|
||||
- *
|
||||
* Helper for knfsd's SSC to access ops in NFS client modules
|
||||
*
|
||||
* Author: Dai Ngo <dai.ngo@oracle.com>
|
||||
diff --git a/fs/nfsd/Kconfig b/fs/nfsd/Kconfig
|
||||
index dbbc583d627306..821e5913faee49 100644
|
||||
--- a/fs/nfsd/Kconfig
|
||||
+++ b/fs/nfsd/Kconfig
|
||||
@@ -77,6 +77,7 @@ config NFSD_V4
|
||||
select CRYPTO_MD5
|
||||
select CRYPTO_SHA256
|
||||
select GRACE_PERIOD
|
||||
+ select NFS_V4_2_SSC_HELPER if NFS_V4_2
|
||||
help
|
||||
This option enables support in your system's NFS server for
|
||||
version 4 of the NFS protocol (RFC 3530).
|
@ -1,92 +0,0 @@
|
||||
From d9092b4bb2109502eb8972021a3f74febc931a63 Mon Sep 17 00:00:00 2001
|
||||
From: Dai Ngo <dai.ngo@oracle.com>
|
||||
Date: Thu, 22 Apr 2021 03:37:49 -0400
|
||||
Subject: [PATCH] NFSv4.2: Remove ifdef CONFIG_NFSD from NFSv4.2 client SSC
|
||||
code.
|
||||
|
||||
The client SSC code should not depend on any of the CONFIG_NFSD config.
|
||||
This patch removes all CONFIG_NFSD from NFSv4.2 client SSC code and
|
||||
simplifies the config of CONFIG_NFS_V4_2_SSC_HELPER, NFSD_V4_2_INTER_SSC.
|
||||
|
||||
Signed-off-by: Dai Ngo <dai.ngo@oracle.com>
|
||||
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
|
||||
---
|
||||
fs/Kconfig | 4 ++--
|
||||
fs/nfs/nfs4file.c | 4 ----
|
||||
fs/nfs/super.c | 4 ----
|
||||
fs/nfsd/Kconfig | 2 +-
|
||||
4 files changed, 3 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/fs/Kconfig b/fs/Kconfig
|
||||
index a55bda4233bbea..afa585e62332bf 100644
|
||||
--- a/fs/Kconfig
|
||||
+++ b/fs/Kconfig
|
||||
@@ -334,8 +334,8 @@ config NFS_COMMON
|
||||
default y
|
||||
|
||||
config NFS_V4_2_SSC_HELPER
|
||||
- tristate
|
||||
- default y if NFS_V4=y || NFS_FS=y
|
||||
+ bool
|
||||
+ default y if NFS_V4_2
|
||||
|
||||
source "net/sunrpc/Kconfig"
|
||||
source "fs/ceph/Kconfig"
|
||||
diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c
|
||||
index 441a2fa073c8f2..57b3821d975a35 100644
|
||||
--- a/fs/nfs/nfs4file.c
|
||||
+++ b/fs/nfs/nfs4file.c
|
||||
@@ -420,9 +420,7 @@ static const struct nfs4_ssc_client_ops nfs4_ssc_clnt_ops_tbl = {
|
||||
*/
|
||||
void nfs42_ssc_register_ops(void)
|
||||
{
|
||||
-#ifdef CONFIG_NFSD_V4
|
||||
nfs42_ssc_register(&nfs4_ssc_clnt_ops_tbl);
|
||||
-#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -433,9 +431,7 @@ void nfs42_ssc_register_ops(void)
|
||||
*/
|
||||
void nfs42_ssc_unregister_ops(void)
|
||||
{
|
||||
-#ifdef CONFIG_NFSD_V4
|
||||
nfs42_ssc_unregister(&nfs4_ssc_clnt_ops_tbl);
|
||||
-#endif
|
||||
}
|
||||
#endif /* CONFIG_NFS_V4_2 */
|
||||
|
||||
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
|
||||
index 13a650750f04a8..5bfcc25571879a 100644
|
||||
--- a/fs/nfs/super.c
|
||||
+++ b/fs/nfs/super.c
|
||||
@@ -116,16 +116,12 @@ static void unregister_nfs4_fs(void)
|
||||
#ifdef CONFIG_NFS_V4_2
|
||||
static void nfs_ssc_register_ops(void)
|
||||
{
|
||||
-#ifdef CONFIG_NFSD_V4
|
||||
nfs_ssc_register(&nfs_ssc_clnt_ops_tbl);
|
||||
-#endif
|
||||
}
|
||||
|
||||
static void nfs_ssc_unregister_ops(void)
|
||||
{
|
||||
-#ifdef CONFIG_NFSD_V4
|
||||
nfs_ssc_unregister(&nfs_ssc_clnt_ops_tbl);
|
||||
-#endif
|
||||
}
|
||||
#endif /* CONFIG_NFS_V4_2 */
|
||||
|
||||
diff --git a/fs/nfsd/Kconfig b/fs/nfsd/Kconfig
|
||||
index d6cff5fbe705b4..c5346196c46f7e 100644
|
||||
--- a/fs/nfsd/Kconfig
|
||||
+++ b/fs/nfsd/Kconfig
|
||||
@@ -138,7 +138,7 @@ config NFSD_FLEXFILELAYOUT
|
||||
|
||||
config NFSD_V4_2_INTER_SSC
|
||||
bool "NFSv4.2 inter server to server COPY"
|
||||
- depends on NFSD_V4 && NFS_V4_1 && NFS_V4_2
|
||||
+ depends on NFSD_V4 && NFS_V4_2
|
||||
help
|
||||
This option enables support for NFSv4.2 inter server to
|
||||
server copy where the destination server calls the NFSv4.2
|
@ -0,0 +1,32 @@
|
||||
From a4d82940ff85a7e307953dfa715f65d5ab487e10 Mon Sep 17 00:00:00 2001
|
||||
From: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
Date: Sun, 18 Apr 2021 23:46:14 +0200
|
||||
Subject: dt-bindings: mtd: brcm,trx: Add brcm,trx-magic
|
||||
|
||||
This adds the description of an additional property which allows to
|
||||
specify a custom partition parser magic to detect a trx partition.
|
||||
Buffalo has multiple device which are using the trx format, but with
|
||||
different magic values.
|
||||
|
||||
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
Acked-by: Rob Herring <robh@kernel.org>
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Link: https://lore.kernel.org/linux-mtd/20210418214616.239574-2-hauke@hauke-m.de
|
||||
---
|
||||
.../devicetree/bindings/mtd/partitions/brcm,trx.txt | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
--- a/Documentation/devicetree/bindings/mtd/partitions/brcm,trx.txt
|
||||
+++ b/Documentation/devicetree/bindings/mtd/partitions/brcm,trx.txt
|
||||
@@ -28,6 +28,11 @@ detected by a software parsing TRX heade
|
||||
Required properties:
|
||||
- compatible : (required) must be "brcm,trx"
|
||||
|
||||
+Optional properties:
|
||||
+
|
||||
+- brcm,trx-magic: TRX magic, if it is different from the default magic
|
||||
+ 0x30524448 as a u32.
|
||||
+
|
||||
Example:
|
||||
|
||||
flash@0 {
|
@ -0,0 +1,50 @@
|
||||
From d7f7e04f8b67571a4bf5a0dcd4f9da4214f5262c Mon Sep 17 00:00:00 2001
|
||||
From: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
Date: Sun, 18 Apr 2021 23:46:15 +0200
|
||||
Subject: mtd: parsers: trx: Allow to specify brcm, trx-magic in DT
|
||||
|
||||
Buffalo uses a different TRX magic for every device, to be able to use
|
||||
this trx parser, make it possible to specify the TRX magic in device
|
||||
tree. If no TRX magic is specified in device tree, the standard value
|
||||
will be used. This value should only be specified if a vendor chooses to
|
||||
use a non standard TRX magic.
|
||||
|
||||
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Link: https://lore.kernel.org/linux-mtd/20210418214616.239574-3-hauke@hauke-m.de
|
||||
---
|
||||
drivers/mtd/parsers/parser_trx.c | 9 ++++++++-
|
||||
1 file changed, 8 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/mtd/parsers/parser_trx.c
|
||||
+++ b/drivers/mtd/parsers/parser_trx.c
|
||||
@@ -51,13 +51,20 @@ static int parser_trx_parse(struct mtd_i
|
||||
const struct mtd_partition **pparts,
|
||||
struct mtd_part_parser_data *data)
|
||||
{
|
||||
+ struct device_node *np = mtd_get_of_node(mtd);
|
||||
struct mtd_partition *parts;
|
||||
struct mtd_partition *part;
|
||||
struct trx_header trx;
|
||||
size_t bytes_read;
|
||||
uint8_t curr_part = 0, i = 0;
|
||||
+ uint32_t trx_magic = TRX_MAGIC;
|
||||
int err;
|
||||
|
||||
+ /* Get different magic from device tree if specified */
|
||||
+ err = of_property_read_u32(np, "brcm,trx-magic", &trx_magic);
|
||||
+ if (err != 0 && err != -EINVAL)
|
||||
+ pr_err("failed to parse \"brcm,trx-magic\" DT attribute, using default: %d\n", err);
|
||||
+
|
||||
parts = kcalloc(TRX_PARSER_MAX_PARTS, sizeof(struct mtd_partition),
|
||||
GFP_KERNEL);
|
||||
if (!parts)
|
||||
@@ -70,7 +77,7 @@ static int parser_trx_parse(struct mtd_i
|
||||
return err;
|
||||
}
|
||||
|
||||
- if (trx.magic != TRX_MAGIC) {
|
||||
+ if (trx.magic != trx_magic) {
|
||||
kfree(parts);
|
||||
return -ENOENT;
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
From 81bb218c829246962a6327c64eec18ddcc049936 Mon Sep 17 00:00:00 2001
|
||||
From: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
Date: Sun, 18 Apr 2021 23:46:16 +0200
|
||||
Subject: mtd: parsers: trx: Allow to use TRX parser on Mediatek SoCs
|
||||
|
||||
Buffalo uses the TRX partition format also on Mediatek MT7622 SoCs.
|
||||
|
||||
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Link: https://lore.kernel.org/linux-mtd/20210418214616.239574-4-hauke@hauke-m.de
|
||||
---
|
||||
drivers/mtd/parsers/Kconfig | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/mtd/parsers/Kconfig
|
||||
+++ b/drivers/mtd/parsers/Kconfig
|
||||
@@ -115,7 +115,7 @@ config MTD_AFS_PARTS
|
||||
|
||||
config MTD_PARSER_TRX
|
||||
tristate "Parser for TRX format partitions"
|
||||
- depends on MTD && (BCM47XX || ARCH_BCM_5301X || COMPILE_TEST)
|
||||
+ depends on MTD && (BCM47XX || ARCH_BCM_5301X || ARCH_MEDIATEK || COMPILE_TEST)
|
||||
help
|
||||
TRX is a firmware format used by Broadcom on their devices. It
|
||||
may contain up to 3/4 partitions (depending on the version).
|
@ -0,0 +1,33 @@
|
||||
From 2365f91c861cbfeef7141c69842848c7b2d3c2db Mon Sep 17 00:00:00 2001
|
||||
From: INAGAKI Hiroshi <musashino.open@gmail.com>
|
||||
Date: Sun, 13 Feb 2022 15:40:44 +0900
|
||||
Subject: [PATCH] mtd: parsers: trx: allow to use on MediaTek MIPS SoCs
|
||||
|
||||
Buffalo sells some router devices which have trx-formatted firmware,
|
||||
based on MediaTek MIPS SoCs. To use parser_trx on those devices, add
|
||||
"RALINK" to dependency and allow to compile for MediaTek MIPS SoCs.
|
||||
|
||||
examples:
|
||||
|
||||
- WCR-1166DS (MT7628)
|
||||
- WSR-1166DHP (MT7621)
|
||||
- WSR-2533DHP (MT7621)
|
||||
|
||||
Signed-off-by: INAGAKI Hiroshi <musashino.open@gmail.com>
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Link: https://lore.kernel.org/linux-mtd/20220213064045.1781-1-musashino.open@gmail.com
|
||||
---
|
||||
drivers/mtd/parsers/Kconfig | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/mtd/parsers/Kconfig
|
||||
+++ b/drivers/mtd/parsers/Kconfig
|
||||
@@ -115,7 +115,7 @@ config MTD_AFS_PARTS
|
||||
|
||||
config MTD_PARSER_TRX
|
||||
tristate "Parser for TRX format partitions"
|
||||
- depends on MTD && (BCM47XX || ARCH_BCM_5301X || ARCH_MEDIATEK || COMPILE_TEST)
|
||||
+ depends on MTD && (BCM47XX || ARCH_BCM_5301X || ARCH_MEDIATEK || RALINK || COMPILE_TEST)
|
||||
help
|
||||
TRX is a firmware format used by Broadcom on their devices. It
|
||||
may contain up to 3/4 partitions (depending on the version).
|
@ -0,0 +1,172 @@
|
||||
From bd568cc04c675b7fa97214d278a54794c2ecc2ad Mon Sep 17 00:00:00 2001
|
||||
From: Reto Schneider <reto.schneider@husqvarnagroup.com>
|
||||
Date: Thu, 11 Feb 2021 12:36:19 +0100
|
||||
Subject: [PATCH] mtd: spinand: gigadevice: Support GD5F1GQ5UExxG
|
||||
|
||||
The relevant changes to the already existing GD5F1GQ4UExxG support has
|
||||
been determined by consulting the GigaDevice product change notice
|
||||
AN-0392-10, version 1.0 from November 30, 2020.
|
||||
|
||||
As the overlaps are huge, variable names have been generalized
|
||||
accordingly.
|
||||
|
||||
Apart from the lowered ECC strength (4 instead of 8 bits per 512 bytes),
|
||||
the new device ID, and the extra quad IO dummy byte, no changes had to
|
||||
be taken into account.
|
||||
|
||||
New hardware features are not supported, namely:
|
||||
- Power on reset
|
||||
- Unique ID
|
||||
- Double transfer rate (DTR)
|
||||
- Parameter page
|
||||
- Random data quad IO
|
||||
|
||||
The inverted semantic of the "driver strength" register bits, defaulting
|
||||
to 100% instead of 50% for the Q5 devices, got ignored as the driver has
|
||||
never touched them anyway.
|
||||
|
||||
The no longer supported "read from cache during block erase"
|
||||
functionality is not reflected as the current SPI NAND core does not
|
||||
support it anyway.
|
||||
|
||||
Implementation has been tested on MediaTek MT7688 based GARDENA smart
|
||||
Gateways using both, GigaDevice GD5F1GQ5UEYIG and GD5F1GQ4UBYIG.
|
||||
|
||||
Signed-off-by: Reto Schneider <reto.schneider@husqvarnagroup.com>
|
||||
Reviewed-by: Frieder Schrempf <frieder.schrempf@kontron.de>
|
||||
Reviewed-by: Stefan Roese <sr@denx.de>
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Link: https://lore.kernel.org/linux-mtd/20210211113619.3502-1-code@reto-schneider.ch
|
||||
(cherry picked from commit 469b992489852b500d39048aa0013639dfe9f2e6)
|
||||
---
|
||||
drivers/mtd/nand/spi/gigadevice.c | 69 +++++++++++++++++++++++++++----
|
||||
1 file changed, 60 insertions(+), 9 deletions(-)
|
||||
|
||||
--- a/drivers/mtd/nand/spi/gigadevice.c
|
||||
+++ b/drivers/mtd/nand/spi/gigadevice.c
|
||||
@@ -13,7 +13,10 @@
|
||||
#define GD5FXGQ4XA_STATUS_ECC_1_7_BITFLIPS (1 << 4)
|
||||
#define GD5FXGQ4XA_STATUS_ECC_8_BITFLIPS (3 << 4)
|
||||
|
||||
-#define GD5FXGQ4UEXXG_REG_STATUS2 0xf0
|
||||
+#define GD5FXGQ5XE_STATUS_ECC_1_4_BITFLIPS (1 << 4)
|
||||
+#define GD5FXGQ5XE_STATUS_ECC_4_BITFLIPS (3 << 4)
|
||||
+
|
||||
+#define GD5FXGQXXEXXG_REG_STATUS2 0xf0
|
||||
|
||||
#define GD5FXGQ4UXFXXG_STATUS_ECC_MASK (7 << 4)
|
||||
#define GD5FXGQ4UXFXXG_STATUS_ECC_NO_BITFLIPS (0 << 4)
|
||||
@@ -102,7 +105,7 @@ static int gd5fxgq4xa_ecc_get_status(str
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
-static int gd5fxgq4_variant2_ooblayout_ecc(struct mtd_info *mtd, int section,
|
||||
+static int gd5fxgqx_variant2_ooblayout_ecc(struct mtd_info *mtd, int section,
|
||||
struct mtd_oob_region *region)
|
||||
{
|
||||
if (section)
|
||||
@@ -114,7 +117,7 @@ static int gd5fxgq4_variant2_ooblayout_e
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int gd5fxgq4_variant2_ooblayout_free(struct mtd_info *mtd, int section,
|
||||
+static int gd5fxgqx_variant2_ooblayout_free(struct mtd_info *mtd, int section,
|
||||
struct mtd_oob_region *region)
|
||||
{
|
||||
if (section)
|
||||
@@ -127,9 +130,10 @@ static int gd5fxgq4_variant2_ooblayout_f
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static const struct mtd_ooblayout_ops gd5fxgq4_variant2_ooblayout = {
|
||||
- .ecc = gd5fxgq4_variant2_ooblayout_ecc,
|
||||
- .free = gd5fxgq4_variant2_ooblayout_free,
|
||||
+/* Valid for Q4/Q5 and Q6 (untested) devices */
|
||||
+static const struct mtd_ooblayout_ops gd5fxgqx_variant2_ooblayout = {
|
||||
+ .ecc = gd5fxgqx_variant2_ooblayout_ecc,
|
||||
+ .free = gd5fxgqx_variant2_ooblayout_free,
|
||||
};
|
||||
|
||||
static int gd5fxgq4xc_ooblayout_256_ecc(struct mtd_info *mtd, int section,
|
||||
@@ -165,7 +169,7 @@ static int gd5fxgq4uexxg_ecc_get_status(
|
||||
u8 status)
|
||||
{
|
||||
u8 status2;
|
||||
- struct spi_mem_op op = SPINAND_GET_FEATURE_OP(GD5FXGQ4UEXXG_REG_STATUS2,
|
||||
+ struct spi_mem_op op = SPINAND_GET_FEATURE_OP(GD5FXGQXXEXXG_REG_STATUS2,
|
||||
&status2);
|
||||
int ret;
|
||||
|
||||
@@ -203,6 +207,43 @@ static int gd5fxgq4uexxg_ecc_get_status(
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
+static int gd5fxgq5xexxg_ecc_get_status(struct spinand_device *spinand,
|
||||
+ u8 status)
|
||||
+{
|
||||
+ u8 status2;
|
||||
+ struct spi_mem_op op = SPINAND_GET_FEATURE_OP(GD5FXGQXXEXXG_REG_STATUS2,
|
||||
+ &status2);
|
||||
+ int ret;
|
||||
+
|
||||
+ switch (status & STATUS_ECC_MASK) {
|
||||
+ case STATUS_ECC_NO_BITFLIPS:
|
||||
+ return 0;
|
||||
+
|
||||
+ case GD5FXGQ5XE_STATUS_ECC_1_4_BITFLIPS:
|
||||
+ /*
|
||||
+ * Read status2 register to determine a more fine grained
|
||||
+ * bit error status
|
||||
+ */
|
||||
+ ret = spi_mem_exec_op(spinand->spimem, &op);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ /*
|
||||
+ * 1 ... 4 bits are flipped (and corrected)
|
||||
+ */
|
||||
+ /* bits sorted this way (1...0): ECCSE1, ECCSE0 */
|
||||
+ return ((status2 & STATUS_ECC_MASK) >> 4) + 1;
|
||||
+
|
||||
+ case STATUS_ECC_UNCOR_ERROR:
|
||||
+ return -EBADMSG;
|
||||
+
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ return -EINVAL;
|
||||
+}
|
||||
+
|
||||
static int gd5fxgq4ufxxg_ecc_get_status(struct spinand_device *spinand,
|
||||
u8 status)
|
||||
{
|
||||
@@ -282,7 +323,7 @@ static const struct spinand_info gigadev
|
||||
&write_cache_variants,
|
||||
&update_cache_variants),
|
||||
SPINAND_HAS_QE_BIT,
|
||||
- SPINAND_ECCINFO(&gd5fxgq4_variant2_ooblayout,
|
||||
+ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
|
||||
gd5fxgq4uexxg_ecc_get_status)),
|
||||
SPINAND_INFO("GD5F1GQ4UFxxG",
|
||||
SPINAND_ID(SPINAND_READID_METHOD_OPCODE, 0xb1, 0x48),
|
||||
@@ -292,8 +333,18 @@ static const struct spinand_info gigadev
|
||||
&write_cache_variants,
|
||||
&update_cache_variants),
|
||||
SPINAND_HAS_QE_BIT,
|
||||
- SPINAND_ECCINFO(&gd5fxgq4_variant2_ooblayout,
|
||||
+ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
|
||||
gd5fxgq4ufxxg_ecc_get_status)),
|
||||
+ SPINAND_INFO("GD5F1GQ5UExxG",
|
||||
+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x51),
|
||||
+ NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
|
||||
+ NAND_ECCREQ(4, 512),
|
||||
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
|
||||
+ &write_cache_variants,
|
||||
+ &update_cache_variants),
|
||||
+ SPINAND_HAS_QE_BIT,
|
||||
+ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
|
||||
+ gd5fxgq5xexxg_ecc_get_status)),
|
||||
};
|
||||
|
||||
static const struct spinand_manufacturer_ops gigadevice_spinand_manuf_ops = {
|
@ -0,0 +1,44 @@
|
||||
From a4f9dd55c5e1bb951db6f1dee20e62e0103f3438 Mon Sep 17 00:00:00 2001
|
||||
From: Chuanhong Guo <gch981213@gmail.com>
|
||||
Date: Sun, 20 Mar 2022 17:59:57 +0800
|
||||
Subject: [PATCH 1/5] mtd: spinand: gigadevice: fix Quad IO for GD5F1GQ5UExxG
|
||||
|
||||
Read From Cache Quad IO (EBH) uses 2 dummy bytes on this chip according
|
||||
to page 23 of the datasheet[0].
|
||||
|
||||
[0]: https://www.gigadevice.com/datasheet/gd5f1gq5xexxg/
|
||||
|
||||
Fixes: 469b99248985 ("mtd: spinand: gigadevice: Support GD5F1GQ5UExxG")
|
||||
Signed-off-by: Chuanhong Guo <gch981213@gmail.com>
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Link: https://lore.kernel.org/linux-mtd/20220320100001.247905-2-gch981213@gmail.com
|
||||
---
|
||||
drivers/mtd/nand/spi/gigadevice.c | 10 +++++++++-
|
||||
1 file changed, 9 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/mtd/nand/spi/gigadevice.c
|
||||
+++ b/drivers/mtd/nand/spi/gigadevice.c
|
||||
@@ -39,6 +39,14 @@ static SPINAND_OP_VARIANTS(read_cache_va
|
||||
SPINAND_PAGE_READ_FROM_CACHE_OP_3A(true, 0, 1, NULL, 0),
|
||||
SPINAND_PAGE_READ_FROM_CACHE_OP_3A(false, 0, 0, NULL, 0));
|
||||
|
||||
+static SPINAND_OP_VARIANTS(read_cache_variants_1gq5,
|
||||
+ SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, 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));
|
||||
@@ -339,7 +347,7 @@ static const struct spinand_info gigadev
|
||||
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x51),
|
||||
NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
|
||||
NAND_ECCREQ(4, 512),
|
||||
- SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
|
||||
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
|
||||
&write_cache_variants,
|
||||
&update_cache_variants),
|
||||
SPINAND_HAS_QE_BIT,
|
@ -0,0 +1,58 @@
|
||||
From 573eec222bc82fb5e724586267fbbb1aed9ffd03 Mon Sep 17 00:00:00 2001
|
||||
From: Chuanhong Guo <gch981213@gmail.com>
|
||||
Date: Sun, 20 Mar 2022 17:59:58 +0800
|
||||
Subject: [PATCH 2/5] mtd: spinand: gigadevice: add support for GD5FxGQ4xExxG
|
||||
|
||||
Add support for:
|
||||
GD5F1GQ4RExxG
|
||||
GD5F2GQ4{U,R}ExxG
|
||||
|
||||
These chips differ from GD5F1GQ4UExxG only in chip ID, voltage
|
||||
and capacity.
|
||||
|
||||
Signed-off-by: Chuanhong Guo <gch981213@gmail.com>
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Link: https://lore.kernel.org/linux-mtd/20220320100001.247905-3-gch981213@gmail.com
|
||||
---
|
||||
drivers/mtd/nand/spi/gigadevice.c | 30 ++++++++++++++++++++++++++++++
|
||||
1 file changed, 30 insertions(+)
|
||||
|
||||
--- a/drivers/mtd/nand/spi/gigadevice.c
|
||||
+++ b/drivers/mtd/nand/spi/gigadevice.c
|
||||
@@ -333,6 +333,36 @@ static const struct spinand_info gigadev
|
||||
SPINAND_HAS_QE_BIT,
|
||||
SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
|
||||
gd5fxgq4uexxg_ecc_get_status)),
|
||||
+ SPINAND_INFO("GD5F1GQ4RExxG",
|
||||
+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xc1),
|
||||
+ NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 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(&gd5fxgqx_variant2_ooblayout,
|
||||
+ gd5fxgq4uexxg_ecc_get_status)),
|
||||
+ SPINAND_INFO("GD5F2GQ4UExxG",
|
||||
+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xd2),
|
||||
+ 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(&gd5fxgqx_variant2_ooblayout,
|
||||
+ gd5fxgq4uexxg_ecc_get_status)),
|
||||
+ SPINAND_INFO("GD5F2GQ4RExxG",
|
||||
+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xc2),
|
||||
+ 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(&gd5fxgqx_variant2_ooblayout,
|
||||
+ gd5fxgq4uexxg_ecc_get_status)),
|
||||
SPINAND_INFO("GD5F1GQ4UFxxG",
|
||||
SPINAND_ID(SPINAND_READID_METHOD_OPCODE, 0xb1, 0x48),
|
||||
NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
|
@ -0,0 +1,33 @@
|
||||
From 620a988813403318023296b61228ee8f3fcdb8e0 Mon Sep 17 00:00:00 2001
|
||||
From: Chuanhong Guo <gch981213@gmail.com>
|
||||
Date: Sun, 20 Mar 2022 17:59:59 +0800
|
||||
Subject: [PATCH 3/5] mtd: spinand: gigadevice: add support for GD5F1GQ5RExxG
|
||||
|
||||
This chip is the 1.8v version of GD5F1GQ5UExxG.
|
||||
|
||||
Signed-off-by: Chuanhong Guo <gch981213@gmail.com>
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Link: https://lore.kernel.org/linux-mtd/20220320100001.247905-4-gch981213@gmail.com
|
||||
---
|
||||
drivers/mtd/nand/spi/gigadevice.c | 10 ++++++++++
|
||||
1 file changed, 10 insertions(+)
|
||||
|
||||
--- a/drivers/mtd/nand/spi/gigadevice.c
|
||||
+++ b/drivers/mtd/nand/spi/gigadevice.c
|
||||
@@ -383,6 +383,16 @@ static const struct spinand_info gigadev
|
||||
SPINAND_HAS_QE_BIT,
|
||||
SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
|
||||
gd5fxgq5xexxg_ecc_get_status)),
|
||||
+ SPINAND_INFO("GD5F1GQ5RExxG",
|
||||
+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x41),
|
||||
+ NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
|
||||
+ NAND_ECCREQ(4, 512),
|
||||
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
|
||||
+ &write_cache_variants,
|
||||
+ &update_cache_variants),
|
||||
+ SPINAND_HAS_QE_BIT,
|
||||
+ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
|
||||
+ gd5fxgq5xexxg_ecc_get_status)),
|
||||
};
|
||||
|
||||
static const struct spinand_manufacturer_ops gigadevice_spinand_manuf_ops = {
|
@ -0,0 +1,84 @@
|
||||
From 194ec04b3a9e7fa97d1fbef296410631bc3cf1c8 Mon Sep 17 00:00:00 2001
|
||||
From: Chuanhong Guo <gch981213@gmail.com>
|
||||
Date: Sun, 20 Mar 2022 18:00:00 +0800
|
||||
Subject: [PATCH 4/5] mtd: spinand: gigadevice: add support for GD5F{2,
|
||||
4}GQ5xExxG
|
||||
|
||||
Add support for:
|
||||
GD5F2GQ5{U,R}ExxG
|
||||
GD5F4GQ6{U,R}ExxG
|
||||
|
||||
These chips uses 4 dummy bytes for quad io and 2 dummy bytes for dual io.
|
||||
Besides that and memory layout, they are identical to their 1G variant.
|
||||
|
||||
Signed-off-by: Chuanhong Guo <gch981213@gmail.com>
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Link: https://lore.kernel.org/linux-mtd/20220320100001.247905-5-gch981213@gmail.com
|
||||
---
|
||||
drivers/mtd/nand/spi/gigadevice.c | 48 +++++++++++++++++++++++++++++++
|
||||
1 file changed, 48 insertions(+)
|
||||
|
||||
--- a/drivers/mtd/nand/spi/gigadevice.c
|
||||
+++ b/drivers/mtd/nand/spi/gigadevice.c
|
||||
@@ -47,6 +47,14 @@ static SPINAND_OP_VARIANTS(read_cache_va
|
||||
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(read_cache_variants_2gq5,
|
||||
+ SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 4, NULL, 0),
|
||||
+ SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
|
||||
+ SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 2, 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));
|
||||
@@ -391,6 +399,46 @@ static const struct spinand_info gigadev
|
||||
&write_cache_variants,
|
||||
&update_cache_variants),
|
||||
SPINAND_HAS_QE_BIT,
|
||||
+ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
|
||||
+ gd5fxgq5xexxg_ecc_get_status)),
|
||||
+ SPINAND_INFO("GD5F2GQ5UExxG",
|
||||
+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x52),
|
||||
+ NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
|
||||
+ NAND_ECCREQ(4, 512),
|
||||
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants_2gq5,
|
||||
+ &write_cache_variants,
|
||||
+ &update_cache_variants),
|
||||
+ SPINAND_HAS_QE_BIT,
|
||||
+ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
|
||||
+ gd5fxgq5xexxg_ecc_get_status)),
|
||||
+ SPINAND_INFO("GD5F2GQ5RExxG",
|
||||
+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x42),
|
||||
+ NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
|
||||
+ NAND_ECCREQ(4, 512),
|
||||
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants_2gq5,
|
||||
+ &write_cache_variants,
|
||||
+ &update_cache_variants),
|
||||
+ SPINAND_HAS_QE_BIT,
|
||||
+ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
|
||||
+ gd5fxgq5xexxg_ecc_get_status)),
|
||||
+ SPINAND_INFO("GD5F4GQ6UExxG",
|
||||
+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x55),
|
||||
+ NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 2, 1),
|
||||
+ NAND_ECCREQ(4, 512),
|
||||
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants_2gq5,
|
||||
+ &write_cache_variants,
|
||||
+ &update_cache_variants),
|
||||
+ SPINAND_HAS_QE_BIT,
|
||||
+ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
|
||||
+ gd5fxgq5xexxg_ecc_get_status)),
|
||||
+ SPINAND_INFO("GD5F4GQ6RExxG",
|
||||
+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x45),
|
||||
+ NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 2, 1),
|
||||
+ NAND_ECCREQ(4, 512),
|
||||
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants_2gq5,
|
||||
+ &write_cache_variants,
|
||||
+ &update_cache_variants),
|
||||
+ SPINAND_HAS_QE_BIT,
|
||||
SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
|
||||
gd5fxgq5xexxg_ecc_get_status)),
|
||||
};
|
@ -0,0 +1,91 @@
|
||||
From 54647cd003c08b714474a5b599a147ec6a160486 Mon Sep 17 00:00:00 2001
|
||||
From: Chuanhong Guo <gch981213@gmail.com>
|
||||
Date: Sun, 20 Mar 2022 18:00:01 +0800
|
||||
Subject: [PATCH 5/5] mtd: spinand: gigadevice: add support for GD5FxGM7xExxG
|
||||
|
||||
Add support for:
|
||||
GD5F{1,2}GM7{U,R}ExxG
|
||||
GD5F4GM8{U,R}ExxG
|
||||
|
||||
These are new 27nm counterparts for the GD5FxGQ4 chips from GigaDevice
|
||||
with 8b/512b on-die ECC capability.
|
||||
These chips (and currently supported GD5FxGQ5 chips) have QIO DTR
|
||||
instruction for reading page cache. It isn't added in this patch because
|
||||
I don't have a DTR spi controller for testing.
|
||||
|
||||
Signed-off-by: Chuanhong Guo <gch981213@gmail.com>
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Link: https://lore.kernel.org/linux-mtd/20220320100001.247905-6-gch981213@gmail.com
|
||||
---
|
||||
drivers/mtd/nand/spi/gigadevice.c | 60 +++++++++++++++++++++++++++++++
|
||||
1 file changed, 60 insertions(+)
|
||||
|
||||
--- a/drivers/mtd/nand/spi/gigadevice.c
|
||||
+++ b/drivers/mtd/nand/spi/gigadevice.c
|
||||
@@ -441,6 +441,66 @@ static const struct spinand_info gigadev
|
||||
SPINAND_HAS_QE_BIT,
|
||||
SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
|
||||
gd5fxgq5xexxg_ecc_get_status)),
|
||||
+ SPINAND_INFO("GD5F1GM7UExxG",
|
||||
+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x91),
|
||||
+ NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
|
||||
+ NAND_ECCREQ(8, 512),
|
||||
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
|
||||
+ &write_cache_variants,
|
||||
+ &update_cache_variants),
|
||||
+ SPINAND_HAS_QE_BIT,
|
||||
+ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
|
||||
+ gd5fxgq4uexxg_ecc_get_status)),
|
||||
+ SPINAND_INFO("GD5F1GM7RExxG",
|
||||
+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x81),
|
||||
+ NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
|
||||
+ NAND_ECCREQ(8, 512),
|
||||
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
|
||||
+ &write_cache_variants,
|
||||
+ &update_cache_variants),
|
||||
+ SPINAND_HAS_QE_BIT,
|
||||
+ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
|
||||
+ gd5fxgq4uexxg_ecc_get_status)),
|
||||
+ SPINAND_INFO("GD5F2GM7UExxG",
|
||||
+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x92),
|
||||
+ NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
|
||||
+ NAND_ECCREQ(8, 512),
|
||||
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
|
||||
+ &write_cache_variants,
|
||||
+ &update_cache_variants),
|
||||
+ SPINAND_HAS_QE_BIT,
|
||||
+ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
|
||||
+ gd5fxgq4uexxg_ecc_get_status)),
|
||||
+ SPINAND_INFO("GD5F2GM7RExxG",
|
||||
+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x82),
|
||||
+ NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
|
||||
+ NAND_ECCREQ(8, 512),
|
||||
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
|
||||
+ &write_cache_variants,
|
||||
+ &update_cache_variants),
|
||||
+ SPINAND_HAS_QE_BIT,
|
||||
+ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
|
||||
+ gd5fxgq4uexxg_ecc_get_status)),
|
||||
+ SPINAND_INFO("GD5F4GM8UExxG",
|
||||
+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x95),
|
||||
+ NAND_MEMORG(1, 2048, 128, 64, 4096, 80, 1, 1, 1),
|
||||
+ NAND_ECCREQ(8, 512),
|
||||
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
|
||||
+ &write_cache_variants,
|
||||
+ &update_cache_variants),
|
||||
+ SPINAND_HAS_QE_BIT,
|
||||
+ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
|
||||
+ gd5fxgq4uexxg_ecc_get_status)),
|
||||
+ SPINAND_INFO("GD5F4GM8RExxG",
|
||||
+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x85),
|
||||
+ NAND_MEMORG(1, 2048, 128, 64, 4096, 80, 1, 1, 1),
|
||||
+ NAND_ECCREQ(8, 512),
|
||||
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
|
||||
+ &write_cache_variants,
|
||||
+ &update_cache_variants),
|
||||
+ SPINAND_HAS_QE_BIT,
|
||||
+ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
|
||||
+ gd5fxgq4uexxg_ecc_get_status)),
|
||||
};
|
||||
|
||||
static const struct spinand_manufacturer_ops gigadevice_spinand_manuf_ops = {
|
@ -1,105 +0,0 @@
|
||||
--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
|
||||
+++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <linux/rhashtable.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/ip.h>
|
||||
+#include <linux/ipv6.h>
|
||||
#include <net/flow_offload.h>
|
||||
#include <net/pkt_cls.h>
|
||||
#include <net/dsa.h>
|
||||
@@ -20,6 +21,11 @@ struct mtk_flow_data {
|
||||
__be32 src_addr;
|
||||
__be32 dst_addr;
|
||||
} v4;
|
||||
+
|
||||
+ struct {
|
||||
+ struct in6_addr src_addr;
|
||||
+ struct in6_addr dst_addr;
|
||||
+ } v6;
|
||||
};
|
||||
|
||||
__be16 src_port;
|
||||
@@ -64,6 +70,14 @@ mtk_flow_set_ipv4_addr(struct mtk_foe_en
|
||||
data->v4.dst_addr, data->dst_port);
|
||||
}
|
||||
|
||||
+static int
|
||||
+mtk_flow_set_ipv6_addr(struct mtk_foe_entry *foe, struct mtk_flow_data *data)
|
||||
+{
|
||||
+ return mtk_foe_entry_set_ipv6_tuple(foe,
|
||||
+ data->v6.src_addr.s6_addr32, data->src_port,
|
||||
+ data->v6.dst_addr.s6_addr32, data->dst_port);
|
||||
+}
|
||||
+
|
||||
static void
|
||||
mtk_flow_offload_mangle_eth(const struct flow_action_entry *act, void *eth)
|
||||
{
|
||||
@@ -128,6 +142,29 @@ mtk_flow_mangle_ipv4(const struct flow_a
|
||||
}
|
||||
|
||||
static int
|
||||
+mtk_flow_mangle_ipv6(const struct flow_action_entry *act,
|
||||
+ struct mtk_flow_data *data)
|
||||
+{
|
||||
+ __be32 *dest;
|
||||
+ size_t offset_of_ip6_daddr = offsetof(struct ipv6hdr, daddr);
|
||||
+ size_t offset_of_ip6_saddr = offsetof(struct ipv6hdr, saddr);
|
||||
+ u32 idx;
|
||||
+
|
||||
+ if (act->mangle.offset >= offset_of_ip6_daddr && act->mangle.offset < offset_of_ip6_daddr) {
|
||||
+ idx = (act->mangle.offset - offset_of_ip6_saddr) / 4;
|
||||
+ dest = &data->v6.src_addr.s6_addr32[idx];
|
||||
+ } else if (act->mangle.offset >= offset_of_ip6_daddr &&
|
||||
+ act->mangle.offset < offset_of_ip6_daddr + 16) {
|
||||
+ idx = (act->mangle.offset - offset_of_ip6_daddr) / 4;
|
||||
+ dest = &data->v6.dst_addr.s6_addr32[idx];
|
||||
+ }
|
||||
+
|
||||
+ memcpy(dest, &act->mangle.val, sizeof(u32));
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
mtk_flow_get_dsa_port(struct net_device **dev)
|
||||
{
|
||||
#if IS_ENABLED(CONFIG_NET_DSA)
|
||||
@@ -251,6 +288,9 @@ mtk_flow_offload_replace(struct mtk_eth
|
||||
case FLOW_DISSECTOR_KEY_IPV4_ADDRS:
|
||||
offload_type = MTK_PPE_PKT_TYPE_IPV4_HNAPT;
|
||||
break;
|
||||
+ case FLOW_DISSECTOR_KEY_IPV6_ADDRS:
|
||||
+ offload_type = MTK_PPE_PKT_TYPE_IPV6_ROUTE_5T;
|
||||
+ break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
@@ -286,6 +326,17 @@ mtk_flow_offload_replace(struct mtk_eth
|
||||
mtk_flow_set_ipv4_addr(&foe, &data, false);
|
||||
}
|
||||
|
||||
+ if (addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) {
|
||||
+ struct flow_match_ipv6_addrs addrs;
|
||||
+
|
||||
+ flow_rule_match_ipv6_addrs(rule, &addrs);
|
||||
+
|
||||
+ data.v6.src_addr = addrs.key->src;
|
||||
+ data.v6.dst_addr = addrs.key->dst;
|
||||
+
|
||||
+ mtk_flow_set_ipv6_addr(&foe, &data);
|
||||
+ }
|
||||
+
|
||||
flow_action_for_each(i, act, &rule->action) {
|
||||
if (act->id != FLOW_ACTION_MANGLE)
|
||||
continue;
|
||||
@@ -289,6 +349,9 @@ mtk_flow_offload_replace(struct mtk_eth
|
||||
case FLOW_ACT_MANGLE_HDR_TYPE_IP4:
|
||||
err = mtk_flow_mangle_ipv4(act, &data);
|
||||
break;
|
||||
+ case FLOW_ACT_MANGLE_HDR_TYPE_IP6:
|
||||
+ err = mtk_flow_mangle_ipv6(act, &data);
|
||||
+ break;
|
||||
case FLOW_ACT_MANGLE_HDR_TYPE_ETH:
|
||||
/* handled earlier */
|
||||
break;
|
@ -33,7 +33,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
enum udp_conntrack {
|
||||
--- a/net/netfilter/nf_conntrack_proto_tcp.c
|
||||
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
|
||||
@@ -1438,6 +1438,11 @@ void nf_conntrack_tcp_init_net(struct ne
|
||||
@@ -1447,6 +1447,11 @@ void nf_conntrack_tcp_init_net(struct ne
|
||||
tn->tcp_loose = nf_ct_tcp_loose;
|
||||
tn->tcp_be_liberal = nf_ct_tcp_be_liberal;
|
||||
tn->tcp_max_retrans = nf_ct_tcp_max_retrans;
|
||||
|
@ -0,0 +1,138 @@
|
||||
From 4fd59792097a6b2fb949d41264386a7ecade469e Mon Sep 17 00:00:00 2001
|
||||
From: DENG Qingfang <dqfext@gmail.com>
|
||||
Date: Mon, 25 Jan 2021 12:20:46 +0800
|
||||
Subject: [PATCH] net: ethernet: mediatek: support setting MTU
|
||||
|
||||
MT762x HW, except for MT7628, supports frame length up to 2048
|
||||
(maximum length on GDM), so allow setting MTU up to 2030.
|
||||
|
||||
Also set the default frame length to the hardware default 1518.
|
||||
|
||||
Signed-off-by: DENG Qingfang <dqfext@gmail.com>
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Link: https://lore.kernel.org/r/20210125042046.5599-1-dqfext@gmail.com
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 43 ++++++++++++++++++---
|
||||
drivers/net/ethernet/mediatek/mtk_eth_soc.h | 12 ++++--
|
||||
2 files changed, 47 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
||||
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
||||
@@ -355,7 +355,7 @@ static void mtk_mac_config(struct phylin
|
||||
/* Setup gmac */
|
||||
mcr_cur = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id));
|
||||
mcr_new = mcr_cur;
|
||||
- mcr_new |= MAC_MCR_MAX_RX_1536 | MAC_MCR_IPG_CFG | MAC_MCR_FORCE_MODE |
|
||||
+ mcr_new |= MAC_MCR_IPG_CFG | MAC_MCR_FORCE_MODE |
|
||||
MAC_MCR_BACKOFF_EN | MAC_MCR_BACKPR_EN | MAC_MCR_FORCE_LINK;
|
||||
|
||||
/* Only update control register when needed! */
|
||||
@@ -782,8 +782,8 @@ static void mtk_get_stats64(struct net_d
|
||||
static inline int mtk_max_frag_size(int mtu)
|
||||
{
|
||||
/* make sure buf_size will be at least MTK_MAX_RX_LENGTH */
|
||||
- if (mtu + MTK_RX_ETH_HLEN < MTK_MAX_RX_LENGTH)
|
||||
- mtu = MTK_MAX_RX_LENGTH - MTK_RX_ETH_HLEN;
|
||||
+ if (mtu + MTK_RX_ETH_HLEN < MTK_MAX_RX_LENGTH_2K)
|
||||
+ mtu = MTK_MAX_RX_LENGTH_2K - MTK_RX_ETH_HLEN;
|
||||
|
||||
return SKB_DATA_ALIGN(MTK_RX_HLEN + mtu) +
|
||||
SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
|
||||
@@ -794,7 +794,7 @@ static inline int mtk_max_buf_size(int f
|
||||
int buf_size = frag_size - NET_SKB_PAD - NET_IP_ALIGN -
|
||||
SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
|
||||
|
||||
- WARN_ON(buf_size < MTK_MAX_RX_LENGTH);
|
||||
+ WARN_ON(buf_size < MTK_MAX_RX_LENGTH_2K);
|
||||
|
||||
return buf_size;
|
||||
}
|
||||
@@ -2606,6 +2606,35 @@ static void mtk_uninit(struct net_device
|
||||
mtk_rx_irq_disable(eth, ~0);
|
||||
}
|
||||
|
||||
+static int mtk_change_mtu(struct net_device *dev, int new_mtu)
|
||||
+{
|
||||
+ int length = new_mtu + MTK_RX_ETH_HLEN;
|
||||
+ struct mtk_mac *mac = netdev_priv(dev);
|
||||
+ struct mtk_eth *eth = mac->hw;
|
||||
+ u32 mcr_cur, mcr_new;
|
||||
+
|
||||
+ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628)) {
|
||||
+ mcr_cur = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id));
|
||||
+ mcr_new = mcr_cur & ~MAC_MCR_MAX_RX_MASK;
|
||||
+
|
||||
+ if (length <= 1518)
|
||||
+ mcr_new |= MAC_MCR_MAX_RX(MAC_MCR_MAX_RX_1518);
|
||||
+ else if (length <= 1536)
|
||||
+ mcr_new |= MAC_MCR_MAX_RX(MAC_MCR_MAX_RX_1536);
|
||||
+ else if (length <= 1552)
|
||||
+ mcr_new |= MAC_MCR_MAX_RX(MAC_MCR_MAX_RX_1552);
|
||||
+ else
|
||||
+ mcr_new |= MAC_MCR_MAX_RX(MAC_MCR_MAX_RX_2048);
|
||||
+
|
||||
+ if (mcr_new != mcr_cur)
|
||||
+ mtk_w32(mac->hw, mcr_new, MTK_MAC_MCR(mac->id));
|
||||
+ }
|
||||
+
|
||||
+ dev->mtu = new_mtu;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int mtk_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
|
||||
{
|
||||
struct mtk_mac *mac = netdev_priv(dev);
|
||||
@@ -2902,6 +2931,7 @@ static const struct net_device_ops mtk_n
|
||||
.ndo_set_mac_address = mtk_set_mac_address,
|
||||
.ndo_validate_addr = eth_validate_addr,
|
||||
.ndo_do_ioctl = mtk_do_ioctl,
|
||||
+ .ndo_change_mtu = mtk_change_mtu,
|
||||
.ndo_tx_timeout = mtk_tx_timeout,
|
||||
.ndo_get_stats64 = mtk_get_stats64,
|
||||
.ndo_fix_features = mtk_fix_features,
|
||||
@@ -3004,7 +3034,10 @@ static int mtk_add_mac(struct mtk_eth *e
|
||||
eth->netdev[id]->irq = eth->irq[0];
|
||||
eth->netdev[id]->dev.of_node = np;
|
||||
|
||||
- eth->netdev[id]->max_mtu = MTK_MAX_RX_LENGTH - MTK_RX_ETH_HLEN;
|
||||
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628))
|
||||
+ eth->netdev[id]->max_mtu = MTK_MAX_RX_LENGTH - MTK_RX_ETH_HLEN;
|
||||
+ else
|
||||
+ eth->netdev[id]->max_mtu = MTK_MAX_RX_LENGTH_2K - MTK_RX_ETH_HLEN;
|
||||
|
||||
return 0;
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
||||
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
||||
@@ -20,12 +20,13 @@
|
||||
#include "mtk_ppe.h"
|
||||
|
||||
#define MTK_QDMA_PAGE_SIZE 2048
|
||||
-#define MTK_MAX_RX_LENGTH 1536
|
||||
+#define MTK_MAX_RX_LENGTH 1536
|
||||
+#define MTK_MAX_RX_LENGTH_2K 2048
|
||||
#define MTK_TX_DMA_BUF_LEN 0x3fff
|
||||
#define MTK_DMA_SIZE 512
|
||||
#define MTK_NAPI_WEIGHT 64
|
||||
#define MTK_MAC_COUNT 2
|
||||
-#define MTK_RX_ETH_HLEN (VLAN_ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN)
|
||||
+#define MTK_RX_ETH_HLEN (ETH_HLEN + ETH_FCS_LEN)
|
||||
#define MTK_RX_HLEN (NET_SKB_PAD + MTK_RX_ETH_HLEN + NET_IP_ALIGN)
|
||||
#define MTK_DMA_DUMMY_DESC 0xffffffff
|
||||
#define MTK_DEFAULT_MSG_ENABLE (NETIF_MSG_DRV | \
|
||||
@@ -352,7 +353,12 @@
|
||||
|
||||
/* Mac control registers */
|
||||
#define MTK_MAC_MCR(x) (0x10100 + (x * 0x100))
|
||||
-#define MAC_MCR_MAX_RX_1536 BIT(24)
|
||||
+#define MAC_MCR_MAX_RX_MASK GENMASK(25, 24)
|
||||
+#define MAC_MCR_MAX_RX(_x) (MAC_MCR_MAX_RX_MASK & ((_x) << 24))
|
||||
+#define MAC_MCR_MAX_RX_1518 0x0
|
||||
+#define MAC_MCR_MAX_RX_1536 0x1
|
||||
+#define MAC_MCR_MAX_RX_1552 0x2
|
||||
+#define MAC_MCR_MAX_RX_2048 0x3
|
||||
#define MAC_MCR_IPG_CFG (BIT(18) | BIT(16))
|
||||
#define MAC_MCR_FORCE_MODE BIT(15)
|
||||
#define MAC_MCR_TX_EN BIT(14)
|
@ -0,0 +1,100 @@
|
||||
From d532bcd0b2699d84d71a0c71d37157ac6eb3be25 Mon Sep 17 00:00:00 2001
|
||||
Message-Id: <d532bcd0b2699d84d71a0c71d37157ac6eb3be25.1645246598.git.plr.vincent@gmail.com>
|
||||
From: Florian Westphal <fw@strlen.de>
|
||||
Date: Thu, 26 Aug 2021 15:54:19 +0200
|
||||
Subject: [PATCH] netfilter: conntrack: sanitize table size default settings
|
||||
|
||||
conntrack has two distinct table size settings:
|
||||
nf_conntrack_max and nf_conntrack_buckets.
|
||||
|
||||
The former limits how many conntrack objects are allowed to exist
|
||||
in each namespace.
|
||||
|
||||
The second sets the size of the hashtable.
|
||||
|
||||
As all entries are inserted twice (once for original direction, once for
|
||||
reply), there should be at least twice as many buckets in the table than
|
||||
the maximum number of conntrack objects that can exist at the same time.
|
||||
|
||||
Change the default multiplier to 1 and increase the chosen bucket sizes.
|
||||
This results in the same nf_conntrack_max settings as before but reduces
|
||||
the average bucket list length.
|
||||
|
||||
Signed-off-by: Florian Westphal <fw@strlen.de>
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
---
|
||||
.../networking/nf_conntrack-sysctl.rst | 13 ++++----
|
||||
net/netfilter/nf_conntrack_core.c | 30 +++++++++----------
|
||||
2 files changed, 22 insertions(+), 21 deletions(-)
|
||||
|
||||
--- a/Documentation/networking/nf_conntrack-sysctl.rst
|
||||
+++ b/Documentation/networking/nf_conntrack-sysctl.rst
|
||||
@@ -17,9 +17,8 @@ nf_conntrack_acct - BOOLEAN
|
||||
nf_conntrack_buckets - INTEGER
|
||||
Size of hash table. If not specified as parameter during module
|
||||
loading, the default size is calculated by dividing total memory
|
||||
- by 16384 to determine the number of buckets but the hash table will
|
||||
- never have fewer than 32 and limited to 16384 buckets. For systems
|
||||
- with more than 4GB of memory it will be 65536 buckets.
|
||||
+ by 16384 to determine the number of buckets. The hash table will
|
||||
+ never have fewer than 1024 and never more than 262144 buckets.
|
||||
This sysctl is only writeable in the initial net namespace.
|
||||
|
||||
nf_conntrack_checksum - BOOLEAN
|
||||
@@ -100,8 +99,12 @@ nf_conntrack_log_invalid - INTEGER
|
||||
Log invalid packets of a type specified by value.
|
||||
|
||||
nf_conntrack_max - INTEGER
|
||||
- Size of connection tracking table. Default value is
|
||||
- nf_conntrack_buckets value * 4.
|
||||
+ Maximum number of allowed connection tracking entries. This value is set
|
||||
+ to nf_conntrack_buckets by default.
|
||||
+ Note that connection tracking entries are added to the table twice -- once
|
||||
+ for the original direction and once for the reply direction (i.e., with
|
||||
+ the reversed address). This means that with default settings a maxed-out
|
||||
+ table will have a average hash chain length of 2, not 1.
|
||||
|
||||
nf_conntrack_tcp_be_liberal - BOOLEAN
|
||||
- 0 - disabled (default)
|
||||
--- a/net/netfilter/nf_conntrack_core.c
|
||||
+++ b/net/netfilter/nf_conntrack_core.c
|
||||
@@ -2575,26 +2575,24 @@ int nf_conntrack_init_start(void)
|
||||
spin_lock_init(&nf_conntrack_locks[i]);
|
||||
|
||||
if (!nf_conntrack_htable_size) {
|
||||
- /* Idea from tcp.c: use 1/16384 of memory.
|
||||
- * On i386: 32MB machine has 512 buckets.
|
||||
- * >= 1GB machines have 16384 buckets.
|
||||
- * >= 4GB machines have 65536 buckets.
|
||||
- */
|
||||
nf_conntrack_htable_size
|
||||
= (((nr_pages << PAGE_SHIFT) / 16384)
|
||||
/ sizeof(struct hlist_head));
|
||||
- if (nr_pages > (4 * (1024 * 1024 * 1024 / PAGE_SIZE)))
|
||||
- nf_conntrack_htable_size = 65536;
|
||||
+ if (BITS_PER_LONG >= 64 &&
|
||||
+ nr_pages > (4 * (1024 * 1024 * 1024 / PAGE_SIZE)))
|
||||
+ nf_conntrack_htable_size = 262144;
|
||||
else if (nr_pages > (1024 * 1024 * 1024 / PAGE_SIZE))
|
||||
- nf_conntrack_htable_size = 16384;
|
||||
- if (nf_conntrack_htable_size < 32)
|
||||
- nf_conntrack_htable_size = 32;
|
||||
+ nf_conntrack_htable_size = 65536;
|
||||
|
||||
- /* Use a max. factor of four by default to get the same max as
|
||||
- * with the old struct list_heads. When a table size is given
|
||||
- * we use the old value of 8 to avoid reducing the max.
|
||||
- * entries. */
|
||||
- max_factor = 4;
|
||||
+ if (nf_conntrack_htable_size < 1024)
|
||||
+ nf_conntrack_htable_size = 1024;
|
||||
+ /* Use a max. factor of one by default to keep the average
|
||||
+ * hash chain length at 2 entries. Each entry has to be added
|
||||
+ * twice (once for original direction, once for reply).
|
||||
+ * When a table size is given we use the old value of 8 to
|
||||
+ * avoid implicit reduction of the max entries setting.
|
||||
+ */
|
||||
+ max_factor = 1;
|
||||
}
|
||||
|
||||
nf_conntrack_hash = nf_ct_alloc_hashtable(&nf_conntrack_htable_size, 1);
|
@ -0,0 +1,56 @@
|
||||
From b1ae3587d16a8c8fc9453e147c8708d6f006ffbb Mon Sep 17 00:00:00 2001
|
||||
From: Bjarni Jonasson <bjarni.jonasson@microchip.com>
|
||||
Date: Wed, 13 Jan 2021 12:56:25 +0100
|
||||
Subject: [PATCH] net: phy: Add 100 base-x mode
|
||||
|
||||
Sparx-5 supports this mode and it is missing in the PHY core.
|
||||
|
||||
Signed-off-by: Bjarni Jonasson <bjarni.jonasson@microchip.com>
|
||||
Reviewed-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
Documentation/networking/phy.rst | 5 +++++
|
||||
include/linux/phy.h | 4 ++++
|
||||
2 files changed, 9 insertions(+)
|
||||
|
||||
--- a/Documentation/networking/phy.rst
|
||||
+++ b/Documentation/networking/phy.rst
|
||||
@@ -286,6 +286,11 @@ Some of the interface modes are describe
|
||||
Note: due to legacy usage, some 10GBASE-R usage incorrectly makes
|
||||
use of this definition.
|
||||
|
||||
+``PHY_INTERFACE_MODE_100BASEX``
|
||||
+ This defines IEEE 802.3 Clause 24. The link operates at a fixed data
|
||||
+ rate of 125Mpbs using a 4B/5B encoding scheme, resulting in an underlying
|
||||
+ data rate of 100Mpbs.
|
||||
+
|
||||
Pause frames / flow control
|
||||
===========================
|
||||
|
||||
--- a/include/linux/phy.h
|
||||
+++ b/include/linux/phy.h
|
||||
@@ -104,6 +104,7 @@ extern const int phy_10gbit_features_arr
|
||||
* @PHY_INTERFACE_MODE_MOCA: Multimedia over Coax
|
||||
* @PHY_INTERFACE_MODE_QSGMII: Quad SGMII
|
||||
* @PHY_INTERFACE_MODE_TRGMII: Turbo RGMII
|
||||
+ * @PHY_INTERFACE_MODE_100BASEX: 100 BaseX
|
||||
* @PHY_INTERFACE_MODE_1000BASEX: 1000 BaseX
|
||||
* @PHY_INTERFACE_MODE_2500BASEX: 2500 BaseX
|
||||
* @PHY_INTERFACE_MODE_RXAUI: Reduced XAUI
|
||||
@@ -135,6 +136,7 @@ typedef enum {
|
||||
PHY_INTERFACE_MODE_MOCA,
|
||||
PHY_INTERFACE_MODE_QSGMII,
|
||||
PHY_INTERFACE_MODE_TRGMII,
|
||||
+ PHY_INTERFACE_MODE_100BASEX,
|
||||
PHY_INTERFACE_MODE_1000BASEX,
|
||||
PHY_INTERFACE_MODE_2500BASEX,
|
||||
PHY_INTERFACE_MODE_RXAUI,
|
||||
@@ -217,6 +219,8 @@ static inline const char *phy_modes(phy_
|
||||
return "usxgmii";
|
||||
case PHY_INTERFACE_MODE_10GKR:
|
||||
return "10gbase-kr";
|
||||
+ case PHY_INTERFACE_MODE_100BASEX:
|
||||
+ return "100base-x";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
From 6e12f35cef6b8a458d7ecf507ae330e0bffaad8c Mon Sep 17 00:00:00 2001
|
||||
From: Bjarni Jonasson <bjarni.jonasson@microchip.com>
|
||||
Date: Wed, 13 Jan 2021 12:56:26 +0100
|
||||
Subject: [PATCH] sfp: add support for 100 base-x SFPs
|
||||
|
||||
Add support for 100Base-FX, 100Base-LX, 100Base-PX and 100Base-BX10 modules
|
||||
This is needed for Sparx-5 switch.
|
||||
|
||||
Signed-off-by: Bjarni Jonasson <bjarni.jonasson@microchip.com>
|
||||
Reviewed-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/phy/sfp-bus.c | 9 +++++++++
|
||||
1 file changed, 9 insertions(+)
|
||||
|
||||
--- a/drivers/net/phy/sfp-bus.c
|
||||
+++ b/drivers/net/phy/sfp-bus.c
|
||||
@@ -280,6 +280,12 @@ void sfp_parse_support(struct sfp_bus *b
|
||||
br_min <= 1300 && br_max >= 1200)
|
||||
phylink_set(modes, 1000baseX_Full);
|
||||
|
||||
+ /* 100Base-FX, 100Base-LX, 100Base-PX, 100Base-BX10 */
|
||||
+ if (id->base.e100_base_fx || id->base.e100_base_lx)
|
||||
+ phylink_set(modes, 100baseFX_Full);
|
||||
+ if ((id->base.e_base_px || id->base.e_base_bx10) && br_nom == 100)
|
||||
+ phylink_set(modes, 100baseFX_Full);
|
||||
+
|
||||
/* For active or passive cables, select the link modes
|
||||
* based on the bit rates and the cable compliance bytes.
|
||||
*/
|
||||
@@ -399,6 +405,9 @@ phy_interface_t sfp_select_interface(str
|
||||
if (phylink_test(link_modes, 1000baseX_Full))
|
||||
return PHY_INTERFACE_MODE_1000BASEX;
|
||||
|
||||
+ if (phylink_test(link_modes, 100baseFX_Full))
|
||||
+ return PHY_INTERFACE_MODE_100BASEX;
|
||||
+
|
||||
dev_warn(bus->sfp_dev, "Unable to ascertain link mode\n");
|
||||
|
||||
return PHY_INTERFACE_MODE_NA;
|
@ -0,0 +1,549 @@
|
||||
From 41d26bf4aba070dfd2ab48866cc27a48ee6228c7 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Marek=20Beh=C3=BAn?= <kabel@kernel.org>
|
||||
Date: Tue, 20 Apr 2021 09:53:59 +0200
|
||||
Subject: [PATCH] net: phy: marvell: refactor HWMON OOP style
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Use a structure of Marvell PHY specific HWMON methods to reduce code
|
||||
duplication. Store a pointer to this structure into the PHY driver's
|
||||
driver_data member.
|
||||
|
||||
Signed-off-by: Marek Behún <kabel@kernel.org>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/phy/marvell.c | 369 +++++++++++++-------------------------
|
||||
1 file changed, 125 insertions(+), 244 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/marvell.c
|
||||
+++ b/drivers/net/phy/marvell.c
|
||||
@@ -2141,6 +2141,19 @@ static int marvell_vct7_cable_test_get_s
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HWMON
|
||||
+struct marvell_hwmon_ops {
|
||||
+ int (*get_temp)(struct phy_device *phydev, long *temp);
|
||||
+ int (*get_temp_critical)(struct phy_device *phydev, long *temp);
|
||||
+ int (*set_temp_critical)(struct phy_device *phydev, long temp);
|
||||
+ int (*get_temp_alarm)(struct phy_device *phydev, long *alarm);
|
||||
+};
|
||||
+
|
||||
+static const struct marvell_hwmon_ops *
|
||||
+to_marvell_hwmon_ops(const struct phy_device *phydev)
|
||||
+{
|
||||
+ return phydev->drv->driver_data;
|
||||
+}
|
||||
+
|
||||
static int m88e1121_get_temp(struct phy_device *phydev, long *temp)
|
||||
{
|
||||
int oldpage;
|
||||
@@ -2184,75 +2197,6 @@ error:
|
||||
return phy_restore_page(phydev, oldpage, ret);
|
||||
}
|
||||
|
||||
-static int m88e1121_hwmon_read(struct device *dev,
|
||||
- enum hwmon_sensor_types type,
|
||||
- u32 attr, int channel, long *temp)
|
||||
-{
|
||||
- struct phy_device *phydev = dev_get_drvdata(dev);
|
||||
- int err;
|
||||
-
|
||||
- switch (attr) {
|
||||
- case hwmon_temp_input:
|
||||
- err = m88e1121_get_temp(phydev, temp);
|
||||
- break;
|
||||
- default:
|
||||
- return -EOPNOTSUPP;
|
||||
- }
|
||||
-
|
||||
- return err;
|
||||
-}
|
||||
-
|
||||
-static umode_t m88e1121_hwmon_is_visible(const void *data,
|
||||
- enum hwmon_sensor_types type,
|
||||
- u32 attr, int channel)
|
||||
-{
|
||||
- if (type != hwmon_temp)
|
||||
- return 0;
|
||||
-
|
||||
- switch (attr) {
|
||||
- case hwmon_temp_input:
|
||||
- return 0444;
|
||||
- default:
|
||||
- return 0;
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-static u32 m88e1121_hwmon_chip_config[] = {
|
||||
- HWMON_C_REGISTER_TZ,
|
||||
- 0
|
||||
-};
|
||||
-
|
||||
-static const struct hwmon_channel_info m88e1121_hwmon_chip = {
|
||||
- .type = hwmon_chip,
|
||||
- .config = m88e1121_hwmon_chip_config,
|
||||
-};
|
||||
-
|
||||
-static u32 m88e1121_hwmon_temp_config[] = {
|
||||
- HWMON_T_INPUT,
|
||||
- 0
|
||||
-};
|
||||
-
|
||||
-static const struct hwmon_channel_info m88e1121_hwmon_temp = {
|
||||
- .type = hwmon_temp,
|
||||
- .config = m88e1121_hwmon_temp_config,
|
||||
-};
|
||||
-
|
||||
-static const struct hwmon_channel_info *m88e1121_hwmon_info[] = {
|
||||
- &m88e1121_hwmon_chip,
|
||||
- &m88e1121_hwmon_temp,
|
||||
- NULL
|
||||
-};
|
||||
-
|
||||
-static const struct hwmon_ops m88e1121_hwmon_hwmon_ops = {
|
||||
- .is_visible = m88e1121_hwmon_is_visible,
|
||||
- .read = m88e1121_hwmon_read,
|
||||
-};
|
||||
-
|
||||
-static const struct hwmon_chip_info m88e1121_hwmon_chip_info = {
|
||||
- .ops = &m88e1121_hwmon_hwmon_ops,
|
||||
- .info = m88e1121_hwmon_info,
|
||||
-};
|
||||
-
|
||||
static int m88e1510_get_temp(struct phy_device *phydev, long *temp)
|
||||
{
|
||||
int ret;
|
||||
@@ -2315,92 +2259,6 @@ static int m88e1510_get_temp_alarm(struc
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int m88e1510_hwmon_read(struct device *dev,
|
||||
- enum hwmon_sensor_types type,
|
||||
- u32 attr, int channel, long *temp)
|
||||
-{
|
||||
- struct phy_device *phydev = dev_get_drvdata(dev);
|
||||
- int err;
|
||||
-
|
||||
- switch (attr) {
|
||||
- case hwmon_temp_input:
|
||||
- err = m88e1510_get_temp(phydev, temp);
|
||||
- break;
|
||||
- case hwmon_temp_crit:
|
||||
- err = m88e1510_get_temp_critical(phydev, temp);
|
||||
- break;
|
||||
- case hwmon_temp_max_alarm:
|
||||
- err = m88e1510_get_temp_alarm(phydev, temp);
|
||||
- break;
|
||||
- default:
|
||||
- return -EOPNOTSUPP;
|
||||
- }
|
||||
-
|
||||
- return err;
|
||||
-}
|
||||
-
|
||||
-static int m88e1510_hwmon_write(struct device *dev,
|
||||
- enum hwmon_sensor_types type,
|
||||
- u32 attr, int channel, long temp)
|
||||
-{
|
||||
- struct phy_device *phydev = dev_get_drvdata(dev);
|
||||
- int err;
|
||||
-
|
||||
- switch (attr) {
|
||||
- case hwmon_temp_crit:
|
||||
- err = m88e1510_set_temp_critical(phydev, temp);
|
||||
- break;
|
||||
- default:
|
||||
- return -EOPNOTSUPP;
|
||||
- }
|
||||
- return err;
|
||||
-}
|
||||
-
|
||||
-static umode_t m88e1510_hwmon_is_visible(const void *data,
|
||||
- enum hwmon_sensor_types type,
|
||||
- u32 attr, int channel)
|
||||
-{
|
||||
- if (type != hwmon_temp)
|
||||
- return 0;
|
||||
-
|
||||
- switch (attr) {
|
||||
- case hwmon_temp_input:
|
||||
- case hwmon_temp_max_alarm:
|
||||
- return 0444;
|
||||
- case hwmon_temp_crit:
|
||||
- return 0644;
|
||||
- default:
|
||||
- return 0;
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-static u32 m88e1510_hwmon_temp_config[] = {
|
||||
- HWMON_T_INPUT | HWMON_T_CRIT | HWMON_T_MAX_ALARM,
|
||||
- 0
|
||||
-};
|
||||
-
|
||||
-static const struct hwmon_channel_info m88e1510_hwmon_temp = {
|
||||
- .type = hwmon_temp,
|
||||
- .config = m88e1510_hwmon_temp_config,
|
||||
-};
|
||||
-
|
||||
-static const struct hwmon_channel_info *m88e1510_hwmon_info[] = {
|
||||
- &m88e1121_hwmon_chip,
|
||||
- &m88e1510_hwmon_temp,
|
||||
- NULL
|
||||
-};
|
||||
-
|
||||
-static const struct hwmon_ops m88e1510_hwmon_hwmon_ops = {
|
||||
- .is_visible = m88e1510_hwmon_is_visible,
|
||||
- .read = m88e1510_hwmon_read,
|
||||
- .write = m88e1510_hwmon_write,
|
||||
-};
|
||||
-
|
||||
-static const struct hwmon_chip_info m88e1510_hwmon_chip_info = {
|
||||
- .ops = &m88e1510_hwmon_hwmon_ops,
|
||||
- .info = m88e1510_hwmon_info,
|
||||
-};
|
||||
-
|
||||
static int m88e6390_get_temp(struct phy_device *phydev, long *temp)
|
||||
{
|
||||
int sum = 0;
|
||||
@@ -2459,63 +2317,112 @@ error:
|
||||
return ret;
|
||||
}
|
||||
|
||||
-static int m88e6390_hwmon_read(struct device *dev,
|
||||
- enum hwmon_sensor_types type,
|
||||
- u32 attr, int channel, long *temp)
|
||||
+static int marvell_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
|
||||
+ u32 attr, int channel, long *temp)
|
||||
{
|
||||
struct phy_device *phydev = dev_get_drvdata(dev);
|
||||
- int err;
|
||||
+ const struct marvell_hwmon_ops *ops = to_marvell_hwmon_ops(phydev);
|
||||
+ int err = -EOPNOTSUPP;
|
||||
|
||||
switch (attr) {
|
||||
case hwmon_temp_input:
|
||||
- err = m88e6390_get_temp(phydev, temp);
|
||||
+ if (ops->get_temp)
|
||||
+ err = ops->get_temp(phydev, temp);
|
||||
+ break;
|
||||
+ case hwmon_temp_crit:
|
||||
+ if (ops->get_temp_critical)
|
||||
+ err = ops->get_temp_critical(phydev, temp);
|
||||
+ break;
|
||||
+ case hwmon_temp_max_alarm:
|
||||
+ if (ops->get_temp_alarm)
|
||||
+ err = ops->get_temp_alarm(phydev, temp);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+static int marvell_hwmon_write(struct device *dev, enum hwmon_sensor_types type,
|
||||
+ u32 attr, int channel, long temp)
|
||||
+{
|
||||
+ struct phy_device *phydev = dev_get_drvdata(dev);
|
||||
+ const struct marvell_hwmon_ops *ops = to_marvell_hwmon_ops(phydev);
|
||||
+ int err = -EOPNOTSUPP;
|
||||
+
|
||||
+ switch (attr) {
|
||||
+ case hwmon_temp_crit:
|
||||
+ if (ops->set_temp_critical)
|
||||
+ err = ops->set_temp_critical(phydev, temp);
|
||||
break;
|
||||
default:
|
||||
- return -EOPNOTSUPP;
|
||||
+ fallthrough;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
-static umode_t m88e6390_hwmon_is_visible(const void *data,
|
||||
- enum hwmon_sensor_types type,
|
||||
- u32 attr, int channel)
|
||||
+static umode_t marvell_hwmon_is_visible(const void *data,
|
||||
+ enum hwmon_sensor_types type,
|
||||
+ u32 attr, int channel)
|
||||
{
|
||||
+ const struct phy_device *phydev = data;
|
||||
+ const struct marvell_hwmon_ops *ops = to_marvell_hwmon_ops(phydev);
|
||||
+
|
||||
if (type != hwmon_temp)
|
||||
return 0;
|
||||
|
||||
switch (attr) {
|
||||
case hwmon_temp_input:
|
||||
- return 0444;
|
||||
+ return ops->get_temp ? 0444 : 0;
|
||||
+ case hwmon_temp_max_alarm:
|
||||
+ return ops->get_temp_alarm ? 0444 : 0;
|
||||
+ case hwmon_temp_crit:
|
||||
+ return (ops->get_temp_critical ? 0444 : 0) |
|
||||
+ (ops->set_temp_critical ? 0200 : 0);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
-static u32 m88e6390_hwmon_temp_config[] = {
|
||||
- HWMON_T_INPUT,
|
||||
+static u32 marvell_hwmon_chip_config[] = {
|
||||
+ HWMON_C_REGISTER_TZ,
|
||||
0
|
||||
};
|
||||
|
||||
-static const struct hwmon_channel_info m88e6390_hwmon_temp = {
|
||||
+static const struct hwmon_channel_info marvell_hwmon_chip = {
|
||||
+ .type = hwmon_chip,
|
||||
+ .config = marvell_hwmon_chip_config,
|
||||
+};
|
||||
+
|
||||
+/* we can define HWMON_T_CRIT and HWMON_T_MAX_ALARM even though these are not
|
||||
+ * defined for all PHYs, because the hwmon code checks whether the attributes
|
||||
+ * exists via the .is_visible method
|
||||
+ */
|
||||
+static u32 marvell_hwmon_temp_config[] = {
|
||||
+ HWMON_T_INPUT | HWMON_T_CRIT | HWMON_T_MAX_ALARM,
|
||||
+ 0
|
||||
+};
|
||||
+
|
||||
+static const struct hwmon_channel_info marvell_hwmon_temp = {
|
||||
.type = hwmon_temp,
|
||||
- .config = m88e6390_hwmon_temp_config,
|
||||
+ .config = marvell_hwmon_temp_config,
|
||||
};
|
||||
|
||||
-static const struct hwmon_channel_info *m88e6390_hwmon_info[] = {
|
||||
- &m88e1121_hwmon_chip,
|
||||
- &m88e6390_hwmon_temp,
|
||||
+static const struct hwmon_channel_info *marvell_hwmon_info[] = {
|
||||
+ &marvell_hwmon_chip,
|
||||
+ &marvell_hwmon_temp,
|
||||
NULL
|
||||
};
|
||||
|
||||
-static const struct hwmon_ops m88e6390_hwmon_hwmon_ops = {
|
||||
- .is_visible = m88e6390_hwmon_is_visible,
|
||||
- .read = m88e6390_hwmon_read,
|
||||
+static const struct hwmon_ops marvell_hwmon_hwmon_ops = {
|
||||
+ .is_visible = marvell_hwmon_is_visible,
|
||||
+ .read = marvell_hwmon_read,
|
||||
+ .write = marvell_hwmon_write,
|
||||
};
|
||||
|
||||
-static const struct hwmon_chip_info m88e6390_hwmon_chip_info = {
|
||||
- .ops = &m88e6390_hwmon_hwmon_ops,
|
||||
- .info = m88e6390_hwmon_info,
|
||||
+static const struct hwmon_chip_info marvell_hwmon_chip_info = {
|
||||
+ .ops = &marvell_hwmon_hwmon_ops,
|
||||
+ .info = marvell_hwmon_info,
|
||||
};
|
||||
|
||||
static int marvell_hwmon_name(struct phy_device *phydev)
|
||||
@@ -2538,49 +2445,48 @@ static int marvell_hwmon_name(struct phy
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int marvell_hwmon_probe(struct phy_device *phydev,
|
||||
- const struct hwmon_chip_info *chip)
|
||||
+static int marvell_hwmon_probe(struct phy_device *phydev)
|
||||
{
|
||||
+ const struct marvell_hwmon_ops *ops = to_marvell_hwmon_ops(phydev);
|
||||
struct marvell_priv *priv = phydev->priv;
|
||||
struct device *dev = &phydev->mdio.dev;
|
||||
int err;
|
||||
|
||||
+ if (!ops)
|
||||
+ return 0;
|
||||
+
|
||||
err = marvell_hwmon_name(phydev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
priv->hwmon_dev = devm_hwmon_device_register_with_info(
|
||||
- dev, priv->hwmon_name, phydev, chip, NULL);
|
||||
+ dev, priv->hwmon_name, phydev, &marvell_hwmon_chip_info, NULL);
|
||||
|
||||
return PTR_ERR_OR_ZERO(priv->hwmon_dev);
|
||||
}
|
||||
|
||||
-static int m88e1121_hwmon_probe(struct phy_device *phydev)
|
||||
-{
|
||||
- return marvell_hwmon_probe(phydev, &m88e1121_hwmon_chip_info);
|
||||
-}
|
||||
+static const struct marvell_hwmon_ops m88e1121_hwmon_ops = {
|
||||
+ .get_temp = m88e1121_get_temp,
|
||||
+};
|
||||
|
||||
-static int m88e1510_hwmon_probe(struct phy_device *phydev)
|
||||
-{
|
||||
- return marvell_hwmon_probe(phydev, &m88e1510_hwmon_chip_info);
|
||||
-}
|
||||
+static const struct marvell_hwmon_ops m88e1510_hwmon_ops = {
|
||||
+ .get_temp = m88e1510_get_temp,
|
||||
+ .get_temp_critical = m88e1510_get_temp_critical,
|
||||
+ .set_temp_critical = m88e1510_set_temp_critical,
|
||||
+ .get_temp_alarm = m88e1510_get_temp_alarm,
|
||||
+};
|
||||
+
|
||||
+static const struct marvell_hwmon_ops m88e6390_hwmon_ops = {
|
||||
+ .get_temp = m88e6390_get_temp,
|
||||
+};
|
||||
+
|
||||
+#define DEF_MARVELL_HWMON_OPS(s) (&(s))
|
||||
|
||||
-static int m88e6390_hwmon_probe(struct phy_device *phydev)
|
||||
-{
|
||||
- return marvell_hwmon_probe(phydev, &m88e6390_hwmon_chip_info);
|
||||
-}
|
||||
#else
|
||||
-static int m88e1121_hwmon_probe(struct phy_device *phydev)
|
||||
-{
|
||||
- return 0;
|
||||
-}
|
||||
|
||||
-static int m88e1510_hwmon_probe(struct phy_device *phydev)
|
||||
-{
|
||||
- return 0;
|
||||
-}
|
||||
+#define DEF_MARVELL_HWMON_OPS(s) NULL
|
||||
|
||||
-static int m88e6390_hwmon_probe(struct phy_device *phydev)
|
||||
+static int marvell_hwmon_probe(struct phy_device *phydev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -2596,40 +2502,7 @@ static int marvell_probe(struct phy_devi
|
||||
|
||||
phydev->priv = priv;
|
||||
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static int m88e1121_probe(struct phy_device *phydev)
|
||||
-{
|
||||
- int err;
|
||||
-
|
||||
- err = marvell_probe(phydev);
|
||||
- if (err)
|
||||
- return err;
|
||||
-
|
||||
- return m88e1121_hwmon_probe(phydev);
|
||||
-}
|
||||
-
|
||||
-static int m88e1510_probe(struct phy_device *phydev)
|
||||
-{
|
||||
- int err;
|
||||
-
|
||||
- err = marvell_probe(phydev);
|
||||
- if (err)
|
||||
- return err;
|
||||
-
|
||||
- return m88e1510_hwmon_probe(phydev);
|
||||
-}
|
||||
-
|
||||
-static int m88e6390_probe(struct phy_device *phydev)
|
||||
-{
|
||||
- int err;
|
||||
-
|
||||
- err = marvell_probe(phydev);
|
||||
- if (err)
|
||||
- return err;
|
||||
-
|
||||
- return m88e6390_hwmon_probe(phydev);
|
||||
+ return marvell_hwmon_probe(phydev);
|
||||
}
|
||||
|
||||
static struct phy_driver marvell_drivers[] = {
|
||||
@@ -2714,8 +2587,9 @@ static struct phy_driver marvell_drivers
|
||||
.phy_id = MARVELL_PHY_ID_88E1121R,
|
||||
.phy_id_mask = MARVELL_PHY_ID_MASK,
|
||||
.name = "Marvell 88E1121R",
|
||||
+ .driver_data = DEF_MARVELL_HWMON_OPS(m88e1121_hwmon_ops),
|
||||
/* PHY_GBIT_FEATURES */
|
||||
- .probe = m88e1121_probe,
|
||||
+ .probe = marvell_probe,
|
||||
.config_init = marvell_config_init,
|
||||
.config_aneg = m88e1121_config_aneg,
|
||||
.read_status = marvell_read_status,
|
||||
@@ -2834,9 +2708,10 @@ static struct phy_driver marvell_drivers
|
||||
.phy_id = MARVELL_PHY_ID_88E1510,
|
||||
.phy_id_mask = MARVELL_PHY_ID_MASK,
|
||||
.name = "Marvell 88E1510",
|
||||
+ .driver_data = DEF_MARVELL_HWMON_OPS(m88e1510_hwmon_ops),
|
||||
.features = PHY_GBIT_FIBRE_FEATURES,
|
||||
.flags = PHY_POLL_CABLE_TEST,
|
||||
- .probe = m88e1510_probe,
|
||||
+ .probe = marvell_probe,
|
||||
.config_init = m88e1510_config_init,
|
||||
.config_aneg = m88e1510_config_aneg,
|
||||
.read_status = marvell_read_status,
|
||||
@@ -2863,9 +2738,10 @@ static struct phy_driver marvell_drivers
|
||||
.phy_id = MARVELL_PHY_ID_88E1540,
|
||||
.phy_id_mask = MARVELL_PHY_ID_MASK,
|
||||
.name = "Marvell 88E1540",
|
||||
+ .driver_data = DEF_MARVELL_HWMON_OPS(m88e1510_hwmon_ops),
|
||||
/* PHY_GBIT_FEATURES */
|
||||
.flags = PHY_POLL_CABLE_TEST,
|
||||
- .probe = m88e1510_probe,
|
||||
+ .probe = marvell_probe,
|
||||
.config_init = marvell_config_init,
|
||||
.config_aneg = m88e1510_config_aneg,
|
||||
.read_status = marvell_read_status,
|
||||
@@ -2889,7 +2765,8 @@ static struct phy_driver marvell_drivers
|
||||
.phy_id = MARVELL_PHY_ID_88E1545,
|
||||
.phy_id_mask = MARVELL_PHY_ID_MASK,
|
||||
.name = "Marvell 88E1545",
|
||||
- .probe = m88e1510_probe,
|
||||
+ .driver_data = DEF_MARVELL_HWMON_OPS(m88e1510_hwmon_ops),
|
||||
+ .probe = marvell_probe,
|
||||
/* PHY_GBIT_FEATURES */
|
||||
.flags = PHY_POLL_CABLE_TEST,
|
||||
.config_init = marvell_config_init,
|
||||
@@ -2935,9 +2812,10 @@ static struct phy_driver marvell_drivers
|
||||
.phy_id = MARVELL_PHY_ID_88E6341_FAMILY,
|
||||
.phy_id_mask = MARVELL_PHY_ID_MASK,
|
||||
.name = "Marvell 88E6341 Family",
|
||||
+ .driver_data = DEF_MARVELL_HWMON_OPS(m88e1510_hwmon_ops),
|
||||
/* PHY_GBIT_FEATURES */
|
||||
.flags = PHY_POLL_CABLE_TEST,
|
||||
- .probe = m88e1510_probe,
|
||||
+ .probe = marvell_probe,
|
||||
.config_init = marvell_config_init,
|
||||
.config_aneg = m88e6390_config_aneg,
|
||||
.read_status = marvell_read_status,
|
||||
@@ -2961,9 +2839,10 @@ static struct phy_driver marvell_drivers
|
||||
.phy_id = MARVELL_PHY_ID_88E6390_FAMILY,
|
||||
.phy_id_mask = MARVELL_PHY_ID_MASK,
|
||||
.name = "Marvell 88E6390 Family",
|
||||
+ .driver_data = DEF_MARVELL_HWMON_OPS(m88e6390_hwmon_ops),
|
||||
/* PHY_GBIT_FEATURES */
|
||||
.flags = PHY_POLL_CABLE_TEST,
|
||||
- .probe = m88e6390_probe,
|
||||
+ .probe = marvell_probe,
|
||||
.config_init = marvell_config_init,
|
||||
.config_aneg = m88e6390_config_aneg,
|
||||
.read_status = marvell_read_status,
|
||||
@@ -2987,7 +2866,8 @@ static struct phy_driver marvell_drivers
|
||||
.phy_id = MARVELL_PHY_ID_88E1340S,
|
||||
.phy_id_mask = MARVELL_PHY_ID_MASK,
|
||||
.name = "Marvell 88E1340S",
|
||||
- .probe = m88e1510_probe,
|
||||
+ .driver_data = DEF_MARVELL_HWMON_OPS(m88e1510_hwmon_ops),
|
||||
+ .probe = marvell_probe,
|
||||
/* PHY_GBIT_FEATURES */
|
||||
.config_init = marvell_config_init,
|
||||
.config_aneg = m88e1510_config_aneg,
|
||||
@@ -3009,7 +2889,8 @@ static struct phy_driver marvell_drivers
|
||||
.phy_id = MARVELL_PHY_ID_88E1548P,
|
||||
.phy_id_mask = MARVELL_PHY_ID_MASK,
|
||||
.name = "Marvell 88E1548P",
|
||||
- .probe = m88e1510_probe,
|
||||
+ .driver_data = DEF_MARVELL_HWMON_OPS(m88e1510_hwmon_ops),
|
||||
+ .probe = marvell_probe,
|
||||
.features = PHY_GBIT_FIBRE_FEATURES,
|
||||
.config_init = marvell_config_init,
|
||||
.config_aneg = m88e1510_config_aneg,
|
@ -0,0 +1,161 @@
|
||||
From b697d9d38a5a5ab405d7cc4743d39fe2c5d7517c Mon Sep 17 00:00:00 2001
|
||||
From: Ivan Bornyakov <i.bornyakov@metrotek.ru>
|
||||
Date: Thu, 12 Aug 2021 16:42:56 +0300
|
||||
Subject: [PATCH] net: phy: marvell: add SFP support for 88E1510
|
||||
|
||||
Add support for SFP cages connected to the Marvell 88E1512 transceiver.
|
||||
88E1512 supports for SGMII/1000Base-X/100Base-FX media type with RGMII
|
||||
on system interface. Configure PHY to appropriate mode depending on the
|
||||
type of SFP inserted. On SFP removal configure PHY to the RGMII-copper
|
||||
mode so RJ-45 port can still work.
|
||||
|
||||
Signed-off-by: Ivan Bornyakov <i.bornyakov@metrotek.ru>
|
||||
Link: https://lore.kernel.org/r/20210812134256.2436-1-i.bornyakov@metrotek.ru
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/phy/marvell.c | 105 +++++++++++++++++++++++++++++++++++++-
|
||||
1 file changed, 104 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/phy/marvell.c
|
||||
+++ b/drivers/net/phy/marvell.c
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <linux/marvell_phy.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/of.h>
|
||||
+#include <linux/sfp.h>
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <asm/irq.h>
|
||||
@@ -46,6 +47,7 @@
|
||||
#define MII_MARVELL_MISC_TEST_PAGE 0x06
|
||||
#define MII_MARVELL_VCT7_PAGE 0x07
|
||||
#define MII_MARVELL_WOL_PAGE 0x11
|
||||
+#define MII_MARVELL_MODE_PAGE 0x12
|
||||
|
||||
#define MII_M1011_IEVENT 0x13
|
||||
#define MII_M1011_IEVENT_CLEAR 0x0000
|
||||
@@ -162,7 +164,14 @@
|
||||
|
||||
#define MII_88E1510_GEN_CTRL_REG_1 0x14
|
||||
#define MII_88E1510_GEN_CTRL_REG_1_MODE_MASK 0x7
|
||||
+#define MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII 0x0 /* RGMII to copper */
|
||||
#define MII_88E1510_GEN_CTRL_REG_1_MODE_SGMII 0x1 /* SGMII to copper */
|
||||
+/* RGMII to 1000BASE-X */
|
||||
+#define MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII_1000X 0x2
|
||||
+/* RGMII to 100BASE-FX */
|
||||
+#define MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII_100FX 0x3
|
||||
+/* RGMII to SGMII */
|
||||
+#define MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII_SGMII 0x4
|
||||
#define MII_88E1510_GEN_CTRL_REG_1_RESET 0x8000 /* Soft reset */
|
||||
|
||||
#define MII_VCT5_TX_RX_MDI0_COUPLING 0x10
|
||||
@@ -2505,6 +2514,100 @@ static int marvell_probe(struct phy_devi
|
||||
return marvell_hwmon_probe(phydev);
|
||||
}
|
||||
|
||||
+static int m88e1510_sfp_insert(void *upstream, const struct sfp_eeprom_id *id)
|
||||
+{
|
||||
+ struct phy_device *phydev = upstream;
|
||||
+ phy_interface_t interface;
|
||||
+ struct device *dev;
|
||||
+ int oldpage;
|
||||
+ int ret = 0;
|
||||
+ u16 mode;
|
||||
+
|
||||
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(supported) = { 0, };
|
||||
+
|
||||
+ dev = &phydev->mdio.dev;
|
||||
+
|
||||
+ sfp_parse_support(phydev->sfp_bus, id, supported);
|
||||
+ interface = sfp_select_interface(phydev->sfp_bus, supported);
|
||||
+
|
||||
+ dev_info(dev, "%s SFP module inserted\n", phy_modes(interface));
|
||||
+
|
||||
+ switch (interface) {
|
||||
+ case PHY_INTERFACE_MODE_1000BASEX:
|
||||
+ mode = MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII_1000X;
|
||||
+
|
||||
+ break;
|
||||
+ case PHY_INTERFACE_MODE_100BASEX:
|
||||
+ mode = MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII_100FX;
|
||||
+
|
||||
+ break;
|
||||
+ case PHY_INTERFACE_MODE_SGMII:
|
||||
+ mode = MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII_SGMII;
|
||||
+
|
||||
+ break;
|
||||
+ default:
|
||||
+ dev_err(dev, "Incompatible SFP module inserted\n");
|
||||
+
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ oldpage = phy_select_page(phydev, MII_MARVELL_MODE_PAGE);
|
||||
+ if (oldpage < 0)
|
||||
+ goto error;
|
||||
+
|
||||
+ ret = __phy_modify(phydev, MII_88E1510_GEN_CTRL_REG_1,
|
||||
+ MII_88E1510_GEN_CTRL_REG_1_MODE_MASK, mode);
|
||||
+ if (ret < 0)
|
||||
+ goto error;
|
||||
+
|
||||
+ ret = __phy_set_bits(phydev, MII_88E1510_GEN_CTRL_REG_1,
|
||||
+ MII_88E1510_GEN_CTRL_REG_1_RESET);
|
||||
+
|
||||
+error:
|
||||
+ return phy_restore_page(phydev, oldpage, ret);
|
||||
+}
|
||||
+
|
||||
+static void m88e1510_sfp_remove(void *upstream)
|
||||
+{
|
||||
+ struct phy_device *phydev = upstream;
|
||||
+ int oldpage;
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ oldpage = phy_select_page(phydev, MII_MARVELL_MODE_PAGE);
|
||||
+ if (oldpage < 0)
|
||||
+ goto error;
|
||||
+
|
||||
+ ret = __phy_modify(phydev, MII_88E1510_GEN_CTRL_REG_1,
|
||||
+ MII_88E1510_GEN_CTRL_REG_1_MODE_MASK,
|
||||
+ MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII);
|
||||
+ if (ret < 0)
|
||||
+ goto error;
|
||||
+
|
||||
+ ret = __phy_set_bits(phydev, MII_88E1510_GEN_CTRL_REG_1,
|
||||
+ MII_88E1510_GEN_CTRL_REG_1_RESET);
|
||||
+
|
||||
+error:
|
||||
+ phy_restore_page(phydev, oldpage, ret);
|
||||
+}
|
||||
+
|
||||
+static const struct sfp_upstream_ops m88e1510_sfp_ops = {
|
||||
+ .module_insert = m88e1510_sfp_insert,
|
||||
+ .module_remove = m88e1510_sfp_remove,
|
||||
+ .attach = phy_sfp_attach,
|
||||
+ .detach = phy_sfp_detach,
|
||||
+};
|
||||
+
|
||||
+static int m88e1510_probe(struct phy_device *phydev)
|
||||
+{
|
||||
+ int err;
|
||||
+
|
||||
+ err = marvell_probe(phydev);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ return phy_sfp_probe(phydev, &m88e1510_sfp_ops);
|
||||
+}
|
||||
+
|
||||
static struct phy_driver marvell_drivers[] = {
|
||||
{
|
||||
.phy_id = MARVELL_PHY_ID_88E1101,
|
||||
@@ -2711,7 +2814,7 @@ static struct phy_driver marvell_drivers
|
||||
.driver_data = DEF_MARVELL_HWMON_OPS(m88e1510_hwmon_ops),
|
||||
.features = PHY_GBIT_FIBRE_FEATURES,
|
||||
.flags = PHY_POLL_CABLE_TEST,
|
||||
- .probe = marvell_probe,
|
||||
+ .probe = m88e1510_probe,
|
||||
.config_init = m88e1510_config_init,
|
||||
.config_aneg = m88e1510_config_aneg,
|
||||
.read_status = marvell_read_status,
|
@ -0,0 +1,181 @@
|
||||
From 429a0edeefd88cbfca5c417dfb8561047bb50769 Mon Sep 17 00:00:00 2001
|
||||
From: DENG Qingfang <dqfext@gmail.com>
|
||||
Date: Mon, 25 Jan 2021 12:43:22 +0800
|
||||
Subject: [PATCH] net: dsa: mt7530: MT7530 optional GPIO support
|
||||
|
||||
MT7530's LED controller can drive up to 15 LED/GPIOs.
|
||||
|
||||
Add support for GPIO control and allow users to use its GPIOs by
|
||||
setting gpio-controller property in device tree.
|
||||
|
||||
Signed-off-by: DENG Qingfang <dqfext@gmail.com>
|
||||
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/dsa/mt7530.c | 110 +++++++++++++++++++++++++++++++++++++++
|
||||
drivers/net/dsa/mt7530.h | 20 +++++++
|
||||
2 files changed, 130 insertions(+)
|
||||
|
||||
--- a/drivers/net/dsa/mt7530.c
|
||||
+++ b/drivers/net/dsa/mt7530.c
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/reset.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
+#include <linux/gpio/driver.h>
|
||||
#include <net/dsa.h>
|
||||
|
||||
#include "mt7530.h"
|
||||
@@ -1534,6 +1535,109 @@ mtk_get_tag_protocol(struct dsa_switch *
|
||||
}
|
||||
}
|
||||
|
||||
+static inline u32
|
||||
+mt7530_gpio_to_bit(unsigned int offset)
|
||||
+{
|
||||
+ /* Map GPIO offset to register bit
|
||||
+ * [ 2: 0] port 0 LED 0..2 as GPIO 0..2
|
||||
+ * [ 6: 4] port 1 LED 0..2 as GPIO 3..5
|
||||
+ * [10: 8] port 2 LED 0..2 as GPIO 6..8
|
||||
+ * [14:12] port 3 LED 0..2 as GPIO 9..11
|
||||
+ * [18:16] port 4 LED 0..2 as GPIO 12..14
|
||||
+ */
|
||||
+ return BIT(offset + offset / 3);
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+mt7530_gpio_get(struct gpio_chip *gc, unsigned int offset)
|
||||
+{
|
||||
+ struct mt7530_priv *priv = gpiochip_get_data(gc);
|
||||
+ u32 bit = mt7530_gpio_to_bit(offset);
|
||||
+
|
||||
+ return !!(mt7530_read(priv, MT7530_LED_GPIO_DATA) & bit);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+mt7530_gpio_set(struct gpio_chip *gc, unsigned int offset, int value)
|
||||
+{
|
||||
+ struct mt7530_priv *priv = gpiochip_get_data(gc);
|
||||
+ u32 bit = mt7530_gpio_to_bit(offset);
|
||||
+
|
||||
+ if (value)
|
||||
+ mt7530_set(priv, MT7530_LED_GPIO_DATA, bit);
|
||||
+ else
|
||||
+ mt7530_clear(priv, MT7530_LED_GPIO_DATA, bit);
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+mt7530_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
|
||||
+{
|
||||
+ struct mt7530_priv *priv = gpiochip_get_data(gc);
|
||||
+ u32 bit = mt7530_gpio_to_bit(offset);
|
||||
+
|
||||
+ return (mt7530_read(priv, MT7530_LED_GPIO_DIR) & bit) ?
|
||||
+ GPIO_LINE_DIRECTION_OUT : GPIO_LINE_DIRECTION_IN;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+mt7530_gpio_direction_input(struct gpio_chip *gc, unsigned int offset)
|
||||
+{
|
||||
+ struct mt7530_priv *priv = gpiochip_get_data(gc);
|
||||
+ u32 bit = mt7530_gpio_to_bit(offset);
|
||||
+
|
||||
+ mt7530_clear(priv, MT7530_LED_GPIO_OE, bit);
|
||||
+ mt7530_clear(priv, MT7530_LED_GPIO_DIR, bit);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+mt7530_gpio_direction_output(struct gpio_chip *gc, unsigned int offset, int value)
|
||||
+{
|
||||
+ struct mt7530_priv *priv = gpiochip_get_data(gc);
|
||||
+ u32 bit = mt7530_gpio_to_bit(offset);
|
||||
+
|
||||
+ mt7530_set(priv, MT7530_LED_GPIO_DIR, bit);
|
||||
+
|
||||
+ if (value)
|
||||
+ mt7530_set(priv, MT7530_LED_GPIO_DATA, bit);
|
||||
+ else
|
||||
+ mt7530_clear(priv, MT7530_LED_GPIO_DATA, bit);
|
||||
+
|
||||
+ mt7530_set(priv, MT7530_LED_GPIO_OE, bit);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+mt7530_setup_gpio(struct mt7530_priv *priv)
|
||||
+{
|
||||
+ struct device *dev = priv->dev;
|
||||
+ struct gpio_chip *gc;
|
||||
+
|
||||
+ gc = devm_kzalloc(dev, sizeof(*gc), GFP_KERNEL);
|
||||
+ if (!gc)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ mt7530_write(priv, MT7530_LED_GPIO_OE, 0);
|
||||
+ mt7530_write(priv, MT7530_LED_GPIO_DIR, 0);
|
||||
+ mt7530_write(priv, MT7530_LED_IO_MODE, 0);
|
||||
+
|
||||
+ gc->label = "mt7530";
|
||||
+ gc->parent = dev;
|
||||
+ gc->owner = THIS_MODULE;
|
||||
+ gc->get_direction = mt7530_gpio_get_direction;
|
||||
+ gc->direction_input = mt7530_gpio_direction_input;
|
||||
+ gc->direction_output = mt7530_gpio_direction_output;
|
||||
+ gc->get = mt7530_gpio_get;
|
||||
+ gc->set = mt7530_gpio_set;
|
||||
+ gc->base = -1;
|
||||
+ gc->ngpio = 15;
|
||||
+ gc->can_sleep = true;
|
||||
+
|
||||
+ return devm_gpiochip_add_data(dev, gc, priv);
|
||||
+}
|
||||
+
|
||||
static int
|
||||
mt7530_setup(struct dsa_switch *ds)
|
||||
{
|
||||
@@ -1675,6 +1779,12 @@ mt7530_setup(struct dsa_switch *ds)
|
||||
}
|
||||
}
|
||||
|
||||
+ if (of_property_read_bool(priv->dev->of_node, "gpio-controller")) {
|
||||
+ ret = mt7530_setup_gpio(priv);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
mt7530_setup_port5(ds, interface);
|
||||
|
||||
/* Flush the FDB table */
|
||||
--- a/drivers/net/dsa/mt7530.h
|
||||
+++ b/drivers/net/dsa/mt7530.h
|
||||
@@ -529,6 +529,26 @@ enum mt7531_clk_skew {
|
||||
#define MT7531_GPIO12_RG_RXD3_MASK GENMASK(19, 16)
|
||||
#define MT7531_EXT_P_MDIO_12 (2 << 16)
|
||||
|
||||
+/* Registers for LED GPIO control (MT7530 only)
|
||||
+ * All registers follow this pattern:
|
||||
+ * [ 2: 0] port 0
|
||||
+ * [ 6: 4] port 1
|
||||
+ * [10: 8] port 2
|
||||
+ * [14:12] port 3
|
||||
+ * [18:16] port 4
|
||||
+ */
|
||||
+
|
||||
+/* LED enable, 0: Disable, 1: Enable (Default) */
|
||||
+#define MT7530_LED_EN 0x7d00
|
||||
+/* LED mode, 0: GPIO mode, 1: PHY mode (Default) */
|
||||
+#define MT7530_LED_IO_MODE 0x7d04
|
||||
+/* GPIO direction, 0: Input, 1: Output */
|
||||
+#define MT7530_LED_GPIO_DIR 0x7d10
|
||||
+/* GPIO output enable, 0: Disable, 1: Enable */
|
||||
+#define MT7530_LED_GPIO_OE 0x7d14
|
||||
+/* GPIO value, 0: Low, 1: High */
|
||||
+#define MT7530_LED_GPIO_DATA 0x7d18
|
||||
+
|
||||
#define MT7530_CREV 0x7ffc
|
||||
#define CHIP_NAME_SHIFT 16
|
||||
#define MT7530_ID 0x7530
|
@ -17,7 +17,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
|
||||
--- a/drivers/net/dsa/mt7530.c
|
||||
+++ b/drivers/net/dsa/mt7530.c
|
||||
@@ -2261,6 +2261,17 @@ static void mt753x_phylink_mac_link_up(s
|
||||
@@ -2371,6 +2371,17 @@ static void mt753x_phylink_mac_link_up(s
|
||||
mcr |= PMCR_RX_FC_EN;
|
||||
}
|
||||
|
||||
@ -35,7 +35,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
mt7530_set(priv, MT7530_PMCR_P(port), mcr);
|
||||
}
|
||||
|
||||
@@ -2491,6 +2502,36 @@ mt753x_phy_write(struct dsa_switch *ds,
|
||||
@@ -2601,6 +2612,36 @@ mt753x_phy_write(struct dsa_switch *ds,
|
||||
return priv->info->phy_write(ds, port, regnum, val);
|
||||
}
|
||||
|
||||
@ -72,7 +72,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
static const struct dsa_switch_ops mt7530_switch_ops = {
|
||||
.get_tag_protocol = mtk_get_tag_protocol,
|
||||
.setup = mt753x_setup,
|
||||
@@ -2519,6 +2560,8 @@ static const struct dsa_switch_ops mt753
|
||||
@@ -2629,6 +2670,8 @@ static const struct dsa_switch_ops mt753
|
||||
.phylink_mac_an_restart = mt753x_phylink_mac_an_restart,
|
||||
.phylink_mac_link_down = mt753x_phylink_mac_link_down,
|
||||
.phylink_mac_link_up = mt753x_phylink_mac_link_up,
|
@ -272,7 +272,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
void __iomem *descmap;
|
||||
const struct of_device_id *of_id = NULL;
|
||||
|
||||
@@ -1525,10 +1524,8 @@ static int altera_tse_probe(struct platf
|
||||
@@ -1528,10 +1527,8 @@ static int altera_tse_probe(struct platf
|
||||
priv->rx_dma_buf_sz = ALTERA_RXDMABUFFER_SIZE;
|
||||
|
||||
/* get default MAC address from device tree */
|
||||
@ -319,7 +319,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
int tx_size, err, i;
|
||||
struct ag71xx *ag;
|
||||
|
||||
@@ -1957,10 +1956,8 @@ static int ag71xx_probe(struct platform_
|
||||
@@ -1952,10 +1951,8 @@ static int ag71xx_probe(struct platform_
|
||||
ag->stop_desc->ctrl = 0;
|
||||
ag->stop_desc->next = (u32)ag->stop_desc_dma;
|
||||
|
||||
@ -334,7 +334,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
}
|
||||
--- a/drivers/net/ethernet/broadcom/bcmsysport.c
|
||||
+++ b/drivers/net/ethernet/broadcom/bcmsysport.c
|
||||
@@ -2465,7 +2465,6 @@ static int bcm_sysport_probe(struct plat
|
||||
@@ -2468,7 +2468,6 @@ static int bcm_sysport_probe(struct plat
|
||||
struct bcm_sysport_priv *priv;
|
||||
struct device_node *dn;
|
||||
struct net_device *dev;
|
||||
@ -342,7 +342,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
u32 txq, rxq;
|
||||
int ret;
|
||||
|
||||
@@ -2560,12 +2559,10 @@ static int bcm_sysport_probe(struct plat
|
||||
@@ -2563,12 +2562,10 @@ static int bcm_sysport_probe(struct plat
|
||||
}
|
||||
|
||||
/* Initialize netdevice members */
|
||||
@ -423,7 +423,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
if (bgmac->irq < 0)
|
||||
--- a/drivers/net/ethernet/cadence/macb_main.c
|
||||
+++ b/drivers/net/ethernet/cadence/macb_main.c
|
||||
@@ -4456,7 +4456,6 @@ static int macb_probe(struct platform_de
|
||||
@@ -4479,7 +4479,6 @@ static int macb_probe(struct platform_de
|
||||
struct net_device *dev;
|
||||
struct resource *regs;
|
||||
void __iomem *mem;
|
||||
@ -431,7 +431,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
struct macb *bp;
|
||||
int err, val;
|
||||
|
||||
@@ -4569,15 +4568,11 @@ static int macb_probe(struct platform_de
|
||||
@@ -4592,15 +4591,11 @@ static int macb_probe(struct platform_de
|
||||
if (bp->caps & MACB_CAPS_NEEDS_RSTONUBR)
|
||||
bp->rx_intr_mask |= MACB_BIT(RXUBR);
|
||||
|
||||
@ -607,7 +607,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
/*
|
||||
--- a/drivers/net/ethernet/freescale/fman/mac.c
|
||||
+++ b/drivers/net/ethernet/freescale/fman/mac.c
|
||||
@@ -605,7 +605,6 @@ static int mac_probe(struct platform_dev
|
||||
@@ -616,7 +616,6 @@ static int mac_probe(struct platform_dev
|
||||
struct platform_device *of_dev;
|
||||
struct resource res;
|
||||
struct mac_priv_s *priv;
|
||||
@ -615,7 +615,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
u32 val;
|
||||
u8 fman_id;
|
||||
phy_interface_t phy_if;
|
||||
@@ -723,11 +722,9 @@ static int mac_probe(struct platform_dev
|
||||
@@ -734,11 +733,9 @@ static int mac_probe(struct platform_dev
|
||||
priv->cell_index = (u8)val;
|
||||
|
||||
/* Get the MAC address */
|
||||
@ -629,7 +629,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
|
||||
/* Get the port handles */
|
||||
nph = of_count_phandle_with_args(mac_node, "fsl,fman-ports", NULL);
|
||||
@@ -853,7 +850,7 @@ static int mac_probe(struct platform_dev
|
||||
@@ -864,7 +861,7 @@ static int mac_probe(struct platform_dev
|
||||
if (err < 0)
|
||||
dev_err(dev, "fman_set_mac_active_pause() = %d\n", err);
|
||||
|
||||
@ -819,7 +819,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
if (is_valid_ether_addr(hw_mac_addr)) {
|
||||
--- a/drivers/net/ethernet/marvell/prestera/prestera_main.c
|
||||
+++ b/drivers/net/ethernet/marvell/prestera/prestera_main.c
|
||||
@@ -462,20 +462,17 @@ static int prestera_switch_set_base_mac_
|
||||
@@ -466,20 +466,17 @@ static int prestera_switch_set_base_mac_
|
||||
{
|
||||
struct device_node *base_mac_np;
|
||||
struct device_node *np;
|
||||
@ -933,7 +933,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
}
|
||||
--- a/drivers/net/ethernet/microchip/lan743x_main.c
|
||||
+++ b/drivers/net/ethernet/microchip/lan743x_main.c
|
||||
@@ -2837,7 +2837,6 @@ static int lan743x_pcidev_probe(struct p
|
||||
@@ -2831,7 +2831,6 @@ static int lan743x_pcidev_probe(struct p
|
||||
{
|
||||
struct lan743x_adapter *adapter = NULL;
|
||||
struct net_device *netdev = NULL;
|
||||
@ -941,7 +941,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
int ret = -ENODEV;
|
||||
|
||||
netdev = devm_alloc_etherdev(&pdev->dev,
|
||||
@@ -2854,9 +2853,7 @@ static int lan743x_pcidev_probe(struct p
|
||||
@@ -2848,9 +2847,7 @@ static int lan743x_pcidev_probe(struct p
|
||||
NETIF_MSG_IFDOWN | NETIF_MSG_TX_QUEUED;
|
||||
netdev->max_mtu = LAN743X_MAX_FRAME_SIZE;
|
||||
|
||||
@ -1360,7 +1360,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
int irq;
|
||||
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
|
||||
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
|
||||
@@ -4957,7 +4957,7 @@ int stmmac_dvr_probe(struct device *devi
|
||||
@@ -4988,7 +4988,7 @@ int stmmac_dvr_probe(struct device *devi
|
||||
priv->wol_irq = res->wol_irq;
|
||||
priv->lpi_irq = res->lpi_irq;
|
||||
|
||||
@ -1371,7 +1371,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
dev_set_drvdata(device, priv->dev);
|
||||
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
|
||||
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
|
||||
@@ -394,7 +394,7 @@ static int stmmac_of_get_mac_mode(struct
|
||||
@@ -395,7 +395,7 @@ static int stmmac_of_get_mac_mode(struct
|
||||
* set some private fields that will be used by the main at runtime.
|
||||
*/
|
||||
struct plat_stmmacenet_data *
|
||||
@ -1380,7 +1380,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct plat_stmmacenet_data *plat;
|
||||
@@ -406,12 +406,12 @@ stmmac_probe_config_dt(struct platform_d
|
||||
@@ -407,12 +407,12 @@ stmmac_probe_config_dt(struct platform_d
|
||||
if (!plat)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
@ -1398,7 +1398,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
}
|
||||
|
||||
phy_mode = device_get_phy_mode(&pdev->dev);
|
||||
@@ -643,7 +643,7 @@ void stmmac_remove_config_dt(struct plat
|
||||
@@ -644,7 +644,7 @@ void stmmac_remove_config_dt(struct plat
|
||||
}
|
||||
#else
|
||||
struct plat_stmmacenet_data *
|
||||
@ -1595,7 +1595,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
__be32 *p;
|
||||
bool little_endian;
|
||||
int rc = 0;
|
||||
@@ -1561,8 +1561,8 @@ static int temac_probe(struct platform_d
|
||||
@@ -1563,8 +1563,8 @@ static int temac_probe(struct platform_d
|
||||
|
||||
if (temac_np) {
|
||||
/* Retrieve the MAC address */
|
||||
@ -1608,7 +1608,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
}
|
||||
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
|
||||
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
|
||||
@@ -1803,8 +1803,8 @@ static int axienet_probe(struct platform
|
||||
@@ -1843,8 +1843,8 @@ static int axienet_probe(struct platform
|
||||
struct device_node *np;
|
||||
struct axienet_local *lp;
|
||||
struct net_device *ndev;
|
||||
@ -1618,7 +1618,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
int addr_width = 32;
|
||||
u32 value;
|
||||
|
||||
@@ -2004,13 +2004,14 @@ static int axienet_probe(struct platform
|
||||
@@ -2044,13 +2044,14 @@ static int axienet_probe(struct platform
|
||||
dev_info(&pdev->dev, "Ethernet core IRQ not defined\n");
|
||||
|
||||
/* Retrieve the MAC address */
|
@ -0,0 +1,42 @@
|
||||
From 029497e66bdc762e001880e4c85a91f35a54b1e2 Mon Sep 17 00:00:00 2001
|
||||
From: Christian Lamparter <chunkeey@gmail.com>
|
||||
Date: Sun, 19 Sep 2021 13:57:25 +0200
|
||||
Subject: [PATCH] net: bgmac-bcma: handle deferred probe error due to
|
||||
mac-address
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Due to the inclusion of nvmem handling into the mac-address getter
|
||||
function of_get_mac_address() by
|
||||
commit d01f449c008a ("of_net: add NVMEM support to of_get_mac_address")
|
||||
it is now possible to get a -EPROBE_DEFER return code. Which did cause
|
||||
bgmac to assign a random ethernet address.
|
||||
|
||||
This exact issue happened on my Meraki MR32. The nvmem provider is
|
||||
an EEPROM (at24c64) which gets instantiated once the module
|
||||
driver is loaded... This happens once the filesystem becomes available.
|
||||
|
||||
With this patch, bgmac_probe() will propagate the -EPROBE_DEFER error.
|
||||
Then the driver subsystem will reschedule the probe at a later time.
|
||||
|
||||
Cc: Petr Štetiar <ynezz@true.cz>
|
||||
Cc: Michael Walle <michael@walle.cc>
|
||||
Fixes: d01f449c008a ("of_net: add NVMEM support to of_get_mac_address")
|
||||
Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/broadcom/bgmac-bcma.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
--- a/drivers/net/ethernet/broadcom/bgmac-bcma.c
|
||||
+++ b/drivers/net/ethernet/broadcom/bgmac-bcma.c
|
||||
@@ -129,6 +129,8 @@ static int bgmac_probe(struct bcma_devic
|
||||
bcma_set_drvdata(core, bgmac);
|
||||
|
||||
err = of_get_mac_address(bgmac->dev->of_node, bgmac->net_dev->dev_addr);
|
||||
+ if (err == -EPROBE_DEFER)
|
||||
+ return err;
|
||||
|
||||
/* If no MAC address assigned via device tree, check SPROM */
|
||||
if (err) {
|
@ -0,0 +1,36 @@
|
||||
From 763716a55cb1f480ffe1a9702e6b5d9ea1a80a24 Mon Sep 17 00:00:00 2001
|
||||
From: Matthew Hagan <mnhagan88@gmail.com>
|
||||
Date: Sat, 25 Sep 2021 11:36:27 +0000
|
||||
Subject: [PATCH] net: bgmac-platform: handle mac-address deferral
|
||||
|
||||
This patch is a replication of Christian Lamparter's "net: bgmac-bcma:
|
||||
handle deferred probe error due to mac-address" patch for the
|
||||
bgmac-platform driver [1].
|
||||
|
||||
As is the case with the bgmac-bcma driver, this change is to cover the
|
||||
scenario where the MAC address cannot yet be discovered due to reliance
|
||||
on an nvmem provider which is yet to be instantiated, resulting in a
|
||||
random address being assigned that has to be manually overridden.
|
||||
|
||||
[1] https://lore.kernel.org/netdev/20210919115725.29064-1-chunkeey@gmail.com
|
||||
|
||||
Signed-off-by: Matthew Hagan <mnhagan88@gmail.com>
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/broadcom/bgmac-platform.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
--- a/drivers/net/ethernet/broadcom/bgmac-platform.c
|
||||
+++ b/drivers/net/ethernet/broadcom/bgmac-platform.c
|
||||
@@ -193,6 +193,9 @@ static int bgmac_probe(struct platform_d
|
||||
bgmac->dma_dev = &pdev->dev;
|
||||
|
||||
ret = of_get_mac_address(np, bgmac->net_dev->dev_addr);
|
||||
+ if (ret == -EPROBE_DEFER)
|
||||
+ return ret;
|
||||
+
|
||||
if (ret)
|
||||
dev_warn(&pdev->dev,
|
||||
"MAC address not present in device tree\n");
|
@ -0,0 +1,84 @@
|
||||
From b5375509184dc23d2b7fa0c5ed8763899ccc9674 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
|
||||
Date: Sat, 2 Oct 2021 19:58:11 +0200
|
||||
Subject: [PATCH] net: bgmac: improve handling PHY
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
1. Use info from DT if available
|
||||
|
||||
It allows describing for example a fixed link. It's more accurate than
|
||||
just guessing there may be one (depending on a chipset).
|
||||
|
||||
2. Verify PHY ID before trying to connect PHY
|
||||
|
||||
PHY addr 0x1e (30) is special in Broadcom routers and means a switch
|
||||
connected as MDIO devices instead of a real PHY. Don't try connecting to
|
||||
it.
|
||||
|
||||
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/broadcom/bgmac-bcma.c | 33 ++++++++++++++--------
|
||||
1 file changed, 21 insertions(+), 12 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/broadcom/bgmac-bcma.c
|
||||
+++ b/drivers/net/ethernet/broadcom/bgmac-bcma.c
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <linux/bcma/bcma.h>
|
||||
#include <linux/brcmphy.h>
|
||||
#include <linux/etherdevice.h>
|
||||
+#include <linux/of_mdio.h>
|
||||
#include <linux/of_net.h>
|
||||
#include "bgmac.h"
|
||||
|
||||
@@ -86,17 +87,28 @@ static int bcma_phy_connect(struct bgmac
|
||||
struct phy_device *phy_dev;
|
||||
char bus_id[MII_BUS_ID_SIZE + 3];
|
||||
|
||||
+ /* DT info should be the most accurate */
|
||||
+ phy_dev = of_phy_get_and_connect(bgmac->net_dev, bgmac->dev->of_node,
|
||||
+ bgmac_adjust_link);
|
||||
+ if (phy_dev)
|
||||
+ return 0;
|
||||
+
|
||||
/* Connect to the PHY */
|
||||
- snprintf(bus_id, sizeof(bus_id), PHY_ID_FMT, bgmac->mii_bus->id,
|
||||
- bgmac->phyaddr);
|
||||
- phy_dev = phy_connect(bgmac->net_dev, bus_id, bgmac_adjust_link,
|
||||
- PHY_INTERFACE_MODE_MII);
|
||||
- if (IS_ERR(phy_dev)) {
|
||||
- dev_err(bgmac->dev, "PHY connection failed\n");
|
||||
- return PTR_ERR(phy_dev);
|
||||
+ if (bgmac->mii_bus && bgmac->phyaddr != BGMAC_PHY_NOREGS) {
|
||||
+ snprintf(bus_id, sizeof(bus_id), PHY_ID_FMT, bgmac->mii_bus->id,
|
||||
+ bgmac->phyaddr);
|
||||
+ phy_dev = phy_connect(bgmac->net_dev, bus_id, bgmac_adjust_link,
|
||||
+ PHY_INTERFACE_MODE_MII);
|
||||
+ if (IS_ERR(phy_dev)) {
|
||||
+ dev_err(bgmac->dev, "PHY connection failed\n");
|
||||
+ return PTR_ERR(phy_dev);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
- return 0;
|
||||
+ /* Assume a fixed link to the switch port */
|
||||
+ return bgmac_phy_connect_direct(bgmac);
|
||||
}
|
||||
|
||||
static const struct bcma_device_id bgmac_bcma_tbl[] = {
|
||||
@@ -297,10 +309,7 @@ static int bgmac_probe(struct bcma_devic
|
||||
bgmac->cco_ctl_maskset = bcma_bgmac_cco_ctl_maskset;
|
||||
bgmac->get_bus_clock = bcma_bgmac_get_bus_clock;
|
||||
bgmac->cmn_maskset32 = bcma_bgmac_cmn_maskset32;
|
||||
- if (bgmac->mii_bus)
|
||||
- bgmac->phy_connect = bcma_phy_connect;
|
||||
- else
|
||||
- bgmac->phy_connect = bgmac_phy_connect_direct;
|
||||
+ bgmac->phy_connect = bcma_phy_connect;
|
||||
|
||||
err = bgmac_enet_probe(bgmac);
|
||||
if (err)
|
@ -0,0 +1,54 @@
|
||||
From 45c9d966688e7fad7f24bfc450547d91e4304d0b Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
|
||||
Date: Sat, 2 Oct 2021 19:58:12 +0200
|
||||
Subject: [PATCH] net: bgmac: support MDIO described in DT
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Check ethernet controller DT node for "mdio" subnode and use it with
|
||||
of_mdiobus_register() when present. That allows specifying MDIO and its
|
||||
PHY devices in a standard DT based way.
|
||||
|
||||
This is required for BCM53573 SoC support. That family is sometimes
|
||||
called Northstar (by marketing?) but is quite different from it. It uses
|
||||
different CPU(s) and many different hw blocks.
|
||||
|
||||
One of shared blocks in BCM53573 is Ethernet controller. Switch however
|
||||
is not SRAB accessible (as it Northstar) but is MDIO attached.
|
||||
|
||||
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/broadcom/bgmac-bcma-mdio.c | 6 +++++-
|
||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/ethernet/broadcom/bgmac-bcma-mdio.c
|
||||
+++ b/drivers/net/ethernet/broadcom/bgmac-bcma-mdio.c
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include <linux/bcma/bcma.h>
|
||||
#include <linux/brcmphy.h>
|
||||
+#include <linux/of_mdio.h>
|
||||
#include "bgmac.h"
|
||||
|
||||
static bool bcma_mdio_wait_value(struct bcma_device *core, u16 reg, u32 mask,
|
||||
@@ -211,6 +212,7 @@ struct mii_bus *bcma_mdio_mii_register(s
|
||||
{
|
||||
struct bcma_device *core = bgmac->bcma.core;
|
||||
struct mii_bus *mii_bus;
|
||||
+ struct device_node *np;
|
||||
int err;
|
||||
|
||||
mii_bus = mdiobus_alloc();
|
||||
@@ -229,7 +231,9 @@ struct mii_bus *bcma_mdio_mii_register(s
|
||||
mii_bus->parent = &core->dev;
|
||||
mii_bus->phy_mask = ~(1 << bgmac->phyaddr);
|
||||
|
||||
- err = mdiobus_register(mii_bus);
|
||||
+ np = of_get_child_by_name(core->dev.of_node, "mdio");
|
||||
+
|
||||
+ err = of_mdiobus_register(mii_bus, np);
|
||||
if (err) {
|
||||
dev_err(&core->dev, "Registration of mii bus failed\n");
|
||||
goto err_free_bus;
|
@ -0,0 +1,35 @@
|
||||
From 5d9e068402dcf7354cc8ee66c2152845306d2ccb Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Fri, 14 May 2021 22:59:51 +0200
|
||||
Subject: [PATCH] net: dsa: qca8k: change simple print to dev variant
|
||||
|
||||
Change pr_err and pr_warn to dev variant.
|
||||
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/qca8k.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/qca8k.c
|
||||
+++ b/drivers/net/dsa/qca8k.c
|
||||
@@ -701,7 +701,7 @@ qca8k_setup(struct dsa_switch *ds)
|
||||
|
||||
/* Make sure that port 0 is the cpu port */
|
||||
if (!dsa_is_cpu_port(ds, 0)) {
|
||||
- pr_err("port 0 is not the CPU port\n");
|
||||
+ dev_err(priv->dev, "port 0 is not the CPU port");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -711,7 +711,7 @@ qca8k_setup(struct dsa_switch *ds)
|
||||
priv->regmap = devm_regmap_init(ds->dev, NULL, priv,
|
||||
&qca8k_regmap_config);
|
||||
if (IS_ERR(priv->regmap))
|
||||
- pr_warn("regmap initialization failed");
|
||||
+ dev_warn(priv->dev, "regmap initialization failed");
|
||||
|
||||
ret = qca8k_setup_mdio_bus(priv);
|
||||
if (ret)
|
@ -0,0 +1,61 @@
|
||||
From 2ad255f2faaffb3af786031fba2e7955454b558a Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Fri, 14 May 2021 22:59:52 +0200
|
||||
Subject: [PATCH] net: dsa: qca8k: use iopoll macro for qca8k_busy_wait
|
||||
|
||||
Use iopoll macro instead of while loop.
|
||||
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/qca8k.c | 23 +++++++++++------------
|
||||
drivers/net/dsa/qca8k.h | 2 ++
|
||||
2 files changed, 13 insertions(+), 12 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/qca8k.c
|
||||
+++ b/drivers/net/dsa/qca8k.c
|
||||
@@ -262,21 +262,20 @@ static struct regmap_config qca8k_regmap
|
||||
static int
|
||||
qca8k_busy_wait(struct qca8k_priv *priv, u32 reg, u32 mask)
|
||||
{
|
||||
- unsigned long timeout;
|
||||
+ u32 val;
|
||||
+ int ret;
|
||||
|
||||
- timeout = jiffies + msecs_to_jiffies(20);
|
||||
+ ret = read_poll_timeout(qca8k_read, val, !(val & mask),
|
||||
+ 0, QCA8K_BUSY_WAIT_TIMEOUT * USEC_PER_MSEC, false,
|
||||
+ priv, reg);
|
||||
|
||||
- /* loop until the busy flag has cleared */
|
||||
- do {
|
||||
- u32 val = qca8k_read(priv, reg);
|
||||
- int busy = val & mask;
|
||||
+ /* Check if qca8k_read has failed for a different reason
|
||||
+ * before returning -ETIMEDOUT
|
||||
+ */
|
||||
+ if (ret < 0 && val < 0)
|
||||
+ return val;
|
||||
|
||||
- if (!busy)
|
||||
- break;
|
||||
- cond_resched();
|
||||
- } while (!time_after_eq(jiffies, timeout));
|
||||
-
|
||||
- return time_after_eq(jiffies, timeout);
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
--- a/drivers/net/dsa/qca8k.h
|
||||
+++ b/drivers/net/dsa/qca8k.h
|
||||
@@ -18,6 +18,8 @@
|
||||
#define PHY_ID_QCA8337 0x004dd036
|
||||
#define QCA8K_ID_QCA8337 0x13
|
||||
|
||||
+#define QCA8K_BUSY_WAIT_TIMEOUT 20
|
||||
+
|
||||
#define QCA8K_NUM_FDB_RECORDS 2048
|
||||
|
||||
#define QCA8K_CPU_PORT 0
|
@ -0,0 +1,86 @@
|
||||
From 504bf65931824eda83494e5b5d75686e27ace03e Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Fri, 14 May 2021 22:59:53 +0200
|
||||
Subject: [PATCH] net: dsa: qca8k: improve qca8k read/write/rmw bus access
|
||||
|
||||
Put bus in local variable to improve faster access to the mdio bus.
|
||||
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/qca8k.c | 29 ++++++++++++++++-------------
|
||||
1 file changed, 16 insertions(+), 13 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/qca8k.c
|
||||
+++ b/drivers/net/dsa/qca8k.c
|
||||
@@ -142,17 +142,18 @@ qca8k_set_page(struct mii_bus *bus, u16
|
||||
static u32
|
||||
qca8k_read(struct qca8k_priv *priv, u32 reg)
|
||||
{
|
||||
+ struct mii_bus *bus = priv->bus;
|
||||
u16 r1, r2, page;
|
||||
u32 val;
|
||||
|
||||
qca8k_split_addr(reg, &r1, &r2, &page);
|
||||
|
||||
- mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED);
|
||||
+ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
|
||||
|
||||
- qca8k_set_page(priv->bus, page);
|
||||
- val = qca8k_mii_read32(priv->bus, 0x10 | r2, r1);
|
||||
+ qca8k_set_page(bus, page);
|
||||
+ val = qca8k_mii_read32(bus, 0x10 | r2, r1);
|
||||
|
||||
- mutex_unlock(&priv->bus->mdio_lock);
|
||||
+ mutex_unlock(&bus->mdio_lock);
|
||||
|
||||
return val;
|
||||
}
|
||||
@@ -160,35 +161,37 @@ qca8k_read(struct qca8k_priv *priv, u32
|
||||
static void
|
||||
qca8k_write(struct qca8k_priv *priv, u32 reg, u32 val)
|
||||
{
|
||||
+ struct mii_bus *bus = priv->bus;
|
||||
u16 r1, r2, page;
|
||||
|
||||
qca8k_split_addr(reg, &r1, &r2, &page);
|
||||
|
||||
- mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED);
|
||||
+ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
|
||||
|
||||
- qca8k_set_page(priv->bus, page);
|
||||
- qca8k_mii_write32(priv->bus, 0x10 | r2, r1, val);
|
||||
+ qca8k_set_page(bus, page);
|
||||
+ qca8k_mii_write32(bus, 0x10 | r2, r1, val);
|
||||
|
||||
- mutex_unlock(&priv->bus->mdio_lock);
|
||||
+ mutex_unlock(&bus->mdio_lock);
|
||||
}
|
||||
|
||||
static u32
|
||||
qca8k_rmw(struct qca8k_priv *priv, u32 reg, u32 mask, u32 val)
|
||||
{
|
||||
+ struct mii_bus *bus = priv->bus;
|
||||
u16 r1, r2, page;
|
||||
u32 ret;
|
||||
|
||||
qca8k_split_addr(reg, &r1, &r2, &page);
|
||||
|
||||
- mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED);
|
||||
+ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
|
||||
|
||||
- qca8k_set_page(priv->bus, page);
|
||||
- ret = qca8k_mii_read32(priv->bus, 0x10 | r2, r1);
|
||||
+ qca8k_set_page(bus, page);
|
||||
+ ret = qca8k_mii_read32(bus, 0x10 | r2, r1);
|
||||
ret &= ~mask;
|
||||
ret |= val;
|
||||
- qca8k_mii_write32(priv->bus, 0x10 | r2, r1, ret);
|
||||
+ qca8k_mii_write32(bus, 0x10 | r2, r1, ret);
|
||||
|
||||
- mutex_unlock(&priv->bus->mdio_lock);
|
||||
+ mutex_unlock(&bus->mdio_lock);
|
||||
|
||||
return ret;
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
From ba5707ec58cfb6853dff41c2aae72deb6a03d389 Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Fri, 14 May 2021 22:59:54 +0200
|
||||
Subject: [PATCH] net: dsa: qca8k: handle qca8k_set_page errors
|
||||
|
||||
With a remote possibility, the set_page function can fail. Since this is
|
||||
a critical part of the write/read qca8k regs, propagate the error and
|
||||
terminate any read/write operation.
|
||||
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/qca8k.c | 33 ++++++++++++++++++++++++++-------
|
||||
1 file changed, 26 insertions(+), 7 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/qca8k.c
|
||||
+++ b/drivers/net/dsa/qca8k.c
|
||||
@@ -127,16 +127,23 @@ qca8k_mii_write32(struct mii_bus *bus, i
|
||||
"failed to write qca8k 32bit register\n");
|
||||
}
|
||||
|
||||
-static void
|
||||
+static int
|
||||
qca8k_set_page(struct mii_bus *bus, u16 page)
|
||||
{
|
||||
+ int ret;
|
||||
+
|
||||
if (page == qca8k_current_page)
|
||||
- return;
|
||||
+ return 0;
|
||||
|
||||
- if (bus->write(bus, 0x18, 0, page) < 0)
|
||||
+ ret = bus->write(bus, 0x18, 0, page);
|
||||
+ if (ret < 0) {
|
||||
dev_err_ratelimited(&bus->dev,
|
||||
"failed to set qca8k page\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
qca8k_current_page = page;
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
static u32
|
||||
@@ -150,11 +157,14 @@ qca8k_read(struct qca8k_priv *priv, u32
|
||||
|
||||
mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
|
||||
|
||||
- qca8k_set_page(bus, page);
|
||||
+ val = qca8k_set_page(bus, page);
|
||||
+ if (val < 0)
|
||||
+ goto exit;
|
||||
+
|
||||
val = qca8k_mii_read32(bus, 0x10 | r2, r1);
|
||||
|
||||
+exit:
|
||||
mutex_unlock(&bus->mdio_lock);
|
||||
-
|
||||
return val;
|
||||
}
|
||||
|
||||
@@ -163,14 +173,19 @@ qca8k_write(struct qca8k_priv *priv, u32
|
||||
{
|
||||
struct mii_bus *bus = priv->bus;
|
||||
u16 r1, r2, page;
|
||||
+ int ret;
|
||||
|
||||
qca8k_split_addr(reg, &r1, &r2, &page);
|
||||
|
||||
mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
|
||||
|
||||
- qca8k_set_page(bus, page);
|
||||
+ ret = qca8k_set_page(bus, page);
|
||||
+ if (ret < 0)
|
||||
+ goto exit;
|
||||
+
|
||||
qca8k_mii_write32(bus, 0x10 | r2, r1, val);
|
||||
|
||||
+exit:
|
||||
mutex_unlock(&bus->mdio_lock);
|
||||
}
|
||||
|
||||
@@ -185,12 +200,16 @@ qca8k_rmw(struct qca8k_priv *priv, u32 r
|
||||
|
||||
mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
|
||||
|
||||
- qca8k_set_page(bus, page);
|
||||
+ ret = qca8k_set_page(bus, page);
|
||||
+ if (ret < 0)
|
||||
+ goto exit;
|
||||
+
|
||||
ret = qca8k_mii_read32(bus, 0x10 | r2, r1);
|
||||
ret &= ~mask;
|
||||
ret |= val;
|
||||
qca8k_mii_write32(bus, 0x10 | r2, r1, ret);
|
||||
|
||||
+exit:
|
||||
mutex_unlock(&bus->mdio_lock);
|
||||
|
||||
return ret;
|
@ -0,0 +1,207 @@
|
||||
From 028f5f8ef44fcf87a456772cbb9f0d90a0a22884 Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Fri, 14 May 2021 22:59:55 +0200
|
||||
Subject: [PATCH] net: dsa: qca8k: handle error with qca8k_read operation
|
||||
|
||||
qca8k_read can fail. Rework any user to handle error values and
|
||||
correctly return.
|
||||
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/qca8k.c | 73 ++++++++++++++++++++++++++++++++---------
|
||||
1 file changed, 58 insertions(+), 15 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/qca8k.c
|
||||
+++ b/drivers/net/dsa/qca8k.c
|
||||
@@ -231,8 +231,13 @@ static int
|
||||
qca8k_regmap_read(void *ctx, uint32_t reg, uint32_t *val)
|
||||
{
|
||||
struct qca8k_priv *priv = (struct qca8k_priv *)ctx;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = qca8k_read(priv, reg);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
|
||||
- *val = qca8k_read(priv, reg);
|
||||
+ *val = ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -300,15 +305,20 @@ qca8k_busy_wait(struct qca8k_priv *priv,
|
||||
return ret;
|
||||
}
|
||||
|
||||
-static void
|
||||
+static int
|
||||
qca8k_fdb_read(struct qca8k_priv *priv, struct qca8k_fdb *fdb)
|
||||
{
|
||||
- u32 reg[4];
|
||||
+ u32 reg[4], val;
|
||||
int i;
|
||||
|
||||
/* load the ARL table into an array */
|
||||
- for (i = 0; i < 4; i++)
|
||||
- reg[i] = qca8k_read(priv, QCA8K_REG_ATU_DATA0 + (i * 4));
|
||||
+ for (i = 0; i < 4; i++) {
|
||||
+ val = qca8k_read(priv, QCA8K_REG_ATU_DATA0 + (i * 4));
|
||||
+ if (val < 0)
|
||||
+ return val;
|
||||
+
|
||||
+ reg[i] = val;
|
||||
+ }
|
||||
|
||||
/* vid - 83:72 */
|
||||
fdb->vid = (reg[2] >> QCA8K_ATU_VID_S) & QCA8K_ATU_VID_M;
|
||||
@@ -323,6 +333,8 @@ qca8k_fdb_read(struct qca8k_priv *priv,
|
||||
fdb->mac[3] = (reg[0] >> QCA8K_ATU_ADDR3_S) & 0xff;
|
||||
fdb->mac[4] = (reg[0] >> QCA8K_ATU_ADDR4_S) & 0xff;
|
||||
fdb->mac[5] = reg[0] & 0xff;
|
||||
+
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -374,6 +386,8 @@ qca8k_fdb_access(struct qca8k_priv *priv
|
||||
/* Check for table full violation when adding an entry */
|
||||
if (cmd == QCA8K_FDB_LOAD) {
|
||||
reg = qca8k_read(priv, QCA8K_REG_ATU_FUNC);
|
||||
+ if (reg < 0)
|
||||
+ return reg;
|
||||
if (reg & QCA8K_ATU_FUNC_FULL)
|
||||
return -1;
|
||||
}
|
||||
@@ -388,10 +402,10 @@ qca8k_fdb_next(struct qca8k_priv *priv,
|
||||
|
||||
qca8k_fdb_write(priv, fdb->vid, fdb->port_mask, fdb->mac, fdb->aging);
|
||||
ret = qca8k_fdb_access(priv, QCA8K_FDB_NEXT, port);
|
||||
- if (ret >= 0)
|
||||
- qca8k_fdb_read(priv, fdb);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
|
||||
- return ret;
|
||||
+ return qca8k_fdb_read(priv, fdb);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -449,6 +463,8 @@ qca8k_vlan_access(struct qca8k_priv *pri
|
||||
/* Check for table full violation when adding an entry */
|
||||
if (cmd == QCA8K_VLAN_LOAD) {
|
||||
reg = qca8k_read(priv, QCA8K_REG_VTU_FUNC1);
|
||||
+ if (reg < 0)
|
||||
+ return reg;
|
||||
if (reg & QCA8K_VTU_FUNC1_FULL)
|
||||
return -ENOMEM;
|
||||
}
|
||||
@@ -475,6 +491,8 @@ qca8k_vlan_add(struct qca8k_priv *priv,
|
||||
goto out;
|
||||
|
||||
reg = qca8k_read(priv, QCA8K_REG_VTU_FUNC0);
|
||||
+ if (reg < 0)
|
||||
+ return reg;
|
||||
reg |= QCA8K_VTU_FUNC0_VALID | QCA8K_VTU_FUNC0_IVL_EN;
|
||||
reg &= ~(QCA8K_VTU_FUNC0_EG_MODE_MASK << QCA8K_VTU_FUNC0_EG_MODE_S(port));
|
||||
if (untagged)
|
||||
@@ -506,6 +524,8 @@ qca8k_vlan_del(struct qca8k_priv *priv,
|
||||
goto out;
|
||||
|
||||
reg = qca8k_read(priv, QCA8K_REG_VTU_FUNC0);
|
||||
+ if (reg < 0)
|
||||
+ return reg;
|
||||
reg &= ~(3 << QCA8K_VTU_FUNC0_EG_MODE_S(port));
|
||||
reg |= QCA8K_VTU_FUNC0_EG_MODE_NOT <<
|
||||
QCA8K_VTU_FUNC0_EG_MODE_S(port);
|
||||
@@ -621,8 +641,11 @@ qca8k_mdio_read(struct qca8k_priv *priv,
|
||||
QCA8K_MDIO_MASTER_BUSY))
|
||||
return -ETIMEDOUT;
|
||||
|
||||
- val = (qca8k_read(priv, QCA8K_MDIO_MASTER_CTRL) &
|
||||
- QCA8K_MDIO_MASTER_DATA_MASK);
|
||||
+ val = qca8k_read(priv, QCA8K_MDIO_MASTER_CTRL);
|
||||
+ if (val < 0)
|
||||
+ return val;
|
||||
+
|
||||
+ val &= QCA8K_MDIO_MASTER_DATA_MASK;
|
||||
|
||||
return val;
|
||||
}
|
||||
@@ -978,6 +1001,8 @@ qca8k_phylink_mac_link_state(struct dsa_
|
||||
u32 reg;
|
||||
|
||||
reg = qca8k_read(priv, QCA8K_REG_PORT_STATUS(port));
|
||||
+ if (reg < 0)
|
||||
+ return reg;
|
||||
|
||||
state->link = !!(reg & QCA8K_PORT_STATUS_LINK_UP);
|
||||
state->an_complete = state->link;
|
||||
@@ -1078,18 +1103,26 @@ qca8k_get_ethtool_stats(struct dsa_switc
|
||||
{
|
||||
struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
|
||||
const struct qca8k_mib_desc *mib;
|
||||
- u32 reg, i;
|
||||
+ u32 reg, i, val;
|
||||
u64 hi;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ar8327_mib); i++) {
|
||||
mib = &ar8327_mib[i];
|
||||
reg = QCA8K_PORT_MIB_COUNTER(port) + mib->offset;
|
||||
|
||||
- data[i] = qca8k_read(priv, reg);
|
||||
+ val = qca8k_read(priv, reg);
|
||||
+ if (val < 0)
|
||||
+ continue;
|
||||
+
|
||||
if (mib->size == 2) {
|
||||
hi = qca8k_read(priv, reg + 4);
|
||||
- data[i] |= hi << 32;
|
||||
+ if (hi < 0)
|
||||
+ continue;
|
||||
}
|
||||
+
|
||||
+ data[i] = val;
|
||||
+ if (mib->size == 2)
|
||||
+ data[i] |= hi << 32;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1107,18 +1140,25 @@ qca8k_set_mac_eee(struct dsa_switch *ds,
|
||||
{
|
||||
struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
|
||||
u32 lpi_en = QCA8K_REG_EEE_CTRL_LPI_EN(port);
|
||||
+ int ret = 0;
|
||||
u32 reg;
|
||||
|
||||
mutex_lock(&priv->reg_mutex);
|
||||
reg = qca8k_read(priv, QCA8K_REG_EEE_CTRL);
|
||||
+ if (reg < 0) {
|
||||
+ ret = reg;
|
||||
+ goto exit;
|
||||
+ }
|
||||
+
|
||||
if (eee->eee_enabled)
|
||||
reg |= lpi_en;
|
||||
else
|
||||
reg &= ~lpi_en;
|
||||
qca8k_write(priv, QCA8K_REG_EEE_CTRL, reg);
|
||||
- mutex_unlock(&priv->reg_mutex);
|
||||
|
||||
- return 0;
|
||||
+exit:
|
||||
+ mutex_unlock(&priv->reg_mutex);
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -1456,6 +1496,9 @@ qca8k_sw_probe(struct mdio_device *mdiod
|
||||
|
||||
/* read the switches ID register */
|
||||
id = qca8k_read(priv, QCA8K_REG_MASK_CTRL);
|
||||
+ if (id < 0)
|
||||
+ return id;
|
||||
+
|
||||
id >>= QCA8K_MASK_CTRL_ID_S;
|
||||
id &= QCA8K_MASK_CTRL_ID_M;
|
||||
if (id != QCA8K_ID_QCA8337)
|
@ -0,0 +1,263 @@
|
||||
From d7805757c75c76e9518fc1023a29f0c4eed5b581 Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Fri, 14 May 2021 22:59:56 +0200
|
||||
Subject: [PATCH] net: dsa: qca8k: handle error with qca8k_write operation
|
||||
|
||||
qca8k_write can fail. Rework any user to handle error values and
|
||||
correctly return.
|
||||
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/qca8k.c | 102 ++++++++++++++++++++++++++--------------
|
||||
1 file changed, 67 insertions(+), 35 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/qca8k.c
|
||||
+++ b/drivers/net/dsa/qca8k.c
|
||||
@@ -168,7 +168,7 @@ exit:
|
||||
return val;
|
||||
}
|
||||
|
||||
-static void
|
||||
+static int
|
||||
qca8k_write(struct qca8k_priv *priv, u32 reg, u32 val)
|
||||
{
|
||||
struct mii_bus *bus = priv->bus;
|
||||
@@ -187,6 +187,7 @@ qca8k_write(struct qca8k_priv *priv, u32
|
||||
|
||||
exit:
|
||||
mutex_unlock(&bus->mdio_lock);
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
static u32
|
||||
@@ -247,9 +248,7 @@ qca8k_regmap_write(void *ctx, uint32_t r
|
||||
{
|
||||
struct qca8k_priv *priv = (struct qca8k_priv *)ctx;
|
||||
|
||||
- qca8k_write(priv, reg, val);
|
||||
-
|
||||
- return 0;
|
||||
+ return qca8k_write(priv, reg, val);
|
||||
}
|
||||
|
||||
static const struct regmap_range qca8k_readable_ranges[] = {
|
||||
@@ -367,6 +366,7 @@ static int
|
||||
qca8k_fdb_access(struct qca8k_priv *priv, enum qca8k_fdb_cmd cmd, int port)
|
||||
{
|
||||
u32 reg;
|
||||
+ int ret;
|
||||
|
||||
/* Set the command and FDB index */
|
||||
reg = QCA8K_ATU_FUNC_BUSY;
|
||||
@@ -377,7 +377,9 @@ qca8k_fdb_access(struct qca8k_priv *priv
|
||||
}
|
||||
|
||||
/* Write the function register triggering the table access */
|
||||
- qca8k_write(priv, QCA8K_REG_ATU_FUNC, reg);
|
||||
+ ret = qca8k_write(priv, QCA8K_REG_ATU_FUNC, reg);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
|
||||
/* wait for completion */
|
||||
if (qca8k_busy_wait(priv, QCA8K_REG_ATU_FUNC, QCA8K_ATU_FUNC_BUSY))
|
||||
@@ -447,6 +449,7 @@ static int
|
||||
qca8k_vlan_access(struct qca8k_priv *priv, enum qca8k_vlan_cmd cmd, u16 vid)
|
||||
{
|
||||
u32 reg;
|
||||
+ int ret;
|
||||
|
||||
/* Set the command and VLAN index */
|
||||
reg = QCA8K_VTU_FUNC1_BUSY;
|
||||
@@ -454,7 +457,9 @@ qca8k_vlan_access(struct qca8k_priv *pri
|
||||
reg |= vid << QCA8K_VTU_FUNC1_VID_S;
|
||||
|
||||
/* Write the function register triggering the table access */
|
||||
- qca8k_write(priv, QCA8K_REG_VTU_FUNC1, reg);
|
||||
+ ret = qca8k_write(priv, QCA8K_REG_VTU_FUNC1, reg);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
|
||||
/* wait for completion */
|
||||
if (qca8k_busy_wait(priv, QCA8K_REG_VTU_FUNC1, QCA8K_VTU_FUNC1_BUSY))
|
||||
@@ -502,7 +507,9 @@ qca8k_vlan_add(struct qca8k_priv *priv,
|
||||
reg |= QCA8K_VTU_FUNC0_EG_MODE_TAG <<
|
||||
QCA8K_VTU_FUNC0_EG_MODE_S(port);
|
||||
|
||||
- qca8k_write(priv, QCA8K_REG_VTU_FUNC0, reg);
|
||||
+ ret = qca8k_write(priv, QCA8K_REG_VTU_FUNC0, reg);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
ret = qca8k_vlan_access(priv, QCA8K_VLAN_LOAD, vid);
|
||||
|
||||
out:
|
||||
@@ -545,7 +552,9 @@ qca8k_vlan_del(struct qca8k_priv *priv,
|
||||
if (del) {
|
||||
ret = qca8k_vlan_access(priv, QCA8K_VLAN_PURGE, vid);
|
||||
} else {
|
||||
- qca8k_write(priv, QCA8K_REG_VTU_FUNC0, reg);
|
||||
+ ret = qca8k_write(priv, QCA8K_REG_VTU_FUNC0, reg);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
ret = qca8k_vlan_access(priv, QCA8K_VLAN_LOAD, vid);
|
||||
}
|
||||
|
||||
@@ -555,15 +564,20 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
-static void
|
||||
+static int
|
||||
qca8k_mib_init(struct qca8k_priv *priv)
|
||||
{
|
||||
+ int ret;
|
||||
+
|
||||
mutex_lock(&priv->reg_mutex);
|
||||
qca8k_reg_set(priv, QCA8K_REG_MIB, QCA8K_MIB_FLUSH | QCA8K_MIB_BUSY);
|
||||
qca8k_busy_wait(priv, QCA8K_REG_MIB, QCA8K_MIB_BUSY);
|
||||
qca8k_reg_set(priv, QCA8K_REG_MIB, QCA8K_MIB_CPU_KEEP);
|
||||
- qca8k_write(priv, QCA8K_REG_MODULE_EN, QCA8K_MODULE_EN_MIB);
|
||||
+
|
||||
+ ret = qca8k_write(priv, QCA8K_REG_MODULE_EN, QCA8K_MODULE_EN_MIB);
|
||||
+
|
||||
mutex_unlock(&priv->reg_mutex);
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -600,6 +614,7 @@ static int
|
||||
qca8k_mdio_write(struct qca8k_priv *priv, int port, u32 regnum, u16 data)
|
||||
{
|
||||
u32 phy, val;
|
||||
+ int ret;
|
||||
|
||||
if (regnum >= QCA8K_MDIO_MASTER_MAX_REG)
|
||||
return -EINVAL;
|
||||
@@ -613,7 +628,9 @@ qca8k_mdio_write(struct qca8k_priv *priv
|
||||
QCA8K_MDIO_MASTER_REG_ADDR(regnum) |
|
||||
QCA8K_MDIO_MASTER_DATA(data);
|
||||
|
||||
- qca8k_write(priv, QCA8K_MDIO_MASTER_CTRL, val);
|
||||
+ ret = qca8k_write(priv, QCA8K_MDIO_MASTER_CTRL, val);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
|
||||
return qca8k_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL,
|
||||
QCA8K_MDIO_MASTER_BUSY);
|
||||
@@ -623,6 +640,7 @@ static int
|
||||
qca8k_mdio_read(struct qca8k_priv *priv, int port, u32 regnum)
|
||||
{
|
||||
u32 phy, val;
|
||||
+ int ret;
|
||||
|
||||
if (regnum >= QCA8K_MDIO_MASTER_MAX_REG)
|
||||
return -EINVAL;
|
||||
@@ -635,7 +653,9 @@ qca8k_mdio_read(struct qca8k_priv *priv,
|
||||
QCA8K_MDIO_MASTER_READ | QCA8K_MDIO_MASTER_PHY_ADDR(phy) |
|
||||
QCA8K_MDIO_MASTER_REG_ADDR(regnum);
|
||||
|
||||
- qca8k_write(priv, QCA8K_MDIO_MASTER_CTRL, val);
|
||||
+ ret = qca8k_write(priv, QCA8K_MDIO_MASTER_CTRL, val);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
|
||||
if (qca8k_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL,
|
||||
QCA8K_MDIO_MASTER_BUSY))
|
||||
@@ -766,12 +786,18 @@ qca8k_setup(struct dsa_switch *ds)
|
||||
QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN);
|
||||
|
||||
/* Enable MIB counters */
|
||||
- qca8k_mib_init(priv);
|
||||
+ ret = qca8k_mib_init(priv);
|
||||
+ if (ret)
|
||||
+ dev_warn(priv->dev, "mib init failed");
|
||||
|
||||
/* Enable QCA header mode on the cpu port */
|
||||
- qca8k_write(priv, QCA8K_REG_PORT_HDR_CTRL(QCA8K_CPU_PORT),
|
||||
- QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_TX_S |
|
||||
- QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_RX_S);
|
||||
+ ret = qca8k_write(priv, QCA8K_REG_PORT_HDR_CTRL(QCA8K_CPU_PORT),
|
||||
+ QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_TX_S |
|
||||
+ QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_RX_S);
|
||||
+ if (ret) {
|
||||
+ dev_err(priv->dev, "failed enabling QCA header mode");
|
||||
+ return ret;
|
||||
+ }
|
||||
|
||||
/* Disable forwarding by default on all ports */
|
||||
for (i = 0; i < QCA8K_NUM_PORTS; i++)
|
||||
@@ -783,11 +809,13 @@ qca8k_setup(struct dsa_switch *ds)
|
||||
qca8k_port_set_status(priv, i, 0);
|
||||
|
||||
/* Forward all unknown frames to CPU port for Linux processing */
|
||||
- qca8k_write(priv, QCA8K_REG_GLOBAL_FW_CTRL1,
|
||||
- BIT(0) << QCA8K_GLOBAL_FW_CTRL1_IGMP_DP_S |
|
||||
- BIT(0) << QCA8K_GLOBAL_FW_CTRL1_BC_DP_S |
|
||||
- BIT(0) << QCA8K_GLOBAL_FW_CTRL1_MC_DP_S |
|
||||
- BIT(0) << QCA8K_GLOBAL_FW_CTRL1_UC_DP_S);
|
||||
+ ret = qca8k_write(priv, QCA8K_REG_GLOBAL_FW_CTRL1,
|
||||
+ BIT(0) << QCA8K_GLOBAL_FW_CTRL1_IGMP_DP_S |
|
||||
+ BIT(0) << QCA8K_GLOBAL_FW_CTRL1_BC_DP_S |
|
||||
+ BIT(0) << QCA8K_GLOBAL_FW_CTRL1_MC_DP_S |
|
||||
+ BIT(0) << QCA8K_GLOBAL_FW_CTRL1_UC_DP_S);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
|
||||
/* Setup connection between CPU port & user ports */
|
||||
for (i = 0; i < QCA8K_NUM_PORTS; i++) {
|
||||
@@ -815,16 +843,20 @@ qca8k_setup(struct dsa_switch *ds)
|
||||
qca8k_rmw(priv, QCA8K_EGRESS_VLAN(i),
|
||||
0xfff << shift,
|
||||
QCA8K_PORT_VID_DEF << shift);
|
||||
- qca8k_write(priv, QCA8K_REG_PORT_VLAN_CTRL0(i),
|
||||
- QCA8K_PORT_VLAN_CVID(QCA8K_PORT_VID_DEF) |
|
||||
- QCA8K_PORT_VLAN_SVID(QCA8K_PORT_VID_DEF));
|
||||
+ ret = qca8k_write(priv, QCA8K_REG_PORT_VLAN_CTRL0(i),
|
||||
+ QCA8K_PORT_VLAN_CVID(QCA8K_PORT_VID_DEF) |
|
||||
+ QCA8K_PORT_VLAN_SVID(QCA8K_PORT_VID_DEF));
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Setup our port MTUs to match power on defaults */
|
||||
for (i = 0; i < QCA8K_NUM_PORTS; i++)
|
||||
priv->port_mtu[i] = ETH_FRAME_LEN + ETH_FCS_LEN;
|
||||
- qca8k_write(priv, QCA8K_MAX_FRAME_SIZE, ETH_FRAME_LEN + ETH_FCS_LEN);
|
||||
+ ret = qca8k_write(priv, QCA8K_MAX_FRAME_SIZE, ETH_FRAME_LEN + ETH_FCS_LEN);
|
||||
+ if (ret)
|
||||
+ dev_warn(priv->dev, "failed setting MTU settings");
|
||||
|
||||
/* Flush the FDB table */
|
||||
qca8k_fdb_flush(priv);
|
||||
@@ -1140,8 +1172,8 @@ qca8k_set_mac_eee(struct dsa_switch *ds,
|
||||
{
|
||||
struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
|
||||
u32 lpi_en = QCA8K_REG_EEE_CTRL_LPI_EN(port);
|
||||
- int ret = 0;
|
||||
u32 reg;
|
||||
+ int ret;
|
||||
|
||||
mutex_lock(&priv->reg_mutex);
|
||||
reg = qca8k_read(priv, QCA8K_REG_EEE_CTRL);
|
||||
@@ -1154,7 +1186,7 @@ qca8k_set_mac_eee(struct dsa_switch *ds,
|
||||
reg |= lpi_en;
|
||||
else
|
||||
reg &= ~lpi_en;
|
||||
- qca8k_write(priv, QCA8K_REG_EEE_CTRL, reg);
|
||||
+ ret = qca8k_write(priv, QCA8K_REG_EEE_CTRL, reg);
|
||||
|
||||
exit:
|
||||
mutex_unlock(&priv->reg_mutex);
|
||||
@@ -1284,9 +1316,7 @@ qca8k_port_change_mtu(struct dsa_switch
|
||||
mtu = priv->port_mtu[i];
|
||||
|
||||
/* Include L2 header / FCS length */
|
||||
- qca8k_write(priv, QCA8K_MAX_FRAME_SIZE, mtu + ETH_HLEN + ETH_FCS_LEN);
|
||||
-
|
||||
- return 0;
|
||||
+ return qca8k_write(priv, QCA8K_MAX_FRAME_SIZE, mtu + ETH_HLEN + ETH_FCS_LEN);
|
||||
}
|
||||
|
||||
static int
|
@ -0,0 +1,226 @@
|
||||
From aaf421425cbdec4eb6fd75a29e65c2867b0b7bbd Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Fri, 14 May 2021 22:59:57 +0200
|
||||
Subject: [PATCH] net: dsa: qca8k: handle error with qca8k_rmw operation
|
||||
|
||||
qca8k_rmw can fail. Rework any user to handle error values and
|
||||
correctly return. Change qca8k_rmw to return the error code or 0 instead
|
||||
of the reg value. The reg returned by qca8k_rmw wasn't used anywhere,
|
||||
so this doesn't cause any functional change.
|
||||
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/qca8k.c | 133 +++++++++++++++++++++++++---------------
|
||||
1 file changed, 83 insertions(+), 50 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/qca8k.c
|
||||
+++ b/drivers/net/dsa/qca8k.c
|
||||
@@ -190,12 +190,13 @@ exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
-static u32
|
||||
-qca8k_rmw(struct qca8k_priv *priv, u32 reg, u32 mask, u32 val)
|
||||
+static int
|
||||
+qca8k_rmw(struct qca8k_priv *priv, u32 reg, u32 mask, u32 write_val)
|
||||
{
|
||||
struct mii_bus *bus = priv->bus;
|
||||
u16 r1, r2, page;
|
||||
- u32 ret;
|
||||
+ u32 val;
|
||||
+ int ret;
|
||||
|
||||
qca8k_split_addr(reg, &r1, &r2, &page);
|
||||
|
||||
@@ -205,10 +206,15 @@ qca8k_rmw(struct qca8k_priv *priv, u32 r
|
||||
if (ret < 0)
|
||||
goto exit;
|
||||
|
||||
- ret = qca8k_mii_read32(bus, 0x10 | r2, r1);
|
||||
- ret &= ~mask;
|
||||
- ret |= val;
|
||||
- qca8k_mii_write32(bus, 0x10 | r2, r1, ret);
|
||||
+ val = qca8k_mii_read32(bus, 0x10 | r2, r1);
|
||||
+ if (val < 0) {
|
||||
+ ret = val;
|
||||
+ goto exit;
|
||||
+ }
|
||||
+
|
||||
+ val &= ~mask;
|
||||
+ val |= write_val;
|
||||
+ qca8k_mii_write32(bus, 0x10 | r2, r1, val);
|
||||
|
||||
exit:
|
||||
mutex_unlock(&bus->mdio_lock);
|
||||
@@ -216,16 +222,16 @@ exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
-static void
|
||||
+static int
|
||||
qca8k_reg_set(struct qca8k_priv *priv, u32 reg, u32 val)
|
||||
{
|
||||
- qca8k_rmw(priv, reg, 0, val);
|
||||
+ return qca8k_rmw(priv, reg, 0, val);
|
||||
}
|
||||
|
||||
-static void
|
||||
+static int
|
||||
qca8k_reg_clear(struct qca8k_priv *priv, u32 reg, u32 val)
|
||||
{
|
||||
- qca8k_rmw(priv, reg, val, 0);
|
||||
+ return qca8k_rmw(priv, reg, val, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -570,12 +576,19 @@ qca8k_mib_init(struct qca8k_priv *priv)
|
||||
int ret;
|
||||
|
||||
mutex_lock(&priv->reg_mutex);
|
||||
- qca8k_reg_set(priv, QCA8K_REG_MIB, QCA8K_MIB_FLUSH | QCA8K_MIB_BUSY);
|
||||
+ ret = qca8k_reg_set(priv, QCA8K_REG_MIB, QCA8K_MIB_FLUSH | QCA8K_MIB_BUSY);
|
||||
+ if (ret)
|
||||
+ goto exit;
|
||||
+
|
||||
qca8k_busy_wait(priv, QCA8K_REG_MIB, QCA8K_MIB_BUSY);
|
||||
- qca8k_reg_set(priv, QCA8K_REG_MIB, QCA8K_MIB_CPU_KEEP);
|
||||
+
|
||||
+ ret = qca8k_reg_set(priv, QCA8K_REG_MIB, QCA8K_MIB_CPU_KEEP);
|
||||
+ if (ret)
|
||||
+ goto exit;
|
||||
|
||||
ret = qca8k_write(priv, QCA8K_REG_MODULE_EN, QCA8K_MODULE_EN_MIB);
|
||||
|
||||
+exit:
|
||||
mutex_unlock(&priv->reg_mutex);
|
||||
return ret;
|
||||
}
|
||||
@@ -747,9 +760,8 @@ qca8k_setup_mdio_bus(struct qca8k_priv *
|
||||
* a dt-overlay and driver reload changed the configuration
|
||||
*/
|
||||
|
||||
- qca8k_reg_clear(priv, QCA8K_MDIO_MASTER_CTRL,
|
||||
- QCA8K_MDIO_MASTER_EN);
|
||||
- return 0;
|
||||
+ return qca8k_reg_clear(priv, QCA8K_MDIO_MASTER_CTRL,
|
||||
+ QCA8K_MDIO_MASTER_EN);
|
||||
}
|
||||
|
||||
priv->ops.phy_read = qca8k_phy_read;
|
||||
@@ -782,8 +794,12 @@ qca8k_setup(struct dsa_switch *ds)
|
||||
return ret;
|
||||
|
||||
/* Enable CPU Port */
|
||||
- qca8k_reg_set(priv, QCA8K_REG_GLOBAL_FW_CTRL0,
|
||||
- QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN);
|
||||
+ ret = qca8k_reg_set(priv, QCA8K_REG_GLOBAL_FW_CTRL0,
|
||||
+ QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN);
|
||||
+ if (ret) {
|
||||
+ dev_err(priv->dev, "failed enabling CPU port");
|
||||
+ return ret;
|
||||
+ }
|
||||
|
||||
/* Enable MIB counters */
|
||||
ret = qca8k_mib_init(priv);
|
||||
@@ -800,9 +816,12 @@ qca8k_setup(struct dsa_switch *ds)
|
||||
}
|
||||
|
||||
/* Disable forwarding by default on all ports */
|
||||
- for (i = 0; i < QCA8K_NUM_PORTS; i++)
|
||||
- qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i),
|
||||
- QCA8K_PORT_LOOKUP_MEMBER, 0);
|
||||
+ for (i = 0; i < QCA8K_NUM_PORTS; i++) {
|
||||
+ ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i),
|
||||
+ QCA8K_PORT_LOOKUP_MEMBER, 0);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ }
|
||||
|
||||
/* Disable MAC by default on all ports */
|
||||
for (i = 1; i < QCA8K_NUM_PORTS; i++)
|
||||
@@ -821,28 +840,37 @@ qca8k_setup(struct dsa_switch *ds)
|
||||
for (i = 0; i < QCA8K_NUM_PORTS; i++) {
|
||||
/* CPU port gets connected to all user ports of the switch */
|
||||
if (dsa_is_cpu_port(ds, i)) {
|
||||
- qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(QCA8K_CPU_PORT),
|
||||
- QCA8K_PORT_LOOKUP_MEMBER, dsa_user_ports(ds));
|
||||
+ ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(QCA8K_CPU_PORT),
|
||||
+ QCA8K_PORT_LOOKUP_MEMBER, dsa_user_ports(ds));
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
/* Individual user ports get connected to CPU port only */
|
||||
if (dsa_is_user_port(ds, i)) {
|
||||
int shift = 16 * (i % 2);
|
||||
|
||||
- qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i),
|
||||
- QCA8K_PORT_LOOKUP_MEMBER,
|
||||
- BIT(QCA8K_CPU_PORT));
|
||||
+ ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i),
|
||||
+ QCA8K_PORT_LOOKUP_MEMBER,
|
||||
+ BIT(QCA8K_CPU_PORT));
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
|
||||
/* Enable ARP Auto-learning by default */
|
||||
- qca8k_reg_set(priv, QCA8K_PORT_LOOKUP_CTRL(i),
|
||||
- QCA8K_PORT_LOOKUP_LEARN);
|
||||
+ ret = qca8k_reg_set(priv, QCA8K_PORT_LOOKUP_CTRL(i),
|
||||
+ QCA8K_PORT_LOOKUP_LEARN);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
|
||||
/* For port based vlans to work we need to set the
|
||||
* default egress vid
|
||||
*/
|
||||
- qca8k_rmw(priv, QCA8K_EGRESS_VLAN(i),
|
||||
- 0xfff << shift,
|
||||
- QCA8K_PORT_VID_DEF << shift);
|
||||
+ ret = qca8k_rmw(priv, QCA8K_EGRESS_VLAN(i),
|
||||
+ 0xfff << shift,
|
||||
+ QCA8K_PORT_VID_DEF << shift);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
ret = qca8k_write(priv, QCA8K_REG_PORT_VLAN_CTRL0(i),
|
||||
QCA8K_PORT_VLAN_CVID(QCA8K_PORT_VID_DEF) |
|
||||
QCA8K_PORT_VLAN_SVID(QCA8K_PORT_VID_DEF));
|
||||
@@ -1234,7 +1262,7 @@ qca8k_port_bridge_join(struct dsa_switch
|
||||
{
|
||||
struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
|
||||
int port_mask = BIT(QCA8K_CPU_PORT);
|
||||
- int i;
|
||||
+ int i, ret;
|
||||
|
||||
for (i = 1; i < QCA8K_NUM_PORTS; i++) {
|
||||
if (dsa_to_port(ds, i)->bridge_dev != br)
|
||||
@@ -1242,17 +1270,20 @@ qca8k_port_bridge_join(struct dsa_switch
|
||||
/* Add this port to the portvlan mask of the other ports
|
||||
* in the bridge
|
||||
*/
|
||||
- qca8k_reg_set(priv,
|
||||
- QCA8K_PORT_LOOKUP_CTRL(i),
|
||||
- BIT(port));
|
||||
+ ret = qca8k_reg_set(priv,
|
||||
+ QCA8K_PORT_LOOKUP_CTRL(i),
|
||||
+ BIT(port));
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
if (i != port)
|
||||
port_mask |= BIT(i);
|
||||
}
|
||||
+
|
||||
/* Add all other ports to this ports portvlan mask */
|
||||
- qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
|
||||
- QCA8K_PORT_LOOKUP_MEMBER, port_mask);
|
||||
+ ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
|
||||
+ QCA8K_PORT_LOOKUP_MEMBER, port_mask);
|
||||
|
||||
- return 0;
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
static void
|
@ -0,0 +1,66 @@
|
||||
From b7c818d194927bdc60ed15db55bb8654496a36b7 Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Fri, 14 May 2021 22:59:58 +0200
|
||||
Subject: [PATCH] net: dsa: qca8k: handle error from qca8k_busy_wait
|
||||
|
||||
Propagate errors from qca8k_busy_wait instead of hardcoding return
|
||||
value.
|
||||
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/qca8k.c | 21 +++++++++++++--------
|
||||
1 file changed, 13 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/qca8k.c
|
||||
+++ b/drivers/net/dsa/qca8k.c
|
||||
@@ -388,8 +388,9 @@ qca8k_fdb_access(struct qca8k_priv *priv
|
||||
return ret;
|
||||
|
||||
/* wait for completion */
|
||||
- if (qca8k_busy_wait(priv, QCA8K_REG_ATU_FUNC, QCA8K_ATU_FUNC_BUSY))
|
||||
- return -1;
|
||||
+ ret = qca8k_busy_wait(priv, QCA8K_REG_ATU_FUNC, QCA8K_ATU_FUNC_BUSY);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
|
||||
/* Check for table full violation when adding an entry */
|
||||
if (cmd == QCA8K_FDB_LOAD) {
|
||||
@@ -468,8 +469,9 @@ qca8k_vlan_access(struct qca8k_priv *pri
|
||||
return ret;
|
||||
|
||||
/* wait for completion */
|
||||
- if (qca8k_busy_wait(priv, QCA8K_REG_VTU_FUNC1, QCA8K_VTU_FUNC1_BUSY))
|
||||
- return -ETIMEDOUT;
|
||||
+ ret = qca8k_busy_wait(priv, QCA8K_REG_VTU_FUNC1, QCA8K_VTU_FUNC1_BUSY);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
|
||||
/* Check for table full violation when adding an entry */
|
||||
if (cmd == QCA8K_VLAN_LOAD) {
|
||||
@@ -580,7 +582,9 @@ qca8k_mib_init(struct qca8k_priv *priv)
|
||||
if (ret)
|
||||
goto exit;
|
||||
|
||||
- qca8k_busy_wait(priv, QCA8K_REG_MIB, QCA8K_MIB_BUSY);
|
||||
+ ret = qca8k_busy_wait(priv, QCA8K_REG_MIB, QCA8K_MIB_BUSY);
|
||||
+ if (ret)
|
||||
+ goto exit;
|
||||
|
||||
ret = qca8k_reg_set(priv, QCA8K_REG_MIB, QCA8K_MIB_CPU_KEEP);
|
||||
if (ret)
|
||||
@@ -670,9 +674,10 @@ qca8k_mdio_read(struct qca8k_priv *priv,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
- if (qca8k_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL,
|
||||
- QCA8K_MDIO_MASTER_BUSY))
|
||||
- return -ETIMEDOUT;
|
||||
+ ret = qca8k_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL,
|
||||
+ QCA8K_MDIO_MASTER_BUSY);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
|
||||
val = qca8k_read(priv, QCA8K_MDIO_MASTER_CTRL);
|
||||
if (val < 0)
|
@ -0,0 +1,96 @@
|
||||
From 6e82a457e06252b59102486767539cc9c2aba60b Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Fri, 14 May 2021 22:59:59 +0200
|
||||
Subject: [PATCH] net: dsa: qca8k: add support for qca8327 switch
|
||||
|
||||
qca8327 switch is a low tier version of the more recent qca8337.
|
||||
It does share the same regs used by the qca8k driver and can be
|
||||
supported with minimal change.
|
||||
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
|
||||
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/qca8k.c | 23 ++++++++++++++++++++---
|
||||
drivers/net/dsa/qca8k.h | 6 ++++++
|
||||
2 files changed, 26 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/qca8k.c
|
||||
+++ b/drivers/net/dsa/qca8k.c
|
||||
@@ -1533,6 +1533,7 @@ static const struct dsa_switch_ops qca8k
|
||||
static int
|
||||
qca8k_sw_probe(struct mdio_device *mdiodev)
|
||||
{
|
||||
+ const struct qca8k_match_data *data;
|
||||
struct qca8k_priv *priv;
|
||||
u32 id;
|
||||
|
||||
@@ -1560,6 +1561,11 @@ qca8k_sw_probe(struct mdio_device *mdiod
|
||||
gpiod_set_value_cansleep(priv->reset_gpio, 0);
|
||||
}
|
||||
|
||||
+ /* get the switches ID from the compatible */
|
||||
+ data = of_device_get_match_data(&mdiodev->dev);
|
||||
+ if (!data)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
/* read the switches ID register */
|
||||
id = qca8k_read(priv, QCA8K_REG_MASK_CTRL);
|
||||
if (id < 0)
|
||||
@@ -1567,8 +1573,10 @@ qca8k_sw_probe(struct mdio_device *mdiod
|
||||
|
||||
id >>= QCA8K_MASK_CTRL_ID_S;
|
||||
id &= QCA8K_MASK_CTRL_ID_M;
|
||||
- if (id != QCA8K_ID_QCA8337)
|
||||
+ if (id != data->id) {
|
||||
+ dev_err(&mdiodev->dev, "Switch id detected %x but expected %x", id, data->id);
|
||||
return -ENODEV;
|
||||
+ }
|
||||
|
||||
priv->ds = devm_kzalloc(&mdiodev->dev, sizeof(*priv->ds), GFP_KERNEL);
|
||||
if (!priv->ds)
|
||||
@@ -1634,9 +1642,18 @@ static int qca8k_resume(struct device *d
|
||||
static SIMPLE_DEV_PM_OPS(qca8k_pm_ops,
|
||||
qca8k_suspend, qca8k_resume);
|
||||
|
||||
+static const struct qca8k_match_data qca832x = {
|
||||
+ .id = QCA8K_ID_QCA8327,
|
||||
+};
|
||||
+
|
||||
+static const struct qca8k_match_data qca833x = {
|
||||
+ .id = QCA8K_ID_QCA8337,
|
||||
+};
|
||||
+
|
||||
static const struct of_device_id qca8k_of_match[] = {
|
||||
- { .compatible = "qca,qca8334" },
|
||||
- { .compatible = "qca,qca8337" },
|
||||
+ { .compatible = "qca,qca8327", .data = &qca832x },
|
||||
+ { .compatible = "qca,qca8334", .data = &qca833x },
|
||||
+ { .compatible = "qca,qca8337", .data = &qca833x },
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
--- a/drivers/net/dsa/qca8k.h
|
||||
+++ b/drivers/net/dsa/qca8k.h
|
||||
@@ -15,6 +15,8 @@
|
||||
#define QCA8K_NUM_PORTS 7
|
||||
#define QCA8K_MAX_MTU 9000
|
||||
|
||||
+#define PHY_ID_QCA8327 0x004dd034
|
||||
+#define QCA8K_ID_QCA8327 0x12
|
||||
#define PHY_ID_QCA8337 0x004dd036
|
||||
#define QCA8K_ID_QCA8337 0x13
|
||||
|
||||
@@ -213,6 +215,10 @@ struct ar8xxx_port_status {
|
||||
int enabled;
|
||||
};
|
||||
|
||||
+struct qca8k_match_data {
|
||||
+ u8 id;
|
||||
+};
|
||||
+
|
||||
struct qca8k_priv {
|
||||
struct regmap *regmap;
|
||||
struct mii_bus *bus;
|
@ -0,0 +1,26 @@
|
||||
From 227a9ffc1bc77037339530607fe129af3824620e Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Fri, 14 May 2021 23:00:00 +0200
|
||||
Subject: [PATCH] devicetree: net: dsa: qca8k: Document new compatible qca8327
|
||||
|
||||
Add support for qca8327 in the compatible list.
|
||||
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Acked-by: Rob Herring <robh@kernel.org>
|
||||
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
Documentation/devicetree/bindings/net/dsa/qca8k.txt | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/Documentation/devicetree/bindings/net/dsa/qca8k.txt
|
||||
+++ b/Documentation/devicetree/bindings/net/dsa/qca8k.txt
|
||||
@@ -3,6 +3,7 @@
|
||||
Required properties:
|
||||
|
||||
- compatible: should be one of:
|
||||
+ "qca,qca8327"
|
||||
"qca,qca8334"
|
||||
"qca,qca8337"
|
||||
|
@ -0,0 +1,130 @@
|
||||
From 83a3ceb39b2495171aabe9446271b94c678354f3 Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Fri, 14 May 2021 23:00:01 +0200
|
||||
Subject: [PATCH] net: dsa: qca8k: add priority tweak to qca8337 switch
|
||||
|
||||
The port 5 of the qca8337 have some problem in flood condition. The
|
||||
original legacy driver had some specific buffer and priority settings
|
||||
for the different port suggested by the QCA switch team. Add this
|
||||
missing settings to improve switch stability under load condition.
|
||||
The packet priority tweak is only needed for the qca8337 switch and
|
||||
other qca8k switch are not affected.
|
||||
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/qca8k.c | 47 +++++++++++++++++++++++++++++++++++++++++
|
||||
drivers/net/dsa/qca8k.h | 25 ++++++++++++++++++++++
|
||||
2 files changed, 72 insertions(+)
|
||||
|
||||
--- a/drivers/net/dsa/qca8k.c
|
||||
+++ b/drivers/net/dsa/qca8k.c
|
||||
@@ -779,6 +779,7 @@ qca8k_setup(struct dsa_switch *ds)
|
||||
{
|
||||
struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
|
||||
int ret, i;
|
||||
+ u32 mask;
|
||||
|
||||
/* Make sure that port 0 is the cpu port */
|
||||
if (!dsa_is_cpu_port(ds, 0)) {
|
||||
@@ -884,6 +885,51 @@ qca8k_setup(struct dsa_switch *ds)
|
||||
}
|
||||
}
|
||||
|
||||
+ /* The port 5 of the qca8337 have some problem in flood condition. The
|
||||
+ * original legacy driver had some specific buffer and priority settings
|
||||
+ * for the different port suggested by the QCA switch team. Add this
|
||||
+ * missing settings to improve switch stability under load condition.
|
||||
+ * This problem is limited to qca8337 and other qca8k switch are not affected.
|
||||
+ */
|
||||
+ if (priv->switch_id == QCA8K_ID_QCA8337) {
|
||||
+ for (i = 0; i < QCA8K_NUM_PORTS; i++) {
|
||||
+ switch (i) {
|
||||
+ /* The 2 CPU port and port 5 requires some different
|
||||
+ * priority than any other ports.
|
||||
+ */
|
||||
+ case 0:
|
||||
+ case 5:
|
||||
+ case 6:
|
||||
+ mask = QCA8K_PORT_HOL_CTRL0_EG_PRI0(0x3) |
|
||||
+ QCA8K_PORT_HOL_CTRL0_EG_PRI1(0x4) |
|
||||
+ QCA8K_PORT_HOL_CTRL0_EG_PRI2(0x4) |
|
||||
+ QCA8K_PORT_HOL_CTRL0_EG_PRI3(0x4) |
|
||||
+ QCA8K_PORT_HOL_CTRL0_EG_PRI4(0x6) |
|
||||
+ QCA8K_PORT_HOL_CTRL0_EG_PRI5(0x8) |
|
||||
+ QCA8K_PORT_HOL_CTRL0_EG_PORT(0x1e);
|
||||
+ break;
|
||||
+ default:
|
||||
+ mask = QCA8K_PORT_HOL_CTRL0_EG_PRI0(0x3) |
|
||||
+ QCA8K_PORT_HOL_CTRL0_EG_PRI1(0x4) |
|
||||
+ QCA8K_PORT_HOL_CTRL0_EG_PRI2(0x6) |
|
||||
+ QCA8K_PORT_HOL_CTRL0_EG_PRI3(0x8) |
|
||||
+ QCA8K_PORT_HOL_CTRL0_EG_PORT(0x19);
|
||||
+ }
|
||||
+ qca8k_write(priv, QCA8K_REG_PORT_HOL_CTRL0(i), mask);
|
||||
+
|
||||
+ mask = QCA8K_PORT_HOL_CTRL1_ING(0x6) |
|
||||
+ QCA8K_PORT_HOL_CTRL1_EG_PRI_BUF_EN |
|
||||
+ QCA8K_PORT_HOL_CTRL1_EG_PORT_BUF_EN |
|
||||
+ QCA8K_PORT_HOL_CTRL1_WRED_EN;
|
||||
+ qca8k_rmw(priv, QCA8K_REG_PORT_HOL_CTRL1(i),
|
||||
+ QCA8K_PORT_HOL_CTRL1_ING_BUF |
|
||||
+ QCA8K_PORT_HOL_CTRL1_EG_PRI_BUF_EN |
|
||||
+ QCA8K_PORT_HOL_CTRL1_EG_PORT_BUF_EN |
|
||||
+ QCA8K_PORT_HOL_CTRL1_WRED_EN,
|
||||
+ mask);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
/* Setup our port MTUs to match power on defaults */
|
||||
for (i = 0; i < QCA8K_NUM_PORTS; i++)
|
||||
priv->port_mtu[i] = ETH_FRAME_LEN + ETH_FCS_LEN;
|
||||
@@ -1578,6 +1624,7 @@ qca8k_sw_probe(struct mdio_device *mdiod
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
+ priv->switch_id = id;
|
||||
priv->ds = devm_kzalloc(&mdiodev->dev, sizeof(*priv->ds), GFP_KERNEL);
|
||||
if (!priv->ds)
|
||||
return -ENOMEM;
|
||||
--- a/drivers/net/dsa/qca8k.h
|
||||
+++ b/drivers/net/dsa/qca8k.h
|
||||
@@ -168,6 +168,30 @@
|
||||
#define QCA8K_PORT_LOOKUP_STATE GENMASK(18, 16)
|
||||
#define QCA8K_PORT_LOOKUP_LEARN BIT(20)
|
||||
|
||||
+#define QCA8K_REG_PORT_HOL_CTRL0(_i) (0x970 + (_i) * 0x8)
|
||||
+#define QCA8K_PORT_HOL_CTRL0_EG_PRI0_BUF GENMASK(3, 0)
|
||||
+#define QCA8K_PORT_HOL_CTRL0_EG_PRI0(x) ((x) << 0)
|
||||
+#define QCA8K_PORT_HOL_CTRL0_EG_PRI1_BUF GENMASK(7, 4)
|
||||
+#define QCA8K_PORT_HOL_CTRL0_EG_PRI1(x) ((x) << 4)
|
||||
+#define QCA8K_PORT_HOL_CTRL0_EG_PRI2_BUF GENMASK(11, 8)
|
||||
+#define QCA8K_PORT_HOL_CTRL0_EG_PRI2(x) ((x) << 8)
|
||||
+#define QCA8K_PORT_HOL_CTRL0_EG_PRI3_BUF GENMASK(15, 12)
|
||||
+#define QCA8K_PORT_HOL_CTRL0_EG_PRI3(x) ((x) << 12)
|
||||
+#define QCA8K_PORT_HOL_CTRL0_EG_PRI4_BUF GENMASK(19, 16)
|
||||
+#define QCA8K_PORT_HOL_CTRL0_EG_PRI4(x) ((x) << 16)
|
||||
+#define QCA8K_PORT_HOL_CTRL0_EG_PRI5_BUF GENMASK(23, 20)
|
||||
+#define QCA8K_PORT_HOL_CTRL0_EG_PRI5(x) ((x) << 20)
|
||||
+#define QCA8K_PORT_HOL_CTRL0_EG_PORT_BUF GENMASK(29, 24)
|
||||
+#define QCA8K_PORT_HOL_CTRL0_EG_PORT(x) ((x) << 24)
|
||||
+
|
||||
+#define QCA8K_REG_PORT_HOL_CTRL1(_i) (0x974 + (_i) * 0x8)
|
||||
+#define QCA8K_PORT_HOL_CTRL1_ING_BUF GENMASK(3, 0)
|
||||
+#define QCA8K_PORT_HOL_CTRL1_ING(x) ((x) << 0)
|
||||
+#define QCA8K_PORT_HOL_CTRL1_EG_PRI_BUF_EN BIT(6)
|
||||
+#define QCA8K_PORT_HOL_CTRL1_EG_PORT_BUF_EN BIT(7)
|
||||
+#define QCA8K_PORT_HOL_CTRL1_WRED_EN BIT(8)
|
||||
+#define QCA8K_PORT_HOL_CTRL1_EG_MIRROR_EN BIT(16)
|
||||
+
|
||||
/* Pkt edit registers */
|
||||
#define QCA8K_EGRESS_VLAN(x) (0x0c70 + (4 * (x / 2)))
|
||||
|
||||
@@ -220,6 +244,7 @@ struct qca8k_match_data {
|
||||
};
|
||||
|
||||
struct qca8k_priv {
|
||||
+ u8 switch_id;
|
||||
struct regmap *regmap;
|
||||
struct mii_bus *bus;
|
||||
struct ar8xxx_port_status port_sts[QCA8K_NUM_PORTS];
|
@ -0,0 +1,31 @@
|
||||
From 5bf9ff3b9fb5ecb67a1a3517b26db3a00f2a2f11 Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Fri, 14 May 2021 23:00:02 +0200
|
||||
Subject: [PATCH] net: dsa: qca8k: limit port5 delay to qca8337
|
||||
|
||||
Limit port5 rx delay to qca8337. This is taken from the legacy QSDK code
|
||||
that limits the rx delay on port5 to only this particular switch version,
|
||||
on other switch only the tx and rx delay for port0 are needed.
|
||||
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/qca8k.c | 6 ++++--
|
||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/qca8k.c
|
||||
+++ b/drivers/net/dsa/qca8k.c
|
||||
@@ -1003,8 +1003,10 @@ qca8k_phylink_mac_config(struct dsa_swit
|
||||
QCA8K_PORT_PAD_RGMII_EN |
|
||||
QCA8K_PORT_PAD_RGMII_TX_DELAY(QCA8K_MAX_DELAY) |
|
||||
QCA8K_PORT_PAD_RGMII_RX_DELAY(QCA8K_MAX_DELAY));
|
||||
- qca8k_write(priv, QCA8K_REG_PORT5_PAD_CTRL,
|
||||
- QCA8K_PORT_PAD_RGMII_RX_DELAY_EN);
|
||||
+ /* QCA8337 requires to set rgmii rx delay */
|
||||
+ if (priv->switch_id == QCA8K_ID_QCA8337)
|
||||
+ qca8k_write(priv, QCA8K_REG_PORT5_PAD_CTRL,
|
||||
+ QCA8K_PORT_PAD_RGMII_RX_DELAY_EN);
|
||||
break;
|
||||
case PHY_INTERFACE_MODE_SGMII:
|
||||
case PHY_INTERFACE_MODE_1000BASEX:
|
@ -0,0 +1,48 @@
|
||||
From 0fc57e4b5e39461fc0a54aae0afe4241363a7267 Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Fri, 14 May 2021 23:00:03 +0200
|
||||
Subject: [PATCH] net: dsa: qca8k: add GLOBAL_FC settings needed for qca8327
|
||||
|
||||
Switch qca8327 needs special settings for the GLOBAL_FC_THRES regs.
|
||||
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/qca8k.c | 10 ++++++++++
|
||||
drivers/net/dsa/qca8k.h | 6 ++++++
|
||||
2 files changed, 16 insertions(+)
|
||||
|
||||
--- a/drivers/net/dsa/qca8k.c
|
||||
+++ b/drivers/net/dsa/qca8k.c
|
||||
@@ -930,6 +930,16 @@ qca8k_setup(struct dsa_switch *ds)
|
||||
}
|
||||
}
|
||||
|
||||
+ /* Special GLOBAL_FC_THRESH value are needed for ar8327 switch */
|
||||
+ if (priv->switch_id == QCA8K_ID_QCA8327) {
|
||||
+ mask = QCA8K_GLOBAL_FC_GOL_XON_THRES(288) |
|
||||
+ QCA8K_GLOBAL_FC_GOL_XOFF_THRES(496);
|
||||
+ qca8k_rmw(priv, QCA8K_REG_GLOBAL_FC_THRESH,
|
||||
+ QCA8K_GLOBAL_FC_GOL_XON_THRES_S |
|
||||
+ QCA8K_GLOBAL_FC_GOL_XOFF_THRES_S,
|
||||
+ mask);
|
||||
+ }
|
||||
+
|
||||
/* Setup our port MTUs to match power on defaults */
|
||||
for (i = 0; i < QCA8K_NUM_PORTS; i++)
|
||||
priv->port_mtu[i] = ETH_FRAME_LEN + ETH_FCS_LEN;
|
||||
--- a/drivers/net/dsa/qca8k.h
|
||||
+++ b/drivers/net/dsa/qca8k.h
|
||||
@@ -168,6 +168,12 @@
|
||||
#define QCA8K_PORT_LOOKUP_STATE GENMASK(18, 16)
|
||||
#define QCA8K_PORT_LOOKUP_LEARN BIT(20)
|
||||
|
||||
+#define QCA8K_REG_GLOBAL_FC_THRESH 0x800
|
||||
+#define QCA8K_GLOBAL_FC_GOL_XON_THRES(x) ((x) << 16)
|
||||
+#define QCA8K_GLOBAL_FC_GOL_XON_THRES_S GENMASK(24, 16)
|
||||
+#define QCA8K_GLOBAL_FC_GOL_XOFF_THRES(x) ((x) << 0)
|
||||
+#define QCA8K_GLOBAL_FC_GOL_XOFF_THRES_S GENMASK(8, 0)
|
||||
+
|
||||
#define QCA8K_REG_PORT_HOL_CTRL0(_i) (0x970 + (_i) * 0x8)
|
||||
#define QCA8K_PORT_HOL_CTRL0_EG_PRI0_BUF GENMASK(3, 0)
|
||||
#define QCA8K_PORT_HOL_CTRL0_EG_PRI0(x) ((x) << 0)
|
@ -0,0 +1,114 @@
|
||||
From 95ffeaf18b3bb90eeef52cbf7d79ccc9d0345ff5 Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Fri, 14 May 2021 23:00:04 +0200
|
||||
Subject: [PATCH] net: dsa: qca8k: add support for switch rev
|
||||
|
||||
qca8k internal phy driver require some special debug value to be set
|
||||
based on the switch revision. Rework the switch id read function to
|
||||
also read the chip revision.
|
||||
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/qca8k.c | 53 ++++++++++++++++++++++++++---------------
|
||||
drivers/net/dsa/qca8k.h | 7 ++++--
|
||||
2 files changed, 39 insertions(+), 21 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/qca8k.c
|
||||
+++ b/drivers/net/dsa/qca8k.c
|
||||
@@ -1588,12 +1588,40 @@ static const struct dsa_switch_ops qca8k
|
||||
.phylink_mac_link_up = qca8k_phylink_mac_link_up,
|
||||
};
|
||||
|
||||
+static int qca8k_read_switch_id(struct qca8k_priv *priv)
|
||||
+{
|
||||
+ const struct qca8k_match_data *data;
|
||||
+ u32 val;
|
||||
+ u8 id;
|
||||
+
|
||||
+ /* get the switches ID from the compatible */
|
||||
+ data = of_device_get_match_data(priv->dev);
|
||||
+ if (!data)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ val = qca8k_read(priv, QCA8K_REG_MASK_CTRL);
|
||||
+ if (val < 0)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ id = QCA8K_MASK_CTRL_DEVICE_ID(val & QCA8K_MASK_CTRL_DEVICE_ID_MASK);
|
||||
+ if (id != data->id) {
|
||||
+ dev_err(priv->dev, "Switch id detected %x but expected %x", id, data->id);
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ priv->switch_id = id;
|
||||
+
|
||||
+ /* Save revision to communicate to the internal PHY driver */
|
||||
+ priv->switch_revision = (val & QCA8K_MASK_CTRL_REV_ID_MASK);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int
|
||||
qca8k_sw_probe(struct mdio_device *mdiodev)
|
||||
{
|
||||
- const struct qca8k_match_data *data;
|
||||
struct qca8k_priv *priv;
|
||||
- u32 id;
|
||||
+ int ret;
|
||||
|
||||
/* allocate the private data struct so that we can probe the switches
|
||||
* ID register
|
||||
@@ -1619,24 +1647,11 @@ qca8k_sw_probe(struct mdio_device *mdiod
|
||||
gpiod_set_value_cansleep(priv->reset_gpio, 0);
|
||||
}
|
||||
|
||||
- /* get the switches ID from the compatible */
|
||||
- data = of_device_get_match_data(&mdiodev->dev);
|
||||
- if (!data)
|
||||
- return -ENODEV;
|
||||
+ /* Check the detected switch id */
|
||||
+ ret = qca8k_read_switch_id(priv);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
|
||||
- /* read the switches ID register */
|
||||
- id = qca8k_read(priv, QCA8K_REG_MASK_CTRL);
|
||||
- if (id < 0)
|
||||
- return id;
|
||||
-
|
||||
- id >>= QCA8K_MASK_CTRL_ID_S;
|
||||
- id &= QCA8K_MASK_CTRL_ID_M;
|
||||
- if (id != data->id) {
|
||||
- dev_err(&mdiodev->dev, "Switch id detected %x but expected %x", id, data->id);
|
||||
- return -ENODEV;
|
||||
- }
|
||||
-
|
||||
- priv->switch_id = id;
|
||||
priv->ds = devm_kzalloc(&mdiodev->dev, sizeof(*priv->ds), GFP_KERNEL);
|
||||
if (!priv->ds)
|
||||
return -ENOMEM;
|
||||
--- a/drivers/net/dsa/qca8k.h
|
||||
+++ b/drivers/net/dsa/qca8k.h
|
||||
@@ -30,8 +30,10 @@
|
||||
|
||||
/* Global control registers */
|
||||
#define QCA8K_REG_MASK_CTRL 0x000
|
||||
-#define QCA8K_MASK_CTRL_ID_M 0xff
|
||||
-#define QCA8K_MASK_CTRL_ID_S 8
|
||||
+#define QCA8K_MASK_CTRL_REV_ID_MASK GENMASK(7, 0)
|
||||
+#define QCA8K_MASK_CTRL_REV_ID(x) ((x) >> 0)
|
||||
+#define QCA8K_MASK_CTRL_DEVICE_ID_MASK GENMASK(15, 8)
|
||||
+#define QCA8K_MASK_CTRL_DEVICE_ID(x) ((x) >> 8)
|
||||
#define QCA8K_REG_PORT0_PAD_CTRL 0x004
|
||||
#define QCA8K_REG_PORT5_PAD_CTRL 0x008
|
||||
#define QCA8K_REG_PORT6_PAD_CTRL 0x00c
|
||||
@@ -251,6 +253,7 @@ struct qca8k_match_data {
|
||||
|
||||
struct qca8k_priv {
|
||||
u8 switch_id;
|
||||
+ u8 switch_revision;
|
||||
struct regmap *regmap;
|
||||
struct mii_bus *bus;
|
||||
struct ar8xxx_port_status port_sts[QCA8K_NUM_PORTS];
|
@ -0,0 +1,28 @@
|
||||
From 1ee0591a1093c2448642c33433483e9260275f7b Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Fri, 14 May 2021 23:00:05 +0200
|
||||
Subject: [PATCH] net: dsa: qca8k: add ethernet-ports fallback to
|
||||
setup_mdio_bus
|
||||
|
||||
Dsa now also supports ethernet-ports. Add this new binding as a fallback
|
||||
if the ports node can't be found.
|
||||
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/qca8k.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
--- a/drivers/net/dsa/qca8k.c
|
||||
+++ b/drivers/net/dsa/qca8k.c
|
||||
@@ -719,6 +719,9 @@ qca8k_setup_mdio_bus(struct qca8k_priv *
|
||||
|
||||
ports = of_get_child_by_name(priv->dev->of_node, "ports");
|
||||
if (!ports)
|
||||
+ ports = of_get_child_by_name(priv->dev->of_node, "ethernet-ports");
|
||||
+
|
||||
+ if (!ports)
|
||||
return -EINVAL;
|
||||
|
||||
for_each_available_child_of_node(ports, port) {
|
@ -0,0 +1,188 @@
|
||||
From e4b9977cee1583da38a6e9118078bb728aaccf7b Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Fri, 14 May 2021 23:00:06 +0200
|
||||
Subject: [PATCH] net: dsa: qca8k: make rgmii delay configurable
|
||||
|
||||
The legacy qsdk code used a different delay instead of the max value.
|
||||
Qsdk use 1 ns for rx and 2 ns for tx. Make these values configurable
|
||||
using the standard rx/tx-internal-delay-ps ethernet binding and apply
|
||||
qsdk values by default. The connected gmac doesn't add any delay so no
|
||||
additional delay is added to tx/rx.
|
||||
On this switch the delay is actually in ns so value should be in the
|
||||
1000 order. Any value converted from ps to ns by dividing it by 1000
|
||||
as the switch max value for delay is 3ns.
|
||||
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/qca8k.c | 82 ++++++++++++++++++++++++++++++++++++++++-
|
||||
drivers/net/dsa/qca8k.h | 11 +++---
|
||||
2 files changed, 86 insertions(+), 7 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/qca8k.c
|
||||
+++ b/drivers/net/dsa/qca8k.c
|
||||
@@ -778,6 +778,68 @@ qca8k_setup_mdio_bus(struct qca8k_priv *
|
||||
}
|
||||
|
||||
static int
|
||||
+qca8k_setup_of_rgmii_delay(struct qca8k_priv *priv)
|
||||
+{
|
||||
+ struct device_node *port_dn;
|
||||
+ phy_interface_t mode;
|
||||
+ struct dsa_port *dp;
|
||||
+ u32 val;
|
||||
+
|
||||
+ /* CPU port is already checked */
|
||||
+ dp = dsa_to_port(priv->ds, 0);
|
||||
+
|
||||
+ port_dn = dp->dn;
|
||||
+
|
||||
+ /* Check if port 0 is set to the correct type */
|
||||
+ of_get_phy_mode(port_dn, &mode);
|
||||
+ if (mode != PHY_INTERFACE_MODE_RGMII_ID &&
|
||||
+ mode != PHY_INTERFACE_MODE_RGMII_RXID &&
|
||||
+ mode != PHY_INTERFACE_MODE_RGMII_TXID) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ switch (mode) {
|
||||
+ case PHY_INTERFACE_MODE_RGMII_ID:
|
||||
+ case PHY_INTERFACE_MODE_RGMII_RXID:
|
||||
+ if (of_property_read_u32(port_dn, "rx-internal-delay-ps", &val))
|
||||
+ val = 2;
|
||||
+ else
|
||||
+ /* Switch regs accept value in ns, convert ps to ns */
|
||||
+ val = val / 1000;
|
||||
+
|
||||
+ if (val > QCA8K_MAX_DELAY) {
|
||||
+ dev_err(priv->dev, "rgmii rx delay is limited to a max value of 3ns, setting to the max value");
|
||||
+ val = 3;
|
||||
+ }
|
||||
+
|
||||
+ priv->rgmii_rx_delay = val;
|
||||
+ /* Stop here if we need to check only for rx delay */
|
||||
+ if (mode != PHY_INTERFACE_MODE_RGMII_ID)
|
||||
+ break;
|
||||
+
|
||||
+ fallthrough;
|
||||
+ case PHY_INTERFACE_MODE_RGMII_TXID:
|
||||
+ if (of_property_read_u32(port_dn, "tx-internal-delay-ps", &val))
|
||||
+ val = 1;
|
||||
+ else
|
||||
+ /* Switch regs accept value in ns, convert ps to ns */
|
||||
+ val = val / 1000;
|
||||
+
|
||||
+ if (val > QCA8K_MAX_DELAY) {
|
||||
+ dev_err(priv->dev, "rgmii tx delay is limited to a max value of 3ns, setting to the max value");
|
||||
+ val = 3;
|
||||
+ }
|
||||
+
|
||||
+ priv->rgmii_tx_delay = val;
|
||||
+ break;
|
||||
+ default:
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
qca8k_setup(struct dsa_switch *ds)
|
||||
{
|
||||
struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
|
||||
@@ -802,6 +864,10 @@ qca8k_setup(struct dsa_switch *ds)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
+ ret = qca8k_setup_of_rgmii_delay(priv);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
/* Enable CPU Port */
|
||||
ret = qca8k_reg_set(priv, QCA8K_REG_GLOBAL_FW_CTRL0,
|
||||
QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN);
|
||||
@@ -970,6 +1036,8 @@ qca8k_phylink_mac_config(struct dsa_swit
|
||||
case 0: /* 1st CPU port */
|
||||
if (state->interface != PHY_INTERFACE_MODE_RGMII &&
|
||||
state->interface != PHY_INTERFACE_MODE_RGMII_ID &&
|
||||
+ state->interface != PHY_INTERFACE_MODE_RGMII_TXID &&
|
||||
+ state->interface != PHY_INTERFACE_MODE_RGMII_RXID &&
|
||||
state->interface != PHY_INTERFACE_MODE_SGMII)
|
||||
return;
|
||||
|
||||
@@ -985,6 +1053,8 @@ qca8k_phylink_mac_config(struct dsa_swit
|
||||
case 6: /* 2nd CPU port / external PHY */
|
||||
if (state->interface != PHY_INTERFACE_MODE_RGMII &&
|
||||
state->interface != PHY_INTERFACE_MODE_RGMII_ID &&
|
||||
+ state->interface != PHY_INTERFACE_MODE_RGMII_TXID &&
|
||||
+ state->interface != PHY_INTERFACE_MODE_RGMII_RXID &&
|
||||
state->interface != PHY_INTERFACE_MODE_SGMII &&
|
||||
state->interface != PHY_INTERFACE_MODE_1000BASEX)
|
||||
return;
|
||||
@@ -1008,14 +1078,18 @@ qca8k_phylink_mac_config(struct dsa_swit
|
||||
qca8k_write(priv, reg, QCA8K_PORT_PAD_RGMII_EN);
|
||||
break;
|
||||
case PHY_INTERFACE_MODE_RGMII_ID:
|
||||
+ case PHY_INTERFACE_MODE_RGMII_TXID:
|
||||
+ case PHY_INTERFACE_MODE_RGMII_RXID:
|
||||
/* RGMII_ID needs internal delay. This is enabled through
|
||||
* PORT5_PAD_CTRL for all ports, rather than individual port
|
||||
* registers
|
||||
*/
|
||||
qca8k_write(priv, reg,
|
||||
QCA8K_PORT_PAD_RGMII_EN |
|
||||
- QCA8K_PORT_PAD_RGMII_TX_DELAY(QCA8K_MAX_DELAY) |
|
||||
- QCA8K_PORT_PAD_RGMII_RX_DELAY(QCA8K_MAX_DELAY));
|
||||
+ QCA8K_PORT_PAD_RGMII_TX_DELAY(priv->rgmii_tx_delay) |
|
||||
+ QCA8K_PORT_PAD_RGMII_RX_DELAY(priv->rgmii_rx_delay) |
|
||||
+ QCA8K_PORT_PAD_RGMII_TX_DELAY_EN |
|
||||
+ QCA8K_PORT_PAD_RGMII_RX_DELAY_EN);
|
||||
/* QCA8337 requires to set rgmii rx delay */
|
||||
if (priv->switch_id == QCA8K_ID_QCA8337)
|
||||
qca8k_write(priv, QCA8K_REG_PORT5_PAD_CTRL,
|
||||
@@ -1073,6 +1147,8 @@ qca8k_phylink_validate(struct dsa_switch
|
||||
if (state->interface != PHY_INTERFACE_MODE_NA &&
|
||||
state->interface != PHY_INTERFACE_MODE_RGMII &&
|
||||
state->interface != PHY_INTERFACE_MODE_RGMII_ID &&
|
||||
+ state->interface != PHY_INTERFACE_MODE_RGMII_TXID &&
|
||||
+ state->interface != PHY_INTERFACE_MODE_RGMII_RXID &&
|
||||
state->interface != PHY_INTERFACE_MODE_SGMII)
|
||||
goto unsupported;
|
||||
break;
|
||||
@@ -1090,6 +1166,8 @@ qca8k_phylink_validate(struct dsa_switch
|
||||
if (state->interface != PHY_INTERFACE_MODE_NA &&
|
||||
state->interface != PHY_INTERFACE_MODE_RGMII &&
|
||||
state->interface != PHY_INTERFACE_MODE_RGMII_ID &&
|
||||
+ state->interface != PHY_INTERFACE_MODE_RGMII_TXID &&
|
||||
+ state->interface != PHY_INTERFACE_MODE_RGMII_RXID &&
|
||||
state->interface != PHY_INTERFACE_MODE_SGMII &&
|
||||
state->interface != PHY_INTERFACE_MODE_1000BASEX)
|
||||
goto unsupported;
|
||||
--- a/drivers/net/dsa/qca8k.h
|
||||
+++ b/drivers/net/dsa/qca8k.h
|
||||
@@ -38,12 +38,11 @@
|
||||
#define QCA8K_REG_PORT5_PAD_CTRL 0x008
|
||||
#define QCA8K_REG_PORT6_PAD_CTRL 0x00c
|
||||
#define QCA8K_PORT_PAD_RGMII_EN BIT(26)
|
||||
-#define QCA8K_PORT_PAD_RGMII_TX_DELAY(x) \
|
||||
- ((0x8 + (x & 0x3)) << 22)
|
||||
-#define QCA8K_PORT_PAD_RGMII_RX_DELAY(x) \
|
||||
- ((0x10 + (x & 0x3)) << 20)
|
||||
-#define QCA8K_MAX_DELAY 3
|
||||
+#define QCA8K_PORT_PAD_RGMII_TX_DELAY(x) ((x) << 22)
|
||||
+#define QCA8K_PORT_PAD_RGMII_RX_DELAY(x) ((x) << 20)
|
||||
+#define QCA8K_PORT_PAD_RGMII_TX_DELAY_EN BIT(25)
|
||||
#define QCA8K_PORT_PAD_RGMII_RX_DELAY_EN BIT(24)
|
||||
+#define QCA8K_MAX_DELAY 3
|
||||
#define QCA8K_PORT_PAD_SGMII_EN BIT(7)
|
||||
#define QCA8K_REG_PWS 0x010
|
||||
#define QCA8K_PWS_SERDES_AEN_DIS BIT(7)
|
||||
@@ -254,6 +253,8 @@ struct qca8k_match_data {
|
||||
struct qca8k_priv {
|
||||
u8 switch_id;
|
||||
u8 switch_revision;
|
||||
+ u8 rgmii_tx_delay;
|
||||
+ u8 rgmii_rx_delay;
|
||||
struct regmap *regmap;
|
||||
struct mii_bus *bus;
|
||||
struct ar8xxx_port_status port_sts[QCA8K_NUM_PORTS];
|
@ -0,0 +1,50 @@
|
||||
From 63c33bbfeb6842a956a0eb12901e28eb335bdb18 Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Fri, 14 May 2021 23:00:07 +0200
|
||||
Subject: [PATCH] net: dsa: qca8k: clear MASTER_EN after phy read/write
|
||||
|
||||
Clear MDIO_MASTER_EN bit from MDIO_MASTER_CTRL after read/write
|
||||
operation. The MDIO_MASTER_EN bit is not reset after read/write
|
||||
operation and the next operation can be wrongly interpreted by the
|
||||
switch as a mdio operation. This cause a production of wrong/garbage
|
||||
data from the switch and underfined bheavior. (random port drop,
|
||||
unplugged port flagged with link up, wrong port speed)
|
||||
Also on driver remove the MASTER_CTRL can be left set and cause the
|
||||
malfunction of any next driver using the mdio device.
|
||||
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/qca8k.c | 14 ++++++++++++--
|
||||
1 file changed, 12 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/qca8k.c
|
||||
+++ b/drivers/net/dsa/qca8k.c
|
||||
@@ -649,8 +649,14 @@ qca8k_mdio_write(struct qca8k_priv *priv
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
- return qca8k_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL,
|
||||
- QCA8K_MDIO_MASTER_BUSY);
|
||||
+ ret = qca8k_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL,
|
||||
+ QCA8K_MDIO_MASTER_BUSY);
|
||||
+
|
||||
+ /* even if the busy_wait timeouts try to clear the MASTER_EN */
|
||||
+ qca8k_reg_clear(priv, QCA8K_MDIO_MASTER_CTRL,
|
||||
+ QCA8K_MDIO_MASTER_EN);
|
||||
+
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -685,6 +691,10 @@ qca8k_mdio_read(struct qca8k_priv *priv,
|
||||
|
||||
val &= QCA8K_MDIO_MASTER_DATA_MASK;
|
||||
|
||||
+ /* even if the busy_wait timeouts try to clear the MASTER_EN */
|
||||
+ qca8k_reg_clear(priv, QCA8K_MDIO_MASTER_CTRL,
|
||||
+ QCA8K_MDIO_MASTER_EN);
|
||||
+
|
||||
return val;
|
||||
}
|
||||
|
@ -0,0 +1,128 @@
|
||||
From 60df02b6ea4581d72eb7a3ab7204504a54059b72 Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Fri, 14 May 2021 23:00:08 +0200
|
||||
Subject: [PATCH] net: dsa: qca8k: dsa: qca8k: protect MASTER busy_wait with
|
||||
mdio mutex
|
||||
|
||||
MDIO_MASTER operation have a dedicated busy wait that is not protected
|
||||
by the mdio mutex. This can cause situation where the MASTER operation
|
||||
is done and a normal operation is executed between the MASTER read/write
|
||||
and the MASTER busy_wait. Rework the qca8k_mdio_read/write function to
|
||||
address this issue by binding the lock for the whole MASTER operation
|
||||
and not only the mdio read/write common operation.
|
||||
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/qca8k.c | 68 +++++++++++++++++++++++++++++++++--------
|
||||
1 file changed, 55 insertions(+), 13 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/qca8k.c
|
||||
+++ b/drivers/net/dsa/qca8k.c
|
||||
@@ -628,8 +628,31 @@ qca8k_port_to_phy(int port)
|
||||
}
|
||||
|
||||
static int
|
||||
+qca8k_mdio_busy_wait(struct qca8k_priv *priv, u32 reg, u32 mask)
|
||||
+{
|
||||
+ u16 r1, r2, page;
|
||||
+ u32 val;
|
||||
+ int ret;
|
||||
+
|
||||
+ qca8k_split_addr(reg, &r1, &r2, &page);
|
||||
+
|
||||
+ ret = read_poll_timeout(qca8k_mii_read32, val, !(val & mask), 0,
|
||||
+ QCA8K_BUSY_WAIT_TIMEOUT * USEC_PER_MSEC, false,
|
||||
+ priv->bus, 0x10 | r2, r1);
|
||||
+
|
||||
+ /* Check if qca8k_read has failed for a different reason
|
||||
+ * before returnting -ETIMEDOUT
|
||||
+ */
|
||||
+ if (ret < 0 && val < 0)
|
||||
+ return val;
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
qca8k_mdio_write(struct qca8k_priv *priv, int port, u32 regnum, u16 data)
|
||||
{
|
||||
+ u16 r1, r2, page;
|
||||
u32 phy, val;
|
||||
int ret;
|
||||
|
||||
@@ -645,12 +668,21 @@ qca8k_mdio_write(struct qca8k_priv *priv
|
||||
QCA8K_MDIO_MASTER_REG_ADDR(regnum) |
|
||||
QCA8K_MDIO_MASTER_DATA(data);
|
||||
|
||||
- ret = qca8k_write(priv, QCA8K_MDIO_MASTER_CTRL, val);
|
||||
+ qca8k_split_addr(QCA8K_MDIO_MASTER_CTRL, &r1, &r2, &page);
|
||||
+
|
||||
+ mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED);
|
||||
+
|
||||
+ ret = qca8k_set_page(priv->bus, page);
|
||||
if (ret)
|
||||
- return ret;
|
||||
+ goto exit;
|
||||
+
|
||||
+ qca8k_mii_write32(priv->bus, 0x10 | r2, r1, val);
|
||||
|
||||
- ret = qca8k_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL,
|
||||
- QCA8K_MDIO_MASTER_BUSY);
|
||||
+ ret = qca8k_mdio_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL,
|
||||
+ QCA8K_MDIO_MASTER_BUSY);
|
||||
+
|
||||
+exit:
|
||||
+ mutex_unlock(&priv->bus->mdio_lock);
|
||||
|
||||
/* even if the busy_wait timeouts try to clear the MASTER_EN */
|
||||
qca8k_reg_clear(priv, QCA8K_MDIO_MASTER_CTRL,
|
||||
@@ -662,6 +694,7 @@ qca8k_mdio_write(struct qca8k_priv *priv
|
||||
static int
|
||||
qca8k_mdio_read(struct qca8k_priv *priv, int port, u32 regnum)
|
||||
{
|
||||
+ u16 r1, r2, page;
|
||||
u32 phy, val;
|
||||
int ret;
|
||||
|
||||
@@ -676,21 +709,30 @@ qca8k_mdio_read(struct qca8k_priv *priv,
|
||||
QCA8K_MDIO_MASTER_READ | QCA8K_MDIO_MASTER_PHY_ADDR(phy) |
|
||||
QCA8K_MDIO_MASTER_REG_ADDR(regnum);
|
||||
|
||||
- ret = qca8k_write(priv, QCA8K_MDIO_MASTER_CTRL, val);
|
||||
- if (ret)
|
||||
- return ret;
|
||||
+ qca8k_split_addr(QCA8K_MDIO_MASTER_CTRL, &r1, &r2, &page);
|
||||
+
|
||||
+ mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED);
|
||||
|
||||
- ret = qca8k_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL,
|
||||
- QCA8K_MDIO_MASTER_BUSY);
|
||||
+ ret = qca8k_set_page(priv->bus, page);
|
||||
if (ret)
|
||||
- return ret;
|
||||
+ goto exit;
|
||||
|
||||
- val = qca8k_read(priv, QCA8K_MDIO_MASTER_CTRL);
|
||||
- if (val < 0)
|
||||
- return val;
|
||||
+ qca8k_mii_write32(priv->bus, 0x10 | r2, r1, val);
|
||||
+
|
||||
+ ret = qca8k_mdio_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL,
|
||||
+ QCA8K_MDIO_MASTER_BUSY);
|
||||
+ if (ret)
|
||||
+ goto exit;
|
||||
|
||||
+ val = qca8k_mii_read32(priv->bus, 0x10 | r2, r1);
|
||||
val &= QCA8K_MDIO_MASTER_DATA_MASK;
|
||||
|
||||
+exit:
|
||||
+ mutex_unlock(&priv->bus->mdio_lock);
|
||||
+
|
||||
+ if (val >= 0)
|
||||
+ val &= QCA8K_MDIO_MASTER_DATA_MASK;
|
||||
+
|
||||
/* even if the busy_wait timeouts try to clear the MASTER_EN */
|
||||
qca8k_reg_clear(priv, QCA8K_MDIO_MASTER_CTRL,
|
||||
QCA8K_MDIO_MASTER_EN);
|
@ -0,0 +1,39 @@
|
||||
From 617960d72e93de0f3fa52407e2d39e8c43e73b0a Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Fri, 14 May 2021 23:00:09 +0200
|
||||
Subject: [PATCH] net: dsa: qca8k: enlarge mdio delay and timeout
|
||||
|
||||
The witch require some extra delay after setting page or the next
|
||||
read/write can use still use the old page. Add a delay after the
|
||||
set_page function to address this as it's done in QSDK legacy driver.
|
||||
Some timeouts were notice with VLAN and phy function, enlarge the
|
||||
mdio busy wait timeout to fix these problems.
|
||||
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/qca8k.c | 1 +
|
||||
drivers/net/dsa/qca8k.h | 2 +-
|
||||
2 files changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/dsa/qca8k.c
|
||||
+++ b/drivers/net/dsa/qca8k.c
|
||||
@@ -143,6 +143,7 @@ qca8k_set_page(struct mii_bus *bus, u16
|
||||
}
|
||||
|
||||
qca8k_current_page = page;
|
||||
+ usleep_range(1000, 2000);
|
||||
return 0;
|
||||
}
|
||||
|
||||
--- a/drivers/net/dsa/qca8k.h
|
||||
+++ b/drivers/net/dsa/qca8k.h
|
||||
@@ -20,7 +20,7 @@
|
||||
#define PHY_ID_QCA8337 0x004dd036
|
||||
#define QCA8K_ID_QCA8337 0x13
|
||||
|
||||
-#define QCA8K_BUSY_WAIT_TIMEOUT 20
|
||||
+#define QCA8K_BUSY_WAIT_TIMEOUT 2000
|
||||
|
||||
#define QCA8K_NUM_FDB_RECORDS 2048
|
||||
|
@ -0,0 +1,267 @@
|
||||
From 759bafb8a3226326ca357613bc90acf738f80c32 Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Fri, 14 May 2021 23:00:10 +0200
|
||||
Subject: [PATCH] net: dsa: qca8k: add support for internal phy and internal
|
||||
mdio
|
||||
|
||||
Add support to setup_mdio_bus for internal phy declaration. Introduce a
|
||||
flag to use the legacy port phy mapping by default and use the direct
|
||||
mapping if a mdio node is detected in the switch node. Register a
|
||||
dedicated mdio internal mdio bus to address the different mapping
|
||||
between port and phy if the mdio node is detected.
|
||||
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/qca8k.c | 112 +++++++++++++++++++++++++++++-----------
|
||||
drivers/net/dsa/qca8k.h | 1 +
|
||||
2 files changed, 83 insertions(+), 30 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/qca8k.c
|
||||
+++ b/drivers/net/dsa/qca8k.c
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <linux/netdevice.h>
|
||||
#include <net/dsa.h>
|
||||
#include <linux/of_net.h>
|
||||
+#include <linux/of_mdio.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/if_bridge.h>
|
||||
#include <linux/mdio.h>
|
||||
@@ -629,7 +630,7 @@ qca8k_port_to_phy(int port)
|
||||
}
|
||||
|
||||
static int
|
||||
-qca8k_mdio_busy_wait(struct qca8k_priv *priv, u32 reg, u32 mask)
|
||||
+qca8k_mdio_busy_wait(struct mii_bus *bus, u32 reg, u32 mask)
|
||||
{
|
||||
u16 r1, r2, page;
|
||||
u32 val;
|
||||
@@ -639,7 +640,7 @@ qca8k_mdio_busy_wait(struct qca8k_priv *
|
||||
|
||||
ret = read_poll_timeout(qca8k_mii_read32, val, !(val & mask), 0,
|
||||
QCA8K_BUSY_WAIT_TIMEOUT * USEC_PER_MSEC, false,
|
||||
- priv->bus, 0x10 | r2, r1);
|
||||
+ bus, 0x10 | r2, r1);
|
||||
|
||||
/* Check if qca8k_read has failed for a different reason
|
||||
* before returnting -ETIMEDOUT
|
||||
@@ -651,19 +652,16 @@ qca8k_mdio_busy_wait(struct qca8k_priv *
|
||||
}
|
||||
|
||||
static int
|
||||
-qca8k_mdio_write(struct qca8k_priv *priv, int port, u32 regnum, u16 data)
|
||||
+qca8k_mdio_write(struct mii_bus *salve_bus, int phy, int regnum, u16 data)
|
||||
{
|
||||
+ struct qca8k_priv *priv = salve_bus->priv;
|
||||
u16 r1, r2, page;
|
||||
- u32 phy, val;
|
||||
+ u32 val;
|
||||
int ret;
|
||||
|
||||
if (regnum >= QCA8K_MDIO_MASTER_MAX_REG)
|
||||
return -EINVAL;
|
||||
|
||||
- /* callee is responsible for not passing bad ports,
|
||||
- * but we still would like to make spills impossible.
|
||||
- */
|
||||
- phy = qca8k_port_to_phy(port) % PHY_MAX_ADDR;
|
||||
val = QCA8K_MDIO_MASTER_BUSY | QCA8K_MDIO_MASTER_EN |
|
||||
QCA8K_MDIO_MASTER_WRITE | QCA8K_MDIO_MASTER_PHY_ADDR(phy) |
|
||||
QCA8K_MDIO_MASTER_REG_ADDR(regnum) |
|
||||
@@ -679,33 +677,29 @@ qca8k_mdio_write(struct qca8k_priv *priv
|
||||
|
||||
qca8k_mii_write32(priv->bus, 0x10 | r2, r1, val);
|
||||
|
||||
- ret = qca8k_mdio_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL,
|
||||
+ ret = qca8k_mdio_busy_wait(priv->bus, QCA8K_MDIO_MASTER_CTRL,
|
||||
QCA8K_MDIO_MASTER_BUSY);
|
||||
|
||||
exit:
|
||||
- mutex_unlock(&priv->bus->mdio_lock);
|
||||
-
|
||||
/* even if the busy_wait timeouts try to clear the MASTER_EN */
|
||||
- qca8k_reg_clear(priv, QCA8K_MDIO_MASTER_CTRL,
|
||||
- QCA8K_MDIO_MASTER_EN);
|
||||
+ qca8k_mii_write32(priv->bus, 0x10 | r2, r1, 0);
|
||||
+
|
||||
+ mutex_unlock(&priv->bus->mdio_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
-qca8k_mdio_read(struct qca8k_priv *priv, int port, u32 regnum)
|
||||
+qca8k_mdio_read(struct mii_bus *salve_bus, int phy, int regnum)
|
||||
{
|
||||
+ struct qca8k_priv *priv = salve_bus->priv;
|
||||
u16 r1, r2, page;
|
||||
- u32 phy, val;
|
||||
+ u32 val;
|
||||
int ret;
|
||||
|
||||
if (regnum >= QCA8K_MDIO_MASTER_MAX_REG)
|
||||
return -EINVAL;
|
||||
|
||||
- /* callee is responsible for not passing bad ports,
|
||||
- * but we still would like to make spills impossible.
|
||||
- */
|
||||
- phy = qca8k_port_to_phy(port) % PHY_MAX_ADDR;
|
||||
val = QCA8K_MDIO_MASTER_BUSY | QCA8K_MDIO_MASTER_EN |
|
||||
QCA8K_MDIO_MASTER_READ | QCA8K_MDIO_MASTER_PHY_ADDR(phy) |
|
||||
QCA8K_MDIO_MASTER_REG_ADDR(regnum);
|
||||
@@ -720,24 +714,22 @@ qca8k_mdio_read(struct qca8k_priv *priv,
|
||||
|
||||
qca8k_mii_write32(priv->bus, 0x10 | r2, r1, val);
|
||||
|
||||
- ret = qca8k_mdio_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL,
|
||||
+ ret = qca8k_mdio_busy_wait(priv->bus, QCA8K_MDIO_MASTER_CTRL,
|
||||
QCA8K_MDIO_MASTER_BUSY);
|
||||
if (ret)
|
||||
goto exit;
|
||||
|
||||
val = qca8k_mii_read32(priv->bus, 0x10 | r2, r1);
|
||||
- val &= QCA8K_MDIO_MASTER_DATA_MASK;
|
||||
|
||||
exit:
|
||||
+ /* even if the busy_wait timeouts try to clear the MASTER_EN */
|
||||
+ qca8k_mii_write32(priv->bus, 0x10 | r2, r1, 0);
|
||||
+
|
||||
mutex_unlock(&priv->bus->mdio_lock);
|
||||
|
||||
if (val >= 0)
|
||||
val &= QCA8K_MDIO_MASTER_DATA_MASK;
|
||||
|
||||
- /* even if the busy_wait timeouts try to clear the MASTER_EN */
|
||||
- qca8k_reg_clear(priv, QCA8K_MDIO_MASTER_CTRL,
|
||||
- QCA8K_MDIO_MASTER_EN);
|
||||
-
|
||||
return val;
|
||||
}
|
||||
|
||||
@@ -746,7 +738,14 @@ qca8k_phy_write(struct dsa_switch *ds, i
|
||||
{
|
||||
struct qca8k_priv *priv = ds->priv;
|
||||
|
||||
- return qca8k_mdio_write(priv, port, regnum, data);
|
||||
+ /* Check if the legacy mapping should be used and the
|
||||
+ * port is not correctly mapped to the right PHY in the
|
||||
+ * devicetree
|
||||
+ */
|
||||
+ if (priv->legacy_phy_port_mapping)
|
||||
+ port = qca8k_port_to_phy(port) % PHY_MAX_ADDR;
|
||||
+
|
||||
+ return qca8k_mdio_write(priv->bus, port, regnum, data);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -755,7 +754,14 @@ qca8k_phy_read(struct dsa_switch *ds, in
|
||||
struct qca8k_priv *priv = ds->priv;
|
||||
int ret;
|
||||
|
||||
- ret = qca8k_mdio_read(priv, port, regnum);
|
||||
+ /* Check if the legacy mapping should be used and the
|
||||
+ * port is not correctly mapped to the right PHY in the
|
||||
+ * devicetree
|
||||
+ */
|
||||
+ if (priv->legacy_phy_port_mapping)
|
||||
+ port = qca8k_port_to_phy(port) % PHY_MAX_ADDR;
|
||||
+
|
||||
+ ret = qca8k_mdio_read(priv->bus, port, regnum);
|
||||
|
||||
if (ret < 0)
|
||||
return 0xffff;
|
||||
@@ -764,10 +770,37 @@ qca8k_phy_read(struct dsa_switch *ds, in
|
||||
}
|
||||
|
||||
static int
|
||||
+qca8k_mdio_register(struct qca8k_priv *priv, struct device_node *mdio)
|
||||
+{
|
||||
+ struct dsa_switch *ds = priv->ds;
|
||||
+ struct mii_bus *bus;
|
||||
+
|
||||
+ bus = devm_mdiobus_alloc(ds->dev);
|
||||
+
|
||||
+ if (!bus)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ bus->priv = (void *)priv;
|
||||
+ bus->name = "qca8k slave mii";
|
||||
+ bus->read = qca8k_mdio_read;
|
||||
+ bus->write = qca8k_mdio_write;
|
||||
+ snprintf(bus->id, MII_BUS_ID_SIZE, "qca8k-%d",
|
||||
+ ds->index);
|
||||
+
|
||||
+ bus->parent = ds->dev;
|
||||
+ bus->phy_mask = ~ds->phys_mii_mask;
|
||||
+
|
||||
+ ds->slave_mii_bus = bus;
|
||||
+
|
||||
+ return devm_of_mdiobus_register(priv->dev, bus, mdio);
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
qca8k_setup_mdio_bus(struct qca8k_priv *priv)
|
||||
{
|
||||
u32 internal_mdio_mask = 0, external_mdio_mask = 0, reg;
|
||||
- struct device_node *ports, *port;
|
||||
+ struct device_node *ports, *port, *mdio;
|
||||
+ phy_interface_t mode;
|
||||
int err;
|
||||
|
||||
ports = of_get_child_by_name(priv->dev->of_node, "ports");
|
||||
@@ -788,7 +821,10 @@ qca8k_setup_mdio_bus(struct qca8k_priv *
|
||||
if (!dsa_is_user_port(priv->ds, reg))
|
||||
continue;
|
||||
|
||||
- if (of_property_read_bool(port, "phy-handle"))
|
||||
+ of_get_phy_mode(port, &mode);
|
||||
+
|
||||
+ if (of_property_read_bool(port, "phy-handle") &&
|
||||
+ mode != PHY_INTERFACE_MODE_INTERNAL)
|
||||
external_mdio_mask |= BIT(reg);
|
||||
else
|
||||
internal_mdio_mask |= BIT(reg);
|
||||
@@ -825,8 +861,23 @@ qca8k_setup_mdio_bus(struct qca8k_priv *
|
||||
QCA8K_MDIO_MASTER_EN);
|
||||
}
|
||||
|
||||
+ /* Check if the devicetree declare the port:phy mapping */
|
||||
+ mdio = of_get_child_by_name(priv->dev->of_node, "mdio");
|
||||
+ if (of_device_is_available(mdio)) {
|
||||
+ err = qca8k_mdio_register(priv, mdio);
|
||||
+ if (err)
|
||||
+ of_node_put(mdio);
|
||||
+
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ /* If a mapping can't be found the legacy mapping is used,
|
||||
+ * using the qca8k_port_to_phy function
|
||||
+ */
|
||||
+ priv->legacy_phy_port_mapping = true;
|
||||
priv->ops.phy_read = qca8k_phy_read;
|
||||
priv->ops.phy_write = qca8k_phy_write;
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1212,7 +1263,8 @@ qca8k_phylink_validate(struct dsa_switch
|
||||
case 5:
|
||||
/* Internal PHY */
|
||||
if (state->interface != PHY_INTERFACE_MODE_NA &&
|
||||
- state->interface != PHY_INTERFACE_MODE_GMII)
|
||||
+ state->interface != PHY_INTERFACE_MODE_GMII &&
|
||||
+ state->interface != PHY_INTERFACE_MODE_INTERNAL)
|
||||
goto unsupported;
|
||||
break;
|
||||
case 6: /* 2nd CPU port / external PHY */
|
||||
--- a/drivers/net/dsa/qca8k.h
|
||||
+++ b/drivers/net/dsa/qca8k.h
|
||||
@@ -255,6 +255,7 @@ struct qca8k_priv {
|
||||
u8 switch_revision;
|
||||
u8 rgmii_tx_delay;
|
||||
u8 rgmii_rx_delay;
|
||||
+ bool legacy_phy_port_mapping;
|
||||
struct regmap *regmap;
|
||||
struct mii_bus *bus;
|
||||
struct ar8xxx_port_status port_sts[QCA8K_NUM_PORTS];
|
@ -0,0 +1,93 @@
|
||||
From 0c994a28e7518f098c84a3049cb2915780db873a Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Fri, 14 May 2021 23:00:11 +0200
|
||||
Subject: [PATCH] devicetree: bindings: dsa: qca8k: Document internal mdio
|
||||
definition
|
||||
|
||||
Document new way of declare mapping of internal PHY to port.
|
||||
The new implementation directly declare the PHY connected to the port
|
||||
by adding a node in the switch node. The driver detect this and register
|
||||
an internal mdiobus using the mapping defined in the mdio node.
|
||||
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Reviewed-by: Rob Herring <robh@kernel.org>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
.../devicetree/bindings/net/dsa/qca8k.txt | 39 +++++++++++++++++++
|
||||
1 file changed, 39 insertions(+)
|
||||
|
||||
--- a/Documentation/devicetree/bindings/net/dsa/qca8k.txt
|
||||
+++ b/Documentation/devicetree/bindings/net/dsa/qca8k.txt
|
||||
@@ -21,6 +21,10 @@ described in dsa/dsa.txt. If the QCA8K s
|
||||
mdio-bus each subnode describing a port needs to have a valid phandle
|
||||
referencing the internal PHY it is connected to. This is because there's no
|
||||
N:N mapping of port and PHY id.
|
||||
+To declare the internal mdio-bus configuration, declare a mdio node in the
|
||||
+switch node and declare the phandle for the port referencing the internal
|
||||
+PHY is connected to. In this config a internal mdio-bus is registered and
|
||||
+the mdio MASTER is used as communication.
|
||||
|
||||
Don't use mixed external and internal mdio-bus configurations, as this is
|
||||
not supported by the hardware.
|
||||
@@ -150,26 +154,61 @@ for the internal master mdio-bus configu
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
label = "lan1";
|
||||
+ phy-mode = "internal";
|
||||
+ phy-handle = <&phy_port1>;
|
||||
};
|
||||
|
||||
port@2 {
|
||||
reg = <2>;
|
||||
label = "lan2";
|
||||
+ phy-mode = "internal";
|
||||
+ phy-handle = <&phy_port2>;
|
||||
};
|
||||
|
||||
port@3 {
|
||||
reg = <3>;
|
||||
label = "lan3";
|
||||
+ phy-mode = "internal";
|
||||
+ phy-handle = <&phy_port3>;
|
||||
};
|
||||
|
||||
port@4 {
|
||||
reg = <4>;
|
||||
label = "lan4";
|
||||
+ phy-mode = "internal";
|
||||
+ phy-handle = <&phy_port4>;
|
||||
};
|
||||
|
||||
port@5 {
|
||||
reg = <5>;
|
||||
label = "wan";
|
||||
+ phy-mode = "internal";
|
||||
+ phy-handle = <&phy_port5>;
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ mdio {
|
||||
+ #address-cells = <1>;
|
||||
+ #size-cells = <0>;
|
||||
+
|
||||
+ phy_port1: phy@0 {
|
||||
+ reg = <0>;
|
||||
+ };
|
||||
+
|
||||
+ phy_port2: phy@1 {
|
||||
+ reg = <1>;
|
||||
+ };
|
||||
+
|
||||
+ phy_port3: phy@2 {
|
||||
+ reg = <2>;
|
||||
+ };
|
||||
+
|
||||
+ phy_port4: phy@3 {
|
||||
+ reg = <3>;
|
||||
+ };
|
||||
+
|
||||
+ phy_port5: phy@4 {
|
||||
+ reg = <4>;
|
||||
};
|
||||
};
|
||||
};
|
@ -0,0 +1,95 @@
|
||||
From b7ebac354d54f1657bb89b7a7ca149db50203e6a Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Fri, 14 May 2021 23:00:12 +0200
|
||||
Subject: [PATCH] net: dsa: qca8k: improve internal mdio read/write bus access
|
||||
|
||||
Improve the internal mdio read/write bus access by caching the value
|
||||
without accessing it for every read/write.
|
||||
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/qca8k.c | 28 +++++++++++++++-------------
|
||||
1 file changed, 15 insertions(+), 13 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/qca8k.c
|
||||
+++ b/drivers/net/dsa/qca8k.c
|
||||
@@ -655,6 +655,7 @@ static int
|
||||
qca8k_mdio_write(struct mii_bus *salve_bus, int phy, int regnum, u16 data)
|
||||
{
|
||||
struct qca8k_priv *priv = salve_bus->priv;
|
||||
+ struct mii_bus *bus = priv->bus;
|
||||
u16 r1, r2, page;
|
||||
u32 val;
|
||||
int ret;
|
||||
@@ -669,22 +670,22 @@ qca8k_mdio_write(struct mii_bus *salve_b
|
||||
|
||||
qca8k_split_addr(QCA8K_MDIO_MASTER_CTRL, &r1, &r2, &page);
|
||||
|
||||
- mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED);
|
||||
+ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
|
||||
|
||||
- ret = qca8k_set_page(priv->bus, page);
|
||||
+ ret = qca8k_set_page(bus, page);
|
||||
if (ret)
|
||||
goto exit;
|
||||
|
||||
- qca8k_mii_write32(priv->bus, 0x10 | r2, r1, val);
|
||||
+ qca8k_mii_write32(bus, 0x10 | r2, r1, val);
|
||||
|
||||
- ret = qca8k_mdio_busy_wait(priv->bus, QCA8K_MDIO_MASTER_CTRL,
|
||||
+ ret = qca8k_mdio_busy_wait(bus, QCA8K_MDIO_MASTER_CTRL,
|
||||
QCA8K_MDIO_MASTER_BUSY);
|
||||
|
||||
exit:
|
||||
/* even if the busy_wait timeouts try to clear the MASTER_EN */
|
||||
- qca8k_mii_write32(priv->bus, 0x10 | r2, r1, 0);
|
||||
+ qca8k_mii_write32(bus, 0x10 | r2, r1, 0);
|
||||
|
||||
- mutex_unlock(&priv->bus->mdio_lock);
|
||||
+ mutex_unlock(&bus->mdio_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -693,6 +694,7 @@ static int
|
||||
qca8k_mdio_read(struct mii_bus *salve_bus, int phy, int regnum)
|
||||
{
|
||||
struct qca8k_priv *priv = salve_bus->priv;
|
||||
+ struct mii_bus *bus = priv->bus;
|
||||
u16 r1, r2, page;
|
||||
u32 val;
|
||||
int ret;
|
||||
@@ -706,26 +708,26 @@ qca8k_mdio_read(struct mii_bus *salve_bu
|
||||
|
||||
qca8k_split_addr(QCA8K_MDIO_MASTER_CTRL, &r1, &r2, &page);
|
||||
|
||||
- mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED);
|
||||
+ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
|
||||
|
||||
- ret = qca8k_set_page(priv->bus, page);
|
||||
+ ret = qca8k_set_page(bus, page);
|
||||
if (ret)
|
||||
goto exit;
|
||||
|
||||
- qca8k_mii_write32(priv->bus, 0x10 | r2, r1, val);
|
||||
+ qca8k_mii_write32(bus, 0x10 | r2, r1, val);
|
||||
|
||||
- ret = qca8k_mdio_busy_wait(priv->bus, QCA8K_MDIO_MASTER_CTRL,
|
||||
+ ret = qca8k_mdio_busy_wait(bus, QCA8K_MDIO_MASTER_CTRL,
|
||||
QCA8K_MDIO_MASTER_BUSY);
|
||||
if (ret)
|
||||
goto exit;
|
||||
|
||||
- val = qca8k_mii_read32(priv->bus, 0x10 | r2, r1);
|
||||
+ val = qca8k_mii_read32(bus, 0x10 | r2, r1);
|
||||
|
||||
exit:
|
||||
/* even if the busy_wait timeouts try to clear the MASTER_EN */
|
||||
- qca8k_mii_write32(priv->bus, 0x10 | r2, r1, 0);
|
||||
+ qca8k_mii_write32(bus, 0x10 | r2, r1, 0);
|
||||
|
||||
- mutex_unlock(&priv->bus->mdio_lock);
|
||||
+ mutex_unlock(&bus->mdio_lock);
|
||||
|
||||
if (val >= 0)
|
||||
val &= QCA8K_MDIO_MASTER_DATA_MASK;
|
@ -0,0 +1,48 @@
|
||||
From a46aec02bc06ac2c33f326339e4ef88c735dc30d Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Fri, 14 May 2021 23:00:13 +0200
|
||||
Subject: [PATCH] net: dsa: qca8k: pass switch_revision info to phy dev_flags
|
||||
|
||||
Define get_phy_flags to pass switch_Revision needed to tweak the
|
||||
internal PHY with debug values based on the revision.
|
||||
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/qca8k.c | 17 +++++++++++++++++
|
||||
1 file changed, 17 insertions(+)
|
||||
|
||||
--- a/drivers/net/dsa/qca8k.c
|
||||
+++ b/drivers/net/dsa/qca8k.c
|
||||
@@ -1740,6 +1740,22 @@ qca8k_port_vlan_del(struct dsa_switch *d
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static u32 qca8k_get_phy_flags(struct dsa_switch *ds, int port)
|
||||
+{
|
||||
+ struct qca8k_priv *priv = ds->priv;
|
||||
+
|
||||
+ /* Communicate to the phy internal driver the switch revision.
|
||||
+ * Based on the switch revision different values needs to be
|
||||
+ * set to the dbg and mmd reg on the phy.
|
||||
+ * The first 2 bit are used to communicate the switch revision
|
||||
+ * to the phy driver.
|
||||
+ */
|
||||
+ if (port > 0 && port < 6)
|
||||
+ return priv->switch_revision;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static enum dsa_tag_protocol
|
||||
qca8k_get_tag_protocol(struct dsa_switch *ds, int port,
|
||||
enum dsa_tag_protocol mp)
|
||||
@@ -1774,6 +1790,7 @@ static const struct dsa_switch_ops qca8k
|
||||
.phylink_mac_config = qca8k_phylink_mac_config,
|
||||
.phylink_mac_link_down = qca8k_phylink_mac_link_down,
|
||||
.phylink_mac_link_up = qca8k_phylink_mac_link_up,
|
||||
+ .get_phy_flags = qca8k_get_phy_flags,
|
||||
};
|
||||
|
||||
static int qca8k_read_switch_id(struct qca8k_priv *priv)
|
@ -0,0 +1,229 @@
|
||||
From 272833b9b3b3969be7a91839121d86662c8c4253 Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Fri, 14 May 2021 23:00:15 +0200
|
||||
Subject: [PATCH] net: phy: add support for qca8k switch internal PHY in at803x
|
||||
|
||||
Since the at803x share the same regs, it's assumed they are based on the
|
||||
same implementation. Make it part of the at803x PHY driver to skip
|
||||
having redudant code.
|
||||
Add initial support for qca8k internal PHYs. The internal PHYs requires
|
||||
special mmd and debug values to be set based on the switch revision
|
||||
passwd using the dev_flags. Supports output of idle, receive and eee_wake
|
||||
errors stats.
|
||||
Some debug values sets can't be translated as the documentation lacks any
|
||||
reference about them.
|
||||
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/phy/Kconfig | 5 +-
|
||||
drivers/net/phy/at803x.c | 132 ++++++++++++++++++++++++++++++++++++++-
|
||||
2 files changed, 134 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/Kconfig
|
||||
+++ b/drivers/net/phy/Kconfig
|
||||
@@ -235,10 +235,11 @@ config NXP_TJA11XX_PHY
|
||||
Currently supports the NXP TJA1100 and TJA1101 PHY.
|
||||
|
||||
config AT803X_PHY
|
||||
- tristate "Qualcomm Atheros AR803X PHYs"
|
||||
+ tristate "Qualcomm Atheros AR803X PHYs and QCA833x PHYs"
|
||||
depends on REGULATOR
|
||||
help
|
||||
- Currently supports the AR8030, AR8031, AR8033 and AR8035 model
|
||||
+ Currently supports the AR8030, AR8031, AR8033, AR8035 and internal
|
||||
+ QCA8337(Internal qca8k PHY) model
|
||||
|
||||
config QSEMI_PHY
|
||||
tristate "Quality Semiconductor PHYs"
|
||||
--- a/drivers/net/phy/at803x.c
|
||||
+++ b/drivers/net/phy/at803x.c
|
||||
@@ -92,10 +92,16 @@
|
||||
#define AT803X_DEBUG_REG_5 0x05
|
||||
#define AT803X_DEBUG_TX_CLK_DLY_EN BIT(8)
|
||||
|
||||
+#define AT803X_DEBUG_REG_3C 0x3C
|
||||
+
|
||||
+#define AT803X_DEBUG_REG_3D 0x3D
|
||||
+
|
||||
#define AT803X_DEBUG_REG_1F 0x1F
|
||||
#define AT803X_DEBUG_PLL_ON BIT(2)
|
||||
#define AT803X_DEBUG_RGMII_1V8 BIT(3)
|
||||
|
||||
+#define MDIO_AZ_DEBUG 0x800D
|
||||
+
|
||||
/* AT803x supports either the XTAL input pad, an internal PLL or the
|
||||
* DSP as clock reference for the clock output pad. The XTAL reference
|
||||
* is only used for 25 MHz output, all other frequencies need the PLL.
|
||||
@@ -142,10 +148,34 @@
|
||||
#define AT803X_PAGE_FIBER 0
|
||||
#define AT803X_PAGE_COPPER 1
|
||||
|
||||
+#define QCA8327_PHY_ID 0x004dd034
|
||||
+#define QCA8337_PHY_ID 0x004dd036
|
||||
+#define QCA8K_PHY_ID_MASK 0xffffffff
|
||||
+
|
||||
+#define QCA8K_DEVFLAGS_REVISION_MASK GENMASK(2, 0)
|
||||
+
|
||||
MODULE_DESCRIPTION("Qualcomm Atheros AR803x PHY driver");
|
||||
MODULE_AUTHOR("Matus Ujhelyi");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
+enum stat_access_type {
|
||||
+ PHY,
|
||||
+ MMD
|
||||
+};
|
||||
+
|
||||
+struct at803x_hw_stat {
|
||||
+ const char *string;
|
||||
+ u8 reg;
|
||||
+ u32 mask;
|
||||
+ enum stat_access_type access_type;
|
||||
+};
|
||||
+
|
||||
+static struct at803x_hw_stat at803x_hw_stats[] = {
|
||||
+ { "phy_idle_errors", 0xa, GENMASK(7, 0), PHY},
|
||||
+ { "phy_receive_errors", 0x15, GENMASK(15, 0), PHY},
|
||||
+ { "eee_wake_errors", 0x16, GENMASK(15, 0), MMD},
|
||||
+};
|
||||
+
|
||||
struct at803x_priv {
|
||||
int flags;
|
||||
#define AT803X_KEEP_PLL_ENABLED BIT(0) /* don't turn off internal PLL */
|
||||
@@ -154,6 +184,7 @@ struct at803x_priv {
|
||||
struct regulator_dev *vddio_rdev;
|
||||
struct regulator_dev *vddh_rdev;
|
||||
struct regulator *vddio;
|
||||
+ u64 stats[ARRAY_SIZE(at803x_hw_stats)];
|
||||
};
|
||||
|
||||
struct at803x_context {
|
||||
@@ -165,6 +196,17 @@ struct at803x_context {
|
||||
u16 led_control;
|
||||
};
|
||||
|
||||
+static int at803x_debug_reg_write(struct phy_device *phydev, u16 reg, u16 data)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = phy_write(phydev, AT803X_DEBUG_ADDR, reg);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ return phy_write(phydev, AT803X_DEBUG_DATA, data);
|
||||
+}
|
||||
+
|
||||
static int at803x_debug_reg_read(struct phy_device *phydev, u16 reg)
|
||||
{
|
||||
int ret;
|
||||
@@ -327,6 +369,53 @@ static void at803x_get_wol(struct phy_de
|
||||
wol->wolopts |= WAKE_MAGIC;
|
||||
}
|
||||
|
||||
+static int at803x_get_sset_count(struct phy_device *phydev)
|
||||
+{
|
||||
+ return ARRAY_SIZE(at803x_hw_stats);
|
||||
+}
|
||||
+
|
||||
+static void at803x_get_strings(struct phy_device *phydev, u8 *data)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(at803x_hw_stats); i++) {
|
||||
+ strscpy(data + i * ETH_GSTRING_LEN,
|
||||
+ at803x_hw_stats[i].string, ETH_GSTRING_LEN);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static u64 at803x_get_stat(struct phy_device *phydev, int i)
|
||||
+{
|
||||
+ struct at803x_hw_stat stat = at803x_hw_stats[i];
|
||||
+ struct at803x_priv *priv = phydev->priv;
|
||||
+ int val;
|
||||
+ u64 ret;
|
||||
+
|
||||
+ if (stat.access_type == MMD)
|
||||
+ val = phy_read_mmd(phydev, MDIO_MMD_PCS, stat.reg);
|
||||
+ else
|
||||
+ val = phy_read(phydev, stat.reg);
|
||||
+
|
||||
+ if (val < 0) {
|
||||
+ ret = U64_MAX;
|
||||
+ } else {
|
||||
+ val = val & stat.mask;
|
||||
+ priv->stats[i] += val;
|
||||
+ ret = priv->stats[i];
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static void at803x_get_stats(struct phy_device *phydev,
|
||||
+ struct ethtool_stats *stats, u64 *data)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(at803x_hw_stats); i++)
|
||||
+ data[i] = at803x_get_stat(phydev, i);
|
||||
+}
|
||||
+
|
||||
static int at803x_suspend(struct phy_device *phydev)
|
||||
{
|
||||
int value;
|
||||
@@ -1102,6 +1191,34 @@ static int at803x_cable_test_start(struc
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int qca83xx_config_init(struct phy_device *phydev)
|
||||
+{
|
||||
+ u8 switch_revision;
|
||||
+
|
||||
+ switch_revision = phydev->dev_flags & QCA8K_DEVFLAGS_REVISION_MASK;
|
||||
+
|
||||
+ switch (switch_revision) {
|
||||
+ case 1:
|
||||
+ /* For 100M waveform */
|
||||
+ at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_0, 0x02ea);
|
||||
+ /* Turn on Gigabit clock */
|
||||
+ at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_3D, 0x68a0);
|
||||
+ break;
|
||||
+
|
||||
+ case 2:
|
||||
+ phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0x0);
|
||||
+ fallthrough;
|
||||
+ case 4:
|
||||
+ phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_AZ_DEBUG, 0x803f);
|
||||
+ at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_3D, 0x6860);
|
||||
+ at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_5, 0x2c46);
|
||||
+ at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_3C, 0x6000);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static struct phy_driver at803x_driver[] = {
|
||||
{
|
||||
/* Qualcomm Atheros AR8035 */
|
||||
@@ -1198,7 +1315,20 @@ static struct phy_driver at803x_driver[]
|
||||
.read_status = at803x_read_status,
|
||||
.soft_reset = genphy_soft_reset,
|
||||
.config_aneg = at803x_config_aneg,
|
||||
-} };
|
||||
+}, {
|
||||
+ /* QCA8337 */
|
||||
+ .phy_id = QCA8337_PHY_ID,
|
||||
+ .phy_id_mask = QCA8K_PHY_ID_MASK,
|
||||
+ .name = "QCA PHY 8337",
|
||||
+ /* PHY_GBIT_FEATURES */
|
||||
+ .probe = at803x_probe,
|
||||
+ .flags = PHY_IS_INTERNAL,
|
||||
+ .config_init = qca83xx_config_init,
|
||||
+ .soft_reset = genphy_soft_reset,
|
||||
+ .get_sset_count = at803x_get_sset_count,
|
||||
+ .get_strings = at803x_get_strings,
|
||||
+ .get_stats = at803x_get_stats,
|
||||
+}, };
|
||||
|
||||
module_phy_driver(at803x_driver);
|
||||
|
@ -0,0 +1,64 @@
|
||||
From 0d56e5c191b197e1d30a0a4c92628836dafced0f Mon Sep 17 00:00:00 2001
|
||||
From: Wei Yongjun <weiyongjun1@huawei.com>
|
||||
Date: Tue, 18 May 2021 11:24:13 +0000
|
||||
Subject: [PATCH] net: dsa: qca8k: fix missing unlock on error in
|
||||
qca8k_vlan_(add|del)
|
||||
|
||||
Add the missing unlock before return from function qca8k_vlan_add()
|
||||
and qca8k_vlan_del() in the error handling case.
|
||||
|
||||
Fixes: 028f5f8ef44f ("net: dsa: qca8k: handle error with qca8k_read operation")
|
||||
Reported-by: Hulk Robot <hulkci@huawei.com>
|
||||
Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com>
|
||||
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/qca8k.c | 16 ++++++++++------
|
||||
1 file changed, 10 insertions(+), 6 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/qca8k.c
|
||||
+++ b/drivers/net/dsa/qca8k.c
|
||||
@@ -506,8 +506,10 @@ qca8k_vlan_add(struct qca8k_priv *priv,
|
||||
goto out;
|
||||
|
||||
reg = qca8k_read(priv, QCA8K_REG_VTU_FUNC0);
|
||||
- if (reg < 0)
|
||||
- return reg;
|
||||
+ if (reg < 0) {
|
||||
+ ret = reg;
|
||||
+ goto out;
|
||||
+ }
|
||||
reg |= QCA8K_VTU_FUNC0_VALID | QCA8K_VTU_FUNC0_IVL_EN;
|
||||
reg &= ~(QCA8K_VTU_FUNC0_EG_MODE_MASK << QCA8K_VTU_FUNC0_EG_MODE_S(port));
|
||||
if (untagged)
|
||||
@@ -519,7 +521,7 @@ qca8k_vlan_add(struct qca8k_priv *priv,
|
||||
|
||||
ret = qca8k_write(priv, QCA8K_REG_VTU_FUNC0, reg);
|
||||
if (ret)
|
||||
- return ret;
|
||||
+ goto out;
|
||||
ret = qca8k_vlan_access(priv, QCA8K_VLAN_LOAD, vid);
|
||||
|
||||
out:
|
||||
@@ -541,8 +543,10 @@ qca8k_vlan_del(struct qca8k_priv *priv,
|
||||
goto out;
|
||||
|
||||
reg = qca8k_read(priv, QCA8K_REG_VTU_FUNC0);
|
||||
- if (reg < 0)
|
||||
- return reg;
|
||||
+ if (reg < 0) {
|
||||
+ ret = reg;
|
||||
+ goto out;
|
||||
+ }
|
||||
reg &= ~(3 << QCA8K_VTU_FUNC0_EG_MODE_S(port));
|
||||
reg |= QCA8K_VTU_FUNC0_EG_MODE_NOT <<
|
||||
QCA8K_VTU_FUNC0_EG_MODE_S(port);
|
||||
@@ -564,7 +568,7 @@ qca8k_vlan_del(struct qca8k_priv *priv,
|
||||
} else {
|
||||
ret = qca8k_write(priv, QCA8K_REG_VTU_FUNC0, reg);
|
||||
if (ret)
|
||||
- return ret;
|
||||
+ goto out;
|
||||
ret = qca8k_vlan_access(priv, QCA8K_VLAN_LOAD, vid);
|
||||
}
|
||||
|
@ -0,0 +1,348 @@
|
||||
From 7c9896e37807862e276064dd9331860f5d27affc Mon Sep 17 00:00:00 2001
|
||||
From: Yang Yingliang <yangyingliang@huawei.com>
|
||||
Date: Sat, 29 May 2021 11:04:38 +0800
|
||||
Subject: [PATCH] net: dsa: qca8k: check return value of read functions
|
||||
correctly
|
||||
|
||||
Current return type of qca8k_mii_read32() and qca8k_read() are
|
||||
unsigned, it can't be negative, so the return value check is
|
||||
unuseful. For check the return value correctly, change return
|
||||
type of the read functions and add a output parameter to store
|
||||
the read value.
|
||||
|
||||
Signed-off-by: Yang Yingliang <yangyingliang@huawei.com>
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/dsa/qca8k.c | 130 +++++++++++++++++++---------------------
|
||||
1 file changed, 60 insertions(+), 70 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/qca8k.c
|
||||
+++ b/drivers/net/dsa/qca8k.c
|
||||
@@ -89,26 +89,26 @@ qca8k_split_addr(u32 regaddr, u16 *r1, u
|
||||
*page = regaddr & 0x3ff;
|
||||
}
|
||||
|
||||
-static u32
|
||||
-qca8k_mii_read32(struct mii_bus *bus, int phy_id, u32 regnum)
|
||||
+static int
|
||||
+qca8k_mii_read32(struct mii_bus *bus, int phy_id, u32 regnum, u32 *val)
|
||||
{
|
||||
- u32 val;
|
||||
int ret;
|
||||
|
||||
ret = bus->read(bus, phy_id, regnum);
|
||||
if (ret >= 0) {
|
||||
- val = ret;
|
||||
+ *val = ret;
|
||||
ret = bus->read(bus, phy_id, regnum + 1);
|
||||
- val |= ret << 16;
|
||||
+ *val |= ret << 16;
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
dev_err_ratelimited(&bus->dev,
|
||||
"failed to read qca8k 32bit register\n");
|
||||
+ *val = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
- return val;
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -148,26 +148,26 @@ qca8k_set_page(struct mii_bus *bus, u16
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static u32
|
||||
-qca8k_read(struct qca8k_priv *priv, u32 reg)
|
||||
+static int
|
||||
+qca8k_read(struct qca8k_priv *priv, u32 reg, u32 *val)
|
||||
{
|
||||
struct mii_bus *bus = priv->bus;
|
||||
u16 r1, r2, page;
|
||||
- u32 val;
|
||||
+ int ret;
|
||||
|
||||
qca8k_split_addr(reg, &r1, &r2, &page);
|
||||
|
||||
mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
|
||||
|
||||
- val = qca8k_set_page(bus, page);
|
||||
- if (val < 0)
|
||||
+ ret = qca8k_set_page(bus, page);
|
||||
+ if (ret < 0)
|
||||
goto exit;
|
||||
|
||||
- val = qca8k_mii_read32(bus, 0x10 | r2, r1);
|
||||
+ ret = qca8k_mii_read32(bus, 0x10 | r2, r1, val);
|
||||
|
||||
exit:
|
||||
mutex_unlock(&bus->mdio_lock);
|
||||
- return val;
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -208,11 +208,9 @@ qca8k_rmw(struct qca8k_priv *priv, u32 r
|
||||
if (ret < 0)
|
||||
goto exit;
|
||||
|
||||
- val = qca8k_mii_read32(bus, 0x10 | r2, r1);
|
||||
- if (val < 0) {
|
||||
- ret = val;
|
||||
+ ret = qca8k_mii_read32(bus, 0x10 | r2, r1, &val);
|
||||
+ if (ret < 0)
|
||||
goto exit;
|
||||
- }
|
||||
|
||||
val &= ~mask;
|
||||
val |= write_val;
|
||||
@@ -240,15 +238,8 @@ static int
|
||||
qca8k_regmap_read(void *ctx, uint32_t reg, uint32_t *val)
|
||||
{
|
||||
struct qca8k_priv *priv = (struct qca8k_priv *)ctx;
|
||||
- int ret;
|
||||
-
|
||||
- ret = qca8k_read(priv, reg);
|
||||
- if (ret < 0)
|
||||
- return ret;
|
||||
-
|
||||
- *val = ret;
|
||||
|
||||
- return 0;
|
||||
+ return qca8k_read(priv, reg, val);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -296,18 +287,18 @@ static struct regmap_config qca8k_regmap
|
||||
static int
|
||||
qca8k_busy_wait(struct qca8k_priv *priv, u32 reg, u32 mask)
|
||||
{
|
||||
+ int ret, ret1;
|
||||
u32 val;
|
||||
- int ret;
|
||||
|
||||
- ret = read_poll_timeout(qca8k_read, val, !(val & mask),
|
||||
+ ret = read_poll_timeout(qca8k_read, ret1, !(val & mask),
|
||||
0, QCA8K_BUSY_WAIT_TIMEOUT * USEC_PER_MSEC, false,
|
||||
- priv, reg);
|
||||
+ priv, reg, &val);
|
||||
|
||||
/* Check if qca8k_read has failed for a different reason
|
||||
* before returning -ETIMEDOUT
|
||||
*/
|
||||
- if (ret < 0 && val < 0)
|
||||
- return val;
|
||||
+ if (ret < 0 && ret1 < 0)
|
||||
+ return ret1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -316,13 +307,13 @@ static int
|
||||
qca8k_fdb_read(struct qca8k_priv *priv, struct qca8k_fdb *fdb)
|
||||
{
|
||||
u32 reg[4], val;
|
||||
- int i;
|
||||
+ int i, ret;
|
||||
|
||||
/* load the ARL table into an array */
|
||||
for (i = 0; i < 4; i++) {
|
||||
- val = qca8k_read(priv, QCA8K_REG_ATU_DATA0 + (i * 4));
|
||||
- if (val < 0)
|
||||
- return val;
|
||||
+ ret = qca8k_read(priv, QCA8K_REG_ATU_DATA0 + (i * 4), &val);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
|
||||
reg[i] = val;
|
||||
}
|
||||
@@ -396,9 +387,9 @@ qca8k_fdb_access(struct qca8k_priv *priv
|
||||
|
||||
/* Check for table full violation when adding an entry */
|
||||
if (cmd == QCA8K_FDB_LOAD) {
|
||||
- reg = qca8k_read(priv, QCA8K_REG_ATU_FUNC);
|
||||
- if (reg < 0)
|
||||
- return reg;
|
||||
+ ret = qca8k_read(priv, QCA8K_REG_ATU_FUNC, ®);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
if (reg & QCA8K_ATU_FUNC_FULL)
|
||||
return -1;
|
||||
}
|
||||
@@ -477,9 +468,9 @@ qca8k_vlan_access(struct qca8k_priv *pri
|
||||
|
||||
/* Check for table full violation when adding an entry */
|
||||
if (cmd == QCA8K_VLAN_LOAD) {
|
||||
- reg = qca8k_read(priv, QCA8K_REG_VTU_FUNC1);
|
||||
- if (reg < 0)
|
||||
- return reg;
|
||||
+ ret = qca8k_read(priv, QCA8K_REG_VTU_FUNC1, ®);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
if (reg & QCA8K_VTU_FUNC1_FULL)
|
||||
return -ENOMEM;
|
||||
}
|
||||
@@ -505,11 +496,9 @@ qca8k_vlan_add(struct qca8k_priv *priv,
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
- reg = qca8k_read(priv, QCA8K_REG_VTU_FUNC0);
|
||||
- if (reg < 0) {
|
||||
- ret = reg;
|
||||
+ ret = qca8k_read(priv, QCA8K_REG_VTU_FUNC0, ®);
|
||||
+ if (ret < 0)
|
||||
goto out;
|
||||
- }
|
||||
reg |= QCA8K_VTU_FUNC0_VALID | QCA8K_VTU_FUNC0_IVL_EN;
|
||||
reg &= ~(QCA8K_VTU_FUNC0_EG_MODE_MASK << QCA8K_VTU_FUNC0_EG_MODE_S(port));
|
||||
if (untagged)
|
||||
@@ -542,11 +531,9 @@ qca8k_vlan_del(struct qca8k_priv *priv,
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
- reg = qca8k_read(priv, QCA8K_REG_VTU_FUNC0);
|
||||
- if (reg < 0) {
|
||||
- ret = reg;
|
||||
+ ret = qca8k_read(priv, QCA8K_REG_VTU_FUNC0, ®);
|
||||
+ if (ret < 0)
|
||||
goto out;
|
||||
- }
|
||||
reg &= ~(3 << QCA8K_VTU_FUNC0_EG_MODE_S(port));
|
||||
reg |= QCA8K_VTU_FUNC0_EG_MODE_NOT <<
|
||||
QCA8K_VTU_FUNC0_EG_MODE_S(port);
|
||||
@@ -638,19 +625,19 @@ qca8k_mdio_busy_wait(struct mii_bus *bus
|
||||
{
|
||||
u16 r1, r2, page;
|
||||
u32 val;
|
||||
- int ret;
|
||||
+ int ret, ret1;
|
||||
|
||||
qca8k_split_addr(reg, &r1, &r2, &page);
|
||||
|
||||
- ret = read_poll_timeout(qca8k_mii_read32, val, !(val & mask), 0,
|
||||
+ ret = read_poll_timeout(qca8k_mii_read32, ret1, !(val & mask), 0,
|
||||
QCA8K_BUSY_WAIT_TIMEOUT * USEC_PER_MSEC, false,
|
||||
- bus, 0x10 | r2, r1);
|
||||
+ bus, 0x10 | r2, r1, &val);
|
||||
|
||||
/* Check if qca8k_read has failed for a different reason
|
||||
* before returnting -ETIMEDOUT
|
||||
*/
|
||||
- if (ret < 0 && val < 0)
|
||||
- return val;
|
||||
+ if (ret < 0 && ret1 < 0)
|
||||
+ return ret1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -725,7 +712,7 @@ qca8k_mdio_read(struct mii_bus *salve_bu
|
||||
if (ret)
|
||||
goto exit;
|
||||
|
||||
- val = qca8k_mii_read32(bus, 0x10 | r2, r1);
|
||||
+ ret = qca8k_mii_read32(bus, 0x10 | r2, r1, &val);
|
||||
|
||||
exit:
|
||||
/* even if the busy_wait timeouts try to clear the MASTER_EN */
|
||||
@@ -733,10 +720,10 @@ exit:
|
||||
|
||||
mutex_unlock(&bus->mdio_lock);
|
||||
|
||||
- if (val >= 0)
|
||||
- val &= QCA8K_MDIO_MASTER_DATA_MASK;
|
||||
+ if (ret >= 0)
|
||||
+ ret = val & QCA8K_MDIO_MASTER_DATA_MASK;
|
||||
|
||||
- return val;
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -1211,7 +1198,7 @@ qca8k_phylink_mac_config(struct dsa_swit
|
||||
qca8k_write(priv, reg, QCA8K_PORT_PAD_SGMII_EN);
|
||||
|
||||
/* Enable/disable SerDes auto-negotiation as necessary */
|
||||
- val = qca8k_read(priv, QCA8K_REG_PWS);
|
||||
+ qca8k_read(priv, QCA8K_REG_PWS, &val);
|
||||
if (phylink_autoneg_inband(mode))
|
||||
val &= ~QCA8K_PWS_SERDES_AEN_DIS;
|
||||
else
|
||||
@@ -1219,7 +1206,7 @@ qca8k_phylink_mac_config(struct dsa_swit
|
||||
qca8k_write(priv, QCA8K_REG_PWS, val);
|
||||
|
||||
/* Configure the SGMII parameters */
|
||||
- val = qca8k_read(priv, QCA8K_REG_SGMII_CTRL);
|
||||
+ qca8k_read(priv, QCA8K_REG_SGMII_CTRL, &val);
|
||||
|
||||
val |= QCA8K_SGMII_EN_PLL | QCA8K_SGMII_EN_RX |
|
||||
QCA8K_SGMII_EN_TX | QCA8K_SGMII_EN_SD;
|
||||
@@ -1314,10 +1301,11 @@ qca8k_phylink_mac_link_state(struct dsa_
|
||||
{
|
||||
struct qca8k_priv *priv = ds->priv;
|
||||
u32 reg;
|
||||
+ int ret;
|
||||
|
||||
- reg = qca8k_read(priv, QCA8K_REG_PORT_STATUS(port));
|
||||
- if (reg < 0)
|
||||
- return reg;
|
||||
+ ret = qca8k_read(priv, QCA8K_REG_PORT_STATUS(port), ®);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
|
||||
state->link = !!(reg & QCA8K_PORT_STATUS_LINK_UP);
|
||||
state->an_complete = state->link;
|
||||
@@ -1419,19 +1407,20 @@ qca8k_get_ethtool_stats(struct dsa_switc
|
||||
struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
|
||||
const struct qca8k_mib_desc *mib;
|
||||
u32 reg, i, val;
|
||||
- u64 hi;
|
||||
+ u64 hi = 0;
|
||||
+ int ret;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ar8327_mib); i++) {
|
||||
mib = &ar8327_mib[i];
|
||||
reg = QCA8K_PORT_MIB_COUNTER(port) + mib->offset;
|
||||
|
||||
- val = qca8k_read(priv, reg);
|
||||
- if (val < 0)
|
||||
+ ret = qca8k_read(priv, reg, &val);
|
||||
+ if (ret < 0)
|
||||
continue;
|
||||
|
||||
if (mib->size == 2) {
|
||||
- hi = qca8k_read(priv, reg + 4);
|
||||
- if (hi < 0)
|
||||
+ ret = qca8k_read(priv, reg + 4, (u32 *)&hi);
|
||||
+ if (ret < 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1459,7 +1448,7 @@ qca8k_set_mac_eee(struct dsa_switch *ds,
|
||||
int ret;
|
||||
|
||||
mutex_lock(&priv->reg_mutex);
|
||||
- reg = qca8k_read(priv, QCA8K_REG_EEE_CTRL);
|
||||
+ ret = qca8k_read(priv, QCA8K_REG_EEE_CTRL, ®);
|
||||
if (reg < 0) {
|
||||
ret = reg;
|
||||
goto exit;
|
||||
@@ -1802,14 +1791,15 @@ static int qca8k_read_switch_id(struct q
|
||||
const struct qca8k_match_data *data;
|
||||
u32 val;
|
||||
u8 id;
|
||||
+ int ret;
|
||||
|
||||
/* get the switches ID from the compatible */
|
||||
data = of_device_get_match_data(priv->dev);
|
||||
if (!data)
|
||||
return -ENODEV;
|
||||
|
||||
- val = qca8k_read(priv, QCA8K_REG_MASK_CTRL);
|
||||
- if (val < 0)
|
||||
+ ret = qca8k_read(priv, QCA8K_REG_MASK_CTRL, &val);
|
||||
+ if (ret < 0)
|
||||
return -ENODEV;
|
||||
|
||||
id = QCA8K_MASK_CTRL_DEVICE_ID(val & QCA8K_MASK_CTRL_DEVICE_ID_MASK);
|
@ -0,0 +1,47 @@
|
||||
From 9fe99de01440d9ede74d447ac76e9c445d8daae9 Mon Sep 17 00:00:00 2001
|
||||
From: Yang Yingliang <yangyingliang@huawei.com>
|
||||
Date: Sat, 29 May 2021 11:04:39 +0800
|
||||
Subject: [PATCH] net: dsa: qca8k: add missing check return value in
|
||||
qca8k_phylink_mac_config()
|
||||
|
||||
Now we can check qca8k_read() return value correctly, so if
|
||||
it fails, we need return directly.
|
||||
|
||||
Signed-off-by: Yang Yingliang <yangyingliang@huawei.com>
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/dsa/qca8k.c | 9 +++++++--
|
||||
1 file changed, 7 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/qca8k.c
|
||||
+++ b/drivers/net/dsa/qca8k.c
|
||||
@@ -1128,6 +1128,7 @@ qca8k_phylink_mac_config(struct dsa_swit
|
||||
{
|
||||
struct qca8k_priv *priv = ds->priv;
|
||||
u32 reg, val;
|
||||
+ int ret;
|
||||
|
||||
switch (port) {
|
||||
case 0: /* 1st CPU port */
|
||||
@@ -1198,7 +1199,9 @@ qca8k_phylink_mac_config(struct dsa_swit
|
||||
qca8k_write(priv, reg, QCA8K_PORT_PAD_SGMII_EN);
|
||||
|
||||
/* Enable/disable SerDes auto-negotiation as necessary */
|
||||
- qca8k_read(priv, QCA8K_REG_PWS, &val);
|
||||
+ ret = qca8k_read(priv, QCA8K_REG_PWS, &val);
|
||||
+ if (ret)
|
||||
+ return;
|
||||
if (phylink_autoneg_inband(mode))
|
||||
val &= ~QCA8K_PWS_SERDES_AEN_DIS;
|
||||
else
|
||||
@@ -1206,7 +1209,9 @@ qca8k_phylink_mac_config(struct dsa_swit
|
||||
qca8k_write(priv, QCA8K_REG_PWS, val);
|
||||
|
||||
/* Configure the SGMII parameters */
|
||||
- qca8k_read(priv, QCA8K_REG_SGMII_CTRL, &val);
|
||||
+ ret = qca8k_read(priv, QCA8K_REG_SGMII_CTRL, &val);
|
||||
+ if (ret)
|
||||
+ return;
|
||||
|
||||
val |= QCA8K_SGMII_EN_PLL | QCA8K_SGMII_EN_RX |
|
||||
QCA8K_SGMII_EN_TX | QCA8K_SGMII_EN_SD;
|
@ -0,0 +1,47 @@
|
||||
From aa3d020b22cb844ab7bdbb9e5d861a64666e2b74 Mon Sep 17 00:00:00 2001
|
||||
From: Dan Carpenter <dan.carpenter@oracle.com>
|
||||
Date: Wed, 9 Jun 2021 12:52:12 +0300
|
||||
Subject: [PATCH] net: dsa: qca8k: fix an endian bug in
|
||||
qca8k_get_ethtool_stats()
|
||||
|
||||
The "hi" variable is a u64 but the qca8k_read() writes to the top 32
|
||||
bits of it. That will work on little endian systems but it's a bit
|
||||
subtle. It's cleaner to make declare "hi" as a u32. We will still need
|
||||
to cast it when we shift it later on in the function but that's fine.
|
||||
|
||||
Fixes: 7c9896e37807 ("net: dsa: qca8k: check return value of read functions correctly")
|
||||
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
|
||||
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/qca8k.c | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/qca8k.c
|
||||
+++ b/drivers/net/dsa/qca8k.c
|
||||
@@ -1412,7 +1412,7 @@ qca8k_get_ethtool_stats(struct dsa_switc
|
||||
struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
|
||||
const struct qca8k_mib_desc *mib;
|
||||
u32 reg, i, val;
|
||||
- u64 hi = 0;
|
||||
+ u32 hi = 0;
|
||||
int ret;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ar8327_mib); i++) {
|
||||
@@ -1424,14 +1424,14 @@ qca8k_get_ethtool_stats(struct dsa_switc
|
||||
continue;
|
||||
|
||||
if (mib->size == 2) {
|
||||
- ret = qca8k_read(priv, reg + 4, (u32 *)&hi);
|
||||
+ ret = qca8k_read(priv, reg + 4, &hi);
|
||||
if (ret < 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
data[i] = val;
|
||||
if (mib->size == 2)
|
||||
- data[i] |= hi << 32;
|
||||
+ data[i] |= (u64)hi << 32;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,31 @@
|
||||
From 3d0167f2a627528032821cdeb78b4eab0510460f Mon Sep 17 00:00:00 2001
|
||||
From: Dan Carpenter <dan.carpenter@oracle.com>
|
||||
Date: Wed, 9 Jun 2021 12:53:03 +0300
|
||||
Subject: [PATCH] net: dsa: qca8k: check the correct variable in
|
||||
qca8k_set_mac_eee()
|
||||
|
||||
This code check "reg" but "ret" was intended so the error handling will
|
||||
never trigger.
|
||||
|
||||
Fixes: 7c9896e37807 ("net: dsa: qca8k: check return value of read functions correctly")
|
||||
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
|
||||
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/qca8k.c | 4 +---
|
||||
1 file changed, 1 insertion(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/qca8k.c
|
||||
+++ b/drivers/net/dsa/qca8k.c
|
||||
@@ -1454,10 +1454,8 @@ qca8k_set_mac_eee(struct dsa_switch *ds,
|
||||
|
||||
mutex_lock(&priv->reg_mutex);
|
||||
ret = qca8k_read(priv, QCA8K_REG_EEE_CTRL, ®);
|
||||
- if (reg < 0) {
|
||||
- ret = reg;
|
||||
+ if (ret < 0)
|
||||
goto exit;
|
||||
- }
|
||||
|
||||
if (eee->eee_enabled)
|
||||
reg |= lpi_en;
|
@ -0,0 +1,80 @@
|
||||
From ce062a0adbfe933b1932235fdfd874c4c91d1bb0 Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Sat, 11 Sep 2021 17:50:09 +0200
|
||||
Subject: net: dsa: qca8k: fix kernel panic with legacy mdio mapping
|
||||
|
||||
When the mdio legacy mapping is used the mii_bus priv registered by DSA
|
||||
refer to the dsa switch struct instead of the qca8k_priv struct and
|
||||
causes a kernel panic. Create dedicated function when the internal
|
||||
dedicated mdio driver is used to properly handle the 2 different
|
||||
implementation.
|
||||
|
||||
Fixes: 759bafb8a322 ("net: dsa: qca8k: add support for internal phy and internal mdio")
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/qca8k.c | 30 ++++++++++++++++++++++--------
|
||||
1 file changed, 22 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/qca8k.c
|
||||
+++ b/drivers/net/dsa/qca8k.c
|
||||
@@ -643,10 +643,8 @@ qca8k_mdio_busy_wait(struct mii_bus *bus
|
||||
}
|
||||
|
||||
static int
|
||||
-qca8k_mdio_write(struct mii_bus *salve_bus, int phy, int regnum, u16 data)
|
||||
+qca8k_mdio_write(struct mii_bus *bus, int phy, int regnum, u16 data)
|
||||
{
|
||||
- struct qca8k_priv *priv = salve_bus->priv;
|
||||
- struct mii_bus *bus = priv->bus;
|
||||
u16 r1, r2, page;
|
||||
u32 val;
|
||||
int ret;
|
||||
@@ -682,10 +680,8 @@ exit:
|
||||
}
|
||||
|
||||
static int
|
||||
-qca8k_mdio_read(struct mii_bus *salve_bus, int phy, int regnum)
|
||||
+qca8k_mdio_read(struct mii_bus *bus, int phy, int regnum)
|
||||
{
|
||||
- struct qca8k_priv *priv = salve_bus->priv;
|
||||
- struct mii_bus *bus = priv->bus;
|
||||
u16 r1, r2, page;
|
||||
u32 val;
|
||||
int ret;
|
||||
@@ -727,6 +723,24 @@ exit:
|
||||
}
|
||||
|
||||
static int
|
||||
+qca8k_internal_mdio_write(struct mii_bus *slave_bus, int phy, int regnum, u16 data)
|
||||
+{
|
||||
+ struct qca8k_priv *priv = slave_bus->priv;
|
||||
+ struct mii_bus *bus = priv->bus;
|
||||
+
|
||||
+ return qca8k_mdio_write(bus, phy, regnum, data);
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+qca8k_internal_mdio_read(struct mii_bus *slave_bus, int phy, int regnum)
|
||||
+{
|
||||
+ struct qca8k_priv *priv = slave_bus->priv;
|
||||
+ struct mii_bus *bus = priv->bus;
|
||||
+
|
||||
+ return qca8k_mdio_read(bus, phy, regnum);
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
qca8k_phy_write(struct dsa_switch *ds, int port, int regnum, u16 data)
|
||||
{
|
||||
struct qca8k_priv *priv = ds->priv;
|
||||
@@ -775,8 +789,8 @@ qca8k_mdio_register(struct qca8k_priv *p
|
||||
|
||||
bus->priv = (void *)priv;
|
||||
bus->name = "qca8k slave mii";
|
||||
- bus->read = qca8k_mdio_read;
|
||||
- bus->write = qca8k_mdio_write;
|
||||
+ bus->read = qca8k_internal_mdio_read;
|
||||
+ bus->write = qca8k_internal_mdio_write;
|
||||
snprintf(bus->id, MII_BUS_ID_SIZE, "qca8k-%d",
|
||||
ds->index);
|
||||
|
@ -0,0 +1,65 @@
|
||||
From ee47ed08d75e8f16b3cf882061ee19c2ea19dd6c Mon Sep 17 00:00:00 2001
|
||||
From: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Date: Wed, 10 Mar 2021 10:52:26 -0800
|
||||
Subject: [PATCH] net: dsa: b53: Add debug prints in b53_vlan_enable()
|
||||
|
||||
Having dynamic debug prints in b53_vlan_enable() has been helpful to
|
||||
uncover a recent but update the function to indicate the port being
|
||||
configured (or -1 for initial setup) and include the global VLAN enabled
|
||||
and VLAN filtering enable status.
|
||||
|
||||
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/b53/b53_common.c | 11 +++++++----
|
||||
1 file changed, 7 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/b53/b53_common.c
|
||||
+++ b/drivers/net/dsa/b53/b53_common.c
|
||||
@@ -349,7 +349,7 @@ static void b53_set_forwarding(struct b5
|
||||
b53_write8(dev, B53_CTRL_PAGE, B53_IP_MULTICAST_CTRL, mgmt);
|
||||
}
|
||||
|
||||
-static void b53_enable_vlan(struct b53_device *dev, bool enable,
|
||||
+static void b53_enable_vlan(struct b53_device *dev, int port, bool enable,
|
||||
bool enable_filtering)
|
||||
{
|
||||
u8 mgmt, vc0, vc1, vc4 = 0, vc5;
|
||||
@@ -431,6 +431,9 @@ static void b53_enable_vlan(struct b53_d
|
||||
b53_write8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, mgmt);
|
||||
|
||||
dev->vlan_enabled = enable;
|
||||
+
|
||||
+ dev_dbg(dev->dev, "Port %d VLAN enabled: %d, filtering: %d\n",
|
||||
+ port, enable, enable_filtering);
|
||||
}
|
||||
|
||||
static int b53_set_jumbo(struct b53_device *dev, bool enable, bool allow_10_100)
|
||||
@@ -708,7 +711,7 @@ int b53_configure_vlan(struct dsa_switch
|
||||
b53_do_vlan_op(dev, VTA_CMD_CLEAR);
|
||||
}
|
||||
|
||||
- b53_enable_vlan(dev, dev->vlan_enabled, ds->vlan_filtering);
|
||||
+ b53_enable_vlan(dev, -1, dev->vlan_enabled, ds->vlan_filtering);
|
||||
|
||||
b53_for_each_port(dev, i)
|
||||
b53_write16(dev, B53_VLAN_PAGE,
|
||||
@@ -1390,7 +1393,7 @@ int b53_vlan_filtering(struct dsa_switch
|
||||
if (switchdev_trans_ph_prepare(trans))
|
||||
return 0;
|
||||
|
||||
- b53_enable_vlan(dev, dev->vlan_enabled, vlan_filtering);
|
||||
+ b53_enable_vlan(dev, port, dev->vlan_enabled, vlan_filtering);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1415,7 +1418,7 @@ int b53_vlan_prepare(struct dsa_switch *
|
||||
if (vlan->vid_end >= dev->num_vlans)
|
||||
return -ERANGE;
|
||||
|
||||
- b53_enable_vlan(dev, true, ds->vlan_filtering);
|
||||
+ b53_enable_vlan(dev, port, true, ds->vlan_filtering);
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
From 6d16eadab6db0c1d61e59fee7ed1ecc2d10269be Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari@gmail.com>
|
||||
Date: Mon, 15 Mar 2021 15:14:23 +0100
|
||||
Subject: [PATCH] net: dsa: b53: spi: allow device tree probing
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Add missing of_match_table to allow device tree probing.
|
||||
|
||||
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/b53/b53_spi.c | 13 +++++++++++++
|
||||
1 file changed, 13 insertions(+)
|
||||
|
||||
--- a/drivers/net/dsa/b53/b53_spi.c
|
||||
+++ b/drivers/net/dsa/b53/b53_spi.c
|
||||
@@ -324,9 +324,22 @@ static int b53_spi_remove(struct spi_dev
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static const struct of_device_id b53_spi_of_match[] = {
|
||||
+ { .compatible = "brcm,bcm5325" },
|
||||
+ { .compatible = "brcm,bcm5365" },
|
||||
+ { .compatible = "brcm,bcm5395" },
|
||||
+ { .compatible = "brcm,bcm5397" },
|
||||
+ { .compatible = "brcm,bcm5398" },
|
||||
+ { .compatible = "brcm,bcm53115" },
|
||||
+ { .compatible = "brcm,bcm53125" },
|
||||
+ { .compatible = "brcm,bcm53128" },
|
||||
+ { /* sentinel */ }
|
||||
+};
|
||||
+
|
||||
static struct spi_driver b53_spi_driver = {
|
||||
.driver = {
|
||||
.name = "b53-switch",
|
||||
+ .of_match_table = b53_spi_of_match,
|
||||
},
|
||||
.probe = b53_spi_probe,
|
||||
.remove = b53_spi_remove,
|
@ -0,0 +1,31 @@
|
||||
From ad426d7d966b525b73ed5a1842dd830312bbba71 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari@gmail.com>
|
||||
Date: Wed, 17 Mar 2021 09:42:01 +0100
|
||||
Subject: [PATCH] net: dsa: b53: relax is63xx() condition
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
BCM63xx switches are present on bcm63xx and bmips devices.
|
||||
|
||||
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
|
||||
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/b53/b53_priv.h | 4 ----
|
||||
1 file changed, 4 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/b53/b53_priv.h
|
||||
+++ b/drivers/net/dsa/b53/b53_priv.h
|
||||
@@ -186,11 +186,7 @@ static inline int is531x5(struct b53_dev
|
||||
|
||||
static inline int is63xx(struct b53_device *dev)
|
||||
{
|
||||
-#ifdef CONFIG_BCM63XX
|
||||
return dev->chip_id == BCM63XX_DEVICE_ID;
|
||||
-#else
|
||||
- return 0;
|
||||
-#endif
|
||||
}
|
||||
|
||||
static inline int is5301x(struct b53_device *dev)
|
@ -0,0 +1,180 @@
|
||||
From 964dbf186eaa84d409c359ddf09c827a3fbe8228 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari@gmail.com>
|
||||
Date: Wed, 17 Mar 2021 11:29:26 +0100
|
||||
Subject: [PATCH] net: dsa: tag_brcm: add support for legacy tags
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Add support for legacy Broadcom tags, which are similar to DSA_TAG_PROTO_BRCM.
|
||||
These tags are used on BCM5325, BCM5365 and BCM63xx switches.
|
||||
|
||||
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
include/net/dsa.h | 2 +
|
||||
net/dsa/Kconfig | 7 +++
|
||||
net/dsa/tag_brcm.c | 107 +++++++++++++++++++++++++++++++++++++++++++--
|
||||
3 files changed, 113 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/include/net/dsa.h
|
||||
+++ b/include/net/dsa.h
|
||||
@@ -45,10 +45,12 @@ struct phylink_link_state;
|
||||
#define DSA_TAG_PROTO_OCELOT_VALUE 15
|
||||
#define DSA_TAG_PROTO_AR9331_VALUE 16
|
||||
#define DSA_TAG_PROTO_RTL4_A_VALUE 17
|
||||
+#define DSA_TAG_PROTO_BRCM_LEGACY_VALUE 22
|
||||
|
||||
enum dsa_tag_protocol {
|
||||
DSA_TAG_PROTO_NONE = DSA_TAG_PROTO_NONE_VALUE,
|
||||
DSA_TAG_PROTO_BRCM = DSA_TAG_PROTO_BRCM_VALUE,
|
||||
+ DSA_TAG_PROTO_BRCM_LEGACY = DSA_TAG_PROTO_BRCM_LEGACY_VALUE,
|
||||
DSA_TAG_PROTO_BRCM_PREPEND = DSA_TAG_PROTO_BRCM_PREPEND_VALUE,
|
||||
DSA_TAG_PROTO_DSA = DSA_TAG_PROTO_DSA_VALUE,
|
||||
DSA_TAG_PROTO_EDSA = DSA_TAG_PROTO_EDSA_VALUE,
|
||||
--- a/net/dsa/Kconfig
|
||||
+++ b/net/dsa/Kconfig
|
||||
@@ -47,6 +47,13 @@ config NET_DSA_TAG_BRCM
|
||||
Say Y if you want to enable support for tagging frames for the
|
||||
Broadcom switches which place the tag after the MAC source address.
|
||||
|
||||
+config NET_DSA_TAG_BRCM_LEGACY
|
||||
+ tristate "Tag driver for Broadcom legacy switches using in-frame headers"
|
||||
+ select NET_DSA_TAG_BRCM_COMMON
|
||||
+ help
|
||||
+ Say Y if you want to enable support for tagging frames for the
|
||||
+ Broadcom legacy switches which place the tag after the MAC source
|
||||
+ address.
|
||||
|
||||
config NET_DSA_TAG_BRCM_PREPEND
|
||||
tristate "Tag driver for Broadcom switches using prepended headers"
|
||||
--- a/net/dsa/tag_brcm.c
|
||||
+++ b/net/dsa/tag_brcm.c
|
||||
@@ -11,9 +11,26 @@
|
||||
|
||||
#include "dsa_priv.h"
|
||||
|
||||
-/* This tag length is 4 bytes, older ones were 6 bytes, we do not
|
||||
- * handle them
|
||||
- */
|
||||
+/* Legacy Broadcom tag (6 bytes) */
|
||||
+#define BRCM_LEG_TAG_LEN 6
|
||||
+
|
||||
+/* Type fields */
|
||||
+/* 1st byte in the tag */
|
||||
+#define BRCM_LEG_TYPE_HI 0x88
|
||||
+/* 2nd byte in the tag */
|
||||
+#define BRCM_LEG_TYPE_LO 0x74
|
||||
+
|
||||
+/* Tag fields */
|
||||
+/* 3rd byte in the tag */
|
||||
+#define BRCM_LEG_UNICAST (0 << 5)
|
||||
+#define BRCM_LEG_MULTICAST (1 << 5)
|
||||
+#define BRCM_LEG_EGRESS (2 << 5)
|
||||
+#define BRCM_LEG_INGRESS (3 << 5)
|
||||
+
|
||||
+/* 6th byte in the tag */
|
||||
+#define BRCM_LEG_PORT_ID (0xf)
|
||||
+
|
||||
+/* Newer Broadcom tag (4 bytes) */
|
||||
#define BRCM_TAG_LEN 4
|
||||
|
||||
/* Tag is constructed and desconstructed using byte by byte access
|
||||
@@ -194,6 +211,87 @@ DSA_TAG_DRIVER(brcm_netdev_ops);
|
||||
MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_BRCM);
|
||||
#endif
|
||||
|
||||
+#if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_LEGACY)
|
||||
+static struct sk_buff *brcm_leg_tag_xmit(struct sk_buff *skb,
|
||||
+ struct net_device *dev)
|
||||
+{
|
||||
+ struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||
+ u8 *brcm_tag;
|
||||
+
|
||||
+ /* The Ethernet switch we are interfaced with needs packets to be at
|
||||
+ * least 64 bytes (including FCS) otherwise they will be discarded when
|
||||
+ * they enter the switch port logic. When Broadcom tags are enabled, we
|
||||
+ * need to make sure that packets are at least 70 bytes
|
||||
+ * (including FCS and tag) because the length verification is done after
|
||||
+ * the Broadcom tag is stripped off the ingress packet.
|
||||
+ *
|
||||
+ * Let dsa_slave_xmit() free the SKB
|
||||
+ */
|
||||
+ if (__skb_put_padto(skb, ETH_ZLEN + BRCM_LEG_TAG_LEN, false))
|
||||
+ return NULL;
|
||||
+
|
||||
+ skb_push(skb, BRCM_LEG_TAG_LEN);
|
||||
+
|
||||
+ memmove(skb->data, skb->data + BRCM_LEG_TAG_LEN, 2 * ETH_ALEN);
|
||||
+
|
||||
+ brcm_tag = skb->data + 2 * ETH_ALEN;
|
||||
+
|
||||
+ /* Broadcom tag type */
|
||||
+ brcm_tag[0] = BRCM_LEG_TYPE_HI;
|
||||
+ brcm_tag[1] = BRCM_LEG_TYPE_LO;
|
||||
+
|
||||
+ /* Broadcom tag value */
|
||||
+ brcm_tag[2] = BRCM_LEG_EGRESS;
|
||||
+ brcm_tag[3] = 0;
|
||||
+ brcm_tag[4] = 0;
|
||||
+ brcm_tag[5] = dp->index & BRCM_LEG_PORT_ID;
|
||||
+
|
||||
+ return skb;
|
||||
+}
|
||||
+
|
||||
+static struct sk_buff *brcm_leg_tag_rcv(struct sk_buff *skb,
|
||||
+ struct net_device *dev,
|
||||
+ struct packet_type *pt)
|
||||
+{
|
||||
+ int source_port;
|
||||
+ u8 *brcm_tag;
|
||||
+
|
||||
+ if (unlikely(!pskb_may_pull(skb, BRCM_LEG_PORT_ID)))
|
||||
+ return NULL;
|
||||
+
|
||||
+ brcm_tag = skb->data - 2;
|
||||
+
|
||||
+ source_port = brcm_tag[5] & BRCM_LEG_PORT_ID;
|
||||
+
|
||||
+ skb->dev = dsa_master_find_slave(dev, 0, source_port);
|
||||
+ if (!skb->dev)
|
||||
+ return NULL;
|
||||
+
|
||||
+ /* Remove Broadcom tag and update checksum */
|
||||
+ skb_pull_rcsum(skb, BRCM_LEG_TAG_LEN);
|
||||
+
|
||||
+ skb->offload_fwd_mark = 1;
|
||||
+
|
||||
+ /* Move the Ethernet DA and SA */
|
||||
+ memmove(skb->data - ETH_HLEN,
|
||||
+ skb->data - ETH_HLEN - BRCM_LEG_TAG_LEN,
|
||||
+ 2 * ETH_ALEN);
|
||||
+
|
||||
+ return skb;
|
||||
+}
|
||||
+
|
||||
+static const struct dsa_device_ops brcm_legacy_netdev_ops = {
|
||||
+ .name = "brcm-legacy",
|
||||
+ .proto = DSA_TAG_PROTO_BRCM_LEGACY,
|
||||
+ .xmit = brcm_leg_tag_xmit,
|
||||
+ .rcv = brcm_leg_tag_rcv,
|
||||
+ .overhead = BRCM_LEG_TAG_LEN,
|
||||
+};
|
||||
+
|
||||
+DSA_TAG_DRIVER(brcm_legacy_netdev_ops);
|
||||
+MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_BRCM_LEGACY);
|
||||
+#endif /* CONFIG_NET_DSA_TAG_BRCM_LEGACY */
|
||||
+
|
||||
#if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_PREPEND)
|
||||
static struct sk_buff *brcm_tag_xmit_prepend(struct sk_buff *skb,
|
||||
struct net_device *dev)
|
||||
@@ -226,6 +324,9 @@ static struct dsa_tag_driver *dsa_tag_dr
|
||||
#if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM)
|
||||
&DSA_TAG_DRIVER_NAME(brcm_netdev_ops),
|
||||
#endif
|
||||
+#if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_LEGACY)
|
||||
+ &DSA_TAG_DRIVER_NAME(brcm_legacy_netdev_ops),
|
||||
+#endif
|
||||
#if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_PREPEND)
|
||||
&DSA_TAG_DRIVER_NAME(brcm_prepend_netdev_ops),
|
||||
#endif
|
@ -0,0 +1,53 @@
|
||||
From 46c5176c586c81306bf9e7024c13b95da775490f Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari@gmail.com>
|
||||
Date: Wed, 17 Mar 2021 11:29:27 +0100
|
||||
Subject: [PATCH] net: dsa: b53: support legacy tags
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
These tags are used on BCM5325, BCM5365 and BCM63xx switches.
|
||||
|
||||
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
|
||||
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/b53/Kconfig | 1 +
|
||||
drivers/net/dsa/b53/b53_common.c | 12 +++++++-----
|
||||
2 files changed, 8 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/b53/Kconfig
|
||||
+++ b/drivers/net/dsa/b53/Kconfig
|
||||
@@ -3,6 +3,7 @@ menuconfig B53
|
||||
tristate "Broadcom BCM53xx managed switch support"
|
||||
depends on NET_DSA
|
||||
select NET_DSA_TAG_BRCM
|
||||
+ select NET_DSA_TAG_BRCM_LEGACY
|
||||
select NET_DSA_TAG_BRCM_PREPEND
|
||||
help
|
||||
This driver adds support for Broadcom managed switch chips. It supports
|
||||
--- a/drivers/net/dsa/b53/b53_common.c
|
||||
+++ b/drivers/net/dsa/b53/b53_common.c
|
||||
@@ -2024,15 +2024,17 @@ enum dsa_tag_protocol b53_get_tag_protoc
|
||||
{
|
||||
struct b53_device *dev = ds->priv;
|
||||
|
||||
- /* Older models (5325, 5365) support a different tag format that we do
|
||||
- * not support in net/dsa/tag_brcm.c yet.
|
||||
- */
|
||||
- if (is5325(dev) || is5365(dev) ||
|
||||
- !b53_can_enable_brcm_tags(ds, port, mprot)) {
|
||||
+ if (!b53_can_enable_brcm_tags(ds, port, mprot)) {
|
||||
dev->tag_protocol = DSA_TAG_PROTO_NONE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
+ /* Older models require a different 6 byte tag */
|
||||
+ if (is5325(dev) || is5365(dev) || is63xx(dev)) {
|
||||
+ dev->tag_protocol = DSA_TAG_PROTO_BRCM_LEGACY;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
/* Broadcom BCM58xx chips have a flow accelerator on Port 8
|
||||
* which requires us to use the prepended Broadcom tag type
|
||||
*/
|
@ -0,0 +1,92 @@
|
||||
From a5538a777b73b35750ed1ffff8c1ef539e861624 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari@gmail.com>
|
||||
Date: Wed, 17 Mar 2021 10:23:17 +0100
|
||||
Subject: [PATCH] net: dsa: b53: mmap: Add device tree support
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Add device tree support to b53_mmap.c while keeping platform devices support.
|
||||
|
||||
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/b53/b53_mmap.c | 55 ++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 55 insertions(+)
|
||||
|
||||
--- a/drivers/net/dsa/b53/b53_mmap.c
|
||||
+++ b/drivers/net/dsa/b53/b53_mmap.c
|
||||
@@ -16,6 +16,7 @@
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
+#include <linux/bits.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/io.h>
|
||||
@@ -228,11 +229,65 @@ static const struct b53_io_ops b53_mmap_
|
||||
.write64 = b53_mmap_write64,
|
||||
};
|
||||
|
||||
+static int b53_mmap_probe_of(struct platform_device *pdev,
|
||||
+ struct b53_platform_data **ppdata)
|
||||
+{
|
||||
+ struct device_node *np = pdev->dev.of_node;
|
||||
+ struct device_node *of_ports, *of_port;
|
||||
+ struct device *dev = &pdev->dev;
|
||||
+ struct b53_platform_data *pdata;
|
||||
+ void __iomem *mem;
|
||||
+
|
||||
+ mem = devm_platform_ioremap_resource(pdev, 0);
|
||||
+ if (IS_ERR(mem))
|
||||
+ return PTR_ERR(mem);
|
||||
+
|
||||
+ pdata = devm_kzalloc(dev, sizeof(struct b53_platform_data),
|
||||
+ GFP_KERNEL);
|
||||
+ if (!pdata)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ pdata->regs = mem;
|
||||
+ pdata->chip_id = BCM63XX_DEVICE_ID;
|
||||
+ pdata->big_endian = of_property_read_bool(np, "big-endian");
|
||||
+
|
||||
+ of_ports = of_get_child_by_name(np, "ports");
|
||||
+ if (!of_ports) {
|
||||
+ dev_err(dev, "no ports child node found\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ for_each_available_child_of_node(of_ports, of_port) {
|
||||
+ u32 reg;
|
||||
+
|
||||
+ if (of_property_read_u32(of_port, "reg", ®))
|
||||
+ continue;
|
||||
+
|
||||
+ if (reg < B53_CPU_PORT)
|
||||
+ pdata->enabled_ports |= BIT(reg);
|
||||
+ }
|
||||
+
|
||||
+ of_node_put(of_ports);
|
||||
+ *ppdata = pdata;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int b53_mmap_probe(struct platform_device *pdev)
|
||||
{
|
||||
+ struct device_node *np = pdev->dev.of_node;
|
||||
struct b53_platform_data *pdata = pdev->dev.platform_data;
|
||||
struct b53_mmap_priv *priv;
|
||||
struct b53_device *dev;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (!pdata && np) {
|
||||
+ ret = b53_mmap_probe_of(pdev, &pdata);
|
||||
+ if (ret) {
|
||||
+ dev_err(&pdev->dev, "OF probe error\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
|
||||
if (!pdata)
|
||||
return -EINVAL;
|
@ -0,0 +1,27 @@
|
||||
From 866f1577ba69bde2b9f36c300f603596c7d84a62 Mon Sep 17 00:00:00 2001
|
||||
From: Qinglang Miao <miaoqinglang@huawei.com>
|
||||
Date: Thu, 25 Mar 2021 17:19:54 +0800
|
||||
Subject: [PATCH] net: dsa: b53: spi: add missing MODULE_DEVICE_TABLE
|
||||
|
||||
This patch adds missing MODULE_DEVICE_TABLE definition which generates
|
||||
correct modalias for automatic loading of this driver when it is built
|
||||
as an external module.
|
||||
|
||||
Reported-by: Hulk Robot <hulkci@huawei.com>
|
||||
Signed-off-by: Qinglang Miao <miaoqinglang@huawei.com>
|
||||
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/b53/b53_spi.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/drivers/net/dsa/b53/b53_spi.c
|
||||
+++ b/drivers/net/dsa/b53/b53_spi.c
|
||||
@@ -335,6 +335,7 @@ static const struct of_device_id b53_spi
|
||||
{ .compatible = "brcm,bcm53128" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
+MODULE_DEVICE_TABLE(of, b53_spi_of_match);
|
||||
|
||||
static struct spi_driver b53_spi_driver = {
|
||||
.driver = {
|
@ -0,0 +1,86 @@
|
||||
From 2c32a3d3c233b855943677609fe388f82b1f0975 Mon Sep 17 00:00:00 2001
|
||||
From: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Date: Tue, 8 Jun 2021 14:22:04 -0700
|
||||
Subject: [PATCH] net: dsa: b53: Do not force CPU to be always tagged
|
||||
|
||||
Commit ca8931948344 ("net: dsa: b53: Keep CPU port as tagged in all
|
||||
VLANs") forced the CPU port to be always tagged in any VLAN membership.
|
||||
This was necessary back then because we did not support Broadcom tags
|
||||
for all configurations so the only way to differentiate tagged and
|
||||
untagged traffic while DSA_TAG_PROTO_NONE was used was to force the CPU
|
||||
port into being always tagged.
|
||||
|
||||
With most configurations enabling Broadcom tags, especially after
|
||||
8fab459e69ab ("net: dsa: b53: Enable Broadcom tags for 531x5/539x
|
||||
families") we do not need to apply this unconditional force tagging of
|
||||
the CPU port in all VLANs.
|
||||
|
||||
A helper function is introduced to faciliate the encapsulation of the
|
||||
specific condition requiring the CPU port to be tagged in all VLANs and
|
||||
the dsa_switch_ops::untag_bridge_pvid boolean is moved to when
|
||||
dsa_switch_ops::setup is called when we have already determined the
|
||||
tagging protocol we will be using.
|
||||
|
||||
Reported-by: Matthew Hagan <mnhagan88@gmail.com>
|
||||
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
|
||||
Tested-by: Matthew Hagan <mnhagan88@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/b53/b53_common.c | 17 ++++++++++++++---
|
||||
1 file changed, 14 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/b53/b53_common.c
|
||||
+++ b/drivers/net/dsa/b53/b53_common.c
|
||||
@@ -1049,6 +1049,11 @@ static int b53_setup(struct dsa_switch *
|
||||
unsigned int port;
|
||||
int ret;
|
||||
|
||||
+ /* Request bridge PVID untagged when DSA_TAG_PROTO_NONE is set
|
||||
+ * which forces the CPU port to be tagged in all VLANs.
|
||||
+ */
|
||||
+ ds->untag_bridge_pvid = dev->tag_protocol == DSA_TAG_PROTO_NONE;
|
||||
+
|
||||
ret = b53_reset_switch(dev);
|
||||
if (ret) {
|
||||
dev_err(ds->dev, "failed to reset switch\n");
|
||||
@@ -1423,6 +1428,13 @@ int b53_vlan_prepare(struct dsa_switch *
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(b53_vlan_prepare);
|
||||
+
|
||||
+static bool b53_vlan_port_needs_forced_tagged(struct dsa_switch *ds, int port)
|
||||
+{
|
||||
+ struct b53_device *dev = ds->priv;
|
||||
+
|
||||
+ return dev->tag_protocol == DSA_TAG_PROTO_NONE && dsa_is_cpu_port(ds, port);
|
||||
+}
|
||||
|
||||
void b53_vlan_add(struct dsa_switch *ds, int port,
|
||||
const struct switchdev_obj_port_vlan *vlan)
|
||||
@@ -1442,7 +1454,7 @@ void b53_vlan_add(struct dsa_switch *ds,
|
||||
untagged = true;
|
||||
|
||||
vl->members |= BIT(port);
|
||||
- if (untagged && !dsa_is_cpu_port(ds, port))
|
||||
+ if (untagged && !b53_vlan_port_needs_forced_tagged(ds, port))
|
||||
vl->untag |= BIT(port);
|
||||
else
|
||||
vl->untag &= ~BIT(port);
|
||||
@@ -1480,7 +1492,7 @@ int b53_vlan_del(struct dsa_switch *ds,
|
||||
if (pvid == vid)
|
||||
pvid = b53_default_pvid(dev);
|
||||
|
||||
- if (untagged && !dsa_is_cpu_port(ds, port))
|
||||
+ if (untagged && !b53_vlan_port_needs_forced_tagged(ds, port))
|
||||
vl->untag &= ~(BIT(port));
|
||||
|
||||
b53_set_vlan_entry(dev, vid, vl);
|
||||
@@ -2644,7 +2656,6 @@ struct b53_device *b53_switch_alloc(stru
|
||||
dev->ops = ops;
|
||||
ds->ops = &b53_switch_ops;
|
||||
ds->configure_vlan_while_not_filtering = true;
|
||||
- ds->untag_bridge_pvid = true;
|
||||
dev->vlan_enabled = ds->configure_vlan_while_not_filtering;
|
||||
/* Let DSA handle the case were multiple bridges span the same switch
|
||||
* device and different VLAN awareness settings are requested, which
|
@ -0,0 +1,30 @@
|
||||
From 11b57faf951cd3a570e3d9e463fc7c41023bc8c6 Mon Sep 17 00:00:00 2001
|
||||
From: Colin Ian King <colin.king@canonical.com>
|
||||
Date: Tue, 15 Jun 2021 10:05:16 +0100
|
||||
Subject: [PATCH] net: dsa: b53: remove redundant null check on dev
|
||||
|
||||
The pointer dev can never be null, the null check is redundant
|
||||
and can be removed. Cleans up a static analysis warning that
|
||||
pointer priv is dereferencing dev before dev is being null
|
||||
checked.
|
||||
|
||||
Addresses-Coverity: ("Dereference before null check")
|
||||
Signed-off-by: Colin Ian King <colin.king@canonical.com>
|
||||
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/b53/b53_srab.c | 3 +--
|
||||
1 file changed, 1 insertion(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/b53/b53_srab.c
|
||||
+++ b/drivers/net/dsa/b53/b53_srab.c
|
||||
@@ -632,8 +632,7 @@ static int b53_srab_remove(struct platfo
|
||||
struct b53_srab_priv *priv = dev->priv;
|
||||
|
||||
b53_srab_intr_set(priv, false);
|
||||
- if (dev)
|
||||
- b53_switch_remove(dev);
|
||||
+ b53_switch_remove(dev);
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
From 64a81b24487f0d2fba0f033029eec2abc7d82cee Mon Sep 17 00:00:00 2001
|
||||
From: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Date: Mon, 21 Jun 2021 15:10:55 -0700
|
||||
Subject: [PATCH] net: dsa: b53: Create default VLAN entry explicitly
|
||||
|
||||
In case CONFIG_VLAN_8021Q is not set, there will be no call down to the
|
||||
b53 driver to ensure that the default PVID VLAN entry will be configured
|
||||
with the appropriate untagged attribute towards the CPU port. We were
|
||||
implicitly relying on dsa_slave_vlan_rx_add_vid() to do that for us,
|
||||
instead make it explicit.
|
||||
|
||||
Reported-by: Vladimir Oltean <olteanv@gmail.com>
|
||||
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/b53/b53_common.c | 27 +++++++++++++++++++--------
|
||||
1 file changed, 19 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/b53/b53_common.c
|
||||
+++ b/drivers/net/dsa/b53/b53_common.c
|
||||
@@ -693,6 +693,13 @@ static u16 b53_default_pvid(struct b53_d
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static bool b53_vlan_port_needs_forced_tagged(struct dsa_switch *ds, int port)
|
||||
+{
|
||||
+ struct b53_device *dev = ds->priv;
|
||||
+
|
||||
+ return dev->tag_protocol == DSA_TAG_PROTO_NONE && dsa_is_cpu_port(ds, port);
|
||||
+}
|
||||
+
|
||||
int b53_configure_vlan(struct dsa_switch *ds)
|
||||
{
|
||||
struct b53_device *dev = ds->priv;
|
||||
@@ -713,9 +720,20 @@ int b53_configure_vlan(struct dsa_switch
|
||||
|
||||
b53_enable_vlan(dev, -1, dev->vlan_enabled, ds->vlan_filtering);
|
||||
|
||||
- b53_for_each_port(dev, i)
|
||||
+ /* Create an untagged VLAN entry for the default PVID in case
|
||||
+ * CONFIG_VLAN_8021Q is disabled and there are no calls to
|
||||
+ * dsa_slave_vlan_rx_add_vid() to create the default VLAN
|
||||
+ * entry. Do this only when the tagging protocol is not
|
||||
+ * DSA_TAG_PROTO_NONE
|
||||
+ */
|
||||
+ b53_for_each_port(dev, i) {
|
||||
+ v = &dev->vlans[def_vid];
|
||||
+ v->members |= BIT(i);
|
||||
+ if (!b53_vlan_port_needs_forced_tagged(ds, i))
|
||||
+ v->untag = v->members;
|
||||
b53_write16(dev, B53_VLAN_PAGE,
|
||||
B53_VLAN_PORT_DEF_TAG(i), def_vid);
|
||||
+ }
|
||||
|
||||
/* Upon initial call we have not set-up any VLANs, but upon
|
||||
* system resume, we need to restore all VLAN entries.
|
||||
@@ -1429,13 +1447,6 @@ int b53_vlan_prepare(struct dsa_switch *
|
||||
}
|
||||
EXPORT_SYMBOL(b53_vlan_prepare);
|
||||
|
||||
-static bool b53_vlan_port_needs_forced_tagged(struct dsa_switch *ds, int port)
|
||||
-{
|
||||
- struct b53_device *dev = ds->priv;
|
||||
-
|
||||
- return dev->tag_protocol == DSA_TAG_PROTO_NONE && dsa_is_cpu_port(ds, port);
|
||||
-}
|
||||
-
|
||||
void b53_vlan_add(struct dsa_switch *ds, int port,
|
||||
const struct switchdev_obj_port_vlan *vlan)
|
||||
{
|
@ -0,0 +1,48 @@
|
||||
From 0ccf8511182436183c031e8a2f740ae91a02c625 Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Tue, 14 Sep 2021 14:33:45 +0200
|
||||
Subject: net: phy: at803x: add support for qca 8327 internal phy
|
||||
|
||||
Add support for qca8327 internal phy needed for correct init of the
|
||||
switch port. It does use the same qca8337 function and reg just with a
|
||||
different id.
|
||||
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Tested-by: Rosen Penev <rosenp@gmail.com>
|
||||
Tested-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/phy/at803x.c | 15 +++++++++++++++
|
||||
1 file changed, 15 insertions(+)
|
||||
|
||||
--- a/drivers/net/phy/at803x.c
|
||||
+++ b/drivers/net/phy/at803x.c
|
||||
@@ -1328,6 +1328,19 @@ static struct phy_driver at803x_driver[]
|
||||
.get_sset_count = at803x_get_sset_count,
|
||||
.get_strings = at803x_get_strings,
|
||||
.get_stats = at803x_get_stats,
|
||||
+}, {
|
||||
+ /* QCA8327 */
|
||||
+ .phy_id = QCA8327_PHY_ID,
|
||||
+ .phy_id_mask = QCA8K_PHY_ID_MASK,
|
||||
+ .name = "QCA PHY 8327",
|
||||
+ /* PHY_GBIT_FEATURES */
|
||||
+ .probe = at803x_probe,
|
||||
+ .flags = PHY_IS_INTERNAL,
|
||||
+ .config_init = qca83xx_config_init,
|
||||
+ .soft_reset = genphy_soft_reset,
|
||||
+ .get_sset_count = at803x_get_sset_count,
|
||||
+ .get_strings = at803x_get_strings,
|
||||
+ .get_stats = at803x_get_stats,
|
||||
}, };
|
||||
|
||||
module_phy_driver(at803x_driver);
|
||||
@@ -1338,6 +1351,8 @@ static struct mdio_device_id __maybe_unu
|
||||
{ PHY_ID_MATCH_EXACT(ATH8032_PHY_ID) },
|
||||
{ PHY_ID_MATCH_EXACT(ATH8035_PHY_ID) },
|
||||
{ PHY_ID_MATCH_EXACT(ATH9331_PHY_ID) },
|
||||
+ { PHY_ID_MATCH_EXACT(QCA8337_PHY_ID) },
|
||||
+ { PHY_ID_MATCH_EXACT(QCA8327_PHY_ID) },
|
||||
{ }
|
||||
};
|
||||
|
@ -0,0 +1,131 @@
|
||||
From 983d96a9116a328668601555d96736261d33170c Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
|
||||
Date: Thu, 16 Sep 2021 14:03:51 +0200
|
||||
Subject: [PATCH] net: dsa: b53: Include all ports in "enabled_ports"
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Make "enabled_ports" bitfield contain all available switch ports
|
||||
including a CPU port. This way there is no need for fixup during
|
||||
initialization.
|
||||
|
||||
For BCM53010, BCM53018 and BCM53019 include also other available ports.
|
||||
|
||||
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
||||
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Tested-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/dsa/b53/b53_common.c | 23 +++++++++++------------
|
||||
1 file changed, 11 insertions(+), 12 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/b53/b53_common.c
|
||||
+++ b/drivers/net/dsa/b53/b53_common.c
|
||||
@@ -2288,7 +2288,7 @@ static const struct b53_chip_data b53_sw
|
||||
.chip_id = BCM5325_DEVICE_ID,
|
||||
.dev_name = "BCM5325",
|
||||
.vlans = 16,
|
||||
- .enabled_ports = 0x1f,
|
||||
+ .enabled_ports = 0x3f,
|
||||
.arl_bins = 2,
|
||||
.arl_buckets = 1024,
|
||||
.imp_port = 5,
|
||||
@@ -2299,7 +2299,7 @@ static const struct b53_chip_data b53_sw
|
||||
.chip_id = BCM5365_DEVICE_ID,
|
||||
.dev_name = "BCM5365",
|
||||
.vlans = 256,
|
||||
- .enabled_ports = 0x1f,
|
||||
+ .enabled_ports = 0x3f,
|
||||
.arl_bins = 2,
|
||||
.arl_buckets = 1024,
|
||||
.imp_port = 5,
|
||||
@@ -2310,7 +2310,7 @@ static const struct b53_chip_data b53_sw
|
||||
.chip_id = BCM5389_DEVICE_ID,
|
||||
.dev_name = "BCM5389",
|
||||
.vlans = 4096,
|
||||
- .enabled_ports = 0x1f,
|
||||
+ .enabled_ports = 0x11f,
|
||||
.arl_bins = 4,
|
||||
.arl_buckets = 1024,
|
||||
.imp_port = 8,
|
||||
@@ -2324,7 +2324,7 @@ static const struct b53_chip_data b53_sw
|
||||
.chip_id = BCM5395_DEVICE_ID,
|
||||
.dev_name = "BCM5395",
|
||||
.vlans = 4096,
|
||||
- .enabled_ports = 0x1f,
|
||||
+ .enabled_ports = 0x11f,
|
||||
.arl_bins = 4,
|
||||
.arl_buckets = 1024,
|
||||
.imp_port = 8,
|
||||
@@ -2338,7 +2338,7 @@ static const struct b53_chip_data b53_sw
|
||||
.chip_id = BCM5397_DEVICE_ID,
|
||||
.dev_name = "BCM5397",
|
||||
.vlans = 4096,
|
||||
- .enabled_ports = 0x1f,
|
||||
+ .enabled_ports = 0x11f,
|
||||
.arl_bins = 4,
|
||||
.arl_buckets = 1024,
|
||||
.imp_port = 8,
|
||||
@@ -2352,7 +2352,7 @@ static const struct b53_chip_data b53_sw
|
||||
.chip_id = BCM5398_DEVICE_ID,
|
||||
.dev_name = "BCM5398",
|
||||
.vlans = 4096,
|
||||
- .enabled_ports = 0x7f,
|
||||
+ .enabled_ports = 0x17f,
|
||||
.arl_bins = 4,
|
||||
.arl_buckets = 1024,
|
||||
.imp_port = 8,
|
||||
@@ -2366,7 +2366,7 @@ static const struct b53_chip_data b53_sw
|
||||
.chip_id = BCM53115_DEVICE_ID,
|
||||
.dev_name = "BCM53115",
|
||||
.vlans = 4096,
|
||||
- .enabled_ports = 0x1f,
|
||||
+ .enabled_ports = 0x11f,
|
||||
.arl_bins = 4,
|
||||
.arl_buckets = 1024,
|
||||
.vta_regs = B53_VTA_REGS,
|
||||
@@ -2380,7 +2380,7 @@ static const struct b53_chip_data b53_sw
|
||||
.chip_id = BCM53125_DEVICE_ID,
|
||||
.dev_name = "BCM53125",
|
||||
.vlans = 4096,
|
||||
- .enabled_ports = 0xff,
|
||||
+ .enabled_ports = 0x1ff,
|
||||
.arl_bins = 4,
|
||||
.arl_buckets = 1024,
|
||||
.imp_port = 8,
|
||||
@@ -2422,7 +2422,7 @@ static const struct b53_chip_data b53_sw
|
||||
.chip_id = BCM53010_DEVICE_ID,
|
||||
.dev_name = "BCM53010",
|
||||
.vlans = 4096,
|
||||
- .enabled_ports = 0x1f,
|
||||
+ .enabled_ports = 0x1bf,
|
||||
.arl_bins = 4,
|
||||
.arl_buckets = 1024,
|
||||
.imp_port = 8,
|
||||
@@ -2464,7 +2464,7 @@ static const struct b53_chip_data b53_sw
|
||||
.chip_id = BCM53018_DEVICE_ID,
|
||||
.dev_name = "BCM53018",
|
||||
.vlans = 4096,
|
||||
- .enabled_ports = 0x1f,
|
||||
+ .enabled_ports = 0x1bf,
|
||||
.arl_bins = 4,
|
||||
.arl_buckets = 1024,
|
||||
.imp_port = 8,
|
||||
@@ -2478,7 +2478,7 @@ static const struct b53_chip_data b53_sw
|
||||
.chip_id = BCM53019_DEVICE_ID,
|
||||
.dev_name = "BCM53019",
|
||||
.vlans = 4096,
|
||||
- .enabled_ports = 0x1f,
|
||||
+ .enabled_ports = 0x1bf,
|
||||
.arl_bins = 4,
|
||||
.arl_buckets = 1024,
|
||||
.imp_port = 8,
|
||||
@@ -2605,7 +2605,6 @@ static int b53_switch_init(struct b53_de
|
||||
dev->cpu_port = 5;
|
||||
}
|
||||
|
||||
- dev->enabled_ports |= BIT(dev->cpu_port);
|
||||
dev->num_ports = fls(dev->enabled_ports);
|
||||
|
||||
dev->ds->num_ports = min_t(unsigned int, dev->num_ports, DSA_MAX_PORTS);
|
@ -0,0 +1,42 @@
|
||||
From b290c6384afabbca5ae6e2af72fb1b2bc37922be Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
|
||||
Date: Thu, 16 Sep 2021 14:03:52 +0200
|
||||
Subject: [PATCH] net: dsa: b53: Drop BCM5301x workaround for a wrong CPU/IMP
|
||||
port
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
On BCM5301x port 8 requires a fixed link when used.
|
||||
|
||||
Years ago when b53 was an OpenWrt downstream driver (with configuration
|
||||
based on sometimes bugged NVRAM) there was a need for a fixup. In case
|
||||
of forcing fixed link for (incorrectly specified) port 5 the code had to
|
||||
actually setup port 8 link.
|
||||
|
||||
For upstream b53 driver with setup based on DT there is no need for that
|
||||
workaround. In DT we have and require correct ports setup.
|
||||
|
||||
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
||||
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Tested-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/dsa/b53/b53_common.c | 6 ------
|
||||
1 file changed, 6 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/b53/b53_common.c
|
||||
+++ b/drivers/net/dsa/b53/b53_common.c
|
||||
@@ -1256,12 +1256,6 @@ static void b53_adjust_link(struct dsa_s
|
||||
return;
|
||||
}
|
||||
}
|
||||
- } else if (is5301x(dev)) {
|
||||
- if (port != dev->cpu_port) {
|
||||
- b53_force_port_config(dev, dev->cpu_port, 2000,
|
||||
- DUPLEX_FULL, true, true);
|
||||
- b53_force_link(dev, dev->cpu_port, 1);
|
||||
- }
|
||||
}
|
||||
|
||||
/* Re-negotiate EEE if it was enabled already */
|
@ -0,0 +1,32 @@
|
||||
From 3ff26b29230c54fea2353b63124c589b61953e14 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
|
||||
Date: Thu, 16 Sep 2021 14:03:53 +0200
|
||||
Subject: [PATCH] net: dsa: b53: Improve flow control setup on BCM5301x
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
According to the Broadcom's reference driver flow control needs to be
|
||||
enabled for any CPU switch port (5, 7 or 8 - depending on which one is
|
||||
used). Current code makes it work only for the port 5. Use
|
||||
dsa_is_cpu_port() which solved that problem.
|
||||
|
||||
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
||||
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Tested-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/dsa/b53/b53_common.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/dsa/b53/b53_common.c
|
||||
+++ b/drivers/net/dsa/b53/b53_common.c
|
||||
@@ -1187,7 +1187,7 @@ static void b53_adjust_link(struct dsa_s
|
||||
return;
|
||||
|
||||
/* Enable flow control on BCM5301x's CPU port */
|
||||
- if (is5301x(dev) && port == dev->cpu_port)
|
||||
+ if (is5301x(dev) && dsa_is_cpu_port(ds, port))
|
||||
tx_pause = rx_pause = true;
|
||||
|
||||
if (phydev->pause) {
|
@ -0,0 +1,205 @@
|
||||
From 7d5af56418d7d01e43247a33b6fe6492ea871923 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
|
||||
Date: Thu, 16 Sep 2021 14:03:54 +0200
|
||||
Subject: [PATCH] net: dsa: b53: Drop unused "cpu_port" field
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
It's set but never used anymore.
|
||||
|
||||
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
||||
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Tested-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/dsa/b53/b53_common.c | 28 ----------------------------
|
||||
drivers/net/dsa/b53/b53_priv.h | 1 -
|
||||
2 files changed, 29 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/b53/b53_common.c
|
||||
+++ b/drivers/net/dsa/b53/b53_common.c
|
||||
@@ -2286,7 +2286,6 @@ static const struct b53_chip_data b53_sw
|
||||
.arl_bins = 2,
|
||||
.arl_buckets = 1024,
|
||||
.imp_port = 5,
|
||||
- .cpu_port = B53_CPU_PORT_25,
|
||||
.duplex_reg = B53_DUPLEX_STAT_FE,
|
||||
},
|
||||
{
|
||||
@@ -2297,7 +2296,6 @@ static const struct b53_chip_data b53_sw
|
||||
.arl_bins = 2,
|
||||
.arl_buckets = 1024,
|
||||
.imp_port = 5,
|
||||
- .cpu_port = B53_CPU_PORT_25,
|
||||
.duplex_reg = B53_DUPLEX_STAT_FE,
|
||||
},
|
||||
{
|
||||
@@ -2308,7 +2306,6 @@ static const struct b53_chip_data b53_sw
|
||||
.arl_bins = 4,
|
||||
.arl_buckets = 1024,
|
||||
.imp_port = 8,
|
||||
- .cpu_port = B53_CPU_PORT,
|
||||
.vta_regs = B53_VTA_REGS,
|
||||
.duplex_reg = B53_DUPLEX_STAT_GE,
|
||||
.jumbo_pm_reg = B53_JUMBO_PORT_MASK,
|
||||
@@ -2322,7 +2319,6 @@ static const struct b53_chip_data b53_sw
|
||||
.arl_bins = 4,
|
||||
.arl_buckets = 1024,
|
||||
.imp_port = 8,
|
||||
- .cpu_port = B53_CPU_PORT,
|
||||
.vta_regs = B53_VTA_REGS,
|
||||
.duplex_reg = B53_DUPLEX_STAT_GE,
|
||||
.jumbo_pm_reg = B53_JUMBO_PORT_MASK,
|
||||
@@ -2336,7 +2332,6 @@ static const struct b53_chip_data b53_sw
|
||||
.arl_bins = 4,
|
||||
.arl_buckets = 1024,
|
||||
.imp_port = 8,
|
||||
- .cpu_port = B53_CPU_PORT,
|
||||
.vta_regs = B53_VTA_REGS_9798,
|
||||
.duplex_reg = B53_DUPLEX_STAT_GE,
|
||||
.jumbo_pm_reg = B53_JUMBO_PORT_MASK,
|
||||
@@ -2350,7 +2345,6 @@ static const struct b53_chip_data b53_sw
|
||||
.arl_bins = 4,
|
||||
.arl_buckets = 1024,
|
||||
.imp_port = 8,
|
||||
- .cpu_port = B53_CPU_PORT,
|
||||
.vta_regs = B53_VTA_REGS_9798,
|
||||
.duplex_reg = B53_DUPLEX_STAT_GE,
|
||||
.jumbo_pm_reg = B53_JUMBO_PORT_MASK,
|
||||
@@ -2365,7 +2359,6 @@ static const struct b53_chip_data b53_sw
|
||||
.arl_buckets = 1024,
|
||||
.vta_regs = B53_VTA_REGS,
|
||||
.imp_port = 8,
|
||||
- .cpu_port = B53_CPU_PORT,
|
||||
.duplex_reg = B53_DUPLEX_STAT_GE,
|
||||
.jumbo_pm_reg = B53_JUMBO_PORT_MASK,
|
||||
.jumbo_size_reg = B53_JUMBO_MAX_SIZE,
|
||||
@@ -2378,7 +2371,6 @@ static const struct b53_chip_data b53_sw
|
||||
.arl_bins = 4,
|
||||
.arl_buckets = 1024,
|
||||
.imp_port = 8,
|
||||
- .cpu_port = B53_CPU_PORT,
|
||||
.vta_regs = B53_VTA_REGS,
|
||||
.duplex_reg = B53_DUPLEX_STAT_GE,
|
||||
.jumbo_pm_reg = B53_JUMBO_PORT_MASK,
|
||||
@@ -2392,7 +2384,6 @@ static const struct b53_chip_data b53_sw
|
||||
.arl_bins = 4,
|
||||
.arl_buckets = 1024,
|
||||
.imp_port = 8,
|
||||
- .cpu_port = B53_CPU_PORT,
|
||||
.vta_regs = B53_VTA_REGS,
|
||||
.duplex_reg = B53_DUPLEX_STAT_GE,
|
||||
.jumbo_pm_reg = B53_JUMBO_PORT_MASK,
|
||||
@@ -2406,7 +2397,6 @@ static const struct b53_chip_data b53_sw
|
||||
.arl_bins = 4,
|
||||
.arl_buckets = 1024,
|
||||
.imp_port = 8,
|
||||
- .cpu_port = B53_CPU_PORT,
|
||||
.vta_regs = B53_VTA_REGS_63XX,
|
||||
.duplex_reg = B53_DUPLEX_STAT_63XX,
|
||||
.jumbo_pm_reg = B53_JUMBO_PORT_MASK_63XX,
|
||||
@@ -2420,7 +2410,6 @@ static const struct b53_chip_data b53_sw
|
||||
.arl_bins = 4,
|
||||
.arl_buckets = 1024,
|
||||
.imp_port = 8,
|
||||
- .cpu_port = B53_CPU_PORT_25, /* TODO: auto detect */
|
||||
.vta_regs = B53_VTA_REGS,
|
||||
.duplex_reg = B53_DUPLEX_STAT_GE,
|
||||
.jumbo_pm_reg = B53_JUMBO_PORT_MASK,
|
||||
@@ -2434,7 +2423,6 @@ static const struct b53_chip_data b53_sw
|
||||
.arl_bins = 4,
|
||||
.arl_buckets = 1024,
|
||||
.imp_port = 8,
|
||||
- .cpu_port = B53_CPU_PORT_25, /* TODO: auto detect */
|
||||
.vta_regs = B53_VTA_REGS,
|
||||
.duplex_reg = B53_DUPLEX_STAT_GE,
|
||||
.jumbo_pm_reg = B53_JUMBO_PORT_MASK,
|
||||
@@ -2448,7 +2436,6 @@ static const struct b53_chip_data b53_sw
|
||||
.arl_bins = 4,
|
||||
.arl_buckets = 1024,
|
||||
.imp_port = 8,
|
||||
- .cpu_port = B53_CPU_PORT_25, /* TODO: auto detect */
|
||||
.vta_regs = B53_VTA_REGS,
|
||||
.duplex_reg = B53_DUPLEX_STAT_GE,
|
||||
.jumbo_pm_reg = B53_JUMBO_PORT_MASK,
|
||||
@@ -2462,7 +2449,6 @@ static const struct b53_chip_data b53_sw
|
||||
.arl_bins = 4,
|
||||
.arl_buckets = 1024,
|
||||
.imp_port = 8,
|
||||
- .cpu_port = B53_CPU_PORT_25, /* TODO: auto detect */
|
||||
.vta_regs = B53_VTA_REGS,
|
||||
.duplex_reg = B53_DUPLEX_STAT_GE,
|
||||
.jumbo_pm_reg = B53_JUMBO_PORT_MASK,
|
||||
@@ -2476,7 +2462,6 @@ static const struct b53_chip_data b53_sw
|
||||
.arl_bins = 4,
|
||||
.arl_buckets = 1024,
|
||||
.imp_port = 8,
|
||||
- .cpu_port = B53_CPU_PORT_25, /* TODO: auto detect */
|
||||
.vta_regs = B53_VTA_REGS,
|
||||
.duplex_reg = B53_DUPLEX_STAT_GE,
|
||||
.jumbo_pm_reg = B53_JUMBO_PORT_MASK,
|
||||
@@ -2490,7 +2475,6 @@ static const struct b53_chip_data b53_sw
|
||||
.arl_bins = 4,
|
||||
.arl_buckets = 1024,
|
||||
.imp_port = 8,
|
||||
- .cpu_port = B53_CPU_PORT,
|
||||
.vta_regs = B53_VTA_REGS,
|
||||
.duplex_reg = B53_DUPLEX_STAT_GE,
|
||||
.jumbo_pm_reg = B53_JUMBO_PORT_MASK,
|
||||
@@ -2504,7 +2488,6 @@ static const struct b53_chip_data b53_sw
|
||||
.arl_bins = 4,
|
||||
.arl_buckets = 1024,
|
||||
.imp_port = 8,
|
||||
- .cpu_port = B53_CPU_PORT,
|
||||
.vta_regs = B53_VTA_REGS,
|
||||
.duplex_reg = B53_DUPLEX_STAT_GE,
|
||||
.jumbo_pm_reg = B53_JUMBO_PORT_MASK,
|
||||
@@ -2518,7 +2501,6 @@ static const struct b53_chip_data b53_sw
|
||||
.arl_bins = 4,
|
||||
.arl_buckets = 1024,
|
||||
.imp_port = 8,
|
||||
- .cpu_port = B53_CPU_PORT,
|
||||
.vta_regs = B53_VTA_REGS,
|
||||
.duplex_reg = B53_DUPLEX_STAT_GE,
|
||||
.jumbo_pm_reg = B53_JUMBO_PORT_MASK,
|
||||
@@ -2532,7 +2514,6 @@ static const struct b53_chip_data b53_sw
|
||||
.arl_bins = 4,
|
||||
.arl_buckets = 256,
|
||||
.imp_port = 8,
|
||||
- .cpu_port = B53_CPU_PORT,
|
||||
.vta_regs = B53_VTA_REGS,
|
||||
.duplex_reg = B53_DUPLEX_STAT_GE,
|
||||
.jumbo_pm_reg = B53_JUMBO_PORT_MASK,
|
||||
@@ -2558,7 +2539,6 @@ static int b53_switch_init(struct b53_de
|
||||
dev->vta_regs[2] = chip->vta_regs[2];
|
||||
dev->jumbo_pm_reg = chip->jumbo_pm_reg;
|
||||
dev->imp_port = chip->imp_port;
|
||||
- dev->cpu_port = chip->cpu_port;
|
||||
dev->num_vlans = chip->vlans;
|
||||
dev->num_arl_bins = chip->arl_bins;
|
||||
dev->num_arl_buckets = chip->arl_buckets;
|
||||
@@ -2590,13 +2570,6 @@ static int b53_switch_init(struct b53_de
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
- } else if (dev->chip_id == BCM53115_DEVICE_ID) {
|
||||
- u64 strap_value;
|
||||
-
|
||||
- b53_read48(dev, B53_STAT_PAGE, B53_STRAP_VALUE, &strap_value);
|
||||
- /* use second IMP port if GMII is enabled */
|
||||
- if (strap_value & SV_GMII_CTRL_115)
|
||||
- dev->cpu_port = 5;
|
||||
}
|
||||
|
||||
dev->num_ports = fls(dev->enabled_ports);
|
||||
--- a/drivers/net/dsa/b53/b53_priv.h
|
||||
+++ b/drivers/net/dsa/b53/b53_priv.h
|
||||
@@ -123,7 +123,6 @@ struct b53_device {
|
||||
/* used ports mask */
|
||||
u16 enabled_ports;
|
||||
unsigned int imp_port;
|
||||
- unsigned int cpu_port;
|
||||
|
||||
/* connect specific data */
|
||||
u8 current_page;
|
@ -0,0 +1,138 @@
|
||||
From bea7907837c57a0aaac009931eb14efb056dafab Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Oltean <vladimir.oltean@nxp.com>
|
||||
Date: Thu, 29 Jul 2021 17:56:00 +0300
|
||||
Subject: [PATCH] net: dsa: don't set skb->offload_fwd_mark when not offloading
|
||||
the bridge
|
||||
|
||||
DSA has gained the recent ability to deal gracefully with upper
|
||||
interfaces it cannot offload, such as the bridge, bonding or team
|
||||
drivers. When such uppers exist, the ports are still in standalone mode
|
||||
as far as the hardware is concerned.
|
||||
|
||||
But when we deliver packets to the software bridge in order for that to
|
||||
do the forwarding, there is an unpleasant surprise in that the bridge
|
||||
will refuse to forward them. This is because we unconditionally set
|
||||
skb->offload_fwd_mark = true, meaning that the bridge thinks the frames
|
||||
were already forwarded in hardware by us.
|
||||
|
||||
Since dp->bridge_dev is populated only when there is hardware offload
|
||||
for it, but not in the software fallback case, let's introduce a new
|
||||
helper that can be called from the tagger data path which sets the
|
||||
skb->offload_fwd_mark accordingly to zero when there is no hardware
|
||||
offload for bridging. This lets the bridge forward packets back to other
|
||||
interfaces of our switch, if needed.
|
||||
|
||||
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
|
||||
Reviewed-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
net/dsa/dsa_priv.h | 14 ++++++++++++++
|
||||
net/dsa/tag_brcm.c | 4 ++--
|
||||
net/dsa/tag_dsa.c | 15 +++++++++++----
|
||||
net/dsa/tag_ksz.c | 2 +-
|
||||
net/dsa/tag_lan9303.c | 3 ++-
|
||||
net/dsa/tag_mtk.c | 2 +-
|
||||
net/dsa/tag_ocelot.c | 2 +-
|
||||
net/dsa/tag_rtl4_a.c | 2 +-
|
||||
net/dsa/tag_sja1105.c | 20 ++++++++++++++------
|
||||
9 files changed, 47 insertions(+), 17 deletions(-)
|
||||
|
||||
--- a/net/dsa/dsa_priv.h
|
||||
+++ b/net/dsa/dsa_priv.h
|
||||
@@ -266,6 +266,20 @@ static inline struct sk_buff *dsa_untag_
|
||||
return skb;
|
||||
}
|
||||
|
||||
+/* If the ingress port offloads the bridge, we mark the frame as autonomously
|
||||
+ * forwarded by hardware, so the software bridge doesn't forward in twice, back
|
||||
+ * to us, because we already did. However, if we're in fallback mode and we do
|
||||
+ * software bridging, we are not offloading it, therefore the dp->bridge_dev
|
||||
+ * pointer is not populated, and flooding needs to be done by software (we are
|
||||
+ * effectively operating in standalone ports mode).
|
||||
+ */
|
||||
+static inline void dsa_default_offload_fwd_mark(struct sk_buff *skb)
|
||||
+{
|
||||
+ struct dsa_port *dp = dsa_slave_to_port(skb->dev);
|
||||
+
|
||||
+ skb->offload_fwd_mark = !!(dp->bridge_dev);
|
||||
+}
|
||||
+
|
||||
/* switch.c */
|
||||
int dsa_switch_register_notifier(struct dsa_switch *ds);
|
||||
void dsa_switch_unregister_notifier(struct dsa_switch *ds);
|
||||
--- a/net/dsa/tag_brcm.c
|
||||
+++ b/net/dsa/tag_brcm.c
|
||||
@@ -166,7 +166,7 @@ static struct sk_buff *brcm_tag_rcv_ll(s
|
||||
/* Remove Broadcom tag and update checksum */
|
||||
skb_pull_rcsum(skb, BRCM_TAG_LEN);
|
||||
|
||||
- skb->offload_fwd_mark = 1;
|
||||
+ dsa_default_offload_fwd_mark(skb);
|
||||
|
||||
return skb;
|
||||
}
|
||||
@@ -270,7 +270,7 @@ static struct sk_buff *brcm_leg_tag_rcv(
|
||||
/* Remove Broadcom tag and update checksum */
|
||||
skb_pull_rcsum(skb, BRCM_LEG_TAG_LEN);
|
||||
|
||||
- skb->offload_fwd_mark = 1;
|
||||
+ dsa_default_offload_fwd_mark(skb);
|
||||
|
||||
/* Move the Ethernet DA and SA */
|
||||
memmove(skb->data - ETH_HLEN,
|
||||
--- a/net/dsa/tag_ksz.c
|
||||
+++ b/net/dsa/tag_ksz.c
|
||||
@@ -24,7 +24,7 @@ static struct sk_buff *ksz_common_rcv(st
|
||||
|
||||
pskb_trim_rcsum(skb, skb->len - len);
|
||||
|
||||
- skb->offload_fwd_mark = true;
|
||||
+ dsa_default_offload_fwd_mark(skb);
|
||||
|
||||
return skb;
|
||||
}
|
||||
--- a/net/dsa/tag_lan9303.c
|
||||
+++ b/net/dsa/tag_lan9303.c
|
||||
@@ -115,7 +115,8 @@ static struct sk_buff *lan9303_rcv(struc
|
||||
skb_pull_rcsum(skb, 2 + 2);
|
||||
memmove(skb->data - ETH_HLEN, skb->data - (ETH_HLEN + LAN9303_TAG_LEN),
|
||||
2 * ETH_ALEN);
|
||||
- skb->offload_fwd_mark = !(lan9303_tag1 & LAN9303_TAG_RX_TRAPPED_TO_CPU);
|
||||
+ if (!(lan9303_tag1 & LAN9303_TAG_RX_TRAPPED_TO_CPU))
|
||||
+ dsa_default_offload_fwd_mark(skb);
|
||||
|
||||
return skb;
|
||||
}
|
||||
--- a/net/dsa/tag_mtk.c
|
||||
+++ b/net/dsa/tag_mtk.c
|
||||
@@ -104,7 +104,7 @@ static struct sk_buff *mtk_tag_rcv(struc
|
||||
|
||||
/* Only unicast or broadcast frames are offloaded */
|
||||
if (likely(!is_multicast_skb))
|
||||
- skb->offload_fwd_mark = 1;
|
||||
+ dsa_default_offload_fwd_mark(skb);
|
||||
|
||||
return skb;
|
||||
}
|
||||
--- a/net/dsa/tag_ocelot.c
|
||||
+++ b/net/dsa/tag_ocelot.c
|
||||
@@ -225,7 +225,7 @@ static struct sk_buff *ocelot_rcv(struct
|
||||
*/
|
||||
return NULL;
|
||||
|
||||
- skb->offload_fwd_mark = 1;
|
||||
+ dsa_default_offload_fwd_mark(skb);
|
||||
skb->priority = qos_class;
|
||||
|
||||
/* Ocelot switches copy frames unmodified to the CPU. However, it is
|
||||
--- a/net/dsa/tag_rtl4_a.c
|
||||
+++ b/net/dsa/tag_rtl4_a.c
|
||||
@@ -115,7 +115,7 @@ static struct sk_buff *rtl4a_tag_rcv(str
|
||||
skb->data - ETH_HLEN - RTL4_A_HDR_LEN,
|
||||
2 * ETH_ALEN);
|
||||
|
||||
- skb->offload_fwd_mark = 1;
|
||||
+ dsa_default_offload_fwd_mark(skb);
|
||||
|
||||
return skb;
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
From b4df02b562f4aa14ff6811f30e1b4d2159585c59 Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Sun, 19 Sep 2021 18:28:15 +0200
|
||||
Subject: net: phy: at803x: add support for qca 8327 A variant internal phy
|
||||
|
||||
For qca8327 internal phy there are 2 different switch variant with 2
|
||||
different phy id. Add this missing variant so the internal phy can be
|
||||
correctly identified and fixed.
|
||||
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/phy/at803x.c | 25 ++++++++++++++++++++-----
|
||||
1 file changed, 20 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/at803x.c
|
||||
+++ b/drivers/net/phy/at803x.c
|
||||
@@ -148,7 +148,8 @@
|
||||
#define AT803X_PAGE_FIBER 0
|
||||
#define AT803X_PAGE_COPPER 1
|
||||
|
||||
-#define QCA8327_PHY_ID 0x004dd034
|
||||
+#define QCA8327_A_PHY_ID 0x004dd033
|
||||
+#define QCA8327_B_PHY_ID 0x004dd034
|
||||
#define QCA8337_PHY_ID 0x004dd036
|
||||
#define QCA8K_PHY_ID_MASK 0xffffffff
|
||||
|
||||
@@ -1329,10 +1330,23 @@ static struct phy_driver at803x_driver[]
|
||||
.get_strings = at803x_get_strings,
|
||||
.get_stats = at803x_get_stats,
|
||||
}, {
|
||||
- /* QCA8327 */
|
||||
- .phy_id = QCA8327_PHY_ID,
|
||||
+ /* QCA8327-A from switch QCA8327-AL1A */
|
||||
+ .phy_id = QCA8327_A_PHY_ID,
|
||||
.phy_id_mask = QCA8K_PHY_ID_MASK,
|
||||
- .name = "QCA PHY 8327",
|
||||
+ .name = "QCA PHY 8327-A",
|
||||
+ /* PHY_GBIT_FEATURES */
|
||||
+ .probe = at803x_probe,
|
||||
+ .flags = PHY_IS_INTERNAL,
|
||||
+ .config_init = qca83xx_config_init,
|
||||
+ .soft_reset = genphy_soft_reset,
|
||||
+ .get_sset_count = at803x_get_sset_count,
|
||||
+ .get_strings = at803x_get_strings,
|
||||
+ .get_stats = at803x_get_stats,
|
||||
+}, {
|
||||
+ /* QCA8327-B from switch QCA8327-BL1A */
|
||||
+ .phy_id = QCA8327_B_PHY_ID,
|
||||
+ .phy_id_mask = QCA8K_PHY_ID_MASK,
|
||||
+ .name = "QCA PHY 8327-B",
|
||||
/* PHY_GBIT_FEATURES */
|
||||
.probe = at803x_probe,
|
||||
.flags = PHY_IS_INTERNAL,
|
||||
@@ -1352,7 +1366,8 @@ static struct mdio_device_id __maybe_unu
|
||||
{ PHY_ID_MATCH_EXACT(ATH8035_PHY_ID) },
|
||||
{ PHY_ID_MATCH_EXACT(ATH9331_PHY_ID) },
|
||||
{ PHY_ID_MATCH_EXACT(QCA8337_PHY_ID) },
|
||||
- { PHY_ID_MATCH_EXACT(QCA8327_PHY_ID) },
|
||||
+ { PHY_ID_MATCH_EXACT(QCA8327_A_PHY_ID) },
|
||||
+ { PHY_ID_MATCH_EXACT(QCA8327_B_PHY_ID) },
|
||||
{ }
|
||||
};
|
||||
|
@ -0,0 +1,45 @@
|
||||
From 15b9df4ece17d084f14eb0ca1cf05f2ad497e425 Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Sun, 19 Sep 2021 18:28:16 +0200
|
||||
Subject: net: phy: at803x: add resume/suspend function to qca83xx phy
|
||||
|
||||
Add resume/suspend function to qca83xx internal phy.
|
||||
We can't use the at803x generic function as the documentation lacks of
|
||||
any support for WoL regs.
|
||||
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/phy/at803x.c | 6 ++++++
|
||||
1 file changed, 6 insertions(+)
|
||||
|
||||
--- a/drivers/net/phy/at803x.c
|
||||
+++ b/drivers/net/phy/at803x.c
|
||||
@@ -1329,6 +1329,8 @@ static struct phy_driver at803x_driver[]
|
||||
.get_sset_count = at803x_get_sset_count,
|
||||
.get_strings = at803x_get_strings,
|
||||
.get_stats = at803x_get_stats,
|
||||
+ .suspend = genphy_suspend,
|
||||
+ .resume = genphy_resume,
|
||||
}, {
|
||||
/* QCA8327-A from switch QCA8327-AL1A */
|
||||
.phy_id = QCA8327_A_PHY_ID,
|
||||
@@ -1342,6 +1344,8 @@ static struct phy_driver at803x_driver[]
|
||||
.get_sset_count = at803x_get_sset_count,
|
||||
.get_strings = at803x_get_strings,
|
||||
.get_stats = at803x_get_stats,
|
||||
+ .suspend = genphy_suspend,
|
||||
+ .resume = genphy_resume,
|
||||
}, {
|
||||
/* QCA8327-B from switch QCA8327-BL1A */
|
||||
.phy_id = QCA8327_B_PHY_ID,
|
||||
@@ -1355,6 +1359,8 @@ static struct phy_driver at803x_driver[]
|
||||
.get_sset_count = at803x_get_sset_count,
|
||||
.get_strings = at803x_get_strings,
|
||||
.get_stats = at803x_get_stats,
|
||||
+ .suspend = genphy_suspend,
|
||||
+ .resume = genphy_resume,
|
||||
}, };
|
||||
|
||||
module_phy_driver(at803x_driver);
|
@ -0,0 +1,95 @@
|
||||
From d44fd8604a4ab92119adb35f05fd87612af722b5 Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Sun, 19 Sep 2021 18:28:17 +0200
|
||||
Subject: net: phy: at803x: fix spacing and improve name for 83xx phy
|
||||
|
||||
Fix spacing and improve name for 83xx phy following other phy in the
|
||||
same driver.
|
||||
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/phy/at803x.c | 60 ++++++++++++++++++++++++------------------------
|
||||
1 file changed, 30 insertions(+), 30 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/at803x.c
|
||||
+++ b/drivers/net/phy/at803x.c
|
||||
@@ -1318,47 +1318,47 @@ static struct phy_driver at803x_driver[]
|
||||
.config_aneg = at803x_config_aneg,
|
||||
}, {
|
||||
/* QCA8337 */
|
||||
- .phy_id = QCA8337_PHY_ID,
|
||||
- .phy_id_mask = QCA8K_PHY_ID_MASK,
|
||||
- .name = "QCA PHY 8337",
|
||||
+ .phy_id = QCA8337_PHY_ID,
|
||||
+ .phy_id_mask = QCA8K_PHY_ID_MASK,
|
||||
+ .name = "Qualcomm Atheros 8337 internal PHY",
|
||||
/* PHY_GBIT_FEATURES */
|
||||
- .probe = at803x_probe,
|
||||
- .flags = PHY_IS_INTERNAL,
|
||||
- .config_init = qca83xx_config_init,
|
||||
- .soft_reset = genphy_soft_reset,
|
||||
- .get_sset_count = at803x_get_sset_count,
|
||||
- .get_strings = at803x_get_strings,
|
||||
- .get_stats = at803x_get_stats,
|
||||
+ .probe = at803x_probe,
|
||||
+ .flags = PHY_IS_INTERNAL,
|
||||
+ .config_init = qca83xx_config_init,
|
||||
+ .soft_reset = genphy_soft_reset,
|
||||
+ .get_sset_count = at803x_get_sset_count,
|
||||
+ .get_strings = at803x_get_strings,
|
||||
+ .get_stats = at803x_get_stats,
|
||||
.suspend = genphy_suspend,
|
||||
.resume = genphy_resume,
|
||||
}, {
|
||||
/* QCA8327-A from switch QCA8327-AL1A */
|
||||
- .phy_id = QCA8327_A_PHY_ID,
|
||||
- .phy_id_mask = QCA8K_PHY_ID_MASK,
|
||||
- .name = "QCA PHY 8327-A",
|
||||
+ .phy_id = QCA8327_A_PHY_ID,
|
||||
+ .phy_id_mask = QCA8K_PHY_ID_MASK,
|
||||
+ .name = "Qualcomm Atheros 8327-A internal PHY",
|
||||
/* PHY_GBIT_FEATURES */
|
||||
- .probe = at803x_probe,
|
||||
- .flags = PHY_IS_INTERNAL,
|
||||
- .config_init = qca83xx_config_init,
|
||||
- .soft_reset = genphy_soft_reset,
|
||||
- .get_sset_count = at803x_get_sset_count,
|
||||
- .get_strings = at803x_get_strings,
|
||||
- .get_stats = at803x_get_stats,
|
||||
+ .probe = at803x_probe,
|
||||
+ .flags = PHY_IS_INTERNAL,
|
||||
+ .config_init = qca83xx_config_init,
|
||||
+ .soft_reset = genphy_soft_reset,
|
||||
+ .get_sset_count = at803x_get_sset_count,
|
||||
+ .get_strings = at803x_get_strings,
|
||||
+ .get_stats = at803x_get_stats,
|
||||
.suspend = genphy_suspend,
|
||||
.resume = genphy_resume,
|
||||
}, {
|
||||
/* QCA8327-B from switch QCA8327-BL1A */
|
||||
- .phy_id = QCA8327_B_PHY_ID,
|
||||
- .phy_id_mask = QCA8K_PHY_ID_MASK,
|
||||
- .name = "QCA PHY 8327-B",
|
||||
+ .phy_id = QCA8327_B_PHY_ID,
|
||||
+ .phy_id_mask = QCA8K_PHY_ID_MASK,
|
||||
+ .name = "Qualcomm Atheros 8327-B internal PHY",
|
||||
/* PHY_GBIT_FEATURES */
|
||||
- .probe = at803x_probe,
|
||||
- .flags = PHY_IS_INTERNAL,
|
||||
- .config_init = qca83xx_config_init,
|
||||
- .soft_reset = genphy_soft_reset,
|
||||
- .get_sset_count = at803x_get_sset_count,
|
||||
- .get_strings = at803x_get_strings,
|
||||
- .get_stats = at803x_get_stats,
|
||||
+ .probe = at803x_probe,
|
||||
+ .flags = PHY_IS_INTERNAL,
|
||||
+ .config_init = qca83xx_config_init,
|
||||
+ .soft_reset = genphy_soft_reset,
|
||||
+ .get_sset_count = at803x_get_sset_count,
|
||||
+ .get_strings = at803x_get_strings,
|
||||
+ .get_stats = at803x_get_stats,
|
||||
.suspend = genphy_suspend,
|
||||
.resume = genphy_resume,
|
||||
}, };
|
@ -0,0 +1,131 @@
|
||||
From ba3c01ee02ed0d821c9f241f179bbc9457542b8f Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Sun, 10 Oct 2021 00:46:15 +0200
|
||||
Subject: net: phy: at803x: fix resume for QCA8327 phy
|
||||
|
||||
From Documentation phy resume triggers phy reset and restart
|
||||
auto-negotiation. Add a dedicated function to wait reset to finish as
|
||||
it was notice a regression where port sometime are not reliable after a
|
||||
suspend/resume session. The reset wait logic is copied from phy_poll_reset.
|
||||
Add dedicated suspend function to use genphy_suspend only with QCA8337
|
||||
phy and set only additional debug settings for QCA8327. With more test
|
||||
it was reported that QCA8327 doesn't proprely support this mode and
|
||||
using this cause the unreliability of the switch ports, especially the
|
||||
malfunction of the port0.
|
||||
|
||||
Fixes: 15b9df4ece17 ("net: phy: at803x: add resume/suspend function to qca83xx phy")
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/phy/at803x.c | 69 +++++++++++++++++++++++++++++++++++++++++++-----
|
||||
1 file changed, 63 insertions(+), 6 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/at803x.c
|
||||
+++ b/drivers/net/phy/at803x.c
|
||||
@@ -92,9 +92,14 @@
|
||||
#define AT803X_DEBUG_REG_5 0x05
|
||||
#define AT803X_DEBUG_TX_CLK_DLY_EN BIT(8)
|
||||
|
||||
+#define AT803X_DEBUG_REG_HIB_CTRL 0x0b
|
||||
+#define AT803X_DEBUG_HIB_CTRL_SEL_RST_80U BIT(10)
|
||||
+#define AT803X_DEBUG_HIB_CTRL_EN_ANY_CHANGE BIT(13)
|
||||
+
|
||||
#define AT803X_DEBUG_REG_3C 0x3C
|
||||
|
||||
#define AT803X_DEBUG_REG_3D 0x3D
|
||||
+#define AT803X_DEBUG_GATE_CLK_IN1000 BIT(6)
|
||||
|
||||
#define AT803X_DEBUG_REG_1F 0x1F
|
||||
#define AT803X_DEBUG_PLL_ON BIT(2)
|
||||
@@ -1220,6 +1225,58 @@ static int qca83xx_config_init(struct ph
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int qca83xx_resume(struct phy_device *phydev)
|
||||
+{
|
||||
+ int ret, val;
|
||||
+
|
||||
+ /* Skip reset if not suspended */
|
||||
+ if (!phydev->suspended)
|
||||
+ return 0;
|
||||
+
|
||||
+ /* Reinit the port, reset values set by suspend */
|
||||
+ qca83xx_config_init(phydev);
|
||||
+
|
||||
+ /* Reset the port on port resume */
|
||||
+ phy_set_bits(phydev, MII_BMCR, BMCR_RESET | BMCR_ANENABLE);
|
||||
+
|
||||
+ /* On resume from suspend the switch execute a reset and
|
||||
+ * restart auto-negotiation. Wait for reset to complete.
|
||||
+ */
|
||||
+ ret = phy_read_poll_timeout(phydev, MII_BMCR, val, !(val & BMCR_RESET),
|
||||
+ 50000, 600000, true);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ msleep(1);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int qca83xx_suspend(struct phy_device *phydev)
|
||||
+{
|
||||
+ u16 mask = 0;
|
||||
+
|
||||
+ /* Only QCA8337 support actual suspend.
|
||||
+ * QCA8327 cause port unreliability when phy suspend
|
||||
+ * is set.
|
||||
+ */
|
||||
+ if (phydev->drv->phy_id == QCA8337_PHY_ID) {
|
||||
+ genphy_suspend(phydev);
|
||||
+ } else {
|
||||
+ mask |= ~(BMCR_SPEED1000 | BMCR_FULLDPLX);
|
||||
+ phy_modify(phydev, MII_BMCR, mask, 0);
|
||||
+ }
|
||||
+
|
||||
+ at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_3D,
|
||||
+ AT803X_DEBUG_GATE_CLK_IN1000, 0);
|
||||
+
|
||||
+ at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_HIB_CTRL,
|
||||
+ AT803X_DEBUG_HIB_CTRL_EN_ANY_CHANGE |
|
||||
+ AT803X_DEBUG_HIB_CTRL_SEL_RST_80U, 0);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static struct phy_driver at803x_driver[] = {
|
||||
{
|
||||
/* Qualcomm Atheros AR8035 */
|
||||
@@ -1329,8 +1386,8 @@ static struct phy_driver at803x_driver[]
|
||||
.get_sset_count = at803x_get_sset_count,
|
||||
.get_strings = at803x_get_strings,
|
||||
.get_stats = at803x_get_stats,
|
||||
- .suspend = genphy_suspend,
|
||||
- .resume = genphy_resume,
|
||||
+ .suspend = qca83xx_suspend,
|
||||
+ .resume = qca83xx_resume,
|
||||
}, {
|
||||
/* QCA8327-A from switch QCA8327-AL1A */
|
||||
.phy_id = QCA8327_A_PHY_ID,
|
||||
@@ -1344,8 +1401,8 @@ static struct phy_driver at803x_driver[]
|
||||
.get_sset_count = at803x_get_sset_count,
|
||||
.get_strings = at803x_get_strings,
|
||||
.get_stats = at803x_get_stats,
|
||||
- .suspend = genphy_suspend,
|
||||
- .resume = genphy_resume,
|
||||
+ .suspend = qca83xx_suspend,
|
||||
+ .resume = qca83xx_resume,
|
||||
}, {
|
||||
/* QCA8327-B from switch QCA8327-BL1A */
|
||||
.phy_id = QCA8327_B_PHY_ID,
|
||||
@@ -1359,8 +1416,8 @@ static struct phy_driver at803x_driver[]
|
||||
.get_sset_count = at803x_get_sset_count,
|
||||
.get_strings = at803x_get_strings,
|
||||
.get_stats = at803x_get_stats,
|
||||
- .suspend = genphy_suspend,
|
||||
- .resume = genphy_resume,
|
||||
+ .suspend = qca83xx_suspend,
|
||||
+ .resume = qca83xx_resume,
|
||||
}, };
|
||||
|
||||
module_phy_driver(at803x_driver);
|
@ -0,0 +1,91 @@
|
||||
From 1ca8311949aec5c9447645731ef1c6bc5bd71350 Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Sun, 10 Oct 2021 00:46:16 +0200
|
||||
Subject: net: phy: at803x: add DAC amplitude fix for 8327 phy
|
||||
|
||||
QCA8327 internal phy require DAC amplitude adjustement set to +6% with
|
||||
100m speed. Also add additional define to report a change of the same
|
||||
reg in QCA8337. (different scope it does set 1000m voltage)
|
||||
Add link_change_notify function to set the proper amplitude adjustement
|
||||
on PHY_RUNNING state and disable on any other state.
|
||||
|
||||
Fixes: b4df02b562f4 ("net: phy: at803x: add support for qca 8327 A variant internal phy")
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/phy/at803x.c | 33 +++++++++++++++++++++++++++++++++
|
||||
1 file changed, 33 insertions(+)
|
||||
|
||||
--- a/drivers/net/phy/at803x.c
|
||||
+++ b/drivers/net/phy/at803x.c
|
||||
@@ -87,6 +87,8 @@
|
||||
#define AT803X_PSSR_MR_AN_COMPLETE 0x0200
|
||||
|
||||
#define AT803X_DEBUG_REG_0 0x00
|
||||
+#define QCA8327_DEBUG_MANU_CTRL_EN BIT(2)
|
||||
+#define QCA8337_DEBUG_MANU_CTRL_EN GENMASK(3, 2)
|
||||
#define AT803X_DEBUG_RX_CLK_DLY_EN BIT(15)
|
||||
|
||||
#define AT803X_DEBUG_REG_5 0x05
|
||||
@@ -1222,9 +1224,37 @@ static int qca83xx_config_init(struct ph
|
||||
break;
|
||||
}
|
||||
|
||||
+ /* QCA8327 require DAC amplitude adjustment for 100m set to +6%.
|
||||
+ * Disable on init and enable only with 100m speed following
|
||||
+ * qca original source code.
|
||||
+ */
|
||||
+ if (phydev->drv->phy_id == QCA8327_A_PHY_ID ||
|
||||
+ phydev->drv->phy_id == QCA8327_B_PHY_ID)
|
||||
+ at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_0,
|
||||
+ QCA8327_DEBUG_MANU_CTRL_EN, 0);
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static void qca83xx_link_change_notify(struct phy_device *phydev)
|
||||
+{
|
||||
+ /* QCA8337 doesn't require DAC Amplitude adjustement */
|
||||
+ if (phydev->drv->phy_id == QCA8337_PHY_ID)
|
||||
+ return;
|
||||
+
|
||||
+ /* Set DAC Amplitude adjustment to +6% for 100m on link running */
|
||||
+ if (phydev->state == PHY_RUNNING) {
|
||||
+ if (phydev->speed == SPEED_100)
|
||||
+ at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_0,
|
||||
+ QCA8327_DEBUG_MANU_CTRL_EN,
|
||||
+ QCA8327_DEBUG_MANU_CTRL_EN);
|
||||
+ } else {
|
||||
+ /* Reset DAC Amplitude adjustment */
|
||||
+ at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_0,
|
||||
+ QCA8327_DEBUG_MANU_CTRL_EN, 0);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static int qca83xx_resume(struct phy_device *phydev)
|
||||
{
|
||||
int ret, val;
|
||||
@@ -1379,6 +1409,7 @@ static struct phy_driver at803x_driver[]
|
||||
.phy_id_mask = QCA8K_PHY_ID_MASK,
|
||||
.name = "Qualcomm Atheros 8337 internal PHY",
|
||||
/* PHY_GBIT_FEATURES */
|
||||
+ .link_change_notify = qca83xx_link_change_notify,
|
||||
.probe = at803x_probe,
|
||||
.flags = PHY_IS_INTERNAL,
|
||||
.config_init = qca83xx_config_init,
|
||||
@@ -1394,6 +1425,7 @@ static struct phy_driver at803x_driver[]
|
||||
.phy_id_mask = QCA8K_PHY_ID_MASK,
|
||||
.name = "Qualcomm Atheros 8327-A internal PHY",
|
||||
/* PHY_GBIT_FEATURES */
|
||||
+ .link_change_notify = qca83xx_link_change_notify,
|
||||
.probe = at803x_probe,
|
||||
.flags = PHY_IS_INTERNAL,
|
||||
.config_init = qca83xx_config_init,
|
||||
@@ -1409,6 +1441,7 @@ static struct phy_driver at803x_driver[]
|
||||
.phy_id_mask = QCA8K_PHY_ID_MASK,
|
||||
.name = "Qualcomm Atheros 8327-B internal PHY",
|
||||
/* PHY_GBIT_FEATURES */
|
||||
+ .link_change_notify = qca83xx_link_change_notify,
|
||||
.probe = at803x_probe,
|
||||
.flags = PHY_IS_INTERNAL,
|
||||
.config_init = qca83xx_config_init,
|
@ -0,0 +1,27 @@
|
||||
From 9d1c29b4028557a496be9c5eb2b4b86063700636 Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Sun, 10 Oct 2021 00:46:17 +0200
|
||||
Subject: net: phy: at803x: enable prefer master for 83xx internal phy
|
||||
|
||||
From original QCA source code the port was set to prefer master as port
|
||||
type in 1000BASE-T mode. Apply the same settings also here.
|
||||
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/phy/at803x.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
--- a/drivers/net/phy/at803x.c
|
||||
+++ b/drivers/net/phy/at803x.c
|
||||
@@ -1233,6 +1233,9 @@ static int qca83xx_config_init(struct ph
|
||||
at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_0,
|
||||
QCA8327_DEBUG_MANU_CTRL_EN, 0);
|
||||
|
||||
+ /* Following original QCA sourcecode set port to prefer master */
|
||||
+ phy_set_bits(phydev, MII_CTRL1000, CTL1000_PREFER_MASTER);
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user