From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 95D50C433EF for ; Wed, 30 Mar 2022 10:19:37 +0000 (UTC) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 1D79C840D7; Wed, 30 Mar 2022 12:15:43 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=denx.de Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=denx.de; s=phobos-20191101; t=1648635343; bh=f8OFKFr/o973PMRObmdWbiAyB8sAA+qPmMfMyLGz8Jg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=MTfWPzBNkZkjYyq+iInP6M83sRAHSXFMhk8cjglQC7fl3A/wDR/OJKz3ys8a5javR XjxAfvh2z0K3y9g+ac65Go9xfjvoaccXTKWofb1Ux5M/wPZRDCKXO6LG1o/otuY9I4 UPzAzIOYhxfAZwZcmm6CZQYmXu6+KL9V/VHLebaJYvaklwRi62UI5V3+FqbSVFGFY7 OYkYqtz+v+gtfwWQ6Smzid8RgYOQnImUL8BIMmZFpbOFjA1JoYumgbBG5ZhCP+rmEJ ldTO9kIlSlKF6YVWTE5MUqUTwkhZEOSXsR4Q+ZxK9H2yYYWYdDzAxtruUx1nBQV0d9 aWzO9s1qzwPHg== Received: by phobos.denx.de (Postfix, from userid 109) id A386184106; Wed, 30 Mar 2022 12:08:15 +0200 (CEST) Received: from mout-u-107.mailbox.org (mout-u-107.mailbox.org [IPv6:2001:67c:2050:1::465:107]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 0078A840DE for ; Wed, 30 Mar 2022 12:07:50 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=denx.de Authentication-Results: phobos.denx.de; spf=fail smtp.mailfrom=sr@denx.de Received: from smtp102.mailbox.org (unknown [91.198.250.119]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-384) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-u-107.mailbox.org (Postfix) with ESMTPS id 4KT2Dj2qpgz9sR9; Wed, 30 Mar 2022 12:07:49 +0200 (CEST) From: Stefan Roese To: u-boot@lists.denx.de Cc: awilliams@marvell.com, cchavva@marvell.com Subject: [PATCH 18/52] mips: octeon: Add cvmx-helper-pko.c Date: Wed, 30 Mar 2022 12:06:54 +0200 Message-Id: <20220330100728.871561-19-sr@denx.de> In-Reply-To: <20220330100728.871561-1-sr@denx.de> References: <20220330100728.871561-1-sr@denx.de> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.5 at phobos.denx.de X-Virus-Status: Clean From: Aaron Williams Import cvmx-helper-pko.c from 2013 U-Boot. It will be used by the later added drivers to support networking on the MIPS Octeon II / III platforms. Signed-off-by: Aaron Williams Signed-off-by: Stefan Roese --- arch/mips/mach-octeon/cvmx-helper-pko.c | 312 ++++++++++++++++++++++++ 1 file changed, 312 insertions(+) create mode 100644 arch/mips/mach-octeon/cvmx-helper-pko.c diff --git a/arch/mips/mach-octeon/cvmx-helper-pko.c b/arch/mips/mach-octeon/cvmx-helper-pko.c new file mode 100644 index 000000000000..0dc7980b25f2 --- /dev/null +++ b/arch/mips/mach-octeon/cvmx-helper-pko.c @@ -0,0 +1,312 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2018-2022 Marvell International Ltd. + * + * Helper Functions for the PKO + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +static s64 pko_fpa_config_pool = -1; +static u64 pko_fpa_config_size = 1024; +static u64 pko_fpa_config_count; + +/** + * cvmx_override_pko_queue_priority(int pko_port, u64 + * priorities[16]) is a function pointer. It is meant to allow + * customization of the PKO queue priorities based on the port + * number. Users should set this pointer to a function before + * calling any cvmx-helper operations. + */ +void (*cvmx_override_pko_queue_priority)(int ipd_port, + uint8_t *priorities) = NULL; + +void cvmx_pko_set_cmd_que_pool_config(s64 pool, u64 buffer_size, + u64 buffer_count) +{ + pko_fpa_config_pool = pool; + pko_fpa_config_size = buffer_size; + pko_fpa_config_count = buffer_count; +} + +void cvmx_pko_set_cmd_queue_pool_buffer_count(u64 buffer_count) +{ + pko_fpa_config_count = buffer_count; +} + +void cvmx_pko_get_cmd_que_pool_config(cvmx_fpa_pool_config_t *pko_pool) +{ + pko_pool->pool_num = pko_fpa_config_pool; + pko_pool->buffer_size = pko_fpa_config_size; + pko_pool->buffer_count = pko_fpa_config_count; +} + +int64_t cvmx_fpa_get_pko_pool(void) +{ + return pko_fpa_config_pool; +} + +/** + * Gets the buffer size of pko pool + */ +u64 cvmx_fpa_get_pko_pool_block_size(void) +{ + return pko_fpa_config_size; +} + +/** + * Gets the buffer size of pko pool + */ +u64 cvmx_fpa_get_pko_pool_buffer_count(void) +{ + return pko_fpa_config_count; +} + +/** + * Initialize PKO command queue buffer pool + */ +static int cvmx_helper_pko_pool_init(void) +{ + u8 pool; + unsigned int buf_count; + unsigned int pkt_buf_count; + int rc; + + /* Reserve pool */ + pool = cvmx_fpa_get_pko_pool(); + + /* Avoid redundant pool creation */ + if (cvmx_fpa_get_block_size(pool) > 0) { +#ifdef DEBUG + debug("WARNING: %s: pool %d already initialized\n", __func__, + pool); +#endif + /* It is up to the app to have sufficient buffer count */ + return pool; + } + + /* Calculate buffer count: one per queue + 3-word-cmds * max_pkts */ + pkt_buf_count = cvmx_fpa_get_packet_pool_buffer_count(); + buf_count = CVMX_PKO_MAX_OUTPUT_QUEUES + (pkt_buf_count * 3) / 8; + + /* Allocate pools for pko command queues */ + rc = __cvmx_helper_initialize_fpa_pool(pool, + cvmx_fpa_get_pko_pool_block_size(), + buf_count, "PKO Cmd-bufs"); + + if (rc < 0) + debug("%s: ERROR: in PKO buffer pool\n", __func__); + + pool = rc; + return pool; +} + +/** + * Initialize the PKO + * + */ +int cvmx_helper_pko_init(void) +{ + int rc; + + rc = cvmx_helper_pko_pool_init(); + if (rc < 0) + return rc; + + __cvmx_helper_init_port_config_data(0); + + cvmx_pko_hw_init(cvmx_fpa_get_pko_pool(), + cvmx_fpa_get_pko_pool_block_size()); + return 0; +} + +/** + * @INTERNAL + * Setup the PKO for the ports on an interface. The number of + * queues per port and the priority of each PKO output queue + * is set here. PKO must be disabled when this function is called. + * + * @param interface to setup PKO for + * + * @return Zero on success, negative on failure + * + * @note This is for PKO1/PKO2, and is not used for PKO3. + */ +int __cvmx_helper_interface_setup_pko(int interface) +{ + /* + * Each packet output queue has an associated priority. The + * higher the priority, the more often it can send a packet. A + * priority of 8 means it can send in all 8 rounds of + * contention. We're going to make each queue one less than + * the last. The vector of priorities has been extended to + * support CN5xxx CPUs, where up to 16 queues can be + * associated to a port. To keep backward compatibility we + * don't change the initial 8 priorities and replicate them in + * the second half. With per-core PKO queues (PKO lockless + * operation) all queues have the same priority. + */ + /* uint8_t priorities[16] = {8,7,6,5,4,3,2,1,8,7,6,5,4,3,2,1}; */ + u8 priorities[16] = { [0 ... 15] = 8 }; + + /* + * Setup the IPD/PIP and PKO for the ports discovered + * above. Here packet classification, tagging and output + * priorities are set. + */ + int num_ports = cvmx_helper_ports_on_interface(interface); + + while (num_ports--) { + int ipd_port; + + if (!cvmx_helper_is_port_valid(interface, num_ports)) + continue; + + ipd_port = cvmx_helper_get_ipd_port(interface, num_ports); + /* + * Give the user a chance to override the per queue + * priorities. + */ + if (cvmx_override_pko_queue_priority) + cvmx_override_pko_queue_priority(ipd_port, priorities); + + cvmx_pko_config_port(ipd_port, + cvmx_pko_get_base_queue(ipd_port), + cvmx_pko_get_num_queues(ipd_port), + priorities); + ipd_port++; + } + return 0; + /* NOTE: + * Now this function is called for all chips including 68xx, + * but on the 68xx it does not enable multiple pko_iports per + * eport, while before it was doing 3 pko_iport per eport + * buf the reason for that is not clear. + */ +} + +/** + * wait for the pko queue to drain + * + * @param queue a valid pko queue + * @return count is the length of the queue after calling this + * function + */ +static int cvmx_helper_wait_pko_queue_drain(int queue) +{ + const int timeout = 5; /* Wait up to 5 seconds for timeouts */ + int count; + u64 start_cycle; + + count = cvmx_pko_queue_pend_count(queue); + if (count < 0) + return count; + + start_cycle = get_timer(0); + + while (count > 0 && (get_timer(start_cycle) < timeout * 1000)) { + mdelay(1); + count = cvmx_pko_queue_pend_count(queue); + } + + return count; +} + +/** + * @INTERNAL + * + * Drain and wait until all PKO queues are empty. + */ +int __cvmx_helper_pko_drain(void) +{ + int result = 0; + + if (octeon_has_feature(OCTEON_FEATURE_PKND)) { + int queue, max_queue; + + /* PKO2 */ + max_queue = __cvmx_helper_cfg_pko_max_queue(); + for (queue = 0; queue < max_queue; queue++) { + if (cvmx_helper_wait_pko_queue_drain(queue)) { + result = -1; + return result; + } + } + } else { + int num_interfaces = cvmx_helper_get_number_of_interfaces(); + int interface, num_ports, index; + + /* PKO1 */ + for (interface = 0; interface < num_interfaces; interface++) { + num_ports = cvmx_helper_ports_on_interface(interface); + for (index = 0; index < num_ports; index++) { + int pko_port; + int queue; + int max_queue; + + if (!cvmx_helper_is_port_valid(interface, + index)) + continue; + pko_port = cvmx_helper_get_ipd_port(interface, + index); + queue = cvmx_pko_get_base_queue(pko_port); + max_queue = queue + + cvmx_pko_get_num_queues(pko_port); + while (queue < max_queue) { + if (cvmx_helper_wait_pko_queue_drain(queue)) { + result = -1; + return result; + } + queue++; + } + } + } + } + return result; +} -- 2.35.1