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 
12*a6a15acaSAlejandro 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"
1908135eecSEdward Cree 
205687eb34SEdward Cree #define EFX_EF100_REP_DRIVER	"efx_ef100_rep"
215687eb34SEdward Cree 
229fe00c80SEdward Cree #define EFX_REP_DEFAULT_PSEUDO_RING_SIZE	64
239fe00c80SEdward Cree 
2469bb5fa7SEdward Cree static int efx_ef100_rep_poll(struct napi_struct *napi, int weight);
2569bb5fa7SEdward Cree 
26e1479556SEdward Cree static int efx_ef100_rep_init_struct(struct efx_nic *efx, struct efx_rep *efv,
27e1479556SEdward Cree 				     unsigned int i)
2808135eecSEdward Cree {
2908135eecSEdward Cree 	efv->parent = efx;
30e1479556SEdward Cree 	efv->idx = i;
3108135eecSEdward Cree 	INIT_LIST_HEAD(&efv->list);
3267ab160eSEdward Cree 	efv->dflt.fw_id = MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL;
3367ab160eSEdward Cree 	INIT_LIST_HEAD(&efv->dflt.acts.list);
3469bb5fa7SEdward Cree 	INIT_LIST_HEAD(&efv->rx_list);
3569bb5fa7SEdward Cree 	spin_lock_init(&efv->rx_lock);
3608135eecSEdward Cree 	efv->msg_enable = NETIF_MSG_DRV | NETIF_MSG_PROBE |
3708135eecSEdward Cree 			  NETIF_MSG_LINK | NETIF_MSG_IFDOWN |
3808135eecSEdward Cree 			  NETIF_MSG_IFUP | NETIF_MSG_RX_ERR |
3908135eecSEdward Cree 			  NETIF_MSG_TX_ERR | NETIF_MSG_HW;
4008135eecSEdward Cree 	return 0;
4108135eecSEdward Cree }
4208135eecSEdward Cree 
4369bb5fa7SEdward Cree static int efx_ef100_rep_open(struct net_device *net_dev)
4469bb5fa7SEdward Cree {
4569bb5fa7SEdward Cree 	struct efx_rep *efv = netdev_priv(net_dev);
4669bb5fa7SEdward Cree 
47b48b89f9SJakub Kicinski 	netif_napi_add(net_dev, &efv->napi, efx_ef100_rep_poll);
4869bb5fa7SEdward Cree 	napi_enable(&efv->napi);
4969bb5fa7SEdward Cree 	return 0;
5069bb5fa7SEdward Cree }
5169bb5fa7SEdward Cree 
5269bb5fa7SEdward Cree static int efx_ef100_rep_close(struct net_device *net_dev)
5369bb5fa7SEdward Cree {
5469bb5fa7SEdward Cree 	struct efx_rep *efv = netdev_priv(net_dev);
5569bb5fa7SEdward Cree 
5669bb5fa7SEdward Cree 	napi_disable(&efv->napi);
5769bb5fa7SEdward Cree 	netif_napi_del(&efv->napi);
5869bb5fa7SEdward Cree 	return 0;
5969bb5fa7SEdward Cree }
6069bb5fa7SEdward Cree 
61f72c38faSEdward Cree static netdev_tx_t efx_ef100_rep_xmit(struct sk_buff *skb,
62f72c38faSEdward Cree 				      struct net_device *dev)
63f72c38faSEdward Cree {
64f72c38faSEdward Cree 	struct efx_rep *efv = netdev_priv(dev);
65f72c38faSEdward Cree 	struct efx_nic *efx = efv->parent;
66f72c38faSEdward Cree 	netdev_tx_t rc;
67f72c38faSEdward Cree 
68f72c38faSEdward Cree 	/* __ef100_hard_start_xmit() will always return success even in the
69f72c38faSEdward Cree 	 * case of TX drops, where it will increment efx's tx_dropped.  The
70f72c38faSEdward Cree 	 * efv stats really only count attempted TX, not success/failure.
71f72c38faSEdward Cree 	 */
72f72c38faSEdward Cree 	atomic64_inc(&efv->stats.tx_packets);
73f72c38faSEdward Cree 	atomic64_add(skb->len, &efv->stats.tx_bytes);
74f72c38faSEdward Cree 	netif_tx_lock(efx->net_dev);
75f72c38faSEdward Cree 	rc = __ef100_hard_start_xmit(skb, efx, dev, efv);
76f72c38faSEdward Cree 	netif_tx_unlock(efx->net_dev);
77f72c38faSEdward Cree 	return rc;
78f72c38faSEdward Cree }
79f72c38faSEdward Cree 
80e1479556SEdward Cree static int efx_ef100_rep_get_port_parent_id(struct net_device *dev,
81e1479556SEdward Cree 					    struct netdev_phys_item_id *ppid)
82e1479556SEdward Cree {
83e1479556SEdward Cree 	struct efx_rep *efv = netdev_priv(dev);
84e1479556SEdward Cree 	struct efx_nic *efx = efv->parent;
85e1479556SEdward Cree 	struct ef100_nic_data *nic_data;
86e1479556SEdward Cree 
87e1479556SEdward Cree 	nic_data = efx->nic_data;
88e1479556SEdward Cree 	/* nic_data->port_id is a u8[] */
89e1479556SEdward Cree 	ppid->id_len = sizeof(nic_data->port_id);
90e1479556SEdward Cree 	memcpy(ppid->id, nic_data->port_id, sizeof(nic_data->port_id));
91e1479556SEdward Cree 	return 0;
92e1479556SEdward Cree }
93e1479556SEdward Cree 
94e1479556SEdward Cree static int efx_ef100_rep_get_phys_port_name(struct net_device *dev,
95e1479556SEdward Cree 					    char *buf, size_t len)
96e1479556SEdward Cree {
97e1479556SEdward Cree 	struct efx_rep *efv = netdev_priv(dev);
98e1479556SEdward Cree 	struct efx_nic *efx = efv->parent;
99e1479556SEdward Cree 	struct ef100_nic_data *nic_data;
100e1479556SEdward Cree 	int ret;
101e1479556SEdward Cree 
102e1479556SEdward Cree 	nic_data = efx->nic_data;
103e1479556SEdward Cree 	ret = snprintf(buf, len, "p%upf%uvf%u", efx->port_num,
104e1479556SEdward Cree 		       nic_data->pf_index, efv->idx);
105e1479556SEdward Cree 	if (ret >= len)
106e1479556SEdward Cree 		return -EOPNOTSUPP;
107e1479556SEdward Cree 
108e1479556SEdward Cree 	return 0;
109e1479556SEdward Cree }
110e1479556SEdward Cree 
1119dc0cad2SEdward Cree static int efx_ef100_rep_setup_tc(struct net_device *net_dev,
1129dc0cad2SEdward Cree 				  enum tc_setup_type type, void *type_data)
1139dc0cad2SEdward Cree {
1149dc0cad2SEdward Cree 	struct efx_rep *efv = netdev_priv(net_dev);
1159dc0cad2SEdward Cree 	struct efx_nic *efx = efv->parent;
1169dc0cad2SEdward Cree 
1179dc0cad2SEdward Cree 	if (type == TC_SETUP_CLSFLOWER)
1189dc0cad2SEdward Cree 		return efx_tc_flower(efx, net_dev, type_data, efv);
1199dc0cad2SEdward Cree 	if (type == TC_SETUP_BLOCK)
1209dc0cad2SEdward Cree 		return efx_tc_setup_block(net_dev, efx, type_data, efv);
1219dc0cad2SEdward Cree 
1229dc0cad2SEdward Cree 	return -EOPNOTSUPP;
1239dc0cad2SEdward Cree }
1249dc0cad2SEdward Cree 
125a95115c4SEdward Cree static void efx_ef100_rep_get_stats64(struct net_device *dev,
126a95115c4SEdward Cree 				      struct rtnl_link_stats64 *stats)
127a95115c4SEdward Cree {
128a95115c4SEdward Cree 	struct efx_rep *efv = netdev_priv(dev);
129a95115c4SEdward Cree 
130a95115c4SEdward Cree 	stats->rx_packets = atomic64_read(&efv->stats.rx_packets);
131a95115c4SEdward Cree 	stats->tx_packets = atomic64_read(&efv->stats.tx_packets);
132a95115c4SEdward Cree 	stats->rx_bytes = atomic64_read(&efv->stats.rx_bytes);
133a95115c4SEdward Cree 	stats->tx_bytes = atomic64_read(&efv->stats.tx_bytes);
134a95115c4SEdward Cree 	stats->rx_dropped = atomic64_read(&efv->stats.rx_dropped);
135a95115c4SEdward Cree 	stats->tx_errors = atomic64_read(&efv->stats.tx_errors);
136a95115c4SEdward Cree }
137a95115c4SEdward Cree 
138f54a28a2SEdward Cree const struct net_device_ops efx_ef100_rep_netdev_ops = {
13969bb5fa7SEdward Cree 	.ndo_open		= efx_ef100_rep_open,
14069bb5fa7SEdward Cree 	.ndo_stop		= efx_ef100_rep_close,
141f72c38faSEdward Cree 	.ndo_start_xmit		= efx_ef100_rep_xmit,
142e1479556SEdward Cree 	.ndo_get_port_parent_id	= efx_ef100_rep_get_port_parent_id,
143e1479556SEdward Cree 	.ndo_get_phys_port_name	= efx_ef100_rep_get_phys_port_name,
144a95115c4SEdward Cree 	.ndo_get_stats64	= efx_ef100_rep_get_stats64,
1459dc0cad2SEdward Cree 	.ndo_setup_tc		= efx_ef100_rep_setup_tc,
14608135eecSEdward Cree };
14708135eecSEdward Cree 
1485687eb34SEdward Cree static void efx_ef100_rep_get_drvinfo(struct net_device *dev,
1495687eb34SEdward Cree 				      struct ethtool_drvinfo *drvinfo)
1505687eb34SEdward Cree {
1515687eb34SEdward Cree 	strscpy(drvinfo->driver, EFX_EF100_REP_DRIVER, sizeof(drvinfo->driver));
1525687eb34SEdward Cree }
1535687eb34SEdward Cree 
1545687eb34SEdward Cree static u32 efx_ef100_rep_ethtool_get_msglevel(struct net_device *net_dev)
1555687eb34SEdward Cree {
1565687eb34SEdward Cree 	struct efx_rep *efv = netdev_priv(net_dev);
1575687eb34SEdward Cree 
1585687eb34SEdward Cree 	return efv->msg_enable;
1595687eb34SEdward Cree }
1605687eb34SEdward Cree 
1615687eb34SEdward Cree static void efx_ef100_rep_ethtool_set_msglevel(struct net_device *net_dev,
1625687eb34SEdward Cree 					       u32 msg_enable)
1635687eb34SEdward Cree {
1645687eb34SEdward Cree 	struct efx_rep *efv = netdev_priv(net_dev);
1655687eb34SEdward Cree 
1665687eb34SEdward Cree 	efv->msg_enable = msg_enable;
1675687eb34SEdward Cree }
1685687eb34SEdward Cree 
1697267aa6dSEdward Cree static void efx_ef100_rep_ethtool_get_ringparam(struct net_device *net_dev,
1707267aa6dSEdward Cree 						struct ethtool_ringparam *ring,
1717267aa6dSEdward Cree 						struct kernel_ethtool_ringparam *kring,
1727267aa6dSEdward Cree 						struct netlink_ext_ack *ext_ack)
1737267aa6dSEdward Cree {
1747267aa6dSEdward Cree 	struct efx_rep *efv = netdev_priv(net_dev);
1757267aa6dSEdward Cree 
1767267aa6dSEdward Cree 	ring->rx_max_pending = U32_MAX;
1777267aa6dSEdward Cree 	ring->rx_pending = efv->rx_pring_size;
1787267aa6dSEdward Cree }
1797267aa6dSEdward Cree 
1807267aa6dSEdward Cree static int efx_ef100_rep_ethtool_set_ringparam(struct net_device *net_dev,
1817267aa6dSEdward Cree 					       struct ethtool_ringparam *ring,
1827267aa6dSEdward Cree 					       struct kernel_ethtool_ringparam *kring,
1837267aa6dSEdward Cree 					       struct netlink_ext_ack *ext_ack)
1847267aa6dSEdward Cree {
1857267aa6dSEdward Cree 	struct efx_rep *efv = netdev_priv(net_dev);
1867267aa6dSEdward Cree 
1877267aa6dSEdward Cree 	if (ring->rx_mini_pending || ring->rx_jumbo_pending || ring->tx_pending)
1887267aa6dSEdward Cree 		return -EINVAL;
1897267aa6dSEdward Cree 
1907267aa6dSEdward Cree 	efv->rx_pring_size = ring->rx_pending;
1917267aa6dSEdward Cree 	return 0;
1927267aa6dSEdward Cree }
1937267aa6dSEdward Cree 
19408135eecSEdward Cree static const struct ethtool_ops efx_ef100_rep_ethtool_ops = {
1955687eb34SEdward Cree 	.get_drvinfo		= efx_ef100_rep_get_drvinfo,
1965687eb34SEdward Cree 	.get_msglevel		= efx_ef100_rep_ethtool_get_msglevel,
1975687eb34SEdward Cree 	.set_msglevel		= efx_ef100_rep_ethtool_set_msglevel,
1987267aa6dSEdward Cree 	.get_ringparam		= efx_ef100_rep_ethtool_get_ringparam,
1997267aa6dSEdward Cree 	.set_ringparam		= efx_ef100_rep_ethtool_set_ringparam,
20008135eecSEdward Cree };
20108135eecSEdward Cree 
20208135eecSEdward Cree static struct efx_rep *efx_ef100_rep_create_netdev(struct efx_nic *efx,
20308135eecSEdward Cree 						   unsigned int i)
20408135eecSEdward Cree {
20508135eecSEdward Cree 	struct net_device *net_dev;
20608135eecSEdward Cree 	struct efx_rep *efv;
20708135eecSEdward Cree 	int rc;
20808135eecSEdward Cree 
20908135eecSEdward Cree 	net_dev = alloc_etherdev_mq(sizeof(*efv), 1);
21008135eecSEdward Cree 	if (!net_dev)
21108135eecSEdward Cree 		return ERR_PTR(-ENOMEM);
21208135eecSEdward Cree 
21308135eecSEdward Cree 	efv = netdev_priv(net_dev);
214e1479556SEdward Cree 	rc = efx_ef100_rep_init_struct(efx, efv, i);
21508135eecSEdward Cree 	if (rc)
21608135eecSEdward Cree 		goto fail1;
21708135eecSEdward Cree 	efv->net_dev = net_dev;
21808135eecSEdward Cree 	rtnl_lock();
21908135eecSEdward Cree 	spin_lock_bh(&efx->vf_reps_lock);
22008135eecSEdward Cree 	list_add_tail(&efv->list, &efx->vf_reps);
22108135eecSEdward Cree 	spin_unlock_bh(&efx->vf_reps_lock);
22284e7fc25SEdward Cree 	if (netif_running(efx->net_dev) && efx->state == STATE_NET_UP) {
22384e7fc25SEdward Cree 		netif_device_attach(net_dev);
22484e7fc25SEdward Cree 		netif_carrier_on(net_dev);
22584e7fc25SEdward Cree 	} else {
22608135eecSEdward Cree 		netif_carrier_off(net_dev);
22708135eecSEdward Cree 		netif_tx_stop_all_queues(net_dev);
22884e7fc25SEdward Cree 	}
22908135eecSEdward Cree 	rtnl_unlock();
23008135eecSEdward Cree 
23108135eecSEdward Cree 	net_dev->netdev_ops = &efx_ef100_rep_netdev_ops;
23208135eecSEdward Cree 	net_dev->ethtool_ops = &efx_ef100_rep_ethtool_ops;
23308135eecSEdward Cree 	net_dev->min_mtu = EFX_MIN_MTU;
23408135eecSEdward Cree 	net_dev->max_mtu = EFX_MAX_MTU;
235f72c38faSEdward Cree 	net_dev->features |= NETIF_F_LLTX;
236f72c38faSEdward Cree 	net_dev->hw_features |= NETIF_F_LLTX;
23708135eecSEdward Cree 	return efv;
23808135eecSEdward Cree fail1:
23908135eecSEdward Cree 	free_netdev(net_dev);
24008135eecSEdward Cree 	return ERR_PTR(rc);
24108135eecSEdward Cree }
24208135eecSEdward Cree 
243da56552dSEdward Cree static int efx_ef100_configure_rep(struct efx_rep *efv)
244da56552dSEdward Cree {
245da56552dSEdward Cree 	struct efx_nic *efx = efv->parent;
246da56552dSEdward Cree 	u32 selector;
247da56552dSEdward Cree 	int rc;
248da56552dSEdward Cree 
2499fe00c80SEdward Cree 	efv->rx_pring_size = EFX_REP_DEFAULT_PSEUDO_RING_SIZE;
250da56552dSEdward Cree 	/* Construct mport selector for corresponding VF */
251da56552dSEdward Cree 	efx_mae_mport_vf(efx, efv->idx, &selector);
252da56552dSEdward Cree 	/* Look up actual mport ID */
253da56552dSEdward Cree 	rc = efx_mae_lookup_mport(efx, selector, &efv->mport);
254da56552dSEdward Cree 	if (rc)
255da56552dSEdward Cree 		return rc;
256da56552dSEdward Cree 	pci_dbg(efx->pci_dev, "VF %u has mport ID %#x\n", efv->idx, efv->mport);
257da56552dSEdward Cree 	/* mport label should fit in 16 bits */
258da56552dSEdward Cree 	WARN_ON(efv->mport >> 16);
259da56552dSEdward Cree 
26067ab160eSEdward Cree 	return efx_tc_configure_default_rule_rep(efv);
26167ab160eSEdward Cree }
26267ab160eSEdward Cree 
26367ab160eSEdward Cree static void efx_ef100_deconfigure_rep(struct efx_rep *efv)
26467ab160eSEdward Cree {
26567ab160eSEdward Cree 	struct efx_nic *efx = efv->parent;
26667ab160eSEdward Cree 
26767ab160eSEdward Cree 	efx_tc_deconfigure_default_rule(efx, &efv->dflt);
268da56552dSEdward Cree }
269da56552dSEdward Cree 
27008135eecSEdward Cree static void efx_ef100_rep_destroy_netdev(struct efx_rep *efv)
27108135eecSEdward Cree {
27208135eecSEdward Cree 	struct efx_nic *efx = efv->parent;
27308135eecSEdward Cree 
27484e7fc25SEdward Cree 	rtnl_lock();
27508135eecSEdward Cree 	spin_lock_bh(&efx->vf_reps_lock);
27608135eecSEdward Cree 	list_del(&efv->list);
27708135eecSEdward Cree 	spin_unlock_bh(&efx->vf_reps_lock);
27884e7fc25SEdward Cree 	rtnl_unlock();
279f50e8fcdSEdward Cree 	synchronize_rcu();
28008135eecSEdward Cree 	free_netdev(efv->net_dev);
28108135eecSEdward Cree }
28208135eecSEdward Cree 
28308135eecSEdward Cree int efx_ef100_vfrep_create(struct efx_nic *efx, unsigned int i)
28408135eecSEdward Cree {
28508135eecSEdward Cree 	struct efx_rep *efv;
28608135eecSEdward Cree 	int rc;
28708135eecSEdward Cree 
28808135eecSEdward Cree 	efv = efx_ef100_rep_create_netdev(efx, i);
28908135eecSEdward Cree 	if (IS_ERR(efv)) {
29008135eecSEdward Cree 		rc = PTR_ERR(efv);
29108135eecSEdward Cree 		pci_err(efx->pci_dev,
29208135eecSEdward Cree 			"Failed to create representor for VF %d, rc %d\n", i,
29308135eecSEdward Cree 			rc);
29408135eecSEdward Cree 		return rc;
29508135eecSEdward Cree 	}
296da56552dSEdward Cree 	rc = efx_ef100_configure_rep(efv);
297da56552dSEdward Cree 	if (rc) {
298da56552dSEdward Cree 		pci_err(efx->pci_dev,
299da56552dSEdward Cree 			"Failed to configure representor for VF %d, rc %d\n",
300da56552dSEdward Cree 			i, rc);
30167ab160eSEdward Cree 		goto fail1;
302da56552dSEdward Cree 	}
30308135eecSEdward Cree 	rc = register_netdev(efv->net_dev);
30408135eecSEdward Cree 	if (rc) {
30508135eecSEdward Cree 		pci_err(efx->pci_dev,
30608135eecSEdward Cree 			"Failed to register representor for VF %d, rc %d\n",
30708135eecSEdward Cree 			i, rc);
30867ab160eSEdward Cree 		goto fail2;
30908135eecSEdward Cree 	}
31008135eecSEdward Cree 	pci_dbg(efx->pci_dev, "Representor for VF %d is %s\n", i,
31108135eecSEdward Cree 		efv->net_dev->name);
31208135eecSEdward Cree 	return 0;
31367ab160eSEdward Cree fail2:
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);
32967ab160eSEdward Cree 	efx_ef100_deconfigure_rep(efv);
33008135eecSEdward Cree 	efx_ef100_rep_destroy_netdev(efv);
33108135eecSEdward Cree }
33208135eecSEdward Cree 
33308135eecSEdward Cree void efx_ef100_fini_vfreps(struct efx_nic *efx)
33408135eecSEdward Cree {
33508135eecSEdward Cree 	struct ef100_nic_data *nic_data = efx->nic_data;
33608135eecSEdward Cree 	struct efx_rep *efv, *next;
33708135eecSEdward Cree 
33808135eecSEdward Cree 	if (!nic_data->grp_mae)
33908135eecSEdward Cree 		return;
34008135eecSEdward Cree 
34108135eecSEdward Cree 	list_for_each_entry_safe(efv, next, &efx->vf_reps, list)
34208135eecSEdward Cree 		efx_ef100_vfrep_destroy(efx, efv);
34308135eecSEdward Cree }
34469bb5fa7SEdward Cree 
345*a6a15acaSAlejandro Lucero void efx_ef100_init_reps(struct efx_nic *efx)
346*a6a15acaSAlejandro Lucero {
347*a6a15acaSAlejandro Lucero 	struct ef100_nic_data *nic_data = efx->nic_data;
348*a6a15acaSAlejandro Lucero 	int rc;
349*a6a15acaSAlejandro Lucero 
350*a6a15acaSAlejandro Lucero 	nic_data->have_local_intf = false;
351*a6a15acaSAlejandro Lucero 	rc = efx_mae_enumerate_mports(efx);
352*a6a15acaSAlejandro Lucero 	if (rc)
353*a6a15acaSAlejandro Lucero 		pci_warn(efx->pci_dev,
354*a6a15acaSAlejandro Lucero 			 "Could not enumerate mports (rc=%d), are we admin?",
355*a6a15acaSAlejandro Lucero 			 rc);
356*a6a15acaSAlejandro Lucero }
357*a6a15acaSAlejandro Lucero 
358*a6a15acaSAlejandro Lucero void efx_ef100_fini_reps(struct efx_nic *efx)
359*a6a15acaSAlejandro Lucero {
360*a6a15acaSAlejandro Lucero 	struct efx_mae *mae = efx->mae;
361*a6a15acaSAlejandro Lucero 
362*a6a15acaSAlejandro Lucero 	rhashtable_free_and_destroy(&mae->mports_ht, efx_mae_remove_mport,
363*a6a15acaSAlejandro Lucero 				    NULL);
364*a6a15acaSAlejandro Lucero }
365*a6a15acaSAlejandro Lucero 
36669bb5fa7SEdward Cree static int efx_ef100_rep_poll(struct napi_struct *napi, int weight)
36769bb5fa7SEdward Cree {
36869bb5fa7SEdward Cree 	struct efx_rep *efv = container_of(napi, struct efx_rep, napi);
36969bb5fa7SEdward Cree 	unsigned int read_index;
37069bb5fa7SEdward Cree 	struct list_head head;
37169bb5fa7SEdward Cree 	struct sk_buff *skb;
37269bb5fa7SEdward Cree 	bool need_resched;
37369bb5fa7SEdward Cree 	int spent = 0;
37469bb5fa7SEdward Cree 
37569bb5fa7SEdward Cree 	INIT_LIST_HEAD(&head);
37669bb5fa7SEdward Cree 	/* Grab up to 'weight' pending SKBs */
37769bb5fa7SEdward Cree 	spin_lock_bh(&efv->rx_lock);
37869bb5fa7SEdward Cree 	read_index = efv->write_index;
37969bb5fa7SEdward Cree 	while (spent < weight && !list_empty(&efv->rx_list)) {
38069bb5fa7SEdward Cree 		skb = list_first_entry(&efv->rx_list, struct sk_buff, list);
38169bb5fa7SEdward Cree 		list_del(&skb->list);
38269bb5fa7SEdward Cree 		list_add_tail(&skb->list, &head);
38369bb5fa7SEdward Cree 		spent++;
38469bb5fa7SEdward Cree 	}
38569bb5fa7SEdward Cree 	spin_unlock_bh(&efv->rx_lock);
38669bb5fa7SEdward Cree 	/* Receive them */
38769bb5fa7SEdward Cree 	netif_receive_skb_list(&head);
38869bb5fa7SEdward Cree 	if (spent < weight)
38969bb5fa7SEdward Cree 		if (napi_complete_done(napi, spent)) {
39069bb5fa7SEdward Cree 			spin_lock_bh(&efv->rx_lock);
39169bb5fa7SEdward Cree 			efv->read_index = read_index;
39269bb5fa7SEdward Cree 			/* If write_index advanced while we were doing the
39369bb5fa7SEdward Cree 			 * RX, then storing our read_index won't re-prime the
39469bb5fa7SEdward Cree 			 * fake-interrupt.  In that case, we need to schedule
39569bb5fa7SEdward Cree 			 * NAPI again to consume the additional packet(s).
39669bb5fa7SEdward Cree 			 */
39769bb5fa7SEdward Cree 			need_resched = efv->write_index != read_index;
39869bb5fa7SEdward Cree 			spin_unlock_bh(&efv->rx_lock);
39969bb5fa7SEdward Cree 			if (need_resched)
40069bb5fa7SEdward Cree 				napi_schedule(&efv->napi);
40169bb5fa7SEdward Cree 		}
40269bb5fa7SEdward Cree 	return spent;
40369bb5fa7SEdward Cree }
4049fe00c80SEdward Cree 
4059fe00c80SEdward Cree void efx_ef100_rep_rx_packet(struct efx_rep *efv, struct efx_rx_buffer *rx_buf)
4069fe00c80SEdward Cree {
4079fe00c80SEdward Cree 	u8 *eh = efx_rx_buf_va(rx_buf);
4089fe00c80SEdward Cree 	struct sk_buff *skb;
4099fe00c80SEdward Cree 	bool primed;
4109fe00c80SEdward Cree 
4119fe00c80SEdward Cree 	/* Don't allow too many queued SKBs to build up, as they consume
4129fe00c80SEdward Cree 	 * GFP_ATOMIC memory.  If we overrun, just start dropping.
4139fe00c80SEdward Cree 	 */
4149fe00c80SEdward Cree 	if (efv->write_index - READ_ONCE(efv->read_index) > efv->rx_pring_size) {
4159fe00c80SEdward Cree 		atomic64_inc(&efv->stats.rx_dropped);
4169fe00c80SEdward Cree 		if (net_ratelimit())
4179fe00c80SEdward Cree 			netif_dbg(efv->parent, rx_err, efv->net_dev,
4189fe00c80SEdward Cree 				  "nodesc-dropped packet of length %u\n",
4199fe00c80SEdward Cree 				  rx_buf->len);
4209fe00c80SEdward Cree 		return;
4219fe00c80SEdward Cree 	}
4229fe00c80SEdward Cree 
4239fe00c80SEdward Cree 	skb = netdev_alloc_skb(efv->net_dev, rx_buf->len);
4249fe00c80SEdward Cree 	if (!skb) {
4259fe00c80SEdward Cree 		atomic64_inc(&efv->stats.rx_dropped);
4269fe00c80SEdward Cree 		if (net_ratelimit())
4279fe00c80SEdward Cree 			netif_dbg(efv->parent, rx_err, efv->net_dev,
4289fe00c80SEdward Cree 				  "noskb-dropped packet of length %u\n",
4299fe00c80SEdward Cree 				  rx_buf->len);
4309fe00c80SEdward Cree 		return;
4319fe00c80SEdward Cree 	}
4329fe00c80SEdward Cree 	memcpy(skb->data, eh, rx_buf->len);
4339fe00c80SEdward Cree 	__skb_put(skb, rx_buf->len);
4349fe00c80SEdward Cree 
4359fe00c80SEdward Cree 	skb_record_rx_queue(skb, 0); /* rep is single-queue */
4369fe00c80SEdward Cree 
4379fe00c80SEdward Cree 	/* Move past the ethernet header */
4389fe00c80SEdward Cree 	skb->protocol = eth_type_trans(skb, efv->net_dev);
4399fe00c80SEdward Cree 
4409fe00c80SEdward Cree 	skb_checksum_none_assert(skb);
4419fe00c80SEdward Cree 
4429fe00c80SEdward Cree 	atomic64_inc(&efv->stats.rx_packets);
4439fe00c80SEdward Cree 	atomic64_add(rx_buf->len, &efv->stats.rx_bytes);
4449fe00c80SEdward Cree 
4459fe00c80SEdward Cree 	/* Add it to the rx list */
4469fe00c80SEdward Cree 	spin_lock_bh(&efv->rx_lock);
4479fe00c80SEdward Cree 	primed = efv->read_index == efv->write_index;
4489fe00c80SEdward Cree 	list_add_tail(&skb->list, &efv->rx_list);
4499fe00c80SEdward Cree 	efv->write_index++;
4509fe00c80SEdward Cree 	spin_unlock_bh(&efv->rx_lock);
4519fe00c80SEdward Cree 	/* Trigger rx work */
4529fe00c80SEdward Cree 	if (primed)
4539fe00c80SEdward Cree 		napi_schedule(&efv->napi);
4549fe00c80SEdward Cree }
455f50e8fcdSEdward Cree 
456f50e8fcdSEdward Cree struct efx_rep *efx_ef100_find_rep_by_mport(struct efx_nic *efx, u16 mport)
457f50e8fcdSEdward Cree {
458f50e8fcdSEdward Cree 	struct efx_rep *efv, *out = NULL;
459f50e8fcdSEdward Cree 
460f50e8fcdSEdward Cree 	/* spinlock guards against list mutation while we're walking it;
461f50e8fcdSEdward Cree 	 * but caller must also hold rcu_read_lock() to ensure the netdev
462f50e8fcdSEdward Cree 	 * isn't freed after we drop the spinlock.
463f50e8fcdSEdward Cree 	 */
464f50e8fcdSEdward Cree 	spin_lock_bh(&efx->vf_reps_lock);
465f50e8fcdSEdward Cree 	list_for_each_entry(efv, &efx->vf_reps, list)
466f50e8fcdSEdward Cree 		if (efv->mport == mport) {
467f50e8fcdSEdward Cree 			out = efv;
468f50e8fcdSEdward Cree 			break;
469f50e8fcdSEdward Cree 		}
470f50e8fcdSEdward Cree 	spin_unlock_bh(&efx->vf_reps_lock);
471f50e8fcdSEdward Cree 	return out;
472f50e8fcdSEdward Cree }
473