11a59d1b8SThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-or-later */
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds * ALSA sequencer Memory Manager
41da177e4SLinus Torvalds * Copyright (c) 1998 by Frank van de Pol <fvdpol@coil.demon.nl>
51da177e4SLinus Torvalds */
61da177e4SLinus Torvalds #ifndef __SND_SEQ_MEMORYMGR_H
71da177e4SLinus Torvalds #define __SND_SEQ_MEMORYMGR_H
81da177e4SLinus Torvalds
91da177e4SLinus Torvalds #include <sound/seq_kernel.h>
101da177e4SLinus Torvalds #include <linux/poll.h>
111da177e4SLinus Torvalds
12fea952e5SClemens Ladisch struct snd_info_buffer;
13fea952e5SClemens Ladisch
14*46397622STakashi Iwai /* aliasing for legacy and UMP event packet handling */
15*46397622STakashi Iwai union __snd_seq_event {
16*46397622STakashi Iwai struct snd_seq_event legacy;
17*46397622STakashi Iwai #if IS_ENABLED(CONFIG_SND_SEQ_UMP)
18*46397622STakashi Iwai struct snd_seq_ump_event ump;
19*46397622STakashi Iwai #endif
20*46397622STakashi Iwai struct {
21*46397622STakashi Iwai struct snd_seq_event event;
22*46397622STakashi Iwai #if IS_ENABLED(CONFIG_SND_SEQ_UMP)
23*46397622STakashi Iwai u32 extra;
24*46397622STakashi Iwai #endif
25*46397622STakashi Iwai } __packed raw;
26*46397622STakashi Iwai };
27*46397622STakashi Iwai
281da177e4SLinus Torvalds /* container for sequencer event (internal use) */
29c7e0b5bfSTakashi Iwai struct snd_seq_event_cell {
30*46397622STakashi Iwai union {
31c7e0b5bfSTakashi Iwai struct snd_seq_event event;
32*46397622STakashi Iwai union __snd_seq_event ump;
33*46397622STakashi Iwai };
34c7e0b5bfSTakashi Iwai struct snd_seq_pool *pool; /* used pool */
35c7e0b5bfSTakashi Iwai struct snd_seq_event_cell *next; /* next cell */
36c7e0b5bfSTakashi Iwai };
371da177e4SLinus Torvalds
38d6e05edcSAndreas Mohr /* design note: the pool is a contiguous block of memory, if we dynamicly
391da177e4SLinus Torvalds want to add additional cells to the pool be better store this in another
401da177e4SLinus Torvalds pool as we need to know the base address of the pool when releasing
411da177e4SLinus Torvalds memory. */
421da177e4SLinus Torvalds
43c7e0b5bfSTakashi Iwai struct snd_seq_pool {
44c7e0b5bfSTakashi Iwai struct snd_seq_event_cell *ptr; /* pointer to first event chunk */
45c7e0b5bfSTakashi Iwai struct snd_seq_event_cell *free; /* pointer to the head of the free list */
461da177e4SLinus Torvalds
471da177e4SLinus Torvalds int total_elements; /* pool size actually allocated */
481da177e4SLinus Torvalds atomic_t counter; /* cells free */
491da177e4SLinus Torvalds
501da177e4SLinus Torvalds int size; /* pool size to be allocated */
511da177e4SLinus Torvalds int room; /* watermark for sleep/wakeup */
521da177e4SLinus Torvalds
531da177e4SLinus Torvalds int closing;
541da177e4SLinus Torvalds
551da177e4SLinus Torvalds /* statistics */
561da177e4SLinus Torvalds int max_used;
571da177e4SLinus Torvalds int event_alloc_nopool;
581da177e4SLinus Torvalds int event_alloc_failures;
591da177e4SLinus Torvalds int event_alloc_success;
601da177e4SLinus Torvalds
611da177e4SLinus Torvalds /* Write locking */
621da177e4SLinus Torvalds wait_queue_head_t output_sleep;
631da177e4SLinus Torvalds
641da177e4SLinus Torvalds /* Pool lock */
651da177e4SLinus Torvalds spinlock_t lock;
661da177e4SLinus Torvalds };
671da177e4SLinus Torvalds
68c7e0b5bfSTakashi Iwai void snd_seq_cell_free(struct snd_seq_event_cell *cell);
691da177e4SLinus Torvalds
70c7e0b5bfSTakashi Iwai int snd_seq_event_dup(struct snd_seq_pool *pool, struct snd_seq_event *event,
717bd80091STakashi Iwai struct snd_seq_event_cell **cellp, int nonblock,
727bd80091STakashi Iwai struct file *file, struct mutex *mutexp);
731da177e4SLinus Torvalds
741da177e4SLinus Torvalds /* return number of unused (free) cells */
snd_seq_unused_cells(struct snd_seq_pool * pool)75c7e0b5bfSTakashi Iwai static inline int snd_seq_unused_cells(struct snd_seq_pool *pool)
761da177e4SLinus Torvalds {
771da177e4SLinus Torvalds return pool ? pool->total_elements - atomic_read(&pool->counter) : 0;
781da177e4SLinus Torvalds }
791da177e4SLinus Torvalds
801da177e4SLinus Torvalds /* return total number of allocated cells */
snd_seq_total_cells(struct snd_seq_pool * pool)81c7e0b5bfSTakashi Iwai static inline int snd_seq_total_cells(struct snd_seq_pool *pool)
821da177e4SLinus Torvalds {
831da177e4SLinus Torvalds return pool ? pool->total_elements : 0;
841da177e4SLinus Torvalds }
851da177e4SLinus Torvalds
861da177e4SLinus Torvalds /* init pool - allocate events */
87c7e0b5bfSTakashi Iwai int snd_seq_pool_init(struct snd_seq_pool *pool);
881da177e4SLinus Torvalds
891da177e4SLinus Torvalds /* done pool - free events */
90c520ff3dSTakashi Iwai void snd_seq_pool_mark_closing(struct snd_seq_pool *pool);
91c7e0b5bfSTakashi Iwai int snd_seq_pool_done(struct snd_seq_pool *pool);
921da177e4SLinus Torvalds
931da177e4SLinus Torvalds /* create pool */
94c7e0b5bfSTakashi Iwai struct snd_seq_pool *snd_seq_pool_new(int poolsize);
951da177e4SLinus Torvalds
961da177e4SLinus Torvalds /* remove pool */
97c7e0b5bfSTakashi Iwai int snd_seq_pool_delete(struct snd_seq_pool **pool);
981da177e4SLinus Torvalds
991da177e4SLinus Torvalds /* polling */
100c7e0b5bfSTakashi Iwai int snd_seq_pool_poll_wait(struct snd_seq_pool *pool, struct file *file, poll_table *wait);
1011da177e4SLinus Torvalds
102fea952e5SClemens Ladisch void snd_seq_info_pool(struct snd_info_buffer *buffer,
103fea952e5SClemens Ladisch struct snd_seq_pool *pool, char *space);
1041da177e4SLinus Torvalds
1051da177e4SLinus Torvalds #endif
106