1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Support for Medifield PNW Camera Imaging ISP subsystem.
4 *
5 * Copyright (c) 2010-2017 Intel Corporation. All Rights Reserved.
6 *
7 * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License version
11 * 2 as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 *
19 */
20 /*
21 * This file contains entry functions for memory management of ISP driver
22 */
23 #include <linux/kernel.h>
24 #include <linux/types.h>
25 #include <linux/mm.h>
26 #include <linux/highmem.h> /* for kmap */
27 #include <linux/io.h> /* for page_to_phys */
28 #include <linux/sysfs.h>
29
30 #include "hmm/hmm.h"
31 #include "hmm/hmm_pool.h"
32 #include "hmm/hmm_bo.h"
33
34 #include "atomisp_internal.h"
35 #include "asm/cacheflush.h"
36 #include "mmu/isp_mmu.h"
37 #include "mmu/sh_mmu_mrfld.h"
38
39 struct hmm_bo_device bo_device;
40 struct hmm_pool dynamic_pool;
41 struct hmm_pool reserved_pool;
42 static ia_css_ptr dummy_ptr = mmgr_EXCEPTION;
43 static bool hmm_initialized;
44 struct _hmm_mem_stat hmm_mem_stat;
45
46 /*
47 * p: private
48 * s: shared
49 * u: user
50 * i: ion
51 */
52 static const char hmm_bo_type_string[] = "psui";
53
bo_show(struct device * dev,struct device_attribute * attr,char * buf,struct list_head * bo_list,bool active)54 static ssize_t bo_show(struct device *dev, struct device_attribute *attr,
55 char *buf, struct list_head *bo_list, bool active)
56 {
57 ssize_t ret = 0;
58 struct hmm_buffer_object *bo;
59 unsigned long flags;
60 int i;
61 long total[HMM_BO_LAST] = { 0 };
62 long count[HMM_BO_LAST] = { 0 };
63 int index1 = 0;
64 int index2 = 0;
65
66 ret = scnprintf(buf, PAGE_SIZE, "type pgnr\n");
67 if (ret <= 0)
68 return 0;
69
70 index1 += ret;
71
72 spin_lock_irqsave(&bo_device.list_lock, flags);
73 list_for_each_entry(bo, bo_list, list) {
74 if ((active && (bo->status & HMM_BO_ALLOCED)) ||
75 (!active && !(bo->status & HMM_BO_ALLOCED))) {
76 ret = scnprintf(buf + index1, PAGE_SIZE - index1,
77 "%c %d\n",
78 hmm_bo_type_string[bo->type], bo->pgnr);
79
80 total[bo->type] += bo->pgnr;
81 count[bo->type]++;
82 if (ret > 0)
83 index1 += ret;
84 }
85 }
86 spin_unlock_irqrestore(&bo_device.list_lock, flags);
87
88 for (i = 0; i < HMM_BO_LAST; i++) {
89 if (count[i]) {
90 ret = scnprintf(buf + index1 + index2,
91 PAGE_SIZE - index1 - index2,
92 "%ld %c buffer objects: %ld KB\n",
93 count[i], hmm_bo_type_string[i],
94 total[i] * 4);
95 if (ret > 0)
96 index2 += ret;
97 }
98 }
99
100 /* Add trailing zero, not included by scnprintf */
101 return index1 + index2 + 1;
102 }
103
active_bo_show(struct device * dev,struct device_attribute * attr,char * buf)104 static ssize_t active_bo_show(struct device *dev, struct device_attribute *attr,
105 char *buf)
106 {
107 return bo_show(dev, attr, buf, &bo_device.entire_bo_list, true);
108 }
109
free_bo_show(struct device * dev,struct device_attribute * attr,char * buf)110 static ssize_t free_bo_show(struct device *dev, struct device_attribute *attr,
111 char *buf)
112 {
113 return bo_show(dev, attr, buf, &bo_device.entire_bo_list, false);
114 }
115
reserved_pool_show(struct device * dev,struct device_attribute * attr,char * buf)116 static ssize_t reserved_pool_show(struct device *dev,
117 struct device_attribute *attr,
118 char *buf)
119 {
120 ssize_t ret = 0;
121
122 struct hmm_reserved_pool_info *pinfo = reserved_pool.pool_info;
123 unsigned long flags;
124
125 if (!pinfo || !pinfo->initialized)
126 return 0;
127
128 spin_lock_irqsave(&pinfo->list_lock, flags);
129 ret = scnprintf(buf, PAGE_SIZE, "%d out of %d pages available\n",
130 pinfo->index, pinfo->pgnr);
131 spin_unlock_irqrestore(&pinfo->list_lock, flags);
132
133 if (ret > 0)
134 ret++; /* Add trailing zero, not included by scnprintf */
135
136 return ret;
137 };
138
dynamic_pool_show(struct device * dev,struct device_attribute * attr,char * buf)139 static ssize_t dynamic_pool_show(struct device *dev,
140 struct device_attribute *attr,
141 char *buf)
142 {
143 ssize_t ret = 0;
144
145 struct hmm_dynamic_pool_info *pinfo = dynamic_pool.pool_info;
146 unsigned long flags;
147
148 if (!pinfo || !pinfo->initialized)
149 return 0;
150
151 spin_lock_irqsave(&pinfo->list_lock, flags);
152 ret = scnprintf(buf, PAGE_SIZE, "%d (max %d) pages available\n",
153 pinfo->pgnr, pinfo->pool_size);
154 spin_unlock_irqrestore(&pinfo->list_lock, flags);
155
156 if (ret > 0)
157 ret++; /* Add trailing zero, not included by scnprintf */
158
159 return ret;
160 };
161
162 static DEVICE_ATTR_RO(active_bo);
163 static DEVICE_ATTR_RO(free_bo);
164 static DEVICE_ATTR_RO(reserved_pool);
165 static DEVICE_ATTR_RO(dynamic_pool);
166
167 static struct attribute *sysfs_attrs_ctrl[] = {
168 &dev_attr_active_bo.attr,
169 &dev_attr_free_bo.attr,
170 &dev_attr_reserved_pool.attr,
171 &dev_attr_dynamic_pool.attr,
172 NULL
173 };
174
175 static struct attribute_group atomisp_attribute_group[] = {
176 {.attrs = sysfs_attrs_ctrl },
177 };
178
hmm_init(void)179 int hmm_init(void)
180 {
181 int ret;
182
183 ret = hmm_bo_device_init(&bo_device, &sh_mmu_mrfld,
184 ISP_VM_START, ISP_VM_SIZE);
185 if (ret)
186 dev_err(atomisp_dev, "hmm_bo_device_init failed.\n");
187
188 hmm_initialized = true;
189
190 /*
191 * As hmm use NULL to indicate invalid ISP virtual address,
192 * and ISP_VM_START is defined to 0 too, so we allocate
193 * one piece of dummy memory, which should return value 0,
194 * at the beginning, to avoid hmm_alloc return 0 in the
195 * further allocation.
196 */
197 dummy_ptr = hmm_alloc(1, HMM_BO_PRIVATE, 0, NULL, 0);
198
199 if (!ret) {
200 ret = sysfs_create_group(&atomisp_dev->kobj,
201 atomisp_attribute_group);
202 if (ret)
203 dev_err(atomisp_dev,
204 "%s Failed to create sysfs\n", __func__);
205 }
206
207 return ret;
208 }
209
hmm_cleanup(void)210 void hmm_cleanup(void)
211 {
212 if (dummy_ptr == mmgr_EXCEPTION)
213 return;
214 sysfs_remove_group(&atomisp_dev->kobj, atomisp_attribute_group);
215
216 /* free dummy memory first */
217 hmm_free(dummy_ptr);
218 dummy_ptr = 0;
219
220 hmm_bo_device_exit(&bo_device);
221 hmm_initialized = false;
222 }
223
hmm_alloc(size_t bytes,enum hmm_bo_type type,int from_highmem,const void __user * userptr,const uint16_t attrs)224 ia_css_ptr hmm_alloc(size_t bytes, enum hmm_bo_type type,
225 int from_highmem, const void __user *userptr,
226 const uint16_t attrs)
227 {
228 unsigned int pgnr;
229 struct hmm_buffer_object *bo;
230 bool cached = attrs & ATOMISP_MAP_FLAG_CACHED;
231 int ret;
232
233 WARN_ON(attrs & ATOMISP_MAP_FLAG_CONTIGUOUS);
234
235 /*
236 * Check if we are initialized. In the ideal world we wouldn't need
237 * this but we can tackle it once the driver is a lot cleaner
238 */
239
240 if (!hmm_initialized)
241 hmm_init();
242 /* Get page number from size */
243 pgnr = size_to_pgnr_ceil(bytes);
244
245 /* Buffer object structure init */
246 bo = hmm_bo_alloc(&bo_device, pgnr);
247 if (!bo) {
248 dev_err(atomisp_dev, "hmm_bo_create failed.\n");
249 goto create_bo_err;
250 }
251
252 /* Allocate pages for memory */
253 ret = hmm_bo_alloc_pages(bo, type, from_highmem, userptr, cached);
254 if (ret) {
255 dev_err(atomisp_dev, "hmm_bo_alloc_pages failed.\n");
256 goto alloc_page_err;
257 }
258
259 /* Combine the virtual address and pages together */
260 ret = hmm_bo_bind(bo);
261 if (ret) {
262 dev_err(atomisp_dev, "hmm_bo_bind failed.\n");
263 goto bind_err;
264 }
265
266 hmm_mem_stat.tol_cnt += pgnr;
267
268 if (attrs & ATOMISP_MAP_FLAG_CLEARED)
269 hmm_set(bo->start, 0, bytes);
270
271 dev_dbg(atomisp_dev,
272 "%s: pages: 0x%08x (%zu bytes), type: %d from highmem %d, user ptr %p, cached %d\n",
273 __func__, bo->start, bytes, type, from_highmem, userptr, cached);
274
275 return bo->start;
276
277 bind_err:
278 hmm_bo_free_pages(bo);
279 alloc_page_err:
280 hmm_bo_unref(bo);
281 create_bo_err:
282 return 0;
283 }
284
hmm_free(ia_css_ptr virt)285 void hmm_free(ia_css_ptr virt)
286 {
287 struct hmm_buffer_object *bo;
288
289 dev_dbg(atomisp_dev, "%s: free 0x%08x\n", __func__, virt);
290
291 if (WARN_ON(virt == mmgr_EXCEPTION))
292 return;
293
294 bo = hmm_bo_device_search_start(&bo_device, (unsigned int)virt);
295
296 if (!bo) {
297 dev_err(atomisp_dev,
298 "can not find buffer object start with address 0x%x\n",
299 (unsigned int)virt);
300 return;
301 }
302
303 hmm_mem_stat.tol_cnt -= bo->pgnr;
304
305 hmm_bo_unbind(bo);
306 hmm_bo_free_pages(bo);
307 hmm_bo_unref(bo);
308 }
309
hmm_check_bo(struct hmm_buffer_object * bo,unsigned int ptr)310 static inline int hmm_check_bo(struct hmm_buffer_object *bo, unsigned int ptr)
311 {
312 if (!bo) {
313 dev_err(atomisp_dev,
314 "can not find buffer object contains address 0x%x\n",
315 ptr);
316 return -EINVAL;
317 }
318
319 if (!hmm_bo_page_allocated(bo)) {
320 dev_err(atomisp_dev,
321 "buffer object has no page allocated.\n");
322 return -EINVAL;
323 }
324
325 if (!hmm_bo_allocated(bo)) {
326 dev_err(atomisp_dev,
327 "buffer object has no virtual address space allocated.\n");
328 return -EINVAL;
329 }
330
331 return 0;
332 }
333
334 /* Read function in ISP memory management */
load_and_flush_by_kmap(ia_css_ptr virt,void * data,unsigned int bytes)335 static int load_and_flush_by_kmap(ia_css_ptr virt, void *data,
336 unsigned int bytes)
337 {
338 struct hmm_buffer_object *bo;
339 unsigned int idx, offset, len;
340 char *src, *des;
341 int ret;
342
343 bo = hmm_bo_device_search_in_range(&bo_device, virt);
344 ret = hmm_check_bo(bo, virt);
345 if (ret)
346 return ret;
347
348 des = (char *)data;
349 while (bytes) {
350 idx = (virt - bo->start) >> PAGE_SHIFT;
351 offset = (virt - bo->start) - (idx << PAGE_SHIFT);
352
353 src = (char *)kmap(bo->page_obj[idx].page) + offset;
354
355 if ((bytes + offset) >= PAGE_SIZE) {
356 len = PAGE_SIZE - offset;
357 bytes -= len;
358 } else {
359 len = bytes;
360 bytes = 0;
361 }
362
363 virt += len; /* update virt for next loop */
364
365 if (des) {
366 memcpy(des, src, len);
367 des += len;
368 }
369
370 clflush_cache_range(src, len);
371
372 kunmap(bo->page_obj[idx].page);
373 }
374
375 return 0;
376 }
377
378 /* Read function in ISP memory management */
load_and_flush(ia_css_ptr virt,void * data,unsigned int bytes)379 static int load_and_flush(ia_css_ptr virt, void *data, unsigned int bytes)
380 {
381 struct hmm_buffer_object *bo;
382 int ret;
383
384 bo = hmm_bo_device_search_in_range(&bo_device, virt);
385 ret = hmm_check_bo(bo, virt);
386 if (ret)
387 return ret;
388
389 if (bo->status & HMM_BO_VMAPED || bo->status & HMM_BO_VMAPED_CACHED) {
390 void *src = bo->vmap_addr;
391
392 src += (virt - bo->start);
393 memcpy(data, src, bytes);
394 if (bo->status & HMM_BO_VMAPED_CACHED)
395 clflush_cache_range(src, bytes);
396 } else {
397 void *vptr;
398
399 vptr = hmm_bo_vmap(bo, true);
400 if (!vptr)
401 return load_and_flush_by_kmap(virt, data, bytes);
402 else
403 vptr = vptr + (virt - bo->start);
404
405 memcpy(data, vptr, bytes);
406 clflush_cache_range(vptr, bytes);
407 hmm_bo_vunmap(bo);
408 }
409
410 return 0;
411 }
412
413 /* Read function in ISP memory management */
hmm_load(ia_css_ptr virt,void * data,unsigned int bytes)414 int hmm_load(ia_css_ptr virt, void *data, unsigned int bytes)
415 {
416 if (!virt) {
417 dev_warn(atomisp_dev,
418 "hmm_store: address is NULL\n");
419 return -EINVAL;
420 }
421 if (!data) {
422 dev_err(atomisp_dev,
423 "hmm_store: data is a NULL argument\n");
424 return -EINVAL;
425 }
426 return load_and_flush(virt, data, bytes);
427 }
428
429 /* Flush hmm data from the data cache */
hmm_flush(ia_css_ptr virt,unsigned int bytes)430 int hmm_flush(ia_css_ptr virt, unsigned int bytes)
431 {
432 return load_and_flush(virt, NULL, bytes);
433 }
434
435 /* Write function in ISP memory management */
hmm_store(ia_css_ptr virt,const void * data,unsigned int bytes)436 int hmm_store(ia_css_ptr virt, const void *data, unsigned int bytes)
437 {
438 struct hmm_buffer_object *bo;
439 unsigned int idx, offset, len;
440 char *src, *des;
441 int ret;
442
443 if (!virt) {
444 dev_warn(atomisp_dev,
445 "hmm_store: address is NULL\n");
446 return -EINVAL;
447 }
448 if (!data) {
449 dev_err(atomisp_dev,
450 "hmm_store: data is a NULL argument\n");
451 return -EINVAL;
452 }
453
454 bo = hmm_bo_device_search_in_range(&bo_device, virt);
455 ret = hmm_check_bo(bo, virt);
456 if (ret)
457 return ret;
458
459 if (bo->status & HMM_BO_VMAPED || bo->status & HMM_BO_VMAPED_CACHED) {
460 void *dst = bo->vmap_addr;
461
462 dst += (virt - bo->start);
463 memcpy(dst, data, bytes);
464 if (bo->status & HMM_BO_VMAPED_CACHED)
465 clflush_cache_range(dst, bytes);
466 } else {
467 void *vptr;
468
469 vptr = hmm_bo_vmap(bo, true);
470 if (vptr) {
471 vptr = vptr + (virt - bo->start);
472
473 memcpy(vptr, data, bytes);
474 clflush_cache_range(vptr, bytes);
475 hmm_bo_vunmap(bo);
476 return 0;
477 }
478 }
479
480 src = (char *)data;
481 while (bytes) {
482 idx = (virt - bo->start) >> PAGE_SHIFT;
483 offset = (virt - bo->start) - (idx << PAGE_SHIFT);
484
485 if (in_atomic())
486 des = (char *)kmap_atomic(bo->page_obj[idx].page);
487 else
488 des = (char *)kmap(bo->page_obj[idx].page);
489
490 if (!des) {
491 dev_err(atomisp_dev,
492 "kmap buffer object page failed: pg_idx = %d\n",
493 idx);
494 return -EINVAL;
495 }
496
497 des += offset;
498
499 if ((bytes + offset) >= PAGE_SIZE) {
500 len = PAGE_SIZE - offset;
501 bytes -= len;
502 } else {
503 len = bytes;
504 bytes = 0;
505 }
506
507 virt += len;
508
509 memcpy(des, src, len);
510
511 src += len;
512
513 clflush_cache_range(des, len);
514
515 if (in_atomic())
516 /*
517 * Note: kunmap_atomic requires return addr from
518 * kmap_atomic, not the page. See linux/highmem.h
519 */
520 kunmap_atomic(des - offset);
521 else
522 kunmap(bo->page_obj[idx].page);
523 }
524
525 return 0;
526 }
527
528 /* memset function in ISP memory management */
hmm_set(ia_css_ptr virt,int c,unsigned int bytes)529 int hmm_set(ia_css_ptr virt, int c, unsigned int bytes)
530 {
531 struct hmm_buffer_object *bo;
532 unsigned int idx, offset, len;
533 char *des;
534 int ret;
535
536 bo = hmm_bo_device_search_in_range(&bo_device, virt);
537 ret = hmm_check_bo(bo, virt);
538 if (ret)
539 return ret;
540
541 if (bo->status & HMM_BO_VMAPED || bo->status & HMM_BO_VMAPED_CACHED) {
542 void *dst = bo->vmap_addr;
543
544 dst += (virt - bo->start);
545 memset(dst, c, bytes);
546
547 if (bo->status & HMM_BO_VMAPED_CACHED)
548 clflush_cache_range(dst, bytes);
549 } else {
550 void *vptr;
551
552 vptr = hmm_bo_vmap(bo, true);
553 if (vptr) {
554 vptr = vptr + (virt - bo->start);
555 memset(vptr, c, bytes);
556 clflush_cache_range(vptr, bytes);
557 hmm_bo_vunmap(bo);
558 return 0;
559 }
560 }
561
562 while (bytes) {
563 idx = (virt - bo->start) >> PAGE_SHIFT;
564 offset = (virt - bo->start) - (idx << PAGE_SHIFT);
565
566 des = (char *)kmap(bo->page_obj[idx].page) + offset;
567
568 if ((bytes + offset) >= PAGE_SIZE) {
569 len = PAGE_SIZE - offset;
570 bytes -= len;
571 } else {
572 len = bytes;
573 bytes = 0;
574 }
575
576 virt += len;
577
578 memset(des, c, len);
579
580 clflush_cache_range(des, len);
581
582 kunmap(bo->page_obj[idx].page);
583 }
584
585 return 0;
586 }
587
588 /* Virtual address to physical address convert */
hmm_virt_to_phys(ia_css_ptr virt)589 phys_addr_t hmm_virt_to_phys(ia_css_ptr virt)
590 {
591 unsigned int idx, offset;
592 struct hmm_buffer_object *bo;
593
594 bo = hmm_bo_device_search_in_range(&bo_device, virt);
595 if (!bo) {
596 dev_err(atomisp_dev,
597 "can not find buffer object contains address 0x%x\n",
598 virt);
599 return -1;
600 }
601
602 idx = (virt - bo->start) >> PAGE_SHIFT;
603 offset = (virt - bo->start) - (idx << PAGE_SHIFT);
604
605 return page_to_phys(bo->page_obj[idx].page) + offset;
606 }
607
hmm_mmap(struct vm_area_struct * vma,ia_css_ptr virt)608 int hmm_mmap(struct vm_area_struct *vma, ia_css_ptr virt)
609 {
610 struct hmm_buffer_object *bo;
611
612 bo = hmm_bo_device_search_start(&bo_device, virt);
613 if (!bo) {
614 dev_err(atomisp_dev,
615 "can not find buffer object start with address 0x%x\n",
616 virt);
617 return -EINVAL;
618 }
619
620 return hmm_bo_mmap(vma, bo);
621 }
622
623 /* Map ISP virtual address into IA virtual address */
hmm_vmap(ia_css_ptr virt,bool cached)624 void *hmm_vmap(ia_css_ptr virt, bool cached)
625 {
626 struct hmm_buffer_object *bo;
627 void *ptr;
628
629 bo = hmm_bo_device_search_in_range(&bo_device, virt);
630 if (!bo) {
631 dev_err(atomisp_dev,
632 "can not find buffer object contains address 0x%x\n",
633 virt);
634 return NULL;
635 }
636
637 ptr = hmm_bo_vmap(bo, cached);
638 if (ptr)
639 return ptr + (virt - bo->start);
640 else
641 return NULL;
642 }
643
644 /* Flush the memory which is mapped as cached memory through hmm_vmap */
hmm_flush_vmap(ia_css_ptr virt)645 void hmm_flush_vmap(ia_css_ptr virt)
646 {
647 struct hmm_buffer_object *bo;
648
649 bo = hmm_bo_device_search_in_range(&bo_device, virt);
650 if (!bo) {
651 dev_warn(atomisp_dev,
652 "can not find buffer object contains address 0x%x\n",
653 virt);
654 return;
655 }
656
657 hmm_bo_flush_vmap(bo);
658 }
659
hmm_vunmap(ia_css_ptr virt)660 void hmm_vunmap(ia_css_ptr virt)
661 {
662 struct hmm_buffer_object *bo;
663
664 bo = hmm_bo_device_search_in_range(&bo_device, virt);
665 if (!bo) {
666 dev_warn(atomisp_dev,
667 "can not find buffer object contains address 0x%x\n",
668 virt);
669 return;
670 }
671
672 hmm_bo_vunmap(bo);
673 }
674
hmm_pool_register(unsigned int pool_size,enum hmm_pool_type pool_type)675 int hmm_pool_register(unsigned int pool_size, enum hmm_pool_type pool_type)
676 {
677 #if 0 // Just use the "normal" pool
678 switch (pool_type) {
679 case HMM_POOL_TYPE_RESERVED:
680 reserved_pool.pops = &reserved_pops;
681 return reserved_pool.pops->pool_init(&reserved_pool.pool_info,
682 pool_size);
683 case HMM_POOL_TYPE_DYNAMIC:
684 dynamic_pool.pops = &dynamic_pops;
685 return dynamic_pool.pops->pool_init(&dynamic_pool.pool_info,
686 pool_size);
687 default:
688 dev_err(atomisp_dev, "invalid pool type.\n");
689 return -EINVAL;
690 }
691 #else
692 return 0;
693 #endif
694 }
695
hmm_pool_unregister(enum hmm_pool_type pool_type)696 void hmm_pool_unregister(enum hmm_pool_type pool_type)
697 {
698 #if 0 // Just use the "normal" pool
699 switch (pool_type) {
700 case HMM_POOL_TYPE_RESERVED:
701 if (reserved_pool.pops && reserved_pool.pops->pool_exit)
702 reserved_pool.pops->pool_exit(&reserved_pool.pool_info);
703 break;
704 case HMM_POOL_TYPE_DYNAMIC:
705 if (dynamic_pool.pops && dynamic_pool.pops->pool_exit)
706 dynamic_pool.pops->pool_exit(&dynamic_pool.pool_info);
707 break;
708 default:
709 dev_err(atomisp_dev, "invalid pool type.\n");
710 break;
711 }
712 #endif
713
714 return;
715 }
716
hmm_isp_vaddr_to_host_vaddr(ia_css_ptr ptr,bool cached)717 void *hmm_isp_vaddr_to_host_vaddr(ia_css_ptr ptr, bool cached)
718 {
719 return hmm_vmap(ptr, cached);
720 /* vmunmap will be done in hmm_bo_release() */
721 }
722
hmm_host_vaddr_to_hrt_vaddr(const void * ptr)723 ia_css_ptr hmm_host_vaddr_to_hrt_vaddr(const void *ptr)
724 {
725 struct hmm_buffer_object *bo;
726
727 bo = hmm_bo_device_search_vmap_start(&bo_device, ptr);
728 if (bo)
729 return bo->start;
730
731 dev_err(atomisp_dev,
732 "can not find buffer object whose kernel virtual address is %p\n",
733 ptr);
734 return 0;
735 }
736
hmm_show_mem_stat(const char * func,const int line)737 void hmm_show_mem_stat(const char *func, const int line)
738 {
739 pr_info("tol_cnt=%d usr_size=%d res_size=%d res_cnt=%d sys_size=%d dyc_thr=%d dyc_size=%d.\n",
740 hmm_mem_stat.tol_cnt,
741 hmm_mem_stat.usr_size, hmm_mem_stat.res_size,
742 hmm_mem_stat.res_cnt, hmm_mem_stat.sys_size,
743 hmm_mem_stat.dyc_thr, hmm_mem_stat.dyc_size);
744 }
745
hmm_init_mem_stat(int res_pgnr,int dyc_en,int dyc_pgnr)746 void hmm_init_mem_stat(int res_pgnr, int dyc_en, int dyc_pgnr)
747 {
748 hmm_mem_stat.res_size = res_pgnr;
749 /* If reserved mem pool is not enabled, set its "mem stat" values as -1. */
750 if (hmm_mem_stat.res_size == 0) {
751 hmm_mem_stat.res_size = -1;
752 hmm_mem_stat.res_cnt = -1;
753 }
754
755 /* If dynamic memory pool is not enabled, set its "mem stat" values as -1. */
756 if (!dyc_en) {
757 hmm_mem_stat.dyc_size = -1;
758 hmm_mem_stat.dyc_thr = -1;
759 } else {
760 hmm_mem_stat.dyc_size = 0;
761 hmm_mem_stat.dyc_thr = dyc_pgnr;
762 }
763 hmm_mem_stat.usr_size = 0;
764 hmm_mem_stat.sys_size = 0;
765 hmm_mem_stat.tol_cnt = 0;
766 }
767