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:
Shijith Thotton 2017-03-25 11:54:30 +05:30 committed by Ferruh Yigit
parent 64af21f803
commit c6186279df
4 changed files with 291 additions and 0 deletions

View File

@ -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) \

View File

@ -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, &eth_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;
}

View File

@ -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_ */

View File

@ -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;