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#include "crystalhd.h"
28
29#include <linux/slab.h>
30
31uint32_t g_linklog_level;
32
33static inline uint32_t crystalhd_dram_rd(struct crystalhd_adp *adp, uint32_t mem_off)
34{
35 crystalhd_reg_wr(adp, DCI_DRAM_BASE_ADDR, (mem_off >> 19));
36 return bc_dec_reg_rd(adp, (0x00380000 | (mem_off & 0x0007FFFF)));
37}
38
39static inline void crystalhd_dram_wr(struct crystalhd_adp *adp, uint32_t mem_off, uint32_t val)
40{
41 crystalhd_reg_wr(adp, DCI_DRAM_BASE_ADDR, (mem_off >> 19));
42 bc_dec_reg_wr(adp, (0x00380000 | (mem_off & 0x0007FFFF)), val);
43}
44
45static inline enum BC_STATUS bc_chk_dram_range(struct crystalhd_adp *adp, uint32_t start_off, uint32_t cnt)
46{
47 return BC_STS_SUCCESS;
48}
49
50static struct crystalhd_dio_req *crystalhd_alloc_dio(struct crystalhd_adp *adp)
51{
52 unsigned long flags = 0;
53 struct crystalhd_dio_req *temp = NULL;
54
55 if (!adp) {
56 BCMLOG_ERR("Invalid Arg!!\n");
57 return temp;
58 }
59
60 spin_lock_irqsave(&adp->lock, flags);
61 temp = adp->ua_map_free_head;
62 if (temp)
63 adp->ua_map_free_head = adp->ua_map_free_head->next;
64 spin_unlock_irqrestore(&adp->lock, flags);
65
66 return temp;
67}
68
69static void crystalhd_free_dio(struct crystalhd_adp *adp, struct crystalhd_dio_req *dio)
70{
71 unsigned long flags = 0;
72
73 if (!adp || !dio)
74 return;
75 spin_lock_irqsave(&adp->lock, flags);
76 dio->sig = crystalhd_dio_inv;
77 dio->page_cnt = 0;
78 dio->fb_size = 0;
79 memset(&dio->uinfo, 0, sizeof(dio->uinfo));
80 dio->next = adp->ua_map_free_head;
81 adp->ua_map_free_head = dio;
82 spin_unlock_irqrestore(&adp->lock, flags);
83}
84
85static struct crystalhd_elem *crystalhd_alloc_elem(struct crystalhd_adp *adp)
86{
87 unsigned long flags = 0;
88 struct crystalhd_elem *temp = NULL;
89
90 if (!adp)
91 return temp;
92 spin_lock_irqsave(&adp->lock, flags);
93 temp = adp->elem_pool_head;
94 if (temp) {
95 adp->elem_pool_head = adp->elem_pool_head->flink;
96 memset(temp, 0, sizeof(*temp));
97 }
98 spin_unlock_irqrestore(&adp->lock, flags);
99
100 return temp;
101}
102static void crystalhd_free_elem(struct crystalhd_adp *adp, struct crystalhd_elem *elem)
103{
104 unsigned long flags = 0;
105
106 if (!adp || !elem)
107 return;
108 spin_lock_irqsave(&adp->lock, flags);
109 elem->flink = adp->elem_pool_head;
110 adp->elem_pool_head = elem;
111 spin_unlock_irqrestore(&adp->lock, flags);
112}
113
114static inline void crystalhd_set_sg(struct scatterlist *sg, struct page *page,
115 unsigned int len, unsigned int offset)
116{
117 sg_set_page(sg, page, len, offset);
118#ifdef CONFIG_X86_64
119 sg->dma_length = len;
120#endif
121}
122
123static inline void crystalhd_init_sg(struct scatterlist *sg, unsigned int entries)
124{
125
126 sg_init_table(sg, entries);
127}
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142uint32_t bc_dec_reg_rd(struct crystalhd_adp *adp, uint32_t reg_off)
143{
144 if (!adp || (reg_off > adp->pci_mem_len)) {
145 BCMLOG_ERR("dec_rd_reg_off outof range: 0x%08x\n", reg_off);
146 return 0;
147 }
148
149 return readl(adp->addr + reg_off);
150}
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165void bc_dec_reg_wr(struct crystalhd_adp *adp, uint32_t reg_off, uint32_t val)
166{
167 if (!adp || (reg_off > adp->pci_mem_len)) {
168 BCMLOG_ERR("dec_wr_reg_off outof range: 0x%08x\n", reg_off);
169 return;
170 }
171 writel(val, adp->addr + reg_off);
172 udelay(8);
173}
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188uint32_t crystalhd_reg_rd(struct crystalhd_adp *adp, uint32_t reg_off)
189{
190 if (!adp || (reg_off > adp->pci_i2o_len)) {
191 BCMLOG_ERR("link_rd_reg_off outof range: 0x%08x\n", reg_off);
192 return 0;
193 }
194 return readl(adp->i2o_addr + reg_off);
195}
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211void crystalhd_reg_wr(struct crystalhd_adp *adp, uint32_t reg_off, uint32_t val)
212{
213 if (!adp || (reg_off > adp->pci_i2o_len)) {
214 BCMLOG_ERR("link_wr_reg_off outof range: 0x%08x\n", reg_off);
215 return;
216 }
217 writel(val, adp->i2o_addr + reg_off);
218}
219
220
221
222
223
224
225
226
227
228
229
230
231
232enum BC_STATUS crystalhd_mem_rd(struct crystalhd_adp *adp, uint32_t start_off,
233 uint32_t dw_cnt, uint32_t *rd_buff)
234{
235 uint32_t ix = 0;
236
237 if (!adp || !rd_buff ||
238 (bc_chk_dram_range(adp, start_off, dw_cnt) != BC_STS_SUCCESS)) {
239 BCMLOG_ERR("Invalid arg\n");
240 return BC_STS_INV_ARG;
241 }
242 for (ix = 0; ix < dw_cnt; ix++)
243 rd_buff[ix] = crystalhd_dram_rd(adp, (start_off + (ix * 4)));
244
245 return BC_STS_SUCCESS;
246}
247
248
249
250
251
252
253
254
255
256
257
258
259
260enum BC_STATUS crystalhd_mem_wr(struct crystalhd_adp *adp, uint32_t start_off,
261 uint32_t dw_cnt, uint32_t *wr_buff)
262{
263 uint32_t ix = 0;
264
265 if (!adp || !wr_buff ||
266 (bc_chk_dram_range(adp, start_off, dw_cnt) != BC_STS_SUCCESS)) {
267 BCMLOG_ERR("Invalid arg\n");
268 return BC_STS_INV_ARG;
269 }
270
271 for (ix = 0; ix < dw_cnt; ix++)
272 crystalhd_dram_wr(adp, (start_off + (ix * 4)), wr_buff[ix]);
273
274 return BC_STS_SUCCESS;
275}
276
277
278
279
280
281
282
283
284
285
286
287
288enum BC_STATUS crystalhd_pci_cfg_rd(struct crystalhd_adp *adp, uint32_t off,
289 uint32_t len, uint32_t *val)
290{
291 enum BC_STATUS sts = BC_STS_SUCCESS;
292 int rc = 0;
293
294 if (!adp || !val) {
295 BCMLOG_ERR("Invalid arg\n");
296 return BC_STS_INV_ARG;
297 }
298
299 switch (len) {
300 case 1:
301 rc = pci_read_config_byte(adp->pdev, off, (u8 *)val);
302 break;
303 case 2:
304 rc = pci_read_config_word(adp->pdev, off, (u16 *)val);
305 break;
306 case 4:
307 rc = pci_read_config_dword(adp->pdev, off, (u32 *)val);
308 break;
309 default:
310 rc = -EINVAL;
311 sts = BC_STS_INV_ARG;
312 BCMLOG_ERR("Invalid len:%d\n", len);
313 }
314
315 if (rc && (sts == BC_STS_SUCCESS))
316 sts = BC_STS_ERROR;
317
318 return sts;
319}
320
321
322
323
324
325
326
327
328
329
330
331
332
333enum BC_STATUS crystalhd_pci_cfg_wr(struct crystalhd_adp *adp, uint32_t off,
334 uint32_t len, uint32_t val)
335{
336 enum BC_STATUS sts = BC_STS_SUCCESS;
337 int rc = 0;
338
339 if (!adp || !val) {
340 BCMLOG_ERR("Invalid arg\n");
341 return BC_STS_INV_ARG;
342 }
343
344 switch (len) {
345 case 1:
346 rc = pci_write_config_byte(adp->pdev, off, (u8)val);
347 break;
348 case 2:
349 rc = pci_write_config_word(adp->pdev, off, (u16)val);
350 break;
351 case 4:
352 rc = pci_write_config_dword(adp->pdev, off, val);
353 break;
354 default:
355 rc = -EINVAL;
356 sts = BC_STS_INV_ARG;
357 BCMLOG_ERR("Invalid len:%d\n", len);
358 }
359
360 if (rc && (sts == BC_STS_SUCCESS))
361 sts = BC_STS_ERROR;
362
363 return sts;
364}
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379void *bc_kern_dma_alloc(struct crystalhd_adp *adp, uint32_t sz,
380 dma_addr_t *phy_addr)
381{
382 void *temp = NULL;
383
384 if (!adp || !sz || !phy_addr) {
385 BCMLOG_ERR("Invalide Arg..\n");
386 return temp;
387 }
388
389 temp = pci_alloc_consistent(adp->pdev, sz, phy_addr);
390 if (temp)
391 memset(temp, 0, sz);
392
393 return temp;
394}
395
396
397
398
399
400
401
402
403
404
405
406
407void bc_kern_dma_free(struct crystalhd_adp *adp, uint32_t sz, void *ka,
408 dma_addr_t phy_addr)
409{
410 if (!adp || !ka || !sz || !phy_addr) {
411 BCMLOG_ERR("Invalide Arg..\n");
412 return;
413 }
414
415 pci_free_consistent(adp->pdev, sz, ka, phy_addr);
416}
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431enum BC_STATUS crystalhd_create_dioq(struct crystalhd_adp *adp,
432 struct crystalhd_dioq **dioq_hnd,
433 crystalhd_data_free_cb cb, void *cbctx)
434{
435 struct crystalhd_dioq *dioq = NULL;
436
437 if (!adp || !dioq_hnd) {
438 BCMLOG_ERR("Invalid arg!!\n");
439 return BC_STS_INV_ARG;
440 }
441
442 dioq = kzalloc(sizeof(*dioq), GFP_KERNEL);
443 if (!dioq)
444 return BC_STS_INSUFF_RES;
445
446 spin_lock_init(&dioq->lock);
447 dioq->sig = BC_LINK_DIOQ_SIG;
448 dioq->head = (struct crystalhd_elem *)&dioq->head;
449 dioq->tail = (struct crystalhd_elem *)&dioq->head;
450 crystalhd_create_event(&dioq->event);
451 dioq->adp = adp;
452 dioq->data_rel_cb = cb;
453 dioq->cb_context = cbctx;
454 *dioq_hnd = dioq;
455
456 return BC_STS_SUCCESS;
457}
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472void crystalhd_delete_dioq(struct crystalhd_adp *adp, struct crystalhd_dioq *dioq)
473{
474 void *temp;
475
476 if (!dioq || (dioq->sig != BC_LINK_DIOQ_SIG))
477 return;
478
479 do {
480 temp = crystalhd_dioq_fetch(dioq);
481 if (temp && dioq->data_rel_cb)
482 dioq->data_rel_cb(dioq->cb_context, temp);
483 } while (temp);
484 dioq->sig = 0;
485 kfree(dioq);
486}
487
488
489
490
491
492
493
494
495
496
497
498
499
500enum BC_STATUS crystalhd_dioq_add(struct crystalhd_dioq *ioq, void *data,
501 bool wake, uint32_t tag)
502{
503 unsigned long flags = 0;
504 struct crystalhd_elem *tmp;
505
506 if (!ioq || (ioq->sig != BC_LINK_DIOQ_SIG) || !data) {
507 BCMLOG_ERR("Invalid arg!!\n");
508 return BC_STS_INV_ARG;
509 }
510
511 tmp = crystalhd_alloc_elem(ioq->adp);
512 if (!tmp) {
513 BCMLOG_ERR("No free elements.\n");
514 return BC_STS_INSUFF_RES;
515 }
516
517 tmp->data = data;
518 tmp->tag = tag;
519 spin_lock_irqsave(&ioq->lock, flags);
520 tmp->flink = (struct crystalhd_elem *)&ioq->head;
521 tmp->blink = ioq->tail;
522 tmp->flink->blink = tmp;
523 tmp->blink->flink = tmp;
524 ioq->count++;
525 spin_unlock_irqrestore(&ioq->lock, flags);
526
527 if (wake)
528 crystalhd_set_event(&ioq->event);
529
530 return BC_STS_SUCCESS;
531}
532
533
534
535
536
537
538
539
540
541
542void *crystalhd_dioq_fetch(struct crystalhd_dioq *ioq)
543{
544 unsigned long flags = 0;
545 struct crystalhd_elem *tmp;
546 struct crystalhd_elem *ret = NULL;
547 void *data = NULL;
548
549 if (!ioq || (ioq->sig != BC_LINK_DIOQ_SIG)) {
550 BCMLOG_ERR("Invalid arg!!\n");
551 return data;
552 }
553
554 spin_lock_irqsave(&ioq->lock, flags);
555 tmp = ioq->head;
556 if (tmp != (struct crystalhd_elem *)&ioq->head) {
557 ret = tmp;
558 tmp->flink->blink = tmp->blink;
559 tmp->blink->flink = tmp->flink;
560 ioq->count--;
561 }
562 spin_unlock_irqrestore(&ioq->lock, flags);
563 if (ret) {
564 data = ret->data;
565 crystalhd_free_elem(ioq->adp, ret);
566 }
567
568 return data;
569}
570
571
572
573
574
575
576
577
578
579
580void *crystalhd_dioq_find_and_fetch(struct crystalhd_dioq *ioq, uint32_t tag)
581{
582 unsigned long flags = 0;
583 struct crystalhd_elem *tmp;
584 struct crystalhd_elem *ret = NULL;
585 void *data = NULL;
586
587 if (!ioq || (ioq->sig != BC_LINK_DIOQ_SIG)) {
588 BCMLOG_ERR("Invalid arg!!\n");
589 return data;
590 }
591
592 spin_lock_irqsave(&ioq->lock, flags);
593 tmp = ioq->head;
594 while (tmp != (struct crystalhd_elem *)&ioq->head) {
595 if (tmp->tag == tag) {
596 ret = tmp;
597 tmp->flink->blink = tmp->blink;
598 tmp->blink->flink = tmp->flink;
599 ioq->count--;
600 break;
601 }
602 tmp = tmp->flink;
603 }
604 spin_unlock_irqrestore(&ioq->lock, flags);
605
606 if (ret) {
607 data = ret->data;
608 crystalhd_free_elem(ioq->adp, ret);
609 }
610
611 return data;
612}
613
614
615
616
617
618
619
620
621
622
623
624
625void *crystalhd_dioq_fetch_wait(struct crystalhd_dioq *ioq, uint32_t to_secs,
626 uint32_t *sig_pend)
627{
628 unsigned long flags = 0;
629 int rc = 0, count;
630 void *tmp = NULL;
631
632 if (!ioq || (ioq->sig != BC_LINK_DIOQ_SIG) || !to_secs || !sig_pend) {
633 BCMLOG_ERR("Invalid arg!!\n");
634 return tmp;
635 }
636
637 count = to_secs;
638 spin_lock_irqsave(&ioq->lock, flags);
639 while ((ioq->count == 0) && count) {
640 spin_unlock_irqrestore(&ioq->lock, flags);
641
642 crystalhd_wait_on_event(&ioq->event, (ioq->count > 0), 1000, rc, 0);
643 if (rc == 0) {
644 goto out;
645 } else if (rc == -EINTR) {
646 BCMLOG(BCMLOG_INFO, "Cancelling fetch wait\n");
647 *sig_pend = 1;
648 return tmp;
649 }
650 spin_lock_irqsave(&ioq->lock, flags);
651 count--;
652 }
653 spin_unlock_irqrestore(&ioq->lock, flags);
654
655out:
656 return crystalhd_dioq_fetch(ioq);
657}
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675enum BC_STATUS crystalhd_map_dio(struct crystalhd_adp *adp, void *ubuff,
676 uint32_t ubuff_sz, uint32_t uv_offset,
677 bool en_422mode, bool dir_tx,
678 struct crystalhd_dio_req **dio_hnd)
679{
680 struct crystalhd_dio_req *dio;
681
682 unsigned long start = 0, end = 0, uaddr = 0, count = 0;
683 unsigned long spsz = 0, uv_start = 0;
684 int i = 0, rw = 0, res = 0, nr_pages = 0, skip_fb_sg = 0;
685
686 if (!adp || !ubuff || !ubuff_sz || !dio_hnd) {
687 BCMLOG_ERR("Invalid arg\n");
688 return BC_STS_INV_ARG;
689 }
690
691 uaddr = (unsigned long)ubuff;
692 count = (unsigned long)ubuff_sz;
693 end = (uaddr + count + PAGE_SIZE - 1) >> PAGE_SHIFT;
694 start = uaddr >> PAGE_SHIFT;
695 nr_pages = end - start;
696
697 if (!count || ((uaddr + count) < uaddr)) {
698 BCMLOG_ERR("User addr overflow!!\n");
699 return BC_STS_INV_ARG;
700 }
701
702 dio = crystalhd_alloc_dio(adp);
703 if (!dio) {
704 BCMLOG_ERR("dio pool empty..\n");
705 return BC_STS_INSUFF_RES;
706 }
707
708 if (dir_tx) {
709 rw = WRITE;
710 dio->direction = DMA_TO_DEVICE;
711 } else {
712 rw = READ;
713 dio->direction = DMA_FROM_DEVICE;
714 }
715
716 if (nr_pages > dio->max_pages) {
717 BCMLOG_ERR("max_pages(%d) exceeded(%d)!!\n",
718 dio->max_pages, nr_pages);
719 crystalhd_unmap_dio(adp, dio);
720 return BC_STS_INSUFF_RES;
721 }
722
723 if (uv_offset) {
724 uv_start = (uaddr + (unsigned long)uv_offset) >> PAGE_SHIFT;
725 dio->uinfo.uv_sg_ix = uv_start - start;
726 dio->uinfo.uv_sg_off = ((uaddr + (unsigned long)uv_offset) & ~PAGE_MASK);
727 }
728
729 dio->fb_size = ubuff_sz & 0x03;
730 if (dio->fb_size) {
731 res = copy_from_user(dio->fb_va,
732 (void *)(uaddr + count - dio->fb_size),
733 dio->fb_size);
734 if (res) {
735 BCMLOG_ERR("failed %d to copy %u fill bytes from %p\n",
736 res, dio->fb_size,
737 (void *)(uaddr + count-dio->fb_size));
738 crystalhd_unmap_dio(adp, dio);
739 return BC_STS_INSUFF_RES;
740 }
741 }
742
743 down_read(¤t->mm->mmap_sem);
744 res = get_user_pages(current, current->mm, uaddr, nr_pages, rw == READ,
745 0, dio->pages, NULL);
746 up_read(¤t->mm->mmap_sem);
747
748
749 dio->sig = crystalhd_dio_locked;
750 if (res < nr_pages) {
751 BCMLOG_ERR("get pages failed: %d-%d\n", nr_pages, res);
752 dio->page_cnt = res;
753 crystalhd_unmap_dio(adp, dio);
754 return BC_STS_ERROR;
755 }
756
757 dio->page_cnt = nr_pages;
758
759 crystalhd_init_sg(dio->sg, dio->page_cnt);
760 crystalhd_set_sg(&dio->sg[0], dio->pages[0], 0, uaddr & ~PAGE_MASK);
761 if (nr_pages > 1) {
762 dio->sg[0].length = PAGE_SIZE - dio->sg[0].offset;
763
764#ifdef CONFIG_X86_64
765 dio->sg[0].dma_length = dio->sg[0].length;
766#endif
767 count -= dio->sg[0].length;
768 for (i = 1; i < nr_pages; i++) {
769 if (count < 4) {
770 spsz = count;
771 skip_fb_sg = 1;
772 } else {
773 spsz = (count < PAGE_SIZE) ?
774 (count & ~0x03) : PAGE_SIZE;
775 }
776 crystalhd_set_sg(&dio->sg[i], dio->pages[i], spsz, 0);
777 count -= spsz;
778 }
779 } else {
780 if (count < 4) {
781 dio->sg[0].length = count;
782 skip_fb_sg = 1;
783 } else {
784 dio->sg[0].length = count - dio->fb_size;
785 }
786#ifdef CONFIG_X86_64
787 dio->sg[0].dma_length = dio->sg[0].length;
788#endif
789 }
790 dio->sg_cnt = pci_map_sg(adp->pdev, dio->sg,
791 dio->page_cnt, dio->direction);
792 if (dio->sg_cnt <= 0) {
793 BCMLOG_ERR("sg map %d-%d\n", dio->sg_cnt, dio->page_cnt);
794 crystalhd_unmap_dio(adp, dio);
795 return BC_STS_ERROR;
796 }
797 if (dio->sg_cnt && skip_fb_sg)
798 dio->sg_cnt -= 1;
799 dio->sig = crystalhd_dio_sg_mapped;
800
801 dio->uinfo.xfr_len = ubuff_sz;
802 dio->uinfo.xfr_buff = ubuff;
803 dio->uinfo.uv_offset = uv_offset;
804 dio->uinfo.b422mode = en_422mode;
805 dio->uinfo.dir_tx = dir_tx;
806
807 *dio_hnd = dio;
808
809 return BC_STS_SUCCESS;
810}
811
812
813
814
815
816
817
818
819
820
821
822enum BC_STATUS crystalhd_unmap_dio(struct crystalhd_adp *adp, struct crystalhd_dio_req *dio)
823{
824 struct page *page = NULL;
825 int j = 0;
826
827 if (!adp || !dio) {
828 BCMLOG_ERR("Invalid arg\n");
829 return BC_STS_INV_ARG;
830 }
831
832 if ((dio->page_cnt > 0) && (dio->sig != crystalhd_dio_inv)) {
833 for (j = 0; j < dio->page_cnt; j++) {
834 page = dio->pages[j];
835 if (page) {
836 if (!PageReserved(page) &&
837 (dio->direction == DMA_FROM_DEVICE))
838 SetPageDirty(page);
839 page_cache_release(page);
840 }
841 }
842 }
843 if (dio->sig == crystalhd_dio_sg_mapped)
844 pci_unmap_sg(adp->pdev, dio->sg, dio->page_cnt, dio->direction);
845
846 crystalhd_free_dio(adp, dio);
847
848 return BC_STS_SUCCESS;
849}
850
851
852
853
854
855
856
857
858
859
860
861
862int crystalhd_create_dio_pool(struct crystalhd_adp *adp, uint32_t max_pages)
863{
864 uint32_t asz = 0, i = 0;
865 uint8_t *temp;
866 struct crystalhd_dio_req *dio;
867
868 if (!adp || !max_pages) {
869 BCMLOG_ERR("Invalid Arg!!\n");
870 return -EINVAL;
871 }
872
873
874 adp->fill_byte_pool = pci_pool_create("crystalhd_fbyte",
875 adp->pdev, 8, 8, 0);
876 if (!adp->fill_byte_pool) {
877 BCMLOG_ERR("failed to create fill byte pool\n");
878 return -ENOMEM;
879 }
880
881
882 asz = (sizeof(*dio->pages) * max_pages) +
883 (sizeof(*dio->sg) * max_pages) + sizeof(*dio);
884
885 BCMLOG(BCMLOG_DBG, "Initializing Dio pool %d %d %x %p\n",
886 BC_LINK_SG_POOL_SZ, max_pages, asz, adp->fill_byte_pool);
887
888 for (i = 0; i < BC_LINK_SG_POOL_SZ; i++) {
889 temp = kzalloc(asz, GFP_KERNEL);
890 if ((temp) == NULL) {
891 BCMLOG_ERR("Failed to alloc %d mem\n", asz);
892 return -ENOMEM;
893 }
894
895 dio = (struct crystalhd_dio_req *)temp;
896 temp += sizeof(*dio);
897 dio->pages = (struct page **)temp;
898 temp += (sizeof(*dio->pages) * max_pages);
899 dio->sg = (struct scatterlist *)temp;
900 dio->max_pages = max_pages;
901 dio->fb_va = pci_pool_alloc(adp->fill_byte_pool, GFP_KERNEL,
902 &dio->fb_pa);
903 if (!dio->fb_va) {
904 BCMLOG_ERR("fill byte alloc failed.\n");
905 return -ENOMEM;
906 }
907
908 crystalhd_free_dio(adp, dio);
909 }
910
911 return 0;
912}
913
914
915
916
917
918
919
920
921
922
923void crystalhd_destroy_dio_pool(struct crystalhd_adp *adp)
924{
925 struct crystalhd_dio_req *dio;
926 int count = 0;
927
928 if (!adp) {
929 BCMLOG_ERR("Invalid Arg!!\n");
930 return;
931 }
932
933 do {
934 dio = crystalhd_alloc_dio(adp);
935 if (dio) {
936 if (dio->fb_va)
937 pci_pool_free(adp->fill_byte_pool,
938 dio->fb_va, dio->fb_pa);
939 count++;
940 kfree(dio);
941 }
942 } while (dio);
943
944 if (adp->fill_byte_pool) {
945 pci_pool_destroy(adp->fill_byte_pool);
946 adp->fill_byte_pool = NULL;
947 }
948
949 BCMLOG(BCMLOG_DBG, "Released dio pool %d\n", count);
950}
951
952
953
954
955
956
957
958
959
960
961
962
963int crystalhd_create_elem_pool(struct crystalhd_adp *adp,
964 uint32_t pool_size)
965{
966 uint32_t i;
967 struct crystalhd_elem *temp;
968
969 if (!adp || !pool_size)
970 return -EINVAL;
971
972 for (i = 0; i < pool_size; i++) {
973 temp = kzalloc(sizeof(*temp), GFP_KERNEL);
974 if (!temp) {
975 BCMLOG_ERR("kalloc failed\n");
976 return -ENOMEM;
977 }
978 crystalhd_free_elem(adp, temp);
979 }
980 BCMLOG(BCMLOG_DBG, "allocated %d elem\n", pool_size);
981 return 0;
982}
983
984
985
986
987
988
989
990
991
992
993void crystalhd_delete_elem_pool(struct crystalhd_adp *adp)
994{
995 struct crystalhd_elem *temp;
996 int dbg_cnt = 0;
997
998 if (!adp)
999 return;
1000
1001 do {
1002 temp = crystalhd_alloc_elem(adp);
1003 if (temp) {
1004 kfree(temp);
1005 dbg_cnt++;
1006 }
1007 } while (temp);
1008
1009 BCMLOG(BCMLOG_DBG, "released %d elem\n", dbg_cnt);
1010}
1011
1012
1013void crystalhd_show_buffer(uint32_t off, uint8_t *buff, uint32_t dwcount)
1014{
1015 uint32_t i, k = 1;
1016
1017 for (i = 0; i < dwcount; i++) {
1018 if (k == 1)
1019 BCMLOG(BCMLOG_DATA, "0x%08X : ", off);
1020
1021 BCMLOG(BCMLOG_DATA, " 0x%08X ", *((uint32_t *)buff));
1022
1023 buff += sizeof(uint32_t);
1024 off += sizeof(uint32_t);
1025 k++;
1026 if ((i == dwcount - 1) || (k > 4)) {
1027 BCMLOG(BCMLOG_DATA, "\n");
1028 k = 1;
1029 }
1030 }
1031}
1032