summaryrefslogtreecommitdiffstats
path: root/src/spdk/dpdk/drivers/common/octeontx
diff options
context:
space:
mode:
Diffstat (limited to 'src/spdk/dpdk/drivers/common/octeontx')
-rw-r--r--src/spdk/dpdk/drivers/common/octeontx/Makefile22
-rw-r--r--src/spdk/dpdk/drivers/common/octeontx/meson.build5
-rw-r--r--src/spdk/dpdk/drivers/common/octeontx/octeontx_mbox.c358
-rw-r--r--src/spdk/dpdk/drivers/common/octeontx/octeontx_mbox.h46
-rw-r--r--src/spdk/dpdk/drivers/common/octeontx/rte_common_octeontx_version.map12
5 files changed, 443 insertions, 0 deletions
diff --git a/src/spdk/dpdk/drivers/common/octeontx/Makefile b/src/spdk/dpdk/drivers/common/octeontx/Makefile
new file mode 100644
index 000000000..5e67df058
--- /dev/null
+++ b/src/spdk/dpdk/drivers/common/octeontx/Makefile
@@ -0,0 +1,22 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2018 Cavium, Inc
+#
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+#
+# library name
+#
+LIB = librte_common_octeontx.a
+
+CFLAGS += $(WERROR_FLAGS)
+EXPORT_MAP := rte_common_octeontx_version.map
+
+#
+# all source are stored in SRCS-y
+#
+SRCS-y += octeontx_mbox.c
+
+LDLIBS += -lrte_eal
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/src/spdk/dpdk/drivers/common/octeontx/meson.build b/src/spdk/dpdk/drivers/common/octeontx/meson.build
new file mode 100644
index 000000000..203d1ef49
--- /dev/null
+++ b/src/spdk/dpdk/drivers/common/octeontx/meson.build
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2018 Cavium, Inc
+#
+
+sources = files('octeontx_mbox.c')
diff --git a/src/spdk/dpdk/drivers/common/octeontx/octeontx_mbox.c b/src/spdk/dpdk/drivers/common/octeontx/octeontx_mbox.c
new file mode 100644
index 000000000..effe0b267
--- /dev/null
+++ b/src/spdk/dpdk/drivers/common/octeontx/octeontx_mbox.c
@@ -0,0 +1,358 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Cavium, Inc
+ */
+
+#include <string.h>
+
+#include <rte_atomic.h>
+#include <rte_common.h>
+#include <rte_cycles.h>
+#include <rte_io.h>
+#include <rte_spinlock.h>
+
+#include "octeontx_mbox.h"
+
+/* Mbox operation timeout in seconds */
+#define MBOX_WAIT_TIME_SEC 3
+#define MAX_RAM_MBOX_LEN ((SSOW_BAR4_LEN >> 1) - 8 /* Mbox header */)
+
+/* Mbox channel state */
+enum {
+ MBOX_CHAN_STATE_REQ = 1,
+ MBOX_CHAN_STATE_RES = 0,
+};
+
+/* Response messages */
+enum {
+ MBOX_RET_SUCCESS,
+ MBOX_RET_INVALID,
+ MBOX_RET_INTERNAL_ERR,
+};
+
+struct mbox {
+ int init_once;
+ uint8_t ready;
+ uint8_t *ram_mbox_base; /* Base address of mbox message stored in ram */
+ uint8_t *reg; /* Store to this register triggers PF mbox interrupt */
+ uint16_t tag_own; /* Last tag which was written to own channel */
+ uint16_t domain; /* Domain */
+ rte_spinlock_t lock;
+};
+
+static struct mbox octeontx_mbox;
+
+/*
+ * Structure used for mbox synchronization
+ * This structure sits at the begin of Mbox RAM and used as main
+ * synchronization point for channel communication
+ */
+struct mbox_ram_hdr {
+ union {
+ uint64_t u64;
+ struct {
+ uint8_t chan_state : 1;
+ uint8_t coproc : 7;
+ uint8_t msg;
+ uint8_t vfid;
+ uint8_t res_code;
+ uint16_t tag;
+ uint16_t len;
+ };
+ };
+};
+
+/* MBOX interface version message */
+struct mbox_intf_ver {
+ uint32_t platform:12;
+ uint32_t major:10;
+ uint32_t minor:10;
+};
+
+int octeontx_logtype_mbox;
+
+RTE_INIT(otx_init_log)
+{
+ octeontx_logtype_mbox = rte_log_register("pmd.octeontx.mbox");
+ if (octeontx_logtype_mbox >= 0)
+ rte_log_set_level(octeontx_logtype_mbox, RTE_LOG_NOTICE);
+}
+
+static inline void
+mbox_msgcpy(volatile uint8_t *d, volatile const uint8_t *s, uint16_t size)
+{
+ uint16_t i;
+
+ for (i = 0; i < size; i++)
+ d[i] = s[i];
+}
+
+static inline void
+mbox_send_request(struct mbox *m, struct octeontx_mbox_hdr *hdr,
+ const void *txmsg, uint16_t txsize)
+{
+ struct mbox_ram_hdr old_hdr;
+ struct mbox_ram_hdr new_hdr = { {0} };
+ uint64_t *ram_mbox_hdr = (uint64_t *)m->ram_mbox_base;
+ uint8_t *ram_mbox_msg = m->ram_mbox_base + sizeof(struct mbox_ram_hdr);
+
+ /*
+ * Initialize the channel with the tag left by last send.
+ * On success full mbox send complete, PF increments the tag by one.
+ * The sender can validate integrity of PF message with this scheme
+ */
+ old_hdr.u64 = rte_read64(ram_mbox_hdr);
+ m->tag_own = (old_hdr.tag + 2) & (~0x1ul); /* next even number */
+
+ /* Copy msg body */
+ if (txmsg)
+ mbox_msgcpy(ram_mbox_msg, txmsg, txsize);
+
+ /* Prepare new hdr */
+ new_hdr.chan_state = MBOX_CHAN_STATE_REQ;
+ new_hdr.coproc = hdr->coproc;
+ new_hdr.msg = hdr->msg;
+ new_hdr.vfid = hdr->vfid;
+ new_hdr.tag = m->tag_own;
+ new_hdr.len = txsize;
+
+ /* Write the msg header */
+ rte_write64(new_hdr.u64, ram_mbox_hdr);
+ rte_smp_wmb();
+ /* Notify PF about the new msg - write to MBOX reg generates PF IRQ */
+ rte_write64(0, m->reg);
+}
+
+static inline int
+mbox_wait_response(struct mbox *m, struct octeontx_mbox_hdr *hdr,
+ void *rxmsg, uint16_t rxsize)
+{
+ int res = 0, wait;
+ uint16_t len;
+ struct mbox_ram_hdr rx_hdr;
+ uint64_t *ram_mbox_hdr = (uint64_t *)m->ram_mbox_base;
+ uint8_t *ram_mbox_msg = m->ram_mbox_base + sizeof(struct mbox_ram_hdr);
+
+ /* Wait for response */
+ wait = MBOX_WAIT_TIME_SEC * 1000 * 10;
+ while (wait > 0) {
+ rte_delay_us(100);
+ rx_hdr.u64 = rte_read64(ram_mbox_hdr);
+ if (rx_hdr.chan_state == MBOX_CHAN_STATE_RES)
+ break;
+ --wait;
+ }
+
+ hdr->res_code = rx_hdr.res_code;
+ m->tag_own++;
+
+ /* Timeout */
+ if (wait <= 0) {
+ res = -ETIMEDOUT;
+ goto error;
+ }
+
+ /* Tag mismatch */
+ if (m->tag_own != rx_hdr.tag) {
+ res = -EINVAL;
+ goto error;
+ }
+
+ /* PF nacked the msg */
+ if (rx_hdr.res_code != MBOX_RET_SUCCESS) {
+ res = -EBADMSG;
+ goto error;
+ }
+
+ len = RTE_MIN(rx_hdr.len, rxsize);
+ if (rxmsg)
+ mbox_msgcpy(rxmsg, ram_mbox_msg, len);
+
+ return len;
+
+error:
+ mbox_log_err("Failed to send mbox(%d/%d) coproc=%d msg=%d ret=(%d,%d)",
+ m->tag_own, rx_hdr.tag, hdr->coproc, hdr->msg, res,
+ hdr->res_code);
+ return res;
+}
+
+static inline int
+mbox_send(struct mbox *m, struct octeontx_mbox_hdr *hdr, const void *txmsg,
+ uint16_t txsize, void *rxmsg, uint16_t rxsize)
+{
+ int res = -EINVAL;
+
+ if (m->init_once == 0 || hdr == NULL ||
+ txsize > MAX_RAM_MBOX_LEN || rxsize > MAX_RAM_MBOX_LEN) {
+ mbox_log_err("Invalid init_once=%d hdr=%p txsz=%d rxsz=%d",
+ m->init_once, hdr, txsize, rxsize);
+ return res;
+ }
+
+ rte_spinlock_lock(&m->lock);
+
+ mbox_send_request(m, hdr, txmsg, txsize);
+ res = mbox_wait_response(m, hdr, rxmsg, rxsize);
+
+ rte_spinlock_unlock(&m->lock);
+ return res;
+}
+
+int
+octeontx_mbox_set_ram_mbox_base(uint8_t *ram_mbox_base, uint16_t domain)
+{
+ struct mbox *m = &octeontx_mbox;
+
+ if (m->init_once)
+ return -EALREADY;
+
+ if (ram_mbox_base == NULL) {
+ mbox_log_err("Invalid ram_mbox_base=%p", ram_mbox_base);
+ return -EINVAL;
+ }
+
+ m->ram_mbox_base = ram_mbox_base;
+
+ if (m->reg != NULL) {
+ rte_spinlock_init(&m->lock);
+ m->init_once = 1;
+ m->domain = domain;
+ }
+
+ return 0;
+}
+
+int
+octeontx_mbox_set_reg(uint8_t *reg, uint16_t domain)
+{
+ struct mbox *m = &octeontx_mbox;
+
+ if (m->init_once)
+ return -EALREADY;
+
+ if (reg == NULL) {
+ mbox_log_err("Invalid reg=%p", reg);
+ return -EINVAL;
+ }
+
+ m->reg = reg;
+
+ if (m->ram_mbox_base != NULL) {
+ rte_spinlock_init(&m->lock);
+ m->init_once = 1;
+ m->domain = domain;
+ }
+
+ return 0;
+}
+
+int
+octeontx_mbox_send(struct octeontx_mbox_hdr *hdr, void *txdata,
+ uint16_t txlen, void *rxdata, uint16_t rxlen)
+{
+ struct mbox *m = &octeontx_mbox;
+
+ RTE_BUILD_BUG_ON(sizeof(struct mbox_ram_hdr) != 8);
+ if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+ return -EINVAL;
+
+ return mbox_send(m, hdr, txdata, txlen, rxdata, rxlen);
+}
+
+static int
+octeontx_start_domain(void)
+{
+ struct octeontx_mbox_hdr hdr = {0};
+ int result = -EINVAL;
+
+ hdr.coproc = NO_COPROC;
+ hdr.msg = RM_START_APP;
+
+ result = octeontx_mbox_send(&hdr, NULL, 0, NULL, 0);
+ if (result != 0) {
+ mbox_log_err("Could not start domain. Err=%d. FuncErr=%d\n",
+ result, hdr.res_code);
+ result = -EINVAL;
+ }
+
+ return result;
+}
+
+static int
+octeontx_check_mbox_version(struct mbox_intf_ver *app_intf_ver,
+ struct mbox_intf_ver *intf_ver)
+{
+ struct mbox_intf_ver kernel_intf_ver = {0};
+ struct octeontx_mbox_hdr hdr = {0};
+ int result = 0;
+
+
+ hdr.coproc = NO_COPROC;
+ hdr.msg = RM_INTERFACE_VERSION;
+
+ result = octeontx_mbox_send(&hdr, app_intf_ver,
+ sizeof(struct mbox_intf_ver),
+ &kernel_intf_ver, sizeof(kernel_intf_ver));
+ if (result != sizeof(kernel_intf_ver)) {
+ mbox_log_err("Could not send interface version. Err=%d. FuncErr=%d\n",
+ result, hdr.res_code);
+ result = -EINVAL;
+ }
+
+ if (intf_ver)
+ *intf_ver = kernel_intf_ver;
+
+ if (app_intf_ver->platform != kernel_intf_ver.platform ||
+ app_intf_ver->major != kernel_intf_ver.major ||
+ app_intf_ver->minor != kernel_intf_ver.minor)
+ result = -EINVAL;
+
+ return result;
+}
+
+int
+octeontx_mbox_init(void)
+{
+ struct mbox_intf_ver MBOX_INTERFACE_VERSION = {
+ .platform = 0x01,
+ .major = 0x01,
+ .minor = 0x03
+ };
+ struct mbox_intf_ver rm_intf_ver = {0};
+ struct mbox *m = &octeontx_mbox;
+ int ret;
+
+ if (m->ready)
+ return 0;
+
+ ret = octeontx_start_domain();
+ if (ret < 0) {
+ m->init_once = 0;
+ return ret;
+ }
+
+ ret = octeontx_check_mbox_version(&MBOX_INTERFACE_VERSION,
+ &rm_intf_ver);
+ if (ret < 0) {
+ mbox_log_err("MBOX version: Kernel(%d.%d.%d) != DPDK(%d.%d.%d)",
+ rm_intf_ver.platform, rm_intf_ver.major,
+ rm_intf_ver.minor, MBOX_INTERFACE_VERSION.platform,
+ MBOX_INTERFACE_VERSION.major,
+ MBOX_INTERFACE_VERSION.minor);
+ m->init_once = 0;
+ return -EINVAL;
+ }
+
+ m->ready = 1;
+ rte_mb();
+
+ return 0;
+}
+
+uint16_t
+octeontx_get_global_domain(void)
+{
+ struct mbox *m = &octeontx_mbox;
+
+ return m->domain;
+}
diff --git a/src/spdk/dpdk/drivers/common/octeontx/octeontx_mbox.h b/src/spdk/dpdk/drivers/common/octeontx/octeontx_mbox.h
new file mode 100644
index 000000000..e56719cb8
--- /dev/null
+++ b/src/spdk/dpdk/drivers/common/octeontx/octeontx_mbox.h
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Cavium, Inc
+ */
+
+#ifndef __OCTEONTX_MBOX_H__
+#define __OCTEONTX_MBOX_H__
+
+#include <rte_common.h>
+#include <rte_spinlock.h>
+
+#define SSOW_BAR4_LEN (64 * 1024)
+#define SSO_VHGRP_PF_MBOX(x) (0x200ULL | ((x) << 3))
+
+#define NO_COPROC 0x0
+#define RM_START_APP 0x1
+#define RM_INTERFACE_VERSION 0x2
+
+
+#define MBOX_LOG(level, fmt, args...) \
+ rte_log(RTE_LOG_ ## level, octeontx_logtype_mbox,\
+ "%s() line %u: " fmt "\n", __func__, __LINE__, ## args)
+
+#define mbox_log_info(fmt, ...) MBOX_LOG(INFO, fmt, ##__VA_ARGS__)
+#define mbox_log_dbg(fmt, ...) MBOX_LOG(DEBUG, fmt, ##__VA_ARGS__)
+#define mbox_log_err(fmt, ...) MBOX_LOG(ERR, fmt, ##__VA_ARGS__)
+#define mbox_func_trace mbox_log_dbg
+
+extern int octeontx_logtype_mbox;
+
+struct octeontx_mbox_hdr {
+ uint16_t vfid; /* VF index or pf resource index local to the domain */
+ uint8_t coproc; /* Coprocessor id */
+ uint8_t msg; /* Message id */
+ uint8_t oob; /* out of band data */
+ uint8_t res_code; /* Functional layer response code */
+};
+
+int octeontx_mbox_init(void);
+void octeontx_set_global_domain(uint16_t global_domain);
+uint16_t octeontx_get_global_domain(void);
+int octeontx_mbox_set_ram_mbox_base(uint8_t *ram_mbox_base, uint16_t domain);
+int octeontx_mbox_set_reg(uint8_t *reg, uint16_t domain);
+int octeontx_mbox_send(struct octeontx_mbox_hdr *hdr,
+ void *txdata, uint16_t txlen, void *rxdata, uint16_t rxlen);
+
+#endif /* __OCTEONTX_MBOX_H__ */
diff --git a/src/spdk/dpdk/drivers/common/octeontx/rte_common_octeontx_version.map b/src/spdk/dpdk/drivers/common/octeontx/rte_common_octeontx_version.map
new file mode 100644
index 000000000..5f6aa8bd3
--- /dev/null
+++ b/src/spdk/dpdk/drivers/common/octeontx/rte_common_octeontx_version.map
@@ -0,0 +1,12 @@
+DPDK_20.0 {
+ global:
+
+ octeontx_get_global_domain;
+ octeontx_logtype_mbox;
+ octeontx_mbox_init;
+ octeontx_mbox_send;
+ octeontx_mbox_set_ram_mbox_base;
+ octeontx_mbox_set_reg;
+
+ local: *;
+};