From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id ECEA743747; Tue, 19 Dec 2023 18:40:57 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id DCECC42E53; Tue, 19 Dec 2023 18:40:44 +0100 (CET) Received: from mx0b-0016f401.pphosted.com (mx0b-0016f401.pphosted.com [67.231.156.173]) by mails.dpdk.org (Postfix) with ESMTP id 0C4C842E5E for ; Tue, 19 Dec 2023 18:40:42 +0100 (CET) Received: from pps.filterd (m0045851.ppops.net [127.0.0.1]) by mx0b-0016f401.pphosted.com (8.17.1.24/8.17.1.24) with ESMTP id 3BJ93T8W016883 for ; Tue, 19 Dec 2023 09:40:42 -0800 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h= from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-type; s=pfpt0220; bh=F/r+yjC6WSKCba9sWmIt6 RLrjx9S5KQhijeSVR0hsQA=; b=PKPn5NtnvQ1og3pu9mpxxiCuWFyf3o2o1+7aY fk6lB1A/CbESpgBrbL8E28VYwzlFJHdLzw3B6fhBk2JrPvlCySljIELg9TTmgFR1 VyKRTKA9LeWOtwg9U8lA3FyRxZ11pud7xnhK+gyS0Lh5HKX9JeAF/I6ZgkAYTZ0V zFWV4nTuEK4CNvlEF1GARv86IRSjsG+NpkYdDebEu5Zi2zW1YkQns0O6sunNkGZu fZ1JcaPMZ0nhBXyES/i/m/3arxJ2kEU5y77Yr/OZU62q6fnInOX8FT00QG0NeA3J H309e+R3Y+G6ruo6q5zg2nrVtag9MfHmhp+4XpMRl58at74Fg== Received: from dc5-exch02.marvell.com ([199.233.59.182]) by mx0b-0016f401.pphosted.com (PPS) with ESMTPS id 3v1c9kumdh-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Tue, 19 Dec 2023 09:40:42 -0800 (PST) Received: from DC5-EXCH01.marvell.com (10.69.176.38) by DC5-EXCH02.marvell.com (10.69.176.39) with Microsoft SMTP Server (TLS) id 15.0.1497.48; Tue, 19 Dec 2023 09:40:40 -0800 Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server id 15.0.1497.48 via Frontend Transport; Tue, 19 Dec 2023 09:40:40 -0800 Received: from localhost.localdomain (unknown [10.29.52.211]) by maili.marvell.com (Postfix) with ESMTP id A8F913F7098; Tue, 19 Dec 2023 09:40:37 -0800 (PST) From: Harman Kalra To: Nithin Dabilpuram , Kiran Kumar K , Sunil Kumar Kori , Satha Rao , Harman Kalra CC: , Subject: [PATCH v2 04/24] net/cnxk: eswitch devargs parsing Date: Tue, 19 Dec 2023 23:09:43 +0530 Message-ID: <20231219174003.72901-5-hkalra@marvell.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20231219174003.72901-1-hkalra@marvell.com> References: <20230811163419.165790-1-hkalra@marvell.com> <20231219174003.72901-1-hkalra@marvell.com> MIME-Version: 1.0 Content-Type: text/plain X-Proofpoint-ORIG-GUID: QJpGhgC1ZB97IHK1aBW41X-sxocXo3hW X-Proofpoint-GUID: QJpGhgC1ZB97IHK1aBW41X-sxocXo3hW X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.272,Aquarius:18.0.997,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2023-12-09_02,2023-12-07_01,2023-05-22_02 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Implementing the devargs parsing logic via which the representors pattern is provided. These patterns define for which representies representors shall be created. Signed-off-by: Harman Kalra --- drivers/net/cnxk/cnxk_eswitch.c | 88 +++++++++ drivers/net/cnxk/cnxk_eswitch.h | 52 ++++++ drivers/net/cnxk/cnxk_eswitch_devargs.c | 236 ++++++++++++++++++++++++ drivers/net/cnxk/meson.build | 1 + 4 files changed, 377 insertions(+) create mode 100644 drivers/net/cnxk/cnxk_eswitch_devargs.c diff --git a/drivers/net/cnxk/cnxk_eswitch.c b/drivers/net/cnxk/cnxk_eswitch.c index 306edc6037..739a09c034 100644 --- a/drivers/net/cnxk/cnxk_eswitch.c +++ b/drivers/net/cnxk/cnxk_eswitch.c @@ -456,6 +456,7 @@ nix_lf_setup(struct cnxk_eswitch_dev *eswitch_dev) plt_err("Failed to get rep cnt, rc=%d(%s)", rc, roc_error_msg_get(rc)); goto free_cqs; } + eswitch_dev->repr_cnt.max_repr = eswitch_dev->nix.rep_cnt; /* Allocating an NIX LF */ nb_rxq = CNXK_ESWITCH_MAX_RXQ; @@ -601,11 +602,73 @@ eswitch_hw_rsrc_setup(struct cnxk_eswitch_dev *eswitch_dev) return rc; } +int +cnxk_eswitch_representor_info_get(struct cnxk_eswitch_dev *eswitch_dev, + struct rte_eth_representor_info *info) +{ + struct cnxk_eswitch_devargs *esw_da; + int rc = 0, n_entries, i, j = 0, k = 0; + + for (i = 0; i < eswitch_dev->nb_esw_da; i++) { + for (j = 0; j < eswitch_dev->esw_da[i].nb_repr_ports; j++) + k++; + } + n_entries = k; + + if (info == NULL) + goto out; + + if ((uint32_t)n_entries > info->nb_ranges_alloc) + n_entries = info->nb_ranges_alloc; + + k = 0; + info->controller = 0; + info->pf = 0; + for (i = 0; i < eswitch_dev->nb_esw_da; i++) { + esw_da = &eswitch_dev->esw_da[i]; + info->ranges[k].type = esw_da->da.type; + switch (esw_da->da.type) { + case RTE_ETH_REPRESENTOR_PF: + info->ranges[k].controller = 0; + info->ranges[k].pf = esw_da->repr_hw_info[0].pfvf; + info->ranges[k].vf = 0; + info->ranges[k].id_base = info->ranges[i].pf; + info->ranges[k].id_end = info->ranges[i].pf; + snprintf(info->ranges[k].name, sizeof(info->ranges[k].name), "pf%d", + info->ranges[k].pf); + k++; + break; + case RTE_ETH_REPRESENTOR_VF: + for (j = 0; j < esw_da->nb_repr_ports; j++) { + info->ranges[k].controller = 0; + info->ranges[k].pf = esw_da->da.ports[0]; + info->ranges[k].vf = esw_da->repr_hw_info[j].pfvf; + info->ranges[k].id_base = esw_da->repr_hw_info[j].port_id; + info->ranges[k].id_end = esw_da->repr_hw_info[j].port_id; + snprintf(info->ranges[k].name, sizeof(info->ranges[k].name), + "pf%dvf%d", info->ranges[k].pf, info->ranges[k].vf); + k++; + } + break; + default: + plt_err("Invalid type %d", esw_da->da.type); + rc = 0; + goto fail; + }; + } + info->nb_ranges = k; +fail: + return rc; +out: + return n_entries; +} + static int cnxk_eswitch_dev_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev) { struct cnxk_eswitch_dev *eswitch_dev; const struct rte_memzone *mz = NULL; + uint16_t num_reps; int rc = -ENOMEM; RTE_SET_USED(pci_drv); @@ -638,12 +701,37 @@ cnxk_eswitch_dev_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pc } } + if (pci_dev->device.devargs) { + rc = cnxk_eswitch_repr_devargs(pci_dev, eswitch_dev); + if (rc) + goto rsrc_cleanup; + } + + if (eswitch_dev->repr_cnt.nb_repr_created > eswitch_dev->repr_cnt.max_repr) { + plt_err("Representors to be created %d can be greater than max allowed %d", + eswitch_dev->repr_cnt.nb_repr_created, eswitch_dev->repr_cnt.max_repr); + rc = -EINVAL; + goto rsrc_cleanup; + } + + num_reps = eswitch_dev->repr_cnt.nb_repr_created; + if (!num_reps) { + plt_err("No representors enabled"); + goto fail; + } + + plt_esw_dbg("Max no of reps %d reps to be created %d Eswtch pfunc %x", + eswitch_dev->repr_cnt.max_repr, eswitch_dev->repr_cnt.nb_repr_created, + roc_nix_get_pf_func(&eswitch_dev->nix)); + /* Spinlock for synchronization between representors traffic and control * messages */ rte_spinlock_init(&eswitch_dev->rep_lock); return rc; +rsrc_cleanup: + eswitch_hw_rsrc_cleanup(eswitch_dev); free_mem: if (mz) rte_memzone_free(mz); diff --git a/drivers/net/cnxk/cnxk_eswitch.h b/drivers/net/cnxk/cnxk_eswitch.h index 331397021b..dcb787cf02 100644 --- a/drivers/net/cnxk/cnxk_eswitch.h +++ b/drivers/net/cnxk/cnxk_eswitch.h @@ -25,6 +25,47 @@ #define CNXK_ESWITCH_QUEUE_STATE_STARTED 2 #define CNXK_ESWITCH_QUEUE_STATE_STOPPED 3 +enum cnxk_esw_da_pattern_type { + CNXK_ESW_DA_TYPE_LIST = 0, + CNXK_ESW_DA_TYPE_PFVF, +}; + +struct cnxk_esw_repr_hw_info { + /* Representee pcifunc value */ + uint16_t hw_func; + /* rep id in sync with kernel */ + uint16_t rep_id; + /* pf or vf id */ + uint16_t pfvf; + /* representor port id assigned to representee */ + uint16_t port_id; +}; + +/* Structure representing per devarg information - this can be per representee + * or range of representee + */ +struct cnxk_eswitch_devargs { + /* Devargs populated */ + struct rte_eth_devargs da; + /* HW info of representee */ + struct cnxk_esw_repr_hw_info *repr_hw_info; + /* No of representor ports */ + uint16_t nb_repr_ports; + /* Devargs pattern type */ + enum cnxk_esw_da_pattern_type type; +}; + +struct cnxk_eswitch_repr_cnt { + /* Max possible representors */ + uint16_t max_repr; + /* Representors to be created as per devargs passed */ + uint16_t nb_repr_created; + /* Representors probed successfully */ + uint16_t nb_repr_probed; + /* Representors started representing a representee */ + uint16_t nb_repr_started; +}; + struct cnxk_rep_info { struct rte_eth_dev *rep_eth_dev; }; @@ -70,6 +111,14 @@ struct cnxk_eswitch_dev { uint16_t rep_cnt; uint8_t configured; + /* Eswitch Representors Devargs */ + uint16_t nb_esw_da; + uint16_t last_probed; + struct cnxk_eswitch_devargs esw_da[RTE_MAX_ETHPORTS]; + + /* No of representors */ + struct cnxk_eswitch_repr_cnt repr_cnt; + /* Port representor fields */ rte_spinlock_t rep_lock; uint16_t switch_domain_id; @@ -90,6 +139,9 @@ cnxk_eswitch_pmd_priv(void) } int cnxk_eswitch_nix_rsrc_start(struct cnxk_eswitch_dev *eswitch_dev); +int cnxk_eswitch_repr_devargs(struct rte_pci_device *pci_dev, struct cnxk_eswitch_dev *eswitch_dev); +int cnxk_eswitch_representor_info_get(struct cnxk_eswitch_dev *eswitch_dev, + struct rte_eth_representor_info *info); int cnxk_eswitch_txq_setup(struct cnxk_eswitch_dev *eswitch_dev, uint16_t qid, uint16_t nb_desc, const struct rte_eth_txconf *tx_conf); int cnxk_eswitch_txq_release(struct cnxk_eswitch_dev *eswitch_dev, uint16_t qid); diff --git a/drivers/net/cnxk/cnxk_eswitch_devargs.c b/drivers/net/cnxk/cnxk_eswitch_devargs.c new file mode 100644 index 0000000000..f1a1b05a99 --- /dev/null +++ b/drivers/net/cnxk/cnxk_eswitch_devargs.c @@ -0,0 +1,236 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2023 Marvell. + */ + +#include + +#define PF_SHIFT 10 +static inline int +get_hw_func(uint16_t pf, uint16_t vf) +{ + return (pf << PF_SHIFT) | vf; +} + +static int +devargs_enlist(uint16_t *list, uint16_t *len_list, const uint16_t max_list, uint16_t val) +{ + uint16_t i; + + for (i = 0; i < *len_list; i++) { + if (list[i] == val) + return 0; + } + if (*len_list >= max_list) + return -1; + list[(*len_list)++] = val; + return 0; +} + +static char * +devargs_process_range(char *str, uint16_t *list, uint16_t *len_list, const uint16_t max_list) +{ + uint16_t lo, hi, val; + int result, n = 0; + char *pos = str; + + result = sscanf(str, "%hu%n-%hu%n", &lo, &n, &hi, &n); + if (result == 1) { + if (devargs_enlist(list, len_list, max_list, lo) != 0) + return NULL; + } else if (result == 2) { + if (lo > hi) + return NULL; + for (val = lo; val <= hi; val++) { + if (devargs_enlist(list, len_list, max_list, val) != 0) + return NULL; + } + } else { + return NULL; + } + + return pos + n; +} + +static char * +devargs_process_list(char *str, uint16_t *list, uint16_t *len_list, const uint16_t max_list) +{ + char *pos = str; + + if (*pos == '[') + pos++; + while (1) { + pos = devargs_process_range(pos, list, len_list, max_list); + if (pos == NULL) + return NULL; + if (*pos != ',') /* end of list */ + break; + pos++; + } + if (*str == '[' && *pos != ']') + return NULL; + if (*pos == ']') + pos++; + return pos; +} + +static int +devargs_parse_representor_ports(char *str, void *data) +{ + struct rte_eth_devargs *eth_da = data; + + if (str[0] == 'p' && str[1] == 'f') { + eth_da->type = RTE_ETH_REPRESENTOR_PF; + str += 2; + str = devargs_process_list(str, eth_da->ports, ð_da->nb_ports, + RTE_DIM(eth_da->ports)); + if (str == NULL || str[0] == '\0') + goto done; + } + + if (str[0] == 'v' && str[1] == 'f') { + eth_da->type = RTE_ETH_REPRESENTOR_VF; + str += 2; + } else if (str[0] == 's' && str[1] == 'f') { + eth_da->type = RTE_ETH_REPRESENTOR_SF; + str += 2; + } else { + /* 'pf' must followed by 'vf' or 'sf'. */ + if (eth_da->type == RTE_ETH_REPRESENTOR_PF) { + str = NULL; + goto done; + } + eth_da->type = RTE_ETH_REPRESENTOR_VF; + } + str = devargs_process_list(str, eth_da->representor_ports, ð_da->nb_representor_ports, + RTE_DIM(eth_da->representor_ports)); +done: + if (str == NULL) + plt_err("wrong representor format: %s", str); + return str == NULL ? -1 : 0; +} + +static int +populate_repr_hw_info(struct cnxk_eswitch_dev *eswitch_dev, struct rte_eth_devargs *eth_da, + uint16_t idx) +{ + struct cnxk_eswitch_devargs *esw_da = &eswitch_dev->esw_da[idx]; + uint16_t nb_repr_ports, hw_func; + int rc, i, j; + + if (eth_da->type == RTE_ETH_REPRESENTOR_NONE) { + plt_err("No representor type found"); + return -EINVAL; + } + + if (eth_da->type != RTE_ETH_REPRESENTOR_VF && eth_da->type != RTE_ETH_REPRESENTOR_PF && + eth_da->type != RTE_ETH_REPRESENTOR_SF) { + plt_err("unsupported representor type %d\n", eth_da->type); + return -ENOTSUP; + } + + nb_repr_ports = (eth_da->type == RTE_ETH_REPRESENTOR_PF) ? eth_da->nb_ports : + eth_da->nb_representor_ports; + esw_da->nb_repr_ports = nb_repr_ports; + /* If plain list is provided as representor pattern */ + if (eth_da->nb_ports == 0) + return 0; + + esw_da->repr_hw_info = plt_zmalloc(nb_repr_ports * sizeof(struct cnxk_esw_repr_hw_info), 0); + if (!esw_da->repr_hw_info) { + plt_err("Failed to allocate memory"); + rc = -ENOMEM; + goto fail; + } + + plt_esw_dbg("Representor param %d has %d pfvf", idx, nb_repr_ports); + /* Check if representor can be created for PFVF and populating HW func list */ + for (i = 0; i < nb_repr_ports; i++) { + if (eth_da->type == RTE_ETH_REPRESENTOR_PF) + hw_func = get_hw_func(eth_da->ports[0], 0); + else + hw_func = get_hw_func(eth_da->ports[0], eth_da->representor_ports[i] + 1); + + for (j = 0; j < eswitch_dev->repr_cnt.max_repr; j++) { + if (eswitch_dev->nix.rep_pfvf_map[j] == hw_func) + break; + } + + /* HW func which does not match the map table received from AF, no + * representor port is assigned. + */ + if (j == eswitch_dev->repr_cnt.max_repr) { + plt_err("Representor port cant be created for PF%dVF%d", eth_da->ports[0], + eth_da->representor_ports[i]); + rc = -EINVAL; + goto fail; + } + + esw_da->repr_hw_info[i].hw_func = hw_func; + esw_da->repr_hw_info[i].rep_id = j; + esw_da->repr_hw_info[i].pfvf = (eth_da->type == RTE_ETH_REPRESENTOR_PF) ? + eth_da->ports[0] : + eth_da->representor_ports[i]; + plt_esw_dbg(" HW func %x index %d", hw_func, j); + } + + esw_da->type = CNXK_ESW_DA_TYPE_PFVF; + + return 0; +fail: + return rc; +} + +int +cnxk_eswitch_repr_devargs(struct rte_pci_device *pci_dev, struct cnxk_eswitch_dev *eswitch_dev) +{ + struct rte_devargs *devargs = pci_dev->device.devargs; + struct rte_eth_devargs *eth_da; + struct rte_kvargs *kvlist; + uint32_t i; + int rc, j; + + if (devargs == NULL) { + plt_err("No devargs passed"); + rc = -EINVAL; + goto fail; + } + + kvlist = rte_kvargs_parse(devargs->args, NULL); + if (kvlist == NULL) { + plt_err("Failed to find representor key in devargs list"); + rc = -EINVAL; + goto fail; + } + + if (rte_kvargs_count(kvlist, "representor") <= 0) { + plt_err("Invalid representor key count"); + rc = -EINVAL; + goto fail; + } + + j = eswitch_dev->nb_esw_da; + for (i = 0; i < kvlist->count; i++) { + eth_da = &eswitch_dev->esw_da[j].da; + memset(eth_da, 0, sizeof(*eth_da)); + rc = devargs_parse_representor_ports(kvlist->pairs[i].value, eth_da); + if (rc) { + plt_err("Failed to parse the representor devargs, err %d", rc); + goto fail; + } + + rc = populate_repr_hw_info(eswitch_dev, eth_da, j); + if (rc) { + plt_err("Failed to populate representer hw funcs, err %d", rc); + goto fail; + } + + /* No of representor ports to be created */ + eswitch_dev->repr_cnt.nb_repr_created += eswitch_dev->esw_da[j].nb_repr_ports; + j++; + } + eswitch_dev->nb_esw_da += kvlist->count; + + return 0; +fail: + return rc; +} diff --git a/drivers/net/cnxk/meson.build b/drivers/net/cnxk/meson.build index 012d098f80..ea7e363e89 100644 --- a/drivers/net/cnxk/meson.build +++ b/drivers/net/cnxk/meson.build @@ -29,6 +29,7 @@ sources = files( 'cnxk_ethdev_telemetry.c', 'cnxk_ethdev_sec_telemetry.c', 'cnxk_eswitch.c', + 'cnxk_eswitch_devargs.c', 'cnxk_link.c', 'cnxk_lookup.c', 'cnxk_ptp.c', -- 2.18.0