lib: Add a fifo implementation.
authorAtish Patra <atish.patra@wdc.com>
Tue, 2 Apr 2019 00:04:05 +0000 (17:04 -0700)
committerAnup Patel <anup@brainfault.org>
Wed, 3 Apr 2019 04:27:42 +0000 (09:57 +0530)
Implement a fifo to accomodate outstanding IPIs for a specific hart
at the same time.

Signed-off-by: Atish Patra <atish.patra@wdc.com>
include/sbi/sbi_fifo.h [new file with mode: 0644]
lib/objects.mk
lib/sbi_fifo.c [new file with mode: 0644]

diff --git a/include/sbi/sbi_fifo.h b/include/sbi/sbi_fifo.h
new file mode 100644 (file)
index 0000000..ba9769b
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2019 Western Digital Corporation or its affiliates.
+ *
+ * Authors:
+ *   Atish Patra<atish.patra@wdc.com>
+ *
+ */
+
+#ifndef __SBI_FIFO_H__
+#define __SBI_FIFO_H__
+
+#include <sbi/riscv_locks.h>
+#include <sbi/sbi_types.h>
+
+struct sbi_fifo {
+       int head;
+       int tail;
+       spinlock_t qlock;
+       unsigned long entrysize;
+       unsigned long num_entries;
+       void *queue;
+};
+
+int sbi_fifo_dequeue(struct sbi_fifo *fifo, void *data);
+int sbi_fifo_enqueue(struct sbi_fifo *fifo, void *data);
+void sbi_fifo_init(struct sbi_fifo *fifo, unsigned long entries,
+                  unsigned long entrysize);
+bool sbi_fifo_is_empty(struct sbi_fifo *fifo);
+bool sbi_fifo_is_full(struct sbi_fifo *fifo);
+#endif
index ebee592..137d7f0 100644 (file)
@@ -15,6 +15,7 @@ lib-objs-y += riscv_locks.o
 lib-objs-y += sbi_console.o
 lib-objs-y += sbi_ecall.o
 lib-objs-y += sbi_emulate_csr.o
+lib-objs-y += sbi_fifo.o
 lib-objs-y += sbi_hart.o
 lib-objs-y += sbi_illegal_insn.o
 lib-objs-y += sbi_init.o
@@ -23,3 +24,6 @@ lib-objs-y += sbi_misaligned_ldst.o
 lib-objs-y += sbi_system.o
 lib-objs-y += sbi_timer.o
 lib-objs-y += sbi_trap.o
+
+# External Libraries to include
+PLATFORM_INCLUDE_LIBC=y
diff --git a/lib/sbi_fifo.c b/lib/sbi_fifo.c
new file mode 100644 (file)
index 0000000..9d9a5b9
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2019 Western Digital Corporation or its affiliates.
+ *
+ * Authors:
+ *   Atish Patra<atish.patra@wdc.com>
+ *
+ */
+#include <sbi/riscv_locks.h>
+#include <sbi/sbi_fifo.h>
+#include <plat/string.h>
+
+void sbi_fifo_init(struct sbi_fifo *fifo, unsigned long entries,
+                  unsigned long size)
+{
+       fifo->head = -1;
+       fifo->tail = -1;
+       fifo->num_entries = entries;
+       fifo->entrysize = size;
+       SPIN_LOCK_INIT(&fifo->qlock);
+       memset(fifo->queue, 0, entries * size);
+}
+
+bool sbi_fifo_is_full(struct sbi_fifo *fifo)
+{
+       if (((fifo->head == fifo->num_entries-1) && fifo->tail == 0) ||
+            (fifo->tail == fifo->head + 1)) {
+               return TRUE;
+       }
+       return FALSE;
+}
+
+bool sbi_fifo_is_empty(struct sbi_fifo *fifo)
+{
+       if (fifo->head == -1)
+               return TRUE;
+       return FALSE;
+}
+
+int sbi_fifo_enqueue(struct sbi_fifo *fifo, void *data)
+{
+       if (!fifo || !data)
+               return -1;
+       spin_lock(&fifo->qlock);
+       if (sbi_fifo_is_full(fifo)) {
+               spin_unlock(&fifo->qlock);
+               return -1;
+       }
+       if (fifo->tail == -1)
+               fifo->tail = 0;
+       fifo->head = (fifo->head + 1) % fifo->num_entries;
+       memcpy(fifo->queue + fifo->head * fifo->entrysize, data,
+              fifo->entrysize);
+       spin_unlock(&fifo->qlock);
+
+       return 0;
+}
+
+int sbi_fifo_dequeue(struct sbi_fifo *fifo, void *data)
+{
+       if (!fifo || !data)
+               return -1;
+
+       spin_lock(&fifo->qlock);
+       if (sbi_fifo_is_empty(fifo)) {
+               spin_unlock(&fifo->qlock);
+               return -1;
+       }
+       memcpy(data, fifo->queue + fifo->tail * fifo->entrysize,
+              fifo->entrysize);
+
+       if (fifo->tail == fifo->head) {
+               fifo->tail = -1;
+               fifo->head = -1;
+       } else {
+               fifo->tail = (fifo->tail + 1) % fifo->num_entries;
+       }
+       spin_unlock(&fifo->qlock);
+
+       return 0;
+}