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 ED1E1458FA; Wed, 4 Sep 2024 04:43:45 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id D2D8E40299; Wed, 4 Sep 2024 04:43:43 +0200 (CEST) Received: from mail-lf1-f50.google.com (mail-lf1-f50.google.com [209.85.167.50]) by mails.dpdk.org (Postfix) with ESMTP id 3D7F64028A for ; Wed, 4 Sep 2024 04:43:42 +0200 (CEST) Received: by mail-lf1-f50.google.com with SMTP id 2adb3069b0e04-533488ffaddso7395124e87.1 for ; Tue, 03 Sep 2024 19:43:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1725417821; x=1726022621; darn=dpdk.org; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=5ET6TG2vnRCw1RitSIWLEGh+KbBNzw/56IeEllcN660=; b=Ms+NbGO4XN9Bg5xfqtS5w/Fw6Wch8MSb15uHMU5j2sGKh5fv4bJa2EsD3e6Zo2oGAn Kr2xHkSAr5mjUNSvwKREu444J9pAu6jKzy1YqNi0wOVtYLqJs8M9kdGgrccASse0Hvn+ 35e/JNi4k/8NYvrGxffvihXw6dRZhtxjtkzEY= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1725417821; x=1726022621; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=5ET6TG2vnRCw1RitSIWLEGh+KbBNzw/56IeEllcN660=; b=Y0/Ij/J2X3k1O9VMiXmTBjPCcAf2of2XjL2FjalPI4XtRcMogGKjiFxv7w5XJi52mk kyd+UTJzEk+OzUuAARCP6t/3gm2Z0512uerEhhPYFtbZh2XXEwAyN928201HTj1bWYnY 8BPFvwDTbMmNBLj9hPbY+EVq2XLodC5qrVKlSGjeYZw0+k8ny/fjg2HokXfRTGBjm0r8 bIgXZUPZYbP8adJt2fYhh594WfIDOXrCIoJSAR20+wMsmqhQGbjxy0XqLZtOOb07+D+M 6kW0KRks95+oh1gqJV8KN73SL2IeX/CFBfNdg9yzrjf7BKEmyCEtlrnp0HYii76Nxuig u/JA== X-Forwarded-Encrypted: i=1; AJvYcCU5XrQA7n9WXPAg/BmrqNRQzJoo88CQ67PJafPAixEVRDMWZNVXIlzxBF19ZtCYu/IjpDA=@dpdk.org X-Gm-Message-State: AOJu0YyAKCt3ZlbGBljyw6kcTW2tUQ7RZTfVtVqieq+GVTHT6Nw9B8AW VyrRwpv7jf8wtuDHlpRHEeuphCxiQt2pNA+i4ONFzrmkTwfzFYS6AAegoY/CP6WAhH4L2nM+hLu XeIo2OYq4o3wbiBsfWOr5g67/iFQPy72NdvatPTAx7GnDE9EeO0QrzA6u5Rf1ebq8KQnZXuel7r /Ey6w5 X-Google-Smtp-Source: AGHT+IFzsoP1eAog0pjtfOBT7CfQNij3GI4KM2DhaaD042CzRsnreMjybmXY/5ouMltZtZN7UcOarrmYGQ5VRsknuB8= X-Received: by 2002:a05:6512:1321:b0:52e:9b92:4990 with SMTP id 2adb3069b0e04-53546b42590mr10884077e87.32.1725417821202; Tue, 03 Sep 2024 19:43:41 -0700 (PDT) MIME-Version: 1.0 References: <20240708232351.491529-1-damodharam.ammepalli@broadcom.com> <3577879f-4652-4633-8ea8-badd36aaeb8a@amd.com> <17127642-49bf-409f-98ff-0059720ec9ec@amd.com> In-Reply-To: <17127642-49bf-409f-98ff-0059720ec9ec@amd.com> From: Damodharam Ammepalli Date: Tue, 3 Sep 2024 19:43:28 -0700 Message-ID: Subject: Re: [PATCH v4] ethdev: Add link_speed lanes support To: Ferruh Yigit Cc: ajit.khaparde@broadcom.com, dev@dpdk.org, huangdengdui@huawei.com, kalesh-anakkur.purayil@broadcom.com Content-Type: multipart/signed; protocol="application/pkcs7-signature"; micalg=sha-256; boundary="0000000000005cf825062142246f" 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 --0000000000005cf825062142246f Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable On Wed, Jul 10, 2024 at 2:06=E2=80=AFAM Ferruh Yigit = wrote: > > On 7/9/2024 10:20 PM, Damodharam Ammepalli wrote: > > On Tue, Jul 9, 2024 at 4:10=E2=80=AFAM Ferruh Yigit wrote: > >> > >> On 7/9/2024 12:22 AM, Damodharam Ammepalli wrote: > >>> Update the eth_dev_ops structure with new function vectors > >>> to get, get capabilities and set ethernet link speed lanes. > >>> Update the testpmd to provide required config and information > >>> display infrastructure. > >>> > >>> The supporting ethernet controller driver will register callbacks > >>> to avail link speed lanes config and get services. This lanes > >>> configuration is applicable only when the nic is forced to fixed > >>> speeds. In Autonegiation mode, the hardware automatically > >>> negotiates the number of lanes. > >>> > >>> These are the new commands. > >>> > >>> testpmd> show port 0 speed_lanes capabilities > >>> > >>> Supported speeds Valid lanes > >>> ----------------------------------- > >>> 10 Gbps 1 > >>> 25 Gbps 1 > >>> 40 Gbps 4 > >>> 50 Gbps 1 2 > >>> 100 Gbps 1 2 4 > >>> 200 Gbps 2 4 > >>> 400 Gbps 4 8 > >>> testpmd> > >>> > >>> testpmd> > >>> testpmd> port stop 0 > >>> testpmd> port config 0 speed_lanes 4 > >>> testpmd> port config 0 speed 200000 duplex full > >>> > >> > >> Is there a requirement to set speed before speed_lane? > >> Because I expect driver will verify if a speed_lane value is valid or > >> not for a specific speed value. In above usage, driver will verify bas= ed > >> on existing speed, whatever it is, later chaning speed may cause inval= id > >> speed_lane configuration. > >> > >> > > There is no requirement to set speed before speed_lane. > > If the controller supports lanes configuration capability, if no lanes > > are given (which is 0) > > the driver will pick up the lowest speed (eg: 200 gbps with NRZ mode), > > if a fixed speed > > already exists or is configured in tandem with speed_lanes. If speed > > is already Auto, > > test-pmd's speed_lane config is ignored. > > > > We don't see your driver code yet, so it is hard to know the intention, > but for your case will it work if first speed is set, later lane is set? > (Btw, in the context of lanes, I am always assuming it is fixed speed > configuration.) > Ack. Follow up series will carry the patches. > Assume that default speed is 10G, when speed_lane is set first, is it > expected that driver verify the lane for that speed? If so, perhaps that > specific lane config is not valid for the default speed and fails to > set, do you think is this a valid case? > No, Let me take 100G as an example which has lanes capability. If the link is Auto Negotiated, the driver will ignore the user's lane configuration. Lane configuration will only be applied if the existing linked up speed(eg: 100G) is a fixed speed. Driver will check the lane's validity and reject it if it doesn't match the speed's capability. > Overall, the issue I am trying to clarify is the reason why Dengdui went > with having different desing to couple speed and lanes. We said we will > go with this separated design, but lets clarify relation/order in user > perspective, since this is something that impacts driver implementation. > And not clarifying this enough for sure will cause confusion and > inconsistency in different driver implemntations. > Ack. Since the port is stopped, order of configuration does not matter. Once the port is started, the driver will pick up up test pmds lanes and sp= eed configuration and re-configures the phy in one shot. The recommended steps are to stop the port, configure a fixed speed and lane count. > >>> testpmd> port start 0 > >>> testpmd> > >>> testpmd> show port info 0 > >>> > >>> ********************* Infos for port 0 ********************* > >>> MAC address: 14:23:F2:C3:BA:D2 > >>> Device name: 0000:b1:00.0 > >>> Driver name: net_bnxt > >>> Firmware-version: 228.9.115.0 > >>> Connect to socket: 2 > >>> memory allocation on the socket: 2 > >>> Link status: up > >>> Link speed: 200 Gbps > >>> Active Lanes: 4 > >>> Link duplex: full-duplex > >>> Autoneg status: Off > >>> > >>> Signed-off-by: Damodharam Ammepalli > >>> --- > >>> v2->v3 Consolidating the testpmd and rtelib patches into a single pat= ch > >>> as requested. > >>> v3->v4 Addressed comments and fix help string and documentation. > >>> > >>> app/test-pmd/cmdline.c | 230 +++++++++++++++++++++++++++++++++++= ++ > >>> app/test-pmd/config.c | 69 ++++++++++- > >>> app/test-pmd/testpmd.h | 4 + > >>> lib/ethdev/ethdev_driver.h | 77 +++++++++++++ > >>> lib/ethdev/rte_ethdev.c | 51 ++++++++ > >>> lib/ethdev/rte_ethdev.h | 92 +++++++++++++++ > >>> lib/ethdev/version.map | 5 + > >>> 7 files changed, 526 insertions(+), 2 deletions(-) > >>> > >>> diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c > >>> index b7759e38a8..a507df31d8 100644 > >>> --- a/app/test-pmd/cmdline.c > >>> +++ b/app/test-pmd/cmdline.c > >>> @@ -284,6 +284,9 @@ static void cmd_help_long_parsed(void *parsed_res= ult, > >>> > >>> "dump_log_types\n" > >>> " Dumps the log level for all the dpdk modul= es\n\n" > >>> + > >>> + "show port (port_id) speed_lanes capabilities" > >>> + " Show speed lanes capabilities of a port= .\n\n" > >>> ); > >>> } > >>> > >>> @@ -823,6 +826,9 @@ static void cmd_help_long_parsed(void *parsed_res= ult, > >>> "port config (port_id) txq (queue_id) affinity = (value)\n" > >>> " Map a Tx queue with an aggregated port " > >>> "of the DPDK port\n\n" > >>> + > >>> + "port config (port_id|all) speed_lanes (0|1|4|8= )\n" > >>> + " Set number of lanes for all ports or port_= id for a forced speed\n\n" > >>> ); > >>> } > >>> > >>> @@ -1560,6 +1566,110 @@ static cmdline_parse_inst_t cmd_config_speed_= specific =3D { > >>> }, > >>> }; > >>> > >>> +static int > >>> +parse_speed_lanes_cfg(portid_t pid, uint32_t lanes) > >>> +{ > >>> + int ret; > >>> + uint32_t lanes_capa; > >>> + > >>> + ret =3D parse_speed_lanes(lanes, &lanes_capa); > >>> + if (ret < 0) { > >>> + fprintf(stderr, "Unknown speed lane value: %d for port = %d\n", lanes, pid); > >>> + return -1; > >>> + } > >>> + > >>> + ret =3D rte_eth_speed_lanes_set(pid, lanes_capa); > >>> + if (ret =3D=3D -ENOTSUP) { > >>> + fprintf(stderr, "Function not implemented\n"); > >>> + return -1; > >>> + } else if (ret < 0) { > >>> + fprintf(stderr, "Set speed lanes failed\n"); > >>> + return -1; > >>> + } > >>> + > >>> + return 0; > >>> +} > >>> + > >>> +/* *** display speed lanes per port capabilities *** */ > >>> +struct cmd_show_speed_lanes_result { > >>> + cmdline_fixed_string_t cmd_show; > >>> + cmdline_fixed_string_t cmd_port; > >>> + cmdline_fixed_string_t cmd_keyword; > >>> + portid_t cmd_pid; > >>> +}; > >>> + > >>> +static void > >>> +cmd_show_speed_lanes_parsed(void *parsed_result, > >>> + __rte_unused struct cmdline *cl, > >>> + __rte_unused void *data) > >>> +{ > >>> + struct cmd_show_speed_lanes_result *res =3D parsed_result; > >>> + struct rte_eth_speed_lanes_capa *speed_lanes_capa; > >>> + unsigned int num; > >>> + int ret; > >>> + > >>> + if (!rte_eth_dev_is_valid_port(res->cmd_pid)) { > >>> + fprintf(stderr, "Invalid port id %u\n", res->cmd_pid); > >>> + return; > >>> + } > >>> + > >>> + ret =3D rte_eth_speed_lanes_get_capability(res->cmd_pid, NULL, = 0); > >>> + if (ret =3D=3D -ENOTSUP) { > >>> + fprintf(stderr, "Function not implemented\n"); > >>> + return; > >>> + } else if (ret < 0) { > >>> + fprintf(stderr, "Get speed lanes capability failed: %d\= n", ret); > >>> + return; > >>> + } > >>> + > >>> + num =3D (unsigned int)ret; > >>> + speed_lanes_capa =3D calloc(num, sizeof(*speed_lanes_capa)); > >>> + if (speed_lanes_capa =3D=3D NULL) { > >>> + fprintf(stderr, "Failed to alloc speed lanes capability= buffer\n"); > >>> + return; > >>> + } > >>> + > >>> + ret =3D rte_eth_speed_lanes_get_capability(res->cmd_pid, speed_= lanes_capa, num); > >>> + if (ret < 0) { > >>> + fprintf(stderr, "Error getting speed lanes capability: = %d\n", ret); > >>> + goto out; > >>> + } > >>> + > >>> + show_speed_lanes_capability(num, speed_lanes_capa); > >>> +out: > >>> + free(speed_lanes_capa); > >>> +} > >>> + > >>> +static cmdline_parse_token_string_t cmd_show_speed_lanes_show =3D > >>> + TOKEN_STRING_INITIALIZER(struct cmd_show_speed_lanes_result, > >>> + cmd_show, "show"); > >>> +static cmdline_parse_token_string_t cmd_show_speed_lanes_port =3D > >>> + TOKEN_STRING_INITIALIZER(struct cmd_show_speed_lanes_result, > >>> + cmd_port, "port"); > >>> +static cmdline_parse_token_num_t cmd_show_speed_lanes_pid =3D > >>> + TOKEN_NUM_INITIALIZER(struct cmd_show_speed_lanes_result, > >>> + cmd_pid, RTE_UINT16); > >>> +static cmdline_parse_token_string_t cmd_show_speed_lanes_keyword =3D > >>> + TOKEN_STRING_INITIALIZER(struct cmd_show_speed_lanes_result, > >>> + cmd_keyword, "speed_lanes"); > >>> +static cmdline_parse_token_string_t cmd_show_speed_lanes_cap_keyword= =3D > >>> + TOKEN_STRING_INITIALIZER(struct cmd_show_speed_lanes_result, > >>> + cmd_keyword, "capabilities"); > >>> + > >>> +static cmdline_parse_inst_t cmd_show_speed_lanes =3D { > >>> + .f =3D cmd_show_speed_lanes_parsed, > >>> + .data =3D NULL, > >>> + .help_str =3D "show port speed_lanes capabilities", > >>> + .tokens =3D { > >>> + (void *)&cmd_show_speed_lanes_show, > >>> + (void *)&cmd_show_speed_lanes_port, > >>> + (void *)&cmd_show_speed_lanes_pid, > >>> + (void *)&cmd_show_speed_lanes_keyword, > >>> + (void *)&cmd_show_speed_lanes_cap_keyword, > >>> + NULL, > >>> + }, > >>> +}; > >>> + > >>> /* *** configure loopback for all ports *** */ > >>> struct cmd_config_loopback_all { > >>> cmdline_fixed_string_t port; > >>> @@ -1676,6 +1786,123 @@ static cmdline_parse_inst_t cmd_config_loopba= ck_specific =3D { > >>> }, > >>> }; > >>> > >>> +/* *** configure speed_lanes for all ports *** */ > >>> +struct cmd_config_speed_lanes_all { > >>> + cmdline_fixed_string_t port; > >>> + cmdline_fixed_string_t keyword; > >>> + cmdline_fixed_string_t all; > >>> + cmdline_fixed_string_t item; > >>> + uint32_t lanes; > >>> +}; > >>> + > >>> +static void > >>> +cmd_config_speed_lanes_all_parsed(void *parsed_result, > >>> + __rte_unused struct cmdline *cl, > >>> + __rte_unused void *data) > >>> +{ > >>> + struct cmd_config_speed_lanes_all *res =3D parsed_result; > >>> + portid_t pid; > >>> + > >>> + if (!all_ports_stopped()) { > >>> + fprintf(stderr, "Please stop all ports first\n"); > >>> + return; > >>> + } > >>> + > >>> + RTE_ETH_FOREACH_DEV(pid) { > >>> + if (parse_speed_lanes_cfg(pid, res->lanes)) > >>> + return; > >>> + } > >>> + > >>> + cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1); > >>> +} > >>> + > >>> +static cmdline_parse_token_string_t cmd_config_speed_lanes_all_port = =3D > >>> + TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_all, por= t, "port"); > >>> +static cmdline_parse_token_string_t cmd_config_speed_lanes_all_keywo= rd =3D > >>> + TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_all, key= word, > >>> + "config"); > >>> +static cmdline_parse_token_string_t cmd_config_speed_lanes_all_all = =3D > >>> + TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_all, all= , "all"); > >>> +static cmdline_parse_token_string_t cmd_config_speed_lanes_all_item = =3D > >>> + TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_all, ite= m, > >>> + "speed_lanes"); > >>> +static cmdline_parse_token_num_t cmd_config_speed_lanes_all_lanes = =3D > >>> + TOKEN_NUM_INITIALIZER(struct cmd_config_speed_lanes_all, lanes,= RTE_UINT32); > >>> + > >>> +static cmdline_parse_inst_t cmd_config_speed_lanes_all =3D { > >>> + .f =3D cmd_config_speed_lanes_all_parsed, > >>> + .data =3D NULL, > >>> + .help_str =3D "port config all speed_lanes ", > >>> + .tokens =3D { > >>> + (void *)&cmd_config_speed_lanes_all_port, > >>> + (void *)&cmd_config_speed_lanes_all_keyword, > >>> + (void *)&cmd_config_speed_lanes_all_all, > >>> + (void *)&cmd_config_speed_lanes_all_item, > >>> + (void *)&cmd_config_speed_lanes_all_lanes, > >>> + NULL, > >>> + }, > >>> +}; > >>> + > >>> +/* *** configure speed_lanes for specific port *** */ > >>> +struct cmd_config_speed_lanes_specific { > >>> + cmdline_fixed_string_t port; > >>> + cmdline_fixed_string_t keyword; > >>> + uint16_t port_id; > >>> + cmdline_fixed_string_t item; > >>> + uint32_t lanes; > >>> +}; > >>> + > >>> +static void > >>> +cmd_config_speed_lanes_specific_parsed(void *parsed_result, > >>> + __rte_unused struct cmdline *cl, > >>> + __rte_unused void *data) > >>> +{ > >>> + struct cmd_config_speed_lanes_specific *res =3D parsed_result; > >>> + > >>> + if (port_id_is_invalid(res->port_id, ENABLED_WARN)) > >>> + return; > >>> + > >>> + if (!port_is_stopped(res->port_id)) { > >>> + fprintf(stderr, "Please stop port %u first\n", res->por= t_id); > >>> + return; > >>> + } > >>> > >> > >> There is a requirement here, that port needs to be stopped before > >> calling the rte_eth_speed_lanes_set(), > >> is this requirement documented in the API documentation? > >> > >> > > Speed link mode needs a phy reset, hence port stop is a requirement. > > I will update this in the documentation in the next patch. > > > > That is OK to have the stop requirement, only it needs to be clear. > And addition to document this in the API documentation, what do you > think to add this check in the API, so it guarantees in coding level > that this requirement is satified. > So this check in application level can be dropped. > Ack. updated the relevant comments section and also added check in the func= tion. > >>> + > >>> + if (parse_speed_lanes_cfg(res->port_id, res->lanes)) > >>> + return; > >>> + > >>> + cmd_reconfig_device_queue(res->port_id, 1, 1); > >>> +} > >>> + > >>> +static cmdline_parse_token_string_t cmd_config_speed_lanes_specific_= port =3D > >>> + TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_specific= , port, > >>> + "port"); > >>> +static cmdline_parse_token_string_t cmd_config_speed_lanes_specific_= keyword =3D > >>> + TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_specific= , keyword, > >>> + "config"); > >>> +static cmdline_parse_token_num_t cmd_config_speed_lanes_specific_id = =3D > >>> + TOKEN_NUM_INITIALIZER(struct cmd_config_speed_lanes_specific, p= ort_id, > >>> + RTE_UINT16); > >>> +static cmdline_parse_token_string_t cmd_config_speed_lanes_specific_= item =3D > >>> + TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_specific= , item, > >>> + "speed_lanes"); > >>> +static cmdline_parse_token_num_t cmd_config_speed_lanes_specific_lan= es =3D > >>> + TOKEN_NUM_INITIALIZER(struct cmd_config_speed_lanes_specific, l= anes, > >>> + RTE_UINT32); > >>> + > >>> +static cmdline_parse_inst_t cmd_config_speed_lanes_specific =3D { > >>> + .f =3D cmd_config_speed_lanes_specific_parsed, > >>> + .data =3D NULL, > >>> + .help_str =3D "port config speed_lanes ", > >>> + .tokens =3D { > >>> + (void *)&cmd_config_speed_lanes_specific_port, > >>> + (void *)&cmd_config_speed_lanes_specific_keyword, > >>> + (void *)&cmd_config_speed_lanes_specific_id, > >>> + (void *)&cmd_config_speed_lanes_specific_item, > >>> + (void *)&cmd_config_speed_lanes_specific_lanes, > >>> + NULL, > >>> + }, > >>> +}; > >>> + > >>> /* *** configure txq/rxq, txd/rxd *** */ > >>> struct cmd_config_rx_tx { > >>> cmdline_fixed_string_t port; > >>> @@ -13238,6 +13465,9 @@ static cmdline_parse_ctx_t builtin_ctx[] =3D = { > >>> (cmdline_parse_inst_t *)&cmd_set_port_setup_on, > >>> (cmdline_parse_inst_t *)&cmd_config_speed_all, > >>> (cmdline_parse_inst_t *)&cmd_config_speed_specific, > >>> + (cmdline_parse_inst_t *)&cmd_config_speed_lanes_all, > >>> + (cmdline_parse_inst_t *)&cmd_config_speed_lanes_specific, > >>> + (cmdline_parse_inst_t *)&cmd_show_speed_lanes, > >>> (cmdline_parse_inst_t *)&cmd_config_loopback_all, > >>> (cmdline_parse_inst_t *)&cmd_config_loopback_specific, > >>> (cmdline_parse_inst_t *)&cmd_config_rx_tx, > >>> diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c > >>> index 66c3a68c1d..498a7db467 100644 > >>> --- a/app/test-pmd/config.c > >>> +++ b/app/test-pmd/config.c > >>> @@ -207,6 +207,32 @@ static const struct { > >>> {"gtpu", RTE_ETH_FLOW_GTPU}, > >>> }; > >>> > >>> +static const struct { > >>> + enum rte_eth_speed_lanes lane; > >>> + const uint32_t value; > >>> +} speed_lane_name[] =3D { > >>> + { > >>> + .lane =3D RTE_ETH_SPEED_LANE_UNKNOWN, > >>> + .value =3D 0, > >>> + }, > >>> + { > >>> + .lane =3D RTE_ETH_SPEED_LANE_1, > >>> + .value =3D 1, > >>> + }, > >>> + { > >>> + .lane =3D RTE_ETH_SPEED_LANE_2, > >>> + .value =3D 2, > >>> + }, > >>> + { > >>> + .lane =3D RTE_ETH_SPEED_LANE_4, > >>> + .value =3D 4, > >>> + }, > >>> + { > >>> + .lane =3D RTE_ETH_SPEED_LANE_8, > >>> + .value =3D 8, > >>> + }, > >>> +}; > >>> + > >>> static void > >>> print_ethaddr(const char *name, struct rte_ether_addr *eth_addr) > >>> { > >>> @@ -786,6 +812,7 @@ port_infos_display(portid_t port_id) > >>> char name[RTE_ETH_NAME_MAX_LEN]; > >>> int ret; > >>> char fw_version[ETHDEV_FWVERS_LEN]; > >>> + uint32_t lanes; > >>> > >>> if (port_id_is_invalid(port_id, ENABLED_WARN)) { > >>> print_valid_ports(); > >>> @@ -828,6 +855,12 @@ port_infos_display(portid_t port_id) > >>> > >>> printf("\nLink status: %s\n", (link.link_status) ? ("up") : ("d= own")); > >>> printf("Link speed: %s\n", rte_eth_link_speed_to_str(link.link_= speed)); > >>> + if (rte_eth_speed_lanes_get(port_id, &lanes) =3D=3D 0) { > >>> + if (lanes > 0) > >>> + printf("Active Lanes: %d\n", lanes); > >>> + else > >>> + printf("Active Lanes: %s\n", "Unknown"); > >>> > >> > >> What can be the 'else' case? > >> As 'lanes' is unsigned, only option is it being zero. Is API allowed t= o > >> return zero as lane number? > >> Ack, in the ensuing patch, removing the else case since as per your next comment, driver returns either error code or 0, with lanes count > 0. > >> > > Yes. link is down, but controller supports speed_lanes capability, > > then we can show "unknown" > > Other cases from brcm spec. > > 1gb 1Gb link speed < no lane info > (theoretically it can't be zero, > > but we need to show what controller provides in the query). > > 10Gb (NRZ: 10G per lane, 1 lane) link speed > > > > I don't understand how application proccess the information that > 'rte_eth_speed_lanes_get()' returns success but lane is zero. > Ack. Answered in the next comment. > For the link down case, doesn't it make sense to return error for the > 'rte_eth_speed_lanes_get()' API? > Ack. > And for other cases, like 1G that doesn't support the lane > configuration, does it make sense to return 1? > And for these cases what is the capability value you are returning? > Ack. For speeds like 1G, checking with firmware engineers confirmed, a lane= =3D 1 would be appropriate and the driver will always return lanes > 0. > > >>> + } > >>> printf("Link duplex: %s\n", (link.link_duplex =3D=3D RTE_ETH_LI= NK_FULL_DUPLEX) ? > >>> ("full-duplex") : ("half-duplex")); > >>> printf("Autoneg status: %s\n", (link.link_autoneg =3D=3D RTE_ET= H_LINK_AUTONEG) ? > >>> @@ -962,7 +995,7 @@ port_summary_header_display(void) > >>> > >>> port_number =3D rte_eth_dev_count_avail(); > >>> printf("Number of available ports: %i\n", port_number); > >>> - printf("%-4s %-17s %-12s %-14s %-8s %s\n", "Port", "MAC Address= ", "Name", > >>> + printf("%-4s %-17s %-12s %-14s %-8s %-8s\n", "Port", "MAC Addre= ss", "Name", > >>> "Driver", "Status", "Link"); > >>> } > >>> > >>> @@ -993,7 +1026,7 @@ port_summary_display(portid_t port_id) > >>> if (ret !=3D 0) > >>> return; > >>> > >>> - printf("%-4d " RTE_ETHER_ADDR_PRT_FMT " %-12s %-14s %-8s %s\n", > >>> + printf("%-4d " RTE_ETHER_ADDR_PRT_FMT " %-12s %-14s %-8s %-8s\n= ", > >>> > >> > >> Summary updates are irrelevant in the patch, can you please drop them. > >> > >> > > Sure I will. > > > >>> port_id, RTE_ETHER_ADDR_BYTES(&mac_addr), name, > >>> dev_info.driver_name, (link.link_status) ? ("up") : ("d= own"), > >>> rte_eth_link_speed_to_str(link.link_speed)); > >>> @@ -7244,3 +7277,35 @@ show_mcast_macs(portid_t port_id) > >>> printf(" %s\n", buf); > >>> } > >>> } > >>> + > >>> +int > >>> +parse_speed_lanes(uint32_t lane, uint32_t *speed_lane) > >>> +{ > >>> + uint8_t i; > >>> + > >>> + for (i =3D 0; i < RTE_DIM(speed_lane_name); i++) { > >>> + if (speed_lane_name[i].value =3D=3D lane) { > >>> + *speed_lane =3D lane; > >>> > >> > >> This converts from 8 -> 8, 4 -> 4 .... > >> > >> Why not completely eliminate this fucntion? See below. > >> > > Sure, will evaluate and do the needful. > > > >>> + return 0; > >>> + } > >>> + } > >>> + return -1; > >>> +} > >>> + > >>> +void > >>> +show_speed_lanes_capability(unsigned int num, struct rte_eth_speed_l= anes_capa *speed_lanes_capa) > >>> +{ > >>> + unsigned int i, j; > >>> + > >>> + printf("\n%-15s %-10s", "Supported-speeds", "Valid-lanes"); > >>> + printf("\n-----------------------------------\n"); > >>> + for (i =3D 0; i < num; i++) { > >>> + printf("%-17s ", rte_eth_link_speed_to_str(speed_lanes_= capa[i].speed)); > >>> + > >>> + for (j =3D 0; j < RTE_ETH_SPEED_LANE_MAX; j++) { > >>> + if (RTE_ETH_SPEED_LANES_TO_CAPA(j) & speed_lane= s_capa[i].capa) > >>> + printf("%-2d ", speed_lane_name[j].valu= e); > >>> + } > >> > >> To eliminate both RTE_ETH_SPEED_LANE_MAX & speed_lane_name, what do yo= u > >> think about: > >> > >> capa =3D speed_lanes_capa[i].capa; > >> int s =3D 0; > >> while (capa) { > >> if (capa & 0x1) > >> printf("%-2d ", 1 << s); > >> s++; > >> capa =3D capa >> 1; > >> } > >> > > Am new to the DPDK world. > > Followed the FEC driver conventions for consistency. > > Will update it as you suggested and it makes sense. > > > > FEC values goes sequential, but lane values in power of two, we can > benefit from this fact. (though if we have lane value not power of two > later, this logic may need to change.) > > Btw, I can see some of the code copies existing FEC implementation, > which makes sense, but it seems FEC code could be improved as well but > we missed at that time. > Instead of copying FEC exactly, lets try to improve whatever we can for > first merge, otherwise less likely these things will be fixed later. > Ack. Follow up patch will have comments addressed. Thanks for the review and sorry for the delay, as other priorities took the front seat. > Thanks, > ferruh --=20 This electronic communication and the information and any files transmitted= =20 with it, or attached to it, are confidential and are intended solely for=20 the use of the individual or entity to whom it is addressed and may contain= =20 information that is confidential, legally privileged, protected by privacy= =20 laws, or otherwise restricted from disclosure to anyone else. If you are=20 not the intended recipient or the person responsible for delivering the=20 e-mail to the intended recipient, you are hereby notified that any use,=20 copying, distributing, dissemination, forwarding, printing, or copying of= =20 this e-mail is strictly prohibited. If you received this e-mail in error,= =20 please return the e-mail to the sender, delete it from your computer, and= =20 destroy any printed copy of it. --0000000000005cf825062142246f Content-Type: application/pkcs7-signature; name="smime.p7s" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="smime.p7s" Content-Description: S/MIME Cryptographic Signature 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 tJVewHuOmXgWQxNWV7Oiszu1d9xAcqyj65s1PrEIIaHnxEM3eTK+teecLEy8QymZjjDTrCHg4x36 2AczdlQAIiq5TSAucGja5VP8g1zTnfL/RAxEZvLS471GABptArolXY2hMVHdVEYcTduZlu8aHARc phXveOB5/l3bPqpMVf2aFalv4ab733Aw6cPuQkbtwpMFifp9Y3s/0HGBfADomK4OeDTDJfuvCp8g a907E48SjOJBGkh6c6B3ace2XH+CyB7+WBsoK6hsrV5twAXSe7frgP4lN/4Cm2isQl3D7vXM3PBQ ddI2aZzmewTfbgZptt4KCUhZh+t7FGB6ZKppQ++Rx0zsGN1s71MtjJnhXvJyPs9UyL1n7KQPTEX/ 07kwIwdMjxC/hpbZmVq0mVccpMy7FYlTuiwFD+TEnhmxGDTVTJ267fcfrySVBHioA7vugeXaX3yL SqGQdCWnsz5LyCxWvcfI7zjiXJLwefechLp0LWEBIH5+0fJPB1lfiy1DUutGDJTh9WZHeXfVVFsf rSQ3y0VaTqBESMjYsJnFFYQJ9tZJScBluOYacW6gqPGC6EU+bNYC1wpngwVayaQQMIIGdjCCBF6g AwIBAgIMLn8lLzdNn3iuIRSnMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNVBAYTAkJFMRkwFwYDVQQK ExBHbG9iYWxTaWduIG52LXNhMSgwJgYDVQQDEx9HbG9iYWxTaWduIEdDQyBSNiBTTUlNRSBDQSAy MDIzMB4XDTI0MDgxNTEwMzAxMVoXDTI2MDgxNjEwMzAxMVowgbkxCzAJBgNVBAYTAlVTMRMwEQYD VQQIEwpDYWxpZm9ybmlhMREwDwYDVQQHEwhTYW4gSm9zZTEZMBcGA1UEYRMQTlRSVVMrREUtNjYx MDExNzEWMBQGA1UEChMNQlJPQURDT00gSU5DLjEdMBsGA1UEAxMURGFtb2RoYXJhbSBBbW1lcGFs bGkxMDAuBgkqhkiG9w0BCQEWIWRhbW9kaGFyYW0uYW1tZXBhbGxpQGJyb2FkY29tLmNvbTCCASIw DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKTOTiEM9VXocEeEqNwSSCInX6pzIDka9Ux5oY37 MzNBjrka0eveof2NigzPwsVrOLiIxbdWAGwTg0Y8CJGLhW2oeaAMvR4DRiNKoVkAlq87iA+0Lt+b UlOWZ9GhhdGiyoKgyiVXVoHNE+qaCdiA7jSt2IiKNwtbrJ5ORhhVJhVO7TUWSA+eHhxxX6YVobyW h8I72UXTTrWfZrpyVpnzcjRD46GJDB0p0KU/2mY7wE2nUvT20sCt1G9JQTq8fr+CHG4DXJj3HFyr xucep3rDhxi6mbVTlXY3GuQSPWjJ5b/MtvWL3b02wY85/WEzAw5yP1QoxWyfCvS9C4+QlRgMwVcC AwEAAaOCAeIwggHeMA4GA1UdDwEB/wQEAwIFoDCBkwYIKwYBBQUHAQEEgYYwgYMwRgYIKwYBBQUH MAKGOmh0dHA6Ly9zZWN1cmUuZ2xvYmFsc2lnbi5jb20vY2FjZXJ0L2dzZ2NjcjZzbWltZWNhMjAy My5jcnQwOQYIKwYBBQUHMAGGLWh0dHA6Ly9vY3NwLmdsb2JhbHNpZ24uY29tL2dzZ2NjcjZzbWlt ZWNhMjAyMzBlBgNVHSAEXjBcMAkGB2eBDAEFAwEwCwYJKwYBBAGgMgEoMEIGCisGAQQBoDIKAwIw NDAyBggrBgEFBQcCARYmaHR0cHM6Ly93d3cuZ2xvYmFsc2lnbi5jb20vcmVwb3NpdG9yeS8wCQYD VR0TBAIwADBBBgNVHR8EOjA4MDagNKAyhjBodHRwOi8vY3JsLmdsb2JhbHNpZ24uY29tL2dzZ2Nj cjZzbWltZWNhMjAyMy5jcmwwLAYDVR0RBCUwI4EhZGFtb2RoYXJhbS5hbW1lcGFsbGlAYnJvYWRj b20uY29tMBMGA1UdJQQMMAoGCCsGAQUFBwMEMB8GA1UdIwQYMBaAFAApNp5ceroPry1QLdugI4UY sKCSMB0GA1UdDgQWBBQPTiO195ramjDswK3B4QGsKDTPRjANBgkqhkiG9w0BAQsFAAOCAgEAk/bL jIfng3rwfvQM0w6iGYjLlBQUSPgjuJMjshP/aADrjnHhcxKKImHh8mmWGxMHY4POjHmYAIbQrFHi yG8aVI2kLKc3/0zJOKqGqx7NvyKmwerKKELVOMdDBXEnXExqAMOj3rYACeJhZqYwqGaK1BcLvTgo hbrXTFXUvlU12mx0OHcc0GGEQu90+qFwFFPiGcJiHu0pAMH0d2e83iNeJ3ply+KhDxw5Wc/pqAEy XOcuERQuTAGZH1NY+UVFxxIrr6pvquPAABXaXGU3QG36jWtGPPSjL+1Qf2Jmb3KKm0h4BAHRka1c KfrM/0EF+/7YszLeeA7o2bpqhcahprLZUuiy7dgCRQs9b8wN+kJBpV2Ql7bBDj5Cm0avWUtGxjkR LxqSIHo8rccZJskrJx004QmEwKVnkChGRxZ8LrhNKLy8ikzmrxpA2eK7cPyGewmFKhxBoGDsGCfy CMVthgjbMyh2cVbo7cIXrnx8rf7q9S0aAPt9yHX4+GtXPw44iTsJmD/EOmwX2QLPjjdBKbSgi55S nUnMFar9lAhGDw826s0j4dQooqLC1BX/jGH1VapU8AGfGAWbsGhBG74yjHfRC74KkFuOj2ORU+9f ueOdPBxQH3SIl77cHdNp3NWTwFAdBKpdDLMyGf79t5bgpNRYDZ/szNAxW6aH6PhnUMBtD0gxggJk MIICYAIBATBiMFIxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMSgwJgYD VQQDEx9HbG9iYWxTaWduIEdDQyBSNiBTTUlNRSBDQSAyMDIzAgwufyUvN02feK4hFKcwDQYJYIZI AWUDBAIBBQCggdQwLwYJKoZIhvcNAQkEMSIEILRaaEPkOFZjMG5fgi6qynH3vsNxTUeOOTPFoDna AfxbMBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTI0MDkwNDAyNDM0 MVowaQYJKoZIhvcNAQkPMVwwWjALBglghkgBZQMEASowCwYJYIZIAWUDBAEWMAsGCWCGSAFlAwQB AjAKBggqhkiG9w0DBzALBgkqhkiG9w0BAQowCwYJKoZIhvcNAQEHMAsGCWCGSAFlAwQCATANBgkq hkiG9w0BAQEFAASCAQAldI+/V0VH9K4OIkRsv++1ssUmpo+MQupd2M0li+t/uKgPZQAZ9Gc3n4BI jzUK3Jh5Z2eqQrgmqlpnwmEeEf3Vvobb0bIyFSgzBpLrEKRKl6BFqG52RgFYY5oki5myqqt7rTcv I4/aup6ud61r91ld3v5CN8/fMSdTxu9MuhKUvk96hkG7W4J1lsi6wQ4LPckunPxiG6yQcF7UlnX3 miZg7BvgYdEUE/XoX5CeRsH7VAB+vLKbUz2Lese9RaG41rQZBmwxmwsN48JldX3FV6OItn5sK5rO +ZHzS6JiDPmV6VYnQimi0aNvCWDGOrFcIYWvVLm/LMHfbcuZJ89jdt/G --0000000000005cf825062142246f--