Author | Tokens | Token Proportion | Commits | Commit Proportion |
---|---|---|---|---|
Jakub Kiciński | 1412 | 85.84% | 27 | 61.36% |
Danielle Ratson | 64 | 3.89% | 2 | 4.55% |
Ryan C Goodfellow | 62 | 3.77% | 1 | 2.27% |
Jiri Pirko | 53 | 3.22% | 7 | 15.91% |
Arkadi Sharshevsky | 30 | 1.82% | 1 | 2.27% |
Simon Horman | 9 | 0.55% | 1 | 2.27% |
Jacob E Keller | 7 | 0.43% | 3 | 6.82% |
Diana Wang | 6 | 0.36% | 1 | 2.27% |
Yinjun Zhang | 2 | 0.12% | 1 | 2.27% |
Total | 1645 | 44 |
// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) /* Copyright (C) 2017-2018 Netronome Systems, Inc. */ #include <linux/rtnetlink.h> #include <net/devlink.h> #include "nfpcore/nfp.h" #include "nfpcore/nfp_nsp.h" #include "nfp_app.h" #include "nfp_main.h" #include "nfp_port.h" static int nfp_devlink_fill_eth_port(struct nfp_port *port, struct nfp_eth_table_port *copy) { struct nfp_eth_table_port *eth_port; eth_port = __nfp_port_get_eth_port(port); if (!eth_port) return -EINVAL; memcpy(copy, eth_port, sizeof(*eth_port)); return 0; } static int nfp_devlink_fill_eth_port_from_id(struct nfp_pf *pf, struct devlink_port *dl_port, struct nfp_eth_table_port *copy) { struct nfp_port *port = container_of(dl_port, struct nfp_port, dl_port); return nfp_devlink_fill_eth_port(port, copy); } static int nfp_devlink_set_lanes(struct nfp_pf *pf, unsigned int idx, unsigned int lanes) { struct nfp_nsp *nsp; int ret; nsp = nfp_eth_config_start(pf->cpp, idx); if (IS_ERR(nsp)) return PTR_ERR(nsp); ret = __nfp_eth_set_split(nsp, lanes); if (ret) { nfp_eth_config_cleanup_end(nsp); return ret; } ret = nfp_eth_config_commit_end(nsp); if (ret < 0) return ret; if (ret) /* no change */ return 0; return nfp_net_refresh_port_table_sync(pf); } static int nfp_devlink_port_split(struct devlink *devlink, struct devlink_port *port, unsigned int count, struct netlink_ext_ack *extack) { struct nfp_pf *pf = devlink_priv(devlink); struct nfp_eth_table_port eth_port; unsigned int lanes; int ret; rtnl_lock(); ret = nfp_devlink_fill_eth_port_from_id(pf, port, ð_port); rtnl_unlock(); if (ret) return ret; if (eth_port.port_lanes % count) return -EINVAL; /* Special case the 100G CXP -> 2x40G split */ lanes = eth_port.port_lanes / count; if (eth_port.lanes == 10 && count == 2) lanes = 8 / count; return nfp_devlink_set_lanes(pf, eth_port.index, lanes); } static int nfp_devlink_port_unsplit(struct devlink *devlink, struct devlink_port *port, struct netlink_ext_ack *extack) { struct nfp_pf *pf = devlink_priv(devlink); struct nfp_eth_table_port eth_port; unsigned int lanes; int ret; rtnl_lock(); ret = nfp_devlink_fill_eth_port_from_id(pf, port, ð_port); rtnl_unlock(); if (ret) return ret; if (!eth_port.is_split) return -EINVAL; /* Special case the 100G CXP -> 2x40G unsplit */ lanes = eth_port.port_lanes; if (eth_port.port_lanes == 8) lanes = 10; return nfp_devlink_set_lanes(pf, eth_port.index, lanes); } static int nfp_devlink_sb_pool_get(struct devlink *devlink, unsigned int sb_index, u16 pool_index, struct devlink_sb_pool_info *pool_info) { struct nfp_pf *pf = devlink_priv(devlink); return nfp_shared_buf_pool_get(pf, sb_index, pool_index, pool_info); } 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) { struct nfp_pf *pf = devlink_priv(devlink); return nfp_shared_buf_pool_set(pf, sb_index, pool_index, size, threshold_type); } static int nfp_devlink_eswitch_mode_get(struct devlink *devlink, u16 *mode) { struct nfp_pf *pf = devlink_priv(devlink); return nfp_app_eswitch_mode_get(pf->app, mode); } static int nfp_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode, struct netlink_ext_ack *extack) { struct nfp_pf *pf = devlink_priv(devlink); return nfp_app_eswitch_mode_set(pf->app, mode); } static const struct nfp_devlink_versions_simple { const char *key; const char *hwinfo; } nfp_devlink_versions_hwinfo[] = { { DEVLINK_INFO_VERSION_GENERIC_BOARD_ID, "assembly.partno", }, { DEVLINK_INFO_VERSION_GENERIC_BOARD_REV, "assembly.revision", }, { DEVLINK_INFO_VERSION_GENERIC_BOARD_MANUFACTURE, "assembly.vendor", }, { "board.model", /* code name */ "assembly.model", }, }; static int nfp_devlink_versions_get_hwinfo(struct nfp_pf *pf, struct devlink_info_req *req) { unsigned int i; int err; for (i = 0; i < ARRAY_SIZE(nfp_devlink_versions_hwinfo); i++) { const struct nfp_devlink_versions_simple *info; const char *val; info = &nfp_devlink_versions_hwinfo[i]; val = nfp_hwinfo_lookup(pf->hwinfo, info->hwinfo); if (!val) continue; err = devlink_info_version_fixed_put(req, info->key, val); if (err) return err; } return 0; } static const struct nfp_devlink_versions { enum nfp_nsp_versions id; const char *key; } nfp_devlink_versions_nsp[] = { { NFP_VERSIONS_BUNDLE, DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID, }, { NFP_VERSIONS_BSP, DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, }, { NFP_VERSIONS_CPLD, "fw.cpld", }, { NFP_VERSIONS_APP, DEVLINK_INFO_VERSION_GENERIC_FW_APP, }, { NFP_VERSIONS_UNDI, DEVLINK_INFO_VERSION_GENERIC_FW_UNDI, }, { NFP_VERSIONS_NCSI, DEVLINK_INFO_VERSION_GENERIC_FW_NCSI, }, { NFP_VERSIONS_CFGR, "chip.init", }, }; static int nfp_devlink_versions_get_nsp(struct devlink_info_req *req, bool flash, const u8 *buf, unsigned int size) { unsigned int i; int err; for (i = 0; i < ARRAY_SIZE(nfp_devlink_versions_nsp); i++) { const struct nfp_devlink_versions *info; const char *version; info = &nfp_devlink_versions_nsp[i]; version = nfp_nsp_versions_get(info->id, flash, buf, size); if (IS_ERR(version)) { if (PTR_ERR(version) == -ENOENT) continue; else return PTR_ERR(version); } if (flash) err = devlink_info_version_stored_put(req, info->key, version); else err = devlink_info_version_running_put(req, info->key, version); if (err) return err; } return 0; } static int nfp_devlink_info_get(struct devlink *devlink, struct devlink_info_req *req, struct netlink_ext_ack *extack) { struct nfp_pf *pf = devlink_priv(devlink); const char *sn, *vendor, *part; struct nfp_nsp *nsp; char *buf = NULL; int err; vendor = nfp_hwinfo_lookup(pf->hwinfo, "assembly.vendor"); part = nfp_hwinfo_lookup(pf->hwinfo, "assembly.partno"); sn = nfp_hwinfo_lookup(pf->hwinfo, "assembly.serial"); if (vendor && part && sn) { char *buf; buf = kmalloc(strlen(vendor) + strlen(part) + strlen(sn) + 1, GFP_KERNEL); if (!buf) return -ENOMEM; buf[0] = '\0'; strcat(buf, vendor); strcat(buf, part); strcat(buf, sn); err = devlink_info_serial_number_put(req, buf); kfree(buf); if (err) return err; } nsp = nfp_nsp_open(pf->cpp); if (IS_ERR(nsp)) { NL_SET_ERR_MSG_MOD(extack, "can't access NSP"); return PTR_ERR(nsp); } if (nfp_nsp_has_versions(nsp)) { buf = kzalloc(NFP_NSP_VERSION_BUFSZ, GFP_KERNEL); if (!buf) { err = -ENOMEM; goto err_close_nsp; } err = nfp_nsp_versions(nsp, buf, NFP_NSP_VERSION_BUFSZ); if (err) goto err_free_buf; err = nfp_devlink_versions_get_nsp(req, false, buf, NFP_NSP_VERSION_BUFSZ); if (err) goto err_free_buf; err = nfp_devlink_versions_get_nsp(req, true, buf, NFP_NSP_VERSION_BUFSZ); if (err) goto err_free_buf; kfree(buf); } nfp_nsp_close(nsp); return nfp_devlink_versions_get_hwinfo(pf, req); err_free_buf: kfree(buf); err_close_nsp: nfp_nsp_close(nsp); return err; } static int nfp_devlink_flash_update(struct devlink *devlink, struct devlink_flash_update_params *params, struct netlink_ext_ack *extack) { return nfp_flash_update_common(devlink_priv(devlink), params->fw, extack); } const struct devlink_ops nfp_devlink_ops = { .sb_pool_get = nfp_devlink_sb_pool_get, .sb_pool_set = nfp_devlink_sb_pool_set, .eswitch_mode_get = nfp_devlink_eswitch_mode_get, .eswitch_mode_set = nfp_devlink_eswitch_mode_set, .info_get = nfp_devlink_info_get, .flash_update = nfp_devlink_flash_update, }; static const struct devlink_port_ops nfp_devlink_port_ops = { .port_split = nfp_devlink_port_split, .port_unsplit = nfp_devlink_port_unsplit, }; int nfp_devlink_port_register(struct nfp_app *app, struct nfp_port *port) { struct devlink_port_attrs attrs = {}; struct nfp_eth_table_port eth_port; struct devlink *devlink; const u8 *serial; int serial_len; int ret; SET_NETDEV_DEVLINK_PORT(port->netdev, &port->dl_port); rtnl_lock(); ret = nfp_devlink_fill_eth_port(port, ð_port); rtnl_unlock(); if (ret) return ret; attrs.split = eth_port.is_split; attrs.splittable = eth_port.port_lanes > 1 && !attrs.split; attrs.lanes = eth_port.port_lanes; attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL; attrs.phys.port_number = eth_port.label_port; attrs.phys.split_subport_number = eth_port.label_subport; serial_len = nfp_cpp_serial(port->app->cpp, &serial); memcpy(attrs.switch_id.id, serial, serial_len); attrs.switch_id.id_len = serial_len; devlink_port_attrs_set(&port->dl_port, &attrs); devlink = priv_to_devlink(app->pf); return devl_port_register_with_ops(devlink, &port->dl_port, port->eth_id, &nfp_devlink_port_ops); } void nfp_devlink_port_unregister(struct nfp_port *port) { devl_port_unregister(&port->dl_port); }
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with Cregit http://github.com/cregit/cregit
Version 2.0-RC1