.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd |
---|
3 | 4 | * Author:Mark Yao <mark.yao@rock-chips.com> |
---|
4 | | - * |
---|
5 | | - * This software is licensed under the terms of the GNU General Public |
---|
6 | | - * License version 2, as published by the Free Software Foundation, and |
---|
7 | | - * may be copied, distributed, and modified under those terms. |
---|
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 | 5 | */ |
---|
14 | 6 | |
---|
| 7 | +#include <linux/dma-buf-cache.h> |
---|
| 8 | +#include <linux/iommu.h> |
---|
| 9 | +#include <linux/vmalloc.h> |
---|
| 10 | + |
---|
15 | 11 | #include <drm/drm.h> |
---|
16 | | -#include <drm/drmP.h> |
---|
17 | 12 | #include <drm/drm_gem.h> |
---|
| 13 | +#include <drm/drm_prime.h> |
---|
18 | 14 | #include <drm/drm_vma_manager.h> |
---|
19 | 15 | |
---|
20 | | -#include <linux/dma-buf.h> |
---|
21 | 16 | #include <linux/genalloc.h> |
---|
22 | 17 | #include <linux/iommu.h> |
---|
23 | 18 | #include <linux/pagemap.h> |
---|
24 | 19 | #include <linux/vmalloc.h> |
---|
25 | | -#include <linux/swiotlb.h> |
---|
| 20 | +#include <linux/rockchip/rockchip_sip.h> |
---|
26 | 21 | |
---|
27 | 22 | #include "rockchip_drm_drv.h" |
---|
28 | 23 | #include "rockchip_drm_gem.h" |
---|
| 24 | + |
---|
| 25 | +static u32 bank_bit_first = 12; |
---|
| 26 | +static u32 bank_bit_mask = 0x7; |
---|
29 | 27 | |
---|
30 | 28 | struct page_info { |
---|
31 | 29 | struct page *page; |
---|
.. | .. |
---|
54 | 52 | |
---|
55 | 53 | rk_obj->dma_addr = rk_obj->mm.start; |
---|
56 | 54 | |
---|
57 | | - ret = iommu_map_sg(private->domain, rk_obj->dma_addr, rk_obj->sgt->sgl, |
---|
58 | | - rk_obj->sgt->nents, prot); |
---|
| 55 | + ret = iommu_map_sgtable(private->domain, rk_obj->dma_addr, rk_obj->sgt, |
---|
| 56 | + prot); |
---|
59 | 57 | if (ret < rk_obj->base.size) { |
---|
60 | 58 | DRM_ERROR("failed to map buffer: size=%zd request_size=%zd\n", |
---|
61 | 59 | ret, rk_obj->base.size); |
---|
.. | .. |
---|
63 | 61 | goto err_remove_node; |
---|
64 | 62 | } |
---|
65 | 63 | |
---|
66 | | -#ifdef CONFIG_IOMMU_API |
---|
67 | | - if (private->domain->ops->flush_iotlb_all) |
---|
68 | | - private->domain->ops->flush_iotlb_all(private->domain); |
---|
69 | | -#endif |
---|
| 64 | + iommu_flush_iotlb_all(private->domain); |
---|
70 | 65 | |
---|
71 | 66 | rk_obj->size = ret; |
---|
72 | 67 | |
---|
.. | .. |
---|
109 | 104 | } |
---|
110 | 105 | } |
---|
111 | 106 | |
---|
112 | | -static struct sg_table *rockchip_gem_pages_to_sg(struct page **pages, unsigned int nr_pages) |
---|
| 107 | +void rockchip_gem_get_ddr_info(void) |
---|
113 | 108 | { |
---|
114 | | - struct sg_table *sg = NULL; |
---|
115 | | - int ret; |
---|
116 | | -#define SG_SIZE_MAX (IO_TLB_SEGSIZE * (1 << IO_TLB_SHIFT)) |
---|
| 109 | + struct dram_addrmap_info *ddr_map_info; |
---|
117 | 110 | |
---|
118 | | - sg = kmalloc(sizeof(struct sg_table), GFP_KERNEL); |
---|
119 | | - if (!sg) { |
---|
120 | | - ret = -ENOMEM; |
---|
121 | | - goto out; |
---|
| 111 | + ddr_map_info = sip_smc_get_dram_map(); |
---|
| 112 | + if (ddr_map_info) { |
---|
| 113 | + bank_bit_first = ddr_map_info->bank_bit_first; |
---|
| 114 | + bank_bit_mask = ddr_map_info->bank_bit_mask; |
---|
122 | 115 | } |
---|
123 | | - |
---|
124 | | - ret = __sg_alloc_table_from_pages(sg, pages, nr_pages, 0, |
---|
125 | | - nr_pages << PAGE_SHIFT, |
---|
126 | | - SG_SIZE_MAX, GFP_KERNEL); |
---|
127 | | - if (ret) |
---|
128 | | - goto out; |
---|
129 | | - |
---|
130 | | - return sg; |
---|
131 | | -out: |
---|
132 | | - kfree(sg); |
---|
133 | | - return ERR_PTR(ret); |
---|
134 | | -} |
---|
135 | | - |
---|
136 | | -static struct page **get_pages(struct drm_gem_object *obj) |
---|
137 | | -{ |
---|
138 | | - if (IS_ENABLED(CONFIG_DMABUF_PAGE_POOL)) { |
---|
139 | | - struct drm_device *drm = obj->dev; |
---|
140 | | - struct rockchip_drm_private *priv = drm->dev_private; |
---|
141 | | - struct dmabuf_page_pool *pool = priv->page_pools; |
---|
142 | | - |
---|
143 | | - return dmabuf_page_pool_alloc_pages_array(pool, |
---|
144 | | - obj->size >> |
---|
145 | | - PAGE_SHIFT); |
---|
146 | | - } |
---|
147 | | - |
---|
148 | | - return drm_gem_get_pages(obj); |
---|
149 | | -} |
---|
150 | | - |
---|
151 | | -static void put_pages(struct drm_gem_object *obj, struct page **pages, |
---|
152 | | - bool dirty, bool accessed) |
---|
153 | | -{ |
---|
154 | | - if (IS_ENABLED(CONFIG_DMABUF_PAGE_POOL)) { |
---|
155 | | - struct drm_device *drm = obj->dev; |
---|
156 | | - struct rockchip_drm_private *priv = drm->dev_private; |
---|
157 | | - struct dmabuf_page_pool *pool = priv->page_pools; |
---|
158 | | - |
---|
159 | | - return dmabuf_page_pool_free_pages_array(pool, pages, |
---|
160 | | - obj->size >> |
---|
161 | | - PAGE_SHIFT); |
---|
162 | | - } |
---|
163 | | - |
---|
164 | | - return drm_gem_put_pages(obj, pages, dirty, accessed); |
---|
165 | 116 | } |
---|
166 | 117 | |
---|
167 | 118 | static int rockchip_gem_get_pages(struct rockchip_gem_object *rk_obj) |
---|
.. | .. |
---|
178 | 129 | struct list_head lists[PG_ROUND]; |
---|
179 | 130 | dma_addr_t phys; |
---|
180 | 131 | int end = 0; |
---|
181 | | - unsigned int bit12_14; |
---|
| 132 | + unsigned int bit_index; |
---|
182 | 133 | unsigned int block_index[PG_ROUND] = {0}; |
---|
183 | 134 | struct page_info *info; |
---|
184 | 135 | unsigned int maximum; |
---|
.. | .. |
---|
186 | 137 | for (i = 0; i < PG_ROUND; i++) |
---|
187 | 138 | INIT_LIST_HEAD(&lists[i]); |
---|
188 | 139 | |
---|
189 | | - pages = get_pages(&rk_obj->base); |
---|
| 140 | + pages = drm_gem_get_pages(&rk_obj->base); |
---|
190 | 141 | if (IS_ERR(pages)) |
---|
191 | 142 | return PTR_ERR(pages); |
---|
192 | 143 | |
---|
.. | .. |
---|
197 | 148 | n_pages = rk_obj->num_pages; |
---|
198 | 149 | |
---|
199 | 150 | dst_pages = __vmalloc(sizeof(struct page *) * n_pages, |
---|
200 | | - GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL); |
---|
| 151 | + GFP_KERNEL | __GFP_HIGHMEM); |
---|
201 | 152 | if (!dst_pages) { |
---|
202 | 153 | ret = -ENOMEM; |
---|
203 | 154 | goto err_put_pages; |
---|
204 | 155 | } |
---|
| 156 | + |
---|
| 157 | + DRM_DEBUG_KMS("bank_bit_first = 0x%x, bank_bit_mask = 0x%x\n", |
---|
| 158 | + bank_bit_first, bank_bit_mask); |
---|
205 | 159 | |
---|
206 | 160 | cur_page = 0; |
---|
207 | 161 | remain = n_pages; |
---|
.. | .. |
---|
214 | 168 | } |
---|
215 | 169 | |
---|
216 | 170 | chunk_pages = j - cur_page; |
---|
217 | | - if (chunk_pages > 7) { |
---|
| 171 | + if (chunk_pages >= PG_ROUND) { |
---|
218 | 172 | for (i = 0; i < chunk_pages; i++) |
---|
219 | 173 | dst_pages[end + i] = pages[cur_page + i]; |
---|
220 | 174 | end += chunk_pages; |
---|
.. | .. |
---|
229 | 183 | INIT_LIST_HEAD(&info->list); |
---|
230 | 184 | info->page = pages[cur_page + i]; |
---|
231 | 185 | phys = page_to_phys(info->page); |
---|
232 | | - bit12_14 = (phys >> 12) & 0x7; |
---|
233 | | - list_add_tail(&info->list, &lists[bit12_14]); |
---|
234 | | - block_index[bit12_14]++; |
---|
| 186 | + bit_index = ((phys >> bank_bit_first) & bank_bit_mask) % PG_ROUND; |
---|
| 187 | + list_add_tail(&info->list, &lists[bit_index]); |
---|
| 188 | + block_index[bit_index]++; |
---|
235 | 189 | } |
---|
236 | 190 | } |
---|
237 | 191 | |
---|
.. | .. |
---|
259 | 213 | |
---|
260 | 214 | DRM_DEBUG_KMS("%s, %d, end = %d, n_pages = %d\n", __func__, __LINE__, |
---|
261 | 215 | end, n_pages); |
---|
262 | | - |
---|
263 | | - rk_obj->sgt = rockchip_gem_pages_to_sg(dst_pages, rk_obj->num_pages); |
---|
264 | | - |
---|
| 216 | + rk_obj->sgt = drm_prime_pages_to_sg(rk_obj->base.dev, |
---|
| 217 | + dst_pages, rk_obj->num_pages); |
---|
265 | 218 | if (IS_ERR(rk_obj->sgt)) { |
---|
266 | 219 | ret = PTR_ERR(rk_obj->sgt); |
---|
267 | 220 | goto err_put_list; |
---|
.. | .. |
---|
276 | 229 | * TODO: Replace this by drm_clflush_sg() once it can be implemented |
---|
277 | 230 | * without relying on symbols that are not exported. |
---|
278 | 231 | */ |
---|
279 | | - for_each_sg(rk_obj->sgt->sgl, s, rk_obj->sgt->nents, i) |
---|
| 232 | + for_each_sgtable_sg(rk_obj->sgt, s, i) |
---|
280 | 233 | sg_dma_address(s) = sg_phys(s); |
---|
281 | 234 | |
---|
282 | | - dma_sync_sg_for_device(drm->dev, rk_obj->sgt->sgl, rk_obj->sgt->nents, |
---|
283 | | - DMA_TO_DEVICE); |
---|
| 235 | + dma_sync_sgtable_for_device(drm->dev, rk_obj->sgt, DMA_TO_DEVICE); |
---|
284 | 236 | |
---|
285 | 237 | kvfree(pages); |
---|
286 | 238 | |
---|
.. | .. |
---|
290 | 242 | rockchip_gem_free_list(lists); |
---|
291 | 243 | kvfree(dst_pages); |
---|
292 | 244 | err_put_pages: |
---|
293 | | - put_pages(&rk_obj->base, rk_obj->pages, false, false); |
---|
294 | | - rk_obj->pages = NULL; |
---|
| 245 | + drm_gem_put_pages(&rk_obj->base, rk_obj->pages, false, false); |
---|
295 | 246 | return ret; |
---|
296 | 247 | } |
---|
297 | 248 | |
---|
.. | .. |
---|
299 | 250 | { |
---|
300 | 251 | sg_free_table(rk_obj->sgt); |
---|
301 | 252 | kfree(rk_obj->sgt); |
---|
302 | | - rk_obj->sgt = NULL; |
---|
303 | | - put_pages(&rk_obj->base, rk_obj->pages, true, true); |
---|
304 | | - rk_obj->pages = NULL; |
---|
| 253 | + drm_gem_put_pages(&rk_obj->base, rk_obj->pages, true, true); |
---|
305 | 254 | } |
---|
306 | 255 | |
---|
307 | 256 | static inline void *drm_calloc_large(size_t nmemb, size_t size); |
---|
.. | .. |
---|
351 | 300 | rk_obj->pages = drm_calloc_large(rk_obj->num_pages, |
---|
352 | 301 | sizeof(*rk_obj->pages)); |
---|
353 | 302 | if (!rk_obj->pages) { |
---|
| 303 | + ret = -ENOMEM; |
---|
354 | 304 | DRM_ERROR("failed to allocate pages.\n"); |
---|
355 | 305 | goto err_sg_table_free; |
---|
356 | 306 | } |
---|
.. | .. |
---|
388 | 338 | return kcalloc(nmemb, size, GFP_KERNEL); |
---|
389 | 339 | |
---|
390 | 340 | return __vmalloc(size * nmemb, |
---|
391 | | - GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO, PAGE_KERNEL); |
---|
| 341 | + GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO); |
---|
392 | 342 | } |
---|
393 | 343 | |
---|
394 | 344 | static inline void drm_free_large(void *ptr) |
---|
.. | .. |
---|
433 | 383 | paddr += PAGE_SIZE; |
---|
434 | 384 | i++; |
---|
435 | 385 | } |
---|
436 | | - sgt = rockchip_gem_pages_to_sg(rk_obj->pages, rk_obj->num_pages); |
---|
| 386 | + sgt = drm_prime_pages_to_sg(obj->dev, rk_obj->pages, rk_obj->num_pages); |
---|
437 | 387 | if (IS_ERR(sgt)) { |
---|
438 | 388 | ret = PTR_ERR(sgt); |
---|
439 | 389 | goto err_free_pages; |
---|
.. | .. |
---|
567 | 517 | } |
---|
568 | 518 | } |
---|
569 | 519 | |
---|
570 | | -/* |
---|
571 | | - * __vm_map_pages - maps range of kernel pages into user vma |
---|
572 | | - * @vma: user vma to map to |
---|
573 | | - * @pages: pointer to array of source kernel pages |
---|
574 | | - * @num: number of pages in page array |
---|
575 | | - * @offset: user's requested vm_pgoff |
---|
576 | | - * |
---|
577 | | - * This allows drivers to map range of kernel pages into a user vma. |
---|
578 | | - * |
---|
579 | | - * Return: 0 on success and error code otherwise. |
---|
580 | | - */ |
---|
581 | | -static int __vm_map_pages(struct vm_area_struct *vma, struct page **pages, |
---|
582 | | - unsigned long num, unsigned long offset) |
---|
583 | | -{ |
---|
584 | | - unsigned long count = vma_pages(vma); |
---|
585 | | - unsigned long uaddr = vma->vm_start; |
---|
586 | | - int ret, i; |
---|
587 | | - |
---|
588 | | - /* Fail if the user requested offset is beyond the end of the object */ |
---|
589 | | - if (offset > num) |
---|
590 | | - return -ENXIO; |
---|
591 | | - |
---|
592 | | - /* Fail if the user requested size exceeds available object size */ |
---|
593 | | - if (count > num - offset) |
---|
594 | | - return -ENXIO; |
---|
595 | | - |
---|
596 | | - for (i = 0; i < count; i++) { |
---|
597 | | - ret = vm_insert_page(vma, uaddr, pages[offset + i]); |
---|
598 | | - if (ret < 0) |
---|
599 | | - return ret; |
---|
600 | | - uaddr += PAGE_SIZE; |
---|
601 | | - } |
---|
602 | | - |
---|
603 | | - return 0; |
---|
604 | | -} |
---|
605 | | - |
---|
606 | 520 | static int rockchip_drm_gem_object_mmap_iommu(struct drm_gem_object *obj, |
---|
607 | 521 | struct vm_area_struct *vma) |
---|
608 | 522 | { |
---|
.. | .. |
---|
613 | 527 | if (user_count == 0) |
---|
614 | 528 | return -ENXIO; |
---|
615 | 529 | |
---|
616 | | - return __vm_map_pages(vma, rk_obj->pages, count, vma->vm_pgoff); |
---|
| 530 | + return vm_map_pages(vma, rk_obj->pages, count); |
---|
617 | 531 | } |
---|
618 | 532 | |
---|
619 | 533 | static int rockchip_drm_gem_object_mmap_dma(struct drm_gem_object *obj, |
---|
.. | .. |
---|
650 | 564 | } else { |
---|
651 | 565 | ret = rockchip_drm_gem_object_mmap_dma(obj, vma); |
---|
652 | 566 | } |
---|
653 | | - |
---|
654 | | - if (ret) |
---|
655 | | - drm_gem_vm_close(vma); |
---|
656 | 567 | |
---|
657 | 568 | return ret; |
---|
658 | 569 | } |
---|
.. | .. |
---|
697 | 608 | } |
---|
698 | 609 | |
---|
699 | 610 | static struct rockchip_gem_object * |
---|
700 | | - rockchip_gem_alloc_object(struct drm_device *drm, unsigned int size) |
---|
| 611 | +rockchip_gem_alloc_object(struct drm_device *drm, unsigned int size, |
---|
| 612 | + unsigned int flags) |
---|
701 | 613 | { |
---|
702 | 614 | struct address_space *mapping; |
---|
703 | 615 | struct rockchip_gem_object *rk_obj; |
---|
.. | .. |
---|
708 | 620 | #else |
---|
709 | 621 | gfp_t gfp_mask = GFP_HIGHUSER | __GFP_RECLAIMABLE; |
---|
710 | 622 | #endif |
---|
| 623 | + |
---|
| 624 | + if (flags & ROCKCHIP_BO_DMA32) |
---|
| 625 | + gfp_mask |= __GFP_DMA32; |
---|
| 626 | + |
---|
711 | 627 | size = round_up(size, PAGE_SIZE); |
---|
712 | 628 | |
---|
713 | 629 | rk_obj = kzalloc(sizeof(*rk_obj), GFP_KERNEL); |
---|
.. | .. |
---|
731 | 647 | struct rockchip_gem_object *rk_obj; |
---|
732 | 648 | int ret; |
---|
733 | 649 | |
---|
734 | | - rk_obj = rockchip_gem_alloc_object(drm, size); |
---|
| 650 | + rk_obj = rockchip_gem_alloc_object(drm, size, flags); |
---|
735 | 651 | if (IS_ERR(rk_obj)) |
---|
736 | 652 | return rk_obj; |
---|
737 | 653 | rk_obj->flags = flags; |
---|
.. | .. |
---|
748 | 664 | } |
---|
749 | 665 | |
---|
750 | 666 | /* |
---|
| 667 | + * rockchip_gem_destroy - destroy gem object |
---|
| 668 | + * |
---|
| 669 | + * The dma_buf_unmap_attachment and dma_buf_detach will be re-defined if |
---|
| 670 | + * CONFIG_DMABUF_CACHE is enabled. |
---|
| 671 | + * |
---|
| 672 | + * Same as drm_prime_gem_destroy |
---|
| 673 | + */ |
---|
| 674 | +static void rockchip_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg) |
---|
| 675 | +{ |
---|
| 676 | + struct dma_buf_attachment *attach; |
---|
| 677 | + struct dma_buf *dma_buf; |
---|
| 678 | + |
---|
| 679 | + attach = obj->import_attach; |
---|
| 680 | + if (sg) |
---|
| 681 | + dma_buf_unmap_attachment(attach, sg, DMA_BIDIRECTIONAL); |
---|
| 682 | + dma_buf = attach->dmabuf; |
---|
| 683 | + dma_buf_detach(attach->dmabuf, attach); |
---|
| 684 | + /* remove the reference */ |
---|
| 685 | + dma_buf_put(dma_buf); |
---|
| 686 | +} |
---|
| 687 | + |
---|
| 688 | +/* |
---|
751 | 689 | * rockchip_gem_free_object - (struct drm_driver)->gem_free_object_unlocked |
---|
752 | 690 | * callback function |
---|
753 | 691 | */ |
---|
.. | .. |
---|
761 | 699 | if (private->domain) { |
---|
762 | 700 | rockchip_gem_iommu_unmap(rk_obj); |
---|
763 | 701 | } else { |
---|
764 | | - dma_unmap_sg(drm->dev, rk_obj->sgt->sgl, |
---|
765 | | - rk_obj->sgt->nents, DMA_BIDIRECTIONAL); |
---|
| 702 | + dma_unmap_sgtable(drm->dev, rk_obj->sgt, |
---|
| 703 | + DMA_BIDIRECTIONAL, 0); |
---|
766 | 704 | } |
---|
767 | 705 | drm_free_large(rk_obj->pages); |
---|
768 | | -#ifndef CONFIG_ARCH_ROCKCHIP |
---|
769 | | - drm_prime_gem_destroy(obj, rk_obj->sgt); |
---|
770 | | -#endif |
---|
| 706 | + rockchip_gem_destroy(obj, rk_obj->sgt); |
---|
771 | 707 | } else { |
---|
772 | 708 | rockchip_gem_free_buf(rk_obj); |
---|
773 | 709 | } |
---|
.. | .. |
---|
807 | 743 | goto err_handle_create; |
---|
808 | 744 | |
---|
809 | 745 | /* drop reference from allocate - handle holds it now. */ |
---|
810 | | - drm_gem_object_put_unlocked(obj); |
---|
| 746 | + drm_gem_object_put(obj); |
---|
811 | 747 | |
---|
812 | 748 | return rk_obj; |
---|
813 | 749 | |
---|
.. | .. |
---|
857 | 793 | int ret; |
---|
858 | 794 | |
---|
859 | 795 | if (rk_obj->pages) |
---|
860 | | - return rockchip_gem_pages_to_sg(rk_obj->pages, rk_obj->num_pages); |
---|
| 796 | + return drm_prime_pages_to_sg(obj->dev, rk_obj->pages, rk_obj->num_pages); |
---|
861 | 797 | |
---|
862 | 798 | sgt = kzalloc(sizeof(*sgt), GFP_KERNEL); |
---|
863 | 799 | if (!sgt) |
---|
.. | .. |
---|
873 | 809 | } |
---|
874 | 810 | |
---|
875 | 811 | return sgt; |
---|
876 | | -} |
---|
877 | | - |
---|
878 | | -static unsigned long rockchip_sg_get_contiguous_size(struct sg_table *sgt, |
---|
879 | | - int count) |
---|
880 | | -{ |
---|
881 | | - struct scatterlist *s; |
---|
882 | | - dma_addr_t expected = sg_dma_address(sgt->sgl); |
---|
883 | | - unsigned int i; |
---|
884 | | - unsigned long size = 0; |
---|
885 | | - |
---|
886 | | - for_each_sg(sgt->sgl, s, count, i) { |
---|
887 | | - if (sg_dma_address(s) != expected) |
---|
888 | | - break; |
---|
889 | | - expected = sg_dma_address(s) + sg_dma_len(s); |
---|
890 | | - size += sg_dma_len(s); |
---|
891 | | - } |
---|
892 | | - return size; |
---|
893 | 812 | } |
---|
894 | 813 | |
---|
895 | 814 | static int |
---|
.. | .. |
---|
908 | 827 | struct sg_table *sg, |
---|
909 | 828 | struct rockchip_gem_object *rk_obj) |
---|
910 | 829 | { |
---|
911 | | - int count = dma_map_sg(drm->dev, sg->sgl, sg->nents, |
---|
912 | | - DMA_BIDIRECTIONAL); |
---|
913 | | - if (!count) |
---|
914 | | - return -EINVAL; |
---|
| 830 | + int err = dma_map_sgtable(drm->dev, sg, DMA_BIDIRECTIONAL, 0); |
---|
| 831 | + if (err) |
---|
| 832 | + return err; |
---|
915 | 833 | |
---|
916 | | - if (rockchip_sg_get_contiguous_size(sg, count) < attach->dmabuf->size) { |
---|
| 834 | + if (drm_prime_get_contiguous_size(sg) < attach->dmabuf->size) { |
---|
917 | 835 | DRM_ERROR("failed to map sg_table to contiguous linear address.\n"); |
---|
918 | | - dma_unmap_sg(drm->dev, sg->sgl, sg->nents, |
---|
919 | | - DMA_BIDIRECTIONAL); |
---|
| 836 | + dma_unmap_sgtable(drm->dev, sg, DMA_BIDIRECTIONAL, 0); |
---|
920 | 837 | return -EINVAL; |
---|
921 | 838 | } |
---|
922 | 839 | |
---|
.. | .. |
---|
934 | 851 | struct rockchip_gem_object *rk_obj; |
---|
935 | 852 | int ret; |
---|
936 | 853 | |
---|
937 | | - rk_obj = rockchip_gem_alloc_object(drm, attach->dmabuf->size); |
---|
| 854 | + rk_obj = rockchip_gem_alloc_object(drm, attach->dmabuf->size, 0); |
---|
938 | 855 | if (IS_ERR(rk_obj)) |
---|
939 | 856 | return ERR_CAST(rk_obj); |
---|
940 | 857 | |
---|
.. | .. |
---|
974 | 891 | { |
---|
975 | 892 | struct rockchip_gem_object *rk_obj = to_rockchip_obj(obj); |
---|
976 | 893 | |
---|
977 | | - if (rk_obj->pages) { |
---|
978 | | - pgprot_t prot; |
---|
979 | | - |
---|
980 | | - prot = rk_obj->flags & ROCKCHIP_BO_CACHABLE ? PAGE_KERNEL : pgprot_writecombine(PAGE_KERNEL); |
---|
981 | | - |
---|
982 | | - return vmap(rk_obj->pages, rk_obj->num_pages, VM_MAP, prot); |
---|
983 | | - } |
---|
| 894 | + if (rk_obj->pages) |
---|
| 895 | + return vmap(rk_obj->pages, rk_obj->num_pages, VM_MAP, |
---|
| 896 | + pgprot_writecombine(PAGE_KERNEL)); |
---|
984 | 897 | |
---|
985 | 898 | if (rk_obj->dma_attrs & DMA_ATTR_NO_KERNEL_MAPPING) |
---|
986 | 899 | return NULL; |
---|
.. | .. |
---|
1000 | 913 | /* Nothing to do if allocated by DMA mapping API. */ |
---|
1001 | 914 | } |
---|
1002 | 915 | |
---|
1003 | | -int rockchip_gem_dumb_map_offset(struct drm_file *file_priv, |
---|
1004 | | - struct drm_device *dev, uint32_t handle, |
---|
1005 | | - uint64_t *offset) |
---|
1006 | | -{ |
---|
1007 | | - struct drm_gem_object *obj; |
---|
1008 | | - int ret = 0; |
---|
1009 | | - |
---|
1010 | | - obj = drm_gem_object_lookup(file_priv, handle); |
---|
1011 | | - if (!obj) { |
---|
1012 | | - DRM_ERROR("failed to lookup gem object.\n"); |
---|
1013 | | - return -EINVAL; |
---|
1014 | | - } |
---|
1015 | | - |
---|
1016 | | - ret = drm_gem_create_mmap_offset(obj); |
---|
1017 | | - if (ret) |
---|
1018 | | - goto out; |
---|
1019 | | - |
---|
1020 | | - *offset = drm_vma_node_offset_addr(&obj->vma_node); |
---|
1021 | | - DRM_DEBUG_KMS("offset = 0x%llx\n", *offset); |
---|
1022 | | - |
---|
1023 | | -out: |
---|
1024 | | - drm_gem_object_unreference_unlocked(obj); |
---|
1025 | | - |
---|
1026 | | - return ret; |
---|
1027 | | -} |
---|
1028 | | - |
---|
1029 | 916 | int rockchip_gem_create_ioctl(struct drm_device *dev, void *data, |
---|
1030 | 917 | struct drm_file *file_priv) |
---|
1031 | 918 | { |
---|
.. | .. |
---|
1042 | 929 | { |
---|
1043 | 930 | struct drm_rockchip_gem_map_off *args = data; |
---|
1044 | 931 | |
---|
1045 | | - return rockchip_gem_dumb_map_offset(file_priv, drm, args->handle, |
---|
1046 | | - &args->offset); |
---|
| 932 | + return drm_gem_dumb_map_offset(file_priv, drm, args->handle, |
---|
| 933 | + &args->offset); |
---|
1047 | 934 | } |
---|
1048 | 935 | |
---|
1049 | 936 | int rockchip_gem_get_phys_ioctl(struct drm_device *dev, void *data, |
---|
.. | .. |
---|
1070 | 957 | args->phy_addr = page_to_phys(rk_obj->pages[0]); |
---|
1071 | 958 | |
---|
1072 | 959 | out: |
---|
1073 | | - drm_gem_object_unreference_unlocked(obj); |
---|
| 960 | + drm_gem_object_put(obj); |
---|
| 961 | + |
---|
1074 | 962 | return ret; |
---|
1075 | 963 | } |
---|
1076 | 964 | |
---|
.. | .. |
---|
1089 | 977 | } |
---|
1090 | 978 | |
---|
1091 | 979 | int rockchip_gem_prime_end_cpu_access(struct drm_gem_object *obj, |
---|
1092 | | - enum dma_data_direction dir) |
---|
| 980 | + enum dma_data_direction dir) |
---|
1093 | 981 | { |
---|
1094 | 982 | struct rockchip_gem_object *rk_obj = to_rockchip_obj(obj); |
---|
1095 | 983 | struct drm_device *drm = obj->dev; |
---|
.. | .. |
---|
1099 | 987 | |
---|
1100 | 988 | dma_sync_sg_for_device(drm->dev, rk_obj->sgt->sgl, |
---|
1101 | 989 | rk_obj->sgt->nents, dir); |
---|
1102 | | - return 0; |
---|
1103 | | -} |
---|
1104 | | - |
---|
1105 | | -static int rockchip_gem_prime_sgl_sync_range(struct device *dev, |
---|
1106 | | - struct scatterlist *sgl, unsigned int nents, |
---|
1107 | | - unsigned int offset, unsigned int length, |
---|
1108 | | - enum dma_data_direction dir, bool for_cpu) |
---|
1109 | | -{ |
---|
1110 | | - int i; |
---|
1111 | | - struct scatterlist *sg; |
---|
1112 | | - unsigned int len = 0; |
---|
1113 | | - dma_addr_t sg_dma_addr; |
---|
1114 | | - |
---|
1115 | | - for_each_sg(sgl, sg, nents, i) { |
---|
1116 | | - unsigned int sg_offset, sg_left, size = 0; |
---|
1117 | | - |
---|
1118 | | - len += sg->length; |
---|
1119 | | - if (len <= offset) |
---|
1120 | | - continue; |
---|
1121 | | - |
---|
1122 | | - sg_dma_addr = sg_dma_address(sg); |
---|
1123 | | - sg_left = len - offset; |
---|
1124 | | - sg_offset = sg->length - sg_left; |
---|
1125 | | - |
---|
1126 | | - size = (length < sg_left) ? length : sg_left; |
---|
1127 | | - if (for_cpu) |
---|
1128 | | - dma_sync_single_range_for_cpu(dev, sg_dma_addr, |
---|
1129 | | - sg_offset, size, dir); |
---|
1130 | | - else |
---|
1131 | | - dma_sync_single_range_for_device(dev, sg_dma_addr, |
---|
1132 | | - sg_offset, size, dir); |
---|
1133 | | - |
---|
1134 | | - offset += size; |
---|
1135 | | - length -= size; |
---|
1136 | | - |
---|
1137 | | - if (length == 0) |
---|
1138 | | - break; |
---|
1139 | | - } |
---|
1140 | | - |
---|
1141 | | - return 0; |
---|
1142 | | -} |
---|
1143 | | - |
---|
1144 | | -int rockchip_gem_prime_begin_cpu_access_partial(struct drm_gem_object *obj, |
---|
1145 | | - enum dma_data_direction dir, |
---|
1146 | | - unsigned int offset, |
---|
1147 | | - unsigned int len) |
---|
1148 | | -{ |
---|
1149 | | - struct rockchip_gem_object *rk_obj = to_rockchip_obj(obj); |
---|
1150 | | - struct drm_device *drm = obj->dev; |
---|
1151 | | - |
---|
1152 | | - if (!rk_obj->sgt) |
---|
1153 | | - return 0; |
---|
1154 | | - |
---|
1155 | | - rockchip_gem_prime_sgl_sync_range(drm->dev, rk_obj->sgt->sgl, |
---|
1156 | | - rk_obj->sgt->nents, |
---|
1157 | | - offset, len, dir, true); |
---|
1158 | | - |
---|
1159 | | - return 0; |
---|
1160 | | -} |
---|
1161 | | - |
---|
1162 | | -int rockchip_gem_prime_end_cpu_access_partial(struct drm_gem_object *obj, |
---|
1163 | | - enum dma_data_direction dir, |
---|
1164 | | - unsigned int offset, |
---|
1165 | | - unsigned int len) |
---|
1166 | | -{ |
---|
1167 | | - struct rockchip_gem_object *rk_obj = to_rockchip_obj(obj); |
---|
1168 | | - struct drm_device *drm = obj->dev; |
---|
1169 | | - |
---|
1170 | | - if (!rk_obj->sgt) |
---|
1171 | | - return 0; |
---|
1172 | | - |
---|
1173 | | - rockchip_gem_prime_sgl_sync_range(drm->dev, rk_obj->sgt->sgl, |
---|
1174 | | - rk_obj->sgt->nents, |
---|
1175 | | - offset, len, dir, false); |
---|
1176 | | - |
---|
1177 | 990 | return 0; |
---|
1178 | 991 | } |
---|