net/liquidio: add API to configure device
Add API to configure device and initialize ethernet device operations. Signed-off-by: Shijith Thotton <shijith.thotton@caviumnetworks.com> Signed-off-by: Jerin Jacob <jerin.jacob@caviumnetworks.com> Signed-off-by: Derek Chickles <derek.chickles@caviumnetworks.com> Signed-off-by: Venkat Koppula <venkat.koppula@caviumnetworks.com> Signed-off-by: Srisivasubramanian S <ssrinivasan@caviumnetworks.com> Signed-off-by: Mallesham Jatharakonda <mjatharakonda@oneconvergence.com>
This commit is contained in:
parent
64af21f803
commit
c6186279df
@ -95,6 +95,8 @@ enum lio_card_type {
|
||||
#define LIO_BASE_MINOR_VERSION 5
|
||||
#define LIO_BASE_MICRO_VERSION 1
|
||||
|
||||
#define LIO_FW_VERSION_LENGTH 32
|
||||
|
||||
/** Tag types used by Octeon cores in its work. */
|
||||
enum octeon_tag_type {
|
||||
OCTEON_ORDERED_TAG = 0,
|
||||
@ -104,6 +106,18 @@ enum octeon_tag_type {
|
||||
/* pre-defined host->NIC tag values */
|
||||
#define LIO_CONTROL (0x11111110)
|
||||
|
||||
/* used for NIC operations */
|
||||
#define LIO_OPCODE 1
|
||||
|
||||
/** LIO_OPCODE subcodes */
|
||||
/* This subcode is sent by core PCI driver to indicate cores are ready. */
|
||||
#define LIO_OPCODE_IF_CFG 0x09
|
||||
|
||||
/* Interface flags communicated between host driver and core app. */
|
||||
enum lio_ifflags {
|
||||
LIO_IFFLAG_UNICAST = 0x10
|
||||
};
|
||||
|
||||
/* Routines for reading and writing CSRs */
|
||||
#ifdef RTE_LIBRTE_LIO_DEBUG_REGS
|
||||
#define lio_write_csr(lio_dev, reg_off, value) \
|
||||
|
@ -41,6 +41,166 @@
|
||||
#include "lio_ethdev.h"
|
||||
#include "lio_rxtx.h"
|
||||
|
||||
static uint64_t
|
||||
lio_hweight64(uint64_t w)
|
||||
{
|
||||
uint64_t res = w - ((w >> 1) & 0x5555555555555555ul);
|
||||
|
||||
res =
|
||||
(res & 0x3333333333333333ul) + ((res >> 2) & 0x3333333333333333ul);
|
||||
res = (res + (res >> 4)) & 0x0F0F0F0F0F0F0F0Ful;
|
||||
res = res + (res >> 8);
|
||||
res = res + (res >> 16);
|
||||
|
||||
return (res + (res >> 32)) & 0x00000000000000FFul;
|
||||
}
|
||||
|
||||
static int lio_dev_configure(struct rte_eth_dev *eth_dev)
|
||||
{
|
||||
struct lio_device *lio_dev = LIO_DEV(eth_dev);
|
||||
uint16_t timeout = LIO_MAX_CMD_TIMEOUT;
|
||||
int retval, num_iqueues, num_oqueues;
|
||||
uint8_t mac[ETHER_ADDR_LEN], i;
|
||||
struct lio_if_cfg_resp *resp;
|
||||
struct lio_soft_command *sc;
|
||||
union lio_if_cfg if_cfg;
|
||||
uint32_t resp_size;
|
||||
|
||||
PMD_INIT_FUNC_TRACE();
|
||||
|
||||
/* Re-configuring firmware not supported.
|
||||
* Can't change tx/rx queues per port from initial value.
|
||||
*/
|
||||
if (lio_dev->port_configured) {
|
||||
if ((lio_dev->nb_rx_queues != eth_dev->data->nb_rx_queues) ||
|
||||
(lio_dev->nb_tx_queues != eth_dev->data->nb_tx_queues)) {
|
||||
lio_dev_err(lio_dev,
|
||||
"rxq/txq re-conf not supported. Restart application with new value.\n");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
lio_dev->nb_rx_queues = eth_dev->data->nb_rx_queues;
|
||||
lio_dev->nb_tx_queues = eth_dev->data->nb_tx_queues;
|
||||
|
||||
resp_size = sizeof(struct lio_if_cfg_resp);
|
||||
sc = lio_alloc_soft_command(lio_dev, 0, resp_size, 0);
|
||||
if (sc == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
resp = (struct lio_if_cfg_resp *)sc->virtrptr;
|
||||
|
||||
/* Firmware doesn't have capability to reconfigure the queues,
|
||||
* Claim all queues, and use as many required
|
||||
*/
|
||||
if_cfg.if_cfg64 = 0;
|
||||
if_cfg.s.num_iqueues = lio_dev->nb_tx_queues;
|
||||
if_cfg.s.num_oqueues = lio_dev->nb_rx_queues;
|
||||
if_cfg.s.base_queue = 0;
|
||||
|
||||
if_cfg.s.gmx_port_id = lio_dev->pf_num;
|
||||
|
||||
lio_prepare_soft_command(lio_dev, sc, LIO_OPCODE,
|
||||
LIO_OPCODE_IF_CFG, 0,
|
||||
if_cfg.if_cfg64, 0);
|
||||
|
||||
/* Setting wait time in seconds */
|
||||
sc->wait_time = LIO_MAX_CMD_TIMEOUT / 1000;
|
||||
|
||||
retval = lio_send_soft_command(lio_dev, sc);
|
||||
if (retval == LIO_IQ_SEND_FAILED) {
|
||||
lio_dev_err(lio_dev, "iq/oq config failed status: %x\n",
|
||||
retval);
|
||||
/* Soft instr is freed by driver in case of failure. */
|
||||
goto nic_config_fail;
|
||||
}
|
||||
|
||||
/* Sleep on a wait queue till the cond flag indicates that the
|
||||
* response arrived or timed-out.
|
||||
*/
|
||||
while ((*sc->status_word == LIO_COMPLETION_WORD_INIT) && --timeout) {
|
||||
lio_process_ordered_list(lio_dev);
|
||||
rte_delay_ms(1);
|
||||
}
|
||||
|
||||
retval = resp->status;
|
||||
if (retval) {
|
||||
lio_dev_err(lio_dev, "iq/oq config failed\n");
|
||||
goto nic_config_fail;
|
||||
}
|
||||
|
||||
lio_swap_8B_data((uint64_t *)(&resp->cfg_info),
|
||||
sizeof(struct octeon_if_cfg_info) >> 3);
|
||||
|
||||
num_iqueues = lio_hweight64(resp->cfg_info.iqmask);
|
||||
num_oqueues = lio_hweight64(resp->cfg_info.oqmask);
|
||||
|
||||
if (!(num_iqueues) || !(num_oqueues)) {
|
||||
lio_dev_err(lio_dev,
|
||||
"Got bad iqueues (%016lx) or oqueues (%016lx) from firmware.\n",
|
||||
(unsigned long)resp->cfg_info.iqmask,
|
||||
(unsigned long)resp->cfg_info.oqmask);
|
||||
goto nic_config_fail;
|
||||
}
|
||||
|
||||
lio_dev_dbg(lio_dev,
|
||||
"interface %d, iqmask %016lx, oqmask %016lx, numiqueues %d, numoqueues %d\n",
|
||||
eth_dev->data->port_id,
|
||||
(unsigned long)resp->cfg_info.iqmask,
|
||||
(unsigned long)resp->cfg_info.oqmask,
|
||||
num_iqueues, num_oqueues);
|
||||
|
||||
lio_dev->linfo.num_rxpciq = num_oqueues;
|
||||
lio_dev->linfo.num_txpciq = num_iqueues;
|
||||
|
||||
for (i = 0; i < num_oqueues; i++) {
|
||||
lio_dev->linfo.rxpciq[i].rxpciq64 =
|
||||
resp->cfg_info.linfo.rxpciq[i].rxpciq64;
|
||||
lio_dev_dbg(lio_dev, "index %d OQ %d\n",
|
||||
i, lio_dev->linfo.rxpciq[i].s.q_no);
|
||||
}
|
||||
|
||||
for (i = 0; i < num_iqueues; i++) {
|
||||
lio_dev->linfo.txpciq[i].txpciq64 =
|
||||
resp->cfg_info.linfo.txpciq[i].txpciq64;
|
||||
lio_dev_dbg(lio_dev, "index %d IQ %d\n",
|
||||
i, lio_dev->linfo.txpciq[i].s.q_no);
|
||||
}
|
||||
|
||||
lio_dev->linfo.hw_addr = resp->cfg_info.linfo.hw_addr;
|
||||
lio_dev->linfo.gmxport = resp->cfg_info.linfo.gmxport;
|
||||
lio_dev->linfo.link.link_status64 =
|
||||
resp->cfg_info.linfo.link.link_status64;
|
||||
|
||||
/* 64-bit swap required on LE machines */
|
||||
lio_swap_8B_data(&lio_dev->linfo.hw_addr, 1);
|
||||
for (i = 0; i < ETHER_ADDR_LEN; i++)
|
||||
mac[i] = *((uint8_t *)(((uint8_t *)&lio_dev->linfo.hw_addr) +
|
||||
2 + i));
|
||||
|
||||
/* Copy the permanent MAC address */
|
||||
ether_addr_copy((struct ether_addr *)mac, ð_dev->data->mac_addrs[0]);
|
||||
|
||||
lio_dev->port_configured = 1;
|
||||
|
||||
lio_free_soft_command(sc);
|
||||
|
||||
return 0;
|
||||
|
||||
nic_config_fail:
|
||||
lio_dev_err(lio_dev, "Failed retval %d\n", retval);
|
||||
lio_free_soft_command(sc);
|
||||
lio_free_instr_queue0(lio_dev);
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Define our ethernet definitions */
|
||||
static const struct eth_dev_ops liovf_eth_dev_ops = {
|
||||
.dev_configure = lio_dev_configure,
|
||||
};
|
||||
|
||||
static void
|
||||
lio_check_pf_hs_response(void *lio_dev)
|
||||
{
|
||||
@ -215,13 +375,22 @@ lio_eth_dev_init(struct rte_eth_dev *eth_dev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
eth_dev->dev_ops = &liovf_eth_dev_ops;
|
||||
eth_dev->data->mac_addrs = rte_zmalloc("lio", ETHER_ADDR_LEN, 0);
|
||||
if (eth_dev->data->mac_addrs == NULL) {
|
||||
lio_dev_err(lio_dev,
|
||||
"MAC addresses memory allocation failed\n");
|
||||
eth_dev->dev_ops = NULL;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
rte_atomic64_set(&lio_dev->status, LIO_DEV_RUNNING);
|
||||
rte_wmb();
|
||||
|
||||
lio_dev->port_configured = 0;
|
||||
/* Always allow unicast packets */
|
||||
lio_dev->ifflags |= LIO_IFFLAG_UNICAST;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -36,5 +36,41 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "lio_struct.h"
|
||||
|
||||
#define LIO_MAX_CMD_TIMEOUT 10000 /* 10000ms (10s) */
|
||||
|
||||
#define LIO_DEV(_eth_dev) ((_eth_dev)->data->dev_private)
|
||||
|
||||
struct octeon_if_cfg_info {
|
||||
uint64_t iqmask; /** mask for IQs enabled for the port */
|
||||
uint64_t oqmask; /** mask for OQs enabled for the port */
|
||||
struct octeon_link_info linfo; /** initial link information */
|
||||
char lio_firmware_version[LIO_FW_VERSION_LENGTH];
|
||||
};
|
||||
|
||||
union lio_if_cfg {
|
||||
uint64_t if_cfg64;
|
||||
struct {
|
||||
#if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
|
||||
uint64_t base_queue : 16;
|
||||
uint64_t num_iqueues : 16;
|
||||
uint64_t num_oqueues : 16;
|
||||
uint64_t gmx_port_id : 8;
|
||||
uint64_t vf_id : 8;
|
||||
#else
|
||||
uint64_t vf_id : 8;
|
||||
uint64_t gmx_port_id : 8;
|
||||
uint64_t num_oqueues : 16;
|
||||
uint64_t num_iqueues : 16;
|
||||
uint64_t base_queue : 16;
|
||||
#endif
|
||||
} s;
|
||||
};
|
||||
|
||||
struct lio_if_cfg_resp {
|
||||
uint64_t rh;
|
||||
struct octeon_if_cfg_info cfg_info;
|
||||
uint64_t status;
|
||||
};
|
||||
#endif /* _LIO_ETHDEV_H_ */
|
||||
|
@ -274,6 +274,75 @@ struct lio_config {
|
||||
int def_rx_buf_size;
|
||||
};
|
||||
|
||||
/** Status of a RGMII Link on Octeon as seen by core driver. */
|
||||
union octeon_link_status {
|
||||
uint64_t link_status64;
|
||||
|
||||
struct {
|
||||
#if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
|
||||
uint64_t duplex : 8;
|
||||
uint64_t mtu : 16;
|
||||
uint64_t speed : 16;
|
||||
uint64_t link_up : 1;
|
||||
uint64_t autoneg : 1;
|
||||
uint64_t if_mode : 5;
|
||||
uint64_t pause : 1;
|
||||
uint64_t flashing : 1;
|
||||
uint64_t reserved : 15;
|
||||
#else
|
||||
uint64_t reserved : 15;
|
||||
uint64_t flashing : 1;
|
||||
uint64_t pause : 1;
|
||||
uint64_t if_mode : 5;
|
||||
uint64_t autoneg : 1;
|
||||
uint64_t link_up : 1;
|
||||
uint64_t speed : 16;
|
||||
uint64_t mtu : 16;
|
||||
uint64_t duplex : 8;
|
||||
#endif
|
||||
} s;
|
||||
};
|
||||
|
||||
/** The rxpciq info passed to host from the firmware */
|
||||
union octeon_rxpciq {
|
||||
uint64_t rxpciq64;
|
||||
|
||||
struct {
|
||||
#if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
|
||||
uint64_t q_no : 8;
|
||||
uint64_t reserved : 56;
|
||||
#else
|
||||
uint64_t reserved : 56;
|
||||
uint64_t q_no : 8;
|
||||
#endif
|
||||
} s;
|
||||
};
|
||||
|
||||
/** Information for a OCTEON ethernet interface shared between core & host. */
|
||||
struct octeon_link_info {
|
||||
union octeon_link_status link;
|
||||
uint64_t hw_addr;
|
||||
|
||||
#if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
|
||||
uint64_t gmxport : 16;
|
||||
uint64_t macaddr_is_admin_assigned : 1;
|
||||
uint64_t vlan_is_admin_assigned : 1;
|
||||
uint64_t rsvd : 30;
|
||||
uint64_t num_txpciq : 8;
|
||||
uint64_t num_rxpciq : 8;
|
||||
#else
|
||||
uint64_t num_rxpciq : 8;
|
||||
uint64_t num_txpciq : 8;
|
||||
uint64_t rsvd : 30;
|
||||
uint64_t vlan_is_admin_assigned : 1;
|
||||
uint64_t macaddr_is_admin_assigned : 1;
|
||||
uint64_t gmxport : 16;
|
||||
#endif
|
||||
|
||||
union octeon_txpciq txpciq[LIO_MAX_IOQS_PER_IF];
|
||||
union octeon_rxpciq rxpciq[LIO_MAX_IOQS_PER_IF];
|
||||
};
|
||||
|
||||
/* ----------------------- THE LIO DEVICE --------------------------- */
|
||||
/** The lio device.
|
||||
* Each lio device has this structure to represent all its
|
||||
@ -294,6 +363,8 @@ struct lio_device {
|
||||
/** The state of this device */
|
||||
rte_atomic64_t status;
|
||||
|
||||
struct octeon_link_info linfo;
|
||||
|
||||
uint8_t *hw_addr;
|
||||
|
||||
struct lio_fn_list fn_list;
|
||||
@ -324,6 +395,7 @@ struct lio_device {
|
||||
|
||||
struct rte_eth_dev *eth_dev;
|
||||
|
||||
uint64_t ifflags;
|
||||
uint8_t max_rx_queues;
|
||||
uint8_t max_tx_queues;
|
||||
uint8_t nb_rx_queues;
|
||||
|
Loading…
Reference in New Issue
Block a user