Patches contributed by University of Waterloo
commit 9e76a7ac87c13bb7515e5d7652bbb6bda4733b6e
Author: Sarah Nadi <snadi@uwaterloo.ca>
Date: Tue May 17 10:38:43 2011 -0400
cris: typo in mach-fs Makefile
Signed-off-by: Sarah Nadi <snadi@uwaterloo.ca>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
diff --git a/arch/cris/arch-v32/mach-fs/Makefile b/arch/cris/arch-v32/mach-fs/Makefile
index 4ff407a1b931..41fa6a6893a9 100644
--- a/arch/cris/arch-v32/mach-fs/Makefile
+++ b/arch/cris/arch-v32/mach-fs/Makefile
@@ -4,7 +4,7 @@
#
obj-y := dma.o pinmux.o io.o arbiter.o
-bj-$(CONFIG_ETRAX_VCS_SIM) += vcs_hook.o
+obj-$(CONFIG_ETRAX_VCS_SIM) += vcs_hook.o
obj-$(CONFIG_CPU_FREQ) += cpufreq.o
clean:
commit 8c1a1158c98b810d34b469c787840ac16904e5fa
Author: Kyle Spaans <kspaans@uwaterloo.ca>
Date: Tue Jun 8 09:48:22 2010 -0400
mtd: remove redundant dependency checks in Kconfig files
Look for dependency checks for "FOO" when inside of an "if FOO" block and remove them.
Signed-off-by: Kyle Spaans <kspaans@uwaterloo.ca>
Reviewed-by: Robert P. J. Day <rpjday@crashcourse.ca>
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index f8210bf2d241..71eda03b925f 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -319,7 +319,6 @@ config SM_FTL
config MTD_OOPS
tristate "Log panic/oops to an MTD buffer"
- depends on MTD
help
This enables panic and oops messages to be logged to a circular
buffer in a flash partition where it can be read back at some
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index ffc3720929f1..4d4066f315be 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -37,7 +37,6 @@ config MTD_SM_COMMON
config MTD_NAND_MUSEUM_IDS
bool "Enable chip ids for obsolete ancient NAND devices"
- depends on MTD_NAND
default n
help
Enable this option only when your board has first generation
@@ -101,13 +100,13 @@ config MTD_NAND_AMS_DELTA
config MTD_NAND_OMAP2
tristate "NAND Flash device on OMAP2 and OMAP3"
- depends on ARM && MTD_NAND && (ARCH_OMAP2 || ARCH_OMAP3)
+ depends on ARM && (ARCH_OMAP2 || ARCH_OMAP3)
help
Support for NAND flash on Texas Instruments OMAP2 and OMAP3 platforms.
config MTD_NAND_OMAP_PREFETCH
bool "GPMC prefetch support for NAND Flash device"
- depends on MTD_NAND && MTD_NAND_OMAP2
+ depends on MTD_NAND_OMAP2
default y
help
The NAND device can be accessed for Read/Write using GPMC PREFETCH engine
@@ -146,7 +145,7 @@ config MTD_NAND_AU1550
config MTD_NAND_BF5XX
tristate "Blackfin on-chip NAND Flash Controller driver"
- depends on (BF54x || BF52x) && MTD_NAND
+ depends on BF54x || BF52x
help
This enables the Blackfin on-chip NAND flash controller
@@ -236,7 +235,7 @@ config MTD_NAND_S3C2410_CLKSTOP
config MTD_NAND_BCM_UMI
tristate "NAND Flash support for BCM Reference Boards"
- depends on ARCH_BCMRING && MTD_NAND
+ depends on ARCH_BCMRING
help
This enables the NAND flash controller on the BCM UMI block.
@@ -395,7 +394,7 @@ endchoice
config MTD_NAND_PXA3xx
tristate "Support for NAND flash devices on PXA3xx"
- depends on MTD_NAND && (PXA3xx || ARCH_MMP)
+ depends on PXA3xx || ARCH_MMP
help
This enables the driver for the NAND flash device found on
PXA3xx processors
@@ -409,18 +408,18 @@ config MTD_NAND_PXA3xx_BUILTIN
config MTD_NAND_CM_X270
tristate "Support for NAND Flash on CM-X270 modules"
- depends on MTD_NAND && MACH_ARMCORE
+ depends on MACH_ARMCORE
config MTD_NAND_PASEMI
tristate "NAND support for PA Semi PWRficient"
- depends on MTD_NAND && PPC_PASEMI
+ depends on PPC_PASEMI
help
Enables support for NAND Flash interface on PA Semi PWRficient
based boards
config MTD_NAND_TMIO
tristate "NAND Flash device on Toshiba Mobile IO Controller"
- depends on MTD_NAND && MFD_TMIO
+ depends on MFD_TMIO
help
Support for NAND flash connected to a Toshiba Mobile IO
Controller in some PDAs, including the Sharp SL6000x.
@@ -434,7 +433,6 @@ config MTD_NAND_NANDSIM
config MTD_NAND_PLATFORM
tristate "Support for generic platform NAND driver"
- depends on MTD_NAND
help
This implements a generic NAND driver for on-SOC platform
devices. You will need to provide platform-specific functions
@@ -442,14 +440,14 @@ config MTD_NAND_PLATFORM
config MTD_ALAUDA
tristate "MTD driver for Olympus MAUSB-10 and Fujifilm DPC-R1"
- depends on MTD_NAND && USB
+ depends on USB
help
These two (and possibly other) Alauda-based cardreaders for
SmartMedia and xD allow raw flash access.
config MTD_NAND_ORION
tristate "NAND Flash support for Marvell Orion SoC"
- depends on PLAT_ORION && MTD_NAND
+ depends on PLAT_ORION
help
This enables the NAND flash controller on Orion machines.
@@ -458,7 +456,7 @@ config MTD_NAND_ORION
config MTD_NAND_FSL_ELBC
tristate "NAND support for Freescale eLBC controllers"
- depends on MTD_NAND && PPC_OF
+ depends on PPC_OF
help
Various Freescale chips, including the 8313, include a NAND Flash
Controller Module with built-in hardware ECC capabilities.
@@ -467,7 +465,7 @@ config MTD_NAND_FSL_ELBC
config MTD_NAND_FSL_UPM
tristate "Support for NAND on Freescale UPM"
- depends on MTD_NAND && (PPC_83xx || PPC_85xx)
+ depends on PPC_83xx || PPC_85xx
select FSL_LBC
help
Enables support for NAND Flash chips wired onto Freescale PowerPC
@@ -495,7 +493,7 @@ config MTD_NAND_NOMADIK
config MTD_NAND_SH_FLCTL
tristate "Support for NAND on Renesas SuperH FLCTL"
- depends on MTD_NAND && (SUPERH || ARCH_SHMOBILE)
+ depends on SUPERH || ARCH_SHMOBILE
help
Several Renesas SuperH CPU has FLCTL. This option enables support
for NAND Flash using FLCTL.
@@ -515,7 +513,7 @@ config MTD_NAND_TXX9NDFMC
config MTD_NAND_SOCRATES
tristate "Support for NAND on Socrates board"
- depends on MTD_NAND && SOCRATES
+ depends on SOCRATES
help
Enables support for NAND Flash chips wired onto Socrates board.
diff --git a/drivers/mtd/onenand/Kconfig b/drivers/mtd/onenand/Kconfig
index 9a49d68ba5f9..3f32289fdbb5 100644
--- a/drivers/mtd/onenand/Kconfig
+++ b/drivers/mtd/onenand/Kconfig
@@ -25,14 +25,14 @@ config MTD_ONENAND_GENERIC
config MTD_ONENAND_OMAP2
tristate "OneNAND on OMAP2/OMAP3 support"
- depends on MTD_ONENAND && (ARCH_OMAP2 || ARCH_OMAP3)
+ depends on ARCH_OMAP2 || ARCH_OMAP3
help
Support for a OneNAND flash device connected to an OMAP2/OMAP3 CPU
via the GPMC memory controller.
config MTD_ONENAND_SAMSUNG
tristate "OneNAND on Samsung SOC controller support"
- depends on MTD_ONENAND && (ARCH_S3C64XX || ARCH_S5PC100 || ARCH_S5PV210)
+ depends on ARCH_S3C64XX || ARCH_S5PC100 || ARCH_S5PV210
help
Support for a OneNAND flash device connected to an Samsung SOC
S3C64XX/S5PC1XX controller.
commit dd21731022faf43c1250050e5d28d11add599149
Author: Lennart Sorensen <lsorense@csclub.uwaterloo.ca>
Date: Thu May 5 16:44:44 2016 -0400
powerpc/sstep: Fix sstep.c compile on powerpcspe
Commit be96f63375a1 ("powerpc: Split out instruction analysis part of
emulate_step()") introduced ldarx and stdcx into the instructions in
sstep.c, which are not accepted by the assembler on powerpcspe, but does
seem to be accepted by the normal powerpc assembler even in 32 bit mode.
Wrap these two instructions in a __powerpc64__ check like it is
everywhere else in the file.
Fixes: be96f63375a1 ("powerpc: Split out instruction analysis part of emulate_step()")
Signed-off-by: Len Sorensen <lsorense@csclub.uwaterloo.ca>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
index dc885b30f7a6..6d34310f1141 100644
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -1818,9 +1818,11 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
case 4:
__get_user_asmx(val, op.ea, err, "lwarx");
break;
+#ifdef __powerpc64__
case 8:
__get_user_asmx(val, op.ea, err, "ldarx");
break;
+#endif
default:
return 0;
}
@@ -1841,9 +1843,11 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
case 4:
__put_user_asmx(op.val, op.ea, err, "stwcx.", cr);
break;
+#ifdef __powerpc64__
case 8:
__put_user_asmx(op.val, op.ea, err, "stdcx.", cr);
break;
+#endif
default:
return 0;
}
commit a6f0331236fa75afba14bbcf6668d42cebb55c43
Author: Lennart Sorensen <lsorense@csclub.uwaterloo.ca>
Date: Wed Jan 21 15:24:27 2015 -0500
USB: cp210x: add ID for RUGGEDCOM USB Serial Console
Added the USB serial console device ID for Siemens Ruggedcom devices
which have a USB port for their serial console.
Signed-off-by: Len Sorensen <lsorense@csclub.uwaterloo.ca>
Cc: stable <stable@vger.kernel.org>
Signed-off-by: Johan Hovold <johan@kernel.org>
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index f4c56fc1a9f6..f40c856ff758 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -56,6 +56,7 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x0846, 0x1100) }, /* NetGear Managed Switch M4100 series, M5300 series, M7100 series */
{ USB_DEVICE(0x08e6, 0x5501) }, /* Gemalto Prox-PU/CU contactless smartcard reader */
{ USB_DEVICE(0x08FD, 0x000A) }, /* Digianswer A/S , ZigBee/802.15.4 MAC Device */
+ { USB_DEVICE(0x0908, 0x01FF) }, /* Siemens RUGGEDCOM USB Serial Console */
{ USB_DEVICE(0x0BED, 0x1100) }, /* MEI (TM) Cashflow-SC Bill/Voucher Acceptor */
{ USB_DEVICE(0x0BED, 0x1101) }, /* MEI series 2000 Combo Acceptor */
{ USB_DEVICE(0x0FCF, 0x1003) }, /* Dynastream ANT development board */
commit 999f934de195a1506089b52c77429fdba25da688
Author: Lennart Sorensen <lsorense@csclub.uwaterloo.ca>
Date: Mon Jan 5 15:45:45 2015 -0800
ARM: omap5/dra7xx: Enable booting secondary CPU in HYP mode
If the boot loader enables HYP mode on the boot CPU, the secondary CPU
also needs to call into the ROM to switch to HYP mode before booting.
The firmwares on the omap5 and dra7xx unfortunately do not take care
of this, so it has to be handled by the kernel.
This patch is based on "[PATCH 2/2] ARM: OMAP5: Add HYP mode entry support
for secondary CPUs" by Santosh Shilimkar <santosh.shilimkar@ti.com>,
except this version does not require a compile time CONFIG to control
if it should enable HYP mode or not, it simply does it based on the mode
of the boot CPU, so it works whether the CPU boots in SVC or HYP mode,
and should even work as a guest kernel inside kvm if qemu decides to
support emulating the omap5 or dra7xx.
Cc: stable@vger.kernel.org #v3.16+
Signed-off-by: Len Sorensen <lsorense@csclub.uwaterloo.ca>
Signed-off-by: Tony Lindgren <tony@atomide.com>
diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h
index 377eea849e7b..db57741c9c8a 100644
--- a/arch/arm/mach-omap2/common.h
+++ b/arch/arm/mach-omap2/common.h
@@ -249,6 +249,7 @@ extern void omap4_cpu_die(unsigned int cpu);
extern struct smp_operations omap4_smp_ops;
extern void omap5_secondary_startup(void);
+extern void omap5_secondary_hyp_startup(void);
#endif
#if defined(CONFIG_SMP) && defined(CONFIG_PM)
diff --git a/arch/arm/mach-omap2/omap-headsmp.S b/arch/arm/mach-omap2/omap-headsmp.S
index 4993d4bfe9b2..6d1dffca6c7b 100644
--- a/arch/arm/mach-omap2/omap-headsmp.S
+++ b/arch/arm/mach-omap2/omap-headsmp.S
@@ -22,6 +22,7 @@
/* Physical address needed since MMU not enabled yet on secondary core */
#define AUX_CORE_BOOT0_PA 0x48281800
+#define API_HYP_ENTRY 0x102
/*
* OMAP5 specific entry point for secondary CPU to jump from ROM
@@ -40,6 +41,26 @@ wait: ldr r2, =AUX_CORE_BOOT0_PA @ read from AuxCoreBoot0
bne wait
b secondary_startup
ENDPROC(omap5_secondary_startup)
+/*
+ * Same as omap5_secondary_startup except we call into the ROM to
+ * enable HYP mode first. This is called instead of
+ * omap5_secondary_startup if the primary CPU was put into HYP mode by
+ * the boot loader.
+ */
+ENTRY(omap5_secondary_hyp_startup)
+wait_2: ldr r2, =AUX_CORE_BOOT0_PA @ read from AuxCoreBoot0
+ ldr r0, [r2]
+ mov r0, r0, lsr #5
+ mrc p15, 0, r4, c0, c0, 5
+ and r4, r4, #0x0f
+ cmp r0, r4
+ bne wait_2
+ ldr r12, =API_HYP_ENTRY
+ adr r0, hyp_boot
+ smc #0
+hyp_boot:
+ b secondary_startup
+ENDPROC(omap5_secondary_hyp_startup)
/*
* OMAP4 specific entry point for secondary CPU to jump from ROM
* code. This routine also provides a holding flag into which
diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c
index 256e84ef0f67..5305ec7341ec 100644
--- a/arch/arm/mach-omap2/omap-smp.c
+++ b/arch/arm/mach-omap2/omap-smp.c
@@ -22,6 +22,7 @@
#include <linux/irqchip/arm-gic.h>
#include <asm/smp_scu.h>
+#include <asm/virt.h>
#include "omap-secure.h"
#include "omap-wakeupgen.h"
@@ -227,8 +228,16 @@ static void __init omap4_smp_prepare_cpus(unsigned int max_cpus)
if (omap_secure_apis_support())
omap_auxcoreboot_addr(virt_to_phys(startup_addr));
else
- writel_relaxed(virt_to_phys(omap5_secondary_startup),
- base + OMAP_AUX_CORE_BOOT_1);
+ /*
+ * If the boot CPU is in HYP mode then start secondary
+ * CPU in HYP mode as well.
+ */
+ if ((__boot_cpu_mode & MODE_MASK) == HYP_MODE)
+ writel_relaxed(virt_to_phys(omap5_secondary_hyp_startup),
+ base + OMAP_AUX_CORE_BOOT_1);
+ else
+ writel_relaxed(virt_to_phys(omap5_secondary_startup),
+ base + OMAP_AUX_CORE_BOOT_1);
}
commit afc9d590b8a150cfeaac0078ef5de6fb21a5ea6a
Author: Lennart Sorensen <lsorense@csclub.uwaterloo.ca>
Date: Mon Jan 5 15:45:45 2015 -0800
ARM: dra7xx: Fix counter frequency drift for AM572x errata i856
Errata i856 for the AM572x (DRA7xx) points out that the 32.768KHz external
crystal is not enabled at power up. Instead the CPU falls back to using
an emulation for the 32KHz clock which is SYSCLK1/610. SYSCLK1 is usually
20MHz on boards so far (which gives an emulated frequency of 32.786KHz),
but can also be 19.2 or 27MHz which result in much larger drift.
Since this is used to drive the master counter at 32.768KHz * 375 /
2 = 6.144MHz, the emulated speed for 20MHz is of by 570ppm, or about 43
seconds per day, and more than the 500ppm NTP is able to tolerate.
Checking the CTRL_CORE_BOOTSTRAP register can determine if the CPU
is using the real 32.768KHz crystal or the emulated SYSCLK1/610, and
by known that the real counter frequency can be determined and used.
The real speed is then SYSCLK1 / 610 * 375 / 2 or SYSCLK1 * 75 / 244.
Signed-off-by: Len Sorensen <lsorense@csclub.uwaterloo.ca>
Tested-by: Lokesh Vutla <lokeshvutla@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
diff --git a/arch/arm/mach-omap2/control.h b/arch/arm/mach-omap2/control.h
index a3c013345c45..a80ac2d70bb1 100644
--- a/arch/arm/mach-omap2/control.h
+++ b/arch/arm/mach-omap2/control.h
@@ -286,6 +286,10 @@
#define OMAP5XXX_CONTROL_STATUS 0x134
#define OMAP5_DEVICETYPE_MASK (0x7 << 6)
+/* DRA7XX CONTROL CORE BOOTSTRAP */
+#define DRA7_CTRL_CORE_BOOTSTRAP 0x6c4
+#define DRA7_SPEEDSELECT_MASK (0x3 << 8)
+
/*
* REVISIT: This list of registers is not comprehensive - there are more
* that should be added.
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
index fb0cb2b817a9..7d45c84c69ba 100644
--- a/arch/arm/mach-omap2/timer.c
+++ b/arch/arm/mach-omap2/timer.c
@@ -54,6 +54,7 @@
#include "soc.h"
#include "common.h"
+#include "control.h"
#include "powerdomain.h"
#include "omap-secure.h"
@@ -496,7 +497,8 @@ static void __init realtime_counter_init(void)
void __iomem *base;
static struct clk *sys_clk;
unsigned long rate;
- unsigned int reg, num, den;
+ unsigned int reg;
+ unsigned long long num, den;
base = ioremap(REALTIME_COUNTER_BASE, SZ_32);
if (!base) {
@@ -511,6 +513,35 @@ static void __init realtime_counter_init(void)
}
rate = clk_get_rate(sys_clk);
+
+ if (soc_is_dra7xx()) {
+ /*
+ * Errata i856 says the 32.768KHz crystal does not start at
+ * power on, so the CPU falls back to an emulated 32KHz clock
+ * based on sysclk / 610 instead. This causes the master counter
+ * frequency to not be 6.144MHz but at sysclk / 610 * 375 / 2
+ * (OR sysclk * 75 / 244)
+ *
+ * This affects at least the DRA7/AM572x 1.0, 1.1 revisions.
+ * Of course any board built without a populated 32.768KHz
+ * crystal would also need this fix even if the CPU is fixed
+ * later.
+ *
+ * Either case can be detected by using the two speedselect bits
+ * If they are not 0, then the 32.768KHz clock driving the
+ * coarse counter that corrects the fine counter every time it
+ * ticks is actually rate/610 rather than 32.768KHz and we
+ * should compensate to avoid the 570ppm (at 20MHz, much worse
+ * at other rates) too fast system time.
+ */
+ reg = omap_ctrl_readl(DRA7_CTRL_CORE_BOOTSTRAP);
+ if (reg & DRA7_SPEEDSELECT_MASK) {
+ num = 75;
+ den = 244;
+ goto sysclk1_based;
+ }
+ }
+
/* Numerator/denumerator values refer TRM Realtime Counter section */
switch (rate) {
case 12000000:
@@ -545,6 +576,7 @@ static void __init realtime_counter_init(void)
break;
}
+sysclk1_based:
/* Program numerator and denumerator registers */
reg = readl_relaxed(base + INCREMENTER_NUMERATOR_OFFSET) &
NUMERATOR_DENUMERATOR_MASK;
@@ -556,7 +588,7 @@ static void __init realtime_counter_init(void)
reg |= den;
writel_relaxed(reg, base + INCREMENTER_DENUMERATOR_RELOAD_OFFSET);
- arch_timer_freq = (rate / den) * num;
+ arch_timer_freq = DIV_ROUND_UP_ULL(rate * num, den);
set_cntfreq();
iounmap(base);
commit 572b24e6d85d98cdc552f07e9fb9870d9460d81b
Author: Lennart Sorensen <lsorense@csclub.uwaterloo.ca>
Date: Mon Jan 5 15:45:45 2015 -0800
ARM: omap5/dra7xx: Fix frequency typos
The switch statement of the possible list of SYSCLK1 frequencies is
missing a 0 in 4 out of the 7 frequencies.
Fixes: fa6d79d27614 ("ARM: OMAP: Add initialisation for the real-time counter")
Cc: stable@vger.kernel.org # v3.7+
Signed-off-by: Len Sorensen <lsorense@csclub.uwaterloo.ca>
Reviewed-by: Lokesh Vutla <lokeshvutla@ti.com>
Acked-by: Nishanth Menon <nm@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
index 4f61148ec168..fb0cb2b817a9 100644
--- a/arch/arm/mach-omap2/timer.c
+++ b/arch/arm/mach-omap2/timer.c
@@ -513,11 +513,11 @@ static void __init realtime_counter_init(void)
rate = clk_get_rate(sys_clk);
/* Numerator/denumerator values refer TRM Realtime Counter section */
switch (rate) {
- case 1200000:
+ case 12000000:
num = 64;
den = 125;
break;
- case 1300000:
+ case 13000000:
num = 768;
den = 1625;
break;
@@ -529,11 +529,11 @@ static void __init realtime_counter_init(void)
num = 192;
den = 625;
break;
- case 2600000:
+ case 26000000:
num = 384;
den = 1625;
break;
- case 2700000:
+ case 27000000:
num = 256;
den = 1125;
break;
commit 1e5c4bc497c0a96e1ad2974539d353870f2cb0b6
Author: Lennart Sorensen <lsorense@csclub.uwaterloo.ca>
Date: Fri Oct 31 13:38:52 2014 -0400
drivers: net: cpsw: Support ALLMULTI and fix IFF_PROMISC in switch mode
The cpsw driver did not support the IFF_ALLMULTI flag which makes dynamic
multicast routing not work. Related to this, when enabling IFF_PROMISC
in switch mode, all registered multicast addresses are flushed, resulting
in only broadcast and unicast traffic being received.
A new cpsw_ale_set_allmulti function now scans through the ALE entry
table and adds/removes the host port from the unregistered multicast
port mask of each vlan entry depending on the state of IFF_ALLMULTI.
In promiscious mode, cpsw_ale_set_allmulti is used to force reception
of all multicast traffic in addition to the unicast and broadcast traffic.
With this change dynamic multicast and promiscious mode both work in
switch mode.
Signed-off-by: Len Sorensen <lsorense@csclub.uwaterloo.ca>
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index fd4577d30c5d..d8794488f80a 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -638,12 +638,16 @@ static void cpsw_ndo_set_rx_mode(struct net_device *ndev)
if (ndev->flags & IFF_PROMISC) {
/* Enable promiscuous mode */
cpsw_set_promiscious(ndev, true);
+ cpsw_ale_set_allmulti(priv->ale, IFF_ALLMULTI);
return;
} else {
/* Disable promiscuous mode */
cpsw_set_promiscious(ndev, false);
}
+ /* Restore allmulti on vlans if necessary */
+ cpsw_ale_set_allmulti(priv->ale, priv->ndev->flags & IFF_ALLMULTI);
+
/* Clear all mcast from ALE */
cpsw_ale_flush_multicast(priv->ale, ALE_ALL_PORTS << priv->host_port);
@@ -1149,6 +1153,7 @@ static inline void cpsw_add_default_vlan(struct cpsw_priv *priv)
const int port = priv->host_port;
u32 reg;
int i;
+ int unreg_mcast_mask;
reg = (priv->version == CPSW_VERSION_1) ? CPSW1_PORT_VLAN :
CPSW2_PORT_VLAN;
@@ -1158,9 +1163,14 @@ static inline void cpsw_add_default_vlan(struct cpsw_priv *priv)
for (i = 0; i < priv->data.slaves; i++)
slave_write(priv->slaves + i, vlan, reg);
+ if (priv->ndev->flags & IFF_ALLMULTI)
+ unreg_mcast_mask = ALE_ALL_PORTS;
+ else
+ unreg_mcast_mask = ALE_PORT_1 | ALE_PORT_2;
+
cpsw_ale_add_vlan(priv->ale, vlan, ALE_ALL_PORTS << port,
ALE_ALL_PORTS << port, ALE_ALL_PORTS << port,
- (ALE_PORT_1 | ALE_PORT_2) << port);
+ unreg_mcast_mask << port);
}
static void cpsw_init_host_port(struct cpsw_priv *priv)
@@ -1620,11 +1630,17 @@ static inline int cpsw_add_vlan_ale_entry(struct cpsw_priv *priv,
unsigned short vid)
{
int ret;
+ int unreg_mcast_mask;
+
+ if (priv->ndev->flags & IFF_ALLMULTI)
+ unreg_mcast_mask = ALE_ALL_PORTS;
+ else
+ unreg_mcast_mask = ALE_PORT_1 | ALE_PORT_2;
ret = cpsw_ale_add_vlan(priv->ale, vid,
ALE_ALL_PORTS << priv->host_port,
0, ALE_ALL_PORTS << priv->host_port,
- (ALE_PORT_1 | ALE_PORT_2) << priv->host_port);
+ unreg_mcast_mask << priv->host_port);
if (ret != 0)
return ret;
diff --git a/drivers/net/ethernet/ti/cpsw_ale.c b/drivers/net/ethernet/ti/cpsw_ale.c
index 0579b2243bb6..3ae83879a75f 100644
--- a/drivers/net/ethernet/ti/cpsw_ale.c
+++ b/drivers/net/ethernet/ti/cpsw_ale.c
@@ -443,6 +443,35 @@ int cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port_mask)
return 0;
}
+void cpsw_ale_set_allmulti(struct cpsw_ale *ale, int allmulti)
+{
+ u32 ale_entry[ALE_ENTRY_WORDS];
+ int type, idx;
+ int unreg_mcast = 0;
+
+ /* Only bother doing the work if the setting is actually changing */
+ if (ale->allmulti == allmulti)
+ return;
+
+ /* Remember the new setting to check against next time */
+ ale->allmulti = allmulti;
+
+ for (idx = 0; idx < ale->params.ale_entries; idx++) {
+ cpsw_ale_read(ale, idx, ale_entry);
+ type = cpsw_ale_get_entry_type(ale_entry);
+ if (type != ALE_TYPE_VLAN)
+ continue;
+
+ unreg_mcast = cpsw_ale_get_vlan_unreg_mcast(ale_entry);
+ if (allmulti)
+ unreg_mcast |= 1;
+ else
+ unreg_mcast &= ~1;
+ cpsw_ale_set_vlan_unreg_mcast(ale_entry, unreg_mcast);
+ cpsw_ale_write(ale, idx, ale_entry);
+ }
+}
+
struct ale_control_info {
const char *name;
int offset, port_offset;
diff --git a/drivers/net/ethernet/ti/cpsw_ale.h b/drivers/net/ethernet/ti/cpsw_ale.h
index 31cf43cab42e..c0d4127aa549 100644
--- a/drivers/net/ethernet/ti/cpsw_ale.h
+++ b/drivers/net/ethernet/ti/cpsw_ale.h
@@ -27,6 +27,7 @@ struct cpsw_ale {
struct cpsw_ale_params params;
struct timer_list timer;
unsigned long ageout;
+ int allmulti;
};
enum cpsw_ale_control {
@@ -103,6 +104,7 @@ int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask,
int cpsw_ale_add_vlan(struct cpsw_ale *ale, u16 vid, int port, int untag,
int reg_mcast, int unreg_mcast);
int cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port);
+void cpsw_ale_set_allmulti(struct cpsw_ale *ale, int allmulti);
int cpsw_ale_control_get(struct cpsw_ale *ale, int port, int control);
int cpsw_ale_control_set(struct cpsw_ale *ale, int port,
commit 6f979eb3fcfb4c3f42f230d174db4bbad0080710
Author: Lennart Sorensen <lsorense@csclub.uwaterloo.ca>
Date: Fri Oct 31 13:28:54 2014 -0400
drivers: net: cpsw: Fix broken loop condition in switch mode
0d961b3b52f566f823070ce2366511a7f64b928c (drivers: net: cpsw: fix buggy
loop condition) accidentally fixed a loop comparison in too many places
while fixing a real bug.
It was correct to fix the dual_emac mode section since there 'i' is used
as an index into priv->slaves which is a 0 based array.
However the other two changes (which are only used in switch mode)
are wrong since there 'i' is actually the ALE port number, and port 0
is the host port, while port 1 and up are the slave ports.
Putting the loop condition back in the switch mode section fixes it.
A comment has been added to point out the intent clearly to avoid future
confusion. Also a comment is fixed that said the opposite of what was
actually happening.
Signed-off-by: Len Sorensen <lsorense@csclub.uwaterloo.ca>
Acked-by: Heiko Schocher <hs@denx.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index d81b84b5e3df..fd4577d30c5d 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -591,8 +591,8 @@ static void cpsw_set_promiscious(struct net_device *ndev, bool enable)
if (enable) {
unsigned long timeout = jiffies + HZ;
- /* Disable Learn for all ports */
- for (i = 0; i < priv->data.slaves; i++) {
+ /* Disable Learn for all ports (host is port 0 and slaves are port 1 and up */
+ for (i = 0; i <= priv->data.slaves; i++) {
cpsw_ale_control_set(ale, i,
ALE_PORT_NOLEARN, 1);
cpsw_ale_control_set(ale, i,
@@ -616,11 +616,11 @@ static void cpsw_set_promiscious(struct net_device *ndev, bool enable)
cpsw_ale_control_set(ale, 0, ALE_P0_UNI_FLOOD, 1);
dev_dbg(&ndev->dev, "promiscuity enabled\n");
} else {
- /* Flood All Unicast Packets to Host port */
+ /* Don't Flood All Unicast Packets to Host port */
cpsw_ale_control_set(ale, 0, ALE_P0_UNI_FLOOD, 0);
- /* Enable Learn for all ports */
- for (i = 0; i < priv->data.slaves; i++) {
+ /* Enable Learn for all ports (host is port 0 and slaves are port 1 and up */
+ for (i = 0; i <= priv->data.slaves; i++) {
cpsw_ale_control_set(ale, i,
ALE_PORT_NOLEARN, 0);
cpsw_ale_control_set(ale, i,
commit 10738eeaf4ab3de092586cefcc082e7d43ca0044
Author: Lennart Sorensen <lsorense@csclub.uwaterloo.ca>
Date: Fri Oct 31 13:38:52 2014 -0400
drivers: net: cpsw: Support ALLMULTI and fix IFF_PROMISC in switch mode
The cpsw driver did not support the IFF_ALLMULTI flag which makes dynamic
multicast routing not work. Related to this, when enabling IFF_PROMISC
in switch mode, all registered multicast addresses are flushed, resulting
in only broadcast and unicast traffic being received.
A new cpsw_ale_set_allmulti function now scans through the ALE entry
table and adds/removes the host port from the unregistered multicast
port mask of each vlan entry depending on the state of IFF_ALLMULTI.
In promiscious mode, cpsw_ale_set_allmulti is used to force reception
of all multicast traffic in addition to the unicast and broadcast traffic.
With this change dynamic multicast and promiscious mode both work in
switch mode.
Signed-off-by: Len Sorensen <lsorense@csclub.uwaterloo.ca>
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 4683196c6592..96a61d169215 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -638,12 +638,16 @@ static void cpsw_ndo_set_rx_mode(struct net_device *ndev)
if (ndev->flags & IFF_PROMISC) {
/* Enable promiscuous mode */
cpsw_set_promiscious(ndev, true);
+ cpsw_ale_set_allmulti(priv->ale, IFF_ALLMULTI);
return;
} else {
/* Disable promiscuous mode */
cpsw_set_promiscious(ndev, false);
}
+ /* Restore allmulti on vlans if necessary */
+ cpsw_ale_set_allmulti(priv->ale, priv->ndev->flags & IFF_ALLMULTI);
+
/* Clear all mcast from ALE */
cpsw_ale_flush_multicast(priv->ale, ALE_ALL_PORTS << priv->host_port);
@@ -1149,6 +1153,7 @@ static inline void cpsw_add_default_vlan(struct cpsw_priv *priv)
const int port = priv->host_port;
u32 reg;
int i;
+ int unreg_mcast_mask;
reg = (priv->version == CPSW_VERSION_1) ? CPSW1_PORT_VLAN :
CPSW2_PORT_VLAN;
@@ -1158,9 +1163,14 @@ static inline void cpsw_add_default_vlan(struct cpsw_priv *priv)
for (i = 0; i < priv->data.slaves; i++)
slave_write(priv->slaves + i, vlan, reg);
+ if (priv->ndev->flags & IFF_ALLMULTI)
+ unreg_mcast_mask = ALE_ALL_PORTS;
+ else
+ unreg_mcast_mask = ALE_PORT_1 | ALE_PORT_2;
+
cpsw_ale_add_vlan(priv->ale, vlan, ALE_ALL_PORTS << port,
ALE_ALL_PORTS << port, ALE_ALL_PORTS << port,
- (ALE_PORT_1 | ALE_PORT_2) << port);
+ unreg_mcast_mask << port);
}
static void cpsw_init_host_port(struct cpsw_priv *priv)
@@ -1620,11 +1630,17 @@ static inline int cpsw_add_vlan_ale_entry(struct cpsw_priv *priv,
unsigned short vid)
{
int ret;
+ int unreg_mcast_mask;
+
+ if (priv->ndev->flags & IFF_ALLMULTI)
+ unreg_mcast_mask = ALE_ALL_PORTS;
+ else
+ unreg_mcast_mask = ALE_PORT_1 | ALE_PORT_2;
ret = cpsw_ale_add_vlan(priv->ale, vid,
ALE_ALL_PORTS << priv->host_port,
0, ALE_ALL_PORTS << priv->host_port,
- (ALE_PORT_1 | ALE_PORT_2) << priv->host_port);
+ unreg_mcast_mask << priv->host_port);
if (ret != 0)
return ret;
diff --git a/drivers/net/ethernet/ti/cpsw_ale.c b/drivers/net/ethernet/ti/cpsw_ale.c
index 0579b2243bb6..3ae83879a75f 100644
--- a/drivers/net/ethernet/ti/cpsw_ale.c
+++ b/drivers/net/ethernet/ti/cpsw_ale.c
@@ -443,6 +443,35 @@ int cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port_mask)
return 0;
}
+void cpsw_ale_set_allmulti(struct cpsw_ale *ale, int allmulti)
+{
+ u32 ale_entry[ALE_ENTRY_WORDS];
+ int type, idx;
+ int unreg_mcast = 0;
+
+ /* Only bother doing the work if the setting is actually changing */
+ if (ale->allmulti == allmulti)
+ return;
+
+ /* Remember the new setting to check against next time */
+ ale->allmulti = allmulti;
+
+ for (idx = 0; idx < ale->params.ale_entries; idx++) {
+ cpsw_ale_read(ale, idx, ale_entry);
+ type = cpsw_ale_get_entry_type(ale_entry);
+ if (type != ALE_TYPE_VLAN)
+ continue;
+
+ unreg_mcast = cpsw_ale_get_vlan_unreg_mcast(ale_entry);
+ if (allmulti)
+ unreg_mcast |= 1;
+ else
+ unreg_mcast &= ~1;
+ cpsw_ale_set_vlan_unreg_mcast(ale_entry, unreg_mcast);
+ cpsw_ale_write(ale, idx, ale_entry);
+ }
+}
+
struct ale_control_info {
const char *name;
int offset, port_offset;
diff --git a/drivers/net/ethernet/ti/cpsw_ale.h b/drivers/net/ethernet/ti/cpsw_ale.h
index 31cf43cab42e..c0d4127aa549 100644
--- a/drivers/net/ethernet/ti/cpsw_ale.h
+++ b/drivers/net/ethernet/ti/cpsw_ale.h
@@ -27,6 +27,7 @@ struct cpsw_ale {
struct cpsw_ale_params params;
struct timer_list timer;
unsigned long ageout;
+ int allmulti;
};
enum cpsw_ale_control {
@@ -103,6 +104,7 @@ int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask,
int cpsw_ale_add_vlan(struct cpsw_ale *ale, u16 vid, int port, int untag,
int reg_mcast, int unreg_mcast);
int cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port);
+void cpsw_ale_set_allmulti(struct cpsw_ale *ale, int allmulti);
int cpsw_ale_control_get(struct cpsw_ale *ale, int port, int control);
int cpsw_ale_control_set(struct cpsw_ale *ale, int port,