linux/drivers/staging/tidspbridge/rmgr/mgr.c
<<
>>
Prefs
   1/*
   2 * mgr.c
   3 *
   4 * DSP-BIOS Bridge driver support functions for TI OMAP processors.
   5 *
   6 * Implementation of Manager interface to the device object at the
   7 * driver level. This queries the NDB data base and retrieves the
   8 * data about Node and Processor.
   9 *
  10 * Copyright (C) 2005-2006 Texas Instruments, Inc.
  11 *
  12 * This package is free software; you can redistribute it and/or modify
  13 * it under the terms of the GNU General Public License version 2 as
  14 * published by the Free Software Foundation.
  15 *
  16 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  18 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  19 */
  20
  21#include <linux/types.h>
  22
  23/*  ----------------------------------- Host OS */
  24#include <dspbridge/host_os.h>
  25
  26/*  ----------------------------------- DSP/BIOS Bridge */
  27#include <dspbridge/dbdefs.h>
  28
  29/*  ----------------------------------- Trace & Debug */
  30#include <dspbridge/dbc.h>
  31
  32/*  ----------------------------------- OS Adaptation Layer */
  33#include <dspbridge/sync.h>
  34
  35/*  ----------------------------------- Others */
  36#include <dspbridge/dbdcd.h>
  37#include <dspbridge/drv.h>
  38#include <dspbridge/dev.h>
  39
  40/*  ----------------------------------- This */
  41#include <dspbridge/mgr.h>
  42
  43/*  ----------------------------------- Defines, Data Structures, Typedefs */
  44#define ZLDLLNAME               ""
  45
  46struct mgr_object {
  47        struct dcd_manager *hdcd_mgr;   /* Proc/Node data manager */
  48};
  49
  50/*  ----------------------------------- Globals */
  51static u32 refs;
  52
  53/*
  54 *  ========= mgr_create =========
  55 *  Purpose:
  56 *      MGR Object gets created only once during driver Loading.
  57 */
  58int mgr_create(struct mgr_object **mgr_obj,
  59                      struct cfg_devnode *dev_node_obj)
  60{
  61        int status = 0;
  62        struct mgr_object *pmgr_obj = NULL;
  63        struct drv_data *drv_datap = dev_get_drvdata(bridge);
  64
  65        DBC_REQUIRE(mgr_obj != NULL);
  66        DBC_REQUIRE(refs > 0);
  67
  68        pmgr_obj = kzalloc(sizeof(struct mgr_object), GFP_KERNEL);
  69        if (pmgr_obj) {
  70                status = dcd_create_manager(ZLDLLNAME, &pmgr_obj->hdcd_mgr);
  71                if (!status) {
  72                        /* If succeeded store the handle in the MGR Object */
  73                        if (drv_datap) {
  74                                drv_datap->mgr_object = (void *)pmgr_obj;
  75                        } else {
  76                                status = -EPERM;
  77                                pr_err("%s: Failed to store MGR object\n",
  78                                                                __func__);
  79                        }
  80
  81                        if (!status) {
  82                                *mgr_obj = pmgr_obj;
  83                        } else {
  84                                dcd_destroy_manager(pmgr_obj->hdcd_mgr);
  85                                kfree(pmgr_obj);
  86                        }
  87                } else {
  88                        /* failed to Create DCD Manager */
  89                        kfree(pmgr_obj);
  90                }
  91        } else {
  92                status = -ENOMEM;
  93        }
  94
  95        DBC_ENSURE(status || pmgr_obj);
  96        return status;
  97}
  98
  99/*
 100 *  ========= mgr_destroy =========
 101 *     This function is invoked during bridge driver unloading.Frees MGR object.
 102 */
 103int mgr_destroy(struct mgr_object *hmgr_obj)
 104{
 105        int status = 0;
 106        struct mgr_object *pmgr_obj = (struct mgr_object *)hmgr_obj;
 107        struct drv_data *drv_datap = dev_get_drvdata(bridge);
 108
 109        DBC_REQUIRE(refs > 0);
 110        DBC_REQUIRE(hmgr_obj);
 111
 112        /* Free resources */
 113        if (hmgr_obj->hdcd_mgr)
 114                dcd_destroy_manager(hmgr_obj->hdcd_mgr);
 115
 116        kfree(pmgr_obj);
 117        /* Update the driver data with NULL for MGR Object */
 118        if (drv_datap) {
 119                drv_datap->mgr_object = NULL;
 120        } else {
 121                status = -EPERM;
 122                pr_err("%s: Failed to store MGR object\n", __func__);
 123        }
 124
 125        return status;
 126}
 127
 128/*
 129 *  ======== mgr_enum_node_info ========
 130 *      Enumerate and get configuration information about nodes configured
 131 *      in the node database.
 132 */
 133int mgr_enum_node_info(u32 node_id, struct dsp_ndbprops *pndb_props,
 134                              u32 undb_props_size, u32 *pu_num_nodes)
 135{
 136        int status = 0;
 137        struct dsp_uuid node_uuid, temp_uuid;
 138        u32 temp_index = 0;
 139        u32 node_index = 0;
 140        struct dcd_genericobj gen_obj;
 141        struct mgr_object *pmgr_obj = NULL;
 142        struct drv_data *drv_datap = dev_get_drvdata(bridge);
 143
 144        DBC_REQUIRE(pndb_props != NULL);
 145        DBC_REQUIRE(pu_num_nodes != NULL);
 146        DBC_REQUIRE(undb_props_size >= sizeof(struct dsp_ndbprops));
 147        DBC_REQUIRE(refs > 0);
 148
 149        *pu_num_nodes = 0;
 150        /* Get the Manager Object from the driver data */
 151        if (!drv_datap || !drv_datap->mgr_object) {
 152                status = -ENODATA;
 153                pr_err("%s: Failed to retrieve the object handle\n", __func__);
 154                goto func_cont;
 155        } else {
 156                pmgr_obj = drv_datap->mgr_object;
 157        }
 158
 159        DBC_ASSERT(pmgr_obj);
 160        /* Forever loop till we hit failed or no more items in the
 161         * Enumeration. We will exit the loop other than 0; */
 162        while (status == 0) {
 163                status = dcd_enumerate_object(temp_index++, DSP_DCDNODETYPE,
 164                                              &temp_uuid);
 165                if (status == 0) {
 166                        node_index++;
 167                        if (node_id == (node_index - 1))
 168                                node_uuid = temp_uuid;
 169
 170                }
 171        }
 172        if (!status) {
 173                if (node_id > (node_index - 1)) {
 174                        status = -EINVAL;
 175                } else {
 176                        status = dcd_get_object_def(pmgr_obj->hdcd_mgr,
 177                                                    (struct dsp_uuid *)
 178                                                    &node_uuid, DSP_DCDNODETYPE,
 179                                                    &gen_obj);
 180                        if (!status) {
 181                                /* Get the Obj def */
 182                                *pndb_props =
 183                                    gen_obj.obj_data.node_obj.ndb_props;
 184                                *pu_num_nodes = node_index;
 185                        }
 186                }
 187        }
 188
 189func_cont:
 190        DBC_ENSURE((!status && *pu_num_nodes > 0) ||
 191                   (status && *pu_num_nodes == 0));
 192
 193        return status;
 194}
 195
 196/*
 197 *  ======== mgr_enum_processor_info ========
 198 *      Enumerate and get configuration information about available
 199 *      DSP processors.
 200 */
 201int mgr_enum_processor_info(u32 processor_id,
 202                                   struct dsp_processorinfo *
 203                                   processor_info, u32 processor_info_size,
 204                                   u8 *pu_num_procs)
 205{
 206        int status = 0;
 207        int status1 = 0;
 208        int status2 = 0;
 209        struct dsp_uuid temp_uuid;
 210        u32 temp_index = 0;
 211        u32 proc_index = 0;
 212        struct dcd_genericobj gen_obj;
 213        struct mgr_object *pmgr_obj = NULL;
 214        struct mgr_processorextinfo *ext_info;
 215        struct dev_object *hdev_obj;
 216        struct drv_object *hdrv_obj;
 217        u8 dev_type;
 218        struct cfg_devnode *dev_node;
 219        struct drv_data *drv_datap = dev_get_drvdata(bridge);
 220        bool proc_detect = false;
 221
 222        DBC_REQUIRE(processor_info != NULL);
 223        DBC_REQUIRE(pu_num_procs != NULL);
 224        DBC_REQUIRE(processor_info_size >= sizeof(struct dsp_processorinfo));
 225        DBC_REQUIRE(refs > 0);
 226
 227        *pu_num_procs = 0;
 228
 229        /* Retrieve the Object handle from the driver data */
 230        if (!drv_datap || !drv_datap->drv_object) {
 231                status = -ENODATA;
 232                pr_err("%s: Failed to retrieve the object handle\n", __func__);
 233        } else {
 234                hdrv_obj = drv_datap->drv_object;
 235        }
 236
 237        if (!status) {
 238                status = drv_get_dev_object(processor_id, hdrv_obj, &hdev_obj);
 239                if (!status) {
 240                        status = dev_get_dev_type(hdev_obj, (u8 *) &dev_type);
 241                        status = dev_get_dev_node(hdev_obj, &dev_node);
 242                        if (dev_type != DSP_UNIT)
 243                                status = -EPERM;
 244
 245                        if (!status)
 246                                processor_info->processor_type = DSPTYPE64;
 247                }
 248        }
 249        if (status)
 250                goto func_end;
 251
 252        /* Get The Manager Object from the driver data */
 253        if (drv_datap && drv_datap->mgr_object) {
 254                pmgr_obj = drv_datap->mgr_object;
 255        } else {
 256                dev_dbg(bridge, "%s: Failed to get MGR Object\n", __func__);
 257                goto func_end;
 258        }
 259        DBC_ASSERT(pmgr_obj);
 260        /* Forever loop till we hit no more items in the
 261         * Enumeration. We will exit the loop other than 0; */
 262        while (status1 == 0) {
 263                status1 = dcd_enumerate_object(temp_index++,
 264                                               DSP_DCDPROCESSORTYPE,
 265                                               &temp_uuid);
 266                if (status1 != 0)
 267                        break;
 268
 269                proc_index++;
 270                /* Get the Object properties to find the Device/Processor
 271                 * Type */
 272                if (proc_detect != false)
 273                        continue;
 274
 275                status2 = dcd_get_object_def(pmgr_obj->hdcd_mgr,
 276                                             (struct dsp_uuid *)&temp_uuid,
 277                                             DSP_DCDPROCESSORTYPE, &gen_obj);
 278                if (!status2) {
 279                        /* Get the Obj def */
 280                        if (processor_info_size <
 281                            sizeof(struct mgr_processorextinfo)) {
 282                                *processor_info = gen_obj.obj_data.proc_info;
 283                        } else {
 284                                /* extended info */
 285                                ext_info = (struct mgr_processorextinfo *)
 286                                    processor_info;
 287                                *ext_info = gen_obj.obj_data.ext_proc_obj;
 288                        }
 289                        dev_dbg(bridge, "%s: Got proctype  from DCD %x\n",
 290                                __func__, processor_info->processor_type);
 291                        /* See if we got the needed processor */
 292                        if (dev_type == DSP_UNIT) {
 293                                if (processor_info->processor_type ==
 294                                    DSPPROCTYPE_C64)
 295                                        proc_detect = true;
 296                        } else if (dev_type == IVA_UNIT) {
 297                                if (processor_info->processor_type ==
 298                                    IVAPROCTYPE_ARM7)
 299                                        proc_detect = true;
 300                        }
 301                        /* User applciatiuons aonly check for chip type, so
 302                         * this clumsy overwrite */
 303                        processor_info->processor_type = DSPTYPE64;
 304                } else {
 305                        dev_dbg(bridge, "%s: Failed to get DCD processor info "
 306                                "%x\n", __func__, status2);
 307                        status = -EPERM;
 308                }
 309        }
 310        *pu_num_procs = proc_index;
 311        if (proc_detect == false) {
 312                dev_dbg(bridge, "%s: Failed to get proc info from DCD, so use "
 313                        "CFG registry\n", __func__);
 314                processor_info->processor_type = DSPTYPE64;
 315        }
 316func_end:
 317        return status;
 318}
 319
 320/*
 321 *  ======== mgr_exit ========
 322 *      Decrement reference count, and free resources when reference count is
 323 *      0.
 324 */
 325void mgr_exit(void)
 326{
 327        DBC_REQUIRE(refs > 0);
 328        refs--;
 329        if (refs == 0)
 330                dcd_exit();
 331
 332        DBC_ENSURE(refs >= 0);
 333}
 334
 335/*
 336 *  ======== mgr_get_dcd_handle ========
 337 *      Retrieves the MGR handle. Accessor Function.
 338 */
 339int mgr_get_dcd_handle(struct mgr_object *mgr_handle,
 340                              u32 *dcd_handle)
 341{
 342        int status = -EPERM;
 343        struct mgr_object *pmgr_obj = (struct mgr_object *)mgr_handle;
 344
 345        DBC_REQUIRE(refs > 0);
 346        DBC_REQUIRE(dcd_handle != NULL);
 347
 348        *dcd_handle = (u32) NULL;
 349        if (pmgr_obj) {
 350                *dcd_handle = (u32) pmgr_obj->hdcd_mgr;
 351                status = 0;
 352        }
 353        DBC_ENSURE((!status && *dcd_handle != (u32) NULL) ||
 354                   (status && *dcd_handle == (u32) NULL));
 355
 356        return status;
 357}
 358
 359/*
 360 *  ======== mgr_init ========
 361 *      Initialize MGR's private state, keeping a reference count on each call.
 362 */
 363bool mgr_init(void)
 364{
 365        bool ret = true;
 366        bool init_dcd = false;
 367
 368        DBC_REQUIRE(refs >= 0);
 369
 370        if (refs == 0) {
 371                init_dcd = dcd_init();  /*  DCD Module */
 372
 373                if (!init_dcd)
 374                        ret = false;
 375        }
 376
 377        if (ret)
 378                refs++;
 379
 380        DBC_ENSURE((ret && (refs > 0)) || (!ret && (refs >= 0)));
 381
 382        return ret;
 383}
 384
 385/*
 386 *  ======== mgr_wait_for_bridge_events ========
 387 *      Block on any Bridge event(s)
 388 */
 389int mgr_wait_for_bridge_events(struct dsp_notification **anotifications,
 390                                      u32 count, u32 *pu_index,
 391                                      u32 utimeout)
 392{
 393        int status;
 394        struct sync_object *sync_events[MAX_EVENTS];
 395        u32 i;
 396
 397        DBC_REQUIRE(count < MAX_EVENTS);
 398
 399        for (i = 0; i < count; i++)
 400                sync_events[i] = anotifications[i]->handle;
 401
 402        status = sync_wait_on_multiple_events(sync_events, count, utimeout,
 403                                              pu_index);
 404
 405        return status;
 406
 407}
 408