aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/staging/tidspbridge/core/_tiomap.h24
-rw-r--r--drivers/staging/tidspbridge/core/tiomap3430.c153
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/dspdefs.h44
-rw-r--r--drivers/staging/tidspbridge/pmgr/dev.c2
-rw-r--r--drivers/staging/tidspbridge/rmgr/proc.c34
5 files changed, 141 insertions, 116 deletions
diff --git a/drivers/staging/tidspbridge/core/_tiomap.h b/drivers/staging/tidspbridge/core/_tiomap.h
index 877749258acb..c1bf95d756b3 100644
--- a/drivers/staging/tidspbridge/core/_tiomap.h
+++ b/drivers/staging/tidspbridge/core/_tiomap.h
@@ -383,28 +383,4 @@ extern s32 dsp_debug;
383 */ 383 */
384int sm_interrupt_dsp(struct bridge_dev_context *dev_context, u16 mb_val); 384int sm_interrupt_dsp(struct bridge_dev_context *dev_context, u16 mb_val);
385 385
386/**
387 * user_to_dsp_map() - maps user to dsp virtual address
388 * @mmu: Pointer to iommu handle.
389 * @uva: Virtual user space address.
390 * @da DSP address
391 * @size Buffer size to map.
392 * @usr_pgs struct page array pointer where the user pages will be stored
393 *
394 * This function maps a user space buffer into DSP virtual address.
395 *
396 */
397u32 user_to_dsp_map(struct iommu *mmu, u32 uva, u32 da, u32 size,
398 struct page **usr_pgs);
399
400/**
401 * user_to_dsp_unmap() - unmaps DSP virtual buffer.
402 * @mmu: Pointer to iommu handle.
403 * @da DSP address
404 *
405 * This function unmaps a user space buffer into DSP virtual address.
406 *
407 */
408int user_to_dsp_unmap(struct iommu *mmu, u32 da);
409
410#endif /* _TIOMAP_ */ 386#endif /* _TIOMAP_ */
diff --git a/drivers/staging/tidspbridge/core/tiomap3430.c b/drivers/staging/tidspbridge/core/tiomap3430.c
index a342feed42f6..7ab272ca643d 100644
--- a/drivers/staging/tidspbridge/core/tiomap3430.c
+++ b/drivers/staging/tidspbridge/core/tiomap3430.c
@@ -109,6 +109,12 @@ static int bridge_brd_mem_copy(struct bridge_dev_context *dev_ctxt,
109static int bridge_brd_mem_write(struct bridge_dev_context *dev_ctxt, 109static int bridge_brd_mem_write(struct bridge_dev_context *dev_ctxt,
110 u8 *host_buff, u32 dsp_addr, 110 u8 *host_buff, u32 dsp_addr,
111 u32 ul_num_bytes, u32 mem_type); 111 u32 ul_num_bytes, u32 mem_type);
112static int bridge_brd_mem_map(struct bridge_dev_context *dev_ctxt,
113 u32 ul_mpu_addr, u32 virt_addr,
114 u32 ul_num_bytes, u32 ul_map_attr,
115 struct page **mapped_pages);
116static int bridge_brd_mem_un_map(struct bridge_dev_context *dev_ctxt,
117 u32 da);
112static int bridge_dev_create(struct bridge_dev_context 118static int bridge_dev_create(struct bridge_dev_context
113 **dev_cntxt, 119 **dev_cntxt,
114 struct dev_object *hdev_obj, 120 struct dev_object *hdev_obj,
@@ -116,6 +122,9 @@ static int bridge_dev_create(struct bridge_dev_context
116static int bridge_dev_ctrl(struct bridge_dev_context *dev_context, 122static int bridge_dev_ctrl(struct bridge_dev_context *dev_context,
117 u32 dw_cmd, void *pargs); 123 u32 dw_cmd, void *pargs);
118static int bridge_dev_destroy(struct bridge_dev_context *dev_ctxt); 124static int bridge_dev_destroy(struct bridge_dev_context *dev_ctxt);
125static int get_io_pages(struct mm_struct *mm, u32 uva, unsigned pages,
126 struct page **usr_pgs);
127static u32 user_va2_pa(struct mm_struct *mm, u32 address);
119static int pte_update(struct bridge_dev_context *dev_ctxt, u32 pa, 128static int pte_update(struct bridge_dev_context *dev_ctxt, u32 pa,
120 u32 va, u32 size, 129 u32 va, u32 size,
121 struct hw_mmu_map_attrs_t *map_attrs); 130 struct hw_mmu_map_attrs_t *map_attrs);
@@ -185,6 +194,8 @@ static struct bridge_drv_interface drv_interface_fxns = {
185 bridge_brd_set_state, 194 bridge_brd_set_state,
186 bridge_brd_mem_copy, 195 bridge_brd_mem_copy,
187 bridge_brd_mem_write, 196 bridge_brd_mem_write,
197 bridge_brd_mem_map,
198 bridge_brd_mem_un_map,
188 /* The following CHNL functions are provided by chnl_io.lib: */ 199 /* The following CHNL functions are provided by chnl_io.lib: */
189 bridge_chnl_create, 200 bridge_chnl_create,
190 bridge_chnl_destroy, 201 bridge_chnl_destroy,
@@ -1155,77 +1166,22 @@ static int bridge_brd_mem_write(struct bridge_dev_context *dev_ctxt,
1155} 1166}
1156 1167
1157/* 1168/*
1158 * ======== user_va2_pa ======== 1169 * ======== bridge_brd_mem_map ========
1159 * Purpose: 1170 * This function maps MPU buffer to the DSP address space. It performs
1160 * This function walks through the page tables to convert a userland 1171 * linear to physical address translation if required. It translates each
1161 * virtual address to physical address 1172 * page since linear addresses can be physically non-contiguous
1162 */ 1173 * All address & size arguments are assumed to be page aligned (in proc.c)
1163static u32 user_va2_pa(struct mm_struct *mm, u32 address)
1164{
1165 pgd_t *pgd;
1166 pmd_t *pmd;
1167 pte_t *ptep, pte;
1168
1169 pgd = pgd_offset(mm, address);
1170 if (!(pgd_none(*pgd) || pgd_bad(*pgd))) {
1171 pmd = pmd_offset(pgd, address);
1172 if (!(pmd_none(*pmd) || pmd_bad(*pmd))) {
1173 ptep = pte_offset_map(pmd, address);
1174 if (ptep) {
1175 pte = *ptep;
1176 if (pte_present(pte))
1177 return pte & PAGE_MASK;
1178 }
1179 }
1180 }
1181
1182 return 0;
1183}
1184
1185/**
1186 * get_io_pages() - pin and get pages of io user's buffer.
1187 * @mm: mm_struct Pointer of the process.
1188 * @uva: Virtual user space address.
1189 * @pages Pages to be pined.
1190 * @usr_pgs struct page array pointer where the user pages will be stored
1191 * 1174 *
1175 * TODO: Disable MMU while updating the page tables (but that'll stall DSP)
1192 */ 1176 */
1193static int get_io_pages(struct mm_struct *mm, u32 uva, unsigned pages, 1177static int bridge_brd_mem_map(struct bridge_dev_context *dev_ctx,
1194 struct page **usr_pgs) 1178 u32 uva, u32 da, u32 size, u32 attr,
1195{ 1179 struct page **usr_pgs)
1196 u32 pa;
1197 int i;
1198 struct page *pg;
1199
1200 for (i = 0; i < pages; i++) {
1201 pa = user_va2_pa(mm, uva);
1202 1180
1203 if (!pfn_valid(__phys_to_pfn(pa)))
1204 break;
1205
1206 pg = PHYS_TO_PAGE(pa);
1207 usr_pgs[i] = pg;
1208 get_page(pg);
1209 }
1210 return i;
1211}
1212
1213/**
1214 * user_to_dsp_map() - maps user to dsp virtual address
1215 * @mmu: Pointer to iommu handle.
1216 * @uva: Virtual user space address.
1217 * @da DSP address
1218 * @size Buffer size to map.
1219 * @usr_pgs struct page array pointer where the user pages will be stored
1220 *
1221 * This function maps a user space buffer into DSP virtual address.
1222 *
1223 */
1224u32 user_to_dsp_map(struct iommu *mmu, u32 uva, u32 da, u32 size,
1225 struct page **usr_pgs)
1226{ 1181{
1227 int res, w; 1182 int res, w;
1228 unsigned pages, i; 1183 unsigned pages, i;
1184 struct iommu *mmu = dev_ctx->dsp_mmu;
1229 struct vm_area_struct *vma; 1185 struct vm_area_struct *vma;
1230 struct mm_struct *mm = current->mm; 1186 struct mm_struct *mm = current->mm;
1231 struct sg_table *sgt; 1187 struct sg_table *sgt;
@@ -1282,7 +1238,7 @@ u32 user_to_dsp_map(struct iommu *mmu, u32 uva, u32 da, u32 size,
1282 da = iommu_vmap(mmu, da, sgt, IOVMF_ENDIAN_LITTLE | IOVMF_ELSZ_32); 1238 da = iommu_vmap(mmu, da, sgt, IOVMF_ENDIAN_LITTLE | IOVMF_ELSZ_32);
1283 1239
1284 if (!IS_ERR_VALUE(da)) 1240 if (!IS_ERR_VALUE(da))
1285 return da; 1241 return 0;
1286 res = (int)da; 1242 res = (int)da;
1287 1243
1288 sg_free_table(sgt); 1244 sg_free_table(sgt);
@@ -1295,21 +1251,21 @@ err_pages:
1295 return res; 1251 return res;
1296} 1252}
1297 1253
1298/** 1254/*
1299 * user_to_dsp_unmap() - unmaps DSP virtual buffer. 1255 * ======== bridge_brd_mem_un_map ========
1300 * @mmu: Pointer to iommu handle. 1256 * Invalidate the PTEs for the DSP VA block to be unmapped.
1301 * @da DSP address
1302 *
1303 * This function unmaps a user space buffer into DSP virtual address.
1304 * 1257 *
1258 * PTEs of a mapped memory block are contiguous in any page table
1259 * So, instead of looking up the PTE address for every 4K block,
1260 * we clear consecutive PTEs until we unmap all the bytes
1305 */ 1261 */
1306int user_to_dsp_unmap(struct iommu *mmu, u32 da) 1262static int bridge_brd_mem_un_map(struct bridge_dev_context *dev_ctx, u32 da)
1307{ 1263{
1308 unsigned i; 1264 unsigned i;
1309 struct sg_table *sgt; 1265 struct sg_table *sgt;
1310 struct scatterlist *sg; 1266 struct scatterlist *sg;
1311 1267
1312 sgt = iommu_vunmap(mmu, da); 1268 sgt = iommu_vunmap(dev_ctx->dsp_mmu, da);
1313 if (!sgt) 1269 if (!sgt)
1314 return -EFAULT; 1270 return -EFAULT;
1315 1271
@@ -1321,6 +1277,55 @@ int user_to_dsp_unmap(struct iommu *mmu, u32 da)
1321 return 0; 1277 return 0;
1322} 1278}
1323 1279
1280
1281static int get_io_pages(struct mm_struct *mm, u32 uva, unsigned pages,
1282 struct page **usr_pgs)
1283{
1284 u32 pa;
1285 int i;
1286 struct page *pg;
1287
1288 for (i = 0; i < pages; i++) {
1289 pa = user_va2_pa(mm, uva);
1290
1291 if (!pfn_valid(__phys_to_pfn(pa)))
1292 break;
1293
1294 pg = PHYS_TO_PAGE(pa);
1295 usr_pgs[i] = pg;
1296 get_page(pg);
1297 }
1298 return i;
1299}
1300
1301/*
1302 * ======== user_va2_pa ========
1303 * Purpose:
1304 * This function walks through the page tables to convert a userland
1305 * virtual address to physical address
1306 */
1307static u32 user_va2_pa(struct mm_struct *mm, u32 address)
1308{
1309 pgd_t *pgd;
1310 pmd_t *pmd;
1311 pte_t *ptep, pte;
1312
1313 pgd = pgd_offset(mm, address);
1314 if (!(pgd_none(*pgd) || pgd_bad(*pgd))) {
1315 pmd = pmd_offset(pgd, address);
1316 if (!(pmd_none(*pmd) || pmd_bad(*pmd))) {
1317 ptep = pte_offset_map(pmd, address);
1318 if (ptep) {
1319 pte = *ptep;
1320 if (pte_present(pte))
1321 return pte & PAGE_MASK;
1322 }
1323 }
1324 }
1325
1326 return 0;
1327}
1328
1324/* 1329/*
1325 * ======== pte_update ======== 1330 * ======== pte_update ========
1326 * This function calculates the optimum page-aligned addresses and sizes 1331 * This function calculates the optimum page-aligned addresses and sizes
diff --git a/drivers/staging/tidspbridge/include/dspbridge/dspdefs.h b/drivers/staging/tidspbridge/include/dspbridge/dspdefs.h
index 615363474810..173dfbb42019 100644
--- a/drivers/staging/tidspbridge/include/dspbridge/dspdefs.h
+++ b/drivers/staging/tidspbridge/include/dspbridge/dspdefs.h
@@ -162,6 +162,48 @@ typedef int(*fxn_brd_memwrite) (struct bridge_dev_context
162 u32 mem_type); 162 u32 mem_type);
163 163
164/* 164/*
165 * ======== bridge_brd_mem_map ========
166 * Purpose:
167 * Map a MPU memory region to a DSP/IVA memory space
168 * Parameters:
169 * dev_ctxt: Handle to Bridge driver defined device info.
170 * ul_mpu_addr: MPU memory region start address.
171 * virt_addr: DSP/IVA memory region u8 address.
172 * ul_num_bytes: Number of bytes to map.
173 * map_attrs: Mapping attributes (e.g. endianness).
174 * Returns:
175 * 0: Success.
176 * -EPERM: Other, unspecified error.
177 * Requires:
178 * dev_ctxt != NULL;
179 * Ensures:
180 */
181typedef int(*fxn_brd_memmap) (struct bridge_dev_context
182 * dev_ctxt, u32 ul_mpu_addr,
183 u32 virt_addr, u32 ul_num_bytes,
184 u32 map_attr,
185 struct page **mapped_pages);
186
187/*
188 * ======== bridge_brd_mem_un_map ========
189 * Purpose:
190 * UnMap an MPU memory region from DSP/IVA memory space
191 * Parameters:
192 * dev_ctxt: Handle to Bridge driver defined device info.
193 * virt_addr: DSP/IVA memory region u8 address.
194 * ul_num_bytes: Number of bytes to unmap.
195 * Returns:
196 * 0: Success.
197 * -EPERM: Other, unspecified error.
198 * Requires:
199 * dev_ctxt != NULL;
200 * Ensures:
201 */
202typedef int(*fxn_brd_memunmap) (struct bridge_dev_context
203 * dev_ctxt,
204 u32 da);
205
206/*
165 * ======== bridge_brd_stop ======== 207 * ======== bridge_brd_stop ========
166 * Purpose: 208 * Purpose:
167 * Bring board to the BRD_STOPPED state. 209 * Bring board to the BRD_STOPPED state.
@@ -951,6 +993,8 @@ struct bridge_drv_interface {
951 fxn_brd_setstate pfn_brd_set_state; /* Sets the Board State */ 993 fxn_brd_setstate pfn_brd_set_state; /* Sets the Board State */
952 fxn_brd_memcopy pfn_brd_mem_copy; /* Copies DSP Memory */ 994 fxn_brd_memcopy pfn_brd_mem_copy; /* Copies DSP Memory */
953 fxn_brd_memwrite pfn_brd_mem_write; /* Write DSP Memory w/o halt */ 995 fxn_brd_memwrite pfn_brd_mem_write; /* Write DSP Memory w/o halt */
996 fxn_brd_memmap pfn_brd_mem_map; /* Maps MPU mem to DSP mem */
997 fxn_brd_memunmap pfn_brd_mem_un_map; /* Unmaps MPU mem to DSP mem */
954 fxn_chnl_create pfn_chnl_create; /* Create channel manager. */ 998 fxn_chnl_create pfn_chnl_create; /* Create channel manager. */
955 fxn_chnl_destroy pfn_chnl_destroy; /* Destroy channel manager. */ 999 fxn_chnl_destroy pfn_chnl_destroy; /* Destroy channel manager. */
956 fxn_chnl_open pfn_chnl_open; /* Create a new channel. */ 1000 fxn_chnl_open pfn_chnl_open; /* Create a new channel. */
diff --git a/drivers/staging/tidspbridge/pmgr/dev.c b/drivers/staging/tidspbridge/pmgr/dev.c
index e3c78fbfb3c0..132e960967b9 100644
--- a/drivers/staging/tidspbridge/pmgr/dev.c
+++ b/drivers/staging/tidspbridge/pmgr/dev.c
@@ -1118,6 +1118,8 @@ static void store_interface_fxns(struct bridge_drv_interface *drv_fxns,
1118 STORE_FXN(fxn_brd_setstate, pfn_brd_set_state); 1118 STORE_FXN(fxn_brd_setstate, pfn_brd_set_state);
1119 STORE_FXN(fxn_brd_memcopy, pfn_brd_mem_copy); 1119 STORE_FXN(fxn_brd_memcopy, pfn_brd_mem_copy);
1120 STORE_FXN(fxn_brd_memwrite, pfn_brd_mem_write); 1120 STORE_FXN(fxn_brd_memwrite, pfn_brd_mem_write);
1121 STORE_FXN(fxn_brd_memmap, pfn_brd_mem_map);
1122 STORE_FXN(fxn_brd_memunmap, pfn_brd_mem_un_map);
1121 STORE_FXN(fxn_chnl_create, pfn_chnl_create); 1123 STORE_FXN(fxn_chnl_create, pfn_chnl_create);
1122 STORE_FXN(fxn_chnl_destroy, pfn_chnl_destroy); 1124 STORE_FXN(fxn_chnl_destroy, pfn_chnl_destroy);
1123 STORE_FXN(fxn_chnl_open, pfn_chnl_open); 1125 STORE_FXN(fxn_chnl_open, pfn_chnl_open);
diff --git a/drivers/staging/tidspbridge/rmgr/proc.c b/drivers/staging/tidspbridge/rmgr/proc.c
index 59c946bb3ed2..97c5b61f1014 100644
--- a/drivers/staging/tidspbridge/rmgr/proc.c
+++ b/drivers/staging/tidspbridge/rmgr/proc.c
@@ -52,7 +52,6 @@
52#include <dspbridge/msg.h> 52#include <dspbridge/msg.h>
53#include <dspbridge/dspioctl.h> 53#include <dspbridge/dspioctl.h>
54#include <dspbridge/drv.h> 54#include <dspbridge/drv.h>
55#include <_tiomap.h>
56 55
57/* ----------------------------------- This */ 56/* ----------------------------------- This */
58#include <dspbridge/proc.h> 57#include <dspbridge/proc.h>
@@ -1358,6 +1357,7 @@ int proc_map(void *hprocessor, void *pmpu_addr, u32 ul_size,
1358 int status = 0; 1357 int status = 0;
1359 struct proc_object *p_proc_object = (struct proc_object *)hprocessor; 1358 struct proc_object *p_proc_object = (struct proc_object *)hprocessor;
1360 struct dmm_map_object *map_obj; 1359 struct dmm_map_object *map_obj;
1360 u32 tmp_addr = 0;
1361 1361
1362#ifdef CONFIG_TIDSPBRIDGE_CACHE_LINE_CHECK 1362#ifdef CONFIG_TIDSPBRIDGE_CACHE_LINE_CHECK
1363 if ((ul_map_attr & BUFMODE_MASK) != RBUF) { 1363 if ((ul_map_attr & BUFMODE_MASK) != RBUF) {
@@ -1390,27 +1390,24 @@ int proc_map(void *hprocessor, void *pmpu_addr, u32 ul_size,
1390 1390
1391 /* Add mapping to the page tables. */ 1391 /* Add mapping to the page tables. */
1392 if (!status) { 1392 if (!status) {
1393
1394 /* Mapped address = MSB of VA | LSB of PA */
1395 tmp_addr = (va_align | ((u32) pmpu_addr & (PG_SIZE4K - 1)));
1393 /* mapped memory resource tracking */ 1396 /* mapped memory resource tracking */
1394 map_obj = add_mapping_info(pr_ctxt, pa_align, va_align, 1397 map_obj = add_mapping_info(pr_ctxt, pa_align, tmp_addr,
1395 size_align); 1398 size_align);
1396 if (!map_obj) { 1399 if (!map_obj)
1397 status = -ENOMEM; 1400 status = -ENOMEM;
1398 } else { 1401 else
1399 va_align = user_to_dsp_map( 1402 status = (*p_proc_object->intf_fxns->pfn_brd_mem_map)
1400 p_proc_object->hbridge_context->dsp_mmu, 1403 (p_proc_object->hbridge_context, pa_align, va_align,
1401 pa_align, va_align, size_align, 1404 size_align, ul_map_attr, map_obj->pages);
1402 map_obj->pages);
1403 if (IS_ERR_VALUE(va_align))
1404 status = (int)va_align;
1405 }
1406 } 1405 }
1407 if (!status) { 1406 if (!status) {
1408 /* Mapped address = MSB of VA | LSB of PA */ 1407 /* Mapped address = MSB of VA | LSB of PA */
1409 map_obj->dsp_addr = (va_align | 1408 *pp_map_addr = (void *) tmp_addr;
1410 ((u32)pmpu_addr & (PG_SIZE4K - 1)));
1411 *pp_map_addr = (void *)map_obj->dsp_addr;
1412 } else { 1409 } else {
1413 remove_mapping_information(pr_ctxt, va_align, size_align); 1410 remove_mapping_information(pr_ctxt, tmp_addr, size_align);
1414 dmm_un_map_memory(dmm_mgr, va_align, &size_align); 1411 dmm_un_map_memory(dmm_mgr, va_align, &size_align);
1415 } 1412 }
1416 mutex_unlock(&proc_lock); 1413 mutex_unlock(&proc_lock);
@@ -1724,9 +1721,10 @@ int proc_un_map(void *hprocessor, void *map_addr,
1724 */ 1721 */
1725 status = dmm_un_map_memory(dmm_mgr, (u32) va_align, &size_align); 1722 status = dmm_un_map_memory(dmm_mgr, (u32) va_align, &size_align);
1726 /* Remove mapping from the page tables. */ 1723 /* Remove mapping from the page tables. */
1727 if (!status) 1724 if (!status) {
1728 status = user_to_dsp_unmap( 1725 status = (*p_proc_object->intf_fxns->pfn_brd_mem_un_map)
1729 p_proc_object->hbridge_context->dsp_mmu, va_align); 1726 (p_proc_object->hbridge_context, va_align);
1727 }
1730 1728
1731 mutex_unlock(&proc_lock); 1729 mutex_unlock(&proc_lock);
1732 if (status) 1730 if (status)