mirror of
https://github.com/Fishwaldo/opensbi.git
synced 2025-07-09 06:28:18 +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;
|
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_dequeue(struct sbi_fifo *fifo, void *data);
|
||||||
int sbi_fifo_enqueue(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,
|
void sbi_fifo_init(struct sbi_fifo *fifo, void *queue_mem,
|
||||||
u16 entries, u16 entry_size);
|
u16 entries, u16 entry_size);
|
||||||
bool sbi_fifo_is_empty(struct sbi_fifo *fifo);
|
bool sbi_fifo_is_empty(struct sbi_fifo *fifo);
|
||||||
bool sbi_fifo_is_full(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
|
#endif
|
||||||
|
|
|
@ -29,6 +29,20 @@ static inline bool __sbi_fifo_is_full(struct sbi_fifo *fifo)
|
||||||
return (fifo->avail == fifo->num_entries) ? TRUE : FALSE;
|
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 sbi_fifo_is_full(struct sbi_fifo *fifo)
|
||||||
{
|
{
|
||||||
bool ret;
|
bool ret;
|
||||||
|
@ -57,6 +71,66 @@ bool sbi_fifo_is_empty(struct sbi_fifo *fifo)
|
||||||
return ret;
|
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)
|
int sbi_fifo_enqueue(struct sbi_fifo *fifo, void *data)
|
||||||
{
|
{
|
||||||
u32 head;
|
u32 head;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue