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
, unsigned int port_index
,
30 struct nfp_eth_table_port
*copy
)
32 struct nfp_port
*port
;
34 port
= nfp_port_from_id(pf
, NFP_PORT_PHYS_PORT
, port_index
);
36 return nfp_devlink_fill_eth_port(port
, copy
);
40 nfp_devlink_set_lanes(struct nfp_pf
*pf
, unsigned int idx
, unsigned int lanes
)
45 nsp
= nfp_eth_config_start(pf
->cpp
, idx
);
49 ret
= __nfp_eth_set_split(nsp
, lanes
);
51 nfp_eth_config_cleanup_end(nsp
);
55 ret
= nfp_eth_config_commit_end(nsp
);
58 if (ret
) /* no change */
61 return nfp_net_refresh_port_table_sync(pf
);
65 nfp_devlink_port_split(struct devlink
*devlink
, unsigned int port_index
,
66 unsigned int count
, struct netlink_ext_ack
*extack
)
68 struct nfp_pf
*pf
= devlink_priv(devlink
);
69 struct nfp_eth_table_port eth_port
;
73 mutex_lock(&pf
->lock
);
76 ret
= nfp_devlink_fill_eth_port_from_id(pf
, port_index
, ð_port
);
81 if (eth_port
.port_lanes
% count
) {
86 /* Special case the 100G CXP -> 2x40G split */
87 lanes
= eth_port
.port_lanes
/ count
;
88 if (eth_port
.lanes
== 10 && count
== 2)
91 ret
= nfp_devlink_set_lanes(pf
, eth_port
.index
, lanes
);
93 mutex_unlock(&pf
->lock
);
99 nfp_devlink_port_unsplit(struct devlink
*devlink
, unsigned int port_index
,
100 struct netlink_ext_ack
*extack
)
102 struct nfp_pf
*pf
= devlink_priv(devlink
);
103 struct nfp_eth_table_port eth_port
;
107 mutex_lock(&pf
->lock
);
110 ret
= nfp_devlink_fill_eth_port_from_id(pf
, port_index
, ð_port
);
115 if (!eth_port
.is_split
) {
120 /* Special case the 100G CXP -> 2x40G unsplit */
121 lanes
= eth_port
.port_lanes
;
122 if (eth_port
.port_lanes
== 8)
125 ret
= nfp_devlink_set_lanes(pf
, eth_port
.index
, lanes
);
127 mutex_unlock(&pf
->lock
);
133 nfp_devlink_sb_pool_get(struct devlink
*devlink
, unsigned int sb_index
,
134 u16 pool_index
, struct devlink_sb_pool_info
*pool_info
)
136 struct nfp_pf
*pf
= devlink_priv(devlink
);
138 return nfp_shared_buf_pool_get(pf
, sb_index
, pool_index
, pool_info
);
142 nfp_devlink_sb_pool_set(struct devlink
*devlink
, unsigned int sb_index
,
144 u32 size
, enum devlink_sb_threshold_type threshold_type
,
145 struct netlink_ext_ack
*extack
)
147 struct nfp_pf
*pf
= devlink_priv(devlink
);
149 return nfp_shared_buf_pool_set(pf
, sb_index
, pool_index
,
150 size
, threshold_type
);
153 static int nfp_devlink_eswitch_mode_get(struct devlink
*devlink
, u16
*mode
)
155 struct nfp_pf
*pf
= devlink_priv(devlink
);
157 return nfp_app_eswitch_mode_get(pf
->app
, mode
);
160 static int nfp_devlink_eswitch_mode_set(struct devlink
*devlink
, u16 mode
,
161 struct netlink_ext_ack
*extack
)
163 struct nfp_pf
*pf
= devlink_priv(devlink
);
166 mutex_lock(&pf
->lock
);
167 ret
= nfp_app_eswitch_mode_set(pf
->app
, mode
);
168 mutex_unlock(&pf
->lock
);
173 static const struct nfp_devlink_versions_simple
{
176 } nfp_devlink_versions_hwinfo
[] = {
177 { DEVLINK_INFO_VERSION_GENERIC_BOARD_ID
, "assembly.partno", },
178 { DEVLINK_INFO_VERSION_GENERIC_BOARD_REV
, "assembly.revision", },
179 { DEVLINK_INFO_VERSION_GENERIC_BOARD_MANUFACTURE
, "assembly.vendor", },
180 { "board.model", /* code name */ "assembly.model", },
184 nfp_devlink_versions_get_hwinfo(struct nfp_pf
*pf
, struct devlink_info_req
*req
)
189 for (i
= 0; i
< ARRAY_SIZE(nfp_devlink_versions_hwinfo
); i
++) {
190 const struct nfp_devlink_versions_simple
*info
;
193 info
= &nfp_devlink_versions_hwinfo
[i
];
195 val
= nfp_hwinfo_lookup(pf
->hwinfo
, info
->hwinfo
);
199 err
= devlink_info_version_fixed_put(req
, info
->key
, val
);
207 static const struct nfp_devlink_versions
{
208 enum nfp_nsp_versions id
;
210 } nfp_devlink_versions_nsp
[] = {
211 { NFP_VERSIONS_BUNDLE
, DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID
, },
212 { NFP_VERSIONS_BSP
, DEVLINK_INFO_VERSION_GENERIC_FW_MGMT
, },
213 { NFP_VERSIONS_CPLD
, "fw.cpld", },
214 { NFP_VERSIONS_APP
, DEVLINK_INFO_VERSION_GENERIC_FW_APP
, },
215 { NFP_VERSIONS_UNDI
, DEVLINK_INFO_VERSION_GENERIC_FW_UNDI
, },
216 { NFP_VERSIONS_NCSI
, DEVLINK_INFO_VERSION_GENERIC_FW_NCSI
, },
217 { NFP_VERSIONS_CFGR
, "chip.init", },
221 nfp_devlink_versions_get_nsp(struct devlink_info_req
*req
, bool flash
,
222 const u8
*buf
, unsigned int size
)
227 for (i
= 0; i
< ARRAY_SIZE(nfp_devlink_versions_nsp
); i
++) {
228 const struct nfp_devlink_versions
*info
;
231 info
= &nfp_devlink_versions_nsp
[i
];
233 version
= nfp_nsp_versions_get(info
->id
, flash
, buf
, size
);
234 if (IS_ERR(version
)) {
235 if (PTR_ERR(version
) == -ENOENT
)
238 return PTR_ERR(version
);
242 err
= devlink_info_version_stored_put(req
, info
->key
,
245 err
= devlink_info_version_running_put(req
, info
->key
,
255 nfp_devlink_info_get(struct devlink
*devlink
, struct devlink_info_req
*req
,
256 struct netlink_ext_ack
*extack
)
258 struct nfp_pf
*pf
= devlink_priv(devlink
);
259 const char *sn
, *vendor
, *part
;
264 err
= devlink_info_driver_name_put(req
, "nfp");
268 vendor
= nfp_hwinfo_lookup(pf
->hwinfo
, "assembly.vendor");
269 part
= nfp_hwinfo_lookup(pf
->hwinfo
, "assembly.partno");
270 sn
= nfp_hwinfo_lookup(pf
->hwinfo
, "assembly.serial");
271 if (vendor
&& part
&& sn
) {
274 buf
= kmalloc(strlen(vendor
) + strlen(part
) + strlen(sn
) + 1,
284 err
= devlink_info_serial_number_put(req
, buf
);
290 nsp
= nfp_nsp_open(pf
->cpp
);
292 NL_SET_ERR_MSG_MOD(extack
, "can't access NSP");
296 if (nfp_nsp_has_versions(nsp
)) {
297 buf
= kzalloc(NFP_NSP_VERSION_BUFSZ
, GFP_KERNEL
);
303 err
= nfp_nsp_versions(nsp
, buf
, NFP_NSP_VERSION_BUFSZ
);
307 err
= nfp_devlink_versions_get_nsp(req
, false,
308 buf
, NFP_NSP_VERSION_BUFSZ
);
312 err
= nfp_devlink_versions_get_nsp(req
, true,
313 buf
, NFP_NSP_VERSION_BUFSZ
);
322 return nfp_devlink_versions_get_hwinfo(pf
, req
);
332 nfp_devlink_flash_update(struct devlink
*devlink
,
333 struct devlink_flash_update_params
*params
,
334 struct netlink_ext_ack
*extack
)
336 return nfp_flash_update_common(devlink_priv(devlink
), params
->fw
, extack
);
339 const struct devlink_ops nfp_devlink_ops
= {
340 .port_split
= nfp_devlink_port_split
,
341 .port_unsplit
= nfp_devlink_port_unsplit
,
342 .sb_pool_get
= nfp_devlink_sb_pool_get
,
343 .sb_pool_set
= nfp_devlink_sb_pool_set
,
344 .eswitch_mode_get
= nfp_devlink_eswitch_mode_get
,
345 .eswitch_mode_set
= nfp_devlink_eswitch_mode_set
,
346 .info_get
= nfp_devlink_info_get
,
347 .flash_update
= nfp_devlink_flash_update
,
350 int nfp_devlink_port_register(struct nfp_app
*app
, struct nfp_port
*port
)
352 struct devlink_port_attrs attrs
= {};
353 struct nfp_eth_table_port eth_port
;
354 struct devlink
*devlink
;
360 ret
= nfp_devlink_fill_eth_port(port
, ð_port
);
365 attrs
.split
= eth_port
.is_split
;
366 attrs
.splittable
= !attrs
.split
;
367 attrs
.flavour
= DEVLINK_PORT_FLAVOUR_PHYSICAL
;
368 attrs
.phys
.port_number
= eth_port
.label_port
;
369 attrs
.phys
.split_subport_number
= eth_port
.label_subport
;
370 serial_len
= nfp_cpp_serial(port
->app
->cpp
, &serial
);
371 memcpy(attrs
.switch_id
.id
, serial
, serial_len
);
372 attrs
.switch_id
.id_len
= serial_len
;
373 devlink_port_attrs_set(&port
->dl_port
, &attrs
);
375 devlink
= priv_to_devlink(app
->pf
);
377 return devlink_port_register(devlink
, &port
->dl_port
, port
->eth_id
);
380 void nfp_devlink_port_unregister(struct nfp_port
*port
)
382 devlink_port_unregister(&port
->dl_port
);
385 void nfp_devlink_port_type_eth_set(struct nfp_port
*port
)
387 devlink_port_type_eth_set(&port
->dl_port
, port
->netdev
);
390 void nfp_devlink_port_type_clear(struct nfp_port
*port
)
392 devlink_port_type_clear(&port
->dl_port
);
395 struct devlink_port
*nfp_devlink_get_devlink_port(struct net_device
*netdev
)
397 struct nfp_port
*port
;
399 port
= nfp_port_from_netdev(netdev
);
403 return &port
->dl_port
;