From 295f647a38a2680de89f299adc1a50681240405a Mon Sep 17 00:00:00 2001 From: Ivan Malov Date: Thu, 9 Mar 2017 16:21:30 +0000 Subject: [PATCH] net/sfc: set multicast address list in started state only 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 Coverity issue: 141296 Fixes: 0fa0070e4391 ("net/sfc: support multicast addresses list controls") Fixes: e9ddf37a507d ("net/sfc: fix setting empty multicast list") Cc: stable@dpdk.org Signed-off-by: Ivan Malov Signed-off-by: Andrew Rybchenko Reviewed-by: Andrew Lee Reviewed-by: Andy Moreton --- 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 b782360000..6aeeda525d 100644 --- a/drivers/net/sfc/sfc.h +++ b/drivers/net/sfc/sfc.h @@ -152,6 +152,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 5297159c49..e84731acaf 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 e2f504383b..e77848d426 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 @@ fail_mac_drain: 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.20.1