xref: /linux/sound/core/seq/seq_memory.h (revision cdd5b5a9761fd66d17586e4f4ba6588c70e640ea)
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