xref: /openbmc/linux/drivers/net/ethernet/netronome/nfp/nfp_devlink.c (revision 2612e3bbc0386368a850140a6c9b990cd496a5ec)
196de2506SJakub Kicinski // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
296de2506SJakub Kicinski /* Copyright (C) 2017-2018 Netronome Systems, Inc. */
31851f93fSSimon Horman 
453e7a08fSJakub Kicinski #include <linux/rtnetlink.h>
51851f93fSSimon Horman #include <net/devlink.h>
61851f93fSSimon Horman 
74adba008SJakub Kicinski #include "nfpcore/nfp.h"
853e7a08fSJakub Kicinski #include "nfpcore/nfp_nsp.h"
953e7a08fSJakub Kicinski #include "nfp_app.h"
101851f93fSSimon Horman #include "nfp_main.h"
1153e7a08fSJakub Kicinski #include "nfp_port.h"
1253e7a08fSJakub Kicinski 
1353e7a08fSJakub Kicinski static int
nfp_devlink_fill_eth_port(struct nfp_port * port,struct nfp_eth_table_port * copy)1453e7a08fSJakub Kicinski nfp_devlink_fill_eth_port(struct nfp_port *port,
1553e7a08fSJakub Kicinski 			  struct nfp_eth_table_port *copy)
1653e7a08fSJakub Kicinski {
1753e7a08fSJakub Kicinski 	struct nfp_eth_table_port *eth_port;
1853e7a08fSJakub Kicinski 
1953e7a08fSJakub Kicinski 	eth_port = __nfp_port_get_eth_port(port);
2053e7a08fSJakub Kicinski 	if (!eth_port)
2153e7a08fSJakub Kicinski 		return -EINVAL;
2253e7a08fSJakub Kicinski 
2353e7a08fSJakub Kicinski 	memcpy(copy, eth_port, sizeof(*eth_port));
2453e7a08fSJakub Kicinski 
2553e7a08fSJakub Kicinski 	return 0;
2653e7a08fSJakub Kicinski }
271851f93fSSimon Horman 
28ec8b1fbeSJakub Kicinski static int
nfp_devlink_fill_eth_port_from_id(struct nfp_pf * pf,struct devlink_port * dl_port,struct nfp_eth_table_port * copy)29706217c1SJakub Kicinski nfp_devlink_fill_eth_port_from_id(struct nfp_pf *pf,
30706217c1SJakub Kicinski 				  struct devlink_port *dl_port,
31ec8b1fbeSJakub Kicinski 				  struct nfp_eth_table_port *copy)
32ec8b1fbeSJakub Kicinski {
33706217c1SJakub Kicinski 	struct nfp_port *port = container_of(dl_port, struct nfp_port, dl_port);
34ec8b1fbeSJakub Kicinski 
35ec8b1fbeSJakub Kicinski 	return nfp_devlink_fill_eth_port(port, copy);
36ec8b1fbeSJakub Kicinski }
37ec8b1fbeSJakub Kicinski 
38ec8b1fbeSJakub Kicinski static int
nfp_devlink_set_lanes(struct nfp_pf * pf,unsigned int idx,unsigned int lanes)39ec8b1fbeSJakub Kicinski nfp_devlink_set_lanes(struct nfp_pf *pf, unsigned int idx, unsigned int lanes)
40ec8b1fbeSJakub Kicinski {
41ec8b1fbeSJakub Kicinski 	struct nfp_nsp *nsp;
42ec8b1fbeSJakub Kicinski 	int ret;
43ec8b1fbeSJakub Kicinski 
44ec8b1fbeSJakub Kicinski 	nsp = nfp_eth_config_start(pf->cpp, idx);
45ec8b1fbeSJakub Kicinski 	if (IS_ERR(nsp))
46ec8b1fbeSJakub Kicinski 		return PTR_ERR(nsp);
47ec8b1fbeSJakub Kicinski 
48ec8b1fbeSJakub Kicinski 	ret = __nfp_eth_set_split(nsp, lanes);
49ec8b1fbeSJakub Kicinski 	if (ret) {
50ec8b1fbeSJakub Kicinski 		nfp_eth_config_cleanup_end(nsp);
51ec8b1fbeSJakub Kicinski 		return ret;
52ec8b1fbeSJakub Kicinski 	}
53ec8b1fbeSJakub Kicinski 
54ec8b1fbeSJakub Kicinski 	ret = nfp_eth_config_commit_end(nsp);
55ec8b1fbeSJakub Kicinski 	if (ret < 0)
56ec8b1fbeSJakub Kicinski 		return ret;
57ec8b1fbeSJakub Kicinski 	if (ret) /* no change */
58ec8b1fbeSJakub Kicinski 		return 0;
59ec8b1fbeSJakub Kicinski 
60ec8b1fbeSJakub Kicinski 	return nfp_net_refresh_port_table_sync(pf);
61ec8b1fbeSJakub Kicinski }
62ec8b1fbeSJakub Kicinski 
63ec8b1fbeSJakub Kicinski static int
nfp_devlink_port_split(struct devlink * devlink,struct devlink_port * port,unsigned int count,struct netlink_ext_ack * extack)64706217c1SJakub Kicinski nfp_devlink_port_split(struct devlink *devlink, struct devlink_port *port,
65ac0fc8a1SDavid Ahern 		       unsigned int count, struct netlink_ext_ack *extack)
66ec8b1fbeSJakub Kicinski {
67ec8b1fbeSJakub Kicinski 	struct nfp_pf *pf = devlink_priv(devlink);
68ec8b1fbeSJakub Kicinski 	struct nfp_eth_table_port eth_port;
695948185bSRyan C Goodfellow 	unsigned int lanes;
70ec8b1fbeSJakub Kicinski 	int ret;
71ec8b1fbeSJakub Kicinski 
72ec8b1fbeSJakub Kicinski 	rtnl_lock();
73706217c1SJakub Kicinski 	ret = nfp_devlink_fill_eth_port_from_id(pf, port, &eth_port);
74ec8b1fbeSJakub Kicinski 	rtnl_unlock();
75ec8b1fbeSJakub Kicinski 	if (ret)
7649e83bbeSJakub Kicinski 		return ret;
77ec8b1fbeSJakub Kicinski 
7849e83bbeSJakub Kicinski 	if (eth_port.port_lanes % count)
7949e83bbeSJakub Kicinski 		return -EINVAL;
80ec8b1fbeSJakub Kicinski 
815948185bSRyan C Goodfellow 	/* Special case the 100G CXP -> 2x40G split */
825948185bSRyan C Goodfellow 	lanes = eth_port.port_lanes / count;
835948185bSRyan C Goodfellow 	if (eth_port.lanes == 10 && count == 2)
845948185bSRyan C Goodfellow 		lanes = 8 / count;
855948185bSRyan C Goodfellow 
8649e83bbeSJakub Kicinski 	return nfp_devlink_set_lanes(pf, eth_port.index, lanes);
87ec8b1fbeSJakub Kicinski }
88ec8b1fbeSJakub Kicinski 
89ec8b1fbeSJakub Kicinski static int
nfp_devlink_port_unsplit(struct devlink * devlink,struct devlink_port * port,struct netlink_ext_ack * extack)90706217c1SJakub Kicinski nfp_devlink_port_unsplit(struct devlink *devlink, struct devlink_port *port,
91ac0fc8a1SDavid Ahern 			 struct netlink_ext_ack *extack)
92ec8b1fbeSJakub Kicinski {
93ec8b1fbeSJakub Kicinski 	struct nfp_pf *pf = devlink_priv(devlink);
94ec8b1fbeSJakub Kicinski 	struct nfp_eth_table_port eth_port;
955948185bSRyan C Goodfellow 	unsigned int lanes;
96ec8b1fbeSJakub Kicinski 	int ret;
97ec8b1fbeSJakub Kicinski 
98ec8b1fbeSJakub Kicinski 	rtnl_lock();
99706217c1SJakub Kicinski 	ret = nfp_devlink_fill_eth_port_from_id(pf, port, &eth_port);
100ec8b1fbeSJakub Kicinski 	rtnl_unlock();
101ec8b1fbeSJakub Kicinski 	if (ret)
10249e83bbeSJakub Kicinski 		return ret;
103ec8b1fbeSJakub Kicinski 
10449e83bbeSJakub Kicinski 	if (!eth_port.is_split)
10549e83bbeSJakub Kicinski 		return -EINVAL;
106ec8b1fbeSJakub Kicinski 
1075948185bSRyan C Goodfellow 	/* Special case the 100G CXP -> 2x40G unsplit */
1085948185bSRyan C Goodfellow 	lanes = eth_port.port_lanes;
1095948185bSRyan C Goodfellow 	if (eth_port.port_lanes == 8)
1105948185bSRyan C Goodfellow 		lanes = 10;
1115948185bSRyan C Goodfellow 
11249e83bbeSJakub Kicinski 	return nfp_devlink_set_lanes(pf, eth_port.index, lanes);
113ec8b1fbeSJakub Kicinski }
114ec8b1fbeSJakub Kicinski 
115a0d163f4SJakub Kicinski static int
nfp_devlink_sb_pool_get(struct devlink * devlink,unsigned int sb_index,u16 pool_index,struct devlink_sb_pool_info * pool_info)116a0d163f4SJakub Kicinski nfp_devlink_sb_pool_get(struct devlink *devlink, unsigned int sb_index,
117a0d163f4SJakub Kicinski 			u16 pool_index, struct devlink_sb_pool_info *pool_info)
118a0d163f4SJakub Kicinski {
119a0d163f4SJakub Kicinski 	struct nfp_pf *pf = devlink_priv(devlink);
120a0d163f4SJakub Kicinski 
121a0d163f4SJakub Kicinski 	return nfp_shared_buf_pool_get(pf, sb_index, pool_index, pool_info);
122a0d163f4SJakub Kicinski }
123a0d163f4SJakub Kicinski 
124a0d163f4SJakub Kicinski static int
nfp_devlink_sb_pool_set(struct devlink * devlink,unsigned int sb_index,u16 pool_index,u32 size,enum devlink_sb_threshold_type threshold_type,struct netlink_ext_ack * extack)125a0d163f4SJakub Kicinski nfp_devlink_sb_pool_set(struct devlink *devlink, unsigned int sb_index,
126a0d163f4SJakub Kicinski 			u16 pool_index,
127f2ad1a52SIdo Schimmel 			u32 size, enum devlink_sb_threshold_type threshold_type,
128f2ad1a52SIdo Schimmel 			struct netlink_ext_ack *extack)
129a0d163f4SJakub Kicinski {
130a0d163f4SJakub Kicinski 	struct nfp_pf *pf = devlink_priv(devlink);
131a0d163f4SJakub Kicinski 
132a0d163f4SJakub Kicinski 	return nfp_shared_buf_pool_set(pf, sb_index, pool_index,
133a0d163f4SJakub Kicinski 				       size, threshold_type);
134a0d163f4SJakub Kicinski }
135a0d163f4SJakub Kicinski 
nfp_devlink_eswitch_mode_get(struct devlink * devlink,u16 * mode)1369daee04aSJakub Kicinski static int nfp_devlink_eswitch_mode_get(struct devlink *devlink, u16 *mode)
1379daee04aSJakub Kicinski {
1389daee04aSJakub Kicinski 	struct nfp_pf *pf = devlink_priv(devlink);
1399daee04aSJakub Kicinski 
140bcc93a23SJakub Kicinski 	return nfp_app_eswitch_mode_get(pf->app, mode);
1419daee04aSJakub Kicinski }
1429daee04aSJakub Kicinski 
nfp_devlink_eswitch_mode_set(struct devlink * devlink,u16 mode,struct netlink_ext_ack * extack)143db7ff19eSEli Britstein static int nfp_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode,
144db7ff19eSEli Britstein 					struct netlink_ext_ack *extack)
1454afa3af4SJakub Kicinski {
1464afa3af4SJakub Kicinski 	struct nfp_pf *pf = devlink_priv(devlink);
1474afa3af4SJakub Kicinski 
14814e426bfSJakub Kicinski 	return nfp_app_eswitch_mode_set(pf->app, mode);
1494afa3af4SJakub Kicinski }
1504afa3af4SJakub Kicinski 
151937a3e26SJakub Kicinski static const struct nfp_devlink_versions_simple {
152937a3e26SJakub Kicinski 	const char *key;
153937a3e26SJakub Kicinski 	const char *hwinfo;
154937a3e26SJakub Kicinski } nfp_devlink_versions_hwinfo[] = {
155937a3e26SJakub Kicinski 	{ DEVLINK_INFO_VERSION_GENERIC_BOARD_ID,	"assembly.partno", },
156937a3e26SJakub Kicinski 	{ DEVLINK_INFO_VERSION_GENERIC_BOARD_REV,	"assembly.revision", },
15705fe4ab7SJakub Kicinski 	{ DEVLINK_INFO_VERSION_GENERIC_BOARD_MANUFACTURE, "assembly.vendor", },
158937a3e26SJakub Kicinski 	{ "board.model", /* code name */		"assembly.model", },
159937a3e26SJakub Kicinski };
160937a3e26SJakub Kicinski 
161937a3e26SJakub Kicinski static int
nfp_devlink_versions_get_hwinfo(struct nfp_pf * pf,struct devlink_info_req * req)162937a3e26SJakub Kicinski nfp_devlink_versions_get_hwinfo(struct nfp_pf *pf, struct devlink_info_req *req)
163937a3e26SJakub Kicinski {
164937a3e26SJakub Kicinski 	unsigned int i;
165937a3e26SJakub Kicinski 	int err;
166937a3e26SJakub Kicinski 
167937a3e26SJakub Kicinski 	for (i = 0; i < ARRAY_SIZE(nfp_devlink_versions_hwinfo); i++) {
168937a3e26SJakub Kicinski 		const struct nfp_devlink_versions_simple *info;
169937a3e26SJakub Kicinski 		const char *val;
170937a3e26SJakub Kicinski 
171937a3e26SJakub Kicinski 		info = &nfp_devlink_versions_hwinfo[i];
172937a3e26SJakub Kicinski 
173937a3e26SJakub Kicinski 		val = nfp_hwinfo_lookup(pf->hwinfo, info->hwinfo);
174937a3e26SJakub Kicinski 		if (!val)
175937a3e26SJakub Kicinski 			continue;
176937a3e26SJakub Kicinski 
177937a3e26SJakub Kicinski 		err = devlink_info_version_fixed_put(req, info->key, val);
178937a3e26SJakub Kicinski 		if (err)
179937a3e26SJakub Kicinski 			return err;
180937a3e26SJakub Kicinski 	}
181937a3e26SJakub Kicinski 
182937a3e26SJakub Kicinski 	return 0;
183937a3e26SJakub Kicinski }
184937a3e26SJakub Kicinski 
1857c908f46SJakub Kicinski static const struct nfp_devlink_versions {
1867c908f46SJakub Kicinski 	enum nfp_nsp_versions id;
1877c908f46SJakub Kicinski 	const char *key;
1887c908f46SJakub Kicinski } nfp_devlink_versions_nsp[] = {
189c90977a3SJacob Keller 	{ NFP_VERSIONS_BUNDLE,	DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID, },
1907c908f46SJakub Kicinski 	{ NFP_VERSIONS_BSP,	DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, },
1917c908f46SJakub Kicinski 	{ NFP_VERSIONS_CPLD,	"fw.cpld", },
1927c908f46SJakub Kicinski 	{ NFP_VERSIONS_APP,	DEVLINK_INFO_VERSION_GENERIC_FW_APP, },
1937c908f46SJakub Kicinski 	{ NFP_VERSIONS_UNDI,	DEVLINK_INFO_VERSION_GENERIC_FW_UNDI, },
1947c908f46SJakub Kicinski 	{ NFP_VERSIONS_NCSI,	DEVLINK_INFO_VERSION_GENERIC_FW_NCSI, },
1957c908f46SJakub Kicinski 	{ NFP_VERSIONS_CFGR,	"chip.init", },
1967c908f46SJakub Kicinski };
1977c908f46SJakub Kicinski 
1987c908f46SJakub Kicinski static int
nfp_devlink_versions_get_nsp(struct devlink_info_req * req,bool flash,const u8 * buf,unsigned int size)1997c908f46SJakub Kicinski nfp_devlink_versions_get_nsp(struct devlink_info_req *req, bool flash,
2007c908f46SJakub Kicinski 			     const u8 *buf, unsigned int size)
2017c908f46SJakub Kicinski {
2027c908f46SJakub Kicinski 	unsigned int i;
2037c908f46SJakub Kicinski 	int err;
2047c908f46SJakub Kicinski 
2057c908f46SJakub Kicinski 	for (i = 0; i < ARRAY_SIZE(nfp_devlink_versions_nsp); i++) {
2067c908f46SJakub Kicinski 		const struct nfp_devlink_versions *info;
2077c908f46SJakub Kicinski 		const char *version;
2087c908f46SJakub Kicinski 
2097c908f46SJakub Kicinski 		info = &nfp_devlink_versions_nsp[i];
2107c908f46SJakub Kicinski 
2117c908f46SJakub Kicinski 		version = nfp_nsp_versions_get(info->id, flash, buf, size);
2127c908f46SJakub Kicinski 		if (IS_ERR(version)) {
2137c908f46SJakub Kicinski 			if (PTR_ERR(version) == -ENOENT)
2147c908f46SJakub Kicinski 				continue;
2157c908f46SJakub Kicinski 			else
2167c908f46SJakub Kicinski 				return PTR_ERR(version);
2177c908f46SJakub Kicinski 		}
2187c908f46SJakub Kicinski 
2197c908f46SJakub Kicinski 		if (flash)
2207c908f46SJakub Kicinski 			err = devlink_info_version_stored_put(req, info->key,
2217c908f46SJakub Kicinski 							      version);
2227c908f46SJakub Kicinski 		else
2237c908f46SJakub Kicinski 			err = devlink_info_version_running_put(req, info->key,
2247c908f46SJakub Kicinski 							       version);
2257c908f46SJakub Kicinski 		if (err)
2267c908f46SJakub Kicinski 			return err;
2277c908f46SJakub Kicinski 	}
2287c908f46SJakub Kicinski 
2297c908f46SJakub Kicinski 	return 0;
2307c908f46SJakub Kicinski }
2317c908f46SJakub Kicinski 
2324adba008SJakub Kicinski static int
nfp_devlink_info_get(struct devlink * devlink,struct devlink_info_req * req,struct netlink_ext_ack * extack)2334adba008SJakub Kicinski nfp_devlink_info_get(struct devlink *devlink, struct devlink_info_req *req,
2344adba008SJakub Kicinski 		     struct netlink_ext_ack *extack)
2354adba008SJakub Kicinski {
2364adba008SJakub Kicinski 	struct nfp_pf *pf = devlink_priv(devlink);
2371f5cf103SJakub Kicinski 	const char *sn, *vendor, *part;
2387c908f46SJakub Kicinski 	struct nfp_nsp *nsp;
2397c908f46SJakub Kicinski 	char *buf = NULL;
2404adba008SJakub Kicinski 	int err;
2414adba008SJakub Kicinski 
2421f5cf103SJakub Kicinski 	vendor = nfp_hwinfo_lookup(pf->hwinfo, "assembly.vendor");
2431f5cf103SJakub Kicinski 	part = nfp_hwinfo_lookup(pf->hwinfo, "assembly.partno");
2444adba008SJakub Kicinski 	sn = nfp_hwinfo_lookup(pf->hwinfo, "assembly.serial");
2451f5cf103SJakub Kicinski 	if (vendor && part && sn) {
2461f5cf103SJakub Kicinski 		char *buf;
2471f5cf103SJakub Kicinski 
2481f5cf103SJakub Kicinski 		buf = kmalloc(strlen(vendor) + strlen(part) + strlen(sn) + 1,
2491f5cf103SJakub Kicinski 			      GFP_KERNEL);
2501f5cf103SJakub Kicinski 		if (!buf)
2511f5cf103SJakub Kicinski 			return -ENOMEM;
2521f5cf103SJakub Kicinski 
2531f5cf103SJakub Kicinski 		buf[0] = '\0';
2541f5cf103SJakub Kicinski 		strcat(buf, vendor);
2551f5cf103SJakub Kicinski 		strcat(buf, part);
2561f5cf103SJakub Kicinski 		strcat(buf, sn);
2571f5cf103SJakub Kicinski 
2581f5cf103SJakub Kicinski 		err = devlink_info_serial_number_put(req, buf);
2591f5cf103SJakub Kicinski 		kfree(buf);
2604adba008SJakub Kicinski 		if (err)
2614adba008SJakub Kicinski 			return err;
2624adba008SJakub Kicinski 	}
2634adba008SJakub Kicinski 
2647c908f46SJakub Kicinski 	nsp = nfp_nsp_open(pf->cpp);
2657c908f46SJakub Kicinski 	if (IS_ERR(nsp)) {
2667c908f46SJakub Kicinski 		NL_SET_ERR_MSG_MOD(extack, "can't access NSP");
2677c908f46SJakub Kicinski 		return PTR_ERR(nsp);
2687c908f46SJakub Kicinski 	}
2697c908f46SJakub Kicinski 
2707c908f46SJakub Kicinski 	if (nfp_nsp_has_versions(nsp)) {
2717c908f46SJakub Kicinski 		buf = kzalloc(NFP_NSP_VERSION_BUFSZ, GFP_KERNEL);
2727c908f46SJakub Kicinski 		if (!buf) {
2737c908f46SJakub Kicinski 			err = -ENOMEM;
2747c908f46SJakub Kicinski 			goto err_close_nsp;
2757c908f46SJakub Kicinski 		}
2767c908f46SJakub Kicinski 
2777c908f46SJakub Kicinski 		err = nfp_nsp_versions(nsp, buf, NFP_NSP_VERSION_BUFSZ);
2787c908f46SJakub Kicinski 		if (err)
2797c908f46SJakub Kicinski 			goto err_free_buf;
2807c908f46SJakub Kicinski 
2817c908f46SJakub Kicinski 		err = nfp_devlink_versions_get_nsp(req, false,
2827c908f46SJakub Kicinski 						   buf, NFP_NSP_VERSION_BUFSZ);
2837c908f46SJakub Kicinski 		if (err)
2847c908f46SJakub Kicinski 			goto err_free_buf;
2857c908f46SJakub Kicinski 
2867c908f46SJakub Kicinski 		err = nfp_devlink_versions_get_nsp(req, true,
2877c908f46SJakub Kicinski 						   buf, NFP_NSP_VERSION_BUFSZ);
2887c908f46SJakub Kicinski 		if (err)
2897c908f46SJakub Kicinski 			goto err_free_buf;
2907c908f46SJakub Kicinski 
2917c908f46SJakub Kicinski 		kfree(buf);
2927c908f46SJakub Kicinski 	}
2937c908f46SJakub Kicinski 
2947c908f46SJakub Kicinski 	nfp_nsp_close(nsp);
2957c908f46SJakub Kicinski 
296937a3e26SJakub Kicinski 	return nfp_devlink_versions_get_hwinfo(pf, req);
2977c908f46SJakub Kicinski 
2987c908f46SJakub Kicinski err_free_buf:
2997c908f46SJakub Kicinski 	kfree(buf);
3007c908f46SJakub Kicinski err_close_nsp:
3017c908f46SJakub Kicinski 	nfp_nsp_close(nsp);
3027c908f46SJakub Kicinski 	return err;
3034adba008SJakub Kicinski }
3044adba008SJakub Kicinski 
3055c5696f3SJakub Kicinski static int
nfp_devlink_flash_update(struct devlink * devlink,struct devlink_flash_update_params * params,struct netlink_ext_ack * extack)306bc75c054SJacob Keller nfp_devlink_flash_update(struct devlink *devlink,
307bc75c054SJacob Keller 			 struct devlink_flash_update_params *params,
308bc75c054SJacob Keller 			 struct netlink_ext_ack *extack)
3095c5696f3SJakub Kicinski {
310b44cfd4fSJacob Keller 	return nfp_flash_update_common(devlink_priv(devlink), params->fw, extack);
3115c5696f3SJakub Kicinski }
3125c5696f3SJakub Kicinski 
3131851f93fSSimon Horman const struct devlink_ops nfp_devlink_ops = {
314a0d163f4SJakub Kicinski 	.sb_pool_get		= nfp_devlink_sb_pool_get,
315a0d163f4SJakub Kicinski 	.sb_pool_set		= nfp_devlink_sb_pool_set,
3169daee04aSJakub Kicinski 	.eswitch_mode_get	= nfp_devlink_eswitch_mode_get,
3174afa3af4SJakub Kicinski 	.eswitch_mode_set	= nfp_devlink_eswitch_mode_set,
3184adba008SJakub Kicinski 	.info_get		= nfp_devlink_info_get,
3195c5696f3SJakub Kicinski 	.flash_update		= nfp_devlink_flash_update,
3201851f93fSSimon Horman };
32153e7a08fSJakub Kicinski 
322ab8ccc6cSJiri Pirko static const struct devlink_port_ops nfp_devlink_port_ops = {
323*f58a3e4dSJiri Pirko 	.port_split		= nfp_devlink_port_split,
324*f58a3e4dSJiri Pirko 	.port_unsplit		= nfp_devlink_port_unsplit,
325ab8ccc6cSJiri Pirko };
326ab8ccc6cSJiri Pirko 
nfp_devlink_port_register(struct nfp_app * app,struct nfp_port * port)32753e7a08fSJakub Kicinski int nfp_devlink_port_register(struct nfp_app *app, struct nfp_port *port)
32853e7a08fSJakub Kicinski {
32971ad8d55SDanielle Ratson 	struct devlink_port_attrs attrs = {};
33053e7a08fSJakub Kicinski 	struct nfp_eth_table_port eth_port;
33153e7a08fSJakub Kicinski 	struct devlink *devlink;
3321b15c902SJiri Pirko 	const u8 *serial;
3331b15c902SJiri Pirko 	int serial_len;
33453e7a08fSJakub Kicinski 	int ret;
33553e7a08fSJakub Kicinski 
336ac73d4bfSJiri Pirko 	SET_NETDEV_DEVLINK_PORT(port->netdev, &port->dl_port);
337ac73d4bfSJiri Pirko 
33853e7a08fSJakub Kicinski 	rtnl_lock();
33953e7a08fSJakub Kicinski 	ret = nfp_devlink_fill_eth_port(port, &eth_port);
34053e7a08fSJakub Kicinski 	rtnl_unlock();
34153e7a08fSJakub Kicinski 	if (ret)
34253e7a08fSJakub Kicinski 		return ret;
34353e7a08fSJakub Kicinski 
34471ad8d55SDanielle Ratson 	attrs.split = eth_port.is_split;
3454abd9600SDiana Wang 	attrs.splittable = eth_port.port_lanes > 1 && !attrs.split;
34690b669d6SYinjun Zhang 	attrs.lanes = eth_port.port_lanes;
34771ad8d55SDanielle Ratson 	attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
34871ad8d55SDanielle Ratson 	attrs.phys.port_number = eth_port.label_port;
34971ad8d55SDanielle Ratson 	attrs.phys.split_subport_number = eth_port.label_subport;
3501b15c902SJiri Pirko 	serial_len = nfp_cpp_serial(port->app->cpp, &serial);
35171ad8d55SDanielle Ratson 	memcpy(attrs.switch_id.id, serial, serial_len);
35271ad8d55SDanielle Ratson 	attrs.switch_id.id_len = serial_len;
35371ad8d55SDanielle Ratson 	devlink_port_attrs_set(&port->dl_port, &attrs);
35453e7a08fSJakub Kicinski 
35553e7a08fSJakub Kicinski 	devlink = priv_to_devlink(app->pf);
35653e7a08fSJakub Kicinski 
357ab8ccc6cSJiri Pirko 	return devl_port_register_with_ops(devlink, &port->dl_port,
358ab8ccc6cSJiri Pirko 					   port->eth_id, &nfp_devlink_port_ops);
35953e7a08fSJakub Kicinski }
36053e7a08fSJakub Kicinski 
nfp_devlink_port_unregister(struct nfp_port * port)36153e7a08fSJakub Kicinski void nfp_devlink_port_unregister(struct nfp_port *port)
36253e7a08fSJakub Kicinski {
363162cca42SJakub Kicinski 	devl_port_unregister(&port->dl_port);
36453e7a08fSJakub Kicinski }
365