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
efx_ef100_rep_init_struct(struct efx_nic * efx,struct efx_rep * efv,unsigned int i)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
efx_ef100_rep_open(struct net_device * net_dev)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
efx_ef100_rep_close(struct net_device * net_dev)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
efx_ef100_rep_xmit(struct sk_buff * skb,struct net_device * dev)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
efx_ef100_rep_get_port_parent_id(struct net_device * dev,struct netdev_phys_item_id * ppid)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
efx_ef100_rep_get_phys_port_name(struct net_device * dev,char * buf,size_t len)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
efx_ef100_rep_setup_tc(struct net_device * net_dev,enum tc_setup_type type,void * type_data)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
efx_ef100_rep_get_stats64(struct net_device * dev,struct rtnl_link_stats64 * stats)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
efx_ef100_rep_get_drvinfo(struct net_device * dev,struct ethtool_drvinfo * drvinfo)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
efx_ef100_rep_ethtool_get_msglevel(struct net_device * net_dev)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
efx_ef100_rep_ethtool_set_msglevel(struct net_device * net_dev,u32 msg_enable)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
efx_ef100_rep_ethtool_get_ringparam(struct net_device * net_dev,struct ethtool_ringparam * ring,struct kernel_ethtool_ringparam * kring,struct netlink_ext_ack * ext_ack)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
efx_ef100_rep_ethtool_set_ringparam(struct net_device * net_dev,struct ethtool_ringparam * ring,struct kernel_ethtool_ringparam * kring,struct netlink_ext_ack * ext_ack)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
efx_ef100_rep_create_netdev(struct efx_nic * efx,unsigned int i)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
efx_ef100_configure_rep(struct efx_rep * efv)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
efx_ef100_deconfigure_rep(struct efx_rep * efv)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
efx_ef100_rep_destroy_netdev(struct efx_rep * efv)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
efx_ef100_vfrep_create(struct efx_nic * efx,unsigned int i)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
efx_ef100_vfrep_destroy(struct efx_nic * efx,struct efx_rep * efv)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
efx_ef100_fini_vfreps(struct efx_nic * efx)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
ef100_mport_is_pcie_vnic(struct mae_mport_desc * mport_desc)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
ef100_mport_on_local_intf(struct efx_nic * efx,struct mae_mport_desc * mport_desc)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
ef100_mport_is_vf(struct mae_mport_desc * mport_desc)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
efx_ef100_init_reps(struct efx_nic * efx)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
efx_ef100_fini_reps(struct efx_nic * efx)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
efx_ef100_rep_poll(struct napi_struct * napi,int weight)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
efx_ef100_rep_rx_packet(struct efx_rep * efv,struct efx_rx_buffer * rx_buf)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
efx_ef100_find_rep_by_mport(struct efx_nic * efx,u16 mport)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