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