All of lore.kernel.org
 help / color / mirror / Atom feed
From: Beniamino Galvani <b.galvani@gmail.com>
To: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Cc: qemu-devel@nongnu.org, dslutz@verizon.com
Subject: Re: [Qemu-devel] [PATCH for-2.1 v2 2/2] util/fifo: Generalise for common integer widths
Date: Tue, 8 Apr 2014 23:42:32 +0200	[thread overview]
Message-ID: <20140408214230.GB26832@gmail.com> (raw)
In-Reply-To: <d62027a6230c84d51394c406a240d142bb889810.1396920202.git.peter.crosthwaite@xilinx.com>

On Mon, Apr 07, 2014 at 07:05:18PM -0700, Peter Crosthwaite wrote:
> Add support for 16, 32 and 64 bit width FIFOs. The push and pop
> functions are patched to accept uint64_t always to support up to 64bit
> integer elements. The element width is set at creation time.
> 
> The backing storage for all element types is still uint8_t regardless of
> element width so some save-load logic is needed to handle endianness
> issue WRT VMSD.
> 
> Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
> ---
> 
>  hw/char/serial.c        |   4 +-
>  hw/net/allwinner_emac.c |   6 +--
>  hw/ssi/xilinx_spi.c     |   4 +-
>  hw/ssi/xilinx_spips.c   |   4 +-
>  include/qemu/fifo.h     |  19 +++++----
>  util/fifo.c             | 109 +++++++++++++++++++++++++++++++++++++++++-------
>  6 files changed, 114 insertions(+), 32 deletions(-)
> 
> diff --git a/hw/char/serial.c b/hw/char/serial.c
> index a0d8024..3060769 100644
> --- a/hw/char/serial.c
> +++ b/hw/char/serial.c
> @@ -659,8 +659,8 @@ void serial_realize_core(SerialState *s, Error **errp)
>  
>      qemu_chr_add_handlers(s->chr, serial_can_receive1, serial_receive1,
>                            serial_event, s);
> -    fifo_create(&s->recv_fifo, UART_FIFO_LENGTH);
> -    fifo_create(&s->xmit_fifo, UART_FIFO_LENGTH);
> +    fifo_create(&s->recv_fifo, UART_FIFO_LENGTH, 8);
> +    fifo_create(&s->xmit_fifo, UART_FIFO_LENGTH, 8);
>  }
>  
>  void serial_exit_core(SerialState *s)
> diff --git a/hw/net/allwinner_emac.c b/hw/net/allwinner_emac.c
> index e804411..2a0d2ac 100644
> --- a/hw/net/allwinner_emac.c
> +++ b/hw/net/allwinner_emac.c
> @@ -455,9 +455,9 @@ static void aw_emac_realize(DeviceState *dev, Error **errp)
>                            object_get_typename(OBJECT(dev)), dev->id, s);
>      qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
>  
> -    fifo_create(&s->rx_fifo, RX_FIFO_SIZE);
> -    fifo_create(&s->tx_fifo[0], TX_FIFO_SIZE);
> -    fifo_create(&s->tx_fifo[1], TX_FIFO_SIZE);
> +    fifo_create(&s->rx_fifo, RX_FIFO_SIZE, 8);
> +    fifo_create(&s->tx_fifo[0], TX_FIFO_SIZE, 8);
> +    fifo_create(&s->tx_fifo[1], TX_FIFO_SIZE, 8);
>  }
>  
>  static Property aw_emac_properties[] = {
> diff --git a/hw/ssi/xilinx_spi.c b/hw/ssi/xilinx_spi.c
> index 8fe3072..cac666b 100644
> --- a/hw/ssi/xilinx_spi.c
> +++ b/hw/ssi/xilinx_spi.c
> @@ -341,8 +341,8 @@ static int xilinx_spi_init(SysBusDevice *sbd)
>  
>      s->irqline = -1;
>  
> -    fifo_create(&s->tx_fifo, FIFO_CAPACITY);
> -    fifo_create(&s->rx_fifo, FIFO_CAPACITY);
> +    fifo_create(&s->tx_fifo, FIFO_CAPACITY, 8);
> +    fifo_create(&s->rx_fifo, FIFO_CAPACITY, 8);
>  
>      return 0;
>  }
> diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
> index d7d4c41..a7a639f 100644
> --- a/hw/ssi/xilinx_spips.c
> +++ b/hw/ssi/xilinx_spips.c
> @@ -669,8 +669,8 @@ static void xilinx_spips_realize(DeviceState *dev, Error **errp)
>  
>      s->irqline = -1;
>  
> -    fifo_create(&s->rx_fifo, xsc->rx_fifo_size);
> -    fifo_create(&s->tx_fifo, xsc->tx_fifo_size);
> +    fifo_create(&s->rx_fifo, xsc->rx_fifo_size, 8);
> +    fifo_create(&s->tx_fifo, xsc->tx_fifo_size, 8);
>  }
>  
>  static void xilinx_qspips_realize(DeviceState *dev, Error **errp)
> diff --git a/include/qemu/fifo.h b/include/qemu/fifo.h
> index 44766b3..8738027 100644
> --- a/include/qemu/fifo.h
> +++ b/include/qemu/fifo.h
> @@ -5,8 +5,12 @@
>  
>  typedef struct {
>      /* All fields are private */
> +    int width; /* byte width each each element */

of each element

> +    uint32_t capacity; /* number of elements */
> +
>      uint8_t *data;
> -    uint32_t capacity;
> +    uint32_t buffer_size;
> +
>      uint32_t head;
>      uint32_t num;
>  } Fifo;
> @@ -14,13 +18,14 @@ typedef struct {
>  /**
>   * fifo_create:
>   * @fifo: struct Fifo to initialise with new FIFO
> - * @capacity: capacity of the newly created FIFO
> + * @capacity: capacity (number of elements) of the newly created FIFO
> + * @width: integer width of each element. Must be 8, 16, 32 or 64.
>   *
>   * Create a FIFO of the specified size. Clients should call fifo_destroy()
>   * when finished using the fifo. The FIFO is initially empty.
>   */
>  
> -void fifo_create(Fifo *fifo, uint32_t capacity);
> +void fifo_create(Fifo *fifo, uint32_t capacity, int width);
>  
>  /**
>   * fifo_destroy:
> @@ -41,7 +46,7 @@ void fifo_destroy(Fifo *fifo);
>   * Clients are responsible for checking for fullness using fifo_is_full().
>   */
>  
> -void fifo_push(Fifo *fifo, uint8_t data);
> +void fifo_push(Fifo *fifo, uint64_t data);
>  
>  /**
>   * fifo_push_all:
> @@ -54,7 +59,7 @@ void fifo_push(Fifo *fifo, uint8_t data);
>   * fifo_num_free().
>   */
>  
> -void fifo_push_all(Fifo *fifo, const uint8_t *data, uint32_t num);
> +void fifo_push_all(Fifo *fifo, const void *data, uint32_t num);
>  
>  /**
>   * fifo_pop:
> @@ -66,7 +71,7 @@ void fifo_push_all(Fifo *fifo, const uint8_t *data, uint32_t num);
>   * Returns: The popped data value.
>   */
>  
> -uint8_t fifo_pop(Fifo *fifo);
> +uint64_t fifo_pop(Fifo *fifo);
>  
>  /**
>   * fifo_pop_buf:
> @@ -93,7 +98,7 @@ uint8_t fifo_pop(Fifo *fifo);
>   * Returns: A pointer to popped data.
>   */
>  
> -const uint8_t *fifo_pop_buf(Fifo *fifo, uint32_t max, uint32_t *num);
> +const void *fifo_pop_buf(Fifo *fifo, uint32_t max, uint32_t *num);
>  
>  /**
>   * fifo_reset:
> diff --git a/util/fifo.c b/util/fifo.c
> index ffadf55..51318ad 100644
> --- a/util/fifo.c
> +++ b/util/fifo.c
> @@ -15,9 +15,11 @@
>  #include "qemu-common.h"
>  #include "qemu/fifo.h"
>  
> -void fifo_create(Fifo *fifo, uint32_t capacity)
> +void fifo_create(Fifo *fifo, uint32_t capacity, int width)
>  {
> -    fifo->data = g_new(uint8_t, capacity);
> +    assert(width == 8 || width == 16 || width == 32 || width == 64);
> +    fifo->width = width / 8;
> +    fifo->data = g_new(uint8_t, capacity * fifo->width);
>      fifo->capacity = capacity;
>      fifo->head = 0;
>      fifo->num = 0;
> @@ -28,16 +30,33 @@ void fifo_destroy(Fifo *fifo)
>      g_free(fifo->data);
>  }
>  
> -void fifo_push(Fifo *fifo, uint8_t data)
> +void fifo_push(Fifo *fifo, uint64_t data)
>  {
> +    uint32_t next_idx = (fifo->head + fifo->num) % fifo->capacity;
> +
>      if (fifo->num == fifo->capacity) {
>          abort();
>      }
> -    fifo->data[(fifo->head + fifo->num) % fifo->capacity] = data;
> +    switch (fifo->width) {
> +    case(1):

To me 'case 1:' looks better, but it's only a personal taste :)

> +        ((uint8_t *)fifo->data)[next_idx] = data;
> +        break;
> +    case(2):
> +        ((uint16_t *)fifo->data)[next_idx] = data;
> +        break;
> +    case(4):
> +        ((uint32_t *)fifo->data)[next_idx] = data;
> +        break;
> +    case(8):
> +        ((uint64_t *)fifo->data)[next_idx] = data;
> +        break;
> +    default:
> +        abort();
> +    }
>      fifo->num++;
>  }
>  
> -void fifo_push_all(Fifo *fifo, const uint8_t *data, uint32_t num)
> +void fifo_push_all(Fifo *fifo, const void *data, uint32_t num)
>  {
>      uint32_t start, avail;
>  
> @@ -48,38 +67,51 @@ void fifo_push_all(Fifo *fifo, const uint8_t *data, uint32_t num)
>      start = (fifo->head + fifo->num) % fifo->capacity;
>  
>      if (start + num <= fifo->capacity) {
> -        memcpy(&fifo->data[start], data, num);
> +        memcpy(&fifo->data[start * fifo->width], data, num * fifo->width);
>      } else {
>          avail = fifo->capacity - start;
> -        memcpy(&fifo->data[start], data, avail);
> -        memcpy(&fifo->data[0], &data[avail], num - avail);
> +        memcpy(&fifo->data[start * fifo->width], data, avail * fifo->width);
> +        memcpy(&fifo->data[0], data + avail * fifo->width,
> +               (num - avail) * fifo->width);
>      }
>  
>      fifo->num += num;
>  }
>  
> -uint8_t fifo_pop(Fifo *fifo)
> +uint64_t fifo_pop(Fifo *fifo)
>  {
> -    uint8_t ret;
> +    uint32_t next_idx;
>  
>      if (fifo->num == 0) {
>          abort();
>      }
> -    ret = fifo->data[fifo->head++];
> +    next_idx = fifo->head++;
>      fifo->head %= fifo->capacity;
>      fifo->num--;
> -    return ret;
> +    switch (fifo->width) {
> +    case(1):
> +        return ((uint8_t *)fifo->data)[next_idx];
> +    case(2):
> +        return ((uint16_t *)fifo->data)[next_idx];
> +    case(4):
> +        return ((uint32_t *)fifo->data)[next_idx];
> +    case(8):
> +        return ((uint64_t *)fifo->data)[next_idx];
> +    default:
> +        abort();
> +        return 0; /* unreachable */
> +    }
>  }
>  
> -const uint8_t *fifo_pop_buf(Fifo *fifo, uint32_t max, uint32_t *num)
> +const void *fifo_pop_buf(Fifo *fifo, uint32_t max, uint32_t *num)
>  {
> -    uint8_t *ret;
> +    void *ret;
>  
>      if (max == 0 || max > fifo->num) {
>          abort();
>      }
>      *num = MIN(fifo->capacity - fifo->head, max);
> -    ret = &fifo->data[fifo->head];
> +    ret = &fifo->data[fifo->head * fifo->width];
>      fifo->head += *num;
>      fifo->head %= fifo->capacity;
>      fifo->num -= *num;
> @@ -112,13 +144,58 @@ uint32_t fifo_num_used(Fifo *fifo)
>      return fifo->num;
>  }
>  
> +/* Always store buffer data in little (arbitrarily chosen) endian format to
> + * allow for migration to/from BE <-> LE hosts.
> + */
> +
> +static inline void fifo_save_load_swap(Fifo *fifo)
> +{
> +#ifdef HOST_WORDS_BIGENDIAN
> +    int i;
> +    uint16_t *d16 = (uint16_t *)fifo->data;
> +    uint32_t *d32 = (uint32_t *)fifo->data;
> +    uint64_t *d64 = (uint64_t *)fifo->data;
> +
> +    for (i = 0; i < fifo->capacity; ++i) {
> +        switch (fifo->width) {
> +        case(1):
> +            return;
> +        case(2):
> +            d16[i] = bswap16(d16[i]);
> +            break;
> +        case(4):
> +            d32[i] = bswap32(d32[i]);
> +            break;
> +        case(8):
> +            d64[i] = bswap64(d64[i]);
> +            break;
> +        default:
> +            abort();
> +        }
> +    }
> +#endif
> +}
> +
> +static void fifo_pre_save(void *opaque)
> +{
> +    fifo_save_load_swap((Fifo *)opaque);
> +}
> +
> +static int fifo_post_load(void *opaque, int version_id)
> +{
> +    fifo_save_load_swap((Fifo *)opaque);
> +    return 0;
> +}
> +
>  const VMStateDescription vmstate_fifo = {
>      .name = "Fifo8",
>      .version_id = 1,
>      .minimum_version_id = 1,
>      .minimum_version_id_old = 1,
> +    .pre_save = fifo_pre_save,
> +    .post_load = fifo_post_load,
>      .fields      = (VMStateField[]) {
> -        VMSTATE_VBUFFER_UINT32(data, Fifo, 1, NULL, 0, capacity),
> +        VMSTATE_VBUFFER_UINT32(data, Fifo, 1, NULL, 0, buffer_size),
>          VMSTATE_UINT32(head, Fifo),
>          VMSTATE_UINT32(num, Fifo),
>          VMSTATE_END_OF_LIST()
> -- 
> 1.9.1.1.gbb9f595


I'm not familiar with vmsd save/load code, but the rest of the patch
seems good to me.

Beniamino

  reply	other threads:[~2014-04-08 21:42 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-04-08  2:04 [Qemu-devel] [PATCH for-2.1 v2 0/2] Generalise FIFO to more integer types Peter Crosthwaite
2014-04-08  2:04 ` [Qemu-devel] [PATCH for-2.1 v2 1/2] util/fifo: s/fifo8/fifo globally Peter Crosthwaite
2014-04-08 18:48   ` Beniamino Galvani
2014-04-09  1:50     ` Peter Crosthwaite
2014-04-08  2:05 ` [Qemu-devel] [PATCH for-2.1 v2 2/2] util/fifo: Generalise for common integer widths Peter Crosthwaite
2014-04-08 21:42   ` Beniamino Galvani [this message]
2014-04-09  1:51     ` Peter Crosthwaite
2014-04-08  7:14 ` [Qemu-devel] [PATCH for-2.1 v2 0/2] Generalise FIFO to more integer types Markus Armbruster
2014-04-08  7:24   ` Peter Crosthwaite
2014-04-08  9:10     ` Markus Armbruster
2014-04-08 21:22       ` Don Slutz
2014-04-09  0:03         ` Peter Crosthwaite

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20140408214230.GB26832@gmail.com \
    --to=b.galvani@gmail.com \
    --cc=dslutz@verizon.com \
    --cc=peter.crosthwaite@xilinx.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.