From: Ivan Malov <ivan.ma...@oktetlabs.ru> According to 'libefx' API requirements, one is allowed to apply multicast address list to the port in started state only, otherwise the new array should be copied to a local storage in order to be applied during the next port start
Fixes: 0fa0070e4391 ("net/sfc: support multicast addresses list controls") Coverity issue: 141296 Fixes: e9ddf37a507d ("net/sfc: fix setting empty multicast list") Cc: sta...@dpdk.org Signed-off-by: Ivan Malov <ivan.ma...@oktetlabs.ru> Signed-off-by: Andrew Rybchenko <arybche...@solarflare.com> Reviewed-by: Andrew Lee <a...@solarflare.com> Reviewed-by: Andy Moreton <amore...@solarflare.com> --- drivers/net/sfc/sfc.h | 4 ++++ drivers/net/sfc/sfc_ethdev.c | 35 ++++++++++++++++------------------- drivers/net/sfc/sfc_port.c | 19 +++++++++++++++++++ 3 files changed, 39 insertions(+), 19 deletions(-) diff --git a/drivers/net/sfc/sfc.h b/drivers/net/sfc/sfc.h index 655328f..0b3b318 100644 --- a/drivers/net/sfc/sfc.h +++ b/drivers/net/sfc/sfc.h @@ -150,6 +150,10 @@ struct sfc_port { boolean_t promisc; boolean_t allmulti; + unsigned int max_mcast_addrs; + unsigned int nb_mcast_addrs; + uint8_t *mcast_addrs; + rte_spinlock_t mac_stats_lock; uint64_t *mac_stats_buf; efsys_mem_t mac_stats_dma_mem; diff --git a/drivers/net/sfc/sfc_ethdev.c b/drivers/net/sfc/sfc_ethdev.c index cac01ac..135f3da 100644 --- a/drivers/net/sfc/sfc_ethdev.c +++ b/drivers/net/sfc/sfc_ethdev.c @@ -826,36 +826,33 @@ sfc_set_mc_addr_list(struct rte_eth_dev *dev, struct ether_addr *mc_addr_set, uint32_t nb_mc_addr) { struct sfc_adapter *sa = dev->data->dev_private; - uint8_t *mc_addrs_p = NULL; + struct sfc_port *port = &sa->port; + uint8_t *mc_addrs = port->mcast_addrs; int rc; unsigned int i; - if (nb_mc_addr > EFX_MAC_MULTICAST_LIST_MAX) { + if (mc_addrs == NULL) + return -ENOBUFS; + + if (nb_mc_addr > port->max_mcast_addrs) { sfc_err(sa, "too many multicast addresses: %u > %u", - nb_mc_addr, EFX_MAC_MULTICAST_LIST_MAX); + nb_mc_addr, port->max_mcast_addrs); return -EINVAL; } - if (nb_mc_addr != 0) { - uint8_t *mc_addrs; - - mc_addrs_p = rte_calloc("mc-addrs", nb_mc_addr, - EFX_MAC_ADDR_LEN, 0); - if (mc_addrs_p == NULL) - return -ENOMEM; - - mc_addrs = mc_addrs_p; - for (i = 0; i < nb_mc_addr; ++i) { - (void)rte_memcpy(mc_addrs, mc_addr_set[i].addr_bytes, - EFX_MAC_ADDR_LEN); - mc_addrs += EFX_MAC_ADDR_LEN; - } + for (i = 0; i < nb_mc_addr; ++i) { + (void)rte_memcpy(mc_addrs, mc_addr_set[i].addr_bytes, + EFX_MAC_ADDR_LEN); + mc_addrs += EFX_MAC_ADDR_LEN; } - rc = efx_mac_multicast_list_set(sa->nic, mc_addrs_p, nb_mc_addr); + port->nb_mcast_addrs = nb_mc_addr; - rte_free(mc_addrs_p); + if (sa->state != SFC_ADAPTER_STARTED) + return 0; + rc = efx_mac_multicast_list_set(sa->nic, port->mcast_addrs, + port->nb_mcast_addrs); if (rc != 0) sfc_err(sa, "cannot set multicast address list (rc = %u)", rc); diff --git a/drivers/net/sfc/sfc_port.c b/drivers/net/sfc/sfc_port.c index e2f5043..e77848d 100644 --- a/drivers/net/sfc/sfc_port.c +++ b/drivers/net/sfc/sfc_port.c @@ -153,6 +153,12 @@ sfc_port_start(struct sfc_adapter *sa) if (rc != 0) goto fail_mac_filter_set; + sfc_log_init(sa, "set multicast address list"); + rc = efx_mac_multicast_list_set(sa->nic, port->mcast_addrs, + port->nb_mcast_addrs); + if (rc != 0) + goto fail_mcast_address_list_set; + if (port->mac_stats_reset_pending) { rc = sfc_port_reset_mac_stats(sa); if (rc != 0) @@ -196,6 +202,7 @@ sfc_port_start(struct sfc_adapter *sa) 0, B_FALSE); fail_mac_stats_periodic: +fail_mcast_address_list_set: fail_mac_filter_set: fail_mac_addr_set: fail_mac_pdu_set: @@ -245,6 +252,17 @@ sfc_port_init(struct sfc_adapter *sa) else port->pdu = EFX_MAC_PDU(dev_data->mtu); + port->max_mcast_addrs = EFX_MAC_MULTICAST_LIST_MAX; + port->nb_mcast_addrs = 0; + port->mcast_addrs = rte_calloc_socket("mcast_addr_list_buf", + port->max_mcast_addrs, + EFX_MAC_ADDR_LEN, 0, + sa->socket_id); + if (port->mcast_addrs == NULL) { + rc = ENOMEM; + goto fail_mcast_addr_list_buf_alloc; + } + rte_spinlock_init(&port->mac_stats_lock); rc = ENOMEM; @@ -267,6 +285,7 @@ sfc_port_init(struct sfc_adapter *sa) fail_mac_stats_dma_alloc: rte_free(port->mac_stats_buf); fail_mac_stats_buf_alloc: +fail_mcast_addr_list_buf_alloc: sfc_log_init(sa, "failed %d", rc); return rc; } -- 2.9.3