diff options
author | Sudhir Vyas <svyas@nvidia.com> | 2017-11-09 08:55:43 -0500 |
---|---|---|
committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2017-11-14 12:53:43 -0500 |
commit | cc210201488de431c0602603f0b9a5a24925be81 (patch) | |
tree | 0746da9aba6ad7f388cc3cf6c0416fa2c9b26593 /drivers/media | |
parent | 0979f851071c9ac1420d12102bd63ff8f712ffb5 (diff) |
media: tegra: camera: refactor pin reloc APIs
Refactor pin and reloc API functions.
Also rebase vi capture driver to capture common.
Jira CRTC-1472
Change-Id: I4f6eeba8e0637ea864a8b8c3ad1220b2770e9ad1
Signed-off-by: Sudhir Vyas <svyas@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1595206
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/platform/tegra/camera/capture_common.c | 51 | ||||
-rw-r--r-- | drivers/media/platform/tegra/camera/isp/capture_isp.c | 118 | ||||
-rw-r--r-- | drivers/media/platform/tegra/camera/vi/capture.c | 241 |
3 files changed, 111 insertions, 299 deletions
diff --git a/drivers/media/platform/tegra/camera/capture_common.c b/drivers/media/platform/tegra/camera/capture_common.c index a2a4e8428..a2fc848bb 100644 --- a/drivers/media/platform/tegra/camera/capture_common.c +++ b/drivers/media/platform/tegra/camera/capture_common.c | |||
@@ -13,7 +13,7 @@ | |||
13 | #include <linux/dma-buf.h> | 13 | #include <linux/dma-buf.h> |
14 | #include <linux/dma-mapping.h> | 14 | #include <linux/dma-mapping.h> |
15 | #include <linux/nvhost.h> | 15 | #include <linux/nvhost.h> |
16 | #include <linux/scatterlist.h> | 16 | #include <linux/slab.h> |
17 | #include <media/capture_common.h> | 17 | #include <media/capture_common.h> |
18 | #include <media/mc_common.h> | 18 | #include <media/mc_common.h> |
19 | 19 | ||
@@ -81,16 +81,51 @@ void capture_common_unpin_memory(struct capture_common_buf *unpin_data) | |||
81 | 81 | ||
82 | int capture_common_request_pin_and_reloc(struct capture_common_pin_req *req) | 82 | int capture_common_request_pin_and_reloc(struct capture_common_pin_req *req) |
83 | { | 83 | { |
84 | uint32_t num_relocs = req->relocs->num_relocs; | 84 | uint32_t *reloc_relatives; |
85 | void *reloc_page_addr = NULL; | 85 | void *reloc_page_addr = NULL; |
86 | int last_page = -1; | 86 | int last_page = -1; |
87 | int i; | 87 | int i; |
88 | int err = 0; | 88 | int err = 0; |
89 | 89 | ||
90 | dev_dbg(req->dev, "%s: relocating %u addresses", __func__, num_relocs); | 90 | if (!req) { |
91 | pr_err("%s: NULL pin request", __func__); | ||
92 | return -EINVAL; | ||
93 | } | ||
94 | |||
95 | if (req->unpins) { | ||
96 | dev_err(req->dev, "%s: request unpins already exist", __func__); | ||
97 | return -EEXIST; | ||
98 | } | ||
91 | 99 | ||
92 | for (i = 0; i < num_relocs; i++) { | 100 | req->unpins = devm_kzalloc(req->dev, |
93 | uint32_t reloc_relative = req->relocs->reloc_relatives[i]; | 101 | sizeof(struct capture_common_unpins) + |
102 | (sizeof(struct capture_common_buf) * req->num_relocs), | ||
103 | GFP_KERNEL); | ||
104 | if (req->unpins == NULL) { | ||
105 | dev_err(req->dev, "failed to allocate request unpins\n"); | ||
106 | return -ENOMEM; | ||
107 | } | ||
108 | |||
109 | reloc_relatives = kcalloc(req->num_relocs, sizeof(uint32_t), | ||
110 | GFP_KERNEL); | ||
111 | if (reloc_relatives == NULL) { | ||
112 | dev_err(req->dev, "failed to allocate request reloc array\n"); | ||
113 | err = -ENOMEM; | ||
114 | goto reloc_fail; | ||
115 | } | ||
116 | |||
117 | err = copy_from_user(reloc_relatives, req->reloc_user, | ||
118 | req->num_relocs * sizeof(uint32_t)) ? -EFAULT : 0; | ||
119 | if (err < 0) { | ||
120 | dev_err(req->dev, "failed to copy request user relocs\n"); | ||
121 | goto cp_fail; | ||
122 | } | ||
123 | |||
124 | dev_dbg(req->dev, "%s: relocating %u addresses", __func__, | ||
125 | req->num_relocs); | ||
126 | |||
127 | for (i = 0; i < req->num_relocs; i++) { | ||
128 | uint32_t reloc_relative = reloc_relatives[i]; | ||
94 | uint32_t reloc_offset = req->request_offset + reloc_relative; | 129 | uint32_t reloc_offset = req->request_offset + reloc_relative; |
95 | 130 | ||
96 | uint64_t surface_raw; | 131 | uint64_t surface_raw; |
@@ -181,6 +216,7 @@ int capture_common_request_pin_and_reloc(struct capture_common_pin_req *req) | |||
181 | req->request_size, DMA_TO_DEVICE); | 216 | req->request_size, DMA_TO_DEVICE); |
182 | } | 217 | } |
183 | 218 | ||
219 | kfree(reloc_relatives); | ||
184 | return 0; | 220 | return 0; |
185 | 221 | ||
186 | fail: | 222 | fail: |
@@ -191,5 +227,10 @@ fail: | |||
191 | for (i = 0; i < req->unpins->num_unpins; i++) | 227 | for (i = 0; i < req->unpins->num_unpins; i++) |
192 | capture_common_unpin_memory(&req->unpins->data[i]); | 228 | capture_common_unpin_memory(&req->unpins->data[i]); |
193 | 229 | ||
230 | cp_fail: | ||
231 | kfree(reloc_relatives); | ||
232 | |||
233 | reloc_fail: | ||
234 | devm_kfree(req->dev, req->unpins); | ||
194 | return err; | 235 | return err; |
195 | } | 236 | } |
diff --git a/drivers/media/platform/tegra/camera/isp/capture_isp.c b/drivers/media/platform/tegra/camera/isp/capture_isp.c index 4da20845a..60a1f08e1 100644 --- a/drivers/media/platform/tegra/camera/isp/capture_isp.c +++ b/drivers/media/platform/tegra/camera/isp/capture_isp.c | |||
@@ -716,14 +716,12 @@ static void isp_capture_request_unpin(struct tegra_isp_channel *chan, | |||
716 | 716 | ||
717 | mutex_lock(&capture->capture_desc_ctx.unpins_list_lock); | 717 | mutex_lock(&capture->capture_desc_ctx.unpins_list_lock); |
718 | unpins = capture->capture_desc_ctx.unpins_list[buffer_index]; | 718 | unpins = capture->capture_desc_ctx.unpins_list[buffer_index]; |
719 | if (unpins == NULL) { | 719 | if (unpins != NULL) { |
720 | mutex_unlock(&capture->capture_desc_ctx.unpins_list_lock); | 720 | for (i = 0; i < unpins->num_unpins; i++) |
721 | return; | 721 | capture_common_unpin_memory(&unpins->data[i]); |
722 | devm_kfree(chan->isp_dev, unpins); | ||
723 | capture->capture_desc_ctx.unpins_list[buffer_index] = NULL; | ||
722 | } | 724 | } |
723 | for (i = 0; i < unpins->num_unpins; i++) | ||
724 | capture_common_unpin_memory(&unpins->data[i]); | ||
725 | devm_kfree(chan->isp_dev, unpins); | ||
726 | capture->capture_desc_ctx.unpins_list[buffer_index] = NULL; | ||
727 | mutex_unlock(&capture->capture_desc_ctx.unpins_list_lock); | 725 | mutex_unlock(&capture->capture_desc_ctx.unpins_list_lock); |
728 | } | 726 | } |
729 | 727 | ||
@@ -736,14 +734,12 @@ static void isp_capture_program_request_unpin(struct tegra_isp_channel *chan, | |||
736 | 734 | ||
737 | mutex_lock(&capture->program_desc_ctx.unpins_list_lock); | 735 | mutex_lock(&capture->program_desc_ctx.unpins_list_lock); |
738 | unpins = capture->program_desc_ctx.unpins_list[buffer_index]; | 736 | unpins = capture->program_desc_ctx.unpins_list[buffer_index]; |
739 | if (unpins == NULL) { | 737 | if (unpins != NULL) { |
740 | mutex_unlock(&capture->program_desc_ctx.unpins_list_lock); | 738 | for (i = 0; i < unpins->num_unpins; i++) |
741 | return; | 739 | capture_common_unpin_memory(&unpins->data[i]); |
740 | devm_kfree(chan->isp_dev, unpins); | ||
741 | capture->program_desc_ctx.unpins_list[buffer_index] = NULL; | ||
742 | } | 742 | } |
743 | for (i = 0; i < unpins->num_unpins; i++) | ||
744 | capture_common_unpin_memory(&unpins->data[i]); | ||
745 | devm_kfree(chan->isp_dev, unpins); | ||
746 | capture->program_desc_ctx.unpins_list[buffer_index] = NULL; | ||
747 | mutex_unlock(&capture->program_desc_ctx.unpins_list_lock); | 743 | mutex_unlock(&capture->program_desc_ctx.unpins_list_lock); |
748 | } | 744 | } |
749 | 745 | ||
@@ -753,10 +749,8 @@ int isp_capture_program_request(struct tegra_isp_channel *chan, | |||
753 | struct isp_capture *capture = chan->capture_data; | 749 | struct isp_capture *capture = chan->capture_data; |
754 | struct CAPTURE_MSG capture_msg; | 750 | struct CAPTURE_MSG capture_msg; |
755 | int err = 0; | 751 | int err = 0; |
756 | struct capture_common_unpins *unpins; | 752 | struct capture_common_unpins *unpins = NULL; |
757 | struct capture_common_pin_req cap_common_req; | 753 | struct capture_common_pin_req cap_common_req; |
758 | struct capture_common_relocs *relocs; | ||
759 | uint32_t __user *reloc_relatives; | ||
760 | 754 | ||
761 | if (capture == NULL) { | 755 | if (capture == NULL) { |
762 | dev_err(chan->isp_dev, | 756 | dev_err(chan->isp_dev, |
@@ -777,35 +771,6 @@ int isp_capture_program_request(struct tegra_isp_channel *chan, | |||
777 | req->buffer_index; | 771 | req->buffer_index; |
778 | 772 | ||
779 | /* memory pin and reloc */ | 773 | /* memory pin and reloc */ |
780 | unpins = devm_kzalloc(chan->isp_dev, | ||
781 | sizeof(struct capture_common_unpins) + | ||
782 | (sizeof(struct capture_common_buf) * | ||
783 | req->isp_program_relocs.num_relocs), | ||
784 | GFP_KERNEL); | ||
785 | if (unpins == NULL) | ||
786 | return -ENOMEM; | ||
787 | |||
788 | relocs = devm_kzalloc(chan->isp_dev, | ||
789 | sizeof(struct capture_common_relocs) + | ||
790 | (sizeof(uint32_t) * req->isp_program_relocs.num_relocs), | ||
791 | GFP_KERNEL); | ||
792 | if (unlikely(relocs == NULL)) { | ||
793 | dev_err(chan->isp_dev, "failed to allocate relocs\n"); | ||
794 | goto fail; | ||
795 | } | ||
796 | |||
797 | relocs->num_relocs = req->isp_program_relocs.num_relocs; | ||
798 | |||
799 | reloc_relatives = (uint32_t __user *) | ||
800 | (uintptr_t)req->isp_program_relocs.reloc_relatives; | ||
801 | |||
802 | err = copy_from_user(relocs->reloc_relatives, reloc_relatives, | ||
803 | relocs->num_relocs * sizeof(uint32_t)) ? -EFAULT : 0; | ||
804 | if (err < 0) { | ||
805 | dev_err(chan->isp_dev, "failed to copy program user-relocs\n"); | ||
806 | goto reloc_fail; | ||
807 | } | ||
808 | |||
809 | cap_common_req.dev = chan->isp_dev; | 774 | cap_common_req.dev = chan->isp_dev; |
810 | cap_common_req.rtcpu_dev = capture->rtcpu_dev; | 775 | cap_common_req.rtcpu_dev = capture->rtcpu_dev; |
811 | cap_common_req.unpins = unpins; | 776 | cap_common_req.unpins = unpins; |
@@ -814,10 +779,16 @@ int isp_capture_program_request(struct tegra_isp_channel *chan, | |||
814 | cap_common_req.request_size = capture->program_desc_ctx.request_size; | 779 | cap_common_req.request_size = capture->program_desc_ctx.request_size; |
815 | cap_common_req.request_offset = req->buffer_index * | 780 | cap_common_req.request_offset = req->buffer_index * |
816 | capture->program_desc_ctx.request_size; | 781 | capture->program_desc_ctx.request_size; |
817 | cap_common_req.relocs = relocs; | ||
818 | cap_common_req.requests_mem = capture->program_desc_ctx.desc_mem; | 782 | cap_common_req.requests_mem = capture->program_desc_ctx.desc_mem; |
783 | cap_common_req.num_relocs = req->isp_program_relocs.num_relocs; | ||
784 | cap_common_req.reloc_user = (uint32_t __user *) | ||
785 | (uintptr_t)req->isp_program_relocs.reloc_relatives; | ||
819 | 786 | ||
820 | capture_common_request_pin_and_reloc(&cap_common_req); | 787 | err = capture_common_request_pin_and_reloc(&cap_common_req); |
788 | if (err < 0) { | ||
789 | dev_err(chan->isp_dev, "request pin and reloc failed\n"); | ||
790 | goto fail; | ||
791 | } | ||
821 | 792 | ||
822 | /* add pinned memory ctx to unpins_list */ | 793 | /* add pinned memory ctx to unpins_list */ |
823 | mutex_lock(&capture->program_desc_ctx.unpins_list_lock); | 794 | mutex_lock(&capture->program_desc_ctx.unpins_list_lock); |
@@ -832,13 +803,11 @@ int isp_capture_program_request(struct tegra_isp_channel *chan, | |||
832 | sizeof(capture_msg)); | 803 | sizeof(capture_msg)); |
833 | if (err < 0) { | 804 | if (err < 0) { |
834 | dev_err(chan->isp_dev, "IVC program submit failed\n"); | 805 | dev_err(chan->isp_dev, "IVC program submit failed\n"); |
835 | goto reloc_fail; | 806 | goto fail; |
836 | } | 807 | } |
837 | 808 | ||
838 | return 0; | 809 | return 0; |
839 | 810 | ||
840 | reloc_fail: | ||
841 | devm_kfree(chan->isp_dev, relocs); | ||
842 | fail: | 811 | fail: |
843 | isp_capture_program_request_unpin(chan, req->buffer_index); | 812 | isp_capture_program_request_unpin(chan, req->buffer_index); |
844 | return err; | 813 | return err; |
@@ -880,10 +849,8 @@ int isp_capture_request(struct tegra_isp_channel *chan, | |||
880 | { | 849 | { |
881 | struct isp_capture *capture = chan->capture_data; | 850 | struct isp_capture *capture = chan->capture_data; |
882 | struct CAPTURE_MSG capture_msg; | 851 | struct CAPTURE_MSG capture_msg; |
883 | struct capture_common_unpins *unpins; | 852 | struct capture_common_unpins *unpins = NULL; |
884 | struct capture_common_pin_req cap_common_req; | 853 | struct capture_common_pin_req cap_common_req; |
885 | struct capture_common_relocs *relocs; | ||
886 | uint32_t __user *reloc_relatives; | ||
887 | int err = 0; | 854 | int err = 0; |
888 | 855 | ||
889 | if (capture == NULL) { | 856 | if (capture == NULL) { |
@@ -903,35 +870,6 @@ int isp_capture_request(struct tegra_isp_channel *chan, | |||
903 | capture_msg.header.channel_id = capture->channel_id; | 870 | capture_msg.header.channel_id = capture->channel_id; |
904 | capture_msg.capture_isp_request_req.buffer_index = req->buffer_index; | 871 | capture_msg.capture_isp_request_req.buffer_index = req->buffer_index; |
905 | 872 | ||
906 | unpins = devm_kzalloc(chan->isp_dev, | ||
907 | sizeof(struct capture_common_unpins) + | ||
908 | (sizeof(struct capture_common_buf) * | ||
909 | req->isp_relocs.num_relocs), | ||
910 | GFP_KERNEL); | ||
911 | if (unpins == NULL) | ||
912 | return -ENOMEM; | ||
913 | |||
914 | relocs = devm_kzalloc(chan->isp_dev, | ||
915 | sizeof(struct capture_common_relocs) + | ||
916 | (sizeof(uint32_t) * req->isp_relocs.num_relocs), | ||
917 | GFP_KERNEL); | ||
918 | if (unlikely(relocs == NULL)) { | ||
919 | dev_err(chan->isp_dev, "failed to allocate relocs\n"); | ||
920 | goto fail; | ||
921 | } | ||
922 | |||
923 | relocs->num_relocs = req->isp_relocs.num_relocs; | ||
924 | |||
925 | reloc_relatives = (uint32_t __user *) | ||
926 | (uintptr_t)req->isp_relocs.reloc_relatives; | ||
927 | |||
928 | err = copy_from_user(relocs->reloc_relatives, reloc_relatives, | ||
929 | relocs->num_relocs * sizeof(uint32_t)) ? -EFAULT : 0; | ||
930 | if (err < 0) { | ||
931 | dev_err(chan->isp_dev, "failed to copy request user relocs\n"); | ||
932 | goto reloc_fail; | ||
933 | } | ||
934 | |||
935 | /* pin and reloc */ | 873 | /* pin and reloc */ |
936 | cap_common_req.dev = chan->isp_dev; | 874 | cap_common_req.dev = chan->isp_dev; |
937 | cap_common_req.rtcpu_dev = capture->rtcpu_dev; | 875 | cap_common_req.rtcpu_dev = capture->rtcpu_dev; |
@@ -941,10 +879,16 @@ int isp_capture_request(struct tegra_isp_channel *chan, | |||
941 | cap_common_req.request_size = capture->capture_desc_ctx.request_size; | 879 | cap_common_req.request_size = capture->capture_desc_ctx.request_size; |
942 | cap_common_req.request_offset = req->buffer_index * | 880 | cap_common_req.request_offset = req->buffer_index * |
943 | capture->capture_desc_ctx.request_size; | 881 | capture->capture_desc_ctx.request_size; |
944 | cap_common_req.relocs = relocs; | ||
945 | cap_common_req.requests_mem = capture->capture_desc_ctx.desc_mem; | 882 | cap_common_req.requests_mem = capture->capture_desc_ctx.desc_mem; |
883 | cap_common_req.num_relocs = req->isp_relocs.num_relocs; | ||
884 | cap_common_req.reloc_user = (uint32_t __user *) | ||
885 | (uintptr_t)req->isp_relocs.reloc_relatives; | ||
946 | 886 | ||
947 | capture_common_request_pin_and_reloc(&cap_common_req); | 887 | err = capture_common_request_pin_and_reloc(&cap_common_req); |
888 | if (err < 0) { | ||
889 | dev_err(chan->isp_dev, "request pin and reloc failed\n"); | ||
890 | goto fail; | ||
891 | } | ||
948 | 892 | ||
949 | /* add pinned memory ctx to unpins_list */ | 893 | /* add pinned memory ctx to unpins_list */ |
950 | mutex_lock(&capture->capture_desc_ctx.unpins_list_lock); | 894 | mutex_lock(&capture->capture_desc_ctx.unpins_list_lock); |
@@ -959,13 +903,11 @@ int isp_capture_request(struct tegra_isp_channel *chan, | |||
959 | sizeof(capture_msg)); | 903 | sizeof(capture_msg)); |
960 | if (err < 0) { | 904 | if (err < 0) { |
961 | dev_err(chan->isp_dev, "IVC capture submit failed\n"); | 905 | dev_err(chan->isp_dev, "IVC capture submit failed\n"); |
962 | goto reloc_fail; | 906 | goto fail; |
963 | } | 907 | } |
964 | 908 | ||
965 | return 0; | 909 | return 0; |
966 | 910 | ||
967 | reloc_fail: | ||
968 | devm_kfree(chan->isp_dev, relocs); | ||
969 | fail: | 911 | fail: |
970 | isp_capture_request_unpin(chan, req->buffer_index); | 912 | isp_capture_request_unpin(chan, req->buffer_index); |
971 | return err; | 913 | return err; |
diff --git a/drivers/media/platform/tegra/camera/vi/capture.c b/drivers/media/platform/tegra/camera/vi/capture.c index c1d24d101..9cf1de17f 100644 --- a/drivers/media/platform/tegra/camera/vi/capture.c +++ b/drivers/media/platform/tegra/camera/vi/capture.c | |||
@@ -11,16 +11,14 @@ | |||
11 | * it under the terms of the GNU General Public License version 2 as | 11 | * it under the terms of the GNU General Public License version 2 as |
12 | * published by the Free Software Foundation. | 12 | * published by the Free Software Foundation. |
13 | */ | 13 | */ |
14 | #include <linux/uaccess.h> | 14 | |
15 | #include <linux/completion.h> | 15 | #include <linux/completion.h> |
16 | #include <linux/dma-buf.h> | ||
17 | #include <linux/dma-mapping.h> | ||
18 | #include <linux/nvhost.h> | 16 | #include <linux/nvhost.h> |
19 | #include <linux/of_platform.h> | 17 | #include <linux/of_platform.h> |
20 | #include <linux/printk.h> | 18 | #include <linux/printk.h> |
21 | #include <linux/scatterlist.h> | ||
22 | #include <linux/tegra-capture-ivc.h> | 19 | #include <linux/tegra-capture-ivc.h> |
23 | #include <media/capture.h> | 20 | #include <media/capture.h> |
21 | #include <media/capture_common.h> | ||
24 | #include <media/capture_vi_channel.h> | 22 | #include <media/capture_vi_channel.h> |
25 | 23 | ||
26 | #include "soc/tegra/camrtc-capture.h" | 24 | #include "soc/tegra/camrtc-capture.h" |
@@ -40,23 +38,11 @@ | |||
40 | #define CAPTURE_CHANNEL_INVALID_ID 0xFFFF | 38 | #define CAPTURE_CHANNEL_INVALID_ID 0xFFFF |
41 | #define CAPTURE_CHANNEL_INVALID_MASK 0llu | 39 | #define CAPTURE_CHANNEL_INVALID_MASK 0llu |
42 | 40 | ||
43 | struct vi_capture_buf { | ||
44 | struct dma_buf *buf; | ||
45 | struct dma_buf_attachment *attach; | ||
46 | struct sg_table *sgt; | ||
47 | dma_addr_t iova; | ||
48 | }; | ||
49 | |||
50 | struct vi_capture_unpins { | ||
51 | uint32_t num_unpins; | ||
52 | struct vi_capture_buf data[]; | ||
53 | }; | ||
54 | |||
55 | struct vi_capture { | 41 | struct vi_capture { |
56 | uint16_t channel_id; | 42 | uint16_t channel_id; |
57 | struct device *rtcpu_dev; | 43 | struct device *rtcpu_dev; |
58 | struct tegra_vi_channel *vi_channel; | 44 | struct tegra_vi_channel *vi_channel; |
59 | struct vi_capture_buf requests; | 45 | struct capture_common_buf requests; |
60 | size_t request_buf_size; | 46 | size_t request_buf_size; |
61 | uint32_t queue_depth; | 47 | uint32_t queue_depth; |
62 | uint32_t request_size; | 48 | uint32_t request_size; |
@@ -71,7 +57,7 @@ struct vi_capture { | |||
71 | struct CAPTURE_CONTROL_MSG control_resp_msg; | 57 | struct CAPTURE_CONTROL_MSG control_resp_msg; |
72 | 58 | ||
73 | struct mutex unpins_list_lock; | 59 | struct mutex unpins_list_lock; |
74 | struct vi_capture_unpins **unpins_list; | 60 | struct capture_common_unpins **unpins_list; |
75 | }; | 61 | }; |
76 | 62 | ||
77 | static void vi_capture_ivc_control_callback(const void *ivc_resp, | 63 | static void vi_capture_ivc_control_callback(const void *ivc_resp, |
@@ -258,67 +244,6 @@ fail: | |||
258 | return err; | 244 | return err; |
259 | } | 245 | } |
260 | 246 | ||
261 | static int pin_memory(struct device *dev, | ||
262 | uint32_t mem, struct vi_capture_buf *unpin_data); | ||
263 | static void unpin_memory(struct vi_capture_buf *unpin_data); | ||
264 | |||
265 | static int pin_memory(struct device *dev, | ||
266 | uint32_t mem, struct vi_capture_buf *unpin_data) | ||
267 | { | ||
268 | struct dma_buf *buf; | ||
269 | struct dma_buf_attachment *attach; | ||
270 | struct sg_table *sgt; | ||
271 | int err = 0; | ||
272 | |||
273 | buf = dma_buf_get(mem); | ||
274 | if (IS_ERR(buf)) { | ||
275 | err = PTR_ERR(buf); | ||
276 | goto fail; | ||
277 | } | ||
278 | |||
279 | attach = dma_buf_attach(buf, dev); | ||
280 | if (IS_ERR(attach)) { | ||
281 | err = PTR_ERR(attach); | ||
282 | goto fail; | ||
283 | } | ||
284 | |||
285 | sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL); | ||
286 | if (IS_ERR(sgt)) { | ||
287 | err = PTR_ERR(sgt); | ||
288 | goto fail; | ||
289 | } | ||
290 | |||
291 | if (sg_dma_address(sgt->sgl) == 0) | ||
292 | sg_dma_address(sgt->sgl) = sg_phys(sgt->sgl); | ||
293 | |||
294 | unpin_data->iova = sg_dma_address(sgt->sgl); | ||
295 | unpin_data->buf = buf; | ||
296 | unpin_data->attach = attach; | ||
297 | unpin_data->sgt = sgt; | ||
298 | |||
299 | return 0; | ||
300 | |||
301 | fail: | ||
302 | unpin_memory(unpin_data); | ||
303 | return err; | ||
304 | } | ||
305 | |||
306 | static void unpin_memory(struct vi_capture_buf *unpin_data) | ||
307 | { | ||
308 | if (unpin_data->sgt != NULL) | ||
309 | dma_buf_unmap_attachment(unpin_data->attach, unpin_data->sgt, | ||
310 | DMA_BIDIRECTIONAL); | ||
311 | if (unpin_data->attach != NULL) | ||
312 | dma_buf_detach(unpin_data->buf, unpin_data->attach); | ||
313 | if (unpin_data->buf != NULL) | ||
314 | dma_buf_put(unpin_data->buf); | ||
315 | |||
316 | unpin_data->sgt = NULL; | ||
317 | unpin_data->attach = NULL; | ||
318 | unpin_data->buf = NULL; | ||
319 | unpin_data->iova = 0; | ||
320 | } | ||
321 | |||
322 | static int vi_capture_setup_syncpts(struct tegra_vi_channel *chan, | 247 | static int vi_capture_setup_syncpts(struct tegra_vi_channel *chan, |
323 | uint32_t flags); | 248 | uint32_t flags); |
324 | static void vi_capture_release_syncpts(struct tegra_vi_channel *chan); | 249 | static void vi_capture_release_syncpts(struct tegra_vi_channel *chan); |
@@ -433,7 +358,8 @@ int vi_capture_setup(struct tegra_vi_channel *chan, | |||
433 | /* pin the capture descriptor ring buffer */ | 358 | /* pin the capture descriptor ring buffer */ |
434 | dev_dbg(chan->dev, "%s: descr buffer handle %u\n", | 359 | dev_dbg(chan->dev, "%s: descr buffer handle %u\n", |
435 | __func__, setup->mem); | 360 | __func__, setup->mem); |
436 | err = pin_memory(capture->rtcpu_dev, setup->mem, &capture->requests); | 361 | err = capture_common_pin_memory(capture->rtcpu_dev, |
362 | setup->mem, &capture->requests); | ||
437 | if (err < 0) { | 363 | if (err < 0) { |
438 | dev_err(chan->dev, "%s: memory setup failed\n", __func__); | 364 | dev_err(chan->dev, "%s: memory setup failed\n", __func__); |
439 | return -EFAULT; | 365 | return -EFAULT; |
@@ -444,7 +370,8 @@ int vi_capture_setup(struct tegra_vi_channel *chan, | |||
444 | 370 | ||
445 | /* allocate for unpin list based on queue depth */ | 371 | /* allocate for unpin list based on queue depth */ |
446 | capture->unpins_list = devm_kzalloc(chan->dev, | 372 | capture->unpins_list = devm_kzalloc(chan->dev, |
447 | sizeof(struct vi_capture_unpins *) * capture->queue_depth, | 373 | sizeof(struct capture_common_unpins *) * |
374 | capture->queue_depth, | ||
448 | GFP_KERNEL); | 375 | GFP_KERNEL); |
449 | if (unlikely(capture->unpins_list == NULL)) { | 376 | if (unlikely(capture->unpins_list == NULL)) { |
450 | dev_err(chan->dev, "failed to allocate unpins array\n"); | 377 | dev_err(chan->dev, "failed to allocate unpins array\n"); |
@@ -521,7 +448,7 @@ control_cb_fail: | |||
521 | syncpt_fail: | 448 | syncpt_fail: |
522 | devm_kfree(chan->dev, capture->unpins_list); | 449 | devm_kfree(chan->dev, capture->unpins_list); |
523 | unpins_list_fail: | 450 | unpins_list_fail: |
524 | unpin_memory(&capture->requests); | 451 | capture_common_unpin_memory(&capture->requests); |
525 | return err; | 452 | return err; |
526 | } | 453 | } |
527 | 454 | ||
@@ -675,7 +602,7 @@ int vi_capture_release(struct tegra_vi_channel *chan, | |||
675 | vi_capture_request_unpin(chan, i); | 602 | vi_capture_request_unpin(chan, i); |
676 | 603 | ||
677 | vi_capture_release_syncpts(chan); | 604 | vi_capture_release_syncpts(chan); |
678 | unpin_memory(&capture->requests); | 605 | capture_common_unpin_memory(&capture->requests); |
679 | 606 | ||
680 | capture->channel_id = CAPTURE_CHANNEL_INVALID_ID; | 607 | capture->channel_id = CAPTURE_CHANNEL_INVALID_ID; |
681 | 608 | ||
@@ -825,136 +752,18 @@ struct surface_t { | |||
825 | uint32_t offset_hi; | 752 | uint32_t offset_hi; |
826 | }; | 753 | }; |
827 | 754 | ||
828 | static int vi_capture_request_pin_and_reloc(struct tegra_vi_channel *chan, | ||
829 | struct vi_capture_req *req) | ||
830 | { | ||
831 | struct vi_capture *capture = chan->capture_data; | ||
832 | uint32_t num_relocs = req->num_relocs; | ||
833 | uint32_t __user *reloc_relatives = | ||
834 | (uint32_t __user *)(uintptr_t)req->reloc_relatives; | ||
835 | uint32_t local_reloc_relatives[VI_NUM_ATOMP_SURFACES]; | ||
836 | struct vi_capture_unpins *unpins; | ||
837 | uint32_t request_offset = req->buffer_index * capture->request_size; | ||
838 | void *reloc_page_addr = NULL; | ||
839 | uint32_t prev_mem = 0; | ||
840 | int last_page = -1; | ||
841 | dma_addr_t surface_phys_addr = 0; | ||
842 | int i = 0; | ||
843 | int err = 0; | ||
844 | |||
845 | err = copy_from_user(local_reloc_relatives, reloc_relatives, | ||
846 | num_relocs * sizeof(uint32_t)) ? -EFAULT : 0; | ||
847 | if (err < 0) | ||
848 | return err; | ||
849 | |||
850 | unpins = devm_kzalloc(chan->dev, | ||
851 | sizeof(struct vi_capture_unpins) + | ||
852 | sizeof(struct vi_capture_buf) * num_relocs, | ||
853 | GFP_KERNEL); | ||
854 | if (unpins == NULL) | ||
855 | return -ENOMEM; | ||
856 | |||
857 | dev_dbg(chan->dev, "%s: relocating %u surfaces\n", | ||
858 | __func__, num_relocs); | ||
859 | for (i = 0; i < num_relocs; i++) { | ||
860 | uint32_t reloc_offset = | ||
861 | request_offset + local_reloc_relatives[i]; | ||
862 | uint64_t surface_raw; | ||
863 | struct surface_t *surface; | ||
864 | uint32_t mem; | ||
865 | uint32_t target_offset; | ||
866 | dma_addr_t target_phys_addr; | ||
867 | |||
868 | dev_dbg(chan->dev, | ||
869 | "%s: idx:%i reloc:%u reloc_offset:%u", __func__, | ||
870 | i, local_reloc_relatives[i], reloc_offset); | ||
871 | |||
872 | /* locate page of the request descr buffer relocation is on */ | ||
873 | if (last_page != reloc_offset >> PAGE_SHIFT) { | ||
874 | if (reloc_page_addr != NULL) | ||
875 | dma_buf_kunmap(capture->requests.buf, last_page, | ||
876 | reloc_page_addr); | ||
877 | |||
878 | reloc_page_addr = dma_buf_kmap(capture->requests.buf, | ||
879 | reloc_offset >> PAGE_SHIFT); | ||
880 | last_page = reloc_offset >> PAGE_SHIFT; | ||
881 | |||
882 | if (unlikely(reloc_page_addr == NULL)) { | ||
883 | dev_err(chan->dev, | ||
884 | "%s: couldn't map request\n", __func__); | ||
885 | goto fail; | ||
886 | } | ||
887 | } | ||
888 | |||
889 | /* read surface offset and memory handle from request descr */ | ||
890 | surface_raw = __raw_readq( | ||
891 | (void __iomem *)(reloc_page_addr + | ||
892 | (reloc_offset & ~PAGE_MASK))); | ||
893 | surface = (struct surface_t *)&surface_raw; | ||
894 | target_offset = surface->offset; | ||
895 | mem = surface->offset_hi; | ||
896 | dev_dbg(chan->dev, "%s: hmem:%u offset:%u\n", __func__, | ||
897 | mem, target_offset); | ||
898 | |||
899 | if (mem != prev_mem) { | ||
900 | err = pin_memory(chan->dev, | ||
901 | mem, &unpins->data[unpins->num_unpins]); | ||
902 | if (err < 0) { | ||
903 | goto fail; | ||
904 | } | ||
905 | unpins->num_unpins++; | ||
906 | surface_phys_addr = unpins->data[i].iova; | ||
907 | } | ||
908 | |||
909 | target_phys_addr = surface_phys_addr + target_offset; | ||
910 | dev_dbg(chan->dev, "%s: surface addr %lx at desc %lx\n", | ||
911 | __func__, (unsigned long)target_phys_addr, | ||
912 | (unsigned long)reloc_page_addr + | ||
913 | (reloc_offset & ~PAGE_MASK)); | ||
914 | |||
915 | /* write relocated physical address to request descr */ | ||
916 | __raw_writeq( | ||
917 | target_phys_addr, | ||
918 | (void __iomem *)(reloc_page_addr + | ||
919 | (reloc_offset & ~PAGE_MASK))); | ||
920 | |||
921 | dma_sync_single_range_for_device(capture->rtcpu_dev, | ||
922 | capture->requests.iova, request_offset, | ||
923 | capture->request_size, DMA_TO_DEVICE); | ||
924 | } | ||
925 | |||
926 | /* assign the unpins list to the capture to be unpinned and */ | ||
927 | /* freed at capture completion (vi_capture_request_unpin) */ | ||
928 | mutex_lock(&capture->unpins_list_lock); | ||
929 | capture->unpins_list[req->buffer_index] = unpins; | ||
930 | mutex_unlock(&capture->unpins_list_lock); | ||
931 | |||
932 | return 0; | ||
933 | |||
934 | fail: | ||
935 | if (reloc_page_addr != NULL) | ||
936 | dma_buf_kunmap(capture->requests.buf, last_page, | ||
937 | reloc_page_addr); | ||
938 | |||
939 | for (i = 0; i < unpins->num_unpins; i++) | ||
940 | unpin_memory(&unpins->data[i]); | ||
941 | devm_kfree(chan->dev, unpins); | ||
942 | |||
943 | return err; | ||
944 | } | ||
945 | |||
946 | static void vi_capture_request_unpin(struct tegra_vi_channel *chan, | 755 | static void vi_capture_request_unpin(struct tegra_vi_channel *chan, |
947 | uint32_t buffer_index) | 756 | uint32_t buffer_index) |
948 | { | 757 | { |
949 | struct vi_capture *capture = chan->capture_data; | 758 | struct vi_capture *capture = chan->capture_data; |
950 | struct vi_capture_unpins *unpins; | 759 | struct capture_common_unpins *unpins; |
951 | int i = 0; | 760 | int i = 0; |
952 | 761 | ||
953 | mutex_lock(&capture->unpins_list_lock); | 762 | mutex_lock(&capture->unpins_list_lock); |
954 | unpins = capture->unpins_list[buffer_index]; | 763 | unpins = capture->unpins_list[buffer_index]; |
955 | if (unpins != NULL) { | 764 | if (unpins != NULL) { |
956 | for (i = 0; i < unpins->num_unpins; i++) | 765 | for (i = 0; i < unpins->num_unpins; i++) |
957 | unpin_memory(&unpins->data[i]); | 766 | capture_common_unpin_memory(&unpins->data[i]); |
958 | capture->unpins_list[buffer_index] = NULL; | 767 | capture->unpins_list[buffer_index] = NULL; |
959 | devm_kfree(chan->dev, unpins); | 768 | devm_kfree(chan->dev, unpins); |
960 | } | 769 | } |
@@ -966,6 +775,8 @@ int vi_capture_request(struct tegra_vi_channel *chan, | |||
966 | { | 775 | { |
967 | struct vi_capture *capture = chan->capture_data; | 776 | struct vi_capture *capture = chan->capture_data; |
968 | struct CAPTURE_MSG capture_desc; | 777 | struct CAPTURE_MSG capture_desc; |
778 | struct capture_common_unpins *unpins = NULL; | ||
779 | struct capture_common_pin_req cap_common_req = {0}; | ||
969 | int err = 0; | 780 | int err = 0; |
970 | 781 | ||
971 | if (capture == NULL) { | 782 | if (capture == NULL) { |
@@ -985,13 +796,31 @@ int vi_capture_request(struct tegra_vi_channel *chan, | |||
985 | capture_desc.header.channel_id = capture->channel_id; | 796 | capture_desc.header.channel_id = capture->channel_id; |
986 | capture_desc.capture_request_req.buffer_index = req->buffer_index; | 797 | capture_desc.capture_request_req.buffer_index = req->buffer_index; |
987 | 798 | ||
988 | /* perform surface pinning and relocation */ | 799 | /* pin and reloc */ |
989 | err = vi_capture_request_pin_and_reloc(chan, req); | 800 | cap_common_req.dev = chan->dev; |
801 | cap_common_req.rtcpu_dev = capture->rtcpu_dev; | ||
802 | cap_common_req.unpins = unpins; | ||
803 | cap_common_req.requests = &capture->requests; | ||
804 | cap_common_req.requests_dev = NULL; | ||
805 | cap_common_req.request_size = capture->request_size; | ||
806 | cap_common_req.request_offset = req->buffer_index * | ||
807 | capture->request_size; | ||
808 | cap_common_req.num_relocs = req->num_relocs; | ||
809 | cap_common_req.reloc_user = (uint32_t __user *) | ||
810 | (uintptr_t)req->reloc_relatives; | ||
811 | |||
812 | err = capture_common_request_pin_and_reloc(&cap_common_req); | ||
990 | if (err < 0) { | 813 | if (err < 0) { |
991 | dev_err(chan->dev, "relocation failed\n"); | 814 | dev_err(chan->dev, "request relocation failed\n"); |
992 | return err; | 815 | return err; |
993 | } | 816 | } |
994 | 817 | ||
818 | /* assign the unpins list to the capture to be unpinned and */ | ||
819 | /* freed at capture completion (vi_capture_request_unpin) */ | ||
820 | mutex_lock(&capture->unpins_list_lock); | ||
821 | capture->unpins_list[req->buffer_index] = unpins; | ||
822 | mutex_unlock(&capture->unpins_list_lock); | ||
823 | |||
995 | dev_dbg(chan->dev, "%s: sending chan_id %u msg_id %u buf:%u\n", | 824 | dev_dbg(chan->dev, "%s: sending chan_id %u msg_id %u buf:%u\n", |
996 | __func__, capture_desc.header.channel_id, | 825 | __func__, capture_desc.header.channel_id, |
997 | capture_desc.header.msg_id, req->buffer_index); | 826 | capture_desc.header.msg_id, req->buffer_index); |