• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 HiSilicon (Shanghai) Technologies CO., LIMITED.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17  */
18 
19 #include <linux/module.h>
20 #include <linux/kernel.h>
21 #include <linux/printk.h>
22 #include <linux/fs.h>
23 #include <linux/poll.h>
24 #include <linux/slab.h>
25 #include <linux/vmalloc.h>
26 #include <linux/mm_types.h>
27 #include <linux/mm.h>
28 #include <linux/kmod.h>
29 #include "himedia.h"
30 #include "securec.h"
31 #include "hi_osal.h"
32 
33 #define DRVAL_DEBUG    0
34 
35 #define GET_FILE(file)            \
36     do {                          \
37         if (__get_file(file) < 0) \
38             return -1;            \
39     } while (0)
40 
41 #define PUT_FILE(file)            \
42     do {                          \
43         if (__put_file(file) < 0) \
44             return -1;            \
45     } while (0)
46 
47 typedef struct osal_coat_dev {
48     struct osal_dev osal_dev;
49     struct himedia_device himedia_dev;
50 } osal_coat_dev_t;
51 
52 struct osal_private_data {
53     struct osal_dev *dev;
54     void *data;
55     struct osal_poll table;
56     int f_ref_cnt;
57 };
58 
59 spinlock_t g_f_lock;
60 
osal_device_init(void)61 void osal_device_init(void)
62 {
63     spin_lock_init(&g_f_lock);
64 }
65 
__get_file(struct file * file)66 static int __get_file(struct file *file)
67 {
68     struct osal_private_data *pdata = NULL;
69 
70     spin_lock(&g_f_lock);
71     pdata = file->private_data;
72     if (pdata == NULL) {
73         spin_unlock(&g_f_lock);
74         return -1;
75     }
76 
77     pdata->f_ref_cnt++;
78     spin_unlock(&g_f_lock);
79 
80     return 0;
81 }
82 
__put_file(struct file * file)83 static int __put_file(struct file *file)
84 {
85     struct osal_private_data *pdata = NULL;
86 
87     spin_lock(&g_f_lock);
88     pdata = file->private_data;
89     if (pdata == NULL) {
90         spin_unlock(&g_f_lock);
91         return -1;
92     }
93 
94     pdata->f_ref_cnt--;
95     spin_unlock(&g_f_lock);
96 
97     return 0;
98 }
99 
osal_open(struct inode * inode,struct file * file)100 static int osal_open(struct inode *inode, struct file *file)
101 {
102     struct himedia_device *himedia = NULL;
103     osal_coat_dev_t *coat_dev = NULL;
104     struct osal_private_data *pdata = NULL;
105 
106     osal_unused(inode);
107 
108     himedia = (struct himedia_device *)file->private_data;
109     if (himedia == NULL) {
110         osal_trace("%s - get himedia device error!\n", __FUNCTION__);
111         return -1;
112     }
113     coat_dev = osal_container_of(himedia, struct osal_coat_dev, himedia_dev);
114     pdata = (struct osal_private_data *)kmalloc(sizeof(struct osal_private_data), GFP_KERNEL);
115     if (pdata == NULL) {
116         osal_trace("%s - kmalloc error!\n", __FUNCTION__);
117         return -1;
118     }
119     if (DRVAL_DEBUG) {
120         osal_trace("%s - file->private_data=%pK!\n", __FUNCTION__, pdata);
121     }
122 
123     (void)memset_s(pdata, sizeof(struct osal_private_data), 0, sizeof(struct osal_private_data));
124 
125     file->private_data = pdata;
126     pdata->dev = &(coat_dev->osal_dev);
127     if (coat_dev->osal_dev.fops->open != NULL) {
128         return coat_dev->osal_dev.fops->open((void *)&(pdata->data));
129     }
130     return 0;
131 }
132 
osal_read(struct file * file,char __user * buf,size_t size,loff_t * offset)133 static ssize_t osal_read(struct file *file, char __user *buf, size_t size, loff_t *offset)
134 {
135     struct osal_private_data *pdata = file->private_data;
136     int ret = 0;
137 
138     GET_FILE(file);
139 
140     if (pdata->dev->fops->read != NULL) {
141         ret = pdata->dev->fops->read(buf, (int)size, (long *)offset, (void *)&(pdata->data));
142     }
143 
144     PUT_FILE(file);
145     return ret;
146 }
147 
osal_write(struct file * file,const char __user * buf,size_t size,loff_t * offset)148 static ssize_t osal_write(struct file *file, const char __user *buf, size_t size, loff_t *offset)
149 {
150     struct osal_private_data *pdata = file->private_data;
151     int ret = -1;
152 
153     GET_FILE(file);
154     if (pdata->dev->fops->write != NULL) {
155         ret = pdata->dev->fops->write(buf, (int)size, (long *)offset, (void *)&(pdata->data));
156     }
157     PUT_FILE(file);
158     return ret;
159 }
160 
osal_llseek(struct file * file,loff_t offset,int whence)161 static loff_t osal_llseek(struct file *file, loff_t offset, int whence)
162 {
163     struct osal_private_data *pdata = file->private_data;
164     int ret = 0;
165 
166     GET_FILE(file);
167     if (DRVAL_DEBUG) {
168         osal_trace("%s - file->private_data=%pK!\n", __FUNCTION__, pdata);
169     }
170 
171     if (whence == SEEK_SET) {
172         if (pdata->dev->fops->llseek != NULL) {
173             ret = pdata->dev->fops->llseek((long)offset, OSAL_SEEK_SET, (void *)&(pdata->data));
174         }
175     } else if (whence == SEEK_CUR) {
176         if (pdata->dev->fops->llseek != NULL) {
177             ret = pdata->dev->fops->llseek((long)offset, OSAL_SEEK_CUR, (void *)&(pdata->data));
178         }
179     } else if (whence == SEEK_END) {
180         if (pdata->dev->fops->llseek != NULL) {
181             ret = pdata->dev->fops->llseek((long)offset, OSAL_SEEK_END, (void *)&(pdata->data));
182         }
183     }
184 
185     PUT_FILE(file);
186     return (loff_t)ret;
187 }
188 
osal_release(struct inode * inode,struct file * file)189 static int osal_release(struct inode *inode, struct file *file)
190 {
191     int ret = 0;
192     struct osal_private_data *pdata = file->private_data;
193 
194     osal_unused(inode);
195     GET_FILE(file);
196 
197     if (DRVAL_DEBUG) {
198         osal_trace("%s - file->private_data=%pK!\n", __FUNCTION__, pdata);
199     }
200 
201     if (pdata->dev->fops->release != NULL) {
202         ret = pdata->dev->fops->release((void *)&(pdata->data));
203     }
204     PUT_FILE(file);
205     if (ret != 0) {
206         osal_trace("%s - release failed!\n", __FUNCTION__);
207         return ret;
208     }
209 
210     spin_lock(&g_f_lock);
211     if (pdata->f_ref_cnt != 0) {
212         osal_trace("%s - release failed!\n", __FUNCTION__);
213         spin_unlock(&g_f_lock);
214         return -1;
215     }
216     kfree(file->private_data);
217     file->private_data = NULL;
218     spin_unlock(&g_f_lock);
219 
220     return 0;
221 }
222 
__osal_unlocked_ioctl(struct file * file,unsigned int cmd,unsigned long arg)223 static long __osal_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
224 {
225     int ret = -1;
226     struct osal_private_data *pdata = file->private_data;
227     char *kbuf = NULL;
228 
229     if (DRVAL_DEBUG) {
230         osal_trace("%s - file->private_data=%pK!\n", __FUNCTION__, pdata);
231     }
232 
233     if (((_IOC_SIZE(cmd) == 0) && (_IOC_DIR(cmd) != _IOC_NONE))) {
234         return -1;
235     }
236 
237     if ((_IOC_DIR(cmd) != _IOC_NONE) && (((char *)(uintptr_t)arg) == NULL)) {
238         osal_trace("%s - Input param err,it is null!\n", __FUNCTION__);
239         return -1;
240     }
241 
242     if (_IOC_DIR(cmd) == _IOC_NONE) {
243         if (pdata->dev->fops->unlocked_ioctl == NULL) {
244             return -1;
245         } else {
246             ret = pdata->dev->fops->unlocked_ioctl(cmd, (unsigned long)NULL, (void *)&(pdata->data));
247         }
248     } else if (_IOC_DIR(cmd) == _IOC_WRITE) {
249         kbuf = (char *)vmalloc(_IOC_SIZE(cmd));
250         if (kbuf == NULL) {
251             osal_trace("%s - vmalloc failed!\n", __FUNCTION__);
252             return -1;
253         }
254 
255         if (copy_from_user(kbuf, (char *)(uintptr_t)arg, _IOC_SIZE(cmd))) {
256             vfree(kbuf);
257             kbuf = NULL;
258             return -1;
259         }
260 
261         if (pdata->dev->fops->unlocked_ioctl == NULL) {
262             vfree(kbuf);
263             kbuf = NULL;
264             return -1;
265         } else {
266             ret = pdata->dev->fops->unlocked_ioctl (cmd, (unsigned long)(uintptr_t)kbuf, (void *)&(pdata->data));
267         }
268     } else if (_IOC_DIR(cmd) == _IOC_READ) {
269         if (pdata->dev->fops->unlocked_ioctl == NULL) {
270             return -1;
271         }
272 
273         kbuf = vmalloc(_IOC_SIZE(cmd));
274         if (kbuf == NULL) {
275             osal_trace("%s - vmalloc failed!\n", __FUNCTION__);
276             return -1;
277         }
278 
279         ret = pdata->dev->fops->unlocked_ioctl (cmd, (unsigned long)(uintptr_t)kbuf, (void *)&(pdata->data));
280         if (ret == 0) {
281             if (copy_to_user((char *)(uintptr_t)arg, kbuf, _IOC_SIZE(cmd))) {
282                 vfree(kbuf);
283                 return -1;
284             }
285         }
286     } else if (_IOC_DIR(cmd) == (_IOC_READ + _IOC_WRITE)) {
287         kbuf = vmalloc(_IOC_SIZE(cmd));
288         if (kbuf == NULL) {
289             osal_trace("%s - vmalloc failed!\n", __FUNCTION__);
290             return -1;
291         }
292 
293         if (copy_from_user(kbuf, (char *)(uintptr_t)arg, _IOC_SIZE(cmd))) {
294             vfree(kbuf);
295             kbuf = NULL;
296             return -1;
297         }
298 
299         if (pdata->dev->fops->unlocked_ioctl == NULL) {
300             vfree(kbuf);
301             kbuf = NULL;
302             return -1;
303         } else {
304             ret = pdata->dev->fops->unlocked_ioctl (cmd, (unsigned long)(uintptr_t)kbuf, (void *)&(pdata->data));
305             if (ret == 0) {
306                 if (copy_to_user((char *)(uintptr_t)arg, kbuf, _IOC_SIZE(cmd))) {
307                     vfree(kbuf);
308                     kbuf = NULL;
309                     return -1;
310                 }
311             }
312         }
313     }
314 
315     if (kbuf != NULL) {
316         vfree(kbuf);
317         kbuf = NULL;
318     }
319 
320     return ret;
321 }
322 
osal_unlocked_ioctl(struct file * file,unsigned int cmd,unsigned long arg)323 static long osal_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
324 {
325     long ret;
326 
327     GET_FILE(file);
328 
329     ret = __osal_unlocked_ioctl(file, cmd, arg);
330     PUT_FILE(file);
331 
332     return ret;
333 }
334 
335 #ifdef CONFIG_COMPAT
__osal_compat_ioctl(struct file * file,unsigned int cmd,unsigned long arg)336 static long __osal_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
337 {
338     int ret = -1;
339     struct osal_private_data *pdata = file->private_data;
340     char *kbuf = NULL;
341 
342     if (DRVAL_DEBUG) {
343         osal_trace("%s - file->private_data=%pK!\n", __FUNCTION__, pdata);
344     }
345 
346     if ((_IOC_SIZE(cmd) == 0) && (_IOC_DIR(cmd) != _IOC_NONE)) {
347         return -1;
348     }
349 
350     if ((_IOC_DIR(cmd) != _IOC_NONE) && (((char *)(uintptr_t)arg) == NULL)) {
351         osal_trace("%s - Input param err,it is null!\n", __FUNCTION__);
352         return -1;
353     }
354 
355     if (_IOC_DIR(cmd) == _IOC_NONE) {
356         if (pdata->dev->fops->compat_ioctl == NULL) {
357             return -1;
358         } else {
359             ret = pdata->dev->fops->compat_ioctl(cmd, arg, (void *)&(pdata->data));
360         }
361     } else if (_IOC_DIR(cmd) == _IOC_WRITE) {
362         kbuf = (char *)vmalloc(_IOC_SIZE(cmd));
363         if (kbuf == NULL) {
364             osal_trace("%s - vmalloc failed!\n", __FUNCTION__);
365             return -1;
366         }
367 
368         if (copy_from_user(kbuf, (char *)(uintptr_t)arg, _IOC_SIZE(cmd))) {
369             vfree(kbuf);
370             return -1;
371         }
372 
373         if (pdata->dev->fops->compat_ioctl == NULL) {
374             vfree(kbuf);
375             return -1;
376         } else {
377             ret = pdata->dev->fops->compat_ioctl (cmd, (unsigned long)(uintptr_t)kbuf, (void *)&(pdata->data));
378         }
379     } else if (_IOC_DIR(cmd) == _IOC_READ) {
380         kbuf = vmalloc(_IOC_SIZE(cmd));
381         if (kbuf == NULL) {
382             osal_trace("%s - vmalloc failed!\n", __FUNCTION__);
383             return -1;
384         }
385         if (pdata->dev->fops->compat_ioctl == NULL) {
386             vfree(kbuf);
387             return -1;
388         } else {
389             ret = pdata->dev->fops->compat_ioctl (cmd, (unsigned long)(uintptr_t)kbuf, (void *)&(pdata->data));
390             if (ret == 0) {
391                 if (copy_to_user((char *)(uintptr_t)arg, kbuf, _IOC_SIZE(cmd))) {
392                     vfree(kbuf);
393                     return -1;
394                 }
395             }
396         }
397     } else if (_IOC_DIR(cmd) == (_IOC_READ + _IOC_WRITE)) {
398         kbuf = vmalloc(_IOC_SIZE(cmd));
399         if (kbuf == NULL) {
400             osal_trace("%s - vmalloc failed!\n", __FUNCTION__);
401             return -1;
402         }
403 
404         if (copy_from_user(kbuf, (char *)(uintptr_t)arg, _IOC_SIZE(cmd))) {
405             vfree(kbuf);
406             return -1;
407         }
408 
409         if (pdata->dev->fops->compat_ioctl == NULL) {
410             vfree(kbuf);
411             return -1;
412         } else {
413             ret = pdata->dev->fops->compat_ioctl (cmd, (unsigned long)(uintptr_t)kbuf, (void *)&(pdata->data));
414             if (ret == 0) {
415                 if (copy_to_user((char *)(uintptr_t)arg, kbuf, _IOC_SIZE(cmd))) {
416                     vfree(kbuf);
417                     return -1;
418                 }
419             }
420         }
421     }
422 
423     if (kbuf != NULL) {
424         vfree(kbuf);
425     }
426 
427     return ret;
428 }
429 
osal_compat_ioctl(struct file * file,unsigned int cmd,unsigned long arg)430 static long osal_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
431 {
432     long ret;
433 
434     GET_FILE(file);
435 
436     ret = __osal_compat_ioctl(file, cmd, arg);
437     PUT_FILE(file);
438 
439     return ret;
440 }
441 
442 #endif
443 
osal_poll(struct file * file,struct poll_table_struct * table)444 static unsigned int osal_poll(struct file *file, struct poll_table_struct *table)
445 {
446     struct osal_private_data *pdata = file->private_data;
447     struct osal_poll t;
448     unsigned int ret = 0;
449 
450     GET_FILE(file);
451 
452     if (DRVAL_DEBUG) {
453         osal_trace("%s - table=%pK, file=%pK!\n", __FUNCTION__, table, file);
454     }
455     t.poll_table = table;
456     t.data = file;
457     if (pdata->dev->fops->poll != NULL) {
458         ret = pdata->dev->fops->poll(&t, (void *)&(pdata->data));
459     }
460 
461     PUT_FILE(file);
462     return ret;
463 }
464 
valid_mmap_phys_addr_range(unsigned long pfn,size_t size)465 int valid_mmap_phys_addr_range(unsigned long pfn, size_t size)
466 {
467     /* check physical addr greater than the max addr supported by the system */
468     if ((pfn + (size >> PAGE_SHIFT)) > (1 + ((~0UL) >> PAGE_SHIFT))) {
469         osal_trace("--%s - %d--!\n", __FUNCTION__, __LINE__);
470         return 0;
471     }
472 
473     /* It's necessary for the variable "size" to align 4k(page_size). */
474 #define PAGE_SIZE_MASK 0xfffffffffffff000ULL
475     if ((unsigned long)size & (~PAGE_SIZE_MASK)) {
476         osal_trace("--%s - %d--!\n", __FUNCTION__, __LINE__);
477         return 0;
478     }
479 #undef PAGE_SIZE_MASK
480 
481     return 1;
482 }
483 
osal_mmap(struct file * file,struct vm_area_struct * vm)484 static int osal_mmap(struct file *file, struct vm_area_struct *vm)
485 {
486     struct osal_vm osal_vm;
487     struct osal_private_data *pdata = file->private_data;
488     osal_vm.vm = vm;
489 
490     if (!valid_mmap_phys_addr_range(vm->vm_pgoff, vm->vm_end - vm->vm_start)) {
491         osal_trace("\n%s - invalid argument   size=%ld!!!\n", __FUNCTION__, vm->vm_end - vm->vm_start);
492         return -EINVAL;
493     }
494 
495     if (DRVAL_DEBUG) {
496         osal_trace("%s - start=%lx, end=%lx!, off=%lx\n", __FUNCTION__, vm->vm_start, vm->vm_end, vm->vm_pgoff);
497     }
498     if (pdata->dev->fops->mmap != NULL) {
499         return pdata->dev->fops->mmap(&osal_vm, vm->vm_start, vm->vm_end, vm->vm_pgoff, (void *)&(pdata->data));
500     }
501     return 0;
502 }
503 
504 static struct file_operations g_osal_fops = {
505     .owner = THIS_MODULE,
506     .open = osal_open,
507     .read = osal_read,
508     .write = osal_write,
509     .llseek = osal_llseek,
510     .unlocked_ioctl = osal_unlocked_ioctl,
511     .release = osal_release,
512     .poll = osal_poll,
513     .mmap = osal_mmap,
514 #ifdef CONFIG_COMPAT
515     .compat_ioctl = osal_compat_ioctl,
516 #endif
517 };
518 
osal_pm_prepare(struct himedia_device * himedia)519 static int osal_pm_prepare(struct himedia_device *himedia)
520 {
521     osal_coat_dev_t *coat_dev = container_of(himedia, struct osal_coat_dev, himedia_dev);
522     if (coat_dev != NULL) {
523         if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_prepare) {
524             return coat_dev->osal_dev.osal_pmops->pm_prepare(&(coat_dev->osal_dev));
525         }
526     }
527     return 0;
528 }
529 
osal_pm_complete(struct himedia_device * himedia)530 static void osal_pm_complete(struct himedia_device *himedia)
531 {
532     osal_coat_dev_t *coat_dev = container_of(himedia, struct osal_coat_dev, himedia_dev);
533     if (coat_dev != NULL) {
534         if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_complete) {
535             coat_dev->osal_dev.osal_pmops->pm_complete(&(coat_dev->osal_dev));
536         }
537     }
538 }
539 
osal_pm_suspend(struct himedia_device * himedia)540 static int osal_pm_suspend(struct himedia_device *himedia)
541 {
542     osal_coat_dev_t *coat_dev = container_of(himedia, struct osal_coat_dev, himedia_dev);
543     if (coat_dev != NULL) {
544         if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_suspend) {
545             return coat_dev->osal_dev.osal_pmops->pm_suspend(&(coat_dev->osal_dev));
546         }
547     }
548     return 0;
549 }
550 
osal_pm_resume(struct himedia_device * himedia)551 static int osal_pm_resume(struct himedia_device *himedia)
552 {
553     osal_coat_dev_t *coat_dev = container_of(himedia, struct osal_coat_dev, himedia_dev);
554     if (coat_dev != NULL) {
555         if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_resume) {
556             return coat_dev->osal_dev.osal_pmops->pm_resume(&(coat_dev->osal_dev));
557         }
558     }
559     return 0;
560 }
561 
osal_pm_freeze(struct himedia_device * himedia)562 static int osal_pm_freeze(struct himedia_device *himedia)
563 {
564     osal_coat_dev_t *coat_dev = container_of(himedia, struct osal_coat_dev, himedia_dev);
565     if (coat_dev != NULL) {
566         if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_freeze) {
567             return coat_dev->osal_dev.osal_pmops->pm_freeze(&(coat_dev->osal_dev));
568         }
569     }
570     return 0;
571 }
572 
osal_pm_thaw(struct himedia_device * himedia)573 static int osal_pm_thaw(struct himedia_device *himedia)
574 {
575     osal_coat_dev_t *coat_dev = container_of(himedia, struct osal_coat_dev, himedia_dev);
576     if (coat_dev != NULL) {
577         if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_thaw) {
578             return coat_dev->osal_dev.osal_pmops->pm_thaw(&(coat_dev->osal_dev));
579         }
580     }
581     return 0;
582 }
583 
osal_pm_poweroff(struct himedia_device * himedia)584 static int osal_pm_poweroff(struct himedia_device *himedia)
585 {
586     osal_coat_dev_t *coat_dev = container_of(himedia, struct osal_coat_dev, himedia_dev);
587     if (coat_dev != NULL) {
588         if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_poweroff) {
589             return coat_dev->osal_dev.osal_pmops->pm_poweroff(&(coat_dev->osal_dev));
590         }
591     }
592     return 0;
593 }
594 
osal_pm_restore(struct himedia_device * himedia)595 static int osal_pm_restore(struct himedia_device *himedia)
596 {
597     osal_coat_dev_t *coat_dev = container_of(himedia, struct osal_coat_dev, himedia_dev);
598     if (coat_dev != NULL) {
599         if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_restore) {
600             return coat_dev->osal_dev.osal_pmops->pm_restore(&(coat_dev->osal_dev));
601         }
602     }
603     return 0;
604 }
605 
osal_pm_suspend_late(struct himedia_device * himedia)606 static int osal_pm_suspend_late(struct himedia_device *himedia)
607 {
608     osal_coat_dev_t *coat_dev = container_of(himedia, struct osal_coat_dev, himedia_dev);
609     if (coat_dev != NULL) {
610         if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_suspend_late) {
611             return coat_dev->osal_dev.osal_pmops->pm_suspend_late(&(coat_dev->osal_dev));
612         }
613     }
614     return 0;
615 }
616 
osal_pm_resume_early(struct himedia_device * himedia)617 static int osal_pm_resume_early(struct himedia_device *himedia)
618 {
619     osal_coat_dev_t *coat_dev = container_of(himedia, struct osal_coat_dev, himedia_dev);
620     if (coat_dev != NULL) {
621         if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_resume_early) {
622             return coat_dev->osal_dev.osal_pmops->pm_resume_early(&(coat_dev->osal_dev));
623         }
624     }
625     return 0;
626 }
627 
osal_pm_freeze_late(struct himedia_device * himedia)628 static int osal_pm_freeze_late(struct himedia_device *himedia)
629 {
630     osal_coat_dev_t *coat_dev = container_of(himedia, struct osal_coat_dev, himedia_dev);
631     if (coat_dev != NULL) {
632         if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_freeze_late) {
633             return coat_dev->osal_dev.osal_pmops->pm_freeze_late(&(coat_dev->osal_dev));
634         }
635     }
636     return 0;
637 }
638 
osal_pm_thaw_early(struct himedia_device * himedia)639 static int osal_pm_thaw_early(struct himedia_device *himedia)
640 {
641     osal_coat_dev_t *coat_dev = container_of(himedia, struct osal_coat_dev, himedia_dev);
642     if (coat_dev != NULL) {
643         if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_thaw_early) {
644             return coat_dev->osal_dev.osal_pmops->pm_thaw_early(&(coat_dev->osal_dev));
645         }
646     }
647     return 0;
648 }
649 
osal_pm_poweroff_late(struct himedia_device * himedia)650 static int osal_pm_poweroff_late(struct himedia_device *himedia)
651 {
652     osal_coat_dev_t *coat_dev = container_of(himedia, struct osal_coat_dev, himedia_dev);
653     if (coat_dev != NULL) {
654         if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_poweroff_late) {
655             return coat_dev->osal_dev.osal_pmops->pm_poweroff_late(&(coat_dev->osal_dev));
656         }
657     }
658     return 0;
659 }
660 
osal_pm_restore_early(struct himedia_device * himedia)661 static int osal_pm_restore_early(struct himedia_device *himedia)
662 {
663     osal_coat_dev_t *coat_dev = container_of(himedia, struct osal_coat_dev, himedia_dev);
664     if (coat_dev != NULL) {
665         if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_restore_early) {
666             return coat_dev->osal_dev.osal_pmops->pm_restore_early(&(coat_dev->osal_dev));
667         }
668     }
669     return 0;
670 }
671 
osal_pm_suspend_noirq(struct himedia_device * himedia)672 static int osal_pm_suspend_noirq(struct himedia_device *himedia)
673 {
674     osal_coat_dev_t *coat_dev = container_of(himedia, struct osal_coat_dev, himedia_dev);
675     if (coat_dev != NULL) {
676         if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_suspend_noirq) {
677             return coat_dev->osal_dev.osal_pmops->pm_suspend_noirq(&(coat_dev->osal_dev));
678         }
679     }
680     return 0;
681 }
682 
osal_pm_resume_noirq(struct himedia_device * himedia)683 static int osal_pm_resume_noirq(struct himedia_device *himedia)
684 {
685     osal_coat_dev_t *coat_dev = container_of(himedia, struct osal_coat_dev, himedia_dev);
686     if (coat_dev != NULL) {
687         if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_resume_noirq) {
688             return coat_dev->osal_dev.osal_pmops->pm_resume_noirq(&(coat_dev->osal_dev));
689         }
690     }
691     return 0;
692 }
693 
osal_pm_freeze_noirq(struct himedia_device * himedia)694 static int osal_pm_freeze_noirq(struct himedia_device *himedia)
695 {
696     osal_coat_dev_t *coat_dev = container_of(himedia, struct osal_coat_dev, himedia_dev);
697     if (coat_dev != NULL) {
698         if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_freeze_noirq) {
699             return coat_dev->osal_dev.osal_pmops->pm_freeze_noirq(&(coat_dev->osal_dev));
700         }
701     }
702     return 0;
703 }
704 
osal_pm_thaw_noirq(struct himedia_device * himedia)705 static int osal_pm_thaw_noirq(struct himedia_device *himedia)
706 {
707     osal_coat_dev_t *coat_dev = container_of(himedia, struct osal_coat_dev, himedia_dev);
708     if (coat_dev != NULL) {
709         if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_thaw_noirq) {
710             return coat_dev->osal_dev.osal_pmops->pm_thaw_noirq(&(coat_dev->osal_dev));
711         }
712     }
713     return 0;
714 }
715 
osal_pm_poweroff_noirq(struct himedia_device * himedia)716 static int osal_pm_poweroff_noirq(struct himedia_device *himedia)
717 {
718     osal_coat_dev_t *coat_dev = container_of(himedia, struct osal_coat_dev, himedia_dev);
719     if (coat_dev != NULL) {
720         if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_poweroff_noirq) {
721             return coat_dev->osal_dev.osal_pmops->pm_poweroff_noirq(&(coat_dev->osal_dev));
722         }
723     }
724     return 0;
725 }
726 
osal_pm_restore_noirq(struct himedia_device * himedia)727 static int osal_pm_restore_noirq(struct himedia_device *himedia)
728 {
729     osal_coat_dev_t *coat_dev = container_of(himedia, struct osal_coat_dev, himedia_dev);
730     if (coat_dev != NULL) {
731         if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_restore_noirq) {
732             return coat_dev->osal_dev.osal_pmops->pm_restore_noirq(&(coat_dev->osal_dev));
733         }
734     }
735     return 0;
736 }
737 
738 static struct himedia_ops g_osal_pmops = {
739     .pm_prepare = osal_pm_prepare,
740     .pm_complete = osal_pm_complete,
741     .pm_suspend = osal_pm_suspend,
742     .pm_resume = osal_pm_resume,
743     .pm_freeze = osal_pm_freeze,
744     .pm_thaw = osal_pm_thaw,
745     .pm_poweroff = osal_pm_poweroff,
746     .pm_restore = osal_pm_restore,
747     .pm_suspend_late = osal_pm_suspend_late,
748     .pm_resume_early = osal_pm_resume_early,
749     .pm_freeze_late = osal_pm_freeze_late,
750     .pm_thaw_early = osal_pm_thaw_early,
751     .pm_poweroff_late = osal_pm_poweroff_late,
752     .pm_restore_early = osal_pm_restore_early,
753     .pm_suspend_noirq = osal_pm_suspend_noirq,
754     .pm_resume_noirq = osal_pm_resume_noirq,
755     .pm_freeze_noirq = osal_pm_freeze_noirq,
756     .pm_thaw_noirq = osal_pm_thaw_noirq,
757     .pm_poweroff_noirq = osal_pm_poweroff_noirq,
758     .pm_restore_noirq = osal_pm_restore_noirq,
759 };
760 
osal_createdev(const char * name)761 osal_dev_t *osal_createdev(const char *name)
762 {
763     osal_coat_dev_t *pdev = NULL;
764     errno_t err_value;
765 
766     if (name == NULL) {
767         osal_trace("%s - parameter invalid!\n", __FUNCTION__);
768         return NULL;
769     }
770     pdev = (osal_coat_dev_t *)kmalloc(sizeof(osal_coat_dev_t), GFP_KERNEL);
771     if (pdev == NULL) {
772         osal_trace("%s - kmalloc error!\n", __FUNCTION__);
773         return NULL;
774     }
775     (void)memset_s(pdev, sizeof(osal_coat_dev_t), 0, sizeof(osal_coat_dev_t));
776     err_value = strncpy_s(pdev->osal_dev.name, OSAL_MAX_DEV_NAME_LEN, name, sizeof(pdev->osal_dev.name) - 1);
777     if (err_value != EOK) {
778         kfree(pdev);
779         osal_trace("%s - strncpy_s failed!\n", __FUNCTION__);
780         return NULL;
781     }
782     pdev->osal_dev.dev = pdev;
783     return &(pdev->osal_dev);
784 }
785 EXPORT_SYMBOL(osal_createdev);
786 
osal_destroydev(osal_dev_t * osal_dev)787 int osal_destroydev(osal_dev_t *osal_dev)
788 {
789     osal_coat_dev_t *pdev = NULL;
790     if (osal_dev == NULL) {
791         osal_trace("%s - parameter invalid!\n", __FUNCTION__);
792         return -1;
793     }
794     pdev = osal_dev->dev;
795     if (pdev == NULL) {
796         osal_trace("%s - parameter invalid!\n", __FUNCTION__);
797         return -1;
798     }
799     kfree(pdev);
800     return 0;
801 }
802 EXPORT_SYMBOL(osal_destroydev);
803 
osal_registerdevice(osal_dev_t * osal_dev)804 int osal_registerdevice(osal_dev_t *osal_dev)
805 {
806     struct himedia_device *himedia = NULL;
807     errno_t err_value;
808 
809     if ((osal_dev == NULL) || (osal_dev->fops == NULL)) {
810         osal_trace("%s - parameter invalid!\n", __FUNCTION__);
811         return -1;
812     }
813     himedia = &(((osal_coat_dev_t *)(osal_dev->dev))->himedia_dev);
814     if (osal_dev->minor != 0) {
815         himedia->minor = osal_dev->minor;
816     } else {
817         himedia->minor = HIMEDIA_DYNAMIC_MINOR;
818     }
819     himedia->owner = THIS_MODULE;
820     himedia->fops = &g_osal_fops;
821     himedia->drvops = &g_osal_pmops;
822     err_value = strncpy_s(himedia->devfs_name, HIMIDIA_MAX_DEV_NAME_LEN, osal_dev->name,
823         sizeof(himedia->devfs_name) - 1);
824     if (err_value != EOK) {
825         osal_trace("%s - strncpy_s failed!\n", __FUNCTION__);
826         return -1;
827     }
828     return himedia_register(himedia);
829 }
830 EXPORT_SYMBOL(osal_registerdevice);
831 
osal_deregisterdevice(osal_dev_t * pdev)832 void osal_deregisterdevice(osal_dev_t *pdev)
833 {
834     if (pdev == NULL) {
835         osal_trace("%s - parameter invalid!\n", __FUNCTION__);
836         return;
837     }
838     himedia_unregister((struct himedia_device *)&(((osal_coat_dev_t *)(pdev->dev))->himedia_dev));
839 }
840 EXPORT_SYMBOL(osal_deregisterdevice);
841 
osal_poll_wait(osal_poll_t * table,osal_wait_t * wait)842 void osal_poll_wait(osal_poll_t *table, osal_wait_t *wait)
843 {
844     if ((table != NULL) && (wait != NULL)) {
845         if (DRVAL_DEBUG) {
846             osal_trace("%s - call poll_wait +!, table=%pK, file=%pK\n", __FUNCTION__, table->poll_table, table->data);
847         }
848 
849         poll_wait ((struct file *)table->data, (wait_queue_head_t *)(wait->wait), table->poll_table);
850 
851         if (DRVAL_DEBUG) {
852             osal_trace("%s - call poll_wait -!\n", __FUNCTION__);
853         }
854     }
855 }
856 EXPORT_SYMBOL(osal_poll_wait);
857 
osal_pgprot_noncached(osal_vm_t * vm)858 void osal_pgprot_noncached(osal_vm_t *vm)
859 {
860     if (vm != NULL) {
861         struct vm_area_struct *v = (struct vm_area_struct *)(vm->vm);
862         v->vm_page_prot = pgprot_writecombine(v->vm_page_prot);
863     }
864 }
865 EXPORT_SYMBOL(osal_pgprot_noncached);
866 
osal_pgprot_cached(osal_vm_t * vm)867 void osal_pgprot_cached(osal_vm_t *vm)
868 {
869     if (vm != NULL) {
870         struct vm_area_struct *v = (struct vm_area_struct *)(vm->vm);
871 
872 #ifdef CONFIG_64BIT
873         v->vm_page_prot = __pgprot(pgprot_val(v->vm_page_prot) |
874                                               PTE_VALID | PTE_DIRTY | PTE_AF);
875 #else
876 
877         v->vm_page_prot = __pgprot(pgprot_val(v->vm_page_prot) | L_PTE_PRESENT |
878                                    L_PTE_YOUNG | L_PTE_DIRTY | L_PTE_MT_DEV_CACHED);
879 #endif
880     }
881 }
882 EXPORT_SYMBOL(osal_pgprot_cached);
883 
osal_pgprot_writecombine(osal_vm_t * vm)884 void osal_pgprot_writecombine(osal_vm_t *vm)
885 {
886     if (vm != NULL) {
887         struct vm_area_struct *v = (struct vm_area_struct *)(vm->vm);
888         v->vm_page_prot = pgprot_writecombine(v->vm_page_prot);
889     }
890 }
891 EXPORT_SYMBOL(osal_pgprot_writecombine);
892 
osal_remap_pfn_range(osal_vm_t * vm,unsigned long addr,unsigned long pfn,unsigned long size)893 int osal_remap_pfn_range(osal_vm_t *vm, unsigned long addr, unsigned long pfn, unsigned long size)
894 {
895     struct vm_area_struct *v = NULL;
896     if (vm == NULL) {
897         return -EINVAL;
898     }
899     v = (struct vm_area_struct *)(vm->vm);
900     if (size == 0) {
901         return -EPERM;
902     }
903     return remap_pfn_range(v, addr, pfn, size, v->vm_page_prot);
904 }
905 EXPORT_SYMBOL(osal_remap_pfn_range);
906 
907