diff options
Diffstat (limited to 'qemu/hw/net/rocker/rocker_desc.c')
-rw-r--r-- | qemu/hw/net/rocker/rocker_desc.c | 374 |
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; -} |