summaryrefslogtreecommitdiff
path: root/drivers/mxc/security/sahara2/sah_queue.c
blob: 0f3e56e4c2548b7191bcfe0ecdc28c804f5fe202 (plain)
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
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
/*
 * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
 */

/*
 * The code contained herein is licensed under the GNU General Public
 * License. You may obtain a copy of the GNU General Public License
 * Version 2 or later at the following locations:
 *
 * http://www.opensource.org/licenses/gpl-license.html
 * http://www.gnu.org/copyleft/gpl.html
 */

/*!
* @file sah_queue.c
*
* @brief This file provides a FIFO Queue implementation.
*
*/
/******************************************************************************
*
* CAUTION:
*******************************************************************
*/

/* SAHARA Includes */
#include <sah_queue_manager.h>
#ifdef DIAG_DRV_QUEUE
#include <diagnostic.h>
#endif

/******************************************************************************
* Queue Functions
******************************************************************************/

/*!
*******************************************************************************
* This function constructs a new sah_Queue.
*
* @brief     sah_Queue Constructor
*
* @return   A pointer to a newly allocated sah_Queue.
* @return   NULL if allocation of memory failed.
*/
/******************************************************************************
*
* CAUTION:  This function may sleep in low-memory situations, as it uses
*           kmalloc ( ..., GFP_KERNEL).
******************************************************************************/
sah_Queue *sah_Queue_Construct(void)
{
	sah_Queue *q = (sah_Queue *) os_alloc_memory(sizeof(sah_Queue),
						     GFP_KERNEL);

	if (q != NULL) {
		/* Initialise the queue to an empty state. */
		q->head = NULL;
		q->tail = NULL;
		q->count = 0;
	}
#ifdef DIAG_DRV_QUEUE
	else {
		LOG_KDIAG("kmalloc() failed.");
	}
#endif

	return q;
}

/*!
*******************************************************************************
* This function destroys a sah_Queue.
*
* @brief     sah_Queue Destructor
*
* @param    q    A pointer to a sah_Queue.
*
* @return   void
*/
/******************************************************************************
*
* CAUTION:  This function does not free any queue entries.
*
******************************************************************************/
void sah_Queue_Destroy(sah_Queue * q)
{
#ifdef DIAG_DRV_QUEUE
	if (q == NULL) {
		LOG_KDIAG("Trying to kfree() a NULL pointer.");
	} else {
		if (q->count != 0) {
			LOG_KDIAG
			    ("Trying to destroy a queue that is not empty.");
		}
	}
#endif

	if (q != NULL) {
		os_free_memory(q);
		q = NULL;
	}
}

/*!
*******************************************************************************
* This function appends a sah_Head_Desc to the tail of a sah_Queue.
*
* @brief     Appends a sah_Head_Desc to a sah_Queue.
*
* @param    q       A pointer to a sah_Queue to append to.
* @param    entry   A pointer to a sah_Head_Desc to append.
*
* @pre   The #desc_queue_lock must be held before calling this function.
*
* @return   void
*/
/******************************************************************************
*
* CAUTION: NONE
******************************************************************************/
void sah_Queue_Append_Entry(sah_Queue * q, sah_Head_Desc * entry)
{
	sah_Head_Desc *tail_entry = NULL;

	if ((q == NULL) || (entry == NULL)) {
#ifdef DIAG_DRV_QUEUE
		LOG_KDIAG("Null pointer input.");
#endif
		return;
	}

	if (q->count == 0) {
		/* The queue is empty */
		q->head = entry;
		q->tail = entry;
		entry->next = NULL;
		entry->prev = NULL;
	} else {
		/* The queue is not empty */
		tail_entry = q->tail;
		tail_entry->next = entry;
		entry->next = NULL;
		entry->prev = tail_entry;
		q->tail = entry;
	}
	q->count++;
}

/*!
*******************************************************************************
* This function a removes a sah_Head_Desc from the head of a sah_Queue.
*
* @brief     Removes a sah_Head_Desc from a the head of a sah_Queue.
*
* @param    q    A pointer to a sah_Queue to remove from.
*
* @pre   The #desc_queue_lock must be held before calling this function.
*
* @return   void
*/
/******************************************************************************
*
* CAUTION:  This does not kfree() the entry.
******************************************************************************/
void sah_Queue_Remove_Entry(sah_Queue * q)
{
	sah_Queue_Remove_Any_Entry(q, q->head);
}

/*!
*******************************************************************************
* This function a removes a sah_Head_Desc from anywhere in a sah_Queue.
*
* @brief     Removes a sah_Head_Desc from anywhere in a sah_Queue.
*
* @param    qq      A pointer to a sah_Queue to remove from.
* @param    entry   A pointer to a sah_Head_Desc to remove.
*
* @pre   The #desc_queue_lock must be held before calling this function.
*
* @return   void
*/
/******************************************************************************
*
* CAUTION:  This does not kfree() the entry. Does not check to see if the entry
*           actually belongs to the queue.
******************************************************************************/
void sah_Queue_Remove_Any_Entry(sah_Queue * q, sah_Head_Desc * entry)
{
	sah_Head_Desc *prev_entry = NULL;
	sah_Head_Desc *next_entry = NULL;

	if ((q == NULL) || (entry == NULL)) {
#if defined DIAG_DRV_QUEUE && defined DIAG_DURING_INTERRUPT
		LOG_KDIAG("Null pointer input.");
#endif
		return;
	}

	if (q->count == 1) {
		/* If q is the only entry in the queue. */
		q->tail = NULL;
		q->head = NULL;
		q->count = 0;
	} else if (q->count > 1) {
		/* There are 2 or more entries in the queue. */

#if defined DIAG_DRV_QUEUE && defined DIAG_DURING_INTERRUPT
		if ((entry->next == NULL) && (entry->prev == NULL)) {
			LOG_KDIAG
			    ("Queue is not empty yet both next and prev pointers"
			     " are NULL");
		}
#endif

		if (entry->next == NULL) {
			/* If this is the end of the queue */
			prev_entry = entry->prev;
			prev_entry->next = NULL;
			q->tail = prev_entry;
		} else if (entry->prev == NULL) {
			/* If this is the head of the queue */
			next_entry = entry->next;
			next_entry->prev = NULL;
			q->head = next_entry;
		} else {
			/* If this is somewhere in the middle of the queue */
			prev_entry = entry->prev;
			next_entry = entry->next;
			prev_entry->next = next_entry;
			next_entry->prev = prev_entry;
		}
		q->count--;
	}
	/*
	 * Otherwise we are removing an entry from an empty queue.
	 * Don't do anything in the product code
	 */
#if defined DIAG_DRV_QUEUE && defined DIAG_DURING_INTERRUPT
	else {
		LOG_KDIAG("Trying to remove an entry from an empty queue.");
	}
#endif

	entry->next = NULL;
	entry->prev = NULL;
}

/* End of sah_queue.c */