1/* SPDX-License-Identifier: GPL-2.0-or-later */
2/*
3 *  ALSA sequencer Memory Manager
4 *  Copyright (c) 1998 by Frank van de Pol <fvdpol@coil.demon.nl>
5 */
6#ifndef __SND_SEQ_MEMORYMGR_H
7#define __SND_SEQ_MEMORYMGR_H
8
9#include <sound/seq_kernel.h>
10#include <linux/poll.h>
11
12struct snd_info_buffer;
13
14/* aliasing for legacy and UMP event packet handling */
15union __snd_seq_event {
16	struct snd_seq_event legacy;
17#if IS_ENABLED(CONFIG_SND_SEQ_UMP)
18	struct snd_seq_ump_event ump;
19#endif
20	struct {
21		struct snd_seq_event event;
22#if IS_ENABLED(CONFIG_SND_SEQ_UMP)
23		u32 extra;
24#endif
25	} __packed raw;
26};
27
28/* container for sequencer event (internal use) */
29struct snd_seq_event_cell {
30	union {
31		struct snd_seq_event event;
32		union __snd_seq_event ump;
33	};
34	struct snd_seq_pool *pool;				/* used pool */
35	struct snd_seq_event_cell *next;	/* next cell */
36};
37
38/* design note: the pool is a contiguous block of memory, if we dynamicly
39   want to add additional cells to the pool be better store this in another
40   pool as we need to know the base address of the pool when releasing
41   memory. */
42
43struct snd_seq_pool {
44	struct snd_seq_event_cell *ptr;	/* pointer to first event chunk */
45	struct snd_seq_event_cell *free;	/* pointer to the head of the free list */
46
47	int total_elements;	/* pool size actually allocated */
48	atomic_t counter;	/* cells free */
49
50	int size;		/* pool size to be allocated */
51	int room;		/* watermark for sleep/wakeup */
52
53	int closing;
54
55	/* statistics */
56	int max_used;
57	int event_alloc_nopool;
58	int event_alloc_failures;
59	int event_alloc_success;
60
61	/* Write locking */
62	wait_queue_head_t output_sleep;
63
64	/* Pool lock */
65	spinlock_t lock;
66};
67
68void snd_seq_cell_free(struct snd_seq_event_cell *cell);
69
70int snd_seq_event_dup(struct snd_seq_pool *pool, struct snd_seq_event *event,
71		      struct snd_seq_event_cell **cellp, int nonblock,
72		      struct file *file, struct mutex *mutexp);
73
74/* return number of unused (free) cells */
75static inline int snd_seq_unused_cells(struct snd_seq_pool *pool)
76{
77	return pool ? pool->total_elements - atomic_read(&pool->counter) : 0;
78}
79
80/* return total number of allocated cells */
81static inline int snd_seq_total_cells(struct snd_seq_pool *pool)
82{
83	return pool ? pool->total_elements : 0;
84}
85
86/* init pool - allocate events */
87int snd_seq_pool_init(struct snd_seq_pool *pool);
88
89/* done pool - free events */
90void snd_seq_pool_mark_closing(struct snd_seq_pool *pool);
91int snd_seq_pool_done(struct snd_seq_pool *pool);
92
93/* create pool */
94struct snd_seq_pool *snd_seq_pool_new(int poolsize);
95
96/* remove pool */
97int snd_seq_pool_delete(struct snd_seq_pool **pool);
98
99/* polling */
100int snd_seq_pool_poll_wait(struct snd_seq_pool *pool, struct file *file, poll_table *wait);
101
102void snd_seq_info_pool(struct snd_info_buffer *buffer,
103		       struct snd_seq_pool *pool, char *space);
104
105#endif
106