// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) /* Copyright (C) 2015-2017 Netronome Systems, Inc. */
/* Authors: David Brunecz <david.brunecz@netronome.com> * Jakub Kicinski <jakub.kicinski@netronome.com> * Jason Mcmullan <jason.mcmullan@netronome.com>
*/
for (i = 0; i < table->count; i++) {
table->max_index = max(table->max_index, table->ports[i].index);
for (j = 0; j < table->count; j++) { if (table->ports[i].label_port !=
table->ports[j].label_port) continue;
table->ports[i].port_lanes += table->ports[j].lanes;
if (i == j) continue; if (table->ports[i].label_subport ==
table->ports[j].label_subport)
nfp_warn(cpp, "Port %d subport %d is a duplicate\n",
table->ports[i].label_port,
table->ports[i].label_subport);
ret = nfp_nsp_read_media(nsp, ðm, sizeof(ethm)); if (ret) {
nfp_err(cpp, "Reading media link modes failed: %d\n", ret); return;
}
for (i = 0; i < 2; i++) {
entry->link_modes_supp[i] = le64_to_cpu(ethm.supported_modes[i]);
entry->link_modes_ad[i] = le64_to_cpu(ethm.advertised_modes[i]);
}
}
/** * nfp_eth_read_ports() - retrieve port information * @cpp: NFP CPP handle * * Read the port information from the device. Returned structure should * be freed with kfree() once no longer needed. * * Return: populated ETH table or NULL on error.
*/ struct nfp_eth_table *nfp_eth_read_ports(struct nfp_cpp *cpp)
{ struct nfp_eth_table *ret; struct nfp_nsp *nsp;
nsp = nfp_nsp_open(cpp); if (IS_ERR(nsp)) return NULL;
ret = __nfp_eth_read_ports(cpp, nsp);
nfp_nsp_close(nsp);
return ret;
}
struct nfp_eth_table *
__nfp_eth_read_ports(struct nfp_cpp *cpp, struct nfp_nsp *nsp)
{ union eth_table_entry *entries; struct nfp_eth_table *table; int i, j, ret, cnt = 0;
entries = kzalloc(NSP_ETH_TABLE_SIZE, GFP_KERNEL); if (!entries) return NULL;
ret = nfp_nsp_read_eth_table(nsp, entries, NSP_ETH_TABLE_SIZE); if (ret < 0) {
nfp_err(cpp, "reading port table failed %d\n", ret); goto err;
}
for (i = 0; i < NSP_ETH_MAX_COUNT; i++) if (entries[i].port & NSP_ETH_PORT_LANES_MASK)
cnt++;
/* Some versions of flash will give us 0 instead of port count. * For those that give a port count, verify it against the value * calculated above.
*/ if (ret && ret != cnt) {
nfp_err(cpp, "table entry count reported (%d) does not match entries present (%d)\n",
ret, cnt); goto err;
}
table = kzalloc(struct_size(table, ports, cnt), GFP_KERNEL); if (!table) goto err;
table->count = cnt; for (i = 0, j = 0; i < NSP_ETH_MAX_COUNT; i++) if (entries[i].port & NSP_ETH_PORT_LANES_MASK)
nfp_eth_port_translate(nsp, &entries[i], i,
&table->ports[j++]);
nfp_eth_calc_port_geometry(cpp, table); for (i = 0; i < table->count; i++) {
nfp_eth_calc_port_type(cpp, &table->ports[i]);
nfp_eth_read_media(cpp, nsp, &table->ports[i]);
}
kfree(entries);
return table;
err:
kfree(entries); return NULL;
}
struct nfp_nsp *nfp_eth_config_start(struct nfp_cpp *cpp, unsignedint idx)
{ union eth_table_entry *entries; struct nfp_nsp *nsp; int ret;
entries = kzalloc(NSP_ETH_TABLE_SIZE, GFP_KERNEL); if (!entries) return ERR_PTR(-ENOMEM);
nsp = nfp_nsp_open(cpp); if (IS_ERR(nsp)) {
kfree(entries); return nsp;
}
ret = nfp_nsp_read_eth_table(nsp, entries, NSP_ETH_TABLE_SIZE); if (ret < 0) {
nfp_err(cpp, "reading port table failed %d\n", ret); goto err;
}
if (!(entries[idx].port & NSP_ETH_PORT_LANES_MASK)) {
nfp_warn(cpp, "trying to set port state on disabled port %d\n",
idx); goto err;
}
/** * nfp_eth_config_commit_end() - perform recorded configuration changes * @nsp: NFP NSP handle returned from nfp_eth_config_start() * * Perform the configuration which was requested with __nfp_eth_set_*() * helpers and recorded in @nsp state. If device was already configured * as requested or no __nfp_eth_set_*() operations were made no NSP command * will be performed. * * Return: * 0 - configuration successful; * 1 - no changes were needed; * -ERRNO - configuration failed.
*/ int nfp_eth_config_commit_end(struct nfp_nsp *nsp)
{ union eth_table_entry *entries = nfp_nsp_config_entries(nsp); int ret = 1;
if (nfp_nsp_config_modified(nsp)) {
ret = nfp_nsp_write_eth_table(nsp, entries, NSP_ETH_TABLE_SIZE);
ret = ret < 0 ? ret : 0;
}
nfp_eth_config_cleanup_end(nsp);
return ret;
}
/** * nfp_eth_set_mod_enable() - set PHY module enable control bit * @cpp: NFP CPP handle * @idx: NFP chip-wide port index * @enable: Desired state * * Enable or disable PHY module (this usually means setting the TX lanes * disable bits). * * Return: * 0 - configuration successful; * 1 - no changes were needed; * -ERRNO - configuration failed.
*/ int nfp_eth_set_mod_enable(struct nfp_cpp *cpp, unsignedint idx, bool enable)
{ union eth_table_entry *entries; struct nfp_nsp *nsp;
u64 reg;
nsp = nfp_eth_config_start(cpp, idx); if (IS_ERR(nsp)) return PTR_ERR(nsp);
entries = nfp_nsp_config_entries(nsp);
/* Check if we are already in requested state */
reg = le64_to_cpu(entries[idx].state); if (enable != FIELD_GET(NSP_ETH_CTRL_ENABLED, reg)) {
reg = le64_to_cpu(entries[idx].control);
reg &= ~NSP_ETH_CTRL_ENABLED;
reg |= FIELD_PREP(NSP_ETH_CTRL_ENABLED, enable);
entries[idx].control = cpu_to_le64(reg);
nfp_nsp_config_set_modified(nsp, true);
}
return nfp_eth_config_commit_end(nsp);
}
/** * nfp_eth_set_configured() - set PHY module configured control bit * @cpp: NFP CPP handle * @idx: NFP chip-wide port index * @configed: Desired state * * Set the ifup/ifdown state on the PHY. * * Return: * 0 - configuration successful; * 1 - no changes were needed; * -ERRNO - configuration failed.
*/ int nfp_eth_set_configured(struct nfp_cpp *cpp, unsignedint idx, bool configed)
{ union eth_table_entry *entries; struct nfp_nsp *nsp;
u64 reg;
nsp = nfp_eth_config_start(cpp, idx); if (IS_ERR(nsp)) return PTR_ERR(nsp);
/* Older ABI versions did support this feature, however this has only * been reliable since ABI 20.
*/ if (nfp_nsp_get_abi_ver_minor(nsp) < 20) {
nfp_eth_config_cleanup_end(nsp); return -EOPNOTSUPP;
}
entries = nfp_nsp_config_entries(nsp);
/* Check if we are already in requested state */
reg = le64_to_cpu(entries[idx].state); if (configed != FIELD_GET(NSP_ETH_STATE_CONFIGURED, reg)) {
reg = le64_to_cpu(entries[idx].control);
reg &= ~NSP_ETH_CTRL_CONFIGURED;
reg |= FIELD_PREP(NSP_ETH_CTRL_CONFIGURED, configed);
entries[idx].control = cpu_to_le64(reg);
/* Note: set features were added in ABI 0.14 but the error * codes were initially not populated correctly.
*/ if (nfp_nsp_get_abi_ver_minor(nsp) < 17) {
nfp_err(nfp_nsp_cpp(nsp), "set operations not supported, please update flash\n"); return -EOPNOTSUPP;
}
/* Check if we are already in requested state */
reg = le64_to_cpu(entries[idx].raw[raw_idx]); if (val == (reg & mask) >> shift) return 0;
int nfp_eth_set_idmode(struct nfp_cpp *cpp, unsignedint idx, bool state)
{ union eth_table_entry *entries; struct nfp_nsp *nsp;
u64 reg;
nsp = nfp_eth_config_start(cpp, idx); if (IS_ERR(nsp)) return PTR_ERR(nsp);
/* Set this features were added in ABI 0.32 */ if (nfp_nsp_get_abi_ver_minor(nsp) < 32) {
nfp_err(nfp_nsp_cpp(nsp), "set id mode operation not supported, please update flash\n");
nfp_eth_config_cleanup_end(nsp); return -EOPNOTSUPP;
}
/** * __nfp_eth_set_speed() - set interface speed/rate * @nsp: NFP NSP handle returned from nfp_eth_config_start() * @speed: Desired speed (per lane) * * Set lane speed. Provided @speed value should be subport speed divided * by number of lanes this subport is spanning (i.e. 10000 for 40G, 25000 for * 50G, etc.) * Will write to hwinfo overrides in the flash (persistent config). * * Return: 0 or -ERRNO.
*/ int __nfp_eth_set_speed(struct nfp_nsp *nsp, unsignedint speed)
{ enum nfp_eth_rate rate;
rate = nfp_eth_speed2rate(speed); if (rate == RATE_INVALID) {
nfp_warn(nfp_nsp_cpp(nsp), "could not find matching lane rate for speed %u\n",
speed); return -EINVAL;
}
/** * __nfp_eth_set_split() - set interface lane split * @nsp: NFP NSP handle returned from nfp_eth_config_start() * @lanes: Desired lanes per port * * Set number of lanes in the port. * Will write to hwinfo overrides in the flash (persistent config). * * Return: 0 or -ERRNO.
*/ int __nfp_eth_set_split(struct nfp_nsp *nsp, unsignedint lanes)
{ return NFP_ETH_SET_BIT_CONFIG(nsp, NSP_ETH_RAW_PORT, NSP_ETH_PORT_LANES,
lanes, NSP_ETH_CTRL_SET_LANES);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.