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