#include "hw_queue.h"
#include "helper.h"
+
//#define DEBUG_SFN
#ifdef DEBUG_SFN
#define DEBUG_QUEUE(x...) printf("sfn5122f_q : " x)
//#define DELAY 1
// TX Queue
-#define TX_ENTRIES 2048
-#define RX_ENTRIES 2048
+#define TX_ENTRIES 4096
+#define RX_ENTRIES 4096
+#define EV_ENTRIES 32768
// Event Queue
#define EV_CODE_RX 0
#define EV_CODE_TX 2
/* for each TX/RX entry one entry plus an additonal 2 for mcdi completion
and link state events */
-#define EV_ENTRIES 4096
+
+struct sfn5122f_queue* queues[1024];
+
/** Misc */
static errval_t update_rxtail(struct sfn5122f_queue* q, size_t tail)
assert(q->device != NULL);
uint64_t reg = 0;
- reg = sfn5122f_rx_desc_upd_reg_hi_rx_desc_wptr_insert(reg, tail);
- /* don't want to push an additional rx descriptor with the write pointer */
- reg = sfn5122f_rx_desc_upd_reg_hi_rx_desc_push_cmd_insert(reg, 0);
- /* the lower register will be ignored */
- sfn5122f_rx_desc_upd_reg_lo_wr(q->device, q->id, 0);
- sfn5122f_rx_desc_upd_reg_hi_wr(q->device, q->id, reg);
+ q->rx_batch_size++;
+
+ if (q->rx_batch_size > 31) {
+ /* Write to this register is very very expensive (2500 cycles +)
+ So we batch the updates together*/
+ reg = sfn5122f_rx_desc_upd_reg_hi_rx_desc_wptr_insert(reg, tail);
+ /* don't want to push an additional rx descriptor with the write pointer */
+ reg = sfn5122f_rx_desc_upd_reg_hi_rx_desc_push_cmd_insert(reg, 0);
+ /* the lower register will be ignored */
+ sfn5122f_rx_desc_upd_reg_lo_wr(q->device, q->id, 0);
+ sfn5122f_rx_desc_upd_reg_hi_wr(q->device, q->id, reg);
+ q->rx_batch_size = 0;
+ }
return SYS_ERR_OK;
}
return SYS_ERR_OK;
}
+static void interrupt_cb(struct sfn5122f_devif_binding *b, uint16_t qid)
+{
+ struct sfn5122f_queue* q = queues[qid];
+ q->cb(q);
+}
+
+static struct sfn5122f_devif_rx_vtbl rx_vtbl = {
+ .interrupt = interrupt_cb,
+};
+
static void bind_cb(void *st, errval_t err, struct sfn5122f_devif_binding *b)
{
DEBUG_QUEUE("binding CB \n");
struct sfn5122f_queue* queue = (struct sfn5122f_queue*) st;
b->st = queue;
+ b->rx_vtbl = rx_vtbl;
// Initi RPC client
queue->b = b;
cur->next = entry;
+ DEBUG_QUEUE("Region %d registered \n", rid);
return SYS_ERR_OK;
}
static errval_t sfn5122f_control(struct devq* q, uint64_t cmd, uint64_t value, uint64_t *result)
{
-
+
DEBUG_QUEUE("Control cmd=%lu value=%lu \n", cmd, value);
return SYS_ERR_OK;
}
genoffset_t valid_data, genoffset_t valid_length,
uint64_t flags)
{
-
DEBUG_QUEUE("Enqueueing RX buf \n");
// check if there is space
+
if (sfn5122f_queue_free_rxslots(q) == 0) {
- printf("SFN5122F_%d: Not enough space in RX ring, not adding buffer\n",
+ DEBUG_QUEUE("SFN5122F_%d: Not enough space in RX ring, not adding buffer\n",
q->id);
return DEVQ_ERR_QUEUE_FULL;
}
// find region
+
struct region_entry* entry = q->regions;
+ // If regions already empty -> return error
+ if (entry == NULL) {
+ return DEVQ_ERR_INVALID_REGION_ARGS;
+ }
+
while((entry->next != NULL) && (entry->rid != rid)) {
entry = entry->next;
}
if (entry == NULL) {
return DEVQ_ERR_INVALID_REGION_ARGS;
}
-
- // compute buffer table entry of the rx buffer and the within it offset
- uint64_t buftbl_idx = entry->buftbl_idx + (offset/BUF_SIZE);
- uint16_t b_off = offset & 0x00000FFF;
- // still in the same buffer table entry
- assert(buftbl_idx == (entry->buftbl_idx + ((offset+length-1)/BUF_SIZE)));
-
-
- DEBUG_QUEUE("RX_BUF tbl_idx=%lu offset=%d flags=%lu \n",
- buftbl_idx, b_off, flags);
if (q->userspace) {
+ // compute buffer table entry of the rx buffer and the within it offset
+ uint64_t buftbl_idx = entry->buftbl_idx + (offset/BUF_SIZE);
+ uint16_t b_off = offset & 0x00000FFF;
+
+ DEBUG_QUEUE("RX_BUF tbl_idx=%lu offset=%d flags=%lu \n",
+ buftbl_idx, b_off, flags);
+ // still in the same buffer table entry
+ assert(buftbl_idx == (entry->buftbl_idx + ((offset+length-1)/BUF_SIZE)));
sfn5122f_queue_add_user_rxbuf_devif(q, buftbl_idx, b_off,
rid, offset, length, valid_data,
valid_length, flags);
} else {
sfn5122f_queue_add_rxbuf_devif(q, entry->phys + offset, rid, offset, length,
valid_data, valid_length, flags);
+
}
- sfn5122f_queue_bump_rxtail(q);
+
+ update_rxtail(q, q->rx_tail);
return SYS_ERR_OK;
}
-
static errval_t enqueue_tx_buf(struct sfn5122f_queue* q, regionid_t rid,
genoffset_t offset, genoffset_t length,
genoffset_t valid_data, genoffset_t valid_length,
uint64_t flags)
{
- DEBUG_QUEUE("Enqueueing TX buf \n");
+ DEBUG_QUEUE("Enqueueing TX buf\n");
// check if there is space
if (sfn5122f_queue_free_txslots(q) == 0) {
printf("SFN5122F_%d: Not enough space in TX ring, not adding buffer\n",
// find region
struct region_entry* entry = q->regions;
+ if (entry == NULL) {
+ return DEVQ_ERR_INVALID_REGION_ARGS;
+ }
+
while((entry->next != NULL) && (entry->rid != rid)) {
entry = entry->next;
}
return DEVQ_ERR_INVALID_REGION_ARGS;
}
- // compute buffer table entry of the rx buffer and the within it offset
- uint64_t buftbl_idx = entry->buftbl_idx + (offset/BUF_SIZE);
- uint16_t b_off = offset & 0x00000FFF;
+ if (q->userspace) {
+ // compute buffer table entry of the rx buffer and the within it offset
+ uint64_t buftbl_idx = entry->buftbl_idx + (offset/BUF_SIZE);
+ uint16_t b_off = offset & 0x00000FFF;
- // still in the same buffer table entry
- assert(buftbl_idx == (entry->buftbl_idx + ((offset+length-1)/BUF_SIZE)));
- DEBUG_QUEUE("TX_BUF tbl_idx=%lu offset=%d flags=%lu \n", buftbl_idx, b_off,
+ DEBUG_QUEUE("TX_BUF tbl_idx=%lu offset=%d flags=%lx \n", buftbl_idx, b_off,
flags);
- if (q->userspace) {
-
- DEBUG_QUEUE("TX_BUF tbl_idx=%lu offset=%d flags=%lu \n", buftbl_idx, b_off,
- flags);
+ // still in the same buffer table entry
+ assert(buftbl_idx == (entry->buftbl_idx + ((offset+length-1)/BUF_SIZE)));
sfn5122f_queue_add_user_txbuf_devif(q, buftbl_idx, b_off,
rid, offset, length, valid_data,
valid_length, flags);
+
} else {
- DEBUG_QUEUE("TX_BUF flags=%lu \n", flags);
+ DEBUG_QUEUE("TX_BUF phys=%zu \n", entry->phys + offset);
sfn5122f_queue_add_txbuf_devif(q, entry->phys + offset, rid, offset,
length, valid_data, valid_length,
flags);
}
- sfn5122f_queue_bump_txtail(q);
+ update_txtail(q, q->tx_tail);
return SYS_ERR_OK;
}
if (err_is_fail(err)) {
return err;
}
+ } else {
+ printf("Unknown buffer flags \n");
+ return NIC_ERR_ENQUEUE;
}
return SYS_ERR_OK;
struct sfn5122f_queue* queue = (struct sfn5122f_queue*) q;
- sfn5122f_evq_rptr_reg_wr(queue->device, queue->id, queue->ev_head);
+ //sfn5122f_evq_rptr_reg_wr(queue->device, queue->id, queue->ev_head);
//__sync_synchronize();
if (queue->num_left > 0) {
err = sfn5122f_queue_handle_rx_ev_devif(queue, rid, offset, length,
valid_data, valid_length,
flags);
- if (err_is_ok(err)) {
- DEBUG_QUEUE(" RX_EV Q_ID: %d len %ld \n", queue->id, *length);
+ DEBUG_QUEUE("RX_EV Q_ID: %d len %ld OK %s \n", queue->id, *valid_length,
+ err_getstring(err));
+
+ if (err_is_fail(err)) {
+ err = enqueue_rx_buf(queue, *rid, *offset, *length,
+ *valid_data, *valid_length,
+ *flags);
+ if (err_is_fail(err)) {
+ printf("Error receiving packet, could not enqueue buffer\n");
+ }
+ sfn5122f_queue_bump_evhead(queue);
+ continue;
}
sfn5122f_queue_bump_evhead(queue);
+ assert(*valid_length > 0);
return SYS_ERR_OK;
case EV_CODE_TX:
err = sfn5122f_queue_handle_tx_ev_devif(queue, rid, offset, length,
sfn5122f_queue_bump_evhead(queue);
return SYS_ERR_OK;
case EV_CODE_DRV:
- //DEBUG_QUEUE("DRIVER EVENT %d\n", qi);
+ DEBUG_QUEUE("DRIVER EVENT %d\n", queue->id);
sfn5122f_handle_drv_ev(queue, queue->id);
sfn5122f_queue_bump_evhead(queue);
break;
sfn5122f_queue_bump_evhead(queue);
break;
case EV_CODE_MCDI:
- //DEBUG_QUEUE("MCDI EVENT \n");
+ DEBUG_QUEUE("MCDI EVENT \n");
sfn5122f_queue_handle_mcdi_event(queue);
sfn5122f_queue_bump_evhead(queue);
break;
static void interrupt_handler(void* arg)
{
- printf("WTF \n");
struct sfn5122f_queue* queue = (struct sfn5122f_queue*) arg;
- // TODO check fata interrupts
queue->cb(queue);
}
+
+
/**
* Public functions
*
/* Allocate memory for descriptor rings
No difference for userspace networking*/
- // TODO too large ...
total_size = sizeof(uint64_t)*(TX_ENTRIES + RX_ENTRIES + EV_ENTRIES);
tx_virt = alloc_map_frame(VREGION_FLAGS_READ_WRITE, total_size, &frame);
if (tx_virt == NULL) {
*q = queue;
+ queues[queue->id] = queue;
+
return SYS_ERR_OK;
}
#include <barrelfish/net_constants.h>
#include <devif/queue_interface.h>
#include <devif/backends/descq.h>
+#include <devif/backends/net/sfn5122f_devif.h>
+#include <devif/backends/net/e10k_devif.h>
#define MAX_SERVICE_NAME_LEN 256 // Max len that a name of service can have
#define BUFFER_SIZE 2048
static uint64_t bufid_tx;
static regionid_t regid_tx;
+static struct devq *devq_direct = NULL;
+static regionid_t regid_direct;
+static bool direct = false;
+static bool reg = false;
+
+
static struct capref buffer_frame;
void *buffer_base = NULL;
size_t buffer_size = 2048;
errval_t err;
offset += idx * BUFFER_SIZE;
- err = devq_enqueue((struct devq *)devq_tx, regid_tx, offset, length, 0, 0, flags);
- assert(err_is_ok(err));
+ if (!direct) {
+ err = devq_enqueue((struct devq *)devq_tx, regid_tx, offset, length, 0, 0, flags);
+ } else {
+ flags = 0;
+ err = devq_enqueue((struct devq *)devq_direct, regid_direct, offset,
+ length, 0, length, (flags | NETIF_TXFLAG | NETIF_TXFLAG_LAST));
+ }
return err;
}
size_t offset;
offset = idx * BUFFER_SIZE;
- err = devq_enqueue((struct devq *)devq_rx, regid_rx, offset, BUFFER_SIZE, 0, 0, 0);
- assert(err_is_ok(err));
+ if (!direct) {
+ err = devq_enqueue((struct devq *)devq_rx, regid_rx, offset, BUFFER_SIZE, 0, 0, 0);
+ } else {
+ uint64_t flags = 0;
+ err = devq_enqueue((struct devq *)devq_direct, regid_direct, offset, BUFFER_SIZE,
+ 0, BUFFER_SIZE, flags | NETIF_RXFLAG);
+ }
return err;
}
static void buffers_init(size_t count)
{
- alloc_mem(&buffer_frame, &buffer_base, BUFFER_SIZE * count);
errval_t err;
- err = devq_register((struct devq *)devq_rx, buffer_frame, ®id_rx);
- assert(err_is_ok(err));
- err = devq_register((struct devq *)devq_tx, buffer_frame, ®id_tx);
- assert(err_is_ok(err));
+ alloc_mem(&buffer_frame, &buffer_base, BUFFER_SIZE * count);
+
+ if (!direct) {
+ err = devq_register((struct devq *)devq_rx, buffer_frame, ®id_rx);
+ assert(err_is_ok(err));
+ err = devq_register((struct devq *)devq_tx, buffer_frame, ®id_tx);
+ assert(err_is_ok(err));
+ } else {
+ err = devq_register((struct devq *)devq_direct, buffer_frame, ®id_direct);
+ assert(err_is_ok(err));
+ reg = true;
+ }
}
struct descq_func_pointer f;
f.notify = isRX ? notify_rx: notify_tx;
- debug_printf("Descriptor queue test started \n");
err = descq_create(isRX ? &devq_rx: &devq_tx, DESCQ_DEFAULT_SIZE, qm_name,
false, true, !isRX, isRX ? &bufid_rx: &bufid_tx, &f);
assert(err_is_ok(err));
}
+static void int_handler(void* args)
+{
+ regionid_t rid;
+ genoffset_t offset;
+ genoffset_t length;
+ genoffset_t valid_data;
+ genoffset_t valid_length;
+ uint64_t flags;
+
+ for (;;) {
+ errval_t err;
+ err = devq_dequeue(devq_direct, &rid, &offset, &length,
+ &valid_data, &valid_length, &flags);
+ if (err_is_fail(err))
+ break;
+
+ size_t idx = offset / BUFFER_SIZE;
+ if (flags & NETIF_TXFLAG) {
+ benchmark_tx_done(idx);
+ } else if (flags & NETIF_RXFLAG) {
+ assert(valid_length > 0);
+ benchmark_rx_done(idx, valid_length, 0/*more*/, flags);
+ }
+ }
+
+}
+
void net_if_init(const char* cardname, uint64_t qid)
{
+ errval_t err;
static bool initialized = false;
struct waitset *ws = get_default_waitset();
queue_id = qid;
// Connect RX path
- connect_to_driver(cardname, queue_id, true, ws);
- // Connect TX path
- connect_to_driver(cardname, queue_id, false, ws);
+ if ((strcmp(cardname, "e1000") == 0) || (qid == 0)) {
+ connect_to_driver(cardname, queue_id, true, ws);
+ // Connect TX path
+ connect_to_driver(cardname, queue_id, false, ws);
+ } else if ((strcmp(cardname, "e10k") == 0) && (qid != 0)) {
+ USER_PANIC("e10k queue NIY \n");
+ /*
+ direct = true;
+ struct e10k_queue* e10k;
+ err = e10k_queue_create(&e10k, int_handler, false, false);
+ assert(err_is_ok(err));
+
+ devq_direct = (struct devq*) e10k;
+ card_mac = 0x1; // TODO
+ */
+ } else if ((strcmp(cardname, "sfn5122f") == 0) && qid != 0) {
+ direct = true;
+ struct sfn5122f_queue* sfn5122f;
+ err = sfn5122f_queue_create(&sfn5122f, int_handler, false, true);
+ assert(err_is_ok(err));
+
+ devq_direct = (struct devq*) sfn5122f;
+ card_mac = 0x000f530748d4; // TODO
+ } else {
+ USER_PANIC("Unknown card name \n");
+ }
+
buffers_init(BUFFER_COUNT);
// Get MAC address
- errval_t err;
- err = devq_control((struct devq *)devq_rx, 0, 0, &card_mac);
- assert(err_is_ok(err));
+ if (!direct) {
+ err = devq_control((struct devq *)devq_rx, 0, 0, &card_mac);
+ assert(err_is_ok(err));
+ }
initialized = true;
}