From patchwork Wed Dec 11 09:52:07 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiaojun Liu X-Patchwork-Id: 63743 X-Patchwork-Delegate: xiaolong.ye@intel.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id B521DA04F1; Wed, 11 Dec 2019 10:52:29 +0100 (CET) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id EAF011BF70; Wed, 11 Dec 2019 10:52:11 +0100 (CET) Received: from EUR01-VE1-obe.outbound.protection.outlook.com (mail-eopbgr140117.outbound.protection.outlook.com [40.107.14.117]) by dpdk.org (Postfix) with ESMTP id 8365B1BEC4 for ; Wed, 11 Dec 2019 10:52:10 +0100 (CET) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=bodpxItW5JGbEu1/2SDYdjWTDnmTmMd86BTr4JHqX/Oo1zQoi5ydpnCfr5Tr/+Xd537xHaZ5Gzqd3WB21JhDJZnZS+EB+tRUNNrt/HoP7nT4vrTe4i83cgufQoPCxb3OTA/0UWgjSGZgZpTInOCkQ89bcC/9r5k35zLR+7vstau/e3xL5lco3lWDd+W/GrJ3T5UMV/rA7gEhoCoDCmWSB+/dZwLuUujo41b397BGWsFMsWQBVdDxyWVhc7NfJqMn+tESEtFrz4jN43TNmyib+5/ElKl3LyQAsDPRW3jlcIEpu3x2arBWXJB0+sf83J7yDc/M/j284FC+2hyhvunqaA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=yezLZgyHsPMTDaJ02G9zAKRsXC3FWC7CrpBT7riDHqc=; b=PifOFd1HxzH8jTck4Y89ufG5yauEpSFITzVlozxMLKSCrTWPw7THii6FhjtHakQfIIwKbc0X5ruS19Xdzp9WcbOWN8q+qjh6IVQy9+CC2MG2IhTAMQKVAfFxRqMv/NBDqiylF/YeuyP8E5ANbNxdP36w8k75QafRKsss2kGumHOrgAP+wFUxcHy7mP1EP7DBdjZAassbklVfsvtEGxdchN4LxWS11DWtyB8IEhmmy0+XYHbZ0WdHdbrm6GXsp+nd7Z+cEeB0EHRVe81zERpqPfbhRlp9L8yVcpHq+2CEd3IqU4fvXswu371jH5ZE705jWIGfQU5032EYY2/c2/idGw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=silicom.co.il; dmarc=pass action=none header.from=silicom.co.il; dkim=pass header.d=silicom.co.il; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=SILICOMLTD.onmicrosoft.com; s=selector2-SILICOMLTD-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=yezLZgyHsPMTDaJ02G9zAKRsXC3FWC7CrpBT7riDHqc=; b=wgzegaDH0xgDFTTnGp82G56hRmSUrszj6wLgx/WNeeSZH4XV+wl52FcLho//2s9y+NrOj9B+4ByJ4DU0EIqcyCKWtykDM2rZImdw5lq7Zw44uIg3B+/5pasaoiCQInDh6vR3ZOSu9uvW6cTYaBwUH0YJ8QkGVsp1e29RMliVPJc= Received: from DB7PR04MB5196.eurprd04.prod.outlook.com (20.176.234.140) by DB7PR04MB4203.eurprd04.prod.outlook.com (52.135.131.12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2538.14; Wed, 11 Dec 2019 09:52:07 +0000 Received: from DB7PR04MB5196.eurprd04.prod.outlook.com ([fe80::cdaa:fcae:322b:59ed]) by DB7PR04MB5196.eurprd04.prod.outlook.com ([fe80::cdaa:fcae:322b:59ed%7]) with mapi id 15.20.2516.018; Wed, 11 Dec 2019 09:52:07 +0000 From: Xiaojun Liu To: "xiao.w.wang@intel.com" , "qi.z.zhang@intel.com" , "ngai-mint.kwan@intel.com" , "jakub.fornal@intel.co" , "jacob.e.keller@intel.com" CC: "dev@dpdk.org" , Xiaojun Liu Thread-Topic: [PATCH v2 3/7] net/fm10k: add config ffu statistics support Thread-Index: AQHVsAimuLj90oPUBUmPd2ppt77Zzw== Date: Wed, 11 Dec 2019 09:52:07 +0000 Message-ID: <1576057875-7677-4-git-send-email-xiaojun.liu@silicom.co.il> References: <1576057875-7677-1-git-send-email-xiaojun.liu@silicom.co.il> In-Reply-To: <1576057875-7677-1-git-send-email-xiaojun.liu@silicom.co.il> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-clientproxiedby: HK2PR02CA0180.apcprd02.prod.outlook.com (2603:1096:201:21::16) To DB7PR04MB5196.eurprd04.prod.outlook.com (2603:10a6:10:1a::12) authentication-results: spf=none (sender IP is ) smtp.mailfrom=xiaojun.liu@silicom.co.il; x-ms-exchange-messagesentrepresentingtype: 1 x-mailer: git-send-email 1.8.3.1 x-originating-ip: [113.110.226.253] x-ms-publictraffictype: Email x-ms-office365-filtering-correlation-id: 499b82db-da7e-449f-5338-08d77e1fc8c7 x-ms-traffictypediagnostic: DB7PR04MB4203: x-ms-exchange-transport-forked: True x-microsoft-antispam-prvs: x-ms-oob-tlc-oobclassifiers: OLM:113; x-forefront-prvs: 024847EE92 x-forefront-antispam-report: SFV:NSPM; SFS:(10019020)(346002)(366004)(136003)(39850400004)(376002)(396003)(199004)(189003)(51234002)(2906002)(71200400001)(81156014)(64756008)(316002)(66556008)(6506007)(44832011)(8676002)(52116002)(81166006)(26005)(66476007)(54906003)(110136005)(66946007)(186003)(36756003)(30864003)(6512007)(4326008)(86362001)(2616005)(107886003)(6486002)(66446008)(8936002)(5660300002)(478600001)(579004)(569006); DIR:OUT; SFP:1102; SCL:1; SRVR:DB7PR04MB4203; H:DB7PR04MB5196.eurprd04.prod.outlook.com; FPR:; SPF:None; LANG:en; PTR:InfoNoRecords; A:1; MX:1; received-spf: None (protection.outlook.com: silicom.co.il does not designate permitted sender hosts) x-ms-exchange-senderadcheck: 1 x-microsoft-antispam: BCL:0; x-microsoft-antispam-message-info: 5D2Se+r5Khhx4T30qe9tbnqehMYR+DDLpCLyu4q5i8SV+QHoMl8bC0H/vlZ+9EaJlo2Tf6IRNAKJM5URWu/LskkK0ndF4Se1WwZoBFwULY8MAhP8hSAbowc8jwpgzZ2XG7d1o2eYLlM6mATfyR8aPJaXqI4W29LeIQzsqy3qJzHHtez8uZeffeC/dzeueqbxM9FJUJFETNSfytI1VsGT5V3KsyUdaXQI48W2C8HQP/oreeEXlC4ad6RsyyS8dN9jcV8N5cM2v2Sg1N6WN8MM0kkDixMoMMlUork8jM/yVewfNgWqsSQOsDGuE+NpkBz6abVPfpIjoxU7SqrL94xxpitILsqNB461yQqhCMf+MKlfBYB2Bf4DywNemaSCaEqPnPO36FCi5GtDeCs10eUlIaZC0QoAi9Opedi682segLIwKL8We5C3XuIORrfzqfqA0GJpI/gquRi5iSpmkTfNOfqLquROfMVpofy4rdgayT6quzD4Crn9YoluNnIybx0PtkN6KF5PCJcqGWl7S1ZEjQ== MIME-Version: 1.0 X-OriginatorOrg: silicom.co.il X-MS-Exchange-CrossTenant-Network-Message-Id: 499b82db-da7e-449f-5338-08d77e1fc8c7 X-MS-Exchange-CrossTenant-originalarrivaltime: 11 Dec 2019 09:52:07.5715 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: c9e326d8-ce47-4930-8612-cc99d3c87ad1 X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: OtMqw7L6dx0ylgcbvTE2DmCmaaVvweY5oFxkE7iL7jjBOWyMYz8Z3aarfcVRbrkj6Y/uVpgAvj4RDnkvGUfYtrSWJKE5VuIgw81Htj/pwiU= X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB7PR04MB4203 Subject: [dpdk-dev] [PATCH v2 3/7] net/fm10k: add config ffu statistics support X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" To support switch management, add the following new files: Add fm10k/switch/fm10k_config.h. Add fm10k/switch/fm10k_config.c(support switch configuration) Add fm10k/switch/fm10k_ffu.h Add fm10k/switch/fm10k_ffu.c(support switch ffu rule) Add fm10k/switch/fm10k_stats.h Add fm10k/switch/fm10k_stats.c(support switch statistics) and modify fm10k/Makefile(add fm10k_config.c, fm10k_ffu.c, and fm10k_stats.c). To avoid configuration for both kernel driver and userspace SDK outside DPDK, we add switch management in FM10K DPDK PMD driver. To enable switch management, you need add CONFIG_RTE_FM10K_MANAGEMENT=y in config/common_linux when building. Signed-off-by: Xiaojun Liu --- drivers/net/fm10k/Makefile | 3 + drivers/net/fm10k/switch/fm10k_config.c | 855 +++++++++++++++++++++ drivers/net/fm10k/switch/fm10k_config.h | 171 +++++ drivers/net/fm10k/switch/fm10k_ffu.c | 1209 ++++++++++++++++++++++++++++++ drivers/net/fm10k/switch/fm10k_ffu.h | 31 + drivers/net/fm10k/switch/fm10k_stats.c | 1242 +++++++++++++++++++++++++++++++ drivers/net/fm10k/switch/fm10k_stats.h | 257 +++++++ 7 files changed, 3768 insertions(+) create mode 100644 drivers/net/fm10k/switch/fm10k_config.c create mode 100644 drivers/net/fm10k/switch/fm10k_config.h create mode 100644 drivers/net/fm10k/switch/fm10k_ffu.c create mode 100644 drivers/net/fm10k/switch/fm10k_ffu.h create mode 100644 drivers/net/fm10k/switch/fm10k_stats.c create mode 100644 drivers/net/fm10k/switch/fm10k_stats.h diff --git a/drivers/net/fm10k/Makefile b/drivers/net/fm10k/Makefile index 4ec2a80..ed73251 100644 --- a/drivers/net/fm10k/Makefile +++ b/drivers/net/fm10k/Makefile @@ -90,6 +90,9 @@ SRCS-$(CONFIG_RTE_LIBRTE_FM10K_PMD) += fm10k_sbus.c SRCS-$(CONFIG_RTE_LIBRTE_FM10K_PMD) += fm10k_serdes.c SRCS-$(CONFIG_RTE_LIBRTE_FM10K_PMD) += fm10k_sm.c SRCS-$(CONFIG_RTE_LIBRTE_FM10K_PMD) += fm10k_spico_code.c +SRCS-$(CONFIG_RTE_LIBRTE_FM10K_PMD) += fm10k_stats.c +SRCS-$(CONFIG_RTE_LIBRTE_FM10K_PMD) += fm10k_ffu.c +SRCS-$(CONFIG_RTE_LIBRTE_FM10K_PMD) += fm10k_config.c endif SRCS-$(CONFIG_RTE_LIBRTE_FM10K_INC_VECTOR) += fm10k_rxtx_vec.c diff --git a/drivers/net/fm10k/switch/fm10k_config.c b/drivers/net/fm10k/switch/fm10k_config.c new file mode 100644 index 0000000..46c3fae --- /dev/null +++ b/drivers/net/fm10k/switch/fm10k_config.c @@ -0,0 +1,855 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright 2019 Silicom Ltd. Connectivity Solutions + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include "../base/fm10k_type.h" +#include "../base/fm10k_osdep.h" + +#include "../fm10k.h" +#include "../fm10k_logs.h" +#include "fm10k_debug.h" +#include "fm10k_regs.h" +#include "fm10k_switch.h" +#include "fm10k_config.h" + +#define FM10K_CONFIG_WORD_MAX 10 +#define FM10K_CONFIG_WORD_LEN 20 +#define FM10K_CONFIG_STR_MAX 100 + +struct fm10k_cfg_key_item { + const char *key_str[FM10K_CONFIG_WORD_MAX]; + uint8_t type; +}; + +static const char *fm10k_config_dpdk_conf_file = "/etc/dpdk_fm10k.conf"; +static struct fm10k_dpdk_cfg fm10k_config_dpdk_cfg; + +static struct fm10k_cfg_key_item fm10k_config_key_items[] = { + /* debug configuration */ + { {"debug", "print", "enable"}, + FM10K_CONFIG_DEBUG_ENABLE}, + { {"debug", "print", "config"}, + FM10K_CONFIG_DEBUG_CONFIG}, + { {"debug", "print", "ffu", "init"}, + FM10K_CONFIG_DEBUG_FFU_INIT}, + { {"debug", "print", "ffu", "register"}, + FM10K_CONFIG_DEBUG_FFU_REG}, + { {"debug", "print", "ffu", "rule"}, + FM10K_CONFIG_DEBUG_FFU_RULE}, + { {"debug", "print", "stats", "port"}, + FM10K_CONFIG_DEBUG_STATS_PORT}, + { {"debug", "print", "stats", "queue"}, + FM10K_CONFIG_DEBUG_STATS_QUEUE}, + { {"debug", "print", "stats", "rule"}, + FM10K_CONFIG_DEBUG_STATS_FFU}, + { {"debug", "print", "stats", "detail"}, + FM10K_CONFIG_DEBUG_STATS_MORE}, + { {"debug", "print", "stats", "interval"}, + FM10K_CONFIG_DEBUG_STATS_INTERVAL}, + /* general configuration */ + { {"dpdk", "bind", "pf", "number"}, + FM10K_CONFIG_BIND_PF_NUMBER}, + { {"extern", "port", "speed"}, + FM10K_CONFIG_EXT_PORT_SPEED}, + /* internal redirect configuration */ + { {"dpdk", "port", "*", "map", "pf"}, + FM10K_CONFIG_DPDK_PORT_MAP_PF}, + { {"extern", "port", "*", "map", "pf"}, + FM10K_CONFIG_EXT_PORT_MAP_PF}, + /* external redirect configuration */ + { {"flowset", "start"}, + FM10K_CONFIG_FLOWSET_START}, + { {"flowset", "stop"}, + FM10K_CONFIG_FLOWSET_STOP}, + { {"flowset", "enable"}, + FM10K_CONFIG_FLOWSET_ENABLE}, + { {"flow", "*", "condition", "source", "extern", "port"}, + FM10K_CONFIG_FLOW_COND_SRC_EXT_PORT}, + { {"flow", "*", "condition", "source", "dpdk", "port"}, + FM10K_CONFIG_FLOW_COND_SRC_DPDK_PORT}, + { {"flow", "*", "condition", "vlan"}, + FM10K_CONFIG_FLOW_COND_VLAN}, + { {"flow", "*", "action", "forward", "extern", "port"}, + FM10K_CONFIG_FLOW_ACT_FW_EXT_PORT}, + { {"flow", "*", "action", "forward", "dpdk", "port"}, + FM10K_CONFIG_FLOW_ACT_FW_DPDK_PORT}, + { {"flow", "*", "action", "forward", "vlan"}, + FM10K_CONFIG_FLOW_ACT_FW_VALN}, +}; + +static char default_flowset[10] = "default"; + +static struct fm10k_cfg_config_item fm10k_silc_nic_2ext_2pep[] = { + { FM10K_CONFIG_BIND_PF_NUMBER, FM10K_CONFIG_VALUE_INT, 0, + "# Tell how many PF ports are bound in DPDK.\n" + "# Driver will check the number when initializes.", + .val.int64 = 2 + }, + { FM10K_CONFIG_EXT_PORT_SPEED, FM10K_CONFIG_VALUE_INT, 0, + "# Set external port speed, 40 means 40G, 100 means 100G.", + .val.int64 = 100 + }, + { FM10K_CONFIG_DPDK_PORT_MAP_PF, FM10K_CONFIG_VALUE_INT, 0, + "# Map 1 or 2 PF ports to one DPDK port.\n" + "# If mapped PF number is 2, traffic will be\n" + "# load balance between the 2 PF.\n" + "# And the DPDK port queue number will be configured\n" + "# more than 2(each PF need at least 1 DPDK port queue).", + .val.int64 = 0 + }, + { FM10K_CONFIG_DPDK_PORT_MAP_PF, FM10K_CONFIG_VALUE_INT, 1, + "", + .val.int64 = 1 + }, + { FM10K_CONFIG_EXT_PORT_MAP_PF, FM10K_CONFIG_VALUE_INT, 1, + "# Map 1 or 2 PF to one external port. If mapped PF number is 2,\n" + "# traffic will be load balance between the 2 PF. ", + .val.int64 = 0 + }, + { FM10K_CONFIG_EXT_PORT_MAP_PF, FM10K_CONFIG_VALUE_INT, 2, + "", + .val.int64 = 1 + }, + { FM10K_CONFIG_FLOWSET_START, FM10K_CONFIG_VALUE_STR, 0, + "# Define flow rule", + .val.str = default_flowset + }, + { FM10K_CONFIG_FLOWSET_STOP, FM10K_CONFIG_VALUE_STR, 0, + "", + .val.str = default_flowset + }, + { FM10K_CONFIG_FLOWSET_ENABLE, FM10K_CONFIG_VALUE_STR, 0, + "", + .val.str = default_flowset + }, + { FM10K_CONFIG_TYPE_NULL, 0, 0, + "", + .val.int64 = 0 + }, +}; + +static struct fm10k_cfg_config_item fm10k_silc_nic_2ext_4pep[] = { + { FM10K_CONFIG_BIND_PF_NUMBER, FM10K_CONFIG_VALUE_INT, 0, + "# Tell how many PF ports are bound in DPDK.\n" + "# Driver will check the number when initializes.", + .val.int64 = 4 + }, + + { FM10K_CONFIG_EXT_PORT_SPEED, FM10K_CONFIG_VALUE_INT, 0, + "# Set external port speed, 40 means 40G, 100 means 100G.", + .val.int64 = 100 + }, + { FM10K_CONFIG_DPDK_PORT_MAP_PF, FM10K_CONFIG_VALUE_INT, 0, + "# Map 1 or 2 PF ports to one DPDK port.\n" + "# If mapped PF number is 2, traffic will be\n" + "# load balance between the 2 PFs.\n" + "# And the DPDK port queue number will be configured\n" + "# more than 2(each PF need at least 1 DPDK port queue).", + .val.int64 = 0 + }, + { FM10K_CONFIG_DPDK_PORT_MAP_PF, FM10K_CONFIG_VALUE_INT, 0, + "", + .val.int64 = 2 + }, + { FM10K_CONFIG_DPDK_PORT_MAP_PF, FM10K_CONFIG_VALUE_INT, 1, + "", + .val.int64 = 1 + }, + { FM10K_CONFIG_DPDK_PORT_MAP_PF, FM10K_CONFIG_VALUE_INT, 1, + "", + .val.int64 = 3 + }, + { FM10K_CONFIG_EXT_PORT_MAP_PF, FM10K_CONFIG_VALUE_INT, 1, + "# Map 1 or 2 PF to one external port. If mapped PF number is 2,\n" + "# traffic will be load balance between the 2 PF.", + .val.int64 = 0 + }, + { FM10K_CONFIG_EXT_PORT_MAP_PF, FM10K_CONFIG_VALUE_INT, 1, + "", + .val.int64 = 2 + }, + { FM10K_CONFIG_EXT_PORT_MAP_PF, FM10K_CONFIG_VALUE_INT, 2, + "", + .val.int64 = 1 + }, + { FM10K_CONFIG_EXT_PORT_MAP_PF, FM10K_CONFIG_VALUE_INT, 2, + "", + .val.int64 = 3 + }, + { FM10K_CONFIG_FLOWSET_START, FM10K_CONFIG_VALUE_STR, 0, + "# Define flow rule", + .val.str = default_flowset + }, + { FM10K_CONFIG_FLOWSET_STOP, FM10K_CONFIG_VALUE_STR, 0, + "", + .val.str = default_flowset + }, + { FM10K_CONFIG_FLOWSET_ENABLE, FM10K_CONFIG_VALUE_STR, 0, + "", + .val.str = default_flowset + }, + { FM10K_CONFIG_TYPE_NULL, 0, 0, + "", + .val.int64 = 0 + }, +}; + + +static int +fm10k_config_conf_line_parser(char *buff, struct fm10k_cfg_config_item *item) +{ + char *p; + char *endptr; + const char *cfg_delims = { " " }; + const char *key_delims = { "." }; + struct fm10k_cfg_key_item *key; + char cfgs[3][FM10K_CONFIG_STR_MAX]; + char cmp_keys[FM10K_CONFIG_WORD_MAX][FM10K_CONFIG_WORD_LEN]; + long key_param = 0; + uint16_t i, j; + uint8_t val_type = FM10K_CONFIG_VALUE_NULL; + + for (i = 0; i < 3; i++) { + if (i == 0) + p = strtok(buff, cfg_delims); + else + p = strtok(NULL, cfg_delims); + if (p == NULL) + return -1; + strncpy(cfgs[i], p, FM10K_CONFIG_STR_MAX); + } + + p = strtok(NULL, cfg_delims); + if (p) + return -1; + + memset(cmp_keys, 0, sizeof(cmp_keys)); + for (i = 0; i < FM10K_CONFIG_WORD_MAX; i++) { + if (i == 0) + p = strtok(cfgs[0], key_delims); + else + p = strtok(NULL, key_delims); + if (p == NULL) + break; + strncpy(cmp_keys[i], p, FM10K_CONFIG_WORD_LEN); + } + + if (strcmp(cfgs[1], "int") == 0) + val_type = FM10K_CONFIG_VALUE_INT; + else if (strcmp(cfgs[1], "string") == 0) + val_type = FM10K_CONFIG_VALUE_STR; + else + return -1; + + for (i = 0; + i < sizeof(fm10k_config_key_items) / + sizeof(fm10k_config_key_items[0]); + i++) { + key = &fm10k_config_key_items[i]; + for (j = 0; j < FM10K_CONFIG_WORD_MAX; j++) { + if (key->key_str[j] && + strlen(cmp_keys[j]) > 0) { + if (strcmp(key->key_str[j], "*") == 0) { + key_param = + strtol(cmp_keys[j], &endptr, 10); + if ((key_param == 0 && + endptr == cmp_keys[j]) || + (endptr != cmp_keys[j] && + strlen(endptr) != 0)) + break; + } else if (strcmp(key->key_str[j], + cmp_keys[j]) != 0) { + break; + } + } else if (key->key_str[j] == 0 && + strlen(cmp_keys[j]) == 0) { + if (val_type == FM10K_CONFIG_VALUE_STR) { + item->val.str = + malloc(strlen(cfgs[2]) + 1); + if (item->val.str == NULL) + return -1; + strcpy(item->val.str, cfgs[2]); + } else { + item->val.int64 = + strtol(cfgs[2], NULL, 10); + } + item->type = key->type; + item->key_param = key_param; + item->val_type = val_type; + return 0; + } + } + } + return -1; +} + +static bool +fm10k_config_blank_line_check(char *line) +{ + uint16_t i; + + for (i = 0; i < strlen(line); i++) { + if (line[i] == ' ' || + line[i] == '\n' || + line[i] == '\t' || line[i] == 0x0d) /* 0d: CR */ + continue; + else + return false; + } + return true; +} + +static int +fm10k_config_conf_file_load(void) +{ + int i = 0; + FILE *fp; + char buff[255]; + struct fm10k_cfg_config_item *item; + + fp = fopen(fm10k_config_dpdk_conf_file, "r"); + if (fp == NULL) + return -1; + + fm10k_config_dpdk_cfg.config_list = malloc + (sizeof(struct fm10k_cfg_config_item) * FM10K_SW_CONFIG_MAX); + if (fm10k_config_dpdk_cfg.config_list == NULL) + return -1; + memset(fm10k_config_dpdk_cfg.config_list, 0, + sizeof(struct fm10k_cfg_config_item) * FM10K_SW_CONFIG_MAX); + + while (fgets(buff, sizeof(buff), fp)) { + if (buff[0] == '#' || buff[0] == 0) + continue; + + if (fm10k_config_blank_line_check(buff)) + continue; + + item = &fm10k_config_dpdk_cfg.config_list[i++]; + if (fm10k_config_conf_line_parser(buff, item) < 0) { + FM10K_SW_ERR("Unknown configuration: %s", buff); + return -1; + } + } + + return 0; +} + +struct fm10k_hw* +fm10k_config_hw_get(int port_no) +{ + int hw_port; + + hw_port = fm10k_config_dpdk_cfg.dpdk_port_map[port_no].map_no[0]; + return fm10k_config_dpdk_cfg.pf_hw[hw_port]; +} + +struct fm10k_cfg_flowset * +fm10k_config_flowset_current_get(void) +{ + return fm10k_config_dpdk_cfg.current; +} + +void +fm10k_config_flowset_current_set(struct fm10k_cfg_flowset *new) +{ + fm10k_config_dpdk_cfg.current = new; +} + +bool +fm10k_config_flow_list_end(struct fm10k_cfg_flow *list, + struct fm10k_cfg_flow *flow) +{ + return (list == flow); +} + +static void +fm10k_config_flow_list_init(struct fm10k_cfg_flow *list) +{ + list->next = list; + list->prev = list; +} + +static void +fm10k_config_flow_list_add(struct fm10k_cfg_flow *new, + struct fm10k_cfg_flow *list) +{ + struct fm10k_cfg_flow *next = list->next; + next->prev = new; + new->next = next; + new->prev = list; + list->next = new; +} + +void +fm10k_config_flow_list_add_tail(struct fm10k_cfg_flowset *flowset, + struct fm10k_cfg_flow *flow) +{ + fm10k_config_flow_list_add(flow, flowset->flow_head.prev); +} + +void +fm10k_config_flow_list_delete(struct fm10k_cfg_flow *flow) +{ + flow->prev->next = flow->next; + flow->next->prev = flow->prev; + flow->prev = NULL; + flow->next = NULL; +} + +struct fm10k_cfg_flowset * +fm10k_config_flowset_get(const char *name) +{ + struct fm10k_cfg_flowset *flowset; + + flowset = fm10k_config_dpdk_cfg.flowset_head.next; + while (flowset) { + if (strcmp(flowset->name, name) == 0) + break; + flowset = flowset->next; + } + + if (flowset == NULL) { + flowset = malloc(sizeof(struct fm10k_cfg_flowset)); + if (flowset == NULL) + return NULL; + strcpy(flowset->name, name); + fm10k_config_flow_list_init(&flowset->flow_head); + flowset->next = fm10k_config_dpdk_cfg.flowset_head.next; + fm10k_config_dpdk_cfg.flowset_head.next = flowset; + } + return flowset; +} + + +static int +fm10k_cfg_flow_item_set(struct fm10k_cfg_flowset *flowset, + uint8_t flow_no, uint8_t type, int64_t val) +{ + struct fm10k_cfg_flow *tmp; + struct fm10k_cfg_flow *flow = NULL; + + if (flowset == NULL) + return -1; + + tmp = flowset->flow_head.next; + while (!fm10k_config_flow_list_end(&flowset->flow_head, tmp)) { + if (tmp->flow_no == flow_no) { + flow = tmp; + break; + } + tmp = tmp->next; + } + if (flow == NULL) { + flow = malloc(sizeof(struct fm10k_cfg_flow)); + memset(flow, 0, sizeof(struct fm10k_cfg_flow)); + flow->flow_no = flow_no; + fm10k_config_flow_list_add_tail(flowset, flow); + } + if (flow == NULL) + return -1; + + switch (type) { + case FM10K_CONFIG_FLOW_COND_SRC_EXT_PORT: + flow->src_port.port_type = FM10K_CONFIG_FLOW_EXT_PORT; + flow->src_port.port_no = val; + break; + case FM10K_CONFIG_FLOW_COND_SRC_DPDK_PORT: + flow->src_port.port_type = FM10K_CONFIG_FLOW_DPDK_PORT; + flow->src_port.port_no = val; + break; + case FM10K_CONFIG_FLOW_COND_VLAN: + flow->src_port.vlan_id = val; + break; + case FM10K_CONFIG_FLOW_ACT_FW_EXT_PORT: + if (flow->fw_port[0].port_type == FM10K_CONFIG_FLOW_NONE_PORT) { + flow->fw_port[0].port_type = FM10K_CONFIG_FLOW_EXT_PORT; + flow->fw_port[0].port_no = val; + } else { + flow->fw_port[1].port_type = FM10K_CONFIG_FLOW_EXT_PORT; + flow->fw_port[1].port_no = val; + } + break; + case FM10K_CONFIG_FLOW_ACT_FW_DPDK_PORT: + if (flow->fw_port[0].port_type == FM10K_CONFIG_FLOW_NONE_PORT) { + flow->fw_port[0].port_type = + FM10K_CONFIG_FLOW_DPDK_PORT; + flow->fw_port[0].port_no = val; + } else { + flow->fw_port[1].port_type = + FM10K_CONFIG_FLOW_DPDK_PORT; + flow->fw_port[1].port_no = val; + } + break; + case FM10K_CONFIG_FLOW_ACT_FW_VALN: + if (flow->fw_port[0].vlan_id == 0) + flow->fw_port[0].vlan_id = val; + else + flow->fw_port[1].vlan_id = val; + break; + default: + return -1; + } + + return 0; +} + +static int +fm10k_config_conf_file_transfer(void) +{ + int i; + int offset; + uint32_t tmp, data; + struct fm10k_cfg_config_item *item; + struct fm10k_cfg_flowset *flowset = NULL; + struct fm10k_cfg_port_pf_map *map; + + for (i = 0; i < FM10K_SW_CONFIG_MAX; i++) { + item = &fm10k_config_dpdk_cfg.config_list[i]; + if (item->type == FM10K_CONFIG_TYPE_NULL) + break; + + switch (item->type) { + case FM10K_CONFIG_BIND_PF_NUMBER: + fm10k_config_dpdk_cfg.pf_num = item->val.int64; + break; + case FM10K_CONFIG_EXT_PORT_SPEED: + fm10k_config_dpdk_cfg.ext_port_speed = item->val.int64; + break; + case FM10K_CONFIG_DPDK_PORT_MAP_PF: + map = + &fm10k_config_dpdk_cfg.dpdk_port_map[item->key_param]; + if (map->type == FM10K_CONFIG_PORT_MAP_PF) { + map->type = FM10K_CONFIG_PORT_MAP_PFS; + map->map_no[1] = item->val.int64; + } else { + map->type = FM10K_CONFIG_PORT_MAP_PF; + map->map_no[0] = item->val.int64; + } + break; + case FM10K_CONFIG_EXT_PORT_MAP_PF: + map = + &fm10k_config_dpdk_cfg.ext_port_map + [item->key_param - 1]; + if (map->type == FM10K_CONFIG_PORT_MAP_PF) { + map->type = FM10K_CONFIG_PORT_MAP_PFS; + map->map_no[1] = item->val.int64; + } else { + map->type = FM10K_CONFIG_PORT_MAP_PF; + map->map_no[0] = item->val.int64; + } + break; + + case FM10K_CONFIG_DEBUG_ENABLE: + case FM10K_CONFIG_DEBUG_CONFIG: + case FM10K_CONFIG_DEBUG_FFU_INIT: + case FM10K_CONFIG_DEBUG_FFU_REG: + case FM10K_CONFIG_DEBUG_FFU_RULE: + case FM10K_CONFIG_DEBUG_STATS_PORT: + case FM10K_CONFIG_DEBUG_STATS_QUEUE: + case FM10K_CONFIG_DEBUG_STATS_FFU: + case FM10K_CONFIG_DEBUG_STATS_MORE: + offset = item->type - FM10K_CONFIG_DEBUG_START; + tmp = fm10k_config_dpdk_cfg.debug_cfg; + data = 1; + if (item->val.int64 != 1) + fm10k_config_dpdk_cfg.debug_cfg = + tmp & ~(data << offset); + else + fm10k_config_dpdk_cfg.debug_cfg |= + (data << offset); + break; + case FM10K_CONFIG_DEBUG_STATS_INTERVAL: + fm10k_config_dpdk_cfg.stats_interval = item->val.int64; + break; + + case FM10K_CONFIG_FLOWSET_START: + /* skip /n */ + item->val.str[strlen(item->val.str) - 1] = 0; + flowset = fm10k_config_flowset_get(item->val.str); + if (flowset == NULL) + return -1; + break; + case FM10K_CONFIG_FLOWSET_STOP: + flowset = NULL; + break; + case FM10K_CONFIG_FLOWSET_ENABLE: + /* skip /n */ + item->val.str[strlen(item->val.str) - 1] = 0; + fm10k_config_dpdk_cfg.current = + fm10k_config_flowset_get(item->val.str); + break; + case FM10K_CONFIG_FLOW_COND_SRC_EXT_PORT: + case FM10K_CONFIG_FLOW_COND_SRC_DPDK_PORT: + case FM10K_CONFIG_FLOW_COND_VLAN: + case FM10K_CONFIG_FLOW_ACT_FW_EXT_PORT: + case FM10K_CONFIG_FLOW_ACT_FW_DPDK_PORT: + case FM10K_CONFIG_FLOW_ACT_FW_VALN: + if (flowset == NULL || + fm10k_cfg_flow_item_set(flowset, + item->key_param, item->type, + item->val.int64) != 0) + return -1; + break; + default: + return -1; + } + } + return 0; +} + +static bool +fm10k_config_conf_file_exist(void) +{ + if (access(fm10k_config_dpdk_conf_file, 0) == 0) + return true; + return false; +} + +static int +fm10k_config_conf_file_item_create(FILE *fp, char *buff, + struct fm10k_cfg_key_item *key, + struct fm10k_cfg_config_item *item) +{ + int i; + + if (item->type != key->type) + return 0; + + for (i = 0; i < FM10K_CONFIG_WORD_MAX; i++) { + if (key->key_str[i] == 0) + break; + if (i == 0) { + sprintf(buff + strlen(buff), + "%s", key->key_str[i]); + } else { + if (strcmp(key->key_str[i], "*") == 0) + sprintf(buff + strlen(buff), + ".%u", item->key_param); + else + sprintf(buff + strlen(buff), + ".%s", key->key_str[i]); + } + } + if (item->val_type == FM10K_CONFIG_VALUE_INT) + sprintf(buff + strlen(buff), + " int %lld\n", (long long)item->val.int64); + else if (item->val_type == FM10K_CONFIG_VALUE_STR) + sprintf(buff + strlen(buff), " string %s\n", item->val.str); + else + return -1; + fwrite(buff, strlen(buff), 1, fp); + FM10K_SW_TRACE("[write] %s", buff); + + return 0; +} + +static int +fm10k_config_conf_file_create(void) +{ + uint16_t i, j; + struct fm10k_cfg_key_item *key; + struct fm10k_cfg_config_item *item; + FILE *fp; + char buff[255] = ""; + + fp = fopen(fm10k_config_dpdk_conf_file, "w"); + if (fp == NULL) + return -1; + + for (i = 0; i < FM10K_SW_CONFIG_MAX; i++) { + item = &fm10k_config_dpdk_cfg.config_list[i]; + if (item->type == FM10K_CONFIG_TYPE_NULL) + break; + buff[0] = 0; + if (strlen(item->describe) > 0) + sprintf(buff, "\n\n%s\n", item->describe); + for (j = 0; + j < sizeof(fm10k_config_key_items) / + sizeof(fm10k_config_key_items[0]); + j++) { + key = &fm10k_config_key_items[j]; + if (fm10k_config_conf_file_item_create + (fp, buff, key, item) != 0) { + fclose(fp); + return -1; + } + } + } + fclose(fp); + return 0; +} + +void +fm10k_config_cfg_flowset_show(void) +{ + struct fm10k_cfg_flowset *flowset; + + printf(" FLOWSET ENABLE: %s\n", fm10k_config_dpdk_cfg.current->name); + + flowset = fm10k_config_dpdk_cfg.flowset_head.next; + while (flowset) { + printf("\n FLOWSET : %s\n", flowset->name); + struct fm10k_cfg_flow *flow = flowset->flow_head.next; + while (!fm10k_config_flow_list_end(&flowset->flow_head, flow)) { + const char *port_type[3] = { "NON", "EXT", "DPDK" }; + if (flow->fw_port[1].port_type != + FM10K_CONFIG_FLOW_NONE_PORT) { + printf(" FLOW %d : %4s PORT %d VLAN %4d --> " + "%4s PORT %d VLAN %4d & %4s PORT %d VLAN %4d\n", + flow->flow_no, + port_type[flow->src_port.port_type], + flow->src_port.port_no, + flow->src_port.vlan_id, + port_type[flow->fw_port[0].port_type], + flow->fw_port[0].port_no, + flow->fw_port[0].vlan_id, + port_type[flow->fw_port[1].port_type], + flow->fw_port[1].port_no, + flow->fw_port[1].vlan_id); + } else { + printf(" FLOW %d : %4s PORT %d VLAN %4d --> " + "%4s PORT %d VLAN %4d\n", + flow->flow_no, + port_type[flow->src_port.port_type], + flow->src_port.port_no, + flow->src_port.vlan_id, + port_type[flow->fw_port[0].port_type], + flow->fw_port[0].port_no, + flow->fw_port[0].vlan_id); + } + flow = flow->next; + } + flowset = flowset->next; + } +} + +static void +fm10k_config_cfg_describe(struct fm10k_switch *sw, + struct fm10k_device_info *info) +{ + uint16_t i; + struct fm10k_cfg_flowset *flowset; + + if (!fm10k_config_check_debug(sw->dpdk_cfg, FM10K_CONFIG_DEBUG_CONFIG)) + return; + + printf("--- FM10K STATIC CONFIG ---\n"); + printf(" Card Type: %s\n", info->desc); + printf(" PF Max : %d\n", fm10k_config_dpdk_cfg.pf_max); + printf(" PF Bind : %d\n", fm10k_config_dpdk_cfg.pf_num); + printf(" DEBUG : %#x\n", fm10k_config_dpdk_cfg.debug_cfg); + printf(" STATS GAP: %d sec\n", fm10k_config_dpdk_cfg.stats_interval); + printf(" EXT PORT speed: %d Gbps\n", + fm10k_config_dpdk_cfg.ext_port_speed); + printf(" FLOWSET ENABLE: %s\n", fm10k_config_dpdk_cfg.current->name); + + for (i = 0; i < fm10k_config_dpdk_cfg.ext_port_num; i++) { + if (fm10k_config_dpdk_cfg.ext_port_map[i].type == + FM10K_CONFIG_PORT_MAP_NULL) + continue; + if (fm10k_config_dpdk_cfg.ext_port_map[i].type == + FM10K_CONFIG_PORT_MAP_PF) + printf(" EXT PORT[%d] MAP: PF%d\n", i + 1, + fm10k_config_dpdk_cfg.ext_port_map[i].map_no[0]); + else + printf(" EXT PORT[%d] MAP: PF%d PF%d\n", i + 1, + fm10k_config_dpdk_cfg.ext_port_map[i].map_no[0], + fm10k_config_dpdk_cfg.ext_port_map[i].map_no[1]); + } + + for (i = 0; i < FM10K_SW_LOGICAL_PORTS_MAX; i++) { + if (fm10k_config_dpdk_cfg.dpdk_port_map[i].type == + FM10K_CONFIG_PORT_MAP_NULL) + continue; + if (fm10k_config_dpdk_cfg.ext_port_map[i].type == + FM10K_CONFIG_PORT_MAP_PF) + printf(" DPDK PORT[%d] MAP: PF%d\n", i, + fm10k_config_dpdk_cfg.dpdk_port_map[i].map_no[0]); + else + printf(" DPDK PORT[%d] MAP: PF%d PF%d\n", i, + fm10k_config_dpdk_cfg.dpdk_port_map[i].map_no[0], + fm10k_config_dpdk_cfg.dpdk_port_map[i].map_no[1]); + } + + flowset = fm10k_config_dpdk_cfg.flowset_head.next; + while (flowset) { + printf("\n FLOWSET : %s\n", flowset->name); + struct fm10k_cfg_flow *flow = flowset->flow_head.next; + while (!fm10k_config_flow_list_end(&flowset->flow_head, flow)) { + const char *port_type[3] = { "NON", "EXT", "DPDK" }; + if (flow->fw_port[1].port_type != + FM10K_CONFIG_FLOW_NONE_PORT) { + printf(" FLOW %d : %4s PORT %d VLAN %4d --> " + "%4s PORT %d VLAN %4d & %4s PORT %d " + "VLAN %4d\n", + flow->flow_no, + port_type[flow->src_port.port_type], + flow->src_port.port_no, + flow->src_port.vlan_id, + port_type[flow->fw_port[0].port_type], + flow->fw_port[0].port_no, + flow->fw_port[0].vlan_id, + port_type[flow->fw_port[1].port_type], + flow->fw_port[1].port_no, + flow->fw_port[1].vlan_id); + } else { + printf(" FLOW %d : %4s PORT %d VLAN %4d --> " + "%4s PORT %d VLAN %4d\n", + flow->flow_no, + port_type[flow->src_port.port_type], + flow->src_port.port_no, + flow->src_port.vlan_id, + port_type[flow->fw_port[0].port_type], + flow->fw_port[0].port_no, + flow->fw_port[0].vlan_id); + } + flow = flow->next; + } + flowset = flowset->next; + } + printf("\n"); +} + +int +fm10k_config_init(struct fm10k_switch *sw, struct fm10k_hw *hw) +{ + struct fm10k_device_info *info = fm10k_get_device_info(hw); + + fm10k_config_dpdk_cfg.stats_interval = 2; + fm10k_config_dpdk_cfg.pf_max = info->num_peps; + fm10k_config_dpdk_cfg.ext_port_num = info->num_ext_ports; + + if (!fm10k_config_conf_file_exist()) { + if (info->num_epls == 2 && info->num_peps == 2) + fm10k_config_dpdk_cfg.config_list = + fm10k_silc_nic_2ext_2pep; + else if (info->num_epls == 2 && info->num_peps == 4) + fm10k_config_dpdk_cfg.config_list = + fm10k_silc_nic_2ext_4pep; + else + return -1; + + fm10k_config_conf_file_create(); + } else { + if (fm10k_config_conf_file_load() < 0) + return -1; + } + + if (fm10k_config_conf_file_transfer() < 0) + return -1; + sw->dpdk_cfg = &fm10k_config_dpdk_cfg; + + fm10k_config_cfg_describe(sw, info); + + return 0; +} diff --git a/drivers/net/fm10k/switch/fm10k_config.h b/drivers/net/fm10k/switch/fm10k_config.h new file mode 100644 index 0000000..f79df01 --- /dev/null +++ b/drivers/net/fm10k/switch/fm10k_config.h @@ -0,0 +1,171 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright 2019 Silicom Ltd. Connectivity Solutions + */ + +#ifndef _FM10K_CONFIG_H_ +#define _FM10K_CONFIG_H_ + + +#include +#include "fm10k_switch.h" + +/* General configuration */ +#define FM10K_CONFIG_TYPE_NULL 0 +#define FM10K_CONFIG_BIND_PF_NUMBER 1 +#define FM10K_CONFIG_EXT_PORT_SPEED 2 + +/* Internal redirect configuration */ +#define FM10K_CONFIG_DPDK_PORT_MAP_PF 10 +#define FM10K_CONFIG_EXT_PORT_MAP_PF 11 + +/* Debug configuration */ +#define FM10K_CONFIG_DEBUG_START 50 +#define FM10K_CONFIG_DEBUG_ENABLE (FM10K_CONFIG_DEBUG_START + 0) +#define FM10K_CONFIG_DEBUG_CONFIG (FM10K_CONFIG_DEBUG_START + 1) +#define FM10K_CONFIG_DEBUG_FFU_INIT (FM10K_CONFIG_DEBUG_START + 2) +#define FM10K_CONFIG_DEBUG_FFU_REG (FM10K_CONFIG_DEBUG_START + 3) +#define FM10K_CONFIG_DEBUG_FFU_RULE (FM10K_CONFIG_DEBUG_START + 4) +#define FM10K_CONFIG_DEBUG_STATS_PORT (FM10K_CONFIG_DEBUG_START + 5) +#define FM10K_CONFIG_DEBUG_STATS_QUEUE (FM10K_CONFIG_DEBUG_START + 6) +#define FM10K_CONFIG_DEBUG_STATS_FFU (FM10K_CONFIG_DEBUG_START + 7) +#define FM10K_CONFIG_DEBUG_STATS_MORE (FM10K_CONFIG_DEBUG_START + 8) +#define FM10K_CONFIG_DEBUG_STATS_INTERVAL (FM10K_CONFIG_DEBUG_START + 9) + +/* external redirect configuration */ +#define FM10K_CONFIG_FLOWSET_START 80 +#define FM10K_CONFIG_FLOWSET_STOP 81 +#define FM10K_CONFIG_FLOWSET_ENABLE 82 + +#define FM10K_CONFIG_FLOW_COND_START 100 +#define FM10K_CONFIG_FLOW_COND_SRC_EXT_PORT (FM10K_CONFIG_FLOW_COND_START + 0) +#define FM10K_CONFIG_FLOW_COND_SRC_DPDK_PORT (FM10K_CONFIG_FLOW_COND_START + 1) +#define FM10K_CONFIG_FLOW_COND_VLAN (FM10K_CONFIG_FLOW_COND_START + 2) +#define FM10K_CONFIG_FLOW_COND_END (FM10K_CONFIG_FLOW_COND_START + 2) + +#define FM10K_CONFIG_FLOW_ACT_START 200 +#define FM10K_CONFIG_FLOW_ACT_FW_EXT_PORT (FM10K_CONFIG_FLOW_ACT_START + 0) +#define FM10K_CONFIG_FLOW_ACT_FW_DPDK_PORT (FM10K_CONFIG_FLOW_ACT_START + 1) +#define FM10K_CONFIG_FLOW_ACT_FW_VALN (FM10K_CONFIG_FLOW_ACT_START + 2) +#define FM10K_CONFIG_FLOW_ACT_END (FM10K_CONFIG_FLOW_ACT_START + 2) + +#define FM10K_CONFIG_FLOW_NONE_PORT 0 +#define FM10K_CONFIG_FLOW_EXT_PORT 1 +#define FM10K_CONFIG_FLOW_DPDK_PORT 2 + +#define FM10K_CONFIG_VALUE_NULL 0 +#define FM10K_CONFIG_VALUE_INT 1 +#define FM10K_CONFIG_VALUE_STR 2 + +/* SWITCH config */ +#define FM10K_CONFIG_PORT_MAP_NULL 0 +#define FM10K_CONFIG_PORT_MAP_PF 1 +#define FM10K_CONFIG_PORT_MAP_PFS 2 +#define FM10K_CONFIG_PORT_MAP_PFSS 3 + +/* DPDK port */ +#define FM10K_CONFIG_DPDK_NULL 0 +#define FM10K_CONFIG_DPDK_PF 1 +#define FM10K_CONFIG_DPDK_VF 2 +#define FM10K_CONFIG_DPDK_MAX 3 + +struct fm10k_cfg_port_pf_map { + uint8_t type; + uint8_t map_no[2]; +}; + +/* Configuration read from file */ +struct fm10k_cfg_config_item { + uint8_t type; + uint8_t val_type; + uint16_t key_param; + const char *describe; + union { + int64_t int64; + char *str; + } val; +}; + +struct fm10k_hw; + +struct fm10k_dpdk_port { + uint8_t type; + struct fm10k_hw *hw; + void *rte_dev; + void *flow_list; + uint16_t pf_no; + uint8_t tx_queue_num; + uint8_t rx_queue_num; +}; + + +/* Flow configuration */ +struct fm10k_cfg_port { + uint8_t port_type; + uint8_t port_no; + uint16_t vlan_id; +}; + +struct fm10k_cfg_flow { + /* set by configuration */ + struct fm10k_cfg_flow *prev; + struct fm10k_cfg_flow *next; + uint8_t flow_no; /* only configured flow has this NO. */ + struct fm10k_cfg_port src_port; + struct fm10k_cfg_port fw_port[2]; + /* set by ffu rule add */ + uint16_t rule_id; +}; + +#define FM10K_CONFIG_FLOWSET_NAME_MAX 256 +struct fm10k_cfg_flowset { + char name[FM10K_CONFIG_FLOWSET_NAME_MAX]; + struct fm10k_cfg_flow flow_head; + struct fm10k_cfg_flowset *next; +}; + +/* Configuration */ +struct fm10k_dpdk_cfg { + uint8_t pf_num; /* configure by conf */ + uint8_t pf_bind; /* initialize by dpdk */ + uint8_t pf_max; /* set by card type */ + uint8_t ext_port_num; /* configure by conf */ + uint8_t ext_port_speed; /* configure by conf */ + uint32_t debug_cfg; /* configure by conf */ + uint32_t stats_interval;/* configure by conf */ + + struct fm10k_hw *master_hw; /* initialize by dpdk */ + struct fm10k_hw *pf_hw[FM10K_SW_PEP_PORTS_MAX]; /* initialize by dpdk */ + + /* initialize by dpdk */ + struct fm10k_dpdk_port ports[FM10K_SW_LOGICAL_PORTS_MAX]; + /* configure by conf or default*/ + struct fm10k_cfg_port_pf_map dpdk_port_map + [FM10K_SW_LOGICAL_PORTS_MAX]; + /* configure by conf */ + struct fm10k_cfg_port_pf_map ext_port_map[FM10K_SW_EXT_PORTS_MAX]; + struct fm10k_cfg_config_item *config_list; /* configure by conf */ + struct fm10k_cfg_flowset flowset_head; /* transfer from conf file */ + struct fm10k_cfg_flowset *current; +}; + +static inline bool +fm10k_config_check_debug(struct fm10k_dpdk_cfg *cfg, uint16_t dbg) +{ + return cfg->debug_cfg & 1 << (dbg - FM10K_CONFIG_DEBUG_START) && + cfg->debug_cfg & 1; +} + +struct fm10k_cfg_flowset *fm10k_config_flowset_get(const char *name); +struct fm10k_cfg_flowset *fm10k_config_flowset_current_get(void); +void fm10k_config_flowset_current_set(struct fm10k_cfg_flowset *new); +void fm10k_config_flow_list_add_tail(struct fm10k_cfg_flowset *flowset, + struct fm10k_cfg_flow *flow); +void fm10k_config_flow_list_delete(struct fm10k_cfg_flow *flow); +bool fm10k_config_flow_list_end(struct fm10k_cfg_flow *list, + struct fm10k_cfg_flow *flow); + +void fm10k_config_cfg_flowset_show(void); +struct fm10k_hw *fm10k_config_hw_get(int port_no); +int fm10k_config_init(struct fm10k_switch *sw, struct fm10k_hw *hw); + +#endif /* _FM10K_CONFIG_H */ diff --git a/drivers/net/fm10k/switch/fm10k_ffu.c b/drivers/net/fm10k/switch/fm10k_ffu.c new file mode 100644 index 0000000..c2e8491 --- /dev/null +++ b/drivers/net/fm10k/switch/fm10k_ffu.c @@ -0,0 +1,1209 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright 2019 Silicom Ltd. Connectivity Solutions + */ + +#include +#include +#include +#include +#include +#include + +#include "../base/fm10k_type.h" +#include "../base/fm10k_osdep.h" + +#include "../fm10k.h" +#include "../fm10k_logs.h" +#include "fm10k_debug.h" +#include "fm10k_regs.h" +#include "fm10k_switch.h" +#include "fm10k_config.h" +#include "fm10k_ffu.h" +#include "fm10k_stats.h" + +/* + * one SLICE for 40bits SEL + * SLICE 28 FOR SEL SGLORT(16bits) and VLAN(16bits) + * FOR ACT ROUTE + * SLICE 29 FOR SEL ETHER_TYPE(16bits) + * FOR ACT MIRROR | SET_VLAN + * SLICE 30 FOR SEL MPLS_LABEL0(32bits) + * SLICE 31 FOR SEL MPLS_LABEL1(32bits) + */ +#define FM10K_FFU_SLICE_START 28 +#define FM10K_FFU_SLICE_SGLORT_VID 28 +#define FM10K_FFU_SLICE_ETYPE_VID2 29 +#define FM10K_FFU_SLICE_MPLS_LABEL0 30 +#define FM10K_FFU_SLICE_MPLS_LABEL1 31 + +#define FM10K_FFU_SLICE_SGLORT_VLAN_CFG \ + (FM10K_SW_MAKE_REG_FIELD64(FFU_SLICE_CFG_SELECT_0, \ + FM10K_SW_FFU_MUX_SEL_SGLORT) | \ + FM10K_SW_MAKE_REG_FIELD64(FFU_SLICE_CFG_SELECT_1, \ + FM10K_SW_FFU_MUX_SEL_SGLORT) | \ + FM10K_SW_MAKE_REG_FIELD64(FFU_SLICE_CFG_SELECT_2, \ + FM10K_SW_FFU_MUX_SEL_VPRI_VID) | \ + FM10K_SW_MAKE_REG_FIELD64(FFU_SLICE_CFG_SELECT_3, \ + FM10K_SW_FFU_MUX_SEL_VPRI_VID) | \ + FM10K_SW_FFU_SLICE_CFG_START_ACTION | \ + FM10K_SW_FFU_SLICE_CFG_START_COMPARE | \ + FM10K_SW_FFU_SLICE_CFG_VALID_LOW) + +#define FM10K_FFU_SLICE_ETHER_TYPE_CFG \ + (FM10K_SW_MAKE_REG_FIELD64(FFU_SLICE_CFG_SELECT_0, \ + FM10K_SW_FFU_MUX_SEL_L2_TYPE) | \ + FM10K_SW_MAKE_REG_FIELD64(FFU_SLICE_CFG_SELECT_1, \ + FM10K_SW_FFU_MUX_SEL_L2_TYPE) | \ + FM10K_SW_MAKE_REG_FIELD64(FFU_SLICE_CFG_SELECT_2, \ + FM10K_SW_FFU_MUX_SEL_VPRI2_VID2) | \ + FM10K_SW_MAKE_REG_FIELD64(FFU_SLICE_CFG_SELECT_3, \ + FM10K_SW_FFU_MUX_SEL_VPRI2_VID2) | \ + FM10K_SW_FFU_SLICE_CFG_VALID_LOW) + +#define FM10K_FFU_SLICE_MPLS_LABEL0_CFG \ + (FM10K_SW_MAKE_REG_FIELD64(FFU_SLICE_CFG_SELECT_0, \ + FM10K_SW_FFU_MUX_SEL_L3_SIP_127_96) | \ + FM10K_SW_MAKE_REG_FIELD64(FFU_SLICE_CFG_SELECT_1, \ + FM10K_SW_FFU_MUX_SEL_L3_SIP_127_96) | \ + FM10K_SW_MAKE_REG_FIELD64(FFU_SLICE_CFG_SELECT_2, \ + FM10K_SW_FFU_MUX_SEL_L3_SIP_127_96) | \ + FM10K_SW_MAKE_REG_FIELD64(FFU_SLICE_CFG_SELECT_3, \ + FM10K_SW_FFU_MUX_SEL_L3_SIP_127_96) | \ + FM10K_SW_FFU_SLICE_CFG_START_COMPARE | \ + FM10K_SW_FFU_SLICE_CFG_VALID_LOW) + +#define FM10K_FFU_SLICE_MPLS_LABEL1_CFG \ + (FM10K_SW_MAKE_REG_FIELD64(FFU_SLICE_CFG_SELECT_0, \ + FM10K_SW_FFU_MUX_SEL_L3_SIP_95_64) | \ + FM10K_SW_MAKE_REG_FIELD64(FFU_SLICE_CFG_SELECT_1, \ + FM10K_SW_FFU_MUX_SEL_L3_SIP_95_64) | \ + FM10K_SW_MAKE_REG_FIELD64(FFU_SLICE_CFG_SELECT_2, \ + FM10K_SW_FFU_MUX_SEL_L3_SIP_95_64) | \ + FM10K_SW_MAKE_REG_FIELD64(FFU_SLICE_CFG_SELECT_3, \ + FM10K_SW_FFU_MUX_SEL_L3_SIP_95_64) | \ + FM10K_SW_FFU_SLICE_CFG_START_COMPARE | \ + FM10K_SW_FFU_SLICE_CFG_VALID_LOW) + +static uint64_t fm10k_ffu_slice_cfgs[4] = { + FM10K_FFU_SLICE_SGLORT_VLAN_CFG, + FM10K_FFU_SLICE_ETHER_TYPE_CFG, + FM10K_FFU_SLICE_MPLS_LABEL0_CFG, + FM10K_FFU_SLICE_MPLS_LABEL1_CFG +}; + +#define FM10K_FFU_INIT_PRINT(cfg, ...) do { \ + if (fm10k_config_check_debug(cfg, FM10K_CONFIG_DEBUG_FFU_INIT)) \ + printf(__VA_ARGS__); \ +} while (0) + +#define FM10K_FFU_RULE_PRINT(cfg, ...) do { \ + if (fm10k_config_check_debug(cfg, FM10K_CONFIG_DEBUG_FFU_RULE)) \ + printf(__VA_ARGS__); \ +} while (0) + +#define FM10K_FFU_CNT_INDEX(x) (FM10K_SW_FFU_CNT_START + (x)) + +#define FM10K_FFU_FLOW_START 10 +#define FM10K_FFU_MIRROR_PROFILE 1 + +#define FM10K_FFU_SGLORT_TYPE_NULL 0 +#define FM10K_FFU_SGLORT_TYPE_EPL 1 +#define FM10K_FFU_SGLORT_TYPE_PF 2 +#define FM10K_FFU_SGLORT_TYPE_PFS 3 +#define FM10K_FFU_SGLORT_TYPE_DPDK 4 + +struct fm10k_ffu_rule_data { + uint16_t sglort_type; + uint16_t cond_sglort; + uint16_t cond_vlan; + uint16_t act_dglort; + uint16_t act_vlan; + uint16_t bypass_dglort; + uint16_t bypass_vlan; +}; + + +static uint8_t fm10k_ffu_bitmap[FM10K_FFU_RULE_MAX / 8]; +static uint8_t +fm10k_ffu_rule_get_bit(int id) +{ + int num = id / 8; + int offset = id % 8; + + return (fm10k_ffu_bitmap[num] >> offset) & 0x1; +} + +static void +fm10k_ffu_rule_set_bit(int id, uint8_t bit) +{ + int num = id / 8; + int offset = id % 8; + uint8_t tmp = fm10k_ffu_bitmap[num]; + uint8_t data = 1; + + if (bit == 0) + fm10k_ffu_bitmap[num] = tmp & ~(data << offset); + else + fm10k_ffu_bitmap[num] |= (data << offset); +} + +static int +fm10k_ffu_rule_alloc(void) +{ + int i; + + for (i = FM10K_FFU_FLOW_START; i < FM10K_FFU_RULE_MAX; i++) { + if (fm10k_ffu_rule_get_bit(i) != 0) + continue; + fm10k_ffu_rule_set_bit(i, 1); + return i; + } + return -1; +} + +static void +fm10k_ffu_rule_free(int id) +{ + fm10k_ffu_rule_set_bit(id, 0); +} + +static void +fm10k_ffu_always_mismatch(struct fm10k_switch *sw, + unsigned int slice, unsigned int idx) +{ + uint64_t temp64; + + temp64 = + FM10K_SW_MAKE_REG_FIELD64(FFU_SLICE_TCAM_KEY, ~0ULL) | + FM10K_SW_MAKE_REG_FIELD64(FFU_SLICE_TCAM_KEY_TOP, ~0ULL); + fm10k_write_switch_reg128(sw, FM10K_SW_FFU_SLICE_TCAM(slice, idx), + temp64, temp64); +} + +static void +fm10k_ffu_route_dglort(struct fm10k_switch *sw, unsigned int slice, + unsigned int idx, uint16_t sglort, uint16_t dglort) +{ + uint64_t temp64, temp64_2; + + /* + * Set the key to exact match on the 16 SGLORT bits and + * always match everywhere else. + */ + temp64 = FM10K_SW_MAKE_REG_FIELD64(FFU_SLICE_TCAM_KEY, sglort); + temp64_2 = + FM10K_SW_MAKE_REG_FIELD64(FFU_SLICE_TCAM_KEY, ~sglort & 0xffff); + fm10k_write_switch_reg128(sw, + FM10K_SW_FFU_SLICE_TCAM(slice, idx), + temp64_2, temp64); + + /* + * Set the corresponding SRAM entry to ROUTE_GLORT to the + * corresponding DGLORT. + */ + temp64 = 0x40; + temp64 = temp64 << 32 | + FM10K_SW_MAKE_REG_FIELD(FFU_SLICE_SRAM_ROUTE_GLORT_DGLORT, dglort); + temp64 |= + FM10K_SW_MAKE_REG_FIELD64(FFU_SLICE_SRAM_COMMAND, + FM10K_SW_FFU_SLICE_SRAM_COMMAND_ROUTE_GLORT); + /* + * 11.5.4.2 FFU_SLICE_SRAM[0..31][0..1023] + */ + temp64_2 = + FM10K_SW_FFU_CNT_BANK << (35 - 23) | + (FM10K_SW_FFU_CNT_START + idx); + temp64 |= temp64_2 << 23; + fm10k_write_switch_reg64(sw, + FM10K_SW_FFU_SLICE_SRAM(slice, idx), temp64); +} + + +static void +fm10k_ffu_set_dest_glort_mask(struct fm10k_switch *sw, + unsigned int idx, uint16_t dglort, uint64_t dport_mask) +{ + uint64_t temp64; + unsigned int multiple_dports; + unsigned int num_dports; + unsigned int amplification_factor; + unsigned int hashed_entries; + unsigned int i, j; + + multiple_dports = (dport_mask & (dport_mask - 1)); + + FM10K_FFU_INIT_PRINT(sw->dpdk_cfg, + "%s set glort %#x to port ", __func__, dglort); + /* + * Create an exact-match key for the given DGLORT in the DGLORT CAM. + */ + fm10k_write_switch_reg(sw, FM10K_SW_GLORT_CAM(idx), + FM10K_SW_MAKE_REG_FIELD(GLORT_CAM_KEY, dglort) | + FM10K_SW_MAKE_REG_FIELD(GLORT_CAM_KEY_INVERT, ~dglort)); + + if (multiple_dports) { + /* + * Create a pair of entries and use the hash value to select + * among them. + */ + num_dports = 0; + for (i = 0; i < FM10K_SW_LOGICAL_PORTS_MAX; i++) + if (dport_mask & (1ULL << i)) { + num_dports++; + FM10K_FFU_INIT_PRINT(sw->dpdk_cfg, " %d", i); + } + FM10K_FFU_INIT_PRINT(sw->dpdk_cfg, "\n"); + + /* + * Create multiple entries for each dport to increase the + * hash modulus and capture more hash entropy. The maximum + * number of hashed entries is 16. + */ + amplification_factor = 16 / num_dports; + hashed_entries = num_dports * amplification_factor; + temp64 = + FM10K_SW_MAKE_REG_FIELD64(GLORT_RAM_STRICT, + FM10K_SW_GLORT_RAM_STRICT_HASHED); + temp64 |= + FM10K_SW_MAKE_REG_FIELD64(GLORT_RAM_DEST_INDEX, + sw->glort_dest_table_idx); + temp64 |= + FM10K_SW_MAKE_REG_FIELD64(GLORT_RAM_DEST_COUNT, + hashed_entries); + fm10k_write_switch_reg64(sw, FM10K_SW_GLORT_RAM(idx), temp64); + + for (i = 0; i < FM10K_SW_LOGICAL_PORTS_MAX; i++) + if (dport_mask & (1ULL << i)) + for (j = 0; j < amplification_factor; j++) { + fm10k_write_switch_reg64(sw, + FM10K_SW_GLORT_DEST_TABLE + (sw->glort_dest_table_idx), + FM10K_SW_MAKE_REG_FIELD64 + (GLORT_DEST_TABLE_MASK, + (1ULL << i))); + sw->glort_dest_table_idx++; + } + } else { + /* + * Set the corresponding entry in the DGLORT map RAM to use + * strict indexing straight into the DEST_TABLE, then write + * the corresponding destination port in the DEST_TABLE. + */ + + temp64 = + FM10K_SW_MAKE_REG_FIELD64(GLORT_RAM_STRICT, + FM10K_SW_GLORT_RAM_STRICT_STRICT); + temp64 |= + FM10K_SW_MAKE_REG_FIELD64(GLORT_RAM_DEST_INDEX, + sw->glort_dest_table_idx); + fm10k_write_switch_reg64(sw, + FM10K_SW_GLORT_RAM(idx), temp64); + + fm10k_write_switch_reg64(sw, + FM10K_SW_GLORT_DEST_TABLE(sw->glort_dest_table_idx), + FM10K_SW_MAKE_REG_FIELD64 + (GLORT_DEST_TABLE_MASK, + dport_mask)); + sw->glort_dest_table_idx++; + for (i = 0; i < FM10K_SW_LOGICAL_PORTS_MAX; i++) + if (dport_mask & (1ULL << i)) + FM10K_FFU_INIT_PRINT(sw->dpdk_cfg, " %d\n", i); + } +} + + +static uint32_t +fm10k_ffu_set_dest_glort_multi_cast(struct fm10k_switch *sw, + uint8_t lport1, uint8_t lport2, + uint16_t vlan1, uint16_t vlan2) +{ + uint32_t dglort; + bool is_new; + uint32_t idx; + uint64_t temp64; + + dglort = + fm10k_switch_multi_glort_get(lport1, lport2, + vlan1, vlan2, &is_new); + + if (!is_new) + return dglort; + + FM10K_FFU_INIT_PRINT(sw->dpdk_cfg, + "%s set glort %#x to (%d:%d) (%d:%d)\n", + __func__, dglort, lport1, vlan1, lport2, vlan2); + /* + * Create an exact-match key for the given DGLORT in the DGLORT CAM. + */ + idx = sw->glort_cam_ram_idx++; + fm10k_write_switch_reg(sw, FM10K_SW_GLORT_CAM(idx), + FM10K_SW_MAKE_REG_FIELD(GLORT_CAM_KEY, dglort) | + FM10K_SW_MAKE_REG_FIELD(GLORT_CAM_KEY_INVERT, ~dglort)); + + /* + * Create multiple entries for each dport to increase the + * hash modulus and capture more hash entropy. The maximum + * number of hashed entries is 16. + */ + temp64 = + FM10K_SW_MAKE_REG_FIELD64(GLORT_RAM_STRICT, + FM10K_SW_GLORT_RAM_STRICT_STRICT); + temp64 |= + FM10K_SW_MAKE_REG_FIELD64(GLORT_RAM_DEST_INDEX, + sw->glort_dest_table_idx); + fm10k_write_switch_reg64(sw, + FM10K_SW_GLORT_RAM(idx), temp64); + + /* GLORT_DEST_TABLE + * Field Name Bit(s) Type Default + * DestMask 47:0 RW 0x0 + * IP_MulticastIndex59:48 RW 0x0 + * Reserved 63:60 RSV 0x0 + */ + temp64 = sw->mcast_dest_table_idx; + temp64 = temp64 << 48 | 1 << lport1 | 1 << lport2; + fm10k_write_switch_reg64(sw, + FM10K_SW_GLORT_DEST_TABLE + (sw->glort_dest_table_idx), temp64); + sw->glort_dest_table_idx++; + + /* MCAST_DEST_TABLE + * Field Name Bit(s) Type Default + * PortMask 47:0 RW 0x0 + * LenTableIdx 61:48 RW 0x0 + * Reserved 63:62 RSV 00b + */ + temp64 = sw->mcast_len_table_idx; + temp64 = 1 << lport1 | 1 << lport2 | temp64 << 48; + fm10k_write_switch_reg64(sw, + FM10K_SW_SCHED_MCAST_DEST_TABLE + (sw->mcast_dest_table_idx++), temp64); + + /* MCAST_LEN_TABLE + * Field Name Bit(s) Type Default + * L3_McastIdx 14:0 RW 0x0 + * L3_Repcnt 26:15 RW 0x0 + * Reserved 31:27 RSV 0x0 + */ + temp64 = + sw->mcast_vlan_table_idx | 1 << 15; + fm10k_write_switch_reg64(sw, + FM10K_SW_SCHED_MCAST_LEN_TABLE + (sw->mcast_len_table_idx++), temp64); + + /* MCAST_VLAN_TABLE + * Field Name Bit(s) Type Default + * VID 11:0 RW 0x0 + * DGLORT 27:12 RW 0x0 + * ReplaceVID 28 RW 0b + * ReplaceDGLORT 29 RW 0b + * Reserved 31:30 RSV 00b + */ + temp64 = vlan1 | + fm10k_switch_pf_glort_get + (lport1) << 12 | 1 << 28 | 1 << 29; + fm10k_write_switch_reg64(sw, + FM10K_SW_MOD_MCAST_VLAN_TABLE + (sw->mcast_vlan_table_idx++), temp64); + temp64 = vlan2 | + fm10k_switch_pf_glort_get + (lport2) << 12 | 1 << 28 | 1 << 29; + fm10k_write_switch_reg64(sw, + FM10K_SW_MOD_MCAST_VLAN_TABLE + (sw->mcast_vlan_table_idx++), temp64); + + return dglort; +} + +static uint64_t +fm10k_data64_field64_get(uint64_t data, int start, int end) +{ + uint64_t tmp64 = data; + + if (start == end) { + tmp64 = (data >> start) & 1; + } else { + tmp64 = tmp64 << (64 - end); + tmp64 = tmp64 >> (64 - end + start); + } + return tmp64; +} + +static uint32_t +fm10k_data64_field32_get(uint64_t data, int start, int end) +{ + uint64_t tmp64 = data; + uint32_t tmp32; + + if (start == end) { + tmp32 = (data >> start) & 1; + } else { + tmp64 = tmp64 << (64 - end); + tmp32 = tmp64 >> (64 - end + start); + } + return tmp32; +} + +static uint32_t +fm10k_data32_field_get(uint32_t data, int start, int end) +{ + uint32_t tmp32 = data; + + if (start == end) { + tmp32 = (data >> start) & 1; + } else { + tmp32 = tmp32 << (64 - end); + tmp32 = tmp32 >> (64 - end + start); + } + return tmp32; +} + + +static void +fm10k_glort_register_dump(struct fm10k_switch *sw) +{ + uint32_t i; + uint64_t data64; + uint32_t data32; + uint32_t tmp32; + + if (!fm10k_config_check_debug + (sw->dpdk_cfg, FM10K_CONFIG_DEBUG_FFU_REG)) + return; + + printf("----- GLORT -----\n"); + + for (i = 0; i < sw->glort_cam_ram_idx; i++) { + data32 = fm10k_read_switch_reg(sw, FM10K_SW_GLORT_CAM(i)); + printf("[%02u]GLORT_CAM %#x Key %#x\n", i, data32, + fm10k_data32_field_get(data32, 0, 15)); + data64 = fm10k_read_switch_reg64(sw, FM10K_SW_GLORT_RAM(i)); + printf(" GLORT_RAM %#llx Strict %u DestIndex %u\n", + (unsigned long long)data64, + fm10k_data64_field32_get(data64, 0, 1), + fm10k_data64_field32_get(data64, 2, 13)); + tmp32 = fm10k_data64_field32_get(data64, 2, 13); + data64 = + fm10k_read_switch_reg64(sw, + FM10K_SW_GLORT_DEST_TABLE(tmp32)); + printf(" GLORT_DEST_TABLE[%u] %#llx IP_MulticastIndex %u\n", + tmp32, (unsigned long long)data64, + fm10k_data64_field32_get(data64, 48, 59)); + tmp32 = fm10k_data64_field32_get(data64, 48, 59); + if (tmp32 == 0) + continue; + data64 = fm10k_read_switch_reg64(sw, + FM10K_SW_SCHED_MCAST_DEST_TABLE(tmp32)); + printf(" SCHED_MCAST_DEST_TABLE[%u] %#llx PortMask %#llx" + " LenTableIdx %u\n", tmp32, + (unsigned long long)data64, + (unsigned long long) + fm10k_data64_field64_get(data64, 0, 47), + fm10k_data64_field32_get(data64, 48, 61)); + tmp32 = fm10k_data64_field32_get(data64, 48, 61); + data32 = fm10k_read_switch_reg(sw, + FM10K_SW_SCHED_MCAST_LEN_TABLE(tmp32)); + printf(" SCHED_MCAST_LEN_TABLE[%u] %#x " + "L3_McastIdx %u L3_Repcnt %u\n", + tmp32, data32, + fm10k_data32_field_get(data32, 0, 14), + fm10k_data32_field_get(data32, 15, 26)); + tmp32 = fm10k_data32_field_get(data32, 0, 14); + data32 = fm10k_read_switch_reg(sw, + FM10K_SW_MOD_MCAST_VLAN_TABLE(tmp32)); + printf(" MOD_MCAST_VLAN_TABLE[%u] %#x VID %u " + "DGLORT %#x ReplaceVID %u ReplaceDGLORT %u\n", + tmp32, data32, + fm10k_data32_field_get(data32, 0, 11), + fm10k_data32_field_get(data32, 12, 27), + fm10k_data32_field_get(data32, 28, 28), + fm10k_data32_field_get(data32, 29, 29)); + data32 = fm10k_read_switch_reg(sw, + FM10K_SW_MOD_MCAST_VLAN_TABLE(tmp32 + 1)); + printf(" MOD_MCAST_VLAN_TABLE[%u] %#x VID %u " + "DGLORT %#x ReplaceVID %u ReplaceDGLORT %u\n", + tmp32 + 1, data32, + fm10k_data32_field_get(data32, 0, 11), + fm10k_data32_field_get(data32, 12, 27), + fm10k_data32_field_get(data32, 28, 28), + fm10k_data32_field_get(data32, 29, 29)); + } +} + +static void +fm10k_ffu_register_dump(struct fm10k_switch *sw) +{ + int i, j; + uint32_t data[8]; + uint32_t ffu_valid; + + if (!fm10k_config_check_debug(sw->dpdk_cfg, FM10K_CONFIG_DEBUG_FFU_REG)) + return; + + printf("--------------- FFU REGISTERS DUMP ------------------\n"); + + fm10k_read_switch_array(sw, FM10K_SW_FFU_MASTER_VALID, data, 2); + printf("FFU_MASTER_VALID: %#x %#x\n", data[0], data[1]); + ffu_valid = data[0]; + + for (i = 0; i < 32; i++) { + if ((ffu_valid & (1 << i)) == 0) + continue; + + printf("------ SLICE%d ------\n", i); + fm10k_read_switch_array(sw, + FM10K_SW_FFU_SLICE_VALID(i), data, 2); + if (data[0] != 0 || data[1] != 0) + printf("FFU_SLICE_VALID[%d]: %#x %#x\n", + i, data[0], data[1]); + + fm10k_read_switch_array(sw, + FM10K_SW_FFU_SLICE_CASCADE_ACTION(i), data, 2); + if (data[0] != 0 || data[1] != 0) + printf("FFU_SLICE_CASCADE_ACTION[%d]: %#x %#x\n", + i, data[0], data[1]); + + for (j = 0; j < 1; j++) { + fm10k_read_switch_array(sw, + FM10K_SW_FFU_SLICE_CFG(i, j), data, 2); + if (data[0] != 0 || data[1] != 0) + printf("FFU_SLICE_CFG[%d][%d]: %#x %#x\n", + i, j, data[0], data[1]); + } + for (j = 0; j < 32; j++) { + fm10k_read_switch_array(sw, + FM10K_SW_FFU_SLICE_TCAM(i, j), data, 4); + if ((data[0] != 0 || data[1] != 0 || + data[2] != 0 || data[3] != 0)) + printf("FFU_SLICE_TCAM[%d][%d]: %#x %#x %#x %#x\n", + i, j, data[0], data[1], + data[2], data[3]); + + fm10k_read_switch_array(sw, + FM10K_SW_FFU_SLICE_SRAM(i, j), data, 2); + if (data[0] != 0 || data[1] != 0) + printf("FFU_SLICE_SRAM[%d][%d]: %#x %#x\n", + i, j, data[0], data[1]); + } + } +} + + +static void +fm10k_ffu_mirror_set_action(struct fm10k_switch *sw, + uint16_t ffu_slice, uint16_t table_idx) +{ + uint64_t data64; + + /* blank the next ffu slice */ + fm10k_write_switch_reg128(sw, + FM10K_SW_FFU_SLICE_TCAM + (ffu_slice, table_idx), 0xffffffffff, 0x1); + /* SET FFU RX_MIRROR */ + data64 = 0x60; /* higher than route, not necessary */ + data64 = data64 << 32 | 0x2 << 21 | 1 << (8 + 4) | 1 << 4; + fm10k_write_switch_reg64(sw, + FM10K_SW_FFU_SLICE_SRAM(ffu_slice, table_idx), data64); +} + +static void +fm10k_ffu_mirror_set_forward(struct fm10k_switch *sw, + int profile, + uint16_t vlan, + uint16_t dest_lport, + uint32_t dest_sglort) +{ + uint64_t data64; + + /* RX_MIRROR_CFG */ + fm10k_write_switch_reg(sw, 0xd50000 + 0xd, profile); + + /* FH_MIRROR_PROFILE_TABLE */ + fm10k_write_switch_reg(sw, + 0xd50000 + 0x1 * profile + 0x40, dest_lport); + + /* MOD_MIRROR_PROFILE_TABLE don't work */ + data64 = vlan; + data64 = (dest_sglort & 0xffff) | data64 << 17; + fm10k_write_switch_reg64(sw, + 0xe80000 + 0x2 * profile + 0x24000, data64); +} + + +int +fm10k_ffu_mirror_set(struct fm10k_switch *sw, + uint16_t src_ext_port, + uint16_t dest_ext_port, + uint16_t vlan) +{ + uint16_t table_idx; + uint16_t ffu_slice = FM10K_FFU_SLICE_SGLORT_VID + 1; + uint16_t mirror_profile = FM10K_FFU_MIRROR_PROFILE; + + table_idx = FM10K_FFU_EXT_PORT_RULE_INGRESS(src_ext_port - 1); + fm10k_ffu_mirror_set_action(sw, ffu_slice, table_idx); + + fm10k_ffu_mirror_set_forward(sw, mirror_profile, + vlan, sw->epl_map[dest_ext_port - 1].logical_port, + sw->epl_map[dest_ext_port - 1].glort); + return 0; +} + +int +fm10k_ffu_mirror_reset(struct fm10k_switch *sw, int src_ext_port) +{ + uint16_t table_idx; + uint16_t ffu_slice = FM10K_FFU_SLICE_SGLORT_VID + 1; + + table_idx = FM10K_FFU_EXT_PORT_RULE_INGRESS(src_ext_port - 1); + fm10k_write_switch_reg64(sw, + FM10K_SW_FFU_SLICE_SRAM(ffu_slice, table_idx), 0); + return 0; +} + +static void +fm10k_ffu_logical_port_vlan_set(struct fm10k_switch *sw, + uint16_t lport, uint16_t vlan_id) +{ + uint64_t data; + + /* 11.21.3.9 INGRESS_VID_TABLE[0..4095] */ + data = fm10k_read_switch_reg64(sw, + 0xE80000 + 0x2 * vlan_id + 0x20000); + data |= 1 << lport; + fm10k_write_switch_reg64(sw, + 0xE80000 + 0x2 * vlan_id + 0x20000, data); + + FM10K_FFU_RULE_PRINT(sw->dpdk_cfg, + "%s lport:%d, vlan_id:%d, reg:%#llx\n", + __func__, lport, vlan_id, (unsigned long long)data); +} + +static void +fm10k_ffu_glort_port_vlan_set(struct fm10k_switch *sw, + uint16_t glort, uint16_t vlan_id) +{ + int i; + + for (i = 0; i < FM10K_SW_PEPS_SUPPORTED; i++) { + if (sw->pep_map[i].glort == glort) { + fm10k_ffu_logical_port_vlan_set(sw, + sw->pep_map[i].logical_port, vlan_id); + break; + } + } + for (i = 0; i < FM10K_SW_EPLS_SUPPORTED; i++) { + if (sw->epl_map[i].glort == glort) { + fm10k_ffu_logical_port_vlan_set(sw, + sw->epl_map[i].logical_port, vlan_id); + break; + } + } +} + + +static uint16_t +fm10k_ffu_dpdk_port_glort_get(struct fm10k_switch *sw, int port) +{ + int pf; + uint16_t glort = 0; + + if (sw->dpdk_cfg->dpdk_port_map[port].type == + FM10K_CONFIG_PORT_MAP_PFS || + sw->dpdk_cfg->dpdk_port_map[port].type == + FM10K_CONFIG_PORT_MAP_PFSS) { + glort = fm10k_switch_pfs_glort_get + (sw->dpdk_cfg->dpdk_port_map[port].map_no[0], + sw->dpdk_cfg->dpdk_port_map[port].map_no[1]); + } else if (sw->dpdk_cfg->dpdk_port_map[port].type == + FM10K_CONFIG_PORT_MAP_PF) { + pf = sw->dpdk_cfg->dpdk_port_map[port].map_no[0]; + glort = fm10k_switch_pf_glort_get(pf); + } + return glort; +} + +static void +fm10k_ffu_rule_enable_single_cast(struct fm10k_switch *sw, + int rule_id, + uint16_t sglort, + uint16_t svlan, + uint16_t dglort, + uint16_t dvlan) +{ + uint64_t temp64; + uint64_t sglort_vid_tcam = 0, sglort_vid_tcam_mask = 0; + uint64_t sram[4] = { 0, 0, 0, 0 }; + uint16_t sram_idx = 0, tcam_slice, sram_slice, i; + + sglort_vid_tcam |= sglort; + sglort_vid_tcam_mask |= 0xffff; + if (svlan) { + temp64 = svlan; + sglort_vid_tcam |= temp64 << 16; + sglort_vid_tcam_mask |= 0xfff0000; + fm10k_ffu_glort_port_vlan_set(sw, sglort, svlan); + } + + /* set counter */ + sram[sram_idx] |= + FM10K_SW_MAKE_REG_FIELD64 + (FFU_SLICE_SRAM_COUNTER_BANK, + FM10K_SW_FFU_CNT_BANK) | + FM10K_SW_MAKE_REG_FIELD64 + (FFU_SLICE_SRAM_COUNTER_INDEX, + FM10K_FFU_CNT_INDEX(rule_id)); + + sram[sram_idx] |= + FM10K_SW_MAKE_REG_FIELD64 + (FFU_SLICE_SRAM_PRECEDENCE, 3) | + FM10K_SW_MAKE_REG_FIELD + (FFU_SLICE_SRAM_ROUTE_GLORT_DGLORT, dglort) | + FM10K_SW_MAKE_REG_FIELD64 + (FFU_SLICE_SRAM_COMMAND, + FM10K_SW_FFU_SLICE_SRAM_COMMAND_ROUTE_GLORT); + sram_idx++; + + if (dvlan) { + /* Force updating VLAN tag if present. + * Add if absent. 11.5.3.4 + */ + temp64 = 3; + sram[sram_idx] = + temp64 << 16 | dvlan | + FM10K_SW_MAKE_REG_FIELD64 + (FFU_SLICE_SRAM_PRECEDENCE, 2) | + FM10K_SW_MAKE_REG_FIELD64 + (FFU_SLICE_SRAM_COMMAND, + FM10K_SW_FFU_SLICE_SRAM_COMMAND_FIELD_SET); + fm10k_ffu_glort_port_vlan_set(sw, dglort, dvlan); + sram_idx++; + } + + if (sglort_vid_tcam) { + tcam_slice = FM10K_FFU_SLICE_SGLORT_VID; + temp64 = + FM10K_SW_MAKE_REG_FIELD64 + (FFU_SLICE_TCAM_KEY, + ~sglort_vid_tcam & sglort_vid_tcam_mask); + fm10k_write_switch_reg128(sw, + FM10K_SW_FFU_SLICE_TCAM(tcam_slice, rule_id), + temp64, sglort_vid_tcam); + FM10K_FFU_RULE_PRINT(sw->dpdk_cfg, + "TCAM slice:%d, rule:%d, data0:%#llx, data1:%#llx\n", + tcam_slice, rule_id, + (unsigned long long)sglort_vid_tcam, + (unsigned long long)temp64); + } + + /* blank the next SLICE TCAM */ + fm10k_ffu_always_mismatch(sw, tcam_slice + 1, rule_id); + + for (i = 0; i < sram_idx; i++) { + sram_slice = FM10K_FFU_SLICE_START + i; + fm10k_write_switch_reg64(sw, + FM10K_SW_FFU_SLICE_SRAM(sram_slice, rule_id), sram[i]); + FM10K_FFU_RULE_PRINT(sw->dpdk_cfg, + "SRAM slice:%d, rule:%d, data:%#llx\n", + sram_slice, rule_id, (unsigned long long)sram[i]); + } + /* disable the next SLICE SRAM */ + fm10k_write_switch_reg64(sw, + FM10K_SW_FFU_SLICE_SRAM(sram_slice + 1, rule_id), 0); + + fm10k_stats_rule_count_reg(rule_id); +} + +static void +fm10k_ffu_rule_enable_multi_cast(struct fm10k_switch *sw, + int rule_id, + uint16_t sglort, + uint16_t svlan, + uint8_t lport1, + uint8_t lport2, + uint16_t vlan1, + uint16_t vlan2) +{ + uint64_t temp64; + uint32_t dglort; + uint64_t sglort_vid_tcam = 0, sglort_vid_tcam_mask = 0; + uint64_t sram[4] = { 0, 0, 0, 0 }; + uint16_t sram_idx = 0, tcam_slice, sram_slice, i; + + dglort = + fm10k_ffu_set_dest_glort_multi_cast(sw, + lport1, lport2, vlan1, vlan2); + + sglort_vid_tcam |= sglort; + sglort_vid_tcam_mask |= 0xffff; + if (svlan) { + temp64 = svlan; + sglort_vid_tcam |= temp64 << 16; + sglort_vid_tcam_mask |= 0xfff0000; + fm10k_ffu_glort_port_vlan_set(sw, sglort, svlan); + } + + fm10k_ffu_logical_port_vlan_set(sw, lport1, vlan1); + fm10k_ffu_logical_port_vlan_set(sw, lport2, vlan2); + + /* set counter */ + sram[sram_idx] |= + FM10K_SW_MAKE_REG_FIELD64 + (FFU_SLICE_SRAM_COUNTER_BANK, + FM10K_SW_FFU_CNT_BANK) | + FM10K_SW_MAKE_REG_FIELD64 + (FFU_SLICE_SRAM_COUNTER_INDEX, + FM10K_FFU_CNT_INDEX(rule_id)); + + sram[sram_idx] |= + FM10K_SW_MAKE_REG_FIELD64 + (FFU_SLICE_SRAM_PRECEDENCE, 3) | + FM10K_SW_MAKE_REG_FIELD + (FFU_SLICE_SRAM_ROUTE_GLORT_DGLORT, dglort) | + FM10K_SW_MAKE_REG_FIELD64 + (FFU_SLICE_SRAM_COMMAND, + FM10K_SW_FFU_SLICE_SRAM_COMMAND_ROUTE_GLORT); + sram_idx++; + + if (sglort_vid_tcam) { + tcam_slice = FM10K_FFU_SLICE_SGLORT_VID; + temp64 = + FM10K_SW_MAKE_REG_FIELD64 + (FFU_SLICE_TCAM_KEY, + ~sglort_vid_tcam & sglort_vid_tcam_mask); + fm10k_write_switch_reg128(sw, + FM10K_SW_FFU_SLICE_TCAM(tcam_slice, rule_id), + temp64, sglort_vid_tcam); + FM10K_FFU_RULE_PRINT(sw->dpdk_cfg, + "TCAM slice:%d, rule:%d, data0:%#llx, data1:%#llx\n", + tcam_slice, rule_id, + (unsigned long long)sglort_vid_tcam, + (unsigned long long)temp64); + } + + /* blank the next SLICE TCAM */ + fm10k_ffu_always_mismatch(sw, tcam_slice + 1, rule_id); + + for (i = 0; i < sram_idx; i++) { + sram_slice = FM10K_FFU_SLICE_START + i; + fm10k_write_switch_reg64(sw, + FM10K_SW_FFU_SLICE_SRAM(sram_slice, rule_id), sram[i]); + FM10K_FFU_RULE_PRINT(sw->dpdk_cfg, + "SRAM slice:%d, rule:%d, data:%#llx\n", + sram_slice, rule_id, (unsigned long long)sram[i]); + } + /* disable the next SLICE SRAM */ + fm10k_write_switch_reg64(sw, + FM10K_SW_FFU_SLICE_SRAM(sram_slice + 1, rule_id), 0); + + fm10k_stats_rule_count_reg(rule_id); +} + + +void +fm10k_ffu_flow_enable(struct fm10k_switch *sw, struct fm10k_cfg_flow *flow) +{ + uint16_t sglort = 0; + uint16_t svlan = 0; + uint16_t dglort = 0; + uint16_t dvlan = 0; + uint16_t lport1 = 0, lport2 = 0; + uint16_t dvlan2 = 0; + + switch (flow->src_port.port_type) { + case FM10K_CONFIG_FLOW_EXT_PORT: + sglort = fm10k_switch_epl_glort_get(flow->src_port.port_no - 1); + break; + case FM10K_CONFIG_FLOW_DPDK_PORT: + sglort = + fm10k_ffu_dpdk_port_glort_get(sw, + flow->src_port.port_no); + break; + } + switch (flow->fw_port[0].port_type) { + case FM10K_CONFIG_FLOW_EXT_PORT: + dglort = + fm10k_switch_epl_glort_get + (flow->fw_port[0].port_no - 1); + lport1 = + fm10k_switch_epl_logical_get + (flow->fw_port[0].port_no - 1); + break; + case FM10K_CONFIG_FLOW_DPDK_PORT: + dglort = + fm10k_ffu_dpdk_port_glort_get + (sw, flow->fw_port[0].port_no); + lport1 = + fm10k_switch_pf_logical_get + (flow->fw_port[0].port_no); + break; + } + svlan = flow->src_port.vlan_id; + dvlan = flow->fw_port[0].vlan_id; + + flow->rule_id = fm10k_ffu_rule_alloc(); + + FM10K_FFU_RULE_PRINT(sw->dpdk_cfg, + "Set rule cond sglort:%#x, vlan:%d ==> " + "act dglort:%#x, vlan:%d", + sglort, svlan, dglort, dvlan); + + if (flow->fw_port[1].port_type) { + switch (flow->fw_port[1].port_type) { + case FM10K_CONFIG_FLOW_EXT_PORT: + dglort = + fm10k_switch_epl_glort_get + (flow->fw_port[1].port_no - 1); + lport2 = + fm10k_switch_epl_logical_get + (flow->fw_port[1].port_no - 1); + break; + case FM10K_CONFIG_FLOW_DPDK_PORT: + dglort = + fm10k_ffu_dpdk_port_glort_get + (sw, flow->fw_port[1].port_no); + lport2 = + fm10k_switch_pf_logical_get + (flow->fw_port[1].port_no); + break; + } + dvlan2 = flow->fw_port[1].vlan_id; + FM10K_FFU_RULE_PRINT(sw->dpdk_cfg, + " (bypass glort:%#x, vlan:%d)\n", + dglort, dvlan2); + + fm10k_ffu_rule_enable_multi_cast(sw, + flow->rule_id, sglort, svlan, + lport1, lport2, dvlan, dvlan2); + } else { + FM10K_FFU_RULE_PRINT(sw->dpdk_cfg, "\n"); + fm10k_ffu_rule_enable_single_cast(sw, + flow->rule_id, sglort, svlan, dglort, dvlan); + } +} + + +void +fm10k_ffu_flow_disable(struct fm10k_switch *sw, struct fm10k_cfg_flow *flow) +{ + int i; + + if (flow->rule_id == 0) + return; + + FM10K_FFU_RULE_PRINT(sw->dpdk_cfg, + "Remove flow %d rule %d\n", + flow->flow_no, flow->rule_id); + + for (i = FM10K_FFU_SLICE_START; i < FM10K_SW_FFU_NUM_SLICES; i++) { + fm10k_ffu_always_mismatch(sw, i, flow->rule_id); + fm10k_write_switch_reg64(sw, + FM10K_SW_FFU_SLICE_SRAM(i, flow->rule_id), 0); + } + fm10k_ffu_rule_free(flow->rule_id); +} + + +static int +fm10k_ffu_configured_flowset_enable(struct fm10k_switch *sw) +{ + struct fm10k_cfg_flowset *flowset; + struct fm10k_cfg_flow *flow; + + flowset = fm10k_config_flowset_current_get(); + flow = flowset->flow_head.next; + while (!fm10k_config_flow_list_end(&flowset->flow_head, flow)) { + fm10k_ffu_flow_enable(sw, flow); + flow = flow->next; + } + + return 0; +} + + +void +fm10k_ffu_flowset_switch(struct fm10k_switch *sw, const char *new_name) +{ + struct fm10k_cfg_flowset *flowset; + struct fm10k_cfg_flowset *cur_fs; + struct fm10k_cfg_flow *flow; + + cur_fs = fm10k_config_flowset_current_get(); + if (strcmp(cur_fs->name, new_name) == 0) + return; + + flowset = fm10k_config_flowset_get(new_name); + if (flowset == NULL) { + FM10K_SW_ERR("Can not find flowset %s!!\n", new_name); + return; + } + + /* disable current flowset */ + flow = cur_fs->flow_head.next; + while (!fm10k_config_flow_list_end(&cur_fs->flow_head, flow)) { + fm10k_ffu_flow_disable(sw, flow); + flow = flow->next; + } + + /* enable new flowset */ + fm10k_config_flowset_current_set(flowset); + flow = flowset->flow_head.next; + while (!fm10k_config_flow_list_end(&flowset->flow_head, flow)) { + fm10k_ffu_flow_enable(sw, flow); + flow = flow->next; + } +} + + +int +fm10k_ffu_init(struct fm10k_switch *sw, struct fm10k_dpdk_cfg *cfg) +{ + int ret = 0; + uint64_t data64; + uint16_t i, j; + uint32_t sglort = 0, dglort = 0; + uint16_t table_idx = 0; + uint16_t ffu_slice = FM10K_FFU_SLICE_START; + + sw->mcast_dest_table_idx = 1; + sw->mcast_len_table_idx = 1; + sw->mcast_vlan_table_idx = 1; + + for (i = 0; + i < sizeof(fm10k_ffu_slice_cfgs) / sizeof(uint64_t); + i++) { + for (j = 0; j < FM10K_SW_FFU_NUM_SCENARIOS; j++) { + data64 = fm10k_ffu_slice_cfgs[i]; + fm10k_write_switch_reg64(sw, + FM10K_SW_FFU_SLICE_CFG + (FM10K_FFU_SLICE_START + i, j), + data64); + } + FM10K_FFU_INIT_PRINT(cfg, "SET slice %d cfg = %#llx\n", + FM10K_FFU_SLICE_START + i, + (unsigned long long)data64); + } + + for (table_idx = 0; + table_idx < FM10K_SW_FFU_SLICE_TCAM_ENTRIES / 2; + table_idx++) + for (i = ffu_slice; i < FM10K_SW_FFU_NUM_SLICES; i++) + fm10k_ffu_always_mismatch(sw, i, table_idx); + + /* + * Create a TCAM entry to match each SGLORT that might be used, and + * set the corresponding SRAM action entries to ROUTE_GLORT to the + * corresponding DGLORT (see above table). + * SGLORT ROUTE is always the first slice + */ + for (i = 0; i < FM10K_SW_EXT_PORTS_MAX; i++) { + if (cfg->ext_port_map[i].type == FM10K_CONFIG_PORT_MAP_NULL) + continue; + + if (cfg->ext_port_map[i].type == FM10K_CONFIG_PORT_MAP_PF) { + sglort = fm10k_switch_epl_glort_get(i); + dglort = + fm10k_switch_pf_glort_get + (cfg->ext_port_map[i].map_no[0]); + } else if (cfg->ext_port_map[i].type == + FM10K_CONFIG_PORT_MAP_PFS) { + sglort = fm10k_switch_epl_glort_get(i); + dglort = + fm10k_switch_pfs_glort_get + (cfg->ext_port_map[i].map_no[0], + cfg->ext_port_map[i].map_no[1]); + } + + table_idx = FM10K_FFU_EXT_PORT_RULE_INGRESS(i); + fm10k_ffu_route_dglort(sw, + ffu_slice, table_idx, sglort, dglort); + + /* blank the next ffu slice */ + fm10k_write_switch_reg128(sw, + FM10K_SW_FFU_SLICE_TCAM + (ffu_slice + 1, table_idx), + 0xffffffffff, 0x1); + table_idx = FM10K_FFU_EXT_PORT_RULE_EGRESS(i); + fm10k_ffu_route_dglort(sw, + ffu_slice, table_idx, dglort, sglort); + + /* blank the next ffu slice */ + fm10k_write_switch_reg128(sw, + FM10K_SW_FFU_SLICE_TCAM + (ffu_slice + 1, table_idx), + 0xffffffffff, 0x1); + } + + for (i = ffu_slice; i < FM10K_SW_FFU_NUM_SLICES; i++) { + fm10k_write_switch_reg64(sw, + FM10K_SW_FFU_SLICE_CASCADE_ACTION(i), + 0xf0f000f); + /* Set slice 0 to valid for all scenarios */ + fm10k_write_switch_reg64(sw, + FM10K_SW_FFU_SLICE_VALID(i), + FM10K_SW_FFU_SLICE_VALID_ALL_SCENARIOS); + } + + /* Mark slice 0 as valid and all chunks as invalid */ + data64 = 0; + for (i = ffu_slice; i < FM10K_SW_FFU_NUM_SLICES; i++) + data64 |= FM10K_SW_FFU_MASTER_VALID_SLICE_VALID(i); + fm10k_write_switch_reg64(sw, FM10K_SW_FFU_MASTER_VALID, data64); + + /* + * Set up the DGLORT map according to the desired + * SGLORT -> { DGLORT, logical_port } map. + */ + for (i = 0; i < sw->info->num_peps; i++) { + if (sw->pep_map[i].glort == 0) + continue; + fm10k_ffu_set_dest_glort_mask(sw, + sw->glort_cam_ram_idx++, + sw->pep_map[i].glort, + FM10K_SW_DPORT_MASK + (sw->pep_map[i].logical_port)); + } + + for (i = 0; i < FM10K_SW_EPLS_SUPPORTED; i++) { + if (sw->epl_map[i].glort == 0) + continue; + fm10k_ffu_set_dest_glort_mask(sw, + sw->glort_cam_ram_idx++, + sw->epl_map[i].glort, + FM10K_SW_DPORT_MASK + (sw->epl_map[i].logical_port)); + } + + for (i = 0; i < FM10K_SW_EXT_PORTS_MAX; i++) { + uint64_t dport_mask = 0; + + if (cfg->ext_port_map[i].type == + FM10K_CONFIG_PORT_MAP_PFS) { + dglort = + fm10k_switch_pfs_glort_get + (cfg->ext_port_map[i].map_no[0], + cfg->ext_port_map[i].map_no[1]); + dport_mask = + FM10K_SW_DPORT_MASK + (sw->pep_map[cfg->ext_port_map[i].map_no[0]].logical_port) | + FM10K_SW_DPORT_MASK + (sw->pep_map[cfg->ext_port_map[i].map_no[1]].logical_port); + fm10k_ffu_set_dest_glort_mask(sw, + sw->glort_cam_ram_idx++, dglort, dport_mask); + } + } + + /* Ensure the rest of the DGLORT TCAM won't match */ + for (table_idx = sw->glort_cam_ram_idx; + table_idx < FM10K_SW_GLORT_CAM_ENTRIES; + table_idx++) + fm10k_write_switch_reg(sw, + FM10K_SW_GLORT_CAM(table_idx), + FM10K_SW_GLORT_CAM_MATCH_NONE); + + ret = fm10k_ffu_configured_flowset_enable(sw); + + fm10k_ffu_register_dump(sw); + fm10k_glort_register_dump(sw); + return ret; +} diff --git a/drivers/net/fm10k/switch/fm10k_ffu.h b/drivers/net/fm10k/switch/fm10k_ffu.h new file mode 100644 index 0000000..9d46007 --- /dev/null +++ b/drivers/net/fm10k/switch/fm10k_ffu.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright 2019 Silicom Ltd. Connectivity Solutions + */ + +#ifndef _FM10K_FFU_H_ +#define _FM10K_FFU_H_ + + +#include + +#define FM10K_FFU_EXT_PORT_RULE_INGRESS(i) ((i) * 2) +#define FM10K_FFU_EXT_PORT_RULE_EGRESS(i) ((i) * 2 + 1) +#define FM10K_FFU_RULE_MAX FM10K_SW_FFU_RULE_MAX + +struct fm10k_switch; +struct fm10k_dpdk_cfg; +struct fm10k_cfg_flow; + +int fm10k_ffu_init(struct fm10k_switch *sw, struct fm10k_dpdk_cfg *cfg); + +int fm10k_ffu_mirror_set(struct fm10k_switch *sw, + uint16_t src_dpdk_port, u16 dest_dpdk_port, uint16_t vlan); +int fm10k_ffu_mirror_reset(struct fm10k_switch *sw, int src_dpdk_port); + +void fm10k_ffu_flow_enable(struct fm10k_switch *sw, + struct fm10k_cfg_flow *flow); +void fm10k_ffu_flow_disable(struct fm10k_switch *sw, + struct fm10k_cfg_flow *flow); +void fm10k_ffu_flowset_switch(struct fm10k_switch *sw, const char *new_name); + +#endif /* _FM10K_FFU_H */ diff --git a/drivers/net/fm10k/switch/fm10k_stats.c b/drivers/net/fm10k/switch/fm10k_stats.c new file mode 100644 index 0000000..4172b22 --- /dev/null +++ b/drivers/net/fm10k/switch/fm10k_stats.c @@ -0,0 +1,1242 @@ +/* spdx-license-identifier: bsd-3-clause + * copyright 2019 silicom ltd. connectivity solutions + */ + +#include +#include +#include +#include +#include +#include + +#include "../base/fm10k_type.h" +#include "../base/fm10k_osdep.h" + +#include "../fm10k.h" +#include "../fm10k_logs.h" +#include "fm10k_debug.h" +#include "fm10k_regs.h" +#include "fm10k_ext_port.h" +#include "fm10k_stats.h" +#include "fm10k_switch.h" +#include "fm10k_config.h" +#include "fm10k_ffu.h" + + +#define FM10K_MAX_VLAN_COUNTER 63 +#define FM10K_NB_RX_STATS_BANKS 6 +#define FM10K_BINS_PER_RX_STATS_BANK 16 +#define FM10K_WORDS_PER_RX_STATS_COUNTER 4 + +/* Max expected entries in read stats scatter gather list */ +#define MAX_STATS_SGLIST 128 +#define FM10K_RX_STATS_BASE (0xE00000) +#define FM10K_MOD_BASE (0xE80000) +#define FM10K_CM_APPLY_BASE (0xD40000) +#define FM10K_EPL_BASE (0x0E0000) + +#define FM10K_RX_STATS_BANK(index1, index0, word) \ + ((0x001000) * ((index1) - 0) + \ + (0x000004) * ((index0) - 0) + \ + (word) + (0x000000) + \ + (FM10K_RX_STATS_BASE)) +#define FM10K_MOD_STATS_BANK_FRAME(index1, index0, word) \ + ((0x000800) * ((index1) - 0) + \ + (0x000002) * ((index0) - 0) + \ + (word) + (0x025000) + \ + (FM10K_MOD_BASE)) +#define FM10K_MOD_STATS_BANK_BYTE(index1, index0, word) \ + ((0x000800) * ((index1) - 0) + \ + (0x000002) * ((index0) - 0) + \ + (word) + (0x026000) + \ + (FM10K_MOD_BASE)) +#define FM10K_CM_APPLY_DROP_COUNT(index, word) \ + ((0x000002) * ((index) - 0) + \ + (word) + (0x000880) + \ + (FM10K_CM_APPLY_BASE)) +#define FM10K_MAC_OVERSIZE_COUNTER(index1, index0) \ + ((0x000400) * ((index1) - 0) + \ + (0x000080) * ((index0) - 0) + \ + (0x000021) + \ + (FM10K_EPL_BASE)) +#define FM10K_MAC_JABBER_COUNTER(index1, index0) \ + ((0x000400) * ((index1) - 0) + \ + (0x000080) * ((index0) - 0) + \ + (0x000022) + \ + (FM10K_EPL_BASE)) +#define FM10K_MAC_UNDERSIZE_COUNTER(index1, index0) \ + ((0x000400) * ((index1) - 0) + \ + (0x000080) * ((index0) - 0) + \ + (0x000023) + \ + (FM10K_EPL_BASE)) +#define FM10K_MAC_RUNT_COUNTER(index1, index0) \ + ((0x000400) * ((index1) - 0) + \ + (0x000080) * ((index0) - 0) + \ + (0x000024) + \ + (FM10K_EPL_BASE)) +#define FM10K_MAC_OVERRUN_COUNTER(index1, index0) \ + ((0x000400) * ((index1) - 0) + \ + (0x000080) * ((index0) - 0) + \ + (0x000025) + \ + (FM10K_EPL_BASE)) +#define FM10K_MAC_UNDERRUN_COUNTER(index1, index0) \ + ((0x000400) * ((index1) - 0) + \ + (0x000080) * ((index0) - 0) + \ + (0x000026) + \ + (FM10K_EPL_BASE)) +#define FM10K_MAC_CODE_ERROR_COUNTER(index1, index0) \ + ((0x000400) * ((index1) - 0) + \ + (0x000080) * ((index0) - 0) + \ + (0x000027) + \ + (FM10K_EPL_BASE)) + +/* Rx Bank Definitions */ +#define FM10K_RX_STAT_BANK_TYPE 0 +#define FM10K_RX_STAT_BANK_SIZE 1 +#define FM10K_RX_STAT_BANK_PRI 2 +#define FM10K_RX_STAT_BANK_FWD_1 3 +#define FM10K_RX_STAT_BANK_FWD_2 4 +#define FM10K_RX_STAT_BANK_VLAN 5 + +/* FM10K_RX_STAT_BANK_TYPE Bin Definitions */ +#define FM10K_RX_STAT_NONIP_L2UCAST 0 +#define FM10K_RX_STAT_NONIP_L2MCAST 1 +#define FM10K_RX_STAT_NONIP_L2BCAST 2 +#define FM10K_RX_STAT_IPV4_L2UCAST 3 +#define FM10K_RX_STAT_IPV4_L2MCAST 4 +#define FM10K_RX_STAT_IPV4_L2BCAST 5 +#define FM10K_RX_STAT_IPV6_L2UCAST 6 +#define FM10K_RX_STAT_IPV6_L2MCAST 7 +#define FM10K_RX_STAT_IPV6_L2BCAST 8 +#define FM10K_RX_STAT_IEEE802_3_PAUSE 9 +#define FM10K_RX_STAT_CLASS_BASED_PAUSE 10 +#define FM10K_RX_STAT_FRAMING_ERR 11 +#define FM10K_RX_STAT_FCS_ERR 12 + +/* FM10K_RX_STAT_BANK_SIZE Bin Definitions */ +#define FM10K_RX_STAT_LEN_LT_64 0 +#define FM10K_RX_STAT_LEN_EQ_64 1 +#define FM10K_RX_STAT_LEN_65_127 2 +#define FM10K_RX_STAT_LEN_128_255 3 +#define FM10K_RX_STAT_LEN_256_511 4 +#define FM10K_RX_STAT_LEN_512_1023 5 +#define FM10K_RX_STAT_LEN_1024_1522 6 +#define FM10K_RX_STAT_LEN_1523_2047 7 +#define FM10K_RX_STAT_LEN_2048_4095 8 +#define FM10K_RX_STAT_LEN_4096_8191 9 +#define FM10K_RX_STAT_LEN_8192_10239 10 +#define FM10K_RX_STAT_LEN_GE_10240 11 + +/* FM10K_RX_STAT_BANK_PRI Bin Definitions */ +#define FM10K_RX_STAT_PRI_0 0 +#define FM10K_RX_STAT_PRI_1 1 +#define FM10K_RX_STAT_PRI_2 2 +#define FM10K_RX_STAT_PRI_3 3 +#define FM10K_RX_STAT_PRI_4 4 +#define FM10K_RX_STAT_PRI_5 5 +#define FM10K_RX_STAT_PRI_6 6 +#define FM10K_RX_STAT_PRI_7 7 +#define FM10K_RX_STAT_PRI_8 8 +#define FM10K_RX_STAT_PRI_9 9 +#define FM10K_RX_STAT_PRI_10 10 +#define FM10K_RX_STAT_PRI_11 11 +#define FM10K_RX_STAT_PRI_12 12 +#define FM10K_RX_STAT_PRI_13 13 +#define FM10K_RX_STAT_PRI_14 14 +#define FM10K_RX_STAT_PRI_15 15 + +/* FM10K_RX_STAT_BANK_FWD_1 Bin Definitions */ +#define FM10K_RX_STAT_FID_FORWARDED 0 +#define FM10K_RX_STAT_FLOOD_FORWARDED 1 +#define FM10K_RX_STAT_SPECIALLY_HANDLED 2 +#define FM10K_RX_STAT_PARSER_ERROR_DROP 3 +#define FM10K_RX_STAT_ECC_ERROR_DROP 4 +#define FM10K_RX_STAT_TRAPPED 5 +#define FM10K_RX_STAT_PAUSE_DROPS 6 +#define FM10K_RX_STAT_STP_DROPS 7 +#define FM10K_RX_STAT_SECURITY_VIOLATIONS 8 +#define FM10K_RX_STAT_VLAN_TAG_DROPS 9 +#define FM10K_RX_STAT_VLAN_INGRESS_DROPS 10 +#define FM10K_RX_STAT_VLAN_EGRESS_DROPS 11 +#define FM10K_RX_STAT_GLORT_MISS_DROPS 12 +#define FM10K_RX_STAT_FFU_DROPS 13 +#define FM10K_RX_STAT_TRIGGER_DROPS 14 +#define FM10K_RX_STAT_OVERFLOW4 15 + +/* FM10K_RX_STAT_BANK_FWD_2 Bin Definitions */ +#define FM10K_RX_STAT_POLICER_DROPS 0 +#define FM10K_RX_STAT_TTL_DROPS 1 +#define FM10K_RX_STAT_CM_PRIV_DROPS 2 +#define FM10K_RX_STAT_CM_SMP0_DROPS 3 +#define FM10K_RX_STAT_CM_SMP1_DROPS 4 +#define FM10K_RX_STAT_CM_RX_HOG_0_DROPS 5 +#define FM10K_RX_STAT_CM_RX_HOG_1_DROPS 6 +#define FM10K_RX_STAT_CM_TX_HOG_0_DROPS 7 +#define FM10K_RX_STAT_CM_TX_HOG_1_DROPS 8 +/* Bin 9 reserved */ +#define FM10K_RX_STAT_TRIGGER_REDIRECTS 10 +#define FM10K_RX_STAT_FLOOD_CONTROL_DROPS 11 +#define FM10K_RX_STAT_GLORT_FORWARDED 12 +#define FM10K_RX_STAT_LOOPBACK_SUPPRESS 13 +#define FM10K_RX_STAT_OTHERS 14 +#define FM10K_RX_STAT_OVERFLOW5 15 + +/* FM10K_RX_STAT_BANK_VLAN Bin definitions */ +#define FM10K_RX_STAT_VLAN_UCAST 0 +#define FM10K_RX_STAT_VLAN_MCAST 1 +#define FM10K_RX_STAT_VLAN_BCAST 2 + +/* Tx Bank Definitions */ +#define FM10K_TX_STAT_BANK_TYPE 0 +#define FM10K_TX_STAT_BANK_SIZE 1 + +/* FM10K_TX_STAT_BANK_TYPE Bin Definitions */ +#define FM10K_TX_STAT_L2UCAST 0 +#define FM10K_TX_STAT_L2MCAST 1 +#define FM10K_TX_STAT_L2BCAST 2 +#define FM10K_TX_STAT_ERR_SENT 3 +#define FM10K_TX_STAT_TIMEOUT_DROP 4 +#define FM10K_TX_STAT_ERR_DROP 5 +#define FM10K_TX_STAT_ECC_DROP 6 +#define FM10K_TX_STAT_LOOPBACK_DROP 7 +#define FM10K_TX_STAT_TTL1_DROP 8 +#define FM10K_TX_STAT_IEEE802_3_PAUSE 9 +#define FM10K_TX_STAT_CLASS_BASED_PAUSE 10 + +/* FM10K_TX_STAT_BANK_SIZE Bin Definitions */ +#define FM10K_TX_STAT_LEN_LT_64 0 +#define FM10K_TX_STAT_LEN_EQ_64 1 +#define FM10K_TX_STAT_LEN_65_127 2 +#define FM10K_TX_STAT_LEN_128_255 3 +#define FM10K_TX_STAT_LEN_256_511 4 +#define FM10K_TX_STAT_LEN_512_1023 5 +#define FM10K_TX_STAT_LEN_1024_1522 6 +#define FM10K_TX_STAT_LEN_1523_2047 7 +#define FM10K_TX_STAT_LEN_2048_4095 8 +#define FM10K_TX_STAT_LEN_4096_8191 9 +#define FM10K_TX_STAT_LEN_8192_10239 10 +#define FM10K_TX_STAT_LEN_GE_10240 11 + + +/* This structure is used to build a table of all rx / tx counters */ +struct fm10k_port_count_mapping { + /* Bank in which the counter is located */ + uint32_t bank; + + /* Bin in which the counter is located */ + uint32_t bin; + + /* + * Offset (in bytes) of a the frame counter in + * the fm10k_counters structure + */ + uint32_t frame_offset; + + /* + * Offset (in bytes) of a the byte counter in + * the fm10k_counters structure + */ + uint32_t byte_offset; +}; + + +/* + * Table of all RX port counters in the RX banks + * This table is used for retrieving counters as + * well as resetting them + */ +static struct fm10k_port_count_mapping rx_port_cnt_map_table[] = { + /* Bank Bin + * -------------------------- ------------------------------ + * frame_offset + * --------------------------------------------- + * byte_offset + * --------------------------------------------------- + */ + /* Type Bank */ +{ FM10K_RX_STAT_BANK_TYPE, FM10K_RX_STAT_NONIP_L2UCAST, + offsetof(struct fm10k_port_counters, cnt_rx_ucst_pkts_nonip), + offsetof(struct fm10k_port_counters, cnt_rx_ucst_octets_nonip)}, +{ FM10K_RX_STAT_BANK_TYPE, FM10K_RX_STAT_NONIP_L2MCAST, + offsetof(struct fm10k_port_counters, cnt_rx_mcst_pkts_nonip), + offsetof(struct fm10k_port_counters, cnt_rx_mcst_octets_nonip)}, +{ FM10K_RX_STAT_BANK_TYPE, FM10K_RX_STAT_NONIP_L2BCAST, + offsetof(struct fm10k_port_counters, cnt_rx_bcst_pkts_nonip), + offsetof(struct fm10k_port_counters, cnt_rx_bcst_octets_nonip)}, +{ FM10K_RX_STAT_BANK_TYPE, FM10K_RX_STAT_IPV4_L2UCAST, + offsetof(struct fm10k_port_counters, cnt_rx_ucst_pkts_ipv4), + offsetof(struct fm10k_port_counters, cnt_rx_ucst_octets_ipv4)}, +{ FM10K_RX_STAT_BANK_TYPE, FM10K_RX_STAT_IPV4_L2MCAST, + offsetof(struct fm10k_port_counters, cnt_rx_mcst_pkts_ipv4), + offsetof(struct fm10k_port_counters, cnt_rx_mcst_octets_ipv4)}, +{ FM10K_RX_STAT_BANK_TYPE, FM10K_RX_STAT_IPV4_L2BCAST, + offsetof(struct fm10k_port_counters, cnt_rx_bcst_pkts_ipv4), + offsetof(struct fm10k_port_counters, cnt_rx_bcst_octets_ipv4)}, +{ FM10K_RX_STAT_BANK_TYPE, FM10K_RX_STAT_IPV6_L2UCAST, + offsetof(struct fm10k_port_counters, cnt_rx_ucst_pkts_ipv6), + offsetof(struct fm10k_port_counters, cnt_rx_ucst_octets_ipv6)}, +{ FM10K_RX_STAT_BANK_TYPE, FM10K_RX_STAT_IPV6_L2MCAST, + offsetof(struct fm10k_port_counters, cnt_rx_mcst_pkts_ipv6), + offsetof(struct fm10k_port_counters, cnt_rx_mcst_octets_ipv6)}, +{ FM10K_RX_STAT_BANK_TYPE, FM10K_RX_STAT_IPV6_L2BCAST, + offsetof(struct fm10k_port_counters, cnt_rx_bcst_pkts_ipv6), + offsetof(struct fm10k_port_counters, cnt_rx_bcst_octets_ipv6)}, +{ FM10K_RX_STAT_BANK_TYPE, FM10K_RX_STAT_IEEE802_3_PAUSE, + offsetof(struct fm10k_port_counters, cnt_rx_pause_pkts), + offsetof(struct fm10k_port_counters, cnt_rx_pause_octets)}, +{ FM10K_RX_STAT_BANK_TYPE, FM10K_RX_STAT_CLASS_BASED_PAUSE, + offsetof(struct fm10k_port_counters, cnt_rx_cbpause_pkts), + offsetof(struct fm10k_port_counters, cnt_rx_cbpause_octets)}, +{ FM10K_RX_STAT_BANK_TYPE, FM10K_RX_STAT_FRAMING_ERR, + offsetof(struct fm10k_port_counters, cnt_rx_framing_error_pkts), + offsetof(struct fm10k_port_counters, cnt_rx_framing_error_octets)}, +{ FM10K_RX_STAT_BANK_TYPE, FM10K_RX_STAT_FCS_ERR, + offsetof(struct fm10k_port_counters, cnt_rx_fcs_errors), + offsetof(struct fm10k_port_counters, cnt_rx_fcs_errors_octets)}, + + /* Size Bank */ +{ FM10K_RX_STAT_BANK_SIZE, FM10K_RX_STAT_LEN_LT_64, + offsetof(struct fm10k_port_counters, cnt_rx_minto63_pkts), + offsetof(struct fm10k_port_counters, cnt_rx_minto63_octets)}, +{ FM10K_RX_STAT_BANK_SIZE, FM10K_RX_STAT_LEN_EQ_64, + offsetof(struct fm10k_port_counters, cnt_rx_64_pkts), + offsetof(struct fm10k_port_counters, cnt_rx_64_octets)}, +{ FM10K_RX_STAT_BANK_SIZE, FM10K_RX_STAT_LEN_65_127, + offsetof(struct fm10k_port_counters, cnt_rx_65to127_pkts), + offsetof(struct fm10k_port_counters, cnt_rx_65to127_octets)}, +{ FM10K_RX_STAT_BANK_SIZE, FM10K_RX_STAT_LEN_128_255, + offsetof(struct fm10k_port_counters, cnt_rx_128to255_pkts), + offsetof(struct fm10k_port_counters, cnt_rx_128to255_octets)}, +{ FM10K_RX_STAT_BANK_SIZE, FM10K_RX_STAT_LEN_256_511, + offsetof(struct fm10k_port_counters, cnt_rx_256to511_pkts), + offsetof(struct fm10k_port_counters, cnt_rx_256to511_octets)}, +{ FM10K_RX_STAT_BANK_SIZE, FM10K_RX_STAT_LEN_512_1023, + offsetof(struct fm10k_port_counters, cnt_rx_512to1023_pkts), + offsetof(struct fm10k_port_counters, cnt_rx_512to1023_octets)}, +{ FM10K_RX_STAT_BANK_SIZE, FM10K_RX_STAT_LEN_1024_1522, + offsetof(struct fm10k_port_counters, cnt_rx_1024to1522_pkts), + offsetof(struct fm10k_port_counters, cnt_rx_1024to1522_octets)}, +{ FM10K_RX_STAT_BANK_SIZE, FM10K_RX_STAT_LEN_1523_2047, + offsetof(struct fm10k_port_counters, cnt_rx_1523to2047_pkts), + offsetof(struct fm10k_port_counters, cnt_rx_1523to2047_octets)}, +{ FM10K_RX_STAT_BANK_SIZE, FM10K_RX_STAT_LEN_2048_4095, + offsetof(struct fm10k_port_counters, cnt_rx_2048to4095_pkts), + offsetof(struct fm10k_port_counters, cnt_rx_2048to4095_octets)}, +{ FM10K_RX_STAT_BANK_SIZE, FM10K_RX_STAT_LEN_4096_8191, + offsetof(struct fm10k_port_counters, cnt_rx_4096to8191_pkts), + offsetof(struct fm10k_port_counters, cnt_rx_4096to8191_octets)}, +{ FM10K_RX_STAT_BANK_SIZE, FM10K_RX_STAT_LEN_8192_10239, + offsetof(struct fm10k_port_counters, cnt_rx_8192to10239_pkts), + offsetof(struct fm10k_port_counters, cnt_rx_8192to10239_octets)}, +{ FM10K_RX_STAT_BANK_SIZE, FM10K_RX_STAT_LEN_GE_10240, + offsetof(struct fm10k_port_counters, cnt_rx_10240tomax_pkts), + offsetof(struct fm10k_port_counters, cnt_rx_10240tomax_octets)}, + + /* priority Bank */ +{ FM10K_RX_STAT_BANK_PRI, FM10K_RX_STAT_PRI_0, + offsetof(struct fm10k_port_counters, cnt_rx_priority_pkts[0]), + offsetof(struct fm10k_port_counters, cnt_rx_priority_octets[0])}, +{ FM10K_RX_STAT_BANK_PRI, FM10K_RX_STAT_PRI_1, + offsetof(struct fm10k_port_counters, cnt_rx_priority_pkts[1]), + offsetof(struct fm10k_port_counters, cnt_rx_priority_octets[1])}, +{ FM10K_RX_STAT_BANK_PRI, FM10K_RX_STAT_PRI_2, + offsetof(struct fm10k_port_counters, cnt_rx_priority_pkts[2]), + offsetof(struct fm10k_port_counters, cnt_rx_priority_octets[2])}, +{ FM10K_RX_STAT_BANK_PRI, FM10K_RX_STAT_PRI_3, + offsetof(struct fm10k_port_counters, cnt_rx_priority_pkts[3]), + offsetof(struct fm10k_port_counters, cnt_rx_priority_octets[3])}, +{ FM10K_RX_STAT_BANK_PRI, FM10K_RX_STAT_PRI_4, + offsetof(struct fm10k_port_counters, cnt_rx_priority_pkts[4]), + offsetof(struct fm10k_port_counters, cnt_rx_priority_octets[4])}, +{ FM10K_RX_STAT_BANK_PRI, FM10K_RX_STAT_PRI_5, + offsetof(struct fm10k_port_counters, cnt_rx_priority_pkts[5]), + offsetof(struct fm10k_port_counters, cnt_rx_priority_octets[5])}, +{ FM10K_RX_STAT_BANK_PRI, FM10K_RX_STAT_PRI_6, + offsetof(struct fm10k_port_counters, cnt_rx_priority_pkts[6]), + offsetof(struct fm10k_port_counters, cnt_rx_priority_octets[6])}, +{ FM10K_RX_STAT_BANK_PRI, FM10K_RX_STAT_PRI_7, + offsetof(struct fm10k_port_counters, cnt_rx_priority_pkts[7]), + offsetof(struct fm10k_port_counters, cnt_rx_priority_octets[7])}, +{ FM10K_RX_STAT_BANK_PRI, FM10K_RX_STAT_PRI_8, + offsetof(struct fm10k_port_counters, cnt_rx_priority_pkts[8]), + offsetof(struct fm10k_port_counters, cnt_rx_priority_octets[8])}, +{ FM10K_RX_STAT_BANK_PRI, FM10K_RX_STAT_PRI_9, + offsetof(struct fm10k_port_counters, cnt_rx_priority_pkts[9]), + offsetof(struct fm10k_port_counters, cnt_rx_priority_octets[9])}, +{ FM10K_RX_STAT_BANK_PRI, FM10K_RX_STAT_PRI_10, + offsetof(struct fm10k_port_counters, cnt_rx_priority_pkts[10]), + offsetof(struct fm10k_port_counters, cnt_rx_priority_octets[10])}, +{ FM10K_RX_STAT_BANK_PRI, FM10K_RX_STAT_PRI_11, + offsetof(struct fm10k_port_counters, cnt_rx_priority_pkts[11]), + offsetof(struct fm10k_port_counters, cnt_rx_priority_octets[11])}, +{ FM10K_RX_STAT_BANK_PRI, FM10K_RX_STAT_PRI_12, + offsetof(struct fm10k_port_counters, cnt_rx_priority_pkts[12]), + offsetof(struct fm10k_port_counters, cnt_rx_priority_octets[12])}, +{ FM10K_RX_STAT_BANK_PRI, FM10K_RX_STAT_PRI_13, + offsetof(struct fm10k_port_counters, cnt_rx_priority_pkts[13]), + offsetof(struct fm10k_port_counters, cnt_rx_priority_octets[13])}, +{ FM10K_RX_STAT_BANK_PRI, FM10K_RX_STAT_PRI_14, + offsetof(struct fm10k_port_counters, cnt_rx_priority_pkts[14]), + offsetof(struct fm10k_port_counters, cnt_rx_priority_octets[14])}, +{ FM10K_RX_STAT_BANK_PRI, FM10K_RX_STAT_PRI_15, + offsetof(struct fm10k_port_counters, cnt_rx_priority_pkts[15]), + offsetof(struct fm10k_port_counters, cnt_rx_priority_octets[15])}, + + /* Forwarding Bank */ +{ FM10K_RX_STAT_BANK_FWD_1, FM10K_RX_STAT_FID_FORWARDED, + offsetof(struct fm10k_port_counters, cnt_fid_forwarded_pkts), + offsetof(struct fm10k_port_counters, cnt_fid_forwarded_octets)}, +{ FM10K_RX_STAT_BANK_FWD_1, FM10K_RX_STAT_FLOOD_FORWARDED, + offsetof(struct fm10k_port_counters, cnt_flood_forwarded_pkts), + offsetof(struct fm10k_port_counters, cnt_flood_forwarded_octets)}, +{ FM10K_RX_STAT_BANK_FWD_1, FM10K_RX_STAT_SPECIALLY_HANDLED, + offsetof(struct fm10k_port_counters, cnt_specially_handled_pkts), + offsetof(struct fm10k_port_counters, cnt_specially_handled_octets)}, +{ FM10K_RX_STAT_BANK_FWD_1, FM10K_RX_STAT_PARSER_ERROR_DROP, + offsetof(struct fm10k_port_counters, cnt_parse_err_drop_pkts), + offsetof(struct fm10k_port_counters, cnt_parse_err_drop_octets)}, +{ FM10K_RX_STAT_BANK_FWD_1, FM10K_RX_STAT_ECC_ERROR_DROP, + offsetof(struct fm10k_port_counters, cnt_parity_error_pkts), + offsetof(struct fm10k_port_counters, cnt_parity_error_octets)}, +{ FM10K_RX_STAT_BANK_FWD_1, FM10K_RX_STAT_TRAPPED, + offsetof(struct fm10k_port_counters, cnt_trapped_pkts), + offsetof(struct fm10k_port_counters, cnt_trapped_octets)}, +{ FM10K_RX_STAT_BANK_FWD_1, FM10K_RX_STAT_PAUSE_DROPS, + offsetof(struct fm10k_port_counters, cnt_pause_drop_pkts), + offsetof(struct fm10k_port_counters, cnt_pause_drop_octets)}, +{ FM10K_RX_STAT_BANK_FWD_1, FM10K_RX_STAT_STP_DROPS, + offsetof(struct fm10k_port_counters, cnt_stp_drop_pkts), + offsetof(struct fm10k_port_counters, cnt_stp_drop_octets)}, +{ FM10K_RX_STAT_BANK_FWD_1, FM10K_RX_STAT_SECURITY_VIOLATIONS, + offsetof(struct fm10k_port_counters, cnt_security_violation_pkts), + offsetof(struct fm10k_port_counters, cnt_security_violation_octets)}, +{ FM10K_RX_STAT_BANK_FWD_1, FM10K_RX_STAT_VLAN_TAG_DROPS, + offsetof(struct fm10k_port_counters, cnt_vlan_tag_drop_pkts), + offsetof(struct fm10k_port_counters, cnt_vlan_tag_drop_octets)}, +{ FM10K_RX_STAT_BANK_FWD_1, FM10K_RX_STAT_VLAN_INGRESS_DROPS, + offsetof(struct fm10k_port_counters, cnt_vlan_ingressbv_pkts), + offsetof(struct fm10k_port_counters, cnt_vlan_ingressbv_octets)}, +{ FM10K_RX_STAT_BANK_FWD_1, FM10K_RX_STAT_VLAN_EGRESS_DROPS, + offsetof(struct fm10k_port_counters, cnt_vlan_egressbv_pkts), + offsetof(struct fm10k_port_counters, cnt_vlan_egressbv_octets)}, +{ FM10K_RX_STAT_BANK_FWD_1, FM10K_RX_STAT_GLORT_MISS_DROPS, + offsetof(struct fm10k_port_counters, cnt_glort_miss_drop_pkts), + offsetof(struct fm10k_port_counters, cnt_glort_miss_drop_octets)}, +{ FM10K_RX_STAT_BANK_FWD_1, FM10K_RX_STAT_FFU_DROPS, + offsetof(struct fm10k_port_counters, cnt_ffu_drop_pkts), + offsetof(struct fm10k_port_counters, cnt_ffu_drop_octets)}, +{ FM10K_RX_STAT_BANK_FWD_1, FM10K_RX_STAT_TRIGGER_DROPS, + offsetof(struct fm10k_port_counters, cnt_trigger_drop_pkts), + offsetof(struct fm10k_port_counters, cnt_trigger_drop_octets)}, +{ FM10K_RX_STAT_BANK_FWD_2, FM10K_RX_STAT_POLICER_DROPS, + offsetof(struct fm10k_port_counters, cnt_policer_drop_pkts), + offsetof(struct fm10k_port_counters, cnt_policer_drop_octets)}, +{ FM10K_RX_STAT_BANK_FWD_2, FM10K_RX_STAT_TTL_DROPS, + offsetof(struct fm10k_port_counters, cnt_ttl_drop_pkts), + offsetof(struct fm10k_port_counters, cnt_ttl_drop_octets)}, +{ FM10K_RX_STAT_BANK_FWD_2, FM10K_RX_STAT_CM_PRIV_DROPS, + offsetof(struct fm10k_port_counters, cnt_cmpriv_drop_pkts), + offsetof(struct fm10k_port_counters, cnt_cmpriv_drop_octets)}, +{ FM10K_RX_STAT_BANK_FWD_2, FM10K_RX_STAT_CM_SMP0_DROPS, + offsetof(struct fm10k_port_counters, cnt_smp0_drop_pkts), + offsetof(struct fm10k_port_counters, cnt_smp0_drop_octets)}, +{ FM10K_RX_STAT_BANK_FWD_2, FM10K_RX_STAT_CM_SMP1_DROPS, + offsetof(struct fm10k_port_counters, cnt_smp1_drop_pkts), + offsetof(struct fm10k_port_counters, cnt_smp1_drop_octets)}, +{ FM10K_RX_STAT_BANK_FWD_2, FM10K_RX_STAT_CM_RX_HOG_0_DROPS, + offsetof(struct fm10k_port_counters, cnt_rx_hog0_drop_pkts), + offsetof(struct fm10k_port_counters, cnt_rx_hog0_drop_octets)}, +{ FM10K_RX_STAT_BANK_FWD_2, FM10K_RX_STAT_CM_RX_HOG_1_DROPS, + offsetof(struct fm10k_port_counters, cnt_rx_hog1_drop_pkts), + offsetof(struct fm10k_port_counters, cnt_rx_hog1_drop_octets)}, +{ FM10K_RX_STAT_BANK_FWD_2, FM10K_RX_STAT_CM_TX_HOG_0_DROPS, + offsetof(struct fm10k_port_counters, cnt_tx_hog0_drop_pkts), + offsetof(struct fm10k_port_counters, cnt_tx_hog0_drop_octets)}, +{ FM10K_RX_STAT_BANK_FWD_2, FM10K_RX_STAT_CM_TX_HOG_1_DROPS, + offsetof(struct fm10k_port_counters, cnt_tx_hog1_drop_pkts), + offsetof(struct fm10k_port_counters, cnt_tx_hog1_drop_octets)}, +{ FM10K_RX_STAT_BANK_FWD_2, FM10K_RX_STAT_TRIGGER_REDIRECTS, + offsetof(struct fm10k_port_counters, cnt_trigger_redir_pkts), + offsetof(struct fm10k_port_counters, cnt_trigger_redir_octets)}, +{ FM10K_RX_STAT_BANK_FWD_2, FM10K_RX_STAT_FLOOD_CONTROL_DROPS, + offsetof(struct fm10k_port_counters, cnt_flood_control_drop_pkts), + offsetof(struct fm10k_port_counters, cnt_flood_control_drop_octets)}, +{ FM10K_RX_STAT_BANK_FWD_2, FM10K_RX_STAT_GLORT_FORWARDED, + offsetof(struct fm10k_port_counters, cnt_glort_forwarded_pkts), + offsetof(struct fm10k_port_counters, cnt_glort_forwarded_octets)}, +{ FM10K_RX_STAT_BANK_FWD_2, FM10K_RX_STAT_LOOPBACK_SUPPRESS, + offsetof(struct fm10k_port_counters, cnt_loopback_drops_pkts), + offsetof(struct fm10k_port_counters, cnt_loopback_drop_octets)}, +{ FM10K_RX_STAT_BANK_FWD_2, FM10K_RX_STAT_OTHERS, + offsetof(struct fm10k_port_counters, cnt_other_pkts), + offsetof(struct fm10k_port_counters, cnt_other_octets)}, + +}; /* end rxPortCntMapTable */ + + +/* + * Table of all TX port counters in the TX banks + * This table is used for retrieving counters as + * well as resetting them + */ +static struct fm10k_port_count_mapping tx_port_cnt_map_table[] = { + /* Bank Bin + * -------------------------- ------------------------------ + * frame_offset + * --------------------------------------------- + * byte_offset + * --------------------------------------------------- + */ + /* Type Bank */ +{ FM10K_TX_STAT_BANK_TYPE, FM10K_TX_STAT_L2UCAST, + offsetof(struct fm10k_port_counters, cnt_tx_ucst_pkts), + offsetof(struct fm10k_port_counters, cnt_tx_ucst_octets)}, +{ FM10K_TX_STAT_BANK_TYPE, FM10K_TX_STAT_L2MCAST, + offsetof(struct fm10k_port_counters, cnt_tx_mcst_pkts), + offsetof(struct fm10k_port_counters, cnt_tx_mcst_octets)}, +{ FM10K_TX_STAT_BANK_TYPE, FM10K_TX_STAT_L2BCAST, + offsetof(struct fm10k_port_counters, cnt_tx_bcst_pkts), + offsetof(struct fm10k_port_counters, cnt_tx_bcst_octets)}, +{ FM10K_TX_STAT_BANK_TYPE, FM10K_TX_STAT_ERR_SENT, + offsetof(struct fm10k_port_counters, cnt_tx_error_sent_pkts), + offsetof(struct fm10k_port_counters, cnt_tx_error_sent_octets)}, +{ FM10K_TX_STAT_BANK_TYPE, FM10K_TX_STAT_TIMEOUT_DROP, + offsetof(struct fm10k_port_counters, cnt_tx_timeout_pkts), + offsetof(struct fm10k_port_counters, cnt_tx_timeout_octets)}, +{ FM10K_TX_STAT_BANK_TYPE, FM10K_TX_STAT_ERR_DROP, + offsetof(struct fm10k_port_counters, cnt_tx_error_drop_pkts), + offsetof(struct fm10k_port_counters, cnt_tx_error_octets)}, +{ FM10K_TX_STAT_BANK_TYPE, FM10K_TX_STAT_ECC_DROP, + offsetof(struct fm10k_port_counters, cnt_tx_unrepair_ecc_pkts), + offsetof(struct fm10k_port_counters, cnt_tx_unrepair_ecc_octets)}, +{ FM10K_TX_STAT_BANK_TYPE, FM10K_TX_STAT_LOOPBACK_DROP, + offsetof(struct fm10k_port_counters, cnt_tx_loopback_pkts), + offsetof(struct fm10k_port_counters, cnt_tx_loopback_octets)}, +{ FM10K_TX_STAT_BANK_TYPE, FM10K_TX_STAT_TTL1_DROP, + offsetof(struct fm10k_port_counters, cnt_tx_ttl_drop_pkts), + offsetof(struct fm10k_port_counters, cnt_tx_ttl_drop_octets)}, +{ FM10K_TX_STAT_BANK_TYPE, FM10K_TX_STAT_IEEE802_3_PAUSE, + offsetof(struct fm10k_port_counters, cnt_tx_pause_pkts), + offsetof(struct fm10k_port_counters, cnt_tx_pause_octets)}, +{ FM10K_TX_STAT_BANK_TYPE, FM10K_TX_STAT_CLASS_BASED_PAUSE, + offsetof(struct fm10k_port_counters, cnt_tx_cbpause_pkts), + offsetof(struct fm10k_port_counters, cnt_tx_cbpause_octets)}, + + /* Size Bank */ +{ FM10K_TX_STAT_BANK_SIZE, FM10K_TX_STAT_LEN_LT_64, + offsetof(struct fm10k_port_counters, cnt_tx_minto63_pkts), + offsetof(struct fm10k_port_counters, cnt_tx_minto63_octets)}, +{ FM10K_TX_STAT_BANK_SIZE, FM10K_TX_STAT_LEN_EQ_64, + offsetof(struct fm10k_port_counters, cnt_tx_64_pkts), + offsetof(struct fm10k_port_counters, cnt_tx_64_octets)}, +{ FM10K_TX_STAT_BANK_SIZE, FM10K_TX_STAT_LEN_65_127, + offsetof(struct fm10k_port_counters, cnt_tx_65to127_pkts), + offsetof(struct fm10k_port_counters, cnt_tx_65to127_octets)}, +{ FM10K_TX_STAT_BANK_SIZE, FM10K_TX_STAT_LEN_128_255, + offsetof(struct fm10k_port_counters, cnt_tx_128to255_pkts), + offsetof(struct fm10k_port_counters, cnt_tx_128to255_octets)}, +{ FM10K_TX_STAT_BANK_SIZE, FM10K_TX_STAT_LEN_256_511, + offsetof(struct fm10k_port_counters, cnt_tx_256to511_pkts), + offsetof(struct fm10k_port_counters, cnt_tx_256to511_octets)}, +{ FM10K_TX_STAT_BANK_SIZE, FM10K_TX_STAT_LEN_512_1023, + offsetof(struct fm10k_port_counters, cnt_tx_512to1023_pkts), + offsetof(struct fm10k_port_counters, cnt_tx_512to1023_octets)}, +{ FM10K_TX_STAT_BANK_SIZE, FM10K_TX_STAT_LEN_1024_1522, + offsetof(struct fm10k_port_counters, cnt_tx_1024to1522_pkts), + offsetof(struct fm10k_port_counters, cnt_tx_1024to1522_octets)}, +{ FM10K_TX_STAT_BANK_SIZE, FM10K_TX_STAT_LEN_1523_2047, + offsetof(struct fm10k_port_counters, cnt_tx_1523to2047_pkts), + offsetof(struct fm10k_port_counters, cnt_tx_1523to2047_octets)}, +{ FM10K_TX_STAT_BANK_SIZE, FM10K_TX_STAT_LEN_2048_4095, + offsetof(struct fm10k_port_counters, cnt_tx_2048to4095_pkts), + offsetof(struct fm10k_port_counters, cnt_tx_2048to4095_octets)}, +{ FM10K_TX_STAT_BANK_SIZE, FM10K_TX_STAT_LEN_4096_8191, + offsetof(struct fm10k_port_counters, cnt_tx_4096to8191_pkts), + offsetof(struct fm10k_port_counters, cnt_tx_4096to8191_octets)}, +{ FM10K_TX_STAT_BANK_SIZE, FM10K_TX_STAT_LEN_8192_10239, + offsetof(struct fm10k_port_counters, cnt_tx_8192to10239_pkts), + offsetof(struct fm10k_port_counters, cnt_tx_8192to10239_octets)}, +{ FM10K_TX_STAT_BANK_SIZE, FM10K_TX_STAT_LEN_GE_10240, + offsetof(struct fm10k_port_counters, cnt_tx_10240tomax_pkts), + offsetof(struct fm10k_port_counters, cnt_tx_10240tomax_octets)}, + +}; /* end tx_port_cnt_map_table */ + + +/* + * Get a 32bit EPL counter by adding it to the scatter gather + * list. + * Depends on the existence of the variables: + * sgList [out] - scatter gather array to hold the reads + * sgListCnt [out] - number of entry in the sgList + */ +static inline void +fm10k_get_epl_port_stat32(struct fm10k_scatter_gather_entry *sg_list, + struct fm10k_port_counters *counters, + int *sg_list_cnt, int epl, int lane) +{ + sg_list[*sg_list_cnt].addr = FM10K_MAC_OVERSIZE_COUNTER(epl, lane); + sg_list[*sg_list_cnt].data = + (uint32_t *)&counters->cnt_rx_oversized_pkts; + sg_list[*sg_list_cnt].count = 1; + (*sg_list_cnt)++; + + sg_list[*sg_list_cnt].addr = FM10K_MAC_JABBER_COUNTER(epl, lane); + sg_list[*sg_list_cnt].data = + (uint32_t *)&counters->cnt_rx_jabber_pkts; + sg_list[*sg_list_cnt].count = 1; + (*sg_list_cnt)++; + + sg_list[*sg_list_cnt].addr = FM10K_MAC_UNDERSIZE_COUNTER(epl, lane); + sg_list[*sg_list_cnt].data = + (uint32_t *)&counters->cnt_rx_undersized_pkts; + sg_list[*sg_list_cnt].count = 1; + (*sg_list_cnt)++; + + sg_list[*sg_list_cnt].addr = FM10K_MAC_RUNT_COUNTER(epl, lane); + sg_list[*sg_list_cnt].data = + (uint32_t *)&counters->cnt_rx_fragment_pkts; + sg_list[*sg_list_cnt].count = 1; + (*sg_list_cnt)++; + + sg_list[*sg_list_cnt].addr = FM10K_MAC_OVERRUN_COUNTER(epl, lane); + sg_list[*sg_list_cnt].data = + (uint32_t *)&counters->cnt_over_run_pkts; + sg_list[*sg_list_cnt].count = 1; + (*sg_list_cnt)++; + + sg_list[*sg_list_cnt].addr = FM10K_MAC_CODE_ERROR_COUNTER(epl, lane); + sg_list[*sg_list_cnt].data = + (uint32_t *)&counters->cnt_code_errors; + sg_list[*sg_list_cnt].count = 1; + (*sg_list_cnt)++; +} + + +static void +fm10k_read_scatter_gather(struct fm10k_switch *sw, + int n_entries, + struct fm10k_scatter_gather_entry *sg_list) +{ + int i; + + for (i = 0; i < n_entries; i++) { + uint32_t addr = sg_list[i].addr; + uint32_t count = sg_list[i].count; + uint32_t *data = sg_list[i].data; + + fm10k_read_switch_array(sw, addr, data, count); + } +} + + +static int +fm10k_get_port_counters(struct fm10k_switch *sw, + struct fm10k_ext_port *ext_port, + struct fm10k_port_counters *counters) +{ + int phys_port; + int epl; + int lane; + struct timeval ts; + bool valid_ip_stats = true; + uint32_t i; + struct fm10k_scatter_gather_entry sg_list[MAX_STATS_SGLIST]; + int sg_list_cnt = 0; + /* Temporary bin array to retrieve 128bit + * port counters (frame + bytes). + */ + uint32_t cnt_rx_port_stats_bank + [FM10K_NB_RX_STATS_BANKS] + [FM10K_BINS_PER_RX_STATS_BANK] + [FM10K_WORDS_PER_RX_STATS_COUNTER]; + /* + * Fill the counters structure with 0 to assure + * all fields not explicitly set below, which will + * be the fields not supported by the FM10000, + * will be 0 on return. + */ + memset(counters, 0, sizeof(*counters)); + + phys_port = ext_port->portno; + epl = ext_port->eplno; + lane = ext_port->first_lane; + + counters->cnt_version = FM10K_STATS_VERSION; + + /* + * Reading counters for each RX bank + * + * Because the RX_STATS_BANK register contains + * both, frame count and byte count in a 128bit + * register, we first store the data in a temporary + * array. + * 1. Fill Scatter Gather to retrieve each bin + * counter from the rx bank and store in a temp + * array. + */ + for (i = 0; + i < sizeof(rx_port_cnt_map_table) / + sizeof(rx_port_cnt_map_table[0]); + i++) { + /* + * Add a 128bit read of an rx counter to the scatter gather + * list. + * NOTE: Read values will be stored in the temporary + * array switchExt->cnt_rx_port_stats_bank; + * Depends on the existence of the variables: + * switchExt->cnt_rx_PortStatsBank [out] - Array to store the + * 128bit values sgList + * [out] - scatter gather array to hold the reads sgListCnt + * [out] - number of entry in the sgList + */ + uint32_t bank = rx_port_cnt_map_table[i].bank; + uint32_t bin = rx_port_cnt_map_table[i].bin; + + sg_list[sg_list_cnt].addr = + FM10K_RX_STATS_BANK(bank, (phys_port << 4 | (bin)), 0); + sg_list[sg_list_cnt].data = cnt_rx_port_stats_bank[bank][bin]; + sg_list[sg_list_cnt].count = 4; + sg_list_cnt++; +} + + /* + * 2. Fill in the scatter gather for tx bank + * counters. They will directly be stored + * in the fm10k_counters structure upon + * scatter gather read. + */ + for (i = 0; + i < sizeof(tx_port_cnt_map_table) / + sizeof(tx_port_cnt_map_table[0]); + i++) { + /* + * Add a 64bit read of a tx counter to the scatter gather list. + * Depends on the existence of the variables: + * sgList [out] - scatter gather array to hold the reads + * sgListCnt [out] - number of entry in the sgList + */ + uint32_t bank = tx_port_cnt_map_table[i].bank; + uint32_t bin = tx_port_cnt_map_table[i].bin; + uint32_t frame_offset = tx_port_cnt_map_table[i].frame_offset; + + sg_list[sg_list_cnt].addr = + FM10K_MOD_STATS_BANK_FRAME(bank, + (phys_port << 4 | (bin)), 0); + sg_list[sg_list_cnt].data = + (uint32_t *)(((uint8_t *)counters) + (frame_offset)); + sg_list[sg_list_cnt].count = 2; + sg_list_cnt++; + } + + /* + * 3. Fill in the scatter gather for TX CM DROP + * and for EPL counters. They will directly be + * stored in the fm10k_counters structure upon + * scatter gather read. + */ + sg_list[sg_list_cnt].addr = + FM10K_CM_APPLY_DROP_COUNT(phys_port, 0); + sg_list[sg_list_cnt].data = + (uint32_t *)&counters->cnt_rx_cm_drop_pkts; + sg_list[sg_list_cnt].count = 2; + sg_list_cnt++; + /* EPL Counters */ + fm10k_get_epl_port_stat32(sg_list, counters, &sg_list_cnt, epl, lane); + + /* + * 4. Execute scatter gather read. + */ + if (sg_list_cnt >= MAX_STATS_SGLIST) { + /* + * Pretty static. Mainly to warn if something new added, + * but the array size is not adjust accordingly + */ + FM10K_SW_ERR("Scatter list array %d for port %d overflow.\n", + sg_list_cnt, phys_port); + return -1; + } + + /* + * Taking lock to protect temporary structures used to + * store 128b counters + */ + FM10K_SW_SWITCH_LOCK(sw); + + /* now get the stats in one shot, optimized for fibm */ + fm10k_read_scatter_gather(sw, sg_list_cnt, sg_list); + FM10K_SW_SWITCH_UNLOCK(sw); + + counters->timestamp = ts.tv_sec * 1000000 + ts.tv_usec; + + /* + * 5. Retrieve the frame/byte counts from 128bit + * registers stored in temporary array and set + * the proper fm_portCounter structure members. + */ + for (i = 0; + i < sizeof(rx_port_cnt_map_table) / + sizeof(rx_port_cnt_map_table[0]); + i++) { + /* + * Update the counter variable related to a 128bit HW counter + * NOTE: Read values will be retrieved from the temporary + * array switchExt->cnt_rx_PortStatsBank; + * Depends on the existence of the variables: + * switchExt->cnt_rx_PortStatsBank [in] - Array to read the + * 128bit values from + */ + uint32_t bank = rx_port_cnt_map_table[i].bank; + uint32_t bin = rx_port_cnt_map_table[i].bin; + uint32_t frame_offset = rx_port_cnt_map_table[i].frame_offset; + uint32_t byte_offset = rx_port_cnt_map_table[i].byte_offset; + + *((uint64_t *)(((uint8_t *)counters) + frame_offset)) = + (((uint64_t)(cnt_rx_port_stats_bank[bank][bin][1]) << 32) | + ((uint64_t)(cnt_rx_port_stats_bank[bank][bin][0]))); + + *((uint64_t *)(((uint8_t *)counters) + byte_offset)) = + (((uint64_t)(cnt_rx_port_stats_bank[bank][bin][3]) << 32) | + ((uint64_t)(cnt_rx_port_stats_bank[bank][bin][2]))); + } + + /* + * 6. Set some counters that are not available + * in HW but can be computed from two or more + * HW counters. + */ + /* + * If IP parsing is enabled then the IP stats will be read and will be + * valid. Else all traffic, whether IP or not, is counted as _nonip. + */ + if (valid_ip_stats) { + /* + * RX counters. + */ + counters->cnt_rx_ucst_pkts = + counters->cnt_rx_ucst_pkts_nonip + + counters->cnt_rx_ucst_pkts_ipv4 + + counters->cnt_rx_ucst_pkts_ipv6; + + counters->cnt_rx_mcst_pkts = + counters->cnt_rx_mcst_pkts_nonip + + counters->cnt_rx_mcst_pkts_ipv4 + + counters->cnt_rx_mcst_pkts_ipv6; + + counters->cnt_rx_bcst_pkts = + counters->cnt_rx_bcst_pkts_nonip + + counters->cnt_rx_bcst_pkts_ipv4 + + counters->cnt_rx_bcst_pkts_ipv6; + + /* + * Misc. counters. + */ + counters->cnt_rx_octets_nonip = + counters->cnt_rx_ucst_octets_nonip + + counters->cnt_rx_mcst_octets_nonip + + counters->cnt_rx_bcst_octets_nonip; + + counters->cnt_rx_octets_ipv4 = + counters->cnt_rx_ucst_octets_ipv4 + + counters->cnt_rx_mcst_octets_ipv4 + + counters->cnt_rx_bcst_octets_ipv4; + + counters->cnt_rx_octets_ipv6 = + counters->cnt_rx_ucst_octets_ipv6 + + counters->cnt_rx_mcst_octets_ipv6 + + counters->cnt_rx_bcst_octets_ipv6; + + counters->cnt_rx_good_octets = + counters->cnt_rx_octets_nonip + + counters->cnt_rx_octets_ipv4 + + counters->cnt_rx_octets_ipv6; + } else { + /* + * RX counters. + */ + counters->cnt_rx_ucst_pkts = + counters->cnt_rx_ucst_pkts_nonip; + counters->cnt_rx_mcst_pkts = + counters->cnt_rx_mcst_pkts_nonip; + counters->cnt_rx_bcst_pkts = + counters->cnt_rx_bcst_pkts_nonip; + + /* + * Misc. counters. + */ + counters->cnt_rx_octets_nonip = + counters->cnt_rx_ucst_octets_nonip + + counters->cnt_rx_mcst_octets_nonip + + counters->cnt_rx_bcst_octets_nonip; + + counters->cnt_rx_good_octets = + counters->cnt_rx_octets_nonip; + } + + counters->cnt_trigger_drop_redir_pkts = + counters->cnt_trigger_redir_pkts + + counters->cnt_trigger_drop_pkts; + + /* Emulate Tx _octets counter using the sum of all size bins. */ + counters->cnt_tx_octets += counters->cnt_tx_minto63_octets; + counters->cnt_tx_octets += counters->cnt_tx_64_octets; + counters->cnt_tx_octets += counters->cnt_tx_65to127_octets; + counters->cnt_tx_octets += counters->cnt_tx_128to255_octets; + counters->cnt_tx_octets += counters->cnt_tx_256to511_octets; + counters->cnt_tx_octets += counters->cnt_tx_512to1023_octets; + counters->cnt_tx_octets += counters->cnt_tx_1024to1522_octets; + counters->cnt_tx_octets += counters->cnt_tx_1523to2047_octets; + counters->cnt_tx_octets += counters->cnt_tx_2048to4095_octets; + counters->cnt_tx_octets += counters->cnt_tx_4096to8191_octets; + counters->cnt_tx_octets += counters->cnt_tx_8192to10239_octets; + counters->cnt_tx_octets += counters->cnt_tx_10240tomax_octets; + + return 0; +} /* end fm10k_get_port_counters */ + + +struct fm10k_stats_data { + uint64_t rx_pkts; + uint64_t tx_pkts; + uint64_t rx_drop; +}; + + +static uint64_t +fm10k_stats_ffu_count_get(struct fm10k_switch *sw, int table_id) +{ + uint64_t data; + + if (FM10K_SW_FFU_CNT_BANK < 2) { + data = fm10k_read_switch_reg64(sw, + 0xE40000 + 0x4000 * FM10K_SW_FFU_CNT_BANK + + 0x4 * (table_id + FM10K_SW_FFU_CNT_START) + + 0x8000); + } else { + data = fm10k_read_switch_reg64(sw, + 0xE40000 + 0x800 * (FM10K_SW_FFU_CNT_BANK - 2) + + 0x4 * (table_id + FM10K_SW_FFU_CNT_START) + + 0x10000); + } + return data; +} + +static void +fm10k_stats_epl_ffu_print(struct fm10k_switch *sw, int epl) +{ + int table_id; + uint64_t data; + + table_id = FM10K_FFU_EXT_PORT_RULE_INGRESS(epl); + data = fm10k_stats_ffu_count_get(sw, table_id); + printf(" FFU[%d] ingress %-12llu\n", + table_id, (unsigned long long)(data)); + + table_id = FM10K_FFU_EXT_PORT_RULE_EGRESS(epl); + data = fm10k_stats_ffu_count_get(sw, table_id); + printf(" FFU[%d] egress %-12llu\n", + table_id, (unsigned long long)(data)); +} + +#define FM10K_STATS_RULE_NUM_MAX 100 +static uint16_t fm10k_stats_rule_list[FM10K_STATS_RULE_NUM_MAX]; +void +fm10k_stats_rule_count_reg(uint16_t rule_id) +{ + int i; + + for (i = 0; i < FM10K_STATS_RULE_NUM_MAX; i++) { + if (fm10k_stats_rule_list[i] == 0) { + fm10k_stats_rule_list[i] = rule_id; + break; + } + } +} + +void +fm10k_stats_ffu_count_print(struct fm10k_switch *sw) +{ + int i, rule_id; + uint64_t data; + static uint64_t ffu_count[FM10K_STATS_RULE_NUM_MAX]; + + for (i = 0; i < FM10K_STATS_RULE_NUM_MAX; i++) { + if (fm10k_stats_rule_list[i] == 0) + continue; + + rule_id = fm10k_stats_rule_list[i]; + data = fm10k_stats_ffu_count_get(sw, rule_id); + printf("FFU[%d] count %-12llu\n", + rule_id, + (unsigned long long) + (data - ffu_count[rule_id])); + ffu_count[rule_id] = data; + } +} + +void +fm10k_stats_epl_port_print(struct fm10k_switch *sw) +{ + int i, lport; + struct fm10k_port_counters counters; + struct fm10k_ext_port ext_port; + static struct fm10k_stats_data last_data[FM10K_SW_EXT_PORTS_MAX]; + struct fm10k_stats_data data; + + for (i = 0; i < FM10K_SW_EPLS_SUPPORTED; i++) { + lport = sw->epl_map[i].logical_port; + ext_port.portno = lport; + fm10k_get_port_counters(sw, &ext_port, &counters); + + data.rx_pkts = + counters.cnt_rx_bcst_pkts + + counters.cnt_rx_ucst_pkts; + data.tx_pkts = + counters.cnt_tx_bcst_pkts + + counters.cnt_tx_ucst_pkts; + data.rx_drop = counters.cnt_cmpriv_drop_pkts; + printf("EPL port %-2d lport %-5d tx_pkt %-12llu rx_pkt %-12llu drop_pkt %-12llu\n", + i, lport, + (unsigned long long) + (data.tx_pkts - last_data[i].tx_pkts), + (unsigned long long) + (data.rx_pkts - last_data[i].rx_pkts), + (unsigned long long) + (data.rx_drop - last_data[i].rx_drop)); + last_data[i] = data; + + if (fm10k_config_check_debug(sw->dpdk_cfg, + FM10K_CONFIG_DEBUG_STATS_FFU)) + fm10k_stats_epl_ffu_print(sw, i); + } +} + + +void +fm10k_stats_dpdk_port_print(struct fm10k_switch *sw) +{ + int i, j, lport, pf_no; + struct fm10k_port_counters counters; + struct fm10k_ext_port ext_port; + static struct fm10k_stats_data last_data[FM10K_SW_PEPS_MAX]; + static struct fm10k_stats_data last_queue_data[FM10K_SW_PEPS_MAX][4]; + struct fm10k_stats_data data, mydata; + char pf_ports[10]; + + for (i = 0; i < FM10K_SW_LOGICAL_PORTS_MAX; i++) { + if (sw->dpdk_cfg->ports[i].hw == NULL) + continue; + if (sw->dpdk_cfg->ports[i].type != FM10K_CONFIG_DPDK_PF) + continue; + if (sw->dpdk_cfg->dpdk_port_map[i].type == + FM10K_CONFIG_PORT_MAP_NULL) + continue; + + memset(&mydata, 0, sizeof(mydata)); + if (sw->dpdk_cfg->dpdk_port_map[i].type == + FM10K_CONFIG_PORT_MAP_PFS) { + for (j = 0; j < 2; j++) { + pf_no = + sw->dpdk_cfg->dpdk_port_map[i].map_no[j]; + lport = sw->pep_map[pf_no].logical_port; + memset(&ext_port, 0, sizeof(ext_port)); + ext_port.portno = lport; + fm10k_get_port_counters + (sw, &ext_port, &counters); + data.rx_pkts = counters.cnt_rx_bcst_pkts + + counters.cnt_rx_ucst_pkts; + data.tx_pkts = counters.cnt_tx_bcst_pkts + + counters.cnt_tx_ucst_pkts; + data.rx_drop = counters.cnt_cmpriv_drop_pkts; + mydata.rx_pkts += data.rx_pkts - + last_data[pf_no].rx_pkts; + mydata.tx_pkts += data.tx_pkts - + last_data[pf_no].tx_pkts; + mydata.rx_drop += data.rx_drop - + last_data[pf_no].rx_drop; + last_data[pf_no] = data; + } + } else if (sw->dpdk_cfg->dpdk_port_map[i].type == + FM10K_CONFIG_PORT_MAP_PF) { + pf_no = sw->dpdk_cfg->dpdk_port_map[i].map_no[0]; + lport = sw->pep_map[pf_no].logical_port; + memset(&ext_port, 0, sizeof(ext_port)); + ext_port.portno = lport; + fm10k_get_port_counters(sw, &ext_port, &counters); + data.rx_pkts = counters.cnt_rx_bcst_pkts + + counters.cnt_rx_ucst_pkts; + data.tx_pkts = counters.cnt_tx_bcst_pkts + + counters.cnt_tx_ucst_pkts; + data.rx_drop = counters.cnt_cmpriv_drop_pkts; + mydata.rx_pkts += data.rx_pkts - + last_data[pf_no].rx_pkts; + mydata.tx_pkts += data.tx_pkts - + last_data[pf_no].tx_pkts; + mydata.rx_drop += data.rx_drop - + last_data[pf_no].rx_drop; + last_data[pf_no] = data; + } else { + continue; + } + + if (sw->dpdk_cfg->dpdk_port_map[i].type == + FM10K_CONFIG_PORT_MAP_PF) + sprintf(pf_ports, "%d", + sw->dpdk_cfg->dpdk_port_map[i].map_no[0]); + else + sprintf(pf_ports, "%d/%d", + sw->dpdk_cfg->dpdk_port_map[i].map_no[0], + sw->dpdk_cfg->dpdk_port_map[i].map_no[1]); + + printf("DPDK port %-2d pf %-5s tx_pkt %-12llu " + "rx_pkt %-12llu drop_pkt %-12llu\n", + i, pf_ports, + (unsigned long long)mydata.tx_pkts, + (unsigned long long)mydata.rx_pkts, + (unsigned long long)mydata.rx_drop); + + if (!fm10k_config_check_debug(sw->dpdk_cfg, + FM10K_CONFIG_DEBUG_STATS_QUEUE)) + continue; + memset(&mydata, 0, sizeof(mydata)); + for (j = 0; + j < sw->dpdk_cfg->ports[i].tx_queue_num; + j++) { + struct fm10k_hw *hw = sw->dpdk_cfg->ports[i].hw; + uint16_t queue_id = j, pf_no; + + fm10k_switch_dpdk_hw_queue_map(hw, queue_id, + sw->dpdk_cfg->ports[i].tx_queue_num, + &hw, &queue_id); + pf_no = fm10k_switch_dpdk_pf_no_get(hw); + data.tx_pkts = + FM10K_READ_REG(hw, FM10K_QPTC(queue_id)); + data.rx_pkts = + FM10K_READ_REG(hw, FM10K_QPRC(queue_id)); + data.rx_drop = + FM10K_READ_REG(hw, FM10K_QPRDC(queue_id)); + mydata.tx_pkts += data.tx_pkts - + last_queue_data[pf_no][queue_id].tx_pkts; + mydata.rx_pkts += data.rx_pkts - + last_queue_data[pf_no][queue_id].rx_pkts; + mydata.rx_drop += data.rx_drop - + last_queue_data[pf_no][queue_id].rx_drop; + printf(" queue %d(%d:%d) tx_pkt %-12llu " + "rx_pkt %-12llu drop_pkt %-12llu\n", j, + pf_no, queue_id, + (unsigned long long)(data.tx_pkts - + last_queue_data[pf_no][queue_id].tx_pkts), + (unsigned long long)(data.rx_pkts - + last_queue_data[pf_no][queue_id].rx_pkts), + (unsigned long long)(data.rx_drop - + last_queue_data[pf_no][queue_id].rx_drop)); + last_queue_data[pf_no][queue_id] = data; + } + printf(" total tx_pkt %-12llu " + "rx_pkt %-12llu drop_pkt %-12llu\n", + (unsigned long long)mydata.tx_pkts, + (unsigned long long)mydata.rx_pkts, + (unsigned long long)mydata.rx_drop); + } +} + + +static void +fm10k_stats_port_counter_print(struct fm10k_switch *sw, int lport) +{ + unsigned int i; + struct fm10k_port_counters counters; + struct fm10k_ext_port ext_port; + uint64_t *pdata; + + memset(&ext_port, 0, sizeof(ext_port)); + ext_port.portno = lport; + fm10k_get_port_counters(sw, &ext_port, &counters); + + for (i = 0; + i < sizeof(rx_port_cnt_map_table) / + sizeof(rx_port_cnt_map_table[0]); + i++) { + pdata = + (uint64_t *)((uint8_t *)(&counters) + + rx_port_cnt_map_table[i].frame_offset); + if (*pdata != 0) { + printf("port %d rx bank %d idx %d pkt %llu\n", lport, + rx_port_cnt_map_table[i].bank, + rx_port_cnt_map_table[i].bin, + (unsigned long long)*pdata); + } + } + for (i = 0; + i < sizeof(tx_port_cnt_map_table) / + sizeof(tx_port_cnt_map_table[0]); + i++) { + pdata = + (uint64_t *)((uint8_t *)(&counters) + + tx_port_cnt_map_table[i].frame_offset); + if (*pdata != 0) { + printf("port %d tx bank %d idx %d pkt %llu\n", + lport, + tx_port_cnt_map_table[i].bank, + tx_port_cnt_map_table[i].bin, + (unsigned long long)*pdata); + } + } +} + +void +fm10k_stats_port_bank_print(struct fm10k_switch *sw) +{ + int i; + + for (i = 0; + i < FM10K_SW_EPLS_SUPPORTED; + i++) { + fm10k_stats_port_counter_print(sw, + sw->epl_map[i].logical_port); + } + for (i = 0; + i < FM10K_SW_PEPS_SUPPORTED; + i++) { + fm10k_stats_port_counter_print(sw, + sw->pep_map[i].logical_port); + } +} + + +void * +fm10k_switch_process_stats(void *ctx) +{ + struct fm10k_switch *sw = ctx; + + usec_delay(5000000); + + if (!fm10k_config_check_debug(sw->dpdk_cfg, + FM10K_CONFIG_DEBUG_ENABLE)) + return NULL; + + if (!sw->dpdk_cfg->stats_interval) + return NULL; + + while (1) { + if (fm10k_config_check_debug(sw->dpdk_cfg, + FM10K_CONFIG_DEBUG_STATS_PORT)) { + printf("--- port statistic ---\n"); + fm10k_stats_epl_port_print(sw); + fm10k_stats_dpdk_port_print(sw); + } + if (fm10k_config_check_debug(sw->dpdk_cfg, + FM10K_CONFIG_DEBUG_STATS_FFU)) { + printf("--- ffu statistic ---\n"); + fm10k_stats_ffu_count_print(sw); + } + if (fm10k_config_check_debug(sw->dpdk_cfg, + FM10K_CONFIG_DEBUG_STATS_MORE)) { + printf("--- detail statistic ---\n"); + fm10k_stats_port_bank_print(sw); + } + usec_delay(1000000 * sw->dpdk_cfg->stats_interval); + } + return NULL; +} + diff --git a/drivers/net/fm10k/switch/fm10k_stats.h b/drivers/net/fm10k/switch/fm10k_stats.h new file mode 100644 index 0000000..5180312 --- /dev/null +++ b/drivers/net/fm10k/switch/fm10k_stats.h @@ -0,0 +1,257 @@ +/* spdx-license-identifier: bsd-3-clause + * copyright 2019 silicom ltd. connectivity solutions + */ + +#ifndef _fm10k_stats_h_ +#define _fm10k_stats_h_ + + +#include + + +#define FM10K_STATS_VERSION (1 << 4) + + +struct fm10k_scatter_gather_entry { + uint32_t addr; + uint32_t count; + uint32_t *data; + +}; + + +struct fm10k_port_counters { + uint64_t cnt_version; + uint64_t cnt_rx_ucst_pkts; + uint64_t cnt_rx_ucst_pkts_nonip; + uint64_t cnt_rx_ucst_pkts_ipv4; + uint64_t cnt_rx_ucst_pkts_ipv6; + uint64_t cnt_rx_bcst_pkts; + uint64_t cnt_rx_bcst_pkts_nonip; + uint64_t cnt_rx_bcst_pkts_ipv4; + uint64_t cnt_rx_bcst_pkts_ipv6; + uint64_t cnt_rx_mcst_pkts; + uint64_t cnt_rx_mcst_pkts_nonip; + uint64_t cnt_rx_mcst_pkts_ipv4; + uint64_t cnt_rx_mcst_pkts_ipv6; + uint64_t cnt_rx_pause_pkts; + uint64_t cnt_rx_cbpause_pkts; + uint64_t cnt_rx_fcs_errors; + uint64_t cnt_rx_symbol_errors; + uint64_t cnt_rx_framesize_errors; + uint64_t cnt_rx_framing_error_pkts; + uint64_t cnt_rx_minto63_pkts; + uint64_t cnt_rx_64_pkts; + uint64_t cnt_rx_65to127_pkts; + uint64_t cnt_rx_128to255_pkts; + uint64_t cnt_rx_256to511_pkts; + uint64_t cnt_rx_512to1023_pkts; + uint64_t cnt_rx_1024to1522_pkts; + uint64_t cnt_rx_1523to2047_pkts; + uint64_t cnt_rx_2048to4095_pkts; + uint64_t cnt_rx_4096to8191_pkts; + uint64_t cnt_rx_8192to10239_pkts; + uint64_t cnt_rx_10240tomax_pkts; + uint64_t cnt_rx_minto63_octets; + uint64_t cnt_rx_64_octets; + uint64_t cnt_rx_65to127_octets; + uint64_t cnt_rx_128to255_octets; + uint64_t cnt_rx_256to511_octets; + uint64_t cnt_rx_512to1023_octets; + uint64_t cnt_rx_1024to1522_octets; + uint64_t cnt_rx_1523to2047_octets; + uint64_t cnt_rx_2048to4095_octets; + uint64_t cnt_rx_4096to8191_octets; + uint64_t cnt_rx_8192to10239_octets; + uint64_t cnt_rx_10240tomax_octets; + uint64_t cnt_rx_octets_nonip; + uint64_t cnt_rx_octets_ipv4; + uint64_t cnt_rx_octets_ipv6; + uint64_t cnt_rx_ucst_octets_nonip; + uint64_t cnt_rx_ucst_octets_ipv4; + uint64_t cnt_rx_ucst_octets_ipv6; + uint64_t cnt_rx_bcst_octets_nonip; + uint64_t cnt_rx_bcst_octets_ipv4; + uint64_t cnt_rx_bcst_octets_ipv6; + uint64_t cnt_rx_mcst_octets_nonip; + uint64_t cnt_rx_mcst_octets_ipv4; + uint64_t cnt_rx_mcst_octets_ipv6; + uint64_t cnt_rx_pause_octets; + uint64_t cnt_rx_cbpause_octets; + uint64_t cnt_rx_fcs_errors_octets; + uint64_t cnt_rx_framing_error_octets; + uint64_t cnt_rx_good_octets; + uint64_t cnt_rx_bad_octets; + uint64_t cnt_rx_priority_pkts[16]; + uint64_t cnt_rx_invalid_priority_pkts; + uint64_t cnt_rx_priority_octets[16]; + uint64_t cnt_rx_invalid_priority_octets; + uint64_t cnt_fid_forwarded_pkts; + uint64_t cnt_flood_forwarded_pkts; + uint64_t cnt_glort_switched_pkts; + uint64_t cnt_glort_routed_pkts; + uint64_t cnt_specially_handled_pkts; + uint64_t cnt_parse_err_drop_pkts; + uint64_t cnt_parity_error_pkts; + uint64_t cnt_trapped_pkts; + uint64_t cnt_pause_drop_pkts; + uint64_t cnt_stp_drop_pkts; + uint64_t cnt_stp_ingress_drops_pkts; + uint64_t cnt_stp_egress_drops_pkts; + uint64_t cnt_reserved_trap_pkts; + uint64_t cnt_security_violation_pkts; + uint64_t cnt_vlan_tag_drop_pkts; + uint64_t cnt_vlan_ingressbv_pkts; + uint64_t cnt_vlan_egressbv_pkts; + uint64_t cnt_loopback_drops_pkts; + uint64_t cnt_glort_miss_drop_pkts; + uint64_t cnt_ffu_drop_pkts; + uint64_t cnt_invalid_drop_pkts; + uint64_t cnt_policer_drop_pkts; + uint64_t cnt_ttl_drop_pkts; + uint64_t cnt_global_wmdrop_pkts; + uint64_t cnt_rx_mpdrop_pkts; + uint64_t cnt_rx_hogdrop_pkts; + uint64_t cnt_tx_hogdrop_pkts; + uint64_t cnt_other_pkts; + uint64_t cnt_flood_control_drop_pkts; + uint64_t cnt_cmpriv_drop_pkts; + uint64_t cnt_smp0_drop_pkts; + uint64_t cnt_smp1_drop_pkts; + uint64_t cnt_rx_hog0_drop_pkts; + uint64_t cnt_rx_hog1_drop_pkts; + uint64_t cnt_tx_hog0_drop_pkts; + uint64_t cnt_tx_hog1_drop_pkts; + uint64_t cnt_rate_limit0_drop_pkts; + uint64_t cnt_rate_limit1_drop_pkts; + uint64_t cnt_bad_smp_drop_pkts; + uint64_t cnt_trigger_drop_redir_pkts; + uint64_t cnt_trigger_drop_pkts; + uint64_t cnt_trigger_redir_pkts; + uint64_t cnt_glort_forwarded_pkts; + uint64_t cnt_trigger_mirrored_pkts; + uint64_t cnt_broadcast_drop_pkts; + uint64_t cnt_dlf_drop_pkts; + uint64_t cnt_rx_cm_drop_pkts; + uint64_t cnt_fid_forwarded_octets; + uint64_t cnt_flood_forwarded_octets; + uint64_t cnt_specially_handled_octets; + uint64_t cnt_parse_err_drop_octets; + uint64_t cnt_parity_error_octets; + uint64_t cnt_trapped_octets; + uint64_t cnt_pause_drop_octets; + uint64_t cnt_stp_drop_octets; + uint64_t cnt_security_violation_octets; + uint64_t cnt_vlan_tag_drop_octets; + uint64_t cnt_vlan_ingressbv_octets; + uint64_t cnt_vlan_egressbv_octets; + uint64_t cnt_loopback_drop_octets; + uint64_t cnt_glort_miss_drop_octets; + uint64_t cnt_ffu_drop_octets; + uint64_t cnt_policer_drop_octets; + uint64_t cnt_ttl_drop_octets; + uint64_t cnt_other_octets; + uint64_t cnt_flood_control_drop_octets; + uint64_t cnt_cmpriv_drop_octets; + uint64_t cnt_smp0_drop_octets; + uint64_t cnt_smp1_drop_octets; + uint64_t cnt_rx_hog0_drop_octets; + uint64_t cnt_rx_hog1_drop_octets; + uint64_t cnt_tx_hog0_drop_octets; + uint64_t cnt_tx_hog1_drop_octets; + uint64_t cnt_trigger_drop_octets; + uint64_t cnt_trigger_redir_octets; + uint64_t cnt_glort_forwarded_octets; + uint64_t cnt_tx_ucst_pkts; + uint64_t cnt_tx_bcst_pkts; + uint64_t cnt_tx_mcst_pkts; + uint64_t cnt_tx_ucst_pkts_nonip; + uint64_t cnt_tx_bcst_pkts_nonip; + uint64_t cnt_tx_mcst_pkts_nonip; + uint64_t cnt_tx_ucst_pkts_ip; + uint64_t cnt_tx_bcst_pkts_ip; + uint64_t cnt_tx_mcst_pkts_ip; + uint64_t cnt_tx_pause_pkts; + uint64_t cnt_tx_cbpause_pkts; + uint64_t cnt_tx_fcs_err_drop_pkts; + uint64_t cnt_tx_framing_error_pkts; + uint64_t cnt_tx_error_sent_pkts; + uint64_t cnt_tx_error_drop_pkts; + uint64_t cnt_tx_timeout_pkts; + uint64_t cnt_tx_outofmem_err_pkts; + uint64_t cnt_tx_unrepair_ecc_pkts; + uint64_t cnt_tx_loopback_pkts; + uint64_t cnt_tx_ttl_drop_pkts; + uint64_t cnt_tx_minto63_pkts; + uint64_t cnt_tx_64_pkts; + uint64_t cnt_tx_65to127_pkts; + uint64_t cnt_tx_128to255_pkts; + uint64_t cnt_tx_256to511_pkts; + uint64_t cnt_tx_512to1023_pkts; + uint64_t cnt_tx_1024to1522_pkts; + uint64_t cnt_tx_1523to2047_pkts; + uint64_t cnt_tx_2048to4095_pkts; + uint64_t cnt_tx_4096to8191_pkts; + uint64_t cnt_tx_8192to10239_pkts; + uint64_t cnt_tx_10240tomax_pkts; + uint64_t cnt_tx_minto63_octets; + uint64_t cnt_tx_64_octets; + uint64_t cnt_tx_65to127_octets; + uint64_t cnt_tx_128to255_octets; + uint64_t cnt_tx_256to511_octets; + uint64_t cnt_tx_512to1023_octets; + uint64_t cnt_tx_1024to1522_octets; + uint64_t cnt_tx_1523to2047_octets; + uint64_t cnt_tx_2048to4095_octets; + uint64_t cnt_tx_4096to8191_octets; + uint64_t cnt_tx_8192to10239_octets; + uint64_t cnt_tx_10240tomax_octets; + uint64_t cnt_tx_ucst_octets_nonip; + uint64_t cnt_tx_bcst_octets_nonip; + uint64_t cnt_tx_mcst_octets_nonip; + uint64_t cnt_tx_ucst_octets_ip; + uint64_t cnt_tx_bcst_octets_ip; + uint64_t cnt_tx_mcst_octets_ip; + uint64_t cnt_tx_ucst_octets; + uint64_t cnt_tx_mcst_octets; + uint64_t cnt_tx_bcst_octets; + uint64_t cnt_tx_fcs_err_drop_octets; + uint64_t cnt_tx_octets; + uint64_t cnt_tx_error_octets; + uint64_t cnt_tx_framing_error_octets; + uint64_t cnt_tx_pause_octets; + uint64_t cnt_tx_cbpause_octets; + uint64_t cnt_tx_fcs_errored_octets; + uint64_t cnt_tx_error_sent_octets; + uint64_t cnt_tx_timeout_octets; + uint64_t cnt_tx_outofmem_err_octets; + uint64_t cnt_tx_unrepair_ecc_octets; + uint64_t cnt_tx_loopback_octets; + uint64_t cnt_tx_ttl_drop_octets; + uint64_t cnt_tx_priority_octets[16]; + uint64_t cnt_under_run_pkts; + uint64_t cnt_over_run_pkts; + uint64_t cnt_rx_fragment_pkts; + uint64_t cnt_rx_undersized_pkts; + uint64_t cnt_rx_jabber_pkts; + uint64_t cnt_corrupted_pkts; + uint64_t cnt_code_errors; + uint64_t cnt_rx_oversized_pkts; + uint64_t cnt_tx_fcs_errored_pkts; + uint64_t cnt_stats_drop_count_tx; + uint64_t cnt_stats_drop_count_rx; + uint64_t cnt_tx_mirror_pkts; + uint64_t cnt_tx_mirror_octets; + uint64_t cnt_tx_cmdrop_pkts; + uint64_t timestamp; +}; + +void fm10k_stats_rule_count_reg(uint16_t rule_id); +void *fm10k_switch_process_stats(void *ctx_); + +void fm10k_stats_epl_port_print(struct fm10k_switch *sw); +void fm10k_stats_dpdk_port_print(struct fm10k_switch *sw); +void fm10k_stats_ffu_count_print(struct fm10k_switch *sw); +void fm10k_stats_port_bank_print(struct fm10k_switch *sw); + +#endif /* _fm10k_stats_h */