mirror of
https://github.com/Fishwaldo/opensbi.git
synced 2025-07-08 14:09:23 +00:00
lib: Provide a lock enabled iteration of fifo.
Implement a lock enabled iteration for fifo so that caller can determine if next entry can be skipped or any existing entries in fifo can be updated before enqueue. Signed-off-by: Atish Patra <atish.patra@wdc.com>
This commit is contained in:
parent
54f31e8209
commit
110eef44f0
2 changed files with 84 additions and 0 deletions
|
@ -23,11 +23,21 @@ struct sbi_fifo {
|
|||
u16 tail;
|
||||
};
|
||||
|
||||
enum sbi_fifo_inplace_update_types {
|
||||
SBI_FIFO_SKIP,
|
||||
SBI_FIFO_UPDATED,
|
||||
SBI_FIFO_RESET,
|
||||
SBI_FIFO_UNCHANGED,
|
||||
};
|
||||
|
||||
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, void *queue_mem,
|
||||
u16 entries, u16 entry_size);
|
||||
bool sbi_fifo_is_empty(struct sbi_fifo *fifo);
|
||||
bool sbi_fifo_is_full(struct sbi_fifo *fifo);
|
||||
int sbi_fifo_inplace_update(struct sbi_fifo *fifo, void *in,
|
||||
int (*fptr) (void *in, void *data));
|
||||
u16 sbi_fifo_avail(struct sbi_fifo *fifo);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -29,6 +29,20 @@ static inline bool __sbi_fifo_is_full(struct sbi_fifo *fifo)
|
|||
return (fifo->avail == fifo->num_entries) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
u16 sbi_fifo_avail(struct sbi_fifo *fifo)
|
||||
{
|
||||
u16 ret;
|
||||
|
||||
if (!fifo)
|
||||
return 0;
|
||||
|
||||
spin_lock(&fifo->qlock);
|
||||
ret = fifo->avail;
|
||||
spin_unlock(&fifo->qlock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool sbi_fifo_is_full(struct sbi_fifo *fifo)
|
||||
{
|
||||
bool ret;
|
||||
|
@ -57,6 +71,66 @@ bool sbi_fifo_is_empty(struct sbi_fifo *fifo)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* Note: must be called with fifo->qlock held */
|
||||
static inline void __sbi_fifo_reset(struct sbi_fifo *fifo)
|
||||
{
|
||||
fifo->avail = 0;
|
||||
fifo->tail = 0;
|
||||
memset(fifo->queue, 0, fifo->num_entries * fifo->entry_size);
|
||||
}
|
||||
|
||||
bool sbi_fifo_reset(struct sbi_fifo *fifo)
|
||||
{
|
||||
if (!fifo)
|
||||
return FALSE;
|
||||
|
||||
spin_lock(&fifo->qlock);
|
||||
__sbi_fifo_reset(fifo);
|
||||
spin_unlock(&fifo->qlock);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a helper function to do inplace update to the fifo.
|
||||
* Note: The callback function is called with lock being held.
|
||||
*
|
||||
* **Do not** invoke any other fifo function from callback. Otherwise, it will
|
||||
* lead to deadlock.
|
||||
*/
|
||||
int sbi_fifo_inplace_update(struct sbi_fifo *fifo, void *in,
|
||||
int (*fptr)(void *in, void *data))
|
||||
{
|
||||
int i, index = 0;
|
||||
int ret = SBI_FIFO_UNCHANGED;
|
||||
void *entry;
|
||||
|
||||
if (!fifo || !in )
|
||||
return ret;
|
||||
spin_lock(&fifo->qlock);
|
||||
if (__sbi_fifo_is_empty(fifo)) {
|
||||
spin_unlock(&fifo->qlock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < fifo->avail; i ++) {
|
||||
index = fifo->tail + i;
|
||||
if (index >= fifo->num_entries)
|
||||
index = index - fifo->num_entries;
|
||||
entry = (void *)fifo->queue + (u32) index * fifo->entry_size;
|
||||
ret = fptr(in, entry);
|
||||
if (ret == SBI_FIFO_SKIP || ret == SBI_FIFO_UPDATED) {
|
||||
break;
|
||||
} else if (ret == SBI_FIFO_RESET) {
|
||||
__sbi_fifo_reset(fifo);
|
||||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock(&fifo->qlock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int sbi_fifo_enqueue(struct sbi_fifo *fifo, void *data)
|
||||
{
|
||||
u32 head;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue