brintos

brintos / linux-shallow public Read only

0
0
Text · 5.0 KiB · 54640bc Raw
226 lines · c
1// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)2/* Copyright (C) 2017-2018 Netronome Systems, Inc. */3 4#include <linux/lockdep.h>5#include <linux/netdevice.h>6 7#include "nfpcore/nfp_cpp.h"8#include "nfpcore/nfp_nsp.h"9#include "nfp_app.h"10#include "nfp_main.h"11#include "nfp_net.h"12#include "nfp_port.h"13 14struct nfp_port *nfp_port_from_netdev(struct net_device *netdev)15{16	if (nfp_netdev_is_nfp_net(netdev)) {17		struct nfp_net *nn = netdev_priv(netdev);18 19		return nn->port;20	}21 22	if (nfp_netdev_is_nfp_repr(netdev)) {23		struct nfp_repr *repr = netdev_priv(netdev);24 25		return repr->port;26	}27 28	WARN(1, "Unknown netdev type for nfp_port\n");29 30	return NULL;31}32 33int nfp_port_get_port_parent_id(struct net_device *netdev,34				struct netdev_phys_item_id *ppid)35{36	struct nfp_port *port;37	const u8 *serial;38 39	port = nfp_port_from_netdev(netdev);40	if (!port)41		return -EOPNOTSUPP;42 43	ppid->id_len = nfp_cpp_serial(port->app->cpp, &serial);44	memcpy(&ppid->id, serial, ppid->id_len);45 46	return 0;47}48 49int nfp_port_setup_tc(struct net_device *netdev, enum tc_setup_type type,50		      void *type_data)51{52	struct nfp_port *port;53 54	port = nfp_port_from_netdev(netdev);55	if (!port)56		return -EOPNOTSUPP;57 58	return nfp_app_setup_tc(port->app, netdev, type, type_data);59}60 61int nfp_port_set_features(struct net_device *netdev, netdev_features_t features)62{63	struct nfp_port *port;64 65	port = nfp_port_from_netdev(netdev);66	if (!port)67		return 0;68 69	if ((netdev->features & NETIF_F_HW_TC) > (features & NETIF_F_HW_TC) &&70	    port->tc_offload_cnt) {71		netdev_err(netdev, "Cannot disable HW TC offload while offloads active\n");72		return -EBUSY;73	}74 75	return 0;76}77 78struct nfp_eth_table_port *__nfp_port_get_eth_port(struct nfp_port *port)79{80	if (!port)81		return NULL;82	if (port->type != NFP_PORT_PHYS_PORT)83		return NULL;84 85	return port->eth_port;86}87 88struct nfp_eth_table_port *nfp_port_get_eth_port(struct nfp_port *port)89{90	if (!__nfp_port_get_eth_port(port))91		return NULL;92 93	if (test_bit(NFP_PORT_CHANGED, &port->flags))94		if (nfp_net_refresh_eth_port(port))95			return NULL;96 97	return __nfp_port_get_eth_port(port);98}99 100int101nfp_port_get_phys_port_name(struct net_device *netdev, char *name, size_t len)102{103	struct nfp_eth_table_port *eth_port;104	struct nfp_port *port;105	int n;106 107	port = nfp_port_from_netdev(netdev);108	if (!port)109		return -EOPNOTSUPP;110 111	switch (port->type) {112	case NFP_PORT_PHYS_PORT:113		eth_port = __nfp_port_get_eth_port(port);114		if (!eth_port)115			return -EOPNOTSUPP;116 117		if (!eth_port->is_split)118			n = snprintf(name, len, "p%d", eth_port->label_port);119		else120			n = snprintf(name, len, "p%ds%d", eth_port->label_port,121				     eth_port->label_subport);122		break;123	case NFP_PORT_PF_PORT:124		if (!port->pf_split)125			n = snprintf(name, len, "pf%d", port->pf_id);126		else127			n = snprintf(name, len, "pf%ds%d", port->pf_id,128				     port->pf_split_id);129		break;130	case NFP_PORT_VF_PORT:131		n = snprintf(name, len, "pf%dvf%d", port->pf_id, port->vf_id);132		break;133	default:134		return -EOPNOTSUPP;135	}136 137	if (n >= len)138		return -EINVAL;139 140	return 0;141}142 143/**144 * nfp_port_configure() - helper to set the interface configured bit145 * @netdev:	net_device instance146 * @configed:	Desired state147 *148 * Helper to set the ifup/ifdown state on the PHY only if there is a physical149 * interface associated with the netdev.150 *151 * Return:152 * 0 - configuration successful (or no change);153 * -ERRNO - configuration failed.154 */155int nfp_port_configure(struct net_device *netdev, bool configed)156{157	struct nfp_eth_table_port *eth_port;158	struct nfp_port *port;159	int err;160 161	port = nfp_port_from_netdev(netdev);162	eth_port = __nfp_port_get_eth_port(port);163	if (!eth_port)164		return 0;165	if (port->eth_forced)166		return 0;167 168	err = nfp_eth_set_configured(port->app->cpp, eth_port->index, configed);169	return err < 0 && err != -EOPNOTSUPP ? err : 0;170}171 172int nfp_port_init_phy_port(struct nfp_pf *pf, struct nfp_app *app,173			   struct nfp_port *port, unsigned int id)174{175	/* Check if vNIC has external port associated and cfg is OK */176	if (!pf->eth_tbl || id >= pf->eth_tbl->count) {177		nfp_err(app->cpp,178			"NSP port entries don't match vNICs (no entry %d)\n",179			id);180		return -EINVAL;181	}182	if (pf->eth_tbl->ports[id].override_changed) {183		nfp_warn(app->cpp,184			 "Config changed for port #%d, reboot required before port will be operational\n",185			 pf->eth_tbl->ports[id].index);186		port->type = NFP_PORT_INVALID;187		return 0;188	}189 190	port->eth_port = &pf->eth_tbl->ports[id];191	port->eth_id = pf->eth_tbl->ports[id].index;192	port->netdev->dev_port = id;193	if (pf->mac_stats_mem)194		port->eth_stats =195			pf->mac_stats_mem + port->eth_id * NFP_MAC_STATS_SIZE;196 197	return 0;198}199 200struct nfp_port *201nfp_port_alloc(struct nfp_app *app, enum nfp_port_type type,202	       struct net_device *netdev)203{204	struct nfp_port *port;205 206	port = kzalloc(sizeof(*port), GFP_KERNEL);207	if (!port)208		return ERR_PTR(-ENOMEM);209 210	port->netdev = netdev;211	port->type = type;212	port->app = app;213 214	list_add_tail(&port->port_list, &app->pf->ports);215 216	return port;217}218 219void nfp_port_free(struct nfp_port *port)220{221	if (!port)222		return;223	list_del(&port->port_list);224	kfree(port);225}226