From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wm0-f52.google.com (mail-wm0-f52.google.com [74.125.82.52]) by dpdk.org (Postfix) with ESMTP id 20782558B for ; Mon, 14 Mar 2016 22:57:31 +0100 (CET) Received: by mail-wm0-f52.google.com with SMTP id p65so1798006wmp.0 for ; Mon, 14 Mar 2016 14:57:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=6wind-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=rQL/2RtXS0TdAIlw+GQ/Xwu5HfXPG34VV4EMOqrexGg=; b=BNWO1vMRhfMeeB/MPmN05l5SQWydv4yJVH3ZcPNUu1mwh/SEkWoCfCTlRbxzhipgpZ ck/fL8Y77WgeoesUHN9boLtTqbSKtywvjpgO1ynskDJx1SJPPW3t1Q04lFsRuaEHB2Is Q9kq2J9izwrdq2rWxkDbqcPRKljYQhHv1tuGyCq2JhAGQxn/rTwYeuzePi2qbM1JpIf1 fTgtRW5JFy0MQzE+Bw09OHq8pZB6NO3DhGMeYoTn0LB4QsXHTzGHxWKQXUSkf6baTQmX wzdEz1s+69abrTm5CHzn3e2fY3AoCLA3ZcSccCbnZFVLitXc2EXG3tgxCBy6ShyxA4fY S3pg== 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=rQL/2RtXS0TdAIlw+GQ/Xwu5HfXPG34VV4EMOqrexGg=; b=B8e0x/aKcw9rEHnIqsyK6zY3pdD/hpzBCWk9fIGI9fFtpfIagZMgz6SYN2YJTXzdam Xha3aJ9fGys6GEEFgad3tSG/UrmG0fWXUuILlxx3JWshk9gCBq9ANdKTOzQlLZ32rBtm /upxMT/2R/2UFIHK7ASKLcAqFqQQyRZakk2TRanVlomQEcNsU8faqoT+mbF5CWGnVROy eNlyrbFrBZ1hPULnmT5kqQedwvH2I5nuOOhf3x2ALCCsQI3OsKgmiItA5VCb6q2QQ0x0 ksLPAiXcmi9tMR4bIGOnP6uaBRYdNYrXXlKB6v2jdjyn0oq2cgQVGUTBP5DYVIn2xPa1 BDRQ== X-Gm-Message-State: AD7BkJLXVyyMitbqaVeYfBpb+tJ2FOi9uGsGFhuOqJJmW/JjEVvSojRaGHXu4Ok0bwwuCj6K X-Received: by 10.194.2.169 with SMTP id 9mr26648654wjv.7.1457992650955; Mon, 14 Mar 2016 14:57:30 -0700 (PDT) Received: from XPS13.localdomain (91.111.75.86.rev.sfr.net. [86.75.111.91]) by smtp.gmail.com with ESMTPSA id w133sm17918804wmd.3.2016.03.14.14.57.28 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 14 Mar 2016 14:57:30 -0700 (PDT) From: Thomas Monjalon To: marcdevel@gmail.com, bruce.richardson@intel.com, declan.doherty@intel.com, konstantin.ananyev@intel.com, wenzhuo.lu@intel.com, helin.zhang@intel.com, jing.d.chen@intel.com, harish.patil@qlogic.com, rahul.lakkireddy@chelsio.com, johndale@cisco.com, vido@cesnet.cz, adrien.mazarguil@6wind.com, alejandro.lucero@netronome.com Cc: dev@dpdk.org Date: Mon, 14 Mar 2016 22:55:44 +0100 Message-Id: <1457992546-32230-7-git-send-email-thomas.monjalon@6wind.com> X-Mailer: git-send-email 2.7.0 In-Reply-To: <1457992546-32230-1-git-send-email-thomas.monjalon@6wind.com> References: <1456793151-1475-1-git-send-email-marcdevel@gmail.com> <1457992546-32230-1-git-send-email-thomas.monjalon@6wind.com> Subject: [dpdk-dev] [PATCH v10 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: , X-List-Received-Date: Mon, 14 Mar 2016 21:57:31 -0000 From: Marc Sune 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 --- PLEASE REVIEW CAREFULLY THIS PATCH app/test-pmd/cmdline.c | 26 ++++---- 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 | 99 +++++++++++++++---------------- drivers/net/e1000/igb_ethdev.c | 94 +++++++++++++++-------------- drivers/net/i40e/i40e_ethdev.c | 48 +++++++-------- drivers/net/i40e/i40e_ethdev_vf.c | 7 ++- drivers/net/ixgbe/ixgbe_ethdev.c | 46 ++++++-------- drivers/net/mlx4/mlx4.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 +++++---- 20 files changed, 195 insertions(+), 184 deletions(-) diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index 874129a..3bc7bb4 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -984,7 +984,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; @@ -1001,20 +1001,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 { @@ -1032,8 +1034,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()) { @@ -1046,8 +1047,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); @@ -1105,8 +1105,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"); @@ -1120,8 +1119,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/release_16_04.rst b/doc/guides/rel_notes/release_16_04.rst index fd24a6f..f6d00f5 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. + * **Virtio 1.0.** Enabled virtio 1.0 support for virtio pmd driver. @@ -216,6 +222,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 ff0d299..d6b14e9 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 b86784e..d3d88a7 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_AUTONEG); 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 5f9c9b3..3b446e1 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 dddffff..d2f1b25 100644 --- a/drivers/net/e1000/em_ethdev.c +++ b/drivers/net/e1000/em_ethdev.c @@ -509,6 +509,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(); @@ -583,56 +586,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_AUTONEG); + + /* 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)) { + 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 > 2))) 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)) { @@ -665,9 +658,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; } @@ -1075,8 +1067,11 @@ 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 == 0)) { - 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 ? ETH_LINK_FULL_DUPLEX : + ETH_LINK_HALF_DUPLEX; + link.link_speed = speed; link.link_status = ETH_LINK_UP; } else if (!link_check && (link.link_status == ETH_LINK_UP)) { link.link_speed = 0; diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c index 743fe1b..ca82872 100644 --- a/drivers/net/e1000/igb_ethdev.c +++ b/drivers/net/e1000/igb_ethdev.c @@ -1121,6 +1121,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(); @@ -1221,48 +1224,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_AUTONEG); + + /* 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)) { + 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 > 2))) 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)) { @@ -1294,9 +1295,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; } @@ -2023,13 +2023,19 @@ 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 ? 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_AUTONEG); } 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 3b2a4ae..a0aaca0 100644 --- a/drivers/net/i40e/i40e_ethdev.c +++ b/drivers/net/i40e/i40e_ethdev.c @@ -1358,27 +1358,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; } @@ -1404,9 +1397,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_AUTONEG) abilities |= I40E_AQ_PHY_AN_ENABLED; else abilities |= I40E_AQ_PHY_LINK_ENABLED; @@ -1426,10 +1419,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_AUTONEG)) { + PMD_INIT_LOG(ERR, "Invalid link_speeds for port %hhu; autonegotiation disabled", dev->data->port_id); return -EINVAL; } @@ -1502,6 +1493,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"); @@ -1786,6 +1783,9 @@ i40e_dev_link_update(struct rte_eth_dev *dev, break; } + link.link_autoneg = (dev->data->dev_conf.link_speeds & + ETH_LINK_SPEED_AUTONEG); + 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 7ac5c48..03c03ea 100644 --- a/drivers/net/i40e/i40e_ethdev_vf.c +++ b/drivers/net/i40e/i40e_ethdev_vf.c @@ -1911,12 +1911,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 1c108a0..7f150e5 100644 --- a/drivers/net/ixgbe/ixgbe_ethdev.c +++ b/drivers/net/ixgbe/ixgbe_ethdev.c @@ -2035,14 +2035,13 @@ 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, + if (!(dev->data->dev_conf.link_speeds & ETH_LINK_SPEED_AUTONEG)) { + PMD_INIT_LOG(ERR, "Invalid link_speeds for port %hhu; autonegotiation disabled", dev->data->port_id); return -EINVAL; } @@ -2132,32 +2131,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; @@ -2981,7 +2969,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; @@ -3000,7 +2988,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 7397cbf..54f8c70 100644 --- a/drivers/net/mlx4/mlx4.c +++ b/drivers/net/mlx4/mlx4.c @@ -4634,6 +4634,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_AUTONEG); 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 fc1f90d..1ca05c2 100644 --- a/drivers/net/mpipe/mpipe_tilegx.c +++ b/drivers/net/mpipe/mpipe_tilegx.c @@ -388,6 +388,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 3f37c54..fa06b9d 100644 --- a/drivers/net/null/rte_eth_null.c +++ b/drivers/net/null/rte_eth_null.c @@ -96,6 +96,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 5251b9f..650b521 100644 --- a/drivers/net/pcap/rte_eth_pcap.c +++ b/drivers/net/pcap/rte_eth_pcap.c @@ -128,6 +128,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 bd18508..8c0bf7b 100644 --- a/drivers/net/ring/rte_eth_ring.c +++ b/drivers/net/ring/rte_eth_ring.c @@ -74,6 +74,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 9d46987..38be554 100644 --- a/drivers/net/szedata2/rte_eth_szedata2.c +++ b/drivers/net/szedata2/rte_eth_szedata2.c @@ -111,7 +111,7 @@ static struct ether_addr eth_addr = { }; static const char *drivername = "SZEdata2 PMD"; static struct rte_eth_link pmd_link = { - .link_speed = ETH_SPEED_NUM_10G, + .link_speed = ETH_LINK_SPEED_10G, .link_duplex = ETH_LINK_FULL_DUPLEX, .link_status = ETH_LINK_DOWN }; diff --git a/drivers/net/vmxnet3/vmxnet3_ethdev.c b/drivers/net/vmxnet3/vmxnet3_ethdev.c index 64a035c..2bb6ee9 100644 --- a/drivers/net/vmxnet3/vmxnet3_ethdev.c +++ b/drivers/net/vmxnet3/vmxnet3_ethdev.c @@ -739,6 +739,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 e39c23e..28112f7 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 017e24b..08881de 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_FIXED (0 << 0) /**< Disable autoneg (fixed speed) */ +#define ETH_LINK_SPEED_AUTONEG (1 << 0) /**< Autonegotiate (all speeds) */ #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 -- 2.7.0