1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /* Copyright(c) 2007-2022 Intel Corporation */
3 /* $FreeBSD$ */
4 #include "qat_utils.h"
5 
6 #include <sys/types.h>
7 #include <sys/lock.h>
8 #include <sys/sema.h>
9 #include <sys/mutex.h>
10 
11 /* Define a 64 bit number */
12 #define QAT_UTILS_MAX_LONG (0x7FFFFFFF)
13 
14 /* Max timeout in MS, used to guard against possible overflow */
15 #define QAT_UTILS_MAX_TIMEOUT_MS (QAT_UTILS_MAX_LONG / hz)
16 
17 CpaStatus
18 qatUtilsSemaphoreInit(struct sema **pSid, uint32_t start_value)
19 {
20 	if (!pSid)
21 		return CPA_STATUS_FAIL;
22 
23 	*pSid = malloc(sizeof(struct sema), M_QAT, M_WAITOK);
24 
25 	sema_init(*pSid, start_value, "qat sema");
26 
27 	return CPA_STATUS_SUCCESS;
28 }
29 
30 /**
31  * DESCRIPTION: If the semaphore is unset, the calling thread is blocked.
32  *         If the semaphore is set, it is taken and control is returned
33  *         to the caller. If the time indicated in 'timeout' is reached,
34  *         the thread will unblock and return an error indication. If the
35  *         timeout is set to 'QAT_UTILS_WAIT_NONE', the thread will never block;
36  *         if it is set to 'QAT_UTILS_WAIT_FOREVER', the thread will block until
37  *         the semaphore is available.
38  *
39  *
40  */
41 
42 CpaStatus
43 qatUtilsSemaphoreWait(struct sema **pSid, int32_t timeout)
44 {
45 
46 	CpaStatus Status = CPA_STATUS_SUCCESS;
47 	unsigned long timeoutTime;
48 
49 	if (!pSid)
50 		return CPA_STATUS_FAIL;
51 	/*
52 	 * Guard against illegal timeout values
53 	 */
54 	if ((timeout < 0) && (timeout != QAT_UTILS_WAIT_FOREVER)) {
55 		QAT_UTILS_LOG(
56 		    "QatUtilsSemaphoreWait(): illegal timeout value\n");
57 		return CPA_STATUS_FAIL;
58 	} else if (timeout > QAT_UTILS_MAX_TIMEOUT_MS) {
59 		QAT_UTILS_LOG(
60 		    "QatUtilsSemaphoreWait(): use a smaller timeout value to avoid overflow.\n");
61 		return CPA_STATUS_FAIL;
62 	}
63 
64 	if (timeout == QAT_UTILS_WAIT_FOREVER) {
65 		sema_wait(*pSid);
66 	} else if (timeout == QAT_UTILS_WAIT_NONE) {
67 		if (sema_trywait(*pSid)) {
68 			Status = CPA_STATUS_FAIL;
69 		}
70 	} else {
71 		/* Convert timeout in milliseconds to HZ */
72 		timeoutTime = timeout * hz / 1000;
73 		if (sema_timedwait(*pSid, timeoutTime)) {
74 			Status = CPA_STATUS_FAIL;
75 		}
76 	} /* End of if */
77 
78 	return Status;
79 }
80 
81 CpaStatus
82 qatUtilsSemaphoreTryWait(struct sema **pSid)
83 {
84 	if (!pSid)
85 		return CPA_STATUS_FAIL;
86 	if (sema_trywait(*pSid)) {
87 		return CPA_STATUS_FAIL;
88 	}
89 	return CPA_STATUS_SUCCESS;
90 }
91 
92 /**
93  *
94  * DESCRIPTION: This function causes the next available thread in the pend queue
95  *              to be unblocked. If no thread is pending on this semaphore, the
96  *              semaphore becomes 'full'.
97  */
98 CpaStatus
99 qatUtilsSemaphorePost(struct sema **pSid)
100 {
101 	if (!pSid)
102 		return CPA_STATUS_FAIL;
103 	sema_post(*pSid);
104 	return CPA_STATUS_SUCCESS;
105 }
106 
107 CpaStatus
108 qatUtilsSemaphoreDestroy(struct sema **pSid)
109 {
110 	if (!pSid)
111 		return CPA_STATUS_FAIL;
112 
113 	sema_destroy(*pSid);
114 	free(*pSid, M_QAT);
115 
116 	return CPA_STATUS_SUCCESS;
117 }
118 
119 /****************************
120  *    Mutex
121  ****************************/
122 
123 CpaStatus
124 qatUtilsMutexInit(struct mtx **pMutex)
125 {
126 	if (!pMutex)
127 		return CPA_STATUS_FAIL;
128 	*pMutex = malloc(sizeof(struct mtx), M_QAT, M_WAITOK);
129 
130 	memset(*pMutex, 0, sizeof(struct mtx));
131 
132 	mtx_init(*pMutex, "qat mtx", NULL, MTX_DEF);
133 	return CPA_STATUS_SUCCESS;
134 }
135 
136 CpaStatus
137 qatUtilsMutexLock(struct mtx **pMutex, int32_t timeout)
138 {
139 	if (!pMutex)
140 		return CPA_STATUS_FAIL;
141 	if (timeout != QAT_UTILS_WAIT_FOREVER) {
142 		QAT_UTILS_LOG("QatUtilsMutexLock(): Illegal timeout value\n");
143 		return CPA_STATUS_FAIL;
144 	}
145 
146 	mtx_lock(*pMutex);
147 	return CPA_STATUS_SUCCESS;
148 }
149 
150 CpaStatus
151 qatUtilsMutexUnlock(struct mtx **pMutex)
152 {
153 	if (!pMutex || !(*pMutex))
154 		return CPA_STATUS_FAIL;
155 	mtx_unlock(*pMutex);
156 	return CPA_STATUS_SUCCESS;
157 }
158 
159 CpaStatus
160 qatUtilsMutexDestroy(struct mtx **pMutex)
161 {
162 	if (!pMutex || !(*pMutex))
163 		return CPA_STATUS_FAIL;
164 	mtx_destroy(*pMutex);
165 	free(*pMutex, M_QAT);
166 	*pMutex = NULL;
167 
168 	return CPA_STATUS_SUCCESS;
169 }
170