1/* 2 * dspapi.c 3 * 4 * DSP-BIOS Bridge driver support functions for TI OMAP processors. 5 * 6 * Common DSP API functions, also includes the wrapper 7 * functions called directly by the DeviceIOControl interface. 8 * 9 * Copyright (C) 2005-2006 Texas Instruments, Inc. 10 * 11 * This package is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License version 2 as 13 * published by the Free Software Foundation. 14 * 15 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 17 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 18 */ 19#include <linux/types.h> 20 21/* ----------------------------------- Host OS */ 22#include <dspbridge/host_os.h> 23 24/* ----------------------------------- DSP/BIOS Bridge */ 25#include <dspbridge/dbdefs.h> 26 27/* ----------------------------------- Trace & Debug */ 28#include <dspbridge/dbc.h> 29 30/* ----------------------------------- OS Adaptation Layer */ 31#include <dspbridge/cfg.h> 32#include <dspbridge/ntfy.h> 33#include <dspbridge/services.h> 34 35/* ----------------------------------- Platform Manager */ 36#include <dspbridge/chnl.h> 37#include <dspbridge/dev.h> 38#include <dspbridge/drv.h> 39 40#include <dspbridge/proc.h> 41#include <dspbridge/strm.h> 42 43/* ----------------------------------- Resource Manager */ 44#include <dspbridge/disp.h> 45#include <dspbridge/mgr.h> 46#include <dspbridge/node.h> 47#include <dspbridge/rmm.h> 48 49/* ----------------------------------- Others */ 50#include <dspbridge/msg.h> 51#include <dspbridge/cmm.h> 52#include <dspbridge/io.h> 53 54/* ----------------------------------- This */ 55#include <dspbridge/dspapi.h> 56#include <dspbridge/dbdcd.h> 57 58#include <dspbridge/resourcecleanup.h> 59 60/* ----------------------------------- Defines, Data Structures, Typedefs */ 61#define MAX_TRACEBUFLEN 255 62#define MAX_LOADARGS 16 63#define MAX_NODES 64 64#define MAX_STREAMS 16 65#define MAX_BUFS 64 66 67/* Used to get dspbridge ioctl table */ 68#define DB_GET_IOC_TABLE(cmd) (DB_GET_MODULE(cmd) >> DB_MODULE_SHIFT) 69 70/* Device IOCtl function pointer */ 71struct api_cmd { 72 u32(*fxn) (union trapped_args *args, void *pr_ctxt); 73 u32 dw_index; 74}; 75 76/* ----------------------------------- Globals */ 77static u32 api_c_refs; 78 79/* 80 * Function tables. 81 * The order of these functions MUST be the same as the order of the command 82 * numbers defined in dspapi-ioctl.h This is how an IOCTL number in user mode 83 * turns into a function call in kernel mode. 84 */ 85 86/* MGR wrapper functions */ 87static struct api_cmd mgr_cmd[] = { 88 {mgrwrap_enum_node_info}, /* MGR_ENUMNODE_INFO */ 89 {mgrwrap_enum_proc_info}, /* MGR_ENUMPROC_INFO */ 90 {mgrwrap_register_object}, /* MGR_REGISTEROBJECT */ 91 {mgrwrap_unregister_object}, /* MGR_UNREGISTEROBJECT */ 92 {mgrwrap_wait_for_bridge_events}, /* MGR_WAIT */ 93 {mgrwrap_get_process_resources_info}, /* MGR_GET_PROC_RES */ 94}; 95 96/* PROC wrapper functions */ 97static struct api_cmd proc_cmd[] = { 98 {procwrap_attach}, /* PROC_ATTACH */ 99 {procwrap_ctrl}, /* PROC_CTRL */ 100 {procwrap_detach}, /* PROC_DETACH */ 101 {procwrap_enum_node_info}, /* PROC_ENUMNODE */ 102 {procwrap_enum_resources}, /* PROC_ENUMRESOURCES */ 103 {procwrap_get_state}, /* PROC_GET_STATE */ 104 {procwrap_get_trace}, /* PROC_GET_TRACE */ 105 {procwrap_load}, /* PROC_LOAD */ 106 {procwrap_register_notify}, /* PROC_REGISTERNOTIFY */ 107 {procwrap_start}, /* PROC_START */ 108 {procwrap_reserve_memory}, /* PROC_RSVMEM */ 109 {procwrap_un_reserve_memory}, /* PROC_UNRSVMEM */ 110 {procwrap_map}, /* PROC_MAPMEM */ 111 {procwrap_un_map}, /* PROC_UNMAPMEM */ 112 {procwrap_flush_memory}, /* PROC_FLUSHMEMORY */ 113 {procwrap_stop}, /* PROC_STOP */ 114 {procwrap_invalidate_memory}, /* PROC_INVALIDATEMEMORY */ 115 {procwrap_begin_dma}, /* PROC_BEGINDMA */ 116 {procwrap_end_dma}, /* PROC_ENDDMA */ 117}; 118 119/* NODE wrapper functions */ 120static struct api_cmd node_cmd[] = { 121 {nodewrap_allocate}, /* NODE_ALLOCATE */ 122 {nodewrap_alloc_msg_buf}, /* NODE_ALLOCMSGBUF */ 123 {nodewrap_change_priority}, /* NODE_CHANGEPRIORITY */ 124 {nodewrap_connect}, /* NODE_CONNECT */ 125 {nodewrap_create}, /* NODE_CREATE */ 126 {nodewrap_delete}, /* NODE_DELETE */ 127 {nodewrap_free_msg_buf}, /* NODE_FREEMSGBUF */ 128 {nodewrap_get_attr}, /* NODE_GETATTR */ 129 {nodewrap_get_message}, /* NODE_GETMESSAGE */ 130 {nodewrap_pause}, /* NODE_PAUSE */ 131 {nodewrap_put_message}, /* NODE_PUTMESSAGE */ 132 {nodewrap_register_notify}, /* NODE_REGISTERNOTIFY */ 133 {nodewrap_run}, /* NODE_RUN */ 134 {nodewrap_terminate}, /* NODE_TERMINATE */ 135 {nodewrap_get_uuid_props}, /* NODE_GETUUIDPROPS */ 136}; 137 138/* STRM wrapper functions */ 139static struct api_cmd strm_cmd[] = { 140 {strmwrap_allocate_buffer}, /* STRM_ALLOCATEBUFFER */ 141 {strmwrap_close}, /* STRM_CLOSE */ 142 {strmwrap_free_buffer}, /* STRM_FREEBUFFER */ 143 {strmwrap_get_event_handle}, /* STRM_GETEVENTHANDLE */ 144 {strmwrap_get_info}, /* STRM_GETINFO */ 145 {strmwrap_idle}, /* STRM_IDLE */ 146 {strmwrap_issue}, /* STRM_ISSUE */ 147 {strmwrap_open}, /* STRM_OPEN */ 148 {strmwrap_reclaim}, /* STRM_RECLAIM */ 149 {strmwrap_register_notify}, /* STRM_REGISTERNOTIFY */ 150 {strmwrap_select}, /* STRM_SELECT */ 151}; 152 153/* CMM wrapper functions */ 154static struct api_cmd cmm_cmd[] = { 155 {cmmwrap_calloc_buf}, /* CMM_ALLOCBUF */ 156 {cmmwrap_free_buf}, /* CMM_FREEBUF */ 157 {cmmwrap_get_handle}, /* CMM_GETHANDLE */ 158 {cmmwrap_get_info}, /* CMM_GETINFO */ 159}; 160 161/* Array used to store ioctl table sizes. It can hold up to 8 entries */ 162static u8 size_cmd[] = { 163 ARRAY_SIZE(mgr_cmd), 164 ARRAY_SIZE(proc_cmd), 165 ARRAY_SIZE(node_cmd), 166 ARRAY_SIZE(strm_cmd), 167 ARRAY_SIZE(cmm_cmd), 168}; 169 170static inline void _cp_fm_usr(void *to, const void __user * from, 171 int *err, unsigned long bytes) 172{ 173 if (*err) 174 return; 175 176 if (unlikely(!from)) { 177 *err = -EFAULT; 178 return; 179 } 180 181 if (unlikely(copy_from_user(to, from, bytes))) 182 *err = -EFAULT; 183} 184 185#define CP_FM_USR(to, from, err, n) \ 186 _cp_fm_usr(to, from, &(err), (n) * sizeof(*(to))) 187 188static inline void _cp_to_usr(void __user *to, const void *from, 189 int *err, unsigned long bytes) 190{ 191 if (*err) 192 return; 193 194 if (unlikely(!to)) { 195 *err = -EFAULT; 196 return; 197 } 198 199 if (unlikely(copy_to_user(to, from, bytes))) 200 *err = -EFAULT; 201} 202 203#define CP_TO_USR(to, from, err, n) \ 204 _cp_to_usr(to, from, &(err), (n) * sizeof(*(from))) 205 206/* 207 * ======== api_call_dev_ioctl ======== 208 * Purpose: 209 * Call the (wrapper) function for the corresponding API IOCTL. 210 */ 211inline int api_call_dev_ioctl(u32 cmd, union trapped_args *args, 212 u32 *result, void *pr_ctxt) 213{ 214 u32(*ioctl_cmd) (union trapped_args *args, void *pr_ctxt) = NULL; 215 int i; 216 217 if (_IOC_TYPE(cmd) != DB) { 218 pr_err("%s: Incompatible dspbridge ioctl number\n", __func__); 219 goto err; 220 } 221 222 if (DB_GET_IOC_TABLE(cmd) > ARRAY_SIZE(size_cmd)) { 223 pr_err("%s: undefined ioctl module\n", __func__); 224 goto err; 225 } 226 227 /* Check the size of the required cmd table */ 228 i = DB_GET_IOC(cmd); 229 if (i > size_cmd[DB_GET_IOC_TABLE(cmd)]) { 230 pr_err("%s: requested ioctl %d out of bounds for table %d\n", 231 __func__, i, DB_GET_IOC_TABLE(cmd)); 232 goto err; 233 } 234 235 switch (DB_GET_MODULE(cmd)) { 236 case DB_MGR: 237 ioctl_cmd = mgr_cmd[i].fxn; 238 break; 239 case DB_PROC: 240 ioctl_cmd = proc_cmd[i].fxn; 241 break; 242 case DB_NODE: 243 ioctl_cmd = node_cmd[i].fxn; 244 break; 245 case DB_STRM: 246 ioctl_cmd = strm_cmd[i].fxn; 247 break; 248 case DB_CMM: 249 ioctl_cmd = cmm_cmd[i].fxn; 250 break; 251 } 252 253 if (!ioctl_cmd) { 254 pr_err("%s: requested ioctl not defined\n", __func__); 255 goto err; 256 } else { 257 *result = (*ioctl_cmd) (args, pr_ctxt); 258 } 259 260 return 0; 261 262err: 263 return -EINVAL; 264} 265 266/* 267 * ======== api_exit ======== 268 */ 269void api_exit(void) 270{ 271 DBC_REQUIRE(api_c_refs > 0); 272 api_c_refs--; 273 274 if (api_c_refs == 0) { 275 /* Release all modules initialized in api_init(). */ 276 cod_exit(); 277 dev_exit(); 278 chnl_exit(); 279 msg_exit(); 280 io_exit(); 281 strm_exit(); 282 disp_exit(); 283 node_exit(); 284 proc_exit(); 285 mgr_exit(); 286 rmm_exit(); 287 drv_exit(); 288 } 289 DBC_ENSURE(api_c_refs >= 0); 290} 291 292/* 293 * ======== api_init ======== 294 * Purpose: 295 * Module initialization used by Bridge API. 296 */ 297bool api_init(void) 298{ 299 bool ret = true; 300 bool fdrv, fdev, fcod, fchnl, fmsg, fio; 301 bool fmgr, fproc, fnode, fdisp, fstrm, frmm; 302 303 if (api_c_refs == 0) { 304 /* initialize driver and other modules */ 305 fdrv = drv_init(); 306 fmgr = mgr_init(); 307 fproc = proc_init(); 308 fnode = node_init(); 309 fdisp = disp_init(); 310 fstrm = strm_init(); 311 frmm = rmm_init(); 312 fchnl = chnl_init(); 313 fmsg = msg_mod_init(); 314 fio = io_init(); 315 fdev = dev_init(); 316 fcod = cod_init(); 317 ret = fdrv && fdev && fchnl && fcod && fmsg && fio; 318 ret = ret && fmgr && fproc && frmm; 319 if (!ret) { 320 if (fdrv) 321 drv_exit(); 322 323 if (fmgr) 324 mgr_exit(); 325 326 if (fstrm) 327 strm_exit(); 328 329 if (fproc) 330 proc_exit(); 331 332 if (fnode) 333 node_exit(); 334 335 if (fdisp) 336 disp_exit(); 337 338 if (fchnl) 339 chnl_exit(); 340 341 if (fmsg) 342 msg_exit(); 343 344 if (fio) 345 io_exit(); 346 347 if (fdev) 348 dev_exit(); 349 350 if (fcod) 351 cod_exit(); 352 353 if (frmm) 354 rmm_exit(); 355 356 } 357 } 358 if (ret) 359 api_c_refs++; 360 361 return ret; 362} 363 364/* 365 * ======== api_init_complete2 ======== 366 * Purpose: 367 * Perform any required bridge initialization which cannot 368 * be performed in api_init() or dev_start_device() due 369 * to the fact that some services are not yet 370 * completely initialized. 371 * Parameters: 372 * Returns: 373 * 0: Allow this device to load 374 * -EPERM: Failure. 375 * Requires: 376 * Bridge API initialized. 377 * Ensures: 378 */ 379int api_init_complete2(void) 380{ 381 int status = 0; 382 struct cfg_devnode *dev_node; 383 struct dev_object *hdev_obj; 384 u8 dev_type; 385 u32 tmp; 386 387 DBC_REQUIRE(api_c_refs > 0); 388 389 /* Walk the list of DevObjects, get each devnode, and attempting to 390 * autostart the board. Note that this requires COF loading, which 391 * requires KFILE. */ 392 for (hdev_obj = dev_get_first(); hdev_obj != NULL; 393 hdev_obj = dev_get_next(hdev_obj)) { 394 if (dev_get_dev_node(hdev_obj, &dev_node)) 395 continue; 396 397 if (dev_get_dev_type(hdev_obj, &dev_type)) 398 continue; 399 400 if ((dev_type == DSP_UNIT) || (dev_type == IVA_UNIT)) 401 if (cfg_get_auto_start(dev_node, &tmp) == 0 402 && tmp) 403 proc_auto_start(dev_node, hdev_obj); 404 } 405 406 return status; 407} 408 409/* TODO: Remove deprecated and not implemented ioctl wrappers */ 410 411/* 412 * ======== mgrwrap_enum_node_info ======== 413 */ 414u32 mgrwrap_enum_node_info(union trapped_args *args, void *pr_ctxt) 415{ 416 u8 *pndb_props; 417 u32 num_nodes; 418 int status = 0; 419 u32 size = args->args_mgr_enumnode_info.undb_props_size; 420 421 if (size < sizeof(struct dsp_ndbprops)) 422 return -EINVAL; 423 424 pndb_props = kmalloc(size, GFP_KERNEL); 425 if (pndb_props == NULL) 426 status = -ENOMEM; 427 428 if (!status) { 429 status = 430 mgr_enum_node_info(args->args_mgr_enumnode_info.node_id, 431 (struct dsp_ndbprops *)pndb_props, size, 432 &num_nodes); 433 } 434 CP_TO_USR(args->args_mgr_enumnode_info.pndb_props, pndb_props, status, 435 size); 436 CP_TO_USR(args->args_mgr_enumnode_info.pu_num_nodes, &num_nodes, status, 437 1); 438 kfree(pndb_props); 439 440 return status; 441} 442 443/* 444 * ======== mgrwrap_enum_proc_info ======== 445 */ 446u32 mgrwrap_enum_proc_info(union trapped_args *args, void *pr_ctxt) 447{ 448 u8 *processor_info; 449 u8 num_procs; 450 int status = 0; 451 u32 size = args->args_mgr_enumproc_info.processor_info_size; 452 453 if (size < sizeof(struct dsp_processorinfo)) 454 return -EINVAL; 455 456 processor_info = kmalloc(size, GFP_KERNEL); 457 if (processor_info == NULL) 458 status = -ENOMEM; 459 460 if (!status) { 461 status = 462 mgr_enum_processor_info(args->args_mgr_enumproc_info. 463 processor_id, 464 (struct dsp_processorinfo *) 465 processor_info, size, &num_procs); 466 } 467 CP_TO_USR(args->args_mgr_enumproc_info.processor_info, processor_info, 468 status, size); 469 CP_TO_USR(args->args_mgr_enumproc_info.pu_num_procs, &num_procs, 470 status, 1); 471 kfree(processor_info); 472 473 return status; 474} 475 476#define WRAP_MAP2CALLER(x) x 477/* 478 * ======== mgrwrap_register_object ======== 479 */ 480u32 mgrwrap_register_object(union trapped_args *args, void *pr_ctxt) 481{ 482 u32 ret; 483 struct dsp_uuid uuid_obj; 484 u32 path_size = 0; 485 char *psz_path_name = NULL; 486 int status = 0; 487 488 CP_FM_USR(&uuid_obj, args->args_mgr_registerobject.uuid_obj, status, 1); 489 if (status) 490 goto func_end; 491 /* path_size is increased by 1 to accommodate NULL */ 492 path_size = strlen_user((char *) 493 args->args_mgr_registerobject.psz_path_name) + 494 1; 495 psz_path_name = kmalloc(path_size, GFP_KERNEL); 496 if (!psz_path_name) 497 goto func_end; 498 ret = strncpy_from_user(psz_path_name, 499 (char *)args->args_mgr_registerobject. 500 psz_path_name, path_size); 501 if (!ret) { 502 status = -EFAULT; 503 goto func_end; 504 } 505 506 if (args->args_mgr_registerobject.obj_type >= DSP_DCDMAXOBJTYPE) 507 return -EINVAL; 508 509 status = dcd_register_object(&uuid_obj, 510 args->args_mgr_registerobject.obj_type, 511 (char *)psz_path_name); 512func_end: 513 kfree(psz_path_name); 514 return status; 515} 516 517/* 518 * ======== mgrwrap_unregister_object ======== 519 */ 520u32 mgrwrap_unregister_object(union trapped_args *args, void *pr_ctxt) 521{ 522 int status = 0; 523 struct dsp_uuid uuid_obj; 524 525 CP_FM_USR(&uuid_obj, args->args_mgr_registerobject.uuid_obj, status, 1); 526 if (status) 527 goto func_end; 528 529 status = dcd_unregister_object(&uuid_obj, 530 args->args_mgr_unregisterobject. 531 obj_type); 532func_end: 533 return status; 534 535} 536 537/* 538 * ======== mgrwrap_wait_for_bridge_events ======== 539 */ 540u32 mgrwrap_wait_for_bridge_events(union trapped_args *args, void *pr_ctxt) 541{ 542 int status = 0; 543 struct dsp_notification *anotifications[MAX_EVENTS]; 544 struct dsp_notification notifications[MAX_EVENTS]; 545 u32 index, i; 546 u32 count = args->args_mgr_wait.count; 547 548 if (count > MAX_EVENTS) 549 status = -EINVAL; 550 551 /* get the array of pointers to user structures */ 552 CP_FM_USR(anotifications, args->args_mgr_wait.anotifications, 553 status, count); 554 /* get the events */ 555 for (i = 0; i < count; i++) { 556 CP_FM_USR(¬ifications[i], anotifications[i], status, 1); 557 if (status || !notifications[i].handle) { 558 status = -EINVAL; 559 break; 560 } 561 /* set the array of pointers to kernel structures */ 562 anotifications[i] = ¬ifications[i]; 563 } 564 if (!status) { 565 status = mgr_wait_for_bridge_events(anotifications, count, 566 &index, 567 args->args_mgr_wait. 568 utimeout); 569 } 570 CP_TO_USR(args->args_mgr_wait.pu_index, &index, status, 1); 571 return status; 572} 573 574/* 575 * ======== MGRWRAP_GetProcessResourceInfo ======== 576 */ 577u32 __deprecated mgrwrap_get_process_resources_info(union trapped_args * args, 578 void *pr_ctxt) 579{ 580 pr_err("%s: deprecated dspbridge ioctl\n", __func__); 581 return 0; 582} 583 584/* 585 * ======== procwrap_attach ======== 586 */ 587u32 procwrap_attach(union trapped_args *args, void *pr_ctxt) 588{ 589 void *processor; 590 int status = 0; 591 struct dsp_processorattrin proc_attr_in, *attr_in = NULL; 592 593 /* Optional argument */ 594 if (args->args_proc_attach.attr_in) { 595 CP_FM_USR(&proc_attr_in, args->args_proc_attach.attr_in, status, 596 1); 597 if (!status) 598 attr_in = &proc_attr_in; 599 else 600 goto func_end; 601 602 } 603 status = proc_attach(args->args_proc_attach.processor_id, attr_in, 604 &processor, pr_ctxt); 605 CP_TO_USR(args->args_proc_attach.ph_processor, &processor, status, 1); 606func_end: 607 return status; 608} 609 610/* 611 * ======== procwrap_ctrl ======== 612 */ 613u32 procwrap_ctrl(union trapped_args *args, void *pr_ctxt) 614{ 615 u32 cb_data_size, __user * psize = (u32 __user *) 616 args->args_proc_ctrl.pargs; 617 u8 *pargs = NULL; 618 int status = 0; 619 void *hprocessor = ((struct process_context *)pr_ctxt)->hprocessor; 620 621 if (psize) { 622 if (get_user(cb_data_size, psize)) { 623 status = -EPERM; 624 goto func_end; 625 } 626 cb_data_size += sizeof(u32); 627 pargs = kmalloc(cb_data_size, GFP_KERNEL); 628 if (pargs == NULL) { 629 status = -ENOMEM; 630 goto func_end; 631 } 632 633 CP_FM_USR(pargs, args->args_proc_ctrl.pargs, status, 634 cb_data_size); 635 } 636 if (!status) { 637 status = proc_ctrl(hprocessor, 638 args->args_proc_ctrl.dw_cmd, 639 (struct dsp_cbdata *)pargs); 640 } 641 642 /* CP_TO_USR(args->args_proc_ctrl.pargs, pargs, status, 1); */ 643 kfree(pargs); 644func_end: 645 return status; 646} 647 648/* 649 * ======== procwrap_detach ======== 650 */ 651u32 __deprecated procwrap_detach(union trapped_args * args, void *pr_ctxt) 652{ 653 /* proc_detach called at bridge_release only */ 654 pr_err("%s: deprecated dspbridge ioctl\n", __func__); 655 return 0; 656} 657 658/* 659 * ======== procwrap_enum_node_info ======== 660 */ 661u32 procwrap_enum_node_info(union trapped_args *args, void *pr_ctxt) 662{ 663 int status; 664 void *node_tab[MAX_NODES]; 665 u32 num_nodes; 666 u32 alloc_cnt; 667 void *hprocessor = ((struct process_context *)pr_ctxt)->hprocessor; 668 669 if (!args->args_proc_enumnode_info.node_tab_size) 670 return -EINVAL; 671 672 status = proc_enum_nodes(hprocessor, 673 node_tab, 674 args->args_proc_enumnode_info.node_tab_size, 675 &num_nodes, &alloc_cnt); 676 CP_TO_USR(args->args_proc_enumnode_info.node_tab, node_tab, status, 677 num_nodes); 678 CP_TO_USR(args->args_proc_enumnode_info.pu_num_nodes, &num_nodes, 679 status, 1); 680 CP_TO_USR(args->args_proc_enumnode_info.pu_allocated, &alloc_cnt, 681 status, 1); 682 return status; 683} 684 685u32 procwrap_end_dma(union trapped_args *args, void *pr_ctxt) 686{ 687 int status; 688 689 if (args->args_proc_dma.dir >= DMA_NONE) 690 return -EINVAL; 691 692 status = proc_end_dma(pr_ctxt, 693 args->args_proc_dma.pmpu_addr, 694 args->args_proc_dma.ul_size, 695 args->args_proc_dma.dir); 696 return status; 697} 698 699u32 procwrap_begin_dma(union trapped_args *args, void *pr_ctxt) 700{ 701 int status; 702 703 if (args->args_proc_dma.dir >= DMA_NONE) 704 return -EINVAL; 705 706 status = proc_begin_dma(pr_ctxt, 707 args->args_proc_dma.pmpu_addr, 708 args->args_proc_dma.ul_size, 709 args->args_proc_dma.dir); 710 return status; 711} 712 713/* 714 * ======== procwrap_flush_memory ======== 715 */ 716u32 procwrap_flush_memory(union trapped_args *args, void *pr_ctxt) 717{ 718 int status; 719 720 if (args->args_proc_flushmemory.ul_flags > 721 PROC_WRITEBACK_INVALIDATE_MEM) 722 return -EINVAL; 723 724 status = proc_flush_memory(pr_ctxt, 725 args->args_proc_flushmemory.pmpu_addr, 726 args->args_proc_flushmemory.ul_size, 727 args->args_proc_flushmemory.ul_flags); 728 return status; 729} 730 731/* 732 * ======== procwrap_invalidate_memory ======== 733 */ 734u32 procwrap_invalidate_memory(union trapped_args *args, void *pr_ctxt) 735{ 736 int status; 737 738 status = 739 proc_invalidate_memory(pr_ctxt, 740 args->args_proc_invalidatememory.pmpu_addr, 741 args->args_proc_invalidatememory.ul_size); 742 return status; 743} 744 745/* 746 * ======== procwrap_enum_resources ======== 747 */ 748u32 procwrap_enum_resources(union trapped_args *args, void *pr_ctxt) 749{ 750 int status = 0; 751 struct dsp_resourceinfo resource_info; 752 void *hprocessor = ((struct process_context *)pr_ctxt)->hprocessor; 753 754 if (args->args_proc_enumresources.resource_info_size < 755 sizeof(struct dsp_resourceinfo)) 756 return -EINVAL; 757 758 status = 759 proc_get_resource_info(hprocessor, 760 args->args_proc_enumresources.resource_type, 761 &resource_info, 762 args->args_proc_enumresources. 763 resource_info_size); 764 765 CP_TO_USR(args->args_proc_enumresources.resource_info, &resource_info, 766 status, 1); 767 768 return status; 769 770} 771 772/* 773 * ======== procwrap_get_state ======== 774 */ 775u32 procwrap_get_state(union trapped_args *args, void *pr_ctxt) 776{ 777 int status; 778 struct dsp_processorstate proc_state; 779 void *hprocessor = ((struct process_context *)pr_ctxt)->hprocessor; 780 781 if (args->args_proc_getstate.state_info_size < 782 sizeof(struct dsp_processorstate)) 783 return -EINVAL; 784 785 status = proc_get_state(hprocessor, &proc_state, 786 args->args_proc_getstate.state_info_size); 787 CP_TO_USR(args->args_proc_getstate.proc_state_obj, &proc_state, status, 788 1); 789 return status; 790 791} 792 793/* 794 * ======== procwrap_get_trace ======== 795 */ 796u32 procwrap_get_trace(union trapped_args *args, void *pr_ctxt) 797{ 798 int status; 799 u8 *pbuf; 800 void *hprocessor = ((struct process_context *)pr_ctxt)->hprocessor; 801 802 if (args->args_proc_gettrace.max_size > MAX_TRACEBUFLEN) 803 return -EINVAL; 804 805 pbuf = kzalloc(args->args_proc_gettrace.max_size, GFP_KERNEL); 806 if (pbuf != NULL) { 807 status = proc_get_trace(hprocessor, pbuf, 808 args->args_proc_gettrace.max_size); 809 } else { 810 status = -ENOMEM; 811 } 812 CP_TO_USR(args->args_proc_gettrace.pbuf, pbuf, status, 813 args->args_proc_gettrace.max_size); 814 kfree(pbuf); 815 816 return status; 817} 818 819/* 820 * ======== procwrap_load ======== 821 */ 822u32 procwrap_load(union trapped_args *args, void *pr_ctxt) 823{ 824 s32 i, len; 825 int status = 0; 826 char *temp; 827 s32 count = args->args_proc_load.argc_index; 828 u8 **argv = NULL, **envp = NULL; 829 void *hprocessor = ((struct process_context *)pr_ctxt)->hprocessor; 830 831 if (count <= 0 || count > MAX_LOADARGS) { 832 status = -EINVAL; 833 goto func_cont; 834 } 835 836 argv = kmalloc(count * sizeof(u8 *), GFP_KERNEL); 837 if (!argv) { 838 status = -ENOMEM; 839 goto func_cont; 840 } 841 842 CP_FM_USR(argv, args->args_proc_load.user_args, status, count); 843 if (status) { 844 kfree(argv); 845 argv = NULL; 846 goto func_cont; 847 } 848 849 for (i = 0; i < count; i++) { 850 if (argv[i]) { 851 /* User space pointer to argument */ 852 temp = (char *)argv[i]; 853 /* len is increased by 1 to accommodate NULL */ 854 len = strlen_user((char *)temp) + 1; 855 /* Kernel space pointer to argument */ 856 argv[i] = kmalloc(len, GFP_KERNEL); 857 if (argv[i]) { 858 CP_FM_USR(argv[i], temp, status, len); 859 if (status) { 860 kfree(argv[i]); 861 argv[i] = NULL; 862 goto func_cont; 863 } 864 } else { 865 status = -ENOMEM; 866 goto func_cont; 867 } 868 } 869 } 870 /* TODO: validate this */ 871 if (args->args_proc_load.user_envp) { 872 /* number of elements in the envp array including NULL */ 873 count = 0; 874 do { 875 get_user(temp, args->args_proc_load.user_envp + count); 876 count++; 877 } while (temp); 878 envp = kmalloc(count * sizeof(u8 *), GFP_KERNEL); 879 if (!envp) { 880 status = -ENOMEM; 881 goto func_cont; 882 } 883 884 CP_FM_USR(envp, args->args_proc_load.user_envp, status, count); 885 if (status) { 886 kfree(envp); 887 envp = NULL; 888 goto func_cont; 889 } 890 for (i = 0; envp[i]; i++) { 891 /* User space pointer to argument */ 892 temp = (char *)envp[i]; 893 /* len is increased by 1 to accommodate NULL */ 894 len = strlen_user((char *)temp) + 1; 895 /* Kernel space pointer to argument */ 896 envp[i] = kmalloc(len, GFP_KERNEL); 897 if (envp[i]) { 898 CP_FM_USR(envp[i], temp, status, len); 899 if (status) { 900 kfree(envp[i]); 901 envp[i] = NULL; 902 goto func_cont; 903 } 904 } else { 905 status = -ENOMEM; 906 goto func_cont; 907 } 908 } 909 } 910 911 if (!status) { 912 status = proc_load(hprocessor, 913 args->args_proc_load.argc_index, 914 (const char **)argv, (const char **)envp); 915 } 916func_cont: 917 if (envp) { 918 i = 0; 919 while (envp[i]) 920 kfree(envp[i++]); 921 922 kfree(envp); 923 } 924 925 if (argv) { 926 count = args->args_proc_load.argc_index; 927 for (i = 0; (i < count) && argv[i]; i++) 928 kfree(argv[i]); 929 930 kfree(argv); 931 } 932 933 return status; 934} 935 936/* 937 * ======== procwrap_map ======== 938 */ 939u32 procwrap_map(union trapped_args *args, void *pr_ctxt) 940{ 941 int status; 942 void *map_addr; 943 void *hprocessor = ((struct process_context *)pr_ctxt)->hprocessor; 944 945 if (!args->args_proc_mapmem.ul_size) 946 return -EINVAL; 947 948 status = proc_map(args->args_proc_mapmem.hprocessor, 949 args->args_proc_mapmem.pmpu_addr, 950 args->args_proc_mapmem.ul_size, 951 args->args_proc_mapmem.req_addr, &map_addr, 952 args->args_proc_mapmem.ul_map_attr, pr_ctxt); 953 if (!status) { 954 if (put_user(map_addr, args->args_proc_mapmem.pp_map_addr)) { 955 status = -EINVAL; 956 proc_un_map(hprocessor, map_addr, pr_ctxt); 957 } 958 959 } 960 return status; 961} 962 963/* 964 * ======== procwrap_register_notify ======== 965 */ 966u32 procwrap_register_notify(union trapped_args *args, void *pr_ctxt) 967{ 968 int status; 969 struct dsp_notification notification; 970 void *hprocessor = ((struct process_context *)pr_ctxt)->hprocessor; 971 972 /* Initialize the notification data structure */ 973 notification.ps_name = NULL; 974 notification.handle = NULL; 975 976 status = proc_register_notify(hprocessor, 977 args->args_proc_register_notify.event_mask, 978 args->args_proc_register_notify.notify_type, 979 ¬ification); 980 CP_TO_USR(args->args_proc_register_notify.hnotification, ¬ification, 981 status, 1); 982 return status; 983} 984 985/* 986 * ======== procwrap_reserve_memory ======== 987 */ 988u32 procwrap_reserve_memory(union trapped_args *args, void *pr_ctxt) 989{ 990 int status; 991 void *prsv_addr; 992 void *hprocessor = ((struct process_context *)pr_ctxt)->hprocessor; 993 994 if ((args->args_proc_rsvmem.ul_size <= 0) || 995 (args->args_proc_rsvmem.ul_size & (PG_SIZE4K - 1)) != 0) 996 return -EINVAL; 997 998 status = proc_reserve_memory(hprocessor, 999 args->args_proc_rsvmem.ul_size, &prsv_addr, 1000 pr_ctxt); 1001 if (!status) { 1002 if (put_user(prsv_addr, args->args_proc_rsvmem.pp_rsv_addr)) { 1003 status = -EINVAL; 1004 proc_un_reserve_memory(args->args_proc_rsvmem. 1005 hprocessor, prsv_addr, pr_ctxt); 1006 } 1007 } 1008 return status; 1009} 1010 1011/* 1012 * ======== procwrap_start ======== 1013 */ 1014u32 procwrap_start(union trapped_args *args, void *pr_ctxt) 1015{ 1016 u32 ret; 1017 1018 ret = proc_start(((struct process_context *)pr_ctxt)->hprocessor); 1019 return ret; 1020} 1021 1022/* 1023 * ======== procwrap_un_map ======== 1024 */ 1025u32 procwrap_un_map(union trapped_args *args, void *pr_ctxt) 1026{ 1027 int status; 1028 1029 status = proc_un_map(((struct process_context *)pr_ctxt)->hprocessor, 1030 args->args_proc_unmapmem.map_addr, pr_ctxt); 1031 return status; 1032} 1033 1034/* 1035 * ======== procwrap_un_reserve_memory ======== 1036 */ 1037u32 procwrap_un_reserve_memory(union trapped_args *args, void *pr_ctxt) 1038{ 1039 int status; 1040 void *hprocessor = ((struct process_context *)pr_ctxt)->hprocessor; 1041 1042 status = proc_un_reserve_memory(hprocessor, 1043 args->args_proc_unrsvmem.prsv_addr, 1044 pr_ctxt); 1045 return status; 1046} 1047 1048/* 1049 * ======== procwrap_stop ======== 1050 */ 1051u32 procwrap_stop(union trapped_args *args, void *pr_ctxt) 1052{ 1053 u32 ret; 1054 1055 ret = proc_stop(((struct process_context *)pr_ctxt)->hprocessor); 1056 1057 return ret; 1058} 1059 1060/* 1061 * ======== find_handle ========= 1062 */ 1063inline void find_node_handle(struct node_res_object **noderes, 1064 void *pr_ctxt, void *hnode) 1065{ 1066 rcu_read_lock(); 1067 *noderes = idr_find(((struct process_context *)pr_ctxt)->node_id, 1068 (int)hnode - 1); 1069 rcu_read_unlock(); 1070 return; 1071} 1072 1073 1074/* 1075 * ======== nodewrap_allocate ======== 1076 */ 1077u32 nodewrap_allocate(union trapped_args *args, void *pr_ctxt) 1078{ 1079 int status = 0; 1080 struct dsp_uuid node_uuid; 1081 u32 cb_data_size = 0; 1082 u32 __user *psize = (u32 __user *) args->args_node_allocate.pargs; 1083 u8 *pargs = NULL; 1084 struct dsp_nodeattrin proc_attr_in, *attr_in = NULL; 1085 struct node_res_object *node_res; 1086 int nodeid; 1087 void *hprocessor = ((struct process_context *)pr_ctxt)->hprocessor; 1088 1089 /* Optional argument */ 1090 if (psize) { 1091 if (get_user(cb_data_size, psize)) 1092 status = -EPERM; 1093 1094 cb_data_size += sizeof(u32); 1095 if (!status) { 1096 pargs = kmalloc(cb_data_size, GFP_KERNEL); 1097 if (pargs == NULL) 1098 status = -ENOMEM; 1099 1100 } 1101 CP_FM_USR(pargs, args->args_node_allocate.pargs, status, 1102 cb_data_size); 1103 } 1104 CP_FM_USR(&node_uuid, args->args_node_allocate.node_id_ptr, status, 1); 1105 if (status) 1106 goto func_cont; 1107 /* Optional argument */ 1108 if (args->args_node_allocate.attr_in) { 1109 CP_FM_USR(&proc_attr_in, args->args_node_allocate.attr_in, 1110 status, 1); 1111 if (!status) 1112 attr_in = &proc_attr_in; 1113 else 1114 status = -ENOMEM; 1115 1116 } 1117 if (!status) { 1118 status = node_allocate(hprocessor, 1119 &node_uuid, (struct dsp_cbdata *)pargs, 1120 attr_in, &node_res, pr_ctxt); 1121 } 1122 if (!status) { 1123 nodeid = node_res->id + 1; 1124 CP_TO_USR(args->args_node_allocate.ph_node, &nodeid, 1125 status, 1); 1126 if (status) { 1127 status = -EFAULT; 1128 node_delete(node_res, pr_ctxt); 1129 } 1130 } 1131func_cont: 1132 kfree(pargs); 1133 1134 return status; 1135} 1136 1137/* 1138 * ======== nodewrap_alloc_msg_buf ======== 1139 */ 1140u32 nodewrap_alloc_msg_buf(union trapped_args *args, void *pr_ctxt) 1141{ 1142 int status = 0; 1143 struct dsp_bufferattr *pattr = NULL; 1144 struct dsp_bufferattr attr; 1145 u8 *pbuffer = NULL; 1146 struct node_res_object *node_res; 1147 1148 find_node_handle(&node_res, pr_ctxt, 1149 args->args_node_allocmsgbuf.hnode); 1150 1151 if (!node_res) 1152 return -EFAULT; 1153 1154 if (!args->args_node_allocmsgbuf.usize) 1155 return -EINVAL; 1156 1157 if (args->args_node_allocmsgbuf.pattr) { /* Optional argument */ 1158 CP_FM_USR(&attr, args->args_node_allocmsgbuf.pattr, status, 1); 1159 if (!status) 1160 pattr = &attr; 1161 1162 } 1163 /* argument */ 1164 CP_FM_USR(&pbuffer, args->args_node_allocmsgbuf.pbuffer, status, 1); 1165 if (!status) { 1166 status = node_alloc_msg_buf(node_res->hnode, 1167 args->args_node_allocmsgbuf.usize, 1168 pattr, &pbuffer); 1169 } 1170 CP_TO_USR(args->args_node_allocmsgbuf.pbuffer, &pbuffer, status, 1); 1171 return status; 1172} 1173 1174/* 1175 * ======== nodewrap_change_priority ======== 1176 */ 1177u32 nodewrap_change_priority(union trapped_args *args, void *pr_ctxt) 1178{ 1179 u32 ret; 1180 struct node_res_object *node_res; 1181 1182 find_node_handle(&node_res, pr_ctxt, 1183 args->args_node_changepriority.hnode); 1184 1185 if (!node_res) 1186 return -EFAULT; 1187 1188 ret = node_change_priority(node_res->hnode, 1189 args->args_node_changepriority.prio); 1190 1191 return ret; 1192} 1193 1194/* 1195 * ======== nodewrap_connect ======== 1196 */ 1197u32 nodewrap_connect(union trapped_args *args, void *pr_ctxt) 1198{ 1199 int status = 0; 1200 struct dsp_strmattr attrs; 1201 struct dsp_strmattr *pattrs = NULL; 1202 u32 cb_data_size; 1203 u32 __user *psize = (u32 __user *) args->args_node_connect.conn_param; 1204 u8 *pargs = NULL; 1205 struct node_res_object *node_res1, *node_res2; 1206 struct node_object *node1 = NULL, *node2 = NULL; 1207 1208 if ((int)args->args_node_connect.hnode != DSP_HGPPNODE) { 1209 find_node_handle(&node_res1, pr_ctxt, 1210 args->args_node_connect.hnode); 1211 if (node_res1) 1212 node1 = node_res1->hnode; 1213 } else { 1214 node1 = args->args_node_connect.hnode; 1215 } 1216 1217 if ((int)args->args_node_connect.other_node != DSP_HGPPNODE) { 1218 find_node_handle(&node_res2, pr_ctxt, 1219 args->args_node_connect.other_node); 1220 if (node_res2) 1221 node2 = node_res2->hnode; 1222 } else { 1223 node2 = args->args_node_connect.other_node; 1224 } 1225 1226 if (!node1 || !node2) 1227 return -EFAULT; 1228 1229 /* Optional argument */ 1230 if (psize) { 1231 if (get_user(cb_data_size, psize)) 1232 status = -EPERM; 1233 1234 cb_data_size += sizeof(u32); 1235 if (!status) { 1236 pargs = kmalloc(cb_data_size, GFP_KERNEL); 1237 if (pargs == NULL) { 1238 status = -ENOMEM; 1239 goto func_cont; 1240 } 1241 1242 } 1243 CP_FM_USR(pargs, args->args_node_connect.conn_param, status, 1244 cb_data_size); 1245 if (status) 1246 goto func_cont; 1247 } 1248 if (args->args_node_connect.pattrs) { /* Optional argument */ 1249 CP_FM_USR(&attrs, args->args_node_connect.pattrs, status, 1); 1250 if (!status) 1251 pattrs = &attrs; 1252 1253 } 1254 if (!status) { 1255 status = node_connect(node1, 1256 args->args_node_connect.stream_id, 1257 node2, 1258 args->args_node_connect.other_stream, 1259 pattrs, (struct dsp_cbdata *)pargs); 1260 } 1261func_cont: 1262 kfree(pargs); 1263 1264 return status; 1265} 1266 1267/* 1268 * ======== nodewrap_create ======== 1269 */ 1270u32 nodewrap_create(union trapped_args *args, void *pr_ctxt) 1271{ 1272 u32 ret; 1273 struct node_res_object *node_res; 1274 1275 find_node_handle(&node_res, pr_ctxt, args->args_node_create.hnode); 1276 1277 if (!node_res) 1278 return -EFAULT; 1279 1280 ret = node_create(node_res->hnode); 1281 1282 return ret; 1283} 1284 1285/* 1286 * ======== nodewrap_delete ======== 1287 */ 1288u32 nodewrap_delete(union trapped_args *args, void *pr_ctxt) 1289{ 1290 u32 ret; 1291 struct node_res_object *node_res; 1292 1293 find_node_handle(&node_res, pr_ctxt, args->args_node_delete.hnode); 1294 1295 if (!node_res) 1296 return -EFAULT; 1297 1298 ret = node_delete(node_res, pr_ctxt); 1299 1300 return ret; 1301} 1302 1303/* 1304 * ======== nodewrap_free_msg_buf ======== 1305 */ 1306u32 nodewrap_free_msg_buf(union trapped_args *args, void *pr_ctxt) 1307{ 1308 int status = 0; 1309 struct dsp_bufferattr *pattr = NULL; 1310 struct dsp_bufferattr attr; 1311 struct node_res_object *node_res; 1312 1313 find_node_handle(&node_res, pr_ctxt, args->args_node_freemsgbuf.hnode); 1314 1315 if (!node_res) 1316 return -EFAULT; 1317 1318 if (args->args_node_freemsgbuf.pattr) { /* Optional argument */ 1319 CP_FM_USR(&attr, args->args_node_freemsgbuf.pattr, status, 1); 1320 if (!status) 1321 pattr = &attr; 1322 1323 } 1324 1325 if (!args->args_node_freemsgbuf.pbuffer) 1326 return -EFAULT; 1327 1328 if (!status) { 1329 status = node_free_msg_buf(node_res->hnode, 1330 args->args_node_freemsgbuf.pbuffer, 1331 pattr); 1332 } 1333 1334 return status; 1335} 1336 1337/* 1338 * ======== nodewrap_get_attr ======== 1339 */ 1340u32 nodewrap_get_attr(union trapped_args *args, void *pr_ctxt) 1341{ 1342 int status = 0; 1343 struct dsp_nodeattr attr; 1344 struct node_res_object *node_res; 1345 1346 find_node_handle(&node_res, pr_ctxt, args->args_node_getattr.hnode); 1347 1348 if (!node_res) 1349 return -EFAULT; 1350 1351 status = node_get_attr(node_res->hnode, &attr, 1352 args->args_node_getattr.attr_size); 1353 CP_TO_USR(args->args_node_getattr.pattr, &attr, status, 1); 1354 1355 return status; 1356} 1357 1358/* 1359 * ======== nodewrap_get_message ======== 1360 */ 1361u32 nodewrap_get_message(union trapped_args *args, void *pr_ctxt) 1362{ 1363 int status; 1364 struct dsp_msg msg; 1365 struct node_res_object *node_res; 1366 1367 find_node_handle(&node_res, pr_ctxt, args->args_node_getmessage.hnode); 1368 1369 if (!node_res) 1370 return -EFAULT; 1371 1372 status = node_get_message(node_res->hnode, &msg, 1373 args->args_node_getmessage.utimeout); 1374 1375 CP_TO_USR(args->args_node_getmessage.message, &msg, status, 1); 1376 1377 return status; 1378} 1379 1380/* 1381 * ======== nodewrap_pause ======== 1382 */ 1383u32 nodewrap_pause(union trapped_args *args, void *pr_ctxt) 1384{ 1385 u32 ret; 1386 struct node_res_object *node_res; 1387 1388 find_node_handle(&node_res, pr_ctxt, args->args_node_pause.hnode); 1389 1390 if (!node_res) 1391 return -EFAULT; 1392 1393 ret = node_pause(node_res->hnode); 1394 1395 return ret; 1396} 1397 1398/* 1399 * ======== nodewrap_put_message ======== 1400 */ 1401u32 nodewrap_put_message(union trapped_args *args, void *pr_ctxt) 1402{ 1403 int status = 0; 1404 struct dsp_msg msg; 1405 struct node_res_object *node_res; 1406 1407 find_node_handle(&node_res, pr_ctxt, args->args_node_putmessage.hnode); 1408 1409 if (!node_res) 1410 return -EFAULT; 1411 1412 CP_FM_USR(&msg, args->args_node_putmessage.message, status, 1); 1413 1414 if (!status) { 1415 status = 1416 node_put_message(node_res->hnode, &msg, 1417 args->args_node_putmessage.utimeout); 1418 } 1419 1420 return status; 1421} 1422 1423/* 1424 * ======== nodewrap_register_notify ======== 1425 */ 1426u32 nodewrap_register_notify(union trapped_args *args, void *pr_ctxt) 1427{ 1428 int status = 0; 1429 struct dsp_notification notification; 1430 struct node_res_object *node_res; 1431 1432 find_node_handle(&node_res, pr_ctxt, 1433 args->args_node_registernotify.hnode); 1434 1435 if (!node_res) 1436 return -EFAULT; 1437 1438 /* Initialize the notification data structure */ 1439 notification.ps_name = NULL; 1440 notification.handle = NULL; 1441 1442 if (!args->args_proc_register_notify.event_mask) 1443 CP_FM_USR(¬ification, 1444 args->args_proc_register_notify.hnotification, 1445 status, 1); 1446 1447 status = node_register_notify(node_res->hnode, 1448 args->args_node_registernotify.event_mask, 1449 args->args_node_registernotify. 1450 notify_type, ¬ification); 1451 CP_TO_USR(args->args_node_registernotify.hnotification, ¬ification, 1452 status, 1); 1453 return status; 1454} 1455 1456/* 1457 * ======== nodewrap_run ======== 1458 */ 1459u32 nodewrap_run(union trapped_args *args, void *pr_ctxt) 1460{ 1461 u32 ret; 1462 struct node_res_object *node_res; 1463 1464 find_node_handle(&node_res, pr_ctxt, args->args_node_run.hnode); 1465 1466 if (!node_res) 1467 return -EFAULT; 1468 1469 ret = node_run(node_res->hnode); 1470 1471 return ret; 1472} 1473 1474/* 1475 * ======== nodewrap_terminate ======== 1476 */ 1477u32 nodewrap_terminate(union trapped_args *args, void *pr_ctxt) 1478{ 1479 int status; 1480 int tempstatus; 1481 struct node_res_object *node_res; 1482 1483 find_node_handle(&node_res, pr_ctxt, args->args_node_terminate.hnode); 1484 1485 if (!node_res) 1486 return -EFAULT; 1487 1488 status = node_terminate(node_res->hnode, &tempstatus); 1489 1490 CP_TO_USR(args->args_node_terminate.pstatus, &tempstatus, status, 1); 1491 1492 return status; 1493} 1494 1495/* 1496 * ======== nodewrap_get_uuid_props ======== 1497 */ 1498u32 nodewrap_get_uuid_props(union trapped_args *args, void *pr_ctxt) 1499{ 1500 int status = 0; 1501 struct dsp_uuid node_uuid; 1502 struct dsp_ndbprops *pnode_props = NULL; 1503 void *hprocessor = ((struct process_context *)pr_ctxt)->hprocessor; 1504 1505 CP_FM_USR(&node_uuid, args->args_node_getuuidprops.node_id_ptr, status, 1506 1); 1507 if (status) 1508 goto func_cont; 1509 pnode_props = kmalloc(sizeof(struct dsp_ndbprops), GFP_KERNEL); 1510 if (pnode_props != NULL) { 1511 status = 1512 node_get_uuid_props(hprocessor, &node_uuid, pnode_props); 1513 CP_TO_USR(args->args_node_getuuidprops.node_props, pnode_props, 1514 status, 1); 1515 } else 1516 status = -ENOMEM; 1517func_cont: 1518 kfree(pnode_props); 1519 return status; 1520} 1521 1522/* 1523 * ======== find_strm_handle ========= 1524 */ 1525inline void find_strm_handle(struct strm_res_object **strmres, 1526 void *pr_ctxt, void *hstream) 1527{ 1528 rcu_read_lock(); 1529 *strmres = idr_find(((struct process_context *)pr_ctxt)->stream_id, 1530 (int)hstream - 1); 1531 rcu_read_unlock(); 1532 return; 1533} 1534 1535/* 1536 * ======== strmwrap_allocate_buffer ======== 1537 */ 1538u32 strmwrap_allocate_buffer(union trapped_args *args, void *pr_ctxt) 1539{ 1540 int status; 1541 u8 **ap_buffer = NULL; 1542 u32 num_bufs = args->args_strm_allocatebuffer.num_bufs; 1543 struct strm_res_object *strm_res; 1544 1545 find_strm_handle(&strm_res, pr_ctxt, 1546 args->args_strm_allocatebuffer.hstream); 1547 1548 if (!strm_res) 1549 return -EFAULT; 1550 1551 if (num_bufs > MAX_BUFS) 1552 return -EINVAL; 1553 1554 ap_buffer = kmalloc((num_bufs * sizeof(u8 *)), GFP_KERNEL); 1555 if (ap_buffer == NULL) 1556 return -ENOMEM; 1557 1558 status = strm_allocate_buffer(strm_res, 1559 args->args_strm_allocatebuffer.usize, 1560 ap_buffer, num_bufs, pr_ctxt); 1561 if (!status) { 1562 CP_TO_USR(args->args_strm_allocatebuffer.ap_buffer, ap_buffer, 1563 status, num_bufs); 1564 if (status) { 1565 status = -EFAULT; 1566 strm_free_buffer(strm_res, 1567 ap_buffer, num_bufs, pr_ctxt); 1568 } 1569 } 1570 kfree(ap_buffer); 1571 1572 return status; 1573} 1574 1575/* 1576 * ======== strmwrap_close ======== 1577 */ 1578u32 strmwrap_close(union trapped_args *args, void *pr_ctxt) 1579{ 1580 struct strm_res_object *strm_res; 1581 1582 find_strm_handle(&strm_res, pr_ctxt, args->args_strm_close.hstream); 1583 1584 if (!strm_res) 1585 return -EFAULT; 1586 1587 return strm_close(strm_res, pr_ctxt); 1588} 1589 1590/* 1591 * ======== strmwrap_free_buffer ======== 1592 */ 1593u32 strmwrap_free_buffer(union trapped_args *args, void *pr_ctxt) 1594{ 1595 int status = 0; 1596 u8 **ap_buffer = NULL; 1597 u32 num_bufs = args->args_strm_freebuffer.num_bufs; 1598 struct strm_res_object *strm_res; 1599 1600 find_strm_handle(&strm_res, pr_ctxt, 1601 args->args_strm_freebuffer.hstream); 1602 1603 if (!strm_res) 1604 return -EFAULT; 1605 1606 if (num_bufs > MAX_BUFS) 1607 return -EINVAL; 1608 1609 ap_buffer = kmalloc((num_bufs * sizeof(u8 *)), GFP_KERNEL); 1610 if (ap_buffer == NULL) 1611 return -ENOMEM; 1612 1613 CP_FM_USR(ap_buffer, args->args_strm_freebuffer.ap_buffer, status, 1614 num_bufs); 1615 1616 if (!status) 1617 status = strm_free_buffer(strm_res, 1618 ap_buffer, num_bufs, pr_ctxt); 1619 1620 CP_TO_USR(args->args_strm_freebuffer.ap_buffer, ap_buffer, status, 1621 num_bufs); 1622 kfree(ap_buffer); 1623 1624 return status; 1625} 1626 1627/* 1628 * ======== strmwrap_get_event_handle ======== 1629 */ 1630u32 __deprecated strmwrap_get_event_handle(union trapped_args * args, 1631 void *pr_ctxt) 1632{ 1633 pr_err("%s: deprecated dspbridge ioctl\n", __func__); 1634 return -ENOSYS; 1635} 1636 1637/* 1638 * ======== strmwrap_get_info ======== 1639 */ 1640u32 strmwrap_get_info(union trapped_args *args, void *pr_ctxt) 1641{ 1642 int status = 0; 1643 struct stream_info strm_info; 1644 struct dsp_streaminfo user; 1645 struct dsp_streaminfo *temp; 1646 struct strm_res_object *strm_res; 1647 1648 find_strm_handle(&strm_res, pr_ctxt, 1649 args->args_strm_getinfo.hstream); 1650 1651 if (!strm_res) 1652 return -EFAULT; 1653 1654 CP_FM_USR(&strm_info, args->args_strm_getinfo.stream_info, status, 1); 1655 temp = strm_info.user_strm; 1656 1657 strm_info.user_strm = &user; 1658 1659 if (!status) { 1660 status = strm_get_info(strm_res->hstream, 1661 &strm_info, 1662 args->args_strm_getinfo. 1663 stream_info_size); 1664 } 1665 CP_TO_USR(temp, strm_info.user_strm, status, 1); 1666 strm_info.user_strm = temp; 1667 CP_TO_USR(args->args_strm_getinfo.stream_info, &strm_info, status, 1); 1668 return status; 1669} 1670 1671/* 1672 * ======== strmwrap_idle ======== 1673 */ 1674u32 strmwrap_idle(union trapped_args *args, void *pr_ctxt) 1675{ 1676 u32 ret; 1677 struct strm_res_object *strm_res; 1678 1679 find_strm_handle(&strm_res, pr_ctxt, args->args_strm_idle.hstream); 1680 1681 if (!strm_res) 1682 return -EFAULT; 1683 1684 ret = strm_idle(strm_res->hstream, args->args_strm_idle.flush_flag); 1685 1686 return ret; 1687} 1688 1689/* 1690 * ======== strmwrap_issue ======== 1691 */ 1692u32 strmwrap_issue(union trapped_args *args, void *pr_ctxt) 1693{ 1694 int status = 0; 1695 struct strm_res_object *strm_res; 1696 1697 find_strm_handle(&strm_res, pr_ctxt, args->args_strm_issue.hstream); 1698 1699 if (!strm_res) 1700 return -EFAULT; 1701 1702 if (!args->args_strm_issue.pbuffer) 1703 return -EFAULT; 1704 1705 /* No need of doing CP_FM_USR for the user buffer (pbuffer) 1706 as this is done in Bridge internal function bridge_chnl_add_io_req 1707 in chnl_sm.c */ 1708 status = strm_issue(strm_res->hstream, 1709 args->args_strm_issue.pbuffer, 1710 args->args_strm_issue.dw_bytes, 1711 args->args_strm_issue.dw_buf_size, 1712 args->args_strm_issue.dw_arg); 1713 1714 return status; 1715} 1716 1717/* 1718 * ======== strmwrap_open ======== 1719 */ 1720u32 strmwrap_open(union trapped_args *args, void *pr_ctxt) 1721{ 1722 int status = 0; 1723 struct strm_attr attr; 1724 struct strm_res_object *strm_res_obj; 1725 struct dsp_streamattrin strm_attr_in; 1726 struct node_res_object *node_res; 1727 int strmid; 1728 1729 find_node_handle(&node_res, pr_ctxt, args->args_strm_open.hnode); 1730 1731 if (!node_res) 1732 return -EFAULT; 1733 1734 CP_FM_USR(&attr, args->args_strm_open.attr_in, status, 1); 1735 1736 if (attr.stream_attr_in != NULL) { /* Optional argument */ 1737 CP_FM_USR(&strm_attr_in, attr.stream_attr_in, status, 1); 1738 if (!status) { 1739 attr.stream_attr_in = &strm_attr_in; 1740 if (attr.stream_attr_in->strm_mode == STRMMODE_LDMA) 1741 return -ENOSYS; 1742 } 1743 1744 } 1745 status = strm_open(node_res->hnode, 1746 args->args_strm_open.direction, 1747 args->args_strm_open.index, &attr, &strm_res_obj, 1748 pr_ctxt); 1749 if (!status) { 1750 strmid = strm_res_obj->id + 1; 1751 CP_TO_USR(args->args_strm_open.ph_stream, &strmid, status, 1); 1752 } 1753 return status; 1754} 1755 1756/* 1757 * ======== strmwrap_reclaim ======== 1758 */ 1759u32 strmwrap_reclaim(union trapped_args *args, void *pr_ctxt) 1760{ 1761 int status = 0; 1762 u8 *buf_ptr; 1763 u32 ul_bytes; 1764 u32 dw_arg; 1765 u32 ul_buf_size; 1766 struct strm_res_object *strm_res; 1767 1768 find_strm_handle(&strm_res, pr_ctxt, args->args_strm_reclaim.hstream); 1769 1770 if (!strm_res) 1771 return -EFAULT; 1772 1773 status = strm_reclaim(strm_res->hstream, &buf_ptr, 1774 &ul_bytes, &ul_buf_size, &dw_arg); 1775 CP_TO_USR(args->args_strm_reclaim.buf_ptr, &buf_ptr, status, 1); 1776 CP_TO_USR(args->args_strm_reclaim.bytes, &ul_bytes, status, 1); 1777 CP_TO_USR(args->args_strm_reclaim.pdw_arg, &dw_arg, status, 1); 1778 1779 if (args->args_strm_reclaim.buf_size_ptr != NULL) { 1780 CP_TO_USR(args->args_strm_reclaim.buf_size_ptr, &ul_buf_size, 1781 status, 1); 1782 } 1783 1784 return status; 1785} 1786 1787/* 1788 * ======== strmwrap_register_notify ======== 1789 */ 1790u32 strmwrap_register_notify(union trapped_args *args, void *pr_ctxt) 1791{ 1792 int status = 0; 1793 struct dsp_notification notification; 1794 struct strm_res_object *strm_res; 1795 1796 find_strm_handle(&strm_res, pr_ctxt, 1797 args->args_strm_registernotify.hstream); 1798 1799 if (!strm_res) 1800 return -EFAULT; 1801 1802 /* Initialize the notification data structure */ 1803 notification.ps_name = NULL; 1804 notification.handle = NULL; 1805 1806 status = strm_register_notify(strm_res->hstream, 1807 args->args_strm_registernotify.event_mask, 1808 args->args_strm_registernotify. 1809 notify_type, ¬ification); 1810 CP_TO_USR(args->args_strm_registernotify.hnotification, ¬ification, 1811 status, 1); 1812 1813 return status; 1814} 1815 1816/* 1817 * ======== strmwrap_select ======== 1818 */ 1819u32 strmwrap_select(union trapped_args *args, void *pr_ctxt) 1820{ 1821 u32 mask; 1822 struct strm_object *strm_tab[MAX_STREAMS]; 1823 int status = 0; 1824 struct strm_res_object *strm_res; 1825 int *ids[MAX_STREAMS]; 1826 int i; 1827 1828 if (args->args_strm_select.strm_num > MAX_STREAMS) 1829 return -EINVAL; 1830 1831 CP_FM_USR(ids, args->args_strm_select.stream_tab, status, 1832 args->args_strm_select.strm_num); 1833 1834 if (status) 1835 return status; 1836 1837 for (i = 0; i < args->args_strm_select.strm_num; i++) { 1838 find_strm_handle(&strm_res, pr_ctxt, ids[i]); 1839 1840 if (!strm_res) 1841 return -EFAULT; 1842 1843 strm_tab[i] = strm_res->hstream; 1844 } 1845 1846 if (!status) { 1847 status = strm_select(strm_tab, args->args_strm_select.strm_num, 1848 &mask, args->args_strm_select.utimeout); 1849 } 1850 CP_TO_USR(args->args_strm_select.pmask, &mask, status, 1); 1851 return status; 1852} 1853 1854/* CMM */ 1855 1856/* 1857 * ======== cmmwrap_calloc_buf ======== 1858 */ 1859u32 __deprecated cmmwrap_calloc_buf(union trapped_args * args, void *pr_ctxt) 1860{ 1861 /* This operation is done in kernel */ 1862 pr_err("%s: deprecated dspbridge ioctl\n", __func__); 1863 return -ENOSYS; 1864} 1865 1866/* 1867 * ======== cmmwrap_free_buf ======== 1868 */ 1869u32 __deprecated cmmwrap_free_buf(union trapped_args * args, void *pr_ctxt) 1870{ 1871 /* This operation is done in kernel */ 1872 pr_err("%s: deprecated dspbridge ioctl\n", __func__); 1873 return -ENOSYS; 1874} 1875 1876/* 1877 * ======== cmmwrap_get_handle ======== 1878 */ 1879u32 cmmwrap_get_handle(union trapped_args *args, void *pr_ctxt) 1880{ 1881 int status = 0; 1882 struct cmm_object *hcmm_mgr; 1883 void *hprocessor = ((struct process_context *)pr_ctxt)->hprocessor; 1884 1885 status = cmm_get_handle(hprocessor, &hcmm_mgr); 1886 1887 CP_TO_USR(args->args_cmm_gethandle.ph_cmm_mgr, &hcmm_mgr, status, 1); 1888 1889 return status; 1890} 1891 1892/* 1893 * ======== cmmwrap_get_info ======== 1894 */ 1895u32 cmmwrap_get_info(union trapped_args *args, void *pr_ctxt) 1896{ 1897 int status = 0; 1898 struct cmm_info cmm_info_obj; 1899 1900 status = cmm_get_info(args->args_cmm_getinfo.hcmm_mgr, &cmm_info_obj); 1901 1902 CP_TO_USR(args->args_cmm_getinfo.cmm_info_obj, &cmm_info_obj, status, 1903 1); 1904 1905 return status; 1906} 1907