ethdev: redesign link speed config
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 <marcdevel@gmail.com> Tested-by: Nelio Laranjeiro <nelio.laranjeiro@6wind.com> Signed-off-by: Thomas Monjalon <thomas.monjalon@6wind.com> Tested-by: Beilei Xing <beilei.xing@intel.com> Tested-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>
This commit is contained in:
parent
e274f57322
commit
82113036e4
@ -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);
|
||||
}
|
||||
|
@ -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]
|
||||
|
@ -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
|
||||
@ -472,6 +478,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``.
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
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_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
|
||||
}
|
||||
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_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
|
||||
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
|
||||
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)) {
|
||||
@ -695,9 +688,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,13 +1099,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);
|
||||
|
||||
|
@ -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
|
||||
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_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
|
||||
}
|
||||
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_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
|
||||
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
|
||||
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);
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
@ -2198,30 +2200,25 @@ ixgbe_dev_start(struct rte_eth_dev *dev)
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
switch(dev->data->dev_conf.link_speed) {
|
||||
case ETH_LINK_SPEED_AUTONEG:
|
||||
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_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);
|
||||
goto error;
|
||||
} else {
|
||||
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);
|
||||
@ -3088,7 +3085,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;
|
||||
@ -3107,7 +3104,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;
|
||||
|
||||
|
@ -4736,6 +4736,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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -779,6 +779,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);
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
||||
|
@ -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,17 +280,19 @@ 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. */
|
||||
#define ETH_LINK_FIXED 0 /**< No autonegotiation. */
|
||||
#define ETH_LINK_AUTONEG 1 /**< Autonegotiated. */
|
||||
|
||||
/**
|
||||
* A structure used to configure the ring threshold registers of an RX/TX
|
||||
@ -802,10 +806,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
|
||||
|
Loading…
Reference in New Issue
Block a user