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