rpc register_region(in uint16 qid, in cap reg, out uint64 buftbl_id, out errval err);
rpc deregister_region(in uint64 buftbl_id, in uint64 size, out errval err);
+ message interrupt(uint16 qid);
};
#define DEVICE_ID 0x803
// TX Queue
#define TX_DESC_CACHE_SIZE 16
-#define TX_ENTRIES 2048
+#define TX_ENTRIES 4096
#define TX_DC_BASE 0x11000
// Event Queue
#define EV_CODE_RX 0
/* for each TX/RX entry one entry plus an additonal 2 for mcdi completion
and link state events */
-#define EV_ENTRIES 4096
+#define EV_ENTRIES 32768
// RX Queue
#define RX_DESC_CACHE_SIZE 64
-#define RX_ENTRIES 2048
+#define RX_ENTRIES 4096
#define RX_DC_BASE 0xD000
// calculcat max frame length
#define MTU 1500
#include <barrelfish/nameservice_client.h>
#include <barrelfish/spawn_client.h>
#include <barrelfish/deferred.h>
+#include <netd/netd.h>
+#include <net_device_manager/net_device_manager.h>
#include <pci/pci.h>
#include <ipv4/lwip/inet.h>
#include <barrelfish/debug.h>
#include <if/net_ARP_defs.h>
#include <if/net_ARP_defs.h>
-
#include "sfn5122f.h"
#include "sfn5122f_debug.h"
#include "buffer_tbl.h"
+#include "sfn5122f_qdriver.h"
struct queue_state {
bool enabled;
static bool use_msix = false;
static const char *service_name = "sfn5122f";
static sfn5122f_t *d = NULL;
+static void* d_virt;
//static sfn5122f_msix_t *d_msix = NULL;
static uint64_t d_mac[2];
static int initialized = 0;
static size_t cdriver_msix = -1;
static uint8_t cdriver_vector;
-static bool use_interrupt = false;
+static bool use_interrupt = true;
// first to start everything
static bool first = 1;
uint8_t mc_hash[32];
// Filters
-//static uint32_t ip = 175178791;
+//static uint32_t ip = 0x2704710A;
static uint32_t ip = 0;
enum filter_type_ip {
static void probe_all(void);
static uint32_t init_txq(uint16_t n, lpaddr_t phys, bool csum, bool userspace);
static uint32_t init_rxq(uint16_t n, lpaddr_t phys, bool userspace);
-static uint32_t init_evq(uint16_t n, lpaddr_t phys);
+static uint32_t init_evq(uint16_t n, lpaddr_t phys, bool interrupt);
static void queue_hw_stop(uint16_t n);
static void setup_interrupt(size_t *msix_index, uint8_t core, uint8_t vector);
reg_hi = sfn5122f_rx_filter_ctl_reg_hi_ethernet_full_search_limit_insert(reg_hi, 1);
reg_hi = sfn5122f_rx_filter_ctl_reg_hi_ethernet_wildcard_search_limit_insert(reg_hi, 3);
- // TODO set to 0
reg_lo = sfn5122f_rx_filter_ctl_reg_lo_multicast_nomatch_q_id_lo_insert(reg_lo, 0);
reg_lo = sfn5122f_rx_filter_ctl_reg_lo_unicast_nomatch_q_id_insert(reg_lo, 0);
reg_lo = sfn5122f_rx_filter_ctl_reg_lo_unicast_nomatch_rss_enabled_insert(reg_lo, 0);
// unset bit and set other bit which are not in documentation (43 and 47)
reg = sfn5122f_rx_cfg_reg_lo_rx_desc_push_en_insert(reg, 0) ;
reg = sfn5122f_rx_cfg_reg_lo_rx_ingr_en_insert(reg, 1);
- reg = sfn5122f_rx_cfg_reg_lo_rx_usr_buf_size_insert(reg, (MTU_MAX-256) >> 5);
- //reg = sfn5122f_rx_cfg_reg_lo_rx_usr_buf_size_insert(reg, 4096 >> 5);
+ //reg = sfn5122f_rx_cfg_reg_lo_rx_usr_buf_size_insert(reg, (MTU_MAX-256) >> 5);
+ reg = sfn5122f_rx_cfg_reg_lo_rx_usr_buf_size_insert(reg, 4096 >> 5);
//reg = sfn5122f_rx_cfg_reg_lo_rx_ownerr_ctl_insert(reg, 1);
reg = sfn5122f_rx_cfg_reg_lo_rx_ip_hash_insert(reg, 1);
//reg = sfn5122f_rx_cfg_reg_lo_rx_hash_insrt_hdr_insert(reg, 1);
(from linux driver) */
reg = sfn5122f_tx_reserved_reg_lo_rd(d);
reg = sfn5122f_tx_reserved_reg_lo_tx_rx_spacer_en_insert(reg, 1);
- reg = sfn5122f_tx_reserved_reg_lo_tx_one_pkt_per_q_insert(reg, 1);
+ reg = sfn5122f_tx_reserved_reg_lo_tx_one_pkt_per_q_insert(reg, 0);
reg = sfn5122f_tx_reserved_reg_lo_tx_dis_non_ip_ev_insert(reg, 1);
/* Enable software events */
reg2 = sfn5122f_tx_reserved_reg_hi_rd(d);
reg2 = sfn5122f_tx_reserved_reg_hi_tx_push_en_insert(reg2, 0);
reg2 = sfn5122f_tx_reserved_reg_hi_tx_push_chk_dis_insert(reg2, 0);
- reg2 = sfn5122f_tx_reserved_reg_hi_tx_rx_spacer_insert(reg2, 0xfe);
+ //reg2 = sfn5122f_tx_reserved_reg_hi_tx_rx_spacer_insert(reg2, 0xfe);
+ reg2 = sfn5122f_tx_reserved_reg_hi_tx_rx_spacer_insert(reg2, 0x1);
sfn5122f_tx_reserved_reg_lo_wr(d, reg);
sfn5122f_tx_reserved_reg_hi_wr(d, reg2);
static void start_all(void)
{
uint64_t reg;
- uint8_t in[CMD_MAC_STATS_IN_LEN];
- unsigned long long* stats = (unsigned long long *) mac_virt;
- uint8_t* pointer;
start_port(pci_function);
sfn5122f_int_en_reg_ker_hi_wr(d, sfn5122f_int_en_reg_ker_hi_rd(d));
/* Start MAC stats */
+ /*
+ uint8_t in[CMD_MAC_STATS_IN_LEN];
+ unsigned long long* stats = (unsigned long long *) mac_virt;
+ uint8_t* pointer;
+
memset(in, 0, sizeof(in));
stats[0x60] = (unsigned long long) (-1);
memcpy(in, &mac_phys, 8);
errval_t err = mcdi_rpc(CMD_MAC_STATS, in, CMD_MAC_STATS_IN_LEN,
NULL, 0, NULL, pci_function, d);
assert(err_is_ok(err));
+ */
}
/**************************************************************************
-static uint32_t init_evq(uint16_t n, lpaddr_t phys)
+static uint32_t init_evq(uint16_t n, lpaddr_t phys, bool interrupt)
{
//errval_t r;
} else {
reg = sfn5122f_timer_tbl_lo_int_pend_insert(reg, 0);
reg = sfn5122f_timer_tbl_lo_int_armd_insert(reg, 0);
- if (use_interrupt) {
+ if (use_interrupt && interrupt) {
reg = sfn5122f_timer_tbl_lo_host_notify_mode_insert(reg, 0);
} else {
reg = sfn5122f_timer_tbl_lo_host_notify_mode_insert(reg, 1);
// setup EV queue
reg = sfn5122f_evq_ptr_tbl_lo_rd(d, n);
reg = sfn5122f_evq_ptr_tbl_lo_evq_en_insert(reg, 1);
- reg = sfn5122f_evq_ptr_tbl_lo_evq_size_insert(reg, 3);
+ reg = sfn5122f_evq_ptr_tbl_lo_evq_size_insert(reg, 6);
reg = sfn5122f_evq_ptr_tbl_lo_evq_buf_base_id_insert(reg,
buffer_offset);
sfn5122f_timer_command_reg_lo_wr(d, n, reg);
-
sfn5122f_evq_rptr_reg_wr(d, n, queues[n].ev_head);
return buffer_offset;
static uint32_t init_rxq(uint16_t n, lpaddr_t phys, bool userspace)
{
//errval_t r;
- size_t num_ent_rx;
//struct frame_identity frameid = { .base = 0, .bytes = 0 };
uint64_t reg_lo, reg_hi, buffer_offset;
/*
rx_phys = frameid.base;
rx_size = frameid.bytes;
*/
+
+ /* RX */
if (userspace) {
- num_ent_rx = NUM_ENT_RX_USR;
+ buffer_offset = alloc_buf_tbl_entries(phys, NUM_ENT_RX_USR, 0, false, d);
} else {
- num_ent_rx = NUM_ENT_RX;
+ buffer_offset = alloc_buf_tbl_entries(phys, NUM_ENT_RX, 0, false, d);
}
- /* RX */
- buffer_offset = alloc_buf_tbl_entries(phys, num_ent_rx, 0, 0, d);
-
if (buffer_offset == -1) {
return -1;
}
reg_lo = sfn5122f_rx_desc_ptr_tbl_lo_rx_descq_label_insert(reg_lo, n);
/* 1024 entries = 1 (512 = 0; 2048 = 2 ; 4096 = 3) */
- reg_lo = sfn5122f_rx_desc_ptr_tbl_lo_rx_descq_size_insert(reg_lo, 1);
+ reg_lo = sfn5122f_rx_desc_ptr_tbl_lo_rx_descq_size_insert(reg_lo, 3);
if (!userspace) {
reg_lo = sfn5122f_rx_desc_ptr_tbl_lo_rx_descq_type_insert(reg_lo, 0);
reg_lo = sfn5122f_rx_desc_ptr_tbl_lo_rx_descq_en_insert(reg_lo, 1);
/* Hardware verifies data digest */
- reg_hi = sfn5122f_rx_desc_ptr_tbl_hi_rx_iscsi_ddig_en_insert(reg_hi, 1);
- reg_hi = sfn5122f_rx_desc_ptr_tbl_hi_rx_iscsi_hdig_en_insert(reg_hi, 1);
+ reg_hi = sfn5122f_rx_desc_ptr_tbl_hi_rx_iscsi_ddig_en_insert(reg_hi, 0);
+ reg_hi = sfn5122f_rx_desc_ptr_tbl_hi_rx_iscsi_hdig_en_insert(reg_hi, 0);
sfn5122f_rx_desc_ptr_tbl_lo_wr(d, n, reg_lo);
sfn5122f_rx_desc_ptr_tbl_hi_wr(d, n, reg_hi);
}
reg = sfn5122f_tx_desc_ptr_tbl_lo_tx_descq_label_insert(reg , n);
/* 1024 entries = 1 (512 = 0; 2048 = 2 ; 4096 = 3) */
- reg = sfn5122f_tx_desc_ptr_tbl_lo_tx_descq_size_insert(reg , 2);
+ reg = sfn5122f_tx_desc_ptr_tbl_lo_tx_descq_size_insert(reg , 3);
/* No user lvl networking */
if (!userspace) {
*msix_index, core, dest, vector);
}
+static void resend_interrupt(void* arg)
+{
+ errval_t err;
+ uint64_t i = (uint64_t) arg;
+ err = queues[i].devif->tx_vtbl.interrupt(queues[i].devif, NOP_CONT, i);
+ // If the queue is busy, there is already an oustanding message
+ if (err_is_fail(err) && err != FLOUNDER_ERR_TX_BUSY) {
+ USER_PANIC("Error when sending interrupt %s \n", err_getstring(err));
+ }
+}
+
/** Here are the global interrupts handled. */
static void global_interrupt_handler(void* arg)
{
//uint64_t reg;
- uint32_t queue;
+ errval_t err;
+ uint32_t q_to_check;
errval_t syserr;
uint8_t* net_ivec_fatal = (uint8_t *) int_ker_virt;
}
- queue = sfn5122f_int_isr0_reg_lo_rd(d);
- DEBUG("AN INTERRUPT OCCURED %d \n", queue);
+ q_to_check = sfn5122f_int_isr0_reg_lo_rd(d);
+
+ for (uint64_t i = 1; i < 32; i++) {
+ if ((q_to_check >> i) & 0x1) {
+ if (queues[i].use_irq && queues[i].devif != NULL) {
+ DEBUG("Interrupt to queue %lu \n", i);
+ err = queues[i].devif->tx_vtbl.interrupt(queues[i].devif, NOP_CONT, i);
+ if (err_is_fail(err)) {
+ err = queues[i].devif->register_send(queues[i].devif,
+ get_default_waitset(),
+ MKCONT(resend_interrupt, (void*)i));
+ }
+ }
+ }
+ }
+
+ if (q_to_check & 0x1) {
+ DEBUG("Interrupt to queue 0 \n");
+ check_queue_0();
+ }
-
-
+
// Don't need to start event queues because we're already polling
}
struct frame_identity id;
err = invoke_frame_identify(ev_frame, &id);
assert(err_is_ok(err));
- queues[n].ev_buf_tbl = init_evq(n, id.base);
+ queues[n].ev_buf_tbl = init_evq(n, id.base, use_irq);
// enable checksums
errval_t *err,
uint64_t *fid)
{
- DEBUG("idc_register_port_filter: called (q=%d t=%d p=%d)\n",
- queue, type, port);
if (ip == 0) {
/* Get cards IP */
waitset_init(&rpc_ws);
bind_arp(&rpc_ws);
arp_ip_info();
+ printf("IP %d \n", ip);
}
+ DEBUG("idc_register_port_filter: called (q=%d t=%d p=%d)\n",
+ queue, type, port);
+
struct sfn5122f_filter_ip f = {
.dst_port = port,
.dst_ip = htonl(ip),
struct frame_identity id;
int n = -1;
- for (int i = 0; i < NUM_QUEUES; i++) {
+ for (int i = 1; i < NUM_QUEUES; i++) {
if (queues[i].enabled == false) {
n = i;
break;
queues[n].msix_intdest = core;
queues[n].msix_intvec = msix_vector;
- if (queues[n].use_irq) {
+ if (queues[n].use_irq && use_msix) {
if (queues[n].msix_intvec != 0) {
if (queues[n].msix_index == -1) {
setup_interrupt(&queues[n].msix_index, queues[n].msix_intdest,
err = invoke_frame_identify(frame, &id);
assert(err_is_ok(err));
- queues[n].ev_buf_tbl = init_evq(n, id.base+sizeof(uint64_t)*(TX_ENTRIES+RX_ENTRIES));
// enable checksums
queues[n].tx_buf_tbl = init_txq(n, id.base, csum_offload, user);
queues[n].rx_buf_tbl = init_rxq(n, id.base+ sizeof(uint64_t)*TX_ENTRIES, user);
+ queues[n].ev_buf_tbl = init_evq(n, id.base+sizeof(uint64_t)*(TX_ENTRIES+RX_ENTRIES),
+ interrupt);
if(queues[n].ev_buf_tbl == -1 ||
queues[n].tx_buf_tbl == -1 ||
queues[n].rx_buf_tbl == -1){
size_t size = id.bytes;
lpaddr_t addr = id.base;
- // TODO unsigned/signed not nice ...
+ // TODO unsigned/signed
buffer_offset = alloc_buf_tbl_entries(addr, size/BUF_SIZE, qid, true, d);
if (buffer_offset == -1) {
err = b->tx_vtbl.register_region_response(b, NOP_CONT, 0, NIC_ERR_REGISTER_REGION);
}
err = b->tx_vtbl.register_region_response(b, NOP_CONT, buffer_offset, SYS_ERR_OK);
- assert(err_is_ok(err));
+ if (err_is_fail(err)) {
+
+ }
}
/* Initialize Mackerel binding */
sfn5122f_initialize(d, (void*) bar_info[0].vaddr);
+ d_virt = bar_info[0].vaddr;
// Initialize manager for MSI-X vectors
if (use_msix) {
eventloop();
}
+
+
+/*
+static errval_t init_stack(void)
+{
+
+ struct netd_state *state;
+ char* card_name = "sfn5122f";
+ uint32_t allocated_queue = 0;
+ uint32_t total_queues = 16;
+ uint8_t filter_type = 2;
+ bool do_dhcp = false;
+ char* ip_addr_str = "10.113.4.39";
+ char* netmask_str = "255.255.252.0";
+ char* gateway_str = "10.113.4.4";
+ errval_t err;
+
+ err = init_device_manager(card_name, total_queues, filter_type);
+ if (err_is_fail(err)) {
+ return err;
+ }
+
+ err = netd_init(&state, card_name, allocated_queue, do_dhcp,
+ ip_addr_str, netmask_str, gateway_str);
+ if (err_is_fail(err)) {
+ return err;
+ }
+
+ return SYS_ERR_OK;
+}
+*/
+
int main(int argc, char** argv)
{
DEBUG("SFN5122F driver started \n");
- errval_t r;
+ errval_t err;
parse_cmdline(argc, argv);
/* Register our device driver */
- r = pci_client_connect();
- assert(err_is_ok(r));
- r = pci_register_driver_irq(pci_init_card, PCI_CLASS_ETHERNET,
+ err = pci_client_connect();
+ assert(err_is_ok(err));
+ err = pci_register_driver_irq(pci_init_card, PCI_CLASS_ETHERNET,
PCI_DONT_CARE, PCI_DONT_CARE,
PCI_VENDOR_SOLARFLARE, DEVICE_ID,
pci_bus, pci_device, pci_function,
event_dispatch(get_default_waitset());
}
+ init_queue_0("sfn5122f", d_mac[pci_function], d_virt,
+ use_interrupt, false, &queues[0].ev_frame,
+ &queues[0].tx_frame, &queues[0].rx_frame);
+
+ queues[0].enabled = false;
+ queues[0].tx_head = 0;
+ queues[0].rx_head = 0;
+ queues[0].ev_head = 0;
+ queues[0].rxbufsz = MTU_MAX;
+ queues[0].binding = NULL;
+ queues[0].use_irq = true;
+ queues[0].userspace = false;
+
+ struct frame_identity id;
+ err = invoke_frame_identify(queues[0].ev_frame, &id);
+ assert(err_is_ok(err));
+ queues[0].ev_buf_tbl = init_evq(0, id.base, queues[0].use_irq);
+ // enable checksums
+ err = invoke_frame_identify(queues[0].tx_frame, &id);
+ assert(err_is_ok(err));
+ queues[0].tx_buf_tbl = init_txq(0, id.base, csum_offload, false);
+
+ err = invoke_frame_identify(queues[0].rx_frame, &id);
+ assert(err_is_ok(err));
+ queues[0].rx_buf_tbl = init_rxq(0, id.base, false);
+
+ write_queue_tails();
+
+ start_all();
+
+ /*
+ err = init_stack();
+ if (err_is_fail(err)) {
+ USER_PANIC("Failed initalizing netd etc %s \n", err_getstring(err));
+ }
+ */
+
+ /*
+ struct sfn5122f_filter_ip f = {
+ .dst_port = 7,
+ .dst_ip = htonl(0x2704710A),
+ .src_ip = 0,
+ .src_port = 0,
+ .type_ip = sfn5122f_PORT_UDP,
+ .queue = 1,
+ };
+
+ uint64_t fid;
+ for (int i = 0; i < 10; i++) {
+ f.dst_port = 7+i;
+ f.queue = i+1;
+ err = reg_port_filter(&f, &fid);
+ assert(err_is_ok(err));
+
+ }
+ */
/* loop myself */
cd_main();
}
#endif
-#ifdef DEBUG_buftbl
+#ifdef DEBUG_BUFTBL
#define DEBUG_BUF(x...) printf("buftbl: " x)
#else
#define DEBUG_BUF(x...) do {} while (0)
-/* Copyright (c) 2007-2011, ETH Zurich.
+/* Copyright (c) 2017, ETH Zurich.
* All rights reserved.
*
* This file is distributed under the terms in the attached LICENSE file.
* If you do not find this file, copies can be found by writing to:
- * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
+ * ETH Zurich D-INFK, Universitätstrasse 6, CH-8092 Zurich. Attn: Systems Group.
*/
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <net_queue_manager/net_queue_manager.h>
-#include <barrelfish/nameservice_client.h>
-#include <barrelfish/spawn_client.h>
-#include <barrelfish/debug.h>
-#include <barrelfish/deferred.h>
-#include <pci/pci.h>
-
-#include <if/sfn5122f_defs.h>
#include <dev/sfn5122f_dev.h>
#include <dev/sfn5122f_q_dev.h>
#include "sfn5122f_queue.h"
#include "sfn5122f_debug.h"
#include "buffer_tbl.h"
-
-/******************************************************************************/
-/* Prototypes */
-
-static void idc_register_queue_memory(uint8_t queue,
- struct capref tx_frame,
- struct capref ev_frame,
- struct capref rx_frame,
- uint32_t rxbufsz,
- uint8_t vector,
- coreid_t core);
-
-static void idc_terminate_queue(void);
-
-void qd_queue_init_data(struct sfn5122f_binding *b, struct capref registers,
- uint64_t macaddr);
-void qd_queue_memory_registered(struct sfn5122f_binding *b);
-void qd_write_queue_tails(struct sfn5122f_binding *b);
-
-void qd_argument(const char *arg);
-void qd_main(void);
-int main(int argc, char **argv) __attribute__((weak));
-
-/* Global state */
-static const char* service_name = "sfn5122f";
-
-/** Binding to the internal sfn5122f management service */
-static struct sfn5122f_binding *binding = NULL;
+#include "sfn5122f_qdriver.h"
/** Queue index for this manager instance */
-static int qi = -1;
+static int qi = 0;
/** Mackerel handle for device */
static sfn5122f_t *d = NULL;
static uint64_t mac_address = 0;
/** Indicates if the initialization is done */
-static int initialized = 0;
+static bool initialized = false;
/**
* Indicates whether we should rely on cache coherence for the descriptor
static bool cache_coherence = true;
/** Indicates whether Interrupts should be used */
-static bool use_interrupts = false;
-static bool use_msix = false;
-static coreid_t core = 0;
-static uint8_t vector = 0;
+static bool use_interrupts = true;
/** Capability for hardware TX ring */
static struct capref tx_frame;
//static void* mac_virt;
uint64_t mac_stats_array[NUM_MAC_STATS];
-/** Userspace networking enable */
-static bool userspace = 0;
/******************************************************************************/
/* Transmit path */
}
static errval_t transmit_pbuf_list_fn(struct driver_buffer *buffers,
- size_t count)
+ size_t count)
{
size_t i;
// need to block until initalized
if (!initialized) {
- return 0;
+ return NIC_ERR_QDRIVER;
}
ev_code = sfn5122f_get_event_code(q);
buf[0].opaque = op;
process_received_packet(buf, 1, 0);
} else {
+ DEBUG_QUEUE("Failed receiveing \n");
// TODO how to tell the the upper layer that it can reuse
// the rx buffer
}
sfn5122f_queue_bump_evhead(q);
break;
case EV_CODE_TX:
- if (sfn5122f_queue_handle_tx_ev(q, &op) == SYS_ERR_OK) {
+ if (sfn5122f_queue_handle_tx_ev(q) == SYS_ERR_OK) {
DEBUG_QUEUE("TX EVENT OK %d \n", qi);
- handle_tx_done(op);
+ uint8_t index = 0;
+ while (q->num_left > 0) {
+ handle_tx_done(q->bufs[0]);
+ index++;
+ q->num_left--;
+ }
} else {
DEBUG_QUEUE("TX EVENT ERR %d \n", qi);
}
sfn5122f_queue_bump_evhead(q);
break;
case EV_CODE_DRV:
- //DEBUG_QUEUE("DRIVER EVENT %d\n", qi);
+ DEBUG_QUEUE("DRIVER EVENT %d\n", qi);
sfn5122f_handle_drv_ev(q, qi);
sfn5122f_queue_bump_evhead(q);
break;
sfn5122f_queue_bump_evhead(q);
break;
case EV_CODE_MCDI:
- //DEBUG_QUEUE("MCDI EVENT \n");
+ DEBUG_QUEUE("MCDI EVENT \n");
sfn5122f_queue_handle_mcdi_event(q);
sfn5122f_queue_bump_evhead(q);
break;
{
memcpy(mac, &mac_address, 6);
}
-/******************************************************************************/
-/* Interrupts */
-
-static void qd_interrupt(void)
-{
- size_t count;
-
- count = check_for_new_events();
- if (count <= 0) {
- DEBUG_QUEUE("qd_int_%d: qid=%d no events \n", disp_get_core_id(), qi);
- } else {
- DEBUG_QUEUE("qd_int_%d: qid=%d events processed=%ld \n", disp_get_core_id(),
- qi, count);
- }
-
-}
-
-static void interrupt_handler(void *data)
-{
- qd_interrupt();
-}
/******************************************************************************/
/* Device/queue initialization */
/** Allocate queue n and return handle for queue manager */
-static void setup_queue(void)
+static void setup_queue(struct capref* ev, struct capref* tx, struct capref* rx)
{
size_t tx_size, rx_size, ev_size;
void *tx_virt, *rx_virt, *ev_virt;
/* Allocate memory for descriptor rings
No difference for userspace networking*/
tx_size = sfn5122f_q_tx_ker_desc_size * TX_ENTRIES;
- tx_virt = alloc_map_frame(flags_vreg, tx_size, &tx_frame);
+ tx_virt = alloc_map_frame(flags_vreg, tx_size, tx);
assert(tx_virt != NULL);
- if (!userspace) {
- rx_size = sfn5122f_q_rx_ker_desc_size * RX_ENTRIES;
- } else {
- rx_size = sfn5122f_q_rx_user_desc_size * RX_ENTRIES;
- }
+ rx_size = sfn5122f_q_rx_ker_desc_size * RX_ENTRIES;
- rx_virt = alloc_map_frame(flags_vreg, rx_size, &rx_frame);
+ rx_virt = alloc_map_frame(flags_vreg, rx_size, rx);
assert(rx_virt != NULL);
ev_size = sfn5122f_q_event_entry_size * EV_ENTRIES;
- ev_virt = alloc_map_frame(flags_vreg, ev_size, &ev_frame);
+ ev_virt = alloc_map_frame(flags_vreg, ev_size, ev);
assert(ev_virt != NULL);
- if (use_interrupts && use_msix) {
- DEBUG_QUEUE("Enabling MSI-X interrupts\n");
- errval_t err = pci_setup_inthandler(interrupt_handler, NULL, &vector);
- assert(err_is_ok(err));
- core = disp_get_core_id();
- } else {
- if (use_interrupts) {
- DEBUG_QUEUE("Enabling legacy interrupts\n");
- }
- vector = 0;
- core = 0;
- }
-
-
// Initialize queue manager
q = sfn5122f_queue_init(tx_virt, TX_ENTRIES, rx_virt, RX_ENTRIES,
- ev_virt, EV_ENTRIES, &ops, NULL, userspace);
- idc_register_queue_memory(qi, tx_frame, rx_frame,
- ev_frame, MTU_MAX, vector, core);
-
-}
-
-/** Terminate this queue driver */
-static void terminate_queue_fn(void)
-{
- idc_terminate_queue();
+ ev_virt, EV_ENTRIES, &ops, NULL, false);
}
-/******************************************************************************/
-/* Management interface implemetation */
-/** Request device register cap from card driver */
-static void idc_request_device_info(void)
+void write_queue_tails(void)
{
+ DEBUG_QUEUE("idc_write_queue_tails()\n");
- errval_t r;
- DEBUG_QUEUE("idc_request_device_info()\n");
-
- r = sfn5122f_request_device_info__tx(binding, NOP_CONT);
- // TODO: handle busy
- assert(err_is_ok(r));
+ sfn5122f_queue_bump_rxtail(q);
+ sfn5122f_queue_bump_txtail(q);
}
-/** Send memory caps to card driver */
-static void idc_register_queue_memory(uint8_t queue,
- struct capref tx,
- struct capref rx,
- struct capref ev,
- uint32_t rxbufsz,
- uint8_t vec,
- coreid_t cid)
+size_t check_queue_0(void)
{
-
- errval_t r;
- DEBUG_QUEUE("idc_register_queue_memory()\n");
-
- r = sfn5122f_register_queue_memory__tx(binding, NOP_CONT, queue,
- tx, rx, ev, rxbufsz,
- use_interrupts, userspace,
- vec, cid);
- // TODO: handle busy
- assert(err_is_ok(r));
+ do_pending_work_for_all();
+ return check_for_new_events();
}
-// Callback from device manager
-void qd_queue_init_data(struct sfn5122f_binding *b, struct capref registers,
- uint64_t macaddr)
+static void terminate_queue_fn(void)
{
- struct frame_identity frameid = { .base = 0, .bytes = 0 };
errval_t err;
- void *virt;
-
- DEBUG_QUEUE("idc_queue_init_data\n");
-
- mac_address = macaddr;
-
- // Map device registers
- invoke_frame_identify(registers, &frameid);
- err = vspace_map_one_frame_attr(&virt, frameid.bytes, registers,
- VREGION_FLAGS_READ_WRITE_NOCACHE, NULL, NULL);
-
+ err = terminate_queue_0();
assert(err_is_ok(err));
-
- // Initialize mackerel device
- d = malloc(sizeof(*d));
- sfn5122f_initialize(d, virt);
- // Initialize queue
- setup_queue();
-}
-
-/** Tell card driver to stop this queue. */
-static void idc_terminate_queue(void)
-{
- errval_t r;
- DEBUG_QUEUE("idc_terminate_queue()\n");
-
- r = sfn5122f_terminate_queue__tx(binding, NOP_CONT, qi);
- // TODO: handle busy
- assert(err_is_ok(r));
}
// Callback from device manager
-void qd_queue_memory_registered(struct sfn5122f_binding *b)
-{
- initialized = 1;
- // Register queue with queue_mgr library
- DEBUG_QUEUE("Called ethersrv_init() \n");
- ethersrv_init((char*) service_name, qi,
- get_mac_address_fn,
- terminate_queue_fn,
- transmit_pbuf_list_fn,
- find_tx_free_slot_count_fn,
- handle_free_tx_slot_fn,
- MTU_MAX,
- register_rx_buffer_fn,
- find_rx_free_slot_count_fn);
-}
-
-// Callback from device manager
-void qd_write_queue_tails(struct sfn5122f_binding *b)
-{
- DEBUG_QUEUE("idc_write_queue_tails()\n");
-
- sfn5122f_queue_bump_rxtail(q);
- sfn5122f_queue_bump_txtail(q);
-}
-
-
-// Callback from device manager
-static void idc_queue_terminated(struct sfn5122f_binding *b)
+errval_t terminate_queue_0(void)
{
errval_t err;
// Free memory for hardware ring buffers
if (q->userspace) {
err = vspace_unmap(q->tx_ring.user);
- assert(err_is_ok(err));
+ if (err_is_fail(err)) {
+ return err;
+ }
err = vspace_unmap(q->rx_ring.user);
- assert(err_is_ok(err));
+ if (err_is_fail(err)) {
+ return err;
+ }
} else {
err = vspace_unmap(q->tx_ring.ker);
- assert(err_is_ok(err));
+ if (err_is_fail(err)) {
+ return err;
+ }
err = vspace_unmap(q->rx_ring.ker);
- assert(err_is_ok(err));
+ if (err_is_fail(err)) {
+ return err;
+ }
}
err = vspace_unmap(q->ev_ring);
- assert(err_is_ok(err));
+ if (err_is_fail(err)) {
+ return err;
+ }
err = cap_delete(tx_frame);
- assert(err_is_ok(err));
- err = cap_delete(rx_frame);
- assert(err_is_ok(err));
- err = cap_delete(ev_frame);
- assert(err_is_ok(err));
-
- exit(0);
-}
-
-static struct sfn5122f_rx_vtbl rx_vtbl = {
- .queue_init_data = qd_queue_init_data,
- .queue_memory_registered = qd_queue_memory_registered,
- .write_queue_tails = qd_write_queue_tails,
- .queue_terminated = idc_queue_terminated,
-};
-
-static void bind_cb(void *st, errval_t err, struct sfn5122f_binding *b)
-{
- assert(err_is_ok(err));
-
- DEBUG_QUEUE("Sucessfully connected to management interface\n");
-
- b->rx_vtbl = rx_vtbl;
- binding = b;
-
- idc_request_device_info();
-}
-
-/** Connect to the management interface */
-static void connect_to_mngif(void)
-{
- errval_t r;
- iref_t iref;
- const char *suffix = "_sfn5122fmng";
- char name[strlen(service_name) + strlen(suffix) + 1];
-
- // Build label for interal management service
- sprintf(name, "%s%s", service_name, suffix);
-
- // Connect to service
- DEBUG_QUEUE("Looking up management interface (%s)\n", name);
- r = nameservice_blocking_lookup(name, &iref);
- assert(err_is_ok(r));
-
- DEBUG_QUEUE("Binding to management interface\n");
- r = sfn5122f_bind(iref, bind_cb, NULL, get_default_waitset(),
- IDC_BIND_FLAGS_DEFAULT);
- assert(err_is_ok(r));
-}
-
-void qd_argument(const char *arg)
-{
- if (strncmp(arg, "cardname=", strlen("cardname=") - 1) == 0) {
- service_name = arg + strlen("cardname=");
- ethersrv_argument(arg);
-
- } else if (strncmp(arg, "queue=", strlen("queue=") - 1) == 0) {
- qi = atol(arg + strlen("queue="));
- ethersrv_argument(arg);
-
- } else if (strncmp(arg, "cache_coherence=",
- strlen("cache_coherence=") - 1) == 0) {
- cache_coherence = !!atol(arg + strlen("cache_coherence="));
-
- } else if (strncmp(arg, "interrupts=", strlen("interrupts=") - 1) == 0) {
- use_interrupts = !!atol(arg + strlen("interrupts="));
- DEBUG_QUEUE("Interrupts enabled: legacy interrupts for fatal device errors\n");
- } else if (strncmp(arg, "msix=", strlen("msix=") - 1) == 0) {
- USER_PANIC("MSI-X not fully implemented yet!");
- use_msix = !!atol(arg + strlen("msix="));
- DEBUG_QUEUE("Using msix \n");
- } else if (strncmp(arg, "userspace=", strlen("userspace=") - 1) == 0) {
- USER_PANIC("Userspace networking for SFN5122F not implemented!");
- /*
- userspace = atol(arg + strlen("userspace="));
- ethersrv_argument(arg);
- */
- } else {
- ethersrv_argument(arg);
+ if (err_is_fail(err)) {
+ return err;
}
-}
-
-static void parse_cmdline(int argc, char **argv)
-{
- int i;
- for (i = 1; i < argc; i++) {
- qd_argument(argv[i]);
+ err = cap_delete(rx_frame);
+ if (err_is_fail(err)) {
+ return err;
}
-}
-
-static void eventloop(void)
-{
- struct waitset *ws;
- errval_t err;
-
- DEBUG_QUEUE("eventloop()\n");
-
- ws = get_default_waitset();
- while (1) {
- err = event_dispatch_non_block(ws);
- do_pending_work_for_all();
- check_for_new_events();
+ err = cap_delete(ev_frame);
+ if (err_is_fail(err)) {
+ return err;
}
+ return SYS_ERR_OK;
}
-static void eventloop_ints(void)
+errval_t init_queue_0(char* cname, uint64_t mac_addr, void* device,
+ bool interrupts, bool userspace, struct capref* ev,
+ struct capref* tx, struct capref* rx)
{
- struct waitset *ws;
- DEBUG_QUEUE("eventloop_ints()\n");
-
- ws = get_default_waitset();
- while (1) {
- event_dispatch(ws);
- do_pending_work_for_all();
- }
-}
+ use_interrupts = interrupts;
+ mac_address = mac_addr;
-void qd_main(void)
-{
- // Validate some settings
- if (qi == -1) {
- USER_PANIC("For queue driver the queue= parameter has to be specified "
- "on the command line!");
- }
+ d = malloc(sizeof(*d));
+ sfn5122f_initialize(d, device);
+ // Initialize queue
+ setup_queue(ev, tx, rx);
- connect_to_mngif();
+ ethersrv_init((char*) cname, 0,
+ get_mac_address_fn,
+ terminate_queue_fn,
+ transmit_pbuf_list_fn,
+ find_tx_free_slot_count_fn,
+ handle_free_tx_slot_fn,
+ MTU_MAX,
+ register_rx_buffer_fn,
+ find_rx_free_slot_count_fn);
- if (use_interrupts) {
- eventloop_ints();
- } else {
- eventloop();
- }
-}
+ tx_frame = *tx;
+ rx_frame = *tx;
+ ev_frame = *tx;
-int main(int argc, char **argv)
-{
- DEBUG_QUEUE("Started\n");
- parse_cmdline(argc, argv);
- qd_main();
+ initialized = true;
+
+ return SYS_ERR_OK;
}
--- /dev/null
+/* Copyright (c) 2017, ETH Zurich.
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, Universitätstrasse 6, CH-8092 Zurich. Attn: Systems Group.
+ */
+
+#ifndef LIBQDRIVER_H_
+#define LIBQDRIVER_H_
+
+void write_queue_tails(void);
+size_t check_queue_0(void);
+errval_t terminate_queue_0(void);
+errval_t init_queue_0(char* cname, uint64_t mac_addr, void* device,
+ bool interrupts, bool userspace, struct capref* ev,
+ struct capref* tx, struct capref* rx);
+
+#endif
#include <string.h>
#include <stdlib.h>
-#include <devif/queue_interface.h>
#include <dev/sfn5122f_q_dev.h>
#include <dev/sfn5122f_dev.h>
#include "helper.h"
+#include "sfn5122f_debug.h"
#define MTU_MAX 2048
-struct sfn5122f_devif_binding;
-struct sfn5122f_devif_rpc_client;
struct sfn5122f_queue;
struct sfn5122f_queue_ops {
uint16_t id;
sfn5122f_t *device;
struct region_entry* regions;
+
+ // TX envents might merge multiple TX descirptors
+ void* bufs[32];
+ uint8_t last;
+ uint8_t num_left;
};
typedef struct sfn5122f_queue sfn5122f_queue_t;
+
+static inline bool is_batched(size_t size, uint16_t tx_head, uint16_t q_tx_head)
+{
+ if (tx_head >= q_tx_head) {
+ return (tx_head - q_tx_head > 0);
+ } else {
+ return (((tx_head + size) - q_tx_head) > 0);
+ }
+}
+
static inline sfn5122f_queue_t* sfn5122f_queue_init(void* tx,
size_t tx_size,
void* rx,
return 0;
}
-
-static inline int sfn5122f_queue_add_user_rxbuf_devif(sfn5122f_queue_t* q,
- uint32_t buf_id,
- uint16_t offset,
- regionid_t rid,
- bufferid_t devq_bid,
- lpaddr_t base,
- size_t len,
- uint64_t flags)
-{
- struct devq_buf* buf;
- sfn5122f_q_rx_user_desc_t d;
- size_t tail = q->rx_tail;
-
- d = q->rx_ring.user[tail];
- buf = &q->rx_bufs[tail];
-
- buf->rid = rid;
- buf->bid = devq_bid;
- buf->addr = base;
- buf->len = len;
- buf->flags = flags;
- sfn5122f_q_rx_user_desc_rx_user_buf_id_insert(d, buf_id);
- sfn5122f_q_rx_user_desc_rx_user_2byte_offset_insert(d, offset >> 1);
- q->rx_tail = (tail + 1) % q->rx_size;
- return 0;
-}
-
-static inline int sfn5122f_queue_add_rxbuf_devif(sfn5122f_queue_t* q,
- regionid_t rid,
- bufferid_t bid,
- lpaddr_t addr,
- size_t len,
- uint64_t flags)
-{
- struct devq_buf* buf;
- sfn5122f_q_rx_ker_desc_t d;
- size_t tail = q->rx_tail;
-
- d = q->rx_ring.ker[tail];
-
- buf = &q->rx_bufs[tail];
-
- buf->rid = rid;
- buf->bid = bid;
- buf->addr = addr;
- buf->len = len;
- buf->flags = flags;
-
- sfn5122f_q_rx_ker_desc_rx_ker_buf_addr_insert(d, addr);
- sfn5122f_q_rx_ker_desc_rx_ker_buf_region_insert(d, 0);
- // TODO: Check size
- sfn5122f_q_rx_ker_desc_rx_ker_buf_size_insert(d, len);
- q->rx_tail = (tail + 1) % q->rx_size;
- return 0;
-}
-
-
static inline errval_t sfn5122f_queue_handle_rx_ev(sfn5122f_queue_t* q,
void** opaque,
size_t* len)
sfn5122f_q_rx_user_desc_t d_user = 0;
ev = q->ev_ring[ev_head];
+ rx_head = sfn5122f_q_rx_ev_rx_ev_desc_ptr_extract(ev);
if(!sfn5122f_q_rx_ev_rx_ev_pkt_ok_extract(ev)) {
// TODO error handling
+ q->rx_head = (rx_head + 1) % q->rx_size;
if (sfn5122f_q_rx_ev_rx_ev_tobe_disc_extract(ev)) {
// packet discared by softare -> ok
return NIC_ERR_RX_DISCARD;
}
- printf("Packet not ok \n");
+ if (sfn5122f_q_rx_ev_rx_ev_frm_trunc_extract(ev)) {
+ //printf("Packet truncated \n");
+ }
+
+ if (sfn5122f_q_rx_ev_rx_ev_pkt_not_parsed_extract(ev)) {
+ DEBUG_QUEUE("Packet not parsed\n");
+ }
+
+ if (sfn5122f_q_rx_ev_rx_ev_ip_frag_err_extract(ev)) {
+ DEBUG_QUEUE("Packet IP header err\n");
+ }
+
+ if (sfn5122f_q_rx_ev_rx_ev_ip_hdr_chksum_err_extract(ev)) {
+ DEBUG_QUEUE("Packet IP header checksum err\n");
+ }
+
+ if (sfn5122f_q_rx_ev_rx_ev_tcp_udp_chksum_err_extract(ev)) {
+ DEBUG_QUEUE("Packet TCP/UPD checksum err\n");
+ }
+
+ if (sfn5122f_q_rx_ev_rx_ev_eth_crc_err_extract(ev)) {
+ DEBUG_QUEUE("Packet Ethernet CRC err\n");
+ }
+
+ DEBUG_QUEUE("Packet not ok \n");
return NIC_ERR_RX_PKT;
}
*len = 16384;
}
- rx_head = sfn5122f_q_rx_ev_rx_ev_desc_ptr_extract(ev);
if (q->userspace) {
d_user = q->rx_ring.user[rx_head];
} else {
return SYS_ERR_OK;
}
-
-static inline errval_t sfn5122f_queue_handle_rx_ev_devif(sfn5122f_queue_t* q,
- regionid_t* rid,
- bufferid_t* bid,
- lpaddr_t* base,
- size_t* len,
- uint64_t* flags)
-{
- /* Only one event is generated even if there is more than one
- descriptor per packet */
- struct devq_buf* buf;
- size_t ev_head = q->ev_head;
- size_t rx_head;
- sfn5122f_q_rx_ev_t ev;
- sfn5122f_q_rx_user_desc_t d_user = 0;
-
- ev = q->ev_ring[ev_head];
- rx_head = sfn5122f_q_rx_ev_rx_ev_desc_ptr_extract(ev);
-
- buf = &q->rx_bufs[rx_head];
-
- *rid = buf->rid;
- *bid = buf->bid;
- *base = buf->addr;
- *flags = buf->flags;
-
- if(!sfn5122f_q_rx_ev_rx_ev_pkt_ok_extract(ev)) {
- // TODO error handling
- q->rx_head = (rx_head + 1) % q->rx_size;
- if (sfn5122f_q_rx_ev_rx_ev_tobe_disc_extract(ev)) {
- // packet discared by softare -> ok
- return NIC_ERR_RX_DISCARD;
- }
-
- printf("Packet not ok \n");
- if (sfn5122f_q_rx_ev_rx_ev_buf_owner_id_extract(ev)) {
- printf("Wrong owner \n");
- }
- return NIC_ERR_RX_PKT;
- }
-
- *len = sfn5122f_q_rx_ev_rx_ev_byte_ctn_extract(ev);
- /* Length of 0 is treated as 16384 bytes */
- if (*len == 0) {
- *len = 16384;
- }
-
- rx_head = sfn5122f_q_rx_ev_rx_ev_desc_ptr_extract(ev);
- d_user = q->rx_ring.user[rx_head];
-
- buf = &q->rx_bufs[rx_head];
-
- *rid = buf->rid;
- *bid = buf->bid;
- *base = buf->addr;
- *flags = buf->flags;
-
- memset(ev, 0xff, sfn5122f_q_event_entry_size);
- memset(d_user, 0 , sfn5122f_q_rx_user_desc_size);
-
- q->rx_head = (rx_head + 1) % q->rx_size;
- return SYS_ERR_OK;
-}
-
static inline void sfn5122f_queue_bump_evhead(sfn5122f_queue_t* q)
{
q->ev_head = (q->ev_head +1) % q->ev_size;
}
-static inline errval_t sfn5122f_queue_handle_tx_ev(sfn5122f_queue_t* q, void** opaque)
+static inline errval_t sfn5122f_queue_handle_tx_ev(sfn5122f_queue_t* q)
{
/* Only one event is generated even if there is more than one
descriptor per packet */
size_t tx_head;
sfn5122f_q_tx_ev_t ev;
sfn5122f_q_tx_ker_desc_t d = 0;
- sfn5122f_q_tx_user_desc_t d_user= 0;
+
ev = q->ev_ring[ev_head];
+ tx_head = sfn5122f_q_tx_ev_tx_ev_desc_ptr_extract(ev);
+
if(sfn5122f_q_tx_ev_tx_ev_pkt_err_extract(ev)){
//TODO error handling
return NIC_ERR_TX_PKT;
}
+
if (sfn5122f_q_tx_ev_tx_ev_comp_extract(ev) == 1){
- tx_head = sfn5122f_q_tx_ev_tx_ev_desc_ptr_extract(ev);
- if (q->userspace) {
- d_user = q->tx_ring.user[tx_head];
- } else {
+ // TX Event is a batch
+ if (is_batched(q->tx_size, tx_head, q->tx_head)) {
+ uint8_t index = 0;
+ q->num_left = 0;
+ d = q->tx_ring.ker[q->tx_head];
+ while (q->tx_head != (tx_head + 1) % q->tx_size ) {
+ q->bufs[index] = q->tx_opaque[q->tx_head];
+ index++;
+ q->tx_head = (q->tx_head + 1) % q->tx_size;
+ q->num_left++;
+ }
+ memset(d, 0 , sfn5122f_q_tx_ker_desc_size*q->num_left);
+ } else { // Singe descriptor
d = q->tx_ring.ker[tx_head];
+ q->num_left = 1;
+ q->bufs[0] = q->tx_opaque[tx_head];
+ memset(d, 0 , sfn5122f_q_tx_ker_desc_size);
}
- *opaque = q->tx_opaque[tx_head];
-
// reset entry event in queue
memset(ev, 0xff, sfn5122f_q_event_entry_size);
- if (q->userspace) {
- memset(d_user, 0 , sfn5122f_q_tx_user_desc_size);
- } else {
- memset(d, 0 , sfn5122f_q_tx_ker_desc_size);
- }
- q->tx_head = (tx_head +1) % q->tx_size;
- }
-
- return SYS_ERR_OK;
-}
-
-
-static inline errval_t sfn5122f_queue_handle_tx_ev_devif(sfn5122f_queue_t* q,
- regionid_t* rid,
- bufferid_t* bid,
- lpaddr_t* base,
- size_t* len,
- uint64_t* flags)
-{
- /* Only one event is generated even if there is more than one
- descriptor per packet */
- size_t ev_head = q->ev_head;
- size_t tx_head;
- struct devq_buf* buf;
- sfn5122f_q_tx_ev_t ev;
- sfn5122f_q_tx_user_desc_t d_user= 0;
-
- ev = q->ev_ring[ev_head];
- tx_head = sfn5122f_q_tx_ev_tx_ev_desc_ptr_extract(ev);
-
-
- buf = &q->tx_bufs[tx_head];
-
- *rid = buf->rid;
- *bid = buf->bid;
- *base = buf->addr;
- *flags = buf->flags;
-
- if (sfn5122f_q_tx_ev_tx_ev_pkt_err_extract(ev)){
- q->tx_head = (tx_head +1) % q->tx_size;
- return NIC_ERR_TX_PKT;
- }
-
- if (sfn5122f_q_tx_ev_tx_ev_comp_extract(ev) == 1){
- d_user = q->tx_ring.user[tx_head];
-
- // reset entry event in queue
- memset(ev, 0xff, sfn5122f_q_event_entry_size);
- memset(d_user, 0 , sfn5122f_q_tx_user_desc_size);
q->tx_head = (tx_head +1) % q->tx_size;
}
return 0;
}
-static inline int sfn5122f_queue_add_txbuf_devif(sfn5122f_queue_t* q,
- regionid_t rid,
- bufferid_t bid,
- lpaddr_t base,
- size_t len,
- uint64_t flags)
-{
- struct devq_buf* buf;
- sfn5122f_q_tx_ker_desc_t d;
- size_t tail = q->tx_tail;
-
- d = q->tx_ring.ker[tail];
-
- buf = &q->tx_bufs[tail];
-
- bool last = flags & DEVQ_BUF_FLAG_TX_LAST;
- buf->rid = rid;
- buf->bid = bid;
- buf->addr = base;
- buf->len = len;
- buf->flags = flags;
-
- sfn5122f_q_tx_ker_desc_tx_ker_buf_addr_insert(d, base);
- sfn5122f_q_tx_ker_desc_tx_ker_byte_count_insert(d, len);
- sfn5122f_q_tx_ker_desc_tx_ker_cont_insert(d, !last);
- sfn5122f_q_tx_ker_desc_tx_ker_buf_region_insert(d, 0);
-
- __sync_synchronize();
-
- q->tx_tail = (tail + 1) % q->tx_size;
- return 0;
-}
-
-
-static inline int sfn5122f_queue_add_user_txbuf_devif(sfn5122f_queue_t* q,
- uint64_t buftbl_idx,
- uint64_t offset,
- regionid_t rid,
- bufferid_t devq_bid,
- lpaddr_t base,
- size_t len,
- uint64_t flags)
-{
- sfn5122f_q_tx_user_desc_t d;
- struct devq_buf* buf;
- size_t tail = q->tx_tail;
-
- d = q->tx_ring.ker[tail];
- buf = &q->tx_bufs[tail];
-
- bool last = flags & DEVQ_BUF_FLAG_TX_LAST;
- buf->rid = rid;
- buf->bid = devq_bid;
- buf->addr = base;
- buf->len = len;
- buf->flags = flags;
-
- sfn5122f_q_tx_user_desc_tx_user_sw_ev_en_insert(d, 0);
- sfn5122f_q_tx_user_desc_tx_user_cont_insert(d, !last);
- sfn5122f_q_tx_user_desc_tx_user_byte_cnt_insert(d, len);
- sfn5122f_q_tx_user_desc_tx_user_buf_id_insert(d, buftbl_idx);
- sfn5122f_q_tx_user_desc_tx_user_byte_ofs_insert(d, offset);
-
- __sync_synchronize();
-
- q->tx_tail = (tail + 1) % q->tx_size;
- return 0;
-}
-
-#endif //ndef SFN5122F_CHANNEL_H_
+#endif