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 applciatiuons aonly check for chip type, so 266 * this 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