From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wm0-f45.google.com (mail-wm0-f45.google.com [74.125.82.45]) by dpdk.org (Postfix) with ESMTP id ABEB65902 for ; Thu, 17 Mar 2016 19:10:54 +0100 (CET) Received: by mail-wm0-f45.google.com with SMTP id p65so37768348wmp.1 for ; Thu, 17 Mar 2016 11:10:54 -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=K/zZImjmdCmw2DIQsOWhAUp9avL5eAkoFIM/8Kmm2nU=; b=DBD7pv6Al9UwUomm6g53BluS9+cQJ5h8ncI7fG+L5TmDmRi1VWLUJCeKRPSVxIjeBq 5xCNqjIa7PIQgqMDVIWAZdlPOao3nVy7XwmDtVL0LNL/M2fl4U3VAzMF0gKMie+2cUsd AhFS+XdYEVhSu5GeVayljB59lQnmR48fOkhn9jc9cclPxbclteJGgA8VR3vODu2DSl9c C+HNhVYCO13+w9vUQgG8PauRp4BP9KfqX7sH+g4lBtphOWUZign5iERtWhX0fDioIXF3 7DQuktiYYH+sXiTpqL6Gl2csDRRFUWou0suwepbV1Dl6CIIApG65ouJ/HA0EaNPjJ/Zq e36w== 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=K/zZImjmdCmw2DIQsOWhAUp9avL5eAkoFIM/8Kmm2nU=; b=PQE1M4fl7bE9Z/NWpOTxT1DAOaxe+F3YCHmoENikFVu9O12NMFODX7qwgSPsTF005e 1dtcw3eIksj9FNI1t4ACbR9eJoh919NCVstY0Gkp5/YIGK5ZWi8yPFU/a35vC9k4mYtm HEfEgzdMkRAl4HPdld8LgxxRY2C30YlwFZcNjEBPDWsxWd8r9sm2jxLEJrlnPHHPy+91 9WmBazRdZi3nAygSuDqXrl8l6HXxh5HfcHDIMkozIBf4ZM6aAJ0rlgkTQZHnMBToYauQ /+lqu2ot5mFZsZfP3RzBeI+n7r4JLzMqCgx0ODSwp5gPekHcGt/3uH3iy5GcYkneunbY qhgw== X-Gm-Message-State: AD7BkJIAMMkKXHaX+YmnIWzpxLMxbrwDI16vDu7jqwgZWjcOSUMwu6mZQUt+9RkIL+bXhL9u X-Received: by 10.194.78.37 with SMTP id y5mr11450164wjw.78.1458238254547; Thu, 17 Mar 2016 11:10:54 -0700 (PDT) Received: from XPS13.localdomain (91.111.75.86.rev.sfr.net. [86.75.111.91]) by smtp.gmail.com with ESMTPSA id u14sm31196179wmu.8.2016.03.17.11.10.51 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 17 Mar 2016 11:10:53 -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: Thu, 17 Mar 2016 19:09:03 +0100 Message-Id: <1458238145-7496-7-git-send-email-thomas.monjalon@6wind.com> X-Mailer: git-send-email 2.7.0 In-Reply-To: <1458238145-7496-1-git-send-email-thomas.monjalon@6wind.com> References: <1457992546-32230-1-git-send-email-thomas.monjalon@6wind.com> <1458238145-7496-1-git-send-email-thomas.monjalon@6wind.com> Subject: [dpdk-dev] [PATCH v11 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: Thu, 17 Mar 2016 18:10:55 -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 --- 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, 196 insertions(+), 183 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 6ecd304..6540941 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. + * **Restored vmxnet3 Tx data ring.** Tx data ring has been shown to improve small pkt forwarding performance @@ -402,6 +408,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 607d2f4..71c2360 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 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 2a50857..70326e1 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_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)) { @@ -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; } @@ -1107,8 +1099,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 == 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 ? 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 b7e706a..2208d48 100644 --- a/drivers/net/e1000/igb_ethdev.c +++ b/drivers/net/e1000/igb_ethdev.c @@ -1130,6 +1130,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(); @@ -1230,48 +1233,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)) { @@ -1303,9 +1304,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; } @@ -2032,13 +2032,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 dee7ef7..d71d840 100644 --- a/drivers/net/i40e/i40e_ethdev.c +++ b/drivers/net/i40e/i40e_ethdev.c @@ -1367,27 +1367,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; } @@ -1413,9 +1406,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; @@ -1435,10 +1428,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; } @@ -1511,6 +1502,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"); @@ -1795,6 +1792,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 f2b37a2..cb8b6cf 100644 --- a/drivers/net/i40e/i40e_ethdev_vf.c +++ b/drivers/net/i40e/i40e_ethdev_vf.c @@ -1953,12 +1953,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 3d2e801..861b9b9 100644 --- a/drivers/net/ixgbe/ixgbe_ethdev.c +++ b/drivers/net/ixgbe/ixgbe_ethdev.c @@ -2074,14 +2074,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; } @@ -2173,32 +2172,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; @@ -3019,7 +3007,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; @@ -3038,7 +3026,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 3a4a989..10e29e2 100644 --- a/drivers/net/mlx4/mlx4.c +++ b/drivers/net/mlx4/mlx4.c @@ -4687,6 +4687,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 960d468..d5ab7dc 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 854cb5c..0708e4a 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 ad8029b..076de7a 100644 --- a/drivers/net/vmxnet3/vmxnet3_ethdev.c +++ b/drivers/net/vmxnet3/vmxnet3_ethdev.c @@ -763,6 +763,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 7aa39f9..470e434 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