mirror of
https://github.com/corundum/corundum.git
synced 2025-01-16 08:12:53 +08:00
448fa8eb4c
Signed-off-by: Alex Forencich <alex@alexforencich.com>
274 lines
8.7 KiB
C
274 lines
8.7 KiB
C
// SPDX-License-Identifier: BSD-2-Clause-Views
|
|
/*
|
|
* Copyright (c) 2019-2023 The Regents of the University of California
|
|
*/
|
|
|
|
#include "mqnic.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
struct mqnic_if *mqnic_if_open(struct mqnic *dev, int index, volatile uint8_t *regs)
|
|
{
|
|
struct mqnic_if *interface = calloc(1, sizeof(struct mqnic_if));
|
|
uint32_t count, offset, stride;
|
|
uint32_t val;
|
|
|
|
if (!interface)
|
|
return NULL;
|
|
|
|
interface->mqnic = dev;
|
|
|
|
interface->index = index;
|
|
|
|
interface->regs_size = dev->if_stride;
|
|
interface->regs = regs;
|
|
interface->csr_regs = interface->regs + dev->if_csr_offset;
|
|
|
|
if (interface->regs >= dev->regs+dev->regs_size || interface->csr_regs >= dev->regs+dev->regs_size)
|
|
{
|
|
fprintf(stderr, "Error: computed pointer out of range\n");
|
|
goto fail;
|
|
}
|
|
|
|
// Enumerate registers
|
|
interface->rb_list = mqnic_enumerate_reg_block_list(interface->regs, dev->if_csr_offset, interface->regs_size);
|
|
|
|
if (!interface->rb_list)
|
|
{
|
|
fprintf(stderr, "Error: filed to enumerate blocks\n");
|
|
goto fail;
|
|
}
|
|
|
|
interface->if_ctrl_rb = mqnic_find_reg_block(interface->rb_list, MQNIC_RB_IF_CTRL_TYPE, MQNIC_RB_IF_CTRL_VER, 0);
|
|
|
|
if (!interface->if_ctrl_rb)
|
|
{
|
|
fprintf(stderr, "Error: Interface control block not found\n");
|
|
goto fail;
|
|
}
|
|
|
|
interface->if_features = mqnic_reg_read32(interface->if_ctrl_rb->regs, MQNIC_RB_IF_CTRL_REG_FEATURES);
|
|
interface->port_count = mqnic_reg_read32(interface->if_ctrl_rb->regs, MQNIC_RB_IF_CTRL_REG_PORT_COUNT);
|
|
interface->sched_block_count = mqnic_reg_read32(interface->if_ctrl_rb->regs, MQNIC_RB_IF_CTRL_REG_SCHED_COUNT);
|
|
interface->max_tx_mtu = mqnic_reg_read32(interface->if_ctrl_rb->regs, MQNIC_RB_IF_CTRL_REG_MAX_TX_MTU);
|
|
interface->max_rx_mtu = mqnic_reg_read32(interface->if_ctrl_rb->regs, MQNIC_RB_IF_CTRL_REG_MAX_RX_MTU);
|
|
|
|
interface->eq_rb = mqnic_find_reg_block(interface->rb_list, MQNIC_RB_EQM_TYPE, MQNIC_RB_EQM_VER, 0);
|
|
|
|
if (!interface->eq_rb)
|
|
{
|
|
fprintf(stderr, "Error: EQ block not found\n");
|
|
goto fail;
|
|
}
|
|
|
|
offset = mqnic_reg_read32(interface->eq_rb->regs, MQNIC_RB_EQM_REG_OFFSET);
|
|
count = mqnic_reg_read32(interface->eq_rb->regs, MQNIC_RB_EQM_REG_COUNT);
|
|
stride = mqnic_reg_read32(interface->eq_rb->regs, MQNIC_RB_EQM_REG_STRIDE);
|
|
|
|
if (count > MQNIC_MAX_EQ)
|
|
count = MQNIC_MAX_EQ;
|
|
|
|
interface->eq_res = mqnic_res_open(count, interface->regs + offset, stride);
|
|
|
|
if (!interface->eq_res)
|
|
goto fail;
|
|
|
|
interface->txq_rb = mqnic_find_reg_block(interface->rb_list, MQNIC_RB_TX_QM_TYPE, MQNIC_RB_TX_QM_VER, 0);
|
|
|
|
if (!interface->txq_rb)
|
|
{
|
|
fprintf(stderr, "Error: TXQ block not found\n");
|
|
goto fail;
|
|
}
|
|
|
|
offset = mqnic_reg_read32(interface->txq_rb->regs, MQNIC_RB_TX_QM_REG_OFFSET);
|
|
count = mqnic_reg_read32(interface->txq_rb->regs, MQNIC_RB_TX_QM_REG_COUNT);
|
|
stride = mqnic_reg_read32(interface->txq_rb->regs, MQNIC_RB_TX_QM_REG_STRIDE);
|
|
|
|
if (count > MQNIC_MAX_TXQ)
|
|
count = MQNIC_MAX_TXQ;
|
|
|
|
interface->txq_res = mqnic_res_open(count, interface->regs + offset, stride);
|
|
|
|
if (!interface->txq_res)
|
|
goto fail;
|
|
|
|
interface->tx_cq_rb = mqnic_find_reg_block(interface->rb_list, MQNIC_RB_TX_CQM_TYPE, MQNIC_RB_TX_CQM_VER, 0);
|
|
|
|
if (!interface->tx_cq_rb)
|
|
{
|
|
fprintf(stderr, "Error: TX CQ block not found\n");
|
|
goto fail;
|
|
}
|
|
|
|
offset = mqnic_reg_read32(interface->tx_cq_rb->regs, MQNIC_RB_TX_CQM_REG_OFFSET);
|
|
count = mqnic_reg_read32(interface->tx_cq_rb->regs, MQNIC_RB_TX_CQM_REG_COUNT);
|
|
stride = mqnic_reg_read32(interface->tx_cq_rb->regs, MQNIC_RB_TX_CQM_REG_STRIDE);
|
|
|
|
if (count > MQNIC_MAX_TX_CQ)
|
|
count = MQNIC_MAX_TX_CQ;
|
|
|
|
interface->tx_cq_res = mqnic_res_open(count, interface->regs + offset, stride);
|
|
|
|
if (!interface->tx_cq_res)
|
|
goto fail;
|
|
|
|
interface->rxq_rb = mqnic_find_reg_block(interface->rb_list, MQNIC_RB_RX_QM_TYPE, MQNIC_RB_RX_QM_VER, 0);
|
|
|
|
if (!interface->rxq_rb)
|
|
{
|
|
fprintf(stderr, "Error: RXQ block not found\n");
|
|
goto fail;
|
|
}
|
|
|
|
offset = mqnic_reg_read32(interface->rxq_rb->regs, MQNIC_RB_RX_QM_REG_OFFSET);
|
|
count = mqnic_reg_read32(interface->rxq_rb->regs, MQNIC_RB_RX_QM_REG_COUNT);
|
|
stride = mqnic_reg_read32(interface->rxq_rb->regs, MQNIC_RB_RX_QM_REG_STRIDE);
|
|
|
|
if (count > MQNIC_MAX_RXQ)
|
|
count = MQNIC_MAX_RXQ;
|
|
|
|
interface->rxq_res = mqnic_res_open(count, interface->regs + offset, stride);
|
|
|
|
if (!interface->rxq_res)
|
|
goto fail;
|
|
|
|
interface->rx_cq_rb = mqnic_find_reg_block(interface->rb_list, MQNIC_RB_RX_CQM_TYPE, MQNIC_RB_RX_CQM_VER, 0);
|
|
|
|
if (!interface->rx_cq_rb)
|
|
{
|
|
fprintf(stderr, "Error: RX CQ block not found\n");
|
|
goto fail;
|
|
}
|
|
|
|
offset = mqnic_reg_read32(interface->rx_cq_rb->regs, MQNIC_RB_RX_CQM_REG_OFFSET);
|
|
count = mqnic_reg_read32(interface->rx_cq_rb->regs, MQNIC_RB_RX_CQM_REG_COUNT);
|
|
stride = mqnic_reg_read32(interface->rx_cq_rb->regs, MQNIC_RB_RX_CQM_REG_STRIDE);
|
|
|
|
if (count > MQNIC_MAX_RX_CQ)
|
|
count = MQNIC_MAX_RX_CQ;
|
|
|
|
interface->rx_cq_res = mqnic_res_open(count, interface->regs + offset, stride);
|
|
|
|
if (!interface->rx_cq_res)
|
|
goto fail;
|
|
|
|
interface->rx_queue_map_rb = mqnic_find_reg_block(interface->rb_list, MQNIC_RB_RX_QUEUE_MAP_TYPE, MQNIC_RB_RX_QUEUE_MAP_VER, 0);
|
|
|
|
if (!interface->rx_queue_map_rb)
|
|
{
|
|
fprintf(stderr, "Error: RX queue map block not found\n");
|
|
goto fail;
|
|
}
|
|
|
|
val = mqnic_reg_read32(interface->rx_queue_map_rb->regs, MQNIC_RB_RX_QUEUE_MAP_REG_CFG);
|
|
interface->rx_queue_map_indir_table_size = 1 << ((val >> 8) & 0xff);
|
|
|
|
for (int k = 0; k < interface->port_count; k++)
|
|
{
|
|
interface->rx_queue_map_indir_table[k] = interface->regs + mqnic_reg_read32(interface->rx_queue_map_rb->regs, MQNIC_RB_RX_QUEUE_MAP_CH_OFFSET +
|
|
MQNIC_RB_RX_QUEUE_MAP_CH_STRIDE*k + MQNIC_RB_RX_QUEUE_MAP_CH_REG_OFFSET);
|
|
}
|
|
|
|
for (int k = 0; k < interface->port_count; k++)
|
|
{
|
|
struct mqnic_reg_block *port_rb = mqnic_find_reg_block(interface->rb_list, MQNIC_RB_PORT_TYPE, MQNIC_RB_PORT_VER, k);
|
|
struct mqnic_port *port;
|
|
|
|
if (!port_rb)
|
|
goto fail;
|
|
|
|
port = mqnic_port_open(interface, k, port_rb);
|
|
|
|
if (!port)
|
|
goto fail;
|
|
|
|
interface->ports[k] = port;
|
|
}
|
|
|
|
for (int k = 0; k < interface->sched_block_count; k++)
|
|
{
|
|
struct mqnic_reg_block *sched_block_rb = mqnic_find_reg_block(interface->rb_list, MQNIC_RB_SCHED_BLOCK_TYPE, MQNIC_RB_SCHED_BLOCK_VER, k);
|
|
struct mqnic_sched_block *sched_block;
|
|
|
|
if (!sched_block_rb)
|
|
goto fail;
|
|
|
|
sched_block = mqnic_sched_block_open(interface, k, sched_block_rb);
|
|
|
|
if (!sched_block)
|
|
goto fail;
|
|
|
|
interface->sched_blocks[k] = sched_block;
|
|
}
|
|
|
|
return interface;
|
|
|
|
fail:
|
|
mqnic_if_close(interface);
|
|
return NULL;
|
|
}
|
|
|
|
void mqnic_if_close(struct mqnic_if *interface)
|
|
{
|
|
if (!interface)
|
|
return;
|
|
|
|
for (int k = 0; k < interface->sched_block_count; k++)
|
|
{
|
|
if (!interface->sched_blocks[k])
|
|
continue;
|
|
|
|
mqnic_sched_block_close(interface->sched_blocks[k]);
|
|
interface->sched_blocks[k] = NULL;
|
|
}
|
|
|
|
for (int k = 0; k < interface->port_count; k++)
|
|
{
|
|
if (!interface->ports[k])
|
|
continue;
|
|
|
|
mqnic_port_close(interface->ports[k]);
|
|
interface->ports[k] = NULL;
|
|
}
|
|
|
|
mqnic_res_close(interface->eq_res);
|
|
mqnic_res_close(interface->txq_res);
|
|
mqnic_res_close(interface->tx_cq_res);
|
|
mqnic_res_close(interface->rxq_res);
|
|
mqnic_res_close(interface->rx_cq_res);
|
|
|
|
if (interface->rb_list)
|
|
mqnic_free_reg_block_list(interface->rb_list);
|
|
|
|
free(interface);
|
|
}
|
|
|
|
uint32_t mqnic_interface_get_tx_mtu(struct mqnic_if *interface)
|
|
{
|
|
return mqnic_reg_read32(interface->if_ctrl_rb->regs, MQNIC_RB_IF_CTRL_REG_TX_MTU);
|
|
}
|
|
|
|
uint32_t mqnic_interface_get_rx_mtu(struct mqnic_if *interface)
|
|
{
|
|
return mqnic_reg_read32(interface->if_ctrl_rb->regs, MQNIC_RB_IF_CTRL_REG_RX_MTU);
|
|
}
|
|
|
|
uint32_t mqnic_interface_get_rx_queue_map_rss_mask(struct mqnic_if *interface, int port)
|
|
{
|
|
return mqnic_reg_read32(interface->rx_queue_map_rb->regs, MQNIC_RB_RX_QUEUE_MAP_CH_OFFSET +
|
|
MQNIC_RB_RX_QUEUE_MAP_CH_STRIDE*port + MQNIC_RB_RX_QUEUE_MAP_CH_REG_RSS_MASK);
|
|
}
|
|
|
|
uint32_t mqnic_interface_get_rx_queue_map_app_mask(struct mqnic_if *interface, int port)
|
|
{
|
|
return mqnic_reg_read32(interface->rx_queue_map_rb->regs, MQNIC_RB_RX_QUEUE_MAP_CH_OFFSET +
|
|
MQNIC_RB_RX_QUEUE_MAP_CH_STRIDE*port + MQNIC_RB_RX_QUEUE_MAP_CH_REG_APP_MASK);
|
|
}
|
|
|
|
uint32_t mqnic_interface_get_rx_queue_map_indir_table(struct mqnic_if *interface, int port, int index)
|
|
{
|
|
return mqnic_reg_read32(interface->rx_queue_map_indir_table[port], index*4);
|
|
}
|