From patchwork Sat Mar 26 01:27:18 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marc Sune X-Patchwork-Id: 11757 Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [IPv6:::1]) by dpdk.org (Postfix) with ESMTP id F39305AB9; Sat, 26 Mar 2016 02:28:29 +0100 (CET) Received: from mail-wm0-f67.google.com (mail-wm0-f67.google.com [74.125.82.67]) by dpdk.org (Postfix) with ESMTP id C46425A9D for ; Sat, 26 Mar 2016 02:28:08 +0100 (CET) Received: by mail-wm0-f67.google.com with SMTP id u125so7234594wmg.0 for ; Fri, 25 Mar 2016 18:28:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=SgUI1ZC9/Z3eaJKZUw7xfaYFj1g20bZRxQQilVHDHIw=; b=iPwDLTrpy4ggMCqJrt8kaoXI28epbN5MwcZ8XwNOnYPVM13itgaV3jFiw56kqZxBy0 jNaU3sHRwRvn4K7QvksDyTBAud6HAs7sHay91WoCqcGfQe/7xUjVXddEPpU8gzA5lUdI P7N5f8XsikIRRDfz7Oe9pnXFzG1ltpJilvc3vLol0oa+EZEoBpEB34/ZYhXhJtnXll+1 EH1vxxGc2eZSC0fVg0JxwTCmLKm/+MWcZIvwWnChAjr6nTe/cbmAefp/zPKk1eUlMJOI DrwENpQXYWCar8vL55T1y0MwmgqktGNQTDNeb24ZSa2g8Dy4pJ7cPjizuKROneRC8Ud2 Y6Cg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=SgUI1ZC9/Z3eaJKZUw7xfaYFj1g20bZRxQQilVHDHIw=; b=WuGk8n9LDWACK6ZuXXos+QtY8M9Hh3gvPfD+xWFN8EFrX76AFu38VpbzcPJ1/6fwuy +4crOxXRb3Zy40JRU6kr+xVzZxqbOjYt+KuCtace/fZ37+gnw8QlnwLev7Pv2fMgQ6tB nPxwwDe0rCrIh3IW2hxjO8FbYTPQds1jKFDmavjHiLL1TirO4zZAZhvFmebYM+e/aK75 JDKW7xB0gspOu4+jljvBorpgFTjQHAGA2wHP4nTrpXCp3XUlJHL5cz2nRkl61UKiHq8a IUpwCj4Dm9kNqHSBHdZRu2VPCSHvoNIErXg4M4O1ED5bAVFoGhlDjtF4pljd6uofqM0E Y4Xg== X-Gm-Message-State: AD7BkJJCTOfbivF5DZWJYikBz7yU0VkPIS8seK4fW9Cc6OkQJgCguJlVvmtnKQQXOJ3JxQ== X-Received: by 10.194.103.198 with SMTP id fy6mr20027109wjb.48.1458955688481; Fri, 25 Mar 2016 18:28:08 -0700 (PDT) Received: from localhost.localdomain (28.red-88-23-79.staticip.rima-tde.net. [88.23.79.28]) by smtp.gmail.com with ESMTPSA id hh8sm14070113wjc.42.2016.03.25.18.28.07 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 25 Mar 2016 18:28:07 -0700 (PDT) From: Marc Sune To: Thomas Monjalon , "Xu, Qian Q" , "Xing, Beilei" , "dev@dpdk.org" , "Ananyev, Konstantin" , "Lu, Wenzhuo" , "Richardson, Bruce" , "Glynn, Michael J" Cc: Marc Sune Date: Sat, 26 Mar 2016 02:27:18 +0100 Message-Id: <1458955640-22951-7-git-send-email-marcdevel@gmail.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1458955640-22951-1-git-send-email-marcdevel@gmail.com> References: <1458934950-23333-1-git-send-email-thomas.monjalon@6wind.com> <1458955640-22951-1-git-send-email-marcdevel@gmail.com> Subject: [dpdk-dev] [PATCH v13 6/8] ethdev: redesign link speed config X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" This patch redesigns the API to set the link speed/s configuration of an ethernet port. Specifically: - it allows to define a set of advertised speeds for auto-negociation. - it allows to disable link auto-negociation (single fixed speed). - default: auto-negociate all supported speeds. A flag autoneg in struct rte_eth_link indicates if link speed was a result of auto-negociation or was fixed by configuration. Signed-off-by: Marc Sune Tested-by: Nelio Laranjeiro Signed-off-by: Thomas Monjalon --- app/test-pmd/cmdline.c | 26 ++++---- doc/guides/rel_notes/deprecation.rst | 3 - doc/guides/rel_notes/release_16_04.rst | 9 +++ drivers/net/af_packet/rte_eth_af_packet.c | 1 + drivers/net/bnx2x/bnx2x_ethdev.c | 4 +- drivers/net/bonding/rte_eth_bond_8023ad.c | 2 +- drivers/net/e1000/em_ethdev.c | 103 +++++++++++++++--------------- drivers/net/e1000/igb_ethdev.c | 95 ++++++++++++++------------- drivers/net/i40e/i40e_ethdev.c | 48 +++++++------- drivers/net/i40e/i40e_ethdev_vf.c | 7 +- drivers/net/ixgbe/ixgbe_ethdev.c | 51 ++++++--------- drivers/net/mlx4/mlx4.c | 2 + drivers/net/mlx5/mlx5_ethdev.c | 2 + drivers/net/mpipe/mpipe_tilegx.c | 2 + drivers/net/null/rte_eth_null.c | 1 + drivers/net/pcap/rte_eth_pcap.c | 1 + drivers/net/ring/rte_eth_ring.c | 1 + drivers/net/szedata2/rte_eth_szedata2.c | 2 + drivers/net/vmxnet3/vmxnet3_ethdev.c | 1 + drivers/net/xenvirt/rte_eth_xenvirt.c | 1 + examples/ip_pipeline/config_parse.c | 3 +- lib/librte_ether/rte_ethdev.h | 29 +++++---- 22 files changed, 207 insertions(+), 187 deletions(-) diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index 815b53b..741cac3 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -989,7 +989,7 @@ struct cmd_config_speed_all { }; static int -parse_and_check_speed_duplex(char *speedstr, char *duplexstr, uint16_t *speed) +parse_and_check_speed_duplex(char *speedstr, char *duplexstr, uint32_t *speed) { int duplex; @@ -1006,20 +1006,22 @@ parse_and_check_speed_duplex(char *speedstr, char *duplexstr, uint16_t *speed) } if (!strcmp(speedstr, "10")) { - *speed = ETH_SPEED_NUM_10M; + *speed = (duplex == ETH_LINK_HALF_DUPLEX) ? + ETH_LINK_SPEED_10M_HD : ETH_LINK_SPEED_10M; } else if (!strcmp(speedstr, "100")) { - *speed = ETH_SPEED_NUM_100M; + *speed = (duplex == ETH_LINK_HALF_DUPLEX) ? + ETH_LINK_SPEED_100M_HD : ETH_LINK_SPEED_100M; } else { if (duplex != ETH_LINK_FULL_DUPLEX) { printf("Invalid speed/duplex parameters\n"); return -1; } if (!strcmp(speedstr, "1000")) { - *speed = ETH_SPEED_NUM_1G; + *speed = ETH_LINK_SPEED_1G; } else if (!strcmp(speedstr, "10000")) { - *speed = ETH_SPEED_NUM_10G; + *speed = ETH_LINK_SPEED_10G; } else if (!strcmp(speedstr, "40000")) { - *speed = ETH_SPEED_NUM_40G; + *speed = ETH_LINK_SPEED_40G; } else if (!strcmp(speedstr, "auto")) { *speed = ETH_LINK_SPEED_AUTONEG; } else { @@ -1037,8 +1039,7 @@ cmd_config_speed_all_parsed(void *parsed_result, __attribute__((unused)) void *data) { struct cmd_config_speed_all *res = parsed_result; - uint16_t link_speed = ETH_LINK_SPEED_AUTONEG; - uint16_t link_duplex = 0; + uint32_t link_speed; portid_t pid; if (!all_ports_stopped()) { @@ -1051,8 +1052,7 @@ cmd_config_speed_all_parsed(void *parsed_result, return; FOREACH_PORT(pid, ports) { - ports[pid].dev_conf.link_speed = link_speed; - ports[pid].dev_conf.link_duplex = link_duplex; + ports[pid].dev_conf.link_speeds = link_speed; } cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1); @@ -1110,8 +1110,7 @@ cmd_config_speed_specific_parsed(void *parsed_result, __attribute__((unused)) void *data) { struct cmd_config_speed_specific *res = parsed_result; - uint16_t link_speed = ETH_LINK_SPEED_AUTONEG; - uint16_t link_duplex = 0; + uint32_t link_speed; if (!all_ports_stopped()) { printf("Please stop all ports first\n"); @@ -1125,8 +1124,7 @@ cmd_config_speed_specific_parsed(void *parsed_result, &link_speed) < 0) return; - ports[res->id].dev_conf.link_speed = link_speed; - ports[res->id].dev_conf.link_duplex = link_duplex; + ports[res->id].dev_conf.link_speeds = link_speed; cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1); } diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst index 179e30f..c47610d 100644 --- a/doc/guides/rel_notes/deprecation.rst +++ b/doc/guides/rel_notes/deprecation.rst @@ -19,9 +19,6 @@ Deprecation Notices ibadcrc, ibadlen, imcasts, fdirmatch, fdirmiss, tx_pause_xon, rx_pause_xon, tx_pause_xoff, rx_pause_xoff -* The ethdev structures rte_eth_link, rte_eth_dev_info and rte_eth_conf - must be updated to support 100G link and to have a cleaner link speed API. - * ABI changes are planned for adding four new flow types. This impacts RTE_ETH_FLOW_MAX. The release 2.2 does not contain these ABI changes, but release 2.3 will. [postponed] diff --git a/doc/guides/rel_notes/release_16_04.rst b/doc/guides/rel_notes/release_16_04.rst index 9e7b0b7..c891a55 100644 --- a/doc/guides/rel_notes/release_16_04.rst +++ b/doc/guides/rel_notes/release_16_04.rst @@ -52,6 +52,12 @@ This section should contain new features added in this release. Sample format: The structure ``rte_eth_dev_info`` has now a ``speed_capa`` bitmap, which allows the application to know the supported speeds of each device. +* **Added bitmap of link speeds to advertise.** + + Allow defining a set of advertised speeds for auto-negotiation, + explicitly disabling link auto-negotiation (single speed) + and full auto-negotiation. + * **Added new poll-mode driver for Amazon Elastic Network Adapters (ENA).** The driver operates variety of ENA adapters through feature negotiation @@ -464,6 +470,9 @@ This section should contain API changes. Sample format: * The ethdev structure ``rte_eth_dev_info`` was changed to support device speed capabilities. +* The ethdev structures ``rte_eth_link`` and ``rte_eth_conf`` were changed to + support the new link API. + * The functions ``rte_eth_dev_udp_tunnel_add`` and ``rte_eth_dev_udp_tunnel_delete`` have been renamed into ``rte_eth_dev_udp_tunnel_port_add`` and ``rte_eth_dev_udp_tunnel_port_delete``. diff --git a/drivers/net/af_packet/rte_eth_af_packet.c b/drivers/net/af_packet/rte_eth_af_packet.c index 641f849..f17bd7e 100644 --- a/drivers/net/af_packet/rte_eth_af_packet.c +++ b/drivers/net/af_packet/rte_eth_af_packet.c @@ -119,6 +119,7 @@ static struct rte_eth_link pmd_link = { .link_speed = ETH_SPEED_NUM_10G, .link_duplex = ETH_LINK_FULL_DUPLEX, .link_status = ETH_LINK_DOWN, + .link_autoneg = ETH_LINK_SPEED_AUTONEG }; static uint16_t diff --git a/drivers/net/bnx2x/bnx2x_ethdev.c b/drivers/net/bnx2x/bnx2x_ethdev.c index 897081f..071b44f 100644 --- a/drivers/net/bnx2x/bnx2x_ethdev.c +++ b/drivers/net/bnx2x/bnx2x_ethdev.c @@ -44,9 +44,9 @@ bnx2x_link_update(struct rte_eth_dev *dev) case DUPLEX_HALF: dev->data->dev_link.link_duplex = ETH_LINK_HALF_DUPLEX; break; - default: - dev->data->dev_link.link_duplex = ETH_LINK_AUTONEG_DUPLEX; } + dev->data->dev_link.link_autoneg = !(dev->data->dev_conf.link_speeds & + ETH_LINK_SPEED_FIXED); dev->data->dev_link.link_status = sc->link_vars.link_up; } diff --git a/drivers/net/bonding/rte_eth_bond_8023ad.c b/drivers/net/bonding/rte_eth_bond_8023ad.c index ac8306f..cca7cc3 100644 --- a/drivers/net/bonding/rte_eth_bond_8023ad.c +++ b/drivers/net/bonding/rte_eth_bond_8023ad.c @@ -708,7 +708,7 @@ link_speed_key(uint16_t speed) { uint16_t key_speed; switch (speed) { - case ETH_LINK_SPEED_AUTONEG: + case ETH_SPEED_NUM_NONE: key_speed = 0x00; break; case ETH_SPEED_NUM_10M: diff --git a/drivers/net/e1000/em_ethdev.c b/drivers/net/e1000/em_ethdev.c index d5f8c7f..9fb59a2 100644 --- a/drivers/net/e1000/em_ethdev.c +++ b/drivers/net/e1000/em_ethdev.c @@ -538,6 +538,9 @@ eth_em_start(struct rte_eth_dev *dev) struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle; int ret, mask; uint32_t intr_vector = 0; + uint32_t *speeds; + int num_speeds; + bool autoneg; PMD_INIT_FUNC_TRACE(); @@ -612,56 +615,46 @@ eth_em_start(struct rte_eth_dev *dev) E1000_WRITE_REG(hw, E1000_ITR, UINT16_MAX); /* Setup link speed and duplex */ - switch (dev->data->dev_conf.link_speed) { - case ETH_LINK_SPEED_AUTONEG: - if (dev->data->dev_conf.link_duplex == ETH_LINK_AUTONEG_DUPLEX) - hw->phy.autoneg_advertised = E1000_ALL_SPEED_DUPLEX; - else if (dev->data->dev_conf.link_duplex == - ETH_LINK_HALF_DUPLEX) - hw->phy.autoneg_advertised = E1000_ALL_HALF_DUPLEX; - else if (dev->data->dev_conf.link_duplex == - ETH_LINK_FULL_DUPLEX) - hw->phy.autoneg_advertised = E1000_ALL_FULL_DUPLEX; - else - goto error_invalid_config; - break; - case ETH_SPEED_NUM_10M: - if (dev->data->dev_conf.link_duplex == ETH_LINK_AUTONEG_DUPLEX) - hw->phy.autoneg_advertised = E1000_ALL_10_SPEED; - else if (dev->data->dev_conf.link_duplex == - ETH_LINK_HALF_DUPLEX) - hw->phy.autoneg_advertised = ADVERTISE_10_HALF; - else if (dev->data->dev_conf.link_duplex == - ETH_LINK_FULL_DUPLEX) - hw->phy.autoneg_advertised = ADVERTISE_10_FULL; - else - goto error_invalid_config; - break; - case ETH_SPEED_NUM_100M: - if (dev->data->dev_conf.link_duplex == ETH_LINK_AUTONEG_DUPLEX) - hw->phy.autoneg_advertised = E1000_ALL_100_SPEED; - else if (dev->data->dev_conf.link_duplex == - ETH_LINK_HALF_DUPLEX) - hw->phy.autoneg_advertised = ADVERTISE_100_HALF; - else if (dev->data->dev_conf.link_duplex == - ETH_LINK_FULL_DUPLEX) - hw->phy.autoneg_advertised = ADVERTISE_100_FULL; - else + speeds = &dev->data->dev_conf.link_speeds; + if (*speeds == ETH_LINK_SPEED_AUTONEG) { + hw->phy.autoneg_advertised = E1000_ALL_SPEED_DUPLEX; + } else { + num_speeds = 0; + autoneg = (*speeds & ETH_LINK_SPEED_FIXED) == 0; + + /* Reset */ + hw->phy.autoneg_advertised = 0; + + if (*speeds & ~(ETH_LINK_SPEED_10M_HD | ETH_LINK_SPEED_10M | + ETH_LINK_SPEED_100M_HD | ETH_LINK_SPEED_100M | + ETH_LINK_SPEED_1G | ETH_LINK_SPEED_FIXED)) { + num_speeds = -1; goto error_invalid_config; - break; - case ETH_SPEED_NUM_1G: - if ((dev->data->dev_conf.link_duplex == - ETH_LINK_AUTONEG_DUPLEX) || - (dev->data->dev_conf.link_duplex == - ETH_LINK_FULL_DUPLEX)) - hw->phy.autoneg_advertised = ADVERTISE_1000_FULL; - else + } + if (*speeds & ETH_LINK_SPEED_10M_HD) { + hw->phy.autoneg_advertised |= ADVERTISE_10_HALF; + num_speeds++; + } + if (*speeds & ETH_LINK_SPEED_10M) { + hw->phy.autoneg_advertised |= ADVERTISE_10_FULL; + num_speeds++; + } + if (*speeds & ETH_LINK_SPEED_100M_HD) { + hw->phy.autoneg_advertised |= ADVERTISE_100_HALF; + num_speeds++; + } + if (*speeds & ETH_LINK_SPEED_100M) { + hw->phy.autoneg_advertised |= ADVERTISE_100_FULL; + num_speeds++; + } + if (*speeds & ETH_LINK_SPEED_1G) { + hw->phy.autoneg_advertised |= ADVERTISE_1000_FULL; + num_speeds++; + } + if (num_speeds == 0 || (!autoneg && (num_speeds > 1))) goto error_invalid_config; - break; - case ETH_SPEED_NUM_10G: - default: - goto error_invalid_config; } + e1000_setup_link(hw); if (rte_intr_allow_others(intr_handle)) { @@ -694,9 +687,8 @@ eth_em_start(struct rte_eth_dev *dev) return 0; error_invalid_config: - PMD_INIT_LOG(ERR, "Invalid link_speed/link_duplex (%u/%u) for port %u", - dev->data->dev_conf.link_speed, - dev->data->dev_conf.link_duplex, dev->data->port_id); + PMD_INIT_LOG(ERR, "Invalid advertised speeds (%u) for port %u", + dev->data->dev_conf.link_speeds, dev->data->port_id); em_dev_clear_queues(dev); return -EINVAL; } @@ -1106,13 +1098,20 @@ eth_em_link_update(struct rte_eth_dev *dev, int wait_to_complete) /* Now we check if a transition has happened */ if (link_check && (link.link_status == ETH_LINK_DOWN)) { - hw->mac.ops.get_link_up_info(hw, &link.link_speed, - &link.link_duplex); + uint16_t duplex, speed; + hw->mac.ops.get_link_up_info(hw, &speed, &duplex); + link.link_duplex = (duplex == FULL_DUPLEX) ? + ETH_LINK_FULL_DUPLEX : + ETH_LINK_HALF_DUPLEX; + link.link_speed = speed; link.link_status = ETH_LINK_UP; + link.link_autoneg = !(dev->data->dev_conf.link_speeds & + ETH_LINK_SPEED_FIXED); } else if (!link_check && (link.link_status == ETH_LINK_UP)) { link.link_speed = 0; link.link_duplex = ETH_LINK_HALF_DUPLEX; link.link_status = ETH_LINK_DOWN; + link.link_autoneg = ETH_LINK_SPEED_FIXED; } rte_em_dev_atomic_write_link_status(dev, &link); diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c index 95d1711..e0053fe 100644 --- a/drivers/net/e1000/igb_ethdev.c +++ b/drivers/net/e1000/igb_ethdev.c @@ -1133,6 +1133,9 @@ eth_igb_start(struct rte_eth_dev *dev) int ret, mask; uint32_t intr_vector = 0; uint32_t ctrl_ext; + uint32_t *speeds; + int num_speeds; + bool autoneg; PMD_INIT_FUNC_TRACE(); @@ -1233,48 +1236,46 @@ eth_igb_start(struct rte_eth_dev *dev) } /* Setup link speed and duplex */ - switch (dev->data->dev_conf.link_speed) { - case ETH_LINK_SPEED_AUTONEG: - if (dev->data->dev_conf.link_duplex == ETH_LINK_AUTONEG_DUPLEX) - hw->phy.autoneg_advertised = E1000_ALL_SPEED_DUPLEX; - else if (dev->data->dev_conf.link_duplex == ETH_LINK_HALF_DUPLEX) - hw->phy.autoneg_advertised = E1000_ALL_HALF_DUPLEX; - else if (dev->data->dev_conf.link_duplex == ETH_LINK_FULL_DUPLEX) - hw->phy.autoneg_advertised = E1000_ALL_FULL_DUPLEX; - else - goto error_invalid_config; - break; - case ETH_SPEED_NUM_10M: - if (dev->data->dev_conf.link_duplex == ETH_LINK_AUTONEG_DUPLEX) - hw->phy.autoneg_advertised = E1000_ALL_10_SPEED; - else if (dev->data->dev_conf.link_duplex == ETH_LINK_HALF_DUPLEX) - hw->phy.autoneg_advertised = ADVERTISE_10_HALF; - else if (dev->data->dev_conf.link_duplex == ETH_LINK_FULL_DUPLEX) - hw->phy.autoneg_advertised = ADVERTISE_10_FULL; - else - goto error_invalid_config; - break; - case ETH_SPEED_NUM_100M: - if (dev->data->dev_conf.link_duplex == ETH_LINK_AUTONEG_DUPLEX) - hw->phy.autoneg_advertised = E1000_ALL_100_SPEED; - else if (dev->data->dev_conf.link_duplex == ETH_LINK_HALF_DUPLEX) - hw->phy.autoneg_advertised = ADVERTISE_100_HALF; - else if (dev->data->dev_conf.link_duplex == ETH_LINK_FULL_DUPLEX) - hw->phy.autoneg_advertised = ADVERTISE_100_FULL; - else + speeds = &dev->data->dev_conf.link_speeds; + if (*speeds == ETH_LINK_SPEED_AUTONEG) { + hw->phy.autoneg_advertised = E1000_ALL_SPEED_DUPLEX; + } else { + num_speeds = 0; + autoneg = (*speeds & ETH_LINK_SPEED_FIXED) == 0; + + /* Reset */ + hw->phy.autoneg_advertised = 0; + + if (*speeds & ~(ETH_LINK_SPEED_10M_HD | ETH_LINK_SPEED_10M | + ETH_LINK_SPEED_100M_HD | ETH_LINK_SPEED_100M | + ETH_LINK_SPEED_1G | ETH_LINK_SPEED_FIXED)) { + num_speeds = -1; goto error_invalid_config; - break; - case ETH_SPEED_NUM_1G: - if ((dev->data->dev_conf.link_duplex == ETH_LINK_AUTONEG_DUPLEX) || - (dev->data->dev_conf.link_duplex == ETH_LINK_FULL_DUPLEX)) - hw->phy.autoneg_advertised = ADVERTISE_1000_FULL; - else + } + if (*speeds & ETH_LINK_SPEED_10M_HD) { + hw->phy.autoneg_advertised |= ADVERTISE_10_HALF; + num_speeds++; + } + if (*speeds & ETH_LINK_SPEED_10M) { + hw->phy.autoneg_advertised |= ADVERTISE_10_FULL; + num_speeds++; + } + if (*speeds & ETH_LINK_SPEED_100M_HD) { + hw->phy.autoneg_advertised |= ADVERTISE_100_HALF; + num_speeds++; + } + if (*speeds & ETH_LINK_SPEED_100M) { + hw->phy.autoneg_advertised |= ADVERTISE_100_FULL; + num_speeds++; + } + if (*speeds & ETH_LINK_SPEED_1G) { + hw->phy.autoneg_advertised |= ADVERTISE_1000_FULL; + num_speeds++; + } + if (num_speeds == 0 || (!autoneg && (num_speeds > 1))) goto error_invalid_config; - break; - case ETH_SPEED_NUM_10G: - default: - goto error_invalid_config; } + e1000_setup_link(hw); if (rte_intr_allow_others(intr_handle)) { @@ -1306,9 +1307,8 @@ eth_igb_start(struct rte_eth_dev *dev) return 0; error_invalid_config: - PMD_INIT_LOG(ERR, "Invalid link_speed/link_duplex (%u/%u) for port %u", - dev->data->dev_conf.link_speed, - dev->data->dev_conf.link_duplex, dev->data->port_id); + PMD_INIT_LOG(ERR, "Invalid advertised speeds (%u) for port %u", + dev->data->dev_conf.link_speeds, dev->data->port_id); igb_dev_clear_queues(dev); return -EINVAL; } @@ -2061,13 +2061,20 @@ eth_igb_link_update(struct rte_eth_dev *dev, int wait_to_complete) /* Now we check if a transition has happened */ if (link_check) { - hw->mac.ops.get_link_up_info(hw, &link.link_speed, - &link.link_duplex); + uint16_t duplex, speed; + hw->mac.ops.get_link_up_info(hw, &speed, &duplex); + link.link_duplex = (duplex == FULL_DUPLEX) ? + ETH_LINK_FULL_DUPLEX : + ETH_LINK_HALF_DUPLEX; + link.link_speed = speed; link.link_status = ETH_LINK_UP; + link.link_autoneg = !(dev->data->dev_conf.link_speeds & + ETH_LINK_SPEED_FIXED); } else if (!link_check) { link.link_speed = 0; link.link_duplex = ETH_LINK_HALF_DUPLEX; link.link_status = ETH_LINK_DOWN; + link.link_autoneg = ETH_LINK_SPEED_FIXED; } rte_igb_dev_atomic_write_link_status(dev, &link); diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c index dce31db..c9ef417 100644 --- a/drivers/net/i40e/i40e_ethdev.c +++ b/drivers/net/i40e/i40e_ethdev.c @@ -1381,27 +1381,20 @@ i40e_vsi_disable_queues_intr(struct i40e_vsi *vsi) } static inline uint8_t -i40e_parse_link_speed(uint16_t eth_link_speed) +i40e_parse_link_speeds(uint16_t link_speeds) { uint8_t link_speed = I40E_LINK_SPEED_UNKNOWN; - switch (eth_link_speed) { - case ETH_SPEED_NUM_40G: - link_speed = I40E_LINK_SPEED_40GB; - break; - case ETH_SPEED_NUM_20G: - link_speed = I40E_LINK_SPEED_20GB; - break; - case ETH_SPEED_NUM_10G: - link_speed = I40E_LINK_SPEED_10GB; - break; - case ETH_SPEED_NUM_1G: - link_speed = I40E_LINK_SPEED_1GB; - break; - case ETH_SPEED_NUM_100M: - link_speed = I40E_LINK_SPEED_100MB; - break; - } + if (link_speeds & ETH_LINK_SPEED_40G) + link_speed |= I40E_LINK_SPEED_40GB; + if (link_speeds & ETH_LINK_SPEED_20G) + link_speed |= I40E_LINK_SPEED_20GB; + if (link_speeds & ETH_LINK_SPEED_10G) + link_speed |= I40E_LINK_SPEED_10GB; + if (link_speeds & ETH_LINK_SPEED_1G) + link_speed |= I40E_LINK_SPEED_1GB; + if (link_speeds & ETH_LINK_SPEED_100M) + link_speed |= I40E_LINK_SPEED_100MB; return link_speed; } @@ -1427,9 +1420,9 @@ i40e_apply_link_speed(struct rte_eth_dev *dev) struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct rte_eth_conf *conf = &dev->data->dev_conf; - speed = i40e_parse_link_speed(conf->link_speed); + speed = i40e_parse_link_speeds(conf->link_speeds); abilities |= I40E_AQ_PHY_ENABLE_ATOMIC_LINK; - if (conf->link_speed == ETH_LINK_SPEED_AUTONEG) + if (!(conf->link_speeds & ETH_LINK_SPEED_FIXED)) abilities |= I40E_AQ_PHY_AN_ENABLED; else abilities |= I40E_AQ_PHY_LINK_ENABLED; @@ -1449,10 +1442,8 @@ i40e_dev_start(struct rte_eth_dev *dev) hw->adapter_stopped = 0; - if ((dev->data->dev_conf.link_duplex != ETH_LINK_AUTONEG_DUPLEX) && - (dev->data->dev_conf.link_duplex != ETH_LINK_FULL_DUPLEX)) { - PMD_INIT_LOG(ERR, "Invalid link_duplex (%hu) for port %hhu", - dev->data->dev_conf.link_duplex, + if (dev->data->dev_conf.link_speeds & ETH_LINK_SPEED_FIXED) { + PMD_INIT_LOG(ERR, "Invalid link_speeds for port %hhu; autonegotiation disabled", dev->data->port_id); return -EINVAL; } @@ -1525,6 +1516,12 @@ i40e_dev_start(struct rte_eth_dev *dev) } /* Apply link configure */ + if (dev->data->dev_conf.link_speeds & ~(ETH_LINK_SPEED_100M | + ETH_LINK_SPEED_1G | ETH_LINK_SPEED_10G | + ETH_LINK_SPEED_20G | ETH_LINK_SPEED_40G)) { + PMD_DRV_LOG(ERR, "Invalid link setting"); + goto err_up; + } ret = i40e_apply_link_speed(dev); if (I40E_SUCCESS != ret) { PMD_DRV_LOG(ERR, "Fail to apply link setting"); @@ -1809,6 +1806,9 @@ i40e_dev_link_update(struct rte_eth_dev *dev, break; } + link.link_autoneg = !(dev->data->dev_conf.link_speeds & + ETH_LINK_SPEED_FIXED); + out: rte_i40e_dev_atomic_write_link_status(dev, &link); if (link.link_status == old.link_status) diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c index 295dcd2..8cf22ee 100644 --- a/drivers/net/i40e/i40e_ethdev_vf.c +++ b/drivers/net/i40e/i40e_ethdev_vf.c @@ -2121,12 +2121,13 @@ i40evf_dev_link_update(struct rte_eth_dev *dev, * DPDK pf host provide interfacet to acquire link status * while Linux driver does not */ - if (vf->version_major == I40E_DPDK_VERSION_MAJOR) + if (vf->version_major == I40E_DPDK_VERSION_MAJOR) { i40evf_get_link_status(dev, &new_link); - else { + } else { /* Always assume it's up, for Linux driver PF host */ - new_link.link_duplex = ETH_LINK_AUTONEG_DUPLEX; new_link.link_speed = ETH_SPEED_NUM_10G; + new_link.link_duplex = ETH_LINK_FULL_DUPLEX; + new_link.link_autoneg = ETH_LINK_SPEED_AUTONEG; new_link.link_status = ETH_LINK_UP; } i40evf_dev_atomic_write_link_status(dev, &new_link); diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c index a98e8eb..6cc2da0 100644 --- a/drivers/net/ixgbe/ixgbe_ethdev.c +++ b/drivers/net/ixgbe/ixgbe_ethdev.c @@ -2094,14 +2094,16 @@ ixgbe_dev_start(struct rte_eth_dev *dev) int mask = 0; int status; uint16_t vf, idx; + uint32_t *link_speeds; PMD_INIT_FUNC_TRACE(); - /* IXGBE devices don't support half duplex */ - if ((dev->data->dev_conf.link_duplex != ETH_LINK_AUTONEG_DUPLEX) && - (dev->data->dev_conf.link_duplex != ETH_LINK_FULL_DUPLEX)) { - PMD_INIT_LOG(ERR, "Invalid link_duplex (%hu) for port %hhu", - dev->data->dev_conf.link_duplex, + /* IXGBE devices don't support: + * - half duplex (checked afterwards for valid speeds) + * - fixed speed: TODO implement + */ + if (dev->data->dev_conf.link_speeds & ETH_LINK_SPEED_FIXED) { + PMD_INIT_LOG(ERR, "Invalid link_speeds for port %hhu; fix speed not supported", dev->data->port_id); return -EINVAL; } @@ -2193,32 +2195,21 @@ ixgbe_dev_start(struct rte_eth_dev *dev) if (err) goto error; - switch(dev->data->dev_conf.link_speed) { - case ETH_LINK_SPEED_AUTONEG: - speed = (hw->mac.type != ixgbe_mac_82598EB) ? - IXGBE_LINK_SPEED_82599_AUTONEG : - IXGBE_LINK_SPEED_82598_AUTONEG; - break; - case ETH_SPEED_NUM_100M: - /* - * Invalid for 82598 but error will be detected by - * ixgbe_setup_link() - */ - speed = IXGBE_LINK_SPEED_100_FULL; - break; - case ETH_SPEED_NUM_1G: - speed = IXGBE_LINK_SPEED_1GB_FULL; - break; - case ETH_SPEED_NUM_10G: - speed = IXGBE_LINK_SPEED_10GB_FULL; - break; - default: - PMD_INIT_LOG(ERR, "Invalid link_speed (%hu) for port %hhu", - dev->data->dev_conf.link_speed, - dev->data->port_id); + link_speeds = &dev->data->dev_conf.link_speeds; + if (*link_speeds & ~(ETH_LINK_SPEED_100M | ETH_LINK_SPEED_1G | + ETH_LINK_SPEED_10G)) { + PMD_INIT_LOG(ERR, "Invalid link setting"); goto error; } + speed = 0x0; + if (*link_speeds & ETH_LINK_SPEED_10G) + speed |= IXGBE_LINK_SPEED_10GB_FULL; + if (*link_speeds & ETH_LINK_SPEED_1G) + speed |= IXGBE_LINK_SPEED_1GB_FULL; + if (*link_speeds & ETH_LINK_SPEED_100M) + speed |= IXGBE_LINK_SPEED_100_FULL; + err = ixgbe_setup_link(hw, speed, link_up); if (err) goto error; @@ -3083,7 +3074,7 @@ ixgbe_dev_link_update(struct rte_eth_dev *dev, int wait_to_complete) if (diag != 0) { link.link_speed = ETH_SPEED_NUM_100M; - link.link_duplex = ETH_LINK_HALF_DUPLEX; + link.link_duplex = ETH_LINK_FULL_DUPLEX; rte_ixgbe_dev_atomic_write_link_status(dev, &link); if (link.link_status == old.link_status) return -1; @@ -3102,7 +3093,7 @@ ixgbe_dev_link_update(struct rte_eth_dev *dev, int wait_to_complete) switch (link_speed) { default: case IXGBE_LINK_SPEED_UNKNOWN: - link.link_duplex = ETH_LINK_HALF_DUPLEX; + link.link_duplex = ETH_LINK_FULL_DUPLEX; link.link_speed = ETH_SPEED_NUM_100M; break; diff --git a/drivers/net/mlx4/mlx4.c b/drivers/net/mlx4/mlx4.c index 59ac423..81528c9 100644 --- a/drivers/net/mlx4/mlx4.c +++ b/drivers/net/mlx4/mlx4.c @@ -4721,6 +4721,8 @@ mlx4_link_update_unlocked(struct rte_eth_dev *dev, int wait_to_complete) dev_link.link_speed = link_speed; dev_link.link_duplex = ((edata.duplex == DUPLEX_HALF) ? ETH_LINK_HALF_DUPLEX : ETH_LINK_FULL_DUPLEX); + dev_link.link_autoneg = !(dev->data->dev_conf.link_speeds & + ETH_LINK_SPEED_FIXED); if (memcmp(&dev_link, &dev->data->dev_link, sizeof(dev_link))) { /* Link status changed. */ dev->data->dev_link = dev_link; diff --git a/drivers/net/mlx5/mlx5_ethdev.c b/drivers/net/mlx5/mlx5_ethdev.c index d7a0eea..beecc63 100644 --- a/drivers/net/mlx5/mlx5_ethdev.c +++ b/drivers/net/mlx5/mlx5_ethdev.c @@ -629,6 +629,8 @@ mlx5_link_update_unlocked(struct rte_eth_dev *dev, int wait_to_complete) dev_link.link_speed = link_speed; dev_link.link_duplex = ((edata.duplex == DUPLEX_HALF) ? ETH_LINK_HALF_DUPLEX : ETH_LINK_FULL_DUPLEX); + dev_link.link_autoneg = !(dev->data->dev_conf.link_speeds & + ETH_LINK_SPEED_FIXED); if (memcmp(&dev_link, &dev->data->dev_link, sizeof(dev_link))) { /* Link status changed. */ dev->data->dev_link = dev_link; diff --git a/drivers/net/mpipe/mpipe_tilegx.c b/drivers/net/mpipe/mpipe_tilegx.c index 1a77c7a..adcbc19 100644 --- a/drivers/net/mpipe/mpipe_tilegx.c +++ b/drivers/net/mpipe/mpipe_tilegx.c @@ -394,6 +394,8 @@ mpipe_link_update(struct rte_eth_dev *dev, int wait_to_complete) speed = state & GXIO_MPIPE_LINK_SPEED_MASK; + new.link_autoneg = (dev->data->dev_conf.link_speeds & + ETH_LINK_SPEED_AUTONEG); if (speed == GXIO_MPIPE_LINK_1G) { new.link_speed = ETH_SPEED_NUM_1G; new.link_duplex = ETH_LINK_FULL_DUPLEX; diff --git a/drivers/net/null/rte_eth_null.c b/drivers/net/null/rte_eth_null.c index 5640585..5e8e203 100644 --- a/drivers/net/null/rte_eth_null.c +++ b/drivers/net/null/rte_eth_null.c @@ -92,6 +92,7 @@ static struct rte_eth_link pmd_link = { .link_speed = ETH_SPEED_NUM_10G, .link_duplex = ETH_LINK_FULL_DUPLEX, .link_status = ETH_LINK_DOWN, + .link_autoneg = ETH_LINK_SPEED_AUTONEG, }; static uint16_t diff --git a/drivers/net/pcap/rte_eth_pcap.c b/drivers/net/pcap/rte_eth_pcap.c index c657951..c98e234 100644 --- a/drivers/net/pcap/rte_eth_pcap.c +++ b/drivers/net/pcap/rte_eth_pcap.c @@ -126,6 +126,7 @@ static struct rte_eth_link pmd_link = { .link_speed = ETH_SPEED_NUM_10G, .link_duplex = ETH_LINK_FULL_DUPLEX, .link_status = ETH_LINK_DOWN, + .link_autoneg = ETH_LINK_SPEED_FIXED, }; static int diff --git a/drivers/net/ring/rte_eth_ring.c b/drivers/net/ring/rte_eth_ring.c index 58685e9..b1783c3 100644 --- a/drivers/net/ring/rte_eth_ring.c +++ b/drivers/net/ring/rte_eth_ring.c @@ -80,6 +80,7 @@ static struct rte_eth_link pmd_link = { .link_speed = ETH_SPEED_NUM_10G, .link_duplex = ETH_LINK_FULL_DUPLEX, .link_status = ETH_LINK_DOWN, + .link_autoneg = ETH_LINK_SPEED_AUTONEG }; static uint16_t diff --git a/drivers/net/szedata2/rte_eth_szedata2.c b/drivers/net/szedata2/rte_eth_szedata2.c index dd1ae9e..ee97a4e 100644 --- a/drivers/net/szedata2/rte_eth_szedata2.c +++ b/drivers/net/szedata2/rte_eth_szedata2.c @@ -1174,6 +1174,8 @@ eth_link_update(struct rte_eth_dev *dev, link.link_status = (cgmii_ibuf_is_enabled(ibuf) && cgmii_ibuf_is_link_up(ibuf)) ? ETH_LINK_UP : ETH_LINK_DOWN; + link.link_autoneg = ETH_LINK_SPEED_FIXED; + rte_atomic64_cmpset((uint64_t *)dev_link, *(uint64_t *)dev_link, *(uint64_t *)link_ptr); diff --git a/drivers/net/vmxnet3/vmxnet3_ethdev.c b/drivers/net/vmxnet3/vmxnet3_ethdev.c index 6afa14e..94d1b2c 100644 --- a/drivers/net/vmxnet3/vmxnet3_ethdev.c +++ b/drivers/net/vmxnet3/vmxnet3_ethdev.c @@ -780,6 +780,7 @@ vmxnet3_dev_link_update(struct rte_eth_dev *dev, __attribute__((unused)) int wai link.link_status = ETH_LINK_UP; link.link_duplex = ETH_LINK_FULL_DUPLEX; link.link_speed = ETH_SPEED_NUM_10G; + link.link_autoneg = ETH_LINK_SPEED_FIXED; } vmxnet3_dev_atomic_write_link_status(dev, &link); diff --git a/drivers/net/xenvirt/rte_eth_xenvirt.c b/drivers/net/xenvirt/rte_eth_xenvirt.c index 77d3ba1..b9638d9 100644 --- a/drivers/net/xenvirt/rte_eth_xenvirt.c +++ b/drivers/net/xenvirt/rte_eth_xenvirt.c @@ -73,6 +73,7 @@ static struct rte_eth_link pmd_link = { .link_speed = ETH_SPEED_NUM_10G, .link_duplex = ETH_LINK_FULL_DUPLEX, .link_status = ETH_LINK_DOWN, + .link_autoneg = ETH_LINK_SPEED_FIXED }; static void diff --git a/examples/ip_pipeline/config_parse.c b/examples/ip_pipeline/config_parse.c index 152889d..2cd5707 100644 --- a/examples/ip_pipeline/config_parse.c +++ b/examples/ip_pipeline/config_parse.c @@ -87,8 +87,7 @@ static const struct app_link_params link_params_default = { .pci_bdf = {0}, .conf = { - .link_speed = 0, - .link_duplex = 0, + .link_speeds = 0, .rxmode = { .mq_mode = ETH_MQ_RX_NONE, diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h index 49fdcb7..9a1466b 100644 --- a/lib/librte_ether/rte_ethdev.h +++ b/lib/librte_ether/rte_ethdev.h @@ -244,6 +244,8 @@ struct rte_eth_stats { /** * Device supported speeds bitmap flags */ +#define ETH_LINK_SPEED_AUTONEG (0 << 0) /**< Autonegotiate (all speeds) */ +#define ETH_LINK_SPEED_FIXED (1 << 0) /**< Disable autoneg (fixed speed) */ #define ETH_LINK_SPEED_10M_HD (1 << 1) /**< 10 Mbps half-duplex */ #define ETH_LINK_SPEED_10M (1 << 2) /**< 10 Mbps full-duplex */ #define ETH_LINK_SPEED_100M_HD (1 << 3) /**< 100 Mbps half-duplex */ @@ -261,7 +263,7 @@ struct rte_eth_stats { /** * Ethernet numeric link speeds in Mbps */ -#define ETH_LINK_SPEED_AUTONEG 0 /**< Auto-negotiate link speed. */ +#define ETH_SPEED_NUM_NONE 0 /**< Not defined */ #define ETH_SPEED_NUM_10M 10 /**< 10 Mbps */ #define ETH_SPEED_NUM_100M 100 /**< 100 Mbps */ #define ETH_SPEED_NUM_1G 1000 /**< 1 Gbps */ @@ -278,15 +280,15 @@ struct rte_eth_stats { * A structure used to retrieve link-level information of an Ethernet port. */ struct rte_eth_link { - uint16_t link_speed; /**< ETH_SPEED_NUM_ */ - uint16_t link_duplex; /**< ETH_LINK_[HALF/FULL]_DUPLEX */ - uint8_t link_status : 1; /**< ETH_LINK_[DOWN/UP] */ -}__attribute__((aligned(8))); /**< aligned for atomic64 read/write */ + uint16_t link_speed; /**< ETH_SPEED_NUM_ */ + uint16_t link_duplex : 1; /**< ETH_LINK_[HALF/FULL]_DUPLEX */ + uint16_t link_autoneg : 1; /**< ETH_LINK_SPEED_[AUTONEG/FIXED] */ + uint16_t link_status : 1; /**< ETH_LINK_[DOWN/UP] */ +} __attribute__((aligned(8))); /**< aligned for atomic64 read/write */ /* Utility constants */ -#define ETH_LINK_AUTONEG_DUPLEX 0 /**< Auto-negotiate duplex. */ -#define ETH_LINK_HALF_DUPLEX 1 /**< Half-duplex connection. */ -#define ETH_LINK_FULL_DUPLEX 2 /**< Full-duplex connection. */ +#define ETH_LINK_HALF_DUPLEX 0 /**< Half-duplex connection. */ +#define ETH_LINK_FULL_DUPLEX 1 /**< Full-duplex connection. */ #define ETH_LINK_DOWN 0 /**< Link is down. */ #define ETH_LINK_UP 1 /**< Link is up. */ @@ -802,10 +804,13 @@ struct rte_intr_conf { * configuration settings may be needed. */ struct rte_eth_conf { - uint16_t link_speed; - /**< ETH_SPEED_NUM_ or 0 for autonegotiation */ - uint16_t link_duplex; - /**< ETH_LINK_[HALF_DUPLEX|FULL_DUPLEX], or 0 for autonegotation */ + uint32_t link_speeds; /**< bitmap of ETH_LINK_SPEED_XXX of speeds to be + used. ETH_LINK_SPEED_FIXED disables link + autonegotiation, and a unique speed shall be + set. Otherwise, the bitmap defines the set of + speeds to be advertised. If the special value + ETH_LINK_SPEED_AUTONEG (0) is used, all speeds + supported are advertised. */ struct rte_eth_rxmode rxmode; /**< Port RX configuration. */ struct rte_eth_txmode txmode; /**< Port TX configuration. */ uint32_t lpbk_mode; /**< Loopback operation mode. By default the value