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 @@ 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; }