2017-11-29 00:57:58

by David Daney

[permalink] [raw]
Subject: [PATCH v4 0/8] Cavium OCTEON-III network driver.

We are adding the Cavium OCTEON-III network driver. But since
interacting with the input and output queues is done via special CPU
local memory, we also need to add support to the MIPS/Octeon
architecture code. Aren't SoCs nice in this way?

The first six patches add the SoC support needed by the driver, the
last two add the driver and an entry in MAINTAINERS.

Since these touch several subsystems (mips, staging, netdev), I would
propose merging via netdev, but defer to the maintainers if they think
something else would work better.

A separate pull request was recently done by Steven Hill for the
firmware required by the driver.

Changes from v3:

o Use phy_print_status() instead of open coding the equivalent.

o Print warning on phy mode mismatch.

o Improve dt-bindings and add Acked-by.

Changes from v2:

o Fix PKI (RX path) initialization to work with little endian kernel.

Changes from v1:

o Cleanup and use of standard bindings in the device tree bindings
document.

o Added (hopefully) clarifying comments about several OCTEON
architectural peculiarities.

o Removed unused testing code from the driver.

o Removed some module parameters that already default to the proper
values.

o KConfig cleanup, including testing on x86_64, arm64 and mips.

o Fixed breakage to the driver for previous generation of OCTEON SoCs (in
the staging directory still).

o Verified bisectability of the patch set.

Carlos Munoz (5):
dt-bindings: Add Cavium Octeon Common Ethernet Interface.
MIPS: Octeon: Enable LMTDMA/LMTST operations.
MIPS: Octeon: Add a global resource manager.
MIPS: Octeon: Add Free Pointer Unit (FPA) support.
netdev: octeon-ethernet: Add Cavium Octeon III support.

David Daney (3):
MIPS: Octeon: Automatically provision CVMSEG space.
staging: octeon: Remove USE_ASYNC_IOBDMA macro.
MAINTAINERS: Add entry for
drivers/net/ethernet/cavium/octeon/octeon3-*

.../devicetree/bindings/net/cavium-bgx.txt | 61 +
MAINTAINERS | 6 +
arch/mips/cavium-octeon/Kconfig | 35 +-
arch/mips/cavium-octeon/Makefile | 4 +-
arch/mips/cavium-octeon/octeon-fpa3.c | 364 ++++
arch/mips/cavium-octeon/resource-mgr.c | 371 ++++
arch/mips/cavium-octeon/setup.c | 22 +-
.../asm/mach-cavium-octeon/kernel-entry-init.h | 20 +-
arch/mips/include/asm/mipsregs.h | 2 +
arch/mips/include/asm/octeon/octeon.h | 47 +-
arch/mips/include/asm/processor.h | 2 +-
arch/mips/kernel/octeon_switch.S | 2 -
arch/mips/mm/tlbex.c | 29 +-
drivers/net/ethernet/cavium/Kconfig | 55 +-
drivers/net/ethernet/cavium/octeon/Makefile | 6 +
.../net/ethernet/cavium/octeon/octeon3-bgx-nexus.c | 698 +++++++
.../net/ethernet/cavium/octeon/octeon3-bgx-port.c | 2033 +++++++++++++++++++
drivers/net/ethernet/cavium/octeon/octeon3-core.c | 2068 ++++++++++++++++++++
drivers/net/ethernet/cavium/octeon/octeon3-pki.c | 832 ++++++++
drivers/net/ethernet/cavium/octeon/octeon3-pko.c | 1719 ++++++++++++++++
drivers/net/ethernet/cavium/octeon/octeon3-sso.c | 309 +++
drivers/net/ethernet/cavium/octeon/octeon3.h | 411 ++++
drivers/staging/octeon/ethernet-defines.h | 6 -
drivers/staging/octeon/ethernet-rx.c | 25 +-
drivers/staging/octeon/ethernet-tx.c | 85 +-
25 files changed, 9069 insertions(+), 143 deletions(-)
create mode 100644 Documentation/devicetree/bindings/net/cavium-bgx.txt
create mode 100644 arch/mips/cavium-octeon/octeon-fpa3.c
create mode 100644 arch/mips/cavium-octeon/resource-mgr.c
create mode 100644 drivers/net/ethernet/cavium/octeon/octeon3-bgx-nexus.c
create mode 100644 drivers/net/ethernet/cavium/octeon/octeon3-bgx-port.c
create mode 100644 drivers/net/ethernet/cavium/octeon/octeon3-core.c
create mode 100644 drivers/net/ethernet/cavium/octeon/octeon3-pki.c
create mode 100644 drivers/net/ethernet/cavium/octeon/octeon3-pko.c
create mode 100644 drivers/net/ethernet/cavium/octeon/octeon3-sso.c
create mode 100644 drivers/net/ethernet/cavium/octeon/octeon3.h

--
2.14.3


From 1585409462209927906@xxx Wed Nov 29 14:04:45 +0000 2017
X-GM-THRID: 1585409462209927906
X-Gmail-Labels: Inbox,Category Forums,HistoricalUnread


2017-11-29 00:58:13

by David Daney

[permalink] [raw]
Subject: [PATCH v4 1/8] dt-bindings: Add Cavium Octeon Common Ethernet Interface.

From: Carlos Munoz <[email protected]>

Add bindings for Common Ethernet Interface (BGX) block.

Acked-by: Rob Herring <[email protected]>
Signed-off-by: Carlos Munoz <[email protected]>
Signed-off-by: Steven J. Hill <[email protected]>
Signed-off-by: David Daney <[email protected]>
---
.../devicetree/bindings/net/cavium-bgx.txt | 61 ++++++++++++++++++++++
1 file changed, 61 insertions(+)
create mode 100644 Documentation/devicetree/bindings/net/cavium-bgx.txt

diff --git a/Documentation/devicetree/bindings/net/cavium-bgx.txt b/Documentation/devicetree/bindings/net/cavium-bgx.txt
new file mode 100644
index 000000000000..830c5f08dddd
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/cavium-bgx.txt
@@ -0,0 +1,61 @@
+* Common Ethernet Interface (BGX) block
+
+Properties:
+
+- compatible: "cavium,octeon-7890-bgx": Compatibility with all cn7xxx SOCs.
+
+- reg: The base address of the BGX block.
+
+- #address-cells: Must be <1>.
+
+- #size-cells: Must be <0>. BGX addresses have no size component.
+
+A BGX block has several children, each representing an Ethernet
+interface.
+
+
+* Ethernet Interface (BGX port) connects to PKI/PKO
+
+Properties:
+
+- compatible: "cavium,octeon-7890-bgx-port": Compatibility with all
+ cn7xxx SOCs.
+
+ "cavium,octeon-7360-xcv": Compatibility with cn73xx SOCs
+ for RGMII.
+
+- reg: The index of the interface within the BGX block.
+
+Optional properties:
+
+- local-mac-address: Mac address for the interface.
+
+- phy-handle: phandle to the phy node connected to the interface.
+
+- phy-mode: described in ethernet.txt.
+
+- fixed-link: described in fixed-link.txt.
+
+Example:
+
+ ethernet-mac-nexus@11800e0000000 {
+ compatible = "cavium,octeon-7890-bgx";
+ reg = <0x00011800 0xe0000000 0x00000000 0x01000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethernet@0 {
+ compatible = "cavium,octeon-7360-xcv";
+ reg = <0>;
+ local-mac-address = [ 00 01 23 45 67 89 ];
+ phy-handle = <&phy3>;
+ phy-mode = "rgmii-rxid"
+ };
+ ethernet@1 {
+ compatible = "cavium,octeon-7890-bgx-port";
+ reg = <1>;
+ local-mac-address = [ 00 01 23 45 67 8a ];
+ phy-handle = <&phy4>;
+ phy-mode = "sgmii"
+ };
+ };
--
2.14.3


From 1585415724040697848@xxx Wed Nov 29 15:44:16 +0000 2017
X-GM-THRID: 1585415724040697848
X-Gmail-Labels: Inbox,Category Forums,HistoricalUnread

2017-11-29 00:59:42

by David Daney

[permalink] [raw]
Subject: [PATCH v4 8/8] MAINTAINERS: Add entry for drivers/net/ethernet/cavium/octeon/octeon3-*

Signed-off-by: David Daney <[email protected]>
---
MAINTAINERS | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index aa71ab52fd76..e9239ff3cf05 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3249,6 +3249,12 @@ W: http://www.cavium.com
S: Supported
F: drivers/mmc/host/cavium*

+CAVIUM OCTEON-III NETWORK DRIVER
+M: David Daney <[email protected]>
+L: [email protected]
+S: Supported
+F: drivers/net/ethernet/cavium/octeon/octeon3-*
+
CAVIUM OCTEON-TX CRYPTO DRIVER
M: George Cherian <[email protected]>
L: [email protected]
--
2.14.3


From 1585348540456910397@xxx Tue Nov 28 21:56:25 +0000 2017
X-GM-THRID: 1585348540456910397
X-Gmail-Labels: Inbox,Category Forums,HistoricalUnread

2017-11-29 01:01:37

by David Daney

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

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 <[email protected]>
Signed-off-by: Carlos Munoz <[email protected]>
---
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


From 1586584694486595226@xxx Tue Dec 12 13:24:33 +0000 2017
X-GM-THRID: 1586582610021635426
X-Gmail-Labels: Inbox,Category Forums,HistoricalUnread

2017-11-29 01:00:07

by David Daney

[permalink] [raw]
Subject: [PATCH v4 4/8] MIPS: Octeon: Add Free Pointer Unit (FPA) support.

From: Carlos Munoz <[email protected]>

>From the hardware user manual: "The FPA is a unit that maintains
pools of pointers to free L2/DRAM memory. To provide QoS, the pools
are referenced indirectly through 1024 auras. Both core software
and hardware units allocate and free pointers."

Signed-off-by: Carlos Munoz <[email protected]>
Signed-off-by: Steven J. Hill <[email protected]>
Signed-off-by: David Daney <[email protected]>
---
arch/mips/cavium-octeon/Kconfig | 8 +
arch/mips/cavium-octeon/Makefile | 1 +
arch/mips/cavium-octeon/octeon-fpa3.c | 364 ++++++++++++++++++++++++++++++++++
arch/mips/include/asm/octeon/octeon.h | 15 ++
4 files changed, 388 insertions(+)
create mode 100644 arch/mips/cavium-octeon/octeon-fpa3.c

diff --git a/arch/mips/cavium-octeon/Kconfig b/arch/mips/cavium-octeon/Kconfig
index 204a1670fd9b..ce469f982134 100644
--- a/arch/mips/cavium-octeon/Kconfig
+++ b/arch/mips/cavium-octeon/Kconfig
@@ -87,4 +87,12 @@ config OCTEON_ILM
To compile this driver as a module, choose M here. The module
will be called octeon-ilm

+config OCTEON_FPA3
+ tristate "Octeon III fpa driver"
+ help
+ This option enables a Octeon III driver for the Free Pool Unit (FPA).
+ The FPA is a hardware unit that manages pools of pointers to free
+ L2/DRAM memory. This driver provides an interface to reserve,
+ initialize, and fill fpa pools.
+
endif # CAVIUM_OCTEON_SOC
diff --git a/arch/mips/cavium-octeon/Makefile b/arch/mips/cavium-octeon/Makefile
index 0a299ab8719f..0ef967399702 100644
--- a/arch/mips/cavium-octeon/Makefile
+++ b/arch/mips/cavium-octeon/Makefile
@@ -20,3 +20,4 @@ obj-$(CONFIG_MTD) += flash_setup.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_OCTEON_ILM) += oct_ilm.o
obj-$(CONFIG_USB) += octeon-usb.o
+obj-$(CONFIG_OCTEON_FPA3) += octeon-fpa3.o
diff --git a/arch/mips/cavium-octeon/octeon-fpa3.c b/arch/mips/cavium-octeon/octeon-fpa3.c
new file mode 100644
index 000000000000..a7c7decdbc9a
--- /dev/null
+++ b/arch/mips/cavium-octeon/octeon-fpa3.c
@@ -0,0 +1,364 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver for the Octeon III Free Pool Unit (fpa).
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2015-2017 Cavium, Inc.
+ */
+
+#include <linux/module.h>
+
+#include <asm/octeon/octeon.h>
+
+
+/* Registers are accessed via xkphys */
+#define SET_XKPHYS (1ull << 63)
+#define NODE_OFFSET 0x1000000000ull
+#define SET_NODE(node) ((node) * NODE_OFFSET)
+
+#define FPA_BASE 0x1280000000000ull
+#define SET_FPA_BASE(node) (SET_XKPHYS + SET_NODE(node) + FPA_BASE)
+
+#define FPA_GEN_CFG(n) (SET_FPA_BASE(n) + 0x00000050)
+
+#define FPA_POOLX_CFG(n, p) (SET_FPA_BASE(n) + (p<<3) + 0x10000000)
+#define FPA_POOLX_START_ADDR(n, p) (SET_FPA_BASE(n) + (p<<3) + 0x10500000)
+#define FPA_POOLX_END_ADDR(n, p) (SET_FPA_BASE(n) + (p<<3) + 0x10600000)
+#define FPA_POOLX_STACK_BASE(n, p) (SET_FPA_BASE(n) + (p<<3) + 0x10700000)
+#define FPA_POOLX_STACK_END(n, p) (SET_FPA_BASE(n) + (p<<3) + 0x10800000)
+#define FPA_POOLX_STACK_ADDR(n, p) (SET_FPA_BASE(n) + (p<<3) + 0x10900000)
+
+#define FPA_AURAX_POOL(n, a) (SET_FPA_BASE(n) + (a<<3) + 0x20000000)
+#define FPA_AURAX_CFG(n, a) (SET_FPA_BASE(n) + (a<<3) + 0x20100000)
+#define FPA_AURAX_CNT(n, a) (SET_FPA_BASE(n) + (a<<3) + 0x20200000)
+#define FPA_AURAX_CNT_LIMIT(n, a) (SET_FPA_BASE(n) + (a<<3) + 0x20400000)
+#define FPA_AURAX_CNT_THRESHOLD(n, a) (SET_FPA_BASE(n) + (a<<3) + 0x20500000)
+#define FPA_AURAX_POOL_LEVELS(n, a) (SET_FPA_BASE(n) + (a<<3) + 0x20700000)
+#define FPA_AURAX_CNT_LEVELS(n, a) (SET_FPA_BASE(n) + (a<<3) + 0x20800000)
+
+static inline u64 oct_csr_read(u64 addr)
+{
+ return __raw_readq((void __iomem *)addr);
+}
+
+static inline void oct_csr_write(u64 data, u64 addr)
+{
+ __raw_writeq(data, (void __iomem *)addr);
+}
+
+static DEFINE_MUTEX(octeon_fpa3_lock);
+
+static int get_num_pools(void)
+{
+ if (OCTEON_IS_MODEL(OCTEON_CN78XX))
+ return 64;
+ if (OCTEON_IS_MODEL(OCTEON_CNF75XX) || OCTEON_IS_MODEL(OCTEON_CN73XX))
+ return 32;
+ return 0;
+}
+
+static int get_num_auras(void)
+{
+ if (OCTEON_IS_MODEL(OCTEON_CN78XX))
+ return 1024;
+ if (OCTEON_IS_MODEL(OCTEON_CNF75XX) || OCTEON_IS_MODEL(OCTEON_CN73XX))
+ return 512;
+ return 0;
+}
+
+/**
+ * octeon_fpa3_init - Initialize the fpa to default values.
+ * @node: Node of fpa to initialize.
+ *
+ * Returns 0 if successful.
+ * Returns <0 for error codes.
+ */
+int octeon_fpa3_init(int node)
+{
+ static bool init_done[2];
+ u64 data;
+ int aura_cnt, i;
+
+ mutex_lock(&octeon_fpa3_lock);
+
+ if (init_done[node])
+ goto done;
+
+ aura_cnt = get_num_auras();
+ for (i = 0; i < aura_cnt; i++) {
+ oct_csr_write(0x100000000ull, FPA_AURAX_CNT(node, i));
+ oct_csr_write(0xfffffffffull, FPA_AURAX_CNT_LIMIT(node, i));
+ oct_csr_write(0xffffffffeull, FPA_AURAX_CNT_THRESHOLD(node, i));
+ }
+
+ data = oct_csr_read(FPA_GEN_CFG(node));
+ data &= ~GENMASK_ULL(9, 4);
+ data |= 3 << 4;
+ oct_csr_write(data, FPA_GEN_CFG(node));
+
+ init_done[node] = 1;
+ done:
+ mutex_unlock(&octeon_fpa3_lock);
+ return 0;
+}
+EXPORT_SYMBOL(octeon_fpa3_init);
+
+/**
+ * octeon_fpa3_pool_init - Initialize a pool.
+ * @node: Node to initialize pool on.
+ * @pool_num: Requested pool number (-1 for don't care).
+ * @pool: Updated with the initialized pool number.
+ * @pool_stack: Updated with the base of the memory allocated for the pool
+ * stack.
+ * @num_ptrs: Number of pointers to allocated on the stack.
+ *
+ * Returns 0 if successful.
+ * Returns <0 for error codes.
+ */
+int octeon_fpa3_pool_init(int node, int pool_num, int *pool, void **pool_stack, int num_ptrs)
+{
+ struct global_resource_tag tag;
+ char buf[16];
+ u64 pool_stack_start, pool_stack_end, data;
+ int stack_size, rc = 0;
+
+ mutex_lock(&octeon_fpa3_lock);
+
+ strncpy((char *)&tag.lo, "cvm_pool", 8);
+ snprintf(buf, 16, "_%d......", node);
+ memcpy(&tag.hi, buf, 8);
+
+ res_mgr_create_resource(tag, get_num_pools());
+ *pool = res_mgr_alloc(tag, pool_num, true);
+ if (*pool < 0) {
+ rc = -ENODEV;
+ goto error;
+ }
+
+ oct_csr_write(0, FPA_POOLX_CFG(node, *pool));
+ oct_csr_write(128, FPA_POOLX_START_ADDR(node, *pool));
+ oct_csr_write(GENMASK_ULL(41, 7), FPA_POOLX_END_ADDR(node, *pool));
+
+ stack_size = (DIV_ROUND_UP(num_ptrs, 29) + 1) * 128;
+ *pool_stack = kmalloc_node(stack_size, GFP_KERNEL, node);
+ if (!*pool_stack) {
+ pr_err("Failed to allocate pool stack memory pool=%d\n",
+ pool_num);
+ rc = -ENOMEM;
+ goto error_stack;
+ }
+
+ pool_stack_start = virt_to_phys(*pool_stack);
+ pool_stack_end = round_down(pool_stack_start + stack_size, 128);
+ pool_stack_start = round_up(pool_stack_start, 128);
+ oct_csr_write(pool_stack_start, FPA_POOLX_STACK_BASE(node, *pool));
+ oct_csr_write(pool_stack_start, FPA_POOLX_STACK_ADDR(node, *pool));
+ oct_csr_write(pool_stack_end, FPA_POOLX_STACK_END(node, *pool));
+
+ data = (2 << 3) | BIT(0);
+ oct_csr_write(data, FPA_POOLX_CFG(node, *pool));
+
+ mutex_unlock(&octeon_fpa3_lock);
+ return 0;
+
+error_stack:
+ res_mgr_free(tag, *pool);
+error:
+ mutex_unlock(&octeon_fpa3_lock);
+ return rc;
+}
+EXPORT_SYMBOL(octeon_fpa3_pool_init);
+
+/**
+ * octeon_fpa3_release_pool - Release a pool.
+ * @node: Node pool is on.
+ * @pool: Pool to release.
+ */
+void octeon_fpa3_release_pool(int node, int pool)
+{
+ struct global_resource_tag tag;
+ char buf[16];
+
+ mutex_lock(&octeon_fpa3_lock);
+
+ strncpy((char *)&tag.lo, "cvm_pool", 8);
+ snprintf(buf, 16, "_%d......", node);
+ memcpy(&tag.hi, buf, 8);
+
+ res_mgr_free(tag, pool);
+
+ mutex_unlock(&octeon_fpa3_lock);
+}
+EXPORT_SYMBOL(octeon_fpa3_release_pool);
+
+/**
+ * octeon_fpa3_aura_init - Initialize an aura.
+ * @node: Node to initialize aura on.
+ * @pool: Pool the aura belongs to.
+ * @aura_num: Requested aura number (-1 for don't care).
+ * @aura: Updated with the initialized aura number.
+ * @num_bufs: Number of buffers in the aura.
+ * @limit: Limit for the aura.
+ *
+ * Returns 0 if successful.
+ * Returns <0 for error codes.
+ */
+int octeon_fpa3_aura_init(int node, int pool, int aura_num, int *aura, int num_bufs, unsigned int limit)
+{
+ struct global_resource_tag tag;
+ char buf[16];
+ u64 data, shift;
+ unsigned int drop, pass;
+ int rc = 0;
+
+ mutex_lock(&octeon_fpa3_lock);
+
+ strncpy((char *)&tag.lo, "cvm_aura", 8);
+ snprintf(buf, 16, "_%d......", node);
+ memcpy(&tag.hi, buf, 8);
+
+ res_mgr_create_resource(tag, get_num_auras());
+ *aura = res_mgr_alloc(tag, aura_num, true);
+ if (*aura < 0) {
+ rc = -ENODEV;
+ goto error;
+ }
+
+ oct_csr_write(0, FPA_AURAX_CFG(node, *aura));
+
+ /* Allow twice the limit before saturation at zero */
+ limit *= 2;
+ data = limit;
+ oct_csr_write(data, FPA_AURAX_CNT_LIMIT(node, *aura));
+ oct_csr_write(data, FPA_AURAX_CNT(node, *aura));
+
+ oct_csr_write(pool, FPA_AURAX_POOL(node, *aura));
+
+ /* No per-pool RED/Drop */
+ oct_csr_write(0, FPA_AURAX_POOL_LEVELS(node, *aura));
+
+ shift = 0;
+ while ((limit >> shift) > 255)
+ shift++;
+
+ drop = (limit - num_bufs / 20) >> shift; /* 95% */
+ pass = (limit - (num_bufs * 3) / 20) >> shift; /* 85% */
+
+ /* Enable per aura RED/drop */
+ data = BIT(38) | (shift << 32) | (drop << 16) | (pass << 8);
+ oct_csr_write(data, FPA_AURAX_CNT_LEVELS(node, *aura));
+
+error:
+ mutex_unlock(&octeon_fpa3_lock);
+ return rc;
+}
+EXPORT_SYMBOL(octeon_fpa3_aura_init);
+
+/**
+ * octeon_fpa3_release_aura - Release an aura.
+ * @node: Node to aura is on.
+ * @aura: Aura to release.
+ */
+void octeon_fpa3_release_aura(int node, int aura)
+{
+ struct global_resource_tag tag;
+ char buf[16];
+
+ mutex_lock(&octeon_fpa3_lock);
+
+ strncpy((char *)&tag.lo, "cvm_aura", 8);
+ snprintf(buf, 16, "_%d......", node);
+ memcpy(&tag.hi, buf, 8);
+
+ res_mgr_free(tag, aura);
+
+ mutex_unlock(&octeon_fpa3_lock);
+}
+EXPORT_SYMBOL(octeon_fpa3_release_aura);
+
+/**
+ * octeon_fpa3_alloc - Get a buffer from a aura's pool.
+ * @node: Node to free memory to.
+ * @aura: Aura to free memory to.
+ *
+ * Returns allocated buffer pointer if successful
+ * Returns NULL on error.
+ */
+void *octeon_fpa3_alloc(u64 node, int aura)
+{
+ u64 buf_phys, addr;
+ void *buf = NULL;
+
+ /* Buffer pointers are obtained using load operations */
+ addr = BIT(63) | BIT(48) | (0x29ull << 40) | (node << 36) |
+ (aura << 16);
+ buf_phys = *(u64 *)addr;
+
+ if (buf_phys)
+ buf = phys_to_virt(buf_phys);
+
+ return buf;
+}
+EXPORT_SYMBOL(octeon_fpa3_alloc);
+
+/**
+ * octeon_fpa3_free - Add a buffer back to the aura's pool.
+ * @node: Node to free memory to.
+ * @aura: Aura to free memory to.
+ * @buf: Address of buffer to free to the aura's pool.
+ */
+void octeon_fpa3_free(u64 node, int aura, const void *buf)
+{
+ u64 buf_phys, addr;
+
+ buf_phys = virt_to_phys(buf);
+
+ /* Make sure that any previous writes to memory go out before we free
+ * this buffer. This also serves as a barrier to prevent GCC from
+ * reordering operations to after the free.
+ */
+ wmb();
+
+ /* Buffers are added to fpa pools using store operations */
+ addr = BIT(63) | BIT(48) | (0x29ull << 40) | (node << 36) | (aura << 16);
+ *(u64 *)addr = buf_phys;
+}
+EXPORT_SYMBOL(octeon_fpa3_free);
+
+/**
+ * octeon_fpa3_mem_fill - Add buffers to an aura.
+ * @node: Node to get memory from.
+ * @cache: Memory cache to allocate from.
+ * @aura: Aura to add buffers to.
+ * @num_bufs: Number of buffers to add to the aura.
+ *
+ * Returns 0 if successful.
+ * Returns <0 for error codes.
+ */
+int octeon_fpa3_mem_fill(int node, struct kmem_cache *cache, int aura, int num_bufs)
+{
+ void *mem;
+ int i, rc = 0;
+
+ mutex_lock(&octeon_fpa3_lock);
+
+ for (i = 0; i < num_bufs; i++) {
+ mem = kmem_cache_alloc_node(cache, GFP_KERNEL, node);
+ if (!mem) {
+ pr_err("Failed to allocate memory for aura=%d\n", aura);
+ rc = -ENOMEM;
+ break;
+ }
+ octeon_fpa3_free(node, aura, mem);
+ }
+
+ mutex_unlock(&octeon_fpa3_lock);
+ return rc;
+}
+EXPORT_SYMBOL(octeon_fpa3_mem_fill);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Cavium, Inc. Octeon III FPA manager.");
diff --git a/arch/mips/include/asm/octeon/octeon.h b/arch/mips/include/asm/octeon/octeon.h
index 0411efdb465c..d184592e6515 100644
--- a/arch/mips/include/asm/octeon/octeon.h
+++ b/arch/mips/include/asm/octeon/octeon.h
@@ -10,6 +10,7 @@

#include <asm/octeon/cvmx.h>
#include <asm/bitfield.h>
+#include <linux/slab.h>

extern uint64_t octeon_bootmem_alloc_range_phys(uint64_t size,
uint64_t alignment,
@@ -364,6 +365,20 @@ int res_mgr_alloc_range(struct global_resource_tag tag, int req_inst,
int req_cnt, bool use_last_avail, int *inst);
int res_mgr_create_resource(struct global_resource_tag tag, int inst_cnt);

+#if IS_ENABLED(CONFIG_OCTEON_FPA3)
+int octeon_fpa3_init(int node);
+int octeon_fpa3_pool_init(int node, int pool_num, int *pool, void **pool_stack,
+ int num_ptrs);
+int octeon_fpa3_aura_init(int node, int pool, int aura_num, int *aura,
+ int num_bufs, unsigned int limit);
+int octeon_fpa3_mem_fill(int node, struct kmem_cache *cache, int aura,
+ int num_bufs);
+void octeon_fpa3_free(u64 node, int aura, const void *buf);
+void *octeon_fpa3_alloc(u64 node, int aura);
+void octeon_fpa3_release_pool(int node, int pool);
+void octeon_fpa3_release_aura(int node, int aura);
+#endif
+
/**
* Read a 32bit value from the Octeon NPI register space
*
--
2.14.3


From 1585372293168946991@xxx Wed Nov 29 04:13:57 +0000 2017
X-GM-THRID: 1585372293168946991
X-Gmail-Labels: Inbox,Category Forums,HistoricalUnread