summaryrefslogtreecommitdiffstats
path: root/qemu/hw/net/rocker/rocker_desc.c
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/hw/net/rocker/rocker_desc.c')
-rw-r--r--qemu/hw/net/rocker/rocker_desc.c374
1 files changed, 0 insertions, 374 deletions
diff --git a/qemu/hw/net/rocker/rocker_desc.c b/qemu/hw/net/rocker/rocker_desc.c
deleted file mode 100644
index ac02797b7..000000000
--- a/qemu/hw/net/rocker/rocker_desc.c
+++ /dev/null
@@ -1,374 +0,0 @@
-/*
- * QEMU rocker switch emulation - Descriptor ring support
- *
- * Copyright (c) 2014 Scott Feldman <sfeldma@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include "qemu/osdep.h"
-#include "net/net.h"
-#include "hw/hw.h"
-#include "hw/pci/pci.h"
-
-#include "rocker.h"
-#include "rocker_hw.h"
-#include "rocker_desc.h"
-
-struct desc_ring {
- hwaddr base_addr;
- uint32_t size;
- uint32_t head;
- uint32_t tail;
- uint32_t ctrl;
- uint32_t credits;
- Rocker *r;
- DescInfo *info;
- int index;
- desc_ring_consume *consume;
- unsigned msix_vector;
-};
-
-struct desc_info {
- DescRing *ring;
- RockerDesc desc;
- char *buf;
- size_t buf_size;
-};
-
-uint16_t desc_buf_size(DescInfo *info)
-{
- return le16_to_cpu(info->desc.buf_size);
-}
-
-uint16_t desc_tlv_size(DescInfo *info)
-{
- return le16_to_cpu(info->desc.tlv_size);
-}
-
-char *desc_get_buf(DescInfo *info, bool read_only)
-{
- PCIDevice *dev = PCI_DEVICE(info->ring->r);
- size_t size = read_only ? le16_to_cpu(info->desc.tlv_size) :
- le16_to_cpu(info->desc.buf_size);
-
- if (size > info->buf_size) {
- info->buf = g_realloc(info->buf, size);
- info->buf_size = size;
- }
-
- if (!info->buf) {
- return NULL;
- }
-
- if (pci_dma_read(dev, le64_to_cpu(info->desc.buf_addr), info->buf, size)) {
- return NULL;
- }
-
- return info->buf;
-}
-
-int desc_set_buf(DescInfo *info, size_t tlv_size)
-{
- PCIDevice *dev = PCI_DEVICE(info->ring->r);
-
- if (tlv_size > info->buf_size) {
- DPRINTF("ERROR: trying to write more to desc buf than it "
- "can hold buf_size %zu tlv_size %zu\n",
- info->buf_size, tlv_size);
- return -ROCKER_EMSGSIZE;
- }
-
- info->desc.tlv_size = cpu_to_le16(tlv_size);
- pci_dma_write(dev, le64_to_cpu(info->desc.buf_addr), info->buf, tlv_size);
-
- return ROCKER_OK;
-}
-
-DescRing *desc_get_ring(DescInfo *info)
-{
- return info->ring;
-}
-
-int desc_ring_index(DescRing *ring)
-{
- return ring->index;
-}
-
-static bool desc_ring_empty(DescRing *ring)
-{
- return ring->head == ring->tail;
-}
-
-bool desc_ring_set_base_addr(DescRing *ring, uint64_t base_addr)
-{
- if (base_addr & 0x7) {
- DPRINTF("ERROR: ring[%d] desc base addr (0x" TARGET_FMT_plx
- ") not 8-byte aligned\n", ring->index, base_addr);
- return false;
- }
-
- ring->base_addr = base_addr;
-
- return true;
-}
-
-uint64_t desc_ring_get_base_addr(DescRing *ring)
-{
- return ring->base_addr;
-}
-
-bool desc_ring_set_size(DescRing *ring, uint32_t size)
-{
- int i;
-
- if (size < 2 || size > 0x10000 || (size & (size - 1))) {
- DPRINTF("ERROR: ring[%d] size (%d) not a power of 2 "
- "or in range [2, 64K]\n", ring->index, size);
- return false;
- }
-
- for (i = 0; i < ring->size; i++) {
- g_free(ring->info[i].buf);
- }
-
- ring->size = size;
- ring->head = ring->tail = 0;
-
- ring->info = g_renew(DescInfo, ring->info, size);
- if (!ring->info) {
- return false;
- }
-
- memset(ring->info, 0, size * sizeof(DescInfo));
-
- for (i = 0; i < size; i++) {
- ring->info[i].ring = ring;
- }
-
- return true;
-}
-
-uint32_t desc_ring_get_size(DescRing *ring)
-{
- return ring->size;
-}
-
-static DescInfo *desc_read(DescRing *ring, uint32_t index)
-{
- PCIDevice *dev = PCI_DEVICE(ring->r);
- DescInfo *info = &ring->info[index];
- hwaddr addr = ring->base_addr + (sizeof(RockerDesc) * index);
-
- pci_dma_read(dev, addr, &info->desc, sizeof(info->desc));
-
- return info;
-}
-
-static void desc_write(DescRing *ring, uint32_t index)
-{
- PCIDevice *dev = PCI_DEVICE(ring->r);
- DescInfo *info = &ring->info[index];
- hwaddr addr = ring->base_addr + (sizeof(RockerDesc) * index);
-
- pci_dma_write(dev, addr, &info->desc, sizeof(info->desc));
-}
-
-static bool desc_ring_base_addr_check(DescRing *ring)
-{
- if (!ring->base_addr) {
- DPRINTF("ERROR: ring[%d] not-initialized desc base address!\n",
- ring->index);
- return false;
- }
- return true;
-}
-
-static DescInfo *__desc_ring_fetch_desc(DescRing *ring)
-{
- return desc_read(ring, ring->tail);
-}
-
-DescInfo *desc_ring_fetch_desc(DescRing *ring)
-{
- if (desc_ring_empty(ring) || !desc_ring_base_addr_check(ring)) {
- return NULL;
- }
-
- return desc_read(ring, ring->tail);
-}
-
-static bool __desc_ring_post_desc(DescRing *ring, int err)
-{
- uint16_t comp_err = 0x8000 | (uint16_t)-err;
- DescInfo *info = &ring->info[ring->tail];
-
- info->desc.comp_err = cpu_to_le16(comp_err);
- desc_write(ring, ring->tail);
- ring->tail = (ring->tail + 1) % ring->size;
-
- /* return true if starting credit count */
-
- return ring->credits++ == 0;
-}
-
-bool desc_ring_post_desc(DescRing *ring, int err)
-{
- if (desc_ring_empty(ring)) {
- DPRINTF("ERROR: ring[%d] trying to post desc to empty ring\n",
- ring->index);
- return false;
- }
-
- if (!desc_ring_base_addr_check(ring)) {
- return false;
- }
-
- return __desc_ring_post_desc(ring, err);
-}
-
-static bool ring_pump(DescRing *ring)
-{
- DescInfo *info;
- bool primed = false;
- int err;
-
- /* If the ring has a consumer, call consumer for each
- * desc starting at tail and stopping when tail reaches
- * head (the empty ring condition).
- */
-
- if (ring->consume) {
- while (ring->head != ring->tail) {
- info = __desc_ring_fetch_desc(ring);
- err = ring->consume(ring->r, info);
- if (__desc_ring_post_desc(ring, err)) {
- primed = true;
- }
- }
- }
-
- return primed;
-}
-
-bool desc_ring_set_head(DescRing *ring, uint32_t new)
-{
- uint32_t tail = ring->tail;
- uint32_t head = ring->head;
-
- if (!desc_ring_base_addr_check(ring)) {
- return false;
- }
-
- if (new >= ring->size) {
- DPRINTF("ERROR: trying to set head (%d) past ring[%d] size (%d)\n",
- new, ring->index, ring->size);
- return false;
- }
-
- if (((head < tail) && ((new >= tail) || (new < head))) ||
- ((head > tail) && ((new >= tail) && (new < head)))) {
- DPRINTF("ERROR: trying to wrap ring[%d] "
- "(head %d, tail %d, new head %d)\n",
- ring->index, head, tail, new);
- return false;
- }
-
- if (new == ring->head) {
- DPRINTF("WARNING: setting head (%d) to current head position\n", new);
- }
-
- ring->head = new;
-
- return ring_pump(ring);
-}
-
-uint32_t desc_ring_get_head(DescRing *ring)
-{
- return ring->head;
-}
-
-uint32_t desc_ring_get_tail(DescRing *ring)
-{
- return ring->tail;
-}
-
-void desc_ring_set_ctrl(DescRing *ring, uint32_t val)
-{
- if (val & ROCKER_DMA_DESC_CTRL_RESET) {
- DPRINTF("ring[%d] resetting\n", ring->index);
- desc_ring_reset(ring);
- }
-}
-
-bool desc_ring_ret_credits(DescRing *ring, uint32_t credits)
-{
- if (credits > ring->credits) {
- DPRINTF("ERROR: trying to return more credits (%d) "
- "than are outstanding (%d)\n", credits, ring->credits);
- ring->credits = 0;
- return false;
- }
-
- ring->credits -= credits;
-
- /* return true if credits are still outstanding */
-
- return ring->credits > 0;
-}
-
-uint32_t desc_ring_get_credits(DescRing *ring)
-{
- return ring->credits;
-}
-
-void desc_ring_set_consume(DescRing *ring, desc_ring_consume *consume,
- unsigned vector)
-{
- ring->consume = consume;
- ring->msix_vector = vector;
-}
-
-unsigned desc_ring_get_msix_vector(DescRing *ring)
-{
- return ring->msix_vector;
-}
-
-DescRing *desc_ring_alloc(Rocker *r, int index)
-{
- DescRing *ring;
-
- ring = g_new0(DescRing, 1);
- if (!ring) {
- return NULL;
- }
-
- ring->r = r;
- ring->index = index;
-
- return ring;
-}
-
-void desc_ring_free(DescRing *ring)
-{
- g_free(ring->info);
- g_free(ring);
-}
-
-void desc_ring_reset(DescRing *ring)
-{
- ring->base_addr = 0;
- ring->size = 0;
- ring->head = 0;
- ring->tail = 0;
- ring->ctrl = 0;
- ring->credits = 0;
-}