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
46 struct mgr_object {
47 struct dcd_manager *dcd_mgr; /* Proc/Node data manager */
48 };
49
50 /* ----------------------------------- Globals */
51 static u32 refs;
52
53 /*
54 * ========= mgr_create =========
55 * Purpose:
56 * MGR Object gets created only once during driver Loading.
57 */
mgr_create(struct mgr_object ** mgr_obj,struct cfg_devnode * dev_node_obj)58 int 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->dcd_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->dcd_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 */
mgr_destroy(struct mgr_object * hmgr_obj)103 int 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->dcd_mgr)
114 dcd_destroy_manager(hmgr_obj->dcd_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 */
mgr_enum_node_info(u32 node_id,struct dsp_ndbprops * pndb_props,u32 undb_props_size,u32 * pu_num_nodes)133 int 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;
138 u32 node_index = 0;
139 struct dcd_genericobj gen_obj;
140 struct mgr_object *pmgr_obj = NULL;
141 struct drv_data *drv_datap = dev_get_drvdata(bridge);
142
143 DBC_REQUIRE(pndb_props != NULL);
144 DBC_REQUIRE(pu_num_nodes != NULL);
145 DBC_REQUIRE(undb_props_size >= sizeof(struct dsp_ndbprops));
146 DBC_REQUIRE(refs > 0);
147
148 *pu_num_nodes = 0;
149 /* Get the Manager Object from the driver data */
150 if (!drv_datap || !drv_datap->mgr_object) {
151 pr_err("%s: Failed to retrieve the object handle\n", __func__);
152 return -ENODATA;
153 }
154 pmgr_obj = drv_datap->mgr_object;
155
156 DBC_ASSERT(pmgr_obj);
157 /* Forever loop till we hit failed or no more items in the
158 * Enumeration. We will exit the loop other than 0; */
159 while (!status) {
160 status = dcd_enumerate_object(node_index++, DSP_DCDNODETYPE,
161 &node_uuid);
162 if (status)
163 break;
164 *pu_num_nodes = node_index;
165 if (node_id == (node_index - 1)) {
166 status = dcd_get_object_def(pmgr_obj->dcd_mgr,
167 &node_uuid, DSP_DCDNODETYPE, &gen_obj);
168 if (status)
169 break;
170 /* Get the Obj def */
171 *pndb_props = gen_obj.obj_data.node_obj.ndb_props;
172 }
173 }
174
175 /* the last status is not 0, but neither an error */
176 if (status > 0)
177 status = 0;
178
179 return status;
180 }
181
182 /*
183 * ======== mgr_enum_processor_info ========
184 * Enumerate and get configuration information about available
185 * DSP processors.
186 */
mgr_enum_processor_info(u32 processor_id,struct dsp_processorinfo * processor_info,u32 processor_info_size,u8 * pu_num_procs)187 int mgr_enum_processor_info(u32 processor_id,
188 struct dsp_processorinfo *
189 processor_info, u32 processor_info_size,
190 u8 *pu_num_procs)
191 {
192 int status = 0;
193 int status1 = 0;
194 int status2 = 0;
195 struct dsp_uuid temp_uuid;
196 u32 temp_index = 0;
197 u32 proc_index = 0;
198 struct dcd_genericobj gen_obj;
199 struct mgr_object *pmgr_obj = NULL;
200 struct mgr_processorextinfo *ext_info;
201 struct dev_object *hdev_obj;
202 struct drv_object *hdrv_obj;
203 u8 dev_type;
204 struct cfg_devnode *dev_node;
205 struct drv_data *drv_datap = dev_get_drvdata(bridge);
206 bool proc_detect = false;
207
208 DBC_REQUIRE(processor_info != NULL);
209 DBC_REQUIRE(pu_num_procs != NULL);
210 DBC_REQUIRE(processor_info_size >= sizeof(struct dsp_processorinfo));
211 DBC_REQUIRE(refs > 0);
212
213 *pu_num_procs = 0;
214
215 /* Retrieve the Object handle from the driver data */
216 if (!drv_datap || !drv_datap->drv_object) {
217 status = -ENODATA;
218 pr_err("%s: Failed to retrieve the object handle\n", __func__);
219 } else {
220 hdrv_obj = drv_datap->drv_object;
221 }
222
223 if (!status) {
224 status = drv_get_dev_object(processor_id, hdrv_obj, &hdev_obj);
225 if (!status) {
226 status = dev_get_dev_type(hdev_obj, (u8 *) &dev_type);
227 status = dev_get_dev_node(hdev_obj, &dev_node);
228 if (dev_type != DSP_UNIT)
229 status = -EPERM;
230
231 if (!status)
232 processor_info->processor_type = DSPTYPE64;
233 }
234 }
235 if (status)
236 goto func_end;
237
238 /* Get The Manager Object from the driver data */
239 if (drv_datap && drv_datap->mgr_object) {
240 pmgr_obj = drv_datap->mgr_object;
241 } else {
242 dev_dbg(bridge, "%s: Failed to get MGR Object\n", __func__);
243 goto func_end;
244 }
245 DBC_ASSERT(pmgr_obj);
246 /* Forever loop till we hit no more items in the
247 * Enumeration. We will exit the loop other than 0; */
248 while (status1 == 0) {
249 status1 = dcd_enumerate_object(temp_index++,
250 DSP_DCDPROCESSORTYPE,
251 &temp_uuid);
252 if (status1 != 0)
253 break;
254
255 proc_index++;
256 /* Get the Object properties to find the Device/Processor
257 * Type */
258 if (proc_detect != false)
259 continue;
260
261 status2 = dcd_get_object_def(pmgr_obj->dcd_mgr,
262 (struct dsp_uuid *)&temp_uuid,
263 DSP_DCDPROCESSORTYPE, &gen_obj);
264 if (!status2) {
265 /* Get the Obj def */
266 if (processor_info_size <
267 sizeof(struct mgr_processorextinfo)) {
268 *processor_info = gen_obj.obj_data.proc_info;
269 } else {
270 /* extended info */
271 ext_info = (struct mgr_processorextinfo *)
272 processor_info;
273 *ext_info = gen_obj.obj_data.ext_proc_obj;
274 }
275 dev_dbg(bridge, "%s: Got proctype from DCD %x\n",
276 __func__, processor_info->processor_type);
277 /* See if we got the needed processor */
278 if (dev_type == DSP_UNIT) {
279 if (processor_info->processor_type ==
280 DSPPROCTYPE_C64)
281 proc_detect = true;
282 } else if (dev_type == IVA_UNIT) {
283 if (processor_info->processor_type ==
284 IVAPROCTYPE_ARM7)
285 proc_detect = true;
286 }
287 /* User applciatiuons aonly check for chip type, so
288 * this clumsy overwrite */
289 processor_info->processor_type = DSPTYPE64;
290 } else {
291 dev_dbg(bridge, "%s: Failed to get DCD processor info "
292 "%x\n", __func__, status2);
293 status = -EPERM;
294 }
295 }
296 *pu_num_procs = proc_index;
297 if (proc_detect == false) {
298 dev_dbg(bridge, "%s: Failed to get proc info from DCD, so use "
299 "CFG registry\n", __func__);
300 processor_info->processor_type = DSPTYPE64;
301 }
302 func_end:
303 return status;
304 }
305
306 /*
307 * ======== mgr_exit ========
308 * Decrement reference count, and free resources when reference count is
309 * 0.
310 */
mgr_exit(void)311 void mgr_exit(void)
312 {
313 DBC_REQUIRE(refs > 0);
314 refs--;
315 if (refs == 0)
316 dcd_exit();
317
318 DBC_ENSURE(refs >= 0);
319 }
320
321 /*
322 * ======== mgr_get_dcd_handle ========
323 * Retrieves the MGR handle. Accessor Function.
324 */
mgr_get_dcd_handle(struct mgr_object * mgr_handle,u32 * dcd_handle)325 int mgr_get_dcd_handle(struct mgr_object *mgr_handle,
326 u32 *dcd_handle)
327 {
328 int status = -EPERM;
329 struct mgr_object *pmgr_obj = (struct mgr_object *)mgr_handle;
330
331 DBC_REQUIRE(refs > 0);
332 DBC_REQUIRE(dcd_handle != NULL);
333
334 *dcd_handle = (u32) NULL;
335 if (pmgr_obj) {
336 *dcd_handle = (u32) pmgr_obj->dcd_mgr;
337 status = 0;
338 }
339 DBC_ENSURE((!status && *dcd_handle != (u32) NULL) ||
340 (status && *dcd_handle == (u32) NULL));
341
342 return status;
343 }
344
345 /*
346 * ======== mgr_init ========
347 * Initialize MGR's private state, keeping a reference count on each call.
348 */
mgr_init(void)349 bool mgr_init(void)
350 {
351 bool ret = true;
352 bool init_dcd = false;
353
354 DBC_REQUIRE(refs >= 0);
355
356 if (refs == 0) {
357 init_dcd = dcd_init(); /* DCD Module */
358
359 if (!init_dcd)
360 ret = false;
361 }
362
363 if (ret)
364 refs++;
365
366 DBC_ENSURE((ret && (refs > 0)) || (!ret && (refs >= 0)));
367
368 return ret;
369 }
370
371 /*
372 * ======== mgr_wait_for_bridge_events ========
373 * Block on any Bridge event(s)
374 */
mgr_wait_for_bridge_events(struct dsp_notification ** anotifications,u32 count,u32 * pu_index,u32 utimeout)375 int mgr_wait_for_bridge_events(struct dsp_notification **anotifications,
376 u32 count, u32 *pu_index,
377 u32 utimeout)
378 {
379 int status;
380 struct sync_object *sync_events[MAX_EVENTS];
381 u32 i;
382
383 DBC_REQUIRE(count < MAX_EVENTS);
384
385 for (i = 0; i < count; i++)
386 sync_events[i] = anotifications[i]->handle;
387
388 status = sync_wait_on_multiple_events(sync_events, count, utimeout,
389 pu_index);
390
391 return status;
392
393 }
394