1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32#include <linux/types.h>
33#include <linux/list.h>
34
35
36#include <dspbridge/dbdefs.h>
37
38
39#include <dspbridge/dbc.h>
40
41
42#include <dspbridge/sync.h>
43
44
45#include <dspbridge/dev.h>
46#include <dspbridge/proc.h>
47
48
49#include <dspbridge/cmm.h>
50
51
52#define NEXT_PA(pnode) (pnode->pa + pnode->size)
53
54
55#define DSPPA2GPPPA(base, x, y) ((x)+(y))
56#define GPPPA2DSPPA(base, x, y) ((x)-(y))
57
58
59
60
61
62
63
64struct cmm_allocator {
65 unsigned int shm_base;
66 u32 sm_size;
67 unsigned int vm_base;
68
69 u32 dsp_phys_addr_offset;
70
71 s8 c_factor;
72 unsigned int dsp_base;
73 u32 dsp_size;
74 struct cmm_object *cmm_mgr;
75
76 struct list_head free_list;
77
78 struct list_head in_use_list;
79};
80
81struct cmm_xlator {
82
83 struct cmm_object *cmm_mgr;
84
85
86
87
88
89 unsigned int virt_base;
90 u32 virt_size;
91 u32 seg_id;
92};
93
94
95struct cmm_object {
96
97
98
99 struct mutex cmm_lock;
100 struct list_head node_free_list;
101 u32 min_block_size;
102 u32 page_size;
103
104 struct cmm_allocator *pa_gppsm_seg_tab[CMM_MAXGPPSEGS];
105};
106
107
108static struct cmm_mgrattrs cmm_dfltmgrattrs = {
109
110 16
111};
112
113
114static struct cmm_attrs cmm_dfltalctattrs = {
115 1
116};
117
118
119static struct cmm_xlatorattrs cmm_dfltxlatorattrs = {
120
121 1,
122 0,
123 0,
124 NULL,
125 0,
126};
127
128
129struct cmm_mnode {
130 struct list_head link;
131 u32 pa;
132 u32 va;
133 u32 size;
134 u32 client_proc;
135};
136
137
138static u32 refs;
139
140
141static void add_to_free_list(struct cmm_allocator *allocator,
142 struct cmm_mnode *pnode);
143static struct cmm_allocator *get_allocator(struct cmm_object *cmm_mgr_obj,
144 u32 ul_seg_id);
145static struct cmm_mnode *get_free_block(struct cmm_allocator *allocator,
146 u32 usize);
147static struct cmm_mnode *get_node(struct cmm_object *cmm_mgr_obj, u32 dw_pa,
148 u32 dw_va, u32 ul_size);
149
150static s32 get_slot(struct cmm_object *cmm_mgr_obj);
151static void un_register_gppsm_seg(struct cmm_allocator *psma);
152
153
154
155
156
157
158
159
160
161
162
163
164void *cmm_calloc_buf(struct cmm_object *hcmm_mgr, u32 usize,
165 struct cmm_attrs *pattrs, void **pp_buf_va)
166{
167 struct cmm_object *cmm_mgr_obj = (struct cmm_object *)hcmm_mgr;
168 void *buf_pa = NULL;
169 struct cmm_mnode *pnode = NULL;
170 struct cmm_mnode *new_node = NULL;
171 struct cmm_allocator *allocator = NULL;
172 u32 delta_size;
173 u8 *pbyte = NULL;
174 s32 cnt;
175
176 if (pattrs == NULL)
177 pattrs = &cmm_dfltalctattrs;
178
179 if (pp_buf_va != NULL)
180 *pp_buf_va = NULL;
181
182 if (cmm_mgr_obj && (usize != 0)) {
183 if (pattrs->seg_id > 0) {
184
185
186 allocator =
187 get_allocator(cmm_mgr_obj, pattrs->seg_id);
188
189 usize =
190 ((usize - 1) & ~(cmm_mgr_obj->min_block_size -
191 1))
192 + cmm_mgr_obj->min_block_size;
193 mutex_lock(&cmm_mgr_obj->cmm_lock);
194 pnode = get_free_block(allocator, usize);
195 }
196 if (pnode) {
197 delta_size = (pnode->size - usize);
198 if (delta_size >= cmm_mgr_obj->min_block_size) {
199
200
201 new_node =
202 get_node(cmm_mgr_obj, pnode->pa + usize,
203 pnode->va + usize,
204 (u32) delta_size);
205
206 add_to_free_list(allocator, new_node);
207
208 pnode->size = usize;
209 }
210
211
212
213
214
215 pnode->client_proc = current->tgid;
216
217
218 list_add_tail(&pnode->link, &allocator->in_use_list);
219 buf_pa = (void *)pnode->pa;
220
221 pbyte = (u8 *) pnode->va;
222 for (cnt = 0; cnt < (s32) usize; cnt++, pbyte++)
223 *pbyte = 0;
224
225 if (pp_buf_va != NULL) {
226
227 *pp_buf_va = (void *)pnode->va;
228 }
229 }
230 mutex_unlock(&cmm_mgr_obj->cmm_lock);
231 }
232 return buf_pa;
233}
234
235
236
237
238
239
240int cmm_create(struct cmm_object **ph_cmm_mgr,
241 struct dev_object *hdev_obj,
242 const struct cmm_mgrattrs *mgr_attrts)
243{
244 struct cmm_object *cmm_obj = NULL;
245 int status = 0;
246
247 DBC_REQUIRE(refs > 0);
248 DBC_REQUIRE(ph_cmm_mgr != NULL);
249
250 *ph_cmm_mgr = NULL;
251
252 cmm_obj = kzalloc(sizeof(struct cmm_object), GFP_KERNEL);
253 if (!cmm_obj)
254 return -ENOMEM;
255
256 if (mgr_attrts == NULL)
257 mgr_attrts = &cmm_dfltmgrattrs;
258
259
260 DBC_ASSERT(mgr_attrts->min_block_size >= 4);
261
262 cmm_obj->min_block_size = mgr_attrts->min_block_size;
263 cmm_obj->page_size = PAGE_SIZE;
264
265
266 INIT_LIST_HEAD(&cmm_obj->node_free_list);
267 mutex_init(&cmm_obj->cmm_lock);
268 *ph_cmm_mgr = cmm_obj;
269
270 return status;
271}
272
273
274
275
276
277
278int cmm_destroy(struct cmm_object *hcmm_mgr, bool force)
279{
280 struct cmm_object *cmm_mgr_obj = (struct cmm_object *)hcmm_mgr;
281 struct cmm_info temp_info;
282 int status = 0;
283 s32 slot_seg;
284 struct cmm_mnode *node, *tmp;
285
286 DBC_REQUIRE(refs > 0);
287 if (!hcmm_mgr) {
288 status = -EFAULT;
289 return status;
290 }
291 mutex_lock(&cmm_mgr_obj->cmm_lock);
292
293 if (!force) {
294
295 status = cmm_get_info(hcmm_mgr, &temp_info);
296 if (!status) {
297 if (temp_info.total_in_use_cnt > 0) {
298
299 status = -EPERM;
300 }
301 }
302 }
303 if (!status) {
304
305 for (slot_seg = 0; slot_seg < CMM_MAXGPPSEGS; slot_seg++) {
306 if (cmm_mgr_obj->pa_gppsm_seg_tab[slot_seg] != NULL) {
307 un_register_gppsm_seg
308 (cmm_mgr_obj->pa_gppsm_seg_tab[slot_seg]);
309
310 cmm_mgr_obj->pa_gppsm_seg_tab[slot_seg] = NULL;
311 }
312 }
313 }
314 list_for_each_entry_safe(node, tmp, &cmm_mgr_obj->node_free_list,
315 link) {
316 list_del(&node->link);
317 kfree(node);
318 }
319 mutex_unlock(&cmm_mgr_obj->cmm_lock);
320 if (!status) {
321
322 mutex_destroy(&cmm_mgr_obj->cmm_lock);
323 kfree(cmm_mgr_obj);
324 }
325 return status;
326}
327
328
329
330
331
332
333
334void cmm_exit(void)
335{
336 DBC_REQUIRE(refs > 0);
337
338 refs--;
339}
340
341
342
343
344
345
346int cmm_free_buf(struct cmm_object *hcmm_mgr, void *buf_pa, u32 ul_seg_id)
347{
348 struct cmm_object *cmm_mgr_obj = (struct cmm_object *)hcmm_mgr;
349 int status = -EFAULT;
350 struct cmm_mnode *curr, *tmp;
351 struct cmm_allocator *allocator;
352 struct cmm_attrs *pattrs;
353
354 DBC_REQUIRE(refs > 0);
355 DBC_REQUIRE(buf_pa != NULL);
356
357 if (ul_seg_id == 0) {
358 pattrs = &cmm_dfltalctattrs;
359 ul_seg_id = pattrs->seg_id;
360 }
361 if (!hcmm_mgr || !(ul_seg_id > 0)) {
362 status = -EFAULT;
363 return status;
364 }
365
366 allocator = get_allocator(cmm_mgr_obj, ul_seg_id);
367 if (!allocator)
368 return status;
369
370 mutex_lock(&cmm_mgr_obj->cmm_lock);
371 list_for_each_entry_safe(curr, tmp, &allocator->in_use_list, link) {
372 if (curr->pa == (u32) buf_pa) {
373 list_del(&curr->link);
374 add_to_free_list(allocator, curr);
375 status = 0;
376 break;
377 }
378 }
379 mutex_unlock(&cmm_mgr_obj->cmm_lock);
380
381 return status;
382}
383
384
385
386
387
388
389
390int cmm_get_handle(void *hprocessor, struct cmm_object ** ph_cmm_mgr)
391{
392 int status = 0;
393 struct dev_object *hdev_obj;
394
395 DBC_REQUIRE(refs > 0);
396 DBC_REQUIRE(ph_cmm_mgr != NULL);
397 if (hprocessor != NULL)
398 status = proc_get_dev_object(hprocessor, &hdev_obj);
399 else
400 hdev_obj = dev_get_first();
401
402 if (!status)
403 status = dev_get_cmm_mgr(hdev_obj, ph_cmm_mgr);
404
405 return status;
406}
407
408
409
410
411
412
413int cmm_get_info(struct cmm_object *hcmm_mgr,
414 struct cmm_info *cmm_info_obj)
415{
416 struct cmm_object *cmm_mgr_obj = (struct cmm_object *)hcmm_mgr;
417 u32 ul_seg;
418 int status = 0;
419 struct cmm_allocator *altr;
420 struct cmm_mnode *curr;
421
422 DBC_REQUIRE(cmm_info_obj != NULL);
423
424 if (!hcmm_mgr) {
425 status = -EFAULT;
426 return status;
427 }
428 mutex_lock(&cmm_mgr_obj->cmm_lock);
429 cmm_info_obj->num_gppsm_segs = 0;
430
431 cmm_info_obj->total_in_use_cnt = 0;
432
433 cmm_info_obj->min_block_size = cmm_mgr_obj->min_block_size;
434
435 for (ul_seg = 1; ul_seg <= CMM_MAXGPPSEGS; ul_seg++) {
436
437 altr = get_allocator(cmm_mgr_obj, ul_seg);
438 if (!altr)
439 continue;
440 cmm_info_obj->num_gppsm_segs++;
441 cmm_info_obj->seg_info[ul_seg - 1].seg_base_pa =
442 altr->shm_base - altr->dsp_size;
443 cmm_info_obj->seg_info[ul_seg - 1].total_seg_size =
444 altr->dsp_size + altr->sm_size;
445 cmm_info_obj->seg_info[ul_seg - 1].gpp_base_pa =
446 altr->shm_base;
447 cmm_info_obj->seg_info[ul_seg - 1].gpp_size =
448 altr->sm_size;
449 cmm_info_obj->seg_info[ul_seg - 1].dsp_base_va =
450 altr->dsp_base;
451 cmm_info_obj->seg_info[ul_seg - 1].dsp_size =
452 altr->dsp_size;
453 cmm_info_obj->seg_info[ul_seg - 1].seg_base_va =
454 altr->vm_base - altr->dsp_size;
455 cmm_info_obj->seg_info[ul_seg - 1].in_use_cnt = 0;
456
457 list_for_each_entry(curr, &altr->in_use_list, link) {
458 cmm_info_obj->total_in_use_cnt++;
459 cmm_info_obj->seg_info[ul_seg - 1].in_use_cnt++;
460 }
461 }
462 mutex_unlock(&cmm_mgr_obj->cmm_lock);
463 return status;
464}
465
466
467
468
469
470
471bool cmm_init(void)
472{
473 bool ret = true;
474
475 DBC_REQUIRE(refs >= 0);
476 if (ret)
477 refs++;
478
479 DBC_ENSURE((ret && (refs > 0)) || (!ret && (refs >= 0)));
480
481 return ret;
482}
483
484
485
486
487
488
489
490int cmm_register_gppsm_seg(struct cmm_object *hcmm_mgr,
491 u32 dw_gpp_base_pa, u32 ul_size,
492 u32 dsp_addr_offset, s8 c_factor,
493 u32 dw_dsp_base, u32 ul_dsp_size,
494 u32 *sgmt_id, u32 gpp_base_va)
495{
496 struct cmm_object *cmm_mgr_obj = (struct cmm_object *)hcmm_mgr;
497 struct cmm_allocator *psma = NULL;
498 int status = 0;
499 struct cmm_mnode *new_node;
500 s32 slot_seg;
501
502 DBC_REQUIRE(ul_size > 0);
503 DBC_REQUIRE(sgmt_id != NULL);
504 DBC_REQUIRE(dw_gpp_base_pa != 0);
505 DBC_REQUIRE(gpp_base_va != 0);
506 DBC_REQUIRE((c_factor <= CMM_ADDTODSPPA) &&
507 (c_factor >= CMM_SUBFROMDSPPA));
508
509 dev_dbg(bridge, "%s: dw_gpp_base_pa %x ul_size %x dsp_addr_offset %x "
510 "dw_dsp_base %x ul_dsp_size %x gpp_base_va %x\n",
511 __func__, dw_gpp_base_pa, ul_size, dsp_addr_offset,
512 dw_dsp_base, ul_dsp_size, gpp_base_va);
513
514 if (!hcmm_mgr)
515 return -EFAULT;
516
517
518 mutex_lock(&cmm_mgr_obj->cmm_lock);
519
520 slot_seg = get_slot(cmm_mgr_obj);
521 if (slot_seg < 0) {
522 status = -EPERM;
523 goto func_end;
524 }
525
526
527 if (ul_size < cmm_mgr_obj->min_block_size) {
528 status = -EINVAL;
529 goto func_end;
530 }
531
532
533 psma = kzalloc(sizeof(struct cmm_allocator), GFP_KERNEL);
534 if (!psma) {
535 status = -ENOMEM;
536 goto func_end;
537 }
538
539 psma->cmm_mgr = hcmm_mgr;
540 psma->shm_base = dw_gpp_base_pa;
541 psma->sm_size = ul_size;
542 psma->vm_base = gpp_base_va;
543 psma->dsp_phys_addr_offset = dsp_addr_offset;
544 psma->c_factor = c_factor;
545 psma->dsp_base = dw_dsp_base;
546 psma->dsp_size = ul_dsp_size;
547 if (psma->vm_base == 0) {
548 status = -EPERM;
549 goto func_end;
550 }
551
552 *sgmt_id = (u32) slot_seg + 1;
553
554 INIT_LIST_HEAD(&psma->free_list);
555 INIT_LIST_HEAD(&psma->in_use_list);
556
557
558 new_node = get_node(cmm_mgr_obj, dw_gpp_base_pa,
559 psma->vm_base, ul_size);
560
561 if (new_node) {
562 list_add_tail(&new_node->link, &psma->free_list);
563 } else {
564 status = -ENOMEM;
565 goto func_end;
566 }
567
568 cmm_mgr_obj->pa_gppsm_seg_tab[slot_seg] = psma;
569
570func_end:
571
572 if (status && psma)
573 un_register_gppsm_seg(psma);
574 mutex_unlock(&cmm_mgr_obj->cmm_lock);
575
576 return status;
577}
578
579
580
581
582
583
584int cmm_un_register_gppsm_seg(struct cmm_object *hcmm_mgr,
585 u32 ul_seg_id)
586{
587 struct cmm_object *cmm_mgr_obj = (struct cmm_object *)hcmm_mgr;
588 int status = 0;
589 struct cmm_allocator *psma;
590 u32 ul_id = ul_seg_id;
591
592 DBC_REQUIRE(ul_seg_id > 0);
593 if (!hcmm_mgr)
594 return -EFAULT;
595
596 if (ul_seg_id == CMM_ALLSEGMENTS)
597 ul_id = 1;
598
599 if ((ul_id <= 0) || (ul_id > CMM_MAXGPPSEGS))
600 return -EINVAL;
601
602
603
604
605
606 while (ul_id <= CMM_MAXGPPSEGS) {
607 mutex_lock(&cmm_mgr_obj->cmm_lock);
608
609 psma = cmm_mgr_obj->pa_gppsm_seg_tab[ul_id - 1];
610 if (psma != NULL) {
611 un_register_gppsm_seg(psma);
612
613 cmm_mgr_obj->pa_gppsm_seg_tab[ul_id - 1] = NULL;
614 } else if (ul_seg_id != CMM_ALLSEGMENTS) {
615 status = -EPERM;
616 }
617 mutex_unlock(&cmm_mgr_obj->cmm_lock);
618 if (ul_seg_id != CMM_ALLSEGMENTS)
619 break;
620
621 ul_id++;
622 }
623 return status;
624}
625
626
627
628
629
630
631
632
633
634static void un_register_gppsm_seg(struct cmm_allocator *psma)
635{
636 struct cmm_mnode *curr, *tmp;
637
638 DBC_REQUIRE(psma != NULL);
639
640
641 list_for_each_entry_safe(curr, tmp, &psma->free_list, link) {
642 list_del(&curr->link);
643 kfree(curr);
644 }
645
646
647 list_for_each_entry_safe(curr, tmp, &psma->in_use_list, link) {
648 list_del(&curr->link);
649 kfree(curr);
650 }
651
652 if ((void *)psma->vm_base != NULL)
653 MEM_UNMAP_LINEAR_ADDRESS((void *)psma->vm_base);
654
655
656 kfree(psma);
657}
658
659
660
661
662
663
664static s32 get_slot(struct cmm_object *cmm_mgr_obj)
665{
666 s32 slot_seg = -1;
667 DBC_REQUIRE(cmm_mgr_obj != NULL);
668
669 for (slot_seg = 0; slot_seg < CMM_MAXGPPSEGS; slot_seg++) {
670 if (cmm_mgr_obj->pa_gppsm_seg_tab[slot_seg] == NULL)
671 break;
672
673 }
674 if (slot_seg == CMM_MAXGPPSEGS)
675 slot_seg = -1;
676
677 return slot_seg;
678}
679
680
681
682
683
684
685static struct cmm_mnode *get_node(struct cmm_object *cmm_mgr_obj, u32 dw_pa,
686 u32 dw_va, u32 ul_size)
687{
688 struct cmm_mnode *pnode;
689
690 DBC_REQUIRE(cmm_mgr_obj != NULL);
691 DBC_REQUIRE(dw_pa != 0);
692 DBC_REQUIRE(dw_va != 0);
693 DBC_REQUIRE(ul_size != 0);
694
695
696 if (list_empty(&cmm_mgr_obj->node_free_list)) {
697 pnode = kzalloc(sizeof(struct cmm_mnode), GFP_KERNEL);
698 if (!pnode)
699 return NULL;
700 } else {
701
702 pnode = list_first_entry(&cmm_mgr_obj->node_free_list,
703 struct cmm_mnode, link);
704 list_del_init(&pnode->link);
705 }
706
707 pnode->pa = dw_pa;
708 pnode->va = dw_va;
709 pnode->size = ul_size;
710
711 return pnode;
712}
713
714
715
716
717
718
719
720static void delete_node(struct cmm_object *cmm_mgr_obj, struct cmm_mnode *pnode)
721{
722 DBC_REQUIRE(pnode != NULL);
723 list_add_tail(&pnode->link, &cmm_mgr_obj->node_free_list);
724}
725
726
727
728
729
730
731
732static struct cmm_mnode *get_free_block(struct cmm_allocator *allocator,
733 u32 usize)
734{
735 struct cmm_mnode *node, *tmp;
736
737 if (!allocator)
738 return NULL;
739
740 list_for_each_entry_safe(node, tmp, &allocator->free_list, link) {
741 if (usize <= node->size) {
742 list_del(&node->link);
743 return node;
744 }
745 }
746
747 return NULL;
748}
749
750
751
752
753
754
755static void add_to_free_list(struct cmm_allocator *allocator,
756 struct cmm_mnode *node)
757{
758 struct cmm_mnode *curr;
759
760 if (!node) {
761 pr_err("%s: failed - node is NULL\n", __func__);
762 return;
763 }
764
765 list_for_each_entry(curr, &allocator->free_list, link) {
766 if (NEXT_PA(curr) == node->pa) {
767 curr->size += node->size;
768 delete_node(allocator->cmm_mgr, node);
769 return;
770 }
771 if (curr->pa == NEXT_PA(node)) {
772 curr->pa = node->pa;
773 curr->va = node->va;
774 curr->size += node->size;
775 delete_node(allocator->cmm_mgr, node);
776 return;
777 }
778 }
779 list_for_each_entry(curr, &allocator->free_list, link) {
780 if (curr->size >= node->size) {
781 list_add_tail(&node->link, &curr->link);
782 return;
783 }
784 }
785 list_add_tail(&node->link, &allocator->free_list);
786}
787
788
789
790
791
792
793
794static struct cmm_allocator *get_allocator(struct cmm_object *cmm_mgr_obj,
795 u32 ul_seg_id)
796{
797 DBC_REQUIRE(cmm_mgr_obj != NULL);
798 DBC_REQUIRE((ul_seg_id > 0) && (ul_seg_id <= CMM_MAXGPPSEGS));
799
800 return cmm_mgr_obj->pa_gppsm_seg_tab[ul_seg_id - 1];
801}
802
803
804
805
806
807
808
809
810
811
812
813
814int cmm_xlator_create(struct cmm_xlatorobject **xlator,
815 struct cmm_object *hcmm_mgr,
816 struct cmm_xlatorattrs *xlator_attrs)
817{
818 struct cmm_xlator *xlator_object = NULL;
819 int status = 0;
820
821 DBC_REQUIRE(refs > 0);
822 DBC_REQUIRE(xlator != NULL);
823 DBC_REQUIRE(hcmm_mgr != NULL);
824
825 *xlator = NULL;
826 if (xlator_attrs == NULL)
827 xlator_attrs = &cmm_dfltxlatorattrs;
828
829 xlator_object = kzalloc(sizeof(struct cmm_xlator), GFP_KERNEL);
830 if (xlator_object != NULL) {
831 xlator_object->cmm_mgr = hcmm_mgr;
832
833 xlator_object->seg_id = xlator_attrs->seg_id;
834 } else {
835 status = -ENOMEM;
836 }
837 if (!status)
838 *xlator = (struct cmm_xlatorobject *)xlator_object;
839
840 return status;
841}
842
843
844
845
846void *cmm_xlator_alloc_buf(struct cmm_xlatorobject *xlator, void *va_buf,
847 u32 pa_size)
848{
849 struct cmm_xlator *xlator_obj = (struct cmm_xlator *)xlator;
850 void *pbuf = NULL;
851 void *tmp_va_buff;
852 struct cmm_attrs attrs;
853
854 DBC_REQUIRE(refs > 0);
855 DBC_REQUIRE(xlator != NULL);
856 DBC_REQUIRE(xlator_obj->cmm_mgr != NULL);
857 DBC_REQUIRE(va_buf != NULL);
858 DBC_REQUIRE(pa_size > 0);
859 DBC_REQUIRE(xlator_obj->seg_id > 0);
860
861 if (xlator_obj) {
862 attrs.seg_id = xlator_obj->seg_id;
863 __raw_writel(0, va_buf);
864
865 pbuf =
866 cmm_calloc_buf(xlator_obj->cmm_mgr, pa_size, &attrs, NULL);
867 if (pbuf) {
868
869
870 tmp_va_buff = cmm_xlator_translate(xlator,
871 pbuf, CMM_PA2VA);
872 __raw_writel((u32)tmp_va_buff, va_buf);
873 }
874 }
875 return pbuf;
876}
877
878
879
880
881
882
883
884int cmm_xlator_free_buf(struct cmm_xlatorobject *xlator, void *buf_va)
885{
886 struct cmm_xlator *xlator_obj = (struct cmm_xlator *)xlator;
887 int status = -EPERM;
888 void *buf_pa = NULL;
889
890 DBC_REQUIRE(refs > 0);
891 DBC_REQUIRE(buf_va != NULL);
892 DBC_REQUIRE(xlator_obj->seg_id > 0);
893
894 if (xlator_obj) {
895
896 buf_pa = cmm_xlator_translate(xlator, buf_va, CMM_VA2PA);
897 if (buf_pa) {
898 status = cmm_free_buf(xlator_obj->cmm_mgr, buf_pa,
899 xlator_obj->seg_id);
900 if (status) {
901
902
903 DBC_ASSERT(false);
904 }
905 }
906 }
907 return status;
908}
909
910
911
912
913
914
915int cmm_xlator_info(struct cmm_xlatorobject *xlator, u8 ** paddr,
916 u32 ul_size, u32 segm_id, bool set_info)
917{
918 struct cmm_xlator *xlator_obj = (struct cmm_xlator *)xlator;
919 int status = 0;
920
921 DBC_REQUIRE(refs > 0);
922 DBC_REQUIRE(paddr != NULL);
923 DBC_REQUIRE((segm_id > 0) && (segm_id <= CMM_MAXGPPSEGS));
924
925 if (xlator_obj) {
926 if (set_info) {
927
928 xlator_obj->virt_base = (u32) *paddr;
929 xlator_obj->virt_size = ul_size;
930 } else {
931 *paddr = (u8 *) xlator_obj->virt_base;
932 }
933 } else {
934 status = -EFAULT;
935 }
936 return status;
937}
938
939
940
941
942void *cmm_xlator_translate(struct cmm_xlatorobject *xlator, void *paddr,
943 enum cmm_xlatetype xtype)
944{
945 u32 dw_addr_xlate = 0;
946 struct cmm_xlator *xlator_obj = (struct cmm_xlator *)xlator;
947 struct cmm_object *cmm_mgr_obj = NULL;
948 struct cmm_allocator *allocator = NULL;
949 u32 dw_offset = 0;
950
951 DBC_REQUIRE(refs > 0);
952 DBC_REQUIRE(paddr != NULL);
953 DBC_REQUIRE((xtype >= CMM_VA2PA) && (xtype <= CMM_DSPPA2PA));
954
955 if (!xlator_obj)
956 goto loop_cont;
957
958 cmm_mgr_obj = (struct cmm_object *)xlator_obj->cmm_mgr;
959
960 DBC_ASSERT(xlator_obj->seg_id > 0);
961 allocator = cmm_mgr_obj->pa_gppsm_seg_tab[xlator_obj->seg_id - 1];
962 if (!allocator)
963 goto loop_cont;
964
965 if ((xtype == CMM_VA2DSPPA) || (xtype == CMM_VA2PA) ||
966 (xtype == CMM_PA2VA)) {
967 if (xtype == CMM_PA2VA) {
968
969 dw_offset = (u8 *) paddr - (u8 *) (allocator->shm_base -
970 allocator->
971 dsp_size);
972 dw_addr_xlate = xlator_obj->virt_base + dw_offset;
973
974 if ((dw_addr_xlate < xlator_obj->virt_base) ||
975 (dw_addr_xlate >=
976 (xlator_obj->virt_base +
977 xlator_obj->virt_size))) {
978 dw_addr_xlate = 0;
979 }
980 } else {
981
982 dw_offset =
983 (u8 *) paddr - (u8 *) xlator_obj->virt_base;
984 dw_addr_xlate =
985 allocator->shm_base - allocator->dsp_size +
986 dw_offset;
987 }
988 } else {
989 dw_addr_xlate = (u32) paddr;
990 }
991
992 if ((xtype == CMM_VA2DSPPA) || (xtype == CMM_PA2DSPPA)) {
993
994 dw_addr_xlate =
995 GPPPA2DSPPA((allocator->shm_base - allocator->dsp_size),
996 dw_addr_xlate,
997 allocator->dsp_phys_addr_offset *
998 allocator->c_factor);
999 } else if (xtype == CMM_DSPPA2PA) {
1000
1001 dw_addr_xlate =
1002 DSPPA2GPPPA(allocator->shm_base - allocator->dsp_size,
1003 dw_addr_xlate,
1004 allocator->dsp_phys_addr_offset *
1005 allocator->c_factor);
1006 }
1007loop_cont:
1008 return (void *)dw_addr_xlate;
1009}
1010