1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2 /* Copyright (C) 2017-2018 Netronome Systems, Inc. */
4 #include <linux/rtnetlink.h>
5 #include <net/devlink.h>
7 #include "nfpcore/nfp.h"
8 #include "nfpcore/nfp_nsp.h"
14 nfp_devlink_fill_eth_port(struct nfp_port
*port
,
15 struct nfp_eth_table_port
*copy
)
17 struct nfp_eth_table_port
*eth_port
;
19 eth_port
= __nfp_port_get_eth_port(port
);
23 memcpy(copy
, eth_port
, sizeof(*eth_port
));
29 nfp_devlink_fill_eth_port_from_id(struct nfp_pf
*pf
,
30 struct devlink_port
*dl_port
,
31 struct nfp_eth_table_port
*copy
)
33 struct nfp_port
*port
= container_of(dl_port
, struct nfp_port
, dl_port
);
35 return nfp_devlink_fill_eth_port(port
, copy
);
39 nfp_devlink_set_lanes(struct nfp_pf
*pf
, unsigned int idx
, unsigned int lanes
)
44 nsp
= nfp_eth_config_start(pf
->cpp
, idx
);
48 ret
= __nfp_eth_set_split(nsp
, lanes
);
50 nfp_eth_config_cleanup_end(nsp
);
54 ret
= nfp_eth_config_commit_end(nsp
);
57 if (ret
) /* no change */
60 return nfp_net_refresh_port_table_sync(pf
);
64 nfp_devlink_port_split(struct devlink
*devlink
, struct devlink_port
*port
,
65 unsigned int count
, struct netlink_ext_ack
*extack
)
67 struct nfp_pf
*pf
= devlink_priv(devlink
);
68 struct nfp_eth_table_port eth_port
;
73 ret
= nfp_devlink_fill_eth_port_from_id(pf
, port
, ð_port
);
78 if (eth_port
.port_lanes
% count
) {
79 NL_SET_ERR_MSG_MOD(extack
, "invalid count");
83 /* Special case the 100G CXP -> 2x40G split */
84 lanes
= eth_port
.port_lanes
/ count
;
85 if (eth_port
.lanes
== 10 && count
== 2)
88 return nfp_devlink_set_lanes(pf
, eth_port
.index
, lanes
);
92 nfp_devlink_port_unsplit(struct devlink
*devlink
, struct devlink_port
*port
,
93 struct netlink_ext_ack
*extack
)
95 struct nfp_pf
*pf
= devlink_priv(devlink
);
96 struct nfp_eth_table_port eth_port
;
101 ret
= nfp_devlink_fill_eth_port_from_id(pf
, port
, ð_port
);
106 if (!eth_port
.is_split
) {
107 NL_SET_ERR_MSG_MOD(extack
, "port is not split");
111 /* Special case the 100G CXP -> 2x40G unsplit */
112 lanes
= eth_port
.port_lanes
;
113 if (eth_port
.port_lanes
== 8)
116 return nfp_devlink_set_lanes(pf
, eth_port
.index
, lanes
);
120 nfp_devlink_sb_pool_get(struct devlink
*devlink
, unsigned int sb_index
,
121 u16 pool_index
, struct devlink_sb_pool_info
*pool_info
)
123 struct nfp_pf
*pf
= devlink_priv(devlink
);
125 return nfp_shared_buf_pool_get(pf
, sb_index
, pool_index
, pool_info
);
129 nfp_devlink_sb_pool_set(struct devlink
*devlink
, unsigned int sb_index
,
131 u32 size
, enum devlink_sb_threshold_type threshold_type
,
132 struct netlink_ext_ack
*extack
)
134 struct nfp_pf
*pf
= devlink_priv(devlink
);
136 return nfp_shared_buf_pool_set(pf
, sb_index
, pool_index
,
137 size
, threshold_type
);
140 static int nfp_devlink_eswitch_mode_get(struct devlink
*devlink
, u16
*mode
)
142 struct nfp_pf
*pf
= devlink_priv(devlink
);
144 return nfp_app_eswitch_mode_get(pf
->app
, mode
);
147 static int nfp_devlink_eswitch_mode_set(struct devlink
*devlink
, u16 mode
,
148 struct netlink_ext_ack
*extack
)
150 struct nfp_pf
*pf
= devlink_priv(devlink
);
152 return nfp_app_eswitch_mode_set(pf
->app
, mode
);
155 static const struct nfp_devlink_versions_simple
{
158 } nfp_devlink_versions_hwinfo
[] = {
159 { DEVLINK_INFO_VERSION_GENERIC_BOARD_ID
, "assembly.partno", },
160 { DEVLINK_INFO_VERSION_GENERIC_BOARD_REV
, "assembly.revision", },
161 { DEVLINK_INFO_VERSION_GENERIC_BOARD_MANUFACTURE
, "assembly.vendor", },
162 { "board.model", /* code name */ "assembly.model", },
163 { DEVLINK_INFO_VERSION_GENERIC_BOARD_PART_NUMBER
, "pn", },
167 nfp_devlink_versions_get_hwinfo(struct nfp_pf
*pf
, struct devlink_info_req
*req
)
172 for (i
= 0; i
< ARRAY_SIZE(nfp_devlink_versions_hwinfo
); i
++) {
173 const struct nfp_devlink_versions_simple
*info
;
176 info
= &nfp_devlink_versions_hwinfo
[i
];
178 val
= nfp_hwinfo_lookup(pf
->hwinfo
, info
->hwinfo
);
182 err
= devlink_info_version_fixed_put(req
, info
->key
, val
);
190 static const struct nfp_devlink_versions
{
191 enum nfp_nsp_versions id
;
193 } nfp_devlink_versions_nsp
[] = {
194 { NFP_VERSIONS_BUNDLE
, DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID
, },
195 { NFP_VERSIONS_BSP
, DEVLINK_INFO_VERSION_GENERIC_FW_MGMT
, },
196 { NFP_VERSIONS_CPLD
, "fw.cpld", },
197 { NFP_VERSIONS_APP
, DEVLINK_INFO_VERSION_GENERIC_FW_APP
, },
198 { NFP_VERSIONS_UNDI
, DEVLINK_INFO_VERSION_GENERIC_FW_UNDI
, },
199 { NFP_VERSIONS_NCSI
, DEVLINK_INFO_VERSION_GENERIC_FW_NCSI
, },
200 { NFP_VERSIONS_CFGR
, "chip.init", },
204 nfp_devlink_versions_get_nsp(struct devlink_info_req
*req
, bool flash
,
205 const u8
*buf
, unsigned int size
)
210 for (i
= 0; i
< ARRAY_SIZE(nfp_devlink_versions_nsp
); i
++) {
211 const struct nfp_devlink_versions
*info
;
214 info
= &nfp_devlink_versions_nsp
[i
];
216 version
= nfp_nsp_versions_get(info
->id
, flash
, buf
, size
);
217 if (IS_ERR(version
)) {
218 if (PTR_ERR(version
) == -ENOENT
)
221 return PTR_ERR(version
);
225 err
= devlink_info_version_stored_put(req
, info
->key
,
228 err
= devlink_info_version_running_put(req
, info
->key
,
238 nfp_devlink_info_get(struct devlink
*devlink
, struct devlink_info_req
*req
,
239 struct netlink_ext_ack
*extack
)
241 struct nfp_pf
*pf
= devlink_priv(devlink
);
242 const char *sn
, *vendor
, *part
;
247 vendor
= nfp_hwinfo_lookup(pf
->hwinfo
, "assembly.vendor");
248 part
= nfp_hwinfo_lookup(pf
->hwinfo
, "assembly.partno");
249 sn
= nfp_hwinfo_lookup(pf
->hwinfo
, "assembly.serial");
250 if (vendor
&& part
&& sn
) {
253 buf
= kmalloc(strlen(vendor
) + strlen(part
) + strlen(sn
) + 1,
263 err
= devlink_info_serial_number_put(req
, buf
);
269 nsp
= nfp_nsp_open(pf
->cpp
);
271 NL_SET_ERR_MSG_MOD(extack
, "can't access NSP");
275 if (nfp_nsp_has_versions(nsp
)) {
276 buf
= kzalloc(NFP_NSP_VERSION_BUFSZ
, GFP_KERNEL
);
282 err
= nfp_nsp_versions(nsp
, buf
, NFP_NSP_VERSION_BUFSZ
);
286 err
= nfp_devlink_versions_get_nsp(req
, false,
287 buf
, NFP_NSP_VERSION_BUFSZ
);
291 err
= nfp_devlink_versions_get_nsp(req
, true,
292 buf
, NFP_NSP_VERSION_BUFSZ
);
301 return nfp_devlink_versions_get_hwinfo(pf
, req
);
311 nfp_devlink_flash_update(struct devlink
*devlink
,
312 struct devlink_flash_update_params
*params
,
313 struct netlink_ext_ack
*extack
)
315 return nfp_flash_update_common(devlink_priv(devlink
), params
->fw
, extack
);
318 const struct devlink_ops nfp_devlink_ops
= {
319 .sb_pool_get
= nfp_devlink_sb_pool_get
,
320 .sb_pool_set
= nfp_devlink_sb_pool_set
,
321 .eswitch_mode_get
= nfp_devlink_eswitch_mode_get
,
322 .eswitch_mode_set
= nfp_devlink_eswitch_mode_set
,
323 .info_get
= nfp_devlink_info_get
,
324 .flash_update
= nfp_devlink_flash_update
,
327 static const struct devlink_port_ops nfp_devlink_port_ops
= {
328 .port_split
= nfp_devlink_port_split
,
329 .port_unsplit
= nfp_devlink_port_unsplit
,
332 int nfp_devlink_port_register(struct nfp_app
*app
, struct nfp_port
*port
)
334 struct devlink_port_attrs attrs
= {};
335 struct nfp_eth_table_port eth_port
;
336 struct devlink
*devlink
;
341 SET_NETDEV_DEVLINK_PORT(port
->netdev
, &port
->dl_port
);
344 ret
= nfp_devlink_fill_eth_port(port
, ð_port
);
349 attrs
.split
= eth_port
.is_split
;
350 attrs
.splittable
= eth_port
.port_lanes
> 1 && !attrs
.split
;
351 attrs
.lanes
= eth_port
.port_lanes
;
352 attrs
.flavour
= DEVLINK_PORT_FLAVOUR_PHYSICAL
;
353 attrs
.phys
.port_number
= eth_port
.label_port
;
354 attrs
.phys
.split_subport_number
= eth_port
.label_subport
;
355 serial_len
= nfp_cpp_serial(port
->app
->cpp
, &serial
);
356 memcpy(attrs
.switch_id
.id
, serial
, serial_len
);
357 attrs
.switch_id
.id_len
= serial_len
;
358 devlink_port_attrs_set(&port
->dl_port
, &attrs
);
360 devlink
= priv_to_devlink(app
->pf
);
362 return devl_port_register_with_ops(devlink
, &port
->dl_port
,
363 port
->eth_id
, &nfp_devlink_port_ops
);
366 void nfp_devlink_port_unregister(struct nfp_port
*port
)
368 devl_port_unregister(&port
->dl_port
);