summaryrefslogtreecommitdiffstats
path: root/drivers/net/octeontx/base
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/octeontx/base')
-rw-r--r--drivers/net/octeontx/base/octeontx_bgx.c273
-rw-r--r--drivers/net/octeontx/base/octeontx_bgx.h150
-rw-r--r--drivers/net/octeontx/base/octeontx_io.h156
-rw-r--r--drivers/net/octeontx/base/octeontx_pki_var.h237
-rw-r--r--drivers/net/octeontx/base/octeontx_pkivf.c169
-rw-r--r--drivers/net/octeontx/base/octeontx_pkivf.h553
-rw-r--r--drivers/net/octeontx/base/octeontx_pkovf.c617
-rw-r--r--drivers/net/octeontx/base/octeontx_pkovf.h97
8 files changed, 2252 insertions, 0 deletions
diff --git a/drivers/net/octeontx/base/octeontx_bgx.c b/drivers/net/octeontx/base/octeontx_bgx.c
new file mode 100644
index 00000000..c2d0d433
--- /dev/null
+++ b/drivers/net/octeontx/base/octeontx_bgx.c
@@ -0,0 +1,273 @@
+/*
+ * BSD LICENSE
+ *
+ * Copyright (C) Cavium Inc. 2017. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Cavium networks nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <string.h>
+
+#include "octeontx_bgx.h"
+
+int
+octeontx_bgx_port_open(int port, octeontx_mbox_bgx_port_conf_t *conf)
+{
+ struct octeontx_mbox_hdr hdr;
+ octeontx_mbox_bgx_port_conf_t bgx_conf;
+ int len = sizeof(octeontx_mbox_bgx_port_conf_t);
+ int res;
+
+ memset(&bgx_conf, 0, sizeof(octeontx_mbox_bgx_port_conf_t));
+ hdr.coproc = OCTEONTX_BGX_COPROC;
+ hdr.msg = MBOX_BGX_PORT_OPEN;
+ hdr.vfid = port;
+
+ res = octeontx_ssovf_mbox_send(&hdr, NULL, 0, &bgx_conf, len);
+ if (res < 0)
+ return -EACCES;
+
+ conf->enable = bgx_conf.enable;
+ conf->promisc = bgx_conf.promisc;
+ conf->bpen = bgx_conf.bpen;
+ conf->node = bgx_conf.node;
+ conf->base_chan = bgx_conf.base_chan;
+ conf->num_chans = bgx_conf.num_chans;
+ conf->mtu = bgx_conf.mtu;
+ conf->bgx = bgx_conf.bgx;
+ conf->lmac = bgx_conf.lmac;
+ conf->mode = bgx_conf.mode;
+ conf->pkind = bgx_conf.pkind;
+ memcpy(conf->macaddr, bgx_conf.macaddr, 6);
+
+ return res;
+}
+
+int
+octeontx_bgx_port_close(int port)
+{
+ struct octeontx_mbox_hdr hdr;
+ int res;
+
+ hdr.coproc = OCTEONTX_BGX_COPROC;
+ hdr.msg = MBOX_BGX_PORT_CLOSE;
+ hdr.vfid = port;
+
+ res = octeontx_ssovf_mbox_send(&hdr, NULL, 0, NULL, 0);
+ if (res < 0)
+ return -EACCES;
+
+ return res;
+}
+
+int
+octeontx_bgx_port_start(int port)
+{
+ struct octeontx_mbox_hdr hdr;
+ int res;
+
+ hdr.coproc = OCTEONTX_BGX_COPROC;
+ hdr.msg = MBOX_BGX_PORT_START;
+ hdr.vfid = port;
+
+ res = octeontx_ssovf_mbox_send(&hdr, NULL, 0, NULL, 0);
+ if (res < 0)
+ return -EACCES;
+
+ return res;
+}
+
+int
+octeontx_bgx_port_stop(int port)
+{
+ struct octeontx_mbox_hdr hdr;
+ int res;
+
+ hdr.coproc = OCTEONTX_BGX_COPROC;
+ hdr.msg = MBOX_BGX_PORT_STOP;
+ hdr.vfid = port;
+
+ res = octeontx_ssovf_mbox_send(&hdr, NULL, 0, NULL, 0);
+ if (res < 0)
+ return -EACCES;
+
+ return res;
+}
+
+int
+octeontx_bgx_port_get_config(int port, octeontx_mbox_bgx_port_conf_t *conf)
+{
+ struct octeontx_mbox_hdr hdr;
+ octeontx_mbox_bgx_port_conf_t bgx_conf;
+ int len = sizeof(octeontx_mbox_bgx_port_conf_t);
+ int res;
+
+ hdr.coproc = OCTEONTX_BGX_COPROC;
+ hdr.msg = MBOX_BGX_PORT_GET_CONFIG;
+ hdr.vfid = port;
+
+ memset(&bgx_conf, 0, sizeof(octeontx_mbox_bgx_port_conf_t));
+ res = octeontx_ssovf_mbox_send(&hdr, NULL, 0, &bgx_conf, len);
+ if (res < 0)
+ return -EACCES;
+
+ conf->enable = bgx_conf.enable;
+ conf->promisc = bgx_conf.promisc;
+ conf->bpen = bgx_conf.bpen;
+ conf->node = bgx_conf.node;
+ conf->base_chan = bgx_conf.base_chan;
+ conf->num_chans = bgx_conf.num_chans;
+ conf->mtu = bgx_conf.mtu;
+ conf->bgx = bgx_conf.bgx;
+ conf->lmac = bgx_conf.lmac;
+ conf->mode = bgx_conf.mode;
+ conf->pkind = bgx_conf.pkind;
+ memcpy(conf->macaddr, bgx_conf.macaddr, 6);
+
+ return res;
+}
+
+int
+octeontx_bgx_port_status(int port, octeontx_mbox_bgx_port_status_t *stat)
+{
+ struct octeontx_mbox_hdr hdr;
+ octeontx_mbox_bgx_port_status_t bgx_stat;
+ int len = sizeof(octeontx_mbox_bgx_port_status_t);
+ int res;
+
+ hdr.coproc = OCTEONTX_BGX_COPROC;
+ hdr.msg = MBOX_BGX_PORT_GET_STATUS;
+ hdr.vfid = port;
+
+ res = octeontx_ssovf_mbox_send(&hdr, NULL, 0, &bgx_stat, len);
+ if (res < 0)
+ return -EACCES;
+
+ stat->link_up = bgx_stat.link_up;
+
+ return res;
+}
+
+int
+octeontx_bgx_port_stats(int port, octeontx_mbox_bgx_port_stats_t *stats)
+{
+ struct octeontx_mbox_hdr hdr;
+ octeontx_mbox_bgx_port_stats_t bgx_stats;
+ int len = sizeof(octeontx_mbox_bgx_port_stats_t);
+ int res;
+
+ hdr.coproc = OCTEONTX_BGX_COPROC;
+ hdr.msg = MBOX_BGX_PORT_GET_STATS;
+ hdr.vfid = port;
+
+ res = octeontx_ssovf_mbox_send(&hdr, NULL, 0, &bgx_stats, len);
+ if (res < 0)
+ return -EACCES;
+
+ stats->rx_packets = bgx_stats.rx_packets;
+ stats->rx_bytes = bgx_stats.rx_bytes;
+ stats->rx_dropped = bgx_stats.rx_dropped;
+ stats->rx_errors = bgx_stats.rx_errors;
+ stats->tx_packets = bgx_stats.tx_packets;
+ stats->tx_bytes = bgx_stats.tx_bytes;
+ stats->tx_dropped = bgx_stats.tx_dropped;
+ stats->tx_errors = bgx_stats.tx_errors;
+ return res;
+}
+
+int
+octeontx_bgx_port_stats_clr(int port)
+{
+ struct octeontx_mbox_hdr hdr;
+ int res;
+
+ hdr.coproc = OCTEONTX_BGX_COPROC;
+ hdr.msg = MBOX_BGX_PORT_CLR_STATS;
+ hdr.vfid = port;
+
+ res = octeontx_ssovf_mbox_send(&hdr, NULL, 0, NULL, 0);
+ if (res < 0)
+ return -EACCES;
+
+ return res;
+}
+
+int
+octeontx_bgx_port_link_status(int port)
+{
+ struct octeontx_mbox_hdr hdr;
+ uint8_t link;
+ int len = sizeof(uint8_t);
+ int res;
+
+ hdr.coproc = OCTEONTX_BGX_COPROC;
+ hdr.msg = MBOX_BGX_PORT_GET_LINK_STATUS;
+ hdr.vfid = port;
+
+ res = octeontx_ssovf_mbox_send(&hdr, NULL, 0, &link, len);
+ if (res < 0)
+ return -EACCES;
+
+ return link;
+}
+
+int
+octeontx_bgx_port_promisc_set(int port, int en)
+{
+ struct octeontx_mbox_hdr hdr;
+ uint8_t prom;
+ int res;
+
+ hdr.coproc = OCTEONTX_BGX_COPROC;
+ hdr.msg = MBOX_BGX_PORT_SET_PROMISC;
+ hdr.vfid = port;
+ prom = en ? 1 : 0;
+
+ res = octeontx_ssovf_mbox_send(&hdr, &prom, sizeof(prom), NULL, 0);
+ if (res < 0)
+ return -EACCES;
+
+ return res;
+}
+
+int
+octeontx_bgx_port_mac_set(int port, uint8_t *mac_addr)
+{
+ struct octeontx_mbox_hdr hdr;
+ int len = 6;
+ int res = 0;
+
+ hdr.coproc = OCTEONTX_BGX_COPROC;
+ hdr.msg = MBOX_BGX_PORT_SET_MACADDR;
+ hdr.vfid = port;
+
+ res = octeontx_ssovf_mbox_send(&hdr, mac_addr, len, NULL, 0);
+ if (res < 0)
+ return -EACCES;
+
+ return res;
+}
diff --git a/drivers/net/octeontx/base/octeontx_bgx.h b/drivers/net/octeontx/base/octeontx_bgx.h
new file mode 100644
index 00000000..f740a1d9
--- /dev/null
+++ b/drivers/net/octeontx/base/octeontx_bgx.h
@@ -0,0 +1,150 @@
+/*
+ * BSD LICENSE
+ *
+ * Copyright (C) Cavium Inc. 2017. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Cavium networks nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __OCTEONTX_BGX_H__
+#define __OCTEONTX_BGX_H__
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <octeontx_mbox.h>
+
+#define OCTEONTX_BGX_COPROC 6
+
+/* BGX messages */
+#define MBOX_BGX_PORT_OPEN 0
+#define MBOX_BGX_PORT_CLOSE 1
+#define MBOX_BGX_PORT_START 2
+#define MBOX_BGX_PORT_STOP 3
+#define MBOX_BGX_PORT_GET_CONFIG 4
+#define MBOX_BGX_PORT_GET_STATUS 5
+#define MBOX_BGX_PORT_GET_STATS 6
+#define MBOX_BGX_PORT_CLR_STATS 7
+#define MBOX_BGX_PORT_GET_LINK_STATUS 8
+#define MBOX_BGX_PORT_SET_PROMISC 9
+#define MBOX_BGX_PORT_SET_MACADDR 10
+#define MBOX_BGX_PORT_SET_BP 11
+#define MBOX_BGX_PORT_SET_BCAST 12
+#define MBOX_BGX_PORT_SET_MCAST 13
+
+/* BGX port configuration parameters: */
+typedef struct octeontx_mbox_bgx_port_conf {
+ uint8_t enable;
+ uint8_t promisc;
+ uint8_t bpen;
+ uint8_t macaddr[6]; /* MAC address.*/
+ uint8_t fcs_strip;
+ uint8_t bcast_mode;
+ uint8_t mcast_mode;
+ uint8_t node; /* CPU node */
+ uint16_t base_chan;
+ uint16_t num_chans;
+ uint16_t mtu;
+ uint8_t bgx;
+ uint8_t lmac;
+ uint8_t mode;
+ uint8_t pkind;
+} octeontx_mbox_bgx_port_conf_t;
+
+/* BGX port status: */
+typedef struct octeontx_mbox_bgx_port_status {
+ uint8_t link_up;
+ uint8_t bp;
+} octeontx_mbox_bgx_port_status_t;
+
+/* BGX port statistics: */
+typedef struct octeontx_mbox_bgx_port_stats {
+ uint64_t rx_packets;
+ uint64_t tx_packets;
+ uint64_t rx_bytes;
+ uint64_t tx_bytes;
+ uint64_t rx_errors;
+ uint64_t tx_errors;
+ uint64_t rx_dropped;
+ uint64_t tx_dropped;
+ uint64_t multicast;
+ uint64_t collisions;
+
+ uint64_t rx_length_errors;
+ uint64_t rx_over_errors;
+ uint64_t rx_crc_errors;
+ uint64_t rx_frame_errors;
+ uint64_t rx_fifo_errors;
+ uint64_t rx_missed_errors;
+
+ /* Detailed transmit errors. */
+ uint64_t tx_aborted_errors;
+ uint64_t tx_carrier_errors;
+ uint64_t tx_fifo_errors;
+ uint64_t tx_heartbeat_errors;
+ uint64_t tx_window_errors;
+
+ /* Extended statistics based on RFC2819. */
+ uint64_t rx_1_to_64_packets;
+ uint64_t rx_65_to_127_packets;
+ uint64_t rx_128_to_255_packets;
+ uint64_t rx_256_to_511_packets;
+ uint64_t rx_512_to_1023_packets;
+ uint64_t rx_1024_to_1522_packets;
+ uint64_t rx_1523_to_max_packets;
+
+ uint64_t tx_1_to_64_packets;
+ uint64_t tx_65_to_127_packets;
+ uint64_t tx_128_to_255_packets;
+ uint64_t tx_256_to_511_packets;
+ uint64_t tx_512_to_1023_packets;
+ uint64_t tx_1024_to_1522_packets;
+ uint64_t tx_1523_to_max_packets;
+
+ uint64_t tx_multicast_packets;
+ uint64_t rx_broadcast_packets;
+ uint64_t tx_broadcast_packets;
+ uint64_t rx_undersized_errors;
+ uint64_t rx_oversize_errors;
+ uint64_t rx_fragmented_errors;
+ uint64_t rx_jabber_errors;
+} octeontx_mbox_bgx_port_stats_t;
+
+int octeontx_bgx_port_open(int port, octeontx_mbox_bgx_port_conf_t *conf);
+int octeontx_bgx_port_close(int port);
+int octeontx_bgx_port_start(int port);
+int octeontx_bgx_port_stop(int port);
+int octeontx_bgx_port_get_config(int port, octeontx_mbox_bgx_port_conf_t *conf);
+int octeontx_bgx_port_status(int port, octeontx_mbox_bgx_port_status_t *stat);
+int octeontx_bgx_port_stats(int port, octeontx_mbox_bgx_port_stats_t *stats);
+int octeontx_bgx_port_stats_clr(int port);
+int octeontx_bgx_port_link_status(int port);
+int octeontx_bgx_port_promisc_set(int port, int en);
+int octeontx_bgx_port_mac_set(int port, uint8_t *mac_addr);
+
+#endif /* __OCTEONTX_BGX_H__ */
+
diff --git a/drivers/net/octeontx/base/octeontx_io.h b/drivers/net/octeontx/base/octeontx_io.h
new file mode 100644
index 00000000..ec4ce1dc
--- /dev/null
+++ b/drivers/net/octeontx/base/octeontx_io.h
@@ -0,0 +1,156 @@
+/*
+ * BSD LICENSE
+ *
+ * Copyright (C) Cavium Inc. 2017. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Cavium networks nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __OCTEONTX_IO_H__
+#define __OCTEONTX_IO_H__
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <rte_io.h>
+
+/* In Cavium OcteonTX SoC, all accesses to the device registers are
+ * implicitly strongly ordered. So, The relaxed version of IO operation is
+ * safe to use with out any IO memory barriers.
+ */
+#define octeontx_read64 rte_read64_relaxed
+#define octeontx_write64 rte_write64_relaxed
+
+/* ARM64 specific functions */
+#if defined(RTE_ARCH_ARM64)
+#define octeontx_prefetch_store_keep(_ptr) ({\
+ asm volatile("prfm pstl1keep, %a0\n" : : "p" (_ptr)); })
+
+#define octeontx_load_pair(val0, val1, addr) ({ \
+ asm volatile( \
+ "ldp %x[x0], %x[x1], [%x[p1]]" \
+ :[x0]"=r"(val0), [x1]"=r"(val1) \
+ :[p1]"r"(addr) \
+ ); })
+
+#define octeontx_store_pair(val0, val1, addr) ({ \
+ asm volatile( \
+ "stp %x[x0], %x[x1], [%x[p1]]" \
+ ::[x0]"r"(val0), [x1]"r"(val1), [p1]"r"(addr) \
+ ); })
+#else /* Un optimized functions for building on non arm64 arch */
+
+#define octeontx_prefetch_store_keep(_ptr) do {} while (0)
+
+#define octeontx_load_pair(val0, val1, addr) \
+do { \
+ val0 = rte_read64(addr); \
+ val1 = rte_read64(((uint8_t *)addr) + 8); \
+} while (0)
+
+#define octeontx_store_pair(val0, val1, addr) \
+do { \
+ rte_write64(val0, addr); \
+ rte_write64(val1, (((uint8_t *)addr) + 8)); \
+} while (0)
+#endif
+
+#if defined(RTE_ARCH_ARM64)
+/**
+ * Perform an atomic fetch-and-add operation.
+ */
+static inline uint64_t
+octeontx_reg_ldadd_u64(void *addr, int64_t off)
+{
+ uint64_t old_val;
+
+ __asm__ volatile(
+ " .cpu generic+lse\n"
+ " ldadd %1, %0, [%2]\n"
+ : "=r" (old_val) : "r" (off), "r" (addr) : "memory");
+
+ return old_val;
+}
+
+/**
+ * Perform a LMTST operation - an atomic write of up to 128 byte to
+ * an I/O block that supports this operation type.
+ *
+ * @param lmtline_va is the address where LMTLINE is mapped
+ * @param ioreg_va is the virtual address of the device register
+ * @param cmdbuf is the array of peripheral commands to execute
+ * @param cmdsize is the number of 64-bit words in 'cmdbuf'
+ *
+ * @return N/A
+ */
+static inline void
+octeontx_reg_lmtst(void *lmtline_va, void *ioreg_va, const uint64_t cmdbuf[],
+ uint64_t cmdsize)
+{
+ uint64_t result;
+ uint64_t word_count;
+ uint64_t *lmtline = lmtline_va;
+
+ word_count = cmdsize;
+
+ do {
+ /* Copy commands to LMTLINE */
+ for (result = 0; result < word_count; result += 2) {
+ lmtline[result + 0] = cmdbuf[result + 0];
+ lmtline[result + 1] = cmdbuf[result + 1];
+ }
+
+ /* LDEOR initiates atomic transfer to I/O device */
+ __asm__ volatile(
+ " .cpu generic+lse\n"
+ " ldeor xzr, %0, [%1]\n"
+ : "=r" (result) : "r" (ioreg_va) : "memory");
+ } while (!result);
+}
+
+#else
+
+static inline uint64_t
+octeontx_reg_ldadd_u64(void *addr, int64_t off)
+{
+ RTE_SET_USED(addr);
+ RTE_SET_USED(off);
+ return 0;
+}
+
+static inline void
+octeontx_reg_lmtst(void *lmtline_va, void *ioreg_va, const uint64_t cmdbuf[],
+ uint64_t cmdsize)
+{
+ RTE_SET_USED(lmtline_va);
+ RTE_SET_USED(ioreg_va);
+ RTE_SET_USED(cmdbuf);
+ RTE_SET_USED(cmdsize);
+}
+
+#endif
+#endif /* __OCTEONTX_IO_H__ */
diff --git a/drivers/net/octeontx/base/octeontx_pki_var.h b/drivers/net/octeontx/base/octeontx_pki_var.h
new file mode 100644
index 00000000..def6cbb9
--- /dev/null
+++ b/drivers/net/octeontx/base/octeontx_pki_var.h
@@ -0,0 +1,237 @@
+/*
+ * BSD LICENSE
+ *
+ * Copyright (C) Cavium Inc. 2017. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Cavium networks nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __OCTEONTX_PKI_VAR_H__
+#define __OCTEONTX_PKI_VAR_H__
+
+#include <rte_byteorder.h>
+
+#define OCTTX_PACKET_WQE_SKIP 128
+#define OCTTX_PACKET_FIRST_SKIP 240
+#define OCTTX_PACKET_LATER_SKIP 128
+
+/* WQE descriptor */
+typedef union octtx_wqe_s {
+ uint64_t w[6];
+
+ struct {
+#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
+ struct {
+ uint64_t pknd : 6;
+ uint64_t rsvd0 : 10;
+ uint64_t style : 8;
+ uint64_t bufs : 8;
+ uint64_t chan : 12;
+ uint64_t apad : 3;
+ uint64_t rsvd1 : 1;
+ uint64_t aura : 12;
+ uint64_t rsvd2 : 4;
+ } w0;
+
+ struct {
+ uint64_t tag : 32;
+ uint64_t tt : 2;
+ uint64_t grp : 10;
+ uint64_t rsvd0 : 2;
+ uint64_t rsvd1 : 2;
+ uint64_t len : 16;
+ } w1;
+
+ struct {
+ uint64_t op_code : 8;
+ uint64_t err_lev : 3;
+ uint64_t raw : 1;
+ uint64_t l2m : 1;
+ uint64_t l2b : 1;
+ uint64_t l3m : 1;
+ uint64_t l3b : 1;
+ uint64_t l3fr : 1;
+ uint64_t pf1 : 1;
+ uint64_t pf2 : 1;
+ uint64_t pf3 : 1;
+ uint64_t pf4 : 1;
+ uint64_t sh : 1;
+ uint64_t vs : 1;
+ uint64_t vv : 1;
+ uint64_t rsvd0 : 8;
+ uint64_t lae : 1;
+ uint64_t lbty : 5;
+ uint64_t lcty : 5;
+ uint64_t ldty : 5;
+ uint64_t lety : 5;
+ uint64_t lfty : 5;
+ uint64_t lgty : 5;
+ uint64_t sw : 1;
+ } w2;
+
+ struct {
+ uint64_t addr; /* Byte addr of start-of-pkt */
+ } w3;
+
+ struct {
+ uint64_t laptr : 8;
+ uint64_t lbptr : 8;
+ uint64_t lcptr : 8;
+ uint64_t ldprt : 8;
+ uint64_t leptr : 8;
+ uint64_t lfptr : 8;
+ uint64_t lgptr : 8;
+ uint64_t vlptr : 8;
+ } w4;
+
+ struct {
+ uint64_t rsvd0 : 47;
+ uint64_t dwd : 1;
+ uint64_t size : 16;
+ } w5;
+#else
+ struct {
+ uint64_t rsvd2 : 4;
+ uint64_t aura : 12;
+ uint64_t rsvd1 : 1;
+ uint64_t apad : 3;
+ uint64_t chan : 12;
+ uint64_t bufs : 8;
+ uint64_t style : 8;
+ uint64_t rsvd0 : 10;
+ uint64_t pknd : 6;
+ } w0;
+
+ struct {
+ uint64_t len : 16;
+ uint64_t rsvd1 : 2;
+ uint64_t rsvd0 : 2;
+ uint64_t grp : 10;
+ uint64_t tt : 2;
+ uint64_t tag : 32;
+ } w1;
+
+ struct {
+ uint64_t sw : 1;
+ uint64_t lgty : 5;
+ uint64_t lfty : 5;
+ uint64_t lety : 5;
+ uint64_t ldty : 5;
+ uint64_t lcty : 5;
+ uint64_t lbty : 5;
+ uint64_t lae : 1;
+ uint64_t rsvd0 : 8;
+ uint64_t vv : 1;
+ uint64_t vs : 1;
+ uint64_t sh : 1;
+ uint64_t pf4 : 1;
+ uint64_t pf3 : 1;
+ uint64_t pf2 : 1;
+ uint64_t pf1 : 1;
+ uint64_t l3fr : 1;
+ uint64_t l3b : 1;
+ uint64_t l3m : 1;
+ uint64_t l2b : 1;
+ uint64_t l2m : 1;
+ uint64_t raw : 1;
+ uint64_t err_lev : 3;
+ uint64_t op_code : 8;
+ } w2;
+
+ struct {
+ uint64_t addr; /* Byte addr of start-of-pkt */
+ } w3;
+
+ struct {
+ uint64_t vlptr : 8;
+ uint64_t lgptr : 8;
+ uint64_t lfptr : 8;
+ uint64_t leptr : 8;
+ uint64_t ldprt : 8;
+ uint64_t lcptr : 8;
+ uint64_t lbptr : 8;
+ uint64_t laptr : 8;
+ } w4;
+#endif
+ } s;
+
+} __rte_packed octtx_wqe_t;
+
+enum occtx_pki_ltype_e {
+ OCCTX_PKI_LTYPE_NONE = 0,
+ OCCTX_PKI_LTYPE_ENET = 1,
+ OCCTX_PKI_LTYPE_VLAN = 2,
+ OCCTX_PKI_LTYPE_SNAP_PAYLD = 5,
+ OCCTX_PKI_LTYPE_ARP = 6,
+ OCCTX_PKI_LTYPE_RARP = 7,
+ OCCTX_PKI_LTYPE_IP4 = 8,
+ OCCTX_PKI_LTYPE_IP4_OPT = 9,
+ OCCTX_PKI_LTYPE_IP6 = 0xa,
+ OCCTX_PKI_LTYPE_IP6_OPT = 0xb,
+ OCCTX_PKI_LTYPE_IPSEC_ESP = 0xc,
+ OCCTX_PKI_LTYPE_IPFRAG = 0xd,
+ OCCTX_PKI_LTYPE_IPCOMP = 0xe,
+ OCCTX_PKI_LTYPE_TCP = 0x10,
+ OCCTX_PKI_LTYPE_UDP = 0x11,
+ OCCTX_PKI_LTYPE_SCTP = 0x12,
+ OCCTX_PKI_LTYPE_UDP_VXLAN = 0x13,
+ OCCTX_PKI_LTYPE_GRE = 0x14,
+ OCCTX_PKI_LTYPE_NVGRE = 0x15,
+ OCCTX_PKI_LTYPE_GTP = 0x16,
+ OCCTX_PKI_LTYPE_UDP_GENEVE = 0x17,
+ OCCTX_PKI_LTYPE_SW28 = 0x1c,
+ OCCTX_PKI_LTYPE_SW29 = 0x1d,
+ OCCTX_PKI_LTYPE_SW30 = 0x1e,
+ OCCTX_PKI_LTYPE_SW31 = 0x1f,
+ OCCTX_PKI_LTYPE_LAST
+};
+
+enum lc_type_e {
+ LC_NONE = OCCTX_PKI_LTYPE_NONE,
+ LC_IPV4 = OCCTX_PKI_LTYPE_IP4,
+ LC_IPV4_OPT = OCCTX_PKI_LTYPE_IP4_OPT,
+ LC_IPV6 = OCCTX_PKI_LTYPE_IP6,
+ LC_IPV6_OPT = OCCTX_PKI_LTYPE_IP6_OPT,
+};
+
+enum le_type_e {
+ LE_NONE = OCCTX_PKI_LTYPE_NONE,
+};
+
+enum lf_type_e {
+ LF_NONE = OCCTX_PKI_LTYPE_NONE,
+ LF_IPSEC_ESP = OCCTX_PKI_LTYPE_IPSEC_ESP,
+ LF_IPFRAG = OCCTX_PKI_LTYPE_IPFRAG,
+ LF_IPCOMP = OCCTX_PKI_LTYPE_IPCOMP,
+ LF_TCP = OCCTX_PKI_LTYPE_TCP,
+ LF_UDP = OCCTX_PKI_LTYPE_UDP,
+ LF_GRE = OCCTX_PKI_LTYPE_GRE,
+ LF_UDP_GENEVE = OCCTX_PKI_LTYPE_UDP_GENEVE,
+ LF_UDP_VXLAN = OCCTX_PKI_LTYPE_UDP_VXLAN,
+ LF_NVGRE = OCCTX_PKI_LTYPE_NVGRE,
+};
+#endif /* __OCTEONTX_PKI_VAR_H__ */
diff --git a/drivers/net/octeontx/base/octeontx_pkivf.c b/drivers/net/octeontx/base/octeontx_pkivf.c
new file mode 100644
index 00000000..b97f05cd
--- /dev/null
+++ b/drivers/net/octeontx/base/octeontx_pkivf.c
@@ -0,0 +1,169 @@
+/*
+ * BSD LICENSE
+ *
+ * Copyright (C) Cavium Inc. 2017. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Cavium networks nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <string.h>
+
+#include <rte_eal.h>
+#include <rte_bus_pci.h>
+
+#include "octeontx_pkivf.h"
+
+int
+octeontx_pki_port_open(int port)
+{
+ struct octeontx_mbox_hdr hdr;
+ int res;
+
+ hdr.coproc = OCTEONTX_PKI_COPROC;
+ hdr.msg = MBOX_PKI_PORT_OPEN;
+ hdr.vfid = port;
+
+ res = octeontx_ssovf_mbox_send(&hdr, NULL, 0, NULL, 0);
+ if (res < 0)
+ return -EACCES;
+ return res;
+}
+
+int
+octeontx_pki_port_hash_config(int port, pki_hash_cfg_t *hash_cfg)
+{
+ struct octeontx_mbox_hdr hdr;
+ int res;
+
+ mbox_pki_hash_cfg_t h_cfg = *(mbox_pki_hash_cfg_t *)hash_cfg;
+ int len = sizeof(mbox_pki_hash_cfg_t);
+
+ hdr.coproc = OCTEONTX_PKI_COPROC;
+ hdr.msg = MBOX_PKI_PORT_HASH_CONFIG;
+ hdr.vfid = port;
+
+ res = octeontx_ssovf_mbox_send(&hdr, &h_cfg, len, NULL, 0);
+ if (res < 0)
+ return -EACCES;
+
+ return res;
+}
+
+int
+octeontx_pki_port_pktbuf_config(int port, pki_pktbuf_cfg_t *buf_cfg)
+{
+ struct octeontx_mbox_hdr hdr;
+ int res;
+
+ mbox_pki_pktbuf_cfg_t b_cfg = *(mbox_pki_pktbuf_cfg_t *)buf_cfg;
+ int len = sizeof(mbox_pki_pktbuf_cfg_t);
+
+ hdr.coproc = OCTEONTX_PKI_COPROC;
+ hdr.msg = MBOX_PKI_PORT_PKTBUF_CONFIG;
+ hdr.vfid = port;
+
+ res = octeontx_ssovf_mbox_send(&hdr, &b_cfg, len, NULL, 0);
+ if (res < 0)
+ return -EACCES;
+ return res;
+}
+
+int
+octeontx_pki_port_create_qos(int port, pki_qos_cfg_t *qos_cfg)
+{
+ struct octeontx_mbox_hdr hdr;
+ int res;
+
+ mbox_pki_qos_cfg_t q_cfg = *(mbox_pki_qos_cfg_t *)qos_cfg;
+ int len = sizeof(mbox_pki_qos_cfg_t);
+
+ hdr.coproc = OCTEONTX_PKI_COPROC;
+ hdr.msg = MBOX_PKI_PORT_CREATE_QOS;
+ hdr.vfid = port;
+
+ res = octeontx_ssovf_mbox_send(&hdr, &q_cfg, len, NULL, 0);
+ if (res < 0)
+ return -EACCES;
+
+ return res;
+}
+
+
+int
+octeontx_pki_port_errchk_config(int port, pki_errchk_cfg_t *cfg)
+{
+ struct octeontx_mbox_hdr hdr;
+ int res;
+
+ mbox_pki_errcheck_cfg_t e_cfg;
+ e_cfg = *((mbox_pki_errcheck_cfg_t *)(cfg));
+ int len = sizeof(mbox_pki_errcheck_cfg_t);
+
+ hdr.coproc = OCTEONTX_PKI_COPROC;
+ hdr.msg = MBOX_PKI_PORT_ERRCHK_CONFIG;
+ hdr.vfid = port;
+
+ res = octeontx_ssovf_mbox_send(&hdr, &e_cfg, len, NULL, 0);
+ if (res < 0)
+ return -EACCES;
+
+ return res;
+}
+
+#define PCI_VENDOR_ID_CAVIUM 0x177D
+#define PCI_DEVICE_ID_OCTEONTX_PKI_VF 0xA0DD
+
+/* PKIVF pcie device */
+static int
+pkivf_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
+{
+ RTE_SET_USED(pci_drv);
+ RTE_SET_USED(pci_dev);
+
+ /* For secondary processes, the primary has done all the work */
+ if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+ return 0;
+
+ return 0;
+}
+
+static const struct rte_pci_id pci_pkivf_map[] = {
+ {
+ RTE_PCI_DEVICE(PCI_VENDOR_ID_CAVIUM,
+ PCI_DEVICE_ID_OCTEONTX_PKI_VF)
+ },
+ {
+ .vendor_id = 0,
+ },
+};
+
+static struct rte_pci_driver pci_pkivf = {
+ .id_table = pci_pkivf_map,
+ .drv_flags = RTE_PCI_DRV_NEED_MAPPING,
+ .probe = pkivf_probe,
+};
+
+RTE_PMD_REGISTER_PCI(octeontx_pkivf, pci_pkivf);
diff --git a/drivers/net/octeontx/base/octeontx_pkivf.h b/drivers/net/octeontx/base/octeontx_pkivf.h
new file mode 100644
index 00000000..004dedcc
--- /dev/null
+++ b/drivers/net/octeontx/base/octeontx_pkivf.h
@@ -0,0 +1,553 @@
+/*
+ * BSD LICENSE
+ *
+ * Copyright (C) Cavium Inc. 2017. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Cavium networks nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __OCTEONTX_PKI_H__
+#define __OCTEONTX_PKI_H__
+
+#include <stdint.h>
+
+#include <octeontx_mbox.h>
+
+#define OCTEONTX_PKI_COPROC 5
+
+/* PKI messages */
+
+#define MBOX_PKI_PORT_OPEN 1
+#define MBOX_PKI_PORT_START 2
+#define MBOX_PKI_PORT_STOP 3
+#define MBOX_PKI_PORT_CLOSE 4
+#define MBOX_PKI_PORT_CONFIG 5
+#define MBOX_PKI_PORT_OPT_PARSER_CONFIG 6
+#define MBOX_PKI_PORT_CUSTOM_PARSER_CONFIG 7
+#define MBOX_PKI_PORT_PKTBUF_CONFIG 8
+#define MBOX_PKI_PORT_HASH_CONFIG 9
+#define MBOX_PKI_PORT_ERRCHK_CONFIG 10
+#define MBOX_PKI_PORT_CREATE_QOS 11
+#define MBOX_PKI_PORT_MODIFY_QOS 12
+#define MBOX_PKI_PORT_DELETE_QOS 13
+#define MBOX_PKI_PORT_PKTDROP_CONFIG 14
+#define MBOX_PKI_PORT_WQE_GEN_CONFIG 15
+#define MBOX_PKI_BACKPRESSURE_CONFIG 16
+#define MBOX_PKI_PORT_GET_STATS 17
+#define MBOX_PKI_PORT_RESET_STATS 18
+#define MBOX_PKI_GET_PORT_CONFIG 19
+#define MBOX_PKI_GET_PORT_QOS_CONFIG 20
+
+#define MBOX_PKI_MAX_QOS_ENTRY 64
+
+/* pki pkind parse mode */
+enum {
+ MBOX_PKI_PARSE_LA_TO_LG = 0,
+ MBOX_PKI_PARSE_LB_TO_LG = 1,
+ MBOX_PKI_PARSE_LC_TO_LG = 3,
+ MBOX_PKI_PARSE_LG = 0x3f,
+ MBOX_PKI_PARSE_NOTHING = 0x7f
+};
+
+/* Interface types: */
+enum {
+ OCTTX_PORT_TYPE_NET, /* Network interface ports */
+ OCTTX_PORT_TYPE_INT, /* CPU internal interface ports */
+ OCTTX_PORT_TYPE_PCI, /* DPI/PCIe interface ports */
+ OCTTX_PORT_TYPE_MAX
+};
+
+/* pki port config */
+typedef struct mbox_pki_port_type {
+ uint8_t port_type;
+} mbox_pki_port_t;
+
+/* pki port config */
+typedef struct mbox_pki_port_cfg {
+ uint8_t port_type;
+ struct {
+ uint8_t fcs_pres:1;
+ uint8_t fcs_skip:1;
+ uint8_t parse_mode:1;
+ uint8_t mpls_parse:1;
+ uint8_t inst_hdr_parse:1;
+ uint8_t fulc_parse:1;
+ uint8_t dsa_parse:1;
+ uint8_t hg2_parse:1;
+ uint8_t hg_parse:1;
+ } mmask;
+ uint8_t fcs_pres;
+ uint8_t fcs_skip;
+ uint8_t parse_mode;
+ uint8_t mpls_parse;
+ uint8_t inst_hdr_parse;
+ uint8_t fulc_parse;
+ uint8_t dsa_parse;
+ uint8_t hg2_parse;
+ uint8_t hg_parse;
+} mbox_pki_prt_cfg_t;
+
+/* pki Flow/style packet buffer config */
+typedef struct mbox_pki_port_pktbuf_cfg {
+ uint8_t port_type;
+ struct {
+ uint16_t f_mbuff_size:1;
+ uint16_t f_wqe_skip:1;
+ uint16_t f_first_skip:1;
+ uint16_t f_later_skip:1;
+ uint16_t f_pkt_outside_wqe:1;
+ uint16_t f_wqe_endian:1;
+ uint16_t f_cache_mode:1;
+ } mmask;
+ uint16_t mbuff_size;
+ uint16_t wqe_skip;
+ uint16_t first_skip;
+ uint16_t later_skip;
+ uint8_t pkt_outside_wqe;
+ uint8_t wqe_endian;
+ uint8_t cache_mode;
+} mbox_pki_pktbuf_cfg_t;
+
+/* pki flow/style tag config */
+typedef struct mbox_pki_port_hash_cfg {
+ uint8_t port_type;
+ uint32_t tag_slf:1;
+ uint32_t tag_sle:1;
+ uint32_t tag_sld:1;
+ uint32_t tag_slc:1;
+ uint32_t tag_dlf:1;
+ uint32_t tag_dle:1;
+ uint32_t tag_dld:1;
+ uint32_t tag_dlc:1;
+ uint32_t tag_prt:1;
+ uint32_t tag_vlan0:1;
+ uint32_t tag_vlan1:1;
+ uint32_t tag_ip_pctl:1;
+ uint32_t tag_sync:1;
+ uint32_t tag_spi:1;
+ uint32_t tag_gtp:1;
+ uint32_t tag_vni:1;
+} mbox_pki_hash_cfg_t;
+
+/* pki flow/style errcheck config */
+typedef struct mbox_pki_port_errcheck_cfg {
+ uint8_t port_type;
+ struct {
+ uint32_t f_ip6_udp_opt:1;
+ uint32_t f_lenerr_en:1;
+ uint32_t f_maxerr_en:1;
+ uint32_t f_minerr_en:1;
+ uint32_t f_fcs_chk:1;
+ uint32_t f_fcs_strip:1;
+ uint32_t f_len_lf:1;
+ uint32_t f_len_le:1;
+ uint32_t f_len_ld:1;
+ uint32_t f_len_lc:1;
+ uint32_t f_csum_lf:1;
+ uint32_t f_csum_le:1;
+ uint32_t f_csum_ld:1;
+ uint32_t f_csum_lc:1;
+ uint32_t f_min_frame_len;
+ uint32_t f_max_frame_len;
+ } mmask;
+ uint64_t ip6_udp_opt:1;
+ uint64_t lenerr_en:1;
+ uint64_t maxerr_en:1;
+ uint64_t minerr_en:1;
+ uint64_t fcs_chk:1;
+ uint64_t fcs_strip:1;
+ uint64_t len_lf:1;
+ uint64_t len_le:1;
+ uint64_t len_ld:1;
+ uint64_t len_lc:1;
+ uint64_t csum_lf:1;
+ uint64_t csum_le:1;
+ uint64_t csum_ld:1;
+ uint64_t csum_lc:1;
+ uint64_t min_frame_len;
+ uint64_t max_frame_len;
+} mbox_pki_errcheck_cfg_t;
+
+/* CACHE MODE*/
+enum {
+ MBOX_PKI_OPC_MODE_STT = 0LL,
+ MBOX_PKI_OPC_MODE_STF = 1LL,
+ MBOX_PKI_OPC_MODE_STF1_STT = 2LL,
+ MBOX_PKI_OPC_MODE_STF2_STT = 3LL
+};
+
+/* PKI QPG QOS*/
+enum {
+ MBOX_PKI_QPG_QOS_NONE = 0,
+ MBOX_PKI_QPG_QOS_VLAN,
+ MBOX_PKI_QPG_QOS_MPLS,
+ MBOX_PKI_QPG_QOS_DSA_SRC,
+ MBOX_PKI_QPG_QOS_DIFFSERV,
+ MBOX_PKI_QPG_QOS_HIGIG,
+};
+
+struct mbox_pki_qos_entry {
+ uint16_t port_add;
+ uint16_t ggrp_ok;
+ uint16_t ggrp_bad;
+ uint16_t gaura;
+ uint8_t grptag_ok;
+ uint8_t grptag_bad;
+};
+
+/* pki flow/style enable qos */
+typedef struct mbox_pki_port_create_qos {
+ uint8_t port_type;
+ uint8_t qpg_qos;
+ uint8_t num_entry;
+ uint8_t tag_type;
+ uint8_t drop_policy;
+ struct mbox_pki_qos_entry qos_entry[MBOX_PKI_MAX_QOS_ENTRY];
+} mbox_pki_qos_cfg_t;
+
+/* pki flow/style enable qos */
+typedef struct mbox_pki_port_modify_qos_entry {
+ uint8_t port_type;
+ uint16_t index;
+ struct {
+ uint8_t f_port_add:1;
+ uint8_t f_grp_ok:1;
+ uint8_t f_grp_bad:1;
+ uint8_t f_gaura:1;
+ uint8_t f_grptag_ok:1;
+ uint8_t f_grptag_bad:1;
+ uint8_t f_tag_type:1;
+ } mmask;
+ uint8_t tag_type;
+ struct mbox_pki_qos_entry qos_entry;
+} mbox_pki_mod_qos_t;
+
+/* pki flow/style enable qos */
+typedef struct mbox_pki_port_delete_qos_entry {
+ uint8_t port_type;
+ uint16_t index;
+} mbox_pki_del_qos_t;
+
+/* PKI maximum constants */
+#define PKI_VF_MAX (1)
+#define PKI_MAX_PKTLEN (32768)
+
+/* pki pkind parse mode */
+enum {
+ PKI_PARSE_LA_TO_LG = 0,
+ PKI_PARSE_LB_TO_LG = 1,
+ PKI_PARSE_LC_TO_LG = 3,
+ PKI_PARSE_LG = 0x3f,
+ PKI_PARSE_NOTHING = 0x7f
+};
+
+/* pki port config */
+typedef struct pki_port_cfg {
+ uint8_t port_type;
+ struct {
+ uint8_t fcs_pres:1;
+ uint8_t fcs_skip:1;
+ uint8_t parse_mode:1;
+ uint8_t mpls_parse:1;
+ uint8_t inst_hdr_parse:1;
+ uint8_t fulc_parse:1;
+ uint8_t dsa_parse:1;
+ uint8_t hg2_parse:1;
+ uint8_t hg_parse:1;
+ } mmask;
+ uint8_t fcs_pres;
+ uint8_t fcs_skip;
+ uint8_t parse_mode;
+ uint8_t mpls_parse;
+ uint8_t inst_hdr_parse;
+ uint8_t fulc_parse;
+ uint8_t dsa_parse;
+ uint8_t hg2_parse;
+ uint8_t hg_parse;
+} pki_prt_cfg_t;
+
+
+/* pki Flow/style packet buffer config */
+typedef struct pki_port_pktbuf_cfg {
+ uint8_t port_type;
+ struct {
+ uint16_t f_mbuff_size:1;
+ uint16_t f_wqe_skip:1;
+ uint16_t f_first_skip:1;
+ uint16_t f_later_skip:1;
+ uint16_t f_pkt_outside_wqe:1;
+ uint16_t f_wqe_endian:1;
+ uint16_t f_cache_mode:1;
+ } mmask;
+ uint16_t mbuff_size;
+ uint16_t wqe_skip;
+ uint16_t first_skip;
+ uint16_t later_skip;
+ uint8_t pkt_outside_wqe;
+ uint8_t wqe_endian;
+ uint8_t cache_mode;
+} pki_pktbuf_cfg_t;
+
+/* pki flow/style tag config */
+typedef struct pki_port_hash_cfg {
+ uint8_t port_type;
+ uint32_t tag_slf:1;
+ uint32_t tag_sle:1;
+ uint32_t tag_sld:1;
+ uint32_t tag_slc:1;
+ uint32_t tag_dlf:1;
+ uint32_t tag_dle:1;
+ uint32_t tag_dld:1;
+ uint32_t tag_dlc:1;
+ uint32_t tag_prt:1;
+ uint32_t tag_vlan0:1;
+ uint32_t tag_vlan1:1;
+ uint32_t tag_ip_pctl:1;
+ uint32_t tag_sync:1;
+ uint32_t tag_spi:1;
+ uint32_t tag_gtp:1;
+ uint32_t tag_vni:1;
+} pki_hash_cfg_t;
+
+/* pki flow/style errcheck config */
+typedef struct pki_port_errcheck_cfg {
+ uint8_t port_type;
+ struct {
+ uint32_t f_ip6_udp_opt:1;
+ uint32_t f_lenerr_en:1;
+ uint32_t f_maxerr_en:1;
+ uint32_t f_minerr_en:1;
+ uint32_t f_fcs_chk:1;
+ uint32_t f_fcs_strip:1;
+ uint32_t f_len_lf:1;
+ uint32_t f_len_le:1;
+ uint32_t f_len_ld:1;
+ uint32_t f_len_lc:1;
+ uint32_t f_csum_lf:1;
+ uint32_t f_csum_le:1;
+ uint32_t f_csum_ld:1;
+ uint32_t f_csum_lc:1;
+ uint32_t f_min_frame_len;
+ uint32_t f_max_frame_len;
+ } mmask;
+ uint64_t ip6_udp_opt:1;
+ uint64_t lenerr_en:1;
+ uint64_t maxerr_en:1;
+ uint64_t minerr_en:1;
+ uint64_t fcs_chk:1;
+ uint64_t fcs_strip:1;
+ uint64_t len_lf:1;
+ uint64_t len_le:1;
+ uint64_t len_ld:1;
+ uint64_t len_lc:1;
+ uint64_t csum_lf:1;
+ uint64_t csum_le:1;
+ uint64_t csum_ld:1;
+ uint64_t csum_lc:1;
+ uint64_t min_frame_len;
+ uint64_t max_frame_len;
+} pki_errchk_cfg_t;
+
+
+/* CACHE MODE*/
+enum {
+ PKI_OPC_MODE_STT = 0LL,
+ PKI_OPC_MODE_STF = 1LL,
+ PKI_OPC_MODE_STF1_STT = 2LL,
+ PKI_OPC_MODE_STF2_STT = 3LL
+};
+
+/* PKI QPG QOS*/
+enum {
+ PKI_QPG_QOS_NONE = 0,
+ PKI_QPG_QOS_VLAN,
+ PKI_QPG_QOS_MPLS,
+ PKI_QPG_QOS_DSA_SRC,
+ PKI_QPG_QOS_DIFFSERV,
+ PKI_QPG_QOS_HIGIG,
+};
+
+struct pki_qos_entry {
+ uint16_t port_add;
+ uint16_t ggrp_ok;
+ uint16_t ggrp_bad;
+ uint16_t gaura;
+ uint8_t grptag_ok;
+ uint8_t grptag_bad;
+ uint8_t ena_red;
+ uint8_t ena_drop;
+};
+
+#define PKO_MAX_QOS_ENTRY 64
+
+/* pki flow/style enable qos */
+typedef struct pki_port_create_qos {
+ uint8_t port_type;
+ uint8_t qpg_qos;
+ uint8_t num_entry;
+ uint8_t tag_type;
+ uint8_t drop_policy;
+ struct pki_qos_entry qos_entry[PKO_MAX_QOS_ENTRY];
+} pki_qos_cfg_t;
+
+/* pki flow/style enable qos */
+typedef struct pki_port_delete_qos_entry {
+ uint8_t port_type;
+ uint16_t index;
+} pki_del_qos_t;
+
+/* pki flow/style enable qos */
+typedef struct pki_port_modify_qos_entry {
+ uint8_t port_type;
+ uint16_t index;
+ struct {
+ uint8_t f_port_add:1;
+ uint8_t f_grp_ok:1;
+ uint8_t f_grp_bad:1;
+ uint8_t f_gaura:1;
+ uint8_t f_grptag_ok:1;
+ uint8_t f_grptag_bad:1;
+ uint8_t f_tag_type:1;
+ } mmask;
+ uint8_t tag_type;
+ struct pki_qos_entry qos_entry;
+} pki_mod_qos_t;
+
+static inline int
+octeontx_pki_port_modify_qos(int port, pki_mod_qos_t *qos_cfg)
+{
+ struct octeontx_mbox_hdr hdr;
+ int res;
+
+ mbox_pki_mod_qos_t q_cfg = *(mbox_pki_mod_qos_t *)qos_cfg;
+ int len = sizeof(mbox_pki_mod_qos_t);
+
+ hdr.coproc = OCTEONTX_PKI_COPROC;
+ hdr.msg = MBOX_PKI_PORT_MODIFY_QOS;
+ hdr.vfid = port;
+
+ res = octeontx_ssovf_mbox_send(&hdr, &q_cfg, len, NULL, 0);
+ if (res < 0)
+ return -EACCES;
+
+ return res;
+}
+
+static inline int
+octeontx_pki_port_delete_qos(int port, pki_del_qos_t *qos_cfg)
+{
+ struct octeontx_mbox_hdr hdr;
+ int res;
+
+ mbox_pki_del_qos_t q_cfg = *(mbox_pki_del_qos_t *)qos_cfg;
+ int len = sizeof(mbox_pki_del_qos_t);
+
+ hdr.coproc = OCTEONTX_PKI_COPROC;
+ hdr.msg = MBOX_PKI_PORT_DELETE_QOS;
+ hdr.vfid = port;
+
+ res = octeontx_ssovf_mbox_send(&hdr, &q_cfg, len, NULL, 0);
+ if (res < 0)
+ return -EACCES;
+
+ return res;
+}
+
+static inline int
+octeontx_pki_port_close(int port)
+{
+ struct octeontx_mbox_hdr hdr;
+ int res;
+
+ mbox_pki_port_t ptype;
+ int len = sizeof(mbox_pki_port_t);
+ memset(&ptype, 0, len);
+ ptype.port_type = OCTTX_PORT_TYPE_NET;
+
+ hdr.coproc = OCTEONTX_PKI_COPROC;
+ hdr.msg = MBOX_PKI_PORT_CLOSE;
+ hdr.vfid = port;
+
+ res = octeontx_ssovf_mbox_send(&hdr, &ptype, len, NULL, 0);
+ if (res < 0)
+ return -EACCES;
+
+ return res;
+}
+
+static inline int
+octeontx_pki_port_start(int port)
+{
+ struct octeontx_mbox_hdr hdr;
+ int res;
+
+ mbox_pki_port_t ptype;
+ int len = sizeof(mbox_pki_port_t);
+ memset(&ptype, 0, len);
+ ptype.port_type = OCTTX_PORT_TYPE_NET;
+
+ hdr.coproc = OCTEONTX_PKI_COPROC;
+ hdr.msg = MBOX_PKI_PORT_START;
+ hdr.vfid = port;
+
+ res = octeontx_ssovf_mbox_send(&hdr, &ptype, len, NULL, 0);
+ if (res < 0)
+ return -EACCES;
+
+ return res;
+}
+
+static inline int
+octeontx_pki_port_stop(int port)
+{
+ struct octeontx_mbox_hdr hdr;
+ int res;
+
+ mbox_pki_port_t ptype;
+ int len = sizeof(mbox_pki_port_t);
+ memset(&ptype, 0, len);
+ ptype.port_type = OCTTX_PORT_TYPE_NET;
+
+ hdr.coproc = OCTEONTX_PKI_COPROC;
+ hdr.msg = MBOX_PKI_PORT_STOP;
+ hdr.vfid = port;
+
+ res = octeontx_ssovf_mbox_send(&hdr, &ptype, len, NULL, 0);
+ if (res < 0)
+ return -EACCES;
+
+ return res;
+}
+
+int octeontx_pki_port_open(int port);
+int octeontx_pki_port_hash_config(int port, pki_hash_cfg_t *hash_cfg);
+int octeontx_pki_port_pktbuf_config(int port, pki_pktbuf_cfg_t *buf_cfg);
+int octeontx_pki_port_create_qos(int port, pki_qos_cfg_t *qos_cfg);
+int octeontx_pki_port_close(int port);
+int octeontx_pki_port_errchk_config(int port, pki_errchk_cfg_t *cfg);
+
+#endif /* __OCTEONTX_PKI_H__ */
diff --git a/drivers/net/octeontx/base/octeontx_pkovf.c b/drivers/net/octeontx/base/octeontx_pkovf.c
new file mode 100644
index 00000000..f01d948e
--- /dev/null
+++ b/drivers/net/octeontx/base/octeontx_pkovf.c
@@ -0,0 +1,617 @@
+/*
+ * BSD LICENSE
+ *
+ * Copyright (C) Cavium Inc. 2017. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Cavium networks nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdbool.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <rte_eal.h>
+#include <rte_cycles.h>
+#include <rte_malloc.h>
+#include <rte_memory.h>
+#include <rte_bus_pci.h>
+#include <rte_spinlock.h>
+
+#include "../octeontx_logs.h"
+#include "octeontx_io.h"
+#include "octeontx_pkovf.h"
+
+struct octeontx_pko_iomem {
+ uint8_t *va;
+ rte_iova_t iova;
+ size_t size;
+};
+
+#define PKO_IOMEM_NULL (struct octeontx_pko_iomem){0, 0, 0}
+
+struct octeontx_pko_fc_ctl_s {
+ int64_t buf_cnt;
+ int64_t padding[(PKO_DQ_FC_STRIDE / 8) - 1];
+};
+
+struct octeontx_pkovf {
+ uint8_t *bar0;
+ uint8_t *bar2;
+ uint16_t domain;
+ uint16_t vfid;
+};
+
+struct octeontx_pko_vf_ctl_s {
+ rte_spinlock_t lock;
+
+ struct octeontx_pko_iomem fc_iomem;
+ struct octeontx_pko_fc_ctl_s *fc_ctl;
+ struct octeontx_pkovf pko[PKO_VF_MAX];
+ struct {
+ uint64_t chanid;
+ } dq_map[PKO_VF_MAX * PKO_VF_NUM_DQ];
+};
+
+static struct octeontx_pko_vf_ctl_s pko_vf_ctl;
+
+static void *
+octeontx_pko_dq_vf_bar0(uint16_t txq)
+{
+ int vf_ix;
+
+ vf_ix = txq / PKO_VF_NUM_DQ;
+ return pko_vf_ctl.pko[vf_ix].bar0;
+}
+
+static int
+octeontx_pko_dq_gdq(uint16_t txq)
+{
+ return txq % PKO_VF_NUM_DQ;
+}
+
+/**
+ * Open a PKO DQ.
+ */
+static inline
+int octeontx_pko_dq_open(uint16_t txq)
+{
+ unsigned int reg_off;
+ uint8_t *vf_bar0;
+ uint64_t rtn;
+ int gdq;
+
+ vf_bar0 = octeontx_pko_dq_vf_bar0(txq);
+ gdq = octeontx_pko_dq_gdq(txq);
+
+ if (unlikely(gdq < 0 || vf_bar0 == NULL))
+ return -EINVAL;
+ *(volatile int64_t*)(pko_vf_ctl.fc_ctl + txq) =
+ PKO_DQ_FC_DEPTH_PAGES - PKO_DQ_FC_SKID;
+
+ rte_wmb();
+
+ octeontx_write64(PKO_DQ_FC_DEPTH_PAGES,
+ vf_bar0 + PKO_VF_DQ_FC_STATUS(gdq));
+
+ /* Set the register to return descriptor (packet) count as DEPTH */
+ /* KIND=1, NCB_QUERY_RSP=0 */
+ octeontx_write64(1ull << PKO_DQ_KIND_BIT,
+ vf_bar0 + PKO_VF_DQ_WM_CTL(gdq));
+ reg_off = PKO_VF_DQ_OP_OPEN(gdq);
+
+ rtn = octeontx_reg_ldadd_u64(vf_bar0 + reg_off, 0);
+
+ /* PKO_DQOP_E::OPEN */
+ if (((rtn >> PKO_DQ_OP_BIT) & 0x3) != 0x1)
+ return -EIO;
+
+ switch (rtn >> PKO_DQ_STATUS_BIT) {
+ case 0xC: /* DQALREADYCREATED */
+ case 0x0: /* PASS */
+ break;
+ default:
+ return -EIO;
+ }
+
+ /* DRAIN=0, DRAIN_NULL_LINK=0, SW_XOFF=0 */
+ octeontx_write64(0, vf_bar0 + PKO_VF_DQ_SW_XOFF(gdq));
+
+ return rtn & ((1ull << PKO_DQ_OP_BIT) - 1);
+}
+
+/**
+ * Close a PKO DQ
+ * Flush all packets pending.
+ */
+static inline
+int octeontx_pko_dq_close(uint16_t txq)
+{
+ unsigned int reg_off;
+ uint8_t *vf_bar0;
+ uint64_t rtn;
+ int res;
+
+ vf_bar0 = octeontx_pko_dq_vf_bar0(txq);
+ res = octeontx_pko_dq_gdq(txq);
+
+ if (unlikely(res < 0 || vf_bar0 == NULL))
+ return -EINVAL;
+
+ reg_off = PKO_VF_DQ_OP_CLOSE(res);
+
+ rtn = octeontx_reg_ldadd_u64(vf_bar0 + reg_off, 0);
+
+ /* PKO_DQOP_E::CLOSE */
+ if (((rtn >> PKO_DQ_OP_BIT) & 0x3) != 0x2)
+ return -EIO;
+
+ switch (rtn >> PKO_DQ_STATUS_BIT) {
+ case 0xD: /* DQNOTCREATED */
+ case 0x0: /* PASS */
+ break;
+ default:
+ return -EIO;
+ }
+
+ res = rtn & ((1ull << PKO_DQ_OP_BIT) - 1); /* DEPTH */
+ return res;
+}
+
+/* Flush all packets pending on a DQ */
+static inline
+int octeontx_pko_dq_drain(uint16_t txq)
+{
+ unsigned int gdq;
+ uint8_t *vf_bar0;
+ uint64_t reg;
+ int res, timo = PKO_DQ_DRAIN_TO;
+
+ vf_bar0 = octeontx_pko_dq_vf_bar0(txq);
+ res = octeontx_pko_dq_gdq(txq);
+ gdq = res;
+
+ /* DRAIN=1, DRAIN_NULL_LINK=0, SW_XOFF=1 */
+ octeontx_write64(0x3, vf_bar0 + PKO_VF_DQ_SW_XOFF(gdq));
+ /* Wait until buffers leave DQs */
+ reg = octeontx_read64(vf_bar0 + PKO_VF_DQ_WM_CNT(gdq));
+ while (reg && timo > 0) {
+ rte_delay_us(100);
+ timo--;
+ reg = octeontx_read64(vf_bar0 + PKO_VF_DQ_WM_CNT(gdq));
+ }
+ /* DRAIN=0, DRAIN_NULL_LINK=0, SW_XOFF=0 */
+ octeontx_write64(0, vf_bar0 + PKO_VF_DQ_SW_XOFF(gdq));
+
+ return reg;
+}
+
+static inline int
+octeontx_pko_dq_range_lookup(struct octeontx_pko_vf_ctl_s *ctl, uint64_t chanid,
+ unsigned int dq_num, unsigned int dq_from)
+{
+ unsigned int dq, dq_cnt;
+ unsigned int dq_base;
+
+ dq_cnt = 0;
+ dq = dq_from;
+ while (dq < RTE_DIM(ctl->dq_map)) {
+ dq_base = dq;
+ dq_cnt = 0;
+ while (ctl->dq_map[dq].chanid == ~chanid &&
+ dq < RTE_DIM(ctl->dq_map)) {
+ dq_cnt++;
+ if (dq_cnt == dq_num)
+ return dq_base;
+ dq++;
+ }
+ dq++;
+ }
+ return -1;
+}
+
+static inline void
+octeontx_pko_dq_range_assign(struct octeontx_pko_vf_ctl_s *ctl, uint64_t chanid,
+ unsigned int dq_base, unsigned int dq_num)
+{
+ unsigned int dq, dq_cnt;
+
+ dq_cnt = 0;
+ while (dq_cnt < dq_num) {
+ dq = dq_base + dq_cnt;
+
+ octeontx_log_dbg("DQ# %u assigned to CHAN# %" PRIx64 "", dq,
+ chanid);
+
+ ctl->dq_map[dq].chanid = ~chanid;
+ dq_cnt++;
+ }
+}
+
+static inline int
+octeontx_pko_dq_claim(struct octeontx_pko_vf_ctl_s *ctl, unsigned int dq_base,
+ unsigned int dq_num, uint64_t chanid)
+{
+ const uint64_t null_chanid = ~0ull;
+ int dq;
+
+ rte_spinlock_lock(&ctl->lock);
+
+ dq = octeontx_pko_dq_range_lookup(ctl, null_chanid, dq_num, dq_base);
+ if (dq < 0 || (unsigned int)dq != dq_base) {
+ rte_spinlock_unlock(&ctl->lock);
+ return -1;
+ }
+ octeontx_pko_dq_range_assign(ctl, chanid, dq_base, dq_num);
+
+ rte_spinlock_unlock(&ctl->lock);
+
+ return 0;
+}
+
+static inline int
+octeontx_pko_dq_free(struct octeontx_pko_vf_ctl_s *ctl, uint64_t chanid)
+{
+ const uint64_t null_chanid = ~0ull;
+ unsigned int dq = 0, dq_cnt = 0;
+
+ rte_spinlock_lock(&ctl->lock);
+ while (dq < RTE_DIM(ctl->dq_map)) {
+ if (ctl->dq_map[dq].chanid == ~chanid) {
+ ctl->dq_map[dq].chanid = ~null_chanid;
+ dq_cnt++;
+ }
+ dq++;
+ }
+ rte_spinlock_unlock(&ctl->lock);
+
+ return dq_cnt > 0 ? 0 : -EINVAL;
+}
+
+int
+octeontx_pko_channel_open(int dq_base, int dq_num, int chanid)
+{
+ struct octeontx_pko_vf_ctl_s *ctl = &pko_vf_ctl;
+ int res;
+
+ res = octeontx_pko_dq_claim(ctl, dq_base, dq_num, chanid);
+ if (res < 0)
+ return -1;
+
+ return 0;
+}
+
+int
+octeontx_pko_channel_close(int chanid)
+{
+ struct octeontx_pko_vf_ctl_s *ctl = &pko_vf_ctl;
+ int res;
+
+ res = octeontx_pko_dq_free(ctl, chanid);
+ if (res < 0)
+ return -1;
+
+ return 0;
+}
+
+static inline int
+octeontx_pko_chan_start(struct octeontx_pko_vf_ctl_s *ctl, uint64_t chanid)
+{
+ unsigned int dq_vf;
+ unsigned int dq, dq_cnt;
+
+ dq_cnt = 0;
+ dq = 0;
+ while (dq < RTE_DIM(ctl->dq_map)) {
+ dq_vf = dq / PKO_VF_NUM_DQ;
+
+ if (!ctl->pko[dq_vf].bar0) {
+ dq += PKO_VF_NUM_DQ;
+ continue;
+ }
+
+ if (ctl->dq_map[dq].chanid != ~chanid) {
+ dq++;
+ continue;
+ }
+
+ if (octeontx_pko_dq_open(dq) < 0)
+ break;
+
+ dq_cnt++;
+ dq++;
+ }
+
+ return dq_cnt;
+}
+
+int
+octeontx_pko_channel_start(int chanid)
+{
+ struct octeontx_pko_vf_ctl_s *ctl = &pko_vf_ctl;
+ int dq_cnt;
+
+ dq_cnt = octeontx_pko_chan_start(ctl, chanid);
+ if (dq_cnt < 0)
+ return -1;
+
+ return dq_cnt;
+}
+
+static inline int
+octeontx_pko_chan_stop(struct octeontx_pko_vf_ctl_s *ctl, uint64_t chanid)
+{
+ unsigned int dq, dq_cnt, dq_vf;
+ int res;
+
+ dq_cnt = 0;
+ dq = 0;
+ while (dq < RTE_DIM(ctl->dq_map)) {
+ dq_vf = dq / PKO_VF_NUM_DQ;
+
+ if (!ctl->pko[dq_vf].bar0) {
+ dq += PKO_VF_NUM_DQ;
+ continue;
+ }
+
+ if (ctl->dq_map[dq].chanid != ~chanid) {
+ dq++;
+ continue;
+ }
+
+ res = octeontx_pko_dq_drain(dq);
+ if (res > 0)
+ octeontx_log_err("draining DQ%d, buffers left: %x",
+ dq, res);
+
+ res = octeontx_pko_dq_close(dq);
+ if (res < 0)
+ octeontx_log_err("closing DQ%d failed\n", dq);
+
+ dq_cnt++;
+ dq++;
+ }
+ return dq_cnt;
+}
+
+int
+octeontx_pko_channel_stop(int chanid)
+{
+ struct octeontx_pko_vf_ctl_s *ctl = &pko_vf_ctl;
+
+ octeontx_pko_chan_stop(ctl, chanid);
+ return 0;
+}
+
+static inline int
+octeontx_pko_channel_query(struct octeontx_pko_vf_ctl_s *ctl, uint64_t chanid,
+ void *out, size_t out_elem_size,
+ size_t dq_num, octeontx_pko_dq_getter_t getter)
+{
+ octeontx_dq_t curr;
+ unsigned int dq_vf;
+ unsigned int dq;
+
+ RTE_SET_USED(out_elem_size);
+ memset(&curr, 0, sizeof(octeontx_dq_t));
+
+ dq_vf = dq_num / PKO_VF_NUM_DQ;
+ dq = dq_num % PKO_VF_NUM_DQ;
+
+ if (!ctl->pko[dq_vf].bar0)
+ return -EINVAL;
+
+ if (ctl->dq_map[dq_num].chanid != ~chanid)
+ return -EINVAL;
+
+ uint8_t *iter = (uint8_t *)out;
+ curr.lmtline_va = ctl->pko[dq_vf].bar2;
+ curr.ioreg_va = (void *)((uintptr_t)ctl->pko[dq_vf].bar0
+ + PKO_VF_DQ_OP_SEND((dq), 0));
+ curr.fc_status_va = ctl->fc_ctl + dq;
+
+ octeontx_log_dbg("lmtline=%p ioreg_va=%p fc_status_va=%p",
+ curr.lmtline_va, curr.ioreg_va,
+ curr.fc_status_va);
+
+ getter(&curr, (void *)iter);
+ return 0;
+}
+
+int
+octeontx_pko_channel_query_dqs(int chanid, void *out, size_t out_elem_size,
+ size_t dq_num, octeontx_pko_dq_getter_t getter)
+{
+ struct octeontx_pko_vf_ctl_s *ctl = &pko_vf_ctl;
+ int dq_cnt;
+
+ dq_cnt = octeontx_pko_channel_query(ctl, chanid, out, out_elem_size,
+ dq_num, getter);
+ if (dq_cnt < 0)
+ return -1;
+
+ return dq_cnt;
+}
+
+int
+octeontx_pko_vf_count(void)
+{
+ int vf_cnt;
+
+ vf_cnt = 0;
+ while (pko_vf_ctl.pko[vf_cnt].bar0)
+ vf_cnt++;
+
+ return vf_cnt;
+}
+
+int
+octeontx_pko_init_fc(const size_t pko_vf_count)
+{
+ int dq_ix;
+ uint64_t reg;
+ uint8_t *vf_bar0;
+ size_t vf_idx;
+ size_t fc_mem_size;
+
+ fc_mem_size = sizeof(struct octeontx_pko_fc_ctl_s) *
+ pko_vf_count * PKO_VF_NUM_DQ;
+
+ pko_vf_ctl.fc_iomem.va = rte_malloc(NULL, fc_mem_size, 128);
+ if (unlikely(!pko_vf_ctl.fc_iomem.va)) {
+ octeontx_log_err("fc_iomem: not enough memory");
+ return -ENOMEM;
+ }
+
+ pko_vf_ctl.fc_iomem.iova = rte_malloc_virt2iova((void *)
+ pko_vf_ctl.fc_iomem.va);
+ pko_vf_ctl.fc_iomem.size = fc_mem_size;
+
+ pko_vf_ctl.fc_ctl =
+ (struct octeontx_pko_fc_ctl_s *)pko_vf_ctl.fc_iomem.va;
+
+ /* Configure Flow-Control feature for all DQs of open VFs */
+ for (vf_idx = 0; vf_idx < pko_vf_count; vf_idx++) {
+ dq_ix = vf_idx * PKO_VF_NUM_DQ;
+
+ vf_bar0 = pko_vf_ctl.pko[vf_idx].bar0;
+
+ reg = (pko_vf_ctl.fc_iomem.iova +
+ (sizeof(struct octeontx_pko_fc_ctl_s) * dq_ix)) & ~0x7F;
+ reg |= /* BASE */
+ (0x2 << 3) | /* HYST_BITS */
+ (((PKO_DQ_FC_STRIDE == PKO_DQ_FC_STRIDE_16) ? 1 : 0) << 2) |
+ (0x1 << 0); /* ENABLE */
+
+ octeontx_write64(reg, vf_bar0 + PKO_VF_DQ_FC_CONFIG);
+
+ octeontx_log_dbg("PKO: bar0 %p VF_idx %d DQ_FC_CFG=%" PRIx64 "",
+ vf_bar0, (int)vf_idx, reg);
+ }
+ return 0;
+}
+
+void
+octeontx_pko_fc_free(void)
+{
+ rte_free(pko_vf_ctl.fc_iomem.va);
+}
+
+static void
+octeontx_pkovf_setup(void)
+{
+ static bool init_once;
+
+ if (!init_once) {
+ unsigned int i;
+
+ rte_spinlock_init(&pko_vf_ctl.lock);
+
+ pko_vf_ctl.fc_iomem = PKO_IOMEM_NULL;
+ pko_vf_ctl.fc_ctl = NULL;
+
+ for (i = 0; i < PKO_VF_MAX; i++) {
+ pko_vf_ctl.pko[i].bar0 = NULL;
+ pko_vf_ctl.pko[i].bar2 = NULL;
+ pko_vf_ctl.pko[i].domain = ~(uint16_t)0;
+ pko_vf_ctl.pko[i].vfid = ~(uint16_t)0;
+ }
+
+ for (i = 0; i < (PKO_VF_MAX * PKO_VF_NUM_DQ); i++)
+ pko_vf_ctl.dq_map[i].chanid = 0;
+
+ init_once = true;
+ }
+}
+
+/* PKOVF pcie device*/
+static int
+pkovf_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
+{
+ uint64_t val;
+ uint16_t vfid;
+ uint16_t domain;
+ uint8_t *bar0;
+ uint8_t *bar2;
+ struct octeontx_pkovf *res;
+
+ RTE_SET_USED(pci_drv);
+
+ /* For secondary processes, the primary has done all the work */
+ if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+ return 0;
+
+ if (pci_dev->mem_resource[0].addr == NULL ||
+ pci_dev->mem_resource[2].addr == NULL) {
+ octeontx_log_err("Empty bars %p %p",
+ pci_dev->mem_resource[0].addr,
+ pci_dev->mem_resource[2].addr);
+ return -ENODEV;
+ }
+ bar0 = pci_dev->mem_resource[0].addr;
+ bar2 = pci_dev->mem_resource[2].addr;
+
+ octeontx_pkovf_setup();
+
+ /* get vfid and domain */
+ val = octeontx_read64(bar0 + PKO_VF_DQ_FC_CONFIG);
+ domain = (val >> 7) & 0xffff;
+ vfid = (val >> 23) & 0xffff;
+
+ if (unlikely(vfid >= PKO_VF_MAX)) {
+ octeontx_log_err("pko: Invalid vfid %d", vfid);
+ return -EINVAL;
+ }
+
+ res = &pko_vf_ctl.pko[vfid];
+ res->vfid = vfid;
+ res->domain = domain;
+ res->bar0 = bar0;
+ res->bar2 = bar2;
+
+ octeontx_log_dbg("Domain=%d group=%d", res->domain, res->vfid);
+ return 0;
+}
+
+#define PCI_VENDOR_ID_CAVIUM 0x177D
+#define PCI_DEVICE_ID_OCTEONTX_PKO_VF 0xA049
+
+static const struct rte_pci_id pci_pkovf_map[] = {
+ {
+ RTE_PCI_DEVICE(PCI_VENDOR_ID_CAVIUM,
+ PCI_DEVICE_ID_OCTEONTX_PKO_VF)
+ },
+ {
+ .vendor_id = 0,
+ },
+};
+
+static struct rte_pci_driver pci_pkovf = {
+ .id_table = pci_pkovf_map,
+ .drv_flags = RTE_PCI_DRV_NEED_MAPPING,
+ .probe = pkovf_probe,
+};
+
+RTE_PMD_REGISTER_PCI(octeontx_pkovf, pci_pkovf);
diff --git a/drivers/net/octeontx/base/octeontx_pkovf.h b/drivers/net/octeontx/base/octeontx_pkovf.h
new file mode 100644
index 00000000..cfc3715d
--- /dev/null
+++ b/drivers/net/octeontx/base/octeontx_pkovf.h
@@ -0,0 +1,97 @@
+/*
+ * BSD LICENSE
+ *
+ * Copyright (C) Cavium Inc. 2017. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Cavium networks nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __OCTEONTX_PKO_H__
+#define __OCTEONTX_PKO_H__
+
+/* PKO maximum constants */
+#define PKO_VF_MAX (32)
+#define PKO_VF_NUM_DQ (8)
+#define PKO_MAX_NUM_DQ (8)
+#define PKO_DQ_DRAIN_TO (1000)
+
+#define PKO_DQ_FC_SKID (4)
+#define PKO_DQ_FC_DEPTH_PAGES (2048)
+#define PKO_DQ_FC_STRIDE_16 (16)
+#define PKO_DQ_FC_STRIDE_128 (128)
+#define PKO_DQ_FC_STRIDE PKO_DQ_FC_STRIDE_16
+
+#define PKO_DQ_KIND_BIT 49
+#define PKO_DQ_STATUS_BIT 60
+#define PKO_DQ_OP_BIT 48
+
+/* PKO VF register offsets from VF_BAR0 */
+#define PKO_VF_DQ_SW_XOFF(gdq) (0x000100 | (gdq) << 17)
+#define PKO_VF_DQ_WM_CTL(gdq) (0x000130 | (gdq) << 17)
+#define PKO_VF_DQ_WM_CNT(gdq) (0x000150 | (gdq) << 17)
+#define PKO_VF_DQ_FC_CONFIG (0x000160)
+#define PKO_VF_DQ_FC_STATUS(gdq) (0x000168 | (gdq) << 17)
+#define PKO_VF_DQ_OP_SEND(gdq, op) (0x001000 | (gdq) << 17 | (op) << 3)
+#define PKO_VF_DQ_OP_OPEN(gdq) (0x001100 | (gdq) << 17)
+#define PKO_VF_DQ_OP_CLOSE(gdq) (0x001200 | (gdq) << 17)
+#define PKO_VF_DQ_OP_QUERY(gdq) (0x001300 | (gdq) << 17)
+
+/* pko_send_hdr_s + pko_send_link */
+#define PKO_CMD_SZ (2 << 1)
+#define PKO_SEND_GATHER_SUBDC (0x0ull << 60)
+#define PKO_SEND_GATHER_LDTYPE(x) ((x) << 58)
+#define PKO_SEND_GATHER_GAUAR(x) ((x) << 24)
+
+typedef struct octeontx_dq_s {
+ void *lmtline_va;
+ void *ioreg_va;
+ void *fc_status_va;
+} octeontx_dq_t;
+
+/**
+ * Function for extracting information out of a given DQ.
+ *
+ * It is intended to be used in slow path (configuration) in
+ * octeontx_pko_channel_query().
+ *
+ * @param dq The DQ to extract information from.
+ * @param out Pointer to the user's structure he wants to fill.
+ */
+typedef void (*octeontx_pko_dq_getter_t)(octeontx_dq_t *dq, void *out);
+
+int
+octeontx_pko_channel_query_dqs(int chanid, void *out, size_t out_elem_size,
+ size_t dq_num, octeontx_pko_dq_getter_t getter);
+int octeontx_pko_channel_open(int dq_base, int dq_num, int chanid);
+int octeontx_pko_channel_close(int chanid);
+int octeontx_pko_channel_start(int chanid);
+int octeontx_pko_channel_stop(int chanid);
+int octeontx_pko_vf_count(void);
+int octeontx_pko_init_fc(const size_t pko_vf_count);
+void octeontx_pko_fc_free(void);
+
+#endif /* __OCTEONTX_PKO_H__ */