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/*  ----------------------------------- 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 = strlen_user((char *)
 418                                args->args_mgr_registerobject.sz_path_name);
 419        if (!path_size) {
 420                status = -EINVAL;
 421                goto func_end;
 422        }
 423
 424        psz_path_name = kmalloc(path_size, GFP_KERNEL);
 425        if (!psz_path_name) {
 426                status = -ENOMEM;
 427                goto func_end;
 428        }
 429        ret = strncpy_from_user(psz_path_name,
 430                                (char *)args->args_mgr_registerobject.
 431                                sz_path_name, path_size);
 432        if (!ret) {
 433                status = -EFAULT;
 434                goto func_end;
 435        }
 436
 437        if (args->args_mgr_registerobject.obj_type >= DSP_DCDMAXOBJTYPE) {
 438                status = -EINVAL;
 439                goto func_end;
 440        }
 441
 442        status = dcd_register_object(&uuid_obj,
 443                                     args->args_mgr_registerobject.obj_type,
 444                                     (char *)psz_path_name);
 445func_end:
 446        kfree(psz_path_name);
 447        return status;
 448}
 449
 450/*
 451 * ======== mgrwrap_unregister_object ========
 452 */
 453u32 mgrwrap_unregister_object(union trapped_args *args, void *pr_ctxt)
 454{
 455        int status = 0;
 456        struct dsp_uuid uuid_obj;
 457
 458        CP_FM_USR(&uuid_obj, args->args_mgr_registerobject.uuid_obj, status, 1);
 459        if (status)
 460                goto func_end;
 461
 462        status = dcd_unregister_object(&uuid_obj,
 463                                       args->args_mgr_unregisterobject.
 464                                       obj_type);
 465func_end:
 466        return status;
 467
 468}
 469
 470/*
 471 * ======== mgrwrap_wait_for_bridge_events ========
 472 */
 473u32 mgrwrap_wait_for_bridge_events(union trapped_args *args, void *pr_ctxt)
 474{
 475        int status = 0;
 476        struct dsp_notification *anotifications[MAX_EVENTS];
 477        struct dsp_notification notifications[MAX_EVENTS];
 478        u32 index, i;
 479        u32 count = args->args_mgr_wait.count;
 480
 481        if (count > MAX_EVENTS)
 482                status = -EINVAL;
 483
 484        /* get the array of pointers to user structures */
 485        CP_FM_USR(anotifications, args->args_mgr_wait.anotifications,
 486                  status, count);
 487        /* get the events */
 488        for (i = 0; i < count; i++) {
 489                CP_FM_USR(&notifications[i], anotifications[i], status, 1);
 490                if (status || !notifications[i].handle) {
 491                        status = -EINVAL;
 492                        break;
 493                }
 494                /* set the array of pointers to kernel structures */
 495                anotifications[i] = &notifications[i];
 496        }
 497        if (!status) {
 498                status = mgr_wait_for_bridge_events(anotifications, count,
 499                                                         &index,
 500                                                         args->args_mgr_wait.
 501                                                         timeout);
 502        }
 503        CP_TO_USR(args->args_mgr_wait.index, &index, status, 1);
 504        return status;
 505}
 506
 507/*
 508 * ======== MGRWRAP_GetProcessResourceInfo ========
 509 */
 510u32 __deprecated mgrwrap_get_process_resources_info(union trapped_args * args,
 511                                                    void *pr_ctxt)
 512{
 513        pr_err("%s: deprecated dspbridge ioctl\n", __func__);
 514        return 0;
 515}
 516
 517/*
 518 * ======== procwrap_attach ========
 519 */
 520u32 procwrap_attach(union trapped_args *args, void *pr_ctxt)
 521{
 522        void *processor;
 523        int status = 0;
 524        struct dsp_processorattrin proc_attr_in, *attr_in = NULL;
 525
 526        /* Optional argument */
 527        if (args->args_proc_attach.attr_in) {
 528                CP_FM_USR(&proc_attr_in, args->args_proc_attach.attr_in, status,
 529                          1);
 530                if (!status)
 531                        attr_in = &proc_attr_in;
 532                else
 533                        goto func_end;
 534
 535        }
 536        status = proc_attach(args->args_proc_attach.processor_id, attr_in,
 537                             &processor, pr_ctxt);
 538        CP_TO_USR(args->args_proc_attach.ph_processor, &processor, status, 1);
 539func_end:
 540        return status;
 541}
 542
 543/*
 544 * ======== procwrap_ctrl ========
 545 */
 546u32 procwrap_ctrl(union trapped_args *args, void *pr_ctxt)
 547{
 548        u32 cb_data_size, __user * psize = (u32 __user *)
 549            args->args_proc_ctrl.args;
 550        u8 *pargs = NULL;
 551        int status = 0;
 552        void *hprocessor = ((struct process_context *)pr_ctxt)->processor;
 553
 554        if (psize) {
 555                if (get_user(cb_data_size, psize)) {
 556                        status = -EPERM;
 557                        goto func_end;
 558                }
 559                cb_data_size += sizeof(u32);
 560                pargs = kmalloc(cb_data_size, GFP_KERNEL);
 561                if (pargs == NULL) {
 562                        status = -ENOMEM;
 563                        goto func_end;
 564                }
 565
 566                CP_FM_USR(pargs, args->args_proc_ctrl.args, status,
 567                          cb_data_size);
 568        }
 569        if (!status) {
 570                status = proc_ctrl(hprocessor,
 571                                   args->args_proc_ctrl.cmd,
 572                                   (struct dsp_cbdata *)pargs);
 573        }
 574
 575        /* CP_TO_USR(args->args_proc_ctrl.args, pargs, status, 1); */
 576        kfree(pargs);
 577func_end:
 578        return status;
 579}
 580
 581/*
 582 * ======== procwrap_detach ========
 583 */
 584u32 __deprecated procwrap_detach(union trapped_args * args, void *pr_ctxt)
 585{
 586        /* proc_detach called at bridge_release only */
 587        pr_err("%s: deprecated dspbridge ioctl\n", __func__);
 588        return 0;
 589}
 590
 591/*
 592 * ======== procwrap_enum_node_info ========
 593 */
 594u32 procwrap_enum_node_info(union trapped_args *args, void *pr_ctxt)
 595{
 596        int status;
 597        void *node_tab[MAX_NODES];
 598        u32 num_nodes;
 599        u32 alloc_cnt;
 600        void *hprocessor = ((struct process_context *)pr_ctxt)->processor;
 601
 602        if (!args->args_proc_enumnode_info.node_tab_size)
 603                return -EINVAL;
 604
 605        status = proc_enum_nodes(hprocessor,
 606                                 node_tab,
 607                                 args->args_proc_enumnode_info.node_tab_size,
 608                                 &num_nodes, &alloc_cnt);
 609        CP_TO_USR(args->args_proc_enumnode_info.node_tab, node_tab, status,
 610                  num_nodes);
 611        CP_TO_USR(args->args_proc_enumnode_info.num_nodes, &num_nodes,
 612                  status, 1);
 613        CP_TO_USR(args->args_proc_enumnode_info.allocated, &alloc_cnt,
 614                  status, 1);
 615        return status;
 616}
 617
 618u32 procwrap_end_dma(union trapped_args *args, void *pr_ctxt)
 619{
 620        int status;
 621
 622        if (args->args_proc_dma.dir >= DMA_NONE)
 623                return -EINVAL;
 624
 625        status = proc_end_dma(pr_ctxt,
 626                                   args->args_proc_dma.mpu_addr,
 627                                   args->args_proc_dma.size,
 628                                   args->args_proc_dma.dir);
 629        return status;
 630}
 631
 632u32 procwrap_begin_dma(union trapped_args *args, void *pr_ctxt)
 633{
 634        int status;
 635
 636        if (args->args_proc_dma.dir >= DMA_NONE)
 637                return -EINVAL;
 638
 639        status = proc_begin_dma(pr_ctxt,
 640                                   args->args_proc_dma.mpu_addr,
 641                                   args->args_proc_dma.size,
 642                                   args->args_proc_dma.dir);
 643        return status;
 644}
 645
 646/*
 647 * ======== procwrap_flush_memory ========
 648 */
 649u32 procwrap_flush_memory(union trapped_args *args, void *pr_ctxt)
 650{
 651        int status;
 652
 653        if (args->args_proc_flushmemory.flags >
 654            PROC_WRITEBACK_INVALIDATE_MEM)
 655                return -EINVAL;
 656
 657        status = proc_flush_memory(pr_ctxt,
 658                                   args->args_proc_flushmemory.mpu_addr,
 659                                   args->args_proc_flushmemory.size,
 660                                   args->args_proc_flushmemory.flags);
 661        return status;
 662}
 663
 664/*
 665 * ======== procwrap_invalidate_memory ========
 666 */
 667u32 procwrap_invalidate_memory(union trapped_args *args, void *pr_ctxt)
 668{
 669        int status;
 670
 671        status =
 672            proc_invalidate_memory(pr_ctxt,
 673                                   args->args_proc_invalidatememory.mpu_addr,
 674                                   args->args_proc_invalidatememory.size);
 675        return status;
 676}
 677
 678/*
 679 * ======== procwrap_enum_resources ========
 680 */
 681u32 procwrap_enum_resources(union trapped_args *args, void *pr_ctxt)
 682{
 683        int status = 0;
 684        struct dsp_resourceinfo resource_info;
 685        void *hprocessor = ((struct process_context *)pr_ctxt)->processor;
 686
 687        if (args->args_proc_enumresources.resource_info_size <
 688            sizeof(struct dsp_resourceinfo))
 689                return -EINVAL;
 690
 691        status =
 692            proc_get_resource_info(hprocessor,
 693                                   args->args_proc_enumresources.resource_type,
 694                                   &resource_info,
 695                                   args->args_proc_enumresources.
 696                                   resource_info_size);
 697
 698        CP_TO_USR(args->args_proc_enumresources.resource_info, &resource_info,
 699                  status, 1);
 700
 701        return status;
 702
 703}
 704
 705/*
 706 * ======== procwrap_get_state ========
 707 */
 708u32 procwrap_get_state(union trapped_args *args, void *pr_ctxt)
 709{
 710        int status;
 711        struct dsp_processorstate proc_state;
 712        void *hprocessor = ((struct process_context *)pr_ctxt)->processor;
 713
 714        if (args->args_proc_getstate.state_info_size <
 715            sizeof(struct dsp_processorstate))
 716                return -EINVAL;
 717
 718        status = proc_get_state(hprocessor, &proc_state,
 719                           args->args_proc_getstate.state_info_size);
 720        CP_TO_USR(args->args_proc_getstate.proc_state_obj, &proc_state, status,
 721                  1);
 722        return status;
 723
 724}
 725
 726/*
 727 * ======== procwrap_get_trace ========
 728 */
 729u32 procwrap_get_trace(union trapped_args *args, void *pr_ctxt)
 730{
 731        int status;
 732        u8 *pbuf;
 733        void *hprocessor = ((struct process_context *)pr_ctxt)->processor;
 734
 735        if (args->args_proc_gettrace.max_size > MAX_TRACEBUFLEN)
 736                return -EINVAL;
 737
 738        pbuf = kzalloc(args->args_proc_gettrace.max_size, GFP_KERNEL);
 739        if (pbuf != NULL) {
 740                status = proc_get_trace(hprocessor, pbuf,
 741                                        args->args_proc_gettrace.max_size);
 742        } else {
 743                status = -ENOMEM;
 744        }
 745        CP_TO_USR(args->args_proc_gettrace.buf, pbuf, status,
 746                  args->args_proc_gettrace.max_size);
 747        kfree(pbuf);
 748
 749        return status;
 750}
 751
 752/*
 753 * ======== procwrap_load ========
 754 */
 755u32 procwrap_load(union trapped_args *args, void *pr_ctxt)
 756{
 757        s32 i, len;
 758        int status = 0;
 759        char *temp;
 760        s32 count = args->args_proc_load.argc_index;
 761        u8 **argv = NULL, **envp = NULL;
 762        void *hprocessor = ((struct process_context *)pr_ctxt)->processor;
 763
 764        if (count <= 0 || count > MAX_LOADARGS) {
 765                status = -EINVAL;
 766                goto func_cont;
 767        }
 768
 769        argv = kmalloc(count * sizeof(u8 *), GFP_KERNEL);
 770        if (!argv) {
 771                status = -ENOMEM;
 772                goto func_cont;
 773        }
 774
 775        CP_FM_USR(argv, args->args_proc_load.user_args, status, count);
 776        if (status) {
 777                kfree(argv);
 778                argv = NULL;
 779                goto func_cont;
 780        }
 781
 782        for (i = 0; i < count; i++) {
 783                if (argv[i]) {
 784                        /* User space pointer to argument */
 785                        temp = (char *)argv[i];
 786                        /* len is increased by 1 to accommodate NULL */
 787                        len = strlen_user((char *)temp) + 1;
 788                        /* Kernel space pointer to argument */
 789                        argv[i] = kmalloc(len, GFP_KERNEL);
 790                        if (argv[i]) {
 791                                CP_FM_USR(argv[i], temp, status, len);
 792                                if (status) {
 793                                        kfree(argv[i]);
 794                                        argv[i] = NULL;
 795                                        goto func_cont;
 796                                }
 797                        } else {
 798                                status = -ENOMEM;
 799                                goto func_cont;
 800                        }
 801                }
 802        }
 803        /* TODO: validate this */
 804        if (args->args_proc_load.user_envp) {
 805                /* number of elements in the envp array including NULL */
 806                count = 0;
 807                do {
 808                        if (get_user(temp,
 809                                     args->args_proc_load.user_envp + count)) {
 810                                status = -EFAULT;
 811                                goto func_cont;
 812                        }
 813                        count++;
 814                } while (temp);
 815                envp = kmalloc(count * sizeof(u8 *), GFP_KERNEL);
 816                if (!envp) {
 817                        status = -ENOMEM;
 818                        goto func_cont;
 819                }
 820
 821                CP_FM_USR(envp, args->args_proc_load.user_envp, status, count);
 822                if (status) {
 823                        kfree(envp);
 824                        envp = NULL;
 825                        goto func_cont;
 826                }
 827                for (i = 0; envp[i]; i++) {
 828                        /* User space pointer to argument */
 829                        temp = (char *)envp[i];
 830                        /* len is increased by 1 to accommodate NULL */
 831                        len = strlen_user((char *)temp) + 1;
 832                        /* Kernel space pointer to argument */
 833                        envp[i] = kmalloc(len, GFP_KERNEL);
 834                        if (envp[i]) {
 835                                CP_FM_USR(envp[i], temp, status, len);
 836                                if (status) {
 837                                        kfree(envp[i]);
 838                                        envp[i] = NULL;
 839                                        goto func_cont;
 840                                }
 841                        } else {
 842                                status = -ENOMEM;
 843                                goto func_cont;
 844                        }
 845                }
 846        }
 847
 848        if (!status) {
 849                status = proc_load(hprocessor,
 850                                   args->args_proc_load.argc_index,
 851                                   (const char **)argv, (const char **)envp);
 852        }
 853func_cont:
 854        if (envp) {
 855                i = 0;
 856                while (envp[i])
 857                        kfree(envp[i++]);
 858
 859                kfree(envp);
 860        }
 861
 862        if (argv) {
 863                count = args->args_proc_load.argc_index;
 864                for (i = 0; (i < count) && argv[i]; i++)
 865                        kfree(argv[i]);
 866
 867                kfree(argv);
 868        }
 869
 870        return status;
 871}
 872
 873/*
 874 * ======== procwrap_map ========
 875 */
 876u32 procwrap_map(union trapped_args *args, void *pr_ctxt)
 877{
 878        int status;
 879        void *map_addr;
 880        void *hprocessor = ((struct process_context *)pr_ctxt)->processor;
 881
 882        if (!args->args_proc_mapmem.size)
 883                return -EINVAL;
 884
 885        status = proc_map(args->args_proc_mapmem.processor,
 886                          args->args_proc_mapmem.mpu_addr,
 887                          args->args_proc_mapmem.size,
 888                          args->args_proc_mapmem.req_addr, &map_addr,
 889                          args->args_proc_mapmem.map_attr, pr_ctxt);
 890        if (!status) {
 891                if (put_user(map_addr, args->args_proc_mapmem.map_addr)) {
 892                        status = -EINVAL;
 893                        proc_un_map(hprocessor, map_addr, pr_ctxt);
 894                }
 895
 896        }
 897        return status;
 898}
 899
 900/*
 901 * ======== procwrap_register_notify ========
 902 */
 903u32 procwrap_register_notify(union trapped_args *args, void *pr_ctxt)
 904{
 905        int status;
 906        struct dsp_notification notification;
 907        void *hprocessor = ((struct process_context *)pr_ctxt)->processor;
 908
 909        /* Initialize the notification data structure */
 910        notification.name = NULL;
 911        notification.handle = NULL;
 912
 913        status = proc_register_notify(hprocessor,
 914                                 args->args_proc_register_notify.event_mask,
 915                                 args->args_proc_register_notify.notify_type,
 916                                 &notification);
 917        CP_TO_USR(args->args_proc_register_notify.notification, &notification,
 918                  status, 1);
 919        return status;
 920}
 921
 922/*
 923 * ======== procwrap_reserve_memory ========
 924 */
 925u32 procwrap_reserve_memory(union trapped_args *args, void *pr_ctxt)
 926{
 927        int status;
 928        void *prsv_addr;
 929        void *hprocessor = ((struct process_context *)pr_ctxt)->processor;
 930
 931        if ((args->args_proc_rsvmem.size <= 0) ||
 932            (args->args_proc_rsvmem.size & (PG_SIZE4K - 1)) != 0)
 933                return -EINVAL;
 934
 935        status = proc_reserve_memory(hprocessor,
 936                                     args->args_proc_rsvmem.size, &prsv_addr,
 937                                     pr_ctxt);
 938        if (!status) {
 939                if (put_user(prsv_addr, args->args_proc_rsvmem.rsv_addr)) {
 940                        status = -EINVAL;
 941                        proc_un_reserve_memory(args->args_proc_rsvmem.
 942                                               processor, prsv_addr, pr_ctxt);
 943                }
 944        }
 945        return status;
 946}
 947
 948/*
 949 * ======== procwrap_start ========
 950 */
 951u32 procwrap_start(union trapped_args *args, void *pr_ctxt)
 952{
 953        u32 ret;
 954
 955        ret = proc_start(((struct process_context *)pr_ctxt)->processor);
 956        return ret;
 957}
 958
 959/*
 960 * ======== procwrap_un_map ========
 961 */
 962u32 procwrap_un_map(union trapped_args *args, void *pr_ctxt)
 963{
 964        int status;
 965
 966        status = proc_un_map(((struct process_context *)pr_ctxt)->processor,
 967                             args->args_proc_unmapmem.map_addr, pr_ctxt);
 968        return status;
 969}
 970
 971/*
 972 * ======== procwrap_un_reserve_memory ========
 973 */
 974u32 procwrap_un_reserve_memory(union trapped_args *args, void *pr_ctxt)
 975{
 976        int status;
 977        void *hprocessor = ((struct process_context *)pr_ctxt)->processor;
 978
 979        status = proc_un_reserve_memory(hprocessor,
 980                                        args->args_proc_unrsvmem.rsv_addr,
 981                                        pr_ctxt);
 982        return status;
 983}
 984
 985/*
 986 * ======== procwrap_stop ========
 987 */
 988u32 procwrap_stop(union trapped_args *args, void *pr_ctxt)
 989{
 990        u32 ret;
 991
 992        ret = proc_stop(((struct process_context *)pr_ctxt)->processor);
 993
 994        return ret;
 995}
 996
 997/*
 998 * ======== find_handle =========
 999 */
1000inline void find_node_handle(struct node_res_object **noderes,
1001                                void *pr_ctxt, void *hnode)
1002{
1003        rcu_read_lock();
1004        *noderes = idr_find(((struct process_context *)pr_ctxt)->node_id,
1005                                                                (int)hnode - 1);
1006        rcu_read_unlock();
1007        return;
1008}
1009
1010
1011/*
1012 * ======== nodewrap_allocate ========
1013 */
1014u32 nodewrap_allocate(union trapped_args *args, void *pr_ctxt)
1015{
1016        int status = 0;
1017        struct dsp_uuid node_uuid;
1018        u32 cb_data_size = 0;
1019        u32 __user *psize = (u32 __user *) args->args_node_allocate.args;
1020        u8 *pargs = NULL;
1021        struct dsp_nodeattrin proc_attr_in, *attr_in = NULL;
1022        struct node_res_object *node_res;
1023        int nodeid;
1024        void *hprocessor = ((struct process_context *)pr_ctxt)->processor;
1025
1026        /* Optional argument */
1027        if (psize) {
1028                if (get_user(cb_data_size, psize))
1029                        status = -EPERM;
1030
1031                cb_data_size += sizeof(u32);
1032                if (!status) {
1033                        pargs = kmalloc(cb_data_size, GFP_KERNEL);
1034                        if (pargs == NULL)
1035                                status = -ENOMEM;
1036
1037                }
1038                CP_FM_USR(pargs, args->args_node_allocate.args, status,
1039                          cb_data_size);
1040        }
1041        CP_FM_USR(&node_uuid, args->args_node_allocate.node_id_ptr, status, 1);
1042        if (status)
1043                goto func_cont;
1044        /* Optional argument */
1045        if (args->args_node_allocate.attr_in) {
1046                CP_FM_USR(&proc_attr_in, args->args_node_allocate.attr_in,
1047                          status, 1);
1048                if (!status)
1049                        attr_in = &proc_attr_in;
1050                else
1051                        status = -ENOMEM;
1052
1053        }
1054        if (!status) {
1055                status = node_allocate(hprocessor,
1056                                       &node_uuid, (struct dsp_cbdata *)pargs,
1057                                       attr_in, &node_res, pr_ctxt);
1058        }
1059        if (!status) {
1060                nodeid = node_res->id + 1;
1061                CP_TO_USR(args->args_node_allocate.node, &nodeid,
1062                        status, 1);
1063                if (status) {
1064                        status = -EFAULT;
1065                        node_delete(node_res, pr_ctxt);
1066                }
1067        }
1068func_cont:
1069        kfree(pargs);
1070
1071        return status;
1072}
1073
1074/*
1075 *  ======== nodewrap_alloc_msg_buf ========
1076 */
1077u32 nodewrap_alloc_msg_buf(union trapped_args *args, void *pr_ctxt)
1078{
1079        int status = 0;
1080        struct dsp_bufferattr *pattr = NULL;
1081        struct dsp_bufferattr attr;
1082        u8 *pbuffer = NULL;
1083        struct node_res_object *node_res;
1084
1085        find_node_handle(&node_res,  pr_ctxt,
1086                                args->args_node_allocmsgbuf.node);
1087
1088        if (!node_res)
1089                return -EFAULT;
1090
1091        if (!args->args_node_allocmsgbuf.size)
1092                return -EINVAL;
1093
1094        if (args->args_node_allocmsgbuf.attr) { /* Optional argument */
1095                CP_FM_USR(&attr, args->args_node_allocmsgbuf.attr, status, 1);
1096                if (!status)
1097                        pattr = &attr;
1098
1099        }
1100        /* argument */
1101        CP_FM_USR(&pbuffer, args->args_node_allocmsgbuf.buffer, status, 1);
1102        if (!status) {
1103                status = node_alloc_msg_buf(node_res->node,
1104                                            args->args_node_allocmsgbuf.size,
1105                                            pattr, &pbuffer);
1106        }
1107        CP_TO_USR(args->args_node_allocmsgbuf.buffer, &pbuffer, status, 1);
1108        return status;
1109}
1110
1111/*
1112 * ======== nodewrap_change_priority ========
1113 */
1114u32 nodewrap_change_priority(union trapped_args *args, void *pr_ctxt)
1115{
1116        u32 ret;
1117        struct node_res_object *node_res;
1118
1119        find_node_handle(&node_res, pr_ctxt,
1120                                args->args_node_changepriority.node);
1121
1122        if (!node_res)
1123                return -EFAULT;
1124
1125        ret = node_change_priority(node_res->node,
1126                                   args->args_node_changepriority.prio);
1127
1128        return ret;
1129}
1130
1131/*
1132 * ======== nodewrap_connect ========
1133 */
1134u32 nodewrap_connect(union trapped_args *args, void *pr_ctxt)
1135{
1136        int status = 0;
1137        struct dsp_strmattr attrs;
1138        struct dsp_strmattr *pattrs = NULL;
1139        u32 cb_data_size;
1140        u32 __user *psize = (u32 __user *) args->args_node_connect.conn_param;
1141        u8 *pargs = NULL;
1142        struct node_res_object *node_res1, *node_res2;
1143        struct node_object *node1 = NULL, *node2 = NULL;
1144
1145        if ((int)args->args_node_connect.node != DSP_HGPPNODE) {
1146                find_node_handle(&node_res1, pr_ctxt,
1147                                args->args_node_connect.node);
1148                if (node_res1)
1149                        node1 = node_res1->node;
1150        } else {
1151                node1 = args->args_node_connect.node;
1152        }
1153
1154        if ((int)args->args_node_connect.other_node != DSP_HGPPNODE) {
1155                find_node_handle(&node_res2, pr_ctxt,
1156                                args->args_node_connect.other_node);
1157                if (node_res2)
1158                        node2 = node_res2->node;
1159        } else {
1160                node2 = args->args_node_connect.other_node;
1161        }
1162
1163        if (!node1 || !node2)
1164                return -EFAULT;
1165
1166        /* Optional argument */
1167        if (psize) {
1168                if (get_user(cb_data_size, psize))
1169                        status = -EPERM;
1170
1171                cb_data_size += sizeof(u32);
1172                if (!status) {
1173                        pargs = kmalloc(cb_data_size, GFP_KERNEL);
1174                        if (pargs == NULL) {
1175                                status = -ENOMEM;
1176                                goto func_cont;
1177                        }
1178
1179                }
1180                CP_FM_USR(pargs, args->args_node_connect.conn_param, status,
1181                          cb_data_size);
1182                if (status)
1183                        goto func_cont;
1184        }
1185        if (args->args_node_connect.attrs) {    /* Optional argument */
1186                CP_FM_USR(&attrs, args->args_node_connect.attrs, status, 1);
1187                if (!status)
1188                        pattrs = &attrs;
1189
1190        }
1191        if (!status) {
1192                status = node_connect(node1,
1193                                      args->args_node_connect.stream_id,
1194                                      node2,
1195                                      args->args_node_connect.other_stream,
1196                                      pattrs, (struct dsp_cbdata *)pargs);
1197        }
1198func_cont:
1199        kfree(pargs);
1200
1201        return status;
1202}
1203
1204/*
1205 * ======== nodewrap_create ========
1206 */
1207u32 nodewrap_create(union trapped_args *args, void *pr_ctxt)
1208{
1209        u32 ret;
1210        struct node_res_object *node_res;
1211
1212        find_node_handle(&node_res, pr_ctxt, args->args_node_create.node);
1213
1214        if (!node_res)
1215                return -EFAULT;
1216
1217        ret = node_create(node_res->node);
1218
1219        return ret;
1220}
1221
1222/*
1223 * ======== nodewrap_delete ========
1224 */
1225u32 nodewrap_delete(union trapped_args *args, void *pr_ctxt)
1226{
1227        u32 ret;
1228        struct node_res_object *node_res;
1229
1230        find_node_handle(&node_res, pr_ctxt, args->args_node_delete.node);
1231
1232        if (!node_res)
1233                return -EFAULT;
1234
1235        ret = node_delete(node_res, pr_ctxt);
1236
1237        return ret;
1238}
1239
1240/*
1241 *  ======== nodewrap_free_msg_buf ========
1242 */
1243u32 nodewrap_free_msg_buf(union trapped_args *args, void *pr_ctxt)
1244{
1245        int status = 0;
1246        struct dsp_bufferattr *pattr = NULL;
1247        struct dsp_bufferattr attr;
1248        struct node_res_object *node_res;
1249
1250        find_node_handle(&node_res, pr_ctxt, args->args_node_freemsgbuf.node);
1251
1252        if (!node_res)
1253                return -EFAULT;
1254
1255        if (args->args_node_freemsgbuf.attr) {  /* Optional argument */
1256                CP_FM_USR(&attr, args->args_node_freemsgbuf.attr, status, 1);
1257                if (!status)
1258                        pattr = &attr;
1259
1260        }
1261
1262        if (!args->args_node_freemsgbuf.buffer)
1263                return -EFAULT;
1264
1265        if (!status) {
1266                status = node_free_msg_buf(node_res->node,
1267                                           args->args_node_freemsgbuf.buffer,
1268                                           pattr);
1269        }
1270
1271        return status;
1272}
1273
1274/*
1275 * ======== nodewrap_get_attr ========
1276 */
1277u32 nodewrap_get_attr(union trapped_args *args, void *pr_ctxt)
1278{
1279        int status = 0;
1280        struct dsp_nodeattr attr;
1281        struct node_res_object *node_res;
1282
1283        find_node_handle(&node_res, pr_ctxt, args->args_node_getattr.node);
1284
1285        if (!node_res)
1286                return -EFAULT;
1287
1288        status = node_get_attr(node_res->node, &attr,
1289                               args->args_node_getattr.attr_size);
1290        CP_TO_USR(args->args_node_getattr.attr, &attr, status, 1);
1291
1292        return status;
1293}
1294
1295/*
1296 * ======== nodewrap_get_message ========
1297 */
1298u32 nodewrap_get_message(union trapped_args *args, void *pr_ctxt)
1299{
1300        int status;
1301        struct dsp_msg msg;
1302        struct node_res_object *node_res;
1303
1304        find_node_handle(&node_res, pr_ctxt, args->args_node_getmessage.node);
1305
1306        if (!node_res)
1307                return -EFAULT;
1308
1309        status = node_get_message(node_res->node, &msg,
1310                                  args->args_node_getmessage.timeout);
1311
1312        CP_TO_USR(args->args_node_getmessage.message, &msg, status, 1);
1313
1314        return status;
1315}
1316
1317/*
1318 * ======== nodewrap_pause ========
1319 */
1320u32 nodewrap_pause(union trapped_args *args, void *pr_ctxt)
1321{
1322        u32 ret;
1323        struct node_res_object *node_res;
1324
1325        find_node_handle(&node_res, pr_ctxt, args->args_node_pause.node);
1326
1327        if (!node_res)
1328                return -EFAULT;
1329
1330        ret = node_pause(node_res->node);
1331
1332        return ret;
1333}
1334
1335/*
1336 * ======== nodewrap_put_message ========
1337 */
1338u32 nodewrap_put_message(union trapped_args *args, void *pr_ctxt)
1339{
1340        int status = 0;
1341        struct dsp_msg msg;
1342        struct node_res_object *node_res;
1343
1344        find_node_handle(&node_res, pr_ctxt, args->args_node_putmessage.node);
1345
1346        if (!node_res)
1347                return -EFAULT;
1348
1349        CP_FM_USR(&msg, args->args_node_putmessage.message, status, 1);
1350
1351        if (!status) {
1352                status =
1353                    node_put_message(node_res->node, &msg,
1354                                     args->args_node_putmessage.timeout);
1355        }
1356
1357        return status;
1358}
1359
1360/*
1361 * ======== nodewrap_register_notify ========
1362 */
1363u32 nodewrap_register_notify(union trapped_args *args, void *pr_ctxt)
1364{
1365        int status = 0;
1366        struct dsp_notification notification;
1367        struct node_res_object *node_res;
1368
1369        find_node_handle(&node_res, pr_ctxt,
1370                        args->args_node_registernotify.node);
1371
1372        if (!node_res)
1373                return -EFAULT;
1374
1375        /* Initialize the notification data structure */
1376        notification.name = NULL;
1377        notification.handle = NULL;
1378
1379        if (!args->args_proc_register_notify.event_mask)
1380                CP_FM_USR(&notification,
1381                          args->args_proc_register_notify.notification,
1382                          status, 1);
1383
1384        status = node_register_notify(node_res->node,
1385                                      args->args_node_registernotify.event_mask,
1386                                      args->args_node_registernotify.
1387                                      notify_type, &notification);
1388        CP_TO_USR(args->args_node_registernotify.notification, &notification,
1389                  status, 1);
1390        return status;
1391}
1392
1393/*
1394 * ======== nodewrap_run ========
1395 */
1396u32 nodewrap_run(union trapped_args *args, void *pr_ctxt)
1397{
1398        u32 ret;
1399        struct node_res_object *node_res;
1400
1401        find_node_handle(&node_res, pr_ctxt, args->args_node_run.node);
1402
1403        if (!node_res)
1404                return -EFAULT;
1405
1406        ret = node_run(node_res->node);
1407
1408        return ret;
1409}
1410
1411/*
1412 * ======== nodewrap_terminate ========
1413 */
1414u32 nodewrap_terminate(union trapped_args *args, void *pr_ctxt)
1415{
1416        int status;
1417        int tempstatus;
1418        struct node_res_object *node_res;
1419
1420        find_node_handle(&node_res, pr_ctxt, args->args_node_terminate.node);
1421
1422        if (!node_res)
1423                return -EFAULT;
1424
1425        status = node_terminate(node_res->node, &tempstatus);
1426
1427        CP_TO_USR(args->args_node_terminate.status, &tempstatus, status, 1);
1428
1429        return status;
1430}
1431
1432/*
1433 * ======== nodewrap_get_uuid_props ========
1434 */
1435u32 nodewrap_get_uuid_props(union trapped_args *args, void *pr_ctxt)
1436{
1437        int status = 0;
1438        struct dsp_uuid node_uuid;
1439        struct dsp_ndbprops *pnode_props = NULL;
1440        void *hprocessor = ((struct process_context *)pr_ctxt)->processor;
1441
1442        CP_FM_USR(&node_uuid, args->args_node_getuuidprops.node_id_ptr, status,
1443                  1);
1444        if (status)
1445                goto func_cont;
1446        pnode_props = kmalloc(sizeof(struct dsp_ndbprops), GFP_KERNEL);
1447        if (pnode_props != NULL) {
1448                status =
1449                    node_get_uuid_props(hprocessor, &node_uuid, pnode_props);
1450                CP_TO_USR(args->args_node_getuuidprops.node_props, pnode_props,
1451                          status, 1);
1452        } else
1453                status = -ENOMEM;
1454func_cont:
1455        kfree(pnode_props);
1456        return status;
1457}
1458
1459/*
1460 * ======== find_strm_handle =========
1461 */
1462inline void find_strm_handle(struct strm_res_object **strmres,
1463                                void *pr_ctxt, void *hstream)
1464{
1465        rcu_read_lock();
1466        *strmres = idr_find(((struct process_context *)pr_ctxt)->stream_id,
1467                                                        (int)hstream - 1);
1468        rcu_read_unlock();
1469        return;
1470}
1471
1472/*
1473 * ======== strmwrap_allocate_buffer ========
1474 */
1475u32 strmwrap_allocate_buffer(union trapped_args *args, void *pr_ctxt)
1476{
1477        int status;
1478        u8 **ap_buffer = NULL;
1479        u32 num_bufs = args->args_strm_allocatebuffer.num_bufs;
1480        struct strm_res_object *strm_res;
1481
1482        find_strm_handle(&strm_res, pr_ctxt,
1483                args->args_strm_allocatebuffer.stream);
1484
1485        if (!strm_res)
1486                return -EFAULT;
1487
1488        if (num_bufs > MAX_BUFS)
1489                return -EINVAL;
1490
1491        ap_buffer = kmalloc((num_bufs * sizeof(u8 *)), GFP_KERNEL);
1492        if (ap_buffer == NULL)
1493                return -ENOMEM;
1494
1495        status = strm_allocate_buffer(strm_res,
1496                                      args->args_strm_allocatebuffer.size,
1497                                      ap_buffer, num_bufs, pr_ctxt);
1498        if (!status) {
1499                CP_TO_USR(args->args_strm_allocatebuffer.ap_buffer, ap_buffer,
1500                          status, num_bufs);
1501                if (status) {
1502                        status = -EFAULT;
1503                        strm_free_buffer(strm_res,
1504                                         ap_buffer, num_bufs, pr_ctxt);
1505                }
1506        }
1507        kfree(ap_buffer);
1508
1509        return status;
1510}
1511
1512/*
1513 * ======== strmwrap_close ========
1514 */
1515u32 strmwrap_close(union trapped_args *args, void *pr_ctxt)
1516{
1517        struct strm_res_object *strm_res;
1518
1519        find_strm_handle(&strm_res, pr_ctxt, args->args_strm_close.stream);
1520
1521        if (!strm_res)
1522                return -EFAULT;
1523
1524        return strm_close(strm_res, pr_ctxt);
1525}
1526
1527/*
1528 * ======== strmwrap_free_buffer ========
1529 */
1530u32 strmwrap_free_buffer(union trapped_args *args, void *pr_ctxt)
1531{
1532        int status = 0;
1533        u8 **ap_buffer = NULL;
1534        u32 num_bufs = args->args_strm_freebuffer.num_bufs;
1535        struct strm_res_object *strm_res;
1536
1537        find_strm_handle(&strm_res, pr_ctxt,
1538                        args->args_strm_freebuffer.stream);
1539
1540        if (!strm_res)
1541                return -EFAULT;
1542
1543        if (num_bufs > MAX_BUFS)
1544                return -EINVAL;
1545
1546        ap_buffer = kmalloc_array(num_bufs, sizeof(u8 *), GFP_KERNEL);
1547        if (ap_buffer == NULL)
1548                return -ENOMEM;
1549
1550        CP_FM_USR(ap_buffer, args->args_strm_freebuffer.ap_buffer, status,
1551                  num_bufs);
1552
1553        if (!status)
1554                status = strm_free_buffer(strm_res,
1555                                          ap_buffer, num_bufs, pr_ctxt);
1556
1557        CP_TO_USR(args->args_strm_freebuffer.ap_buffer, ap_buffer, status,
1558                  num_bufs);
1559        kfree(ap_buffer);
1560
1561        return status;
1562}
1563
1564/*
1565 * ======== strmwrap_get_event_handle ========
1566 */
1567u32 __deprecated strmwrap_get_event_handle(union trapped_args * args,
1568                                           void *pr_ctxt)
1569{
1570        pr_err("%s: deprecated dspbridge ioctl\n", __func__);
1571        return -ENOSYS;
1572}
1573
1574/*
1575 * ======== strmwrap_get_info ========
1576 */
1577u32 strmwrap_get_info(union trapped_args *args, void *pr_ctxt)
1578{
1579        int status = 0;
1580        struct stream_info strm_info;
1581        struct dsp_streaminfo user;
1582        struct dsp_streaminfo *temp;
1583        struct strm_res_object *strm_res;
1584
1585        find_strm_handle(&strm_res, pr_ctxt,
1586                        args->args_strm_getinfo.stream);
1587
1588        if (!strm_res)
1589                return -EFAULT;
1590
1591        CP_FM_USR(&strm_info, args->args_strm_getinfo.stream_info, status, 1);
1592        temp = strm_info.user_strm;
1593
1594        strm_info.user_strm = &user;
1595
1596        if (!status) {
1597                status = strm_get_info(strm_res->stream,
1598                                       &strm_info,
1599                                       args->args_strm_getinfo.
1600                                       stream_info_size);
1601        }
1602        CP_TO_USR(temp, strm_info.user_strm, status, 1);
1603        strm_info.user_strm = temp;
1604        CP_TO_USR(args->args_strm_getinfo.stream_info, &strm_info, status, 1);
1605        return status;
1606}
1607
1608/*
1609 * ======== strmwrap_idle ========
1610 */
1611u32 strmwrap_idle(union trapped_args *args, void *pr_ctxt)
1612{
1613        u32 ret;
1614        struct strm_res_object *strm_res;
1615
1616        find_strm_handle(&strm_res, pr_ctxt, args->args_strm_idle.stream);
1617
1618        if (!strm_res)
1619                return -EFAULT;
1620
1621        ret = strm_idle(strm_res->stream, args->args_strm_idle.flush_flag);
1622
1623        return ret;
1624}
1625
1626/*
1627 * ======== strmwrap_issue ========
1628 */
1629u32 strmwrap_issue(union trapped_args *args, void *pr_ctxt)
1630{
1631        int status = 0;
1632        struct strm_res_object *strm_res;
1633
1634        find_strm_handle(&strm_res, pr_ctxt, args->args_strm_issue.stream);
1635
1636        if (!strm_res)
1637                return -EFAULT;
1638
1639        if (!args->args_strm_issue.buffer)
1640                return -EFAULT;
1641
1642        /* No need of doing CP_FM_USR for the user buffer (pbuffer)
1643           as this is done in Bridge internal function bridge_chnl_add_io_req
1644           in chnl_sm.c */
1645        status = strm_issue(strm_res->stream,
1646                            args->args_strm_issue.buffer,
1647                            args->args_strm_issue.bytes,
1648                            args->args_strm_issue.buf_size,
1649                            args->args_strm_issue.arg);
1650
1651        return status;
1652}
1653
1654/*
1655 * ======== strmwrap_open ========
1656 */
1657u32 strmwrap_open(union trapped_args *args, void *pr_ctxt)
1658{
1659        int status = 0;
1660        struct strm_attr attr;
1661        struct strm_res_object *strm_res_obj;
1662        struct dsp_streamattrin strm_attr_in;
1663        struct node_res_object *node_res;
1664        int strmid;
1665
1666        find_node_handle(&node_res, pr_ctxt, args->args_strm_open.node);
1667
1668        if (!node_res)
1669                return -EFAULT;
1670
1671        CP_FM_USR(&attr, args->args_strm_open.attr_in, status, 1);
1672
1673        if (attr.stream_attr_in != NULL) {      /* Optional argument */
1674                CP_FM_USR(&strm_attr_in, attr.stream_attr_in, status, 1);
1675                if (!status) {
1676                        attr.stream_attr_in = &strm_attr_in;
1677                        if (attr.stream_attr_in->strm_mode == STRMMODE_LDMA)
1678                                return -ENOSYS;
1679                }
1680
1681        }
1682        status = strm_open(node_res->node,
1683                           args->args_strm_open.direction,
1684                           args->args_strm_open.index, &attr, &strm_res_obj,
1685                           pr_ctxt);
1686        if (!status) {
1687                strmid = strm_res_obj->id + 1;
1688                CP_TO_USR(args->args_strm_open.stream, &strmid, status, 1);
1689        }
1690        return status;
1691}
1692
1693/*
1694 * ======== strmwrap_reclaim ========
1695 */
1696u32 strmwrap_reclaim(union trapped_args *args, void *pr_ctxt)
1697{
1698        int status = 0;
1699        u8 *buf_ptr;
1700        u32 ul_bytes;
1701        u32 dw_arg;
1702        u32 ul_buf_size;
1703        struct strm_res_object *strm_res;
1704
1705        find_strm_handle(&strm_res, pr_ctxt, args->args_strm_reclaim.stream);
1706
1707        if (!strm_res)
1708                return -EFAULT;
1709
1710        status = strm_reclaim(strm_res->stream, &buf_ptr,
1711                              &ul_bytes, &ul_buf_size, &dw_arg);
1712        CP_TO_USR(args->args_strm_reclaim.buf_ptr, &buf_ptr, status, 1);
1713        CP_TO_USR(args->args_strm_reclaim.bytes, &ul_bytes, status, 1);
1714        CP_TO_USR(args->args_strm_reclaim.arg, &dw_arg, status, 1);
1715
1716        if (args->args_strm_reclaim.buf_size_ptr != NULL) {
1717                CP_TO_USR(args->args_strm_reclaim.buf_size_ptr, &ul_buf_size,
1718                          status, 1);
1719        }
1720
1721        return status;
1722}
1723
1724/*
1725 * ======== strmwrap_register_notify ========
1726 */
1727u32 strmwrap_register_notify(union trapped_args *args, void *pr_ctxt)
1728{
1729        int status = 0;
1730        struct dsp_notification notification;
1731        struct strm_res_object *strm_res;
1732
1733        find_strm_handle(&strm_res, pr_ctxt,
1734                        args->args_strm_registernotify.stream);
1735
1736        if (!strm_res)
1737                return -EFAULT;
1738
1739        /* Initialize the notification data structure */
1740        notification.name = NULL;
1741        notification.handle = NULL;
1742
1743        status = strm_register_notify(strm_res->stream,
1744                                      args->args_strm_registernotify.event_mask,
1745                                      args->args_strm_registernotify.
1746                                      notify_type, &notification);
1747        CP_TO_USR(args->args_strm_registernotify.notification, &notification,
1748                  status, 1);
1749
1750        return status;
1751}
1752
1753/*
1754 * ======== strmwrap_select ========
1755 */
1756u32 strmwrap_select(union trapped_args *args, void *pr_ctxt)
1757{
1758        u32 mask;
1759        struct strm_object *strm_tab[MAX_STREAMS];
1760        int status = 0;
1761        struct strm_res_object *strm_res;
1762        int *ids[MAX_STREAMS];
1763        int i;
1764
1765        if (args->args_strm_select.strm_num > MAX_STREAMS)
1766                return -EINVAL;
1767
1768        CP_FM_USR(ids, args->args_strm_select.stream_tab, status,
1769                args->args_strm_select.strm_num);
1770
1771        if (status)
1772                return status;
1773
1774        for (i = 0; i < args->args_strm_select.strm_num; i++) {
1775                find_strm_handle(&strm_res, pr_ctxt, ids[i]);
1776
1777                if (!strm_res)
1778                        return -EFAULT;
1779
1780                strm_tab[i] = strm_res->stream;
1781        }
1782
1783        if (!status) {
1784                status = strm_select(strm_tab, args->args_strm_select.strm_num,
1785                                     &mask, args->args_strm_select.timeout);
1786        }
1787        CP_TO_USR(args->args_strm_select.mask, &mask, status, 1);
1788        return status;
1789}
1790
1791/* CMM */
1792
1793/*
1794 * ======== cmmwrap_calloc_buf ========
1795 */
1796u32 __deprecated cmmwrap_calloc_buf(union trapped_args * args, void *pr_ctxt)
1797{
1798        /* This operation is done in kernel */
1799        pr_err("%s: deprecated dspbridge ioctl\n", __func__);
1800        return -ENOSYS;
1801}
1802
1803/*
1804 * ======== cmmwrap_free_buf ========
1805 */
1806u32 __deprecated cmmwrap_free_buf(union trapped_args * args, void *pr_ctxt)
1807{
1808        /* This operation is done in kernel */
1809        pr_err("%s: deprecated dspbridge ioctl\n", __func__);
1810        return -ENOSYS;
1811}
1812
1813/*
1814 * ======== cmmwrap_get_handle ========
1815 */
1816u32 cmmwrap_get_handle(union trapped_args *args, void *pr_ctxt)
1817{
1818        int status = 0;
1819        struct cmm_object *hcmm_mgr;
1820        void *hprocessor = ((struct process_context *)pr_ctxt)->processor;
1821
1822        status = cmm_get_handle(hprocessor, &hcmm_mgr);
1823
1824        CP_TO_USR(args->args_cmm_gethandle.cmm_mgr, &hcmm_mgr, status, 1);
1825
1826        return status;
1827}
1828
1829/*
1830 * ======== cmmwrap_get_info ========
1831 */
1832u32 cmmwrap_get_info(union trapped_args *args, void *pr_ctxt)
1833{
1834        int status = 0;
1835        struct cmm_info cmm_info_obj;
1836
1837        status = cmm_get_info(args->args_cmm_getinfo.cmm_mgr, &cmm_info_obj);
1838
1839        CP_TO_USR(args->args_cmm_getinfo.cmm_info_obj, &cmm_info_obj, status,
1840                  1);
1841
1842        return status;
1843}
1844