[PATCH v4 5/8] MIPS: Octeon: Automatically provision CVMSEG space.

From: David Daney
Date: Tue Nov 28 2017 - 19:59:16 EST


Remove CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE and automatically calculate
the amount of CVMSEG space needed.

1st 128-bytes: Use by IOBDMA
2nd 128-bytes: Reserved by kernel for scratch/TLS emulation.
3rd 128-bytes: OCTEON-III LMTLINE

New config variable CONFIG_CAVIUM_OCTEON_EXTRA_CVMSEG provisions
additional lines, defaults to zero.

Signed-off-by: David Daney <david.daney@xxxxxxxxxx>
Signed-off-by: Carlos Munoz <cmunoz@xxxxxxxxxxxxxxxxxx>
---
arch/mips/cavium-octeon/Kconfig | 27 ++++++++++++--------
arch/mips/cavium-octeon/setup.c | 16 ++++++------
.../asm/mach-cavium-octeon/kernel-entry-init.h | 20 +++++++++------
arch/mips/include/asm/mipsregs.h | 2 ++
arch/mips/include/asm/octeon/octeon.h | 2 ++
arch/mips/include/asm/processor.h | 2 +-
arch/mips/kernel/octeon_switch.S | 2 --
arch/mips/mm/tlbex.c | 29 ++++++----------------
drivers/staging/octeon/ethernet-defines.h | 2 +-
9 files changed, 50 insertions(+), 52 deletions(-)

diff --git a/arch/mips/cavium-octeon/Kconfig b/arch/mips/cavium-octeon/Kconfig
index ce469f982134..29c4d81364a6 100644
--- a/arch/mips/cavium-octeon/Kconfig
+++ b/arch/mips/cavium-octeon/Kconfig
@@ -11,21 +11,26 @@ config CAVIUM_CN63XXP1
non-CN63XXP1 hardware, so it is recommended to select "n"
unless it is known the workarounds are needed.

-config CAVIUM_OCTEON_CVMSEG_SIZE
- int "Number of L1 cache lines reserved for CVMSEG memory"
- range 0 54
- default 1
- help
- CVMSEG LM is a segment that accesses portions of the dcache as a
- local memory; the larger CVMSEG is, the smaller the cache is.
- This selects the size of CVMSEG LM, which is in cache blocks. The
- legally range is from zero to 54 cache blocks (i.e. CVMSEG LM is
- between zero and 6192 bytes).
-
endif # CPU_CAVIUM_OCTEON

if CAVIUM_OCTEON_SOC

+config CAVIUM_OCTEON_EXTRA_CVMSEG
+ int "Number of extra L1 cache lines reserved for CVMSEG memory"
+ range 0 50
+ default 0
+ help
+ CVMSEG LM is a segment that accesses portions of the dcache
+ as a local memory; the larger CVMSEG is, the smaller the
+ cache is. The kernel uses two or three blocks (one for TLB
+ exception handlers, one for driver IOBDMA operations, and on
+ models that need it, one for LMTDMA operations). This
+ selects an optional extra number of CVMSEG lines for use by
+ other software.
+
+ Normally no extra lines are required, and this parameter
+ should be set to zero.
+
config CAVIUM_OCTEON_LOCK_L2
bool "Lock often used kernel code in the L2"
default "y"
diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c
index 99e6a68bc652..51c4d3c3cada 100644
--- a/arch/mips/cavium-octeon/setup.c
+++ b/arch/mips/cavium-octeon/setup.c
@@ -68,6 +68,12 @@ extern void pci_console_init(const char *arg);
static unsigned long long max_memory = ULLONG_MAX;
static unsigned long long reserve_low_mem;

+/*
+ * modified in hernel-entry-init.h, must have an initial value to keep
+ * it from being clobbered when bss is zeroed.
+ */
+u32 octeon_cvmseg_lines = 2;
+
DEFINE_SEMAPHORE(octeon_bootbus_sem);
EXPORT_SYMBOL(octeon_bootbus_sem);

@@ -604,11 +610,7 @@ void octeon_user_io_init(void)

/* R/W If set, CVMSEG is available for loads/stores in
* kernel/debug mode. */
-#if CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0
cvmmemctl.s.cvmsegenak = 1;
-#else
- cvmmemctl.s.cvmsegenak = 0;
-#endif
if (OCTEON_IS_OCTEON3()) {
/* Enable LMTDMA */
cvmmemctl.s.lmtena = 1;
@@ -626,9 +628,9 @@ void octeon_user_io_init(void)

/* Setup of CVMSEG is done in kernel-entry-init.h */
if (smp_processor_id() == 0)
- pr_notice("CVMSEG size: %d cache lines (%d bytes)\n",
- CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE,
- CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE * 128);
+ pr_notice("CVMSEG size: %u cache lines (%u bytes)\n",
+ octeon_cvmseg_lines,
+ octeon_cvmseg_lines * 128);

if (octeon_has_feature(OCTEON_FEATURE_FAU)) {
union cvmx_iob_fau_timeout fau_timeout;
diff --git a/arch/mips/include/asm/mach-cavium-octeon/kernel-entry-init.h b/arch/mips/include/asm/mach-cavium-octeon/kernel-entry-init.h
index c38b38ce5a3d..cdcca60978a2 100644
--- a/arch/mips/include/asm/mach-cavium-octeon/kernel-entry-init.h
+++ b/arch/mips/include/asm/mach-cavium-octeon/kernel-entry-init.h
@@ -26,11 +26,18 @@
# a3 = address of boot descriptor block
.set push
.set arch=octeon
+ mfc0 v1, CP0_PRID_REG
+ andi v1, 0xff00
+ li v0, 0x9500 # cn78XX or later
+ subu v1, v1, v0
+ li t2, 2 + CONFIG_CAVIUM_OCTEON_EXTRA_CVMSEG
+ bltz v1, 1f
+ addiu t2, 1 # t2 has cvmseg_size
+1:
# Read the cavium mem control register
dmfc0 v0, CP0_CVMMEMCTL_REG
# Clear the lower 6 bits, the CVMSEG size
- dins v0, $0, 0, 6
- ori v0, CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE
+ dins v0, t2, 0, 6
dmtc0 v0, CP0_CVMMEMCTL_REG # Write the cavium mem control register
dmfc0 v0, CP0_CVMCTL_REG # Read the cavium control register
# Disable unaligned load/store support but leave HW fixup enabled
@@ -70,7 +77,7 @@
# Flush dcache after config change
cache 9, 0($0)
# Zero all of CVMSEG to make sure parity is correct
- dli v0, CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE
+ move v0, t2
dsll v0, 7
beqz v0, 2f
1: dsubu v0, 8
@@ -126,12 +133,7 @@
LONG_L sp, (t0)
# Set the SP global variable to zero so the master knows we've started
LONG_S zero, (t0)
-#ifdef __OCTEON__
- syncw
- syncw
-#else
sync
-#endif
# Jump to the normal Linux SMP entry point
j smp_bootstrap
nop
@@ -148,6 +150,8 @@

#endif /* CONFIG_SMP */
octeon_main_processor:
+ dla v0, octeon_cvmseg_lines
+ sw t2, 0(v0)
.set pop
.endm

diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h
index 6b1f1ad0542c..0b588640b65a 100644
--- a/arch/mips/include/asm/mipsregs.h
+++ b/arch/mips/include/asm/mipsregs.h
@@ -1126,6 +1126,8 @@
#define FPU_CSR_RD 0x3 /* towards -Infinity */


+#define CAVIUM_OCTEON_SCRATCH_OFFSET (2 * 128 - 16 - 32768)
+
#ifndef __ASSEMBLY__

/*
diff --git a/arch/mips/include/asm/octeon/octeon.h b/arch/mips/include/asm/octeon/octeon.h
index d184592e6515..02eb194b2cdc 100644
--- a/arch/mips/include/asm/octeon/octeon.h
+++ b/arch/mips/include/asm/octeon/octeon.h
@@ -392,6 +392,8 @@ static inline uint32_t octeon_npi_read32(uint64_t address)

extern struct cvmx_bootinfo *octeon_bootinfo;

+extern u32 octeon_cvmseg_lines;
+
extern uint64_t octeon_bootloader_entry_addr;

extern void (*octeon_irq_setup_secondary)(void);
diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h
index af34afbc32d9..1a20f9c5509f 100644
--- a/arch/mips/include/asm/processor.h
+++ b/arch/mips/include/asm/processor.h
@@ -216,7 +216,7 @@ struct octeon_cop2_state {
.cp2 = {0,},

struct octeon_cvmseg_state {
- unsigned long cvmseg[CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE]
+ unsigned long cvmseg[CONFIG_CAVIUM_OCTEON_EXTRA_CVMSEG + 3]
[cpu_dcache_line_size() / sizeof(unsigned long)];
};

diff --git a/arch/mips/kernel/octeon_switch.S b/arch/mips/kernel/octeon_switch.S
index e42113fe2762..4f56902d5ee7 100644
--- a/arch/mips/kernel/octeon_switch.S
+++ b/arch/mips/kernel/octeon_switch.S
@@ -29,7 +29,6 @@
cpu_save_nonscratch a0
LONG_S ra, THREAD_REG31(a0)

-#if CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0
/* Check if we need to store CVMSEG state */
dmfc0 t0, $11,7 /* CvmMemCtl */
bbit0 t0, 6, 3f /* Is user access enabled? */
@@ -58,7 +57,6 @@
dmfc0 t0, $11,7 /* CvmMemCtl */
xori t0, t0, 0x40 /* Bit 6 is CVMSEG user enable */
dmtc0 t0, $11,7 /* CvmMemCtl */
-#endif
3:

#if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP)
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 79b9f2ad3ff5..3d3dfba465ae 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -115,33 +115,17 @@ static int use_lwx_insns(void)
return 0;
}
}
-#if defined(CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE) && \
- CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0
-static bool scratchpad_available(void)
-{
- return true;
-}
-static int scratchpad_offset(int i)
-{
- /*
- * CVMSEG starts at address -32768 and extends for
- * CAVIUM_OCTEON_CVMSEG_SIZE 128 byte cache lines.
- */
- i += 1; /* Kernel use starts at the top and works down. */
- return CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE * 128 - (8 * i) - 32768;
-}
-#else
-static bool scratchpad_available(void)
-{
- return false;
-}
+
static int scratchpad_offset(int i)
{
+ if (IS_ENABLED(CONFIG_CPU_CAVIUM_OCTEON))
+ return (CAVIUM_OCTEON_SCRATCH_OFFSET - (8 * i));
+
BUG();
/* Really unreachable, but evidently some GCC want this. */
return 0;
}
-#endif
+
/*
* Found by experiment: At least some revisions of the 4kc throw under
* some circumstances a machine check exception, triggered by invalid
@@ -1302,7 +1286,8 @@ static void build_r4000_tlb_refill_handler(void)
memset(relocs, 0, sizeof(relocs));
memset(final_handler, 0, sizeof(final_handler));

- if (IS_ENABLED(CONFIG_64BIT) && (scratch_reg >= 0 || scratchpad_available()) && use_bbit_insns()) {
+ if (IS_ENABLED(CONFIG_64BIT) && use_bbit_insns() &&
+ (scratch_reg >= 0 || IS_ENABLED(CONFIG_CPU_CAVIUM_OCTEON))) {
htlb_info = build_fast_tlb_refill_handler(&p, &l, &r, K0, K1,
scratch_reg);
vmalloc_mode = refill_scratch;
diff --git a/drivers/staging/octeon/ethernet-defines.h b/drivers/staging/octeon/ethernet-defines.h
index 07bd2b87f6a0..e898df25b87f 100644
--- a/drivers/staging/octeon/ethernet-defines.h
+++ b/drivers/staging/octeon/ethernet-defines.h
@@ -32,7 +32,7 @@
#define REUSE_SKBUFFS_WITHOUT_FREE 1
#endif

-#define USE_ASYNC_IOBDMA (CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0)
+#define USE_ASYNC_IOBDMA 1

/* Maximum number of SKBs to try to free per xmit packet. */
#define MAX_OUT_QUEUE_DEPTH 1000
--
2.14.3