mirror of https://github.com/F-Stack/f-stack.git
227 lines
4.9 KiB
C
227 lines
4.9 KiB
C
/* SPDX-License-Identifier: BSD-3-Clause
|
|
* Copyright (c) 2023 Corigine, Inc.
|
|
* All rights reserved.
|
|
*/
|
|
|
|
#include "nfp_common.h"
|
|
|
|
#include "nfp_common_log.h"
|
|
|
|
/*
|
|
* This is used by the reconfig protocol. It sets the maximum time waiting in
|
|
* milliseconds before a reconfig timeout happens.
|
|
*/
|
|
#define NFP_NET_POLL_TIMEOUT 5000
|
|
|
|
int
|
|
nfp_reconfig_real(struct nfp_hw *hw,
|
|
uint32_t update)
|
|
{
|
|
uint32_t cnt;
|
|
uint32_t new;
|
|
struct timespec wait;
|
|
|
|
PMD_DRV_LOG(DEBUG, "Writing to the configuration queue (%p)...",
|
|
hw->qcp_cfg);
|
|
|
|
if (hw->qcp_cfg == NULL) {
|
|
PMD_DRV_LOG(ERR, "Bad configuration queue pointer");
|
|
return -ENXIO;
|
|
}
|
|
|
|
nfp_qcp_ptr_add(hw->qcp_cfg, NFP_QCP_WRITE_PTR, 1);
|
|
|
|
wait.tv_sec = 0;
|
|
wait.tv_nsec = 1000000; /* 1ms */
|
|
|
|
PMD_DRV_LOG(DEBUG, "Polling for update ack...");
|
|
|
|
/* Poll update field, waiting for NFP to ack the config */
|
|
for (cnt = 0; ; cnt++) {
|
|
new = nn_cfg_readl(hw, NFP_NET_CFG_UPDATE);
|
|
if (new == 0)
|
|
break;
|
|
|
|
if ((new & NFP_NET_CFG_UPDATE_ERR) != 0) {
|
|
PMD_DRV_LOG(ERR, "Reconfig error: %#08x", new);
|
|
return -1;
|
|
}
|
|
|
|
if (cnt >= NFP_NET_POLL_TIMEOUT) {
|
|
PMD_DRV_LOG(ERR, "Reconfig timeout for %#08x after %u ms",
|
|
update, cnt);
|
|
return -EIO;
|
|
}
|
|
|
|
nanosleep(&wait, 0); /* waiting for a 1ms */
|
|
}
|
|
|
|
PMD_DRV_LOG(DEBUG, "Ack DONE");
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Reconfigure the NIC.
|
|
*
|
|
* Write the update word to the BAR and ping the reconfig queue. Then poll
|
|
* until the firmware has acknowledged the update by zeroing the update word.
|
|
*
|
|
* @param hw
|
|
* Device to reconfigure.
|
|
* @param ctrl
|
|
* The value for the ctrl field in the BAR config.
|
|
* @param update
|
|
* The value for the update field in the BAR config.
|
|
*
|
|
* @return
|
|
* - (0) if OK to reconfigure the device.
|
|
* - (-EIO) if I/O err and fail to reconfigure the device.
|
|
*/
|
|
int
|
|
nfp_reconfig(struct nfp_hw *hw,
|
|
uint32_t ctrl,
|
|
uint32_t update)
|
|
{
|
|
int ret;
|
|
|
|
rte_spinlock_lock(&hw->reconfig_lock);
|
|
|
|
nn_cfg_writel(hw, NFP_NET_CFG_CTRL, ctrl);
|
|
nn_cfg_writel(hw, NFP_NET_CFG_UPDATE, update);
|
|
|
|
rte_wmb();
|
|
|
|
ret = nfp_reconfig_real(hw, update);
|
|
|
|
rte_spinlock_unlock(&hw->reconfig_lock);
|
|
|
|
if (ret != 0) {
|
|
PMD_DRV_LOG(ERR, "Error nfp reconfig: ctrl=%#08x update=%#08x",
|
|
ctrl, update);
|
|
return -EIO;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Reconfigure the NIC for the extend ctrl BAR.
|
|
*
|
|
* Write the update word to the BAR and ping the reconfig queue. Then poll
|
|
* until the firmware has acknowledged the update by zeroing the update word.
|
|
*
|
|
* @param hw
|
|
* Device to reconfigure.
|
|
* @param ctrl_ext
|
|
* The value for the first word of extend ctrl field in the BAR config.
|
|
* @param update
|
|
* The value for the update field in the BAR config.
|
|
*
|
|
* @return
|
|
* - (0) if OK to reconfigure the device.
|
|
* - (-EIO) if I/O err and fail to reconfigure the device.
|
|
*/
|
|
int
|
|
nfp_ext_reconfig(struct nfp_hw *hw,
|
|
uint32_t ctrl_ext,
|
|
uint32_t update)
|
|
{
|
|
int ret;
|
|
|
|
rte_spinlock_lock(&hw->reconfig_lock);
|
|
|
|
nn_cfg_writel(hw, NFP_NET_CFG_CTRL_WORD1, ctrl_ext);
|
|
nn_cfg_writel(hw, NFP_NET_CFG_UPDATE, update);
|
|
|
|
rte_wmb();
|
|
|
|
ret = nfp_reconfig_real(hw, update);
|
|
|
|
rte_spinlock_unlock(&hw->reconfig_lock);
|
|
|
|
if (ret != 0) {
|
|
PMD_DRV_LOG(ERR, "Error nfp ext reconfig: ctrl_ext=%#08x update=%#08x",
|
|
ctrl_ext, update);
|
|
return -EIO;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
nfp_read_mac(struct nfp_hw *hw)
|
|
{
|
|
uint32_t tmp;
|
|
|
|
tmp = rte_be_to_cpu_32(nn_cfg_readl(hw, NFP_NET_CFG_MACADDR));
|
|
memcpy(&hw->mac_addr.addr_bytes[0], &tmp, 4);
|
|
|
|
tmp = rte_be_to_cpu_32(nn_cfg_readl(hw, NFP_NET_CFG_MACADDR + 4));
|
|
memcpy(&hw->mac_addr.addr_bytes[4], &tmp, 2);
|
|
}
|
|
|
|
void
|
|
nfp_write_mac(struct nfp_hw *hw,
|
|
uint8_t *mac)
|
|
{
|
|
uint32_t mac0;
|
|
uint16_t mac1;
|
|
|
|
mac0 = *(uint32_t *)mac;
|
|
nn_writel(rte_cpu_to_be_32(mac0), hw->ctrl_bar + NFP_NET_CFG_MACADDR);
|
|
|
|
mac += 4;
|
|
mac1 = *(uint16_t *)mac;
|
|
nn_writew(rte_cpu_to_be_16(mac1),
|
|
hw->ctrl_bar + NFP_NET_CFG_MACADDR + 6);
|
|
}
|
|
|
|
void
|
|
nfp_enable_queues(struct nfp_hw *hw,
|
|
uint16_t nb_rx_queues,
|
|
uint16_t nb_tx_queues)
|
|
{
|
|
int i;
|
|
uint64_t enabled_queues;
|
|
|
|
/* Enabling the required TX queues in the device */
|
|
enabled_queues = 0;
|
|
for (i = 0; i < nb_tx_queues; i++)
|
|
enabled_queues |= (1ULL << i);
|
|
|
|
nn_cfg_writeq(hw, NFP_NET_CFG_TXRS_ENABLE, enabled_queues);
|
|
|
|
/* Enabling the required RX queues in the device */
|
|
enabled_queues = 0;
|
|
for (i = 0; i < nb_rx_queues; i++)
|
|
enabled_queues |= (1ULL << i);
|
|
|
|
nn_cfg_writeq(hw, NFP_NET_CFG_RXRS_ENABLE, enabled_queues);
|
|
}
|
|
|
|
void
|
|
nfp_disable_queues(struct nfp_hw *hw)
|
|
{
|
|
int ret;
|
|
uint32_t update;
|
|
uint32_t new_ctrl;
|
|
|
|
nn_cfg_writeq(hw, NFP_NET_CFG_TXRS_ENABLE, 0);
|
|
nn_cfg_writeq(hw, NFP_NET_CFG_RXRS_ENABLE, 0);
|
|
|
|
new_ctrl = hw->ctrl & ~NFP_NET_CFG_CTRL_ENABLE;
|
|
update = NFP_NET_CFG_UPDATE_GEN |
|
|
NFP_NET_CFG_UPDATE_RING |
|
|
NFP_NET_CFG_UPDATE_MSIX;
|
|
|
|
if ((hw->cap & NFP_NET_CFG_CTRL_RINGCFG) != 0)
|
|
new_ctrl &= ~NFP_NET_CFG_CTRL_RINGCFG;
|
|
|
|
/* If an error when reconfig we avoid to change hw state */
|
|
ret = nfp_reconfig(hw, new_ctrl, update);
|
|
if (ret < 0)
|
|
return;
|
|
|
|
hw->ctrl = new_ctrl;
|
|
}
|