sync with upstream patch

This commit is contained in:
coolsnowwolf 2019-01-02 21:48:12 +08:00
parent 331b551c40
commit a01e7df608
51 changed files with 1907 additions and 723 deletions

View File

@ -0,0 +1,119 @@
From adcc81f148d733b7e8e641300c5590a2cdc13bf3 Mon Sep 17 00:00:00 2001
From: Paul Burton <paul.burton@mips.com>
Date: Thu, 20 Dec 2018 17:45:43 +0000
Subject: MIPS: math-emu: Write-protect delay slot emulation pages
Mapping the delay slot emulation page as both writeable & executable
presents a security risk, in that if an exploit can write to & jump into
the page then it can be used as an easy way to execute arbitrary code.
Prevent this by mapping the page read-only for userland, and using
access_process_vm() with the FOLL_FORCE flag to write to it from
mips_dsemul().
This will likely be less efficient due to copy_to_user_page() performing
cache maintenance on a whole page, rather than a single line as in the
previous use of flush_cache_sigtramp(). However this delay slot
emulation code ought not to be running in any performance critical paths
anyway so this isn't really a problem, and we can probably do better in
copy_to_user_page() anyway in future.
A major advantage of this approach is that the fix is small & simple to
backport to stable kernels.
Reported-by: Andy Lutomirski <luto@kernel.org>
Signed-off-by: Paul Burton <paul.burton@mips.com>
Fixes: 432c6bacbd0c ("MIPS: Use per-mm page to execute branch delay slot instructions")
Cc: stable@vger.kernel.org # v4.8+
Cc: linux-mips@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: Rich Felker <dalias@libc.org>
Cc: David Daney <david.daney@cavium.com>
---
arch/mips/kernel/vdso.c | 4 ++--
arch/mips/math-emu/dsemul.c | 38 ++++++++++++++++++++------------------
2 files changed, 22 insertions(+), 20 deletions(-)
--- a/arch/mips/kernel/vdso.c
+++ b/arch/mips/kernel/vdso.c
@@ -126,8 +126,8 @@ int arch_setup_additional_pages(struct l
/* Map delay slot emulation page */
base = mmap_region(NULL, STACK_TOP, PAGE_SIZE,
- VM_READ|VM_WRITE|VM_EXEC|
- VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
+ VM_READ | VM_EXEC |
+ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC,
0, NULL);
if (IS_ERR_VALUE(base)) {
ret = base;
--- a/arch/mips/math-emu/dsemul.c
+++ b/arch/mips/math-emu/dsemul.c
@@ -214,8 +214,9 @@ int mips_dsemul(struct pt_regs *regs, mi
{
int isa16 = get_isa16_mode(regs->cp0_epc);
mips_instruction break_math;
- struct emuframe __user *fr;
- int err, fr_idx;
+ unsigned long fr_uaddr;
+ struct emuframe fr;
+ int fr_idx, ret;
/* NOP is easy */
if (ir == 0)
@@ -250,27 +251,31 @@ int mips_dsemul(struct pt_regs *regs, mi
fr_idx = alloc_emuframe();
if (fr_idx == BD_EMUFRAME_NONE)
return SIGBUS;
- fr = &dsemul_page()[fr_idx];
/* Retrieve the appropriately encoded break instruction */
break_math = BREAK_MATH(isa16);
/* Write the instructions to the frame */
if (isa16) {
- err = __put_user(ir >> 16,
- (u16 __user *)(&fr->emul));
- err |= __put_user(ir & 0xffff,
- (u16 __user *)((long)(&fr->emul) + 2));
- err |= __put_user(break_math >> 16,
- (u16 __user *)(&fr->badinst));
- err |= __put_user(break_math & 0xffff,
- (u16 __user *)((long)(&fr->badinst) + 2));
+ union mips_instruction _emul = {
+ .halfword = { ir >> 16, ir }
+ };
+ union mips_instruction _badinst = {
+ .halfword = { break_math >> 16, break_math }
+ };
+
+ fr.emul = _emul.word;
+ fr.badinst = _badinst.word;
} else {
- err = __put_user(ir, &fr->emul);
- err |= __put_user(break_math, &fr->badinst);
+ fr.emul = ir;
+ fr.badinst = break_math;
}
- if (unlikely(err)) {
+ /* Write the frame to user memory */
+ fr_uaddr = (unsigned long)&dsemul_page()[fr_idx];
+ ret = access_process_vm(current, fr_uaddr, &fr, sizeof(fr),
+ FOLL_FORCE | FOLL_WRITE);
+ if (unlikely(ret != sizeof(fr))) {
MIPS_FPU_EMU_INC_STATS(errors);
free_emuframe(fr_idx, current->mm);
return SIGBUS;
@@ -282,10 +287,7 @@ int mips_dsemul(struct pt_regs *regs, mi
atomic_set(&current->thread.bd_emu_frame, fr_idx);
/* Change user register context to execute the frame */
- regs->cp0_epc = (unsigned long)&fr->emul | isa16;
-
- /* Ensure the icache observes our newly written frame */
- flush_cache_sigtramp((unsigned long)&fr->emul);
+ regs->cp0_epc = fr_uaddr | isa16;
return 0;
}

View File

@ -0,0 +1,79 @@
From 03556dab1cb02d85b50d7be3ee3a3bac001f5991 Mon Sep 17 00:00:00 2001
From: Koen Vandeputte <koen.vandeputte@ncentric.com>
Date: Tue, 18 Dec 2018 12:14:06 +0100
Subject: [PATCH] arm: cns3xxx: fix writing to wrong PCI registers after
alignment
Originally, cns3xxx used it's own functions for mapping, reading and writing registers.
Commit 802b7c06adc7 ("ARM: cns3xxx: Convert PCI to use generic config accessors")
removed the internal PCI config write function in favor of the generic one:
cns3xxx_pci_write_config() --> pci_generic_config_write()
cns3xxx_pci_write_config() expected aligned addresses, being produced by cns3xxx_pci_map_bus()
while the generic one pci_generic_config_write() actually expects the real address
as both the function and hardware are capable of byte-aligned writes.
This currently leads to pci_generic_config_write() writing
to the wrong registers on some ocasions.
First issue seen due to this:
- driver ath9k gets loaded
- The driver wants to write value 0xA8 to register PCI_LATENCY_TIMER, located at 0x0D
- cns3xxx_pci_map_bus() aligns the address to 0x0C
- pci_generic_config_write() effectively writes 0xA8 into register 0x0C (CACHE_LINE_SIZE)
This seems to cause some slight instability when certain PCI devices are used.
Another issue example caused by this this is the PCI bus numbering,
where the primary bus is higher than the secondary, which is impossible.
Before:
00:00.0 PCI bridge: Cavium, Inc. Device 3400 (rev 01) (prog-if 00 [Normal decode])
Flags: bus master, fast devsel, latency 0, IRQ 255
Bus: primary=02, secondary=01, subordinate=ff, sec-latency=0
After fix:
00:00.0 PCI bridge: Cavium, Inc. Device 3400 (rev 01) (prog-if 00 [Normal decode])
Flags: bus master, fast devsel, latency 0, IRQ 255
Bus: primary=00, secondary=01, subordinate=02, sec-latency=0
And very likely some more ..
Fix all by omitting the alignment being done in the mapping function.
Fixes: 802b7c06adc7 ("ARM: cns3xxx: Convert PCI to use generic config accessors")
Signed-off-by: Koen Vandeputte <koen.vandeputte@ncentric.com>
CC: Arnd Bergmann <arnd@arndb.de>
CC: Bjorn Helgaas <bhelgaas@google.com>
CC: Krzysztof Halasa <khalasa@piap.pl>
CC: Olof Johansson <olof@lixom.net>
CC: Robin Leblon <robin.leblon@ncentric.com>
CC: Rob Herring <robh@kernel.org>
CC: Russell King <linux@armlinux.org.uk>
CC: Tim Harvey <tharvey@gateworks.com>
CC: stable@vger.kernel.org # v4.0+
---
arch/arm/mach-cns3xxx/pcie.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/mach-cns3xxx/pcie.c b/arch/arm/mach-cns3xxx/pcie.c
index 318394ed5c7a..5e11ad3164e0 100644
--- a/arch/arm/mach-cns3xxx/pcie.c
+++ b/arch/arm/mach-cns3xxx/pcie.c
@@ -83,7 +83,7 @@ static void __iomem *cns3xxx_pci_map_bus(struct pci_bus *bus,
} else /* remote PCI bus */
base = cnspci->cfg1_regs + ((busno & 0xf) << 20);
- return base + (where & 0xffc) + (devfn << 12);
+ return base + where + (devfn << 12);
}
static int cns3xxx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
--
2.17.1

View File

@ -0,0 +1,79 @@
From 46bf067870156abd61fe24d14c2486d15b8b502c Mon Sep 17 00:00:00 2001
From: Dave Taht <dave@taht.net>
Date: Fri, 14 Dec 2018 18:38:40 +0000
Subject: [PATCH 1/1] Allow class-e address assignment in ifconfig and early
boot
While the linux kernel became mostly "class-e clean" a decade ago,
and most distributions long ago switched to the iproute2 suite
of utilities, which allow class-e (240.0.0.0/4) address assignment,
distributions relying on busybox, toybox and other forms of
ifconfig cannot assign class-e addresses without this kernel patch.
With this patch, also, a boot command line on these addresses is feasible:
(ip=248.0.1.2::248.0.1.1:255.255.255.0).
While CIDR has been obsolete for 2 decades, and a survey of all the
userspace open source code in the world shows most IN_whatever macros
are also obsolete... rather than obsolete CIDR from this ioctl entirely,
this patch merely enables class-e assignment, sanely.
H/T to Vince Fuller and his original patch here:
https://lkml.org/lkml/2008/1/7/370
Signed-off-by: Dave Taht <dave.taht@gmail.com>
Reviewed-by: John Gilmore <gnu@toad.com>
---
include/uapi/linux/in.h | 8 ++++++--
net/ipv4/devinet.c | 4 +++-
net/ipv4/ipconfig.c | 2 ++
3 files changed, 11 insertions(+), 3 deletions(-)
--- a/include/uapi/linux/in.h
+++ b/include/uapi/linux/in.h
@@ -266,8 +266,12 @@ struct sockaddr_in {
#define IN_MULTICAST(a) IN_CLASSD(a)
#define IN_MULTICAST_NET 0xF0000000
-#define IN_EXPERIMENTAL(a) ((((long int) (a)) & 0xf0000000) == 0xf0000000)
-#define IN_BADCLASS(a) IN_EXPERIMENTAL((a))
+#define IN_BADCLASS(a) ((((long int) (a) ) == 0xffffffff)
+#define IN_EXPERIMENTAL(a) IN_BADCLASS((a))
+
+#define IN_CLASSE(a) ((((long int) (a)) & 0xf0000000) == 0xf0000000)
+#define IN_CLASSE_NET 0xffffffff
+#define IN_CLASSE_NSHIFT 0
/* Address to accept any incoming messages. */
#define INADDR_ANY ((unsigned long int) 0x00000000)
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -898,7 +898,7 @@ static int inet_abc_len(__be32 addr)
{
int rc = -1; /* Something else, probably a multicast. */
- if (ipv4_is_zeronet(addr))
+ if (ipv4_is_zeronet(addr) || ipv4_is_lbcast(addr))
rc = 0;
else {
__u32 haddr = ntohl(addr);
@@ -909,6 +909,8 @@ static int inet_abc_len(__be32 addr)
rc = 16;
else if (IN_CLASSC(haddr))
rc = 24;
+ else if (IN_CLASSE(haddr))
+ rc = 32;
}
return rc;
--- a/net/ipv4/ipconfig.c
+++ b/net/ipv4/ipconfig.c
@@ -455,6 +455,8 @@ static int __init ic_defaults(void)
ic_netmask = htonl(IN_CLASSB_NET);
else if (IN_CLASSC(ntohl(ic_myaddr)))
ic_netmask = htonl(IN_CLASSC_NET);
+ else if (IN_CLASSE(ntohl(ic_myaddr)))
+ ic_netmask = htonl(IN_CLASSE_NET);
else {
pr_err("IP-Config: Unable to guess netmask for address %pI4\n",
&ic_myaddr);

View File

@ -0,0 +1,119 @@
From adcc81f148d733b7e8e641300c5590a2cdc13bf3 Mon Sep 17 00:00:00 2001
From: Paul Burton <paul.burton@mips.com>
Date: Thu, 20 Dec 2018 17:45:43 +0000
Subject: MIPS: math-emu: Write-protect delay slot emulation pages
Mapping the delay slot emulation page as both writeable & executable
presents a security risk, in that if an exploit can write to & jump into
the page then it can be used as an easy way to execute arbitrary code.
Prevent this by mapping the page read-only for userland, and using
access_process_vm() with the FOLL_FORCE flag to write to it from
mips_dsemul().
This will likely be less efficient due to copy_to_user_page() performing
cache maintenance on a whole page, rather than a single line as in the
previous use of flush_cache_sigtramp(). However this delay slot
emulation code ought not to be running in any performance critical paths
anyway so this isn't really a problem, and we can probably do better in
copy_to_user_page() anyway in future.
A major advantage of this approach is that the fix is small & simple to
backport to stable kernels.
Reported-by: Andy Lutomirski <luto@kernel.org>
Signed-off-by: Paul Burton <paul.burton@mips.com>
Fixes: 432c6bacbd0c ("MIPS: Use per-mm page to execute branch delay slot instructions")
Cc: stable@vger.kernel.org # v4.8+
Cc: linux-mips@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: Rich Felker <dalias@libc.org>
Cc: David Daney <david.daney@cavium.com>
---
arch/mips/kernel/vdso.c | 4 ++--
arch/mips/math-emu/dsemul.c | 38 ++++++++++++++++++++------------------
2 files changed, 22 insertions(+), 20 deletions(-)
--- a/arch/mips/kernel/vdso.c
+++ b/arch/mips/kernel/vdso.c
@@ -111,8 +111,8 @@ int arch_setup_additional_pages(struct l
/* Map delay slot emulation page */
base = mmap_region(NULL, STACK_TOP, PAGE_SIZE,
- VM_READ|VM_WRITE|VM_EXEC|
- VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
+ VM_READ | VM_EXEC |
+ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC,
0);
if (IS_ERR_VALUE(base)) {
ret = base;
--- a/arch/mips/math-emu/dsemul.c
+++ b/arch/mips/math-emu/dsemul.c
@@ -211,8 +211,9 @@ int mips_dsemul(struct pt_regs *regs, mi
{
int isa16 = get_isa16_mode(regs->cp0_epc);
mips_instruction break_math;
- struct emuframe __user *fr;
- int err, fr_idx;
+ unsigned long fr_uaddr;
+ struct emuframe fr;
+ int fr_idx, ret;
/* NOP is easy */
if (ir == 0)
@@ -247,27 +248,31 @@ int mips_dsemul(struct pt_regs *regs, mi
fr_idx = alloc_emuframe();
if (fr_idx == BD_EMUFRAME_NONE)
return SIGBUS;
- fr = &dsemul_page()[fr_idx];
/* Retrieve the appropriately encoded break instruction */
break_math = BREAK_MATH(isa16);
/* Write the instructions to the frame */
if (isa16) {
- err = __put_user(ir >> 16,
- (u16 __user *)(&fr->emul));
- err |= __put_user(ir & 0xffff,
- (u16 __user *)((long)(&fr->emul) + 2));
- err |= __put_user(break_math >> 16,
- (u16 __user *)(&fr->badinst));
- err |= __put_user(break_math & 0xffff,
- (u16 __user *)((long)(&fr->badinst) + 2));
+ union mips_instruction _emul = {
+ .halfword = { ir >> 16, ir }
+ };
+ union mips_instruction _badinst = {
+ .halfword = { break_math >> 16, break_math }
+ };
+
+ fr.emul = _emul.word;
+ fr.badinst = _badinst.word;
} else {
- err = __put_user(ir, &fr->emul);
- err |= __put_user(break_math, &fr->badinst);
+ fr.emul = ir;
+ fr.badinst = break_math;
}
- if (unlikely(err)) {
+ /* Write the frame to user memory */
+ fr_uaddr = (unsigned long)&dsemul_page()[fr_idx];
+ ret = access_process_vm(current, fr_uaddr, &fr, sizeof(fr),
+ FOLL_FORCE | FOLL_WRITE);
+ if (unlikely(ret != sizeof(fr))) {
MIPS_FPU_EMU_INC_STATS(errors);
free_emuframe(fr_idx, current->mm);
return SIGBUS;
@@ -279,10 +284,7 @@ int mips_dsemul(struct pt_regs *regs, mi
atomic_set(&current->thread.bd_emu_frame, fr_idx);
/* Change user register context to execute the frame */
- regs->cp0_epc = (unsigned long)&fr->emul | isa16;
-
- /* Ensure the icache observes our newly written frame */
- flush_cache_sigtramp((unsigned long)&fr->emul);
+ regs->cp0_epc = fr_uaddr | isa16;
return 0;
}

View File

@ -0,0 +1,32 @@
From 508b09046c0f21678652fb66fd1e9959d55591d2 Mon Sep 17 00:00:00 2001
From: Alin Nastac <alin.nastac@gmail.com>
Date: Wed, 21 Nov 2018 14:00:30 +0100
Subject: [PATCH] netfilter: ipv6: Preserve link scope traffic original oif
When ip6_route_me_harder is invoked, it resets outgoing interface of:
- link-local scoped packets sent by neighbor discovery
- multicast packets sent by MLD host
- multicast packets send by MLD proxy daemon that sets outgoing
interface through IPV6_PKTINFO ipi6_ifindex
Link-local and multicast packets must keep their original oif after
ip6_route_me_harder is called.
Signed-off-by: Alin Nastac <alin.nastac@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/ipv6/netfilter.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/net/ipv6/netfilter.c
+++ b/net/ipv6/netfilter.c
@@ -24,7 +24,8 @@ int ip6_route_me_harder(struct net *net,
unsigned int hh_len;
struct dst_entry *dst;
struct flowi6 fl6 = {
- .flowi6_oif = skb->sk ? skb->sk->sk_bound_dev_if : 0,
+ .flowi6_oif = skb->sk && skb->sk->sk_bound_dev_if ? skb->sk->sk_bound_dev_if :
+ rt6_need_strict(&iph->daddr) ? skb_dst(skb)->dev->ifindex : 0,
.flowi6_mark = skb->mark,
.daddr = iph->daddr,
.saddr = iph->saddr,

View File

@ -0,0 +1,79 @@
From 03556dab1cb02d85b50d7be3ee3a3bac001f5991 Mon Sep 17 00:00:00 2001
From: Koen Vandeputte <koen.vandeputte@ncentric.com>
Date: Tue, 18 Dec 2018 12:14:06 +0100
Subject: [PATCH] arm: cns3xxx: fix writing to wrong PCI registers after
alignment
Originally, cns3xxx used it's own functions for mapping, reading and writing registers.
Commit 802b7c06adc7 ("ARM: cns3xxx: Convert PCI to use generic config accessors")
removed the internal PCI config write function in favor of the generic one:
cns3xxx_pci_write_config() --> pci_generic_config_write()
cns3xxx_pci_write_config() expected aligned addresses, being produced by cns3xxx_pci_map_bus()
while the generic one pci_generic_config_write() actually expects the real address
as both the function and hardware are capable of byte-aligned writes.
This currently leads to pci_generic_config_write() writing
to the wrong registers on some ocasions.
First issue seen due to this:
- driver ath9k gets loaded
- The driver wants to write value 0xA8 to register PCI_LATENCY_TIMER, located at 0x0D
- cns3xxx_pci_map_bus() aligns the address to 0x0C
- pci_generic_config_write() effectively writes 0xA8 into register 0x0C (CACHE_LINE_SIZE)
This seems to cause some slight instability when certain PCI devices are used.
Another issue example caused by this this is the PCI bus numbering,
where the primary bus is higher than the secondary, which is impossible.
Before:
00:00.0 PCI bridge: Cavium, Inc. Device 3400 (rev 01) (prog-if 00 [Normal decode])
Flags: bus master, fast devsel, latency 0, IRQ 255
Bus: primary=02, secondary=01, subordinate=ff, sec-latency=0
After fix:
00:00.0 PCI bridge: Cavium, Inc. Device 3400 (rev 01) (prog-if 00 [Normal decode])
Flags: bus master, fast devsel, latency 0, IRQ 255
Bus: primary=00, secondary=01, subordinate=02, sec-latency=0
And very likely some more ..
Fix all by omitting the alignment being done in the mapping function.
Fixes: 802b7c06adc7 ("ARM: cns3xxx: Convert PCI to use generic config accessors")
Signed-off-by: Koen Vandeputte <koen.vandeputte@ncentric.com>
CC: Arnd Bergmann <arnd@arndb.de>
CC: Bjorn Helgaas <bhelgaas@google.com>
CC: Krzysztof Halasa <khalasa@piap.pl>
CC: Olof Johansson <olof@lixom.net>
CC: Robin Leblon <robin.leblon@ncentric.com>
CC: Rob Herring <robh@kernel.org>
CC: Russell King <linux@armlinux.org.uk>
CC: Tim Harvey <tharvey@gateworks.com>
CC: stable@vger.kernel.org # v4.0+
---
arch/arm/mach-cns3xxx/pcie.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/mach-cns3xxx/pcie.c b/arch/arm/mach-cns3xxx/pcie.c
index 318394ed5c7a..5e11ad3164e0 100644
--- a/arch/arm/mach-cns3xxx/pcie.c
+++ b/arch/arm/mach-cns3xxx/pcie.c
@@ -83,7 +83,7 @@ static void __iomem *cns3xxx_pci_map_bus(struct pci_bus *bus,
} else /* remote PCI bus */
base = cnspci->cfg1_regs + ((busno & 0xf) << 20);
- return base + (where & 0xffc) + (devfn << 12);
+ return base + where + (devfn << 12);
}
static int cns3xxx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
--
2.17.1

View File

@ -0,0 +1,588 @@
From 06f502f57d0d7728f9fa0f157ec5e4111ddb98f6 Mon Sep 17 00:00:00 2001
From: Ben Whitten <ben.whitten@gmail.com>
Date: Sun, 10 Dec 2017 21:17:55 +0000
Subject: [PATCH] leds: trigger: Introduce a NETDEV trigger
This commit introduces a NETDEV trigger for named device
activity. Available triggers are link, rx, and tx.
Signed-off-by: Ben Whitten <ben.whitten@gmail.com>
Acked-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Jacek Anaszewski <jacek.anaszewski@gmail.com>
---
.../ABI/testing/sysfs-class-led-trigger-netdev | 45 ++
drivers/leds/trigger/Kconfig | 7 +
drivers/leds/trigger/Makefile | 1 +
drivers/leds/trigger/ledtrig-netdev.c | 496 +++++++++++++++++++++
4 files changed, 549 insertions(+)
create mode 100644 Documentation/ABI/testing/sysfs-class-led-trigger-netdev
create mode 100644 drivers/leds/trigger/ledtrig-netdev.c
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-led-trigger-netdev
@@ -0,0 +1,45 @@
+What: /sys/class/leds/<led>/device_name
+Date: Dec 2017
+KernelVersion: 4.16
+Contact: linux-leds@vger.kernel.org
+Description:
+ Specifies the network device name to monitor.
+
+What: /sys/class/leds/<led>/interval
+Date: Dec 2017
+KernelVersion: 4.16
+Contact: linux-leds@vger.kernel.org
+Description:
+ Specifies the duration of the LED blink in milliseconds.
+ Defaults to 50 ms.
+
+What: /sys/class/leds/<led>/link
+Date: Dec 2017
+KernelVersion: 4.16
+Contact: linux-leds@vger.kernel.org
+Description:
+ Signal the link state of the named network device.
+ If set to 0 (default), the LED's normal state is off.
+ If set to 1, the LED's normal state reflects the link state
+ of the named network device.
+ Setting this value also immediately changes the LED state.
+
+What: /sys/class/leds/<led>/tx
+Date: Dec 2017
+KernelVersion: 4.16
+Contact: linux-leds@vger.kernel.org
+Description:
+ Signal transmission of data on the named network device.
+ If set to 0 (default), the LED will not blink on transmission.
+ If set to 1, the LED will blink for the milliseconds specified
+ in interval to signal transmission.
+
+What: /sys/class/leds/<led>/rx
+Date: Dec 2017
+KernelVersion: 4.16
+Contact: linux-leds@vger.kernel.org
+Description:
+ Signal reception of data on the named network device.
+ If set to 0 (default), the LED will not blink on reception.
+ If set to 1, the LED will blink for the milliseconds specified
+ in interval to signal reception.
--- a/drivers/leds/trigger/Kconfig
+++ b/drivers/leds/trigger/Kconfig
@@ -126,4 +126,11 @@ config LEDS_TRIGGER_PANIC
a different trigger.
If unsure, say Y.
+config LEDS_TRIGGER_NETDEV
+ tristate "LED Netdev Trigger"
+ depends on NET && LEDS_TRIGGERS
+ help
+ This allows LEDs to be controlled by network device activity.
+ If unsure, say Y.
+
endif # LEDS_TRIGGERS
--- a/drivers/leds/trigger/Makefile
+++ b/drivers/leds/trigger/Makefile
@@ -10,3 +10,4 @@ obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) +=
obj-$(CONFIG_LEDS_TRIGGER_TRANSIENT) += ledtrig-transient.o
obj-$(CONFIG_LEDS_TRIGGER_CAMERA) += ledtrig-camera.o
obj-$(CONFIG_LEDS_TRIGGER_PANIC) += ledtrig-panic.o
+obj-$(CONFIG_LEDS_TRIGGER_NETDEV) += ledtrig-netdev.o
--- /dev/null
+++ b/drivers/leds/trigger/ledtrig-netdev.c
@@ -0,0 +1,496 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright 2017 Ben Whitten <ben.whitten@gmail.com>
+// Copyright 2007 Oliver Jowett <oliver@opencloud.com>
+//
+// LED Kernel Netdev Trigger
+//
+// Toggles the LED to reflect the link and traffic state of a named net device
+//
+// Derived from ledtrig-timer.c which is:
+// Copyright 2005-2006 Openedhand Ltd.
+// Author: Richard Purdie <rpurdie@openedhand.com>
+
+#include <linux/atomic.h>
+#include <linux/ctype.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/leds.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/spinlock.h>
+#include <linux/timer.h>
+#include "../leds.h"
+
+/*
+ * Configurable sysfs attributes:
+ *
+ * device_name - network device name to monitor
+ * interval - duration of LED blink, in milliseconds
+ * link - LED's normal state reflects whether the link is up
+ * (has carrier) or not
+ * tx - LED blinks on transmitted data
+ * rx - LED blinks on receive data
+ *
+ */
+
+struct led_netdev_data {
+ spinlock_t lock;
+
+ struct delayed_work work;
+ struct notifier_block notifier;
+
+ struct led_classdev *led_cdev;
+ struct net_device *net_dev;
+
+ char device_name[IFNAMSIZ];
+ atomic_t interval;
+ unsigned int last_activity;
+
+ unsigned long mode;
+#define NETDEV_LED_LINK 0
+#define NETDEV_LED_TX 1
+#define NETDEV_LED_RX 2
+#define NETDEV_LED_MODE_LINKUP 3
+};
+
+enum netdev_led_attr {
+ NETDEV_ATTR_LINK,
+ NETDEV_ATTR_TX,
+ NETDEV_ATTR_RX
+};
+
+static void set_baseline_state(struct led_netdev_data *trigger_data)
+{
+ int current_brightness;
+ struct led_classdev *led_cdev = trigger_data->led_cdev;
+
+ current_brightness = led_cdev->brightness;
+ if (current_brightness)
+ led_cdev->blink_brightness = current_brightness;
+ if (!led_cdev->blink_brightness)
+ led_cdev->blink_brightness = led_cdev->max_brightness;
+
+ if (!test_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode))
+ led_set_brightness(led_cdev, LED_OFF);
+ else {
+ if (test_bit(NETDEV_LED_LINK, &trigger_data->mode))
+ led_set_brightness(led_cdev,
+ led_cdev->blink_brightness);
+ else
+ led_set_brightness(led_cdev, LED_OFF);
+
+ /* If we are looking for RX/TX start periodically
+ * checking stats
+ */
+ if (test_bit(NETDEV_LED_TX, &trigger_data->mode) ||
+ test_bit(NETDEV_LED_RX, &trigger_data->mode))
+ schedule_delayed_work(&trigger_data->work, 0);
+ }
+}
+
+static ssize_t device_name_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
+ struct led_netdev_data *trigger_data = led_cdev->trigger_data;
+ ssize_t len;
+
+ spin_lock_bh(&trigger_data->lock);
+ len = sprintf(buf, "%s\n", trigger_data->device_name);
+ spin_unlock_bh(&trigger_data->lock);
+
+ return len;
+}
+
+static ssize_t device_name_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t size)
+{
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
+ struct led_netdev_data *trigger_data = led_cdev->trigger_data;
+
+ if (size >= IFNAMSIZ)
+ return -EINVAL;
+
+ cancel_delayed_work_sync(&trigger_data->work);
+
+ spin_lock_bh(&trigger_data->lock);
+
+ if (trigger_data->net_dev) {
+ dev_put(trigger_data->net_dev);
+ trigger_data->net_dev = NULL;
+ }
+
+ strncpy(trigger_data->device_name, buf, size);
+ if (size > 0 && trigger_data->device_name[size - 1] == '\n')
+ trigger_data->device_name[size - 1] = 0;
+
+ if (trigger_data->device_name[0] != 0)
+ trigger_data->net_dev =
+ dev_get_by_name(&init_net, trigger_data->device_name);
+
+ clear_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode);
+ if (trigger_data->net_dev != NULL)
+ if (netif_carrier_ok(trigger_data->net_dev))
+ set_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode);
+
+ trigger_data->last_activity = 0;
+
+ set_baseline_state(trigger_data);
+ spin_unlock_bh(&trigger_data->lock);
+
+ return size;
+}
+
+static DEVICE_ATTR_RW(device_name);
+
+static ssize_t netdev_led_attr_show(struct device *dev, char *buf,
+ enum netdev_led_attr attr)
+{
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
+ struct led_netdev_data *trigger_data = led_cdev->trigger_data;
+ int bit;
+
+ switch (attr) {
+ case NETDEV_ATTR_LINK:
+ bit = NETDEV_LED_LINK;
+ break;
+ case NETDEV_ATTR_TX:
+ bit = NETDEV_LED_TX;
+ break;
+ case NETDEV_ATTR_RX:
+ bit = NETDEV_LED_RX;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return sprintf(buf, "%u\n", test_bit(bit, &trigger_data->mode));
+}
+
+static ssize_t netdev_led_attr_store(struct device *dev, const char *buf,
+ size_t size, enum netdev_led_attr attr)
+{
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
+ struct led_netdev_data *trigger_data = led_cdev->trigger_data;
+ unsigned long state;
+ int ret;
+ int bit;
+
+ ret = kstrtoul(buf, 0, &state);
+ if (ret)
+ return ret;
+
+ switch (attr) {
+ case NETDEV_ATTR_LINK:
+ bit = NETDEV_LED_LINK;
+ break;
+ case NETDEV_ATTR_TX:
+ bit = NETDEV_LED_TX;
+ break;
+ case NETDEV_ATTR_RX:
+ bit = NETDEV_LED_RX;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ cancel_delayed_work_sync(&trigger_data->work);
+
+ if (state)
+ set_bit(bit, &trigger_data->mode);
+ else
+ clear_bit(bit, &trigger_data->mode);
+
+ set_baseline_state(trigger_data);
+
+ return size;
+}
+
+static ssize_t link_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return netdev_led_attr_show(dev, buf, NETDEV_ATTR_LINK);
+}
+
+static ssize_t link_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ return netdev_led_attr_store(dev, buf, size, NETDEV_ATTR_LINK);
+}
+
+static DEVICE_ATTR_RW(link);
+
+static ssize_t tx_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return netdev_led_attr_show(dev, buf, NETDEV_ATTR_TX);
+}
+
+static ssize_t tx_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ return netdev_led_attr_store(dev, buf, size, NETDEV_ATTR_TX);
+}
+
+static DEVICE_ATTR_RW(tx);
+
+static ssize_t rx_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return netdev_led_attr_show(dev, buf, NETDEV_ATTR_RX);
+}
+
+static ssize_t rx_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ return netdev_led_attr_store(dev, buf, size, NETDEV_ATTR_RX);
+}
+
+static DEVICE_ATTR_RW(rx);
+
+static ssize_t interval_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
+ struct led_netdev_data *trigger_data = led_cdev->trigger_data;
+
+ return sprintf(buf, "%u\n",
+ jiffies_to_msecs(atomic_read(&trigger_data->interval)));
+}
+
+static ssize_t interval_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t size)
+{
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
+ struct led_netdev_data *trigger_data = led_cdev->trigger_data;
+ unsigned long value;
+ int ret;
+
+ ret = kstrtoul(buf, 0, &value);
+ if (ret)
+ return ret;
+
+ /* impose some basic bounds on the timer interval */
+ if (value >= 5 && value <= 10000) {
+ cancel_delayed_work_sync(&trigger_data->work);
+
+ atomic_set(&trigger_data->interval, msecs_to_jiffies(value));
+ set_baseline_state(trigger_data); /* resets timer */
+ }
+
+ return size;
+}
+
+static DEVICE_ATTR_RW(interval);
+
+static int netdev_trig_notify(struct notifier_block *nb,
+ unsigned long evt, void *dv)
+{
+ struct net_device *dev =
+ netdev_notifier_info_to_dev((struct netdev_notifier_info *)dv);
+ struct led_netdev_data *trigger_data = container_of(nb,
+ struct
+ led_netdev_data,
+ notifier);
+
+ if (evt != NETDEV_UP && evt != NETDEV_DOWN && evt != NETDEV_CHANGE
+ && evt != NETDEV_REGISTER && evt != NETDEV_UNREGISTER
+ && evt != NETDEV_CHANGENAME)
+ return NOTIFY_DONE;
+
+ if (strcmp(dev->name, trigger_data->device_name))
+ return NOTIFY_DONE;
+
+ cancel_delayed_work_sync(&trigger_data->work);
+
+ spin_lock_bh(&trigger_data->lock);
+
+ clear_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode);
+ switch (evt) {
+ case NETDEV_REGISTER:
+ if (trigger_data->net_dev)
+ dev_put(trigger_data->net_dev);
+ dev_hold(dev);
+ trigger_data->net_dev = dev;
+ break;
+ case NETDEV_CHANGENAME:
+ case NETDEV_UNREGISTER:
+ if (trigger_data->net_dev) {
+ dev_put(trigger_data->net_dev);
+ trigger_data->net_dev = NULL;
+ }
+ break;
+ case NETDEV_UP:
+ case NETDEV_CHANGE:
+ if (netif_carrier_ok(dev))
+ set_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode);
+ break;
+ }
+
+ set_baseline_state(trigger_data);
+
+ spin_unlock_bh(&trigger_data->lock);
+
+ return NOTIFY_DONE;
+}
+
+/* here's the real work! */
+static void netdev_trig_work(struct work_struct *work)
+{
+ struct led_netdev_data *trigger_data = container_of(work,
+ struct
+ led_netdev_data,
+ work.work);
+ struct rtnl_link_stats64 *dev_stats;
+ unsigned int new_activity;
+ struct rtnl_link_stats64 temp;
+ unsigned long interval;
+ int invert;
+
+ /* If we dont have a device, insure we are off */
+ if (!trigger_data->net_dev) {
+ led_set_brightness(trigger_data->led_cdev, LED_OFF);
+ return;
+ }
+
+ /* If we are not looking for RX/TX then return */
+ if (!test_bit(NETDEV_LED_TX, &trigger_data->mode) &&
+ !test_bit(NETDEV_LED_RX, &trigger_data->mode))
+ return;
+
+ dev_stats = dev_get_stats(trigger_data->net_dev, &temp);
+ new_activity =
+ (test_bit(NETDEV_LED_TX, &trigger_data->mode) ?
+ dev_stats->tx_packets : 0) +
+ (test_bit(NETDEV_LED_RX, &trigger_data->mode) ?
+ dev_stats->rx_packets : 0);
+
+ if (trigger_data->last_activity != new_activity) {
+ led_stop_software_blink(trigger_data->led_cdev);
+
+ invert = test_bit(NETDEV_LED_LINK, &trigger_data->mode);
+ interval = jiffies_to_msecs(
+ atomic_read(&trigger_data->interval));
+ /* base state is ON (link present) */
+ led_blink_set_oneshot(trigger_data->led_cdev,
+ &interval,
+ &interval,
+ invert);
+ trigger_data->last_activity = new_activity;
+ }
+
+ schedule_delayed_work(&trigger_data->work,
+ (atomic_read(&trigger_data->interval)*2));
+}
+
+static void netdev_trig_activate(struct led_classdev *led_cdev)
+{
+ struct led_netdev_data *trigger_data;
+ int rc;
+
+ trigger_data = kzalloc(sizeof(struct led_netdev_data), GFP_KERNEL);
+ if (!trigger_data)
+ return;
+
+ spin_lock_init(&trigger_data->lock);
+
+ trigger_data->notifier.notifier_call = netdev_trig_notify;
+ trigger_data->notifier.priority = 10;
+
+ INIT_DELAYED_WORK(&trigger_data->work, netdev_trig_work);
+
+ trigger_data->led_cdev = led_cdev;
+ trigger_data->net_dev = NULL;
+ trigger_data->device_name[0] = 0;
+
+ trigger_data->mode = 0;
+ atomic_set(&trigger_data->interval, msecs_to_jiffies(50));
+ trigger_data->last_activity = 0;
+
+ led_cdev->trigger_data = trigger_data;
+
+ rc = device_create_file(led_cdev->dev, &dev_attr_device_name);
+ if (rc)
+ goto err_out;
+ rc = device_create_file(led_cdev->dev, &dev_attr_link);
+ if (rc)
+ goto err_out_device_name;
+ rc = device_create_file(led_cdev->dev, &dev_attr_rx);
+ if (rc)
+ goto err_out_link;
+ rc = device_create_file(led_cdev->dev, &dev_attr_tx);
+ if (rc)
+ goto err_out_rx;
+ rc = device_create_file(led_cdev->dev, &dev_attr_interval);
+ if (rc)
+ goto err_out_tx;
+ rc = register_netdevice_notifier(&trigger_data->notifier);
+ if (rc)
+ goto err_out_interval;
+ return;
+
+err_out_interval:
+ device_remove_file(led_cdev->dev, &dev_attr_interval);
+err_out_tx:
+ device_remove_file(led_cdev->dev, &dev_attr_tx);
+err_out_rx:
+ device_remove_file(led_cdev->dev, &dev_attr_rx);
+err_out_link:
+ device_remove_file(led_cdev->dev, &dev_attr_link);
+err_out_device_name:
+ device_remove_file(led_cdev->dev, &dev_attr_device_name);
+err_out:
+ led_cdev->trigger_data = NULL;
+ kfree(trigger_data);
+}
+
+static void netdev_trig_deactivate(struct led_classdev *led_cdev)
+{
+ struct led_netdev_data *trigger_data = led_cdev->trigger_data;
+
+ if (trigger_data) {
+ unregister_netdevice_notifier(&trigger_data->notifier);
+
+ device_remove_file(led_cdev->dev, &dev_attr_device_name);
+ device_remove_file(led_cdev->dev, &dev_attr_link);
+ device_remove_file(led_cdev->dev, &dev_attr_rx);
+ device_remove_file(led_cdev->dev, &dev_attr_tx);
+ device_remove_file(led_cdev->dev, &dev_attr_interval);
+
+ cancel_delayed_work_sync(&trigger_data->work);
+
+ if (trigger_data->net_dev)
+ dev_put(trigger_data->net_dev);
+
+ kfree(trigger_data);
+ }
+}
+
+static struct led_trigger netdev_led_trigger = {
+ .name = "netdev",
+ .activate = netdev_trig_activate,
+ .deactivate = netdev_trig_deactivate,
+};
+
+static int __init netdev_trig_init(void)
+{
+ return led_trigger_register(&netdev_led_trigger);
+}
+
+static void __exit netdev_trig_exit(void)
+{
+ led_trigger_unregister(&netdev_led_trigger);
+}
+
+module_init(netdev_trig_init);
+module_exit(netdev_trig_exit);
+
+MODULE_AUTHOR("Ben Whitten <ben.whitten@gmail.com>");
+MODULE_AUTHOR("Oliver Jowett <oliver@opencloud.com>");
+MODULE_DESCRIPTION("Netdev LED trigger");
+MODULE_LICENSE("GPL v2");

View File

@ -0,0 +1,44 @@
From a74515604a7b171f2702bdcbd1e231225fb456d0 Mon Sep 17 00:00:00 2001
From: Anderson Luiz Alves <alacn1@gmail.com>
Date: Fri, 30 Nov 2018 21:58:36 -0200
Subject: [PATCH] mv88e6060: disable hardware level MAC learning
Disable hardware level MAC learning because it breaks station roaming.
When enabled it drops all frames that arrive from a MAC address
that is on a different port at learning table.
Signed-off-by: Anderson Luiz Alves <alacn1@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/dsa/mv88e6060.c | 10 +++-------
1 file changed, 3 insertions(+), 7 deletions(-)
--- a/drivers/net/dsa/mv88e6060.c
+++ b/drivers/net/dsa/mv88e6060.c
@@ -114,8 +114,7 @@ static int mv88e6060_switch_reset(struct
/* Reset the switch. */
REG_WRITE(REG_GLOBAL, GLOBAL_ATU_CONTROL,
GLOBAL_ATU_CONTROL_SWRESET |
- GLOBAL_ATU_CONTROL_ATUSIZE_1024 |
- GLOBAL_ATU_CONTROL_ATE_AGE_5MIN);
+ GLOBAL_ATU_CONTROL_LEARNDIS);
/* Wait up to one second for reset to complete. */
timeout = jiffies + 1 * HZ;
@@ -140,13 +139,10 @@ static int mv88e6060_setup_global(struct
*/
REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL, GLOBAL_CONTROL_MAX_FRAME_1536);
- /* Enable automatic address learning, set the address
- * database size to 1024 entries, and set the default aging
- * time to 5 minutes.
+ /* Disable automatic address learning.
*/
REG_WRITE(REG_GLOBAL, GLOBAL_ATU_CONTROL,
- GLOBAL_ATU_CONTROL_ATUSIZE_1024 |
- GLOBAL_ATU_CONTROL_ATE_AGE_5MIN);
+ GLOBAL_ATU_CONTROL_LEARNDIS);
return 0;
}

View File

@ -273,6 +273,7 @@ CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=8
# CONFIG_ARCH_ZYNQMP is not set
# CONFIG_ARCNET is not set
# CONFIG_ARC_EMAC is not set
# CONFIG_ARM64_ERRATUM_1024718 is not set
# CONFIG_ARM64_ERRATUM_819472 is not set
# CONFIG_ARM64_ERRATUM_824069 is not set
# CONFIG_ARM64_ERRATUM_826319 is not set
@ -282,7 +283,6 @@ CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=8
# CONFIG_ARM64_ERRATUM_843419 is not set
# CONFIG_ARM64_ERRATUM_845719 is not set
# CONFIG_ARM64_ERRATUM_858921 is not set
# CONFIG_ARM64_ERRATUM_1024718 is not set
# CONFIG_ARM64_RELOC_TEST is not set
# CONFIG_ARM_APPENDED_DTB is not set
# CONFIG_ARM_ARCH_TIMER is not set
@ -627,7 +627,7 @@ CONFIG_BRIDGE=y
CONFIG_BRIDGE_IGMP_SNOOPING=y
# CONFIG_BRIDGE_NETFILTER is not set
# CONFIG_BRIDGE_NF_EBTABLES is not set
# CONFIG_BRIDGE_VLAN_FILTERING is not set
CONFIG_BRIDGE_VLAN_FILTERING=y
# CONFIG_BROADCOM_PHY is not set
CONFIG_BROKEN_ON_SMP=y
# CONFIG_BSD_DISKLABEL is not set
@ -717,6 +717,8 @@ CONFIG_CARDBUS=y
# CONFIG_CB710_CORE is not set
# CONFIG_CC10001_ADC is not set
# CONFIG_CCS811 is not set
CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
# CONFIG_CC_STACKPROTECTOR is not set
CONFIG_CC_STACKPROTECTOR_NONE=y
# CONFIG_CC_STACKPROTECTOR_REGULAR is not set
@ -916,9 +918,9 @@ CONFIG_CRYPTO_BLKCIPHER2=y
# CONFIG_CRYPTO_DEV_QAT_DH895xCC is not set
# CONFIG_CRYPTO_DEV_QAT_DH895xCCVF is not set
# CONFIG_CRYPTO_DEV_QCE is not set
# CONFIG_CRYPTO_DEV_S5P is not set
# CONFIG_CRYPTO_DEV_SAFEXCEL is not set
# CONFIG_CRYPTO_DEV_SAHARA is not set
# CONFIG_CRYPTO_DEV_S5P is not set
# CONFIG_CRYPTO_DEV_TALITOS is not set
# CONFIG_CRYPTO_DEV_VIRTIO is not set
# CONFIG_CRYPTO_DH is not set
@ -1180,12 +1182,14 @@ CONFIG_DQL=y
# CONFIG_DRM_NOUVEAU is not set
# CONFIG_DRM_NXP_PTN3460 is not set
# CONFIG_DRM_OMAP is not set
# CONFIG_DRM_PANEL_INNOLUX_P079ZCA is not set
# CONFIG_DRM_PANEL_JDI_LT070ME05000 is not set
# CONFIG_DRM_PANEL_LG_LG4573 is not set
# CONFIG_DRM_PANEL_LVDS is not set
# CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00 is not set
# CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN is not set
# CONFIG_DRM_PANEL_SAMSUNG_LD9040 is not set
# CONFIG_DRM_PANEL_SAMSUNG_S6E3HA2 is not set
# CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0 is not set
# CONFIG_DRM_PANEL_SHARP_LQ101R1SX01 is not set
# CONFIG_DRM_PANEL_SHARP_LS043T1LE01 is not set
@ -3162,13 +3166,13 @@ CONFIG_NFS_V3=y
# CONFIG_NFT_DUP_IPV6 is not set
# CONFIG_NFT_FIB_IPV4 is not set
# CONFIG_NFT_FIB_IPV6 is not set
# CONFIG_NFT_FIB_NETDEV is not set
# CONFIG_NFT_FLOW_OFFLOAD is not set
# CONFIG_NFT_OBJREF is not set
# CONFIG_NFT_RT is not set
# CONFIG_NFT_SET_BITMAP is not set
# CONFIG_NF_CONNTRACK is not set
# CONFIG_NF_CONNTRACK_AMANDA is not set
# CONFIG_NF_CONNTRACK_CHAIN_EVENTS is not set
# CONFIG_NF_CONNTRACK_EVENTS is not set
# CONFIG_NF_CONNTRACK_FTP is not set
# CONFIG_NF_CONNTRACK_H323 is not set
@ -4496,6 +4500,7 @@ CONFIG_SND_PROC_FS=y
# CONFIG_SND_SOC_FSL_SPDIF is not set
# CONFIG_SND_SOC_FSL_SSI is not set
# CONFIG_SND_SOC_GTM601 is not set
# CONFIG_SND_SOC_ICS43432 is not set
# CONFIG_SND_SOC_IMG is not set
# CONFIG_SND_SOC_IMX_AUDMUX is not set
# CONFIG_SND_SOC_IMX_ES8328 is not set

View File

@ -743,12 +743,11 @@ CONFIG_CARDBUS=y
# CONFIG_CB710_CORE is not set
# CONFIG_CC10001_ADC is not set
# CONFIG_CCS811 is not set
CONFIG_CC_HAS_SANCOV_TRACE_PC=y
CONFIG_CC_HAS_STACKPROTECTOR_NONE=y
CONFIG_CC_IS_GCC=y
CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
# CONFIG_CC_STACKPROTECTOR is not set
CONFIG_CC_STACKPROTECTOR_NONE=y
# CONFIG_CC_STACKPROTECTOR_REGULAR is not set
# CONFIG_CC_STACKPROTECTOR_STRONG is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_CEPH_FS is not set
# CONFIG_CEPH_LIB is not set
@ -802,6 +801,7 @@ CONFIG_CIFS_STATS=y
# CONFIG_CIFS_WEAK_PW_HASH is not set
# CONFIG_CIFS_XATTR is not set
# CONFIG_CIO_DAC is not set
CONFIG_CLANG_VERSION=0
# CONFIG_CLEANCACHE is not set
# CONFIG_CLKSRC_VERSATILE is not set
# CONFIG_CLK_HSDK is not set
@ -1102,6 +1102,7 @@ CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_PREEMPT is not set
# CONFIG_DEBUG_RODATA is not set
# CONFIG_DEBUG_RODATA_TEST is not set
# CONFIG_DEBUG_RSEQ is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_DEBUG_RWSEMS is not set
# CONFIG_DEBUG_SECTION_MISMATCH is not set
@ -1531,6 +1532,7 @@ CONFIG_GACT_PROB=y
# CONFIG_GAMEPORT is not set
# CONFIG_GATEWORKS_GW16083 is not set
# CONFIG_GCC_PLUGINS is not set
CONFIG_GCC_VERSION=70400
# CONFIG_GCOV is not set
# CONFIG_GCOV_KERNEL is not set
# CONFIG_GDB_SCRIPTS is not set
@ -1650,6 +1652,7 @@ CONFIG_HAVE_KERNEL_XZ=y
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_NMI=y
CONFIG_HAVE_STACKPROTECTOR=y
# CONFIG_HCALL_STATS is not set
# CONFIG_HDC100X is not set
# CONFIG_HDLC is not set
@ -3350,6 +3353,7 @@ CONFIG_NF_CONNTRACK_PROCFS=y
# CONFIG_NF_DUP_IPV6 is not set
# CONFIG_NF_FLOW_TABLE is not set
# CONFIG_NF_LOG_ARP is not set
# CONFIG_NF_LOG_BRIDGE is not set
# CONFIG_NF_LOG_IPV4 is not set
# CONFIG_NF_LOG_NETDEV is not set
# CONFIG_NF_NAT is not set
@ -3661,7 +3665,10 @@ CONFIG_PCI_SYSCALL=y
# CONFIG_PHY_PXA_28NM_HSIC is not set
# CONFIG_PHY_PXA_28NM_USB2 is not set
# CONFIG_PHY_QCOM_DWC3 is not set
# CONFIG_PHY_QCOM_USB_HS is not set
# CONFIG_PHY_QCOM_USB_HSIC is not set
# CONFIG_PHY_SAMSUNG_USB2 is not set
# CONFIG_PHY_TUSB1210 is not set
# CONFIG_PHY_XGENE is not set
# CONFIG_PI433 is not set
# CONFIG_PID_IN_CONTEXTIDR is not set
@ -3685,6 +3692,7 @@ CONFIG_PINMUX=y
# CONFIG_PLATFORM_MHU is not set
# CONFIG_PLAT_SPEAR is not set
# CONFIG_PLIP is not set
CONFIG_PLUGIN_HOSTCC=""
# CONFIG_PLX_HERMES is not set
# CONFIG_PM is not set
# CONFIG_PMBUS is not set
@ -4939,6 +4947,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB_SILENT is not set
# CONFIG_SSFDC is not set
# CONFIG_STACKPROTECTOR is not set
# CONFIG_STACKPROTECTOR_STRONG is not set
# CONFIG_STACKTRACE is not set
CONFIG_STACKTRACE_SUPPORT=y
# CONFIG_STACK_TRACER is not set
@ -5326,6 +5335,7 @@ CONFIG_USB_DEFAULT_PERSIST=y
# CONFIG_USB_DWC3_OF_SIMPLE is not set
# CONFIG_USB_DWC3_PCI is not set
# CONFIG_USB_DWC3_QCOM is not set
# CONFIG_USB_DWC3_ULPI is not set
# CONFIG_USB_DYNAMIC_MINORS is not set
# CONFIG_USB_EG20T is not set
# CONFIG_USB_EHCI_ATH79 is not set

View File

@ -260,6 +260,7 @@ CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=8
# CONFIG_ARCH_ZYNQMP is not set
# CONFIG_ARCNET is not set
# CONFIG_ARC_EMAC is not set
# CONFIG_ARM64_ERRATUM_1024718 is not set
# CONFIG_ARM64_ERRATUM_819472 is not set
# CONFIG_ARM64_ERRATUM_824069 is not set
# CONFIG_ARM64_ERRATUM_826319 is not set
@ -268,7 +269,6 @@ CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=8
# CONFIG_ARM64_ERRATUM_834220 is not set
# CONFIG_ARM64_ERRATUM_843419 is not set
# CONFIG_ARM64_ERRATUM_845719 is not set
# CONFIG_ARM64_ERRATUM_1024718 is not set
# CONFIG_ARM_APPENDED_DTB is not set
# CONFIG_ARM_ARCH_TIMER is not set
# CONFIG_ARM_BIG_LITTLE_CPUFREQ is not set
@ -598,7 +598,7 @@ CONFIG_BRIDGE=y
CONFIG_BRIDGE_IGMP_SNOOPING=y
# CONFIG_BRIDGE_NETFILTER is not set
# CONFIG_BRIDGE_NF_EBTABLES is not set
# CONFIG_BRIDGE_VLAN_FILTERING is not set
CONFIG_BRIDGE_VLAN_FILTERING=y
# CONFIG_BROADCOM_PHY is not set
CONFIG_BROKEN_ON_SMP=y
# CONFIG_BSD_DISKLABEL is not set
@ -691,8 +691,8 @@ CONFIG_CC_STACKPROTECTOR_NONE=y
# CONFIG_CFG80211_CERTIFICATION_ONUS is not set
# CONFIG_CGROUPS is not set
# CONFIG_CGROUP_DEBUG is not set
# CONFIG_CGROUP_NET_PRIO is not set
# CONFIG_CGROUP_NET_CLASSID is not set
# CONFIG_CGROUP_NET_PRIO is not set
# CONFIG_CHARGER_BQ2415X is not set
# CONFIG_CHARGER_BQ24190 is not set
# CONFIG_CHARGER_BQ24257 is not set
@ -2974,7 +2974,6 @@ CONFIG_NFS_V3=y
# CONFIG_NFT_DUP_IPV6 is not set
# CONFIG_NF_CONNTRACK is not set
# CONFIG_NF_CONNTRACK_AMANDA is not set
# CONFIG_NF_CONNTRACK_CHAIN_EVENTS is not set
# CONFIG_NF_CONNTRACK_EVENTS is not set
# CONFIG_NF_CONNTRACK_FTP is not set
# CONFIG_NF_CONNTRACK_H323 is not set
@ -4225,6 +4224,7 @@ CONFIG_SND_PROC_FS=y
# CONFIG_SND_SOC_FSL_SPDIF is not set
# CONFIG_SND_SOC_FSL_SSI is not set
# CONFIG_SND_SOC_GTM601 is not set
# CONFIG_SND_SOC_ICS43432 is not set
# CONFIG_SND_SOC_IMG is not set
# CONFIG_SND_SOC_IMX_AUDMUX is not set
# CONFIG_SND_SOC_IMX_ES8328 is not set

View File

@ -1,444 +0,0 @@
/*
* LED Kernel Netdev Trigger
*
* Toggles the LED to reflect the link and traffic state of a named net device
*
* Copyright 2007 Oliver Jowett <oliver@opencloud.com>
*
* Derived from ledtrig-timer.c which is:
* Copyright 2005-2006 Openedhand Ltd.
* Author: Richard Purdie <rpurdie@openedhand.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
#include <linux/module.h>
#include <linux/jiffies.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/device.h>
#include <linux/netdevice.h>
#include <linux/timer.h>
#include <linux/ctype.h>
#include <linux/leds.h>
#include "leds.h"
/*
* Configurable sysfs attributes:
*
* device_name - network device name to monitor
*
* interval - duration of LED blink, in milliseconds
*
* mode - either "none" (LED is off) or a space separated list of one or more of:
* link: LED's normal state reflects whether the link is up (has carrier) or not
* tx: LED blinks on transmitted data
* rx: LED blinks on receive data
*
* Some suggestions:
*
* Simple link status LED:
* $ echo netdev >someled/trigger
* $ echo eth0 >someled/device_name
* $ echo link >someled/mode
*
* Ethernet-style link/activity LED:
* $ echo netdev >someled/trigger
* $ echo eth0 >someled/device_name
* $ echo "link tx rx" >someled/mode
*
* Modem-style tx/rx LEDs:
* $ echo netdev >led1/trigger
* $ echo ppp0 >led1/device_name
* $ echo tx >led1/mode
* $ echo netdev >led2/trigger
* $ echo ppp0 >led2/device_name
* $ echo rx >led2/mode
*
*/
#define MODE_LINK 1
#define MODE_TX 2
#define MODE_RX 4
struct led_netdev_data {
spinlock_t lock;
struct delayed_work work;
struct notifier_block notifier;
struct led_classdev *led_cdev;
struct net_device *net_dev;
char device_name[IFNAMSIZ];
unsigned interval;
unsigned mode;
unsigned link_up;
unsigned last_activity;
};
static void set_baseline_state(struct led_netdev_data *trigger_data)
{
if ((trigger_data->mode & MODE_LINK) != 0 && trigger_data->link_up)
led_set_brightness(trigger_data->led_cdev, LED_FULL);
else
led_set_brightness(trigger_data->led_cdev, LED_OFF);
if ((trigger_data->mode & (MODE_TX | MODE_RX)) != 0 && trigger_data->link_up)
schedule_delayed_work(&trigger_data->work, trigger_data->interval);
}
static ssize_t led_device_name_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct led_classdev *led_cdev = dev_get_drvdata(dev);
struct led_netdev_data *trigger_data = led_cdev->trigger_data;
spin_lock_bh(&trigger_data->lock);
sprintf(buf, "%s\n", trigger_data->device_name);
spin_unlock_bh(&trigger_data->lock);
return strlen(buf) + 1;
}
static ssize_t led_device_name_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
struct led_classdev *led_cdev = dev_get_drvdata(dev);
struct led_netdev_data *trigger_data = led_cdev->trigger_data;
if (size >= IFNAMSIZ)
return -EINVAL;
cancel_delayed_work_sync(&trigger_data->work);
spin_lock_bh(&trigger_data->lock);
strcpy(trigger_data->device_name, buf);
if (size > 0 && trigger_data->device_name[size-1] == '\n')
trigger_data->device_name[size-1] = 0;
trigger_data->link_up = 0;
trigger_data->last_activity = 0;
if (trigger_data->device_name[0] != 0) {
/* check for existing device to update from */
trigger_data->net_dev = dev_get_by_name(&init_net, trigger_data->device_name);
if (trigger_data->net_dev != NULL)
trigger_data->link_up = (dev_get_flags(trigger_data->net_dev) & IFF_LOWER_UP) != 0;
}
set_baseline_state(trigger_data);
spin_unlock_bh(&trigger_data->lock);
return size;
}
static DEVICE_ATTR(device_name, 0644, led_device_name_show, led_device_name_store);
static ssize_t led_mode_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct led_classdev *led_cdev = dev_get_drvdata(dev);
struct led_netdev_data *trigger_data = led_cdev->trigger_data;
spin_lock_bh(&trigger_data->lock);
if (trigger_data->mode == 0) {
strcpy(buf, "none\n");
} else {
if (trigger_data->mode & MODE_LINK)
strcat(buf, "link ");
if (trigger_data->mode & MODE_TX)
strcat(buf, "tx ");
if (trigger_data->mode & MODE_RX)
strcat(buf, "rx ");
strcat(buf, "\n");
}
spin_unlock_bh(&trigger_data->lock);
return strlen(buf)+1;
}
static ssize_t led_mode_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
struct led_classdev *led_cdev = dev_get_drvdata(dev);
struct led_netdev_data *trigger_data = led_cdev->trigger_data;
char copybuf[128];
int new_mode = -1;
char *p, *token;
/* take a copy since we don't want to trash the inbound buffer when using strsep */
strncpy(copybuf, buf, sizeof(copybuf));
copybuf[sizeof(copybuf) - 1] = 0;
p = copybuf;
while ((token = strsep(&p, " \t\n")) != NULL) {
if (!*token)
continue;
if (new_mode == -1)
new_mode = 0;
if (!strcmp(token, "none"))
new_mode = 0;
else if (!strcmp(token, "tx"))
new_mode |= MODE_TX;
else if (!strcmp(token, "rx"))
new_mode |= MODE_RX;
else if (!strcmp(token, "link"))
new_mode |= MODE_LINK;
else
return -EINVAL;
}
if (new_mode == -1)
return -EINVAL;
cancel_delayed_work_sync(&trigger_data->work);
spin_lock_bh(&trigger_data->lock);
trigger_data->mode = new_mode;
set_baseline_state(trigger_data);
spin_unlock_bh(&trigger_data->lock);
return size;
}
static DEVICE_ATTR(mode, 0644, led_mode_show, led_mode_store);
static ssize_t led_interval_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct led_classdev *led_cdev = dev_get_drvdata(dev);
struct led_netdev_data *trigger_data = led_cdev->trigger_data;
spin_lock_bh(&trigger_data->lock);
sprintf(buf, "%u\n", jiffies_to_msecs(trigger_data->interval));
spin_unlock_bh(&trigger_data->lock);
return strlen(buf) + 1;
}
static ssize_t led_interval_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
struct led_classdev *led_cdev = dev_get_drvdata(dev);
struct led_netdev_data *trigger_data = led_cdev->trigger_data;
int ret = -EINVAL;
char *after;
unsigned long value = simple_strtoul(buf, &after, 10);
size_t count = after - buf;
if (isspace(*after))
count++;
/* impose some basic bounds on the timer interval */
if (count == size && value >= 5 && value <= 10000) {
cancel_delayed_work_sync(&trigger_data->work);
spin_lock_bh(&trigger_data->lock);
trigger_data->interval = msecs_to_jiffies(value);
set_baseline_state(trigger_data); /* resets timer */
spin_unlock_bh(&trigger_data->lock);
ret = count;
}
return ret;
}
static DEVICE_ATTR(interval, 0644, led_interval_show, led_interval_store);
static int netdev_trig_notify(struct notifier_block *nb,
unsigned long evt,
void *dv)
{
struct net_device *dev = netdev_notifier_info_to_dev((struct netdev_notifier_info *) dv);
struct led_netdev_data *trigger_data = container_of(nb, struct led_netdev_data, notifier);
if (evt != NETDEV_UP && evt != NETDEV_DOWN && evt != NETDEV_CHANGE && evt != NETDEV_REGISTER && evt != NETDEV_UNREGISTER && evt != NETDEV_CHANGENAME)
return NOTIFY_DONE;
if (strcmp(dev->name, trigger_data->device_name))
return NOTIFY_DONE;
cancel_delayed_work_sync(&trigger_data->work);
spin_lock_bh(&trigger_data->lock);
if (evt == NETDEV_REGISTER || evt == NETDEV_CHANGENAME) {
if (trigger_data->net_dev != NULL)
dev_put(trigger_data->net_dev);
dev_hold(dev);
trigger_data->net_dev = dev;
trigger_data->link_up = 0;
goto done;
}
if (evt == NETDEV_UNREGISTER && trigger_data->net_dev != NULL) {
dev_put(trigger_data->net_dev);
trigger_data->net_dev = NULL;
goto done;
}
/* UP / DOWN / CHANGE */
trigger_data->link_up = (evt != NETDEV_DOWN && netif_carrier_ok(dev));
set_baseline_state(trigger_data);
done:
spin_unlock_bh(&trigger_data->lock);
return NOTIFY_DONE;
}
/* here's the real work! */
static void netdev_trig_work(struct work_struct *work)
{
struct led_netdev_data *trigger_data = container_of(work, struct led_netdev_data, work.work);
struct rtnl_link_stats64 *dev_stats;
unsigned new_activity;
struct rtnl_link_stats64 temp;
if (!trigger_data->link_up || !trigger_data->net_dev || (trigger_data->mode & (MODE_TX | MODE_RX)) == 0) {
/* we don't need to do timer work, just reflect link state. */
led_set_brightness(trigger_data->led_cdev, ((trigger_data->mode & MODE_LINK) != 0 && trigger_data->link_up) ? LED_FULL : LED_OFF);
return;
}
dev_stats = dev_get_stats(trigger_data->net_dev, &temp);
new_activity =
((trigger_data->mode & MODE_TX) ? dev_stats->tx_packets : 0) +
((trigger_data->mode & MODE_RX) ? dev_stats->rx_packets : 0);
if (trigger_data->mode & MODE_LINK) {
/* base state is ON (link present) */
/* if there's no link, we don't get this far and the LED is off */
/* OFF -> ON always */
/* ON -> OFF on activity */
if (trigger_data->led_cdev->brightness == LED_OFF) {
led_set_brightness(trigger_data->led_cdev, LED_FULL);
} else if (trigger_data->last_activity != new_activity) {
led_set_brightness(trigger_data->led_cdev, LED_OFF);
}
} else {
/* base state is OFF */
/* ON -> OFF always */
/* OFF -> ON on activity */
if (trigger_data->led_cdev->brightness == LED_FULL) {
led_set_brightness(trigger_data->led_cdev, LED_OFF);
} else if (trigger_data->last_activity != new_activity) {
led_set_brightness(trigger_data->led_cdev, LED_FULL);
}
}
trigger_data->last_activity = new_activity;
schedule_delayed_work(&trigger_data->work, trigger_data->interval);
}
static void netdev_trig_activate(struct led_classdev *led_cdev)
{
struct led_netdev_data *trigger_data;
int rc;
trigger_data = kzalloc(sizeof(struct led_netdev_data), GFP_KERNEL);
if (!trigger_data)
return;
spin_lock_init(&trigger_data->lock);
trigger_data->notifier.notifier_call = netdev_trig_notify;
trigger_data->notifier.priority = 10;
INIT_DELAYED_WORK(&trigger_data->work, netdev_trig_work);
trigger_data->led_cdev = led_cdev;
trigger_data->net_dev = NULL;
trigger_data->device_name[0] = 0;
trigger_data->mode = 0;
trigger_data->interval = msecs_to_jiffies(50);
trigger_data->link_up = 0;
trigger_data->last_activity = 0;
led_cdev->trigger_data = trigger_data;
rc = device_create_file(led_cdev->dev, &dev_attr_device_name);
if (rc)
goto err_out;
rc = device_create_file(led_cdev->dev, &dev_attr_mode);
if (rc)
goto err_out_device_name;
rc = device_create_file(led_cdev->dev, &dev_attr_interval);
if (rc)
goto err_out_mode;
register_netdevice_notifier(&trigger_data->notifier);
return;
err_out_mode:
device_remove_file(led_cdev->dev, &dev_attr_mode);
err_out_device_name:
device_remove_file(led_cdev->dev, &dev_attr_device_name);
err_out:
led_cdev->trigger_data = NULL;
kfree(trigger_data);
}
static void netdev_trig_deactivate(struct led_classdev *led_cdev)
{
struct led_netdev_data *trigger_data = led_cdev->trigger_data;
if (trigger_data) {
unregister_netdevice_notifier(&trigger_data->notifier);
device_remove_file(led_cdev->dev, &dev_attr_device_name);
device_remove_file(led_cdev->dev, &dev_attr_mode);
device_remove_file(led_cdev->dev, &dev_attr_interval);
cancel_delayed_work_sync(&trigger_data->work);
spin_lock_bh(&trigger_data->lock);
if (trigger_data->net_dev) {
dev_put(trigger_data->net_dev);
trigger_data->net_dev = NULL;
}
spin_unlock_bh(&trigger_data->lock);
kfree(trigger_data);
}
}
static struct led_trigger netdev_led_trigger = {
.name = "netdev",
.activate = netdev_trig_activate,
.deactivate = netdev_trig_deactivate,
};
static int __init netdev_trig_init(void)
{
return led_trigger_register(&netdev_led_trigger);
}
static void __exit netdev_trig_exit(void)
{
led_trigger_unregister(&netdev_led_trigger);
}
module_init(netdev_trig_init);
module_exit(netdev_trig_exit);
MODULE_AUTHOR("Oliver Jowett <oliver@opencloud.com>");
MODULE_DESCRIPTION("Netdev LED trigger");
MODULE_LICENSE("GPL");

View File

@ -79,9 +79,15 @@ static int mtdsplit_parse_eva(struct mtd_info *master,
return EVA_NR_PARTS;
}
static const struct of_device_id mtdsplit_eva_of_match_table[] = {
{ .compatible = "avm,eva-firmware" },
{},
};
static struct mtd_part_parser mtdsplit_eva_parser = {
.owner = THIS_MODULE,
.name = "eva-fw",
.of_match_table = mtdsplit_eva_of_match_table,
.parse_fn = mtdsplit_parse_eva,
.type = MTD_PARSER_TYPE_FIRMWARE,
};

View File

@ -120,9 +120,15 @@ mtdsplit_fit_parse(struct mtd_info *mtd,
return 2;
}
static const struct of_device_id mtdsplit_fit_of_match_table[] = {
{ .compatible = "denx,fit" },
{},
};
static struct mtd_part_parser uimage_parser = {
.owner = THIS_MODULE,
.name = "fit-fw",
.of_match_table = mtdsplit_fit_of_match_table,
.parse_fn = mtdsplit_fit_parse,
.type = MTD_PARSER_TYPE_FIRMWARE,
};

View File

@ -256,9 +256,15 @@ mtdsplit_jimage_parse_generic(struct mtd_info *master,
jimage_verify_default);
}
static const struct of_device_id mtdsplit_jimage_of_match_table[] = {
{ .compatible = "amit,jimage" },
{},
};
static struct mtd_part_parser jimage_generic_parser = {
.owner = THIS_MODULE,
.name = "jimage-fw",
.of_match_table = mtdsplit_jimage_of_match_table,
.parse_fn = mtdsplit_jimage_parse_generic,
.type = MTD_PARSER_TYPE_FIRMWARE,
};

View File

@ -79,9 +79,16 @@ static int mtdsplit_parse_lzma(struct mtd_info *master,
return LZMA_NR_PARTS;
}
static const struct of_device_id mtdsplit_lzma_of_match_table[] = {
{ .compatible = "lzma" },
{},
};
MODULE_DEVICE_TABLE(of, mtdsplit_lzma_of_match_table);
static struct mtd_part_parser mtdsplit_lzma_parser = {
.owner = THIS_MODULE,
.name = "lzma-fw",
.of_match_table = mtdsplit_lzma_of_match_table,
.parse_fn = mtdsplit_parse_lzma,
.type = MTD_PARSER_TYPE_FIRMWARE,
};

View File

@ -100,9 +100,16 @@ static int mtdsplit_parse_minor(struct mtd_info *master,
return MINOR_NR_PARTS;
}
static const struct of_device_id mtdsplit_minor_of_match_table[] = {
{ .compatible = "mikrotik,minor" },
{},
};
MODULE_DEVICE_TABLE(of, mtdsplit_minor_of_match_table);
static struct mtd_part_parser mtdsplit_minor_parser = {
.owner = THIS_MODULE,
.name = "minor-fw",
.of_match_table = mtdsplit_minor_of_match_table,
.parse_fn = mtdsplit_parse_minor,
.type = MTD_PARSER_TYPE_FIRMWARE,
};

View File

@ -93,9 +93,16 @@ static int mtdsplit_parse_seama(struct mtd_info *master,
return SEAMA_NR_PARTS;
}
static const struct of_device_id mtdsplit_seama_of_match_table[] = {
{ .compatible = "seama" },
{},
};
MODULE_DEVICE_TABLE(of, mtdsplit_seama_of_match_table);
static struct mtd_part_parser mtdsplit_seama_parser = {
.owner = THIS_MODULE,
.name = "seama-fw",
.of_match_table = mtdsplit_seama_of_match_table,
.parse_fn = mtdsplit_parse_seama,
.type = MTD_PARSER_TYPE_FIRMWARE,
};

View File

@ -152,9 +152,15 @@ static int mtdsplit_parse_tplink(struct mtd_info *master,
return TPLINK_NR_PARTS;
}
static const struct of_device_id mtdsplit_tplink_of_match_table[] = {
{ .compatible = "tplink,firmware" },
{},
};
static struct mtd_part_parser mtdsplit_tplink_parser = {
.owner = THIS_MODULE,
.name = "tplink-fw",
.of_match_table = mtdsplit_tplink_of_match_table,
.parse_fn = mtdsplit_parse_tplink,
.type = MTD_PARSER_TYPE_FIRMWARE,
};

View File

@ -130,9 +130,16 @@ err:
return ret;
}
static const struct of_device_id trx_parser_of_match_table[] = {
{ .compatible = "openwrt,trx" },
{},
};
MODULE_DEVICE_TABLE(of, trx_parser_of_match_table);
static struct mtd_part_parser trx_parser = {
.owner = THIS_MODULE,
.name = "trx-fw",
.of_match_table = trx_parser_of_match_table,
.parse_fn = mtdsplit_parse_trx,
.type = MTD_PARSER_TYPE_FIRMWARE,
};

View File

@ -16,6 +16,7 @@
#include <linux/vmalloc.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/version.h>
#include <linux/byteorder/generic.h>
#include "mtdsplit.h"
@ -239,9 +240,19 @@ mtdsplit_uimage_parse_generic(struct mtd_info *master,
uimage_verify_default);
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)
static const struct of_device_id mtdsplit_uimage_of_match_table[] = {
{ .compatible = "denx,uimage" },
{},
};
#endif
static struct mtd_part_parser uimage_generic_parser = {
.owner = THIS_MODULE,
.name = "uimage-fw",
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)
.of_match_table = mtdsplit_uimage_of_match_table,
#endif
.parse_fn = mtdsplit_uimage_parse_generic,
.type = MTD_PARSER_TYPE_FIRMWARE,
};
@ -296,9 +307,19 @@ mtdsplit_uimage_parse_netgear(struct mtd_info *master,
uimage_verify_wndr3700);
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)
static const struct of_device_id mtdsplit_uimage_netgear_of_match_table[] = {
{ .compatible = "netgear,uimage" },
{},
};
#endif
static struct mtd_part_parser uimage_netgear_parser = {
.owner = THIS_MODULE,
.name = "netgear-fw",
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)
.of_match_table = mtdsplit_uimage_netgear_of_match_table,
#endif
.parse_fn = mtdsplit_uimage_parse_netgear,
.type = MTD_PARSER_TYPE_FIRMWARE,
};

View File

@ -107,9 +107,16 @@ static int mtdsplit_parse_wrgg(struct mtd_info *master,
return WRGG_NR_PARTS;
}
static const struct of_device_id mtdsplit_wrgg_of_match_table[] = {
{ .compatible = "wrg" },
{},
};
MODULE_DEVICE_TABLE(of, mtdsplit_wrgg_of_match_table);
static struct mtd_part_parser mtdsplit_wrgg_parser = {
.owner = THIS_MODULE,
.name = "wrgg-fw",
.of_match_table = mtdsplit_wrgg_of_match_table,
.parse_fn = mtdsplit_parse_wrgg,
.type = MTD_PARSER_TYPE_FIRMWARE,
};

View File

@ -295,6 +295,17 @@ ar8xxx_rmw(struct ar8xxx_priv *priv, int reg, u32 mask, u32 val)
return ret;
}
void
ar8xxx_phy_dbg_read(struct ar8xxx_priv *priv, int phy_addr,
u16 dbg_addr, u16 *dbg_data)
{
struct mii_bus *bus = priv->mii_bus;
mutex_lock(&bus->mdio_lock);
bus->write(bus, phy_addr, MII_ATH_DBG_ADDR, dbg_addr);
*dbg_data = bus->read(bus, phy_addr, MII_ATH_DBG_DATA);
mutex_unlock(&bus->mdio_lock);
}
void
ar8xxx_phy_dbg_write(struct ar8xxx_priv *priv, int phy_addr,
@ -749,7 +760,6 @@ static void ar8216_get_arl_entry(struct ar8xxx_priv *priv,
u16 r2, page;
u16 r1_func0, r1_func1, r1_func2;
u32 t, val0, val1, val2;
int i;
split_addr(AR8216_REG_ATU_FUNC0, &r1_func0, &r2, &page);
r2 |= 0x10;
@ -785,12 +795,7 @@ static void ar8216_get_arl_entry(struct ar8xxx_priv *priv,
if (!*status)
break;
i = 0;
t = AR8216_ATU_PORT0;
while (!(val2 & t) && ++i < priv->dev.ports)
t <<= 1;
a->port = i;
a->portmap = (val2 & AR8216_ATU_PORTS) >> AR8216_ATU_PORTS_S;
a->mac[0] = (val0 & AR8216_ATU_ADDR5) >> AR8216_ATU_ADDR5_S;
a->mac[1] = (val0 & AR8216_ATU_ADDR4) >> AR8216_ATU_ADDR4_S;
a->mac[2] = (val1 & AR8216_ATU_ADDR3) >> AR8216_ATU_ADDR3_S;
@ -1516,8 +1521,12 @@ ar8xxx_sw_get_arl_table(struct switch_dev *dev,
*/
for (j = 0; j < i; ++j) {
a1 = &priv->arl_table[j];
if (a->port == a1->port && !memcmp(a->mac, a1->mac, sizeof(a->mac)))
goto duplicate;
if (!memcmp(a->mac, a1->mac, sizeof(a->mac))) {
/* ignore ports already seen in former entry */
a->portmap &= ~a1->portmap;
if (!a->portmap)
goto duplicate;
}
}
}
@ -1534,7 +1543,7 @@ ar8xxx_sw_get_arl_table(struct switch_dev *dev,
for (j = 0; j < priv->dev.ports; ++j) {
for (k = 0; k < i; ++k) {
a = &priv->arl_table[k];
if (a->port != j)
if (!(a->portmap & BIT(j)))
continue;
len += snprintf(buf + len, sizeof(priv->arl_buf) - len,
"Port %d: MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
@ -2104,7 +2113,8 @@ ar8xxx_phy_read_status(struct phy_device *phydev)
phydev->state = PHY_RUNNING;
netif_carrier_on(phydev->attached_dev);
phydev->adjust_link(phydev->attached_dev);
if (phydev->adjust_link)
phydev->adjust_link(phydev->attached_dev);
return 0;
}
@ -2167,7 +2177,7 @@ ar8xxx_phy_probe(struct phy_device *phydev)
int ret;
/* skip PHYs at unused adresses */
if (phydev->mdio.addr != 0 && phydev->mdio.addr != 4)
if (phydev->mdio.addr != 0 && phydev->mdio.addr != 3 && phydev->mdio.addr != 4)
return -ENODEV;
if (!ar8xxx_is_possible(phydev->mdio.bus))
@ -2226,6 +2236,8 @@ found:
phydev->supported |= SUPPORTED_1000baseT_Full;
phydev->advertising |= ADVERTISED_1000baseT_Full;
}
if (priv->chip->phy_rgmii_set)
priv->chip->phy_rgmii_set(priv, phydev);
}
phydev->priv = priv;

View File

@ -112,6 +112,7 @@
#define AR8216_REG_ATU_FUNC2 0x0058
#define AR8216_ATU_PORTS BITS(0, 6)
#define AR8216_ATU_PORTS_S 0
#define AR8216_ATU_PORT0 BIT(0)
#define AR8216_ATU_PORT1 BIT(1)
#define AR8216_ATU_PORT2 BIT(2)
@ -367,7 +368,7 @@ enum arl_op {
};
struct arl_entry {
u8 port;
u16 portmap;
u8 mac[6];
};
@ -412,6 +413,7 @@ struct ar8xxx_chip {
void (*get_arl_entry)(struct ar8xxx_priv *priv, struct arl_entry *a,
u32 *status, enum arl_op op);
int (*sw_hw_apply)(struct switch_dev *dev);
void (*phy_rgmii_set)(struct ar8xxx_priv *priv, struct phy_device *phydev);
const struct ar8xxx_mib_desc *mib_decs;
unsigned num_mibs;
@ -476,6 +478,9 @@ ar8xxx_write(struct ar8xxx_priv *priv, int reg, u32 val);
u32
ar8xxx_rmw(struct ar8xxx_priv *priv, int reg, u32 mask, u32 val);
void
ar8xxx_phy_dbg_read(struct ar8xxx_priv *priv, int phy_addr,
u16 dbg_addr, u16 *dbg_data);
void
ar8xxx_phy_dbg_write(struct ar8xxx_priv *priv, int phy_addr,
u16 dbg_addr, u16 dbg_data);

View File

@ -127,6 +127,49 @@ ar8327_get_pad_cfg(struct ar8327_pad_cfg *cfg)
return t;
}
static void
ar8327_phy_rgmii_set(struct ar8xxx_priv *priv, struct phy_device *phydev)
{
u16 phy_val = 0;
int phyaddr = phydev->mdio.addr;
struct device_node *np = phydev->mdio.dev.of_node;
if (!np)
return;
if (!of_property_read_bool(np, "qca,phy-rgmii-en")) {
pr_err("ar8327: qca,phy-rgmii-en is not specified\n");
return -EINVAL;
}
ar8xxx_phy_dbg_read(priv, phyaddr,
AR8327_PHY_MODE_SEL, &phy_val);
phy_val |= AR8327_PHY_MODE_SEL_RGMII;
ar8xxx_phy_dbg_write(priv, phyaddr,
AR8327_PHY_MODE_SEL, phy_val);
/* set rgmii tx clock delay if needed */
if (!of_property_read_bool(np, "qca,txclk-delay-en")) {
pr_err("ar8327: qca,txclk-delay-en is not specified\n");
return -EINVAL;
}
ar8xxx_phy_dbg_read(priv, phyaddr,
AR8327_PHY_SYS_CTRL, &phy_val);
phy_val |= AR8327_PHY_SYS_CTRL_RGMII_TX_DELAY;
ar8xxx_phy_dbg_write(priv, phyaddr,
AR8327_PHY_SYS_CTRL, phy_val);
/* set rgmii rx clock delay if needed */
if (!of_property_read_bool(np, "qca,rxclk-delay-en")) {
pr_err("ar8327: qca,rxclk-delay-en is not specified\n");
return -EINVAL;
}
ar8xxx_phy_dbg_read(priv, phyaddr,
AR8327_PHY_TEST_CTRL, &phy_val);
phy_val |= AR8327_PHY_TEST_CTRL_RGMII_RX_DELAY;
ar8xxx_phy_dbg_write(priv, phyaddr,
AR8327_PHY_TEST_CTRL, phy_val);
}
static void
ar8327_phy_fixup(struct ar8xxx_priv *priv, int phy)
{
@ -1057,8 +1100,7 @@ static void ar8327_get_arl_entry(struct ar8xxx_priv *priv,
struct mii_bus *bus = priv->mii_bus;
u16 r2, page;
u16 r1_data0, r1_data1, r1_data2, r1_func;
u32 t, val0, val1, val2;
int i;
u32 val0, val1, val2;
split_addr(AR8327_REG_ATU_DATA0, &r1_data0, &r2, &page);
r2 |= 0x10;
@ -1095,12 +1137,7 @@ static void ar8327_get_arl_entry(struct ar8xxx_priv *priv,
if (!*status)
break;
i = 0;
t = AR8327_ATU_PORT0;
while (!(val1 & t) && ++i < AR8327_NUM_PORTS)
t <<= 1;
a->port = i;
a->portmap = (val1 & AR8327_ATU_PORTS) >> AR8327_ATU_PORTS_S;
a->mac[0] = (val0 & AR8327_ATU_ADDR0) >> AR8327_ATU_ADDR0_S;
a->mac[1] = (val0 & AR8327_ATU_ADDR1) >> AR8327_ATU_ADDR1_S;
a->mac[2] = (val0 & AR8327_ATU_ADDR2) >> AR8327_ATU_ADDR2_S;
@ -1496,6 +1533,7 @@ const struct ar8xxx_chip ar8337_chip = {
.set_mirror_regs = ar8327_set_mirror_regs,
.get_arl_entry = ar8327_get_arl_entry,
.sw_hw_apply = ar8327_sw_hw_apply,
.phy_rgmii_set = ar8327_phy_rgmii_set,
.num_mibs = ARRAY_SIZE(ar8236_mibs),
.mib_decs = ar8236_mibs,

View File

@ -199,6 +199,7 @@
#define AR8327_ATU_ADDR5 BITS(8, 8)
#define AR8327_ATU_ADDR5_S 8
#define AR8327_ATU_PORTS BITS(16, 7)
#define AR8327_ATU_PORTS_S 16
#define AR8327_ATU_PORT0 BIT(16)
#define AR8327_ATU_PORT1 BIT(17)
#define AR8327_ATU_PORT2 BIT(18)
@ -283,6 +284,13 @@
#define AR8337_PAD_MAC06_EXCHANGE_EN BIT(31)
#define AR8327_PHY_MODE_SEL 0x12
#define AR8327_PHY_MODE_SEL_RGMII BIT(3)
#define AR8327_PHY_TEST_CTRL 0x0
#define AR8327_PHY_TEST_CTRL_RGMII_RX_DELAY BIT(15)
#define AR8327_PHY_SYS_CTRL 0x5
#define AR8327_PHY_SYS_CTRL_RGMII_TX_DELAY BIT(8)
enum ar8327_led_pattern {
AR8327_LED_PATTERN_OFF = 0,
AR8327_LED_PATTERN_BLINK,

View File

@ -273,47 +273,34 @@ static struct b53_io_ops b53_mdio_ops = {
static int b53_phy_probe(struct phy_device *phydev)
{
struct b53_device dev;
struct b53_device *dev;
int ret;
/* allow the generic phy driver to take over */
if (phydev->mdio.addr != B53_PSEUDO_PHY && phydev->mdio.addr != 0)
return -ENODEV;
dev.current_page = 0xff;
dev.priv = phydev->mdio.bus;
dev.ops = &b53_mdio_ops;
dev.pdata = NULL;
mutex_init(&dev.reg_mutex);
dev = b53_switch_alloc(&phydev->mdio.dev, &b53_mdio_ops, phydev->mdio.bus);
if (!dev)
return -ENOMEM;
ret = b53_switch_detect(&dev);
dev->current_page = 0xff;
dev->priv = phydev->mdio.bus;
dev->ops = &b53_mdio_ops;
dev->pdata = NULL;
mutex_init(&dev->reg_mutex);
ret = b53_switch_detect(dev);
if (ret)
return ret;
if (is5325(&dev) || is5365(&dev))
if (is5325(dev) || is5365(dev))
phydev->supported = SUPPORTED_100baseT_Full;
else
phydev->supported = SUPPORTED_1000baseT_Full;
phydev->advertising = phydev->supported;
return 0;
}
static int b53_phy_config_init(struct phy_device *phydev)
{
struct b53_device *dev;
int ret;
dev = b53_switch_alloc(&phydev->mdio.dev, &b53_mdio_ops, phydev->mdio.bus);
if (!dev)
return -ENOMEM;
/* we don't use page 0xff, so force a page set */
dev->current_page = 0xff;
/* force the ethX as alias */
dev->sw_dev.alias = phydev->attached_dev->name;
ret = b53_switch_register(dev);
if (ret) {
dev_err(dev->dev, "failed to register switch: %i\n", ret);
@ -325,6 +312,18 @@ static int b53_phy_config_init(struct phy_device *phydev)
return 0;
}
static int b53_phy_config_init(struct phy_device *phydev)
{
struct b53_device *dev = phydev->priv;
/* we don't use page 0xff, so force a page set */
dev->current_page = 0xff;
/* force the ethX as alias */
dev->sw_dev.alias = phydev->attached_dev->name;
return 0;
}
static void b53_phy_remove(struct phy_device *phydev)
{
struct b53_device *priv = phydev->priv;

View File

@ -454,6 +454,86 @@ static int mvsw61xx_set_enable_vlan(struct switch_dev *dev,
return 0;
}
static int mvsw61xx_get_mirror_rx_enable(struct switch_dev *dev,
const struct switch_attr *attr, struct switch_val *val)
{
struct mvsw61xx_state *state = get_state(dev);
val->value.i = state->mirror_rx;
return 0;
}
static int mvsw61xx_set_mirror_rx_enable(struct switch_dev *dev,
const struct switch_attr *attr, struct switch_val *val)
{
struct mvsw61xx_state *state = get_state(dev);
state->mirror_rx = val->value.i;
return 0;
}
static int mvsw61xx_get_mirror_tx_enable(struct switch_dev *dev,
const struct switch_attr *attr, struct switch_val *val)
{
struct mvsw61xx_state *state = get_state(dev);
val->value.i = state->mirror_tx;
return 0;
}
static int mvsw61xx_set_mirror_tx_enable(struct switch_dev *dev,
const struct switch_attr *attr, struct switch_val *val)
{
struct mvsw61xx_state *state = get_state(dev);
state->mirror_tx = val->value.i;
return 0;
}
static int mvsw61xx_get_mirror_monitor_port(struct switch_dev *dev,
const struct switch_attr *attr, struct switch_val *val)
{
struct mvsw61xx_state *state = get_state(dev);
val->value.i = state->monitor_port;
return 0;
}
static int mvsw61xx_set_mirror_monitor_port(struct switch_dev *dev,
const struct switch_attr *attr, struct switch_val *val)
{
struct mvsw61xx_state *state = get_state(dev);
state->monitor_port = val->value.i;
return 0;
}
static int mvsw61xx_get_mirror_source_port(struct switch_dev *dev,
const struct switch_attr *attr, struct switch_val *val)
{
struct mvsw61xx_state *state = get_state(dev);
val->value.i = state->source_port;
return 0;
}
static int mvsw61xx_set_mirror_source_port(struct switch_dev *dev,
const struct switch_attr *attr, struct switch_val *val)
{
struct mvsw61xx_state *state = get_state(dev);
state->source_port = val->value.i;
return 0;
}
static int mvsw61xx_vtu_program(struct switch_dev *dev)
{
struct mvsw61xx_state *state = get_state(dev);
@ -604,6 +684,40 @@ static int mvsw61xx_update_state(struct switch_dev *dev)
mvsw61xx_vtu_program(dev);
/* port mirroring */
/* reset all mirror registers */
for (i = 0; i < dev->ports; i++) {
reg = sr16(dev, MV_PORTREG(CONTROL2, i));
reg &= ~(MV_MIRROR_RX_SRC_MASK | MV_MIRROR_TX_SRC_MASK);
sw16(dev, MV_PORTREG(CONTROL2, i), reg);
}
reg = sr16(dev, MV_GLOBALREG(MONITOR_CTRL));
reg |= MV_MIRROR_RX_DEST_MASK | MV_MIRROR_TX_DEST_MASK;
sw16(dev, MV_GLOBALREG(MONITOR_CTRL), reg);
/* now enable mirroring if necessary */
if (state->mirror_rx) {
/* set ingress monitor source */
reg = sr16(dev, MV_PORTREG(CONTROL2, state->source_port)) & ~MV_MIRROR_RX_SRC_MASK;
reg |= state->mirror_rx << MV_MIRROR_RX_SRC_SHIFT;
sw16(dev, MV_PORTREG(CONTROL2, state->source_port), reg);
/* set ingress monitor destination */
reg = sr16(dev, MV_GLOBALREG(MONITOR_CTRL)) & ~MV_MIRROR_RX_DEST_MASK;
reg |= state->monitor_port << MV_MIRROR_RX_DEST_SHIFT;
sw16(dev, MV_GLOBALREG(MONITOR_CTRL), reg);
}
if (state->mirror_tx) {
/* set egress monitor source */
reg = sr16(dev, MV_PORTREG(CONTROL2, state->source_port)) & ~MV_MIRROR_TX_SRC_MASK;
reg |= state->mirror_tx << MV_MIRROR_TX_SRC_SHIFT;
sw16(dev, MV_PORTREG(CONTROL2, state->source_port), reg);
/* set egress monitor destination */
reg = sr16(dev, MV_GLOBALREG(MONITOR_CTRL)) & ~MV_MIRROR_TX_DEST_MASK;
reg |= state->monitor_port << MV_MIRROR_TX_DEST_SHIFT;
sw16(dev, MV_GLOBALREG(MONITOR_CTRL), reg);
}
return 0;
}
@ -693,6 +807,11 @@ static int _mvsw61xx_reset(struct switch_dev *dev, bool full)
state->vlan_enabled = 0;
state->mirror_rx = false;
state->mirror_tx = false;
state->source_port = 0;
state->monitor_port = 0;
mvsw61xx_update_state(dev);
/* Re-enable ports */
@ -710,10 +829,6 @@ static int mvsw61xx_reset(struct switch_dev *dev)
return _mvsw61xx_reset(dev, false);
}
enum {
MVSW61XX_ENABLE_VLAN,
};
enum {
MVSW61XX_VLAN_PORT_BASED,
MVSW61XX_VLAN_ID,
@ -725,14 +840,45 @@ enum {
};
static const struct switch_attr mvsw61xx_global[] = {
[MVSW61XX_ENABLE_VLAN] = {
.id = MVSW61XX_ENABLE_VLAN,
{
.type = SWITCH_TYPE_INT,
.name = "enable_vlan",
.description = "Enable 802.1q VLAN support",
.get = mvsw61xx_get_enable_vlan,
.set = mvsw61xx_set_enable_vlan,
},
{
.type = SWITCH_TYPE_INT,
.name = "enable_mirror_rx",
.description = "Enable mirroring of RX packets",
.set = mvsw61xx_set_mirror_rx_enable,
.get = mvsw61xx_get_mirror_rx_enable,
.max = 1
},
{
.type = SWITCH_TYPE_INT,
.name = "enable_mirror_tx",
.description = "Enable mirroring of TX packets",
.set = mvsw61xx_set_mirror_tx_enable,
.get = mvsw61xx_get_mirror_tx_enable,
.max = 1
},
{
.type = SWITCH_TYPE_INT,
.name = "mirror_monitor_port",
.description = "Mirror monitor port",
.set = mvsw61xx_set_mirror_monitor_port,
.get = mvsw61xx_get_mirror_monitor_port,
.max = MV_PORTS - 1
},
{
.type = SWITCH_TYPE_INT,
.name = "mirror_source_port",
.description = "Mirror source port",
.set = mvsw61xx_set_mirror_source_port,
.get = mvsw61xx_get_mirror_source_port,
.max = MV_PORTS - 1
},
};
static const struct switch_attr mvsw61xx_vlan[] = {

View File

@ -165,6 +165,7 @@ enum {
MV_GLOBAL_VTU_DATA1 = 0x07,
MV_GLOBAL_VTU_DATA2 = 0x08,
MV_GLOBAL_VTU_DATA3 = 0x09,
MV_GLOBAL_MONITOR_CTRL = 0x1a,
MV_GLOBAL_CONTROL2 = 0x1c,
};
#define MV_GLOBALREG(_type) MV_SWITCH_GLOBAL, MV_GLOBAL_##_type
@ -242,6 +243,16 @@ enum {
#define MV_FDB_HI_SHIFT 4
#define MV_FDB_LO_SHIFT 12
#define MV_MIRROR_RX_DEST_MASK 0xf000
#define MV_MIRROR_TX_DEST_MASK 0x0f00
#define MV_MIRROR_RX_DEST_SHIFT 12
#define MV_MIRROR_TX_DEST_SHIFT 8
#define MV_MIRROR_RX_SRC_SHIFT 4
#define MV_MIRROR_RX_SRC_MASK (1 << MV_MIRROR_RX_SRC_SHIFT)
#define MV_MIRROR_TX_SRC_SHIFT 5
#define MV_MIRROR_TX_SRC_MASK (1 << MV_MIRROR_TX_SRC_SHIFT)
/* Marvell Specific PHY register */
#define MII_MV_SPEC_CTRL 16
enum {
@ -284,6 +295,12 @@ struct mvsw61xx_state {
u32 port_sstate;
} vlans[MV_VLANS];
/* mirroring */
bool mirror_rx;
bool mirror_tx;
int source_port;
int monitor_port;
char buf[128];
};

View File

@ -1553,8 +1553,8 @@ int rtl8366_smi_probe_of(struct platform_device *pdev, struct rtl8366_smi *smi)
smi->ext_mbus = of_mdio_find_bus(mdio_node);
if (!smi->ext_mbus) {
dev_err(&pdev->dev,
"cannot find mdio bus from bus handle");
dev_info(&pdev->dev,
"cannot find mdio bus from bus handle (yet)");
goto try_gpio;
}
@ -1562,8 +1562,12 @@ int rtl8366_smi_probe_of(struct platform_device *pdev, struct rtl8366_smi *smi)
try_gpio:
if (!gpio_is_valid(sck) || !gpio_is_valid(sda)) {
dev_err(&pdev->dev, "gpios missing in devictree\n");
return -EINVAL;
if (!mdio_node) {
dev_err(&pdev->dev, "gpios missing in devictree\n");
return -EINVAL;
} else {
return -EPROBE_DEFER;
}
}
smi->gpio_sda = sda;
@ -1619,7 +1623,7 @@ struct rtl8366_smi *rtl8366_smi_probe(struct platform_device *pdev)
free_smi:
kfree(smi);
return NULL;
return ERR_PTR(err);
}
EXPORT_SYMBOL_GPL(rtl8366_smi_probe);

View File

@ -1445,8 +1445,8 @@ static int rtl8366rb_probe(struct platform_device *pdev)
" version " RTL8366RB_DRIVER_VER"\n");
smi = rtl8366_smi_probe(pdev);
if (!smi)
return -ENODEV;
if (IS_ERR(smi))
return PTR_ERR(smi);
smi->clk_delay = 10;
smi->cmd_read = 0xa9;

View File

@ -1233,8 +1233,8 @@ static int rtl8366s_probe(struct platform_device *pdev)
" version " RTL8366S_DRIVER_VER"\n");
smi = rtl8366_smi_probe(pdev);
if (!smi)
return -ENODEV;
if (IS_ERR(smi))
return PTR_ERR(smi);
smi->clk_delay = 10;
smi->cmd_read = 0xa9;

View File

@ -1752,8 +1752,8 @@ static int rtl8367_probe(struct platform_device *pdev)
int err;
smi = rtl8366_smi_probe(pdev);
if (!smi)
return -ENODEV;
if (IS_ERR(smi))
return PTR_ERR(smi);
smi->clk_delay = 1500;
smi->cmd_read = 0xb9;

View File

@ -1401,7 +1401,7 @@ static int rtl8367b_switch_init(struct rtl8366_smi *smi)
int err;
dev->name = "RTL8367B";
dev->cpu_port = RTL8367B_CPU_PORT_NUM;
dev->cpu_port = smi->cpu_port;
dev->ports = RTL8367B_NUM_PORTS;
dev->vlans = RTL8367B_NUM_VIDS;
dev->ops = &rtl8367b_sw_ops;
@ -1527,15 +1527,17 @@ static int rtl8367b_probe(struct platform_device *pdev)
int err;
smi = rtl8366_smi_probe(pdev);
if (!smi)
return -ENODEV;
if (IS_ERR(smi))
return PTR_ERR(smi);
smi->clk_delay = 1500;
smi->cmd_read = 0xb9;
smi->cmd_write = 0xb8;
smi->ops = &rtl8367b_smi_ops;
smi->cpu_port = RTL8367B_CPU_PORT_NUM;
smi->num_ports = RTL8367B_NUM_PORTS;
if (of_property_read_u32(pdev->dev.of_node, "cpu_port", &smi->cpu_port)
|| smi->cpu_port >= smi->num_ports)
smi->cpu_port = RTL8367B_CPU_PORT_NUM;
smi->num_vlan_mc = RTL8367B_NUM_VLANS;
smi->mib_counters = rtl8367b_mib_counters;
smi->num_mib_counters = ARRAY_SIZE(rtl8367b_mib_counters);

View File

@ -274,19 +274,16 @@ static ssize_t swconfig_trig_mode_store(struct device *dev,
static DEVICE_ATTR(mode, 0644, swconfig_trig_mode_show,
swconfig_trig_mode_store);
static void
static int
swconfig_trig_activate(struct led_classdev *led_cdev)
{
struct switch_led_trigger *sw_trig;
struct swconfig_trig_data *trig_data;
int err;
if (led_cdev->trigger->activate != swconfig_trig_activate)
return;
trig_data = kzalloc(sizeof(struct swconfig_trig_data), GFP_KERNEL);
if (!trig_data)
return;
return -ENOMEM;
sw_trig = (void *) led_cdev->trigger;
@ -309,7 +306,7 @@ swconfig_trig_activate(struct led_classdev *led_cdev)
if (err)
goto err_mode_free;
return;
return 0;
err_mode_free:
device_remove_file(led_cdev->dev, &dev_attr_speed_mask);
@ -320,8 +317,18 @@ err_dev_free:
err_free:
led_cdev->trigger_data = NULL;
kfree(trig_data);
return err;
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,19,0)
static void
swconfig_trig_activate_void(struct led_classdev *led_cdev)
{
swconfig_trig_activate(led_cdev);
}
#endif
static void
swconfig_trig_deactivate(struct led_classdev *led_cdev)
{
@ -516,7 +523,11 @@ swconfig_create_led_trigger(struct switch_dev *swdev)
sw_trig->swdev = swdev;
sw_trig->trig.name = swdev->devname;
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,19,0)
sw_trig->trig.activate = swconfig_trig_activate_void;
#else
sw_trig->trig.activate = swconfig_trig_activate;
#endif
sw_trig->trig.deactivate = swconfig_trig_deactivate;
INIT_DELAYED_WORK(&sw_trig->sw_led_work, swconfig_led_work_func);

View File

@ -1,36 +0,0 @@
/*
* B53 platform data
*
* Copyright (C) 2013 Jonas Gorski <jogo@openwrt.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef __B53_H
#define __B53_H
#include <linux/kernel.h>
struct b53_platform_data {
u32 chip_id;
u16 enabled_ports;
/* allow to specify an ethX alias */
const char *alias;
/* only used by MMAP'd driver */
unsigned big_endian:1;
void __iomem *regs;
};
#endif

View File

@ -126,3 +126,15 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
obj-$(CONFIG_MDIO_BCM_IPROC) += mdio-bcm-iproc.o
obj-$(CONFIG_MDIO_BCM_UNIMAC) += mdio-bcm-unimac.o
obj-$(CONFIG_MDIO_BITBANG) += mdio-bitbang.o
--- a/include/linux/platform_data/b53.h
+++ b/include/linux/platform_data/b53.h
@@ -25,6 +25,9 @@ struct b53_platform_data {
u32 chip_id;
u16 enabled_ports;
+ /* allow to specify an ethX alias */
+ const char *alias;
+
/* only used by MMAP'd driver */
unsigned big_endian:1;
void __iomem *regs;

View File

@ -0,0 +1,83 @@
From c942c462411e4757aafba73bf13b5e5c7a4b62ca Mon Sep 17 00:00:00 2001
From: Christian Lamparter <chunkeey@gmail.com>
Date: Sun, 23 Dec 2018 00:38:55 +0100
Subject: [PATCH] mtd: rawnand: qcom: fix memory corruption that causes panic
This patch fixes a memory corruption that occured in the
qcom-nandc driver since it was converted to nand_scan().
On boot, an affected device will panic from a NPE at a weird place:
| Unable to handle kernel NULL pointer dereference at virtual address 00000000
| pgd = (ptrval)
| [00000000] *pgd=00000000
| Internal error: Oops: 80000005 [#1] SMP ARM
| CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.19.9 #0
| Hardware name: Generic DT based system
| PC is at (null)
| LR is at nand_block_isbad+0x90/0xa4
| pc : [<00000000>] lr : [<c0592240>] psr: 80000013
| sp : cf839d40 ip : 00000000 fp : cfae9e20
| r10: cf815810 r9 : 00000000 r8 : 00000000
| r7 : 00000000 r6 : 00000000 r5 : 00000001 r4 : cf815810
| r3 : 00000000 r2 : cfae9810 r1 : ffffffff r0 : cf815810
| Flags: Nzcv IRQs on FIQs on Mode SVC_32 ISA ARM Segment none
| Control: 10c5387d Table: 8020406a DAC: 00000051
| Process swapper/0 (pid: 1, stack limit = 0x(ptrval))
| [<c0592240>] (nand_block_isbad) from [<c0580a94>] (allocate_partition+0x7a0/0x7dc)
| [<c0580a94>] (allocate_partition) from [<c05811e4>] (add_mtd_partitions+0x58/0x10c)
| [<c05811e4>] (add_mtd_partitions) from [<c0581164>] (parse_mtd_partitions+0x310/0x338)
| [<c0581164>] (parse_mtd_partitions) from [<c057def4>] (mtd_device_parse_register+0x60/0x15c)
| [<c057def4>] (mtd_device_parse_register) from [<c059d274>] (qcom_nandc_probe+0x770/0x8f4)
| [<c059d274>] (qcom_nandc_probe) from [<c0567f00>] (platform_drv_probe+0x34/0x70)
The problem is that the nand_scan()'s qcom_nand_attach_chip callback
is updating the nandc->max_cwperpage from 1 to 4. This causes the
sg_init_table of clear_bam_transaction() in the driver's
qcom_nandc_block_bad() to memset much more than what was initially
allocated by alloc_bam_transaction().
Hence, this patch restores the old behavior by performing the
alloc_bam_transaction() after the chip was identified.
Fixes: 6a3cec64f18c ("mtd: rawnand: qcom: convert driver to nand_scan()")
Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
---
drivers/mtd/nand/raw/qcom_nandc.c | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
--- a/drivers/mtd/nand/raw/qcom_nandc.c
+++ b/drivers/mtd/nand/raw/qcom_nandc.c
@@ -2839,6 +2839,16 @@ static int qcom_nand_host_init_and_regis
if (ret)
return ret;
+ if (nandc->props->is_bam) {
+ free_bam_transaction(nandc);
+ nandc->bam_txn = alloc_bam_transaction(nandc);
+ if (!nandc->bam_txn) {
+ dev_err(nandc->dev,
+ "failed to allocate bam transaction\n");
+ return -ENOMEM;
+ }
+ }
+
ret = mtd_device_register(mtd, NULL, 0);
if (ret)
nand_cleanup(chip);
@@ -2853,16 +2863,6 @@ static int qcom_probe_nand_devices(struc
struct qcom_nand_host *host;
int ret;
- if (nandc->props->is_bam) {
- free_bam_transaction(nandc);
- nandc->bam_txn = alloc_bam_transaction(nandc);
- if (!nandc->bam_txn) {
- dev_err(nandc->dev,
- "failed to allocate bam transaction\n");
- return -ENOMEM;
- }
- }
-
for_each_available_child_of_node(dn, child) {
host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL);
if (!host) {

View File

@ -0,0 +1,84 @@
From 38a3549ffc0033761063cc5c7b994ab075694db8 Mon Sep 17 00:00:00 2001
From: Christian Lamparter <chunkeey@gmail.com>
Date: Tue, 25 Dec 2018 21:11:08 +0100
Subject: [RFC PATCH] leds: fix regression in usbport led trigger
In the patch "usb: simplify usbport trigger" together with
"leds: triggers: add device attribute support" caused an
regression for the usbport trigger. it will no longer
enumerate any "ports" (i.e the sysfs directory stays empty)
if the usb host drivers are fully initialized before the
usbport trigger was loaded.
The reason is that the usbport driver registers the sysfs
entries in the ports subdirectory during the activate()
callback. Whereas the patch
"leds: triggers: add device attribute support" made it so
that the sysfs "ports" group was only being added after
the activate() callback succeeded.
This patch moves the device_add_groups() in front of the
call to the trigger's activate() function in order to
solve the problem.
Fixes: 6f7b0bad8839 ("usb: simplify usbport trigger")
Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
---
drivers/leds/led-triggers.c | 19 ++++++++++---------
1 file changed, 10 insertions(+), 9 deletions(-)
diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c
index 17d73db1456e..08e7c724a9dc 100644
--- a/drivers/leds/led-triggers.c
+++ b/drivers/leds/led-triggers.c
@@ -134,6 +134,12 @@ int led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig)
led_set_brightness(led_cdev, LED_OFF);
}
if (trig) {
+ ret = device_add_groups(led_cdev->dev, trig->groups);
+ if (ret) {
+ dev_err(led_cdev->dev, "Failed to add trigger attributes\n");
+ goto err_add_groups;
+ }
+
write_lock_irqsave(&trig->leddev_list_lock, flags);
list_add_tail(&led_cdev->trig_list, &trig->led_cdevs);
write_unlock_irqrestore(&trig->leddev_list_lock, flags);
@@ -146,12 +152,6 @@ int led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig)
if (ret)
goto err_activate;
-
- ret = device_add_groups(led_cdev->dev, trig->groups);
- if (ret) {
- dev_err(led_cdev->dev, "Failed to add trigger attributes\n");
- goto err_add_groups;
- }
}
if (event) {
@@ -165,17 +165,18 @@ int led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig)
return 0;
-err_add_groups:
-
+err_activate:
+ device_remove_groups(led_cdev->dev, trig->groups);
if (trig->deactivate)
trig->deactivate(led_cdev);
-err_activate:
led_cdev->trigger = NULL;
led_cdev->trigger_data = NULL;
write_lock_irqsave(&led_cdev->trigger->leddev_list_lock, flags);
list_del(&led_cdev->trig_list);
write_unlock_irqrestore(&led_cdev->trigger->leddev_list_lock, flags);
+
+err_add_groups:
led_set_brightness(led_cdev, LED_OFF);
return ret;
--
2.20.1

View File

@ -136,3 +136,15 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
header-y += synclink.h
header-y += sync_file.h
header-y += sysctl.h
--- a/include/linux/platform_data/b53.h
+++ b/include/linux/platform_data/b53.h
@@ -25,6 +25,9 @@ struct b53_platform_data {
u32 chip_id;
u16 enabled_ports;
+ /* allow to specify an ethX alias */
+ const char *alias;
+
/* only used by MMAP'd driver */
unsigned big_endian:1;
void __iomem *regs;

View File

@ -19,3 +19,42 @@
obj-$(CONFIG_FIXED_PHY) += fixed.o
obj-$(CONFIG_MDIO_BITBANG) += mdio-bitbang.o
obj-$(CONFIG_MDIO_GPIO) += mdio-gpio.o
--- /dev/null
+++ b/linux/platform_data/b53.h
@@ -0,0 +1,36 @@
+/*
+ * B53 platform data
+ *
+ * Copyright (C) 2013 Jonas Gorski <jogo@openwrt.org>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __B53_H
+#define __B53_H
+
+#include <linux/kernel.h>
+
+struct b53_platform_data {
+ u32 chip_id;
+ u16 enabled_ports;
+
+ /* allow to specify an ethX alias */
+ const char *alias;
+
+ /* only used by MMAP'd driver */
+ unsigned big_endian:1;
+ void __iomem *regs;
+};
+
+#endif

View File

@ -1,21 +0,0 @@
--- a/drivers/leds/trigger/Kconfig
+++ b/drivers/leds/trigger/Kconfig
@@ -108,4 +108,11 @@ config LEDS_TRIGGER_CAMERA
This enables direct flash/torch on/off by the driver, kernel space.
If unsure, say Y.
+config LEDS_TRIGGER_NETDEV
+ tristate "LED Netdev Trigger"
+ depends on NET && LEDS_TRIGGERS
+ help
+ This allows LEDs to be controlled by network device activity.
+ If unsure, say Y.
+
endif # LEDS_TRIGGERS
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -62,3 +62,4 @@ obj-$(CONFIG_LEDS_DAC124S085) += leds-d
# LED Triggers
obj-$(CONFIG_LEDS_TRIGGERS) += trigger/
+obj-$(CONFIG_LEDS_TRIGGER_NETDEV) += ledtrig-netdev.o

View File

@ -0,0 +1,51 @@
From: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
To: linux-f2fs-devel@lists.sourceforge.net, yuchao0@huawei.com,
jaegeuk@kernel.org
Subject: [PATCH v2 1/1] f2fs: fix validation of the block count in
sanity_check_raw_super
Date: Sat, 22 Dec 2018 11:22:26 +0100
Message-Id: <20181222102226.10050-2-martin.blumenstingl@googlemail.com>
Treat "block_count" from struct f2fs_super_block as 64-bit little endian
value in sanity_check_raw_super() because struct f2fs_super_block
declares "block_count" as "__le64".
This fixes a bug where the superblock validation fails on big endian
devices with the following error:
F2FS-fs (sda1): Wrong segment_count / block_count (61439 > 0)
F2FS-fs (sda1): Can't find valid F2FS filesystem in 1th superblock
F2FS-fs (sda1): Wrong segment_count / block_count (61439 > 0)
F2FS-fs (sda1): Can't find valid F2FS filesystem in 2th superblock
As result of this the partition cannot be mounted.
With this patch applied the superblock validation works fine and the
partition can be mounted again:
F2FS-fs (sda1): Mounted with checkpoint version = 7c84
My little endian x86-64 hardware was able to mount the partition without
this fix.
To confirm that mounting f2fs filesystems works on big endian machines
again I tested this on a 32-bit MIPS big endian (lantiq) device.
Fixes: 0cfe75c5b01199 ("f2fs: enhance sanity_check_raw_super() to avoid potential overflows")
Cc: stable@vger.kernel.org
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
Reviewed-by: Chao Yu <yuchao0@huawei.com>
---
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -1897,10 +1897,10 @@ static int sanity_check_raw_super(struct
return 1;
}
- if (segment_count > (le32_to_cpu(raw_super->block_count) >> 9)) {
+ if (segment_count > (le64_to_cpu(raw_super->block_count) >> 9)) {
f2fs_msg(sb, KERN_INFO,
- "Wrong segment_count / block_count (%u > %u)",
- segment_count, le32_to_cpu(raw_super->block_count));
+ "Wrong segment_count / block_count (%u > %llu)",
+ segment_count, le64_to_cpu(raw_super->block_count));
return 1;
}

View File

@ -1,30 +0,0 @@
From: Felix Fietkau <nbd@nbd.name>
Subject: MIPS: fix cache flushing for highmem pages
Most cache flush ops were no-op for highmem pages. This led to nasty
segfaults and (in the case of page_address(page) == NULL) kernel
crashes.
Fix this by always flushing highmem pages using kmap/kunmap_atomic
around the actual cache flush. This might be a bit inefficient, but at
least it's stable.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/arch/mips/mm/cache.c
+++ b/arch/mips/mm/cache.c
@@ -116,6 +116,13 @@ void __flush_anon_page(struct page *page
{
unsigned long addr = (unsigned long) page_address(page);
+ if (PageHighMem(page)) {
+ addr = (unsigned long)kmap_atomic(page);
+ flush_data_cache_page(addr);
+ __kunmap_atomic((void *)addr);
+ return;
+ }
+
if (pages_do_alias(addr, vmaddr)) {
if (page_mapcount(page) && !Page_dcache_dirty(page)) {
void *kaddr;

View File

@ -0,0 +1,49 @@
From: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
Subject: [PATCH v2 1/1] f2fs: fix validation of the block count in
sanity_check_raw_super
Date: Sat, 22 Dec 2018 11:22:26 +0100
Message-Id: <20181222102226.10050-2-martin.blumenstingl@googlemail.com>
Treat "block_count" from struct f2fs_super_block as 64-bit little endian
value in sanity_check_raw_super() because struct f2fs_super_block
declares "block_count" as "__le64".
This fixes a bug where the superblock validation fails on big endian
devices with the following error:
F2FS-fs (sda1): Wrong segment_count / block_count (61439 > 0)
F2FS-fs (sda1): Can't find valid F2FS filesystem in 1th superblock
F2FS-fs (sda1): Wrong segment_count / block_count (61439 > 0)
F2FS-fs (sda1): Can't find valid F2FS filesystem in 2th superblock
As result of this the partition cannot be mounted.
With this patch applied the superblock validation works fine and the
partition can be mounted again:
F2FS-fs (sda1): Mounted with checkpoint version = 7c84
My little endian x86-64 hardware was able to mount the partition without
this fix.
To confirm that mounting f2fs filesystems works on big endian machines
again I tested this on a 32-bit MIPS big endian (lantiq) device.
Fixes: 0cfe75c5b01199 ("f2fs: enhance sanity_check_raw_super() to avoid potential overflows")
Cc: stable@vger.kernel.org
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
Reviewed-by: Chao Yu <yuchao0@huawei.com>
---
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -2267,10 +2267,10 @@ static int sanity_check_raw_super(struct
return 1;
}
- if (segment_count > (le32_to_cpu(raw_super->block_count) >> 9)) {
+ if (segment_count > (le64_to_cpu(raw_super->block_count) >> 9)) {
f2fs_msg(sb, KERN_INFO,
- "Wrong segment_count / block_count (%u > %u)",
- segment_count, le32_to_cpu(raw_super->block_count));
+ "Wrong segment_count / block_count (%u > %llu)",
+ segment_count, le64_to_cpu(raw_super->block_count));
return 1;
}

View File

@ -68,7 +68,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
mtd_add_partition_attrs(new);
@@ -728,6 +733,35 @@ int mtd_del_partition(struct mtd_info *m
@@ -728,6 +733,29 @@ int mtd_del_partition(struct mtd_info *m
}
EXPORT_SYMBOL_GPL(mtd_del_partition);
@ -82,11 +82,6 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
+{
+}
+
+void __weak arch_split_mtd_part(struct mtd_info *master, const char *name,
+ int offset, int size)
+{
+}
+
+static void mtd_partition_split(struct mtd_info *master, struct mtd_part *part)
+{
+ static int rootfs_found = 0;
@ -94,17 +89,16 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
+ if (rootfs_found)
+ return;
+
+ if (!strcmp(part->mtd.name, SPLIT_FIRMWARE_NAME) &&
+ IS_ENABLED(CONFIG_MTD_SPLIT_FIRMWARE))
+ if (IS_ENABLED(CONFIG_MTD_SPLIT_FIRMWARE) &&
+ !strcmp(part->mtd.name, SPLIT_FIRMWARE_NAME) &&
+ !of_find_property(mtd_get_of_node(&part->mtd), "compatible", NULL))
+ split_firmware(master, part);
+
+ arch_split_mtd_part(master, part->mtd.name, part->offset,
+ part->mtd.size);
+}
+
/*
* This function, given a master MTD object and a partition table, creates
* and registers slave MTD objects which are bound to the master according to
@@ -759,6 +793,7 @@ int add_mtd_partitions(struct mtd_info *
@@ -759,6 +787,7 @@ int add_mtd_partitions(struct mtd_info *
mutex_unlock(&mtd_partitions_mutex);
add_mtd_device(&slave->mtd);
@ -112,13 +106,3 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
mtd_add_partition_attrs(slave);
/* Look for subpartitions */
parse_mtd_partitions(&slave->mtd, parts[i].types, NULL);
--- a/include/linux/mtd/partitions.h
+++ b/include/linux/mtd/partitions.h
@@ -110,5 +110,7 @@ int mtd_add_partition(struct mtd_info *m
long long offset, long long length);
int mtd_del_partition(struct mtd_info *master, int partno);
uint64_t mtd_get_device_size(const struct mtd_info *mtd);
+extern void __weak arch_split_mtd_part(struct mtd_info *master,
+ const char *name, int offset, int size);
#endif

View File

@ -57,7 +57,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
#ifdef CONFIG_MTD_SPLIT_FIRMWARE_NAME
#define SPLIT_FIRMWARE_NAME CONFIG_MTD_SPLIT_FIRMWARE_NAME
#else
@@ -1115,6 +1149,61 @@ void mtd_part_parser_cleanup(struct mtd_
@@ -1109,6 +1143,61 @@ void mtd_part_parser_cleanup(struct mtd_
}
}

View File

@ -17,8 +17,8 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+ run_parsers_by_type(part, MTD_PARSER_TYPE_FIRMWARE);
}
void __weak arch_split_mtd_part(struct mtd_info *master, const char *name,
@@ -789,6 +790,12 @@ static void mtd_partition_split(struct m
static void mtd_partition_split(struct mtd_info *master, struct mtd_part *part)
@@ -784,6 +785,12 @@ static void mtd_partition_split(struct m
if (rootfs_found)
return;
@ -28,9 +28,9 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+ rootfs_found = 1;
+ }
+
if (!strcmp(part->mtd.name, SPLIT_FIRMWARE_NAME) &&
IS_ENABLED(CONFIG_MTD_SPLIT_FIRMWARE))
split_firmware(master, part);
if (IS_ENABLED(CONFIG_MTD_SPLIT_FIRMWARE) &&
!strcmp(part->mtd.name, SPLIT_FIRMWARE_NAME) &&
!of_find_property(mtd_get_of_node(&part->mtd), "compatible", NULL))
--- a/include/linux/mtd/partitions.h
+++ b/include/linux/mtd/partitions.h
@@ -75,6 +75,8 @@ struct mtd_part_parser_data {

View File

@ -11,7 +11,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -1228,6 +1228,24 @@ int mtd_is_partition(const struct mtd_in
@@ -1222,6 +1222,24 @@ int mtd_is_partition(const struct mtd_in
}
EXPORT_SYMBOL_GPL(mtd_is_partition);
@ -72,5 +72,5 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+struct mtd_info *mtdpart_get_master(const struct mtd_info *mtd);
+uint64_t mtdpart_get_offset(const struct mtd_info *mtd);
uint64_t mtd_get_device_size(const struct mtd_info *mtd);
extern void __weak arch_split_mtd_part(struct mtd_info *master,
const char *name, int offset, int size);
#endif

View File

@ -1,74 +0,0 @@
From: Alexey Brodkin <abrodkin@synopsys.com>
Subject: usb: Remove annoying warning about bogus URB
When ath9k-htc Wi-Fi dongle is used with generic OHCI controller
infinite stream of warnings appears in debug console like this:
-------------------------->8----------------------
usb 1-1: new full-speed USB device number 2 using ohci-platform
usb 1-1: ath9k_htc: Firmware ath9k_htc/htc_9271-1.4.0.fw requested
usb 1-1: ath9k_htc: Transferred FW: ath9k_htc/htc_9271-1.4.0.fw, size:
51008
------------[ cut here ]------------
WARNING: CPU: 0 PID: 19 at drivers/usb/core/urb.c:449
usb_submit_urb+0x1b4/0x498()
usb 1-1: BOGUS urb xfer, pipe 1 != type 3
Modules linked in:
CPU: 0 PID: 19 Comm: kworker/0:1 Not tainted
4.4.0-rc4-00017-g00e2d79-dirty #3
Workqueue: events request_firmware_work_func
Stack Trace:
arc_unwind_core.constprop.1+0xa4/0x110
---[ end trace 649ef8c342817fc2 ]---
------------[ cut here ]------------
WARNING: CPU: 0 PID: 19 at drivers/usb/core/urb.c:449
usb_submit_urb+0x1b4/0x498()
usb 1-1: BOGUS urb xfer, pipe 1 != type 3
Modules linked in:
CPU: 0 PID: 19 Comm: kworker/0:1 Tainted: G W
4.4.0-rc4-00017-g00e2d79-dirty #3
Workqueue: events request_firmware_work_func
Stack Trace:
arc_unwind_core.constprop.1+0xa4/0x110
---[ end trace 649ef8c342817fc3 ]---
------------[ cut here ]------------
-------------------------->8----------------------
There're some discussions in mailing lists proposing to disable
that particular check alltogether and magically all seem to work
fine with muted warning.
Anyways new thread on that regard could be found here:
http://lists.infradead.org/pipermail/linux-snps-arc/2016-July/001310.html
Let's see what comes out of that new discussion, hopefully patching
of generic USB stuff won't be required then.
Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
---
drivers/leds/Makefile | 1 +
drivers/leds/trigger/Kconfig | 7 +++++++
2 files changed, 8 insertions(+)
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -77,3 +77,4 @@ obj-$(CONFIG_LEDS_DAC124S085) += leds-d
# LED Triggers
obj-$(CONFIG_LEDS_TRIGGERS) += trigger/
+obj-$(CONFIG_LEDS_TRIGGER_NETDEV) += ledtrig-netdev.o
--- a/drivers/leds/trigger/Kconfig
+++ b/drivers/leds/trigger/Kconfig
@@ -126,4 +126,11 @@ config LEDS_TRIGGER_PANIC
a different trigger.
If unsure, say Y.
+config LEDS_TRIGGER_NETDEV
+ tristate "LED Netdev Trigger"
+ depends on NET && LEDS_TRIGGERS
+ help
+ This allows LEDs to be controlled by network device activity.
+ If unsure, say Y.
+
endif # LEDS_TRIGGERS

View File

@ -384,7 +384,6 @@ CONFIG_NVRAM=y
CONFIG_OLD_SIGACTION=y
CONFIG_OLD_SIGSUSPEND3=y
CONFIG_OPROFILE_NMI_TIMER=y
# CONFIG_OPTIMIZE_INLINING is not set
CONFIG_OUTPUT_FORMAT="elf32-i386"
CONFIG_PADATA=y
CONFIG_PAGE_OFFSET=0xC0000000
@ -446,6 +445,7 @@ CONFIG_SATA_AHCI_PLATFORM=y
CONFIG_SATA_MV=y
CONFIG_SATA_NV=y
CONFIG_SATA_VIA=y
# CONFIG_SATA_ZPODD is not set
# CONFIG_SBC7240_WDT is not set
# CONFIG_SBC8360_WDT is not set
# CONFIG_SBC_EPX_C3_WATCHDOG is not set
@ -593,4 +593,3 @@ CONFIG_XPS=y
CONFIG_XZ_DEC_BCJ=y
CONFIG_XZ_DEC_X86=y
CONFIG_ZLIB_INFLATE=y
# CONFIG_SATA_ZPODD is not set