xref: /openbmc/linux/drivers/net/ethernet/sfc/ef100_rep.c (revision 84e7fc2591f72987b43da91b3fdb01a196204379)
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 
1208135eecSEdward Cree #include "ef100_rep.h"
13f72c38faSEdward Cree #include "ef100_netdev.h"
1408135eecSEdward Cree #include "ef100_nic.h"
15da56552dSEdward Cree #include "mae.h"
1608135eecSEdward Cree 
175687eb34SEdward Cree #define EFX_EF100_REP_DRIVER	"efx_ef100_rep"
185687eb34SEdward Cree 
19e1479556SEdward Cree static int efx_ef100_rep_init_struct(struct efx_nic *efx, struct efx_rep *efv,
20e1479556SEdward Cree 				     unsigned int i)
2108135eecSEdward Cree {
2208135eecSEdward Cree 	efv->parent = efx;
23e1479556SEdward Cree 	efv->idx = i;
2408135eecSEdward Cree 	INIT_LIST_HEAD(&efv->list);
2508135eecSEdward Cree 	efv->msg_enable = NETIF_MSG_DRV | NETIF_MSG_PROBE |
2608135eecSEdward Cree 			  NETIF_MSG_LINK | NETIF_MSG_IFDOWN |
2708135eecSEdward Cree 			  NETIF_MSG_IFUP | NETIF_MSG_RX_ERR |
2808135eecSEdward Cree 			  NETIF_MSG_TX_ERR | NETIF_MSG_HW;
2908135eecSEdward Cree 	return 0;
3008135eecSEdward Cree }
3108135eecSEdward Cree 
32f72c38faSEdward Cree static netdev_tx_t efx_ef100_rep_xmit(struct sk_buff *skb,
33f72c38faSEdward Cree 				      struct net_device *dev)
34f72c38faSEdward Cree {
35f72c38faSEdward Cree 	struct efx_rep *efv = netdev_priv(dev);
36f72c38faSEdward Cree 	struct efx_nic *efx = efv->parent;
37f72c38faSEdward Cree 	netdev_tx_t rc;
38f72c38faSEdward Cree 
39f72c38faSEdward Cree 	/* __ef100_hard_start_xmit() will always return success even in the
40f72c38faSEdward Cree 	 * case of TX drops, where it will increment efx's tx_dropped.  The
41f72c38faSEdward Cree 	 * efv stats really only count attempted TX, not success/failure.
42f72c38faSEdward Cree 	 */
43f72c38faSEdward Cree 	atomic64_inc(&efv->stats.tx_packets);
44f72c38faSEdward Cree 	atomic64_add(skb->len, &efv->stats.tx_bytes);
45f72c38faSEdward Cree 	netif_tx_lock(efx->net_dev);
46f72c38faSEdward Cree 	rc = __ef100_hard_start_xmit(skb, efx, dev, efv);
47f72c38faSEdward Cree 	netif_tx_unlock(efx->net_dev);
48f72c38faSEdward Cree 	return rc;
49f72c38faSEdward Cree }
50f72c38faSEdward Cree 
51e1479556SEdward Cree static int efx_ef100_rep_get_port_parent_id(struct net_device *dev,
52e1479556SEdward Cree 					    struct netdev_phys_item_id *ppid)
53e1479556SEdward Cree {
54e1479556SEdward Cree 	struct efx_rep *efv = netdev_priv(dev);
55e1479556SEdward Cree 	struct efx_nic *efx = efv->parent;
56e1479556SEdward Cree 	struct ef100_nic_data *nic_data;
57e1479556SEdward Cree 
58e1479556SEdward Cree 	nic_data = efx->nic_data;
59e1479556SEdward Cree 	/* nic_data->port_id is a u8[] */
60e1479556SEdward Cree 	ppid->id_len = sizeof(nic_data->port_id);
61e1479556SEdward Cree 	memcpy(ppid->id, nic_data->port_id, sizeof(nic_data->port_id));
62e1479556SEdward Cree 	return 0;
63e1479556SEdward Cree }
64e1479556SEdward Cree 
65e1479556SEdward Cree static int efx_ef100_rep_get_phys_port_name(struct net_device *dev,
66e1479556SEdward Cree 					    char *buf, size_t len)
67e1479556SEdward Cree {
68e1479556SEdward Cree 	struct efx_rep *efv = netdev_priv(dev);
69e1479556SEdward Cree 	struct efx_nic *efx = efv->parent;
70e1479556SEdward Cree 	struct ef100_nic_data *nic_data;
71e1479556SEdward Cree 	int ret;
72e1479556SEdward Cree 
73e1479556SEdward Cree 	nic_data = efx->nic_data;
74e1479556SEdward Cree 	ret = snprintf(buf, len, "p%upf%uvf%u", efx->port_num,
75e1479556SEdward Cree 		       nic_data->pf_index, efv->idx);
76e1479556SEdward Cree 	if (ret >= len)
77e1479556SEdward Cree 		return -EOPNOTSUPP;
78e1479556SEdward Cree 
79e1479556SEdward Cree 	return 0;
80e1479556SEdward Cree }
81e1479556SEdward Cree 
8208135eecSEdward Cree static const struct net_device_ops efx_ef100_rep_netdev_ops = {
83f72c38faSEdward Cree 	.ndo_start_xmit		= efx_ef100_rep_xmit,
84e1479556SEdward Cree 	.ndo_get_port_parent_id	= efx_ef100_rep_get_port_parent_id,
85e1479556SEdward Cree 	.ndo_get_phys_port_name	= efx_ef100_rep_get_phys_port_name,
8608135eecSEdward Cree };
8708135eecSEdward Cree 
885687eb34SEdward Cree static void efx_ef100_rep_get_drvinfo(struct net_device *dev,
895687eb34SEdward Cree 				      struct ethtool_drvinfo *drvinfo)
905687eb34SEdward Cree {
915687eb34SEdward Cree 	strscpy(drvinfo->driver, EFX_EF100_REP_DRIVER, sizeof(drvinfo->driver));
925687eb34SEdward Cree }
935687eb34SEdward Cree 
945687eb34SEdward Cree static u32 efx_ef100_rep_ethtool_get_msglevel(struct net_device *net_dev)
955687eb34SEdward Cree {
965687eb34SEdward Cree 	struct efx_rep *efv = netdev_priv(net_dev);
975687eb34SEdward Cree 
985687eb34SEdward Cree 	return efv->msg_enable;
995687eb34SEdward Cree }
1005687eb34SEdward Cree 
1015687eb34SEdward Cree static void efx_ef100_rep_ethtool_set_msglevel(struct net_device *net_dev,
1025687eb34SEdward Cree 					       u32 msg_enable)
1035687eb34SEdward Cree {
1045687eb34SEdward Cree 	struct efx_rep *efv = netdev_priv(net_dev);
1055687eb34SEdward Cree 
1065687eb34SEdward Cree 	efv->msg_enable = msg_enable;
1075687eb34SEdward Cree }
1085687eb34SEdward Cree 
10908135eecSEdward Cree static const struct ethtool_ops efx_ef100_rep_ethtool_ops = {
1105687eb34SEdward Cree 	.get_drvinfo		= efx_ef100_rep_get_drvinfo,
1115687eb34SEdward Cree 	.get_msglevel		= efx_ef100_rep_ethtool_get_msglevel,
1125687eb34SEdward Cree 	.set_msglevel		= efx_ef100_rep_ethtool_set_msglevel,
11308135eecSEdward Cree };
11408135eecSEdward Cree 
11508135eecSEdward Cree static struct efx_rep *efx_ef100_rep_create_netdev(struct efx_nic *efx,
11608135eecSEdward Cree 						   unsigned int i)
11708135eecSEdward Cree {
11808135eecSEdward Cree 	struct net_device *net_dev;
11908135eecSEdward Cree 	struct efx_rep *efv;
12008135eecSEdward Cree 	int rc;
12108135eecSEdward Cree 
12208135eecSEdward Cree 	net_dev = alloc_etherdev_mq(sizeof(*efv), 1);
12308135eecSEdward Cree 	if (!net_dev)
12408135eecSEdward Cree 		return ERR_PTR(-ENOMEM);
12508135eecSEdward Cree 
12608135eecSEdward Cree 	efv = netdev_priv(net_dev);
127e1479556SEdward Cree 	rc = efx_ef100_rep_init_struct(efx, efv, i);
12808135eecSEdward Cree 	if (rc)
12908135eecSEdward Cree 		goto fail1;
13008135eecSEdward Cree 	efv->net_dev = net_dev;
13108135eecSEdward Cree 	rtnl_lock();
13208135eecSEdward Cree 	spin_lock_bh(&efx->vf_reps_lock);
13308135eecSEdward Cree 	list_add_tail(&efv->list, &efx->vf_reps);
13408135eecSEdward Cree 	spin_unlock_bh(&efx->vf_reps_lock);
135*84e7fc25SEdward Cree 	if (netif_running(efx->net_dev) && efx->state == STATE_NET_UP) {
136*84e7fc25SEdward Cree 		netif_device_attach(net_dev);
137*84e7fc25SEdward Cree 		netif_carrier_on(net_dev);
138*84e7fc25SEdward Cree 	} else {
13908135eecSEdward Cree 		netif_carrier_off(net_dev);
14008135eecSEdward Cree 		netif_tx_stop_all_queues(net_dev);
141*84e7fc25SEdward Cree 	}
14208135eecSEdward Cree 	rtnl_unlock();
14308135eecSEdward Cree 
14408135eecSEdward Cree 	net_dev->netdev_ops = &efx_ef100_rep_netdev_ops;
14508135eecSEdward Cree 	net_dev->ethtool_ops = &efx_ef100_rep_ethtool_ops;
14608135eecSEdward Cree 	net_dev->min_mtu = EFX_MIN_MTU;
14708135eecSEdward Cree 	net_dev->max_mtu = EFX_MAX_MTU;
148f72c38faSEdward Cree 	net_dev->features |= NETIF_F_LLTX;
149f72c38faSEdward Cree 	net_dev->hw_features |= NETIF_F_LLTX;
15008135eecSEdward Cree 	return efv;
15108135eecSEdward Cree fail1:
15208135eecSEdward Cree 	free_netdev(net_dev);
15308135eecSEdward Cree 	return ERR_PTR(rc);
15408135eecSEdward Cree }
15508135eecSEdward Cree 
156da56552dSEdward Cree static int efx_ef100_configure_rep(struct efx_rep *efv)
157da56552dSEdward Cree {
158da56552dSEdward Cree 	struct efx_nic *efx = efv->parent;
159da56552dSEdward Cree 	u32 selector;
160da56552dSEdward Cree 	int rc;
161da56552dSEdward Cree 
162da56552dSEdward Cree 	/* Construct mport selector for corresponding VF */
163da56552dSEdward Cree 	efx_mae_mport_vf(efx, efv->idx, &selector);
164da56552dSEdward Cree 	/* Look up actual mport ID */
165da56552dSEdward Cree 	rc = efx_mae_lookup_mport(efx, selector, &efv->mport);
166da56552dSEdward Cree 	if (rc)
167da56552dSEdward Cree 		return rc;
168da56552dSEdward Cree 	pci_dbg(efx->pci_dev, "VF %u has mport ID %#x\n", efv->idx, efv->mport);
169da56552dSEdward Cree 	/* mport label should fit in 16 bits */
170da56552dSEdward Cree 	WARN_ON(efv->mport >> 16);
171da56552dSEdward Cree 
172da56552dSEdward Cree 	return 0;
173da56552dSEdward Cree }
174da56552dSEdward Cree 
17508135eecSEdward Cree static void efx_ef100_rep_destroy_netdev(struct efx_rep *efv)
17608135eecSEdward Cree {
17708135eecSEdward Cree 	struct efx_nic *efx = efv->parent;
17808135eecSEdward Cree 
179*84e7fc25SEdward Cree 	rtnl_lock();
18008135eecSEdward Cree 	spin_lock_bh(&efx->vf_reps_lock);
18108135eecSEdward Cree 	list_del(&efv->list);
18208135eecSEdward Cree 	spin_unlock_bh(&efx->vf_reps_lock);
183*84e7fc25SEdward Cree 	rtnl_unlock();
18408135eecSEdward Cree 	free_netdev(efv->net_dev);
18508135eecSEdward Cree }
18608135eecSEdward Cree 
18708135eecSEdward Cree int efx_ef100_vfrep_create(struct efx_nic *efx, unsigned int i)
18808135eecSEdward Cree {
18908135eecSEdward Cree 	struct efx_rep *efv;
19008135eecSEdward Cree 	int rc;
19108135eecSEdward Cree 
19208135eecSEdward Cree 	efv = efx_ef100_rep_create_netdev(efx, i);
19308135eecSEdward Cree 	if (IS_ERR(efv)) {
19408135eecSEdward Cree 		rc = PTR_ERR(efv);
19508135eecSEdward Cree 		pci_err(efx->pci_dev,
19608135eecSEdward Cree 			"Failed to create representor for VF %d, rc %d\n", i,
19708135eecSEdward Cree 			rc);
19808135eecSEdward Cree 		return rc;
19908135eecSEdward Cree 	}
200da56552dSEdward Cree 	rc = efx_ef100_configure_rep(efv);
201da56552dSEdward Cree 	if (rc) {
202da56552dSEdward Cree 		pci_err(efx->pci_dev,
203da56552dSEdward Cree 			"Failed to configure representor for VF %d, rc %d\n",
204da56552dSEdward Cree 			i, rc);
205da56552dSEdward Cree 		goto fail;
206da56552dSEdward Cree 	}
20708135eecSEdward Cree 	rc = register_netdev(efv->net_dev);
20808135eecSEdward Cree 	if (rc) {
20908135eecSEdward Cree 		pci_err(efx->pci_dev,
21008135eecSEdward Cree 			"Failed to register representor for VF %d, rc %d\n",
21108135eecSEdward Cree 			i, rc);
21208135eecSEdward Cree 		goto fail;
21308135eecSEdward Cree 	}
21408135eecSEdward Cree 	pci_dbg(efx->pci_dev, "Representor for VF %d is %s\n", i,
21508135eecSEdward Cree 		efv->net_dev->name);
21608135eecSEdward Cree 	return 0;
21708135eecSEdward Cree fail:
21808135eecSEdward Cree 	efx_ef100_rep_destroy_netdev(efv);
21908135eecSEdward Cree 	return rc;
22008135eecSEdward Cree }
22108135eecSEdward Cree 
22208135eecSEdward Cree void efx_ef100_vfrep_destroy(struct efx_nic *efx, struct efx_rep *efv)
22308135eecSEdward Cree {
22408135eecSEdward Cree 	struct net_device *rep_dev;
22508135eecSEdward Cree 
22608135eecSEdward Cree 	rep_dev = efv->net_dev;
22708135eecSEdward Cree 	if (!rep_dev)
22808135eecSEdward Cree 		return;
22908135eecSEdward Cree 	netif_dbg(efx, drv, rep_dev, "Removing VF representor\n");
23008135eecSEdward Cree 	unregister_netdev(rep_dev);
23108135eecSEdward Cree 	efx_ef100_rep_destroy_netdev(efv);
23208135eecSEdward Cree }
23308135eecSEdward Cree 
23408135eecSEdward Cree void efx_ef100_fini_vfreps(struct efx_nic *efx)
23508135eecSEdward Cree {
23608135eecSEdward Cree 	struct ef100_nic_data *nic_data = efx->nic_data;
23708135eecSEdward Cree 	struct efx_rep *efv, *next;
23808135eecSEdward Cree 
23908135eecSEdward Cree 	if (!nic_data->grp_mae)
24008135eecSEdward Cree 		return;
24108135eecSEdward Cree 
24208135eecSEdward Cree 	list_for_each_entry_safe(efv, next, &efx->vf_reps, list)
24308135eecSEdward Cree 		efx_ef100_vfrep_destroy(efx, efv);
24408135eecSEdward Cree }
245