Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C), 2025, Wuxi Stars Micro System Technologies Co., Ltd.
3 : : */
4 : :
5 : : #include <sys/types.h>
6 : : #include <sys/stat.h>
7 : : #include <fcntl.h>
8 : : #include <sys/ioctl.h>
9 : : #include <sys/mman.h>
10 : : #include <unistd.h>
11 : : #include <inttypes.h>
12 : : #include <rte_version.h>
13 : : #include <eal_export.h>
14 : :
15 : : #include "sxe2_osal.h"
16 : : #include "sxe2_common_log.h"
17 : : #include "sxe2_ioctl_chnl.h"
18 : : #include "sxe2_ioctl_chnl_func.h"
19 : :
20 : : #define SXE2_CHR_DEV_NAME "/dev/sxe2-dpdk-"
21 : :
22 : : RTE_EXPORT_INTERNAL_SYMBOL(sxe2_drv_cmd_close)
23 : : void
24 : 0 : sxe2_drv_cmd_close(struct sxe2_common_device *cdev)
25 : : {
26 : 0 : cdev->config.kernel_reset = true;
27 : 0 : }
28 : :
29 : : RTE_EXPORT_INTERNAL_SYMBOL(sxe2_drv_cmd_exec)
30 : : int32_t
31 : 0 : sxe2_drv_cmd_exec(struct sxe2_common_device *cdev,
32 : : struct sxe2_drv_cmd_params *cmd_params)
33 : : {
34 : : int32_t cmd_fd;
35 : : int32_t ret = -EIO;
36 : :
37 [ # # ]: 0 : if (cdev->config.kernel_reset) {
38 : : ret = -EPERM;
39 : 0 : PMD_LOG_WARN(COM, "kernel reset, need restart app.");
40 : 0 : goto l_end;
41 : : }
42 : :
43 : 0 : cmd_fd = SXE2_CDEV_TO_CMD_FD(cdev);
44 [ # # ]: 0 : if (cmd_fd < 0) {
45 : : ret = -EBADF;
46 : 0 : PMD_LOG_ERR(COM, "Fail to exec cmd, fd[%d] error", cmd_fd);
47 : 0 : goto l_end;
48 : : }
49 : :
50 : 0 : PMD_LOG_DEBUG(COM, "Exec drv cmd fd[%d] trace_id[0x%"PRIx64"]"
51 : : "opcode[0x%x] req_len[%d] resp_len[%d]",
52 : : cmd_fd, cmd_params->trace_id, cmd_params->opcode,
53 : : cmd_params->req_len, cmd_params->resp_len);
54 : :
55 : 0 : pthread_mutex_lock(&cdev->config.lock);
56 : 0 : ret = ioctl(cmd_fd, SXE2_COM_CMD_PASSTHROUGH, cmd_params);
57 [ # # ]: 0 : if (ret < 0) {
58 : 0 : PMD_LOG_ERR(COM, "Fail to exec cmd, fd[%d] opcode[0x%x] ret[%d], err:%s",
59 : : cmd_fd, cmd_params->opcode, ret, strerror(errno));
60 : 0 : ret = -errno;
61 : 0 : pthread_mutex_unlock(&cdev->config.lock);
62 : 0 : goto l_end;
63 : : }
64 : 0 : pthread_mutex_unlock(&cdev->config.lock);
65 : :
66 : 0 : l_end:
67 : 0 : return ret;
68 : : }
69 : :
70 : :
71 : : RTE_EXPORT_INTERNAL_SYMBOL(sxe2_drv_dev_open)
72 : : int32_t
73 : 0 : sxe2_drv_dev_open(struct sxe2_common_device *cdev, struct rte_pci_device *pci_dev)
74 : : {
75 : : int32_t ret = 0;
76 : : int32_t fd = 0;
77 : 0 : char drv_name[32] = {0};
78 : :
79 : 0 : snprintf(drv_name, sizeof(drv_name),
80 : : "%s%04"PRIx32":%02"PRIx8":%02"PRIx8".%"PRIx8,
81 : : SXE2_CHR_DEV_NAME,
82 : : pci_dev->addr.domain,
83 : 0 : pci_dev->addr.bus,
84 : 0 : pci_dev->addr.devid,
85 : 0 : pci_dev->addr.function);
86 : :
87 : : fd = open(drv_name, O_RDWR);
88 [ # # ]: 0 : if (fd < 0) {
89 : : ret = -EBADF;
90 : 0 : PMD_LOG_ERR(COM, "Fail to open device:%s, ret=%d, err:%s",
91 : : drv_name, ret, strerror(errno));
92 : 0 : goto l_end;
93 : : }
94 : :
95 : 0 : SXE2_CDEV_TO_CMD_FD(cdev) = fd;
96 : :
97 : 0 : PMD_LOG_INFO(COM, "Successfully opened device:%s, fd=%d",
98 : : drv_name, SXE2_CDEV_TO_CMD_FD(cdev));
99 : :
100 : 0 : l_end:
101 : 0 : return ret;
102 : : }
103 : :
104 : : RTE_EXPORT_INTERNAL_SYMBOL(sxe2_drv_dev_close)
105 : : void
106 : 0 : sxe2_drv_dev_close(struct sxe2_common_device *cdev)
107 : : {
108 : 0 : int32_t fd = SXE2_CDEV_TO_CMD_FD(cdev);
109 : :
110 [ # # ]: 0 : if (fd >= 0) {
111 : 0 : close(fd);
112 : 0 : PMD_LOG_INFO(COM, "closed device fd=%d", fd);
113 : : }
114 : :
115 : 0 : SXE2_CDEV_TO_CMD_FD(cdev) = SXE2_CMD_FD_INVALID;
116 : 0 : }
117 : :
118 : : RTE_EXPORT_INTERNAL_SYMBOL(sxe2_drv_dev_handshake)
119 : : int32_t
120 : 0 : sxe2_drv_dev_handshake(struct sxe2_common_device *cdev)
121 : : {
122 : : int32_t ret = 0;
123 : : int32_t cmd_fd = 0;
124 : : struct sxe2_ioctl_cmd_common_hdr cmd_params;
125 : :
126 [ # # ]: 0 : if (cdev->config.kernel_reset) {
127 : : ret = -EPERM;
128 : 0 : PMD_LOG_WARN(COM, "kernel reset, need restart app.");
129 : 0 : goto l_end;
130 : : }
131 : :
132 : 0 : cmd_fd = SXE2_CDEV_TO_CMD_FD(cdev);
133 [ # # ]: 0 : if (cmd_fd < 0) {
134 : : ret = -EBADF;
135 : 0 : PMD_LOG_ERR(COM, "Failed to exec cmd, fd=%d", cmd_fd);
136 : 0 : goto l_end;
137 : : }
138 : :
139 : 0 : PMD_LOG_DEBUG(COM, "Open fd=%d to handshake with kernel", cmd_fd);
140 : :
141 : : memset(&cmd_params, 0, sizeof(struct sxe2_ioctl_cmd_common_hdr));
142 : 0 : cmd_params.dpdk_ver = SXE2_COM_VER;
143 : 0 : cmd_params.msg_len = sizeof(struct sxe2_ioctl_cmd_common_hdr);
144 : :
145 : 0 : pthread_mutex_lock(&cdev->config.lock);
146 : 0 : ret = ioctl(cmd_fd, SXE2_COM_CMD_HANDSHAKE, &cmd_params);
147 [ # # ]: 0 : if (ret < 0) {
148 : 0 : PMD_LOG_ERR(COM, "Failed to handshake, fd=%d, ret=%d, err:%s",
149 : : cmd_fd, ret, strerror(errno));
150 : : ret = -EIO;
151 : 0 : pthread_mutex_unlock(&cdev->config.lock);
152 : 0 : goto l_end;
153 : : }
154 : 0 : pthread_mutex_unlock(&cdev->config.lock);
155 : :
156 [ # # ]: 0 : if (cmd_params.cap & RTE_BIT32(SXE2_COM_CAP_IOMMU_MAP))
157 : 0 : cdev->config.support_iommu = true;
158 : : else
159 : 0 : cdev->config.support_iommu = false;
160 : :
161 : 0 : l_end:
162 : 0 : return ret;
163 : : }
164 : :
165 : : RTE_EXPORT_INTERNAL_SYMBOL(sxe2_drv_dev_rxq_irq_set)
166 : : int32_t
167 : 0 : sxe2_drv_dev_rxq_irq_set(struct sxe2_common_device *cdev,
168 : : uint16_t base_irq, int32_t *efd, uint16_t nb_irq)
169 : : {
170 : : struct sxe2_ioctl_irq_set cmd_params;
171 : : int32_t ret = 0;
172 : : int32_t cmd_fd = 0;
173 : :
174 [ # # ]: 0 : if (cdev->config.kernel_reset) {
175 : : ret = -EPERM;
176 : 0 : PMD_LOG_WARN(COM, "kernel reset, need restart app.");
177 : 0 : goto l_end;
178 : : }
179 : :
180 : 0 : cmd_fd = SXE2_CDEV_TO_CMD_FD(cdev);
181 [ # # ]: 0 : if (cmd_fd < 0) {
182 : : ret = -EBADF;
183 : 0 : PMD_LOG_ERR(COM, "Failed to exec cmd, fd=%d", cmd_fd);
184 : 0 : goto l_end;
185 : : }
186 : :
187 : 0 : PMD_LOG_DEBUG(COM, "Open fd=%d to set rxq irq, base_queue=%d, efds=%p, nb_irq=%d",
188 : : cmd_fd, base_irq, efd, nb_irq);
189 : :
190 : : memset(&cmd_params, 0, sizeof(struct sxe2_ioctl_irq_set));
191 : 0 : cmd_params.base_irq_in_com = base_irq;
192 : 0 : cmd_params.cnt = nb_irq;
193 : 0 : cmd_params.event_fd = efd;
194 : :
195 : 0 : pthread_mutex_lock(&cdev->config.lock);
196 : 0 : ret = ioctl(cmd_fd, SXE2_COM_CMD_IO_IRQS_REQ, &cmd_params);
197 [ # # ]: 0 : if (ret < 0) {
198 : 0 : PMD_LOG_ERR(COM, "Failed to set io irqs, fd=%d, ret=%d, err:%s",
199 : : cmd_fd, ret, strerror(errno));
200 : 0 : pthread_mutex_unlock(&cdev->config.lock);
201 : 0 : goto l_end;
202 : : }
203 : 0 : pthread_mutex_unlock(&cdev->config.lock);
204 : :
205 : 0 : l_end:
206 : 0 : return ret;
207 : : }
208 : :
209 : : RTE_EXPORT_INTERNAL_SYMBOL(sxe2_drv_dev_other_irq_set)
210 : : int32_t
211 : 0 : sxe2_drv_dev_other_irq_set(struct sxe2_common_device *cdev,
212 : : int32_t efd, uint64_t event)
213 : : {
214 : : int32_t ret = 0;
215 : : int32_t cmd_fd = 0;
216 : : struct sxe2_ioctl_other_evt_set cmd_params;
217 : :
218 [ # # ]: 0 : if (cdev->config.kernel_reset) {
219 : : ret = -EPERM;
220 : 0 : PMD_LOG_WARN(COM, "kernel reset, need restart app.");
221 : 0 : goto l_end;
222 : : }
223 : :
224 : 0 : cmd_fd = SXE2_CDEV_TO_CMD_FD(cdev);
225 [ # # ]: 0 : if (cmd_fd < 0) {
226 : : ret = -EBADF;
227 : 0 : PMD_LOG_ERR(COM, "Failed to exec cmd, fd=%d", cmd_fd);
228 : 0 : goto l_end;
229 : : }
230 : :
231 : 0 : PMD_LOG_DEBUG(COM, "Open fd=%d to set other irq, efd=%d, event=%"PRIu64"",
232 : : cmd_fd, efd, event);
233 : :
234 : : memset(&cmd_params, 0, sizeof(struct sxe2_ioctl_other_evt_set));
235 : 0 : cmd_params.eventfd = efd;
236 : 0 : cmd_params.filter_table = event;
237 : :
238 : 0 : pthread_mutex_lock(&cdev->config.lock);
239 : 0 : ret = ioctl(cmd_fd, SXE2_COM_CMD_EVT_IRQ_REQ, &cmd_params);
240 [ # # ]: 0 : if (ret < 0) {
241 : 0 : PMD_LOG_ERR(COM, "Failed to set others evt, fd=%d, ret=%d, err:%s",
242 : : cmd_fd, ret, strerror(errno));
243 : : ret = -EIO;
244 : 0 : pthread_mutex_unlock(&cdev->config.lock);
245 : 0 : goto l_end;
246 : : }
247 : 0 : pthread_mutex_unlock(&cdev->config.lock);
248 : :
249 : 0 : l_end:
250 : 0 : return ret;
251 : : }
252 : :
253 : : RTE_EXPORT_INTERNAL_SYMBOL(sxe2_drv_dev_other_irq_get)
254 : : int32_t
255 : 0 : sxe2_drv_dev_other_irq_get(struct sxe2_common_device *cdev, uint64_t *event)
256 : : {
257 : : int32_t ret = 0;
258 : : int32_t cmd_fd = 0;
259 : : struct sxe2_ioctl_other_evt_get cmd_params;
260 : :
261 [ # # ]: 0 : if (cdev->config.kernel_reset) {
262 : : ret = -EPERM;
263 : 0 : PMD_LOG_WARN(COM, "kernel reset, need restart app.");
264 : 0 : goto l_end;
265 : : }
266 : :
267 : 0 : cmd_fd = SXE2_CDEV_TO_CMD_FD(cdev);
268 [ # # ]: 0 : if (cmd_fd < 0) {
269 : : ret = -EBADF;
270 : 0 : PMD_LOG_ERR(COM, "Failed to exec cmd, fd=%d", cmd_fd);
271 : 0 : goto l_end;
272 : : }
273 : :
274 : 0 : PMD_LOG_DEBUG(COM, "Open fd=%d to get other irq", cmd_fd);
275 : :
276 : : memset(&cmd_params, 0, sizeof(struct sxe2_ioctl_other_evt_get));
277 : :
278 : 0 : pthread_mutex_lock(&cdev->config.lock);
279 : 0 : ret = ioctl(cmd_fd, SXE2_COM_CMD_EVT_CAUSE_GET, &cmd_params);
280 [ # # ]: 0 : if (ret < 0) {
281 : 0 : PMD_LOG_ERR(COM, "Failed to set others evt, fd=%d, ret=%d, err:%s",
282 : : cmd_fd, ret, strerror(errno));
283 : : ret = -EIO;
284 : 0 : pthread_mutex_unlock(&cdev->config.lock);
285 : 0 : goto l_end;
286 : : }
287 : 0 : pthread_mutex_unlock(&cdev->config.lock);
288 : 0 : *event = cmd_params.evt_cause;
289 : :
290 : 0 : l_end:
291 : 0 : return ret;
292 : : }
293 : :
294 : : RTE_EXPORT_INTERNAL_SYMBOL(sxe2_drv_dev_reset_irq_set)
295 : : int32_t
296 : 0 : sxe2_drv_dev_reset_irq_set(struct sxe2_common_device *cdev, int32_t efd)
297 : : {
298 : : int32_t ret = 0;
299 : : int32_t cmd_fd = 0;
300 : : struct sxe2_ioctl_reset_sub_set cmd_params;
301 : :
302 [ # # ]: 0 : if (cdev->config.kernel_reset) {
303 : : ret = -EPERM;
304 : 0 : PMD_LOG_WARN(COM, "kernel reset, need restart app.");
305 : 0 : goto l_end;
306 : : }
307 : :
308 : 0 : cmd_fd = SXE2_CDEV_TO_CMD_FD(cdev);
309 [ # # ]: 0 : if (cmd_fd < 0) {
310 : : ret = -EBADF;
311 : 0 : PMD_LOG_ERR(COM, "Failed to exec cmd, fd=%d", cmd_fd);
312 : 0 : goto l_end;
313 : : }
314 : :
315 : 0 : PMD_LOG_DEBUG(COM, "Open fd=%d to set reset irq, efd=%d",
316 : : cmd_fd, efd);
317 : :
318 : : memset(&cmd_params, 0, sizeof(struct sxe2_ioctl_reset_sub_set));
319 : 0 : cmd_params.eventfd = efd;
320 : :
321 : 0 : pthread_mutex_lock(&cdev->config.lock);
322 : 0 : ret = ioctl(cmd_fd, SXE2_COM_CMD_RST_IRQ_REQ, &cmd_params);
323 [ # # ]: 0 : if (ret < 0) {
324 : 0 : PMD_LOG_ERR(COM, "Failed to set reset irqs, fd=%d, ret=%d, err:%s",
325 : : cmd_fd, ret, strerror(errno));
326 : : ret = -EIO;
327 : 0 : pthread_mutex_unlock(&cdev->config.lock);
328 : 0 : goto l_end;
329 : : }
330 : 0 : pthread_mutex_unlock(&cdev->config.lock);
331 : :
332 : 0 : l_end:
333 : 0 : return ret;
334 : : }
335 : :
336 : : RTE_EXPORT_INTERNAL_SYMBOL(sxe2_drv_dev_mmap)
337 : : void
338 : 0 : *sxe2_drv_dev_mmap(struct sxe2_common_device *cdev, uint8_t bar_idx, uint64_t len, uint64_t offset)
339 : : {
340 : : int32_t cmd_fd = 0;
341 : : void *virt = NULL;
342 : :
343 [ # # ]: 0 : if (cdev->config.kernel_reset) {
344 : 0 : PMD_LOG_WARN(COM, "kernel reset, need restart app.");
345 : 0 : goto l_err;
346 : : }
347 : :
348 : 0 : cmd_fd = SXE2_CDEV_TO_CMD_FD(cdev);
349 [ # # ]: 0 : if (cmd_fd < 0) {
350 : 0 : PMD_LOG_ERR(COM, "Failed to exec cmd, fd=%d", cmd_fd);
351 : 0 : goto l_err;
352 : : }
353 : :
354 : 0 : PMD_LOG_DEBUG(COM, "fd=%d, bar idx=%d, len=%"PRIu64", "
355 : : "offset=0x%"PRIx64", pci_offset=0x%"PRIx64"",
356 : : cmd_fd, bar_idx, len, offset, SXE2_COM_PCI_OFFSET_GEN(bar_idx, offset));
357 : :
358 : 0 : virt = mmap(NULL, len, PROT_READ | PROT_WRITE,
359 : : MAP_SHARED, cmd_fd, SXE2_COM_PCI_OFFSET_GEN(bar_idx, offset));
360 [ # # ]: 0 : if (virt == MAP_FAILED) {
361 : 0 : PMD_LOG_ERR(COM, "Failed mmap, cmd_fd=%d, len=%"PRIu64", offset=0x%"PRIx64", err:%s",
362 : : cmd_fd, len, offset, strerror(errno));
363 : 0 : goto l_err;
364 : : }
365 : :
366 : : return virt;
367 : : l_err:
368 : : return NULL;
369 : : }
370 : :
371 : : RTE_EXPORT_INTERNAL_SYMBOL(sxe2_drv_dev_munmap)
372 : : int32_t
373 : 0 : sxe2_drv_dev_munmap(struct sxe2_common_device *cdev __rte_unused, void *virt, uint64_t len)
374 : : {
375 : : int32_t ret = 0;
376 : :
377 : 0 : PMD_LOG_DEBUG(COM, "Munmap virt=%p, len=0x%"PRIx64"",
378 : : virt, len);
379 : :
380 : 0 : ret = munmap(virt, len);
381 [ # # ]: 0 : if (ret < 0) {
382 : 0 : PMD_LOG_ERR(COM, "Failed to munmap, virt=%p, len=%"PRIu64", err:%s",
383 : : virt, len, strerror(errno));
384 : 0 : ret = -errno;
385 : 0 : goto l_end;
386 : : }
387 : :
388 : 0 : l_end:
389 : 0 : return ret;
390 : : }
391 : :
392 : : RTE_EXPORT_INTERNAL_SYMBOL(sxe2_drv_dev_dma_map)
393 : : int32_t
394 : 0 : sxe2_drv_dev_dma_map(struct sxe2_common_device *cdev, uint64_t vaddr,
395 : : uint64_t iova, uint64_t size)
396 : : {
397 : : struct sxe2_ioctl_iommu_dma_map cmd_params;
398 : : enum rte_iova_mode iova_mode;
399 : : int32_t ret = 0;
400 : : int32_t cmd_fd = 0;
401 : :
402 [ # # ]: 0 : if (cdev->config.kernel_reset) {
403 : : ret = -EPERM;
404 : 0 : PMD_LOG_WARN(COM, "kernel reset, need restart app.");
405 : 0 : goto l_end;
406 : : }
407 : :
408 : 0 : iova_mode = rte_eal_iova_mode();
409 [ # # ]: 0 : if (iova_mode == RTE_IOVA_PA) {
410 [ # # ]: 0 : if (cdev->config.support_iommu) {
411 : 0 : PMD_LOG_ERR(COM, "iommu not support pa mode");
412 : : ret = -EIO;
413 : : }
414 : 0 : goto l_end;
415 [ # # ]: 0 : } else if (iova_mode == RTE_IOVA_VA) {
416 [ # # ]: 0 : if (!cdev->config.support_iommu) {
417 : 0 : PMD_LOG_ERR(COM, "no iommu not support va mode, please use pa mode.");
418 : : ret = -EIO;
419 : 0 : goto l_end;
420 : : }
421 : : }
422 : :
423 : 0 : cmd_fd = SXE2_CDEV_TO_CMD_FD(cdev);
424 [ # # ]: 0 : if (cmd_fd < 0) {
425 : : ret = -EBADF;
426 : 0 : PMD_LOG_ERR(COM, "Failed to exec cmd, fd=%d", cmd_fd);
427 : 0 : goto l_end;
428 : : }
429 : :
430 : : memset(&cmd_params, 0, sizeof(struct sxe2_ioctl_iommu_dma_map));
431 : 0 : cmd_params.vaddr = vaddr;
432 : 0 : cmd_params.iova = iova;
433 : 0 : cmd_params.size = size;
434 : :
435 : 0 : pthread_mutex_lock(&cdev->config.lock);
436 : 0 : ret = ioctl(cmd_fd, SXE2_COM_CMD_DMA_MAP, &cmd_params);
437 [ # # ]: 0 : if (ret < 0) {
438 : 0 : PMD_LOG_ERR(COM, "Failed to dma map, fd=%d, ret=%d, err:%s",
439 : : cmd_fd, ret, strerror(errno));
440 : : ret = -EIO;
441 : 0 : pthread_mutex_unlock(&cdev->config.lock);
442 : 0 : goto l_end;
443 : : }
444 : 0 : pthread_mutex_unlock(&cdev->config.lock);
445 : :
446 : 0 : l_end:
447 : 0 : return ret;
448 : : }
449 : :
450 : : RTE_EXPORT_INTERNAL_SYMBOL(sxe2_drv_dev_dma_unmap)
451 : : int32_t
452 : 0 : sxe2_drv_dev_dma_unmap(struct sxe2_common_device *cdev, uint64_t iova)
453 : : {
454 : : int32_t ret = 0;
455 : : int32_t cmd_fd = 0;
456 : : struct sxe2_ioctl_iommu_dma_unmap cmd_params;
457 : :
458 [ # # ]: 0 : if (cdev->config.kernel_reset) {
459 : : ret = -EPERM;
460 : 0 : PMD_LOG_WARN(COM, "kernel reset, need restart app.");
461 : 0 : goto l_end;
462 : : }
463 : :
464 [ # # ]: 0 : if (!cdev->config.support_iommu)
465 : 0 : goto l_end;
466 : :
467 : 0 : cmd_fd = SXE2_CDEV_TO_CMD_FD(cdev);
468 [ # # ]: 0 : if (cmd_fd < 0) {
469 : : ret = -EBADF;
470 : 0 : PMD_LOG_ERR(COM, "Failed to exec cmd, fd=%d", cmd_fd);
471 : 0 : goto l_end;
472 : : }
473 : :
474 : 0 : PMD_LOG_DEBUG(COM, "fd %d dma unmap iova=0x%"PRIX64"",
475 : : cmd_fd, iova);
476 : :
477 : : memset(&cmd_params, 0, sizeof(struct sxe2_ioctl_iommu_dma_unmap));
478 : 0 : cmd_params.iova = iova;
479 : :
480 : 0 : pthread_mutex_lock(&cdev->config.lock);
481 : 0 : ret = ioctl(cmd_fd, SXE2_COM_CMD_DMA_UNMAP, &cmd_params);
482 [ # # ]: 0 : if (ret < 0) {
483 : 0 : PMD_LOG_ERR(COM, "Failed to dma unmap, fd=%d, ret=%d, err:%s",
484 : : cmd_fd, ret, strerror(errno));
485 : : ret = -EIO;
486 : 0 : pthread_mutex_unlock(&cdev->config.lock);
487 : 0 : goto l_end;
488 : : }
489 : 0 : pthread_mutex_unlock(&cdev->config.lock);
490 : :
491 : 0 : l_end:
492 : 0 : return ret;
493 : : }
|