aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/tidspbridge/include/dspbridge/ntfy.h
blob: cbc8819c61ccc58bd68adb991dc540d700a1d5fe (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
/*
 * ntfy.h
 *
 * DSP-BIOS Bridge driver support functions for TI OMAP processors.
 *
 * Manage lists of notification events.
 *
 * Copyright (C) 2005-2006 Texas Instruments, Inc.
 *
 * This package is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#ifndef NTFY_
#define NTFY_

#include <dspbridge/host_os.h>
#include <dspbridge/dbdefs.h>
#include <dspbridge/sync.h>

/**
 * ntfy_object - head structure to nofify dspbridge events
 * @head:	List of notify objects
 * @ntfy_lock:	lock for list access.
 *
 */
struct ntfy_object {
	struct raw_notifier_head head;/* List of notifier objects */
	spinlock_t ntfy_lock;	/* For critical sections */
};

/**
 * ntfy_event - structure store specify event to be notified
 * @noti_block:	List of notify objects
 * @event:	event that it respond
 * @type: 	event type (only DSP_SIGNALEVENT supported)
 * @sync_obj:	sync_event used to set the event
 *
 */
struct ntfy_event {
	struct notifier_block noti_block;
	u32 event;	/* Events to be notified about */
	u32 type;	/* Type of notification to be sent */
	struct sync_object sync_obj;
};


/**
 * dsp_notifier_event() - callback function to nofity events
 * @this:		pointer to itself struct notifier_block
 * @event:	event to be notified.
 * @data:		Currently not used.
 *
 */
int dsp_notifier_event(struct notifier_block *this, unsigned long event,
			   void *data);

/**
 * ntfy_init() - Set the initial state of the ntfy_object structure.
 * @no:		pointer to ntfy_object structure.
 *
 * This function sets the initial state of the ntfy_object in order it
 * can be used by the other ntfy functions.
 */

static inline void ntfy_init(struct ntfy_object *no)
{
	spin_lock_init(&no->ntfy_lock);
	RAW_INIT_NOTIFIER_HEAD(&no->head);
}

/**
 * ntfy_delete() - delete list of nofy events registered.
 * @ntfy_obj:	Pointer to the ntfy object structure.
 *
 * This function is used to remove all the notify events  registered.
 * unregister function is not needed in this function, to unregister
 * a ntfy_event please look at ntfy_register function.
 *
 */
static inline void ntfy_delete(struct ntfy_object *ntfy_obj)
{
	struct ntfy_event *ne;
	struct notifier_block *nb;

	spin_lock_bh(&ntfy_obj->ntfy_lock);
	nb = ntfy_obj->head.head;
	while (nb) {
		ne = container_of(nb, struct ntfy_event, noti_block);
		nb = nb->next;
		kfree(ne);
	}
	spin_unlock_bh(&ntfy_obj->ntfy_lock);
}

/**
 * ntfy_notify() - nofity all event register for an specific event.
 * @ntfy_obj:	Pointer to the ntfy_object structure.
 * @event:	event to be notified.
 *
 * This function traverses all the ntfy events registers and
 * set the event with mach with @event.
 */
static inline void ntfy_notify(struct ntfy_object *ntfy_obj, u32 event)
{
	spin_lock_bh(&ntfy_obj->ntfy_lock);
	raw_notifier_call_chain(&ntfy_obj->head, event, NULL);
	spin_unlock_bh(&ntfy_obj->ntfy_lock);
}



/**
 * ntfy_init() - Create and initialize a ntfy_event structure.
 * @event:	event that the ntfy event will respond
 * @type		event type (only DSP_SIGNALEVENT supported)
 *
 * This function create a ntfy_event element and sets the event it will
 * respond the ntfy_event in order it can be used by the other ntfy functions.
 * In case of success it will return a pointer to the ntfy_event struct
 * created. Otherwise it will return NULL;
 */

static inline struct ntfy_event *ntfy_event_create(u32 event, u32 type)
{
	struct ntfy_event *ne;
	ne = kmalloc(sizeof(struct ntfy_event), GFP_KERNEL);
	if (ne) {
		sync_init_event(&ne->sync_obj);
		ne->noti_block.notifier_call = dsp_notifier_event;
		ne->event = event;
		ne->type = type;
	}
	return ne;
}

/**
 * ntfy_register() - register new ntfy_event into a given ntfy_object
 * @ntfy_obj:	Pointer to the ntfy_object structure.
 * @noti:		Pointer to the handle to be returned to the user space.
 * @event	event that the ntfy event will respond
 * @type		event type (only DSP_SIGNALEVENT supported)
 *
 * This function register a new ntfy_event into the ntfy_object list,
 * which will respond to the @event passed.
 * This function will return 0 in case of error.
 * -EFAULT in case of bad pointers and
 * DSP_EMemory in case of no memory to create ntfy_event.
 */
static  inline int ntfy_register(struct ntfy_object *ntfy_obj,
			 struct dsp_notification *noti,
			 u32 event, u32 type)
{
	struct ntfy_event *ne;
	int status = 0;

	if (!noti || !ntfy_obj) {
		status = -EFAULT;
		goto func_end;
	}
	if (!event) {
		status = -EINVAL;
		goto func_end;
	}
	ne = ntfy_event_create(event, type);
	if (!ne) {
		status = -ENOMEM;
		goto func_end;
	}
	noti->handle = &ne->sync_obj;

	spin_lock_bh(&ntfy_obj->ntfy_lock);
	raw_notifier_chain_register(&ntfy_obj->head, &ne->noti_block);
	spin_unlock_bh(&ntfy_obj->ntfy_lock);
func_end:
	return status;
}

/**
 * ntfy_unregister() - unregister a ntfy_event from a given ntfy_object
 * @ntfy_obj:	Pointer to the ntfy_object structure.
 * @noti:		Pointer to the event that will be removed.
 *
 * This function unregister a ntfy_event from the ntfy_object list,
 * @noti contains the event which is wanted to be removed.
 * This function will return 0 in case of error.
 * -EFAULT in case of bad pointers and
 * DSP_EMemory in case of no memory to create ntfy_event.
 */
static  inline int ntfy_unregister(struct ntfy_object *ntfy_obj,
			 struct dsp_notification *noti)
{
	int status = 0;
	struct ntfy_event *ne;

	if (!noti || !ntfy_obj) {
		status = -EFAULT;
		goto func_end;
	}

	ne = container_of((struct sync_object *)noti, struct ntfy_event,
								sync_obj);
	spin_lock_bh(&ntfy_obj->ntfy_lock);
	raw_notifier_chain_unregister(&ntfy_obj->head,
						&ne->noti_block);
	kfree(ne);
	spin_unlock_bh(&ntfy_obj->ntfy_lock);
func_end:
	return status;
}

#endif				/* NTFY_ */