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/*  ----------------------------------- OS Adaptation Layer */
  30#include <dspbridge/sync.h>
  31
  32/*  ----------------------------------- Others */
  33#include <dspbridge/dbdcd.h>
  34#include <dspbridge/drv.h>
  35#include <dspbridge/dev.h>
  36
  37/*  ----------------------------------- This */
  38#include <dspbridge/mgr.h>
  39
  40/*  ----------------------------------- Defines, Data Structures, Typedefs */
  41#define ZLDLLNAME               ""
  42
  43struct mgr_object {
  44        struct dcd_manager *dcd_mgr;    /* Proc/Node data manager */
  45};
  46
  47/*  ----------------------------------- Globals */
  48static u32 refs;
  49
  50/*
  51 *  ========= mgr_create =========
  52 *  Purpose:
  53 *      MGR Object gets created only once during driver Loading.
  54 */
  55int mgr_create(struct mgr_object **mgr_obj,
  56                      struct cfg_devnode *dev_node_obj)
  57{
  58        int status = 0;
  59        struct mgr_object *pmgr_obj = NULL;
  60        struct drv_data *drv_datap = dev_get_drvdata(bridge);
  61
  62        pmgr_obj = kzalloc(sizeof(struct mgr_object), GFP_KERNEL);
  63        if (pmgr_obj) {
  64                status = dcd_create_manager(ZLDLLNAME, &pmgr_obj->dcd_mgr);
  65                if (!status) {
  66                        /* If succeeded store the handle in the MGR Object */
  67                        if (drv_datap) {
  68                                drv_datap->mgr_object = (void *)pmgr_obj;
  69                        } else {
  70                                status = -EPERM;
  71                                pr_err("%s: Failed to store MGR object\n",
  72                                                                __func__);
  73                        }
  74
  75                        if (!status) {
  76                                *mgr_obj = pmgr_obj;
  77                        } else {
  78                                dcd_destroy_manager(pmgr_obj->dcd_mgr);
  79                                kfree(pmgr_obj);
  80                        }
  81                } else {
  82                        /* failed to Create DCD Manager */
  83                        kfree(pmgr_obj);
  84                }
  85        } else {
  86                status = -ENOMEM;
  87        }
  88
  89        return status;
  90}
  91
  92/*
  93 *  ========= mgr_destroy =========
  94 *     This function is invoked during bridge driver unloading.Frees MGR object.
  95 */
  96int mgr_destroy(struct mgr_object *hmgr_obj)
  97{
  98        int status = 0;
  99        struct mgr_object *pmgr_obj = (struct mgr_object *)hmgr_obj;
 100        struct drv_data *drv_datap = dev_get_drvdata(bridge);
 101
 102        /* Free resources */
 103        if (hmgr_obj->dcd_mgr)
 104                dcd_destroy_manager(hmgr_obj->dcd_mgr);
 105
 106        kfree(pmgr_obj);
 107        /* Update the driver data with NULL for MGR Object */
 108        if (drv_datap) {
 109                drv_datap->mgr_object = NULL;
 110        } else {
 111                status = -EPERM;
 112                pr_err("%s: Failed to store MGR object\n", __func__);
 113        }
 114
 115        return status;
 116}
 117
 118/*
 119 *  ======== mgr_enum_node_info ========
 120 *      Enumerate and get configuration information about nodes configured
 121 *      in the node database.
 122 */
 123int mgr_enum_node_info(u32 node_id, struct dsp_ndbprops *pndb_props,
 124                              u32 undb_props_size, u32 *pu_num_nodes)
 125{
 126        int status = 0;
 127        struct dsp_uuid node_uuid;
 128        u32 node_index = 0;
 129        struct dcd_genericobj gen_obj;
 130        struct mgr_object *pmgr_obj = NULL;
 131        struct drv_data *drv_datap = dev_get_drvdata(bridge);
 132
 133        *pu_num_nodes = 0;
 134        /* Get the Manager Object from the driver data */
 135        if (!drv_datap || !drv_datap->mgr_object) {
 136                pr_err("%s: Failed to retrieve the object handle\n", __func__);
 137                return -ENODATA;
 138        }
 139        pmgr_obj = drv_datap->mgr_object;
 140
 141        /* Forever loop till we hit failed or no more items in the
 142         * Enumeration. We will exit the loop other than 0; */
 143        while (!status) {
 144                status = dcd_enumerate_object(node_index++, DSP_DCDNODETYPE,
 145                                &node_uuid);
 146                if (status)
 147                        break;
 148                *pu_num_nodes = node_index;
 149                if (node_id == (node_index - 1)) {
 150                        status = dcd_get_object_def(pmgr_obj->dcd_mgr,
 151                                        &node_uuid, DSP_DCDNODETYPE, &gen_obj);
 152                        if (status)
 153                                break;
 154                        /* Get the Obj def */
 155                        *pndb_props = gen_obj.obj_data.node_obj.ndb_props;
 156                }
 157        }
 158
 159        /* the last status is not 0, but neither an error */
 160        if (status > 0)
 161                status = 0;
 162
 163        return status;
 164}
 165
 166/*
 167 *  ======== mgr_enum_processor_info ========
 168 *      Enumerate and get configuration information about available
 169 *      DSP processors.
 170 */
 171int mgr_enum_processor_info(u32 processor_id,
 172                                   struct dsp_processorinfo *
 173                                   processor_info, u32 processor_info_size,
 174                                   u8 *pu_num_procs)
 175{
 176        int status = 0;
 177        int status1 = 0;
 178        int status2 = 0;
 179        struct dsp_uuid temp_uuid;
 180        u32 temp_index = 0;
 181        u32 proc_index = 0;
 182        struct dcd_genericobj gen_obj;
 183        struct mgr_object *pmgr_obj = NULL;
 184        struct mgr_processorextinfo *ext_info;
 185        struct dev_object *hdev_obj;
 186        struct drv_object *hdrv_obj;
 187        u8 dev_type;
 188        struct cfg_devnode *dev_node;
 189        struct drv_data *drv_datap = dev_get_drvdata(bridge);
 190        bool proc_detect = false;
 191
 192        *pu_num_procs = 0;
 193
 194        /* Retrieve the Object handle from the driver data */
 195        if (!drv_datap || !drv_datap->drv_object) {
 196                status = -ENODATA;
 197                pr_err("%s: Failed to retrieve the object handle\n", __func__);
 198        } else {
 199                hdrv_obj = drv_datap->drv_object;
 200        }
 201
 202        if (!status) {
 203                status = drv_get_dev_object(processor_id, hdrv_obj, &hdev_obj);
 204                if (!status) {
 205                        status = dev_get_dev_type(hdev_obj, (u8 *) &dev_type);
 206                        status = dev_get_dev_node(hdev_obj, &dev_node);
 207                        if (dev_type != DSP_UNIT)
 208                                status = -EPERM;
 209
 210                        if (!status)
 211                                processor_info->processor_type = DSPTYPE64;
 212                }
 213        }
 214        if (status)
 215                goto func_end;
 216
 217        /* Get The Manager Object from the driver data */
 218        if (drv_datap && drv_datap->mgr_object) {
 219                pmgr_obj = drv_datap->mgr_object;
 220        } else {
 221                dev_dbg(bridge, "%s: Failed to get MGR Object\n", __func__);
 222                goto func_end;
 223        }
 224        /* Forever loop till we hit no more items in the
 225         * Enumeration. We will exit the loop other than 0; */
 226        while (status1 == 0) {
 227                status1 = dcd_enumerate_object(temp_index++,
 228                                               DSP_DCDPROCESSORTYPE,
 229                                               &temp_uuid);
 230                if (status1 != 0)
 231                        break;
 232
 233                proc_index++;
 234                /* Get the Object properties to find the Device/Processor
 235                 * Type */
 236                if (proc_detect != false)
 237                        continue;
 238
 239                status2 = dcd_get_object_def(pmgr_obj->dcd_mgr,
 240                                             (struct dsp_uuid *)&temp_uuid,
 241                                             DSP_DCDPROCESSORTYPE, &gen_obj);
 242                if (!status2) {
 243                        /* Get the Obj def */
 244                        if (processor_info_size <
 245                            sizeof(struct mgr_processorextinfo)) {
 246                                *processor_info = gen_obj.obj_data.proc_info;
 247                        } else {
 248                                /* extended info */
 249                                ext_info = (struct mgr_processorextinfo *)
 250                                    processor_info;
 251                                *ext_info = gen_obj.obj_data.ext_proc_obj;
 252                        }
 253                        dev_dbg(bridge, "%s: Got proctype  from DCD %x\n",
 254                                __func__, processor_info->processor_type);
 255                        /* See if we got the needed processor */
 256                        if (dev_type == DSP_UNIT) {
 257                                if (processor_info->processor_type ==
 258                                    DSPPROCTYPE_C64)
 259                                        proc_detect = true;
 260                        } else if (dev_type == IVA_UNIT) {
 261                                if (processor_info->processor_type ==
 262                                    IVAPROCTYPE_ARM7)
 263                                        proc_detect = true;
 264                        }
 265                        /* User applications only check for chip type, so
 266                         * this is a clumsy overwrite */
 267                        processor_info->processor_type = DSPTYPE64;
 268                } else {
 269                        dev_dbg(bridge, "%s: Failed to get DCD processor info "
 270                                "%x\n", __func__, status2);
 271                        status = -EPERM;
 272                }
 273        }
 274        *pu_num_procs = proc_index;
 275        if (proc_detect == false) {
 276                dev_dbg(bridge, "%s: Failed to get proc info from DCD, so use "
 277                        "CFG registry\n", __func__);
 278                processor_info->processor_type = DSPTYPE64;
 279        }
 280func_end:
 281        return status;
 282}
 283
 284/*
 285 *  ======== mgr_exit ========
 286 *      Decrement reference count, and free resources when reference count is
 287 *      0.
 288 */
 289void mgr_exit(void)
 290{
 291        refs--;
 292        if (refs == 0)
 293                dcd_exit();
 294}
 295
 296/*
 297 *  ======== mgr_get_dcd_handle ========
 298 *      Retrieves the MGR handle. Accessor Function.
 299 */
 300int mgr_get_dcd_handle(struct mgr_object *mgr_handle,
 301                              u32 *dcd_handle)
 302{
 303        int status = -EPERM;
 304        struct mgr_object *pmgr_obj = (struct mgr_object *)mgr_handle;
 305
 306        *dcd_handle = (u32) NULL;
 307        if (pmgr_obj) {
 308                *dcd_handle = (u32) pmgr_obj->dcd_mgr;
 309                status = 0;
 310        }
 311
 312        return status;
 313}
 314
 315/*
 316 *  ======== mgr_init ========
 317 *      Initialize MGR's private state, keeping a reference count on each call.
 318 */
 319bool mgr_init(void)
 320{
 321        bool ret = true;
 322
 323        if (refs == 0)
 324                ret = dcd_init();       /*  DCD Module */
 325
 326        if (ret)
 327                refs++;
 328
 329        return ret;
 330}
 331
 332/*
 333 *  ======== mgr_wait_for_bridge_events ========
 334 *      Block on any Bridge event(s)
 335 */
 336int mgr_wait_for_bridge_events(struct dsp_notification **anotifications,
 337                                      u32 count, u32 *pu_index,
 338                                      u32 utimeout)
 339{
 340        int status;
 341        struct sync_object *sync_events[MAX_EVENTS];
 342        u32 i;
 343
 344        for (i = 0; i < count; i++)
 345                sync_events[i] = anotifications[i]->handle;
 346
 347        status = sync_wait_on_multiple_events(sync_events, count, utimeout,
 348                                              pu_index);
 349
 350        return status;
 351
 352}
 353