108135eecSEdward Cree // SPDX-License-Identifier: GPL-2.0-only 208135eecSEdward Cree /**************************************************************************** 308135eecSEdward Cree * Driver for Solarflare network controllers and boards 408135eecSEdward Cree * Copyright 2019 Solarflare Communications Inc. 508135eecSEdward Cree * Copyright 2020-2022 Xilinx Inc. 608135eecSEdward Cree * 708135eecSEdward Cree * This program is free software; you can redistribute it and/or modify it 808135eecSEdward Cree * under the terms of the GNU General Public License version 2 as published 908135eecSEdward Cree * by the Free Software Foundation, incorporated herein by reference. 1008135eecSEdward Cree */ 1108135eecSEdward Cree 12a6a15acaSAlejandro Lucero #include <linux/rhashtable.h> 1308135eecSEdward Cree #include "ef100_rep.h" 14f72c38faSEdward Cree #include "ef100_netdev.h" 1508135eecSEdward Cree #include "ef100_nic.h" 16da56552dSEdward Cree #include "mae.h" 179fe00c80SEdward Cree #include "rx_common.h" 189dc0cad2SEdward Cree #include "tc_bindings.h" 1925414b2aSAlejandro Lucero #include "efx_devlink.h" 2008135eecSEdward Cree 215687eb34SEdward Cree #define EFX_EF100_REP_DRIVER "efx_ef100_rep" 225687eb34SEdward Cree 239fe00c80SEdward Cree #define EFX_REP_DEFAULT_PSEUDO_RING_SIZE 64 249fe00c80SEdward Cree 2569bb5fa7SEdward Cree static int efx_ef100_rep_poll(struct napi_struct *napi, int weight); 2669bb5fa7SEdward Cree 27e1479556SEdward Cree static int efx_ef100_rep_init_struct(struct efx_nic *efx, struct efx_rep *efv, 28e1479556SEdward Cree unsigned int i) 2908135eecSEdward Cree { 3008135eecSEdward Cree efv->parent = efx; 31e1479556SEdward Cree efv->idx = i; 3208135eecSEdward Cree INIT_LIST_HEAD(&efv->list); 3367ab160eSEdward Cree efv->dflt.fw_id = MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL; 3467ab160eSEdward Cree INIT_LIST_HEAD(&efv->dflt.acts.list); 3569bb5fa7SEdward Cree INIT_LIST_HEAD(&efv->rx_list); 3669bb5fa7SEdward Cree spin_lock_init(&efv->rx_lock); 3708135eecSEdward Cree efv->msg_enable = NETIF_MSG_DRV | NETIF_MSG_PROBE | 3808135eecSEdward Cree NETIF_MSG_LINK | NETIF_MSG_IFDOWN | 3908135eecSEdward Cree NETIF_MSG_IFUP | NETIF_MSG_RX_ERR | 4008135eecSEdward Cree NETIF_MSG_TX_ERR | NETIF_MSG_HW; 4108135eecSEdward Cree return 0; 4208135eecSEdward Cree } 4308135eecSEdward Cree 4469bb5fa7SEdward Cree static int efx_ef100_rep_open(struct net_device *net_dev) 4569bb5fa7SEdward Cree { 4669bb5fa7SEdward Cree struct efx_rep *efv = netdev_priv(net_dev); 4769bb5fa7SEdward Cree 48b48b89f9SJakub Kicinski netif_napi_add(net_dev, &efv->napi, efx_ef100_rep_poll); 4969bb5fa7SEdward Cree napi_enable(&efv->napi); 5069bb5fa7SEdward Cree return 0; 5169bb5fa7SEdward Cree } 5269bb5fa7SEdward Cree 5369bb5fa7SEdward Cree static int efx_ef100_rep_close(struct net_device *net_dev) 5469bb5fa7SEdward Cree { 5569bb5fa7SEdward Cree struct efx_rep *efv = netdev_priv(net_dev); 5669bb5fa7SEdward Cree 5769bb5fa7SEdward Cree napi_disable(&efv->napi); 5869bb5fa7SEdward Cree netif_napi_del(&efv->napi); 5969bb5fa7SEdward Cree return 0; 6069bb5fa7SEdward Cree } 6169bb5fa7SEdward Cree 62f72c38faSEdward Cree static netdev_tx_t efx_ef100_rep_xmit(struct sk_buff *skb, 63f72c38faSEdward Cree struct net_device *dev) 64f72c38faSEdward Cree { 65f72c38faSEdward Cree struct efx_rep *efv = netdev_priv(dev); 66f72c38faSEdward Cree struct efx_nic *efx = efv->parent; 67f72c38faSEdward Cree netdev_tx_t rc; 68f72c38faSEdward Cree 69f72c38faSEdward Cree /* __ef100_hard_start_xmit() will always return success even in the 70f72c38faSEdward Cree * case of TX drops, where it will increment efx's tx_dropped. The 71f72c38faSEdward Cree * efv stats really only count attempted TX, not success/failure. 72f72c38faSEdward Cree */ 73f72c38faSEdward Cree atomic64_inc(&efv->stats.tx_packets); 74f72c38faSEdward Cree atomic64_add(skb->len, &efv->stats.tx_bytes); 75f72c38faSEdward Cree netif_tx_lock(efx->net_dev); 76f72c38faSEdward Cree rc = __ef100_hard_start_xmit(skb, efx, dev, efv); 77f72c38faSEdward Cree netif_tx_unlock(efx->net_dev); 78f72c38faSEdward Cree return rc; 79f72c38faSEdward Cree } 80f72c38faSEdward Cree 81e1479556SEdward Cree static int efx_ef100_rep_get_port_parent_id(struct net_device *dev, 82e1479556SEdward Cree struct netdev_phys_item_id *ppid) 83e1479556SEdward Cree { 84e1479556SEdward Cree struct efx_rep *efv = netdev_priv(dev); 85e1479556SEdward Cree struct efx_nic *efx = efv->parent; 86e1479556SEdward Cree struct ef100_nic_data *nic_data; 87e1479556SEdward Cree 88e1479556SEdward Cree nic_data = efx->nic_data; 89e1479556SEdward Cree /* nic_data->port_id is a u8[] */ 90e1479556SEdward Cree ppid->id_len = sizeof(nic_data->port_id); 91e1479556SEdward Cree memcpy(ppid->id, nic_data->port_id, sizeof(nic_data->port_id)); 92e1479556SEdward Cree return 0; 93e1479556SEdward Cree } 94e1479556SEdward Cree 95e1479556SEdward Cree static int efx_ef100_rep_get_phys_port_name(struct net_device *dev, 96e1479556SEdward Cree char *buf, size_t len) 97e1479556SEdward Cree { 98e1479556SEdward Cree struct efx_rep *efv = netdev_priv(dev); 99e1479556SEdward Cree struct efx_nic *efx = efv->parent; 100e1479556SEdward Cree struct ef100_nic_data *nic_data; 101e1479556SEdward Cree int ret; 102e1479556SEdward Cree 103e1479556SEdward Cree nic_data = efx->nic_data; 104e1479556SEdward Cree ret = snprintf(buf, len, "p%upf%uvf%u", efx->port_num, 105e1479556SEdward Cree nic_data->pf_index, efv->idx); 106e1479556SEdward Cree if (ret >= len) 107e1479556SEdward Cree return -EOPNOTSUPP; 108e1479556SEdward Cree 109e1479556SEdward Cree return 0; 110e1479556SEdward Cree } 111e1479556SEdward Cree 1129dc0cad2SEdward Cree static int efx_ef100_rep_setup_tc(struct net_device *net_dev, 1139dc0cad2SEdward Cree enum tc_setup_type type, void *type_data) 1149dc0cad2SEdward Cree { 1159dc0cad2SEdward Cree struct efx_rep *efv = netdev_priv(net_dev); 1169dc0cad2SEdward Cree struct efx_nic *efx = efv->parent; 1179dc0cad2SEdward Cree 1189dc0cad2SEdward Cree if (type == TC_SETUP_CLSFLOWER) 1199dc0cad2SEdward Cree return efx_tc_flower(efx, net_dev, type_data, efv); 1209dc0cad2SEdward Cree if (type == TC_SETUP_BLOCK) 1219dc0cad2SEdward Cree return efx_tc_setup_block(net_dev, efx, type_data, efv); 1229dc0cad2SEdward Cree 1239dc0cad2SEdward Cree return -EOPNOTSUPP; 1249dc0cad2SEdward Cree } 1259dc0cad2SEdward Cree 126a95115c4SEdward Cree static void efx_ef100_rep_get_stats64(struct net_device *dev, 127a95115c4SEdward Cree struct rtnl_link_stats64 *stats) 128a95115c4SEdward Cree { 129a95115c4SEdward Cree struct efx_rep *efv = netdev_priv(dev); 130a95115c4SEdward Cree 131a95115c4SEdward Cree stats->rx_packets = atomic64_read(&efv->stats.rx_packets); 132a95115c4SEdward Cree stats->tx_packets = atomic64_read(&efv->stats.tx_packets); 133a95115c4SEdward Cree stats->rx_bytes = atomic64_read(&efv->stats.rx_bytes); 134a95115c4SEdward Cree stats->tx_bytes = atomic64_read(&efv->stats.tx_bytes); 135a95115c4SEdward Cree stats->rx_dropped = atomic64_read(&efv->stats.rx_dropped); 136a95115c4SEdward Cree stats->tx_errors = atomic64_read(&efv->stats.tx_errors); 137a95115c4SEdward Cree } 138a95115c4SEdward Cree 139f54a28a2SEdward Cree const struct net_device_ops efx_ef100_rep_netdev_ops = { 14069bb5fa7SEdward Cree .ndo_open = efx_ef100_rep_open, 14169bb5fa7SEdward Cree .ndo_stop = efx_ef100_rep_close, 142f72c38faSEdward Cree .ndo_start_xmit = efx_ef100_rep_xmit, 143e1479556SEdward Cree .ndo_get_port_parent_id = efx_ef100_rep_get_port_parent_id, 144e1479556SEdward Cree .ndo_get_phys_port_name = efx_ef100_rep_get_phys_port_name, 145a95115c4SEdward Cree .ndo_get_stats64 = efx_ef100_rep_get_stats64, 1469dc0cad2SEdward Cree .ndo_setup_tc = efx_ef100_rep_setup_tc, 14708135eecSEdward Cree }; 14808135eecSEdward Cree 1495687eb34SEdward Cree static void efx_ef100_rep_get_drvinfo(struct net_device *dev, 1505687eb34SEdward Cree struct ethtool_drvinfo *drvinfo) 1515687eb34SEdward Cree { 1525687eb34SEdward Cree strscpy(drvinfo->driver, EFX_EF100_REP_DRIVER, sizeof(drvinfo->driver)); 1535687eb34SEdward Cree } 1545687eb34SEdward Cree 1555687eb34SEdward Cree static u32 efx_ef100_rep_ethtool_get_msglevel(struct net_device *net_dev) 1565687eb34SEdward Cree { 1575687eb34SEdward Cree struct efx_rep *efv = netdev_priv(net_dev); 1585687eb34SEdward Cree 1595687eb34SEdward Cree return efv->msg_enable; 1605687eb34SEdward Cree } 1615687eb34SEdward Cree 1625687eb34SEdward Cree static void efx_ef100_rep_ethtool_set_msglevel(struct net_device *net_dev, 1635687eb34SEdward Cree u32 msg_enable) 1645687eb34SEdward Cree { 1655687eb34SEdward Cree struct efx_rep *efv = netdev_priv(net_dev); 1665687eb34SEdward Cree 1675687eb34SEdward Cree efv->msg_enable = msg_enable; 1685687eb34SEdward Cree } 1695687eb34SEdward Cree 1707267aa6dSEdward Cree static void efx_ef100_rep_ethtool_get_ringparam(struct net_device *net_dev, 1717267aa6dSEdward Cree struct ethtool_ringparam *ring, 1727267aa6dSEdward Cree struct kernel_ethtool_ringparam *kring, 1737267aa6dSEdward Cree struct netlink_ext_ack *ext_ack) 1747267aa6dSEdward Cree { 1757267aa6dSEdward Cree struct efx_rep *efv = netdev_priv(net_dev); 1767267aa6dSEdward Cree 1777267aa6dSEdward Cree ring->rx_max_pending = U32_MAX; 1787267aa6dSEdward Cree ring->rx_pending = efv->rx_pring_size; 1797267aa6dSEdward Cree } 1807267aa6dSEdward Cree 1817267aa6dSEdward Cree static int efx_ef100_rep_ethtool_set_ringparam(struct net_device *net_dev, 1827267aa6dSEdward Cree struct ethtool_ringparam *ring, 1837267aa6dSEdward Cree struct kernel_ethtool_ringparam *kring, 1847267aa6dSEdward Cree struct netlink_ext_ack *ext_ack) 1857267aa6dSEdward Cree { 1867267aa6dSEdward Cree struct efx_rep *efv = netdev_priv(net_dev); 1877267aa6dSEdward Cree 1887267aa6dSEdward Cree if (ring->rx_mini_pending || ring->rx_jumbo_pending || ring->tx_pending) 1897267aa6dSEdward Cree return -EINVAL; 1907267aa6dSEdward Cree 1917267aa6dSEdward Cree efv->rx_pring_size = ring->rx_pending; 1927267aa6dSEdward Cree return 0; 1937267aa6dSEdward Cree } 1947267aa6dSEdward Cree 19508135eecSEdward Cree static const struct ethtool_ops efx_ef100_rep_ethtool_ops = { 1965687eb34SEdward Cree .get_drvinfo = efx_ef100_rep_get_drvinfo, 1975687eb34SEdward Cree .get_msglevel = efx_ef100_rep_ethtool_get_msglevel, 1985687eb34SEdward Cree .set_msglevel = efx_ef100_rep_ethtool_set_msglevel, 1997267aa6dSEdward Cree .get_ringparam = efx_ef100_rep_ethtool_get_ringparam, 2007267aa6dSEdward Cree .set_ringparam = efx_ef100_rep_ethtool_set_ringparam, 20108135eecSEdward Cree }; 20208135eecSEdward Cree 20308135eecSEdward Cree static struct efx_rep *efx_ef100_rep_create_netdev(struct efx_nic *efx, 20408135eecSEdward Cree unsigned int i) 20508135eecSEdward Cree { 20608135eecSEdward Cree struct net_device *net_dev; 20708135eecSEdward Cree struct efx_rep *efv; 20808135eecSEdward Cree int rc; 20908135eecSEdward Cree 21008135eecSEdward Cree net_dev = alloc_etherdev_mq(sizeof(*efv), 1); 21108135eecSEdward Cree if (!net_dev) 21208135eecSEdward Cree return ERR_PTR(-ENOMEM); 21308135eecSEdward Cree 21408135eecSEdward Cree efv = netdev_priv(net_dev); 215e1479556SEdward Cree rc = efx_ef100_rep_init_struct(efx, efv, i); 21608135eecSEdward Cree if (rc) 21708135eecSEdward Cree goto fail1; 21808135eecSEdward Cree efv->net_dev = net_dev; 21908135eecSEdward Cree rtnl_lock(); 22008135eecSEdward Cree spin_lock_bh(&efx->vf_reps_lock); 22108135eecSEdward Cree list_add_tail(&efv->list, &efx->vf_reps); 22208135eecSEdward Cree spin_unlock_bh(&efx->vf_reps_lock); 22384e7fc25SEdward Cree if (netif_running(efx->net_dev) && efx->state == STATE_NET_UP) { 22484e7fc25SEdward Cree netif_device_attach(net_dev); 22584e7fc25SEdward Cree netif_carrier_on(net_dev); 22684e7fc25SEdward Cree } else { 22708135eecSEdward Cree netif_carrier_off(net_dev); 22808135eecSEdward Cree netif_tx_stop_all_queues(net_dev); 22984e7fc25SEdward Cree } 23008135eecSEdward Cree rtnl_unlock(); 23108135eecSEdward Cree 23208135eecSEdward Cree net_dev->netdev_ops = &efx_ef100_rep_netdev_ops; 23308135eecSEdward Cree net_dev->ethtool_ops = &efx_ef100_rep_ethtool_ops; 23408135eecSEdward Cree net_dev->min_mtu = EFX_MIN_MTU; 23508135eecSEdward Cree net_dev->max_mtu = EFX_MAX_MTU; 236f72c38faSEdward Cree net_dev->features |= NETIF_F_LLTX; 237f72c38faSEdward Cree net_dev->hw_features |= NETIF_F_LLTX; 23808135eecSEdward Cree return efv; 23908135eecSEdward Cree fail1: 24008135eecSEdward Cree free_netdev(net_dev); 24108135eecSEdward Cree return ERR_PTR(rc); 24208135eecSEdward Cree } 24308135eecSEdward Cree 244da56552dSEdward Cree static int efx_ef100_configure_rep(struct efx_rep *efv) 245da56552dSEdward Cree { 246da56552dSEdward Cree struct efx_nic *efx = efv->parent; 247da56552dSEdward Cree int rc; 248da56552dSEdward Cree 2499fe00c80SEdward Cree efv->rx_pring_size = EFX_REP_DEFAULT_PSEUDO_RING_SIZE; 250da56552dSEdward Cree /* Look up actual mport ID */ 2515227adffSAlejandro Lucero rc = efx_mae_lookup_mport(efx, efv->idx, &efv->mport); 252da56552dSEdward Cree if (rc) 253da56552dSEdward Cree return rc; 254da56552dSEdward Cree pci_dbg(efx->pci_dev, "VF %u has mport ID %#x\n", efv->idx, efv->mport); 255da56552dSEdward Cree /* mport label should fit in 16 bits */ 256da56552dSEdward Cree WARN_ON(efv->mport >> 16); 257da56552dSEdward Cree 25867ab160eSEdward Cree return efx_tc_configure_default_rule_rep(efv); 25967ab160eSEdward Cree } 26067ab160eSEdward Cree 26167ab160eSEdward Cree static void efx_ef100_deconfigure_rep(struct efx_rep *efv) 26267ab160eSEdward Cree { 26367ab160eSEdward Cree struct efx_nic *efx = efv->parent; 26467ab160eSEdward Cree 26567ab160eSEdward Cree efx_tc_deconfigure_default_rule(efx, &efv->dflt); 266da56552dSEdward Cree } 267da56552dSEdward Cree 26808135eecSEdward Cree static void efx_ef100_rep_destroy_netdev(struct efx_rep *efv) 26908135eecSEdward Cree { 27008135eecSEdward Cree struct efx_nic *efx = efv->parent; 27108135eecSEdward Cree 27284e7fc25SEdward Cree rtnl_lock(); 27308135eecSEdward Cree spin_lock_bh(&efx->vf_reps_lock); 27408135eecSEdward Cree list_del(&efv->list); 27508135eecSEdward Cree spin_unlock_bh(&efx->vf_reps_lock); 27684e7fc25SEdward Cree rtnl_unlock(); 277f50e8fcdSEdward Cree synchronize_rcu(); 27808135eecSEdward Cree free_netdev(efv->net_dev); 27908135eecSEdward Cree } 28008135eecSEdward Cree 28108135eecSEdward Cree int efx_ef100_vfrep_create(struct efx_nic *efx, unsigned int i) 28208135eecSEdward Cree { 28308135eecSEdward Cree struct efx_rep *efv; 28408135eecSEdward Cree int rc; 28508135eecSEdward Cree 28608135eecSEdward Cree efv = efx_ef100_rep_create_netdev(efx, i); 28708135eecSEdward Cree if (IS_ERR(efv)) { 28808135eecSEdward Cree rc = PTR_ERR(efv); 28908135eecSEdward Cree pci_err(efx->pci_dev, 29008135eecSEdward Cree "Failed to create representor for VF %d, rc %d\n", i, 29108135eecSEdward Cree rc); 29208135eecSEdward Cree return rc; 29308135eecSEdward Cree } 294da56552dSEdward Cree rc = efx_ef100_configure_rep(efv); 295da56552dSEdward Cree if (rc) { 296da56552dSEdward Cree pci_err(efx->pci_dev, 297da56552dSEdward Cree "Failed to configure representor for VF %d, rc %d\n", 298da56552dSEdward Cree i, rc); 29967ab160eSEdward Cree goto fail1; 300da56552dSEdward Cree } 30125414b2aSAlejandro Lucero ef100_rep_set_devlink_port(efv); 30208135eecSEdward Cree rc = register_netdev(efv->net_dev); 30308135eecSEdward Cree if (rc) { 30408135eecSEdward Cree pci_err(efx->pci_dev, 30508135eecSEdward Cree "Failed to register representor for VF %d, rc %d\n", 30608135eecSEdward Cree i, rc); 30767ab160eSEdward Cree goto fail2; 30808135eecSEdward Cree } 30908135eecSEdward Cree pci_dbg(efx->pci_dev, "Representor for VF %d is %s\n", i, 31008135eecSEdward Cree efv->net_dev->name); 31108135eecSEdward Cree return 0; 31267ab160eSEdward Cree fail2: 31325414b2aSAlejandro Lucero ef100_rep_unset_devlink_port(efv); 31467ab160eSEdward Cree efx_ef100_deconfigure_rep(efv); 31567ab160eSEdward Cree fail1: 31608135eecSEdward Cree efx_ef100_rep_destroy_netdev(efv); 31708135eecSEdward Cree return rc; 31808135eecSEdward Cree } 31908135eecSEdward Cree 32008135eecSEdward Cree void efx_ef100_vfrep_destroy(struct efx_nic *efx, struct efx_rep *efv) 32108135eecSEdward Cree { 32208135eecSEdward Cree struct net_device *rep_dev; 32308135eecSEdward Cree 32408135eecSEdward Cree rep_dev = efv->net_dev; 32508135eecSEdward Cree if (!rep_dev) 32608135eecSEdward Cree return; 32708135eecSEdward Cree netif_dbg(efx, drv, rep_dev, "Removing VF representor\n"); 32808135eecSEdward Cree unregister_netdev(rep_dev); 32925414b2aSAlejandro Lucero ef100_rep_unset_devlink_port(efv); 33067ab160eSEdward Cree efx_ef100_deconfigure_rep(efv); 33108135eecSEdward Cree efx_ef100_rep_destroy_netdev(efv); 33208135eecSEdward Cree } 33308135eecSEdward Cree 33408135eecSEdward Cree void efx_ef100_fini_vfreps(struct efx_nic *efx) 33508135eecSEdward Cree { 33608135eecSEdward Cree struct ef100_nic_data *nic_data = efx->nic_data; 33708135eecSEdward Cree struct efx_rep *efv, *next; 33808135eecSEdward Cree 33908135eecSEdward Cree if (!nic_data->grp_mae) 34008135eecSEdward Cree return; 34108135eecSEdward Cree 34208135eecSEdward Cree list_for_each_entry_safe(efv, next, &efx->vf_reps, list) 34308135eecSEdward Cree efx_ef100_vfrep_destroy(efx, efv); 34408135eecSEdward Cree } 34569bb5fa7SEdward Cree 34625414b2aSAlejandro Lucero static bool ef100_mport_is_pcie_vnic(struct mae_mport_desc *mport_desc) 34725414b2aSAlejandro Lucero { 34825414b2aSAlejandro Lucero return mport_desc->mport_type == MAE_MPORT_DESC_MPORT_TYPE_VNIC && 34925414b2aSAlejandro Lucero mport_desc->vnic_client_type == MAE_MPORT_DESC_VNIC_CLIENT_TYPE_FUNCTION; 35025414b2aSAlejandro Lucero } 35125414b2aSAlejandro Lucero 35225414b2aSAlejandro Lucero bool ef100_mport_on_local_intf(struct efx_nic *efx, 35325414b2aSAlejandro Lucero struct mae_mport_desc *mport_desc) 35425414b2aSAlejandro Lucero { 35525414b2aSAlejandro Lucero struct ef100_nic_data *nic_data = efx->nic_data; 35625414b2aSAlejandro Lucero bool pcie_func; 35725414b2aSAlejandro Lucero 35825414b2aSAlejandro Lucero pcie_func = ef100_mport_is_pcie_vnic(mport_desc); 35925414b2aSAlejandro Lucero 36025414b2aSAlejandro Lucero return nic_data->have_local_intf && pcie_func && 36125414b2aSAlejandro Lucero mport_desc->interface_idx == nic_data->local_mae_intf; 36225414b2aSAlejandro Lucero } 36325414b2aSAlejandro Lucero 364*fa78b017SAlejandro Lucero bool ef100_mport_is_vf(struct mae_mport_desc *mport_desc) 365*fa78b017SAlejandro Lucero { 366*fa78b017SAlejandro Lucero bool pcie_func; 367*fa78b017SAlejandro Lucero 368*fa78b017SAlejandro Lucero pcie_func = ef100_mport_is_pcie_vnic(mport_desc); 369*fa78b017SAlejandro Lucero return pcie_func && (mport_desc->vf_idx != MAE_MPORT_DESC_VF_IDX_NULL); 370*fa78b017SAlejandro Lucero } 371*fa78b017SAlejandro Lucero 372a6a15acaSAlejandro Lucero void efx_ef100_init_reps(struct efx_nic *efx) 373a6a15acaSAlejandro Lucero { 374a6a15acaSAlejandro Lucero struct ef100_nic_data *nic_data = efx->nic_data; 375a6a15acaSAlejandro Lucero int rc; 376a6a15acaSAlejandro Lucero 377a6a15acaSAlejandro Lucero nic_data->have_local_intf = false; 378a6a15acaSAlejandro Lucero rc = efx_mae_enumerate_mports(efx); 379a6a15acaSAlejandro Lucero if (rc) 380a6a15acaSAlejandro Lucero pci_warn(efx->pci_dev, 381a6a15acaSAlejandro Lucero "Could not enumerate mports (rc=%d), are we admin?", 382a6a15acaSAlejandro Lucero rc); 383a6a15acaSAlejandro Lucero } 384a6a15acaSAlejandro Lucero 385a6a15acaSAlejandro Lucero void efx_ef100_fini_reps(struct efx_nic *efx) 386a6a15acaSAlejandro Lucero { 387a6a15acaSAlejandro Lucero struct efx_mae *mae = efx->mae; 388a6a15acaSAlejandro Lucero 389a6a15acaSAlejandro Lucero rhashtable_free_and_destroy(&mae->mports_ht, efx_mae_remove_mport, 390a6a15acaSAlejandro Lucero NULL); 391a6a15acaSAlejandro Lucero } 392a6a15acaSAlejandro Lucero 39369bb5fa7SEdward Cree static int efx_ef100_rep_poll(struct napi_struct *napi, int weight) 39469bb5fa7SEdward Cree { 39569bb5fa7SEdward Cree struct efx_rep *efv = container_of(napi, struct efx_rep, napi); 39669bb5fa7SEdward Cree unsigned int read_index; 39769bb5fa7SEdward Cree struct list_head head; 39869bb5fa7SEdward Cree struct sk_buff *skb; 39969bb5fa7SEdward Cree bool need_resched; 40069bb5fa7SEdward Cree int spent = 0; 40169bb5fa7SEdward Cree 40269bb5fa7SEdward Cree INIT_LIST_HEAD(&head); 40369bb5fa7SEdward Cree /* Grab up to 'weight' pending SKBs */ 40469bb5fa7SEdward Cree spin_lock_bh(&efv->rx_lock); 40569bb5fa7SEdward Cree read_index = efv->write_index; 40669bb5fa7SEdward Cree while (spent < weight && !list_empty(&efv->rx_list)) { 40769bb5fa7SEdward Cree skb = list_first_entry(&efv->rx_list, struct sk_buff, list); 40869bb5fa7SEdward Cree list_del(&skb->list); 40969bb5fa7SEdward Cree list_add_tail(&skb->list, &head); 41069bb5fa7SEdward Cree spent++; 41169bb5fa7SEdward Cree } 41269bb5fa7SEdward Cree spin_unlock_bh(&efv->rx_lock); 41369bb5fa7SEdward Cree /* Receive them */ 41469bb5fa7SEdward Cree netif_receive_skb_list(&head); 41569bb5fa7SEdward Cree if (spent < weight) 41669bb5fa7SEdward Cree if (napi_complete_done(napi, spent)) { 41769bb5fa7SEdward Cree spin_lock_bh(&efv->rx_lock); 41869bb5fa7SEdward Cree efv->read_index = read_index; 41969bb5fa7SEdward Cree /* If write_index advanced while we were doing the 42069bb5fa7SEdward Cree * RX, then storing our read_index won't re-prime the 42169bb5fa7SEdward Cree * fake-interrupt. In that case, we need to schedule 42269bb5fa7SEdward Cree * NAPI again to consume the additional packet(s). 42369bb5fa7SEdward Cree */ 42469bb5fa7SEdward Cree need_resched = efv->write_index != read_index; 42569bb5fa7SEdward Cree spin_unlock_bh(&efv->rx_lock); 42669bb5fa7SEdward Cree if (need_resched) 42769bb5fa7SEdward Cree napi_schedule(&efv->napi); 42869bb5fa7SEdward Cree } 42969bb5fa7SEdward Cree return spent; 43069bb5fa7SEdward Cree } 4319fe00c80SEdward Cree 4329fe00c80SEdward Cree void efx_ef100_rep_rx_packet(struct efx_rep *efv, struct efx_rx_buffer *rx_buf) 4339fe00c80SEdward Cree { 4349fe00c80SEdward Cree u8 *eh = efx_rx_buf_va(rx_buf); 4359fe00c80SEdward Cree struct sk_buff *skb; 4369fe00c80SEdward Cree bool primed; 4379fe00c80SEdward Cree 4389fe00c80SEdward Cree /* Don't allow too many queued SKBs to build up, as they consume 4399fe00c80SEdward Cree * GFP_ATOMIC memory. If we overrun, just start dropping. 4409fe00c80SEdward Cree */ 4419fe00c80SEdward Cree if (efv->write_index - READ_ONCE(efv->read_index) > efv->rx_pring_size) { 4429fe00c80SEdward Cree atomic64_inc(&efv->stats.rx_dropped); 4439fe00c80SEdward Cree if (net_ratelimit()) 4449fe00c80SEdward Cree netif_dbg(efv->parent, rx_err, efv->net_dev, 4459fe00c80SEdward Cree "nodesc-dropped packet of length %u\n", 4469fe00c80SEdward Cree rx_buf->len); 4479fe00c80SEdward Cree return; 4489fe00c80SEdward Cree } 4499fe00c80SEdward Cree 4509fe00c80SEdward Cree skb = netdev_alloc_skb(efv->net_dev, rx_buf->len); 4519fe00c80SEdward Cree if (!skb) { 4529fe00c80SEdward Cree atomic64_inc(&efv->stats.rx_dropped); 4539fe00c80SEdward Cree if (net_ratelimit()) 4549fe00c80SEdward Cree netif_dbg(efv->parent, rx_err, efv->net_dev, 4559fe00c80SEdward Cree "noskb-dropped packet of length %u\n", 4569fe00c80SEdward Cree rx_buf->len); 4579fe00c80SEdward Cree return; 4589fe00c80SEdward Cree } 4599fe00c80SEdward Cree memcpy(skb->data, eh, rx_buf->len); 4609fe00c80SEdward Cree __skb_put(skb, rx_buf->len); 4619fe00c80SEdward Cree 4629fe00c80SEdward Cree skb_record_rx_queue(skb, 0); /* rep is single-queue */ 4639fe00c80SEdward Cree 4649fe00c80SEdward Cree /* Move past the ethernet header */ 4659fe00c80SEdward Cree skb->protocol = eth_type_trans(skb, efv->net_dev); 4669fe00c80SEdward Cree 4679fe00c80SEdward Cree skb_checksum_none_assert(skb); 4689fe00c80SEdward Cree 4699fe00c80SEdward Cree atomic64_inc(&efv->stats.rx_packets); 4709fe00c80SEdward Cree atomic64_add(rx_buf->len, &efv->stats.rx_bytes); 4719fe00c80SEdward Cree 4729fe00c80SEdward Cree /* Add it to the rx list */ 4739fe00c80SEdward Cree spin_lock_bh(&efv->rx_lock); 4749fe00c80SEdward Cree primed = efv->read_index == efv->write_index; 4759fe00c80SEdward Cree list_add_tail(&skb->list, &efv->rx_list); 4769fe00c80SEdward Cree efv->write_index++; 4779fe00c80SEdward Cree spin_unlock_bh(&efv->rx_lock); 4789fe00c80SEdward Cree /* Trigger rx work */ 4799fe00c80SEdward Cree if (primed) 4809fe00c80SEdward Cree napi_schedule(&efv->napi); 4819fe00c80SEdward Cree } 482f50e8fcdSEdward Cree 483f50e8fcdSEdward Cree struct efx_rep *efx_ef100_find_rep_by_mport(struct efx_nic *efx, u16 mport) 484f50e8fcdSEdward Cree { 485f50e8fcdSEdward Cree struct efx_rep *efv, *out = NULL; 486f50e8fcdSEdward Cree 487f50e8fcdSEdward Cree /* spinlock guards against list mutation while we're walking it; 488f50e8fcdSEdward Cree * but caller must also hold rcu_read_lock() to ensure the netdev 489f50e8fcdSEdward Cree * isn't freed after we drop the spinlock. 490f50e8fcdSEdward Cree */ 491f50e8fcdSEdward Cree spin_lock_bh(&efx->vf_reps_lock); 492f50e8fcdSEdward Cree list_for_each_entry(efv, &efx->vf_reps, list) 493f50e8fcdSEdward Cree if (efv->mport == mport) { 494f50e8fcdSEdward Cree out = efv; 495f50e8fcdSEdward Cree break; 496f50e8fcdSEdward Cree } 497f50e8fcdSEdward Cree spin_unlock_bh(&efx->vf_reps_lock); 498f50e8fcdSEdward Cree return out; 499f50e8fcdSEdward Cree } 500