diff --git a/doc/guides/rel_notes/release_18_11.rst b/doc/guides/rel_notes/release_18_11.rst index 3ae6b3f58b..24204e67b2 100644 --- a/doc/guides/rel_notes/release_18_11.rst +++ b/doc/guides/rel_notes/release_18_11.rst @@ -68,6 +68,12 @@ API Changes Also, make sure to start the actual text at the margin. ========================================================= +* A new device flag, RTE_ETH_DEV_NOLIVE_MAC_ADDR, changes the order of + actions inside rte_eth_dev_start regarding MAC set. Some NICs do not + support MAC changes once the port has started and with this new device + flag the MAC can be properly configured in any case. This is particularly + important for bonding. + ABI Changes ----------- diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c index f32722f361..16825bf3c1 100644 --- a/lib/librte_ethdev/rte_ethdev.c +++ b/lib/librte_ethdev/rte_ethdev.c @@ -1219,19 +1219,14 @@ _rte_eth_dev_reset(struct rte_eth_dev *dev) } static void -rte_eth_dev_config_restore(uint16_t port_id) +rte_eth_dev_mac_restore(struct rte_eth_dev *dev, + struct rte_eth_dev_info *dev_info) { - struct rte_eth_dev *dev; - struct rte_eth_dev_info dev_info; struct ether_addr *addr; uint16_t i; uint32_t pool = 0; uint64_t pool_mask; - dev = &rte_eth_devices[port_id]; - - rte_eth_dev_info_get(port_id, &dev_info); - /* replay MAC address configuration including default MAC */ addr = &dev->data->mac_addrs[0]; if (*dev->dev_ops->mac_addr_set != NULL) @@ -1240,7 +1235,7 @@ rte_eth_dev_config_restore(uint16_t port_id) (*dev->dev_ops->mac_addr_add)(dev, addr, 0, pool); if (*dev->dev_ops->mac_addr_add != NULL) { - for (i = 1; i < dev_info.max_mac_addrs; i++) { + for (i = 1; i < dev_info->max_mac_addrs; i++) { addr = &dev->data->mac_addrs[i]; /* skip zero address */ @@ -1259,6 +1254,14 @@ rte_eth_dev_config_restore(uint16_t port_id) } while (pool_mask); } } +} + +static void +rte_eth_dev_config_restore(struct rte_eth_dev *dev, + struct rte_eth_dev_info *dev_info, uint16_t port_id) +{ + if (!(*dev_info->dev_flags & RTE_ETH_DEV_NOLIVE_MAC_ADDR)) + rte_eth_dev_mac_restore(dev, dev_info); /* replay promiscuous configuration */ if (rte_eth_promiscuous_get(port_id) == 1) @@ -1277,6 +1280,7 @@ int rte_eth_dev_start(uint16_t port_id) { struct rte_eth_dev *dev; + struct rte_eth_dev_info dev_info; int diag; RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -EINVAL); @@ -1292,13 +1296,19 @@ rte_eth_dev_start(uint16_t port_id) return 0; } + rte_eth_dev_info_get(port_id, &dev_info); + + /* Lets restore MAC now if device does not support live change */ + if (*dev_info.dev_flags & RTE_ETH_DEV_NOLIVE_MAC_ADDR) + rte_eth_dev_mac_restore(dev, &dev_info); + diag = (*dev->dev_ops->dev_start)(dev); if (diag == 0) dev->data->dev_started = 1; else return eth_err(port_id, diag); - rte_eth_dev_config_restore(port_id); + rte_eth_dev_config_restore(dev, &dev_info, port_id); if (dev->data->dev_conf.intr_conf.lsc == 0) { RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->link_update, -ENOTSUP); diff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h index 7070e9ab40..fa2812bcae 100644 --- a/lib/librte_ethdev/rte_ethdev.h +++ b/lib/librte_ethdev/rte_ethdev.h @@ -1268,6 +1268,8 @@ struct rte_eth_dev_owner { #define RTE_ETH_DEV_INTR_RMV 0x0008 /** Device is port representor */ #define RTE_ETH_DEV_REPRESENTOR 0x0010 +/** Device does not support MAC change after started */ +#define RTE_ETH_DEV_NOLIVE_MAC_ADDR 0x0020 /** * Iterates over valid ethdev ports owned by a specific owner. @@ -1750,6 +1752,10 @@ int rte_eth_dev_tx_queue_stop(uint16_t port_id, uint16_t tx_queue_id); * The device start step is the last one and consists of setting the configured * offload features and in starting the transmit and the receive units of the * device. + * + * Device RTE_ETH_DEV_NOLIVE_MAC_ADDR flag causes MAC address to be set before + * PMD port start callback function is invoked. + * * On success, all basic functions exported by the Ethernet API (link status, * receive/transmit, and so on) can be invoked. *